richardslensproblem.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_LENS_PROBLEM_HH
29#define EWOMS_RICHARDS_LENS_PROBLEM_HH
30
32
33#include <opm/material/components/SimpleH2O.hpp>
34#include <opm/material/fluidsystems/LiquidPhase.hpp>
35#include <opm/material/fluidmatrixinteractions/RegularizedVanGenuchten.hpp>
36#include <opm/material/fluidmatrixinteractions/LinearMaterial.hpp>
37#include <opm/material/fluidmatrixinteractions/EffToAbsLaw.hpp>
38#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
39
41
42#include <dune/grid/yaspgrid.hh>
43#include <dune/grid/io/file/dgfparser/dgfyasp.hh>
44
45#include <dune/common/version.hh>
46#include <dune/common/fvector.hh>
47#include <dune/common/fmatrix.hh>
48
49namespace Opm {
50template <class TypeTag>
51class RichardsLensProblem;
52
53} // namespace Opm
54
55namespace Opm::Properties {
56
57// Create new type tags
58namespace TTag {
59struct RichardsLensProblem { using InheritsFrom = std::tuple<Richards>; };
60} // end namespace TTag
61
62// Use 2d YaspGrid
63template<class TypeTag>
64struct Grid<TypeTag, TTag::RichardsLensProblem> { using type = Dune::YaspGrid<2>; };
65
66// Set the physical problem to be solved
67template<class TypeTag>
69
70// Set the wetting phase
71template<class TypeTag>
72struct WettingFluid<TypeTag, TTag::RichardsLensProblem>
73{
74private:
76
77public:
78 using type = Opm::LiquidPhase<Scalar, Opm::SimpleH2O<Scalar> >;
79};
80
81// Set the material Law
82template<class TypeTag>
83struct MaterialLaw<TypeTag, TTag::RichardsLensProblem>
84{
85private:
87 enum { wettingPhaseIdx = FluidSystem::wettingPhaseIdx };
88 enum { nonWettingPhaseIdx = FluidSystem::nonWettingPhaseIdx };
89
91 using Traits = Opm::TwoPhaseMaterialTraits<Scalar,
92 /*wettingPhaseIdx=*/FluidSystem::wettingPhaseIdx,
93 /*nonWettingPhaseIdx=*/FluidSystem::nonWettingPhaseIdx>;
94
95 // define the material law which is parameterized by effective
96 // saturations
97 using EffectiveLaw = Opm::RegularizedVanGenuchten<Traits>;
98
99public:
100 // define the material law parameterized by absolute saturations
101 using type = Opm::EffToAbsLaw<EffectiveLaw>;
102};
103
104} // namespace Opm::Properties
105
106namespace Opm {
107
124template <class TypeTag>
125class RichardsLensProblem : public GetPropType<TypeTag, Properties::BaseProblem>
126{
128
139
141 enum {
142 // copy some indices for convenience
143 pressureWIdx = Indices::pressureWIdx,
144 contiEqIdx = Indices::contiEqIdx,
145 wettingPhaseIdx = FluidSystem::wettingPhaseIdx,
146 nonWettingPhaseIdx = FluidSystem::nonWettingPhaseIdx,
147 numPhases = FluidSystem::numPhases,
148
149 // Grid and world dimension
150 dimWorld = GridView::dimensionworld
151 };
152
153 // get the material law from the property system
156 using MaterialLawParams = typename MaterialLaw::Params;
157
158 using CoordScalar = typename GridView::ctype;
159 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
160 using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
161 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
162
163public:
167 explicit RichardsLensProblem(Simulator& simulator)
168 : ParentType(simulator)
169 , pnRef_(1e5)
170 {
171 dofIsInLens_.resize(simulator.model().numGridDof());
172 }
173
178 {
179 ParentType::finishInit();
180
181 eps_ = 3e-6;
182 pnRef_ = 1e5;
183
184 lensLowerLeft_[0] = 1.0;
185 lensLowerLeft_[1] = 2.0;
186
187 lensUpperRight_[0] = 4.0;
188 lensUpperRight_[1] = 3.0;
189
190 // parameters for the Van Genuchten law
191 // alpha and n
192 lensMaterialParams_.setVgAlpha(0.00045);
193 lensMaterialParams_.setVgN(7.3);
194 lensMaterialParams_.finalize();
195
196 outerMaterialParams_.setVgAlpha(0.0037);
197 outerMaterialParams_.setVgN(4.7);
198 outerMaterialParams_.finalize();
199
200 // parameters for the linear law
201 // minimum and maximum pressures
202 // lensMaterialParams_.setEntryPC(0);
203 // outerMaterialParams_.setEntryPC(0);
204 // lensMaterialParams_.setMaxPC(0);
205 // outerMaterialParams_.setMaxPC(0);
206
207 lensK_ = this->toDimMatrix_(1e-12);
208 outerK_ = this->toDimMatrix_(5e-12);
209
210 // determine which degrees of freedom are in the lens
211 Stencil stencil(this->gridView(), this->simulator().model().dofMapper() );
212 for (const auto& elem : elements(this->gridView())) {
213 stencil.update(elem);
214 for (unsigned dofIdx = 0; dofIdx < stencil.numPrimaryDof(); ++ dofIdx) {
215 unsigned globalDofIdx = stencil.globalSpaceIndex(dofIdx);
216 const auto& dofPos = stencil.subControlVolume(dofIdx).center();
217 dofIsInLens_[globalDofIdx] = isInLens_(dofPos);
218 }
219 }
220 }
221
225 static void registerParameters()
226 {
227 ParentType::registerParameters();
228
229 Parameters::SetDefault<Parameters::GridFile>("./data/richardslens_24x16.dgf");
230
231 // Use central differences to approximate the Jacobian matrix
233 constexpr bool useFD = std::is_same_v<LLS, Properties::TTag::FiniteDifferenceLocalLinearizer>;
234 if constexpr (useFD) {
235 Parameters::SetDefault<Parameters::NumericDifferenceMethod>(0);
236 }
237
238 Parameters::SetDefault<Parameters::EndTime<Scalar>>(3000.0);
239 Parameters::SetDefault<Parameters::InitialTimeStepSize<Scalar>>(100.0);
240 Parameters::SetDefault<Parameters::NewtonMaxIterations>(28);
241 Parameters::SetDefault<Parameters::NewtonTargetIterations>(18);
242 Parameters::SetDefault<Parameters::EnableGravity>(true);
243 }
244
249
253 std::string name() const
254 {
255 std::ostringstream oss;
256 oss << "lens_richards_"
257 << Model::discretizationName();
258 return oss.str();
259 }
260
265 {
266#ifndef NDEBUG
267 this->model().checkConservativeness();
268
269 // Calculate storage terms
270 EqVector storage;
271 this->model().globalStorage(storage);
272
273 // Write mass balance information for rank 0
274 if (this->gridView().comm().rank() == 0) {
275 std::cout << "Storage: " << storage << std::endl << std::flush;
276 }
277#endif // NDEBUG
278 }
279
283 template <class Context>
284 Scalar temperature(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
285 { return temperature(context.globalSpaceIndex(spaceIdx, timeIdx), timeIdx); }
286
287 Scalar temperature(unsigned /*globalSpaceIdx*/, unsigned /*timeIdx*/) const
288 { return 273.15 + 10; } // -> 10°C
289
293 template <class Context>
294 const DimMatrix& intrinsicPermeability(const Context& context,
295 unsigned spaceIdx,
296 unsigned timeIdx) const
297 {
298 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
299 if (isInLens_(pos))
300 return lensK_;
301 return outerK_;
302 }
303
307 template <class Context>
308 Scalar porosity(const Context& /*context*/,
309 unsigned /*spaceIdx*/,
310 unsigned /*timeIdx*/) const
311 { return 0.4; }
312
316 template <class Context>
317 const MaterialLawParams& materialLawParams(const Context& context,
318 unsigned spaceIdx,
319 unsigned timeIdx) const
320 {
321 unsigned globalSpaceIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
322 return materialLawParams(globalSpaceIdx, timeIdx);
323 }
324
325 const MaterialLawParams& materialLawParams(unsigned globalSpaceIdx,
326 unsigned /*timeIdx*/) const
327 {
328 if (dofIsInLens_[globalSpaceIdx])
329 return lensMaterialParams_;
330 return outerMaterialParams_;
331 }
332
338 template <class Context>
339 Scalar referencePressure(const Context& context,
340 unsigned spaceIdx,
341 unsigned timeIdx) const
342 { return referencePressure(context.globalSpaceIndex(spaceIdx, timeIdx), timeIdx); }
343
344 // the Richards model does not have an element context available at all places
345 // where the reference pressure is required...
346 Scalar referencePressure(unsigned /*globalSpaceIdx*/,
347 unsigned /*timeIdx*/) const
348 { return pnRef_; }
349
351
356
360 template <class Context>
361 void boundary(BoundaryRateVector& values,
362 const Context& context,
363 unsigned spaceIdx,
364 unsigned timeIdx) const
365 {
366 const auto& pos = context.pos(spaceIdx, timeIdx);
367
368 if (onLeftBoundary_(pos) || onRightBoundary_(pos)) {
369 const auto& materialParams = this->materialLawParams(context, spaceIdx, timeIdx);
370
371 Scalar Sw = 0.0;
372 Opm::ImmiscibleFluidState<Scalar, FluidSystem> fs;
373 fs.setSaturation(wettingPhaseIdx, Sw);
374 fs.setSaturation(nonWettingPhaseIdx, 1.0 - Sw);
375
376 PhaseVector pC;
377 MaterialLaw::capillaryPressures(pC, materialParams, fs);
378 fs.setPressure(wettingPhaseIdx, pnRef_ + pC[wettingPhaseIdx] - pC[nonWettingPhaseIdx]);
379 fs.setPressure(nonWettingPhaseIdx, pnRef_);
380
381 typename FluidSystem::template ParameterCache<Scalar> paramCache;
382 paramCache.updateAll(fs);
383 fs.setDensity(wettingPhaseIdx, FluidSystem::density(fs, paramCache, wettingPhaseIdx));
384 //fs.setDensity(nonWettingPhaseIdx, FluidSystem::density(fs, paramCache, nonWettingPhaseIdx));
385
386 fs.setViscosity(wettingPhaseIdx, FluidSystem::viscosity(fs, paramCache, wettingPhaseIdx));
387 //fs.setViscosity(nonWettingPhaseIdx, FluidSystem::viscosity(fs, paramCache, nonWettingPhaseIdx));
388
389 values.setFreeFlow(context, spaceIdx, timeIdx, fs);
390 }
391 else if (onInlet_(pos)) {
392 RateVector massRate(0.0);
393
394 // inflow of water
395 massRate[contiEqIdx] = -0.04; // kg / (m * s)
396
397 values.setMassRate(massRate);
398 }
399 else
400 values.setNoFlow();
401 }
402
404
409
413 template <class Context>
414 void initial(PrimaryVariables& values,
415 const Context& context,
416 unsigned spaceIdx,
417 unsigned timeIdx) const
418 {
419 const auto& materialParams = this->materialLawParams(context, spaceIdx, timeIdx);
420
421 Scalar Sw = 0.0;
422 Opm::ImmiscibleFluidState<Scalar, FluidSystem> fs;
423 fs.setSaturation(wettingPhaseIdx, Sw);
424 fs.setSaturation(nonWettingPhaseIdx, 1.0 - Sw);
425
426 PhaseVector pC;
427 MaterialLaw::capillaryPressures(pC, materialParams, fs);
428 values[pressureWIdx] = pnRef_ + (pC[wettingPhaseIdx] - pC[nonWettingPhaseIdx]);
429 }
430
437 template <class Context>
438 void source(RateVector& rate,
439 const Context& /*context*/,
440 unsigned /*spaceIdx*/,
441 unsigned /*timeIdx*/) const
442 { rate = Scalar(0.0); }
443
445
446private:
447 bool onLeftBoundary_(const GlobalPosition& pos) const
448 { return pos[0] < this->boundingBoxMin()[0] + eps_; }
449
450 bool onRightBoundary_(const GlobalPosition& pos) const
451 { return pos[0] > this->boundingBoxMax()[0] - eps_; }
452
453 bool onLowerBoundary_(const GlobalPosition& pos) const
454 { return pos[1] < this->boundingBoxMin()[1] + eps_; }
455
456 bool onUpperBoundary_(const GlobalPosition& pos) const
457 { return pos[1] > this->boundingBoxMax()[1] - eps_; }
458
459 bool onInlet_(const GlobalPosition& pos) const
460 {
461 Scalar width = this->boundingBoxMax()[0] - this->boundingBoxMin()[0];
462 Scalar lambda = (this->boundingBoxMax()[0] - pos[0]) / width;
463 return onUpperBoundary_(pos) && 0.5 < lambda && lambda < 2.0 / 3.0;
464 }
465
466 bool isInLens_(const GlobalPosition& pos) const
467 {
468 for (unsigned i = 0; i < dimWorld; ++i) {
469 if (pos[i] < lensLowerLeft_[i] || pos[i] > lensUpperRight_[i])
470 return false;
471 }
472 return true;
473 }
474
475 GlobalPosition lensLowerLeft_;
476 GlobalPosition lensUpperRight_;
477
478 DimMatrix lensK_;
479 DimMatrix outerK_;
480 MaterialLawParams lensMaterialParams_;
481 MaterialLawParams outerMaterialParams_;
482
483 std::vector<bool> dofIsInLens_;
484
485 Scalar eps_;
486 Scalar pnRef_;
487};
488} // namespace Opm
489
490#endif
A water infiltration problem with a low-permeability lens embedded into a high-permeability domain.
Definition: richardslensproblem.hh:126
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: richardslensproblem.hh:177
static void registerParameters()
Definition: richardslensproblem.hh:225
std::string name() const
The problem name.
Definition: richardslensproblem.hh:253
const MaterialLawParams & materialLawParams(unsigned globalSpaceIdx, unsigned) const
Definition: richardslensproblem.hh:325
const MaterialLawParams & materialLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: richardslensproblem.hh:317
Scalar temperature(unsigned, unsigned) const
Definition: richardslensproblem.hh:287
Scalar referencePressure(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Return the reference pressure [Pa] of the wetting phase.
Definition: richardslensproblem.hh:339
RichardsLensProblem(Simulator &simulator)
Definition: richardslensproblem.hh:167
const DimMatrix & intrinsicPermeability(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: richardslensproblem.hh:294
void source(RateVector &rate, const Context &, unsigned, unsigned) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: richardslensproblem.hh:438
Scalar referencePressure(unsigned, unsigned) const
Definition: richardslensproblem.hh:346
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: richardslensproblem.hh:361
void endTimeStep()
Called by the simulator after each time integration.
Definition: richardslensproblem.hh:264
Scalar temperature(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: richardslensproblem.hh:284
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: richardslensproblem.hh:414
Scalar porosity(const Context &, unsigned, unsigned) const
Definition: richardslensproblem.hh:308
Definition: blackoilmodel.hh:74
Definition: blackoilbioeffectsmodules.hh:45
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
Dune::YaspGrid< 2 > type
Definition: richardslensproblem.hh:64
The type of the DUNE grid.
Definition: basicproperties.hh:104
Opm::EffToAbsLaw< EffectiveLaw > type
Definition: richardslensproblem.hh:101
The material law which ought to be used (extracted from the spatial parameters)
Definition: multiphasebaseproperties.hh:55
The type of the problem.
Definition: fvbaseproperties.hh:86
Definition: richardslensproblem.hh:59
std::tuple< Richards > InheritsFrom
Definition: richardslensproblem.hh:59
Opm::LiquidPhase< Scalar, Opm::SimpleH2O< Scalar > > type
Definition: richardslensproblem.hh:78
Definition: richardsproperties.hh:40