infiltrationproblem.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*/
27#ifndef EWOMS_INFILTRATION_PROBLEM_HH
28#define EWOMS_INFILTRATION_PROBLEM_HH
29
30#include <dune/common/fmatrix.hh>
31#include <dune/common/fvector.hh>
32#include <dune/common/version.hh>
33
34#include <dune/grid/yaspgrid.hh>
35#include <dune/grid/io/file/dgfparser/dgfyasp.hh>
36
37#include <opm/material/common/Valgrind.hpp>
38#include <opm/material/constraintsolvers/ComputeFromReferencePhase.hpp>
39#include <opm/material/fluidmatrixinteractions/ThreePhaseParkerVanGenuchten.hpp>
40#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
41#include <opm/material/fluidstates/CompositionalFluidState.hpp>
42#include <opm/material/fluidsystems/H2OAirMesityleneFluidSystem.hpp>
43
45
47
49
50#include <sstream>
51#include <string>
52
53namespace Opm {
54template <class TypeTag>
55class InfiltrationProblem;
56}
57
58namespace Opm::Properties {
59
60namespace TTag {
62}
63
64// Set the grid type
65template<class TypeTag>
66struct Grid<TypeTag, TTag::InfiltrationBaseProblem> { using type = Dune::YaspGrid<2>; };
67
68// Set the problem property
69template<class TypeTag>
70struct Problem<TypeTag, TTag::InfiltrationBaseProblem> { using type = Opm::InfiltrationProblem<TypeTag>; };
71
72// Set the fluid system
73template<class TypeTag>
74struct FluidSystem<TypeTag, TTag::InfiltrationBaseProblem>
75{ using type = Opm::H2OAirMesityleneFluidSystem<GetPropType<TypeTag, Properties::Scalar>>; };
76
77// Set the material Law
78template<class TypeTag>
79struct MaterialLaw<TypeTag, TTag::InfiltrationBaseProblem>
80{
81private:
84
85 using Traits= Opm::ThreePhaseMaterialTraits<
86 Scalar,
87 /*wettingPhaseIdx=*/FluidSystem::waterPhaseIdx,
88 /*nonWettingPhaseIdx=*/FluidSystem::naplPhaseIdx,
89 /*gasPhaseIdx=*/FluidSystem::gasPhaseIdx,
90 /* hysteresis */ false,
91 /* endpointscaling */ false>;
92
93public:
94 using type = Opm::ThreePhaseParkerVanGenuchten<Traits>;
95};
96
97} // namespace Opm::Properties
98
99namespace Opm {
122template <class TypeTag>
123class InfiltrationProblem : public GetPropType<TypeTag, Properties::BaseProblem>
124{
126
138
139 // copy some indices for convenience
141 enum {
142 // equation indices
143 conti0EqIdx = Indices::conti0EqIdx,
144
145 // number of phases/components
146 numPhases = FluidSystem::numPhases,
147
148 // component indices
149 NAPLIdx = FluidSystem::NAPLIdx,
150 H2OIdx = FluidSystem::H2OIdx,
151 airIdx = FluidSystem::airIdx,
152
153 // phase indices
154 waterPhaseIdx = FluidSystem::waterPhaseIdx,
155 gasPhaseIdx = FluidSystem::gasPhaseIdx,
156 naplPhaseIdx = FluidSystem::naplPhaseIdx,
157
158 // Grid and world dimension
159 dim = GridView::dimension,
160 dimWorld = GridView::dimensionworld
161 };
162
163 using CoordScalar = typename GridView::ctype;
164 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
165 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
166
167public:
171 explicit InfiltrationProblem(Simulator& simulator)
172 : ParentType(simulator)
173 , eps_(1e-6)
174 { }
175
180 {
181 ParentType::finishInit();
182
183 temperature_ = 273.15 + 10.0; // -> 10 degrees Celsius
184 FluidSystem::init(/*tempMin=*/temperature_ - 1,
185 /*tempMax=*/temperature_ + 1,
186 /*nTemp=*/3,
187 /*pressMin=*/0.8 * 1e5,
188 /*pressMax=*/3 * 1e5,
189 /*nPress=*/200);
190
191 // intrinsic permeabilities
192 fineK_ = this->toDimMatrix_(1e-11);
193 coarseK_ = this->toDimMatrix_(1e-11);
194
195 // porosities
196 porosity_ = 0.40;
197
198 // residual saturations
199 materialParams_.setSwr(0.12);
200 materialParams_.setSwrx(0.12);
201 materialParams_.setSnr(0.07);
202 materialParams_.setSgr(0.03);
203
204 // parameters for the three-phase van Genuchten law
205 materialParams_.setVgAlpha(0.0005);
206 materialParams_.setVgN(4.);
207 materialParams_.setkrRegardsSnr(false);
208
209 materialParams_.finalize();
210 materialParams_.checkDefined();
211 }
212
216 static void registerParameters()
217 {
218 ParentType::registerParameters();
219
220 Parameters::SetDefault<Parameters::GridFile>("./data/infiltration_50x3.dgf");
221 Parameters::SetDefault<Parameters::NumericDifferenceMethod>(1);
222 Parameters::SetDefault<Parameters::EndTime<Scalar>>(6e3);
223 Parameters::SetDefault<Parameters::InitialTimeStepSize<Scalar>>(60.0);
224 Parameters::SetDefault<Parameters::EnableGravity>(true);
225 }
226
231
238 { return true; }
239
243 std::string name() const
244 {
245 std::ostringstream oss;
246 oss << "infiltration_" << Model::name();
247 return oss.str();
248 }
249
254 {
255#ifndef NDEBUG
256 this->model().checkConservativeness();
257
258 // Calculate storage terms
259 EqVector storage;
260 this->model().globalStorage(storage);
261
262 // Write mass balance information for rank 0
263 if (this->gridView().comm().rank() == 0) {
264 std::cout << "Storage: " << storage << std::endl << std::flush;
265 }
266#endif // NDEBUG
267 }
268
272 template <class Context>
273 Scalar temperature(const Context& /*context*/,
274 unsigned /*spaceIdx*/,
275 unsigned /*timeIdx*/) const
276 { return temperature_; }
277
281 template <class Context>
282 const DimMatrix&
283 intrinsicPermeability(const Context& context,
284 unsigned spaceIdx,
285 unsigned timeIdx) const
286 {
287 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
288 if (isFineMaterial_(pos))
289 return fineK_;
290 return coarseK_;
291 }
292
296 template <class Context>
297 Scalar porosity(const Context& /*context*/,
298 unsigned /*spaceIdx*/,
299 unsigned /*timeIdx*/) const
300 { return porosity_; }
301
305 template <class Context>
306 const MaterialLawParams&
307 materialLawParams(const Context& /*context*/,
308 unsigned /*spaceIdx*/,
309 unsigned /*timeIdx*/) const
310 { return materialParams_; }
311
313
318
322 template <class Context>
323 void boundary(BoundaryRateVector& values,
324 const Context& context,
325 unsigned spaceIdx,
326 unsigned timeIdx) const
327 {
328 const auto& pos = context.pos(spaceIdx, timeIdx);
329
330 if (onLeftBoundary_(pos) || onRightBoundary_(pos)) {
331 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
332
333 initialFluidState_(fs, context, spaceIdx, timeIdx);
334
335 values.setFreeFlow(context, spaceIdx, timeIdx, fs);
336 }
337 else if (onInlet_(pos)) {
338 RateVector molarRate(0.0);
339 molarRate[conti0EqIdx + NAPLIdx] = -0.001;
340
341 values.setMolarRate(molarRate);
342 Opm::Valgrind::CheckDefined(values);
343 }
344 else
345 values.setNoFlow();
346 }
347
349
354
358 template <class Context>
359 void initial(PrimaryVariables& values,
360 const Context& context,
361 unsigned spaceIdx,
362 unsigned timeIdx) const
363 {
364 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
365
366 initialFluidState_(fs, context, spaceIdx, timeIdx);
367
368 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
369 values.assignMassConservative(fs, matParams, /*inEquilibrium=*/true);
370 Opm::Valgrind::CheckDefined(values);
371 }
372
379 template <class Context>
380 void source(RateVector& rate,
381 const Context& /*context*/,
382 unsigned /*spaceIdx*/,
383 unsigned /*timeIdx*/) const
384 { rate = Scalar(0.0); }
385
387
388private:
389 bool onLeftBoundary_(const GlobalPosition& pos) const
390 { return pos[0] < eps_; }
391
392 bool onRightBoundary_(const GlobalPosition& pos) const
393 { return pos[0] > this->boundingBoxMax()[0] - eps_; }
394
395 bool onLowerBoundary_(const GlobalPosition& pos) const
396 { return pos[1] < eps_; }
397
398 bool onUpperBoundary_(const GlobalPosition& pos) const
399 { return pos[1] > this->boundingBoxMax()[1] - eps_; }
400
401 bool onInlet_(const GlobalPosition& pos) const
402 { return onUpperBoundary_(pos) && 50 < pos[0] && pos[0] < 75; }
403
404 template <class FluidState, class Context>
405 void initialFluidState_(FluidState& fs, const Context& context,
406 unsigned spaceIdx, unsigned timeIdx) const
407 {
408 const GlobalPosition pos = context.pos(spaceIdx, timeIdx);
409 Scalar y = pos[1];
410 Scalar x = pos[0];
411
412 Scalar densityW = 1000.0;
413 Scalar pc = 9.81 * densityW * (y - (5 - 5e-4 * x));
414 if (pc < 0.0)
415 pc = 0.0;
416
417 // set pressures
418 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
419 Scalar Sw = matParams.Swr();
420 Scalar Swr = matParams.Swr();
421 Scalar Sgr = matParams.Sgr();
422 if (Sw < Swr)
423 Sw = Swr;
424 if (Sw > 1 - Sgr)
425 Sw = 1 - Sgr;
426 Scalar Sg = 1 - Sw;
427
428 Opm::Valgrind::CheckDefined(Sw);
429 Opm::Valgrind::CheckDefined(Sg);
430
431 fs.setSaturation(waterPhaseIdx, Sw);
432 fs.setSaturation(gasPhaseIdx, Sg);
433 fs.setSaturation(naplPhaseIdx, 0);
434
435 // set temperature of all phases
436 fs.setTemperature(temperature_);
437
438 // compute pressures
439 Scalar pcAll[numPhases];
440 Scalar pg = 1e5;
441 if (onLeftBoundary_(pos))
442 pg += 10e3;
443 MaterialLaw::capillaryPressures(pcAll, matParams, fs);
444 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
445 fs.setPressure(phaseIdx, pg + (pcAll[phaseIdx] - pcAll[gasPhaseIdx]));
446
447 // set composition of gas phase
448 fs.setMoleFraction(gasPhaseIdx, H2OIdx, 1e-6);
449 fs.setMoleFraction(gasPhaseIdx, airIdx,
450 1 - fs.moleFraction(gasPhaseIdx, H2OIdx));
451 fs.setMoleFraction(gasPhaseIdx, NAPLIdx, 0);
452
453 using CFRP = Opm::ComputeFromReferencePhase<Scalar, FluidSystem>;
454 typename FluidSystem::template ParameterCache<Scalar> paramCache;
455 CFRP::solve(fs, paramCache, gasPhaseIdx,
456 /*setViscosity=*/true,
457 /*setEnthalpy=*/false);
458
459 fs.setMoleFraction(waterPhaseIdx, H2OIdx,
460 1 - fs.moleFraction(waterPhaseIdx, H2OIdx));
461 }
462
463 bool isFineMaterial_(const GlobalPosition& pos) const
464 { return 70. <= pos[0] && pos[0] <= 85. && 7.0 <= pos[1] && pos[1] <= 7.50; }
465
466 DimMatrix fineK_;
467 DimMatrix coarseK_;
468
469 Scalar porosity_;
470
471 MaterialLawParams materialParams_;
472
473 Scalar temperature_;
474 Scalar eps_;
475};
476} // namespace Opm
477
478#endif
Isothermal NAPL infiltration problem where LNAPL contaminates the unsaturated and the saturated groun...
Definition: infiltrationproblem.hh:124
void source(RateVector &rate, const Context &, unsigned, unsigned) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: infiltrationproblem.hh:380
Scalar temperature(const Context &, unsigned, unsigned) const
Definition: infiltrationproblem.hh:273
const DimMatrix & intrinsicPermeability(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: infiltrationproblem.hh:283
std::string name() const
The problem name.
Definition: infiltrationproblem.hh:243
Scalar porosity(const Context &, unsigned, unsigned) const
Definition: infiltrationproblem.hh:297
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: infiltrationproblem.hh:323
const MaterialLawParams & materialLawParams(const Context &, unsigned, unsigned) const
Definition: infiltrationproblem.hh:307
void endTimeStep()
Called by the simulator after each time integration.
Definition: infiltrationproblem.hh:253
InfiltrationProblem(Simulator &simulator)
Definition: infiltrationproblem.hh:171
bool shouldWriteRestartFile() const
Returns true if a restart file should be written to disk.
Definition: infiltrationproblem.hh:237
static void registerParameters()
Definition: infiltrationproblem.hh:216
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: infiltrationproblem.hh:359
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: infiltrationproblem.hh:179
Defines the common parameters for the porous medium multi-phase models.
Definition: blackoilmodel.hh:79
Definition: blackoilbioeffectsmodules.hh:43
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
Declares the properties required for the compositional multi-phase primary variable switching model.
Opm::H2OAirMesityleneFluidSystem< GetPropType< TypeTag, Properties::Scalar > > type
Definition: infiltrationproblem.hh:75
The fluid systems including the information about the phases.
Definition: multiphasebaseproperties.hh:79
Dune::YaspGrid< 2 > type
Definition: infiltrationproblem.hh:66
The type of the DUNE grid.
Definition: basicproperties.hh:100
Opm::ThreePhaseParkerVanGenuchten< Traits > type
Definition: infiltrationproblem.hh:94
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:81
Definition: infiltrationproblem.hh:61