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