Forked from
ogs / ogs
14645 commits behind the upstream repository.
-
Dmitri Naumov authoredDmitri Naumov authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
LocalToGlobalIndexMapMultiComponent.cpp 13.22 KiB
/*
* \copyright
* Copyright (c) 2012-2019, 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 <memory>
#include "GeoLib/GEOObjects.h"
#include "GeoLib/Polyline.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/Location.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshEditing/DuplicateMeshComponents.h"
#include "MeshLib/MeshGenerators/MeshGenerator.h"
#include "MeshLib/MeshSearch/NodeSearch.h"
#include "MeshLib/MeshSubset.h"
#include "NumLib/DOF/LocalToGlobalIndexMap.h"
#include "MeshGeoToolsLib/MeshNodeSearcher.h"
#include "MeshGeoToolsLib/BoundaryElementsSearcher.h"
namespace NL = NumLib;
namespace MeL = MeshLib;
namespace MGTL = MeshGeoToolsLib;
class NumLibLocalToGlobalIndexMapMultiDOFTest : public ::testing::Test
{
public:
static const std::size_t mesh_subdivs = 4;
NumLibLocalToGlobalIndexMapMultiDOFTest()
{
mesh.reset(MeL::MeshGenerator::generateRegularQuadMesh(2.0, mesh_subdivs));
mesh_items_all_nodes =
std::make_unique<MeL::MeshSubset>(*mesh, mesh->getNodes());
auto ply_pnts = std::make_unique<std::vector<GeoLib::Point*>>();
ply_pnts->push_back(new GeoLib::Point(0.0, 0.0, 0.0));
ply_pnts->push_back(new GeoLib::Point(1.0, 0.0, 0.0));
std::string geometry_0("GeometryWithPntsAndPolyline");
geo_objs.addPointVec(std::move(ply_pnts), geometry_0, nullptr);
auto ply = new GeoLib::Polyline(*geo_objs.getPointVec(geometry_0));
ply->addPoint(0);
ply->addPoint(1);
auto plys = std::make_unique<std::vector<GeoLib::Polyline*>>();
plys->push_back(ply);
geo_objs.addPolylineVec(std::move(plys), geometry_0, nullptr);
auto search_length = std::make_unique<MGTL::SearchLength>();
MGTL::MeshNodeSearcher const& searcher_nodes =
MGTL::MeshNodeSearcher::getMeshNodeSearcher(
*mesh, std::move(search_length));
MGTL::BoundaryElementsSearcher searcher_elements(*mesh, searcher_nodes);
boundary_mesh = createMeshFromElementSelection(
"boundary_mesh",
MeshLib::cloneElements(
searcher_elements.getBoundaryElements(*ply)));
mesh_items_boundary = std::make_unique<MeshLib::MeshSubset>(
*boundary_mesh, boundary_mesh->getNodes());
}
void initComponents(const int num_components,
const int selected_component,
const NL::ComponentOrder order)
{
assert(selected_component < static_cast<int>(num_components));
std::vector<MeshLib::MeshSubset> components;
for (int i = 0; i < num_components; ++i)
{
components.emplace_back(*mesh_items_all_nodes);
}
std::vector<int> vec_var_n_components(1, num_components);
dof_map = std::make_unique<NL::LocalToGlobalIndexMap>(
std::move(components), vec_var_n_components, order);
MeL::MeshSubset components_boundary{*mesh_items_boundary};
dof_map_boundary.reset(dof_map->deriveBoundaryConstrainedMap(
0, // variable id
{selected_component},
std::move(components_boundary)));
}
// Multi-component version.
void initComponents(int const num_components,
std::vector<int> const& selected_components,
NL::ComponentOrder const order)
{
assert(static_cast<int>(selected_components.size()) <= num_components);
std::vector<MeshLib::MeshSubset> components;
for (int i = 0; i < num_components; ++i)
{
components.emplace_back(*mesh_items_all_nodes);
}
std::vector<int> vec_var_n_components(1, num_components);
dof_map = std::make_unique<NL::LocalToGlobalIndexMap>(
std::move(components), vec_var_n_components, order);
MeL::MeshSubset components_boundary{*mesh_items_boundary};
dof_map_boundary.reset(dof_map->deriveBoundaryConstrainedMap(
0, // variable id
selected_components,
std::move(components_boundary)));
}
template <NL::ComponentOrder order>
void test(const int num_components, const int selected_component,
std::function<std::size_t(std::size_t, std::size_t)> const&
compute_global_index);
// Multicomponent version
template <NL::ComponentOrder order>
void test(const int num_components,
std::vector<int> const& selected_component,
std::function<std::size_t(std::size_t, std::size_t)> const&
compute_global_index);
std::unique_ptr<const MeshLib::Mesh> mesh;
std::unique_ptr<MeL::MeshSubset const> mesh_items_all_nodes;
GeoLib::GEOObjects geo_objs;
std::unique_ptr<NL::LocalToGlobalIndexMap> dof_map;
std::unique_ptr<NL::LocalToGlobalIndexMap> dof_map_boundary;
std::unique_ptr<const MeshLib::Mesh> boundary_mesh;
std::unique_ptr<MeL::MeshSubset const> mesh_items_boundary;
/// Intersection of boundary nodes and bulk mesh subset.
std::vector<MeshLib::Node*> nodes_subset;
};
struct ComputeGlobalIndexByComponent
{
std::size_t num_nodes;
std::size_t operator()(std::size_t const node,
std::size_t const component) const
{
return node + component * num_nodes;
}
};
struct ComputeGlobalIndexByLocation
{
std::size_t num_components;
std::size_t operator()(std::size_t const node,
std::size_t const component) const
{
return node * num_components + component;
}
};
template <NL::ComponentOrder ComponentOrder>
void NumLibLocalToGlobalIndexMapMultiDOFTest::test(
const int num_components,
const int selected_component,
std::function<std::size_t(std::size_t, std::size_t)> const&
compute_global_index)
{
initComponents(num_components, selected_component, ComponentOrder);
ASSERT_EQ(dof_map->getNumberOfComponents(), num_components);
ASSERT_EQ(dof_map->size(), mesh->getNumberOfElements());
ASSERT_EQ(dof_map_boundary->getNumberOfComponents(), 1);
ASSERT_EQ(dof_map_boundary->size(), boundary_mesh->getNumberOfElements());
// check mesh elements
for (unsigned e=0; e<dof_map->size(); ++e)
{
auto const element_nodes_size = mesh->getElement(e)->getNumberOfNodes();
auto const ptr_element_nodes = mesh->getElement(e)->getNodes();
for (int c = 0; c < dof_map->getNumberOfComponents(); ++c)
{
auto const& global_idcs = (*dof_map)(e, c).rows;
ASSERT_EQ(element_nodes_size, global_idcs.size());
for (unsigned n = 0; n < element_nodes_size; ++n)
{
auto const node_id = ptr_element_nodes[n]->getID();
auto const glob_idx = compute_global_index(node_id, c);
EXPECT_EQ(glob_idx, global_idcs[n]);
}
}
}
// check boundary elements
for (unsigned e=0; e<dof_map_boundary->size(); ++e)
{
ASSERT_EQ(1, dof_map_boundary->getNumberOfComponents());
for (int c = 0; c < 1; ++c)
{
auto const& global_idcs = (*dof_map_boundary)(e, c).rows;
ASSERT_EQ(2, global_idcs.size()); // boundary of quad is line with two nodes
// e is the number of a boundary element (which is a line, so two
// nodes) from 0 to something. e+n must be the node ids along the
// x-axis of the mesh;
for (unsigned n = 0; n < 2; ++n)
{
auto const node = e + n;
auto const glob_idx =
compute_global_index(node, selected_component);
EXPECT_EQ(glob_idx, global_idcs[n]);
}
}
}
}
// Multicomponent version
template <NL::ComponentOrder ComponentOrder>
void NumLibLocalToGlobalIndexMapMultiDOFTest::test(
int const num_components,
std::vector<int> const& selected_components,
std::function<std::size_t(std::size_t, std::size_t)> const&
compute_global_index)
{
initComponents(num_components, selected_components, ComponentOrder);
ASSERT_EQ(dof_map->getNumberOfComponents(), num_components);
ASSERT_EQ(dof_map->size(), mesh->getNumberOfElements());
ASSERT_EQ(dof_map_boundary->getNumberOfComponents(),
selected_components.size());
ASSERT_EQ(dof_map_boundary->size(), boundary_mesh->getNumberOfElements());
// check mesh elements
for (unsigned e = 0; e < dof_map->size(); ++e)
{
auto const element_nodes_size = mesh->getElement(e)->getNumberOfNodes();
auto const ptr_element_nodes = mesh->getElement(e)->getNodes();
for (int c = 0; c < dof_map->getNumberOfComponents(); ++c)
{
auto const& global_idcs = (*dof_map)(e, c).rows;
ASSERT_EQ(element_nodes_size, global_idcs.size());
for (unsigned n = 0; n < element_nodes_size; ++n)
{
auto const node_id = ptr_element_nodes[n]->getID();
auto const glob_idx = compute_global_index(node_id, c);
EXPECT_EQ(glob_idx, global_idcs[n]);
}
}
}
// check boundary elements
for (unsigned e = 0; e < dof_map_boundary->size(); ++e)
{
ASSERT_EQ(selected_components.size(),
dof_map_boundary->getNumberOfComponents());
for (int c = 0; c < static_cast<int>(selected_components.size()); ++c)
{
auto const& global_idcs = (*dof_map_boundary)(e, c).rows;
ASSERT_EQ(
2,
global_idcs.size()); // boundary of quad is line with two nodes
// e is the number of a boundary element (which is a line, so two
// nodes) from 0 to something. e+n must be the node ids along the
// x-axis of the mesh;
for (unsigned n = 0; n < 2; ++n)
{
auto const node = e + n;
auto const glob_idx =
compute_global_index(node, selected_components[c]);
EXPECT_EQ(glob_idx, global_idcs[n]);
}
}
}
}
void assert_equal(NL::LocalToGlobalIndexMap const& dof1, NL::LocalToGlobalIndexMap const& dof2)
{
ASSERT_EQ(dof1.size(), dof2.size());
ASSERT_EQ(dof1.getNumberOfComponents(), dof2.getNumberOfComponents());
for (unsigned e=0; e<dof1.size(); ++e)
{
for (int c = 0; c < dof1.getNumberOfComponents(); ++c)
{
EXPECT_EQ(dof1(e, c).rows, dof2(e, c).rows);
EXPECT_EQ(dof1(e, c).columns, dof2(e, c).columns);
}
}
}
#ifndef USE_PETSC
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, Test1Comp)
#else
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, DISABLED_Test1Comp)
#endif
{
int const num_components = 1;
test<NL::ComponentOrder::BY_LOCATION>(
num_components, 0, ComputeGlobalIndexByComponent{num_components});
auto dof_map_bc = std::move(dof_map);
auto dof_map_boundary_bc = std::move(dof_map_boundary);
test<NL::ComponentOrder::BY_COMPONENT>(
num_components, 0,
ComputeGlobalIndexByComponent{(mesh_subdivs + 1) * (mesh_subdivs + 1)});
assert_equal(*dof_map, *dof_map_bc);
assert_equal(*dof_map_boundary, *dof_map_boundary_bc);
}
#ifndef USE_PETSC
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, TestMultiCompByComponent)
#else
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, DISABLED_TestMultiCompByComponent)
#endif
{
int const num_components = 5;
for (int c = 0; c < num_components; ++c)
{
test<NL::ComponentOrder::BY_COMPONENT>(
num_components, c,
ComputeGlobalIndexByComponent{(mesh_subdivs + 1) *
(mesh_subdivs + 1)});
}
}
#ifndef USE_PETSC
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, TestMultiCompByLocation)
#else
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, DISABLED_TestMultiCompByLocation)
#endif
{
int const num_components = 5;
for (int c = 0; c < num_components; ++c)
{
test<NL::ComponentOrder::BY_LOCATION>(
num_components, c, ComputeGlobalIndexByLocation{num_components});
}
}
#ifndef USE_PETSC
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, TestMultiComp2ByComponent)
#else
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest,
DISABLED_TestMultiComp2ByComponent)
#endif
{
int const num_components = 5;
for (int c = 0; c < num_components; ++c)
{
std::vector<int> const components = {c, (c + 1) % num_components};
test<NL::ComponentOrder::BY_COMPONENT>(
num_components, components,
ComputeGlobalIndexByComponent{(mesh_subdivs + 1) *
(mesh_subdivs + 1)});
}
}
#ifndef USE_PETSC
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest, TestMultiComp2ByLocation)
#else
TEST_F(NumLibLocalToGlobalIndexMapMultiDOFTest,
DISABLED_TestMultiComp2ByLocation)
#endif
{
int const num_components = 5;
for (int c = 0; c < num_components; ++c)
{
std::vector<int> const components = {c, (c + 1) % num_components};
test<NL::ComponentOrder::BY_LOCATION>(
num_components, components,
ComputeGlobalIndexByLocation{num_components});
}
}