Skip to content
Snippets Groups Projects
Commit cbf94508 authored by Martin Schneider's avatar Martin Schneider Committed by Leon Keim
Browse files

[ex][model] Update Model exercise

[ex][model] Add more definitions to doc

[ex][model] Allow to directly uncomment whole section

[ex][model] Cleanup CMakeLists

[ex][model] Update patch
parent 10da0ed3
No related branches found
No related tags found
1 merge request!241[ex][model] Update doc
diff -ruN exercises/exercise-model/CMakeLists.txt exercises/solution/exercise-model/CMakeLists.txt
--- exercises/exercise-model/CMakeLists.txt 2024-05-21 14:15:07.153554813 +0200
+++ exercises/solution/exercise-model/CMakeLists.txt 2024-05-21 14:15:07.213555107 +0200
--- exercises/exercise-model/CMakeLists.txt 2024-07-12 09:11:32.256227192 +0200
+++ exercises/solution/exercise-model/CMakeLists.txt 2024-07-12 09:11:32.264227248 +0200
@@ -1,4 +1,4 @@
-set(CMAKE_BUILD_TYPE Release)
dune_symlink_to_source_files(FILES images params.input)
-dumux_add_test(NAME exercise_nonlineardiffusion
+
+dumux_add_test(NAME exercise_nonlineardiffusion_sol
SOURCES main.cc)
diff -ruN exercises/exercise-model/main.cc exercises/solution/exercise-model/main.cc
--- exercises/exercise-model/main.cc 2024-05-29 14:31:49.247625156 +0200
+++ exercises/solution/exercise-model/main.cc 2024-05-21 14:15:07.213555107 +0200
--- exercises/exercise-model/main.cc 2024-07-12 09:11:32.256227192 +0200
+++ exercises/solution/exercise-model/main.cc 2024-07-12 09:11:32.264227248 +0200
@@ -41,6 +41,8 @@
#include <dumux/nonlinear/newtonsolver.hh>
#include <dumux/assembly/fvassembler.hh>
......@@ -38,11 +37,51 @@ diff -ruN exercises/exercise-model/main.cc exercises/solution/exercise-model/mai
- // using Problem = GetPropType<TypeTag, Properties::Problem>;
- // using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
- // using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
- //
-
- // auto problem = std::make_shared<Problem>(gridGeometry);
- // auto sol = createInitialSolution<SolutionVector>(*gridGeometry, imageData);
- // auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
- // gridVariables->init(sol);
-
- // // We initialize the VTK output module and write out the initial concentration field
- // VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, sol, problem->name());
- // vtkWriter.addVolumeVariable([](const auto& vv){ return vv.priVar(0); }, "imageIntensity");
- // vtkWriter.write(0.0);
-
- // // We instantiate time loop using start and end time as well as
- // // the time step size from the parameter tree (`params.input`)
- // auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(
- // getParam<Scalar>("TimeLoop.TStart", 0.0),
- // getParam<Scalar>("TimeLoop.Dt"),
- // getParam<Scalar>("TimeLoop.TEnd")
- // );
-
- // // Next, we choose the type of assembler, linear solver and nonlinear solver
- // // and construct instances of these classes.
- // using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
- // using LinearSolver = SSORCGIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
- // using Solver = Dumux::NewtonSolver<Assembler, LinearSolver>;
-
- // auto oldSol = sol; // copy the vector to store state of previous time step
- // auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables, timeLoop, oldSol);
- // auto linearSolver = std::make_shared<LinearSolver>(gridGeometry->gridView(), gridGeometry->dofMapper());
- // Solver solver(assembler, linearSolver);
-
- // // time loop
- // timeLoop->start(); do
- // {
- // // assemble & solve
- // solver.solve(sol);
-
- // // make the new solution the old solution
- // oldSol = sol;
- // gridVariables->advanceTimeStep();
-
- // // advance to the time loop to the next step
- // timeLoop->advanceTimeStep();
-
- // // write VTK output (writes out the concentration field)
- // vtkWriter.write(timeLoop->time());
+ using Scalar = GetPropType<TypeTag, Properties::Scalar>;
+ using Problem = GetPropType<TypeTag, Properties::Problem>;
+ using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
......@@ -52,33 +91,22 @@ diff -ruN exercises/exercise-model/main.cc exercises/solution/exercise-model/mai
+ auto sol = createInitialSolution<SolutionVector>(*gridGeometry, imageData);
+ auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
+ gridVariables->init(sol);
// We initialize the VTK output module and write out the initial concentration field
- // VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, sol, problem->name());
- // vtkWriter.addVolumeVariable([](const auto& vv){ return vv.priVar(0); }, "imageIntensity");
- // vtkWriter.write(0.0);
+
+ // We initialize the VTK output module and write out the initial concentration field
+ VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, sol, problem->name());
+ vtkWriter.addVolumeVariable([](const auto& vv){ return vv.imageIntensity(); }, "imageIntensity");
+ vtkWriter.write(0.0);
// We instantiate time loop using start and end time as well as
// the time step size from the parameter tree (`params.input`)
- // auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(
- // getParam<Scalar>("TimeLoop.TStart", 0.0),
- // getParam<Scalar>("TimeLoop.Dt"),
- // getParam<Scalar>("TimeLoop.TEnd")
- // );
+
+ // We instantiate time loop using start and end time as well as
+ // the time step size from the parameter tree (`params.input`)
+ auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(
+ getParam<Scalar>("TimeLoop.TStart", 0.0),
+ getParam<Scalar>("TimeLoop.Dt"),
+ getParam<Scalar>("TimeLoop.TEnd")
+ );
// Next, we choose the type of assembler, linear solver and nonlinear solver
// and construct instances of these classes.
- // using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
- // using LinearSolver = SSORCGIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
- // using Solver = Dumux::NewtonSolver<Assembler, LinearSolver>;
+
+ // Next, we choose the type of assembler, linear solver and nonlinear solver
+ // and construct instances of these classes.
+ using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
+ using LinearSolver = SSORCGIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
+ using Solver = Dumux::NewtonSolver<Assembler, LinearSolver>;
......@@ -87,37 +115,20 @@ diff -ruN exercises/exercise-model/main.cc exercises/solution/exercise-model/mai
+ auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables, timeLoop, oldSol);
+ auto linearSolver = std::make_shared<LinearSolver>(gridGeometry->gridView(), gridGeometry->dofMapper());
+ Solver solver(assembler, linearSolver);
- // auto oldSol = sol; // copy the vector to store state of previous time step
- // auto assembler = std::make_shared<Assembler>(problem, gridGeometry, gridVariables, timeLoop, oldSol);
- // auto linearSolver = std::make_shared<LinearSolver>(gridGeometry->gridView(), gridGeometry->dofMapper());
- // Solver solver(assembler, linearSolver);
-
- // // time loop
- // timeLoop->start(); do
- // {
- // // assemble & solve
- // solver.solve(sol);
+
+ // time loop
+ timeLoop->start(); do
+ {
+ // assemble & solve
+ solver.solve(sol);
- // // make the new solution the old solution
- // oldSol = sol;
- // gridVariables->advanceTimeStep();
+
+ // make the new solution the old solution
+ oldSol = sol;
+ gridVariables->advanceTimeStep();
- // // advance to the time loop to the next step
- // timeLoop->advanceTimeStep();
+
+ // advance to the time loop to the next step
+ timeLoop->advanceTimeStep();
- // // write VTK output (writes out the concentration field)
- // vtkWriter.write(timeLoop->time());
+
+ // write VTK output (writes out the concentration field)
+ vtkWriter.write(timeLoop->time());
......@@ -136,7 +147,7 @@ diff -ruN exercises/exercise-model/main.cc exercises/solution/exercise-model/mai
}// end main
diff -ruN exercises/exercise-model/model.hh exercises/solution/exercise-model/model.hh
--- exercises/exercise-model/model.hh 1970-01-01 01:00:00.000000000 +0100
+++ exercises/solution/exercise-model/model.hh 2024-05-21 14:15:07.213555107 +0200
+++ exercises/solution/exercise-model/model.hh 2024-07-12 09:11:32.264227248 +0200
@@ -0,0 +1,222 @@
+// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+// vi: set et ts=4 sw=4 sts=4:
......@@ -361,9 +372,9 @@ diff -ruN exercises/exercise-model/model.hh exercises/solution/exercise-model/mo
+
+#endif
diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/README.md
--- exercises/exercise-model/README.md 2024-05-21 14:15:07.153554813 +0200
--- exercises/exercise-model/README.md 2024-07-12 09:11:32.256227192 +0200
+++ exercises/solution/exercise-model/README.md 1970-01-01 01:00:00.000000000 +0100
@@ -1,208 +0,0 @@
@@ -1,195 +0,0 @@
-# Exercise Model (DuMuX course)
-The aim of this exercise is it to learn how to set up a new model (new system of equations).
-As an example, we implement a nonlinear diffusion equation model and apply it for image denoising.
......@@ -373,7 +384,7 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
-
-## Equation and Problem set-up
-
-We consider a nonlinear diffusion equation on a domain $\Omega \subset \mathbb{R}^2$ and time interval $(0,T]$ with boundary $\partial\Omega$ given by
-We consider a nonlinear diffusion equation on a domain $\Omega \subset \mathbb{R}^2$, with boundary $\partial\Omega$, and time interval $(0,T]$ given by
-
-```math
-\begin{aligned}
......@@ -382,25 +393,20 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
- c &= c^0 && \mathrm{for}\; t = 0,
-\end{aligned}
-```
-where for a position $\mathbf{x} \in \Omega$ and time $t$, $c(\mathbf{x},t)$ denotes the unknown evolving concentration field and $D(c)$ the solution-dependent diffusion coefficient.
-where for a position $\mathbf{x} \in \Omega$ and time $t$, $c(\mathbf{x},t)$ denotes the unknown evolving concentration field, $D(c)$ the solution-dependent diffusion coefficient, and $c^0$ the initial concentration field.
-
-In this exercise we want to model image denoising such that the primary variable $c$ corresponds to the **image intensity** and $D$ is given (due to Perona & Malik), as
-In this exercise we want to model image denoising such that the primary variable $c$ corresponds to the **image intensity**, $c^0$ to the noisy image data, and $D$ is given (due to Perona & Malik), as
-```math
-D(c) = \frac{1}{1 + \left(\frac{|| \nabla c ||}{K}\right)^2},
-```
-with conductance $K$.
-
-<br><br>
-## Task 1: Getting familiar with the diffusion example
-<hr>
-
-When implementing a new model it is advisable to built upon an already existing model that might be similar and only needs modifications. Since the above equation is a nonlinear diffusion equation, we can built upon the diffusion model implemented in the [diffusion example](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/tree/master/examples/diffusion).
-The diffusion example also derives the discrete equations using the Box method as spatial discretization scheme.
-<hr>
-
-<br><br>
-## Task 2: Set up the model
-<hr>
-
-:arrow_right: Copy the `model.hh` file from the diffusion example into `dumux-course/exercises/exercise-model` and choose appropriate class names.
-
......@@ -428,9 +434,7 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
-} // end namespace Dumux::Properties
-```
-
-<br><br>
-## Task 3: Set up the test case
-<hr>
-
-:arrow_right: Open the file `main.cc`.
-
......@@ -451,7 +455,7 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
-
-:arrow_right: Include the header `model.hh` <br>
-:arrow_right: To use the new model for this test case, make
-the test type tag inherit properties from the model type tag
-the `NonlinearDiffusionTest` type tag inherit properties from the model type tag
-
-```c++
-namespace Dumux::Properties::TTag {
......@@ -487,11 +491,9 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
-
-:arrow_right: Fix any compiler errors and warnings.
-
-<br><br>
-## Task 4: Nonlinear diffusion
-<hr>
-
-In the local residual class, instead of using a constant `1.0`, we now
-In the local residual class, instead of using a constant diffusion coefficient of `1.0`, we now
-want to implement the nonlinear diffusion function specified above. With a `Dune::FieldVector`
-you can get the 2-norm of the vector via `v.two_norm()` and its square with `v.two_norm2()`. (The reason
-for having two different interfaces is that the second one is more efficient.)
......@@ -507,9 +509,7 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
-the derivatives of your residual by hand and implement them. This greatly simplifies implementing
-nonlinear equations.
-
-<br><br>
-## Task 5: Running the image denosing test case
-<hr>
-
-:arrow_right: Compile and run like above.
-
......@@ -525,11 +525,9 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
- </center>
-</figure>
-
-<br><br>
-## Task 6: Custom volume variables
-<hr>
-
-The volume variables represent variables of the control volume. So far we have used
-The volume variables represent variables related to control volumes. So far we have used
-the `BasicVolumeVariables` class that only stores the primary variables at control volumes.
-We have used the interface `priVar` to access the primary variables. In more complex models,
-we often want to
......@@ -541,7 +539,7 @@ diff -ruN exercises/exercise-model/README.md exercises/solution/exercise-model/R
-
-:arrow_right: Implement your own `ImageDenoisingVolumeVariables` class (either within a new header file or directly in `model.hh`). As basis you can use the `BasicVolumeVariables`, see `dumux/common/volumevariables.hh`. Copy the class into `model.hh` and rename it.
-
-<br> Add a function `imageIntensity()` that returns the first primary variable. <br>
-:arrow_right: Add a function `imageIntensity()` that returns the first primary variable.
-
-:arrow_right: In order to use the new `ImageDenoisingVolumeVariables` class in your model, set in your model-specific properties (see `dumux-course/exercises/exercise-properties`):
-```c++
......
set(CMAKE_BUILD_TYPE Release)
dune_symlink_to_source_files(FILES images params.input)
dumux_add_test(NAME exercise_nonlineardiffusion
SOURCES main.cc)
......@@ -7,7 +7,7 @@ and solve such a problem with DuMux. We also implement the model for a specific
## Equation and Problem set-up
We consider a nonlinear diffusion equation on a domain $\Omega \subset \mathbb{R}^2$ and time interval $(0,T]$ with boundary $\partial\Omega$ given by
We consider a nonlinear diffusion equation on a domain $\Omega \subset \mathbb{R}^2$, with boundary $\partial\Omega$, and time interval $(0,T]$ given by
```math
\begin{aligned}
......@@ -16,25 +16,20 @@ We consider a nonlinear diffusion equation on a domain $\Omega \subset \mathbb{R
c &= c^0 && \mathrm{for}\; t = 0,
\end{aligned}
```
where for a position $\mathbf{x} \in \Omega$ and time $t$, $c(\mathbf{x},t)$ denotes the unknown evolving concentration field and $D(c)$ the solution-dependent diffusion coefficient.
where for a position $\mathbf{x} \in \Omega$ and time $t$, $c(\mathbf{x},t)$ denotes the unknown evolving concentration field, $D(c)$ the solution-dependent diffusion coefficient, and $c^0$ the initial concentration field.
In this exercise we want to model image denoising such that the primary variable $c$ corresponds to the **image intensity** and $D$ is given (due to Perona & Malik), as
In this exercise we want to model image denoising such that the primary variable $c$ corresponds to the **image intensity**, $c^0$ to the noisy image data, and $D$ is given (due to Perona & Malik), as
```math
D(c) = \frac{1}{1 + \left(\frac{|| \nabla c ||}{K}\right)^2},
```
with conductance $K$.
<br><br>
## Task 1: Getting familiar with the diffusion example
<hr>
When implementing a new model it is advisable to built upon an already existing model that might be similar and only needs modifications. Since the above equation is a nonlinear diffusion equation, we can built upon the diffusion model implemented in the [diffusion example](https://git.iws.uni-stuttgart.de/dumux-repositories/dumux/-/tree/master/examples/diffusion).
The diffusion example also derives the discrete equations using the Box method as spatial discretization scheme.
<hr>
<br><br>
## Task 2: Set up the model
<hr>
:arrow_right: Copy the `model.hh` file from the diffusion example into `dumux-course/exercises/exercise-model` and choose appropriate class names.
......@@ -62,9 +57,7 @@ namespace Dumux::Properties {
} // end namespace Dumux::Properties
```
<br><br>
## Task 3: Set up the test case
<hr>
:arrow_right: Open the file `main.cc`.
......@@ -85,7 +78,7 @@ const auto imageData = NetPBMReader::readPGM(imageFileName);
:arrow_right: Include the header `model.hh` <br>
:arrow_right: To use the new model for this test case, make
the test type tag inherit properties from the model type tag
the `NonlinearDiffusionTest` type tag inherit properties from the model type tag
```c++
namespace Dumux::Properties::TTag {
......@@ -121,11 +114,9 @@ make exercise_nonlineardiffusion
:arrow_right: Fix any compiler errors and warnings.
<br><br>
## Task 4: Nonlinear diffusion
<hr>
In the local residual class, instead of using a constant `1.0`, we now
In the local residual class, instead of using a constant diffusion coefficient of `1.0`, we now
want to implement the nonlinear diffusion function specified above. With a `Dune::FieldVector`
you can get the 2-norm of the vector via `v.two_norm()` and its square with `v.two_norm2()`. (The reason
for having two different interfaces is that the second one is more efficient.)
......@@ -141,9 +132,7 @@ As the DuMux assembler uses numeric differentiation to approximate the Jacobian
the derivatives of your residual by hand and implement them. This greatly simplifies implementing
nonlinear equations.
<br><br>
## Task 5: Running the image denosing test case
<hr>
:arrow_right: Compile and run like above.
......@@ -159,11 +148,9 @@ __The final result should look like this:__
</center>
</figure>
<br><br>
## Task 6: Custom volume variables
<hr>
The volume variables represent variables of the control volume. So far we have used
The volume variables represent variables related to control volumes. So far we have used
the `BasicVolumeVariables` class that only stores the primary variables at control volumes.
We have used the interface `priVar` to access the primary variables. In more complex models,
we often want to
......@@ -175,7 +162,7 @@ In this task we will implement a custom volume variable class, while in this sim
:arrow_right: Implement your own `ImageDenoisingVolumeVariables` class (either within a new header file or directly in `model.hh`). As basis you can use the `BasicVolumeVariables`, see `dumux/common/volumevariables.hh`. Copy the class into `model.hh` and rename it.
<br> Add a function `imageIntensity()` that returns the first primary variable. <br>
:arrow_right: Add a function `imageIntensity()` that returns the first primary variable.
:arrow_right: In order to use the new `ImageDenoisingVolumeVariables` class in your model, set in your model-specific properties (see `dumux-course/exercises/exercise-properties`):
```c++
......
......@@ -153,27 +153,27 @@ int main(int argc, char** argv)
// using Problem = GetPropType<TypeTag, Properties::Problem>;
// using SolutionVector = GetPropType<TypeTag, Properties::SolutionVector>;
// using GridVariables = GetPropType<TypeTag, Properties::GridVariables>;
//
// auto problem = std::make_shared<Problem>(gridGeometry);
// auto sol = createInitialSolution<SolutionVector>(*gridGeometry, imageData);
// auto gridVariables = std::make_shared<GridVariables>(problem, gridGeometry);
// gridVariables->init(sol);
// We initialize the VTK output module and write out the initial concentration field
// // We initialize the VTK output module and write out the initial concentration field
// VtkOutputModule<GridVariables, SolutionVector> vtkWriter(*gridVariables, sol, problem->name());
// vtkWriter.addVolumeVariable([](const auto& vv){ return vv.priVar(0); }, "imageIntensity");
// vtkWriter.write(0.0);
// We instantiate time loop using start and end time as well as
// the time step size from the parameter tree (`params.input`)
// // We instantiate time loop using start and end time as well as
// // the time step size from the parameter tree (`params.input`)
// auto timeLoop = std::make_shared<CheckPointTimeLoop<Scalar>>(
// getParam<Scalar>("TimeLoop.TStart", 0.0),
// getParam<Scalar>("TimeLoop.Dt"),
// getParam<Scalar>("TimeLoop.TEnd")
// );
// Next, we choose the type of assembler, linear solver and nonlinear solver
// and construct instances of these classes.
// // Next, we choose the type of assembler, linear solver and nonlinear solver
// // and construct instances of these classes.
// using Assembler = FVAssembler<TypeTag, DiffMethod::numeric>;
// using LinearSolver = SSORCGIstlSolver<LinearSolverTraits<GridGeometry>, LinearAlgebraTraitsFromAssembler<Assembler>>;
// using Solver = Dumux::NewtonSolver<Assembler, LinearSolver>;
......
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