Source code for openmc.stats.multivariate

from abc import ABCMeta, abstractmethod
from collections import Iterable
from math import pi
from numbers import Real
import sys
from xml.etree import ElementTree as ET

import numpy as np

import openmc.checkvalue as cv
from openmc.stats.univariate import Univariate, Uniform

if sys.version_info[0] >= 3:
    basestring = str


[docs]class UnitSphere(object): """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 ---------- reference_uvw : Iterable of float Direction from which polar angle is measured Attributes ---------- reference_uvw : Iterable of float Direction from which polar angle is measured """ __metaclass__ = ABCMeta def __init__(self, reference_uvw=None): 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) self._reference_uvw = uvw/np.linalg.norm(uvw) @abstractmethod def to_xml(self): return ''
[docs]class PolarAzimuthal(UnitSphere): """Angular distribution represented by polar and azimuthal angles This distribution allows one to specify the distribution of the cosine of the polar angle and the azimuthal angle independently of once another. Parameters ---------- mu : openmc.stats.Univariate Distribution of the cosine of the polar angle phi : openmc.stats.Univariate Distribution of the azimuthal angle in radians reference_uvw : Iterable of float Direction from which polar angle is measured. Defaults to the positive z-direction. Attributes ---------- mu : openmc.stats.Univariate Distribution of the cosine of the polar angle phi : openmc.stats.Univariate Distribution of the azimuthal angle in radians """ def __init__(self, mu=None, phi=None, reference_uvw=[0., 0., 1.]): super(PolarAzimuthal, self).__init__(reference_uvw) if mu is not None: self.mu = mu else: self.mu = Uniform(-1., 1.) if phi is not None: self.phi = phi else: self.phi = Uniform(0., 2*pi) @property def mu(self): return self._mu @property def phi(self): return self._phi @mu.setter def mu(self, mu): cv.check_type('cosine of polar angle', mu, Univariate) self._mu = mu @phi.setter def phi(self, phi): cv.check_type('azimuthal angle', phi, Univariate) self._phi = phi def to_xml(self): element = ET.Element('angle') element.set("type", "mu-phi") if self.reference_uvw is not None: element.set("reference_uvw", ' '.join(map(str, self.reference_uvw))) element.append(self.mu.to_xml('mu')) element.append(self.phi.to_xml('phi')) return element
[docs]class Isotropic(UnitSphere): """Isotropic angular distribution. """ def __init__(self): super(Isotropic, self).__init__() def to_xml(self): element = ET.Element('angle') element.set("type", "isotropic") return element
[docs]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 ---------- reference_uvw : Iterable of float Direction from which polar angle is measured. Defaults to the positive x-direction. """ def __init__(self, reference_uvw=[1., 0., 0.]): super(Monodirectional, self).__init__(reference_uvw) def to_xml(self): element = ET.Element('angle') element.set("type", "monodirectional") if self.reference_uvw is not None: element.set("reference_uvw", ' '.join(map(str, self.reference_uvw))) return element
[docs]class Spatial(object): """Distribution of locations in three-dimensional Euclidean space. Classes derived from this abstract class can be used for spatial distributions of source sites. """ __metaclass__ = ABCMeta def __init__(self): pass @abstractmethod def to_xml(self): return ''
[docs]class CartesianIndependent(Spatial): """Spatial distribution with independent x, y, and z distributions. This distribution allows one to specify a coordinates whose x-, y-, and z- components are sampled independently from one another. Parameters ---------- x : openmc.stats.Univariate Distribution of x-coordinates y : openmc.stats.Univariate Distribution of y-coordinates z : openmc.stats.Univariate Distribution of z-coordinates Attributes ---------- x : openmc.stats.Univariate Distribution of x-coordinates y : openmc.stats.Univariate Distribution of y-coordinates z : openmc.stats.Univariate Distribution of z-coordinates """ def __init__(self, x, y, z): super(CartesianIndependent, self).__init__() self.x = x self.y = y self.z = z @property def x(self): return self._x @property def y(self): return self._y @property def z(self): return self._z @x.setter def x(self, x): cv.check_type('x coordinate', x, Univariate) self._x = x @y.setter def y(self, y): cv.check_type('y coordinate', y, Univariate) self._y = y @z.setter def z(self, z): cv.check_type('z coordinate', z, Univariate) self._z = z def to_xml(self): element = ET.Element('space') element.set('type', 'cartesian') element.append(self.x.to_xml('x')) element.append(self.y.to_xml('y')) element.append(self.z.to_xml('z')) return element
[docs]class Box(Spatial): """Uniform distribution of coordinates in a rectangular cuboid. Parameters ---------- lower_left : Iterable of float Lower-left coordinates of cuboid upper_right : Iterable of float Upper-right coordinates of cuboid only_fissionable : bool, optional Whether spatial sites should only be accepted if they occur in fissionable materials Attributes ---------- lower_left : Iterable of float Lower-left coordinates of cuboid upper_right : Iterable of float Upper-right coordinates of cuboid only_fissionable : bool, optional Whether spatial sites should only be accepted if they occur in fissionable materials """ def __init__(self, lower_left, upper_right, only_fissionable=False): super(Box, self).__init__() self.lower_left = lower_left self.upper_right = upper_right self.only_fissionable = only_fissionable @property def lower_left(self): return self._lower_left @property def upper_right(self): return self._upper_right @property def only_fissionable(self): return self._only_fissionable @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 @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 @only_fissionable.setter def only_fissionable(self, only_fissionable): cv.check_type('only fissionable', only_fissionable, bool) self._only_fissionable = only_fissionable def to_xml(self): element = ET.Element('space') 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
[docs]class Point(Spatial): """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 ---------- xyz : Iterable of float, optional Cartesian coordinates of location. Defaults to (0., 0., 0.). Attributes ---------- xyz : Iterable of float Cartesian coordinates of location """ def __init__(self, xyz=(0., 0., 0.)): super(Point, self).__init__() 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 def to_xml(self): element = ET.Element('space') element.set("type", "point") params = ET.SubElement(element, "parameters") params.text = ' '.join(map(str, self.xyz)) return element