Newer
Older
// -*- 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 3 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/>. *
*****************************************************************************/

Andreas Lauser
committed
/*!
* \file

Andreas Lauser
committed
* \brief A water infiltration problem with a low-permeability lens
* embedded into a high-permeability domain which uses the

Andreas Lauser
committed
* Richards box model.
*/
#ifndef DUMUX_RICHARDS_LENSPROBLEM_HH
#define DUMUX_RICHARDS_LENSPROBLEM_HH
#include <dumux/common/properties.hh>
#include <dumux/common/parameters.hh>
#include <dumux/common/boundarytypes.hh>
#include <dumux/common/numeqvector.hh>
namespace Dumux {
* \ingroup RichardsTests

Andreas Lauser
committed
*
* \brief A water infiltration problem with a low-permeability lens
* embedded into a high-permeability domain which uses the

Andreas Lauser
committed
* The domain is box shaped. Left and right boundaries are Dirichlet

Andreas Lauser
committed
* boundaries with fixed water pressure (fixed Saturation \f$S_w = 0\f$),

Andreas Lauser
committed
* bottom boundary is closed (Neumann 0 boundary), the top boundary
* (Neumann 0 boundary) is also closed except for infiltration
* section, where water is infiltrating into an initially unsaturated
* porous medium. This problem is very similar to the LensProblem
* which uses the TwoPBoxModel, with the main difference being that
* the domain is initially fully saturated by gas instead of water and

Andreas Lauser
committed
* water instead of a %DNAPL infiltrates from the top.
*
* To run the simulation execute the following line in shell:
* <tt>./test_boxrichards -parameterFile test_boxrichards.input -TimeManager.TEnd 10000000</tt>
* <tt>./test_ccrichards -parameterFile test_ccrichards.input -TimeManager.TEnd 10000000</tt>

Andreas Lauser
committed
* where the initial time step is 100 seconds, and the end of the
* simulation time is 10,000,000 seconds (115.7 days)

Andreas Lauser
committed
template <class TypeTag>
class RichardsLensProblem : public PorousMediumFlowProblem<TypeTag>

Simon Emmert
committed
using GridView = typename GetPropType<TypeTag, Properties::GridGeometry>::GridView;
using PrimaryVariables = GetPropType<TypeTag, Properties::PrimaryVariables>;
using BoundaryTypes = Dumux::BoundaryTypes<GetPropType<TypeTag, Properties::ModelTraits>::numEq()>;
using NumEqVector = Dumux::NumEqVector<PrimaryVariables>;
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using Indices = typename GetPropType<TypeTag, Properties::ModelTraits>::Indices;
using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
pressureIdx = Indices::pressureIdx,
conti0EqIdx = Indices::conti0EqIdx,
// world dimension
dimWorld = GridView::dimensionworld
using Element = typename GridView::template Codim<0>::Entity;
using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
RichardsLensProblem(std::shared_ptr<const GridGeometry> gridGeometry)
: ParentType(gridGeometry)
name_ = getParam<std::string>("Problem.Name");
/*!
* \name Problem parameters
*/
// \{
/*!

Andreas Lauser
committed
* \brief The problem name
*
* This is used as a prefix for files generated by the simulation.
*/
const std::string& name() const

Bernd Flemisch
committed
{ return name_; }

Andreas Lauser
committed
* \brief Returns the temperature [K] within a finite volume
*
* This problem assumes a temperature of 10 degrees Celsius.
*/

Andreas Lauser
committed
Scalar temperature() const
{ return 273.15 + 10; }; // -> 10°C
* \brief Returns the reference pressure [Pa] of the nonwetting

Andreas Lauser
committed
* fluid phase within a finite volume
*
* This problem assumes a constant reference pressure of 1 bar.
Scalar nonwettingReferencePressure() const
{ return 1.0e5; };
/*!
* \name Boundary conditions
*/
// \{
/*!
* \brief Specifies which kind of boundary condition should be
* used for which equation on a given boundary segment.
* \param globalPos The position for which the boundary type is set
BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
BoundaryTypes bcTypes;
if (onLeftBoundary_(globalPos) || onRightBoundary_(globalPos))
bcTypes.setAllDirichlet();
bcTypes.setAllNeumann();
return bcTypes;
* \brief Evaluates the boundary conditions for a Dirichlet boundary segment.
* \param globalPos The position for which the Dirichlet value is set
* For this method, the \a values parameter stores primary variables.
*/
PrimaryVariables dirichletAtPos(const GlobalPosition &globalPos) const
return initial_(globalPos);
* \brief Evaluates the boundary conditions for a Neumann boundary segment.
*
* For this method, the \a values parameter stores the mass flux
* in normal direction of each phase. Negative values mean influx.

Andreas Lauser
committed
*
* \param globalPos The position for which the Neumann value is set
NumEqVector neumannAtPos(const GlobalPosition &globalPos) const
NumEqVector values(0.0);
if (onInlet_(globalPos))
values[conti0EqIdx] = -0.04; // kg/(m*s)
return values;
}
/*!
* \name Volume terms
*/
// \{
/*!
* \brief Evaluates the initial values for a control volume.
*
* For this method, the \a values parameter stores primary
* variables.

Andreas Lauser
committed
*
* \param globalPos The position for which the boundary type is set
PrimaryVariables initialAtPos(const GlobalPosition &globalPos) const
{ return initial_(globalPos); };
PrimaryVariables initial_(const GlobalPosition &globalPos) const
PrimaryVariables values(0.0);
const Scalar sw = 0.0;
const Scalar pc = this->spatialParams().fluidMatrixInteractionAtPos(globalPos).pc(sw);
values[pressureIdx] = nonwettingReferencePressure() - pc;
return values;
bool onLeftBoundary_(const GlobalPosition &globalPos) const
{
return globalPos[0] < this->gridGeometry().bBoxMin()[0] + eps_;
}
bool onRightBoundary_(const GlobalPosition &globalPos) const
{
return globalPos[0] > this->gridGeometry().bBoxMax()[0] - eps_;
}
bool onLowerBoundary_(const GlobalPosition &globalPos) const
{
return globalPos[1] < this->gridGeometry().bBoxMin()[1] + eps_;
}
bool onUpperBoundary_(const GlobalPosition &globalPos) const
{
return globalPos[1] > this->gridGeometry().bBoxMax()[1] - eps_;
}
bool onInlet_(const GlobalPosition &globalPos) const
{
Scalar width = this->gridGeometry().bBoxMax()[0] - this->gridGeometry().bBoxMin()[0];
Scalar lambda = (this->gridGeometry().bBoxMax()[0] - globalPos[0])/width;
return onUpperBoundary_(globalPos) && 0.5 < lambda + eps_ && lambda < 2.0/3.0 + eps_;
static constexpr Scalar eps_ = 1.5e-7;
GlobalPosition lensLowerLeft_;
GlobalPosition lensUpperRight_;
std::string name_;
} // end namespace Dumux