richardsnewtonmethod.hh
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 EWOMS_RICHARDS_NEWTON_METHOD_HH
29#define EWOMS_RICHARDS_NEWTON_METHOD_HH
30
31#include <dune/common/fvector.hh>
32
33#include <opm/material/fluidstates/ImmiscibleFluidState.hpp>
34
38
39#include <algorithm>
40
41namespace Opm {
42
48template <class TypeTag>
49class RichardsNewtonMethod : public GetPropType<TypeTag, Properties::DiscNewtonMethod>
50{
52
61
63 enum { pressureWIdx = Indices::pressureWIdx };
64 enum { numPhases = FluidSystem::numPhases };
65 enum { liquidPhaseIdx = getPropValue<TypeTag, Properties::LiquidPhaseIndex>() };
66 enum { gasPhaseIdx = getPropValue<TypeTag, Properties::GasPhaseIndex>() };
67
68 using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
69
70public:
71 explicit RichardsNewtonMethod(Simulator& simulator)
72 : ParentType(simulator)
73 {}
74
75protected:
77 friend ParentType;
78
82 void updatePrimaryVariables_(unsigned globalDofIdx,
83 PrimaryVariables& nextValue,
84 const PrimaryVariables& currentValue,
85 const EqVector& update,
86 const EqVector&)
87 {
88 // normal Newton-Raphson update
89 nextValue = currentValue;
90 nextValue -= update;
91
92 // do not clamp anything after 4 iterations
93 if (this->numIterations_ > 4) {
94 return;
95 }
96
97 const auto& problem = this->simulator_.problem();
98
99 // calculate the old wetting phase saturation
100 const MaterialLawParams& matParams =
101 problem.materialLawParams(globalDofIdx, /*timeIdx=*/0);
102
103 ImmiscibleFluidState<Scalar, FluidSystem> fs;
104
105 // set the temperature
106 const Scalar T = problem.temperature(globalDofIdx, /*timeIdx=*/0);
107 fs.setTemperature(T);
108
110 // calculate the phase pressures of the previous iteration
112
113 // first, we have to find the minimum capillary pressure
114 // (i.e. Sw = 0)
115 fs.setSaturation(liquidPhaseIdx, 1.0);
116 fs.setSaturation(gasPhaseIdx, 0.0);
117 PhaseVector pC;
118 MaterialLaw::capillaryPressures(pC, matParams, fs);
119
120 // non-wetting pressure can be larger than the
121 // reference pressure if the medium is fully
122 // saturated by the wetting phase
123 const Scalar pWOld = currentValue[pressureWIdx];
124 const Scalar pNOld =
125 std::max(problem.referencePressure(globalDofIdx, /*timeIdx=*/0),
126 pWOld + (pC[gasPhaseIdx] - pC[liquidPhaseIdx]));
127
129 // find the saturations of the previous iteration
131 fs.setPressure(liquidPhaseIdx, pWOld);
132 fs.setPressure(gasPhaseIdx, pNOld);
133
134 PhaseVector satOld;
135 MaterialLaw::saturations(satOld, matParams, fs);
136 satOld[liquidPhaseIdx] = std::max(Scalar{0.0}, satOld[liquidPhaseIdx]);
137
139 // find the wetting phase pressures which
140 // corrospond to a 20% increase and a 20% decrease
141 // of the wetting saturation
143 fs.setSaturation(liquidPhaseIdx, satOld[liquidPhaseIdx] - 0.2);
144 fs.setSaturation(gasPhaseIdx, 1.0 - (satOld[liquidPhaseIdx] - 0.2));
145 MaterialLaw::capillaryPressures(pC, matParams, fs);
146 const Scalar pwMin = pNOld - (pC[gasPhaseIdx] - pC[liquidPhaseIdx]);
147
148 fs.setSaturation(liquidPhaseIdx, satOld[liquidPhaseIdx] + 0.2);
149 fs.setSaturation(gasPhaseIdx, 1.0 - (satOld[liquidPhaseIdx] + 0.2));
150 MaterialLaw::capillaryPressures(pC, matParams, fs);
151 const Scalar pwMax = pNOld - (pC[gasPhaseIdx] - pC[liquidPhaseIdx]);
152
154 // clamp the result to the minimum and the maximum
155 // pressures we just calculated
157 const Scalar pW = std::clamp(nextValue[pressureWIdx], pwMin, pwMax);
158 nextValue[pressureWIdx] = pW;
159 }
160};
161
162} // namespace Opm
163
164#endif
The multi-dimensional Newton method.
Definition: newtonmethod.hh:100
A Richards model specific Newton method.
Definition: richardsnewtonmethod.hh:50
RichardsNewtonMethod(Simulator &simulator)
Definition: richardsnewtonmethod.hh:71
void updatePrimaryVariables_(unsigned globalDofIdx, PrimaryVariables &nextValue, const PrimaryVariables &currentValue, const EqVector &update, const EqVector &)
Update a single primary variables object.
Definition: richardsnewtonmethod.hh:82
friend ParentType
Definition: richardsnewtonmethod.hh:77
Defines the common properties required by the porous medium multi-phase models.
Definition: blackoilboundaryratevector.hh:39
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
Contains the property declarations for the Richards model.