mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 05:35:49 -04:00
Implemented new scatter MGXS library specification on python side and fixed python2 bug in writing strings to hdf5 file
This commit is contained in:
parent
88abdfb5ce
commit
1ef9acb8bd
2 changed files with 162 additions and 52 deletions
|
|
@ -56,17 +56,18 @@ data for the nuclide or material that it represents.
|
|||
that the azimuthal angular domain is subdivided if the
|
||||
`representation` attribute is "angle". This parameter is
|
||||
ignored otherwise.
|
||||
- **num-polar** (*int*) -- Number of equal width angular bins
|
||||
- **num-polar** (*int*) -- Number of equal width angular bins
|
||||
that the polar angular domain is subdivided if the
|
||||
`representation` attribute is "angle". This parameter is
|
||||
ignored otherwise.
|
||||
- **scatter-type** (*char[]*) -- The representation of the
|
||||
scattering angular distribution. The options are either
|
||||
"legendre", "histogram", or "tabular". If not provided, the
|
||||
default of "legendre" will be assumed.
|
||||
- **order** (*int*) -- Either the Legendre order, number of bins,
|
||||
or number of points (depending on the value of `scatter-type`)
|
||||
used to describe the angular distribution associated with each group-to-group transfer probability.
|
||||
- **scatter-type** (*char[]*) -- The representation of the
|
||||
scattering angular distribution. The options are either
|
||||
"legendre", "histogram", or "tabular". If not provided, the
|
||||
default of "legendre" will be assumed.
|
||||
- **order** (*int*) -- Either the Legendre order, number of bins,
|
||||
or number of points (depending on the value of `scatter-type`)
|
||||
used to describe the angular distribution associated with each
|
||||
group-to-group transfer probability.
|
||||
|
||||
**/<library name>/kTs/**
|
||||
|
||||
|
|
@ -86,30 +87,6 @@ Temperature-dependent data, provided for temperature <TTT>K.
|
|||
This is a 1-D vector if `representation` is "isotropic", or a 3-D
|
||||
vector if `representation` is "angle" with dimensions of
|
||||
[groups, azimuthal, polar].
|
||||
- **scatter matrix** (*double[][][]* or *double[][][][][]*) --
|
||||
Scattering moment matrices. This dataset requires the scattering
|
||||
moment matrices presented with the columns representing incoming
|
||||
group and rows representing the outgoing group. That is,
|
||||
down-scatter will be above the diagonal of the resultant matrix.
|
||||
This matrix is repeated for every Legendre order (in order of
|
||||
increasing orders) if `scatter-type` is "legendre"; otherwise, this
|
||||
matrix is repeated for every bin of the histogram or tabular
|
||||
representation. Finally, if ``representation`` is "angle", the
|
||||
above is repeated for every azimuthal angle and every polar angle,
|
||||
in that order.
|
||||
- **multiplicity matrix** (*double[][]* or *double[][][][]*) --
|
||||
Scattering multiplicity matrices.
|
||||
This dataset provides the ratio of neutrons produced in scattering
|
||||
collisions to the neutrons which undergo scattering collisions;
|
||||
that is, the multiplicity provides the code with a scaling factor
|
||||
to account for neutrons being produced in (n,xn) reactions. This
|
||||
information is assumed isotropic and therefore is not repeated for
|
||||
every Legendre moment or histogram/tabular bin. This matrix
|
||||
follows the same arrangement as described for the `scatter`
|
||||
dataset, with the exception of the data needed to provide the
|
||||
scattering type information.
|
||||
This dataset is optional, if it is not provided no multiplication
|
||||
(i.e., values of 1.0) will be assumed.
|
||||
- **fission** (*double[]* or *double[][][]*) -- Fission
|
||||
cross section.
|
||||
This is a 1-D vector if `representation` is "isotropic", or a 3-D
|
||||
|
|
@ -135,4 +112,46 @@ Temperature-dependent data, provided for temperature <TTT>K.
|
|||
the `nu-fission` data must represent the fission neutron energy
|
||||
spectra as well and thus will have one additional dimension
|
||||
for the outgoing energy group. In this case, `nu-fission` has the
|
||||
same dimensionality as `multiplicity matrix`.
|
||||
same dimensionality as `multiplicity matrix`.
|
||||
|
||||
**/<library name>/<TTT>K/scatter data/**
|
||||
|
||||
Data specific to neutron scattering for the temperature <TTT>K
|
||||
|
||||
:Datasets: - **g_out bounds** (*int[2]* or *int[][][2]) --
|
||||
Minimum (most energetic) and maximum (most thermal) outgoing groups
|
||||
with non-zero values of the scattering matrix. These group numbers
|
||||
use the standard ordering where the fastest neutron energy group
|
||||
is group 1 while the most thermal neutron energy group is group G.
|
||||
The dimensionality of `g_out bounds` is:
|
||||
`g_out bounds][g_in][g_out]`, or
|
||||
`g_out bounds[num-polar][num-azimuthal][g_in][g_out]`.
|
||||
The former is used when `representation` is "isotropic", and the
|
||||
latter when `representation` is "angle".
|
||||
- **scatter matrix** (*double[][]* or *double[][][][]*) --
|
||||
Flattened representation of the scattering moment matrices where
|
||||
the [g_in] and [g_out] indices are flattened. The pre-flattened
|
||||
array is shaped as follows (in row-major format):
|
||||
`scatter matrix[order(+1)][g_in][g_out]`, or
|
||||
`scatter matrix[num-polar][num-azimuthal][order(+1)][g_in][g_out]`
|
||||
The former is used when `representation` is "isotropic", and the
|
||||
latter when `representation` is "angle". Note that if the value of
|
||||
`scatter-type` is "legendre", the order dimension will be one
|
||||
larger than the value of `order`, otherwise it will match `order`.
|
||||
Finally, the g_out dimension has a dimensionality of
|
||||
`g_out bounds`[0] to `g_out bounds`[1].
|
||||
- **multiplicity matrix** (*double[]*) -- Flattened representation of
|
||||
the scattering moment matrices where the [g_in] and [g_out] indices
|
||||
are flattened. This dataset provides the code with a scaling factor
|
||||
to account for neutrons being produced in (n,xn) reactions. This
|
||||
is assumed isotropic and therefore is not repeated for every
|
||||
Legendre moment or histogram/tabular bin. This dataset is optional,
|
||||
if it is not provided no multiplication (i.e., values of 1.0) will
|
||||
be assumed.
|
||||
The pre-flattened array is shaped as follows (in row-major format):
|
||||
`multiplicity matrix[g_in][g_out]`, or
|
||||
`multiplicity matrix[num-polar][num-azimuthal][g_in][g_out]`
|
||||
The former is used when `representation` is "isotropic", and the
|
||||
latter when `representation` is "angle". Finally, the g_out
|
||||
dimension has a dimensionality of `g_out bounds`[0] to
|
||||
`g_out bounds`[1].
|
||||
|
|
@ -1137,14 +1137,15 @@ class XSdata(object):
|
|||
if self.fissionable is not None:
|
||||
grp.attrs['fissionable'] = self.fissionable
|
||||
if self.representation is not None:
|
||||
grp.attrs['representation'] = np.string_(self.representation)
|
||||
grp.attrs['representation'] = np.array(self.representation,
|
||||
dtype='S')
|
||||
if self.representation == 'angle':
|
||||
if self.num_azimuthal is not None:
|
||||
grp.attrs['num-azimuthal'] = self.num_azimuthal
|
||||
if self.num_polar is not None:
|
||||
grp.attrs['num-polar'] = self.num_polar
|
||||
if self.scatter_type is not None:
|
||||
grp.attrs['scatter-type'] = np.string_(self.scatter_type)
|
||||
grp.attrs['scatter-type'] = np.array(self.scatter_type, dtype='S')
|
||||
if self.order is not None:
|
||||
grp.attrs['order'] = self.order
|
||||
|
||||
|
|
@ -1157,20 +1158,16 @@ class XSdata(object):
|
|||
# Create the temperature datasets
|
||||
for i, temperature in enumerate(self.temperatures):
|
||||
xsgrp = grp.create_group(str(int(np.round(temperature))) + "K")
|
||||
if self._total[i] is not None:
|
||||
xsgrp.create_dataset("total", data=self._total[i],
|
||||
compression=compression)
|
||||
if self._absorption[i] is not None:
|
||||
xsgrp.create_dataset("absorption", data=self._absorption[i],
|
||||
compression=compression)
|
||||
if self._scatter_matrix[i] is not None:
|
||||
xsgrp.create_dataset("scatter matrix",
|
||||
data=self._scatter_matrix[i],
|
||||
compression=compression)
|
||||
if self._multiplicity_matrix[i] is not None:
|
||||
xsgrp.create_dataset("multiplicity matrix",
|
||||
data=self._multiplicity_matrix[i],
|
||||
compression=compression)
|
||||
if self._total[i] is None:
|
||||
raise ValueError('total data must be provided when writing '
|
||||
'the HDF5 library')
|
||||
xsgrp.create_dataset("total", data=self._total[i],
|
||||
compression=compression)
|
||||
if self._absorption[i] is None:
|
||||
raise ValueError('absorption data must be provided when '
|
||||
'writing the HDF5 library')
|
||||
xsgrp.create_dataset("absorption", data=self._absorption[i],
|
||||
compression=compression)
|
||||
if self.fissionable:
|
||||
if self._fission[i] is not None:
|
||||
xsgrp.create_dataset("fission", data=self._fission[i],
|
||||
|
|
@ -1182,9 +1179,103 @@ class XSdata(object):
|
|||
if self._chi[i] is not None:
|
||||
xsgrp.create_dataset("chi", data=self._chi[i],
|
||||
compression=compression)
|
||||
if self._nu_fission[i] is not None:
|
||||
xsgrp.create_dataset("nu-fission",
|
||||
data=self._nu_fission[i],
|
||||
if self._nu_fission[i] is None:
|
||||
raise ValueError('nu-fission data must be provided when '
|
||||
'writing the HDF5 library')
|
||||
xsgrp.create_dataset("nu-fission",
|
||||
data=self._nu_fission[i],
|
||||
compression=compression)
|
||||
|
||||
if self._scatter_matrix[i] is None:
|
||||
raise ValueError('Scatter matrix must be provided when '
|
||||
'writing the HDF5 library')
|
||||
# Get the sparse scattering data to print to the library
|
||||
G = self.energy_groups.num_groups
|
||||
if self.representation is 'isotropic':
|
||||
g_out_bounds = np.zeros((G, 2), dtype=np.int)
|
||||
for g_in in range(G):
|
||||
nz = np.nonzero(self._scatter_matrix[i][0, g_in, :])
|
||||
g_out_bounds[g_in, 0] = nz[0]
|
||||
g_out_bounds[g_in, 1] = nz[-1]
|
||||
# Now create the flattened scatter matrix array
|
||||
flat_scatt = []
|
||||
for l in range(self._scatter_matrix[i].shape[0]):
|
||||
for g_in in range(G):
|
||||
matrix = self._scatter_matrix[i][l, g_in, :]
|
||||
for g_out in range(g_out_bounds[g_in, 0],
|
||||
g_out_bounds[g_in, 1] + 1):
|
||||
flat_scatt.append(matrix[g_out])
|
||||
# And write it.
|
||||
scatt_grp = xsgrp.create_group('scatter data')
|
||||
scatt_grp.create_dataset("scatter matrix",
|
||||
data=np.array(flat_scatt),
|
||||
compression=compression)
|
||||
# Repeat for multiplicity
|
||||
if self._multiplicity_matrix[i] is not None:
|
||||
# Now create the flattened scatter matrix array
|
||||
flat_mult = []
|
||||
for g_in in range(G):
|
||||
matrix = self._multiplicity_matrix[i][g_in, :]
|
||||
for g_out in range(g_out_bounds[g_in, 0],
|
||||
g_out_bounds[g_in, 1] + 1):
|
||||
flat_mult.append(matrix[g_out])
|
||||
scatt_grp.create_dataset("multiplicity matrix",
|
||||
data=np.array(flat_mult),
|
||||
compression=compression)
|
||||
# And finally, adjust g_out_bounds for 1-based group counting
|
||||
# and write it.
|
||||
g_out_bounds[:, :] += 1
|
||||
scatt_grp.create_dataset("g_out bounds", data=g_out_bounds,
|
||||
compression=compression)
|
||||
|
||||
else:
|
||||
Np = self.num_polar
|
||||
Na = self.num_azimuthal
|
||||
g_out_bounds = np.zeros((Np, Na, G, 2), dtype=np.int)
|
||||
for p in range(Np):
|
||||
for a in range(Na):
|
||||
for g_in in range(G):
|
||||
matrix = self._scatter_matrix[i][p, a, 0, g_in, :]
|
||||
nz = np.nonzero(matrix)
|
||||
g_out_bounds[p, a, g_in, 0] = nz[0]
|
||||
g_out_bounds[p, a, g_in, 1] = nz[-1]
|
||||
# Now create the flattened scatter matrix array
|
||||
flat_scatt = [[[] for a in range(Na)] for p in range(Np)]
|
||||
for p in range(Np):
|
||||
for a in range(Na):
|
||||
for l in range(self._scatter_matrix[i].shape[2]):
|
||||
for g_in in range(G):
|
||||
matrix = \
|
||||
self._scatter_matrix[i][p, a, 0, g_in, :]
|
||||
for g_out in range(g_out_bounds[p, a, g_in, 0],
|
||||
g_out_bounds[p, a, g_in, 1]
|
||||
+ 1):
|
||||
flat_scatt[p][a].append(matrix[g_out])
|
||||
# And write it.
|
||||
scatt_grp = xsgrp.create_group('scatter data')
|
||||
scatt_grp.create_dataset("scatter matrix",
|
||||
data=np.array(flat_scatt).flatten(),
|
||||
compression=compression)
|
||||
# Repeat for multiplicity
|
||||
if self._multiplicity_matrix[i] is not None:
|
||||
# Now create the flattened scatter matrix array
|
||||
flat_mult = [[[] for a in range(Na)] for p in range(Np)]
|
||||
for p in range(Np):
|
||||
for a in range(Na):
|
||||
for l in range(self._scatter_matrix[i].shape[2]):
|
||||
for g_in in range(G):
|
||||
matrix = \
|
||||
self._multiplicity_matrix[i][p, a, g_in, :]
|
||||
for g_out in range(g_out_bounds[p, a, g_in, 0],
|
||||
g_out_bounds[p, a, g_in, 1] + 1):
|
||||
flat_mult[p][a].append(matrix[g_out])
|
||||
scatt_grp.create_dataset("multiplicity matrix",
|
||||
data=np.array(flat_mult).flatten(),
|
||||
compression=compression)
|
||||
# And finally, adjust g_out_bounds for 1-based group counting
|
||||
# and write it.
|
||||
g_out_bounds[:, :, :, :] += 1
|
||||
scatt_grp.create_dataset("g_out bounds", data=g_out_bounds,
|
||||
compression=compression)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue