1- # cmip7_prep/regrid.py
1+
22"""Regridding utilities for CESM -> 1° lat/lon using precomputed ESMF weights."""
33from __future__ import annotations
44from dataclasses import dataclass
1010import numpy as np
1111
1212# Default weight maps; override via function args.
13- DEFAULT_CONS_MAP = Path ("map_ne30pg3_to_1x1d_aave.nc" )
14- DEFAULT_BILIN_MAP = Path ("" ) # optional bilinear map
13+ DEFAULT_CONS_MAP = Path ("/glade/campaign/cesm/cesmdata/inputdata/cpl/gridmaps/ne30pg3/ map_ne30pg3_to_1x1d_aave.nc" )
14+ DEFAULT_BILIN_MAP = Path ("/glade/campaign/cesm/cesmdata/inputdata/cpl/gridmaps/ne30pg3/map_ne30pg3_to_1x1d_bilin.nc " ) # optional bilinear map
1515
1616# Variables treated as "intensive" → prefer bilinear when available.
1717INTENSIVE_VARS = {
@@ -26,16 +26,37 @@ class MapSpec:
2626 path : Path
2727
2828class _RegridderCache :
29- """Cache of xESMF Regridders constructed from weight files."""
29+ """Cache of xESMF Regridders constructed from weight files.
30+
31+ This avoids reconstructing regridders for the same weight file multiple times
32+ and provides a small API to fetch or clear cached instances.
33+ """
3034 _cache : Dict [Path , xe .Regridder ] = {}
3135
3236 @classmethod
3337 def get (cls , mapfile : Path , method_label : str ) -> xe .Regridder :
38+ """Return a cached regridder for the given weight file and method.
39+
40+ If no regridder exists yet for `mapfile`, it is created using xESMF with
41+ `filename=mapfile` (so source/destination grids are read from the weight
42+ file) and stored in the cache. Subsequent calls reuse the same instance.
43+
44+ Parameters
45+ ----------
46+ mapfile : Path
47+ Path to an ESMF weight file.
48+ method_label : str
49+ xESMF method label; used only for constructor parity.
50+
51+ Returns
52+ -------
53+ xe.Regridder
54+ Cached or newly created regridder.
55+ """
3456 mapfile = mapfile .expanduser ().resolve ()
3557 if mapfile not in cls ._cache :
3658 if not mapfile .exists ():
3759 raise FileNotFoundError (f"Regrid weights not found: { mapfile } " )
38- # With filename=..., xESMF reads grids from the weight file.
3960 cls ._cache [mapfile ] = xe .Regridder (
4061 xr .Dataset (), xr .Dataset (),
4162 method = method_label ,
@@ -44,6 +65,11 @@ def get(cls, mapfile: Path, method_label: str) -> xe.Regridder:
4465 )
4566 return cls ._cache [mapfile ]
4667
68+ @classmethod
69+ def clear (cls ) -> None :
70+ """Clear all cached regridders (useful for tests or releasing resources)."""
71+ cls ._cache .clear ()
72+
4773def _pick_maps (
4874 varname : str ,
4975 conservative_map : Optional [Path ] = None ,
@@ -202,4 +228,3 @@ def regrid_mask_or_area(
202228 pass
203229
204230 return out
205-
0 commit comments