Select Git revision
HypoelasticSolver.hpp
test_MeshLineEdgeBoundary.cpp 49.12 KiB
#include <catch2/catch_test_macros.hpp>
#include <catch2/matchers/catch_matchers_all.hpp>
#include <MeshDataBaseForTests.hpp>
#include <algebra/TinyMatrix.hpp>
#include <mesh/Connectivity.hpp>
#include <mesh/Mesh.hpp>
#include <mesh/MeshLineEdgeBoundary.hpp>
#include <mesh/NamedBoundaryDescriptor.hpp>
#include <mesh/NumberedBoundaryDescriptor.hpp>
// clazy:excludeall=non-pod-global-static
TEST_CASE("MeshLineEdgeBoundary", "[mesh]")
{
auto is_same = [](const auto& a, const auto& b) -> bool {
if (a.size() > 0 and b.size() > 0) {
return (a[0] == b[0]);
} else {
return (a.size() == b.size());
}
};
auto get_edge_list_from_tag = [](const size_t tag, const auto& connectivity) -> Array<const EdgeId> {
for (size_t i = 0; i < connectivity.template numberOfRefItemList<ItemType::edge>(); ++i) {
const auto& ref_edge_list = connectivity.template refItemList<ItemType::edge>(i);
const RefId ref_id = ref_edge_list.refId();
if (ref_id.tagNumber() == tag) {
return ref_edge_list.list();
}
}
return {};
};
auto get_edge_list_from_name = [](const std::string& name, const auto& connectivity) -> Array<const EdgeId> {
for (size_t i = 0; i < connectivity.template numberOfRefItemList<ItemType::edge>(); ++i) {
const auto& ref_edge_list = connectivity.template refItemList<ItemType::edge>(i);
const RefId ref_id = ref_edge_list.refId();
if (ref_id.tagName() == name) {
return ref_edge_list.list();
}
}
return {};
};
SECTION("aligned axis")
{
SECTION("2D")
{
static constexpr size_t Dimension = 2;
using ConnectivityType = Connectivity<Dimension>;
using MeshType = Mesh<ConnectivityType>;
using R2 = TinyVector<2>;
SECTION("cartesian 2d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian2DMesh();
const MeshType& mesh = *p_mesh;
const ConnectivityType& connectivity = mesh.connectivity();
{
const std::set<size_t> tag_set = {0, 1, 2, 3};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
switch (tag) {
case 0: {
direction = R2{0, 1};
break;
}
case 1: {
direction = R2{0, 1};
break;
}
case 2: {
direction = R2{1, 0};
break;
}
case 3: {
direction = R2{1, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(10)),
"error: cannot find edge list with name \"10\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(11)),
"error: cannot find edge list with name \"11\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(12)),
"error: cannot find edge list with name \"12\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(13)),
"error: cannot find edge list with name \"13\"");
}
}
{
const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
if (name == "XMIN") {
direction = R2{0, 1};
} else if (name == "XMAX") {
direction = R2{0, 1};
} else if (name == "YMIN") {
direction = R2{1, 0};
} else if (name == "YMAX") {
direction = R2{1, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMIN")),
"error: cannot find edge list with name \"XMINYMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMAX")),
"error: cannot find edge list with name \"XMINYMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMIN")),
"error: cannot find edge list with name \"XMAXYMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMAX")),
"error: cannot find edge list with name \"XMAXYMAX\"");
}
}
}
SECTION("hybrid 2d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid2DMesh();
const MeshType& mesh = *p_mesh;
const ConnectivityType& connectivity = mesh.connectivity();
{
const std::set<size_t> tag_set = {1, 2, 3, 4};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
switch (tag) {
case 1: {
direction = R2{0, 1};
break;
}
case 2: {
direction = R2{0, 1};
break;
}
case 3: {
direction = R2{1, 0};
break;
}
case 4: {
direction = R2{1, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(8)),
"error: cannot find edge list with name \"8\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(9)),
"error: cannot find edge list with name \"9\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(10)),
"error: cannot find edge list with name \"10\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(11)),
"error: cannot find edge list with name \"11\"");
}
}
{
const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
R2 direction = zero;
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
if (name == "XMIN") {
direction = R2{0, 1};
} else if (name == "XMAX") {
direction = R2{0, 1};
} else if (name == "YMIN") {
direction = R2{1, 0};
} else if (name == "YMAX") {
direction = R2{1, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMIN")),
"error: cannot find edge list with name \"XMINYMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMAX")),
"error: cannot find edge list with name \"XMINYMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMIN")),
"error: cannot find edge list with name \"XMAXYMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMAX")),
"error: cannot find edge list with name \"XMAXYMAX\"");
}
}
}
}
SECTION("3D")
{
static constexpr size_t Dimension = 3;
using ConnectivityType = Connectivity<Dimension>;
using MeshType = Mesh<ConnectivityType>;
using R3 = TinyVector<3>;
SECTION("cartesian 3d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian3DMesh();
const MeshType& mesh = *p_mesh;
const ConnectivityType& connectivity = mesh.connectivity();
{
const std::set<size_t> tag_set = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
switch (tag) {
case 20:
case 21:
case 22:
case 23: {
direction = R3{0, 0, -1};
break;
}
case 24:
case 25:
case 26:
case 27: {
direction = R3{0, -1, 0};
break;
}
case 28:
case 29:
case 30:
case 31: {
direction = R3{1, 0, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(0)),
"error: invalid boundary \"XMIN(0)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(1)),
"error: invalid boundary \"XMAX(1)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(2)),
"error: invalid boundary \"YMIN(2)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(3)),
"error: invalid boundary \"YMAX(3)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(4)),
"error: invalid boundary \"ZMIN(4)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(5)),
"error: invalid boundary \"ZMAX(5)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(10)),
"error: cannot find edge list with name \"10\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(11)),
"error: cannot find edge list with name \"11\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(12)),
"error: cannot find edge list with name \"12\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(13)),
"error: cannot find edge list with name \"13\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(14)),
"error: cannot find edge list with name \"14\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(15)),
"error: cannot find edge list with name \"15\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(16)),
"error: cannot find edge list with name \"16\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(17)),
"error: cannot find edge list with name \"17\"");
}
{
const std::set<std::string> name_set = {"XMINYMIN", "XMINYMAX", "XMAXYMIN", "XMAXYMAX",
"XMINZMIN", "XMINZMAX", "XMAXZMAX", "XMINZMAX",
"YMINZMIN", "YMINZMAX", "YMAXZMAX", "YMAXZMIN"};
for (const auto& name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
if ((name == "XMINYMIN") or (name == "XMINYMAX") or (name == "XMAXYMIN") or (name == "XMAXYMAX")) {
direction = R3{0, 0, -1};
} else if ((name == "XMINZMIN") or (name == "XMINZMAX") or (name == "XMAXZMIN") or (name == "XMAXZMAX")) {
direction = R3{0, -1, 0};
} else if ((name == "YMINZMIN") or (name == "YMINZMAX") or (name == "YMAXZMIN") or (name == "YMAXZMAX")) {
direction = R3{1, 0, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMIN")),
"error: invalid boundary \"XMIN(0)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAX")),
"error: invalid boundary \"XMAX(1)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMIN")),
"error: invalid boundary \"YMIN(2)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMAX")),
"error: invalid boundary \"YMAX(3)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("ZMIN")),
"error: invalid boundary \"ZMIN(4)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("ZMAX")),
"error: invalid boundary \"ZMAX(5)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMINZMIN")),
"error: cannot find edge list with name \"XMINYMINZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMINZMIN")),
"error: cannot find edge list with name \"XMAXYMINZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMAXZMIN")),
"error: cannot find edge list with name \"XMAXYMAXZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMAXZMIN")),
"error: cannot find edge list with name \"XMINYMAXZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMINZMAX")),
"error: cannot find edge list with name \"XMINYMINZMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMINZMAX")),
"error: cannot find edge list with name \"XMAXYMINZMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMAXZMAX")),
"error: cannot find edge list with name \"XMAXYMAXZMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMAXZMAX")),
"error: cannot find edge list with name \"XMINYMAXZMAX\"");
}
}
}
SECTION("hybrid 3d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid3DMesh();
const MeshType& mesh = *p_mesh;
const ConnectivityType& connectivity = mesh.connectivity();
{
const std::set<size_t> tag_set = {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
switch (tag) {
case 30:
case 31:
case 34:
case 35: {
direction = R3{0, 0, -1};
break;
}
case 28:
case 29:
case 32:
case 33: {
direction = R3{0, -1, 0};
break;
}
case 36:
case 37:
case 38:
case 39: {
direction = R3{1, 0, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(22)),
"error: invalid boundary \"XMIN(22)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(23)),
"error: invalid boundary \"XMAX(23)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(24)),
"error: invalid boundary \"ZMAX(24)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(25)),
"error: invalid boundary \"ZMIN(25)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(26)),
"error: invalid boundary \"YMAX(26)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(27)),
"error: invalid boundary \"YMIN(27)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(40)),
"error: cannot find edge list with name \"40\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(41)),
"error: cannot find edge list with name \"41\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(42)),
"error: cannot find edge list with name \"42\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(43)),
"error: cannot find edge list with name \"43\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(44)),
"error: cannot find edge list with name \"44\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(45)),
"error: cannot find edge list with name \"45\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(47)),
"error: cannot find edge list with name \"47\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(51)),
"error: cannot find edge list with name \"51\"");
}
}
{
const std::set<std::string> name_set = {"XMINYMIN", "XMINYMAX", "XMAXYMIN", "XMAXYMAX",
"XMINZMIN", "XMINZMAX", "XMAXZMAX", "XMINZMAX",
"YMINZMIN", "YMINZMAX", "YMAXZMAX", "YMAXZMIN"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
if ((name == "XMINYMIN") or (name == "XMINYMAX") or (name == "XMAXYMIN") or (name == "XMAXYMAX")) {
direction = R3{0, 0, -1};
} else if ((name == "XMINZMIN") or (name == "XMINZMAX") or (name == "XMAXZMIN") or (name == "XMAXZMAX")) {
direction = R3{0, -1, 0};
} else if ((name == "YMINZMIN") or (name == "YMINZMAX") or (name == "YMAXZMIN") or (name == "YMAXZMAX")) {
direction = R3{1, 0, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMIN")),
"error: invalid boundary \"XMIN(22)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAX")),
"error: invalid boundary \"XMAX(23)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMIN")),
"error: invalid boundary \"YMIN(27)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMAX")),
"error: invalid boundary \"YMAX(26)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("ZMIN")),
"error: invalid boundary \"ZMIN(25)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("ZMAX")),
"error: invalid boundary \"ZMAX(24)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMINZMIN")),
"error: cannot find edge list with name \"XMINYMINZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMINZMIN")),
"error: cannot find edge list with name \"XMAXYMINZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMAXZMIN")),
"error: cannot find edge list with name \"XMAXYMAXZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMAXZMIN")),
"error: cannot find edge list with name \"XMINYMAXZMIN\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMINZMAX")),
"error: cannot find edge list with name \"XMINYMINZMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMINZMAX")),
"error: cannot find edge list with name \"XMAXYMINZMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMAXYMAXZMAX")),
"error: cannot find edge list with name \"XMAXYMAXZMAX\"");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("XMINYMAXZMAX")),
"error: cannot find edge list with name \"XMINYMAXZMAX\"");
}
}
}
}
}
SECTION("rotated axis")
{
SECTION("2D")
{
static constexpr size_t Dimension = 2;
using ConnectivityType = Connectivity<Dimension>;
using MeshType = Mesh<ConnectivityType>;
using R2 = TinyVector<2>;
const double theta = 0.3;
const TinyMatrix<2> R{std::cos(theta), -std::sin(theta), //
std::sin(theta), std::cos(theta)};
SECTION("cartesian 2d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian2DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
NodeValue<R2> rotated_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { rotated_xr[node_id] = R * xr[node_id]; });
MeshType mesh{p_mesh->shared_connectivity(), rotated_xr};
{
const std::set<size_t> tag_set = {0, 1, 2, 3};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
switch (tag) {
case 0: {
direction = R * R2{0, -1};
break;
}
case 1: {
direction = R * R2{0, -1};
break;
}
case 2: {
direction = R * R2{1, 0};
break;
}
case 3: {
direction = R * R2{1, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
{
const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
if (name == "XMIN") {
direction = R * R2{0, -1};
} else if (name == "XMAX") {
direction = R * R2{0, -1};
} else if (name == "YMIN") {
direction = R * R2{1, 0};
} else if (name == "YMAX") {
direction = R * R2{1, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
}
SECTION("hybrid 2d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid2DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
NodeValue<R2> rotated_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { rotated_xr[node_id] = R * xr[node_id]; });
MeshType mesh{p_mesh->shared_connectivity(), rotated_xr};
{
const std::set<size_t> tag_set = {1, 2, 3, 4};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
switch (tag) {
case 1: {
direction = R * R2{0, -1};
break;
}
case 2: {
direction = R * R2{0, -1};
break;
}
case 3: {
direction = R * R2{1, 0};
break;
}
case 4: {
direction = R * R2{1, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
{
const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN", "YMAX"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
R2 direction = zero;
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
if (name == "XMIN") {
direction = R * R2{0, -1};
} else if (name == "XMAX") {
direction = R * R2{0, -1};
} else if (name == "YMIN") {
direction = R * R2{1, 0};
} else if (name == "YMAX") {
direction = R * R2{1, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
}
}
SECTION("3D")
{
static constexpr size_t Dimension = 3;
using ConnectivityType = Connectivity<Dimension>;
using MeshType = Mesh<ConnectivityType>;
using R3 = TinyVector<3>;
const double theta = 0.3;
const double phi = 0.4;
const TinyMatrix<3> R =
TinyMatrix<3>{std::cos(theta), -std::sin(theta), 0, std::sin(theta), std::cos(theta), 0, 0, 0, 1} *
TinyMatrix<3>{0, std::cos(phi), -std::sin(phi), 0, std::sin(phi), std::cos(phi), 1, 0, 0};
SECTION("cartesian 3d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian3DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
NodeValue<R3> rotated_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { rotated_xr[node_id] = R * xr[node_id]; });
MeshType mesh{p_mesh->shared_connectivity(), rotated_xr};
{
const std::set<size_t> tag_set = {20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
switch (tag) {
case 20:
case 21:
case 22:
case 23: {
direction = R * R3{0, 0, -1};
break;
}
case 24:
case 25:
case 26:
case 27: {
direction = R * R3{0, 1, 0};
break;
}
case 28:
case 29:
case 30:
case 31: {
direction = R * R3{-1, 0, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
{
const std::set<std::string> name_set = {"XMINYMIN", "XMINYMAX", "XMAXYMIN", "XMAXYMAX",
"XMINZMIN", "XMINZMAX", "XMAXZMAX", "XMINZMAX",
"YMINZMIN", "YMINZMAX", "YMAXZMAX", "YMAXZMIN"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
if ((name == "XMINYMIN") or (name == "XMINYMAX") or (name == "XMAXYMIN") or (name == "XMAXYMAX")) {
direction = R * R3{0, 0, -1};
} else if ((name == "XMINZMIN") or (name == "XMINZMAX") or (name == "XMAXZMIN") or (name == "XMAXZMAX")) {
direction = R * R3{0, 1, 0};
} else if ((name == "YMINZMIN") or (name == "YMINZMAX") or (name == "YMAXZMIN") or (name == "YMAXZMAX")) {
direction = R * R3{-1, 0, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
}
SECTION("hybrid 3d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid3DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
NodeValue<R3> rotated_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { rotated_xr[node_id] = R * xr[node_id]; });
MeshType mesh{p_mesh->shared_connectivity(), rotated_xr};
{
const std::set<size_t> tag_set = {28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
switch (tag) {
case 30:
case 31:
case 34:
case 35: {
direction = R * R3{0, 0, -1};
break;
}
case 28:
case 29:
case 32:
case 33: {
direction = R * R3{0, 1, 0};
break;
}
case 36:
case 37:
case 38:
case 39: {
direction = R * R3{-1, 0, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
{
const std::set<std::string> name_set = {"XMINYMIN", "XMINYMAX", "XMAXYMIN", "XMAXYMAX",
"XMINZMIN", "XMINZMAX", "XMAXZMAX", "XMINZMAX",
"YMINZMIN", "YMINZMAX", "YMAXZMAX", "YMAXZMIN"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
if ((name == "XMINYMIN") or (name == "XMINYMAX") or (name == "XMAXYMIN") or (name == "XMAXYMAX")) {
direction = R * R3{0, 0, -1};
} else if ((name == "XMINZMIN") or (name == "XMINZMAX") or (name == "XMAXZMIN") or (name == "XMAXZMAX")) {
direction = R * R3{0, 1, 0};
} else if ((name == "YMINZMIN") or (name == "YMINZMAX") or (name == "YMAXZMIN") or (name == "YMAXZMAX")) {
direction = R * R3{-1, 0, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
}
}
}
}
SECTION("curved mesh")
{
SECTION("2D")
{
static constexpr size_t Dimension = 2;
using ConnectivityType = Connectivity<Dimension>;
using MeshType = Mesh<ConnectivityType>;
using R2 = TinyVector<2>;
auto curve = [](const R2& X) -> R2 { return R2{X[0], (1 + X[0] * X[0]) * X[1]}; };
SECTION("hybrid 2d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid2DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
NodeValue<TinyVector<2>> curved_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { curved_xr[node_id] = curve(xr[node_id]); });
MeshType mesh{p_mesh->shared_connectivity(), curved_xr};
{
const std::set<size_t> tag_set = {1, 2, 4};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R2 direction = zero;
switch (tag) {
case 1: {
direction = R2{0, 1};
break;
}
case 2: {
direction = R2{0, 1};
break;
}
case 4: {
direction = R2{1, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
NumberedBoundaryDescriptor numbered_boundary_descriptor(3);
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor),
"error: invalid boundary \"YMAX(3)\": boundary is not a line!");
}
}
{
const std::set<std::string> name_set = {"XMIN", "XMAX", "YMIN"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
R2 direction = zero;
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
if (name == "XMIN") {
direction = R2{0, 1};
} else if (name == "XMAX") {
direction = R2{0, 1};
} else if (name == "YMIN") {
direction = R2{1, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
NamedBoundaryDescriptor named_boundary_descriptor("YMAX");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, named_boundary_descriptor),
"error: invalid boundary \"YMAX(3)\": boundary is not a line!");
}
}
}
}
SECTION("3D")
{
static constexpr size_t Dimension = 3;
using ConnectivityType = Connectivity<Dimension>;
using MeshType = Mesh<ConnectivityType>;
using R3 = TinyVector<3>;
SECTION("cartesian 3d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().cartesian3DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
auto curve = [](const R3& X) -> R3 {
return R3{X[0], (1 + X[0] * X[0]) * (X[1] + 1), (1 - 0.2 * X[0] * X[0]) * X[2]};
};
NodeValue<R3> curved_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { curved_xr[node_id] = curve(xr[node_id]); });
MeshType mesh{p_mesh->shared_connectivity(), curved_xr};
{
const std::set<size_t> tag_set = {20, 21, 22, 23, 24, 25, 26, 27, 28};
for (auto tag : tag_set) {
auto edge_list = get_edge_list_from_tag(tag, connectivity);
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
switch (tag) {
case 20:
case 21:
case 22:
case 23: {
direction = R3{0, 0, -1};
break;
}
case 24:
case 25:
case 26:
case 27: {
direction = R3{0, -1, 0};
break;
}
case 28: {
direction = R3{1, 0, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(29)),
"error: invalid boundary \"YMINZMAX(29)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(30)),
"error: invalid boundary \"YMAXZMAX(30)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(31)),
"error: invalid boundary \"YMAXZMIN(31)\": boundary is not a line!");
}
}
{
const std::set<std::string> name_set = {"XMINYMIN", "XMINYMAX", "XMAXYMIN", "XMAXYMAX", "XMINZMIN",
"XMINZMAX", "XMAXZMAX", "XMINZMAX", "YMINZMIN"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
if ((name == "XMINYMIN") or (name == "XMINYMAX") or (name == "XMAXYMIN") or (name == "XMAXYMAX")) {
direction = R3{0, 0, -1};
} else if ((name == "XMINZMIN") or (name == "XMINZMAX") or (name == "XMAXZMIN") or (name == "XMAXZMAX")) {
direction = R3{0, -1, 0};
} else if ((name == "YMINZMIN")) {
direction = R3{1, 0, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMAXZMAX")),
"error: invalid boundary \"YMAXZMAX(30)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMINZMAX")),
"error: invalid boundary \"YMINZMAX(29)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMAXZMIN")),
"error: invalid boundary \"YMAXZMIN(31)\": boundary is not a line!");
}
}
}
SECTION("hybrid 3d")
{
std::shared_ptr p_mesh = MeshDataBaseForTests::get().hybrid3DMesh();
const ConnectivityType& connectivity = p_mesh->connectivity();
auto xr = p_mesh->xr();
auto curve = [](const R3& X) -> R3 {
return R3{X[0], (1 + X[0] * X[0]) * X[1], (1 - 0.2 * X[0] * X[0]) * X[2]};
};
NodeValue<R3> curved_xr{connectivity};
parallel_for(
connectivity.numberOfNodes(), PUGS_LAMBDA(const NodeId node_id) { curved_xr[node_id] = curve(xr[node_id]); });
MeshType mesh{p_mesh->shared_connectivity(), curved_xr};
{
const std::set<size_t> tag_set = {28, 29, 30, 31, 32, 33, 34, 35, 36};
for (auto tag : tag_set) {
NumberedBoundaryDescriptor numbered_boundary_descriptor(tag);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, numbered_boundary_descriptor);
auto edge_list = get_edge_list_from_tag(tag, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
switch (tag) {
case 30:
case 31:
case 34:
case 35: {
direction = R3{0, 0, -1};
break;
}
case 28:
case 29:
case 32:
case 33: {
direction = R3{0, -1, 0};
break;
}
case 36:
// case 37:
// case 38:
case 39: {
direction = R3{1, 0, 0};
break;
}
default: {
FAIL("unexpected tag number");
}
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(37)),
"error: invalid boundary \"YMINZMAX(37)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(38)),
"error: invalid boundary \"YMAXZMIN(38)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NumberedBoundaryDescriptor(39)),
"error: invalid boundary \"YMAXZMAX(39)\": boundary is not a line!");
}
}
{
const std::set<std::string> name_set = {"XMINYMIN", "XMINYMAX", "XMAXYMIN", "XMAXYMAX", "XMINZMIN",
"XMINZMAX", "XMAXZMAX", "XMINZMAX", "YMINZMIN"};
for (auto name : name_set) {
NamedBoundaryDescriptor named_boundary_descriptor(name);
const auto& edge_boundary = getMeshLineEdgeBoundary(mesh, named_boundary_descriptor);
auto edge_list = get_edge_list_from_name(name, connectivity);
REQUIRE(is_same(edge_boundary.edgeList(), edge_list));
R3 direction = zero;
if ((name == "XMINYMIN") or (name == "XMINYMAX") or (name == "XMAXYMIN") or (name == "XMAXYMAX")) {
direction = R3{0, 0, -1};
} else if ((name == "XMINZMIN") or (name == "XMINZMAX") or (name == "XMAXZMIN") or (name == "XMAXZMAX")) {
direction = R3{0, -1, 0};
} else if ((name == "YMINZMIN")) {
direction = R3{1, 0, 0};
} else {
FAIL("unexpected name: " + name);
}
REQUIRE(l2Norm(edge_boundary.direction() - direction) == Catch::Approx(0).margin(1E-13));
}
{
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMAXZMAX")),
"error: invalid boundary \"YMAXZMAX(39)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMINZMAX")),
"error: invalid boundary \"YMINZMAX(37)\": boundary is not a line!");
REQUIRE_THROWS_WITH(getMeshLineEdgeBoundary(mesh, NamedBoundaryDescriptor("YMAXZMIN")),
"error: invalid boundary \"YMAXZMIN(38)\": boundary is not a line!");
}
}
}
}
}
}