-
Notifications
You must be signed in to change notification settings - Fork 42
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
New cubed sphere 2 grid #245
base: develop
Are you sure you want to change the base?
New cubed sphere 2 grid #245
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to see a much simpler CS grid! I've added some changes. It's mostly style related. I'm sure @wdeconinck can make some more comments/suggestions.
After this, we should probably plumb the grid into the grid builder.
@wdeconinck, what do you think?
|
||
std::string CubedSphere2::name() const { | ||
return "CS-LFR-" + std::to_string(N_) + "-2"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add some tests to check the return values of these functions. It should be relatively straightforward to add a new section to your test that checks the basic API.
Grid::Spec CubedSphere2::spec() const { | ||
Grid::Spec grid_spec; | ||
|
||
if (type() == "cubedsphere2") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe we need this if, else
structure around the code. Also, for completeness we should add the domain spec to grid_spec
.
// Private methods | ||
|
||
// Get tile of point given global index | ||
int CubedSphere2::get_tile(idx_t n) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this tij
index logic could be a bit more readable and with less duplication if we did:
using CSIndices = std::array<idx_t, 3>;
// Useful to have this a public method
idx_t CubedSphere2::N() const {return N_;}
CSIndices CubedSphere2::get_cs_indices(gidx_t n) const {
ATLAS_ASSERT(n >= size());
const idx_t tile_size = N() * N();
const idx_t t = n / tile_size;
const idx_t ij = n % tile_size;
const idx_t j = ij / N();
const idx_t i = ij % N();
return {t, i, j};
}
You can then use auto [t, i, j] = get_cs_indicies(...)
to set separate t
, i
and j
values if you need to.
idx_t N_; | ||
|
||
// Number of tiles | ||
static const idx_t nTiles_ = 6; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might as well make nTiles_ constexpr
.
|
||
private: | ||
std::string type_ = {"cubedsphere2"}; | ||
static constexpr int lfric_rotations_[6][9] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be more expressive. For example:
using col = int;
using row = std::array<col, 3>;
using matrix = std::array<row, 3>;
std::array<matrix, nTiles_> rotations_ {matrix{row{0, 0, 1},
row{1, 0, 0},
row{0, -1, 0}},
matrix...}
|
||
// Get point between [-pi/4..pi/4] given index and number of points along edge | ||
// Applies offset to get from prime to dual mesh | ||
double CubedSphere2::index_to_curvilinear(idx_t index) const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the intent is clearer if we define:
using PointAlphaBeta = Point2;
PointAlphaBeta CubedSphere2::ij_to_curvilinear_coord(idx_t i, idx_t j) {
const auto get_coord = [&](idx_t idx){
return M_PI / 2 * (-0.5 + (0.5 + idx) / N());
};
return {get_coord(i), get_coord(j)};
}
PointXY CubedSphere2::curvilinear_to_tangent_coord(const PointAlphaBeta& curvi_coord) {
return {std::tan(curvi_coord[0]), std::tan(curvi_coord[1])};
}
PointXYZ CubedSphere2::tangent_to_xyz_coord(const PointXY& tan_coord) {
/// Perform coordinate rotations...
}
void xy(idx_t n, Point2& point) const; | ||
Point2 xy(idx_t n) const; | ||
|
||
void lonlat(idx_t n, Point2& point) const {xy(n, point);} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You want to call projection_.xy2lonlat(xy)
here.
+ lfric_rotations_[tile][8] * base_point[2]; | ||
|
||
// 3. Project the point onto a (cubed)sphere | ||
point[0] = std::atan2(xyz[1], xyz[0]) * rad_to_deg_; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description
Initial implementation of a new cubed sphere grid.
@odlomax and @wdeconinck can both have a look over to recommend any changes - I expect this will have changed once everything else has also been implemented.
Using this implementation generates the following lonlat points - n=12, red=tile0, purple=tile5, darkest point of each colour is tij=0, lightest point is tij=143. This matches the sequence of the points in the LFRic cubed sphere.
Impact
Once everything else is also implemented, this makes the cubed sphere more maintainable.
Checklist