opm-simulators
Loading...
Searching...
No Matches
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
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
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
91template<class GridView, class FluidSystem>
92FlowGenericProblem<GridView,FluidSystem>
93FlowGenericProblem<GridView,FluidSystem>::
94serializationTestObject(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
112template<class GridView, class FluidSystem>
113std::string
114FlowGenericProblem<GridView,FluidSystem>::
115helpPreamble(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
127template<class GridView, class FluidSystem>
128std::string
129FlowGenericProblem<GridView,FluidSystem>::
130briefDescription()
131{
132 return briefDescription_;
133}
134
135template<class GridView, class FluidSystem>
137readRockParameters_(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
225template<class GridView, class FluidSystem>
226void FlowGenericProblem<GridView,FluidSystem>::
227readRockCompactionParameters_()
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
320template<class GridView, class FluidSystem>
321typename FlowGenericProblem<GridView,FluidSystem>::Scalar
322FlowGenericProblem<GridView,FluidSystem>::
323rockCompressibility(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
335template<class GridView, class FluidSystem>
336typename FlowGenericProblem<GridView,FluidSystem>::Scalar
337FlowGenericProblem<GridView,FluidSystem>::
338porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
339{
340 return this->referencePorosity_[timeIdx][globalSpaceIdx];
341}
342
343template<class GridView, class FluidSystem>
344typename FlowGenericProblem<GridView,FluidSystem>::Scalar
345FlowGenericProblem<GridView,FluidSystem>::
346rockBiotComp(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
354template<class GridView, class FluidSystem>
355typename FlowGenericProblem<GridView,FluidSystem>::Scalar
356FlowGenericProblem<GridView,FluidSystem>::
357lame(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
385template<class GridView, class FluidSystem>
386typename FlowGenericProblem<GridView,FluidSystem>::Scalar
387FlowGenericProblem<GridView,FluidSystem>::
388biotCoeff(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
407template<class GridView, class FluidSystem>
408template<class T>
410updateNum(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
429template<class GridView, class FluidSystem>
430void FlowGenericProblem<GridView,FluidSystem>::
431updatePvtnum_()
432{
433 const auto num_regions = eclState_.getTableManager().getTabdims().getNumPVTTables();
434 updateNum("PVTNUM", pvtnum_, num_regions);
435}
436
437template<class GridView, class FluidSystem>
438void FlowGenericProblem<GridView,FluidSystem>::
439updateSatnum_()
440{
441 const auto num_regions = eclState_.getTableManager().getTabdims().getNumSatTables();
442 updateNum("SATNUM", satnum_, num_regions);
443}
444
445template<class GridView, class FluidSystem>
446void FlowGenericProblem<GridView,FluidSystem>::
447updateMiscnum_()
448{
449 const auto num_regions = 1; // we only support single region
450 updateNum("MISCNUM", miscnum_, num_regions);
451}
452
453template<class GridView, class FluidSystem>
454void FlowGenericProblem<GridView,FluidSystem>::
455updatePlmixnum_()
456{
457 const auto num_regions = 1; // we only support single region
458 updateNum("PLMIXNUM", plmixnum_, num_regions);
459}
460
461template<class GridView, class FluidSystem>
462bool FlowGenericProblem<GridView,FluidSystem>::
463vapparsActive(int episodeIdx) const
464{
465 const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
466 return (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::VAPPARS);
467}
468
469template<class GridView, class FluidSystem>
470bool FlowGenericProblem<GridView,FluidSystem>::
471beginEpisode_(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
506template<class GridView, class FluidSystem>
507void FlowGenericProblem<GridView,FluidSystem>::
508beginTimeStep_(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
531template<class GridView, class FluidSystem>
532void FlowGenericProblem<GridView,FluidSystem>::
533initFluidSystem_()
534{
535 FluidSystem::initFromState(eclState_, schedule_);
536}
537
538template<class GridView, class FluidSystem>
539void FlowGenericProblem<GridView,FluidSystem>::
540readBlackoilExtentionsInitialConditions_(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
613template<class GridView, class FluidSystem>
614typename FlowGenericProblem<GridView,FluidSystem>::Scalar
615FlowGenericProblem<GridView,FluidSystem>::
616maxWaterSaturation(unsigned globalDofIdx) const
617{
618 if (maxWaterSaturation_.empty())
619 return 0.0;
620
621 return maxWaterSaturation_[globalDofIdx];
622}
623
624template<class GridView, class FluidSystem>
625typename FlowGenericProblem<GridView,FluidSystem>::Scalar
626FlowGenericProblem<GridView,FluidSystem>::
627minOilPressure(unsigned globalDofIdx) const
628{
629 if (minRefPressure_.empty())
630 return 0.0;
631
632 return minRefPressure_[globalDofIdx];
633}
634
635template<class GridView, class FluidSystem>
636typename FlowGenericProblem<GridView,FluidSystem>::Scalar
637FlowGenericProblem<GridView,FluidSystem>::
638overburdenPressure(unsigned elementIdx) const
639{
640 if (overburdenPressure_.empty())
641 return 0.0;
642
643 return overburdenPressure_[elementIdx];
644}
645
646template<class GridView, class FluidSystem>
647typename FlowGenericProblem<GridView,FluidSystem>::Scalar
648FlowGenericProblem<GridView,FluidSystem>::
649solventSaturation(unsigned elemIdx) const
650{
651 if (solventSaturation_.empty())
652 return 0;
653
654 return solventSaturation_[elemIdx];
655}
656
657template<class GridView, class FluidSystem>
658typename FlowGenericProblem<GridView,FluidSystem>::Scalar
659FlowGenericProblem<GridView,FluidSystem>::
660solventRsw(unsigned elemIdx) const
661{
662 if (solventRsw_.empty())
663 return 0;
664
665 return solventRsw_[elemIdx];
666}
667
668
669
670template<class GridView, class FluidSystem>
671typename FlowGenericProblem<GridView,FluidSystem>::Scalar
672FlowGenericProblem<GridView,FluidSystem>::
673polymerConcentration(unsigned elemIdx) const
674{
675 if (polymer_.concentration.empty()) {
676 return 0;
677 }
678
679 return polymer_.concentration[elemIdx];
680}
681
682template<class GridView, class FluidSystem>
683typename FlowGenericProblem<GridView,FluidSystem>::Scalar
684FlowGenericProblem<GridView,FluidSystem>::
685polymerMolecularWeight(const unsigned elemIdx) const
686{
687 if (polymer_.moleWeight.empty()) {
688 return 0.0;
689 }
690
691 return polymer_.moleWeight[elemIdx];
692}
693
694template<class GridView, class FluidSystem>
695typename FlowGenericProblem<GridView,FluidSystem>::Scalar
696FlowGenericProblem<GridView,FluidSystem>::
697microbialConcentration(unsigned elemIdx) const
698{
699 if (bioeffects_.microbialConcentration.empty()) {
700 return 0;
701 }
702
703 return bioeffects_.microbialConcentration[elemIdx];
704}
705
706template<class GridView, class FluidSystem>
707typename FlowGenericProblem<GridView,FluidSystem>::Scalar
708FlowGenericProblem<GridView,FluidSystem>::
709oxygenConcentration(unsigned elemIdx) const
710{
711 if (bioeffects_.oxygenConcentration.empty()) {
712 return 0;
713 }
714
715 return bioeffects_.oxygenConcentration[elemIdx];
716}
717
718template<class GridView, class FluidSystem>
719typename FlowGenericProblem<GridView,FluidSystem>::Scalar
720FlowGenericProblem<GridView,FluidSystem>::
721ureaConcentration(unsigned elemIdx) const
722{
723 if (bioeffects_.ureaConcentration.empty()) {
724 return 0;
725 }
726
727 return bioeffects_.ureaConcentration[elemIdx];
728}
729
730template<class GridView, class FluidSystem>
731typename FlowGenericProblem<GridView,FluidSystem>::Scalar
732FlowGenericProblem<GridView,FluidSystem>::
733biofilmVolumeFraction(unsigned elemIdx) const
734{
735 if (bioeffects_.biofilmVolumeFraction.empty()) {
736 return 0;
737 }
738
739 return bioeffects_.biofilmVolumeFraction[elemIdx];
740}
741
742template<class GridView, class FluidSystem>
743typename FlowGenericProblem<GridView,FluidSystem>::Scalar
744FlowGenericProblem<GridView,FluidSystem>::
745calciteVolumeFraction(unsigned elemIdx) const
746{
747 if (bioeffects_.calciteVolumeFraction.empty()) {
748 return 0;
749 }
750
751 return bioeffects_.calciteVolumeFraction[elemIdx];
752}
753
754template<class GridView, class FluidSystem>
755unsigned FlowGenericProblem<GridView,FluidSystem>::
756pvtRegionIndex(unsigned elemIdx) const
757{
758 if (pvtnum_.empty())
759 return 0;
760
761 return pvtnum_[elemIdx];
762}
763
764template<class GridView, class FluidSystem>
765unsigned FlowGenericProblem<GridView,FluidSystem>::
766satnumRegionIndex(unsigned elemIdx) const
767{
768 if (satnum_.empty())
769 return 0;
770
771 return satnum_[elemIdx];
772}
773
774template<class GridView, class FluidSystem>
775unsigned FlowGenericProblem<GridView,FluidSystem>::
776miscnumRegionIndex(unsigned elemIdx) const
777{
778 if (miscnum_.empty())
779 return 0;
780
781 return miscnum_[elemIdx];
782}
783
784template<class GridView, class FluidSystem>
785unsigned FlowGenericProblem<GridView,FluidSystem>::
786plmixnumRegionIndex(unsigned elemIdx) const
787{
788 if (plmixnum_.empty())
789 return 0;
790
791 return plmixnum_[elemIdx];
792}
793
794template<class GridView, class FluidSystem>
795typename FlowGenericProblem<GridView,FluidSystem>::Scalar
796FlowGenericProblem<GridView,FluidSystem>::
797maxPolymerAdsorption(unsigned elemIdx) const
798{
799 if (polymer_.maxAdsorption.empty()) {
800 return 0;
801 }
802
803 return polymer_.maxAdsorption[elemIdx];
804}
805
806template<class GridView, class FluidSystem>
808operator==(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
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
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
static std::string briefDescription()
Returns a human readable description of the problem for the help message.
Definition FlowGenericProblem_impl.hpp:130
Scalar lame(unsigned elementIdx) const
Direct access to Lame's second parameter in an element.
Definition FlowGenericProblem_impl.hpp:357
Scalar biotCoeff(unsigned elementIdx) const
Direct access to Biot coefficient in an element.
Definition FlowGenericProblem_impl.hpp:388
Declare the properties used by the infrastructure code of the finite volume discretizations.
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilbioeffectsmodules.hh:45
This file provides the infrastructure to retrieve run-time parameters.