opm-simulators
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 
41 namespace Opm {
42 
48 template <class TypeTag>
49 class 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 
70 public:
71  explicit RichardsNewtonMethod(Simulator& simulator)
72  : ParentType(simulator)
73  {}
74 
75 protected:
76  friend NewtonMethod<TypeTag>;
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->problem().iterationContext().iteration() > 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:64
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
void updatePrimaryVariables_(unsigned globalDofIdx, PrimaryVariables &nextValue, const PrimaryVariables &currentValue, const EqVector &update, const EqVector &)
Update a single primary variables object.
Definition: richardsnewtonmethod.hh:82
Defines the common properties required by the porous medium multi-phase models.
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
A Newton method for models using a finite volume discretization.
A Richards model specific Newton method.
Definition: richardsnewtonmethod.hh:49
Contains the property declarations for the Richards model.