diff --git a/src/SIM/SIM2D.C b/src/SIM/SIM2D.C index baa1fe33..ca05d49f 100644 --- a/src/SIM/SIM2D.C +++ b/src/SIM/SIM2D.C @@ -68,6 +68,45 @@ SIM2D::SIM2D (IntegrandBase* itg, unsigned char n, bool check) : SIMgeneric(itg) } +bool SIM2D::addConnection (int master, int slave, int mIdx, + int sIdx, int orient, int basis, bool coordCheck) +{ + if (orient < 0 || orient > 1) { + std::cerr <<" *** SIM2D::addConnection: Invalid orientation "<< orient <<"." + << std::endl; + return false; + } + + int lmaster = this->getLocalPatchIndex(master); + int lslave = this->getLocalPatchIndex(slave); + + if (lmaster > 0 && lslave > 0) + { + IFEM::cout <<"\tConnecting P"<< slave <<" E"<< sIdx + <<" to P"<< master <<" E"<< mIdx + <<" reversed? "<< orient << std::endl; + + ASMs2D* spch = static_cast(myModel[lslave-1]); + ASMs2D* mpch = static_cast(myModel[lmaster-1]); + + std::set bases; + if (basis == 0) + for (size_t b = 1; b <= spch->getNoBasis(); ++b) + bases.insert(b); + else + bases = utl::getDigits(basis); + + for (const int& b : bases) + if (!spch->connectPatch(sIdx,*mpch,mIdx,orient,b,coordCheck)) + return false; + } + else + adm.dd.ghostConnections.insert(DomainDecomposition::Interface{master, slave, mIdx, sIdx, orient, 1}); + + return true; +} + + bool SIM2D::parseGeometryTag (const TiXmlElement* elem) { IFEM::cout <<" Parsing <"<< elem->Value() <<">"<< std::endl; @@ -157,13 +196,19 @@ bool SIM2D::parseGeometryTag (const TiXmlElement* elem) const TiXmlElement* child = elem->FirstChildElement("connection"); for (; child; child = child->NextSiblingElement()) { - int master = 0, slave = 0, mEdge = 0, sEdge = 0; - bool rever = false; + int master = 0, slave = 0, mEdge = 0, sEdge = 0, orient = 0, basis = 0; + bool rever = false, periodic = false; utl::getAttribute(child,"master",master); - utl::getAttribute(child,"medge",mEdge); + if (!utl::getAttribute(child,"midx",mEdge)) + utl::getAttribute(child,"medge",mEdge); utl::getAttribute(child,"slave",slave); - utl::getAttribute(child,"sedge",sEdge); - utl::getAttribute(child,"reverse",rever); + if (!utl::getAttribute(child,"sidx",sEdge)) + utl::getAttribute(child,"sedge",sEdge); + if (!utl::getAttribute(child,"orient",orient)) + if (utl::getAttribute(child,"reverse",rever) && rever) + orient = 1; + utl::getAttribute(child,"basis",basis); + utl::getAttribute(child,"periodic",periodic); if (master == slave || master < 1 || master > nGlPatches || @@ -173,24 +218,17 @@ bool SIM2D::parseGeometryTag (const TiXmlElement* elem) << master <<" "<< slave << std::endl; return false; } - int lmaster = this->getLocalPatchIndex(master); - int lslave = this->getLocalPatchIndex(slave); - if (lmaster > 0 && lslave > 0) + if (!this->addConnection(master,slave,mEdge,sEdge,orient,basis,!periodic)) { - IFEM::cout <<"\tConnecting P"<< lslave <<" E"<< sEdge - <<" to P"<< lmaster <<" E"<< mEdge - <<" reversed? "<< rever << std::endl; - ASMs2D* spch = static_cast(myModel[lslave-1]); - ASMs2D* mpch = static_cast(myModel[lmaster-1]); - if (!spch->connectPatch(sEdge,*mpch,mEdge,rever)) - return false; - else if (opt.discretization == ASM::SplineC1) - top.push_back(Interface(static_cast(mpch),mEdge, - static_cast(spch),sEdge,rever)); + std::cerr <<" *** SIM2D::parse: Error establishing connection." + << std::endl; + return false; } - else - adm.dd.ghostConnections.insert(DomainDecomposition::Interface{master, slave, mEdge, sEdge, rever?1:0, 1}); + + if (opt.discretization == ASM::SplineC1) + top.push_back(Interface(static_cast(this->getPatch(master,true)),mEdge, + static_cast(this->getPatch(slave,true)),sEdge,orient)); } // Second pass for C1-continuous patches, to set up additional constraints diff --git a/src/SIM/SIM2D.h b/src/SIM/SIM2D.h index 98e303aa..c35b4de0 100644 --- a/src/SIM/SIM2D.h +++ b/src/SIM/SIM2D.h @@ -70,6 +70,17 @@ public: virtual bool readPatches(std::istream& isp, PatchVec& patches, const char* whiteSpace) const; + //! \brief Connect two patches. + //! \param master Master patch + //! \param slave Slave patch + //! \param mEdge Edge on master + //! \param sEdge Edge on slave + //! \param orient Orientation flag for connection (1 for reversed) + //! \param basis Which bases to connect (0 for all) + //! \param coordCheck False to turn off coordinate checks + bool addConnection(int master, int slave, int mEdge, int sEdge, + int orient, int basis = 0, bool coordCheck = true); + //! \brief Evaluates the primary solution at the given point. //! \param[in] psol Primary solution vector //! \param[in] u First parameter of the point to evaluate at diff --git a/src/SIM/SIM3D.C b/src/SIM/SIM3D.C index 4f857316..aa864385 100644 --- a/src/SIM/SIM3D.C +++ b/src/SIM/SIM3D.C @@ -46,6 +46,44 @@ SIM3D::SIM3D (IntegrandBase* itg, unsigned char n, bool check) : SIMgeneric(itg) } +bool SIM3D::addConnection (int master, int slave, int mIdx, + int sIdx, int orient, int basis, bool coordCheck) +{ + if (orient < 0 || orient > 7) { + std::cerr <<" *** SIM3D::addConnection: Invalid orientation "<< orient <<"." + << std::endl; + return false; + } + + int lmaster = this->getLocalPatchIndex(master); + int lslave = this->getLocalPatchIndex(slave); + if (lmaster > 0 && lslave > 0) + { + IFEM::cout <<"\tConnecting P"<< slave <<" F"<< sIdx + <<" to P"<< master <<" F"<< mIdx + <<" orient "<< orient << std::endl; + + ASMs3D* spch = static_cast(myModel[lslave-1]); + ASMs3D* mpch = static_cast(myModel[lmaster-1]); + + std::set bases; + if (basis == 0) + for (size_t b = 1; b <= spch->getNoBasis(); ++b) + bases.insert(b); + else + bases = utl::getDigits(basis); + + for (const int& b : bases) + if (!spch->connectPatch(sIdx,*mpch,mIdx,orient,b,coordCheck)) + return false; + } + else + adm.dd.ghostConnections.insert(DomainDecomposition::Interface{master, slave, mIdx, sIdx, orient, 2}); + + return true; +} + + bool SIM3D::parseGeometryTag (const TiXmlElement* elem) { IFEM::cout <<" Parsing <"<< elem->Value() <<">"<< std::endl; @@ -138,12 +176,15 @@ bool SIM3D::parseGeometryTag (const TiXmlElement* elem) const TiXmlElement* child = elem->FirstChildElement("connection"); for (; child; child = child->NextSiblingElement()) { - int master = 0, slave = 0, mFace = 0, sFace = 0, orient = 0; + int master = 0, slave = 0, mFace = 0, sFace = 0, orient = 0, basis = 0; + bool periodic = false; utl::getAttribute(child,"master",master); utl::getAttribute(child,"mface",mFace); utl::getAttribute(child,"slave",slave); utl::getAttribute(child,"sface",sFace); utl::getAttribute(child,"orient",orient); + utl::getAttribute(child,"basis",basis); + utl::getAttribute(child,"periodic",periodic); if (master == slave || master < 1 || master > nGlPatches || @@ -153,18 +194,14 @@ bool SIM3D::parseGeometryTag (const TiXmlElement* elem) << master <<" "<< slave << std::endl; return false; } - int lmaster = this->getLocalPatchIndex(master); - int lslave = this->getLocalPatchIndex(slave); - if (lmaster > 0 && lslave > 0) { - IFEM::cout <<"\tConnecting P"<< lslave <<" F"<< sFace - <<" to P"<< lmaster <<" F"<< mFace - <<" orient "<< orient << std::endl; - ASMs3D* spch = static_cast(myModel[lslave-1]); - ASMs3D* mpch = static_cast(myModel[lmaster-1]); - if (!spch->connectPatch(sFace,*mpch,mFace,orient)) - return false; - } else - adm.dd.ghostConnections.insert(DomainDecomposition::Interface{master, slave, mFace, sFace, orient, 2}); + + if (!this->addConnection(master, slave, mFace, sFace, + orient, basis, !periodic)) + { + std::cerr <<" *** SIM3D::parse: Error establishing connection." + << std::endl; + return false; + } } } diff --git a/src/SIM/SIM3D.h b/src/SIM/SIM3D.h index df9aeaeb..9cbebb8f 100644 --- a/src/SIM/SIM3D.h +++ b/src/SIM/SIM3D.h @@ -65,6 +65,17 @@ public: virtual bool readPatches(std::istream& isp, PatchVec& patches, const char* whiteSpace) const; + //! \brief Connect two patches. + //! \param master Master patch + //! \param slave Slave patch + //! \param mFace Face on master + //! \param sFace Face on slave + //! \param orient Orientation flag for connection + //! \param basis Which bases to connect (0 for all) + //! \param coordCheck False to turn off coordinate checks + bool addConnection(int master, int slave, int mFace, int sFace, + int orient, int basis = 0, bool coordCheck = true); + //! \brief Evaluates the primary solution at the given point. //! \param[in] psol Primary solution vector //! \param[in] u First parameter of the point to evaluate at diff --git a/src/SIM/SIMbase.h b/src/SIM/SIMbase.h index 84cb50fa..c61f5723 100644 --- a/src/SIM/SIMbase.h +++ b/src/SIM/SIMbase.h @@ -91,6 +91,18 @@ public: //! \brief Returns a list of prioritized XML-tags. virtual const char** getPrioritizedTags() const; + //! \brief Connect two patches. + //! \param master Master patch + //! \param slave Slave patch + //! \param mIdx Index on master + //! \param sIdx Index on slave + //! \param orient Orientation flag + //! \param basis Which bases to connect (0 for all) + //! \param coordCheck False to turn off coordinate checks. + virtual bool addConnection(int master, int slave, int mIdx, int sIdx, + int orient, int basis = 0, bool coordCheck = true) + { return false; } + protected: //! \brief Parses the "set" attribute of a material XML-tag. //! \param[in] elem The XML element extract the set name from