From a5dec8c119148d5d666e6421a2db652ea8b890c0 Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Mon, 24 Jan 2022 14:26:20 +0000 Subject: [PATCH 1/7] Added new tests to test_tokamak_source --- tests/test_tokamak_source.py | 115 +++++++++++++++++------------------ 1 file changed, 55 insertions(+), 60 deletions(-) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index 957cc16..c1be5bd 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -1,74 +1,69 @@ from openmc_plasma_source import TokamakSource - from openmc import Source +import numpy as np import pytest -def test_creation(): - my_source = TokamakSource( - elongation=1.557, - ion_density_centre=1.09e20, - ion_density_peaking_factor=1, - ion_density_pedestal=1.09e20, - ion_density_separatrix=3e19, - ion_temperature_centre=45.9, - ion_temperature_peaking_factor=8.06, - ion_temperature_pedestal=6.09, - ion_temperature_separatrix=0.1, - major_radius=9.06, - minor_radius=2.92258, - pedestal_radius=0.8 * 2.92258, - mode="H", - shafranov_factor=0.44789, - triangularity=0.270, - ion_temperature_beta=6, - ) - for source in my_source.make_openmc_sources(): +@pytest.fixture +def tokamak_input(): + return { + "elongation": 1.557, + "triangularity": 0.270, + "major_radius": 9.06, + "minor_radius": 2.92258, + "pedestal_radius": 0.8 * 2.92258, + "shafranov_factor": 0.44789, + "ion_density_centre": 1.09e20, + "ion_density_peaking_factor": 1, + "ion_density_pedestal": 1.09e20, + "ion_density_separatrix": 3e19, + "ion_temperature_centre": 45.9, + "ion_temperature_peaking_factor": 8.06, + "ion_temperature_pedestal": 6.09, + "ion_temperature_separatrix": 0.1, + "mode": "H", + "ion_temperature_beta": 6, + } + + +@pytest.fixture +def my_source(tokamak_input): + return TokamakSource(**tokamak_input) + + +def test_creation(my_source): + for source in my_source.sources: assert isinstance(source, Source) -def test_strengths_are_normalised(): +def test_strengths_are_normalised(my_source): """Tests that the sum of the strengths attribute is equal to""" - my_source = TokamakSource( - elongation=1.557, - ion_density_centre=1.09e20, - ion_density_peaking_factor=1, - ion_density_pedestal=1.09e20, - ion_density_separatrix=3e19, - ion_temperature_centre=45.9, - ion_temperature_peaking_factor=8.06, - ion_temperature_pedestal=6.09, - ion_temperature_separatrix=0.1, - major_radius=9.06, - minor_radius=2.92258, - pedestal_radius=0.8 * 2.92258, - mode="H", - shafranov_factor=0.44789, - triangularity=0.270, - ion_temperature_beta=6, - ) assert pytest.approx(sum(my_source.strengths), 1) -def test_angles(): +def test_source_locations_are_within_correct_range(tokamak_input, my_source): + """Tests that each source has RZ locations within the expected range. + Note that this test is not wholly accurate, as it only ensures that + R and Z fall within a box defined by the lower-left point (R_min,Z_min) + and upper-right point (R_max,Z_max), and does not account for the + actual expected plasma geometry. + """ + r_min = tokamak_input["major_radius"] - tokamak_input["minor_radius"] + r_max = tokamak_input["major_radius"] + tokamak_input["minor_radius"] + z_max = tokamak_input["minor_radius"] * tokamak_input["elongation"] + for source in my_source.sources: + r, z = source.space.r.x[0], source.space.z.x[0] + assert r >= r_min + assert r <= r_max + assert abs(z) <= z_max + + +def test_angles(tokamak_input): """Checks that custom angles can be set""" - my_source = TokamakSource( - elongation=1.557, - ion_density_centre=1.09e20, - ion_density_peaking_factor=1, - ion_density_pedestal=1.09e20, - ion_density_separatrix=3e19, - ion_temperature_centre=45.9, - ion_temperature_peaking_factor=8.06, - ion_temperature_pedestal=6.09, - ion_temperature_separatrix=0.1, - major_radius=9.06, - minor_radius=2.92258, - pedestal_radius=0.8 * 2.92258, - mode="H", - shafranov_factor=0.44789, - triangularity=0.270, - ion_temperature_beta=6, - angles=(0, 1), - ) + alt_input = tokamak_input.copy() + alt_input["angles"] = (0, 1) + alt_source = TokamakSource(**alt_input) + assert alt_source.angles == (0, 1) + for source in alt_source.sources: + assert (source.space.phi.a, source.space.phi.b) == (0, 1) From b597987ca4afe719af64cda034f1d8dfbc09cadb Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Mon, 24 Jan 2022 17:38:11 +0000 Subject: [PATCH 2/7] Further constrained tokamak source test --- tests/test_tokamak_source.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index c1be5bd..2dd733b 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -1,6 +1,6 @@ from openmc_plasma_source import TokamakSource from openmc import Source -import numpy as np +import math import pytest @@ -49,14 +49,29 @@ def test_source_locations_are_within_correct_range(tokamak_input, my_source): and upper-right point (R_max,Z_max), and does not account for the actual expected plasma geometry. """ - r_min = tokamak_input["major_radius"] - tokamak_input["minor_radius"] - r_max = tokamak_input["major_radius"] + tokamak_input["minor_radius"] - z_max = tokamak_input["minor_radius"] * tokamak_input["elongation"] + R_0 = tokamak_input["major_radius"] + A = tokamak_input["minor_radius"] + El = tokamak_input["elongation"] + delta = tokamak_input["triangularity"] + def get_R(alpha): + return R_0 + A * math.cos(alpha + delta * math.sin(alpha)) for source in my_source.sources: - r, z = source.space.r.x[0], source.space.z.x[0] - assert r >= r_min - assert r <= r_max - assert abs(z) <= z_max + R, Z = source.space.r.x[0], source.space.z.x[0] + # First test that the point is contained with a simple box with + # lower left (r_min,-z_max) and upper right (r_max,z_max) + assert R >= R_0 - A + assert R <= R_0 + A + assert abs(Z) <= A * El + # For a given Z, we can determine the two values of alpha where + # where a = minor_radius, and from there determine the upper and + # lower bounds for R. + alpha_1 = math.asin(abs(Z) / (El * A)) + alpha_2 = math.pi - alpha_1 + R_max, R_min = get_R(alpha_1), get_R(alpha_2) + assert R_max <= R_0 + A + assert R_min >= R_0 - A + assert R <= R_max + assert R >= R_min def test_angles(tokamak_input): From cc2586e86427e38115925744cdb09ec804f4b890 Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Tue, 25 Jan 2022 18:13:03 +0000 Subject: [PATCH 3/7] Added hypothesis testing to cover a wide range of tokamak geometries --- tests/test_tokamak_source.py | 102 ++++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 31 deletions(-) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index 2dd733b..f040fa5 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -1,19 +1,16 @@ from openmc_plasma_source import TokamakSource from openmc import Source -import math +import numpy as np import pytest +from hypothesis import given, settings, assume, strategies as st +finites = {"allow_nan": False, "allow_infinity": False, "allow_subnormal": False} -@pytest.fixture -def tokamak_input(): + +@pytest.fixture(scope="module") +def tokamak_plasma_input(): return { - "elongation": 1.557, - "triangularity": 0.270, - "major_radius": 9.06, - "minor_radius": 2.92258, - "pedestal_radius": 0.8 * 2.92258, - "shafranov_factor": 0.44789, "ion_density_centre": 1.09e20, "ion_density_peaking_factor": 1, "ion_density_pedestal": 1.09e20, @@ -27,51 +24,94 @@ def tokamak_input(): } -@pytest.fixture -def my_source(tokamak_input): +@pytest.fixture(scope="module") +def tokamak_geometry_input(): + return { + "elongation": 1.557, + "triangularity": 0.270, + "major_radius": 9.06, + "minor_radius": 2.92258, + "pedestal_radius": 0.8 * 2.92258, + "shafranov_factor": 0.44789, + } + + +@pytest.fixture(scope="module") +def tokamak_input(tokamak_plasma_input, tokamak_geometry_input): + return {**tokamak_plasma_input, **tokamak_geometry_input} + + +@pytest.fixture(scope="function") +def tokamak_source(tokamak_input): return TokamakSource(**tokamak_input) -def test_creation(my_source): - for source in my_source.sources: +@st.composite +def tokamak_geometry(draw): + minor_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) + major_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) + pedestal_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) + elongation = draw(st.floats(min_value=1.0, max_value=10.0, **finites)) + triangularity = draw(st.floats(min_value=0.0, max_value=1.0, **finites)) + shafranov_factor = draw(st.floats(min_value=0.0, max_value=1.0, **finites)) + assume(major_radius > minor_radius) + assume(minor_radius > pedestal_radius) + assume(minor_radius > shafranov_factor) + return { + "elongation": elongation, + "triangularity": triangularity, + "major_radius": major_radius, + "minor_radius": minor_radius, + "pedestal_radius": pedestal_radius, + "shafranov_factor": shafranov_factor, + } + + +def test_creation(tokamak_source): + for source in tokamak_source.sources: assert isinstance(source, Source) -def test_strengths_are_normalised(my_source): +def test_strengths_are_normalised(tokamak_source): """Tests that the sum of the strengths attribute is equal to""" - assert pytest.approx(sum(my_source.strengths), 1) + assert pytest.approx(sum(tokamak_source.strengths), 1) -def test_source_locations_are_within_correct_range(tokamak_input, my_source): +@given(geometry=tokamak_geometry()) +@settings(max_examples=100,deadline=None) +def test_source_locations_are_within_correct_range(geometry, tokamak_plasma_input): """Tests that each source has RZ locations within the expected range. Note that this test is not wholly accurate, as it only ensures that R and Z fall within a box defined by the lower-left point (R_min,Z_min) and upper-right point (R_max,Z_max), and does not account for the actual expected plasma geometry. """ - R_0 = tokamak_input["major_radius"] - A = tokamak_input["minor_radius"] - El = tokamak_input["elongation"] - delta = tokamak_input["triangularity"] + tokamak_source = TokamakSource(**geometry, **tokamak_plasma_input) + R_0 = geometry["major_radius"] + A = geometry["minor_radius"] + El = geometry["elongation"] + delta = geometry["triangularity"] + def get_R(alpha): - return R_0 + A * math.cos(alpha + delta * math.sin(alpha)) - for source in my_source.sources: + return R_0 + A * np.cos(alpha + delta * np.sin(alpha)) + + for source in tokamak_source.sources: R, Z = source.space.r.x[0], source.space.z.x[0] # First test that the point is contained with a simple box with # lower left (r_min,-z_max) and upper right (r_max,z_max) - assert R >= R_0 - A - assert R <= R_0 + A - assert abs(Z) <= A * El + assert R > R_0 - A or np.isclose(R, R_0 - A) + assert R < R_0 + A or np.isclose(R, R_0 + A) + assert abs(Z) < A * El or np.isclose(abs(Z), A * El) # For a given Z, we can determine the two values of alpha where # where a = minor_radius, and from there determine the upper and # lower bounds for R. - alpha_1 = math.asin(abs(Z) / (El * A)) - alpha_2 = math.pi - alpha_1 + alpha_1 = np.arcsin(abs(Z) / (El * A)) + alpha_2 = np.pi - alpha_1 R_max, R_min = get_R(alpha_1), get_R(alpha_2) - assert R_max <= R_0 + A - assert R_min >= R_0 - A - assert R <= R_max - assert R >= R_min + assert R_max < R_0 + A or np.isclose(R_max, R_0 + A) + assert R_min > R_0 - A or np.isclose(R_min, R_0 - A) + assert R < R_max or np.isclose(R, R_max) + assert R > R_min or np.isclose(R, R_min) def test_angles(tokamak_input): From 277a30fbe83c2fae87cc55f07417835ca3d2d8bd Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Wed, 26 Jan 2022 15:13:09 +0000 Subject: [PATCH 4/7] Added better comments to test_tokamak_source --- tests/test_tokamak_source.py | 42 +++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index f040fa5..fed9365 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -5,11 +5,10 @@ import pytest from hypothesis import given, settings, assume, strategies as st -finites = {"allow_nan": False, "allow_infinity": False, "allow_subnormal": False} - @pytest.fixture(scope="module") def tokamak_plasma_input(): + """Defines a fixed set of plasma inputs, known to be valid.""" return { "ion_density_centre": 1.09e20, "ion_density_peaking_factor": 1, @@ -26,6 +25,7 @@ def tokamak_plasma_input(): @pytest.fixture(scope="module") def tokamak_geometry_input(): + """Defines a fixed set of tokamak geometry inputs, known to be valid.""" return { "elongation": 1.557, "triangularity": 0.270, @@ -38,25 +38,39 @@ def tokamak_geometry_input(): @pytest.fixture(scope="module") def tokamak_input(tokamak_plasma_input, tokamak_geometry_input): + """ Combines the plasma input and geometry input fixtures for convenience.""" return {**tokamak_plasma_input, **tokamak_geometry_input} @pytest.fixture(scope="function") def tokamak_source(tokamak_input): + """Creates example of a TokamakSource with inputs known to be valid. + Note that this fixture is rebuilt for each function call. + """ return TokamakSource(**tokamak_input) @st.composite -def tokamak_geometry(draw): +def tokamak_geometry_strategy(draw): + """Defines a hypothesis strategy that automatically generates dictionaries of + tokamak geometry inputs. + """ + # Used to avoid generation of inappropriate float values + finites = {"allow_nan": False, "allow_infinity": False, "allow_subnormal": False} + + # Specify the base strategies for each geometry input minor_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) major_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) pedestal_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) elongation = draw(st.floats(min_value=1.0, max_value=10.0, **finites)) triangularity = draw(st.floats(min_value=0.0, max_value=1.0, **finites)) shafranov_factor = draw(st.floats(min_value=0.0, max_value=1.0, **finites)) + + # Specify requirements that must be satisfied for a valid tokamak assume(major_radius > minor_radius) assume(minor_radius > pedestal_radius) assume(minor_radius > shafranov_factor) + return { "elongation": elongation, "triangularity": triangularity, @@ -68,6 +82,7 @@ def tokamak_geometry(draw): def test_creation(tokamak_source): + """Tests that the sources generated by TokamakSource are of type openmc.Source""" for source in tokamak_source.sources: assert isinstance(source, Source) @@ -77,14 +92,16 @@ def test_strengths_are_normalised(tokamak_source): assert pytest.approx(sum(tokamak_source.strengths), 1) -@given(geometry=tokamak_geometry()) -@settings(max_examples=100,deadline=None) +@given(geometry=tokamak_geometry_strategy()) +@settings(max_examples=100, deadline=None) def test_source_locations_are_within_correct_range(geometry, tokamak_plasma_input): """Tests that each source has RZ locations within the expected range. - Note that this test is not wholly accurate, as it only ensures that - R and Z fall within a box defined by the lower-left point (R_min,Z_min) - and upper-right point (R_max,Z_max), and does not account for the - actual expected plasma geometry. + As the function converting (a,alpha) coordinates to (R,Z) is not bijective, we + cannot convert back to validate each individual point. However, we can determine + whether the generated points are contained within the shell of the last closed + magnetic surface. + See "Tokamak D-T neutron source models for different plasma physics confinement + modes", C. Fausser et al., Fusion Engineering and Design, 2012 for more info. """ tokamak_source = TokamakSource(**geometry, **tokamak_plasma_input) R_0 = geometry["major_radius"] @@ -92,9 +109,10 @@ def test_source_locations_are_within_correct_range(geometry, tokamak_plasma_inpu El = geometry["elongation"] delta = geometry["triangularity"] - def get_R(alpha): + def get_R_on_LCMS(alpha): + """Gets R on the last closed magnetic surface for a given alpha""" return R_0 + A * np.cos(alpha + delta * np.sin(alpha)) - + for source in tokamak_source.sources: R, Z = source.space.r.x[0], source.space.z.x[0] # First test that the point is contained with a simple box with @@ -107,7 +125,7 @@ def get_R(alpha): # lower bounds for R. alpha_1 = np.arcsin(abs(Z) / (El * A)) alpha_2 = np.pi - alpha_1 - R_max, R_min = get_R(alpha_1), get_R(alpha_2) + R_max, R_min = get_R_on_LCMS(alpha_1), get_R_on_LCMS(alpha_2) assert R_max < R_0 + A or np.isclose(R_max, R_0 + A) assert R_min > R_0 - A or np.isclose(R_min, R_0 - A) assert R < R_max or np.isclose(R, R_max) From ecff5592a8884560ee0dfe09751424adc8b32865 Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Wed, 26 Jan 2022 15:45:21 +0000 Subject: [PATCH 5/7] Added hypothesis to circleci config --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index b2691e1..81d58cb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,6 +9,8 @@ jobs: - run: name: install command: | + python -m pip install --upgrade pip + python -m pip install pytest hypothesis python setup.py install apt-get update -y && apt-get install -y curl - run: From 108fa72df0ba915b6cabddc443d05ca734fa730d Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Thu, 27 Jan 2022 13:36:51 +0000 Subject: [PATCH 6/7] Improved readability of tokamak source tests --- tests/test_tokamak_source.py | 127 ++++++++++++++--------------------- 1 file changed, 51 insertions(+), 76 deletions(-) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index fed9365..b30d377 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -5,55 +5,11 @@ import pytest from hypothesis import given, settings, assume, strategies as st - -@pytest.fixture(scope="module") -def tokamak_plasma_input(): - """Defines a fixed set of plasma inputs, known to be valid.""" - return { - "ion_density_centre": 1.09e20, - "ion_density_peaking_factor": 1, - "ion_density_pedestal": 1.09e20, - "ion_density_separatrix": 3e19, - "ion_temperature_centre": 45.9, - "ion_temperature_peaking_factor": 8.06, - "ion_temperature_pedestal": 6.09, - "ion_temperature_separatrix": 0.1, - "mode": "H", - "ion_temperature_beta": 6, - } - - -@pytest.fixture(scope="module") -def tokamak_geometry_input(): - """Defines a fixed set of tokamak geometry inputs, known to be valid.""" - return { - "elongation": 1.557, - "triangularity": 0.270, - "major_radius": 9.06, - "minor_radius": 2.92258, - "pedestal_radius": 0.8 * 2.92258, - "shafranov_factor": 0.44789, - } - - -@pytest.fixture(scope="module") -def tokamak_input(tokamak_plasma_input, tokamak_geometry_input): - """ Combines the plasma input and geometry input fixtures for convenience.""" - return {**tokamak_plasma_input, **tokamak_geometry_input} - - -@pytest.fixture(scope="function") -def tokamak_source(tokamak_input): - """Creates example of a TokamakSource with inputs known to be valid. - Note that this fixture is rebuilt for each function call. - """ - return TokamakSource(**tokamak_input) - - @st.composite -def tokamak_geometry_strategy(draw): - """Defines a hypothesis strategy that automatically generates dictionaries of - tokamak geometry inputs. +def tokamak_source_strategy(draw,return_dict=False): + """Defines a hypothesis strategy that automatically generates a TokamakSource. + When passed `return_dict=True`, only a dict of the args is passed. + Geometry attributes are varied, while plasma attributes are fixed. """ # Used to avoid generation of inappropriate float values finites = {"allow_nan": False, "allow_infinity": False, "allow_subnormal": False} @@ -63,7 +19,7 @@ def tokamak_geometry_strategy(draw): major_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) pedestal_radius = draw(st.floats(min_value=0.0, max_value=100.0, **finites)) elongation = draw(st.floats(min_value=1.0, max_value=10.0, **finites)) - triangularity = draw(st.floats(min_value=0.0, max_value=1.0, **finites)) + triangularity = draw(st.floats(min_value=-1.0, max_value=1.0, **finites)) shafranov_factor = draw(st.floats(min_value=0.0, max_value=1.0, **finites)) # Specify requirements that must be satisfied for a valid tokamak @@ -71,30 +27,46 @@ def tokamak_geometry_strategy(draw): assume(minor_radius > pedestal_radius) assume(minor_radius > shafranov_factor) - return { - "elongation": elongation, - "triangularity": triangularity, - "major_radius": major_radius, - "minor_radius": minor_radius, - "pedestal_radius": pedestal_radius, - "shafranov_factor": shafranov_factor, + args_dict = { + "elongation" : elongation, + "triangularity" : triangularity, + "major_radius" : major_radius, + "minor_radius" : minor_radius, + "pedestal_radius" : pedestal_radius, + "shafranov_factor" : shafranov_factor, + "ion_density_centre" : 1.09e20, + "ion_density_peaking_factor" : 1, + "ion_density_pedestal" : 1.09e20, + "ion_density_separatrix" : 3e19, + "ion_temperature_centre" : 45.9, + "ion_temperature_peaking_factor" : 8.06, + "ion_temperature_pedestal" : 6.09, + "ion_temperature_separatrix" : 0.1, + "mode" : "H", + "ion_temperature_beta" : 6, } + return args_dict if return_dict else TokamakSource(**args_dict) + +@given(tokamak_source=tokamak_source_strategy()) +@settings(max_examples=1, deadline=None) def test_creation(tokamak_source): """Tests that the sources generated by TokamakSource are of type openmc.Source""" for source in tokamak_source.sources: assert isinstance(source, Source) +@given(tokamak_source=tokamak_source_strategy()) +@settings(max_examples=100, deadline=None) def test_strengths_are_normalised(tokamak_source): """Tests that the sum of the strengths attribute is equal to""" assert pytest.approx(sum(tokamak_source.strengths), 1) -@given(geometry=tokamak_geometry_strategy()) +@given(tokamak_source=tokamak_source_strategy()) @settings(max_examples=100, deadline=None) -def test_source_locations_are_within_correct_range(geometry, tokamak_plasma_input): +def test_source_locations_are_within_correct_range(tokamak_source): """Tests that each source has RZ locations within the expected range. As the function converting (a,alpha) coordinates to (R,Z) is not bijective, we cannot convert back to validate each individual point. However, we can determine @@ -103,40 +75,43 @@ def test_source_locations_are_within_correct_range(geometry, tokamak_plasma_inpu See "Tokamak D-T neutron source models for different plasma physics confinement modes", C. Fausser et al., Fusion Engineering and Design, 2012 for more info. """ - tokamak_source = TokamakSource(**geometry, **tokamak_plasma_input) - R_0 = geometry["major_radius"] - A = geometry["minor_radius"] - El = geometry["elongation"] - delta = geometry["triangularity"] + R_0 = tokamak_source.major_radius + A = tokamak_source.minor_radius + El = tokamak_source.elongation + delta = tokamak_source.triangularity def get_R_on_LCMS(alpha): """Gets R on the last closed magnetic surface for a given alpha""" return R_0 + A * np.cos(alpha + delta * np.sin(alpha)) + approx_lt = lambda x,y : x < y or np.isclose(x,y) + approx_gt = lambda x,y : x > y or np.isclose(x,y) + for source in tokamak_source.sources: R, Z = source.space.r.x[0], source.space.z.x[0] # First test that the point is contained with a simple box with # lower left (r_min,-z_max) and upper right (r_max,z_max) - assert R > R_0 - A or np.isclose(R, R_0 - A) - assert R < R_0 + A or np.isclose(R, R_0 + A) - assert abs(Z) < A * El or np.isclose(abs(Z), A * El) + assert approx_gt(R,R_0 - A) + assert approx_lt(R,R_0 + A) + assert approx_lt(abs(Z), A*El) # For a given Z, we can determine the two values of alpha where # where a = minor_radius, and from there determine the upper and # lower bounds for R. alpha_1 = np.arcsin(abs(Z) / (El * A)) alpha_2 = np.pi - alpha_1 R_max, R_min = get_R_on_LCMS(alpha_1), get_R_on_LCMS(alpha_2) - assert R_max < R_0 + A or np.isclose(R_max, R_0 + A) - assert R_min > R_0 - A or np.isclose(R_min, R_0 - A) - assert R < R_max or np.isclose(R, R_max) - assert R > R_min or np.isclose(R, R_min) + assert approx_lt(R_max,R_0+A) + assert approx_gt(R_min,R_0-A) + assert approx_lt(R, R_max) + assert approx_gt(R, R_min) -def test_angles(tokamak_input): +@given(tokamak_args_dict=tokamak_source_strategy(return_dict=True)) +@settings(max_examples=1, deadline=None) +def test_angles(tokamak_args_dict): """Checks that custom angles can be set""" - alt_input = tokamak_input.copy() - alt_input["angles"] = (0, 1) - alt_source = TokamakSource(**alt_input) - assert alt_source.angles == (0, 1) - for source in alt_source.sources: + tokamak_args_dict["angles"] = (0, 1) + tokamak_source = TokamakSource(**tokamak_args_dict) + assert tokamak_source.angles == (0, 1) + for source in tokamak_source.sources: assert (source.space.phi.a, source.space.phi.b) == (0, 1) From edbc0b2e52d7a35ca06d8ffe3abe197b62c0e10b Mon Sep 17 00:00:00 2001 From: Liam Pattinson Date: Thu, 27 Jan 2022 18:22:36 +0000 Subject: [PATCH 7/7] PEP8 formatting update --- tests/test_tokamak_source.py | 49 ++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/tests/test_tokamak_source.py b/tests/test_tokamak_source.py index b30d377..ca28b77 100644 --- a/tests/test_tokamak_source.py +++ b/tests/test_tokamak_source.py @@ -5,8 +5,9 @@ import pytest from hypothesis import given, settings, assume, strategies as st + @st.composite -def tokamak_source_strategy(draw,return_dict=False): +def tokamak_source_strategy(draw, return_dict=False): """Defines a hypothesis strategy that automatically generates a TokamakSource. When passed `return_dict=True`, only a dict of the args is passed. Geometry attributes are varied, while plasma attributes are fixed. @@ -28,22 +29,22 @@ def tokamak_source_strategy(draw,return_dict=False): assume(minor_radius > shafranov_factor) args_dict = { - "elongation" : elongation, - "triangularity" : triangularity, - "major_radius" : major_radius, - "minor_radius" : minor_radius, - "pedestal_radius" : pedestal_radius, - "shafranov_factor" : shafranov_factor, - "ion_density_centre" : 1.09e20, - "ion_density_peaking_factor" : 1, - "ion_density_pedestal" : 1.09e20, - "ion_density_separatrix" : 3e19, - "ion_temperature_centre" : 45.9, - "ion_temperature_peaking_factor" : 8.06, - "ion_temperature_pedestal" : 6.09, - "ion_temperature_separatrix" : 0.1, - "mode" : "H", - "ion_temperature_beta" : 6, + "elongation": elongation, + "triangularity": triangularity, + "major_radius": major_radius, + "minor_radius": minor_radius, + "pedestal_radius": pedestal_radius, + "shafranov_factor": shafranov_factor, + "ion_density_centre": 1.09e20, + "ion_density_peaking_factor": 1, + "ion_density_pedestal": 1.09e20, + "ion_density_separatrix": 3e19, + "ion_temperature_centre": 45.9, + "ion_temperature_peaking_factor": 8.06, + "ion_temperature_pedestal": 6.09, + "ion_temperature_separatrix": 0.1, + "mode": "H", + "ion_temperature_beta": 6, } return args_dict if return_dict else TokamakSource(**args_dict) @@ -84,24 +85,24 @@ def get_R_on_LCMS(alpha): """Gets R on the last closed magnetic surface for a given alpha""" return R_0 + A * np.cos(alpha + delta * np.sin(alpha)) - approx_lt = lambda x,y : x < y or np.isclose(x,y) - approx_gt = lambda x,y : x > y or np.isclose(x,y) + approx_lt = lambda x, y: x < y or np.isclose(x, y) + approx_gt = lambda x, y: x > y or np.isclose(x, y) for source in tokamak_source.sources: R, Z = source.space.r.x[0], source.space.z.x[0] # First test that the point is contained with a simple box with # lower left (r_min,-z_max) and upper right (r_max,z_max) - assert approx_gt(R,R_0 - A) - assert approx_lt(R,R_0 + A) - assert approx_lt(abs(Z), A*El) + assert approx_gt(R, R_0 - A) + assert approx_lt(R, R_0 + A) + assert approx_lt(abs(Z), A * El) # For a given Z, we can determine the two values of alpha where # where a = minor_radius, and from there determine the upper and # lower bounds for R. alpha_1 = np.arcsin(abs(Z) / (El * A)) alpha_2 = np.pi - alpha_1 R_max, R_min = get_R_on_LCMS(alpha_1), get_R_on_LCMS(alpha_2) - assert approx_lt(R_max,R_0+A) - assert approx_gt(R_min,R_0-A) + assert approx_lt(R_max, R_0 + A) + assert approx_gt(R_min, R_0 - A) assert approx_lt(R, R_max) assert approx_gt(R, R_min)