diff --git a/cmake/Scripts/IFEMTesting.cmake b/cmake/Scripts/IFEMTesting.cmake index 1e11e4f4..abb714c0 100644 --- a/cmake/Scripts/IFEMTesting.cmake +++ b/cmake/Scripts/IFEMTesting.cmake @@ -61,6 +61,11 @@ macro(IFEM_add_unittests IFEM_PATH) list(REMOVE_ITEM TEST_SOURCES ${IFEM_PATH}/src/LinAlg/Test/TestISTLPETScMatrix.C) endif() + if(LRSPLINE_FOUND OR LRSpline_FOUND) + file(GLOB LR_TEST_SRCS ${PROJECT_SOURCE_DIR}/src/ASM/LR/Test/*.C) + list(APPEND TEST_SOURCES ${LR_TEST_SRCS}) + endif() + IFEM_add_test_app("${TEST_SOURCES}" ${IFEM_PATH} IFEM diff --git a/src/ASM/LR/ASMu2D.C b/src/ASM/LR/ASMu2D.C index 30fa7582..207d8d70 100644 --- a/src/ASM/LR/ASMu2D.C +++ b/src/ASM/LR/ASMu2D.C @@ -1710,7 +1710,28 @@ bool ASMu2D::evalSolution (Matrix& sField, const IntegrandBase& integrand, void ASMu2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const { - // TODO: Implement this before attempting FSI simulations with LR B-splines + if (basis == 0) + basis = 1; + + if (!this->getBasis(basis)) return; // silently ignore empty patches + + LR::parameterEdge edge; + switch (lIndex) { + case 1: edge = LR::WEST; break; + case 2: edge = LR::EAST; break; + case 3: edge = LR::SOUTH; break; + case 4: edge = LR::NORTH; break; + default: return; + } + + nodes = this->getEdgeNodes(edge, basis); + +#if SP_DEBUG > 1 + std::cout <<"Boundary nodes in patch "<< idx+1 <<" edge "<< lIndex <<":"; + for (size_t i = 0; i < nodes.size(); i++) + std::cout <<" "<< nodes[i]; + std::cout << std::endl; +#endif } diff --git a/src/ASM/LR/ASMu3D.C b/src/ASM/LR/ASMu3D.C index c05d5d38..625103cf 100644 --- a/src/ASM/LR/ASMu3D.C +++ b/src/ASM/LR/ASMu3D.C @@ -1917,9 +1917,50 @@ bool ASMu3D::evalSolution (Matrix& sField, const IntegrandBase& integrand, } +std::vector ASMu3D::getFaceNodes (int face, int basis) const +{ + size_t ofs = 1; + for (int i = 1; i < basis; i++) + ofs += this->getNoNodes(i); + + std::vector edgeFunctions; + this->getBasis(basis)->getEdgeFunctions(edgeFunctions, + static_cast(face)); + + std::vector result(edgeFunctions.size()); + std::transform(edgeFunctions.begin(), edgeFunctions.end(), result.begin(), + [ofs](LR::Basisfunction* a) { return a->getId()+ofs; }); + + return result; +} + + void ASMu3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const { - // TODO: Implement this before attempting FSI simulations with LR B-splines + if (basis == 0) + basis = 1; + + if (!this->getBasis(basis)) return; // silently ignore empty patches + + LR::parameterEdge edge; + switch (lIndex) { + case 1: edge = LR::WEST; break; + case 2: edge = LR::EAST; break; + case 3: edge = LR::SOUTH; break; + case 4: edge = LR::NORTH; break; + case 5: edge = LR::BOTTOM; break; + case 6: edge = LR::TOP; break; + default: return; + } + + nodes = this->getFaceNodes(edge, basis); + +#if SP_DEBUG > 1 + std::cout <<"Boundary nodes in patch "<< idx+1 <<" edge "<< lIndex <<":"; + for (size_t i = 0; i < nodes.size(); i++) + std::cout <<" "<< nodes[i]; + std::cout << std::endl; +#endif } diff --git a/src/ASM/LR/ASMu3D.h b/src/ASM/LR/ASMu3D.h index 185e5257..5c24b6ac 100644 --- a/src/ASM/LR/ASMu3D.h +++ b/src/ASM/LR/ASMu3D.h @@ -84,6 +84,9 @@ public: //! \param[in] displ Incremental displacements to update the coordinates with virtual bool updateCoords(const Vector& displ); + //! \brief Returns the node indices for a given face. + std::vector getFaceNodes(int face, int basis = 1) const; + //! \brief Finds the global numbers of the nodes on a patch boundary. //! \param[in] lIndex Local index of the boundary edge //! \param glbNodes Array of global boundary node numbers diff --git a/src/ASM/LR/Test/TestASMu2D.C b/src/ASM/LR/Test/TestASMu2D.C new file mode 100644 index 00000000..1ef262ec --- /dev/null +++ b/src/ASM/LR/Test/TestASMu2D.C @@ -0,0 +1,80 @@ +//============================================================================== +//! +//! \file TestASMu2D.C +//! +//! \date Jul 14 2016 +//! +//! \author Arne Morten Kvarving / SINTEF +//! +//! \brief Tests for driver for assembly of unstructured 2D spline FE models. +//! +//============================================================================== + +#include "ASMu2D.h" +#include "IFEM.h" +#include "SIM2D.h" + +#include "gtest/gtest.h" + +TEST(TestASMu2D, BoundaryNodesE1) +{ + SIM2D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Edge1",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 4U); + for (int i = 0; i < 4; ++i) + ASSERT_EQ(vec[i], 4*i+1); +} + + +TEST(TestASMu2D, BoundaryNodesE2) +{ + SIM2D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Edge2",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 4U); + for (int i = 0; i < 4; ++i) + ASSERT_EQ(vec[i], 2+4*i); +} + + +TEST(TestASMu2D, BoundaryNodesE3) +{ + SIM2D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Edge3",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 4U); + for (int i = 0; i < 4; ++i) + ASSERT_EQ(vec[i], i+1); +} + + +TEST(TestASMu2D, BoundaryNodesE4) +{ + SIM2D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Edge4",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 4U); + for (int i = 0; i < 4; ++i) + ASSERT_EQ(vec[i], 5+i); +} diff --git a/src/ASM/LR/Test/TestASMu3D.C b/src/ASM/LR/Test/TestASMu3D.C new file mode 100644 index 00000000..19b5c68f --- /dev/null +++ b/src/ASM/LR/Test/TestASMu3D.C @@ -0,0 +1,116 @@ +//============================================================================== +//! +//! \file TestASMu3D.C +//! +//! \date Jul 14 2016 +//! +//! \author Arne Morten Kvarving / SINTEF +//! +//! \brief Tests for driver for assembly of unstructured 3D spline FE models. +//! +//============================================================================== + +#include "ASMu3D.h" +#include "IFEM.h" +#include "SIM3D.h" + +#include "gtest/gtest.h" + +TEST(TestASMu3D, BoundaryNodesF1) +{ + SIM3D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Face1",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + + ASSERT_EQ(vec.size(), 16U); + for (int i = 0; i < 16; ++i) + ASSERT_EQ(vec[i], 1+4*i); +} + + +TEST(TestASMu3D, BoundaryNodesF2) +{ + SIM3D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Face2",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 16U); + for (int i = 0; i < 16; ++i) + ASSERT_EQ(vec[i], 2+4*i); +} + + +TEST(TestASMu3D, BoundaryNodesF3) +{ + SIM3D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Face3",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + + ASSERT_EQ(vec.size(), 16U); + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + ASSERT_EQ(vec[4*i+j], 16*i+j+1); +} + + +TEST(TestASMu3D, BoundaryNodesF4) +{ + SIM3D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Face4",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 16U); + for (int i = 0; i < 4; ++i) + for (int j = 0; j < 4; ++j) + ASSERT_EQ(vec[4*i+j], 5+16*i+j); +} + + +TEST(TestASMu3D, BoundaryNodesF5) +{ + SIM3D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Face5",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 16U); + for (int i = 0; i < 16; ++i) + ASSERT_EQ(vec[i], i+1); +} + + +TEST(TestASMu3D, BoundaryNodesF6) +{ + SIM3D sim(1); + sim.opt.discretization = ASM::LRSpline; + ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); + sim.preprocess(); + + int bcode = sim.getUniquePropertyCode("Face6",0); + std::vector vec; + sim.getBoundaryNodes(bcode, vec); + ASSERT_EQ(vec.size(), 16U); + for (int i = 0; i < 16; ++i) + ASSERT_EQ(vec[i], 17+i); +} diff --git a/src/ASM/LR/Test/refdata/boundary_nodes.xinp b/src/ASM/LR/Test/refdata/boundary_nodes.xinp new file mode 100644 index 00000000..6bd44fa3 --- /dev/null +++ b/src/ASM/LR/Test/refdata/boundary_nodes.xinp @@ -0,0 +1,24 @@ + + + + + + + + + + 1 + + + 2 + + + 3 + + + 4 + + + + + diff --git a/src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp b/src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp new file mode 100644 index 00000000..6518f42b --- /dev/null +++ b/src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp @@ -0,0 +1,30 @@ + + + + + + + + + + 1 + + + 2 + + + 3 + + + 4 + + + 5 + + + 6 + + + + +