2023-08-05 21:16:42 +01:00
from __future__ import annotations
2020-04-01 13:10:05 -05:00
from abc import ABC , abstractmethod
2024-07-18 12:40:42 -05:00
from collections . abc import Iterable , Sequence
2023-08-05 21:16:42 +01:00
from math import cos , pi
2015-12-18 09:13:41 -06:00
from numbers import Real
2024-05-15 22:49:04 +02:00
from warnings import warn
2015-12-18 09:13:41 -06:00
2023-08-05 21:16:42 +01:00
import lxml . etree as ET
2015-12-18 09:13:41 -06:00
import numpy as np
2024-07-18 12:40:42 -05:00
import openmc
2015-12-18 09:13:41 -06:00
import openmc . checkvalue as cv
2025-08-08 20:47:55 +03:00
from . . _xml import get_elem_list , get_text
2022-12-29 10:39:41 -06:00
from . . mesh import MeshBase
2026-02-21 22:00:36 +02:00
from . univariate import PowerLaw , Uniform , Univariate , delta_function
2015-12-18 09:13:41 -06:00
2020-04-01 13:10:05 -05:00
class UnitSphere ( ABC ) :
2015-12-18 09:13:41 -06:00
""" Distribution of points on the unit sphere.
This abstract class is used for angular distributions , since a direction is
represented as a unit vector ( i . e . , vector on the unit sphere ) .
Parameters
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
reference_uvw : Iterable of float
2015-12-18 09:13:41 -06:00
Direction from which polar angle is measured
Attributes
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
reference_uvw : Iterable of float
2015-12-18 09:13:41 -06:00
Direction from which polar angle is measured
"""
2016-01-15 06:29:41 -06:00
def __init__ ( self , reference_uvw = None ) :
2015-12-18 09:13:41 -06:00
self . _reference_uvw = None
if reference_uvw is not None :
self . reference_uvw = reference_uvw
@property
def reference_uvw ( self ) :
return self . _reference_uvw
@reference_uvw.setter
def reference_uvw ( self , uvw ) :
cv . check_type ( ' reference direction ' , uvw , Iterable , Real )
uvw = np . asarray ( uvw )
2016-01-15 07:09:40 -06:00
self . _reference_uvw = uvw / np . linalg . norm ( uvw )
2015-12-18 09:13:41 -06:00
@abstractmethod
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
2015-12-18 09:13:41 -06:00
return ' '
2019-04-18 08:22:40 -05:00
@classmethod
@abstractmethod
def from_xml_element ( cls , elem ) :
2019-05-22 19:26:15 -06:00
distribution = get_text ( elem , ' type ' )
if distribution == ' mu-phi ' :
return PolarAzimuthal . from_xml_element ( elem )
elif distribution == ' isotropic ' :
return Isotropic . from_xml_element ( elem )
elif distribution == ' monodirectional ' :
return Monodirectional . from_xml_element ( elem )
2019-04-18 08:22:40 -05:00
2015-12-18 09:13:41 -06:00
class PolarAzimuthal ( UnitSphere ) :
""" Angular distribution represented by polar and azimuthal angles
This distribution allows one to specify the distribution of the cosine of
2017-03-15 11:25:24 -04:00
the polar angle and the azimuthal angle independently of one another . The
polar angle is measured relative to the reference angle .
2015-12-18 09:13:41 -06:00
Parameters
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
mu : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of the cosine of the polar angle
2016-04-13 22:17:16 -05:00
phi : openmc . stats . Univariate
2016-01-14 06:46:32 -06:00
Distribution of the azimuthal angle in radians
2016-04-13 22:17:16 -05:00
reference_uvw : Iterable of float
2015-12-18 09:13:41 -06:00
Direction from which polar angle is measured . Defaults to the positive
z - direction .
2025-11-03 09:42:59 +02:00
reference_vwu : Iterable of float
Direction from which azimuthal angle is measured . Defaults to the positive
2026-01-12 10:51:12 -05:00
x - direction .
2015-12-18 09:13:41 -06:00
Attributes
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
mu : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of the cosine of the polar angle
2016-04-13 22:17:16 -05:00
phi : openmc . stats . Univariate
2016-01-14 06:46:32 -06:00
Distribution of the azimuthal angle in radians
2015-12-18 09:13:41 -06:00
"""
2025-11-03 09:42:59 +02:00
def __init__ ( self , mu = None , phi = None , reference_uvw = ( 0. , 0. , 1. ) , reference_vwu = ( 1. , 0. , 0. ) ) :
2017-12-24 16:34:25 +07:00
super ( ) . __init__ ( reference_uvw )
2025-11-03 09:42:59 +02:00
self . reference_vwu = reference_vwu
2015-12-18 09:13:41 -06:00
if mu is not None :
self . mu = mu
else :
2016-01-14 06:46:32 -06:00
self . mu = Uniform ( - 1. , 1. )
2015-12-18 09:13:41 -06:00
if phi is not None :
self . phi = phi
else :
2016-01-14 06:46:32 -06:00
self . phi = Uniform ( 0. , 2 * pi )
2026-01-12 10:51:12 -05:00
2025-11-03 09:42:59 +02:00
@property
def reference_vwu ( self ) :
return self . _reference_vwu
@reference_vwu.setter
def reference_vwu ( self , vwu ) :
cv . check_type ( ' reference v direction ' , vwu , Iterable , Real )
vwu = np . asarray ( vwu )
uvw = self . reference_uvw
2026-01-12 10:51:12 -05:00
cv . check_greater_than ( ' reference v direction must not be parallel to reference u direction ' , np . linalg . norm ( np . cross ( vwu , uvw ) ) , 1e-6 * np . linalg . norm ( vwu ) )
vwu - = vwu . dot ( uvw ) * uvw
2025-11-03 09:42:59 +02:00
cv . check_less_than ( ' reference v direction must be orthogonal to reference u direction ' , np . abs ( vwu . dot ( uvw ) ) , 1e-6 )
self . _reference_vwu = vwu / np . linalg . norm ( vwu )
2015-12-18 09:13:41 -06:00
@property
def mu ( self ) :
return self . _mu
@mu.setter
def mu ( self , mu ) :
cv . check_type ( ' cosine of polar angle ' , mu , Univariate )
self . _mu = mu
2023-06-17 04:34:02 +01:00
@property
def phi ( self ) :
return self . _phi
2015-12-18 09:13:41 -06:00
@phi.setter
def phi ( self , phi ) :
cv . check_type ( ' azimuthal angle ' , phi , Univariate )
self . _phi = phi
2026-01-12 10:51:12 -05:00
def to_xml_element ( self , element_name : str = None ) :
2016-07-28 13:52:42 -05:00
""" Return XML representation of the angular distribution
2026-01-12 10:51:12 -05:00
Parameters
- - - - - - - - - -
element_name : str , optional
XML element name
2016-07-28 13:52:42 -05:00
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2016-07-28 13:52:42 -05:00
XML element containing angular distribution data
"""
2026-01-12 10:51:12 -05:00
if element_name is not None :
element = ET . Element ( element_name )
else :
element = ET . Element ( ' angle ' )
2015-12-18 09:13:41 -06:00
element . set ( " type " , " mu-phi " )
if self . reference_uvw is not None :
element . set ( " reference_uvw " , ' ' . join ( map ( str , self . reference_uvw ) ) )
2025-11-03 09:42:59 +02:00
if self . reference_vwu is not None :
2026-01-12 10:51:12 -05:00
element . set ( " reference_vwu " , ' ' . join ( map ( str , self . reference_vwu ) ) )
2016-07-28 13:52:42 -05:00
element . append ( self . mu . to_xml_element ( ' mu ' ) )
element . append ( self . phi . to_xml_element ( ' phi ' ) )
2015-12-18 09:13:41 -06:00
return element
2019-04-18 08:22:40 -05:00
@classmethod
def from_xml_element ( cls , elem ) :
""" Generate angular distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-04-18 08:22:40 -05:00
XML element
Returns
- - - - - - -
openmc . stats . PolarAzimuthal
Angular distribution generated from XML element
"""
mu_phi = cls ( )
2025-08-08 20:47:55 +03:00
uvw = get_elem_list ( elem , " reference_uvw " , float )
2022-08-30 21:15:58 -05:00
if uvw is not None :
2025-08-08 20:47:55 +03:00
mu_phi . reference_uvw = uvw
2025-11-03 09:42:59 +02:00
vwu = get_elem_list ( elem , " reference_vwu " , float )
if vwu is not None :
2026-01-12 10:51:12 -05:00
mu_phi . reference_vwu = vwu
2019-05-22 19:26:15 -06:00
mu_phi . mu = Univariate . from_xml_element ( elem . find ( ' mu ' ) )
mu_phi . phi = Univariate . from_xml_element ( elem . find ( ' phi ' ) )
2019-04-18 08:22:40 -05:00
return mu_phi
2015-12-18 09:13:41 -06:00
class Isotropic ( UnitSphere ) :
2026-01-12 10:51:12 -05:00
""" Isotropic angular distribution.
Parameters
- - - - - - - - - -
bias : openmc . stats . PolarAzimuthal , optional
Distribution for biased sampling .
Attributes
- - - - - - - - - -
bias : openmc . stats . PolarAzimuthal or None
Distribution for biased sampling
"""
2015-12-18 09:13:41 -06:00
2026-01-12 10:51:12 -05:00
def __init__ ( self , bias : PolarAzimuthal | None = None ) :
2017-12-24 16:34:25 +07:00
super ( ) . __init__ ( )
2026-01-12 10:51:12 -05:00
self . bias = bias
@property
def bias ( self ) :
return self . _bias
@bias.setter
def bias ( self , bias ) :
cv . check_type ( ' Biasing distribution ' , bias , PolarAzimuthal , none_ok = True )
if bias is not None :
if ( bias . mu . bias is not None ) or ( bias . phi . bias is not None ) :
raise RuntimeError ( ' Biasing distributions should not have their own bias. ' )
elif ( bias . mu . support != ( - 1. , 1. )
or not np . all ( np . isclose ( bias . phi . support , ( 0. , 2 * np . pi ) ) ) ) :
raise ValueError ( " Biasing distribution for an isotropic "
" distribution should be supported on "
" mu=(-1.0,1.0) and phi=(0.0,2*pi). " )
self . _bias = bias
2015-12-18 09:13:41 -06:00
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the isotropic distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2016-07-28 13:52:42 -05:00
XML element containing isotropic distribution data
"""
2016-01-15 06:29:41 -06:00
element = ET . Element ( ' angle ' )
2015-12-18 09:13:41 -06:00
element . set ( " type " , " isotropic " )
2026-01-12 10:51:12 -05:00
if self . bias is not None :
bias_dist = self . bias
if ( bias_dist . mu . bias is not None ) or ( bias_dist . phi . bias is not None ) :
raise RuntimeError ( ' Biasing distributions should not have their own bias! ' )
else :
bias_elem = self . bias . to_xml_element ( " bias " )
element . append ( bias_elem )
2015-12-18 09:13:41 -06:00
return element
2019-04-18 08:22:40 -05:00
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-04-18 08:22:40 -05:00
""" Generate isotropic distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-04-18 08:22:40 -05:00
XML element
Returns
- - - - - - -
openmc . stats . Isotropic
Isotropic distribution generated from XML element
"""
2026-01-12 10:51:12 -05:00
bias_elem = elem . find ( ' bias ' )
if bias_elem is not None :
bias_dist = PolarAzimuthal . from_xml_element ( bias_elem )
return cls ( bias = bias_dist )
else :
return cls ( )
2019-04-18 08:22:40 -05:00
2015-12-18 09:13:41 -06:00
class Monodirectional ( UnitSphere ) :
""" Monodirectional angular distribution.
A monodirectional angular distribution is one for which the polar and
azimuthal angles are always the same . It is completely specified by the
reference direction vector .
Parameters
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
reference_uvw : Iterable of float
2015-12-18 09:13:41 -06:00
Direction from which polar angle is measured . Defaults to the positive
x - direction .
"""
2024-07-18 12:40:42 -05:00
def __init__ ( self , reference_uvw : Sequence [ float ] = [ 1. , 0. , 0. ] ) :
2017-12-24 16:34:25 +07:00
super ( ) . __init__ ( reference_uvw )
2015-12-18 09:13:41 -06:00
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the monodirectional distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2016-07-28 13:52:42 -05:00
XML element containing monodirectional distribution data
"""
2016-01-15 06:29:41 -06:00
element = ET . Element ( ' angle ' )
2015-12-18 09:13:41 -06:00
element . set ( " type " , " monodirectional " )
if self . reference_uvw is not None :
element . set ( " reference_uvw " , ' ' . join ( map ( str , self . reference_uvw ) ) )
return element
2019-04-18 08:22:40 -05:00
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-04-18 08:22:40 -05:00
""" Generate monodirectional distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-04-18 08:22:40 -05:00
XML element
Returns
- - - - - - -
openmc . stats . Monodirectional
Monodirectional distribution generated from XML element
"""
monodirectional = cls ( )
2025-08-08 20:47:55 +03:00
uvw = get_elem_list ( elem , " reference_uvw " , float )
2022-08-30 21:15:58 -05:00
if uvw is not None :
2025-08-08 20:47:55 +03:00
monodirectional . reference_uvw = uvw
2019-04-18 08:22:40 -05:00
return monodirectional
2015-12-18 09:13:41 -06:00
2020-04-01 13:10:05 -05:00
class Spatial ( ABC ) :
2015-12-18 09:13:41 -06:00
""" Distribution of locations in three-dimensional Euclidean space.
Classes derived from this abstract class can be used for spatial
distributions of source sites .
"""
@abstractmethod
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
2015-12-18 09:13:41 -06:00
return ' '
2019-04-18 08:22:40 -05:00
@classmethod
@abstractmethod
2023-02-03 20:11:25 -06:00
def from_xml_element ( cls , elem , meshes = None ) :
2019-05-22 19:26:15 -06:00
distribution = get_text ( elem , ' type ' )
if distribution == ' cartesian ' :
return CartesianIndependent . from_xml_element ( elem )
2019-12-31 12:11:49 -05:00
elif distribution == ' cylindrical ' :
return CylindricalIndependent . from_xml_element ( elem )
2019-11-04 17:27:50 -05:00
elif distribution == ' spherical ' :
return SphericalIndependent . from_xml_element ( elem )
2019-05-22 19:26:15 -06:00
elif distribution == ' box ' or distribution == ' fission ' :
return Box . from_xml_element ( elem )
elif distribution == ' point ' :
return Point . from_xml_element ( elem )
2022-12-23 12:10:47 -06:00
elif distribution == ' mesh ' :
2023-02-03 20:11:25 -06:00
return MeshSpatial . from_xml_element ( elem , meshes )
2024-11-13 15:39:41 -06:00
elif distribution == ' cloud ' :
return PointCloud . from_xml_element ( elem )
2019-04-18 08:22:40 -05:00
2015-12-18 09:13:41 -06:00
2016-01-15 06:29:41 -06:00
class CartesianIndependent ( Spatial ) :
2015-12-18 09:13:41 -06:00
""" Spatial distribution with independent x, y, and z distributions.
2019-11-04 17:27:50 -05:00
This distribution allows one to specify coordinates whose x - , y - , and z -
2015-12-18 09:13:41 -06:00
components are sampled independently from one another .
Parameters
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
x : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of x - coordinates
2016-04-13 22:17:16 -05:00
y : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of y - coordinates
2016-04-13 22:17:16 -05:00
z : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of z - coordinates
Attributes
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
x : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of x - coordinates
2016-04-13 22:17:16 -05:00
y : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of y - coordinates
2016-04-13 22:17:16 -05:00
z : openmc . stats . Univariate
2015-12-18 09:13:41 -06:00
Distribution of z - coordinates
"""
2023-08-05 21:16:42 +01:00
def __init__ (
self ,
x : openmc . stats . Univariate ,
y : openmc . stats . Univariate ,
z : openmc . stats . Univariate
) :
2015-12-18 09:13:41 -06:00
self . x = x
self . y = y
self . z = z
@property
def x ( self ) :
return self . _x
@x.setter
def x ( self , x ) :
cv . check_type ( ' x coordinate ' , x , Univariate )
self . _x = x
2023-06-17 04:34:02 +01:00
@property
def y ( self ) :
return self . _y
2015-12-18 09:13:41 -06:00
@y.setter
def y ( self , y ) :
cv . check_type ( ' y coordinate ' , y , Univariate )
self . _y = y
2023-06-17 04:34:02 +01:00
@property
def z ( self ) :
return self . _z
2016-01-13 13:16:18 -06:00
@z.setter
2015-12-18 09:13:41 -06:00
def z ( self , z ) :
cv . check_type ( ' z coordinate ' , z , Univariate )
self . _z = z
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the spatial distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2016-07-28 13:52:42 -05:00
XML element containing spatial distribution data
"""
2016-01-15 06:29:41 -06:00
element = ET . Element ( ' space ' )
2016-01-15 06:38:30 -06:00
element . set ( ' type ' , ' cartesian ' )
2016-07-28 13:52:42 -05:00
element . append ( self . x . to_xml_element ( ' x ' ) )
element . append ( self . y . to_xml_element ( ' y ' ) )
element . append ( self . z . to_xml_element ( ' z ' ) )
2015-12-18 09:13:41 -06:00
return element
2019-04-18 08:22:40 -05:00
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-04-18 08:22:40 -05:00
""" Generate spatial distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-04-18 08:22:40 -05:00
XML element
Returns
- - - - - - -
openmc . stats . CartesianIndependent
Spatial distribution generated from XML element
"""
2019-05-22 19:26:15 -06:00
x = Univariate . from_xml_element ( elem . find ( ' x ' ) )
y = Univariate . from_xml_element ( elem . find ( ' y ' ) )
z = Univariate . from_xml_element ( elem . find ( ' z ' ) )
2019-04-18 08:22:40 -05:00
return cls ( x , y , z )
2015-12-18 09:13:41 -06:00
2019-11-04 17:27:50 -05:00
class SphericalIndependent ( Spatial ) :
2019-12-31 12:11:49 -05:00
r """ Spatial distribution represented in spherical coordinates.
2019-11-04 17:27:50 -05:00
This distribution allows one to specify coordinates whose : math : ` r ` ,
2022-05-16 14:39:28 +02:00
: math : ` \theta ` , and : math : ` \phi ` components are sampled independently
2022-05-09 20:23:18 +02:00
from one another and centered on the coordinates ( x0 , y0 , z0 ) .
2019-11-04 17:27:50 -05:00
2022-08-16 16:19:55 -05:00
. . versionadded : : 0.12
. . versionchanged : : 0.13 .1
Accepts ` ` cos_theta ` ` instead of ` ` theta ` `
2020-04-10 21:52:43 -05:00
2019-11-04 17:27:50 -05:00
Parameters
- - - - - - - - - -
r : openmc . stats . Univariate
2019-12-31 12:11:49 -05:00
Distribution of r - coordinates in a reference frame specified by
the origin parameter
2022-05-09 20:23:18 +02:00
cos_theta : openmc . stats . Univariate
2022-05-10 09:17:23 +02:00
Distribution of the cosine of the theta - coordinates ( angle relative to
2022-05-09 20:23:18 +02:00
the z - axis ) in a reference frame specified by the origin parameter
2019-11-04 17:27:50 -05:00
phi : openmc . stats . Univariate
2019-12-31 12:11:49 -05:00
Distribution of phi - coordinates ( azimuthal angle ) in a reference frame
specified by the origin parameter
2019-11-04 17:27:50 -05:00
origin : Iterable of float , optional
2019-12-31 12:11:49 -05:00
coordinates ( x0 , y0 , z0 ) of the center of the spherical reference frame
for the source . Defaults to ( 0.0 , 0.0 , 0.0 )
2019-11-04 17:27:50 -05:00
Attributes
- - - - - - - - - -
r : openmc . stats . Univariate
2019-12-31 12:11:49 -05:00
Distribution of r - coordinates in the local reference frame
2022-05-09 20:03:28 +02:00
cos_theta : openmc . stats . Univariate
2022-05-10 09:17:40 +02:00
Distribution of the cosine of the theta - coordinates ( angle relative to
2022-05-09 20:03:28 +02:00
the z - axis ) in the local reference frame
2019-11-04 17:27:50 -05:00
phi : openmc . stats . Univariate
2019-12-31 12:11:49 -05:00
Distribution of phi - coordinates ( azimuthal angle ) in the local
reference frame
2019-11-04 17:27:50 -05:00
origin : Iterable of float , optional
2019-12-31 12:11:49 -05:00
coordinates ( x0 , y0 , z0 ) of the center of the spherical reference
frame . Defaults to ( 0.0 , 0.0 , 0.0 )
2019-11-04 17:27:50 -05:00
"""
2022-05-09 20:03:28 +02:00
def __init__ ( self , r , cos_theta , phi , origin = ( 0.0 , 0.0 , 0.0 ) ) :
2019-11-04 17:27:50 -05:00
self . r = r
2022-05-09 20:03:28 +02:00
self . cos_theta = cos_theta
2019-11-04 17:27:50 -05:00
self . phi = phi
self . origin = origin
@property
def r ( self ) :
return self . _r
@r.setter
def r ( self , r ) :
cv . check_type ( ' r coordinate ' , r , Univariate )
self . _r = r
2023-06-17 04:34:02 +01:00
@property
def cos_theta ( self ) :
return self . _cos_theta
2022-05-09 20:03:28 +02:00
@cos_theta.setter
def cos_theta ( self , cos_theta ) :
cv . check_type ( ' cos_theta coordinate ' , cos_theta , Univariate )
self . _cos_theta = cos_theta
2019-11-04 17:27:50 -05:00
2023-06-17 04:34:02 +01:00
@property
def phi ( self ) :
return self . _phi
2019-11-04 17:27:50 -05:00
@phi.setter
def phi ( self , phi ) :
cv . check_type ( ' phi coordinate ' , phi , Univariate )
self . _phi = phi
2023-06-17 04:34:02 +01:00
@property
def origin ( self ) :
return self . _origin
2019-11-04 17:27:50 -05:00
@origin.setter
def origin ( self , origin ) :
cv . check_type ( ' origin coordinates ' , origin , Iterable , Real )
origin = np . asarray ( origin )
self . _origin = origin
def to_xml_element ( self ) :
""" Return XML representation of the spatial distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2019-11-04 17:27:50 -05:00
XML element containing spatial distribution data
"""
element = ET . Element ( ' space ' )
element . set ( ' type ' , ' spherical ' )
element . append ( self . r . to_xml_element ( ' r ' ) )
2022-05-09 20:03:28 +02:00
element . append ( self . cos_theta . to_xml_element ( ' cos_theta ' ) )
2019-11-04 17:27:50 -05:00
element . append ( self . phi . to_xml_element ( ' phi ' ) )
element . set ( " origin " , ' ' . join ( map ( str , self . origin ) ) )
return element
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-11-04 17:27:50 -05:00
""" Generate spatial distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-11-04 17:27:50 -05:00
XML element
Returns
- - - - - - -
openmc . stats . SphericalIndependent
Spatial distribution generated from XML element
"""
r = Univariate . from_xml_element ( elem . find ( ' r ' ) )
2022-05-09 20:23:18 +02:00
cos_theta = Univariate . from_xml_element ( elem . find ( ' cos_theta ' ) )
2019-11-04 17:27:50 -05:00
phi = Univariate . from_xml_element ( elem . find ( ' phi ' ) )
2025-08-08 20:47:55 +03:00
origin = get_elem_list ( elem , " origin " , float )
2022-05-09 20:23:18 +02:00
return cls ( r , cos_theta , phi , origin = origin )
2019-11-04 17:27:50 -05:00
2022-01-20 10:33:53 -06:00
2019-12-31 12:11:49 -05:00
class CylindricalIndependent ( Spatial ) :
2021-04-26 09:22:45 -05:00
r """ Spatial distribution represented in cylindrical coordinates.
2019-12-31 12:11:49 -05:00
This distribution allows one to specify coordinates whose : math : ` r ` ,
: math : ` \phi ` , and : math : ` z ` components are sampled independently from
one another and in a reference frame whose origin is specified by the
coordinates ( x0 , y0 , z0 ) .
2020-04-10 21:52:43 -05:00
. . versionadded : : 0.12
2019-12-31 12:11:49 -05:00
Parameters
- - - - - - - - - -
r : openmc . stats . Univariate
Distribution of r - coordinates in a reference frame specified by the
origin parameter
phi : openmc . stats . Univariate
Distribution of phi - coordinates ( azimuthal angle ) in a reference frame
specified by the origin parameter
z : openmc . stats . Univariate
Distribution of z - coordinates in a reference frame specified by the
origin parameter
origin : Iterable of float , optional
coordinates ( x0 , y0 , z0 ) of the center of the cylindrical reference
frame . Defaults to ( 0.0 , 0.0 , 0.0 )
2026-02-21 22:00:36 +02:00
r_dir : Iterable of float , optional
Unit vector of the cylinder r axis at phi = 0.
z_dir : Iterable of float , optional
Unit vector of the cylinder z axis direction .
2019-12-31 12:11:49 -05:00
Attributes
- - - - - - - - - -
r : openmc . stats . Univariate
Distribution of r - coordinates in the local reference frame
phi : openmc . stats . Univariate
Distribution of phi - coordinates ( azimuthal angle ) in the local
reference frame
z : openmc . stats . Univariate
Distribution of z - coordinates in the local reference frame
origin : Iterable of float , optional
coordinates ( x0 , y0 , z0 ) of the center of the cylindrical reference
frame . Defaults to ( 0.0 , 0.0 , 0.0 )
2026-02-21 22:00:36 +02:00
r_dir : Iterable of float , optional
Unit vector of the cylinder r axis at phi = 0.
z_dir : Iterable of float , optional
Unit vector of the cylinder z axis direction .
2019-12-31 12:11:49 -05:00
"""
2026-02-21 22:00:36 +02:00
def __init__ ( self , r , phi , z , origin = ( 0.0 , 0.0 , 0.0 ) , r_dir = ( 1.0 , 0.0 , 0.0 ) ,
z_dir = ( 0.0 , 0.0 , 1.0 ) ) :
2019-12-31 12:11:49 -05:00
self . r = r
self . phi = phi
self . z = z
self . origin = origin
2026-02-21 22:00:36 +02:00
self . z_dir = z_dir
self . r_dir = r_dir
2019-12-31 12:11:49 -05:00
@property
def r ( self ) :
return self . _r
@r.setter
def r ( self , r ) :
cv . check_type ( ' r coordinate ' , r , Univariate )
self . _r = r
2023-06-17 04:34:02 +01:00
@property
def phi ( self ) :
return self . _phi
2019-12-31 12:11:49 -05:00
@phi.setter
def phi ( self , phi ) :
cv . check_type ( ' phi coordinate ' , phi , Univariate )
self . _phi = phi
2023-06-17 04:34:02 +01:00
@property
def z ( self ) :
return self . _z
2019-12-31 12:11:49 -05:00
@z.setter
def z ( self , z ) :
cv . check_type ( ' z coordinate ' , z , Univariate )
self . _z = z
2023-06-17 04:34:02 +01:00
@property
def origin ( self ) :
return self . _origin
2019-12-31 12:11:49 -05:00
@origin.setter
def origin ( self , origin ) :
cv . check_type ( ' origin coordinates ' , origin , Iterable , Real )
origin = np . asarray ( origin )
self . _origin = origin
2026-02-21 22:00:36 +02:00
@property
def z_dir ( self ) :
return self . _z_dir
@z_dir.setter
def z_dir ( self , z_dir ) :
cv . check_type ( ' z-axis direction ' , z_dir , Iterable , Real )
z_dir = np . array ( z_dir )
norm = np . linalg . norm ( z_dir )
cv . check_greater_than ( ' z-axis direction magnitude ' , norm , 0.0 )
z_dir / = norm
self . _z_dir = z_dir
@property
def r_dir ( self ) :
return self . _r_dir
@r_dir.setter
def r_dir ( self , r_dir ) :
cv . check_type ( ' r-axis direction ' , r_dir , Iterable , Real )
r_dir = np . array ( r_dir )
r_dir - = np . dot ( r_dir , self . z_dir ) * self . z_dir
norm = np . linalg . norm ( r_dir )
cv . check_greater_than ( ' r-axis direction magnitude ' , norm , 0.0 )
r_dir / = norm
self . _r_dir = r_dir
2019-12-31 12:11:49 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the spatial distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2019-12-31 12:11:49 -05:00
XML element containing spatial distribution data
"""
element = ET . Element ( ' space ' )
element . set ( ' type ' , ' cylindrical ' )
element . append ( self . r . to_xml_element ( ' r ' ) )
element . append ( self . phi . to_xml_element ( ' phi ' ) )
element . append ( self . z . to_xml_element ( ' z ' ) )
2026-02-21 22:00:36 +02:00
if not np . allclose ( self . origin , [ 0. , 0. , 0. ] ) :
element . set ( " origin " , ' ' . join ( map ( str , self . origin ) ) )
if not np . allclose ( self . r_dir , [ 1. , 0. , 0. ] ) :
element . set ( " r_dir " , ' ' . join ( map ( str , self . r_dir ) ) )
if not np . allclose ( self . z_dir , [ 0. , 0. , 1. ] ) :
element . set ( " z_dir " , ' ' . join ( map ( str , self . z_dir ) ) )
2019-12-31 12:11:49 -05:00
return element
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-12-31 12:11:49 -05:00
""" Generate spatial distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-12-31 12:11:49 -05:00
XML element
Returns
- - - - - - -
openmc . stats . CylindricalIndependent
Spatial distribution generated from XML element
"""
r = Univariate . from_xml_element ( elem . find ( ' r ' ) )
phi = Univariate . from_xml_element ( elem . find ( ' phi ' ) )
z = Univariate . from_xml_element ( elem . find ( ' z ' ) )
2026-02-21 22:00:36 +02:00
origin = get_elem_list ( elem , " origin " , float ) or [ 0.0 , 0.0 , 0.0 ]
r_dir = get_elem_list ( elem , " r_dir " , float ) or [ 1.0 , 0.0 , 0.0 ]
z_dir = get_elem_list ( elem , " z_dir " , float ) or [ 0.0 , 0.0 , 1.0 ]
return cls ( r , phi , z , origin = origin , r_dir = r_dir , z_dir = z_dir )
2019-12-31 12:11:49 -05:00
2023-01-12 23:13:09 -06:00
2022-08-10 14:42:57 -05:00
class MeshSpatial ( Spatial ) :
2022-07-06 08:59:12 -05:00
""" Spatial distribution for a mesh.
2023-01-12 23:13:09 -06:00
This distribution specifies a mesh to sample over with source strengths
specified for each mesh element .
2022-07-06 08:59:12 -05:00
2022-12-29 08:15:45 -06:00
. . versionadded : : 0.13 .3
2022-07-06 08:59:12 -05:00
Parameters
- - - - - - - - - -
mesh : openmc . MeshBase
2023-01-12 23:13:09 -06:00
The mesh instance used for sampling
strengths : iterable of float , optional
An iterable of values that represents the weights of each element . If no
2023-01-03 10:35:44 -06:00
source strengths are specified , they will be equal for all mesh
elements .
2022-12-23 12:10:47 -06:00
volume_normalized : bool , optional
2023-01-03 10:35:44 -06:00
Whether or not the strengths will be multiplied by element volumes at
runtime . Default is True .
2026-01-12 10:51:12 -05:00
bias : iterable of float , optional
An iterable of values giving the selection weights assigned to each
element during biased sampling .
2022-07-06 08:59:12 -05:00
Attributes
- - - - - - - - - -
mesh : openmc . MeshBase
2023-01-12 23:13:09 -06:00
The mesh instance used for sampling
strengths : numpy . ndarray or None
An array of source strengths for each mesh element
2022-12-23 12:10:47 -06:00
volume_normalized : bool
2023-01-03 10:35:44 -06:00
Whether or not the strengths will be multiplied by element volumes at
runtime .
2026-01-12 10:51:12 -05:00
bias : numpy . ndarray or None
Distribution for biased sampling
2022-07-06 08:59:12 -05:00
"""
2026-01-12 10:51:12 -05:00
def __init__ ( self , mesh , strengths = None , volume_normalized = True ,
bias : Sequence [ float ] | None = None ) :
2022-12-23 12:10:47 -06:00
self . mesh = mesh
2022-08-08 11:21:09 -05:00
self . strengths = strengths
self . volume_normalized = volume_normalized
2026-01-12 10:51:12 -05:00
self . bias = bias
2022-07-06 08:59:12 -05:00
@property
def mesh ( self ) :
return self . _mesh
@mesh.setter
def mesh ( self , mesh ) :
2023-01-12 23:13:09 -06:00
if mesh is not None :
cv . check_type ( ' mesh instance ' , mesh , MeshBase )
2022-07-06 08:59:12 -05:00
self . _mesh = mesh
@property
2022-08-08 11:21:09 -05:00
def volume_normalized ( self ) :
return self . _volume_normalized
2022-07-06 08:59:12 -05:00
2022-08-08 11:21:09 -05:00
@volume_normalized.setter
def volume_normalized ( self , volume_normalized ) :
2023-01-03 10:35:44 -06:00
cv . check_type ( ' Multiply strengths by element volumes ' , volume_normalized , bool )
2022-08-08 11:21:09 -05:00
self . _volume_normalized = volume_normalized
2022-07-06 08:59:12 -05:00
@property
2022-08-08 11:21:09 -05:00
def strengths ( self ) :
return self . _strengths
@strengths.setter
def strengths ( self , given_strengths ) :
if given_strengths is not None :
cv . check_type ( ' strengths array passed in ' , given_strengths , Iterable , Real )
2023-01-12 23:13:09 -06:00
self . _strengths = np . asarray ( given_strengths , dtype = float ) . flatten ( )
2022-07-06 08:59:12 -05:00
else :
2022-08-08 11:21:09 -05:00
self . _strengths = None
2022-07-06 08:59:12 -05:00
2026-01-12 10:51:12 -05:00
@property
def bias ( self ) :
return self . _bias
@bias.setter
def bias ( self , given_bias ) :
if given_bias is not None :
cv . check_type ( ' Biasing strengths array ' , given_bias , Iterable , Real )
bias_array = np . asarray ( given_bias , dtype = float ) . flatten ( )
if bias_array . size != self . strengths . size :
raise ValueError (
' Bias strengths array must have same size as strengths array. ' )
else :
self . _bias = bias_array
else :
self . _bias = None
2022-07-06 08:59:12 -05:00
@property
2022-08-08 11:21:09 -05:00
def num_strength_bins ( self ) :
2023-01-12 23:13:09 -06:00
if self . strengths is None :
2022-08-08 11:21:09 -05:00
raise ValueError ( ' Strengths are not set ' )
return self . strengths . size
2022-12-23 12:10:47 -06:00
2022-07-06 08:59:12 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the spatial distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2022-07-06 08:59:12 -05:00
XML element containing spatial distribution data
"""
element = ET . Element ( ' space ' )
2023-12-02 11:35:23 -06:00
2022-07-06 08:59:12 -05:00
element . set ( ' type ' , ' mesh ' )
element . set ( " mesh_id " , str ( self . mesh . id ) )
2022-08-08 11:21:09 -05:00
element . set ( " volume_normalized " , str ( self . volume_normalized ) )
2022-07-06 08:59:12 -05:00
2022-08-08 11:21:09 -05:00
if self . strengths is not None :
subelement = ET . SubElement ( element , ' strengths ' )
subelement . text = ' ' . join ( str ( e ) for e in self . strengths )
2022-07-06 08:59:12 -05:00
2026-01-12 10:51:12 -05:00
if self . bias is not None :
Univariate . _append_array_bias_to_xml ( self , element )
2022-07-06 08:59:12 -05:00
return element
@classmethod
2023-02-03 20:11:25 -06:00
def from_xml_element ( cls , elem , meshes ) :
2022-07-06 08:59:12 -05:00
""" Generate spatial distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2022-07-06 08:59:12 -05:00
XML element
2023-02-03 20:11:25 -06:00
meshes : dict
A dictionary with mesh IDs as keys and openmc . MeshBase instances as
values
2022-07-06 08:59:12 -05:00
Returns
- - - - - - -
2022-08-10 14:42:57 -05:00
openmc . stats . MeshSpatial
2022-07-06 08:59:12 -05:00
Spatial distribution generated from XML element
"""
2025-08-08 20:47:55 +03:00
mesh_id = int ( get_text ( elem , " mesh_id " ) )
2022-12-23 12:10:47 -06:00
# check if this mesh has been read in from another location already
2023-02-03 20:11:25 -06:00
if mesh_id not in meshes :
2023-12-13 08:41:51 -06:00
raise ValueError ( f ' Could not locate mesh with ID " { mesh_id } " ' )
2022-12-23 12:10:47 -06:00
2022-08-08 11:21:09 -05:00
volume_normalized = get_text ( elem , ' volume_normalized ' ) . lower ( ) == ' true '
2025-08-08 20:47:55 +03:00
strengths = get_elem_list ( elem , ' strengths ' , float )
2026-01-12 10:51:12 -05:00
bias_strengths = Univariate . _read_array_bias_from_xml ( elem )
return cls ( meshes [ mesh_id ] , strengths , volume_normalized , bias = bias_strengths )
2022-07-06 08:59:12 -05:00
2019-11-04 17:27:50 -05:00
2024-11-13 15:39:41 -06:00
class PointCloud ( Spatial ) :
""" Spatial distribution from a point cloud.
This distribution specifies a discrete list of points , with corresponding
relative probabilities .
. . versionadded : : 0.15 .1
Parameters
- - - - - - - - - -
positions : iterable of 3 - tuples
The points in space to be sampled
strengths : iterable of float , optional
An iterable of values that represents the relative probabilty of each
point .
2026-01-12 10:51:12 -05:00
bias : iterable of float , optional
An iterable of values representing the relative probability of each
point under biased sampling .
2024-11-13 15:39:41 -06:00
Attributes
- - - - - - - - - -
positions : numpy . ndarray
The points in space to be sampled with shape ( N , 3 )
strengths : numpy . ndarray or None
An array of relative probabilities for each mesh point
2026-01-12 10:51:12 -05:00
bias : numpy . ndarray or None
An array of relative probabilities for biased sampling of mesh points
2024-11-13 15:39:41 -06:00
"""
def __init__ (
self ,
positions : Sequence [ Sequence [ float ] ] ,
2026-01-12 10:51:12 -05:00
strengths : Sequence [ float ] | None = None ,
bias : Sequence [ float ] | None = None
2024-11-13 15:39:41 -06:00
) :
self . positions = positions
self . strengths = strengths
2026-01-12 10:51:12 -05:00
self . bias = bias
2024-11-13 15:39:41 -06:00
@property
def positions ( self ) - > np . ndarray :
return self . _positions
@positions.setter
def positions ( self , positions ) :
positions = np . array ( positions , dtype = float )
if positions . ndim != 2 :
raise ValueError ( ' positions must be a 2D array ' )
elif positions . shape [ 1 ] != 3 :
raise ValueError ( ' Each position must have 3 values ' )
self . _positions = positions
@property
def strengths ( self ) - > np . ndarray :
return self . _strengths
@strengths.setter
def strengths ( self , strengths ) :
if strengths is not None :
strengths = np . array ( strengths , dtype = float )
if strengths . ndim != 1 :
raise ValueError ( ' strengths must be a 1D array ' )
elif strengths . size != self . positions . shape [ 0 ] :
raise ValueError ( ' strengths must have the same length as positions ' )
self . _strengths = strengths
2026-01-12 10:51:12 -05:00
@property
def bias ( self ) :
return self . _bias
@bias.setter
def bias ( self , given_bias ) :
if given_bias is not None :
cv . check_type ( ' Biasing strengths array ' , given_bias , Iterable , Real )
bias_array = np . asarray ( given_bias , dtype = float ) . flatten ( )
if bias_array . size != self . strengths . size :
raise ValueError (
' Bias strengths array must have same size as strengths array. ' )
else :
self . _bias = bias_array
else :
self . _bias = None
2024-11-13 15:39:41 -06:00
@property
def num_strength_bins ( self ) - > int :
if self . strengths is None :
raise ValueError ( ' Strengths are not set ' )
return self . strengths . size
def to_xml_element ( self ) - > ET . Element :
""" Return XML representation of the spatial distribution
Returns
- - - - - - -
element : lxml . etree . _Element
XML element containing spatial distribution data
"""
element = ET . Element ( ' space ' )
element . set ( ' type ' , ' cloud ' )
subelement = ET . SubElement ( element , ' coords ' )
subelement . text = ' ' . join ( str ( e ) for e in self . positions . flatten ( ) )
if self . strengths is not None :
subelement = ET . SubElement ( element , ' strengths ' )
subelement . text = ' ' . join ( str ( e ) for e in self . strengths )
2026-01-12 10:51:12 -05:00
if self . bias is not None :
Univariate . _append_array_bias_to_xml ( self , element )
2024-11-13 15:39:41 -06:00
return element
@classmethod
def from_xml_element ( cls , elem : ET . Element ) - > PointCloud :
""" Generate spatial distribution from an XML element
Parameters
- - - - - - - - - -
elem : lxml . etree . _Element
XML element
Returns
- - - - - - -
openmc . stats . PointCloud
Spatial distribution generated from XML element
"""
2025-08-08 20:47:55 +03:00
coord_data = get_elem_list ( elem , ' coords ' , float )
positions = np . array ( coord_data ) . reshape ( ( - 1 , 3 ) )
2024-11-13 15:39:41 -06:00
2025-08-08 20:47:55 +03:00
strengths = get_elem_list ( elem , ' strengths ' , float )
2026-01-12 10:51:12 -05:00
bias_strengths = Univariate . _read_array_bias_from_xml ( elem )
return cls ( positions , strengths , bias = bias_strengths )
2024-11-13 15:39:41 -06:00
2016-01-15 06:29:41 -06:00
class Box ( Spatial ) :
2015-12-18 09:13:41 -06:00
""" Uniform distribution of coordinates in a rectangular cuboid.
Parameters
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
lower_left : Iterable of float
2015-12-18 09:13:41 -06:00
Lower - left coordinates of cuboid
2016-04-13 22:17:16 -05:00
upper_right : Iterable of float
2015-12-18 09:13:41 -06:00
Upper - right coordinates of cuboid
only_fissionable : bool , optional
Whether spatial sites should only be accepted if they occur in
fissionable materials
2024-06-21 20:28:56 -05:00
. . deprecated : : 0.15 .0
2024-05-15 22:49:04 +02:00
Use the ` constraints ` argument when defining a source object instead .
2015-12-18 09:13:41 -06:00
Attributes
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
lower_left : Iterable of float
2015-12-18 09:13:41 -06:00
Lower - left coordinates of cuboid
2016-04-13 22:17:16 -05:00
upper_right : Iterable of float
2015-12-18 09:13:41 -06:00
Upper - right coordinates of cuboid
only_fissionable : bool , optional
Whether spatial sites should only be accepted if they occur in
fissionable materials
2024-06-21 20:28:56 -05:00
. . deprecated : : 0.15 .0
2024-05-15 22:49:04 +02:00
Use the ` constraints ` argument when defining a source object instead .
2015-12-18 09:13:41 -06:00
"""
2023-08-05 21:16:42 +01:00
def __init__ (
self ,
2024-07-18 12:40:42 -05:00
lower_left : Sequence [ float ] ,
upper_right : Sequence [ float ] ,
2023-08-05 21:16:42 +01:00
only_fissionable : bool = False
) :
2015-12-18 09:13:41 -06:00
self . lower_left = lower_left
self . upper_right = upper_right
self . only_fissionable = only_fissionable
@property
def lower_left ( self ) :
return self . _lower_left
@lower_left.setter
def lower_left ( self , lower_left ) :
cv . check_type ( ' lower left coordinate ' , lower_left , Iterable , Real )
cv . check_length ( ' lower left coordinate ' , lower_left , 3 )
self . _lower_left = lower_left
2023-06-17 04:34:02 +01:00
@property
def upper_right ( self ) :
return self . _upper_right
2015-12-18 09:13:41 -06:00
@upper_right.setter
def upper_right ( self , upper_right ) :
cv . check_type ( ' upper right coordinate ' , upper_right , Iterable , Real )
cv . check_length ( ' upper right coordinate ' , upper_right , 3 )
self . _upper_right = upper_right
2023-06-17 04:34:02 +01:00
@property
def only_fissionable ( self ) :
return self . _only_fissionable
2015-12-18 09:13:41 -06:00
@only_fissionable.setter
def only_fissionable ( self , only_fissionable ) :
cv . check_type ( ' only fissionable ' , only_fissionable , bool )
self . _only_fissionable = only_fissionable
2024-05-15 22:49:04 +02:00
if only_fissionable :
warn ( " The ' only_fissionable ' has been deprecated. Use the "
" ' constraints ' argument when defining a source instead. " ,
FutureWarning )
2015-12-18 09:13:41 -06:00
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the box distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2016-07-28 13:52:42 -05:00
XML element containing box distribution data
"""
2016-01-15 06:29:41 -06:00
element = ET . Element ( ' space ' )
2015-12-18 09:13:41 -06:00
if self . only_fissionable :
element . set ( " type " , " fission " )
else :
element . set ( " type " , " box " )
params = ET . SubElement ( element , " parameters " )
params . text = ' ' . join ( map ( str , self . lower_left ) ) + ' ' + \
' ' . join ( map ( str , self . upper_right ) )
return element
2019-04-18 08:22:40 -05:00
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-04-18 08:22:40 -05:00
""" Generate box distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-04-18 08:22:40 -05:00
XML element
Returns
- - - - - - -
openmc . stats . Box
Box distribution generated from XML element
"""
2019-04-25 20:07:53 -05:00
only_fissionable = get_text ( elem , ' type ' ) == ' fission '
2025-08-08 20:47:55 +03:00
params = get_elem_list ( elem , " parameters " , float )
2019-04-18 08:22:40 -05:00
lower_left = params [ : len ( params ) / / 2 ]
2019-04-25 20:07:53 -05:00
upper_right = params [ len ( params ) / / 2 : ]
2019-04-18 08:22:40 -05:00
return cls ( lower_left , upper_right , only_fissionable )
2015-12-18 09:13:41 -06:00
2016-01-15 06:29:41 -06:00
class Point ( Spatial ) :
2015-12-18 09:13:41 -06:00
""" Delta function in three dimensions.
This spatial distribution can be used for a point source where sites are
emitted at a specific location given by its Cartesian coordinates .
Parameters
- - - - - - - - - -
2016-05-10 10:37:07 -05:00
xyz : Iterable of float , optional
Cartesian coordinates of location . Defaults to ( 0. , 0. , 0. ) .
2015-12-18 09:13:41 -06:00
Attributes
- - - - - - - - - -
2016-04-13 22:17:16 -05:00
xyz : Iterable of float
2015-12-18 09:13:41 -06:00
Cartesian coordinates of location
"""
2024-07-18 12:40:42 -05:00
def __init__ ( self , xyz : Sequence [ float ] = ( 0. , 0. , 0. ) ) :
2015-12-18 09:13:41 -06:00
self . xyz = xyz
@property
def xyz ( self ) :
return self . _xyz
@xyz.setter
def xyz ( self , xyz ) :
cv . check_type ( ' coordinate ' , xyz , Iterable , Real )
cv . check_length ( ' coordinate ' , xyz , 3 )
self . _xyz = xyz
2016-07-28 13:52:42 -05:00
def to_xml_element ( self ) :
""" Return XML representation of the point distribution
Returns
- - - - - - -
2023-05-09 11:41:04 -04:00
element : lxml . etree . _Element
2016-07-28 13:52:42 -05:00
XML element containing point distribution location
"""
2016-01-15 06:29:41 -06:00
element = ET . Element ( ' space ' )
2015-12-18 09:13:41 -06:00
element . set ( " type " , " point " )
params = ET . SubElement ( element , " parameters " )
params . text = ' ' . join ( map ( str , self . xyz ) )
return element
2019-04-18 08:22:40 -05:00
@classmethod
2023-08-05 21:16:42 +01:00
def from_xml_element ( cls , elem : ET . Element ) :
2019-04-18 08:22:40 -05:00
""" Generate point distribution from an XML element
Parameters
- - - - - - - - - -
2023-05-09 11:41:04 -04:00
elem : lxml . etree . _Element
2019-04-18 08:22:40 -05:00
XML element
Returns
- - - - - - -
openmc . stats . Point
Point distribution generated from XML element
"""
2025-08-08 20:47:55 +03:00
xyz = get_elem_list ( elem , " parameters " , float )
2019-04-18 08:22:40 -05:00
return cls ( xyz )
2022-05-10 15:40:37 +02:00
2023-08-05 21:16:42 +01:00
def spherical_uniform (
r_outer : float ,
r_inner : float = 0.0 ,
2024-07-18 12:40:42 -05:00
thetas : Sequence [ float ] = ( 0. , pi ) ,
phis : Sequence [ float ] = ( 0. , 2 * pi ) ,
origin : Sequence [ float ] = ( 0. , 0. , 0. )
2023-08-05 21:16:42 +01:00
) :
2022-05-14 09:08:54 +02:00
""" Return a uniform spatial distribution over a spherical shell.
2022-05-10 15:40:37 +02:00
2022-05-14 09:08:54 +02:00
This function provides a uniform spatial distribution over a spherical
shell between ` r_inner ` and ` r_outer ` . Optionally , the range of angles
can be restricted by the ` thetas ` and ` phis ` arguments .
2022-05-10 15:40:37 +02:00
2022-08-16 16:19:55 -05:00
. . versionadded : : 0.13 .1
2022-05-10 15:40:37 +02:00
Parameters
- - - - - - - - - -
2022-05-14 09:09:21 +02:00
r_outer : float
Outer radius of the spherical shell in [ cm ]
2023-08-05 21:16:42 +01:00
r_inner : float
2022-05-14 09:09:21 +02:00
Inner radius of the spherical shell in [ cm ]
2023-08-05 21:16:42 +01:00
thetas : iterable of float
2022-05-14 09:09:21 +02:00
Starting and ending theta coordinates ( angle relative to
the z - axis ) in radius in a reference frame centered at ` origin `
2023-08-05 21:16:42 +01:00
phis : iterable of float
2022-05-14 09:09:21 +02:00
Starting and ending phi coordinates ( azimuthal angle ) in
radians in a reference frame centered at ` origin `
2023-08-05 21:16:42 +01:00
origin : iterable of float
2022-05-14 09:09:21 +02:00
Coordinates ( x0 , y0 , z0 ) of the center of the spherical
reference frame for the distribution .
Returns
- - - - - - -
openmc . stats . SphericalIndependent
Uniform distribution over the spherical shell
2022-05-10 15:40:37 +02:00
"""
2022-05-13 21:14:44 +02:00
r_dist = PowerLaw ( r_inner , r_outer , 2 )
2022-05-16 14:38:46 +02:00
cos_thetas_dist = Uniform ( cos ( thetas [ 1 ] ) , cos ( thetas [ 0 ] ) )
2022-05-13 21:14:44 +02:00
phis_dist = Uniform ( phis [ 0 ] , phis [ 1 ] )
2022-05-10 15:40:37 +02:00
2022-05-13 21:14:44 +02:00
return SphericalIndependent ( r_dist , cos_thetas_dist , phis_dist , origin )
2026-02-21 22:00:36 +02:00
def cylindrical_uniform (
r_outer : float ,
height : float ,
r_inner : float = 0.0 ,
phis : Sequence [ float ] = ( 0. , 2 * pi ) ,
* * kwargs ,
) :
""" Return a uniform spatial distribution over a cylindrical shell.
This function provides a uniform spatial distribution over a cylindrical
shell between ` r_inner ` and ` r_outer ` . When ` height ` is zero , a delta
function is used for the z - distribution , giving a uniform distribution over
a flat ring ( annulus ) at z = 0 in the local coordinate frame . Optionally , the
range of angles can be restricted by the ` phis ` argument .
. . versionadded : : 0.15 .4
Parameters
- - - - - - - - - -
r_outer : float
Outer radius of the cylindrical shell in [ cm ]
height : float
Height of the cylindrical shell in [ cm ] . When 0 , the distribution is a
flat ring at z = 0 in the local frame .
r_inner : float
Inner radius of the cylindrical shell in [ cm ]
phis : iterable of float
Starting and ending phi coordinates ( azimuthal angle ) in radians in a
reference frame centered at ` origin ` .
* * kwargs
Keyword arguments passed directly to
: class : ` ~ openmc . stats . CylindricalIndependent ` ( e . g . , ` ` origin ` ` ,
` ` r_dir ` ` , ` ` z_dir ` ` ) .
Returns
- - - - - - -
openmc . stats . CylindricalIndependent
Uniform distribution over the cylindrical shell
"""
r_dist = PowerLaw ( r_inner , r_outer , 1 )
phis_dist = Uniform ( phis [ 0 ] , phis [ 1 ] )
z_dist = delta_function ( 0.0 ) if height == 0.0 else Uniform ( - height / 2 , height / 2 )
return CylindricalIndependent ( r_dist , phis_dist , z_dist , * * kwargs )