Skip to content

Commit 16ce778

Browse files
BenjaminRodenberguekermanMakisH
authored
Partitioned heat conduction with Schwarz-type domain decomposition (#381)
* Add heat equation Schwarz domain decomposition. * Apply suggestions from code review --------- Co-authored-by: Benjamin Uekermann <[email protected]> Co-authored-by: Gerasimos Chourdakis <[email protected]>
1 parent 2113377 commit 16ce778

14 files changed

+467
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
title: Partitioned heat conduction with overlapping Schwarz-type domain decomposition
3+
permalink: tutorials-partitioned-heat-conduction-overlap.html
4+
keywords: FEniCS, heat conduction, overlap
5+
summary: We solve a simple heat equation. The domain is partitioned and the coupling is established in an overlapping-Schwarz-type domain decomposition.
6+
---
7+
8+
{% note %}
9+
Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/partitioned-heat-conduction-overlap). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html).
10+
{% endnote %}
11+
12+
## Setup
13+
14+
We solve a partitioned heat equation, but apply an overlapping Schwarz-type domain decomposition method in this tutorial.
15+
16+
![Case setup of partitioned-heat-conduction case with overlapping Schwarz-type domain decomposition](images/tutorials-partitioned-heat-conduction-overlap-setup.png)
17+
18+
Note that this case applies an overlapping Schwarz-type coupling method and not (like most other tutorials in this repository) a Dirichlet-Neumann coupling. This results in a symmetric setup of the solvers.
19+
20+
## Running the simulation
21+
22+
This tutorial is for FEniCS.
23+
24+
For choosing whether you want to run the left or right participant, please provide the following commandline input:
25+
26+
* `python3 heat.py left` flag will run the left participant.
27+
* `python3 heat.py right` flag will run the right participant.
28+
29+
Like for the case `partitioned-heat-conduction` (using Dirichlet-Neumann coupling), we can also expect for the overlapping domain decomposition applied here to recover the analytical solution. `errorcomputation.py` checks this explicitly, by comparing the numerical to the analytical solution and raising an error, if the approximation error is not within a given tolerance.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../tools/clean-tutorial-base.sh
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
\documentclass{standalone}
2+
3+
\usepackage{tikz}
4+
\usetikzlibrary{fit,positioning,calc}
5+
6+
\usepackage{pgfplots}
7+
\pgfplotsset{
8+
compat=1.16,
9+
}
10+
\usepgfplotslibrary{external}
11+
\tikzexternalize[
12+
only named,
13+
]
14+
15+
\definecolor{pblue}{RGB}{0,102,189} % precice blue
16+
\definecolor{porange}{RGB}{243,98,33} % precice orange
17+
18+
% Make the 'export as png' a seperate style, with default density 200
19+
\tikzset{
20+
export as png/.style={
21+
external/system call/.add={}{
22+
&& convert -density #1 -transparent white "\image.pdf" "\image.png"
23+
},
24+
},
25+
export as png/.default={200},
26+
}
27+
28+
\begin{document}
29+
30+
\tikzset{export as png}
31+
\tikzsetnextfilename{tutorials-partitioned-heat-conduction-schwarz-setup}
32+
\begin{tikzpicture}
33+
\draw
34+
(0,0) coordinate (a)
35+
rectangle
36+
++(3,3) coordinate (b);
37+
\node[fill=pblue!50, draw=black, fit=(a) (b),inner sep=0pt] (participantL) {$\Omega_\mathcal{L}$};
38+
39+
\draw
40+
($(participantL.south east)+(2,0)$) coordinate (a)
41+
rectangle
42+
++(3,3) coordinate (b);
43+
\node[fill=porange!50, draw=black, fit=(a) (b),inner sep=0pt] (participantR) {$\Omega_\mathcal{R}$};
44+
45+
\draw
46+
($(participantL.south east)-(1,0)$) coordinate (a)
47+
rectangle
48+
($(participantL.north east)$) coordinate (b);
49+
\node[fill=porange!50,opacity=0.5, fit=(a) (b),inner sep=0pt] (overlapL){};
50+
51+
\draw
52+
($(participantR.south west)+(1,0)$) coordinate (a)
53+
rectangle
54+
($(participantR.north west)$) coordinate (b);
55+
\node[fill=pblue!50,opacity=0.5, fit=(a) (b),inner sep=0pt] (overlapR){};
56+
57+
\node[below = 0.5cm of participantR,xshift=-0.2cm](overlapLabel){Overlapping region: $\Omega_\mathcal{R}\cap\Omega_\mathcal{L}$};
58+
\draw[dashed] ([yshift=-.5cm]overlapL.center) -- (overlapLabel);
59+
\draw[dashed] ([yshift=-.5cm]overlapR.center) -- (overlapLabel);
60+
61+
\draw[very thick, pblue]($(participantL.south east)-(1,0)$) -- ($(participantL.north east)-(1,0)$);
62+
\draw[very thick, porange]($(participantR.south west)+(1,0)$) -- ($(participantR.north west)+(1,0)$);
63+
64+
\draw[very thick, porange](participantL.south east) -- node[right]{$\Gamma_\mathcal{R}$}($(participantL.north east)$);
65+
\draw[very thick, pblue](participantR.south west) -- node[left]{$\Gamma_\mathcal{L}$} ($(participantR.north west)$);
66+
67+
\node[left = 0cm of participantL,align=center] {Dirichlet solver $\mathcal{L}$\\ acts on left part $\Omega_\mathcal{L}$};
68+
\node[right = 0cm of participantR,align=center] {Dirichlet solver $\mathcal{R}$\\ acts on right part $\Omega_\mathcal{R}$};
69+
70+
\draw[->]($(participantR.north west)+(1,0)$) to[out=150,in=30] node[above right,align=center]{Temperature $u$ on $\Gamma_\mathcal{R}$ for $\mathcal{L}$} (participantL.north east);
71+
\draw[->]($(participantL.north east)-(1,0)$) to[out=30,in=150] node[above left,align=center]{Temperature $u$ on $\Gamma_\mathcal{L}$ for $\mathcal{R}$} (participantR.north west);
72+
73+
\draw[draw=none] (participantL.south east) -- node[below]{$\Gamma_D$} (participantL.south west);
74+
\draw[draw=none] (participantR.south east) -- node[below]{$\Gamma_D$} (participantR.south west);
75+
\end{tikzpicture}
76+
77+
\end{document}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
set -e -u
3+
4+
. ../../tools/cleaning-tools.sh
5+
6+
clean_fenics .
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"participant_name": "Left",
3+
"config_file_name": "../precice-config.xml",
4+
"interface": {
5+
"coupling_mesh_name": "Left-Mesh",
6+
"write_data_name": "Temperature-Left",
7+
"read_data_name": "Temperature-Right"
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
set -e -u
3+
4+
python3 ../solver-fenics/heat.py Left
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<precice-configuration>
3+
<log>
4+
<sink
5+
filter="%Severity% > debug and %Rank% = 0"
6+
format="---[precice] %ColorizedSeverity% %Message%"
7+
enabled="true" />
8+
</log>
9+
10+
<data:scalar name="Temperature-Left" />
11+
<data:scalar name="Temperature-Right" />
12+
13+
<mesh name="Left-Mesh" dimensions="2">
14+
<use-data name="Temperature-Left" />
15+
<use-data name="Temperature-Right" />
16+
</mesh>
17+
18+
<mesh name="Right-Mesh" dimensions="2">
19+
<use-data name="Temperature-Left" />
20+
<use-data name="Temperature-Right" />
21+
</mesh>
22+
23+
<participant name="Left">
24+
<provide-mesh name="Left-Mesh" />
25+
<receive-mesh name="Right-Mesh" from="Right" />
26+
<write-data name="Temperature-Left" mesh="Left-Mesh" />
27+
<read-data name="Temperature-Right" mesh="Left-Mesh" />
28+
<mapping:nearest-neighbor
29+
direction="read"
30+
from="Right-Mesh"
31+
to="Left-Mesh"
32+
constraint="consistent" />
33+
</participant>
34+
35+
<participant name="Right">
36+
<provide-mesh name="Right-Mesh" />
37+
<receive-mesh name="Left-Mesh" from="Left" />
38+
<write-data name="Temperature-Right" mesh="Right-Mesh" />
39+
<read-data name="Temperature-Left" mesh="Right-Mesh" />
40+
<mapping:nearest-neighbor
41+
direction="read"
42+
from="Left-Mesh"
43+
to="Right-Mesh"
44+
constraint="consistent" />
45+
</participant>
46+
47+
<m2n:sockets acceptor="Left" connector="Right" exchange-directory=".." />
48+
49+
<coupling-scheme:serial-implicit>
50+
<participants first="Left" second="Right" />
51+
<max-time value="1.0" />
52+
<time-window-size value="0.1" />
53+
<max-iterations value="100" />
54+
<exchange data="Temperature-Left" mesh="Left-Mesh" from="Left" to="Right" initialize="true" />
55+
<exchange data="Temperature-Right" mesh="Right-Mesh" from="Right" to="Left" initialize="true" />
56+
<relative-convergence-measure data="Temperature-Left" mesh="Left-Mesh" limit="1e-5" />
57+
<relative-convergence-measure data="Temperature-Right" mesh="Right-Mesh" limit="1e-5" />
58+
<acceleration:IQN-ILS>
59+
<data name="Temperature-Right" mesh="Right-Mesh" />
60+
<initial-relaxation value="0.1" />
61+
<max-used-iterations value="100" />
62+
<time-windows-reused value="5" />
63+
<filter type="QR2" limit="1e-3" />
64+
</acceleration:IQN-ILS>
65+
</coupling-scheme:serial-implicit>
66+
</precice-configuration>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
set -e -u
3+
4+
. ../../tools/cleaning-tools.sh
5+
6+
clean_fenics .
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"participant_name": "Right",
3+
"config_file_name": "../precice-config.xml",
4+
"interface": {
5+
"coupling_mesh_name": "Right-Mesh",
6+
"write_data_name": "Temperature-Right",
7+
"read_data_name": "Temperature-Left"
8+
}
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
set -e -u
3+
4+
python3 ../solver-fenics/heat.py Right
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from fenics import inner, assemble, dx, project, sqrt
2+
3+
4+
def compute_errors(u_approx, u_ref, v, total_error_tol=10 ** -4):
5+
# compute pointwise L2 error
6+
error_normalized = (u_ref - u_approx) / u_ref
7+
# project onto function space
8+
error_pointwise = project(abs(error_normalized), v)
9+
# determine L2 norm to estimate total error
10+
error_total = sqrt(assemble(inner(error_pointwise, error_pointwise) * dx))
11+
error_pointwise.rename("error", " ")
12+
13+
assert (error_total < total_error_tol)
14+
15+
return error_total, error_pointwise

0 commit comments

Comments
 (0)