FlowProblem.hpp
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*
4 Copyright 2023 INRIA
5
6 This file is part of the Open Porous Media project (OPM).
7
8 OPM is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 2 of the License, or
11 (at your option) any later version.
12
13 OPM is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with OPM. If not, see <http://www.gnu.org/licenses/>.
20
21 Consult the COPYING file in the top-level source directory of this
22 module for the precise wording of the license and the list of
23 copyright holders.
24*/
30#ifndef OPM_FLOW_PROBLEM_HPP
31#define OPM_FLOW_PROBLEM_HPP
32
33#include <dune/common/version.hh>
34#include <dune/common/fvector.hh>
35#include <dune/common/fmatrix.hh>
36
37#include <opm/common/utility/TimeService.hpp>
38
39#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
40#include <opm/input/eclipse/Schedule/Schedule.hpp>
41#include <opm/input/eclipse/Units/Units.hpp>
42
43#include <opm/material/common/ConditionalStorage.hpp>
44#include <opm/material/common/Valgrind.hpp>
45#include <opm/material/densead/Evaluation.hpp>
46#include <opm/material/fluidmatrixinteractions/EclMaterialLawManager.hpp>
47#include <opm/material/thermal/EclThermalLawManager.hpp>
48
54
55#include <opm/output/eclipse/EclipseIO.hpp>
56
62// TODO: maybe we can name it FlowProblemProperties.hpp
73
77
78#include <opm/utility/CopyablePtr.hpp>
79
80#include <algorithm>
81#include <cstddef>
82#include <functional>
83#include <set>
84#include <stdexcept>
85#include <string>
86#include <type_traits>
87#include <vector>
88
89namespace Opm {
90
97template <class TypeTag>
98class FlowProblem : public GetPropType<TypeTag, Properties::BaseProblem>
99 , public FlowGenericProblem<GetPropType<TypeTag, Properties::GridView>,
100 GetPropType<TypeTag, Properties::FluidSystem>>
101{
102protected:
107
116
117 // Grid and world dimension
118 enum { dim = GridView::dimension };
119 enum { dimWorld = GridView::dimensionworld };
120
121 // copy some indices for convenience
122 enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
123 enum { numPhases = FluidSystem::numPhases };
124 enum { numComponents = FluidSystem::numComponents };
125
126 static constexpr bool enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
127 static constexpr bool enableBrine = getPropValue<TypeTag, Properties::EnableBrine>();
128 static constexpr bool enableConvectiveMixing = getPropValue<TypeTag, Properties::EnableConvectiveMixing>();
129 static constexpr bool enableDiffusion = getPropValue<TypeTag, Properties::EnableDiffusion>();
130 static constexpr bool enableDispersion = getPropValue<TypeTag, Properties::EnableDispersion>();
131 static constexpr bool enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>();
132 static constexpr bool enableFoam = getPropValue<TypeTag, Properties::EnableFoam>();
133 static constexpr bool enablePolymer = getPropValue<TypeTag, Properties::EnablePolymer>();
134 static constexpr bool enablePolymerMolarWeight = getPropValue<TypeTag, Properties::EnablePolymerMW>();
135 static constexpr bool enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>();
136
137 static constexpr EnergyModules energyModuleType = getPropValue<TypeTag, Properties::EnergyModuleType>();
138 enum { enableFullyImplicitThermal = getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal };
139 enum { enableExperiments = getPropValue<TypeTag, Properties::EnableExperiments>() };
140 enum { enableMICP = Indices::enableMICP };
141 enum { enableSaltPrecipitation = getPropValue<TypeTag, Properties::EnableSaltPrecipitation>() };
142 enum { enableThermalFluxBoundaries = getPropValue<TypeTag, Properties::EnableThermalFluxBoundaries>() };
143
144 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
145 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
146 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
147
148 // TODO: later, gasCompIdx, oilCompIdx and waterCompIdx should go to the FlowProblemBlackoil in the future
149 // we do not want them in the compositional setting
150 enum { gasCompIdx = FluidSystem::gasCompIdx };
151 enum { oilCompIdx = FluidSystem::oilCompIdx };
152 enum { waterCompIdx = FluidSystem::waterCompIdx };
153
157 using Element = typename GridView::template Codim<0>::Entity;
161 using MaterialLawParams = typename EclMaterialLawManager::MaterialLawParams;
162 using SolidEnergyLawParams = typename EclThermalLawManager::SolidEnergyLawParams;
163 using ThermalConductionLawParams = typename EclThermalLawManager::ThermalConductionLawParams;
170
171 using Toolbox = MathToolbox<Evaluation>;
172 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
173
176 using DirectionalMobilityPtr = Utility::CopyablePtr<DirectionalMobility<TypeTag>>;
178
179public:
180
183 std::string extraTrailerSummary() const
184 { return {}; }
191 using BaseType::lame;
193 using BaseType::biotTemp;
195 using BaseType::porosity;
196
200 static void registerParameters()
201 {
202 ParentType::registerParameters();
203
204 registerFlowProblemParameters<Scalar>();
205 }
206
216 static int handlePositionalParameter(std::function<void(const std::string&,
217 const std::string&)> addKey,
218 std::set<std::string>& seenParams,
219 std::string& errorMsg,
220 int,
221 const char** argv,
222 int paramIdx,
223 int)
224 {
225 return detail::eclPositionalParameter(addKey,
226 seenParams,
227 errorMsg,
228 argv,
229 paramIdx);
230 }
231
235 explicit FlowProblem(Simulator& simulator)
236 : ParentType(simulator)
237 , BaseType(simulator.vanguard().eclState(),
238 simulator.vanguard().schedule(),
239 simulator.vanguard().gridView())
240 , transmissibilities_(simulator.vanguard().eclState(),
241 simulator.vanguard().gridView(),
242 simulator.vanguard().cartesianIndexMapper(),
243 simulator.vanguard().grid(),
244 simulator.vanguard().cellCentroids(),
245 (energyModuleType == EnergyModules::FullyImplicitThermal ||
246 energyModuleType == EnergyModules::SequentialImplicitThermal),
249 , wellModel_(simulator, this->iterationContext())
250 , aquiferModel_(simulator)
251 , pffDofData_(simulator.gridView(), this->elementMapper())
252 , tracerModel_(simulator)
253 , temperatureModel_(simulator)
254 , thresholdPressures_(simulator)
255 , enable_state_rollback_(Parameters::Get<Parameters::EnableStateRollback>())
256 {
257 if (! Parameters::Get<Parameters::CheckSatfuncConsistency>()) {
258 // User did not enable the "new" saturation function consistency
259 // check module. Run the original checker instead. This is a
260 // temporary measure.
261 RelpermDiagnostics relpermDiagnostics{};
262 relpermDiagnostics.diagnosis(simulator.vanguard().eclState(),
263 simulator.vanguard().levelCartesianIndexMapper());
264 }
265
266 if (energyModuleType == EnergyModules::SequentialImplicitThermal) {
267 this->enableDriftCompensationTemp_ = Parameters::Get<Parameters::EnableDriftCompensationTemp>();
268 }
269
270 }
271
272 virtual ~FlowProblem() = default;
273
274 void prefetch(const Element& elem) const
275 { this->pffDofData_.prefetch(elem); }
276
288 template <class Restarter>
289 void deserialize(Restarter& res)
290 {
291 // reload the current episode/report step from the deck
292 this->beginEpisode();
293
294 // deserialize the wells
295 wellModel_.deserialize(res);
296
297 // deserialize the aquifer
298 aquiferModel_.deserialize(res);
299 }
300
307 template <class Restarter>
308 void serialize(Restarter& res)
309 {
310 wellModel_.serialize(res);
311
312 aquiferModel_.serialize(res);
313 }
314
315 int episodeIndex() const
316 {
317 return std::max(this->simulator().episodeIndex(), 0);
318 }
319
323 virtual void beginEpisode()
324 {
325 OPM_TIMEBLOCK(beginEpisode);
326 // Proceed to the next report step
327 auto& simulator = this->simulator();
328 int episodeIdx = simulator.episodeIndex();
329 auto& eclState = simulator.vanguard().eclState();
330 const auto& schedule = simulator.vanguard().schedule();
331 const auto& events = schedule[episodeIdx].events();
332
333 if (episodeIdx >= 0 && events.hasEvent(ScheduleEvents::GEO_MODIFIER)) {
334 // bring the contents of the keywords to the current state of the SCHEDULE
335 // section.
336 //
337 // TODO (?): make grid topology changes possible (depending on what exactly
338 // has changed, the grid may need be re-created which has some serious
339 // implications on e.g., the solution of the simulation.)
340 const auto& miniDeck = schedule[episodeIdx].geo_keywords();
341 const auto& cc = simulator.vanguard().grid().comm();
342 eclState.apply_schedule_keywords( miniDeck );
343 eclBroadcast(cc, eclState.getTransMult() );
344
345 // Re-ordering in case of ALUGrid
346 std::function<unsigned int(unsigned int)> equilGridToGrid = [&simulator](unsigned int i) {
347 return simulator.vanguard().gridEquilIdxToGridIdx(i);
348 };
349
350 // re-compute all quantities which may possibly be affected.
351 using TransUpdateQuantities = typename Vanguard::TransmissibilityType::TransUpdateQuantities;
352 transmissibilities_.update(true, TransUpdateQuantities::All, equilGridToGrid);
353 this->referencePorosity_[1] = this->referencePorosity_[0];
355 this->rockFraction_[1] = this->rockFraction_[0];
358 this->model().linearizer().updateDiscretizationParameters();
359 }
360
361 bool tuningEvent = this->beginEpisode_(enableExperiments, this->episodeIndex());
362
363 // set up the wells for the next episode.
364 wellModel_.beginEpisode();
365
366 // set up the aquifers for the next episode.
367 aquiferModel_.beginEpisode();
368
369 // set the size of the initial time step of the episode
370 Scalar dt = limitNextTimeStepSize_(simulator.episodeLength());
371 // negative value of initialTimeStepSize_ indicates no active limit from TSINIT or NEXTSTEP
372 if ( (episodeIdx == 0 || tuningEvent) && this->initialTimeStepSize_ > 0)
373 // allow the size of the initial time step to be set via an external parameter
374 // if TUNING is enabled, also limit the time step size after a tuning event to TSINIT
375 dt = std::min(dt, this->initialTimeStepSize_);
376 simulator.setTimeStepSize(dt);
377 }
378
382 virtual void beginTimeStep()
383 {
384 OPM_TIMEBLOCK(beginTimeStep);
385 const int episodeIdx = this->episodeIndex();
386 const int timeStepSize = this->simulator().timeStepSize();
387
390 }
391
393 episodeIdx,
394 this->simulator().timeStepIndex(),
395 this->simulator().startTime(),
396 this->simulator().time(),
397 timeStepSize,
398 this->simulator().endTime());
399
400 // update maximum water saturation and minimum pressure
401 // used when ROCKCOMP is activated
402 // Do not update max RS first step after a restart
403 this->updateExplicitQuantities_(episodeIdx, timeStepSize, first_step_ && (episodeIdx > 0));
404 first_step_ = false;
405
407 this->model().linearizer().updateBoundaryConditionData();
408 }
409
410 wellModel_.beginTimeStep();
411 aquiferModel_.beginTimeStep();
412 tracerModel_.beginTimeStep();
413 temperatureModel_.beginTimeStep();
414 }
415
421 {
424 }
425 wellModel_.updateFailed();
426 this->model().updateFailed();
427 }
428
434 {
435 this->model().advanceTimeLevel();
436 wellModel_.advanceTimeLevel();
437 }
438
443 {
444 OPM_TIMEBLOCK(beginIteration);
445 wellModel_.beginIteration();
446 aquiferModel_.beginIteration();
447 }
448
453 {
454 OPM_TIMEBLOCK(endIteration);
455 wellModel_.endIteration();
456 aquiferModel_.endIteration();
457 }
458
462 virtual void endTimeStep()
463 {
464 OPM_TIMEBLOCK(endTimeStep);
465
466#ifndef NDEBUG
467 if constexpr (getPropValue<TypeTag, Properties::EnableDebuggingChecks>()) {
468 // in debug mode, we don't care about performance, so we check
469 // if the model does the right thing (i.e., the mass change
470 // inside the whole reservoir must be equivalent to the fluxes
471 // over the grid's boundaries plus the source rates specified by
472 // the problem).
473 const int rank = this->simulator().gridView().comm().rank();
474 if (rank == 0) {
475 std::cout << "checking conservativeness of solution\n";
476 }
477
478 this->model().checkConservativeness(/*tolerance=*/-1, /*verbose=*/true);
479 if (rank == 0) {
480 std::cout << "solution is sufficiently conservative\n";
481 }
482 }
483#endif // NDEBUG
484
485 auto& simulator = this->simulator();
486 simulator.setTimeStepIndex(simulator.timeStepIndex()+1);
487
488 this->wellModel_.endTimeStep();
489 this->aquiferModel_.endTimeStep();
490 this->tracerModel_.endTimeStep();
491
492 // Compute flux for output
493 this->model().linearizer().updateFlowsInfo();
494
496 OPM_TIMEBLOCK(driftCompansation);
497
498 const auto& residual = this->model().linearizer().residual();
499
500 for (unsigned globalDofIdx = 0; globalDofIdx < residual.size(); globalDofIdx ++) {
501 int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(globalDofIdx);
502 this->drift_[sfcdofIdx] = residual[sfcdofIdx] * simulator.timeStepSize();
503
504 if constexpr (getPropValue<TypeTag, Properties::UseVolumetricResidual>()) {
505 this->drift_[sfcdofIdx] *= this->model().dofTotalVolume(sfcdofIdx);
506 }
507 }
508 }
509
510 // For sequential implicit thermal: finalize TEMP solve,
511 // then refresh cached intensive quantities (temperature-dependent).
512 if constexpr(energyModuleType == EnergyModules::SequentialImplicitThermal) {
513 this->temperatureModel_.endTimeStep(wellModel_.wellState());
514 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
515 }
516 }
517
521 virtual void endEpisode()
522 {
523 const int episodeIdx = this->episodeIndex();
524
525 this->wellModel_.endEpisode();
526 this->aquiferModel_.endEpisode();
527
528 const auto& schedule = this->simulator().vanguard().schedule();
529
530 // End simulation when completed.
531 if (episodeIdx + 1 >= static_cast<int>(schedule.size()) - 1) {
532 this->simulator().setFinished(true);
533 return;
534 }
535
536 // Otherwise, start next episode (report step).
537 this->simulator().startNextEpisode(schedule.stepLength(episodeIdx + 1));
538 }
539
544 virtual void writeOutput(bool verbose)
545 {
546 OPM_TIMEBLOCK(problemWriteOutput);
547
548 if (Parameters::Get<Parameters::EnableWriteAllSolutions>() ||
549 this->episodeWillBeOver())
550 {
551 // Create VTK output as needed.
552 ParentType::writeOutput(verbose);
553 }
554 }
555
559 template <class Context>
560 const DimMatrix& intrinsicPermeability(const Context& context,
561 unsigned spaceIdx,
562 unsigned timeIdx) const
563 {
564 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
565 return transmissibilities_.permeability(globalSpaceIdx);
566 }
567
574 const DimMatrix& intrinsicPermeability(unsigned globalElemIdx) const
575 { return transmissibilities_.permeability(globalElemIdx); }
576
580 template <class Context>
581 Scalar transmissibility(const Context& context,
582 [[maybe_unused]] unsigned fromDofLocalIdx,
583 unsigned toDofLocalIdx) const
584 {
585 assert(fromDofLocalIdx == 0);
586 return pffDofData_.get(context.element(), toDofLocalIdx).transmissibility;
587 }
588
592 Scalar transmissibility(unsigned globalCenterElemIdx, unsigned globalElemIdx) const
593 {
594 return transmissibilities_.transmissibility(globalCenterElemIdx, globalElemIdx);
595 }
596
600 Scalar thresholdPressure(unsigned elem1Idx, unsigned elem2Idx) const
601 { return thresholdPressures_.thresholdPressure(elem1Idx, elem2Idx); }
602
604 { return thresholdPressures_; }
605
607 { return thresholdPressures_; }
608
610 { return moduleParams_; }
611
615 template <class Context>
616 Scalar diffusivity(const Context& context,
617 [[maybe_unused]] unsigned fromDofLocalIdx,
618 unsigned toDofLocalIdx) const
619 {
620 assert(fromDofLocalIdx == 0);
621 return *pffDofData_.get(context.element(), toDofLocalIdx).diffusivity;
622 }
623
627 Scalar diffusivity(const unsigned globalCellIn, const unsigned globalCellOut) const{
628 return transmissibilities_.diffusivity(globalCellIn, globalCellOut);
629 }
630
634 Scalar dispersivity(const unsigned globalCellIn, const unsigned globalCellOut) const{
635 return transmissibilities_.dispersivity(globalCellIn, globalCellOut);
636 }
637
641 Scalar thermalTransmissibilityBoundary(const unsigned globalSpaceIdx,
642 const unsigned boundaryFaceIdx) const
643 {
644 return transmissibilities_.thermalTransmissibilityBoundary(globalSpaceIdx, boundaryFaceIdx);
645 }
646
647
648
649
653 template <class Context>
654 Scalar transmissibilityBoundary(const Context& elemCtx,
655 unsigned boundaryFaceIdx) const
656 {
657 unsigned elemIdx = elemCtx.globalSpaceIndex(/*dofIdx=*/0, /*timeIdx=*/0);
658 return transmissibilities_.transmissibilityBoundary(elemIdx, boundaryFaceIdx);
659 }
660
664 Scalar transmissibilityBoundary(const unsigned globalSpaceIdx,
665 const unsigned boundaryFaceIdx) const
666 {
667 return transmissibilities_.transmissibilityBoundary(globalSpaceIdx, boundaryFaceIdx);
668 }
669
670
674 Scalar thermalHalfTransmissibility(const unsigned globalSpaceIdxIn,
675 const unsigned globalSpaceIdxOut) const
676 {
677 return transmissibilities_.thermalHalfTrans(globalSpaceIdxIn,globalSpaceIdxOut);
678 }
679
683 template <class Context>
684 Scalar thermalHalfTransmissibilityIn(const Context& context,
685 unsigned faceIdx,
686 unsigned timeIdx) const
687 {
688 const auto& face = context.stencil(timeIdx).interiorFace(faceIdx);
689 unsigned toDofLocalIdx = face.exteriorIndex();
690 return *pffDofData_.get(context.element(), toDofLocalIdx).thermalHalfTransIn;
691 }
692
696 template <class Context>
698 unsigned faceIdx,
699 unsigned timeIdx) const
700 {
701 const auto& face = context.stencil(timeIdx).interiorFace(faceIdx);
702 unsigned toDofLocalIdx = face.exteriorIndex();
703 return *pffDofData_.get(context.element(), toDofLocalIdx).thermalHalfTransOut;
704 }
705
709 template <class Context>
711 unsigned boundaryFaceIdx) const
712 {
713 unsigned elemIdx = elemCtx.globalSpaceIndex(/*dofIdx=*/0, /*timeIdx=*/0);
714 return transmissibilities_.thermalHalfTransBoundary(elemIdx, boundaryFaceIdx);
715 }
716
720 const typename Vanguard::TransmissibilityType& eclTransmissibilities() const
721 { return transmissibilities_; }
722
723
725 { return tracerModel_; }
726
728 { return tracerModel_; }
729
730 TemperatureModel& temperatureModel() // need for restart
731 { return temperatureModel_; }
732
741 template <class Context>
742 Scalar porosity(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
743 {
744 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
745 return this->porosity(globalSpaceIdx, timeIdx);
746 }
747
754 template <class Context>
755 Scalar dofCenterDepth(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
756 {
757 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
758 return this->dofCenterDepth(globalSpaceIdx);
759 }
760
767 Scalar dofCenterDepth(unsigned globalSpaceIdx) const
768 {
769 return this->simulator().vanguard().cellCenterDepth(globalSpaceIdx);
770 }
771
775 template <class Context>
776 Scalar rockCompressibility(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
777 {
778 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
779 return this->rockCompressibility(globalSpaceIdx);
780 }
781
785 template <class Context>
786 Scalar rockBiotComp(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
787 {
788 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
789 return this->rockBiotComp(globalSpaceIdx);
790 }
791
795 template <class Context>
796 Scalar rockBiotTemp(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
797 {
798 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
799 return this->rockBiotTemp(globalSpaceIdx);
800 }
801
805 template <class Context>
806 Scalar lame(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
807 {
808 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
809 return this->lame(globalSpaceIdx);
810 }
811
815 template <class Context>
816 Scalar biotCoeff(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
817 {
818 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
819 return this->biotCoeff(globalSpaceIdx);
820 }
821
825 template <class Context>
826 Scalar biotTemp(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
827 {
828 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
829 return this->biotTemp(globalSpaceIdx);
830 }
831
835 template <class Context>
836 Scalar rockReferencePressure(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
837 {
838 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
839 return rockReferencePressure(globalSpaceIdx);
840 }
841
845 Scalar rockReferencePressure(unsigned globalSpaceIdx) const
846 {
847 const auto& rock_config = this->simulator().vanguard().eclState().getSimulationConfig().rock_config();
848 if (rock_config.store()) {
849 return asImp_().initialFluidState(globalSpaceIdx).pressure(refPressurePhaseIdx_());
850 }
851 else {
852 if (this->rockParams_.empty())
853 return 1e5;
854
855 unsigned tableIdx = 0;
856 if (!this->rockTableIdx_.empty()) {
857 tableIdx = this->rockTableIdx_[globalSpaceIdx];
858 }
859 return this->rockParams_[tableIdx].referencePressure;
860 }
861 }
862
866 template <class Context>
867 const MaterialLawParams& materialLawParams(const Context& context,
868 unsigned spaceIdx, unsigned timeIdx) const
869 {
870 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
871 return this->materialLawParams(globalSpaceIdx);
872 }
873
874 const MaterialLawParams& materialLawParams(unsigned globalDofIdx) const
875 {
876 return materialLawManager_->materialLawParams(globalDofIdx);
877 }
878
879 const MaterialLawParams& materialLawParams(unsigned globalDofIdx, FaceDir::DirEnum facedir) const
880 {
881 return materialLawManager_->materialLawParams(globalDofIdx, facedir);
882 }
883
887 template <class Context>
889 solidEnergyLawParams(const Context& context,
890 unsigned spaceIdx,
891 unsigned timeIdx) const
892 {
893 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
894 return thermalLawManager_->solidEnergyLawParams(globalSpaceIdx);
895 }
896
900 template <class Context>
902 thermalConductionLawParams(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
903 {
904 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
905 return thermalLawManager_->thermalConductionLawParams(globalSpaceIdx);
906 }
907
914 std::shared_ptr<const EclMaterialLawManager> materialLawManager() const
915 { return materialLawManager_; }
916
917 // Avoid shared_ptr reference-count traffic in per-cell calculations.
919 { return *materialLawManager_; }
920
921 std::shared_ptr<const EclThermalLawManager> thermalLawManager() const
922 { return thermalLawManager_; }
923
924 template <class FluidState, class ...Args>
926 std::array<Evaluation,numPhases> &mobility,
928 FluidState &fluidState,
929 unsigned globalSpaceIdx) const
930 {
931 using ContainerT = std::array<Evaluation, numPhases>;
932 OPM_TIMEBLOCK_LOCAL(updateRelperms, Subsystem::SatProps);
933 {
934 // calculate relative permeabilities. note that we store the result into the
935 // mobility_ class attribute. the division by the phase viscosity happens later.
936 const auto& materialParams = materialLawParams(globalSpaceIdx);
937 MaterialLaw::template relativePermeabilities<ContainerT, FluidState, Args...>(mobility, materialParams, fluidState);
938 Valgrind::CheckDefined(mobility);
939 }
940 if (materialLawManager_->hasDirectionalRelperms()
941 || materialLawManager_->hasDirectionalImbnum())
942 {
943 using Dir = FaceDir::DirEnum;
944 constexpr int ndim = 3;
945 dirMob = std::make_unique<DirectionalMobility<TypeTag>>();
946 Dir facedirs[ndim] = {Dir::XPlus, Dir::YPlus, Dir::ZPlus};
947 for (int i = 0; i<ndim; i++) {
948 const auto& materialParams = materialLawParams(globalSpaceIdx, facedirs[i]);
949 auto& mob_array = dirMob->getArray(i);
950 MaterialLaw::template relativePermeabilities<ContainerT, FluidState, Args...>(mob_array, materialParams, fluidState);
951 }
952 }
953 }
954
958 std::shared_ptr<EclMaterialLawManager> materialLawManager()
959 { return materialLawManager_; }
960
965 template <class Context>
966 unsigned pvtRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
967 { return pvtRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
968
973 template <class Context>
974 unsigned satnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
975 { return this->satnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
976
981 template <class Context>
982 unsigned miscnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
983 { return this->miscnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
984
989 template <class Context>
990 unsigned plmixnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
991 { return this->plmixnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
992
993 // TODO: polymer related might need to go to the blackoil side
998 template <class Context>
999 Scalar maxPolymerAdsorption(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
1000 { return this->maxPolymerAdsorption(context.globalSpaceIndex(spaceIdx, timeIdx)); }
1001
1005 std::string name() const
1006 { return this->simulator().vanguard().caseName(); }
1007
1011 template <class Context>
1012 Scalar temperature(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
1013 {
1014 // use the initial temperature of the DOF if temperature is not a primary
1015 // variable
1016 unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
1017 if constexpr (energyModuleType == EnergyModules::SequentialImplicitThermal)
1018 return temperatureModel_.temperature(globalDofIdx);
1019
1020 return asImp_().initialFluidState(globalDofIdx).temperature(/*phaseIdx=*/0);
1021 }
1022
1023
1024 Scalar temperature(unsigned globalDofIdx, unsigned /*timeIdx*/) const
1025 {
1026 // use the initial temperature of the DOF if temperature is not a primary
1027 // variable
1028 if constexpr (energyModuleType == EnergyModules::SequentialImplicitThermal)
1029 return temperatureModel_.temperature(globalDofIdx);
1030
1031 return asImp_().initialFluidState(globalDofIdx).temperature(/*phaseIdx=*/0);
1032 }
1033
1035 solidEnergyLawParams(unsigned globalSpaceIdx,
1036 unsigned /*timeIdx*/) const
1037 {
1038 return this->thermalLawManager_->solidEnergyLawParams(globalSpaceIdx);
1039 }
1041 thermalConductionLawParams(unsigned globalSpaceIdx,
1042 unsigned /*timeIdx*/)const
1043 {
1044 return this->thermalLawManager_->thermalConductionLawParams(globalSpaceIdx);
1045 }
1046
1056 Scalar maxOilSaturation(unsigned globalDofIdx) const
1057 {
1058 if (!this->vapparsActive(this->episodeIndex()))
1059 return 0.0;
1060
1061 return this->maxOilSaturation_[globalDofIdx];
1062 }
1063
1073 void setMaxOilSaturation(unsigned globalDofIdx, Scalar value)
1074 {
1075 if (!this->vapparsActive(this->episodeIndex()))
1076 return;
1077
1078 this->maxOilSaturation_[globalDofIdx] = value;
1079 }
1080
1085 {
1086 // Calculate all intensive quantities.
1087 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx*/0);
1088
1089 // We also need the intensive quantities for timeIdx == 1
1090 // corresponding to the start of the current timestep, if we
1091 // do not use the storage cache, or if we cannot recycle the
1092 // first iteration storage.
1093 if (!this->model().enableStorageCache() || !this->recycleFirstIterationStorage()) {
1094 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx*/1);
1095 }
1096
1097 // initialize the wells. Note that this needs to be done after initializing the
1098 // intrinsic permeabilities and the after applying the initial solution because
1099 // the well model uses these...
1100 wellModel_.init();
1101
1102 aquiferModel_.initialSolutionApplied();
1103
1104 const bool invalidateFromHyst = updateHysteresis_();
1105 if (invalidateFromHyst) {
1106 OPM_TIMEBLOCK(beginTimeStepInvalidateIntensiveQuantities);
1107 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
1108 }
1109 }
1110
1116 template <class Context>
1117 void source(RateVector& rate,
1118 const Context& context,
1119 unsigned spaceIdx,
1120 unsigned timeIdx) const
1121 {
1122 const unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
1123 source(rate, globalDofIdx, timeIdx);
1124 }
1125
1126 void source(RateVector& rate,
1127 unsigned globalDofIdx,
1128 unsigned timeIdx) const
1129 {
1130 OPM_TIMEBLOCK_LOCAL(eclProblemSource, Subsystem::Assembly);
1131 rate = 0.0;
1132
1133 // Add well contribution to source here.
1134 wellModel_.computeTotalRatesForDof(rate, globalDofIdx);
1135
1136 // convert the source term from the total mass rate of the
1137 // cell to the one per unit of volume as used by the model.
1138 for (unsigned eqIdx = 0; eqIdx < numEq; ++ eqIdx) {
1139 rate[eqIdx] /= this->model().dofTotalVolume(globalDofIdx);
1140
1141 Valgrind::CheckDefined(rate[eqIdx]);
1142 assert(isfinite(rate[eqIdx]));
1143 }
1144
1145 // Add non-well sources.
1146 addToSourceDense(rate, globalDofIdx, timeIdx);
1147 }
1148
1149 virtual void addToSourceDense(RateVector& rate,
1150 unsigned globalDofIdx,
1151 unsigned timeIdx) const = 0;
1152
1158 const WellModel& wellModel() const
1159 { return wellModel_; }
1160
1162 { return wellModel_; }
1163
1165 { return aquiferModel_; }
1166
1168 { return aquiferModel_; }
1169
1172
1180 {
1181 OPM_TIMEBLOCK(nexTimeStepSize);
1182 // allow external code to do the timestepping
1183 if (this->nextTimeStepSize_ > 0.0)
1184 return this->nextTimeStepSize_;
1185
1186 const auto& simulator = this->simulator();
1187 int episodeIdx = simulator.episodeIndex();
1188
1189 // for the initial episode, we use a fixed time step size
1190 if (episodeIdx < 0)
1191 return this->initialTimeStepSize_;
1192
1193 // ask the newton method for a suggestion. This suggestion will be based on how
1194 // well the previous time step converged. After that, apply the runtime time
1195 // stepping constraints.
1196 const auto& newtonMethod = this->model().newtonMethod();
1197 return limitNextTimeStepSize_(newtonMethod.suggestTimeStepSize(simulator.timeStepSize()));
1198 }
1199
1205 template <class LhsEval>
1206 LhsEval rockCompPoroMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx) const
1207 {
1208 OPM_TIMEBLOCK_LOCAL(rockCompPoroMultiplier, Subsystem::PvtProps);
1209 if (this->rockCompPoroMult_.empty() && this->rockCompPoroMultWc_.empty())
1210 return 1.0;
1211
1212 unsigned tableIdx = 0;
1213 if (!this->rockTableIdx_.empty())
1214 tableIdx = this->rockTableIdx_[elementIdx];
1215
1216 const auto& fs = intQuants.fluidState();
1217 const auto& rock_config = this->simulator().vanguard().eclState().getSimulationConfig().rock_config();
1218
1219 if (!this->rockCompPoroMultElastic_.empty()) {
1220 // ROCKCOMP HYSTERESIS=HYSTER: follow the deflation (virgin/plastic) curve
1221 // at or below the lowest pressure ever reached by this cell, and the
1222 // reversible elastic reload curve, anchored at that turning pressure,
1223 // above it.
1224 LhsEval effectivePressure = decay<LhsEval>(fs.pressure(refPressurePhaseIdx_()));
1225 LhsEval turningPressure = this->minRefPressure_[elementIdx];
1226
1227 if (!this->overburdenPressure_.empty()) {
1228 effectivePressure -= this->overburdenPressure_[elementIdx];
1229 turningPressure -= this->overburdenPressure_[elementIdx];
1230 }
1231
1232 if (rock_config.store()) {
1233 const auto& initialPressure = asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
1234 effectivePressure -= initialPressure;
1235 turningPressure -= initialPressure;
1236 }
1237
1238 if (effectivePressure <= turningPressure)
1239 return this->rockCompPoroMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
1240
1241 return this->rockCompPoroMultElastic_[tableIdx].eval(turningPressure, effectivePressure, /*extrapolation=*/true);
1242 }
1243
1244 LhsEval effectivePressure = decay<LhsEval>(fs.pressure(refPressurePhaseIdx_()));
1245 if (!this->minRefPressure_.empty())
1246 // The pore space change is irreversible
1247 effectivePressure =
1248 min(decay<LhsEval>(fs.pressure(refPressurePhaseIdx_())),
1249 this->minRefPressure_[elementIdx]);
1250
1251 if (!this->overburdenPressure_.empty())
1252 effectivePressure -= this->overburdenPressure_[elementIdx];
1253
1254 if (rock_config.store()) {
1255 effectivePressure -= asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
1256 }
1257
1258 if (!this->rockCompPoroMult_.empty()) {
1259 return this->rockCompPoroMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
1260 }
1261
1262 // water compaction
1263 assert(!this->rockCompPoroMultWc_.empty());
1264 LhsEval SwMax = max(decay<LhsEval>(fs.saturation(waterPhaseIdx)), this->maxWaterSaturation_[elementIdx]);
1265 LhsEval SwDeltaMax = SwMax - asImp_().initialFluidStates()[elementIdx].saturation(waterPhaseIdx);
1266
1267 return this->rockCompPoroMultWc_[tableIdx].eval(effectivePressure, SwDeltaMax, /*extrapolation=*/true);
1268 }
1269
1275 template <class LhsEval>
1276 LhsEval rockCompTransMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx) const
1277 {
1278 auto obtain = [](const auto& value)
1279 {
1280 if constexpr (std::is_same_v<LhsEval, Scalar>) {
1281 return getValue(value);
1282 } else {
1283 return value;
1284 }
1285 };
1286 return rockCompTransMultiplier<LhsEval>(intQuants, elementIdx, obtain);
1287 }
1288
1289 template <class LhsEval, class Callback>
1290 LhsEval rockCompTransMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
1291 {
1292 const bool implicit = !this->explicitRockCompaction_;
1293 return implicit ? this->simulator().problem().template computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain)
1294 : this->simulator().problem().getRockCompTransMultVal(elementIdx);
1295 }
1296
1297 template <class LhsEval, class Callback>
1298 LhsEval wellTransMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
1299 {
1300 OPM_TIMEBLOCK_LOCAL(wellTransMultiplier, Subsystem::Wells);
1301
1302 const bool implicit = !this->explicitRockCompaction_;
1303 LhsEval trans_mult = implicit ? this->simulator().problem().template computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain)
1304 : this->simulator().problem().getRockCompTransMultVal(elementIdx);
1305 trans_mult *= this->simulator().problem().template permFactTransMultiplier<LhsEval>(intQuants, elementIdx, obtain);
1306
1307 return trans_mult;
1308 }
1309
1310 std::pair<BCType, RateVector> boundaryCondition(const unsigned int globalSpaceIdx, const int directionId) const
1311 {
1312 OPM_TIMEBLOCK_LOCAL(boundaryCondition, Subsystem::Assembly);
1314 return { BCType::NONE, RateVector(0.0) };
1315 }
1316 FaceDir::DirEnum dir = FaceDir::FromIntersectionIndex(directionId);
1317 const auto& schedule = this->simulator().vanguard().schedule();
1318 if (bcindex_(dir)[globalSpaceIdx] == 0) {
1319 return { BCType::NONE, RateVector(0.0) };
1320 }
1321 if (schedule[this->episodeIndex()].bcstate.size() == 0) {
1322 return { BCType::NONE, RateVector(0.0) };
1323 }
1324 const auto& bc = schedule[this->episodeIndex()].bcstate[bcindex_(dir)[globalSpaceIdx]];
1325 if (bc.bctype!=BCType::RATE) {
1326 return { bc.bctype, RateVector(0.0) };
1327 }
1328
1329 RateVector rate = 0.0;
1330 switch (bc.component) {
1331 case BCComponent::OIL:
1332 rate[FluidSystem::canonicalToActiveCompIdx(oilCompIdx)] = bc.rate;
1333 break;
1334 case BCComponent::GAS:
1335 rate[FluidSystem::canonicalToActiveCompIdx(gasCompIdx)] = bc.rate;
1336 break;
1337 case BCComponent::WATER:
1338 rate[FluidSystem::canonicalToActiveCompIdx(waterCompIdx)] = bc.rate;
1339 break;
1340 case BCComponent::SOLVENT:
1341 this->handleSolventBC(bc, rate);
1342 break;
1343 case BCComponent::POLYMER:
1344 this->handlePolymerBC(bc, rate);
1345 break;
1346 case BCComponent::MICR:
1347 this->handleMicrBC(bc, rate);
1348 break;
1349 case BCComponent::OXYG:
1350 this->handleOxygBC(bc, rate);
1351 break;
1352 case BCComponent::UREA:
1353 this->handleUreaBC(bc, rate);
1354 break;
1355 case BCComponent::NONE:
1356 throw std::logic_error("you need to specify the component when RATE type is set in BC");
1357 break;
1358 }
1359 //TODO add support for enthalpy rate
1360 return {bc.bctype, rate};
1361 }
1362
1363
1364 template<class Serializer>
1365 void serializeOp(Serializer& serializer)
1366 {
1367 serializer(static_cast<BaseType&>(*this));
1368 serializer(first_step_);
1369 serializer(drift_);
1370 serializer(wellModel_);
1371 serializer(aquiferModel_);
1372 serializer(tracerModel_);
1373 serializer(temperatureModel_);
1374 serializer(*materialLawManager_);
1375 }
1376
1377 const GlobalEqVector& drift() const
1378 {
1379 return drift_;
1380 }
1381
1382private:
1383 Implementation& asImp_()
1384 { return *static_cast<Implementation *>(this); }
1385
1386 const Implementation& asImp_() const
1387 { return *static_cast<const Implementation *>(this); }
1388
1389protected:
1397 {
1404 if (materialLawManager_ && materialLawManager_->enableHysteresis()) {
1405 materialLawManager_->captureBeginTimeStepState();
1406 }
1407 }
1408
1411 {
1418 if (materialLawManager_ && materialLawManager_->enableHysteresis()) {
1419 materialLawManager_->restoreBeginTimeStepState();
1420 }
1421 }
1422
1424 {
1425 this->transmissibilities_.finishInit(
1426 [&vg = this->simulator().vanguard()](const unsigned int index) {
1427 return vg.gridIdxToEquilGridIdx(index);
1428 });
1429 }
1430
1431 template<class EclWriterType>
1432 bool prepareTransmissibilityOutput_(EclWriterType& eclWriter,
1433 const bool enableEclOutput)
1434 {
1435 auto& simulator = this->simulator();
1436 bool localTransmissibilitiesFinished = false;
1437
1438 if (enableEclOutput) {
1439 // Parallel TRANX, TRANY, TRANZ and NNC output requires the global
1440 // grid's transmissibilities on the I/O rank -- except with LGRs, below.
1441 if (simulator.vanguard().grid().comm().size() > 1) {
1442 bool wholeGridTransNeeded = simulator.vanguard().grid().comm().rank() == 0;
1443 // Parallel LGR: reuse the simulator's own (distributed) transmissibilities for the
1444 // INIT output -- each rank contributes its interior connections, gathered on the
1445 // I/O rank and keyed by level-Cartesian indices so the output walk over the global
1446 // (equil) grid can look them up directly. This reuses the values already computed
1447 // in parallel for the simulation itself instead of recomputing a whole-grid
1448 // transmissibility. The local transmissibilities are built here, before the INIT
1449 // write, and reported as finished so that they are not built again.
1450 if constexpr (std::is_same_v<GetPropType<TypeTag, Properties::Grid>, Dune::CpGrid>) {
1451 // Gate on the deck's LGRs -- the same condition the writer keys its LGR
1452 // output walk on (writeInit / extractOutputTransAndNNC). Grid refinement
1453 // alone (grid().maxLevel() > 0, e.g. after adapt()) must not enable the
1454 // gathered mode: the writer would look up different keys than the ones
1455 // the leaf-grid walk records.
1456 if (simulator.vanguard().eclState().getLgrs().size() > 0) {
1458 localTransmissibilitiesFinished = true;
1459 const auto& localTrans = simulator.problem().eclTransmissibilities();
1460 eclWriter.setGatheredLgrTrans(
1461 gatherLgrOutputTrans(simulator.vanguard().grid(),
1462 simulator.vanguard().gridView(),
1463 [&localTrans](unsigned c1, unsigned c2)
1464 { return static_cast<double>(localTrans.transmissibility(c1, c2)); }));
1465 // All output values (TRANX/Y/Z and NNC) come from the gathered records --
1466 // no whole-grid transmissibility object is needed on the I/O rank.
1467 wholeGridTransNeeded = false;
1468 }
1469 }
1470 if (wholeGridTransNeeded) {
1471 eclWriter.setTransmissibilities(&simulator.vanguard().globalTransmissibility());
1472 }
1473 }
1474 else {
1476 localTransmissibilitiesFinished = true;
1477 eclWriter.setTransmissibilities(&simulator.problem().eclTransmissibilities());
1478 }
1479
1480 std::function<unsigned int(unsigned int)> equilGridToGrid =
1481 [&simulator](const unsigned int index) {
1482 return simulator.vanguard().gridEquilIdxToGridIdx(index);
1483 };
1484 eclWriter.extractOutputTransAndNNC(equilGridToGrid);
1485 }
1486
1487 simulator.vanguard().releaseGlobalTransmissibilities();
1488 return localTransmissibilitiesFinished;
1489 }
1490
1492 {
1493 auto& simulator = this->simulator();
1494 const auto& eclState = simulator.vanguard().eclState();
1495 const auto& schedule = simulator.vanguard().schedule();
1496
1497 simulator.setStartTime(TimeService::to_time_t(schedule.getStartTime()));
1498 simulator.setEndTime(TimeService::to_time_t(schedule.simTime(schedule.size() - 1)));
1499
1500 // Represent initialization as a zero-length episode before report step zero.
1501 simulator.setEpisodeIndex(-1);
1502 simulator.setEpisodeLength(0.0);
1503
1504 this->initGravity_(eclState);
1505
1506 if (this->enableTuning_) {
1507 // If support for the TUNING keyword is enabled, get the initial time
1508 // stepping parameters from it instead of from command line parameters.
1509 const auto& tuning = schedule[0].tuning();
1510 this->initialTimeStepSize_ = tuning.TSINIT.value_or(-1.0);
1511 this->maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
1512 }
1513 }
1514
1516 {
1517 auto& simulator = this->simulator();
1518
1519 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) &&
1520 FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
1521 this->maxOilSaturation_.resize(this->model().numGridDof(), 0.0);
1522 }
1523
1524 this->readRockParameters_(
1525 simulator.vanguard().cellCenterDepths(),
1526 [&simulator](const unsigned int index) {
1527 std::array<int, dim> coords;
1528 simulator.vanguard().cartesianCoordinate(index, coords);
1529 std::ranges::transform(coords, coords.begin(),
1530 [](const auto coordinate) { return coordinate + 1; });
1531 return coords;
1532 });
1533
1535 this->readThermalParameters_();
1536 }
1537
1538 template<class UpdateFunc>
1539 void updateProperty_(const std::string& failureMsg,
1540 UpdateFunc func)
1541 {
1542 OPM_TIMEBLOCK(updateProperty);
1543 const auto& model = this->simulator().model();
1544 const auto& primaryVars = model.solution(/*timeIdx*/0);
1545 const auto& vanguard = this->simulator().vanguard();
1546 std::size_t numGridDof = primaryVars.size();
1548#ifdef _OPENMP
1549#pragma omp parallel for
1550#endif
1551 for (unsigned dofIdx = 0; dofIdx < numGridDof; ++dofIdx) {
1552 const auto& iq = model.intensiveQuantities(dofIdx, /*timeIdx=*/ 0);
1553 func(dofIdx, iq);
1554 }
1555 OPM_END_PARALLEL_TRY_CATCH(failureMsg, vanguard.grid().comm());
1556 }
1557
1559 {
1560 OPM_TIMEBLOCK(updateMaxOilSaturation);
1561 int episodeIdx = this->episodeIndex();
1562
1563 // we use VAPPARS
1564 if (this->vapparsActive(episodeIdx)) {
1565 this->updateProperty_("FlowProblem::updateMaxOilSaturation_() failed:",
1566 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1567 {
1568 this->updateMaxOilSaturation_(compressedDofIdx,iq);
1569 });
1570 return true;
1571 }
1572
1573 return false;
1574 }
1575
1576 bool updateMaxOilSaturation_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1577 {
1578 OPM_TIMEBLOCK_LOCAL(updateMaxOilSaturation, Subsystem::SatProps);
1579 const auto& fs = iq.fluidState();
1580 const Scalar So = decay<Scalar>(fs.saturation(refPressurePhaseIdx_()));
1581 auto& mos = this->maxOilSaturation_;
1582 if(mos[compressedDofIdx] < So){
1583 mos[compressedDofIdx] = So;
1584 return true;
1585 }else{
1586 return false;
1587 }
1588 }
1589
1591 {
1592 OPM_TIMEBLOCK(updateMaxWaterSaturation);
1593 // water compaction is activated in ROCKCOMP
1594 if (this->maxWaterSaturation_.empty())
1595 return false;
1596
1597 this->updateProperty_("FlowProblem::updateMaxWaterSaturation_() failed:",
1598 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1599 {
1600 this->updateMaxWaterSaturation_(compressedDofIdx,iq);
1601 });
1602 return true;
1603 }
1604
1605
1606 bool updateMaxWaterSaturation_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1607 {
1608 OPM_TIMEBLOCK_LOCAL(updateMaxWaterSaturation, Subsystem::SatProps);
1609 const auto& fs = iq.fluidState();
1610 const Scalar Sw = decay<Scalar>(fs.saturation(waterPhaseIdx));
1611 auto& mow = this->maxWaterSaturation_;
1612 if(mow[compressedDofIdx]< Sw){
1613 mow[compressedDofIdx] = Sw;
1614 return true;
1615 }else{
1616 return false;
1617 }
1618 }
1619
1621 {
1622 OPM_TIMEBLOCK(updateMinPressure);
1623 // IRREVERS option is used in ROCKCOMP
1624 if (this->minRefPressure_.empty())
1625 return false;
1626
1627 this->updateProperty_("FlowProblem::updateMinPressure_() failed:",
1628 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1629 {
1630 this->updateMinPressure_(compressedDofIdx,iq);
1631 });
1632 return true;
1633 }
1634
1635 bool updateMinPressure_(unsigned compressedDofIdx, const IntensiveQuantities& iq){
1636 OPM_TIMEBLOCK_LOCAL(updateMinPressure, Subsystem::PvtProps);
1637 const auto& fs = iq.fluidState();
1638 const Scalar min_pressure = getValue(fs.pressure(refPressurePhaseIdx_()));
1639 auto& min_pressures = this->minRefPressure_;
1640 if(min_pressures[compressedDofIdx]> min_pressure){
1641 min_pressures[compressedDofIdx] = min_pressure;
1642 return true;
1643 }else{
1644 return false;
1645 }
1646 }
1647
1648 // \brief Function to assign field properties of type double, on the leaf grid view.
1649 //
1650 // For CpGrid with local grid refinement, the field property of a cell on the leaf
1651 // is inherited from its parent or equivalent (when has no parent) cell on level zero.
1652 std::function<std::vector<double>(const FieldPropsManager&, const std::string&)>
1654 {
1655 const auto& lookup = this->lookUpData_;
1656 return [&lookup](const FieldPropsManager& fieldPropManager, const std::string& propString)
1657 {
1658 return lookup.assignFieldPropsDoubleOnLeaf(fieldPropManager, propString);
1659 };
1660 }
1661
1662 // \brief Function to assign field properties of type int, unsigned int, ..., on the leaf grid view.
1663 //
1664 // For CpGrid with local grid refinement, the field property of a cell on the leaf
1665 // is inherited from its parent or equivalent (when has no parent) cell on level zero.
1666 template<typename IntType>
1667 std::function<std::vector<IntType>(const FieldPropsManager&, const std::string&, bool)>
1669 {
1670 const auto& lookup = this->lookUpData_;
1671 return [&lookup](const FieldPropsManager& fieldPropManager, const std::string& propString, bool needsTranslation)
1672 {
1673 return lookup.template assignFieldPropsIntOnLeaf<IntType>(fieldPropManager, propString, needsTranslation);
1674 };
1675 }
1676
1678 {
1679 OPM_TIMEBLOCK(readMaterialParameters);
1680 const auto& simulator = this->simulator();
1681 const auto& vanguard = simulator.vanguard();
1682 const auto& eclState = vanguard.eclState();
1683
1684 // the PVT and saturation region numbers
1686 this->updatePvtnum_();
1687 this->updateSatnum_();
1688
1689 // the MISC region numbers (solvent model)
1690 this->updateMiscnum_();
1691 // the PLMIX region numbers (polymer model)
1692 this->updatePlmixnum_();
1693
1694 OPM_END_PARALLEL_TRY_CATCH("Invalid region numbers: ", vanguard.gridView().comm());
1696 // porosity
1697 updateReferencePorosity_();
1698 this->referencePorosity_[1] = this->referencePorosity_[0];
1700
1702 // rock fraction
1703 updateRockFraction_();
1704 this->rockFraction_[1] = this->rockFraction_[0];
1706
1708 // fluid-matrix interactions (saturation functions; relperm/capillary pressure)
1709 materialLawManager_ = std::make_shared<EclMaterialLawManager>();
1710 materialLawManager_->initFromState(eclState);
1711 materialLawManager_->initParamsForElements(eclState, this->model().numGridDof(),
1712 this-> template fieldPropIntTypeOnLeafAssigner_<int>(),
1713 this-> lookupIdxOnLevelZeroAssigner_());
1715 }
1716
1718 {
1719 if constexpr (energyModuleType == EnergyModules::FullyImplicitThermal ||
1720 energyModuleType == EnergyModules::SequentialImplicitThermal )
1721 {
1722 const auto& simulator = this->simulator();
1723 const auto& vanguard = simulator.vanguard();
1724 const auto& eclState = vanguard.eclState();
1725
1726 // fluid-matrix interactions (saturation functions; relperm/capillary pressure)
1727 thermalLawManager_ = std::make_shared<EclThermalLawManager>();
1728 thermalLawManager_->initParamsForElements(eclState, this->model().numGridDof(),
1729 this-> fieldPropDoubleOnLeafAssigner_(),
1730 this-> template fieldPropIntTypeOnLeafAssigner_<unsigned int>());
1731 }
1732 }
1733
1735 {
1736 const auto& simulator = this->simulator();
1737 const auto& vanguard = simulator.vanguard();
1738 const auto& eclState = vanguard.eclState();
1739
1740 std::size_t numDof = this->model().numGridDof();
1741
1742 this->referencePorosity_[/*timeIdx=*/0].resize(numDof);
1743
1744 const auto& fp = eclState.fieldProps();
1745 const std::vector<double> porvData = this -> fieldPropDoubleOnLeafAssigner_()(fp, "PORV");
1746 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
1747 int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(dofIdx);
1748 Scalar poreVolume = porvData[dofIdx];
1749
1750 // we define the porosity as the accumulated pore volume divided by the
1751 // geometric volume of the element. Note that -- in pathetic cases -- it can
1752 // be larger than 1.0!
1753 Scalar dofVolume = simulator.model().dofTotalVolume(sfcdofIdx);
1754 assert(dofVolume > 0.0);
1755 this->referencePorosity_[/*timeIdx=*/0][sfcdofIdx] = poreVolume/dofVolume;
1756 }
1757 }
1758
1760
1761 const bool solveEnergyEquation = (energyModuleType == EnergyModules::FullyImplicitThermal ||
1762 energyModuleType == EnergyModules::SequentialImplicitThermal);
1763 if (!solveEnergyEquation)
1764 return;
1765
1766 const auto& simulator = this->simulator();
1767 const auto& vanguard = simulator.vanguard();
1768 const auto& eclState = vanguard.eclState();
1769
1770 std::size_t numDof = this->model().numGridDof();
1771 this->rockFraction_[/*timeIdx=*/0].resize(numDof);
1772 // For the energy equation, we need the volume of the rock.
1773 // The volume of the rock is computed by rockFraction * geometric volume of the element.
1774 // The reference porosity is defined as porosity * ntg * pore-volume-multiplier.
1775 // A common practice in reservoir simulation is to use large pore-volume-multipliers in boundary cells
1776 // to model boundary conditions other than no-flow. This may result in reference porosities that are larger than 1.
1777 // A simple (1-reference porosity) * geometric volume of the element may give unphysical results.
1778 // We therefore instead consider the pore-volume-multiplier as a volume multiplier. The rock fraction is thus given by
1779 // (1 - porosity * ntg) * pore-volume-multiplier = (1 - porosity * ntg) * reference porosity / (porosity * ntg)
1780 const auto& fp = eclState.fieldProps();
1781 const std::vector<double> poroData = this->fieldPropDoubleOnLeafAssigner_()(fp, "PORO");
1782 const std::vector<double> ntgData = this->fieldPropDoubleOnLeafAssigner_()(fp, "NTG");
1783
1784 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
1785 const auto ntg = ntgData[dofIdx];
1786 const auto poro_eff = ntg * poroData[dofIdx];
1787 const int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(dofIdx);
1788 const auto rock_fraction = (1 - poro_eff) * this->referencePorosity_[/*timeIdx=*/0][sfcdofIdx] / poro_eff;
1789 this->rockFraction_[/*timeIdx=*/0][sfcdofIdx] = rock_fraction;
1790 }
1791 }
1792
1794 {
1795 // TODO: whether we should move this to FlowProblemBlackoil
1796 const auto& simulator = this->simulator();
1797 const auto& vanguard = simulator.vanguard();
1798 const auto& eclState = vanguard.eclState();
1799
1800 if (eclState.getInitConfig().hasEquil())
1801 readEquilInitialCondition_();
1802 else
1803 readExplicitInitialCondition_();
1804
1805 //initialize min/max values
1806 std::size_t numElems = this->model().numGridDof();
1807 for (std::size_t elemIdx = 0; elemIdx < numElems; ++elemIdx) {
1808 const auto& fs = asImp_().initialFluidStates()[elemIdx];
1809 if (!this->maxWaterSaturation_.empty() && waterPhaseIdx > -1)
1810 this->maxWaterSaturation_[elemIdx] = std::max(this->maxWaterSaturation_[elemIdx], fs.saturation(waterPhaseIdx));
1811 if (!this->maxOilSaturation_.empty() && oilPhaseIdx > -1)
1812 this->maxOilSaturation_[elemIdx] = std::max(this->maxOilSaturation_[elemIdx], fs.saturation(oilPhaseIdx));
1813 if (!this->minRefPressure_.empty() && refPressurePhaseIdx_() > -1)
1814 this->minRefPressure_[elemIdx] = std::min(this->minRefPressure_[elemIdx], fs.pressure(refPressurePhaseIdx_()));
1815 }
1816 }
1817
1818 virtual void readEquilInitialCondition_() = 0;
1820
1821 // update the hysteresis parameters of the material laws for the whole grid
1823 {
1824 if (!materialLawManager_->enableHysteresis())
1825 return false;
1826
1827 // we need to update the hysteresis data for _all_ elements (i.e., not just the
1828 // interior ones) to avoid desynchronization of the processes in the parallel case!
1829 this->updateProperty_("FlowProblem::updateHysteresis_() failed:",
1830 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1831 {
1832 materialLawManager_->updateHysteresis(iq.fluidState(), compressedDofIdx);
1833 });
1834 return true;
1835 }
1836
1837
1838 bool updateHysteresis_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1839 {
1840 OPM_TIMEBLOCK_LOCAL(updateHysteresis_, Subsystem::SatProps);
1841 materialLawManager_->updateHysteresis(iq.fluidState(), compressedDofIdx);
1842 //TODO change materials to give a bool
1843 return true;
1844 }
1845
1846 Scalar getRockCompTransMultVal(std::size_t dofIdx) const
1847 {
1848 if (this->rockCompTransMultVal_.empty())
1849 return 1.0;
1850
1851 return this->rockCompTransMultVal_[dofIdx];
1852 }
1853
1854protected:
1863 void initGravity_(const EclipseState& eclState)
1864 {
1865 this->gravity_ = 0.0;
1866
1867 if (Parameters::Get<Parameters::EnableGravity>() &&
1868 eclState.getInitConfig().hasGravity())
1869 {
1870 // unit::gravity is 9.80665 m^2/s--i.e., standard measure at Tellus equator.
1871 this->gravity_[dim - 1] = unit::gravity;
1872 }
1873 }
1874
1876 {
1877 ConditionalStorage<enableFullyImplicitThermal, Scalar> thermalHalfTransIn;
1878 ConditionalStorage<enableFullyImplicitThermal, Scalar> thermalHalfTransOut;
1879 ConditionalStorage<enableDiffusion, Scalar> diffusivity;
1880 ConditionalStorage<enableDispersion, Scalar> dispersivity;
1882 };
1883
1884 // update the prefetch friendly data object
1886 {
1887 const auto& distFn =
1888 [this](PffDofData_& dofData,
1889 const Stencil& stencil,
1890 unsigned localDofIdx)
1891 -> void
1892 {
1893 const auto& elementMapper = this->model().elementMapper();
1894
1895 unsigned globalElemIdx = elementMapper.index(stencil.entity(localDofIdx));
1896 if (localDofIdx != 0) {
1897 unsigned globalCenterElemIdx = elementMapper.index(stencil.entity(/*dofIdx=*/0));
1898 dofData.transmissibility = transmissibilities_.transmissibility(globalCenterElemIdx, globalElemIdx);
1899
1900 if constexpr (enableFullyImplicitThermal) {
1901 *dofData.thermalHalfTransIn = transmissibilities_.thermalHalfTrans(globalCenterElemIdx, globalElemIdx);
1902 *dofData.thermalHalfTransOut = transmissibilities_.thermalHalfTrans(globalElemIdx, globalCenterElemIdx);
1903 }
1904 if constexpr (enableDiffusion)
1905 *dofData.diffusivity = transmissibilities_.diffusivity(globalCenterElemIdx, globalElemIdx);
1906 if (enableDispersion)
1907 dofData.dispersivity = transmissibilities_.dispersivity(globalCenterElemIdx, globalElemIdx);
1908 }
1909 };
1910
1911 pffDofData_.update(distFn);
1912 }
1913
1914 virtual void updateExplicitQuantities_(int episodeIdx, int timeStepSize, bool first_step_after_restart) = 0;
1915
1917 {
1918 const auto& simulator = this->simulator();
1919 const auto& vanguard = simulator.vanguard();
1920 const auto& bcconfig = vanguard.eclState().getSimulationConfig().bcconfig();
1921 if (bcconfig.size() > 0) {
1922 nonTrivialBoundaryConditions_ = true;
1923
1924 std::size_t numCartDof = vanguard.cartesianSize();
1925 unsigned numElems = vanguard.gridView().size(/*codim=*/0);
1926 std::vector<int> cartesianToCompressedElemIdx(numCartDof, -1);
1927
1928 for (unsigned elemIdx = 0; elemIdx < numElems; ++elemIdx)
1929 cartesianToCompressedElemIdx[vanguard.cartesianIndex(elemIdx)] = elemIdx;
1930
1931 bcindex_.resize(numElems, 0);
1932 auto loopAndApply = [&cartesianToCompressedElemIdx,
1933 &vanguard](const auto& bcface,
1934 auto apply)
1935 {
1936 for (int i = bcface.i1; i <= bcface.i2; ++i) {
1937 for (int j = bcface.j1; j <= bcface.j2; ++j) {
1938 for (int k = bcface.k1; k <= bcface.k2; ++k) {
1939 std::array<int, 3> tmp = {i,j,k};
1940 auto elemIdx = cartesianToCompressedElemIdx[vanguard.cartesianIndex(tmp)];
1941 if (elemIdx >= 0)
1942 apply(elemIdx);
1943 }
1944 }
1945 }
1946 };
1947 for (const auto& bcface : bcconfig) {
1948 std::vector<int>& data = bcindex_(bcface.dir);
1949 const int index = bcface.index;
1950 loopAndApply(bcface,
1951 [&data,index](int elemIdx)
1952 { data[elemIdx] = index; });
1953 }
1954 }
1955 }
1956
1957 // this method applies the runtime constraints specified via the deck and/or command
1958 // line parameters for the size of the next time step.
1960 {
1961 if constexpr (enableExperiments) {
1962 const auto& simulator = this->simulator();
1963 const auto& schedule = simulator.vanguard().schedule();
1964 int episodeIdx = simulator.episodeIndex();
1965
1966 // first thing in the morning, limit the time step size to the maximum size
1967 Scalar maxTimeStepSize = Parameters::Get<Parameters::SolverMaxTimeStepInDays<Scalar>>() * 24 * 60 * 60;
1968 int reportStepIdx = std::max(episodeIdx, 0);
1969 if (this->enableTuning_) {
1970 const auto& tuning = schedule[reportStepIdx].tuning();
1971 maxTimeStepSize = tuning.TSMAXZ;
1972 }
1973
1974 dtNext = std::min(dtNext, maxTimeStepSize);
1975
1976 Scalar remainingEpisodeTime =
1977 simulator.episodeStartTime() + simulator.episodeLength()
1978 - (simulator.startTime() + simulator.time());
1979 assert(remainingEpisodeTime >= 0.0);
1980
1981 // if we would have a small amount of time left over in the current episode, make
1982 // two equal time steps instead of a big and a small one
1983 if (remainingEpisodeTime/2.0 < dtNext && dtNext < remainingEpisodeTime*(1.0 - 1e-5))
1984 // note: limiting to the maximum time step size here is probably not strictly
1985 // necessary, but it should not hurt and is more fool-proof
1986 dtNext = std::min(maxTimeStepSize, remainingEpisodeTime/2.0);
1987
1988 if (simulator.episodeStarts()) {
1989 // if a well event occurred, respect the limit for the maximum time step after
1990 // that, too
1991 const auto& events = simulator.vanguard().schedule()[reportStepIdx].events();
1992 bool wellEventOccured =
1993 events.hasEvent(ScheduleEvents::NEW_WELL)
1994 || events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE)
1995 || events.hasEvent(ScheduleEvents::INJECTION_UPDATE)
1996 || events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
1997 if (episodeIdx >= 0 && wellEventOccured && this->maxTimeStepAfterWellEvent_ > 0)
1998 dtNext = std::min(dtNext, this->maxTimeStepAfterWellEvent_);
1999 }
2000 }
2001
2002 return dtNext;
2003 }
2004
2006 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2007 return oilPhaseIdx;
2008 }
2009 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2010 return gasPhaseIdx;
2011 }
2012 else {
2013 return waterPhaseIdx;
2014 }
2015 }
2016
2018 {
2019 const auto& model = this->simulator().model();
2020 std::size_t numGridDof = this->model().numGridDof();
2021 this->rockCompTransMultVal_.resize(numGridDof, 1.0);
2022 for (std::size_t elementIdx = 0; elementIdx < numGridDof; ++elementIdx) {
2023 const auto& iq = model.intensiveQuantities(elementIdx, /*timeIdx=*/ 0);
2024 Scalar trans_mult = computeRockCompTransMultiplier_<Scalar>(iq, elementIdx);
2025 this->rockCompTransMultVal_[elementIdx] = trans_mult;
2026 }
2027 }
2028
2034 template <class LhsEval>
2035 LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities& intQuants, unsigned elementIdx) const
2036 {
2037 auto obtain = [](const auto& value)
2038 {
2039 if constexpr (std::is_same_v<LhsEval, Scalar>) {
2040 return getValue(value);
2041 } else {
2042 return value;
2043 }
2044 };
2045
2046 return computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain);
2047 }
2048
2049 template <class LhsEval, class Callback>
2050 LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
2051 {
2052 OPM_TIMEBLOCK_LOCAL(computeRockCompTransMultiplier, Subsystem::PvtProps);
2053 if (this->rockCompTransMult_.empty() && this->rockCompTransMultWc_.empty())
2054 return 1.0;
2055
2056 unsigned tableIdx = 0;
2057 if (!this->rockTableIdx_.empty())
2058 tableIdx = this->rockTableIdx_[elementIdx];
2059
2060 const auto& fs = intQuants.fluidState();
2061 const auto& rock_config = this->simulator().vanguard().eclState().getSimulationConfig().rock_config();
2062
2063 if (!this->rockCompTransMultElastic_.empty()) {
2064 // ROCKCOMP HYSTERESIS=HYSTER: see rockCompPoroMultiplier() above.
2065 LhsEval effectivePressure = obtain(fs.pressure(refPressurePhaseIdx_()));
2066 LhsEval turningPressure = this->minRefPressure_[elementIdx];
2067
2068 if (!this->overburdenPressure_.empty()) {
2069 effectivePressure -= this->overburdenPressure_[elementIdx];
2070 turningPressure -= this->overburdenPressure_[elementIdx];
2071 }
2072
2073 if (rock_config.store()) {
2074 const auto& initialPressure = asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
2075 effectivePressure -= initialPressure;
2076 turningPressure -= initialPressure;
2077 }
2078
2079 if (effectivePressure <= turningPressure)
2080 return this->rockCompTransMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
2081
2082 return this->rockCompTransMultElastic_[tableIdx].eval(turningPressure, effectivePressure, /*extrapolation=*/true);
2083 }
2084
2085 LhsEval effectivePressure = obtain(fs.pressure(refPressurePhaseIdx_()));
2086 if (!this->minRefPressure_.empty())
2087 // The pore space change is irreversible
2088 effectivePressure =
2089 min(obtain(fs.pressure(refPressurePhaseIdx_())),
2090 this->minRefPressure_[elementIdx]);
2091
2092 if (!this->overburdenPressure_.empty())
2093 effectivePressure -= this->overburdenPressure_[elementIdx];
2094
2095 if (rock_config.store()) {
2096 effectivePressure -= asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
2097 }
2098
2099 if (!this->rockCompTransMult_.empty())
2100 return this->rockCompTransMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
2101
2102 // water compaction
2103 assert(!this->rockCompTransMultWc_.empty());
2104 LhsEval SwMax = max(obtain(fs.saturation(waterPhaseIdx)), this->maxWaterSaturation_[elementIdx]);
2105 LhsEval SwDeltaMax = SwMax - asImp_().initialFluidStates()[elementIdx].saturation(waterPhaseIdx);
2106
2107 return this->rockCompTransMultWc_[tableIdx].eval(effectivePressure, SwDeltaMax, /*extrapolation=*/true);
2108 }
2109
2110 typename Vanguard::TransmissibilityType transmissibilities_;
2111
2112 std::shared_ptr<EclMaterialLawManager> materialLawManager_;
2113 std::shared_ptr<EclThermalLawManager> thermalLawManager_;
2114
2116
2119
2123
2126
2127 template<class T>
2128 struct BCData
2129 {
2130 std::array<std::vector<T>,6> data;
2131
2132 void resize(std::size_t size, T defVal)
2133 {
2134 for (auto& d : data)
2135 d.resize(size, defVal);
2136 }
2137
2138 const std::vector<T>& operator()(FaceDir::DirEnum dir) const
2139 {
2140 if (dir == FaceDir::DirEnum::Unknown)
2141 throw std::runtime_error("Tried to access BC data for the 'Unknown' direction");
2142 int idx = 0;
2143 int div = static_cast<int>(dir);
2144 while ((div /= 2) >= 1)
2145 ++idx;
2146 assert(idx >= 0 && idx <= 5);
2147 return data[idx];
2148 }
2149
2150 std::vector<T>& operator()(FaceDir::DirEnum dir)
2151 {
2152 return const_cast<std::vector<T>&>(std::as_const(*this)(dir));
2153 }
2154 };
2155
2156 virtual void handleSolventBC(const BCState::BCFace&, RateVector&) const = 0;
2157
2158 virtual void handlePolymerBC(const BCState::BCFace&, RateVector&) const = 0;
2159
2160 virtual void handleMicrBC(const BCState::BCFace&, RateVector&) const = 0;
2161
2162 virtual void handleOxygBC(const BCState::BCFace&, RateVector&) const = 0;
2163
2164 virtual void handleUreaBC(const BCState::BCFace&, RateVector&) const = 0;
2165
2167 bool nonTrivialBoundaryConditions_ = false;
2168 bool first_step_ = true;
2169 bool enable_state_rollback_ = false;
2170
2178 {
2179 bool first_step = true;
2180 std::vector<Scalar> max_polymer_adsorption;
2181 std::vector<Scalar> max_oil_saturation;
2182 std::vector<Scalar> max_water_saturation;
2183 std::vector<Scalar> min_ref_pressure;
2184 std::vector<Scalar> rock_comp_trans_mult_val;
2185 };
2186
2188
2191 virtual bool episodeWillBeOver() const
2192 {
2193 return this->simulator().episodeWillBeOver();
2194 }
2195};
2196
2197} // namespace Opm
2198
2199#endif // OPM_FLOW_PROBLEM_HPP
#define OPM_END_PARALLEL_TRY_CATCH(prefix, comm)
Catch exception and throw in a parallel try-catch clause.
Definition: DeferredLoggingErrorHelpers.hpp:197
#define OPM_BEGIN_PARALLEL_TRY_CATCH()
Macro to setup the try of a parallel try-catch.
Definition: DeferredLoggingErrorHelpers.hpp:160
Classes required for dynamic convective mixing.
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowGenericProblem.hpp:61
Scalar maxPolymerAdsorption(unsigned elemIdx) const
Returns the max polymer adsorption value.
Definition: FlowGenericProblem_impl.hpp:963
unsigned pvtRegionIndex(unsigned elemIdx) const
Returns the index the relevant PVT region given a cell index.
Definition: FlowGenericProblem_impl.hpp:922
Scalar rockBiotTemp(unsigned elementIdx) const
Returns the rock compressibility of an element due to thermoelasticity.
Definition: FlowGenericProblem_impl.hpp:420
std::array< std::vector< Scalar >, 2 > rockFraction_
Definition: FlowGenericProblem.hpp:362
std::vector< TabulatedTwoDFunction > rockCompPoroMultWc_
Definition: FlowGenericProblem.hpp:371
Scalar porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
Direct indexed access to the porosity.
Definition: FlowGenericProblem_impl.hpp:401
Scalar rockCompressibility(unsigned globalSpaceIdx) const
Definition: FlowGenericProblem_impl.hpp:386
unsigned miscnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant MISC region given a cell index.
Definition: FlowGenericProblem_impl.hpp:942
unsigned satnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant saturation function region given a cell index.
Definition: FlowGenericProblem_impl.hpp:932
Scalar lame(unsigned elementIdx) const
Direct access to Lame's second parameter in an element.
Definition: FlowGenericProblem_impl.hpp:432
void beginTimeStep_(bool enableExperiments, int episodeIdx, int timeStepIndex, Scalar startTime, Scalar time, Scalar timeStepSize, Scalar endTime)
Definition: FlowGenericProblem_impl.hpp:658
std::vector< TabulatedTwoDFunction > rockCompPoroMultElastic_
Definition: FlowGenericProblem.hpp:379
unsigned plmixnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant PLMIXNUM (for polymer module) region given a cell index.
Definition: FlowGenericProblem_impl.hpp:952
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:156
std::array< std::vector< Scalar >, 2 > referencePorosity_
Definition: FlowGenericProblem.hpp:361
Scalar rockBiotComp(unsigned elementIdx) const
Returns the rock compressibility of an element due to poroelasticity.
Definition: FlowGenericProblem_impl.hpp:409
bool beginEpisode_(bool enableExperiments, int episodeIdx)
Definition: FlowGenericProblem_impl.hpp:621
bool shouldWriteOutput() const
Always returns true. The ecl output writer takes care of the rest.
Definition: FlowGenericProblem.hpp:318
static std::string helpPreamble(int, const char **argv)
Definition: FlowGenericProblem_impl.hpp:134
Scalar biotTemp(unsigned elementIdx) const
Direct access to Biot temperature coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:484
bool shouldWriteRestartFile() const
Returns true if an eWoms restart file should be written to disk.
Definition: FlowGenericProblem.hpp:327
Scalar biotCoeff(unsigned elementIdx) const
Direct access to Biot coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:463
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblem.hpp:101
virtual bool episodeWillBeOver() const
Definition: FlowProblem.hpp:2191
const WellModel & wellModel() const
Returns a reference to the ECL well manager used by the problem.
Definition: FlowProblem.hpp:1158
GetPropType< TypeTag, Properties::Evaluation > Evaluation
Definition: FlowProblem.hpp:166
Scalar transmissibility(unsigned globalCenterElemIdx, unsigned globalElemIdx) const
Direct access to the transmissibility between two elements.
Definition: FlowProblem.hpp:592
static constexpr bool enableFoam
Definition: FlowProblem.hpp:132
Scalar thresholdPressure(unsigned elem1Idx, unsigned elem2Idx) const
Threshold pressure [Pa] for the intersection between two elements.
Definition: FlowProblem.hpp:600
static int handlePositionalParameter(std::function< void(const std::string &, const std::string &)> addKey, std::set< std::string > &seenParams, std::string &errorMsg, int, const char **argv, int paramIdx, int)
Handles positional command line parameters.
Definition: FlowProblem.hpp:216
bool nonTrivialBoundaryConditions() const
Definition: FlowProblem.hpp:1170
const GlobalEqVector & drift() const
Definition: FlowProblem.hpp:1377
virtual void writeOutput(bool verbose)
Write the requested quantities of the current solution into the output files.
Definition: FlowProblem.hpp:544
virtual void handleOxygBC(const BCState::BCFace &, RateVector &) const =0
std::function< std::vector< IntType >(const FieldPropsManager &, const std::string &, bool)> fieldPropIntTypeOnLeafAssigner_()
Definition: FlowProblem.hpp:1668
const DimMatrix & intrinsicPermeability(unsigned globalElemIdx) const
This method returns the intrinsic permeability tensor given a global element index.
Definition: FlowProblem.hpp:574
unsigned pvtRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:966
LhsEval wellTransMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx, Callback &obtain) const
Definition: FlowProblem.hpp:1298
Scalar porosity(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:742
virtual void handlePolymerBC(const BCState::BCFace &, RateVector &) const =0
void beginIteration()
Called by the simulator before each Newton-Raphson iteration.
Definition: FlowProblem.hpp:442
virtual void restoreBeginTimeStepState_()
Put the explicit quantities back as they were before the step.
Definition: FlowProblem.hpp:1410
GetPropType< TypeTag, Properties::Vanguard > Vanguard
Definition: FlowProblem.hpp:114
GetPropType< TypeTag, Properties::DofMapper > DofMapper
Definition: FlowProblem.hpp:165
Scalar rockBiotComp(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:786
@ numComponents
Definition: FlowProblem.hpp:124
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: FlowProblem.hpp:108
typename EclThermalLawManager::SolidEnergyLawParams SolidEnergyLawParams
Definition: FlowProblem.hpp:162
bool updateHysteresis_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1838
GetPropType< TypeTag, Properties::BaseProblem > ParentType
Definition: FlowProblem.hpp:105
void initGravity_(const EclipseState &eclState)
Set the gravity vector from the run's configuration.
Definition: FlowProblem.hpp:1863
GetPropType< TypeTag, Properties::EqVector > EqVector
Definition: FlowProblem.hpp:113
unsigned satnumRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:974
virtual void updateExplicitQuantities_(int episodeIdx, int timeStepSize, bool first_step_after_restart)=0
Scalar thermalHalfTransmissibilityOut(const Context &context, unsigned faceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:697
bool first_step_
Definition: FlowProblem.hpp:2168
GetPropType< TypeTag, Properties::ElementContext > ElementContext
Definition: FlowProblem.hpp:158
const ThermalConductionLawParams & thermalConductionLawParams(unsigned globalSpaceIdx, unsigned) const
Definition: FlowProblem.hpp:1041
AquiferModel aquiferModel_
Definition: FlowProblem.hpp:2118
GlobalEqVector drift_
Definition: FlowProblem.hpp:2115
bool updateMinPressure_()
Definition: FlowProblem.hpp:1620
std::function< std::vector< double >(const FieldPropsManager &, const std::string &)> fieldPropDoubleOnLeafAssigner_()
Definition: FlowProblem.hpp:1653
virtual void handleSolventBC(const BCState::BCFace &, RateVector &) const =0
@ gasCompIdx
Definition: FlowProblem.hpp:150
Scalar transmissibilityBoundary(const Context &elemCtx, unsigned boundaryFaceIdx) const
Definition: FlowProblem.hpp:654
GetPropType< TypeTag, Properties::RateVector > RateVector
Definition: FlowProblem.hpp:155
void updateReferencePorosity_()
Definition: FlowProblem.hpp:1734
Scalar thermalHalfTransmissibility(const unsigned globalSpaceIdxIn, const unsigned globalSpaceIdxOut) const
Definition: FlowProblem.hpp:674
LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities &intQuants, unsigned elementIdx, Callback &obtain) const
Definition: FlowProblem.hpp:2050
BCData< int > bcindex_
Definition: FlowProblem.hpp:2166
GetPropType< TypeTag, Properties::TracerModel > TracerModel
Definition: FlowProblem.hpp:175
Scalar rockCompressibility(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:776
bool updateMaxWaterSaturation_()
Definition: FlowProblem.hpp:1590
virtual void handleUreaBC(const BCState::BCFace &, RateVector &) const =0
FlowThresholdPressure< TypeTag > thresholdPressures_
Definition: FlowProblem.hpp:2124
Dune::FieldMatrix< Scalar, dimWorld, dimWorld > DimMatrix
Definition: FlowProblem.hpp:172
@ waterPhaseIdx
Definition: FlowProblem.hpp:146
const EclMaterialLawManager & materialLawManagerRef() const
Definition: FlowProblem.hpp:918
void advanceTimeLevel()
Called by the simulator to accept the current state as the new time level after a successful timestep...
Definition: FlowProblem.hpp:433
Scalar maxOilSaturation(unsigned globalDofIdx) const
Returns an element's historic maximum oil phase saturation that was observed during the simulation.
Definition: FlowProblem.hpp:1056
bool updateMinPressure_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1635
std::string name() const
The problem name.
Definition: FlowProblem.hpp:1005
int episodeIndex() const
Definition: FlowProblem.hpp:315
Scalar biotTemp(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:826
LhsEval rockCompTransMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx) const
Calculate the transmissibility multiplier due to water induced rock compaction.
Definition: FlowProblem.hpp:1276
void endIteration()
Called by the simulator after each Newton-Raphson iteration.
Definition: FlowProblem.hpp:452
GetPropType< TypeTag, Properties::Indices > Indices
Definition: FlowProblem.hpp:115
FlowProblem(Simulator &simulator)
Definition: FlowProblem.hpp:235
ModuleParams moduleParams_
Definition: FlowProblem.hpp:2125
@ enableFullyImplicitThermal
Definition: FlowProblem.hpp:138
GetPropType< TypeTag, Properties::GlobalEqVector > GlobalEqVector
Definition: FlowProblem.hpp:112
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: FlowProblem.hpp:156
const Vanguard::TransmissibilityType & eclTransmissibilities() const
Return a reference to the object that handles the "raw" transmissibilities.
Definition: FlowProblem.hpp:720
void source(RateVector &rate, unsigned globalDofIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:1126
@ enableExperiments
Definition: FlowProblem.hpp:139
virtual void readEquilInitialCondition_()=0
Scalar nextTimeStepSize() const
Propose the size of the next time step to the simulator.
Definition: FlowProblem.hpp:1179
LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities &intQuants, unsigned elementIdx) const
Calculate the transmissibility multiplier due to water induced rock compaction.
Definition: FlowProblem.hpp:2035
std::pair< BCType, RateVector > boundaryCondition(const unsigned int globalSpaceIdx, const int directionId) const
Definition: FlowProblem.hpp:1310
typename EclMaterialLawManager::MaterialLawParams MaterialLawParams
Definition: FlowProblem.hpp:161
static constexpr bool enableDiffusion
Definition: FlowProblem.hpp:129
virtual ~FlowProblem()=default
PffGridVector< GridView, Stencil, PffDofData_, DofMapper > pffDofData_
Definition: FlowProblem.hpp:2120
@ dimWorld
Definition: FlowProblem.hpp:119
const FlowThresholdPressure< TypeTag > & thresholdPressure() const
Definition: FlowProblem.hpp:603
const ThermalConductionLawParams & thermalConductionLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:902
Scalar transmissibility(const Context &context, unsigned fromDofLocalIdx, unsigned toDofLocalIdx) const
Definition: FlowProblem.hpp:581
TracerModel tracerModel_
Definition: FlowProblem.hpp:2121
@ enableThermalFluxBoundaries
Definition: FlowProblem.hpp:142
const TracerModel & tracerModel() const
Definition: FlowProblem.hpp:724
WellModel wellModel_
Definition: FlowProblem.hpp:2117
virtual void beginEpisode()
Called by the simulator before an episode begins.
Definition: FlowProblem.hpp:323
const SolidEnergyLawParams & solidEnergyLawParams(unsigned globalSpaceIdx, unsigned) const
Definition: FlowProblem.hpp:1035
virtual void captureBeginTimeStepState_()
Snapshot the explicit quantities before the timestep runs.
Definition: FlowProblem.hpp:1396
static constexpr bool enablePolymerMolarWeight
Definition: FlowProblem.hpp:134
Scalar getRockCompTransMultVal(std::size_t dofIdx) const
Definition: FlowProblem.hpp:1846
virtual void beginTimeStep()
Called by the simulator before each time integration.
Definition: FlowProblem.hpp:382
@ gasPhaseIdx
Definition: FlowProblem.hpp:144
Scalar dofCenterDepth(unsigned globalSpaceIdx) const
Direct indexed acces to the depth of an degree of freedom [m].
Definition: FlowProblem.hpp:767
typename GetProp< TypeTag, Properties::MaterialLaw >::EclMaterialLawManager EclMaterialLawManager
Definition: FlowProblem.hpp:159
static constexpr bool enableSolvent
Definition: FlowProblem.hpp:135
const MaterialLawParams & materialLawParams(unsigned globalDofIdx, FaceDir::DirEnum facedir) const
Definition: FlowProblem.hpp:879
std::shared_ptr< const EclMaterialLawManager > materialLawManager() const
Returns the ECL material law manager.
Definition: FlowProblem.hpp:914
unsigned plmixnumRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:990
const MaterialLawParams & materialLawParams(unsigned globalDofIdx) const
Definition: FlowProblem.hpp:874
Scalar temperature(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:1012
Scalar thermalHalfTransmissibilityBoundary(const Context &elemCtx, unsigned boundaryFaceIdx) const
Definition: FlowProblem.hpp:710
unsigned miscnumRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:982
void updateRockCompTransMultVal_()
Definition: FlowProblem.hpp:2017
@ numPhases
Definition: FlowProblem.hpp:123
std::shared_ptr< EclThermalLawManager > thermalLawManager_
Definition: FlowProblem.hpp:2113
Scalar limitNextTimeStepSize_(Scalar dtNext) const
Definition: FlowProblem.hpp:1959
void finishTransmissibilities_()
Definition: FlowProblem.hpp:1423
GetPropType< TypeTag, Properties::Stencil > Stencil
Definition: FlowProblem.hpp:110
typename GetProp< TypeTag, Properties::SolidEnergyLaw >::EclThermalLawManager EclThermalLawManager
Definition: FlowProblem.hpp:160
FlowThresholdPressure< TypeTag > & thresholdPressure()
Definition: FlowProblem.hpp:606
virtual void readExplicitInitialCondition_()=0
static constexpr bool enablePolymer
Definition: FlowProblem.hpp:133
GetPropType< TypeTag, Properties::WellModel > WellModel
Definition: FlowProblem.hpp:168
@ numEq
Definition: FlowProblem.hpp:122
const DimMatrix & intrinsicPermeability(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:560
PrevTimestepState prev_timestep_state_
Definition: FlowProblem.hpp:2187
void updateFailed()
Called by the simulator to restore the state captured at the beginning of the timestep after a failed...
Definition: FlowProblem.hpp:420
bool updateHysteresis_()
Definition: FlowProblem.hpp:1822
void readThermalParameters_()
Definition: FlowProblem.hpp:1717
void serializeOp(Serializer &serializer)
Definition: FlowProblem.hpp:1365
Scalar maxPolymerAdsorption(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the max polymer adsorption value.
Definition: FlowProblem.hpp:999
Scalar thermalHalfTransmissibilityIn(const Context &context, unsigned faceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:684
void setMaxOilSaturation(unsigned globalDofIdx, Scalar value)
Sets an element's maximum oil phase saturation observed during the simulation.
Definition: FlowProblem.hpp:1073
const SolidEnergyLawParams & solidEnergyLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Return the parameters for the energy storage law of the rock.
Definition: FlowProblem.hpp:889
typename EclThermalLawManager::ThermalConductionLawParams ThermalConductionLawParams
Definition: FlowProblem.hpp:163
Scalar dispersivity(const unsigned globalCellIn, const unsigned globalCellOut) const
Definition: FlowProblem.hpp:634
AquiferModel & mutableAquiferModel()
Definition: FlowProblem.hpp:1167
@ dim
Definition: FlowProblem.hpp:118
GetPropType< TypeTag, Properties::IntensiveQuantities > IntensiveQuantities
Definition: FlowProblem.hpp:167
Scalar temperature(unsigned globalDofIdx, unsigned) const
Definition: FlowProblem.hpp:1024
Scalar lame(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:806
Scalar rockBiotTemp(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:796
@ enableSaltPrecipitation
Definition: FlowProblem.hpp:141
GetPropType< TypeTag, Properties::AquiferModel > AquiferModel
Definition: FlowProblem.hpp:169
TemperatureModel temperatureModel_
Definition: FlowProblem.hpp:2122
static constexpr bool enableExtbo
Definition: FlowProblem.hpp:131
std::shared_ptr< EclMaterialLawManager > materialLawManager_
Definition: FlowProblem.hpp:2112
WellModel & wellModel()
Definition: FlowProblem.hpp:1161
const ModuleParams & moduleParams() const
Definition: FlowProblem.hpp:609
static constexpr bool enableConvectiveMixing
Definition: FlowProblem.hpp:128
GetPropType< TypeTag, Properties::GridView > GridView
Definition: FlowProblem.hpp:109
GetPropType< TypeTag, Properties::TemperatureModel > TemperatureModel
Definition: FlowProblem.hpp:174
void updateProperty_(const std::string &failureMsg, UpdateFunc func)
Definition: FlowProblem.hpp:1539
bool prepareTransmissibilityOutput_(EclWriterType &eclWriter, const bool enableEclOutput)
Definition: FlowProblem.hpp:1432
LhsEval rockCompTransMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx, Callback &obtain) const
Definition: FlowProblem.hpp:1290
@ oilCompIdx
Definition: FlowProblem.hpp:151
void initializeSimulatorTime_()
Definition: FlowProblem.hpp:1491
bool updateMaxOilSaturation_()
Definition: FlowProblem.hpp:1558
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblem.hpp:200
void updatePffDofData_()
Definition: FlowProblem.hpp:1885
static constexpr bool enableDispersion
Definition: FlowProblem.hpp:130
virtual void endEpisode()
Called by the simulator after the end of an episode.
Definition: FlowProblem.hpp:521
@ oilPhaseIdx
Definition: FlowProblem.hpp:145
GetPropType< TypeTag, Properties::PrimaryVariables > PrimaryVariables
Definition: FlowProblem.hpp:154
bool nonTrivialBoundaryConditions_
Definition: FlowProblem.hpp:2167
GetPropType< TypeTag, Properties::Problem > Implementation
Definition: FlowProblem.hpp:106
void readBoundaryConditions_()
Definition: FlowProblem.hpp:1916
void updateRelperms(std::array< Evaluation, numPhases > &mobility, DirectionalMobilityPtr &dirMob, FluidState &fluidState, unsigned globalSpaceIdx) const
Definition: FlowProblem.hpp:925
Vanguard::TransmissibilityType transmissibilities_
Definition: FlowProblem.hpp:2110
void source(RateVector &rate, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: FlowProblem.hpp:1117
virtual void addToSourceDense(RateVector &rate, unsigned globalDofIdx, unsigned timeIdx) const =0
virtual void endTimeStep()
Called by the simulator after each time integration.
Definition: FlowProblem.hpp:462
TemperatureModel & temperatureModel()
Definition: FlowProblem.hpp:730
Utility::CopyablePtr< DirectionalMobility< TypeTag > > DirectionalMobilityPtr
Definition: FlowProblem.hpp:176
virtual void readInitialCondition_()
Definition: FlowProblem.hpp:1793
virtual void initialSolutionApplied()
Callback used by the model to indicate that the initial solution has been determined for all degrees ...
Definition: FlowProblem.hpp:1084
const MaterialLawParams & materialLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:867
Scalar thermalTransmissibilityBoundary(const unsigned globalSpaceIdx, const unsigned boundaryFaceIdx) const
Direct access to a boundary transmissibility.
Definition: FlowProblem.hpp:641
static constexpr EnergyModules energyModuleType
Definition: FlowProblem.hpp:137
Scalar diffusivity(const Context &context, unsigned fromDofLocalIdx, unsigned toDofLocalIdx) const
Definition: FlowProblem.hpp:616
Scalar rockReferencePressure(unsigned globalSpaceIdx) const
Definition: FlowProblem.hpp:845
std::string extraTrailerSummary() const
Definition: FlowProblem.hpp:183
void deserialize(Restarter &res)
This method restores the complete state of the problem and its sub-objects from disk.
Definition: FlowProblem.hpp:289
bool enable_state_rollback_
Definition: FlowProblem.hpp:2169
Scalar biotCoeff(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:816
std::shared_ptr< EclMaterialLawManager > materialLawManager()
Definition: FlowProblem.hpp:958
std::shared_ptr< const EclThermalLawManager > thermalLawManager() const
Definition: FlowProblem.hpp:921
bool updateMaxWaterSaturation_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1606
typename GridView::template Codim< 0 >::Entity Element
Definition: FlowProblem.hpp:157
Scalar dofCenterDepth(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the depth of an degree of freedom [m].
Definition: FlowProblem.hpp:755
bool updateMaxOilSaturation_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1576
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: FlowProblem.hpp:111
GetPropType< TypeTag, Properties::MaterialLaw > MaterialLaw
Definition: FlowProblem.hpp:164
const AquiferModel & aquiferModel() const
Definition: FlowProblem.hpp:1164
void initializeModelProperties_()
Definition: FlowProblem.hpp:1515
int refPressurePhaseIdx_() const
Definition: FlowProblem.hpp:2005
static constexpr bool enableBioeffects
Definition: FlowProblem.hpp:126
LhsEval rockCompPoroMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx) const
Calculate the porosity multiplier due to water induced rock compaction.
Definition: FlowProblem.hpp:1206
Scalar transmissibilityBoundary(const unsigned globalSpaceIdx, const unsigned boundaryFaceIdx) const
Direct access to a boundary transmissibility.
Definition: FlowProblem.hpp:664
TracerModel & tracerModel()
Definition: FlowProblem.hpp:727
void readMaterialParameters_()
Definition: FlowProblem.hpp:1677
static constexpr bool enableBrine
Definition: FlowProblem.hpp:127
void serialize(Restarter &res)
This method writes the complete state of the problem and its subobjects to disk.
Definition: FlowProblem.hpp:308
MathToolbox< Evaluation > Toolbox
Definition: FlowProblem.hpp:171
@ waterCompIdx
Definition: FlowProblem.hpp:152
virtual void handleMicrBC(const BCState::BCFace &, RateVector &) const =0
Scalar rockReferencePressure(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:836
Scalar diffusivity(const unsigned globalCellIn, const unsigned globalCellOut) const
Definition: FlowProblem.hpp:627
@ enableMICP
Definition: FlowProblem.hpp:140
void updateRockFraction_()
Definition: FlowProblem.hpp:1759
void prefetch(const Element &elem) const
Definition: FlowProblem.hpp:274
This class calculates the threshold pressure for grid faces according to the Eclipse Reference Manual...
Definition: FlowThresholdPressure.hpp:59
A random-access container which stores data attached to a grid's degrees of freedom in a prefetch fri...
Definition: pffgridvector.hh:50
Definition: RelpermDiagnostics.hpp:51
void diagnosis(const EclipseState &eclState, const LevelCartesianIndexMapper &levelCartesianIndexMapper)
This file contains definitions related to directional mobilities.
@ NONE
Definition: DeferredLogger.hpp:46
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition: parametersystem.hpp:192
static constexpr int dim
Definition: structuredgridvanguard.hh:68
int eclPositionalParameter(std::function< void(const std::string &, const std::string &)> addKey, std::set< std::string > &seenParams, std::string &errorMsg, const char **argv, int paramIdx)
Definition: blackoilbioeffectsmodules.hh:45
GatheredLgrOutputTrans gatherLgrOutputTrans(const Dune::CpGrid &grid, const GridView &gridView, TransFn &&transFn)
Definition: LgrOutputTransGather.hpp:118
void eclBroadcast(Parallel::Communication, T &)
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:224
Definition: FlowProblem.hpp:2129
const std::vector< T > & operator()(FaceDir::DirEnum dir) const
Definition: FlowProblem.hpp:2138
void resize(std::size_t size, T defVal)
Definition: FlowProblem.hpp:2132
std::vector< T > & operator()(FaceDir::DirEnum dir)
Definition: FlowProblem.hpp:2150
std::array< std::vector< T >, 6 > data
Definition: FlowProblem.hpp:2130
Definition: FlowProblem.hpp:1876
ConditionalStorage< enableFullyImplicitThermal, Scalar > thermalHalfTransOut
Definition: FlowProblem.hpp:1878
ConditionalStorage< enableFullyImplicitThermal, Scalar > thermalHalfTransIn
Definition: FlowProblem.hpp:1877
ConditionalStorage< enableDiffusion, Scalar > diffusivity
Definition: FlowProblem.hpp:1879
ConditionalStorage< enableDispersion, Scalar > dispersivity
Definition: FlowProblem.hpp:1880
Scalar transmissibility
Definition: FlowProblem.hpp:1881
Explicit quantities as they stood at the start of the current timestep, restored if that timestep fai...
Definition: FlowProblem.hpp:2178
bool first_step
first step of the episode
Definition: FlowProblem.hpp:2179
std::vector< Scalar > min_ref_pressure
ROCKCOMP irreversible compaction.
Definition: FlowProblem.hpp:2183
std::vector< Scalar > rock_comp_trans_mult_val
ROCKCOMP transmissibility multiplier.
Definition: FlowProblem.hpp:2184
std::vector< Scalar > max_polymer_adsorption
POLYMER.
Definition: FlowProblem.hpp:2180
std::vector< Scalar > max_water_saturation
ROCKCOMP water-induced compaction.
Definition: FlowProblem.hpp:2182
std::vector< Scalar > max_oil_saturation
VAPPARS / DRSDT saturation history.
Definition: FlowProblem.hpp:2181