Skip to content
Snippets Groups Projects

Tested the c++ codes run on GPUs and fixed unit tests associated with them

Open Pradipta Samanta requested to merge fix-cpp-codes-gpu into feature-add-cpp-codes
All threads resolved!
1 file
+ 251
189
Compare changes
  • Side-by-side
  • Inline
+ 251
189
@@ -14,14 +14,13 @@
#include <vector>
#include <Kokkos_Core.hpp>
#include <gtest/gtest.h>
#include <dim_helper.hpp>
#include <gtest/gtest.h>
#include <horizontal/mo_lib_divrot.hpp>
#include <support/mo_lib_loopindices.hpp>
/// Test class for the horizontal divergence tests. Templated for the ValueType
template <typename ValueType>
class HorizontalDivTest : public ::testing::Test {
template <typename ValueType> class HorizontalDivTest : public ::testing::Test {
protected:
static constexpr int nproma = 3; // inner loop length
static constexpr int nlev = 2; // number of vertical levels
@@ -37,26 +36,26 @@ protected:
std::vector<int> elev;
bool lacc = false; // Not using ACC-specific behavior.
// Here we allocate Kokkos::View objects in a memory space that is directly accessible
// from both the host and device
// Here we allocate Kokkos::View objects in a memory space that is directly
// accessible from both the host and device
using exec_space = Kokkos::DefaultExecutionSpace;
using memory_space = exec_space::memory_space;
// Views for the test data. All the data is assigned as one-dimensional arrays
Kokkos::View<ValueType*, memory_space> vec_e;
Kokkos::View<int*, memory_space> cell_edge_idx;
Kokkos::View<int*, memory_space> cell_edge_blk;
Kokkos::View<ValueType*, memory_space> geofac_div;
Kokkos::View<ValueType*, memory_space> div_vec_c;
Kokkos::View<ValueType*, memory_space> f4din;
Kokkos::View<ValueType*, memory_space> f4dout;
Kokkos::View<ValueType *, memory_space> vec_e;
Kokkos::View<int *, memory_space> cell_edge_idx;
Kokkos::View<int *, memory_space> cell_edge_blk;
Kokkos::View<ValueType *, memory_space> geofac_div;
Kokkos::View<ValueType *, memory_space> div_vec_c;
Kokkos::View<ValueType *, memory_space> f4din;
Kokkos::View<ValueType *, memory_space> f4dout;
// Followings are needed in HorizontalDivAvgTest
Kokkos::View<int*, memory_space> cell_neighbor_idx;
Kokkos::View<int*, memory_space> cell_neighbor_blk;
Kokkos::View<ValueType*, memory_space> avg_coeff;
Kokkos::View<ValueType*, memory_space> opt_in2;
Kokkos::View<ValueType*, memory_space> opt_out2;
Kokkos::View<int *, memory_space> cell_neighbor_idx;
Kokkos::View<int *, memory_space> cell_neighbor_blk;
Kokkos::View<ValueType *, memory_space> avg_coeff;
Kokkos::View<ValueType *, memory_space> opt_in2;
Kokkos::View<ValueType *, memory_space> opt_out2;
HorizontalDivTest()
: vec_e("vec_e", dim_combine(nproma, nlev, nblks_e)),
@@ -70,13 +69,12 @@ protected:
cell_neighbor_blk("cell_neighbor_blk", dim_combine(nproma, nblks_c, 3)),
avg_coeff("avg_coeff", dim_combine(nproma, 4, nblks_c)),
opt_in2("opt_in2", dim_combine(nproma, nlev, nblks_e)),
opt_out2("opt_out2", dim_combine(nproma, nlev, nblks_c))
{
opt_out2("opt_out2", dim_combine(nproma, nlev, nblks_c)) {
// We keep slev and elev as std::vector since they are small and used only on the host.
// We keep slev and elev as std::vector since they are small and used only
// on the host.
slev.resize(dim4d, 0);
elev.resize(dim4d, nlev); // Full vertical range (0 .. nlev-1)
}
};
@@ -126,8 +124,8 @@ TYPED_TEST(HorizontalDivTest, TestDiv3DSpecific) {
div_vec_c_h[div_vec_c_at(i, k, 0)] = static_cast<TypeParam>(0.0);
}
}
// Copy the initialized data back to the device memory (or unified memory, which in some
// cases may be a no-op if already accessible on the host).
// Copy the initialized data back to the device memory (or unified memory,
// which in some cases may be a no-op if already accessible on the host).
Kokkos::deep_copy(this->vec_e, vec_e_h);
Kokkos::deep_copy(this->cell_edge_idx, cell_edge_idx_h);
Kokkos::deep_copy(this->cell_edge_blk, cell_edge_blk_h);
@@ -144,12 +142,18 @@ TYPED_TEST(HorizontalDivTest, TestDiv3DSpecific) {
Kokkos::deep_copy(div_vec_c_h, this->div_vec_c);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(0, 0, 0)), static_cast<TypeParam>(1.7), 1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(0, 1, 0)), static_cast<TypeParam>(3.4), 1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(1, 0, 0)), static_cast<TypeParam>(2.1), 1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(1, 1, 0)), static_cast<TypeParam>(4.2), 1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(2, 0, 0)), static_cast<TypeParam>(2.2), 1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(2, 1, 0)), static_cast<TypeParam>(4.4), 1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(0, 0, 0)), static_cast<TypeParam>(1.7),
1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(0, 1, 0)), static_cast<TypeParam>(3.4),
1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(1, 0, 0)), static_cast<TypeParam>(2.1),
1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(1, 1, 0)), static_cast<TypeParam>(4.2),
1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(2, 0, 0)), static_cast<TypeParam>(2.2),
1e-6);
EXPECT_NEAR(div_vec_c_h(div_vec_c_at(2, 1, 0)), static_cast<TypeParam>(4.4),
1e-6);
}
TYPED_TEST(HorizontalDivTest, TestDiv3DRandom) {
@@ -163,7 +167,7 @@ TYPED_TEST(HorizontalDivTest, TestDiv3DRandom) {
const auto &geofac_div_at = at<nproma, 3, nblks_c>;
const auto &div_vec_c_at = at<nproma, nlev, nblks_c>;
//create mirror views to store data on the host
// create mirror views to store data on the host
auto vec_e_h = Kokkos::create_mirror_view(this->vec_e);
auto cell_edge_idx_h = Kokkos::create_mirror_view(this->cell_edge_idx);
auto cell_edge_blk_h = Kokkos::create_mirror_view(this->cell_edge_blk);
@@ -201,12 +205,12 @@ TYPED_TEST(HorizontalDivTest, TestDiv3DRandom) {
Kokkos::deep_copy(this->geofac_div, geofac_div_h);
Kokkos::deep_copy(this->div_vec_c, div_vec_c_h);
div3d<TypeParam>(
this->vec_e.data(), this->cell_edge_idx.data(), this->cell_edge_blk.data(),
this->geofac_div.data(), this->div_vec_c.data(), this->i_startblk,
this->i_endblk, this->i_startidx_in, this->i_endidx_in, this->slev[0],
this->elev[0], this->nproma, this->lacc, this->nlev, this->nblks_c,
this->nblks_e);
div3d<TypeParam>(this->vec_e.data(), this->cell_edge_idx.data(),
this->cell_edge_blk.data(), this->geofac_div.data(),
this->div_vec_c.data(), this->i_startblk, this->i_endblk,
this->i_startidx_in, this->i_endidx_in, this->slev[0],
this->elev[0], this->nproma, this->lacc, this->nlev,
this->nblks_c, this->nblks_e);
Kokkos::deep_copy(div_vec_c_h, this->div_vec_c);
@@ -221,17 +225,14 @@ TYPED_TEST(HorizontalDivTest, TestDiv3DRandom) {
for (int jk = this->slev[0]; jk < this->elev[0]; ++jk) {
for (int jc = i_startidx; jc < i_endidx; ++jc) {
ref_div_vec_c[div_vec_c_at(jc, jk, jb)] =
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
geofac_div_h[geofac_div_at(jc, 0, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
geofac_div_h[geofac_div_at(jc, 1, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
geofac_div_h[geofac_div_at(jc, 2, jb)];
}
}
@@ -273,8 +274,10 @@ TYPED_TEST(HorizontalDivTest, TestDiv3D2FSpecific) {
// Initialization with specific values
for (int i = 0; i < nproma; ++i) {
for (int k = 0; k < nlev; ++k) {
vec_e_h[vec_e_at(i, k, 0)] = static_cast<TypeParam>((i + 1) * (k + 1)); // Simple pattern
f4din_h[f4d_at(i, k, 0, 0)] = static_cast<TypeParam>((i + 1) * (k + 2)); // Different pattern for second field
vec_e_h[vec_e_at(i, k, 0)] =
static_cast<TypeParam>((i + 1) * (k + 1)); // Simple pattern
f4din_h[f4d_at(i, k, 0, 0)] = static_cast<TypeParam>(
(i + 1) * (k + 2)); // Different pattern for second field
}
// Set edge indices to point to specific cells (including self)
@@ -322,20 +325,32 @@ TYPED_TEST(HorizontalDivTest, TestDiv3D2FSpecific) {
Kokkos::deep_copy(f4dout_h, this->f4dout);
// Check first field (same as in div3d test)
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(1.7), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(3.4), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(2.1), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(4.2), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(2.2), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(4.4), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(1.7),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(3.4),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(2.1),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(4.2),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(2.2),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(4.4),
1e-6);
// Check second field (expected values calculated manually)
EXPECT_NEAR(f4dout_h[f4dout_at(0, 0, 0, 0)], static_cast<TypeParam>(3.4), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 1, 0, 0)], static_cast<TypeParam>(5.1), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 0, 0, 0)], static_cast<TypeParam>(4.2), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 1, 0, 0)], static_cast<TypeParam>(6.3), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 0, 0, 0)], static_cast<TypeParam>(4.4), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 1, 0, 0)], static_cast<TypeParam>(6.6), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 0, 0, 0)], static_cast<TypeParam>(3.4),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 1, 0, 0)], static_cast<TypeParam>(5.1),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 0, 0, 0)], static_cast<TypeParam>(4.2),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 1, 0, 0)], static_cast<TypeParam>(6.3),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 0, 0, 0)], static_cast<TypeParam>(4.4),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 1, 0, 0)], static_cast<TypeParam>(6.6),
1e-6);
}
TYPED_TEST(HorizontalDivTest, TestDiv3D2FRandom) {
@@ -377,7 +392,8 @@ TYPED_TEST(HorizontalDivTest, TestDiv3D2FRandom) {
// Set random edge indices
for (int j = 0; j < 3; ++j) {
cell_edge_idx_h[cell_edge_at(i, 0, j)] = int_distrib(gen);
cell_edge_blk_h[cell_edge_at(i, 0, j)] = 0; // Keep in same block for simplicity
cell_edge_blk_h[cell_edge_at(i, 0, j)] =
0; // Keep in same block for simplicity
}
// Random geometric factors
@@ -402,12 +418,13 @@ TYPED_TEST(HorizontalDivTest, TestDiv3D2FRandom) {
Kokkos::deep_copy(this->f4dout, f4dout_h);
// Call the div3d_2field function
div3d_2field<TypeParam>(
this->vec_e.data(), this->cell_edge_idx.data(), this->cell_edge_blk.data(),
this->geofac_div.data(), this->div_vec_c.data(), this->f4din.data(),
this->f4dout.data(), this->i_startblk, this->i_endblk, this->i_startidx_in,
this->i_endidx_in, this->slev[0], this->elev[0], this->nproma, this->lacc,
this->nlev, this->nblks_c, this->nblks_e);
div3d_2field<TypeParam>(this->vec_e.data(), this->cell_edge_idx.data(),
this->cell_edge_blk.data(), this->geofac_div.data(),
this->div_vec_c.data(), this->f4din.data(),
this->f4dout.data(), this->i_startblk, this->i_endblk,
this->i_startidx_in, this->i_endidx_in, this->slev[0],
this->elev[0], this->nproma, this->lacc, this->nlev,
this->nblks_c, this->nblks_e);
// Copy results back to host for verification
Kokkos::deep_copy(div_vec_c_h, this->div_vec_c);
@@ -426,32 +443,26 @@ TYPED_TEST(HorizontalDivTest, TestDiv3D2FRandom) {
for (int jc = i_startidx; jc < i_endidx; ++jc) {
// Calculate reference value for first field
ref_div_vec_c[div_vec_c_at(jc, jk, jb)] =
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
geofac_div_h[geofac_div_at(jc, 0, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
geofac_div_h[geofac_div_at(jc, 1, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
geofac_div_h[geofac_div_at(jc, 2, jb)];
// Calculate reference value for second field
ref_f4dout[f4dout_at(jc, jk, jb, 0)] =
f4din_h[f4d_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)], 0)] *
f4din_h[f4d_at(cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)], 0)] *
geofac_div_h[geofac_div_at(jc, 0, jb)] +
f4din_h[f4d_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)], 0)] *
f4din_h[f4d_at(cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)], 0)] *
geofac_div_h[geofac_div_at(jc, 1, jb)] +
f4din_h[f4d_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)], 0)] *
f4din_h[f4d_at(cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)], 0)] *
geofac_div_h[geofac_div_at(jc, 2, jb)];
}
}
@@ -500,7 +511,8 @@ TYPED_TEST(HorizontalDivTest, TestDiv4DSpecific) {
for (int j = 0; j < 3; ++j) {
cell_edge_idx_h[cell_edge_at(i, 0, j)] = (i + j) % nproma;
cell_edge_blk_h[cell_edge_at(i, 0, j)] = 0;
geofac_div_h[geofac_div_at(i, j, 0)] = static_cast<TypeParam>(0.1 * (j + 1));
geofac_div_h[geofac_div_at(i, j, 0)] =
static_cast<TypeParam>(0.1 * (j + 1));
}
for (int k = 0; k < nlev; ++k) {
@@ -519,28 +531,40 @@ TYPED_TEST(HorizontalDivTest, TestDiv4DSpecific) {
Kokkos::deep_copy(this->f4dout, f4dout_h);
// Test function
div4d<TypeParam>(
this->cell_edge_idx.data(), this->cell_edge_blk.data(),
this->geofac_div.data(), this->f4din.data(), this->f4dout.data(),
this->dim4d, this->i_startblk, this->i_endblk, this->i_startidx_in,
this->i_endidx_in, this->slev.data(), this->elev.data(), this->nproma,
this->lacc, this->nlev, this->nblks_c, this->nblks_e);
div4d<TypeParam>(this->cell_edge_idx.data(), this->cell_edge_blk.data(),
this->geofac_div.data(), this->f4din.data(),
this->f4dout.data(), this->dim4d, this->i_startblk,
this->i_endblk, this->i_startidx_in, this->i_endidx_in,
this->slev.data(), this->elev.data(), this->nproma,
this->lacc, this->nlev, this->nblks_c, this->nblks_e);
// Copy results back to host for verification
Kokkos::deep_copy(f4dout_h, this->f4dout);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 0, 0, 0)], static_cast<TypeParam>(1.4), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 0, 0, 0)], static_cast<TypeParam>(1.1), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 0, 0, 0)], static_cast<TypeParam>(1.1), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 1, 0, 0)], static_cast<TypeParam>(2.0), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 1, 0, 0)], static_cast<TypeParam>(1.7), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 1, 0, 0)], static_cast<TypeParam>(1.7), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 0, 0, 1)], static_cast<TypeParam>(2.0), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 0, 0, 1)], static_cast<TypeParam>(1.7), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 0, 0, 1)], static_cast<TypeParam>(1.7), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 1, 0, 1)], static_cast<TypeParam>(2.6), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 1, 0, 1)], static_cast<TypeParam>(2.3), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 1, 0, 1)], static_cast<TypeParam>(2.3), 1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 0, 0, 0)], static_cast<TypeParam>(1.4),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 0, 0, 0)], static_cast<TypeParam>(1.1),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 0, 0, 0)], static_cast<TypeParam>(1.1),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 1, 0, 0)], static_cast<TypeParam>(2.0),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 1, 0, 0)], static_cast<TypeParam>(1.7),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 1, 0, 0)], static_cast<TypeParam>(1.7),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 0, 0, 1)], static_cast<TypeParam>(2.0),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 0, 0, 1)], static_cast<TypeParam>(1.7),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 0, 0, 1)], static_cast<TypeParam>(1.7),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(0, 1, 0, 1)], static_cast<TypeParam>(2.6),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(1, 1, 0, 1)], static_cast<TypeParam>(2.3),
1e-6);
EXPECT_NEAR(f4dout_h[f4dout_at(2, 1, 0, 1)], static_cast<TypeParam>(2.3),
1e-6);
}
TYPED_TEST(HorizontalDivTest, TestDiv4DRandom) {
@@ -591,12 +615,12 @@ TYPED_TEST(HorizontalDivTest, TestDiv4DRandom) {
Kokkos::deep_copy(this->f4dout, f4dout_h);
// Test function
div4d<TypeParam>(
this->cell_edge_idx.data(), this->cell_edge_blk.data(),
this->geofac_div.data(), this->f4din.data(), this->f4dout.data(),
this->dim4d, this->i_startblk, this->i_endblk, this->i_startidx_in,
this->i_endidx_in, this->slev.data(), this->elev.data(), this->nproma,
this->lacc, this->nlev, this->nblks_c, this->nblks_e);
div4d<TypeParam>(this->cell_edge_idx.data(), this->cell_edge_blk.data(),
this->geofac_div.data(), this->f4din.data(),
this->f4dout.data(), this->dim4d, this->i_startblk,
this->i_endblk, this->i_startidx_in, this->i_endidx_in,
this->slev.data(), this->elev.data(), this->nproma,
this->lacc, this->nlev, this->nblks_c, this->nblks_e);
// Copy results back to host for verification
Kokkos::deep_copy(f4dout_h, this->f4dout);
@@ -612,11 +636,10 @@ TYPED_TEST(HorizontalDivTest, TestDiv4DRandom) {
for (int jc = i_startidx; jc < i_endidx; ++jc) {
TypeParam expected = 0.0;
for (int je = 0; je < 3; ++je) {
expected +=
f4din_h[f4din_at(
cell_edge_idx_h[cell_edge_at(jc, jb, je)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, je)], ji)] *
geofac_div_h[geofac_div_at(jc, je, jb)];
expected += f4din_h[f4din_at(
cell_edge_idx_h[cell_edge_at(jc, jb, je)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, je)], ji)] *
geofac_div_h[geofac_div_at(jc, je, jb)];
}
EXPECT_NEAR(f4dout_h[f4dout_at(jc, jk, jb, ji)], expected, 1e-5)
@@ -656,8 +679,10 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecific) {
// Create mirror views to store data on the host
auto vec_e_h = Kokkos::create_mirror_view(this->vec_e);
auto cell_neighbor_idx_h = Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h = Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_neighbor_idx_h =
Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h =
Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_edge_idx_h = Kokkos::create_mirror_view(this->cell_edge_idx);
auto cell_edge_blk_h = Kokkos::create_mirror_view(this->cell_edge_blk);
auto geofac_div_h = Kokkos::create_mirror_view(this->geofac_div);
@@ -669,8 +694,10 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecific) {
// Initialize the vectors with specific values
for (int i = 0; i < nproma; ++i) {
for (int k = 0; k < nlev; ++k) {
vec_e_h[vec_e_at(i, k, 0)] = static_cast<TypeParam>((i + 1) * (k + 1)); // Simple pattern
opt_in2_h[vec_e_at(i, k, 0)] = static_cast<TypeParam>((i + 1) * (k + 1) * 0.5); // Half of vec_e
vec_e_h[vec_e_at(i, k, 0)] =
static_cast<TypeParam>((i + 1) * (k + 1)); // Simple pattern
opt_in2_h[vec_e_at(i, k, 0)] =
static_cast<TypeParam>((i + 1) * (k + 1) * 0.5); // Half of vec_e
}
// Set edge indices to point to specific cells
@@ -696,9 +723,12 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecific) {
// Average coefficients
avg_coeff_h[avg_coeff_at(i, 0, 0)] = static_cast<TypeParam>(0.4); // Self
avg_coeff_h[avg_coeff_at(i, 1, 0)] = static_cast<TypeParam>(0.2); // First neighbor
avg_coeff_h[avg_coeff_at(i, 2, 0)] = static_cast<TypeParam>(0.2); // Second neighbor
avg_coeff_h[avg_coeff_at(i, 3, 0)] = static_cast<TypeParam>(0.2); // Third neighbor
avg_coeff_h[avg_coeff_at(i, 1, 0)] =
static_cast<TypeParam>(0.2); // First neighbor
avg_coeff_h[avg_coeff_at(i, 2, 0)] =
static_cast<TypeParam>(0.2); // Second neighbor
avg_coeff_h[avg_coeff_at(i, 3, 0)] =
static_cast<TypeParam>(0.2); // Third neighbor
// Initialize div_vec_c and opt_out2 to zero
for (int k = 0; k < nlev; ++k) {
@@ -735,20 +765,32 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecific) {
Kokkos::deep_copy(opt_out2_h, this->opt_out2);
// Verify first field results
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(1.88), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(3.76), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(2.04), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(4.08), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(2.08), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(4.16), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(1.88),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(3.76),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(2.04),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(4.08),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(2.08),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(4.16),
1e-6);
// Verify second field results
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(0.94), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(1.88), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(1.02), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(2.04), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(1.04), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(2.08), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(0.94),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(1.88),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(1.02),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(2.04),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(1.04),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(2.08),
1e-6);
}
TYPED_TEST(HorizontalDivTest, TestDivAvgRandom) {
@@ -778,8 +820,10 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandom) {
// Create mirror views to store data on the host
auto vec_e_h = Kokkos::create_mirror_view(this->vec_e);
auto cell_neighbor_idx_h = Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h = Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_neighbor_idx_h =
Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h =
Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_edge_idx_h = Kokkos::create_mirror_view(this->cell_edge_idx);
auto cell_edge_blk_h = Kokkos::create_mirror_view(this->cell_edge_blk);
auto geofac_div_h = Kokkos::create_mirror_view(this->geofac_div);
@@ -804,10 +848,12 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandom) {
// Set random edge indices
for (int j = 0; j < 3; ++j) {
cell_edge_idx_h[cell_edge_at(i, 0, j)] = int_distrib(gen);
cell_edge_blk_h[cell_edge_at(i, 0, j)] = 0; // Keep in same block for simplicity
cell_edge_blk_h[cell_edge_at(i, 0, j)] =
0; // Keep in same block for simplicity
cell_neighbor_idx_h[cell_neighbor_at(i, 0, j)] = int_distrib(gen);
cell_neighbor_blk_h[cell_neighbor_at(i, 0, j)] = 0; // Keep in same block for simplicity
cell_neighbor_blk_h[cell_neighbor_at(i, 0, j)] =
0; // Keep in same block for simplicity
}
// Random geometric factors
@@ -869,31 +915,25 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandom) {
for (int jk = this->slev[0]; jk < this->elev[0]; ++jk) {
for (int jc = i_startidx; jc < i_endidx; ++jc) {
aux_c[div_vec_c_at(jc, jk, jb)] =
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
geofac_div_h[geofac_div_at(jc, 0, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
geofac_div_h[geofac_div_at(jc, 1, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
geofac_div_h[geofac_div_at(jc, 2, jb)];
aux_c2[div_vec_c_at(jc, jk, jb)] =
opt_in2_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
opt_in2_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
geofac_div_h[geofac_div_at(jc, 0, jb)] +
opt_in2_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
opt_in2_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
geofac_div_h[geofac_div_at(jc, 1, jb)] +
opt_in2_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
opt_in2_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
geofac_div_h[geofac_div_at(jc, 2, jb)];
}
}
@@ -1000,8 +1040,10 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecificNoL2fields) {
// Create mirror views to store data on the host
auto vec_e_h = Kokkos::create_mirror_view(this->vec_e);
auto cell_neighbor_idx_h = Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h = Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_neighbor_idx_h =
Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h =
Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_edge_idx_h = Kokkos::create_mirror_view(this->cell_edge_idx);
auto cell_edge_blk_h = Kokkos::create_mirror_view(this->cell_edge_blk);
auto geofac_div_h = Kokkos::create_mirror_view(this->geofac_div);
@@ -1013,8 +1055,10 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecificNoL2fields) {
// Initialize the vectors with specific values
for (int i = 0; i < nproma; ++i) {
for (int k = 0; k < nlev; ++k) {
vec_e_h[vec_e_at(i, k, 0)] = static_cast<TypeParam>((i + 1) * (k + 1)); // Simple pattern
opt_in2_h[vec_e_at(i, k, 0)] = static_cast<TypeParam>((i + 1) * (k + 1) * 0.5); // Half of vec_e
vec_e_h[vec_e_at(i, k, 0)] =
static_cast<TypeParam>((i + 1) * (k + 1)); // Simple pattern
opt_in2_h[vec_e_at(i, k, 0)] =
static_cast<TypeParam>((i + 1) * (k + 1) * 0.5); // Half of vec_e
}
// Set edge indices to point to specific cells
@@ -1040,9 +1084,12 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecificNoL2fields) {
// Average coefficients
avg_coeff_h[avg_coeff_at(i, 0, 0)] = static_cast<TypeParam>(0.4); // Self
avg_coeff_h[avg_coeff_at(i, 1, 0)] = static_cast<TypeParam>(0.2); // First neighbor
avg_coeff_h[avg_coeff_at(i, 2, 0)] = static_cast<TypeParam>(0.2); // Second neighbor
avg_coeff_h[avg_coeff_at(i, 3, 0)] = static_cast<TypeParam>(0.2); // Third neighbor
avg_coeff_h[avg_coeff_at(i, 1, 0)] =
static_cast<TypeParam>(0.2); // First neighbor
avg_coeff_h[avg_coeff_at(i, 2, 0)] =
static_cast<TypeParam>(0.2); // Second neighbor
avg_coeff_h[avg_coeff_at(i, 3, 0)] =
static_cast<TypeParam>(0.2); // Third neighbor
// Initialize div_vec_c and opt_out2 to zero
for (int k = 0; k < nlev; ++k) {
@@ -1079,20 +1126,32 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgSpecificNoL2fields) {
Kokkos::deep_copy(opt_out2_h, this->opt_out2);
// Verify first field results
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(1.88), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(3.76), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(2.04), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(4.08), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(2.08), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(4.16), 1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(1.88),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(3.76),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(2.04),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(4.08),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(2.08),
1e-6);
EXPECT_NEAR(div_vec_c_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(4.16),
1e-6);
// Since l2fields=false, opt_out2 should not be modified
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(0.0), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(0.0), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(0.0), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(0.0), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(0.0), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(0.0), 1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 0, 0)], static_cast<TypeParam>(0.0),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(0, 1, 0)], static_cast<TypeParam>(0.0),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 0, 0)], static_cast<TypeParam>(0.0),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(1, 1, 0)], static_cast<TypeParam>(0.0),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 0, 0)], static_cast<TypeParam>(0.0),
1e-6);
EXPECT_NEAR(opt_out2_h[div_vec_c_at(2, 1, 0)], static_cast<TypeParam>(0.0),
1e-6);
}
TYPED_TEST(HorizontalDivTest, TestDivAvgRandomNoL2fields) {
@@ -1122,8 +1181,10 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandomNoL2fields) {
// Create mirror views to store data on the host
auto vec_e_h = Kokkos::create_mirror_view(this->vec_e);
auto cell_neighbor_idx_h = Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h = Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_neighbor_idx_h =
Kokkos::create_mirror_view(this->cell_neighbor_idx);
auto cell_neighbor_blk_h =
Kokkos::create_mirror_view(this->cell_neighbor_blk);
auto cell_edge_idx_h = Kokkos::create_mirror_view(this->cell_edge_idx);
auto cell_edge_blk_h = Kokkos::create_mirror_view(this->cell_edge_blk);
auto geofac_div_h = Kokkos::create_mirror_view(this->geofac_div);
@@ -1142,16 +1203,19 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandomNoL2fields) {
for (int i = 0; i < nproma; ++i) {
for (int k = 0; k < nlev; ++k) {
vec_e_h[vec_e_at(i, k, 0)] = real_distrib(gen);
opt_in2_h[vec_e_at(i, k, 0)] = real_distrib(gen); // Not used but initialize anyway
opt_in2_h[vec_e_at(i, k, 0)] =
real_distrib(gen); // Not used but initialize anyway
}
// Set random edge indices
for (int j = 0; j < 3; ++j) {
cell_edge_idx_h[cell_edge_at(i, 0, j)] = int_distrib(gen);
cell_edge_blk_h[cell_edge_at(i, 0, j)] = 0; // Keep in same block for simplicity
cell_edge_blk_h[cell_edge_at(i, 0, j)] =
0; // Keep in same block for simplicity
cell_neighbor_idx_h[cell_neighbor_at(i, 0, j)] = int_distrib(gen);
cell_neighbor_blk_h[cell_neighbor_at(i, 0, j)] = 0; // Keep in same block for simplicity
cell_neighbor_blk_h[cell_neighbor_at(i, 0, j)] =
0; // Keep in same block for simplicity
}
// Random geometric factors
@@ -1167,7 +1231,8 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandomNoL2fields) {
// Random initial values for div_vec_c and opt_out2
for (int k = 0; k < nlev; ++k) {
div_vec_c_h[div_vec_c_at(i, k, 0)] = static_cast<TypeParam>(0.0);
opt_out2_h[div_vec_c_at(i, k, 0)] = static_cast<TypeParam>(0.0); // Not used but initialize anyway
opt_out2_h[div_vec_c_at(i, k, 0)] =
static_cast<TypeParam>(0.0); // Not used but initialize anyway
}
}
@@ -1211,17 +1276,14 @@ TYPED_TEST(HorizontalDivTest, TestDivAvgRandomNoL2fields) {
for (int jk = this->slev[0]; jk < this->elev[0]; ++jk) {
for (int jc = i_startidx; jc < i_endidx; ++jc) {
aux_c[div_vec_c_at(jc, jk, jb)] =
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 0)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 0)])] *
geofac_div_h[geofac_div_at(jc, 0, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 1)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 1)])] *
geofac_div_h[geofac_div_at(jc, 1, jb)] +
vec_e_h[vec_e_at(
cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
vec_e_h[vec_e_at(cell_edge_idx_h[cell_edge_at(jc, jb, 2)], jk,
cell_edge_blk_h[cell_edge_at(jc, jb, 2)])] *
geofac_div_h[geofac_div_at(jc, 2, jb)];
}
}
Loading