diff --git a/src/ASM/ASMbase.h b/src/ASM/ASMbase.h index abe5ae5a..2324d3e3 100644 --- a/src/ASM/ASMbase.h +++ b/src/ASM/ASMbase.h @@ -206,12 +206,12 @@ public: //! in one element virtual bool getElementCoordinates(Matrix& X, int iel) const = 0; - //! \brief Finds the global numbers of the nodes on a patch boundary. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary face/edge - //! \param glbNodes Array of global boundary node numbers + //! \param nodes Array of node numbers //! \param basis Which basis to grab nodes for (0 for all) - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, - int basis = 0) const = 0; + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int basis = 0, bool local = false) const = 0; //! \brief Finds the node that is closest to the given point. virtual std::pair findClosestNode(const Vec3&) const diff --git a/src/ASM/ASMs1D.C b/src/ASM/ASMs1D.C index c21f0dea..fc2bbf66 100644 --- a/src/ASM/ASMs1D.C +++ b/src/ASM/ASMs1D.C @@ -584,17 +584,20 @@ bool ASMs1D::updateRotations (const Vector& displ, bool reInit) } -void ASMs1D::getBoundaryNodes (int lIndex, IntVec& glbNodes, int) const +void ASMs1D::getBoundaryNodes (int lIndex, IntVec& nodes, + int, bool local) const { if (!curv) return; // silently ignore empty patches size_t iel = lIndex == 1 ? 0 : nel-1; if (MLGE[iel] > 0) { + int node; if (lIndex == 1) - glbNodes.push_back(MLGN[MNPC[iel].front()]); + node = MNPC[iel].front(); else if (lIndex == 2) - glbNodes.push_back(MLGN[MNPC[iel][curv->order()-1]]); + node = MNPC[iel][curv->order()-1]; + nodes.push_back(local ? node+1 : MLGN[node]); } } diff --git a/src/ASM/ASMs1D.h b/src/ASM/ASMs1D.h index 8b83117a..e35ba6df 100644 --- a/src/ASM/ASMs1D.h +++ b/src/ASM/ASMs1D.h @@ -105,10 +105,12 @@ public: //! \brief Updates the previous nodal rotations for this patch at convergence. void updateRotations() { prevT = myT; } - //! \brief Finds the global number of the node on a patch end. + //! \brief Finds the global (or patch-local) node number on a patch end. //! \param[in] lIndex Local index of the end point - //! \param glbNodes Array of global boundary node numbers - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int) const; + //! \param nodes Array of global boundary node numbers + //! \param local If \e true, return patch-local node numbers + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int, bool local) const; //! \brief Finds the node that is closest to the given point. //! \param[in] X Global coordinates of point to search for diff --git a/src/ASM/ASMs2D.C b/src/ASM/ASMs2D.C index 3bc79520..57530075 100644 --- a/src/ASM/ASMs2D.C +++ b/src/ASM/ASMs2D.C @@ -1292,7 +1292,7 @@ bool ASMs2D::updateCoords (const Vector& displ) } -void ASMs2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const +void ASMs2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis, bool local) const { if (basis == 0) basis = 1; @@ -1316,14 +1316,14 @@ void ASMs2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const node += n1-1; case 1: // Left edge (negative I-direction) for (int i2 = 1; i2 <= n2; i2++, node += n1) - nodes.push_back(getNodeID(node)); + nodes.push_back(local ? node : this->getNodeID(node)); break; case 4: // Back edge (positive J-direction) node += n1*(n2-1); case 3: // Front edge (negative J-direction) for (int i1 = 1; i1 <= n1; i1++, node++) - nodes.push_back(getNodeID(node)); + nodes.push_back(local ? node : this->getNodeID(node)); break; } diff --git a/src/ASM/ASMs2D.h b/src/ASM/ASMs2D.h index 8ade565f..3946c44d 100644 --- a/src/ASM/ASMs2D.h +++ b/src/ASM/ASMs2D.h @@ -179,11 +179,13 @@ public: //! \param[in] displ Incremental displacements to update the coordinates with virtual bool updateCoords(const Vector& displ); - //! \brief Finds the global numbers of the nodes on a patch boundary. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary edge - //! \param glbNodes Array of global boundary node numbers - //! \param basis Which basis to grab nodes for - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis) const; + //! \param nodes Array of node numbers + //! \param basis Which basis to grab nodes for (0 for all) + //! \param local If \e true, return patch-local node numbers + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int basis, bool local) const; //! \brief Returns the node index for a given corner. virtual int getCorner(int I, int J, int basis = 1) const; diff --git a/src/ASM/ASMs2Dmx.C b/src/ASM/ASMs2Dmx.C index 74ff5e3a..05fd3174 100644 --- a/src/ASM/ASMs2Dmx.C +++ b/src/ASM/ASMs2Dmx.C @@ -1014,11 +1014,12 @@ void ASMs2Dmx::generateThreadGroups (const Integrand& integrand, bool silence, } -void ASMs2Dmx::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const +void ASMs2Dmx::getBoundaryNodes (int lIndex, IntVec& nodes, + int basis, bool local) const { if (basis > 0) - this->ASMs2D::getBoundaryNodes(lIndex, nodes, basis); + this->ASMs2D::getBoundaryNodes(lIndex, nodes, basis, local); else for (size_t b = 1; b <= this->getNoBasis(); ++b) - this->ASMs2D::getBoundaryNodes(lIndex, nodes, b); + this->ASMs2D::getBoundaryNodes(lIndex, nodes, b, local); } diff --git a/src/ASM/ASMs2Dmx.h b/src/ASM/ASMs2Dmx.h index 0e2beece..2f128383 100644 --- a/src/ASM/ASMs2Dmx.h +++ b/src/ASM/ASMs2Dmx.h @@ -208,11 +208,12 @@ public: //! \param[in] basis Which basis to return size parameters for virtual bool getSize(int& n1, int& n2, int basis = 0) const; - //! \brief Finds the global numbers of the nodes on a patch boundary. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary edge - //! \param glbNodes Array of global boundary node numbers + //! \param nodes Array of node numbers //! \param basis Which basis to grab nodes for (0 for all) - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis) const; + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int basis, bool local = false) const; protected: std::vector> m_basis; //!< Vector of bases diff --git a/src/ASM/ASMs3D.C b/src/ASM/ASMs3D.C index c24f89ad..c5a2f98d 100644 --- a/src/ASM/ASMs3D.C +++ b/src/ASM/ASMs3D.C @@ -1542,7 +1542,8 @@ bool ASMs3D::updateCoords (const Vector& displ) } -void ASMs3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const +void ASMs3D::getBoundaryNodes (int lIndex, IntVec& nodes, + int basis, bool local) const { if (basis == 0) basis = 1; @@ -1562,7 +1563,7 @@ void ASMs3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const case 1: // Left face (negative I-direction) for (int i3 = 1; i3 <= n3; i3++) for (int i2 = 1; i2 <= n2; i2++, node += n1) - nodes.push_back(getNodeID(node)); + nodes.push_back(local ? node : this->getNodeID(node)); break; case 4: // Back face (positive J-direction) @@ -1570,7 +1571,7 @@ void ASMs3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const case 3: // Front face (negative J-direction) for (int i3 = 1; i3 <= n3; i3++, node += n1*(n2-1)) for (int i1 = 1; i1 <= n1; i1++, node++) - nodes.push_back(getNodeID(node)); + nodes.push_back(local ? node : this->getNodeID(node)); break; case 6: // Top face (positive K-direction) @@ -1578,7 +1579,7 @@ void ASMs3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const case 5: // Bottom face (negative K-direction) for (int i2 = 1; i2 <= n2; i2++) for (int i1 = 1; i1 <= n1; i1++, node++) - nodes.push_back(getNodeID(node)); + nodes.push_back(local ? node : this->getNodeID(node)); break; } diff --git a/src/ASM/ASMs3D.h b/src/ASM/ASMs3D.h index c8ebef98..01cfc46f 100644 --- a/src/ASM/ASMs3D.h +++ b/src/ASM/ASMs3D.h @@ -195,11 +195,13 @@ public: //! \param[in] displ Incremental displacements to update the coordinates with virtual bool updateCoords(const Vector& displ); - //! \brief Finds the global numbers of the nodes on a patch boundary. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary face - //! \param glbNodes Array of global boundary node numbers + //! \param nodes Array of node numbers //! \param basis Which basis to grab nodes for (0 for all) - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis) const; + //! \param local If \e true, return patch-local node numbers + virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis, + bool local) const; //! \brief Returns the node index for a given corner. virtual int getCorner(int I, int J, int K, int basis = 1) const; diff --git a/src/ASM/ASMs3Dmx.C b/src/ASM/ASMs3Dmx.C index 108e9947..41230fa3 100644 --- a/src/ASM/ASMs3Dmx.C +++ b/src/ASM/ASMs3Dmx.C @@ -1109,11 +1109,12 @@ double ASMs3Dmx::getParametricArea (int iel, int dir) const } -void ASMs3Dmx::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const +void ASMs3Dmx::getBoundaryNodes (int lIndex, IntVec& nodes, + int basis, bool local) const { if (basis > 0) - this->ASMs3D::getBoundaryNodes(lIndex, nodes, basis); + this->ASMs3D::getBoundaryNodes(lIndex, nodes, basis, local); else for (size_t b = 1; b <= this->getNoBasis(); ++b) - this->ASMs3D::getBoundaryNodes(lIndex, nodes, b); + this->ASMs3D::getBoundaryNodes(lIndex, nodes, b, local); } diff --git a/src/ASM/ASMs3Dmx.h b/src/ASM/ASMs3Dmx.h index 89829b2f..7b141bb4 100644 --- a/src/ASM/ASMs3Dmx.h +++ b/src/ASM/ASMs3Dmx.h @@ -214,11 +214,13 @@ protected: //! \param[in] dir Local face index of the boundary face double getParametricArea(int iel, int dir) const; - //! \brief Finds the global numbers of the nodes on a patch boundary. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary edge - //! \param glbNodes Array of global boundary node numbers + //! \param nodes Array of global boundary node numbers //! \param basis Which basis to grab nodes for (0 for all) - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis = 0) const; + //! \param local If \e true, return patch-local node numbers + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int basis, bool local) const; private: std::vector> m_basis; //!< Vector of bases diff --git a/src/ASM/LR/ASMu2D.C b/src/ASM/LR/ASMu2D.C index d5aebc0b..cde6e032 100644 --- a/src/ASM/LR/ASMu2D.C +++ b/src/ASM/LR/ASMu2D.C @@ -1812,7 +1812,8 @@ bool ASMu2D::evalSolution (Matrix& sField, const IntegrandBase& integrand, } -void ASMu2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const +void ASMu2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis, + bool local) const { if (basis == 0) basis = 1; diff --git a/src/ASM/LR/ASMu2D.h b/src/ASM/LR/ASMu2D.h index d59c1182..b17b99d3 100644 --- a/src/ASM/LR/ASMu2D.h +++ b/src/ASM/LR/ASMu2D.h @@ -91,10 +91,12 @@ public: //! \param[in] displ Incremental displacements to update the coordinates with virtual bool updateCoords(const Vector& displ); - //! \brief Finds the global numbers of the nodes on a patch boundary. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary edge - //! \param glbNodes Array of global boundary node numbers - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis) const; + //! \param nodes Array of node numbers + //! \param local If true return patch-local node numbers + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int basis, bool local = false) const; //! \brief Returns the polynomial order in each parameter direction. //! \param[out] p1 Order in first (u) direction diff --git a/src/ASM/LR/ASMu3D.C b/src/ASM/LR/ASMu3D.C index 57dee37b..01240200 100644 --- a/src/ASM/LR/ASMu3D.C +++ b/src/ASM/LR/ASMu3D.C @@ -1966,7 +1966,7 @@ std::vector ASMu3D::getFaceNodes (int face, int basis) const } -void ASMu3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis) const +void ASMu3D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis, bool) const { if (basis == 0) basis = 1; diff --git a/src/ASM/LR/ASMu3D.h b/src/ASM/LR/ASMu3D.h index a57a55c1..62fc6679 100644 --- a/src/ASM/LR/ASMu3D.h +++ b/src/ASM/LR/ASMu3D.h @@ -87,10 +87,12 @@ public: //! \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. + //! \brief Finds the global (or patch-local) node numbers on a patch boundary. //! \param[in] lIndex Local index of the boundary edge - //! \param glbNodes Array of global boundary node numbers - virtual void getBoundaryNodes(int lIndex, IntVec& glbNodes, int basis) const; + //! \param nodes Array of global boundary node numbers + //! \param local If \e true return patch-local node numbers + virtual void getBoundaryNodes(int lIndex, IntVec& nodes, + int basis, bool local) const; //! \brief Returns the node index for a given corner. virtual int getCorner(int I, int J, int K, int basis = 1) const; diff --git a/src/ASM/LR/Test/TestASMu2D.C b/src/ASM/LR/Test/TestASMu2D.C index 556c98f0..7cb34804 100644 --- a/src/ASM/LR/Test/TestASMu2D.C +++ b/src/ASM/LR/Test/TestASMu2D.C @@ -31,16 +31,6 @@ class TestASMu2D : public testing::Test, }; -static void getBoundaryNodes (const char* edgeName, std::vector& nodes) -{ - SIM2D sim(1); - sim.opt.discretization = ASM::LRSpline; - ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes.xinp")); - ASSERT_TRUE(sim.createFEMmodel()); - sim.getBoundaryNodes(sim.getUniquePropertyCode(edgeName,0),nodes); -} - - static ASMu2D* getPatch (SIMinput& sim) { sim.opt.discretization = ASM::LRSpline; @@ -50,46 +40,6 @@ static ASMu2D* getPatch (SIMinput& sim) } -TEST(TestASMu2D, BoundaryNodesE1) -{ - std::vector vec; - getBoundaryNodes("Edge1",vec); - ASSERT_EQ(vec.size(), 4U); - for (int i = 0; i < 4; ++i) - ASSERT_EQ(vec[i], 4*i+1); -} - - -TEST(TestASMu2D, BoundaryNodesE2) -{ - std::vector vec; - getBoundaryNodes("Edge2",vec); - ASSERT_EQ(vec.size(), 4U); - for (int i = 0; i < 4; ++i) - ASSERT_EQ(vec[i], 2+4*i); -} - - -TEST(TestASMu2D, BoundaryNodesE3) -{ - std::vector vec; - getBoundaryNodes("Edge3",vec); - ASSERT_EQ(vec.size(), 4U); - for (int i = 0; i < 4; ++i) - ASSERT_EQ(vec[i], i+1); -} - - -TEST(TestASMu2D, BoundaryNodesE4) -{ - std::vector vec; - getBoundaryNodes("Edge4",vec); - ASSERT_EQ(vec.size(), 4U); - for (int i = 0; i < 4; ++i) - ASSERT_EQ(vec[i], 5+i); -} - - TEST_P(TestASMu2D, ConstrainEdge) { SIM2D sim(1); @@ -97,7 +47,7 @@ TEST_P(TestASMu2D, ConstrainEdge) ASSERT_TRUE(pch != nullptr); pch->constrainEdge(GetParam().edgeIdx, false, 1, 1, 1); std::vector glbNodes; - pch->getBoundaryNodes(GetParam().edge, glbNodes, 1); + pch->getBoundaryNodes(GetParam().edge, glbNodes, 1, 1); for (int& it : glbNodes) ASSERT_TRUE(pch->findMPC(it, 1) != nullptr); } @@ -110,7 +60,7 @@ TEST_P(TestASMu2D, ConstrainEdgeOpen) ASSERT_TRUE(pch != nullptr); pch->constrainEdge(GetParam().edgeIdx, true, 1, 1, 1); std::vector glbNodes; - pch->getBoundaryNodes(GetParam().edge, glbNodes, 1); + pch->getBoundaryNodes(GetParam().edge, glbNodes, 1, 1); int crn = pch->getCorner(GetParam().c1[0], GetParam().c1[1], 1); ASSERT_TRUE(pch->findMPC(crn, 1) == nullptr); glbNodes.erase(std::find(glbNodes.begin(), glbNodes.end(), crn)); diff --git a/src/ASM/LR/Test/TestASMu3D.C b/src/ASM/LR/Test/TestASMu3D.C index 9909ddce..d87d4782 100644 --- a/src/ASM/LR/Test/TestASMu3D.C +++ b/src/ASM/LR/Test/TestASMu3D.C @@ -15,74 +15,47 @@ #include "gtest/gtest.h" +class TestASMu3D : + public testing::Test, + public testing::WithParamInterface +{ +}; -static void getBoundaryNodes (const char* faceName, std::vector& nodes) + +TEST_P(TestASMu3D, BoundaryNodes) { SIM3D sim(1); sim.opt.discretization = ASM::LRSpline; ASSERT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes_3d.xinp")); - ASSERT_TRUE(sim.createFEMmodel()); - sim.getBoundaryNodes(sim.getUniquePropertyCode(faceName,0),nodes); -} + sim.preprocess(); - -TEST(TestASMu3D, BoundaryNodesF1) -{ + std::stringstream str; + str << "Face" << GetParam(); + int bcode = sim.getUniquePropertyCode(str.str(),0); std::vector vec; - getBoundaryNodes("Face1",vec); + sim.getBoundaryNodes(bcode,vec); ASSERT_EQ(vec.size(), 16U); - for (int i = 0; i < 16; ++i) - ASSERT_EQ(vec[i], 1+4*i); + auto it = vec.begin(); + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 4; ++j) { + if (GetParam() == 1) + ASSERT_EQ(*it++, 1+4*(4*i+j)); + else if (GetParam() == 2) + ASSERT_EQ(*it++, 2+4*(4*i+j)); + else if (GetParam() == 3) + ASSERT_EQ(*it++, 16*i+j+1); + else if (GetParam() == 4) + ASSERT_EQ(*it++, 5+16*i+j); + else if (GetParam() == 5) + ASSERT_EQ(*it++, 4*i+j+1); + else if (GetParam() == 6) + ASSERT_EQ(*it++, 17+4*i+j); + } + } } -TEST(TestASMu3D, BoundaryNodesF2) -{ - std::vector vec; - getBoundaryNodes("Face2",vec); - ASSERT_EQ(vec.size(), 16U); - for (int i = 0; i < 16; ++i) - ASSERT_EQ(vec[i], 2+4*i); -} - - -TEST(TestASMu3D, BoundaryNodesF3) -{ - std::vector vec; - getBoundaryNodes("Face3",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) -{ - std::vector vec; - getBoundaryNodes("Face4",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) -{ - std::vector vec; - getBoundaryNodes("Face5",vec); - ASSERT_EQ(vec.size(), 16U); - for (int i = 0; i < 16; ++i) - ASSERT_EQ(vec[i], i+1); -} - - -TEST(TestASMu3D, BoundaryNodesF6) -{ - std::vector vec; - getBoundaryNodes("Face6",vec); - ASSERT_EQ(vec.size(), 16U); - for (int i = 0; i < 16; ++i) - ASSERT_EQ(vec[i], 17+i); -} +const std::vector tests = {1,2,3,4,5,6}; +INSTANTIATE_TEST_CASE_P(TestASMu3D, + TestASMu3D, + testing::ValuesIn(tests));