Skip to content

Commit 89d0590

Browse files
Creating convert.mitgcm_to_sgrid
1 parent f644537 commit 89d0590

File tree

1 file changed

+91
-1
lines changed

1 file changed

+91
-1
lines changed

src/parcels/convert.py

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,25 @@
4242
"wo": "W",
4343
}
4444

45+
_MITGCM_AXIS_VARNAMES = {
46+
"XC": "X",
47+
"XG": "X",
48+
"lon": "X",
49+
"YC": "Y",
50+
"YG": "Y",
51+
"lat": "Y",
52+
"Zu": "Z",
53+
"Zl": "Z",
54+
"Zp1": "Z",
55+
"time": "T",
56+
}
57+
58+
_MITGCM_VARNAMES_MAPPING = {
59+
"XG": "lon",
60+
"YG": "lat",
61+
"Zl": "depth",
62+
}
63+
4564
_COPERNICUS_MARINE_AXIS_VARNAMES = {
4665
"X": "lon",
4766
"Y": "lat",
@@ -114,7 +133,8 @@ def _maybe_remove_depth_from_lonlat(ds):
114133

115134
def _set_axis_attrs(ds, dim_axis):
116135
for dim, axis in dim_axis.items():
117-
ds[dim].attrs["axis"] = axis
136+
if dim in ds:
137+
ds[dim].attrs["axis"] = axis
118138
return ds
119139

120140

@@ -128,6 +148,16 @@ def _ds_rename_using_standard_names(ds: xr.Dataset | ux.UxDataset, name_dict: di
128148
return ds
129149

130150

151+
def _maybe_swap_depth_direction(ds: xr.Dataset) -> xr.Dataset:
152+
if ds["depth"].size > 1:
153+
if ds["depth"][0] > ds["depth"][-1]:
154+
logger.info(
155+
"Depth dimension appears to be decreasing upward (i.e., from positive to negative values). Swapping depth dimension to be increasing upward for Parcels simulation."
156+
)
157+
ds = ds.reindex(depth=ds["depth"][::-1])
158+
return ds
159+
160+
131161
# TODO is this function still needed, now that we require users to provide field names explicitly?
132162
def _discover_U_and_V(ds: xr.Dataset, cf_standard_names_fallbacks) -> xr.Dataset:
133163
# Assumes that the dataset has U and V data
@@ -266,6 +296,66 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da
266296
return ds
267297

268298

299+
def mitgcm_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Dataset) -> xr.Dataset:
300+
"""Create an sgrid-compliant xarray.Dataset from a dataset of MITgcm netcdf files.
301+
302+
Parameters
303+
----------
304+
fields : dict[str, xr.Dataset | xr.DataArray]
305+
Dictionary of xarray.DataArray objects as obtained from a set of MITgcm netcdf files.
306+
coords : xarray.Dataset, optional
307+
xarray.Dataset containing coordinate variables.
308+
309+
Returns
310+
-------
311+
xarray.Dataset
312+
Dataset object following SGRID conventions to be (optionally) modified and passed to a FieldSet constructor.
313+
314+
Notes
315+
-----
316+
See the MITgcm tutorial for more information on how to use MITgcm model outputs in Parcels
317+
318+
"""
319+
fields = fields.copy()
320+
321+
for name, field_da in fields.items():
322+
if isinstance(field_da, xr.Dataset):
323+
field_da = field_da[name]
324+
# TODO: logging message, warn if multiple fields are in this dataset
325+
else:
326+
field_da = field_da.rename(name)
327+
fields[name] = field_da
328+
329+
ds = xr.merge(list(fields.values()) + [coords])
330+
ds.attrs.clear() # Clear global attributes from the merging
331+
332+
ds = _maybe_rename_variables(ds, _MITGCM_VARNAMES_MAPPING)
333+
# ds = _set_axis_attrs(ds, _MITGCM_AXIS_VARNAMES)
334+
ds = _maybe_swap_depth_direction(ds)
335+
336+
if "grid" in ds.cf.cf_roles:
337+
raise ValueError(
338+
"Dataset already has a 'grid' variable (according to cf_roles). Didn't expect there to be grid metadata on copernicusmarine datasets - please open an issue with more information about your dataset."
339+
)
340+
341+
ds["grid"] = xr.DataArray(
342+
0,
343+
attrs=sgrid.Grid2DMetadata(
344+
cf_role="grid_topology",
345+
topology_dimension=2,
346+
node_dimensions=("lon", "lat"),
347+
node_coordinates=("lon", "lat"),
348+
face_dimensions=(
349+
sgrid.DimDimPadding("XC", "lon", sgrid.Padding.HIGH),
350+
sgrid.DimDimPadding("YC", "lat", sgrid.Padding.HIGH),
351+
),
352+
vertical_dimensions=(sgrid.DimDimPadding("depth", "depth", sgrid.Padding.HIGH),),
353+
).to_attrs(),
354+
)
355+
356+
return ds
357+
358+
269359
def copernicusmarine_to_sgrid(
270360
*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Dataset | None = None
271361
) -> xr.Dataset:

0 commit comments

Comments
 (0)