MixingRateControls.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 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 2 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19 Consult the COPYING file in the top-level source directory of this
20 module for the precise wording of the license and the list of
21 copyright holders.
22*/
28#ifndef OPM_MIXING_RATE_CONTROLS_HPP
29#define OPM_MIXING_RATE_CONTROLS_HPP
30
31#include <opm/input/eclipse/Schedule/Schedule.hpp>
32
33#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
34#include <opm/material/common/MathToolbox.hpp>
35
36#include <limits>
37#include <vector>
38
39namespace Opm {
40
41class EclipseState;
42
44template<class FluidSystem>
46{
47public:
48 using Scalar = typename FluidSystem::Scalar;
49
50 MixingRateControls(const Schedule& schedule);
52
53 static MixingRateControls serializationTestObject(const Schedule& schedule);
54
55 bool operator==(const MixingRateControls& rhs) const;
57
58 void init(std::size_t numDof, int episodeIdx, const unsigned ntpvt);
59
60 bool drsdtActive(int episodeIdx) const;
61 bool drvdtActive(int episodeIdx) const;
62 bool drsdtConvective(int episodeIdx) const;
63
64 bool drsdtActive(int episodeIdx, std::size_t pvtRegionIdx) const;
65 bool drvdtActive(int episodeIdx, std::size_t pvtRegionIdx) const;
66 bool drsdtConvective(int episodeIdx, std::size_t pvtRegionIdx) const;
70 Scalar drsdtcon(const unsigned elemIdx,
71 int episodeIdx,
72 const int pvtRegionIdx) const;
73
79 unsigned globalDofIdx,
80 const int episodeIdx,
81 const int pvtRegionIdx) const;
82
87 Scalar maxOilVaporizationFactor(const unsigned timeIdx,
88 const unsigned globalDofIdx,
89 const int episodeIdx,
90 const int pvtRegionIdx) const;
91
92 void updateExplicitQuantities(const int episodeIdx,
93 const Scalar timeStepSize);
94
95 void updateLastValues(const unsigned elemIdx,
96 const Scalar Rs,
97 const Scalar Rv);
98
99 void updateMaxValues(const int episodeIdx,
100 const Scalar timeStepSize);
101
102 template<class Serializer>
103 void serializeOp(Serializer& serializer)
104 {
105 serializer(lastRv_);
106 serializer(maxDRv_);
107 serializer(convectiveDrs_);
108 serializer(lastRs_);
109 serializer(maxDRs_);
110 serializer(dRsDtOnlyFreeGas_);
111 }
112
113 template<class IntensiveQuantities>
114 void update(unsigned compressedDofIdx,
115 const IntensiveQuantities& iq,
116 const int episodeIdx,
117 const Scalar gravity,
118 const Scalar permZ,
119 const Scalar distZ,
120 const int pvtRegionIdx)
121 {
122 const auto& oilVaporizationControl = schedule_[episodeIdx].oilvap();
123
124 if (oilVaporizationControl.drsdtConvective(pvtRegionIdx)) {
125 // This implements the convective DRSDT as described in
126 // Sandve et al. "Convective dissolution in field scale CO2 storage simulations using the OPM Flow
127 // simulator" Submitted to TCCS 11, 2021
128 // modification and introduction of regimes following Mykkeltvedt et al. Submitted to TIMP 2024
129 const auto& fs = iq.fluidState();
130
131 const auto& temperature = (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) ?
132 getValue(fs.temperature(FluidSystem::waterPhaseIdx)) :
133 getValue(fs.temperature(FluidSystem::oilPhaseIdx));
134 const auto& pressure = (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) ?
135 getValue(fs.pressure(FluidSystem::waterPhaseIdx)) :
136 getValue(fs.pressure(FluidSystem::oilPhaseIdx));
137 const auto& pressuregas = getValue(fs.pressure(FluidSystem::gasPhaseIdx));
138 const auto& rs = (FluidSystem::phaseIsActive(FluidSystem::waterPhaseIdx)) ?
139 getValue(fs.Rsw()) :
140 getValue(fs.Rs());
141
142 const auto& salt = getValue(fs.saltSaturation());
143
144 this->updateConvectiveDRsDt_(compressedDofIdx,
145 temperature,
146 pressure,
147 pressuregas,
148 rs,
149 getValue(fs.saturation(FluidSystem::gasPhaseIdx)),
150 getValue(iq.porosity()),
151 permZ,
152 distZ,
153 gravity,
154 salt,
155 oilVaporizationControl.getMaxDRSDT(fs.pvtRegionIndex()),
156 oilVaporizationControl.getPsi(fs.pvtRegionIndex()),
157 oilVaporizationControl.getOmega(fs.pvtRegionIndex()),
158 fs.pvtRegionIndex());
159 }
160
161 if (oilVaporizationControl.drsdtActive(pvtRegionIdx)) {
162 const auto& fs = iq.fluidState();
163
164 using FluidState = typename std::decay<decltype(fs)>::type;
165 constexpr Scalar freeGasMinSaturation_ = 1e-7;
166 if (oilVaporizationControl.getOption(pvtRegionIdx) ||
167 fs.saturation(FluidSystem::gasPhaseIdx) > freeGasMinSaturation_) {
168 lastRs_[compressedDofIdx]
169 = ((FluidSystem::enableDissolvedGasInWater())) ?
170 BlackOil::template getRsw_<FluidSystem, FluidState, Scalar>(fs, iq.pvtRegionIndex()) :
171 BlackOil::template getRs_<FluidSystem, FluidState, Scalar>(fs, iq.pvtRegionIndex());
172 }
173 else
174 lastRs_[compressedDofIdx] = std::numeric_limits<Scalar>::infinity();
175 }
176
177 if (oilVaporizationControl.drvdtActive(pvtRegionIdx)) {
178 const auto& fs = iq.fluidState();
179 using FluidState = typename std::decay<decltype(fs)>::type;
180 lastRv_[compressedDofIdx]
181 = BlackOil::template getRv_<FluidSystem, FluidState, Scalar>(fs, iq.pvtRegionIndex());
182 }
183 }
184
185private:
186 void updateConvectiveDRsDt_(const unsigned compressedDofIdx,
187 const Scalar t,
188 const Scalar p,
189 const Scalar pg,
190 const Scalar rs,
191 const Scalar sg,
192 const Scalar poro,
193 const Scalar permz,
194 const Scalar distZ,
195 const Scalar gravity,
196 const Scalar salt,
197 const Scalar Xhi,
198 const Scalar Psi,
199 const Scalar omegainn,
200 const int pvtRegionIndex);
201
202 std::vector<Scalar> lastRv_;
203 std::vector<Scalar> maxDRv_;
204
205 std::vector<Scalar> convectiveDrs_;
206 std::vector<Scalar> lastRs_;
207 std::vector<Scalar> maxDRs_;
208 std::vector<bool> dRsDtOnlyFreeGas_; // apply the DRSDT rate limit only to cells that exhibit free gas
209
210 const Schedule& schedule_;
211};
212
213} // namespace Opm
214
215#endif // OPM_MIXING_RATE_CONTROLS_HPP
Class handling mixing rate controls for a FlowProblemBlackoil.
Definition: MixingRateControls.hpp:46
Scalar maxOilVaporizationFactor(const unsigned timeIdx, const unsigned globalDofIdx, const int episodeIdx, const int pvtRegionIdx) const
Returns the maximum value of the oil vaporization factor at the current time for a given degree of fr...
void updateExplicitQuantities(const int episodeIdx, const Scalar timeStepSize)
bool drsdtActive(int episodeIdx, std::size_t pvtRegionIdx) const
typename FluidSystem::Scalar Scalar
Definition: MixingRateControls.hpp:48
bool drsdtConvective(int episodeIdx) const
Scalar maxGasDissolutionFactor(unsigned timeIdx, unsigned globalDofIdx, const int episodeIdx, const int pvtRegionIdx) const
Returns the maximum value of the gas dissolution factor at the current time for a given degree of fre...
MixingRateControls(const MixingRateControls &rhs)
void serializeOp(Serializer &serializer)
Definition: MixingRateControls.hpp:103
void init(std::size_t numDof, int episodeIdx, const unsigned ntpvt)
bool drsdtActive(int episodeIdx) const
bool operator==(const MixingRateControls &rhs) const
MixingRateControls & operator=(const MixingRateControls &rhs)
bool drvdtActive(int episodeIdx, std::size_t pvtRegionIdx) const
void updateLastValues(const unsigned elemIdx, const Scalar Rs, const Scalar Rv)
bool drvdtActive(int episodeIdx) const
static MixingRateControls serializationTestObject(const Schedule &schedule)
MixingRateControls(const Schedule &schedule)
Scalar drsdtcon(const unsigned elemIdx, int episodeIdx, const int pvtRegionIdx) const
Returns the dynamic drsdt convective mixing value.
void updateMaxValues(const int episodeIdx, const Scalar timeStepSize)
bool drsdtConvective(int episodeIdx, std::size_t pvtRegionIdx) const
void update(unsigned compressedDofIdx, const IntensiveQuantities &iq, const int episodeIdx, const Scalar gravity, const Scalar permZ, const Scalar distZ, const int pvtRegionIdx)
Definition: MixingRateControls.hpp:114
Definition: blackoilboundaryratevector.hh:37