obstacleproblem.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_OBSTACLE_PROBLEM_HH
29#define EWOMS_OBSTACLE_PROBLEM_HH
30
31#include <dune/common/fmatrix.hh>
32#include <dune/common/fvector.hh>
33#include <dune/common/version.hh>
34
35#include <dune/grid/yaspgrid.hh>
36#include <dune/grid/io/file/dgfparser/dgfyasp.hh>
37
38#include <opm/material/constraintsolvers/ComputeFromReferencePhase.hpp>
39#include <opm/material/fluidmatrixinteractions/EffToAbsLaw.hpp>
40#include <opm/material/fluidmatrixinteractions/LinearMaterial.hpp>
41#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
42#include <opm/material/fluidmatrixinteractions/RegularizedBrooksCorey.hpp>
43#include <opm/material/fluidstates/CompositionalFluidState.hpp>
44#include <opm/material/fluidsystems/H2ON2FluidSystem.hpp>
45#include <opm/material/thermal/ConstantSolidHeatCapLaw.hpp>
46#include <opm/material/thermal/SomertonThermalConductionLaw.hpp>
47
49
51
52#include <iostream>
53#include <sstream>
54#include <string>
55
56namespace Opm {
57template <class TypeTag>
58class ObstacleProblem;
59}
60
61namespace Opm::Properties {
62
63namespace TTag {
65}
66
67// Set the grid type
68template<class TypeTag>
69struct Grid<TypeTag, TTag::ObstacleBaseProblem> { using type = Dune::YaspGrid<2>; };
70
71// Set the problem property
72template<class TypeTag>
73struct Problem<TypeTag, TTag::ObstacleBaseProblem> { using type = Opm::ObstacleProblem<TypeTag>; };
74
75// Set fluid configuration
76template<class TypeTag>
77struct FluidSystem<TypeTag, TTag::ObstacleBaseProblem>
78{ using type = Opm::H2ON2FluidSystem<GetPropType<TypeTag, Properties::Scalar>>; };
79
80// Set the material Law
81template<class TypeTag>
82struct MaterialLaw<TypeTag, TTag::ObstacleBaseProblem>
83{
84private:
85 // define the material law
88 using MaterialTraits = Opm::TwoPhaseMaterialTraits<Scalar,
89 /*wettingPhaseIdx=*/FluidSystem::liquidPhaseIdx,
90 /*nonWettingPhaseIdx=*/FluidSystem::gasPhaseIdx>;
91
92 using EffMaterialLaw = Opm::LinearMaterial<MaterialTraits>;
93
94public:
95 using type = Opm::EffToAbsLaw<EffMaterialLaw>;
96};
97
98// Set the thermal conduction law
99template<class TypeTag>
100struct ThermalConductionLaw<TypeTag, TTag::ObstacleBaseProblem>
101{
102private:
105
106public:
107 // define the material law parameterized by absolute saturations
108 using type = Opm::SomertonThermalConductionLaw<FluidSystem, Scalar>;
109};
110
111// set the energy storage law for the solid phase
112template<class TypeTag>
113struct SolidEnergyLaw<TypeTag, TTag::ObstacleBaseProblem>
114{ using type = Opm::ConstantSolidHeatCapLaw<GetPropType<TypeTag, Properties::Scalar>>; };
115
116} // namespace Opm::Properties
117
118namespace Opm {
145template <class TypeTag>
146class ObstacleProblem : public GetPropType<TypeTag, Properties::BaseProblem>
147{
149
159 using ThermalConductionLawParams = GetPropType<TypeTag, Properties::ThermalConductionLawParams>;
161
162 enum {
163 // Grid and world dimension
164 dim = GridView::dimension,
165 dimWorld = GridView::dimensionworld,
166 numPhases = getPropValue<TypeTag, Properties::NumPhases>(),
167 gasPhaseIdx = FluidSystem::gasPhaseIdx,
168 liquidPhaseIdx = FluidSystem::liquidPhaseIdx,
169 H2OIdx = FluidSystem::H2OIdx,
170 N2Idx = FluidSystem::N2Idx
171 };
172
173 using GlobalPosition = Dune::FieldVector<typename GridView::ctype, dimWorld>;
174 using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
175 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
178
179public:
183 ObstacleProblem(Simulator& simulator)
184 : ParentType(simulator)
185 { }
186
191 {
192 ParentType::finishInit();
193
194 eps_ = 1e-6;
195 temperature_ = 273.15 + 25; // -> 25°C
196
197 // initialize the tables of the fluid system
198 Scalar Tmin = temperature_ - 1.0;
199 Scalar Tmax = temperature_ + 1.0;
200 unsigned nT = 3;
201
202 Scalar pmin = 1.0e5 * 0.75;
203 Scalar pmax = 2.0e5 * 1.25;
204 unsigned np = 1000;
205
206 FluidSystem::init(Tmin, Tmax, nT, pmin, pmax, np);
207
208 // intrinsic permeabilities
209 coarseK_ = this->toDimMatrix_(1e-12);
210 fineK_ = this->toDimMatrix_(1e-15);
211
212 // the porosity
213 finePorosity_ = 0.3;
214 coarsePorosity_ = 0.3;
215
216 // residual saturations
217 fineMaterialParams_.setResidualSaturation(liquidPhaseIdx, 0.0);
218 fineMaterialParams_.setResidualSaturation(gasPhaseIdx, 0.0);
219 coarseMaterialParams_.setResidualSaturation(liquidPhaseIdx, 0.0);
220 coarseMaterialParams_.setResidualSaturation(gasPhaseIdx, 0.0);
221
222 // parameters for the linear law, i.e. minimum and maximum
223 // pressures
224 fineMaterialParams_.setPcMinSat(liquidPhaseIdx, 0.0);
225 fineMaterialParams_.setPcMaxSat(liquidPhaseIdx, 0.0);
226 coarseMaterialParams_.setPcMinSat(liquidPhaseIdx, 0.0);
227 coarseMaterialParams_.setPcMaxSat(liquidPhaseIdx, 0.0);
228
229 /*
230 // entry pressures for Brooks-Corey
231 fineMaterialParams_.setEntryPressure(5e3);
232 coarseMaterialParams_.setEntryPressure(1e3);
233
234 // Brooks-Corey shape parameters
235 fineMaterialParams_.setLambda(2);
236 coarseMaterialParams_.setLambda(2);
237 */
238
239 fineMaterialParams_.finalize();
240 coarseMaterialParams_.finalize();
241
242 // parameters for the somerton law of thermal conduction
243 computeThermalCondParams_(fineThermalCondParams_, finePorosity_);
244 computeThermalCondParams_(coarseThermalCondParams_, coarsePorosity_);
245
246 // assume constant volumetric heat capacity and granite
247 solidEnergyLawParams_.setSolidHeatCapacity(790.0 // specific heat capacity of granite [J / (kg K)]
248 * 2700.0); // density of granite [kg/m^3]
249 solidEnergyLawParams_.finalize();
250
251 initFluidStates_();
252 }
253
257 static void registerParameters()
258 {
259 ParentType::registerParameters();
260
261 Parameters::SetDefault<Parameters::GridFile>("./data/obstacle_24x16.dgf");
262 Parameters::SetDefault<Parameters::EndTime<Scalar>>(1e4);
263 Parameters::SetDefault<Parameters::InitialTimeStepSize<Scalar>>(250);
264 Parameters::SetDefault<Parameters::EnableGravity>(true);
265 }
266
271 {
272#ifndef NDEBUG
273 this->model().checkConservativeness();
274
275 // Calculate storage terms of the individual phases
276 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
277 PrimaryVariables phaseStorage;
278 this->model().globalPhaseStorage(phaseStorage, phaseIdx);
279
280 if (this->gridView().comm().rank() == 0) {
281 std::cout << "Storage in " << FluidSystem::phaseName(phaseIdx)
282 << "Phase: [" << phaseStorage << "]"
283 << "\n" << std::flush;
284 }
285 }
286
287 // Calculate total storage terms
288 EqVector storage;
289 this->model().globalStorage(storage);
290
291 // Write mass balance information for rank 0
292 if (this->gridView().comm().rank() == 0) {
293 std::cout << "Storage total: [" << storage << "]"
294 << "\n" << std::flush;
295 }
296#endif // NDEBUG
297 }
298
303
307 std::string name() const
308 {
309 std::ostringstream oss;
310 oss << "obstacle"
311 << "_" << Model::name();
312 return oss.str();
313 }
314
320 template <class Context>
321 Scalar temperature(const Context& /*context*/,
322 unsigned /*spaceIdx*/,
323 unsigned /*timeIdx*/) const
324 { return temperature_; }
325
329 template <class Context>
330 const DimMatrix&
331 intrinsicPermeability(const Context& context,
332 unsigned spaceIdx,
333 unsigned timeIdx) const
334 {
335 if (isFineMaterial_(context.pos(spaceIdx, timeIdx)))
336 return fineK_;
337 return coarseK_;
338 }
339
343 template <class Context>
344 Scalar porosity(const Context& context,
345 unsigned spaceIdx,
346 unsigned timeIdx) const
347 {
348 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
349 if (isFineMaterial_(pos))
350 return finePorosity_;
351 else
352 return coarsePorosity_;
353 }
354
358 template <class Context>
359 const MaterialLawParams&
360 materialLawParams(const Context& context,
361 unsigned spaceIdx,
362 unsigned timeIdx) const
363 {
364 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
365 if (isFineMaterial_(pos))
366 return fineMaterialParams_;
367 else
368 return coarseMaterialParams_;
369 }
370
376 template <class Context>
377 const SolidEnergyLawParams&
378 solidEnergyLawParams(const Context& /*context*/,
379 unsigned /*spaceIdx*/,
380 unsigned /*timeIdx*/) const
381 { return solidEnergyLawParams_; }
382
386 template <class Context>
387 const ThermalConductionLawParams &
388 thermalConductionParams(const Context& context,
389 unsigned spaceIdx,
390 unsigned timeIdx) const
391 {
392 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
393 if (isFineMaterial_(pos))
394 return fineThermalCondParams_;
395 return coarseThermalCondParams_;
396 }
397
399
404
408 template <class Context>
409 void boundary(BoundaryRateVector& values,
410 const Context& context,
411 unsigned spaceIdx,
412 unsigned timeIdx) const
413 {
414 const auto& pos = context.pos(spaceIdx, timeIdx);
415
416 if (onInlet_(pos))
417 values.setFreeFlow(context, spaceIdx, timeIdx, inletFluidState_);
418 else if (onOutlet_(pos))
419 values.setFreeFlow(context, spaceIdx, timeIdx, outletFluidState_);
420 else
421 values.setNoFlow();
422 }
423
425
430
434 template <class Context>
435 void initial(PrimaryVariables& values,
436 const Context& context,
437 unsigned spaceIdx,
438 unsigned timeIdx) const
439 {
440 const auto& matParams = materialLawParams(context, spaceIdx, timeIdx);
441 values.assignMassConservative(outletFluidState_, matParams);
442 }
443
450 template <class Context>
451 void source(RateVector& rate,
452 const Context& /*context*/,
453 unsigned /*spaceIdx*/,
454 unsigned /*timeIdx*/) const
455 { rate = 0.0; }
456
458
459private:
464 bool isFineMaterial_(const GlobalPosition& pos) const
465 { return 10 <= pos[0] && pos[0] <= 20 && 0 <= pos[1] && pos[1] <= 35; }
466
467 bool onInlet_(const GlobalPosition& globalPos) const
468 {
469 Scalar x = globalPos[0];
470 Scalar y = globalPos[1];
471 return x >= 60 - eps_ && y <= 10;
472 }
473
474 bool onOutlet_(const GlobalPosition& globalPos) const
475 {
476 Scalar x = globalPos[0];
477 Scalar y = globalPos[1];
478 return x < eps_ && y <= 10;
479 }
480
481 void initFluidStates_()
482 {
483 initFluidState_(inletFluidState_, coarseMaterialParams_,
484 /*isInlet=*/true);
485 initFluidState_(outletFluidState_, coarseMaterialParams_,
486 /*isInlet=*/false);
487 }
488
489 template <class FluidState>
490 void initFluidState_(FluidState& fs, const MaterialLawParams& matParams, bool isInlet)
491 {
492 unsigned refPhaseIdx;
493 unsigned otherPhaseIdx;
494
495 // set the fluid temperatures
496 fs.setTemperature(temperature_);
497
498 if (isInlet) {
499 // only liquid on inlet
500 refPhaseIdx = liquidPhaseIdx;
501 otherPhaseIdx = gasPhaseIdx;
502
503 // set liquid saturation
504 fs.setSaturation(liquidPhaseIdx, 1.0);
505
506 // set pressure of the liquid phase
507 fs.setPressure(liquidPhaseIdx, 2e5);
508
509 // set the liquid composition to pure water
510 fs.setMoleFraction(liquidPhaseIdx, N2Idx, 0.0);
511 fs.setMoleFraction(liquidPhaseIdx, H2OIdx, 1.0);
512 }
513 else {
514 // elsewhere, only gas
515 refPhaseIdx = gasPhaseIdx;
516 otherPhaseIdx = liquidPhaseIdx;
517
518 // set gas saturation
519 fs.setSaturation(gasPhaseIdx, 1.0);
520
521 // set pressure of the gas phase
522 fs.setPressure(gasPhaseIdx, 1e5);
523
524 // set the gas composition to 99% nitrogen and 1% steam
525 fs.setMoleFraction(gasPhaseIdx, N2Idx, 0.99);
526 fs.setMoleFraction(gasPhaseIdx, H2OIdx, 0.01);
527 }
528
529 // set the other saturation
530 fs.setSaturation(otherPhaseIdx, 1.0 - fs.saturation(refPhaseIdx));
531
532 // calulate the capillary pressure
533 PhaseVector pC;
534 MaterialLaw::capillaryPressures(pC, matParams, fs);
535 fs.setPressure(otherPhaseIdx, fs.pressure(refPhaseIdx)
536 + (pC[otherPhaseIdx] - pC[refPhaseIdx]));
537
538 // make the fluid state consistent with local thermodynamic
539 // equilibrium
540 using ComputeFromReferencePhase = Opm::ComputeFromReferencePhase<Scalar, FluidSystem>;
541
542 typename FluidSystem::template ParameterCache<Scalar> paramCache;
543 ComputeFromReferencePhase::solve(fs, paramCache, refPhaseIdx,
544 /*setViscosity=*/true,
545 /*setEnthalpy=*/false);
546 }
547
548 void computeThermalCondParams_(ThermalConductionLawParams& params, Scalar poro)
549 {
550 Scalar lambdaWater = 0.6;
551 Scalar lambdaGranite = 2.8;
552
553 Scalar lambdaWet = std::pow(lambdaGranite, (1 - poro))
554 * std::pow(lambdaWater, poro);
555 Scalar lambdaDry = std::pow(lambdaGranite, (1 - poro));
556
557 params.setFullySaturatedLambda(gasPhaseIdx, lambdaDry);
558 params.setFullySaturatedLambda(liquidPhaseIdx, lambdaWet);
559 params.setVacuumLambda(lambdaDry);
560 }
561
562 DimMatrix coarseK_;
563 DimMatrix fineK_;
564
565 Scalar coarsePorosity_;
566 Scalar finePorosity_;
567
568 MaterialLawParams fineMaterialParams_;
569 MaterialLawParams coarseMaterialParams_;
570
571 ThermalConductionLawParams fineThermalCondParams_;
572 ThermalConductionLawParams coarseThermalCondParams_;
573 SolidEnergyLawParams solidEnergyLawParams_;
574
575 Opm::CompositionalFluidState<Scalar, FluidSystem> inletFluidState_;
576 Opm::CompositionalFluidState<Scalar, FluidSystem> outletFluidState_;
577
578 Scalar temperature_;
579 Scalar eps_;
580};
581} // namespace Opm
582
583#endif
Problem where liquid water is first stopped by a low-permeability lens and then seeps though it.
Definition: obstacleproblem.hh:147
Scalar porosity(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: obstacleproblem.hh:344
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: obstacleproblem.hh:190
const MaterialLawParams & materialLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: obstacleproblem.hh:360
const DimMatrix & intrinsicPermeability(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: obstacleproblem.hh:331
const ThermalConductionLawParams & thermalConductionParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: obstacleproblem.hh:388
Scalar temperature(const Context &, unsigned, unsigned) const
Definition: obstacleproblem.hh:321
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: obstacleproblem.hh:409
std::string name() const
The problem name.
Definition: obstacleproblem.hh:307
void endTimeStep()
Called by the simulator after each time integration.
Definition: obstacleproblem.hh:270
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: obstacleproblem.hh:435
const SolidEnergyLawParams & solidEnergyLawParams(const Context &, unsigned, unsigned) const
Return the parameters for the energy storage law of the rock.
Definition: obstacleproblem.hh:378
void source(RateVector &rate, const Context &, unsigned, unsigned) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: obstacleproblem.hh:451
ObstacleProblem(Simulator &simulator)
Definition: obstacleproblem.hh:183
static void registerParameters()
Definition: obstacleproblem.hh:257
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 NCP compositional multi-phase model.
Opm::H2ON2FluidSystem< GetPropType< TypeTag, Properties::Scalar > > type
Definition: obstacleproblem.hh:78
The fluid systems including the information about the phases.
Definition: multiphasebaseproperties.hh:69
Dune::YaspGrid< 2 > type
Definition: obstacleproblem.hh:69
The type of the DUNE grid.
Definition: basicproperties.hh:100
Opm::EffToAbsLaw< EffMaterialLaw > type
Definition: obstacleproblem.hh:95
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
Opm::ConstantSolidHeatCapLaw< GetPropType< TypeTag, Properties::Scalar > > type
Definition: obstacleproblem.hh:114
The material law for the energy stored in the solid matrix.
Definition: multiphasebaseproperties.hh:57
Definition: obstacleproblem.hh:64
Opm::SomertonThermalConductionLaw< FluidSystem, Scalar > type
Definition: obstacleproblem.hh:108
The material law for thermal conduction.
Definition: multiphasebaseproperties.hh:63