Skip to content
Snippets Groups Projects
Commit 0003b554 authored by Timo Koch's avatar Timo Koch
Browse files

[slides] Update problem slides

parent dfb2860b
No related branches found
No related tags found
1 merge request!173[slides] Update problem slides
---
title: Setting up a problem / using cmake
title: DuMu^x^ applications
---
## Test Problems / Applications
## DuMu^x^ applications
A test problem / application consists of:
The source code for a
typical DuMu^x^ application consists of:
* A property file (properties.hh)
* a problem file (often problem.hh)
* a spatial parameters file (often spatialparams.hh)
* an input file (often params.input)
* a main file (often main.cc)
* a build system file (CMakeLists.txt)
* Property specializations (e.g. `properties.hh`)
* Problem class definition (e.g. `problem.hh`) and often a spatial parameter class definition (e.g. `spatialparams.hh`)
* A parameter configuration file (e.g. `params.input`)
* The main program (e.g. `main.cc`)
* `CMakeLists.txt` (CMake build system configuration)
## Example: gas injection / immiscible two phase flow
# Example
Mass balance:
## Gas injection / immiscible two phase flow
$\begin{equation}
\phi \frac{\partial \varrho_\alpha S_\alpha}{\partial t}
Mass balance equations for two fluid phases:
$\begin{aligned}
\frac{\partial \left(\phi \varrho_\alpha S_\alpha \right)}{\partial t}
-
\nabla \cdot \boldsymbol{v}_\alpha
-
q_\alpha = 0, \quad \alpha \in \lbrace w, n \rbrace.
\end{aligned}$
Momentum balance equations (multiphase-phase Darcy's law):
$\begin{aligned}
\boldsymbol{v}_\alpha = \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left(\nabla\, p_\alpha - \varrho_{\alpha} \mathbf{g} \right), \quad \alpha \in \lbrace w, n \rbrace.
\end{aligned}$
## Gas injection / immiscible two phase flow
$\begin{aligned}
\frac{\partial \left(\phi \varrho_\alpha S_\alpha \right)}{\partial t}
-
\nabla \cdot \left( \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left(\nabla\, p_\alpha - \varrho_{\alpha} \mathbf{g} \right) \right)
-
q_\alpha = 0
\end{equation}$
\end{aligned}$
Momentum balance:
* $p_w$, $p_n$: wetting and non-wetting fluid phase pressure
* $\varrho_\alpha$, $\mu_\alpha$: fluid phase density and dynamic viscosity
* $\phi$, $\mathbf{K}$, $k_{r\alpha}$: porosity, intrinsic permeability, relative permeability
* $S_w$, $S_n$: wetting and non-wetting saturation
* $\mathbf{g}$, $q_\alpha$: gravitational potential, source term
$\begin{equation}
\boldsymbol{v}_\alpha = \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left(\nabla\, p_\alpha - \varrho_{\alpha} \mathbf{g} \right)
\end{equation}$
## Gas injection / immiscible two phase flow
$\begin{aligned}
\frac{\partial \left(\phi \varrho_\alpha S_\alpha \right)}{\partial t}
-
\nabla \cdot \left( \varrho_\alpha \frac{k_{r\alpha}}{\mu_\alpha} \mathbf{K} \left(\nabla\, p_\alpha - \varrho_{\alpha} \mathbf{g} \right) \right)
-
q_\alpha = 0
\end{aligned}$
# Properties <small>(`properties.hh`)</small>
* Constitutive relations: $p_n := p_w + p_c$, $p_c := p_c(S_w)$, $k_{r\alpha}$ = $k_{r\alpha}(S_w)$
* Physical constraint (no free space): $S_w + S_n = 1$
* Primary variables: $p_w$, $S_n$ (wetting phase pressure, non-wetting phase saturation)
## The properties file
Sets all properties of the current problem. The injection test case inherits from the 2p model:
# Property specializations
```cpp
namespace Dumux::Properties {
## Properties
// define the TypeTag for this problem
namespace TTag {
struct Injection2p { using InheritsFrom = std::tuple<TwoP>; };
} // end namespace TTag
"Compile-time configuration"
// Set/Overwrite properties within the namespace Dumux::Properties
"Tell DuMu^x^ what type of classes to use"
} // end namespace Dumux::Properties
```
Details on properties in [Part II: Property system](./properties.html)
## The properties file
Often specifies the discretization method:
##
`*properties*.hh`
Create tag, choose model and discretization scheme:
```cpp
namespace Dumux::Properties {
// define the TypeTag for this problem with a cell-centered two-point
// flux approximation spatial discretization.
namespace TTag {
struct Injection2p { using InheritsFrom = std::tuple<TwoP>; };
struct Injection2pCC {
using InheritsFrom = std::tuple<Injection2p, CCTpfaModel>; };
} // end namespace TTag
} // end namespace Dumux::Properties
namespace Dumux::Properties::TTag {
// the application type tag (choose any name)
struct Injection2pCC { using InheritsFrom = std::tuple<TwoP, CCTpfaModel>; };
} // end namespace Dumux::Properties::TTag
```
## The properties file
##
Setting the `Grid` type:
Specialize the `Grid` property for tag `TTag::Injection2pCC` to set the grid type:
```cpp
namespace Dumux::Properties {
template<class TypeTag>
struct Grid<TypeTag, TTag::Injection2p>
{ using type = Dune::YaspGrid<2>; };
struct Grid<TypeTag, TTag::Injection2pCC>
{ using type = Dune::YaspGrid<2>; }; // Yet Another Structured Parallel Grid
} // end namespace Dumux::Properties
```
## The properties file
##
Setting our `Problem` type:
Specialize the `Problem` property to set the problem type:
```cpp
namespace Dumux::Properties {
template<class TypeTag>
struct Problem<TypeTag, TTag::Injection2p>
struct Problem<TypeTag, TTag::Injection2pCC>
{ using type = InjectionProblem2P<TypeTag>; };
} // end namespace Dumux::Properties
```
## The properties file
The problem class `InjectionProblem2P` is discussed
in one of the following sections.
##
Setting our `SpatialParams` type:
Specialize the `SpatialParams` property to set the spatial parameter type:
```cpp
// Set the spatial parameters
namespace Dumux::Properties {
template<class TypeTag>
struct SpatialParams<TypeTag, TTag::Injection2p>
struct SpatialParams<TypeTag, TTag::Injection2pCC>
{
private:
using FVGridGeometry = GetPropType<TypeTag,
Properties::FVGridGeometry>;
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
public:
using FVGridGeometry
= GetPropType<TypeTag, Properties::FVGridGeometry>;
using Scalar
= GetPropType<TypeTag, Properties::Scalar>;
using type = InjectionSpatialParams<FVGridGeometry, Scalar>;
};
} // end namespace Dumux::Properties
```
## The properties file
##
Setting the `FluidSystem` type:
Specialize the `FluidSystem` property to set the fluid system type:
```cpp
// Set fluid configuration
namespace Dumux::Properties {
template<class TypeTag>
struct FluidSystem<TypeTag, TTag::Injection2p>
struct FluidSystem<TypeTag, TTag::Injection2pCC>
{
private:
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using Policy = FluidSystems::H2ON2DefaultPolicy<
/*fastButSimplifiedRelations=*/true>;
public:
using type = FluidSystems::H2ON2<Scalar, Policy>;
};
} // end namespace Dumux::Properties
```
##
# Problem definition
<h2>The properties file may set many more properties depending on the utilized model and test case.</h2>
## Problem
# The problem <small>(`problem.hh`)</small>
A "problem" class in DuMu^x^ implements a specific scenario:
## The problem file
A problem in DuMu$^\mathsf{x}$ implements a specific model scenario:
`*problem*.hh`
```cpp
template<class TypeTag>
class InjectionProblem2P : public PorousMediumFlowProblem<TypeTag>
{
// Details of the model scenario
// - BoundaryConditions
// - InitialConditions
// - etc.
// - boundary conditions
// - initial conditions
// - source terms
// - scenario name (for output)
}
```
## The problem file
Inherit from base class `PorousMediumFlowProblem`, only override
scenario-specific functions (static polymorphism).
##
Defining the types of boundary conditions:
The boundary condition types:
```cpp
BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
......@@ -163,23 +202,27 @@ BoundaryTypes boundaryTypesAtPos(const GlobalPosition &globalPos) const
```
## The problem file
##
Evaluating boundary conditions:
Dirichlet boundary condition values (only called on Dirichlet boundaries)
```cpp
PrimaryVariables dirichletAtPos(const GlobalPosition& globalPos) const
{ return initialAtPos(globalPos); }
```
`PrimaryVariables` is an array of primary variables (here, the size of the array is 2).
##
Neumann boundary condition values / boundary fluxes (only called on Neumann boundaries)
```cpp
NumEqVector neumannAtPos(const GlobalPosition& globalPos) const
{
NumEqVector values(0.0);
if (injectionActive() && onInjectionBoundary(globalPos))
{
// inject nitrogen. negative values mean injection
// units kg/(s*m^2)
values[Indices::conti0EqIdx + FluidSystem::N2Idx] = -1e-4;
values[Indices::conti0EqIdx + FluidSystem::H2OIdx] = 0.0;
}
......@@ -188,56 +231,74 @@ NumEqVector neumannAtPos(const GlobalPosition& globalPos) const
}
```
## The problem file
`NumEqVector` is an array of equations (here, the size of the array is 2).
Defining initial conditions:
##
Initial conditions:
```cpp
PrimaryVariables initialAtPos(const GlobalPosition& globalPos) const
{
PrimaryVariables values(0.0);
const Scalar densityW = FluidSystem::H2O::liquidDensity(
temperature(), 1.0e5);
const Scalar pw = 1.0e5 - densityW*this->gravity()[dimWorld-1]*(
aquiferDepth_ - globalPos[dimWorld-1]);
const Scalar densityW
= FluidSystem::H2O::liquidDensity(temperature(), 1.0e5);
const Scalar pw
= 1.0e5 - densityW*this->gravity()[dimWorld-1]
*(aquiferDepth_ - globalPos[dimWorld-1]);
values[Indices::pressureIdx] = pw;
values[Indices::saturationIdx] = 0.0;
return values;
}
```
## The problem file
##
Defining source/sink terms:
Source/sink terms:
```cpp
NumEqVector sourceAtPos(const GlobalPosition &globalPos) const
{
return NumEqVector(0.0);
}
{ return NumEqVector(0.0); }
```
# Spatial Parameters <small>(`spatialparams.hh`)</small>
# Spatial Parameters definition
## The spatial parameters
## Spatial parameters
Defining the intrinsic permeability:
`*spatialparams*.hh`
```cpp
template<class FVGridGeometry, class Scalar>
class InjectionSpatialParams : ...
class InjectionSpatialParams
: public FVPorousMediumFlowSpatialParamsMP<
FVGridGeometry, Scalar,
InjectionSpatialParams<FVGridGeometry, Scalar>
> {
// parameters that are typically position-dependent
// e.g. porosity, permeability
};
```
Inherit from `FVPorousMediumFlowSpatialParamsMP` where
`FV`: finite volumes, `MP`: multi-phase flow.
##
A function returning the instrinsic permeability $K$:
```cpp
auto permeabilityAtPos(const GlobalPosition& globalPos) const
{
auto permeabilityAtPos(const GlobalPosition& globalPos) const
{
if (isInAquitard_(globalPos))
return aquitardK_;
return aquiferK_;
}
if (isInAquitard_(globalPos))
return aquitardK_;
return aquiferK_;
}
```
## The spatial parameters
##
Defining the porosity:
A function returning the porosity:
```cpp
Scalar porosityAtPos(const GlobalPosition& globalPos) const
......@@ -249,11 +310,11 @@ Scalar porosityAtPos(const GlobalPosition& globalPos) const
}
```
## The spatial parameters
Capillary pressure - saturation relationship:
##
More information in a later lecture on the materialsystem!
A function returning a parameterized constitutive law
describing fluid-matrix interactions
($p_c(S_w)$, $k_r(S_w)$):
```cpp
auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const
......@@ -264,23 +325,24 @@ auto fluidMatrixInteractionAtPos(const GlobalPosition& globalPos) const
}
```
## The spatial parameters
##
Defining the temperature in the domain:
Set the (constant) temperature field in the domain:
```cpp
Scalar temperatureAtPos(const GlobalPosition& globalPos) const
{
// constant temperature of 20°C
return 273.15 + 20.0;
return 273.15 + 20.0; // 20°C
}
```
# Runtime parameters <small>(`params.input`)</small>
# Runtime parameters
## Runtime parameters
## The input file
Dune INI syntax (`[Group]` and `Key = Value` pairs)
DUNE INI syntax:
`params.input`
```cpp
[Grid]
......@@ -291,62 +353,69 @@ Cells = 24 16
[Problem]
Name = test
```
Input files are specified as arguments to the executable
`./myexecutable params.input`
See [slides on runtime parameters](./runtimeparams-grids.html) for details.
# Main program and main function
## The input file
## Main program
If no input file is given it defaults to the file `params.input` or `myexecutablename.input`
* Each problem has one main file (`test_name.cc` or `main.cc`)
* Contains the `main` function (mandatory in C/C++ programs)
Parameters can be overwritten in the command line via:
## Main function
```bash
./executable params.input –Problem.Name myNewName
Calling `Dumux::initialize` is mandatory
at the beginning of each DuMu^x^ program to make sure the
environment is correctly set up.
```cpp
int main(int argc, char** argv)
{
// initialize MPI+X backends (mandatory)
Dumux::initialize(argc, argv);
```
##
Parse runtime parameters:
# The main file <small>(`2pmain.cc`)</small>
```cpp
// parse command line arguments and input file
Dumux::Parameters::init(argc, argv);
```
## The main source file
* Each problem has a specific main file (`test_name.cc` or `main.cc`) which sets up the program structure and calls assembler and solvers to assemble and solve the PDEs.
* Depending on the complexity of the problem the main file can be either set up to solve a linear problem, a non-linear problem and stationary as well as instationary problems.
* The main file usually includes the problem, the solvers, the assembler, the VTK output module and the gridmanager.
See [slides on runtime parameters](./runtimeparams-grids.html) for details.
## The main source file
##
Startup / parsing runtime parameters:
Define an alias for the test problem type tag
```cpp
// define the type tag for this problem
using namespace Dumux;
using TypeTag = Properties::TTag::Injection2pCC;
// maybe initialize MPI and/or multithreading backend
const auto& mpiHelper = Dune::MPIHelper::instance();
// print dumux start message
if (mpiHelper.rank() == 0)
DumuxMessage::print(/*firstCall=*/true);
// parse command line arguments and input file
Parameters::init(argc, argv);
```
## The main source file
The tag (tag alias) is used to extract types and values
via the property system (details on properties in [Part II: Property system](./properties.html)).
##
Grid creation:
Create the computational grid:
```cpp
// try to create a grid (from the given grid file or the input file)
// create a grid (take parameters from input file)
GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
gridManager.init();
// we compute on the leaf grid view
const auto& leafGridView = gridManager.grid().leafGridView();
// obtain the grid and a grid view
const auto& grid = gridManager.grid();
const auto& leafGridView = grid.leafGridView();
```
## The main source file
More details on the grid in [Part I: Parameters and grids](./runtimeparams-grids.html).
##
`GridGeometry` and `Problem` instantiation:
......@@ -362,52 +431,54 @@ auto problem = std::make_shared<Problem>(gridGeometry);
```
## The main source file
##
Initial solution and secondary variables:
```cpp
// the solution vector
using SolutionVector = GetPropType<TypeTag,
Properties::SolutionVector>;
using SolutionVector
= GetPropType<TypeTag, Properties::SolutionVector>;
SolutionVector x(gridGeometry->numDofs());
// the grid variables
using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
auto gridVariables = std::make_shared<GridVariables>(
problem, gridGeometry);
auto gridVariables
= std::make_shared<GridVariables>(problem, gridGeometry);
gridVariables->init(x);
```
## The main source file
##
Setting up [VTK](https://vtk.org/) output:
```cpp
// initialize the vtk output module
VtkOutputModule<GridVariables, SolutionVector> vtkWriter(
*gridVariables, x, problem->name());
VtkOutputModule<GridVariables, SolutionVector>
vtkWriter(*gridVariables, x, problem->name());
using VelocityOutput = GetPropType<TypeTag,
Properties::VelocityOutput>;
// optionally add a velocity post-processor
using VelocityOutput
= GetPropType<TypeTag, Properties::VelocityOutput>;
vtkWriter.addVelocityOutput(
std::make_shared<VelocityOutput>(*gridVariables));
// add input/output defaults for the chosen model
using IOFields = GetPropType<TypeTag, Properties::IOFields>;
IOFields::initOutputModule(vtkWriter);
```
## The main source file
##
Differences for various problem cases:
Some typical main function structures:
* Stationary linear problem
* Stationary non-linear problem
* Instationary non-linear problem
* Steady-state linear problems
* Steady-state non-linear problems
* Time-dependent non-linear problems
## The main source file
##
Assembling the system for a linear problem:
Assembling the system for a steady-state linear problem:
```cpp
// the assembler for stationary problems
......@@ -416,17 +487,17 @@ auto assembler = std::make_shared<Assembler>(
problem, gridGeometry, gridVariables);
// the discretization matrices for stationary linear problems
using JacobianMatrix = GetPropType<TypeTag,
Properties::JacobianMatrix>;
using JacobianMatrix
= GetPropType<TypeTag, Properties::JacobianMatrix>;
auto A = std::make_shared<JacobianMatrix>();
auto r = std::make_shared<SolutionVector>();
assembler->setLinearSystem(A, r);
assembler->assembleJacobianAndResidual(x);
```
## The main source file
##
And solving it:
and solve it using an iterative method:
```cpp
using LinearSolver = ILUBiCGSTABIstlSolver<
......@@ -435,32 +506,45 @@ using LinearSolver = ILUBiCGSTABIstlSolver<
auto linearSolver = std::make_shared<LinearSolver>(
gridGeometry->gridView(), gridGeometry->dofMapper());
// we solve Ax = -r to save update and copy
(*r) *= -1.0;
(*r) *= -1.0; // solve Ax = -r to save update and copy
linearSolver->solve(*A, x, *r);
// the grid variables need to be up to date for subsequent output
gridVariables->update(x);
```
## The main source file
##
Simplified code for steady-state linear problem using `Dumux::LinearPDESolver`
```cpp
auto assembler = ...; // construct as before
auto linearSolver = ...; // construct as before
using Solver = LinearPDESolver<Assembler, LinearSolver>;
Solver solver(assembler, linearSolver);
// assemble & solve
solver.solve(x);
```
##
For non-linear problems, use the `NewtonSolver`:
For steady-state non-linear problems, use `Dumux::NewtonSolver`:
```cpp
auto assembler = ...; // as before
auto linearSolver = ...; // as before
auto assembler = ...; // construct as before
auto linearSolver = ...; // construct as before
using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
NewtonSolver nonLinearSolver(assembler, linearSolver);
using Solver = NewtonSolver<Assembler, LinearSolver>;
Solver solver(assembler, linearSolver);
// linearize & solve
nonLinearSolver.solve(x);
solver.solve(x);
```
## The main source file
##
For instationary problems, pass a `TimeLoop` and a solution vector
carrying the solution on the previous time step to the assembler:
For time-dependent problems, pass a `TimeLoop` instance
and a solution vector carrying the solution
on the previous/initial time level to the assembler:
```cpp
SolutionVector xOld = x;
......@@ -470,24 +554,27 @@ timeLoop->setMaxTimeStepSize(maxDt);
using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
auto assembler = std::make_shared<Assembler>(
problem, gridGeometry, gridVariables, timeLoop, xOld);
problem, gridGeometry, gridVariables,
timeLoop, xOld // <-- new arguments
);
// assemble linear/non-linear problem as before
// ...
```
## The main source file
##
The skeleton of a time loop:
```cpp
timeLoop->start(); do
{
// Calculate solution within each time step
timeLoop->start(); do {
// Time loop body
} while (!timeLoop->finished());
```
## The main source file
##
Solving a time step:
......@@ -497,13 +584,12 @@ timeLoop->start(); do
{
// linearize & solve
nonLinearSolver.solve(x, *timeLoop);
// make the new solution the old solution
xOld = x;
gridVariables->advanceTimeStep();
```
## The main source file
##
Advancing the time loop to the next step:
......@@ -517,50 +603,86 @@ Advancing the time loop to the next step:
nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize())
);
} while (!timeLoop->finished());
// print final report
timeLoop->finalize(leafGridView.comm());
```
# Build system <small>(`CMakeLists.txt`)</small>
# Build system (CMake)
## Typical C++ build steps
1. configure
2. compile
3. install (copy programs to some location)
Step 3 is usually skipped by DuMu^x^ developers.
But you can of course "install" Dune modules and DuMu^x^.
## Build system - what is CMake?
* Open source build system tool developed by KITware.
* Offers a one-tool-solution to all building tasks, like configuring, building, linking, testing and packaging.
* Is a build system generator: It supports a set of backends called generators.
* Is portable and supports cross-platform compilation.
* Is controlled by ONE rather simple language.
* Every directory in a project contains a file called `CMakeLists.txt`, which is written in the CMake language. You can think of these as a distributed configure script. Upon configure, the top-level `CMakeLists.txt` is executed.
* [Open-source build system tool developed by KITware](https://cmake.org/)
* Offers a one-tool-solution to all building tasks, like configuring, building, linking, testing and packaging
* Is portable and supports cross-platform compilation
* Build file generator: Support various backends called generators (default: GNU Makefiles)
* Control files written in the CMake language
## Build system - configuring
## Build system - CMakeLists.txt
* Configure build time compiler parameters / linking information.
* Create „targets“ that can be build to create executables.
* Every directory in a project contains a file called `CMakeLists.txt`, which is written in the CMake language
* Upon configure, the top-level `CMakeLists.txt` is executed
* Subfolders are included with the `add_subdirectory(...)` function
## Build system - configuring
* Build with the script `dune-common/bin/dunecontrol <options>` which takes care of all dependencies and modular dune structure.
* Option `all`: build all libraries and executables.
* Option `--opts=<optionfile.opts>` specify e.g. compiler flags; For DuMu$^\mathsf{x}$, you may use `dumux/cmake.opts`.
* Option `--build-dir=<build directory>` specify path for out-of-source build; Default: every module contains its own build directory `build-cmake/`.
* You have to reconfigure (possibly deleting all build directories first) whenever a dependency changes or a Dune library is updated.
* Configure build-time compiler parameters / linking information
* Create "targets" that can be build to create executables
* Find and link external libraries / software dependencies
## Build system - dunecontrol
## Invoking `dunecontrol`
* For Dune, CMake is triggered via the `dunecontrol` script
```bash
./dune-common/bin/dunecontrol --opts=dumux/cmake.opts all
```sh
dune-common/bin/dunecontrol [options] <command>
```
* useful commands:
- `configure`: configure libraries, variables, paths, files
- `make all`: build libraries
- `all`: includes `configure` and `make all`
## Build system - important basic commands
## Build system - dunecontrol
* Use `add_subdirectory` for recursively adding subdirectories.
* The subdirectory has to contain a `CMakeLists.txt` file (can be empty).
* Executables are added via `add_executable(<name> source1 [source2 ...])`.
* Tests are added via `dumux_add_test(...)` which also add a test executable to the test suite.
* Symlinks can be added via `dune_symlink_to_source_files(FILES file1 [file2 ...])`.
* useful options:
- `--opts=<optionfile.opts>` specify e.g. compiler flags; DuMu^x^ provides [`dumux/cmake.opts`](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/blob/master/cmake.opts).
- `--build-dir=<build directory>` specify path for out-of-source build; Default: every module contains its own build directory called `build-cmake/`
- `--only <module>` only apply command to a specific module/s (comma-separated list)
## Build system - dunecontrol
You may have to reconfigure (rerun `dunecontrol`)
whenever a dependency changes or a Dune library is updated.
CMake caches. To reconfigure, you may need to remove the cache first:
```sh
./dune-common/bin/dunecontrol bexec rm -r CMakeFiles CMakeCache.txt
```
removes the `CMake` cache files from all Dune modules.
(Use `--only <module>` to only remove caches of specific modules.)
## Build system - basic CMake functions
* Use `add_subdirectory` for recursively adding subdirectories
* Subdirectory must contain a `CMakeLists.txt` (can be empty)
* Executables are added via `add_executable(<name> source1 [source2 ...])`
* Tests are added via `dumux_add_test` which also add a test executable to the test suite
* Symlinks can be added via `dune_symlink_to_source_files`
## Build system
Simplest incorporation of a test by defining name, source file and command line arguments:
`CMakeLists.txt` for an example application: create a test target `test_2p_incompressible_box`
by defining name, source file and command line arguments:
```cmake
dumux_add_test(
NAME test_2p_incompressible_box
......@@ -570,9 +692,12 @@ dumux_add_test(
```
## Build system
Add extra compile definitions and commands:
Add extra compile definitions and commands (typical
for DuMu^x^ regression tests):
```cmake
dune_add_test(
dumux_add_test(
NAME test_2p_incompressible_box
SOURCES test_2p_fv.cc
COMPILE_DEFINITIONS TYPETAG=TwoPIncompressibleBox
......@@ -598,19 +723,26 @@ target_compile_definitions(
```
## Build system
Important basic commands:
* See also Dune build system documentation on [https://www.dune-project.org/sphinx/core/](https://www.dune-project.org/sphinx/core/) for a comprehensive CMake online documentation.
Useful resources:
* [CMake online documentation](https://cmake.org/cmake/help/latest/)
* [Dune CMake online documentation](https://www.dune-project.org/sphinx/core/) for CMake functions available with Dune.
# Parallelism
## Distributed memory parallelism with MPI
* MPI stands for Message Passing Interface.
* Main idea is the concept of domain decomposition.
* Each local subdomain is solved on an individual process(rank).
* MPI manages the communication between the ranks.
* Most solvers in DuMu$^\mathsf{x}$ are capable of parallel solving.
* MPI stands for Message Passing Interface
* MPI manages communication between processes that run in parallel
## Distributed memory parallelism with MPI
* Main idea is the concept of domain decomposition
* The grid manages the grid partitioning
* Each local subdomain is assembled on an individual process (rank)
* Solvers have to handle decomposed vectors/matrices
* Most solvers in DuMu^x^ (iterative Krylov subspace methods based on dune-istl) are capable of MPI parallel solving
## Distributed memory parallelism with MPI
......@@ -618,38 +750,55 @@ Run with:
```cpp
mpirun -np [n_cores] [executable_name]
```
Handling results:
* Each rank creates its own `*.vtu`/`*.vtp` file.
* These are combined into `*.pvtu`/`*.pvtp` files for each time step.
* A normal `*.pvd` file is created from the `*.pvtu`/`*.pvtp` files.
## Distributed memory parallelism with MPI
Partitioned VTK output files:
## Shared-memory parallelism and multi-threaded applications
* Each rank creates its own `*.vtu`/`*.vtp` file
* Combined into `*.pvtu`/`*.pvtp` files for each time step
* `*.pvd` groups all `*.pvtu`/`*.pvtp` files into a time series
* Dumux can exploit parallelism with the shared memory model.
* Used in the `Dumux::FVAssembler` by default to assemble the residual and stiffness matrix.
* Is enabled when a multi-threading backend is found.
* Backend is selected by `CMAKE` during configuration and stored in `DUMUX_MULTITHREADING_BACKEND`.
* Possible examples are `OpenMP`, `TBB`, C++ parallel algorithms and `Kokkos`.
## Shared-memory parallelism
## Switching off multi-threading
* Dumux can exploit parallelism with the shared memory model
* Used in the `Dumux::FVAssembler` by default to assemble the residual and stiffness matrix
* Is enabled when a multi-threading backend is found
* Backend is selected by `CMAKE` during configuration and stored in `DUMUX_MULTITHREADING_BACKEND`
* Possible examples are `OpenMP`, `TBB`, C++ parallel algorithms, and `Kokkos`
Simply add the following to your input file:
## Shared-memory parallelism
**Restrict the number of threads**
Number of threads can be restricted via the environment variable `DUMUX_NUM_THREADS`
```sh
DUMUX_NUM_THREADS=2 ./executable
```
## Shared-memory parallelism
**Multi-threaded assembly**
Control use of multi-threading during assembly in input file:
```cpp
[Assembly]
Multithreading = false
```
Important for working on clusters: Number of threads can also be restricted via manipulating the environment variable `DUMUX_NUM_THREADS=2 ./executable`
Defaults to `true`.
# Exercises
## Exercises:
Exercise about setting boundary conditions, the problem file etc:
## Exercises
Basic application setup:
* Go to [Exercise basic](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/tree/master/exercises/exercise-basic#exercise-basics-dumux-course)
* Go to [https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/tree/master/exercises/exercise-basic](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/tree/master/exercises/exercise-basic) and check out the README
Exercise for the main-files:
The main function:
* Go to [https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/tree/master/exercises/exercise-mainfile](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/-/tree/master/exercises/exercise-mainfile) and check out the README
* Go to [Exercise main file](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/-/tree/master/exercises/exercise-mainfile#exercise-mainfiles-dumux-course)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment