Skip to content

Commit c546b48

Browse files
committed
Check results are the same regardless of component order
1 parent 26691c7 commit c546b48

File tree

3 files changed

+258
-0
lines changed

3 files changed

+258
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ if(HERMES_TESTS)
281281
hermes_add_integrated_test(alfven-wave)
282282
hermes_add_integrated_test(collfreq-braginskii-afn)
283283
hermes_add_integrated_test(collfreq-multispecies)
284+
hermes_add_integrated_test(component-order)
284285

285286
# Unit tests
286287
option(HERMES_UNIT_TESTS "Build the unit tests" ON)
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
nout = 0
2+
timestep = 1
3+
4+
5+
[mesh]
6+
# 1D simulation, use "y" as the dimension along the fieldline
7+
nx = 10
8+
ny = 10 # Resolution along field-line
9+
nz = 10
10+
ixseps1 = 0
11+
J = 1
12+
13+
14+
[hermes]
15+
components = (d+, he+, he, d, e,
16+
sheath_boundary_simple, braginskii_collisions, braginskii_friction,
17+
braginskii_heat_exchange, reactions, electron_force_balance,
18+
neutral_parallel_diffusion, braginskii_ion_viscosity,
19+
braginskii_conduction, recycling)
20+
21+
22+
[solver]
23+
type = pvode
24+
25+
26+
[sheath_boundary_simple]
27+
lower_y = false
28+
upper_y = true
29+
diagnose = true
30+
31+
32+
[neutral_parallel_diffusion]
33+
dneut = 10
34+
diffusion_collisions_mode = multispecies
35+
36+
37+
[braginskii_collisions]
38+
electron_ion = true
39+
electron_electron = true
40+
electron_neutral = true
41+
ion_ion = true
42+
ion_neutral = true
43+
neutral_neutral = true
44+
diagnose = true
45+
46+
47+
[braginskii_ion_viscosity]
48+
viscosity_collisions_mode = multispecies
49+
50+
[recycling]
51+
species = d+, he+
52+
53+
54+
####################################
55+
[d+]
56+
type = (evolve_density, evolve_pressure, evolve_momentum,
57+
noflow_boundary)
58+
59+
charge = 1
60+
AA = 2
61+
thermal_conduction = true
62+
conduction_collisions_mode = multispecies
63+
noflow_upper_y = false
64+
recycle_as = d
65+
target_recycle = true
66+
diagnose = true
67+
68+
[Nd+]
69+
function = 1
70+
71+
[Pd+]
72+
function = 1
73+
74+
[NVd+]
75+
function = 1
76+
77+
####################################
78+
[he+]
79+
type = (evolve_density, evolve_pressure, evolve_momentum,
80+
noflow_boundary)
81+
82+
charge = 2
83+
AA = 4
84+
thermal_conduction = true
85+
conduction_collisions_mode = multispecies
86+
noflow_upper_y = false
87+
recycle_as = he
88+
target_recycle = true
89+
diagnose = true
90+
91+
[Nhe+]
92+
function = 0.01
93+
94+
[Phe+]
95+
function = 0.001
96+
97+
[NVhe+]
98+
function = 0.001
99+
100+
####################################
101+
[he]
102+
type = (neutral_mixed, noflow_boundary)
103+
104+
AA = 4
105+
diffusion_collisions_mode = multispecies
106+
diagnose = true
107+
108+
[Nhe]
109+
function = 0.001
110+
111+
[Phe]
112+
function = 0.0001
113+
114+
[NVhe]
115+
function = 0.0001
116+
117+
####################################
118+
[d]
119+
type = (neutral_mixed, noflow_boundary)
120+
121+
AA = 2
122+
diffusion_collisions_mode = multispecies
123+
diagnose = true
124+
125+
[Nd]
126+
function = 0.001
127+
128+
[Pd]
129+
function = 0.0001
130+
131+
[NVd]
132+
function = 0.0001
133+
134+
####################################
135+
[e] # Electrons
136+
type = (quasineutral, evolve_pressure, zero_current,
137+
noflow_boundary)
138+
139+
noflow_upper_y = false
140+
141+
charge = -1
142+
AA = 1/1836
143+
thermal_conduction = true # in evolve_pressure
144+
conduction_collisions_mode = multispecies
145+
146+
diagnose = true
147+
148+
[Pe]
149+
150+
function = `Pd+:function`
151+
152+
####################################
153+
154+
155+
[reactions]
156+
diagnose = true
157+
type = (
158+
d + e -> d+ + 2e, # Deuterium ionisation
159+
d+ + e -> d, # Deuterium recombination
160+
d + d+ -> d+ + d, # Charge exchange
161+
162+
he + e -> he+ + 2e, # Helium ionisation
163+
he+ + e -> he, # Helium+ recombination
164+
)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env python3
2+
3+
# Python script to run and analyse two test cases that are identical
4+
# except the order in which the components are specified.
5+
6+
from __future__ import division
7+
from __future__ import print_function
8+
9+
try:
10+
from builtins import str
11+
except:
12+
pass
13+
14+
from boututils.run_wrapper import shell, launch_safe, getmpirun
15+
from boutdata.collect import collect
16+
import numpy
17+
import xhermes
18+
19+
from numpy import sqrt, max, abs, mean, array, log, concatenate
20+
from pathlib import Path
21+
22+
23+
def check_value(name, val, target, **kws):
24+
# override default tolerances to get desired behaviour
25+
kws["atol"] = kws.pop("atol", 0.0)
26+
kws["rtol"] = kws.pop("rtol", 0.0)
27+
28+
success = numpy.isclose(val, target, **kws)
29+
if not success:
30+
# On failure, report the effective abs tolerance used by isclose
31+
atol_eff = kws["atol"] + kws["rtol"] * abs(target)
32+
print(
33+
f"Expected\n {target-atol_eff} < {name} < {target+atol_eff}\nBut actual value was\n {val}"
34+
)
35+
return success
36+
37+
38+
cases = [
39+
"d+, he+, he, d, e, sheath_boundary_simple, braginskii_collisions, braginskii_friction, braginskii_heat_exchange, reactions, electron_force_balance, neutral_parallel_diffusion, braginskii_ion_viscosity, braginskii_conduction, recycling",
40+
"recycling, d+, braginskii_friction, braginskii_heat_exchange, he, reactions, electron_force_balance, neutral_parallel_diffusion, d, braginskii_ion_viscosity, sheath_boundary_simple, he+, braginskii_conduction, braginskii_collisions, e"
41+
]
42+
43+
# Remove old test results and symlink executable
44+
45+
if not Path("hermes-3").is_file():
46+
shell("ln -s ../../../hermes-3 hermes-3")
47+
48+
results = []
49+
50+
# Run and exit if unsuccessful
51+
for i, c in enumerate(cases):
52+
for file in ["BOUT.dmp.0.nc", "BOUT.log.0", "BOUT.restart.0.nc", "BOUT.settings", ".BOUT.pid.0"]:
53+
path = Path("data") / file
54+
if path.is_file():
55+
print(f"Removing old file data/{file}")
56+
path.unlink()
57+
58+
s, out = launch_safe(f"./hermes-3 hermes:components='{c}'", nproc=1, pipe=True)
59+
60+
if s != 0:
61+
print(" => Test failed: ")
62+
print(out)
63+
exit(1)
64+
65+
# Save output to log file
66+
with open(f"run.{i}.log", "w") as f:
67+
f.write(out)
68+
69+
results.append(xhermes.open("data", unnormalise=False).isel(t=-1))
70+
71+
success = True
72+
73+
rtol = 1e-10
74+
atol = 1e-10
75+
diagnostics = ["Nd+", "Pd+", "Vd+", "NVd+", "Nd", "Pd", "Vd", "NVd", "Nhe+", "Phe+", "Vhe+", "NVhe+", "Nhe", "Phe", "Vhe", "NVhe", "Ne", "Pe", "Ve"]
76+
idx = (3, 5, 7)
77+
78+
failing = []
79+
80+
# Check output is the same between the simulations
81+
for d in diagnostics:
82+
if not check_value(d, results[0][d].values[idx], results[1][d].values[idx], rtol=rtol, atol=atol):
83+
success = False
84+
failing.append(d)
85+
86+
87+
# Final output
88+
if success:
89+
print(" => Test passed")
90+
exit(0)
91+
else:
92+
print(f" => Test failed: \nDisagreement in diagnostic(s) {', '.join(failing)}")
93+
exit(1)

0 commit comments

Comments
 (0)