72 using Toolbox = MathToolbox<Evaluation>;
74 using TabulatedFunction =
typename BlackOilBrineParams<Scalar>::TabulatedFunction;
76 static constexpr unsigned saltConcentrationIdx = Indices::saltConcentrationIdx;
77 static constexpr unsigned contiBrineEqIdx = Indices::contiBrineEqIdx;
78 static constexpr unsigned waterPhaseIdx = FluidSystem::waterPhaseIdx;
79 static constexpr bool gasEnabled = Indices::gasEnabled;
80 static constexpr bool oilEnabled = Indices::oilEnabled;
81 static constexpr bool enableBrine = enableBrineV;
82 static constexpr bool enableSaltPrecipitation =
86 static constexpr unsigned numPhases = FluidSystem::numPhases;
101 static bool primaryVarApplies(
unsigned pvIdx)
103 if constexpr (enableBrine) {
104 return pvIdx == saltConcentrationIdx;
114 template <
class Flu
idState>
116 const FluidState& fluidState)
118 if constexpr (enableBrine) {
119 priVars[saltConcentrationIdx] = fluidState.saltConcentration();
123 static std::string primaryVarName([[maybe_unused]]
unsigned pvIdx)
125 assert(primaryVarApplies(pvIdx));
127 return "saltConcentration";
130 static Scalar primaryVarWeight([[maybe_unused]]
unsigned pvIdx)
132 assert(primaryVarApplies(pvIdx));
135 return static_cast<Scalar
>(1.0);
138 static bool eqApplies(
unsigned eqIdx)
140 if constexpr (enableBrine) {
141 return eqIdx == contiBrineEqIdx;
148 static std::string eqName([[maybe_unused]]
unsigned eqIdx)
150 assert(eqApplies(eqIdx));
152 return "conti^brine";
155 static Scalar eqWeight([[maybe_unused]]
unsigned eqIdx)
157 assert(eqApplies(eqIdx));
160 return static_cast<Scalar
>(1.0);
164 template <
class StorageType>
165 OPM_HOST_DEVICE
static void addStorage(StorageType& storage,
166 const IntensiveQuantities& intQuants)
168 using LhsEval =
typename StorageType::value_type;
170 if constexpr (enableBrine) {
171 const auto& fs = intQuants.fluidState();
174 const LhsEval surfaceVolumeWater =
175 max(Toolbox::template decay<LhsEval>(fs.saturation(waterPhaseIdx)) *
176 Toolbox::template decay<LhsEval>(fs.invB(waterPhaseIdx)) *
177 Toolbox::template decay<LhsEval>(intQuants.porosity()),
181 const LhsEval massBrine = surfaceVolumeWater *
182 Toolbox::template decay<LhsEval>(fs.saltConcentration());
184 if constexpr (enableSaltPrecipitation) {
185 const double saltDensity = intQuants.saltDensity();
186 const LhsEval solidSalt =
187 Toolbox::template decay<LhsEval>(intQuants.porosity()) /
188 (1.0 - Toolbox::template decay<LhsEval>(fs.saltSaturation()) + 1.e-8) *
190 Toolbox::template decay<LhsEval>(fs.saltSaturation());
192 storage[contiBrineEqIdx] += massBrine + solidSalt;
195 storage[contiBrineEqIdx] += massBrine;
200 static void computeFlux([[maybe_unused]] RateVector& flux,
201 [[maybe_unused]]
const ElementContext& elemCtx,
202 [[maybe_unused]]
unsigned scvfIdx,
203 [[maybe_unused]]
unsigned timeIdx)
205 if constexpr (enableBrine) {
206 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
207 unsigned focusIdx = elemCtx.focusDofIndex();
208 unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
209 flux[contiBrineEqIdx] = 0.0;
210 if (upIdx == focusIdx)
211 addBrineFluxes_<Evaluation>(flux, elemCtx, scvfIdx, timeIdx);
213 addBrineFluxes_<Scalar>(flux, elemCtx, scvfIdx, timeIdx);
217 template <
class UpstreamEval>
218 static void addBrineFluxes_(RateVector& flux,
219 const ElementContext& elemCtx,
223 const auto& extQuants = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
224 unsigned upIdx = extQuants.upstreamIndex(waterPhaseIdx);
225 const auto& up = elemCtx.intensiveQuantities(upIdx, timeIdx);
226 const auto& upFs = up.fluidState();
227 const auto& volFlux = extQuants.volumeFlux(waterPhaseIdx);
228 addBrineFluxes_<UpstreamEval>(flux, waterPhaseIdx, volFlux, upFs);
231 template <
class UpEval,
class Flu
idState>
232 static void addBrineFluxes_(RateVector& flux,
234 const Evaluation& volFlux,
235 const FluidState& upFs)
237 if constexpr (enableBrine) {
238 if (phaseIdx == waterPhaseIdx) {
239 flux[contiBrineEqIdx] =
240 decay<UpEval>(upFs.saltConcentration())
241 * decay<UpEval>(upFs.invB(waterPhaseIdx))
256 return static_cast<Scalar
>(0.0);
259 template <
class DofEntity>
260 static void serializeEntity(
const Model& model, std::ostream& outstream,
const DofEntity& dof)
262 if constexpr (enableBrine) {
263 const unsigned dofIdx = model.dofMapper().index(dof);
264 const PrimaryVariables& priVars = model.solution(0)[dofIdx];
265 outstream << priVars[saltConcentrationIdx];
269 template <
class DofEntity>
270 static void deserializeEntity(Model& model, std::istream& instream,
const DofEntity& dof)
272 if constexpr (enableBrine) {
273 const unsigned dofIdx = model.dofMapper().index(dof);
274 PrimaryVariables& priVars0 = model.solution(0)[dofIdx];
275 PrimaryVariables& priVars1 = model.solution(1)[dofIdx];
277 instream >> priVars0[saltConcentrationIdx];
280 priVars1[saltConcentrationIdx] = priVars0[saltConcentrationIdx];
284 static Scalar referencePressure(
const ElementContext& elemCtx,
288 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
289 return params_.referencePressure_[pvtnumRegionIdx];
292 static const TabulatedFunction& bdensityTable(
const ElementContext& elemCtx,
296 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
297 return params_.bdensityTable_[pvtnumRegionIdx];
300 static const TabulatedFunction& pcfactTable(
unsigned satnumRegionIdx)
301 {
return params_.pcfactTable_[satnumRegionIdx]; }
303 static const TabulatedFunction& permfactTable(
const ElementContext& elemCtx,
307 const unsigned satnumRegionIdx = elemCtx.problem().satnumRegionIndex(elemCtx, scvIdx, timeIdx);
308 return params_.permfactTable_[satnumRegionIdx];
311 static const TabulatedFunction& permfactTable(
unsigned satnumRegionIdx)
312 {
return params_.permfactTable_[satnumRegionIdx]; }
314 static Scalar saltsolTable(
const ElementContext& elemCtx,
318 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
319 return params_.saltsolTable_[pvtnumRegionIdx];
322 static Scalar saltsolTable(
const unsigned pvtnumRegionIdx)
324 return params_.saltsolTable_[pvtnumRegionIdx];
327 static Scalar saltdenTable(
const ElementContext& elemCtx,
331 const unsigned pvtnumRegionIdx = elemCtx.problem().pvtRegionIndex(elemCtx, scvIdx, timeIdx);
332 return params_.saltdenTable_[pvtnumRegionIdx];
335 static Scalar saltdenTable(
const unsigned pvtnumRegionIdx)
337 return params_.saltdenTable_[pvtnumRegionIdx];
340 static bool hasBDensityTables()
341 {
return !params_.bdensityTable_.empty(); }
343 static bool hasSaltsolTables()
344 {
return !params_.saltsolTable_.empty(); }
346 static bool hasPcfactTables()
348 if constexpr (enableSaltPrecipitation) {
349 return !params_.pcfactTable_.empty();
356 static Scalar saltSol(
unsigned regionIdx)
357 {
return params_.saltsolTable_[regionIdx]; }
360 static BlackOilBrineParams<Scalar> params_;
393 static constexpr int saltConcentrationIdx = Indices::saltConcentrationIdx;
394 static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
395 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
396 static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
397 static constexpr bool enableBrine =
true;
398 static constexpr bool enableSaltPrecipitation =
400 static constexpr int contiBrineEqIdx = Indices::contiBrineEqIdx;
412 const PrimaryVariables& priVars = elemCtx.primaryVars(dofIdx, timeIdx);
417 void updateSaltConcentration_(
const PrimaryVariables& priVars,
418 const unsigned timeIdx,
421 const unsigned pvtnumRegionIdx = priVars.pvtRegionIndex();
422 auto& fs = asImp_().fluidState_;
424 if constexpr (enableSaltPrecipitation) {
425 saltSolubility_ = BrineModule::saltsolTable(pvtnumRegionIdx);
426 saltDensity_ = BrineModule::saltdenTable(pvtnumRegionIdx);
428 if (priVars.primaryVarsMeaningBrine() == PrimaryVariables::BrineMeaning::Sp) {
429 saltSaturation_ = priVars.makeEvaluation(saltConcentrationIdx, timeIdx, lintype);
430 fs.setSaltConcentration(saltSolubility_);
433 saltConcentration_ = priVars.makeEvaluation(saltConcentrationIdx, timeIdx, lintype);
434 fs.setSaltConcentration(saltConcentration_);
435 saltSaturation_ = 0.0;
437 fs.setSaltSaturation(saltSaturation_);
440 saltConcentration_ = priVars.makeEvaluation(saltConcentrationIdx, timeIdx, lintype);
441 fs.setSaltConcentration(saltConcentration_);
445 void saltPropertiesUpdate_([[maybe_unused]]
const ElementContext& elemCtx,
446 [[maybe_unused]]
unsigned dofIdx,
447 [[maybe_unused]]
unsigned timeIdx)
449 if constexpr (enableSaltPrecipitation) {
450 const Evaluation porosityFactor = min(1.0 - asImp_().fluidState_.saltSaturation(), 1.0);
452 const auto& permfactTable = BrineModule::permfactTable(elemCtx, dofIdx, timeIdx);
454 permFactor_ = permfactTable.eval(porosityFactor);
458 const Evaluation& brineRefDensity()
const
459 {
return refDensity_; }
461 Scalar saltSolubility()
const
462 {
return saltSolubility_; }
464 Scalar saltDensity()
const
465 {
return saltDensity_; }
467 const Evaluation& permFactor()
const
468 {
return permFactor_; }
471 Implementation& asImp_()
472 {
return *
static_cast<Implementation*
>(
this); }
474 Evaluation saltConcentration_;
475 Evaluation refDensity_;
476 Evaluation saltSaturation_;
477 Evaluation permFactor_;
478 Scalar saltSolubility_;