|
| 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