waterairproblem.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_WATER_AIR_PROBLEM_HH
29#define EWOMS_WATER_AIR_PROBLEM_HH
30
31#include <dune/common/fmatrix.hh>
32#include <dune/common/fvector.hh>
33
34#include <dune/grid/yaspgrid.hh>
35#include <dune/grid/io/file/dgfparser/dgfyasp.hh>
36
37#include <opm/material/constraintsolvers/ComputeFromReferencePhase.hpp>
38#include <opm/material/fluidmatrixinteractions/LinearMaterial.hpp>
39#include <opm/material/fluidmatrixinteractions/RegularizedBrooksCorey.hpp>
40#include <opm/material/fluidmatrixinteractions/EffToAbsLaw.hpp>
41#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
42#include <opm/material/fluidstates/ImmiscibleFluidState.hpp>
43#include <opm/material/fluidstates/CompositionalFluidState.hpp>
44#include <opm/material/fluidsystems/H2OAirFluidSystem.hpp>
45#include <opm/material/thermal/ConstantSolidHeatCapLaw.hpp>
46#include <opm/material/thermal/SomertonThermalConductionLaw.hpp>
47
49
51
53
55
56#include <sstream>
57#include <string>
58
59namespace Opm {
60template <class TypeTag>
61class WaterAirProblem;
62}
63
64namespace Opm::Properties {
65
66namespace TTag {
68}
69
70// Set the grid type
71template<class TypeTag>
72struct Grid<TypeTag, TTag::WaterAirBaseProblem> { using type = Dune::YaspGrid<2>; };
73
74// Set the problem property
75template<class TypeTag>
76struct Problem<TypeTag, TTag::WaterAirBaseProblem> { using type = Opm::WaterAirProblem<TypeTag>; };
77
78// Set the material Law
79template<class TypeTag>
80struct MaterialLaw<TypeTag, TTag::WaterAirBaseProblem>
81{
82private:
85 using Traits = Opm::TwoPhaseMaterialTraits<Scalar,
86 /*wettingPhaseIdx=*/FluidSystem::liquidPhaseIdx,
87 /*nonWettingPhaseIdx=*/FluidSystem::gasPhaseIdx>;
88
89 // define the material law which is parameterized by effective
90 // saturations
91 using EffMaterialLaw = Opm::RegularizedBrooksCorey<Traits>;
92
93public:
94 // define the material law parameterized by absolute saturations
95 // which uses the two-phase API
96 using type = Opm::EffToAbsLaw<EffMaterialLaw>;
97};
98
99// Set the thermal conduction law
100template<class TypeTag>
101struct ThermalConductionLaw<TypeTag, TTag::WaterAirBaseProblem>
102{
103private:
106
107public:
108 // define the material law parameterized by absolute saturations
109 using type = Opm::SomertonThermalConductionLaw<FluidSystem, Scalar>;
110};
111
112// set the energy storage law for the solid phase
113template<class TypeTag>
114struct SolidEnergyLaw<TypeTag, TTag::WaterAirBaseProblem>
115{ using type = Opm::ConstantSolidHeatCapLaw<GetPropType<TypeTag, Properties::Scalar>>; };
116
117// Set the fluid system. in this case, we use the one which describes
118// air and water
119template<class TypeTag>
120struct FluidSystem<TypeTag, TTag::WaterAirBaseProblem>
121{ using type = Opm::H2OAirFluidSystem<GetPropType<TypeTag, Properties::Scalar>>; };
122
123// Use the restarted GMRES linear solver with the ILU-2 preconditioner from dune-istl
124template<class TypeTag>
125struct LinearSolverSplice<TypeTag, TTag::WaterAirBaseProblem>
127
128template<class TypeTag>
129struct LinearSolverWrapper<TypeTag, TTag::WaterAirBaseProblem>
131
132template<class TypeTag>
133struct PreconditionerWrapper<TypeTag, TTag::WaterAirBaseProblem>
135
136} // namespace Opm::Properties
137
138namespace Opm {
167template <class TypeTag >
168class WaterAirProblem : public GetPropType<TypeTag, Properties::BaseProblem>
169{
171
174
175 // copy some indices for convenience
178 enum {
179 numPhases = FluidSystem::numPhases,
180
181 // energy related indices
182 temperatureIdx = Indices::temperatureIdx,
183 energyEqIdx = Indices::energyEqIdx,
184
185 // component indices
186 H2OIdx = FluidSystem::H2OIdx,
187 AirIdx = FluidSystem::AirIdx,
188
189 // phase indices
190 liquidPhaseIdx = FluidSystem::liquidPhaseIdx,
191 gasPhaseIdx = FluidSystem::gasPhaseIdx,
192
193 // equation indices
194 conti0EqIdx = Indices::conti0EqIdx,
195
196 // Grid and world dimension
197 dim = GridView::dimension,
198 dimWorld = GridView::dimensionworld
199 };
200
201 static const bool enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>();
202
212 using ThermalConductionLawParams = GetPropType<TypeTag, Properties::ThermalConductionLawParams>;
214
215 using CoordScalar = typename GridView::ctype;
216 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
217
218 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
219
220public:
224 WaterAirProblem(Simulator& simulator)
225 : ParentType(simulator)
226 { }
227
232 {
233 ParentType::finishInit();
234
235 maxDepth_ = 1000.0; // [m]
236 eps_ = 1e-6;
237
238 FluidSystem::init(/*Tmin=*/275, /*Tmax=*/600, /*nT=*/100,
239 /*pmin=*/9.5e6, /*pmax=*/10.5e6, /*np=*/200);
240
241 layerBottom_ = 22.0;
242
243 // intrinsic permeabilities
244 fineK_ = this->toDimMatrix_(1e-13);
245 coarseK_ = this->toDimMatrix_(1e-12);
246
247 // porosities
248 finePorosity_ = 0.3;
249 coarsePorosity_ = 0.3;
250
251 // residual saturations
252 fineMaterialParams_.setResidualSaturation(liquidPhaseIdx, 0.2);
253 fineMaterialParams_.setResidualSaturation(gasPhaseIdx, 0.0);
254 coarseMaterialParams_.setResidualSaturation(liquidPhaseIdx, 0.2);
255 coarseMaterialParams_.setResidualSaturation(gasPhaseIdx, 0.0);
256
257 // parameters for the Brooks-Corey law
258 fineMaterialParams_.setEntryPressure(1e4);
259 coarseMaterialParams_.setEntryPressure(1e4);
260 fineMaterialParams_.setLambda(2.0);
261 coarseMaterialParams_.setLambda(2.0);
262
263 fineMaterialParams_.finalize();
264 coarseMaterialParams_.finalize();
265
266 // parameters for the somerton law of thermal conduction
267 computeThermalCondParams_(fineThermalCondParams_, finePorosity_);
268 computeThermalCondParams_(coarseThermalCondParams_, coarsePorosity_);
269
270 // assume constant volumetric heat capacity and granite
271 solidEnergyLawParams_.setSolidHeatCapacity(790.0 // specific heat capacity of granite [J / (kg K)]
272 * 2700.0); // density of granite [kg/m^3]
273 solidEnergyLawParams_.finalize();
274 }
275
280
283 static void registerParameters()
284 {
285 ParentType::registerParameters();
286
287 Parameters::SetDefault<Parameters::GridFile>("./data/waterair.dgf");
288
289 // Use forward differences
290 Parameters::SetDefault<Parameters::NumericDifferenceMethod>(+1);
291
292 Parameters::SetDefault<Parameters::EndTime<Scalar>>(1.0 * 365 * 24 * 60 * 60);
293 Parameters::SetDefault<Parameters::InitialTimeStepSize<Scalar>>(250.0);
294 Parameters::SetDefault<Parameters::EnableGravity>(true);
295 Parameters::SetDefault<Parameters::PreconditionerOrder>(2);
296 }
297
301 std::string name() const
302 {
303 std::ostringstream oss;
304 oss << "waterair_" << Model::name();
305 if (getPropValue<TypeTag, Properties::EnableEnergy>())
306 oss << "_ni";
307
308 return oss.str();
309 }
310
315 {
316#ifndef NDEBUG
317 // checkConservativeness() does not include the effect of constraints, so we
318 // disable it for this problem...
319 //this->model().checkConservativeness();
320
321 // Calculate storage terms
322 EqVector storage;
323 this->model().globalStorage(storage);
324
325 // Write mass balance information for rank 0
326 if (this->gridView().comm().rank() == 0) {
327 std::cout << "Storage: " << storage << std::endl << std::flush;
328 }
329#endif // NDEBUG
330 }
331
338 template <class Context>
339 const DimMatrix& intrinsicPermeability(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
340 {
341 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
342 if (isFineMaterial_(pos))
343 return fineK_;
344 return coarseK_;
345 }
346
350 template <class Context>
351 Scalar porosity(const Context& context, unsigned spaceIdx, unsigned timeIdx) const
352 {
353 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
354 if (isFineMaterial_(pos))
355 return finePorosity_;
356 else
357 return coarsePorosity_;
358 }
359
363 template <class Context>
364 const MaterialLawParams& materialLawParams(const Context& context,
365 unsigned spaceIdx,
366 unsigned timeIdx) const
367 {
368 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
369 if (isFineMaterial_(pos))
370 return fineMaterialParams_;
371 else
372 return coarseMaterialParams_;
373 }
374
380 template <class Context>
381 const SolidEnergyLawParams&
382 solidEnergyLawParams(const Context& /*context*/,
383 unsigned /*spaceIdx*/,
384 unsigned /*timeIdx*/) const
385 { return solidEnergyLawParams_; }
386
390 template <class Context>
391 const ThermalConductionLawParams&
392 thermalConductionLawParams(const Context& context,
393 unsigned spaceIdx,
394 unsigned timeIdx) const
395 {
396 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
397 if (isFineMaterial_(pos))
398 return fineThermalCondParams_;
399 return coarseThermalCondParams_;
400 }
401
403
408
417 template <class Context>
418 void boundary(BoundaryRateVector& values,
419 const Context& context,
420 unsigned spaceIdx, unsigned timeIdx) const
421 {
422 const auto& pos = context.cvCenter(spaceIdx, timeIdx);
423 assert(onLeftBoundary_(pos) ||
424 onLowerBoundary_(pos) ||
425 onRightBoundary_(pos) ||
426 onUpperBoundary_(pos));
427
428 if (onInlet_(pos)) {
429 RateVector massRate(0.0);
430 massRate[conti0EqIdx + AirIdx] = -1e-3; // [kg/(m^2 s)]
431
432 // impose an forced inflow boundary condition on the inlet
433 values.setMassRate(massRate);
434
435 if (enableEnergy) {
436 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
437 initialFluidState_(fs, context, spaceIdx, timeIdx);
438
439 Scalar hl = fs.enthalpy(liquidPhaseIdx);
440 Scalar hg = fs.enthalpy(gasPhaseIdx);
441 values.setEnthalpyRate(values[conti0EqIdx + AirIdx] * hg +
442 values[conti0EqIdx + H2OIdx] * hl);
443 }
444 }
445 else if (onLeftBoundary_(pos) || onRightBoundary_(pos)) {
446 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
447 initialFluidState_(fs, context, spaceIdx, timeIdx);
448
449 // impose an freeflow boundary condition
450 values.setFreeFlow(context, spaceIdx, timeIdx, fs);
451 }
452 else
453 // no flow on top and bottom
454 values.setNoFlow();
455 }
456
458
463
470 template <class Context>
471 void initial(PrimaryVariables& values,
472 const Context& context,
473 unsigned spaceIdx,
474 unsigned timeIdx) const
475 {
476 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
477 initialFluidState_(fs, context, spaceIdx, timeIdx);
478
479 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
480 values.assignMassConservative(fs, matParams, /*inEquilibrium=*/true);
481 }
482
489 template <class Context>
490 void source(RateVector& rate,
491 const Context& /*context*/,
492 unsigned /*spaceIdx*/,
493 unsigned /*timeIdx*/) const
494 { rate = 0; }
495
497
498private:
499 bool onLeftBoundary_(const GlobalPosition& pos) const
500 { return pos[0] < eps_; }
501
502 bool onRightBoundary_(const GlobalPosition& pos) const
503 { return pos[0] > this->boundingBoxMax()[0] - eps_; }
504
505 bool onLowerBoundary_(const GlobalPosition& pos) const
506 { return pos[1] < eps_; }
507
508 bool onUpperBoundary_(const GlobalPosition& pos) const
509 { return pos[1] > this->boundingBoxMax()[1] - eps_; }
510
511 bool onInlet_(const GlobalPosition& pos) const
512 { return onLowerBoundary_(pos) && (15.0 < pos[0]) && (pos[0] < 25.0); }
513
514 bool inHighTemperatureRegion_(const GlobalPosition& pos) const
515 { return (20 < pos[0]) && (pos[0] < 30) && (pos[1] < 30); }
516
517 template <class Context, class FluidState>
518 void initialFluidState_(FluidState& fs,
519 const Context& context,
520 unsigned spaceIdx,
521 unsigned timeIdx) const
522 {
523 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
524
525 Scalar densityW = 1000.0;
526 fs.setPressure(liquidPhaseIdx, 1e5 + (maxDepth_ - pos[1])*densityW*9.81);
527 fs.setSaturation(liquidPhaseIdx, 1.0);
528 fs.setMoleFraction(liquidPhaseIdx, H2OIdx, 1.0);
529 fs.setMoleFraction(liquidPhaseIdx, AirIdx, 0.0);
530
531 if (inHighTemperatureRegion_(pos))
532 fs.setTemperature(380);
533 else
534 fs.setTemperature(283.0 + (maxDepth_ - pos[1])*0.03);
535
536 // set the gas saturation and pressure
537 fs.setSaturation(gasPhaseIdx, 0);
538 Scalar pc[numPhases];
539 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
540 MaterialLaw::capillaryPressures(pc, matParams, fs);
541 fs.setPressure(gasPhaseIdx, fs.pressure(liquidPhaseIdx) + (pc[gasPhaseIdx] - pc[liquidPhaseIdx]));
542
543 typename FluidSystem::template ParameterCache<Scalar> paramCache;
544 using CFRP = Opm::ComputeFromReferencePhase<Scalar, FluidSystem>;
545 CFRP::solve(fs, paramCache, liquidPhaseIdx, /*setViscosity=*/true, /*setEnthalpy=*/true);
546 }
547
548 void computeThermalCondParams_(ThermalConductionLawParams& params, Scalar poro)
549 {
550 Scalar lambdaGranite = 2.8; // [W / (K m)]
551
552 // create a Fluid state which has all phases present
553 Opm::ImmiscibleFluidState<Scalar, FluidSystem> fs;
554 fs.setTemperature(293.15);
555 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
556 fs.setPressure(phaseIdx, 1.0135e5);
557 }
558
559 typename FluidSystem::template ParameterCache<Scalar> paramCache;
560 paramCache.updateAll(fs);
561 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
562 Scalar rho = FluidSystem::density(fs, paramCache, phaseIdx);
563 fs.setDensity(phaseIdx, rho);
564 }
565
566 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
567 Scalar lambdaSaturated;
568 if (FluidSystem::isLiquid(phaseIdx)) {
569 Scalar lambdaFluid =
570 FluidSystem::thermalConductivity(fs, paramCache, phaseIdx);
571 lambdaSaturated = std::pow(lambdaGranite, (1-poro)) + std::pow(lambdaFluid, poro);
572 }
573 else
574 lambdaSaturated = std::pow(lambdaGranite, (1-poro));
575
576 params.setFullySaturatedLambda(phaseIdx, lambdaSaturated);
577 if (!FluidSystem::isLiquid(phaseIdx))
578 params.setVacuumLambda(lambdaSaturated);
579 }
580 }
581
582 bool isFineMaterial_(const GlobalPosition& pos) const
583 { return pos[dim-1] > layerBottom_; }
584
585 DimMatrix fineK_;
586 DimMatrix coarseK_;
587 Scalar layerBottom_;
588
589 Scalar finePorosity_;
590 Scalar coarsePorosity_;
591
592 MaterialLawParams fineMaterialParams_;
593 MaterialLawParams coarseMaterialParams_;
594
595 ThermalConductionLawParams fineThermalCondParams_;
596 ThermalConductionLawParams coarseThermalCondParams_;
597 SolidEnergyLawParams solidEnergyLawParams_;
598
599 Scalar maxDepth_;
600 Scalar eps_;
601};
602} // namespace Opm
603
604#endif
Definition: istlpreconditionerwrappers.hh:153
Solver wrapper for the restarted GMRES solver of dune-istl.
Definition: istlsolverwrappers.hh:115
Non-isothermal gas injection problem where a air is injected into a fully water saturated medium.
Definition: waterairproblem.hh:169
const DimMatrix & intrinsicPermeability(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: waterairproblem.hh:339
static void registerParameters()
Definition: waterairproblem.hh:283
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: waterairproblem.hh:231
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: waterairproblem.hh:471
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: waterairproblem.hh:418
std::string name() const
The problem name.
Definition: waterairproblem.hh:301
Scalar porosity(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: waterairproblem.hh:351
void source(RateVector &rate, const Context &, unsigned, unsigned) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: waterairproblem.hh:490
const ThermalConductionLawParams & thermalConductionLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: waterairproblem.hh:392
void endTimeStep()
Called by the simulator after each time integration.
Definition: waterairproblem.hh:314
WaterAirProblem(Simulator &simulator)
Definition: waterairproblem.hh:224
const MaterialLawParams & materialLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: waterairproblem.hh:364
const SolidEnergyLawParams & solidEnergyLawParams(const Context &, unsigned, unsigned) const
Return the parameters for the energy storage law of the rock.
Definition: waterairproblem.hh:382
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::H2OAirFluidSystem< GetPropType< TypeTag, Properties::Scalar > > type
Definition: waterairproblem.hh:121
The fluid systems including the information about the phases.
Definition: multiphasebaseproperties.hh:69
Dune::YaspGrid< 2 > type
Definition: waterairproblem.hh:72
The type of the DUNE grid.
Definition: basicproperties.hh:100
Definition: fvbaseproperties.hh:53
Definition: linalgproperties.hh:57
Opm::EffToAbsLaw< EffMaterialLaw > type
Definition: waterairproblem.hh:96
The material law which ought to be used (extracted from the spatial parameters)
Definition: multiphasebaseproperties.hh:51
the preconditioner used by the linear solver
Definition: linalgproperties.hh:42
The type of the problem.
Definition: fvbaseproperties.hh:81
Opm::ConstantSolidHeatCapLaw< GetPropType< TypeTag, Properties::Scalar > > type
Definition: waterairproblem.hh:115
The material law for the energy stored in the solid matrix.
Definition: multiphasebaseproperties.hh:57
Definition: parallelistlbackend.hh:40
Definition: waterairproblem.hh:67
Opm::SomertonThermalConductionLaw< FluidSystem, Scalar > type
Definition: waterairproblem.hh:109
The material law for thermal conduction.
Definition: multiphasebaseproperties.hh:63