My Project
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#include <dune/common/parametertree.hh>
27
28#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
29#include <opm/input/eclipse/EclipseState/Tables/OverburdTable.hpp>
30#include <opm/input/eclipse/EclipseState/Tables/RockwnodTable.hpp>
31#include <opm/input/eclipse/Schedule/Schedule.hpp>
32#include <opm/input/eclipse/Units/Units.hpp>
33
36
37#include <boost/date_time.hpp>
38
39#include <fmt/format.h>
40#include <fmt/ranges.h>
41
42#include <iostream>
43#include <stdexcept>
44
45namespace Opm {
46
47template<class GridView, class FluidSystem>
48FlowGenericProblem<GridView,FluidSystem>::
49FlowGenericProblem(const EclipseState& eclState,
50 const Schedule& schedule,
51 const GridView& gridView)
52 : eclState_(eclState)
53 , schedule_(schedule)
54 , gridView_(gridView)
55 , lookUpData_(gridView)
56{
57}
58
59template<class GridView, class FluidSystem>
60FlowGenericProblem<GridView,FluidSystem>
61FlowGenericProblem<GridView,FluidSystem>::
62serializationTestObject(const EclipseState& eclState,
63 const Schedule& schedule,
64 const GridView& gridView)
65{
66 FlowGenericProblem result(eclState, schedule, gridView);
67 result.maxOilSaturation_ = {1.0, 2.0};
68 result.maxWaterSaturation_ = {6.0};
69 result.minRefPressure_ = {7.0, 8.0, 9.0, 10.0};
70 result.overburdenPressure_ = {11.0};
71 result.solventSaturation_ = {15.0};
72 result.solventRsw_ = {18.0};
73 result.polymer_ = PolymerSolutionContainer<Scalar>::serializationTestObject();
74 result.micp_ = MICPSolutionContainer<Scalar>::serializationTestObject();
75
76 return result;
77}
78
79template<class GridView, class FluidSystem>
80std::string
82helpPreamble(int,
83 const char **argv)
84{
85 std::string desc = FlowGenericProblem::briefDescription();
86 if (!desc.empty())
87 desc = desc + "\n";
88
89 return
90 "Usage: "+std::string(argv[0]) + " [OPTIONS] [ECL_DECK_FILENAME]\n"
91 + desc;
93
94template<class GridView, class FluidSystem>
95std::string
98{
99 return briefDescription_;
100}
101
102template<class GridView, class FluidSystem>
104readRockParameters_(const std::vector<Scalar>& cellCenterDepths,
105 std::function<std::array<int,3>(const unsigned)> ijkIndex)
106{
107 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
108
109 // read the rock compressibility parameters
110 {
111 const auto& comp = rock_config.comp();
112 rockParams_.clear();
113 for (const auto& c : comp) {
114 rockParams_.push_back({static_cast<Scalar>(c.pref),
115 static_cast<Scalar>(c.compressibility)});
116 }
117 }
118
119 // read the parameters for water-induced rock compaction
120 readRockCompactionParameters_();
121
122 unsigned numElem = gridView_.size(0);
123 if (eclState_.fieldProps().has_int(rock_config.rocknum_property())) {
124 // Auxiliary function to check rockTableIdx_ values belong to the right range. Otherwise, throws.
125 std::function<void(int, int)> valueCheck = [&ijkIndex,&rock_config,this](int fieldPropValue, int coarseElemIdx)
126 {
127 auto fmtError = [fieldPropValue, coarseElemIdx,&ijkIndex,&rock_config](const char* type, std::size_t size)
128 {
129 return fmt::format("{} table index {} for elem {} read from {}"
130 " is out of bounds for number of tables {}",
131 type, fieldPropValue,
132 ijkIndex(coarseElemIdx),
133 rock_config.rocknum_property(), size);
134 };
135 if (!rockCompPoroMult_.empty() &&
136 fieldPropValue > static_cast<int>(rockCompPoroMult_.size())) {
137 throw std::runtime_error(fmtError("Rock compaction",
138 rockCompPoroMult_.size()));
139 }
140 if (!rockCompPoroMultWc_.empty() &&
141 fieldPropValue > static_cast<int>(rockCompPoroMultWc_.size())) {
142 throw std::runtime_error(fmtError("Rock water compaction",
143 rockCompPoroMultWc_.size()));
144 }
145 };
146
147 rockTableIdx_ = this->lookUpData_.template assignFieldPropsIntOnLeaf<short unsigned int>(eclState_.fieldProps(),
148 rock_config.rocknum_property(),
149 true /*needsTranslation*/,
150 valueCheck);
152
153 // Store overburden pressure pr element
154 const auto& overburdTables = eclState_.getTableManager().getOverburdTables();
155 if (!overburdTables.empty()) {
156 overburdenPressure_.resize(numElem,0.0);
157 std::size_t numRocktabTables = rock_config.num_rock_tables();
158
159 if (overburdTables.size() != numRocktabTables)
160 throw std::runtime_error(std::to_string(numRocktabTables) +" OVERBURD tables is expected, but " + std::to_string(overburdTables.size()) +" is provided");
161
162 std::vector<Tabulated1DFunction<Scalar>> overburdenTables(numRocktabTables);
163 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
164 const OverburdTable& overburdTable = overburdTables.template getTable<OverburdTable>(regionIdx);
165 overburdenTables[regionIdx].setXYContainers(overburdTable.getDepthColumn(),overburdTable.getOverburdenPressureColumn());
166 }
167
168 for (std::size_t elemIdx = 0; elemIdx < numElem; ++ elemIdx) {
169 unsigned tableIdx = 0;
170 if (!rockTableIdx_.empty()) {
171 tableIdx = rockTableIdx_[elemIdx];
172 }
173 overburdenPressure_[elemIdx] =
174 overburdenTables[tableIdx].eval(cellCenterDepths[elemIdx], /*extrapolation=*/true);
175 }
176 }
177}
179template<class GridView, class FluidSystem>
182{
183 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
185 if (!rock_config.active())
186 return; // deck does not enable rock compaction
187
188 unsigned numElem = gridView_.size(0);
189 switch (rock_config.hysteresis_mode()) {
190 case RockConfig::Hysteresis::REVERS:
191 break;
192 case RockConfig::Hysteresis::IRREVERS:
193 // interpolate the porv volume multiplier using the minimum pressure in the cell
194 // i.e. don't allow re-inflation.
195 minRefPressure_.resize(numElem, 1e99);
196 break;
197 default:
198 throw std::runtime_error("Not support ROCKOMP hysteresis option ");
200
201 std::size_t numRocktabTables = rock_config.num_rock_tables();
202 bool waterCompaction = rock_config.water_compaction();
203
204 if (!waterCompaction) {
205 const auto& rocktabTables = eclState_.getTableManager().getRocktabTables();
206 if (rocktabTables.size() != numRocktabTables)
207 throw std::runtime_error("ROCKCOMP is activated." + std::to_string(numRocktabTables)
208 +" ROCKTAB tables is expected, but " + std::to_string(rocktabTables.size()) +" is provided");
210 rockCompPoroMult_.resize(numRocktabTables);
211 rockCompTransMult_.resize(numRocktabTables);
212 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
213 const auto& rocktabTable = rocktabTables.template getTable<RocktabTable>(regionIdx);
214 const auto& pressureColumn = rocktabTable.getPressureColumn();
215 const auto& poroColumn = rocktabTable.getPoreVolumeMultiplierColumn();
216 const auto& transColumn = rocktabTable.getTransmissibilityMultiplierColumn();
217 rockCompPoroMult_[regionIdx].setXYContainers(pressureColumn, poroColumn);
218 rockCompTransMult_[regionIdx].setXYContainers(pressureColumn, transColumn);
219 }
220 } else {
221 const auto& rock2dTables = eclState_.getTableManager().getRock2dTables();
222 const auto& rock2dtrTables = eclState_.getTableManager().getRock2dtrTables();
223 const auto& rockwnodTables = eclState_.getTableManager().getRockwnodTables();
224 maxWaterSaturation_.resize(numElem, 0.0);
225
226 if (rock2dTables.size() != numRocktabTables)
227 throw std::runtime_error("Water compation option is selected in ROCKCOMP." + std::to_string(numRocktabTables)
228 +" ROCK2D tables is expected, but " + std::to_string(rock2dTables.size()) +" is provided");
229
230 if (rockwnodTables.size() != numRocktabTables)
231 throw std::runtime_error("Water compation option is selected in ROCKCOMP." + std::to_string(numRocktabTables)
232 +" ROCKWNOD tables is expected, but " + std::to_string(rockwnodTables.size()) +" is provided");
233 //TODO check size match
234 rockCompPoroMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
235 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
236 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
237 const auto& rock2dTable = rock2dTables[regionIdx];
238
239 if (rockwnodTable.getSaturationColumn().size() != rock2dTable.sizeMultValues())
240 throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2D needs to match.");
241
242 for (std::size_t xIdx = 0; xIdx < rock2dTable.size(); ++xIdx) {
243 rockCompPoroMultWc_[regionIdx].appendXPos(rock2dTable.getPressureValue(xIdx));
244 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
245 rockCompPoroMultWc_[regionIdx].appendSamplePoint(xIdx,
246 rockwnodTable.getSaturationColumn()[yIdx],
247 rock2dTable.getPvmultValue(xIdx, yIdx));
248 }
249 }
250
251 if (!rock2dtrTables.empty()) {
252 rockCompTransMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
253 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
254 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
255 const auto& rock2dtrTable = rock2dtrTables[regionIdx];
256
257 if (rockwnodTable.getSaturationColumn().size() != rock2dtrTable.sizeMultValues())
258 throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2DTR needs to match.");
259
260 for (std::size_t xIdx = 0; xIdx < rock2dtrTable.size(); ++xIdx) {
261 rockCompTransMultWc_[regionIdx].appendXPos(rock2dtrTable.getPressureValue(xIdx));
262 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
263 rockCompTransMultWc_[regionIdx].appendSamplePoint(xIdx,
264 rockwnodTable.getSaturationColumn()[yIdx],
265 rock2dtrTable.getTransMultValue(xIdx, yIdx));
266 }
267 }
268 }
269 }
270}
271
272template<class GridView, class FluidSystem>
273typename FlowGenericProblem<GridView,FluidSystem>::Scalar
275rockCompressibility(unsigned globalSpaceIdx) const
276{
277 if (this->rockParams_.empty())
278 return 0.0;
279
280 unsigned tableIdx = 0;
281 if (!this->rockTableIdx_.empty()) {
282 tableIdx = this->rockTableIdx_[globalSpaceIdx];
283 }
284 return this->rockParams_[tableIdx].compressibility;
285}
286
287template<class GridView, class FluidSystem>
288typename FlowGenericProblem<GridView,FluidSystem>::Scalar
290rockReferencePressure(unsigned globalSpaceIdx) const
291{
292 if (this->rockParams_.empty())
293 return 1e5;
294
295 unsigned tableIdx = 0;
296 if (!this->rockTableIdx_.empty()) {
297 tableIdx = this->rockTableIdx_[globalSpaceIdx];
298 }
299 return this->rockParams_[tableIdx].referencePressure;
300}
301
302template<class GridView, class FluidSystem>
303typename FlowGenericProblem<GridView,FluidSystem>::Scalar
305porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
306{
307 return this->referencePorosity_[timeIdx][globalSpaceIdx];
308}
309
310template<class GridView, class FluidSystem>
311typename FlowGenericProblem<GridView,FluidSystem>::Scalar
313rockFraction(unsigned elementIdx, unsigned timeIdx) const
314{
315 // the reference porosity is defined as the accumulated pore volume divided by the
316 // geometric volume of the element. Note that it can
317 // be larger than 1.0 if porevolume multipliers are used
318 // to for instance implement larger boundary cells
319 auto porosity = this->lookUpData_.fieldPropDouble(eclState_.fieldProps(), "PORO", elementIdx);
320 return referencePorosity(elementIdx, timeIdx) / porosity * (1 - porosity);
321}
322
323template<class GridView, class FluidSystem>
324template<class T>
326updateNum(const std::string& name, std::vector<T>& numbers, std::size_t num_regions)
327{
328 if (!eclState_.fieldProps().has_int(name))
329 return;
330
331 std::function<void(T, int)> valueCheck = [num_regions,name](T fieldPropValue, [[maybe_unused]] int fieldPropIdx) {
332 if ( fieldPropValue > (int)num_regions) {
333 throw std::runtime_error("Values larger than maximum number of regions "
334 + std::to_string(num_regions) + " provided in " + name);
335 }
336 if ( fieldPropValue <= 0) {
337 throw std::runtime_error("zero or negative values provided for region array: " + name);
338 }
339 };
340
341 numbers = this->lookUpData_.template assignFieldPropsIntOnLeaf<T>(eclState_.fieldProps(), name,
342 true /*needsTranslation*/, valueCheck);
343}
344
345template<class GridView, class FluidSystem>
346void FlowGenericProblem<GridView,FluidSystem>::
347updatePvtnum_()
348{
349 const auto num_regions = eclState_.getTableManager().getTabdims().getNumPVTTables();
350 updateNum("PVTNUM", pvtnum_, num_regions);
351}
352
353template<class GridView, class FluidSystem>
354void FlowGenericProblem<GridView,FluidSystem>::
355updateSatnum_()
356{
357 const auto num_regions = eclState_.getTableManager().getTabdims().getNumSatTables();
358 updateNum("SATNUM", satnum_, num_regions);
359}
360
361template<class GridView, class FluidSystem>
362void FlowGenericProblem<GridView,FluidSystem>::
363updateMiscnum_()
364{
365 const auto num_regions = 1; // we only support single region
366 updateNum("MISCNUM", miscnum_, num_regions);
367}
368
369template<class GridView, class FluidSystem>
370void FlowGenericProblem<GridView,FluidSystem>::
371updatePlmixnum_()
372{
373 const auto num_regions = 1; // we only support single region
374 updateNum("PLMIXNUM", plmixnum_, num_regions);
375}
376
377template<class GridView, class FluidSystem>
378bool FlowGenericProblem<GridView,FluidSystem>::
379vapparsActive(int episodeIdx) const
380{
381 const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
382 return (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::VAPPARS);
383}
384
385template<class GridView, class FluidSystem>
386bool FlowGenericProblem<GridView,FluidSystem>::
387beginEpisode_(bool enableExperiments,
388 int episodeIdx)
389{
390 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
391 // print some useful information in experimental mode. (the production
392 // simulator does this externally.)
393 std::ostringstream ss;
394 boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
395 boost::posix_time::ptime curDateTime =
396 boost::posix_time::from_time_t(schedule_.simTime(episodeIdx));
397 ss.imbue(std::locale(std::locale::classic(), facet));
398 ss << "Report step " << episodeIdx + 1
399 << "/" << schedule_.size() - 1
400 << " at day " << schedule_.seconds(episodeIdx)/(24*3600)
401 << "/" << schedule_.seconds(schedule_.size() - 1)/(24*3600)
402 << ", date = " << curDateTime.date()
403 << "\n ";
404 OpmLog::info(ss.str());
405 }
406
407 const auto& events = schedule_[episodeIdx].events();
408
409 // react to TUNING changes
410 if (episodeIdx > 0 && enableTuning_ && events.hasEvent(ScheduleEvents::TUNING_CHANGE))
411 {
412 const auto& sched_state = schedule_[episodeIdx];
413 const auto& tuning = sched_state.tuning();
414 initialTimeStepSize_ = sched_state.max_next_tstep(enableTuning_);
415 maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
416 return true;
417 }
418
419 return false;
420}
421
422template<class GridView, class FluidSystem>
423void FlowGenericProblem<GridView,FluidSystem>::
424beginTimeStep_(bool enableExperiments,
425 int episodeIdx,
426 int timeStepIndex,
427 Scalar startTime,
428 Scalar time,
429 Scalar timeStepSize,
430 Scalar endTime)
431{
432 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
433 std::ostringstream ss;
434 boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
435 boost::posix_time::ptime date = boost::posix_time::from_time_t(startTime) + boost::posix_time::milliseconds(static_cast<long long>(time / prefix::milli));
436 ss.imbue(std::locale(std::locale::classic(), facet));
437 ss <<"\nTime step " << timeStepIndex << ", stepsize "
438 << unit::convert::to(timeStepSize, unit::day) << " days,"
439 << " at day " << (double)unit::convert::to(time, unit::day)
440 << "/" << (double)unit::convert::to(endTime, unit::day)
441 << ", date = " << date;
442 OpmLog::info(ss.str());
443 }
444}
445
446template<class GridView, class FluidSystem>
447void FlowGenericProblem<GridView,FluidSystem>::
448initFluidSystem_()
449{
450 FluidSystem::initFromState(eclState_, schedule_);
451}
452
453template<class GridView, class FluidSystem>
454void FlowGenericProblem<GridView,FluidSystem>::
455readBlackoilExtentionsInitialConditions_(std::size_t numDof,
456 bool enableSolvent,
457 bool enablePolymer,
458 bool enablePolymerMolarWeight,
459 bool enableMICP)
460{
461 auto getArray = [](const std::vector<double>& input)
462 {
463 if constexpr (std::is_same_v<Scalar,double>) {
464 return input;
465 } else {
466 return std::vector<Scalar>{input.begin(), input.end()};
467 }
468 };
469
470 if (enableSolvent) {
471 if (eclState_.fieldProps().has_double("SSOL")) {
472 solventSaturation_ = getArray(eclState_.fieldProps().get_double("SSOL"));
473 } else {
474 solventSaturation_.resize(numDof, 0.0);
475 }
476
477 solventRsw_.resize(numDof, 0.0);
478 }
479
480 if (enablePolymer) {
481 if (eclState_.fieldProps().has_double("SPOLY")) {
482 polymer_.concentration = getArray(eclState_.fieldProps().get_double("SPOLY"));
483 } else {
484 polymer_.concentration.resize(numDof, 0.0);
485 }
486 }
487
488 if (enablePolymerMolarWeight) {
489 if (eclState_.fieldProps().has_double("SPOLYMW")) {
490 polymer_.moleWeight = getArray(eclState_.fieldProps().get_double("SPOLYMW"));
491 } else {
492 polymer_.moleWeight.resize(numDof, 0.0);
493 }
494 }
495
496 if (enableMICP) {
497 if (eclState_.fieldProps().has_double("SMICR")) {
498 micp_.microbialConcentration = getArray(eclState_.fieldProps().get_double("SMICR"));
499 } else {
500 micp_.microbialConcentration.resize(numDof, 0.0);
501 }
502 if (eclState_.fieldProps().has_double("SOXYG")) {
503 micp_.oxygenConcentration = getArray(eclState_.fieldProps().get_double("SOXYG"));
504 } else {
505 micp_.oxygenConcentration.resize(numDof, 0.0);
506 }
507 if (eclState_.fieldProps().has_double("SUREA")) {
508 micp_.ureaConcentration = getArray(eclState_.fieldProps().get_double("SUREA"));
509 } else {
510 micp_.ureaConcentration.resize(numDof, 0.0);
511 }
512 if (eclState_.fieldProps().has_double("SBIOF")) {
513 micp_.biofilmConcentration = getArray(eclState_.fieldProps().get_double("SBIOF"));
514 } else {
515 micp_.biofilmConcentration.resize(numDof, 0.0);
516 }
517 if (eclState_.fieldProps().has_double("SCALC")) {
518 micp_.calciteConcentration = getArray(eclState_.fieldProps().get_double("SCALC"));
519 } else {
520 micp_.calciteConcentration.resize(numDof, 0.0);
521 }
522 }
523}
524
525template<class GridView, class FluidSystem>
526typename FlowGenericProblem<GridView,FluidSystem>::Scalar
528maxWaterSaturation(unsigned globalDofIdx) const
529{
530 if (maxWaterSaturation_.empty())
531 return 0.0;
532
533 return maxWaterSaturation_[globalDofIdx];
534}
535
536template<class GridView, class FluidSystem>
537typename FlowGenericProblem<GridView,FluidSystem>::Scalar
539minOilPressure(unsigned globalDofIdx) const
540{
541 if (minRefPressure_.empty())
542 return 0.0;
543
544 return minRefPressure_[globalDofIdx];
545}
546
547template<class GridView, class FluidSystem>
548typename FlowGenericProblem<GridView,FluidSystem>::Scalar
550overburdenPressure(unsigned elementIdx) const
551{
552 if (overburdenPressure_.empty())
553 return 0.0;
554
555 return overburdenPressure_[elementIdx];
556}
557
558template<class GridView, class FluidSystem>
559typename FlowGenericProblem<GridView,FluidSystem>::Scalar
561solventSaturation(unsigned elemIdx) const
562{
563 if (solventSaturation_.empty())
564 return 0;
565
566 return solventSaturation_[elemIdx];
567}
568
569template<class GridView, class FluidSystem>
570typename FlowGenericProblem<GridView,FluidSystem>::Scalar
572solventRsw(unsigned elemIdx) const
573{
574 if (solventRsw_.empty())
575 return 0;
576
577 return solventRsw_[elemIdx];
578}
579
580
581
582template<class GridView, class FluidSystem>
583typename FlowGenericProblem<GridView,FluidSystem>::Scalar
585polymerConcentration(unsigned elemIdx) const
586{
587 if (polymer_.concentration.empty()) {
588 return 0;
589 }
590
591 return polymer_.concentration[elemIdx];
592}
593
594template<class GridView, class FluidSystem>
595typename FlowGenericProblem<GridView,FluidSystem>::Scalar
597polymerMolecularWeight(const unsigned elemIdx) const
598{
599 if (polymer_.moleWeight.empty()) {
600 return 0.0;
601 }
602
603 return polymer_.moleWeight[elemIdx];
604}
605
606template<class GridView, class FluidSystem>
607typename FlowGenericProblem<GridView,FluidSystem>::Scalar
609microbialConcentration(unsigned elemIdx) const
610{
611 if (micp_.microbialConcentration.empty()) {
612 return 0;
613 }
614
615 return micp_.microbialConcentration[elemIdx];
616}
617
618template<class GridView, class FluidSystem>
619typename FlowGenericProblem<GridView,FluidSystem>::Scalar
621oxygenConcentration(unsigned elemIdx) const
622{
623 if (micp_.oxygenConcentration.empty()) {
624 return 0;
625 }
626
627 return micp_.oxygenConcentration[elemIdx];
628}
629
630template<class GridView, class FluidSystem>
631typename FlowGenericProblem<GridView,FluidSystem>::Scalar
633ureaConcentration(unsigned elemIdx) const
634{
635 if (micp_.ureaConcentration.empty()) {
636 return 0;
637 }
638
639 return micp_.ureaConcentration[elemIdx];
640}
641
642template<class GridView, class FluidSystem>
643typename FlowGenericProblem<GridView,FluidSystem>::Scalar
645biofilmConcentration(unsigned elemIdx) const
646{
647 if (micp_.biofilmConcentration.empty()) {
648 return 0;
649 }
650
651 return micp_.biofilmConcentration[elemIdx];
652}
653
654template<class GridView, class FluidSystem>
655typename FlowGenericProblem<GridView,FluidSystem>::Scalar
657calciteConcentration(unsigned elemIdx) const
658{
659 if (micp_.calciteConcentration.empty()) {
660 return 0;
661 }
662
663 return micp_.calciteConcentration[elemIdx];
664}
665
666template<class GridView, class FluidSystem>
668pvtRegionIndex(unsigned elemIdx) const
669{
670 if (pvtnum_.empty())
671 return 0;
672
673 return pvtnum_[elemIdx];
674}
675
676template<class GridView, class FluidSystem>
678satnumRegionIndex(unsigned elemIdx) const
679{
680 if (satnum_.empty())
681 return 0;
682
683 return satnum_[elemIdx];
684}
685
686template<class GridView, class FluidSystem>
688miscnumRegionIndex(unsigned elemIdx) const
689{
690 if (miscnum_.empty())
691 return 0;
692
693 return miscnum_[elemIdx];
694}
695
696template<class GridView, class FluidSystem>
698plmixnumRegionIndex(unsigned elemIdx) const
699{
700 if (plmixnum_.empty())
701 return 0;
702
703 return plmixnum_[elemIdx];
704}
705
706template<class GridView, class FluidSystem>
707typename FlowGenericProblem<GridView,FluidSystem>::Scalar
709maxPolymerAdsorption(unsigned elemIdx) const
710{
711 if (polymer_.maxAdsorption.empty()) {
712 return 0;
713 }
714
715 return polymer_.maxAdsorption[elemIdx];
716}
717
718template<class GridView, class FluidSystem>
720operator==(const FlowGenericProblem& rhs) const
721{
722 return this->maxWaterSaturation_ == rhs.maxWaterSaturation_ &&
723 this->minRefPressure_ == rhs.minRefPressure_ &&
724 this->overburdenPressure_ == rhs.overburdenPressure_ &&
725 this->solventSaturation_ == rhs.solventSaturation_ &&
726 this->solventRsw_ == rhs.solventRsw_ &&
727 this->polymer_ == rhs.polymer_ &&
728 this->micp_ == rhs.micp_;
729}
730
731} // namespace Opm
732
733#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...
Definition FlowGenericProblem.hpp:63
Scalar oxygenConcentration(unsigned elemIdx) const
Returns the initial oxygen concentration for a given a cell index.
Definition FlowGenericProblem_impl.hpp:621
Scalar microbialConcentration(unsigned elemIdx) const
Returns the initial microbial concentration for a given a cell index.
Definition FlowGenericProblem_impl.hpp:609
Scalar biofilmConcentration(unsigned elemIdx) const
Returns the initial biofilm concentration for a given a cell index.
Definition FlowGenericProblem_impl.hpp:645
Scalar calciteConcentration(unsigned elemIdx) const
Returns the initial calcite concentration for a given a cell index.
Definition FlowGenericProblem_impl.hpp:657
Scalar ureaConcentration(unsigned elemIdx) const
Returns the initial urea concentration for a given a cell index.
Definition FlowGenericProblem_impl.hpp:633
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilboundaryratevector.hh:37
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:242