diff --git a/exercises/exercise-basic/exercise1_2p.cc b/exercises/exercise-basic/exercise1_2p.cc index 558f2d0f3373ed23df1fefbb0af5c296a698484a..fbefdd1eae0db5ea4225dd120be224f7cf86f615 100644 --- a/exercises/exercise-basic/exercise1_2p.cc +++ b/exercises/exercise-basic/exercise1_2p.cc @@ -101,8 +101,6 @@ int main(int argc, char** argv) try gridVariables->init(x, xOld); // get some time loop parameters - // getParam<TYPE>("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME - // of type TYPE given in the group GROUPNAME from the input file using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); const auto tEnd = getParam<Scalar>("TimeLoop.TEnd"); const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize"); diff --git a/exercises/exercise-basic/exercise1_2p2c.cc b/exercises/exercise-basic/exercise1_2p2c.cc index c2b46ea15fcab30a078f85acf0f8d07b122b8209..f24009436f37aa1199b4cddacefa4189bdbb12b8 100644 --- a/exercises/exercise-basic/exercise1_2p2c.cc +++ b/exercises/exercise-basic/exercise1_2p2c.cc @@ -101,8 +101,6 @@ int main(int argc, char** argv) try gridVariables->init(x, xOld); // get some time loop parameters - // getParam<TYPE>("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME - // of type TYPE given in the group GROUPNAME from the input file using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); const auto tEnd = getParam<Scalar>("TimeLoop.TEnd"); const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize"); diff --git a/exercises/exercise-basic/injection2p2cproblem.hh b/exercises/exercise-basic/injection2p2cproblem.hh index 26e111092c6ff2d19ed587c3c2609a6a40389eb8..12535cbe8f06d2247e79993414171414740f7151 100644 --- a/exercises/exercise-basic/injection2p2cproblem.hh +++ b/exercises/exercise-basic/injection2p2cproblem.hh @@ -118,10 +118,6 @@ public: aquiferDepth_ = getParam<Scalar>("Problem.AquiferDepth"); // the duration of the injection, units: second injectionDuration_ = getParam<Scalar>("Problem.InjectionDuration"); - - // TODO: dumux-course-task - // Get the specific inflow of 1e-4 kg/(s m^2) from the input file (totalAreaSpecificInflow_) here as it is done for the injectionDuration_. - } /*! diff --git a/exercises/exercise-basic/injection2pspatialparams.hh b/exercises/exercise-basic/injection2pspatialparams.hh index fac5a1da9896f747dc94b9b9787383976c063f86..fa328bc1a82ecded90d95e7d67419c924f8a71ae 100644 --- a/exercises/exercise-basic/injection2pspatialparams.hh +++ b/exercises/exercise-basic/injection2pspatialparams.hh @@ -126,7 +126,7 @@ public: * * \return the material parameters object */ - const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const + const MaterialLawParams& materialLawParamsAtPos(const GlobalPosition& globalPos) const { if (isInAquitard_(globalPos)) return aquitardMaterialParams_; diff --git a/exercises/solution/ex1/exercise1.input b/exercises/solution/ex1/exercise1.input index 545a170fb594b33f1a0600be18d50495c3953ca0..ada32b39acafe33819dfff1518deb878b2398790 100644 --- a/exercises/solution/ex1/exercise1.input +++ b/exercises/solution/ex1/exercise1.input @@ -12,7 +12,6 @@ Name = injection OnlyPlotMaterialLaws = true AquiferDepth = 2700.0 # m InjectionDuration = 2.628e6 # in seconds, i.e. one month -TotalAreaSpecificInflow = -1e-4 # kg/(s*m^2) [SpatialParams] PermeabilityAquitard = 1e-15 # m^2 diff --git a/exercises/solution/ex1/exercise1_2p2c.cc b/exercises/solution/ex1/exercise1_2p2c.cc deleted file mode 100644 index 55496aad06bae940e473fa8ad013a27d23be5444..0000000000000000000000000000000000000000 --- a/exercises/solution/ex1/exercise1_2p2c.cc +++ /dev/null @@ -1,198 +0,0 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * \brief The main file for the 2p2c porousmediumflow problem in exercise1 - */ -#include <config.h> - -#include <ctime> -#include <iostream> - -#include <dune/common/parallel/mpihelper.hh> -#include <dune/common/timer.hh> -#include <dune/grid/io/file/dgfparser/dgfexception.hh> -#include <dune/grid/io/file/vtk.hh> - -#include <dumux/common/properties.hh> -#include <dumux/common/parameters.hh> -#include <dumux/common/valgrind.hh> -#include <dumux/common/dumuxmessage.hh> - -#include <dumux/linear/amgbackend.hh> -#include <dumux/nonlinear/privarswitchnewtonsolver.hh> - -#include <dumux/assembly/fvassembler.hh> -#include <dumux/assembly/diffmethod.hh> - -#include <dumux/discretization/methods.hh> - -#include <dumux/io/vtkoutputmodule.hh> -#include <dumux/io/grid/gridmanager.hh> - -#include "injection2p2cproblem.hh" - -//////////////////////// -// the main function -//////////////////////// -int main(int argc, char** argv) try -{ - using namespace Dumux; - - // define the type tag for this problem - using TypeTag = TTAG(Injection2p2cCCTypeTag); - - // initialize MPI, finalize is done automatically on exit - const auto& mpiHelper = Dune::MPIHelper::instance(argc, argv); - - // print dumux start message - if (mpiHelper.rank() == 0) - DumuxMessage::print(/*firstCall=*/true); - - // parse command line arguments and input file - Parameters::init(argc, argv); - - // try to create a grid (from the given grid file or the input file) - GridManager<typename GET_PROP_TYPE(TypeTag, Grid)> gridManager; - gridManager.init(); - - //////////////////////////////////////////////////////////// - // run instationary non-linear problem on this grid - //////////////////////////////////////////////////////////// - - // we compute on the leaf grid view - const auto& leafGridView = gridManager.grid().leafGridView(); - - // create the finite volume grid geometry - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - auto fvGridGeometry = std::make_shared<FVGridGeometry>(leafGridView); - fvGridGeometry->update(); - - // the problem (initial and boundary conditions) - using Problem = typename GET_PROP_TYPE(TypeTag, Problem); - auto problem = std::make_shared<Problem>(fvGridGeometry); - - // the solution vector - using SolutionVector = typename GET_PROP_TYPE(TypeTag, SolutionVector); - SolutionVector x(fvGridGeometry->numDofs()); - problem->applyInitialSolution(x); - auto xOld = x; - - // the grid variables - using GridVariables = typename GET_PROP_TYPE(TypeTag, GridVariables); - auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry); - gridVariables->init(x, xOld); - - // get some time loop parameters - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - const auto tEnd = getParam<Scalar>("TimeLoop.TEnd"); - const auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize"); - auto dt = getParam<Scalar>("TimeLoop.DtInitial"); - - // intialize the vtk output module - using VtkOutputFields = typename GET_PROP_TYPE(TypeTag, VtkOutputFields); - VtkOutputModule<TypeTag> vtkWriter(*problem, *fvGridGeometry, *gridVariables, x, problem->name()); - VtkOutputFields::init(vtkWriter); //! Add model specific output fields - - // instantiate time loop - auto timeLoop = std::make_shared<TimeLoop<Scalar>>(0.0, dt, tEnd); - timeLoop->setMaxTimeStepSize(maxDt); - - // the assembler with time loop for instationary problem - using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>; - auto assembler = std::make_shared<Assembler>(problem, fvGridGeometry, gridVariables, timeLoop); - - // the linear solver - using LinearSolver = AMGBackend<TypeTag>; - auto linearSolver = std::make_shared<LinearSolver>(leafGridView, fvGridGeometry->dofMapper()); - - // the non-linear solver - using PrimaryVariableSwitch = typename GET_PROP_TYPE(TypeTag, PrimaryVariableSwitch); - using NewtonSolver = Dumux::PriVarSwitchNewtonSolver<Assembler, LinearSolver, PrimaryVariableSwitch>; - NewtonSolver nonLinearSolver(assembler, linearSolver); - - // time loop - timeLoop->start(); - while (!timeLoop->finished()) - { - // set previous solution for storage evaluations - assembler->setPreviousSolution(xOld); - - //set time in problem (is used in time-dependent Neumann boundary condition) - problem->setTime(timeLoop->time()+timeLoop->timeStepSize()); - - // solve the non-linear system with time step control - nonLinearSolver.solve(x, *timeLoop); - - // make the new solution the old solution - xOld = x; - gridVariables->advanceTimeStep(); - - // advance to the time loop to the next step - timeLoop->advanceTimeStep(); - - // report statistics of this time step - timeLoop->reportTimeStep(); - - // set new dt as suggested by the newton solver - timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())); - - // output to vtk - vtkWriter.write(timeLoop->time()); - } - - timeLoop->finalize(leafGridView.comm()); - - //////////////////////////////////////////////////////////// - // finalize, print dumux message to say goodbye - //////////////////////////////////////////////////////////// - - // print dumux end message - if (mpiHelper.rank() == 0) - { - Parameters::print(); - DumuxMessage::print(/*firstCall=*/false); - } - - return 0; -} // end main -catch (Dumux::ParameterException &e) -{ - std::cerr << std::endl << e << " ---> Abort!" << std::endl; - return 1; -} -catch (Dune::DGFException & e) -{ - std::cerr << "DGF exception thrown (" << e << - "). Most likely, the DGF file name is wrong " - "or the DGF file is corrupted, " - "e.g. missing hash at end of file or wrong number (dimensions) of entries." - << " ---> Abort!" << std::endl; - return 2; -} -catch (Dune::Exception &e) -{ - std::cerr << "Dune reported error: " << e << " ---> Abort!" << std::endl; - return 3; -} -catch (...) -{ - std::cerr << "Unknown exception thrown! ---> Abort!" << std::endl; - return 4; -} diff --git a/exercises/solution/ex1/injection2p2cproblem.hh b/exercises/solution/ex1/injection2p2cproblem.hh deleted file mode 100644 index d33e5a46bb25ea3bffec3f54a804af1947d5f7d9..0000000000000000000000000000000000000000 --- a/exercises/solution/ex1/injection2p2cproblem.hh +++ /dev/null @@ -1,271 +0,0 @@ -// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- -// vi: set et ts=4 sw=4 sts=4: -/***************************************************************************** - * See the file COPYING for full copying permissions. * - * * - * This program is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - *****************************************************************************/ -/*! - * \file - * - * \brief The two-phase porousmediumflow problem for exercise 1 - */ -#ifndef DUMUX_EX1_INJECTION_2P2C_PROBLEM_HH -#define DUMUX_EX1_INJECTION_2P2C_PROBLEM_HH - -#include <dumux/discretization/cellcentered/tpfa/properties.hh> -#include <dumux/porousmediumflow/2p2c/model.hh> -#include <dumux/porousmediumflow/problem.hh> -#include <dumux/material/fluidsystems/h2on2.hh> - -#include "injection2pspatialparams.hh" - -namespace Dumux { - -// forward declare problem -template <class TypeTag> -class Injection2p2cProblem; - -namespace Properties { -NEW_TYPE_TAG(Injection2p2cTypeTag, INHERITS_FROM(TwoPTwoC)); -NEW_TYPE_TAG(Injection2p2cCCTypeTag, INHERITS_FROM(CCTpfaModel, Injection2p2cTypeTag)); - -// Set the grid type -SET_TYPE_PROP(Injection2p2cTypeTag, Grid, Dune::YaspGrid<2>); - -// Set the problem property -SET_TYPE_PROP(Injection2p2cTypeTag, Problem, Injection2p2cProblem<TypeTag>); - -// Set the spatial parameters -SET_TYPE_PROP(Injection2p2cTypeTag, SpatialParams, - InjectionSpatialParams<typename GET_PROP_TYPE(TypeTag, FVGridGeometry), - typename GET_PROP_TYPE(TypeTag, Scalar)>); - -// Set fluid configuration -SET_TYPE_PROP(Injection2p2cTypeTag, FluidSystem, FluidSystems::H2ON2<typename GET_PROP_TYPE(TypeTag, Scalar), /*useComplexRelations=*/ false>); - -// Define whether mole(true) or mass (false) fractions are used -SET_BOOL_PROP(Injection2p2cTypeTag, UseMoles, true); -} // end namespace Properties - -/*! - * \ingroup TwoPTwoCModel - * \ingroup ImplicitTestProblems - * \brief Gas injection problem where a gas (here nitrogen) is injected into a fully - * water saturated medium. During buoyancy driven upward migration the gas - * passes a high temperature area. - * - * The domain is sized 60 m times 40 m. - * - * For the mass conservation equation neumann boundary conditions are used on - * the top, on the bottom and on the right of the domain, while dirichlet conditions - * apply on the left boundary. - * - * Gas is injected at the right boundary from 7 m to 15 m at a rate of - * 0.001 kg/(s m), the remaining neumann boundaries are no-flow - * boundaries. - * - * At the dirichlet boundaries a hydrostatic pressure and a gas saturation of zero a - * - * This problem uses the \ref TwoPModel model. - */ -template<class TypeTag> -class Injection2p2cProblem : public PorousMediumFlowProblem<TypeTag> -{ - using ParentType = PorousMediumFlowProblem<TypeTag>; - using GridView = typename GET_PROP_TYPE(TypeTag, GridView); - using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar); - using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices; - using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables); - using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes); - using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); - using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; - using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); - - enum { dimWorld = GridView::dimensionworld }; - using Element = typename GridView::template Codim<0>::Entity; - using GlobalPosition = typename Element::Geometry::GlobalCoordinate; - -public: - Injection2p2cProblem(std::shared_ptr<const FVGridGeometry> fvGridGeometry) - : ParentType(fvGridGeometry) - { - // initialize the tables of the fluid system - FluidSystem::init(/*tempMin=*/273.15, - /*tempMax=*/423.15, - /*numTemp=*/50, - /*pMin=*/0.0, - /*pMax=*/30e6, - /*numP=*/300); - - // name of the problem and output file - // getParam<TYPE>("GROUPNAME.PARAMNAME") reads and sets parameter PARAMNAME - // of type TYPE given in the group GROUPNAME from the input file - name_ = getParam<std::string>("Problem.Name"); - // depth of the aquifer, units: m - aquiferDepth_ = getParam<Scalar>("Problem.AquiferDepth"); - // the duration of the injection, units: second - injectionDuration_ = getParam<Scalar>("Problem.InjectionDuration"); - totalAreaSpecificInflow_ = getParam<Scalar>("Problem.TotalAreaSpecificInflow"); - } - - /*! - * \name Problem parameters - */ - // \{ - - /*! - * \brief Returns the problem name - * - * This is used as a prefix for files generated by the simulation. - */ - std::string name() const - { return name_+"-2p2c"; } - - /*! - * \brief Returns the temperature \f$ K \f$ - */ - Scalar temperature() const - { - return 273.15 + 30; // [K] - } - - // \} - - /*! - * \name Boundary conditions - */ - // \{ - - /*! - * \brief Specifies which kind of boundary condition should be - * used for which equation on a given boundary segment. - * - * \param bcTypes The boundary types for the conservation equations - * \param globalPos The position for which the bc type should be evaluated - */ - BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const - { - BoundaryTypes bcTypes; - if (globalPos[0] < eps_) - bcTypes.setAllDirichlet(); - else - bcTypes.setAllNeumann(); - - return bcTypes; - } - - /*! - * \brief Evaluates the boundary conditions for a Dirichlet - * boundary segment - * - * \param globalPos The global position - */ - PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const - { - return initialAtPos(globalPos); - } - - /*! - * \brief Evaluate the boundary conditions for a neumann - * boundary segment. - * - * \param values Stores the Neumann values for the conservation equations in - * \f$ [ \textnormal{unit of conserved quantity} / (m^(dim-1) \cdot s )] \f$ - * \param globalPos The position of the integration point of the boundary segment. - * - * For this method, the \a values parameter stores the mass flux - * in normal direction of each phase. Negative values mean influx. - */ - PrimaryVariables neumannAtPos(const GlobalPosition &globalPos) const - { - // initialize values to zero, i.e. no-flow Neumann boundary conditions - PrimaryVariables values(0.0); - - // if we are inside the injection zone set inflow Neumann boundary conditions - if (time_ < injectionDuration_ - && globalPos[1] < 15 + eps_ && globalPos[1] > 7 - eps_ && globalPos[0] > 0.9*this->fvGridGeometry().bBoxMax()[0]) - { - // TODO: dumux-course-task - //instead of setting -1e-4 here directly use totalAreaSpecificInflow_ in the computation - - // inject nitrogen. negative values mean injection - // convert from units kg/(s*m^2) to mole/(s*m^2) - values[Indices::conti0EqIdx + FluidSystem::N2Idx] = totalAreaSpecificInflow_/FluidSystem::molarMass(FluidSystem::N2Idx); - values[Indices::conti0EqIdx + FluidSystem::H2OIdx] = 0.0; - } - - return values; - } - - // \} - - - /*! - * \name Volume terms - */ - // \{ - - /*! - * \brief Evaluate the initial value for a control volume. - * - * \param globalPos The position for which the initial condition should be evaluated - * - * For this method, the \a values parameter stores primary - * variables. - */ - PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const - { - PrimaryVariables values(0.0); - values.setState(Indices::firstPhaseOnly); - // get the water density at atmospheric conditions - const Scalar densityW = FluidSystem::H2O::liquidDensity(temperature(), 1.0e5); - - // assume an intially hydrostatic liquid pressure profile - // note: we subtract rho_w*g*h because g is defined negative - const Scalar pw = 1.0e5 - densityW*this->gravity()[dimWorld-1]*(aquiferDepth_ - globalPos[dimWorld-1]); - - // initially we have some nitrogen dissolved - // saturation mole fraction would be - // moleFracLiquidN2 = (pw + pc + p_vap^sat)/henry; - const Scalar moleFracLiquidN2 = pw*0.95/BinaryCoeff::H2O_N2::henry(temperature()); - - // note that because we start with a single phase system the primary variables - // are pl and x^w_N2. This will switch as soon after we start injecting to a two - // phase system so the primary variables will be pl and Sn (non-wetting saturation). - values[Indices::pressureIdx] = pw; - values[Indices::switchIdx] = moleFracLiquidN2; - - return values; - } - - // \} - - //! set the time for the time dependent boundary conditions (called from main) - void setTime(Scalar time) - { time_ = time; } - -private: - static constexpr Scalar eps_ = 1e-6; - std::string name_; //! Problem name - Scalar aquiferDepth_; //! Depth of the aquifer in m - Scalar injectionDuration_; //! Duration of the injection in seconds - Scalar time_; - Scalar totalAreaSpecificInflow_; - -}; - -} //end namespace Dumux - -#endif diff --git a/exercises/solution/ex1/injection2pniproblem.hh b/exercises/solution/ex1/injection2pniproblem.hh index 70135414a985fcfa0bbf4efdd75ccf0e9306763e..6cc7132b280e6408639f2eeffd114e39a2bd624d 100644 --- a/exercises/solution/ex1/injection2pniproblem.hh +++ b/exercises/solution/ex1/injection2pniproblem.hh @@ -90,6 +90,7 @@ class InjectionProblem2PNI : public PorousMediumFlowProblem<TypeTag> using FVGridGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry); using FVElementGeometry = typename GET_PROP_TYPE(TypeTag, FVGridGeometry)::LocalView; using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem); + using NumEqVector = typename GET_PROP_TYPE(TypeTag, NumEqVector); enum { dimWorld = GridView::dimensionworld }; using Element = typename GridView::template Codim<0>::Entity; @@ -204,6 +205,22 @@ public: */ // \{ + /*! + * \brief Evaluate the source term for all phases within a given + * sub-control-volume. + * + * For this method, the \a priVars parameter stores the rate mass + * of a component is generated or annihilate per volume + * unit. Positive values mean that mass is created, negative ones + * mean that it vanishes. + * + * The units must be according to either using mole or mass fractions. (mole/(m^3*s) or kg/(m^3*s)) + */ + NumEqVector sourceAtPos(const GlobalPosition &globalPos) const + { + return NumEqVector(0.0); + } + /*! * \brief Evaluate the initial value for a control volume. * diff --git a/exercises/solution/ex1/injection2pspatialparams.hh b/exercises/solution/ex1/injection2pspatialparams.hh index 979f14ce9782f08b1a08010b0f8053506265ebf3..fa328bc1a82ecded90d95e7d67419c924f8a71ae 100644 --- a/exercises/solution/ex1/injection2pspatialparams.hh +++ b/exercises/solution/ex1/injection2pspatialparams.hh @@ -49,6 +49,8 @@ class InjectionSpatialParams using ThisType = InjectionSpatialParams<FVGridGeometry, Scalar>; using ParentType = FVSpatialParams<FVGridGeometry, Scalar, ThisType>; using GridView = typename FVGridGeometry::GridView; + + // get the dimensions of the simulation domain from GridView static const int dimWorld = GridView::dimensionworld; using Element = typename GridView::template Codim<0>::Entity; using GlobalPosition = typename Element::Geometry::GlobalCoordinate; @@ -65,7 +67,7 @@ public: * * \param fvGridGeometry The finite volume grid geometry */ - InjectionSpatialParams(std::shared_ptr<const FVGridGeometry> fvGridGeometry) + InjectionSpatialParams(std::shared_ptr<const FVGridGeometry>& fvGridGeometry) : ParentType(fvGridGeometry) { aquiferHeightFromBottom_ = 30.0; @@ -97,8 +99,8 @@ public: * \param globalPos The global position */ PermeabilityType permeabilityAtPos(const GlobalPosition& globalPos) const - { + // here, either aquitard or aquifer permeability are returned, depending on the global position if (isInAquitard_(globalPos)) return aquitardK_; return aquiferK_; @@ -111,6 +113,7 @@ public: */ Scalar porosityAtPos(const GlobalPosition& globalPos) const { + // here, either aquitard or aquifer porosity are returned, depending on the global position if (isInAquitard_(globalPos)) return aquitardPorosity_; return aquiferPorosity_; @@ -144,8 +147,12 @@ private: static constexpr Scalar eps_ = 1e-6; + // provides a convenient way distinguishing whether a given location is inside the aquitard bool isInAquitard_(const GlobalPosition &globalPos) const - { return globalPos[dimWorld-1] > aquiferHeightFromBottom_ + eps_; } + { + // globalPos[dimWorld-1] is the y direction for 2D grids or the z direction for 3D grids + return globalPos[dimWorld-1] > aquiferHeightFromBottom_ + eps_; + } Scalar aquitardK_; Scalar aquiferK_;