Changed: Simplified the boundary nodes extraction a bit.

Always use getBoundaryNodes method and made getEdgeNodes private.
Think there were some small undetected errors also
(local vs. global node numbers).
This commit is contained in:
Knut Morten Okstad
2017-10-05 17:01:18 +02:00
parent 592b725e24
commit 3c9529c072
5 changed files with 203 additions and 240 deletions

View File

@@ -21,193 +21,178 @@
#endif
//! \brief Helper for applying operation to different ASM types
//! \brief Base class for helpers applying nodal constraints.
class NodalConstraintASMHelper {
public:
//! \brief Constructor
//! \param pch The associated ASM class
//! \brief The constructor initializes the patch pointer.
explicit NodalConstraintASMHelper(ASMbase* pch) : bpch(pch) {}
//! \brief Empty destructor
//! \brief Empty destructor.
virtual ~NodalConstraintASMHelper() {}
//! \brief Obtain the global node number of a given corner node on patch.
//! \param vertex Vertex to obtain
//! \param basis Basis for vertex
virtual int getCorner(int vertex, int basis) = 0;
//! \brief Returns the local node number of a given corner of the patch.
//! \param[in] vertex Vertex index to return the node number for
//! \param[in] basis Basis for vertex
virtual int getCorner(int vertex, int basis) const = 0;
//! \brief Constrain a given edge to a given node.
//! \param item Edge index on patch
//! \param comp Component to constrain
//! \param basis Basis to constrain edge for
//! \param idx Global node to constrain edge to.
virtual void constrainEdge(int item, int comp, int basis, int idx) = 0;
//! \brief Constrains a given edge to a given node.
//! \param[in] item Edge index on patch
//! \param[in] comp Component to constrain
//! \param[in] basis Basis to constrain edge for
//! \param[in] idx Global node to constrain edge to
virtual void constrainEdge(int item, int comp, int basis, int idx) {}
//! \brief Constrain a given vertex to a given node.
//! \param item item Vertex index on patch.
//! \param comp Component to constrain
//! \param basis Basis to constrain vertex for.
//! \param idx Global node to constrain edge to.
//! \brief Constrains a given face to a given node.
//! \param[in] item Face index on patch
//! \param[in] comp Component to constrain
//! \param[in] basis Basis to constrain face for
//! \param[in] idx Global node to constrain face to
virtual void constrainFace(int item, int comp, int basis, int idx) {}
//! \brief Constrains a given vertex to a given node.
//! \param[in] item Vertex index on patch
//! \param[in] comp Component to constrain
//! \param[in] basis Basis to constrain vertex for
//! \param[in] idx Global node to constrain edge to
void constrainVertex(int item, int comp, int basis, int idx)
{
int gn = bpch->getNodeID(getCorner(item, basis));
if (gn != idx)
bpch->add2PC(gn, comp, idx);
this->constrainNode(this->getCorner(item,basis),comp,idx);
}
//! \brief Constrain the patch to a given node.
//! \brief Constrains the whole patch to a given node.
//! \param[in] comp Component to constrain
//! \param[in] basis Basis to constrain vertex for.
//! \param[in] idx Global node to constrain patch to.
//! \param[in] basis Basis to constrain patch for
//! \param[in] idx Global node to constrain patch to
void constrainPatch(int comp, int basis, int idx)
{
size_t ofs = getStartNode(basis);
for (size_t i = 1; i <= bpch->getNoNodes(basis); ++i) {
int gn = bpch->getNodeID(ofs+i);
if (gn != idx)
bpch->add2PC(bpch->getNodeID(ofs+i), comp, idx);
}
int nnod = bpch->getNoNodes(basis);
int node = this->getStartNode(basis);
for (int i = 0; i < nnod; i++)
this->constrainNode(++node,comp,idx);
}
//! \brief Obtain the starting node for a given basis.
//! \param[in] basis Basis to obtain the starting node for
size_t getStartNode(size_t basis)
protected:
//! \brief Constrains a given node to another node.
//! \param[in] item Local index of node to constrain
//! \param[in] comp Component to constrain
//! \param[in] idx Global index of the node to constrain to
void constrainNode(int item, int comp, int idx)
{
size_t ofs = 0;
for (size_t i=1;i<basis;++i)
ofs += bpch->getNoNodes(i);
int node = bpch->getNodeID(item);
if (node != idx)
bpch->add2PC(node,comp,idx);
}
//! \brief Returns the starting node for the given \a basis.
int getStartNode(int basis) const
{
int ofs = 0;
for (int i = 1; i < basis; i++)
ofs += bpch->getNoNodes(i);
return ofs;
}
protected:
ASMbase* bpch; //!< ASMbase pointer to associated patch
ASMbase* bpch; //!< Pointer to the associated patch
};
//! \brief Helper for apply constraints to a structured 1D model.
class NodalConstraintASMs1DHelper : public NodalConstraintASMHelper {
public:
//! \brief Constructor
//! \param spch The associated ASM class
explicit NodalConstraintASMs1DHelper(ASMs1D* spch) :
NodalConstraintASMHelper(spch), pch(spch) {}
//! \brief The constructor forwards to the parent class constructor.
explicit NodalConstraintASMs1DHelper(ASMs1D* pch)
: NodalConstraintASMHelper(pch) {}
//! \brief Obtain the global node number of a given corner node on patch.
//! \param vertex Vertex to obtain
//! \param basis Basis for vertex
int getCorner(int vertex, int basis)
//! \copydoc NodalConstraintASMHelper::getCorner
virtual int getCorner(int vertex, int basis) const
{
size_t ofs = getStartNode(basis);
return pch->getNodeID(ofs+(vertex==1?1:pch->getSize(basis)));
int n1 = static_cast<ASMs1D*>(bpch)->getSize(basis);
int ofs = this->getStartNode(basis);
return bpch->getNodeID(ofs + (vertex == 1 ? 1 : n1));
}
//! \brief Constrain a given edge to a given node.
//! \param item Edge index on patch
//! \param comp Component to constrain
//! \param basis Basis to constrain edge for
//! \param idx Global node to constrain edge to.
void constrainEdge(int item, int comp, int basis, int idx) {}
protected:
ASMs1D* pch; //!< The associated patch.
};
//! \brief Helper for apply constraints to a structured 2D model.
class NodalConstraintASMs2DHelper : public NodalConstraintASMHelper {
public:
//! \brief Constructor
//! \param spch The associated ASM class
explicit NodalConstraintASMs2DHelper(ASMs2D* spch) :
NodalConstraintASMHelper(spch), pch(spch) {}
//! \brief The constructor forwards to the parent class constructor.
explicit NodalConstraintASMs2DHelper(ASMs2D* pch)
: NodalConstraintASMHelper(pch) {}
//! \copydoc NodalConstraintASMHelper::getCorner
int getCorner(int vertex, int basis)
virtual int getCorner(int vertex, int basis) const
{
int n1, n2;
pch->getSize(n1, n2, basis);
size_t ofs = getStartNode(basis);
const std::vector<int> idxs = {1, n1, n1*(n2-1)+1, n1*n2};
return pch->getNodeID(idxs[vertex-1]+ofs);
int n1, n2, ofs = this->getStartNode(basis);
static_cast<ASMs2D*>(bpch)->getSize(n1,n2,basis);
const IntVec idxs = { 1, n1, n1*(n2-1)+1, n1*n2 };
return bpch->getNodeID(idxs[vertex-1]+ofs);
}
//! \copydoc NodalConstraintASMHelper::constrainEdge
void constrainEdge(int item, int comp, int basis, int idx)
virtual void constrainEdge(int item, int comp, int basis, int idx)
{
size_t ofs = getStartNode(basis);
int n1, n2, node = 1;
pch->getSize(n1,n2,basis);
int n1, n2, node = 1 + this->getStartNode(basis);
static_cast<ASMs2D*>(bpch)->getSize(n1,n2,basis);
switch (item) {
case 2: // Right edge (positive I-direction)
node += n1-1;
case 1: // Left edge (negative I-direction)
for (int i2 = 1; i2 <= n2; i2++, node += n1) {
int gn = pch->getNodeID(ofs+node);
if (gn != idx)
pch->add2PC(pch->getNodeID(ofs+node), comp, idx);
}
for (int i2 = 1; i2 <= n2; i2++, node += n1)
this->constrainNode(node,comp,idx);
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++) {
int gn = pch->getNodeID(ofs+node);
if (gn != idx)
pch->add2PC(gn, comp, idx);
}
for (int i1 = 1; i1 <= n1; i1++, node++)
this->constrainNode(node,comp,idx);
default:
break;
}
}
protected:
ASMs2D* pch; //!< The associated patch.
};
//! \brief Helper for apply constraints to a structured 3D model.
class NodalConstraintASMs3DHelper : public NodalConstraintASMHelper {
public:
//! \brief Constructor
//! \param spch The associated patch
explicit NodalConstraintASMs3DHelper(ASMs3D* spch) :
NodalConstraintASMHelper(spch), pch(spch) {}
//! \brief The constructor forwards to the parent class constructor.
explicit NodalConstraintASMs3DHelper(ASMs3D* pch)
: NodalConstraintASMHelper(pch) {}
//! \copydoc NodalConstraintASMHelper::getCorner
int getCorner(int vertex, int basis)
virtual int getCorner(int vertex, int basis) const
{
size_t ofs = getStartNode(basis);
int n1, n2, n3;
pch->getSize(n1, n2, n3, basis);
int n1, n2, n3, ofs = this->getStartNode(basis);
static_cast<ASMs3D*>(bpch)->getSize(n1,n2,n3,basis);
int ofs_j = n1*(n2-1);
int ofs_k = n1*n2*(n3-1);
const std::vector<int> idxs = { 1, n1,
ofs_j+1, ofs_j+n1,
ofs_k+1, ofs_k+n1,
ofs_k+ofs_j+1, ofs_k+ofs_j+n1};
return pch->getNodeID(idxs[vertex-1]+ofs);
const IntVec idxs = { 1, n1,
ofs_j+1, ofs_j+n1,
ofs_k+1, ofs_k+n1,
ofs_k+ofs_j+1, ofs_k+ofs_j+n1};
return bpch->getNodeID(idxs[vertex-1]+ofs);
}
//! \copydoc NodalConstraintASMHelper::constrainEdge
void constrainEdge(int item, int comp, int basis, int idx)
virtual void constrainEdge(int item, int comp, int basis, int idx)
{
size_t node = getStartNode(basis)+1;
int n1, n2, n3, node = 1 + this->getStartNode(basis);
static_cast<ASMs3D*>(bpch)->getSize(n1,n2,n3,basis);
int n1, n2, n3;
pch->getSize(n1,n2,n3,basis);
size_t inc = 1;
int n;
int inc = 1;
int n = n1;
if (item > 8) {
inc = n1*n2;
n = n3;
} else if (item > 4) {
inc = n1;
n = n2;
} else
n = n1;
}
switch (item)
{
@@ -234,23 +219,15 @@ public:
break;
}
for (int i = 1; i <= n; i++, node += inc) {
int gn = pch->getNodeID(node);
if (gn != idx)
pch->add2PC(gn, comp, idx);
}
for (int i = 1; i <= n; i++, node += inc)
this->constrainNode(node,comp,idx);
}
//! \brief Constrain a given face to a given node.
//! \param item Face index on patch
//! \param comp Component to constrain
//! \param basis Basis to constrain edge for
//! \param idx Global node to constrain edge to.
void constrainFace(int item, int comp, int basis, int idx)
//! \copydoc NodalConstraintASMHelper::constrainFace
virtual void constrainFace(int item, int comp, int basis, int idx)
{
int node = getStartNode(basis)+1;
int n1, n2, n3;
pch->getSize(n1,n2,n3,basis);
int n1, n2, n3, node = 1 + this->getStartNode(basis);
static_cast<ASMs3D*>(bpch)->getSize(n1,n2,n3,basis);
const std::vector<int> faceDir = {-1, 1, -2, 2, -3, 3};
switch (faceDir[item-1])
@@ -259,93 +236,60 @@ public:
node += n1-1;
case -1: // Left face (negative I-direction)
for (int i3 = 1; i3 <= n3; i3++)
for (int i2 = 1; i2 <= n2; i2++, node += n1) {
int gn = pch->getNodeID(node);
if (gn != idx)
pch->add2PC(gn, comp, idx);
}
for (int i2 = 1; i2 <= n2; i2++, node += n1)
this->constrainNode(node,comp,idx);
break;
case 2: // Back face (positive J-direction)
node += n1*(n2-1);
case -2: // Front face (negative J-direction)
for (int i3 = 1; i3 <= n3; i3++, node += n1*(n2-1))
for (int i1 = 1; i1 <= n1; i1++, node++) {
int gn = pch->getNodeID(node);
if (gn != idx)
pch->add2PC(gn, comp, idx);
}
for (int i1 = 1; i1 <= n1; i1++, node++)
this->constrainNode(node,comp,idx);
break;
case 3: // Top face (positive K-direction)
node += n1*n2*(n3-1);
case -3: // Bottom face (negative K-direction)
for (int i2 = 1; i2 <= n2; i2++)
for (int i1 = 1; i1 <= n1; i1++, node++) {
int gn = pch->getNodeID(node);
if (gn != idx)
pch->add2PC(gn, comp, idx);
}
for (int i1 = 1; i1 <= n1; i1++, node++)
this->constrainNode(node,comp,idx);
break;
}
}
protected:
ASMs3D* pch; //!< The associated patch.
};
#ifdef HAS_LRSPLINE
//! \brief Helper for apply constraints to an unstructured 2D model.
class NodalConstraintASMu2DHelper : public NodalConstraintASMHelper {
public:
//! \brief Constructor
//! \param upch Associated patch
explicit NodalConstraintASMu2DHelper(ASMu2D* upch) :
NodalConstraintASMHelper(upch), pch(upch) {}
explicit NodalConstraintASMu2DHelper(ASMu2D* pch)
: NodalConstraintASMHelper(pch) {}
//! \copydoc NodalConstraintASM2DHelper::getCorner
int getCorner(int vertex, int basis)
//! \copydoc NodalConstraintASMHelper::getCorner
virtual int getCorner(int vertex, int basis) const
{
static const int indices[4][2] = {{-1,-1}, {1, -1}, {-1, 1}, {1,1}};
return pch->getCorner(indices[vertex-1][0], indices[vertex-1][1], basis);
static const int indices[4][2] = {{-1,-1}, {1,-1}, {-1,1}, {1,1}};
return static_cast<ASMu2D*>(bpch)->getCorner(indices[vertex-1][0],
indices[vertex-1][1],
basis);
}
//! \copydoc NodalConstraintASM2DHelper::constrainEdge
void constrainEdge(int item, int comp, int basis, int idx)
//! \copydoc NodalConstraintASMHelper::constrainEdge
virtual void constrainEdge(int item, int comp, int basis, int idx)
{
std::vector<int> map = { LR::WEST, LR::EAST, LR::SOUTH, LR::NORTH };
std::vector<int> nodes = pch->getEdgeNodes(map[item-1], basis, 0);
for (auto& it : nodes) {
int gn = pch->getNodeID(it);
if (gn != idx)
pch->add2PC(gn, comp, idx);
}
IntVec nodes;
bpch->getBoundaryNodes(item,nodes,basis,1,0,true);
for (int node : nodes)
this->constrainNode(node,comp,idx);
}
protected:
ASMu2D* pch; //!< The associated patch.
};
#endif
/*!
\brief Helper function to create a NodalConstraintASMHelper instance.
*/
static NodalConstraintASMHelper* get2DHelper(ASMbase* pch)
{
ASMs2D* spch = dynamic_cast<ASMs2D*>(pch);
if (spch)
return new NodalConstraintASMs2DHelper(spch);
#ifdef HAS_LRSPLINE
ASMu2D* upch = dynamic_cast<ASMu2D*>(pch);
if (upch)
return new NodalConstraintASMu2DHelper(upch);
#endif
return nullptr;
}
//! \brief Template specialization for 1D.
template<> bool SIMNodalConstraint<SIM1D>::applyConstraint()
{
@@ -376,13 +320,26 @@ template<> bool SIMNodalConstraint<SIM1D>::applyConstraint()
//! \brief Template specialization for 2D.
template<> bool SIMNodalConstraint<SIM2D>::applyConstraint()
{
// Lambda function to create the right NodalConstraintASMHelper instance
auto&& getHelper = [this](int pidx) -> NodalConstraintASMHelper*
{
ASMbase* pch = this->getPatch(pidx);
ASMs2D* spch = dynamic_cast<ASMs2D*>(pch);
if (spch) return new NodalConstraintASMs2DHelper(spch);
#ifdef HAS_LRSPLINE
ASMu2D* upch = dynamic_cast<ASMu2D*>(pch);
if (upch) return new NodalConstraintASMu2DHelper(upch);
#endif
return nullptr;
};
for (const auto& it3 : vertConstraints) {
TopologySet::const_iterator it = SIM2D::myEntitys.find(it3.topset);
if (it != SIM2D::myEntitys.end()) {
std::unique_ptr<NodalConstraintASMHelper> helper(get2DHelper(this->getPatch(it3.patch)));
std::unique_ptr<NodalConstraintASMHelper> helper(getHelper(it3.patch));
int idx = helper->getCorner(it3.vertex, it3.basis);
for (const auto& it2 : it->second) {
std::unique_ptr<NodalConstraintASMHelper> helper2(get2DHelper(this->getPatch(it2.patch)));
std::unique_ptr<NodalConstraintASMHelper> helper2(getHelper(it2.patch));
if (it2.idim == 2)
helper2->constrainPatch(it3.comp, it3.basis, idx);
else if (it2.idim == 1) // Edge constraints

View File

@@ -202,9 +202,8 @@ TEST_P(TestSIMNodalConstraint, Edge2DLR)
s.preprocess();
const ASMu2D& pch = static_cast<const ASMu2D&>(*s.getPatch(1));
static const std::vector<LR::parameterEdge> E
{LR::WEST, LR::EAST, LR::SOUTH, LR::NORTH};
auto nodes = pch.getEdgeNodes(E[GetParam()-1], 1, 0);
IntVec nodes;
pch.getBoundaryNodes(GetParam(),nodes,1);
for (size_t i=1; i <= pch.getNoNodes(); ++i) {
if (std::find(nodes.begin(), nodes.end(), i) != nodes.end() &&
i != (size_t)pch.getCorner(1,-1,1) && GetParam() == 1)
@@ -235,9 +234,8 @@ TEST_P(TestSIMNodalConstraint, Edge2DLRmx)
s.preprocess();
const ASMu2D& pch = static_cast<const ASMu2D&>(*s.getPatch(1));
static const std::vector<LR::parameterEdge> E
{LR::WEST, LR::EAST, LR::SOUTH, LR::NORTH};
auto nodes = pch.getEdgeNodes(E[GetParam()-1], 2, 0);
IntVec nodes;
pch.getBoundaryNodes(GetParam(),nodes,2);
size_t ofs = pch.getNoNodes(1);
for (size_t i=1; i <= pch.getNoNodes(1); ++i) {
ASSERT_TRUE(pch.findMPC(i, 1) == nullptr);

View File

@@ -684,27 +684,6 @@ bool ASMu2D::connectBasis (int edge, ASMu2D& neighbor, int nedge, bool revers,
}
IntVec ASMu2D::getEdgeNodes (int edge, int basis, int orient) const
{
size_t ofs = 1;
for (int i = 1; i < basis; i++)
ofs += this->getNoNodes(i);
std::vector<LR::Basisfunction*> edgeFunctions;
this->getBasis(basis)->getEdgeFunctions(edgeFunctions,
static_cast<LR::parameterEdge>(edge));
int v = (edge == 1 || edge == 2) ? 0 : 1;
int u = 1-v;
ASMLRSpline::Sort(u, v, orient, edgeFunctions);
IntVec result(edgeFunctions.size());
std::transform(edgeFunctions.begin(), edgeFunctions.end(), result.begin(),
[ofs](LR::Basisfunction* a) { return a->getId()+ofs; });
return result;
}
ASMu2D::DirichletEdge::DirichletEdge (LR::LRSplineSurface* sf,
int dir, int d, int c, int offset)
: lr(sf), edg(LR::NONE), dof(d), code(c)
@@ -2127,30 +2106,42 @@ bool ASMu2D::evalSolution (Matrix& sField, const IntegrandBase& integrand,
}
void ASMu2D::getEdgeNodes (IntVec& nodes, int edge, int basis,
int orient, bool local) const
{
const LR::LRSplineSurface* srf = this->getBasis(basis);
if (!srf) return; // silently ignore empty patches
size_t ofs = 1;
for (int i = 1; i < basis; i++)
ofs += this->getNoNodes(i);
std::vector<LR::Basisfunction*> edgeFunctions;
srf->getEdgeFunctions(edgeFunctions,static_cast<LR::parameterEdge>(edge));
if (orient >= 0) {
int u = (edge == 1 || edge == 2) ? 1 : 0;
ASMLRSpline::Sort(u, 1-u, orient, edgeFunctions);
}
for (LR::Basisfunction* b : edgeFunctions)
nodes.push_back(local ? b->getId()+ofs : this->getNodeID(b->getId()+ofs));
}
void ASMu2D::getBoundaryNodes (int lIndex, IntVec& nodes, int basis,
int, int orient, bool local) const
{
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 1: this->getEdgeNodes(nodes,LR::WEST ,basis,orient,local); break;
case 2: this->getEdgeNodes(nodes,LR::EAST ,basis,orient,local); break;
case 3: this->getEdgeNodes(nodes,LR::SOUTH,basis,orient,local); break;
case 4: this->getEdgeNodes(nodes,LR::NORTH,basis,orient,local); break;
default: return;
}
if (nodes.empty())
nodes = this->getEdgeNodes(edge, basis, 0);
else {
IntVec nodes2 = this->getEdgeNodes(edge, basis, 0);
nodes.insert(nodes.end(), nodes2.begin(), nodes2.end());
}
#if SP_DEBUG > 1
std::cout <<"Boundary nodes in patch "<< idx+1 <<" edge "<< lIndex <<":";
for (int n : nodes) std::cout <<" "<< n;

View File

@@ -136,8 +136,8 @@ public:
//! \param[in] basis Which basis to grab nodes for (0 for all)
//! \param[in] orient Orientation of boundary (used for sorting)
//! \param[in] local If \e true, return patch-local node numbers
virtual void getBoundaryNodes(int lIndex, IntVec& nodes, int basis,
int, int orient, bool local = false) const;
virtual void getBoundaryNodes(int lIndex, IntVec& nodes, int basis, int = 1,
int orient = 0, bool local = false) const;
//! \brief Returns the polynomial order in each parameter direction.
//! \param[out] p1 Order in first (u) direction
@@ -310,9 +310,6 @@ public:
//! \param[in] basis which basis to consider (for mixed methods)
virtual int getCorner(int I, int J, int basis) const;
//! \brief Returns the node indices for a given edge.
IntVec getEdgeNodes(int edge, int basis, int orient) const;
protected:
//! \brief Evaluates an integral over the interior patch domain.
//! \param integrand Object with problem-specific data and methods
@@ -553,6 +550,15 @@ protected:
//! \return Characteristic element size
double getElementCorners(int iel, std::vector<Vec3>& XC) const;
//! \brief Returns the node indices for a given edge.
//! \param nodes Array of node numbers
//! \param[in] edge Local index of the boundary edge
//! \param[in] basis Which basis to grab nodes for
//! \param[in] orient Orientation of boundary (used for sorting)
//! \param[in] local If \e true, return patch-local node numbers
void getEdgeNodes(IntVec& nodes, int edge, int basis,
int orient, bool local) const;
//! \brief Evaluates the basis functions and derivatives of an element.
//! \param[in] iel 0-based element index
//! \param fe Integration point data for current element

View File

@@ -34,44 +34,55 @@ class TestASMu2D : public testing::Test,
};
static ASMu2D* getPatch (SIMinput& sim)
class TestSIM2D : public SIM2D
{
sim.opt.discretization = ASM::LRSpline;
EXPECT_TRUE(sim.read("src/ASM/LR/Test/refdata/boundary_nodes.xinp"));
EXPECT_TRUE(sim.createFEMmodel());
return static_cast<ASMu2D*>(sim.getPatch(1));
}
public:
TestSIM2D() : SIM2D(1)
{
opt.discretization = ASM::LRSpline;
EXPECT_TRUE(this->read("src/ASM/LR/Test/refdata/boundary_nodes.xinp"));
EXPECT_TRUE(this->createFEMmodel());
}
virtual ~TestSIM2D() {}
};
TEST_P(TestASMu2D, ConstrainEdge)
{
SIM2D sim(1);
ASMu2D* pch = getPatch(sim);
TestSIM2D sim;
ASMu2D* pch = static_cast<ASMu2D*>(sim.getPatch(1));
ASSERT_TRUE(pch != nullptr);
pch->constrainEdge(GetParam().edgeIdx, false, 1, 1, 1);
std::vector<int> glbNodes;
pch->getBoundaryNodes(GetParam().edge, glbNodes, 1, 1, 0);
for (int& it : glbNodes)
ASSERT_TRUE(pch->findMPC(it, 1) != nullptr);
pch->getBoundaryNodes(GetParam().edge, glbNodes, 1);
for (int node : glbNodes)
EXPECT_TRUE(pch->findMPC(node,1) != nullptr);
}
TEST_P(TestASMu2D, ConstrainEdgeOpen)
{
SIM2D sim(1);
ASMu2D* pch = getPatch(sim);
TestSIM2D sim;
ASMu2D* pch = static_cast<ASMu2D*>(sim.getPatch(1));
ASSERT_TRUE(pch != nullptr);
pch->constrainEdge(GetParam().edgeIdx, true, 1, 1, 1);
std::vector<int> glbNodes;
pch->getBoundaryNodes(GetParam().edge, glbNodes, 1, 1, 0);
pch->getBoundaryNodes(GetParam().edge, glbNodes, 1);
int crn = pch->getCorner(GetParam().c1[0], GetParam().c1[1], 1);
ASSERT_TRUE(pch->findMPC(crn, 1) == nullptr);
EXPECT_TRUE(pch->findMPC(crn,1) == nullptr);
glbNodes.erase(std::find(glbNodes.begin(), glbNodes.end(), crn));
crn = pch->getCorner(GetParam().c2[0], GetParam().c2[1], 1);
ASSERT_TRUE(pch->findMPC(crn, 1) == nullptr);
EXPECT_TRUE(pch->findMPC(crn,1) == nullptr);
glbNodes.erase(std::find(glbNodes.begin(), glbNodes.end(), crn));
for (int& it : glbNodes)
ASSERT_TRUE(pch->findMPC(it, 1) != nullptr);
for (int node : glbNodes)
EXPECT_TRUE(pch->findMPC(node,1) != nullptr);
}