FlowGenericProblem_impl.hpp
Go to the documentation of this file.
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
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
56namespace Opm {
57
58template<class GridView, class FluidSystem>
60FlowGenericProblem(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
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 if (Parameters::IsSet<Parameters::NumPressurePointsEquil>()) {
85 numPressurePointsEquil_ = Parameters::Get<Parameters::NumPressurePointsEquil>();
87 throw std::invalid_argument {
88 fmt::format("--num-pressure-points-equil must be at least 1, "
89 "but {} was given.", numPressurePointsEquil_)
90 };
91 }
92 }
93 else {
94 numPressurePointsEquil_ = eclState.getTableManager().getEqldims().getNumDepthNodesP();
96 throw std::invalid_argument {
97 fmt::format("EQLDIMS item 2, the number of depth nodes in the "
98 "equilibration pressure tables, must be at least 1, "
99 "but {} was given.", numPressurePointsEquil_)
100 };
101 }
102 }
103
104 explicitRockCompaction_ = Parameters::Get<Parameters::ExplicitRockCompaction>();
105}
106
107template<class GridView, class FluidSystem>
108FlowGenericProblem<GridView,FluidSystem>
110serializationTestObject(const EclipseState& eclState,
111 const Schedule& schedule,
112 const GridView& gridView)
113{
114 FlowGenericProblem result(eclState, schedule, gridView);
115 result.maxOilSaturation_ = {1.0, 2.0};
116 result.maxWaterSaturation_ = {6.0};
117 result.minRefPressure_ = {7.0, 8.0, 9.0, 10.0};
118 result.overburdenPressure_ = {11.0};
119 result.solventSaturation_ = {15.0};
120 result.solventRsw_ = {18.0};
124
125 return result;
126}
128template<class GridView, class FluidSystem>
129std::string
131helpPreamble(int,
132 const char **argv)
133{
134 std::string desc = FlowGenericProblem::briefDescription();
135 if (!desc.empty())
136 desc = desc + "\n";
137
138 return
139 "Usage: "+std::string(argv[0]) + " [OPTIONS] [ECL_DECK_FILENAME]\n"
140 + desc;
141}
142
143template<class GridView, class FluidSystem>
144std::string
147{
148 return briefDescription_;
149}
150
151template<class GridView, class FluidSystem>
153readRockParameters_(const std::vector<Scalar>& cellCenterDepths,
154 std::function<std::array<int,3>(const unsigned)> ijkIndex)
155{
156 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
157
158 // read the rock compressibility parameters
159 {
160 const auto& comp = rock_config.comp();
161 rockParams_.clear();
162 std::ranges::transform(comp, std::back_inserter(rockParams_),
163 [](const auto& c)
164 {
165 return RockParams{
166 static_cast<Scalar>(c.pref),
167 static_cast<Scalar>(c.compressibility)
168 };
169 });
170 }
171
172 // Warn that ROCK and ROCKOPTS item 2 = STORE is used together
173 if (rock_config.store()) {
174 OpmLog::warning("ROCKOPTS item 2 set to STORE, ROCK item 1 replaced with initial (equilibrated) pressures");
175 }
176
177 // read the parameters for water-induced rock compaction
178 readRockCompactionParameters_();
179
180 unsigned numElem = gridView_.size(0);
181 if (eclState_.fieldProps().has_int(rock_config.rocknum_property())) {
182 // Auxiliary function to check rockTableIdx_ values belong to the right range. Otherwise, throws.
183 std::function<void(int, int)> valueCheck = [&ijkIndex,&rock_config,this](int fieldPropValue, int coarseElemIdx)
184 {
185 auto fmtError = [fieldPropValue, coarseElemIdx,&ijkIndex,&rock_config](const char* type, std::size_t size)
186 {
187 return fmt::format("{} table index {} for elem {} read from {}"
188 " is out of bounds for number of tables {}",
189 type, fieldPropValue,
190 ijkIndex(coarseElemIdx),
191 rock_config.rocknum_property(), size);
192 };
193 if (!rockCompPoroMult_.empty() &&
194 fieldPropValue > static_cast<int>(rockCompPoroMult_.size())) {
195 throw std::runtime_error(fmtError("Rock compaction",
196 rockCompPoroMult_.size()));
197 }
198 if (!rockCompPoroMultWc_.empty() &&
199 fieldPropValue > static_cast<int>(rockCompPoroMultWc_.size())) {
200 throw std::runtime_error(fmtError("Rock water compaction",
201 rockCompPoroMultWc_.size()));
202 }
203 };
205 rockTableIdx_ = this->lookUpData_.template assignFieldPropsIntOnLeaf<short unsigned int>(eclState_.fieldProps(),
206 rock_config.rocknum_property(),
207 true /*needsTranslation*/,
208 valueCheck);
210
211 // Store overburden pressure pr element
212 const auto& overburdTables = eclState_.getTableManager().getOverburdTables();
213 if (!overburdTables.empty() && !rock_config.store()) {
214 overburdenPressure_.resize(numElem,0.0);
215 std::size_t numRocktabTables = rock_config.num_rock_tables();
216
217 if (overburdTables.size() != numRocktabTables)
218 throw std::runtime_error(fmt::format("{} OVERBURD tables is expected, but {} is provided",
219 numRocktabTables, overburdTables.size()));
220
221 std::vector<Tabulated1DFunction<Scalar>> overburdenTables(numRocktabTables);
222 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
223 const OverburdTable& overburdTable = overburdTables.template getTable<OverburdTable>(regionIdx);
224 overburdenTables[regionIdx].setXYContainers(overburdTable.getDepthColumn(),overburdTable.getOverburdenPressureColumn());
225 }
226
227 for (std::size_t elemIdx = 0; elemIdx < numElem; ++ elemIdx) {
228 unsigned tableIdx = 0;
229 if (!rockTableIdx_.empty()) {
230 tableIdx = rockTableIdx_[elemIdx];
231 }
232 overburdenPressure_[elemIdx] =
233 overburdenTables[tableIdx].eval(cellCenterDepths[elemIdx], /*extrapolation=*/true);
234 }
235 }
236 else if (!overburdTables.empty() && rock_config.store()) {
237 OpmLog::warning("ROCKOPTS item 2 set to STORE, OVERBURD ignored!");
238 }
239}
240
241template<class GridView, class FluidSystem>
244{
245 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
246
247 if (!rock_config.active())
248 return; // deck does not enable rock compaction
249
250 unsigned numElem = gridView_.size(0);
251 switch (rock_config.hysteresis_mode()) {
252 case RockConfig::Hysteresis::REVERS:
253 break;
254 case RockConfig::Hysteresis::IRREVERS:
255 // interpolate the porv volume multiplier using the minimum pressure in the cell
256 // i.e. don't allow re-inflation.
257 minRefPressure_.resize(numElem, 1e99);
258 break;
259 default:
260 throw std::runtime_error("Not support ROCKOMP hysteresis option ");
261 }
262
263 std::size_t numRocktabTables = rock_config.num_rock_tables();
264 bool waterCompaction = rock_config.water_compaction();
265
266 if (!waterCompaction) {
267 const auto& rocktabTables = eclState_.getTableManager().getRocktabTables();
268 if (rocktabTables.size() != numRocktabTables)
269 throw std::runtime_error("ROCKCOMP is activated." + std::to_string(numRocktabTables)
270 +" ROCKTAB tables is expected, but " + std::to_string(rocktabTables.size()) +" is provided");
271
272 rockCompPoroMult_.resize(numRocktabTables);
273 rockCompTransMult_.resize(numRocktabTables);
274 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
275 const auto& rocktabTable = rocktabTables.template getTable<RocktabTable>(regionIdx);
276 const auto& pressureColumn = rocktabTable.getPressureColumn();
277 const auto& poroColumn = rocktabTable.getPoreVolumeMultiplierColumn();
278 const auto& transColumn = rocktabTable.getTransmissibilityMultiplierColumn();
279 rockCompPoroMult_[regionIdx].setXYContainers(pressureColumn, poroColumn);
280 rockCompTransMult_[regionIdx].setXYContainers(pressureColumn, transColumn);
281 }
282 } else {
283 const auto& rock2dTables = eclState_.getTableManager().getRock2dTables();
284 const auto& rock2dtrTables = eclState_.getTableManager().getRock2dtrTables();
285 const auto& rockwnodTables = eclState_.getTableManager().getRockwnodTables();
286 maxWaterSaturation_.resize(numElem, 0.0);
287
288 if (rock2dTables.size() != numRocktabTables)
289 throw std::runtime_error(fmt::format("Water compation option is selected in ROCKCOMP."
290 " {} ROCK2D tables is expected, but {} is provided",
291 numRocktabTables, rock2dTables.size()));
292
293 if (rockwnodTables.size() != numRocktabTables)
294 throw std::runtime_error(fmt::format("Water compation option is selected in ROCKCOMP."
295 " {} ROCKWNOD tables is expected, but {} is provided",
296 numRocktabTables, rockwnodTables.size()));
297 //TODO check size match
298 rockCompPoroMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
299 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
300 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
301 const auto& rock2dTable = rock2dTables[regionIdx];
302
303 if (rockwnodTable.getSaturationColumn().size() != rock2dTable.sizeMultValues())
304 throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2D needs to match.");
305
306 for (std::size_t xIdx = 0; xIdx < rock2dTable.size(); ++xIdx) {
307 rockCompPoroMultWc_[regionIdx].appendXPos(rock2dTable.getPressureValue(xIdx));
308 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
309 rockCompPoroMultWc_[regionIdx].appendSamplePoint(xIdx,
310 rockwnodTable.getSaturationColumn()[yIdx],
311 rock2dTable.getPvmultValue(xIdx, yIdx));
312 }
313 }
314
315 if (!rock2dtrTables.empty()) {
316 rockCompTransMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
317 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
318 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
319 const auto& rock2dtrTable = rock2dtrTables[regionIdx];
321 if (rockwnodTable.getSaturationColumn().size() != rock2dtrTable.sizeMultValues())
322 throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2DTR needs to match.");
323
324 for (std::size_t xIdx = 0; xIdx < rock2dtrTable.size(); ++xIdx) {
325 rockCompTransMultWc_[regionIdx].appendXPos(rock2dtrTable.getPressureValue(xIdx));
326 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
327 rockCompTransMultWc_[regionIdx].appendSamplePoint(xIdx,
328 rockwnodTable.getSaturationColumn()[yIdx],
329 rock2dtrTable.getTransMultValue(xIdx, yIdx));
331 }
332 }
333 }
334}
335
336template<class GridView, class FluidSystem>
339rockCompressibility(unsigned globalSpaceIdx) const
340{
341 if (this->rockParams_.empty())
342 return 0.0;
343
344 unsigned tableIdx = 0;
345 if (!this->rockTableIdx_.empty()) {
346 tableIdx = this->rockTableIdx_[globalSpaceIdx];
347 }
348 return this->rockParams_[tableIdx].compressibility;
349}
350
351template<class GridView, class FluidSystem>
354porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
355{
356 return this->referencePorosity_[timeIdx][globalSpaceIdx];
357}
358
359template<class GridView, class FluidSystem>
362rockBiotComp(unsigned elementIdx) const
363{
364 // Additional compressibility of the rock due to Biot poroelasticity
365 auto biot = biotCoeff(elementIdx);
366 auto lameParam = lame(elementIdx);
367 return biot * biot / lameParam;
368}
369
370template<class GridView, class FluidSystem>
373lame(unsigned elementIdx) const
374{
375 Scalar lameParam;
376 const auto& fp = eclState_.fieldProps();
377 if (fp.has_double("LAME")) {
378 lameParam = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "LAME", elementIdx);
379 }
380 else if (fp.has_double("YMODULE") && fp.has_double("SMODULUS")) {
381 const auto& yModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "YMODULE", elementIdx);
382 const auto& sModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "SMODULUS", elementIdx);
383 lameParam = sModulus * (yModulus - 2 * sModulus) / (3 * sModulus - yModulus);
384 }
385 else if (fp.has_double("YMODULE") && fp.has_double("PRATIO")) {
386 const auto& yModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "YMODULE", elementIdx);
387 const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "PRATIO", elementIdx);
388 lameParam = yModulus * pRatio / ((1 + pRatio) * (1 - 2 * pRatio));
389 }
390 else if (fp.has_double("SMODULUS") && fp.has_double("PRATIO")) {
391 const auto& sModulus = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "SMODULUS", elementIdx);
392 const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "PRATIO", elementIdx);
393 lameParam = 2 * sModulus * pRatio / (1 - 2 * pRatio);
394 }
395 else {
396 return 0.0;
397 }
398 return lameParam;
399}
400
401template<class GridView, class FluidSystem>
404biotCoeff(unsigned elementIdx) const
405{
406 Scalar biotC;
407 const auto& fp = eclState_.fieldProps();
408 if (fp.has_double("BIOTCOEF")) {
409 biotC = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "BIOTCOEF", elementIdx);
410 }
411 else if (fp.has_double("POELCOEF") && fp.has_double("PRATIO")) {
412 const auto& poelC = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "POELCOEF", elementIdx);
413 const auto& pRatio = this->lookUpData_.fieldPropDouble(this->eclState_.fieldProps(), "PRATIO", elementIdx);
414 biotC = poelC * (1 - pRatio) / (1 - 2 * pRatio);
415 }
416 else {
417 return 0.0;
418 }
419 return biotC;
420}
421
422
423template<class GridView, class FluidSystem>
424template<class T>
426updateNum(const std::string& name, std::vector<T>& numbers, std::size_t num_regions)
427{
428 if (!eclState_.fieldProps().has_int(name))
429 return;
430
431 std::function<void(T, int)> valueCheck = [num_regions,name](T fieldPropValue, [[maybe_unused]] int fieldPropIdx) {
432 if (fieldPropValue > static_cast<int>(num_regions)) {
433 throw std::runtime_error(fmt::format("Values larger than maximum number of regions {} provided in {}",
434 num_regions, name));
435 }
436 if (fieldPropValue <= 0) {
437 throw std::runtime_error("zero or negative values provided for region array: " + name);
438 }
439 };
440
441 numbers = this->lookUpData_.template assignFieldPropsIntOnLeaf<T>(eclState_.fieldProps(), name,
442 true /*needsTranslation*/, valueCheck);
443}
444
445template<class GridView, class FluidSystem>
448{
449 const auto num_regions = eclState_.getTableManager().getTabdims().getNumPVTTables();
450 updateNum("PVTNUM", pvtnum_, num_regions);
451}
452
453template<class GridView, class FluidSystem>
456{
457 const auto num_regions = eclState_.getTableManager().getTabdims().getNumSatTables();
458 updateNum("SATNUM", satnum_, num_regions);
459}
460
461template<class GridView, class FluidSystem>
464{
465 const auto num_regions = 1; // we only support single region
466 updateNum("MISCNUM", miscnum_, num_regions);
467}
468
469template<class GridView, class FluidSystem>
472{
473 const auto num_regions = 1; // we only support single region
474 updateNum("PLMIXNUM", plmixnum_, num_regions);
475}
476
477template<class GridView, class FluidSystem>
479vapparsActive(int episodeIdx) const
480{
481 const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
482 return (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::VAPPARS);
483}
484
485template<class GridView, class FluidSystem>
487beginEpisode_(bool enableExperiments,
488 int episodeIdx)
489{
490 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
491 // print some useful information in experimental mode. (the production
492 // simulator does this externally.)
493 std::ostringstream ss;
494 boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
495 boost::posix_time::ptime curDateTime =
496 boost::posix_time::from_time_t(schedule_.simTime(episodeIdx));
497 ss.imbue(std::locale(std::locale::classic(), facet));
498 ss << "Report step " << episodeIdx + 1
499 << "/" << schedule_.size() - 1
500 << " at day " << schedule_.seconds(episodeIdx)/(24*3600)
501 << "/" << schedule_.seconds(schedule_.size() - 1)/(24*3600)
502 << ", date = " << curDateTime.date()
503 << "\n ";
504 OpmLog::info(ss.str());
505 }
506
507 const auto& events = schedule_[episodeIdx].events();
508
509 // react to TUNING changes
510 if (episodeIdx > 0 && enableTuning_ && events.hasEvent(ScheduleEvents::TUNING_CHANGE))
511 {
512 const auto& sched_state = schedule_[episodeIdx];
513 const auto& tuning = sched_state.tuning();
514 initialTimeStepSize_ = sched_state.max_next_tstep(enableTuning_);
515 maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
516 return true;
517 }
518
519 return false;
520}
521
522template<class GridView, class FluidSystem>
524beginTimeStep_(bool enableExperiments,
525 int episodeIdx,
526 int timeStepIndex,
527 Scalar startTime,
528 Scalar time,
529 Scalar timeStepSize,
530 Scalar endTime)
531{
532 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
533 std::ostringstream ss;
534 boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
535 boost::posix_time::ptime date = boost::posix_time::from_time_t(startTime) +
536 boost::posix_time::milliseconds(static_cast<long long>(time / prefix::milli));
537 ss.imbue(std::locale(std::locale::classic(), facet));
538 ss <<"\nTime step " << timeStepIndex << ", stepsize "
539 << unit::convert::to(timeStepSize, unit::day) << " days,"
540 << " at day " << (double)unit::convert::to(time, unit::day)
541 << "/" << (double)unit::convert::to(endTime, unit::day)
542 << ", date = " << date;
543 OpmLog::info(ss.str());
544 }
545}
546
547template<class GridView, class FluidSystem>
550{
551 FluidSystem::initFromState(eclState_, schedule_);
552}
553
554template<class GridView, class FluidSystem>
557 bool enableSolvent,
558 bool enablePolymer,
559 bool enablePolymerMolarWeight,
560 bool enableBioeffects,
561 bool enableMICP)
562{
563 // LGR (local grid refinement / CARFIN) is supported for black-oil only. The
564 // solvent/polymer/biofilm/MICP initial conditions below are read straight
565 // from the input-grid field properties and indexed by leaf cell; they are
566 // NOT mapped onto refined cells (see the black-oil EQLNUM/FIPNUM handling via
567 // LookUpData), so refined cells would get wrong/out-of-range values. Fail
568 // early with a clear message rather than producing silently wrong results.
569 if ((enableSolvent || enablePolymer || enablePolymerMolarWeight ||
570 enableBioeffects || enableMICP) &&
571 (eclState_.getLgrs().size() > 0))
572 {
573 throw std::runtime_error(
574 "Local grid refinement (LGR/CARFIN) is only supported for black-oil "
575 "runs. It is not supported together with the solvent, polymer, "
576 "biofilm or MICP extensions.");
577 }
578
579 auto getArray = [](const std::vector<double>& input)
580 {
581 if constexpr (std::is_same_v<Scalar,double>) {
582 return input;
583 } else {
584 return std::vector<Scalar>{input.begin(), input.end()};
585 }
586 };
587
588 if (enableSolvent) {
589 if (eclState_.fieldProps().has_double("SSOL")) {
590 solventSaturation_ = getArray(eclState_.fieldProps().get_double("SSOL"));
591 } else {
592 solventSaturation_.resize(numDof, 0.0);
593 }
594
595 solventRsw_.resize(numDof, 0.0);
596 }
597
598 if (enablePolymer) {
599 if (eclState_.fieldProps().has_double("SPOLY")) {
600 polymer_.concentration = getArray(eclState_.fieldProps().get_double("SPOLY"));
601 } else {
602 polymer_.concentration.resize(numDof, 0.0);
603 }
604 }
605
606 if (enablePolymerMolarWeight) {
607 if (eclState_.fieldProps().has_double("SPOLYMW")) {
608 polymer_.moleWeight = getArray(eclState_.fieldProps().get_double("SPOLYMW"));
609 } else {
610 polymer_.moleWeight.resize(numDof, 0.0);
611 }
612 }
613
614 if (enableBioeffects) {
615 if (eclState_.fieldProps().has_double("SMICR")) {
616 bioeffects_.microbialConcentration = getArray(eclState_.fieldProps().get_double("SMICR"));
617 } else {
618 bioeffects_.microbialConcentration.resize(numDof, 0.0);
619 }
620 if (eclState_.fieldProps().has_double("SBIOF")) {
621 bioeffects_.biofilmVolumeFraction = getArray(eclState_.fieldProps().get_double("SBIOF"));
622 } else {
623 bioeffects_.biofilmVolumeFraction.resize(numDof, 0.0);
624 }
625 if (enableMICP) {
626 if (eclState_.fieldProps().has_double("SOXYG")) {
627 bioeffects_.oxygenConcentration = getArray(eclState_.fieldProps().get_double("SOXYG"));
628 } else {
629 bioeffects_.oxygenConcentration.resize(numDof, 0.0);
630 }
631 if (eclState_.fieldProps().has_double("SUREA")) {
632 bioeffects_.ureaConcentration = getArray(eclState_.fieldProps().get_double("SUREA"));
633 } else {
634 bioeffects_.ureaConcentration.resize(numDof, 0.0);
635 }
636 if (eclState_.fieldProps().has_double("SCALC")) {
637 bioeffects_.calciteVolumeFraction = getArray(eclState_.fieldProps().get_double("SCALC"));
638 } else {
639 bioeffects_.calciteVolumeFraction.resize(numDof, 0.0);
640 }
641 }
642 }
643}
644
645template<class GridView, class FluidSystem>
648maxWaterSaturation(unsigned globalDofIdx) const
649{
650 if (maxWaterSaturation_.empty())
651 return 0.0;
652
653 return maxWaterSaturation_[globalDofIdx];
654}
655
656template<class GridView, class FluidSystem>
659minOilPressure(unsigned globalDofIdx) const
660{
661 if (minRefPressure_.empty())
662 return 0.0;
663
664 return minRefPressure_[globalDofIdx];
665}
666
667template<class GridView, class FluidSystem>
670overburdenPressure(unsigned elementIdx) const
671{
672 if (overburdenPressure_.empty())
673 return 0.0;
674
675 return overburdenPressure_[elementIdx];
676}
677
678template<class GridView, class FluidSystem>
681solventSaturation(unsigned elemIdx) const
682{
683 if (solventSaturation_.empty())
684 return 0;
685
686 return solventSaturation_[elemIdx];
687}
688
689template<class GridView, class FluidSystem>
692solventRsw(unsigned elemIdx) const
693{
694 if (solventRsw_.empty())
695 return 0;
696
697 return solventRsw_[elemIdx];
698}
699
700
701
702template<class GridView, class FluidSystem>
705polymerConcentration(unsigned elemIdx) const
706{
707 if (polymer_.concentration.empty()) {
708 return 0;
709 }
710
711 return polymer_.concentration[elemIdx];
712}
713
714template<class GridView, class FluidSystem>
717polymerMolecularWeight(const unsigned elemIdx) const
718{
719 if (polymer_.moleWeight.empty()) {
720 return 0.0;
721 }
722
723 return polymer_.moleWeight[elemIdx];
724}
725
726template<class GridView, class FluidSystem>
729microbialConcentration(unsigned elemIdx) const
730{
731 if (bioeffects_.microbialConcentration.empty()) {
732 return 0;
733 }
734
735 return bioeffects_.microbialConcentration[elemIdx];
736}
737
738template<class GridView, class FluidSystem>
741oxygenConcentration(unsigned elemIdx) const
742{
743 if (bioeffects_.oxygenConcentration.empty()) {
744 return 0;
745 }
746
747 return bioeffects_.oxygenConcentration[elemIdx];
748}
749
750template<class GridView, class FluidSystem>
753ureaConcentration(unsigned elemIdx) const
754{
755 if (bioeffects_.ureaConcentration.empty()) {
756 return 0;
757 }
758
759 return bioeffects_.ureaConcentration[elemIdx];
760}
761
762template<class GridView, class FluidSystem>
765biofilmVolumeFraction(unsigned elemIdx) const
766{
767 if (bioeffects_.biofilmVolumeFraction.empty()) {
768 return 0;
769 }
770
771 return bioeffects_.biofilmVolumeFraction[elemIdx];
772}
773
774template<class GridView, class FluidSystem>
777calciteVolumeFraction(unsigned elemIdx) const
778{
779 if (bioeffects_.calciteVolumeFraction.empty()) {
780 return 0;
781 }
782
783 return bioeffects_.calciteVolumeFraction[elemIdx];
784}
785
786template<class GridView, class FluidSystem>
788pvtRegionIndex(unsigned elemIdx) const
789{
790 if (pvtnum_.empty())
791 return 0;
792
793 return pvtnum_[elemIdx];
794}
795
796template<class GridView, class FluidSystem>
798satnumRegionIndex(unsigned elemIdx) const
799{
800 if (satnum_.empty())
801 return 0;
802
803 return satnum_[elemIdx];
804}
805
806template<class GridView, class FluidSystem>
808miscnumRegionIndex(unsigned elemIdx) const
809{
810 if (miscnum_.empty())
811 return 0;
812
813 return miscnum_[elemIdx];
814}
815
816template<class GridView, class FluidSystem>
818plmixnumRegionIndex(unsigned elemIdx) const
819{
820 if (plmixnum_.empty())
821 return 0;
822
823 return plmixnum_[elemIdx];
824}
825
826template<class GridView, class FluidSystem>
829maxPolymerAdsorption(unsigned elemIdx) const
830{
831 if (polymer_.maxAdsorption.empty()) {
832 return 0;
833 }
834
835 return polymer_.maxAdsorption[elemIdx];
836}
837
838template<class GridView, class FluidSystem>
840operator==(const FlowGenericProblem& rhs) const
841{
842 return this->maxWaterSaturation_ == rhs.maxWaterSaturation_ &&
843 this->minRefPressure_ == rhs.minRefPressure_ &&
844 this->overburdenPressure_ == rhs.overburdenPressure_ &&
845 this->solventSaturation_ == rhs.solventSaturation_ &&
846 this->solventRsw_ == rhs.solventRsw_ &&
847 this->polymer_ == rhs.polymer_ &&
848 this->bioeffects_ == rhs.bioeffects_;
849}
850
851} // namespace Opm
852
853#endif // OPM_FLOW_GENERIC_PROBLEM_IMPL_HPP
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:829
unsigned pvtRegionIndex(unsigned elemIdx) const
Returns the index the relevant PVT region given a cell index.
Definition: FlowGenericProblem_impl.hpp:788
Scalar oxygenConcentration(unsigned elemIdx) const
Returns the initial oxygen concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:741
Scalar microbialConcentration(unsigned elemIdx) const
Returns the initial microbial concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:729
PolymerSolutionContainer< Scalar > polymer_
Definition: FlowGenericProblem.hpp:353
static std::string briefDescription()
Returns a human readable description of the problem for the help message.
Definition: FlowGenericProblem_impl.hpp:146
Scalar solventRsw(unsigned elemIdx) const
Returns the initial solvent dissolved in water for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:692
Scalar overburdenPressure(unsigned elementIdx) const
Get the pressure of the overburden.
Definition: FlowGenericProblem_impl.hpp:670
void updateMiscnum_()
Definition: FlowGenericProblem_impl.hpp:463
Scalar porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
Direct indexed access to the porosity.
Definition: FlowGenericProblem_impl.hpp:354
Scalar rockCompressibility(unsigned globalSpaceIdx) const
Definition: FlowGenericProblem_impl.hpp:339
Scalar initialTimeStepSize_
Definition: FlowGenericProblem.hpp:365
unsigned miscnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant MISC region given a cell index.
Definition: FlowGenericProblem_impl.hpp:808
bool vapparsActive(int episodeIdx) const
Definition: FlowGenericProblem_impl.hpp:479
unsigned satnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant saturation function region given a cell index.
Definition: FlowGenericProblem_impl.hpp:798
Scalar maxWaterSaturation(unsigned globalDofIdx) const
Returns an element's historic maximum water phase saturation that was observed during the simulation.
Definition: FlowGenericProblem_impl.hpp:648
std::vector< Scalar > solventSaturation_
Definition: FlowGenericProblem.hpp:358
void readRockCompactionParameters_()
Definition: FlowGenericProblem_impl.hpp:243
void updateSatnum_()
Definition: FlowGenericProblem_impl.hpp:455
void updatePvtnum_()
Definition: FlowGenericProblem_impl.hpp:447
bool enableDriftCompensation_
Definition: FlowGenericProblem.hpp:371
Scalar lame(unsigned elementIdx) const
Direct access to Lame's second parameter in an element.
Definition: FlowGenericProblem_impl.hpp:373
static FlowGenericProblem serializationTestObject(const EclipseState &eclState, const Schedule &schedule, const GridView &gridView)
Definition: FlowGenericProblem_impl.hpp:110
void beginTimeStep_(bool enableExperiments, int episodeIdx, int timeStepIndex, Scalar startTime, Scalar time, Scalar timeStepSize, Scalar endTime)
Definition: FlowGenericProblem_impl.hpp:524
Scalar calciteVolumeFraction(unsigned elemIdx) const
Returns the initial calcite volume fraction for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:777
CO2H2SolutionContainer< Scalar > CO2H2_
Definition: FlowGenericProblem.hpp:361
unsigned plmixnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant PLMIXNUM (for polymer module) region given a cell index.
Definition: FlowGenericProblem_impl.hpp:818
FlowGenericProblem(const EclipseState &eclState, const Schedule &schedule, const GridView &gridView)
Definition: FlowGenericProblem_impl.hpp:60
BioeffectsSolutionContainer< Scalar > bioeffects_
Definition: FlowGenericProblem.hpp:360
bool enableTuning_
Definition: FlowGenericProblem.hpp:364
Scalar solventSaturation(unsigned elemIdx) const
Returns the initial solvent saturation for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:681
Scalar polymerMolecularWeight(const unsigned elemIdx) const
Returns the polymer molecule weight for a given cell index.
Definition: FlowGenericProblem_impl.hpp:717
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:153
std::vector< Scalar > maxOilSaturation_
Definition: FlowGenericProblem.hpp:354
Scalar rockBiotComp(unsigned elementIdx) const
Returns the rock compressibility of an element due to poroelasticity.
Definition: FlowGenericProblem_impl.hpp:362
int numPressurePointsEquil_
Definition: FlowGenericProblem.hpp:369
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:659
std::vector< Scalar > maxWaterSaturation_
Definition: FlowGenericProblem.hpp:355
void initFluidSystem_()
Definition: FlowGenericProblem_impl.hpp:549
bool operator==(const FlowGenericProblem &rhs) const
Definition: FlowGenericProblem_impl.hpp:840
Scalar maxTimeStepAfterWellEvent_
Definition: FlowGenericProblem.hpp:366
Scalar ureaConcentration(unsigned elemIdx) const
Returns the initial urea concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:753
std::vector< Scalar > minRefPressure_
Definition: FlowGenericProblem.hpp:356
bool beginEpisode_(bool enableExperiments, int episodeIdx)
Definition: FlowGenericProblem_impl.hpp:487
Scalar biofilmVolumeFraction(unsigned elemIdx) const
Returns the initial biofilm volume fraction for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:765
std::vector< Scalar > solventRsw_
Definition: FlowGenericProblem.hpp:359
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:131
std::vector< Scalar > overburdenPressure_
Definition: FlowGenericProblem.hpp:357
void readBlackoilExtentionsInitialConditions_(std::size_t numDof, bool enableSolvent, bool enablePolymer, bool enablePolymerMolarWeight, bool enableBioeffects, bool enableMICP)
Definition: FlowGenericProblem_impl.hpp:556
Scalar biotCoeff(unsigned elementIdx) const
Direct access to Biot coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:404
void updatePlmixnum_()
Definition: FlowGenericProblem_impl.hpp:471
bool explicitRockCompaction_
Definition: FlowGenericProblem.hpp:373
Scalar polymerConcentration(unsigned elemIdx) const
Returns the initial polymer concentration for a given a cell index.
Definition: FlowGenericProblem_impl.hpp:705
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:191
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: EclTimeSteppingParams.hpp:48
static PolymerSolutionContainer serializationTestObject()