Skip to content
Snippets Groups Projects
Commit fb4518e0 authored by Stéphane Del Pino's avatar Stéphane Del Pino
Browse files

Finalize tests improvements in view of degree 2+

parent cc558591
No related branches found
No related tags found
No related merge requests found
#ifndef DISCRETE_FUNCTION_DPK_FOR_TESTS_HPP
#define DISCRETE_FUNCTION_DPK_FOR_TESTS_HPP
#include <analysis/GaussQuadratureDescriptor.hpp>
#include <analysis/QuadratureFormula.hpp>
#include <analysis/QuadratureManager.hpp>
#include <geometry/CubeTransformation.hpp>
#include <geometry/LineTransformation.hpp>
#include <geometry/PrismTransformation.hpp>
#include <geometry/PyramidTransformation.hpp>
#include <geometry/SquareTransformation.hpp>
#include <geometry/TetrahedronTransformation.hpp>
#include <geometry/TriangleTransformation.hpp>
#include <mesh/Mesh.hpp>
#include <mesh/MeshDataManager.hpp>
#include <type_traits>
namespace test_only
{
template <MeshConcept MeshType, typename DataType>
DiscreteFunctionP0<std::remove_const_t<DataType>>
exact_projection(const MeshType& mesh,
size_t degree,
std::function<DataType(const TinyVector<MeshType::Dimension>&)> exact_function)
{
DiscreteFunctionP0<std::remove_const_t<DataType>> P0_function{mesh.meshVariant()};
auto Vj = MeshDataManager::instance().getMeshData(mesh).Vj();
auto xr = mesh.xr();
auto cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
auto cell_type = mesh.connectivity().cellType();
auto sum = [&exact_function, &Vj](const CellId cell_id, const auto& T,
const auto& qf) -> std::remove_const_t<DataType> {
std::remove_const_t<DataType> integral =
(qf.weight(0) * T.jacobianDeterminant(qf.point(0))) * exact_function(T(qf.point(0)));
for (size_t i_quadrarture = 1; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
integral += (qf.weight(i_quadrarture) * T.jacobianDeterminant(qf.point(i_quadrarture))) *
exact_function(T(qf.point(i_quadrarture)));
}
return 1. / Vj[cell_id] * integral;
};
for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) {
auto cell_nodes = cell_to_node_matrix[cell_id];
if constexpr (MeshType::Dimension == 1) {
LineTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]]};
auto qf = QuadratureManager::instance().getLineFormula(GaussQuadratureDescriptor{degree + 1});
P0_function[cell_id] = sum(cell_id, T, qf);
} else if constexpr (MeshType::Dimension == 2) {
switch (cell_type[cell_id]) {
case CellType::Triangle: {
TriangleTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]]};
auto qf = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{degree + 2});
P0_function[cell_id] = sum(cell_id, T, qf);
break;
}
case CellType::Quadrangle: {
SquareTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]],
xr[cell_nodes[3]]};
auto qf = QuadratureManager::instance().getSquareFormula(GaussQuadratureDescriptor{degree + 2});
P0_function[cell_id] = sum(cell_id, T, qf);
break;
}
default: {
throw UnexpectedError("unexpected cell type");
}
}
} else if constexpr (MeshType::Dimension == 3) {
switch (cell_type[cell_id]) {
case CellType::Tetrahedron: {
TetrahedronTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]]};
auto qf = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{degree + 3});
P0_function[cell_id] = sum(cell_id, T, qf);
break;
}
case CellType::Pyramid: {
PyramidTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]],
xr[cell_nodes[4]]};
auto qf = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{degree + 3});
P0_function[cell_id] = sum(cell_id, T, qf);
break;
}
case CellType::Prism: {
PrismTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]],
xr[cell_nodes[3]], xr[cell_nodes[4]], xr[cell_nodes[5]]};
auto qf = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{degree + 3});
P0_function[cell_id] = sum(cell_id, T, qf);
break;
}
case CellType::Hexahedron: {
CubeTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]],
xr[cell_nodes[4]], xr[cell_nodes[5]], xr[cell_nodes[6]], xr[cell_nodes[7]]};
auto qf = QuadratureManager::instance().getCubeFormula(GaussQuadratureDescriptor{degree + 3});
P0_function[cell_id] = sum(cell_id, T, qf);
break;
}
default: {
throw UnexpectedError("unexpected cell type");
}
}
} else {
throw UnexpectedError("invalid mesh dimension");
}
}
return P0_function;
}
template <MeshConcept MeshType, typename DataType, size_t NbComponents>
DiscreteFunctionP0Vector<std::remove_const_t<DataType>>
exact_projection(
const MeshType& mesh,
size_t degree,
const std::array<std::function<DataType(const TinyVector<MeshType::Dimension>&)>, NbComponents>& vector_exact)
{
DiscreteFunctionP0Vector<std::remove_const_t<DataType>> P0_function_vector{mesh.meshVariant(), vector_exact.size()};
for (size_t i_component = 0; i_component < vector_exact.size(); ++i_component) {
auto exact_function = vector_exact[i_component];
DiscreteFunctionP0 P0_function = exact_projection(mesh, degree, vector_exact[i_component]);
parallel_for(
mesh.numberOfCells(),
PUGS_LAMBDA(const CellId cell_id) { P0_function_vector[cell_id][i_component] = P0_function[cell_id]; });
}
return P0_function_vector;
}
template <typename DataType>
PUGS_INLINE double
get_max_error(const DataType& x, const DataType& y)
{
if constexpr (is_tiny_matrix_v<DataType>) {
return frobeniusNorm(x - y);
} else if constexpr (is_tiny_vector_v<DataType>) {
return l2Norm(x - y);
} else {
static_assert(std::is_arithmetic_v<DataType>, "expecting arithmetic type");
return std::abs(x - y);
}
}
template <MeshConcept MeshType, typename DataType>
double
max_reconstruction_error(const MeshType& mesh,
DiscreteFunctionDPk<MeshType::Dimension, const DataType> dpk_f,
std::function<DataType(const TinyVector<MeshType::Dimension>&)> exact)
{
auto xr = mesh.xr();
auto cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
auto cell_type = mesh.connectivity().cellType();
double max_error = 0;
for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) {
auto cell_nodes = cell_to_node_matrix[cell_id];
if constexpr (MeshType::Dimension == 1) {
Assert(cell_type[cell_id] == CellType::Line);
LineTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]]};
auto qf = QuadratureManager::instance().getLineFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
} else if constexpr (MeshType::Dimension == 2) {
switch (cell_type[cell_id]) {
case CellType::Triangle: {
TriangleTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]]};
auto qf = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
break;
}
case CellType::Quadrangle: {
SquareTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]],
xr[cell_nodes[3]]};
auto qf = QuadratureManager::instance().getSquareFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
break;
}
default: {
throw UnexpectedError("unexpected cell type");
}
}
} else if constexpr (MeshType::Dimension == 3) {
switch (cell_type[cell_id]) {
case CellType::Tetrahedron: {
TetrahedronTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]]};
auto qf = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
break;
}
case CellType::Pyramid: {
PyramidTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]],
xr[cell_nodes[4]]};
auto qf = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
break;
}
case CellType::Prism: {
PrismTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]],
xr[cell_nodes[3]], xr[cell_nodes[4]], xr[cell_nodes[5]]};
auto qf = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
break;
}
case CellType::Hexahedron: {
CubeTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]],
xr[cell_nodes[4]], xr[cell_nodes[5]], xr[cell_nodes[6]], xr[cell_nodes[7]]};
auto qf = QuadratureManager::instance().getCubeFormula(GaussQuadratureDescriptor{dpk_f.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
max_error = std::max(max_error, get_max_error(dpk_f[cell_id](x), exact(x)));
}
break;
}
default: {
throw UnexpectedError("unexpected cell type");
}
}
}
}
return max_error;
}
template <MeshConcept MeshType, typename DataType, size_t NbComponents>
double
max_reconstruction_error(
const MeshType& mesh,
DiscreteFunctionDPkVector<MeshType::Dimension, const DataType> dpk_v,
const std::array<std::function<DataType(const TinyVector<MeshType::Dimension>&)>, NbComponents>& vector_exact)
{
auto xr = mesh.xr();
auto cell_to_node_matrix = mesh.connectivity().cellToNodeMatrix();
double max_error = 0;
auto cell_type = mesh.connectivity().cellType();
REQUIRE(NbComponents == dpk_v.numberOfComponents());
for (CellId cell_id = 0; cell_id < mesh.numberOfCells(); ++cell_id) {
auto cell_nodes = cell_to_node_matrix[cell_id];
if constexpr (MeshType::Dimension == 1) {
Assert(cell_type[cell_id] == CellType::Line);
LineTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]]};
auto qf = QuadratureManager::instance().getLineFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error = std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
} else if constexpr (MeshType::Dimension == 2) {
switch (cell_type[cell_id]) {
case CellType::Triangle: {
TriangleTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]]};
auto qf = QuadratureManager::instance().getTriangleFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error =
std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
break;
}
case CellType::Quadrangle: {
SquareTransformation<MeshType::Dimension> T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]],
xr[cell_nodes[3]]};
auto qf = QuadratureManager::instance().getSquareFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error =
std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
break;
}
default: {
throw UnexpectedError("unexpected cell type");
}
}
} else if constexpr (MeshType::Dimension == 3) {
switch (cell_type[cell_id]) {
case CellType::Tetrahedron: {
TetrahedronTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]]};
auto qf = QuadratureManager::instance().getTetrahedronFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error =
std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
break;
}
case CellType::Pyramid: {
PyramidTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]],
xr[cell_nodes[4]]};
auto qf = QuadratureManager::instance().getPyramidFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error =
std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
break;
}
case CellType::Prism: {
PrismTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]],
xr[cell_nodes[3]], xr[cell_nodes[4]], xr[cell_nodes[5]]};
auto qf = QuadratureManager::instance().getPrismFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error =
std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
break;
}
case CellType::Hexahedron: {
CubeTransformation T{xr[cell_nodes[0]], xr[cell_nodes[1]], xr[cell_nodes[2]], xr[cell_nodes[3]],
xr[cell_nodes[4]], xr[cell_nodes[5]], xr[cell_nodes[6]], xr[cell_nodes[7]]};
auto qf = QuadratureManager::instance().getCubeFormula(GaussQuadratureDescriptor{dpk_v.degree() + 1});
for (size_t i_quadrarture = 0; i_quadrarture < qf.numberOfPoints(); ++i_quadrarture) {
auto x = T(qf.point(i_quadrarture));
for (size_t i_component = 0; i_component < NbComponents; ++i_component) {
max_error =
std::max(max_error, get_max_error(dpk_v(cell_id, i_component)(x), vector_exact[i_component](x)));
}
}
break;
}
default: {
throw UnexpectedError("unexpected cell type");
}
}
}
}
return max_error;
}
} // namespace test_only
#endif // DISCRETE_FUNCTION_DPK_FOR_TESTS_HPP
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment