def mask_background(self, mask_background): check_type('plot mask background', mask_background, Iterable, Integral) check_length('plot mask background', mask_background, 3) for rgb in mask_background: check_greater_than('plot mask background', rgb, 0, True) check_less_than('plot mask background', rgb, 256) self._mask_background = mask_background
def albedo(self, albedo): check_type('CMFD mesh albedo', albedo, Iterable, Real) check_length('CMFD mesh albedo', albedo, 6) for a in albedo: check_greater_than('CMFD mesh albedo', a, 0, True) check_less_than('CMFD mesh albedo', a, 1, True) self._albedo = albedo
def set_source_angle(self, stype, params=[]): """Defined the angular distribution of the external/starting source. Parameters ---------- stype : str The type of angular distribution. Valid options are "isotropic" and "monodirectional". The angle of the particle emitted from a source site is isotropic if the "isotropic" option is given. The angle of the particle emitted from a source site is the direction specified in ``params`` if the "monodirectional" option is given. params : Iterable of float For an "isotropic" angular distribution, ``params`` should not be specified. For a "monodirectional" angular distribution, ``params`` should be given as three floats which specify the angular cosines with respect to each axis. """ check_type("source angle type", stype, basestring) check_value("source angle type", stype, ["isotropic", "monodirectional"]) check_type("source angle parameters", params, Iterable, Real) if stype == "isotropic" and params is not None: msg = ( "Unable to set source angle parameters since they are not " "it is not supported for isotropic type sources" ) raise ValueError(msg) elif stype == "monodirectional": check_length("source angle parameters for a monodirectional " "source", params, 3) self._source_angle_type = stype self._source_angle_params = params
def background(self, background): cv.check_type('plot background', background, Iterable, Integral) cv.check_length('plot background', background, 3) for rgb in background: cv.check_greater_than('plot background', rgb, 0, True) cv.check_less_than('plot background', rgb, 256) self._background = background
def background(self, background): cv.check_type('plot background', background, Iterable, Integral) cv.check_length('plot background', background, 3) for rgb in background: cv.check_greater_than('plot background',rgb, 0, True) cv.check_less_than('plot background', rgb, 256) self._background = background
def trace(self, trace): cv.check_type('trace', trace, Iterable, Integral) cv.check_length('trace', trace, 3) cv.check_greater_than('trace batch', trace[0], 0) cv.check_greater_than('trace generation', trace[1], 0) cv.check_greater_than('trace particle', trace[2], 0) self._trace = trace
def meshlines(self, meshlines): cv.check_type('plot meshlines', meshlines, dict) if 'type' not in meshlines: msg = 'Unable to set on plot the meshlines "{0}" which ' \ 'does not have a "type" key'.format(meshlines) raise ValueError(msg) elif meshlines['type'] not in ['tally', 'entropy', 'ufs', 'cmfd']: msg = 'Unable to set the meshlines with ' \ 'type "{0}"'.format(meshlines['type']) raise ValueError(msg) if 'id' in meshlines: cv.check_type('plot meshlines id', meshlines['id'], Integral) cv.check_greater_than('plot meshlines id', meshlines['id'], 0, equality=True) if 'linewidth' in meshlines: cv.check_type('plot mesh linewidth', meshlines['linewidth'], Integral) cv.check_greater_than('plot mesh linewidth', meshlines['linewidth'], 0, equality=True) if 'color' in meshlines: cv.check_type('plot meshlines color', meshlines['color'], Iterable, Integral) cv.check_length('plot meshlines color', meshlines['color'], 3) for rgb in meshlines['color']: cv.check_greater_than('plot meshlines color', rgb, 0, True) cv.check_less_than('plot meshlines color', rgb, 256) self._meshlines = meshlines
def trace(self, trace): check_type('trace', trace, Iterable, Integral) check_length('trace', trace, 3) check_greater_than('trace batch', trace[0], 0) check_greater_than('trace generation', trace[1], 0) check_greater_than('trace particle', trace[2], 0) self._trace = trace
def set_source_space(self, stype, params): """Defined the spatial bounds of the external/starting source. Parameters ---------- stype : str The type of spatial distribution. Valid options are "box", "fission", and "point". A "box" spatial distribution has coordinates sampled uniformly in a parallelepiped. A "fission" spatial distribution samples locations from a "box" distribution but only locations in fissionable materials are accepted. A "point" spatial distribution has coordinates specified by a triplet. params : Iterable of float For a "box" or "fission" spatial distribution, ``params`` should be given as six real numbers, the first three of which specify the lower-left corner of a parallelepiped and the last three of which specify the upper-right corner. Source sites are sampled uniformly through that parallelepiped. For a "point" spatial distribution, ``params`` should be given as three real numbers which specify the (x,y,z) location of an isotropic point source """ check_type("source space type", stype, basestring) check_value("source space type", stype, ["box", "fission", "point"]) check_type("source space parameters", params, Iterable, Real) if stype in ["box", "fission"]: check_length("source space parameters for a " "box/fission distribution", params, 6) elif stype == "point": check_length("source space parameters for a point source", params, 3) self._source_space_type = stype self._source_space_params = params
def trace(self, trace): check_type("trace", trace, Iterable, Integral) check_length("trace", trace, 3) check_greater_than("trace batch", trace[0], 0) check_greater_than("trace generation", trace[1], 0) check_greater_than("trace particle", trace[2], 0) self._trace = trace
def mask_background(self, mask_background): cv.check_type('plot mask background', mask_background, Iterable, Integral) cv.check_length('plot mask background', mask_background, 3) for rgb in mask_background: cv.check_greater_than('plot mask background', rgb, 0, True) cv.check_less_than('plot mask background', rgb, 256) self._mask_background = mask_background
def upper_right(self, upper_right): cv.check_type('mesh upper_right', upper_right, Iterable, Real) cv.check_length('mesh upper_right', upper_right, 1, 3) self._upper_right = upper_right if self._width is not None: self._width = None warnings.warn("Unsetting width attribute.")
def dd_mesh_dimension(self, dimension): # TODO: remove this when domain decomposition is merged warnings.warn("This feature is not yet implemented in a release " "version of openmc") check_type("DD mesh dimension", dimension, Iterable, Integral) check_length("DD mesh dimension", dimension, 3) self._dd_mesh_dimension = dimension
def __init__(self, alpha, theta, alpha0): check_type("alpha", alpha, np.ndarray, numbers.Complex) check_type("theta", theta, np.ndarray, numbers.Complex) check_length("theta", theta, alpha.size) check_type("alpha0", alpha0, numbers.Real) self.alpha = alpha self.theta = theta self.alpha0 = alpha0
def dd_mesh_upper_right(self, upper_right): # TODO: remove this when domain decomposition is merged warnings.warn("This feature is not yet implemented in a release " "version of openmc") check_type("DD mesh upper right corner", upper_right, Iterable, Real) check_length("DD mesh upper right corner", upper_right, 3) self._dd_mesh_upper_right = upper_right
def width(self, width): cv.check_type('mesh width', width, Iterable, Real) cv.check_length('mesh width', width, 1, 3) self._width = width if self._upper_right is not None: self._upper_right = None warnings.warn("Unsetting upper_right attribute.")
def dd_mesh_dimension(self, dimension): # TODO: remove this when domain decomposition is merged warnings.warn('This feature is not yet implemented in a release ' 'version of openmc') check_type('DD mesh dimension', dimension, Iterable, Integral) check_length('DD mesh dimension', dimension, 3) self._dd_mesh_dimension = dimension
def dd_mesh_lower_left(self, lower_left): # TODO: remove this when domain decomposition is merged warnings.warn('This feature is not yet implemented in a release ' 'version of openmc') cv.check_type('DD mesh lower left corner', lower_left, Iterable, Real) cv.check_length('DD mesh lower left corner', lower_left, 3) self._dd_mesh_lower_left = lower_left
def get_condensed_groups(self, coarse_groups): """Return a coarsened version of this EnergyGroups object. This method merges together energy groups in this object into wider energy groups as defined by the list of groups specified by the user, and returns a new, coarse EnergyGroups object. Parameters ---------- coarse_groups : Iterable of 2-tuple The energy groups of interest - a list of 2-tuples, each directly corresponding to one of the new coarse groups. The values in the 2-tuples are upper/lower energy groups used to construct a new coarse group. For example, if [(1,2), (3,4)] was used as the coarse groups, fine groups 1 and 2 would be merged into coarse group 1 while fine groups 3 and 4 would be merged into coarse group 2. Returns ------- EnergyGroups A coarsened version of this EnergyGroups object. Raises ------ ValueError If the group edges have not yet been set. """ cv.check_type('group edges', coarse_groups, Iterable) for group in coarse_groups: cv.check_type('group edges', group, Iterable) cv.check_length('group edges', group, 2) cv.check_greater_than('lower group', group[0], 1, True) cv.check_less_than('lower group', group[0], self.num_groups, True) cv.check_greater_than('upper group', group[0], 1, True) cv.check_less_than('upper group', group[0], self.num_groups, True) cv.check_less_than('lower group', group[0], group[1], False) # Compute the group indices into the coarse group group_bounds = [group[1] for group in coarse_groups] group_bounds.insert(0, coarse_groups[0][0]) # Determine the indices mapping the fine-to-coarse energy groups group_bounds = np.asarray(group_bounds) group_indices = np.flipud(self.num_groups - group_bounds) group_indices[-1] += 1 # Determine the edges between coarse energy groups and sort # in increasing order in case the user passed in unordered groups group_edges = self.group_edges[group_indices] group_edges = np.sort(group_edges) # Create a new condensed EnergyGroups object condensed_groups = EnergyGroups() condensed_groups.group_edges = group_edges return condensed_groups
def get_condensed_groups(self, coarse_groups): """Return a coarsened version of this EnergyGroups object. This method merges together energy groups in this object into wider energy groups as defined by the list of groups specified by the user, and returns a new, coarse EnergyGroups object. Parameters ---------- coarse_groups : Iterable of 2-tuple The energy groups of interest - a list of 2-tuples, each directly corresponding to one of the new coarse groups. The values in the 2-tuples are upper/lower energy groups used to construct a new coarse group. For example, if [(1,2), (3,4)] was used as the coarse groups, fine groups 1 and 2 would be merged into coarse group 1 while fine groups 3 and 4 would be merged into coarse group 2. Returns ------- openmc.mgxs.EnergyGroups A coarsened version of this EnergyGroups object. Raises ------ ValueError If the group edges have not yet been set. """ cv.check_type('group edges', coarse_groups, Iterable) for group in coarse_groups: cv.check_type('group edges', group, Iterable) cv.check_length('group edges', group, 2) cv.check_greater_than('lower group', group[0], 1, True) cv.check_less_than('lower group', group[0], self.num_groups, True) cv.check_greater_than('upper group', group[0], 1, True) cv.check_less_than('upper group', group[0], self.num_groups, True) cv.check_less_than('lower group', group[0], group[1], False) # Compute the group indices into the coarse group group_bounds = [group[1] for group in coarse_groups] group_bounds.insert(0, coarse_groups[0][0]) # Determine the indices mapping the fine-to-coarse energy groups group_bounds = np.asarray(group_bounds) group_indices = np.flipud(self.num_groups - group_bounds) group_indices[-1] += 1 # Determine the edges between coarse energy groups and sort # in increasing order in case the user passed in unordered groups group_edges = self.group_edges[group_indices] group_edges = np.sort(group_edges) # Create a new condensed EnergyGroups object condensed_groups = EnergyGroups() condensed_groups.group_edges = group_edges return condensed_groups
def dd_mesh_lower_left(self, lower_left): # TODO: remove this when domain decomposition is merged warnings.warn('This feature is not yet implemented in a release ' 'version of openmc') check_type('DD mesh lower left corner', lower_left, Iterable, Real) check_length('DD mesh lower left corner', lower_left, 3) self._dd_mesh_lower_left = lower_left
def dd_mesh_upper_right(self, upper_right): # TODO: remove this when domain decomposition is merged warnings.warn('This feature is not yet implemented in a release ' 'version of openmc') check_type('DD mesh upper right corner', upper_right, Iterable, Real) check_length('DD mesh upper right corner', upper_right, 3) self._dd_mesh_upper_right = upper_right
def mask_background(self, mask_background): cv.check_type('plot mask background', mask_background, Iterable) if isinstance(mask_background, string_types): if mask_background.lower() not in _SVG_COLORS: raise ValueError("'{}' is not a valid color.".format(mask_background)) else: cv.check_length('plot mask_background', mask_background, 3) for rgb in mask_background: cv.check_greater_than('plot mask background', rgb, 0, True) cv.check_less_than('plot mask background', rgb, 256) self._mask_background = mask_background
def _check_color(err_string, color): cv.check_type(err_string, color, Iterable) if isinstance(color, str): if color.lower() not in _SVG_COLORS: raise ValueError("'{}' is not a valid color.".format(color)) else: cv.check_length(err_string, color, 3) for rgb in color: cv.check_type(err_string, rgb, Real) cv.check_greater_than('RGB component', rgb, 0, True) cv.check_less_than('RGB component', rgb, 256)
def __init__(self, mesh, lower_ww_bounds, upper_ww_bounds=None, upper_bound_ratio=None, energy_bins=None, particle_type='neutron', survival_ratio=3, max_lower_bound_ratio=None, max_split=10, weight_cutoff=1.e-38, id=None): self.mesh = mesh self.id = id self.particle_type = particle_type self.energy_bins = energy_bins self.lower_ww_bounds = lower_ww_bounds cv.check_length('Lower window bounds', self.lower_ww_bounds, len(self.energy_bins)) if upper_ww_bounds is not None and upper_bound_ratio: raise ValueError("Exactly one of upper_ww_bounds and " "upper_bound_ratio must be present.") if upper_ww_bounds is None and upper_bound_ratio is None: raise ValueError("Exactly one of upper_ww_bounds and " "upper_bound_ratio must be present.") if upper_bound_ratio: self.upper_ww_bounds = [ lb * upper_bound_ratio for lb in self.lower_ww_bounds ] if upper_ww_bounds is not None: self.upper_ww_bounds = upper_ww_bounds if len(self.lower_ww_bounds) != len(self.upper_ww_bounds): raise ValueError( 'Size of the lower and upper weight window bounds ' 'do not match') self.survival_ratio = survival_ratio self._max_lower_bound_ratio = None if max_lower_bound_ratio is not None: self.max_lower_bound_ratio = max_lower_bound_ratio self.max_split = max_split self.weight_cutoff = weight_cutoff
def rotation(self, rotation): cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) # Save rotation matrix -- the reason we do this instead of having it be # automatically calculated when the rotation_matrix property is accessed # is so that plotting on a rotated geometry can be done faster. phi, theta, psi = self.rotation * (-pi / 180.) c3, s3 = cos(phi), sin(phi) c2, s2 = cos(theta), sin(theta) c1, s1 = cos(psi), sin(psi) self._rotation_matrix = np.array( [[c1 * c2, c1 * s2 * s3 - c3 * s1, s1 * s3 + c1 * c3 * s2], [c2 * s1, c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3], [-s2, c2 * s3, c2 * c3]])
def colors(self, colors): cv.check_type('plot colors', colors, Mapping) for key, value in colors.items(): cv.check_type('plot color key', key, (openmc.Cell, openmc.Material)) cv.check_type('plot color value', value, Iterable) if isinstance(value, string_types): if value.lower() not in _SVG_COLORS: raise ValueError("'{}' is not a valid color.".format(value)) else: cv.check_length('plot color (RGB)', value, 3) for component in value: cv.check_type('RGB component', component, Real) cv.check_greater_than('RGB component', component, 0, True) cv.check_less_than('RGB component', component, 255, True) self._colors = colors
def rotation(self, rotation): if not isinstance(self.fill, openmc.Universe): raise RuntimeError('Cell rotation can only be applied if the cell ' 'is filled with a Universe') cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) # Save rotation matrix phi, theta, psi = self.rotation*(-pi/180.) c3, s3 = cos(phi), sin(phi) c2, s2 = cos(theta), sin(theta) c1, s1 = cos(psi), sin(psi) self._rotation_matrix = np.array([ [c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], [-s2, c2*s3, c2*c3]])
def rotation(self, rotation): if not isinstance(self.fill, openmc.Universe): raise RuntimeError('Cell rotation can only be applied if the cell ' 'is filled with a Universe') cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) # Save rotation matrix phi, theta, psi = self.rotation * (-pi / 180.) c3, s3 = cos(phi), sin(phi) c2, s2 = cos(theta), sin(theta) c1, s1 = cos(psi), sin(psi) self._rotation_matrix = np.array( [[c1 * c2, c1 * s2 * s3 - c3 * s1, s1 * s3 + c1 * c3 * s2], [c2 * s1, c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3], [-s2, c2 * s3, c2 * c3]])
def rotation(self, rotation): if not isinstance(self.fill, openmc.Universe): raise TypeError('Cell rotation can only be applied if the cell ' 'is filled with a Universe.') cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) # Save rotation matrix -- the reason we do this instead of having it be # automatically calculated when the rotation_matrix property is accessed # is so that plotting on a rotated geometry can be done faster. phi, theta, psi = self.rotation*(-pi/180.) c3, s3 = cos(phi), sin(phi) c2, s2 = cos(theta), sin(theta) c1, s1 = cos(psi), sin(psi) self._rotation_matrix = np.array([ [c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2], [c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3], [-s2, c2*s3, c2*c3]])
def rotation(self, rotation): if not isinstance(self.fill, openmc.Universe): raise TypeError('Cell rotation can only be applied if the cell ' 'is filled with a Universe.') cv.check_type('cell rotation', rotation, Iterable, Real) cv.check_length('cell rotation', rotation, 3) self._rotation = np.asarray(rotation) # Save rotation matrix -- the reason we do this instead of having it be # automatically calculated when the rotation_matrix property is accessed # is so that plotting on a rotated geometry can be done faster. phi, theta, psi = self.rotation * (-pi / 180.) c3, s3 = cos(phi), sin(phi) c2, s2 = cos(theta), sin(theta) c1, s1 = cos(psi), sin(psi) self._rotation_matrix = np.array( [[c1 * c2, c1 * s2 * s3 - c3 * s1, s1 * s3 + c1 * c3 * s2], [c2 * s1, c1 * c3 + s1 * s2 * s3, c3 * s1 * s2 - c1 * s3], [-s2, c2 * s3, c2 * c3]])
def set_source_energy(self, stype, params=[]): """Defined the energy distribution of the external/starting source. Parameters ---------- stype : str The type of energy distribution. Valid options are "monoenergetic", "watt", and "maxwell". The "monoenergetic" option produces source sites at a single energy. The "watt" option produces source sites whose energy is sampled from a Watt fission spectrum. The "maxwell" option produce source sites whose energy is sampled from a Maxwell fission spectrum. params : Iterable of float For a "monoenergetic" energy distribution, ``params`` should be given as the energy in MeV of the source sites. For a "watt" energy distribution, ``params`` should be given as two real numbers :math:`a` and :math:`b` that parameterize the distribution :math:`p(E) dE = c e^{-E/a} \sinh \sqrt{b \, E} dE`. For a "maxwell" energy distribution, ``params`` should be given as one real number :math:`a` that parameterizes the distribution :math:`p(E) dE = c E e^{-E/a} dE`. """ check_type('source energy type', stype, basestring) check_value('source energy type', stype, ['monoenergetic', 'watt', 'maxwell']) check_type('source energy parameters', params, Iterable, Real) if stype in ['monoenergetic', 'maxwell']: check_length( 'source energy parameters for a monoenergetic ' 'or Maxwell source', params, 1) elif stype == 'watt': check_length('source energy parameters for a Watt source', params, 2) self._source_energy_type = stype self._source_energy_params = params
def temperature(self, temperature): cv.check_type('temperature settings', temperature, Mapping) for key, value in temperature.items(): cv.check_value( 'temperature key', key, ['default', 'method', 'tolerance', 'multipole', 'range']) if key == 'default': cv.check_type('default temperature', value, Real) elif key == 'method': cv.check_value('temperature method', value, ['nearest', 'interpolation']) elif key == 'tolerance': cv.check_type('temperature tolerance', value, Real) elif key == 'multipole': cv.check_type('temperature multipole', value, bool) elif key == 'range': cv.check_length('temperature range', value, 2) for T in value: cv.check_type('temperature', T, Real) self._temperature = temperature
def temperature(self, temperature): cv.check_type('temperature settings', temperature, Mapping) for key, value in temperature.items(): cv.check_value('temperature key', key, ['default', 'method', 'tolerance', 'multipole', 'range']) if key == 'default': cv.check_type('default temperature', value, Real) elif key == 'method': cv.check_value('temperature method', value, ['nearest', 'interpolation']) elif key == 'tolerance': cv.check_type('temperature tolerance', value, Real) elif key == 'multipole': cv.check_type('temperature multipole', value, bool) elif key == 'range': cv.check_length('temperature range', value, 2) for T in value: cv.check_type('temperature', T, Real) self._temperature = temperature
def set_source_energy(self, stype, params=[]): """Defined the energy distribution of the external/starting source. Parameters ---------- stype : str The type of energy distribution. Valid options are "monoenergetic", "watt", and "maxwell". The "monoenergetic" option produces source sites at a single energy. The "watt" option produces source sites whose energy is sampled from a Watt fission spectrum. The "maxwell" option produce source sites whose energy is sampled from a Maxwell fission spectrum. params : Iterable of float For a "monoenergetic" energy distribution, ``params`` should be given as the energy in MeV of the source sites. For a "watt" energy distribution, ``params`` should be given as two real numbers :math:`a` and :math:`b` that parameterize the distribution :math:`p(E) dE = c e^{-E/a} \sinh \sqrt{b \, E} dE`. For a "maxwell" energy distribution, ``params`` should be given as one real number :math:`a` that parameterizes the distribution :math:`p(E) dE = c E e^{-E/a} dE`. """ check_type('source energy type', stype, basestring) check_value('source energy type', stype, ['monoenergetic', 'watt', 'maxwell']) check_type('source energy parameters', params, Iterable, Real) if stype in ['monoenergetic', 'maxwell']: check_length('source energy parameters for a monoenergetic ' 'or Maxwell source', params, 1) elif stype == 'watt': check_length('source energy parameters for a Watt source', params, 2) self._source_energy_type = stype self._source_energy_params = params
def entropy_mesh(self, entropy): cv.check_type('entropy mesh', entropy, Mesh) cv.check_length('entropy mesh dimension', entropy.dimension, 3) cv.check_length('entropy mesh lower-left corner', entropy.lower_left, 3) cv.check_length('entropy mesh upper-right corner', entropy.upper_right, 3) self._entropy_mesh = entropy
def set_source_space(self, stype, params): """Defined the spatial bounds of the external/starting source. Parameters ---------- stype : str The type of spatial distribution. Valid options are "box", "fission", and "point". A "box" spatial distribution has coordinates sampled uniformly in a parallelepiped. A "fission" spatial distribution samples locations from a "box" distribution but only locations in fissionable materials are accepted. A "point" spatial distribution has coordinates specified by a triplet. params : Iterable of float For a "box" or "fission" spatial distribution, ``params`` should be given as six real numbers, the first three of which specify the lower-left corner of a parallelepiped and the last three of which specify the upper-right corner. Source sites are sampled uniformly through that parallelepiped. For a "point" spatial distribution, ``params`` should be given as three real numbers which specify the (x,y,z) location of an isotropic point source """ check_type('source space type', stype, basestring) check_value('source space type', stype, ['box', 'fission', 'point']) check_type('source space parameters', params, Iterable, Real) if stype in ['box', 'fission']: check_length( 'source space parameters for a ' 'box/fission distribution', params, 6) elif stype == 'point': check_length('source space parameters for a point source', params, 3) self._source_space_type = stype self._source_space_params = params
def set_source_angle(self, stype, params=[]): """Defined the angular distribution of the external/starting source. Parameters ---------- stype : str The type of angular distribution. Valid options are "isotropic" and "monodirectional". The angle of the particle emitted from a source site is isotropic if the "isotropic" option is given. The angle of the particle emitted from a source site is the direction specified in ``params`` if the "monodirectional" option is given. params : Iterable of float For an "isotropic" angular distribution, ``params`` should not be specified. For a "monodirectional" angular distribution, ``params`` should be given as three floats which specify the angular cosines with respect to each axis. """ check_type('source angle type', stype, basestring) check_value('source angle type', stype, ['isotropic', 'monodirectional']) check_type('source angle parameters', params, Iterable, Real) if stype == 'isotropic' and params is not None: msg = 'Unable to set source angle parameters since they are not ' \ 'it is not supported for isotropic type sources' raise ValueError(msg) elif stype == 'monodirectional': check_length( 'source angle parameters for a monodirectional ' 'source', params, 3) self._source_angle_type = stype self._source_angle_params = params
def width(self, width): cv.check_type('mesh width', width, Iterable, Real) cv.check_length('mesh width', width, 1, 3) self._width = width
def upper_right(self, upper_right): cv.check_type('mesh upper_right', upper_right, Iterable, Real) cv.check_length('mesh upper_right', upper_right, 1, 3) self._upper_right = upper_right
def lower_left(self, lower_left): cv.check_type('mesh lower_left', lower_left, Iterable, Real) cv.check_length('mesh lower_left', lower_left, 1, 3) self._lower_left = lower_left
def dimension(self, dimension): cv.check_type('mesh dimension', dimension, Iterable, Integral) cv.check_length('mesh dimension', dimension, 1, 3) self._dimension = dimension
def gauss_seidel_tolerance(self, gauss_seidel_tolerance): check_type('CMFD Gauss-Seidel tolerance', gauss_seidel_tolerance, Iterable, Real) check_length('Gauss-Seidel tolerance', gauss_seidel_tolerance, 2) self._gauss_seidel_tolerance = gauss_seidel_tolerance
def ufs_lower_left(self, lower_left): check_type("UFS mesh lower left corner", lower_left, Iterable, Real) check_length("UFS mesh lower left corner", lower_left, 3) self._ufs_lower_left = lower_left
def lower_left(self, lower_left): cv.check_type('mesh lower_left', lower_left, Iterable, Real) cv.check_length('mesh lower_left', lower_left, 2, 3) self._lower_left = lower_left
def pixels(self, pixels): cv.check_type('plot pixels', pixels, Iterable, Integral) cv.check_length('plot pixels', pixels, 2, 3) for dim in pixels: cv.check_greater_than('plot pixels', dim, 0) self._pixels = pixels
def origin(self, origin): cv.check_type('plot origin', origin, Iterable, Real) cv.check_length('plot origin', origin, 3) self._origin = origin
def build_cells(self, bc=['reflective'] * 6): """Generates a lattice of universes with the same dimensionality as the mesh object. The individual cells/universes produced will not have material definitions applied and so downstream code will have to apply that information. Parameters ---------- bc : iterable of {'reflective', 'periodic', 'transmission', or 'vacuum'} Boundary conditions for each of the four faces of a rectangle (if aplying to a 2D mesh) or six faces of a parallelepiped (if applying to a 3D mesh) provided in the following order: [x min, x max, y min, y max, z min, z max]. 2-D cells do not contain the z min and z max entries. Returns ------- root_cell : openmc.Cell The cell containing the lattice representing the mesh geometry; this cell is a single parallelepiped with boundaries matching the outermost mesh boundary with the boundary conditions from bc applied. cells : iterable of openmc.Cell The list of cells within each lattice position mimicking the mesh geometry. """ cv.check_length('bc', bc, length_min=4, length_max=6) for entry in bc: cv.check_value( 'bc', entry, ['transmission', 'vacuum', 'reflective', 'periodic']) # Build the cell which will contain the lattice xplanes = [ openmc.XPlane(x0=self.lower_left[0], boundary_type=bc[0]), openmc.XPlane(x0=self.upper_right[0], boundary_type=bc[1]) ] if len(self.dimension) == 1: yplanes = [ openmc.YPlane(y0=-1e10, boundary_type='reflective'), openmc.YPlane(y0=1e10, boundary_type='reflective') ] else: yplanes = [ openmc.YPlane(y0=self.lower_left[1], boundary_type=bc[2]), openmc.YPlane(y0=self.upper_right[1], boundary_type=bc[3]) ] if len(self.dimension) <= 2: # Would prefer to have the z ranges be the max supported float, but # these values are apparently different between python and Fortran. # Choosing a safe and sane default. # Values of +/-1e10 are used here as there seems to be an # inconsistency between what numpy uses as the max float and what # Fortran expects for a real(8), so this avoids code complication # and achieves the same goal. zplanes = [ openmc.ZPlane(z0=-1e10, boundary_type='reflective'), openmc.ZPlane(z0=1e10, boundary_type='reflective') ] else: zplanes = [ openmc.ZPlane(z0=self.lower_left[2], boundary_type=bc[4]), openmc.ZPlane(z0=self.upper_right[2], boundary_type=bc[5]) ] root_cell = openmc.Cell() root_cell.region = ((+xplanes[0] & -xplanes[1]) & (+yplanes[0] & -yplanes[1]) & (+zplanes[0] & -zplanes[1])) # Build the universes which will be used for each of the [i,j,k] # locations within the mesh. # We will concurrently build cells to assign to these universes cells = [] universes = [] for [i, j, k] in self.cell_generator(): cells.append(openmc.Cell()) universes.append(openmc.Universe()) universes[-1].add_cell(cells[-1]) lattice = openmc.RectLattice() lattice.lower_left = self.lower_left # Assign the universe and rotate to match the indexing expected for # the lattice lattice.universes = np.rot90(np.reshape(universes, self.dimension)) if self.width is not None: lattice.pitch = self.width else: dx = ((self.upper_right[0] - self.lower_left[0]) / self.dimension[0]) if len(self.dimension) == 1: lattice.pitch = [dx] elif len(self.dimension) == 2: dy = ((self.upper_right[1] - self.lower_left[1]) / self.dimension[1]) lattice.pitch = [dx, dy] else: dy = ((self.upper_right[1] - self.lower_left[1]) / self.dimension[1]) dz = ((self.upper_right[2] - self.lower_left[2]) / self.dimension[2]) lattice.pitch = [dx, dy, dz] # Fill Cell with the Lattice root_cell.fill = lattice return root_cell, cells
def width(self, width): cv.check_type('mesh width', width, Iterable, Real) cv.check_length('mesh width', width, 2, 3) self._width = width
def dimension(self, dimension): cv.check_type('mesh dimension', dimension, Iterable, Integral) cv.check_length('mesh dimension', dimension, 2, 3) self._dimension = dimension
def ufs_dimension(self, dimension): check_type("UFS mesh dimension", dimension, Iterable, Integral) check_length("UFS mesh dimension", dimension, 3) for dim in dimension: check_greater_than("UFS mesh dimension", dim, 1, True) self._ufs_dimension = dimension
def upper_right(self, upper_right): cv.check_type('mesh upper_right', upper_right, Iterable, Real) cv.check_length('mesh upper_right', upper_right, 2, 3) self._upper_right = upper_right
def ufs_upper_right(self, upper_right): check_type("UFS mesh upper right corner", upper_right, Iterable, Real) check_length("UFS mesh upper right corner", upper_right, 3) self._ufs_upper_right = upper_right
def operations(self, operations): cv.check_type('operations', operations, Iterable, np.ufunc) length = len(self.functions) - 1 cv.check_length('operations', operations, length, length_max=length) self._operations = operations
def entropy_upper_right(self, upper_right): check_type("entropy mesh upper right corner", upper_right, Iterable, Real) check_length("entropy mesh upper right corner", upper_right, 3) self._entropy_upper_right = upper_right