Check for positive radii (#3813)

This commit is contained in:
GuySten 2026-02-19 10:36:12 +02:00 committed by GitHub
parent 6d6b051507
commit f007c85a50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 18 deletions

View file

@ -38,10 +38,13 @@ class SurfaceCoefficient:
value : float or str
Value of the coefficient (float) or the name of the coefficient that
it is equivalent to (str).
positive : bool
Does the surface coefficient must be positive. Defaults to False.
"""
def __init__(self, value):
def __init__(self, value, positive=False):
self.value = value
self.positive = positive
def __get__(self, instance, owner=None):
if instance is None:
@ -56,6 +59,8 @@ class SurfaceCoefficient:
if isinstance(self.value, Real):
raise AttributeError('This coefficient is read-only')
check_type(f'{self.value} coefficient', value, Real)
if self.positive:
check_greater_than(f'{self.value} coefficient', value, 0.0)
instance._coefficients[self.value] = value
@ -1261,7 +1266,7 @@ class Cylinder(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r = SurfaceCoefficient('r')
r = SurfaceCoefficient('r', positive=True)
dx = SurfaceCoefficient('dx')
dy = SurfaceCoefficient('dy')
dz = SurfaceCoefficient('dz')
@ -1427,7 +1432,7 @@ class XCylinder(QuadricMixin, Surface):
x0 = SurfaceCoefficient(0.)
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r = SurfaceCoefficient('r')
r = SurfaceCoefficient('r', positive=True)
dx = SurfaceCoefficient(1.)
dy = SurfaceCoefficient(0.)
dz = SurfaceCoefficient(0.)
@ -1525,7 +1530,7 @@ class YCylinder(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient(0.)
z0 = SurfaceCoefficient('z0')
r = SurfaceCoefficient('r')
r = SurfaceCoefficient('r', positive=True)
dx = SurfaceCoefficient(0.)
dy = SurfaceCoefficient(1.)
dz = SurfaceCoefficient(0.)
@ -1623,7 +1628,7 @@ class ZCylinder(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient(0.)
r = SurfaceCoefficient('r')
r = SurfaceCoefficient('r', positive=True)
dx = SurfaceCoefficient(0.)
dy = SurfaceCoefficient(0.)
dz = SurfaceCoefficient(1.)
@ -1723,7 +1728,7 @@ class Sphere(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r = SurfaceCoefficient('r')
r = SurfaceCoefficient('r', positive=True)
def _get_base_coeffs(self):
x0, y0, z0, r = self.x0, self.y0, self.z0, self.r
@ -1849,7 +1854,7 @@ class Cone(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r2 = SurfaceCoefficient('r2')
r2 = SurfaceCoefficient('r2', positive=True)
dx = SurfaceCoefficient('dx')
dy = SurfaceCoefficient('dy')
dz = SurfaceCoefficient('dz')
@ -1985,7 +1990,7 @@ class XCone(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r2 = SurfaceCoefficient('r2')
r2 = SurfaceCoefficient('r2', positive=True)
dx = SurfaceCoefficient(1.)
dy = SurfaceCoefficient(0.)
dz = SurfaceCoefficient(0.)
@ -2087,7 +2092,7 @@ class YCone(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r2 = SurfaceCoefficient('r2')
r2 = SurfaceCoefficient('r2', positive=True)
dx = SurfaceCoefficient(0.)
dy = SurfaceCoefficient(1.)
dz = SurfaceCoefficient(0.)
@ -2189,7 +2194,7 @@ class ZCone(QuadricMixin, Surface):
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
r2 = SurfaceCoefficient('r2')
r2 = SurfaceCoefficient('r2', positive=True)
dx = SurfaceCoefficient(0.)
dy = SurfaceCoefficient(0.)
dz = SurfaceCoefficient(1.)
@ -2292,9 +2297,9 @@ class TorusMixin:
x0 = SurfaceCoefficient('x0')
y0 = SurfaceCoefficient('y0')
z0 = SurfaceCoefficient('z0')
a = SurfaceCoefficient('a')
b = SurfaceCoefficient('b')
c = SurfaceCoefficient('c')
a = SurfaceCoefficient('a', positive=True)
b = SurfaceCoefficient('b', positive=True)
c = SurfaceCoefficient('c', positive=True)
def translate(self, vector, inplace=False):
surf = self if inplace else self.clone()

View file

@ -46,11 +46,6 @@ def test_failure(pin_mats, good_radii):
with pytest.raises(ValueError, match="length"):
pin(good_surfaces[:len(pin_mats) - 2], pin_mats)
# Non-positive radii
rad = [openmc.ZCylinder(r=-0.1)] + good_surfaces[1:]
with pytest.raises(ValueError, match="index 0"):
pin(rad, pin_mats)
# Non-increasing radii
surfs = tuple(reversed(good_surfaces))
with pytest.raises(ValueError, match="index 1"):

View file

@ -195,6 +195,12 @@ def test_cylinder():
assert s.dy == -1
assert s.dz == 1
assert s.r == 2
# Check radius must be positive
with pytest.raises(ValueError):
openmc.Cylinder(x0=x0, y0=y0, z0=z0, dx=dx, dy=dy, dz=dz, r=0.0)
with pytest.raises(ValueError):
openmc.Cylinder(x0=x0, y0=y0, z0=z0, dx=dx, dy=dy, dz=dz, r=-1.0)
# Check bounding box
assert_infinite_bb(s)
@ -244,6 +250,12 @@ def test_xcylinder():
assert s.y0 == y
assert s.z0 == z
assert s.r == r
# Check radius must be positive
with pytest.raises(ValueError):
openmc.XCylinder(y0=y, z0=z, r=0.0)
with pytest.raises(ValueError):
openmc.XCylinder(y0=y, z0=z, r=-1.0)
# Check bounding box
ll, ur = (+s).bounding_box
@ -290,6 +302,12 @@ def test_ycylinder():
assert s.x0 == x
assert s.z0 == z
assert s.r == r
# Check radius must be positive
with pytest.raises(ValueError):
openmc.YCylinder(x0=x, z0=z, r=0.0)
with pytest.raises(ValueError):
openmc.YCylinder(x0=x, z0=z, r=-1.0)
# Check bounding box
ll, ur = (+s).bounding_box
@ -327,6 +345,12 @@ def test_zcylinder():
assert s.x0 == x
assert s.y0 == y
assert s.r == r
# Check radius must be positive
with pytest.raises(ValueError):
openmc.ZCylinder(x0=x, y0=y, r=0.0)
with pytest.raises(ValueError):
openmc.ZCylinder(x0=x, y0=y, r=-1.0)
# Check bounding box
ll, ur = (+s).bounding_box
@ -365,6 +389,12 @@ def test_sphere():
assert s.y0 == y
assert s.z0 == z
assert s.r == r
# Check radius must be positive
with pytest.raises(ValueError):
openmc.Sphere(x0=x, y0=y, z0=z, r=0.0)
with pytest.raises(ValueError):
openmc.Sphere(x0=x, y0=y, z0=z, r=-1.0)
# Check bounding box
ll, ur = (+s).bounding_box
@ -404,6 +434,12 @@ def cone_common(apex, r2, cls):
assert s.y0 == y
assert s.z0 == z
assert s.r2 == r2
# Check radius must be positive
with pytest.raises(ValueError):
cls(x0=x, y0=y, z0=z, r2=0.0)
with pytest.raises(ValueError):
cls(x0=x, y0=y, z0=z, r2=-1.0)
# Check bounding box
assert_infinite_bb(s)
@ -442,6 +478,12 @@ def test_cone():
assert s.dy == -1
assert s.dz == 1
assert s.r2 == 4
# Check radius must be positive
with pytest.raises(ValueError):
openmc.Cone(x0=x0, y0=y0, z0=z0, dx=dx, dy=dy, dz=dz, r2=0.0)
with pytest.raises(ValueError):
openmc.Cone(x0=x0, y0=y0, z0=z0, dx=dx, dy=dy, dz=dz, r2=-1.0)
# Check bounding box
assert_infinite_bb(s)
@ -622,6 +664,13 @@ def torus_common(center, R, r1, r2, cls):
assert s.a == R
assert s.b == r1
assert s.c == r2
# Check radius must be positive
params = [(0.0, r1, r2), (R, 0.0, r2), (R, r1, 0.0),
(-1.0, r1, r2), (R, -1.0, r2), (R, r1, -1.0)]
for a,b,c in params:
with pytest.raises(ValueError):
cls(x0=x, y0=y, z0=z, a=a, b=b, c=c)
# evaluate method
assert s.evaluate((x, y, z)) > 0.0