Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ d8f14fdddb5ca0fbb32d8e2bf5ac2960d6ac5ce6
ed2117e6d6826a98b6988e2f18c0c34e408563b6
# Added by the bot
4b010b7634aee1045743be80c268d4644522cd29
a71cad2dd6ace5741a754e2ca7daacd4bb094e0e
195 changes: 120 additions & 75 deletions tests/unit/mesh/parallel/test_shiftedmetric.cxx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
#include "bout/build_defines.hxx"

#include "gtest/gtest.h"
#include <type_traits>

#include "../../src/mesh/parallel/shiftedmetricinterp.hxx"
#include "test_extras.hxx"
#include "bout/fft.hxx"
#include "bout/options_io.hxx"
#include "bout/output.hxx"
#include "bout/paralleltransform.hxx"

#if BOUT_HAS_FFTW
#include "fake_mesh.hxx"

// The unit tests use the global mesh
using namespace bout::globals;

template <class Transform>
class ShiftedMetricTest : public ::testing::Test {
public:
ShiftedMetricTest() {
Expand Down Expand Up @@ -41,7 +47,7 @@ class ShiftedMetricTest : public ::testing::Test {
// No call to Coordinates::geometry() needed here

auto coords = mesh->getCoordinates();
coords->setParallelTransform(bout::utils::make_unique<ShiftedMetric>(
coords->setParallelTransform(bout::utils::make_unique<Transform>(
*mesh, CELL_CENTRE, zShift, coords->zlength()(0, 0)));

Field3D input_temp{mesh};
Expand Down Expand Up @@ -90,7 +96,10 @@ class ShiftedMetricTest : public ::testing::Test {
Field3D input;
};

TEST_F(ShiftedMetricTest, ToFieldAligned) {
using ShiftedMetricTypes = ::testing::Types<ShiftedMetric, ShiftedMetricInterp>;
TYPED_TEST_SUITE(ShiftedMetricTest, ShiftedMetricTypes);

TYPED_TEST(ShiftedMetricTest, ToFieldAligned) {
Field3D expected{mesh};
expected.setDirectionY(YDirectionType::Aligned);

Expand Down Expand Up @@ -118,18 +127,18 @@ TEST_F(ShiftedMetricTest, ToFieldAligned) {
{4., 5., 1., 3., 2.},
{2., 4., 3., 5., 1.}}});

Field3D result = toFieldAligned(input);
Field3D result = toFieldAligned(this->input);

EXPECT_TRUE(IsFieldEqual(result, expected, "RGN_ALL", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(fromFieldAligned(result), input));
EXPECT_TRUE(IsFieldEqual(fromFieldAligned(result), this->input));
EXPECT_TRUE(areFieldsCompatible(result, expected));
EXPECT_FALSE(areFieldsCompatible(result, input));
EXPECT_FALSE(areFieldsCompatible(result, this->input));
}

TEST_F(ShiftedMetricTest, FromFieldAligned) {
TYPED_TEST(ShiftedMetricTest, FromFieldAligned) {
// reset input.yDirectionType so that fromFieldAligned is not a null
// operation
input.setDirectionY(YDirectionType::Aligned);
this->input.setDirectionY(YDirectionType::Aligned);

Field3D expected{mesh, CELL_CENTRE};
expected.setDirectionY(YDirectionType::Standard);
Expand Down Expand Up @@ -158,28 +167,32 @@ TEST_F(ShiftedMetricTest, FromFieldAligned) {
{2., 4., 5., 1., 3.},
{5., 1., 2., 4., 3.}}});

Field3D result = fromFieldAligned(input);
Field3D result = fromFieldAligned(this->input);

// Loosen tolerance a bit due to FFTs
EXPECT_TRUE(IsFieldEqual(result, expected, "RGN_ALL", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(toFieldAligned(result), input, "RGN_ALL", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(toFieldAligned(result), this->input, "RGN_ALL", FFTTolerance));
EXPECT_TRUE(areFieldsCompatible(result, expected));
EXPECT_FALSE(areFieldsCompatible(result, input));
EXPECT_FALSE(areFieldsCompatible(result, this->input));
}

TEST_F(ShiftedMetricTest, FromToFieldAligned) {
EXPECT_TRUE(IsFieldEqual(fromFieldAligned(toFieldAligned(input)), input, "RGN_ALL",
FFTTolerance));
TYPED_TEST(ShiftedMetricTest, FromToFieldAligned) {
EXPECT_TRUE(IsFieldEqual(fromFieldAligned(toFieldAligned(this->input)), this->input,
"RGN_ALL", FFTTolerance));
}

TEST_F(ShiftedMetricTest, ToFromFieldAligned) {
input.setDirectionY(YDirectionType::Aligned);
TYPED_TEST(ShiftedMetricTest, ToFromFieldAligned) {
this->input.setDirectionY(YDirectionType::Aligned);

EXPECT_TRUE(IsFieldEqual(toFieldAligned(fromFieldAligned(input)), input, "RGN_ALL",
FFTTolerance));
EXPECT_TRUE(IsFieldEqual(toFieldAligned(fromFieldAligned(this->input)), this->input,
"RGN_ALL", FFTTolerance));
}

TEST_F(ShiftedMetricTest, ToFieldAlignedFieldPerp) {
TYPED_TEST(ShiftedMetricTest, ToFieldAlignedFieldPerp) {
if constexpr (std::is_same_v<TypeParam, ShiftedMetricInterp>) {
GTEST_SKIP_("Not implemented yet");
}

Field3D expected{mesh};
expected.setDirectionY(YDirectionType::Aligned);

Expand Down Expand Up @@ -207,22 +220,26 @@ TEST_F(ShiftedMetricTest, ToFieldAlignedFieldPerp) {
{4., 5., 1., 3., 2.},
{2., 4., 3., 5., 1.}}});

FieldPerp result = toFieldAligned(sliceXZ(input, 3), "RGN_NOX");
FieldPerp result = toFieldAligned(sliceXZ(this->input, 3), "RGN_NOX");

// Note that the region argument does not do anything for FieldPerp, as
// FieldPerp does not have a getRegion2D() method. Values are never set in
// the x-guard or x-boundary cells
EXPECT_TRUE(IsFieldEqual(result, sliceXZ(expected, 3), "RGN_NOBNDRY", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(fromFieldAligned(result, "RGN_NOX"), sliceXZ(input, 3),
EXPECT_TRUE(IsFieldEqual(fromFieldAligned(result, "RGN_NOX"), sliceXZ(this->input, 3),
"RGN_NOBNDRY", FFTTolerance));
EXPECT_TRUE(areFieldsCompatible(result, sliceXZ(expected, 3)));
EXPECT_FALSE(areFieldsCompatible(result, sliceXZ(input, 3)));
EXPECT_FALSE(areFieldsCompatible(result, sliceXZ(this->input, 3)));
}

TEST_F(ShiftedMetricTest, FromFieldAlignedFieldPerp) {
// reset input.yDirectionType so that fromFieldAligned is not a null
TYPED_TEST(ShiftedMetricTest, FromFieldAlignedFieldPerp) {
if constexpr (std::is_same_v<TypeParam, ShiftedMetricInterp>) {
GTEST_SKIP_("Not implemented yet");
}

// reset this->input.yDirectionType so that fromFieldAligned is not a null
// operation
input.setDirectionY(YDirectionType::Aligned);
this->input.setDirectionY(YDirectionType::Aligned);

Field3D expected{mesh, CELL_CENTRE};
expected.setDirectionY(YDirectionType::Standard);
Expand Down Expand Up @@ -251,60 +268,85 @@ TEST_F(ShiftedMetricTest, FromFieldAlignedFieldPerp) {
{2., 4., 5., 1., 3.},
{5., 1., 2., 4., 3.}}});

FieldPerp result = fromFieldAligned(sliceXZ(input, 4), "RGN_NOX");
FieldPerp result = fromFieldAligned(sliceXZ(this->input, 4), "RGN_NOX");

// Note that the region argument does not do anything for FieldPerp, as
// FieldPerp does not have a getRegion2D() method. Values are never set in
// the x-guard or x-boundary cells
EXPECT_TRUE(IsFieldEqual(result, sliceXZ(expected, 4), "RGN_NOBNDRY", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(toFieldAligned(result, "RGN_NOX"), sliceXZ(input, 4),
EXPECT_TRUE(IsFieldEqual(toFieldAligned(result, "RGN_NOX"), sliceXZ(this->input, 4),
"RGN_NOBNDRY", FFTTolerance));
EXPECT_TRUE(areFieldsCompatible(result, sliceXZ(expected, 4)));
EXPECT_FALSE(areFieldsCompatible(result, sliceXZ(input, 4)));
EXPECT_FALSE(areFieldsCompatible(result, sliceXZ(this->input, 4)));
}

TEST_F(ShiftedMetricTest, FromToFieldAlignedFieldPerp) {
TYPED_TEST(ShiftedMetricTest, FromToFieldAlignedFieldPerp) {
if constexpr (std::is_same_v<TypeParam, ShiftedMetricInterp>) {
GTEST_SKIP_("Not implemented yet");
}

// Note that the region argument does not do anything for FieldPerp, as
// FieldPerp does not have a getRegion2D() method. Values are never set in
// the x-guard or x-boundary cells
EXPECT_TRUE(IsFieldEqual(
fromFieldAligned(toFieldAligned(sliceXZ(input, 2), "RGN_NOX"), "RGN_NOX"),
sliceXZ(input, 2), "RGN_NOBNDRY", FFTTolerance));
fromFieldAligned(toFieldAligned(sliceXZ(this->input, 2), "RGN_NOX"), "RGN_NOX"),
sliceXZ(this->input, 2), "RGN_NOBNDRY", FFTTolerance));
}

TEST_F(ShiftedMetricTest, ToFromFieldAlignedFieldPerp) {
TYPED_TEST(ShiftedMetricTest, ToFromFieldAlignedFieldPerp) {
if constexpr (std::is_same_v<TypeParam, ShiftedMetricInterp>) {
GTEST_SKIP_("Not implemented yet");
}

// Note that the region argument does not do anything for FieldPerp, as
// FieldPerp does not have a getRegion2D() method. Values are never set in
// the x-guard or x-boundary cells
input.setDirectionY(YDirectionType::Aligned);
this->input.setDirectionY(YDirectionType::Aligned);

EXPECT_TRUE(IsFieldEqual(
toFieldAligned(fromFieldAligned(sliceXZ(input, 6), "RGN_NOX"), "RGN_NOX"),
sliceXZ(input, 6), "RGN_NOBNDRY", FFTTolerance));
toFieldAligned(fromFieldAligned(sliceXZ(this->input, 6), "RGN_NOX"), "RGN_NOX"),
sliceXZ(this->input, 6), "RGN_NOBNDRY", FFTTolerance));
}

TEST_F(ShiftedMetricTest, CalcParallelSlices) {
TYPED_TEST(ShiftedMetricTest, CalcParallelSlices) {
WithQuietOutput quiet_info{output_info};

// We don't shift in the guard cells, and the parallel slices are
// stored offset in y, therefore we need to make new regions that we
// can compare the expected and actual outputs over
output_info.disable();

constexpr bool is_shifted_interp = std::is_same_v<TypeParam, ShiftedMetricInterp>;

// ShiftedMetricInterp doesn't seem to store interpolated values in _any_ of the
// guards, so we can only check the interior X point
const int xstart = is_shifted_interp ? mesh->xstart : 0;
const int xend = is_shifted_interp ? mesh->xend : mesh->LocalNx - 1;

// It also means we can't check in the _y_ guards either.
// TODO(peter): Is this a bug?
const int yup_1_end = is_shifted_interp ? mesh->yend : mesh->yend + 1;
const int yup_2_end = is_shifted_interp ? mesh->yend : mesh->yend + 2;

const int ydown_1_start = is_shifted_interp ? mesh->ystart : mesh->ystart - 1;
const int ydown_2_start = is_shifted_interp ? mesh->ystart : mesh->ystart - 2;

mesh->addRegion3D("RGN_YUP",
Region<Ind3D>(0, mesh->LocalNx - 1, mesh->ystart + 1, mesh->yend + 1,
0, mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
Region<Ind3D>(xstart, xend, mesh->ystart + 1, yup_1_end, 0,
mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
mesh->addRegion3D("RGN_YUP2",
Region<Ind3D>(0, mesh->LocalNx - 1, mesh->ystart + 2, mesh->yend + 2,
0, mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
Region<Ind3D>(xstart, xend, mesh->ystart + 2, yup_2_end, 0,
mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));

mesh->addRegion3D("RGN_YDOWN",
Region<Ind3D>(0, mesh->LocalNx - 1, mesh->ystart - 1, mesh->yend - 1,
0, mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
Region<Ind3D>(xstart, xend, ydown_1_start, mesh->yend - 1, 0,
mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
mesh->addRegion3D("RGN_YDOWN2",
Region<Ind3D>(0, mesh->LocalNx - 1, mesh->ystart - 2, mesh->yend - 2,
0, mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
Region<Ind3D>(xstart, xend, ydown_2_start, mesh->yend - 2, 0,
mesh->LocalNz - 1, mesh->LocalNy, mesh->LocalNz));
output_info.enable();

// Actual interesting bit here!
input.getCoordinates()->getParallelTransform().calcParallelSlices(input);
this->input.getCoordinates()->getParallelTransform().calcParallelSlices(this->input);
// Expected output values

Field3D expected_up_1{mesh};
Expand Down Expand Up @@ -386,35 +428,38 @@ TEST_F(ShiftedMetricTest, CalcParallelSlices) {
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}}});

Field3D expected_down2{mesh};

fillField(expected_down2, {{{4., 5., 1., 2., 3.},
{4., 5., 2., 1., 3.},
{4., 5., 1., 3., 2.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}},

{{1., 3., 4., 5., 2.},
{3., 2., 4., 5., 1.},
{2., 4., 3., 5., 1.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}},

{{5., 1., 3., 2., 4.},
{5., 1., 2., 4., 3.},
{4., 1., 2., 3., 5.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}}});

EXPECT_TRUE(IsFieldEqual(input.ynext(1), expected_up_1, "RGN_YUP", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(input.ynext(2), expected_up_2, "RGN_YUP2", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(input.ynext(-1), expected_down_1, "RGN_YDOWN", FFTTolerance));
EXPECT_TRUE(IsFieldEqual(input.ynext(-2), expected_down2, "RGN_YDOWN2", FFTTolerance));
Field3D expected_down_2{mesh};

fillField(expected_down_2, {{{4., 5., 1., 2., 3.},
{4., 5., 2., 1., 3.},
{4., 5., 1., 3., 2.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}},

{{1., 3., 4., 5., 2.},
{3., 2., 4., 5., 1.},
{2., 4., 3., 5., 1.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}},

{{5., 1., 3., 2., 4.},
{5., 1., 2., 4., 3.},
{4., 1., 2., 3., 5.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0.}}});

EXPECT_TRUE(IsFieldEqual(this->input.ynext(1), expected_up_1, "RGN_YUP", FFTTolerance));
EXPECT_TRUE(
IsFieldEqual(this->input.ynext(2), expected_up_2, "RGN_YUP2", FFTTolerance));
EXPECT_TRUE(
IsFieldEqual(this->input.ynext(-1), expected_down_1, "RGN_YDOWN", FFTTolerance));
EXPECT_TRUE(
IsFieldEqual(this->input.ynext(-2), expected_down_2, "RGN_YDOWN2", FFTTolerance));
}
#endif