28 #ifndef EWOMS_BLACK_OIL_ENERGY_MODULE_HH 29 #define EWOMS_BLACK_OIL_ENERGY_MODULE_HH 31 #include <dune/common/fvector.hh> 33 #include <opm/common/ErrorMacros.hpp> 34 #include <opm/common/utility/gpuDecorators.hpp> 36 #include <opm/material/common/Tabulated1DFunction.hpp> 37 #include <opm/material/common/Valgrind.hpp> 38 #include <opm/material/fluidstates/BlackOilFluidState.hpp> 45 #include <opm/material/thermal/EnergyModuleType.hpp> 63 template <
class TypeTag>
78 static constexpr
unsigned temperatureIdx = Indices::temperatureIdx;
79 static constexpr
unsigned contiEnergyEqIdx = Indices::contiEnergyEqIdx;
81 static constexpr
unsigned enableFullyImplicitThermal =
true;
82 static constexpr
unsigned numEq = getPropValue<TypeTag, Properties::NumEq>();
83 static constexpr
unsigned numPhases = FluidSystem::numPhases;
100 Simulator& simulator)
105 static OPM_HOST_DEVICE
bool primaryVarApplies(
unsigned pvIdx)
107 return pvIdx == temperatureIdx;
110 static std::string primaryVarName([[maybe_unused]]
unsigned pvIdx)
112 assert(primaryVarApplies(pvIdx));
114 return "temperature";
117 static Scalar primaryVarWeight([[maybe_unused]]
unsigned pvIdx)
119 assert(primaryVarApplies(pvIdx));
122 return static_cast<Scalar
>(1.0);
125 static OPM_HOST_DEVICE
bool eqApplies(
unsigned eqIdx)
127 return eqIdx == contiEnergyEqIdx;
130 static std::string eqName([[maybe_unused]]
unsigned eqIdx)
132 assert(eqApplies(eqIdx));
134 return "conti^energy";
137 static Scalar eqWeight([[maybe_unused]]
unsigned eqIdx)
139 assert(eqApplies(eqIdx));
145 template <
class StorageType>
146 OPM_HOST_DEVICE
static void addStorage(StorageType& storage,
147 const IntensiveQuantities& intQuants)
149 using LhsEval =
typename StorageType::value_type;
150 const FluidSystem& fsys = intQuants.getFluidSystem();
152 const auto& poro = decay<LhsEval>(intQuants.porosity());
155 const auto& fs = intQuants.fluidState();
156 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
157 if (!fsys.phaseIsActive(phaseIdx)) {
161 const auto& u = decay<LhsEval>(fs.internalEnergy(phaseIdx));
162 const auto& S = decay<LhsEval>(fs.saturation(phaseIdx));
163 const auto& rho = decay<LhsEval>(fs.density(phaseIdx));
165 storage[contiEnergyEqIdx] += poro*S*u*rho;
169 const Scalar rockFraction = intQuants.rockFraction();
170 const auto& uRock = decay<LhsEval>(intQuants.rockInternalEnergy());
171 storage[contiEnergyEqIdx] += rockFraction * uRock;
172 storage[contiEnergyEqIdx] *= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
175 OPM_HOST_DEVICE
static void computeFlux(RateVector& flux,
176 const ElementContext& elemCtx,
180 flux[contiEnergyEqIdx] = 0.0;
182 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
183 const unsigned focusIdx = elemCtx.focusDofIndex();
184 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
185 if (!FluidSystem::phaseIsActive(phaseIdx)) {
189 const unsigned upIdx = extQuants.upstreamIndex(phaseIdx);
190 if (upIdx == focusIdx) {
191 addPhaseEnthalpyFlux_<Evaluation>(flux, phaseIdx, elemCtx, scvfIdx, timeIdx);
194 addPhaseEnthalpyFlux_<Scalar>(flux, phaseIdx, elemCtx, scvfIdx, timeIdx);
199 flux[contiEnergyEqIdx] += extQuants.energyFlux();
200 flux[contiEnergyEqIdx] *= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
203 template<
class RateVectorT>
204 OPM_HOST_DEVICE
static void addHeatFlux(RateVectorT& flux,
205 const Evaluation& heatFlux)
208 flux[contiEnergyEqIdx] += heatFlux;
209 flux[contiEnergyEqIdx] *= getPropValue<TypeTag, Properties::BlackOilEnergyScalingFactor>();
212 template <
class UpEval,
class RateVectorT,
class Eval,
class Flu
idState>
213 OPM_HOST_DEVICE
static void addPhaseEnthalpyFluxes_(RateVectorT& flux,
215 const Eval& volumeFlux,
216 const FluidState& upFs)
218 flux[contiEnergyEqIdx] +=
219 decay<UpEval>(upFs.enthalpy(phaseIdx)) *
220 decay<UpEval>(upFs.density(phaseIdx)) *
224 template <
class UpstreamEval>
225 OPM_HOST_DEVICE
static void addPhaseEnthalpyFlux_(RateVector& flux,
227 const ElementContext& elemCtx,
231 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
232 const unsigned upIdx = extQuants.upstreamIndex(phaseIdx);
233 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
234 const auto& fs = up.fluidState();
235 const auto& volFlux = extQuants.volumeFlux(phaseIdx);
236 addPhaseEnthalpyFluxes_<UpstreamEval>(flux,
242 OPM_HOST_DEVICE
static void addToEnthalpyRate(RateVector& flux,
243 const Evaluation& hRate)
245 flux[contiEnergyEqIdx] += hRate;
251 template <
class Flu
idState>
253 const FluidState& fluidState)
255 priVars[temperatureIdx] = getValue(fluidState.temperature(0));
262 const PrimaryVariables& oldPv,
263 const EqVector& delta)
266 newPv[temperatureIdx] = oldPv[temperatureIdx] - delta[temperatureIdx];
278 return static_cast<Scalar
>(0.0);
287 return std::abs(scalarValue(resid[contiEnergyEqIdx]));
290 template <
class DofEntity>
291 static void serializeEntity(
const Model& model, std::ostream& outstream,
const DofEntity& dof)
293 const unsigned dofIdx = model.dofMapper().index(dof);
294 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
295 outstream << priVars[temperatureIdx];
298 template <
class DofEntity>
299 static void deserializeEntity(Model& model, std::istream& instream,
const DofEntity& dof)
301 const unsigned dofIdx = model.dofMapper().index(dof);
302 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
303 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
305 instream >> priVars0[temperatureIdx];
308 priVars1 = priVars0[temperatureIdx];
319 template <
class TypeTag>
334 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
335 static constexpr
unsigned temperatureIdx = Indices::temperatureIdx;
342 Evaluation totalThermalConductivity,
344 : rockInternalEnergy_(rockInternalEnergy)
345 , totalThermalConductivity_(totalThermalConductivity)
346 , rockFraction_(rockFraction)
350 template <
class OtherTypeTag>
353 : rockInternalEnergy_(other.rockInternalEnergy())
354 , totalThermalConductivity_(other.totalThermalConductivity())
355 , rockFraction_(other.rockFraction())
358 BlackOilEnergyIntensiveQuantities() =
default;
368 auto& fs = asImp_().fluidState_;
369 const auto& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
372 fs.setTemperature(priVars.makeEvaluation(temperatureIdx, timeIdx, elemCtx.linearizationType()));
380 const PrimaryVariables& priVars,
381 [[maybe_unused]]
unsigned globalDofIdx,
382 const unsigned timeIdx,
385 auto& fs = asImp_().fluidState_;
386 fs.setTemperature(priVars.makeEvaluation(temperatureIdx, timeIdx, lintype));
397 updateEnergyQuantities_(elemCtx.problem(), elemCtx.globalSpaceIndex(dofIdx, timeIdx), timeIdx);
400 OPM_HOST_DEVICE
void updateEnergyQuantities_(
const Problem& problem,
401 const unsigned globalSpaceIdx,
402 const unsigned timeIdx)
404 auto& fs = asImp_().fluidState_;
408 for (
int phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
409 if (!asImp_().getFluidSystem().phaseIsActive(phaseIdx)) {
413 const auto& h = asImp_().getFluidSystem().enthalpy(fs, phaseIdx, problem.pvtRegionIndex(globalSpaceIdx));
414 fs.setEnthalpy(phaseIdx, h);
417 const auto& solidEnergyLawParams = problem.solidEnergyLawParams(globalSpaceIdx, timeIdx);
418 rockInternalEnergy_ = SolidEnergyLaw::solidInternalEnergy(solidEnergyLawParams, fs);
420 const auto& thermalConductionLawParams = problem.thermalConductionLawParams(globalSpaceIdx, timeIdx);
421 totalThermalConductivity_ = ThermalConductionLaw::thermalConductivity(thermalConductionLawParams, fs);
428 rockFraction_ = problem.rockFraction(globalSpaceIdx, timeIdx);
431 OPM_HOST_DEVICE
const Evaluation& rockInternalEnergy()
const 432 {
return rockInternalEnergy_; }
434 OPM_HOST_DEVICE
const Evaluation& totalThermalConductivity()
const 435 {
return totalThermalConductivity_; }
437 OPM_HOST_DEVICE Scalar rockFraction()
const 438 {
return rockFraction_; }
441 OPM_HOST_DEVICE Implementation& asImp_()
442 {
return *
static_cast<Implementation*
>(
this); }
444 Evaluation rockInternalEnergy_;
445 Evaluation totalThermalConductivity_;
446 Scalar rockFraction_;
449 template <
class TypeTag>
463 OPM_HOST_DEVICE
void updateTemperature_(
const ElementContext& elemCtx,
467 updateTemperature_(elemCtx.problem(), elemCtx.globalSpaceIndex(dofIdx, timeIdx), timeIdx);
470 template<
class Problem>
471 OPM_HOST_DEVICE
void updateTemperature_(
const Problem& problem,
472 [[maybe_unused]]
const PrimaryVariables& priVars,
473 unsigned globalDofIdx,
477 updateTemperature_(problem, globalDofIdx, timeIdx);
480 OPM_HOST_DEVICE
void updateTemperature_(
const Problem& problem,
481 unsigned globalDofIdx,
484 auto& fs = asImp_().fluidState_;
485 const Scalar T = problem.temperature(globalDofIdx, timeIdx);
486 fs.setTemperature(T);
489 OPM_HOST_DEVICE
void updateEnergyQuantities_(
const ElementContext&,
492 const typename FluidSystem::template ParameterCache<Evaluation>&)
495 OPM_HOST_DEVICE
const Evaluation& rockInternalEnergy()
const 497 OPM_THROW(std::logic_error,
498 "Requested the rock internal energy, which is " 499 "unavailable because energy is not conserved");
502 OPM_HOST_DEVICE
const Evaluation& totalThermalConductivity()
const 504 OPM_THROW(std::logic_error,
505 "Requested the total thermal conductivity, which is " 506 "unavailable because energy is not conserved");
510 OPM_HOST_DEVICE Implementation& asImp_()
511 {
return *
static_cast<Implementation*
>(
this); }
514 template <
class TypeTag>
530 OPM_HOST_DEVICE
void updateTemperature_(
const Problem& problem,
531 unsigned globalDofIdx,
535 auto& fs = asImp_().fluidState_;
536 fs.setTemperature(problem.temperature(globalDofIdx, timeIdx));
539 OPM_HOST_DEVICE
void updateTemperature_(
const ElementContext& elemCtx,
543 updateTemperature_(elemCtx.problem(), elemCtx.globalSpaceIndex(dofIdx, timeIdx), timeIdx);
546 template<
class Problem>
547 OPM_HOST_DEVICE
void updateTemperature_(
const Problem& problem,
548 [[maybe_unused]]
const PrimaryVariables& priVars,
549 unsigned globalDofIdx,
553 updateTemperature_(problem, globalDofIdx, timeIdx);
561 [[maybe_unused]]
unsigned dofIdx,
562 [[maybe_unused]]
unsigned timeIdx)
566 OPM_HOST_DEVICE
void updateEnergyQuantities_([[maybe_unused]]
const Problem& problem,
567 [[maybe_unused]]
const unsigned globalSpaceIdx,
568 [[maybe_unused]]
const unsigned timeIdx)
572 OPM_HOST_DEVICE
const Evaluation& rockInternalEnergy()
const 574 OPM_THROW(std::logic_error,
575 "Requested the rock internal energy, which is " 576 "unavailable because energy is not conserved");
579 OPM_HOST_DEVICE
const Evaluation& totalThermalConductivity()
const 581 OPM_THROW(std::logic_error,
582 "Requested the total thermal conductivity, which is " 583 "unavailable because energy is not conserved");
587 OPM_HOST_DEVICE Implementation& asImp_()
588 {
return *
static_cast<Implementation*
>(
this); }
599 template <
class TypeTag>
609 template<
class Evaluation,
class Flu
idState,
class IntensiveQuantities>
610 OPM_HOST_DEVICE
static void updateEnergy(Evaluation& energyFlux,
611 const unsigned& focusDofIndex,
612 const unsigned& inIdx,
613 const unsigned& exIdx,
614 const IntensiveQuantities& inIq,
615 const IntensiveQuantities& exIq,
616 const FluidState& inFs,
617 const FluidState& exFs,
618 const Scalar& inAlpha,
619 const Scalar& outAlpha,
620 const Scalar& faceArea)
623 if (focusDofIndex == inIdx) {
624 deltaT = decay<Scalar>(exFs.temperature(0)) -
627 else if (focusDofIndex == exIdx) {
628 deltaT = exFs.temperature(0) -
629 decay<Scalar>(inFs.temperature(0));
632 deltaT = decay<Scalar>(exFs.temperature(0)) -
633 decay<Scalar>(inFs.temperature(0));
637 if (focusDofIndex == inIdx) {
638 inLambda = inIq.totalThermalConductivity();
641 inLambda = decay<Scalar>(inIq.totalThermalConductivity());
645 if (focusDofIndex == exIdx) {
646 exLambda = exIq.totalThermalConductivity();
649 exLambda = decay<Scalar>(exIq.totalThermalConductivity());
653 const Evaluation& inH = inLambda*inAlpha;
654 const Evaluation& exH = exLambda*outAlpha;
655 if (inH > 0 && exH > 0) {
660 H = 1.0 / (1.0 / inH + 1.0 / exH);
666 energyFlux = deltaT * (-H / faceArea);
669 void updateEnergy(
const ElementContext& elemCtx,
673 const auto& stencil = elemCtx.stencil(timeIdx);
674 const auto& scvf = stencil.interiorFace(scvfIdx);
676 const Scalar faceArea = scvf.area();
677 const unsigned inIdx = scvf.interiorIndex();
678 const unsigned exIdx = scvf.exteriorIndex();
679 const auto& inIq = elemCtx.intensiveQuantities(inIdx, timeIdx);
680 const auto& exIq = elemCtx.intensiveQuantities(exIdx, timeIdx);
681 const auto& inFs = inIq.fluidState();
682 const auto& exFs = exIq.fluidState();
683 const Scalar inAlpha = elemCtx.problem().thermalHalfTransmissibilityIn(elemCtx, scvfIdx, timeIdx);
684 const Scalar outAlpha = elemCtx.problem().thermalHalfTransmissibilityOut(elemCtx, scvfIdx, timeIdx);
685 updateEnergy(energyFlux_,
686 elemCtx.focusDofIndex(),
698 template <
class Context,
class BoundaryFlu
idState>
699 void updateEnergyBoundary(
const Context& ctx,
702 const BoundaryFluidState& boundaryFs)
704 const auto& stencil = ctx.stencil(timeIdx);
705 const auto& scvf = stencil.boundaryFace(scvfIdx);
707 const unsigned inIdx = scvf.interiorIndex();
708 const auto& inIq = ctx.intensiveQuantities(inIdx, timeIdx);
709 const auto& focusDofIdx = ctx.focusDofIndex();
710 const Scalar alpha = ctx.problem().thermalHalfTransmissibilityBoundary(ctx, scvfIdx);
711 updateEnergyBoundary(energyFlux_, inIq, focusDofIdx, inIdx, alpha, boundaryFs);
714 template <
class Evaluation,
class BoundaryFlu
idState,
class IntensiveQuantities>
715 OPM_HOST_DEVICE
static void updateEnergyBoundary(Evaluation& energyFlux,
716 const IntensiveQuantities& inIq,
717 unsigned focusDofIndex,
720 const BoundaryFluidState& boundaryFs)
722 const auto& inFs = inIq.fluidState();
724 if (focusDofIndex == inIdx) {
725 deltaT = boundaryFs.temperature(0) -
729 deltaT = decay<Scalar>(boundaryFs.temperature(0)) -
730 decay<Scalar>(inFs.temperature(0));
734 if (focusDofIndex == inIdx) {
735 lambda = inIq.totalThermalConductivity();
738 lambda = decay<Scalar>(inIq.totalThermalConductivity());
746 energyFlux = deltaT * lambda * -alpha;
753 const Evaluation& energyFlux()
const 754 {
return energyFlux_; }
757 Implementation& asImp_()
758 {
return *
static_cast<Implementation*
>(
this); }
760 Evaluation energyFlux_;
763 template <
class TypeTag>
771 template<
class Evaluation,
class Flu
idState,
class IntensiveQuantities>
772 static void updateEnergy(Evaluation& energyFlux,
773 const unsigned& focusDofIndex,
774 const unsigned& inIdx,
775 const unsigned& exIdx,
776 const IntensiveQuantities& inIq,
777 const IntensiveQuantities& exIq,
778 const FluidState& inFs,
779 const FluidState& exFs,
780 const Scalar& inAlpha,
781 const Scalar& outAlpha,
782 const Scalar& faceArea)
798 void updateEnergy(
const ElementContext&,
803 template <
class Context,
class BoundaryFlu
idState>
804 void updateEnergyBoundary(
const Context&,
807 const BoundaryFluidState&)
810 template <
class Evaluation,
class BoundaryFlu
idState,
class IntensiveQuantities>
811 static void updateEnergyBoundary(Evaluation& ,
812 const IntensiveQuantities& ,
817 const BoundaryFluidState& )
820 OPM_HOST_DEVICE
const Evaluation& energyFlux()
const 821 { OPM_THROW(std::logic_error,
"Requested the energy flux, but energy is not conserved"); }
OPM_HOST_DEVICE void updateTemperature_([[maybe_unused]] const Problem &problem, const PrimaryVariables &priVars, [[maybe_unused]] unsigned globalDofIdx, const unsigned timeIdx, const LinearizationType &lintype)
Update the temperature of the intensive quantity's fluid state.
Definition: blackoilenergymodules.hh:379
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(...))
Definition: propertysystem.hh:233
VTK output module for the black oil model's energy related quantities.
Definition: vtkblackoilenergymodule.hpp:53
static void registerOutputModules(Model &model, Simulator &simulator)
Register all energy specific VTK and ECL output modules.
Definition: blackoilenergymodules.hh:99
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
static void registerParameters()
Register all run-time parameters for the multi-phase VTK output module.
Definition: vtkblackoilenergymodule.hpp:84
Contains classes extending the black-oil model.
Definition: blackoilmodules.hpp:62
Declares the properties required by the black oil model.
static OPM_HOST_DEVICE void assignPrimaryVars(PrimaryVariables &priVars, const FluidState &fluidState)
Assign the energy specific primary variables to a PrimaryVariables object.
Definition: blackoilenergymodules.hh:252
Provides the volumetric quantities required for the equations needed by the energys extension of the ...
Definition: blackoilmodules.hpp:67
OPM_HOST_DEVICE void updateEnergyQuantities_([[maybe_unused]] const ElementContext &elemCtx, [[maybe_unused]] unsigned dofIdx, [[maybe_unused]] unsigned timeIdx)
Compute the intensive quantities needed to handle energy conservation.
Definition: blackoilenergymodules.hh:560
VTK output module for the black oil model's energy related quantities.
Definition: linearizationtype.hh:33
This method contains all callback classes for quantities that are required by some extensive quantiti...
The common code for the linearizers of non-linear systems of equations.
Provides the energy specific extensive quantities to the generic black-oil module's extensive quantit...
Definition: blackoilmodules.hpp:72
OPM_HOST_DEVICE void updateTemperature_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Update the temperature of the intensive quantity's fluid state.
Definition: blackoilenergymodules.hh:364
BlackOilEnergyIntensiveQuantities(Evaluation rockInternalEnergy, Evaluation totalThermalConductivity, Scalar rockFraction)
Construct the energy intensive quantities for the fully implicit thermal module.
Definition: blackoilenergymodules.hh:341
OPM_HOST_DEVICE void updateEnergyQuantities_(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Compute the intensive quantities needed to handle energy conservation.
Definition: blackoilenergymodules.hh:393
static OPM_HOST_DEVICE void updatePrimaryVars(PrimaryVariables &newPv, const PrimaryVariables &oldPv, const EqVector &delta)
Do a Newton-Raphson update the primary variables of the energys.
Definition: blackoilenergymodules.hh:261
static void registerParameters()
Register all run-time parameters for the black-oil energy module.
Definition: blackoilenergymodules.hh:91
static OPM_HOST_DEVICE Scalar computeResidualError(const EqVector &resid)
Return how much a residual is considered an error.
Definition: blackoilenergymodules.hh:284
static OPM_HOST_DEVICE Scalar computeUpdateError(const PrimaryVariables &, const EqVector &)
Return how much a Newton-Raphson update is considered an error.
Definition: blackoilenergymodules.hh:272