Skip to content
Snippets Groups Projects

Draft: adding cpp version of codes

Open Pradipta Samanta requested to merge feature-add-cpp-codes into main
1 unresolved thread
Compare and Show latest version
1 file
+ 123
0
Compare changes
  • Side-by-side
  • Inline
+ 123
0
#include <gtest/gtest.h>
#include <Kokkos_Core.hpp>
#include <vector>
#include "mo_lib_interpolation_vector.hpp"
// Dimensions for the test (small, trivial test).
// We assume Fortran ordering: column-major, but our C wrappers will wrap raw pointers into Kokkos::Views with LayoutLeft.
constexpr int nproma = 2;
constexpr int nlev = 3;
constexpr int nblks_e = 2; // For the edge arrays (p_vn_in, p_vt_in)
constexpr int nblks_c = 2; // For the cell arrays and interpolation coefficients
// For the get_indices_c_lib inputs.
constexpr int i_startblk = 0;
constexpr int i_endblk = 1; // two blocks: indices 0 and 1
constexpr int i_startidx_in = 0;
constexpr int i_endidx_in = nproma - 1; // 0 and 1
constexpr int slev = 0;
constexpr int elev = nlev - 1; // 0 .. 2
// Helper to compute total number of elements for a 3D array stored in column-major order.
template<typename T>
size_t num_elements(int dim1, int dim2, int dim3) {
return static_cast<size_t>(dim1) * dim2 * dim3;
}
// Test for the double precision (dp) version.
TEST(Edges2CellsTest, DPTest) {
// Allocate and fill input arrays.
std::vector<double> p_vn_in(num_elements<double>(nproma, nlev, nblks_e), 1.0);
std::vector<double> p_vt_in(num_elements<double>(nproma, nlev, nblks_e), 1.0);
// cell_edge_idx and cell_edge_blk: dimensions [nproma, nblks_c, 3]
std::vector<int> cell_edge_idx(num_elements<int>(nproma, nblks_c, 3), 1);
std::vector<int> cell_edge_blk(num_elements<int>(nproma, nblks_c, 3), 1);
// Here we set cell_edge_idx to 1, 2, 1 for every triple.
for (int i = 0; i < num_elements<int>(nproma, nblks_c, 3); i += 3) {
cell_edge_idx[i] = 1;
cell_edge_idx[i+1] = 2;
cell_edge_idx[i+2] = 1;
}
// Similarly, set cell_edge_blk to all ones (valid since nblks_e=2, so index 1 means block 0 after subtracting 1).
// e_bln_c_u and e_bln_c_v: dimensions [nproma, 6, nblks_c]
std::vector<double> e_bln_c_u(num_elements<double>(nproma, 6, nblks_c), 1.0);
std::vector<double> e_bln_c_v(num_elements<double>(nproma, 6, nblks_c), 1.0);
// Output arrays: dimensions [nproma, nlev, nblks_c]
std::vector<double> p_u_out(num_elements<double>(nproma, nlev, nblks_c), 0.0);
std::vector<double> p_v_out(num_elements<double>(nproma, nlev, nblks_c), 0.0);
std::vector<double> p_u_ref(num_elements<double>(nproma, nlev, nblks_c), 6.0);
std::vector<double> p_v_ref(num_elements<double>(nproma, nlev, nblks_c), 6.0);
// Call the dp (double precision) version.
edges2cells_vector_lib_dp(
p_vn_in.data(), p_vt_in.data(),
cell_edge_idx.data(), cell_edge_blk.data(),
e_bln_c_u.data(), e_bln_c_v.data(),
p_u_out.data(), p_v_out.data(),
i_startblk, i_endblk,
i_startidx_in, i_endidx_in,
slev, elev,
nproma,
nlev, nblks_e, nblks_c);
// Check that for each computed cell in p_u_out and p_v_out, the value is 6.
// This is because for each cell, the kernel adds 6 terms of 1*1.
p_u_ref[0] = 0.0;
p_u_ref[8] = 0.0;
p_u_ref[10] = 0.0;
p_v_ref[0] = 0.0;
p_v_ref[8] = 0.0;
p_v_ref[10] = 0.0;
for (size_t idx = 0; idx < p_u_out.size(); ++idx) {
EXPECT_NEAR(p_u_out[idx], p_u_ref[idx], 1e-12);
EXPECT_NEAR(p_v_out[idx], p_v_ref[idx], 1e-12);
}
}
// Test for the single precision (sp) version.
TEST(Edges2CellsTest, SPTest) {
// Allocate and fill input arrays.
std::vector<float> p_vn_in(num_elements<float>(nproma, nlev, nblks_e), 1.0f);
std::vector<float> p_vt_in(num_elements<float>(nproma, nlev, nblks_e), 1.0f);
std::vector<int> cell_edge_idx(num_elements<int>(nproma, nblks_c, 3), 1);
std::vector<int> cell_edge_blk(num_elements<int>(nproma, nblks_c, 3), 1);
// Set cell_edge_idx values to 1, 2, 1.
for (int i = 0; i < num_elements<int>(nproma, nblks_c, 3); i += 3) {
cell_edge_idx[i] = 1;
cell_edge_idx[i+1] = 2;
cell_edge_idx[i+2] = 1;
}
std::vector<float> e_bln_c_u(num_elements<float>(nproma, 6, nblks_c), 1.0f);
std::vector<float> e_bln_c_v(num_elements<float>(nproma, 6, nblks_c), 1.0f);
std::vector<float> p_u_out(num_elements<float>(nproma, nlev, nblks_c), 0.0f);
std::vector<float> p_v_out(num_elements<float>(nproma, nlev, nblks_c), 0.0f);
std::vector<float> p_u_ref(num_elements<float>(nproma, nlev, nblks_c), 6.0f);
std::vector<float> p_v_ref(num_elements<float>(nproma, nlev, nblks_c), 6.0f);
// Call the sp (float precision) version.
edges2cells_vector_lib_sp(
p_vn_in.data(), p_vt_in.data(),
cell_edge_idx.data(), cell_edge_blk.data(),
e_bln_c_u.data(), e_bln_c_v.data(),
p_u_out.data(), p_v_out.data(),
i_startblk, i_endblk,
i_startidx_in, i_endidx_in,
slev, elev,
nproma,
nlev, nblks_e, nblks_c);
p_u_ref[0] = 0.0f;
p_u_ref[8] = 0.0f;
p_u_ref[10] = 0.0f;
p_v_ref[0] = 0.0f;
p_v_ref[8] = 0.0f;
p_v_ref[10] = 0.0f;
// Verify that every computed output equals 6.
for (size_t idx = 0; idx < p_u_out.size(); ++idx) {
EXPECT_NEAR(p_u_out[idx], p_u_ref[idx], 1e-5f);
EXPECT_NEAR(p_v_out[idx], p_v_ref[idx], 1e-5f);
}
}
Loading