opm-common
Loading...
Searching...
No Matches
EclHysteresisTwoPhaseLaw.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*/
27#ifndef OPM_ECL_HYSTERESIS_TWO_PHASE_LAW_HPP
28#define OPM_ECL_HYSTERESIS_TWO_PHASE_LAW_HPP
29#include <opm/common/TimingMacros.hpp>
31#include <stdexcept>
32
33namespace Opm {
34
40template <class EffectiveLawT,
42class EclHysteresisTwoPhaseLaw : public EffectiveLawT::Traits
43{
44public:
45 using EffectiveLaw = EffectiveLawT;
46 using EffectiveLawParams = typename EffectiveLaw::Params;
47
48 using Traits = typename EffectiveLaw::Traits;
49 using Params = ParamsT;
50 using Scalar = typename EffectiveLaw::Scalar;
51
52 enum { wettingPhaseIdx = Traits::wettingPhaseIdx };
53 enum { nonWettingPhaseIdx = Traits::nonWettingPhaseIdx };
54
56 static constexpr int numPhases = EffectiveLaw::numPhases;
57 static_assert(numPhases == 2,
58 "The endpoint scaling applies to the nested twophase laws, not to "
59 "the threephase one!");
60
63 static constexpr bool implementsTwoPhaseApi = true;
64
65 static_assert(EffectiveLaw::implementsTwoPhaseApi,
66 "The material laws put into EclEpsTwoPhaseLaw must implement the "
67 "two-phase material law API!");
68
71 static constexpr bool implementsTwoPhaseSatApi = true;
72
73 static_assert(EffectiveLaw::implementsTwoPhaseSatApi,
74 "The material laws put into EclEpsTwoPhaseLaw must implement the "
75 "two-phase material law saturation API!");
76
79 static constexpr bool isSaturationDependent = true;
80
83 static constexpr bool isPressureDependent = false;
84
87 static constexpr bool isTemperatureDependent = false;
88
91 static constexpr bool isCompositionDependent = false;
92
103 template <class Container, class FluidState>
104 static void capillaryPressures(Container& /* values */,
105 const Params& /* params */,
106 const FluidState& /* fs */)
107 {
108 throw std::invalid_argument("The capillaryPressures(fs) method is not yet implemented");
109 }
110
121 template <class Container, class FluidState>
122 static void relativePermeabilities(Container& /* values */,
123 const Params& /* params */,
124 const FluidState& /* fs */)
125 {
126 throw std::invalid_argument("The pcnw(fs) method is not yet implemented");
127 }
128
140 template <class FluidState, class Evaluation = typename FluidState::Scalar>
141 static Evaluation pcnw(const Params& /* params */,
142 const FluidState& /* fs */)
143 {
144 throw std::invalid_argument("The pcnw(fs) method is not yet implemented");
145 }
146
147 template <class Evaluation, class ...Args>
148 static Evaluation twoPhaseSatPcnw(const Params& params, const Evaluation& Sw)
149 {
150 OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
151 // if no pc hysteresis is enabled, use the drainage curve
152 if (!params.config().enableHysteresis() || params.config().pcHysteresisModel() < 0)
153 return EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.drainageParams(), Sw);
154
155 // Initial imbibition process
156 if (params.initialImb()) {
157 if (Sw >= params.pcSwMic()) {
158 return EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.imbibitionParams(), Sw);
159 }
160 else { // Reversal
161 const Evaluation& F = (1.0/(params.pcSwMic()-Sw+params.curvatureCapPrs())-1.0/params.curvatureCapPrs())
162 / (1.0/(params.pcSwMic()-params.Swcrd()+params.curvatureCapPrs())-1.0/params.curvatureCapPrs());
163
164 const Evaluation& Pcd = EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.drainageParams(), Sw);
165 const Evaluation& Pci = EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.imbibitionParams(), Sw);
166 const Evaluation& pc_Killough = Pci+F*(Pcd-Pci);
167
168 return pc_Killough;
169 }
170 }
171
172 // Initial drainage process
173 if (Sw <= params.pcSwMdc())
174 return EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.drainageParams(), Sw);
175
176 // Reversal
177 Scalar Swma = 1.0-params.Sncrt();
178 if (Sw >= Swma) {
179 const Evaluation& Pci = EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.imbibitionParams(), Sw);
180 return Pci;
181 }
182 else {
183 Scalar pciwght = params.pcWght(); // Align pci and pcd at Swir
184 Evaluation SwScaled = Sw; // Use without scaling. This is Killough 1976
185 if (params.config().enablePcScalingHyst()) {
186 const Evaluation SwScan = (Sw-params.pcSwMdc())/(Swma-params.pcSwMdc());
187 SwScaled = params.Swcri() + (1 - params.Sncri() - params.Swcri()) * SwScan;
188 }
189 const Evaluation dPc = pciwght*EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.imbibitionParams(), SwScaled) - EffectiveLaw::twoPhaseSatPcnw(params.drainageParams(), SwScaled);
190 const Evaluation Pcd = EffectiveLaw::template twoPhaseSatPcnw<Evaluation, Args...>(params.drainageParams(), Sw);
191 if (dPc == 0.0)
192 return Pcd;
193
194 const Evaluation F = (1.0/(Sw-params.pcSwMdc()+params.curvatureCapPrs())-1.0/params.curvatureCapPrs())
195 / (1.0/(Swma-params.pcSwMdc()+params.curvatureCapPrs())-1.0/params.curvatureCapPrs());
196
197 return Pcd+F*dPc;
198 }
199
200 return 0.0;
201 }
202
206 template <class Container, class FluidState>
207 static void saturations(Container& /* values */,
208 const Params& /* params */,
209 const FluidState& /* fs */)
210 {
211 throw std::invalid_argument("The saturations(fs) method is not yet implemented");
212 }
213
218 template <class FluidState, class Evaluation = typename FluidState::Scalar>
219 static Evaluation Sw(const Params& /* params */,
220 const FluidState& /* fs */)
221 {
222 throw std::invalid_argument("The Sw(fs) method is not yet implemented");
223 }
224
225 template <class Evaluation>
226 static Evaluation twoPhaseSatSw(const Params& /* params */,
227 const Evaluation& /* pc */)
228 {
229 throw std::invalid_argument("The twoPhaseSatSw(pc) method is not yet implemented");
230 }
231
236 template <class FluidState, class Evaluation = typename FluidState::Scalar>
237 static Evaluation Sn(const Params& /* params */,
238 const FluidState& /* fs */)
239 {
240 throw std::invalid_argument("The Sn(pc) method is not yet implemented");
241 }
242
243 template <class Evaluation>
244 static Evaluation twoPhaseSatSn(const Params& /* params */,
245 const Evaluation& /* pc */)
246 {
247 throw std::invalid_argument("The twoPhaseSatSn(pc) method is not yet implemented");
248 }
249
259 template <class FluidState, class Evaluation = typename FluidState::Scalar>
260 static Evaluation krw(const Params& /* params */,
261 const FluidState& /* fs */)
262 {
263 throw std::invalid_argument("The krw(fs) method is not yet implemented");
264 }
265
266 template <class Evaluation, class ...Args>
267 static Evaluation twoPhaseSatKrw(const Params& params, const Evaluation& Sw)
268 {
269
270 OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
271 // if no relperm hysteresis is enabled, use the drainage curve
272 if (!params.config().enableHysteresis() || params.config().krHysteresisModel() < 0)
273 return EffectiveLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.drainageParams(), Sw);
274
275 if (params.config().krHysteresisModel() == 0 || params.config().krHysteresisModel() == 2)
276 // use drainage curve for wetting phase
277 return EffectiveLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.drainageParams(), Sw);
278
279 // use imbibition curve for wetting phase
280 if (params.config().krHysteresisModel() == 1 || params.config().krHysteresisModel() == 3)
281 return EffectiveLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.imbibitionParams(), Sw);
282
283 if (Sw <= params.krnSwMdc()) {
284 return EffectiveLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.drainageParams(), Sw);
285 }
286 // Killough hysteresis for the wetting phase
287 assert(params.config().krHysteresisModel() == 4);
288 Evaluation Snorm = params.Sncri()+(1.0-Sw-params.Sncrt())*(params.Snmaxd()-params.Sncri())/(params.Snhy()-params.Sncrt());
289 Evaluation Krwi_snorm = EffectiveLaw::template twoPhaseSatKrw<Evaluation, Args...>(params.imbibitionParams(), 1 - Snorm);
290 return params.KrwdHy() + params.krwWght() * (Krwi_snorm - params.Krwi_snmax());
291 }
292
296 template <class FluidState, class Evaluation = typename FluidState::Scalar>
297 static Evaluation krn(const Params& /* params */,
298 const FluidState& /* fs */)
299 {
300 throw std::invalid_argument("The krn(fs) method is not yet implemented");
301 }
302
303 template <class Evaluation, class ...Args>
304 static Evaluation twoPhaseSatKrn(const Params& params, const Evaluation& Sw)
305 {
306 OPM_TIMEFUNCTION_LOCAL(Subsystem::SatProps);
307 // If WAG hysteresis is enabled, the convential hysteresis model is ignored.
308 // (Two-phase model, non-wetting: only gas in oil.)
309 if (params.gasOilHysteresisWAG()) {
310
311 // Primary drainage
312 if (Sw <= params.krnSwMdc() + params.tolWAG() && params.nState() == 1) {
313 return EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.drainageParams(), Sw);
314 }
315
316 // Imbibition or reversion to two-phase drainage retracing imb curve
317 // (Shift along primary drainage curve.)
318 if (params.nState() == 1) {
319 Evaluation Swf = params.computeSwf(Sw);
320 return EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.drainageParams(), Swf);
321 }
322
323 // Three-phase drainage along current secondary drainage curve
324 if (Sw <= params.krnSwDrainRevert()+params.tolWAG() /*&& params.nState()>=1 */) {
325 Evaluation Krg = EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.drainageParams(), Sw);
326 Evaluation KrgDrain2 = (Krg-params.krnDrainStart())*params.reductionDrain() + params.krnImbStart();
327 return KrgDrain2;
328 }
329
330 // Subsequent imbibition: Scanning curve derived from previous secondary drainage
331 if (Sw >= params.krnSwWAG()-params.tolWAG() /*&& Sw > params.krnSwDrainRevert() && params.nState()>=1 */) {
332 Evaluation KrgImb2 = params.computeKrImbWAG(Sw);
333 return KrgImb2;
334 }
335 else {/* Sw < params.krnSwWAG() */ // Reversion along "next" drainage curve
336 Evaluation Krg = EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.drainageParams(), Sw);
337 Evaluation KrgDrainNxt = (Krg-params.krnDrainStartNxt())*params.reductionDrainNxt() + params.krnImbStartNxt();
338 return KrgDrainNxt;
339 }
340 }
341 // if no relperm hysteresis is enabled, use the drainage curve
342 if (!params.config().enableHysteresis() || params.config().krHysteresisModel() < 0)
343 return EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.drainageParams(), Sw);
344
345 // if it is enabled, use either the drainage or the imbibition curve. if the
346 // imbibition curve is used, the saturation must be shifted.
347 if (Sw <= params.krnSwMdc()) {
348 return EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.drainageParams(), Sw);
349 }
350
351 if (params.config().krHysteresisModel() <= 1) { //Carlson
352 return EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.imbibitionParams(),
353 Sw + params.deltaSwImbKrn());
354 }
355
356 // Killough
357 assert(params.config().krHysteresisModel() == 2 || params.config().krHysteresisModel() == 3 || params.config().krHysteresisModel() == 4);
358 Evaluation Snorm = params.Sncri()+(1.0-Sw-params.Sncrt())*(params.Snmaxd()-params.Sncri())/(params.Snhy()-params.Sncrt());
359 return params.krnWght()*EffectiveLaw::template twoPhaseSatKrn<Evaluation, Args...>(params.imbibitionParams(),1.0-Snorm);
360 }
361};
362
363} // namespace Opm
364
365#endif
A default implementation of the parameters for the material law which implements the ECL relative per...
A default implementation of the parameters for the material law which implements the ECL relative per...
Definition EclHysteresisTwoPhaseLawParams.hpp:50
This material law implements the hysteresis model of the ECL file format.
Definition EclHysteresisTwoPhaseLaw.hpp:43
static constexpr bool isSaturationDependent
Specify whether the quantities defined by this material law are saturation dependent.
Definition EclHysteresisTwoPhaseLaw.hpp:79
static Evaluation krn(const Params &, const FluidState &)
The relative permeability of the non-wetting phase.
Definition EclHysteresisTwoPhaseLaw.hpp:297
static void capillaryPressures(Container &, const Params &, const FluidState &)
The capillary pressure-saturation curves depending on absolute saturations.
Definition EclHysteresisTwoPhaseLaw.hpp:104
static constexpr bool implementsTwoPhaseApi
Specify whether this material law implements the two-phase convenience API.
Definition EclHysteresisTwoPhaseLaw.hpp:63
static constexpr bool isCompositionDependent
Specify whether the quantities defined by this material law are dependent on the phase composition.
Definition EclHysteresisTwoPhaseLaw.hpp:91
static Evaluation Sw(const Params &, const FluidState &)
Calculate wetting liquid phase saturation given that the rest of the fluid state has been initialized...
Definition EclHysteresisTwoPhaseLaw.hpp:219
static Evaluation Sn(const Params &, const FluidState &)
Calculate non-wetting liquid phase saturation given that the rest of the fluid state has been initial...
Definition EclHysteresisTwoPhaseLaw.hpp:237
static void saturations(Container &, const Params &, const FluidState &)
The saturation-capillary pressure curves.
Definition EclHysteresisTwoPhaseLaw.hpp:207
static Evaluation krw(const Params &, const FluidState &)
The relative permeability for the wetting phase.
Definition EclHysteresisTwoPhaseLaw.hpp:260
static constexpr int numPhases
The number of fluid phases.
Definition EclHysteresisTwoPhaseLaw.hpp:56
static constexpr bool isPressureDependent
Specify whether the quantities defined by this material law are dependent on the absolute pressure.
Definition EclHysteresisTwoPhaseLaw.hpp:83
static constexpr bool implementsTwoPhaseSatApi
Specify whether this material law implements the two-phase convenience API which only depends on the ...
Definition EclHysteresisTwoPhaseLaw.hpp:71
static constexpr bool isTemperatureDependent
Specify whether the quantities defined by this material law are temperature dependent.
Definition EclHysteresisTwoPhaseLaw.hpp:87
static Evaluation pcnw(const Params &, const FluidState &)
The capillary pressure-saturation curve.
Definition EclHysteresisTwoPhaseLaw.hpp:141
static void relativePermeabilities(Container &, const Params &, const FluidState &)
The relative permeability-saturation curves depending on absolute saturations.
Definition EclHysteresisTwoPhaseLaw.hpp:122
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition Exceptions.hpp:30