28#ifndef OPM_FLASH_INTENSIVE_QUANTITIES_HH
29#define OPM_FLASH_INTENSIVE_QUANTITIES_HH
31#include <dune/common/fmatrix.hh>
32#include <dune/common/fvector.hh>
34#include <opm/common/OpmLog/OpmLog.hpp>
36#include <opm/material/Constants.hpp>
37#include <opm/material/common/Valgrind.hpp>
38#include <opm/material/fluidstates/CompositionalFluidState.hpp>
48#include <fmt/format.h>
62template <
class TypeTag>
63class FlashIntensiveQuantities
64 :
public GetPropType<TypeTag, Properties::DiscIntensiveQuantities>
65 ,
public DiffusionIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableDiffusion>() >
66 ,
public EnergyIntensiveQuantities<TypeTag, getPropValue<TypeTag, Properties::EnableEnergy>() >
67 ,
public GetPropType<TypeTag, Properties::FluxModule>::FluxIntensiveQuantities
69 using ParentType = GetPropType<TypeTag, Properties::DiscIntensiveQuantities>;
71 using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
72 using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
73 using MaterialLawParams = GetPropType<TypeTag, Properties::MaterialLawParams>;
74 using Indices = GetPropType<TypeTag, Properties::Indices>;
75 using FluxModule = GetPropType<TypeTag, Properties::FluxModule>;
76 using GridView = GetPropType<TypeTag, Properties::GridView>;
77 using ThreadManager = GetPropType<TypeTag, Properties::ThreadManager>;
80 enum { z0Idx = Indices::z0Idx };
81 enum { numPhases = getPropValue<TypeTag, Properties::NumPhases>() };
82 enum { numComponents = getPropValue<TypeTag, Properties::NumComponents>() };
83 static constexpr bool enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>();
84 static constexpr bool enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>();
85 enum { dimWorld = GridView::dimensionworld };
86 enum { pressure0Idx = Indices::pressure0Idx };
87 enum { water0Idx = Indices::water0Idx};
89 static constexpr bool waterEnabled = Indices::waterEnabled;
91 using Scalar = GetPropType<TypeTag, Properties::Scalar>;
92 using Evaluation = GetPropType<TypeTag, Properties::Evaluation>;
93 using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
94 using FlashSolver = GetPropType<TypeTag, Properties::FlashSolver>;
96 using ComponentVector = Dune::FieldVector<Evaluation, numComponents>;
97 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
101 using FluxIntensiveQuantities =
typename FluxModule::FluxIntensiveQuantities;
105 using FluidState = CompositionalFluidState<Evaluation, FluidSystem, enableEnergy>;
116 void update(
const ElementContext& elemCtx,
unsigned dofIdx,
unsigned timeIdx)
118 ParentType::update(elemCtx, dofIdx, timeIdx);
119 EnergyIntensiveQuantities::updateTemperatures_(fluidState_, elemCtx, dofIdx, timeIdx);
121 const auto& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
122 const auto& problem = elemCtx.problem();
124 const Scalar flashTolerance = Parameters::Get<Parameters::FlashTolerance<Scalar>>();
125 const int flashVerbosity = Parameters::Get<Parameters::FlashVerbosity>();
126 const std::string flashTwoPhaseMethod = Parameters::Get<Parameters::FlashTwoPhaseMethod>();
131 ComponentVector z(0.);
133 Evaluation lastZ = 1.0;
134 for (
unsigned compIdx = 0; compIdx < numComponents - 1; ++compIdx) {
135 z[compIdx] = priVars.makeEvaluation(z0Idx + compIdx, timeIdx);
138 z[numComponents - 1] = lastZ;
140 Evaluation sumz = 0.0;
141 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
146 if (z[compIdx] < 1e-8) {
147 z[compIdx].setValue(1e-8);
154 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
155 fluidState_.setMoleFraction(compIdx, z[compIdx]);
158 Evaluation p = priVars.makeEvaluation(pressure0Idx, timeIdx);
159 for (
int phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
160 fluidState_.setPressure(phaseIdx, p);
164 const auto* hint = elemCtx.thermodynamicHint(dofIdx, timeIdx);
166 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
167 const Evaluation& Ktmp = hint->fluidState().K(compIdx);
168 fluidState_.setKvalue(compIdx, Ktmp);
170 const Evaluation& Ltmp = hint->fluidState().L();
171 fluidState_.setLvalue(Ltmp);
173 else if (timeIdx == 0 && elemCtx.thermodynamicHint(dofIdx, 1)) {
175 const auto& hint2 = elemCtx.thermodynamicHint(dofIdx, 1);
176 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
177 const Evaluation& Ktmp = hint2->fluidState().K(compIdx);
178 fluidState_.setKvalue(compIdx, Ktmp);
180 const Evaluation& Ltmp = hint2->fluidState().L();
181 fluidState_.setLvalue(Ltmp);
184 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
185 const Evaluation Ktmp = fluidState_.wilsonK_(compIdx);
186 fluidState_.setKvalue(compIdx, Ktmp);
188 const Evaluation& Ltmp = -1.0;
189 fluidState_.setLvalue(Ltmp);
195 if (flashVerbosity >= 1) {
196 OpmLog::debug(fmt::format(
"Updating the intensive quantities for cell {}",
197 elemCtx.globalSpaceIndex(dofIdx, timeIdx)));
199 const auto& eos_type = problem.getEosType();
200 FlashSolver::solve(fluidState_, flashTwoPhaseMethod, flashTolerance, eos_type, flashVerbosity);
202 if (flashVerbosity >= 5) {
203 std::string phaseCompositions;
204 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
206 std::back_inserter(phaseCompositions),
207 " component {}: x = {}, y = {}\n",
209 getValue(fluidState_.moleFraction(FluidSystem::oilPhaseIdx, compIdx)),
210 getValue(fluidState_.moleFraction(FluidSystem::gasPhaseIdx, compIdx)));
212 OpmLog::debug(fmt::format(
"After the flash for cell {}: liquid fraction = {}\n{}",
213 elemCtx.globalSpaceIndex(dofIdx, timeIdx),
214 getValue(fluidState_.L()),
219 typename FluidSystem::template ParameterCache<Evaluation> paramCache(eos_type);
220 paramCache.updatePhase(fluidState_, FluidSystem::oilPhaseIdx);
221 paramCache.updatePhase(fluidState_, FluidSystem::gasPhaseIdx);
225 if constexpr (waterEnabled) {
226 Sw = priVars.makeEvaluation(water0Idx, timeIdx);
228 const Evaluation L = fluidState_.L();
229 const Evaluation Vm_L = paramCache.correctedMolarVolume(FluidSystem::oilPhaseIdx);
230 const Evaluation Vm_V = paramCache.correctedMolarVolume(FluidSystem::gasPhaseIdx);
231 Evaluation So = max((1 - Sw) * (L * Vm_L / ( L * Vm_L + (1 - L) * Vm_V)), 0.0);
232 Evaluation Sg = max(1 - So - Sw, 0.0);
233 const Scalar sumS = getValue(So) + getValue(Sg) + getValue(Sw);
237 fluidState_.setSaturation(FluidSystem::oilPhaseIdx, So);
238 fluidState_.setSaturation(FluidSystem::gasPhaseIdx, Sg);
239 if constexpr (waterEnabled) {
241 fluidState_.setSaturation(FluidSystem::waterPhaseIdx, Sw);
246 const Scalar R = Opm::Constants<Scalar>::R;
247 const Evaluation Z_L = (paramCache.molarVolume(FluidSystem::oilPhaseIdx) *
248 fluidState_.pressure(FluidSystem::oilPhaseIdx)) /
249 (R * fluidState_.temperature(FluidSystem::oilPhaseIdx));
250 const Evaluation Z_V = (paramCache.molarVolume(FluidSystem::gasPhaseIdx) *
251 fluidState_.pressure(FluidSystem::gasPhaseIdx)) /
252 (R * fluidState_.temperature(FluidSystem::gasPhaseIdx));
253 fluidState_.setCompressFactor(FluidSystem::oilPhaseIdx, Z_L);
254 fluidState_.setCompressFactor(FluidSystem::gasPhaseIdx, Z_V);
256 if (flashVerbosity >= 5) {
257 OpmLog::debug(fmt::format(
"Flash phase properties for cell {}: "
258 "oil saturation = {}, gas saturation = {}, "
259 "oil molar volume = {}, gas molar volume = {}",
260 elemCtx.globalSpaceIndex(dofIdx, timeIdx),
270 const MaterialLawParams& materialParams = problem.materialLawParams(elemCtx, dofIdx, timeIdx);
273 MaterialLaw::relativePermeabilities(relativePermeability_,
274 materialParams, fluidState_);
275 Valgrind::CheckDefined(relativePermeability_);
278 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
279 if (phaseIdx ==
static_cast<unsigned int>(FluidSystem::oilPhaseIdx) ||
280 phaseIdx ==
static_cast<unsigned int>(FluidSystem::gasPhaseIdx))
282 paramCache.updatePhase(fluidState_, phaseIdx);
285 const Evaluation& mu = FluidSystem::viscosity(fluidState_, paramCache, phaseIdx);
287 fluidState_.setViscosity(phaseIdx, mu);
289 mobility_[phaseIdx] = relativePermeability_[phaseIdx] / mu;
290 Valgrind::CheckDefined(mobility_[phaseIdx]);
292 const Evaluation& rho = FluidSystem::density(fluidState_, paramCache, phaseIdx);
293 fluidState_.setDensity(phaseIdx, rho);
301 porosity_ = problem.porosity(elemCtx, dofIdx, timeIdx);
302 Valgrind::CheckDefined(porosity_);
305 intrinsicPerm_ = problem.intrinsicPermeability(elemCtx, dofIdx, timeIdx);
308 FluxIntensiveQuantities::update_(elemCtx, dofIdx, timeIdx);
311 EnergyIntensiveQuantities::update_(fluidState_, paramCache, elemCtx, dofIdx, timeIdx);
314 DiffusionIntensiveQuantities::update_(fluidState_, paramCache, elemCtx, dofIdx, timeIdx);
321 {
return fluidState_; }
327 {
return intrinsicPerm_; }
333 {
return relativePermeability_[phaseIdx]; }
338 const Evaluation&
mobility(
unsigned phaseIdx)
const
339 {
return mobility_[phaseIdx]; }
345 {
return porosity_; }
348 DimMatrix intrinsicPerm_;
350 Evaluation porosity_;
351 std::array<Evaluation,numPhases> relativePermeability_;
352 std::array<Evaluation,numPhases> mobility_;
Provides the volumetric quantities required for the calculation of molecular diffusive fluxes.
Definition: diffusionmodule.hh:143
Provides the volumetric quantities required for the energy equation.
Definition: energymodule.hh:536
Contains the intensive quantities of the flash-based compositional multi-phase model.
Definition: flash/flashintensivequantities.hh:60
const Evaluation & mobility(unsigned phaseIdx) const
Returns the effective mobility of a given phase within the control volume.
Definition: ptflash/flashintensivequantities.hh:338
const DimMatrix & intrinsicPermeability() const
Returns the intrinsic permeability tensor a degree of freedom.
Definition: ptflash/flashintensivequantities.hh:326
FlashIntensiveQuantities(const FlashIntensiveQuantities &other)=default
const FluidState & fluidState() const
Returns the phase state for the control-volume.
Definition: ptflash/flashintensivequantities.hh:320
const Evaluation & porosity() const
Returns the average porosity within the control volume.
Definition: ptflash/flashintensivequantities.hh:344
const Evaluation & relativePermeability(unsigned phaseIdx) const
Returns the relative permeability of a given phase within the control volume.
Definition: ptflash/flashintensivequantities.hh:332
CompositionalFluidState< Evaluation, FluidSystem, enableEnergy > FluidState
The type of the object returned by the fluidState() method.
Definition: flash/flashintensivequantities.hh:93
FlashIntensiveQuantities()=default
void update(const ElementContext &elemCtx, unsigned dofIdx, unsigned timeIdx)
Definition: ptflash/flashintensivequantities.hh:116
FlashIntensiveQuantities & operator=(const FlashIntensiveQuantities &other)=default
Classes required for molecular diffusion.
Contains the classes required to consider energy as a conservation quantity in a multi-phase module.
Declares the properties required by the compositional multi-phase model based on flash calculations.
Definition: blackoilbioeffectsmodules.hh:45
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
Declares the parameters for the compositional multi-phase model based on flash calculations.