Revision 0e70addbf5d5b77a5cb5111874cca895ed816314 authored by Wenqing Wang on 15 April 2021, 09:10:15 UTC, committed by Wenqing Wang on 15 April 2021, 09:10:15 UTC
1 parent 6d663a4
TestComponentNorms.cpp
/**
* \copyright
* Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#include <gtest/gtest.h>
#include <limits>
#include "BaseLib/Logging.h"
#ifdef USE_PETSC
#include "InfoLib/TestInfo.h"
#endif
#include "MathLib/LinAlg/LinAlg.h"
#include "MathLib/LinAlg/MatrixSpecifications.h"
#include "MathLib/LinAlg/MatrixVectorTraits.h"
#ifdef USE_PETSC
#include "MeshLib/IO/readMeshFromFile.h"
#else
#include "MeshLib/MeshGenerators/MeshGenerator.h"
#endif
#include "NumLib/DOF/DOFTableUtil.h"
#include "NumLib/DOF/LocalToGlobalIndexMap.h"
#include "NumLib/NumericsConfig.h"
#include "Tests/VectorUtils.h"
static std::vector<MeshLib::MeshSubset> createMeshSubsets(
MeshLib::MeshSubset const& mesh_subset, unsigned const num_components)
{
std::vector<MeshLib::MeshSubset> mesh_subsets;
for (unsigned i = 0; i < num_components; ++i)
{
mesh_subsets.emplace_back(mesh_subset);
}
return mesh_subsets;
}
struct DOFTableData
{
DOFTableData(unsigned const num_components,
NumLib::ComponentOrder const order)
#ifdef USE_PETSC
: mesh(MeshLib::IO::readMeshFromFile(
TestInfoLib::TestInfo::data_path +
"/EllipticPETSc/quad_20x10_GroundWaterFlow.")),
#else
: mesh(MeshLib::MeshGenerator::generateRegularHexMesh(
mesh_length, mesh_elements_in_each_direction)),
#endif
mesh_subset_all_nodes(*mesh, mesh->getNodes()),
dof_table(createMeshSubsets(mesh_subset_all_nodes, num_components),
order)
{
}
std::unique_ptr<MeshLib::Mesh> const mesh;
MeshLib::MeshSubset const mesh_subset_all_nodes;
NumLib::LocalToGlobalIndexMap const dof_table;
#ifndef USE_PETSC
private:
static const double mesh_length;
static const std::size_t mesh_elements_in_each_direction;
#endif
};
#ifndef USE_PETSC
const double DOFTableData::mesh_length = 1;
const std::size_t DOFTableData::mesh_elements_in_each_direction = 5;
#endif
template <typename AccumulateCallback, typename AccumulateFinishCallback>
void do_test(unsigned const num_components,
MathLib::VecNormType const norm_type,
double const tolerance,
AccumulateCallback&& accumulate_cb,
AccumulateFinishCallback&& accumulate_finish_cb)
{
/* The idea behind this test is that the accumulated value of all component
* norms must be equal to the 1-/2-/infinity-norm of the whole global
* vector.
*/
using CO = NumLib::ComponentOrder;
#ifdef USE_PETSC
for (auto order : {CO::BY_LOCATION})
#else
for (auto order : {CO::BY_COMPONENT, CO::BY_LOCATION})
#endif
{
DOFTableData dtd(num_components, order);
MathLib::MatrixSpecifications mat_specs(
dtd.dof_table.dofSizeWithoutGhosts(),
dtd.dof_table.dofSizeWithoutGhosts(),
&dtd.dof_table.getGhostIndices(),
nullptr);
auto x =
MathLib::MatrixVectorTraits<GlobalVector>::newInstance(mat_specs);
fillVectorRandomly(*x);
auto const total_norm = MathLib::LinAlg::norm(*x, norm_type);
double compwise_total_norm = 0.0;
for (unsigned comp = 0; comp < num_components; ++comp)
{
compwise_total_norm = accumulate_cb(
compwise_total_norm,
NumLib::norm(*x, comp, norm_type, dtd.dof_table, *dtd.mesh));
}
compwise_total_norm = accumulate_finish_cb(compwise_total_norm);
EXPECT_NEAR(total_norm, compwise_total_norm, tolerance);
}
}
#ifndef USE_PETSC
TEST(NumLib, ComponentNormSingleComponent)
#else
TEST(MPITest_NumLib, ComponentNormSingleComponent)
#endif
{
unsigned const num_components = 1;
auto const tolerance = 800 * std::numeric_limits<double>::epsilon();
using VNT = MathLib::VecNormType;
for (auto norm_type : {VNT::NORM1, VNT::NORM2, VNT::INFINITY_N})
{
DBUG("norm type: {:s}.",
MathLib::convertVecNormTypeToString(norm_type));
do_test(
num_components, norm_type, tolerance,
[](double /*n_total*/, double n) { return n; },
[](double n_total) { return n_total; });
}
}
#ifndef USE_PETSC
TEST(NumLib, ComponentNormMultiComponent1)
#else
TEST(MPITest_NumLib, ComponentNormMultiComponent1)
#endif
{
unsigned const num_components = 3;
auto const norm_type = MathLib::VecNormType::NORM1;
auto const tolerance =
num_components * 1700 * std::numeric_limits<double>::epsilon();
do_test(
num_components, norm_type, tolerance,
[](double n_total, double n) { return n_total + n; },
[](double n_total) { return n_total; });
}
#ifndef USE_PETSC
TEST(NumLib, ComponentNormMultiComponent2)
#else
TEST(MPITest_NumLib, ComponentNormMultiComponent2)
#endif
{
unsigned const num_components = 3;
auto const norm_type = MathLib::VecNormType::NORM2;
auto const tolerance =
num_components * 40 * std::numeric_limits<double>::epsilon();
do_test(
num_components, norm_type, tolerance,
[](double n_total, double n) { return n_total + n * n; },
[](double n_total) { return std::sqrt(n_total); });
}
#ifndef USE_PETSC
TEST(NumLib, ComponentNormMultiComponentInfinity)
#else
TEST(MPITest_NumLib, ComponentNormMultiComponentInfinity)
#endif
{
unsigned const num_components = 3;
auto const norm_type = MathLib::VecNormType::INFINITY_N;
auto const tolerance =
num_components * 1 * std::numeric_limits<double>::epsilon();
do_test(
num_components, norm_type, tolerance,
[](double n_total, double n) { return std::max(n_total, n); },
[](double n_total) { return n_total; });
}
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...