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

Add regional interpolation #215

Merged

Conversation

benjaminmenetrier
Copy link
Contributor

This PR adds a new interpolation for regional structured source grids, available with the factory tag "regional-linear-2d". It uses a generic sparse matrix element class InterpElement added in interpolation/element, that might also be used for vertical interpolation in the future.

An associated test has been added, which defines field values on a coarse source grid, interpolates on a refined target grid, and compute the target field hash on each MPI task (2 tasks requested for this test).

The PR also includes a bugfix in functionspace/detail/StructuredColumns_setup.cc: it seems that the field xy is actually corresponding to the lonlat values for all structured grids. However, this was not true in develop for regional grids. I have implemented a minimal bugfix where the correct values of lonlat are specified in the xy field for regional grids too.

@benjaminmenetrier
Copy link
Contributor Author

It seems the hash test is failing depending on the compiler, I'll do it differently.

@benjaminmenetrier
Copy link
Contributor Author

The new test is working.

@benjaminmenetrier
Copy link
Contributor Author

I have extended the regional interpolation test : accuracy and adjoint tests, for both 1D and 2D fields.

Copy link
Member

@wdeconinck wdeconinck left a comment

Choose a reason for hiding this comment

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

This is a very nice addition @benjaminmenetrier and will be very useful!
This is just a first review without having played around with this feature yet, and sorry that it has taken this long.
Just looking through the code I could find some performance / memory issues that need to be addressed. Please have a look.

Comment on lines 314 to 317
std::vector<bool> toFind = {true, !colocatedX, !colocatedY, !colocatedX && !colocatedY};
std::vector<size_t> valueToFind = {indexI*sourceNy+indexJ, (indexI+1)*sourceNy+indexJ,
indexI*sourceNy+(indexJ+1), (indexI+1)*sourceNy+(indexJ+1)};
std::vector<int> foundIndex(4, -1);
Copy link
Member

Choose a reason for hiding this comment

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

Since these are always size 4, it will be much better to use std::array<type,4> instead of std::vector<type>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

} else {
indexJ = sourceNy-1;
}
std::cout << "WARNING: point outside of the domain" << std::endl;
Copy link
Member

Choose a reason for hiding this comment

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

Please use "Log::info()" or "Log::error()"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

std::vector<int> targetRecvCounts_;
std::vector<int> targetRecvDispls_;
std::vector<size_t> sourceSendMapping_;
std::vector<atlas::interpolation::element::InterpElement> horInterp_;
Copy link
Member

Choose a reason for hiding this comment

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

std::vector<atlas::interpolation::element::InterpElement> in current implementation of InterpElement is essentially the same as
std::vector<std::vector<std::pair<size_t,double>>>

The issue is std::vector<std::vector< ... >> because that infers multiple allocations on the heap within tight loop and slow memory access.
I'm thinking to avoid the InterpElement class altogether (and remove the file etc.)

What would be better is multiple arrays:

std::vector< std::array<size_t,4> > stencil_;
std::vector< std::array<double,4> > weights_;
std::vector< size_t > stencil_size_;

and then resize all these arrays to targetSize_ before looping over target points, and fill the values at the correct place in these arrays, without using the temporary operations variable. This will also allow this loop to become OpenMP multi-threadable.

These 3 vectors are now each one large memory allocation because the memory of std::array<type,4> is known at compile time.
We need the stencil_size_ array to avoid going into possibly over-allocated entries in case of linear interpolation or point value, which will almost never be the case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great suggestion. For regional DA, we often interpolate from a grid to another one with exactly the same rectangular domain, and just a different cell size, so stencil_size_ might be lower than 4 quite often.

xy(gp.r, XX) = compute_x(gp.i, gp.j);
xy(gp.r, YY) = compute_y(gp.j);
if (regional) {
std::vector<double> lonlatVec(2);
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
std::vector<double> lonlatVec(2);
std::array<double,2> lonlatVec;

This avoids heap allocation within the loop over grid points, and should give very nice speedup.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@benjaminmenetrier
Copy link
Contributor Author

Thank you very much @wdeconinck for your very relevant comments. I realize that I am not well aware of memory usage in C++ and should be more careful about it.

Copy link
Member

@wdeconinck wdeconinck left a comment

Choose a reason for hiding this comment

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

Thank you for this nice development, and thank you for addressing the suggestions.

@wdeconinck wdeconinck merged commit 5de0a4b into ecmwf:develop Sep 16, 2024
163 of 164 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants