diff --git a/openmc/element.py b/openmc/element.py index b1cd19e9b..d90cdf4fc 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -261,7 +261,7 @@ class Element(object): return isotopes - def plot_xs(self, types, divisor_types=None, temperature=294., + def plot_xs(self, types, divisor_types=None, temperature=294., axis=None, Erange=(1.E-5, 20.E6), sab_name=None, cross_sections=None, enrichment=None, **kwargs): """Creates a figure of continuous-energy microscopic cross sections @@ -280,6 +280,9 @@ class Element(object): temperature of 294K will be plotted. Note that the nearest temperature in the library for each nuclide will be used as opposed to using any interpolation. + axis : matplotlib.axes, optional + A previously generated axis to use for plotting. If not specified, + a new axis and figure will be generated. Erange : tuple of floats Energy range (in eV) to plot the cross section within sab_name : str, optional @@ -297,7 +300,10 @@ class Element(object): Returns ------- fig : matplotlib.figure.Figure - Matplotlib Figure of the generated macroscopic cross section + If axis is None, then a Matplotlib Figure of the generated + macroscopic cross section will be returned. Otherwise, a value of + None will be returned as the figure and axes have already been + generated. """ @@ -327,8 +333,12 @@ class Element(object): data = data_new # Generate the plot - fig = plt.figure(**kwargs) - ax = fig.add_subplot(111) + if axis is None: + fig = plt.figure(**kwargs) + ax = fig.add_subplot(111) + else: + fig = None + ax = axis for i in range(len(data)): # Set to loglog or semilogx depending on if we are plotting a data # type which we expect to vary linearly @@ -337,11 +347,12 @@ class Element(object): else: plot_func = ax.loglog if np.sum(data[i, :]) > 0.: + print('max = {:.2E}'.format(np.max(data[i, :]))) plot_func(E, data[i, :], label=types[i]) ax.set_xlabel('Energy [eV]') if divisor_types: - ax.set_ylabel('Elemental Cross Section') + ax.set_ylabel('Elemental Data') else: ax.set_ylabel('Elemental Cross Section [b]') ax.legend(loc='best') diff --git a/openmc/material.py b/openmc/material.py index ec68913ca..ed54bffc3 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -666,8 +666,7 @@ class Material(object): nuc_densities = [] nuc_density_types = [] for nuclide in nuclides.items(): - nuc, nuc_data = nuclide - nuc, nuc_density, nuc_density_type = nuc_data + nuc, nuc_density, nuc_density_type = nuclide[1] nucs.append(nuc) nuc_densities.append(nuc_density) nuc_density_types.append(nuc_density_type) @@ -713,7 +712,8 @@ class Material(object): return nuclides def plot_xs(self, types, divisor_types=None, temperature=294., - Erange=(1.E-5, 20.E6), cross_sections=None, **kwargs): + axis=None, Erange=(1.E-5, 20.E6), cross_sections=None, + **kwargs): """Creates a figure of continuous-energy macroscopic cross sections for this material @@ -730,6 +730,9 @@ class Material(object): temperature of 294K will be plotted. Note that the nearest temperature in the library for each nuclide will be used as opposed to using any interpolation. + axis : matplotlib.axes, optional + A previously generated axis to use for plotting. If not specified, + a new axis and figure will be generated. Erange : tuple of floats, optional Energy range (in eV) to plot the cross section within cross_sections : str, optional @@ -740,8 +743,11 @@ class Material(object): Returns ------- - fig : matplotlib.figure.Figure - Matplotlib Figure of the generated macroscopic cross section + fig : matplotlib.figure.Figure or None + If axis is None, then a Matplotlib Figure of the generated + macroscopic cross section will be returned. Otherwise, a value of + None will be returned as the figure and axes have already been + generated. """ @@ -770,8 +776,12 @@ class Material(object): data = data_new # Generate the plot - fig = plt.figure(**kwargs) - ax = fig.add_subplot(111) + if axis is None: + fig = plt.figure(**kwargs) + ax = fig.add_subplot(111) + else: + fig = None + ax = axis for i in range(len(data)): # Set to loglog or semilogx depending on if we are plotting a data # type which we expect to vary linearly @@ -784,7 +794,7 @@ class Material(object): ax.set_xlabel('Energy [eV]') if divisor_types: - ax.set_ylabel('Macroscopic Cross Section') + ax.set_ylabel('Macroscopic Data') else: ax.set_ylabel('Macroscopic Cross Section [1/cm]') ax.legend(loc='best') diff --git a/openmc/nuclide.py b/openmc/nuclide.py index fda44c43a..b549da896 100644 --- a/openmc/nuclide.py +++ b/openmc/nuclide.py @@ -97,7 +97,7 @@ class Nuclide(object): self._scattering = scattering - def plot_xs(self, types, divisor_types=None, temperature=294., + def plot_xs(self, types, divisor_types=None, temperature=294., axis=None, Erange=(1.E-5, 20.E6), sab_name=None, cross_sections=None, **kwargs): """Creates a figure of continuous-energy cross sections for this @@ -116,6 +116,9 @@ class Nuclide(object): temperature of 294K will be plotted. Note that the nearest temperature in the library for each nuclide will be used as opposed to using any interpolation. + axis : matplotlib.axes, optional + A previously generated axis to use for plotting. If not specified, + a new axis and figure will be generated. Erange : tuple of floats Energy range (in eV) to plot the cross section within sab_name : str, optional @@ -129,7 +132,10 @@ class Nuclide(object): Returns ------- fig : matplotlib.figure.Figure - Matplotlib Figure of the generated macroscopic cross section + If axis is None, then a Matplotlib Figure of the generated + macroscopic cross section will be returned. Otherwise, a value of + None will be returned as the figure and axes have already been + generated. """ @@ -158,8 +164,12 @@ class Nuclide(object): data = data_new # Generate the plot - fig = plt.figure(**kwargs) - ax = fig.add_subplot(111) + if axis is None: + fig = plt.figure(**kwargs) + ax = fig.add_subplot(111) + else: + fig = None + ax = axis for i in range(len(data)): to_plot = data[i](E) # Set to loglog or semilogx depending on if we are plotting a data @@ -173,7 +183,7 @@ class Nuclide(object): ax.set_xlabel('Energy [eV]') if divisor_types: - ax.set_ylabel('Microscopic Cross Section') + ax.set_ylabel('Microscopic Data') else: ax.set_ylabel('Microscopic Cross Section [b]') ax.legend(loc='best') @@ -357,8 +367,13 @@ class Nuclide(object): funcs.append(nuc[mt].xs[nucT]) else: funcs.append(nuc[mt].xs[nucT]) - elif mt == 0: + elif mt == UNITY_MT: funcs.append(lambda x: 1.) + elif mt == XI_MT: + awr = nuc.atomic_weight_ratio + alpha = ((awr - 1.) / (awr + 1.))**2 + xi = 1. + alpha * np.log(alpha) / (1. - alpha) + funcs.append(lambda x: xi) else: funcs.append(lambda x: 0.) xs.append(openmc.data.Combination(funcs, op)) diff --git a/openmc/plot_data.py b/openmc/plot_data.py index ac59c16ea..ed87f2f00 100644 --- a/openmc/plot_data.py +++ b/openmc/plot_data.py @@ -2,7 +2,12 @@ import numpy as np # Supported keywords for material xs plotting PLOT_TYPES = ['total', 'scatter', 'elastic', 'inelastic', 'fission', - 'absorption', 'capture', 'nu-fission', 'nu-scatter', 'unity'] + 'absorption', 'capture', 'nu-fission', 'nu-scatter', 'unity', + 'slowing-down power'] + +# Special MT values +UNITY_MT = -1 +XI_MT = -2 # MTs to combine to generate associated plot_types PLOT_TYPES_MT = {'total': (2, 3,), @@ -31,7 +36,15 @@ PLOT_TYPES_MT = {'total': (2, 3,), 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 183, 184, 190, 194, 196, 198, 199, 200, 875, 891), - 'unity': (0,)} + 'unity': (UNITY_MT,), + 'slowing-down power': (2, 4, 11, 16, 17, 22, 23, 24, 25, 28, + 29, 30, 32, 33, 34, 35, 36, 37, 41, 42, + 44, 45, 152, 153, 154, 156, 157, 158, + 159, 160, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 171, 172, 173, 174, + 175, 176, 177, 178, 179, 180, 181, 183, + 184, 190, 194, 196, 198, 199, 200, 875, + 891, XI_MT)} # Operations to use when combining MTs the first np.add is used in reference # to zero PLOT_TYPES_OP = {'total': (np.add,), @@ -41,7 +54,9 @@ PLOT_TYPES_OP = {'total': (np.add,), 'fission': (), 'absorption': (), 'capture': (), 'nu-fission': (), 'nu-scatter': (np.add,) * (len(PLOT_TYPES_MT['nu-scatter']) - 1), - 'unity': ()} + 'unity': (), + 'slowing-down power': + (np.add,) * (len(PLOT_TYPES_MT['slowing-down power']) - 2) + (np.multiply,)} # Whether or not to multiply the reaction by the yield as well PLOT_TYPES_YIELD = {'total': (False, False), @@ -51,7 +66,9 @@ PLOT_TYPES_YIELD = {'total': (False, False), 'fission': (False,), 'absorption': (False,), 'capture': (False,), 'nu-fission': (True,), 'nu-scatter': (True,) * len(PLOT_TYPES_MT['nu-scatter']), - 'unity': (False,)} + 'unity': (False,), + 'slowing-down power': + (True,) * len(PLOT_TYPES_MT['slowing-down power'])} # Types of plots to plot linearly in y PLOT_TYPES_LINEAR = ['nu-fission / fission', 'nu-scatter / scatter']