23#ifndef OPM_FLOW_GENERIC_PROBLEM_IMPL_HPP
24#define OPM_FLOW_GENERIC_PROBLEM_IMPL_HPP
26#ifndef OPM_FLOW_GENERIC_PROBLEM_HPP
31#include <dune/common/parametertree.hh>
33#include <opm/common/ErrorMacros.hpp>
34#include <opm/common/utility/TimeService.hpp>
36#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
37#include <opm/input/eclipse/EclipseState/Tables/OverburdTable.hpp>
38#include <opm/input/eclipse/EclipseState/Tables/RockwnodTable.hpp>
39#include <opm/input/eclipse/Schedule/Schedule.hpp>
40#include <opm/input/eclipse/Units/Units.hpp>
51#include <boost/date_time.hpp>
53#include <fmt/format.h>
54#include <fmt/ranges.h>
61template<
class Gr
idView,
class Flu
idSystem>
64 const Schedule& schedule,
65 const GridView& gridView)
69 , lookUpData_(gridView)
87 if (Parameters::IsSet<Parameters::NumPressurePointsEquil>()) {
90 throw std::invalid_argument {
91 fmt::format(
"--num-pressure-points-equil must be at least 1, "
99 throw std::invalid_argument {
100 fmt::format(
"EQLDIMS item 2, the number of depth nodes in the "
101 "equilibration pressure tables, must be at least 1, "
110template<
class Gr
idView,
class Flu
idSystem>
114 const Schedule& schedule,
115 const GridView& gridView)
131template<
class Gr
idView,
class Flu
idSystem>
142 "Usage: "+std::string(argv[0]) +
" [OPTIONS] [DECK_FILENAME]\n"
146template<
class Gr
idView,
class Flu
idSystem>
151 return briefDescription_;
154template<
class Gr
idView,
class Flu
idSystem>
157 std::function<std::array<int,3>(
const unsigned)> ijkIndex)
159 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
163 const auto& comp = rock_config.comp();
165 std::ranges::transform(comp, std::back_inserter(rockParams_),
169 static_cast<Scalar>(c.pref),
176 if (rock_config.store()) {
177 OpmLog::warning(
"ROCKOPTS item 2 set to STORE, ROCK item 1 replaced with initial (equilibrated) pressures");
181 readRockCompactionParameters_();
183 unsigned numElem = gridView_.size(0);
184 if (eclState_.fieldProps().has_int(rock_config.rocknum_property())) {
186 std::function<void(
int,
int)> valueCheck = [&ijkIndex,&rock_config,
this](
int fieldPropValue,
int coarseElemIdx)
188 auto fmtError = [fieldPropValue, coarseElemIdx,&ijkIndex,&rock_config](
const char* type, std::size_t size)
190 return fmt::format(
"{} table index {} for elem {} read from {}"
191 " is out of bounds for number of tables {}",
192 type, fieldPropValue,
193 ijkIndex(coarseElemIdx),
194 rock_config.rocknum_property(), size);
196 if (!rockCompPoroMult_.empty() &&
197 fieldPropValue >
static_cast<int>(rockCompPoroMult_.size())) {
198 throw std::runtime_error(fmtError(
"Rock compaction",
199 rockCompPoroMult_.size()));
201 if (!rockCompPoroMultWc_.empty() &&
202 fieldPropValue >
static_cast<int>(rockCompPoroMultWc_.size())) {
203 throw std::runtime_error(fmtError(
"Rock water compaction",
204 rockCompPoroMultWc_.size()));
208 rockTableIdx_ = this->lookUpData_.template assignFieldPropsIntOnLeaf<short unsigned int>(eclState_.fieldProps(),
209 rock_config.rocknum_property(),
215 const auto& overburdTables = eclState_.getTableManager().getOverburdTables();
216 if (!overburdTables.empty() && !rock_config.store()) {
217 overburdenPressure_.resize(numElem,0.0);
218 std::size_t numRocktabTables = rock_config.num_rock_tables();
220 if (overburdTables.size() != numRocktabTables)
221 throw std::runtime_error(fmt::format(
"{} OVERBURD tables is expected, but {} is provided",
222 numRocktabTables, overburdTables.size()));
224 std::vector<Tabulated1DFunction<Scalar>> overburdenTables(numRocktabTables);
225 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
226 const OverburdTable& overburdTable = overburdTables.template getTable<OverburdTable>(regionIdx);
227 overburdenTables[regionIdx].setXYContainers(overburdTable.getDepthColumn(),overburdTable.getOverburdenPressureColumn());
230 for (std::size_t elemIdx = 0; elemIdx < numElem; ++ elemIdx) {
231 unsigned tableIdx = 0;
232 if (!rockTableIdx_.empty()) {
233 tableIdx = rockTableIdx_[elemIdx];
235 overburdenPressure_[elemIdx] =
236 overburdenTables[tableIdx].eval(cellCenterDepths[elemIdx],
true);
239 else if (!overburdTables.empty() && rock_config.store()) {
240 OpmLog::warning(
"ROCKOPTS item 2 set to STORE, OVERBURD ignored!");
244template<
class Gr
idView,
class Flu
idSystem>
248 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
250 if (!rock_config.active())
253 unsigned numElem = gridView_.size(0);
254 switch (rock_config.hysteresis_mode()) {
255 case RockConfig::Hysteresis::REVERS:
257 case RockConfig::Hysteresis::IRREVERS:
260 minRefPressure_.resize(numElem, 1e99);
262 case RockConfig::Hysteresis::HYSTER:
266 minRefPressure_.resize(numElem, 1e99);
269 throw std::runtime_error(
"Not support ROCKOMP hysteresis option ");
272 std::size_t numRocktabTables = rock_config.num_rock_tables();
273 bool waterCompaction = rock_config.water_compaction();
275 if (waterCompaction && rock_config.hysteresis_mode() == RockConfig::Hysteresis::HYSTER)
276 throw std::runtime_error(
"ROCKCOMP: combining WATER_COMPACTION with HYSTERESIS=HYSTER is not supported");
278 if (!waterCompaction && rock_config.hysteresis_mode() == RockConfig::Hysteresis::HYSTER) {
279 const auto& rocktabhTables = eclState_.getTableManager().getRocktabhTables();
280 if (rocktabhTables.size() != numRocktabTables)
281 throw std::runtime_error(
"ROCKCOMP HYSTERESIS is set to HYSTER. " +
std::to_string(numRocktabTables)
282 +
" ROCKTABH tables is expected, but " +
std::to_string(rocktabhTables.size()) +
" is provided");
287 rockCompPoroMult_.resize(numRocktabTables);
288 rockCompTransMult_.resize(numRocktabTables);
289 rockCompPoroMultElastic_.resize(numRocktabTables,
TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::LeftExtreme));
290 rockCompTransMultElastic_.resize(numRocktabTables,
TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::LeftExtreme));
291 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
292 const auto& rocktabhTable = rocktabhTables[regionIdx];
294 const auto& deflation = rocktabhTable.deflationCurve();
295 rockCompPoroMult_[regionIdx].setXYContainers(deflation.getColumn(0), deflation.getColumn(1));
296 rockCompTransMult_[regionIdx].setXYContainers(deflation.getColumn(0), deflation.getColumn(2));
298 const std::size_t numCurves = rocktabhTable.numElasticCurves();
299 for (std::size_t curveIdx = 0; curveIdx < numCurves; ++curveIdx) {
300 const auto& curve = rocktabhTable.elasticCurve(curveIdx);
301 const auto& pressure = curve.getColumn(0);
302 const auto& poro = curve.getColumn(1);
303 const auto& trans = curve.getColumn(2);
305 rockCompPoroMultElastic_[regionIdx].appendXPos(pressure[0]);
306 rockCompTransMultElastic_[regionIdx].appendXPos(pressure[0]);
307 for (std::size_t rowIdx = 0; rowIdx < curve.numRows(); ++rowIdx) {
308 rockCompPoroMultElastic_[regionIdx].appendSamplePoint(curveIdx, pressure[rowIdx], poro[rowIdx]);
309 rockCompTransMultElastic_[regionIdx].appendSamplePoint(curveIdx, pressure[rowIdx], trans[rowIdx]);
313 }
else if (!waterCompaction) {
314 const auto& rocktabTables = eclState_.getTableManager().getRocktabTables();
315 if (rocktabTables.size() != numRocktabTables)
316 throw std::runtime_error(
"ROCKCOMP is activated." +
std::to_string(numRocktabTables)
317 +
" ROCKTAB tables is expected, but " +
std::to_string(rocktabTables.size()) +
" is provided");
319 rockCompPoroMult_.resize(numRocktabTables);
320 rockCompTransMult_.resize(numRocktabTables);
321 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
322 const auto& rocktabTable = rocktabTables.template getTable<RocktabTable>(regionIdx);
323 const auto& pressureColumn = rocktabTable.getPressureColumn();
324 const auto& poroColumn = rocktabTable.getPoreVolumeMultiplierColumn();
325 const auto& transColumn = rocktabTable.getTransmissibilityMultiplierColumn();
326 rockCompPoroMult_[regionIdx].setXYContainers(pressureColumn, poroColumn);
327 rockCompTransMult_[regionIdx].setXYContainers(pressureColumn, transColumn);
330 const auto& rock2dTables = eclState_.getTableManager().getRock2dTables();
331 const auto& rock2dtrTables = eclState_.getTableManager().getRock2dtrTables();
332 const auto& rockwnodTables = eclState_.getTableManager().getRockwnodTables();
333 maxWaterSaturation_.resize(numElem, 0.0);
335 if (rock2dTables.size() != numRocktabTables)
336 throw std::runtime_error(fmt::format(
"Water compation option is selected in ROCKCOMP."
337 " {} ROCK2D tables is expected, but {} is provided",
338 numRocktabTables, rock2dTables.size()));
340 if (rockwnodTables.size() != numRocktabTables)
341 throw std::runtime_error(fmt::format(
"Water compation option is selected in ROCKCOMP."
342 " {} ROCKWNOD tables is expected, but {} is provided",
343 numRocktabTables, rockwnodTables.size()));
345 rockCompPoroMultWc_.resize(numRocktabTables,
TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
346 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
347 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
348 const auto& rock2dTable = rock2dTables[regionIdx];
350 if (rockwnodTable.getSaturationColumn().size() != rock2dTable.sizeMultValues())
351 throw std::runtime_error(
"Number of entries in ROCKWNOD and ROCK2D needs to match.");
353 for (std::size_t xIdx = 0; xIdx < rock2dTable.size(); ++xIdx) {
354 rockCompPoroMultWc_[regionIdx].appendXPos(rock2dTable.getPressureValue(xIdx));
355 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
356 rockCompPoroMultWc_[regionIdx].appendSamplePoint(xIdx,
357 rockwnodTable.getSaturationColumn()[yIdx],
358 rock2dTable.getPvmultValue(xIdx, yIdx));
362 if (!rock2dtrTables.empty()) {
363 rockCompTransMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
364 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
365 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
366 const auto& rock2dtrTable = rock2dtrTables[regionIdx];
368 if (rockwnodTable.getSaturationColumn().size() != rock2dtrTable.sizeMultValues())
369 throw std::runtime_error(
"Number of entries in ROCKWNOD and ROCK2DTR needs to match.");
371 for (std::size_t xIdx = 0; xIdx < rock2dtrTable.size(); ++xIdx) {
372 rockCompTransMultWc_[regionIdx].appendXPos(rock2dtrTable.getPressureValue(xIdx));
373 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
374 rockCompTransMultWc_[regionIdx].appendSamplePoint(xIdx,
375 rockwnodTable.getSaturationColumn()[yIdx],
376 rock2dtrTable.getTransMultValue(xIdx, yIdx));
383template<
class Gr
idView,
class Flu
idSystem>
388 if (this->rockParams_.empty())
391 unsigned tableIdx = 0;
392 if (!this->rockTableIdx_.empty()) {
393 tableIdx = this->rockTableIdx_[globalSpaceIdx];
395 return this->rockParams_[tableIdx].compressibility;
398template<
class Gr
idView,
class Flu
idSystem>
401porosity(
unsigned globalSpaceIdx,
unsigned timeIdx)
const
403 return this->referencePorosity_[timeIdx][globalSpaceIdx];
406template<
class Gr
idView,
class Flu
idSystem>
412 const auto biot = biotCoeff(elementIdx);
413 const auto lameParam = lame(elementIdx);
414 return biot * biot / lameParam;
417template <
class Gr
idView,
class Flu
idSystem>
423 const auto biotT = biotTemp(elementIdx);
424 const auto biotC = biotCoeff(elementIdx);
425 const auto lameParam = lame(elementIdx);
426 return biotC * biotT / lameParam;
429template<
class Gr
idView,
class Flu
idSystem>
432lame(
unsigned elementIdx)
const
435 const auto& fp = eclState_.fieldProps();
436 if (fp.has_double(
"LAME")) {
437 lameParam = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"LAME", elementIdx);
439 else if (fp.has_double(
"YMODULE") && fp.has_double(
"SMODULUS")) {
440 const auto& yModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"YMODULE", elementIdx);
441 const auto& sModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"SMODULUS", elementIdx);
442 lameParam = sModulus * (yModulus - 2 * sModulus) / (3 * sModulus - yModulus);
444 else if (fp.has_double(
"YMODULE") && fp.has_double(
"PRATIO")) {
445 const auto& yModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"YMODULE", elementIdx);
446 const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"PRATIO", elementIdx);
447 lameParam = yModulus * pRatio / ((1 + pRatio) * (1 - 2 * pRatio));
449 else if (fp.has_double(
"SMODULUS") && fp.has_double(
"PRATIO")) {
450 const auto& sModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"SMODULUS", elementIdx);
451 const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"PRATIO", elementIdx);
452 lameParam = 2 * sModulus * pRatio / (1 - 2 * pRatio);
460template<
class Gr
idView,
class Flu
idSystem>
466 const auto& fp = eclState_.fieldProps();
467 if (fp.has_double(
"BIOTCOEF")) {
468 biotC = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"BIOTCOEF", elementIdx);
470 else if (fp.has_double(
"POELCOEF") && fp.has_double(
"PRATIO")) {
471 const auto& poelC = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"POELCOEF", elementIdx);
472 const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(),
"PRATIO", elementIdx);
473 biotC = poelC * (1 - pRatio) / (1 - 2 * pRatio);
481template <
class Gr
idView,
class Flu
idSystem>
486 const auto& fp = eclState_.fieldProps();
489 if (!fp.has_double(
"THERMEXR") && !fp.has_double(
"THELCOEF")) {
496 if (fp.has_double(
"THERMEXR") && !fp.has_double(
"THELCOEF")) {
497 const auto thermexr = this->lookUpData_.fieldPropDouble(fp,
"THERMEXR", elementIdx);
499 if (fp.has_double(
"LAME") && fp.has_double(
"SMODULUS")) {
500 const auto lamParam = lame(elementIdx);
501 const auto sMod = this->lookUpData_.fieldPropDouble(fp,
"SMODULUS", elementIdx);
502 biotT = thermexr * (3.0 * lamParam + 2.0 * sMod);
503 }
else if (fp.has_double(
"YMODULE") && fp.has_double(
"PRATIO")) {
504 const auto yMod = this->lookUpData_.fieldPropDouble(fp,
"YMODULE", elementIdx);
505 const auto pRatio = this->lookUpData_.fieldPropDouble(fp,
"PRATIO", elementIdx);
506 biotT = thermexr * yMod / (1.0 - 2.0 * pRatio);
507 }
else if (fp.has_double(
"LAME") && fp.has_double(
"PRATIO")) {
508 const auto lamParam = lame(elementIdx);
509 const auto pRatio = this->lookUpData_.fieldPropDouble(fp,
"PRATIO", elementIdx);
511 thermexr * lamParam * (1.0 / pRatio - 2.0 * pRatio - 1.0) / (1.0 - 2.0 * pRatio);
512 }
else if (fp.has_double(
"SMODULUS") && fp.has_double(
"PRATIO")) {
513 const auto sMod = this->lookUpData_.fieldPropDouble(fp,
"SMODULUS", elementIdx);
514 const auto pRatio = this->lookUpData_.fieldPropDouble(fp,
"PRATIO", elementIdx);
515 biotT = thermexr * 2.0 * sMod * (1 + pRatio) / (1.0 - 2.0 * pRatio);
516 }
else if (fp.has_double(
"YMODULE") && fp.has_double(
"SMODULUS")) {
517 const auto yMod = this->lookUpData_.fieldPropDouble(fp,
"YMODULE", elementIdx);
518 const auto sMod = this->lookUpData_.fieldPropDouble(fp,
"SMODULUS", elementIdx);
519 biotT = thermexr * yMod * sMod / (3.0 * sMod - yMod);
521 OPM_THROW(std::runtime_error,
522 "THERMEXR requires one of (LAME, SMODULUS), (YMODULE, PRATIO), "
523 "(LAME, PRATIO), (SMODULUS, PRATIO) or (YMODULE, SMODULUS) "
524 "to compute the Biot temperature coefficient. "
525 "(YMODULE, LAME) is not supported.");
528 }
else if (!fp.has_double(
"THERMEXR") && fp.has_double(
"THELCOEF")) {
529 const auto thelcoef = this->lookUpData_.fieldPropDouble(fp,
"THELCOEF", elementIdx);
531 if (fp.has_double(
"LAME") && fp.has_double(
"SMODULUS")) {
532 const auto lamParam = lame(elementIdx);
533 const auto sMod = this->lookUpData_.fieldPropDouble(fp,
"SMODULUS", elementIdx);
534 biotT = thelcoef * (lamParam + 2 * sMod) / (2 * sMod);
535 }
else if (fp.has_double(
"PRATIO")) {
536 const auto pRatio = this->lookUpData_.fieldPropDouble(fp,
"PRATIO", elementIdx);
537 biotT = thelcoef * (1 - pRatio) / (1 - 2 * pRatio);
538 }
else if (fp.has_double(
"YMODULE") && fp.has_double(
"SMODULUS")) {
539 const auto yMod = this->lookUpData_.fieldPropDouble(fp,
"YMODULE", elementIdx);
540 const auto sMod = this->lookUpData_.fieldPropDouble(fp,
"SMODULUS", elementIdx);
541 biotT = thelcoef * (4.0 * sMod - yMod) / (6.0 * sMod - 2.0 * yMod);
543 OPM_THROW(std::runtime_error,
544 "THELCOEF requires one of (LAME, SMODULUS), (YMODULE, SMODULUS) "
545 "to compute the Biot temperature coefficient. "
546 "(YMODULE, LAME) is not supported.");
549 OPM_THROW(std::runtime_error,
550 "THERMEXR and THELCOEF cannot both be specified for the "
551 "Biot temperature coefficient");
557template<
class Gr
idView,
class Flu
idSystem>
560updateNum(
const std::string& name, std::vector<T>& numbers, std::size_t num_regions)
562 if (!eclState_.fieldProps().has_int(name))
565 std::function<void(T,
int)> valueCheck = [num_regions,name](T fieldPropValue, [[maybe_unused]]
int fieldPropIdx) {
566 if (fieldPropValue >
static_cast<int>(num_regions)) {
567 throw std::runtime_error(fmt::format(
"Values larger than maximum number of regions {} provided in {}",
570 if (fieldPropValue <= 0) {
571 throw std::runtime_error(
"zero or negative values provided for region array: " + name);
575 numbers = this->lookUpData_.template assignFieldPropsIntOnLeaf<T>(eclState_.fieldProps(), name,
579template<
class Gr
idView,
class Flu
idSystem>
583 const auto num_regions = eclState_.getTableManager().getTabdims().getNumPVTTables();
584 updateNum(
"PVTNUM", pvtnum_, num_regions);
587template<
class Gr
idView,
class Flu
idSystem>
591 const auto num_regions = eclState_.getTableManager().getTabdims().getNumSatTables();
592 updateNum(
"SATNUM", satnum_, num_regions);
595template<
class Gr
idView,
class Flu
idSystem>
599 const auto num_regions = 1;
600 updateNum(
"MISCNUM", miscnum_, num_regions);
603template<
class Gr
idView,
class Flu
idSystem>
607 const auto num_regions = 1;
608 updateNum(
"PLMIXNUM", plmixnum_, num_regions);
611template<
class Gr
idView,
class Flu
idSystem>
615 const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
616 return (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::VAPPARS);
619template<
class Gr
idView,
class Flu
idSystem>
624 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
627 std::ostringstream ss;
628 boost::posix_time::time_facet* facet =
new boost::posix_time::time_facet(
"%d-%b-%Y");
629 boost::posix_time::ptime curDateTime =
630 boost::posix_time::from_time_t(TimeService::to_time_t(schedule_.simTime(episodeIdx)));
631 ss.imbue(std::locale(std::locale::classic(), facet));
632 ss <<
"Report step " << episodeIdx + 1
633 <<
"/" << schedule_.size() - 1
634 <<
" at day " << schedule_.seconds(episodeIdx)/(24*3600)
635 <<
"/" << schedule_.seconds(schedule_.size() - 1)/(24*3600)
636 <<
", date = " << curDateTime.date()
638 OpmLog::info(ss.str());
641 const auto& events = schedule_[episodeIdx].events();
644 if (episodeIdx > 0 && enableTuning_ && events.hasEvent(ScheduleEvents::TUNING_CHANGE))
646 const auto& sched_state = schedule_[episodeIdx];
647 const auto& tuning = sched_state.tuning();
648 initialTimeStepSize_ = sched_state.max_next_tstep(enableTuning_);
649 maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
656template<
class Gr
idView,
class Flu
idSystem>
666 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
667 std::ostringstream ss;
668 boost::posix_time::time_facet* facet =
new boost::posix_time::time_facet(
"%d-%b-%Y");
669 boost::posix_time::ptime date = boost::posix_time::from_time_t(startTime) +
670 boost::posix_time::milliseconds(
static_cast<long long>(time / prefix::milli));
671 ss.imbue(std::locale(std::locale::classic(), facet));
672 ss <<
"\nTime step " << timeStepIndex <<
", stepsize "
673 << unit::convert::to(timeStepSize, unit::day) <<
" days,"
674 <<
" at day " << (double)unit::convert::to(time, unit::day)
675 <<
"/" << (double)unit::convert::to(endTime, unit::day)
676 <<
", date = " << date;
677 OpmLog::info(ss.str());
681template<
class Gr
idView,
class Flu
idSystem>
685 FluidSystem::initFromState(eclState_, schedule_);
688template<
class Gr
idView,
class Flu
idSystem>
693 bool enablePolymerMolarWeight,
694 bool enableBioeffects,
703 if ((enableSolvent || enablePolymer || enablePolymerMolarWeight ||
704 enableBioeffects || enableMICP) &&
705 (eclState_.getLgrs().size() > 0))
707 throw std::runtime_error(
708 "Local grid refinement (LGR/CARFIN) is only supported for black-oil "
709 "runs. It is not supported together with the solvent, polymer, "
710 "biofilm or MICP extensions.");
713 auto getArray = [](
const std::vector<double>& input)
715 if constexpr (std::is_same_v<Scalar,double>) {
718 return std::vector<Scalar>{input.begin(), input.end()};
723 if (eclState_.fieldProps().has_double(
"SSOL")) {
724 solventSaturation_ = getArray(eclState_.fieldProps().get_double(
"SSOL"));
726 solventSaturation_.resize(numDof, 0.0);
729 solventRsw_.resize(numDof, 0.0);
733 if (eclState_.fieldProps().has_double(
"SPOLY")) {
734 polymer_.concentration = getArray(eclState_.fieldProps().get_double(
"SPOLY"));
736 polymer_.concentration.resize(numDof, 0.0);
740 if (enablePolymerMolarWeight) {
741 if (eclState_.fieldProps().has_double(
"SPOLYMW")) {
742 polymer_.moleWeight = getArray(eclState_.fieldProps().get_double(
"SPOLYMW"));
744 polymer_.moleWeight.resize(numDof, 0.0);
748 if (enableBioeffects) {
749 if (eclState_.fieldProps().has_double(
"SMICR")) {
750 bioeffects_.microbialConcentration = getArray(eclState_.fieldProps().get_double(
"SMICR"));
752 bioeffects_.microbialConcentration.resize(numDof, 0.0);
754 if (eclState_.fieldProps().has_double(
"SBIOF")) {
755 bioeffects_.biofilmVolumeFraction = getArray(eclState_.fieldProps().get_double(
"SBIOF"));
757 bioeffects_.biofilmVolumeFraction.resize(numDof, 0.0);
760 if (eclState_.fieldProps().has_double(
"SOXYG")) {
761 bioeffects_.oxygenConcentration = getArray(eclState_.fieldProps().get_double(
"SOXYG"));
763 bioeffects_.oxygenConcentration.resize(numDof, 0.0);
765 if (eclState_.fieldProps().has_double(
"SUREA")) {
766 bioeffects_.ureaConcentration = getArray(eclState_.fieldProps().get_double(
"SUREA"));
768 bioeffects_.ureaConcentration.resize(numDof, 0.0);
770 if (eclState_.fieldProps().has_double(
"SCALC")) {
771 bioeffects_.calciteVolumeFraction = getArray(eclState_.fieldProps().get_double(
"SCALC"));
773 bioeffects_.calciteVolumeFraction.resize(numDof, 0.0);
779template<
class Gr
idView,
class Flu
idSystem>
784 if (maxWaterSaturation_.empty())
787 return maxWaterSaturation_[globalDofIdx];
790template<
class Gr
idView,
class Flu
idSystem>
795 if (minRefPressure_.empty())
798 return minRefPressure_[globalDofIdx];
801template<
class Gr
idView,
class Flu
idSystem>
806 if (overburdenPressure_.empty())
809 return overburdenPressure_[elementIdx];
812template<
class Gr
idView,
class Flu
idSystem>
817 if (solventSaturation_.empty())
820 return solventSaturation_[elemIdx];
823template<
class Gr
idView,
class Flu
idSystem>
828 if (solventRsw_.empty())
831 return solventRsw_[elemIdx];
836template<
class Gr
idView,
class Flu
idSystem>
841 if (polymer_.concentration.empty()) {
845 return polymer_.concentration[elemIdx];
848template<
class Gr
idView,
class Flu
idSystem>
853 if (polymer_.moleWeight.empty()) {
857 return polymer_.moleWeight[elemIdx];
860template<
class Gr
idView,
class Flu
idSystem>
865 if (bioeffects_.microbialConcentration.empty()) {
869 return bioeffects_.microbialConcentration[elemIdx];
872template<
class Gr
idView,
class Flu
idSystem>
877 if (bioeffects_.oxygenConcentration.empty()) {
881 return bioeffects_.oxygenConcentration[elemIdx];
884template<
class Gr
idView,
class Flu
idSystem>
889 if (bioeffects_.ureaConcentration.empty()) {
893 return bioeffects_.ureaConcentration[elemIdx];
896template<
class Gr
idView,
class Flu
idSystem>
901 if (bioeffects_.biofilmVolumeFraction.empty()) {
905 return bioeffects_.biofilmVolumeFraction[elemIdx];
908template<
class Gr
idView,
class Flu
idSystem>
913 if (bioeffects_.calciteVolumeFraction.empty()) {
917 return bioeffects_.calciteVolumeFraction[elemIdx];
920template<
class Gr
idView,
class Flu
idSystem>
927 return pvtnum_[elemIdx];
930template<
class Gr
idView,
class Flu
idSystem>
937 return satnum_[elemIdx];
940template<
class Gr
idView,
class Flu
idSystem>
944 if (miscnum_.empty())
947 return miscnum_[elemIdx];
950template<
class Gr
idView,
class Flu
idSystem>
954 if (plmixnum_.empty())
957 return plmixnum_[elemIdx];
960template<
class Gr
idView,
class Flu
idSystem>
965 if (polymer_.maxAdsorption.empty()) {
969 return polymer_.maxAdsorption[elemIdx];
972template<
class Gr
idView,
class Flu
idSystem>
Defines some fundamental parameters for all models.
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowGenericProblem.hpp:61
UniformXTabulated2DFunction< Scalar > TabulatedTwoDFunction
Definition: FlowGenericProblem.hpp:64
Scalar maxPolymerAdsorption(unsigned elemIdx) const
Returns the max polymer adsorption value.
Definition: FlowGenericProblem_impl.hpp:963
unsigned pvtRegionIndex(unsigned elemIdx) const
Returns the index the relevant PVT region given a cell index.
Definition: FlowGenericProblem_impl.hpp:922
Scalar oxygenConcentration(unsigned elemIdx) const
Returns the initial oxygen concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:875
Scalar microbialConcentration(unsigned elemIdx) const
Returns the initial microbial concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:863
PolymerSolutionContainer< Scalar > polymer_
Definition: FlowGenericProblem.hpp:383
Scalar rockBiotTemp(unsigned elementIdx) const
Returns the rock compressibility of an element due to thermoelasticity.
Definition: FlowGenericProblem_impl.hpp:420
static std::string briefDescription()
Returns a human readable description of the problem for the help message.
Definition: FlowGenericProblem_impl.hpp:149
Scalar solventRsw(unsigned elemIdx) const
Returns the initial solvent dissolved in water for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:826
Scalar overburdenPressure(unsigned elementIdx) const
Get the pressure of the overburden.
Definition: FlowGenericProblem_impl.hpp:804
void updateMiscnum_()
Definition: FlowGenericProblem_impl.hpp:597
Scalar porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
Direct indexed access to the porosity.
Definition: FlowGenericProblem_impl.hpp:401
Scalar rockCompressibility(unsigned globalSpaceIdx) const
Definition: FlowGenericProblem_impl.hpp:386
Scalar initialTimeStepSize_
Definition: FlowGenericProblem.hpp:395
unsigned miscnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant MISC region given a cell index.
Definition: FlowGenericProblem_impl.hpp:942
bool vapparsActive(int episodeIdx) const
Definition: FlowGenericProblem_impl.hpp:613
unsigned satnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant saturation function region given a cell index.
Definition: FlowGenericProblem_impl.hpp:932
Scalar maxWaterSaturation(unsigned globalDofIdx) const
Returns an element's historic maximum water phase saturation that was observed during the simulation.
Definition: FlowGenericProblem_impl.hpp:782
std::vector< Scalar > solventSaturation_
Definition: FlowGenericProblem.hpp:388
void readRockCompactionParameters_()
Definition: FlowGenericProblem_impl.hpp:246
void updateSatnum_()
Definition: FlowGenericProblem_impl.hpp:589
void updatePvtnum_()
Definition: FlowGenericProblem_impl.hpp:581
bool enableDriftCompensation_
Definition: FlowGenericProblem.hpp:401
Scalar lame(unsigned elementIdx) const
Direct access to Lame's second parameter in an element.
Definition: FlowGenericProblem_impl.hpp:432
static FlowGenericProblem serializationTestObject(const EclipseState &eclState, const Schedule &schedule, const GridView &gridView)
Definition: FlowGenericProblem_impl.hpp:113
void beginTimeStep_(bool enableExperiments, int episodeIdx, int timeStepIndex, Scalar startTime, Scalar time, Scalar timeStepSize, Scalar endTime)
Definition: FlowGenericProblem_impl.hpp:658
Scalar calciteVolumeFraction(unsigned elemIdx) const
Returns the initial calcite volume fraction for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:911
CO2H2SolutionContainer< Scalar > CO2H2_
Definition: FlowGenericProblem.hpp:391
unsigned plmixnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant PLMIXNUM (for polymer module) region given a cell index.
Definition: FlowGenericProblem_impl.hpp:952
FlowGenericProblem(const EclipseState &eclState, const Schedule &schedule, const GridView &gridView)
Definition: FlowGenericProblem_impl.hpp:63
BioeffectsSolutionContainer< Scalar > bioeffects_
Definition: FlowGenericProblem.hpp:390
bool enableTuning_
Definition: FlowGenericProblem.hpp:394
Scalar solventSaturation(unsigned elemIdx) const
Returns the initial solvent saturation for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:815
Scalar polymerMolecularWeight(const unsigned elemIdx) const
Returns the polymer molecule weight for a given cell index.
Definition: FlowGenericProblem_impl.hpp:851
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:156
std::vector< Scalar > maxOilSaturation_
Definition: FlowGenericProblem.hpp:384
Scalar rockBiotComp(unsigned elementIdx) const
Returns the rock compressibility of an element due to poroelasticity.
Definition: FlowGenericProblem_impl.hpp:409
int numPressurePointsEquil_
Definition: FlowGenericProblem.hpp:399
Scalar minOilPressure(unsigned globalDofIdx) const
Returns an element's historic minimum pressure of the oil phase that was observed during the simulati...
Definition: FlowGenericProblem_impl.hpp:793
std::vector< Scalar > maxWaterSaturation_
Definition: FlowGenericProblem.hpp:385
void initFluidSystem_()
Definition: FlowGenericProblem_impl.hpp:683
bool operator==(const FlowGenericProblem &rhs) const
Definition: FlowGenericProblem_impl.hpp:974
Scalar maxTimeStepAfterWellEvent_
Definition: FlowGenericProblem.hpp:396
Scalar ureaConcentration(unsigned elemIdx) const
Returns the initial urea concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:887
std::vector< Scalar > minRefPressure_
Definition: FlowGenericProblem.hpp:386
bool beginEpisode_(bool enableExperiments, int episodeIdx)
Definition: FlowGenericProblem_impl.hpp:621
Scalar biofilmVolumeFraction(unsigned elemIdx) const
Returns the initial biofilm volume fraction for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:899
std::vector< Scalar > solventRsw_
Definition: FlowGenericProblem.hpp:389
static std::string helpPreamble(int, const char **argv)
Returns the string that is printed before the list of command line parameters in the help message.
Definition: FlowGenericProblem_impl.hpp:134
std::vector< Scalar > overburdenPressure_
Definition: FlowGenericProblem.hpp:387
void readBlackoilExtentionsInitialConditions_(std::size_t numDof, bool enableSolvent, bool enablePolymer, bool enablePolymerMolarWeight, bool enableBioeffects, bool enableMICP)
Definition: FlowGenericProblem_impl.hpp:690
Scalar biotTemp(unsigned elementIdx) const
Direct access to Biot temperature coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:484
Scalar biotCoeff(unsigned elementIdx) const
Direct access to Biot coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:463
void updatePlmixnum_()
Definition: FlowGenericProblem_impl.hpp:605
bool explicitRockCompaction_
Definition: FlowGenericProblem.hpp:403
typename FluidSystem::Scalar Scalar
Definition: FlowGenericProblem.hpp:63
Scalar polymerConcentration(unsigned elemIdx) const
Returns the initial polymer concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:839
Declare the properties used by the infrastructure code of the finite volume discretizations.
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hpp:192
Definition: blackoilbioeffectsmodules.hh:45
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)
This file provides the infrastructure to retrieve run-time parameters.
static BioeffectsSolutionContainer serializationTestObject()
static CO2H2SolutionContainer serializationTestObject()
Definition: FlowGenericProblem.hpp:67
Definition: EclTimeSteppingParams.hpp:49
static PolymerSolutionContainer serializationTestObject()