Skip to content
Snippets Groups Projects
README.md 9.04 KiB
Newer Older
# Exercise Mainfiles (DuMuX course)
Katharina Heck's avatar
Katharina Heck committed
<br>
Katharina Heck's avatar
Katharina Heck committed
## Problem set-up

This exercise will make you familiar the program sequence in DuMuX and how different levels of complexity can be realized in the main file according to the complexity of your physical problem.
Katharina Heck's avatar
Katharina Heck committed

In order to do so, there are three examples of one phase flow problems. Two examples (a and b) are stationary problems and the third example (c) is an instationary problem.

The stationary examples differ in the `fluidssystems` they are using, which means they differ in the fluid properties (e.g. density, thermal conductivity etc). The first problem (a) uses an incompressible fluid, i.e. the density does not change when pressure changes. This makes it possible to solve the system linearly. The second problem uses a compressible fluid, that means the density is a function of pressure and we need to use a nonlinear solver.
Katharina Heck's avatar
Katharina Heck committed

To summarize, the problems differ in:
* exercise mainfile a: a one-phase incompressible, stationary problem
* exercise mainfile b: a one-phase compressible, stationary problem
* exercise mainfile c: a one-phase compressible, instationary problem
Katharina Heck's avatar
Katharina Heck committed

The problem set-up for all three examples is always the same: It is a two dimensional problem and the domain is $`1 m`$ by $`1 m`$. It is a heterogeneous set-up with a lens in the middle of the domain which has a lower permeability ($`1\cdot 10^{-12} m^2`$ compared to  $`1\cdot 10^{-10} m^2`$ in the rest of the domain).
Katharina Heck's avatar
Katharina Heck committed

<img src="https://git.iws.uni-stuttgart.de/dumux-repositories/dumux-course/raw/master/exercises/extradoc/exercise1_1p_setup.png" width="1000">

In the beginning, there is a uniform pressure of $`1\cdot 10^5 Pa`$ in the whole domain. On the top and the bottom border, dirichlet boundary conditions are set with a pressure of  $`1\cdot 10^5 Pa`$ on top and  $`2 \cdot 10^5 Pa`$ on the bottom. At the sides, there is no in- or outflow and there are no source terms.
Katharina Heck's avatar
Katharina Heck committed

## Preparing the exercise

Katharina Heck's avatar
Katharina Heck committed
* Navigate to the directory `dumux-course/exercises/exercise-mainfile`
Katharina Heck's avatar
Katharina Heck committed

<br><br>
### Task 1: Getting familiar with the code
<hr>

Locate all the files you will need for this exercise
* The __main file__ for the __incompressible, stationary__ problem : `exercise1pamain.cc`
* The __main file__ for the __compressible, stationary__ problem : `exercise1pbmain.cc`
* The __main file__ for the __compressible, instationary__ problem : `exercise1pcmain.cc`
Katharina Heck's avatar
Katharina Heck committed
* The shared __problem file__: `1pproblem.hh`
* The shared __properties file__: `properties.hh`
Katharina Heck's avatar
Katharina Heck committed
* The shared __spatial parameters file__: `1pspatialparams.hh`
* The __input file__ for the __incompressible, stationary__ problem: `exercise_mainfile_a.input`
* The __input file__ for the __compressible, stationary__ problem: `exercise_mainfile_b.input`
* The __input file__ for the __compressible, instationary__ problem: `exercise_mainfile_c.input`
Katharina Heck's avatar
Katharina Heck committed

Please pay special attention to the similarities and differences in the three main files.
The first main file is solved linearly and does not need a newton solver or any other nonlinear solver method.
The second problem is a nonlinear problem and uses newton's method to solve the system.
The third problem is nonlinear and additionally instationary.
Therefore, a time loop needs to be included in the main file.
Katharina Heck's avatar
Katharina Heck committed

The general structure of any main file in DuMuX is:
Katharina Heck's avatar
Katharina Heck committed

* the specific problem `TypeTag` is defined for the problem. This example shows the `TypeTag` for the `CompressibleProblem`:
Katharina Heck's avatar
Katharina Heck committed

```c++
// define the type tag for this problem
Felix Weinhardt's avatar
Felix Weinhardt committed
using TypeTag = Properties::TTag::OnePCompressible;
Katharina Heck's avatar
Katharina Heck committed
```
The `TypeTag` is created in the `properties.hh`. There, you can see that it inherits from the __OneP__ and additionally from the __CCTpfaModel__.
The latter defines the discretization method, which is in this case the cell-centered tpfa method.
* A gridmanager tries to create the grid either from a grid file or the input file:
Katharina Heck's avatar
Katharina Heck committed

```c++
Felix Weinhardt's avatar
Felix Weinhardt committed
GridManager<GetPropType<TypeTag, Properties::Grid>> gridManager;
Katharina Heck's avatar
Katharina Heck committed
gridManager.init();
```
* We create the finite volume grid geometry, the problem, solution vector and the grid variables and initialize them.
Additionally, we initialize the vtk output. Each model has a predefined model specific output with relevant parameters for that model:
Katharina Heck's avatar
Katharina Heck committed

```c++
// create the finite volume grid geometry
using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>;
auto gridGeometry = std::make_shared<GridGeometry>(leafGridView);
Katharina Heck's avatar
Katharina Heck committed

// the problem (initial and boundary conditions)
Felix Weinhardt's avatar
Felix Weinhardt committed
using Problem = GetPropType<TypeTag, Properties::Problem>;
Katharina Heck's avatar
Katharina Heck committed
auto problem = std::make_shared<Problem>(fvGridGeometry);

// the solution vector
Felix Weinhardt's avatar
Felix Weinhardt committed
using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
Katharina Heck's avatar
Katharina Heck committed
SolutionVector x(fvGridGeometry->numDofs());

// the grid variables
Felix Weinhardt's avatar
Felix Weinhardt committed
using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
Katharina Heck's avatar
Katharina Heck committed
auto gridVariables = std::make_shared<GridVariables>(problem, fvGridGeometry);
gridVariables->init(x);

Martin Schneider's avatar
Martin Schneider committed
// initialize the vtk output module
Felix Weinhardt's avatar
Felix Weinhardt committed
VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, x, problem->name());
using VelocityOutput = GetPropType<TypeTag, Properties::VelocityOutput>;
vtkWriter.addVelocityOutput(std::make_shared<VelocityOutput>(*gridVariables));
using IOFields = GetPropType<TypeTag, Properties::IOFields>;
IOFields::initOutputModule(vtkWriter); //!< Add model specific output fields
Katharina Heck's avatar
Katharina Heck committed
vtkWriter.write(0.0);
```

* Then, we need to assemble and solve the system. Depending on the problem, this can be done with a linear solver or a nonlinear solver.
If the problem is time dependent, we additionally need a time loop. An example for that is given in `exercise1pcmain.cc`:
Katharina Heck's avatar
Katharina Heck committed

```c++
Katharina Heck's avatar
Katharina Heck committed
// get some time loop parameters
Felix Weinhardt's avatar
Felix Weinhardt committed
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
Katharina Heck's avatar
Katharina Heck committed
auto tEnd = getParam<Scalar>("TimeLoop.TEnd");
auto dt = getParam<Scalar>("TimeLoop.DtInitial");
auto maxDt = getParam<Scalar>("TimeLoop.MaxTimeStepSize");
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
// instantiate time loop
auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(0.0, dt, tEnd);
timeLoop->setMaxTimeStepSize(maxDt);
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
// the assembler with time loop for instationary problem
using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
auto assembler = std::make_shared<Assembler>(problem, fvGridGeometry, gridVariables, timeLoop);
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
// the linear solver
using LinearSolver = ILU0BiCGSTABBackend;
auto linearSolver = std::make_shared<LinearSolver>();
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
// the non-linear solver
using NewtonSolver = Dumux::NewtonSolver<Assembler, LinearSolver>;
NewtonSolver nonLinearSolver(assembler, linearSolver);
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
// set some check points for the time loop
timeLoop->setPeriodicCheckPoint(tEnd/10.0);
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
// time loop
timeLoop->start(); do
{
    // set previous solution for storage evaluations
    assembler->setPreviousSolution(xOld);
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
    // linearize & solve
    nonLinearSolver.solve(x, *timeLoop);
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
    // make the new solution the old solution
    xOld = x;
    gridVariables->advanceTimeStep();
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
    // advance to the time loop to the next step
    timeLoop->advanceTimeStep();
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
    // write vtk output
    if (timeLoop->isCheckPoint())
        vtkWriter.write(timeLoop->time());
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
    // report statistics of this time step
    timeLoop->reportTimeStep();
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
    // set new dt as suggested by the newton solver
    timeLoop->setTimeStepSize(nonLinearSolver.suggestTimeStepSize(timeLoop->timeStepSize()));
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
} while (!timeLoop->finished());
Katharina Heck's avatar
Katharina Heck committed

Katharina Heck's avatar
Katharina Heck committed
timeLoop->finalize(leafGridView.comm());
Katharina Heck's avatar
Katharina Heck committed
```

<br><br><br>
Katharina Heck's avatar
Katharina Heck committed
### Task 2: Compiling and running an executable
<hr>

* Change to the build-directory

```bash
Katharina Heck's avatar
Katharina Heck committed
cd ../../build-cmake/exercises/exercise-mainfile
Katharina Heck's avatar
Katharina Heck committed
```

* Compile all three executables `exercise_mainfile_a` and `exercise_mainfile_b` and `exercise_mainfile_c`
Katharina Heck's avatar
Katharina Heck committed

```bash
make exercise_mainfile_a exercise_mainfile_b exercise_mainfile_c
Katharina Heck's avatar
Katharina Heck committed
```

* Execute the three problems and inspect the result

```bash
./exercise_mainfile_a
./exercise_mainfile_b
./exercise_mainfile_c
Katharina Heck's avatar
Katharina Heck committed
```

* You can look at the results (e.g. for the first example) with paraview:
Katharina Heck's avatar
Katharina Heck committed

```bash
paraview 1p_incompressible_stationary.pvd
Katharina Heck's avatar
Katharina Heck committed
```
Katharina Heck's avatar
Katharina Heck committed

<br><br><br>
Katharina Heck's avatar
Katharina Heck committed
### Task 3: Analytical differentiation
<hr>

In the input file `exercise_1p_a.input`, you will see that there is a variable `BaseEpsilon`.
This defines the base for the epsilon used in the numeric differentiation.
If that value is too small, you will see that the solution of the numeric differentiation is not correct.
Change that value to $`1 \cdot 10^{-15}`$ and have a look at the solution.
For the incompressible one phase problem, it is also possible to have an analytic solution method.
In this case, the epsilon does not play a role anymore, since the derivatives are calculated analytically.
To implement that, follow the tips in the `exercise1pamain.cc` and the `properties.hh` marked by:
Katharina Heck's avatar
Katharina Heck committed

```c++
// TODO: dumux-course-task 3
Katharina Heck's avatar
Katharina Heck committed
```
For the analytic solution of your immiscible problem, you need analytic solutions for the derivatives of the jacobian.
For that, we have a special local residual, the `OnePIncompressibleLocalResidual` which provides that.
You just need to include `incompressiblelocalresidual.hh` in your `properties.hh`
and use that instead of the `immisciblelocalresidual.hh` which is used as a default for all immiscible models.
Additionally, you need to set the differentiation method in the main file `exercise1pamain.cc` to analytic.