Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/user_guide/examples/tutorial_croco_3D.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we create a FieldSet object using the `FieldSet.from_croco()` method. Note that CROCO is a C-grid (with similar indexing at MITgcm)."
"Now we create a FieldSet object using the `convert.croco_to_sgrid()` function to first create an S-Grid compliant datatset, and then use that in `FieldSet.from_sgrid_conventions()` to create the FieldSet."
]
},
{
Expand All @@ -86,8 +86,7 @@
" \"Cs_w\": ds_fields[\"Cs_w\"],\n",
"}\n",
"\n",
"coords = ds_fields[[\"x_rho\", \"y_rho\", \"s_w\", \"time\"]]\n",
"ds_fset = parcels.convert.croco_to_sgrid(fields=fields, coords=coords)\n",
"ds_fset = parcels.convert.croco_to_sgrid(fields=fields, coords=ds_fields)\n",
"\n",
"fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset)\n",
"\n",
Expand Down
9 changes: 2 additions & 7 deletions docs/user_guide/examples/tutorial_mitgcm.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@
"id": "3",
"metadata": {},
"source": [
"We can use a combination of `parcels.convert.mitgcm_to_sgrid` and `FieldSet.from_sgrid_conventions` to read in the data. See below for an example.\n",
"\n",
"```{note}\n",
"It is very important that you provide the corner nodes as coordinates when converting MITgcm data to S-grid conventions. These corner nodes are typically called `XG` and `YG` in MITgcm output. Failing to do so will lead to incorrect interpolation of the velocity fields.\n",
"```"
"We can use a combination of `parcels.convert.mitgcm_to_sgrid` and `FieldSet.from_sgrid_conventions` to read in the data. See below for an example."
]
},
{
Expand All @@ -52,9 +48,8 @@
"metadata": {},
"outputs": [],
"source": [
"coords = ds_fields[[\"XG\", \"YG\", \"Zl\", \"time\"]]\n",
"ds_fset = parcels.convert.mitgcm_to_sgrid(\n",
" fields={\"U\": ds_fields.UVEL, \"V\": ds_fields.VVEL}, coords=coords\n",
" fields={\"U\": ds_fields.UVEL, \"V\": ds_fields.VVEL}, coords=ds_fields\n",
")\n",
"fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset)"
]
Expand Down
4 changes: 2 additions & 2 deletions docs/user_guide/examples/tutorial_nemo.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "parcels",
"display_name": "docs",
"language": "python",
"name": "python3"
},
Expand All @@ -383,7 +383,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
"version": "3.14.2"
}
},
"nbformat": 4,
Expand Down
22 changes: 21 additions & 1 deletion src/parcels/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
if typing.TYPE_CHECKING:
import uxarray as ux

_NEMO_EXPECTED_COORDS = ["glamf", "gphif"]

_NEMO_DIMENSION_COORD_NAMES = ["x", "y", "time", "x", "x_center", "y", "y_center", "depth", "glamf", "gphif"]

_NEMO_AXIS_VARNAMES = {
Expand All @@ -42,6 +44,8 @@
"wo": "W",
}

_MITGCM_EXPECTED_COORDS = ["XG", "YG", "Zl"]

_MITGCM_AXIS_VARNAMES = {
"XC": "X",
"XG": "X",
Expand Down Expand Up @@ -70,13 +74,25 @@
"T": "time",
}

_CROCO_EXPECTED_COORDS = ["x_rho", "y_rho", "s_w", "time"]

_CROCO_VARNAMES_MAPPING = {
"x_rho": "lon",
"y_rho": "lat",
"s_w": "depth",
}


def _pick_expected_coords(coords: xr.Dataset, expected_coord_names: list[str]) -> xr.Dataset:
coords_to_use = {}
for name in expected_coord_names:
if name in coords:
coords_to_use[name] = coords[name]
else:
raise ValueError(f"Expected coordinate '{name}' not found in provided coords dataset.")
return xr.Dataset(coords_to_use)


def _maybe_bring_UV_depths_to_depth(ds):
if "U" in ds.variables and "depthu" in ds.U.coords and "depth" in ds.coords:
ds["U"] = ds["U"].assign_coords(depthu=ds["depth"].values).rename({"depthu": "depth"})
Expand Down Expand Up @@ -245,7 +261,7 @@ def nemo_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.Da

"""
fields = fields.copy()
coords = coords[["gphif", "glamf"]]
coords = _pick_expected_coords(coords, _NEMO_EXPECTED_COORDS)

for name, field_da in fields.items():
if isinstance(field_da, xr.Dataset):
Expand Down Expand Up @@ -357,6 +373,8 @@ def mitgcm_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.
field_da = field_da.rename(name)
fields[name] = field_da

coords = _pick_expected_coords(coords, _MITGCM_EXPECTED_COORDS)

ds = xr.merge(list(fields.values()) + [coords])
ds.attrs.clear() # Clear global attributes from the merging

Expand Down Expand Up @@ -417,6 +435,8 @@ def croco_to_sgrid(*, fields: dict[str, xr.Dataset | xr.DataArray], coords: xr.D
field_da = field_da.rename(name)
fields[name] = field_da

coords = _pick_expected_coords(coords, _CROCO_EXPECTED_COORDS)

ds = xr.merge(list(fields.values()) + [coords])
ds.attrs.clear() # Clear global attributes from the merging

Expand Down
3 changes: 1 addition & 2 deletions tests/test_advection.py
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,7 @@ def test_mitgcm():
data_folder = parcels.download_example_dataset("MITgcm_example_data")
ds_fields = xr.open_dataset(data_folder / "mitgcm_UV_surface_zonally_reentrant.nc")

coords = ds_fields[["XG", "YG", "Zl", "time"]]
ds_fset = convert.mitgcm_to_sgrid(fields={"U": ds_fields.UVEL, "V": ds_fields.VVEL}, coords=coords)
ds_fset = convert.mitgcm_to_sgrid(fields={"U": ds_fields.UVEL, "V": ds_fields.VVEL}, coords=ds_fields)
fieldset = FieldSet.from_sgrid_conventions(ds_fset)

npart = 10
Expand Down
6 changes: 2 additions & 4 deletions tests/test_sigmagrids.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ def test_conversion_3DCROCO():
"Cs_w": ds_fields["Cs_w"],
}

coords = ds_fields[["x_rho", "y_rho", "s_w", "time"]]
ds_fset = parcels.convert.croco_to_sgrid(fields=fields, coords=coords)
ds_fset = parcels.convert.croco_to_sgrid(fields=fields, coords=ds_fields)

fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset)
fieldset.add_constant("hc", ds_fields.hc.item())
Expand Down Expand Up @@ -61,8 +60,7 @@ def test_advection_3DCROCO():
"omega": ds_fields["omega"],
}

coords = ds_fields[["x_rho", "y_rho", "s_w", "time"]]
ds_fset = parcels.convert.croco_to_sgrid(fields=fields, coords=coords)
ds_fset = parcels.convert.croco_to_sgrid(fields=fields, coords=ds_fields)

fieldset = parcels.FieldSet.from_sgrid_conventions(ds_fset)
fieldset.add_constant("hc", ds_fields.hc.item())
Expand Down
Loading