diff --git a/src/ASM/LR/ASMu2D.C b/src/ASM/LR/ASMu2D.C index 2c25aac2..72aee3e1 100644 --- a/src/ASM/LR/ASMu2D.C +++ b/src/ASM/LR/ASMu2D.C @@ -570,44 +570,44 @@ void ASMu2D::closeEdges (int dir, int basis, int master) */ -void ASMu2D::constrainEdge (int dir, bool open, int dof, int code, char) +std::vector ASMu2D::getEdgeNodes(int dir, int basis) const { - constrainEdge(dir,open,dof,code,0,lrspline.get()); + const LR::LRSplineSurface* srf = getBasis(basis); + size_t ofs = 0; + for (int i=1; i < basis; ++i) + ofs += getNoNodes(i); + + std::vector result; + if (dir > -3 && dir < 3) { + const std::vector map = {LR::SOUTH, LR::WEST, LR::WEST, /* dummy*/ LR::EAST, LR::NORTH}; + std::vector edgeFunctions; + srf->getEdgeFunctions(edgeFunctions, map[dir+2]); + + result.resize(edgeFunctions.size()); + std::transform(edgeFunctions.begin(), edgeFunctions.end(), + result.begin(), [ofs](LR::Basisfunction* a) { return a->getId()+ofs+1; }); + } + + return result; } -void ASMu2D::constrainEdge(int dir, bool open, int dof, int code, size_t ofs, - LR::LRSplineSurface* spline) +void ASMu2D::constrainEdge (int dir, bool open, int dof, int code, char basis) { - std::vector edgeFunctions; - static const std::map m = - {{ 1, LR::EAST}, - {-1, LR::WEST}, - { 2, LR::NORTH}, - {-2, LR::SOUTH}}; - LR::parameterEdge edge = m.find(dir)->second; - - Go::SplineCurve* curve = nullptr; - if (code > 0) - curve = spline->edgeCurve(edge, edgeFunctions); - else - spline->getEdgeFunctions(edgeFunctions, edge); - - if (curve) - dirich.push_back(DirichletEdge(curve,dof,code)); + std::vector nodes = getEdgeNodes(dir, basis); // Skip the first and last function if we are requesting an open boundary. // I here assume the edgeFunctions are ordered such that the physical // end points are represented by the first and last edgeFunction. if (!open) - this->prescribe(edgeFunctions.front()->getId()+1+ofs,dof,code); + this->prescribe(nodes.front(),dof,code); - for (size_t i = 1; i < edgeFunctions.size()-1; i++) - if (this->prescribe(edgeFunctions[i]->getId()+ofs+1,dof,-code) == 0 && code > 0) - dirich.back().nodes.push_back(std::make_pair(i+1,edgeFunctions[i]->getId()+ofs+1)); + for (size_t i = 1; i < nodes.size()-1; i++) + if (this->prescribe(nodes[i],dof,-code) == 0 && code > 0) + dirich.back().nodes.push_back(std::make_pair(i,nodes[i])); if (!open) - this->prescribe(edgeFunctions.back()->getId()+ofs+1,dof,code); + this->prescribe(nodes.back(),dof,code); if (code > 0) if (dirich.back().nodes.empty()) @@ -634,34 +634,48 @@ size_t ASMu2D::constrainEdgeLocal (int dir, bool open, int dof, int code, } -void ASMu2D::constrainCorner (int I, int J, int dof, int code, char) +int ASMu2D::getCorner(int I, int J, int basis) const { std::vector edgeFunctions; + const LR::LRSplineSurface* srf = getBasis(basis); + // Note: Corners are identified by "coordinates" {-1,-1} {-1,1} {1,-1} {1,1}. if (I < 0) { if (J < 0) - lrspline->getEdgeFunctions(edgeFunctions, LR::SOUTH_WEST); + srf->getEdgeFunctions(edgeFunctions, LR::SOUTH_WEST); else if (J > 0) - lrspline->getEdgeFunctions(edgeFunctions, LR::NORTH_WEST); + srf->getEdgeFunctions(edgeFunctions, LR::NORTH_WEST); } else if (I > 0) { if (J < 0) - lrspline->getEdgeFunctions(edgeFunctions, LR::SOUTH_EAST); + srf->getEdgeFunctions(edgeFunctions, LR::SOUTH_EAST); else if (J > 0) - lrspline->getEdgeFunctions(edgeFunctions, LR::NORTH_EAST); + srf->getEdgeFunctions(edgeFunctions, LR::NORTH_EAST); } - if (edgeFunctions.empty()) + if (edgeFunctions.empty()) { std::cerr <<" *** ASMu2D::constrainCorner: Invalid corner I,J=" << I <<","<< J << std::endl; - else - this->prescribe(edgeFunctions.front()->getId()+1,dof,code); + return 0; + } if (edgeFunctions.size() > 1) std::cerr <<" ** ASMu2D::constrainCorner: "<< edgeFunctions.size() <<" corners returned from LRSplineSurface::getEdgeFunctions()" << std::endl; + + return edgeFunctions.front()->getId()+1; +} + + +void ASMu2D::constrainCorner (int I, int J, int dof, int code, char) +{ + int corner = getCorner(I, J, 1); + if (corner == 0) + return; + else + this->prescribe(corner,dof,code); } @@ -1745,3 +1759,9 @@ bool ASMu2D::updateDirichlet (const std::map& func, // evaluation of the Dirichlet functions (since they are interpolatory) return this->ASMbase::updateDirichlet(func,vfunc,time,g2l); } + + +size_t ASMu2D::getNoNodes (int) const +{ + return lrspline->nBasisFunctions(); +} diff --git a/src/ASM/LR/ASMu2D.h b/src/ASM/LR/ASMu2D.h index 2482a41e..f9a51c37 100644 --- a/src/ASM/LR/ASMu2D.h +++ b/src/ASM/LR/ASMu2D.h @@ -48,6 +48,11 @@ public: //! \brief Returns the spline surface representing this patch. LR::LRSplineSurface* getSurface() { return lrspline.get(); } + //! \brief Returns the spline surface representing the basis of this patch. + virtual const LR::LRSplineSurface* getBasis(int = 1) const { return lrspline.get(); } + + //! \brief Returns the spline surface representing the basis of this patch. + virtual LR::LRSplineSurface* getBasis(int = 1) { return lrspline.get(); } // Methods for model generation and refinement // =========================================== @@ -97,6 +102,9 @@ public: //! \param[out] p3 Order in third (w) direction virtual bool getOrder(int& p1, int& p2, int& p3) const; + //! \brief Returns the total number of nodes in this patch. + virtual size_t getNoNodes(int basis = 0) const; + //! \brief Checks that the patch is modelled in a right-hand-side system. virtual bool checkRightHandSystem(); @@ -221,6 +229,13 @@ public: virtual bool updateDirichlet(const std::map& func, const std::map& vfunc, double time, const std::map* g2l = nullptr); + + //! \brief Obtain node index for a given corner. + int getCorner(int I, int J, int basis=1) const; + + //! \brief Obtain node indices for a given edge + std::vector getEdgeNodes(int dir, int basis=1) const; + protected: //! \brief Evaluates an integral over the interior patch domain. //! \param integrand Object with problem-specific data and methods @@ -406,16 +421,6 @@ protected: : curve(sc), dof(d), code(c) {} }; - //! \brief Constrains all DOFs on a given boundary edge. - //! \param[in] dir Parameter direction defining the edge to constrain - //! \param[in] open If \e true, exclude the end points of the edge - //! \param[in] dof Which DOFs to constrain at each node on the edge - //! \param[in] code Inhomogeneous dirichlet condition code - //! \param[in] ofs Offset for nodes (multiple bases). - //! \param[in] spline LRSpline to use for node numbers. - virtual void constrainEdge(int dir, bool open, int dof, int code, - size_t ofs, LR::LRSplineSurface* spline); - std::shared_ptr lrspline; //!< Pointer to the LR-spline surface object std::vector bezierExtract; //!< Bezier extraction matrices diff --git a/src/ASM/LR/ASMu2Dmx.C b/src/ASM/LR/ASMu2Dmx.C index b3e50881..e52497f1 100644 --- a/src/ASM/LR/ASMu2Dmx.C +++ b/src/ASM/LR/ASMu2Dmx.C @@ -53,7 +53,16 @@ ASMu2Dmx::ASMu2Dmx (const ASMu2Dmx& patch, } -LR::LRSplineSurface* ASMu2Dmx::getBasis (int basis) const +const LR::LRSplineSurface* ASMu2Dmx::getBasis (int basis) const +{ + if (basis < 1 || basis > (int)m_basis.size()) + return nullptr; + + return m_basis[basis-1].get(); +} + + +LR::LRSplineSurface* ASMu2Dmx::getBasis (int basis) { if (basis < 1 || basis > (int)m_basis.size()) return nullptr; @@ -554,27 +563,6 @@ bool ASMu2Dmx::evalSolution (Matrix& sField, const IntegrandBase& integrand, } -void ASMu2Dmx::constrainEdge (int dir, bool open, int dof, int code, char basis) -{ - size_t ofs = std::accumulate(nb.begin(),nb.begin()+basis-1, 0); - ASMu2D::constrainEdge(dir,open,dof,code,ofs,m_basis[basis-1].get()); -} - - -Vec3 ASMu2Dmx::getCoord (size_t inod) const -{ - int node = inod, i = 0; - while (node > m_basis[i]->nBasisFunctions()) - node -= m_basis[i++]->nBasisFunctions(); - - LR::Basisfunction* basis = m_basis[i]->getBasisfunction(node-1); - if (!basis) - return Vec3(); - - return Vec3(&(*basis->cp()),nsd); -} - - //! \brief Expand the basis coefficients of a spline surface. //! \details Used for solution transfer during refinement. //! \param[in] basis The surface to extend diff --git a/src/ASM/LR/ASMu2Dmx.h b/src/ASM/LR/ASMu2Dmx.h index 0574d8e8..43055e49 100644 --- a/src/ASM/LR/ASMu2Dmx.h +++ b/src/ASM/LR/ASMu2Dmx.h @@ -39,7 +39,10 @@ public: virtual ~ASMu2Dmx() { lrspline = nullptr; geo = nullptr; } //! \brief Returns the spline surface representing the basis of this patch. - virtual LR::LRSplineSurface* getBasis(int basis = 1) const; + virtual LR::LRSplineSurface* getBasis(int basis = 1); + + //! \brief Returns the spline surface representing the basis of this patch. + virtual const LR::LRSplineSurface* getBasis(int basis = 1) const; // Methods for model generation // ============================ @@ -69,17 +72,6 @@ public: //! \brief Returns the classification of a node. //! \param[in] inod 1-based node index local to current patch virtual char getNodeType(size_t inod) const; - //! \brief Returns the global coordinates for the given node. - //! \param[in] inod 1-based node index local to current patch - virtual Vec3 getCoord(size_t inod) const; - - //! \brief Constrains all DOFs on a given boundary edge. - //! \param[in] dir Parameter direction defining the edge to constrain - //! \param[in] open If \e true, exclude the end points of the edge - //! \param[in] dof Which DOFs to constrain at each node on the edge - //! \param[in] code Inhomogeneous dirichlet condition code - //! \param[in] basis Which basis to constrain the edge for - virtual void constrainEdge(int dir, bool open, int dof, int code, char basis); //! \brief Initializes the patch level MADOF array for mixed problems. virtual void initMADOF(const int* sysMadof);