Page MenuHomec4science

test_integration.cpp
No OneTemporary

File Metadata

Created
Tue, Apr 30, 19:05

test_integration.cpp

/**
* @file
* @section LICENSE
*
* Copyright (©) 2016-2021 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "fft_engine.hh"
#include "integration/accumulator.hh"
#include "mpi_interface.hh"
#include "partitioner.hh"
#include "test.hh"
#include <cmath>
#include <expolit/expolit>
#include <functional>
/* -------------------------------------------------------------------------- */
using namespace tamaas;
namespace ex = expolit;
static Real tol = 1e-13;
class AccumulatorTest : public ::testing::Test {
protected:
void SetUp() override {
nodal_values.resize(n);
for (auto&& grid : nodal_values) {
grid.setNbComponents(6);
grid.resize(Partitioner<2>::local_size({nh, nh}));
grid = 1;
}
accumulator.makeUniformMesh(nodal_values.size(), size);
wavevectors = FFTEngine::computeFrequencies<Real, 2, true>({nh, nh});
}
mpi::sequential_guard guard;
UInt n = 10, nh = 10;
Real size = 3;
std::vector<GridHermitian<Real, 2>> nodal_values;
Grid<Real, 2> wavevectors;
Accumulator<model_type::volume_2d, SymMatrixProxy<Complex, 3>> accumulator;
};
TEST_F(AccumulatorTest, uniformMesh) {
auto& pos = this->accumulator.nodePositions();
std::vector<Real> sol(pos.size());
std::iota(sol.begin(), sol.end(), 0);
std::transform(sol.begin(), sol.end(), sol.begin(),
[&](auto& x) { return size * x / (sol.size() - 1); });
ASSERT_TRUE(compare(sol, pos, AreFloatEqual())) << "Uniform mesh fail";
}
// Litteral type
using Q = ex::Litteral<struct Q_>;
TEST_F(AccumulatorTest, forward) {
ASSERT_TRUE(compare(this->nodal_values.front().sizes(),
this->wavevectors.sizes(), std::equal_to<void>()))
<< "Size mismatch between nodal value and wavevectors";
// Setup for layer checking
std::vector<int> layers_seen, layers_to_see(n);
std::iota(layers_to_see.begin(), layers_to_see.end(), 0);
// Setup for integral checking
constexpr Q q;
constexpr auto z = ex::Polynomial<Real, 1>({0, 1});
constexpr auto g0 = ex::exp(q * z);
constexpr auto g1 = q * z * ex::exp(q * z);
for (auto&& tuple :
accumulator.forward(this->nodal_values, this->wavevectors)) {
auto&& l = std::get<0>(tuple);
auto&& xl_ = std::get<1>(tuple);
auto&& acc_g0 = std::get<2>(tuple);
auto&& acc_g1 = std::get<3>(tuple);
layers_seen.push_back(l);
// fundamental mode
auto testing = acc_g0(0, 0, 0);
EXPECT_NEAR(testing.real(), xl_, tol) << "Fundamental mode G0 fail";
testing = acc_g1(0, 0, 0);
EXPECT_NEAR(testing.real(), 0, tol) << "Fundamental mode G1 fail";
// other modes
testing = acc_g0(1, 0, 0);
EXPECT_NEAR(testing.real(), acc_g0(0, 1, 0).real(), tol) << "Symmetry fail";
EXPECT_NEAR(testing.imag(), acc_g0(0, 1, 0).imag(), tol) << "Symmetry fail";
testing = acc_g0(1, 1, 0);
Real sqrt_two = std::sqrt(Real(2));
auto ref_value = ex::definite_integral(
std::pair<Real, Real>(0, xl_),
ex::substitute<Q::tag>(ex::Constant<Real>({sqrt_two}), g0));
EXPECT_NEAR(testing.real(), ref_value, tol)
<< "Integration of exp(qy)*ϕ(y) fail";
testing = acc_g1(1, 1, 0);
ref_value = ex::definite_integral(
std::pair<Real, Real>(0, xl_),
ex::substitute<Q::tag>(ex::Constant<Real>({sqrt_two}), g1));
EXPECT_NEAR(testing.real(), ref_value, tol)
<< "Integration of qy*exp(qy)*ϕ(y) fail";
}
EXPECT_TRUE(compare(layers_seen, layers_to_see))
<< "Did not see correct layers";
}
TEST_F(AccumulatorTest, backward) {
ASSERT_TRUE(compare(this->nodal_values.front().sizes(),
this->wavevectors.sizes(), std::equal_to<void>()))
<< "Size mismatch between nodal value and wavevectors";
// Setup for layer checking
std::vector<int> layers_seen, layers_to_see(n);
std::iota(layers_to_see.rbegin(), layers_to_see.rend(), 0);
// Setup for integral checking
constexpr Q q;
constexpr auto z = ex::Polynomial<Real, 1>({0, 1});
constexpr auto g0 = ex::exp(q * (z * (-1)));
constexpr auto g1 = q * z * ex::exp(q * ((-1) * z));
for (auto&& tuple : accumulator.backward(nodal_values, wavevectors)) {
auto&& l = std::get<0>(tuple);
auto&& xl_ = std::get<1>(tuple);
auto&& acc_g0 = std::get<2>(tuple);
auto&& acc_g1 = std::get<3>(tuple);
layers_seen.push_back(l);
// fundamental mode
auto testing = acc_g0(0, 0, 0);
EXPECT_NEAR(testing.real(), size - xl_, tol) << "Fundamental mode G0 fail";
testing = acc_g1(0, 0, 0);
EXPECT_NEAR(testing.real(), 0, tol) << "Fundamental mode G1 fail";
// other modes
testing = acc_g0(1, 0, 0);
EXPECT_NEAR(testing.real(), acc_g0(0, 1, 0).real(), tol) << "Symmetry fail";
EXPECT_NEAR(testing.imag(), acc_g0(0, 1, 0).imag(), tol) << "Symmetry fail";
testing = acc_g0(1, 1, 0);
auto ref_value = ex::definite_integral(
std::make_pair(xl_, size),
ex::substitute<Q::tag>(ex::Constant<Real>({std::sqrt(2)}), g0));
EXPECT_NEAR(testing.real(), ref_value, tol)
<< "Integration of exp(-qy)*ϕ(y) fail";
testing = acc_g1(1, 1, 0);
ref_value = ex::definite_integral(
std::make_pair(xl_, size),
ex::substitute<Q::tag>(ex::Constant<Real>({std::sqrt(2)}), g1));
EXPECT_NEAR(testing.real(), ref_value, tol)
<< "Integration of qy*exp(-qy)*ϕ(y) fail";
}
EXPECT_TRUE(compare(layers_seen, layers_to_see))
<< "Did not see correct layers";
}

Event Timeline