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

Cubed sphere 2 grid builder #253

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
ef7ff32
Added grid class boilerplate.
odlomax Nov 12, 2024
8b08305
Added simple concrete implementation.
odlomax Nov 12, 2024
9eb6714
Implement methods unrelated to iterators
mo-jonasganderton Nov 13, 2024
fc87cc2
Change name to CS-LFR-<N>-2
mo-jonasganderton Nov 13, 2024
c31e01b
Fix hash and bounding box
mo-jonasganderton Nov 13, 2024
be15e65
Implement CubedSphere2::print()
mo-jonasganderton Nov 13, 2024
4f71180
Calculate the lonlat for a given point index
mo-jonasganderton Nov 14, 2024
960a290
Change lonlat and xy to use Point2
mo-jonasganderton Nov 18, 2024
633194e
Swap xy and lonlat methods
mo-jonasganderton Nov 21, 2024
040ea2a
Remove temporary testing method
mo-jonasganderton Nov 21, 2024
6e800f1
Combine methods to calculate t,i,j into one simpler method
mo-jonasganderton Nov 28, 2024
ac6a8c0
Change arrays to eckit matrices
mo-jonasganderton Nov 28, 2024
3560c0b
Clean up after tij methods change
mo-jonasganderton Nov 28, 2024
b1b5553
Use projection_.xy2lonlat in lonlat
mo-jonasganderton Nov 28, 2024
5a6a202
Improve clarity of generation of xy point
mo-jonasganderton Nov 29, 2024
a2cb41c
Add static_type()
mo-jonasganderton Dec 2, 2024
7e0fd61
Initial implementation of a Cubed Sphere 2 grid builder
mo-jonasganderton Dec 2, 2024
5056085
Remove old variable type_
mo-jonasganderton Dec 2, 2024
5c1f2f0
Create CubedSphere2 with projection
mo-jonasganderton Jan 10, 2025
2aae5ae
Fix typo to use CubedSphere2ProjectionBase
mo-jonasganderton Jan 10, 2025
358ff93
Remove commented code
mo-jonasganderton Jan 13, 2025
5751e2d
Change projection type name
mo-jonasganderton Jan 13, 2025
142ed04
Enable CS2 grid builder in test
mo-jonasganderton Feb 6, 2025
38add69
Add grid_ to constructor with projection
mo-jonasganderton Feb 6, 2025
a1372b8
Remove unused PointAlphaBeta
mo-jonasganderton Feb 6, 2025
06443d9
Remove unused eckit matrix
mo-jonasganderton Feb 6, 2025
2b5666f
Remove commented code
mo-jonasganderton Feb 7, 2025
c7129d5
Remove cubed sphere 2 projection
mo-jonasganderton Feb 12, 2025
dae5b77
Add test for rotated_lonlat projection
mo-jonasganderton Feb 12, 2025
3cf38e4
Add check for unchanged XY points
mo-jonasganderton Feb 12, 2025
3c2da9c
Remove duplicate test
mo-jonasganderton Feb 12, 2025
c424e10
Merge branch 'develop' into feature/cubed_sphere_2_grid_builder
wdeconinck Feb 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/atlas/grid/CubedSphereGrid2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ CubedSphereGrid2::CubedSphereGrid2(idx_t resolution):
CubedSphereGrid2::CubedSphereGrid2(const Grid& grid):
Grid(grid), grid_(cubedsphere_grid2(get())) {}

CubedSphereGrid2::CubedSphereGrid2(idx_t resolution, Projection projection):
Grid(new grid::detail::grid::CubedSphere2(resolution, projection)), grid_(cubedsphere_grid2(get())) {}

} // namespace atlas
1 change: 1 addition & 0 deletions src/atlas/grid/CubedSphereGrid2.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class CubedSphereGrid2 : public atlas::Grid {
public:
CubedSphereGrid2(idx_t resolution);
CubedSphereGrid2(const Grid& grid);
CubedSphereGrid2(idx_t resolution, Projection projection);

bool valid() const { return grid_; };
operator bool() const { return valid(); }
Expand Down
77 changes: 76 additions & 1 deletion src/atlas/grid/detail/grid/CubedSphere2.cc
Original file line number Diff line number Diff line change
@@ -1,25 +1,49 @@
#include "atlas/grid/detail/grid/CubedSphere2.h"

#include <cmath>
#include <iomanip>

#include "atlas/grid/CubedSphereGrid2.h"
#include "atlas/grid/detail/grid/GridBuilder.h"
#include "atlas/grid/detail/grid/GridFactory.h"
#include "atlas/runtime/Exception.h"
#include "eckit/geometry/Sphere.h"
#include "eckit/utils/Hash.h"
#include "eckit/utils/Translator.h"

namespace atlas {
namespace grid {
namespace detail {
namespace grid {

static eckit::Translator<std::string, int> to_int;

// Public methods

CubedSphere2::CubedSphere2(idx_t resolution) : N_(resolution) {}

CubedSphere2::CubedSphere2(idx_t resolution, Projection projection) :
Grid(), N_(resolution) {

// Copy members
util::Config defaultProjConfig;
defaultProjConfig.set("type", "lonlat");
projection_ = projection ? projection : Projection(defaultProjConfig);

// Domain
domain_ = GlobalDomain();
}

std::string CubedSphere2::name() const {
return "CS-LFR-" + std::to_string(N_) + "-2";
}

std::string CubedSphere2::type() const {
return type_;
return static_type();
}

std::string CubedSphere2::static_type() {
return "cubedsphere2";
}

// Provide a unique identification hash for the grid and the projection.
Expand Down Expand Up @@ -125,6 +149,57 @@ PointXYZ CubedSphere2::tangent_to_xyz_coord(const PointXY& tan_coord, idx_t tile
return PointXYZ::normalize(xyz);
}

namespace {
GridFactoryBuilder<CubedSphere2> __register_CubedSphere2(CubedSphere2::static_type());
}

static class cubedsphere2_lfric : public GridBuilder {
public:
cubedsphere2_lfric():
GridBuilder("cubedsphere2_lfric", {"^[Cc][Ss][_-][Ll][Ff][Rr][-_]([1-9][0-9]*)[_-][2]$"},
{"CS-LFR-<N>-2"}) {}

void print(std::ostream& os) const override {
os << std::left << std::setw(20) << "CS-LFR-<n>-2"
<< "Cubed sphere for LFRic";
}

// Factory constructor
const atlas::Grid::Implementation* create(const std::string& name, const Grid::Config& config) const override {
int id;
std::vector<std::string> matches;
if (match(name, matches, id)) {
util::Config gridconf(config);
int N = to_int(matches[0]);
gridconf.set("type", type());
gridconf.set("N", N);
return create(gridconf);
}
return nullptr;
}

// Factory constructor
const atlas::Grid::Implementation* create(const Grid::Config& config) const override {
int N = 0;
if (not config.get("N", N)) {
throw_AssertionFailed("Could not find \"N\" in configuration of cubed sphere grid 2", Here());
}

std::string name = "CS-LFR-" + std::to_string(N) + "-2";
util::Config projconf;
projconf.set("type", "lonlat");

return new CubedSphereGrid2::grid_t(N, Projection(projconf));
}

void force_link() {}

} cubedsphere2_lfric_;

void force_link_CubedSphere2() {
cubedsphere2_lfric_.force_link();
}

} // namespace grid
} // namespace detail
} // namespace grid
Expand Down
5 changes: 2 additions & 3 deletions src/atlas/grid/detail/grid/CubedSphere2.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,11 @@ class CubedSphere2 : public Grid {
using Spec = atlas::util::Config;

CubedSphere2(idx_t resolution);
CubedSphere2(idx_t resolution, Projection projection);

std::string name() const override;
std::string type() const override;
static std::string static_type();
idx_t N() const {return N_;}

void hash(eckit::Hash&) const override;
Expand Down Expand Up @@ -157,8 +159,6 @@ class CubedSphere2 : public Grid {
static constexpr idx_t nTiles_ = 6;

private:
std::string type_ = {"cubedsphere2"};

using Matrix = std::array<std::array<double, 3>, 3>;

/*
Expand All @@ -181,7 +181,6 @@ class CubedSphere2 : public Grid {
{{ {-1, 0, 0}, {0, 1, 0}, {0, 0, 1} }},
{{ {-1, 0, 0}, {0, -1, 0}, {0, 0, -1} }}
}};

};

} // namespace grid
Expand Down
2 changes: 2 additions & 0 deletions src/atlas/grid/detail/grid/GridBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ static void init() {
namespace detail {
namespace grid {
void force_link_CubedSphere();
void force_link_CubedSphere2();
void force_link_Gaussian();
void force_link_LonLat();
void force_link_Regional();
Expand All @@ -130,6 +131,7 @@ void force_link_Regional_var_resolution();

const GridBuilder::Registry& GridBuilder::nameRegistry() {
detail::grid::force_link_CubedSphere();
detail::grid::force_link_CubedSphere2();
detail::grid::force_link_Gaussian();
detail::grid::force_link_LonLat();
detail::grid::force_link_Regional();
Expand Down
50 changes: 34 additions & 16 deletions src/tests/grid/test_cubedsphere_2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,24 @@ namespace test {
namespace {
using Point2 = eckit::geometry::Point2;

// XY/lonlat for a Cubed Sphere, with N = 2
std::vector<Point2> kgo_lonlat {
{-22.5,20.941}, {22.5,20.941}, {-22.5,-20.941}, {22.5,-20.941}, {67.5,20.941}, {112.5,20.941},
{67.5,-20.941}, {112.5,-20.941}, {157.5,20.941}, {-157.5,20.941}, {157.5,-20.941}, {-157.5,-20.941},
{-112.5,20.941}, {-67.5,20.941}, {-112.5,-20.941}, {-67.5,-20.941}, {-45,59.6388}, {-135,59.6388},
{45,59.6388}, {135,59.6388}, {45,-59.6388}, {135,-59.6388}, {-45,-59.6388}, {-135,-59.6388}
};

template <typename point2_derived>
bool compare_2D_points(std::vector<point2_derived> a, std::vector<Point2> b, double tolerance = 1e-4) {
bool compare_2D_points(std::vector<point2_derived> a, std::vector<Point2> b, bool print_diff = true, double tolerance = 1e-4) {
// Uses a tolerance as the values are stored more precisely than they are printed
ATLAS_ASSERT(a.size() == b.size());
bool equal = true;
for (int i = 0; i < b.size(); ++i) {
for (int j = 0; j < 2; ++j) {
if (std::abs(b[i][j] - a[i][j]) > tolerance) {
std::cout << "[" << i << ", " << j << "]\n\t" << a[i][j] << " != " << b[i][j]
<< "\n\tdiff = " << b[i][j] - a[i][j] << std::endl;
if (print_diff) std::cout << "[" << i << ", " << j << "]\n\t" << a[i][j] << " != " << b[i][j]
<< "\n\tdiff = " << b[i][j] - a[i][j] << std::endl;
equal = false;
}
}
Expand All @@ -27,32 +35,24 @@ bool compare_2D_points(std::vector<point2_derived> a, std::vector<Point2> b, dou

CASE("cubed_sphere_instantiation") {
const int n = 2;
const Grid grid = CubedSphereGrid2(n);

EXPECT(grid.name() == "CS-LFR-" + std::to_string(n) + "-2");
const std::string name = "CS-LFR-" + std::to_string(n) + "-2";

const Grid grid = Grid(name);
EXPECT(grid.name() == name);
EXPECT(grid.type() == "cubedsphere2");
EXPECT(grid.size() == n * n * 6);
}

CASE("constructor_with_grid") {
auto grid_og = Grid("O32");
// auto grid_cs = Grid("CS-LFR-4-2"); // The grid factory is implemented in the next PR
auto grid_cs = CubedSphereGrid2(4);
auto grid_cs = Grid("CS-LFR-4-2");
EXPECT( CubedSphereGrid2( grid_og ).valid() == false );
EXPECT( bool(CubedSphereGrid2( grid_og )) == false );
EXPECT( CubedSphereGrid2( grid_cs ).valid() == true );
EXPECT( bool(CubedSphereGrid2( grid_cs )) == true );
}

CASE("cubed_sphere_grid_kgo") {
// Lonlat and XY are both currently lonlat positions
std::vector<Point2> kgo_lonlat { // N = 2
{-22.5,20.941}, {22.5,20.941}, {-22.5,-20.941}, {22.5,-20.941}, {67.5,20.941}, {112.5,20.941},
{67.5,-20.941}, {112.5,-20.941}, {157.5,20.941}, {-157.5,20.941}, {157.5,-20.941}, {-157.5,-20.941},
{-112.5,20.941}, {-67.5,20.941}, {-112.5,-20.941}, {-67.5,-20.941}, {-45,59.6388}, {-135,59.6388},
{45,59.6388}, {135,59.6388}, {45,-59.6388}, {135,-59.6388}, {-45,-59.6388}, {-135,-59.6388}
};

const Grid grid = CubedSphereGrid2(2);

// LonLat
Expand All @@ -74,6 +74,24 @@ CASE("cubed_sphere_grid_kgo") {
EXPECT(compare_2D_points<PointXY>(points_xy, kgo_lonlat));
}

CASE("cubed_sphere_rotated_lonlat") {
const auto grid_rotated = CubedSphereGrid2(2, Projection(util::Config("type", "rotated_lonlat")("north_pole", std::vector<double>{4., 54.})));

// Expect XY points to still match
std::vector<PointXY> points_xy;
for (const auto &xy : grid_rotated.xy()) {
points_xy.push_back(xy);
}
EXPECT(compare_2D_points<PointXY>(points_xy, kgo_lonlat) == true);

// Expect lonlats to be different
std::vector<PointLonLat> points_lonlat;
for (const auto &lonlat : grid_rotated.lonlat()) {
points_lonlat.push_back(lonlat);
}
EXPECT(compare_2D_points<PointLonLat>(points_lonlat, kgo_lonlat, false) == false);
}

} // namespace
} // namespace test
} // namespace atlas
Expand Down
Loading