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
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
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
1307 int boundaryConditionIndex(const unsigned int globalSpaceIdx, const int directionId) const
1308 {
1310 return 0;
1311 }
1312 return bcindex_(FaceDir::FromIntersectionIndex(directionId))[globalSpaceIdx];
1313 }
1314
1315 std::pair<BCType, RateVector> boundaryCondition(const unsigned int globalSpaceIdx, const int directionId) const
1316 {
1317 OPM_TIMEBLOCK_LOCAL(boundaryCondition, Subsystem::Assembly);
1319 return { BCType::NONE, RateVector(0.0) };
1320 }
1321 FaceDir::DirEnum dir = FaceDir::FromIntersectionIndex(directionId);
1322 const auto& schedule = this->simulator().vanguard().schedule();
1323 if (bcindex_(dir)[globalSpaceIdx] == 0) {
1324 return { BCType::NONE, RateVector(0.0) };
1325 }
1326 if (schedule[this->episodeIndex()].bcstate.size() == 0) {
1327 return { BCType::NONE, RateVector(0.0) };
1328 }
1329 const auto& bc = schedule[this->episodeIndex()].bcstate[bcindex_(dir)[globalSpaceIdx]];
1330 if (bc.bctype!=BCType::RATE) {
1331 return { bc.bctype, RateVector(0.0) };
1332 }
1333
1334 RateVector rate = 0.0;
1335 switch (bc.component) {
1336 case BCComponent::OIL:
1337 rate[FluidSystem::canonicalToActiveCompIdx(oilCompIdx)] = bc.rate;
1338 break;
1339 case BCComponent::GAS:
1340 rate[FluidSystem::canonicalToActiveCompIdx(gasCompIdx)] = bc.rate;
1341 break;
1342 case BCComponent::WATER:
1343 rate[FluidSystem::canonicalToActiveCompIdx(waterCompIdx)] = bc.rate;
1344 break;
1345 case BCComponent::SOLVENT:
1346 this->handleSolventBC(bc, rate);
1347 break;
1348 case BCComponent::POLYMER:
1349 this->handlePolymerBC(bc, rate);
1350 break;
1351 case BCComponent::MICR:
1352 this->handleMicrBC(bc, rate);
1353 break;
1354 case BCComponent::OXYG:
1355 this->handleOxygBC(bc, rate);
1356 break;
1357 case BCComponent::UREA:
1358 this->handleUreaBC(bc, rate);
1359 break;
1360 case BCComponent::NONE:
1361 throw std::logic_error("you need to specify the component when RATE type is set in BC");
1362 break;
1363 }
1364 //TODO add support for enthalpy rate
1365 return {bc.bctype, rate};
1366 }
1367
1368
1369 template<class Serializer>
1370 void serializeOp(Serializer& serializer)
1371 {
1372 serializer(static_cast<BaseType&>(*this));
1373 serializer(first_step_);
1374 serializer(drift_);
1375 serializer(wellModel_);
1376 serializer(aquiferModel_);
1377 serializer(tracerModel_);
1378 serializer(temperatureModel_);
1379 serializer(*materialLawManager_);
1380 }
1381
1382 const GlobalEqVector& drift() const
1383 {
1384 return drift_;
1385 }
1386
1387private:
1388 Implementation& asImp_()
1389 { return *static_cast<Implementation *>(this); }
1390
1391 const Implementation& asImp_() const
1392 { return *static_cast<const Implementation *>(this); }
1393
1394protected:
1402 {
1409 if (materialLawManager_ && materialLawManager_->enableHysteresis()) {
1410 materialLawManager_->captureBeginTimeStepState();
1411 }
1412 }
1413
1416 {
1423 if (materialLawManager_ && materialLawManager_->enableHysteresis()) {
1424 materialLawManager_->restoreBeginTimeStepState();
1425 }
1426 }
1427
1429 {
1430 this->transmissibilities_.finishInit(
1431 [&vg = this->simulator().vanguard()](const unsigned int index) {
1432 return vg.gridIdxToEquilGridIdx(index);
1433 });
1434 }
1435
1436 template<class EclWriterType>
1437 bool prepareTransmissibilityOutput_(EclWriterType& eclWriter,
1438 const bool enableEclOutput)
1439 {
1440 auto& simulator = this->simulator();
1441 bool localTransmissibilitiesFinished = false;
1442
1443 if (enableEclOutput) {
1444 // Parallel TRANX, TRANY, TRANZ and NNC output requires the global
1445 // grid's transmissibilities on the I/O rank -- except with LGRs, below.
1446 if (simulator.vanguard().grid().comm().size() > 1) {
1447 bool wholeGridTransNeeded = simulator.vanguard().grid().comm().rank() == 0;
1448 // Parallel LGR: reuse the simulator's own (distributed) transmissibilities for the
1449 // INIT output -- each rank contributes its interior connections, gathered on the
1450 // I/O rank and keyed by level-Cartesian indices so the output walk over the global
1451 // (equil) grid can look them up directly. This reuses the values already computed
1452 // in parallel for the simulation itself instead of recomputing a whole-grid
1453 // transmissibility. The local transmissibilities are built here, before the INIT
1454 // write, and reported as finished so that they are not built again.
1455 if constexpr (std::is_same_v<GetPropType<TypeTag, Properties::Grid>, Dune::CpGrid>) {
1456 // Gate on the deck's LGRs -- the same condition the writer keys its LGR
1457 // output walk on (writeInit / extractOutputTransAndNNC). Grid refinement
1458 // alone (grid().maxLevel() > 0, e.g. after adapt()) must not enable the
1459 // gathered mode: the writer would look up different keys than the ones
1460 // the leaf-grid walk records.
1461 if (simulator.vanguard().eclState().getLgrs().size() > 0) {
1463 localTransmissibilitiesFinished = true;
1464 const auto& localTrans = simulator.problem().eclTransmissibilities();
1465 eclWriter.setGatheredLgrTrans(
1466 gatherLgrOutputTrans(simulator.vanguard().grid(),
1467 simulator.vanguard().gridView(),
1468 [&localTrans](unsigned c1, unsigned c2)
1469 { return static_cast<double>(localTrans.transmissibility(c1, c2)); }));
1470 // All output values (TRANX/Y/Z and NNC) come from the gathered records --
1471 // no whole-grid transmissibility object is needed on the I/O rank.
1472 wholeGridTransNeeded = false;
1473 }
1474 }
1475 if (wholeGridTransNeeded) {
1476 eclWriter.setTransmissibilities(&simulator.vanguard().globalTransmissibility());
1477 }
1478 }
1479 else {
1481 localTransmissibilitiesFinished = true;
1482 eclWriter.setTransmissibilities(&simulator.problem().eclTransmissibilities());
1483 }
1484
1485 std::function<unsigned int(unsigned int)> equilGridToGrid =
1486 [&simulator](const unsigned int index) {
1487 return simulator.vanguard().gridEquilIdxToGridIdx(index);
1488 };
1489 eclWriter.extractOutputTransAndNNC(equilGridToGrid);
1490 }
1491
1492 simulator.vanguard().releaseGlobalTransmissibilities();
1493 return localTransmissibilitiesFinished;
1494 }
1495
1497 {
1498 auto& simulator = this->simulator();
1499 const auto& eclState = simulator.vanguard().eclState();
1500 const auto& schedule = simulator.vanguard().schedule();
1501
1502 simulator.setStartTime(TimeService::to_time_t(schedule.getStartTime()));
1503 simulator.setEndTime(TimeService::to_time_t(schedule.simTime(schedule.size() - 1)));
1504
1505 // Represent initialization as a zero-length episode before report step zero.
1506 simulator.setEpisodeIndex(-1);
1507 simulator.setEpisodeLength(0.0);
1508
1509 this->initGravity_(eclState);
1510
1511 if (this->enableTuning_) {
1512 // If support for the TUNING keyword is enabled, get the initial time
1513 // stepping parameters from it instead of from command line parameters.
1514 const auto& tuning = schedule[0].tuning();
1515 this->initialTimeStepSize_ = tuning.TSINIT.value_or(-1.0);
1516 this->maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
1517 }
1518 }
1519
1521 {
1522 auto& simulator = this->simulator();
1523
1524 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx) &&
1525 FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
1526 this->maxOilSaturation_.resize(this->model().numGridDof(), 0.0);
1527 }
1528
1529 this->readRockParameters_(
1530 simulator.vanguard().cellCenterDepths(),
1531 [&simulator](const unsigned int index) {
1532 std::array<int, dim> coords;
1533 simulator.vanguard().cartesianCoordinate(index, coords);
1534 std::ranges::transform(coords, coords.begin(),
1535 [](const auto coordinate) { return coordinate + 1; });
1536 return coords;
1537 });
1538
1540 this->readThermalParameters_();
1541 }
1542
1543 template<class UpdateFunc>
1544 void updateProperty_(const std::string& failureMsg,
1545 UpdateFunc func)
1546 {
1547 OPM_TIMEBLOCK(updateProperty);
1548 const auto& model = this->simulator().model();
1549 const auto& primaryVars = model.solution(/*timeIdx*/0);
1550 const auto& vanguard = this->simulator().vanguard();
1551 std::size_t numGridDof = primaryVars.size();
1553#ifdef _OPENMP
1554#pragma omp parallel for
1555#endif
1556 for (unsigned dofIdx = 0; dofIdx < numGridDof; ++dofIdx) {
1557 const auto& iq = model.intensiveQuantities(dofIdx, /*timeIdx=*/ 0);
1558 func(dofIdx, iq);
1559 }
1560 OPM_END_PARALLEL_TRY_CATCH(failureMsg, vanguard.grid().comm());
1561 }
1562
1564 {
1565 OPM_TIMEBLOCK(updateMaxOilSaturation);
1566 int episodeIdx = this->episodeIndex();
1567
1568 // we use VAPPARS
1569 if (this->vapparsActive(episodeIdx)) {
1570 this->updateProperty_("FlowProblem::updateMaxOilSaturation_() failed:",
1571 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1572 {
1573 this->updateMaxOilSaturation_(compressedDofIdx,iq);
1574 });
1575 return true;
1576 }
1577
1578 return false;
1579 }
1580
1581 bool updateMaxOilSaturation_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1582 {
1583 OPM_TIMEBLOCK_LOCAL(updateMaxOilSaturation, Subsystem::SatProps);
1584 const auto& fs = iq.fluidState();
1585 const Scalar So = decay<Scalar>(fs.saturation(refPressurePhaseIdx_()));
1586 auto& mos = this->maxOilSaturation_;
1587 if(mos[compressedDofIdx] < So){
1588 mos[compressedDofIdx] = So;
1589 return true;
1590 }else{
1591 return false;
1592 }
1593 }
1594
1596 {
1597 OPM_TIMEBLOCK(updateMaxWaterSaturation);
1598 // water compaction is activated in ROCKCOMP
1599 if (this->maxWaterSaturation_.empty())
1600 return false;
1601
1602 this->updateProperty_("FlowProblem::updateMaxWaterSaturation_() failed:",
1603 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1604 {
1605 this->updateMaxWaterSaturation_(compressedDofIdx,iq);
1606 });
1607 return true;
1608 }
1609
1610
1611 bool updateMaxWaterSaturation_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1612 {
1613 OPM_TIMEBLOCK_LOCAL(updateMaxWaterSaturation, Subsystem::SatProps);
1614 const auto& fs = iq.fluidState();
1615 const Scalar Sw = decay<Scalar>(fs.saturation(waterPhaseIdx));
1616 auto& mow = this->maxWaterSaturation_;
1617 if(mow[compressedDofIdx]< Sw){
1618 mow[compressedDofIdx] = Sw;
1619 return true;
1620 }else{
1621 return false;
1622 }
1623 }
1624
1626 {
1627 OPM_TIMEBLOCK(updateMinPressure);
1628 // IRREVERS option is used in ROCKCOMP
1629 if (this->minRefPressure_.empty())
1630 return false;
1631
1632 this->updateProperty_("FlowProblem::updateMinPressure_() failed:",
1633 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1634 {
1635 this->updateMinPressure_(compressedDofIdx,iq);
1636 });
1637 return true;
1638 }
1639
1640 bool updateMinPressure_(unsigned compressedDofIdx, const IntensiveQuantities& iq){
1641 OPM_TIMEBLOCK_LOCAL(updateMinPressure, Subsystem::PvtProps);
1642 const auto& fs = iq.fluidState();
1643 const Scalar min_pressure = getValue(fs.pressure(refPressurePhaseIdx_()));
1644 auto& min_pressures = this->minRefPressure_;
1645 if(min_pressures[compressedDofIdx]> min_pressure){
1646 min_pressures[compressedDofIdx] = min_pressure;
1647 return true;
1648 }else{
1649 return false;
1650 }
1651 }
1652
1653 // \brief Function to assign field properties of type double, on the leaf grid view.
1654 //
1655 // For CpGrid with local grid refinement, the field property of a cell on the leaf
1656 // is inherited from its parent or equivalent (when has no parent) cell on level zero.
1657 std::function<std::vector<double>(const FieldPropsManager&, const std::string&)>
1659 {
1660 const auto& lookup = this->lookUpData_;
1661 return [&lookup](const FieldPropsManager& fieldPropManager, const std::string& propString)
1662 {
1663 return lookup.assignFieldPropsDoubleOnLeaf(fieldPropManager, propString);
1664 };
1665 }
1666
1667 // \brief Function to assign field properties of type int, unsigned int, ..., on the leaf grid view.
1668 //
1669 // For CpGrid with local grid refinement, the field property of a cell on the leaf
1670 // is inherited from its parent or equivalent (when has no parent) cell on level zero.
1671 template<typename IntType>
1672 std::function<std::vector<IntType>(const FieldPropsManager&, const std::string&, bool)>
1674 {
1675 const auto& lookup = this->lookUpData_;
1676 return [&lookup](const FieldPropsManager& fieldPropManager, const std::string& propString, bool needsTranslation)
1677 {
1678 return lookup.template assignFieldPropsIntOnLeaf<IntType>(fieldPropManager, propString, needsTranslation);
1679 };
1680 }
1681
1683 {
1684 OPM_TIMEBLOCK(readMaterialParameters);
1685 const auto& simulator = this->simulator();
1686 const auto& vanguard = simulator.vanguard();
1687 const auto& eclState = vanguard.eclState();
1688
1689 // the PVT and saturation region numbers
1691 this->updatePvtnum_();
1692 this->updateSatnum_();
1693
1694 // the MISC region numbers (solvent model)
1695 this->updateMiscnum_();
1696 // the PLMIX region numbers (polymer model)
1697 this->updatePlmixnum_();
1698
1699 OPM_END_PARALLEL_TRY_CATCH("Invalid region numbers: ", vanguard.gridView().comm());
1701 // porosity
1702 updateReferencePorosity_();
1703 this->referencePorosity_[1] = this->referencePorosity_[0];
1705
1707 // rock fraction
1708 updateRockFraction_();
1709 this->rockFraction_[1] = this->rockFraction_[0];
1711
1713 // fluid-matrix interactions (saturation functions; relperm/capillary pressure)
1714 materialLawManager_ = std::make_shared<EclMaterialLawManager>();
1715 materialLawManager_->initFromState(eclState);
1716 materialLawManager_->initParamsForElements(eclState, this->model().numGridDof(),
1717 this-> template fieldPropIntTypeOnLeafAssigner_<int>(),
1718 this-> lookupIdxOnLevelZeroAssigner_());
1720 }
1721
1723 {
1724 if constexpr (energyModuleType == EnergyModules::FullyImplicitThermal ||
1725 energyModuleType == EnergyModules::SequentialImplicitThermal )
1726 {
1727 const auto& simulator = this->simulator();
1728 const auto& vanguard = simulator.vanguard();
1729 const auto& eclState = vanguard.eclState();
1730
1731 // fluid-matrix interactions (saturation functions; relperm/capillary pressure)
1732 thermalLawManager_ = std::make_shared<EclThermalLawManager>();
1733 thermalLawManager_->initParamsForElements(eclState, this->model().numGridDof(),
1734 this-> fieldPropDoubleOnLeafAssigner_(),
1735 this-> template fieldPropIntTypeOnLeafAssigner_<unsigned int>());
1736 }
1737 }
1738
1740 {
1741 const auto& simulator = this->simulator();
1742 const auto& vanguard = simulator.vanguard();
1743 const auto& eclState = vanguard.eclState();
1744
1745 std::size_t numDof = this->model().numGridDof();
1746
1747 this->referencePorosity_[/*timeIdx=*/0].resize(numDof);
1748
1749 const auto& fp = eclState.fieldProps();
1750 const std::vector<double> porvData = this -> fieldPropDoubleOnLeafAssigner_()(fp, "PORV");
1751 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
1752 int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(dofIdx);
1753 Scalar poreVolume = porvData[dofIdx];
1754
1755 // we define the porosity as the accumulated pore volume divided by the
1756 // geometric volume of the element. Note that -- in pathetic cases -- it can
1757 // be larger than 1.0!
1758 Scalar dofVolume = simulator.model().dofTotalVolume(sfcdofIdx);
1759 assert(dofVolume > 0.0);
1760 this->referencePorosity_[/*timeIdx=*/0][sfcdofIdx] = poreVolume/dofVolume;
1761 }
1762 }
1763
1765
1766 const bool solveEnergyEquation = (energyModuleType == EnergyModules::FullyImplicitThermal ||
1767 energyModuleType == EnergyModules::SequentialImplicitThermal);
1768 if (!solveEnergyEquation)
1769 return;
1770
1771 const auto& simulator = this->simulator();
1772 const auto& vanguard = simulator.vanguard();
1773 const auto& eclState = vanguard.eclState();
1774
1775 std::size_t numDof = this->model().numGridDof();
1776 this->rockFraction_[/*timeIdx=*/0].resize(numDof);
1777 // For the energy equation, we need the volume of the rock.
1778 // The volume of the rock is computed by rockFraction * geometric volume of the element.
1779 // The reference porosity is defined as porosity * ntg * pore-volume-multiplier.
1780 // A common practice in reservoir simulation is to use large pore-volume-multipliers in boundary cells
1781 // to model boundary conditions other than no-flow. This may result in reference porosities that are larger than 1.
1782 // A simple (1-reference porosity) * geometric volume of the element may give unphysical results.
1783 // We therefore instead consider the pore-volume-multiplier as a volume multiplier. The rock fraction is thus given by
1784 // (1 - porosity * ntg) * pore-volume-multiplier = (1 - porosity * ntg) * reference porosity / (porosity * ntg)
1785 const auto& fp = eclState.fieldProps();
1786 const std::vector<double> poroData = this->fieldPropDoubleOnLeafAssigner_()(fp, "PORO");
1787 const std::vector<double> ntgData = this->fieldPropDoubleOnLeafAssigner_()(fp, "NTG");
1788
1789 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
1790 const auto ntg = ntgData[dofIdx];
1791 const auto poro_eff = ntg * poroData[dofIdx];
1792 const int sfcdofIdx = simulator.vanguard().gridEquilIdxToGridIdx(dofIdx);
1793 const auto rock_fraction = (1 - poro_eff) * this->referencePorosity_[/*timeIdx=*/0][sfcdofIdx] / poro_eff;
1794 this->rockFraction_[/*timeIdx=*/0][sfcdofIdx] = rock_fraction;
1795 }
1796 }
1797
1799 {
1800 // TODO: whether we should move this to FlowProblemBlackoil
1801 const auto& simulator = this->simulator();
1802 const auto& vanguard = simulator.vanguard();
1803 const auto& eclState = vanguard.eclState();
1804
1805 if (eclState.getInitConfig().hasEquil())
1806 readEquilInitialCondition_();
1807 else
1808 readExplicitInitialCondition_();
1809
1810 //initialize min/max values
1811 std::size_t numElems = this->model().numGridDof();
1812 for (std::size_t elemIdx = 0; elemIdx < numElems; ++elemIdx) {
1813 const auto& fs = asImp_().initialFluidStates()[elemIdx];
1814 if (!this->maxWaterSaturation_.empty() && waterPhaseIdx > -1)
1815 this->maxWaterSaturation_[elemIdx] = std::max(this->maxWaterSaturation_[elemIdx], fs.saturation(waterPhaseIdx));
1816 if (!this->maxOilSaturation_.empty() && oilPhaseIdx > -1)
1817 this->maxOilSaturation_[elemIdx] = std::max(this->maxOilSaturation_[elemIdx], fs.saturation(oilPhaseIdx));
1818 if (!this->minRefPressure_.empty() && refPressurePhaseIdx_() > -1)
1819 this->minRefPressure_[elemIdx] = std::min(this->minRefPressure_[elemIdx], fs.pressure(refPressurePhaseIdx_()));
1820 }
1821 }
1822
1823 virtual void readEquilInitialCondition_() = 0;
1825
1826 // update the hysteresis parameters of the material laws for the whole grid
1828 {
1829 if (!materialLawManager_->enableHysteresis())
1830 return false;
1831
1832 // we need to update the hysteresis data for _all_ elements (i.e., not just the
1833 // interior ones) to avoid desynchronization of the processes in the parallel case!
1834 this->updateProperty_("FlowProblem::updateHysteresis_() failed:",
1835 [this](unsigned compressedDofIdx, const IntensiveQuantities& iq)
1836 {
1837 materialLawManager_->updateHysteresis(iq.fluidState(), compressedDofIdx);
1838 });
1839 return true;
1840 }
1841
1842
1843 bool updateHysteresis_(unsigned compressedDofIdx, const IntensiveQuantities& iq)
1844 {
1845 OPM_TIMEBLOCK_LOCAL(updateHysteresis_, Subsystem::SatProps);
1846 materialLawManager_->updateHysteresis(iq.fluidState(), compressedDofIdx);
1847 //TODO change materials to give a bool
1848 return true;
1849 }
1850
1851 Scalar getRockCompTransMultVal(std::size_t dofIdx) const
1852 {
1853 if (this->rockCompTransMultVal_.empty())
1854 return 1.0;
1855
1856 return this->rockCompTransMultVal_[dofIdx];
1857 }
1858
1859protected:
1868 void initGravity_(const EclipseState& eclState)
1869 {
1870 this->gravity_ = 0.0;
1871
1872 if (Parameters::Get<Parameters::EnableGravity>() &&
1873 eclState.getInitConfig().hasGravity())
1874 {
1875 // unit::gravity is 9.80665 m^2/s--i.e., standard measure at Tellus equator.
1876 this->gravity_[dim - 1] = unit::gravity;
1877 }
1878 }
1879
1881 {
1882 ConditionalStorage<enableFullyImplicitThermal, Scalar> thermalHalfTransIn;
1883 ConditionalStorage<enableFullyImplicitThermal, Scalar> thermalHalfTransOut;
1884 ConditionalStorage<enableDiffusion, Scalar> diffusivity;
1885 ConditionalStorage<enableDispersion, Scalar> dispersivity;
1887 };
1888
1889 // update the prefetch friendly data object
1891 {
1892 const auto& distFn =
1893 [this](PffDofData_& dofData,
1894 const Stencil& stencil,
1895 unsigned localDofIdx)
1896 -> void
1897 {
1898 const auto& elementMapper = this->model().elementMapper();
1899
1900 unsigned globalElemIdx = elementMapper.index(stencil.entity(localDofIdx));
1901 if (localDofIdx != 0) {
1902 unsigned globalCenterElemIdx = elementMapper.index(stencil.entity(/*dofIdx=*/0));
1903 dofData.transmissibility = transmissibilities_.transmissibility(globalCenterElemIdx, globalElemIdx);
1904
1905 if constexpr (enableFullyImplicitThermal) {
1906 *dofData.thermalHalfTransIn = transmissibilities_.thermalHalfTrans(globalCenterElemIdx, globalElemIdx);
1907 *dofData.thermalHalfTransOut = transmissibilities_.thermalHalfTrans(globalElemIdx, globalCenterElemIdx);
1908 }
1909 if constexpr (enableDiffusion)
1910 *dofData.diffusivity = transmissibilities_.diffusivity(globalCenterElemIdx, globalElemIdx);
1911 if (enableDispersion)
1912 dofData.dispersivity = transmissibilities_.dispersivity(globalCenterElemIdx, globalElemIdx);
1913 }
1914 };
1915
1916 pffDofData_.update(distFn);
1917 }
1918
1919 virtual void updateExplicitQuantities_(int episodeIdx, int timeStepSize, bool first_step_after_restart) = 0;
1920
1922 {
1923 const auto& simulator = this->simulator();
1924 const auto& vanguard = simulator.vanguard();
1925 const auto& bcconfig = vanguard.eclState().getSimulationConfig().bcconfig();
1926 if (bcconfig.size() > 0) {
1927 nonTrivialBoundaryConditions_ = true;
1928
1929 std::size_t numCartDof = vanguard.cartesianSize();
1930 unsigned numElems = vanguard.gridView().size(/*codim=*/0);
1931 std::vector<int> cartesianToCompressedElemIdx(numCartDof, -1);
1932
1933 for (unsigned elemIdx = 0; elemIdx < numElems; ++elemIdx)
1934 cartesianToCompressedElemIdx[vanguard.cartesianIndex(elemIdx)] = elemIdx;
1935
1936 bcindex_.resize(numElems, 0);
1937 auto loopAndApply = [&cartesianToCompressedElemIdx,
1938 &vanguard](const auto& bcface,
1939 auto apply)
1940 {
1941 for (int i = bcface.i1; i <= bcface.i2; ++i) {
1942 for (int j = bcface.j1; j <= bcface.j2; ++j) {
1943 for (int k = bcface.k1; k <= bcface.k2; ++k) {
1944 std::array<int, 3> tmp = {i,j,k};
1945 auto elemIdx = cartesianToCompressedElemIdx[vanguard.cartesianIndex(tmp)];
1946 if (elemIdx >= 0)
1947 apply(elemIdx);
1948 }
1949 }
1950 }
1951 };
1952 for (const auto& bcface : bcconfig) {
1953 std::vector<int>& data = bcindex_(bcface.dir);
1954 const int index = bcface.index;
1955 loopAndApply(bcface,
1956 [&data,index](int elemIdx)
1957 { data[elemIdx] = index; });
1958 }
1959 }
1960 }
1961
1962 // this method applies the runtime constraints specified via the deck and/or command
1963 // line parameters for the size of the next time step.
1965 {
1966 if constexpr (enableExperiments) {
1967 const auto& simulator = this->simulator();
1968 const auto& schedule = simulator.vanguard().schedule();
1969 int episodeIdx = simulator.episodeIndex();
1970
1971 // first thing in the morning, limit the time step size to the maximum size
1972 Scalar maxTimeStepSize = Parameters::Get<Parameters::SolverMaxTimeStepInDays<Scalar>>() * 24 * 60 * 60;
1973 int reportStepIdx = std::max(episodeIdx, 0);
1974 if (this->enableTuning_) {
1975 const auto& tuning = schedule[reportStepIdx].tuning();
1976 maxTimeStepSize = tuning.TSMAXZ;
1977 }
1978
1979 dtNext = std::min(dtNext, maxTimeStepSize);
1980
1981 Scalar remainingEpisodeTime =
1982 simulator.episodeStartTime() + simulator.episodeLength()
1983 - (simulator.startTime() + simulator.time());
1984 assert(remainingEpisodeTime >= 0.0);
1985
1986 // if we would have a small amount of time left over in the current episode, make
1987 // two equal time steps instead of a big and a small one
1988 if (remainingEpisodeTime/2.0 < dtNext && dtNext < remainingEpisodeTime*(1.0 - 1e-5))
1989 // note: limiting to the maximum time step size here is probably not strictly
1990 // necessary, but it should not hurt and is more fool-proof
1991 dtNext = std::min(maxTimeStepSize, remainingEpisodeTime/2.0);
1992
1993 if (simulator.episodeStarts()) {
1994 // if a well event occurred, respect the limit for the maximum time step after
1995 // that, too
1996 const auto& events = simulator.vanguard().schedule()[reportStepIdx].events();
1997 bool wellEventOccured =
1998 events.hasEvent(ScheduleEvents::NEW_WELL)
1999 || events.hasEvent(ScheduleEvents::PRODUCTION_UPDATE)
2000 || events.hasEvent(ScheduleEvents::INJECTION_UPDATE)
2001 || events.hasEvent(ScheduleEvents::WELL_STATUS_CHANGE);
2002 if (episodeIdx >= 0 && wellEventOccured && this->maxTimeStepAfterWellEvent_ > 0)
2003 dtNext = std::min(dtNext, this->maxTimeStepAfterWellEvent_);
2004 }
2005 }
2006
2007 return dtNext;
2008 }
2009
2011 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2012 return oilPhaseIdx;
2013 }
2014 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2015 return gasPhaseIdx;
2016 }
2017 else {
2018 return waterPhaseIdx;
2019 }
2020 }
2021
2023 {
2024 const auto& model = this->simulator().model();
2025 std::size_t numGridDof = this->model().numGridDof();
2026 this->rockCompTransMultVal_.resize(numGridDof, 1.0);
2027 for (std::size_t elementIdx = 0; elementIdx < numGridDof; ++elementIdx) {
2028 const auto& iq = model.intensiveQuantities(elementIdx, /*timeIdx=*/ 0);
2029 Scalar trans_mult = computeRockCompTransMultiplier_<Scalar>(iq, elementIdx);
2030 this->rockCompTransMultVal_[elementIdx] = trans_mult;
2031 }
2032 }
2033
2039 template <class LhsEval>
2040 LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities& intQuants, unsigned elementIdx) const
2041 {
2042 auto obtain = [](const auto& value)
2043 {
2044 if constexpr (std::is_same_v<LhsEval, Scalar>) {
2045 return getValue(value);
2046 } else {
2047 return value;
2048 }
2049 };
2050
2051 return computeRockCompTransMultiplier_<LhsEval>(intQuants, elementIdx, obtain);
2052 }
2053
2054 template <class LhsEval, class Callback>
2055 LhsEval computeRockCompTransMultiplier_(const IntensiveQuantities& intQuants, unsigned elementIdx, Callback& obtain) const
2056 {
2057 OPM_TIMEBLOCK_LOCAL(computeRockCompTransMultiplier, Subsystem::PvtProps);
2058 if (this->rockCompTransMult_.empty() && this->rockCompTransMultWc_.empty())
2059 return 1.0;
2060
2061 unsigned tableIdx = 0;
2062 if (!this->rockTableIdx_.empty())
2063 tableIdx = this->rockTableIdx_[elementIdx];
2064
2065 const auto& fs = intQuants.fluidState();
2066 const auto& rock_config = this->simulator().vanguard().eclState().getSimulationConfig().rock_config();
2067
2068 if (!this->rockCompTransMultElastic_.empty()) {
2069 // ROCKCOMP HYSTERESIS=HYSTER: see rockCompPoroMultiplier() above.
2070 LhsEval effectivePressure = obtain(fs.pressure(refPressurePhaseIdx_()));
2071 LhsEval turningPressure = this->minRefPressure_[elementIdx];
2072
2073 if (!this->overburdenPressure_.empty()) {
2074 effectivePressure -= this->overburdenPressure_[elementIdx];
2075 turningPressure -= this->overburdenPressure_[elementIdx];
2076 }
2077
2078 if (rock_config.store()) {
2079 const auto& initialPressure = asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
2080 effectivePressure -= initialPressure;
2081 turningPressure -= initialPressure;
2082 }
2083
2084 if (effectivePressure <= turningPressure)
2085 return this->rockCompTransMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
2086
2087 return this->rockCompTransMultElastic_[tableIdx].eval(turningPressure, effectivePressure, /*extrapolation=*/true);
2088 }
2089
2090 LhsEval effectivePressure = obtain(fs.pressure(refPressurePhaseIdx_()));
2091 if (!this->minRefPressure_.empty())
2092 // The pore space change is irreversible
2093 effectivePressure =
2094 min(obtain(fs.pressure(refPressurePhaseIdx_())),
2095 this->minRefPressure_[elementIdx]);
2096
2097 if (!this->overburdenPressure_.empty())
2098 effectivePressure -= this->overburdenPressure_[elementIdx];
2099
2100 if (rock_config.store()) {
2101 effectivePressure -= asImp_().initialFluidState(elementIdx).pressure(refPressurePhaseIdx_());
2102 }
2103
2104 if (!this->rockCompTransMult_.empty())
2105 return this->rockCompTransMult_[tableIdx].eval(effectivePressure, /*extrapolation=*/true);
2106
2107 // water compaction
2108 assert(!this->rockCompTransMultWc_.empty());
2109 LhsEval SwMax = max(obtain(fs.saturation(waterPhaseIdx)), this->maxWaterSaturation_[elementIdx]);
2110 LhsEval SwDeltaMax = SwMax - asImp_().initialFluidStates()[elementIdx].saturation(waterPhaseIdx);
2111
2112 return this->rockCompTransMultWc_[tableIdx].eval(effectivePressure, SwDeltaMax, /*extrapolation=*/true);
2113 }
2114
2115 typename Vanguard::TransmissibilityType transmissibilities_;
2116
2117 std::shared_ptr<EclMaterialLawManager> materialLawManager_;
2118 std::shared_ptr<EclThermalLawManager> thermalLawManager_;
2119
2121
2124
2128
2131
2132 template<class T>
2133 struct BCData
2134 {
2135 std::array<std::vector<T>,6> data;
2136
2137 void resize(std::size_t size, T defVal)
2138 {
2139 for (auto& d : data)
2140 d.resize(size, defVal);
2141 }
2142
2143 const std::vector<T>& operator()(FaceDir::DirEnum dir) const
2144 {
2145 if (dir == FaceDir::DirEnum::Unknown)
2146 throw std::runtime_error("Tried to access BC data for the 'Unknown' direction");
2147 int idx = 0;
2148 int div = static_cast<int>(dir);
2149 while ((div /= 2) >= 1)
2150 ++idx;
2151 assert(idx >= 0 && idx <= 5);
2152 return data[idx];
2153 }
2154
2155 std::vector<T>& operator()(FaceDir::DirEnum dir)
2156 {
2157 return const_cast<std::vector<T>&>(std::as_const(*this)(dir));
2158 }
2159 };
2160
2161 virtual void handleSolventBC(const BCState::BCFace&, RateVector&) const = 0;
2162
2163 virtual void handlePolymerBC(const BCState::BCFace&, RateVector&) const = 0;
2164
2165 virtual void handleMicrBC(const BCState::BCFace&, RateVector&) const = 0;
2166
2167 virtual void handleOxygBC(const BCState::BCFace&, RateVector&) const = 0;
2168
2169 virtual void handleUreaBC(const BCState::BCFace&, RateVector&) const = 0;
2170
2172 bool nonTrivialBoundaryConditions_ = false;
2173 bool first_step_ = true;
2174 bool enable_state_rollback_ = false;
2175
2183 {
2184 bool first_step = true;
2185 std::vector<Scalar> max_polymer_adsorption;
2186 std::vector<Scalar> max_oil_saturation;
2187 std::vector<Scalar> max_water_saturation;
2188 std::vector<Scalar> min_ref_pressure;
2189 std::vector<Scalar> rock_comp_trans_mult_val;
2190 };
2191
2193
2196 virtual bool episodeWillBeOver() const
2197 {
2198 return this->simulator().episodeWillBeOver();
2199 }
2200};
2201
2202} // namespace Opm
2203
2204#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:62
Scalar maxPolymerAdsorption(unsigned elemIdx) const
Returns the max polymer adsorption value.
Definition: FlowGenericProblem_impl.hpp:971
unsigned pvtRegionIndex(unsigned elemIdx) const
Returns the index the relevant PVT region given a cell index.
Definition: FlowGenericProblem_impl.hpp:930
Scalar rockBiotTemp(unsigned elementIdx) const
Returns the rock compressibility of an element due to thermoelasticity.
Definition: FlowGenericProblem_impl.hpp:428
std::array< std::vector< Scalar >, 2 > rockFraction_
Definition: FlowGenericProblem.hpp:364
std::vector< TabulatedTwoDFunction > rockCompPoroMultWc_
Definition: FlowGenericProblem.hpp:373
Scalar porosity(unsigned globalSpaceIdx, unsigned timeIdx) const
Direct indexed access to the porosity.
Definition: FlowGenericProblem_impl.hpp:409
Scalar rockCompressibility(unsigned globalSpaceIdx) const
Definition: FlowGenericProblem_impl.hpp:394
unsigned miscnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant MISC region given a cell index.
Definition: FlowGenericProblem_impl.hpp:950
unsigned satnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant saturation function region given a cell index.
Definition: FlowGenericProblem_impl.hpp:940
Scalar lame(unsigned elementIdx) const
Direct access to Lame's second parameter in an element.
Definition: FlowGenericProblem_impl.hpp:440
void beginTimeStep_(bool enableExperiments, int episodeIdx, int timeStepIndex, Scalar startTime, Scalar time, Scalar timeStepSize, Scalar endTime)
Definition: FlowGenericProblem_impl.hpp:666
std::vector< TabulatedTwoDFunction > rockCompPoroMultElastic_
Definition: FlowGenericProblem.hpp:381
unsigned plmixnumRegionIndex(unsigned elemIdx) const
Returns the index the relevant PLMIXNUM (for polymer module) region given a cell index.
Definition: FlowGenericProblem_impl.hpp:960
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:156
std::array< std::vector< Scalar >, 2 > referencePorosity_
Definition: FlowGenericProblem.hpp:363
Scalar rockBiotComp(unsigned elementIdx) const
Returns the rock compressibility of an element due to poroelasticity.
Definition: FlowGenericProblem_impl.hpp:417
bool beginEpisode_(bool enableExperiments, int episodeIdx)
Definition: FlowGenericProblem_impl.hpp:629
bool shouldWriteOutput() const
Always returns true. The ecl output writer takes care of the rest.
Definition: FlowGenericProblem.hpp:320
static std::string helpPreamble(int, const char **argv)
Definition: FlowGenericProblem_impl.hpp:134
Scalar biotTemp(unsigned elementIdx) const
Direct access to Biot temperature coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:492
bool shouldWriteRestartFile() const
Returns true if an eWoms restart file should be written to disk.
Definition: FlowGenericProblem.hpp:329
Scalar biotCoeff(unsigned elementIdx) const
Direct access to Biot coefficient in an element.
Definition: FlowGenericProblem_impl.hpp:471
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:2196
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:1382
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:1673
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:1415
int boundaryConditionIndex(const unsigned int globalSpaceIdx, const int directionId) const
Index of the BCCON region applied to the given face of a cell, 0 if none.
Definition: FlowProblem.hpp:1307
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:1843
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:1868
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:2173
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:2123
GlobalEqVector drift_
Definition: FlowProblem.hpp:2120
bool updateMinPressure_()
Definition: FlowProblem.hpp:1625
EclMaterialLawManager & materialLawManager()
Definition: FlowProblem.hpp:954
std::function< std::vector< double >(const FieldPropsManager &, const std::string &)> fieldPropDoubleOnLeafAssigner_()
Definition: FlowProblem.hpp:1658
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:1739
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:2055
BCData< int > bcindex_
Definition: FlowProblem.hpp:2171
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:1595
virtual void handleUreaBC(const BCState::BCFace &, RateVector &) const =0
FlowThresholdPressure< TypeTag > thresholdPressures_
Definition: FlowProblem.hpp:2129
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:1640
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
const EclMaterialLawManager & materialLawManager() const
Returns the ECL material law manager.
Definition: FlowProblem.hpp:914
FlowProblem(Simulator &simulator)
Definition: FlowProblem.hpp:235
ModuleParams moduleParams_
Definition: FlowProblem.hpp:2130
@ 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:2040
std::pair< BCType, RateVector > boundaryCondition(const unsigned int globalSpaceIdx, const int directionId) const
Definition: FlowProblem.hpp:1315
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:2125
@ 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:2126
@ enableThermalFluxBoundaries
Definition: FlowProblem.hpp:142
const TracerModel & tracerModel() const
Definition: FlowProblem.hpp:724
WellModel wellModel_
Definition: FlowProblem.hpp:2122
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:1401
static constexpr bool enablePolymerMolarWeight
Definition: FlowProblem.hpp:134
Scalar getRockCompTransMultVal(std::size_t dofIdx) const
Definition: FlowProblem.hpp:1851
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
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:2022
@ numPhases
Definition: FlowProblem.hpp:123
std::shared_ptr< EclThermalLawManager > thermalLawManager_
Definition: FlowProblem.hpp:2118
Scalar limitNextTimeStepSize_(Scalar dtNext) const
Definition: FlowProblem.hpp:1964
void finishTransmissibilities_()
Definition: FlowProblem.hpp:1428
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:2192
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:1827
void readThermalParameters_()
Definition: FlowProblem.hpp:1722
void serializeOp(Serializer &serializer)
Definition: FlowProblem.hpp:1370
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:2127
static constexpr bool enableExtbo
Definition: FlowProblem.hpp:131
std::shared_ptr< EclMaterialLawManager > materialLawManager_
Definition: FlowProblem.hpp:2117
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:1544
bool prepareTransmissibilityOutput_(EclWriterType &eclWriter, const bool enableEclOutput)
Definition: FlowProblem.hpp:1437
LhsEval rockCompTransMultiplier(const IntensiveQuantities &intQuants, unsigned elementIdx, Callback &obtain) const
Definition: FlowProblem.hpp:1286
@ oilCompIdx
Definition: FlowProblem.hpp:151
void initializeSimulatorTime_()
Definition: FlowProblem.hpp:1496
bool updateMaxOilSaturation_()
Definition: FlowProblem.hpp:1563
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblem.hpp:200
void updatePffDofData_()
Definition: FlowProblem.hpp:1890
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:2172
GetPropType< TypeTag, Properties::Problem > Implementation
Definition: FlowProblem.hpp:106
void readBoundaryConditions_()
Definition: FlowProblem.hpp:1921
void updateRelperms(std::array< Evaluation, numPhases > &mobility, DirectionalMobilityPtr &dirMob, FluidState &fluidState, unsigned globalSpaceIdx) const
Definition: FlowProblem.hpp:921
Vanguard::TransmissibilityType transmissibilities_
Definition: FlowProblem.hpp:2115
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:1798
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:2174
Scalar biotCoeff(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:816
std::shared_ptr< const EclThermalLawManager > thermalLawManager() const
Definition: FlowProblem.hpp:917
bool updateMaxWaterSaturation_(unsigned compressedDofIdx, const IntensiveQuantities &iq)
Definition: FlowProblem.hpp:1611
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:1581
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:1520
int refPressurePhaseIdx_() const
Definition: FlowProblem.hpp:2010
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:1682
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:1764
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:2134
const std::vector< T > & operator()(FaceDir::DirEnum dir) const
Definition: FlowProblem.hpp:2143
void resize(std::size_t size, T defVal)
Definition: FlowProblem.hpp:2137
std::vector< T > & operator()(FaceDir::DirEnum dir)
Definition: FlowProblem.hpp:2155
std::array< std::vector< T >, 6 > data
Definition: FlowProblem.hpp:2135
Definition: FlowProblem.hpp:1881
ConditionalStorage< enableFullyImplicitThermal, Scalar > thermalHalfTransOut
Definition: FlowProblem.hpp:1883
ConditionalStorage< enableFullyImplicitThermal, Scalar > thermalHalfTransIn
Definition: FlowProblem.hpp:1882
ConditionalStorage< enableDiffusion, Scalar > diffusivity
Definition: FlowProblem.hpp:1884
ConditionalStorage< enableDispersion, Scalar > dispersivity
Definition: FlowProblem.hpp:1885
Scalar transmissibility
Definition: FlowProblem.hpp:1886
Explicit quantities as they stood at the start of the current timestep, restored if that timestep fai...
Definition: FlowProblem.hpp:2183
bool first_step
first step of the episode
Definition: FlowProblem.hpp:2184
std::vector< Scalar > min_ref_pressure
ROCKCOMP irreversible compaction.
Definition: FlowProblem.hpp:2188
std::vector< Scalar > rock_comp_trans_mult_val
ROCKCOMP transmissibility multiplier.
Definition: FlowProblem.hpp:2189
std::vector< Scalar > max_polymer_adsorption
POLYMER.
Definition: FlowProblem.hpp:2185
std::vector< Scalar > max_water_saturation
ROCKCOMP water-induced compaction.
Definition: FlowProblem.hpp:2187
std::vector< Scalar > max_oil_saturation
VAPPARS / DRSDT saturation history.
Definition: FlowProblem.hpp:2186