Commit af65683c authored by Dennis Gläser's avatar Dennis Gläser
Browse files

[examples][tracer] generate new readme from changes

parent 7f091910
...@@ -8,76 +8,77 @@ This example contains a contaminant transported by a base groundwater flow in a ...@@ -8,76 +8,77 @@ This example contains a contaminant transported by a base groundwater flow in a
![](./img/setup.png) ![](./img/setup.png)
## Model description ## Model description
Two different models are applied to simulate the system: In a first step, the groundwater velocity is evaluated under stationary conditions. Therefore the single phase model is applied. Two different models are applied to simulate the system: In a first step, the groundwater velocity is evaluated under stationary conditions using the single phase model.
In a second step, the contaminant gets transported based on the groundwater velocity field. It is assumed, that the dissolved contaminant does not affect density and viscosity of the groundwater and thus, it is handled as a tracer by the tracer model. The tracer model is then solved instationarily. In a second step, the contaminant is transported with the groundwater velocity field. It is assumed, that the dissolved contaminant does not affect density and viscosity of the groundwater, and thus, it is handled as a tracer by the tracer model. The tracer model is then solved instationarily.
### 1p Model ### 1p Model
The single phase model uses Darcy's law as the equation for the momentum conservation: The single phase model uses Darcy's law as the equation for the momentum conservation:
```math ```math
\textbf v = - \frac{\textbf K}{\mu} \left(\textbf{grad}\, p - \varrho {\textbf g} \right) \textbf v = - \frac{\textbf K}{\mu} \left(\textbf{grad}\, p - \varrho {\textbf g} \right),
``` ```
With the darcy velocity $` \textbf v `$, the permeability $` \textbf K`$, the dynamic viscosity $` \mu`$, the pressure $`p`$, the density $`\rho`$ and the gravity $`\textbf g`$. with the darcy velocity $` \textbf v `$, the permeability $` \textbf K`$, the dynamic viscosity $` \mu`$, the pressure $`p`$, the density $`\rho`$ and the gravity $`\textbf g`$.
Darcy's law is inserted into the continuity equation: Darcy's law is inserted into the mass balance equation:
```math ```math
\phi \frac{\partial \varrho}{\partial t} + \text{div} \textbf v = 0 \phi \frac{\partial \varrho}{\partial t} + \text{div} \textbf v = 0
``` ```
with porosity $`\phi`$. where $`\phi`$ is the porosity.
The equation is discretized using a cell-centered finite volume scheme as spatial discretization for the pressure as primary variable. For details on the discretization scheme, have a look at the dumux [handbook](https://dumux.org/handbook). The equation is discretized using a cell-centered finite volume scheme as spatial discretization for the pressure as primary variable. For details on the discretization scheme, have a look at the dumux [handbook](https://dumux.org/handbook).
### Tracer Model ### Tracer Model
The transport of the contaminant component $`\kappa`$ is based on the previously evaluated velocity field $`\textbf v`$ with the help the following mass balance equation: The transport of the contaminant component $`\kappa`$ is based on the previously evaluated velocity field $`\textbf v`$ with the help of the following mass balance equation:
```math ```math
\phi \frac{ \partial \varrho X^\kappa}{\partial t} - \text{div} \left\lbrace \varrho X^\kappa {\textbf v} + \varrho D^\kappa_\text{pm} \textbf{grad} X^\kappa \right\rbrace = 0 \phi \frac{ \partial \varrho X^\kappa}{\partial t} - \text{div} \left\lbrace \varrho X^\kappa {\textbf v} + \varrho D^\kappa_\text{pm} \textbf{grad} X^\kappa \right\rbrace = 0,
``` ```
With the porosity $`\phi`$, the mass fraction of the contaminant component $`\kappa`$: $`X^\kappa`$, the porous medium diffusivity $` D^\kappa_\text{pm} `$ and the density of the fluid phase $`\varrho`$. where $`X^\kappa`$ is the mass fraction of the contaminant component $`\kappa`$ and $` D^\kappa_\text{pm} `$ is the effective diffusivity.
The porous medium diffusivity is a function of the diffusion coefficient of the component $`D^\kappa`$, the porosity $`\phi`$ and the porous medium tortuosity $`\tau`$ by the following equation: The effective diffusivity is a function of the diffusion coefficient of the component $`D^\kappa`$ and the porosity and tortuosity $`\tau`$ of the porous medium:
```math ```math
D^\kappa_\text{pm}= \phi \tau D^\kappa D^\kappa_\text{pm}= \phi \tau D^\kappa.
``` ```
The primary variable of this model is the mass fraction $`X^\kappa`$. We apply the same spatial discretization as in the single phase model and use the implicit Euler method for time discretization. For more information, have a look at the dumux handbook. The primary variable of this model is the mass fraction $`X^\kappa`$. We apply the same spatial discretization as in the single phase model and use the implicit Euler method for time discretization. For more information, have a look at the dumux [handbook](https://dumux.org/handbook).
In the following, we take a close look at the files containing the set-up: At first, boundary conditions and spatially distributed parameters are set in `problem_1p.hh` and `spatialparams_1p.hh`, respectively, for the single phase model and subsequently in `problem_tracer.hh` and `spatialparams_tracer.hh` for the tracer model. Afterwards, we show the different steps for solving the model in the source file `main.cc`. At the end, we show some simulation results. In the following, we take a close look at the files containing the set-up: The boundary conditions and spatially distributed parameters for the single phase model are set in `problem_1p.hh` and `spatialparams_1p.hh`.
For the tracer model, this is done in the files `problem_tracer.hh` and `spatialparams_tracer.hh`, respectively. Afterwards, we show the different steps for solving the model in the source file `main.cc`. Finally, some simulation results are shown.
## The file `spatialparams_1p.hh` ## The file `spatialparams_1p.hh`
In this file, we generate the random permeability field in the constructor of the `OnePTestSpatialParams` class. Thereafter, spatial properties of the porous medium such as the permeability and the porosity are defined in various functions for the 1p problem. In this file, we generate a random permeability field in the constructor of the `OnePTestSpatialParams` class.
We want to generate a random permeability field. For this, we use a random number generation of the C++ standard library. For this, we use the random number generation facilities provided by the C++ standard library.
```cpp ```cpp
#include <random> #include <random>
``` ```
In the file `properties.hh` all properties are declared. We use the properties for porous medium flow models, declared in the file `properties.hh`.
```cpp ```cpp
#include <dumux/porousmediumflow/properties.hh> #include <dumux/porousmediumflow/properties.hh>
``` ```
We include the spatial parameters for single-phase, finite volumes from which we will inherit. We include the spatial parameters class for single-phase models discretized by finite volume schemes.
The spatial parameters defined for this example will inherit from those.
```cpp ```cpp
#include <dumux/material/spatialparams/fv1p.hh> #include <dumux/material/spatialparams/fv1p.hh>
namespace Dumux { namespace Dumux {
``` ```
In the `OnePTestSpatialParams` class, we define all functions needed to describe the porous matrix, e.g. porosity and permeability for the 1p_problem. In the `OnePTestSpatialParams` class, we define all functions needed to describe the porous medium, e.g. porosity and permeability for the 1p_problem.
```cpp ```cpp
template<class GridGeometry, class Scalar> template<class GridGeometry, class Scalar>
class OnePTestSpatialParams class OnePTestSpatialParams
: public FVSpatialParamsOneP<GridGeometry, Scalar, : public FVSpatialParamsOneP<GridGeometry, Scalar,
OnePTestSpatialParams<GridGeometry, Scalar>> OnePTestSpatialParams<GridGeometry, Scalar>>
{ {
``` ```
We introduce `using` declarations that are derived from the property system, which we need in this class. We declare aliases for types that we are going to need in this class.
```cpp ```cpp
using GridView = typename GridGeometry::GridView; using GridView = typename GridGeometry::GridView;
using FVElementGeometry = typename GridGeometry::LocalView; using FVElementGeometry = typename GridGeometry::LocalView;
...@@ -90,6 +91,10 @@ We introduce `using` declarations that are derived from the property system, whi ...@@ -90,6 +91,10 @@ We introduce `using` declarations that are derived from the property system, whi
using GlobalPosition = typename SubControlVolume::GlobalPosition; using GlobalPosition = typename SubControlVolume::GlobalPosition;
public: public:
```
The spatial parameters must export the type used to define permeabilities.
Here, we are using scalar permeabilities, but tensors are also supported.
```cpp
using PermeabilityType = Scalar; using PermeabilityType = Scalar;
OnePTestSpatialParams(std::shared_ptr<const GridGeometry> gridGeometry) OnePTestSpatialParams(std::shared_ptr<const GridGeometry> gridGeometry)
: ParentType(gridGeometry), K_(gridGeometry->gridView().size(0), 0.0) : ParentType(gridGeometry), K_(gridGeometry->gridView().size(0), 0.0)
...@@ -101,12 +106,13 @@ We get the permeability of the domain and the lens from the `params.input` file. ...@@ -101,12 +106,13 @@ We get the permeability of the domain and the lens from the `params.input` file.
permeability_ = getParam<Scalar>("SpatialParams.Permeability"); permeability_ = getParam<Scalar>("SpatialParams.Permeability");
permeabilityLens_ = getParam<Scalar>("SpatialParams.PermeabilityLens"); permeabilityLens_ = getParam<Scalar>("SpatialParams.PermeabilityLens");
``` ```
Further, we get the position of the lens, which is defined by the position of the lower left and the upper right corner. Furthermore, we get the position of the lens, which is defined by the position of the lower left and the upper right corner.
```cpp ```cpp
lensLowerLeft_ = getParam<GlobalPosition>("SpatialParams.LensLowerLeft"); lensLowerLeft_ = getParam<GlobalPosition>("SpatialParams.LensLowerLeft");
lensUpperRight_ =getParam<GlobalPosition>("SpatialParams.LensUpperRight"); lensUpperRight_ =getParam<GlobalPosition>("SpatialParams.LensUpperRight");
``` ```
We generate random fields for the permeability using a lognormal distribution, with the `permeability_` as mean value and 10 % of it as standard deviation. A seperate distribution is used for the lens using `permeabilityLens_`. We generate random fields for the permeability using lognormal distributions, with `permeability_` as mean value and 10 % of it as standard deviation.
A separate distribution is used for the lens using `permeabilityLens_`. A permeability value is created for each element of the grid and is stored in the vector `K_`.
```cpp ```cpp
std::mt19937 rand(0); std::mt19937 rand(0);
std::lognormal_distribution<Scalar> K(std::log(permeability_), std::log(permeability_)*0.1); std::lognormal_distribution<Scalar> K(std::log(permeability_), std::log(permeability_)*0.1);
...@@ -120,7 +126,9 @@ We generate random fields for the permeability using a lognormal distribution, w ...@@ -120,7 +126,9 @@ We generate random fields for the permeability using a lognormal distribution, w
} }
``` ```
### Properties of the porous matrix ### Properties of the porous matrix
We define the (intrinsic) permeability $`[m^2]`$ using the generated random permeability field. In this test, we use element-wise distributed permeabilities. This function returns the permeability $`[m^2]`$ to be used within a sub-control volume (`scv`) inside the element `element`.
One can define the permeability as function of the primary variables on the element, which are given in the provided `ElementSolution`.
Here, we use element-wise distributed permeabilities that were randomly generated in the constructor (see above).
```cpp ```cpp
template<class ElementSolution> template<class ElementSolution>
const PermeabilityType& permeability(const Element& element, const PermeabilityType& permeability(const Element& element,
...@@ -131,7 +139,7 @@ We define the (intrinsic) permeability $`[m^2]`$ using the generated random perm ...@@ -131,7 +139,7 @@ We define the (intrinsic) permeability $`[m^2]`$ using the generated random perm
} }
``` ```
We set the porosity $`[-]`$ for the whole domain. We set the porosity $`[-]`$ for the whole domain to a value of $`20 \%`$.
```cpp ```cpp
Scalar porosityAtPos(const GlobalPosition &globalPos) const Scalar porosityAtPos(const GlobalPosition &globalPos) const
{ return 0.2; } { return 0.2; }
...@@ -175,7 +183,7 @@ We have a convenient definition of the position of the lens. ...@@ -175,7 +183,7 @@ We have a convenient definition of the position of the lens.
Before we enter the problem class containing initial and boundary conditions, we include necessary files and introduce properties. Before we enter the problem class containing initial and boundary conditions, we include necessary files and introduce properties.
### Include files ### Include files
The dune grid interphase is included here: We use `YaspGrid`, an implementation of the dune grid interface for structured grids:
```cpp ```cpp
#include <dune/grid/yaspgrid.hh> #include <dune/grid/yaspgrid.hh>
``` ```
...@@ -191,7 +199,7 @@ This is the porous medium problem class that this class is derived from: ...@@ -191,7 +199,7 @@ This is the porous medium problem class that this class is derived from:
```cpp ```cpp
#include <dumux/porousmediumflow/problem.hh> #include <dumux/porousmediumflow/problem.hh>
``` ```
The fluid properties are specified in the following headers: The fluid properties are specified in the following headers (we use liquid water as the fluid phase):
```cpp ```cpp
#include <dumux/material/components/simpleh2o.hh> #include <dumux/material/components/simpleh2o.hh>
#include <dumux/material/fluidsystems/1pliquid.hh> #include <dumux/material/fluidsystems/1pliquid.hh>
...@@ -250,12 +258,12 @@ Finally, we set the spatial parameters: ...@@ -250,12 +258,12 @@ Finally, we set the spatial parameters:
using type = OnePTestSpatialParams<GridGeometry, Scalar>; using type = OnePTestSpatialParams<GridGeometry, Scalar>;
}; };
``` ```
The local residual contains analytic derivative methods for incompressible flow: We use the local residual that contains analytic derivative methods for incompressible flow:
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
struct LocalResidual<TypeTag, TTag::IncompressibleTest> { using type = OnePIncompressibleLocalResidual<TypeTag>; }; struct LocalResidual<TypeTag, TTag::IncompressibleTest> { using type = OnePIncompressibleLocalResidual<TypeTag>; };
``` ```
In the following we define our fluid properties. In the following we define the fluid properties.
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
struct FluidSystem<TypeTag, TTag::IncompressibleTest> struct FluidSystem<TypeTag, TTag::IncompressibleTest>
...@@ -286,14 +294,14 @@ We enable caching for the FV grid geometry ...@@ -286,14 +294,14 @@ We enable caching for the FV grid geometry
template<class TypeTag> template<class TypeTag>
struct EnableGridGeometryCache<TypeTag, TTag::IncompressibleTest> { static constexpr bool value = true; }; struct EnableGridGeometryCache<TypeTag, TTag::IncompressibleTest> { static constexpr bool value = true; };
``` ```
The cache stores values that were already calculated for later usage. This makes the simulation faster. The cache stores values that were already calculated for later usage. This increases the memory demand but makes the simulation faster.
We leave the namespace Properties. We leave the namespace Properties.
```cpp ```cpp
} }
``` ```
### The problem class ### The problem class
We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation.
As this is a porous medium problem, we inherit from the basic `PorousMediumFlowProblem`. As this is a porous medium problem, we inherit from the base class `PorousMediumFlowProblem`.
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
class OnePTestProblem : public PorousMediumFlowProblem<TypeTag> class OnePTestProblem : public PorousMediumFlowProblem<TypeTag>
...@@ -320,18 +328,19 @@ This is the constructor of our problem class: ...@@ -320,18 +328,19 @@ This is the constructor of our problem class:
OnePTestProblem(std::shared_ptr<const GridGeometry> gridGeometry) OnePTestProblem(std::shared_ptr<const GridGeometry> gridGeometry)
: ParentType(gridGeometry) {} : ParentType(gridGeometry) {}
``` ```
First, we define the type of boundary conditions depending on location. Two types of boundary conditions First, we define the type of boundary conditions depending on the location. Two types of boundary conditions
can be specified: Dirichlet or Neumann boundary condition. On a Dirichlet boundary, the values of the can be specified: Dirichlet or Neumann boundary condition. On a Dirichlet boundary, the values of the
primary variables need to be fixed. On a Neumann boundary condition, values for derivatives need to be fixed. primary variables need to be fixed. On a Neumann boundary condition, values for derivatives need to be fixed.
Mixed boundary conditions (different types for different equations on the same boundary) are not accepted. Mixed boundary conditions (different types for different equations on the same boundary) are not accepted for
cell-centered finite volume schemes.
```cpp ```cpp
BoundaryTypes boundaryTypes(const Element &element, BoundaryTypes boundaryTypes(const Element &element,
const SubControlVolumeFace &scvf) const const SubControlVolumeFace &scvf) const
{ {
BoundaryTypes values; BoundaryTypes values;
``` ```
we retreive the global position, i.e. the vector including the global coordinates we retrieve the global position, i.e. the vector with the global coordinates,
of the finite volume of the integration point on the boundary sub-control volume face `scvf`
```cpp ```cpp
const auto globalPos = scvf.ipGlobal(); const auto globalPos = scvf.ipGlobal();
``` ```
...@@ -343,10 +352,10 @@ We specify Dirichlet boundaries on the top and bottom of our domain: ...@@ -343,10 +352,10 @@ We specify Dirichlet boundaries on the top and bottom of our domain:
```cpp ```cpp
if (globalPos[dimWorld-1] < eps || globalPos[dimWorld-1] > this->gridGeometry().bBoxMax()[dimWorld-1] - eps) if (globalPos[dimWorld-1] < eps || globalPos[dimWorld-1] > this->gridGeometry().bBoxMax()[dimWorld-1] - eps)
values.setAllDirichlet(); values.setAllDirichlet();
else
``` ```
The top and bottom of our domain are Neumann boundaries: The top and bottom of our domain are Neumann boundaries:
```cpp ```cpp
else
values.setAllNeumann(); values.setAllNeumann();
return values; return values;
...@@ -363,7 +372,7 @@ we retreive again the global position ...@@ -363,7 +372,7 @@ we retreive again the global position
const auto& pos = scvf.ipGlobal(); const auto& pos = scvf.ipGlobal();
PrimaryVariables values(0); PrimaryVariables values(0);
``` ```
we assign pressure values in [Pa] according to a pressure gradient to 1e5 Pa at the top and 1.1e5 Pa at the bottom. and assign pressure values in [Pa] according to a pressure gradient to 1e5 Pa at the top and 1.1e5 Pa at the bottom.
```cpp ```cpp
values[0] = 1.0e+5*(1.1 - pos[dimWorld-1]*0.1); values[0] = 1.0e+5*(1.1 - pos[dimWorld-1]*0.1);
return values; return values;
...@@ -391,12 +400,13 @@ We leave the namespace Dumux. ...@@ -391,12 +400,13 @@ We leave the namespace Dumux.
## The file `spatialparams_tracer.hh` ## The file `spatialparams_tracer.hh`
In this file, we define spatial properties of the porous medium such as the permeability and the porosity in various functions for the tracer problem. Further, spatial dependent properties of the tracer fluid system are defined and in the end two functions handel the calculated volume fluxes from the solution of the 1p problem. In this file, we define spatial properties of the porous medium such as the permeability and the porosity in various functions for the tracer problem.
In the file `properties.hh`, all properties are declared. Furthermore, spatial dependent properties of the tracer fluid system are defined and in the end two functions handle the calculated volume fluxes from the solution of the 1p problem.
We use the properties for porous medium flow models, declared in the file `properties.hh`.
```cpp ```cpp
#include <dumux/porousmediumflow/properties.hh> #include <dumux/porousmediumflow/properties.hh>
``` ```
As in the 1p spatialparams, we inherit from the spatial parameters for single-phase, finite volumes, which we include here. As in the 1p spatialparams, we inherit from the spatial parameters for single-phase models using finite volumes, which we include here.
```cpp ```cpp
#include <dumux/material/spatialparams/fv1p.hh> #include <dumux/material/spatialparams/fv1p.hh>
``` ```
...@@ -406,7 +416,6 @@ namespace Dumux { ...@@ -406,7 +416,6 @@ namespace Dumux {
``` ```
In the `TracerTestSpatialParams` class, we define all functions needed to describe spatially dependent parameters for the `tracer_problem`. In the `TracerTestSpatialParams` class, we define all functions needed to describe spatially dependent parameters for the `tracer_problem`.
```cpp ```cpp
template<class GridGeometry, class Scalar> template<class GridGeometry, class Scalar>
class TracerTestSpatialParams class TracerTestSpatialParams
: public FVSpatialParamsOneP<GridGeometry, Scalar, : public FVSpatialParamsOneP<GridGeometry, Scalar,
...@@ -443,24 +452,30 @@ We do not consider dispersivity for the tracer transport. So we set the dispersi ...@@ -443,24 +452,30 @@ We do not consider dispersivity for the tracer transport. So we set the dispersi
{ return 0; } { return 0; }
``` ```
### Properties of the fluid system ### Properties of the fluid system
In the following, we define fluid properties that are spatial parameters in the tracer model. They can possible vary with space but are usually constants. Further spatially constant values of the fluid system are defined in the `TracerFluidSystem` class in `problem.hh`. In the following, we define fluid properties that are spatial parameters in the tracer model.
They can possible vary in space but are usually constants.
Furthermore, spatially constant values of the fluid system are defined in the `TracerFluidSystem` class in `problem.hh`.
We define the fluid density to a constant value of 1000 $`\frac{kg}{m^3}`$. We define the fluid density to a constant value of 1000 $`\frac{kg}{m^3}`$.
```cpp ```cpp
Scalar fluidDensity(const Element &element, Scalar fluidDensity(const Element &element,
const SubControlVolume& scv) const const SubControlVolume& scv) const
{ return 1000; } { return 1000; }
``` ```
We define the fluid molar mass. This interface defines the fluid molar mass within the sub-control volume `scv`.
```cpp ```cpp
Scalar fluidMolarMass(const Element &element, Scalar fluidMolarMass(const Element &element,
const SubControlVolume& scv) const const SubControlVolume& scv) const
{ return 18.0; } { return fluidMolarMassAtPos(scv.dofPosition()); }
```
Scalar fluidMolarMass(const GlobalPosition &globalPos) const This interface defines the fluid molar mass depending on the position in the domain.
```cpp
Scalar fluidMolarMassAtPos(const GlobalPosition &globalPos) const
{ return 18.0; } { return 18.0; }
``` ```
### The volume fluxes ### The volume fluxes
We define a function which returns the field of volume fluxes. This is e.g. used to calculate the transport of the tracer. We define a function which returns the volume flux across the given sub-control volume face `scvf`.
This flux is obtained from the vector `volumeFlux_` that contains the fluxes across al sub-control volume faces of the discretization.
This vector can be set using the `setVolumeFlux` function.
```cpp ```cpp
template<class ElementVolumeVariables> template<class ElementVolumeVariables>
Scalar volumeFlux(const Element &element, Scalar volumeFlux(const Element &element,
...@@ -471,7 +486,8 @@ We define a function which returns the field of volume fluxes. This is e.g. used ...@@ -471,7 +486,8 @@ We define a function which returns the field of volume fluxes. This is e.g. used
return volumeFlux_[scvf.index()]; return volumeFlux_[scvf.index()];
} }
``` ```
We define a function to set the volume flux. This is used in the main function to set the volume flux to the calculated value based on the solution of the 1p problem. We define a function that allows setting the volume fluxes for all sub-control volume faces of the discretization.
This is used in the main function after these fluxes have been based on the pressure solution obtained with the single-phase model.
```cpp ```cpp
void setVolumeFlux(const std::vector<Scalar>& f) void setVolumeFlux(const std::vector<Scalar>& f)
{ volumeFlux_ = f; } { volumeFlux_ = f; }
...@@ -491,7 +507,7 @@ private: ...@@ -491,7 +507,7 @@ private:
Before we enter the problem class containing initial and boundary conditions, we include necessary files and introduce properties. Before we enter the problem class containing initial and boundary conditions, we include necessary files and introduce properties.
### Include files ### Include files
Again, we have to include the dune grid interface: Again, we use YaspGrid, the implementation of the dune grid interface for structured grids:
```cpp ```cpp
#include <dune/grid/yaspgrid.hh> #include <dune/grid/yaspgrid.hh>
``` ```
...@@ -507,7 +523,7 @@ We include again the porous medium problem class that this class is derived from ...@@ -507,7 +523,7 @@ We include again the porous medium problem class that this class is derived from
```cpp ```cpp
#include <dumux/porousmediumflow/problem.hh> #include <dumux/porousmediumflow/problem.hh>
``` ```
and the base fluidsystem and the base fluidsystem. We will define a custom fluid system that inherits from that class.
```cpp ```cpp
#include <dumux/material/fluidsystems/base.hh> #include <dumux/material/fluidsystems/base.hh>
``` ```
...@@ -561,30 +577,34 @@ We define the spatial parameters for our tracer simulation: ...@@ -561,30 +577,34 @@ We define the spatial parameters for our tracer simulation:
template<class TypeTag> template<class TypeTag>
struct SpatialParams<TypeTag, TTag::TracerTest> struct SpatialParams<TypeTag, TTag::TracerTest>
{ {
private:
using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
using Scalar = GetPropType<TypeTag, Properties::Scalar>; using Scalar = GetPropType<TypeTag, Properties::Scalar>;
public:
using type = TracerTestSpatialParams<GridGeometry, Scalar>; using type = TracerTestSpatialParams<GridGeometry, Scalar>;
}; };
``` ```
We define that mass fractions are used to define the concentrations One can choose between a formulation in terms of mass or mole fractions. Here, we are using mass fractions.
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
struct UseMoles<TypeTag, TTag::TracerTest> { static constexpr bool value = false; }; struct UseMoles<TypeTag, TTag::TracerTest> { static constexpr bool value = false; };
``` ```
We do not use a solution dependent molecular diffusion coefficient: We use solution-independent molecular diffusion coefficients. Per default, solution-dependent
diffusion coefficients are assumed during the computation of the jacobian matrix entries. Specifying
solution-independent diffusion coefficients can speed up computations:
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
struct SolutionDependentMolecularDiffusion<TypeTag, TTag::TracerTestCC> { static constexpr bool value = false; }; struct SolutionDependentMolecularDiffusion<TypeTag, TTag::TracerTestCC>
{ static constexpr bool value = false; };
``` ```
In the following, we create a new tracer fluid system and derive it from the base fluid system. In the following, we create a new tracer fluid system and derive from the base fluid system.
```cpp ```cpp
template<class TypeTag> template<class TypeTag>
class TracerFluidSystem : public FluidSystems::Base<GetPropType<TypeTag, Properties::Scalar>, class TracerFluidSystem : public FluidSystems::Base<GetPropType<TypeTag, Properties::Scalar>,
TracerFluidSystem<TypeTag>> TracerFluidSystem<TypeTag>>
{ {
``` ```
We define convenient shortcuts to the properties `Scalar`, `Problem`, `GridView`, We define some convenience aliases:
`Element`, `FVElementGeometry` and `SubControlVolume`:
```cpp ```cpp
using Scalar = GetPropType<TypeTag, Properties::Scalar>; using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using Problem = GetPropType<TypeTag, Properties::Problem>; using Problem = GetPropType<TypeTag, Properties::Problem>;
...@@ -595,37 +615,41 @@ We define convenient shortcuts to the properties `Scalar`, `Problem`, `GridView` ...@@ -595,37 +615,41 @@ We define convenient shortcuts to the properties `Scalar`, `Problem`, `GridView`
public: public:
``` ```
We specify, that the fluid system only contains tracer components, We specify that the fluid system only contains tracer components,
```cpp ```cpp
static constexpr bool isTracerFluidSystem() static constexpr bool isTracerFluidSystem()
{ return true; } { return true; }
``` ```
that no component is the main component and that no component is the main component
```cpp ```cpp
static constexpr int getMainComponent(int phaseIdx) static constexpr int getMainComponent(int phaseIdx)
{ return -1; } { return -1; }
``` ```
and the number of components We define the number of components of this fluid system (one single tracer component)
```cpp ```cpp
static constexpr int numComponents = 1; static constexpr int numComponents = 1;
``` ```
We set the component name for the component index (`compIdx`) for the vtk output: This interface is designed to define the names of the components of the fluid system.
Here, we only have a single component, so `compIdx` should always be 0.
The component name is used for the vtk output.
```cpp ```cpp
static std::string componentName(int compIdx) static std::string componentName(int compIdx = 0)
{ return "tracer_" + std::to_string(compIdx); } { return "tracer_" + std::to_string(compIdx); }
``` ```
We set the phase name for the phase index (`phaseIdx`) for velocity vtk output: We set the phase name for the phase index (`phaseIdx`) for velocity vtk output:
Here, we only have a single phase, so `phaseIdx` should always be zero.
```cpp ```cpp
static std::string phaseName(int phaseIdx = 0) static std::string phaseName(int phaseIdx = 0)
{ return "Groundwater"; } { return "Groundwater"; }
``` ```
We set the molar mass of the tracer component with index `compIdx`. We set the molar mass of the tracer component with index `compIdx` (should again always be zero here).
```cpp ```cpp
static Scalar molarMass(unsigned int compIdx) static Scalar molarMass(unsigned int compIdx = 0)
{ return 0.300; } { return 0.300; }
``` ```
We set the value for the binary diffusion coefficient. This We set the value for the binary diffusion coefficient. This
might depend on spatial parameters like pressure / temperature. But for our case it is 0.0: might depend on spatial parameters like pressure / temperature.
But, in this case we neglect diffusion and return 0.0:
```cpp ```cpp
static Scalar binaryDiffusionCoefficient(unsigned int compIdx, static Scalar binaryDiffusionCoefficient(unsigned int compIdx,
const Problem& problem, const Problem& problem,
...@@ -646,7 +670,7 @@ We leave the namespace Properties. ...@@ -646,7 +670,7 @@ We leave the namespace Properties.
``` ```
### The problem class ### The problem class
We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation. We enter the problem class where all necessary boundary conditions and initial conditions are set for our simulation.
As this is a porous medium problem, we inherit from the basic `PorousMediumFlowProblem`. As this is a porous medium problem, we inherit from the base class `PorousMediumFlowProblem`.
```cpp ```cpp
template <class TypeTag> template <class TypeTag>
class TracerTestProblem : public PorousMediumFlowProblem<TypeTag> class TracerTestProblem : public PorousMediumFlowProblem<TypeTag>
...@@ -672,11 +696,11 @@ We use convenient declarations that we derive from the property system. ...@@ -672,11 +696,11 @@ We use convenient declarations that we derive from the property system.
using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView; using FVElementGeometry = typename GetPropType<TypeTag, Properties::GridGeometry>::LocalView;