1212import openmc .checkvalue as cv
1313from .._xml import get_elem_list , get_text
1414from ..mesh import MeshBase
15- from .univariate import PowerLaw , Uniform , Univariate
15+ from .univariate import PowerLaw , Uniform , Univariate , delta_function
1616
1717
1818class UnitSphere (ABC ):
@@ -532,6 +532,10 @@ class CylindricalIndependent(Spatial):
532532 origin: Iterable of float, optional
533533 coordinates (x0, y0, z0) of the center of the cylindrical reference
534534 frame. Defaults to (0.0, 0.0, 0.0)
535+ r_dir : Iterable of float, optional
536+ Unit vector of the cylinder r axis at phi=0. Defaults to (1.0, 0.0, 0.0).
537+ z_dir : Iterable of float, optional
538+ Unit vector of the cylinder z axis direction. Defaults to (0.0, 0.0, 1.0).
535539
536540 Attributes
537541 ----------
@@ -545,14 +549,20 @@ class CylindricalIndependent(Spatial):
545549 origin: Iterable of float, optional
546550 coordinates (x0, y0, z0) of the center of the cylindrical reference
547551 frame. Defaults to (0.0, 0.0, 0.0)
552+ r_dir : Iterable of float, optional
553+ Unit vector of the cylinder r axis at phi=0. Defaults to (1.0, 0.0, 0.0).
554+ z_dir : Iterable of float, optional
555+ Unit vector of the cylinder z axis direction. Defaults to (0.0, 0.0, 1.0).
548556
549557 """
550558
551- def __init__ (self , r , phi , z , origin = (0.0 , 0.0 , 0.0 )):
559+ 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 ) ):
552560 self .r = r
553561 self .phi = phi
554562 self .z = z
555563 self .origin = origin
564+ self .z_dir = z_dir
565+ self .r_dir = r_dir
556566
557567 @property
558568 def r (self ):
@@ -590,6 +600,33 @@ def origin(self, origin):
590600 cv .check_type ('origin coordinates' , origin , Iterable , Real )
591601 origin = np .asarray (origin )
592602 self ._origin = origin
603+
604+ @property
605+ def z_dir (self ):
606+ return self ._z_dir
607+
608+ @z_dir .setter
609+ def z_dir (self , z_dir ):
610+ cv .check_type ('z-axis direction' , z_dir , Iterable , Real )
611+ z_dir = np .asarray (z_dir )
612+ norm2 = np .dot (z_dir ,z_dir )
613+ cv .check_greater_than ('z-axis direction magnitude' , norm2 , 0.0 )
614+ z_dir /= np .sqrt (norm2 )
615+ self ._z_dir = z_dir
616+
617+ @property
618+ def r_dir (self ):
619+ return self ._r_dir
620+
621+ @r_dir .setter
622+ def r_dir (self , r_dir ):
623+ cv .check_type ('r-axis direction' , r_dir , Iterable , Real )
624+ r_dir = np .asarray (r_dir )
625+ r_dir -= np .dot (r_dir ,self .z_dir )* self .z_dir
626+ norm2 = np .dot (r_dir ,r_dir )
627+ cv .check_greater_than ('r-axis direction magnitude' , norm2 ,0.0 )
628+ r_dir /= np .sqrt (norm2 )
629+ self ._r_dir = r_dir
593630
594631 def to_xml_element (self ):
595632 """Return XML representation of the spatial distribution
@@ -606,6 +643,8 @@ def to_xml_element(self):
606643 element .append (self .phi .to_xml_element ('phi' ))
607644 element .append (self .z .to_xml_element ('z' ))
608645 element .set ("origin" , ' ' .join (map (str , self .origin )))
646+ element .set ("r_dir" , ' ' .join (map (str , self .r_dir )))
647+ element .set ("z_dir" , ' ' .join (map (str , self .z_dir )))
609648 return element
610649
611650 @classmethod
@@ -627,7 +666,9 @@ def from_xml_element(cls, elem: ET.Element):
627666 phi = Univariate .from_xml_element (elem .find ('phi' ))
628667 z = Univariate .from_xml_element (elem .find ('z' ))
629668 origin = get_elem_list (elem , "origin" , float )
630- return cls (r , phi , z , origin = origin )
669+ r_dir = get_elem_list (elem , "r_dir" , float ) or [1.0 , 0.0 , 0.0 ]
670+ z_dir = get_elem_list (elem , "z_dir" , float ) or [0.0 , 0.0 , 1.0 ]
671+ return cls (r , phi , z , origin = origin , r_dir = r_dir , z_dir = z_dir )
631672
632673
633674class MeshSpatial (Spatial ):
@@ -1086,3 +1127,95 @@ def spherical_uniform(
10861127 phis_dist = Uniform (phis [0 ], phis [1 ])
10871128
10881129 return SphericalIndependent (r_dist , cos_thetas_dist , phis_dist , origin )
1130+
1131+
1132+ def cylindrical_uniform (
1133+ r_outer : float ,
1134+ height : float ,
1135+ r_inner : float = 0.0 ,
1136+ phis : Sequence [float ] = (0. , 2 * pi ),
1137+ origin : Sequence [float ] = (0. , 0. , 0. ),
1138+ r_dir : Sequence [float ] = (1. , 0. , 0. ),
1139+ z_dir : Sequence [float ] = (0. , 0. , 1. ),
1140+ ):
1141+ """Return a uniform spatial distribution over a cylindrical shell.
1142+
1143+ This function provides a uniform spatial distribution over a cylindrical
1144+ shell between `r_inner` and `r_outer`. Optionally, the range of angles
1145+ can be restricted by the `phis` arguments.
1146+
1147+
1148+ Parameters
1149+ ----------
1150+ r_outer : float
1151+ Outer radius of the cylindrical shell in [cm]
1152+ height : float
1153+ Height of the cylindrical shell in [cm]
1154+ r_inner : float
1155+ Inner radius of the cylindrical shell in [cm]
1156+ phis : iterable of float
1157+ Starting and ending phi coordinates (azimuthal angle) in
1158+ radians in a reference frame centered at `origin`
1159+ origin: iterable of float
1160+ Coordinates (x0, y0, z0) of the center of the cylindrical
1161+ reference frame for the distribution. Defaults to (0.0, 0.0, 0.0)
1162+ r_dir : iterable of float
1163+ Direction of the r-axis at phi=0. Defaults to (1.0, 0.0, 0.0)
1164+ z_dir :
1165+ Direction of the z-axis. Defaults to (0.0, 0.0, 1.0)
1166+
1167+ Returns
1168+ -------
1169+ openmc.stats.CylindricalIndependent
1170+ Uniform distribution over the cylindrical shell
1171+ """
1172+
1173+ r_dist = PowerLaw (r_inner , r_outer , 1 )
1174+ phis_dist = Uniform (phis [0 ], phis [1 ])
1175+ z_dist = Uniform (- height / 2 , height / 2 )
1176+
1177+ return CylindricalIndependent (r_dist , phis_dist , z_dist , origin , r_dir , z_dir )
1178+
1179+ def ring_uniform (
1180+ r_outer : float ,
1181+ r_inner : float = 0.0 ,
1182+ phis : Sequence [float ] = (0. , 2 * pi ),
1183+ origin : Sequence [float ] = (0. , 0. , 0. ),
1184+ r_dir : Sequence [float ] = (1. , 0. , 0. ),
1185+ z_dir : Sequence [float ] = (0. , 0. , 1. ),
1186+ ):
1187+ """Return a uniform spatial distribution over a ring.
1188+
1189+ This function provides a uniform spatial distribution over a ring
1190+ shell between `r_inner` and `r_outer`. Optionally, the range of angles
1191+ can be restricted by the `phis` arguments.
1192+
1193+
1194+ Parameters
1195+ ----------
1196+ r_outer : float
1197+ Outer radius of the ring in [cm]
1198+ r_inner : float
1199+ Inner radius of the ring in [cm]
1200+ phis : iterable of float
1201+ Starting and ending phi coordinates (azimuthal angle) in
1202+ radians in a reference frame centered at `origin`
1203+ origin: iterable of float
1204+ Coordinates (x0, y0, z0) of the center of the cylindrical
1205+ reference frame for the distribution. Defaults to (0.0, 0.0, 0.0)
1206+ r_dir : iterable of float
1207+ Direction of the r-axis at phi=0. Defaults to (1.0, 0.0, 0.0)
1208+ z_dir :
1209+ Direction of the z-axis. Defaults to (0.0, 0.0, 1.0)
1210+
1211+ Returns
1212+ -------
1213+ openmc.stats.CylindricalIndependent
1214+ Uniform distribution over the ring
1215+ """
1216+
1217+ r_dist = PowerLaw (r_inner , r_outer , 1 )
1218+ phis_dist = Uniform (phis [0 ], phis [1 ])
1219+ z_dist = delta_function (np .dot (origin ,z_dir ))
1220+
1221+ return CylindricalIndependent (r_dist , phis_dist , z_dist , origin , r_dir , z_dir )
0 commit comments