70 using Toolbox = MathToolbox<Evaluation>;
72 using TabulatedFunction =
typename BlackOilBrineParams<Scalar>::TabulatedFunction;
74 static constexpr unsigned saltConcentrationIdx = Indices::saltConcentrationIdx;
75 static constexpr unsigned contiBrineEqIdx = Indices::contiBrineEqIdx;
76 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
77 static constexpr bool gasEnabled = Indices::gasEnabled;
78 static constexpr bool oilEnabled = Indices::oilEnabled;
79 static constexpr bool enableBrine = enableBrineV;
80 static constexpr bool enableSaltPrecipitation =
84 static constexpr unsigned numPhases = FluidSystem::numPhases;
99 static bool primaryVarApplies(
unsigned pvIdx)
101 if constexpr (enableBrine) {
102 return pvIdx == saltConcentrationIdx;
112 template <
class Flu
idState>
114 const FluidState& fluidState)
116 if constexpr (enableBrine) {
117 priVars[saltConcentrationIdx] = fluidState.saltConcentration();
121 static std::string primaryVarName([[maybe_unused]]
unsigned pvIdx)
123 assert(primaryVarApplies(pvIdx));
125 return "saltConcentration";
128 static Scalar primaryVarWeight([[maybe_unused]]
unsigned pvIdx)
130 assert(primaryVarApplies(pvIdx));
133 return static_cast<Scalar
>(1.0);
136 static bool eqApplies(
unsigned eqIdx)
138 if constexpr (enableBrine) {
139 return eqIdx == contiBrineEqIdx;
146 static std::string eqName([[maybe_unused]]
unsigned eqIdx)
148 assert(eqApplies(eqIdx));
150 return "conti^brine";
153 static Scalar eqWeight([[maybe_unused]]
unsigned eqIdx)
155 assert(eqApplies(eqIdx));
158 return static_cast<Scalar
>(1.0);
162 template <
class LhsEval>
163 static void addStorage(Dune::FieldVector<LhsEval, numEq>& storage,
164 const IntensiveQuantities& intQuants)
166 if constexpr (enableBrine) {
167 const auto& fs = intQuants.fluidState();
170 const LhsEval surfaceVolumeWater =
171 max(Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx)) *
172 Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx)) *
173 Toolbox::template decay<LhsEval>(intQuants.porosity()),
177 const LhsEval massBrine = surfaceVolumeWater *
178 Toolbox::template decay<LhsEval>(fs.saltConcentration());
180 if constexpr (enableSaltPrecipitation) {
181 const double saltDensity = intQuants.saltDensity();
182 const LhsEval solidSalt =
183 Toolbox::template decay<LhsEval>(intQuants.porosity()) /
184 (1.0 - Toolbox::template decay<LhsEval>(fs.saltSaturation()) + 1.e-8) *
186 Toolbox::template decay<LhsEval>(fs.saltSaturation());
188 storage[contiBrineEqIdx] += massBrine + solidSalt;
191 storage[contiBrineEqIdx] += massBrine;
196 static void computeFlux([[maybe_unused]] RateVector& flux,
197 [[maybe_unused]]
const ElementContext& elemCtx,
198 [[maybe_unused]]
unsigned scvfIdx,
199 [[maybe_unused]]
unsigned timeIdx)
201 if constexpr (enableBrine) {
202 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
203 unsigned focusIdx = elemCtx.focusDofIndex();
204 unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
205 flux[contiBrineEqIdx] = 0.0;
206 if (upIdx == focusIdx)
207 addBrineFluxes_<Evaluation>(flux, elemCtx, scvfIdx, timeIdx);
209 addBrineFluxes_<Scalar>(flux, elemCtx, scvfIdx, timeIdx);
213 template <
class UpstreamEval>
214 static void addBrineFluxes_(RateVector& flux,
215 const ElementContext& elemCtx,
219 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
220 unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
221 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
222 const auto& upFs = up.fluidState();
223 const auto& volFlux = extQuants.volumeFlux(waterPhaseIdx);
224 addBrineFluxes_<UpstreamEval>(flux, waterPhaseIdx, volFlux, upFs);
227 template <
class UpEval,
class Flu
idState>
228 static void addBrineFluxes_(RateVector& flux,
230 const Evaluation& volFlux,
231 const FluidState& upFs)
233 if constexpr (enableBrine) {
234 if (phaseIdx == waterPhaseIdx) {
235 flux[contiBrineEqIdx] =
236 decay<UpEval>(upFs.saltConcentration())
237 * decay<UpEval>(upFs.invB(waterPhaseIdx))
252 return static_cast<Scalar
>(0.0);
255 template <
class DofEntity>
256 static void serializeEntity(
const Model& model, std::ostream& outstream,
const DofEntity& dof)
258 if constexpr (enableBrine) {
259 const unsigned dofIdx = model.dofMapper().index(dof);
260 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
261 outstream << priVars[saltConcentrationIdx];
265 template <
class DofEntity>
266 static void deserializeEntity(Model& model, std::istream& instream,
const DofEntity& dof)
268 if constexpr (enableBrine) {
269 const unsigned dofIdx = model.dofMapper().index(dof);
270 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
271 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
273 instream >> priVars0[saltConcentrationIdx];
276 priVars1[saltConcentrationIdx] = priVars0[saltConcentrationIdx];
280 static Scalar referencePressure(
const ElementContext& elemCtx,
284 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
285 return params_.referencePressure_[pvtnumRegionIdx];
288 static const TabulatedFunction& bdensityTable(
const ElementContext& elemCtx,
292 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
293 return params_.bdensityTable_[pvtnumRegionIdx];
296 static const TabulatedFunction& pcfactTable(
unsigned satnumRegionIdx)
297 {
return params_.pcfactTable_[satnumRegionIdx]; }
299 static const TabulatedFunction& permfactTable(
const ElementContext& elemCtx,
303 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
304 return params_.permfactTable_[satnumRegionIdx];
307 static const TabulatedFunction& permfactTable(
unsigned satnumRegionIdx)
308 {
return params_.permfactTable_[satnumRegionIdx]; }
310 static Scalar saltsolTable(
const ElementContext& elemCtx,
314 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
315 return params_.saltsolTable_[pvtnumRegionIdx];
318 static Scalar saltsolTable(
const unsigned pvtnumRegionIdx)
320 return params_.saltsolTable_[pvtnumRegionIdx];
323 static Scalar saltdenTable(
const ElementContext& elemCtx,
327 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
328 return params_.saltdenTable_[pvtnumRegionIdx];
331 static Scalar saltdenTable(
const unsigned pvtnumRegionIdx)
333 return params_.saltdenTable_[pvtnumRegionIdx];
336 static bool hasBDensityTables()
337 {
return !params_.bdensityTable_.empty(); }
339 static bool hasSaltsolTables()
340 {
return !params_.saltsolTable_.empty(); }
342 static bool hasPcfactTables()
344 if constexpr (enableSaltPrecipitation) {
345 return !params_.pcfactTable_.empty();
352 static Scalar saltSol(
unsigned regionIdx)
353 {
return params_.saltsolTable_[regionIdx]; }
356 static BlackOilBrineParams<Scalar> params_;
389 static constexpr int saltConcentrationIdx = Indices::saltConcentrationIdx;
390 static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
391 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
392 static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
393 static constexpr bool enableBrine =
true;
394 static constexpr bool enableSaltPrecipitation =
396 static constexpr int contiBrineEqIdx = Indices::contiBrineEqIdx;
408 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
413 void updateSaltConcentration_(
const PrimaryVariables& priVars,
414 const unsigned timeIdx,
417 const unsigned pvtnumRegionIdx = priVars.pvtRegionIndex();
418 auto& fs = asImp_().fluidState_;
420 if constexpr (enableSaltPrecipitation) {
421 saltSolubility_ = BrineModule::saltsolTable(pvtnumRegionIdx);
422 saltDensity_ = BrineModule::saltdenTable(pvtnumRegionIdx);
424 if (priVars.primaryVarsMeaningBrine() == PrimaryVariables::BrineMeaning::Sp) {
425 saltSaturation_ = priVars.makeEvaluation(saltConcentrationIdx, timeIdx, lintype);
426 fs.setSaltConcentration(saltSolubility_);
429 saltConcentration_ = priVars.makeEvaluation(saltConcentrationIdx, timeIdx, lintype);
430 fs.setSaltConcentration(saltConcentration_);
431 saltSaturation_ = 0.0;
433 fs.setSaltSaturation(saltSaturation_);
436 saltConcentration_ = priVars.makeEvaluation(saltConcentrationIdx, timeIdx, lintype);
437 fs.setSaltConcentration(saltConcentration_);
441 void saltPropertiesUpdate_([[maybe_unused]]
const ElementContext& elemCtx,
442 [[maybe_unused]]
unsigned dofIdx,
443 [[maybe_unused]]
unsigned timeIdx)
445 if constexpr (enableSaltPrecipitation) {
446 const Evaluation porosityFactor = min(1.0 - asImp_().fluidState_.saltSaturation(), 1.0);
448 const auto& permfactTable = BrineModule::permfactTable(elemCtx, dofIdx, timeIdx);
450 permFactor_ = permfactTable.eval(porosityFactor);
451 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
452 if (!FluidSystem::phaseIsActive(phaseIdx)) {
456 asImp_().mobility_[phaseIdx] *= permFactor_;
461 const Evaluation& brineRefDensity()
const
462 {
return refDensity_; }
464 Scalar saltSolubility()
const
465 {
return saltSolubility_; }
467 Scalar saltDensity()
const
468 {
return saltDensity_; }
470 const Evaluation& permFactor()
const
471 {
return permFactor_; }
474 Implementation& asImp_()
475 {
return *
static_cast<Implementation*
>(
this); }
477 Evaluation saltConcentration_;
478 Evaluation refDensity_;
479 Evaluation saltSaturation_;
480 Evaluation permFactor_;
481 Scalar saltSolubility_;