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 std::shared_ptr<const EclThermalLawManager> thermalLawManager() const
918 { return thermalLawManager_; }
919
920 template <class FluidState, class ...Args>
922 std::array<Evaluation,numPhases> &mobility,
924 FluidState &fluidState,
925 unsigned globalSpaceIdx) const
926 {
927 using ContainerT = std::array<Evaluation, numPhases>;
928 OPM_TIMEBLOCK_LOCAL(updateRelperms, Subsystem::SatProps);
929 {
930 // calculate relative permeabilities. note that we store the result into the
931 // mobility_ class attribute. the division by the phase viscosity happens later.
932 const auto& materialParams = materialLawParams(globalSpaceIdx);
933 MaterialLaw::template relativePermeabilities<ContainerT, FluidState, Args...>(mobility, materialParams, fluidState);
934 Valgrind::CheckDefined(mobility);
935 }
936 if (materialLawManager_->hasDirectionalRelperms()
937 || materialLawManager_->hasDirectionalImbnum())
938 {
939 using Dir = FaceDir::DirEnum;
940 constexpr int ndim = 3;
941 dirMob = std::make_unique<DirectionalMobility<TypeTag>>();
942 Dir facedirs[ndim] = {Dir::XPlus, Dir::YPlus, Dir::ZPlus};
943 for (int i = 0; i<ndim; i++) {
944 const auto& materialParams = materialLawParams(globalSpaceIdx, facedirs[i]);
945 auto& mob_array = dirMob->getArray(i);
946 MaterialLaw::template relativePermeabilities<ContainerT, FluidState, Args...>(mob_array, materialParams, fluidState);
947 }
948 }
949 }
950
954 std::shared_ptr<EclMaterialLawManager> materialLawManager()
955 { return materialLawManager_; }
956
961 template <class Context>
962 unsigned pvtRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
963 { return pvtRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
964
969 template <class Context>
970 unsigned satnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
971 { return this->satnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
972
977 template <class Context>
978 unsigned miscnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
979 { return this->miscnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
980
985 template <class Context>
986 unsigned plmixnumRegionIndex(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
987 { return this->plmixnumRegionIndex(context.globalSpaceIndex(spaceIdx, timeIdx)); }
988
989 // TODO: polymer related might need to go to the blackoil side
994 template <class Context>
995 Scalar maxPolymerAdsorption(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
996 { return this->maxPolymerAdsorption(context.globalSpaceIndex(spaceIdx, timeIdx)); }
997
1001 std::string name() const
1002 { return this->simulator().vanguard().caseName(); }
1003
1007 template <class Context>
1008 Scalar temperature(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
1009 {
1010 // use the initial temperature of the DOF if temperature is not a primary
1011 // variable
1012 unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
1013 if constexpr (energyModuleType == EnergyModules::SequentialImplicitThermal)
1014 return temperatureModel_.temperature(globalDofIdx);
1015
1016 return asImp_().initialFluidState(globalDofIdx).temperature(/*phaseIdx=*/0);
1017 }
1018
1019
1020 Scalar temperature(unsigned globalDofIdx, unsigned /*timeIdx*/) const
1021 {
1022 // use the initial temperature of the DOF if temperature is not a primary
1023 // variable
1024 if constexpr (energyModuleType == EnergyModules::SequentialImplicitThermal)
1025 return temperatureModel_.temperature(globalDofIdx);
1026
1027 return asImp_().initialFluidState(globalDofIdx).temperature(/*phaseIdx=*/0);
1028 }
1029
1031 solidEnergyLawParams(unsigned globalSpaceIdx,
1032 unsigned /*timeIdx*/) const
1033 {
1034 return this->thermalLawManager_->solidEnergyLawParams(globalSpaceIdx);
1035 }
1037 thermalConductionLawParams(unsigned globalSpaceIdx,
1038 unsigned /*timeIdx*/)const
1039 {
1040 return this->thermalLawManager_->thermalConductionLawParams(globalSpaceIdx);
1041 }
1042
1052 Scalar maxOilSaturation(unsigned globalDofIdx) const
1053 {
1054 if (!this->vapparsActive(this->episodeIndex()))
1055 return 0.0;
1056
1057 return this->maxOilSaturation_[globalDofIdx];
1058 }
1059
1069 void setMaxOilSaturation(unsigned globalDofIdx, Scalar value)
1070 {
1071 if (!this->vapparsActive(this->episodeIndex()))
1072 return;
1073
1074 this->maxOilSaturation_[globalDofIdx] = value;
1075 }
1076
1081 {
1082 // Calculate all intensive quantities.
1083 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx*/0);
1084
1085 // We also need the intensive quantities for timeIdx == 1
1086 // corresponding to the start of the current timestep, if we
1087 // do not use the storage cache, or if we cannot recycle the
1088 // first iteration storage.
1089 if (!this->model().enableStorageCache() || !this->recycleFirstIterationStorage()) {
1090 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx*/1);
1091 }
1092
1093 // initialize the wells. Note that this needs to be done after initializing the
1094 // intrinsic permeabilities and the after applying the initial solution because
1095 // the well model uses these...
1096 wellModel_.init();
1097
1098 aquiferModel_.initialSolutionApplied();
1099
1100 const bool invalidateFromHyst = updateHysteresis_();
1101 if (invalidateFromHyst) {
1102 OPM_TIMEBLOCK(beginTimeStepInvalidateIntensiveQuantities);
1103 this->model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
1104 }
1105 }
1106
1112 template <class Context>
1113 void source(RateVector& rate,
1114 const Context& context,
1115 unsigned spaceIdx,
1116 unsigned timeIdx) const
1117 {
1118 const unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
1119 source(rate, globalDofIdx, timeIdx);
1120 }
1121
1122 void source(RateVector& rate,
1123 unsigned globalDofIdx,
1124 unsigned timeIdx) const
1125 {
1126 OPM_TIMEBLOCK_LOCAL(eclProblemSource, Subsystem::Assembly);
1127 rate = 0.0;
1128
1129 // Add well contribution to source here.
1130 wellModel_.computeTotalRatesForDof(rate, globalDofIdx);
1131
1132 // convert the source term from the total mass rate of the
1133 // cell to the one per unit of volume as used by the model.
1134 for (unsigned eqIdx = 0; eqIdx < numEq; ++ eqIdx) {
1135 rate[eqIdx] /= this->model().dofTotalVolume(globalDofIdx);
1136
1137 Valgrind::CheckDefined(rate[eqIdx]);
1138 assert(isfinite(rate[eqIdx]));
1139 }
1140
1141 // Add non-well sources.
1142 addToSourceDense(rate, globalDofIdx, timeIdx);
1143 }
1144
1145 virtual void addToSourceDense(RateVector& rate,
1146 unsigned globalDofIdx,
1147 unsigned timeIdx) const = 0;
1148
1154 const WellModel& wellModel() const
1155 { return wellModel_; }
1156
1158 { return wellModel_; }
1159
1161 { return aquiferModel_; }
1162
1164 { return aquiferModel_; }
1165
1168
1176 {
1177 OPM_TIMEBLOCK(nexTimeStepSize);
1178 // allow external code to do the timestepping
1179 if (this->nextTimeStepSize_ > 0.0)
1180 return this->nextTimeStepSize_;
1181
1182 const auto& simulator = this->simulator();
1183 int episodeIdx = simulator.episodeIndex();
1184
1185 // for the initial episode, we use a fixed time step size
1186 if (episodeIdx < 0)
1187 return this->initialTimeStepSize_;
1188
1189 // ask the newton method for a suggestion. This suggestion will be based on how
1190 // well the previous time step converged. After that, apply the runtime time
1191 // stepping constraints.
1192 const auto& newtonMethod = this->model().newtonMethod();
1193 return limitNextTimeStepSize_(newtonMethod.suggestTimeStepSize(simulator.timeStepSize()));
1194 }
1195
1201 template <class LhsEval>
1202 LhsEval rockCompPoroMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx) const
1203 {
1204 OPM_TIMEBLOCK_LOCAL(rockCompPoroMultiplier, Subsystem::PvtProps);
1205 if (this->rockCompPoroMult_.empty() && this->rockCompPoroMultWc_.empty())
1206 return 1.0;
1207
1208 unsigned tableIdx = 0;
1209 if (!this->rockTableIdx_.empty())
1210 tableIdx = this->rockTableIdx_[elementIdx];
1211
1212 const auto& fs = intQuants.fluidState();
1213 const auto& rock_config = this->simulator().vanguard().eclState().getSimulationConfig().rock_config();
1214
1215 if (!this->rockCompPoroMultElastic_.empty()) {
1216 // ROCKCOMP HYSTERESIS=HYSTER: follow the deflation (virgin/plastic) curve
1217 // at or below the lowest pressure ever reached by this cell, and the
1218 // reversible elastic reload curve, anchored at that turning pressure,
1219 // above it.
1220 LhsEval effectivePressure = decay<LhsEval>(fs.pressure(refPressurePhaseIdx_()));
1221 LhsEval turningPressure = this->minRefPressure_[elementIdx];
1222
1223 if (!this->overburdenPressure_.empty()) {
1224 effectivePressure -= this->overburdenPressure_[elementIdx];
1225 turningPressure -= this->overburdenPressure_[elementIdx];
1226 }
1227
1228 if (rock_config.store()) {
1229 const auto& initialPressure = asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
1230 effectivePressure -= initialPressure;
1231 turningPressure -= initialPressure;
1232 }
1233
1234 if (effectivePressure <= turningPressure)
1235 return this->rockCompPoroMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
1236
1237 return this->rockCompPoroMultElastic_[tableIdx].eval(turningPressure, effectivePressure, /*extrapolation=*/true);
1238 }
1239
1240 LhsEval effectivePressure = decay<LhsEval>(fs.pressure(refPressurePhaseIdx_()));
1241 if (!this->minRefPressure_.empty())
1242 // The pore space change is irreversible
1243 effectivePressure =
1244 min(decay<LhsEval>(fs.pressure(refPressurePhaseIdx_())),
1245 this->minRefPressure_[elementIdx]);
1246
1247 if (!this->overburdenPressure_.empty())
1248 effectivePressure -= this->overburdenPressure_[elementIdx];
1249
1250 if (rock_config.store()) {
1251 effectivePressure -= asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
1252 }
1253
1254 if (!this->rockCompPoroMult_.empty()) {
1255 return this->rockCompPoroMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
1256 }
1257
1258 // water compaction
1259 assert(!this->rockCompPoroMultWc_.empty());
1260 LhsEval SwMax = max(decay<LhsEval>(fs.saturation(waterPhaseIdx)), this->maxWaterSaturation_[elementIdx]);
1261 LhsEval SwDeltaMax = SwMax - asImp_().initialFluidStates()[elementIdx].saturation(waterPhaseIdx);
1262
1263 return this->rockCompPoroMultWc_[tableIdx].eval(effectivePressure, SwDeltaMax, /*extrapolation=*/true);
1264 }
1265
1271 template <class LhsEval>
1272 LhsEval rockCompTransMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx) const
1273 {
1274 auto obtain = [](const auto& value)
1275 {
1276 if constexpr (std::is_same_v<LhsEval, Scalar>) {
1277 return getValue(value);
1278 } else {
1279 return value;
1280 }
1281 };
1282 return rockCompTransMultiplier<LhsEval>(intQuants, elementIdx, obtain);
1283 }
1284
1285 template <class LhsEval, class Callback>
1286 LhsEval rockCompTransMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
1287 {
1288 const bool implicit = !this->explicitRockCompaction_;
1289 return implicit ? this->simulator().problem().template computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain)
1290 : this->simulator().problem().getRockCompTransMultVal(elementIdx);
1291 }
1292
1293 template <class LhsEval, class Callback>
1294 LhsEval wellTransMultiplier(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
1295 {
1296 OPM_TIMEBLOCK_LOCAL(wellTransMultiplier, Subsystem::Wells);
1297
1298 const bool implicit = !this->explicitRockCompaction_;
1299 LhsEval trans_mult = implicit ? this->simulator().problem().template computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain)
1300 : this->simulator().problem().getRockCompTransMultVal(elementIdx);
1301 trans_mult *= this->simulator().problem().template permFactTransMultiplier<LhsEval>(intQuants, elementIdx, obtain);
1302
1303 return trans_mult;
1304 }
1305
1306 std::pair<BCType, RateVector> boundaryCondition(const unsigned int globalSpaceIdx, const int directionId) const
1307 {
1308 OPM_TIMEBLOCK_LOCAL(boundaryCondition, Subsystem::Assembly);
1310 return { BCType::NONE, RateVector(0.0) };
1311 }
1312 FaceDir::DirEnum dir = FaceDir::FromIntersectionIndex(directionId);
1313 const auto& schedule = this->simulator().vanguard().schedule();
1314 if (bcindex_(dir)[globalSpaceIdx] == 0) {
1315 return { BCType::NONE, RateVector(0.0) };
1316 }
1317 if (schedule[this->episodeIndex()].bcstate.size() == 0) {
1318 return { BCType::NONE, RateVector(0.0) };
1319 }
1320 const auto& bc = schedule[this->episodeIndex()].bcstate[bcindex_(dir)[globalSpaceIdx]];
1321 if (bc.bctype!=BCType::RATE) {
1322 return { bc.bctype, RateVector(0.0) };
1323 }
1324
1325 RateVector rate = 0.0;
1326 switch (bc.component) {
1327 case BCComponent::OIL:
1328 rate[FluidSystem::canonicalToActiveCompIdx(oilCompIdx)] = bc.rate;
1329 break;
1330 case BCComponent::GAS:
1331 rate[FluidSystem::canonicalToActiveCompIdx(gasCompIdx)] = bc.rate;
1332 break;
1333 case BCComponent::WATER:
1334 rate[FluidSystem::canonicalToActiveCompIdx(waterCompIdx)] = bc.rate;
1335 break;
1336 case BCComponent::SOLVENT:
1337 this->handleSolventBC(bc, rate);
1338 break;
1339 case BCComponent::POLYMER:
1340 this->handlePolymerBC(bc, rate);
1341 break;
1342 case BCComponent::MICR:
1343 this->handleMicrBC(bc, rate);
1344 break;
1345 case BCComponent::OXYG:
1346 this->handleOxygBC(bc, rate);
1347 break;
1348 case BCComponent::UREA:
1349 this->handleUreaBC(bc, rate);
1350 break;
1351 case BCComponent::NONE:
1352 throw std::logic_error("you need to specify the component when RATE type is set in BC");
1353 break;
1354 }
1355 //TODO add support for enthalpy rate
1356 return {bc.bctype, rate};
1357 }
1358
1359
1360 template<class Serializer>
1361 void serializeOp(Serializer& serializer)
1362 {
1363 serializer(static_cast<BaseType&>(*this));
1364 serializer(first_step_);
1365 serializer(drift_);
1366 serializer(wellModel_);
1367 serializer(aquiferModel_);
1368 serializer(tracerModel_);
1369 serializer(temperatureModel_);
1370 serializer(*materialLawManager_);
1371 }
1372
1373 const GlobalEqVector& drift() const
1374 {
1375 return drift_;
1376 }
1377
1378private:
1379 Implementation& asImp_()
1380 { return *static_cast<Implementation *>(this); }
1381
1382 const Implementation& asImp_() const
1383 { return *static_cast<const Implementation *>(this); }
1384
1385protected:
1393 {
1400 if (materialLawManager_ && materialLawManager_->enableHysteresis()) {
1401 materialLawManager_->captureBeginTimeStepState();
1402 }
1403 }
1404
1407 {
1414 if (materialLawManager_ && materialLawManager_->enableHysteresis()) {
1415 materialLawManager_->restoreBeginTimeStepState();
1416 }
1417 }
1418
1420 {
1421 this->transmissibilities_.finishInit(
1422 [&vg = this->simulator().vanguard()](const unsigned int index) {
1423 return vg.gridIdxToEquilGridIdx(index);
1424 });
1425 }
1426
1427 template<class EclWriterType>
1428 bool prepareTransmissibilityOutput_(EclWriterType& eclWriter,
1429 const bool enableEclOutput)
1430 {
1431 auto& simulator = this->simulator();
1432 bool localTransmissibilitiesFinished = false;
1433
1434 if (enableEclOutput) {
1435 // Parallel TRANX, TRANY, TRANZ and NNC output requires the global
1436 // grid's transmissibilities on the I/O rank -- except with LGRs, below.
1437 if (simulator.vanguard().grid().comm().size() > 1) {
1438 bool wholeGridTransNeeded = simulator.vanguard().grid().comm().rank() == 0;
1439 // Parallel LGR: reuse the simulator's own (distributed) transmissibilities for the
1440 // INIT output -- each rank contributes its interior connections, gathered on the
1441 // I/O rank and keyed by level-Cartesian indices so the output walk over the global
1442 // (equil) grid can look them up directly. This reuses the values already computed
1443 // in parallel for the simulation itself instead of recomputing a whole-grid
1444 // transmissibility. The local transmissibilities are built here, before the INIT
1445 // write, and reported as finished so that they are not built again.
1446 if constexpr (std::is_same_v<GetPropType<TypeTag, Properties::Grid>, Dune::CpGrid>) {
1447 // Gate on the deck's LGRs -- the same condition the writer keys its LGR
1448 // output walk on (writeInit / extractOutputTransAndNNC). Grid refinement
1449 // alone (grid().maxLevel() > 0, e.g. after adapt()) must not enable the
1450 // gathered mode: the writer would look up different keys than the ones
1451 // the leaf-grid walk records.
1452 if (simulator.vanguard().eclState().getLgrs().size() > 0) {
1454 localTransmissibilitiesFinished = true;
1455 const auto& localTrans = simulator.problem().eclTransmissibilities();
1456 eclWriter.setGatheredLgrTrans(
1457 gatherLgrOutputTrans(simulator.vanguard().grid(),
1458 simulator.vanguard().gridView(),
1459 [&localTrans](unsigned c1, unsigned c2)
1460 { return static_cast<double>(localTrans.transmissibility(c1, c2)); }));
1461 // All output values (TRANX/Y/Z and NNC) come from the gathered records --
1462 // no whole-grid transmissibility object is needed on the I/O rank.
1463 wholeGridTransNeeded = false;
1464 }
1465 }
1466 if (wholeGridTransNeeded) {
1467 eclWriter.setTransmissibilities(&simulator.vanguard().globalTransmissibility());
1468 }
1469 }
1470 else {
1472 localTransmissibilitiesFinished = true;
1473 eclWriter.setTransmissibilities(&simulator.problem().eclTransmissibilities());
1474 }
1475
1476 std::function<unsigned int(unsigned int)> equilGridToGrid =
1477 [&simulator](const unsigned int index) {
1478 return simulator.vanguard().gridEquilIdxToGridIdx(index);
1479 };
1480 eclWriter.extractOutputTransAndNNC(equilGridToGrid);
1481 }
1482
1483 simulator.vanguard().releaseGlobalTransmissibilities();
1484 return localTransmissibilitiesFinished;
1485 }
1486
1488 {
1489 auto& simulator = this->simulator();
1490 const auto& eclState = simulator.vanguard().eclState();
1491 const auto& schedule = simulator.vanguard().schedule();
1492
1493 simulator.setStartTime(schedule.getStartTime());
1494 simulator.setEndTime(schedule.simTime(schedule.size() - 1));
1495
1496 // Represent initialization as a zero-length episode before report step zero.
1497 simulator.setEpisodeIndex(-1);
1498 simulator.setEpisodeLength(0.0);
1499
1500 this->initGravity_(eclState);
1501
1502 if (this->enableTuning_) {
1503 // If support for the TUNING keyword is enabled, get the initial time
1504 // stepping parameters from it instead of from command line parameters.
1505 const auto& tuning = schedule[0].tuning();
1506 this->initialTimeStepSize_ = tuning.TSINIT.value_or(-1.0);
1507 this->maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
1508 }
1509 }
1510
1512 {
1513 auto& simulator = this->simulator();
1514
1515 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) &&
1516 FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
1517 this->maxOilSaturation_.resize(this->model().numGridDof(), 0.0);
1518 }
1519
1520 this->readRockParameters_(
1521 simulator.vanguard().cellCenterDepths(),
1522 [&simulator](const unsigned int index) {
1523 std::array<int, dim> coords;
1524 simulator.vanguard().cartesianCoordinate(index, coords);
1525 std::ranges::transform(coords, coords.begin(),
1526 [](const auto coordinate) { return coordinate + 1; });
1527 return coords;
1528 });
1529
1531 this->readThermalParameters_();
1532 }
1533
1534 template<class UpdateFunc>
1535 void updateProperty_(const std::string& failureMsg,
1536 UpdateFunc func)
1537 {
1538 OPM_TIMEBLOCK(updateProperty);
1539 const auto& model = this->simulator().model();
1540 const auto& primaryVars = model.solution(/*timeIdx*/0);
1541 const auto& vanguard = this->simulator().vanguard();
1542 std::size_t numGridDof = primaryVars.size();
1544#ifdef _OPENMP
1545#pragma omp parallel for
1546#endif
1547 for (unsigned dofIdx = 0; dofIdx < numGridDof; ++dofIdx) {
1548 const auto& iq = *model.cachedIntensiveQuantities(dofIdx, /*timeIdx=*/ 0);
1549 func(dofIdx, iq);
1550 }
1551 OPM_END_PARALLEL_TRY_CATCH(failureMsg, vanguard.grid().comm());
1552 }
1553
1555 {
1556 OPM_TIMEBLOCK(updateMaxOilSaturation);
1557 int episodeIdx = this->episodeIndex();
1558
1559 // we use VAPPARS
1560 if (this->vapparsActive(episodeIdx)) {
1561 this->updateProperty_("FlowProblem::updateMaxOilSaturation_() failed:",
1562 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1563 {
1564 this->updateMaxOilSaturation_(compressedDofIdx,iq);
1565 });
1566 return true;
1567 }
1568
1569 return false;
1570 }
1571
1572 bool updateMaxOilSaturation_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1573 {
1574 OPM_TIMEBLOCK_LOCAL(updateMaxOilSaturation, Subsystem::SatProps);
1575 const auto& fs = iq.fluidState();
1576 const Scalar So = decay<Scalar>(fs.saturation(refPressurePhaseIdx_()));
1577 auto& mos = this->maxOilSaturation_;
1578 if(mos[compressedDofIdx] < So){
1579 mos[compressedDofIdx] = So;
1580 return true;
1581 }else{
1582 return false;
1583 }
1584 }
1585
1587 {
1588 OPM_TIMEBLOCK(updateMaxWaterSaturation);
1589 // water compaction is activated in ROCKCOMP
1590 if (this->maxWaterSaturation_.empty())
1591 return false;
1592
1593 this->updateProperty_("FlowProblem::updateMaxWaterSaturation_() failed:",
1594 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1595 {
1596 this->updateMaxWaterSaturation_(compressedDofIdx,iq);
1597 });
1598 return true;
1599 }
1600
1601
1602 bool updateMaxWaterSaturation_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1603 {
1604 OPM_TIMEBLOCK_LOCAL(updateMaxWaterSaturation, Subsystem::SatProps);
1605 const auto& fs = iq.fluidState();
1606 const Scalar Sw = decay<Scalar>(fs.saturation(waterPhaseIdx));
1607 auto& mow = this->maxWaterSaturation_;
1608 if(mow[compressedDofIdx]< Sw){
1609 mow[compressedDofIdx] = Sw;
1610 return true;
1611 }else{
1612 return false;
1613 }
1614 }
1615
1617 {
1618 OPM_TIMEBLOCK(updateMinPressure);
1619 // IRREVERS option is used in ROCKCOMP
1620 if (this->minRefPressure_.empty())
1621 return false;
1622
1623 this->updateProperty_("FlowProblem::updateMinPressure_() failed:",
1624 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1625 {
1626 this->updateMinPressure_(compressedDofIdx,iq);
1627 });
1628 return true;
1629 }
1630
1631 bool updateMinPressure_(unsigned compressedDofIdx, const IntensiveQuantities& iq){
1632 OPM_TIMEBLOCK_LOCAL(updateMinPressure, Subsystem::PvtProps);
1633 const auto& fs = iq.fluidState();
1634 const Scalar min_pressure = getValue(fs.pressure(refPressurePhaseIdx_()));
1635 auto& min_pressures = this->minRefPressure_;
1636 if(min_pressures[compressedDofIdx]> min_pressure){
1637 min_pressures[compressedDofIdx] = min_pressure;
1638 return true;
1639 }else{
1640 return false;
1641 }
1642 }
1643
1644 // \brief Function to assign field properties of type double, on the leaf grid view.
1645 //
1646 // For CpGrid with local grid refinement, the field property of a cell on the leaf
1647 // is inherited from its parent or equivalent (when has no parent) cell on level zero.
1648 std::function<std::vector<double>(const FieldPropsManager&, const std::string&)>
1650 {
1651 const auto& lookup = this->lookUpData_;
1652 return [&lookup](const FieldPropsManager& fieldPropManager, const std::string& propString)
1653 {
1654 return lookup.assignFieldPropsDoubleOnLeaf(fieldPropManager, propString);
1655 };
1656 }
1657
1658 // \brief Function to assign field properties of type int, unsigned int, ..., on the leaf grid view.
1659 //
1660 // For CpGrid with local grid refinement, the field property of a cell on the leaf
1661 // is inherited from its parent or equivalent (when has no parent) cell on level zero.
1662 template<typename IntType>
1663 std::function<std::vector<IntType>(const FieldPropsManager&, const std::string&, bool)>
1665 {
1666 const auto& lookup = this->lookUpData_;
1667 return [&lookup](const FieldPropsManager& fieldPropManager, const std::string& propString, bool needsTranslation)
1668 {
1669 return lookup.template assignFieldPropsIntOnLeaf<IntType>(fieldPropManager, propString, needsTranslation);
1670 };
1671 }
1672
1674 {
1675 OPM_TIMEBLOCK(readMaterialParameters);
1676 const auto& simulator = this->simulator();
1677 const auto& vanguard = simulator.vanguard();
1678 const auto& eclState = vanguard.eclState();
1679
1680 // the PVT and saturation region numbers
1682 this->updatePvtnum_();
1683 this->updateSatnum_();
1684
1685 // the MISC region numbers (solvent model)
1686 this->updateMiscnum_();
1687 // the PLMIX region numbers (polymer model)
1688 this->updatePlmixnum_();
1689
1690 OPM_END_PARALLEL_TRY_CATCH("Invalid region numbers: ", vanguard.gridView().comm());
1692 // porosity
1693 updateReferencePorosity_();
1694 this->referencePorosity_[1] = this->referencePorosity_[0];
1696
1698 // rock fraction
1699 updateRockFraction_();
1700 this->rockFraction_[1] = this->rockFraction_[0];
1702
1704 // fluid-matrix interactions (saturation functions; relperm/capillary pressure)
1705 materialLawManager_ = std::make_shared<EclMaterialLawManager>();
1706 materialLawManager_->initFromState(eclState);
1707 materialLawManager_->initParamsForElements(eclState, this->model().numGridDof(),
1708 this-> template fieldPropIntTypeOnLeafAssigner_<int>(),
1709 this-> lookupIdxOnLevelZeroAssigner_());
1711 }
1712
1714 {
1715 if constexpr (energyModuleType == EnergyModules::FullyImplicitThermal ||
1716 energyModuleType == EnergyModules::SequentialImplicitThermal )
1717 {
1718 const auto& simulator = this->simulator();
1719 const auto& vanguard = simulator.vanguard();
1720 const auto& eclState = vanguard.eclState();
1721
1722 // fluid-matrix interactions (saturation functions; relperm/capillary pressure)
1723 thermalLawManager_ = std::make_shared<EclThermalLawManager>();
1724 thermalLawManager_->initParamsForElements(eclState, this->model().numGridDof(),
1725 this-> fieldPropDoubleOnLeafAssigner_(),
1726 this-> template fieldPropIntTypeOnLeafAssigner_<unsigned int>());
1727 }
1728 }
1729
1731 {
1732 const auto& simulator = this->simulator();
1733 const auto& vanguard = simulator.vanguard();
1734 const auto& eclState = vanguard.eclState();
1735
1736 std::size_t numDof = this->model().numGridDof();
1737
1738 this->referencePorosity_[/*timeIdx=*/0].resize(numDof);
1739
1740 const auto& fp = eclState.fieldProps();
1741 const std::vector<double> porvData = this -> fieldPropDoubleOnLeafAssigner_()(fp, "PORV");
1742 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
1743 int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(dofIdx);
1744 Scalar poreVolume = porvData[dofIdx];
1745
1746 // we define the porosity as the accumulated pore volume divided by the
1747 // geometric volume of the element. Note that -- in pathetic cases -- it can
1748 // be larger than 1.0!
1749 Scalar dofVolume = simulator.model().dofTotalVolume(sfcdofIdx);
1750 assert(dofVolume > 0.0);
1751 this->referencePorosity_[/*timeIdx=*/0][sfcdofIdx] = poreVolume/dofVolume;
1752 }
1753 }
1754
1756
1757 const bool solveEnergyEquation = (energyModuleType == EnergyModules::FullyImplicitThermal ||
1758 energyModuleType == EnergyModules::SequentialImplicitThermal);
1759 if (!solveEnergyEquation)
1760 return;
1761
1762 const auto& simulator = this->simulator();
1763 const auto& vanguard = simulator.vanguard();
1764 const auto& eclState = vanguard.eclState();
1765
1766 std::size_t numDof = this->model().numGridDof();
1767 this->rockFraction_[/*timeIdx=*/0].resize(numDof);
1768 // For the energy equation, we need the volume of the rock.
1769 // The volume of the rock is computed by rockFraction * geometric volume of the element.
1770 // The reference porosity is defined as porosity * ntg * pore-volume-multiplier.
1771 // A common practice in reservoir simulation is to use large pore-volume-multipliers in boundary cells
1772 // to model boundary conditions other than no-flow. This may result in reference porosities that are larger than 1.
1773 // A simple (1-reference porosity) * geometric volume of the element may give unphysical results.
1774 // We therefore instead consider the pore-volume-multiplier as a volume multiplier. The rock fraction is thus given by
1775 // (1 - porosity * ntg) * pore-volume-multiplier = (1 - porosity * ntg) * reference porosity / (porosity * ntg)
1776 const auto& fp = eclState.fieldProps();
1777 const std::vector<double> poroData = this->fieldPropDoubleOnLeafAssigner_()(fp, "PORO");
1778 const std::vector<double> ntgData = this->fieldPropDoubleOnLeafAssigner_()(fp, "NTG");
1779
1780 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
1781 const auto ntg = ntgData[dofIdx];
1782 const auto poro_eff = ntg * poroData[dofIdx];
1783 const int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(dofIdx);
1784 const auto rock_fraction = (1 - poro_eff) * this->referencePorosity_[/*timeIdx=*/0][sfcdofIdx] / poro_eff;
1785 this->rockFraction_[/*timeIdx=*/0][sfcdofIdx] = rock_fraction;
1786 }
1787 }
1788
1790 {
1791 // TODO: whether we should move this to FlowProblemBlackoil
1792 const auto& simulator = this->simulator();
1793 const auto& vanguard = simulator.vanguard();
1794 const auto& eclState = vanguard.eclState();
1795
1796 if (eclState.getInitConfig().hasEquil())
1797 readEquilInitialCondition_();
1798 else
1799 readExplicitInitialCondition_();
1800
1801 //initialize min/max values
1802 std::size_t numElems = this->model().numGridDof();
1803 for (std::size_t elemIdx = 0; elemIdx < numElems; ++elemIdx) {
1804 const auto& fs = asImp_().initialFluidStates()[elemIdx];
1805 if (!this->maxWaterSaturation_.empty() && waterPhaseIdx > -1)
1806 this->maxWaterSaturation_[elemIdx] = std::max(this->maxWaterSaturation_[elemIdx], fs.saturation(waterPhaseIdx));
1807 if (!this->maxOilSaturation_.empty() && oilPhaseIdx > -1)
1808 this->maxOilSaturation_[elemIdx] = std::max(this->maxOilSaturation_[elemIdx], fs.saturation(oilPhaseIdx));
1809 if (!this->minRefPressure_.empty() && refPressurePhaseIdx_() > -1)
1810 this->minRefPressure_[elemIdx] = std::min(this->minRefPressure_[elemIdx], fs.pressure(refPressurePhaseIdx_()));
1811 }
1812 }
1813
1814 virtual void readEquilInitialCondition_() = 0;
1816
1817 // update the hysteresis parameters of the material laws for the whole grid
1819 {
1820 if (!materialLawManager_->enableHysteresis())
1821 return false;
1822
1823 // we need to update the hysteresis data for _all_ elements (i.e., not just the
1824 // interior ones) to avoid desynchronization of the processes in the parallel case!
1825 this->updateProperty_("FlowProblem::updateHysteresis_() failed:",
1826 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1827 {
1828 materialLawManager_->updateHysteresis(iq.fluidState(), compressedDofIdx);
1829 });
1830 return true;
1831 }
1832
1833
1834 bool updateHysteresis_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1835 {
1836 OPM_TIMEBLOCK_LOCAL(updateHysteresis_, Subsystem::SatProps);
1837 materialLawManager_->updateHysteresis(iq.fluidState(), compressedDofIdx);
1838 //TODO change materials to give a bool
1839 return true;
1840 }
1841
1842 Scalar getRockCompTransMultVal(std::size_t dofIdx) const
1843 {
1844 if (this->rockCompTransMultVal_.empty())
1845 return 1.0;
1846
1847 return this->rockCompTransMultVal_[dofIdx];
1848 }
1849
1850protected:
1859 void initGravity_(const EclipseState& eclState)
1860 {
1861 this->gravity_ = 0.0;
1862
1863 if (Parameters::Get<Parameters::EnableGravity>() &&
1864 eclState.getInitConfig().hasGravity())
1865 {
1866 // unit::gravity is 9.80665 m^2/s--i.e., standard measure at Tellus equator.
1867 this->gravity_[dim - 1] = unit::gravity;
1868 }
1869 }
1870
1872 {
1873 ConditionalStorage<enableFullyImplicitThermal, Scalar> thermalHalfTransIn;
1874 ConditionalStorage<enableFullyImplicitThermal, Scalar> thermalHalfTransOut;
1875 ConditionalStorage<enableDiffusion, Scalar> diffusivity;
1876 ConditionalStorage<enableDispersion, Scalar> dispersivity;
1878 };
1879
1880 // update the prefetch friendly data object
1882 {
1883 const auto& distFn =
1884 [this](PffDofData_& dofData,
1885 const Stencil& stencil,
1886 unsigned localDofIdx)
1887 -> void
1888 {
1889 const auto& elementMapper = this->model().elementMapper();
1890
1891 unsigned globalElemIdx = elementMapper.index(stencil.entity(localDofIdx));
1892 if (localDofIdx != 0) {
1893 unsigned globalCenterElemIdx = elementMapper.index(stencil.entity(/*dofIdx=*/0));
1894 dofData.transmissibility = transmissibilities_.transmissibility(globalCenterElemIdx, globalElemIdx);
1895
1896 if constexpr (enableFullyImplicitThermal) {
1897 *dofData.thermalHalfTransIn = transmissibilities_.thermalHalfTrans(globalCenterElemIdx, globalElemIdx);
1898 *dofData.thermalHalfTransOut = transmissibilities_.thermalHalfTrans(globalElemIdx, globalCenterElemIdx);
1899 }
1900 if constexpr (enableDiffusion)
1901 *dofData.diffusivity = transmissibilities_.diffusivity(globalCenterElemIdx, globalElemIdx);
1902 if (enableDispersion)
1903 dofData.dispersivity = transmissibilities_.dispersivity(globalCenterElemIdx, globalElemIdx);
1904 }
1905 };
1906
1907 pffDofData_.update(distFn);
1908 }
1909
1910 virtual void updateExplicitQuantities_(int episodeIdx, int timeStepSize, bool first_step_after_restart) = 0;
1911
1913 {
1914 const auto& simulator = this->simulator();
1915 const auto& vanguard = simulator.vanguard();
1916 const auto& bcconfig = vanguard.eclState().getSimulationConfig().bcconfig();
1917 if (bcconfig.size() > 0) {
1918 nonTrivialBoundaryConditions_ = true;
1919
1920 std::size_t numCartDof = vanguard.cartesianSize();
1921 unsigned numElems = vanguard.gridView().size(/*codim=*/0);
1922 std::vector<int> cartesianToCompressedElemIdx(numCartDof, -1);
1923
1924 for (unsigned elemIdx = 0; elemIdx < numElems; ++elemIdx)
1925 cartesianToCompressedElemIdx[vanguard.cartesianIndex(elemIdx)] = elemIdx;
1926
1927 bcindex_.resize(numElems, 0);
1928 auto loopAndApply = [&cartesianToCompressedElemIdx,
1929 &vanguard](const auto& bcface,
1930 auto apply)
1931 {
1932 for (int i = bcface.i1; i <= bcface.i2; ++i) {
1933 for (int j = bcface.j1; j <= bcface.j2; ++j) {
1934 for (int k = bcface.k1; k <= bcface.k2; ++k) {
1935 std::array<int, 3> tmp = {i,j,k};
1936 auto elemIdx = cartesianToCompressedElemIdx[vanguard.cartesianIndex(tmp)];
1937 if (elemIdx >= 0)
1938 apply(elemIdx);
1939 }
1940 }
1941 }
1942 };
1943 for (const auto& bcface : bcconfig) {
1944 std::vector<int>& data = bcindex_(bcface.dir);
1945 const int index = bcface.index;
1946 loopAndApply(bcface,
1947 [&data,index](int elemIdx)
1948 { data[elemIdx] = index; });
1949 }
1950 }
1951 }
1952
1953 // this method applies the runtime constraints specified via the deck and/or command
1954 // line parameters for the size of the next time step.
1956 {
1957 if constexpr (enableExperiments) {
1958 const auto& simulator = this->simulator();
1959 const auto& schedule = simulator.vanguard().schedule();
1960 int episodeIdx = simulator.episodeIndex();
1961
1962 // first thing in the morning, limit the time step size to the maximum size
1963 Scalar maxTimeStepSize = Parameters::Get<Parameters::SolverMaxTimeStepInDays<Scalar>>() * 24 * 60 * 60;
1964 int reportStepIdx = std::max(episodeIdx, 0);
1965 if (this->enableTuning_) {
1966 const auto& tuning = schedule[reportStepIdx].tuning();
1967 maxTimeStepSize = tuning.TSMAXZ;
1968 }
1969
1970 dtNext = std::min(dtNext, maxTimeStepSize);
1971
1972 Scalar remainingEpisodeTime =
1973 simulator.episodeStartTime() + simulator.episodeLength()
1974 - (simulator.startTime() + simulator.time());
1975 assert(remainingEpisodeTime >= 0.0);
1976
1977 // if we would have a small amount of time left over in the current episode, make
1978 // two equal time steps instead of a big and a small one
1979 if (remainingEpisodeTime/2.0 < dtNext && dtNext < remainingEpisodeTime*(1.0 - 1e-5))
1980 // note: limiting to the maximum time step size here is probably not strictly
1981 // necessary, but it should not hurt and is more fool-proof
1982 dtNext = std::min(maxTimeStepSize, remainingEpisodeTime/2.0);
1983
1984 if (simulator.episodeStarts()) {
1985 // if a well event occurred, respect the limit for the maximum time step after
1986 // that, too
1987 const auto& events = simulator.vanguard().schedule()[reportStepIdx].events();
1988 bool wellEventOccured =
1989 events.hasEvent(ScheduleEvents::NEW_WELL)
1990 || events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE)
1991 || events.hasEvent(ScheduleEvents::INJECTION_UPDATE)
1992 || events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
1993 if (episodeIdx >= 0 && wellEventOccured && this->maxTimeStepAfterWellEvent_ > 0)
1994 dtNext = std::min(dtNext, this->maxTimeStepAfterWellEvent_);
1995 }
1996 }
1997
1998 return dtNext;
1999 }
2000
2002 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2003 return oilPhaseIdx;
2004 }
2005 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2006 return gasPhaseIdx;
2007 }
2008 else {
2009 return waterPhaseIdx;
2010 }
2011 }
2012
2014 {
2015 const auto& model = this->simulator().model();
2016 std::size_t numGridDof = this->model().numGridDof();
2017 this->rockCompTransMultVal_.resize(numGridDof, 1.0);
2018 for (std::size_t elementIdx = 0; elementIdx < numGridDof; ++elementIdx) {
2019 const auto& iq = *model.cachedIntensiveQuantities(elementIdx, /*timeIdx=*/ 0);
2020 Scalar trans_mult = computeRockCompTransMultiplier_<Scalar>(iq, elementIdx);
2021 this->rockCompTransMultVal_[elementIdx] = trans_mult;
2022 }
2023 }
2024
2030 template <class LhsEval>
2031 LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities& intQuants, unsigned elementIdx) const
2032 {
2033 auto obtain = [](const auto& value)
2034 {
2035 if constexpr (std::is_same_v<LhsEval, Scalar>) {
2036 return getValue(value);
2037 } else {
2038 return value;
2039 }
2040 };
2041
2042 return computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain);
2043 }
2044
2045 template <class LhsEval, class Callback>
2046 LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
2047 {
2048 OPM_TIMEBLOCK_LOCAL(computeRockCompTransMultiplier, Subsystem::PvtProps);
2049 if (this->rockCompTransMult_.empty() && this->rockCompTransMultWc_.empty())
2050 return 1.0;
2051
2052 unsigned tableIdx = 0;
2053 if (!this->rockTableIdx_.empty())
2054 tableIdx = this->rockTableIdx_[elementIdx];
2055
2056 const auto& fs = intQuants.fluidState();
2057 const auto& rock_config = this->simulator().vanguard().eclState().getSimulationConfig().rock_config();
2058
2059 if (!this->rockCompTransMultElastic_.empty()) {
2060 // ROCKCOMP HYSTERESIS=HYSTER: see rockCompPoroMultiplier() above.
2061 LhsEval effectivePressure = obtain(fs.pressure(refPressurePhaseIdx_()));
2062 LhsEval turningPressure = this->minRefPressure_[elementIdx];
2063
2064 if (!this->overburdenPressure_.empty()) {
2065 effectivePressure -= this->overburdenPressure_[elementIdx];
2066 turningPressure -= this->overburdenPressure_[elementIdx];
2067 }
2068
2069 if (rock_config.store()) {
2070 const auto& initialPressure = asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
2071 effectivePressure -= initialPressure;
2072 turningPressure -= initialPressure;
2073 }
2074
2075 if (effectivePressure <= turningPressure)
2076 return this->rockCompTransMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
2077
2078 return this->rockCompTransMultElastic_[tableIdx].eval(turningPressure, effectivePressure, /*extrapolation=*/true);
2079 }
2080
2081 LhsEval effectivePressure = obtain(fs.pressure(refPressurePhaseIdx_()));
2082 if (!this->minRefPressure_.empty())
2083 // The pore space change is irreversible
2084 effectivePressure =
2085 min(obtain(fs.pressure(refPressurePhaseIdx_())),
2086 this->minRefPressure_[elementIdx]);
2087
2088 if (!this->overburdenPressure_.empty())
2089 effectivePressure -= this->overburdenPressure_[elementIdx];
2090
2091 if (rock_config.store()) {
2092 effectivePressure -= asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
2093 }
2094
2095 if (!this->rockCompTransMult_.empty())
2096 return this->rockCompTransMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
2097
2098 // water compaction
2099 assert(!this->rockCompTransMultWc_.empty());
2100 LhsEval SwMax = max(obtain(fs.saturation(waterPhaseIdx)), this->maxWaterSaturation_[elementIdx]);
2101 LhsEval SwDeltaMax = SwMax - asImp_().initialFluidStates()[elementIdx].saturation(waterPhaseIdx);
2102
2103 return this->rockCompTransMultWc_[tableIdx].eval(effectivePressure, SwDeltaMax, /*extrapolation=*/true);
2104 }
2105
2106 typename Vanguard::TransmissibilityType transmissibilities_;
2107
2108 std::shared_ptr<EclMaterialLawManager> materialLawManager_;
2109 std::shared_ptr<EclThermalLawManager> thermalLawManager_;
2110
2112
2115
2119
2122
2123 template<class T>
2124 struct BCData
2125 {
2126 std::array<std::vector<T>,6> data;
2127
2128 void resize(std::size_t size, T defVal)
2129 {
2130 for (auto& d : data)
2131 d.resize(size, defVal);
2132 }
2133
2134 const std::vector<T>& operator()(FaceDir::DirEnum dir) const
2135 {
2136 if (dir == FaceDir::DirEnum::Unknown)
2137 throw std::runtime_error("Tried to access BC data for the 'Unknown' direction");
2138 int idx = 0;
2139 int div = static_cast<int>(dir);
2140 while ((div /= 2) >= 1)
2141 ++idx;
2142 assert(idx >= 0 && idx <= 5);
2143 return data[idx];
2144 }
2145
2146 std::vector<T>& operator()(FaceDir::DirEnum dir)
2147 {
2148 return const_cast<std::vector<T>&>(std::as_const(*this)(dir));
2149 }
2150 };
2151
2152 virtual void handleSolventBC(const BCState::BCFace&, RateVector&) const = 0;
2153
2154 virtual void handlePolymerBC(const BCState::BCFace&, RateVector&) const = 0;
2155
2156 virtual void handleMicrBC(const BCState::BCFace&, RateVector&) const = 0;
2157
2158 virtual void handleOxygBC(const BCState::BCFace&, RateVector&) const = 0;
2159
2160 virtual void handleUreaBC(const BCState::BCFace&, RateVector&) const = 0;
2161
2163 bool nonTrivialBoundaryConditions_ = false;
2164 bool first_step_ = true;
2165 bool enable_state_rollback_ = false;
2166
2174 {
2175 bool first_step = true;
2176 std::vector<Scalar> max_polymer_adsorption;
2177 std::vector<Scalar> max_oil_saturation;
2178 std::vector<Scalar> max_water_saturation;
2179 std::vector<Scalar> min_ref_pressure;
2180 std::vector<Scalar> rock_comp_trans_mult_val;
2181 };
2182
2184
2187 virtual bool episodeWillBeOver() const
2188 {
2189 return this->simulator().episodeWillBeOver();
2190 }
2191};
2192
2193} // namespace Opm
2194
2195#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:962
unsigned pvtRegionIndex(unsigned elemIdx) const
Returns the index the relevant PVT region given a cell index.
Definition: FlowGenericProblem_impl.hpp:921
Scalar rockBiotTemp(unsigned elementIdx) const
Returns the rock compressibility of an element due to thermoelasticity.
Definition: FlowGenericProblem_impl.hpp:419
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:400
Scalar rockCompressibility(unsigned globalSpaceIdx) const
Definition: FlowGenericProblem_impl.hpp:385
unsigned miscnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant MISC region given a cell index.
Definition: FlowGenericProblem_impl.hpp:941
unsigned satnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant saturation function region given a cell index.
Definition: FlowGenericProblem_impl.hpp:931
Scalar lame(unsigned elementIdx) const
Direct access to Lame's second parameter in an element.
Definition: FlowGenericProblem_impl.hpp:431
void beginTimeStep_(bool enableExperiments, int episodeIdx, int timeStepIndex, Scalar startTime, Scalar time, Scalar timeStepSize, Scalar endTime)
Definition: FlowGenericProblem_impl.hpp:657
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:951
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:155
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:408
bool beginEpisode_(bool enableExperiments, int episodeIdx)
Definition: FlowGenericProblem_impl.hpp:620
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:133
Scalar biotTemp(unsigned elementIdx) const
Direct access to Biot temperature coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:483
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:462
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:2187
const WellModel & wellModel() const
Returns a reference to the ECL well manager used by the problem.
Definition: FlowProblem.hpp:1154
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:1166
const GlobalEqVector & drift() const
Definition: FlowProblem.hpp:1373
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:1664
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:962
LhsEval wellTransMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx, Callback &obtain) const
Definition: FlowProblem.hpp:1294
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:1406
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:1834
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:1859
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:970
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:2164
GetPropType< TypeTag, Properties::ElementContext > ElementContext
Definition: FlowProblem.hpp:158
const ThermalConductionLawParams & thermalConductionLawParams(unsigned globalSpaceIdx, unsigned) const
Definition: FlowProblem.hpp:1037
AquiferModel aquiferModel_
Definition: FlowProblem.hpp:2114
GlobalEqVector drift_
Definition: FlowProblem.hpp:2111
bool updateMinPressure_()
Definition: FlowProblem.hpp:1616
std::function< std::vector< double >(const FieldPropsManager &, const std::string &)> fieldPropDoubleOnLeafAssigner_()
Definition: FlowProblem.hpp:1649
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:1730
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:2046
BCData< int > bcindex_
Definition: FlowProblem.hpp:2162
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:1586
virtual void handleUreaBC(const BCState::BCFace &, RateVector &) const =0
FlowThresholdPressure< TypeTag > thresholdPressures_
Definition: FlowProblem.hpp:2120
Dune::FieldMatrix< Scalar, dimWorld, dimWorld > DimMatrix
Definition: FlowProblem.hpp:172
@ waterPhaseIdx
Definition: FlowProblem.hpp:146
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:1052
bool updateMinPressure_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1631
std::string name() const
The problem name.
Definition: FlowProblem.hpp:1001
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:1272
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:2121
@ 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:1122
@ 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:1175
LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities &intQuants, unsigned elementIdx) const
Calculate the transmissibility multiplier due to water induced rock compaction.
Definition: FlowProblem.hpp:2031
std::pair< BCType, RateVector > boundaryCondition(const unsigned int globalSpaceIdx, const int directionId) const
Definition: FlowProblem.hpp:1306
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:2116
@ 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:2117
@ enableThermalFluxBoundaries
Definition: FlowProblem.hpp:142
const TracerModel & tracerModel() const
Definition: FlowProblem.hpp:724
WellModel wellModel_
Definition: FlowProblem.hpp:2113
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:1031
virtual void captureBeginTimeStepState_()
Snapshot the explicit quantities before the timestep runs.
Definition: FlowProblem.hpp:1392
static constexpr bool enablePolymerMolarWeight
Definition: FlowProblem.hpp:134
Scalar getRockCompTransMultVal(std::size_t dofIdx) const
Definition: FlowProblem.hpp:1842
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:986
const MaterialLawParams & materialLawParams(unsigned globalDofIdx) const
Definition: FlowProblem.hpp:874
Scalar temperature(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:1008
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:978
void updateRockCompTransMultVal_()
Definition: FlowProblem.hpp:2013
@ numPhases
Definition: FlowProblem.hpp:123
std::shared_ptr< EclThermalLawManager > thermalLawManager_
Definition: FlowProblem.hpp:2109
Scalar limitNextTimeStepSize_(Scalar dtNext) const
Definition: FlowProblem.hpp:1955
void finishTransmissibilities_()
Definition: FlowProblem.hpp:1419
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:2183
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:1818
void readThermalParameters_()
Definition: FlowProblem.hpp:1713
void serializeOp(Serializer &serializer)
Definition: FlowProblem.hpp:1361
Scalar maxPolymerAdsorption(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the max polymer adsorption value.
Definition: FlowProblem.hpp:995
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:1069
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:1163
@ dim
Definition: FlowProblem.hpp:118
GetPropType< TypeTag, Properties::IntensiveQuantities > IntensiveQuantities
Definition: FlowProblem.hpp:167
Scalar temperature(unsigned globalDofIdx, unsigned) const
Definition: FlowProblem.hpp:1020
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:2118
static constexpr bool enableExtbo
Definition: FlowProblem.hpp:131
std::shared_ptr< EclMaterialLawManager > materialLawManager_
Definition: FlowProblem.hpp:2108
WellModel & wellModel()
Definition: FlowProblem.hpp:1157
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:1535
bool prepareTransmissibilityOutput_(EclWriterType &eclWriter, const bool enableEclOutput)
Definition: FlowProblem.hpp:1428
LhsEval rockCompTransMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx, Callback &obtain) const
Definition: FlowProblem.hpp:1286
@ oilCompIdx
Definition: FlowProblem.hpp:151
void initializeSimulatorTime_()
Definition: FlowProblem.hpp:1487
bool updateMaxOilSaturation_()
Definition: FlowProblem.hpp:1554
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblem.hpp:200
void updatePffDofData_()
Definition: FlowProblem.hpp:1881
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:2163
GetPropType< TypeTag, Properties::Problem > Implementation
Definition: FlowProblem.hpp:106
void readBoundaryConditions_()
Definition: FlowProblem.hpp:1912
void updateRelperms(std::array< Evaluation, numPhases > &mobility, DirectionalMobilityPtr &dirMob, FluidState &fluidState, unsigned globalSpaceIdx) const
Definition: FlowProblem.hpp:921
Vanguard::TransmissibilityType transmissibilities_
Definition: FlowProblem.hpp:2106
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:1113
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:1789
virtual void initialSolutionApplied()
Callback used by the model to indicate that the initial solution has been determined for all degrees ...
Definition: FlowProblem.hpp:1080
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:2165
Scalar biotCoeff(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:816
std::shared_ptr< EclMaterialLawManager > materialLawManager()
Definition: FlowProblem.hpp:954
std::shared_ptr< const EclThermalLawManager > thermalLawManager() const
Definition: FlowProblem.hpp:917
bool updateMaxWaterSaturation_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1602
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:1572
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:1160
void initializeModelProperties_()
Definition: FlowProblem.hpp:1511
int refPressurePhaseIdx_() const
Definition: FlowProblem.hpp:2001
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:1202
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:1673
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:1755
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:2125
const std::vector< T > & operator()(FaceDir::DirEnum dir) const
Definition: FlowProblem.hpp:2134
void resize(std::size_t size, T defVal)
Definition: FlowProblem.hpp:2128
std::vector< T > & operator()(FaceDir::DirEnum dir)
Definition: FlowProblem.hpp:2146
std::array< std::vector< T >, 6 > data
Definition: FlowProblem.hpp:2126
Definition: FlowProblem.hpp:1872
ConditionalStorage< enableFullyImplicitThermal, Scalar > thermalHalfTransOut
Definition: FlowProblem.hpp:1874
ConditionalStorage< enableFullyImplicitThermal, Scalar > thermalHalfTransIn
Definition: FlowProblem.hpp:1873
ConditionalStorage< enableDiffusion, Scalar > diffusivity
Definition: FlowProblem.hpp:1875
ConditionalStorage< enableDispersion, Scalar > dispersivity
Definition: FlowProblem.hpp:1876
Scalar transmissibility
Definition: FlowProblem.hpp:1877
Explicit quantities as they stood at the start of the current timestep, restored if that timestep fai...
Definition: FlowProblem.hpp:2174
bool first_step
first step of the episode
Definition: FlowProblem.hpp:2175
std::vector< Scalar > min_ref_pressure
ROCKCOMP irreversible compaction.
Definition: FlowProblem.hpp:2179
std::vector< Scalar > rock_comp_trans_mult_val
ROCKCOMP transmissibility multiplier.
Definition: FlowProblem.hpp:2180
std::vector< Scalar > max_polymer_adsorption
POLYMER.
Definition: FlowProblem.hpp:2176
std::vector< Scalar > max_water_saturation
ROCKCOMP water-induced compaction.
Definition: FlowProblem.hpp:2178
std::vector< Scalar > max_oil_saturation
VAPPARS / DRSDT saturation history.
Definition: FlowProblem.hpp:2177