From 2be42de684e588acb6190d9c85bd04a46d0663c3 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 11:54:31 -0400 Subject: [PATCH 01/45] Roman changes from branch romanc:romanc/pyfms-monitor-ci --- .github/workflows/unit_tests.yaml | 24 +++++++++++++++---- .../monitor/diag_manager_monitor.md | 3 +++ mkdocs.yml | 1 + ndsl/optional_imports.py | 5 ++++ pyproject.toml | 2 ++ tests/monitor/__init__.py | 0 tests/{ => monitor}/test_dm_monitor_cubed.py | 0 tests/{ => monitor}/test_dm_monitor_single.py | 0 tests/{ => monitor}/test_netcdf_monitor.py | 0 tests/{ => monitor}/test_zarr_monitor.py | 0 10 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 docs/docstrings/monitor/diag_manager_monitor.md create mode 100644 tests/monitor/__init__.py rename tests/{ => monitor}/test_dm_monitor_cubed.py (100%) rename tests/{ => monitor}/test_dm_monitor_single.py (100%) rename tests/{ => monitor}/test_netcdf_monitor.py (100%) rename tests/{ => monitor}/test_zarr_monitor.py (100%) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 0e7aa421..0ecdf218 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -19,7 +19,18 @@ jobs: strategy: matrix: python-version: ['3.11', '3.12', '3.13'] - name: Python ${{ matrix.python-version }} + extra: ['test,zarr'] + marker-serial: ['not parallel and not gpu and not pyfms'] + marker-parallel: ['parallel and not gpu and not pyfms'] + include: + # add pyfms tests for 3.12 + - extra: 'test,pyfms' + marker-serial: 'pyfms and not parallel' + marker-parallel: 'pyfms and parallel' + python-version: '3.12' + # don't cancel other jobs if one fails + fail-fast: false + name: Python ${{ matrix.python-version }}${{ contains(matrix.extra, 'pyfms') && ' (pyFMS)' || '' }} steps: - name: Checkout repository uses: actions/checkout@v6 @@ -32,16 +43,21 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install mpi (MPICH flavor) + if: ${{!contains(matrix.extra, 'pyfms')}} run: pip3 install mpich + - name: Install pyFMS dependencies (includes system MPI) + if: contains(matrix.extra, 'pyfms') + run: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + - name: Install Python packages - run: pip3 install .[test,zarr] + run: pip3 install .[${{matrix.extra}}] - name: Run serial cpu tests - run: coverage run --rcfile=pyproject.toml -m pytest -m "not parallel and not gpu" tests + run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests - name: Run parallel cpu tests - run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "parallel and not gpu" tests + run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - name: Output code coverage run: | diff --git a/docs/docstrings/monitor/diag_manager_monitor.md b/docs/docstrings/monitor/diag_manager_monitor.md new file mode 100644 index 00000000..b377bdfa --- /dev/null +++ b/docs/docstrings/monitor/diag_manager_monitor.md @@ -0,0 +1,3 @@ +# diag_manager_monitor + +::: monitor.diag_manager_monitor \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 62b3fbcf..b19fc02a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -75,6 +75,7 @@ nav: - "subtile_grid_sizer": docstrings/initialization/subtile_grid_sizer.md - monitor: - "convert": docstrings/monitor/convert.md + - "diag_manager_monitor": docstrings/monitor/diag_manager_monitor.md - "netcdf_monitor": docstrings/monitor/netcdf_monitor.md - "protocol": docstrings/monitor/protocol.md - "zarr_monitor": docstrings/monitor/zarr_monitor.md diff --git a/ndsl/optional_imports.py b/ndsl/optional_imports.py index 4cc81ea6..af2ec8d0 100644 --- a/ndsl/optional_imports.py +++ b/ndsl/optional_imports.py @@ -17,6 +17,11 @@ def __call__(self, *args: Any, **kwargs: dict) -> None: except ModuleNotFoundError as err: zarr = RaiseWhenAccessed(err) +try: + import pyfms +except ModuleNotFoundError as err: + pyfms = RaiseWhenAccessed(err) + try: import cupy except ImportError: diff --git a/pyproject.toml b/pyproject.toml index 8bce607f..1a7ff3dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,6 +124,8 @@ module = [ markers = [ # tests running on a cpu (e.g. with cupy) "gpu", + # tests relying on the optional pyFMS dependency + "pyfms", # tests relying on at least two MPI processes "parallel", # tests relying on the optional zarr dependency diff --git a/tests/monitor/__init__.py b/tests/monitor/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_dm_monitor_cubed.py b/tests/monitor/test_dm_monitor_cubed.py similarity index 100% rename from tests/test_dm_monitor_cubed.py rename to tests/monitor/test_dm_monitor_cubed.py diff --git a/tests/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py similarity index 100% rename from tests/test_dm_monitor_single.py rename to tests/monitor/test_dm_monitor_single.py diff --git a/tests/test_netcdf_monitor.py b/tests/monitor/test_netcdf_monitor.py similarity index 100% rename from tests/test_netcdf_monitor.py rename to tests/monitor/test_netcdf_monitor.py diff --git a/tests/test_zarr_monitor.py b/tests/monitor/test_zarr_monitor.py similarity index 100% rename from tests/test_zarr_monitor.py rename to tests/monitor/test_zarr_monitor.py From 055148458119712e55f1444a3769ed0e524e84a4 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 12:06:43 -0400 Subject: [PATCH 02/45] Linting --- .github/workflows/unit_tests.yaml | 4 ++-- docs/docstrings/monitor/diag_manager_monitor.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 0ecdf218..89bbc7bf 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -5,8 +5,8 @@ on: pull_request: # ... a PR is opened / updated merge_group: # ... the PR is added to the merge queue push: - branches: - - main # ... when merging into the main branch + # branches: + # - main # ... when merging into the main branch # cancel running jobs if theres a newer push concurrency: diff --git a/docs/docstrings/monitor/diag_manager_monitor.md b/docs/docstrings/monitor/diag_manager_monitor.md index b377bdfa..36b92e81 100644 --- a/docs/docstrings/monitor/diag_manager_monitor.md +++ b/docs/docstrings/monitor/diag_manager_monitor.md @@ -1,3 +1,3 @@ # diag_manager_monitor -::: monitor.diag_manager_monitor \ No newline at end of file +::: monitor.diag_manager_monitor From 319320bad74204946aba069e93e0b3ac96997b50 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 12:19:16 -0400 Subject: [PATCH 03/45] Fixing apt-get update in pyFMS workflow --- .github/workflows/unit_tests.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 89bbc7bf..b077b83c 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,7 +48,9 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: | + sudo apt-get update --fix-missing + sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: pip3 install .[${{matrix.extra}}] From 9e05a012cf7594b714070043c4570e46e2ca91f7 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 12:41:41 -0400 Subject: [PATCH 04/45] Using open_dataset instead of open_mfdataset in diag_manager monitor tests --- tests/monitor/test_dm_monitor_cubed.py | 2 +- tests/monitor/test_dm_monitor_single.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/monitor/test_dm_monitor_cubed.py b/tests/monitor/test_dm_monitor_cubed.py index a1ec8c59..79b4d426 100644 --- a/tests/monitor/test_dm_monitor_cubed.py +++ b/tests/monitor/test_dm_monitor_cubed.py @@ -203,7 +203,7 @@ def test_dm_monitor(): pe = MPIComm()._comm.Get_rank() + 1 filename = "diag_manager_cubed_sphere.tile" + str(pe) + ".nc" assert Path(filename).exists() - ds = xr.open_mfdataset(filename, decode_times=True) + ds = xr.open_dataset(filename, decode_times=True) assert "var1" in ds np.testing.assert_array_equal(ds["var1"].shape, (ntimesteps, ny, nx)) assert "var2" in ds diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index f8c86328..f5411aca 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -220,7 +220,7 @@ def test_dm_monitor_single_tile(): # check output! assert Path("diag_manager_single_tile.nc").exists() - ds = xr.open_mfdataset("diag_manager_single_tile.nc", decode_times=True) + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) assert ds["var_2d"].dims == ("time", "y", "x") From c67041a39db9dd5a811074cfb38bcd0719ee1f65 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 12:47:56 -0400 Subject: [PATCH 05/45] Matching romanc version of tests --- tests/monitor/test_dm_monitor_cubed.py | 12 +++++------- tests/monitor/test_dm_monitor_single.py | 12 +++++------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/tests/monitor/test_dm_monitor_cubed.py b/tests/monitor/test_dm_monitor_cubed.py index 79b4d426..546647e4 100644 --- a/tests/monitor/test_dm_monitor_cubed.py +++ b/tests/monitor/test_dm_monitor_cubed.py @@ -21,9 +21,7 @@ ) from ndsl.config import Backend from ndsl.initialization import SubtileGridSizer - - -pyfms = pytest.importorskip("pyfms") +from ndsl.optional_imports import pyfms # init fms mpi and set up a simple domain @@ -52,7 +50,7 @@ def fms_mpp_init(): return domain_id -def _create_input(reduction: str = "none"): +def _create_input(reduction: str = "none") -> None: diag_config = { "title": "ndsl_diag_manager_test", "base_date": "1 1 1 0 0 0", @@ -89,9 +87,9 @@ def _create_input(reduction: str = "none"): # Simple test, uses a lat/lon grid and (1, npes) layout +@pytest.mark.pyfms @pytest.mark.parallel -def test_dm_monitor(): - +def test_dm_monitor() -> None: npes = MPIComm()._comm.Get_size() if npes % 6 != 0: raise RuntimeError("this test requires npes to be a multiple of 6 to run") @@ -223,4 +221,4 @@ def test_dm_monitor(): np.testing.assert_array_equal(ds["var2"].values[1, :, :, :], 4) np.testing.assert_array_equal(ds["var2"].values[2, :, :, :], 6) - pyfms.fms.end() + pyfms.fms.end() \ No newline at end of file diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index f5411aca..661d904a 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -22,12 +22,10 @@ ) from ndsl.config import Backend from ndsl.initialization import SubtileGridSizer +from ndsl.optional_imports import pyfms -pyfms = pytest.importorskip("pyfms") - - -def _create_input(reduction: str = "none"): +def _create_input() -> None: diag_config = { "title": "ndsl_diag_manager_test", "base_date": "2 1 1 1 1 1", @@ -63,10 +61,10 @@ def _create_input(reduction: str = "none"): f.write(text_content) -def test_dm_monitor_single_tile(): +@pytest.mark.pyfms +def test_dm_monitor_single_tile() -> None: # mpi info npes = MPIComm()._comm.Get_size() - pe = MPIComm()._comm.Get_rank() # tile parameters for quantities/domains nx = 8 ny = 8 @@ -246,4 +244,4 @@ def test_dm_monitor_single_tile(): ds["var_3d"].values[2, :, :, :], var3_global.transpose() ) - pyfms.fms.end() + pyfms.fms.end() \ No newline at end of file From 7a15106640c201abbad522b0185ee1f628dc108e Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 12:48:44 -0400 Subject: [PATCH 06/45] Linting --- .github/workflows/unit_tests.yaml | 2 +- tests/monitor/test_dm_monitor_cubed.py | 2 +- tests/monitor/test_dm_monitor_single.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index b077b83c..5f0a19ba 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -49,7 +49,7 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') run: | - sudo apt-get update --fix-missing + sudo apt-get update --fix-missing sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages diff --git a/tests/monitor/test_dm_monitor_cubed.py b/tests/monitor/test_dm_monitor_cubed.py index 546647e4..5fa2bd82 100644 --- a/tests/monitor/test_dm_monitor_cubed.py +++ b/tests/monitor/test_dm_monitor_cubed.py @@ -221,4 +221,4 @@ def test_dm_monitor() -> None: np.testing.assert_array_equal(ds["var2"].values[1, :, :, :], 4) np.testing.assert_array_equal(ds["var2"].values[2, :, :, :], 6) - pyfms.fms.end() \ No newline at end of file + pyfms.fms.end() diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 661d904a..2671437c 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -244,4 +244,4 @@ def test_dm_monitor_single_tile() -> None: ds["var_3d"].values[2, :, :, :], var3_global.transpose() ) - pyfms.fms.end() \ No newline at end of file + pyfms.fms.end() From 0521b8a000c0f0d3d48d4c0294a62603c25f80b8 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 13:00:13 -0400 Subject: [PATCH 07/45] Looking at pip list in unit_tests --- .github/workflows/unit_tests.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 5f0a19ba..c8290116 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -53,7 +53,9 @@ jobs: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: pip3 install .[${{matrix.extra}}] + run: | + pip3 install .[${{matrix.extra}}] + pip3 list - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests From fc4b13d5b984928f596fb3e6dbc93ed55b8d2ce3 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 13:26:55 -0400 Subject: [PATCH 08/45] Checking non-pip installed netcdf version --- .github/workflows/unit_tests.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index c8290116..81317146 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -56,6 +56,7 @@ jobs: run: | pip3 install .[${{matrix.extra}}] pip3 list + nc-config --version - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests From c410f2233b32d45fea3f93e519a3c5ace53585fe Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 13:41:45 -0400 Subject: [PATCH 09/45] Print statements to debug dm_monitor single test --- .github/workflows/unit_tests.yaml | 6 ++---- tests/monitor/test_dm_monitor_single.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 81317146..3f68df2a 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -55,14 +55,12 @@ jobs: - name: Install Python packages run: | pip3 install .[${{matrix.extra}}] - pip3 list - nc-config --version - name: Run serial cpu tests - run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests + run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests - name: Run parallel cpu tests - run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests + run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests - name: Output code coverage run: | diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 2671437c..1c4c8028 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -77,10 +77,17 @@ def test_dm_monitor_single_tile() -> None: layout_ndsl = (npes, 1) # flipped to match fms domain decomposition global_indices = [0, nx - 1, 0, ny - 1] + print("") + print("INITIALIZED ALL VARIABLES") + _create_input() + print("PASSED CALL TO _CREATE_INPUT") + pyfms.fms.init(localcomm=MPIComm()._comm.py2f(), calendar_type=pyfms.fms.NOLEAP) + print("pyFMS initialized") + domain = pyfms.mpp_domains.define_domains( global_indices=global_indices, layout=layout_fms, @@ -92,6 +99,8 @@ def test_dm_monitor_single_tile() -> None: io_layout=io_layout, ) + print("Domains defined") + if npes > 1: rank = MPIComm()._comm.Get_rank() print(f"intializing partitioner/communicator rank {rank} of {npes}") @@ -119,12 +128,16 @@ def test_dm_monitor_single_tile() -> None: ) quantity_factory = QuantityFactory(sizer, backend=backend) + print("NDSL stuff created") + # set up for diag manager for before the main loop, need to set timestep + end_time and register all axes and fields monitor = DiagManagerMonitor(domain_id=domain_id) start = datetime(2, 1, 1, 1, 1, 1) step = timedelta(seconds=3600) end = start + ntimesteps * step + print("diag_manager Monitor created") + monitor.set_timestep(step) monitor.set_end_time(end) @@ -182,6 +195,8 @@ def test_dm_monitor_single_tile() -> None: assert "var_2d" in monitor.fields assert "var_3d" in monitor.fields + print("Checks on monitor field registers done") + # set up data to send for diagnostics var2_global = np.empty(shape=(nx, ny), dtype=np.float64) var3_global = np.empty(shape=(nx, ny, nz), dtype=np.float64) @@ -216,9 +231,12 @@ def test_dm_monitor_single_tile() -> None: # cleanup writes and closes the file monitor.cleanup() + print("Monitor cleaned up") + # check output! assert Path("diag_manager_single_tile.nc").exists() ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + print("Dataset opened through xarray") assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) assert ds["var_2d"].dims == ("time", "y", "x") From 6cd2d282a16e01f286df281c5aa14f4e0cacbb35 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 14:45:59 -0400 Subject: [PATCH 10/45] Commenting out xarray Dataset accessing calls in test_dm_monitor_single --- tests/monitor/test_dm_monitor_single.py | 54 ++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 1c4c8028..d7e271d1 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -234,32 +234,32 @@ def test_dm_monitor_single_tile() -> None: print("Monitor cleaned up") # check output! - assert Path("diag_manager_single_tile.nc").exists() - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) - print("Dataset opened through xarray") - assert "var_2d" in ds - np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) - assert ds["var_2d"].dims == ("time", "y", "x") - assert ds["var_2d"].attrs["units"] == "muntin" - assert ds["var_3d"].dims == ("time", "z", "y", "x") - assert ds["var_3d"].attrs["units"] == "muntin" - assert ds["time"].shape == (ntimesteps,) - assert ds["time"].dims == ("time",) - assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) - np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) - np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) - # data is transposed when passed into fortran - np.testing.assert_array_equal( - ds["var_3d"].values[0, :, :, :], var3_global.transpose() - ) - np.testing.assert_array_equal( - ds["var_3d"].values[1, :, :, :], var3_global.transpose() - ) - np.testing.assert_array_equal( - ds["var_3d"].values[2, :, :, :], var3_global.transpose() - ) + # assert Path("diag_manager_single_tile.nc").exists() + # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + # print("Dataset opened through xarray") + # assert "var_2d" in ds + # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) + # assert ds["var_2d"].dims == ("time", "y", "x") + # assert ds["var_2d"].attrs["units"] == "muntin" + # assert ds["var_3d"].dims == ("time", "z", "y", "x") + # assert ds["var_3d"].attrs["units"] == "muntin" + # assert ds["time"].shape == (ntimesteps,) + # assert ds["time"].dims == ("time",) + # assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + # assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + # assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + # np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) + # # data is transposed when passed into fortran + # np.testing.assert_array_equal( + # ds["var_3d"].values[0, :, :, :], var3_global.transpose() + # ) + # np.testing.assert_array_equal( + # ds["var_3d"].values[1, :, :, :], var3_global.transpose() + # ) + # np.testing.assert_array_equal( + # ds["var_3d"].values[2, :, :, :], var3_global.transpose() + # ) pyfms.fms.end() From 0131b9715ced008ee0491f8fecffd484e57803d3 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 5 May 2026 14:53:47 -0400 Subject: [PATCH 11/45] Adding back in assert of Path in test_dm_monitor_single --- tests/monitor/test_dm_monitor_single.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index d7e271d1..b5559cb1 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -234,7 +234,7 @@ def test_dm_monitor_single_tile() -> None: print("Monitor cleaned up") # check output! - # assert Path("diag_manager_single_tile.nc").exists() + assert Path("diag_manager_single_tile.nc").exists() # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) # print("Dataset opened through xarray") # assert "var_2d" in ds From 7715c0ca5724fcbafd6cf615ff38cbdd8c6a6aee Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 11:09:00 -0400 Subject: [PATCH 12/45] Moving through dm_monitor_single --- .github/workflows/unit_tests.yaml | 2 +- tests/monitor/test_dm_monitor_single.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 3f68df2a..d606442b 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -60,7 +60,7 @@ jobs: run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests - name: Run parallel cpu tests - run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests + run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests - name: Output code coverage run: | diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index b5559cb1..fbc09348 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -235,7 +235,7 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) # print("Dataset opened through xarray") # assert "var_2d" in ds # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) From 98c48040aa160449bcb9f914be6f46488fc7dce8 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 11:20:59 -0400 Subject: [PATCH 13/45] ALways install mpich and checking xarray call without time decode --- .github/workflows/unit_tests.yaml | 6 +++--- tests/monitor/test_dm_monitor_single.py | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index d606442b..66482b51 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -43,18 +43,18 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install mpi (MPICH flavor) - if: ${{!contains(matrix.extra, 'pyfms')}} + # if: ${{!contains(matrix.extra, 'pyfms')}} run: pip3 install mpich - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') run: | sudo apt-get update --fix-missing - sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + sudo apt-get install netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: | - pip3 install .[${{matrix.extra}}] + pip3 install -v .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index fbc09348..a2facf40 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -235,7 +235,8 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + ds = xr.open_dataset("diag_manager_single_tile.nc") # print("Dataset opened through xarray") # assert "var_2d" in ds # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) From 4238aae8495716e2afbf696595b2b16475e09323 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 11:24:33 -0400 Subject: [PATCH 14/45] Always installing pyfms dependencies --- .github/workflows/unit_tests.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 66482b51..76d39f10 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -42,19 +42,19 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install mpi (MPICH flavor) - # if: ${{!contains(matrix.extra, 'pyfms')}} - run: pip3 install mpich + # - name: Install mpi (MPICH flavor) + # if: ${{!contains(matrix.extra, 'pyfms')}} + # run: pip3 install mpich - name: Install pyFMS dependencies (includes system MPI) - if: contains(matrix.extra, 'pyfms') + # if: contains(matrix.extra, 'pyfms') run: | sudo apt-get update --fix-missing - sudo apt-get install netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: | - pip3 install -v .[${{matrix.extra}}] + pip3 install .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests From c2a34c9826c50d4414205d402765e667e7ab3904 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 11:25:06 -0400 Subject: [PATCH 15/45] Verbose pip install --- .github/workflows/unit_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 76d39f10..4309c1ba 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -54,7 +54,7 @@ jobs: - name: Install Python packages run: | - pip3 install .[${{matrix.extra}}] + pip3 install -v .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests From 2b83d845d8436085ed37103fc9d3baa41c7f4f35 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 13:12:38 -0400 Subject: [PATCH 16/45] Using dask scheduler to avoid race condition --- tests/monitor/test_dm_monitor_single.py | 55 +++++++++++++------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index a2facf40..89ba325d 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -11,6 +11,7 @@ import pytest import xarray as xr import yaml +import dask from ndsl import ( DiagManagerMonitor, @@ -235,32 +236,32 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) - ds = xr.open_dataset("diag_manager_single_tile.nc") - # print("Dataset opened through xarray") - # assert "var_2d" in ds - # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) - # assert ds["var_2d"].dims == ("time", "y", "x") - # assert ds["var_2d"].attrs["units"] == "muntin" - # assert ds["var_3d"].dims == ("time", "z", "y", "x") - # assert ds["var_3d"].attrs["units"] == "muntin" - # assert ds["time"].shape == (ntimesteps,) - # assert ds["time"].dims == ("time",) - # assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - # assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - # assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - # np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) - # # data is transposed when passed into fortran - # np.testing.assert_array_equal( - # ds["var_3d"].values[0, :, :, :], var3_global.transpose() - # ) - # np.testing.assert_array_equal( - # ds["var_3d"].values[1, :, :, :], var3_global.transpose() - # ) - # np.testing.assert_array_equal( - # ds["var_3d"].values[2, :, :, :], var3_global.transpose() - # ) + with dask.config.set(scheduler='synchronous'): + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + print("Dataset opened through xarray") + assert "var_2d" in ds + np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) + assert ds["var_2d"].dims == ("time", "y", "x") + assert ds["var_2d"].attrs["units"] == "muntin" + assert ds["var_3d"].dims == ("time", "z", "y", "x") + assert ds["var_3d"].attrs["units"] == "muntin" + assert ds["time"].shape == (ntimesteps,) + assert ds["time"].dims == ("time",) + assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) + np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) + np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) + # data is transposed when passed into fortran + np.testing.assert_array_equal( + ds["var_3d"].values[0, :, :, :], var3_global.transpose() + ) + np.testing.assert_array_equal( + ds["var_3d"].values[1, :, :, :], var3_global.transpose() + ) + np.testing.assert_array_equal( + ds["var_3d"].values[2, :, :, :], var3_global.transpose() + ) pyfms.fms.end() From 531828cdf702881322ac629cc20cb8bd928aebda Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 13:24:20 -0400 Subject: [PATCH 17/45] Removing debugging print statements --- tests/monitor/test_dm_monitor_single.py | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 89ba325d..c8f69dc9 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -78,17 +78,10 @@ def test_dm_monitor_single_tile() -> None: layout_ndsl = (npes, 1) # flipped to match fms domain decomposition global_indices = [0, nx - 1, 0, ny - 1] - print("") - print("INITIALIZED ALL VARIABLES") - _create_input() - print("PASSED CALL TO _CREATE_INPUT") - pyfms.fms.init(localcomm=MPIComm()._comm.py2f(), calendar_type=pyfms.fms.NOLEAP) - print("pyFMS initialized") - domain = pyfms.mpp_domains.define_domains( global_indices=global_indices, layout=layout_fms, @@ -100,8 +93,6 @@ def test_dm_monitor_single_tile() -> None: io_layout=io_layout, ) - print("Domains defined") - if npes > 1: rank = MPIComm()._comm.Get_rank() print(f"intializing partitioner/communicator rank {rank} of {npes}") @@ -129,16 +120,12 @@ def test_dm_monitor_single_tile() -> None: ) quantity_factory = QuantityFactory(sizer, backend=backend) - print("NDSL stuff created") - # set up for diag manager for before the main loop, need to set timestep + end_time and register all axes and fields monitor = DiagManagerMonitor(domain_id=domain_id) start = datetime(2, 1, 1, 1, 1, 1) step = timedelta(seconds=3600) end = start + ntimesteps * step - print("diag_manager Monitor created") - monitor.set_timestep(step) monitor.set_end_time(end) @@ -196,8 +183,6 @@ def test_dm_monitor_single_tile() -> None: assert "var_2d" in monitor.fields assert "var_3d" in monitor.fields - print("Checks on monitor field registers done") - # set up data to send for diagnostics var2_global = np.empty(shape=(nx, ny), dtype=np.float64) var3_global = np.empty(shape=(nx, ny, nz), dtype=np.float64) @@ -232,8 +217,6 @@ def test_dm_monitor_single_tile() -> None: # cleanup writes and closes the file monitor.cleanup() - print("Monitor cleaned up") - # check output! assert Path("diag_manager_single_tile.nc").exists() with dask.config.set(scheduler='synchronous'): From 26eeaad05af150955773ea3c1b5a82979cac878a Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 7 May 2026 13:46:29 -0400 Subject: [PATCH 18/45] Linting and removing commented sections --- .github/workflows/unit_tests.yaml | 7 +------ tests/monitor/test_dm_monitor_single.py | 4 ++-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 4309c1ba..e3632ef7 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -42,12 +42,7 @@ jobs: with: python-version: ${{ matrix.python-version }} - # - name: Install mpi (MPICH flavor) - # if: ${{!contains(matrix.extra, 'pyfms')}} - # run: pip3 install mpich - - - name: Install pyFMS dependencies (includes system MPI) - # if: contains(matrix.extra, 'pyfms') + - name: Install dependencies run: | sudo apt-get update --fix-missing sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index c8f69dc9..490112c4 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -7,11 +7,11 @@ from pathlib import Path import cftime +import dask import numpy as np import pytest import xarray as xr import yaml -import dask from ndsl import ( DiagManagerMonitor, @@ -219,7 +219,7 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - with dask.config.set(scheduler='synchronous'): + with dask.config.set(scheduler="synchronous"): ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) print("Dataset opened through xarray") assert "var_2d" in ds From 5186f80aa8c3e93ec49b9e0705cba6cf4273b4d0 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 09:28:05 -0400 Subject: [PATCH 19/45] Addressing comments from PR 459: removing use of dask scheduler --- .github/workflows/unit_tests.yaml | 20 +++++++++++--------- tests/monitor/test_dm_monitor_single.py | 9 +++++---- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index e3632ef7..143026f2 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -5,8 +5,8 @@ on: pull_request: # ... a PR is opened / updated merge_group: # ... the PR is added to the merge queue push: - # branches: - # - main # ... when merging into the main branch + branches: + - main # ... when merging into the main branch # cancel running jobs if theres a newer push concurrency: @@ -42,20 +42,22 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: | - sudo apt-get update --fix-missing - sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + - name: Install MPI + if: ${{!contains(matrix.extra, 'pyfms')}} + run: pip3 install mpich + + - name: Install pyFMS dependencies (includes system MPI) + if: contains(matrix.extra, 'pyfms') + run: sudo apt-get install mpich libmpich-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: | - pip3 install -v .[${{matrix.extra}}] + run: pip3 install -v .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests - name: Run parallel cpu tests - run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests + run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests - name: Output code coverage run: | diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 490112c4..6b2e2255 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -7,7 +7,8 @@ from pathlib import Path import cftime -import dask + +# import dask import numpy as np import pytest import xarray as xr @@ -219,9 +220,9 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - with dask.config.set(scheduler="synchronous"): - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) - print("Dataset opened through xarray") + MPIComm()._comm.Barrier() + # with dask.config.set(scheduler="synchronous"): + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) assert ds["var_2d"].dims == ("time", "y", "x") From 0e2e1240eea7a5db6259a5ccff33051d1e29e110 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 09:36:25 -0400 Subject: [PATCH 20/45] Doing sudo apt-get update just for pyfms install --- .github/workflows/unit_tests.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 143026f2..f634de05 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,7 +48,9 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: sudo apt-get install mpich libmpich-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: | + sudo apt-get update + sudo apt-get install mpich libmpich-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: pip3 install -v .[${{matrix.extra}}] From b6933b0ed5bead2c4f2401abc837a6e80f161c85 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 09:50:16 -0400 Subject: [PATCH 21/45] Trying with h5netcdf engine in xarray open_dataset for single dm_monitor test --- .github/workflows/unit_tests.yaml | 2 +- tests/monitor/test_dm_monitor_single.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index f634de05..766a72ea 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -49,7 +49,7 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') run: | - sudo apt-get update + sudo apt-get update sudo apt-get install mpich libmpich-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 6b2e2255..d918af3e 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -222,7 +222,9 @@ def test_dm_monitor_single_tile() -> None: assert Path("diag_manager_single_tile.nc").exists() MPIComm()._comm.Barrier() # with dask.config.set(scheduler="synchronous"): - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True) + ds = xr.open_dataset( + "diag_manager_single_tile.nc", decode_times=True, engine="h5netcdf", chunks={} + ) assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) assert ds["var_2d"].dims == ("time", "y", "x") From 6681da92c899debca4c5a960caa2419dfcf16a59 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 09:57:20 -0400 Subject: [PATCH 22/45] Using threading.Lock to resolve issue in open_dataset loading --- tests/monitor/test_dm_monitor_single.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index d918af3e..eab1767a 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -3,12 +3,11 @@ with data gathered from any other processors. """ +import threading from datetime import datetime, timedelta from pathlib import Path import cftime - -# import dask import numpy as np import pytest import xarray as xr @@ -220,10 +219,9 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - MPIComm()._comm.Barrier() - # with dask.config.set(scheduler="synchronous"): + lock = threading.Lock() ds = xr.open_dataset( - "diag_manager_single_tile.nc", decode_times=True, engine="h5netcdf", chunks={} + "diag_manager_single_tile.nc", decode_times=True, chunks={}, lock=lock ) assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) From b4034983bc25345921186ff22ceb5f5ff87e68e2 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 11:06:19 -0400 Subject: [PATCH 23/45] Using pip list to check versions installed via pip in unit tests --- .github/workflows/unit_tests.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 766a72ea..9da3cfc7 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -53,7 +53,9 @@ jobs: sudo apt-get install mpich libmpich-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: pip3 install -v .[${{matrix.extra}}] + run: | + pip3 install -v .[${{matrix.extra}}] + pip3 list - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests From ea986fc719122a11759b2aa096db867374ad1381 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 12:17:41 -0400 Subject: [PATCH 24/45] Updating allowed version of netcdf4 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ec9dc341..76bdf06e 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ def local_pkg(name: str, relative_path: str) -> str: "cftime", "xarray>=2025.01.2", # datatree + fixes "f90nml>=1.1.0", - "netcdf4==1.7.2", + "netcdf4>=1.7.2", "scipy", # restart capacities only "h5netcdf", # for xarray "h5py", # for h5netcdf >= 1.8 From bd5a5b96d2ed9973221c2ea1292eb01b4b480072 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 12:31:32 -0400 Subject: [PATCH 25/45] Removing chunks={} from open_dataset call --- tests/monitor/test_dm_monitor_single.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index eab1767a..e846c642 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -221,7 +221,7 @@ def test_dm_monitor_single_tile() -> None: assert Path("diag_manager_single_tile.nc").exists() lock = threading.Lock() ds = xr.open_dataset( - "diag_manager_single_tile.nc", decode_times=True, chunks={}, lock=lock + "diag_manager_single_tile.nc", decode_times=True, lock=lock ) assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) From c3a1baa60aa31357b80209455524ee0b865b8f16 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 13:12:08 -0400 Subject: [PATCH 26/45] Checking if python 3.12 is causing breakage --- .github/workflows/unit_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 9da3cfc7..03172e88 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -27,7 +27,7 @@ jobs: - extra: 'test,pyfms' marker-serial: 'pyfms and not parallel' marker-parallel: 'pyfms and parallel' - python-version: '3.12' + python-version: '3.11' # don't cancel other jobs if one fails fail-fast: false name: Python ${{ matrix.python-version }}${{ contains(matrix.extra, 'pyfms') && ' (pyFMS)' || '' }} From 0cf5946df945fa7b725da3b4847f6b0db8247df6 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 13:13:05 -0400 Subject: [PATCH 27/45] Linting --- tests/monitor/test_dm_monitor_single.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index e846c642..dab29659 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -220,9 +220,7 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() lock = threading.Lock() - ds = xr.open_dataset( - "diag_manager_single_tile.nc", decode_times=True, lock=lock - ) + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True, lock=lock) assert "var_2d" in ds np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) assert ds["var_2d"].dims == ("time", "y", "x") From d6cf6c01d2247f4f87a6f27f41374dbb2bc5d5b5 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 13:27:39 -0400 Subject: [PATCH 28/45] Using netcdf4 directly over xarray --- .github/workflows/unit_tests.yaml | 2 +- tests/monitor/test_dm_monitor_single.py | 62 ++++++++++++++----------- 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 03172e88..9da3cfc7 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -27,7 +27,7 @@ jobs: - extra: 'test,pyfms' marker-serial: 'pyfms and not parallel' marker-parallel: 'pyfms and parallel' - python-version: '3.11' + python-version: '3.12' # don't cancel other jobs if one fails fail-fast: false name: Python ${{ matrix.python-version }}${{ contains(matrix.extra, 'pyfms') && ' (pyFMS)' || '' }} diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index dab29659..3ab24b72 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -10,9 +10,12 @@ import cftime import numpy as np import pytest -import xarray as xr import yaml +# import dask +# import xarray as xr +from netCDF4 import Dataset + from ndsl import ( DiagManagerMonitor, LocalComm, @@ -219,31 +222,36 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - lock = threading.Lock() - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True, lock=lock) - assert "var_2d" in ds - np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) - assert ds["var_2d"].dims == ("time", "y", "x") - assert ds["var_2d"].attrs["units"] == "muntin" - assert ds["var_3d"].dims == ("time", "z", "y", "x") - assert ds["var_3d"].attrs["units"] == "muntin" - assert ds["time"].shape == (ntimesteps,) - assert ds["time"].dims == ("time",) - assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) - np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) - np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) - # data is transposed when passed into fortran - np.testing.assert_array_equal( - ds["var_3d"].values[0, :, :, :], var3_global.transpose() - ) - np.testing.assert_array_equal( - ds["var_3d"].values[1, :, :, :], var3_global.transpose() - ) - np.testing.assert_array_equal( - ds["var_3d"].values[2, :, :, :], var3_global.transpose() - ) + # lock = threading.Lock() + # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True, lock=lock) + ds = Dataset("diag_manager_single_tile.nc") + assert "var_2d" in ds.variables + var2 = ds.variables["var_2d"] + assert var2.shape == (ntimesteps, ny, nx) + assert var2.units == "muntin" + # assert "var_2d" in ds + # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) + # assert ds["var_2d"].dims == ("time", "y", "x") + # assert ds["var_2d"].attrs["units"] == "muntin" + # assert ds["var_3d"].dims == ("time", "z", "y", "x") + # assert ds["var_3d"].attrs["units"] == "muntin" + # assert ds["time"].shape == (ntimesteps,) + # assert ds["time"].dims == ("time",) + # assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + # assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + # assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + # np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) + # # data is transposed when passed into fortran + # np.testing.assert_array_equal( + # ds["var_3d"].values[0, :, :, :], var3_global.transpose() + # ) + # np.testing.assert_array_equal( + # ds["var_3d"].values[1, :, :, :], var3_global.transpose() + # ) + # np.testing.assert_array_equal( + # ds["var_3d"].values[2, :, :, :], var3_global.transpose() + # ) pyfms.fms.end() From ab22f589cf38d7e5064d87b1f3ffbacc90410245 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 14:07:18 -0400 Subject: [PATCH 29/45] Bring all asserts back into test_dm_monitor_single.py --- tests/monitor/test_dm_monitor_single.py | 58 ++++++++++--------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 3ab24b72..bc9e4a55 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -3,7 +3,6 @@ with data gathered from any other processors. """ -import threading from datetime import datetime, timedelta from pathlib import Path @@ -11,10 +10,7 @@ import numpy as np import pytest import yaml - -# import dask -# import xarray as xr -from netCDF4 import Dataset +from netCDF4 import Dataset, num2date from ndsl import ( DiagManagerMonitor, @@ -222,36 +218,30 @@ def test_dm_monitor_single_tile() -> None: # check output! assert Path("diag_manager_single_tile.nc").exists() - # lock = threading.Lock() - # ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True, lock=lock) ds = Dataset("diag_manager_single_tile.nc") assert "var_2d" in ds.variables - var2 = ds.variables["var_2d"] - assert var2.shape == (ntimesteps, ny, nx) - assert var2.units == "muntin" - # assert "var_2d" in ds - # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) - # assert ds["var_2d"].dims == ("time", "y", "x") - # assert ds["var_2d"].attrs["units"] == "muntin" - # assert ds["var_3d"].dims == ("time", "z", "y", "x") - # assert ds["var_3d"].attrs["units"] == "muntin" - # assert ds["time"].shape == (ntimesteps,) - # assert ds["time"].dims == ("time",) - # assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - # assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - # assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - # np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) - # # data is transposed when passed into fortran - # np.testing.assert_array_equal( - # ds["var_3d"].values[0, :, :, :], var3_global.transpose() - # ) - # np.testing.assert_array_equal( - # ds["var_3d"].values[1, :, :, :], var3_global.transpose() - # ) - # np.testing.assert_array_equal( - # ds["var_3d"].values[2, :, :, :], var3_global.transpose() - # ) + assert "time" in ds.variables + assert "var_3d" in ds.variables + var2_ds = ds.variables["var_2d"] + time_var = ds.variables["time"] + var3_ds = ds.variables["var_3d"] + np.testing.assert_array_equal(var2_ds.shape, (ntimesteps, nx, ny)) + assert var2_ds.dimensions == ("time", "y", "x") + assert var2_ds.units == "muntin" + assert var3_ds.dimensions == ("time", "z", "y", "x") + assert var3_ds.units == "muntin" + assert time_var.shape == (ntimesteps,) + assert time_var.dimensions == ("time",) + dates = num2date(time_var[:], units=time_var.units, calendar=time_var.calendar) + assert dates[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + assert dates[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + assert dates[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + np.testing.assert_array_equal(var2_ds[0, :, :], var2_global.transpose()) + np.testing.assert_array_equal(var2_ds[1, :, :], var2_global.transpose()) + np.testing.assert_array_equal(var2_ds[2, :, :], var2_global.transpose()) + # data is transposed when passed into fortran + np.testing.assert_array_equal(var3_ds[0, :, :, :], var3_global.transpose()) + np.testing.assert_array_equal(var3_ds[1, :, :, :], var3_global.transpose()) + np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) pyfms.fms.end() From 528f21f0a301defe0b8ca0c5bfa9175e033b0916 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 14:21:06 -0400 Subject: [PATCH 30/45] Adding option for parallel pyfms tests vs non in unit_tests workflow --- .github/workflows/unit_tests.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 9da3cfc7..cbb68435 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -50,17 +50,21 @@ jobs: if: contains(matrix.extra, 'pyfms') run: | sudo apt-get update - sudo apt-get install mpich libmpich-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: | pip3 install -v .[${{matrix.extra}}] - pip3 list - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests + - name: Run parallel cpu tests for pyFMS + if: contains(matrix.extra, 'pyfms') + run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests + - name: Run parallel cpu tests + if: ${{!contains(matrix.extra, 'pyfms')}} run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests - name: Output code coverage From 877fd63c7c72b729de210ff46c7039b8e9c98516 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Fri, 8 May 2026 14:34:28 -0400 Subject: [PATCH 31/45] Using netcdf4 over xarray in test_dm_monitor_cubed.py --- tests/monitor/test_dm_monitor_cubed.py | 42 ++++++++++++++------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/tests/monitor/test_dm_monitor_cubed.py b/tests/monitor/test_dm_monitor_cubed.py index 5fa2bd82..e1bdb557 100644 --- a/tests/monitor/test_dm_monitor_cubed.py +++ b/tests/monitor/test_dm_monitor_cubed.py @@ -8,8 +8,8 @@ import cftime import numpy as np import pytest -import xarray as xr import yaml +from netCDF4 import Dataset, num2date from ndsl import ( CubedSphereCommunicator, @@ -201,24 +201,28 @@ def test_dm_monitor() -> None: pe = MPIComm()._comm.Get_rank() + 1 filename = "diag_manager_cubed_sphere.tile" + str(pe) + ".nc" assert Path(filename).exists() - ds = xr.open_dataset(filename, decode_times=True) - assert "var1" in ds - np.testing.assert_array_equal(ds["var1"].shape, (ntimesteps, ny, nx)) - assert "var2" in ds - np.testing.assert_array_equal(ds["var2"].shape, (ntimesteps, nz, ny, nx)) - assert ds["var1"].dims == ("time", "y", "x") - assert ds["var2"].dims == ("time", "z", "y", "x") - assert ds["time"].shape == (ntimesteps,) - assert ds["time"].dims == ("time",) - assert ds["time"].values[0] == cftime.DatetimeNoLeap(1, 1, 1, 0, 0, 15) - assert ds["time"].values[1] == cftime.DatetimeNoLeap(1, 1, 1, 0, 0, 30) - assert ds["time"].values[2] == cftime.DatetimeNoLeap(1, 1, 1, 0, 0, 45) + ds = Dataset(filename) + assert "var1" in ds.variables + var1_ds = ds.variables["var1"] + np.testing.assert_array_equal(var1_ds.shape, (ntimesteps, ny, nx)) + assert "var2" in ds.variables + var2_ds = ds.variables["var2"] + np.testing.assert_array_equal(var2_ds.shape, (ntimesteps, nz, ny, nx)) + assert var1_ds.dimensions == ("time", "y", "x") + assert var2_ds.dimensions == ("time", "z", "y", "x") + time_var = ds["time"] + dates = num2date(time_var[:], units=time_var.units, calendar=time_var.calendar) + assert time_var.shape == (ntimesteps,) + assert time_var.dimensions == ("time",) + assert dates[0] == cftime.DatetimeNoLeap(1, 1, 1, 0, 0, 15) + assert dates[1] == cftime.DatetimeNoLeap(1, 1, 1, 0, 0, 30) + assert dates[2] == cftime.DatetimeNoLeap(1, 1, 1, 0, 0, 45) # data is just the timestep number - np.testing.assert_array_equal(ds["var1"].values[0, :, :], 1) - np.testing.assert_array_equal(ds["var1"].values[1, :, :], 2) - np.testing.assert_array_equal(ds["var1"].values[2, :, :], 3) - np.testing.assert_array_equal(ds["var2"].values[0, :, :, :], 2) - np.testing.assert_array_equal(ds["var2"].values[1, :, :, :], 4) - np.testing.assert_array_equal(ds["var2"].values[2, :, :, :], 6) + np.testing.assert_array_equal(var1_ds[0, :, :], 1) + np.testing.assert_array_equal(var1_ds[1, :, :], 2) + np.testing.assert_array_equal(var1_ds[2, :, :], 3) + np.testing.assert_array_equal(var2_ds[0, :, :, :], 2) + np.testing.assert_array_equal(var2_ds[1, :, :, :], 4) + np.testing.assert_array_equal(var2_ds[2, :, :, :], 6) pyfms.fms.end() From e6c365f87d5d0770b88c8d597251d82badd9f98e Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 09:55:36 -0400 Subject: [PATCH 32/45] Removing script mode for pip install in unit_tests workflow --- .github/workflows/unit_tests.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index cbb68435..2cfd67a4 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -53,8 +53,7 @@ jobs: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: | - pip3 install -v .[${{matrix.extra}}] + run: pip3 install -v .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests From af1d2a55ce90c9c278c312215f03db2df1928b80 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 14:40:31 -0400 Subject: [PATCH 33/45] Addressing PR 459 comments, removing -s flag, no apt-get update, single parallel test run --- .github/workflows/unit_tests.yaml | 19 ++++++++++--------- setup.py | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 2cfd67a4..f7c75796 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,23 +48,24 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: | - sudo apt-get update - sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: pip3 install -v .[${{matrix.extra}}] + run: pip3 install .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests - - name: Run parallel cpu tests for pyFMS - if: contains(matrix.extra, 'pyfms') - run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests + # - name: Run parallel cpu tests for pyFMS + # if: contains(matrix.extra, 'pyfms') + # run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests + + # - name: Run parallel cpu tests + # if: ${{!contains(matrix.extra, 'pyfms')}} + # run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - name: Run parallel cpu tests - if: ${{!contains(matrix.extra, 'pyfms')}} - run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -s -m "${{matrix.marker-parallel}}" tests + run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - name: Output code coverage run: | diff --git a/setup.py b/setup.py index 76bdf06e..ec9dc341 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,7 @@ def local_pkg(name: str, relative_path: str) -> str: "cftime", "xarray>=2025.01.2", # datatree + fixes "f90nml>=1.1.0", - "netcdf4>=1.7.2", + "netcdf4==1.7.2", "scipy", # restart capacities only "h5netcdf", # for xarray "h5py", # for h5netcdf >= 1.8 From d18e647963e37ab5a8dc39f87e36fe6bd9131c21 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 14:47:51 -0400 Subject: [PATCH 34/45] Using --fix-missing to try to amend broken install for pyfms --- .github/workflows/unit_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index f7c75796..cc3f7ba4 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,7 +48,7 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: sudo apt-get install -y --fix-missing libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: pip3 install .[${{matrix.extra}}] From 424760da9ef218b2664715d0f2a5ad0f47f9c89b Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 15:04:08 -0400 Subject: [PATCH 35/45] Using update for pyfms install to check that other changes are working --- .github/workflows/unit_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index cc3f7ba4..86570b6a 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,7 +48,7 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: sudo apt-get install -y --fix-missing libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: sudo apt-get update && install -y libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: pip3 install .[${{matrix.extra}}] From 62b21c0c1a4576a602100ded52c34445a21ba9d9 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 15:05:36 -0400 Subject: [PATCH 36/45] Removing -y flag from pyfms dependency install --- .github/workflows/unit_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 86570b6a..70073b04 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,7 +48,7 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: sudo apt-get update && install -y libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: sudo apt-get update && install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: pip3 install .[${{matrix.extra}}] From ac125d171c6aa210421467ab3077a5870a0d036d Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 15:08:56 -0400 Subject: [PATCH 37/45] Using script mode for pyfms dependency install --- .github/workflows/unit_tests.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 70073b04..ba36816f 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -48,7 +48,9 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') - run: sudo apt-get update && install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils + run: | + sudo apt-get update + sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages run: pip3 install .[${{matrix.extra}}] From 9d85b3481f033cc6fd24f5e8b5a3ed6c124cf1ee Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 15:18:19 -0400 Subject: [PATCH 38/45] Moving back to using separate parallel test runs in unit tests --- .github/workflows/unit_tests.yaml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index ba36816f..0a1be7bb 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -49,7 +49,7 @@ jobs: - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') run: | - sudo apt-get update + sudo apt-get update sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages @@ -58,15 +58,12 @@ jobs: - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests - # - name: Run parallel cpu tests for pyFMS - # if: contains(matrix.extra, 'pyfms') - # run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - - # - name: Run parallel cpu tests - # if: ${{!contains(matrix.extra, 'pyfms')}} - # run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests + - name: Run parallel cpu tests for pyFMS + if: contains(matrix.extra, 'pyfms') + run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - name: Run parallel cpu tests + if: ${{!contains(matrix.extra, 'pyfms')}} run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - name: Output code coverage From cb49a53e61897a94b612760e15c784928eeeb855 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Mon, 11 May 2026 17:05:31 -0400 Subject: [PATCH 39/45] Always using openmpi in unit_tests workflow --- .github/workflows/unit_tests.yaml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 0a1be7bb..e7aa7ae4 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -44,7 +44,7 @@ jobs: - name: Install MPI if: ${{!contains(matrix.extra, 'pyfms')}} - run: pip3 install mpich + run: pip3 install openmpi - name: Install pyFMS dependencies (includes system MPI) if: contains(matrix.extra, 'pyfms') @@ -58,13 +58,8 @@ jobs: - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests - - name: Run parallel cpu tests for pyFMS - if: contains(matrix.extra, 'pyfms') - run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - - name: Run parallel cpu tests - if: ${{!contains(matrix.extra, 'pyfms')}} - run: mpiexec -np 6 coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests + run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests - name: Output code coverage run: | From dae409499f52461eac02881acb5615b9e57d6df4 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Tue, 12 May 2026 10:29:10 -0400 Subject: [PATCH 40/45] Removing -s flag from serial cpu unit tests --- .github/workflows/unit_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index e7aa7ae4..46d3ca53 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -56,7 +56,7 @@ jobs: run: pip3 install .[${{matrix.extra}}] - name: Run serial cpu tests - run: coverage run --rcfile=pyproject.toml -m pytest -s -m "${{matrix.marker-serial}}" tests + run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests - name: Run parallel cpu tests run: mpiexec -np 6 --oversubscribe coverage run --rcfile=pyproject.toml -m mpi4py -m pytest -m "${{matrix.marker-parallel}}" tests From ae26ded422df8d9d686857cf4008079ef4fe23e0 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 14 May 2026 11:09:43 -0400 Subject: [PATCH 41/45] Trying with chunks set to None in xarray open_dataset to skip Dask --- tests/monitor/test_dm_monitor_single.py | 78 +++++++++++++++++-------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index bc9e4a55..6ea4ca9a 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -11,6 +11,7 @@ import pytest import yaml from netCDF4 import Dataset, num2date +import xarray as xr from ndsl import ( DiagManagerMonitor, @@ -216,32 +217,59 @@ def test_dm_monitor_single_tile() -> None: # cleanup writes and closes the file monitor.cleanup() - # check output! + # # check output! + # assert Path("diag_manager_single_tile.nc").exists() + # ds = Dataset("diag_manager_single_tile.nc") + # assert "var_2d" in ds.variables + # assert "time" in ds.variables + # assert "var_3d" in ds.variables + # var2_ds = ds.variables["var_2d"] + # time_var = ds.variables["time"] + # var3_ds = ds.variables["var_3d"] + # np.testing.assert_array_equal(var2_ds.shape, (ntimesteps, nx, ny)) + # assert var2_ds.dimensions == ("time", "y", "x") + # assert var2_ds.units == "muntin" + # assert var3_ds.dimensions == ("time", "z", "y", "x") + # assert var3_ds.units == "muntin" + # assert time_var.shape == (ntimesteps,) + # assert time_var.dimensions == ("time",) + # dates = num2date(time_var[:], units=time_var.units, calendar=time_var.calendar) + # assert dates[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + # assert dates[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + # assert dates[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + # np.testing.assert_array_equal(var2_ds[0, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(var2_ds[1, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(var2_ds[2, :, :], var2_global.transpose()) + # # data is transposed when passed into fortran + # np.testing.assert_array_equal(var3_ds[0, :, :, :], var3_global.transpose()) + # np.testing.assert_array_equal(var3_ds[1, :, :, :], var3_global.transpose()) + # np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) + assert Path("diag_manager_single_tile.nc").exists() - ds = Dataset("diag_manager_single_tile.nc") - assert "var_2d" in ds.variables - assert "time" in ds.variables - assert "var_3d" in ds.variables - var2_ds = ds.variables["var_2d"] - time_var = ds.variables["time"] - var3_ds = ds.variables["var_3d"] - np.testing.assert_array_equal(var2_ds.shape, (ntimesteps, nx, ny)) - assert var2_ds.dimensions == ("time", "y", "x") - assert var2_ds.units == "muntin" - assert var3_ds.dimensions == ("time", "z", "y", "x") - assert var3_ds.units == "muntin" - assert time_var.shape == (ntimesteps,) - assert time_var.dimensions == ("time",) - dates = num2date(time_var[:], units=time_var.units, calendar=time_var.calendar) - assert dates[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - assert dates[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - assert dates[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - np.testing.assert_array_equal(var2_ds[0, :, :], var2_global.transpose()) - np.testing.assert_array_equal(var2_ds[1, :, :], var2_global.transpose()) - np.testing.assert_array_equal(var2_ds[2, :, :], var2_global.transpose()) + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True, chunks=None) + assert "var_2d" in ds + np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) + assert ds["var_2d"].dims == ("time", "y", "x") + assert ds["var_2d"].attrs["units"] == "muntin" + assert ds["var_3d"].dims == ("time", "z", "y", "x") + assert ds["var_3d"].attrs["units"] == "muntin" + assert ds["time"].shape == (ntimesteps,) + assert ds["time"].dims == ("time",) + assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) + np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) + np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) # data is transposed when passed into fortran - np.testing.assert_array_equal(var3_ds[0, :, :, :], var3_global.transpose()) - np.testing.assert_array_equal(var3_ds[1, :, :, :], var3_global.transpose()) - np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) + np.testing.assert_array_equal( + ds["var_3d"].values[0, :, :, :], var3_global.transpose() + ) + np.testing.assert_array_equal( + ds["var_3d"].values[1, :, :, :], var3_global.transpose() + ) + np.testing.assert_array_equal( + ds["var_3d"].values[2, :, :, :], var3_global.transpose() + ) pyfms.fms.end() From 08c557374040d482da55aaff53f74669549a800c Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 14 May 2026 11:19:48 -0400 Subject: [PATCH 42/45] Checking decode_times use within xarray open_dataset failure --- tests/monitor/test_dm_monitor_single.py | 50 ++++++++++++------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 6ea4ca9a..c901e6fc 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -246,30 +246,30 @@ def test_dm_monitor_single_tile() -> None: # np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) assert Path("diag_manager_single_tile.nc").exists() - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=True, chunks=None) - assert "var_2d" in ds - np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) - assert ds["var_2d"].dims == ("time", "y", "x") - assert ds["var_2d"].attrs["units"] == "muntin" - assert ds["var_3d"].dims == ("time", "z", "y", "x") - assert ds["var_3d"].attrs["units"] == "muntin" - assert ds["time"].shape == (ntimesteps,) - assert ds["time"].dims == ("time",) - assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) - np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) - np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) - # data is transposed when passed into fortran - np.testing.assert_array_equal( - ds["var_3d"].values[0, :, :, :], var3_global.transpose() - ) - np.testing.assert_array_equal( - ds["var_3d"].values[1, :, :, :], var3_global.transpose() - ) - np.testing.assert_array_equal( - ds["var_3d"].values[2, :, :, :], var3_global.transpose() - ) + ds = xr.open_dataset("diag_manager_single_tile.nc", chunks=None) + # assert "var_2d" in ds + # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) + # assert ds["var_2d"].dims == ("time", "y", "x") + # assert ds["var_2d"].attrs["units"] == "muntin" + # assert ds["var_3d"].dims == ("time", "z", "y", "x") + # assert ds["var_3d"].attrs["units"] == "muntin" + # assert ds["time"].shape == (ntimesteps,) + # assert ds["time"].dims == ("time",) + # assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + # assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + # assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + # np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) + # np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) + # # data is transposed when passed into fortran + # np.testing.assert_array_equal( + # ds["var_3d"].values[0, :, :, :], var3_global.transpose() + # ) + # np.testing.assert_array_equal( + # ds["var_3d"].values[1, :, :, :], var3_global.transpose() + # ) + # np.testing.assert_array_equal( + # ds["var_3d"].values[2, :, :, :], var3_global.transpose() + # ) pyfms.fms.end() From 8c5107b8704e2283807d360fe45eb25cbac9eed2 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 14 May 2026 11:28:37 -0400 Subject: [PATCH 43/45] Again checking decode_times in open_dataset and checking xarray version --- .github/workflows/unit_tests.yaml | 4 +++- tests/monitor/test_dm_monitor_single.py | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 46d3ca53..60a25404 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -53,7 +53,9 @@ jobs: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: pip3 install .[${{matrix.extra}}] + run: | + pip3 install .[${{matrix.extra}}] + pip3 list - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index c901e6fc..2631ab39 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -246,7 +246,7 @@ def test_dm_monitor_single_tile() -> None: # np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) assert Path("diag_manager_single_tile.nc").exists() - ds = xr.open_dataset("diag_manager_single_tile.nc", chunks=None) + ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=False, chunks=None) # assert "var_2d" in ds # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) # assert ds["var_2d"].dims == ("time", "y", "x") From 8a7776081122f1370ecf6efc07286dbe86e2e55f Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Thu, 14 May 2026 12:22:05 -0400 Subject: [PATCH 44/45] Reverting changes back to netcdf direct access in test_dm_monitor_single --- tests/monitor/test_dm_monitor_single.py | 80 ++++++++----------------- 1 file changed, 26 insertions(+), 54 deletions(-) diff --git a/tests/monitor/test_dm_monitor_single.py b/tests/monitor/test_dm_monitor_single.py index 2631ab39..bc9e4a55 100644 --- a/tests/monitor/test_dm_monitor_single.py +++ b/tests/monitor/test_dm_monitor_single.py @@ -11,7 +11,6 @@ import pytest import yaml from netCDF4 import Dataset, num2date -import xarray as xr from ndsl import ( DiagManagerMonitor, @@ -217,59 +216,32 @@ def test_dm_monitor_single_tile() -> None: # cleanup writes and closes the file monitor.cleanup() - # # check output! - # assert Path("diag_manager_single_tile.nc").exists() - # ds = Dataset("diag_manager_single_tile.nc") - # assert "var_2d" in ds.variables - # assert "time" in ds.variables - # assert "var_3d" in ds.variables - # var2_ds = ds.variables["var_2d"] - # time_var = ds.variables["time"] - # var3_ds = ds.variables["var_3d"] - # np.testing.assert_array_equal(var2_ds.shape, (ntimesteps, nx, ny)) - # assert var2_ds.dimensions == ("time", "y", "x") - # assert var2_ds.units == "muntin" - # assert var3_ds.dimensions == ("time", "z", "y", "x") - # assert var3_ds.units == "muntin" - # assert time_var.shape == (ntimesteps,) - # assert time_var.dimensions == ("time",) - # dates = num2date(time_var[:], units=time_var.units, calendar=time_var.calendar) - # assert dates[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - # assert dates[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - # assert dates[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - # np.testing.assert_array_equal(var2_ds[0, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(var2_ds[1, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(var2_ds[2, :, :], var2_global.transpose()) - # # data is transposed when passed into fortran - # np.testing.assert_array_equal(var3_ds[0, :, :, :], var3_global.transpose()) - # np.testing.assert_array_equal(var3_ds[1, :, :, :], var3_global.transpose()) - # np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) - + # check output! assert Path("diag_manager_single_tile.nc").exists() - ds = xr.open_dataset("diag_manager_single_tile.nc", decode_times=False, chunks=None) - # assert "var_2d" in ds - # np.testing.assert_array_equal(ds["var_2d"].shape, (ntimesteps, nx, ny)) - # assert ds["var_2d"].dims == ("time", "y", "x") - # assert ds["var_2d"].attrs["units"] == "muntin" - # assert ds["var_3d"].dims == ("time", "z", "y", "x") - # assert ds["var_3d"].attrs["units"] == "muntin" - # assert ds["time"].shape == (ntimesteps,) - # assert ds["time"].dims == ("time",) - # assert ds["time"].values[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) - # assert ds["time"].values[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) - # assert ds["time"].values[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) - # np.testing.assert_array_equal(ds["var_2d"].values[0, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(ds["var_2d"].values[1, :, :], var2_global.transpose()) - # np.testing.assert_array_equal(ds["var_2d"].values[2, :, :], var2_global.transpose()) - # # data is transposed when passed into fortran - # np.testing.assert_array_equal( - # ds["var_3d"].values[0, :, :, :], var3_global.transpose() - # ) - # np.testing.assert_array_equal( - # ds["var_3d"].values[1, :, :, :], var3_global.transpose() - # ) - # np.testing.assert_array_equal( - # ds["var_3d"].values[2, :, :, :], var3_global.transpose() - # ) + ds = Dataset("diag_manager_single_tile.nc") + assert "var_2d" in ds.variables + assert "time" in ds.variables + assert "var_3d" in ds.variables + var2_ds = ds.variables["var_2d"] + time_var = ds.variables["time"] + var3_ds = ds.variables["var_3d"] + np.testing.assert_array_equal(var2_ds.shape, (ntimesteps, nx, ny)) + assert var2_ds.dimensions == ("time", "y", "x") + assert var2_ds.units == "muntin" + assert var3_ds.dimensions == ("time", "z", "y", "x") + assert var3_ds.units == "muntin" + assert time_var.shape == (ntimesteps,) + assert time_var.dimensions == ("time",) + dates = num2date(time_var[:], units=time_var.units, calendar=time_var.calendar) + assert dates[0] == cftime.DatetimeNoLeap(2, 1, 1, 2, 1, 1) + assert dates[1] == cftime.DatetimeNoLeap(2, 1, 1, 3, 1, 1) + assert dates[2] == cftime.DatetimeNoLeap(2, 1, 1, 4, 1, 1) + np.testing.assert_array_equal(var2_ds[0, :, :], var2_global.transpose()) + np.testing.assert_array_equal(var2_ds[1, :, :], var2_global.transpose()) + np.testing.assert_array_equal(var2_ds[2, :, :], var2_global.transpose()) + # data is transposed when passed into fortran + np.testing.assert_array_equal(var3_ds[0, :, :, :], var3_global.transpose()) + np.testing.assert_array_equal(var3_ds[1, :, :, :], var3_global.transpose()) + np.testing.assert_array_equal(var3_ds[2, :, :, :], var3_global.transpose()) pyfms.fms.end() From b6631f8129f289844ac71e3f8b3657e642e48d73 Mon Sep 17 00:00:00 2001 From: Frank Malatino Date: Wed, 20 May 2026 11:46:25 -0400 Subject: [PATCH 45/45] Removing pip list debug command from unit_tests workflow --- .github/workflows/unit_tests.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 60a25404..46d3ca53 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -53,9 +53,7 @@ jobs: sudo apt-get install libopenmpi-dev netcdf-bin libnetcdf-dev libnetcdff-dev nco libyaml-dev diffutils - name: Install Python packages - run: | - pip3 install .[${{matrix.extra}}] - pip3 list + run: pip3 install .[${{matrix.extra}}] - name: Run serial cpu tests run: coverage run --rcfile=pyproject.toml -m pytest -m "${{matrix.marker-serial}}" tests