fingerproblem.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_FINGER_PROBLEM_HH
29#define EWOMS_FINGER_PROBLEM_HH
30
31#if HAVE_DUNE_ALUGRID
32#include <dune/alugrid/grid.hh>
33#endif
34
35#include <dune/common/fmatrix.hh>
36#include <dune/common/fvector.hh>
37#include <dune/common/version.hh>
38
39#include <dune/grid/utility/persistentcontainer.hh>
40
41#include <opm/material/components/Air.hpp>
42#include <opm/material/components/SimpleH2O.hpp>
43
44#include <opm/material/fluidmatrixinteractions/EffToAbsLaw.hpp>
45#include <opm/material/fluidmatrixinteractions/LinearMaterial.hpp>
46#include <opm/material/fluidmatrixinteractions/MaterialTraits.hpp>
47#include <opm/material/fluidmatrixinteractions/ParkerLenhard.hpp>
48#include <opm/material/fluidmatrixinteractions/RegularizedVanGenuchten.hpp>
49
50#include <opm/material/fluidstates/ImmiscibleFluidState.hpp>
51
52#include <opm/material/fluidsystems/TwoPhaseImmiscibleFluidSystem.hpp>
53
55
58
60
62
63#include <string>
64
65namespace Opm {
66template <class TypeTag>
67class FingerProblem;
68
69} // namespace Opm
70
71namespace Opm::Properties {
72
73// Create new type tags
74namespace TTag {
75struct FingerBaseProblem { using InheritsFrom = std::tuple<StructuredGridVanguard>; };
76} // end namespace TTag
77
78#if HAVE_DUNE_ALUGRID
79// use dune-alugrid if available
80template<class TypeTag>
81struct Grid<TypeTag, TTag::FingerBaseProblem>
82{ using type = Dune::ALUGrid</*dim=*/2,
83 /*dimWorld=*/2,
85 Dune::nonconforming>; };
86#endif
87
88// Set the problem property
89template<class TypeTag>
90struct Problem<TypeTag, TTag::FingerBaseProblem> { using type = Opm::FingerProblem<TypeTag>; };
91
92// Set the wetting phase
93template<class TypeTag>
94struct WettingPhase<TypeTag, TTag::FingerBaseProblem>
95{
96private:
98
99public:
100 using type = Opm::LiquidPhase<Scalar, Opm::SimpleH2O<Scalar> >;
101};
102
103// Set the non-wetting phase
104template<class TypeTag>
105struct NonwettingPhase<TypeTag, TTag::FingerBaseProblem>
106{
107private:
109
110public:
111 using type = Opm::GasPhase<Scalar, Opm::Air<Scalar> >;
112};
113
114// Set the material Law
115template<class TypeTag>
116struct MaterialLaw<TypeTag, TTag::FingerBaseProblem>
117{
120 using Traits = Opm::TwoPhaseMaterialTraits<Scalar,
121 /*wettingPhaseIdx=*/FluidSystem::wettingPhaseIdx,
122 /*nonWettingPhaseIdx=*/FluidSystem::nonWettingPhaseIdx>;
123
124 // use the parker-lenhard hysteresis law
125 using ParkerLenhard = Opm::ParkerLenhard<Traits>;
127};
128
129// Enable constraints
130template<class TypeTag>
131struct EnableConstraints<TypeTag, TTag::FingerBaseProblem> { static constexpr int value = true; };
132
133} // namespace Opm::Properties
134
135namespace Opm::Parameters {
136
137template<class Scalar>
138struct InitialWaterSaturation { static constexpr Scalar value = 0.01; };
139
140} // namespace Opm::Parameters
141
142namespace Opm {
143
159template <class TypeTag>
160class FingerProblem : public GetPropType<TypeTag, Properties::BaseProblem>
161{
164
175
176 enum {
177 // number of phases
178 numPhases = FluidSystem::numPhases,
179
180 // phase indices
181 wettingPhaseIdx = FluidSystem::wettingPhaseIdx,
182 nonWettingPhaseIdx = FluidSystem::nonWettingPhaseIdx,
183
184 // equation indices
185 contiWettingEqIdx = Indices::conti0EqIdx + wettingPhaseIdx,
186
187 // Grid and world dimension
188 dim = GridView::dimension,
189 dimWorld = GridView::dimensionworld
190 };
191
194 enum { codim = Stencil::Entity::codimension };
198
202
203 using CoordScalar = typename GridView::ctype;
204 using GlobalPosition = Dune::FieldVector<CoordScalar, dimWorld>;
205 using DimMatrix = Dune::FieldMatrix<Scalar, dimWorld, dimWorld>;
206
207 using Grid = typename GridView :: Grid;
208
209 using MaterialLawParamsContainer = Dune::PersistentContainer< Grid, std::shared_ptr< MaterialLawParams > > ;
211
212public:
214
219 : ParentType(simulator),
220 materialParams_( simulator.vanguard().grid(), codim )
221 {
222 }
223
228
233 {
234 return RestrictProlongOperator( materialParams_ );
235 }
236
240 std::string name() const
241 { return
242 std::string("finger") +
243 "_" + Model::name() +
244 "_" + Model::discretizationName() +
245 (this->model().enableGridAdaptation()?"_adaptive":"");
246 }
247
251 static void registerParameters()
252 {
253 ParentType::registerParameters();
254
255 Parameters::Register<Parameters::InitialWaterSaturation<Scalar>>
256 ("The initial saturation in the domain [] of the wetting phase");
257
258 Parameters::SetDefault<Parameters::CellsX>(20);
259 Parameters::SetDefault<Parameters::DomainSizeX<Scalar>>(0.1);
260
261 if constexpr (dim > 1) {
262 Parameters::SetDefault<Parameters::CellsY>(70);
263 Parameters::SetDefault<Parameters::DomainSizeY<Scalar>>(0.3);
264 }
265 if constexpr (dim == 3) {
266 Parameters::SetDefault<Parameters::CellsZ>(1);
267 Parameters::SetDefault<Parameters::DomainSizeZ<Scalar>>(0.1);
268 }
269
270 // Use forward differences
271 Parameters::SetDefault<Parameters::NumericDifferenceMethod>(+1);
272
273 Parameters::SetDefault<Parameters::EndTime<Scalar>>(215);
274 Parameters::SetDefault<Parameters::InitialTimeStepSize<Scalar>>(10);
275 Parameters::SetDefault<Parameters::EnableGravity>(true);
276 }
277
282 {
283 ParentType::finishInit();
284
285 eps_ = 3e-6;
286
287 temperature_ = 273.15 + 20; // -> 20°C
288
289 FluidSystem::init();
290
291 // parameters for the Van Genuchten law of the main imbibition
292 // and the main drainage curves.
293 micParams_.setVgAlpha(0.0037);
294 micParams_.setVgN(4.7);
295 micParams_.finalize();
296
297 mdcParams_.setVgAlpha(0.0037);
298 mdcParams_.setVgN(4.7);
299 mdcParams_.finalize();
300
301 // initialize the material parameter objects of the individual
302 // finite volumes, resize will resize the container to the number of elements
303 materialParams_.resize();
304
305 for (auto it = materialParams_.begin(),
306 end = materialParams_.end(); it != end; ++it ) {
307 std::shared_ptr< MaterialLawParams >& materialParams = *it ;
308 if( ! materialParams )
309 {
310 materialParams.reset( new MaterialLawParams() );
311 materialParams->setMicParams(&micParams_);
312 materialParams->setMdcParams(&mdcParams_);
313 materialParams->setSwr(0.0);
314 materialParams->setSnr(0.1);
315 materialParams->finalize();
316 ParkerLenhard::reset(*materialParams);
317 }
318 }
319
320 K_ = this->toDimMatrix_(4.6e-10);
321
322 setupInitialFluidState_();
323 }
324
329 {
330#ifndef NDEBUG
331 // checkConservativeness() does not include the effect of constraints, so we
332 // disable it for this problem...
333 //this->model().checkConservativeness();
334
335 // Calculate storage terms
336 EqVector storage;
337 this->model().globalStorage(storage);
338
339 // Write mass balance information for rank 0
340 if (this->gridView().comm().rank() == 0) {
341 std::cout << "Storage: " << storage << std::endl << std::flush;
342 }
343#endif // NDEBUG
344
345 // update the history of the hysteresis law
346 ElementContext elemCtx(this->simulator());
347
348 for (const auto& elem : elements(this->gridView())) {
349 elemCtx.updateAll(elem);
350 size_t numDofs = elemCtx.numDof(/*timeIdx=*/0);
351 for (unsigned scvIdx = 0; scvIdx < numDofs; ++scvIdx)
352 {
353 MaterialLawParams& materialParam = materialLawParams( elemCtx, scvIdx, /*timeIdx=*/0 );
354 const auto& fs = elemCtx.intensiveQuantities(scvIdx, /*timeIdx=*/0).fluidState();
355 ParkerLenhard::update(materialParam, fs);
356 }
357 }
358 }
359
361
366
370 template <class Context>
371 Scalar temperature(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const
372 { return temperature_; }
373
377 template <class Context>
378 const DimMatrix& intrinsicPermeability(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const
379 { return K_; }
380
384 template <class Context>
385 Scalar porosity(const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const
386 { return 0.4; }
387
391 template <class Context>
392 MaterialLawParams& materialLawParams(const Context& context,
393 unsigned spaceIdx, unsigned timeIdx)
394 {
395 const auto& entity = context.stencil(timeIdx).entity(spaceIdx);
396 assert(materialParams_[entity]);
397 return *materialParams_[entity];
398 }
399
403 template <class Context>
404 const MaterialLawParams& materialLawParams(const Context& context,
405 unsigned spaceIdx, unsigned timeIdx) const
406 {
407 const auto& entity = context.stencil(timeIdx).entity( spaceIdx );
408 assert(materialParams_[entity]);
409 return *materialParams_[entity];
410 }
411
413
418
422 template <class Context>
423 void boundary(BoundaryRateVector& values, const Context& context,
424 unsigned spaceIdx, unsigned timeIdx) const
425 {
426 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
427
428 if (onLeftBoundary_(pos) || onRightBoundary_(pos) || onLowerBoundary_(pos))
429 values.setNoFlow();
430 else {
431 assert(onUpperBoundary_(pos));
432
433 values.setFreeFlow(context, spaceIdx, timeIdx, initialFluidState_);
434 }
435
436 // override the value for the liquid phase by forced
437 // imbibition of water on inlet boundary segments
438 if (onInlet_(pos)) {
439 values[contiWettingEqIdx] = -0.001; // [kg/(m^2 s)]
440 }
441 }
442
444
449
453 template <class Context>
454 void initial(PrimaryVariables& values, const Context& /*context*/, unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const
455 {
456 // assign the primary variables
457 values.assignNaive(initialFluidState_);
458 }
459
463 template <class Context>
464 void constraints(Constraints& constraints, const Context& context,
465 unsigned spaceIdx, unsigned timeIdx) const
466 {
467 const GlobalPosition& pos = context.pos(spaceIdx, timeIdx);
468
469 if (onUpperBoundary_(pos) && !onInlet_(pos)) {
470 constraints.setActive(true);
471 constraints.assignNaive(initialFluidState_);
472 }
473 else if (onLowerBoundary_(pos)) {
474 constraints.setActive(true);
475 constraints.assignNaive(initialFluidState_);
476 }
477 }
478
485 template <class Context>
486 void source(RateVector& rate, const Context& /*context*/,
487 unsigned /*spaceIdx*/, unsigned /*timeIdx*/) const
488 { rate = Scalar(0.0); }
490
491private:
492 bool onLeftBoundary_(const GlobalPosition& pos) const
493 { return pos[0] < this->boundingBoxMin()[0] + eps_; }
494
495 bool onRightBoundary_(const GlobalPosition& pos) const
496 { return pos[0] > this->boundingBoxMax()[0] - eps_; }
497
498 bool onLowerBoundary_(const GlobalPosition& pos) const
499 { return pos[1] < this->boundingBoxMin()[1] + eps_; }
500
501 bool onUpperBoundary_(const GlobalPosition& pos) const
502 { return pos[1] > this->boundingBoxMax()[1] - eps_; }
503
504 bool onInlet_(const GlobalPosition& pos) const
505 {
506 Scalar width = this->boundingBoxMax()[0] - this->boundingBoxMin()[0];
507 Scalar lambda = (this->boundingBoxMax()[0] - pos[0]) / width;
508
509 if (!onUpperBoundary_(pos))
510 return false;
511
512 Scalar xInject[] = { 0.25, 0.75 };
513 Scalar injectLen[] = { 0.1, 0.1 };
514 for (unsigned i = 0; i < sizeof(xInject) / sizeof(Scalar); ++i) {
515 if (xInject[i] - injectLen[i] / 2 < lambda
516 && lambda < xInject[i] + injectLen[i] / 2)
517 return true;
518 }
519 return false;
520 }
521
522 void setupInitialFluidState_()
523 {
524 auto& fs = initialFluidState_;
525 fs.setPressure(wettingPhaseIdx, /*pressure=*/1e5);
526
527 Scalar Sw = Parameters::Get<Parameters::InitialWaterSaturation<Scalar>>();
528 fs.setSaturation(wettingPhaseIdx, Sw);
529 fs.setSaturation(nonWettingPhaseIdx, 1 - Sw);
530
531 fs.setTemperature(temperature_);
532
533 // set the absolute pressures
534 Scalar pn = 1e5;
535 fs.setPressure(nonWettingPhaseIdx, pn);
536 fs.setPressure(wettingPhaseIdx, pn);
537
538 typename FluidSystem::template ParameterCache<Scalar> paramCache;
539 paramCache.updateAll(fs);
540 for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++ phaseIdx) {
541 fs.setDensity(phaseIdx, FluidSystem::density(fs, paramCache, phaseIdx));
542 fs.setViscosity(phaseIdx, FluidSystem::viscosity(fs, paramCache, phaseIdx));
543 }
544
545 }
546
547 DimMatrix K_;
548
549 typename MaterialLawParams::VanGenuchtenParams micParams_;
550 typename MaterialLawParams::VanGenuchtenParams mdcParams_;
551
552 MaterialLawParamsContainer materialParams_;
553
554 Opm::ImmiscibleFluidState<Scalar, FluidSystem> initialFluidState_;
555
556 Scalar temperature_;
557 Scalar eps_;
558};
559
560} // namespace Opm
561
562#endif
Definition: restrictprolong.hh:47
Two-phase problem featuring some gravity-driven saturation fingers.
Definition: fingerproblem.hh:161
MaterialLawParams & materialLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx)
Definition: fingerproblem.hh:392
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the boundary conditions for a boundary segment.
Definition: fingerproblem.hh:423
const MaterialLawParams & materialLawParams(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: fingerproblem.hh:404
const DimMatrix & intrinsicPermeability(const Context &, unsigned, unsigned) const
Definition: fingerproblem.hh:378
Scalar porosity(const Context &, unsigned, unsigned) const
Definition: fingerproblem.hh:385
void source(RateVector &rate, const Context &, unsigned, unsigned) const
Evaluate the source term for all phases within a given sub-control-volume.
Definition: fingerproblem.hh:486
void constraints(Constraints &constraints, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the constraints for a control volume.
Definition: fingerproblem.hh:464
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: fingerproblem.hh:281
Scalar temperature(const Context &, unsigned, unsigned) const
Definition: fingerproblem.hh:371
void initial(PrimaryVariables &values, const Context &, unsigned, unsigned) const
Evaluate the initial value for a control volume.
Definition: fingerproblem.hh:454
void endTimeStep()
Called by the simulator after each time integration.
Definition: fingerproblem.hh:328
RestrictProlongOperator restrictProlongOperator()
return restriction and prolongation operator
Definition: fingerproblem.hh:232
static void registerParameters()
Definition: fingerproblem.hh:251
CopyRestrictProlong< Grid, MaterialLawParamsContainer > RestrictProlongOperator
Definition: fingerproblem.hh:213
std::string name() const
The problem name.
Definition: fingerproblem.hh:240
FingerProblem(Simulator &simulator)
Definition: fingerproblem.hh:218
Manages the initializing and running of time dependent problems.
Definition: simulator.hh:92
Defines the properties required for the immiscible multi-phase model.
Defines the common parameters for the porous medium multi-phase models.
Definition: blackoilnewtonmethodparams.hpp:31
void reset()
Reset parameter system.
Definition: blackoilmodel.hh:72
static const int dim
Definition: structuredgridvanguard.hh:67
Definition: blackoilboundaryratevector.hh:37
@ cube
Definition: vcfvstencil.hh:55
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
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:226
Definition: fingerproblem.hh:138
static constexpr Scalar value
Definition: fingerproblem.hh:138
Specify whether the some degrees of fredom can be constraint.
Definition: fvbaseproperties.hh:199
The type of the DUNE grid.
Definition: basicproperties.hh:100
UndefinedProperty type
Definition: basicproperties.hh:100
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: fingerproblem.hh:118
Opm::ParkerLenhard< Traits > ParkerLenhard
Definition: fingerproblem.hh:125
ParkerLenhard type
Definition: fingerproblem.hh:126
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: fingerproblem.hh:119
Opm::TwoPhaseMaterialTraits< Scalar, FluidSystem::wettingPhaseIdx, FluidSystem::nonWettingPhaseIdx > Traits
Definition: fingerproblem.hh:122
The material law which ought to be used (extracted from the spatial parameters)
Definition: multiphasebaseproperties.hh:51
Opm::GasPhase< Scalar, Opm::Air< Scalar > > type
Definition: fingerproblem.hh:111
The non-wetting phase for two-phase models.
Definition: immiscibleproperties.hh:44
The type of the problem.
Definition: fvbaseproperties.hh:81
Definition: fingerproblem.hh:75
std::tuple< StructuredGridVanguard > InheritsFrom
Definition: fingerproblem.hh:75
Opm::LiquidPhase< Scalar, Opm::SimpleH2O< Scalar > > type
Definition: fingerproblem.hh:100
The wetting phase for two-phase models.
Definition: immiscibleproperties.hh:41