diff --git a/openmc_plasma_source/fuel_types.py b/openmc_plasma_source/fuel_types.py index 902a5b1..3d84b71 100644 --- a/openmc_plasma_source/fuel_types.py +++ b/openmc_plasma_source/fuel_types.py @@ -4,12 +4,16 @@ for a given fusion fuel type. """ -import proper_tea as pt +from param import Parameterized, Number -class Fuel: - mean_energy = pt.positive_float(allow_zero=False) # mean energy, eV - mass_of_reactants = pt.positive(allow_zero=False) # mass of the reactants, AMU +class Fuel(Parameterized): + + # mean energy, eV + mean_energy = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) + + # mass of the reactants, AMU + mass_of_reactants = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) def __init__(self, mean_energy, mass_of_reactants): self.mean_energy = mean_energy diff --git a/openmc_plasma_source/point_source.py b/openmc_plasma_source/point_source.py index 61cb889..89f7811 100644 --- a/openmc_plasma_source/point_source.py +++ b/openmc_plasma_source/point_source.py @@ -1,12 +1,11 @@ +import openmc from typing import Tuple -import proper_tea as pt -import proper_tea.numpy -from .fuel_types import fuel_types +from param import Parameterized, Number, NumericTuple, ListSelector -import openmc +from .fuel_types import fuel_types -class FusionPointSource(openmc.Source): +class FusionPointSource(openmc.Source, Parameterized): """An openmc.Source object with some presets to make it more convenient for fusion simulations using a point source. All attributes can be changed after initialization if required. Default isotropic point source at the @@ -19,9 +18,9 @@ class FusionPointSource(openmc.Source): fuel_type (str): The fusion fuel mix. Either 'DT' or 'DD'. """ - coordinate = pt.numpy.numpy_array(shape=(3,), dtype=float) - temperature = pt.positive_float() # temperature in eV - fuel_type = pt.in_set(fuel_types.keys()) + coordinate = NumericTuple(None, length=3) + temperature = Number(None, bounds=(0, None)) # temperature in eV + fuel_type = ListSelector(fuel_types.keys()) def __init__( self, diff --git a/openmc_plasma_source/ring_source.py b/openmc_plasma_source/ring_source.py index 452f14f..a0cfb0a 100644 --- a/openmc_plasma_source/ring_source.py +++ b/openmc_plasma_source/ring_source.py @@ -1,13 +1,12 @@ -from typing import Tuple +import openmc import numpy as np -import proper_tea as pt -import proper_tea.numpy -from .fuel_types import fuel_types +from typing import Tuple +from param import Parameterized, Number, Range, ListSelector -import openmc +from .fuel_types import fuel_types -class FusionRingSource(openmc.Source): +class FusionRingSource(openmc.Source, Parameterized): """An openmc.Source object with some presets to make it more convenient for fusion simulations using a ring source. All attributes can be changed after initialization if required. Default isotropic ring source with a Muir @@ -21,11 +20,11 @@ class FusionRingSource(openmc.Source): fuel_type (str): The fusion fuel mix. Either 'DT' or 'DD'. """ - radius = pt.positive_float() - angles = pt.numpy.numpy_array(shape=(2,), dtype=float, sort=True) - z_placement = pt.floating_point() - temperature = pt.positive_float() - fuel_type = pt.in_set(fuel_types.keys()) + radius = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) + angles = Range((0, 2 * np.pi)) + z_placement = Number() + temperature = Number(bounds=(0, None)) + fuel_type = ListSelector(fuel_types.keys()) def __init__( self, diff --git a/openmc_plasma_source/tokamak_source.py b/openmc_plasma_source/tokamak_source.py index badea6e..9387085 100644 --- a/openmc_plasma_source/tokamak_source.py +++ b/openmc_plasma_source/tokamak_source.py @@ -1,11 +1,10 @@ -from typing import Tuple -import numpy as np -import proper_tea as pt -import proper_tea.numpy import openmc +import numpy as np +from typing import Tuple +from param import Parameterized, Number, Integer, Range, ListSelector -class TokamakSource: +class TokamakSource(Parameterized): """Plasma neutron source sampling. This class greatly relies on models described in [1] @@ -50,23 +49,23 @@ class TokamakSource: to 1000. """ - major_radius = pt.positive_float(allow_zero=False) - minor_radius = pt.positive_float(allow_zero=False) - elongation = pt.positive_float(allow_zero=False) - triangularity = pt.in_range(bounds=(-1.0, 1.0)) - mode = pt.in_set({"H", "L", "A"}) - ion_density_centre = pt.positive_float() - ion_density_peaking_factor = pt.floating_point() - ion_density_pedestal = pt.positive_float() - ion_density_separatrix = pt.positive_float() - ion_temperature_centre = pt.positive_float() - ion_temperature_peaking_factor = pt.floating_point() - ion_temperature_beta = pt.floating_point() - ion_temperature_pedestal = pt.positive_float() - ion_temperature_separatrix = pt.positive_float() - pedestal_radius = pt.positive_float(allow_zero=False) - angles = pt.numpy.numpy_array(shape=(2,), dtype=float, sort=True) - sample_size = pt.positive_int(allow_zero=False) + major_radius = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) + minor_radius = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) + elongation = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) + triangularity = Number(bounds=(-1.0, 1.0)) + mode = ListSelector(["H", "L", "A"]) + ion_density_centre = Number(bounds=(0, None)) + ion_density_peaking_factor = Number() + ion_density_pedestal = Number(bounds=(0, None)) + ion_density_separatrix = Number(bounds=(0, None)) + ion_temperature_centre = Number(bounds=(0, None)) + ion_temperature_peaking_factor = Number() + ion_temperature_beta = Number() + ion_temperature_pedestal = Number(bounds=(0, None)) + ion_temperature_separatrix = Number(bounds=(0, None)) + pedestal_radius = Number(None, bounds=(0, None), inclusive_bounds=(False, False)) + angles = Range((0, 2 * np.pi)) + sample_size = Integer(None, bounds=(0, None), inclusive_bounds=(False, False)) def __init__( self, diff --git a/setup.cfg b/setup.cfg index d89e89a..5f57ee7 100644 --- a/setup.cfg +++ b/setup.cfg @@ -28,7 +28,7 @@ python_requires= >=3.6 install_requires= numpy >= 1.9 matplotlib >= 3.2.2 - proper_tea ~= 0.3.4 + param ~= 1.12.0 importlib-metadata; python_version < "3.8" [options.extras_require] diff --git a/tests/test_point_source.py b/tests/test_point_source.py index 00655ef..11bb78e 100644 --- a/tests/test_point_source.py +++ b/tests/test_point_source.py @@ -18,17 +18,17 @@ def test_creation(): @pytest.mark.parametrize( - "coordinate", [(1.0, 2.0, 3.0), [4, 5, 6], np.linspace(1.0, 3.0, 3)] + "coordinate", [(1.0, 2.0, 3.0), (4, 5, 6), tuple(np.linspace(1.0, 3.0, 3))] ) def test_coordinate(coordinate): - # Should allow any iterable of length 3 with contents convertible to float + # Should allow any tuple of length 3 containing numbers my_source = FusionPointSource(coordinate=coordinate) assert np.array_equal(my_source.coordinate, coordinate) -@pytest.mark.parametrize("coordinate", [(1, 2), [3, 4, 5, 6], 5, "abc"]) +@pytest.mark.parametrize("coordinate", [(1, 2), [3, 4, 5], 5, "abc", ("a", "b", "c")]) def test_bad_coordinate(coordinate): - # Should reject iterables of length != 3, anything non iterable, and anything + # Should reject iterables of length != 3, anything non-tuple, and anything # that can't convert to float with pytest.raises(ValueError): FusionPointSource(coordinate=coordinate) @@ -58,5 +58,5 @@ def test_fuel(fuel): @pytest.mark.parametrize("fuel", ["топливо", 5]) def test_wrong_fuel(fuel): # Should reject fuel types besides those listed in fuel_types.py - with pytest.raises(ValueError): + with pytest.raises((KeyError, TypeError)): FusionPointSource(fuel=fuel) diff --git a/tests/test_ring_source.py b/tests/test_ring_source.py index 7816304..4df2e36 100644 --- a/tests/test_ring_source.py +++ b/tests/test_ring_source.py @@ -31,18 +31,16 @@ def test_bad_radius(radius): my_source = FusionRingSource(radius=radius) -@pytest.mark.parametrize("angles", [(1.0, 2), [0, np.pi], (np.pi, 0)]) +@pytest.mark.parametrize("angles", [(1.0, 2), (0, np.pi), (np.pi, 0)]) def test_angles(angles): - # Should allow any iterable of length 2 with contents convertible to float - # If angles are given in reverse order, it should sort them automatically + # Should allow any tuple of length 2 with contents convertible to float my_source = FusionRingSource(radius=1.0, angles=angles) - assert np.array_equal(my_source.angles, sorted(angles)) - assert my_source.angles[0] < my_source.angles[1] + assert np.array_equal(my_source.angles, angles) -@pytest.mark.parametrize("angles", [(1,), [1, 2, 3, 4], 5, "ab"]) +@pytest.mark.parametrize("angles", [(1,), [1, 2], 5, "ab", ("a", "b")]) def test_bad_angles(angles): - # Should reject iterables of length != 2, anything non iterable, and anything + # Should reject iterables of length != 2, anything non tuple, and anything # that can't convert to float with pytest.raises(ValueError): FusionRingSource(radius=1.0, angles=angles) @@ -72,5 +70,5 @@ def test_fuel(fuel): @pytest.mark.parametrize("fuel", ["топливо", 5]) def test_wrong_fuel(fuel): # Should reject fuel types besides those listed in fuel_types.py - with pytest.raises(ValueError): + with pytest.raises((KeyError, TypeError)): FusionRingSource(radius=1.0, fuel=fuel) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index 740acea..714f130 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -171,12 +171,12 @@ def test_bad_shafranov_factor(tokamak_args_dict, major_radius, minor_radius, sha ) def test_angles(tokamak_args_dict, angles): """Checks that custom angles can be set""" - # Note: should accept negative angles and angles in wrong order + # Note: should accept negative angles and angles in reverse order tokamak_args_dict["angles"] = angles tokamak_source = TokamakSource(**tokamak_args_dict) - assert np.array_equal(tokamak_source.angles, sorted(angles)) + assert np.array_equal(tokamak_source.angles, angles) for source in tokamak_source.sources: - assert np.array_equal((source.space.phi.a, source.space.phi.b), sorted(angles)) + assert np.array_equal((source.space.phi.a, source.space.phi.b), angles) @pytest.mark.parametrize("angles", [(0, 1, 2), -5, ("hello", "world")])