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
91public:
92 using type = Opm::ThreePhaseParkerVanGenuchten<Traits>;
93};
94
95} // namespace Opm::Properties
96
97namespace Opm {
120template <class TypeTag>
121class InfiltrationProblem : public GetPropType<TypeTag, Properties::BaseProblem>
122{
124
136
137 // copy some indices for convenience
139 enum {
140 // equation indices
141 conti0EqIdx = Indices::conti0EqIdx,
142
143 // number of phases/components
144 numPhases = FluidSystem::numPhases,
145
146 // component indices
147 NAPLIdx = FluidSystem::NAPLIdx,
148 H2OIdx = FluidSystem::H2OIdx,
149 airIdx = FluidSystem::airIdx,
150
151 // phase indices
152 waterPhaseIdx = FluidSystem::waterPhaseIdx,
153 gasPhaseIdx = FluidSystem::gasPhaseIdx,
154 naplPhaseIdx = FluidSystem::naplPhaseIdx,
155
156 // Grid and world dimension
157 dim = GridView::dimension,
158 dimWorld = GridView::dimensionworld
159 };
160
161 using CoordScalar = typename GridView::ctype;
162 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
163 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
164
165public:
169 InfiltrationProblem(Simulator& simulator)
170 : ParentType(simulator)
171 , eps_(1e-6)
172 { }
173
178 {
179 ParentType::finishInit();
180
181 temperature_ = 273.15 + 10.0; // -> 10 degrees Celsius
182 FluidSystem::init(/*tempMin=*/temperature_ - 1,
183 /*tempMax=*/temperature_ + 1,
184 /*nTemp=*/3,
185 /*pressMin=*/0.8 * 1e5,
186 /*pressMax=*/3 * 1e5,
187 /*nPress=*/200);
188
189 // intrinsic permeabilities
190 fineK_ = this->toDimMatrix_(1e-11);
191 coarseK_ = this->toDimMatrix_(1e-11);
192
193 // porosities
194 porosity_ = 0.40;
195
196 // residual saturations
197 materialParams_.setSwr(0.12);
198 materialParams_.setSwrx(0.12);
199 materialParams_.setSnr(0.07);
200 materialParams_.setSgr(0.03);
201
202 // parameters for the three-phase van Genuchten law
203 materialParams_.setVgAlpha(0.0005);
204 materialParams_.setVgN(4.);
205 materialParams_.setkrRegardsSnr(false);
206
207 materialParams_.finalize();
208 materialParams_.checkDefined();
209 }
210
214 static void registerParameters()
215 {
216 ParentType::registerParameters();
217
218 Parameters::SetDefault<Parameters::GridFile>("./data/infiltration_50x3.dgf");
219 Parameters::SetDefault<Parameters::NumericDifferenceMethod>(1);
220 Parameters::SetDefault<Parameters::EndTime<Scalar>>(6e3);
221 Parameters::SetDefault<Parameters::InitialTimeStepSize<Scalar>>(60.0);
222 Parameters::SetDefault<Parameters::EnableGravity>(true);
223 }
224
229
236 { return true; }
237
241 std::string name() const
242 {
243 std::ostringstream oss;
244 oss << "infiltration_" << Model::name();
245 return oss.str();
246 }
247
252 {
253#ifndef NDEBUG
254 this->model().checkConservativeness();
255
256 // Calculate storage terms
257 EqVector storage;
258 this->model().globalStorage(storage);
259
260 // Write mass balance information for rank 0
261 if (this->gridView().comm().rank() == 0) {
262 std::cout << "Storage: " << storage << std::endl << std::flush;
263 }
264#endif // NDEBUG
265 }
266
270 template <class Context>
271 Scalar temperature(const Context& /*context*/,
272 unsigned /*spaceIdx*/,
273 unsigned /*timeIdx*/) const
274 { return temperature_; }
275
279 template <class Context>
280 const DimMatrix&
281 intrinsicPermeability(const Context& context,
282 unsigned spaceIdx,
283 unsigned timeIdx) const
284 {
285 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
286 if (isFineMaterial_(pos))
287 return fineK_;
288 return coarseK_;
289 }
290
294 template <class Context>
295 Scalar porosity(const Context& /*context*/,
296 unsigned /*spaceIdx*/,
297 unsigned /*timeIdx*/) const
298 { return porosity_; }
299
303 template <class Context>
304 const MaterialLawParams&
305 materialLawParams(const Context& /*context*/,
306 unsigned /*spaceIdx*/,
307 unsigned /*timeIdx*/) const
308 { return materialParams_; }
309
311
316
320 template <class Context>
321 void boundary(BoundaryRateVector& values,
322 const Context& context,
323 unsigned spaceIdx,
324 unsigned timeIdx) const
325 {
326 const auto& pos = context.pos(spaceIdx, timeIdx);
327
328 if (onLeftBoundary_(pos) || onRightBoundary_(pos)) {
329 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
330
331 initialFluidState_(fs, context, spaceIdx, timeIdx);
332
333 values.setFreeFlow(context, spaceIdx, timeIdx, fs);
334 }
335 else if (onInlet_(pos)) {
336 RateVector molarRate(0.0);
337 molarRate[conti0EqIdx + NAPLIdx] = -0.001;
338
339 values.setMolarRate(molarRate);
340 Opm::Valgrind::CheckDefined(values);
341 }
342 else
343 values.setNoFlow();
344 }
345
347
352
356 template <class Context>
357 void initial(PrimaryVariables& values,
358 const Context& context,
359 unsigned spaceIdx,
360 unsigned timeIdx) const
361 {
362 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
363
364 initialFluidState_(fs, context, spaceIdx, timeIdx);
365
366 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
367 values.assignMassConservative(fs, matParams, /*inEquilibrium=*/true);
368 Opm::Valgrind::CheckDefined(values);
369 }
370
377 template <class Context>
378 void source(RateVector& rate,
379 const Context& /*context*/,
380 unsigned /*spaceIdx*/,
381 unsigned /*timeIdx*/) const
382 { rate = Scalar(0.0); }
383
385
386private:
387 bool onLeftBoundary_(const GlobalPosition& pos) const
388 { return pos[0] < eps_; }
389
390 bool onRightBoundary_(const GlobalPosition& pos) const
391 { return pos[0] > this->boundingBoxMax()[0] - eps_; }
392
393 bool onLowerBoundary_(const GlobalPosition& pos) const
394 { return pos[1] < eps_; }
395
396 bool onUpperBoundary_(const GlobalPosition& pos) const
397 { return pos[1] > this->boundingBoxMax()[1] - eps_; }
398
399 bool onInlet_(const GlobalPosition& pos) const
400 { return onUpperBoundary_(pos) && 50 < pos[0] && pos[0] < 75; }
401
402 template <class FluidState, class Context>
403 void initialFluidState_(FluidState& fs, const Context& context,
404 unsigned spaceIdx, unsigned timeIdx) const
405 {
406 const GlobalPosition pos = context.pos(spaceIdx, timeIdx);
407 Scalar y = pos[1];
408 Scalar x = pos[0];
409
410 Scalar densityW = 1000.0;
411 Scalar pc = 9.81 * densityW * (y - (5 - 5e-4 * x));
412 if (pc < 0.0)
413 pc = 0.0;
414
415 // set pressures
416 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
417 Scalar Sw = matParams.Swr();
418 Scalar Swr = matParams.Swr();
419 Scalar Sgr = matParams.Sgr();
420 if (Sw < Swr)
421 Sw = Swr;
422 if (Sw > 1 - Sgr)
423 Sw = 1 - Sgr;
424 Scalar Sg = 1 - Sw;
425
426 Opm::Valgrind::CheckDefined(Sw);
427 Opm::Valgrind::CheckDefined(Sg);
428
429 fs.setSaturation(waterPhaseIdx, Sw);
430 fs.setSaturation(gasPhaseIdx, Sg);
431 fs.setSaturation(naplPhaseIdx, 0);
432
433 // set temperature of all phases
434 fs.setTemperature(temperature_);
435
436 // compute pressures
437 Scalar pcAll[numPhases];
438 Scalar pg = 1e5;
439 if (onLeftBoundary_(pos))
440 pg += 10e3;
441 MaterialLaw::capillaryPressures(pcAll, matParams, fs);
442 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx)
443 fs.setPressure(phaseIdx, pg + (pcAll[phaseIdx] - pcAll[gasPhaseIdx]));
444
445 // set composition of gas phase
446 fs.setMoleFraction(gasPhaseIdx, H2OIdx, 1e-6);
447 fs.setMoleFraction(gasPhaseIdx, airIdx,
448 1 - fs.moleFraction(gasPhaseIdx, H2OIdx));
449 fs.setMoleFraction(gasPhaseIdx, NAPLIdx, 0);
450
451 using CFRP = Opm::ComputeFromReferencePhase<Scalar, FluidSystem>;
452 typename FluidSystem::template ParameterCache<Scalar> paramCache;
453 CFRP::solve(fs, paramCache, gasPhaseIdx,
454 /*setViscosity=*/true,
455 /*setEnthalpy=*/false);
456
457 fs.setMoleFraction(waterPhaseIdx, H2OIdx,
458 1 - fs.moleFraction(waterPhaseIdx, H2OIdx));
459 }
460
461 bool isFineMaterial_(const GlobalPosition& pos) const
462 { return 70. <= pos[0] && pos[0] <= 85. && 7.0 <= pos[1] && pos[1] <= 7.50; }
463
464 DimMatrix fineK_;
465 DimMatrix coarseK_;
466
467 Scalar porosity_;
468
469 MaterialLawParams materialParams_;
470
471 Scalar temperature_;
472 Scalar eps_;
473};
474} // namespace Opm
475
476#endif
Isothermal NAPL infiltration problem where LNAPL contaminates the unsaturated and the saturated groun...
Definition: infiltrationproblem.hh:122
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:378
Scalar temperature(const Context &, unsigned, unsigned) const
Definition: infiltrationproblem.hh:271
const DimMatrix & intrinsicPermeability(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: infiltrationproblem.hh:281
std::string name() const
The problem name.
Definition: infiltrationproblem.hh:241
Scalar porosity(const Context &, unsigned, unsigned) const
Definition: infiltrationproblem.hh:295
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: infiltrationproblem.hh:321
const MaterialLawParams & materialLawParams(const Context &, unsigned, unsigned) const
Definition: infiltrationproblem.hh:305
void endTimeStep()
Called by the simulator after each time integration.
Definition: infiltrationproblem.hh:251
InfiltrationProblem(Simulator &simulator)
Definition: infiltrationproblem.hh:169
bool shouldWriteRestartFile() const
Returns true if a restart file should be written to disk.
Definition: infiltrationproblem.hh:235
static void registerParameters()
Definition: infiltrationproblem.hh:214
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: infiltrationproblem.hh:357
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: infiltrationproblem.hh:177
Defines the common parameters for the porous medium multi-phase models.
Definition: blackoilmodel.hh:72
Definition: blackoilboundaryratevector.hh:37
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:235
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:69
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:92
The material law which ought to be used (extracted from the spatial parameters)
Definition: multiphasebaseproperties.hh:51
The type of the problem.
Definition: fvbaseproperties.hh:81
Definition: infiltrationproblem.hh:61