Skip to content
Snippets Groups Projects
Commit 280c0717 authored by Christoph Lehmann's avatar Christoph Lehmann
Browse files

[T] added multi-dof test

parent 4ee66f09
No related branches found
No related tags found
1 merge request!871Multiple nodal d.o.f.
/*
* \copyright
* Copyright (c) 2012-2015, 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 "AssemblerLib/LocalAssemblerBuilder.h"
#include "AssemblerLib/VectorMatrixAssembler.h"
#include "MeshLib/Elements/Element.h"
#include "MeshLib/Location.h"
#include "MeshLib/Mesh.h"
#include "MeshLib/MeshSubsets.h"
#include "MeshLib/MeshGenerators/MeshGenerator.h"
#include "MeshLib/MeshSearch/NodeSearch.h"
#include "GeoLib/Polyline.h"
#include "GeoLib/GEOObjects.h"
#include "MeshGeoToolsLib/MeshNodeSearcher.h"
#include "MeshGeoToolsLib/BoundaryElementsSearcher.h"
#include <iostream>
namespace AL = AssemblerLib;
namespace MeL = MeshLib;
namespace MGTL = MeshGeoToolsLib;
class AssemblerLibLocalToGlobalIndexMapMultiDOFTest : public ::testing::Test
{
public:
static const std::size_t mesh_subdivs = 4;
AssemblerLibLocalToGlobalIndexMapMultiDOFTest()
{
mesh.reset(MeL::MeshGenerator::generateRegularQuadMesh(2.0, mesh_subdivs));
mesh_items_all_nodes.reset(new MeL::MeshSubset(*mesh, &mesh->getNodes()));
std::vector<GeoLib::Point*>* ply_pnts = new 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(ply_pnts, geometry_0, nullptr);
auto ply = new GeoLib::Polyline(*geo_objs.getPointVec(geometry_0));
ply->addPoint(0);
ply->addPoint(1);
std::vector<GeoLib::Polyline*>* plys = new std::vector<GeoLib::Polyline*>;
plys->push_back(ply);
geo_objs.addPolylineVec(plys, geometry_0, nullptr);
MGTL::MeshNodeSearcher& searcher_nodes = MGTL::MeshNodeSearcher::getMeshNodeSearcher(*mesh);
MGTL::BoundaryElementsSearcher searcher_elements(*mesh, searcher_nodes);
auto elems = searcher_elements.getBoundaryElements(*ply);
// deep copy because the searcher destroys the elements.
std::transform(elems.cbegin(), elems.cend(),
std::back_inserter(boundary_elements),
std::mem_fn(&MeL::Element::clone));
std::vector<MeL::Node*> nodes = MeL::getUniqueNodes(boundary_elements);
mesh_items_boundary.reset(
mesh_items_all_nodes->getIntersectionByNodes(nodes));
}
virtual ~AssemblerLibLocalToGlobalIndexMapMultiDOFTest()
{
for (auto p : components_boundary)
delete p;
for (auto p : components)
delete p;
for (auto p : boundary_elements)
delete p;
}
void clear()
{
for (auto* mss : components) {
delete mss;
}
components.clear();
for (auto* mss : components_boundary) {
delete mss;
}
components_boundary.clear();
}
void initComponents(const unsigned num_components, const unsigned selected_component,
const AL::ComponentOrder order)
{
assert(selected_component < num_components);
clear();
for (unsigned i=0; i<num_components; ++i)
{
components.push_back(new MeL::MeshSubsets(
mesh_items_all_nodes.get()));
}
dof_map.reset(new AL::LocalToGlobalIndexMap(components, order));
components_boundary.resize(num_components, nullptr);
components_boundary[selected_component] =
new MeL::MeshSubsets(mesh_items_boundary.get());
dof_map_boundary.reset(
dof_map->deriveBoundaryConstrainedMap(components_boundary, boundary_elements)
);
}
template <AL::ComponentOrder order>
void test(const unsigned num_components, const unsigned 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<const MeL::MeshSubset> mesh_items_all_nodes;
std::vector<MeL::MeshSubsets*> components_boundary;
std::vector<MeL::MeshSubsets*> components;
GeoLib::GEOObjects geo_objs;
std::unique_ptr<AL::LocalToGlobalIndexMap> dof_map;
std::unique_ptr<AL::LocalToGlobalIndexMap> dof_map_boundary;
std::unique_ptr<MeL::MeshSubset const> mesh_items_boundary;
std::vector<MeL::Element*> boundary_elements;
};
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 <AL::ComponentOrder ComponentOrder>
void AssemblerLibLocalToGlobalIndexMapMultiDOFTest::test(
const unsigned num_components,
const unsigned selected_component,
std::function<std::size_t(std::size_t, std::size_t)> const
compute_global_index)
{
initComponents(num_components, selected_component, ComponentOrder);
ASSERT_TRUE(dof_map->getNumComponents() == num_components);
ASSERT_TRUE(dof_map->size() == mesh->getNElements());
ASSERT_TRUE(dof_map_boundary->getNumComponents() == 1);
ASSERT_TRUE(dof_map_boundary->size() == boundary_elements.size());
// check mesh elements
for (unsigned e=0; e<dof_map->size(); ++e)
{
for (unsigned c=0; c<dof_map->getNumComponents(); ++c)
{
auto const& global_idcs = (*dof_map)(e, c).rows;
ASSERT_EQ(4, global_idcs.size()); // quad element with four nodes
for (unsigned n=0; n<4; ++n) // boundary of quad is line with two nodes
{
unsigned node = e/4*(mesh_subdivs+1) + e%4; // first node of the quad
switch (n)
{
case 0: break;
case 1: node += 1; break;
case 2: node += 1 + (mesh_subdivs+1); break;
case 3: node += (mesh_subdivs+1); break;
}
auto const glob_idx = compute_global_index(node, 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->getNumComponents());
for (unsigned 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
for (unsigned n=0; n<2; ++n) // boundary of quad is line with two nodes
{
auto const node = e + n;
auto const glob_idx =
compute_global_index(node, selected_component);
EXPECT_EQ(glob_idx, global_idcs[n]);
}
}
}
}
void assert_equal(AL::LocalToGlobalIndexMap const& dof1, AL::LocalToGlobalIndexMap const& dof2)
{
ASSERT_TRUE(dof1.size() == dof2.size());
ASSERT_TRUE(dof1.getNumComponents() == dof2.getNumComponents());
for (unsigned e=0; e<dof1.size(); ++e)
{
for (unsigned c=0; c<dof1.getNumComponents(); ++c)
{
EXPECT_TRUE(dof1(e, c).rows == dof2(e, c).rows);
EXPECT_TRUE(dof1(e, c).columns == dof2(e, c).columns);
}
}
}
TEST_F(AssemblerLibLocalToGlobalIndexMapMultiDOFTest, Test1Comp)
{
unsigned const num_components = 1;
test<AL::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<AL::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);
}
TEST_F(AssemblerLibLocalToGlobalIndexMapMultiDOFTest, Test_2Comp_0thSel_ByComp)
{
test<AL::ComponentOrder::BY_COMPONENT>(
2, 0,
ComputeGlobalIndexByComponent{(mesh_subdivs + 1) * (mesh_subdivs + 1)});
}
TEST_F(AssemblerLibLocalToGlobalIndexMapMultiDOFTest, Test_2Comp_0thSel_ByLoc)
{
test<AL::ComponentOrder::BY_LOCATION>(2, 0,
ComputeGlobalIndexByLocation{2});
}
TEST_F(AssemblerLibLocalToGlobalIndexMapMultiDOFTest, Test_2Comp_1stSel_ByComp)
{
test<AL::ComponentOrder::BY_COMPONENT>(
2, 1,
ComputeGlobalIndexByComponent{(mesh_subdivs + 1) * (mesh_subdivs + 1)});
}
TEST_F(AssemblerLibLocalToGlobalIndexMapMultiDOFTest, Test_2Comp_1stSel_ByLoc)
{
test<AL::ComponentOrder::BY_LOCATION>(2, 1,
ComputeGlobalIndexByLocation{2});
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment