Skip to content

Commit 4461db2

Browse files
authored
Merge branch 'MFlowCode:master' into bubnorm
2 parents 50f78b8 + e2ce07d commit 4461db2

File tree

7 files changed

+361
-9
lines changed

7 files changed

+361
-9
lines changed

examples/1D_convergence/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
This example case contains an automated convergence test using a 1D, two-component advection case.
2+
The case can be run by executing the bash script `./submitJobs.sh` in a terminal after enabling
3+
execution permissions with `chmod +x ./submitJobs.sh` and setting the `ROOT_DIR` and `MFC_DIR`
4+
variables. By default the script runs the case for 6 different grid resolutions with 1st,
5+
3rd, and 5th, order spatial reconstructions. These settings can be modified by editing the variables
6+
at the top of the script. You can also run different model equations by setting the `ME` variable
7+
and different Riemann solvers by setting the `RS` variable.
8+
9+
Once the simulations have been run, you can generate convergence plots with matplotlib by running
10+
`python3 plot.py` in a terminal. This will generate plots of the L1, L2, and Linf error norms and
11+
save the results to `errors.csv`.

examples/1D_convergence/case.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env python3
2+
import math
3+
import json
4+
import argparse
5+
6+
# Parsing command line arguments
7+
parser = argparse.ArgumentParser(description="Generate JSON case configuration for two-fluid convergence simulation.")
8+
parser.add_argument("--mfc", type=json.loads, default="{}", metavar="DICT", help="MFC's toolchain's internal state.")
9+
parser.add_argument("--order", type=int, default=5, help="WENO order (default: 5)")
10+
parser.add_argument("--meqns", type=int, default=2, help="Model equations (default: 2 (five-equation model))")
11+
parser.add_argument("--rs", type=int, default=2, help="Riemann solver (default: 2 (HLLC))")
12+
parser.add_argument("-N", type=int, default=1024, help="Number of grid points (default: 1024)")
13+
14+
args = parser.parse_args()
15+
16+
# Numerical setup
17+
Nx = args.N - 1
18+
dx = 1.0 / (1.0 * (Nx + 1))
19+
20+
Tend, Nt = 5.0, 200000
21+
mydt = Tend / (1.0 * Nt)
22+
23+
# Configuring case dictionary
24+
print(
25+
json.dumps(
26+
{
27+
# Logistics
28+
"run_time_info": "T",
29+
# Computational Domain Parameters
30+
"x_domain%beg": 0.0e00,
31+
"x_domain%end": 1.0e00,
32+
"m": Nx,
33+
"n": 0,
34+
"p": 0,
35+
"dt": mydt,
36+
"t_step_start": 0,
37+
"t_step_stop": int(Nt),
38+
"t_step_save": int(math.ceil(Nt / 10.0)),
39+
# Simulation Algorithm Parameters
40+
"num_patches": 1,
41+
"model_eqns": args.meqns,
42+
"alt_soundspeed": "F",
43+
"num_fluids": 2,
44+
"mpp_lim": "F",
45+
"mixture_err": "F",
46+
"time_stepper": 3,
47+
"weno_order": args.order,
48+
"weno_eps": dx**2,
49+
"weno_Re_flux": "F",
50+
"weno_avg": "F",
51+
"mapped_weno": "F",
52+
"null_weights": "F",
53+
"mp_weno": "F",
54+
"riemann_solver": args.rs,
55+
"wave_speeds": 1,
56+
"avg_state": 2,
57+
"bc_x%beg": -1,
58+
"bc_x%end": -1,
59+
# Formatted Database Files Structure Parameters
60+
"format": 1,
61+
"precision": 2,
62+
"prim_vars_wrt": "T",
63+
"parallel_io": "F",
64+
# Patch 1 L
65+
"patch_icpp(1)%geometry": 1,
66+
"patch_icpp(1)%x_centroid": 0.5,
67+
"patch_icpp(1)%length_x": 1.0,
68+
"patch_icpp(1)%vel(1)": 1.0,
69+
"patch_icpp(1)%pres": 1.0,
70+
"patch_icpp(1)%alpha_rho(1)": f"0.5 - 0.5*sin(2*pi*x)",
71+
"patch_icpp(1)%alpha(1)": f"0.5 - 0.5*sin(2*pi*x)",
72+
"patch_icpp(1)%alpha_rho(2)": f"0.5 + 0.5*sin(2*pi*x)",
73+
"patch_icpp(1)%alpha(2)": f"0.5 + 0.5*sin(2*pi*x)",
74+
# Fluids Physical Parameters
75+
"fluid_pp(1)%gamma": 1.0e00 / (1.4 - 1.0e00),
76+
"fluid_pp(1)%pi_inf": 0.0,
77+
"fluid_pp(2)%gamma": 1.0e00 / (1.4 - 1.0e00),
78+
"fluid_pp(2)%pi_inf": 0.0,
79+
}
80+
)
81+
)

examples/1D_convergence/plot.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import matplotlib.pyplot as plt
2+
import numpy as np
3+
import pandas as pd
4+
5+
N = [32, 64, 128, 256, 512, 1024]
6+
Ord = [1, 3, 5]
7+
8+
errors = np.nan * np.zeros((len(N), len(Ord), 3))
9+
10+
TEND = 200000
11+
12+
for i in range(len(N)):
13+
for j in range(len(Ord)):
14+
15+
sim_a1 = pd.read_csv(f"N{N[i]}_O{Ord[j]}/D/cons.5.00.{TEND}.dat", sep=r"\s+", header=None, names=["x", "y"])
16+
sim_a2 = pd.read_csv(f"N{N[i]}_O{Ord[j]}/D/cons.6.00.{TEND}.dat", sep=r"\s+", header=None, names=["x", "y"])
17+
18+
exact_a1 = pd.read_csv(f"N{N[i]}_O{Ord[j]}/D/cons.5.00.000000.dat", sep=r"\s+", header=None, names=["x", "y"])
19+
exact_a2 = pd.read_csv(f"N{N[i]}_O{Ord[j]}/D/cons.6.00.000000.dat", sep=r"\s+", header=None, names=["x", "y"])
20+
21+
## 2 norm
22+
errors[i, j, 0] = np.linalg.norm(sim_a1.y - exact_a1.y) / np.sqrt(N[i])
23+
errors[i, j, 0] += np.linalg.norm(sim_a2.y - exact_a2.y) / np.sqrt(N[i])
24+
25+
## 1 norm
26+
errors[i, j, 1] = 1 / N[i] * np.sum(np.abs(sim_a1.y - exact_a1.y))
27+
errors[i, j, 1] += 1 / N[i] * np.sum(np.abs(sim_a2.y - exact_a2.y))
28+
29+
## Inf norm
30+
errors[i, j, 2] = np.max([np.nanmax(np.abs(sim_a1.y - exact_a1.y)), np.nanmax(np.abs(sim_a2.y - exact_a2.y))])
31+
32+
fig, ax = plt.subplots(1, 3, figsize=(12, 8), sharex=True)
33+
34+
colors = ["blue", "green", "red", "purple"]
35+
36+
ref = np.nan * np.zeros((len(N), len(Ord)))
37+
38+
for i in range(3):
39+
ax[i].plot(N, 30 / np.array(N) ** 1, label="Slope = -1", color=colors[0])
40+
ax[i].plot(N, 3000 / np.array(N) ** 3, label="Slope = -3", color=colors[1])
41+
ax[i].plot(N, 5000 / np.array(N) ** 5, label="Slope = -5", color=colors[2])
42+
43+
for j in range(len(Ord)):
44+
ax[0].plot(N, errors[:, j, 0], "o-", color=colors[j])
45+
ax[0].set_xscale("log", base=2)
46+
ax[0].set_yscale("log")
47+
ax[0].set_title("||error||_2")
48+
ax[0].legend()
49+
50+
ax[1].plot(N, errors[:, j, 1], "o-", color=colors[j])
51+
ax[1].set_xscale("log", base=2)
52+
ax[1].set_yscale("log")
53+
ax[1].set_title("||error||_1")
54+
55+
ax[2].plot(N, errors[:, j, 2], "o-", color=colors[j])
56+
ax[2].set_xscale("log", base=2)
57+
ax[2].set_yscale("log")
58+
ax[2].set_title("||error||_inf")
59+
60+
plt.tight_layout()
61+
plt.show()
62+
63+
errors = np.column_stack((N, errors[:, :, 0]))
64+
errors = np.column_stack((errors, 7 / np.array(N) ** 1))
65+
errors = np.column_stack((errors, 700 / np.array(N) ** 3))
66+
errors = np.column_stack((errors, 2000 / np.array(N) ** 5))
67+
68+
df = pd.DataFrame(errors, columns=["N", "1", "3", "5", "R1", "R3", "R5"], index=N)
69+
df.to_csv("errors.csv", index=False)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/usr/bin/env bash
2+
set -e # Exit on error
3+
set -u # Exit on undefined variable
4+
5+
Nx=(32 64 128 256 512 1024)
6+
Order=(1 3 5)
7+
8+
ME=2 # Model equations = 2 for five-equation model
9+
RS=2 # Riemann solver = 2 for HLLC
10+
11+
# Get the directory of the script itself
12+
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
13+
# Assume the script is in examples/1D_convergence, so MFC_DIR is two levels up
14+
MFC_DIR="$(dirname "$(dirname "$ROOT_DIR")")"
15+
16+
for i in "${Nx[@]}"; do
17+
for j in "${Order[@]}"; do
18+
rm -rf "N${i}_O${j}"
19+
mkdir -p "N${i}_O${j}"
20+
cp case.py "N${i}_O${j}/"
21+
done
22+
done
23+
24+
cd "$MFC_DIR" || exit 1
25+
26+
for i in "${Nx[@]}"; do
27+
for j in "${Order[@]}"; do
28+
./mfc.sh run "$ROOT_DIR/N${i}_O${j}/case.py" --case-optimization --no-debug -- --order "$j" -N "$i" --meqns "$ME" --rs "$RS" || {
29+
echo "Error: mfc.sh failed for N=${i}, Order=${j}" >&2
30+
exit 1
31+
}
32+
done
33+
done

toolchain/mfc/case.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def rhs_replace(match):
142142
'r': f'patch_icpp({pid})%radius', 'eps': f'patch_icpp({pid})%epsilon', 'beta': f'patch_icpp({pid})%beta',
143143
'tau_e': f'patch_icpp({pid})%tau_e', 'radii': f'patch_icpp({pid})%radii',
144144

145-
'e' : f'{math.e}', 'pi': f'{math.pi}',
145+
'e' : f'{math.e}',
146146
}.get(match.group(), match.group())
147147

148148
lines = []

0 commit comments

Comments
 (0)