Skip to content

Commit c9f724d

Browse files
authored
add a plot showing the network flow at a point (#3150)
This reads the data from the location of peak enuc and uses pynucastro to visualize the network flow
1 parent 8f7bc49 commit c9f724d

File tree

2 files changed

+180
-0
lines changed

2 files changed

+180
-0
lines changed

Exec/science/flame_wave/analysis/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,14 @@ Create a stacked plot of abar at a sequence of time points.
8686
## `schlieren.py`
8787

8888
Make a Schlieren plot (a plot of ln{(∇^2 ρ) / ρ}) of a dataset.
89+
90+
## `netflow.py``
91+
92+
Plot the enuc slice and the flow through the network at a particular
93+
point. This requires defining a reference plotfile, from which we
94+
find the location of the maximum enuc. The idea is that we use that
95+
same reference location for all times to visualize the evolution of
96+
the composition through the network.
97+
98+
You need to have MICROPHYSICS_HOME set and the script needs to be
99+
edited to indicate which network you are using.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import argparse
2+
import importlib
3+
import os
4+
import sys
5+
from pathlib import Path
6+
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
import pynucastro as pyna
10+
import yt
11+
from pynucastro.yt_utils import get_point, to_conditions
12+
from yt.units import cm
13+
14+
# simulation
15+
16+
def doit(plotfile, reference):
17+
18+
# the reference file is used to find the location at which we are
19+
# going to examine the network flow
20+
21+
ds_r = yt.load(reference)
22+
23+
val, loc = ds_r.find_max("enuc")
24+
25+
print("using location for network flow: ", loc)
26+
27+
# now load the plotfile we will plot
28+
29+
if plotfile == reference:
30+
ds = ds_r
31+
else:
32+
ds = yt.load(plotfile)
33+
34+
field = "enuc"
35+
36+
# get the thermodynamic data at our desired location
37+
# from the current (not reference) plotfile
38+
39+
pt = get_point(ds, loc)
40+
rho, T, comp = to_conditions(pt)
41+
42+
43+
# network
44+
mp = os.getenv("MICROPHYSICS_HOME")
45+
46+
moddir = Path(mp) / "networks" / "he-burn" / "cno-he-burn-34am"
47+
sys.path.insert(0, str(moddir))
48+
49+
import cno_he_burn_34am as pynet
50+
51+
net = pynet.create_network()
52+
net.summary()
53+
54+
# setup the figure where we will host the image
55+
56+
fig = plt.figure(figsize=(19.2, 10.8))
57+
58+
inch = 0.3
59+
W, H = fig.get_size_inches()
60+
margin = (inch / W, inch / H)
61+
fig.set_layout_engine('constrained',
62+
rect=[margin[0], margin[1],
63+
1.0 - 2.0*margin[0], 1.0 - 2.0*margin[1]])
64+
65+
gs = fig.add_gridspec(nrows=2, ncols=1,
66+
height_ratios=[1.5, 5.0])
67+
68+
ax_img = fig.add_subplot(gs[0, 0])
69+
gs_flow = gs[1, 0].subgridspec(2, 2, height_ratios=(20, 1))
70+
71+
72+
# setup domain size
73+
# we'll use a buffer size that is proportional to the number of zones
74+
# in the data we are plotting
75+
76+
xmin = ds.domain_left_edge[0]
77+
xmax = ds.domain_right_edge[0]
78+
xctr = 0.5*(xmin + xmax)
79+
L_x = xmax - xmin
80+
81+
ymin = 0.0*cm
82+
ymax = 1.2288e4*cm
83+
84+
yctr = 0.5*(ymin + ymax)
85+
L_y = ymax - ymin
86+
87+
nx, ny, nz = ds.domain_dimensions
88+
ref = int(np.prod(ds.ref_factors[0:ds.max_level]))
89+
90+
dx = ds.domain_width[0] / nx / ref
91+
dy = ds.domain_width[1] / ny / ref
92+
93+
thinning = 1
94+
95+
pxls = int(L_x / dx / thinning), int(L_y / dy / thinning)
96+
97+
# do the plotting
98+
99+
p = yt.SlicePlot(ds, "theta", field,
100+
center=[xctr, yctr, 0.0*cm], width=[L_x, L_y, 0.0*cm])
101+
p.set_buff_size(pxls)
102+
p.set_zlim("enuc", 1.e15, 3.e19)
103+
p.set_background_color("enuc", None)
104+
p.set_axes_unit("cm")
105+
106+
107+
# get the image data and replot it on our axes
108+
109+
im = p[field].image
110+
111+
# Recreate the image on our axes with same appearance
112+
data = im.get_array()
113+
cmap = im.get_cmap()
114+
norm = im.norm
115+
extent = im.get_extent()
116+
origin = getattr(im, "origin", "lower")
117+
118+
119+
im_new = ax_img.imshow(data, cmap=cmap, norm=norm, extent=extent, origin=origin)
120+
ax_img.set_xlabel("r [cm]")
121+
ax_img.set_ylabel("z [cm]")
122+
123+
# keep physical aspect but within the GridSpec cell
124+
ax_img.set_aspect("equal", adjustable="box")
125+
126+
ax_img.scatter([loc[0]], [loc[1]], marker="x", color="red")
127+
128+
# and add a colorbar
129+
cb = fig.colorbar(im_new, ax=ax_img, orientation="horizontal", shrink=0.8)
130+
cb.set_label(field)
131+
132+
133+
# network flow part
134+
135+
net.plot(rho, T, comp,
136+
screen_func=pyna.screening.screen.screen5,
137+
rotated=True, hide_xp=True, hide_xalpha=True,
138+
use_net_rate=True,
139+
color_nodes_by_abundance=True,
140+
node_size=500, node_font_size="9",
141+
grid_spec=gs_flow)
142+
143+
# text
144+
145+
fig.text(0.05, 0.02, f"time = {float(ds.current_time*1000):5.1f} ms",
146+
transform=fig.transFigure, fontsize="12")
147+
148+
# finalize
149+
fig.savefig(f"{os.path.basename(plotfile)}_netflow.png")
150+
151+
152+
if __name__ == "__main__":
153+
154+
p = argparse.ArgumentParser(description="plot enuc and the flow through the reaction network")
155+
156+
p.add_argument("plotfile",
157+
type=lambda p: Path(p).resolve() if Path(p).is_dir() else parser.error(f"{p} is not a directory"),
158+
nargs=1,
159+
help="plotfile to visualize (enuc slice + network flow")
160+
p.add_argument("--reference", type=str,
161+
default=None, help="reference file to use for finding location of max enuc")
162+
163+
args = p.parse_args()
164+
ref = args.reference
165+
if args.reference is None:
166+
ref = args.plotfile[0]
167+
168+
print("reference = ", ref)
169+
doit(args.plotfile[0], ref)

0 commit comments

Comments
 (0)