Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restrict size 1 dimension to source field in regridding #250

Closed
ThibHlln opened this issue Aug 25, 2021 · 4 comments · Fixed by #249
Closed

Restrict size 1 dimension to source field in regridding #250

ThibHlln opened this issue Aug 25, 2021 · 4 comments · Fixed by #249
Labels
enhancement New feature or request

Comments

@ThibHlln
Copy link

Hi David, Hi Sadie,

In the regridding functionality, there currently is a restriction on the size of the dimensions of the grid: any dimension needs to be greater than one.

But after some testing, I found out that it is only problematic to have a size 1 dimension on the source grid, but not on the destination grid. Indeed, ESMF only raises an error when the source grid has a size 1 dimension (see https://github.com/esmf-org/esmf/blob/b4c535d3b3925f43ccad78191f40d6c51f6f2e7e/src/Infrastructure/Field/src/ESMF_FieldRegrid.F90#L2840-L2847). I am not sure what is the underlying reason for this restriction in ESMF, and it is surprising that it complains only for the source grid.

Nevertheless, as a user, I see some situations where I could benefit from the ability to regrid to a destination resolution composed of a single grid cell (e.g. pre-process some gridded data to get a lumped value for a given region). Since it seems to be working for all regridding methods, I thought it may be good to lift the restriction on the destination grid in cf-python.

What do you think?
Also, do you have any idea why ESMF would restrict the size 1 dimension on the source grid only?

@davidhassell
Copy link
Collaborator

davidhassell commented Aug 25, 2021

Hi Thibault,

Thanks for putting this together, with the example, and for the ESMF source code link. It's not obvious to me, after a quick look, that subroutine checkGrid is only called for the source grid - is that the case?

It certainly makes sense to me that "bi-linear" needs the source grid dimensions to be greater than 1, but it's not so clear to me why this is needed for the other methods.

In any event, I think allowing size 1 destination grid axes should be OK, as you have found, and your implementation looks fine (I'll make a comment on the PR, too).

@ThibHlln
Copy link
Author

ThibHlln commented Aug 26, 2021

Hi David,

Thank you for having a look at this issue and related PR (and apologies for opening the PR without opening an issue first).

Thanks for putting this together, with the example, and for the ESMF source code link. It's not obvious to me, after a quick look, that subroutine checkGrid is only called for the source grid - is that the case?

No, I agree with you. This was not obvious to me either. This is why I was doing a bit of experimenting with cf-python/esmpy to see pragmatically what works and what does not. I could not find any mention of the requirement for having at least two grid cells in the EMSF Fortran documentation (I looked in sections 12 ESMF_RegridWeightGen, 13 ESMF_Regrid, and 17 GridComp Class).

I have just checked in the Fortran source code, and subroutine checkGrid is called in functions conserve_GridToMesh and b_or_p_GridToMesh, which themselves seem to be called only on the source grid in subroutine ESMF_FieldRegridStoreNX (https://github.com/esmf-org/esmf/blob/b4c535d3b3925f43ccad78191f40d6c51f6f2e7e/src/Infrastructure/Field/src/ESMF_FieldRegrid.F90#L1025, and https://github.com/esmf-org/esmf/blob/b4c535d3b3925f43ccad78191f40d6c51f6f2e7e/src/Infrastructure/Field/src/ESMF_FieldRegrid.F90#L1031-L1032, respectively).

It certainly makes sense to me that "bi-linear" needs the source grid dimensions to be greater than 1, but it's not so clear to me why this is needed for the other methods.

Yes, you are right, now you say it, it does seem essential to have at least two grid cells on each dimension for bilinear interpolation. This may explain why the check is only done on the source grid: you need two points to interpolate between, but the in-between destination location you are interested in can be just one point.

After some more testing, it seems to work with a size 1 source grid for these regridding methods: 'conservative', 'conservative_2nd', 'nearest_stod', 'nearest_dtos' (only 'linear' and 'patch' are raising an error from subroutine checkGrid). Although, you need to remove the squeezing here:

src_data = d.squeeze().transpose(src_order).array
for it to work.

Using the same fields as in #249, you could test this (after removing the squeezing as mentioned above):

for m in ['conservative', 'conservative_2nd', 
          'nearest_stod', 'nearest_dtos']:
    
    fld3 = fld2.regrids(fld1, method=m)
    
    print(fld3.array)

It would be great if we could get it to work from a size 1 source grid for 'conservative' (at least, but for all methods that seem to work would be even better). I could really do with this feature!

@davidhassell
Copy link
Collaborator

Although, you need to remove the squeezing here: https://github.com/NCAS-CMS/cf-pytho/blob/6c4823d83ca0a3b6ca4d6da3a0d09e4c43b38ee1/cf/field.py#L15848 for it to work.

This needs a bit more treatment for the case when non-regridding axes have size 1. In this case we want to squeeze these non-regridding axes, but leave size-1 regridding axes alone. See 7dfb455 for details.

@davidhassell
Copy link
Collaborator

... and the test:

for m in ['conservative', 'conservative_2nd', 
          'nearest_stod', 'nearest_dtos']:
    fld3 = fld2.regrids(fld1, method=m)
    print(fld3.array)

works with 7dfb455, too.

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
None yet
Development

Successfully merging a pull request may close this issue.

2 participants