Skip to content

Commit 0e6a155

Browse files
Add tutorial: partitioned oscillator (#297)
* Tutorial illustrates a simple case which can be used for convergence studies and waveforms * Case is taken from V. Schüller, B. Rodenberg, B. Uekermann and H. Bungartz, A Simple Test Case for Convergence Order in Time and Energy Conservation of Black-Box Coupling Schemes, in: WCCM-APCOM2022. URL https://www.scipedia.com/public/Rodenberg_2022a Co-authored-by: Benjamin Uekermann <[email protected]>
1 parent ccd0cbd commit 0e6a155

12 files changed

+500
-0
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
88

99
## [Unreleased]
1010

11+
### Added
12+
13+
- Added new oscillator tutorial with Python [#297](https://github.com/precice/tutorials/pull/297).
14+
1115
## [v202202.0] 2022-02-09
1216

1317
### Added

oscillator/README.md

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
title: Oscillator
3+
permalink: tutorials-oscillator.html
4+
keywords: Python, ODE
5+
summary: We solve an oscillator with two masses in a partitioned fashion. Each mass is solved by an independent ODE.
6+
---
7+
8+
{% note %}
9+
Get the [case files of this tutorial](https://github.com/precice/tutorials/tree/master/oscillator). Read how in the [tutorials introduction](https://www.precice.org/tutorials.html).
10+
{% endnote %}
11+
12+
## Setup
13+
14+
This tutorial solves a simple mass-spring oscillator with two masses and three springs. The system is cut at the middle spring and solved in a partitioned fashion:
15+
16+
![Schematic drawing of oscillator example](images/tutorials-oscillator-schematic-drawing.png)
17+
18+
Note that this case applies a 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. We will refer to the solver computing the trajectory of $m_1$ as `Mass-Left` and to the solver computing the trajectory of $m_2$ as `Mass-Right`. For more information, please refer to [1].
19+
20+
## Available solvers
21+
22+
This tutorial is only available in Python. You need to have preCICE and the Python bindings installed on your system.
23+
24+
- *Python*: An example solver using the preCICE [Python bindings](https://www.precice.org/installation-bindings-python.html). This solver also depends on the Python libraries `numpy`, which you can get from your system package manager or with `pip3 install --user <package>`.
25+
26+
## Running the Simulation
27+
28+
### Python
29+
30+
Open two separate terminals and start both participants by calling:
31+
32+
```bash
33+
cd python
34+
./run.sh -m
35+
```
36+
37+
and
38+
39+
```bash
40+
cd python
41+
./run.sh -n
42+
```
43+
44+
## Post-processing
45+
46+
Each simulation run creates two files containing position and velocity of the two masses over time. These files are called `trajectory-Mass-Left.csv` and `trajectory-Mass-Right.csv`. You can use the script `plot-trajectory.py` for post-processing. Type `python3 plot-trajectory --help` to see available options. You can, for example plot the trajectory by running
47+
48+
```bash
49+
python3 plot-trajectory.py python/output/trajectory-Mass-Left.csv TRAJECTORY
50+
```
51+
52+
This allows you to study the effect of different time stepping schemes on energy conservation. Newmark beta conserves energy:
53+
54+
![Trajectory for Newmark beta scheme](images/tutorials-oscillator-trajectory-newmark-beta.png)
55+
56+
Generalized alpha does not conserve energy:
57+
58+
![Trajectory for generalized alpha scheme](images/tutorials-oscillator-trajectory-generalized-alpha.png)
59+
60+
For details, refer to [1].
61+
62+
## References
63+
64+
[1] V. Schüller, B. Rodenberg, B. Uekermann and H. Bungartz, A Simple Test Case for Convergence Order in Time and Energy Conservation of Black-Box Coupling Schemes, in: WCCM-APCOM2022. [URL](https://www.scipedia.com/public/Rodenberg_2022a)

oscillator/clean-tutorial.sh

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../tools/clean-tutorial-base.sh
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
\documentclass{standalone}
2+
\usepackage{tikz}
3+
\usetikzlibrary{patterns,decorations.pathmorphing}
4+
5+
\definecolor{color1}{HTML}{008b8b}
6+
\definecolor{color2}{HTML}{808000}
7+
\begin{document}
8+
\begin{tikzpicture}
9+
% left wall
10+
\fill [pattern = north west lines] (0,0) rectangle ++(.2,3);
11+
\draw[thick] (.2,0) -- ++(0,3);
12+
% spring 1
13+
\draw
14+
[
15+
decoration={
16+
coil,
17+
aspect=0.3,
18+
segment length=1.5mm,
19+
amplitude=2mm,
20+
pre length=3mm,
21+
post length=3mm},
22+
decorate
23+
] (0.2,1.5) -- ++(2,0)
24+
node[midway,below=0.25cm,black]{$k_1$};
25+
% Mass 1
26+
\node[draw,
27+
minimum width=1cm,
28+
minimum height=0.75cm,
29+
anchor=mid] at (2.7,1.5) {$m_1$};
30+
% spring 12
31+
\draw
32+
[
33+
decoration={
34+
coil,
35+
aspect=0.3,
36+
segment length=1.5mm,
37+
amplitude=2mm,
38+
pre length=3mm,
39+
post length=3mm},
40+
decorate
41+
] (3.2,1.5) -- ++(2,0)
42+
node[midway,below=0.25cm,black]{$k_{12}$};
43+
% Mass 2
44+
\node[draw,
45+
minimum width=1cm,
46+
minimum height=0.75cm,
47+
anchor=mid] at (5.7,1.5) {$m_2$};
48+
% spring 2
49+
\draw
50+
[
51+
decoration={
52+
coil,
53+
aspect=0.3,
54+
segment length=1.5mm,
55+
amplitude=2mm,
56+
pre length=3mm,
57+
post length=3mm},
58+
decorate
59+
] (6.2,1.5) -- ++(2,0)
60+
node[midway,below=0.25cm,black]{$k_{2}$};
61+
% right wall
62+
\fill [pattern = north west lines] (8.2,0) rectangle ++(.2,3);
63+
\draw[thick] (8.2,0) -- ++(0,3);
64+
65+
% u1 arrow
66+
\draw [very thick,
67+
color1,
68+
-latex
69+
] (2.7,1.85) -- ++(0,.5) ++(0,-0.25) -- ++ (1,0)
70+
node[midway,above]{\small $u_1$};
71+
72+
% u2 arrow
73+
\draw [very thick,
74+
color2,
75+
-latex
76+
] (5.7,1.85) -- ++(0,.5) ++(0,-0.25) -- ++ (1,0)
77+
node[midway,above]{\small $u_2$};
78+
\end{tikzpicture}
79+
\end{document}
Loading
Loading

oscillator/plot-trajectory.py

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import pandas as pd
2+
from matplotlib import pyplot as plt
3+
import argparse
4+
from enum import Enum
5+
6+
7+
class PlotType(Enum):
8+
U_OVER_T = "position over time"
9+
V_OVER_T = "velocity over time"
10+
TRAJECTORY = "velocity over position (trajectory)"
11+
12+
13+
parser = argparse.ArgumentParser()
14+
parser.add_argument("csvFile", help="CSV file.", type=str)
15+
parser.add_argument("plotType", help="Plot type.", type=str, choices=[pt.name for pt in PlotType])
16+
args = parser.parse_args()
17+
18+
filename = args.csvFile
19+
df = pd.read_csv(filename, delimiter=';')
20+
21+
if args.plotType == PlotType.U_OVER_T.name:
22+
plt.plot(df['time'], df['position'])
23+
plt.title(PlotType.U_OVER_T.value)
24+
elif args.plotType == PlotType.V_OVER_T.name:
25+
plt.plot(df['time'], df['velocity'])
26+
plt.title(PlotType.V_OVER_T.value)
27+
elif args.plotType == PlotType.TRAJECTORY.name:
28+
plt.plot(df['position'], df['velocity'])
29+
plt.scatter([df['position'][0]], [df['velocity'][0]], label=f"(u,v) at t={df['time'][0]}")
30+
plt.scatter([df['position'].iloc[-1]], [df['velocity'].iloc[-1]],
31+
label=f"(u,v) at t={df['time'].iloc[-1]}", marker="*")
32+
plt.title(PlotType.TRAJECTORY.value)
33+
plt.legend()
34+
35+
plt.show()

oscillator/precice-config.xml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?xml version="1.0"?>
2+
<precice-configuration>
3+
<log enabled="1">
4+
<sink filter="%Severity% > debug" />
5+
</log>
6+
7+
<solver-interface dimensions="2" >
8+
<!-- Use this to activate waveforms
9+
<solver-interface dimensions="2" experimental="true">
10+
-->
11+
<data:scalar name="Force-Left" />
12+
<data:scalar name="Force-Right" />
13+
14+
<mesh name="Mass-Left-Mesh">
15+
<use-data name="Force-Left" />
16+
<use-data name="Force-Right" />
17+
</mesh>
18+
19+
<mesh name="Mass-Right-Mesh">
20+
<use-data name="Force-Left" />
21+
<use-data name="Force-Right" />
22+
</mesh>
23+
24+
<participant name="Mass-Left">
25+
<use-mesh name="Mass-Left-Mesh" provide="yes"/>
26+
<write-data name="Force-Left" mesh="Mass-Left-Mesh" />
27+
<read-data name="Force-Right" mesh="Mass-Left-Mesh" />
28+
<!-- Use this to activate first order interpolation
29+
<read-data name="Force-Right" mesh="Mass-Left-Mesh" waveform-order="1" />
30+
-->
31+
</participant>
32+
33+
<participant name="Mass-Right">
34+
<use-mesh name="Mass-Left-Mesh" from="Mass-Left"/>
35+
<use-mesh name="Mass-Right-Mesh" provide="yes"/>
36+
<write-data name="Force-Right" mesh="Mass-Right-Mesh" />
37+
<read-data name="Force-Left" mesh="Mass-Right-Mesh" />
38+
<!-- Use this to activate first order interpolation
39+
<read-data name="Force-Left" mesh="Mass-Right-Mesh" waveform-order="1" />
40+
-->
41+
<mapping:nearest-neighbor direction="write" from="Mass-Right-Mesh" to="Mass-Left-Mesh" constraint="consistent" />
42+
<mapping:nearest-neighbor direction="read" from="Mass-Left-Mesh" to="Mass-Right-Mesh" constraint="consistent" />
43+
</participant>
44+
45+
<m2n:sockets from="Mass-Left" to="Mass-Right" exchange-directory=".." />
46+
47+
<coupling-scheme:serial-implicit>
48+
<participants first="Mass-Left" second="Mass-Right" />
49+
<max-time value="1" />
50+
<time-window-size value="0.01" />
51+
<max-iterations value="200" />
52+
<relative-convergence-measure data="Force-Left" mesh="Mass-Left-Mesh" limit="1e-10"/>
53+
<relative-convergence-measure data="Force-Right" mesh="Mass-Left-Mesh" limit="1e-10"/>
54+
<exchange data="Force-Left" mesh="Mass-Left-Mesh" from="Mass-Left" to="Mass-Right" />
55+
<!-- Use this for higher accuracy with waveforms and preCICE v3
56+
<exchange data="Force-Left" mesh="Mass-Left-Mesh" from="Mass-Left" to="Mass-Right" initialize="true" />
57+
-->
58+
<exchange data="Force-Right" mesh="Mass-Left-Mesh" from="Mass-Right" to="Mass-Left" initialize="true"/>
59+
</coupling-scheme:serial-implicit>
60+
</solver-interface>
61+
62+
</precice-configuration>

oscillator/python/clean.sh

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/sh
2+
set -e -u
3+
4+
. ../../tools/cleaning-tools.sh
5+
6+
rm -rfv ./output/
7+
8+
clean_precice_logs .

0 commit comments

Comments
 (0)