def write_metadata(self, nucs, libs, dirname): track_actinides = [n for n in nucs if nucname.znum(n) in nucname.act] with open(os.path.join(dirname, "manifest.txt"), "w") as f: f.write("\n".join([str(nucname.zzaaam(act)) for act in track_actinides])) f.write("\n") with open(os.path.join(dirname, "params.txt"), "w") as f: if self.rc.get("enrichment") is None: enrichment = self.rc.initial_heavy_metal.get(922350) else: enrichment = self.rc.enrichment if enrichment is not None: f.write("ENRICHMENT {}\n".format(enrichment)) if self.rc.get("batches") is not None: f.write("BATCHES {}\n".format(self.rc.batches)) if self.rc.get("pnl") is not None: f.write("PNL {}\n".format(self.rc.pnl)) f.write("BURNUP {}\n".format(sum(libs["fuel"]["BUd"]))) f.write("FLUX {:.0E}\n".format(np.mean(libs["fuel"]["phi_tot"][1:]))) with open(os.path.join(dirname, "structural.txt"), "w") as f: clad_linear_density = pi * self.rc.clad_density * \ (self.rc.clad_cell_radius ** 2 - self.rc.void_cell_radius ** 2) fuel_linear_density = pi * self.rc.fuel_density * \ self.rc.fuel_cell_radius ** 2 clad_frac = float(clad_linear_density / fuel_linear_density) cladrows = ["{} {:.8f}".format(nucname.zzaaam(n), f*clad_frac) for n, f in self.rc.clad_material.comp.items()] f.write("\n".join(cladrows)) f.write("\n") shutil.copyfile("TAPE9.INP", os.path.join(dirname, "TAPE9.INP"))
def parse_nucs(s): """Parses a string into a set of nuclides.""" nset = set() nucs = s.split(',') for nuc in nucs: if len(nuc) == 0: continue elif '-' in nuc: nsplit = nuc.split() nlower = nucname.zzaaam(nsplit[0]) nupper = nucname.zzaaam(nsplit[1]) if 0 == nupper%10000: nupper += 10000 else: nupper += 1 tmpset = set(range(nlower, nupper)) else: n = nucname.zzaaam(nuc) if 0 == n%10000: nrange = range(n, n + 10000) else: nrange = [n] tmpset = set(nrange) # Add the union nset = (nset | tmpset) return nset
def metastable_ratio(nuc, rx, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the ratio between a reaction that leaves the nuclide in a metastable state and the equivalent reaction that leaves the nuclide in the ground state. This allows the calculation of metastable cross sections via sigma_ms = ratio * sigma_ground. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. rx : str Reaction key. ('gamma', 'alpha', 'p', etc.) temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- ratio_rx_g : ndarray An array of the ratio of the metastable cross section for a reaction to the ground state reaction. Notes ----- This always pulls the absorption reaction cross section out of the cache. See Also -------- pyne.xs.data_source.RX_TYPES pyne.xs.data_source.RX_TYPES_MAP """ if isinstance(nuc, int) or isinstance(nuc, basestring): xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) nuc = nucname.zzaaam(nuc) key = (nuc, rx + "_x_ratio", temp) if key in xs_cache: return xs_cache[key] # Get the cross-sections sigma_rx = sigma_a_reaction(nuc, rx, temp, group_struct, phi_g, xs_cache) sigma_rx_x = sigma_a_reaction(nuc, rx + "_x", temp, group_struct, phi_g, xs_cache) # Get the ratio ratio_rx_g = sigma_rx_x / sigma_rx ratio_rx_g[ratio_rx_g < 0.0] = 0.0 ratio_rx_g[ratio_rx_g == np.inf] = 0.0 ratio_rx_g[np.isnan(ratio_rx_g)] = 0.0 if isinstance(nuc, int): xs_cache[key] = ratio_rx_g return ratio_rx_g
def sigma_f(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the neutron fission cross section for a nuclide. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sigma_f_g : ndarray The fission cross-section, length G. Notes ----- This always pulls the fission cross section out of the cache. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_f, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key = (nuc, "f", temp) return xs_cache[key]
def make_1g_xs_graphs(nuc, sig): global burn_times nuc_zz = nucname.zzaaam(nuc) plt.clf() reactions = ['sigma_t', 'sigma_s', 'sigma_a', 'sigma_f'] markers = ['-', 'o', 's', 'x'] ncol = 2 if nuc_zz < 860000: reactions = reactions[:-1] markers = markers[:-1] ncol = 3 for reaction, marker in zip(reactions, markers): r, s, diff = sig[reaction, nuc] plt.plot(burn_times, s, color='k', marker=marker, linestyle='-', label="Serpent $\\{0}$".format(reaction)) #plt.errorbar(burn_times, r, diff*r, color='r', marker=marker, linestyle='-', label="RMG $\\{0}$".format(reaction)) plt.plot(burn_times, r, color='r', marker=marker, linestyle='-', label="RMG $\\{0}$".format(reaction)) plt.xlabel("burn time [days]") plt.ylabel(nuc + " One-Group Cross Sections [barns]") plt.ticklabel_format(scilimits=(-5, 5)) plt.legend(loc=0, ncol=ncol) plt.savefig(nuc + '_1g_xs.png') plt.savefig(nuc + '_1g_xs.eps') plt.clf()
def update(self, libs, dirname, fname): rownames = ["TIME", "phi_tot", "NEUT_PROD", "NEUT_DEST", "BUd"] trans_matrix = {} for mat, matlib in libs.items(): if isinstance(mat, int): fname = str(nucname.zzaaam(mat)) elif mat == 'fuel': fname = mat else: continue f = open(os.path.join(dirname, fname + ".txt"), "r") lines = f.readlines() time_steps = len(lines[0].split()) i = 5 while i < range(len(lines)): nuc_array = lines[i].split() nuc_name = nuc_array[0] nuc_values = nuc_array[1:] if len(nuc_array) == time_steps: trans_matrix[nuc_name] = nuc_values trans_matrix[nuc_name].append(matlib['material'][-1].comp[temp_nuc]*1000) else: if matlib['material'][-1].comp[nuc_name] > self.rc.track_nuc_threshold: zero_array = [0.]*(time_steps-1) trans_matrix[nuc_name] = zero_array trans_matrix[nuc_name].append(matlib['material'][-1].comp[temp_nuc]*1000) i+=1; if time_steps == len(matlib['TIME']): return libs, trans_matrix for j in range(len(rownames)): store = matlib[rownames[j]][-1] matlib[rownames[j]] = lines[j].split()[1:] matlib[rownames[j]].append(store) return libs, trans_matrix
def write_mat_file(self, dep_dict, mat_file, cumulative_time_at_eds): """Writes the iteration input file containing burnable materials composition used in depletion runs and updated after each depletion step. Parameters ---------- mats : dict Dictionary that contains `Materialflow` objects. ``key`` Name of burnable material. ``value`` `Materialflow` object holding composition and properties. mat_file : str Path to file containing burnable materials composition. cumulative_time_at_eds : float Current time at the end of the depletion step (d). """ matf = open(mat_file, 'w') matf.write('%% Material compositions (after %f days)\n\n' % cumulative_time_at_eds) for key, value in dep_dict.items(): matf.write('mat %s %5.9E burn 1 fix %3s %4i vol %7.5E\n' % (key, -dep_dict[key].density, '09c', dep_dict[key].temp, dep_dict[key].vol)) for nuc_code, wt_frac in dep_dict[key].comp.items(): # Transforms iso name from zas to zzaaam and then to SERPENT iso_name_serpent = pyname.zzaaam(nuc_code) matf.write(' %9s %7.14E\n' % (self.iso_map[iso_name_serpent], -wt_frac)) matf.close()
def test_FuelFabrication_7(): # Reactor to use rp = ReactorParameters() r1g = Reactor1G(rp=rp, n="r1g") # Mass streams to use u235 = Material({922350: 1.0}, 1.0, name="U-235") u238 = Material({922380: 1.0}, 1.0, name="U-238") mats = {"U235": u235, "U238": u238} # Mass weights to use mws = {"U235": -1.0, "U238": -1.0} # Fuel Fabrication Facility ff = FuelFabrication(mats=mats, mws_in=mws, r=r1g, paramtrack=set(["Mass"]), n="ff") keys = ["U235", "U238"] assert_equal(set(ff.materials.keys()), set(keys)) for iso in keys: assert_equal(ff.materials[iso].mass, 1.0) assert_equal(ff.materials[iso].comp[nucname.zzaaam(iso)], 1.0) assert_equal(ff.mass_weights_in, mws) assert_equal(ff.track_params, set(["Mass", "Weight_U235", "deltaR_U235", "Weight_U238", "deltaR_U238"])) assert_equal(ff.name, "ff") assert_equal(ff.reactor.name, "r1g") r1g.name = "r1g name" ff.initialize(mats, mws, r1g) assert_equal(ff.reactor.name, "r1g name")
def parse_scattering_lengths(build_dir): """Converts to scattering lenth data to a numpy array.""" build_filename = os.path.join(build_dir, "scattering_lengths.html") # Read in cinder data file with open(build_filename, 'r') as f: raw_data = f.read() sl_data = [] # Iterate over all isotopes in the table for m in re.finditer(scat_len_pattern, raw_data): md = m.groupdict() slrow = (nucname.zzaaam(md['iso']), nist_num(md['b_coherent']) * (1E-13), nist_num(md['b_incoherent']) * (1E-13), nist_num(md['xs_coherent']), nist_num(md['xs_incoherent']), nist_num(md['xs'])) sl_data.append(slrow) sl_array = np.array(sl_data, dtype=sl_dtype) return sl_array
def make_atomic_weight_table(nuc_data, build_dir=""): """Makes an atomic weight table in the nuc_data library. Parameters ---------- nuc_data : str Path to nuclide data file. build_dir : str Directory to place html files in. """ # Grab raw data atomic_abund = parse_atomic_abund(build_dir) atomic_masses = parse_atmoic_mass_adjustment(build_dir) A = {} # Add normal isotopes to A for nuc_zz, mass, error in atomic_masses: try: nuc_name = nucname.name(nuc_zz) except RuntimeError: continue if nuc_zz in atomic_abund: A[nuc_zz] = nuc_name, nuc_zz, mass, error, atomic_abund[nuc_zz] else: A[nuc_zz] = nuc_name, nuc_zz, mass, error, 0.0 # Add naturally occuring elements for element in nucname.name_zz: nuc_zz = nucname.zzaaam(element) A[nuc_zz] = element, nuc_zz, 0.0, 0.0, 0.0 for nuc, abund in atomic_abund.items(): zz = nuc / 10000 element_zz = zz * 10000 element = nucname.zz_name[zz] nuc_name, nuc_zz, nuc_mass, _error, _abund = A[nuc] elem_name, elem_zz, elem_mass, _error, _abund = A[element_zz] new_elem_mass = elem_mass + (nuc_mass * abund) A[element_zz] = element, element_zz, new_elem_mass, 0.0, 0.0 A = sorted(A.values(), key=lambda x: x[1]) # A = np.array(A, dtype=atomic_weight_dtype) # Open the HDF5 File kdb = tb.openFile(nuc_data, "a", filters=BASIC_FILTERS) # Make a new the table Atable = kdb.createTable("/", "atomic_weight", atomic_weight_desc, "Atomic Weight Data [amu]", expectedrows=len(A)) Atable.append(A) # Ensure that data was written to table Atable.flush() # Close the hdf5 file kdb.close()
def sigma_a_reaction(nuc, rx, E_g=None, E_n=None, phi_n=None): """Calculates the neutron absorption reaction cross-section for a nuclide for a new, lower resolution group structure using a higher fidelity flux. Note that g indexes G, n indexes N, and G < N. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping for which to calculate the absorption reaction cross-section. rx : str Reaction key. ('gamma', 'alpha', 'p', etc.) E_g : array-like of floats, optional New, lower fidelity energy group structure [MeV] that is of length G+1. E_n : array-like of floats, optional Higher resolution energy group structure [MeV] that is of length N+1. phi_n : array-like of floats, optional The high-fidelity flux [n/cm^2/s] to collapse the fission cross-section over. Length N. Returns ------- sigma_rx_g : ndarray An array of the collapsed absorption reaction cross section. Notes ----- This always pulls the absorption reaction cross-section out of the nuc_data. See Also -------- pyne.xs.cache.ABSORPTION_RX pyne.xs.cache.ABSORPTION_RX_MAP """ _prep_cache(E_g, E_n, phi_n) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_a_reaction, nuc, rx) # Get the absorption XS nuc_zz = nucname.zzaaam(nuc) key_n = ('sigma_rx_n', nuc_zz, rx) key_g = ('sigma_rx_g', nuc_zz, rx) # Don't recalculate anything if you don't have to if key_g in xs_cache: return xs_cache[key_g] else: sigma_rx_n = xs_cache[key_n] # Perform the group collapse, knowing that the right data is in the cache sigma_rx_g = group_collapse(sigma_rx_n, xs_cache['phi_n'], phi_g=xs_cache['phi_g'], partial_energies=xs_cache['partial_energy_matrix']) # Put this value back into the cache, with the appropriate label xs_cache[key_g] = sigma_rx_g return sigma_rx_g
def load_nuc_file(path): """Takes a file that contains whitespace separated nuclide names and returns the zzaaam representation as a sorted list.""" with open(path, 'r') as f: s = f.read() nuc_list = [nucname.zzaaam(nuc) for nuc in s.split()] nuc_list.sort() return nuc_list
def parse_for_all_isotopes(htmlfile): """Parses an elemental html file, returning a set of all occuring isotopes.""" isos = set() with open(htmlfile, 'r') as f: for line in f: m = all_iso_regex.search(line) if m is not None: isos.add(nucname.zzaaam(m.group(1))) return isos
def make_atomic_weight_table(nuc_data, build_dir=""): """Makes an atomic weight table in the nuc_data library. Parameters ---------- nuc_data : str Path to nuclide data file. build_dir : str Directory to place html files in. """ # Grab raw data atomic_abund = parse_atomic_abund(build_dir) atomic_masses = parse_atmoic_mass_adjustment(build_dir) A = {} # Add normal isotopes to A for nuc, mass, error in atomic_masses: if nuc in atomic_abund: A[nuc] = nuc, mass, error, atomic_abund[nuc] else: A[nuc] = nuc, mass, error, 0.0 # Add naturally occuring elements for element in nucname.name_zz: nuc = nucname.zzaaam(element) A[nuc] = nuc, 0.0, 0.0, 1.0 for nuc, abund in atomic_abund.items(): zz = nuc / 10000 element_zz = zz * 10000 element = nucname.zz_name[zz] _nuc, nuc_mass, _error, _abund = A[nuc] elem_zz, elem_mass, _error, _abund = A[element_zz] new_elem_mass = elem_mass + (nuc_mass * abund) A[element_zz] = element_zz, new_elem_mass, 0.0, 1.0 A = sorted(A.values(), key=lambda x: x[0]) # Open the HDF5 File kdb = tb.openFile(nuc_data, 'a', filters=BASIC_FILTERS) # Make a new the table Atable = kdb.createTable("/", "atomic_weight", atomic_weight_desc, "Atomic Weight Data [amu]", expectedrows=len(A)) Atable.append(A) # Ensure that data was written to table Atable.flush() # Close the hdf5 file kdb.close()
def sigma_t(nuc, T=300.0, E_g=None, E_n=None, phi_n=None): """Calculates the total neutron cross section for a nuclide. .. math:: \\sigma_{t, g} = \\sigma_{a, g} + \\sigma_{s, g} Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping for which to calculate the total cross section. T : float, optional Tempurature of the target material [kelvin]. E_g : array-like of floats, optional New, lower fidelity energy group structure [MeV] that is of length G+1. E_n : array-like of floats, optional Higher resolution energy group structure [MeV] that is of length N+1. phi_n : array-like of floats, optional The high-fidelity flux [n/cm^2/s] to collapse the fission cross-section over. Length N. Returns ------- sig_t_g : ndarray An array of the total cross section. """ _prep_cache(E_g, E_n, phi_n) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_t, nuc, T) # Get the total XS nuc_zz = nucname.zzaaam(nuc) key_a = ('sigma_a_g', nuc_zz) key_s = ('sigma_t_g', nuc_zz, T) key_t = ('sigma_t_g', nuc_zz, T) # Don't recalculate anything if you don't have to if key_t in xs_cache: return xs_cache[key_t] # This calculation requires the abosorption cross-section if key_a not in xs_cache: xs_cache[key_a] = sigma_a(nuc, E_g, E_n, phi_n) # This calculation requires the scattering cross-section if key_s not in xs_cache: xs_cache[key_s] = sigma_s(nuc, T, E_g, E_n, phi_n) # Sum over all h indeces sig_t_g = xs_cache[key_a] + xs_cache[key_s] # Put this value back into the cache, with the appropriate label xs_cache[key_t] = sig_t_g return sig_t_g
def _to_zzaaam(nuc, m, s): nuc_zz = nucname.zzaaam(nuc.strip()) if m == 'M': state = s.strip() if 0 < len(state): state = int(state) else: state = 1 nuc_zz += state return nuc_zz
def sigma_f(nuc, E_g=None, E_n=None, phi_n=None): """Calculates the neutron fission cross-section for a nuclide for a new, lower resolution group structure using a higher fidelity flux. Note that g indexes G, n indexes N, and G < N. If any of these are None-valued, values from the cache are used. The energy groups and fluxes are normally ordered from highest-to-lowest energy. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping for which to calculate the fission cross-section. E_g : array-like of floats, optional New, lower fidelity energy group structure [MeV] that is of length G+1. E_n : array-like of floats, optional Higher resolution energy group structure [MeV] that is of length N+1. phi_n : array-like of floats, optional The high-fidelity flux [n/cm^2/s] to collapse the fission cross-section over. Length N. Returns ------- sigma_f_g : ndarray An array of the collapsed fission cross-section. Notes ----- This always pulls the fission cross-section out of nuc_data library. """ _prep_cache(E_g, E_n, phi_n) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_f, nuc) # Get the fission XS nuc_zz = nucname.zzaaam(nuc) sigma_f_n_nuc_zz = ('sigma_f_n', nuc_zz) sigma_f_g_nuc_zz = ('sigma_f_g', nuc_zz) # Don't recalculate anything if you don't have to if sigma_f_g_nuc_zz in xs_cache: return xs_cache[sigma_f_g_nuc_zz] else: sigma_f_n = xs_cache[sigma_f_n_nuc_zz] # Perform the group collapse, knowing that the right data is in the cache sigma_f_g = group_collapse(sigma_f_n, xs_cache['phi_n'], phi_g=xs_cache['phi_g'], partial_energies=xs_cache['partial_energy_matrix']) # Put this value back into the cache, with the appropriate label xs_cache[sigma_f_g_nuc_zz] = sigma_f_g return sigma_f_g
def _load_reaction(self, nuc, rx, temp=300.0): """ Note: EAF data does not use temperature information (temp) Parameters ---------- nuc : int Nuclide in zzaaam form. rx : str Reaction MT # in nnnm form. OR: (eventually) Reaction key: 'gamma', 'alpha', 'p', etc. See Also -------- EAF_RX : list List of valid MT #s in the EAF data. EAF_RX_MAP : dict Dictionary for converting string reaction identifiers to MT #s. """ nuc = nucname.zzaaam(nuc) # Munging the rx to an MT# try: int(rx) except ValueError: try: rx = EAF_RX_MAP[rx] except KeyError: pass # Check if usable rx # if rx is None: return None if str(rx) not in EAF_RX: msg = "the reaction '{rx}' is not valid.".format(rx=rx) raise IndexError(msg) # Grab data with tb.openFile(nuc_data, 'r') as f: cond = "(nuc_zz == {0}) & (rxnum == '{1}')".format(nuc, rx) node = f.root.neutron.eaf_xs.eaf_xs rows = [np.array(row['xs']) for row in node.where(cond)] if len(rows) == 0: rxdata = None elif 1 < len(rows): rows = np.array(rows) rxdata = rows.sum(axis=0) else: rxdata = rows[0] return rxdata
def elemental_row(row): if re.match('[A-Z][a-z]?-?(\d{1,3})?$', row[0]): element = nucname.zzaaam(row[0]) weight_frac = row[3] if nucname.name(element) in elemental_mats: composition.update(elemental_mats[row[0].upper()]) else: composition[element] = float(weight_frac) nuc_zz.add(element) else: pass
def test_materials(): keys = ["U235", "U238"] assert_equal(set(ff.materials.keys()), set(keys)) for iso in keys: assert_equal(ff.materials[iso].mass, 1.0) assert_equal(ff.materials[iso].comp[nucname.zzaaam(iso)], 1.0) u235 = Material({922350: 1.0}, 1.0, name="U-235") u238 = Material({922380: 1.0}, 1.0, name="U-238") o16 = Material({80160: 1.0}, 1.0, name="O-16") mats = {"U235": u235, "U238": u238, "O16": o16} ff.materials = mats keys = ["U235", "U238", "O16"] assert_equal(set(ff.materials.keys()), set(keys)) for iso in keys: assert_equal(ff.materials[iso].mass, 1.0) assert_equal(ff.materials[iso].comp[nucname.zzaaam(iso)], 1.0)
def sigma_a_reaction(nuc, rx, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the neutron absorption reaction cross section for a nuclide. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. rx : str Reaction key. ('gamma', 'alpha', 'p', etc.) temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sigma_rx_g : ndarray The collapsed absorption reaction cross section, length G. Notes ----- This always pulls the absorption reaction cross-section out of the nuc_data. See Also -------- pyne.xs.data_source.RX_TYPES pyne.xs.data_source.RX_TYPES_MAP """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_a_reaction, nuc, rx=rx, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key = (nuc, rx, temp) return xs_cache[key]
def test_sigma_s(): if not hasattr(rx_h5.root, 'sigma_s'): raise nose.SkipTest for nuc in nucs: nuc_zz = nucname.zzaaam(nuc) sig_t_arr, sig_t = read_array(rx_h5.root.sigma_t, nuc) sig_s_arr, sig_s = read_array(rx_h5.root.sigma_s, nuc) sig_s_gh_arr, sig_s_gh = read_array(rx_h5.root.sigma_s_gh, nuc) yield check_le, sig_s, sig_t, [sig_s_arr._v_pathname, sig_t_arr._v_pathname] yield check_array_almost_eq, sig_s, sig_s_gh.sum(axis=-2), [sig_s_arr._v_pathname, 'sum(' + sig_s_gh_arr._v_pathname + ')']
def sigma_s(nuc, T, E_g=None, E_n=None, phi_n=None): """Calculates the neutron scattering cross-section for a nuclide. .. math:: \\sigma_{s, g} = \\sum_{h} \\sigma_{s, g\\to h} Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping for which to calculate the scattering cross section. T : float Tempurature of the target material [kelvin]. E_g : array-like of floats, optional New, lower fidelity energy group structure [MeV] that is of length G+1. E_n : array-like of floats, optional Higher resolution energy group structure [MeV] that is of length N+1. phi_n : array-like of floats, optional The high-fidelity flux [n/cm^2/s] to collapse the fission cross-section over. Length N. Returns ------- sig_s_g : ndarray An array of the scattering cross section. """ _prep_cache(E_g, E_n, phi_n) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_s, nuc, T) nuc_zz = nucname.zzaaam(nuc) key_g = ('sigma_s_g', nuc_zz, T) key_gh = ('sigma_s_gh', nuc_zz, T) # Don't recalculate anything if you don't have to if key_g in xs_cache: return xs_cache[key_g] # This calculation requires the scattering kernel if key_gh not in xs_cache: xs_cache[key_gh] = sigma_s_gh(nuc, T, E_g, E_n, phi_n) # Sum over all h sig_s_g = xs_cache[key_gh].sum(axis=1) # Put this value back into the cache, with the appropriate label xs_cache[key_g] = sig_s_g return sig_s_g
def parse_simple_xs(build_dir=""): """Builds and returns a dictionary from cross-section types to nuclides.""" build_dir = os.path.join(build_dir, "KAERI") # Grab and parse elemental summary files. all_nuclides = set() for element in nucname.name_zz.keys(): htmlfile = element + ".html" all_nuclides = all_nuclides | parse_for_all_isotopes(os.path.join(build_dir, htmlfile)) all_nuclides = sorted([nucname.zzaaam(nuc) for nuc in all_nuclides]) energy_tables = {eng: np.zeros(len(all_nuclides), dtype=simple_xs_dtype) for eng in simple_xs_energy.keys()} # Loop through species for i, nuc_zz in enumerate(all_nuclides): nuc_name = nucname.name(nuc_zz) filename = os.path.join(build_dir, nuc_name + "_2.html") # Loop through all energy types for eng in simple_xs_energy: energy_tables[eng]["nuc_name"][i] = nuc_name energy_tables[eng]["nuc_zz"][i] = nuc_zz # Loop trhough reactions for chan in simple_xs_channels: energy_tables[eng][chan][i] = get_xs_from_file(filename, eng, chan) for eng in simple_xs_energy: # Store only non-trivial entries mask = ( energy_tables[eng][simple_xs_channels.keys()] != np.zeros(1, dtype=simple_xs_dtype)[simple_xs_channels.keys()] ) energy_tables[eng] = energy_tables[eng][mask] # Calculate some xs energy_tables[eng]["sigma_s"] = energy_tables[eng]["sigma_e"] + energy_tables[eng]["sigma_i"] energy_tables[eng]["sigma_a"] = ( energy_tables[eng]["sigma_gamma"] + energy_tables[eng]["sigma_f"] + energy_tables[eng]["sigma_alpha"] + energy_tables[eng]["sigma_proton"] + energy_tables[eng]["sigma_deut"] + energy_tables[eng]["sigma_trit"] + energy_tables[eng]["sigma_2n"] + energy_tables[eng]["sigma_3n"] + energy_tables[eng]["sigma_4n"] ) return energy_tables
def grab_photon_fp_info(raw_data): """Grabs the photon fission product info. Parameters ---------- raw_data : str string of the cinder.dat data file. Returns ------- info_table : array Structured array with the form "(index, nuc_name, nuc_zz, type, mass)". """ # Get group sizes N_n, N_g = get_fp_sizes(raw_data) # Grab the part of the file that is a neutron fission product yield info m_info = re.search(gfp_info_pattern, raw_data, re.DOTALL) gfp_info_raw = m_info.group(0) # Grab the index, nuctope, and type iits = re.findall(iit_pattern, gfp_info_raw) # Grab the masses masses = re.findall(mass_pattern, gfp_info_raw) # Make sure data is the right size assert N_g == len(iits) assert N_g == len(masses) # Make info table rows info_table = [] for m in range(N_g): iit = iits[m] index = int(iit[0]) nuc_zz = nucname.zzaaam(iit[1]) # Correct for metastable flag if 0 != nuc_zz%10: nuc_zz = nuc_zz + 2000 nuc_name = nucname.name(nuc_zz) type = fp_type_flag[iit[2]] mass = float(masses[m]) info_row = (index, nuc_name, nuc_zz, type, mass) info_table.append(info_row) info_table = np.array(info_table, dtype=fp_info_dtype) return info_table
def write(self, libs, dirname): if not os.path.isdir(dirname): os.makedirs(dirname) rownames = ["TIME", "NEUT_PROD", "NEUT_DEST", "BUd"] for mat, matlib in libs.items(): if isinstance(mat, int): fname = str(nucname.zzaaam(mat)) else: fname = mat lines = [row + " " + " ".join(map(str, matlib[row])) for row in rownames] nucs = matlib["tracked_nucs"] lines.extend(sorted([n + " " + " ". join(["{:.4g}".format(f) for f in nucs[n]]) for n in nucs])) with open(os.path.join(dirname, fname + ".txt"), "w") as f: f.write("\n".join(lines)) track_actinides = [n for n in nucs if nucname.znum(n) in nucname.act] with open(os.path.join(dirname, "manifest.txt"), "w") as f: f.write("\n".join([str(nucname.zzaaam(act)) for act in track_actinides])) f.write("\n") with open(os.path.join(dirname, "params.txt"), "w") as f: f.write("ENRICHMENT {}\n".format(self.rc.enrichment)) f.write("BATCHES {}\n".format(self.rc.batches)) f.write("PNL {}\n".format(self.rc.pnl)) f.write("BURNUP {}\n".format(sum(libs["fuel"]["BUd"]))) f.write("FLUX {:.0E}\n".format(np.mean(libs["fuel"]["phi_tot"][1:]))) with open(os.path.join(dirname, "structural.txt"), "w") as f: clad_linear_density = pi * self.rc.clad_density * \ (self.rc.clad_cell_radius ** 2 - self.rc.void_cell_radius ** 2) fuel_linear_density = pi * self.rc.fuel_density * \ self.rc.fuel_cell_radius ** 2 clad_frac = float(clad_linear_density / fuel_linear_density) cladrows = ["{} {:.8f}".format(nucname.zzaaam(n), f*clad_frac) for n, f in self.rc.clad_material.comp.items()] f.write("\n".join(cladrows)) f.write("\n") shutil.copyfile("TAPE9.INP", os.path.join(dirname, "TAPE9.INP"))
def sigma_s(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the neutron scattering cross section for a nuclide. .. math:: \\sigma_{s, g} = \\sum_{h} \\sigma_{s, g\\to h} Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sig_s_g : ndarray The scattering cross section, length G. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_s, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key_g = (nuc, 's_g', temp) key_gh = (nuc, 's_gh', temp) # Don't recalculate anything if you don't have to if key_g in xs_cache: return xs_cache[key_g] # This calculation requires the scattering kernel if key_gh not in xs_cache: xs_cache[key_gh] = sigma_s_gh(nuc, temp, group_struct, phi_g, xs_cache) # Sum over all h sig_s_g = xs_cache[key_gh].sum(axis=1) # Put this value back into the cache, with the appropriate label xs_cache[key_g] = sig_s_g return sig_s_g
def parse_simple_xs(build_dir=""): """Builds and returns a dictionary from cross-section types to nuclides.""" build_dir = os.path.join(build_dir, 'KAERI') # Grab and parse elemental summary files. all_nuclides = set() for element in nucname.name_zz.keys(): htmlfile = element + '.html' all_nuclides = all_nuclides | parse_for_all_isotopes( os.path.join(build_dir, htmlfile)) all_nuclides = sorted([nucname.zzaaam(nuc) for nuc in all_nuclides]) energy_tables = dict([(eng, np.zeros(len(all_nuclides), dtype=simple_xs_dtype)) \ for eng in simple_xs_energy.keys()]) # Loop through species for i, nuc in enumerate(all_nuclides): nuc_name = nucname.name(nuc) filename = os.path.join(build_dir, nuc_name + '_2.html') # Loop through all energy types for eng in simple_xs_energy: energy_tables[eng]['nuc'][i] = nuc # Loop trhough reactions for chan in simple_xs_channels: energy_tables[eng][chan][i] = get_xs_from_file( filename, eng, chan) for eng in simple_xs_energy: # Store only non-trivial entries mask = (energy_tables[eng][simple_xs_channels.keys()] != np.zeros( 1, dtype=simple_xs_dtype)[simple_xs_channels.keys()]) energy_tables[eng] = energy_tables[eng][mask] # Calculate some xs energy_tables[eng]['sigma_s'] = energy_tables[eng][ 'sigma_e'] + energy_tables[eng]['sigma_i'] energy_tables[eng]['sigma_a'] = energy_tables[eng]['sigma_gamma'] + \ energy_tables[eng]['sigma_f'] + \ energy_tables[eng]['sigma_alpha'] + \ energy_tables[eng]['sigma_proton'] + \ energy_tables[eng]['sigma_deut'] + \ energy_tables[eng]['sigma_trit'] + \ energy_tables[eng]['sigma_2n'] + \ energy_tables[eng]['sigma_3n'] + \ energy_tables[eng]['sigma_4n'] return energy_tables
def test_chi(): if not hasattr(rx_h5.root, 'chi'): raise nose.SkipTest for nuc in nucs: nuc_zz = nucname.zzaaam(nuc) chi_arr, chi = read_array(rx_h5.root.chi, nuc) sig_f_arr, sig_f = read_array(rx_h5.root.sigma_f, nuc) if 86 <= (nuc_zz/10000): yield check_array_almost_eq, 1.0, chi.sum(axis=1), ['1.0', 'sum(' + chi_arr._v_pathname + ')'] else: yield check_eq, 0.0, chi, ['0.0', chi_arr._v_pathname]
def grab_photon_fp_info(raw_data): """Grabs the photon fission product info. Parameters ---------- raw_data : str string of the cinder.dat data file. Returns ------- info_table : array Structured array with the form "(index, nuc, type, mass)". """ # Get group sizes N_n, N_g = get_fp_sizes(raw_data) # Grab the part of the file that is a neutron fission product yield info m_info = re.search(gfp_info_pattern, raw_data, re.DOTALL) gfp_info_raw = m_info.group(0) # Grab the index, nuctope, and type iits = re.findall(iit_pattern, gfp_info_raw) # Grab the masses masses = re.findall(mass_pattern, gfp_info_raw) # Make sure data is the right size assert N_g == len(iits) assert N_g == len(masses) # Make info table rows info_table = [] for m in range(N_g): iit = iits[m] index = int(iit[0]) nuc = nucname.zzaaam(iit[1]) # Correct for metastable flag if 0 != nuc % 10: nuc = nuc + 2000 type = fp_type_flag[iit[2]] mass = float(masses[m]) info_row = (index, nuc, type, mass) info_table.append(info_row) info_table = np.array(info_table, dtype=fp_info_dtype) return info_table
def sigma_t(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the total neutron cross section for a nuclide. .. math:: \\sigma_{t, g} = \\sigma_{a, g} + \\sigma_{s, g} Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sig_t_g : ndarray The total cross section, length G. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_t, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key_a = (nuc, 'a', temp) key_s = (nuc, 's', temp) key_t = (nuc, 't', temp) # Don't recalculate anything if you don't have to if key_t in xs_cache: return xs_cache[key_t] # This calculation requires the abosorption cross-section if key_a not in xs_cache: xs_cache[key_a] = sigma_a(nuc, temp, group_struct, phi_g, xs_cache) if key_s not in xs_cache: xs_cache[key_s] = sigma_s(nuc, temp, group_struct, phi_g, xs_cache) sig_t_g = xs_cache[key_a] + xs_cache[key_s] xs_cache[key_t] = sig_t_g return sig_t_g
def sigma_s(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the neutron scattering cross section for a nuclide. .. math:: \\sigma_{s, g} = \\sum_{h} \\sigma_{s, g\\to h} Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sig_s_g : ndarray The scattering cross section, length G. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_s, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key_g = (nuc, "s_g", temp) key_gh = (nuc, "s_gh", temp) # Don't recalculate anything if you don't have to if key_g in xs_cache: return xs_cache[key_g] # This calculation requires the scattering kernel if key_gh not in xs_cache: xs_cache[key_gh] = sigma_s_gh(nuc, temp, group_struct, phi_g, xs_cache) # Sum over all h sig_s_g = xs_cache[key_gh].sum(axis=1) # Put this value back into the cache, with the appropriate label xs_cache[key_g] = sig_s_g return sig_s_g
def sigma_t(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the total neutron cross section for a nuclide. .. math:: \\sigma_{t, g} = \\sigma_{a, g} + \\sigma_{s, g} Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sig_t_g : ndarray The total cross section, length G. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_t, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key_a = (nuc, "a", temp) key_s = (nuc, "s", temp) key_t = (nuc, "t", temp) # Don't recalculate anything if you don't have to if key_t in xs_cache: return xs_cache[key_t] # This calculation requires the abosorption cross-section if key_a not in xs_cache: xs_cache[key_a] = sigma_a(nuc, temp, group_struct, phi_g, xs_cache) if key_s not in xs_cache: xs_cache[key_s] = sigma_s(nuc, temp, group_struct, phi_g, xs_cache) sig_t_g = xs_cache[key_a] + xs_cache[key_s] xs_cache[key_t] = sig_t_g return sig_t_g
def write(self, libs, dirname): """Write out libraries to a directory. Parameters ---------- libs : dict The reactor libraries gleaned from buk. dirname : str The output directory. """ if not os.path.isdir(dirname): os.makedirs(dirname) rownames = ["TIME", "phi_tot", "NEUT_PROD", "NEUT_DEST", "BUd"] for mat, matlib in libs.items(): if isinstance(mat, int): fname = str(nucname.zzaaam(mat)) elif mat == 'fuel': fname = mat else: continue trans_matrix = {} if os.path.isdir(os.path.join(dirname, fname + ".txt")): libs, trans_matrix = self.update(libs, dirname, fname) else: i = 0 while i < len(matlib['material']): for temp_nuc in matlib['material'][i].comp: nuc_name = str(nucname.name(temp_nuc)) try: trans_matrix[nuc_name].append(matlib['material'][i].comp[temp_nuc]*1000) except KeyError: if matlib['material'][i].comp[temp_nuc] > self.rc.track_nuc_threshold: zero_array = [0.]*i trans_matrix[nuc_name] = zero_array trans_matrix[nuc_name].append(matlib['material'][i].comp[temp_nuc]*1000) i+=1 lines = [row + " " + " ".join(map(str, matlib[row])) for row in rownames] lines.extend(sorted([n + " " + " ". join(["{:.4g}".format(f) for f in trans_matrix[n]]) for n in trans_matrix])) with open(os.path.join(dirname, fname + ".txt"), "w") as f: f.write("\n".join(lines)) nucs = matlib["tracked_nucs"] if not os.path.isfile(os.path.join(dirname, "manifest.txt")): self.write_metadata(nucs, libs, dirname)
def parse_eaf_xs(build_file): """Create numpy array by parsing EAF data using regular expressions Parameters ---------- build_file : str Path where EAF data is stored. Returns ------- eaf_array : numpy array Numpy array with a row for each isotope+reaction combination found in the EAF data. """ with open(build_file, 'r') as f: raw_data = f.read() eaf_data = list() eaf_pattern = eaf_info_pattern + eaf_bin_pattern # Iterate over all iso/rx combinations in file for m in re.finditer(eaf_pattern, raw_data, re.DOTALL): md = m.groupdict() xs_list = [float(x) for x in md['xs'].split()] xs_list += (175-len(xs_list))*[0.0] # Store information in new row of array. eafrow = ( nucname.zzaaam(md['iso']), md['rxnum'], md['rxstr'], md['daugh'], xs_list ) eaf_data.append(eafrow) eaf_array = np.array(eaf_data, dtype=eaf_dtype) print "Read in {0} sets of EAF data.".format(len(eaf_array)) return eaf_array
def parse_simple_xs(build_dir=""): """Builds and returns a dictionary from cross-section types to nuclides.""" build_dir = os.path.join(build_dir, 'KAERI') # Grab and parse elemental summary files. all_nuclides = set() for element in nucname.name_zz.keys(): htmlfile = element + '.html' all_nuclides = all_nuclides | parse_for_all_isotopes(os.path.join(build_dir, htmlfile)) all_nuclides = sorted([nucname.zzaaam(nuc) for nuc in all_nuclides]) energy_tables = dict([(eng, np.zeros(len(all_nuclides), dtype=simple_xs_dtype)) \ for eng in simple_xs_energy.keys()]) # Loop through species for i, nuc in enumerate(all_nuclides): nuc_name = nucname.name(nuc) filename = os.path.join(build_dir, nuc_name + '_2.html') # Loop through all energy types for eng in simple_xs_energy: energy_tables[eng]['nuc'][i] = nuc # Loop trhough reactions for chan in simple_xs_channels: energy_tables[eng][chan][i] = get_xs_from_file(filename, eng, chan) for eng in simple_xs_energy: # Store only non-trivial entries mask = (energy_tables[eng][simple_xs_channels.keys()] != np.zeros(1, dtype=simple_xs_dtype)[simple_xs_channels.keys()]) energy_tables[eng] = energy_tables[eng][mask] # Calculate some xs energy_tables[eng]['sigma_s'] = energy_tables[eng]['sigma_e'] + energy_tables[eng]['sigma_i'] energy_tables[eng]['sigma_a'] = energy_tables[eng]['sigma_gamma'] + \ energy_tables[eng]['sigma_f'] + \ energy_tables[eng]['sigma_alpha'] + \ energy_tables[eng]['sigma_proton'] + \ energy_tables[eng]['sigma_deut'] + \ energy_tables[eng]['sigma_trit'] + \ energy_tables[eng]['sigma_2n'] + \ energy_tables[eng]['sigma_3n'] + \ energy_tables[eng]['sigma_4n'] return energy_tables
def get_nuc_name(self, nuc_code): """Returns nuclide name in human-readable notation: chemical symbol (one or two characters), dash, and the atomic weight. Lastly, if the nuclide is in metastable state, the letter `m` is concatenated with number of excited state. For example, `Am-242m1`. Parameters ---------- nuc_code : str Name of nuclide in Serpent2 form. For instance, `Am-242m`. Returns ------- nuc_name : str Name of nuclide in human-readable notation (`Am-242m1`). nuc_zzaaam : str Name of nuclide in `zzaaam` form (`952421`). """ if '.' in str(nuc_code): nuc_code = pyname.zzzaaa_to_id(int(nuc_code.split('.')[0])) zz = pyname.znum(nuc_code) aa = pyname.anum(nuc_code) aa_str = str(aa) # at_mass = pydata.atomic_mass(nuc_code_id) if aa > 300: if zz > 76: aa_str = str(aa - 100) + 'm1' aa = aa - 100 else: aa_str = str(aa - 200) + 'm1' aa = aa - 200 nuc_zzaaam = str(zz) + str(aa) + '1' elif aa == 0: aa_str = 'nat' nuc_name = pyname.zz_name[zz] + aa_str else: meta_flag = pyname.snum(nuc_code) if meta_flag: nuc_name = pyname.name(nuc_code)[:-1] + 'm' + str(meta_flag) else: nuc_name = pyname.name(nuc_code) nuc_zzaaam = \ self.convert_nuclide_name_serpent_to_zam(pyname.zzaaam(nuc_code)) return nuc_name, nuc_zzaaam
def _load_reaction(self, nuc, rx, temp=300.0): nuc = nucname.zzaaam(nuc) if rx not in self._rx_avail: return None cond = "nuc == {0}".format(nuc) sig = 'sigma_' + rx with tb.openFile(nuc_data, 'r') as f: simple_xs = f.root.neutron.simple_xs fteen = [row[sig] for row in simple_xs.fourteen_MeV.where(cond)] fissn = [row[sig] for row in simple_xs.fission_spectrum_ave.where(cond)] therm = [row[sig] for row in simple_xs.thermal.where(cond)] if 0 == len(therm): therm = [row[sig] for row in simple_xs.thermal_maxwell_ave.where(cond)] if 0 == len(fteen) and 0 == len(fissn) and 0 == len(therm): rxdata = None else: rxdata = np.array([fteen[0], fissn[0], therm[0]], dtype='float64') return rxdata
def findParents(energyList, energyUncertainty): """Find parent elements of a given intensity peak. Args: energyList: The energies with an intensity peak in our dataset. energyUncertainty: Energy Uncertainties associated with each energy (in order) of our dataset. """ elements = [] for i in range(len(energyList)): for j in data.gamma_parent(energyList[i], energyUncertainty[i]): if j > 0: try: if nucname.zzaaam(j) % 2 == 0: elements.append(j) except: doNothing = 1 raise return elements
def _load_reaction(self, nuc, rx, temp=300.0): nuc = nucname.zzaaam(nuc) rx = _munge_rx(rx) # Set query condition if rx == 'f': cond = 'nuc == {0}'.format(nuc) elif rx in RX_TYPES: cond = "(from_nuc == {0}) & (reaction_type == '{1}')".format(nuc, rx) else: return None with tb.openFile(nuc_data, 'r') as f: node = f.root.neutron.cinder_xs.fission if rx == 'f' else \ f.root.neutron.cinder_xs.absorption rows = [np.array(row['xs']) for row in node.where(cond)] if 1 == len(rows): rxdata = rows[0] elif 1 < len(rows): rows = np.array(rows) rxdata = rows.sum(axis=0) elif 0 == len(rows) and (rx == 'a'): # in case absorption doesn't exist, we compute it fdata = self._load_reaction(nuc, 'f') cond = "(from_nuc == {0}) & (reaction_type != 'c')".format(nuc) with tb.openFile(nuc_data, 'r') as f: node = f.root.neutron.cinder_xs.absorption rows = np.array([row['xs'] for row in node.where(cond)]) if 0 == len(rows) and fdata is None: rxdata = None else: rxdata = rows.sum(axis=0) if fdata is not None: rxdata += fdata else: rxdata = None return rxdata
def sigma_f(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the neutron fission cross section for a nuclide. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sigma_f_g : ndarray The fission cross-section, length G. Notes ----- This always pulls the fission cross section out of the cache. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_f, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key = (nuc, 'f', temp) return xs_cache[key]
def make_mg_absorption(nuc_data, build_dir=""): """Adds the absorption reaction rate cross sections to the hdf5 library. Parameters ---------- nuc_data : str Path to nuclide data file. build_dir : str Directory with cinder.dat file. """ # Open the HDF5 File db = tb.openFile(nuc_data, 'a', filters=BASIC_FILTERS) # Ensure that the appropriate file structure is present _init_cinder(db) # Read in cinder data file cinder_dat = os.path.join(build_dir, 'cinder.dat') with open(cinder_dat, 'r') as f: raw_data = f.read() # Get group sizes nuclides, G_n, G_p, G_g = get_group_sizes(raw_data) # Init the neutron absorption table absorption_dtype = np.dtype(absorption_dtype_tuple + [('xs', float, G_n)]) absorption_table = db.createTable( '/neutron/cinder_xs/', 'absorption', np.empty(0, dtype=absorption_dtype), 'Neutron absorption reaction cross sections [barns]') abrow = absorption_table.row # Init to_nuc_pattern to_nuc_pattern = to_nuc_base + ("\s+(" + cinder_float + ")") * G_n # Iterate through all from nuctopes. for m_from in re.finditer(from_nuc_pattern, raw_data, re.DOTALL): from_nuc = nucname.zzaaam(m_from.group(1)) # Check matestable state if 1 < from_nuc % 10: # Metastable state too high! continue # Grab the string for this from_nuc in order to get all of the to_nucs from_nuc_part = m_from.group(0) # Iterate over all to_nucs for m_to in re.finditer(to_nuc_pattern, from_nuc_part): to_nuc = nucname.zzaaam(m_to.group(1)) # Check matestable state if 1 < to_nuc % 10: # Metastable state too high! continue # Munge reaction type rx_type = m_to.group(2) rx_type = rx_type.strip() # Setup XS array xs = np.array(m_to.groups()[-1:1:-1], dtype=float) assert xs.shape == (G_n, ) # Write this row to the absorption table abrow['from_nuc'] = from_nuc abrow['to_nuc'] = to_nuc abrow['reaction_type'] = rx_type abrow['xs'] = xs abrow.append() # Flush this from nuc absorption_table.flush() # Close the hdf5 file db.close()
def parse_tape6(tape6="TAPE6.OUT"): """Parses an ORIGEN 2.2 TAPE6.OUT file. Parameters ---------- tape6 : str or file-like object Path or file to read the tape6 file from. Returns ------- results : dict Dictionary of parsed values. Warnings -------- This method currently only functions to extract neutronic data from TAPE6 files. It does not yet parse out photonic data. If you would like to see this feature added, please contact the developers. Notes ----- The results dictionary that is returned is highly structured and generally matches the layout of the TAPE6 file. Data is stored as 1d numpy float arrays which (if the TAPE6 is well-formed) will all be of the same length and match the time vector. The possible layout of results is as follows:: |- 'time_sec': time per index in [seconds] |- 'flux': neutron flux at this time [n/cm^2/s] |- 'specific_power_MW': recator specific power at this time [MW] |- 'burnup_MWD': reactor burnup since last time step [MWd/input mass [g] from TAPE4] |- 'k_inf': infinite multiplication factor [unitless] |- 'neutron_production_rate': Total reactor neutron production rate [n/s] |- 'neutron_destruction_rate: Total reactor neutron destruction rate [n/s] |- 'total_burnup': Cummulative burnup over all time [MWd/input mass [g] from TAPE4] |- 'average_flux': average neutron flux over preceeding time interval [n/cm^2/s] |- 'average_specific_power: recator specific power over preceeding time interval [MW] |- 'materials': list of Materials of same length as 'time_sec', only present if | 'table_3' or 'table_5' exist and have 'nuclide' output. |- 'alpha_neutron_source': dict | |- 'title': str | |- 'units': str | |- nuclide or element str: (alpha, n) neutron source [n/s] |- 'spont_fiss_neutron_source': dict | |- 'title': str | |- 'units': str | |- nuclide or element str: spontaneous fission neutron source [n/s] |- 'table_{n}': dict | |- 'nuclide': dict | | |- 'title': str | | |- 'units': str | | |- 'activation_products': dict of (nuc-zzaaam, data) pairs | | |- 'actinides': dict of (nuc-zzaaam, data) pairs | | |- 'fission_products': dict of (nuc-zzaaam, data) pairs | |- 'element': dict | | |- 'title': str | | |- 'units': str | | |- 'activation_products': dict of (elem str, data) pairs | | |- 'actinides': dict of (elem str, data) pairs | | |- 'fission_products': dict of (elem str, data) pairs | |- 'summary': dict | | |- 'title': str | | |- 'units': str | | |- 'activation_products': dict of (elem or nuc str, data) pairs | | |- 'actinides': dict of (elem or nuc str, data) pairs | | |- 'fission_products': dict of (elem or nuc str, data) pairs """ # Read the TAPE6 file opened_here = False if isinstance(tape6, basestring): tape6 = open(tape6, 'r') opened_here = True lines = tape6.readlines() if opened_here: tape6.close() # Prep to parse the file results = {} # Defaults table_key = None table_type = None table_group = None # Read in the file line-by-line for i, line in enumerate(lines): # Get reactivity and burnup data m = _rx_bu_data_line.match(line) if m is not None: key, data = m.groups() new_key = _rx_bu_key_map[key] arr_data = np.array(data.split(), dtype=float) curr_data = results.get(new_key, []) results[new_key] = np.append(curr_data, arr_data) continue # Get table spcies group m = _species_group_line.match(line) if m is not None: table_group = _group_key_map[m.group(1)] continue # Get table header info m = _table_header_line.match(line) or _table_header_alpha_line.match( line) if m is not None: tnum, ttype, ttitle, tunits = m.groups() table_key = "table_{0}".format(tnum) if table_key not in results.keys(): results[table_key] = {} table_type = ttype.lower() if table_type not in results[table_key]: results[table_key][table_type] = {} results[table_key][table_type]["title"] = ttitle.strip().lower() results[table_key][table_type]["units"] = tunits.strip().lower() if table_group not in results[table_key][table_type]: results[table_key][table_type][table_group] = {} continue # Grab nuclide data lines m = _nuclide_line.match(line) if (m is not None) and (table_key is not None): nuc, data = m.groups() nuc_name = nuc.replace(' ', '') # Don't know WTF element 'SF' is suppossed to be! (Spent fuel, spontaneous fission) if nuc_name == 'SF250': continue nuc_zz = nucname.zzaaam(nuc_name) nuc_key = nuc_zz if table_type == 'nuclide' else nuc_name nuc_data = np.array(data.split(), dtype=float) if table_key.startswith('table_'): curr_data = results[table_key][table_type][table_group].get( nuc_key, []) results[table_key][table_type][table_group][ nuc_key] = np.append(curr_data, nuc_data) else: curr_data = results[table_key].get(nuc_key, []) results[table_key][nuc_key] = np.append(curr_data, nuc_data) continue # Grab element data line m = _element_line.match(line) if (m is not None) and (table_key is not None): elem, data = m.groups() elem = elem.replace(' ', '') # Still don't know WTF element 'SF' is suppossed to be! (Spent fuel, spontaneous fission) if elem == 'SF': continue elem_data = np.array(data.split(), dtype=float) if table_key.startswith('table_'): curr_data = results[table_key][table_type][table_group].get( elem, []) results[table_key][table_type][table_group][elem] = np.append( curr_data, elem_data) else: curr_data = results[table_key].get(elem, []) results[table_key][elem] = np.append(curr_data, elem_data) continue # Grab (alpha, n) and spontaneous fission headers m = _alpha_n_header_line.match(line) or _spont_fiss_header_line.match( line) if m is not None: ttitle, tunits = m.groups() table_key = _n_source_key_map[ttitle] if table_key not in results.keys(): results[table_key] = {} table_type = None table_group = None results[table_key]["title"] = ttitle.strip().lower() results[table_key]["units"] = tunits.strip().lower() continue # Photon spectra parsing is not yet supported m = _photon_spec_header_line.match(line) if m is not None: table_key = None table_type = None table_group = None # Done with parsing, try to convert to material tbl = None if ('table_5' in results) and ('nuclide' in results['table_5']): tbl = 'table_5' mat_gen = Material elif ('table_3' in results) and ('nuclide' in results['table_3']): tbl = 'table_3' mat_gen = from_atom_frac if tbl is not None: T = len(results['time_sec']) mats = [Material() for t in range(T)] for grp in _group_key_map.values(): if grp in results[tbl]['nuclide']: mats = [m + mat_gen(dict([(nuc, arr[i]) for nuc, arr in \ results[tbl]['nuclide'][grp].items()])) \ for i, m in enumerate(mats)] results['materials'] = mats return results
def test_zzaaam(): assert_equal(nucname.zzaaam(20040), 20040) assert_equal(nucname.zzaaam("he4"), 20040) assert_equal(nucname.zzaaam("Cm-244"), 962440) assert_equal(nucname.zzaaam("PU239"), 942390) assert_equal(nucname.zzaaam("AM242M"), 952421) assert_equal(nucname.zzaaam(2004), 20040) assert_equal(nucname.zzaaam(95642), 952420) assert_equal(nucname.zzaaam(95242), 952421) assert_equal(nucname.zzaaam(92636), 922361) assert_equal(nucname.zzaaam(95942), 952424) assert_equal(nucname.zzaaam("Am-242m"), 952421) assert_equal(nucname.zzaaam("he"), 20000) assert_equal(nucname.zzaaam("U"), 920000) assert_equal(nucname.zzaaam("Np"), 930000) assert_equal(nucname.zzaaam("4he"), 20040) assert_equal(nucname.zzaaam("244CM"), 962440) assert_equal(nucname.zzaaam("239Pu"), 942390) assert_equal(nucname.zzaaam("242AM"), 952420) assert_equal(nucname.zzaaam(40020), 20040) assert_equal(nucname.zzaaam(2440961), 962441) assert_equal(nucname.zzaaam(2390940), 942390) assert_equal(nucname.zzaaam(2420950), 952420)
core_adensity_before = np.array(f['core adensity before reproc']) keff_boc = np.array(f['keff_BOC']) keff_eoc = np.array(f['keff_EOC']) tank_adensity = np.array(f['tank adensity']) noble_adensity = np.array([]) iso_codes = np.array(f['iso_codes']) iso_zai = [] iso_names = [] for code in iso_codes: code = code.decode() if '.09c' in code: code = code.replace('.09c', '') code = nucname.zzzaaa_to_id(int(code)) else: code = nucname.zzaaam_to_id(int(code)) iso_zai.append(nucname.zzaaam(code)) iso_names.append(nucname.name(code)) iso_zai = np.array(iso_zai) iso_names = np.array(iso_names) shape = core_adensity_after.shape def adens_to_mass(fuel_vol, array, iso_names): shape = array.shape mass_array = np.zeros(shape) for num, row in enumerate(array): mat_dict = {} mass_comp = np.zeros(len(row)) for indx, val in enumerate(row): mat_dict[iso_names[indx]] = val
def chi(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None, eres=101): """Calculates the neutron fission energy spectrum for a nuclide. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. eres : int, optional Number of energy-points to integrate over per group. Returns ------- chi_g : ndarray The fission energy spectrum, length G. See Also -------- pyne.xs.models.chi : used under the covers by this function. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(chi, nuc, temp=temp, xs_cache=xs_cache, eres=eres) nuc = nucname.zzaaam(nuc) key = (nuc, 'chi', temp) # Don't recalculate anything if you don't have to if key in xs_cache: return xs_cache[key] # Get the the set of nuclides we know we need chi for. if 'fissionable_nucs' not in xs_cache: with tb.openFile(pyne.nuc_data, 'r') as f: if '/neutron/cinder_xs/fission' in f: fn = set(f.root.neutron.cinder_xs.fission.cols.nuc) else: fn = set() xs_cache['fissionable_nucs'] = fn fissionable_nucs = xs_cache['fissionable_nucs'] if (nuc not in fissionable_nucs) and (86 <= nuc / 10000): fissionable_nucs.add(nuc) # Perform the group collapse on a continuous chi E_g = xs_cache['E_g'] G = len(E_g) - 1 chi_g = np.zeros(G, dtype='f8') if (nuc in fissionable_nucs): for g in range(G): E_space = np.logspace(np.log10(E_g[g]), np.log10(E_g[g + 1]), eres) dnumer = pyne.xs.models.chi(E_space) numer = scipy.integrate.trapz(dnumer, E_space) denom = (E_g[g + 1] - E_g[g]) chi_g[g] = (numer / denom) # renormalize chi chi_g = chi_g / chi_g.sum() # Put this value back into the cache, with the appropriate label xs_cache[key] = chi_g return chi_g
def metastable_ratio(nuc, rx, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the ratio between a reaction that leaves the nuclide in a metastable state and the equivalent reaction that leaves the nuclide in the ground state. This allows the calculation of metastable cross sections via sigma_ms = ratio * sigma_ground. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. rx : str Reaction key. ('gamma', 'alpha', 'p', etc.) temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- ratio_rx_g : ndarray An array of the ratio of the metastable cross section for a reaction to the ground state reaction. Notes ----- This always pulls the absorption reaction cross section out of the cache. See Also -------- pyne.xs.data_source.RX_TYPES pyne.xs.data_source.RX_TYPES_MAP """ if isinstance(nuc, int) or isinstance(nuc, basestring): xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) nuc = nucname.zzaaam(nuc) key = (nuc, rx + '_x_ratio', temp) if key in xs_cache: return xs_cache[key] # Get the cross-sections sigma_rx = sigma_a_reaction(nuc, rx, temp, group_struct, phi_g, xs_cache) sigma_rx_x = sigma_a_reaction(nuc, rx + '_x', temp, group_struct, phi_g, xs_cache) # Get the ratio ratio_rx_g = sigma_rx_x / sigma_rx ratio_rx_g[ratio_rx_g < 0.0] = 0.0 ratio_rx_g[ratio_rx_g == np.inf] = 0.0 ratio_rx_g[np.isnan(ratio_rx_g)] = 0.0 if isinstance(nuc, int): xs_cache[key] = ratio_rx_g return ratio_rx_g
def make_mg_fission(nuc_data, build_dir=""): """Adds the fission reaction rate cross sections to the hdf5 library. Parameters ---------- nuc_data : str Path to nuclide data file. build_dir : str Directory with cinder.dat file. """ # Open the HDF5 File db = tb.openFile(nuc_data, 'a', filters=BASIC_FILTERS) # Ensure that the appropriate file structure is present _init_cinder(db) # Read in cinder data file cinder_dat = os.path.join(build_dir, 'cinder.dat') with open(cinder_dat, 'r') as f: raw_data = f.read() # Get group sizes nuclides, G_n, G_p, G_g = get_group_sizes(raw_data) # Init the neutron absorption table fission_dtype = np.dtype(fission_dtype_tuple + [('xs', float, G_n)]) fission_table = db.createTable( '/neutron/cinder_xs/', 'fission', np.empty(0, dtype=fission_dtype), 'Neutron fission reaction cross sections [barns]') frow = fission_table.row # Init to_nuc_pattern fission_pattern = fission_base + ("\s+(" + cinder_float + ")") * G_n # Iterate through all from nuctopes. for m_from in re.finditer(from_nuc_pattern, raw_data, re.DOTALL): from_nuc = nucname.zzaaam(m_from.group(1)) # Check matestable state if 1 < from_nuc % 10: # Metastable state too high! continue # Grab the string for this from_nuc in order to get all of the to_nucs from_nuc_part = m_from.group(0) # Grab the fission part m_fission = re.search(fission_pattern, from_nuc_part) if m_fission is None: continue # Grab yield indexes yield_t = int(m_fission.group(1)) yield_f = int(m_fission.group(2)) yield_h = int(m_fission.group(3)) # Grab XS array xs = np.array(m_fission.groups()[-1:2:-1], dtype=float) assert xs.shape == (G_n, ) # Write fission table row frow['nuc'] = from_nuc frow['thermal_yield'] = yield_t frow['fast_yield'] = yield_f frow['high_energy_yield'] = yield_h frow['xs'] = xs # Write out this row frow.append() fission_table.flush() # Close the hdf5 file db.close()
def make_mg_gamma_decay(nuc_data, build_dir=""): """Adds the gamma decay spectrum information to the hdf5 library. Parameters ---------- nuc_data : str Path to nuclide data file. build_dir : str Directory with cinder.dat file. """ # Open the HDF5 File db = tb.openFile(nuc_data, 'a', filters=BASIC_FILTERS) # Ensure that the appropriate file structure is present _init_cinder(db) # Read in cinder data file cinder_dat = os.path.join(build_dir, 'cinder.dat') with open(cinder_dat, 'r') as f: raw_data = f.read() # Get group sizes nuclides, G_n, G_p, G_g = get_group_sizes(raw_data) # Init the gamma absorption table gamma_decay_dtype = np.dtype(gamma_decay_dtype_tuple + [('spectrum', float, G_g)]) gamma_decay_table = db.createTable('/photon/cinder_source/', 'decay_spectra', np.empty(0, dtype=gamma_decay_dtype), 'Gamma decay spectrum [MeV]') gdrow = gamma_decay_table.row # Init to_nuc_pattern gamma_decay_pattern = gamma_decay_base + ("\s+(" + cinder_float + ")") * G_g # Iterate through all from nuctopes. for m_from in re.finditer(from_nuc_pattern, raw_data, re.DOTALL): from_nuc = nucname.zzaaam(m_from.group(1)) # Check matestable state if 1 < from_nuc % 10: # Metastable state too high! continue # Grab the string for this from_nuc in order to get all of the to_nucs from_nuc_part = m_from.group(0) # Grab the fission part m_gd = re.search(gamma_decay_pattern, from_nuc_part) if m_gd is None: continue # Grab base data scale = float(m_gd.group(1)) energy = float(m_gd.group(2)) # Grab spectrum spectrum = np.array(m_gd.groups()[-1:1:-1], dtype=float) assert spectrum.shape == (G_g, ) # Prepare the row gdrow['nuc'] = from_nuc gdrow['energy'] = energy gdrow['scaling_factor'] = scale gdrow['spectrum'] = spectrum # Write out the row gdrow.append() gamma_decay_table.flush() # Close the hdf5 file db.close()
def gendecay(decays, branches, metastable_cutoff=1.0): """This computes ORIGEN TAPE9 decay data based on ENSDF data. Parameters ---------- decays : list decay list from parse_ensdf() branches : list branches list from parse_ensdf() metastable_cutoff : float, optional minimum lifetime of metastable state (in seconds) to be included. Returns ------- t9 : dict a TAPE9 dictionary for the decay library """ t9 = { 1: { '_type': 'decay', 'title': 'PyNE Decay Data for Activation Products' }, 2: { '_type': 'decay', 'title': 'PyNE Decay Data for Actinides & Daughters' }, 3: { '_type': 'decay', 'title': 'PyNE Decay Data for Fission Products' }, } for nlb, lib in t9.items(): for field in origen22.DECAY_FIELDS: lib[field] = {} longest = {} longest2 = {} for item in decays: nuc = nucname.id(item[0]) key = nucname.zzaaam(nuc) if _is_metastable_beta_decay_0(item, metastable_cutoff): if 'B-' in item[5]: _plus_eq_decay_t9(t9, 'frac_beta_minus_x', nuc, key, item[6] / 100.0) if 'B+' in item[5] or "EC" in item[5]: _plus_eq_decay_t9(t9, 'frac_beta_plus_or_electron_capture_x', nuc, key, item[6] / 100.0) if _is_metastable_beta_decay_x(item, metastable_cutoff): key += 1 longest2[key] = longest2.get(key, 0) if item[1] == longest2[key]: if 'B-' in item[5]: _plus_eq_decay_t9(t9, 'frac_beta_minus_x', nuc, key, item[6] / 100.0) #item[6]*item[8]/100.0) if 'B+' in item[5] or "EC" in item[5]: _plus_eq_decay_t9(t9, 'frac_beta_plus_or_electron_capture_x', nuc, key, item[6] / 100.0) #key, item[6]*item[8]/100.0) elif item[1] > longest2[key]: longest2[key] = item[1] if 'B-' in item[5]: #_eq_decay_t9(t9, 'frac_beta_minus_x', nuc, key, item[6]*item[8]/100.0) _eq_decay_t9(t9, 'frac_beta_minus_x', nuc, key, item[6] / 100.0) if 'B+' in item[5] or "EC" in item[5]: _eq_decay_t9(t9, 'frac_beta_plus_or_electron_capture_x', nuc, key, item[6] / 100.0) #key, item[6]*item[8]/100.0) for item in branches: nuc = nucname.id(item[0]) key = nucname.zzaaam(nuc) if (item[1] == 0) and (item[2] > metastable_cutoff): _set_branch_item(t9, nuc, key, item) if (item[1] != 0) and (item[2] > metastable_cutoff): key += 1 longest[key] = longest.get(key, 0) if (item[2] <= longest[key]): continue _set_branch_item(t9, nuc, key, item) for nucs, hl in zip([ origen22.ACTIVATION_PRODUCT_NUCS, origen22.ACTINIDE_AND_DAUGHTER_NUCS, origen22.FISSION_PRODUCT_NUCS ], [t9[i]['half_life'] for i in range(1, 4)]): for nuc in nucs: key = nucname.zzaaam(nuc) if key not in hl: hl[key] = data.half_life(nuc) return t9
def make_photon_fp_yields(nuc_data, build_dir): """Adds the photofission product yields to the hdf5 library. Parameters ---------- nuc_data : str Path to nuclide data file. build_dir : str Directory with cinder.dat file. """ # Open the HDF5 File db = tb.openFile(nuc_data, 'a', filters=BASIC_FILTERS) # Ensure that the appropriate file structure is present _init_cinder(db) # Read in cinder data file cinder_dat = os.path.join(build_dir, 'cinder.dat') with open(cinder_dat, 'r') as f: raw_data = f.read() # Get group sizes N_n, N_g = get_fp_sizes(raw_data) # get the info table info_table = grab_photon_fp_info(raw_data) # Grab the part of the file that is a neutron fission product yields m_yields = re.search(gfp_yields_pattern, raw_data, re.DOTALL) gfp_yields_raw = m_yields.group(0) # Init the neutron fission product info table gfp_table = db.createTable('/photon/cinder_fission_products/', 'yields', np.empty(0, dtype=fp_yields_dtype), 'CINDER Photofission Product Yields') gfprow = gfp_table.row # Iterate over all to-nucs fp_to_nuc_pattern = fp_to_nuc_base + N_g * fp_to_nuc_insert + ")" for m_to in re.finditer(fp_to_nuc_pattern, gfp_yields_raw): to_nuc = nucname.zzaaam(m_to.group(2).strip()) # Check matestable state if 1 < to_nuc % 10: # Metastable state too high! continue # Get the array of yield data yields = np.array(m_to.group(3).split(), dtype=float) assert len(yields) == N_g # Prep rows to the table for n in range(N_g): info = info_table[n] gfprow['index'] = info[0] gfprow['from_nuc'] = info[1] gfprow['to_nuc'] = to_nuc gfprow['mass_frac'] = yields[n] gfprow.append() # Write the table gfp_table.flush() # Close the hdf5 file db.close()
def sigma_s_gh(nuc, temp=300.0, group_struct=None, phi_g=None, xs_cache=None): """Calculates the neutron scattering kernel for a nuclide. Parameters ---------- nuc : int, str, Material, or dict-like A nuclide or nuclide-atom fraction mapping. temp : float, optional Temperature [K] of material, defaults to 300.0. group_struct : array-like of floats, optional Energy group structure E_g [MeV] from highest-to-lowest energy, length G+1, defaults to xs_cache['E_g']. phi_g : array-like of floats, optional Group fluxes [n/cm^2/s] matching group_struct, length G, defaults to xs_cache['phi_g']. xs_cache : XSCache, optional Cross section cache to use, defaults to pyne.xs.cache.xs_cache. Returns ------- sig_s_gh : ndarray The scattering kernel, shape GxG. Notes ----- This pulls the scattering length out of nuc_data library. Warnings -------- This function is currently a stub until the proper way to compute the scattering kernel is determined. This function is safe to use but the results are trivial. This function simply returns an array with the diagonal elements set to sigma_s as computed by pyne.xs.models.sigma_s(). This conserves the calculation of sigma_s_g by summing sigma_s_gh over the h-index. """ xs_cache = cache.xs_cache if xs_cache is None else xs_cache _prep_cache(xs_cache, group_struct, phi_g) if isinstance(nuc, collections.Iterable) and not isinstance(nuc, basestring): return _atom_weight_channel(sigma_s_gh, nuc, temp=temp, xs_cache=xs_cache) nuc = nucname.zzaaam(nuc) key = (nuc, 's_gh', temp) # Don't recalculate anything if you don't have to if key in xs_cache: return xs_cache[key] # Get some needed data E_g = xs_cache['E_g'] G = len(E_g) - 1 b = pyne.data.b(nuc) aw = pyne.data.atomic_mass(nuc) # OMG FIXME So hard! ## Initialize the scattering kernel #sig_s_gh = np.zeros((G, G), dtype=float) # ## Calculate all values of the kernel #for g, h in product(range(G), range(G)): # # Numerator inetgration term # dnumer = lambda _E_prime, _E: sigma_s_E(_E, b, M_A, T) * P(_E, _E_prime, M_A, T) * xs_cache['phi_g'][g] # # # Integral # nE = 26 # E_space = np.logspace(np.log10(xs_cache['E_g'][g]), np.log10(xs_cache['E_g'][g+1]), nE) # E_prime_space = np.logspace(np.log10(xs_cache['E_g'][h]), np.log10(xs_cache['E_g'][h+1]), nE) # # numer = msmintegrate.dbltrapz(dnumer, E_space, E_prime_space) # # # Denominator term, analytically integrated # denom = xs_cache['phi_g'][g] * (xs_cache['E_g'][g+1] - xs_cache['E_g'][g]) # # # Cross section value # sig_s_gh[g, h] = numer / denom # Temporary stub E_g_centers = (E_g[1:] + E_g[:-1]) / 2.0 sig_s = pyne.xs.models.sigma_s(E_g_centers, b, aw, temp) sig_s_gh = np.diag(sig_s) xs_cache[key] = sig_s_gh return sig_s_gh