From 9285bc5ae9ba6fc9db211c69b1cf68adb09d1b54 Mon Sep 17 00:00:00 2001 From: Janice Kim Date: Tue, 21 Oct 2025 12:35:05 -0400 Subject: [PATCH 1/3] Removing ndsl.Namelist from PySHiELD Adding --no_legacy_namelist to translate.yaml --- .github/workflows/translate.yaml | 2 + pyshield/_config.py | 123 ++++++++---------- .../translate/translate_atmos_phy_statein.py | 8 +- tests/savepoint/translate/translate_dcyc.py | 4 +- .../savepoint/translate/translate_fillgfs.py | 2 +- tests/savepoint/translate/translate_fpvs.py | 4 +- .../translate/translate_fv_update_phys.py | 12 +- .../translate/translate_gfs_physics_driver.py | 39 +++--- .../translate/translate_microphysics.py | 32 ++--- tests/savepoint/translate/translate_phifv3.py | 2 +- .../savepoint/translate/translate_physics.py | 6 +- tests/savepoint/translate/translate_prsfv3.py | 2 +- .../translate/translate_update_dwind_phys.py | 9 +- .../translate_update_tracers_phys.py | 34 ++--- 14 files changed, 131 insertions(+), 148 deletions(-) diff --git a/.github/workflows/translate.yaml b/.github/workflows/translate.yaml index c2ae278d..0e201e89 100644 --- a/.github/workflows/translate.yaml +++ b/.github/workflows/translate.yaml @@ -112,6 +112,7 @@ jobs: -v -s --data_path=${{ env.TEST_DATA_PATH }} \ --backend=numpy \ --threshold_overrides_file=./tests/savepoint/translate/overrides/standard.yaml \ + --no_legacy_namelist \ ./tests/savepoint - name: Orchestrated dace:cpu Translate Test @@ -125,4 +126,5 @@ jobs: -vvv -x -s --data_path=${{ env.TEST_DATA_PATH }} \ --backend=dace:cpu \ --threshold_overrides_file=./tests/savepoint/translate/overrides/standard.yaml \ + --no_legacy_namelist \ ./tests/savepoint diff --git a/pyshield/_config.py b/pyshield/_config.py index 4ce6a0e9..877034c1 100644 --- a/pyshield/_config.py +++ b/pyshield/_config.py @@ -1,16 +1,26 @@ +from __future__ import annotations + import dataclasses from enum import Enum, unique from typing import List, Optional, Tuple import f90nml +from dacite import Config, from_dict from ndsl import MetaEnumStr -from ndsl.namelist import Namelist +from ndsl.utils import f90nml_as_dict DEFAULT_INT = 0 DEFAULT_BOOL = False DEFAULT_SCHEMES = ["GFS_microphysics"] +DEFAULT_PHYS_NML_GROUPS = ( + "main_nml", + "coupler_nml", + "gfdl_cloud_microphysics_nml", + "integ_phys_nml", + "gfs_physics_nml", +) @unique @@ -144,6 +154,7 @@ class PhysicsConfig: clin: float = 4.8 """"c" in lin 1983, 4.8 -- > 6. (to enhance ql -- > qs)""" namelist_override: Optional[str] = None + target_nml_groups: Optional[Tuple[str, ...]] = DEFAULT_PHYS_NML_GROUPS daily_mean: bool = DEFAULT_BOOL # flag to replace cosz with daily mean value def __post_init__(self): @@ -160,80 +171,50 @@ def __post_init__(self): f90_nml = f90nml.read(self.namelist_override) except FileNotFoundError: print(f"{self.namelist_override} does not exist") - physics_config = self.from_f90nml(f90_nml) + # TODO: Find a better way to do below. Passing self.* as an argument + # to a class function of the same class is always a bit fishy. + physics_config = self.from_f90nml(f90_nml, self.target_nml_groups) for var in physics_config.__dict__.keys(): setattr(self, var, physics_config.__dict__[var]) @classmethod - def from_f90nml(self, f90_namelist: f90nml.Namelist) -> "PhysicsConfig": - namelist = Namelist.from_f90nml(f90_namelist) - return self.from_namelist(namelist) + def from_f90nml( + cls, + nml: f90nml.Namelist, + target_groups: Tuple[str, ...] | None = DEFAULT_PHYS_NML_GROUPS, + ) -> PhysicsConfig: + """Uses the nml to create a PhysicsConfig. + + Args: + nml: f90nml.Namelist + target_groups: Tuple[str,...] | None + This list will be used to specify which groups in the nml to + use when initializing the PhysicsConfig. If None, all + groups will be used. (Default: DEFAULT_PHYS_NML_GROUPS) + """ + nml_dict = f90nml_as_dict(nml, flatten=True, target_groups=target_groups) + nml_dict["target_nml_groups"] = target_groups + return cls.from_dict(nml_dict) @classmethod - def from_namelist(cls, namelist: Namelist) -> "PhysicsConfig": - return cls( - dt_atmos=namelist.dt_atmos, - hydrostatic=namelist.hydrostatic, - npx=namelist.npx, - npy=namelist.npy, - npz=namelist.npz, - nwat=namelist.nwat, - do_qa=namelist.do_qa, - c_cracw=namelist.c_cracw, - c_paut=namelist.c_paut, - c_pgacs=namelist.c_pgacs, - c_psaci=namelist.c_psaci, - ccn_l=namelist.ccn_l, - ccn_o=namelist.ccn_o, - const_vg=namelist.const_vg, - const_vi=namelist.const_vi, - const_vr=namelist.const_vr, - const_vs=namelist.const_vs, - vs_fac=namelist.vs_fac, - vg_fac=namelist.vg_fac, - vi_fac=namelist.vi_fac, - vr_fac=namelist.vr_fac, - de_ice=namelist.de_ice, - layout=namelist.layout, - tau_imlt=namelist.tau_imlt, - tau_i2s=namelist.tau_i2s, - tau_g2v=namelist.tau_g2v, - tau_v2g=namelist.tau_v2g, - ql_mlt=namelist.ql_mlt, - qs_mlt=namelist.qs_mlt, - t_sub=namelist.t_sub, - qi_gen=namelist.qi_gen, - qi_lim=namelist.qi_lim, - qi0_max=namelist.qi0_max, - rad_snow=namelist.rad_snow, - rad_rain=namelist.rad_rain, - dw_ocean=namelist.dw_ocean, - dw_land=namelist.dw_land, - tau_l2v=namelist.tau_l2v, - c2l_ord=namelist.c2l_ord, - do_sedi_heat=namelist.do_sedi_heat, - do_sedi_w=namelist.do_sedi_w, - fast_sat_adj=namelist.fast_sat_adj, - qc_crt=namelist.qc_crt, - fix_negative=namelist.fix_negative, - irain_f=namelist.irain_f, - mp_time=namelist.mp_time, - prog_ccn=namelist.prog_ccn, - qi0_crt=namelist.qi0_crt, - qs0_crt=namelist.qs0_crt, - rh_inc=namelist.rh_inc, - rh_inr=namelist.rh_inr, - rthresh=namelist.rthresh, - sedi_transport=namelist.sedi_transport, - use_ppm=namelist.use_ppm, - vg_max=namelist.vg_max, - vi_max=namelist.vi_max, - vr_max=namelist.vr_max, - vs_max=namelist.vs_max, - z_slope_ice=namelist.z_slope_ice, - z_slope_liq=namelist.z_slope_liq, - tice=namelist.tice, - alin=namelist.alin, - clin=namelist.clin, - daily_mean=namelist.daily_mean, + def from_dict( + cls, + data: dict, + ) -> PhysicsConfig: + """Create a PhysicsConfig from the given data. + + Args: + data: "flattened" dictionary where the keys match the class member variables + """ + # NOTE: We're setting strict to False so that extra keys in the data are + # ignored. Eventually, we'd like to turn this to True once we move away from + # expecting dicts that are basically flattened f90nml files. + dacite_config = Config( + strict=False, + type_hooks={ + Tuple[int, int]: lambda x: tuple(x), + Tuple[str, ...]: lambda x: tuple(x) if x is not None else None, + }, ) + config = from_dict(data_class=PhysicsConfig, data=data, config=dacite_config) + return config diff --git a/tests/savepoint/translate/translate_atmos_phy_statein.py b/tests/savepoint/translate/translate_atmos_phy_statein.py index 445c3cf9..72ee39ee 100644 --- a/tests/savepoint/translate/translate_atmos_phy_statein.py +++ b/tests/savepoint/translate/translate_atmos_phy_statein.py @@ -33,19 +33,19 @@ def __init__(self, grid, namelist, stencil_factory): "pt": { "serialname": "IPD_tgrs", "out_roll_zero": True, - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qgrs": { "serialname": "IPD_qgrs", - "kend": namelist.npz, + "kend": self.config.npz, "order": "F", "manual": True, }, "delp": { "serialname": "IPD_prsl", "out_roll_zero": True, - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, } @@ -82,7 +82,7 @@ def post_process_qgrs(self, inputs): self.update_info(info, inputs) ds = self.grid.compute_dict() ds.update(info) - k_length = info["kend"] if "kend" in info else self.namelist.npz + k_length = info["kend"] if "kend" in info else self.config.npz index_order = info["order"] if "order" in info else "C" ij_slice = self.grid.slice_dict(ds) qgrs = qgrs[ij_slice[0], ij_slice[1], 0:k_length, :] diff --git a/tests/savepoint/translate/translate_dcyc.py b/tests/savepoint/translate/translate_dcyc.py index 5d78bc31..f752e50c 100644 --- a/tests/savepoint/translate/translate_dcyc.py +++ b/tests/savepoint/translate/translate_dcyc.py @@ -67,10 +67,10 @@ def __init__(self, grid, namelist, stencil_factory): "adjvisdfd": {"shield": True}, } self.grid_indexing = stencil_factory.grid_indexing - self._daily_mean = namelist.daily_mean + self._daily_mean = self.config.daily_mean self.compute_func = stencil_factory.from_origin_domain( interpolate_radiation, - externals={"daily_mean": namelist.daily_mean}, + externals={"daily_mean": self.config.daily_mean}, origin=self.grid_indexing.origin_full(), domain=self.grid_indexing.domain_full(), ) diff --git a/tests/savepoint/translate/translate_fillgfs.py b/tests/savepoint/translate/translate_fillgfs.py index 9a4fafe3..dc76ba07 100644 --- a/tests/savepoint/translate/translate_fillgfs.py +++ b/tests/savepoint/translate/translate_fillgfs.py @@ -15,7 +15,7 @@ def __init__(self, grid, namelist, stencil_factory): "q": {"serialname": "IPD_gq0"}, } self.out_vars = { - "q": {"serialname": "IPD_qvapor", "kend": namelist.npz - 1}, + "q": {"serialname": "IPD_qvapor", "kend": self.config.npz - 1}, } self.grid_indexing = stencil_factory.grid_indexing self.compute_func = stencil_factory.from_origin_domain( diff --git a/tests/savepoint/translate/translate_fpvs.py b/tests/savepoint/translate/translate_fpvs.py index e9ac8c43..58260944 100644 --- a/tests/savepoint/translate/translate_fpvs.py +++ b/tests/savepoint/translate/translate_fpvs.py @@ -1,6 +1,8 @@ import numpy as np -from ndsl import Namelist, StencilFactory +from f90nml import Namelist + +from ndsl import StencilFactory from ndsl.constants import X_DIM, Y_DIM, Z_DIM from ndsl.dsl.gt4py import FORWARD, PARALLEL, computation, interval from ndsl.dsl.typing import FloatField, FloatFieldIJ diff --git a/tests/savepoint/translate/translate_fv_update_phys.py b/tests/savepoint/translate/translate_fv_update_phys.py index 0e495a53..f1a68556 100644 --- a/tests/savepoint/translate/translate_fv_update_phys.py +++ b/tests/savepoint/translate/translate_fv_update_phys.py @@ -1,9 +1,10 @@ import dataclasses +from f90nml import Namelist import numpy as np import ndsl.dsl.gt4py_utils as utils -from ndsl import Namelist, Quantity, StencilFactory +from ndsl import Quantity, StencilFactory from ndsl.constants import X_DIM, X_INTERFACE_DIM, Y_DIM, Y_INTERFACE_DIM, Z_DIM from ndsl.dsl.typing import FloatField, FloatFieldIJ from ndsl.utils import safe_assign_array @@ -78,7 +79,7 @@ def __init__( "iend": self.grid_indexing.iec, "jstart": self.grid_indexing.jsc, "jend": self.grid_indexing.jec, - "kend": namelist.npz, + "kend": self.config.npz, "kaxis": 1, }, "delp": {}, @@ -89,7 +90,7 @@ def __init__( "iend": self.grid_indexing.iec + 1, "jstart": self.grid_indexing.jsc - 1, "jend": self.grid_indexing.jec + 1, - "kend": namelist.npz + 1, + "kend": self.config.npz + 1, "kaxis": 1, }, "pk": grid.compute_buffer_k_dict(), @@ -107,7 +108,6 @@ def __init__( "ua": {}, "va": {}, } - self.namelist = namelist def transform_dwind_serialized_data(self, data): return transform_dwind_serialized_data( @@ -185,7 +185,7 @@ def compute_parallel(self, inputs, communicator): self.stencil_factory, self.grid.quantity_factory, self.grid.grid_data, - self.namelist, + self.config, communicator, self.grid.driver_grid_data, state, @@ -213,7 +213,7 @@ def compute_parallel(self, inputs, communicator): tendencies["u_dt"], tendencies["v_dt"], tendencies["t_dt"], - dt=float(self.namelist.dt_atmos), + dt=float(self.config.dt_atmos), ) out = {} ds = self.grid.default_domain_dict() diff --git a/tests/savepoint/translate/translate_gfs_physics_driver.py b/tests/savepoint/translate/translate_gfs_physics_driver.py index 1de72fae..2e0edfab 100644 --- a/tests/savepoint/translate/translate_gfs_physics_driver.py +++ b/tests/savepoint/translate/translate_gfs_physics_driver.py @@ -12,7 +12,6 @@ def __init__(self, grid, namelist, stencil_factory): super().__init__(grid, namelist, stencil_factory) # using top level namelist rather than PhysicsConfig # because DycoreToPhysics needs some dycore info - self.namelist = PhysicsConfig.from_namelist(namelist) self.in_vars["data_vars"] = { "qvapor": {"dycore": True}, "qliquid": {"dycore": True}, @@ -34,52 +33,52 @@ def __init__(self, grid, namelist, stencil_factory): self.out_vars = { "gt0": { "serialname": "IPD_gt0", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "gu0": { "serialname": "IPD_gu0", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "gv0": { "serialname": "IPD_gv0", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qvapor": { "serialname": "IPD_qvapor", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qliquid": { "serialname": "IPD_qliquid", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qrain": { "serialname": "IPD_rain", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qice": { "serialname": "IPD_qice", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qsnow": { "serialname": "IPD_snow", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qgraupel": { "serialname": "IPD_qgraupel", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, "qcld": { "serialname": "IPD_qcld", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "order": "F", }, } @@ -118,12 +117,12 @@ def compute(self, inputs): backend=self.stencil_factory.backend, ) sizer = SubtileGridSizer.from_tile_params( - nx_tile=self.namelist.npx - 1, - ny_tile=self.namelist.npy - 1, - nz=self.namelist.npz, + nx_tile=self.config.npx - 1, + ny_tile=self.config.npy - 1, + nz=self.config.npz, n_halo=3, extra_dim_lengths={}, - layout=self.namelist.layout, + layout=self.config.layout, ) quantity_factory = QuantityFactory.from_backend( @@ -139,16 +138,16 @@ def compute(self, inputs): self.stencil_factory, self.grid.quantity_factory, self.grid.grid_data, - self.namelist, + self.config, ) - # TODO, self.namelist doesn't have fv_sg_adj because it is PhysicsConfig + # TODO, PhysicsConfig doesn't have fv_sg_adj # either move where GFSPhysicsDriver starts, or pass the full namelist or # get around this issue another way. Setting do_dry_convective_adjustment # to False for now (we don't run this on a case where it is True yet) dycore_to_physics = update_atmos_state.DycoreToPhysics( self.stencil_factory, self.grid.quantity_factory, - self.namelist, + self.config, do_dry_convective_adjust=False, dycore_only=False, ) @@ -207,7 +206,7 @@ def compute(self, inputs): physics_state.microphysics.qa_dt, ) microph_state = physics_state.microphysics - physics._microphysics(microph_state, float(self.namelist.dt_atmos)) + physics._microphysics(microph_state, float(self.config.dt_atmos)) # Fortran uses IPD interface, here we use physics_updated_ # to denote the updated field physics._update_physics_state_with_tendencies( @@ -241,7 +240,7 @@ def compute(self, inputs): physics_state.physics_updated_pt, physics_state.physics_updated_ua, physics_state.physics_updated_va, - float(self.namelist.dt_atmos), + float(self.config.dt_atmos), ) inputs["gt0"] = physics_state.physics_updated_pt inputs["gu0"] = physics_state.physics_updated_ua diff --git a/tests/savepoint/translate/translate_microphysics.py b/tests/savepoint/translate/translate_microphysics.py index e1e5d0ad..55ede29f 100644 --- a/tests/savepoint/translate/translate_microphysics.py +++ b/tests/savepoint/translate/translate_microphysics.py @@ -31,16 +31,16 @@ def __init__(self, grid, namelist, stencil_factory): } self.out_vars = { - "pt_dt": {"serialname": "mph_pt_dt", "kend": namelist.npz - 1}, - "qv_dt": {"serialname": "mph_qv_dt", "kend": namelist.npz - 1}, - "ql_dt": {"serialname": "mph_ql_dt", "kend": namelist.npz - 1}, - "qr_dt": {"serialname": "mph_qr_dt", "kend": namelist.npz - 1}, - "qi_dt": {"serialname": "mph_qi_dt", "kend": namelist.npz - 1}, - "qs_dt": {"serialname": "mph_qs_dt", "kend": namelist.npz - 1}, - "qg_dt": {"serialname": "mph_qg_dt", "kend": namelist.npz - 1}, - "qa_dt": {"serialname": "mph_qa_dt", "kend": namelist.npz - 1}, - "udt": {"serialname": "mph_udt", "kend": namelist.npz - 1}, - "vdt": {"serialname": "mph_vdt", "kend": namelist.npz - 1}, + "pt_dt": {"serialname": "mph_pt_dt", "kend": self.config.npz - 1}, + "qv_dt": {"serialname": "mph_qv_dt", "kend": self.config.npz - 1}, + "ql_dt": {"serialname": "mph_ql_dt", "kend": self.config.npz - 1}, + "qr_dt": {"serialname": "mph_qr_dt", "kend": self.config.npz - 1}, + "qi_dt": {"serialname": "mph_qi_dt", "kend": self.config.npz - 1}, + "qs_dt": {"serialname": "mph_qs_dt", "kend": self.config.npz - 1}, + "qg_dt": {"serialname": "mph_qg_dt", "kend": self.config.npz - 1}, + "qa_dt": {"serialname": "mph_qa_dt", "kend": self.config.npz - 1}, + "udt": {"serialname": "mph_udt", "kend": self.config.npz - 1}, + "vdt": {"serialname": "mph_vdt", "kend": self.config.npz - 1}, } self.stencil_factory = stencil_factory self.grid_indexing = self.stencil_factory.grid_indexing @@ -73,12 +73,12 @@ def compute(self, inputs): inputs["prsi"] = copy.deepcopy(storage) inputs["prsik"] = copy.deepcopy(storage) sizer = SubtileGridSizer.from_tile_params( - nx_tile=self.namelist.npx - 1, - ny_tile=self.namelist.npy - 1, - nz=self.namelist.npz, + nx_tile=self.config.npx - 1, + ny_tile=self.config.npy - 1, + nz=self.config.npz, n_halo=3, extra_dim_lengths={}, - layout=self.namelist.layout, + layout=self.config.layout, ) quantity_factory = QuantityFactory.from_backend( @@ -91,10 +91,10 @@ def compute(self, inputs): schemes=[PHYSICS_PACKAGES["GFS_microphysics"]], ) microphysics = Microphysics( - self.stencil_factory, quantity_factory, self.grid.grid_data, self.namelist + self.stencil_factory, quantity_factory, self.grid.grid_data, self.config ) microph_state = physics_state.microphysics - microphysics(microph_state, timestep=Float(self.namelist.dt_atmos)) + microphysics(microph_state, timestep=Float(self.config.dt_atmos)) inputs["pt_dt"] = microph_state.pt_dt inputs["qv_dt"] = microph_state.qv_dt inputs["ql_dt"] = microph_state.ql_dt diff --git a/tests/savepoint/translate/translate_phifv3.py b/tests/savepoint/translate/translate_phifv3.py index d43d71fc..0fc53d08 100644 --- a/tests/savepoint/translate/translate_phifv3.py +++ b/tests/savepoint/translate/translate_phifv3.py @@ -15,7 +15,7 @@ def __init__(self, grid, namelist, stencil_factory): "out_roll_zero": True, }, "phii": {"serialname": "phi_phii"}, - "phil": {"serialname": "phi_phil", "kend": namelist.npz - 1}, + "phil": {"serialname": "phi_phil", "kend": self.config.npz - 1}, } self.out_vars = { "del_gz": self.in_vars["data_vars"]["del_gz"], diff --git a/tests/savepoint/translate/translate_physics.py b/tests/savepoint/translate/translate_physics.py index 353e85ab..d406f3b1 100644 --- a/tests/savepoint/translate/translate_physics.py +++ b/tests/savepoint/translate/translate_physics.py @@ -47,7 +47,7 @@ def transform_dwind_serialized_data(data, grid_indexing: GridIndexing, backend: class TranslatePhysicsFortranData2Py(TranslateFortranData2Py): def __init__(self, grid, namelist, stencil_factory): super().__init__(grid, stencil_factory) - self.namelist = PhysicsConfig.from_namelist(namelist) + self.config = PhysicsConfig.from_f90nml(namelist) # This test wasn't running (on CI) for a long time because it was misconfigured. # Now it's properly configured and temporarily skipped (i.e. still not running @@ -306,5 +306,5 @@ def slice_output(self, inputs, out_data=None): class ParallelPhysicsTranslate2Py(ParallelTranslate2Py): def __init__(self, rank_grids, namelist, stencil_factory): - physics_namelist = PhysicsConfig.from_namelist(namelist) - super().__init__(rank_grids, physics_namelist, stencil_factory) + super().__init__(rank_grids, namelist, stencil_factory) + self.config = PhysicsConfig.from_f90nml(namelist) diff --git a/tests/savepoint/translate/translate_prsfv3.py b/tests/savepoint/translate/translate_prsfv3.py index 9260426f..82fc5f19 100644 --- a/tests/savepoint/translate/translate_prsfv3.py +++ b/tests/savepoint/translate/translate_prsfv3.py @@ -11,7 +11,7 @@ def __init__(self, grid, namelist, stencil_factory): "prsi": {"serialname": "prs_prsi"}, "tgrs": {"serialname": "prs_tgrs"}, "qgrs": {"serialname": "prs_qgrs"}, - "del_": {"serialname": "prs_del", "kend": namelist.npz - 1}, + "del_": {"serialname": "prs_del", "kend": self.config.npz - 1}, "del_gz": {"serialname": "prs_del_gz", "out_roll_zero": True}, } self.out_vars = { diff --git a/tests/savepoint/translate/translate_update_dwind_phys.py b/tests/savepoint/translate/translate_update_dwind_phys.py index 9fd6a89f..8e6fa4be 100644 --- a/tests/savepoint/translate/translate_update_dwind_phys.py +++ b/tests/savepoint/translate/translate_update_dwind_phys.py @@ -16,21 +16,20 @@ def __init__(self, grid, namelist, stencil_factory): "v_dt": {"dwind": True}, } self.out_vars = { - "u": {"dwind": True, "kend": namelist.npz - 1}, - "v": {"dwind": True, "kend": namelist.npz - 1}, + "u": {"dwind": True, "kend": self.config.npz - 1}, + "v": {"dwind": True, "kend": self.config.npz - 1}, } - self.namelist = namelist self.stencil_factory = stencil_factory def compute(self, inputs): self.make_storage_data_input_vars(inputs) - partitioner = TilePartitioner(self.namelist.layout) + partitioner = TilePartitioner(self.config.layout) self.compute_func = AGrid2DGridPhysics( self.stencil_factory, self.grid.quantity_factory, partitioner, self.grid.rank, - self.namelist, + self.config, grid_info=self.grid.driver_grid_data, ) self.compute_func(**inputs) diff --git a/tests/savepoint/translate/translate_update_tracers_phys.py b/tests/savepoint/translate/translate_update_tracers_phys.py index b70f07da..3574ec19 100644 --- a/tests/savepoint/translate/translate_update_tracers_phys.py +++ b/tests/savepoint/translate/translate_update_tracers_phys.py @@ -24,17 +24,17 @@ def __init__(self, grid, namelist, stencil_factory): "u_t0": {"order": "F"}, "v_t0": {"order": "F"}, "pt_t0": {"order": "F"}, - "qvapor_t0": {"dycore": True, "kend": namelist.npz - 1}, - "qliquid_t0": {"dycore": True, "kend": namelist.npz - 1}, - "qrain_t0": {"dycore": True, "kend": namelist.npz - 1}, - "qsnow_t0": {"dycore": True, "kend": namelist.npz - 1}, - "qice_t0": {"dycore": True, "kend": namelist.npz - 1}, - "qgraupel_t0": {"dycore": True, "kend": namelist.npz - 1}, + "qvapor_t0": {"dycore": True, "kend": self.config.npz - 1}, + "qliquid_t0": {"dycore": True, "kend": self.config.npz - 1}, + "qrain_t0": {"dycore": True, "kend": self.config.npz - 1}, + "qsnow_t0": {"dycore": True, "kend": self.config.npz - 1}, + "qice_t0": {"dycore": True, "kend": self.config.npz - 1}, + "qgraupel_t0": {"dycore": True, "kend": self.config.npz - 1}, "prsi": {"serialname": "IPD_prsi", "order": "F"}, "delp": { "dycore": True, "serialname": "IPD_delp", - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, }, } self.in_vars["parameters"] = ["rdt"] @@ -42,30 +42,30 @@ def __init__(self, grid, namelist, stencil_factory): "u_dt": { "dycore": True, "compute": False, - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, }, "v_dt": { "dycore": True, "compute": False, - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, }, "pt_dt": { "serialname": "t_dt", "dycore": True, - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, }, "delp": { "dycore": True, - "kend": namelist.npz - 1, + "kend": self.config.npz - 1, "compute": False, "out_roll_zero": True, }, - "qvapor_t0": {"dycore": True, "kend": namelist.npz - 1, "compute": False}, - "qliquid_t0": {"dycore": True, "kend": namelist.npz - 1, "compute": False}, - "qrain_t0": {"dycore": True, "kend": namelist.npz - 1, "compute": False}, - "qsnow_t0": {"dycore": True, "kend": namelist.npz - 1, "compute": False}, - "qice_t0": {"dycore": True, "kend": namelist.npz - 1, "compute": False}, - "qgraupel_t0": {"dycore": True, "kend": namelist.npz - 1, "compute": False}, + "qvapor_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qliquid_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qrain_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qsnow_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qice_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qgraupel_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, } self.compute_func = stencil_factory.from_origin_domain( prepare_tendencies_and_update_tracers, From 69db7c7217fb3ba40b6de9864c4bae528802d676 Mon Sep 17 00:00:00 2001 From: Janice Kim Date: Tue, 21 Oct 2025 17:05:05 -0400 Subject: [PATCH 2/3] linting --- tests/savepoint/translate/translate_fpvs.py | 1 - .../translate/translate_fv_update_phys.py | 2 +- .../translate/translate_gfs_physics_driver.py | 4 ++-- .../translate/translate_update_tracers_phys.py | 18 +++++++++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/tests/savepoint/translate/translate_fpvs.py b/tests/savepoint/translate/translate_fpvs.py index 58260944..39b2ddc8 100644 --- a/tests/savepoint/translate/translate_fpvs.py +++ b/tests/savepoint/translate/translate_fpvs.py @@ -1,5 +1,4 @@ import numpy as np - from f90nml import Namelist from ndsl import StencilFactory diff --git a/tests/savepoint/translate/translate_fv_update_phys.py b/tests/savepoint/translate/translate_fv_update_phys.py index f1a68556..99761e80 100644 --- a/tests/savepoint/translate/translate_fv_update_phys.py +++ b/tests/savepoint/translate/translate_fv_update_phys.py @@ -1,7 +1,7 @@ import dataclasses -from f90nml import Namelist import numpy as np +from f90nml import Namelist import ndsl.dsl.gt4py_utils as utils from ndsl import Quantity, StencilFactory diff --git a/tests/savepoint/translate/translate_gfs_physics_driver.py b/tests/savepoint/translate/translate_gfs_physics_driver.py index 2e0edfab..86ef7ee6 100644 --- a/tests/savepoint/translate/translate_gfs_physics_driver.py +++ b/tests/savepoint/translate/translate_gfs_physics_driver.py @@ -2,7 +2,7 @@ import ndsl.dsl.gt4py_utils as utils from ndsl import QuantityFactory, SubtileGridSizer -from pyshield import PHYSICS_PACKAGES, Physics, PhysicsConfig, PhysicsState +from pyshield import PHYSICS_PACKAGES, Physics, PhysicsState from pyshield.update import update_atmos_state from tests.savepoint.translate.translate_physics import TranslatePhysicsFortranData2Py @@ -140,7 +140,7 @@ def compute(self, inputs): self.grid.grid_data, self.config, ) - # TODO, PhysicsConfig doesn't have fv_sg_adj + # TODO, PhysicsConfig doesn't have fv_sg_adj # either move where GFSPhysicsDriver starts, or pass the full namelist or # get around this issue another way. Setting do_dry_convective_adjustment # to False for now (we don't run this on a case where it is True yet) diff --git a/tests/savepoint/translate/translate_update_tracers_phys.py b/tests/savepoint/translate/translate_update_tracers_phys.py index 3574ec19..ea1b2ce1 100644 --- a/tests/savepoint/translate/translate_update_tracers_phys.py +++ b/tests/savepoint/translate/translate_update_tracers_phys.py @@ -60,12 +60,24 @@ def __init__(self, grid, namelist, stencil_factory): "compute": False, "out_roll_zero": True, }, - "qvapor_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, - "qliquid_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qvapor_t0": { + "dycore": True, + "kend": self.config.npz - 1, + "compute": False, + }, + "qliquid_t0": { + "dycore": True, + "kend": self.config.npz - 1, + "compute": False, + }, "qrain_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, "qsnow_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, "qice_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, - "qgraupel_t0": {"dycore": True, "kend": self.config.npz - 1, "compute": False}, + "qgraupel_t0": { + "dycore": True, + "kend": self.config.npz - 1, + "compute": False, + }, } self.compute_func = stencil_factory.from_origin_domain( prepare_tendencies_and_update_tracers, From 6846d6291ecabe5239415230589a77a4471e8c76 Mon Sep 17 00:00:00 2001 From: Janice Kim Date: Mon, 27 Oct 2025 12:40:53 -0400 Subject: [PATCH 3/3] Small fixed based on PR #68 comments --- pyshield/_config.py | 6 +++--- tests/savepoint/translate/translate_fv_update_phys.py | 6 ------ tests/savepoint/translate/translate_gfs_physics_driver.py | 2 -- 3 files changed, 3 insertions(+), 11 deletions(-) diff --git a/pyshield/_config.py b/pyshield/_config.py index 877034c1..56530a6d 100644 --- a/pyshield/_config.py +++ b/pyshield/_config.py @@ -192,7 +192,8 @@ def from_f90nml( use when initializing the PhysicsConfig. If None, all groups will be used. (Default: DEFAULT_PHYS_NML_GROUPS) """ - nml_dict = f90nml_as_dict(nml, flatten=True, target_groups=target_groups) + groups = list(target_groups) if target_groups is not None else None + nml_dict = f90nml_as_dict(nml, flatten=True, target_groups=groups) nml_dict["target_nml_groups"] = target_groups return cls.from_dict(nml_dict) @@ -216,5 +217,4 @@ def from_dict( Tuple[str, ...]: lambda x: tuple(x) if x is not None else None, }, ) - config = from_dict(data_class=PhysicsConfig, data=data, config=dacite_config) - return config + return from_dict(data_class=PhysicsConfig, data=data, config=dacite_config) diff --git a/tests/savepoint/translate/translate_fv_update_phys.py b/tests/savepoint/translate/translate_fv_update_phys.py index 99761e80..84e4a20c 100644 --- a/tests/savepoint/translate/translate_fv_update_phys.py +++ b/tests/savepoint/translate/translate_fv_update_phys.py @@ -15,12 +15,6 @@ ) -try: - import cupy as cp -except ImportError: - cp = None - - try: import cupy as cp except ImportError: diff --git a/tests/savepoint/translate/translate_gfs_physics_driver.py b/tests/savepoint/translate/translate_gfs_physics_driver.py index 86ef7ee6..cf3a9272 100644 --- a/tests/savepoint/translate/translate_gfs_physics_driver.py +++ b/tests/savepoint/translate/translate_gfs_physics_driver.py @@ -10,8 +10,6 @@ class TranslateGFSPhysicsDriver(TranslatePhysicsFortranData2Py): def __init__(self, grid, namelist, stencil_factory): super().__init__(grid, namelist, stencil_factory) - # using top level namelist rather than PhysicsConfig - # because DycoreToPhysics needs some dycore info self.in_vars["data_vars"] = { "qvapor": {"dycore": True}, "qliquid": {"dycore": True},