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
108 return result;
109}
110
111template<class GridView, class FluidSystem>
112std::string
113FlowGenericProblem<GridView,FluidSystem>::
114helpPreamble(int,
115 const char **argv)
116{
117 std::string desc = FlowGenericProblem::briefDescription();
118 if (!desc.empty())
119 desc = desc + "\n";
120
121 return
122 "Usage: "+std::string(argv[0]) + " [OPTIONS] [ECL_DECK_FILENAME]\n"
123 + desc;
124}
125
126template<class GridView, class FluidSystem>
127std::string
128FlowGenericProblem<GridView,FluidSystem>::
129briefDescription()
130{
131 return briefDescription_;
132}
133
134template<class GridView, class FluidSystem>
136readRockParameters_(const std::vector<Scalar>& cellCenterDepths,
137 std::function<std::array<int,3>(const unsigned)> ijkIndex)
138{
139 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
140
141 // read the rock compressibility parameters
142 {
143 const auto& comp = rock_config.comp();
144 rockParams_.clear();
145 std::transform(comp.begin(), comp.end(), std::back_inserter(rockParams_),
146 [](const auto& c)
147 {
148 return RockParams{static_cast<Scalar>(c.pref),
149 static_cast<Scalar>(c.compressibility)};
150 });
151 }
152
153 // Warn that ROCK and ROCKOPTS item 2 = STORE is used together
154 if (rock_config.store()) {
155 OpmLog::warning("ROCKOPTS item 2 set to STORE, ROCK item 1 replaced with initial (equilibrated) pressures");
156 }
157
158 // read the parameters for water-induced rock compaction
159 readRockCompactionParameters_();
160
161 unsigned numElem = gridView_.size(0);
162 if (eclState_.fieldProps().has_int(rock_config.rocknum_property())) {
163 // Auxiliary function to check rockTableIdx_ values belong to the right range. Otherwise, throws.
164 std::function<void(int, int)> valueCheck = [&ijkIndex,&rock_config,this](int fieldPropValue, int coarseElemIdx)
165 {
166 auto fmtError = [fieldPropValue, coarseElemIdx,&ijkIndex,&rock_config](const char* type, std::size_t size)
167 {
168 return fmt::format("{} table index {} for elem {} read from {}"
169 " is out of bounds for number of tables {}",
170 type, fieldPropValue,
171 ijkIndex(coarseElemIdx),
172 rock_config.rocknum_property(), size);
173 };
174 if (!rockCompPoroMult_.empty() &&
175 fieldPropValue > static_cast<int>(rockCompPoroMult_.size())) {
176 throw std::runtime_error(fmtError("Rock compaction",
177 rockCompPoroMult_.size()));
178 }
179 if (!rockCompPoroMultWc_.empty() &&
180 fieldPropValue > static_cast<int>(rockCompPoroMultWc_.size())) {
181 throw std::runtime_error(fmtError("Rock water compaction",
182 rockCompPoroMultWc_.size()));
183 }
184 };
185
186 rockTableIdx_ = this->lookUpData_.template assignFieldPropsIntOnLeaf<short unsigned int>(eclState_.fieldProps(),
187 rock_config.rocknum_property(),
188 true /*needsTranslation*/,
189 valueCheck);
190 }
191
192 // Store overburden pressure pr element
193 const auto& overburdTables = eclState_.getTableManager().getOverburdTables();
194 if (!overburdTables.empty() && !rock_config.store()) {
195 overburdenPressure_.resize(numElem,0.0);
196 std::size_t numRocktabTables = rock_config.num_rock_tables();
197
198 if (overburdTables.size() != numRocktabTables)
199 throw std::runtime_error(std::to_string(numRocktabTables) +" OVERBURD tables is expected, but " + std::to_string(overburdTables.size()) +" is provided");
200
201 std::vector<Tabulated1DFunction<Scalar>> overburdenTables(numRocktabTables);
202 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
203 const OverburdTable& overburdTable = overburdTables.template getTable<OverburdTable>(regionIdx);
204 overburdenTables[regionIdx].setXYContainers(overburdTable.getDepthColumn(),overburdTable.getOverburdenPressureColumn());
205 }
206
207 for (std::size_t elemIdx = 0; elemIdx < numElem; ++ elemIdx) {
208 unsigned tableIdx = 0;
209 if (!rockTableIdx_.empty()) {
210 tableIdx = rockTableIdx_[elemIdx];
211 }
212 overburdenPressure_[elemIdx] =
213 overburdenTables[tableIdx].eval(cellCenterDepths[elemIdx], /*extrapolation=*/true);
214 }
215 }
216 else if (!overburdTables.empty() && rock_config.store()) {
217 OpmLog::warning("ROCKOPTS item 2 set to STORE, OVERBURD ignored!");
218 }
219}
220
221template<class GridView, class FluidSystem>
222void FlowGenericProblem<GridView,FluidSystem>::
223readRockCompactionParameters_()
224{
225 const auto& rock_config = eclState_.getSimulationConfig().rock_config();
226
227 if (!rock_config.active())
228 return; // deck does not enable rock compaction
229
230 unsigned numElem = gridView_.size(0);
231 switch (rock_config.hysteresis_mode()) {
232 case RockConfig::Hysteresis::REVERS:
233 break;
234 case RockConfig::Hysteresis::IRREVERS:
235 // interpolate the porv volume multiplier using the minimum pressure in the cell
236 // i.e. don't allow re-inflation.
237 minRefPressure_.resize(numElem, 1e99);
238 break;
239 default:
240 throw std::runtime_error("Not support ROCKOMP hysteresis option ");
241 }
242
243 std::size_t numRocktabTables = rock_config.num_rock_tables();
244 bool waterCompaction = rock_config.water_compaction();
245
246 if (!waterCompaction) {
247 const auto& rocktabTables = eclState_.getTableManager().getRocktabTables();
248 if (rocktabTables.size() != numRocktabTables)
249 throw std::runtime_error("ROCKCOMP is activated." + std::to_string(numRocktabTables)
250 +" ROCKTAB tables is expected, but " + std::to_string(rocktabTables.size()) +" is provided");
251
252 rockCompPoroMult_.resize(numRocktabTables);
253 rockCompTransMult_.resize(numRocktabTables);
254 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
255 const auto& rocktabTable = rocktabTables.template getTable<RocktabTable>(regionIdx);
256 const auto& pressureColumn = rocktabTable.getPressureColumn();
257 const auto& poroColumn = rocktabTable.getPoreVolumeMultiplierColumn();
258 const auto& transColumn = rocktabTable.getTransmissibilityMultiplierColumn();
259 rockCompPoroMult_[regionIdx].setXYContainers(pressureColumn, poroColumn);
260 rockCompTransMult_[regionIdx].setXYContainers(pressureColumn, transColumn);
261 }
262 } else {
263 const auto& rock2dTables = eclState_.getTableManager().getRock2dTables();
264 const auto& rock2dtrTables = eclState_.getTableManager().getRock2dtrTables();
265 const auto& rockwnodTables = eclState_.getTableManager().getRockwnodTables();
266 maxWaterSaturation_.resize(numElem, 0.0);
267
268 if (rock2dTables.size() != numRocktabTables)
269 throw std::runtime_error("Water compation option is selected in ROCKCOMP." + std::to_string(numRocktabTables)
270 +" ROCK2D tables is expected, but " + std::to_string(rock2dTables.size()) +" is provided");
271
272 if (rockwnodTables.size() != numRocktabTables)
273 throw std::runtime_error("Water compation option is selected in ROCKCOMP." + std::to_string(numRocktabTables)
274 +" ROCKWNOD tables is expected, but " + std::to_string(rockwnodTables.size()) +" is provided");
275 //TODO check size match
276 rockCompPoroMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
277 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
278 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
279 const auto& rock2dTable = rock2dTables[regionIdx];
280
281 if (rockwnodTable.getSaturationColumn().size() != rock2dTable.sizeMultValues())
282 throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2D needs to match.");
283
284 for (std::size_t xIdx = 0; xIdx < rock2dTable.size(); ++xIdx) {
285 rockCompPoroMultWc_[regionIdx].appendXPos(rock2dTable.getPressureValue(xIdx));
286 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
287 rockCompPoroMultWc_[regionIdx].appendSamplePoint(xIdx,
288 rockwnodTable.getSaturationColumn()[yIdx],
289 rock2dTable.getPvmultValue(xIdx, yIdx));
290 }
291 }
292
293 if (!rock2dtrTables.empty()) {
294 rockCompTransMultWc_.resize(numRocktabTables, TabulatedTwoDFunction(TabulatedTwoDFunction::InterpolationPolicy::Vertical));
295 for (std::size_t regionIdx = 0; regionIdx < numRocktabTables; ++regionIdx) {
296 const RockwnodTable& rockwnodTable = rockwnodTables.template getTable<RockwnodTable>(regionIdx);
297 const auto& rock2dtrTable = rock2dtrTables[regionIdx];
298
299 if (rockwnodTable.getSaturationColumn().size() != rock2dtrTable.sizeMultValues())
300 throw std::runtime_error("Number of entries in ROCKWNOD and ROCK2DTR needs to match.");
301
302 for (std::size_t xIdx = 0; xIdx < rock2dtrTable.size(); ++xIdx) {
303 rockCompTransMultWc_[regionIdx].appendXPos(rock2dtrTable.getPressureValue(xIdx));
304 for (std::size_t yIdx = 0; yIdx < rockwnodTable.getSaturationColumn().size(); ++yIdx)
305 rockCompTransMultWc_[regionIdx].appendSamplePoint(xIdx,
306 rockwnodTable.getSaturationColumn()[yIdx],
307 rock2dtrTable.getTransMultValue(xIdx, yIdx));
308 }
309 }
310 }
311 }
312}
313
314template<class GridView, class FluidSystem>
315typename FlowGenericProblem<GridView,FluidSystem>::Scalar
316FlowGenericProblem<GridView,FluidSystem>::
317rockCompressibility(unsigned globalSpaceIdx) const
318{
319 if (this->rockParams_.empty())
320 return 0.0;
321
322 unsigned tableIdx = 0;
323 if (!this->rockTableIdx_.empty()) {
324 tableIdx = this->rockTableIdx_[globalSpaceIdx];
325 }
326 return this->rockParams_[tableIdx].compressibility;
327}
328
329template<class GridView, class FluidSystem>
330typename FlowGenericProblem<GridView,FluidSystem>::Scalar
331FlowGenericProblem<GridView,FluidSystem>::
332porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
333{
334 return this->referencePorosity_[timeIdx][globalSpaceIdx];
335}
336
337template<class GridView, class FluidSystem>
338typename FlowGenericProblem<GridView,FluidSystem>::Scalar
339FlowGenericProblem<GridView,FluidSystem>::
340rockFraction(unsigned elementIdx, unsigned timeIdx) const
341{
342 // For the energy equation, we need the volume of the rock.
343 // The volume of the rock is computed by rockFraction * geometric volume of the element.
344 // The reference porosity is defined as porosity * ntg * pore-volume-multiplier.
345 // A common practice in reservoir simulation is to use large pore-volume-multipliers in boundary cells
346 // to model boundary conditions other than no-flow. This may result in reference porosities that are larger than 1.
347 // A simple (1-reference porosity) * geometric volume of the element may give unphysical results.
348 // We therefore instead consider the pore-volume-multiplier as a volume multiplier. The rock fraction is thus given by
349 // (1 - porosity * ntg) * pore-volume-multiplier = (1 - porosity * ntg) * reference porosity / (porosity * ntg)
350 const auto ntg = this->lookUpData_.fieldPropDouble(eclState_.fieldProps(), "NTG", elementIdx);
351 const auto poro_eff = ntg * this->lookUpData_.fieldPropDouble(eclState_.fieldProps(), "PORO", elementIdx);
352 return (1 - poro_eff) * referencePorosity(elementIdx, timeIdx) / poro_eff;
353}
354
355template<class GridView, class FluidSystem>
356template<class T>
358updateNum(const std::string& name, std::vector<T>& numbers, std::size_t num_regions)
359{
360 if (!eclState_.fieldProps().has_int(name))
361 return;
362
363 std::function<void(T, int)> valueCheck = [num_regions,name](T fieldPropValue, [[maybe_unused]] int fieldPropIdx) {
364 if ( fieldPropValue > (int)num_regions) {
365 throw std::runtime_error("Values larger than maximum number of regions "
366 + std::to_string(num_regions) + " provided in " + name);
367 }
368 if ( fieldPropValue <= 0) {
369 throw std::runtime_error("zero or negative values provided for region array: " + name);
370 }
371 };
372
373 numbers = this->lookUpData_.template assignFieldPropsIntOnLeaf<T>(eclState_.fieldProps(), name,
374 true /*needsTranslation*/, valueCheck);
375}
376
377template<class GridView, class FluidSystem>
378void FlowGenericProblem<GridView,FluidSystem>::
379updatePvtnum_()
380{
381 const auto num_regions = eclState_.getTableManager().getTabdims().getNumPVTTables();
382 updateNum("PVTNUM", pvtnum_, num_regions);
383}
384
385template<class GridView, class FluidSystem>
386void FlowGenericProblem<GridView,FluidSystem>::
387updateSatnum_()
388{
389 const auto num_regions = eclState_.getTableManager().getTabdims().getNumSatTables();
390 updateNum("SATNUM", satnum_, num_regions);
391}
392
393template<class GridView, class FluidSystem>
394void FlowGenericProblem<GridView,FluidSystem>::
395updateMiscnum_()
396{
397 const auto num_regions = 1; // we only support single region
398 updateNum("MISCNUM", miscnum_, num_regions);
399}
400
401template<class GridView, class FluidSystem>
402void FlowGenericProblem<GridView,FluidSystem>::
403updatePlmixnum_()
404{
405 const auto num_regions = 1; // we only support single region
406 updateNum("PLMIXNUM", plmixnum_, num_regions);
407}
408
409template<class GridView, class FluidSystem>
410bool FlowGenericProblem<GridView,FluidSystem>::
411vapparsActive(int episodeIdx) const
412{
413 const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
414 return (oilVaporizationControl.getType() == OilVaporizationProperties::OilVaporization::VAPPARS);
415}
416
417template<class GridView, class FluidSystem>
418bool FlowGenericProblem<GridView,FluidSystem>::
419beginEpisode_(bool enableExperiments,
420 int episodeIdx)
421{
422 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
423 // print some useful information in experimental mode. (the production
424 // simulator does this externally.)
425 std::ostringstream ss;
426 boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
427 boost::posix_time::ptime curDateTime =
428 boost::posix_time::from_time_t(schedule_.simTime(episodeIdx));
429 ss.imbue(std::locale(std::locale::classic(), facet));
430 ss << "Report step " << episodeIdx + 1
431 << "/" << schedule_.size() - 1
432 << " at day " << schedule_.seconds(episodeIdx)/(24*3600)
433 << "/" << schedule_.seconds(schedule_.size() - 1)/(24*3600)
434 << ", date = " << curDateTime.date()
435 << "\n ";
436 OpmLog::info(ss.str());
437 }
438
439 const auto& events = schedule_[episodeIdx].events();
440
441 // react to TUNING changes
442 if (episodeIdx > 0 && enableTuning_ && events.hasEvent(ScheduleEvents::TUNING_CHANGE))
443 {
444 const auto& sched_state = schedule_[episodeIdx];
445 const auto& tuning = sched_state.tuning();
446 initialTimeStepSize_ = sched_state.max_next_tstep(enableTuning_);
447 maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
448 return true;
449 }
450
451 return false;
452}
453
454template<class GridView, class FluidSystem>
455void FlowGenericProblem<GridView,FluidSystem>::
456beginTimeStep_(bool enableExperiments,
457 int episodeIdx,
458 int timeStepIndex,
459 Scalar startTime,
460 Scalar time,
461 Scalar timeStepSize,
462 Scalar endTime)
463{
464 if (enableExperiments && gridView_.comm().rank() == 0 && episodeIdx >= 0) {
465 std::ostringstream ss;
466 boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d-%b-%Y");
467 boost::posix_time::ptime date = boost::posix_time::from_time_t(startTime) + boost::posix_time::milliseconds(static_cast<long long>(time / prefix::milli));
468 ss.imbue(std::locale(std::locale::classic(), facet));
469 ss <<"\nTime step " << timeStepIndex << ", stepsize "
470 << unit::convert::to(timeStepSize, unit::day) << " days,"
471 << " at day " << (double)unit::convert::to(time, unit::day)
472 << "/" << (double)unit::convert::to(endTime, unit::day)
473 << ", date = " << date;
474 OpmLog::info(ss.str());
475 }
476}
477
478template<class GridView, class FluidSystem>
479void FlowGenericProblem<GridView,FluidSystem>::
480initFluidSystem_()
481{
482 FluidSystem::initFromState(eclState_, schedule_);
483}
484
485template<class GridView, class FluidSystem>
486void FlowGenericProblem<GridView,FluidSystem>::
487readBlackoilExtentionsInitialConditions_(std::size_t numDof,
488 bool enableSolvent,
489 bool enablePolymer,
490 bool enablePolymerMolarWeight,
491 bool enableBioeffects,
492 bool enableMICP)
493{
494 auto getArray = [](const std::vector<double>& input)
495 {
496 if constexpr (std::is_same_v<Scalar,double>) {
497 return input;
498 } else {
499 return std::vector<Scalar>{input.begin(), input.end()};
500 }
501 };
502
503 if (enableSolvent) {
504 if (eclState_.fieldProps().has_double("SSOL")) {
505 solventSaturation_ = getArray(eclState_.fieldProps().get_double("SSOL"));
506 } else {
507 solventSaturation_.resize(numDof, 0.0);
508 }
509
510 solventRsw_.resize(numDof, 0.0);
511 }
512
513 if (enablePolymer) {
514 if (eclState_.fieldProps().has_double("SPOLY")) {
515 polymer_.concentration = getArray(eclState_.fieldProps().get_double("SPOLY"));
516 } else {
517 polymer_.concentration.resize(numDof, 0.0);
518 }
519 }
520
521 if (enablePolymerMolarWeight) {
522 if (eclState_.fieldProps().has_double("SPOLYMW")) {
523 polymer_.moleWeight = getArray(eclState_.fieldProps().get_double("SPOLYMW"));
524 } else {
525 polymer_.moleWeight.resize(numDof, 0.0);
526 }
527 }
528
529 if (enableBioeffects) {
530 if (eclState_.fieldProps().has_double("SMICR")) {
531 bioeffects_.microbialConcentration = getArray(eclState_.fieldProps().get_double("SMICR"));
532 } else {
533 bioeffects_.microbialConcentration.resize(numDof, 0.0);
534 }
535 if (eclState_.fieldProps().has_double("SBIOF")) {
536 bioeffects_.biofilmVolumeFraction = getArray(eclState_.fieldProps().get_double("SBIOF"));
537 } else {
538 bioeffects_.biofilmVolumeFraction.resize(numDof, 0.0);
539 }
540 if (enableMICP) {
541 if (eclState_.fieldProps().has_double("SOXYG")) {
542 bioeffects_.oxygenConcentration = getArray(eclState_.fieldProps().get_double("SOXYG"));
543 } else {
544 bioeffects_.oxygenConcentration.resize(numDof, 0.0);
545 }
546 if (eclState_.fieldProps().has_double("SUREA")) {
547 bioeffects_.ureaConcentration = getArray(eclState_.fieldProps().get_double("SUREA"));
548 } else {
549 bioeffects_.ureaConcentration.resize(numDof, 0.0);
550 }
551 if (eclState_.fieldProps().has_double("SCALC")) {
552 bioeffects_.calciteVolumeFraction = getArray(eclState_.fieldProps().get_double("SCALC"));
553 } else {
554 bioeffects_.calciteVolumeFraction.resize(numDof, 0.0);
555 }
556 }
557 }
558}
559
560template<class GridView, class FluidSystem>
561typename FlowGenericProblem<GridView,FluidSystem>::Scalar
562FlowGenericProblem<GridView,FluidSystem>::
563maxWaterSaturation(unsigned globalDofIdx) const
564{
565 if (maxWaterSaturation_.empty())
566 return 0.0;
567
568 return maxWaterSaturation_[globalDofIdx];
569}
570
571template<class GridView, class FluidSystem>
572typename FlowGenericProblem<GridView,FluidSystem>::Scalar
573FlowGenericProblem<GridView,FluidSystem>::
574minOilPressure(unsigned globalDofIdx) const
575{
576 if (minRefPressure_.empty())
577 return 0.0;
578
579 return minRefPressure_[globalDofIdx];
580}
581
582template<class GridView, class FluidSystem>
583typename FlowGenericProblem<GridView,FluidSystem>::Scalar
584FlowGenericProblem<GridView,FluidSystem>::
585overburdenPressure(unsigned elementIdx) const
586{
587 if (overburdenPressure_.empty())
588 return 0.0;
589
590 return overburdenPressure_[elementIdx];
591}
592
593template<class GridView, class FluidSystem>
594typename FlowGenericProblem<GridView,FluidSystem>::Scalar
595FlowGenericProblem<GridView,FluidSystem>::
596solventSaturation(unsigned elemIdx) const
597{
598 if (solventSaturation_.empty())
599 return 0;
600
601 return solventSaturation_[elemIdx];
602}
603
604template<class GridView, class FluidSystem>
605typename FlowGenericProblem<GridView,FluidSystem>::Scalar
606FlowGenericProblem<GridView,FluidSystem>::
607solventRsw(unsigned elemIdx) const
608{
609 if (solventRsw_.empty())
610 return 0;
611
612 return solventRsw_[elemIdx];
613}
614
615
616
617template<class GridView, class FluidSystem>
618typename FlowGenericProblem<GridView,FluidSystem>::Scalar
619FlowGenericProblem<GridView,FluidSystem>::
620polymerConcentration(unsigned elemIdx) const
621{
622 if (polymer_.concentration.empty()) {
623 return 0;
624 }
625
626 return polymer_.concentration[elemIdx];
627}
628
629template<class GridView, class FluidSystem>
630typename FlowGenericProblem<GridView,FluidSystem>::Scalar
631FlowGenericProblem<GridView,FluidSystem>::
632polymerMolecularWeight(const unsigned elemIdx) const
633{
634 if (polymer_.moleWeight.empty()) {
635 return 0.0;
636 }
637
638 return polymer_.moleWeight[elemIdx];
639}
640
641template<class GridView, class FluidSystem>
642typename FlowGenericProblem<GridView,FluidSystem>::Scalar
643FlowGenericProblem<GridView,FluidSystem>::
644microbialConcentration(unsigned elemIdx) const
645{
646 if (bioeffects_.microbialConcentration.empty()) {
647 return 0;
648 }
649
650 return bioeffects_.microbialConcentration[elemIdx];
651}
652
653template<class GridView, class FluidSystem>
654typename FlowGenericProblem<GridView,FluidSystem>::Scalar
655FlowGenericProblem<GridView,FluidSystem>::
656oxygenConcentration(unsigned elemIdx) const
657{
658 if (bioeffects_.oxygenConcentration.empty()) {
659 return 0;
660 }
661
662 return bioeffects_.oxygenConcentration[elemIdx];
663}
664
665template<class GridView, class FluidSystem>
666typename FlowGenericProblem<GridView,FluidSystem>::Scalar
667FlowGenericProblem<GridView,FluidSystem>::
668ureaConcentration(unsigned elemIdx) const
669{
670 if (bioeffects_.ureaConcentration.empty()) {
671 return 0;
672 }
673
674 return bioeffects_.ureaConcentration[elemIdx];
675}
676
677template<class GridView, class FluidSystem>
678typename FlowGenericProblem<GridView,FluidSystem>::Scalar
679FlowGenericProblem<GridView,FluidSystem>::
680biofilmVolumeFraction(unsigned elemIdx) const
681{
682 if (bioeffects_.biofilmVolumeFraction.empty()) {
683 return 0;
684 }
685
686 return bioeffects_.biofilmVolumeFraction[elemIdx];
687}
688
689template<class GridView, class FluidSystem>
690typename FlowGenericProblem<GridView,FluidSystem>::Scalar
691FlowGenericProblem<GridView,FluidSystem>::
692calciteVolumeFraction(unsigned elemIdx) const
693{
694 if (bioeffects_.calciteVolumeFraction.empty()) {
695 return 0;
696 }
697
698 return bioeffects_.calciteVolumeFraction[elemIdx];
699}
700
701template<class GridView, class FluidSystem>
702unsigned FlowGenericProblem<GridView,FluidSystem>::
703pvtRegionIndex(unsigned elemIdx) const
704{
705 if (pvtnum_.empty())
706 return 0;
707
708 return pvtnum_[elemIdx];
709}
710
711template<class GridView, class FluidSystem>
712unsigned FlowGenericProblem<GridView,FluidSystem>::
713satnumRegionIndex(unsigned elemIdx) const
714{
715 if (satnum_.empty())
716 return 0;
717
718 return satnum_[elemIdx];
719}
720
721template<class GridView, class FluidSystem>
722unsigned FlowGenericProblem<GridView,FluidSystem>::
723miscnumRegionIndex(unsigned elemIdx) const
724{
725 if (miscnum_.empty())
726 return 0;
727
728 return miscnum_[elemIdx];
729}
730
731template<class GridView, class FluidSystem>
732unsigned FlowGenericProblem<GridView,FluidSystem>::
733plmixnumRegionIndex(unsigned elemIdx) const
734{
735 if (plmixnum_.empty())
736 return 0;
737
738 return plmixnum_[elemIdx];
739}
740
741template<class GridView, class FluidSystem>
742typename FlowGenericProblem<GridView,FluidSystem>::Scalar
743FlowGenericProblem<GridView,FluidSystem>::
744maxPolymerAdsorption(unsigned elemIdx) const
745{
746 if (polymer_.maxAdsorption.empty()) {
747 return 0;
748 }
749
750 return polymer_.maxAdsorption[elemIdx];
751}
752
753template<class GridView, class FluidSystem>
755operator==(const FlowGenericProblem& rhs) const
756{
757 return this->maxWaterSaturation_ == rhs.maxWaterSaturation_ &&
758 this->minRefPressure_ == rhs.minRefPressure_ &&
759 this->overburdenPressure_ == rhs.overburdenPressure_ &&
760 this->solventSaturation_ == rhs.solventSaturation_ &&
761 this->solventRsw_ == rhs.solventRsw_ &&
762 this->polymer_ == rhs.polymer_ &&
763 this->bioeffects_ == rhs.bioeffects_;
764}
765
766} // namespace Opm
767
768#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:129
Scalar referencePorosity(unsigned elementIdx, unsigned timeIdx) const
Returns the porosity of an element.
Definition FlowGenericProblem.hpp:137
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:43
This file provides the infrastructure to retrieve run-time parameters.