Skip to content

Conversation

@VeckoTheGecko
Copy link
Contributor

This PR supercedes #2447
implementing the following additional functionality:

  • Refactor out the FieldSet.from_nemo() functionality into a convert.py module with a nemo_to_sgrid() function. Also added corresponding tests.
  • Make the input parameters of the nemo_to_sgrid function more closely align with the input datasets
  • Update FieldSet.from_sgrid_conventions to infer mesh from the metadata included in the dataset
  • Add get_value_by_id() function to Grid*DMetadata classes allowing to easily refer to parts of the SGRID metadata model

Future work:

  • Improve logging and metadata conversion convert.py - its important that we refactor this module so that its clearer, and have logging so that changes to the input dataset are communicated to the user. To support this, we need
  • Better testing against different NEMO datasets
    • Reach out to the NEMO community asking for ncdump output so that better see the types of nemo models out there

I'll make an issue to track this future work.

erikvansebille and others added 28 commits January 9, 2026 16:24
And update of tutorial_nemo_curvilinear
And updating tutorial
ANd expading comments on loading in the dataset
To use same ordering as in XLinear
This requires smaller selection_dict for the isel, so hopefully faster code
And also separating offset calculation into its own helper function
It's not clear why this is here, nor why removing it causes a test failure. To be investigated another time.

EDIT: This was introduced in
Parcels-code@c311fba
- though we're investigating if this can be implemented another way
  since there should be no particular difference with NEMO
Gradually reducing the dependency on the `mesh` param
Updates the API for conversion to be more closely aligned with the input data. Also handles the U and V fields separately - correctly assigning the dimension naming before merging into a single dataset.
Avoid assuming there's a U and V field. Maybe this should be refactored later...
@VeckoTheGecko VeckoTheGecko force-pushed the fieldset_from_nemo-nick branch from 6d12f21 to 0b9c787 Compare January 9, 2026 15:25
@VeckoTheGecko
Copy link
Contributor Author

I'll do a full self review next week. Feel free to take a look in the meantime @erikvansebille if you'd like

@VeckoTheGecko
Copy link
Contributor Author

Also still a few failing tests that I need to sort out...

Copy link
Member

@erikvansebille erikvansebille left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice already. Some first comments below

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This and other tutorials still need to be updated to use the new convert workflow? Do you want me to do that? Could be a good test-case how user-friendly the convert functions are

:titlesonly:
examples/explanation_grids.md
examples/tutorial_nemo_curvilinear.ipynb
examples/tutorial_nemo_3D.ipynb
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the file is at examples_v3/tutorial_nemo_3D.ipynb so it either has to be moved (which then destroys the git diff), or we use the old directory here and then update it in a later PR?

Suggested change
examples/tutorial_nemo_3D.ipynb
examples_v3/tutorial_nemo_3D.ipynb # TODO move to examples folder

return _metadata_rename_dims(self, dims_dict)

def get_value_by_id(self, id: str) -> str:
"""In the SGRID specification different parts of the spec are identified to with different "ID"s.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""In the SGRID specification different parts of the spec are identified to with different "ID"s.
"""In the SGRID specification for 2D grids, different parts of the spec are identified by different "ID"s.

return _metadata_rename_dims(self, dims_dict)

def get_value_by_id(self, id: str) -> str:
"""In the SGRID specification different parts of the spec are identified to with different "ID"s.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""In the SGRID specification different parts of the spec are identified to with different "ID"s.
"""In the SGRID specification for 3D grids, different parts of the spec are identified by different "ID"s.

Comment on lines +373 to +375
vector_interp_method=CGrid_Velocity,
# ^Seems to work with AGrid as well? (at least, tests aren't failing -
# either logic needs to be added to choose interpolator, or this interpolator should be renamed)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, this is part of the changes to unit converters in #2455, #2459 and #2461.

In #2461, I propose we attach a new XLinear_Velocity interpolator for A-Grids, for consistency/transparency, but that can be done in a later pR (when the others have merged too)

fields["W"] = Field("W", ds["W"], grid, XLinear)
fields["UVW"] = VectorField("UVW", fields["U"], fields["V"], fields["W"])
fields["UVW"] = VectorField(
"UVW", fields["U"], fields["V"], fields["W"], vector_interp_method=CGrid_Velocity
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here, it would depend on the grid topology whether we use XLinear_Velocity or CGrid_Velocity

Comment on lines +388 to +392
if mesh == "spherical":
if "U" in fieldset.fields:
fieldset.U.units = GeographicPolar()
if "V" in fieldset.fields:
fieldset.V.units = Geographic()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would all go if we implement #2459. We need to be careful when fixing merge conflicts...

These functions use knowledge about the model to attach any missing metadata. The functions
emit verbose messaging so that the user is kept in the loop. The returned output is an
Xarray dataset so that users can further provide any missing metadata that was unable to
be determined.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
be determined.
be determined before they pass it to the FieldSet constructor.

}


def _maybe_bring_UV_depths_to_depth(ds):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would all the functions in this convert file require verbose logging? Or is that too much?

pytest.param(
AdvectionRK4_3D,
marks=pytest.mark.xfail(
reason="from_nemo had 'fieldset.V.units = GeographicPolar()', I'm not sure _why_ this code is needed to get this to pass. To be further investigated.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed in the changes that come with #2455, #2459 and #2461

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

2 participants