opm-simulators
FlowGenericProblem_impl.hpp
1 // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 // vi: set et ts=4 sw=4 sts=4:
3 /*
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 2 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 
19  Consult the COPYING file in the top-level source directory of this
20  module for the precise wording of the license and the list of
21  copyright holders.
22 */
23 #ifndef OPM_FLOW_GENERIC_PROBLEM_IMPL_HPP
24 #define OPM_FLOW_GENERIC_PROBLEM_IMPL_HPP
25 
26 #ifndef OPM_FLOW_GENERIC_PROBLEM_HPP
27 #include <config.h>
29 #endif
30 
31 #include <dune/common/parametertree.hh>
32 
33 #include <opm/input/eclipse/EclipseState/EclipseState.hpp>
34 #include <opm/input/eclipse/EclipseState/Tables/OverburdTable.hpp>
35 #include <opm/input/eclipse/EclipseState/Tables/RockwnodTable.hpp>
36 #include <opm/input/eclipse/Schedule/Schedule.hpp>
37 #include <opm/input/eclipse/Units/Units.hpp>
38 
42 
45 
46 #include <opm/simulators/timestepping/EclTimeSteppingParams.hpp>
47 
48 #include <boost/date_time.hpp>
49 
50 #include <fmt/format.h>
51 #include <fmt/ranges.h>
52 
53 #include <iostream>
54 #include <stdexcept>
55 
56 namespace Opm {
57 
58 template<class GridView, class FluidSystem>
59 FlowGenericProblem<GridView,FluidSystem>::
60 FlowGenericProblem(const EclipseState& eclState,
61  const Schedule& schedule,
62  const GridView& gridView)
63  : eclState_(eclState)
64  , schedule_(schedule)
65  , gridView_(gridView)
66  , lookUpData_(gridView)
67 {
68  // we need to update the FluidSystem based on EclipseState before it is passed around
69  this->initFluidSystem_();
70 
71  enableTuning_ = Parameters::Get<Parameters::EnableTuning>();
72  enableDriftCompensation_ = Parameters::Get<Parameters::EnableDriftCompensation>();
73  initialTimeStepSize_ = Parameters::Get<Parameters::InitialTimeStepSize<Scalar>>();
74  maxTimeStepAfterWellEvent_ = unit::convert::from
75  (Parameters::Get<Parameters::TimeStepAfterEventInDays<Scalar>>(), unit::day);
76 
77  // The value N for this parameter is defined in the following order of precedence:
78  //
79  // 1. Command line value (--num-pressure-points-equil=N)
80  //
81  // 2. EQLDIMS item 2. Default value from
82  // opm-common/opm/input/eclipse/share/keywords/000_Eclipse100/E/EQLDIMS
83 
84  numPressurePointsEquil_ = Parameters::IsSet<Parameters::NumPressurePointsEquil>()
85  ? Parameters::Get<Parameters::NumPressurePointsEquil>()
86  : eclState.getTableManager().getEqldims().getNumDepthNodesP();
87 
88  explicitRockCompaction_ = Parameters::Get<Parameters::ExplicitRockCompaction>();
89 }
90 
91 template<class GridView, class FluidSystem>
92 FlowGenericProblem<GridView,FluidSystem>
93 FlowGenericProblem<GridView,FluidSystem>::
94 serializationTestObject(const EclipseState& eclState,
95  const Schedule& schedule,
96  const GridView& gridView)
97 {
98  FlowGenericProblem result(eclState, schedule, gridView);
99  result.maxOilSaturation_ = {1.0, 2.0};
100  result.maxWaterSaturation_ = {6.0};
101  result.minRefPressure_ = {7.0, 8.0, 9.0, 10.0};
102  result.overburdenPressure_ = {11.0};
103  result.solventSaturation_ = {15.0};
104  result.solventRsw_ = {18.0};
105  result.polymer_ = PolymerSolutionContainer<Scalar>::serializationTestObject();
106  result.bioeffects_ = BioeffectsSolutionContainer<Scalar>::serializationTestObject();
107  result.CO2H2_ = CO2H2SolutionContainer<Scalar>::serializationTestObject();
108 
109  return result;
110 }
111 
112 template<class GridView, class FluidSystem>
113 std::string
114 FlowGenericProblem<GridView,FluidSystem>::
115 helpPreamble(int,
116  const char **argv)
117 {
118  std::string desc = FlowGenericProblem::briefDescription();
119  if (!desc.empty())
120  desc = desc + "\n";
121 
122  return
123  "Usage: "+std::string(argv[0]) + " [OPTIONS] [ECL_DECK_FILENAME]\n"
124  + desc;
125 }
126 
127 template<class GridView, class FluidSystem>
128 std::string
131 {
132  return briefDescription_;
133 }
134 
135 template<class GridView, class FluidSystem>
137 readRockParameters_(const std::vector<Scalar>& cellCenterDepths,
138  std::function<std::array<int,3>(const unsigned)> ijkIndex)
139 {
140  const auto& rock_config = eclState_.getSimulationConfig().rock_config();
141 
142  // read the rock compressibility parameters
143  {
144  const auto& comp = rock_config.comp();
145  rockParams_.clear();
146  std::ranges::transform(comp, std::back_inserter(rockParams_),
147  [](const auto& c)
148  {
149  return RockParams{
150  static_cast<Scalar>(c.pref),
151  static_cast<Scalar>(c.compressibility)
152  };
153  });
154  }
155 
156  // Warn that ROCK and ROCKOPTS item 2 = STORE is used together
157  if (rock_config.store()) {
158  OpmLog::warning("ROCKOPTS item 2 set to STORE, ROCK item 1 replaced with initial (equilibrated) pressures");
159  }
160 
161  // read the parameters for water-induced rock compaction
162  readRockCompactionParameters_();
163 
164  unsigned numElem = gridView_.size(0);
165  if (eclState_.fieldProps().has_int(rock_config.rocknum_property())) {
166  // Auxiliary function to check rockTableIdx_ values belong to the right range. Otherwise, throws.
167  std::function<void(int, int)> valueCheck = [&ijkIndex,&rock_config,this](int fieldPropValue, int coarseElemIdx)
168  {
169  auto fmtError = [fieldPropValue, coarseElemIdx,&ijkIndex,&rock_config](const char* type, std::size_t size)
170  {
171  return fmt::format("{} table index {} for elem {} read from {}"
172  " is out of bounds for number of tables {}",
173  type, fieldPropValue,
174  ijkIndex(coarseElemIdx),
175  rock_config.rocknum_property(), size);
176  };
177  if (!rockCompPoroMult_.empty() &&
178  fieldPropValue > static_cast<int>(rockCompPoroMult_.size())) {
179  throw std::runtime_error(fmtError("Rock compaction",
180  rockCompPoroMult_.size()));
181  }
182  if (!rockCompPoroMultWc_.empty() &&
183  fieldPropValue > static_cast<int>(rockCompPoroMultWc_.size())) {
184  throw std::runtime_error(fmtError("Rock water compaction",
185  rockCompPoroMultWc_.size()));
186  }
187  };
188 
189  rockTableIdx_ = this->lookUpData_.template assignFieldPropsIntOnLeaf<short unsigned int>(eclState_.fieldProps(),
190  rock_config.rocknum_property(),
191  true /*needsTranslation*/,
192  valueCheck);
193  }
194 
195  // Store overburden pressure pr element
196  const auto& overburdTables = eclState_.getTableManager().getOverburdTables();
197  if (!overburdTables.empty() && !rock_config.store()) {
198  overburdenPressure_.resize(numElem,0.0);
199  std::size_t numRocktabTables = rock_config.num_rock_tables();
200 
201  if (overburdTables.size() != numRocktabTables)
202  throw std::runtime_error(fmt::format("{} OVERBURD tables is expected, but {} is provided",
203  numRocktabTables, overburdTables.size()));
204 
205  std::vector<Tabulated1DFunction<Scalar>> overburdenTables(numRocktabTables);
206  for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
207  const OverburdTable& overburdTable = overburdTables.template getTable<OverburdTable>(regionIdx);
208  overburdenTables[regionIdx].setXYContainers(overburdTable.getDepthColumn(),overburdTable.getOverburdenPressureColumn());
209  }
210 
211  for (std::size_t elemIdx = 0; elemIdx < numElem; ++ elemIdx) {
212  unsigned tableIdx = 0;
213  if (!rockTableIdx_.empty()) {
214  tableIdx = rockTableIdx_[elemIdx];
215  }
216  overburdenPressure_[elemIdx] =
217  overburdenTables[tableIdx].eval(cellCenterDepths[elemIdx], /*extrapolation=*/true);
218  }
219  }
220  else if (!overburdTables.empty() && rock_config.store()) {
221  OpmLog::warning("ROCKOPTS item 2 set to STORE, OVERBURD ignored!");
222  }
223 }
224 
225 template<class GridView, class FluidSystem>
226 void FlowGenericProblem<GridView,FluidSystem>::
227 readRockCompactionParameters_()
228 {
229  const auto& rock_config = eclState_.getSimulationConfig().rock_config();
230 
231  if (!rock_config.active())
232  return; // deck does not enable rock compaction
233 
234  unsigned numElem = gridView_.size(0);
235  switch (rock_config.hysteresis_mode()) {
236  case RockConfig::Hysteresis::REVERS:
237  break;
238  case RockConfig::Hysteresis::IRREVERS:
239  // interpolate the porv volume multiplier using the minimum pressure in the cell
240  // i.e. don't allow re-inflation.
241  minRefPressure_.resize(numElem, 1e99);
242  break;
243  default:
244  throw std::runtime_error("Not support ROCKOMP hysteresis option ");
245  }
246 
247  std::size_t numRocktabTables = rock_config.num_rock_tables();
248  bool waterCompaction = rock_config.water_compaction();
249 
250  if (!waterCompaction) {
251  const auto& rocktabTables = eclState_.getTableManager().getRocktabTables();
252  if (rocktabTables.size() != numRocktabTables)
253  throw std::runtime_error("ROCKCOMP is activated." + std::to_string(numRocktabTables)
254  +" ROCKTAB tables is expected, but " + std::to_string(rocktabTables.size()) +" is provided");
255 
256  rockCompPoroMult_.resize(numRocktabTables);
257  rockCompTransMult_.resize(numRocktabTables);
258  for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
259  const auto& rocktabTable = rocktabTables.template getTable<RocktabTable>(regionIdx);
260  const auto& pressureColumn = rocktabTable.getPressureColumn();
261  const auto& poroColumn = rocktabTable.getPoreVolumeMultiplierColumn();
262  const auto& transColumn = rocktabTable.getTransmissibilityMultiplierColumn();
263  rockCompPoroMult_[regionIdx].setXYContainers(pressureColumn, poroColumn);
264  rockCompTransMult_[regionIdx].setXYContainers(pressureColumn, transColumn);
265  }
266  } else {
267  const auto& rock2dTables = eclState_.getTableManager().getRock2dTables();
268  const auto& rock2dtrTables = eclState_.getTableManager().getRock2dtrTables();
269  const auto& rockwnodTables = eclState_.getTableManager().getRockwnodTables();
270  maxWaterSaturation_.resize(numElem, 0.0);
271 
272  if (rock2dTables.size() != numRocktabTables)
273  throw std::runtime_error(fmt::format("Water compation option is selected in ROCKCOMP."
274  " {} ROCK2D tables is expected, but {} is provided",
275  numRocktabTables, rock2dTables.size()));
276 
277  if (rockwnodTables.size() != numRocktabTables)
278  throw std::runtime_error(fmt::format("Water compation option is selected in ROCKCOMP."
279  " {} ROCKWNOD tables is expected, but {} is provided",
280  numRocktabTables, rockwnodTables.size()));
281  //TODO check size match
282  rockCompPoroMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
283  for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
284  const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
285  const auto& rock2dTable = rock2dTables[regionIdx];
286 
287  if (rockwnodTable.getSaturationColumn().size() != rock2dTable.sizeMultValues())
288  throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2D needs to match.");
289 
290  for (std::size_t xIdx = 0; xIdx < rock2dTable.size(); ++xIdx) {
291  rockCompPoroMultWc_[regionIdx].appendXPos(rock2dTable.getPressureValue(xIdx));
292  for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
293  rockCompPoroMultWc_[regionIdx].appendSamplePoint(xIdx,
294  rockwnodTable.getSaturationColumn()[yIdx],
295  rock2dTable.getPvmultValue(xIdx, yIdx));
296  }
297  }
298 
299  if (!rock2dtrTables.empty()) {
300  rockCompTransMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
301  for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
302  const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
303  const auto& rock2dtrTable = rock2dtrTables[regionIdx];
304 
305  if (rockwnodTable.getSaturationColumn().size() != rock2dtrTable.sizeMultValues())
306  throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2DTR needs to match.");
307 
308  for (std::size_t xIdx = 0; xIdx < rock2dtrTable.size(); ++xIdx) {
309  rockCompTransMultWc_[regionIdx].appendXPos(rock2dtrTable.getPressureValue(xIdx));
310  for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
311  rockCompTransMultWc_[regionIdx].appendSamplePoint(xIdx,
312  rockwnodTable.getSaturationColumn()[yIdx],
313  rock2dtrTable.getTransMultValue(xIdx, yIdx));
314  }
315  }
316  }
317  }
318 }
319 
320 template<class GridView, class FluidSystem>
321 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
322 FlowGenericProblem<GridView,FluidSystem>::
323 rockCompressibility(unsigned globalSpaceIdx) const
324 {
325  if (this->rockParams_.empty())
326  return 0.0;
327 
328  unsigned tableIdx = 0;
329  if (!this->rockTableIdx_.empty()) {
330  tableIdx = this->rockTableIdx_[globalSpaceIdx];
331  }
332  return this->rockParams_[tableIdx].compressibility;
333 }
334 
335 template<class GridView, class FluidSystem>
336 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
338 porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
339 {
340  return this->referencePorosity_[timeIdx][globalSpaceIdx];
341 }
342 
343 template<class GridView, class FluidSystem>
344 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
346 rockBiotComp(unsigned elementIdx) const
347 {
348  // Additional compressibility of the rock due to Biot poroelasticity
349  auto biot = biotCoeff(elementIdx);
350  auto lameParam = lame(elementIdx);
351  return biot * biot / lameParam;
352 }
353 
354 template<class GridView, class FluidSystem>
355 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
357 lame(unsigned elementIdx) const
358 {
359  Scalar lameParam;
360  const auto& fp = eclState_.fieldProps();
361  if (fp.has_double("LAME")) {
362  lameParam = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "LAME", elementIdx);
363  }
364  else if (fp.has_double("YMODULE") && fp.has_double("SMODULUS")) {
365  const auto& yModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "YMODULE", elementIdx);
366  const auto& sModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "SMODULUS", elementIdx);
367  lameParam = sModulus * (yModulus - 2 * sModulus) / (3 * sModulus - yModulus);
368  }
369  else if (fp.has_double("YMODULE") && fp.has_double("PRATIO")) {
370  const auto& yModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "YMODULE", elementIdx);
371  const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "PRATIO", elementIdx);
372  lameParam = yModulus * pRatio / ((1 + pRatio) * (1 - 2 * pRatio));
373  }
374  else if (fp.has_double("SMODULUS") && fp.has_double("PRATIO")) {
375  const auto& sModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "SMODULUS", elementIdx);
376  const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "PRATIO", elementIdx);
377  lameParam = 2 * sModulus * pRatio / (1 - 2 * pRatio);
378  }
379  else {
380  return 0.0;
381  }
382  return lameParam;
383 }
384 
385 template<class GridView, class FluidSystem>
386 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
388 biotCoeff(unsigned elementIdx) const
389 {
390  Scalar biotC;
391  const auto& fp = eclState_.fieldProps();
392  if (fp.has_double("BIOTCOEF")) {
393  biotC = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "BIOTCOEF", elementIdx);
394  }
395  else if (fp.has_double("POELCOEF") && fp.has_double("PRATIO")) {
396  const auto& poelC = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "POELCOEF", elementIdx);
397  const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "PRATIO", elementIdx);
398  biotC = poelC * (1 - pRatio) / (1 - 2 * pRatio);
399  }
400  else {
401  return 0.0;
402  }
403  return biotC;
404 }
405 
406 
407 template<class GridView, class FluidSystem>
408 template<class T>
410 updateNum(const std::string& name, std::vector<T>& numbers, std::size_t num_regions)
411 {
412  if (!eclState_.fieldProps().has_int(name))
413  return;
414 
415  std::function<void(T, int)> valueCheck = [num_regions,name](T fieldPropValue, [[maybe_unused]] int fieldPropIdx) {
416  if (fieldPropValue > static_cast<int>(num_regions)) {
417  throw std::runtime_error(fmt::format("Values larger than maximum number of regions {} provided in {}",
418  num_regions, name));
419  }
420  if (fieldPropValue <= 0) {
421  throw std::runtime_error("zero or negative values provided for region array: " + name);
422  }
423  };
424 
425  numbers = this->lookUpData_.template assignFieldPropsIntOnLeaf<T>(eclState_.fieldProps(), name,
426  true /*needsTranslation*/, valueCheck);
427 }
428 
429 template<class GridView, class FluidSystem>
430 void FlowGenericProblem<GridView,FluidSystem>::
431 updatePvtnum_()
432 {
433  const auto num_regions = eclState_.getTableManager().getTabdims().getNumPVTTables();
434  updateNum("PVTNUM", pvtnum_, num_regions);
435 }
436 
437 template<class GridView, class FluidSystem>
438 void FlowGenericProblem<GridView,FluidSystem>::
439 updateSatnum_()
440 {
441  const auto num_regions = eclState_.getTableManager().getTabdims().getNumSatTables();
442  updateNum("SATNUM", satnum_, num_regions);
443 }
444 
445 template<class GridView, class FluidSystem>
446 void FlowGenericProblem<GridView,FluidSystem>::
447 updateMiscnum_()
448 {
449  const auto num_regions = 1; // we only support single region
450  updateNum("MISCNUM", miscnum_, num_regions);
451 }
452 
453 template<class GridView, class FluidSystem>
454 void FlowGenericProblem<GridView,FluidSystem>::
455 updatePlmixnum_()
456 {
457  const auto num_regions = 1; // we only support single region
458  updateNum("PLMIXNUM", plmixnum_, num_regions);
459 }
460 
461 template<class GridView, class FluidSystem>
462 bool FlowGenericProblem<GridView,FluidSystem>::
463 vapparsActive(int episodeIdx) const
464 {
465  const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
466  return (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::VAPPARS);
467 }
468 
469 template<class GridView, class FluidSystem>
470 bool FlowGenericProblem<GridView,FluidSystem>::
471 beginEpisode_(bool enableExperiments,
472  int episodeIdx)
473 {
474  if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
475  // print some useful information in experimental mode. (the production
476  // simulator does this externally.)
477  std::ostringstream ss;
478  boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
479  boost::posix_time::ptime curDateTime =
480  boost::posix_time::from_time_t(schedule_.simTime(episodeIdx));
481  ss.imbue(std::locale(std::locale::classic(), facet));
482  ss << "Report step " << episodeIdx + 1
483  << "/" << schedule_.size() - 1
484  << " at day " << schedule_.seconds(episodeIdx)/(24*3600)
485  << "/" << schedule_.seconds(schedule_.size() - 1)/(24*3600)
486  << ", date = " << curDateTime.date()
487  << "\n ";
488  OpmLog::info(ss.str());
489  }
490 
491  const auto& events = schedule_[episodeIdx].events();
492 
493  // react to TUNING changes
494  if (episodeIdx > 0 && enableTuning_ && events.hasEvent(ScheduleEvents::TUNING_CHANGE))
495  {
496  const auto& sched_state = schedule_[episodeIdx];
497  const auto& tuning = sched_state.tuning();
498  initialTimeStepSize_ = sched_state.max_next_tstep(enableTuning_);
499  maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
500  return true;
501  }
502 
503  return false;
504 }
505 
506 template<class GridView, class FluidSystem>
507 void FlowGenericProblem<GridView,FluidSystem>::
508 beginTimeStep_(bool enableExperiments,
509  int episodeIdx,
510  int timeStepIndex,
511  Scalar startTime,
512  Scalar time,
513  Scalar timeStepSize,
514  Scalar endTime)
515 {
516  if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
517  std::ostringstream ss;
518  boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
519  boost::posix_time::ptime date = boost::posix_time::from_time_t(startTime) +
520  boost::posix_time::milliseconds(static_cast<long long>(time / prefix::milli));
521  ss.imbue(std::locale(std::locale::classic(), facet));
522  ss <<"\nTime step " << timeStepIndex << ", stepsize "
523  << unit::convert::to(timeStepSize, unit::day) << " days,"
524  << " at day " << (double)unit::convert::to(time, unit::day)
525  << "/" << (double)unit::convert::to(endTime, unit::day)
526  << ", date = " << date;
527  OpmLog::info(ss.str());
528  }
529 }
530 
531 template<class GridView, class FluidSystem>
532 void FlowGenericProblem<GridView,FluidSystem>::
533 initFluidSystem_()
534 {
535  FluidSystem::initFromState(eclState_, schedule_);
536 }
537 
538 template<class GridView, class FluidSystem>
539 void FlowGenericProblem<GridView,FluidSystem>::
540 readBlackoilExtentionsInitialConditions_(std::size_t numDof,
541  bool enableSolvent,
542  bool enablePolymer,
543  bool enablePolymerMolarWeight,
544  bool enableBioeffects,
545  bool enableMICP)
546 {
547  auto getArray = [](const std::vector<double>& input)
548  {
549  if constexpr (std::is_same_v<Scalar,double>) {
550  return input;
551  } else {
552  return std::vector<Scalar>{input.begin(), input.end()};
553  }
554  };
555 
556  if (enableSolvent) {
557  if (eclState_.fieldProps().has_double("SSOL")) {
558  solventSaturation_ = getArray(eclState_.fieldProps().get_double("SSOL"));
559  } else {
560  solventSaturation_.resize(numDof, 0.0);
561  }
562 
563  solventRsw_.resize(numDof, 0.0);
564  }
565 
566  if (enablePolymer) {
567  if (eclState_.fieldProps().has_double("SPOLY")) {
568  polymer_.concentration = getArray(eclState_.fieldProps().get_double("SPOLY"));
569  } else {
570  polymer_.concentration.resize(numDof, 0.0);
571  }
572  }
573 
574  if (enablePolymerMolarWeight) {
575  if (eclState_.fieldProps().has_double("SPOLYMW")) {
576  polymer_.moleWeight = getArray(eclState_.fieldProps().get_double("SPOLYMW"));
577  } else {
578  polymer_.moleWeight.resize(numDof, 0.0);
579  }
580  }
581 
582  if (enableBioeffects) {
583  if (eclState_.fieldProps().has_double("SMICR")) {
584  bioeffects_.microbialConcentration = getArray(eclState_.fieldProps().get_double("SMICR"));
585  } else {
586  bioeffects_.microbialConcentration.resize(numDof, 0.0);
587  }
588  if (eclState_.fieldProps().has_double("SBIOF")) {
589  bioeffects_.biofilmVolumeFraction = getArray(eclState_.fieldProps().get_double("SBIOF"));
590  } else {
591  bioeffects_.biofilmVolumeFraction.resize(numDof, 0.0);
592  }
593  if (enableMICP) {
594  if (eclState_.fieldProps().has_double("SOXYG")) {
595  bioeffects_.oxygenConcentration = getArray(eclState_.fieldProps().get_double("SOXYG"));
596  } else {
597  bioeffects_.oxygenConcentration.resize(numDof, 0.0);
598  }
599  if (eclState_.fieldProps().has_double("SUREA")) {
600  bioeffects_.ureaConcentration = getArray(eclState_.fieldProps().get_double("SUREA"));
601  } else {
602  bioeffects_.ureaConcentration.resize(numDof, 0.0);
603  }
604  if (eclState_.fieldProps().has_double("SCALC")) {
605  bioeffects_.calciteVolumeFraction = getArray(eclState_.fieldProps().get_double("SCALC"));
606  } else {
607  bioeffects_.calciteVolumeFraction.resize(numDof, 0.0);
608  }
609  }
610  }
611 }
612 
613 template<class GridView, class FluidSystem>
614 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
615 FlowGenericProblem<GridView,FluidSystem>::
616 maxWaterSaturation(unsigned globalDofIdx) const
617 {
618  if (maxWaterSaturation_.empty())
619  return 0.0;
620 
621  return maxWaterSaturation_[globalDofIdx];
622 }
623 
624 template<class GridView, class FluidSystem>
625 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
627 minOilPressure(unsigned globalDofIdx) const
628 {
629  if (minRefPressure_.empty())
630  return 0.0;
631 
632  return minRefPressure_[globalDofIdx];
633 }
634 
635 template<class GridView, class FluidSystem>
636 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
638 overburdenPressure(unsigned elementIdx) const
639 {
640  if (overburdenPressure_.empty())
641  return 0.0;
642 
643  return overburdenPressure_[elementIdx];
644 }
645 
646 template<class GridView, class FluidSystem>
647 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
649 solventSaturation(unsigned elemIdx) const
650 {
651  if (solventSaturation_.empty())
652  return 0;
653 
654  return solventSaturation_[elemIdx];
655 }
656 
657 template<class GridView, class FluidSystem>
658 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
660 solventRsw(unsigned elemIdx) const
661 {
662  if (solventRsw_.empty())
663  return 0;
664 
665  return solventRsw_[elemIdx];
666 }
667 
668 
669 
670 template<class GridView, class FluidSystem>
671 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
673 polymerConcentration(unsigned elemIdx) const
674 {
675  if (polymer_.concentration.empty()) {
676  return 0;
677  }
678 
679  return polymer_.concentration[elemIdx];
680 }
681 
682 template<class GridView, class FluidSystem>
683 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
685 polymerMolecularWeight(const unsigned elemIdx) const
686 {
687  if (polymer_.moleWeight.empty()) {
688  return 0.0;
689  }
690 
691  return polymer_.moleWeight[elemIdx];
692 }
693 
694 template<class GridView, class FluidSystem>
695 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
697 microbialConcentration(unsigned elemIdx) const
698 {
699  if (bioeffects_.microbialConcentration.empty()) {
700  return 0;
701  }
702 
703  return bioeffects_.microbialConcentration[elemIdx];
704 }
705 
706 template<class GridView, class FluidSystem>
707 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
709 oxygenConcentration(unsigned elemIdx) const
710 {
711  if (bioeffects_.oxygenConcentration.empty()) {
712  return 0;
713  }
714 
715  return bioeffects_.oxygenConcentration[elemIdx];
716 }
717 
718 template<class GridView, class FluidSystem>
719 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
721 ureaConcentration(unsigned elemIdx) const
722 {
723  if (bioeffects_.ureaConcentration.empty()) {
724  return 0;
725  }
726 
727  return bioeffects_.ureaConcentration[elemIdx];
728 }
729 
730 template<class GridView, class FluidSystem>
731 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
733 biofilmVolumeFraction(unsigned elemIdx) const
734 {
735  if (bioeffects_.biofilmVolumeFraction.empty()) {
736  return 0;
737  }
738 
739  return bioeffects_.biofilmVolumeFraction[elemIdx];
740 }
741 
742 template<class GridView, class FluidSystem>
743 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
745 calciteVolumeFraction(unsigned elemIdx) const
746 {
747  if (bioeffects_.calciteVolumeFraction.empty()) {
748  return 0;
749  }
750 
751  return bioeffects_.calciteVolumeFraction[elemIdx];
752 }
753 
754 template<class GridView, class FluidSystem>
756 pvtRegionIndex(unsigned elemIdx) const
757 {
758  if (pvtnum_.empty())
759  return 0;
760 
761  return pvtnum_[elemIdx];
762 }
763 
764 template<class GridView, class FluidSystem>
766 satnumRegionIndex(unsigned elemIdx) const
767 {
768  if (satnum_.empty())
769  return 0;
770 
771  return satnum_[elemIdx];
772 }
773 
774 template<class GridView, class FluidSystem>
776 miscnumRegionIndex(unsigned elemIdx) const
777 {
778  if (miscnum_.empty())
779  return 0;
780 
781  return miscnum_[elemIdx];
782 }
783 
784 template<class GridView, class FluidSystem>
786 plmixnumRegionIndex(unsigned elemIdx) const
787 {
788  if (plmixnum_.empty())
789  return 0;
790 
791  return plmixnum_[elemIdx];
792 }
793 
794 template<class GridView, class FluidSystem>
795 typename FlowGenericProblem<GridView,FluidSystem>::Scalar
797 maxPolymerAdsorption(unsigned elemIdx) const
798 {
799  if (polymer_.maxAdsorption.empty()) {
800  return 0;
801  }
802 
803  return polymer_.maxAdsorption[elemIdx];
804 }
805 
806 template<class GridView, class FluidSystem>
808 operator==(const FlowGenericProblem& rhs) const
809 {
810  return this->maxWaterSaturation_ == rhs.maxWaterSaturation_ &&
811  this->minRefPressure_ == rhs.minRefPressure_ &&
812  this->overburdenPressure_ == rhs.overburdenPressure_ &&
813  this->solventSaturation_ == rhs.solventSaturation_ &&
814  this->solventRsw_ == rhs.solventRsw_ &&
815  this->polymer_ == rhs.polymer_ &&
816  this->bioeffects_ == rhs.bioeffects_;
817 }
818 
819 } // namespace Opm
820 
821 #endif // OPM_FLOW_GENERIC_PROBLEM_IMPL_HPP
Scalar microbialConcentration(unsigned elemIdx) const
Returns the initial microbial concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:697
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
This file provides the infrastructure to retrieve run-time parameters.
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Scalar biofilmVolumeFraction(unsigned elemIdx) const
Returns the initial biofilm volume fraction for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:733
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
Defines some fundamental parameters for all models.
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Scalar oxygenConcentration(unsigned elemIdx) const
Returns the initial oxygen concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:709
Declare the properties used by the infrastructure code of the finite volume discretizations.
Scalar ureaConcentration(unsigned elemIdx) const
Returns the initial urea concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:721
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowGenericProblem.hpp:60
Scalar calciteVolumeFraction(unsigned elemIdx) const
Returns the initial calcite volume fraction for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:745