mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-29 06:35:48 -04:00
Add type checking to PyAPI multipole
This commit is contained in:
parent
8872ccdbc2
commit
85d26be07a
1 changed files with 277 additions and 23 deletions
|
|
@ -1,11 +1,15 @@
|
|||
from six import string_types
|
||||
|
||||
from numbers import Integral, Real
|
||||
|
||||
import h5py
|
||||
import numpy as np
|
||||
from scipy.special import wofz
|
||||
from six import string_types
|
||||
|
||||
from . import WMP_VERSION
|
||||
from .data import K_BOLTZMANN
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.mixin import EqualityMixin
|
||||
|
||||
|
||||
|
|
@ -96,6 +100,217 @@ def broaden_wmp_polynomials(En, dopp, n):
|
|||
|
||||
|
||||
class WindowedMultipole(EqualityMixin):
|
||||
def __init__(self):
|
||||
self.num_l = None
|
||||
self.fit_order = None
|
||||
self.fissionable = None
|
||||
self.formalism = None
|
||||
self.spacing = None
|
||||
self.sqrtAWR = None
|
||||
self.start_E = None
|
||||
self.end_E = None
|
||||
self.data = None
|
||||
self.pseudo_k0RS = None
|
||||
self.l_value = None
|
||||
self.w_start = None
|
||||
self.w_end = None
|
||||
self.broaden_poly = None
|
||||
self.curvefit = None
|
||||
|
||||
@property
|
||||
def num_l(self):
|
||||
return self._num_l
|
||||
|
||||
@property
|
||||
def fit_order(self):
|
||||
return self._fit_order
|
||||
|
||||
@property
|
||||
def fissionable(self):
|
||||
return self._fissionable
|
||||
|
||||
@property
|
||||
def formalism(self):
|
||||
return self._formalism
|
||||
|
||||
@property
|
||||
def spacing(self):
|
||||
return self._spacing
|
||||
|
||||
@property
|
||||
def sqrtAWR(self):
|
||||
return self._sqrtAWR
|
||||
|
||||
@property
|
||||
def start_E(self):
|
||||
return self._start_E
|
||||
|
||||
@property
|
||||
def end_E(self):
|
||||
return self._end_E
|
||||
|
||||
@property
|
||||
def data(self):
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def pseudo_k0RS(self):
|
||||
return self._pseudo_k0RS
|
||||
|
||||
@property
|
||||
def l_value(self):
|
||||
return self._l_value
|
||||
|
||||
@property
|
||||
def w_start(self):
|
||||
return self._w_start
|
||||
|
||||
@property
|
||||
def w_end(self):
|
||||
return self._w_end
|
||||
|
||||
@property
|
||||
def broaden_poly(self):
|
||||
return self._broaden_poly
|
||||
|
||||
@property
|
||||
def curvefit(self):
|
||||
return self._curvefit
|
||||
|
||||
@num_l.setter
|
||||
def num_l(self, num_l):
|
||||
if num_l is not None:
|
||||
cv.check_type('num_l', num_l, Integral)
|
||||
cv.check_greater_than('num_l', num_l, 1, equality=True)
|
||||
self._num_l = num_l
|
||||
|
||||
@fit_order.setter
|
||||
def fit_order(self, fit_order):
|
||||
if fit_order is not None:
|
||||
cv.check_type('fit_order', fit_order, Integral)
|
||||
cv.check_greater_than('fit_order', fit_order, 1, equality=True)
|
||||
self._fit_order = fit_order
|
||||
|
||||
@fissionable.setter
|
||||
def fissionable(self, fissionable):
|
||||
if fissionable is not None:
|
||||
cv.check_type('fissionable', fissionable, bool)
|
||||
self._fissionable = fissionable
|
||||
|
||||
@formalism.setter
|
||||
def formalism(self, formalism):
|
||||
if formalism is not None:
|
||||
cv.check_type('formalism', formalism, string_types)
|
||||
cv.check_value('formalism', formalism, ('MLBW', 'RM'))
|
||||
self._formalism = formalism
|
||||
|
||||
@spacing.setter
|
||||
def spacing(self, spacing):
|
||||
if spacing is not None:
|
||||
cv.check_type('spacing', spacing, Real)
|
||||
cv.check_greater_than('spacing', spacing, 0.0, equality=False)
|
||||
self._spacing = spacing
|
||||
|
||||
@sqrtAWR.setter
|
||||
def sqrtAWR(self, sqrtAWR):
|
||||
if sqrtAWR is not None:
|
||||
cv.check_type('sqrtAWR', sqrtAWR, Real)
|
||||
cv.check_greater_than('sqrtAWR', sqrtAWR, 0.0, equality=False)
|
||||
self._sqrtAWR = sqrtAWR
|
||||
|
||||
@start_E.setter
|
||||
def start_E(self, start_E):
|
||||
if start_E is not None:
|
||||
cv.check_type('start_E', start_E, Real)
|
||||
cv.check_greater_than('start_E', start_E, 0.0, equality=True)
|
||||
self._start_E = start_E
|
||||
|
||||
@end_E.setter
|
||||
def end_E(self, end_E):
|
||||
if end_E is not None:
|
||||
cv.check_type('end_E', end_E, Real)
|
||||
cv.check_greater_than('end_E', end_E, 0.0, equality=False)
|
||||
self._end_E = end_E
|
||||
|
||||
@data.setter
|
||||
def data(self, data):
|
||||
if data is not None:
|
||||
cv.check_type('data', data, np.ndarray)
|
||||
if len(data.shape) != 2:
|
||||
raise ValueError('Multipole data arrays must be 2D')
|
||||
if data.shape[1] not in (4, 5): # 4 for RM, 5 for MLBW
|
||||
raise ValueError('The second dimension of multipole data arrays'
|
||||
' must have a length of either 4 or 5')
|
||||
if not np.issubdtype(data.dtype, np.complex):
|
||||
raise TypeError('Multipole data arrays must be complex dtype')
|
||||
self._data = data
|
||||
|
||||
@pseudo_k0RS.setter
|
||||
def pseudo_k0RS(self, pseudo_k0RS):
|
||||
if pseudo_k0RS is not None:
|
||||
cv.check_type('pseudo_k0RS', pseudo_k0RS, np.ndarray)
|
||||
if len(pseudo_k0RS.shape) != 1:
|
||||
raise ValueError('Multipole pseudo_k0RS arrays must be 1D')
|
||||
if not np.issubdtype(pseudo_k0RS.dtype, np.float):
|
||||
raise TypeError('Multipole data arrays must be float dtype')
|
||||
self._pseudo_k0RS = pseudo_k0RS
|
||||
|
||||
@l_value.setter
|
||||
def l_value(self, l_value):
|
||||
if l_value is not None:
|
||||
cv.check_type('l_value', l_value, np.ndarray)
|
||||
if len(l_value.shape) != 1:
|
||||
raise ValueError('Multipole l_value arrays must be 1D')
|
||||
if not np.issubdtype(l_value.dtype, np.integer):
|
||||
raise TypeError('Multipole l_value arrays must be integer'
|
||||
' dtype')
|
||||
self._l_value = l_value
|
||||
|
||||
@w_start.setter
|
||||
def w_start(self, w_start):
|
||||
if w_start is not None:
|
||||
cv.check_type('w_start', w_start, np.ndarray)
|
||||
if len(w_start.shape) != 1:
|
||||
raise ValueError('Multipole w_start arrays must be 1D')
|
||||
if not np.issubdtype(w_start.dtype, np.integer):
|
||||
raise TypeError('Multipole w_start arrays must be integer'
|
||||
' dtype')
|
||||
self._w_start = w_start
|
||||
|
||||
@w_end.setter
|
||||
def w_end(self, w_end):
|
||||
if w_end is not None:
|
||||
cv.check_type('w_end', w_end, np.ndarray)
|
||||
if len(w_end.shape) != 1:
|
||||
raise ValueError('Multipole w_end arrays must be 1D')
|
||||
if not np.issubdtype(w_end.dtype, np.integer):
|
||||
raise TypeError('Multipole w_end arrays must be integer dtype')
|
||||
self._w_end = w_end
|
||||
|
||||
@broaden_poly.setter
|
||||
def broaden_poly(self, broaden_poly):
|
||||
if broaden_poly is not None:
|
||||
cv.check_type('broaden_poly', broaden_poly, np.ndarray)
|
||||
if len(broaden_poly.shape) != 1:
|
||||
raise ValueError('Multipole broaden_poly arrays must be 1D')
|
||||
if not np.issubdtype(broaden_poly.dtype, np.bool):
|
||||
raise TypeError('Multipole broaden_poly arrays must be boolean'
|
||||
' dtype')
|
||||
self._broaden_poly = broaden_poly
|
||||
|
||||
@curvefit.setter
|
||||
def curvefit(self, curvefit):
|
||||
if curvefit is not None:
|
||||
cv.check_type('curvefit', curvefit, np.ndarray)
|
||||
if len(curvefit.shape) != 3:
|
||||
raise ValueError('Multipole curvefit arrays must be 3D')
|
||||
if curvefit.shape[2] != 3: # One each for sigT, sigA, sigF
|
||||
raise ValueError('The third dimension of multipole curvefit'
|
||||
' arrays must have a length of 3')
|
||||
if not np.issubdtype(curvefit.dtype, np.float):
|
||||
raise TypeError('Multipole curvefit arrays must be float dtype')
|
||||
self._curvefit = curvefit
|
||||
|
||||
@classmethod
|
||||
def from_hdf5(cls, group_or_filename):
|
||||
if isinstance(group_or_filename, h5py.Group):
|
||||
|
|
@ -111,27 +326,59 @@ class WindowedMultipole(EqualityMixin):
|
|||
|
||||
out = cls()
|
||||
|
||||
# Scalars.
|
||||
out.length = group['length'].value
|
||||
out.windows = group['windows'].value
|
||||
# Read scalar values. Note that group['max_w'] is ignored.
|
||||
|
||||
length = group['length'].value
|
||||
windows = group['windows'].value
|
||||
out.num_l = group['num_l'].value
|
||||
out.fit_order = group['fit_order'].value
|
||||
out.max_w = group['max_w'].value
|
||||
out.fissionable = group['fissionable'].value
|
||||
out.formalism = group['formalism'].value
|
||||
out.fissionable = bool(group['fissionable'].value)
|
||||
|
||||
if group['formalism'].value == FORM_MLBW:
|
||||
out.formalism = 'MLBW'
|
||||
elif group['formalism'].value == FORM_RM:
|
||||
out.formalism = 'RM'
|
||||
else:
|
||||
raise ValueError('Unrecognized/Unsupported R-matrix formalism')
|
||||
|
||||
out.spacing = group['spacing'].value
|
||||
out.sqrtAWR = group['sqrtAWR'].value
|
||||
out.start_E = group['start_E'].value
|
||||
out.end_E = group['end_E'].value
|
||||
|
||||
# Arrays.
|
||||
# Read arrays.
|
||||
|
||||
err = "WMP '{:}' array shape is not consistent with the '{:}' value"
|
||||
|
||||
out.data = group['data'].value
|
||||
if out.data.shape[0] != length:
|
||||
raise ValueError(err.format('data', 'length'))
|
||||
|
||||
out.pseudo_k0RS = group['pseudo_K0RS'].value
|
||||
if out.pseudo_k0RS.shape[0] != out.num_l:
|
||||
raise ValueError(err.format('pseudo_k0RS', 'num_l'))
|
||||
|
||||
out.l_value = group['l_value'].value
|
||||
if out.l_value.shape[0] != length:
|
||||
raise ValueError(err.format('l_value', 'length'))
|
||||
|
||||
out.w_start = group['w_start'].value
|
||||
if out.w_start.shape[0] != windows:
|
||||
raise ValueError(err.format('w_start', 'windows'))
|
||||
|
||||
out.w_end = group['w_end'].value
|
||||
out.broaden_poly = group['broaden_poly'].value
|
||||
if out.w_end.shape[0] != windows:
|
||||
raise ValueError(err.format('w_end', 'windows'))
|
||||
|
||||
out.broaden_poly = group['broaden_poly'].value.astype(np.bool)
|
||||
if out.broaden_poly.shape[0] != windows:
|
||||
raise ValueError(err.format('broaden_poly', 'windows'))
|
||||
|
||||
out.curvefit = group['curvefit'].value
|
||||
if out.curvefit.shape[0] != windows:
|
||||
raise ValueError(err.format('curvefit', 'windows'))
|
||||
if out.curvefit.shape[1] != out.fit_order + 1:
|
||||
raise ValueError(err.format('curvefit', 'fit_order'))
|
||||
|
||||
return out
|
||||
|
||||
|
|
@ -203,34 +450,41 @@ class WindowedMultipole(EqualityMixin):
|
|||
if sqrtkT == 0.0:
|
||||
# If at 0K, use asymptotic form.
|
||||
for i_pole in range(startw, endw):
|
||||
psi_chi = -1j / (self.data[i_pole, MP_EA] - sqrtE)
|
||||
c_temp = psi_chi / E
|
||||
if self.formalism == FORM_MLBW:
|
||||
sigT += ((self.data[i_pole, MLBW_RT] * c_temp *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
+ (self.data[i_pole, MLBW_RX] * c_temp).real)
|
||||
sigA += (self.data[i_pole, MLBW_RA] * c_temp).real
|
||||
sigF += (self.data[i_pole, MLBW_RF] * c_temp).real
|
||||
elif self.formalism == FORM_RM:
|
||||
sigT += (self.data[i_pole, RM_RT] * c_temp *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
sigA += (self.data[i_pole, RM_RA] * c_temp).real
|
||||
sigF += (self.data[i_pole, RM_RF] * c_temp).real
|
||||
psi_chi = -1j / (self.data[i_pole, MP_EA] - sqrtE)
|
||||
c_temp = psi_chi / E
|
||||
if self.formalism == 'MLBW':
|
||||
sigT += ((self.data[i_pole, MLBW_RT] * c_temp *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
+ (self.data[i_pole, MLBW_RX] * c_temp).real)
|
||||
sigA += (self.data[i_pole, MLBW_RA] * c_temp).real
|
||||
sigF += (self.data[i_pole, MLBW_RF] * c_temp).real
|
||||
elif self.formalism == 'RM':
|
||||
sigT += (self.data[i_pole, RM_RT] * c_temp *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
sigA += (self.data[i_pole, RM_RA] * c_temp).real
|
||||
sigF += (self.data[i_pole, RM_RF] * c_temp).real
|
||||
else:
|
||||
raise ValueError('Unrecognized/Unsupported R-matrix'
|
||||
' formalism')
|
||||
|
||||
else:
|
||||
# At temperature, use Faddeeva function-based form.
|
||||
for i_pole in range(startw, endw):
|
||||
Z = (sqrtE - self.data[i_pole, MP_EA]) * dopp
|
||||
w_val = faddeeva(Z) * dopp * invE * np.sqrt(np.pi)
|
||||
if self.formalism == FORM_MLBW:
|
||||
if self.formalism == 'MLBW':
|
||||
sigT += ((self.data[i_pole, MLBW_RT] *
|
||||
sigT_factor[self.l_value[i_pole]-1] +
|
||||
self.data[i_pole, MLBW_RX]) * w_val).real
|
||||
sigA += (self.data[i_pole, MLBW_RA] * w_val).real
|
||||
sigF += (self.data[i_pole, MLBW_RF] * w_val).real
|
||||
elif self.formalism == FORM_RM:
|
||||
elif self.formalism == 'RM':
|
||||
sigT += (self.data[i_pole, RM_RT] * w_val *
|
||||
sigT_factor[self.l_value[i_pole]-1]).real
|
||||
sigA += (self.data[i_pole, RM_RA] * w_val).real
|
||||
sigF += (self.data[i_pole, RM_RF] * w_val).real
|
||||
else:
|
||||
raise ValueError('Unrecognized/Unsupported R-matrix'
|
||||
' formalism')
|
||||
|
||||
return sigT, sigA, sigF
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue