Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
---
title: Models in DuMux
---
# Implementing a new DuMu<sup>X</sup> model
## What is a DuMu<sup>X</sup> model
A DuMu<sup>X</sup> model is an implementation of a **mathematical model**, generally given by partial differential equations, by using **discretization** schemes.
## What is a DuMu<sup>X</sup> model
Mathematical model (PDE):
$\begin{equation*}
\small
\frac{\partial S(u)}{\partial t} + \nabla \cdot \mathbf{F}(u) = q, \quad \forall (t,\mathbf{x}) \in (0,T] \times \Omega
\end{equation*}$
<img src=img/model_domain_discretization.png width="100%">
Discrete model, e.g. using finite volumes:
$\begin{equation*}
\small
|B| \frac{S_h(\mathbf{u}^{n+1}_h) - S_h(\mathbf{u}^{n}_h)}{\Delta t} + \sum_{\sigma \in \Sigma_B} F_{B,\sigma}(\mathbf{u}^{n+1}_h) = \int_{B} q^{n+1} \, dx, \quad \forall t_{n+1}\leq T, \; \forall B
\end{equation*}$
## What is a DuMu<sup>X</sup> model
Discrete model, e.g. using finite volumes:
$\begin{equation*}
\small
|B| \frac{S_h(\mathbf{u}^{n+1}_h) - S_h(\mathbf{u}^{n}_h)}{\Delta t} + \sum_{\sigma \in \Sigma_B} F_{B,\sigma}(\mathbf{u}^{n+1}_h) = \int_{B} q \, dx, \quad \forall t_{n+1}\leq T, \; \forall B
\end{equation*}$
* $S_h$: storage calculation
* $F_{B,\sigma}$: flux over sub control volume face
* $q$ source term
How to implement these terms in DuMu<sup>X</sup>?
**local residual**
# Local Residual
## Local Residual
Implements these terms within
* `computeStorage(...)`
* `computeFlux(...)`
* `computeSource(...)`
## Example: Diffusion equation
Mathematical model (PDE):
$\begin{equation}
\frac{\partial c}{\partial t} - \nabla \cdot (D \nabla c) = 0 \:\: \mathrm{in}\; \Omega \times (0,T] \\
\end{equation}$
with
$\begin{aligned}
c: &\:\text{concentration} \\
D: &\:\text{constant diffusion coefficient} \\
\Omega: &\:\text{spatial domain} \\
T: &\:\text{end time}
\end{aligned}$
## Example: Diffusion equation
Discrete model using the Box discretization:
$\begin{equation}
\vert B \vert \frac{c_B^{n+1}-c_B^{n}}{\Delta t} - \sum_{\sigma \in \Sigma_{B}} \left[ D \nabla c_h^{n+1} \cdot \boldsymbol{n}_{B,\sigma} \vert \sigma \vert \right] = 0,
\end{equation}$
with
$\begin{aligned}
c_B^n: &\:\text{concentration at time $t_n$ and control volume $B$} \\
c_h: &\:\text{global discrete solution, interpolation using \textbf{basis functions}} \\
\mathbf{n}: &\:\text{unit outer normal vector} \\
\sigma: &\:\text{sub control volume face} \\
\end{aligned}$
## Local residual
The local residual of the diffusion model:
```cpp
namespace Dumux {
template<class TypeTag>
class DiffusionModelLocalResidual
: public GetPropType<TypeTag, Properties::BaseLocalResidual>
{
```
## Local residual
```cpp
namespace Dumux {
template<class TypeTag>
class DiffusionModelLocalResidual
: public GetPropType<TypeTag, Properties::BaseLocalResidual>
{
```
Our class inherits from the class `BaseLocalResidual`, which has to be chosen depending on the discretization scheme, here *Box scheme*.
## Storage term
```cpp
NumEqVector computeStorage(const Problem& problem,
const SubControlVolume& scv,
const VolumeVariables& volVars) const
{
NumEqVector storage;
storage[Indices::massBalanceEqIdx]
= volVars.priVar(Indices::concentrationIdx);
return storage;
}
```
## Flux term
$\begin{equation}
F_{B,\sigma} = -D \nabla c_h^{n+1} \cdot \boldsymbol{n}_{B,\sigma} \vert \sigma \vert
\end{equation}$
with
$\begin{aligned}
c_h: &\:\text{discrete solution, interpolated using basis functions} \\
\sigma: &\:\text{sub control volume face} \\
\end{aligned}$
## Flux term
Implementation takes place in the dedicated function `computeFlux`:
```cpp
NumEqVector computeFlux(const Problem& problem,
const Element& element,
const FVElementGeometry& fvGeometry,
const ElementVolumeVariables& elemVolVars,
const SubControlVolumeFace& scvf,
const ElementFluxVariablesCache& elemFluxVarsCache) const
{
...
```
## Flux term
Implementation takes place in the dedicated function `computeFlux`:
```cpp
NumEqVector computeFlux(...) const
{
// Compute ∇c
const auto& fluxVarCache = elemFluxVarsCache[scvf];
Dune::FieldVector<Scalar, dimWorld> gradConcentration(0.0);
for (const auto& scv : scvs(fvGeometry))
{
const auto& volVars = elemVolVars[scv];
gradConcentration.axpy(
volVars.priVar(Indices::concentrationIdx),
fluxVarCache.gradN(scv.indexInElement())
);
}
...
}
```
## Flux term
Implementation takes place in the dedicated function `computeFlux`:
```cpp
NumEqVector computeFlux(...) const
{
...
NumEqVector flux;
// Compute the flux
flux[Indices::massBalanceEqIdx] = -1.0*vtmv(
scvf.unitOuterNormal(), problem.diffusionCoefficient(), gradConcentration
)*scvf.area();
return flux;
}
```
## Local Residual
A *local residual* implements the discretized mathematical model.
For its implementation different model-specific properties have to be set
# Model properties
## Model type tag
The property tag is an empty struct with the respective name, e.g. `DiffusionModel`
```cpp
namespace Dumux::Properties::TTag {
//! The diffusion model tag that we can specialize properties for
struct DiffusionModel {};
} // end namespace Dumux::Properties::TTag
```
## Model properties
By specializing properties for the type tag `DiffusionModel`, every other class that knows about the type tag (this will be for example the assembler or the problem), can extract the type information that we specify here.
All properties are defined within the namespace `Dumux::Properties`
```cpp
namespace Dumux::Properties {
//define all properties
} // end namespace Dumux::Properties
```
## Defining model properties
The type of the local residual is the class `DiffusionModelLocalResidual` defined from earlier
```cpp
template<class TypeTag>
struct LocalResidual<TypeTag, TTag::DiffusionModel>
{ using type = DiffusionModelLocalResidual<TypeTag>; };
```
## Defining model properties
The model traits specify information about the model:
```cpp
template<class TypeTag>
struct ModelTraits<TypeTag, TTag::DiffusionModel>
{
struct type
{
struct Indices
{
static constexpr int concentrationIdx = 0;
static constexpr int massBalanceEqIdx = 0;
};
static constexpr int numEq() { return 1; }
};
};
```
## Defining model properties
Further model specific properties can be set accordingly by using the model property tag,
i.e. `TTag::DiffusionModel`
# Exercise: Model
## Exercise: Model
Implementation of a **nonlinear diffusion model**
<figure>
<center>
<img src="../exercises/extradoc/exercisemodel_mri_denoise.gif" alt="denoising"/>
<figcaption> Denosing of MRI image using nonlinear diffusion model.</figcaption>
</center>
</figure>
## Tasks
- Implement local residual
- Set model properties
- Use model in test case
- Customize volume variables