Skip to content

Commit 3d0980a

Browse files
committed
Add CheMFC test cases
1 parent 693837c commit 3d0980a

File tree

24 files changed

+806
-80
lines changed

24 files changed

+806
-80
lines changed

benchmarks/5eq_rk3_weno3_hllc/case.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@
1414
description="This MFC case was created for the purposes of benchmarking MFC.",
1515
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
1616

17-
parser.add_argument("--mfc", type=str, metavar="DICT", help=argparse.SUPPRESS)
18-
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16, help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
17+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
18+
metavar="DICT", help="MFC's toolchain's internal state.")
19+
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16,
20+
help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
1921

2022
ARGS = vars(parser.parse_args())
21-
DICT = json.loads(ARGS["mfc"])
23+
DICT = ARGS["mfc"]
2224

2325
size = 1 if DICT["gpu"] else 0
2426

benchmarks/hypo_hll/case.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
description="This MFC case was created for the purposes of benchmarking MFC.",
1313
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
1414

15-
parser.add_argument("--mfc", type=str, metavar="DICT", help=argparse.SUPPRESS)
16-
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16, help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
15+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
16+
metavar="DICT", help="MFC's toolchain's internal state.")
17+
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16,
18+
help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
1719

1820
ARGS = vars(parser.parse_args())
19-
DICT = json.loads(ARGS["mfc"])
21+
DICT = ARGS["mfc"]
2022

2123
size = 1 if DICT["gpu"] else 0
2224

benchmarks/ibm/case.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
description="This MFC case was created for the purposes of benchmarking MFC.",
1212
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
1313

14-
parser.add_argument("--mfc", type=str, metavar="DICT", help=argparse.SUPPRESS)
15-
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16, help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
14+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
15+
metavar="DICT", help="MFC's toolchain's internal state.")
16+
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16,
17+
help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
1618

1719
ARGS = vars(parser.parse_args())
18-
DICT = json.loads(ARGS["mfc"])
20+
DICT = ARGS["mfc"]
1921

2022
size = 1 if DICT["gpu"] else 0
2123

benchmarks/viscous_weno5_sgb_acoustic/case.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
description="This MFC case was created for the purposes of benchmarking MFC.",
1717
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
1818

19-
parser.add_argument("--mfc", type=str, metavar="DICT", help=argparse.SUPPRESS)
20-
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16, help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
19+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
20+
metavar="DICT", help="MFC's toolchain's internal state.")
21+
parser.add_argument("--gbpp", type=int, metavar="MEM", default=16,
22+
help="Adjusts the problem size per rank to fit into [MEM] GB of GPU memory per GPU.")
2123

2224
ARGS = vars(parser.parse_args())
23-
DICT = json.loads(ARGS["mfc"])
25+
DICT = ARGS["mfc"]
2426

2527
size = 1 if DICT["gpu"] else 0
2628

docs/documentation/case.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,17 @@ Input files can accept command line arguments, forwarded by `mfc.sh run`.
3434
Consider this example from the `scaling` case:
3535

3636
```python
37-
import argparse
37+
import json, argparse
3838

3939
parser = argparse.ArgumentParser(
4040
prog="scaling",
4141
description="Weak- and strong-scaling benchmark case.",
4242
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
4343

44-
parser.add_argument("--mfc", type=str, metavar="DICT", default='{}')
44+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
45+
metavar="DICT", help="MFC's toolchain's internal state.")
4546
parser.add_argument("-s", "--scaling", type=str, metavar="SCALING", choices=["weak", "strong"],
46-
help="Whether weak- or strong-scaling is being exercised.")
47+
help="Whether weak- or strong-scaling is being exercised.")
4748

4849
# Your parsed arguments are here
4950
args = parser.parse_args()

examples/1D_inert_shocktube/case.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,21 @@
44
# + https://doi.org/10.1016/j.compfluid.2013.10.014: 4.3. Multi-component inert shock tube
55

66
import json
7+
import argparse
8+
79
import cantera as ct
810

11+
parser = argparse.ArgumentParser(
12+
prog="nD_inert_shocktube",
13+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
14+
15+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
16+
metavar="DICT", help="MFC's toolchain's internal state.")
17+
parser.add_argument("--no-chem", dest='chemistry', default=True, action="store_false",
18+
help="Disable chemistry.")
19+
20+
args = parser.parse_args()
21+
922
ctfile = 'h2o2.yaml'
1023
sol_L = ct.Solution(ctfile)
1124
sol_L.TPX = 400, 8000, 'H2:2,O2:1,AR:7'
@@ -18,7 +31,6 @@
1831
dt = 5e-9
1932
Tend = 40e-6
2033

21-
chemistry = True
2234
NT = int(Tend / dt)
2335
SAVE_COUNT = 200
2436
NS = NT // SAVE_COUNT
@@ -62,7 +74,7 @@
6274
# ==========================================================================
6375

6476
# Chemistry ================================================================
65-
'chemistry' : 'F' if not chemistry else 'T',
77+
'chemistry' : 'F' if not args.chemistry else 'T',
6678
'chem_params%advection' : 'T',
6779
'chem_params%diffusion' : 'F',
6880
'chem_params%reactions' : 'T',
@@ -104,7 +116,7 @@
104116
# ==========================================================================
105117
}
106118

107-
if chemistry:
119+
if args.chemistry:
108120
for i in range(len(sol_L.Y)):
109121
case[f'patch_icpp(1)%Y({i+1})'] = sol_L.Y[i]
110122
case[f'patch_icpp(2)%Y({i+1})'] = sol_R.Y[i]

examples/1D_reactive_shocktube/case.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,21 @@
44
# + https://doi.org/10.1016/j.ijhydene.2023.03.190: Verification of numerical method
55
# + https://doi.org/10.1016/j.compfluid.2013.10.014: 4.7. Multi-species reactive shock tube
66

7-
import json
7+
import json, argparse
88
import cantera as ct
99

10+
parser = argparse.ArgumentParser(
11+
prog="1D_reactive_shocktube",
12+
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
13+
14+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
15+
metavar="DICT", help="MFC's toolchain's internal state.")
16+
parser.add_argument("--no-chem", dest='chem', default=True, action="store_false",
17+
help="Disable chemistry.")
18+
parser.add_argument("--scale", type=float, default=1, help="Scale.")
19+
20+
args = parser.parse_args()
21+
1022
ctfile = 'h2o2.yaml'
1123
sol_L = ct.Solution(ctfile)
1224
sol_L.DPX = 0.072, 7173, 'H2:2,O2:1,AR:7'
@@ -18,7 +30,7 @@
1830
u_r = -487.34
1931

2032
L = 0.12
21-
Nx = 800
33+
Nx = 800 * args.scale
2234
dx = L/Nx
2335
dt = dx/abs(u_r)*0.01
2436
Tend=230e-6
@@ -27,8 +39,6 @@
2739
SAVE_COUNT=100
2840
NS=NT//SAVE_COUNT
2941

30-
chemistry = True
31-
3242
case = {
3343
# Logistics ================================================================
3444
'run_time_info' : 'T',
@@ -45,7 +55,7 @@
4555
't_step_stop' : NT,
4656
't_step_save' : NS,
4757
't_step_print' : NS,
48-
'parallel_io' : 'F',
58+
'parallel_io' : 'T' if args.mfc.get("mpi", True) else 'F',
4959

5060
# Simulation Algorithm Parameters ==========================================
5161
'model_eqns' : 2,
@@ -66,7 +76,7 @@
6676
'bc_x%end' :-3,
6777

6878
# Chemistry ================================================================
69-
'chemistry' : 'F' if not chemistry else 'T',
79+
'chemistry' : 'F' if not args.chemistry else 'T',
7080
'chem_params%advection' : 'T',
7181
'chem_params%diffusion' : 'F',
7282
'chem_params%reactions' : 'T',
@@ -77,6 +87,7 @@
7787
'format' : 1,
7888
'precision' : 2,
7989
'prim_vars_wrt' : 'T',
90+
'chem_wrt_T' : 'T',
8091
# ==========================================================================
8192

8293
# ==========================================================================
@@ -105,8 +116,9 @@
105116
# ==========================================================================
106117
}
107118

108-
if chemistry:
119+
if args.chemistry:
109120
for i in range(len(sol_L.Y)):
121+
case[f'chem_wrt_Y({i + 1})'] = 'T'
110122
case[f'patch_icpp(1)%Y({i+1})'] = sol_L.Y[i]
111123
case[f'patch_icpp(2)%Y({i+1})'] = sol_R.Y[i]
112124

examples/nD_perfect_reactor/analyze.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import matplotlib.pyplot as plt
55

66
import mfc.viz
7-
from case import dt, NS, Tend, SAVE_COUNT, sol
7+
from case import dt, Tend, SAVE_COUNT, sol
88

99

1010
case = mfc.viz.Case(".", dt)

examples/nD_perfect_reactor/case.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
import cantera as ct
1010

1111
parser = argparse.ArgumentParser(
12-
prog="nD_Reactor",
12+
prog="nD_perfect_reactor",
1313
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
1414

15-
parser.add_argument("--mfc", type=str, default='{}', metavar="DICT")
16-
parser.add_argument("--no-chem", dest='chem', default=True, action="store_false",
17-
help="Disable chemistry.")
18-
parser.add_argument("--scale", type=float, default=1, help="Scale.")
19-
parser.add_argument("--ndim", type=int, default=1, help="Number of dimensions.")
15+
parser.add_argument("--mfc", type=str, type=json.loads, default='{}',
16+
metavar="DICT", help="MFC's toolchain's internal state.")
17+
parser.add_argument("--no-chem", dest='chemistry', default=True, action="store_false",
18+
help="Disable chemistry.")
19+
parser.add_argument("--scale", type=float, default=1, help="Scale.")
20+
parser.add_argument("--ndim", type=int, default=1, help="Number of dimensions.")
2021

2122
args = parser.parse_args()
2223

@@ -28,10 +29,10 @@
2829
Nx = 25 * args.scale
2930
Tend = 1e-4
3031
s = 1e-2
31-
dt = 1e-9
32+
dt = 1e-7
3233

3334
NT = int(Tend / dt)
34-
SAVE_COUNT = 2000
35+
SAVE_COUNT = 20
3536
NS = NT // SAVE_COUNT
3637

3738
case = {
@@ -54,7 +55,7 @@
5455
't_step_stop' : NT,
5556
't_step_save' : NS,
5657
't_step_print' : NS,
57-
'parallel_io' : 'T' if args.ndim > 1 else 'F',
58+
'parallel_io' : 'T' if args.ndim > 1 and args.mfc.get("mpi", True) else 'F',
5859

5960
# Simulation Algorithm Parameters ==========================================
6061
'model_eqns' : 2,
@@ -82,6 +83,7 @@
8283
'format' : 1,
8384
'precision' : 2,
8485
'prim_vars_wrt' : 'T',
86+
'chem_wrt_T' : 'T',
8587
# ==========================================================================
8688

8789
# Patch 1 ==================================================================
@@ -106,7 +108,7 @@
106108
# ==========================================================================
107109
}
108110

109-
if args.chem:
111+
if args.chemistry:
110112
case.update({
111113
# Chemistry ============================================================
112114
'chemistry' : 'T',
@@ -118,6 +120,7 @@
118120
})
119121

120122
for i in range(len(sol.Y)):
123+
case[f'chem_wrt_Y({i + 1})'] = 'T'
121124
case[f'patch_icpp(1)%Y({i+1})'] = sol.Y[i]
122125

123126
case = remove_higher_dimensional_keys(case, args.ndim)
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import csv
2+
import cantera as ct
3+
from tqdm import tqdm
4+
5+
import mfc.viz
6+
from case import dt, NS, Tend, SAVE_COUNT, sol
7+
8+
9+
case = mfc.viz.Case(".", dt)
10+
11+
for name in tqdm(sol.species_names, desc="Loading Variables"):
12+
case.load_variable(f"Y_{name}", f"prim.{5 + sol.species_index(name)}")
13+
case.load_variable("rho", "prim.1")
14+
15+
time_save = Tend/SAVE_COUNT
16+
17+
oh_idx = sol.species_index("OH")
18+
def generate_ct_saves() -> tuple:
19+
reactor = ct.IdealGasReactor(sol)
20+
reactor_network = ct.ReactorNet([reactor])
21+
22+
ct_time = 0.0
23+
ct_ts, ct_Ys, ct_rhos = [0.0], [reactor.thermo.Y], [reactor.thermo.density]
24+
25+
while ct_time < Tend:
26+
reactor_network.advance(ct_time + time_save)
27+
ct_time += time_save
28+
ct_ts.append(ct_time)
29+
ct_Ys.append(reactor.thermo.Y)
30+
ct_rhos.append(reactor.thermo.density)
31+
32+
return ct_ts, ct_Ys, ct_rhos
33+
34+
ct_ts, ct_Ys, ct_rhos = generate_ct_saves()
35+
36+
with open("mfc.csv", "w") as f:
37+
writer = csv.writer(f)
38+
keys = ["t"] + list(set(case.get_data()[0].keys()) - set(["x"]))
39+
writer.writerow(keys)
40+
for i, t_step in enumerate(sorted(case.get_timesteps())):
41+
t = t_step * dt
42+
row = [t] + [case.get_data()[t_step][key][0] for key in keys[1:]]
43+
writer.writerow(row)
44+
45+
with open("cantera.csv", "w") as f:
46+
writer = csv.writer(f)
47+
keys = ["t"] + [f"Y_{_}" for _ in list(sol.species_names)] + ["rho"]
48+
writer.writerow(keys)
49+
for step in range(len(ct_ts)):
50+
row = [ct_ts[step]] + [ ct_Ys[step][i] for i in range(len(sol.species_names)) ] + [ct_rhos[step]]
51+
print([ct_ts[step]], row)
52+
writer.writerow(row)
53+
54+
def find_induction_time(ts: list, Ys: list, rhos: list) -> float:
55+
for t, y, rho in zip(ts, Ys, rhos):
56+
if (y * rho / sol.molecular_weights[oh_idx]) >= 1e-6:
57+
return t
58+
59+
return None
60+
61+
skinner_induction_time = 0.052e-3
62+
ct_induction_time = find_induction_time(
63+
ct_ts,
64+
[y[oh_idx] for y in ct_Ys],
65+
[rho for rho in ct_rhos]
66+
)
67+
mfc_induction_time = find_induction_time(
68+
sorted(case.get_timestamps()),
69+
[ case.get_data()[step]["Y_OH"][0] for step in sorted(case.get_timesteps()) ],
70+
[ case.get_data()[step]["rho"][0] for step in sorted(case.get_timesteps()) ]
71+
)
72+
73+
print("Induction Times ([OH] >= 1e-6):")
74+
print(f" + Skinner et al.: {skinner_induction_time} s")
75+
print(f" + Cantera: {ct_induction_time} s")
76+
print(f" + (Che)MFC: {mfc_induction_time} s")

0 commit comments

Comments
 (0)