def from_hdf5(cls, group): """Generate angular distribution from HDF5 data Parameters ---------- group : h5py.Group HDF5 group to read from Returns ------- openmc.data.AngleDistribution Angular distribution """ energy = group['energy'][()] data = group['mu'] offsets = data.attrs['offsets'] interpolation = data.attrs['interpolation'] mu = [] n_energy = len(energy) for i in range(n_energy): # Determine length of outgoing energy distribution and number of # discrete lines j = offsets[i] if i < n_energy - 1: n = offsets[i + 1] - j else: n = data.shape[1] - j interp = INTERPOLATION_SCHEME[interpolation[i]] mu_i = Tabular(data[0, j:j + n], data[1, j:j + n], interp) mu_i.c = data[2, j:j + n] mu.append(mu_i) return cls(energy, mu)
def from_hdf5(cls, group): """Generate angular distribution from HDF5 data Parameters ---------- group : h5py.Group HDF5 group to read from Returns ------- openmc.data.AngleDistribution Angular distribution """ energy = group['energy'].value data = group['mu'] offsets = data.attrs['offsets'] interpolation = data.attrs['interpolation'] mu = [] n_energy = len(energy) for i in range(n_energy): # Determine length of outgoing energy distribution and number of # discrete lines j = offsets[i] if i < n_energy - 1: n = offsets[i+1] - j else: n = data.shape[1] - j interp = INTERPOLATION_SCHEME[interpolation[i]] mu_i = Tabular(data[0, j:j+n], data[1, j:j+n], interp) mu_i.c = data[2, j:j+n] mu.append(mu_i) return cls(energy, mu)
def from_ace(cls, ace, idx, ldis): """Generate Kalbach-Mann energy-angle distribution from ACE data Parameters ---------- ace : openmc.data.ace.Table ACE table to read from idx : int Index in XSS array of the start of the energy distribution data (LDIS + LOCC - 1) ldis : int Index in XSS array of the start of the energy distribution block (e.g. JXS[11]) Returns ------- openmc.data.KalbachMann Kalbach-Mann energy-angle distribution """ # Read number of interpolation regions and incoming energies n_regions = int(ace.xss[idx]) n_energy_in = int(ace.xss[idx + 1 + 2*n_regions]) # Get interpolation information idx += 1 if n_regions > 0: breakpoints = ace.xss[idx:idx + n_regions].astype(int) interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) else: breakpoints = np.array([n_energy_in]) interpolation = np.array([2]) # Incoming energies at which distributions exist idx += 2*n_regions + 1 energy = ace.xss[idx:idx + n_energy_in]*EV_PER_MEV # Location of distributions idx += n_energy_in loc_dist = ace.xss[idx:idx + n_energy_in].astype(int) # Initialize variables energy_out = [] km_r = [] km_a = [] # Read each outgoing energy distribution for i in range(n_energy_in): idx = ldis + loc_dist[i] - 1 # intt = interpolation scheme (1=hist, 2=lin-lin) INTTp = int(ace.xss[idx]) intt = INTTp % 10 n_discrete_lines = (INTTp - intt)//10 if intt not in (1, 2): warn("Interpolation scheme for continuous tabular distribution " "is not histogram or linear-linear.") intt = 2 n_energy_out = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 5*n_energy_out].copy() data.shape = (5, n_energy_out) data[0,:] *= EV_PER_MEV # Create continuous distribution eout_continuous = Tabular(data[0][n_discrete_lines:], data[1][n_discrete_lines:]/EV_PER_MEV, INTERPOLATION_SCHEME[intt], ignore_negative=True) eout_continuous.c = data[2][n_discrete_lines:] if np.any(data[1][n_discrete_lines:] < 0.0): warn("Kalbach-Mann energy distribution has negative " "probabilities.") # If discrete lines are present, create a mixture distribution if n_discrete_lines > 0: eout_discrete = Discrete(data[0][:n_discrete_lines], data[1][:n_discrete_lines]) eout_discrete.c = data[2][:n_discrete_lines] if n_discrete_lines == n_energy_out: eout_i = eout_discrete else: p_discrete = min(sum(eout_discrete.p), 1.0) eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) else: eout_i = eout_continuous energy_out.append(eout_i) km_r.append(Tabulated1D(data[0], data[3])) km_a.append(Tabulated1D(data[0], data[4])) return cls(breakpoints, interpolation, energy, energy_out, km_r, km_a)
def from_hdf5(cls, group): """Generate Kalbach-Mann distribution from HDF5 data Parameters ---------- group : h5py.Group HDF5 group to read from Returns ------- openmc.data.KalbachMann Kalbach-Mann energy distribution """ interp_data = group['energy'].attrs['interpolation'] energy_breakpoints = interp_data[0, :] energy_interpolation = interp_data[1, :] energy = group['energy'][()] data = group['distribution'] offsets = data.attrs['offsets'] interpolation = data.attrs['interpolation'] n_discrete_lines = data.attrs['n_discrete_lines'] energy_out = [] precompound = [] slope = [] n_energy = len(energy) for i in range(n_energy): # Determine length of outgoing energy distribution and number of # discrete lines j = offsets[i] if i < n_energy - 1: n = offsets[i+1] - j else: n = data.shape[1] - j m = n_discrete_lines[i] # Create discrete distribution if lines are present if m > 0: eout_discrete = Discrete(data[0, j:j+m], data[1, j:j+m]) eout_discrete.c = data[2, j:j+m] p_discrete = eout_discrete.c[-1] # Create continuous distribution if m < n: interp = INTERPOLATION_SCHEME[interpolation[i]] eout_continuous = Tabular(data[0, j+m:j+n], data[1, j+m:j+n], interp) eout_continuous.c = data[2, j+m:j+n] # If both continuous and discrete are present, create a mixture # distribution if m == 0: eout_i = eout_continuous elif m == n: eout_i = eout_discrete else: eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) # Precompound factor and slope are on rows 3 and 4, respectively km_r = Tabulated1D(data[0, j:j+n], data[3, j:j+n]) km_a = Tabulated1D(data[0, j:j+n], data[4, j:j+n]) energy_out.append(eout_i) precompound.append(km_r) slope.append(km_a) return cls(energy_breakpoints, energy_interpolation, energy, energy_out, precompound, slope)
def from_ace(cls, ace, location_dist, location_start): """Generate an angular distribution from ACE data Parameters ---------- ace : openmc.data.ace.Table ACE table to read from location_dist : int Index in the XSS array corresponding to the start of a block, e.g. JXS(9). location_start : int Index in the XSS array corresponding to the start of an angle distribution array Returns ------- openmc.data.AngleDistribution Angular distribution """ # Set starting index for angle distribution idx = location_dist + location_start - 1 # Number of energies at which angular distributions are tabulated n_energies = int(ace.xss[idx]) idx += 1 # Incoming energy grid energy = ace.xss[idx:idx + n_energies] * EV_PER_MEV idx += n_energies # Read locations for angular distributions lc = ace.xss[idx:idx + n_energies].astype(int) idx += n_energies mu = [] for i in range(n_energies): if lc[i] > 0: # Equiprobable 32 bin distribution idx = location_dist + abs(lc[i]) - 1 cos = ace.xss[idx:idx + 33] pdf = np.zeros(33) pdf[:32] = 1.0 / (32.0 * np.diff(cos)) cdf = np.linspace(0.0, 1.0, 33) mu_i = Tabular(cos, pdf, 'histogram', ignore_negative=True) mu_i.c = cdf elif lc[i] < 0: # Tabular angular distribution idx = location_dist + abs(lc[i]) - 1 intt = int(ace.xss[idx]) n_points = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 3 * n_points] data.shape = (3, n_points) mu_i = Tabular(data[0], data[1], INTERPOLATION_SCHEME[intt]) mu_i.c = data[2] else: # Isotropic angular distribution mu_i = Uniform(-1., 1.) mu.append(mu_i) return cls(energy, mu)
def from_ace(cls, ace, idx, ldis): """Generate correlated angle-energy distribution from ACE data Parameters ---------- ace : openmc.data.ace.Table ACE table to read from idx : int Index in XSS array of the start of the energy distribution data (LDIS + LOCC - 1) ldis : int Index in XSS array of the start of the energy distribution block (e.g. JXS[11]) Returns ------- openmc.data.CorrelatedAngleEnergy Correlated angle-energy distribution """ # Read number of interpolation regions and incoming energies n_regions = int(ace.xss[idx]) n_energy_in = int(ace.xss[idx + 1 + 2*n_regions]) # Get interpolation information idx += 1 if n_regions > 0: breakpoints = ace.xss[idx:idx + n_regions].astype(int) interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) else: breakpoints = np.array([n_energy_in]) interpolation = np.array([2]) # Incoming energies at which distributions exist idx += 2*n_regions + 1 energy = ace.xss[idx:idx + n_energy_in]*EV_PER_MEV # Location of distributions idx += n_energy_in loc_dist = ace.xss[idx:idx + n_energy_in].astype(int) # Initialize list of distributions energy_out = [] mu = [] # Read each outgoing energy distribution for i in range(n_energy_in): idx = ldis + loc_dist[i] - 1 # intt = interpolation scheme (1=hist, 2=lin-lin) INTTp = int(ace.xss[idx]) intt = INTTp % 10 n_discrete_lines = (INTTp - intt)//10 if intt not in (1, 2): warn("Interpolation scheme for continuous tabular distribution " "is not histogram or linear-linear.") intt = 2 # Secondary energy distribution n_energy_out = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 4*n_energy_out].copy() data.shape = (4, n_energy_out) data[0,:] *= EV_PER_MEV # Create continuous distribution eout_continuous = Tabular(data[0][n_discrete_lines:], data[1][n_discrete_lines:]/EV_PER_MEV, INTERPOLATION_SCHEME[intt], ignore_negative=True) eout_continuous.c = data[2][n_discrete_lines:] if np.any(data[1][n_discrete_lines:] < 0.0): warn("Correlated angle-energy distribution has negative " "probabilities.") # If discrete lines are present, create a mixture distribution if n_discrete_lines > 0: eout_discrete = Discrete(data[0][:n_discrete_lines], data[1][:n_discrete_lines]) eout_discrete.c = data[2][:n_discrete_lines] if n_discrete_lines == n_energy_out: eout_i = eout_discrete else: p_discrete = min(sum(eout_discrete.p), 1.0) eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) else: eout_i = eout_continuous energy_out.append(eout_i) lc = data[3].astype(int) # Secondary angular distributions mu_i = [] for j in range(n_energy_out): if lc[j] > 0: idx = ldis + abs(lc[j]) - 1 intt = int(ace.xss[idx]) n_cosine = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 3*n_cosine] data.shape = (3, n_cosine) mu_ij = Tabular(data[0], data[1], INTERPOLATION_SCHEME[intt]) mu_ij.c = data[2] else: # Isotropic distribution mu_ij = Uniform(-1., 1.) mu_i.append(mu_ij) # Add cosine distributions for this incoming energy to list mu.append(mu_i) return cls(breakpoints, interpolation, energy, energy_out, mu)
def from_hdf5(cls, group): """Generate correlated angle-energy distribution from HDF5 data Parameters ---------- group : h5py.Group HDF5 group to read from Returns ------- openmc.data.CorrelatedAngleEnergy Correlated angle-energy distribution """ interp_data = group['energy'].attrs['interpolation'] energy_breakpoints = interp_data[0, :] energy_interpolation = interp_data[1, :] energy = group['energy'].value offsets = group['energy_out'].attrs['offsets'] interpolation = group['energy_out'].attrs['interpolation'] n_discrete_lines = group['energy_out'].attrs['n_discrete_lines'] dset_eout = group['energy_out'].value energy_out = [] dset_mu = group['mu'].value mu = [] n_energy = len(energy) for i in range(n_energy): # Determine length of outgoing energy distribution and number of # discrete lines offset_e = offsets[i] if i < n_energy - 1: n = offsets[i+1] - offset_e else: n = dset_eout.shape[1] - offset_e m = n_discrete_lines[i] # Create discrete distribution if lines are present if m > 0: x = dset_eout[0, offset_e:offset_e+m] p = dset_eout[1, offset_e:offset_e+m] eout_discrete = Discrete(x, p) eout_discrete.c = dset_eout[2, offset_e:offset_e+m] p_discrete = eout_discrete.c[-1] # Create continuous distribution if m < n: interp = INTERPOLATION_SCHEME[interpolation[i]] x = dset_eout[0, offset_e+m:offset_e+n] p = dset_eout[1, offset_e+m:offset_e+n] eout_continuous = Tabular(x, p, interp, ignore_negative=True) eout_continuous.c = dset_eout[2, offset_e+m:offset_e+n] # If both continuous and discrete are present, create a mixture # distribution if m == 0: eout_i = eout_continuous elif m == n: eout_i = eout_discrete else: eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) # Read angular distributions mu_i = [] for j in range(n): # Determine interpolation scheme interp_code = int(dset_eout[3, offsets[i] + j]) # Determine offset and length offset_mu = int(dset_eout[4, offsets[i] + j]) if offsets[i] + j < dset_eout.shape[1] - 1: n_mu = int(dset_eout[4, offsets[i] + j + 1]) - offset_mu else: n_mu = dset_mu.shape[1] - offset_mu # Get data x = dset_mu[0, offset_mu:offset_mu+n_mu] p = dset_mu[1, offset_mu:offset_mu+n_mu] c = dset_mu[2, offset_mu:offset_mu+n_mu] if interp_code == 0: mu_ij = Discrete(x, p) else: mu_ij = Tabular(x, p, INTERPOLATION_SCHEME[interp_code], ignore_negative=True) mu_ij.c = c mu_i.append(mu_ij) offset_mu += n_mu energy_out.append(eout_i) mu.append(mu_i) return cls(energy_breakpoints, energy_interpolation, energy, energy_out, mu)
def from_ace(cls, ace, idx, ldis): """Generate correlated angle-energy distribution from ACE data Parameters ---------- ace : openmc.data.ace.Table ACE table to read from idx : int Index in XSS array of the start of the energy distribution data (LDIS + LOCC - 1) ldis : int Index in XSS array of the start of the energy distribution block (e.g. JXS[11]) Returns ------- openmc.data.CorrelatedAngleEnergy Correlated angle-energy distribution """ # Read number of interpolation regions and incoming energies n_regions = int(ace.xss[idx]) n_energy_in = int(ace.xss[idx + 1 + 2*n_regions]) # Get interpolation information idx += 1 if n_regions > 0: breakpoints = ace.xss[idx:idx + n_regions].astype(int) interpolation = ace.xss[idx + n_regions:idx + 2*n_regions].astype(int) else: breakpoints = np.array([n_energy_in]) interpolation = np.array([2]) # Incoming energies at which distributions exist idx += 2*n_regions + 1 energy = ace.xss[idx:idx + n_energy_in]*EV_PER_MEV # Location of distributions idx += n_energy_in loc_dist = ace.xss[idx:idx + n_energy_in].astype(int) # Initialize list of distributions energy_out = [] mu = [] # Read each outgoing energy distribution for i in range(n_energy_in): idx = ldis + loc_dist[i] - 1 # intt = interpolation scheme (1=hist, 2=lin-lin). When discrete # lines are present, the value given is 10*n_discrete_lines + intt n_discrete_lines, intt = divmod(int(ace.xss[idx]), 10) if intt not in (1, 2): warn("Interpolation scheme for continuous tabular distribution " "is not histogram or linear-linear.") intt = 2 # Secondary energy distribution n_energy_out = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 4*n_energy_out].copy() data.shape = (4, n_energy_out) data[0,:] *= EV_PER_MEV # Create continuous distribution eout_continuous = Tabular(data[0][n_discrete_lines:], data[1][n_discrete_lines:]/EV_PER_MEV, INTERPOLATION_SCHEME[intt], ignore_negative=True) eout_continuous.c = data[2][n_discrete_lines:] if np.any(data[1][n_discrete_lines:] < 0.0): warn("Correlated angle-energy distribution has negative " "probabilities.") # If discrete lines are present, create a mixture distribution if n_discrete_lines > 0: eout_discrete = Discrete(data[0][:n_discrete_lines], data[1][:n_discrete_lines]) eout_discrete.c = data[2][:n_discrete_lines] if n_discrete_lines == n_energy_out: eout_i = eout_discrete else: p_discrete = min(sum(eout_discrete.p), 1.0) eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) else: eout_i = eout_continuous energy_out.append(eout_i) lc = data[3].astype(int) # Secondary angular distributions mu_i = [] for j in range(n_energy_out): if lc[j] > 0: idx = ldis + abs(lc[j]) - 1 intt = int(ace.xss[idx]) n_cosine = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 3*n_cosine] data.shape = (3, n_cosine) mu_ij = Tabular(data[0], data[1], INTERPOLATION_SCHEME[intt]) mu_ij.c = data[2] else: # Isotropic distribution mu_ij = Uniform(-1., 1.) mu_i.append(mu_ij) # Add cosine distributions for this incoming energy to list mu.append(mu_i) return cls(breakpoints, interpolation, energy, energy_out, mu)
def from_hdf5(cls, group): """Generate correlated angle-energy distribution from HDF5 data Parameters ---------- group : h5py.Group HDF5 group to read from Returns ------- openmc.data.CorrelatedAngleEnergy Correlated angle-energy distribution """ interp_data = group['energy'].attrs['interpolation'] energy_breakpoints = interp_data[0, :] energy_interpolation = interp_data[1, :] energy = group['energy'][()] offsets = group['energy_out'].attrs['offsets'] interpolation = group['energy_out'].attrs['interpolation'] n_discrete_lines = group['energy_out'].attrs['n_discrete_lines'] dset_eout = group['energy_out'][()] energy_out = [] dset_mu = group['mu'][()] mu = [] n_energy = len(energy) for i in range(n_energy): # Determine length of outgoing energy distribution and number of # discrete lines offset_e = offsets[i] if i < n_energy - 1: n = offsets[i+1] - offset_e else: n = dset_eout.shape[1] - offset_e m = n_discrete_lines[i] # Create discrete distribution if lines are present if m > 0: x = dset_eout[0, offset_e:offset_e+m] p = dset_eout[1, offset_e:offset_e+m] eout_discrete = Discrete(x, p) eout_discrete.c = dset_eout[2, offset_e:offset_e+m] p_discrete = eout_discrete.c[-1] # Create continuous distribution if m < n: interp = INTERPOLATION_SCHEME[interpolation[i]] x = dset_eout[0, offset_e+m:offset_e+n] p = dset_eout[1, offset_e+m:offset_e+n] eout_continuous = Tabular(x, p, interp, ignore_negative=True) eout_continuous.c = dset_eout[2, offset_e+m:offset_e+n] # If both continuous and discrete are present, create a mixture # distribution if m == 0: eout_i = eout_continuous elif m == n: eout_i = eout_discrete else: eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) # Read angular distributions mu_i = [] for j in range(n): # Determine interpolation scheme interp_code = int(dset_eout[3, offsets[i] + j]) # Determine offset and length offset_mu = int(dset_eout[4, offsets[i] + j]) if offsets[i] + j < dset_eout.shape[1] - 1: n_mu = int(dset_eout[4, offsets[i] + j + 1]) - offset_mu else: n_mu = dset_mu.shape[1] - offset_mu # Get data x = dset_mu[0, offset_mu:offset_mu+n_mu] p = dset_mu[1, offset_mu:offset_mu+n_mu] c = dset_mu[2, offset_mu:offset_mu+n_mu] if interp_code == 0: mu_ij = Discrete(x, p) else: mu_ij = Tabular(x, p, INTERPOLATION_SCHEME[interp_code], ignore_negative=True) mu_ij.c = c mu_i.append(mu_ij) offset_mu += n_mu energy_out.append(eout_i) mu.append(mu_i) return cls(energy_breakpoints, energy_interpolation, energy, energy_out, mu)
def from_ace(cls, ace_or_filename, name=None): """Generate thermal scattering data from an ACE table Parameters ---------- ace_or_filename : openmc.data.ace.Table or str ACE table to read from. If given as a string, it is assumed to be the filename for the ACE file. name : str GND-conforming name of the material, e.g. c_H_in_H2O. If none is passed, the appropriate name is guessed based on the name of the ACE table. Returns ------- openmc.data.ThermalScattering Thermal scattering data """ if isinstance(ace_or_filename, Table): ace = ace_or_filename else: ace = get_table(ace_or_filename) # Get new name that is GND-consistent ace_name, xs = ace.name.split('.') name = get_thermal_name(ace_name) # Assign temperature to the running list kTs = [ace.temperature * EV_PER_MEV] temperatures = [ str(int(round(ace.temperature * EV_PER_MEV / K_BOLTZMANN))) + "K" ] table = cls(name, ace.atomic_weight_ratio, kTs) # Incoherent inelastic scattering cross section idx = ace.jxs[1] n_energy = int(ace.xss[idx]) energy = ace.xss[idx + 1:idx + 1 + n_energy] * EV_PER_MEV xs = ace.xss[idx + 1 + n_energy:idx + 1 + 2 * n_energy] table.inelastic_xs[temperatures[0]] = Tabulated1D(energy, xs) if ace.nxs[7] == 0: table.secondary_mode = 'equal' elif ace.nxs[7] == 1: table.secondary_mode = 'skewed' elif ace.nxs[7] == 2: table.secondary_mode = 'continuous' n_energy_out = ace.nxs[4] if table.secondary_mode in ('equal', 'skewed'): n_mu = ace.nxs[3] idx = ace.jxs[3] table.inelastic_e_out[temperatures[0]] = \ ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2): n_mu + 2]*EV_PER_MEV table.inelastic_e_out[temperatures[0]].shape = \ (n_energy, n_energy_out) table.inelastic_mu_out[temperatures[0]] = \ ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2)] table.inelastic_mu_out[temperatures[0]].shape = \ (n_energy, n_energy_out, n_mu+2) table.inelastic_mu_out[temperatures[0]] = \ table.inelastic_mu_out[temperatures[0]][:, :, 1:] else: n_mu = ace.nxs[3] - 1 idx = ace.jxs[3] locc = ace.xss[idx:idx + n_energy].astype(int) n_energy_out = \ ace.xss[idx + n_energy:idx + 2 * n_energy].astype(int) energy_out = [] mu_out = [] for i in range(n_energy): idx = locc[i] # Outgoing energy distribution for incoming energy i e = ace.xss[idx + 1:idx + 1 + n_energy_out[i] * (n_mu + 3):n_mu + 3] * EV_PER_MEV p = ace.xss[idx + 2:idx + 2 + n_energy_out[i] * (n_mu + 3):n_mu + 3] / EV_PER_MEV c = ace.xss[idx + 3:idx + 3 + n_energy_out[i] * (n_mu + 3):n_mu + 3] eout_i = Tabular(e, p, 'linear-linear', ignore_negative=True) eout_i.c = c # Outgoing angle distribution for each # (incoming, outgoing) energy pair mu_i = [] for j in range(n_energy_out[i]): mu = ace.xss[idx + 4:idx + 4 + n_mu] p_mu = 1. / n_mu * np.ones(n_mu) mu_ij = Discrete(mu, p_mu) mu_ij.c = np.cumsum(p_mu) mu_i.append(mu_ij) idx += 3 + n_mu energy_out.append(eout_i) mu_out.append(mu_i) # Create correlated angle-energy distribution breakpoints = [n_energy] interpolation = [2] energy = table.inelastic_xs[temperatures[0]].x table.inelastic_dist[temperatures[0]] = CorrelatedAngleEnergy( breakpoints, interpolation, energy, energy_out, mu_out) # Incoherent/coherent elastic scattering cross section idx = ace.jxs[4] n_mu = ace.nxs[6] + 1 if idx != 0: n_energy = int(ace.xss[idx]) energy = ace.xss[idx + 1:idx + 1 + n_energy] * EV_PER_MEV P = ace.xss[idx + 1 + n_energy:idx + 1 + 2 * n_energy] if ace.nxs[5] == 4: # Coherent elastic table.elastic_xs[temperatures[0]] = CoherentElastic( energy, P * EV_PER_MEV) # Coherent elastic shouldn't have angular distributions listed assert n_mu == 0 else: # Incoherent elastic table.elastic_xs[temperatures[0]] = Tabulated1D(energy, P) # Angular distribution assert n_mu > 0 idx = ace.jxs[6] table.elastic_mu_out[temperatures[0]] = \ ace.xss[idx:idx + n_energy * n_mu] table.elastic_mu_out[temperatures[0]].shape = \ (n_energy, n_mu) # Get relevant nuclides -- NJOY only allows one to specify three # nuclides that the S(a,b) table applies to. Thus, for all elements # other than H and Fe, we automatically add all the naturally-occurring # isotopes. for zaid, awr in ace.pairs: if zaid > 0: Z, A = divmod(zaid, 1000) element = ATOMIC_SYMBOL[Z] if element in ['H', 'Fe']: table.nuclides.append(element + str(A)) else: if element + '0' not in table.nuclides: table.nuclides.append(element + '0') for isotope in sorted(NATURAL_ABUNDANCE): if re.match(r'{}\d+'.format(element), isotope): if isotope not in table.nuclides: table.nuclides.append(isotope) return table
def from_ace(cls, ace_or_filename, name=None): """Generate thermal scattering data from an ACE table Parameters ---------- ace_or_filename : openmc.data.ace.Table or str ACE table to read from. If given as a string, it is assumed to be the filename for the ACE file. name : str GND-conforming name of the material, e.g. c_H_in_H2O. If none is passed, the appropriate name is guessed based on the name of the ACE table. Returns ------- openmc.data.ThermalScattering Thermal scattering data """ if isinstance(ace_or_filename, Table): ace = ace_or_filename else: ace = get_table(ace_or_filename) # Get new name that is GND-consistent ace_name, xs = ace.name.split('.') name = get_thermal_name(ace_name) # Assign temperature to the running list kTs = [ace.temperature*EV_PER_MEV] temperatures = [str(int(round(ace.temperature*EV_PER_MEV / K_BOLTZMANN))) + "K"] table = cls(name, ace.atomic_weight_ratio, kTs) # Incoherent inelastic scattering cross section idx = ace.jxs[1] n_energy = int(ace.xss[idx]) energy = ace.xss[idx+1 : idx+1+n_energy]*EV_PER_MEV xs = ace.xss[idx+1+n_energy : idx+1+2*n_energy] table.inelastic_xs[temperatures[0]] = Tabulated1D(energy, xs) if ace.nxs[7] == 0: table.secondary_mode = 'equal' elif ace.nxs[7] == 1: table.secondary_mode = 'skewed' elif ace.nxs[7] == 2: table.secondary_mode = 'continuous' n_energy_out = ace.nxs[4] if table.secondary_mode in ('equal', 'skewed'): n_mu = ace.nxs[3] idx = ace.jxs[3] table.inelastic_e_out[temperatures[0]] = \ ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2): n_mu + 2]*EV_PER_MEV table.inelastic_e_out[temperatures[0]].shape = \ (n_energy, n_energy_out) table.inelastic_mu_out[temperatures[0]] = \ ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2)] table.inelastic_mu_out[temperatures[0]].shape = \ (n_energy, n_energy_out, n_mu+2) table.inelastic_mu_out[temperatures[0]] = \ table.inelastic_mu_out[temperatures[0]][:, :, 1:] else: n_mu = ace.nxs[3] - 1 idx = ace.jxs[3] locc = ace.xss[idx:idx + n_energy].astype(int) n_energy_out = \ ace.xss[idx + n_energy:idx + 2 * n_energy].astype(int) energy_out = [] mu_out = [] for i in range(n_energy): idx = locc[i] # Outgoing energy distribution for incoming energy i e = ace.xss[idx + 1:idx + 1 + n_energy_out[i]*(n_mu + 3): n_mu + 3]*EV_PER_MEV p = ace.xss[idx + 2:idx + 2 + n_energy_out[i]*(n_mu + 3): n_mu + 3]/EV_PER_MEV c = ace.xss[idx + 3:idx + 3 + n_energy_out[i]*(n_mu + 3): n_mu + 3] eout_i = Tabular(e, p, 'linear-linear', ignore_negative=True) eout_i.c = c # Outgoing angle distribution for each # (incoming, outgoing) energy pair mu_i = [] for j in range(n_energy_out[i]): mu = ace.xss[idx + 4:idx + 4 + n_mu] p_mu = 1. / n_mu * np.ones(n_mu) mu_ij = Discrete(mu, p_mu) mu_ij.c = np.cumsum(p_mu) mu_i.append(mu_ij) idx += 3 + n_mu energy_out.append(eout_i) mu_out.append(mu_i) # Create correlated angle-energy distribution breakpoints = [n_energy] interpolation = [2] energy = table.inelastic_xs[temperatures[0]].x table.inelastic_dist[temperatures[0]] = CorrelatedAngleEnergy( breakpoints, interpolation, energy, energy_out, mu_out) # Incoherent/coherent elastic scattering cross section idx = ace.jxs[4] n_mu = ace.nxs[6] + 1 if idx != 0: n_energy = int(ace.xss[idx]) energy = ace.xss[idx + 1: idx + 1 + n_energy]*EV_PER_MEV P = ace.xss[idx + 1 + n_energy: idx + 1 + 2 * n_energy] if ace.nxs[5] == 4: # Coherent elastic table.elastic_xs[temperatures[0]] = CoherentElastic( energy, P*EV_PER_MEV) # Coherent elastic shouldn't have angular distributions listed assert n_mu == 0 else: # Incoherent elastic table.elastic_xs[temperatures[0]] = Tabulated1D(energy, P) # Angular distribution assert n_mu > 0 idx = ace.jxs[6] table.elastic_mu_out[temperatures[0]] = \ ace.xss[idx:idx + n_energy * n_mu] table.elastic_mu_out[temperatures[0]].shape = \ (n_energy, n_mu) # Get relevant nuclides -- NJOY only allows one to specify three # nuclides that the S(a,b) table applies to. Thus, for all elements # other than H and Fe, we automatically add all the naturally-occurring # isotopes. for zaid, awr in ace.pairs: if zaid > 0: Z, A = divmod(zaid, 1000) element = ATOMIC_SYMBOL[Z] if element in ['H', 'Fe']: table.nuclides.append(element + str(A)) else: if element + '0' not in table.nuclides: table.nuclides.append(element + '0') for isotope in sorted(NATURAL_ABUNDANCE): if re.match(r'{}\d+'.format(element), isotope): if isotope not in table.nuclides: table.nuclides.append(isotope) return table
def from_ace(cls, ace_or_filename, name=None): """Generate thermal scattering data from an ACE table Parameters ---------- ace_or_filename : openmc.data.ace.Table or str ACE table to read from. If given as a string, it is assumed to be the filename for the ACE file. name : str GND-conforming name of the material, e.g. c_H_in_H2O. If none is passed, the appropriate name is guessed based on the name of the ACE table. Returns ------- openmc.data.ThermalScattering Thermal scattering data """ if isinstance(ace_or_filename, Table): ace = ace_or_filename else: ace = get_table(ace_or_filename) # Get new name that is GND-consistent ace_name, xs = ace.name.split('.') if not xs.endswith('t'): raise TypeError( "{} is not a thermal scattering ACE table.".format(ace)) if name is None: name = get_thermal_name(ace_name) # Assign temperature to the running list kTs = [ace.temperature * EV_PER_MEV] # Incoherent inelastic scattering cross section idx = ace.jxs[1] n_energy = int(ace.xss[idx]) energy = ace.xss[idx + 1:idx + 1 + n_energy] * EV_PER_MEV xs = ace.xss[idx + 1 + n_energy:idx + 1 + 2 * n_energy] inelastic_xs = Tabulated1D(energy, xs) energy_max = energy[-1] # Incoherent inelastic angle-energy distribution continuous = (ace.nxs[7] == 2) n_energy_out = ace.nxs[4] if not continuous: n_mu = ace.nxs[3] idx = ace.jxs[3] energy_out = ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2):n_mu + 2] * EV_PER_MEV energy_out.shape = (n_energy, n_energy_out) mu_out = ace.xss[idx:idx + n_energy * n_energy_out * (n_mu + 2)] mu_out.shape = (n_energy, n_energy_out, n_mu + 2) mu_out = mu_out[:, :, 1:] skewed = (ace.nxs[7] == 1) distribution = IncoherentInelasticAEDiscrete( energy_out, mu_out, skewed) else: n_mu = ace.nxs[3] - 1 idx = ace.jxs[3] locc = ace.xss[idx:idx + n_energy].astype(int) n_energy_out = \ ace.xss[idx + n_energy:idx + 2 * n_energy].astype(int) energy_out = [] mu_out = [] for i in range(n_energy): idx = locc[i] # Outgoing energy distribution for incoming energy i e = ace.xss[idx + 1:idx + 1 + n_energy_out[i] * (n_mu + 3):n_mu + 3] * EV_PER_MEV p = ace.xss[idx + 2:idx + 2 + n_energy_out[i] * (n_mu + 3):n_mu + 3] / EV_PER_MEV c = ace.xss[idx + 3:idx + 3 + n_energy_out[i] * (n_mu + 3):n_mu + 3] eout_i = Tabular(e, p, 'linear-linear', ignore_negative=True) eout_i.c = c # Outgoing angle distribution for each # (incoming, outgoing) energy pair mu_i = [] for j in range(n_energy_out[i]): mu = ace.xss[idx + 4:idx + 4 + n_mu] p_mu = 1. / n_mu * np.ones(n_mu) mu_ij = Discrete(mu, p_mu) mu_ij.c = np.cumsum(p_mu) mu_i.append(mu_ij) idx += 3 + n_mu energy_out.append(eout_i) mu_out.append(mu_i) # Create correlated angle-energy distribution breakpoints = [n_energy] interpolation = [2] energy = inelastic_xs.x distribution = IncoherentInelasticAE(breakpoints, interpolation, energy, energy_out, mu_out) table = cls(name, ace.atomic_weight_ratio, energy_max, kTs) T = table.temperatures[0] table.inelastic = ThermalScatteringReaction({T: inelastic_xs}, {T: distribution}) # Incoherent/coherent elastic scattering cross section idx = ace.jxs[4] n_mu = ace.nxs[6] + 1 if idx != 0: n_energy = int(ace.xss[idx]) energy = ace.xss[idx + 1:idx + 1 + n_energy] * EV_PER_MEV P = ace.xss[idx + 1 + n_energy:idx + 1 + 2 * n_energy] if ace.nxs[5] == 4: # Coherent elastic xs = CoherentElastic(energy, P * EV_PER_MEV) distribution = CoherentElasticAE(xs) # Coherent elastic shouldn't have angular distributions listed assert n_mu == 0 else: # Incoherent elastic xs = Tabulated1D(energy, P) # Angular distribution assert n_mu > 0 idx = ace.jxs[6] mu_out = ace.xss[idx:idx + n_energy * n_mu] mu_out.shape = (n_energy, n_mu) distribution = IncoherentElasticAEDiscrete(mu_out) table.elastic = ThermalScatteringReaction({T: xs}, {T: distribution}) # Get relevant nuclides -- NJOY only allows one to specify three # nuclides that the S(a,b) table applies to. Thus, for all elements # other than H and Fe, we automatically add all the naturally-occurring # isotopes. for zaid, awr in ace.pairs: if zaid > 0: Z, A = divmod(zaid, 1000) element = ATOMIC_SYMBOL[Z] if element in ['H', 'Fe']: table.nuclides.append(element + str(A)) else: if element + '0' not in table.nuclides: table.nuclides.append(element + '0') for isotope, _ in isotopes(element): if isotope not in table.nuclides: table.nuclides.append(isotope) return table
def from_ace(cls, ace, location_dist, location_start): """Generate an angular distribution from ACE data Parameters ---------- ace : openmc.data.ace.Table ACE table to read from location_dist : int Index in the XSS array corresponding to the start of a block, e.g. JXS(9). location_start : int Index in the XSS array corresponding to the start of an angle distribution array Returns ------- openmc.data.AngleDistribution Angular distribution """ # Set starting index for angle distribution idx = location_dist + location_start - 1 # Number of energies at which angular distributions are tabulated n_energies = int(ace.xss[idx]) idx += 1 # Incoming energy grid energy = ace.xss[idx:idx + n_energies]*EV_PER_MEV idx += n_energies # Read locations for angular distributions lc = ace.xss[idx:idx + n_energies].astype(int) idx += n_energies mu = [] for i in range(n_energies): if lc[i] > 0: # Equiprobable 32 bin distribution idx = location_dist + abs(lc[i]) - 1 cos = ace.xss[idx:idx + 33] pdf = np.zeros(33) pdf[:32] = 1.0/(32.0*np.diff(cos)) cdf = np.linspace(0.0, 1.0, 33) mu_i = Tabular(cos, pdf, 'histogram', ignore_negative=True) mu_i.c = cdf elif lc[i] < 0: # Tabular angular distribution idx = location_dist + abs(lc[i]) - 1 intt = int(ace.xss[idx]) n_points = int(ace.xss[idx + 1]) data = ace.xss[idx + 2:idx + 2 + 3*n_points] data.shape = (3, n_points) mu_i = Tabular(data[0], data[1], INTERPOLATION_SCHEME[intt]) mu_i.c = data[2] else: # Isotropic angular distribution mu_i = Uniform(-1., 1.) mu.append(mu_i) return cls(energy, mu)
def from_hdf5(cls, group): """Generate Kalbach-Mann distribution from HDF5 data Parameters ---------- group : h5py.Group HDF5 group to read from Returns ------- openmc.data.KalbachMann Kalbach-Mann energy distribution """ interp_data = group['energy'].attrs['interpolation'] energy_breakpoints = interp_data[0, :] energy_interpolation = interp_data[1, :] energy = group['energy'].value data = group['distribution'] offsets = data.attrs['offsets'] interpolation = data.attrs['interpolation'] n_discrete_lines = data.attrs['n_discrete_lines'] energy_out = [] precompound = [] slope = [] n_energy = len(energy) for i in range(n_energy): # Determine length of outgoing energy distribution and number of # discrete lines j = offsets[i] if i < n_energy - 1: n = offsets[i+1] - j else: n = data.shape[1] - j m = n_discrete_lines[i] # Create discrete distribution if lines are present if m > 0: eout_discrete = Discrete(data[0, j:j+m], data[1, j:j+m]) eout_discrete.c = data[2, j:j+m] p_discrete = eout_discrete.c[-1] # Create continuous distribution if m < n: interp = INTERPOLATION_SCHEME[interpolation[i]] eout_continuous = Tabular(data[0, j+m:j+n], data[1, j+m:j+n], interp) eout_continuous.c = data[2, j+m:j+n] # If both continuous and discrete are present, create a mixture # distribution if m == 0: eout_i = eout_continuous elif m == n: eout_i = eout_discrete else: eout_i = Mixture([p_discrete, 1. - p_discrete], [eout_discrete, eout_continuous]) km_r = Tabulated1D(data[0, j:j+n], data[3, j:j+n]) km_a = Tabulated1D(data[0, j:j+n], data[4, j:j+n]) energy_out.append(eout_i) precompound.append(km_r) slope.append(km_a) return cls(energy_breakpoints, energy_interpolation, energy, energy_out, precompound, slope)