// -*- 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 . *
*****************************************************************************/
/*!
* \file
* \ingroup MultiDomain
* \ingroup MultiDomainFacet
* \ingroup TwoPTests
* \brief The sub-problem for the fracture domain in the exercise on two-phase flow in fractured porous media.
*/
#ifndef DUMUX_COURSE_FRACTURESEXERCISE_FRACTURE_PROBLEM_HH
#define DUMUX_COURSE_FRACTURESEXERCISE_FRACTURE_PROBLEM_HH
// include the base problem and properties we inherit from
#include
#include
namespace Dumux {
/*!
* \ingroup MultiDomain
* \ingroup MultiDomainFacet
* \ingroup TwoPTests
* \brief The sub-problem for the fracture domain in the exercise on two-phase flow in fractured porous media.
*/
template
class FractureSubProblem : public PorousMediumFlowProblem
{
using ParentType = PorousMediumFlowProblem;
using BoundaryTypes = GetPropType;
using CouplingManager = GetPropType;
using NumEqVector = GetPropType;
using GridVariables = GetPropType;
using ElementVolumeVariables = typename GridVariables::GridVolumeVariables::LocalView;
using PrimaryVariables = typename GridVariables::PrimaryVariables;
using Scalar = typename GridVariables::Scalar;
using FVGridGeometry = typename GridVariables::GridGeometry;
using FVElementGeometry = typename FVGridGeometry::LocalView;
using SubControlVolume = typename FVGridGeometry::SubControlVolume;
using GridView = typename FVGridGeometry::GridView;
using Element = typename GridView::template Codim<0>::Entity;
using GlobalPosition = typename Element::Geometry::GlobalCoordinate;
// some indices for convenience
using Indices = typename GetPropType::Indices;
enum
{
pressureIdx = Indices::pressureIdx,
saturationIdx = Indices::saturationIdx
};
public:
//! The constructor
FractureSubProblem(std::shared_ptr fvGridGeometry,
std::shared_ptr spatialParams,
const std::string& paramGroup)
: ParentType(fvGridGeometry, spatialParams, paramGroup)
, aperture_(getParamFromGroup(paramGroup, "SpatialParams.Aperture"))
, isExercisePartA_(getParamFromGroup(paramGroup, "Problem.IsExercisePartA"))
, isExercisePartB_(getParamFromGroup(paramGroup, "Problem.IsExercisePartB"))
, isExercisePartC_(getParamFromGroup(paramGroup, "Problem.IsExercisePartC"))
{
// initialize the fluid system, i.e. the tabulation
// of water properties. Use the default p/T ranges.
using FluidSystem = GetPropType;
FluidSystem::init();
}
//! Specifies the type of boundary condition at a given position
BoundaryTypes boundaryTypesAtPos(const GlobalPosition& globalPos) const
{
BoundaryTypes values;
// We only use no-flow boundary conditions for all immersed fractures
// in the domain (fracture tips that do not touch the domain boundary)
// Otherwise, we would lose mass leaving across the fracture tips.
values.setAllNeumann();
// However, there is one fracture reaching the top boundary. For that
// fracture tip we set Dirichlet Bcs - only in the unmodified state of
// the exercise though. In parts a, b & c we consider Neumann here.
if (!isExercisePartA_ && !isExercisePartB_ && !isExercisePartC_)
if (globalPos[1] > this->gridGeometry().bBoxMax()[1] - 1e-6)
values.setAllDirichlet();
return values;
}
//! Evaluate the source term in a sub-control volume of an element
NumEqVector source(const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolume& scv) const
{
// evaluate sources from bulk domain using the function in the coupling manager
auto source = couplingManagerPtr_->evalSourcesFromBulk(element, fvGeometry, elemVolVars, scv);
// these sources are in kg/s, divide by volume and extrusion to have it in kg/s/m³
source /= scv.volume()*elemVolVars[scv].extrusionFactor();
return source;
}
//! Set the aperture as extrusion factor.
Scalar extrusionFactorAtPos(const GlobalPosition& globalPos) const
{
// We treat the fractures as lower-dimensional in the grid,
// but we have to give it the aperture as extrusion factor
// such that the dimensions are correct in the end.
return aperture_;
}
//! evaluates the Dirichlet boundary condition for a given position
PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const
{ return initialAtPos(globalPos); }
//! evaluate the initial conditions
PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
{
// For the grid used here, the height of the domain is equal
// to the maximum y-coordinate
const auto domainHeight = this->gridGeometry().bBoxMax()[1];
// we assume a constant water density of 1000 for initial conditions!
const auto& g = this->spatialParams().gravity(globalPos);
PrimaryVariables values;
Scalar densityW = 1000.0;
values[pressureIdx] = 1e5 - (domainHeight - globalPos[1])*densityW*g[1];
values[saturationIdx] = 0.0;
return values;
}
//! returns the temperature in \f$\mathrm{[K]}\f$ in the domain
Scalar temperature() const
{ return 283.15; /*10°*/ }
//! sets the pointer to the coupling manager.
void setCouplingManager(std::shared_ptr cm)
{ couplingManagerPtr_ = cm; }
//! returns reference to the coupling manager.
const CouplingManager& couplingManager() const
{ return *couplingManagerPtr_; }
private:
std::shared_ptr couplingManagerPtr_;
Scalar aperture_;
bool isExercisePartA_;
bool isExercisePartB_;
bool isExercisePartC_;
};
} // end namespace Dumux
#endif