Skip to content

Bilinear interpolation for ParaGrid - #1102

Open
einola wants to merge 17 commits into
issue1101_base_branchfrom
issue1101_bilinear
Open

Bilinear interpolation for ParaGrid#1102
einola wants to merge 17 commits into
issue1101_base_branchfrom
issue1101_bilinear

Conversation

@einola

@einola einola commented Aug 3, 2026

Copy link
Copy Markdown
Member

Bilinear interpolation for ParaGrid

Fixes subs 1 and 2 of #1101

Task List

  • Linked an issue above that captures the requirements of this PR
  • Defined the tests that specify a complete and functioning change
  • Implemented the source code change that satisfies the tests
  • Commented all code so that it can be understood without additional context
  • No new warnings are generated or they are mentioned below
  • The documentation has been updated (or an issue has been created to do so)
  • Relevant labels (e.g., enhancement, bug) have been applied to this PR
  • This change conforms to the conventions described in the README

Change Description

I've implemented a new class for reading in forcing data, called ParaGridInputs. The name will change, and this class will be integrated into the IParaGridIO interface later. The idea here is to submit the initial working example to a different branch, so the final PR won't be too large.

Key changes:

  • A new class for reading data in from the "raw" netCDF files for TOPAZ4 and ERA5
  • Bilinear interpolation for both lat/lon grids and grids with lat and lon as 2D arrays.
  • TOPAZOCean and ERA5Atmosphere both use this class now
  • Python scripts to "flood" the TOPAZ4 fields to handle mismatches in land mask

Test Description

No tests so far, beyond checking that the interpolated fields look ok on output. The vectors still point in the wrong directions, so don't expect dynamics to run correctly for very long.


Documentation Impact

Documentation about using different I/O interfaces needs to come later.


Other Details

Switching between different I/O interfaces and vector rotation comes later.

einola added 12 commits August 3, 2026 16:12
I ended up implementing a new class, called ParaGridInputs. This may
change later. An object of this class holds information about the input
data, as well as the raw data from before and after the current time
step. Calling 'update' loads new raw data, if needed, rotates vectors on
the original grid, and then interpolates the resulting fields onto the
model grid. Calling 'getField' returns a temporal interpolation between
the data from before and after the current time step. As it stands now,
no interpolation or vector rotation is implemented, but it seems like
the pre-processed data is read in correctly.
This includes implementing weights calculation for the two lat/lon
representation posibilities; a Mercator projection (lat and lon are two
vectors --- untested!) and a general projection with lat and lon as 2D
fields. Lots of refactoring and fixing as well.
I do this, so that we can read in variables from different files as part
of the same data set (as is the case with ERA5, for example).
This required some fixing of setWeights1D and refactoring that affects
the rest of the class. Nothing is well tested so far, beyond looking at
the output fields.
And some cleaning up. I now use FloatType for everything except time.
A small python class to "flood" a dataset's land points with near-by
values. This uses a Delaunay triangulation to calculate the values over
land, meaning that only the convex hull can be filled. This is probably
sensible anyway - we don't want to extrapolate. There's also a function
to fill land points with zeros. The class depends on there being a land
mask available and unique coordinates for the rows and columns. Re-use
of the Delaunay triangulation is ChatGPT code.

This is particularly useful for ocean forcing data, but may also be used
to flood atmospheric forcing (aka "drowning").
Now that we read in "pure" ERA5 data, we must expect Kelvins, and
convert.
Some netCDF files (notably the ERA5 files) save the values as a short,
plus a scale_factor and offset. We now support that through
NetCDFUtils::readNetCDFVar.
There's something not right with the way they're handled ... but they
were zeroed out earlier, so this belongs with a different issue.
I don't know why the static_assert wasn't triggered before, though.
A simple script taking advantage of the flooding.py class to flood the
TOPAZ4 files. This is a prerequsite for running the new code, as the
mask created by make_init_geographic.py may not overlap with the TOPAZ
land mask.
This is to make sure that the new interpolation done in flooding.py fits
with the land mask, i.e. that we don't get ocean cells in the land mask
where there are NaNs in the forcing. Also, some minor fixes.
@einola einola added this to the 3 Stand-alone model milestone Aug 3, 2026
@einola einola added the enhancement New feature or request label Aug 3, 2026
@einola
einola requested a review from timspainNERSC August 3, 2026 14:40
einola added 2 commits August 3, 2026 16:54
Ruff wants me to reformat things.
@einola einola mentioned this pull request Aug 13, 2026
8 tasks
einola added 3 commits August 13, 2026 11:21
It works correctly now, but I'm not sure if I need to be this careful.
Shouldn't it be enough to just wrap to a fixed bound (like [-180 180]).
We can reasonably assume that it's only ever the latitude axis that is
flipped.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Development

Successfully merging this pull request may close these issues.

1 participant