Skip to content

Commit 9e378e7

Browse files
authored
Updating nova setup (#3031)
This updates the nova problem to match the A4 model in the nova paper that is about to be submitted.
1 parent 1b74f64 commit 9e378e7

21 files changed

+16733
-20678
lines changed

Exec/science/nova/GNUmakefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PRECISION = DOUBLE
22
PROFILE = FALSE
33
DEBUG = FALSE
4-
DIM = 2
4+
DIM = 3
55

66
COMP = gnu
77

@@ -10,7 +10,7 @@ USE_OMP = FALSE
1010
USE_CUDA = FALSE
1111

1212
USE_REACT = TRUE
13-
USE_DIFFUSION = TRUE
13+
USE_DIFFUSION = FALSE
1414
USE_GRAV = TRUE
1515

1616
CASTRO_HOME := ../../..
@@ -22,7 +22,7 @@ MAX_NPTS_MODEL = 20000
2222
EOS_DIR := helmholtz
2323

2424
# This sets the network directory in $(MICROPHYSICS_HOME)/networks
25-
NETWORK_DIR := nova2
25+
NETWORK_DIR := nova
2626

2727
# Thi sets the conductivity EOS directory in $(MICROPHYSICS_HOME)/conductivity
2828
CONDUCTIVITY_DIR := stellar

Exec/science/nova/_prob_params

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ velpert_amplitude real 1.e2_rt y
99

1010
num_vortices integer 1 y
1111

12+
num_vortices_x integer 1 y
13+
14+
num_vortices_y integer 1 y
15+
1216
max_num_vortices integer 10 n
1317

1418
xloc_vortices real 0.0_rt n 10
@@ -19,7 +23,9 @@ y_h1 real 0.0_rt n
1923

2024
width real 0.0_rt y
2125

22-
L real 0.0_rt n
26+
L_x real 0.0_rt n
27+
28+
L_y real 0.0_rt n
2329

2430
amplitude real 0.0_rt y
2531

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import yt
2+
import os
3+
import re
4+
import numpy as np
5+
from yt.utilities.parallel_tools.parallel_analysis_interface import communication_system
6+
import matplotlib.pyplot as plt
7+
8+
yt.enable_parallelism()
9+
10+
plt.rcParams['font.size'] = 21
11+
plt.rcParams['font.family'] = 'serif'
12+
plt.rcParams["axes.labelsize"] = 21
13+
plt.rcParams['mathtext.fontset'] = 'stix'
14+
plt.rcParams['savefig.bbox']='tight'
15+
16+
curr_dir = os.getcwd()
17+
plt_dir_a04 = [f.name for f in os.scandir(curr_dir) if (f.is_dir() and re.search("^plt[0-9]{5,8}$",f.name))]
18+
plt_dir_a04.sort(key=lambda x: int(x[3:]))
19+
20+
dir_paths_a04 = []
21+
for dir in plt_dir_a04:
22+
dir_paths_a04.append(os.path.join(curr_dir, dir))
23+
24+
index_a04 = dict(zip(plt_dir_a04, [i for i in range(len(plt_dir_a04))]))
25+
26+
curr_dir = "../nova_t7_0.8km_ext_pert"
27+
plt_dir_a08 = [f.name for f in os.scandir(curr_dir) if (f.is_dir() and re.search("^plt[0-9]{5,8}$",f.name))]
28+
plt_dir_a08.sort(key=lambda x: int(x[3:]))
29+
30+
dir_paths_a08 = []
31+
for dir in plt_dir_a08:
32+
dir_paths_a08.append(os.path.join(curr_dir, dir))
33+
34+
index_a08 = dict(zip(plt_dir_a08, [i for i in range(len(plt_dir_a08))]))
35+
36+
curr_dir = "../nova_t7_0.2km"
37+
plt_dir_b02 = [f.name for f in os.scandir(curr_dir) if (f.is_dir() and re.search("^plt[0-9]{5,8}$",f.name))]
38+
plt_dir_b02.sort(key=lambda x: int(x[3:]))
39+
40+
dir_paths_b02 = []
41+
for dir in plt_dir_b02:
42+
dir_paths_b02.append(os.path.join(curr_dir, dir))
43+
44+
index_b02 = dict(zip(plt_dir_b02, [i for i in range(len(plt_dir_b02))]))
45+
46+
curr_dir = "../nova_t7_0.4km"
47+
plt_dir_b04 = [f.name for f in os.scandir(curr_dir) if (f.is_dir() and re.search("^plt[0-9]{5,8}$",f.name))]
48+
plt_dir_b04.sort(key=lambda x: int(x[3:]))
49+
50+
dir_paths_b04 = []
51+
for dir in plt_dir_b04:
52+
dir_paths_b04.append(os.path.join(curr_dir, dir))
53+
54+
index_b04 = dict(zip(plt_dir_b04, [i for i in range(len(plt_dir_b04))]))
55+
56+
ts_a08 = yt.DatasetSeries(dir_paths_a08)
57+
ts_a04 = yt.DatasetSeries(dir_paths_a04)
58+
59+
ts_b04 = yt.DatasetSeries(dir_paths_b04[0:138])
60+
ts_b02 = yt.DatasetSeries(dir_paths_b02[0:267])
61+
62+
N_a08 = len(plt_dir_a08)
63+
time_a08 = np.zeros(N_a08)
64+
qvalue_a08 = np.zeros(N_a08)
65+
66+
N_a04 = len(plt_dir_a04)
67+
time_a04 = np.zeros(N_a04)
68+
qvalue_a04 = np.zeros(N_a04)
69+
70+
N_b04 = len(plt_dir_b04[0:138])
71+
time_b04 = np.zeros(N_b04)
72+
qvalue_b04 = np.zeros(N_b04)
73+
74+
N_b02 = len(plt_dir_b02[0:267])
75+
time_b02 = np.zeros(N_b02)
76+
qvalue_b02 = np.zeros(N_b02)
77+
78+
comm = communication_system.communicators[-1]
79+
80+
for ds in ts_a04.piter():
81+
82+
id_i = index_a04[ds.basename]
83+
84+
sp = ds.all_data()
85+
86+
max_enuc = sp.max("enuc")
87+
time_a04[id_i] = ds.current_time.value
88+
qvalue_a04[id_i] = max_enuc
89+
90+
ds.index.clear_all_data()
91+
92+
comm.barrier()
93+
94+
for ds in ts_a08.piter():
95+
96+
id_i = index_a08[ds.basename]
97+
98+
sp = ds.all_data()
99+
100+
max_enuc = sp.max("enuc")
101+
time_a08[id_i] = ds.current_time.value
102+
qvalue_a08[id_i] = max_enuc
103+
104+
ds.index.clear_all_data()
105+
106+
for ds in ts_b02.piter():
107+
108+
id_i = index_b02[ds.basename]
109+
110+
sp = ds.all_data()
111+
112+
max_enuc = sp.max("enuc")
113+
time_b02[id_i] = ds.current_time.value
114+
qvalue_b02[id_i] = max_enuc
115+
116+
ds.index.clear_all_data()
117+
118+
for ds in ts_b04.piter():
119+
120+
id_i = index_b04[ds.basename]
121+
122+
sp = ds.all_data()
123+
124+
max_enuc = sp.max("enuc")
125+
time_b04[id_i] = ds.current_time.value
126+
qvalue_b04[id_i] = max_enuc
127+
128+
ds.index.clear_all_data()
129+
130+
time_a04[:] = comm.mpi_allreduce(time_a04[:], op="sum")
131+
qvalue_a04[:] = comm.mpi_allreduce(qvalue_a04[:], op="sum")
132+
133+
time_a08[:] = comm.mpi_allreduce(time_a08[:], op="sum")
134+
qvalue_a08[:] = comm.mpi_allreduce(qvalue_a08[:], op="sum")
135+
136+
time_b02[:] = comm.mpi_allreduce(time_b02[:], op="sum")
137+
qvalue_b02[:] = comm.mpi_allreduce(qvalue_b02[:], op="sum")
138+
139+
time_b04[:] = comm.mpi_allreduce(time_b04[:], op="sum")
140+
qvalue_b04[:] = comm.mpi_allreduce(qvalue_b04[:], op="sum")
141+
142+
if yt.is_root():
143+
144+
per = 10
145+
t_a04 = time_a04[::per]
146+
t_a08 = time_a08[::per]
147+
t_b02 = time_b02[::per]
148+
t_b04 = time_b04[::per]
149+
150+
q_a04 = qvalue_a04[::per]
151+
q_a08 = qvalue_a08[::per]
152+
q_b02 = qvalue_b02[::per]
153+
q_b04 = qvalue_b04[::per]
154+
155+
fig = plt.figure()
156+
ax = fig.add_subplot(111)
157+
ax.plot(t_a04, q_a04, label="Model A4", linestyle='--')
158+
ax.plot(t_a08, q_a08, label="Model A8", linestyle='--')
159+
ax.plot(t_b02, q_b02, label="Model B2", linestyle='-', linewidth=3.0)
160+
ax.plot(t_b04, q_b04, label="Model B4", linestyle='-', linewidth=3.0)
161+
162+
ax.set_xlabel(r'$t\,[s]$')
163+
ax.set_ylabel(r'$\dot{e}_{\mathrm{nuc},\mathrm{max}}\,[\mathrm{erg}\cdot \mathrm{g}^{-1}\,\mathrm{s}^{-1}]$')
164+
ax.set_yscale('log')
165+
ax.set_ylim(1.0e13, 1.0e19)
166+
ax.legend(loc='upper left')
167+
168+
fig.set_size_inches(8, 6)
169+
ax.tick_params(labelsize=21)
170+
plt.tight_layout()
171+
172+
fig.savefig('q_series_04_ext.pdf', bbox_inches="tight")
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""Helper functions for working with Castro diagnostic files (*_diag.out)
2+
3+
To use these in a standalone script, you can do one of the following:
4+
5+
* append $CASTRO_HOME/Util/scripts to sys.path at the top of your script:
6+
sys.path.append("<path to Castro>/Util/scripts")
7+
8+
* add a symlink to this file in the same directory as your script:
9+
$ ln -s "$CASTRO_HOME/Util/scripts/diag_parser.py" .
10+
11+
* copy this file into the same directory as your script
12+
13+
Then you can do `from diag_parser import deduplicate, read_diag_file`.
14+
"""
15+
16+
from pathlib import Path
17+
18+
import numpy as np
19+
20+
""" Format notes
21+
files are opened in Castro.cpp, data is written in sum_integrated_quantities.cpp
22+
23+
data_logs[0]: grid_diag.out
24+
intwidth, fixwidth, datwidth*
25+
26+
data_logs[1]: gravity_diag.out
27+
- this was previously missing the last column number (8), which we handle for
28+
backwards compatibility
29+
intwidth, fixwidth, datwidth, datwidth, datwidth, datwidth, datwidth, datwidth
30+
31+
data_logs[2]: species_diag.out
32+
intwidth, fixwidth, datwidth*
33+
34+
data_logs[3]: amr_diag.out
35+
- if compiled with GPU support, this will have two additional integer fields at
36+
the end with size `datwidth` for the GPU memory usage
37+
- column 5 (max number of subcycles) is an integer
38+
intwidth, fixwidth, fixwidth, intwidth, fixwidth, datwidth
39+
"""
40+
41+
datwidth = 25 # Floating point data in scientific notation
42+
fixwidth = 25 # Floating point data not in scientific notation
43+
intwidth = 12 # Integer data
44+
45+
# Any additional columns after these are assumed to be floating point values in
46+
# scientific notation (amr_diag.out gets special handling)
47+
FIELD_WIDTHS = {
48+
"grid_diag.out": [intwidth, fixwidth],
49+
"gravity_diag.out": [intwidth, fixwidth] + [datwidth] * 6,
50+
"species_diag.out": [intwidth, fixwidth],
51+
"amr_diag.out": [intwidth, fixwidth, fixwidth, intwidth, fixwidth, datwidth],
52+
}
53+
54+
55+
def read_diag_file(file_path):
56+
"""Reads a Castro diagnostic file into a numpy structured array.
57+
58+
Currently only supports the default files that Castro generates.
59+
"""
60+
if not isinstance(file_path, Path):
61+
file_path = Path(file_path)
62+
filetype = file_path.name
63+
if filetype not in FIELD_WIDTHS:
64+
raise ValueError("Unsupported file name")
65+
widths = FIELD_WIDTHS[filetype]
66+
with open(file_path, "r") as f:
67+
# try getting the number of columns from the first line
68+
first_line = f.readline().rstrip("\n")
69+
if filetype == "gravity_diag.out":
70+
# gravity_diag.out is missing the last column number, but it
71+
# fortunately has a fixed number of columns
72+
num_columns = 8
73+
else:
74+
num_columns = int(first_line.split()[-1])
75+
# pad out the widths list on the right if necessary
76+
widths.extend([datwidth] * (num_columns - len(widths)))
77+
# infer datatypes from the widths
78+
dtypes = [int if w == intwidth else float for w in widths]
79+
# amr_diag.out has several integer columns with long names
80+
if filetype == "amr_diag.out":
81+
dtypes[4] = int # max number of subcycles
82+
if num_columns >= 8:
83+
dtypes[6] = int # maximum gpu memory used
84+
dtypes[7] = int # minimum gpu memory free
85+
# already read the first header line, so we don't need to skip any rows
86+
data = np.genfromtxt(
87+
f, delimiter=widths, comments="#", dtype=dtypes, names=True
88+
)
89+
return data
90+
91+
92+
def deduplicate(data):
93+
"""Deduplicate based on the timestep, keeping the only last occurrence."""
94+
# get the unique indices into the reversed timestep array, so we find the
95+
# final occurrence of each timestep
96+
_, rev_indices = np.unique(data["TIMESTEP"][::-1], return_index=True)
97+
# np.unique() sorts by value, so we don't need to un-reverse rev_indices
98+
unique_indices = data.shape[0] - rev_indices - 1
99+
return data[unique_indices]
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import yt
2+
import os
3+
import re
4+
import numpy as np
5+
from yt.utilities.parallel_tools.parallel_analysis_interface import communication_system
6+
import matplotlib.pyplot as plt
7+
from yt.frontends.boxlib.api import CastroDataset
8+
9+
plt.rcParams['font.size'] = 12
10+
plt.rcParams['font.family'] = 'serif'
11+
plt.rcParams['mathtext.fontset'] = 'stix'
12+
plt.rcParams['savefig.bbox']='tight'
13+
14+
curr_dir = os.getcwd()
15+
16+
plt_dir = [f.name for f in os.scandir(curr_dir) if (f.is_dir() and re.search("^plt+[0-9]{5,8}$",f.name))]
17+
plt_dir.sort(key=lambda x: int(x[3:]))
18+
19+
dir_paths = []
20+
for dir in plt_dir:
21+
dir_paths.append(os.path.join(curr_dir, dir))
22+
23+
fig = plt.figure()
24+
ax = fig.add_subplot(111)
25+
ax.set_xlabel(r'$y\,[\mathrm{km}]$')
26+
ax.set_ylabel(r'$\rho\,[\mathrm{g/cm^3}]$')
27+
28+
times = [300, 931, 1524, 1532]
29+
30+
for time in times:
31+
32+
if time == 1532:
33+
ds = ds = CastroDataset(dir_paths[-2])
34+
else:
35+
id = int(time/0.5)
36+
ds = CastroDataset(dir_paths[id])
37+
38+
sp = ds.all_data()
39+
res = 960
40+
profile = yt.create_profile(
41+
sp,
42+
[("boxlib", "y")], [("boxlib", "density")],
43+
weight_field=('boxlib', 'cell_volume'),
44+
accumulation=False,
45+
n_bins=res,
46+
)
47+
48+
y = profile.x.to("km")
49+
val = profile[("boxlib", "density")]
50+
ax.plot(y, val, label="${:.2f}\,[s]$".format(ds.current_time.value))
51+
52+
ax.legend()
53+
54+
fig.set_size_inches(5, 7)
55+
ax.tick_params(labelsize=14)
56+
ax.set_ylim(1.0e-1, 5.0e5)
57+
ax.set_yscale('log')
58+
plt.tight_layout()
59+
60+
fig.savefig('lateral_dens_04_ext.pdf', bbox_inches="tight")

0 commit comments

Comments
 (0)