def burning_limiter(eps_filename, results_base): """Plot the effects of both burning timestep limiters (castro.dtnuc_e and castro.dtnuc_X).""" if (os.path.isfile(eps_filename)): return results_dir = results_base + 'burning_limiter_e/' # Get the list of parameter values we have tried dtnuc_list = wdmerger.get_parameter_list(results_dir) ni56_arr = get_ni56(results_dir) dtnuc_list = [dtnuc[len('dt'):] for dtnuc in dtnuc_list] plt.plot(np.array(dtnuc_list), np.array(ni56_arr), linestyle=linestyles[0], lw=4.0, label=r'$\Delta t_{be}$') results_dir = results_base + 'burning_limiter_X/' # Get the list of parameter values we have tried dtnuc_list = wdmerger.get_parameter_list(results_dir) ni56_arr = get_ni56(results_dir) dtnuc_list = [dtnuc[len('dt'):] for dtnuc in dtnuc_list] plt.plot(np.array(dtnuc_list), np.array(ni56_arr), linestyle=linestyles[1], lw=4.0, label=r'$\Delta t_{bX}$') plt.xscale('log') plt.xlabel(r"Nuclear burning timestep factor", fontsize=20) plt.ylabel(r"$^{56}$Ni generated (M$_{\odot}$)", fontsize=20) plt.tick_params(labelsize=16) plt.legend(loc='best') plt.tight_layout() plt.savefig(eps_filename) wdmerger.insert_commits_into_eps(eps_filename, get_diagfile(results_dir), 'diag') plt.close()
def c_fraction(out_filename, results_base): """Create a table with the nickel generation as a function of the C/O fraction.""" if (os.path.isfile(out_filename)): return # Get the list of parameter values we have tried results_dir = results_base + '/co' param_list = wdmerger.get_parameter_list(results_dir) c_list = [param.split('c')[1].split('o')[0] for param in param_list] ni56_list = get_ni56(results_dir) comment = '%\n' + \ '% Summary of the effect of C/O mass fraction \n' + \ '% on 56Ni yield in a 2D white dwarf collision.\n' + \ '% The first column is the initial carbon mass \n' + \ '% fraction and the second is the final nickel \n' + \ '% mass produced, in solar masses.\n' + \ '%\n' caption = ' Maximum $^{56}Ni$ mass ($M_{\odot}) produced as a function of the ' + \ 'initial mass fraction $C$. Since the white dwarfs are purely ' + \ 'carbon/oxygen the initial oxygen fraction is $1 - C$.' col1title = '$C$' label = 'co' write_ni56_table(results_dir, out_filename, c_list, ni56_list, comment, caption, col1title, label)
def eta3(out_filename, results_base): """Create a table with the nickel generation as a function of the dual energy eta3 parameter.""" if (os.path.isfile(out_filename)): return # Get the list of parameter values we have tried results_dir = results_base + '/eta3' param_list = wdmerger.get_parameter_list(results_dir) eta_list = [param[3:] for param in param_list] ni56_list = get_ni56(results_dir) comment = '%\n' + \ '% Summary of the effect of the dual energy parameter \n' + \ '% castro.dual_energy_eta3 on 56Ni yield in a 2D white \n' + \ '% dwarf collision.\n' + \ '% The first column is the value of eta3 and the second \n' + \ '% is the final nickel mass produced, in solar masses.\n' + \ '%\n' caption = 'Maximum $^{56}Ni$ mass ($M_{\odot}) produced as a function of the ' + \ 'dual energy formalism parameter $\\eta_3$.' col1title = '$\\eta_3$' label = 'eta3' write_ni56_table(results_dir, out_filename, eta_list, ni56_list, comment, caption, col1title, label)
def get_ni56(results_dir, prefix=''): """Return a list of maximum 56Ni production from all completed sub-directories in results_dir.""" import numpy as np ni56_arr = [] dir_list = wdmerger.get_parameter_list(results_dir) # Strip out those directories that don't match the prefix. if (prefix != ''): dir_list = [dir for dir in dir_list if dir[0:len(prefix)] == prefix] if (dir_list == []): return ni56_arr diag_filename_list = [ results_dir + '/' + directory + '/output/species_diag.out' for directory in dir_list ] # Ensure all of the output files are there. for diag_file in diag_filename_list: if not os.path.isfile(diag_file): return ni56_arr ni56_arr = [ np.amax(wdmerger.get_column('Mass ni56', diag_filename)) - np.amin(wdmerger.get_column('Mass ni56', diag_filename)) for diag_filename in diag_filename_list ] return ni56_arr
def get_e_release(results_dir): """Return a list of energy generation from all completed sub-directories in results_dir.""" import wdmerger_grid_diag_analysis as grid_diag import numpy as np dir_list = wdmerger.get_parameter_list(results_dir) if (dir_list == []): return diag_filename_list = [ results_dir + '/' + directory + '/output/grid_diag.out' for directory in dir_list ] e_arr = [ np.amax(wdmerger.get_column('TOTAL ENERGY', diag_filename)) - np.amin(wdmerger.get_column('TOTAL ENERGY', diag_filename)) for diag_filename in diag_filename_list ] # Divide by 10**51 e_arr = [e / 1.0e51 for e in e_arr] return e_arr
def small_temp(out_filename, results_base): """Create a table with the nickel generation as a function of the temperature floor.""" if (os.path.isfile(out_filename)): return # Get the list of parameter values we have tried results_dir = results_base + '/small_temp' param_list = wdmerger.get_parameter_list(results_dir) temp_list = [param[1:] for param in param_list] ni56_list = get_ni56(results_dir) comment = '%\n' + \ '% Summary of the effect of the temperature floor \n' + \ '% castro.small_temp on 56Ni yield in a 2D white \n' + \ '% dwarf collision.\n' + \ '% The first column is the temperature floor and the \n' + \ '% second is the final nickel mass produced, in solar masses.\n' + \ '%\n' caption = 'Maximum $^{56}Ni$ mass ($M_{\odot}) produced as a function of the ' + \ 'temperature floor.' col1title = '$T_{\\text{floor}}$' label = 'smalltemp' write_ni56_table(results_dir, out_filename, temp_list, ni56_list, comment, caption, col1title, label)
def rho_min(out_filename, results_base): """Create a table with the nickel generation as a function of the minimum density for reactions.""" if (os.path.isfile(out_filename)): return # Get the list of parameter values we have tried results_dir = results_base + '/rho_min' param_list = wdmerger.get_parameter_list(results_dir) temp_list = [param[3:] for param in param_list] ni56_list = get_ni56(results_dir) comment = '%\n' + \ '% Summary of the effect of the minimum density\n' + \ '% for reactions on 56Ni yield in a 2D white \n' + \ '% dwarf collision.\n' + \ '% The first column is the density minimum and the \n' + \ '% second is the final nickel mass produced, in solar masses.\n' + \ '%\n' caption = 'Maximum $^{56}Ni$ mass ($M_{\odot}) produced as a function of the ' + \ 'minimum density for allowing nuclear reactions.' col1title = '$\\rho_{\\text{min}}$' label = 'tmin' write_ni56_table(results_dir, out_filename, temp_list, ni56_list, comment, caption, col1title, label)
def get_abar(results_dir, prefix=''): """Return a list of maximum 56Ni production from all completed sub-directories in results_dir.""" import numpy as np abar_arr = [] dir_list = wdmerger.get_parameter_list(results_dir) # Strip out those directories that don't match the prefix. if (prefix != ''): dir_list = [dir for dir in dir_list if dir[0:len(prefix)] == prefix] if (dir_list == []): return abar_arr diag_filename_list = [ results_dir + '/' + directory + '/output/species_diag.out' for directory in dir_list ] # Ensure all of the output files are there. for diag_file in diag_filename_list: if not os.path.isfile(diag_file): return abar_arr abar_arr = [] for diag_filename in diag_filename_list: col_names, col_data = wdmerger.get_column_data(diag_filename) # The only thing we need is the last row, and we can # skip the first two columns (timestep, simulation time). spec_names = col_names[2:] spec_data = col_data[-1, 2:] # Normalize the species by the total mass. spec_data /= sum(spec_data) # Get the atomic masses of each element by stripping out # only the digits from each column header. spec_masses = [ int(''.join(c for c in s if c.isdigit())) for s in spec_names ] # Now compute abar. abar = sum(spec_masses * spec_data) abar_arr.append(abar) return abar_arr
def burning_limiter_X(eps_filename, results_base, do_ni56=True): """Plot the effect of the burning timestep limiter castro.dtnuc_X.""" if (os.path.isfile(eps_filename)): return else: print("Generating file %s" % eps_filename) results_dir = results_base + 'burning_limiter_X/' if not os.path.isdir(results_dir): return # Get the list of parameter values we have tried dtnuc_list = wdmerger.get_parameter_list(results_dir) if (dtnuc_list == []): return if (do_ni56): result_arr = np.array(get_ni56(results_dir)) else: result_arr = np.array(get_abar(results_dir)) # Don't make the plot if we have fewer than two data points. if len(result_arr) < 2: return dtnuc_list = np.array([float(dtnuc[len('dt'):]) for dtnuc in dtnuc_list]) # Sort the lists result_arr = np.array([x for _, x in sorted(zip(dtnuc_list, result_arr))]) dtnuc_list = sorted(dtnuc_list) plt.plot(dtnuc_list, result_arr, linestyle=linestyles[0], lw=4.0, color=colors[0]) plt.xscale('log') plt.xlabel(r"Nuclear burning timestep factor $f_{bX}$", fontsize=20) if (do_ni56): plt.ylabel(r"$^{56}$Ni generated (M$_{\odot}$)", fontsize=20) else: plt.ylabel(r"$\overline{A}$", fontsize=20) plt.tick_params(labelsize=16) plt.tight_layout() plt.savefig(eps_filename) wdmerger.insert_commits_into_eps(eps_filename, get_diagfile(results_dir), 'diag') png_filename = eps_filename[0:-3] + "png" plt.savefig(png_filename) plt.close()
def rho_min(out_filename, results_base): """Create a table with the nickel generation as a function of the minimum density for reactions.""" if (os.path.isfile(out_filename)): return else: print("Generating file %s" % out_filename) # Get the list of parameter values we have tried results_dir = results_base + '/rho_min' if not os.path.isdir(results_dir): return param_list = wdmerger.get_parameter_list(results_dir) if (param_list == []): return temp_list = [float(param[3:]) for param in param_list] ni56_list = get_ni56(results_dir) # Sort the lists ni56_list = np.array([x for _, x in sorted(zip(temp_list, ni56_list))]) temp_list = sorted(temp_list) # Return temp_list to scientific notation temp_list = np.array(["{:.1e}".format(t) for t in temp_list]) comment = '%\n' + \ '% Summary of the effect of the minimum density\n' + \ '% for reactions on 56Ni yield in a white \n' + \ '% dwarf collision.\n' + \ '% The first column is the density minimum and the \n' + \ '% second is the final nickel mass produced, in solar masses.\n' + \ '%\n' title = 'Effect of the density floor for reactions' col1title = '$\\rho_{\\text{min}}$' label = 'tmin' write_ni56_table(results_dir, out_filename, temp_list, ni56_list, comment, col1title, label, title=title)
def burning_limiter_mode(out_filename, results_base): """Create a table with the nickel generation as a function of the mode used for timestep limiting.""" import os if os.path.isfile(out_filename): return else: print("Generating file %s" % out_filename) # Get the list of parameter values we have tried results_dir = results_base + '/burning_limiter_mode' if not os.path.isdir(results_dir): return param_list = wdmerger.get_parameter_list(results_dir) if (param_list == []): return mode_list = [param[4:] for param in param_list] ni56_list = get_ni56(results_dir) comment = '%\n' + \ '% Summary of the effect of the timestep limiting mode \n' + \ '% on 56Ni yield in a white dwarf collision.\n' + \ '% The first column is the limiter mode \n' + \ '% and the second is the final nickel \n' + \ '% mass produced, in solar masses.\n' + \ '%\n' caption = 'The burning limiter modes are explained in \\autoref{sec:hydrocoupling}.' col1title = 'Mode' title = 'Burning Limiter Mode' label = 'burninglimitermode' write_ni56_table(results_dir, out_filename, mode_list, ni56_list, comment, col1title, label, title=title, caption=caption)
def stellar_masses(eps_filename, results_base): """Plot the WD masses as a function of time.""" if not is_root(): return import os if not os.path.exists(results_base): return import matplotlib.pyplot as plt import numpy as np res_list = wdmerger.get_parameter_list(results_base) directory_list = [results_base + '/' + res for res in res_list] for i, directory in enumerate(directory_list): eps_filename_curr = eps_filename.replace('.eps', '_n_' + res_list[i][1:] + '.eps') if os.path.isfile(eps_filename_curr): continue p_diag = directory + '/output/primary_diag.out' s_diag = directory + '/output/secondary_diag.out' p_time = wdmerger.get_column('TIME', p_diag) p_mass = wdmerger.get_column('PRIMARY MASS', p_diag) s_time = wdmerger.get_column('TIME', s_diag) s_mass = wdmerger.get_column('SECONDARY MASS', s_diag) p_mask = np.where(p_time <= 100.0) s_mask = np.where(s_time <= 100.0) plt.plot(np.array(p_time)[p_mask], np.array(p_mass)[p_mask] / np.array(p_mass)[0], lw = 4.0, linestyle = linestyles[0], markersize = 12.0, markevery = 2000, label = 'Primary') plt.plot(np.array(s_time)[s_mask], np.array(s_mass)[s_mask] / np.array(s_mass)[0], lw = 4.0, linestyle = linestyles[1], markersize = 12.0, markevery = 2000, label = 'Secondary') plt.tick_params(labelsize = 20) plt.xlabel('Time (s)', fontsize = 24) plt.ylabel('WD Mass / Initial Mass', fontsize = 24) plt.legend(loc = 'best', prop = {'size':20}, fancybox = True, framealpha = 0.5) plt.tight_layout() plt.savefig(eps_filename_curr) plt.close()
def get_diagfile(results_dir): """Return the name of a diagnostics file in results_dir that is completed. Useful for the functions that insert git commits into files and need a representative diagnostic file to get the git commits from. We arbitrarily pick the last directory.""" dir_list = wdmerger.get_parameter_list(results_dir) diag_filename_list = [ results_dir + '/' + directory + '/output/species_diag.out' for directory in dir_list ] diag_filename = diag_filename_list[-1] return diag_filename
def get_ni56(results_dir): """Return a list of maximum 56Ni production from all completed sub-directories in results_dir.""" import numpy as np dir_list = sorted(wdmerger.get_parameter_list(results_dir)) diag_filename_list = [ results_dir + '/' + directory + '/output/species_diag.out' for directory in dir_list ] ni56_arr = [ np.amax(wdmerger.get_column('Mass ni56', diag_filename)) for diag_filename in diag_filename_list ] return ni56_arr
def stellar_distance(eps_filename, results_base): """Plot the WD distance as a function of time.""" if not is_root(): return import os if os.path.isfile(eps_filename): return if not os.path.exists(results_base): return import matplotlib.pyplot as plt import numpy as np res_list = wdmerger.get_parameter_list(results_base) res_list = sorted([int(res[1:]) for res in res_list]) diag_list = [results_base + '/n' + str(res) + '/output/star_diag.out' for res in res_list] for i, diag in enumerate(diag_list): eps_filename_curr = eps_filename.replace('.eps', '_n_' + str(res_list[i]) + '.eps') if os.path.isfile(eps_filename_curr): return time = np.array(wdmerger.get_column('TIME', diag)) dist = np.array(wdmerger.get_column('WD DISTANCE', diag)) mask = np.where(dist > 0.0) plt.plot(time[mask], dist[mask] / dist[0], lw = 4.0, linestyle = linestyles[0]) plt.tick_params(labelsize = 20) plt.xlabel('Time (s)', fontsize = 24) plt.ylabel('WD Distance / Initial Distance', fontsize = 24) plt.tight_layout() plt.savefig(eps_filename_curr) plt.close()
def stellar_distance_convergence(eps_filename, results_base): """Plot the WD distance as a function of resolution.""" if not is_root(): return import os if os.path.isfile(eps_filename): return if not os.path.exists(results_base): return import matplotlib.pyplot as plt import numpy as np res_list = wdmerger.get_parameter_list(results_base) res_list = sorted([int(res[1:]) for res in res_list]) diag_list = [results_base + '/n' + str(res) + '/output/star_diag.out' for res in res_list] for i, diag in enumerate(diag_list): time = wdmerger.get_column('TIME', diag) dist = wdmerger.get_column('WD DISTANCE', diag) mask = np.where(time <= 50.0) plt.plot(np.array(time)[mask], np.array(dist)[mask] / np.array(dist)[0], lw = 4.0, linestyle = linestyles[i], marker = markers[i], markersize = 12.0, markevery = 2000, label = 'n = ' + str(res_list[i])) plt.tick_params(labelsize = 20) plt.xlabel('Time (s)', fontsize = 24) plt.ylabel('WD Distance / Initial Distance', fontsize = 24) plt.legend(loc = 'best', prop = {'size':20}, fancybox = True, framealpha = 0.5) plt.tight_layout() plt.savefig(eps_filename) plt.close()
def impact_parameter(eps_filename, results_dir): """Plot the effect of the impact parameter.""" import os if os.path.isfile(eps_filename): return import numpy as np from matplotlib import pyplot as plt # Get the list of parameter values we have tried dtnuc_list = wdmerger.get_parameter_list(results_dir) ni56_arr = get_ni56(results_dir) b_list = [dtnuc[len('b'):] for dtnuc in dtnuc_list] b_list = sorted(b_list) plt.plot(np.array(b_list), np.array(ni56_arr), markers[0], markersize=12.0) xaxis_buffer = 0.025 plt.xlim( [float(b_list[0]) - xaxis_buffer, float(b_list[-1]) + xaxis_buffer]) plt.xlabel(r"Impact parameter $b$", fontsize=24) plt.ylabel(r"$^{56}$Ni generated (M$_{\odot}$)", fontsize=24) plt.tick_params(labelsize=20) plt.tight_layout() plt.savefig(eps_filename) wdmerger.insert_commits_into_eps(eps_filename, get_diagfile(results_dir), 'diag') plt.close()
def burning_mode(out_filename, results_base): """Create a table with the nickel generation as a function of the burning_mode parameter.""" if (os.path.isfile(out_filename)): return # Get the list of parameter values we have tried results_dir = results_base + '/burning_mode' param_list = wdmerger.get_parameter_list(results_dir) mode_list = [param for param in param_list] ni56_list = get_ni56(results_dir) comment = '%\n' + \ '% Summary of the effect of the burning mode \n' + \ '% for reactions on 56Ni yield in a 2D white \n' + \ '% dwarf collision.\n' + \ '% The first column is the density minimum and the \n' + \ '% second is the final nickel mass produced, in solar masses.\n' + \ '%\n' caption = 'Maximum $^{56}Ni$ mass ($M_{\odot}) produced as a function of the ' + \ 'burning mode for allowing nuclear reactions. Burning mode 0 is a ' + \ 'hydrostatic burn, mode 1 is a self-heating burn, mode 2 is a hybrid ' + \ 'burn, and mode 3 is a suppressed burn. The meaning of these burning ' + \ 'modes is explained in the text.' col1title = 'Burning Mode' label = 'burningmode' write_ni56_table(results_dir, out_filename, mode_list, ni56_list, comment, caption, col1title, label)
def amr_detonation(eps_filename, results_base): """Plot the effect of the refinement based on the nuclear burning rate on the detonation conditions.""" import os if os.path.isfile(eps_filename): return else: print("Generating file %s" % eps_filename) import math import numpy as np from matplotlib import pyplot as plt if not os.path.isdir(results_base): return diag_file = None # First, generate a plot of nickel production. ncell_list = sorted([int(n[1:]) for n in os.listdir(results_base)]) # Now, generate a plot of the distance from the center of the ignition point. i = 0 for ncell in ncell_list: results_dir = results_base + 'n' + str(ncell) + '/self-heat/dxnuc/' if not os.path.isdir(results_dir): continue # Get the list of parameter values we have tried r_list = wdmerger.get_parameter_list(results_dir) # Strip out the non-refinement directories r_list = [r for r in r_list if r[0] == 'r'] if (r_list == []): continue # Sort them numerically. r_list = ['r' + str(r) for r in sorted([int(r[1:]) for r in r_list])] # Cycle through the plot files. # Get the maximum value of t_sound_t_enuc, and its distance from the origin. # Stop if we hit a detonation (t_sound_t_enuc > 1). for r in r_list: results_dir = results_base + 'n' + str( ncell) + '/self-heat/dxnuc/' + r prefix = 'smallplt' plt_list = [ results_dir + '/output/' + plt for plt in wdmerger.get_plotfiles(results_dir, prefix=prefix) ] for plt in plt_list: [ts_te_max, x, y, z] = wdmerger.get_maxloc(plt, 't_sound_t_enuc') if ts_te_max > 1.0: [rho_max, x, y, z] = wdmerger.get_maxloc(plt, 'density') dist = np.sqrt(x**2 + y**2) time = wdmerger.get_time_from_plotfile(plt) print(ncell, r, time, rho_max, ts_te_max, dist.v / 1.e5) break i += 1
def rho_T_sliceplots(output_base, results_base, smallplt=True, prefix="", domain_frac=1.0, x_ticks=[2.0e9, 4.0e9], y_ticks=[2.0e9, 4.0e9], scale_exp=9): """Create a rho/T sliceplot for every plotfile in a given directory.""" import os if not os.path.isdir(output_base): os.makedirs(output_base) from PIL import Image if (smallplt): plt_prefix = 'smallplt' r_list = wdmerger.get_parameter_list(results_base) # Strip out the non-refinement directories r_list = [r for r in r_list if r[0] == 'r'] if (r_list == []): return dir_list = [results_base + r + '/output/' for r in r_list] for param, directory in zip(r_list, dir_list): output_dir = output_base + param if not os.path.isdir(output_dir): os.makedirs(output_dir) plt_list = wdmerger.get_plotfiles(directory, plt_prefix) eps_list = [ output_dir + "/rho_T_slice" + prefix + "_" + param + "_t_" + str("%.2f" % wdmerger.get_time_from_plotfile(directory + pltfile)) + '.eps' for pltfile in plt_list ] # Generate the plot for eps_file, pltfile in zip(eps_list, plt_list): if os.path.isfile(eps_file): continue print("Generating plot with filename " + eps_file) wdmerger.rho_T_sliceplot(eps_file, directory + pltfile, domain_frac=domain_frac, x_ticks=x_ticks, y_ticks=y_ticks, scale_exp=scale_exp) jpg_list = [eps.replace('eps', 'jpg') for eps in eps_list] mpg_filename = output_dir + "/rho_T_slice" + prefix + "_" + param + ".mpg" if not os.path.isfile(mpg_filename): print("Generating file %s" % mpg_filename) wdmerger.make_movie(output_dir, jpg_list, mpg_filename)
def ode_tolerances(eps_filename, results_base): """Plot the effects of all ODE tolerance options.""" if (os.path.isfile(eps_filename)): return else: print("Generating file %s" % eps_filename) results_dir = results_base + 'spec_tol/' if not os.path.isdir(results_dir): return # Get the list of parameter values we have tried s_tol_list = wdmerger.get_parameter_list(results_dir) if (s_tol_list == []): return ni56_s_arr = np.array(get_ni56(results_dir)) tol_s_list = [tol[len('tol'):] for tol in tol_s_list] tol_s_list = np.array([float(tol.replace('d', 'e')) for tol in tol_s_list]) # Sort the lists ni56_s_arr = np.array([x for _, x in sorted(zip(tol_s_list, ni56_s_arr))]) tol_s_list = sorted(tol_s_list) results_dir = results_base + 'temp_tol/' if not os.path.isdir(results_dir): return # Get the list of parameter values we have tried tol_t_list = wdmerger.get_parameter_list(results_dir) if (tol_t_list == []): return ni56_t_arr = np.array(get_ni56(results_dir)) tol_t_list = [tol[len('tol'):] for tol in tol_t_list] tol_t_list = np.array([float(tol.replace('d', 'e')) for tol in tol_t_list]) # Sort the lists ni56_t_arr = np.array([x for _, x in sorted(zip(tol_t_list, ni56_t_arr))]) tol_t_list = sorted(tol_t_list) results_dir = results_base + 'enuc_tol/' if not os.path.isdir(results_dir): return # Get the list of parameter values we have tried tol_e_list = wdmerger.get_parameter_list(results_dir) if (tol_e_list == []): return ni56_e_arr = np.array(get_ni56(results_dir)) tol_e_list = [tol[len('tol'):] for tol in tol_e_list] tol_e_list = np.array([float(tol.replace('d', 'e')) for tol in tol_e_list]) # Sort the lists ni56_e_arr = np.array([x for _, x in sorted(zip(tol_e_list, ni56_e_arr))]) tol_e_list = sorted(tol_e_list) plt.plot(tol_s_list, ni56_s_arr, linestyle=linestyles[0], lw=4.0, label=r'Species Tolerance') plt.plot(tol_t_list, ni56_t_arr, linestyle=linestyles[1], lw=4.0, label=r'Temperature Tolerance') plt.plot(tol_e_list, ni56_e_arr, linestyle=linestyles[2], lw=4.0, label=r'Energy Tolerance') plt.xscale('log') plt.xlabel(r"ODE Error Tolerance", fontsize=20) plt.ylabel(r"$^{56}$Ni generated (M$_{\odot}$)", fontsize=20) plt.tick_params(labelsize=16) plt.legend(loc='best') plt.tight_layout() plt.savefig(eps_filename) wdmerger.insert_commits_into_eps(eps_filename, get_diagfile(results_dir), 'diag') png_filename = eps_filename[0:-3] + "png" plt.savefig(png_filename) plt.close()
def amr_nickel(eps_filename, results_base): """Plot the effect of the refinement based on the nuclear burning rate on the nickel generation.""" import os if os.path.isfile(eps_filename): return else: print("Generating file %s" % eps_filename) import math import numpy as np from matplotlib import pyplot as plt if not os.path.isdir(results_base): return diag_file = None # First, generate a plot of nickel production. ncell_list = sorted([int(n[1:]) for n in os.listdir(results_base)]) i = 0 for ncell in ncell_list: results_dir = results_base + 'n' + str(ncell) + '/self-heat/dxnuc/' if not os.path.isdir(results_dir): continue # Get the list of parameter values we have tried r_list = wdmerger.get_parameter_list(results_dir) # Strip out the non-refinement directories r_list = [r for r in r_list if r[0] == 'r'] if (r_list == []): continue r_list = [float(r[1:]) for r in r_list] ni56_arr = get_ni56(results_dir, 'r') if ni56_arr == []: continue if diag_file == None and get_diagfile(results_dir) != None: diag_file = get_diagfile(results_dir) # Sort the lists ni56_arr = np.array([x for _, x in sorted(zip(r_list, ni56_arr))]) r_list = np.array(sorted(r_list)) zonesPerDim = [ncell * int(r) for r in r_list] plt.plot(zonesPerDim, ni56_arr, markers[i], markersize=12, linestyle=linestyles[i], lw=4.0, label='n = ' + str(ncell)) i += 1 plt.tick_params(axis='both', which='major', pad=10) plt.xscale('log', basex=2) plt.ylim([0.0, 0.6]) plt.xlabel(r"Effective zones/dimension", fontsize=24) plt.ylabel(r"$^{56}$Ni generated (M$_{\odot}$)", fontsize=24) plt.tick_params(labelsize=16) plt.legend(loc='best', prop={'size': 20}) plt.tight_layout() plt.savefig(eps_filename) wdmerger.insert_commits_into_eps(eps_filename, diag_file, 'diag') png_filename = eps_filename[0:-3] + "png" plt.savefig(png_filename) plt.close()
def amr_ignition(file_base, results_base, do_amr=True): """Plot the effect of the resolution on the detonation conditions.""" if not os.path.isdir(results_base): return size = 1.6384e9 ncell_list = sorted([int(n[1:]) for n in os.listdir(results_base)]) res_lists = [[]] * len(ncell_list) dist_lists = [[]] * len(ncell_list) time_lists = [[]] * len(ncell_list) base_res_list = [] for i, ncell in enumerate(ncell_list): base_res_list.append(size / ncell / 1.e5) dir = results_base + '/n' + str(ncell) if not os.path.isdir(dir): continue # Generate a plot of the distance from the center of the ignition point, # and also the time of the ignition. # Get the list of refinement values we have tried. r_list = wdmerger.get_parameter_list(dir) if (r_list == []): continue # Sort them numerically. r_list = ['r' + str(r) for r in sorted([int(r[1:]) for r in r_list])] # Cycle through the plot files. # Get the distance from the origin of the point where T > 4e9 K, if it exists. zonesPerDim = [] res_list = [] dist_list = [] time_list = [] for r in r_list: results_dir = results_base + '/n' + str(ncell) + '/' + r if not os.path.isdir(results_dir): continue print('Searching in directory ' + results_dir) prefix = 'det_x_plt' plot_list = [ results_dir + '/output/' + plot for plot in wdmerger.get_plotfiles(results_dir, prefix=prefix) ] # Since we'll have stopped after the ignition has occurred, # we'll search through the plotfiles backward. T_max = -1.0 T_last = -1.0 for plot in reversed(plot_list): [T_max, x, y, z] = wdmerger.get_maxloc(plot, 'Temp') if (T_max < 4.0e9 and T_last >= 4.0e9) or (T_max >= 4.0e9 and T_last < 0.0): dist = abs(x.v) / 1.0e5 time = wdmerger.get_time_from_plotfile(plot) zonesPerDim.append(ncell * int(r[1:])) ds = yt.load(plot) problo = ds.domain_left_edge.v probhi = ds.domain_right_edge.v size = probhi[0] - problo[0] res_list.append(size / (ncell * int(r[1:])) / 1.0e5) dist_list.append(dist) time_list.append(time) break else: T_last = T_max res_lists[i] = res_list dist_lists[i] = dist_list time_lists[i] = time_list # Plot location of the ignition and time on the same axis. # We want to combine data at low resolution using their coarse # grid runs, with the AMR data at the highest resolution. res_list = [] dist_list = [] time_list = [] for i in range(len(ncell_list) - 1): res_list.append(res_lists[i][0]) dist_list.append(dist_lists[i][0]) time_list.append(time_lists[i][0]) for res in res_lists[-1]: res_list.append(res) for dist in dist_lists[-1]: dist_list.append(dist) for time in time_lists[-1]: time_list.append(time) fig, ax1 = plt.subplots() ax1.plot(res_list, dist_list, linestyle=linestyles[0], marker=markers[0], color=colors[0], lw=2.0, label='Ignition location') ax1.set_xscale('log', basex=10) ax1.set_xlabel(r"Finest resolution (km)", fontsize=24) ax1.set_ylabel(r"Ignition location (km)", fontsize=24, color=colors[0]) ax1.tick_params(axis='y', labelcolor=colors[0], labelsize=16) ax1.tick_params(axis='x', labelsize=16) ax1.set_ylim(bottom=0.0) ax2 = ax1.twinx() ax2.plot(res_list, time_list, linestyle=linestyles[1], marker=markers[1], color=colors[1], lw=2.0, label='Ignition time') ax2.set_ylabel(r"Ignition time (s)", fontsize=24, color=colors[1]) ax2.tick_params(axis='y', labelcolor=colors[1], labelsize=16) ax2.set_ylim(bottom=0.0) fig.set_size_inches(11, 8.5) fig.tight_layout() plt.savefig(file_base + '.eps') plt.savefig(file_base + '.png') plt.close()
def burning_mode(out_filename, results_base): """Create a table with the nickel generation as a function of the burning_mode parameter.""" if (os.path.isfile(out_filename)): return else: print("Generating file %s" % out_filename) # Get the list of parameter values we have tried results_dir = results_base + '/burning_mode' if not os.path.isdir(results_dir): return param_list = wdmerger.get_parameter_list(results_dir) if (param_list == []): return mode_list = [param for param in param_list] ni56_list = get_ni56(results_dir) # Sort the lists ni56_list = np.array([x for _, x in sorted(zip(mode_list, ni56_list))]) mode_list = sorted(mode_list) # Replace the burning mode numbers with names for output purposes try: mode_list[mode_list.index('0')] = 'Hydrostatic' except: pass try: mode_list[mode_list.index('1')] = 'Self-heating' except: pass try: mode_list[mode_list.index('2')] = 'Hybrid' except: pass try: mode_list[mode_list.index('3')] = 'Suppressed' except: pass comment = '%\n' + \ '% Summary of the effect of the burning mode \n' + \ '% for reactions on 56Ni yield in a white \n' + \ '% dwarf collision.\n' + \ '% The first column is the density minimum and the \n' + \ '% second is the final nickel mass produced, in solar masses.\n' + \ '%\n' caption = 'The burning modes are explained in \\autoref{sec:burner}.' col1title = 'Burning Mode' title = 'Burning Mode' label = 'burningmode' precision = 5 # Because the suppressed burning mode creates so little nickel write_ni56_table(results_dir, out_filename, mode_list, ni56_list, comment, col1title, label, precision=precision, title=title, caption=caption)