diff --git a/.gitignore b/.gitignore index 3454259..4ff8bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -229,3 +229,6 @@ examples/mesh_plot/ thincurr_scratch/ scratch/ synthwave/vessel_caches + +# No figure storage to git, at least of pdfs +*.pdf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5b6d53..0d0839d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,19 +10,19 @@ repos: entry: uv run jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace - id: ruff_format name: ruff_format - entry: uv run ruff format + entry: uv run --no-sync ruff format language: system types: [python] files: "^synthwave/" - id: ruff_check name: ruff_check - entry: uv run ruff check --fix + entry: uv run --no-sync ruff check --fix language: system types: [python] files: "^synthwave/" - id: isort name: isort - entry: uv run isort + entry: uv run --no-sync isort language: system types: [python] files: "^synthwave/" \ No newline at end of file diff --git a/alpha_lhs_new.pdf b/alpha_lhs_new.pdf new file mode 100644 index 0000000..f13d998 Binary files /dev/null and b/alpha_lhs_new.pdf differ diff --git a/alpha_new.pdf b/alpha_new.pdf new file mode 100644 index 0000000..8a8d805 Binary files /dev/null and b/alpha_new.pdf differ diff --git a/alpha_old.pdf b/alpha_old.pdf new file mode 100644 index 0000000..a6a2571 Binary files /dev/null and b/alpha_old.pdf differ diff --git a/alpha_rhs_new.pdf b/alpha_rhs_new.pdf new file mode 100644 index 0000000..1be1bdd Binary files /dev/null and b/alpha_rhs_new.pdf differ diff --git a/eBp_mew_alpha.pdf b/eBp_mew_alpha.pdf new file mode 100644 index 0000000..9a6ffc7 Binary files /dev/null and b/eBp_mew_alpha.pdf differ diff --git a/eBp_old_alpha.pdf b/eBp_old_alpha.pdf new file mode 100644 index 0000000..9613a05 Binary files /dev/null and b/eBp_old_alpha.pdf differ diff --git a/output_plots/filament_pyvista/mode_m2_n1_filament_phase_comparison_174956_NewPhiCorrection.pdf b/output_plots/filament_pyvista/mode_m2_n1_filament_phase_comparison_174956_NewPhiCorrection.pdf new file mode 100644 index 0000000..2822f21 Binary files /dev/null and b/output_plots/filament_pyvista/mode_m2_n1_filament_phase_comparison_174956_NewPhiCorrection.pdf differ diff --git a/output_plots/filament_pyvista/mode_m3_n1_filament_phase_comparison_175028.pdf b/output_plots/filament_pyvista/mode_m3_n1_filament_phase_comparison_175028.pdf new file mode 100644 index 0000000..743276b Binary files /dev/null and b/output_plots/filament_pyvista/mode_m3_n1_filament_phase_comparison_175028.pdf differ diff --git a/output_plots/filament_pyvista/mode_m4_n1_filament_phase_comparison_175028.pdf b/output_plots/filament_pyvista/mode_m4_n1_filament_phase_comparison_175028.pdf new file mode 100644 index 0000000..b11b991 Binary files /dev/null and b/output_plots/filament_pyvista/mode_m4_n1_filament_phase_comparison_175028.pdf differ diff --git a/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028.pdf b/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028.pdf new file mode 100644 index 0000000..2c9a0a0 Binary files /dev/null and b/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028.pdf differ diff --git a/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028_NewPhiCorrection.pdf b/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028_NewPhiCorrection.pdf new file mode 100644 index 0000000..2ae70bd Binary files /dev/null and b/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028_NewPhiCorrection.pdf differ diff --git a/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028_NoPhiCorrection.pdf b/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028_NoPhiCorrection.pdf new file mode 100644 index 0000000..9f62b57 Binary files /dev/null and b/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_175028_NoPhiCorrection.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m1_n1_theta_phi_contours_1120906030.pdf b/output_plots/theta_phi_contours/mode_m1_n1_theta_phi_contours_1120906030.pdf new file mode 100644 index 0000000..2865865 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m1_n1_theta_phi_contours_1120906030.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m2_n1_measured_phase_comparison_174956.pdf b/output_plots/theta_phi_contours/mode_m2_n1_measured_phase_comparison_174956.pdf new file mode 100644 index 0000000..9f5a994 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m2_n1_measured_phase_comparison_174956.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m2_n1_phase_comparison_175028.pdf b/output_plots/theta_phi_contours/mode_m2_n1_phase_comparison_175028.pdf new file mode 100644 index 0000000..623dc3c Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m2_n1_phase_comparison_175028.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_1120906030.pdf b/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_1120906030.pdf new file mode 100644 index 0000000..fbff439 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_1120906030.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_174956.pdf b/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_174956.pdf new file mode 100644 index 0000000..bc1bf1a Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_174956.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_175028.pdf b/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_175028.pdf new file mode 100644 index 0000000..cd5182f Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m2_n1_theta_phi_contours_175028.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m3_n1_measured_phase_comparison_174956.pdf b/output_plots/theta_phi_contours/mode_m3_n1_measured_phase_comparison_174956.pdf new file mode 100644 index 0000000..5136065 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m3_n1_measured_phase_comparison_174956.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m3_n1_phase_comparison_175028.pdf b/output_plots/theta_phi_contours/mode_m3_n1_phase_comparison_175028.pdf new file mode 100644 index 0000000..c2b0d23 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m3_n1_phase_comparison_175028.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m3_n1_theta_phi_contours_174956.pdf b/output_plots/theta_phi_contours/mode_m3_n1_theta_phi_contours_174956.pdf new file mode 100644 index 0000000..13704d1 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m3_n1_theta_phi_contours_174956.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m3_n1_theta_phi_contours_175028.pdf b/output_plots/theta_phi_contours/mode_m3_n1_theta_phi_contours_175028.pdf new file mode 100644 index 0000000..ea81425 Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m3_n1_theta_phi_contours_175028.pdf differ diff --git a/output_plots/theta_phi_contours/mode_m5_n1_theta_phi_contours_1120906030.pdf b/output_plots/theta_phi_contours/mode_m5_n1_theta_phi_contours_1120906030.pdf new file mode 100644 index 0000000..bb29fac Binary files /dev/null and b/output_plots/theta_phi_contours/mode_m5_n1_theta_phi_contours_1120906030.pdf differ diff --git a/synthwave/output_plots/filament_pyvista/mode_m2_n1_filament_phase_comparison_tars_input_180516_NewPhiCorrection.pdf b/synthwave/output_plots/filament_pyvista/mode_m2_n1_filament_phase_comparison_tars_input_180516_NewPhiCorrection.pdf new file mode 100644 index 0000000..11ec5c6 Binary files /dev/null and b/synthwave/output_plots/filament_pyvista/mode_m2_n1_filament_phase_comparison_tars_input_180516_NewPhiCorrection.pdf differ diff --git a/synthwave/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_tars_input_180516_DIII_D_Sensors.pdf b/synthwave/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_tars_input_180516_DIII_D_Sensors.pdf new file mode 100644 index 0000000..f4b107b Binary files /dev/null and b/synthwave/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_tars_input_180516_DIII_D_Sensors.pdf differ diff --git a/synthwave/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_tars_input_180516_DIII_D_Sensors_Only.pdf b/synthwave/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_tars_input_180516_DIII_D_Sensors_Only.pdf new file mode 100644 index 0000000..941c1ef Binary files /dev/null and b/synthwave/output_plots/filament_pyvista/mode_m5_n1_filament_phase_comparison_tars_input_180516_DIII_D_Sensors_Only.pdf differ diff --git a/synthwave/tests/conftest.py b/synthwave/tests/conftest.py index f522110..8df11bf 100644 --- a/synthwave/tests/conftest.py +++ b/synthwave/tests/conftest.py @@ -9,6 +9,7 @@ import gc import pytest +from OpenFUSIONToolkit import OFT_env def pytest_configure(config): @@ -27,3 +28,9 @@ def _serial_gc(request): yield if request.node.get_closest_marker("serial"): gc.collect() + + +# Fixture for OFT environment so only one is created for all tests. +@pytest.fixture(scope="session") +def oft_env(): + return OFT_env(nthreads=2) diff --git a/synthwave/tests/test_direct_response.py b/synthwave/tests/test_direct_response.py index e10cfd6..979be46 100644 --- a/synthwave/tests/test_direct_response.py +++ b/synthwave/tests/test_direct_response.py @@ -17,7 +17,6 @@ import numpy as np import pytest import xarray as xr -from OpenFUSIONToolkit import OFT_env from synthwave import PACKAGE_ROOT from synthwave.magnetic_geometry.equilibrium_field import ( @@ -35,7 +34,10 @@ direct_response_thincurr, ) -# ThinCurr / OFT_env hold global C++ state that cannot be shared across workers +# All tests in this file use the OpenFUSIONToolkit C++ library which has +# global state (OFT_env, ThinCurr) that cannot be shared across concurrent +# workers. Mark the entire module serial so the conftest fixture forces +# sequential execution and GC cleanup between tests. pytestmark = pytest.mark.serial _CMOD_DIR = os.path.join(PACKAGE_ROOT, "input_data", "cmod") @@ -48,11 +50,6 @@ _BASE_NUM_POINTS = 100 -@pytest.fixture(scope="module") -def oft_env(): - return OFT_env(nthreads=2) - - @pytest.fixture(scope="module") def sensor_details(): """Load the C-Mod Mirnov set and conform it to the OFT/Biot-Savart schema. @@ -169,7 +166,7 @@ def test_thincurr_phase_matches_biot_savart(oft_env, direct_response_inputs): gen_OFT_filament_and_eta_file( working_directory=tmpdir, filament_list=filament_list, - resistivity_list=[1e-6] * len(filament_list), + resistivity_list=[1e-6], ) sensor_file_path = gen_OFT_sensors_file( sensor_details=sensor_details, diff --git a/synthwave/tests/test_equilibrium_field.py b/synthwave/tests/test_equilibrium_field.py index 77429e0..fd6aeff 100644 --- a/synthwave/tests/test_equilibrium_field.py +++ b/synthwave/tests/test_equilibrium_field.py @@ -262,6 +262,21 @@ def test_detect_cocos_cmod(self, eqdsk_cmod): f"Expected COCOS {expected_cocos} for C-Mod, got {cocos}" ) + @pytest.mark.skipif( + condition=not os.path.exists( + os.path.join( + PACKAGE_ROOT, + "..", + "submodules", + "OpenFUSIONToolkit", + "examples", + "TokaMaker", + "DIIID", + "g192185.02440", + ) + ), + reason="Test requires DIII-D data which is not open source", + ) def test_detect_cocos_d3d(self, eqdsk_d3d): """DIII-D uses EFIT convention (sigma_RphiZ=+1, e_Bp=0, psi increasing). COCOS depends on sign(Ip) and sign(B0) @@ -345,7 +360,24 @@ def eqdsk(self, request): "eqdsk", [ "eqdsk_cmod", - "eqdsk_d3d", + pytest.param( + "eqdsk_d3d", + marks=pytest.mark.skipif( + condition=not os.path.exists( + os.path.join( + PACKAGE_ROOT, + "..", + "submodules", + "OpenFUSIONToolkit", + "examples", + "TokaMaker", + "DIIID", + "g192185.02440", + ) + ), + reason="Test requires DIII-D data which is not open source", + ), + ), pytest.param( "eqdsk_tcv", marks=pytest.mark.skipif( @@ -392,7 +424,24 @@ def test_convert_cocos_same(self, eqdsk): "eqdsk", [ "eqdsk_cmod", - "eqdsk_d3d", + pytest.param( + "eqdsk_d3d", + marks=pytest.mark.skipif( + condition=not os.path.exists( + os.path.join( + PACKAGE_ROOT, + "..", + "submodules", + "OpenFUSIONToolkit", + "examples", + "TokaMaker", + "DIIID", + "g192185.02440", + ) + ), + reason="Test requires DIII-D data which is not open source", + ), + ), pytest.param( "eqdsk_tcv", marks=pytest.mark.skipif( @@ -449,7 +498,24 @@ def test_convert_cocos_internal(self, eqdsk): "eqdsk", [ "eqdsk_cmod", - "eqdsk_d3d", + pytest.param( + "eqdsk_d3d", + marks=pytest.mark.skipif( + condition=not os.path.exists( + os.path.join( + PACKAGE_ROOT, + "..", + "submodules", + "OpenFUSIONToolkit", + "examples", + "TokaMaker", + "DIIID", + "g192185.02440", + ) + ), + reason="Test requires DIII-D data which is not open source", + ), + ), pytest.param( "eqdsk_tcv", marks=pytest.mark.skipif( diff --git a/synthwave/tests/test_thincurr.py b/synthwave/tests/test_thincurr.py index dc2f973..eda792c 100644 --- a/synthwave/tests/test_thincurr.py +++ b/synthwave/tests/test_thincurr.py @@ -5,7 +5,6 @@ import numpy as np import pytest import xarray as xr -from OpenFUSIONToolkit import OFT_env from sympy import nextprime from synthwave import PACKAGE_ROOT @@ -31,13 +30,6 @@ pytestmark = pytest.mark.serial -# Fixture for oft environment so only one is created for all tests -@pytest.fixture(scope="session") -def oft_env_fixture(): - oft_env = OFT_env(nthreads=2) - return oft_env - - @pytest.mark.parametrize( "mode", [ @@ -49,7 +41,7 @@ def oft_env_fixture(): ], ids=["m2n1", "m3n2", "m-3n2", "m3n1", "m4n3"], ) -def test_toroidal_angles(mode, oft_env_fixture): +def test_toroidal_angles(mode, oft_env): tolerance_tight = np.deg2rad(1) tolerance_loose = np.deg2rad( 5 @@ -171,7 +163,7 @@ def test_toroidal_angles(mode, oft_env_fixture): ) total_response, direct_response, _vessel_response = frequency_response_thincurr( - oft_env=oft_env_fixture, + oft_env=oft_env, tracer=toroidal_tracer, freq=10e3, mesh_file=torus_mesh_file, @@ -317,7 +309,7 @@ def test_gen_OFT_sensors_file(): assert len(content) > 0 -def test_direct_response_thincurr_matches_frequency_response(oft_env_fixture): +def test_direct_response_thincurr_matches_frequency_response(oft_env): """direct_response_thincurr must return the same direct component as frequency_response_thincurr.""" major_radius = 1 @@ -370,13 +362,11 @@ def test_direct_response_thincurr_matches_frequency_response(oft_env_fixture): filament_list, current_list = toroidal_tracer.get_filament_list( num_filaments=num_filaments ) - gen_OFT_filament_and_eta_file( - working_directory, filament_list, [1e-6] * len(filament_list) - ) + gen_OFT_filament_and_eta_file(working_directory, filament_list, [1e-6]) total_response, direct_response_freq, vessel_response = ( frequency_response_thincurr( - oft_env=oft_env_fixture, + oft_env=oft_env, tracer=toroidal_tracer, freq=10e3, mesh_file=torus_mesh_file, @@ -386,7 +376,7 @@ def test_direct_response_thincurr_matches_frequency_response(oft_env_fixture): ) direct_response_only = direct_response_thincurr( - oft_env=oft_env_fixture, + oft_env=oft_env, tracer=toroidal_tracer, mesh_file=torus_mesh_file, sensor_details=sensor_details,