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