From 15a3d5d8040625312b96fb54f8cd99462bbb32e6 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 12 Mar 2019 14:26:46 +0000 Subject: [PATCH 001/408] Initial tinyxml reader for interface --- .gitignore | 1 + library/SpatialDomains/CMakeLists.txt | 2 + library/SpatialDomains/Interface.cpp | 386 ++++++++++++++++++++++++++ library/SpatialDomains/Interface.h | 182 ++++++++++++ 4 files changed, 571 insertions(+) create mode 100644 library/SpatialDomains/Interface.cpp create mode 100644 library/SpatialDomains/Interface.h diff --git a/.gitignore b/.gitignore index a9724a77b..fcf15433c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ ThirdParty *.pdf # Kdevelop project files *.kdev4 +cmake-build-debug diff --git a/library/SpatialDomains/CMakeLists.txt b/library/SpatialDomains/CMakeLists.txt index 38ff75e28..c4eebefa2 100644 --- a/library/SpatialDomains/CMakeLists.txt +++ b/library/SpatialDomains/CMakeLists.txt @@ -1,5 +1,6 @@ SET(SPATIAL_DOMAINS_SOURCES Conditions.cpp +Interface.cpp GeomFactors.cpp Geometry0D.cpp Geometry1D.cpp @@ -22,6 +23,7 @@ TriGeom.cpp SET(SPATIAL_DOMAINS_HEADERS Conditions.h +Interface.h Curve.hpp GeomFactors.h Geometry0D.h diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp new file mode 100644 index 000000000..0ed0cf62e --- /dev/null +++ b/library/SpatialDomains/Interface.cpp @@ -0,0 +1,386 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// File: InterfaceConditions.cpp +// +// For more information, please see: http://www.nektar.info/ +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// License for the specific language governing rights and limitations under +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: +// +// +//////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +using namespace std; + +namespace Nektar +{ + namespace SpatialDomains + { + /** + * Constructor - collective on the session's communicator. + */ + InterfaceConditions::InterfaceConditions( + const LibUtilities::SessionReaderSharedPtr &pSession, + const MeshGraphSharedPtr &meshGraph) : + m_meshGraph(meshGraph), m_session(pSession) + { + Read(m_session->GetElement("Nektar/Conditions")); + } + + InterfaceConditions::InterfaceConditions(void) + { + } + + InterfaceConditions::~InterfaceConditions(void) + { + } + + /** + * Create a new communicator for each boundary region. + * Collective on the session's communicator. + */ + //void InterfaceConditions::CreateInterfaceComms() + /*{ + LibUtilities::CommSharedPtr comm = m_session->GetComm(); + + std::set allids = ShareAllBoundaryIDs(m_boundaryRegions, comm); + + for (auto &it : allids) + { + auto reg_it = m_boundaryRegions.find(it); + int this_rank_participates = (reg_it != m_boundaryRegions.end()); + LibUtilities::CommSharedPtr comm_region = comm->CommCreateIf( + this_rank_participates); + + ASSERTL0(bool(comm_region) == bool(this_rank_participates), + "Rank should be in communicator but wasn't or is in " + "communicator but shouldn't be."); + + if (this_rank_participates) + { + m_boundaryCommunicators[reg_it->first] = comm_region; + } + } + }*/ + + /** + * Collective on the session's communicator. + */ + void InterfaceConditions::Read(TiXmlElement *conditions) + { + ASSERTL0(conditions, "Unable to find CONDITIONS tag in file."); + + TiXmlElement *interfaceRegions = conditions->FirstChildElement( + "INTERFACEREGIONS"); + + if (interfaceRegions) + { + ReadInterfaceRegions(conditions); + CreateInterfaceComms(); + ReadInterfaceConditions(conditions); + } + } + + /** + * + */ + void InterfaceConditions::ReadInterfaceRegions(TiXmlElement *conditions) + { + // ensure interface regions only read once per class definition + if (m_interfaceRegions.size() != 0) + { + return; + } + + TiXmlElement *interfaceRegions = conditions->FirstChildElement( + "INTERFACEREGIONS"); + ASSERTL0(interfaceRegions, + "Unable to find INTERFACEREGIONS block."); + + // See if we have boundary regions defined. + TiXmlElement *interfaceRegionsElement = + interfaceRegions->FirstChildElement("I"); + + while (interfaceRegionsElement) + { + /// All elements are of the form: " ... ", with + /// ? being the element type. + int indx; + int err = interfaceRegionsElement->QueryIntAttribute("ID", + &indx); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID."); + + TiXmlNode *interfaceRegionChild = + interfaceRegionsElement->FirstChild(); + // This is primarily to skip comments that may be present. + // Comments appear as nodes just like elements. + // We are specifically looking for text in the body + // of the definition. + while (interfaceRegionChild + && interfaceRegionChild->Type() + != TiXmlNode::TINYXML_TEXT) + { + interfaceRegionChild = interfaceRegionChild->NextSibling(); + } + + ASSERTL0(interfaceRegionChild, + "Unable to read variable definition body."); + std::string interfaceRegionStr = + interfaceRegionChild->ToText()->ValueStr(); + + std::string::size_type indxBeg = + interfaceRegionStr.find_first_of('[') + 1; + std::string::size_type indxEnd = + interfaceRegionStr.find_last_of( + ']') - 1; + + ASSERTL0(indxBeg <= indxEnd, + (std::string( + "Error reading interface region definition:") + + interfaceRegionStr).c_str()); + + std::string indxStr = interfaceRegionStr.substr(indxBeg, + indxEnd - + indxBeg + 1); + + if (!indxStr.empty()) + { + // Extract the composites from the string and return them in a list. + InterfaceRegionShPtr interfaceRegion( + MemoryManager::AllocateSharedPtr()); + + ASSERTL0(m_interfaceRegions.count(indx) == 0, + "Interface region " + indxStr + + " defined more than " + "once!"); + + m_meshGraph->GetCompositeList(indxStr, *interfaceRegion); + m_interfaceRegions[indx] = interfaceRegion; + } + + interfaceRegionsElement = + interfaceRegionsElement->NextSiblingElement("I"); + } + } + + /** + * + */ + void InterfaceConditions::ReadInterfaceConditions( + TiXmlElement *conditions) + { + // Protect against multiple reads. + if (!m_interfaceConditions.empty()) //before was .size()!=0; + { + return; + } + + // Read REGION tags + TiXmlElement *interfaceConditionsElement = + conditions->FirstChildElement("INTERFACECONDITIONS"); + ASSERTL0(interfaceConditionsElement, + "Boundary conditions must be specified."); + + TiXmlElement *regionElement = + interfaceConditionsElement->FirstChildElement("REGION"); + + // Read F (Fixed), R (Rotating), S (Sliding) tags + while (regionElement) + { + InterfaceConditionMapShPtr interfaceConditions = MemoryManager< + InterfaceConditionMap>::AllocateSharedPtr(); + + int interfaceRegionID; + int err = regionElement->QueryIntAttribute("REF", + &interfaceRegionID); + ASSERTL0(err == TIXML_SUCCESS, + "Error reading interface region reference."); + + ASSERTL0(m_interfaceConditions.count(interfaceRegionID) == 0, + "Interface region '" + boost::lexical_cast( + interfaceRegionID) + + "' appears multiple times."); + + // Find the interface region corresponding to this ID. + std::string interfaceRegionIDStr; + std::ostringstream interfaceRegionIDStrm(interfaceRegionIDStr); + interfaceRegionIDStrm << interfaceRegionID; + + ASSERTL0(m_interfaceRegions.count(interfaceRegionID) == 1, + "Interface region " + boost::lexical_cast( + interfaceRegionID) + " not found"); + + // Find the communicator that belongs to this ID + LibUtilities::CommSharedPtr interfaceRegionComm = + m_interfaceCommunicators[interfaceRegionID]; + + TiXmlElement *conditionElement = + regionElement->FirstChildElement(); + //Below should get list of all domains defined in geometry + //std::vector > domain = m_meshGraph->GetDomain(); + + + while (conditionElement) + { + // Check type. + std::string conditionType = conditionElement->Value(); + std::string attrData; + bool isTimeDependent = false; + + // All have var specified, or else all variables are zero. + TiXmlAttribute *attr = conditionElement->FirstAttribute(); + + std::vector::iterator iter; + std::string attrName; + + attrData = conditionElement->Attribute("DOMAIN"); + + //CHANGE THIS: Currently checks all domains are in every interface region + //Will be wrong with multiple interfaces in future + /* + if (!attrData.empty()) + { + iter = std::find(domain.begin(), domain.end(), attrData); + ASSERTL0(iter != domain.end(), + (std::string("Cannot find domain: ") + + attrData).c_str()); + } + */ + + if (conditionType == "R") //Rotating domain + { + if (attrData.empty()) + { + ASSERTL0(!attrData.empty(), + "Rotating region must have associated attributes."); + } + else + { + // Use the iterator from above, which must point to the variable. + attr = attr->Next(); + + if (attr) + { + vector rotatingIntRegionIndex; + std::vector origin, axis; + NekDouble angularVel; + while (attr) + { + + attrName = attr->Name(); + + if (attrName == "ORIGIN") + { + attrData = attr->Value(); + ASSERTL0(!attrData.empty(), + "ORIGIN attribute must have associated value."); + + // Suppose to go here? + m_session->SubstituteExpressions( + attrData); + + ParseUtils::GenerateVector(attrData, + origin); + + ASSERTL0(origin.size() == 3, + "ORIGIN attribute must have length of 3."); + + } + else if (attrName == "AXIS") + { + attrData = attr->Value(); + ASSERTL0(!attrData.empty(), + "AXIS attribute must have associated value."); + + m_session->SubstituteExpressions( + attrData); + + ParseUtils::GenerateVector(attrData, + axis); + + ASSERTL0(axis.size() == 3, + "AXIS attribute must have length of 3."); + + } + else if (attrName == "ANGVEL") + { + attrData = attr->Value(); + ASSERTL0(!attrData.empty(), + "ANGVEL attribute must be specified."); + + m_session->SubstituteExpressions( + attrData); + + //Convert from string to NekDouble + //@todo add PI parsing so expressions such as 2*PI can be understood + angularVel = static_cast(stod( + attrData)); + } + else + { + ASSERTL0(false, + (std::string( + "Unknown rotating interface condition attribute: ") + + attrName).c_str()); + } + attr = attr->Next(); + } + InterfaceConditionShPtr rotatingCondition( + MemoryManager::AllocateSharedPtr( + rotatingIntRegionIndex[0], + m_session, origin, + axis, angularVel, + interfaceRegionComm)); + (*interfaceConditions)[*iter] = rotatingCondition; + } + } + } + else if (conditionType == "F") + { + + } + else if (conditionType == "S") // Sliding + { + + } + + conditionElement = conditionElement->NextSiblingElement(); + + } + + m_interfaceConditions[interfaceRegionID] = interfaceConditions; + regionElement = regionElement->NextSiblingElement("REGION"); + } + } + } +} diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h new file mode 100644 index 000000000..de426b8c9 --- /dev/null +++ b/library/SpatialDomains/Interface.h @@ -0,0 +1,182 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// File: Conditions.h +// +// For more information, please see: http://www.nektar.info/ +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// License for the specific language governing rights and limitations under +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: +// +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef NEKTAR_SPATIALDOMAINS_INTERFACECONDITIONS_H +#define NEKTAR_SPATIALDOMAINS_BOUNDARYCONDITIONS_H + +#include +#include + +#include +#include +#include + +namespace Nektar +{ + struct OneD; + + namespace SpatialDomains + { + enum InterfaceConditionType + { + eFixed, + eRotating, + eSliding, + eNotDefinedInterface + }; + + struct InterfaceConditionBase + { + InterfaceConditionBase( + InterfaceConditionType type, + LibUtilities::CommSharedPtr comm = LibUtilities::CommSharedPtr()): + m_interfaceConditionType(type), + m_comm(comm) + { + } + + virtual ~InterfaceConditionBase() + {}; + + InterfaceConditionType GetInterfaceConditionType() const + { + return m_interfaceConditionType; + } + + void SetInterfaceConditionType(InterfaceConditionType interfaceType) + { + m_interfaceConditionType = interfaceType; + } + + LibUtilities::CommSharedPtr GetComm() + { + return m_comm; + } + + protected: + InterfaceConditionType m_interfaceConditionType; + std::vector m_origin; + std::vector m_axis; + NekDouble m_angularVel; + LibUtilities::CommSharedPtr m_comm; + }; + + struct RotatingInterfaceCondition : public InterfaceConditionBase + { + RotatingInterfaceCondition( + const unsigned int n, + const LibUtilities::SessionReaderSharedPtr &pSession, + const std::vector origin, + const std::vector axis, + const NekDouble angularVel, + const LibUtilities::CommSharedPtr comm=LibUtilities::CommSharedPtr()): + InterfaceConditionBase(eRotating, comm), + m_connectedInterfaceRegion(n) + { + } + + unsigned int m_connectedInterfaceRegion; + + }; + + typedef std::map InterfaceRegion; + typedef std::shared_ptr InterfaceRegionShPtr; + typedef std::shared_ptr ConstInterfaceRegionShPtr; + typedef std::map InterfaceRegionCollection; + + typedef std::shared_ptr InterfaceConditionShPtr; + typedef std::shared_ptr RotatingInterfaceShPtr; + + typedef std::map InterfaceConditionMap; + typedef std::shared_ptr InterfaceConditionMapShPtr; + typedef std::map InterfaceConditionCollection; + + const static Array NullInterfaceConditionShPtrArray; + + class InterfaceConditions + { + public: + SPATIAL_DOMAINS_EXPORT InterfaceConditions(const LibUtilities::SessionReaderSharedPtr &pSession, const MeshGraphSharedPtr &meshGraph); + + SPATIAL_DOMAINS_EXPORT InterfaceConditions(void); + SPATIAL_DOMAINS_EXPORT ~InterfaceConditions(void); + + const InterfaceRegionCollection &GetInterfaceRegions(void) const + { + return m_interfaceRegions; + } + + void AddInterfaceRegions(const int regionID, InterfaceRegionShPtr &iRegion) + { + m_interfaceRegions[regionID] = iRegion; + } + + const InterfaceConditionCollection &GetInterfaceConditions(void) const + { + return m_interfaceConditions; + } + + + void AddInterfaceConditions(const int regionID, InterfaceConditionMapShPtr &iCond) + { + m_interfaceConditions[regionID] = iCond; + } + + const std::string GetVariable(unsigned int indx) + { + return m_session->GetVariable(indx); + } + + protected: + /// The mesh graph to use for referencing geometry info. + MeshGraphSharedPtr m_meshGraph; + LibUtilities::SessionReaderSharedPtr m_session; + + InterfaceRegionCollection m_interfaceRegions; + InterfaceConditionCollection m_interfaceConditions; + std::map m_interfaceCommunicators; + + private: + + /// Read segments (and general MeshGraph) given TiXmlDocument. + void Read(TiXmlElement *conditions); + void ReadInterfaceRegions(TiXmlElement *regions); + void ReadInterfaceConditions(TiXmlElement *conditions); + void CreateInterfaceComms(); + }; + } +} + +#endif //NEKTAR_SPATIALDOMAINS_INTERFACECONDITIONS_H -- GitLab From f06b1aa99c243e9a470e4cbb4200893cab55b7f8 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 14 Mar 2019 10:20:51 +0000 Subject: [PATCH 002/408] Update to interface reader & basic test prototype --- library/Demos/SpatialDomains/CMakeLists.txt | 2 + .../Demos/SpatialDomains/InterfaceTest.cpp | 29 ++ library/SpatialDomains/Interface.cpp | 341 ++---------------- library/SpatialDomains/Interface.h | 151 ++++---- 4 files changed, 138 insertions(+), 385 deletions(-) create mode 100644 library/Demos/SpatialDomains/InterfaceTest.cpp diff --git a/library/Demos/SpatialDomains/CMakeLists.txt b/library/Demos/SpatialDomains/CMakeLists.txt index efc43579b..d190ce705 100644 --- a/library/Demos/SpatialDomains/CMakeLists.txt +++ b/library/Demos/SpatialDomains/CMakeLists.txt @@ -1,2 +1,4 @@ ADD_NEKTAR_EXECUTABLE(PartitionAnalyse COMPONENT demos DEPENDS SpatialDomains SOURCES PartitionAnalyse.cpp) +ADD_NEKTAR_EXECUTABLE(InterfaceTest + COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceTest.cpp) diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp new file mode 100644 index 000000000..a3a5e83db --- /dev/null +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -0,0 +1,29 @@ +// +// Created by Edward Laughton on 2019-03-12. +// + +#include +#include +#include + +using namespace Nektar; + +int main(int argc, char *argv[]) +{ + LibUtilities::SessionReaderSharedPtr session = + LibUtilities::SessionReader::CreateInstance(argc, argv); + + SpatialDomains::MeshGraphSharedPtr graph = + SpatialDomains::MeshGraph::Read(session); + + Interface conds = SpatialDomains::Interface(session, graph); + auto regions = conds.GetInterfaceRegions(); + + /*for (auto ®ion : regions) + { + std::cout << region->GetInterfaceConditionType() << std::endl; + region->AdjustMeshGraph(graph); + }*/ + + +} \ No newline at end of file diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 0ed0cf62e..08f74835e 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -44,342 +44,77 @@ namespace Nektar { namespace SpatialDomains { - /** - * Constructor - collective on the session's communicator. - */ - InterfaceConditions::InterfaceConditions( + Interfaces::Interfaces( const LibUtilities::SessionReaderSharedPtr &pSession, const MeshGraphSharedPtr &meshGraph) : m_meshGraph(meshGraph), m_session(pSession) { - Read(m_session->GetElement("Nektar/Conditions")); + Read(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); } - InterfaceConditions::InterfaceConditions(void) + Interfaces::Interfaces(void) { } - InterfaceConditions::~InterfaceConditions(void) + Interfaces::~Interfaces(void) { } - /** - * Create a new communicator for each boundary region. - * Collective on the session's communicator. - */ - //void InterfaceConditions::CreateInterfaceComms() - /*{ - LibUtilities::CommSharedPtr comm = m_session->GetComm(); - - std::set allids = ShareAllBoundaryIDs(m_boundaryRegions, comm); - - for (auto &it : allids) - { - auto reg_it = m_boundaryRegions.find(it); - int this_rank_participates = (reg_it != m_boundaryRegions.end()); - LibUtilities::CommSharedPtr comm_region = comm->CommCreateIf( - this_rank_participates); - - ASSERTL0(bool(comm_region) == bool(this_rank_participates), - "Rank should be in communicator but wasn't or is in " - "communicator but shouldn't be."); - - if (this_rank_participates) - { - m_boundaryCommunicators[reg_it->first] = comm_region; - } - } - }*/ - - /** - * Collective on the session's communicator. - */ - void InterfaceConditions::Read(TiXmlElement *conditions) + void Interfaces::Read(TiXmlElement *interfacesTag) { - ASSERTL0(conditions, "Unable to find CONDITIONS tag in file."); + ASSERTL0(interfacesTag, "Unable to find INTERFACES tag in file."); - TiXmlElement *interfaceRegions = conditions->FirstChildElement( - "INTERFACEREGIONS"); - - if (interfaceRegions) + if (interfacesTag) { - ReadInterfaceRegions(conditions); - CreateInterfaceComms(); - ReadInterfaceConditions(conditions); + ReadInterface(interfacesTag); } } - /** - * - */ - void InterfaceConditions::ReadInterfaceRegions(TiXmlElement *conditions) + std::string ReadTag(std::string domainStr) { - // ensure interface regions only read once per class definition - if (m_interfaceRegions.size() != 0) - { - return; - } - - TiXmlElement *interfaceRegions = conditions->FirstChildElement( - "INTERFACEREGIONS"); - ASSERTL0(interfaceRegions, - "Unable to find INTERFACEREGIONS block."); - - // See if we have boundary regions defined. - TiXmlElement *interfaceRegionsElement = - interfaceRegions->FirstChildElement("I"); - - while (interfaceRegionsElement) - { - /// All elements are of the form: " ... ", with - /// ? being the element type. - int indx; - int err = interfaceRegionsElement->QueryIntAttribute("ID", - &indx); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read attribute ID."); - - TiXmlNode *interfaceRegionChild = - interfaceRegionsElement->FirstChild(); - // This is primarily to skip comments that may be present. - // Comments appear as nodes just like elements. - // We are specifically looking for text in the body - // of the definition. - while (interfaceRegionChild - && interfaceRegionChild->Type() - != TiXmlNode::TINYXML_TEXT) - { - interfaceRegionChild = interfaceRegionChild->NextSibling(); - } - - ASSERTL0(interfaceRegionChild, - "Unable to read variable definition body."); - std::string interfaceRegionStr = - interfaceRegionChild->ToText()->ValueStr(); - - std::string::size_type indxBeg = - interfaceRegionStr.find_first_of('[') + 1; - std::string::size_type indxEnd = - interfaceRegionStr.find_last_of( - ']') - 1; - - ASSERTL0(indxBeg <= indxEnd, - (std::string( - "Error reading interface region definition:") - + interfaceRegionStr).c_str()); - - std::string indxStr = interfaceRegionStr.substr(indxBeg, - indxEnd - - indxBeg + 1); - - if (!indxStr.empty()) - { - // Extract the composites from the string and return them in a list. - InterfaceRegionShPtr interfaceRegion( - MemoryManager::AllocateSharedPtr()); + std::string::size_type indxBeg = domainStr.find_first_of('[') + 1; + std::string::size_type indxEnd = domainStr.find_last_of(']') - 1; - ASSERTL0(m_interfaceRegions.count(indx) == 0, - "Interface region " + indxStr + - " defined more than " - "once!"); + ASSERTL0(indxBeg <= indxEnd, + (std::string("Error reading boundary region definition:") + domainStr).c_str()); - m_meshGraph->GetCompositeList(indxStr, *interfaceRegion); - m_interfaceRegions[indx] = interfaceRegion; - } + std::string indxStr = domainStr.substr(indxBeg, indxEnd - indxBeg + 1); - interfaceRegionsElement = - interfaceRegionsElement->NextSiblingElement("I"); - } + return indxStr; } - /** - * - */ - void InterfaceConditions::ReadInterfaceConditions( - TiXmlElement *conditions) + void Interfaces::ReadInterfaces(TiXmlElement *interfacesTag) { - // Protect against multiple reads. - if (!m_interfaceConditions.empty()) //before was .size()!=0; - { - return; - } + TiXmlElement *interfaceElementTag = interfacesTag->FirstChildElement(); + std::string interfaceType = interfaceElementTag->Value(); - // Read REGION tags - TiXmlElement *interfaceConditionsElement = - conditions->FirstChildElement("INTERFACECONDITIONS"); - ASSERTL0(interfaceConditionsElement, - "Boundary conditions must be specified."); - - TiXmlElement *regionElement = - interfaceConditionsElement->FirstChildElement("REGION"); - - // Read F (Fixed), R (Rotating), S (Sliding) tags - while (regionElement) - { - InterfaceConditionMapShPtr interfaceConditions = MemoryManager< - InterfaceConditionMap>::AllocateSharedPtr(); + int err; //variable to check attributes are read correctly + int indx; //value that holds interface ID + err = interfaceElementTag->QueryIntAttribute("ID", &indx); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); - int interfaceRegionID; - int err = regionElement->QueryIntAttribute("REF", - &interfaceRegionID); - ASSERTL0(err == TIXML_SUCCESS, - "Error reading interface region reference."); + std::string interfaceMovingDomainStr; + err = interfaceElementTag->QueryStringAttribute("DOMAIN", &interfaceMovingDomainStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read moving interface domain."); + CompositeMap movingDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceMovingDomainStr))); - ASSERTL0(m_interfaceConditions.count(interfaceRegionID) == 0, - "Interface region '" + boost::lexical_cast( - interfaceRegionID) - + "' appears multiple times."); + std::string interfaceFixedDomainStr; + err = interfaceElementTag->QueryStringAttribute("FIXED", &interfaceFixedDomainStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read fixed interface domain."); + CompositeMap fixedDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceFixedDomainStr))); - // Find the interface region corresponding to this ID. - std::string interfaceRegionIDStr; - std::ostringstream interfaceRegionIDStrm(interfaceRegionIDStr); - interfaceRegionIDStrm << interfaceRegionID; + std::string interfaceEdgeStr; + err = interfaceElementTag->QueryStringAttribute("INTERFACE", &interfaceEdgeStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface composite."); - ASSERTL0(m_interfaceRegions.count(interfaceRegionID) == 1, - "Interface region " + boost::lexical_cast( - interfaceRegionID) + " not found"); + InterfaceEdgeShPtr interfaceEdge; + m_meshGraph->GetCompositeList(ReadTag(interfaceEdgeStr), *interfaceEdge); - // Find the communicator that belongs to this ID - LibUtilities::CommSharedPtr interfaceRegionComm = - m_interfaceCommunicators[interfaceRegionID]; + TiXmlAttribute *attr = interfaceElementTag->FirstAttribute(); - TiXmlElement *conditionElement = - regionElement->FirstChildElement(); - //Below should get list of all domains defined in geometry - //std::vector > domain = m_meshGraph->GetDomain(); - - - while (conditionElement) - { - // Check type. - std::string conditionType = conditionElement->Value(); - std::string attrData; - bool isTimeDependent = false; - - // All have var specified, or else all variables are zero. - TiXmlAttribute *attr = conditionElement->FirstAttribute(); - - std::vector::iterator iter; - std::string attrName; - - attrData = conditionElement->Attribute("DOMAIN"); - - //CHANGE THIS: Currently checks all domains are in every interface region - //Will be wrong with multiple interfaces in future - /* - if (!attrData.empty()) - { - iter = std::find(domain.begin(), domain.end(), attrData); - ASSERTL0(iter != domain.end(), - (std::string("Cannot find domain: ") - + attrData).c_str()); - } - */ - - if (conditionType == "R") //Rotating domain - { - if (attrData.empty()) - { - ASSERTL0(!attrData.empty(), - "Rotating region must have associated attributes."); - } - else - { - // Use the iterator from above, which must point to the variable. - attr = attr->Next(); - - if (attr) - { - vector rotatingIntRegionIndex; - std::vector origin, axis; - NekDouble angularVel; - while (attr) - { - - attrName = attr->Name(); - - if (attrName == "ORIGIN") - { - attrData = attr->Value(); - ASSERTL0(!attrData.empty(), - "ORIGIN attribute must have associated value."); - - // Suppose to go here? - m_session->SubstituteExpressions( - attrData); - - ParseUtils::GenerateVector(attrData, - origin); - - ASSERTL0(origin.size() == 3, - "ORIGIN attribute must have length of 3."); - - } - else if (attrName == "AXIS") - { - attrData = attr->Value(); - ASSERTL0(!attrData.empty(), - "AXIS attribute must have associated value."); - - m_session->SubstituteExpressions( - attrData); - - ParseUtils::GenerateVector(attrData, - axis); - - ASSERTL0(axis.size() == 3, - "AXIS attribute must have length of 3."); - - } - else if (attrName == "ANGVEL") - { - attrData = attr->Value(); - ASSERTL0(!attrData.empty(), - "ANGVEL attribute must be specified."); - - m_session->SubstituteExpressions( - attrData); - - //Convert from string to NekDouble - //@todo add PI parsing so expressions such as 2*PI can be understood - angularVel = static_cast(stod( - attrData)); - } - else - { - ASSERTL0(false, - (std::string( - "Unknown rotating interface condition attribute: ") + - attrName).c_str()); - } - attr = attr->Next(); - } - InterfaceConditionShPtr rotatingCondition( - MemoryManager::AllocateSharedPtr( - rotatingIntRegionIndex[0], - m_session, origin, - axis, angularVel, - interfaceRegionComm)); - (*interfaceConditions)[*iter] = rotatingCondition; - } - } - } - else if (conditionType == "F") - { - - } - else if (conditionType == "S") // Sliding - { - - } - - conditionElement = conditionElement->NextSiblingElement(); - - } + if (interfaceType == "R") + { - m_interfaceConditions[interfaceRegionID] = interfaceConditions; - regionElement = regionElement->NextSiblingElement("REGION"); } } } diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index de426b8c9..4817cf9da 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // -// File: Conditions.h +// File: s.h // // For more information, please see: http://www.nektar.info/ // @@ -16,7 +16,7 @@ // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: +// Software is furnished to do so, subject to the following s: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. @@ -33,8 +33,8 @@ // // //////////////////////////////////////////////////////////////////////////////// -#ifndef NEKTAR_SPATIALDOMAINS_INTERFACECONDITIONS_H -#define NEKTAR_SPATIALDOMAINS_BOUNDARYCONDITIONS_H +#ifndef NEKTAR_SPATIALDOMAINS_INTERFACES_H +#define NEKTAR_SPATIALDOMAINS_INTERFACES_H #include #include @@ -49,134 +49,121 @@ namespace Nektar namespace SpatialDomains { - enum InterfaceConditionType + enum InterfaceType { eFixed, eRotating, eSliding, - eNotDefinedInterface + eNotDefined }; - struct InterfaceConditionBase + typedef std::map InterfaceEdge; + typedef std::shared_ptr InterfaceEdgeShPtr; + + struct InterfaceBase { - InterfaceConditionBase( - InterfaceConditionType type, - LibUtilities::CommSharedPtr comm = LibUtilities::CommSharedPtr()): - m_interfaceConditionType(type), - m_comm(comm) + InterfaceBase( + InterfaceType type, + CompositeMap movingDomain, + CompositeMap fixedDomain, + InterfaceEdgeShPtr interfaceEdge): + m_interfaceType(type), + m_movingDomain(movingDomain), + m_fixedDomain(fixedDomain), + m_interfaceEdge(interfaceEdge) + { } - virtual ~InterfaceConditionBase() + virtual ~InterfaceBase() {}; - InterfaceConditionType GetInterfaceConditionType() const + InterfaceType GetInterfaceType() const + { + return m_interfaceType; + } + + CompositeMap GetMovingDomain() const { - return m_interfaceConditionType; + return m_movingDomain; } - void SetInterfaceConditionType(InterfaceConditionType interfaceType) + CompositeMap GetFixedDomain() const { - m_interfaceConditionType = interfaceType; + return m_fixedDomain; } - LibUtilities::CommSharedPtr GetComm() + InterfaceEdgeShPtr GetInterfaceEdge() const { - return m_comm; + return m_interfaceEdge; } protected: - InterfaceConditionType m_interfaceConditionType; - std::vector m_origin; - std::vector m_axis; - NekDouble m_angularVel; - LibUtilities::CommSharedPtr m_comm; + InterfaceType m_interfaceType; + CompositeMap m_movingDomain; + CompositeMap m_fixedDomain; + InterfaceEdgeShPtr m_interfaceEdge; }; - struct RotatingInterfaceCondition : public InterfaceConditionBase + struct RotatingInterface : public InterfaceBase { - RotatingInterfaceCondition( - const unsigned int n, + RotatingInterface( const LibUtilities::SessionReaderSharedPtr &pSession, - const std::vector origin, + const CompositeMap movingDomain, + const CompositeMap fixedDomain, + const InterfaceEdgeShPtr interfaceEdge, + const PointGeomSharedPtr origin, const std::vector axis, - const NekDouble angularVel, - const LibUtilities::CommSharedPtr comm=LibUtilities::CommSharedPtr()): - InterfaceConditionBase(eRotating, comm), - m_connectedInterfaceRegion(n) + const NekDouble angularVel): + InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge), + m_origin(origin), + m_axis(axis), + m_angularVel(angularVel) { } - unsigned int m_connectedInterfaceRegion; - + PointGeomSharedPtr m_origin; + std::vector m_axis; + NekDouble m_angularVel; }; - typedef std::map InterfaceRegion; - typedef std::shared_ptr InterfaceRegionShPtr; - typedef std::shared_ptr ConstInterfaceRegionShPtr; - typedef std::map InterfaceRegionCollection; + typedef std::shared_ptr InterfaceShPtr; + typedef std::map InterfaceMap; + typedef std::shared_ptr InterfaceMapShPtr; + typedef std::map InterfaceCollection; + typedef std::shared_ptr RotatingInterfaceShPtr; - typedef std::shared_ptr InterfaceConditionShPtr; - typedef std::shared_ptr RotatingInterfaceShPtr; - - typedef std::map InterfaceConditionMap; - typedef std::shared_ptr InterfaceConditionMapShPtr; - typedef std::map InterfaceConditionCollection; - - const static Array NullInterfaceConditionShPtrArray; - - class InterfaceConditions + class Interfaces { public: - SPATIAL_DOMAINS_EXPORT InterfaceConditions(const LibUtilities::SessionReaderSharedPtr &pSession, const MeshGraphSharedPtr &meshGraph); - - SPATIAL_DOMAINS_EXPORT InterfaceConditions(void); - SPATIAL_DOMAINS_EXPORT ~InterfaceConditions(void); - - const InterfaceRegionCollection &GetInterfaceRegions(void) const - { - return m_interfaceRegions; - } - - void AddInterfaceRegions(const int regionID, InterfaceRegionShPtr &iRegion) - { - m_interfaceRegions[regionID] = iRegion; - } - - const InterfaceConditionCollection &GetInterfaceConditions(void) const - { - return m_interfaceConditions; - } + SPATIAL_DOMAINS_EXPORT Interfaces( + const LibUtilities::SessionReaderSharedPtr &pSession, + const MeshGraphSharedPtr &meshGraph); + SPATIAL_DOMAINS_EXPORT Interfaces(void); + SPATIAL_DOMAINS_EXPORT ~Interfaces(void); - void AddInterfaceConditions(const int regionID, InterfaceConditionMapShPtr &iCond) + const InterfaceCollection &GetInterfaces(void) const { - m_interfaceConditions[regionID] = iCond; + return m_interfaces; } - const std::string GetVariable(unsigned int indx) - { - return m_session->GetVariable(indx); - } protected: /// The mesh graph to use for referencing geometry info. MeshGraphSharedPtr m_meshGraph; LibUtilities::SessionReaderSharedPtr m_session; - InterfaceRegionCollection m_interfaceRegions; - InterfaceConditionCollection m_interfaceConditions; - std::map m_interfaceCommunicators; - + InterfaceCollection m_interfaces; private: /// Read segments (and general MeshGraph) given TiXmlDocument. - void Read(TiXmlElement *conditions); - void ReadInterfaceRegions(TiXmlElement *regions); - void ReadInterfaceConditions(TiXmlElement *conditions); - void CreateInterfaceComms(); + void Read(TiXmlElement *interfaceTag); + void ReadInterfaces(TiXmlElement *interfaceTag); }; + + typedef std::shared_ptr InterfaceSharedPtr; } } -#endif //NEKTAR_SPATIALDOMAINS_INTERFACECONDITIONS_H +#endif //NEKTAR_SPATIALDOMAINS_INTERFACES_H -- GitLab From d82cbdd1f4190f2c3649933eb81404bd26205ef0 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 14 Mar 2019 14:12:33 +0000 Subject: [PATCH 003/408] Working interface xml & updated test prototype --- .../Demos/SpatialDomains/InterfaceTest.cpp | 22 ++-- library/SpatialDomains/Interface.cpp | 108 +++++++++++++----- library/SpatialDomains/Interface.h | 34 ++++-- 3 files changed, 115 insertions(+), 49 deletions(-) diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index a3a5e83db..e18571368 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -7,23 +7,21 @@ #include using namespace Nektar; +using namespace SpatialDomains; int main(int argc, char *argv[]) { - LibUtilities::SessionReaderSharedPtr session = - LibUtilities::SessionReader::CreateInstance(argc, argv); + LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); - SpatialDomains::MeshGraphSharedPtr graph = - SpatialDomains::MeshGraph::Read(session); + SpatialDomains::MeshGraphSharedPtr graph = SpatialDomains::MeshGraph::Read(session); + Interfaces interfaceCollection = SpatialDomains::Interfaces(session, graph); - Interface conds = SpatialDomains::Interface(session, graph); - auto regions = conds.GetInterfaceRegions(); + auto regions = interfaceCollection.GetInterfaces(); - /*for (auto ®ion : regions) + for (auto ®ion : regions) { - std::cout << region->GetInterfaceConditionType() << std::endl; - region->AdjustMeshGraph(graph); - }*/ - - + cout << std::to_string(region.second->GetInterfaceType()) << endl; //<--- works + // cout << std::to_string(region.second->GetAngularVel()) << endl; <--- doesn't work + } + cout << "All read" << endl; } \ No newline at end of file diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 08f74835e..3a9282fb6 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -66,19 +66,20 @@ namespace Nektar if (interfacesTag) { - ReadInterface(interfacesTag); + ReadInterfaces(interfacesTag); } } - std::string ReadTag(std::string domainStr) + std::string ReadTag(std::string tagStr) { - std::string::size_type indxBeg = domainStr.find_first_of('[') + 1; - std::string::size_type indxEnd = domainStr.find_last_of(']') - 1; + std::string::size_type indxBeg = tagStr.find_first_of('[') + 1; + std::string::size_type indxEnd = tagStr.find_last_of(']') - 1; ASSERTL0(indxBeg <= indxEnd, - (std::string("Error reading boundary region definition:") + domainStr).c_str()); + (std::string("Error reading boundary region definition:") + + tagStr).c_str()); - std::string indxStr = domainStr.substr(indxBeg, indxEnd - indxBeg + 1); + std::string indxStr = tagStr.substr(indxBeg, indxEnd - indxBeg + 1); return indxStr; } @@ -86,36 +87,89 @@ namespace Nektar void Interfaces::ReadInterfaces(TiXmlElement *interfacesTag) { TiXmlElement *interfaceElementTag = interfacesTag->FirstChildElement(); - std::string interfaceType = interfaceElementTag->Value(); + while(interfaceElementTag) + { + std::vector::iterator iter; + std::string interfaceType = interfaceElementTag->Value(); - int err; //variable to check attributes are read correctly - int indx; //value that holds interface ID - err = interfaceElementTag->QueryIntAttribute("ID", &indx); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); + int err; //variable to check attributes are read correctly + int indx; //value that holds interface ID + err = interfaceElementTag->QueryIntAttribute("ID", &indx); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); - std::string interfaceMovingDomainStr; - err = interfaceElementTag->QueryStringAttribute("DOMAIN", &interfaceMovingDomainStr); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read moving interface domain."); - CompositeMap movingDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceMovingDomainStr))); + std::string interfaceMovingDomainStr; + err = interfaceElementTag->QueryStringAttribute("DOMAIN", + &interfaceMovingDomainStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read moving interface domain."); + CompositeMap movingDomain = m_meshGraph->GetDomain( + stoi(ReadTag(interfaceMovingDomainStr))); - std::string interfaceFixedDomainStr; - err = interfaceElementTag->QueryStringAttribute("FIXED", &interfaceFixedDomainStr); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read fixed interface domain."); - CompositeMap fixedDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceFixedDomainStr))); + std::string interfaceFixedDomainStr; + err = interfaceElementTag->QueryStringAttribute("FIXED", + &interfaceFixedDomainStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read fixed interface domain."); + CompositeMap fixedDomain = m_meshGraph->GetDomain( + stoi(ReadTag(interfaceFixedDomainStr))); - std::string interfaceEdgeStr; - err = interfaceElementTag->QueryStringAttribute("INTERFACE", &interfaceEdgeStr); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface composite."); + std::string interfaceEdgeStr; + err = interfaceElementTag->QueryStringAttribute("INTERFACE", + &interfaceEdgeStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read interface composite."); - InterfaceEdgeShPtr interfaceEdge; - m_meshGraph->GetCompositeList(ReadTag(interfaceEdgeStr), *interfaceEdge); + InterfaceEdgeShPtr interfaceEdge( + MemoryManager::AllocateSharedPtr()); - TiXmlAttribute *attr = interfaceElementTag->FirstAttribute(); + interfaceEdgeStr = ReadTag(interfaceEdgeStr); + m_meshGraph->GetCompositeList(interfaceEdgeStr, *interfaceEdge); - if (interfaceType == "R") - { + if (interfaceType == "R") + { + + std::string originStr; + err = interfaceElementTag->QueryStringAttribute("ORIGIN", + &originStr); + + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read origin."); + + std::vector originVec; + ParseUtils::GenerateVector(originStr, originVec); + PointGeomSharedPtr origin = MemoryManager:: + AllocateSharedPtr(PointGeom(3, 0, originVec[0], originVec[1], originVec[2])); + + std::string axisStr; + err = interfaceElementTag->QueryStringAttribute("AXIS", + &axisStr); + + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read axis."); + + std::vector axis; + ParseUtils::GenerateVector(originStr, axis); + + std::string angularVelStr; + err = interfaceElementTag->QueryStringAttribute("ANGVEL", + &angularVelStr); + + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read angular velocity."); + + NekDouble angularVel = stod(angularVelStr); + + InterfaceShPtr rotatingInterface( + MemoryManager::AllocateSharedPtr( + m_session, movingDomain, fixedDomain, + interfaceEdge, origin, axis, angularVel)); + + m_interfaces[indx] = rotatingInterface; + } + interfaceElementTag = interfaceElementTag->NextSiblingElement(); } + // } } } diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 4817cf9da..fa5e61a4c 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -114,25 +114,41 @@ namespace Nektar const InterfaceEdgeShPtr interfaceEdge, const PointGeomSharedPtr origin, const std::vector axis, - const NekDouble angularVel): - InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge), - m_origin(origin), - m_axis(axis), - m_angularVel(angularVel) + const NekDouble angularVel) + : InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge), + m_origin(origin), + m_axis(axis), + m_angularVel(angularVel) { } + PointGeomSharedPtr GetOrigin() const + { + return m_origin; + } + + std::vector GetAxis() const + { + return m_axis; + } + + NekDouble GetAngularVel() const + { + return m_angularVel; + } + PointGeomSharedPtr m_origin; std::vector m_axis; NekDouble m_angularVel; }; typedef std::shared_ptr InterfaceShPtr; - typedef std::map InterfaceMap; - typedef std::shared_ptr InterfaceMapShPtr; - typedef std::map InterfaceCollection; typedef std::shared_ptr RotatingInterfaceShPtr; + typedef std::map InterfaceCollection; + + + class Interfaces { public: @@ -161,8 +177,6 @@ namespace Nektar void Read(TiXmlElement *interfaceTag); void ReadInterfaces(TiXmlElement *interfaceTag); }; - - typedef std::shared_ptr InterfaceSharedPtr; } } -- GitLab From a99ab665bcd8fce48a51fe98c6463674e31ec026 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 15 Mar 2019 10:36:23 +0000 Subject: [PATCH 004/408] Start interface edge duplication --- library/Demos/SpatialDomains/CMakeLists.txt | 3 + .../SpatialDomains/InterfaceDuplicateEdge.cpp | 61 +++++++++++++++++++ .../Demos/SpatialDomains/InterfaceTest.cpp | 54 +++++++++++++--- library/SpatialDomains/CMakeLists.txt | 5 +- library/SpatialDomains/Interface.cpp | 21 ++++--- library/SpatialDomains/Interface.h | 46 +++++++++++--- 6 files changed, 164 insertions(+), 26 deletions(-) create mode 100644 library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp diff --git a/library/Demos/SpatialDomains/CMakeLists.txt b/library/Demos/SpatialDomains/CMakeLists.txt index d190ce705..94468929d 100644 --- a/library/Demos/SpatialDomains/CMakeLists.txt +++ b/library/Demos/SpatialDomains/CMakeLists.txt @@ -2,3 +2,6 @@ ADD_NEKTAR_EXECUTABLE(PartitionAnalyse COMPONENT demos DEPENDS SpatialDomains SOURCES PartitionAnalyse.cpp) ADD_NEKTAR_EXECUTABLE(InterfaceTest COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceTest.cpp) + +ADD_NEKTAR_EXECUTABLE(InterfaceDuplicateEdge + COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceDuplicateEdge.cpp) \ No newline at end of file diff --git a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp new file mode 100644 index 000000000..267143730 --- /dev/null +++ b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include + +using namespace Nektar; +using namespace Nektar::SpatialDomains; + +int main(int argc, char *argv[]) +{ + LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); + + MeshGraphSharedPtr graph = MeshGraph::Read(session); + Interfaces interface = Interfaces(session, graph); + std::map interfaces = interface.GetInterfaces(); + + for (auto &interface : interfaces) + { + int indx = interface.first; + auto interfaceProperties = interface.second; + + InterfaceEdgeMap interfaceEdgeCompositeCollection = interfaceProperties->GetInterfaceEdge(); + std::vector interfaceVertexIds; + std::vector interfaceEdgeIds; + for (auto &interfaceEdgeCompositeMap : interfaceEdgeCompositeCollection) + { + CompositeSharedPtr interfaceEdgeComposite = interfaceEdgeCompositeMap.second; + std::vector geomVec = interfaceEdgeComposite->m_geomVec; + for (GeometrySharedPtr &geom : geomVec) + { + interfaceEdgeIds.emplace_back(geom->GetGlobalID()); + interfaceVertexIds.emplace_back (geom->GetVertex(0)->GetGlobalID()); + interfaceVertexIds.emplace_back (geom->GetVertex(1)->GetGlobalID()); + } + } + + sort(interfaceVertexIds.begin(), interfaceVertexIds.end()); + interfaceVertexIds.erase(unique(interfaceVertexIds.begin(), interfaceVertexIds.end()), interfaceVertexIds.end()); + + std::vector> domains = graph->GetDomain(); + std::map movingDomain; + std::map fixedDomain; + + for (auto domain : domains) + { + if (domain == interfaceProperties->GetMovingDomain()) + { + domain = movingDomain; + } + else if (domain == interfaceProperties->GetFixedDomain()) + { + domain = fixedDomain; + } + } + + for (auto composite : movingDomain) + { + // + } + } +} diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index e18571368..64aed4474 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -3,25 +3,63 @@ // #include +#include #include #include using namespace Nektar; -using namespace SpatialDomains; +using namespace Nektar::SpatialDomains; int main(int argc, char *argv[]) { LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); - SpatialDomains::MeshGraphSharedPtr graph = SpatialDomains::MeshGraph::Read(session); - Interfaces interfaceCollection = SpatialDomains::Interfaces(session, graph); + MeshGraphSharedPtr graph = MeshGraph::Read(session); + Interfaces interfaceCollection = Interfaces(session, graph); - auto regions = interfaceCollection.GetInterfaces(); + auto interfaces = interfaceCollection.GetInterfaces(); - for (auto ®ion : regions) + for (auto &interface : interfaces) { - cout << std::to_string(region.second->GetInterfaceType()) << endl; //<--- works - // cout << std::to_string(region.second->GetAngularVel()) << endl; <--- doesn't work + int indx = interface.first; + cout << "INTERFACE INDEX: " + std::to_string(indx) << endl; + + auto interfaceProperties = interface.second; + + InterfaceType type = interfaceProperties->GetInterfaceType(); + cout << "Type: " << InterfaceTypeMap[type] << endl; + + CompositeMap movingDomainComposites = interfaceProperties->GetMovingDomain(); + for (auto &movingDomainComposite : movingDomainComposites) + { + cout << "Moving domain composite: " << movingDomainComposite.first << endl; + } + + CompositeMap fixedDomainComposites = interfaceProperties->GetFixedDomain(); + for (auto &fixedDomainComposite : fixedDomainComposites) + { + cout << "Fixed domain composite: " << fixedDomainComposite.first << endl; + } + + InterfaceEdgeMap interfaceEdgeComposites = interfaceProperties->GetInterfaceEdge(); + std::vector interfaceEdgeCompositeList; + for (auto &interfaceEdgeComposite : interfaceEdgeComposites) + { + interfaceEdgeCompositeList.emplace_back(interfaceEdgeComposite.first); + } + std::string interfaceEdgeString = ParseUtils::GenerateSeqString(interfaceEdgeCompositeList); + cout << "Interface edge composite: " << interfaceEdgeString << endl; + + if(type == eRotating) + { + cout << "Angular vel: " << std::to_string(interfaceProperties->GetAngularVel()) << endl; + + std::vector origin(3,0); + interfaceProperties->GetOrigin().GetCoords(origin[0], origin[1], origin[2]); + cout << "Origin: (" << std::to_string(origin[0]) << ", " << std::to_string(origin[1]) << ", "<< std::to_string(origin[2]) << ")" << endl; + + std::vector axis = interfaceProperties->GetAxis(); + cout << "Axis: (" << std::to_string(axis[0]) << ", " << std::to_string(axis[1]) << ", "<< std::to_string(axis[2]) << ")" << endl << endl; + } } - cout << "All read" << endl; } \ No newline at end of file diff --git a/library/SpatialDomains/CMakeLists.txt b/library/SpatialDomains/CMakeLists.txt index c4eebefa2..8a7388370 100644 --- a/library/SpatialDomains/CMakeLists.txt +++ b/library/SpatialDomains/CMakeLists.txt @@ -1,6 +1,5 @@ SET(SPATIAL_DOMAINS_SOURCES Conditions.cpp -Interface.cpp GeomFactors.cpp Geometry0D.cpp Geometry1D.cpp @@ -8,6 +7,8 @@ Geometry2D.cpp Geometry3D.cpp Geometry.cpp HexGeom.cpp +Interface.cpp + ../Demos/SpatialDomains/InterfaceDuplicateEdge.cpp MeshGraph.cpp MeshGraphXml.cpp MeshGraphXmlCompressed.cpp @@ -23,7 +24,6 @@ TriGeom.cpp SET(SPATIAL_DOMAINS_HEADERS Conditions.h -Interface.h Curve.hpp GeomFactors.h Geometry0D.h @@ -32,6 +32,7 @@ Geometry2D.h Geometry3D.h Geometry.h HexGeom.h +Interface.h MeshEntities.hpp MeshGraph.h MeshGraphXml.h diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 3a9282fb6..a4dc7cba7 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -119,11 +119,10 @@ namespace Nektar ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface composite."); - InterfaceEdgeShPtr interfaceEdge( - MemoryManager::AllocateSharedPtr()); + InterfaceEdgeMap interfaceEdge; interfaceEdgeStr = ReadTag(interfaceEdgeStr); - m_meshGraph->GetCompositeList(interfaceEdgeStr, *interfaceEdge); + m_meshGraph->GetCompositeList(interfaceEdgeStr, interfaceEdge); if (interfaceType == "R") { @@ -137,8 +136,7 @@ namespace Nektar std::vector originVec; ParseUtils::GenerateVector(originStr, originVec); - PointGeomSharedPtr origin = MemoryManager:: - AllocateSharedPtr(PointGeom(3, 0, originVec[0], originVec[1], originVec[2])); + PointGeom origin = PointGeom(3, 0, originVec[0], originVec[1], originVec[2]); std::string axisStr; err = interfaceElementTag->QueryStringAttribute("AXIS", @@ -148,7 +146,7 @@ namespace Nektar "Unable to read axis."); std::vector axis; - ParseUtils::GenerateVector(originStr, axis); + ParseUtils::GenerateVector(axisStr, axis); std::string angularVelStr; err = interfaceElementTag->QueryStringAttribute("ANGVEL", @@ -167,9 +165,18 @@ namespace Nektar m_interfaces[indx] = rotatingInterface; } + if (interfaceType == "F") + { + InterfaceShPtr fixedInterface( + MemoryManager::AllocateSharedPtr( + eFixed, movingDomain, fixedDomain, + interfaceEdge)); + + m_interfaces[indx] = fixedInterface; + } + interfaceElementTag = interfaceElementTag->NextSiblingElement(); } - // } } } diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index fa5e61a4c..f1a8d479f 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -57,8 +57,16 @@ namespace Nektar eNotDefined }; - typedef std::map InterfaceEdge; - typedef std::shared_ptr InterfaceEdgeShPtr; + const char* const InterfaceTypeMap[] = + { + "Fixed", + "Rotating", + "Sliding", + "NotDefined" + }; + + typedef std::map InterfaceEdgeMap; + typedef std::shared_ptr InterfaceEdgeShPtr; struct InterfaceBase { @@ -66,7 +74,7 @@ namespace Nektar InterfaceType type, CompositeMap movingDomain, CompositeMap fixedDomain, - InterfaceEdgeShPtr interfaceEdge): + InterfaceEdgeMap interfaceEdge): m_interfaceType(type), m_movingDomain(movingDomain), m_fixedDomain(fixedDomain), @@ -93,16 +101,36 @@ namespace Nektar return m_fixedDomain; } - InterfaceEdgeShPtr GetInterfaceEdge() const + InterfaceEdgeMap GetInterfaceEdge() const { return m_interfaceEdge; } + virtual PointGeom GetOrigin() const + { + return m_origin; + } + + virtual std::vector GetAxis() const + { + return m_axis; + } + + virtual NekDouble GetAngularVel() const + { + return m_angularVel; + } + protected: InterfaceType m_interfaceType; CompositeMap m_movingDomain; CompositeMap m_fixedDomain; - InterfaceEdgeShPtr m_interfaceEdge; + InterfaceEdgeMap m_interfaceEdge; + + private: + PointGeom m_origin; + std::vector m_axis; + NekDouble m_angularVel; }; struct RotatingInterface : public InterfaceBase @@ -111,8 +139,8 @@ namespace Nektar const LibUtilities::SessionReaderSharedPtr &pSession, const CompositeMap movingDomain, const CompositeMap fixedDomain, - const InterfaceEdgeShPtr interfaceEdge, - const PointGeomSharedPtr origin, + const InterfaceEdgeMap interfaceEdge, + const PointGeom origin, const std::vector axis, const NekDouble angularVel) : InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge), @@ -122,7 +150,7 @@ namespace Nektar { } - PointGeomSharedPtr GetOrigin() const + PointGeom GetOrigin() const { return m_origin; } @@ -137,7 +165,7 @@ namespace Nektar return m_angularVel; } - PointGeomSharedPtr m_origin; + PointGeom m_origin; std::vector m_axis; NekDouble m_angularVel; }; -- GitLab From 28b665629e3c445115953b844646c61bb102c161 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 19 Mar 2019 09:37:22 +0000 Subject: [PATCH 005/408] Finished interface duplicate & multi domain output --- .../SpatialDomains/InterfaceDuplicateEdge.cpp | 264 ++++++++++++++++-- .../Demos/SpatialDomains/InterfaceTest.cpp | 26 +- library/SpatialDomains/Geometry2D.h | 5 + library/SpatialDomains/Interface.h | 31 +- library/SpatialDomains/MeshGraphXml.cpp | 28 +- 5 files changed, 298 insertions(+), 56 deletions(-) diff --git a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp index 267143730..0b159d881 100644 --- a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp +++ b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp @@ -6,56 +6,268 @@ using namespace Nektar; using namespace Nektar::SpatialDomains; +bool ContainsElement(CompositeMap &domain, int edgeID) +{ + for (auto &comp : domain) + { + for (auto &geom : comp.second->m_geomVec) + { + if (edgeID == geom->GetGlobalID()) + { + return true; + } + } + } + + return false; +} + +std::vector +VertexToElmt(CompositeMap &domain, int vertId1, int vertId2) +{ + std::vector ret; + + for (auto &comp : domain) + { + for (auto &geom : comp.second->m_geomVec) + { + for (int i = 0; i < geom->GetNumVerts(); ++i) + { + if (geom->GetVid(i) == vertId1 || geom->GetVid(i) == vertId2) + { + ret.push_back(geom); + break; + } + } + } + } + + return ret; +} + int main(int argc, char *argv[]) { - LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); + LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance( + argc, argv); MeshGraphSharedPtr graph = MeshGraph::Read(session); - Interfaces interface = Interfaces(session, graph); - std::map interfaces = interface.GetInterfaces(); + Interfaces interfaceCollection = Interfaces(session, graph); + + std::map interfaces = interfaceCollection.GetInterfaces(); for (auto &interface : interfaces) { int indx = interface.first; auto interfaceProperties = interface.second; - InterfaceEdgeMap interfaceEdgeCompositeCollection = interfaceProperties->GetInterfaceEdge(); - std::vector interfaceVertexIds; - std::vector interfaceEdgeIds; - for (auto &interfaceEdgeCompositeMap : interfaceEdgeCompositeCollection) + auto movingDomain = interfaceProperties->GetMovingDomain(); + auto interfaceEdge = interfaceProperties->GetInterfaceEdge(); + + int maxVertId = -1; + for (auto &vert : graph->GetAllPointGeoms()) { - CompositeSharedPtr interfaceEdgeComposite = interfaceEdgeCompositeMap.second; - std::vector geomVec = interfaceEdgeComposite->m_geomVec; - for (GeometrySharedPtr &geom : geomVec) + maxVertId = std::max(maxVertId, vert.first); + } + + int maxEdgeId = -1; + for (auto &edge : graph->GetAllSegGeoms()) + { + maxEdgeId = std::max(maxEdgeId, edge.first); + } + + ++maxVertId; + ++maxEdgeId; + + // Map that stores existing renumbered vertices. + std::map vertDone; + std::map edgeDone; + std::map elementToDo; + + for (auto &comp : interfaceEdge) + { + for (auto &geom : comp.second->m_geomVec) { - interfaceEdgeIds.emplace_back(geom->GetGlobalID()); - interfaceVertexIds.emplace_back (geom->GetVertex(0)->GetGlobalID()); - interfaceVertexIds.emplace_back (geom->GetVertex(1)->GetGlobalID()); + std::cout << "Processing edge ID = " << geom->GetGlobalID() + << std::endl; + ASSERTL0(geom->GetShapeType() == LibUtilities::eSegment, + "Unexpected geometry type in composite"); + + GeometryLinkSharedPtr elmtLink = graph->GetElementsFromEdge( + std::static_pointer_cast(geom)); + + size_t numElmts = elmtLink->size(); + if (numElmts == 1) + { + continue; + } + + int vid[2] = {geom->GetVid(0), geom->GetVid(1)}; + PointGeomSharedPtr newVerts[2]; + + for (int i = 0; i < 2; ++i) + { + auto it = vertDone.find(vid[i]); + if (it == vertDone.end()) + { + // Create a new vertex + newVerts[i] = MemoryManager::AllocateSharedPtr( + *geom->GetVertex(i)); + newVerts[i]->SetGlobalID(maxVertId); + graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; + vertDone[vid[i]] = maxVertId++; + std::cout << "Replacing vert " << vid[i] << " with " + << maxVertId - 1 << std::endl; + } + else + { + newVerts[i] = graph->GetVertex(it->second); + } + } + + SegGeomSharedPtr oldEdge = std::static_pointer_cast( + geom); + + CurveSharedPtr newCurve; + if (oldEdge->GetCurve()) + { + newCurve = MemoryManager::AllocateSharedPtr( + maxEdgeId, + oldEdge->GetCurve()->m_ptype); + } + + auto newEdge = MemoryManager::AllocateSharedPtr( + maxEdgeId, newVerts[0]->GetCoordim(), newVerts, + newCurve); + std::cout << "Creating new edge " << maxEdgeId << ": " + << newVerts[0]->GetGlobalID() << " " + << newVerts[1]->GetGlobalID() << std::endl; + graph->GetAllSegGeoms()[maxEdgeId] = newEdge; + edgeDone[geom->GetGlobalID()] = newEdge; + maxEdgeId++; + + auto toProcess = VertexToElmt(movingDomain, vid[0], vid[1]); + for (auto &elementToProcess : toProcess) + { + elementToDo[elementToProcess->GetGlobalID()] = elementToProcess; + } } } - sort(interfaceVertexIds.begin(), interfaceVertexIds.end()); - interfaceVertexIds.erase(unique(interfaceVertexIds.begin(), interfaceVertexIds.end()), interfaceVertexIds.end()); - std::vector> domains = graph->GetDomain(); - std::map movingDomain; - std::map fixedDomain; - - for (auto domain : domains) + for (auto &elementMap : elementToDo) { - if (domain == interfaceProperties->GetMovingDomain()) + auto movingGeom = elementMap.second; + + cout << endl << "Looking at element: " << movingGeom->GetGlobalID() + << endl; + std::vector newEdges( + movingGeom->GetNumEdges()); + + // Loop over edges + for (int j = 0; j < newEdges.size(); ++j) { - domain = movingDomain; + auto edge = std::static_pointer_cast( + movingGeom->GetEdge(j)); + cout << "Looking at edge: " << edge->GetGlobalID() << endl; + auto edgeIt = edgeDone.find(edge->GetGlobalID()); + if (edgeIt != edgeDone.end()) + { + newEdges[j] = edgeIt->second; + cout << "Edge: " << edge->GetGlobalID() + << " has already been replaced" << endl; + continue; + } + + int edgeVids[2] = {edge->GetVid(0), edge->GetVid(1)}; + + cout << "Edge: " << edge->GetGlobalID() << " has vertices :" + << edge->GetVid(0) << " " << edge->GetVid(1) << endl; + + PointGeomSharedPtr newEdgeVerts[2]; + bool create = false; + + for (int k = 0; k < 2; ++k) + { + auto vertIt = vertDone.find(edgeVids[k]); + if (vertIt != vertDone.end()) + { + newEdgeVerts[k] = graph->GetVertex(vertIt->second); + create = true; + } + else newEdgeVerts[k] = graph->GetVertex(edgeVids[k]); + } + + cout << "New edge :" << newEdgeVerts[0]->GetGlobalID() << " " + << newEdgeVerts[1]->GetGlobalID() << endl; + + if (create) + { + auto newEdge = MemoryManager::AllocateSharedPtr( + edge->GetGlobalID(), + edge->GetVertex(0)->GetCoordim(), + newEdgeVerts, edge->GetCurve()); + graph->GetAllSegGeoms()[edge->GetGlobalID()] = newEdge; + edgeDone[edge->GetGlobalID()] = newEdge; + newEdges[j] = newEdge; + std::cout << "replacing edge " << edge->GetGlobalID() + << " old = " << edgeVids[0] << " " << edgeVids[1] + << " new = " << newEdgeVerts[0]->GetGlobalID() + << " " << newEdgeVerts[1]->GetGlobalID() + << std::endl; + } + else + { + std::cout << "Using old edge " << edge->GetGlobalID() + << " old = " << edgeVids[0] << " " << edgeVids[1] + << std::endl; + newEdges[j] = edge; + } } - else if (domain == interfaceProperties->GetFixedDomain()) + + if (movingGeom->GetShapeType() == LibUtilities::eQuadrilateral) { - domain = fixedDomain; + // Create a new quad + QuadGeomSharedPtr quad = std::static_pointer_cast( + movingGeom); + QuadGeomSharedPtr newQuad = MemoryManager::AllocateSharedPtr( + quad->GetGlobalID(), &newEdges[0], quad->GetCurve()); + graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; + std::cout << "Replacing quad " << quad->GetGlobalID() + << std::endl; + } + else if (movingGeom->GetShapeType() == LibUtilities::eTriangle) + { + // Create a new tri + TriGeomSharedPtr tri = std::static_pointer_cast( + movingGeom); + TriGeomSharedPtr newTri = MemoryManager::AllocateSharedPtr( + tri->GetGlobalID(), &newEdges[0], tri->GetCurve()); + graph->GetAllTriGeoms()[tri->GetGlobalID()] = newTri; } } - for (auto composite : movingDomain) + std::set seenVerts, seenEdges; + for (auto &comp : interfaceProperties->GetMovingDomain()) { - // + for (auto &geom : comp.second->m_geomVec) + { + auto newGeom = graph->GetGeometry2D(geom->GetGlobalID()); + for (int i = 0; i < newGeom->GetNumVerts(); ++i) + { + PointGeomSharedPtr vert = newGeom->GetVertex(i); + + if (seenVerts.find(vert->GetGlobalID()) != seenVerts.end()) + { + continue; + } +f + (*vert)(1) += 10.0; + seenVerts.insert(vert->GetGlobalID()); + } + } } } + + std::string filename = "out.xml"; + graph->WriteGeometry(filename, true); } diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index 64aed4474..96ebdf9df 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -21,27 +21,27 @@ int main(int argc, char *argv[]) for (auto &interface : interfaces) { + InterfaceShPtr movingInterface = interface.second; + auto type = movingInterface->GetInterfaceType(); int indx = interface.first; - cout << "INTERFACE INDEX: " + std::to_string(indx) << endl; - auto interfaceProperties = interface.second; + cout << "INTERFACE INDEX: " + std::to_string(indx) << endl; - InterfaceType type = interfaceProperties->GetInterfaceType(); cout << "Type: " << InterfaceTypeMap[type] << endl; - CompositeMap movingDomainComposites = interfaceProperties->GetMovingDomain(); + CompositeMap movingDomainComposites = movingInterface->GetMovingDomain(); for (auto &movingDomainComposite : movingDomainComposites) { cout << "Moving domain composite: " << movingDomainComposite.first << endl; } - CompositeMap fixedDomainComposites = interfaceProperties->GetFixedDomain(); + CompositeMap fixedDomainComposites = movingInterface->GetFixedDomain(); for (auto &fixedDomainComposite : fixedDomainComposites) { cout << "Fixed domain composite: " << fixedDomainComposite.first << endl; } - InterfaceEdgeMap interfaceEdgeComposites = interfaceProperties->GetInterfaceEdge(); + InterfaceEdgeMap interfaceEdgeComposites = movingInterface->GetInterfaceEdge(); std::vector interfaceEdgeCompositeList; for (auto &interfaceEdgeComposite : interfaceEdgeComposites) { @@ -52,14 +52,22 @@ int main(int argc, char *argv[]) if(type == eRotating) { - cout << "Angular vel: " << std::to_string(interfaceProperties->GetAngularVel()) << endl; + RotatingInterfaceShPtr movingInterface = static_pointer_cast(interface.second); + + cout << "Angular vel: " << std::to_string(movingInterface->GetAngularVel()) << endl; std::vector origin(3,0); - interfaceProperties->GetOrigin().GetCoords(origin[0], origin[1], origin[2]); + movingInterface->GetOrigin().GetCoords(origin[0], origin[1], origin[2]); cout << "Origin: (" << std::to_string(origin[0]) << ", " << std::to_string(origin[1]) << ", "<< std::to_string(origin[2]) << ")" << endl; - std::vector axis = interfaceProperties->GetAxis(); + std::vector axis = movingInterface->GetAxis(); cout << "Axis: (" << std::to_string(axis[0]) << ", " << std::to_string(axis[1]) << ", "<< std::to_string(axis[2]) << ")" << endl << endl; } + + if(type == eFixed) + { + FixedInterfaceShPtr movingInterface = static_pointer_cast(interface.second); + } + } } \ No newline at end of file diff --git a/library/SpatialDomains/Geometry2D.h b/library/SpatialDomains/Geometry2D.h index b005cb35f..fa1ae27c9 100644 --- a/library/SpatialDomains/Geometry2D.h +++ b/library/SpatialDomains/Geometry2D.h @@ -73,6 +73,11 @@ public: SPATIAL_DOMAINS_EXPORT Geometry2D(const int coordim, CurveSharedPtr curve); SPATIAL_DOMAINS_EXPORT virtual ~Geometry2D(); + SPATIAL_DOMAINS_EXPORT CurveSharedPtr GetCurve() + { + return m_curve; + } + protected: PointGeomVector m_verts; SegGeomVector m_edges; diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index f1a8d479f..5b58e4d16 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -106,21 +106,6 @@ namespace Nektar return m_interfaceEdge; } - virtual PointGeom GetOrigin() const - { - return m_origin; - } - - virtual std::vector GetAxis() const - { - return m_axis; - } - - virtual NekDouble GetAngularVel() const - { - return m_angularVel; - } - protected: InterfaceType m_interfaceType; CompositeMap m_movingDomain; @@ -170,8 +155,24 @@ namespace Nektar NekDouble m_angularVel; }; + struct FixedInterface : public InterfaceBase + { + FixedInterface( + const LibUtilities::SessionReaderSharedPtr &pSession, + const CompositeMap movingDomain, + const CompositeMap fixedDomain, + const InterfaceEdgeMap interfaceEdge, + const PointGeom origin, + const std::vector axis, + const NekDouble angularVel) + : InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge) + { + } + }; + typedef std::shared_ptr InterfaceShPtr; typedef std::shared_ptr RotatingInterfaceShPtr; + typedef std::shared_ptr FixedInterfaceShPtr; typedef std::map InterfaceCollection; diff --git a/library/SpatialDomains/MeshGraphXml.cpp b/library/SpatialDomains/MeshGraphXml.cpp index 41ab37caa..02676a970 100644 --- a/library/SpatialDomains/MeshGraphXml.cpp +++ b/library/SpatialDomains/MeshGraphXml.cpp @@ -2696,20 +2696,36 @@ void MeshGraphXml::WriteComposites(TiXmlElement *geomTag, CompositeMap &comps) } void MeshGraphXml::WriteDomain(TiXmlElement *geomTag, - vector &domain) + vector &domainVector) { TiXmlElement *domTag = new TiXmlElement("DOMAIN"); stringstream domString; + int domainIt =0; - // @todo Fix this to accomodate multi domain output + // @todo Fix this to accomodate multi domain output properly (need the domain input to be a map for ID) vector idxList; - for (auto cIt = domain[0].begin(); cIt != domain[0].end(); ++cIt) + for (CompositeMap &domain : domainVector) { - idxList.push_back(cIt->first); + TiXmlElement *c = new TiXmlElement("D"); + idxList.clear(); + stringstream s; + s << " " << "C" << "["; + + CompositeMap::iterator it = domain.begin(); + while (it != domain.end()) + { + cout << it->first << endl; + idxList.push_back(it->first); + it++; + } + + s << ParseUtils::GenerateSeqString(idxList) << "] "; + c->SetAttribute("ID", domainIt); + c->LinkEndChild(new TiXmlText(s.str())); + domTag->LinkEndChild(c); + domainIt ++; } - domString << " C[" << ParseUtils::GenerateSeqString(idxList) << "] "; - domTag->LinkEndChild(new TiXmlText(domString.str())); geomTag->LinkEndChild(domTag); } -- GitLab From 7cb6545aa1181a438423f58a452cb2ef7921a443 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 19 Mar 2019 11:07:36 +0000 Subject: [PATCH 006/408] Removed deprecated std::iterator for WriteDomain --- .../SpatialDomains/InterfaceDuplicateEdge.cpp | 30 ++++++------------- library/SpatialDomains/MeshGraphXml.cpp | 11 +++---- 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp index 0b159d881..6bb076327 100644 --- a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp +++ b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp @@ -78,9 +78,10 @@ int main(int argc, char *argv[]) ++maxVertId; ++maxEdgeId; - // Map that stores existing renumbered vertices. + // Map that stores existing renumbered geometry. std::map vertDone; std::map edgeDone; + //Map that stores elements to process for renumbered edges and points std::map elementToDo; for (auto &comp : interfaceEdge) @@ -140,7 +141,7 @@ int main(int argc, char *argv[]) newCurve); std::cout << "Creating new edge " << maxEdgeId << ": " << newVerts[0]->GetGlobalID() << " " - << newVerts[1]->GetGlobalID() << std::endl; + << newVerts[1]->GetGlobalID() << std::endl << endl; graph->GetAllSegGeoms()[maxEdgeId] = newEdge; edgeDone[geom->GetGlobalID()] = newEdge; maxEdgeId++; @@ -168,21 +169,17 @@ int main(int argc, char *argv[]) { auto edge = std::static_pointer_cast( movingGeom->GetEdge(j)); - cout << "Looking at edge: " << edge->GetGlobalID() << endl; + cout << "Looking at edge: " << edge->GetGlobalID(); auto edgeIt = edgeDone.find(edge->GetGlobalID()); if (edgeIt != edgeDone.end()) { + cout << " - already redefined to edge " << edgeIt->second->GetGlobalID() << endl; newEdges[j] = edgeIt->second; - cout << "Edge: " << edge->GetGlobalID() - << " has already been replaced" << endl; continue; } int edgeVids[2] = {edge->GetVid(0), edge->GetVid(1)}; - cout << "Edge: " << edge->GetGlobalID() << " has vertices :" - << edge->GetVid(0) << " " << edge->GetVid(1) << endl; - PointGeomSharedPtr newEdgeVerts[2]; bool create = false; @@ -193,13 +190,11 @@ int main(int argc, char *argv[]) { newEdgeVerts[k] = graph->GetVertex(vertIt->second); create = true; + cout << " - redefine edge vertex " << vertIt->first << " to "<< vertIt->second << endl; } else newEdgeVerts[k] = graph->GetVertex(edgeVids[k]); } - cout << "New edge :" << newEdgeVerts[0]->GetGlobalID() << " " - << newEdgeVerts[1]->GetGlobalID() << endl; - if (create) { auto newEdge = MemoryManager::AllocateSharedPtr( @@ -209,18 +204,11 @@ int main(int argc, char *argv[]) graph->GetAllSegGeoms()[edge->GetGlobalID()] = newEdge; edgeDone[edge->GetGlobalID()] = newEdge; newEdges[j] = newEdge; - std::cout << "replacing edge " << edge->GetGlobalID() - << " old = " << edgeVids[0] << " " << edgeVids[1] - << " new = " << newEdgeVerts[0]->GetGlobalID() - << " " << newEdgeVerts[1]->GetGlobalID() - << std::endl; } else { - std::cout << "Using old edge " << edge->GetGlobalID() - << " old = " << edgeVids[0] << " " << edgeVids[1] - << std::endl; newEdges[j] = edge; + cout << " - keep old edge vertices" << endl; } } @@ -232,7 +220,7 @@ int main(int argc, char *argv[]) QuadGeomSharedPtr newQuad = MemoryManager::AllocateSharedPtr( quad->GetGlobalID(), &newEdges[0], quad->GetCurve()); graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; - std::cout << "Replacing quad " << quad->GetGlobalID() + std::cout << "Redefining element: " << quad->GetGlobalID() << std::endl; } else if (movingGeom->GetShapeType() == LibUtilities::eTriangle) @@ -260,7 +248,7 @@ int main(int argc, char *argv[]) { continue; } -f + (*vert)(1) += 10.0; seenVerts.insert(vert->GetGlobalID()); } diff --git a/library/SpatialDomains/MeshGraphXml.cpp b/library/SpatialDomains/MeshGraphXml.cpp index 02676a970..90c382abc 100644 --- a/library/SpatialDomains/MeshGraphXml.cpp +++ b/library/SpatialDomains/MeshGraphXml.cpp @@ -2702,7 +2702,7 @@ void MeshGraphXml::WriteDomain(TiXmlElement *geomTag, stringstream domString; int domainIt =0; - // @todo Fix this to accomodate multi domain output properly (need the domain input to be a map for ID) + // @todo Fix this to accomodate multi domain output properly (need the domain input to be a map for ID instead of just incrementing domainIt++) vector idxList; for (CompositeMap &domain : domainVector) { @@ -2711,19 +2711,16 @@ void MeshGraphXml::WriteDomain(TiXmlElement *geomTag, stringstream s; s << " " << "C" << "["; - CompositeMap::iterator it = domain.begin(); - while (it != domain.end()) + for(const auto &elem : domain) { - cout << it->first << endl; - idxList.push_back(it->first); - it++; + idxList.push_back(elem.first); } s << ParseUtils::GenerateSeqString(idxList) << "] "; c->SetAttribute("ID", domainIt); c->LinkEndChild(new TiXmlText(s.str())); domTag->LinkEndChild(c); - domainIt ++; + domainIt++; } geomTag->LinkEndChild(domTag); -- GitLab From 7df23d8b731869f515bfabe65590648a1ac85655 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Wed, 27 Mar 2019 16:10:54 +0000 Subject: [PATCH 007/408] Incorporating interface in DisContField2D --- library/Demos/SpatialDomains/CMakeLists.txt | 2 +- .../SpatialDomains/InterfaceDuplicateEdge.cpp | 380 ++++++++-------- library/MultiRegions/DisContField2D.cpp | 276 +++++++++++- library/MultiRegions/DisContField2D.h | 6 + library/SpatialDomains/CMakeLists.txt | 1 - library/SpatialDomains/Interface.cpp | 406 ++++++++++++++---- library/SpatialDomains/Interface.h | 83 ++-- 7 files changed, 807 insertions(+), 347 deletions(-) diff --git a/library/Demos/SpatialDomains/CMakeLists.txt b/library/Demos/SpatialDomains/CMakeLists.txt index 94468929d..c35f39c67 100644 --- a/library/Demos/SpatialDomains/CMakeLists.txt +++ b/library/Demos/SpatialDomains/CMakeLists.txt @@ -4,4 +4,4 @@ ADD_NEKTAR_EXECUTABLE(InterfaceTest COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceTest.cpp) ADD_NEKTAR_EXECUTABLE(InterfaceDuplicateEdge - COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceDuplicateEdge.cpp) \ No newline at end of file + COMPONENT demos DEPENDS MultiRegions SOURCES InterfaceDuplicateEdge.cpp) \ No newline at end of file diff --git a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp index 6bb076327..5bc1f5fab 100644 --- a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp +++ b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp @@ -1,261 +1,245 @@ #include -#include +#include #include #include +#include +using namespace std; using namespace Nektar; -using namespace Nektar::SpatialDomains; -bool ContainsElement(CompositeMap &domain, int edgeID) +double SearchForPoint(NekDouble xs[2], SpatialDomains::SegGeomSharedPtr &seg) { - for (auto &comp : domain) + + + + Array xi(1, 0.0); + const NekDouble c1 = 1e-4, c2 = 0.9; + + auto xmap = seg->GetXmap(); + int nq = xmap->GetTotPoints(); + + Array x(nq), y(nq); + xmap->BwdTrans(seg->GetCoeffs(0), x); + xmap->BwdTrans(seg->GetCoeffs(1), y); + + Array xder(nq), yder(nq); + xmap->PhysDeriv(x, xder); + xmap->PhysDeriv(y, yder); + + Array xder2(nq), yder2(nq); + xmap->PhysDeriv(xder, xder2); + xmap->PhysDeriv(yder, yder2); + + bool opt_succeed = false; + + for (int i = 0; i < 1000; ++i) { - for (auto &geom : comp.second->m_geomVec) + + // Compute f(x_k) and its derivatives + NekDouble xc = xmap->PhysEvaluate(xi, x); + NekDouble yc = xmap->PhysEvaluate(xi, y); + + NekDouble xc_der = xmap->PhysEvaluate(xi, xder); + NekDouble yc_der = xmap->PhysEvaluate(xi, yder); + + NekDouble xc_der2 = xmap->PhysEvaluate(xi, xder2); + NekDouble yc_der2 = xmap->PhysEvaluate(xi, yder2); + + NekDouble fx = (xc - xs[0])*(xc - xs[0]) + (yc - xs[1])*(yc - xs[1]); + NekDouble fxp = 2.0 * (xc_der * (xc - xs[0]) + yc_der * (yc - xs[1])); + NekDouble fxp2 = 2.0 * (xc_der2 * (xc - xs[0]) + xc_der * xc_der + +yc_der2 * (yc - xs[1]) + yc_der * yc_der); + + std::cout <<"Gradient descent iteration = " << i << "\t xi = " << xi[0] +<< "\t fx = " << fx << "\t grad = " << fxp << "\t hess = " << fxp2 << std::endl; + + // Check for convergence + if (fx < 1e-16) { - if (edgeID == geom->GetGlobalID()) - { - return true; - } + opt_succeed = true; + break; } - } - return false; -} -std::vector -VertexToElmt(CompositeMap &domain, int vertId1, int vertId2) -{ - std::vector ret; + NekDouble gamma = 1.0; + bool conv = false; - for (auto &comp : domain) - { - for (auto &geom : comp.second->m_geomVec) + // Search direction: quasi-Newton + NekDouble pk = - fxp / fxp2; + + int l =0; + // Backtracking line search + while (gamma > 1e-10) { - for (int i = 0; i < geom->GetNumVerts(); ++i) + cout << "\tLine search iteration: " << l <<"\t gamma = " << gamma << +endl; l++; Array xi_pk(1); xi_pk[0] = xi[0] + pk * gamma; + + if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0) { - if (geom->GetVid(i) == vertId1 || geom->GetVid(i) == vertId2) - { - ret.push_back(geom); - break; - } + gamma /= 2.0; + continue; + } + + NekDouble xc_pk = xmap->PhysEvaluate(xi_pk, x); + NekDouble yc_pk = xmap->PhysEvaluate(xi_pk, y); + + NekDouble xc_der_pk = xmap->PhysEvaluate(xi_pk, xder); + NekDouble yc_der_pk = xmap->PhysEvaluate(xi_pk, yder); + + NekDouble fx_pk = (xc_pk - xs[0])*(xc_pk - xs[0]) + (yc_pk - +xs[1])*(yc_pk - xs[1]); NekDouble fxp_pk = 2.0 * (xc_der_pk * (xc_pk - xs[0]) + +yc_der_pk * (yc_pk - xs[1])); + + // Check Wolfe conditions + if (fx_pk <= fx + c1 * gamma * pk * fxp && -pk * fxp_pk <= - c2 * pk +* fxp) + { + conv = true; + break; } + + gamma /= 2.0; + } + + if (!conv) + { + opt_succeed = false; + break; } + + xi[0] += gamma * pk; + } + + if (opt_succeed) + { + return xi[0]; + } + else + { + return std::numeric_limits::max(); } +} - return ret; +double rand_float( double low, double high ) { + return ((double)rand() * (high - low)) / (double)RAND_MAX + low; } + int main(int argc, char *argv[]) { - LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance( - argc, argv); + LibUtilities::SessionReaderSharedPtr session; + LibUtilities::FieldIOSharedPtr fld; + SpatialDomains::MeshGraphSharedPtr graph; + SpatialDomains::Interfaces interfaceCollection; + MultiRegions::DisContField2DSharedPtr field; +// LibUtilities::EquationSharedPtr icond, ex_sol; +// StdRegions::ConstFactorMap factors; - MeshGraphSharedPtr graph = MeshGraph::Read(session); - Interfaces interfaceCollection = Interfaces(session, graph); + session = LibUtilities::SessionReader::CreateInstance(argc, argv); + graph = SpatialDomains::MeshGraph::Read(session); - std::map interfaces = interfaceCollection.GetInterfaces(); + interfaceCollection = SpatialDomains::Interfaces(session, graph); + auto interfaces = interfaceCollection.GetInterfaces(); + //Split interfaces for (auto &interface : interfaces) { - int indx = interface.first; auto interfaceProperties = interface.second; + interfaceProperties->SeparateGraph(graph); + } - auto movingDomain = interfaceProperties->GetMovingDomain(); - auto interfaceEdge = interfaceProperties->GetInterfaceEdge(); + fld = LibUtilities::FieldIO::CreateDefault(session); - int maxVertId = -1; - for (auto &vert : graph->GetAllPointGeoms()) - { - maxVertId = std::max(maxVertId, vert.first); - } + /* + string sessionName = session->GetSessionName(); + string outFile = sessionName + ".fld"; + unsigned int nSteps = session->GetParameter("NumSteps"); + NekDouble delta_t = session->GetParameter("TimeStep"); + NekDouble epsilon = session->GetParameter("epsilon" ); + */ - int maxEdgeId = -1; - for (auto &edge : graph->GetAllSegGeoms()) - { - maxEdgeId = std::max(maxEdgeId, edge.first); - } + //field = MemoryManager ::AllocateSharedPtr(session, graph, session->GetVariable(0)); + field = MemoryManager ::AllocateSharedPtr(); + // Write geometry + std::string filename = "out.xml"; + graph->WriteGeometry(filename, true); - ++maxVertId; - ++maxEdgeId; + // TESTS for SearchForPoint and the MoveDomain function +#if 0 + auto seg = graph->GetSegGeom(4); + seg->FillGeom(); - // Map that stores existing renumbered geometry. - std::map vertDone; - std::map edgeDone; - //Map that stores elements to process for renumbered edges and points - std::map elementToDo; + std::map foundPoints; - for (auto &comp : interfaceEdge) - { - for (auto &geom : comp.second->m_geomVec) - { - std::cout << "Processing edge ID = " << geom->GetGlobalID() - << std::endl; - ASSERTL0(geom->GetShapeType() == LibUtilities::eSegment, - "Unexpected geometry type in composite"); + for (int i = 0; i < 1000; i++) + { + NekDouble random = rand_float(1.0, 0.5); + NekDouble xs[2] = {0.5, random}; - GeometryLinkSharedPtr elmtLink = graph->GetElementsFromEdge( - std::static_pointer_cast(geom)); + auto foundPoint = SearchForPoint(xs, seg); - size_t numElmts = elmtLink->size(); - if (numElmts == 1) - { - continue; - } + foundPoints[random] = foundPoint; + } - int vid[2] = {geom->GetVid(0), geom->GetVid(1)}; - PointGeomSharedPtr newVerts[2]; + std::ofstream myfile; + myfile.open ("example.csv"); + myfile << "Random number, Found point"<< endl; + for (auto i : foundPoints) + { + myfile << i.first <<"," << i.second << endl; - for (int i = 0; i < 2; ++i) - { - auto it = vertDone.find(vid[i]); - if (it == vertDone.end()) - { - // Create a new vertex - newVerts[i] = MemoryManager::AllocateSharedPtr( - *geom->GetVertex(i)); - newVerts[i]->SetGlobalID(maxVertId); - graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; - vertDone[vid[i]] = maxVertId++; - std::cout << "Replacing vert " << vid[i] << " with " - << maxVertId - 1 << std::endl; - } - else - { - newVerts[i] = graph->GetVertex(it->second); - } - } + } + myfile.close(); - SegGeomSharedPtr oldEdge = std::static_pointer_cast( - geom); + // MOVE DOMAIN + std::set seenVerts, seenEdges; - CurveSharedPtr newCurve; - if (oldEdge->GetCurve()) - { - newCurve = MemoryManager::AllocateSharedPtr( - maxEdgeId, - oldEdge->GetCurve()->m_ptype); - } + for (auto &comp : interfaceProperties->GetMovingDomain()) + { + for (auto &geom : comp.second->m_geomVec) + { + auto newGeom = graph->GetGeometry2D(geom->GetGlobalID()); + for (int i = 0; i < newGeom->GetNumVerts(); ++i) + { + PointGeomSharedPtr vert = newGeom->GetVertex(i); - auto newEdge = MemoryManager::AllocateSharedPtr( - maxEdgeId, newVerts[0]->GetCoordim(), newVerts, - newCurve); - std::cout << "Creating new edge " << maxEdgeId << ": " - << newVerts[0]->GetGlobalID() << " " - << newVerts[1]->GetGlobalID() << std::endl << endl; - graph->GetAllSegGeoms()[maxEdgeId] = newEdge; - edgeDone[geom->GetGlobalID()] = newEdge; - maxEdgeId++; - - auto toProcess = VertexToElmt(movingDomain, vid[0], vid[1]); - for (auto &elementToProcess : toProcess) + if (seenVerts.find(vert->GetGlobalID()) != seenVerts.end()) { - elementToDo[elementToProcess->GetGlobalID()] = elementToProcess; + continue; } - } - } - - for (auto &elementMap : elementToDo) - { - auto movingGeom = elementMap.second; + (*vert)(1) += 10.0; + seenVerts.insert(vert->GetGlobalID()); - cout << endl << "Looking at element: " << movingGeom->GetGlobalID() - << endl; - std::vector newEdges( - movingGeom->GetNumEdges()); + } - // Loop over edges - for (int j = 0; j < newEdges.size(); ++j) + for (int i = 0; i < newGeom->GetNumEdges(); ++i) { - auto edge = std::static_pointer_cast( - movingGeom->GetEdge(j)); - cout << "Looking at edge: " << edge->GetGlobalID(); - auto edgeIt = edgeDone.find(edge->GetGlobalID()); - if (edgeIt != edgeDone.end()) + SegGeomSharedPtr edge = +std::static_pointer_cast(newGeom->GetEdge(i)); + + // move curve points + if (seenEdges.find(edge->GetGlobalID()) != seenEdges.end()) { - cout << " - already redefined to edge " << edgeIt->second->GetGlobalID() << endl; - newEdges[j] = edgeIt->second; continue; } - int edgeVids[2] = {edge->GetVid(0), edge->GetVid(1)}; - - PointGeomSharedPtr newEdgeVerts[2]; - bool create = false; - - for (int k = 0; k < 2; ++k) + CurveSharedPtr curve = edge->GetCurve(); + if (!curve) { - auto vertIt = vertDone.find(edgeVids[k]); - if (vertIt != vertDone.end()) - { - newEdgeVerts[k] = graph->GetVertex(vertIt->second); - create = true; - cout << " - redefine edge vertex " << vertIt->first << " to "<< vertIt->second << endl; - } - else newEdgeVerts[k] = graph->GetVertex(edgeVids[k]); + continue; } - if (create) + for (auto &pt : curve->m_points) { - auto newEdge = MemoryManager::AllocateSharedPtr( - edge->GetGlobalID(), - edge->GetVertex(0)->GetCoordim(), - newEdgeVerts, edge->GetCurve()); - graph->GetAllSegGeoms()[edge->GetGlobalID()] = newEdge; - edgeDone[edge->GetGlobalID()] = newEdge; - newEdges[j] = newEdge; + (*pt)(1) += 10.0; } - else - { - newEdges[j] = edge; - cout << " - keep old edge vertices" << endl; - } - } - - if (movingGeom->GetShapeType() == LibUtilities::eQuadrilateral) - { - // Create a new quad - QuadGeomSharedPtr quad = std::static_pointer_cast( - movingGeom); - QuadGeomSharedPtr newQuad = MemoryManager::AllocateSharedPtr( - quad->GetGlobalID(), &newEdges[0], quad->GetCurve()); - graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; - std::cout << "Redefining element: " << quad->GetGlobalID() - << std::endl; - } - else if (movingGeom->GetShapeType() == LibUtilities::eTriangle) - { - // Create a new tri - TriGeomSharedPtr tri = std::static_pointer_cast( - movingGeom); - TriGeomSharedPtr newTri = MemoryManager::AllocateSharedPtr( - tri->GetGlobalID(), &newEdges[0], tri->GetCurve()); - graph->GetAllTriGeoms()[tri->GetGlobalID()] = newTri; - } - } - - std::set seenVerts, seenEdges; - for (auto &comp : interfaceProperties->GetMovingDomain()) - { - for (auto &geom : comp.second->m_geomVec) - { - auto newGeom = graph->GetGeometry2D(geom->GetGlobalID()); - for (int i = 0; i < newGeom->GetNumVerts(); ++i) - { - PointGeomSharedPtr vert = newGeom->GetVertex(i); - - if (seenVerts.find(vert->GetGlobalID()) != seenVerts.end()) - { - continue; - } - (*vert)(1) += 10.0; - seenVerts.insert(vert->GetGlobalID()); - } + seenEdges.insert(edge->GetGlobalID()); } } } - std::string filename = "out.xml"; - graph->WriteGeometry(filename, true); +} +#endif } diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 123d45759..fe19b06fe 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -39,8 +39,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -50,6 +51,113 @@ namespace Nektar { namespace MultiRegions { + + double SearchForPoint(NekDouble xs[2], SpatialDomains::SegGeomSharedPtr &seg) + { + + Array xi(1, 0.0); + const NekDouble c1 = 1e-4, c2 = 0.9; + + auto xmap = seg->GetXmap(); + int nq = xmap->GetTotPoints(); + + Array x(nq), y(nq); + xmap->BwdTrans(seg->GetCoeffs(0), x); + xmap->BwdTrans(seg->GetCoeffs(1), y); + + Array xder(nq), yder(nq); + xmap->PhysDeriv(x, xder); + xmap->PhysDeriv(y, yder); + + Array xder2(nq), yder2(nq); + xmap->PhysDeriv(xder, xder2); + xmap->PhysDeriv(yder, yder2); + + bool opt_succeed = false; + + for (int i = 0; i < 15; ++i) + { + + // Compute f(x_k) and its derivatives + NekDouble xc = xmap->PhysEvaluate(xi, x); + NekDouble yc = xmap->PhysEvaluate(xi, y); + + NekDouble xc_der = xmap->PhysEvaluate(xi, xder); + NekDouble yc_der = xmap->PhysEvaluate(xi, yder); + + NekDouble xc_der2 = xmap->PhysEvaluate(xi, xder2); + NekDouble yc_der2 = xmap->PhysEvaluate(xi, yder2); + + NekDouble fx = (xc - xs[0])*(xc - xs[0]) + (yc - xs[1])*(yc - xs[1]); + NekDouble fxp = 2.0 * (xc_der * (xc - xs[0]) + yc_der * (yc - xs[1])); + NekDouble fxp2 = 2.0 * (xc_der2 * (xc - xs[0]) + xc_der * xc_der + yc_der2 * (yc - xs[1]) + yc_der * yc_der); + + std::cout <<"iteration = " << i << "\t xi = " << xi[0] << "\t fx = " << fx << "\t grad = " << fxp << "\t hess = " << fxp2 << std::endl; + + // Check for convergence + if (fx < 1e-16) + { + opt_succeed = true; + break; + } + + + NekDouble gamma = 1.0; + bool conv = false; + + // Search direction: quasi-Newton + NekDouble pk = - fxp / fxp2; + + // Backtracking line search + while (gamma > 1e-10) + { + Array xi_pk(1); + xi_pk[0] = xi[0] + pk * gamma; + + if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0) + { + gamma /= 2.0; + continue; + } + + NekDouble xc_pk = xmap->PhysEvaluate(xi_pk, x); + NekDouble yc_pk = xmap->PhysEvaluate(xi_pk, y); + + NekDouble xc_der_pk = xmap->PhysEvaluate(xi_pk, xder); + NekDouble yc_der_pk = xmap->PhysEvaluate(xi_pk, yder); + + NekDouble fx_pk = (xc_pk - xs[0])*(xc_pk - xs[0]) + (yc_pk - xs[1])*(yc_pk - xs[1]); + NekDouble fxp_pk = 2.0 * (xc_der_pk * (xc_pk - xs[0]) + yc_der_pk * (yc_pk - xs[1])); + + // Check Wolfe conditions + if (fx_pk <= fx + c1 * gamma * pk * fxp && -pk * fxp_pk <= - c2 * pk * fxp) + { + conv = true; + break; + } + + gamma /= 2.0; + } + + if (!conv) + { + opt_succeed = false; + break; + } + + xi[0] += gamma * pk; + } + + if (opt_succeed) + { + return xi[0]; + } + else + { + return std::numeric_limits::max(); + } + } + /** * @class DisContField2D * Abstraction of a global discontinuous two-dimensional spectral/hp @@ -116,10 +224,21 @@ namespace Nektar if (variable.compare("DefaultVar") != 0) // do not set up BCs if default variable { + SpatialDomains::Interfaces interfaceCollection(m_session, m_graph); + m_interfaces = interfaceCollection.GetInterfaces(); + for (auto &inter : m_interfaces) + { + inter.second->SeparateGraph(m_graph); + } + + m_interfaces = SpatialDomains::Interfaces().GetInterfaces(); // Blanks interface to skip code + std::string filename = "out.xml"; + m_graph->WriteGeometry(filename, true); // Write split geometry to use when creating VTU + SpatialDomains::BoundaryConditions bcs(m_session, graph2D); GenerateBoundaryConditionExpansion(graph2D, bcs, variable, DeclareCoeffPhysArrays); - + if (DeclareCoeffPhysArrays) { EvaluateBoundaryConditions(0.0, variable); @@ -432,6 +551,8 @@ namespace Nektar // Set up physical normals SetUpPhysNormals(); + + std::unordered_map traceIdToElmt; // Set up information for parallel and periodic problems. for (int i = 0; i < m_trace->GetExpSize(); ++i) @@ -443,6 +564,8 @@ namespace Nektar int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); auto pIt = m_periodicEdges.find(traceGeomId); + traceIdToElmt[traceGeomId] = i; + if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) { if (traceGeomId != min(pIt->second[0].id, traceGeomId)) @@ -457,7 +580,33 @@ namespace Nektar traceEl->GetLeftAdjacentElementEdge()); } } - + + // Loop over all interface edges and then negate edge normals + // corresponding to the 'moving' side. Keep track of both interior + // and exterior interface components. + for (auto &interface : m_interfaces) + { + for (auto id : interface.second->GetEdgeRight()) + { + auto traceEl = std::dynamic_pointer_cast< + LocalRegions::Expansion1D>( + m_trace->GetExp(traceIdToElmt[id])); + traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( + traceEl->GetLeftAdjacentElementEdge()); + m_traceEdgeRight[interface.first].push_back(traceEl); + m_interfaceEdgeRight.insert(id); + } + + for (auto id : interface.second->GetEdgeLeft()) + { + auto traceEl = std::dynamic_pointer_cast< + LocalRegions::Expansion1D>( + m_trace->GetExp(traceIdToElmt[id])); + m_traceEdgeLeft[interface.first].push_back(traceEl); + m_interfaceEdgeLeft.insert(id); + } + } + int cnt, n, e; // Identify boundary edges @@ -1259,21 +1408,33 @@ namespace Nektar bool fwd = true; + if (traceEl->GetLeftAdjacentElementEdge () == -1 || traceEl->GetRightAdjacentElementEdge() == -1) { + // Boundary edge (1 connected element). Do nothing in // serial. auto it = m_boundaryEdges.find(traceEl->GetElmtId()); - + // If the edge does not have a boundary condition set on // it, then assume it is a partition edge. if (it == m_boundaryEdges.end()) { int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); auto pIt = m_periodicEdges.find(traceGeomId); + auto intIt1 = m_interfaceEdgeLeft.find(traceEl->GetGeom()->GetGlobalID()); + auto intIt2 = m_interfaceEdgeRight.find(traceEl->GetGeom()->GetGlobalID()); - if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) + if (intIt1 != m_interfaceEdgeLeft.end()) + { + fwd = true; + } + else if (intIt2 != m_interfaceEdgeRight.end()) + { + fwd = false; + } + else if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) { fwd = traceGeomId == min(traceGeomId,pIt->second[0].id); } @@ -1454,6 +1615,111 @@ namespace Nektar Bwd[m_periodicBwdCopy[n]] = Fwd[m_periodicFwdCopy[n]]; } + // Interpolate from each side of the interface to the other. + + for (auto &interface : m_traceEdgeLeft) + { + auto &edgeOneExps = interface.second; + auto &edgeTwoExps = m_traceEdgeRight[interface.first]; + + // Edge one -> two interpolation + for (n = 0; n < edgeOneExps.size(); ++n) + { + auto elmt = edgeOneExps[n]; + int nq = elmt->GetTotPoints(); + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); + + for (int i = 0; i < nq; ++i) + { + bool found = false; + for (int m = 0; m < edgeTwoExps.size(); ++m) + { + LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; + searchEdge->GetNcoeffs(); + + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed + NekDouble xs[2] = {xc[i], yc[i]}; + auto foundPoint = SearchForPoint(xs, searchEdgeSeg); + if (foundPoint == std::numeric_limits::max()) + { + continue; + } + Array edgePhys = Fwd + m_trace->GetPhys_Offset(m); + Array foundPointArray(1, foundPoint); //Change by Ed + Bwd[m_trace->GetPhys_Offset(n) + i] = searchEdge->StdPhysEvaluate(foundPointArray, Fwd); + found = true; + break; + } + ASSERTL1(found, "Couldn't interpolate across interface"); + } + } + + // Edge two -> one interpolation + for (n = 0; n < edgeTwoExps.size(); ++n) + { + auto elmt = edgeTwoExps[n]; + int nq = elmt->GetTotPoints(); + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); + + for (int i = 0; i < nq; ++i) + { + bool found = false; + for (int m = 0; m < edgeOneExps.size(); ++m) + { + LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; + searchEdge->GetNcoeffs(); + + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed + NekDouble xs[2] = {xc[i], yc[i]}; + auto foundPoint = SearchForPoint(xs, searchEdgeSeg); + if (foundPoint == std::numeric_limits::max()) + { + continue; + } + Array edgePhys = Fwd + m_trace->GetPhys_Offset(m); + Array foundPointArray(1, foundPoint); //Change by Ed + Bwd[m_trace->GetPhys_Offset(n) + i] = searchEdge->StdPhysEvaluate(foundPointArray, Fwd); + found = true; + break; + } + ASSERTL1(found, "Couldn't interpolate across interface"); + } + } + + // Edge two -> one interpolation + for (n = 0; n < edgeTwoExps.size(); ++n) + { + auto elmt = edgeTwoExps[n]; + int nq = elmt->GetTotPoints(); + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); + + for (int i = 0; i < nq; ++i) + { + for (int m = 0; m < edgeOneExps.size(); ++m) + { + LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; + searchEdge->GetNcoeffs(); + + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed + NekDouble xs[2] = {xc[i], yc[i]}; + auto foundPoint = SearchForPoint(xs, searchEdgeSeg); + if (foundPoint == std::numeric_limits::max()) + { + continue; + } + Array edgePhys = Fwd + m_trace->GetPhys_Offset(m); + Array foundPointArray(1, foundPoint); //Change by Ed + Bwd[m_trace->GetPhys_Offset(n) + i] = searchEdge->StdPhysEvaluate(foundPointArray, Fwd); + + } + } + } + } + + // Do parallel exchange for forwards/backwards spaces. m_traceMap->UniversalTraceAssemble(Fwd); m_traceMap->UniversalTraceAssemble(Bwd); diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index d706aca67..93866a20f 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -44,6 +44,7 @@ #include #include #include +#include namespace Nektar { @@ -146,6 +147,11 @@ namespace Nektar */ Array m_bndConditions; + SpatialDomains::InterfaceCollection m_interfaces; + std::map> m_traceEdgeLeft; + std::map> m_traceEdgeRight; + std::unordered_set m_interfaceEdgeLeft, m_interfaceEdgeRight; + GlobalLinSysMapShPtr m_globalBndMat; ExpListSharedPtr m_trace; AssemblyMapDGSharedPtr m_traceMap; diff --git a/library/SpatialDomains/CMakeLists.txt b/library/SpatialDomains/CMakeLists.txt index 8a7388370..25e6a2b0c 100644 --- a/library/SpatialDomains/CMakeLists.txt +++ b/library/SpatialDomains/CMakeLists.txt @@ -8,7 +8,6 @@ Geometry3D.cpp Geometry.cpp HexGeom.cpp Interface.cpp - ../Demos/SpatialDomains/InterfaceDuplicateEdge.cpp MeshGraph.cpp MeshGraphXml.cpp MeshGraphXmlCompressed.cpp diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index a4dc7cba7..203d10d95 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -49,34 +49,16 @@ namespace Nektar const MeshGraphSharedPtr &meshGraph) : m_meshGraph(meshGraph), m_session(pSession) { - Read(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); + ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); } - Interfaces::Interfaces(void) - { - } - - Interfaces::~Interfaces(void) - { - } - - void Interfaces::Read(TiXmlElement *interfacesTag) - { - ASSERTL0(interfacesTag, "Unable to find INTERFACES tag in file."); - - if (interfacesTag) - { - ReadInterfaces(interfacesTag); - } - } - - std::string ReadTag(std::string tagStr) + std::string ReadTag(std::string &tagStr) { std::string::size_type indxBeg = tagStr.find_first_of('[') + 1; std::string::size_type indxEnd = tagStr.find_last_of(']') - 1; ASSERTL0(indxBeg <= indxEnd, - (std::string("Error reading boundary region definition:") + (std::string("Error reading interface region definition:") + tagStr).c_str()); std::string indxStr = tagStr.substr(indxBeg, indxEnd - indxBeg + 1); @@ -84,99 +66,335 @@ namespace Nektar return indxStr; } - void Interfaces::ReadInterfaces(TiXmlElement *interfacesTag) + + std::vector GetElementsFromVertex( + CompositeMap &domain, int vertId1, int vertId2) + { + std::vector ret; + for (auto &comp : domain) { - TiXmlElement *interfaceElementTag = interfacesTag->FirstChildElement(); - while(interfaceElementTag) + for (auto &geom : comp.second->m_geomVec) { - std::vector::iterator iter; - std::string interfaceType = interfaceElementTag->Value(); - - int err; //variable to check attributes are read correctly - int indx; //value that holds interface ID - err = interfaceElementTag->QueryIntAttribute("ID", &indx); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); - - std::string interfaceMovingDomainStr; - err = interfaceElementTag->QueryStringAttribute("DOMAIN", - &interfaceMovingDomainStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read moving interface domain."); - CompositeMap movingDomain = m_meshGraph->GetDomain( - stoi(ReadTag(interfaceMovingDomainStr))); - - std::string interfaceFixedDomainStr; - err = interfaceElementTag->QueryStringAttribute("FIXED", - &interfaceFixedDomainStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read fixed interface domain."); - CompositeMap fixedDomain = m_meshGraph->GetDomain( - stoi(ReadTag(interfaceFixedDomainStr))); - - std::string interfaceEdgeStr; - err = interfaceElementTag->QueryStringAttribute("INTERFACE", - &interfaceEdgeStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read interface composite."); - - InterfaceEdgeMap interfaceEdge; - - interfaceEdgeStr = ReadTag(interfaceEdgeStr); - m_meshGraph->GetCompositeList(interfaceEdgeStr, interfaceEdge); - - if (interfaceType == "R") + for (int i = 0; i < geom->GetNumVerts(); ++i) { + if (geom->GetVid(i) == vertId1 || + geom->GetVid(i) == vertId2) + { + ret.push_back(geom); + break; + } + } + } + } + return ret; + } - std::string originStr; - err = interfaceElementTag->QueryStringAttribute("ORIGIN", - &originStr); + void Interfaces::ReadInterfaces(TiXmlElement *interfaces) + { - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read origin."); + ASSERTL0(interfaces, "Unable to find INTERFACES tag in file."); - std::vector originVec; - ParseUtils::GenerateVector(originStr, originVec); - PointGeom origin = PointGeom(3, 0, originVec[0], originVec[1], originVec[2]); + TiXmlElement *interfaceElement = interfaces->FirstChildElement(); - std::string axisStr; - err = interfaceElementTag->QueryStringAttribute("AXIS", - &axisStr); + while(interfaceElement) + { + std::string interfaceType = interfaceElement->Value(); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read axis."); + int err; + int indx; - std::vector axis; - ParseUtils::GenerateVector(axisStr, axis); + err = interfaceElement->QueryIntAttribute("ID", &indx); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); - std::string angularVelStr; - err = interfaceElementTag->QueryStringAttribute("ANGVEL", - &angularVelStr); + std::string interfaceRightDomainStr; + err = interfaceElement->QueryStringAttribute("RIGHT", + &interfaceRightDomainStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read right interface domain."); + auto rightDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); + std::string interfaceLeftDomainStr; + err = interfaceElement->QueryStringAttribute("LEFT", + &interfaceLeftDomainStr); ASSERTL0(err == TIXML_SUCCESS, - "Unable to read angular velocity."); + "Unable to read left interface domain."); + auto leftDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceLeftDomainStr))); + + + std::string interfaceEdgeStr; + int interfaceErr = interfaceElement->QueryStringAttribute("INTERFACE", + &interfaceEdgeStr); + map interfaceEdge; + if(interfaceErr == TIXML_SUCCESS) + { + std::string indxStr = ReadTag(interfaceEdgeStr); + m_meshGraph->GetCompositeList(indxStr, interfaceEdge); + } + + std::string leftEdgeStr; + int leftEdgeErr = interfaceElement->QueryStringAttribute("LEFTEDGE", + &leftEdgeStr); + map leftEdge; + if(leftEdgeErr == TIXML_SUCCESS) + { + std::string indxStr = ReadTag(leftEdgeStr); + m_meshGraph->GetCompositeList(indxStr, leftEdge); + } + + std::string rightEdgeStr; + int rightEdgeErr = interfaceElement->QueryStringAttribute("RIGHTEDGE", + &rightEdgeStr); + map rightEdge; + if(rightEdgeErr == TIXML_SUCCESS) + { + std::string indxStr = ReadTag(rightEdgeStr); + m_meshGraph->GetCompositeList(indxStr, rightEdge); + } + + if(interfaceErr == TIXML_SUCCESS) + { + ASSERTL0(leftEdgeErr !=TIXML_SUCCESS && rightEdgeErr !=TIXML_SUCCESS, + "Choose to define either INTERFACE or both LEFTEDGE " + "and RIGHTEDGE.") + } + else if(leftEdgeErr ==TIXML_SUCCESS && rightEdgeErr ==TIXML_SUCCESS) + { + ASSERTL0(interfaceErr !=TIXML_SUCCESS, + "Choose to define either INTERFACE or both LEFTEDGE " + "and RIGHTEDGE.") + } + else + { + ASSERTL0((interfaceErr + 1) * (leftEdgeErr +1) * (rightEdgeErr +1 ) == 1, + "Choose to define either INTERFACE or both LEFTEDGE " + "and RIGHTEDGE.") + } + + if (interfaceType == "R") + { + + std::string originStr; + err = interfaceElement->QueryStringAttribute("ORIGIN", + &originStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read origin."); + std::vector originVec; + ParseUtils::GenerateVector(originStr, originVec); + auto origin = PointGeom(3, 0, originVec[0], originVec[1], originVec[2]); + + std::string axisStr; + err = interfaceElement->QueryStringAttribute("AXIS", + &axisStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read axis."); + std::vector axis; + ParseUtils::GenerateVector(axisStr, axis); + + std::string angularVelStr; + err = interfaceElement->QueryStringAttribute("ANGVEL", + &angularVelStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read angular velocity."); + + NekDouble angularVel = stod(angularVelStr); + + InterfaceShPtr rotatingInterface( + MemoryManager::AllocateSharedPtr( + rightDomain, leftDomain, interfaceEdge, + origin, axis, angularVel)); - NekDouble angularVel = stod(angularVelStr); + m_interfaces[indx] = rotatingInterface; + } - InterfaceShPtr rotatingInterface( - MemoryManager::AllocateSharedPtr( - m_session, movingDomain, fixedDomain, - interfaceEdge, origin, axis, angularVel)); + interfaceElement = interfaceElement->NextSiblingElement(); + } + } + + void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) + { - m_interfaces[indx] = rotatingInterface; + auto rightDomain = GetRightDomain(); + auto interfaceEdge = GetInterfaceEdge(); + + int maxVertId = -1; + for (auto &vert : graph->GetAllPointGeoms()) + { + maxVertId = std::max(maxVertId, vert.first); } - if (interfaceType == "F") + int maxEdgeId = -1; + for (auto &edge : graph->GetAllSegGeoms()) { - InterfaceShPtr fixedInterface( - MemoryManager::AllocateSharedPtr( - eFixed, movingDomain, fixedDomain, - interfaceEdge)); + maxEdgeId = std::max(maxEdgeId, edge.first); + } + + ++maxVertId; + ++maxEdgeId; + + // Map that stores existing renumbered geometry. + std::map vertDone; + std::map edgeDone; + //Map that stores elements to process for renumbered edges and points + std::map elementToDo; - m_interfaces[indx] = fixedInterface; + CurveMap &curvedEdges = graph->GetCurvedEdges(); + + for (auto &comp : interfaceEdge) + { + for (auto &geom : comp.second->m_geomVec) + { + ASSERTL0(geom->GetShapeType() == LibUtilities::eSegment, + "Unexpected geometry type in composite"); + + GeometryLinkSharedPtr elmtLink = graph->GetElementsFromEdge( + std::static_pointer_cast(geom)); + + size_t numElmts = elmtLink->size(); + if (numElmts == 1) + { + continue; + } + + int vid[2] = {geom->GetVid(0), geom->GetVid(1)}; + PointGeomSharedPtr newVerts[2]; + + for (int i = 0; i < 2; ++i) + { + auto it = vertDone.find(vid[i]); + if (it == vertDone.end()) + { + // Create a new vertex + newVerts[i] = MemoryManager::AllocateSharedPtr( + *geom->GetVertex(i)); + newVerts[i]->SetGlobalID(maxVertId); + graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; + vertDone[vid[i]] = maxVertId++; + } + else + { + newVerts[i] = graph->GetVertex( + it->second); + } + } + + SegGeomSharedPtr oldEdge = std::static_pointer_cast( + geom); + + CurveSharedPtr newCurve; + if (oldEdge->GetCurve()) + { + newCurve = MemoryManager::AllocateSharedPtr( + maxEdgeId, + oldEdge->GetCurve()->m_ptype); + + for (auto &pt : oldEdge->GetCurve()->m_points) + { + newCurve->m_points.push_back( + MemoryManager::AllocateSharedPtr( + *pt)); + } + + curvedEdges[maxEdgeId] = newCurve; + } + + auto newEdge = MemoryManager::AllocateSharedPtr( + maxEdgeId, newVerts[0]->GetCoordim(), newVerts, + newCurve); + + m_leftEdge.push_back(oldEdge->GetGlobalID()); + m_rightEdge.push_back(maxEdgeId); + + graph->GetAllSegGeoms()[maxEdgeId] = newEdge; + edgeDone[geom->GetGlobalID()] = newEdge; + maxEdgeId++; + + auto toProcess = + GetElementsFromVertex(rightDomain, vid[0], vid[1]); + for (auto &elementToProcess : toProcess) + { + elementToDo[elementToProcess->GetGlobalID()] = elementToProcess; + } + } } - interfaceElementTag = interfaceElementTag->NextSiblingElement(); - } - } + + for (auto &elementMap : elementToDo) + { + auto rightGeom = elementMap.second; + + std::vector newEdges( + rightGeom->GetNumEdges()); + + // Loop over edges + for (int j = 0; j < newEdges.size(); ++j) + { + auto edge = std::static_pointer_cast( + rightGeom->GetEdge(j)); + auto edgeIt = edgeDone.find(edge->GetGlobalID()); + if (edgeIt != edgeDone.end()) + { + newEdges[j] = edgeIt->second; + continue; + } + + int edgeVids[2] = {edge->GetVid(0), edge->GetVid(1)}; + + PointGeomSharedPtr newEdgeVerts[2]; + bool create = false; + + for (int k = 0; k < 2; ++k) + { + auto vertIt = vertDone.find(edgeVids[k]); + if (vertIt != vertDone.end()) + { + newEdgeVerts[k] = graph->GetVertex( + vertIt->second); + create = true; + } + else + newEdgeVerts[k] = graph->GetVertex( + edgeVids[k]); + } + + if (create) + { + auto newEdge = MemoryManager::AllocateSharedPtr( + edge->GetGlobalID(), + edge->GetVertex(0)->GetCoordim(), + newEdgeVerts, edge->GetCurve()); + graph->GetAllSegGeoms()[edge->GetGlobalID()] = newEdge; + edgeDone[edge->GetGlobalID()] = newEdge; + newEdges[j] = newEdge; + } + else + { + newEdges[j] = edge; + } + } + + if (rightGeom->GetShapeType() == + LibUtilities::eQuadrilateral) + { + // Create a new quad + QuadGeomSharedPtr quad = std::static_pointer_cast( + rightGeom); + QuadGeomSharedPtr newQuad = MemoryManager::AllocateSharedPtr( + quad->GetGlobalID(), &newEdges[0], + quad->GetCurve()); + graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; + } + else if (rightGeom->GetShapeType() == + LibUtilities::eTriangle) + { + // Create a new tri + TriGeomSharedPtr tri = std::static_pointer_cast( + rightGeom); + TriGeomSharedPtr newTri = MemoryManager::AllocateSharedPtr( + tri->GetGlobalID(), &newEdges[0], + tri->GetCurve()); + graph->GetAllTriGeoms()[tri->GetGlobalID()] = newTri; + } + } + }; } } diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 5b58e4d16..d1ba32f0f 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -54,7 +54,6 @@ namespace Nektar eFixed, eRotating, eSliding, - eNotDefined }; const char* const InterfaceTypeMap[] = @@ -65,70 +64,73 @@ namespace Nektar "NotDefined" }; - typedef std::map InterfaceEdgeMap; - typedef std::shared_ptr InterfaceEdgeShPtr; - struct InterfaceBase { InterfaceBase( InterfaceType type, - CompositeMap movingDomain, - CompositeMap fixedDomain, - InterfaceEdgeMap interfaceEdge): + CompositeMap rightDomain, + CompositeMap leftDomain, + std::map interfaceEdge): m_interfaceType(type), - m_movingDomain(movingDomain), - m_fixedDomain(fixedDomain), + m_rightDomain(rightDomain), + m_leftDomain(leftDomain), m_interfaceEdge(interfaceEdge) { } - virtual ~InterfaceBase() - {}; - InterfaceType GetInterfaceType() const { return m_interfaceType; } - CompositeMap GetMovingDomain() const + CompositeMap GetRightDomain() const { - return m_movingDomain; + return m_rightDomain; } - CompositeMap GetFixedDomain() const + CompositeMap GetLeftDomain() const { - return m_fixedDomain; + return m_leftDomain; } - InterfaceEdgeMap GetInterfaceEdge() const + CompositeMap GetInterfaceEdge() const { return m_interfaceEdge; } + std::vector const &GetEdgeLeft() const + { + return m_leftEdge; + } + + std::vector const &GetEdgeRight() const + { + return m_rightEdge; + } + + void SeparateGraph(MeshGraphSharedPtr &graph); + protected: InterfaceType m_interfaceType; - CompositeMap m_movingDomain; - CompositeMap m_fixedDomain; - InterfaceEdgeMap m_interfaceEdge; + CompositeMap m_rightDomain; + CompositeMap m_leftDomain; + std::vector m_leftEdge; + std::vector m_rightEdge; + CompositeMap m_interfaceEdge; - private: - PointGeom m_origin; - std::vector m_axis; - NekDouble m_angularVel; }; struct RotatingInterface : public InterfaceBase { RotatingInterface( - const LibUtilities::SessionReaderSharedPtr &pSession, - const CompositeMap movingDomain, - const CompositeMap fixedDomain, - const InterfaceEdgeMap interfaceEdge, + const CompositeMap rightDomain, + const CompositeMap leftDomain, + const std::map interfaceEdge, const PointGeom origin, const std::vector axis, const NekDouble angularVel) - : InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge), + : InterfaceBase(eRotating, rightDomain, leftDomain, interfaceEdge), m_origin(origin), m_axis(axis), m_angularVel(angularVel) @@ -150,30 +152,15 @@ namespace Nektar return m_angularVel; } - PointGeom m_origin; + protected: + PointGeom m_origin; std::vector m_axis; NekDouble m_angularVel; }; - struct FixedInterface : public InterfaceBase - { - FixedInterface( - const LibUtilities::SessionReaderSharedPtr &pSession, - const CompositeMap movingDomain, - const CompositeMap fixedDomain, - const InterfaceEdgeMap interfaceEdge, - const PointGeom origin, - const std::vector axis, - const NekDouble angularVel) - : InterfaceBase(eRotating, movingDomain, fixedDomain, interfaceEdge) - { - } - }; typedef std::shared_ptr InterfaceShPtr; typedef std::shared_ptr RotatingInterfaceShPtr; - typedef std::shared_ptr FixedInterfaceShPtr; - typedef std::map InterfaceCollection; @@ -185,8 +172,7 @@ namespace Nektar const LibUtilities::SessionReaderSharedPtr &pSession, const MeshGraphSharedPtr &meshGraph); - SPATIAL_DOMAINS_EXPORT Interfaces(void); - SPATIAL_DOMAINS_EXPORT ~Interfaces(void); + SPATIAL_DOMAINS_EXPORT Interfaces() = default; const InterfaceCollection &GetInterfaces(void) const { @@ -206,6 +192,7 @@ namespace Nektar void Read(TiXmlElement *interfaceTag); void ReadInterfaces(TiXmlElement *interfaceTag); }; + } } -- GitLab From 1123fa333a87a773fdcb394573a4776831b18955 Mon Sep 17 00:00:00 2001 From: David Moxey Date: Wed, 27 Mar 2019 18:04:20 +0000 Subject: [PATCH 008/408] Fixes to actually use split graph within ExpList --- library/MultiRegions/DisContField2D.cpp | 18 ++++++------------ library/MultiRegions/DisContField2D.h | 1 - library/MultiRegions/ExpList2D.cpp | 14 ++++++++++++++ library/MultiRegions/ExpList2D.h | 3 +++ library/SpatialDomains/Interface.cpp | 16 ++++++++++++++++ library/SpatialDomains/MeshGraph.cpp | 3 +++ library/SpatialDomains/MeshPartitionScotch.cpp | 4 ++-- 7 files changed, 44 insertions(+), 15 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index fe19b06fe..9d93aca23 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -92,7 +92,7 @@ namespace Nektar NekDouble fxp = 2.0 * (xc_der * (xc - xs[0]) + yc_der * (yc - xs[1])); NekDouble fxp2 = 2.0 * (xc_der2 * (xc - xs[0]) + xc_der * xc_der + yc_der2 * (yc - xs[1]) + yc_der * yc_der); - std::cout <<"iteration = " << i << "\t xi = " << xi[0] << "\t fx = " << fx << "\t grad = " << fxp << "\t hess = " << fxp2 << std::endl; + //std::cout <<"iteration = " << i << "\t xi = " << xi[0] << "\t fx = " << fx << "\t grad = " << fxp << "\t hess = " << fxp2 << std::endl; // Check for convergence if (fx < 1e-16) @@ -224,17 +224,6 @@ namespace Nektar if (variable.compare("DefaultVar") != 0) // do not set up BCs if default variable { - SpatialDomains::Interfaces interfaceCollection(m_session, m_graph); - m_interfaces = interfaceCollection.GetInterfaces(); - for (auto &inter : m_interfaces) - { - inter.second->SeparateGraph(m_graph); - } - - m_interfaces = SpatialDomains::Interfaces().GetInterfaces(); // Blanks interface to skip code - std::string filename = "out.xml"; - m_graph->WriteGeometry(filename, true); // Write split geometry to use when creating VTU - SpatialDomains::BoundaryConditions bcs(m_session, graph2D); GenerateBoundaryConditionExpansion(graph2D, bcs, variable, DeclareCoeffPhysArrays); @@ -537,6 +526,7 @@ namespace Nektar //adjoining elements which do not lie in a plane. for (int i = 0; i < m_exp->size(); ++i) { + std::cout << "ELMT " << i << ": "; for (int j = 0; j < (*m_exp)[i]->GetNedges(); ++j) { LocalRegions::Expansion2DSharedPtr exp2d = @@ -546,7 +536,10 @@ namespace Nektar LocalRegions::ExpansionSharedPtr exp = elmtToTrace[i][j];; exp2d->SetEdgeExp (j, exp1d); exp1d->SetAdjacentElementExp(j, exp2d); + std::cout << " " << j << "<->" << exp1d->GetGeom()->GetGlobalID(); } + + std::cout << std::endl; } // Set up physical normals @@ -586,6 +579,7 @@ namespace Nektar // and exterior interface components. for (auto &interface : m_interfaces) { + std::cout << "what" << std::endl; for (auto id : interface.second->GetEdgeRight()) { auto traceEl = std::dynamic_pointer_cast< diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 93866a20f..1cb7fad24 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -147,7 +147,6 @@ namespace Nektar */ Array m_bndConditions; - SpatialDomains::InterfaceCollection m_interfaces; std::map> m_traceEdgeLeft; std::map> m_traceEdgeRight; std::unordered_set m_interfaceEdgeLeft, m_interfaceEdgeRight; diff --git a/library/MultiRegions/ExpList2D.cpp b/library/MultiRegions/ExpList2D.cpp index ccc032140..f884e3e1d 100644 --- a/library/MultiRegions/ExpList2D.cpp +++ b/library/MultiRegions/ExpList2D.cpp @@ -139,6 +139,20 @@ namespace Nektar { SetExpType(e2D); + // Split up our mesh graph along interfaces if necessary. + SpatialDomains::Interfaces interfaceCollection(m_session, m_graph); + m_interfaces = interfaceCollection.GetInterfaces(); + for (auto &inter : m_interfaces) + { + inter.second->SeparateGraph(m_graph); + } + + std::string filename = "out.xml"; + m_graph->WriteGeometry(filename, true); // Write split geometry to use when creating VTU + + // Re-read expansion maps to break our expansions appropriately! + m_graph->ReadExpansions(); + int elmtid=0; LocalRegions::TriExpSharedPtr tri; LocalRegions::NodalTriExpSharedPtr Ntri; diff --git a/library/MultiRegions/ExpList2D.h b/library/MultiRegions/ExpList2D.h index 7309ccfc4..f8f54033c 100644 --- a/library/MultiRegions/ExpList2D.h +++ b/library/MultiRegions/ExpList2D.h @@ -40,6 +40,7 @@ #include #include #include +#include namespace Nektar { @@ -133,6 +134,8 @@ namespace Nektar MULTI_REGIONS_EXPORT virtual ~ExpList2D(); protected: + SpatialDomains::InterfaceCollection m_interfaces; + /// Upwind the \a Fwd and \a Bwd states based on the one- /// dimensional normal velocity field given by \a Vn. MULTI_REGIONS_EXPORT void v_Upwind( diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 203d10d95..bb526d670 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -372,6 +372,7 @@ namespace Nektar } } + GeometrySharedPtr newGeom; if (rightGeom->GetShapeType() == LibUtilities::eQuadrilateral) { @@ -382,6 +383,7 @@ namespace Nektar quad->GetGlobalID(), &newEdges[0], quad->GetCurve()); graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; + newGeom = newQuad; } else if (rightGeom->GetShapeType() == LibUtilities::eTriangle) @@ -393,6 +395,20 @@ namespace Nektar tri->GetGlobalID(), &newEdges[0], tri->GetCurve()); graph->GetAllTriGeoms()[tri->GetGlobalID()] = newTri; + newGeom = newTri; + } + + // Replace this geometry in any composites. + for (auto &comp : graph->GetComposites()) + { + for (int n = 0; n < comp.second->m_geomVec.size(); ++n) + { + if (comp.second->m_geomVec[n]->GetGlobalID() == newGeom->GetGlobalID() && + comp.second->m_geomVec[n]->GetShapeType() == newGeom->GetShapeType()) + { + comp.second->m_geomVec[n] = newGeom; + } + } } } }; diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index 52a443530..f693a6141 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -2499,6 +2499,9 @@ ExpansionMapShPtr MeshGraph::SetUpExpansionMap(void) void MeshGraph::ReadExpansions() { + // Hack? + m_expansionMapShPtrMap.clear();; + // Find the Expansions tag TiXmlElement *expansionTypes = m_session->GetElement("NEKTAR/EXPANSIONS"); ASSERTL0(expansionTypes, "Unable to find EXPANSIONS tag in file."); diff --git a/library/SpatialDomains/MeshPartitionScotch.cpp b/library/SpatialDomains/MeshPartitionScotch.cpp index 27a72b366..cc11c8581 100644 --- a/library/SpatialDomains/MeshPartitionScotch.cpp +++ b/library/SpatialDomains/MeshPartitionScotch.cpp @@ -132,7 +132,7 @@ namespace SpatialDomains // If no communication load data provided if (vsize2 == NULL) { if (PartGraph2 (n, xadj, adjncy, vwgt2, NULL, numflag, nparts, - part, SCOTCH_STRATDEFAULT, 0.01) != 0) + part, SCOTCH_STRATQUALITY, 0.01) != 0) return; } @@ -173,7 +173,7 @@ namespace SpatialDomains } o = PartGraph2 (n, xadj, adjncy, vwgt2, edlotax + baseval, numflag, - nparts, part, SCOTCH_STRATDEFAULT, 0.01); + nparts, part, SCOTCH_STRATQUALITY, 0.01); free (edlotax + baseval); -- GitLab From 3d123e37f0fc43da18cab4b204ff3bcd0092ceef Mon Sep 17 00:00:00 2001 From: David Moxey Date: Wed, 27 Mar 2019 22:45:43 +0000 Subject: [PATCH 009/408] Fix, working version for the quad code --- library/MultiRegions/DisContField2D.cpp | 79 +++++++++++-------------- library/SpatialDomains/Interface.cpp | 3 + 2 files changed, 36 insertions(+), 46 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 9d93aca23..dbbcbbf8d 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -579,12 +579,13 @@ namespace Nektar // and exterior interface components. for (auto &interface : m_interfaces) { - std::cout << "what" << std::endl; for (auto id : interface.second->GetEdgeRight()) { auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( m_trace->GetExp(traceIdToElmt[id])); + std::cout << "Negating normal on edge " << traceEl->GetGeom()->GetGlobalID() << std::endl; + std::cout << "Connect to elmt " << traceEl->GetLeftAdjacentElementExp()->GetGeom()->GetGlobalID() << " edge " << traceEl->GetLeftAdjacentElementEdge() << std::endl; traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( traceEl->GetLeftAdjacentElementEdge()); m_traceEdgeRight[interface.first].push_back(traceEl); @@ -601,6 +602,22 @@ namespace Nektar } } + for (auto &it : m_traceEdgeLeft) + { + std::cout << "LEFT EDGES: "; + for (int i = 0; i < m_traceEdgeLeft[it.first].size(); ++i) + { + std::cout << m_traceEdgeLeft[it.first][i]->GetGeom()->GetGlobalID() << " "; + } + + std::cout << std::endl << "RIGHT EDGES: "; + for (int i = 0; i < m_traceEdgeRight[it.first].size(); ++i) + { + std::cout << m_traceEdgeRight[it.first][i]->GetGeom()->GetGlobalID() << " "; + } + } + std::cout << std::endl; + int cnt, n, e; // Identify boundary edges @@ -1422,10 +1439,12 @@ namespace Nektar if (intIt1 != m_interfaceEdgeLeft.end()) { + std::cout << "ELMT " << n << " EDGE " << e << " left adjacent" << std::endl; fwd = true; } else if (intIt2 != m_interfaceEdgeRight.end()) { + std::cout << "ELMT " << n << " EDGE " << e << " right adjacent" << std::endl; fwd = false; } else if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) @@ -1504,7 +1523,7 @@ namespace Nektar // Basis definition on each element LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); - if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange) + if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) { // blocked routine @@ -1550,7 +1569,6 @@ namespace Nektar field + phys_offset, e_tmp = Bwd + offset); } - } } } @@ -1610,13 +1628,12 @@ namespace Nektar } // Interpolate from each side of the interface to the other. - for (auto &interface : m_traceEdgeLeft) { auto &edgeOneExps = interface.second; auto &edgeTwoExps = m_traceEdgeRight[interface.first]; - // Edge one -> two interpolation + // Edge two -> one interpolation for (n = 0; n < edgeOneExps.size(); ++n) { auto elmt = edgeOneExps[n]; @@ -1630,8 +1647,6 @@ namespace Nektar for (int m = 0; m < edgeTwoExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; - searchEdge->GetNcoeffs(); - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed NekDouble xs[2] = {xc[i], yc[i]}; auto foundPoint = SearchForPoint(xs, searchEdgeSeg); @@ -1639,17 +1654,19 @@ namespace Nektar { continue; } - Array edgePhys = Fwd + m_trace->GetPhys_Offset(m); + Array edgePhys = Bwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); Array foundPointArray(1, foundPoint); //Change by Ed - Bwd[m_trace->GetPhys_Offset(n) + i] = searchEdge->StdPhysEvaluate(foundPointArray, Fwd); + Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); found = true; + //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl;s + //std::cout << "COPYING BWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; break; } ASSERTL1(found, "Couldn't interpolate across interface"); } } - // Edge two -> one interpolation + // Edge one -> two interpolation for (n = 0; n < edgeTwoExps.size(); ++n) { auto elmt = edgeTwoExps[n]; @@ -1663,8 +1680,6 @@ namespace Nektar for (int m = 0; m < edgeOneExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; - searchEdge->GetNcoeffs(); - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed NekDouble xs[2] = {xc[i], yc[i]}; auto foundPoint = SearchForPoint(xs, searchEdgeSeg); @@ -1672,48 +1687,20 @@ namespace Nektar { continue; } - Array edgePhys = Fwd + m_trace->GetPhys_Offset(m); + Array edgePhys = Fwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); Array foundPointArray(1, foundPoint); //Change by Ed - Bwd[m_trace->GetPhys_Offset(n) + i] = searchEdge->StdPhysEvaluate(foundPointArray, Fwd); + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); + //std::cout << "(" << xc[i] << "," << yc[i] << ") -> " << searchEdge->StdPhysEvaluate(foundPointArray, edgePhys) << std::endl; + // std::cout << "1->2 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; + //std::cout << "COPYING FWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; found = true; break; } ASSERTL1(found, "Couldn't interpolate across interface"); } } - - // Edge two -> one interpolation - for (n = 0; n < edgeTwoExps.size(); ++n) - { - auto elmt = edgeTwoExps[n]; - int nq = elmt->GetTotPoints(); - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - - for (int i = 0; i < nq; ++i) - { - for (int m = 0; m < edgeOneExps.size(); ++m) - { - LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; - searchEdge->GetNcoeffs(); - - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed - NekDouble xs[2] = {xc[i], yc[i]}; - auto foundPoint = SearchForPoint(xs, searchEdgeSeg); - if (foundPoint == std::numeric_limits::max()) - { - continue; - } - Array edgePhys = Fwd + m_trace->GetPhys_Offset(m); - Array foundPointArray(1, foundPoint); //Change by Ed - Bwd[m_trace->GetPhys_Offset(n) + i] = searchEdge->StdPhysEvaluate(foundPointArray, Fwd); - - } - } - } } - // Do parallel exchange for forwards/backwards spaces. m_traceMap->UniversalTraceAssemble(Fwd); m_traceMap->UniversalTraceAssemble(Bwd); @@ -1745,7 +1732,7 @@ namespace Nektar Array &outarray) { LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); - if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange) + if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) { Vmath::Zero(outarray.num_elements(), outarray, 1); diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index bb526d670..d212c4ac3 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -266,9 +266,12 @@ namespace Nektar // Create a new vertex newVerts[i] = MemoryManager::AllocateSharedPtr( *geom->GetVertex(i)); + if (abs((*newVerts[i])(1)-0.5) < 1e-8) + (*newVerts[i])(1) += 0.1; newVerts[i]->SetGlobalID(maxVertId); graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; vertDone[vid[i]] = maxVertId++; + } else { -- GitLab From 3caf06c3d7b936eaf0b56d763fca878617a2445b Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 29 Mar 2019 13:55:15 +0000 Subject: [PATCH 010/408] Initial provided non-conformal mesh --- library/MultiRegions/DisContField2D.cpp | 18 +++--- library/SpatialDomains/Interface.cpp | 45 ++++++++++----- library/SpatialDomains/Interface.h | 75 ++++++++++++++++++++----- 3 files changed, 99 insertions(+), 39 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index dbbcbbf8d..aa5fec233 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -579,20 +579,18 @@ namespace Nektar // and exterior interface components. for (auto &interface : m_interfaces) { - for (auto id : interface.second->GetEdgeRight()) + for (int id : interface.second->GetEdgeRightVector()) { auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( m_trace->GetExp(traceIdToElmt[id])); + std::cout << "Negating normal on edge " << traceEl->GetGeom()->GetGlobalID() << std::endl; - std::cout << "Connect to elmt " << traceEl->GetLeftAdjacentElementExp()->GetGeom()->GetGlobalID() << " edge " << traceEl->GetLeftAdjacentElementEdge() << std::endl; - traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( - traceEl->GetLeftAdjacentElementEdge()); m_traceEdgeRight[interface.first].push_back(traceEl); m_interfaceEdgeRight.insert(id); } - for (auto id : interface.second->GetEdgeLeft()) + for (int id : interface.second->GetEdgeLeftVector()) { auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( @@ -1647,7 +1645,7 @@ namespace Nektar for (int m = 0; m < edgeTwoExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); NekDouble xs[2] = {xc[i], yc[i]}; auto foundPoint = SearchForPoint(xs, searchEdgeSeg); if (foundPoint == std::numeric_limits::max()) @@ -1655,10 +1653,10 @@ namespace Nektar continue; } Array edgePhys = Bwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); - Array foundPointArray(1, foundPoint); //Change by Ed + Array foundPointArray(1, foundPoint); Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); found = true; - //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl;s + //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; //std::cout << "COPYING BWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; break; } @@ -1680,7 +1678,7 @@ namespace Nektar for (int m = 0; m < edgeOneExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); NekDouble xs[2] = {xc[i], yc[i]}; auto foundPoint = SearchForPoint(xs, searchEdgeSeg); if (foundPoint == std::numeric_limits::max()) @@ -1688,7 +1686,7 @@ namespace Nektar continue; } Array edgePhys = Fwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); - Array foundPointArray(1, foundPoint); //Change by Ed + Array foundPointArray(1, foundPoint); Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); //std::cout << "(" << xc[i] << "," << yc[i] << ") -> " << searchEdge->StdPhysEvaluate(foundPointArray, edgePhys) << std::endl; // std::cout << "1->2 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index d212c4ac3..fee43632c 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -49,7 +49,10 @@ namespace Nektar const MeshGraphSharedPtr &meshGraph) : m_meshGraph(meshGraph), m_session(pSession) { - ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); + if(m_session->DefinesElement("NEKTAR/CONDITIONS/INTERFACES")) + { + ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); + } } std::string ReadTag(std::string &tagStr) @@ -107,14 +110,14 @@ namespace Nektar ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); std::string interfaceRightDomainStr; - err = interfaceElement->QueryStringAttribute("RIGHT", + err = interfaceElement->QueryStringAttribute("RIGHTDOMAIN", &interfaceRightDomainStr); ASSERTL0(err == TIXML_SUCCESS, "Unable to read right interface domain."); auto rightDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); std::string interfaceLeftDomainStr; - err = interfaceElement->QueryStringAttribute("LEFT", + err = interfaceElement->QueryStringAttribute("LEFTDOMAIN", &interfaceLeftDomainStr); ASSERTL0(err == TIXML_SUCCESS, "Unable to read left interface domain."); @@ -139,6 +142,7 @@ namespace Nektar { std::string indxStr = ReadTag(leftEdgeStr); m_meshGraph->GetCompositeList(indxStr, leftEdge); + cout << leftEdgeStr << endl; } std::string rightEdgeStr; @@ -149,15 +153,16 @@ namespace Nektar { std::string indxStr = ReadTag(rightEdgeStr); m_meshGraph->GetCompositeList(indxStr, rightEdge); + cout << rightEdgeStr << endl; } - if(interfaceErr == TIXML_SUCCESS) + /*if(interfaceErr == TIXML_SUCCESS) { ASSERTL0(leftEdgeErr !=TIXML_SUCCESS && rightEdgeErr !=TIXML_SUCCESS, "Choose to define either INTERFACE or both LEFTEDGE " "and RIGHTEDGE.") } - else if(leftEdgeErr ==TIXML_SUCCESS && rightEdgeErr ==TIXML_SUCCESS) + else if(leftEdgeErr == TIXML_SUCCESS && rightEdgeErr == TIXML_SUCCESS) { ASSERTL0(interfaceErr !=TIXML_SUCCESS, "Choose to define either INTERFACE or both LEFTEDGE " @@ -168,7 +173,7 @@ namespace Nektar ASSERTL0((interfaceErr + 1) * (leftEdgeErr +1) * (rightEdgeErr +1 ) == 1, "Choose to define either INTERFACE or both LEFTEDGE " "and RIGHTEDGE.") - } + }*/ if (interfaceType == "R") { @@ -198,12 +203,25 @@ namespace Nektar NekDouble angularVel = stod(angularVelStr); - InterfaceShPtr rotatingInterface( - MemoryManager::AllocateSharedPtr( - rightDomain, leftDomain, interfaceEdge, - origin, axis, angularVel)); + if (interfaceErr == TIXML_SUCCESS) + { + InterfaceShPtr rotatingInterface( + MemoryManager:: + AllocateSharedPtr(leftDomain, rightDomain, + interfaceEdge, origin, + axis, angularVel)); + m_interfaces[indx] = rotatingInterface; + } + else + { + InterfaceShPtr rotatingInterface( + MemoryManager:: + AllocateSharedPtr(leftDomain, rightDomain, + leftEdge, rightEdge, origin, + axis, angularVel)); + m_interfaces[indx] = rotatingInterface; + } - m_interfaces[indx] = rotatingInterface; } interfaceElement = interfaceElement->NextSiblingElement(); @@ -212,7 +230,6 @@ namespace Nektar void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) { - auto rightDomain = GetRightDomain(); auto interfaceEdge = GetInterfaceEdge(); @@ -304,8 +321,8 @@ namespace Nektar maxEdgeId, newVerts[0]->GetCoordim(), newVerts, newCurve); - m_leftEdge.push_back(oldEdge->GetGlobalID()); - m_rightEdge.push_back(maxEdgeId); + m_leftEdgeVector.push_back(oldEdge->GetGlobalID()); + m_rightEdgeVector.push_back(maxEdgeId); graph->GetAllSegGeoms()[maxEdgeId] = newEdge; edgeDone[geom->GetGlobalID()] = newEdge; diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index d1ba32f0f..dfbff355e 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -53,7 +53,7 @@ namespace Nektar { eFixed, eRotating, - eSliding, + eSliding }; const char* const InterfaceTypeMap[] = @@ -68,17 +68,41 @@ namespace Nektar { InterfaceBase( InterfaceType type, - CompositeMap rightDomain, CompositeMap leftDomain, + CompositeMap rightDomain, std::map interfaceEdge): m_interfaceType(type), - m_rightDomain(rightDomain), m_leftDomain(leftDomain), + m_rightDomain(rightDomain), m_interfaceEdge(interfaceEdge) { } + InterfaceBase( + InterfaceType type, + CompositeMap leftDomain, + CompositeMap rightDomain, + CompositeMap leftEdge, + CompositeMap rightEdge): + m_interfaceType(type), + m_leftDomain(leftDomain), + m_rightDomain(rightDomain), + m_leftEdge(leftEdge), + m_rightEdge(rightEdge) + + { + for (auto &it : m_leftEdge) + { + m_leftEdgeVector.push_back(it.first); + } + + for (auto &it : m_rightEdge) + { + m_rightEdgeVector.push_back(it.first); + } + } + InterfaceType GetInterfaceType() const { return m_interfaceType; @@ -99,41 +123,62 @@ namespace Nektar return m_interfaceEdge; } - std::vector const &GetEdgeLeft() const + std::vector const &GetEdgeLeftVector() const { - return m_leftEdge; + return m_leftEdgeVector; } - std::vector const &GetEdgeRight() const + std::vector const &GetEdgeRightVector() const { - return m_rightEdge; + return m_rightEdgeVector; } void SeparateGraph(MeshGraphSharedPtr &graph); protected: - InterfaceType m_interfaceType; - CompositeMap m_rightDomain; - CompositeMap m_leftDomain; - std::vector m_leftEdge; - std::vector m_rightEdge; - CompositeMap m_interfaceEdge; + InterfaceType m_interfaceType; + CompositeMap m_leftDomain; + CompositeMap m_rightDomain; + CompositeMap m_leftEdge; + CompositeMap m_rightEdge; + std::vector m_leftEdgeVector; + std::vector m_rightEdgeVector; + CompositeMap m_interfaceEdge; }; struct RotatingInterface : public InterfaceBase { RotatingInterface( - const CompositeMap rightDomain, const CompositeMap leftDomain, + const CompositeMap rightDomain, const std::map interfaceEdge, const PointGeom origin, const std::vector axis, const NekDouble angularVel) - : InterfaceBase(eRotating, rightDomain, leftDomain, interfaceEdge), + : InterfaceBase(eRotating, leftDomain, rightDomain, interfaceEdge), m_origin(origin), m_axis(axis), m_angularVel(angularVel) + + + { + } + + RotatingInterface( + const CompositeMap leftDomain, + const CompositeMap rightDomain, + const std::map leftEdge, + const std::map rightEdge, + const PointGeom origin, + const std::vector axis, + const NekDouble angularVel) + : InterfaceBase(eRotating, leftDomain, rightDomain, leftEdge, rightEdge), + m_origin(origin), + m_axis(axis), + m_angularVel(angularVel) + + { } -- GitLab From 8e5c2416e5f85f135f3b3672edbd9983ec2424d2 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 4 Apr 2019 13:36:48 +0100 Subject: [PATCH 011/408] Revert "Initial provided non-conformal mesh" This reverts commit 3caf06c3d7b936eaf0b56d763fca878617a2445b. --- library/MultiRegions/DisContField2D.cpp | 18 +++--- library/SpatialDomains/Interface.cpp | 45 +++++---------- library/SpatialDomains/Interface.h | 75 +++++-------------------- 3 files changed, 39 insertions(+), 99 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index aa5fec233..dbbcbbf8d 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -579,18 +579,20 @@ namespace Nektar // and exterior interface components. for (auto &interface : m_interfaces) { - for (int id : interface.second->GetEdgeRightVector()) + for (auto id : interface.second->GetEdgeRight()) { auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( m_trace->GetExp(traceIdToElmt[id])); - std::cout << "Negating normal on edge " << traceEl->GetGeom()->GetGlobalID() << std::endl; + std::cout << "Connect to elmt " << traceEl->GetLeftAdjacentElementExp()->GetGeom()->GetGlobalID() << " edge " << traceEl->GetLeftAdjacentElementEdge() << std::endl; + traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( + traceEl->GetLeftAdjacentElementEdge()); m_traceEdgeRight[interface.first].push_back(traceEl); m_interfaceEdgeRight.insert(id); } - for (int id : interface.second->GetEdgeLeftVector()) + for (auto id : interface.second->GetEdgeLeft()) { auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( @@ -1645,7 +1647,7 @@ namespace Nektar for (int m = 0; m < edgeTwoExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed NekDouble xs[2] = {xc[i], yc[i]}; auto foundPoint = SearchForPoint(xs, searchEdgeSeg); if (foundPoint == std::numeric_limits::max()) @@ -1653,10 +1655,10 @@ namespace Nektar continue; } Array edgePhys = Bwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); - Array foundPointArray(1, foundPoint); + Array foundPointArray(1, foundPoint); //Change by Ed Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); found = true; - //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; + //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl;s //std::cout << "COPYING BWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; break; } @@ -1678,7 +1680,7 @@ namespace Nektar for (int m = 0; m < edgeOneExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); + SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed NekDouble xs[2] = {xc[i], yc[i]}; auto foundPoint = SearchForPoint(xs, searchEdgeSeg); if (foundPoint == std::numeric_limits::max()) @@ -1686,7 +1688,7 @@ namespace Nektar continue; } Array edgePhys = Fwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); - Array foundPointArray(1, foundPoint); + Array foundPointArray(1, foundPoint); //Change by Ed Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); //std::cout << "(" << xc[i] << "," << yc[i] << ") -> " << searchEdge->StdPhysEvaluate(foundPointArray, edgePhys) << std::endl; // std::cout << "1->2 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index fee43632c..d212c4ac3 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -49,10 +49,7 @@ namespace Nektar const MeshGraphSharedPtr &meshGraph) : m_meshGraph(meshGraph), m_session(pSession) { - if(m_session->DefinesElement("NEKTAR/CONDITIONS/INTERFACES")) - { - ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); - } + ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); } std::string ReadTag(std::string &tagStr) @@ -110,14 +107,14 @@ namespace Nektar ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); std::string interfaceRightDomainStr; - err = interfaceElement->QueryStringAttribute("RIGHTDOMAIN", + err = interfaceElement->QueryStringAttribute("RIGHT", &interfaceRightDomainStr); ASSERTL0(err == TIXML_SUCCESS, "Unable to read right interface domain."); auto rightDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); std::string interfaceLeftDomainStr; - err = interfaceElement->QueryStringAttribute("LEFTDOMAIN", + err = interfaceElement->QueryStringAttribute("LEFT", &interfaceLeftDomainStr); ASSERTL0(err == TIXML_SUCCESS, "Unable to read left interface domain."); @@ -142,7 +139,6 @@ namespace Nektar { std::string indxStr = ReadTag(leftEdgeStr); m_meshGraph->GetCompositeList(indxStr, leftEdge); - cout << leftEdgeStr << endl; } std::string rightEdgeStr; @@ -153,16 +149,15 @@ namespace Nektar { std::string indxStr = ReadTag(rightEdgeStr); m_meshGraph->GetCompositeList(indxStr, rightEdge); - cout << rightEdgeStr << endl; } - /*if(interfaceErr == TIXML_SUCCESS) + if(interfaceErr == TIXML_SUCCESS) { ASSERTL0(leftEdgeErr !=TIXML_SUCCESS && rightEdgeErr !=TIXML_SUCCESS, "Choose to define either INTERFACE or both LEFTEDGE " "and RIGHTEDGE.") } - else if(leftEdgeErr == TIXML_SUCCESS && rightEdgeErr == TIXML_SUCCESS) + else if(leftEdgeErr ==TIXML_SUCCESS && rightEdgeErr ==TIXML_SUCCESS) { ASSERTL0(interfaceErr !=TIXML_SUCCESS, "Choose to define either INTERFACE or both LEFTEDGE " @@ -173,7 +168,7 @@ namespace Nektar ASSERTL0((interfaceErr + 1) * (leftEdgeErr +1) * (rightEdgeErr +1 ) == 1, "Choose to define either INTERFACE or both LEFTEDGE " "and RIGHTEDGE.") - }*/ + } if (interfaceType == "R") { @@ -203,25 +198,12 @@ namespace Nektar NekDouble angularVel = stod(angularVelStr); - if (interfaceErr == TIXML_SUCCESS) - { - InterfaceShPtr rotatingInterface( - MemoryManager:: - AllocateSharedPtr(leftDomain, rightDomain, - interfaceEdge, origin, - axis, angularVel)); - m_interfaces[indx] = rotatingInterface; - } - else - { - InterfaceShPtr rotatingInterface( - MemoryManager:: - AllocateSharedPtr(leftDomain, rightDomain, - leftEdge, rightEdge, origin, - axis, angularVel)); - m_interfaces[indx] = rotatingInterface; - } + InterfaceShPtr rotatingInterface( + MemoryManager::AllocateSharedPtr( + rightDomain, leftDomain, interfaceEdge, + origin, axis, angularVel)); + m_interfaces[indx] = rotatingInterface; } interfaceElement = interfaceElement->NextSiblingElement(); @@ -230,6 +212,7 @@ namespace Nektar void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) { + auto rightDomain = GetRightDomain(); auto interfaceEdge = GetInterfaceEdge(); @@ -321,8 +304,8 @@ namespace Nektar maxEdgeId, newVerts[0]->GetCoordim(), newVerts, newCurve); - m_leftEdgeVector.push_back(oldEdge->GetGlobalID()); - m_rightEdgeVector.push_back(maxEdgeId); + m_leftEdge.push_back(oldEdge->GetGlobalID()); + m_rightEdge.push_back(maxEdgeId); graph->GetAllSegGeoms()[maxEdgeId] = newEdge; edgeDone[geom->GetGlobalID()] = newEdge; diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index dfbff355e..d1ba32f0f 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -53,7 +53,7 @@ namespace Nektar { eFixed, eRotating, - eSliding + eSliding, }; const char* const InterfaceTypeMap[] = @@ -68,41 +68,17 @@ namespace Nektar { InterfaceBase( InterfaceType type, - CompositeMap leftDomain, CompositeMap rightDomain, + CompositeMap leftDomain, std::map interfaceEdge): m_interfaceType(type), - m_leftDomain(leftDomain), m_rightDomain(rightDomain), + m_leftDomain(leftDomain), m_interfaceEdge(interfaceEdge) { } - InterfaceBase( - InterfaceType type, - CompositeMap leftDomain, - CompositeMap rightDomain, - CompositeMap leftEdge, - CompositeMap rightEdge): - m_interfaceType(type), - m_leftDomain(leftDomain), - m_rightDomain(rightDomain), - m_leftEdge(leftEdge), - m_rightEdge(rightEdge) - - { - for (auto &it : m_leftEdge) - { - m_leftEdgeVector.push_back(it.first); - } - - for (auto &it : m_rightEdge) - { - m_rightEdgeVector.push_back(it.first); - } - } - InterfaceType GetInterfaceType() const { return m_interfaceType; @@ -123,62 +99,41 @@ namespace Nektar return m_interfaceEdge; } - std::vector const &GetEdgeLeftVector() const + std::vector const &GetEdgeLeft() const { - return m_leftEdgeVector; + return m_leftEdge; } - std::vector const &GetEdgeRightVector() const + std::vector const &GetEdgeRight() const { - return m_rightEdgeVector; + return m_rightEdge; } void SeparateGraph(MeshGraphSharedPtr &graph); protected: - InterfaceType m_interfaceType; - CompositeMap m_leftDomain; - CompositeMap m_rightDomain; - CompositeMap m_leftEdge; - CompositeMap m_rightEdge; - std::vector m_leftEdgeVector; - std::vector m_rightEdgeVector; - CompositeMap m_interfaceEdge; + InterfaceType m_interfaceType; + CompositeMap m_rightDomain; + CompositeMap m_leftDomain; + std::vector m_leftEdge; + std::vector m_rightEdge; + CompositeMap m_interfaceEdge; }; struct RotatingInterface : public InterfaceBase { RotatingInterface( - const CompositeMap leftDomain, const CompositeMap rightDomain, + const CompositeMap leftDomain, const std::map interfaceEdge, const PointGeom origin, const std::vector axis, const NekDouble angularVel) - : InterfaceBase(eRotating, leftDomain, rightDomain, interfaceEdge), + : InterfaceBase(eRotating, rightDomain, leftDomain, interfaceEdge), m_origin(origin), m_axis(axis), m_angularVel(angularVel) - - - { - } - - RotatingInterface( - const CompositeMap leftDomain, - const CompositeMap rightDomain, - const std::map leftEdge, - const std::map rightEdge, - const PointGeom origin, - const std::vector axis, - const NekDouble angularVel) - : InterfaceBase(eRotating, leftDomain, rightDomain, leftEdge, rightEdge), - m_origin(origin), - m_axis(axis), - m_angularVel(angularVel) - - { } -- GitLab From dd1bd0cb0e1d490541cf91b33017bd382eeef7dd Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 5 Apr 2019 16:50:06 +0100 Subject: [PATCH 012/408] Add pre-separated mesh & linear FindDistance func --- library/MultiRegions/DisContField2D.cpp | 207 +++++++----------------- library/SpatialDomains/Geometry.cpp | 8 + library/SpatialDomains/Geometry.h | 11 ++ library/SpatialDomains/Interface.cpp | 27 ++-- library/SpatialDomains/Interface.h | 59 +++++-- library/SpatialDomains/SegGeom.cpp | 182 ++++++++++++++++++--- library/SpatialDomains/SegGeom.h | 4 + 7 files changed, 303 insertions(+), 195 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index dbbcbbf8d..8d2e06e3e 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -52,112 +52,6 @@ namespace Nektar namespace MultiRegions { - double SearchForPoint(NekDouble xs[2], SpatialDomains::SegGeomSharedPtr &seg) - { - - Array xi(1, 0.0); - const NekDouble c1 = 1e-4, c2 = 0.9; - - auto xmap = seg->GetXmap(); - int nq = xmap->GetTotPoints(); - - Array x(nq), y(nq); - xmap->BwdTrans(seg->GetCoeffs(0), x); - xmap->BwdTrans(seg->GetCoeffs(1), y); - - Array xder(nq), yder(nq); - xmap->PhysDeriv(x, xder); - xmap->PhysDeriv(y, yder); - - Array xder2(nq), yder2(nq); - xmap->PhysDeriv(xder, xder2); - xmap->PhysDeriv(yder, yder2); - - bool opt_succeed = false; - - for (int i = 0; i < 15; ++i) - { - - // Compute f(x_k) and its derivatives - NekDouble xc = xmap->PhysEvaluate(xi, x); - NekDouble yc = xmap->PhysEvaluate(xi, y); - - NekDouble xc_der = xmap->PhysEvaluate(xi, xder); - NekDouble yc_der = xmap->PhysEvaluate(xi, yder); - - NekDouble xc_der2 = xmap->PhysEvaluate(xi, xder2); - NekDouble yc_der2 = xmap->PhysEvaluate(xi, yder2); - - NekDouble fx = (xc - xs[0])*(xc - xs[0]) + (yc - xs[1])*(yc - xs[1]); - NekDouble fxp = 2.0 * (xc_der * (xc - xs[0]) + yc_der * (yc - xs[1])); - NekDouble fxp2 = 2.0 * (xc_der2 * (xc - xs[0]) + xc_der * xc_der + yc_der2 * (yc - xs[1]) + yc_der * yc_der); - - //std::cout <<"iteration = " << i << "\t xi = " << xi[0] << "\t fx = " << fx << "\t grad = " << fxp << "\t hess = " << fxp2 << std::endl; - - // Check for convergence - if (fx < 1e-16) - { - opt_succeed = true; - break; - } - - - NekDouble gamma = 1.0; - bool conv = false; - - // Search direction: quasi-Newton - NekDouble pk = - fxp / fxp2; - - // Backtracking line search - while (gamma > 1e-10) - { - Array xi_pk(1); - xi_pk[0] = xi[0] + pk * gamma; - - if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0) - { - gamma /= 2.0; - continue; - } - - NekDouble xc_pk = xmap->PhysEvaluate(xi_pk, x); - NekDouble yc_pk = xmap->PhysEvaluate(xi_pk, y); - - NekDouble xc_der_pk = xmap->PhysEvaluate(xi_pk, xder); - NekDouble yc_der_pk = xmap->PhysEvaluate(xi_pk, yder); - - NekDouble fx_pk = (xc_pk - xs[0])*(xc_pk - xs[0]) + (yc_pk - xs[1])*(yc_pk - xs[1]); - NekDouble fxp_pk = 2.0 * (xc_der_pk * (xc_pk - xs[0]) + yc_der_pk * (yc_pk - xs[1])); - - // Check Wolfe conditions - if (fx_pk <= fx + c1 * gamma * pk * fxp && -pk * fxp_pk <= - c2 * pk * fxp) - { - conv = true; - break; - } - - gamma /= 2.0; - } - - if (!conv) - { - opt_succeed = false; - break; - } - - xi[0] += gamma * pk; - } - - if (opt_succeed) - { - return xi[0]; - } - else - { - return std::numeric_limits::max(); - } - } - /** * @class DisContField2D * Abstraction of a global discontinuous two-dimensional spectral/hp @@ -579,8 +473,9 @@ namespace Nektar // and exterior interface components. for (auto &interface : m_interfaces) { - for (auto id : interface.second->GetEdgeRight()) + for (auto &iter : interface.second->GetEdgeRight()) { + int id = iter.first; auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( m_trace->GetExp(traceIdToElmt[id])); @@ -592,8 +487,9 @@ namespace Nektar m_interfaceEdgeRight.insert(id); } - for (auto id : interface.second->GetEdgeLeft()) + for (auto &iter : interface.second->GetEdgeLeft()) { + int id = iter.first; auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( m_trace->GetExp(traceIdToElmt[id])); @@ -619,11 +515,11 @@ namespace Nektar std::cout << std::endl; int cnt, n, e; - + // Identify boundary edges for (cnt = 0, n = 0; n < m_bndCondExpansions.num_elements(); ++n) { - if (m_bndConditions[n]->GetBoundaryConditionType() != + if (m_bndConditions[n]->GetBoundaryConditionType() != SpatialDomains::ePeriodic) { for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) @@ -634,7 +530,7 @@ namespace Nektar cnt += m_bndCondExpansions[n]->GetExpSize(); } } - + // Set up information for periodic boundary conditions. std::unordered_map > perEdgeToExpMap; for (cnt = n = 0; n < m_exp->size(); ++n) @@ -732,12 +628,12 @@ namespace Nektar } } } - + m_locTraceToTraceMap = MemoryManager:: AllocateSharedPtr(*this, m_trace, elmtToTrace, m_leftAdjacentEdges); } - + /** * For each boundary region, checks that the types and number of * boundary expansions in that region match. @@ -780,7 +676,7 @@ namespace Nektar * * According to their boundary region, the separate segmental boundary * expansions are bundled together in an object of the class - * MultiRegions#ExpList1D. + * MultiRegions#ExpList1D. * * \param graph2D A mesh, containing information about the domain and * the spectral/hp element expansion. @@ -863,7 +759,7 @@ namespace Nektar m_graph->GetBndRegionOrdering(); SpatialDomains::CompositeMap compMap = m_graph->GetComposites(); - + // Unique collection of pairs of periodic composites (i.e. if // composites 1 and 2 are periodic then this map will contain either // the pair (1,2) or (2,1) but not both). @@ -871,11 +767,11 @@ namespace Nektar map> allVerts; set locVerts; map> allEdges; - + int region1ID, region2ID, i, j, k, cnt; SpatialDomains::BoundaryConditionShPtr locBCond; - // Set up a set of all local verts and edges. + // Set up a set of all local verts and edges. for(i = 0; i < (*m_exp).size(); ++i) { for(j = 0; j < (*m_exp)[i]->GetNverts(); ++j) @@ -916,7 +812,7 @@ namespace Nektar cId1 = bndRegOrder.find(region1ID)->second[0]; cId2 = bndRegOrder.find(region2ID)->second[0]; } - + ASSERTL0(it.second->size() == 1, "Boundary region "+boost::lexical_cast( region1ID)+" should only contain 1 composite."); @@ -925,7 +821,7 @@ namespace Nektar SpatialDomains::CompositeSharedPtr c = it.second->begin()->second; vector tmpOrder; - + for (i = 0; i < c->m_geomVec.size(); ++i) { SpatialDomains::SegGeomSharedPtr segGeom = @@ -953,7 +849,7 @@ namespace Nektar { tmpOrder.push_back(c->m_geomVec[i]->GetGlobalID()); } - + vector vertList(2); vertList[0] = segGeom->GetVid(0); vertList[1] = segGeom->GetVid(1); @@ -964,7 +860,7 @@ namespace Nektar { compOrder[it.second->begin()->first] = tmpOrder; } - + // See if we already have either region1 or region2 stored in // perComps map. if (perComps.count(cId1) == 0) @@ -1074,7 +970,7 @@ namespace Nektar } vComm->AllReduce(vertIds, LibUtilities::ReduceSum); - + // For simplicity's sake create a map of edge id -> orientation. map orientMap; map > vertMap; @@ -1110,7 +1006,7 @@ namespace Nektar } vertMap[edgeIds[i]] = verts; } - + // Go through list of composites and figure out which edges are // parallel from original ordering in session file. This includes // composites which are not necessarily on this process. @@ -1122,7 +1018,7 @@ namespace Nektar // vertices are copied into m_periodicVerts at the end of the // function. PeriodicMap periodicVerts; - + for (auto &cIt : perComps) { SpatialDomains::CompositeSharedPtr c[2]; @@ -1222,7 +1118,7 @@ namespace Nektar orientMap[ids[i]] == orientMap[ids[other]] ? StdRegions::eBackwards : StdRegions::eForwards; - + PeriodicEntity ent(ids [other], o, local[other]); m_periodicEdges[ids[i]].push_back(ent); @@ -1374,7 +1270,7 @@ namespace Nektar auto perIt2 = periodicVerts.find(perIt.second[i].id); ASSERTL0(perIt2 != periodicVerts.end(), "Couldn't find periodic vertex."); - + for (j = 0; j < perIt2->second.size(); ++j) { if (perIt2->second[j].id == perIt.first) @@ -1413,11 +1309,11 @@ namespace Nektar bool DisContField2D::IsLeftAdjacentEdge(const int n, const int e) { - LocalRegions::Expansion1DSharedPtr traceEl = + LocalRegions::Expansion1DSharedPtr traceEl = m_traceMap->GetElmtToTrace()[n][e]-> as(); - - + + bool fwd = true; if (traceEl->GetLeftAdjacentElementEdge () == -1 || @@ -1470,10 +1366,10 @@ namespace Nektar { ASSERTL2( false, "Unconnected trace element!" ); } - + return fwd; } - + // Construct the two trace vectors of the inner and outer // trace solution from the field contained in m_phys, where // the Weak dirichlet boundary conditions are listed in the @@ -1489,7 +1385,7 @@ namespace Nektar * @brief This method extracts the "forward" and "backward" trace data * from the array @a field and puts the data into output vectors @a Fwd * and @a Bwd. - * + * * We first define the convention which defines "forwards" and * "backwards". First an association is made between the edge of each * element and its corresponding edge in the trace space using the @@ -1497,7 +1393,7 @@ namespace Nektar * right-adjacent to this trace edge (see * Expansion1D::GetLeftAdjacentElementExp). Boundary edges are always * left-adjacent since left-adjacency is populated first. - * + * * If the element is left-adjacent we extract the edge trace data from * @a field into the forward trace space @a Fwd; otherwise, we place it * in the backwards trace space @a Bwd. In this way, we form a unique @@ -1525,7 +1421,6 @@ namespace Nektar LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) { - // blocked routine Array edgevals(m_locTraceToTraceMap-> GetNLocTracePts()); @@ -1572,13 +1467,13 @@ namespace Nektar } } } - + // Fill boundary conditions into missing elements int id1, id2 = 0; - + for (cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n) { - if (m_bndConditions[n]->GetBoundaryConditionType() == + if (m_bndConditions[n]->GetBoundaryConditionType() == SpatialDomains::eDirichlet) { for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) @@ -1591,12 +1486,12 @@ namespace Nektar &(m_bndCondExpansions[n]->GetPhys())[id1], 1, &Bwd[id2], 1); } - + cnt += e; } - else if (m_bndConditions[n]->GetBoundaryConditionType() == - SpatialDomains::eNeumann || - m_bndConditions[n]->GetBoundaryConditionType() == + else if (m_bndConditions[n]->GetBoundaryConditionType() == + SpatialDomains::eNeumann || + m_bndConditions[n]->GetBoundaryConditionType() == SpatialDomains::eRobin) { for(e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) @@ -1610,7 +1505,7 @@ namespace Nektar m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt+e)); Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1); } - + cnt += e; } else if (m_bndConditions[n]->GetBoundaryConditionType() != @@ -1620,7 +1515,7 @@ namespace Nektar "Method not set up for this boundary condition."); } } - + // Copy any periodic boundary conditions. for (n = 0; n < m_periodicFwdCopy.size(); ++n) { @@ -1648,9 +1543,13 @@ namespace Nektar { LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed - NekDouble xs[2] = {xc[i], yc[i]}; - auto foundPoint = SearchForPoint(xs, searchEdgeSeg); - if (foundPoint == std::numeric_limits::max()) + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + + NekDouble foundPoint; + NekDouble dist = searchEdgeSeg->FindDistance(xs, foundPoint); + if (dist > 1e-8) { continue; } @@ -1658,11 +1557,11 @@ namespace Nektar Array foundPointArray(1, foundPoint); //Change by Ed Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); found = true; - //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl;s + //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; //std::cout << "COPYING BWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; break; } - ASSERTL1(found, "Couldn't interpolate across interface"); + ASSERTL1(found, "Couldn't interpolate across interface from right to left (bwd)"); } } @@ -1681,9 +1580,13 @@ namespace Nektar { LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed - NekDouble xs[2] = {xc[i], yc[i]}; - auto foundPoint = SearchForPoint(xs, searchEdgeSeg); - if (foundPoint == std::numeric_limits::max()) + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + + NekDouble foundPoint; + NekDouble dist = searchEdgeSeg->FindDistance(xs, foundPoint); + if (dist > 1e-8) { continue; } @@ -1696,7 +1599,7 @@ namespace Nektar found = true; break; } - ASSERTL1(found, "Couldn't interpolate across interface"); + ASSERTL1(found, "Couldn't interpolate across interface from left to right (fwd)"); } } } diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index 2c629b3b3..af910f634 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -257,6 +257,14 @@ bool Geometry::v_ContainsPoint(const Array &gloCoord, return false; } +NekDouble Geometry::v_FindDistance(const Array &xs, + NekDouble &xi) +{ + NEKERROR(ErrorUtil::efatal, + "This function has not been defined for this geometry"); + return false; +} + /** * @copydoc Geometry::GetVertexEdgeMap() */ diff --git a/library/SpatialDomains/Geometry.h b/library/SpatialDomains/Geometry.h index 2ab3ff9ff..92e30aafb 100644 --- a/library/SpatialDomains/Geometry.h +++ b/library/SpatialDomains/Geometry.h @@ -155,6 +155,9 @@ public: Array &Lcoords); SPATIAL_DOMAINS_EXPORT inline NekDouble GetCoord( const int i, const Array &Lcoord); + SPATIAL_DOMAINS_EXPORT inline NekDouble FindDistance( + const Array &xs, + NekDouble &xi); //--------------------------------------- // Misc. helper functions @@ -220,6 +223,8 @@ protected: const Array &Lcoord); virtual NekDouble v_GetLocCoords(const Array &coords, Array &Lcoords); + virtual NekDouble v_FindDistance(const Array &xs, + NekDouble &xi); virtual int v_GetVertexEdgeMap(int i, int j) const; virtual int v_GetVertexFaceMap(int i, int j) const; @@ -540,6 +545,12 @@ inline NekDouble Geometry::GetCoord(const int i, return v_GetCoord(i, Lcoord); } +inline NekDouble Geometry::FindDistance(const Array &xs, + NekDouble &xi) +{ + return v_FindDistance(xs, xi); +} + /** * @brief Returns the standard element edge IDs that are connected to a given * vertex. diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index d212c4ac3..d57b85e17 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -107,14 +107,14 @@ namespace Nektar ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); std::string interfaceRightDomainStr; - err = interfaceElement->QueryStringAttribute("RIGHT", + err = interfaceElement->QueryStringAttribute("RIGHTDOMAIN", &interfaceRightDomainStr); ASSERTL0(err == TIXML_SUCCESS, "Unable to read right interface domain."); auto rightDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); std::string interfaceLeftDomainStr; - err = interfaceElement->QueryStringAttribute("LEFT", + err = interfaceElement->QueryStringAttribute("LEFTDOMAIN", &interfaceLeftDomainStr); ASSERTL0(err == TIXML_SUCCESS, "Unable to read left interface domain."); @@ -172,7 +172,6 @@ namespace Nektar if (interfaceType == "R") { - std::string originStr; err = interfaceElement->QueryStringAttribute("ORIGIN", &originStr); @@ -200,8 +199,17 @@ namespace Nektar InterfaceShPtr rotatingInterface( MemoryManager::AllocateSharedPtr( - rightDomain, leftDomain, interfaceEdge, - origin, axis, angularVel)); + rightDomain, leftDomain, origin, axis, angularVel)); + + if(interfaceErr == TIXML_SUCCESS) + { + rotatingInterface->SetInterfaceEdge(interfaceEdge); + } + else + { + rotatingInterface->SetEdgeRight(rightEdge); + rotatingInterface->SetEdgeLeft(leftEdge); + } m_interfaces[indx] = rotatingInterface; } @@ -266,12 +274,9 @@ namespace Nektar // Create a new vertex newVerts[i] = MemoryManager::AllocateSharedPtr( *geom->GetVertex(i)); - if (abs((*newVerts[i])(1)-0.5) < 1e-8) - (*newVerts[i])(1) += 0.1; newVerts[i]->SetGlobalID(maxVertId); graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; vertDone[vid[i]] = maxVertId++; - } else { @@ -304,11 +309,11 @@ namespace Nektar maxEdgeId, newVerts[0]->GetCoordim(), newVerts, newCurve); - m_leftEdge.push_back(oldEdge->GetGlobalID()); - m_rightEdge.push_back(maxEdgeId); - graph->GetAllSegGeoms()[maxEdgeId] = newEdge; edgeDone[geom->GetGlobalID()] = newEdge; + + m_leftEdge[oldEdge->GetGlobalID()] = oldEdge; + m_rightEdge[maxEdgeId] = newEdge; maxEdgeId++; auto toProcess = diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index d1ba32f0f..87eee026a 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -69,13 +69,10 @@ namespace Nektar InterfaceBase( InterfaceType type, CompositeMap rightDomain, - CompositeMap leftDomain, - std::map interfaceEdge): + CompositeMap leftDomain): m_interfaceType(type), m_rightDomain(rightDomain), - m_leftDomain(leftDomain), - m_interfaceEdge(interfaceEdge) - + m_leftDomain(leftDomain) { } @@ -99,24 +96,65 @@ namespace Nektar return m_interfaceEdge; } - std::vector const &GetEdgeLeft() const + void SetInterfaceEdge(const CompositeMap &interfaceEdge) + { + m_interfaceEdge = interfaceEdge; + } + + std::map const &GetEdgeLeft() const { return m_leftEdge; } - std::vector const &GetEdgeRight() const + void SetEdgeLeft(const std::map &leftEdge) + { + m_leftEdge = leftEdge; + } + + void SetEdgeLeft(const CompositeMap &leftEdge) + { + for (auto &compIt : leftEdge) + { + for (auto &elmtIt : compIt.second->m_geomVec) + { + SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); + ASSERTL0(elmt, "Composite for left edge should only contain segments"); + m_leftEdge[elmt->GetGlobalID()] = elmt; + } + } + } + + std::map const &GetEdgeRight() const { return m_rightEdge; } + void SetEdgeRight(const std::map &rightEdge) + { + m_rightEdge = rightEdge; + } + + void SetEdgeRight(const CompositeMap &rightEdge) + { + for (auto &compIt : rightEdge) + { + for (auto &elmtIt : compIt.second->m_geomVec) + { + SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); + ASSERTL0(elmt, "Composite for right edge should only contain segments"); + m_rightEdge[elmt->GetGlobalID()] = elmt; + } + } + } + void SeparateGraph(MeshGraphSharedPtr &graph); protected: InterfaceType m_interfaceType; CompositeMap m_rightDomain; CompositeMap m_leftDomain; - std::vector m_leftEdge; - std::vector m_rightEdge; + std::map m_leftEdge; + std::map m_rightEdge; CompositeMap m_interfaceEdge; }; @@ -126,11 +164,10 @@ namespace Nektar RotatingInterface( const CompositeMap rightDomain, const CompositeMap leftDomain, - const std::map interfaceEdge, const PointGeom origin, const std::vector axis, const NekDouble angularVel) - : InterfaceBase(eRotating, rightDomain, leftDomain, interfaceEdge), + : InterfaceBase(eRotating, rightDomain, leftDomain), m_origin(origin), m_axis(axis), m_angularVel(angularVel) diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index 41e15eae1..3723130bf 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -34,12 +34,17 @@ // //////////////////////////////////////////////////////////////////////////////// -#include #include +#include +#include // for PointsManager, etc #include #include -#include // for PointsManager, etc + +#include +#include +#include +#include namespace Nektar { @@ -50,16 +55,14 @@ SegGeom::SegGeom() m_shapeType = LibUtilities::eSegment; } -SegGeom::SegGeom(int id, - const int coordim, - const PointGeomSharedPtr vertex[], +SegGeom::SegGeom(int id, const int coordim, const PointGeomSharedPtr vertex[], const CurveSharedPtr curve) : Geometry1D(coordim) { m_shapeType = LibUtilities::eSegment; - m_globalID = id; - m_state = eNotFilled; - m_curve = curve; + m_globalID = id; + m_state = eNotFilled; + m_curve = curve; m_verts[0] = vertex[0]; m_verts[1] = vertex[1]; @@ -72,11 +75,11 @@ SegGeom::SegGeom(const SegGeom &in) // info from EdgeComponent class m_globalID = in.m_globalID; - m_xmap = in.m_xmap; + m_xmap = in.m_xmap; SetUpCoeffs(m_xmap->GetNcoeffs()); // info from SegGeom class - m_coordim = in.m_coordim; + m_coordim = in.m_coordim; m_verts[0] = in.m_verts[0]; m_verts[1] = in.m_verts[1]; @@ -96,8 +99,7 @@ void SegGeom::SetUpXmap() else { const LibUtilities::BasisKey B( - LibUtilities::eModified_A, - 2, + LibUtilities::eModified_A, 2, LibUtilities::PointsKey(2, LibUtilities::eGaussLobattoLegendre)); m_xmap = MemoryManager::AllocateSharedPtr(B); } @@ -116,8 +118,8 @@ SegGeomSharedPtr SegGeom::GenerateOneSpaceDimGeom(void) returnval->m_globalID = m_globalID; // geometric information. - returnval->m_coordim = 1; - NekDouble x0 = (*m_verts[0])[0]; + returnval->m_coordim = 1; + NekDouble x0 = (*m_verts[0])[0]; PointGeomSharedPtr vert0 = MemoryManager::AllocateSharedPtr( 1, m_verts[0]->GetGlobalID(), x0, 0.0, 0.0); vert0->SetGlobalID(vert0->GetGlobalID()); @@ -140,7 +142,7 @@ SegGeomSharedPtr SegGeom::GenerateOneSpaceDimGeom(void) else { Array w0 = base[0]->GetW(); - len = 0.0; + len = 0.0; for (int i = 0; i < jac.num_elements(); ++i) { @@ -223,7 +225,7 @@ StdRegions::Orientation SegGeom::GetEdgeOrientation(const SegGeom &edge1, void SegGeom::v_GenGeomFactors() { - if(!m_setupState) + if (!m_setupState) { SegGeom::v_Setup(); } @@ -328,7 +330,7 @@ void SegGeom::v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces) void SegGeom::v_Setup() { - if(!m_setupState) + if (!m_setupState) { SetUpXmap(); SetUpCoeffs(m_xmap->GetNcoeffs()); @@ -347,7 +349,7 @@ NekDouble SegGeom::v_GetLocCoords(const Array &coords, if (GetMetricInfo()->GetGtype() == eRegular) { NekDouble len = 0.0; - NekDouble xi = 0.0; + NekDouble xi = 0.0; const int npts = m_xmap->GetTotPoints(); Array pts(npts); @@ -360,7 +362,7 @@ NekDouble SegGeom::v_GetLocCoords(const Array &coords, } len = sqrt(len); - xi = sqrt(xi); + xi = sqrt(xi); Lcoords[0] = 2 * xi / len - 1.0; } @@ -373,8 +375,7 @@ NekDouble SegGeom::v_GetLocCoords(const Array &coords, } bool SegGeom::v_ContainsPoint(const Array &gloCoord, - Array &stdCoord, - NekDouble tol, + Array &stdCoord, NekDouble tol, NekDouble &resid) { resid = GetLocCoords(gloCoord, stdCoord); @@ -407,5 +408,144 @@ int SegGeom::v_GetNumEdges() const return kNedges; } +NekDouble SegGeom::v_FindDistance(const Array &xs, + NekDouble &xiOut) +{ + ASSERTL0(m_coordim == 2, "Need to rewrite for m_coordim != 2"); + + if (m_geomFactors->GetGtype() == eRegular) + { + // Geometry is linear, so use analytic BOOST function to compute distance. + std::vector edgeVertexOne(3,0), edgeVertexTwo(3,0); + m_verts[0]->GetCoords(edgeVertexOne[0], edgeVertexOne[1], edgeVertexOne[2]); + m_verts[1]->GetCoords(edgeVertexTwo[0], edgeVertexTwo[1], edgeVertexTwo[2]); + NekDouble xc = (xs[0]-edgeVertexOne[0])/(edgeVertexTwo[0]-edgeVertexOne[0]); + NekDouble yc = (xs[1]-edgeVertexOne[1])/(edgeVertexTwo[1]-edgeVertexOne[1]); + xiOut = 2 * (((isnan(xc)) ? 0 : xc) + ((isnan(yc)) ? 0 : yc)) - 1; + + typedef boost::geometry::model::d2::point_xy point_type; + typedef boost::geometry::model::linestring linestring_type; + point_type p(xs[0],xs[1]); + linestring_type line; + line.push_back(point_type(edgeVertexOne[0],edgeVertexOne[1])); + line.push_back(point_type(edgeVertexTwo[0],edgeVertexTwo[1])); + return boost::geometry::distance(p, line); + } + else if (m_geomFactors->GetGtype() == eDeformed) + { + Array xi(1, 0.0); + const NekDouble c1 = 1e-4, c2 = 0.9; + + int nq = m_xmap->GetTotPoints(); + + Array x(nq), y(nq); + m_xmap->BwdTrans(m_coeffs[0], x); + m_xmap->BwdTrans(m_coeffs[1], y); + + Array xder(nq), yder(nq); + m_xmap->PhysDeriv(x, xder); + m_xmap->PhysDeriv(y, yder); + + Array xder2(nq), yder2(nq); + m_xmap->PhysDeriv(xder, xder2); + m_xmap->PhysDeriv(yder, yder2); + + bool opt_succeed = false; + + NekDouble fx_prev = std::numeric_limits::max(); + + for (int i = 0; i < 15; ++i) + { + // Compute f(x_k) and its derivatives + NekDouble xc = m_xmap->PhysEvaluate(xi, x); + NekDouble yc = m_xmap->PhysEvaluate(xi, y); + + NekDouble xc_der = m_xmap->PhysEvaluate(xi, xder); + NekDouble yc_der = m_xmap->PhysEvaluate(xi, yder); + + NekDouble xc_der2 = m_xmap->PhysEvaluate(xi, xder2); + NekDouble yc_der2 = m_xmap->PhysEvaluate(xi, yder2); + + NekDouble fx = + (xc - xs[0]) * (xc - xs[0]) + (yc - xs[1]) * (yc - xs[1]); + NekDouble fxp = + 2.0 * (xc_der * (xc - xs[0]) + yc_der * (yc - xs[1])); + NekDouble fxp2 = 2.0 * (xc_der2 * (xc - xs[0]) + xc_der * xc_der + + yc_der2 * (yc - xs[1]) + yc_der * yc_der); + + // Check for convergence + if (abs(fx - fx_prev) < 1e-16) + { + opt_succeed = true; + fx_prev = fx; + break; + } + else + { + fx_prev = fx; + } + + NekDouble gamma = 1.0; + bool conv = false; + + // Search direction: quasi-Newton + NekDouble pk = -fxp / fxp2; + + // Backtracking line search + while (gamma > 1e-10) + { + Array xi_pk(1); + xi_pk[0] = xi[0] + pk * gamma; + + if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0) + { + gamma /= 2.0; + continue; + } + + NekDouble xc_pk = m_xmap->PhysEvaluate(xi_pk, x); + NekDouble yc_pk = m_xmap->PhysEvaluate(xi_pk, y); + + NekDouble xc_der_pk = m_xmap->PhysEvaluate(xi_pk, xder); + NekDouble yc_der_pk = m_xmap->PhysEvaluate(xi_pk, yder); + + NekDouble fx_pk = (xc_pk - xs[0]) * (xc_pk - xs[0]) + + (yc_pk - xs[1]) * (yc_pk - xs[1]); + NekDouble fxp_pk = 2.0 * (xc_der_pk * (xc_pk - xs[0]) + + yc_der_pk * (yc_pk - xs[1])); + + // Check Wolfe conditions + if (fx_pk <= fx + c1 * gamma * pk * fxp && + -pk * fxp_pk <= -c2 * pk * fxp) + { + conv = true; + break; + } + + gamma /= 2.0; + } + + if (!conv) + { + opt_succeed = false; + break; + } + + xi[0] += gamma * pk; + } + + if (opt_succeed) + { + xiOut = xi[0]; + return fx_prev; + } + else + { + xiOut = std::numeric_limits::max(); + return std::numeric_limits::max(); + } + } +} + } } diff --git a/library/SpatialDomains/SegGeom.h b/library/SpatialDomains/SegGeom.h index 6d39ed9a0..d7a0967bf 100644 --- a/library/SpatialDomains/SegGeom.h +++ b/library/SpatialDomains/SegGeom.h @@ -103,6 +103,10 @@ protected: NekDouble tol, NekDouble &resid); + virtual NekDouble v_FindDistance(const Array &xs, + NekDouble &xi); + + private: /// Boolean indicating whether object owns the data CurveSharedPtr m_curve; -- GitLab From fe64570b8ef4ccceef44e72b7b7c6f4760459779 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 8 Apr 2019 11:06:27 +0100 Subject: [PATCH 013/408] Begin boundary box search implementation DisCont --- library/MultiRegions/DisContField2D.cpp | 3 +++ library/SpatialDomains/MeshGraph.cpp | 9 ++------- library/SpatialDomains/MeshGraph.h | 14 +++++++++++++- library/SpatialDomains/SegGeom.cpp | 4 ++-- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 8d2e06e3e..a64445c90 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1539,6 +1539,9 @@ namespace Nektar for (int i = 0; i < nq; ++i) { bool found = false; + NekDouble zero = 0.0; + auto vals = m_graph->GetElementsContainingPoint(xc[i], yc[i], zero); + cout << edgeTwoExps.size() << endl; for (int m = 0; m < edgeTwoExps.size(); ++m) { LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index 89420569e..4e17220cf 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -236,20 +236,15 @@ void MeshGraph::FillBoundingBoxTree() } std::vector MeshGraph::GetElementsContainingPoint( - PointGeomSharedPtr p) + NekDouble &x, NekDouble &y, NekDouble &z) { if (m_boundingBoxTree.empty()) { FillBoundingBoxTree(); } - NekDouble x = 0.0; - NekDouble y = 0.0; - NekDouble z = 0.0; std::vector vals; - p->GetCoords(x, y, z); - BgBox b( BgPoint(x, y, z), BgPoint(x, y, z) ); m_boundingBoxTree.query(bg::index::intersects( b ), @@ -2615,7 +2610,7 @@ std::string MeshGraph::GetCompositeString(CompositeSharedPtr comp) void MeshGraph::ReadExpansions() { // Hack? - m_expansionMapShPtrMap.clear();; + m_expansionMapShPtrMap.clear(); // Find the Expansions tag TiXmlElement *expansionTypes = m_session->GetElement("NEKTAR/EXPANSIONS"); diff --git a/library/SpatialDomains/MeshGraph.h b/library/SpatialDomains/MeshGraph.h index d8d3a701b..7626d16a0 100644 --- a/library/SpatialDomains/MeshGraph.h +++ b/library/SpatialDomains/MeshGraph.h @@ -202,7 +202,19 @@ public: SPATIAL_DOMAINS_EXPORT void FillBoundingBoxTree(); SPATIAL_DOMAINS_EXPORT std::vector GetElementsContainingPoint( - PointGeomSharedPtr p); + PointGeomSharedPtr p) + { + NekDouble x = 0.0; + NekDouble y = 0.0; + NekDouble z = 0.0; + + p->GetCoords(x, y, z); + + return GetElementsContainingPoint(x, y, z); + }; + + SPATIAL_DOMAINS_EXPORT std::vector GetElementsContainingPoint( + NekDouble &x, NekDouble &y, NekDouble &z); //////////////////// //////////////////// diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index 9e5270168..3ddbbf5bb 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -410,7 +410,7 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, { ASSERTL0(m_coordim == 2, "Need to rewrite for m_coordim != 2"); - if (m_geomFactors->GetGtype() == eRegular) + if (m_geomFactors->GetGtype() == eDeformed) //eRegular) { // Geometry is linear, so use analytic BOOST function to compute distance. std::vector edgeVertexOne(3,0), edgeVertexTwo(3,0); @@ -428,7 +428,7 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, line.push_back(point_type(edgeVertexTwo[0],edgeVertexTwo[1])); return boost::geometry::distance(p, line); } - else if (m_geomFactors->GetGtype() == eDeformed) + else { Array xi(1, 0.0); const NekDouble c1 = 1e-4, c2 = 0.9; -- GitLab From aed8fe04cf60a7c8a0c31ec0c395b15fa239f0ef Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 8 Apr 2019 17:05:41 +0100 Subject: [PATCH 014/408] Bounding box changes and interface implementation --- library/MultiRegions/DisContField2D.cpp | 150 +++++++++++++----------- library/MultiRegions/ExpList.cpp | 2 +- library/MultiRegions/ExpList2D.cpp | 5 +- library/SpatialDomains/MeshGraph.cpp | 36 +++--- library/SpatialDomains/MeshGraph.h | 15 +-- library/SpatialDomains/SegGeom.cpp | 2 +- 6 files changed, 116 insertions(+), 94 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index a64445c90..51d980cf8 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -420,7 +420,6 @@ namespace Nektar //adjoining elements which do not lie in a plane. for (int i = 0; i < m_exp->size(); ++i) { - std::cout << "ELMT " << i << ": "; for (int j = 0; j < (*m_exp)[i]->GetNedges(); ++j) { LocalRegions::Expansion2DSharedPtr exp2d = @@ -430,10 +429,7 @@ namespace Nektar LocalRegions::ExpansionSharedPtr exp = elmtToTrace[i][j];; exp2d->SetEdgeExp (j, exp1d); exp1d->SetAdjacentElementExp(j, exp2d); - std::cout << " " << j << "<->" << exp1d->GetGeom()->GetGlobalID(); } - - std::cout << std::endl; } // Set up physical normals @@ -479,8 +475,6 @@ namespace Nektar auto traceEl = std::dynamic_pointer_cast< LocalRegions::Expansion1D>( m_trace->GetExp(traceIdToElmt[id])); - std::cout << "Negating normal on edge " << traceEl->GetGeom()->GetGlobalID() << std::endl; - std::cout << "Connect to elmt " << traceEl->GetLeftAdjacentElementExp()->GetGeom()->GetGlobalID() << " edge " << traceEl->GetLeftAdjacentElementEdge() << std::endl; traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( traceEl->GetLeftAdjacentElementEdge()); m_traceEdgeRight[interface.first].push_back(traceEl); @@ -498,22 +492,6 @@ namespace Nektar } } - for (auto &it : m_traceEdgeLeft) - { - std::cout << "LEFT EDGES: "; - for (int i = 0; i < m_traceEdgeLeft[it.first].size(); ++i) - { - std::cout << m_traceEdgeLeft[it.first][i]->GetGeom()->GetGlobalID() << " "; - } - - std::cout << std::endl << "RIGHT EDGES: "; - for (int i = 0; i < m_traceEdgeRight[it.first].size(); ++i) - { - std::cout << m_traceEdgeRight[it.first][i]->GetGeom()->GetGlobalID() << " "; - } - } - std::cout << std::endl; - int cnt, n, e; // Identify boundary edges @@ -1532,39 +1510,58 @@ namespace Nektar for (n = 0; n < edgeOneExps.size(); ++n) { auto elmt = edgeOneExps[n]; - int nq = elmt->GetTotPoints(); + int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); for (int i = 0; i < nq; ++i) { - bool found = false; NekDouble zero = 0.0; - auto vals = m_graph->GetElementsContainingPoint(xc[i], yc[i], zero); - cout << edgeTwoExps.size() << endl; - for (int m = 0; m < edgeTwoExps.size(); ++m) + std::vector + searchEdge; + auto BgRtree = m_graph->GetRegionsContainingPoint( + xc[i], yc[i], zero, 1); + bool found = false; + for (auto boundaryBoxElement : BgRtree) { - LocalRegions::Expansion1DSharedPtr searchEdge = edgeTwoExps[m]; - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed - Array xs(2); - xs[0] = xc[i]; - xs[1] = yc[i]; - - NekDouble foundPoint; - NekDouble dist = searchEdgeSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) + for (int m = 0; m < edgeTwoExps.size(); ++m) { - continue; + auto geom = edgeTwoExps[m]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast< + SpatialDomains::SegGeom>( + geom->GetGeom1D()); + if (boundaryBoxElement.second == + geomSeg->GetGlobalID()) + { + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + + NekDouble foundPoint; + NekDouble dist = + geomSeg->FindDistance(xs, foundPoint); + if (dist > 1e-8) + { + continue; + } + Array edgePhys = + Bwd + m_trace->GetPhys_Offset( + geom->GetElmtId()); + Array foundPointArray( + 1, foundPoint); + Bwd[m_trace->GetPhys_Offset( + elmt->GetElmtId()) + + i] = + geom->StdPhysEvaluate(foundPointArray, + edgePhys); + found = true; + break; + } } - Array edgePhys = Bwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); - Array foundPointArray(1, foundPoint); //Change by Ed - Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); - found = true; - //std::cout << "2->1 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; - //std::cout << "COPYING BWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; - break; } - ASSERTL1(found, "Couldn't interpolate across interface from right to left (bwd)"); + ASSERTL1(found, "Couldn't interpolate across interface " + "from right to left (bwd)"); } } @@ -1572,37 +1569,58 @@ namespace Nektar for (n = 0; n < edgeTwoExps.size(); ++n) { auto elmt = edgeTwoExps[n]; - int nq = elmt->GetTotPoints(); + int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); for (int i = 0; i < nq; ++i) { + NekDouble zero = 0.0; + std::vector + searchEdge; + auto BgRtree = m_graph->GetRegionsContainingPoint( + xc[i], yc[i], zero, 1); bool found = false; - for (int m = 0; m < edgeOneExps.size(); ++m) + for (auto boundaryBoxElement : BgRtree) { - LocalRegions::Expansion1DSharedPtr searchEdge = edgeOneExps[m]; - SpatialDomains::SegGeomSharedPtr searchEdgeSeg = std::static_pointer_cast(searchEdge->GetGeom1D()); //Change by Ed - Array xs(2); - xs[0] = xc[i]; - xs[1] = yc[i]; - - NekDouble foundPoint; - NekDouble dist = searchEdgeSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) + for (int m = 0; m < edgeOneExps.size(); ++m) { - continue; + auto geom = edgeOneExps[m]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast< + SpatialDomains::SegGeom>( + geom->GetGeom1D()); + if (boundaryBoxElement.second == + geomSeg->GetGlobalID()) + { + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + + NekDouble foundPoint; + NekDouble dist = + geomSeg->FindDistance(xs, foundPoint); + if (dist > 1e-8) + { + continue; + } + Array edgePhys = + Fwd + m_trace->GetPhys_Offset( + geom->GetElmtId()); + Array foundPointArray( + 1, foundPoint); + Fwd[m_trace->GetPhys_Offset( + elmt->GetElmtId()) + + i] = + geom->StdPhysEvaluate(foundPointArray, + edgePhys); + found = true; + break; + } } - Array edgePhys = Fwd + m_trace->GetPhys_Offset(searchEdge->GetElmtId()); - Array foundPointArray(1, foundPoint); //Change by Ed - Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = searchEdge->StdPhysEvaluate(foundPointArray, edgePhys); - //std::cout << "(" << xc[i] << "," << yc[i] << ") -> " << searchEdge->StdPhysEvaluate(foundPointArray, edgePhys) << std::endl; - // std::cout << "1->2 ELMT " << elmt->GetGeom()->GetGlobalID() << " found " << searchEdgeSeg->GetGlobalID() << " loc = " << foundPoint << std::endl; - //std::cout << "COPYING FWD TRACE " << searchEdgeSeg->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(searchEdge->GetElmtId()) << " -> TRACE " << elmt->GetGeom()->GetGlobalID() << " OFFSET " << m_trace->GetPhys_Offset(elmt->GetElmtId()) << std::endl; - found = true; - break; } - ASSERTL1(found, "Couldn't interpolate across interface from left to right (fwd)"); + ASSERTL1(found, "Couldn't interpolate across interface " + "from left to right (fwd)"); } } } diff --git a/library/MultiRegions/ExpList.cpp b/library/MultiRegions/ExpList.cpp index da89cd1b5..3fef4da00 100644 --- a/library/MultiRegions/ExpList.cpp +++ b/library/MultiRegions/ExpList.cpp @@ -1477,7 +1477,7 @@ namespace Nektar // Get the list of elements whose bounding box contains the desired // point. std::vector elmts = - m_graph->GetElementsContainingPoint(p); + m_graph->GetRegionsContainingPoint(p, m_graph->GetMeshDimension()); NekDouble nearpt = 1e6; NekDouble nearpt_min = 1e6; diff --git a/library/MultiRegions/ExpList2D.cpp b/library/MultiRegions/ExpList2D.cpp index f884e3e1d..f612b36d3 100644 --- a/library/MultiRegions/ExpList2D.cpp +++ b/library/MultiRegions/ExpList2D.cpp @@ -144,7 +144,10 @@ namespace Nektar m_interfaces = interfaceCollection.GetInterfaces(); for (auto &inter : m_interfaces) { - inter.second->SeparateGraph(m_graph); + if (inter.second->GetEdgeRight().empty()) + { + inter.second->SeparateGraph(m_graph); + } } std::string filename = "out.xml"; diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index 4e17220cf..d4262d243 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -185,49 +185,50 @@ void MeshGraph::FillGraph() } } -void MeshGraph::FillBoundingBoxTree() +void MeshGraph::FillBoundingBoxTree(int &dimension) { - m_boundingBoxTree.clear(); - switch (m_meshDimension) { + ASSERTL0(dimension<=m_meshDimension, "Unknown dim, must be less than or equal to mesh dimension"); + m_boundingBoxTree[dimension].clear(); + switch (dimension) { case 1: for (auto &x : m_segGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } break; case 2: for (auto &x : m_triGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } - for (auto &x : m_quadGeoms) + for (auto &x : m_quadGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } break; case 3: for (auto &x : m_tetGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } for (auto &x : m_prismGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } for (auto &x : m_pyrGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } for (auto &x : m_hexGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree.insert(std::make_pair(b, x.first)); + m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); } break; default: @@ -235,26 +236,25 @@ void MeshGraph::FillBoundingBoxTree() } } -std::vector MeshGraph::GetElementsContainingPoint( - NekDouble &x, NekDouble &y, NekDouble &z) + +std::vector MeshGraph::GetRegionsContainingPoint( + NekDouble &x, NekDouble &y, NekDouble &z, int dimension) { - if (m_boundingBoxTree.empty()) + if (m_boundingBoxTree[dimension].empty()) { - FillBoundingBoxTree(); + FillBoundingBoxTree(dimension); } std::vector vals; BgBox b( BgPoint(x, y, z), BgPoint(x, y, z) ); - m_boundingBoxTree.query(bg::index::intersects( b ), + m_boundingBoxTree[dimension].query(bg::index::intersects( b ), std::back_inserter( vals )); return vals; } - - void MeshGraph::SetDomainRange(NekDouble xmin, NekDouble xmax, NekDouble ymin, NekDouble ymax, NekDouble zmin, NekDouble zmax) { diff --git a/library/SpatialDomains/MeshGraph.h b/library/SpatialDomains/MeshGraph.h index 7626d16a0..8eef346b4 100644 --- a/library/SpatialDomains/MeshGraph.h +++ b/library/SpatialDomains/MeshGraph.h @@ -199,10 +199,11 @@ public: /*transfers the minial data structure to full meshgraph*/ SPATIAL_DOMAINS_EXPORT void FillGraph(); - SPATIAL_DOMAINS_EXPORT void FillBoundingBoxTree(); + SPATIAL_DOMAINS_EXPORT void FillBoundingBoxTree(int dimension); - SPATIAL_DOMAINS_EXPORT std::vector GetElementsContainingPoint( - PointGeomSharedPtr p) + + SPATIAL_DOMAINS_EXPORT std::vector GetRegionsContainingPoint( + PointGeomSharedPtr &p, int dimension) { NekDouble x = 0.0; NekDouble y = 0.0; @@ -210,11 +211,11 @@ public: p->GetCoords(x, y, z); - return GetElementsContainingPoint(x, y, z); + return GetRegionsContainingPoint(x, y, z, dimension); }; - SPATIAL_DOMAINS_EXPORT std::vector GetElementsContainingPoint( - NekDouble &x, NekDouble &y, NekDouble &z); + SPATIAL_DOMAINS_EXPORT std::vector GetRegionsContainingPoint( + NekDouble &x, NekDouble &y, NekDouble &z, int dimension); //////////////////// //////////////////// @@ -489,7 +490,7 @@ protected: CompositeOrdering m_compOrder; BndRegionOrdering m_bndRegOrder; - BgRtree m_boundingBoxTree; + std::map m_boundingBoxTree; }; typedef std::shared_ptr MeshGraphSharedPtr; typedef LibUtilities::NekFactory MeshGraphFactory; diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index 3ddbbf5bb..909703e28 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -410,7 +410,7 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, { ASSERTL0(m_coordim == 2, "Need to rewrite for m_coordim != 2"); - if (m_geomFactors->GetGtype() == eDeformed) //eRegular) + if (m_geomFactors->GetGtype() == eRegular) { // Geometry is linear, so use analytic BOOST function to compute distance. std::vector edgeVertexOne(3,0), edgeVertexTwo(3,0); -- GitLab From 36188ebcc2d2128be05fad343c929ae8ad823a88 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 9 Apr 2019 14:49:54 +0100 Subject: [PATCH 015/408] Bounding tree changes --- library/MultiRegions/DisContField2D.cpp | 132 +++++++++++++----------- library/SpatialDomains/MeshGraph.cpp | 2 +- library/SpatialDomains/SegGeom.cpp | 8 +- 3 files changed, 82 insertions(+), 60 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 51d980cf8..f06d9a6ab 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1510,6 +1510,9 @@ namespace Nektar for (n = 0; n < edgeOneExps.size(); ++n) { auto elmt = edgeOneExps[n]; + std::cout << std::fixed; + std::cout << std::setprecision(5); + cout << "BWD EDGE ID: " << std::static_pointer_cast(elmt->GetGeom1D())->GetGlobalID() << " - (" << n+1 << " / " << edgeOneExps.size() << ")" << endl; int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); @@ -1521,42 +1524,48 @@ namespace Nektar searchEdge; auto BgRtree = m_graph->GetRegionsContainingPoint( xc[i], yc[i], zero, 1); + cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; bool found = false; for (auto boundaryBoxElement : BgRtree) { - for (int m = 0; m < edgeTwoExps.size(); ++m) + if (found == false) { - auto geom = edgeTwoExps[m]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast< - SpatialDomains::SegGeom>( - geom->GetGeom1D()); - if (boundaryBoxElement.second == - geomSeg->GetGlobalID()) + for (int m = 0; m < edgeTwoExps.size(); ++m) { - Array xs(2); - xs[0] = xc[i]; - xs[1] = yc[i]; - - NekDouble foundPoint; - NekDouble dist = - geomSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) + auto geom = edgeTwoExps[m]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast< + SpatialDomains::SegGeom>( + geom->GetGeom1D()); + if (boundaryBoxElement.second == + geomSeg->GetGlobalID()) { - continue; + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + + NekDouble foundPoint; + NekDouble dist = geomSeg->FindDistance( + xs, foundPoint); + cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << " | Distance: " << dist; + if (dist > 1e-8) + { + continue; + } + Array edgePhys = + Bwd + m_trace->GetPhys_Offset( + geom->GetElmtId()); + Array foundPointArray( + 1, foundPoint); + Bwd[m_trace->GetPhys_Offset( + elmt->GetElmtId()) + + i] = + geom->StdPhysEvaluate( + foundPointArray, edgePhys); + found = true; + cout << " | BWD SUCCESS" << endl; + break; } - Array edgePhys = - Bwd + m_trace->GetPhys_Offset( - geom->GetElmtId()); - Array foundPointArray( - 1, foundPoint); - Bwd[m_trace->GetPhys_Offset( - elmt->GetElmtId()) + - i] = - geom->StdPhysEvaluate(foundPointArray, - edgePhys); - found = true; - break; } } } @@ -1569,6 +1578,7 @@ namespace Nektar for (n = 0; n < edgeTwoExps.size(); ++n) { auto elmt = edgeTwoExps[n]; + cout << "FWD EDGE ID: " << std::static_pointer_cast(elmt->GetGeom1D())->GetGlobalID() << " - (" << n+1 << " / " << edgeTwoExps.size() << ")" << endl; int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); @@ -1580,42 +1590,48 @@ namespace Nektar searchEdge; auto BgRtree = m_graph->GetRegionsContainingPoint( xc[i], yc[i], zero, 1); + cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; bool found = false; for (auto boundaryBoxElement : BgRtree) { - for (int m = 0; m < edgeOneExps.size(); ++m) + if (found == false) { - auto geom = edgeOneExps[m]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast< - SpatialDomains::SegGeom>( - geom->GetGeom1D()); - if (boundaryBoxElement.second == - geomSeg->GetGlobalID()) + for (int m = 0; m < edgeOneExps.size(); ++m) { - Array xs(2); - xs[0] = xc[i]; - xs[1] = yc[i]; - - NekDouble foundPoint; - NekDouble dist = - geomSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) + auto geom = edgeOneExps[m]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast< + SpatialDomains::SegGeom>( + geom->GetGeom1D()); + if (boundaryBoxElement.second == + geomSeg->GetGlobalID()) { - continue; + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + + NekDouble foundPoint; + NekDouble dist = geomSeg->FindDistance( + xs, foundPoint); + cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << "\t| Distance: " << dist; + if (dist > 1e-8) + { + continue; + } + Array edgePhys = + Fwd + m_trace->GetPhys_Offset( + geom->GetElmtId()); + Array foundPointArray( + 1, foundPoint); + Fwd[m_trace->GetPhys_Offset( + elmt->GetElmtId()) + + i] = + geom->StdPhysEvaluate( + foundPointArray, edgePhys); + found = true; + cout << " | FWD SUCCESS" << endl; + break; } - Array edgePhys = - Fwd + m_trace->GetPhys_Offset( - geom->GetElmtId()); - Array foundPointArray( - 1, foundPoint); - Fwd[m_trace->GetPhys_Offset( - elmt->GetElmtId()) + - i] = - geom->StdPhysEvaluate(foundPointArray, - edgePhys); - found = true; - break; } } } diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index d4262d243..77bcb00a3 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -185,7 +185,7 @@ void MeshGraph::FillGraph() } } -void MeshGraph::FillBoundingBoxTree(int &dimension) +void MeshGraph::FillBoundingBoxTree(int dimension) { ASSERTL0(dimension<=m_meshDimension, "Unknown dim, must be less than or equal to mesh dimension"); m_boundingBoxTree[dimension].clear(); diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index 909703e28..c4c86f71d 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -412,6 +412,7 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, if (m_geomFactors->GetGtype() == eRegular) { + cout << " | LINEAR "; // Geometry is linear, so use analytic BOOST function to compute distance. std::vector edgeVertexOne(3,0), edgeVertexTwo(3,0); m_verts[0]->GetCoords(edgeVertexOne[0], edgeVertexOne[1], edgeVertexOne[2]); @@ -428,8 +429,9 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, line.push_back(point_type(edgeVertexTwo[0],edgeVertexTwo[1])); return boost::geometry::distance(p, line); } - else + else if (m_geomFactors->GetGtype() == eDeformed) { + cout << " | NON-LINEAR "; Array xi(1, 0.0); const NekDouble c1 = 1e-4, c2 = 0.9; @@ -542,6 +544,10 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, return std::numeric_limits::max(); } } + else + { + ASSERTL0(false, "Geometry type unknown") + } } } -- GitLab From 720bacb2cce092798aef084ebc9f6183700e8e26 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Wed, 10 Apr 2019 11:56:39 +0100 Subject: [PATCH 016/408] Revert MeshGraph bbox & add sep interface bbox --- library/MultiRegions/DisContField2D.cpp | 4224 +++++++++++------------ library/MultiRegions/DisContField2D.h | 4 +- library/MultiRegions/ExpList.cpp | 2 +- library/SpatialDomains/Interface.cpp | 740 ++-- library/SpatialDomains/Interface.h | 345 +- library/SpatialDomains/MeshGraph.cpp | 31 +- library/SpatialDomains/MeshGraph.h | 14 +- 7 files changed, 2642 insertions(+), 2718 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index f06d9a6ab..4f1da9b60 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -34,144 +34,215 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include +#include +#include +#include #include -#include -#include +#include +#include #include -#include +#include #include -#include -#include +#include using namespace std; namespace Nektar { - namespace MultiRegions - { - - /** - * @class DisContField2D - * Abstraction of a global discontinuous two-dimensional spectral/hp - * element expansion which approximates the solution of a set of - * partial differential equations. - */ - - /** - * @brief Default constructor. - */ - DisContField2D::DisContField2D(void) - : ExpList2D (), - m_bndCondExpansions(), - m_bndConditions (), - m_trace (NullExpListSharedPtr) +namespace MultiRegions +{ + +/** + * @class DisContField2D + * Abstraction of a global discontinuous two-dimensional spectral/hp + * element expansion which approximates the solution of a set of + * partial differential equations. + */ + +/** + * @brief Default constructor. + */ +DisContField2D::DisContField2D(void) + : ExpList2D(), m_bndCondExpansions(), m_bndConditions(), + m_trace(NullExpListSharedPtr) +{ +} + +DisContField2D::DisContField2D(const DisContField2D &In, + const bool DeclareCoeffPhysArrays) + : ExpList2D(In, DeclareCoeffPhysArrays), + m_bndCondExpansions(In.m_bndCondExpansions), + m_bndConditions(In.m_bndConditions), m_globalBndMat(In.m_globalBndMat), + m_traceMap(In.m_traceMap), m_locTraceToTraceMap(In.m_locTraceToTraceMap), + m_boundaryEdges(In.m_boundaryEdges), m_periodicVerts(In.m_periodicVerts), + m_periodicEdges(In.m_periodicEdges), + m_periodicFwdCopy(In.m_periodicFwdCopy), + m_periodicBwdCopy(In.m_periodicBwdCopy), + m_leftAdjacentEdges(In.m_leftAdjacentEdges) +{ + if (In.m_trace) + { + m_trace = MemoryManager::AllocateSharedPtr( + *std::dynamic_pointer_cast(In.m_trace), + DeclareCoeffPhysArrays); + } +} + +/** + * @brief Constructs a global discontinuous field based on an input + * mesh with boundary conditions. + */ +DisContField2D::DisContField2D( + const LibUtilities::SessionReaderSharedPtr &pSession, + const SpatialDomains::MeshGraphSharedPtr &graph2D, + const std::string &variable, const bool SetUpJustDG, + const bool DeclareCoeffPhysArrays, + const Collections::ImplementationType ImpType) + : ExpList2D(pSession, graph2D, DeclareCoeffPhysArrays, variable, ImpType), + m_bndCondExpansions(), m_bndConditions(), m_trace(NullExpListSharedPtr), + m_periodicVerts(), m_periodicEdges(), m_periodicFwdCopy(), + m_periodicBwdCopy() +{ + + if (variable.compare("DefaultVar") != + 0) // do not set up BCs if default variable + { + SpatialDomains::BoundaryConditions bcs(m_session, graph2D); + GenerateBoundaryConditionExpansion(graph2D, bcs, variable, + DeclareCoeffPhysArrays); + + if (DeclareCoeffPhysArrays) { + EvaluateBoundaryConditions(0.0, variable); } - DisContField2D::DisContField2D( - const DisContField2D &In, - const bool DeclareCoeffPhysArrays) - : ExpList2D (In,DeclareCoeffPhysArrays), - m_bndCondExpansions (In.m_bndCondExpansions), - m_bndConditions (In.m_bndConditions), - m_globalBndMat (In.m_globalBndMat), - m_traceMap (In.m_traceMap), - m_locTraceToTraceMap (In.m_locTraceToTraceMap), - m_boundaryEdges (In.m_boundaryEdges), - m_periodicVerts (In.m_periodicVerts), - m_periodicEdges (In.m_periodicEdges), - m_periodicFwdCopy (In.m_periodicFwdCopy), - m_periodicBwdCopy (In.m_periodicBwdCopy), - m_leftAdjacentEdges (In.m_leftAdjacentEdges) + // Find periodic edges for this variable. + FindPeriodicEdges(bcs, variable); + } + + if (SetUpJustDG) + { + SetUpDG(variable); + } + else + { + // Set element edges to point to Robin BC edges if required. + int i, cnt; + Array ElmtID, EdgeID; + GetBoundaryToElmtMap(ElmtID, EdgeID); + + for (cnt = i = 0; i < m_bndCondExpansions.num_elements(); ++i) { - if (In.m_trace) + MultiRegions::ExpListSharedPtr locExpList; + int e; + locExpList = m_bndCondExpansions[i]; + + for (e = 0; e < locExpList->GetExpSize(); ++e) { - m_trace = MemoryManager::AllocateSharedPtr( - *std::dynamic_pointer_cast(In.m_trace), - DeclareCoeffPhysArrays); + LocalRegions::Expansion2DSharedPtr exp2d = + (*m_exp)[ElmtID[cnt + e]]->as(); + LocalRegions::Expansion1DSharedPtr exp1d = + locExpList->GetExp(e)->as(); + LocalRegions::ExpansionSharedPtr exp = + locExpList->GetExp(e)->as(); + + exp2d->SetEdgeExp(EdgeID[cnt + e], exp1d); + exp1d->SetAdjacentElementExp(EdgeID[cnt + e], exp2d); } + cnt += m_bndCondExpansions[i]->GetExpSize(); } - /** - * @brief Constructs a global discontinuous field based on an input - * mesh with boundary conditions. - */ - DisContField2D::DisContField2D( - const LibUtilities::SessionReaderSharedPtr &pSession, - const SpatialDomains::MeshGraphSharedPtr &graph2D, - const std::string &variable, - const bool SetUpJustDG, - const bool DeclareCoeffPhysArrays, - const Collections::ImplementationType ImpType) - : ExpList2D(pSession, graph2D, DeclareCoeffPhysArrays, variable, - ImpType), - m_bndCondExpansions(), - m_bndConditions(), - m_trace(NullExpListSharedPtr), - m_periodicVerts(), - m_periodicEdges(), - m_periodicFwdCopy(), - m_periodicBwdCopy() + if (m_session->DefinesSolverInfo("PROJECTION")) { - - if (variable.compare("DefaultVar") != 0) // do not set up BCs if default variable + std::string ProjectStr = m_session->GetSolverInfo("PROJECTION"); + if ((ProjectStr == "MixedCGDG") || + (ProjectStr == "Mixed_CG_Discontinuous")) + { + SetUpDG(); + } + else { - SpatialDomains::BoundaryConditions bcs(m_session, graph2D); - GenerateBoundaryConditionExpansion(graph2D, bcs, variable, - DeclareCoeffPhysArrays); + SetUpPhysNormals(); + } + } + else + { + SetUpPhysNormals(); + } + } +} + +/* + * @brief Copy type constructor which declares new boundary conditions + * and re-uses mapping info and trace space if possible + */ +DisContField2D::DisContField2D( + const DisContField2D &In, const SpatialDomains::MeshGraphSharedPtr &graph2D, + const std::string &variable, const bool SetUpJustDG, + const bool DeclareCoeffPhysArrays) + : ExpList2D(In, DeclareCoeffPhysArrays), m_trace(NullExpListSharedPtr) +{ + // Set up boundary conditions for this variable. + // Do not set up BCs if default variable + if (variable.compare("DefaultVar") != 0) + { + SpatialDomains::BoundaryConditions bcs(m_session, graph2D); + GenerateBoundaryConditionExpansion(graph2D, bcs, variable); - if (DeclareCoeffPhysArrays) - { - EvaluateBoundaryConditions(0.0, variable); - } + if (DeclareCoeffPhysArrays) + { + EvaluateBoundaryConditions(0.0, variable); + } - // Find periodic edges for this variable. - FindPeriodicEdges(bcs, variable); - } + if (!SameTypeOfBoundaryConditions(In)) + { + // Find periodic edges for this variable. + FindPeriodicEdges(bcs, variable); if (SetUpJustDG) { - SetUpDG(variable); + SetUpDG(); } else { - // Set element edges to point to Robin BC edges if required. - int i, cnt; + // set elmt edges to point to robin bc edges if required + int i, cnt = 0; Array ElmtID, EdgeID; GetBoundaryToElmtMap(ElmtID, EdgeID); - for(cnt = i = 0; i < m_bndCondExpansions.num_elements(); ++i) + for (i = 0; i < m_bndCondExpansions.num_elements(); ++i) { MultiRegions::ExpListSharedPtr locExpList; + int e; locExpList = m_bndCondExpansions[i]; - - for(e = 0; e < locExpList->GetExpSize(); ++e) + + for (e = 0; e < locExpList->GetExpSize(); ++e) { LocalRegions::Expansion2DSharedPtr exp2d = - (*m_exp)[ElmtID[cnt+e]]-> - as(); + (*m_exp)[ElmtID[cnt + e]] + ->as(); LocalRegions::Expansion1DSharedPtr exp1d = - locExpList->GetExp(e)-> - as(); - LocalRegions::ExpansionSharedPtr exp = - locExpList->GetExp(e)-> - as (); - - exp2d->SetEdgeExp(EdgeID[cnt+e], exp1d); - exp1d->SetAdjacentElementExp(EdgeID[cnt+e], exp2d); + locExpList->GetExp(e) + ->as(); + LocalRegions::ExpansionSharedPtr exp = + locExpList->GetExp(e) + ->as(); + + exp2d->SetEdgeExp(EdgeID[cnt + e], exp1d); + exp1d->SetAdjacentElementExp(EdgeID[cnt + e], exp2d); } + cnt += m_bndCondExpansions[i]->GetExpSize(); } - - if(m_session->DefinesSolverInfo("PROJECTION")) + + if (m_session->DefinesSolverInfo("PROJECTION")) { std::string ProjectStr = - m_session->GetSolverInfo("PROJECTION"); - if((ProjectStr == "MixedCGDG") || - (ProjectStr == "Mixed_CG_Discontinuous")) + m_session->GetSolverInfo("PROJECTION"); + + if ((ProjectStr == "MixedCGDG") || + (ProjectStr == "Mixed_CG_Discontinuous")) { SetUpDG(); } @@ -186,2374 +257,2193 @@ namespace Nektar } } } - - - /* - * @brief Copy type constructor which declares new boundary conditions - * and re-uses mapping info and trace space if possible - */ - DisContField2D::DisContField2D( - const DisContField2D &In, - const SpatialDomains::MeshGraphSharedPtr &graph2D, - const std::string &variable, - const bool SetUpJustDG, - const bool DeclareCoeffPhysArrays): - ExpList2D(In,DeclareCoeffPhysArrays), - m_trace(NullExpListSharedPtr) + else { - // Set up boundary conditions for this variable. - // Do not set up BCs if default variable - if(variable.compare("DefaultVar") != 0) + if (SetUpJustDG) { - SpatialDomains::BoundaryConditions bcs(m_session, graph2D); - GenerateBoundaryConditionExpansion(graph2D, bcs, variable); - - if (DeclareCoeffPhysArrays) - { - EvaluateBoundaryConditions(0.0, variable); - } - - if (!SameTypeOfBoundaryConditions(In)) - { - // Find periodic edges for this variable. - FindPeriodicEdges(bcs, variable); - - if(SetUpJustDG) - { - SetUpDG(); - } - else - { - // set elmt edges to point to robin bc edges if required - int i, cnt = 0; - Array ElmtID,EdgeID; - GetBoundaryToElmtMap(ElmtID,EdgeID); - - for (i = 0; i < m_bndCondExpansions.num_elements(); ++i) - { - MultiRegions::ExpListSharedPtr locExpList; - - int e; - locExpList = m_bndCondExpansions[i]; - - for(e = 0; e < locExpList->GetExpSize(); ++e) - { - LocalRegions::Expansion2DSharedPtr exp2d - = (*m_exp)[ElmtID[cnt+e]]-> - as(); - LocalRegions::Expansion1DSharedPtr exp1d - = locExpList->GetExp(e)-> - as(); - LocalRegions::ExpansionSharedPtr exp - = locExpList->GetExp(e)-> - as (); - - exp2d->SetEdgeExp(EdgeID[cnt+e], exp1d); - exp1d->SetAdjacentElementExp(EdgeID[cnt+e], - exp2d); - } - - cnt += m_bndCondExpansions[i]->GetExpSize(); - } - - - if (m_session->DefinesSolverInfo("PROJECTION")) - { - std::string ProjectStr = - m_session->GetSolverInfo("PROJECTION"); - - if ((ProjectStr == "MixedCGDG") || - (ProjectStr == "Mixed_CG_Discontinuous")) - { - SetUpDG(); - } - else - { - SetUpPhysNormals(); - } - } - else - { - SetUpPhysNormals(); - } - } - } - else + m_globalBndMat = In.m_globalBndMat; + m_trace = In.m_trace; + m_traceMap = In.m_traceMap; + m_locTraceToTraceMap = In.m_locTraceToTraceMap; + m_periodicEdges = In.m_periodicEdges; + m_periodicVerts = In.m_periodicVerts; + m_periodicFwdCopy = In.m_periodicFwdCopy; + m_periodicBwdCopy = In.m_periodicBwdCopy; + m_boundaryEdges = In.m_boundaryEdges; + m_leftAdjacentEdges = In.m_leftAdjacentEdges; + } + else + { + m_globalBndMat = In.m_globalBndMat; + m_trace = In.m_trace; + m_traceMap = In.m_traceMap; + m_locTraceToTraceMap = In.m_locTraceToTraceMap; + m_periodicEdges = In.m_periodicEdges; + m_periodicVerts = In.m_periodicVerts; + m_periodicFwdCopy = In.m_periodicFwdCopy; + m_periodicBwdCopy = In.m_periodicBwdCopy; + m_boundaryEdges = In.m_boundaryEdges; + m_leftAdjacentEdges = In.m_leftAdjacentEdges; + + // set elmt edges to point to robin bc edges if required + int i, cnt = 0; + Array ElmtID, EdgeID; + GetBoundaryToElmtMap(ElmtID, EdgeID); + + for (i = 0; i < m_bndCondExpansions.num_elements(); ++i) { - if (SetUpJustDG) - { - m_globalBndMat = In.m_globalBndMat; - m_trace = In.m_trace; - m_traceMap = In.m_traceMap; - m_locTraceToTraceMap = In.m_locTraceToTraceMap; - m_periodicEdges = In.m_periodicEdges; - m_periodicVerts = In.m_periodicVerts; - m_periodicFwdCopy = In.m_periodicFwdCopy; - m_periodicBwdCopy = In.m_periodicBwdCopy; - m_boundaryEdges = In.m_boundaryEdges; - m_leftAdjacentEdges = In.m_leftAdjacentEdges; - } - else + MultiRegions::ExpListSharedPtr locExpList; + + int e; + locExpList = m_bndCondExpansions[i]; + + for (e = 0; e < locExpList->GetExpSize(); ++e) { - m_globalBndMat = In.m_globalBndMat; - m_trace = In.m_trace; - m_traceMap = In.m_traceMap; - m_locTraceToTraceMap = In.m_locTraceToTraceMap; - m_periodicEdges = In.m_periodicEdges; - m_periodicVerts = In.m_periodicVerts; - m_periodicFwdCopy = In.m_periodicFwdCopy; - m_periodicBwdCopy = In.m_periodicBwdCopy; - m_boundaryEdges = In.m_boundaryEdges; - m_leftAdjacentEdges = In.m_leftAdjacentEdges; - - // set elmt edges to point to robin bc edges if required - int i, cnt = 0; - Array ElmtID, EdgeID; - GetBoundaryToElmtMap(ElmtID, EdgeID); - - for (i = 0; i < m_bndCondExpansions.num_elements(); ++i) - { - MultiRegions::ExpListSharedPtr locExpList; - - int e; - locExpList = m_bndCondExpansions[i]; - - for (e = 0; e < locExpList->GetExpSize(); ++e) - { - LocalRegions::Expansion2DSharedPtr exp2d - = (*m_exp)[ElmtID[cnt+e]]-> - as(); - LocalRegions::Expansion1DSharedPtr exp1d - = locExpList->GetExp(e)-> - as(); - LocalRegions::ExpansionSharedPtr exp - = locExpList->GetExp(e)-> - as (); - - exp2d->SetEdgeExp(EdgeID[cnt+e], exp1d); - exp1d->SetAdjacentElementExp(EdgeID[cnt+e], - exp2d); - } - cnt += m_bndCondExpansions[i]->GetExpSize(); - } - - SetUpPhysNormals(); + LocalRegions::Expansion2DSharedPtr exp2d = + (*m_exp)[ElmtID[cnt + e]] + ->as(); + LocalRegions::Expansion1DSharedPtr exp1d = + locExpList->GetExp(e) + ->as(); + LocalRegions::ExpansionSharedPtr exp = + locExpList->GetExp(e) + ->as(); + + exp2d->SetEdgeExp(EdgeID[cnt + e], exp1d); + exp1d->SetAdjacentElementExp(EdgeID[cnt + e], exp2d); } + cnt += m_bndCondExpansions[i]->GetExpSize(); } + + SetUpPhysNormals(); } } + } +} + +/** + * @brief Default destructor. + */ +DisContField2D::~DisContField2D() +{ +} + +GlobalLinSysSharedPtr DisContField2D::GetGlobalBndLinSys( + const GlobalLinSysKey &mkey) +{ + ASSERTL0(mkey.GetMatrixType() == StdRegions::eHybridDGHelmBndLam, + "Routine currently only tested for HybridDGHelmholtz"); + ASSERTL1(mkey.GetGlobalSysSolnType() == m_traceMap->GetGlobalSysSolnType(), + "The local to global map is not set up for the requested " + "solution type"); + + GlobalLinSysSharedPtr glo_matrix; + auto matrixIter = m_globalBndMat->find(mkey); + + if (matrixIter == m_globalBndMat->end()) + { + glo_matrix = GenGlobalBndLinSys(mkey, m_traceMap); + (*m_globalBndMat)[mkey] = glo_matrix; + } + else + { + glo_matrix = matrixIter->second; + } + + return glo_matrix; +} - /** - * @brief Default destructor. - */ - DisContField2D::~DisContField2D() +/** + * @brief Set up all DG member variables and maps. + */ +void DisContField2D::SetUpDG(const std::string variable) +{ + // Check for multiple calls + if (m_trace != NullExpListSharedPtr) + { + return; + } + + ExpList1DSharedPtr trace; + + // Set up matrix map + m_globalBndMat = MemoryManager::AllocateSharedPtr(); + + // Set up trace space + trace = MemoryManager::AllocateSharedPtr( + m_session, m_bndCondExpansions, m_bndConditions, *m_exp, m_graph, + m_periodicEdges); + + m_trace = std::dynamic_pointer_cast(trace); + m_traceMap = MemoryManager::AllocateSharedPtr( + m_session, m_graph, trace, *this, m_bndCondExpansions, m_bndConditions, + m_periodicEdges, variable); + + if (m_session->DefinesCmdLineArgument("verbose")) + { + m_traceMap->PrintStats(std::cout, variable); + } + + Array> &elmtToTrace = + m_traceMap->GetElmtToTrace(); + + // Scatter trace segments to 2D elements. For each element, + // we find the trace segment associated to each edge. The + // element then retains a pointer to the trace space segments, + // to ensure uniqueness of normals when retrieving from two + // adjoining elements which do not lie in a plane. + for (int i = 0; i < m_exp->size(); ++i) + { + for (int j = 0; j < (*m_exp)[i]->GetNedges(); ++j) { + LocalRegions::Expansion2DSharedPtr exp2d = + (*m_exp)[i]->as(); + LocalRegions::Expansion1DSharedPtr exp1d = + elmtToTrace[i][j]->as(); + LocalRegions::ExpansionSharedPtr exp = elmtToTrace[i][j]; + ; + exp2d->SetEdgeExp(j, exp1d); + exp1d->SetAdjacentElementExp(j, exp2d); } - - GlobalLinSysSharedPtr DisContField2D::GetGlobalBndLinSys( - const GlobalLinSysKey &mkey) - { - ASSERTL0(mkey.GetMatrixType() == StdRegions::eHybridDGHelmBndLam, - "Routine currently only tested for HybridDGHelmholtz"); - ASSERTL1(mkey.GetGlobalSysSolnType() == - m_traceMap->GetGlobalSysSolnType(), - "The local to global map is not set up for the requested " - "solution type"); + } - GlobalLinSysSharedPtr glo_matrix; - auto matrixIter = m_globalBndMat->find(mkey); + // Set up physical normals + SetUpPhysNormals(); - if(matrixIter == m_globalBndMat->end()) - { - glo_matrix = GenGlobalBndLinSys(mkey,m_traceMap); - (*m_globalBndMat)[mkey] = glo_matrix; - } - else + std::unordered_map traceIdToElmt; + + // Set up information for parallel and periodic problems. + for (int i = 0; i < m_trace->GetExpSize(); ++i) + { + LocalRegions::Expansion1DSharedPtr traceEl = + m_trace->GetExp(i)->as(); + + int offset = m_trace->GetPhys_Offset(i); + int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); + auto pIt = m_periodicEdges.find(traceGeomId); + + traceIdToElmt[traceGeomId] = i; + + if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) + { + if (traceGeomId != min(pIt->second[0].id, traceGeomId)) { - glo_matrix = matrixIter->second; + traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( + traceEl->GetLeftAdjacentElementEdge()); } + } + else if (m_traceMap->GetTraceToUniversalMapUnique(offset) < 0) + { + traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( + traceEl->GetLeftAdjacentElementEdge()); + } + } + + // Loop over all interface edges and then negate edge normals + // corresponding to the 'moving' side. Keep track of both interior + // and exterior interface components. + for (auto &interface : m_interfaces) + { + for (auto &iter : interface.second->GetEdgeRight()) + { + int id = iter.first; + auto traceEl = std::dynamic_pointer_cast( + m_trace->GetExp(traceIdToElmt[id])); + traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( + traceEl->GetLeftAdjacentElementEdge()); + m_traceEdgeRight[interface.first][id] = traceEl; + m_interfaceEdgeRight.insert(id); + } - return glo_matrix; + for (auto &iter : interface.second->GetEdgeLeft()) + { + int id = iter.first; + auto traceEl = std::dynamic_pointer_cast( + m_trace->GetExp(traceIdToElmt[id])); + m_traceEdgeLeft[interface.first][id] = traceEl; + m_interfaceEdgeLeft.insert(id); } + } + + int cnt, n, e; - /** - * @brief Set up all DG member variables and maps. - */ - void DisContField2D::SetUpDG(const std::string variable) + // Identify boundary edges + for (cnt = 0, n = 0; n < m_bndCondExpansions.num_elements(); ++n) + { + if (m_bndConditions[n]->GetBoundaryConditionType() != + SpatialDomains::ePeriodic) { - // Check for multiple calls - if (m_trace != NullExpListSharedPtr) - { - return; - } - - ExpList1DSharedPtr trace; - - // Set up matrix map - m_globalBndMat = MemoryManager:: - AllocateSharedPtr(); - - // Set up trace space - trace = MemoryManager::AllocateSharedPtr( - m_session, m_bndCondExpansions, m_bndConditions, *m_exp, - m_graph, m_periodicEdges); - - m_trace = std::dynamic_pointer_cast(trace); - m_traceMap = MemoryManager:: - AllocateSharedPtr(m_session, m_graph, trace, *this, - m_bndCondExpansions, m_bndConditions, - m_periodicEdges, - variable); - - if (m_session->DefinesCmdLineArgument("verbose")) + for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) { - m_traceMap->PrintStats(std::cout, variable); + m_boundaryEdges.insert( + m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt + e)); } + cnt += m_bndCondExpansions[n]->GetExpSize(); + } + } - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); + // Set up information for periodic boundary conditions. + std::unordered_map> perEdgeToExpMap; + for (cnt = n = 0; n < m_exp->size(); ++n) + { + for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e, ++cnt) + { + auto it = m_periodicEdges.find((*m_exp)[n]->GetGeom()->GetEid(e)); - // Scatter trace segments to 2D elements. For each element, - // we find the trace segment associated to each edge. The - // element then retains a pointer to the trace space segments, - // to ensure uniqueness of normals when retrieving from two - //adjoining elements which do not lie in a plane. - for (int i = 0; i < m_exp->size(); ++i) + if (it != m_periodicEdges.end()) { - for (int j = 0; j < (*m_exp)[i]->GetNedges(); ++j) - { - LocalRegions::Expansion2DSharedPtr exp2d = - (*m_exp)[i]->as(); - LocalRegions::Expansion1DSharedPtr exp1d = - elmtToTrace[i][j]->as(); - LocalRegions::ExpansionSharedPtr exp = elmtToTrace[i][j];; - exp2d->SetEdgeExp (j, exp1d); - exp1d->SetAdjacentElementExp(j, exp2d); - } + perEdgeToExpMap[it->first] = make_pair(n, e); } - - // Set up physical normals - SetUpPhysNormals(); + } + } - std::unordered_map traceIdToElmt; - - // Set up information for parallel and periodic problems. - for (int i = 0; i < m_trace->GetExpSize(); ++i) - { - LocalRegions::Expansion1DSharedPtr traceEl = - m_trace->GetExp(i)->as(); - - int offset = m_trace->GetPhys_Offset(i); - int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); - auto pIt = m_periodicEdges.find(traceGeomId); + // Set up left-adjacent edge list. + m_leftAdjacentEdges.resize(cnt); + cnt = 0; + for (int i = 0; i < m_exp->size(); ++i) + { + for (int j = 0; j < (*m_exp)[i]->GetNedges(); ++j, ++cnt) + { + m_leftAdjacentEdges[cnt] = IsLeftAdjacentEdge(i, j); + } + } + + // Set up mapping to copy Fwd of periodic bcs to Bwd of other edge. + cnt = 0; + for (int n = 0; n < m_exp->size(); ++n) + { + for (int e = 0; e < (*m_exp)[n]->GetNedges(); ++e, ++cnt) + { + int edgeGeomId = (*m_exp)[n]->GetGeom()->GetEid(e); + int offset = + m_trace->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId()); + + // Check to see if this face is periodic. + auto it = m_periodicEdges.find(edgeGeomId); - traceIdToElmt[traceGeomId] = i; + if (it != m_periodicEdges.end()) + { + const PeriodicEntity &ent = it->second[0]; + auto it2 = perEdgeToExpMap.find(ent.id); - if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) + if (it2 == perEdgeToExpMap.end()) { - if (traceGeomId != min(pIt->second[0].id, traceGeomId)) + if (m_session->GetComm()->GetRowComm()->GetSize() > 1 && + !ent.isLocal) + { + continue; + } + else { - traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( - traceEl->GetLeftAdjacentElementEdge()); + ASSERTL1(false, "Periodic edge not found!"); } } - else if (m_traceMap->GetTraceToUniversalMapUnique(offset) < 0) - { - traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( - traceEl->GetLeftAdjacentElementEdge()); - } - } - // Loop over all interface edges and then negate edge normals - // corresponding to the 'moving' side. Keep track of both interior - // and exterior interface components. - for (auto &interface : m_interfaces) - { - for (auto &iter : interface.second->GetEdgeRight()) - { - int id = iter.first; - auto traceEl = std::dynamic_pointer_cast< - LocalRegions::Expansion1D>( - m_trace->GetExp(traceIdToElmt[id])); - traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( - traceEl->GetLeftAdjacentElementEdge()); - m_traceEdgeRight[interface.first].push_back(traceEl); - m_interfaceEdgeRight.insert(id); - } + ASSERTL1(m_leftAdjacentEdges[cnt], + "Periodic edge in non-forward space?"); - for (auto &iter : interface.second->GetEdgeLeft()) - { - int id = iter.first; - auto traceEl = std::dynamic_pointer_cast< - LocalRegions::Expansion1D>( - m_trace->GetExp(traceIdToElmt[id])); - m_traceEdgeLeft[interface.first].push_back(traceEl); - m_interfaceEdgeLeft.insert(id); - } - } + int offset2 = m_trace->GetPhys_Offset( + elmtToTrace[it2->second.first][it2->second.second] + ->GetElmtId()); - int cnt, n, e; + // Calculate relative orientations between edges to + // calculate copying map. + int nquad = elmtToTrace[n][e]->GetNumPoints(0); - // Identify boundary edges - for (cnt = 0, n = 0; n < m_bndCondExpansions.num_elements(); ++n) - { - if (m_bndConditions[n]->GetBoundaryConditionType() != - SpatialDomains::ePeriodic) + vector tmpBwd(nquad); + vector tmpFwd(nquad); + + if (ent.orient == StdRegions::eForwards) { - for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) + for (int i = 0; i < nquad; ++i) { - m_boundaryEdges.insert( - m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt+e)); + tmpBwd[i] = offset2 + i; + tmpFwd[i] = offset + i; } - cnt += m_bndCondExpansions[n]->GetExpSize(); } - } - - // Set up information for periodic boundary conditions. - std::unordered_map > perEdgeToExpMap; - for (cnt = n = 0; n < m_exp->size(); ++n) - { - for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e, ++cnt) + else { - auto it = m_periodicEdges.find( - (*m_exp)[n]->GetGeom()->GetEid(e)); - - if (it != m_periodicEdges.end()) + for (int i = 0; i < nquad; ++i) { - perEdgeToExpMap[it->first] = make_pair(n, e); + tmpBwd[i] = offset2 + i; + tmpFwd[i] = offset + nquad - i - 1; } } - } - // Set up left-adjacent edge list. - m_leftAdjacentEdges.resize(cnt); - cnt = 0; - for (int i = 0; i < m_exp->size(); ++i) - { - for (int j = 0; j < (*m_exp)[i]->GetNedges(); ++j, ++cnt) + for (int i = 0; i < nquad; ++i) { - m_leftAdjacentEdges[cnt] = IsLeftAdjacentEdge(i, j); + m_periodicFwdCopy.push_back(tmpFwd[i]); + m_periodicBwdCopy.push_back(tmpBwd[i]); } } + } + } + + m_locTraceToTraceMap = MemoryManager::AllocateSharedPtr( + *this, m_trace, elmtToTrace, m_leftAdjacentEdges); +} + +/** + * For each boundary region, checks that the types and number of + * boundary expansions in that region match. + * @param In ContField2D to compare with. + * @return True if boundary conditions match. + */ +bool DisContField2D::SameTypeOfBoundaryConditions(const DisContField2D &In) +{ + int i; + bool returnval = true; - // Set up mapping to copy Fwd of periodic bcs to Bwd of other edge. - cnt = 0; - for (int n = 0; n < m_exp->size(); ++n) - { - for (int e = 0; e < (*m_exp)[n]->GetNedges(); ++e, ++cnt) - { - int edgeGeomId = (*m_exp)[n]->GetGeom()->GetEid(e); - int offset = m_trace->GetPhys_Offset( - elmtToTrace[n][e]->GetElmtId()); - - // Check to see if this face is periodic. - auto it = m_periodicEdges.find(edgeGeomId); - - if (it != m_periodicEdges.end()) - { - const PeriodicEntity &ent = it->second[0]; - auto it2 = perEdgeToExpMap.find(ent.id); + for (i = 0; i < m_bndConditions.num_elements(); ++i) + { - if (it2 == perEdgeToExpMap.end()) - { - if (m_session->GetComm()-> - GetRowComm()->GetSize() > 1 && !ent.isLocal) - { - continue; - } - else - { - ASSERTL1(false, "Periodic edge not found!"); - } - } + // check to see if boundary condition type is the same + // and there are the same number of boundary + // conditions in the boundary definition. + if ((m_bndConditions[i]->GetBoundaryConditionType() != + In.m_bndConditions[i]->GetBoundaryConditionType()) || + (m_bndCondExpansions[i]->GetExpSize() != + In.m_bndCondExpansions[i]->GetExpSize())) + { + returnval = false; + break; + } + } + + // Compare with all other processes. Return true only if all + // processes report having the same boundary conditions. + int vSame = (returnval ? 1 : 0); + m_comm->GetRowComm()->AllReduce(vSame, LibUtilities::ReduceMin); + + return (vSame == 1); +} + +/** + * \brief This function discretises the boundary conditions by setting + * up a list of one-dimensional boundary expansions. + * + * According to their boundary region, the separate segmental boundary + * expansions are bundled together in an object of the class + * MultiRegions#ExpList1D. + * + * \param graph2D A mesh, containing information about the domain and + * the spectral/hp element expansion. + * \param bcs An entity containing information about the + * boundaries and boundary conditions. + * \param variable An optional parameter to indicate for which variable + * the boundary conditions should be discretised. + */ +void DisContField2D::GenerateBoundaryConditionExpansion( + const SpatialDomains::MeshGraphSharedPtr &graph2D, + const SpatialDomains::BoundaryConditions &bcs, const std::string &variable, + const bool DeclareCoeffPhysArrays) +{ + int cnt = 0; + SpatialDomains::BoundaryConditionShPtr bc; + MultiRegions::ExpList1DSharedPtr locExpList; + const SpatialDomains::BoundaryRegionCollection &bregions = + bcs.GetBoundaryRegions(); + const SpatialDomains::BoundaryConditionCollection &bconditions = + bcs.GetBoundaryConditions(); + + m_bndCondExpansions = + Array(bregions.size()); + m_bndConditions = + Array(bregions.size()); + + for (auto &it : bregions) + { + bc = GetBoundaryCondition(bconditions, it.first, variable); - ASSERTL1(m_leftAdjacentEdges[cnt], - "Periodic edge in non-forward space?"); + locExpList = MemoryManager::AllocateSharedPtr( + m_session, *(it.second), graph2D, DeclareCoeffPhysArrays, variable, + bc->GetComm()); - int offset2 = m_trace->GetPhys_Offset( - elmtToTrace[it2->second.first][it2->second.second]-> - GetElmtId()); + m_bndCondExpansions[cnt] = locExpList; + m_bndConditions[cnt] = bc; - // Calculate relative orientations between edges to - // calculate copying map. - int nquad = elmtToTrace[n][e]->GetNumPoints(0); + std::string type = m_bndConditions[cnt]->GetUserDefined(); - vector tmpBwd(nquad); - vector tmpFwd(nquad); + // Set up normals on non-Dirichlet boundary conditions. Second + // two conditions ideally should be in local solver setup (when + // made into factory) + if (bc->GetBoundaryConditionType() != SpatialDomains::eDirichlet || + boost::iequals(type, "I") || boost::iequals(type, "CalcBC")) + { + SetUpPhysNormals(); + } - if (ent.orient == StdRegions::eForwards) - { - for (int i = 0; i < nquad; ++i) - { - tmpBwd[i] = offset2 + i; - tmpFwd[i] = offset + i; - } - } - else - { - for (int i = 0; i < nquad; ++i) - { - tmpBwd[i] = offset2 + i; - tmpFwd[i] = offset + nquad - i - 1; - } - } + cnt++; + } +} + +/** + * @brief Determine the periodic edges and vertices for the given graph. + * + * Note that much of this routine is the same as the three-dimensional + * version, which therefore has much better documentation. + * + * @param bcs Information about the boundary conditions. + * @param variable Specifies the field. + * + * @see DisContField3D::FindPeriodicFaces + */ +void DisContField2D::FindPeriodicEdges( + const SpatialDomains::BoundaryConditions &bcs, const std::string &variable) +{ + const SpatialDomains::BoundaryRegionCollection &bregions = + bcs.GetBoundaryRegions(); + const SpatialDomains::BoundaryConditionCollection &bconditions = + bcs.GetBoundaryConditions(); + + LibUtilities::CommSharedPtr vComm = m_session->GetComm()->GetRowComm(); + SpatialDomains::CompositeOrdering compOrder = + m_graph->GetCompositeOrdering(); + SpatialDomains::BndRegionOrdering bndRegOrder = + m_graph->GetBndRegionOrdering(); + SpatialDomains::CompositeMap compMap = m_graph->GetComposites(); + + // Unique collection of pairs of periodic composites (i.e. if + // composites 1 and 2 are periodic then this map will contain either + // the pair (1,2) or (2,1) but not both). + map perComps; + map> allVerts; + set locVerts; + map> allEdges; + + int region1ID, region2ID, i, j, k, cnt; + SpatialDomains::BoundaryConditionShPtr locBCond; + + // Set up a set of all local verts and edges. + for (i = 0; i < (*m_exp).size(); ++i) + { + for (j = 0; j < (*m_exp)[i]->GetNverts(); ++j) + { + int id = (*m_exp)[i]->GetGeom()->GetVid(j); + locVerts.insert(id); + } + } - for (int i = 0; i < nquad; ++i) - { - m_periodicFwdCopy.push_back(tmpFwd[i]); - m_periodicBwdCopy.push_back(tmpBwd[i]); - } - } - } - } + // Construct list of all periodic pairs local to this process. + for (auto &it : bregions) + { + locBCond = GetBoundaryCondition(bconditions, it.first, variable); - m_locTraceToTraceMap = MemoryManager:: - AllocateSharedPtr(*this, m_trace, elmtToTrace, - m_leftAdjacentEdges); + if (locBCond->GetBoundaryConditionType() != SpatialDomains::ePeriodic) + { + continue; } - /** - * For each boundary region, checks that the types and number of - * boundary expansions in that region match. - * @param In ContField2D to compare with. - * @return True if boundary conditions match. - */ - bool DisContField2D::SameTypeOfBoundaryConditions( - const DisContField2D &In) + // Identify periodic boundary region IDs. + region1ID = it.first; + region2ID = + std::static_pointer_cast( + locBCond) + ->m_connectedBoundaryRegion; + + // From this identify composites. Note that in serial this will + // be an empty map. + int cId1, cId2; + if (vComm->GetSize() == 1) { - int i; - bool returnval = true; - - for(i = 0; i < m_bndConditions.num_elements(); ++i) - { + cId1 = it.second->begin()->first; + cId2 = bregions.find(region2ID)->second->begin()->first; + } + else + { + cId1 = bndRegOrder.find(region1ID)->second[0]; + cId2 = bndRegOrder.find(region2ID)->second[0]; + } - // check to see if boundary condition type is the same - // and there are the same number of boundary - // conditions in the boundary definition. - if((m_bndConditions[i]->GetBoundaryConditionType() - != In.m_bndConditions[i]->GetBoundaryConditionType())|| - (m_bndCondExpansions[i]->GetExpSize() - != In.m_bndCondExpansions[i]->GetExpSize())) - { - returnval = false; - break; - } - } + ASSERTL0(it.second->size() == 1, + "Boundary region " + boost::lexical_cast(region1ID) + + " should only contain 1 composite."); - // Compare with all other processes. Return true only if all - // processes report having the same boundary conditions. - int vSame = (returnval?1:0); - m_comm->GetRowComm()->AllReduce(vSame, LibUtilities::ReduceMin); + // Construct set containing all periodic edges on this process + SpatialDomains::CompositeSharedPtr c = it.second->begin()->second; - return (vSame == 1); - } + vector tmpOrder; - /** - * \brief This function discretises the boundary conditions by setting - * up a list of one-dimensional boundary expansions. - * - * According to their boundary region, the separate segmental boundary - * expansions are bundled together in an object of the class - * MultiRegions#ExpList1D. - * - * \param graph2D A mesh, containing information about the domain and - * the spectral/hp element expansion. - * \param bcs An entity containing information about the - * boundaries and boundary conditions. - * \param variable An optional parameter to indicate for which variable - * the boundary conditions should be discretised. - */ - void DisContField2D::GenerateBoundaryConditionExpansion( - const SpatialDomains::MeshGraphSharedPtr &graph2D, - const SpatialDomains::BoundaryConditions &bcs, - const std::string &variable, - const bool DeclareCoeffPhysArrays) + for (i = 0; i < c->m_geomVec.size(); ++i) { - int cnt = 0; - SpatialDomains::BoundaryConditionShPtr bc; - MultiRegions::ExpList1DSharedPtr locExpList; - const SpatialDomains::BoundaryRegionCollection &bregions = - bcs.GetBoundaryRegions(); - const SpatialDomains::BoundaryConditionCollection &bconditions = - bcs.GetBoundaryConditions(); - - m_bndCondExpansions = - Array(bregions.size()); - m_bndConditions = - Array(bregions.size()); - - for (auto &it : bregions) + SpatialDomains::SegGeomSharedPtr segGeom = + std::dynamic_pointer_cast( + c->m_geomVec[i]); + ASSERTL0(segGeom, "Unable to cast to shared ptr"); + + SpatialDomains::GeometryLinkSharedPtr elmt = + m_graph->GetElementsFromEdge(segGeom); + ASSERTL0(elmt->size() == 1, "The periodic boundaries belong to " + "more than one element of the mesh"); + + SpatialDomains::Geometry2DSharedPtr geom = + std::dynamic_pointer_cast( + elmt->at(0).first); + + allEdges[c->m_geomVec[i]->GetGlobalID()] = make_pair( + elmt->at(0).second, geom->GetEorient(elmt->at(0).second)); + + // In serial mesh partitioning will not have occurred so + // need to fill composite ordering map manually. + if (vComm->GetSize() == 1) { - bc = GetBoundaryCondition(bconditions, it.first, variable); - - locExpList = MemoryManager - ::AllocateSharedPtr(m_session, *(it.second), graph2D, - DeclareCoeffPhysArrays, variable, - bc->GetComm()); - - m_bndCondExpansions[cnt] = locExpList; - m_bndConditions[cnt] = bc; - - std::string type = m_bndConditions[cnt]->GetUserDefined(); + tmpOrder.push_back(c->m_geomVec[i]->GetGlobalID()); + } - // Set up normals on non-Dirichlet boundary conditions. Second - // two conditions ideally should be in local solver setup (when - // made into factory) - if(bc->GetBoundaryConditionType() != SpatialDomains::eDirichlet - || boost::iequals(type,"I") || boost::iequals(type,"CalcBC")) - { - SetUpPhysNormals(); - } + vector vertList(2); + vertList[0] = segGeom->GetVid(0); + vertList[1] = segGeom->GetVid(1); + allVerts[c->m_geomVec[i]->GetGlobalID()] = vertList; + } - cnt++; - } + if (vComm->GetSize() == 1) + { + compOrder[it.second->begin()->first] = tmpOrder; } - /** - * @brief Determine the periodic edges and vertices for the given graph. - * - * Note that much of this routine is the same as the three-dimensional - * version, which therefore has much better documentation. - * - * @param bcs Information about the boundary conditions. - * @param variable Specifies the field. - * - * @see DisContField3D::FindPeriodicFaces - */ - void DisContField2D::FindPeriodicEdges( - const SpatialDomains::BoundaryConditions &bcs, - const std::string &variable) + // See if we already have either region1 or region2 stored in + // perComps map. + if (perComps.count(cId1) == 0) { - const SpatialDomains::BoundaryRegionCollection &bregions - = bcs.GetBoundaryRegions(); - const SpatialDomains::BoundaryConditionCollection &bconditions - = bcs.GetBoundaryConditions(); - - LibUtilities::CommSharedPtr vComm = - m_session->GetComm()->GetRowComm(); - SpatialDomains::CompositeOrdering compOrder = - m_graph->GetCompositeOrdering(); - SpatialDomains::BndRegionOrdering bndRegOrder = - m_graph->GetBndRegionOrdering(); - SpatialDomains::CompositeMap compMap = - m_graph->GetComposites(); - - // Unique collection of pairs of periodic composites (i.e. if - // composites 1 and 2 are periodic then this map will contain either - // the pair (1,2) or (2,1) but not both). - map perComps; - map> allVerts; - set locVerts; - map> allEdges; - - int region1ID, region2ID, i, j, k, cnt; - SpatialDomains::BoundaryConditionShPtr locBCond; - - // Set up a set of all local verts and edges. - for(i = 0; i < (*m_exp).size(); ++i) + if (perComps.count(cId2) == 0) { - for(j = 0; j < (*m_exp)[i]->GetNverts(); ++j) - { - int id = (*m_exp)[i]->GetGeom()->GetVid(j); - locVerts.insert(id); - } + perComps[cId1] = cId2; } - - // Construct list of all periodic pairs local to this process. - for (auto &it : bregions) + else { - locBCond = GetBoundaryCondition( - bconditions, it.first, variable); - - if (locBCond->GetBoundaryConditionType() - != SpatialDomains::ePeriodic) - { - continue; - } + std::stringstream ss; + ss << "Boundary region " << cId2 << " should be " + << "periodic with " << perComps[cId2] << " but " + << "found " << cId1 << " instead!"; + ASSERTL0(perComps[cId2] == cId1, ss.str()); + } + } + else + { + std::stringstream ss; + ss << "Boundary region " << cId1 << " should be " + << "periodic with " << perComps[cId1] << " but " + << "found " << cId2 << " instead!"; + ASSERTL0(perComps[cId1] == cId1, ss.str()); + } + } - // Identify periodic boundary region IDs. - region1ID = it.first; - region2ID = std::static_pointer_cast< - SpatialDomains::PeriodicBoundaryCondition>( - locBCond)->m_connectedBoundaryRegion; + // Process local edge list to obtain relative edge orientations. + int n = vComm->GetSize(); + int p = vComm->GetRank(); + int totEdges; + Array edgecounts(n, 0); + Array edgeoffset(n, 0); + Array vertoffset(n, 0); - // From this identify composites. Note that in serial this will - // be an empty map. - int cId1, cId2; - if (vComm->GetSize() == 1) - { - cId1 = it.second->begin()->first; - cId2 = bregions.find(region2ID)->second->begin()->first; - } - else - { - cId1 = bndRegOrder.find(region1ID)->second[0]; - cId2 = bndRegOrder.find(region2ID)->second[0]; - } + edgecounts[p] = allEdges.size(); + vComm->AllReduce(edgecounts, LibUtilities::ReduceSum); - ASSERTL0(it.second->size() == 1, - "Boundary region "+boost::lexical_cast( - region1ID)+" should only contain 1 composite."); + edgeoffset[0] = 0; + for (i = 1; i < n; ++i) + { + edgeoffset[i] = edgeoffset[i - 1] + edgecounts[i - 1]; + } - // Construct set containing all periodic edges on this process - SpatialDomains::CompositeSharedPtr c = it.second->begin()->second; + totEdges = Vmath::Vsum(n, edgecounts, 1); + Array edgeIds(totEdges, 0); + Array edgeIdx(totEdges, 0); + Array edgeOrient(totEdges, 0); + Array edgeVerts(totEdges, 0); - vector tmpOrder; + auto sIt = allEdges.begin(); - for (i = 0; i < c->m_geomVec.size(); ++i) - { - SpatialDomains::SegGeomSharedPtr segGeom = - std::dynamic_pointer_cast< - SpatialDomains::SegGeom>(c->m_geomVec[i]); - ASSERTL0(segGeom, "Unable to cast to shared ptr"); - - SpatialDomains::GeometryLinkSharedPtr elmt = - m_graph->GetElementsFromEdge(segGeom); - ASSERTL0(elmt->size() == 1, - "The periodic boundaries belong to " - "more than one element of the mesh"); - - SpatialDomains::Geometry2DSharedPtr geom = - std::dynamic_pointer_cast( - elmt->at(0).first); - - allEdges[c->m_geomVec[i]->GetGlobalID()] = - make_pair(elmt->at(0).second, - geom->GetEorient(elmt->at(0).second)); - - // In serial mesh partitioning will not have occurred so - // need to fill composite ordering map manually. - if (vComm->GetSize() == 1) - { - tmpOrder.push_back(c->m_geomVec[i]->GetGlobalID()); - } + for (i = 0; sIt != allEdges.end(); ++sIt) + { + edgeIds[edgeoffset[p] + i] = sIt->first; + edgeIdx[edgeoffset[p] + i] = sIt->second.first; + edgeOrient[edgeoffset[p] + i] = sIt->second.second; + edgeVerts[edgeoffset[p] + i++] = allVerts[sIt->first].size(); + } + + vComm->AllReduce(edgeIds, LibUtilities::ReduceSum); + vComm->AllReduce(edgeIdx, LibUtilities::ReduceSum); + vComm->AllReduce(edgeOrient, LibUtilities::ReduceSum); + vComm->AllReduce(edgeVerts, LibUtilities::ReduceSum); + + // Calculate number of vertices on each processor. + Array procVerts(n, 0); + int nTotVerts; + + // Note if there are no periodic edges at all calling Vsum will + // cause a segfault. + if (totEdges > 0) + { + nTotVerts = Vmath::Vsum(totEdges, edgeVerts, 1); + } + else + { + nTotVerts = 0; + } - vector vertList(2); - vertList[0] = segGeom->GetVid(0); - vertList[1] = segGeom->GetVid(1); - allVerts[c->m_geomVec[i]->GetGlobalID()] = vertList; - } + for (i = 0; i < n; ++i) + { + if (edgecounts[i] > 0) + { + procVerts[i] = + Vmath::Vsum(edgecounts[i], edgeVerts + edgeoffset[i], 1); + } + else + { + procVerts[i] = 0; + } + } + vertoffset[0] = 0; - if (vComm->GetSize() == 1) - { - compOrder[it.second->begin()->first] = tmpOrder; - } + for (i = 1; i < n; ++i) + { + vertoffset[i] = vertoffset[i - 1] + procVerts[i - 1]; + } - // See if we already have either region1 or region2 stored in - // perComps map. - if (perComps.count(cId1) == 0) - { - if (perComps.count(cId2) == 0) - { - perComps[cId1] = cId2; - } - else - { - std::stringstream ss; - ss << "Boundary region " << cId2 << " should be " - << "periodic with " << perComps[cId2] << " but " - << "found " << cId1 << " instead!"; - ASSERTL0(perComps[cId2] == cId1, ss.str()); - } - } - else - { - std::stringstream ss; - ss << "Boundary region " << cId1 << " should be " - << "periodic with " << perComps[cId1] << " but " - << "found " << cId2 << " instead!"; - ASSERTL0(perComps[cId1] == cId1, ss.str()); - } - } + Array vertIds(nTotVerts, 0); + for (i = 0, sIt = allEdges.begin(); sIt != allEdges.end(); ++sIt) + { + for (j = 0; j < allVerts[sIt->first].size(); ++j) + { + vertIds[vertoffset[p] + i++] = allVerts[sIt->first][j]; + } + } - // Process local edge list to obtain relative edge orientations. - int n = vComm->GetSize(); - int p = vComm->GetRank(); - int totEdges; - Array edgecounts(n,0); - Array edgeoffset(n,0); - Array vertoffset(n,0); + vComm->AllReduce(vertIds, LibUtilities::ReduceSum); - edgecounts[p] = allEdges.size(); - vComm->AllReduce(edgecounts, LibUtilities::ReduceSum); + // For simplicity's sake create a map of edge id -> orientation. + map orientMap; + map> vertMap; - edgeoffset[0] = 0; - for (i = 1; i < n; ++i) - { - edgeoffset[i] = edgeoffset[i-1] + edgecounts[i-1]; - } + for (cnt = i = 0; i < totEdges; ++i) + { + ASSERTL0(orientMap.count(edgeIds[i]) == 0, + "Already found edge in orientation map!"); + + // Work out relative orientations. To avoid having to exchange + // vertex locations, we figure out if the edges are backwards or + // forwards orientated with respect to a forwards orientation + // that is CCW. Since our local geometries are + // forwards-orientated with respect to the Cartesian axes, we + // need to invert the orientation for the top and left edges of + // a quad and the left edge of a triangle. + StdRegions::Orientation o = (StdRegions::Orientation)edgeOrient[i]; + + if (edgeIdx[i] > 1) + { + o = o == StdRegions::eForwards ? StdRegions::eBackwards + : StdRegions::eForwards; + } - totEdges = Vmath::Vsum(n, edgecounts, 1); - Array edgeIds (totEdges, 0); - Array edgeIdx (totEdges, 0); - Array edgeOrient(totEdges, 0); - Array edgeVerts (totEdges, 0); + orientMap[edgeIds[i]] = o; - auto sIt = allEdges.begin(); + vector verts(edgeVerts[i]); - for (i = 0; sIt != allEdges.end(); ++sIt) - { - edgeIds [edgeoffset[p] + i ] = sIt->first; - edgeIdx [edgeoffset[p] + i ] = sIt->second.first; - edgeOrient[edgeoffset[p] + i ] = sIt->second.second; - edgeVerts [edgeoffset[p] + i++] = allVerts[sIt->first].size(); - } + for (j = 0; j < edgeVerts[i]; ++j) + { + verts[j] = vertIds[cnt++]; + } + vertMap[edgeIds[i]] = verts; + } + + // Go through list of composites and figure out which edges are + // parallel from original ordering in session file. This includes + // composites which are not necessarily on this process. + map allCompPairs; + + // Store temporary map of periodic vertices which will hold all + // periodic vertices on the entire mesh so that doubly periodic + // vertices can be counted properly across partitions. Local + // vertices are copied into m_periodicVerts at the end of the + // function. + PeriodicMap periodicVerts; + + for (auto &cIt : perComps) + { + SpatialDomains::CompositeSharedPtr c[2]; + const int id1 = cIt.first; + const int id2 = cIt.second; + std::string id1s = boost::lexical_cast(id1); + std::string id2s = boost::lexical_cast(id2); - vComm->AllReduce(edgeIds, LibUtilities::ReduceSum); - vComm->AllReduce(edgeIdx, LibUtilities::ReduceSum); - vComm->AllReduce(edgeOrient, LibUtilities::ReduceSum); - vComm->AllReduce(edgeVerts, LibUtilities::ReduceSum); + if (compMap.count(id1) > 0) + { + c[0] = compMap[id1]; + } - // Calculate number of vertices on each processor. - Array procVerts(n,0); - int nTotVerts; + if (compMap.count(id2) > 0) + { + c[1] = compMap[id2]; + } - // Note if there are no periodic edges at all calling Vsum will - // cause a segfault. - if (totEdges > 0) - { - nTotVerts = Vmath::Vsum(totEdges, edgeVerts, 1); - } - else - { - nTotVerts = 0; - } + ASSERTL0(c[0] || c[1], "Both composites not found on this process!"); + + // Loop over composite ordering to construct list of all + // periodic edges regardless of whether they are on this + // process. + map compPairs; + + ASSERTL0(compOrder.count(id1) > 0, + "Unable to find composite " + id1s + " in order map."); + ASSERTL0(compOrder.count(id2) > 0, + "Unable to find composite " + id2s + " in order map."); + ASSERTL0(compOrder[id1].size() == compOrder[id2].size(), + "Periodic composites " + id1s + " and " + id2s + + " should have the same number of elements."); + ASSERTL0(compOrder[id1].size() > 0, "Periodic composites " + id1s + + " and " + id2s + " are empty!"); + + // TODO: Add more checks. + for (i = 0; i < compOrder[id1].size(); ++i) + { + int eId1 = compOrder[id1][i]; + int eId2 = compOrder[id2][i]; - for (i = 0; i < n; ++i) + ASSERTL0(compPairs.count(eId1) == 0, "Already paired."); + + if (compPairs.count(eId2) != 0) { - if (edgecounts[i] > 0) - { - procVerts[i] = Vmath::Vsum( - edgecounts[i], edgeVerts + edgeoffset[i], 1); - } - else - { - procVerts[i] = 0; - } + ASSERTL0(compPairs[eId2] == eId1, "Pairing incorrect"); } - vertoffset[0] = 0; + compPairs[eId1] = eId2; + } - for (i = 1; i < n; ++i) + // Construct set of all edges that we have locally on this + // processor. + set locEdges; + for (i = 0; i < 2; ++i) + { + if (!c[i]) { - vertoffset[i] = vertoffset[i-1] + procVerts[i-1]; + continue; } - Array vertIds(nTotVerts, 0); - for (i = 0, sIt = allEdges.begin(); sIt != allEdges.end(); ++sIt) + if (c[i]->m_geomVec.size() > 0) { - for (j = 0; j < allVerts[sIt->first].size(); ++j) + for (j = 0; j < c[i]->m_geomVec.size(); ++j) { - vertIds[vertoffset[p] + i++] = allVerts[sIt->first][j]; + locEdges.insert(c[i]->m_geomVec[j]->GetGlobalID()); } } + } - vComm->AllReduce(vertIds, LibUtilities::ReduceSum); + // Loop over all edges in the geometry composite. + for (auto &pIt : compPairs) + { + int ids[2] = {pIt.first, pIt.second}; + bool local[2] = {locEdges.count(pIt.first) > 0, + locEdges.count(pIt.second) > 0}; - // For simplicity's sake create a map of edge id -> orientation. - map orientMap; - map > vertMap; + ASSERTL0(orientMap.count(ids[0]) > 0 && orientMap.count(ids[1]) > 0, + "Unable to find edge in orientation map."); - for (cnt = i = 0; i < totEdges; ++i) - { - ASSERTL0(orientMap.count(edgeIds[i]) == 0, - "Already found edge in orientation map!"); - - // Work out relative orientations. To avoid having to exchange - // vertex locations, we figure out if the edges are backwards or - // forwards orientated with respect to a forwards orientation - // that is CCW. Since our local geometries are - // forwards-orientated with respect to the Cartesian axes, we - // need to invert the orientation for the top and left edges of - // a quad and the left edge of a triangle. - StdRegions::Orientation o = - (StdRegions::Orientation)edgeOrient[i]; + allCompPairs[pIt.first] = pIt.second; + allCompPairs[pIt.second] = pIt.first; - if (edgeIdx[i] > 1) + for (i = 0; i < 2; ++i) + { + if (!local[i]) { - o = o == StdRegions::eForwards ? - StdRegions::eBackwards : StdRegions::eForwards; + continue; } - orientMap[edgeIds[i]] = o; + int other = (i + 1) % 2; - vector verts(edgeVerts[i]); + StdRegions::Orientation o = + orientMap[ids[i]] == orientMap[ids[other]] + ? StdRegions::eBackwards + : StdRegions::eForwards; - for (j = 0; j < edgeVerts[i]; ++j) - { - verts[j] = vertIds[cnt++]; - } - vertMap[edgeIds[i]] = verts; + PeriodicEntity ent(ids[other], o, local[other]); + m_periodicEdges[ids[i]].push_back(ent); } - // Go through list of composites and figure out which edges are - // parallel from original ordering in session file. This includes - // composites which are not necessarily on this process. - map allCompPairs; - - // Store temporary map of periodic vertices which will hold all - // periodic vertices on the entire mesh so that doubly periodic - // vertices can be counted properly across partitions. Local - // vertices are copied into m_periodicVerts at the end of the - // function. - PeriodicMap periodicVerts; - - for (auto &cIt : perComps) + for (i = 0; i < 2; ++i) { - SpatialDomains::CompositeSharedPtr c[2]; - const int id1 = cIt.first; - const int id2 = cIt.second; - std::string id1s = boost::lexical_cast(id1); - std::string id2s = boost::lexical_cast(id2); + int other = (i + 1) % 2; - if (compMap.count(id1) > 0) - { - c[0] = compMap[id1]; - } + StdRegions::Orientation o = + orientMap[ids[i]] == orientMap[ids[other]] + ? StdRegions::eBackwards + : StdRegions::eForwards; - if (compMap.count(id2) > 0) - { - c[1] = compMap[id2]; - } + // Determine periodic vertices. + vector perVerts1 = vertMap[ids[i]]; + vector perVerts2 = vertMap[ids[other]]; - ASSERTL0(c[0] || c[1], - "Both composites not found on this process!"); - - // Loop over composite ordering to construct list of all - // periodic edges regardless of whether they are on this - // process. - map compPairs; - - ASSERTL0(compOrder.count(id1) > 0, - "Unable to find composite "+id1s+" in order map."); - ASSERTL0(compOrder.count(id2) > 0, - "Unable to find composite "+id2s+" in order map."); - ASSERTL0(compOrder[id1].size() == compOrder[id2].size(), - "Periodic composites "+id1s+" and "+id2s+ - " should have the same number of elements."); - ASSERTL0(compOrder[id1].size() > 0, - "Periodic composites "+id1s+" and "+id2s+ - " are empty!"); - - // TODO: Add more checks. - for (i = 0; i < compOrder[id1].size(); ++i) + map> tmpMap; + if (o == StdRegions::eForwards) { - int eId1 = compOrder[id1][i]; - int eId2 = compOrder[id2][i]; - - ASSERTL0(compPairs.count(eId1) == 0, - "Already paired."); - - if (compPairs.count(eId2) != 0) - { - ASSERTL0(compPairs[eId2] == eId1, "Pairing incorrect"); - } - compPairs[eId1] = eId2; + tmpMap[perVerts1[0]] = make_pair( + perVerts2[0], locVerts.count(perVerts2[0]) > 0); + tmpMap[perVerts1[1]] = make_pair( + perVerts2[1], locVerts.count(perVerts2[1]) > 0); } - - // Construct set of all edges that we have locally on this - // processor. - set locEdges; - for (i = 0; i < 2; ++i) + else { - if (!c[i]) - { - continue; - } - - if (c[i]->m_geomVec.size() > 0) - { - for (j = 0; j < c[i]->m_geomVec.size(); ++j) - { - locEdges.insert(c[i]->m_geomVec[j]->GetGlobalID()); - } - } + tmpMap[perVerts1[0]] = make_pair( + perVerts2[1], locVerts.count(perVerts2[1]) > 0); + tmpMap[perVerts1[1]] = make_pair( + perVerts2[0], locVerts.count(perVerts2[0]) > 0); } - // Loop over all edges in the geometry composite. - for (auto &pIt : compPairs) + for (auto &mIt : tmpMap) { - int ids [2] = {pIt.first, pIt.second}; - bool local[2] = {locEdges.count(pIt.first) > 0, - locEdges.count(pIt.second) > 0}; - - ASSERTL0(orientMap.count(ids[0]) > 0 && - orientMap.count(ids[1]) > 0, - "Unable to find edge in orientation map."); - - allCompPairs[pIt.first ] = pIt.second; - allCompPairs[pIt.second] = pIt.first; + // See if this vertex has been recorded already. + PeriodicEntity ent2(mIt.second.first, + StdRegions::eNoOrientation, + mIt.second.second); + auto perIt = periodicVerts.find(mIt.first); - for (i = 0; i < 2; ++i) + if (perIt == periodicVerts.end()) { - if (!local[i]) - { - continue; - } - - int other = (i+1) % 2; - - StdRegions::Orientation o = - orientMap[ids[i]] == orientMap[ids[other]] ? - StdRegions::eBackwards : - StdRegions::eForwards; - - PeriodicEntity ent(ids [other], o, - local[other]); - m_periodicEdges[ids[i]].push_back(ent); + periodicVerts[mIt.first].push_back(ent2); + perIt = periodicVerts.find(mIt.first); } - - for (i = 0; i < 2; ++i) + else { - int other = (i+1) % 2; - - StdRegions::Orientation o = - orientMap[ids[i]] == orientMap[ids[other]] ? - StdRegions::eBackwards : - StdRegions::eForwards; - - // Determine periodic vertices. - vector perVerts1 = vertMap[ids[i]]; - vector perVerts2 = vertMap[ids[other]]; - - map > tmpMap; - if (o == StdRegions::eForwards) - { - tmpMap[perVerts1[0]] = make_pair( - perVerts2[0], locVerts.count(perVerts2[0]) > 0); - tmpMap[perVerts1[1]] = make_pair( - perVerts2[1], locVerts.count(perVerts2[1]) > 0); - } - else + bool doAdd = true; + for (j = 0; j < perIt->second.size(); ++j) { - tmpMap[perVerts1[0]] = make_pair( - perVerts2[1], locVerts.count(perVerts2[1]) > 0); - tmpMap[perVerts1[1]] = make_pair( - perVerts2[0], locVerts.count(perVerts2[0]) > 0); + if (perIt->second[j].id == mIt.second.first) + { + doAdd = false; + break; + } } - for (auto &mIt : tmpMap) + if (doAdd) { - // See if this vertex has been recorded already. - PeriodicEntity ent2(mIt.second.first, - StdRegions::eNoOrientation, - mIt.second.second); - auto perIt = periodicVerts.find(mIt.first); - - if (perIt == periodicVerts.end()) - { - periodicVerts[mIt.first].push_back(ent2); - perIt = periodicVerts.find(mIt.first); - } - else - { - bool doAdd = true; - for (j = 0; j < perIt->second.size(); ++j) - { - if (perIt->second[j].id == mIt.second.first) - { - doAdd = false; - break; - } - } - - if (doAdd) - { - perIt->second.push_back(ent2); - } - } + perIt->second.push_back(ent2); } } } } + } + } - Array pairSizes(n, 0); - pairSizes[p] = allCompPairs.size(); - vComm->AllReduce(pairSizes, LibUtilities::ReduceSum); + Array pairSizes(n, 0); + pairSizes[p] = allCompPairs.size(); + vComm->AllReduce(pairSizes, LibUtilities::ReduceSum); - int totPairSizes = Vmath::Vsum(n, pairSizes, 1); + int totPairSizes = Vmath::Vsum(n, pairSizes, 1); - Array pairOffsets(n, 0); - pairOffsets[0] = 0; + Array pairOffsets(n, 0); + pairOffsets[0] = 0; - for (i = 1; i < n; ++i) - { - pairOffsets[i] = pairOffsets[i-1] + pairSizes[i-1]; - } + for (i = 1; i < n; ++i) + { + pairOffsets[i] = pairOffsets[i - 1] + pairSizes[i - 1]; + } - Array first (totPairSizes, 0); - Array second(totPairSizes, 0); + Array first(totPairSizes, 0); + Array second(totPairSizes, 0); - cnt = pairOffsets[p]; + cnt = pairOffsets[p]; - for (auto &pIt : allCompPairs) - { - first [cnt ] = pIt.first; - second[cnt++] = pIt.second; - } + for (auto &pIt : allCompPairs) + { + first[cnt] = pIt.first; + second[cnt++] = pIt.second; + } - vComm->AllReduce(first, LibUtilities::ReduceSum); - vComm->AllReduce(second, LibUtilities::ReduceSum); + vComm->AllReduce(first, LibUtilities::ReduceSum); + vComm->AllReduce(second, LibUtilities::ReduceSum); - allCompPairs.clear(); + allCompPairs.clear(); - for(cnt = 0; cnt < totPairSizes; ++cnt) - { - allCompPairs[first[cnt]] = second[cnt]; - } + for (cnt = 0; cnt < totPairSizes; ++cnt) + { + allCompPairs[first[cnt]] = second[cnt]; + } - // Search for periodic vertices and edges which are not in - // a periodic composite but lie in this process. First, loop - // over all information we have from other processors. - for (cnt = i = 0; i < totEdges; ++i) - { - int edgeId = edgeIds[i]; + // Search for periodic vertices and edges which are not in + // a periodic composite but lie in this process. First, loop + // over all information we have from other processors. + for (cnt = i = 0; i < totEdges; ++i) + { + int edgeId = edgeIds[i]; - ASSERTL0(allCompPairs.count(edgeId) > 0, - "Unable to find matching periodic edge."); + ASSERTL0(allCompPairs.count(edgeId) > 0, + "Unable to find matching periodic edge."); - int perEdgeId = allCompPairs[edgeId]; + int perEdgeId = allCompPairs[edgeId]; - for (j = 0; j < edgeVerts[i]; ++j, ++cnt) - { - int vId = vertIds[cnt]; + for (j = 0; j < edgeVerts[i]; ++j, ++cnt) + { + int vId = vertIds[cnt]; - auto perId = periodicVerts.find(vId); + auto perId = periodicVerts.find(vId); - if (perId == periodicVerts.end()) - { - // This vertex is not included in the map. Figure - // out which vertex it is supposed to be periodic - // with. perEdgeId is the edge ID which is periodic with - // edgeId. The logic is much the same as the loop above. - int perVertexId = - orientMap[edgeId] == orientMap[perEdgeId] ? - vertMap[perEdgeId][(j+1)%2] : vertMap[perEdgeId][j]; - - PeriodicEntity ent(perVertexId, - StdRegions::eNoOrientation, - locVerts.count(perVertexId) > 0); - - periodicVerts[vId].push_back(ent); - } - } + if (perId == periodicVerts.end()) + { + // This vertex is not included in the map. Figure + // out which vertex it is supposed to be periodic + // with. perEdgeId is the edge ID which is periodic with + // edgeId. The logic is much the same as the loop above. + int perVertexId = orientMap[edgeId] == orientMap[perEdgeId] + ? vertMap[perEdgeId][(j + 1) % 2] + : vertMap[perEdgeId][j]; + + PeriodicEntity ent(perVertexId, StdRegions::eNoOrientation, + locVerts.count(perVertexId) > 0); + + periodicVerts[vId].push_back(ent); } + } + } + + // Loop over all periodic vertices to complete connectivity + // information. + for (auto &perIt : periodicVerts) + { + // Loop over associated vertices. + for (i = 0; i < perIt.second.size(); ++i) + { + auto perIt2 = periodicVerts.find(perIt.second[i].id); + ASSERTL0(perIt2 != periodicVerts.end(), + "Couldn't find periodic vertex."); - // Loop over all periodic vertices to complete connectivity - // information. - for (auto &perIt : periodicVerts) + for (j = 0; j < perIt2->second.size(); ++j) { - // Loop over associated vertices. - for (i = 0; i < perIt.second.size(); ++i) + if (perIt2->second[j].id == perIt.first) { - auto perIt2 = periodicVerts.find(perIt.second[i].id); - ASSERTL0(perIt2 != periodicVerts.end(), - "Couldn't find periodic vertex."); + continue; + } - for (j = 0; j < perIt2->second.size(); ++j) + bool doAdd = true; + for (k = 0; k < perIt.second.size(); ++k) + { + if (perIt2->second[j].id == perIt.second[k].id) { - if (perIt2->second[j].id == perIt.first) - { - continue; - } - - bool doAdd = true; - for (k = 0; k < perIt.second.size(); ++k) - { - if (perIt2->second[j].id == perIt.second[k].id) - { - doAdd = false; - break; - } - } - - if (doAdd) - { - perIt.second.push_back(perIt2->second[j]); - } + doAdd = false; + break; } } - } - // Do one final loop over periodic vertices to remove non-local - // vertices from map. - for (auto &perIt : periodicVerts) - { - if (locVerts.count(perIt.first) > 0) + if (doAdd) { - m_periodicVerts.insert(perIt); + perIt.second.push_back(perIt2->second[j]); } } } + } - bool DisContField2D::IsLeftAdjacentEdge(const int n, const int e) + // Do one final loop over periodic vertices to remove non-local + // vertices from map. + for (auto &perIt : periodicVerts) + { + if (locVerts.count(perIt.first) > 0) { - LocalRegions::Expansion1DSharedPtr traceEl = - m_traceMap->GetElmtToTrace()[n][e]-> - as(); - - - bool fwd = true; + m_periodicVerts.insert(perIt); + } + } +} - if (traceEl->GetLeftAdjacentElementEdge () == -1 || - traceEl->GetRightAdjacentElementEdge() == -1) - { +bool DisContField2D::IsLeftAdjacentEdge(const int n, const int e) +{ + LocalRegions::Expansion1DSharedPtr traceEl = + m_traceMap->GetElmtToTrace()[n][e]->as(); - // Boundary edge (1 connected element). Do nothing in - // serial. - auto it = m_boundaryEdges.find(traceEl->GetElmtId()); + bool fwd = true; - // If the edge does not have a boundary condition set on - // it, then assume it is a partition edge. - if (it == m_boundaryEdges.end()) - { - int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); - auto pIt = m_periodicEdges.find(traceGeomId); - auto intIt1 = m_interfaceEdgeLeft.find(traceEl->GetGeom()->GetGlobalID()); - auto intIt2 = m_interfaceEdgeRight.find(traceEl->GetGeom()->GetGlobalID()); + if (traceEl->GetLeftAdjacentElementEdge() == -1 || + traceEl->GetRightAdjacentElementEdge() == -1) + { - if (intIt1 != m_interfaceEdgeLeft.end()) - { - std::cout << "ELMT " << n << " EDGE " << e << " left adjacent" << std::endl; - fwd = true; - } - else if (intIt2 != m_interfaceEdgeRight.end()) - { - std::cout << "ELMT " << n << " EDGE " << e << " right adjacent" << std::endl; - fwd = false; - } - else if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) - { - fwd = traceGeomId == min(traceGeomId,pIt->second[0].id); - } - else - { - int offset = m_trace->GetPhys_Offset(traceEl->GetElmtId()); + // Boundary edge (1 connected element). Do nothing in + // serial. + auto it = m_boundaryEdges.find(traceEl->GetElmtId()); - fwd = m_traceMap-> - GetTraceToUniversalMapUnique(offset) >= 0; - } - } - } - else if ( traceEl->GetLeftAdjacentElementEdge () != -1 && - traceEl->GetRightAdjacentElementEdge() != -1 ) + // If the edge does not have a boundary condition set on + // it, then assume it is a partition edge. + if (it == m_boundaryEdges.end()) + { + int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); + auto pIt = m_periodicEdges.find(traceGeomId); + auto intIt1 = + m_interfaceEdgeLeft.find(traceEl->GetGeom()->GetGlobalID()); + auto intIt2 = + m_interfaceEdgeRight.find(traceEl->GetGeom()->GetGlobalID()); + + if (intIt1 != m_interfaceEdgeLeft.end()) { - // Non-boundary edge (2 connected elements). - fwd = ( traceEl->GetLeftAdjacentElementExp().get() == (*m_exp)[n].get() ); + std::cout << "ELMT " << n << " EDGE " << e << " left adjacent" + << std::endl; + fwd = true; } - else + else if (intIt2 != m_interfaceEdgeRight.end()) { - ASSERTL2( false, "Unconnected trace element!" ); + std::cout << "ELMT " << n << " EDGE " << e << " right adjacent" + << std::endl; + fwd = false; } - - return fwd; - } - - // Construct the two trace vectors of the inner and outer - // trace solution from the field contained in m_phys, where - // the Weak dirichlet boundary conditions are listed in the - // outer part of the vecotr - void DisContField2D::v_GetFwdBwdTracePhys( - Array &Fwd, - Array &Bwd) - { - v_GetFwdBwdTracePhys(m_phys, Fwd, Bwd); - } - - /** - * @brief This method extracts the "forward" and "backward" trace data - * from the array @a field and puts the data into output vectors @a Fwd - * and @a Bwd. - * - * We first define the convention which defines "forwards" and - * "backwards". First an association is made between the edge of each - * element and its corresponding edge in the trace space using the - * mapping #m_traceMap. The element can either be left-adjacent or - * right-adjacent to this trace edge (see - * Expansion1D::GetLeftAdjacentElementExp). Boundary edges are always - * left-adjacent since left-adjacency is populated first. - * - * If the element is left-adjacent we extract the edge trace data from - * @a field into the forward trace space @a Fwd; otherwise, we place it - * in the backwards trace space @a Bwd. In this way, we form a unique - * set of trace normals since these are always extracted from - * left-adjacent elements. - * - * @param field is a NekDouble array which contains the 2D data - * from which we wish to extract the backward and - * forward orientated trace/edge arrays. - * @param Fwd The resulting forwards space. - * @param Bwd The resulting backwards space. - */ - void DisContField2D::v_GetFwdBwdTracePhys( - const Array &field, - Array &Fwd, - Array &Bwd) - { - int cnt, n, e, npts, phys_offset; - - // Zero forward/backward vectors. - Vmath::Zero(Fwd.num_elements(), Fwd, 1); - Vmath::Zero(Bwd.num_elements(), Bwd, 1); - - // Basis definition on each element - LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); - if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) + else if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) { - // blocked routine - Array edgevals(m_locTraceToTraceMap-> - GetNLocTracePts()); - - m_locTraceToTraceMap->LocTracesFromField(field, edgevals); - m_locTraceToTraceMap->InterpLocEdgesToTrace(0, edgevals, Fwd); - - Array invals = edgevals + m_locTraceToTraceMap-> - GetNFwdLocTracePts(); - m_locTraceToTraceMap->InterpLocEdgesToTrace(1, invals, Bwd); + fwd = traceGeomId == min(traceGeomId, pIt->second[0].id); } else { - // Loop over elements and collect forward expansion - int nexp = GetExpSize(); - Array e_tmp; - LocalRegions::Expansion2DSharedPtr exp2d; + int offset = m_trace->GetPhys_Offset(traceEl->GetElmtId()); - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); + fwd = m_traceMap->GetTraceToUniversalMapUnique(offset) >= 0; + } + } + } + else if (traceEl->GetLeftAdjacentElementEdge() != -1 && + traceEl->GetRightAdjacentElementEdge() != -1) + { + // Non-boundary edge (2 connected elements). + fwd = (traceEl->GetLeftAdjacentElementExp().get() == (*m_exp)[n].get()); + } + else + { + ASSERTL2(false, "Unconnected trace element!"); + } + + return fwd; +} + +// Construct the two trace vectors of the inner and outer +// trace solution from the field contained in m_phys, where +// the Weak dirichlet boundary conditions are listed in the +// outer part of the vecotr +void DisContField2D::v_GetFwdBwdTracePhys(Array &Fwd, + Array &Bwd) +{ + v_GetFwdBwdTracePhys(m_phys, Fwd, Bwd); +} + +/** + * @brief This method extracts the "forward" and "backward" trace data + * from the array @a field and puts the data into output vectors @a Fwd + * and @a Bwd. + * + * We first define the convention which defines "forwards" and + * "backwards". First an association is made between the edge of each + * element and its corresponding edge in the trace space using the + * mapping #m_traceMap. The element can either be left-adjacent or + * right-adjacent to this trace edge (see + * Expansion1D::GetLeftAdjacentElementExp). Boundary edges are always + * left-adjacent since left-adjacency is populated first. + * + * If the element is left-adjacent we extract the edge trace data from + * @a field into the forward trace space @a Fwd; otherwise, we place it + * in the backwards trace space @a Bwd. In this way, we form a unique + * set of trace normals since these are always extracted from + * left-adjacent elements. + * + * @param field is a NekDouble array which contains the 2D data + * from which we wish to extract the backward and + * forward orientated trace/edge arrays. + * @param Fwd The resulting forwards space. + * @param Bwd The resulting backwards space. + */ +void DisContField2D::v_GetFwdBwdTracePhys( + const Array &field, Array &Fwd, + Array &Bwd) +{ + int cnt, n, e, npts, phys_offset; - for(cnt = n = 0; n < nexp; ++n) - { - exp2d = (*m_exp)[n]->as(); - phys_offset = GetPhys_Offset(n); + // Zero forward/backward vectors. + Vmath::Zero(Fwd.num_elements(), Fwd, 1); + Vmath::Zero(Bwd.num_elements(), Bwd, 1); - for(e = 0; e < exp2d->GetNedges(); ++e, ++cnt) - { - int offset = m_trace->GetPhys_Offset( - elmtToTrace[n][e]->GetElmtId()); + // Basis definition on each element + LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); + if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) + { + // blocked routine + Array edgevals( + m_locTraceToTraceMap->GetNLocTracePts()); + + m_locTraceToTraceMap->LocTracesFromField(field, edgevals); + m_locTraceToTraceMap->InterpLocEdgesToTrace(0, edgevals, Fwd); + + Array invals = + edgevals + m_locTraceToTraceMap->GetNFwdLocTracePts(); + m_locTraceToTraceMap->InterpLocEdgesToTrace(1, invals, Bwd); + } + else + { + // Loop over elements and collect forward expansion + int nexp = GetExpSize(); + Array e_tmp; + LocalRegions::Expansion2DSharedPtr exp2d; - if (m_leftAdjacentEdges[cnt]) - { - exp2d->GetEdgePhysVals(e, elmtToTrace[n][e], - field + phys_offset, - e_tmp = Fwd + offset); - } - else - { - exp2d->GetEdgePhysVals(e, elmtToTrace[n][e], - field + phys_offset, - e_tmp = Bwd + offset); - } - } - } - } + Array> + &elmtToTrace = m_traceMap->GetElmtToTrace(); - // Fill boundary conditions into missing elements - int id1, id2 = 0; + for (cnt = n = 0; n < nexp; ++n) + { + exp2d = (*m_exp)[n]->as(); + phys_offset = GetPhys_Offset(n); - for (cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n) + for (e = 0; e < exp2d->GetNedges(); ++e, ++cnt) { - if (m_bndConditions[n]->GetBoundaryConditionType() == - SpatialDomains::eDirichlet) - { - for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) - { - npts = m_bndCondExpansions[n]->GetExp(e)->GetNumPoints(0); - id1 = m_bndCondExpansions[n]->GetPhys_Offset(e); - id2 = m_trace->GetPhys_Offset(m_traceMap-> - GetBndCondTraceToGlobalTraceMap(cnt+e)); - Vmath::Vcopy(npts, - &(m_bndCondExpansions[n]->GetPhys())[id1], 1, - &Bwd[id2], 1); - } + int offset = + m_trace->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId()); - cnt += e; - } - else if (m_bndConditions[n]->GetBoundaryConditionType() == - SpatialDomains::eNeumann || - m_bndConditions[n]->GetBoundaryConditionType() == - SpatialDomains::eRobin) + if (m_leftAdjacentEdges[cnt]) { - for(e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) - { - npts = m_bndCondExpansions[n]->GetExp(e)->GetNumPoints(0); - id1 = m_bndCondExpansions[n]->GetPhys_Offset(e); - ASSERTL0((m_bndCondExpansions[n]->GetPhys())[id1]==0.0, - "Method not set up for non-zero Neumann " - "boundary condition"); - id2 = m_trace->GetPhys_Offset( - m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt+e)); - Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1); - } - - cnt += e; + exp2d->GetEdgePhysVals(e, elmtToTrace[n][e], + field + phys_offset, + e_tmp = Fwd + offset); } - else if (m_bndConditions[n]->GetBoundaryConditionType() != - SpatialDomains::ePeriodic) + else { - ASSERTL0(false, - "Method not set up for this boundary condition."); + exp2d->GetEdgePhysVals(e, elmtToTrace[n][e], + field + phys_offset, + e_tmp = Bwd + offset); } } + } + } + + // Fill boundary conditions into missing elements + int id1, id2 = 0; - // Copy any periodic boundary conditions. - for (n = 0; n < m_periodicFwdCopy.size(); ++n) + for (cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n) + { + if (m_bndConditions[n]->GetBoundaryConditionType() == + SpatialDomains::eDirichlet) + { + for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) { - Bwd[m_periodicBwdCopy[n]] = Fwd[m_periodicFwdCopy[n]]; + npts = m_bndCondExpansions[n]->GetExp(e)->GetNumPoints(0); + id1 = m_bndCondExpansions[n]->GetPhys_Offset(e); + id2 = m_trace->GetPhys_Offset( + m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt + e)); + Vmath::Vcopy(npts, &(m_bndCondExpansions[n]->GetPhys())[id1], 1, + &Bwd[id2], 1); } - // Interpolate from each side of the interface to the other. - for (auto &interface : m_traceEdgeLeft) + cnt += e; + } + else if (m_bndConditions[n]->GetBoundaryConditionType() == + SpatialDomains::eNeumann || + m_bndConditions[n]->GetBoundaryConditionType() == + SpatialDomains::eRobin) + { + for (e = 0; e < m_bndCondExpansions[n]->GetExpSize(); ++e) { - auto &edgeOneExps = interface.second; - auto &edgeTwoExps = m_traceEdgeRight[interface.first]; - - // Edge two -> one interpolation - for (n = 0; n < edgeOneExps.size(); ++n) - { - auto elmt = edgeOneExps[n]; - std::cout << std::fixed; - std::cout << std::setprecision(5); - cout << "BWD EDGE ID: " << std::static_pointer_cast(elmt->GetGeom1D())->GetGlobalID() << " - (" << n+1 << " / " << edgeOneExps.size() << ")" << endl; - int nq = elmt->GetTotPoints(); - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - - for (int i = 0; i < nq; ++i) - { - NekDouble zero = 0.0; - std::vector - searchEdge; - auto BgRtree = m_graph->GetRegionsContainingPoint( - xc[i], yc[i], zero, 1); - cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; - bool found = false; - for (auto boundaryBoxElement : BgRtree) - { - if (found == false) - { - for (int m = 0; m < edgeTwoExps.size(); ++m) - { - auto geom = edgeTwoExps[m]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast< - SpatialDomains::SegGeom>( - geom->GetGeom1D()); - if (boundaryBoxElement.second == - geomSeg->GetGlobalID()) - { - Array xs(2); - xs[0] = xc[i]; - xs[1] = yc[i]; - - NekDouble foundPoint; - NekDouble dist = geomSeg->FindDistance( - xs, foundPoint); - cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << " | Distance: " << dist; - if (dist > 1e-8) - { - continue; - } - Array edgePhys = - Bwd + m_trace->GetPhys_Offset( - geom->GetElmtId()); - Array foundPointArray( - 1, foundPoint); - Bwd[m_trace->GetPhys_Offset( - elmt->GetElmtId()) + - i] = - geom->StdPhysEvaluate( - foundPointArray, edgePhys); - found = true; - cout << " | BWD SUCCESS" << endl; - break; - } - } - } - } - ASSERTL1(found, "Couldn't interpolate across interface " - "from right to left (bwd)"); - } - } - - // Edge one -> two interpolation - for (n = 0; n < edgeTwoExps.size(); ++n) - { - auto elmt = edgeTwoExps[n]; - cout << "FWD EDGE ID: " << std::static_pointer_cast(elmt->GetGeom1D())->GetGlobalID() << " - (" << n+1 << " / " << edgeTwoExps.size() << ")" << endl; - int nq = elmt->GetTotPoints(); - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - - for (int i = 0; i < nq; ++i) - { - NekDouble zero = 0.0; - std::vector - searchEdge; - auto BgRtree = m_graph->GetRegionsContainingPoint( - xc[i], yc[i], zero, 1); - cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; - bool found = false; - for (auto boundaryBoxElement : BgRtree) - { - if (found == false) - { - for (int m = 0; m < edgeOneExps.size(); ++m) - { - auto geom = edgeOneExps[m]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast< - SpatialDomains::SegGeom>( - geom->GetGeom1D()); - if (boundaryBoxElement.second == - geomSeg->GetGlobalID()) - { - Array xs(2); - xs[0] = xc[i]; - xs[1] = yc[i]; - - NekDouble foundPoint; - NekDouble dist = geomSeg->FindDistance( - xs, foundPoint); - cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << "\t| Distance: " << dist; - if (dist > 1e-8) - { - continue; - } - Array edgePhys = - Fwd + m_trace->GetPhys_Offset( - geom->GetElmtId()); - Array foundPointArray( - 1, foundPoint); - Fwd[m_trace->GetPhys_Offset( - elmt->GetElmtId()) + - i] = - geom->StdPhysEvaluate( - foundPointArray, edgePhys); - found = true; - cout << " | FWD SUCCESS" << endl; - break; - } - } - } - } - ASSERTL1(found, "Couldn't interpolate across interface " - "from left to right (fwd)"); - } - } + npts = m_bndCondExpansions[n]->GetExp(e)->GetNumPoints(0); + id1 = m_bndCondExpansions[n]->GetPhys_Offset(e); + ASSERTL0((m_bndCondExpansions[n]->GetPhys())[id1] == 0.0, + "Method not set up for non-zero Neumann " + "boundary condition"); + id2 = m_trace->GetPhys_Offset( + m_traceMap->GetBndCondTraceToGlobalTraceMap(cnt + e)); + Vmath::Vcopy(npts, &Fwd[id2], 1, &Bwd[id2], 1); } - // Do parallel exchange for forwards/backwards spaces. - m_traceMap->UniversalTraceAssemble(Fwd); - m_traceMap->UniversalTraceAssemble(Bwd); + cnt += e; } - - - void DisContField2D::v_ExtractTracePhys( - Array &outarray) + else if (m_bndConditions[n]->GetBoundaryConditionType() != + SpatialDomains::ePeriodic) { - ASSERTL1(m_physState == true, - "Field must be in physical state to extract trace space."); - - v_ExtractTracePhys(m_phys, outarray); + ASSERTL0(false, "Method not set up for this boundary condition."); } + } + + // Copy any periodic boundary conditions. + for (n = 0; n < m_periodicFwdCopy.size(); ++n) + { + Bwd[m_periodicBwdCopy[n]] = Fwd[m_periodicFwdCopy[n]]; + } - /** - * @brief This method extracts the trace (edges in 2D) from the field @a - * inarray and puts the values in @a outarray. - * - * It assumes the field is C0 continuous so that it can overwrite the - * edge data when visited by the two adjacent elements. - * - * @param inarray An array containing the 2D data from which we wish - * to extract the edge data. - * @param outarray The resulting edge information. - */ - void DisContField2D::v_ExtractTracePhys( - const Array &inarray, - Array &outarray) + // Interpolate from each side of the interface to the other. + for (auto &interface : m_traceEdgeLeft) + { + // Edge two -> one interpolation + for (auto edges : interface.second) { - LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); - if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) - { - Vmath::Zero(outarray.num_elements(), outarray, 1); - - Array tracevals( - m_locTraceToTraceMap->GetNFwdLocTracePts()); - m_locTraceToTraceMap->FwdLocTracesFromField(inarray,tracevals); - m_locTraceToTraceMap-> - InterpLocEdgesToTrace(0,tracevals,outarray); - m_traceMap->UniversalTraceAssemble(outarray); - } - else + auto elmt = edges.second; + cout << "BWD EDGE ID: " << edges.first << endl; + int nq = elmt->GetTotPoints(); + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); + + for (int i = 0; i < nq; ++i) { - // Loop over elemente and collect forward expansion - int nexp = GetExpSize(); - int n, e, offset, phys_offset; - Array e_tmp; - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); - - ASSERTL1(outarray.num_elements() >= m_trace->GetNpoints(), - "input array is of insufficient length"); - - // use m_trace tmp space in element to fill values - for(n = 0; n < nexp; ++n) + NekDouble zero = 0.0; + auto BgRtree = m_interfaces[interface.first]->GetRightEdgesContainingPoint(xc[i], yc[i], zero); + cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; + bool found = false; + for (auto boundaryBoxElement : BgRtree) { - phys_offset = GetPhys_Offset(n); - - for(e = 0; e < (*m_exp)[n]->GetNedges(); ++e) + if (found == false) { - offset = m_trace->GetPhys_Offset( - elmtToTrace[n][e]->GetElmtId()); - (*m_exp)[n]->GetEdgePhysVals(e, elmtToTrace[n][e], - inarray + phys_offset, - e_tmp = outarray + offset); + auto geom = m_traceEdgeRight[interface.first][boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = std::static_pointer_cast(geom->GetGeom1D()); + + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + NekDouble foundPoint; + NekDouble dist = geomSeg->FindDistance(xs, foundPoint); + cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << " | Distance: " << dist; + if (dist > 1e-8) + { + continue; + } + Array edgePhys = Bwd + m_trace->GetPhys_Offset(geom->GetElmtId()); + Array foundPointArray(1, foundPoint); + Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom->StdPhysEvaluate(foundPointArray, edgePhys); + found = true; + cout << " | BWD SUCCESS" << endl; + break; } } + ASSERTL1(found, "Couldn't interpolate across interface " + "from right to left (bwd)"); } } + } - void DisContField2D::v_AddTraceIntegral( - const Array &Fx, - const Array &Fy, - Array &outarray) + for (auto &interface : m_traceEdgeRight) + { + // Edge one -> two interpolation + for (auto edges : interface.second) { - int e, n, offset, t_offset; - Array e_outarray; - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); - - for(n = 0; n < GetExpSize(); ++n) - { - offset = GetCoeff_Offset(n); - for(e = 0; e < (*m_exp)[n]->GetNedges(); ++e) - { - t_offset = GetTrace()->GetPhys_Offset( - elmtToTrace[n][e]->GetElmtId()); - - (*m_exp)[n]->AddEdgeNormBoundaryInt( - e,elmtToTrace[n][e], - Fx + t_offset, - Fy + t_offset, - e_outarray = outarray+offset); - } - } - } + auto elmt = edges.second; + cout << "FWD EDGE ID: " << edges.first << endl; + int nq = elmt->GetTotPoints(); + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); - /** - * @brief Add trace contributions into elemental coefficient spaces. - * - * Given some quantity \f$ \vec{Fn} \f$, which conatins this - * routine calculates the integral - * - * \f[ - * \int_{\Omega^e} \vec{Fn}, \mathrm{d}S - * \f] - * - * and adds this to the coefficient space provided by outarray. - * - * @see Expansion2D::AddEdgeNormBoundaryInt - * - * @param Fn The trace quantities. - * @param outarray Resulting 2D coefficient space. - */ - void DisContField2D::v_AddTraceIntegral( - const Array &Fn, - Array &outarray) - { - // Basis definition on each element - LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); - if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange) + for (int i = 0; i < nq; ++i) { - Array Fcoeffs(m_trace->GetNcoeffs()); - m_trace->IProductWRTBase(Fn, Fcoeffs); - - m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(Fcoeffs, - outarray); - } - else - { - int e, n, offset, t_offset; - Array e_outarray; - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); - - for(n = 0; n < GetExpSize(); ++n) + NekDouble zero = 0.0; + auto BgRtree = m_interfaces[interface.first]->GetLeftEdgesContainingPoint(xc[i], yc[i], zero); + cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; + bool found = false; + for (auto boundaryBoxElement : BgRtree) { - offset = GetCoeff_Offset(n); - for(e = 0; e < (*m_exp)[n]->GetNedges(); ++e) + if (found == false) { - t_offset = GetTrace()->GetPhys_Offset( - elmtToTrace[n][e]->GetElmtId()); - (*m_exp)[n]->AddEdgeNormBoundaryInt( - e, elmtToTrace[n][e], - Fn+t_offset, - e_outarray = outarray+offset); + auto geom = m_traceEdgeLeft[interface.first][boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = std::static_pointer_cast(geom->GetGeom1D()); + + Array xs(2); + xs[0] = xc[i]; + xs[1] = yc[i]; + NekDouble foundPoint; + NekDouble dist = geomSeg->FindDistance(xs, foundPoint); + cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << "\t| Distance: " << dist; + if (dist > 1e-8) + { + continue; + } + Array edgePhys = Fwd + m_trace->GetPhys_Offset(geom->GetElmtId()); + Array foundPointArray(1, foundPoint); + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom->StdPhysEvaluate(foundPointArray, edgePhys); + found = true; + cout << " | FWD SUCCESS" << endl; + break; } } + ASSERTL1(found, "Couldn't interpolate across interface " + "from left to right (fwd)"); } } - - - /** - * @brief Add trace contributions into elemental coefficient spaces. - * - * Given some quantity \f$ \vec{q} \f$, calculate the elemental integral - * - * \f[ - * \int_{\Omega^e} \vec{q}, \mathrm{d}S - * \f] - * - * and adds this to the coefficient space provided by - * outarray. The value of q is determined from the routine - * IsLeftAdjacentEdge() which if true we use Fwd else we use - * Bwd - * - * @see Expansion2D::AddEdgeNormBoundaryInt - * - * @param Fwd The trace quantities associated with left (fwd) - * adjancent elmt. - * @param Bwd The trace quantities associated with right (bwd) - * adjacent elet. - * @param outarray Resulting 2D coefficient space. - */ - void DisContField2D::v_AddFwdBwdTraceIntegral( - const Array &Fwd, - const Array &Bwd, - Array &outarray) + } + + // Do parallel exchange for forwards/backwards spaces. + m_traceMap->UniversalTraceAssemble(Fwd); + m_traceMap->UniversalTraceAssemble(Bwd); +} + +void DisContField2D::v_ExtractTracePhys(Array &outarray) +{ + ASSERTL1(m_physState == true, + "Field must be in physical state to extract trace space."); + + v_ExtractTracePhys(m_phys, outarray); +} + +/** + * @brief This method extracts the trace (edges in 2D) from the field @a + * inarray and puts the values in @a outarray. + * + * It assumes the field is C0 continuous so that it can overwrite the + * edge data when visited by the two adjacent elements. + * + * @param inarray An array containing the 2D data from which we wish + * to extract the edge data. + * @param outarray The resulting edge information. + */ +void DisContField2D::v_ExtractTracePhys( + const Array &inarray, + Array &outarray) +{ + LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); + if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) + { + Vmath::Zero(outarray.num_elements(), outarray, 1); + + Array tracevals( + m_locTraceToTraceMap->GetNFwdLocTracePts()); + m_locTraceToTraceMap->FwdLocTracesFromField(inarray, tracevals); + m_locTraceToTraceMap->InterpLocEdgesToTrace(0, tracevals, outarray); + m_traceMap->UniversalTraceAssemble(outarray); + } + else + { + // Loop over elemente and collect forward expansion + int nexp = GetExpSize(); + int n, e, offset, phys_offset; + Array e_tmp; + Array> + &elmtToTrace = m_traceMap->GetElmtToTrace(); + + ASSERTL1(outarray.num_elements() >= m_trace->GetNpoints(), + "input array is of insufficient length"); + + // use m_trace tmp space in element to fill values + for (n = 0; n < nexp; ++n) { - int e,n,offset, t_offset; - Array e_outarray; - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); + phys_offset = GetPhys_Offset(n); - for (n = 0; n < GetExpSize(); ++n) + for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e) { - offset = GetCoeff_Offset(n); - for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e) - { - t_offset = GetTrace()->GetPhys_Offset( - elmtToTrace[n][e]->GetElmtId()); - - // Evaluate upwind flux less local edge - if (IsLeftAdjacentEdge(n, e)) - { - (*m_exp)[n]->AddEdgeNormBoundaryInt( - e, elmtToTrace[n][e], Fwd+t_offset, - e_outarray = outarray+offset); - } - else - { - (*m_exp)[n]->AddEdgeNormBoundaryInt( - e, elmtToTrace[n][e], Bwd+t_offset, - e_outarray = outarray+offset); - } - - } + offset = + m_trace->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId()); + (*m_exp)[n]->GetEdgePhysVals(e, elmtToTrace[n][e], + inarray + phys_offset, + e_tmp = outarray + offset); } } + } +} - /** - * @brief Set up a list of element IDs and edge IDs that link to the - * boundary conditions. - */ - void DisContField2D::v_GetBoundaryToElmtMap( - Array &ElmtID, - Array &EdgeID) +void DisContField2D::v_AddTraceIntegral(const Array &Fx, + const Array &Fy, + Array &outarray) +{ + int e, n, offset, t_offset; + Array e_outarray; + Array> &elmtToTrace = + m_traceMap->GetElmtToTrace(); + + for (n = 0; n < GetExpSize(); ++n) + { + offset = GetCoeff_Offset(n); + for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e) { - if (m_BCtoElmMap.num_elements() == 0) - { - map globalIdMap; - int i,n; - int cnt; - int nbcs = 0; - - // Populate global ID map (takes global geometry ID to local - // expansion list ID). - for (i = 0; i < GetExpSize(); ++i) - { - globalIdMap[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i; - } + t_offset = + GetTrace()->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId()); - // Determine number of boundary condition expansions. - for(i = 0; i < m_bndConditions.num_elements(); ++i) - { - nbcs += m_bndCondExpansions[i]->GetExpSize(); - } + (*m_exp)[n]->AddEdgeNormBoundaryInt(e, elmtToTrace[n][e], + Fx + t_offset, Fy + t_offset, + e_outarray = outarray + offset); + } + } +} + +/** + * @brief Add trace contributions into elemental coefficient spaces. + * + * Given some quantity \f$ \vec{Fn} \f$, which conatins this + * routine calculates the integral + * + * \f[ + * \int_{\Omega^e} \vec{Fn}, \mathrm{d}S + * \f] + * + * and adds this to the coefficient space provided by outarray. + * + * @see Expansion2D::AddEdgeNormBoundaryInt + * + * @param Fn The trace quantities. + * @param outarray Resulting 2D coefficient space. + */ +void DisContField2D::v_AddTraceIntegral(const Array &Fn, + Array &outarray) +{ + // Basis definition on each element + LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); + if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange) + { + Array Fcoeffs(m_trace->GetNcoeffs()); + m_trace->IProductWRTBase(Fn, Fcoeffs); - // Initialize arrays - m_BCtoElmMap = Array(nbcs); - m_BCtoEdgMap = Array(nbcs); + m_locTraceToTraceMap->AddTraceCoeffsToFieldCoeffs(Fcoeffs, outarray); + } + else + { + int e, n, offset, t_offset; + Array e_outarray; + Array> + &elmtToTrace = m_traceMap->GetElmtToTrace(); - LocalRegions::Expansion1DSharedPtr exp1d; - for (cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n) - { - for (i = 0; i < m_bndCondExpansions[n]->GetExpSize(); - ++i, ++cnt) - { - exp1d = m_bndCondExpansions[n]->GetExp(i)-> - as(); - // Use edge to element map from MeshGraph. - SpatialDomains::GeometryLinkSharedPtr tmp = - m_graph->GetElementsFromEdge(exp1d->GetGeom1D()); - - m_BCtoElmMap[cnt] = globalIdMap[ - (*tmp)[0].first->GetGlobalID()]; - m_BCtoEdgMap[cnt] = (*tmp)[0].second; - } - } - } - ElmtID = m_BCtoElmMap; - EdgeID = m_BCtoEdgMap; - } - - void DisContField2D::v_GetBndElmtExpansion(int i, - std::shared_ptr &result, - const bool DeclareCoeffPhysArrays) + for (n = 0; n < GetExpSize(); ++n) { - int n, cnt, nq; - int offsetOld, offsetNew; - std::vector eIDs; - - Array ElmtID,EdgeID; - GetBoundaryToElmtMap(ElmtID,EdgeID); - - // Skip other boundary regions - for (cnt = n = 0; n < i; ++n) + offset = GetCoeff_Offset(n); + for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e) { - cnt += m_bndCondExpansions[n]->GetExpSize(); + t_offset = + GetTrace()->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId()); + (*m_exp)[n]->AddEdgeNormBoundaryInt( + e, elmtToTrace[n][e], Fn + t_offset, + e_outarray = outarray + offset); } + } + } +} + +/** + * @brief Add trace contributions into elemental coefficient spaces. + * + * Given some quantity \f$ \vec{q} \f$, calculate the elemental integral + * + * \f[ + * \int_{\Omega^e} \vec{q}, \mathrm{d}S + * \f] + * + * and adds this to the coefficient space provided by + * outarray. The value of q is determined from the routine + * IsLeftAdjacentEdge() which if true we use Fwd else we use + * Bwd + * + * @see Expansion2D::AddEdgeNormBoundaryInt + * + * @param Fwd The trace quantities associated with left (fwd) + * adjancent elmt. + * @param Bwd The trace quantities associated with right (bwd) + * adjacent elet. + * @param outarray Resulting 2D coefficient space. + */ +void DisContField2D::v_AddFwdBwdTraceIntegral( + const Array &Fwd, + const Array &Bwd, Array &outarray) +{ + int e, n, offset, t_offset; + Array e_outarray; + Array> &elmtToTrace = + m_traceMap->GetElmtToTrace(); + + for (n = 0; n < GetExpSize(); ++n) + { + offset = GetCoeff_Offset(n); + for (e = 0; e < (*m_exp)[n]->GetNedges(); ++e) + { + t_offset = + GetTrace()->GetPhys_Offset(elmtToTrace[n][e]->GetElmtId()); - // Populate eIDs with information from BoundaryToElmtMap - for (n = 0; n < m_bndCondExpansions[i]->GetExpSize(); ++n) + // Evaluate upwind flux less local edge + if (IsLeftAdjacentEdge(n, e)) { - eIDs.push_back(ElmtID[cnt+n]); + (*m_exp)[n]->AddEdgeNormBoundaryInt( + e, elmtToTrace[n][e], Fwd + t_offset, + e_outarray = outarray + offset); } - - // Create expansion list - result = - MemoryManager::AllocateSharedPtr - (*this, eIDs, DeclareCoeffPhysArrays); - - // Copy phys and coeffs to new explist - if( DeclareCoeffPhysArrays) + else { - Array tmp1, tmp2; - for (n = 0; n < result->GetExpSize(); ++n) - { - nq = GetExp(ElmtID[cnt+n])->GetTotPoints(); - offsetOld = GetPhys_Offset(ElmtID[cnt+n]); - offsetNew = result->GetPhys_Offset(n); - Vmath::Vcopy(nq, tmp1 = GetPhys()+ offsetOld, 1, - tmp2 = result->UpdatePhys()+ offsetNew, 1); - - nq = GetExp(ElmtID[cnt+n])->GetNcoeffs(); - offsetOld = GetCoeff_Offset(ElmtID[cnt+n]); - offsetNew = result->GetCoeff_Offset(n); - Vmath::Vcopy(nq, tmp1 = GetCoeffs()+ offsetOld, 1, - tmp2 = result->UpdateCoeffs()+ offsetNew, 1); - } + (*m_exp)[n]->AddEdgeNormBoundaryInt( + e, elmtToTrace[n][e], Bwd + t_offset, + e_outarray = outarray + offset); } } + } +} + +/** + * @brief Set up a list of element IDs and edge IDs that link to the + * boundary conditions. + */ +void DisContField2D::v_GetBoundaryToElmtMap(Array &ElmtID, + Array &EdgeID) +{ + if (m_BCtoElmMap.num_elements() == 0) + { + map globalIdMap; + int i, n; + int cnt; + int nbcs = 0; + + // Populate global ID map (takes global geometry ID to local + // expansion list ID). + for (i = 0; i < GetExpSize(); ++i) + { + globalIdMap[(*m_exp)[i]->GetGeom()->GetGlobalID()] = i; + } - /** - * @brief Reset this field, so that geometry information can be updated. - */ - void DisContField2D::v_Reset() + // Determine number of boundary condition expansions. + for (i = 0; i < m_bndConditions.num_elements(); ++i) { - ExpList::v_Reset(); + nbcs += m_bndCondExpansions[i]->GetExpSize(); + } + + // Initialize arrays + m_BCtoElmMap = Array(nbcs); + m_BCtoEdgMap = Array(nbcs); - // Reset boundary condition expansions. - for (int n = 0; n < m_bndCondExpansions.num_elements(); ++n) + LocalRegions::Expansion1DSharedPtr exp1d; + for (cnt = n = 0; n < m_bndCondExpansions.num_elements(); ++n) + { + for (i = 0; i < m_bndCondExpansions[n]->GetExpSize(); ++i, ++cnt) { - m_bndCondExpansions[n]->Reset(); + exp1d = m_bndCondExpansions[n] + ->GetExp(i) + ->as(); + // Use edge to element map from MeshGraph. + SpatialDomains::GeometryLinkSharedPtr tmp = + m_graph->GetElementsFromEdge(exp1d->GetGeom1D()); + + m_BCtoElmMap[cnt] = globalIdMap[(*tmp)[0].first->GetGlobalID()]; + m_BCtoEdgMap[cnt] = (*tmp)[0].second; } } + } + ElmtID = m_BCtoElmMap; + EdgeID = m_BCtoEdgMap; +} + +void DisContField2D::v_GetBndElmtExpansion(int i, + std::shared_ptr &result, + const bool DeclareCoeffPhysArrays) +{ + int n, cnt, nq; + int offsetOld, offsetNew; + std::vector eIDs; - /** - * @brief Calculate the \f$ L^2 \f$ error of the \f$ Q_{\rm dir} \f$ - * derivative using the consistent DG evaluation of \f$ Q_{\rm dir} \f$. - * - * The solution provided is of the primative variation at the quadrature - * points and the derivative is compared to the discrete derivative at - * these points, which is likely to be undesirable unless using a much - * higher number of quadrature points than the polynomial order used to - * evaluate \f$ Q_{\rm dir} \f$. - */ - NekDouble DisContField2D::L2_DGDeriv( - const int dir, - const Array &soln) - { - int i,e,ncoeff_edge; - Array tmp_coeffs; - Array out_d(m_ncoeffs), out_tmp; + Array ElmtID, EdgeID; + GetBoundaryToElmtMap(ElmtID, EdgeID); - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); + // Skip other boundary regions + for (cnt = n = 0; n < i; ++n) + { + cnt += m_bndCondExpansions[n]->GetExpSize(); + } - StdRegions::Orientation edgedir; + // Populate eIDs with information from BoundaryToElmtMap + for (n = 0; n < m_bndCondExpansions[i]->GetExpSize(); ++n) + { + eIDs.push_back(ElmtID[cnt + n]); + } - int cnt; - int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); - Array loc_lambda(LocBndCoeffs), edge_lambda; - m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(),loc_lambda); + // Create expansion list + result = MemoryManager::AllocateSharedPtr( + *this, eIDs, DeclareCoeffPhysArrays); - edge_lambda = loc_lambda; - - // Calculate Q using standard DG formulation. - for(i = cnt = 0; i < GetExpSize(); ++i) - { - // Probably a better way of setting up lambda than this. - // Note cannot use PutCoeffsInToElmts since lambda space - // is mapped during the solve. - int nEdges = (*m_exp)[i]->GetNedges(); - Array > edgeCoeffs(nEdges); + // Copy phys and coeffs to new explist + if (DeclareCoeffPhysArrays) + { + Array tmp1, tmp2; + for (n = 0; n < result->GetExpSize(); ++n) + { + nq = GetExp(ElmtID[cnt + n])->GetTotPoints(); + offsetOld = GetPhys_Offset(ElmtID[cnt + n]); + offsetNew = result->GetPhys_Offset(n); + Vmath::Vcopy(nq, tmp1 = GetPhys() + offsetOld, 1, + tmp2 = result->UpdatePhys() + offsetNew, 1); + + nq = GetExp(ElmtID[cnt + n])->GetNcoeffs(); + offsetOld = GetCoeff_Offset(ElmtID[cnt + n]); + offsetNew = result->GetCoeff_Offset(n); + Vmath::Vcopy(nq, tmp1 = GetCoeffs() + offsetOld, 1, + tmp2 = result->UpdateCoeffs() + offsetNew, 1); + } + } +} - for(e = 0; e < nEdges; ++e) - { - edgedir = (*m_exp)[i]->GetEorient(e); - ncoeff_edge = elmtToTrace[i][e]->GetNcoeffs(); - edgeCoeffs[e] = Array(ncoeff_edge); - Vmath::Vcopy(ncoeff_edge, edge_lambda, 1, edgeCoeffs[e], 1); - elmtToTrace[i][e]->SetCoeffsToOrientation( - edgedir, edgeCoeffs[e], edgeCoeffs[e]); - edge_lambda = edge_lambda + ncoeff_edge; - } +/** + * @brief Reset this field, so that geometry information can be updated. + */ +void DisContField2D::v_Reset() +{ + ExpList::v_Reset(); - (*m_exp)[i]->DGDeriv(dir, - tmp_coeffs=m_coeffs+m_coeff_offset[i], - elmtToTrace[i], - edgeCoeffs, - out_tmp = out_d+cnt); - cnt += (*m_exp)[i]->GetNcoeffs(); - } - - BwdTrans(out_d,m_phys); - Vmath::Vsub(m_npoints,m_phys,1,soln,1,m_phys,1); - return L2(m_phys); - } + // Reset boundary condition expansions. + for (int n = 0; n < m_bndCondExpansions.num_elements(); ++n) + { + m_bndCondExpansions[n]->Reset(); + } +} + +/** + * @brief Calculate the \f$ L^2 \f$ error of the \f$ Q_{\rm dir} \f$ + * derivative using the consistent DG evaluation of \f$ Q_{\rm dir} \f$. + * + * The solution provided is of the primative variation at the quadrature + * points and the derivative is compared to the discrete derivative at + * these points, which is likely to be undesirable unless using a much + * higher number of quadrature points than the polynomial order used to + * evaluate \f$ Q_{\rm dir} \f$. + */ +NekDouble DisContField2D::L2_DGDeriv(const int dir, + const Array &soln) +{ + int i, e, ncoeff_edge; + Array tmp_coeffs; + Array out_d(m_ncoeffs), out_tmp; - void DisContField2D::v_HelmSolve( - const Array &inarray, - Array &outarray, - const FlagList &flags, - const StdRegions::ConstFactorMap &factors, - const StdRegions::VarCoeffMap &varcoeff, - const MultiRegions::VarFactorsMap &varfactors, - const Array &dirForcing, - const bool PhysSpaceForcing) + Array> &elmtToTrace = + m_traceMap->GetElmtToTrace(); - { - int i,j,n,cnt,cnt1,nbndry; - int nexp = GetExpSize(); + StdRegions::Orientation edgedir; - Array f(m_ncoeffs); - DNekVec F(m_ncoeffs,f,eWrapper); - Array e_f, e_l; + int cnt; + int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); + Array loc_lambda(LocBndCoeffs), edge_lambda; + m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(), loc_lambda); - //---------------------------------- - // Setup RHS Inner product - //---------------------------------- - if(PhysSpaceForcing) - { - IProductWRTBase(inarray,f); - Vmath::Neg(m_ncoeffs,f,1); - } - else - { - Vmath::Smul(m_ncoeffs,-1.0,inarray,1,f,1); - } + edge_lambda = loc_lambda; - //---------------------------------- - // Solve continuous flux System - //---------------------------------- - int GloBndDofs = m_traceMap->GetNumGlobalBndCoeffs(); - int NumDirichlet = m_traceMap->GetNumLocalDirBndCoeffs(); - int e_ncoeffs,id; - - // Retrieve block matrix of U^e - GlobalMatrixKey HDGLamToUKey(StdRegions::eHybridDGLamToU, - NullAssemblyMapSharedPtr,factors,varcoeff); - const DNekScalBlkMatSharedPtr &HDGLamToU = GetBlockMatrix( - HDGLamToUKey); - - // Retrieve global trace space storage, \Lambda, from trace - // expansion - Array BndSol = m_trace->UpdateCoeffs(); - - // Create trace space forcing, F - Array BndRhs(GloBndDofs,0.0); - - // Zero \Lambda - Vmath::Zero(GloBndDofs,BndSol,1); - - // Retrieve number of local trace space coefficients N_{\lambda}, - // and set up local elemental trace solution \lambda^e. - int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); - Array loc_lambda(LocBndCoeffs); - DNekVec LocLambda(LocBndCoeffs,loc_lambda,eWrapper); - - //---------------------------------- - // Evaluate Trace Forcing vector F - // Kirby et al, 2010, P23, Step 5. - //---------------------------------- - // Loop over all expansions in the domain - for(cnt = cnt1 = n = 0; n < nexp; ++n) - { - nbndry = (*m_exp)[n]->NumDGBndryCoeffs(); + // Calculate Q using standard DG formulation. + for (i = cnt = 0; i < GetExpSize(); ++i) + { + // Probably a better way of setting up lambda than this. + // Note cannot use PutCoeffsInToElmts since lambda space + // is mapped during the solve. + int nEdges = (*m_exp)[i]->GetNedges(); + Array> edgeCoeffs(nEdges); - e_ncoeffs = (*m_exp)[n]->GetNcoeffs(); - e_f = f + cnt; - e_l = loc_lambda + cnt1; + for (e = 0; e < nEdges; ++e) + { + edgedir = (*m_exp)[i]->GetEorient(e); + ncoeff_edge = elmtToTrace[i][e]->GetNcoeffs(); + edgeCoeffs[e] = Array(ncoeff_edge); + Vmath::Vcopy(ncoeff_edge, edge_lambda, 1, edgeCoeffs[e], 1); + elmtToTrace[i][e]->SetCoeffsToOrientation(edgedir, edgeCoeffs[e], + edgeCoeffs[e]); + edge_lambda = edge_lambda + ncoeff_edge; + } - // Local trace space \lambda^e - DNekVec Floc (nbndry, e_l, eWrapper); - // Local forcing f^e - DNekVec ElmtFce (e_ncoeffs, e_f, eWrapper); - // Compute local (U^e)^{\top} f^e - Floc = Transpose(*(HDGLamToU->GetBlock(n,n)))*ElmtFce; + (*m_exp)[i]->DGDeriv(dir, tmp_coeffs = m_coeffs + m_coeff_offset[i], + elmtToTrace[i], edgeCoeffs, out_tmp = out_d + cnt); + cnt += (*m_exp)[i]->GetNcoeffs(); + } + + BwdTrans(out_d, m_phys); + Vmath::Vsub(m_npoints, m_phys, 1, soln, 1, m_phys, 1); + return L2(m_phys); +} + +void DisContField2D::v_HelmSolve(const Array &inarray, + Array &outarray, + const FlagList &flags, + const StdRegions::ConstFactorMap &factors, + const StdRegions::VarCoeffMap &varcoeff, + const MultiRegions::VarFactorsMap &varfactors, + const Array &dirForcing, + const bool PhysSpaceForcing) - cnt += e_ncoeffs; - cnt1 += nbndry; - } +{ + int i, j, n, cnt, cnt1, nbndry; + int nexp = GetExpSize(); - // Assemble local \lambda_e into global \Lambda - m_traceMap->AssembleBnd(loc_lambda,BndRhs); + Array f(m_ncoeffs); + DNekVec F(m_ncoeffs, f, eWrapper); + Array e_f, e_l; - // Copy Dirichlet boundary conditions and weak forcing into trace - // space - cnt = 0; - for(i = 0; i < m_bndCondExpansions.num_elements(); ++i) + //---------------------------------- + // Setup RHS Inner product + //---------------------------------- + if (PhysSpaceForcing) + { + IProductWRTBase(inarray, f); + Vmath::Neg(m_ncoeffs, f, 1); + } + else + { + Vmath::Smul(m_ncoeffs, -1.0, inarray, 1, f, 1); + } + + //---------------------------------- + // Solve continuous flux System + //---------------------------------- + int GloBndDofs = m_traceMap->GetNumGlobalBndCoeffs(); + int NumDirichlet = m_traceMap->GetNumLocalDirBndCoeffs(); + int e_ncoeffs, id; + + // Retrieve block matrix of U^e + GlobalMatrixKey HDGLamToUKey(StdRegions::eHybridDGLamToU, + NullAssemblyMapSharedPtr, factors, varcoeff); + const DNekScalBlkMatSharedPtr &HDGLamToU = GetBlockMatrix(HDGLamToUKey); + + // Retrieve global trace space storage, \Lambda, from trace + // expansion + Array BndSol = m_trace->UpdateCoeffs(); + + // Create trace space forcing, F + Array BndRhs(GloBndDofs, 0.0); + + // Zero \Lambda + Vmath::Zero(GloBndDofs, BndSol, 1); + + // Retrieve number of local trace space coefficients N_{\lambda}, + // and set up local elemental trace solution \lambda^e. + int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); + Array loc_lambda(LocBndCoeffs); + DNekVec LocLambda(LocBndCoeffs, loc_lambda, eWrapper); + + //---------------------------------- + // Evaluate Trace Forcing vector F + // Kirby et al, 2010, P23, Step 5. + //---------------------------------- + // Loop over all expansions in the domain + for (cnt = cnt1 = n = 0; n < nexp; ++n) + { + nbndry = (*m_exp)[n]->NumDGBndryCoeffs(); + + e_ncoeffs = (*m_exp)[n]->GetNcoeffs(); + e_f = f + cnt; + e_l = loc_lambda + cnt1; + + // Local trace space \lambda^e + DNekVec Floc(nbndry, e_l, eWrapper); + // Local forcing f^e + DNekVec ElmtFce(e_ncoeffs, e_f, eWrapper); + // Compute local (U^e)^{\top} f^e + Floc = Transpose(*(HDGLamToU->GetBlock(n, n))) * ElmtFce; + + cnt += e_ncoeffs; + cnt1 += nbndry; + } + + // Assemble local \lambda_e into global \Lambda + m_traceMap->AssembleBnd(loc_lambda, BndRhs); + + // Copy Dirichlet boundary conditions and weak forcing into trace + // space + cnt = 0; + for (i = 0; i < m_bndCondExpansions.num_elements(); ++i) + { + if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eDirichlet) + { + for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j) { - if(m_bndConditions[i]->GetBoundaryConditionType() == - SpatialDomains::eDirichlet) - { - for(j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j) - { - id = m_traceMap->GetBndCondCoeffsToGlobalCoeffsMap(cnt++); - BndSol[id] = m_bndCondExpansions[i]->GetCoeffs()[j]; - } - } - else if (m_bndConditions[i]->GetBoundaryConditionType() == - SpatialDomains::eNeumann || - m_bndConditions[i]->GetBoundaryConditionType() == - SpatialDomains::eRobin) - { - //Add weak boundary condition to trace forcing - for(j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j) - { - id = m_traceMap->GetBndCondCoeffsToGlobalCoeffsMap(cnt++); - BndRhs[id] += m_bndCondExpansions[i]->GetCoeffs()[j]; - } - } + id = m_traceMap->GetBndCondCoeffsToGlobalCoeffsMap(cnt++); + BndSol[id] = m_bndCondExpansions[i]->GetCoeffs()[j]; } - - //---------------------------------- - // Solve trace problem: \Lambda = K^{-1} F - // K is the HybridDGHelmBndLam matrix. - //---------------------------------- - if(GloBndDofs - NumDirichlet > 0) + } + else if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eNeumann || + m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eRobin) + { + // Add weak boundary condition to trace forcing + for (j = 0; j < (m_bndCondExpansions[i])->GetNcoeffs(); ++j) { - GlobalLinSysKey key(StdRegions::eHybridDGHelmBndLam, - m_traceMap,factors,varcoeff); - GlobalLinSysSharedPtr LinSys = GetGlobalBndLinSys(key); - LinSys->Solve(BndRhs,BndSol,m_traceMap); + id = m_traceMap->GetBndCondCoeffsToGlobalCoeffsMap(cnt++); + BndRhs[id] += m_bndCondExpansions[i]->GetCoeffs()[j]; } - - //---------------------------------- - // Internal element solves - //---------------------------------- - GlobalMatrixKey invHDGhelmkey(StdRegions::eInvHybridDGHelmholtz, - NullAssemblyMapSharedPtr,factors,varcoeff); - const DNekScalBlkMatSharedPtr& InvHDGHelm = GetBlockMatrix( - invHDGhelmkey); - DNekVec out(m_ncoeffs,outarray,eWrapper); - Vmath::Zero(m_ncoeffs,outarray,1); - - // get local trace solution from BndSol - m_traceMap->GlobalToLocalBnd(BndSol,loc_lambda); - - // out = u_f + u_lam = (*InvHDGHelm)*f + (LamtoU)*Lam - out = (*InvHDGHelm)*F + (*HDGLamToU)*LocLambda; } + } + //---------------------------------- + // Solve trace problem: \Lambda = K^{-1} F + // K is the HybridDGHelmBndLam matrix. + //---------------------------------- + if (GloBndDofs - NumDirichlet > 0) + { + GlobalLinSysKey key(StdRegions::eHybridDGHelmBndLam, m_traceMap, + factors, varcoeff); + GlobalLinSysSharedPtr LinSys = GetGlobalBndLinSys(key); + LinSys->Solve(BndRhs, BndSol, m_traceMap); + } + + //---------------------------------- + // Internal element solves + //---------------------------------- + GlobalMatrixKey invHDGhelmkey(StdRegions::eInvHybridDGHelmholtz, + NullAssemblyMapSharedPtr, factors, varcoeff); + const DNekScalBlkMatSharedPtr &InvHDGHelm = GetBlockMatrix(invHDGhelmkey); + DNekVec out(m_ncoeffs, outarray, eWrapper); + Vmath::Zero(m_ncoeffs, outarray, 1); + + // get local trace solution from BndSol + m_traceMap->GlobalToLocalBnd(BndSol, loc_lambda); + + // out = u_f + u_lam = (*InvHDGHelm)*f + (LamtoU)*Lam + out = (*InvHDGHelm) * F + (*HDGLamToU) * LocLambda; +} + +/** + * @brief Calculates the result of the multiplication of a global matrix + * of type specified by @a mkey with a vector given by @a inarray. + * + * @param mkey Key representing desired matrix multiplication. + * @param inarray Input vector. + * @param outarray Resulting multiplication. + */ +void DisContField2D::v_GeneralMatrixOp( + const GlobalMatrixKey &gkey, const Array &inarray, + Array &outarray, CoeffState coeffstate) +{ + int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); + Array loc_lambda(LocBndCoeffs); + DNekVec LocLambda(LocBndCoeffs, loc_lambda, eWrapper); + const DNekScalBlkMatSharedPtr &HDGHelm = GetBlockMatrix(gkey); + + m_traceMap->GlobalToLocalBnd(inarray, loc_lambda); + LocLambda = (*HDGHelm) * LocLambda; + m_traceMap->AssembleBnd(loc_lambda, outarray); +} + +/** + * @brief Search through the edge expansions and identify which ones + * have Robin/Mixed type boundary conditions. + * + * If a Robin boundary is found then store the edge ID of the boundary + * condition and the array of points of the physical space boundary + * condition which are hold the boundary condition primitive variable + * coefficient at the quatrature points + * + * @return A map containing the Robin boundary condition information + * using a key of the element ID. + */ +map DisContField2D::v_GetRobinBCInfo(void) +{ + int i, cnt; + map returnval; + Array ElmtID, EdgeID; + GetBoundaryToElmtMap(ElmtID, EdgeID); - /** - * @brief Calculates the result of the multiplication of a global matrix - * of type specified by @a mkey with a vector given by @a inarray. - * - * @param mkey Key representing desired matrix multiplication. - * @param inarray Input vector. - * @param outarray Resulting multiplication. - */ - void DisContField2D::v_GeneralMatrixOp( - const GlobalMatrixKey &gkey, - const Array &inarray, - Array &outarray, - CoeffState coeffstate) - { - int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); - Array loc_lambda(LocBndCoeffs); - DNekVec LocLambda(LocBndCoeffs,loc_lambda,eWrapper); - const DNekScalBlkMatSharedPtr& HDGHelm = GetBlockMatrix(gkey); - - m_traceMap->GlobalToLocalBnd(inarray, loc_lambda); - LocLambda = (*HDGHelm) * LocLambda; - m_traceMap->AssembleBnd(loc_lambda,outarray); - } + for (cnt = i = 0; i < m_bndCondExpansions.num_elements(); ++i) + { + MultiRegions::ExpListSharedPtr locExpList; - /** - * @brief Search through the edge expansions and identify which ones - * have Robin/Mixed type boundary conditions. - * - * If a Robin boundary is found then store the edge ID of the boundary - * condition and the array of points of the physical space boundary - * condition which are hold the boundary condition primitive variable - * coefficient at the quatrature points - * - * @return A map containing the Robin boundary condition information - * using a key of the element ID. - */ - map DisContField2D::v_GetRobinBCInfo(void) + if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eRobin) { - int i,cnt; - map returnval; - Array ElmtID,EdgeID; - GetBoundaryToElmtMap(ElmtID,EdgeID); + int e, elmtid; + Array Array_tmp; - for(cnt = i = 0; i < m_bndCondExpansions.num_elements(); ++i) - { - MultiRegions::ExpListSharedPtr locExpList; + locExpList = m_bndCondExpansions[i]; - if(m_bndConditions[i]->GetBoundaryConditionType() == - SpatialDomains::eRobin) - { - int e,elmtid; - Array Array_tmp; + int npoints = locExpList->GetNpoints(); + Array x0(npoints, 0.0); + Array x1(npoints, 0.0); + Array x2(npoints, 0.0); + Array coeffphys(npoints); - locExpList = m_bndCondExpansions[i]; + locExpList->GetCoords(x0, x1, x2); - int npoints = locExpList->GetNpoints(); - Array x0(npoints, 0.0); - Array x1(npoints, 0.0); - Array x2(npoints, 0.0); - Array coeffphys(npoints); + LibUtilities::Equation coeffeqn = + std::static_pointer_cast< + SpatialDomains::RobinBoundaryCondition>(m_bndConditions[i]) + ->m_robinPrimitiveCoeff; - locExpList->GetCoords(x0, x1, x2); + // evalaute coefficient + coeffeqn.Evaluate(x0, x1, x2, 0.0, coeffphys); - LibUtilities::Equation coeffeqn = - std::static_pointer_cast< - SpatialDomains::RobinBoundaryCondition> - (m_bndConditions[i])->m_robinPrimitiveCoeff; - - // evalaute coefficient - coeffeqn.Evaluate(x0, x1, x2, 0.0, coeffphys); - - for(e = 0; e < locExpList->GetExpSize(); ++e) - { - RobinBCInfoSharedPtr rInfo = - MemoryManager - ::AllocateSharedPtr( - EdgeID[cnt+e], - Array_tmp = coeffphys + - locExpList->GetPhys_Offset(e)); - - elmtid = ElmtID[cnt+e]; - // make link list if necessary - if(returnval.count(elmtid) != 0) - { - rInfo->next = returnval.find(elmtid)->second; - } - returnval[elmtid] = rInfo; - } + for (e = 0; e < locExpList->GetExpSize(); ++e) + { + RobinBCInfoSharedPtr rInfo = + MemoryManager::AllocateSharedPtr( + EdgeID[cnt + e], + Array_tmp = coeffphys + locExpList->GetPhys_Offset(e)); + + elmtid = ElmtID[cnt + e]; + // make link list if necessary + if (returnval.count(elmtid) != 0) + { + rInfo->next = returnval.find(elmtid)->second; } - cnt += m_bndCondExpansions[i]->GetExpSize(); + returnval[elmtid] = rInfo; } - - return returnval; } + cnt += m_bndCondExpansions[i]->GetExpSize(); + } + + return returnval; +} + +/** + * @brief Evaluate HDG post-processing to increase polynomial order of + * solution. + * + * This function takes the solution (assumed to be one order lower) in + * physical space, and postprocesses at the current polynomial order by + * solving the system: + * + * \f[ + * \begin{aligned} + * (\nabla w, \nabla u^*) &= (\nabla w, u), \\ + * \langle \nabla u^*, 1 \rangle &= \langle \nabla u, 1 \rangle + * \end{aligned} + * \f] + * + * where \f$ u \f$ corresponds with the current solution as stored + * inside #m_coeffs. + * + * @param outarray The resulting field \f$ u^* \f$. + */ +void DisContField2D::EvaluateHDGPostProcessing(Array &outarray) +{ + int i, cnt, e, ncoeff_edge; + Array force, out_tmp, qrhs, qrhs1; + Array> &elmtToTrace = + m_traceMap->GetElmtToTrace(); - /** - * @brief Evaluate HDG post-processing to increase polynomial order of - * solution. - * - * This function takes the solution (assumed to be one order lower) in - * physical space, and postprocesses at the current polynomial order by - * solving the system: - * - * \f[ - * \begin{aligned} - * (\nabla w, \nabla u^*) &= (\nabla w, u), \\ - * \langle \nabla u^*, 1 \rangle &= \langle \nabla u, 1 \rangle - * \end{aligned} - * \f] - * - * where \f$ u \f$ corresponds with the current solution as stored - * inside #m_coeffs. - * - * @param outarray The resulting field \f$ u^* \f$. - */ - void DisContField2D::EvaluateHDGPostProcessing( - Array &outarray) - { - int i,cnt,e,ncoeff_edge; - Array force, out_tmp, qrhs, qrhs1; - Array > - &elmtToTrace = m_traceMap->GetElmtToTrace(); + StdRegions::Orientation edgedir; - StdRegions::Orientation edgedir; + int nq_elmt, nm_elmt; + int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); + Array loc_lambda(LocBndCoeffs), edge_lambda; + Array tmp_coeffs; + m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(), loc_lambda); - int nq_elmt, nm_elmt; - int LocBndCoeffs = m_traceMap->GetNumLocalBndCoeffs(); - Array loc_lambda(LocBndCoeffs), edge_lambda; - Array tmp_coeffs; - m_traceMap->GlobalToLocalBnd(m_trace->GetCoeffs(),loc_lambda); + edge_lambda = loc_lambda; - edge_lambda = loc_lambda; + // Calculate Q using standard DG formulation. + for (i = cnt = 0; i < GetExpSize(); ++i) + { + nq_elmt = (*m_exp)[i]->GetTotPoints(); + nm_elmt = (*m_exp)[i]->GetNcoeffs(); + qrhs = Array(nq_elmt); + qrhs1 = Array(nq_elmt); + force = Array(2 * nm_elmt); + out_tmp = force + nm_elmt; + LocalRegions::ExpansionSharedPtr ppExp; + + int num_points0 = (*m_exp)[i]->GetBasis(0)->GetNumPoints(); + int num_points1 = (*m_exp)[i]->GetBasis(1)->GetNumPoints(); + int num_modes0 = (*m_exp)[i]->GetBasis(0)->GetNumModes(); + int num_modes1 = (*m_exp)[i]->GetBasis(1)->GetNumModes(); + + // Probably a better way of setting up lambda than this. Note + // cannot use PutCoeffsInToElmts since lambda space is mapped + // during the solve. + int nEdges = (*m_exp)[i]->GetNedges(); + Array> edgeCoeffs(nEdges); + + for (e = 0; e < (*m_exp)[i]->GetNedges(); ++e) + { + edgedir = (*m_exp)[i]->GetEorient(e); + ncoeff_edge = elmtToTrace[i][e]->GetNcoeffs(); + edgeCoeffs[e] = Array(ncoeff_edge); + Vmath::Vcopy(ncoeff_edge, edge_lambda, 1, edgeCoeffs[e], 1); + elmtToTrace[i][e]->SetCoeffsToOrientation(edgedir, edgeCoeffs[e], + edgeCoeffs[e]); + edge_lambda = edge_lambda + ncoeff_edge; + } - // Calculate Q using standard DG formulation. - for(i = cnt = 0; i < GetExpSize(); ++i) + // creating orthogonal expansion (checking if we have quads or + // triangles) + LibUtilities::ShapeType shape = (*m_exp)[i]->DetShapeType(); + switch (shape) + { + case LibUtilities::eQuadrilateral: { - nq_elmt = (*m_exp)[i]->GetTotPoints(); - nm_elmt = (*m_exp)[i]->GetNcoeffs(); - qrhs = Array(nq_elmt); - qrhs1 = Array(nq_elmt); - force = Array(2*nm_elmt); - out_tmp = force + nm_elmt; - LocalRegions::ExpansionSharedPtr ppExp; - - int num_points0 = (*m_exp)[i]->GetBasis(0)->GetNumPoints(); - int num_points1 = (*m_exp)[i]->GetBasis(1)->GetNumPoints(); - int num_modes0 = (*m_exp)[i]->GetBasis(0)->GetNumModes(); - int num_modes1 = (*m_exp)[i]->GetBasis(1)->GetNumModes(); - - // Probably a better way of setting up lambda than this. Note - // cannot use PutCoeffsInToElmts since lambda space is mapped - // during the solve. - int nEdges = (*m_exp)[i]->GetNedges(); - Array > edgeCoeffs(nEdges); - - for(e = 0; e < (*m_exp)[i]->GetNedges(); ++e) - { - edgedir = (*m_exp)[i]->GetEorient(e); - ncoeff_edge = elmtToTrace[i][e]->GetNcoeffs(); - edgeCoeffs[e] = Array(ncoeff_edge); - Vmath::Vcopy(ncoeff_edge, edge_lambda, 1, edgeCoeffs[e], 1); - elmtToTrace[i][e]->SetCoeffsToOrientation( - edgedir, edgeCoeffs[e], edgeCoeffs[e]); - edge_lambda = edge_lambda + ncoeff_edge; - } - - //creating orthogonal expansion (checking if we have quads or triangles) - LibUtilities::ShapeType shape = (*m_exp)[i]->DetShapeType(); - switch(shape) - { - case LibUtilities::eQuadrilateral: - { - const LibUtilities::PointsKey PkeyQ1(num_points0,LibUtilities::eGaussLobattoLegendre); - const LibUtilities::PointsKey PkeyQ2(num_points1,LibUtilities::eGaussLobattoLegendre); - LibUtilities::BasisKey BkeyQ1(LibUtilities::eOrtho_A, num_modes0, PkeyQ1); - LibUtilities::BasisKey BkeyQ2(LibUtilities::eOrtho_A, num_modes1, PkeyQ2); - SpatialDomains::QuadGeomSharedPtr qGeom = std::dynamic_pointer_cast((*m_exp)[i]->GetGeom()); - ppExp = MemoryManager::AllocateSharedPtr(BkeyQ1, BkeyQ2, qGeom); - } - break; - case LibUtilities::eTriangle: - { - const LibUtilities::PointsKey PkeyT1(num_points0,LibUtilities::eGaussLobattoLegendre); - const LibUtilities::PointsKey PkeyT2(num_points1,LibUtilities::eGaussRadauMAlpha1Beta0); - LibUtilities::BasisKey BkeyT1(LibUtilities::eOrtho_A, num_modes0, PkeyT1); - LibUtilities::BasisKey BkeyT2(LibUtilities::eOrtho_B, num_modes1, PkeyT2); - SpatialDomains::TriGeomSharedPtr tGeom = std::dynamic_pointer_cast((*m_exp)[i]->GetGeom()); - ppExp = MemoryManager::AllocateSharedPtr(BkeyT1, BkeyT2, tGeom); - } - break; - default: - ASSERTL0(false, "Wrong shape type, HDG postprocessing is not implemented"); - }; - - - //DGDeriv - // (d/dx w, d/dx q_0) - (*m_exp)[i]->DGDeriv( - 0,tmp_coeffs = m_coeffs + m_coeff_offset[i], - elmtToTrace[i], edgeCoeffs, out_tmp); - (*m_exp)[i]->BwdTrans(out_tmp,qrhs); - //(*m_exp)[i]->IProductWRTDerivBase(0,qrhs,force); - ppExp->IProductWRTDerivBase(0,qrhs,force); - - - // + (d/dy w, d/dy q_1) - (*m_exp)[i]->DGDeriv( - 1,tmp_coeffs = m_coeffs + m_coeff_offset[i], - elmtToTrace[i], edgeCoeffs, out_tmp); - - (*m_exp)[i]->BwdTrans(out_tmp,qrhs); - //(*m_exp)[i]->IProductWRTDerivBase(1,qrhs,out_tmp); - ppExp->IProductWRTDerivBase(1,qrhs,out_tmp); - - Vmath::Vadd(nm_elmt,force,1,out_tmp,1,force,1); - - // determine force[0] = (1,u) - (*m_exp)[i]->BwdTrans( - tmp_coeffs = m_coeffs + m_coeff_offset[i],qrhs); - force[0] = (*m_exp)[i]->Integral(qrhs); - - // multiply by inverse Laplacian matrix - // get matrix inverse - LocalRegions::MatrixKey lapkey(StdRegions::eInvLaplacianWithUnityMean, ppExp->DetShapeType(), *ppExp); - DNekScalMatSharedPtr lapsys = ppExp->GetLocMatrix(lapkey); - - NekVector in (nm_elmt,force,eWrapper); - NekVector out(nm_elmt); - - out = (*lapsys)*in; - - // Transforming back to modified basis - Array work(nq_elmt); - ppExp->BwdTrans(out.GetPtr(), work); - (*m_exp)[i]->FwdTrans(work, tmp_coeffs = outarray + m_coeff_offset[i]); + const LibUtilities::PointsKey PkeyQ1( + num_points0, LibUtilities::eGaussLobattoLegendre); + const LibUtilities::PointsKey PkeyQ2( + num_points1, LibUtilities::eGaussLobattoLegendre); + LibUtilities::BasisKey BkeyQ1(LibUtilities::eOrtho_A, + num_modes0, PkeyQ1); + LibUtilities::BasisKey BkeyQ2(LibUtilities::eOrtho_A, + num_modes1, PkeyQ2); + SpatialDomains::QuadGeomSharedPtr qGeom = + std::dynamic_pointer_cast( + (*m_exp)[i]->GetGeom()); + ppExp = MemoryManager::AllocateSharedPtr( + BkeyQ1, BkeyQ2, qGeom); } - } + break; + case LibUtilities::eTriangle: + { + const LibUtilities::PointsKey PkeyT1( + num_points0, LibUtilities::eGaussLobattoLegendre); + const LibUtilities::PointsKey PkeyT2( + num_points1, LibUtilities::eGaussRadauMAlpha1Beta0); + LibUtilities::BasisKey BkeyT1(LibUtilities::eOrtho_A, + num_modes0, PkeyT1); + LibUtilities::BasisKey BkeyT2(LibUtilities::eOrtho_B, + num_modes1, PkeyT2); + SpatialDomains::TriGeomSharedPtr tGeom = + std::dynamic_pointer_cast( + (*m_exp)[i]->GetGeom()); + ppExp = MemoryManager::AllocateSharedPtr( + BkeyT1, BkeyT2, tGeom); + } + break; + default: + ASSERTL0( + false, + "Wrong shape type, HDG postprocessing is not implemented"); + }; + + // DGDeriv + // (d/dx w, d/dx q_0) + (*m_exp)[i]->DGDeriv(0, tmp_coeffs = m_coeffs + m_coeff_offset[i], + elmtToTrace[i], edgeCoeffs, out_tmp); + (*m_exp)[i]->BwdTrans(out_tmp, qrhs); + //(*m_exp)[i]->IProductWRTDerivBase(0,qrhs,force); + ppExp->IProductWRTDerivBase(0, qrhs, force); + + // + (d/dy w, d/dy q_1) + (*m_exp)[i]->DGDeriv(1, tmp_coeffs = m_coeffs + m_coeff_offset[i], + elmtToTrace[i], edgeCoeffs, out_tmp); + + (*m_exp)[i]->BwdTrans(out_tmp, qrhs); + //(*m_exp)[i]->IProductWRTDerivBase(1,qrhs,out_tmp); + ppExp->IProductWRTDerivBase(1, qrhs, out_tmp); + + Vmath::Vadd(nm_elmt, force, 1, out_tmp, 1, force, 1); + + // determine force[0] = (1,u) + (*m_exp)[i]->BwdTrans(tmp_coeffs = m_coeffs + m_coeff_offset[i], qrhs); + force[0] = (*m_exp)[i]->Integral(qrhs); + + // multiply by inverse Laplacian matrix + // get matrix inverse + LocalRegions::MatrixKey lapkey(StdRegions::eInvLaplacianWithUnityMean, + ppExp->DetShapeType(), *ppExp); + DNekScalMatSharedPtr lapsys = ppExp->GetLocMatrix(lapkey); + + NekVector in(nm_elmt, force, eWrapper); + NekVector out(nm_elmt); + + out = (*lapsys) * in; + + // Transforming back to modified basis + Array work(nq_elmt); + ppExp->BwdTrans(out.GetPtr(), work); + (*m_exp)[i]->FwdTrans(work, tmp_coeffs = outarray + m_coeff_offset[i]); + } +} + +/** + * Evaluates the boundary condition expansions, \a bndCondExpansions, + * given the information provided by \a bndConditions. + * @param time The time at which the boundary conditions + * should be evaluated. + * @param bndCondExpansions List of boundary conditions. + * @param bndConditions Information about the boundary conditions. + * + * This will only be undertaken for time dependent + * boundary conditions unless time == 0.0 which is the + * case when the method is called from the constructor. + */ +void DisContField2D::v_EvaluateBoundaryConditions(const NekDouble time, + const std::string varName, + const NekDouble x2_in, + const NekDouble x3_in) +{ + int i; + int npoints; + int nbnd = m_bndCondExpansions.num_elements(); - /** - * Evaluates the boundary condition expansions, \a bndCondExpansions, - * given the information provided by \a bndConditions. - * @param time The time at which the boundary conditions - * should be evaluated. - * @param bndCondExpansions List of boundary conditions. - * @param bndConditions Information about the boundary conditions. - * - * This will only be undertaken for time dependent - * boundary conditions unless time == 0.0 which is the - * case when the method is called from the constructor. - */ - void DisContField2D::v_EvaluateBoundaryConditions( - const NekDouble time, - const std::string varName, - const NekDouble x2_in, - const NekDouble x3_in) - { - int i; - int npoints; - int nbnd = m_bndCondExpansions.num_elements(); + MultiRegions::ExpListSharedPtr locExpList; - MultiRegions::ExpListSharedPtr locExpList; + for (i = 0; i < nbnd; ++i) + { + if (time == 0.0 || m_bndConditions[i]->IsTimeDependent()) + { + locExpList = m_bndCondExpansions[i]; + npoints = locExpList->GetNpoints(); + Array x0(npoints, 0.0); + Array x1(npoints, 0.0); + Array x2(npoints, 0.0); + + // Homogeneous input case for x2. + if (x2_in == NekConstants::kNekUnsetDouble) + { + locExpList->GetCoords(x0, x1, x2); + } + else + { + locExpList->GetCoords(x0, x1, x2); + Vmath::Fill(npoints, x2_in, x2, 1); + } - for (i = 0; i < nbnd; ++i) + if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eDirichlet) { - if (time == 0.0 || - m_bndConditions[i]->IsTimeDependent()) - { - locExpList = m_bndCondExpansions[i]; - npoints = locExpList->GetNpoints(); - Array x0(npoints, 0.0); - Array x1(npoints, 0.0); - Array x2(npoints, 0.0); + SpatialDomains::DirichletBCShPtr bcPtr = + std::static_pointer_cast< + SpatialDomains::DirichletBoundaryCondition>( + m_bndConditions[i]); + string filebcs = bcPtr->m_filename; - // Homogeneous input case for x2. - if (x2_in == NekConstants::kNekUnsetDouble) - { - locExpList->GetCoords(x0, x1, x2); - } - else - { - locExpList->GetCoords(x0, x1, x2); - Vmath::Fill(npoints, x2_in, x2, 1); - } + if (filebcs != "") + { + ExtractFileBCs(filebcs, bcPtr->GetComm(), varName, + locExpList); + } + else + { + LibUtilities::Equation condition = + std::static_pointer_cast< + SpatialDomains::DirichletBoundaryCondition>( + m_bndConditions[i]) + ->m_dirichletCondition; - if (m_bndConditions[i]->GetBoundaryConditionType() - == SpatialDomains::eDirichlet) - { - SpatialDomains::DirichletBCShPtr bcPtr - = std::static_pointer_cast< - SpatialDomains::DirichletBoundaryCondition>( - m_bndConditions[i]); - string filebcs = bcPtr->m_filename; - - if (filebcs != "") - { - ExtractFileBCs(filebcs, bcPtr->GetComm(), varName, locExpList); - } - else - { - LibUtilities::Equation condition = - std::static_pointer_cast< - SpatialDomains::DirichletBoundaryCondition> - (m_bndConditions[i])-> - m_dirichletCondition; - - condition.Evaluate(x0, x1, x2, time, - locExpList->UpdatePhys()); - } + condition.Evaluate(x0, x1, x2, time, + locExpList->UpdatePhys()); + } - locExpList->FwdTrans_BndConstrained( - locExpList->GetPhys(), - locExpList->UpdateCoeffs()); - } - else if (m_bndConditions[i]->GetBoundaryConditionType() - == SpatialDomains::eNeumann) - { - SpatialDomains::NeumannBCShPtr bcPtr = std::static_pointer_cast< - SpatialDomains::NeumannBoundaryCondition>( - m_bndConditions[i]); - string filebcs = bcPtr->m_filename; - if (filebcs != "") - { - ExtractFileBCs(filebcs, bcPtr->GetComm(), varName, locExpList); - } - else - { - LibUtilities::Equation condition = - std::static_pointer_cast< - SpatialDomains::NeumannBoundaryCondition> - (m_bndConditions[i])-> - m_neumannCondition; - condition.Evaluate(x0, x1, x2, time, - locExpList->UpdatePhys()); - } + locExpList->FwdTrans_BndConstrained(locExpList->GetPhys(), + locExpList->UpdateCoeffs()); + } + else if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eNeumann) + { + SpatialDomains::NeumannBCShPtr bcPtr = std::static_pointer_cast< + SpatialDomains::NeumannBoundaryCondition>( + m_bndConditions[i]); + string filebcs = bcPtr->m_filename; + if (filebcs != "") + { + ExtractFileBCs(filebcs, bcPtr->GetComm(), varName, + locExpList); + } + else + { + LibUtilities::Equation condition = + std::static_pointer_cast< + SpatialDomains::NeumannBoundaryCondition>( + m_bndConditions[i]) + ->m_neumannCondition; + condition.Evaluate(x0, x1, x2, time, + locExpList->UpdatePhys()); + } - locExpList->IProductWRTBase( - locExpList->GetPhys(), - locExpList->UpdateCoeffs()); - } - else if (m_bndConditions[i]->GetBoundaryConditionType() - == SpatialDomains::eRobin) - { - SpatialDomains::RobinBCShPtr bcPtr = std::static_pointer_cast< - SpatialDomains::RobinBoundaryCondition> - (m_bndConditions[i]); - string filebcs = bcPtr->m_filename; - - if (filebcs != "") - { - ExtractFileBCs(filebcs, bcPtr->GetComm(), varName, locExpList); - } - else - { - LibUtilities::Equation condition = - std::static_pointer_cast< - SpatialDomains::RobinBoundaryCondition> - (m_bndConditions[i])-> - m_robinFunction; - condition.Evaluate(x0, x1, x2, time, - locExpList->UpdatePhys()); - } + locExpList->IProductWRTBase(locExpList->GetPhys(), + locExpList->UpdateCoeffs()); + } + else if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::eRobin) + { + SpatialDomains::RobinBCShPtr bcPtr = std::static_pointer_cast< + SpatialDomains::RobinBoundaryCondition>(m_bndConditions[i]); + string filebcs = bcPtr->m_filename; - locExpList->IProductWRTBase( - locExpList->GetPhys(), - locExpList->UpdateCoeffs()); - } - else if (m_bndConditions[i]->GetBoundaryConditionType() - == SpatialDomains::ePeriodic) - { - continue; - } - else - { - ASSERTL0(false, "This type of BC not implemented yet"); - } + if (filebcs != "") + { + ExtractFileBCs(filebcs, bcPtr->GetComm(), varName, + locExpList); + } + else + { + LibUtilities::Equation condition = + std::static_pointer_cast< + SpatialDomains::RobinBoundaryCondition>( + m_bndConditions[i]) + ->m_robinFunction; + condition.Evaluate(x0, x1, x2, time, + locExpList->UpdatePhys()); } + + locExpList->IProductWRTBase(locExpList->GetPhys(), + locExpList->UpdateCoeffs()); + } + else if (m_bndConditions[i]->GetBoundaryConditionType() == + SpatialDomains::ePeriodic) + { + continue; + } + else + { + ASSERTL0(false, "This type of BC not implemented yet"); } } - } // end of namespace -} //end of namespace + } +} +} // namespace MultiRegions +} // namespace Nektar diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 1cb7fad24..81c46e47b 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -147,8 +147,8 @@ namespace Nektar */ Array m_bndConditions; - std::map> m_traceEdgeLeft; - std::map> m_traceEdgeRight; + std::map> m_traceEdgeLeft; + std::map> m_traceEdgeRight; std::unordered_set m_interfaceEdgeLeft, m_interfaceEdgeRight; GlobalLinSysMapShPtr m_globalBndMat; diff --git a/library/MultiRegions/ExpList.cpp b/library/MultiRegions/ExpList.cpp index 3fef4da00..da89cd1b5 100644 --- a/library/MultiRegions/ExpList.cpp +++ b/library/MultiRegions/ExpList.cpp @@ -1477,7 +1477,7 @@ namespace Nektar // Get the list of elements whose bounding box contains the desired // point. std::vector elmts = - m_graph->GetRegionsContainingPoint(p, m_graph->GetMeshDimension()); + m_graph->GetElementsContainingPoint(p); NekDouble nearpt = 1e6; NekDouble nearpt_min = 1e6; diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index d57b85e17..9dae22387 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -42,383 +42,445 @@ using namespace std; namespace Nektar { - namespace SpatialDomains +namespace SpatialDomains +{ +Interfaces::Interfaces(const LibUtilities::SessionReaderSharedPtr &pSession, + const MeshGraphSharedPtr &meshGraph) + : m_meshGraph(meshGraph), m_session(pSession) +{ + ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); +} + +std::string ReadTag(std::string &tagStr) +{ + std::string::size_type indxBeg = tagStr.find_first_of('[') + 1; + std::string::size_type indxEnd = tagStr.find_last_of(']') - 1; + + ASSERTL0( + indxBeg <= indxEnd, + (std::string("Error reading interface region definition:") + tagStr) + .c_str()); + + std::string indxStr = tagStr.substr(indxBeg, indxEnd - indxBeg + 1); + + return indxStr; +} + +std::vector GetElementsFromVertex(CompositeMap &domain, + int vertId1, int vertId2) +{ + std::vector ret; + for (auto &comp : domain) { - Interfaces::Interfaces( - const LibUtilities::SessionReaderSharedPtr &pSession, - const MeshGraphSharedPtr &meshGraph) : - m_meshGraph(meshGraph), m_session(pSession) + for (auto &geom : comp.second->m_geomVec) { - ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); + for (int i = 0; i < geom->GetNumVerts(); ++i) + { + if (geom->GetVid(i) == vertId1 || geom->GetVid(i) == vertId2) + { + ret.push_back(geom); + break; + } + } } + } + return ret; +} - std::string ReadTag(std::string &tagStr) +void Interfaces::ReadInterfaces(TiXmlElement *interfaces) +{ + + ASSERTL0(interfaces, "Unable to find INTERFACES tag in file."); + + TiXmlElement *interfaceElement = interfaces->FirstChildElement(); + + while (interfaceElement) + { + std::string interfaceType = interfaceElement->Value(); + + int err; + int indx; + + err = interfaceElement->QueryIntAttribute("ID", &indx); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); + + std::string interfaceRightDomainStr; + err = interfaceElement->QueryStringAttribute("RIGHTDOMAIN", + &interfaceRightDomainStr); + ASSERTL0(err == TIXML_SUCCESS, + "Unable to read right interface domain."); + auto rightDomain = + m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); + + std::string interfaceLeftDomainStr; + err = interfaceElement->QueryStringAttribute("LEFTDOMAIN", + &interfaceLeftDomainStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read left interface domain."); + auto leftDomain = + m_meshGraph->GetDomain(stoi(ReadTag(interfaceLeftDomainStr))); + + std::string interfaceEdgeStr; + int interfaceErr = interfaceElement->QueryStringAttribute( + "INTERFACE", &interfaceEdgeStr); + map interfaceEdge; + if (interfaceErr == TIXML_SUCCESS) { - std::string::size_type indxBeg = tagStr.find_first_of('[') + 1; - std::string::size_type indxEnd = tagStr.find_last_of(']') - 1; + std::string indxStr = ReadTag(interfaceEdgeStr); + m_meshGraph->GetCompositeList(indxStr, interfaceEdge); + } - ASSERTL0(indxBeg <= indxEnd, - (std::string("Error reading interface region definition:") - + tagStr).c_str()); + std::string leftEdgeStr; + int leftEdgeErr = + interfaceElement->QueryStringAttribute("LEFTEDGE", &leftEdgeStr); + map leftEdge; + if (leftEdgeErr == TIXML_SUCCESS) + { + std::string indxStr = ReadTag(leftEdgeStr); + m_meshGraph->GetCompositeList(indxStr, leftEdge); + } - std::string indxStr = tagStr.substr(indxBeg, indxEnd - indxBeg + 1); + std::string rightEdgeStr; + int rightEdgeErr = + interfaceElement->QueryStringAttribute("RIGHTEDGE", &rightEdgeStr); + map rightEdge; + if (rightEdgeErr == TIXML_SUCCESS) + { + std::string indxStr = ReadTag(rightEdgeStr); + m_meshGraph->GetCompositeList(indxStr, rightEdge); + } - return indxStr; + if (interfaceErr == TIXML_SUCCESS) + { + ASSERTL0(leftEdgeErr != TIXML_SUCCESS && + rightEdgeErr != TIXML_SUCCESS, + "Choose to define either INTERFACE or both LEFTEDGE " + "and RIGHTEDGE.") + } + else if (leftEdgeErr == TIXML_SUCCESS && rightEdgeErr == TIXML_SUCCESS) + { + ASSERTL0(interfaceErr != TIXML_SUCCESS, + "Choose to define either INTERFACE or both LEFTEDGE " + "and RIGHTEDGE.") + } + else + { + ASSERTL0((interfaceErr + 1) * (leftEdgeErr + 1) * + (rightEdgeErr + 1) == + 1, + "Choose to define either INTERFACE or both LEFTEDGE " + "and RIGHTEDGE.") } + if (interfaceType == "R") + { + std::string originStr; + err = interfaceElement->QueryStringAttribute("ORIGIN", &originStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read origin."); + std::vector originVec; + ParseUtils::GenerateVector(originStr, originVec); + auto origin = + PointGeom(3, 0, originVec[0], originVec[1], originVec[2]); + + std::string axisStr; + err = interfaceElement->QueryStringAttribute("AXIS", &axisStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read axis."); + std::vector axis; + ParseUtils::GenerateVector(axisStr, axis); + + std::string angularVelStr; + err = interfaceElement->QueryStringAttribute("ANGVEL", + &angularVelStr); + ASSERTL0(err == TIXML_SUCCESS, "Unable to read angular velocity."); + + NekDouble angularVel = stod(angularVelStr); + + InterfaceShPtr rotatingInterface( + MemoryManager::AllocateSharedPtr( + rightDomain, leftDomain, origin, axis, angularVel)); + + if (interfaceErr == TIXML_SUCCESS) + { + rotatingInterface->SetInterfaceEdge(interfaceEdge); + } + else + { + rotatingInterface->SetEdgeRight(rightEdge); + rotatingInterface->SetEdgeLeft(leftEdge); + } + + m_interfaces[indx] = rotatingInterface; + } - std::vector GetElementsFromVertex( - CompositeMap &domain, int vertId1, int vertId2) + interfaceElement = interfaceElement->NextSiblingElement(); + } +} + +void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) +{ + + auto rightDomain = GetRightDomain(); + auto interfaceEdge = GetInterfaceEdge(); + + int maxVertId = -1; + for (auto &vert : graph->GetAllPointGeoms()) + { + maxVertId = std::max(maxVertId, vert.first); + } + + int maxEdgeId = -1; + for (auto &edge : graph->GetAllSegGeoms()) { - std::vector ret; - for (auto &comp : domain) + maxEdgeId = std::max(maxEdgeId, edge.first); + } + + ++maxVertId; + ++maxEdgeId; + + // Map that stores existing renumbered geometry. + std::map vertDone; + std::map edgeDone; + // Map that stores elements to process for renumbered edges and points + std::map elementToDo; + + CurveMap &curvedEdges = graph->GetCurvedEdges(); + + for (auto &comp : interfaceEdge) + { + for (auto &geom : comp.second->m_geomVec) { - for (auto &geom : comp.second->m_geomVec) + ASSERTL0(geom->GetShapeType() == LibUtilities::eSegment, + "Unexpected geometry type in composite"); + + GeometryLinkSharedPtr elmtLink = graph->GetElementsFromEdge( + std::static_pointer_cast(geom)); + + size_t numElmts = elmtLink->size(); + if (numElmts == 1) + { + continue; + } + + int vid[2] = {geom->GetVid(0), geom->GetVid(1)}; + PointGeomSharedPtr newVerts[2]; + + for (int i = 0; i < 2; ++i) { - for (int i = 0; i < geom->GetNumVerts(); ++i) + auto it = vertDone.find(vid[i]); + if (it == vertDone.end()) + { + // Create a new vertex + newVerts[i] = MemoryManager::AllocateSharedPtr( + *geom->GetVertex(i)); + newVerts[i]->SetGlobalID(maxVertId); + graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; + vertDone[vid[i]] = maxVertId++; + } + else { - if (geom->GetVid(i) == vertId1 || - geom->GetVid(i) == vertId2) - { - ret.push_back(geom); - break; - } + newVerts[i] = graph->GetVertex(it->second); } } + + SegGeomSharedPtr oldEdge = std::static_pointer_cast(geom); + + CurveSharedPtr newCurve; + if (oldEdge->GetCurve()) + { + newCurve = MemoryManager::AllocateSharedPtr( + maxEdgeId, oldEdge->GetCurve()->m_ptype); + + for (auto &pt : oldEdge->GetCurve()->m_points) + { + newCurve->m_points.push_back( + MemoryManager::AllocateSharedPtr(*pt)); + } + + curvedEdges[maxEdgeId] = newCurve; + } + + auto newEdge = MemoryManager::AllocateSharedPtr( + maxEdgeId, newVerts[0]->GetCoordim(), newVerts, newCurve); + + graph->GetAllSegGeoms()[maxEdgeId] = newEdge; + edgeDone[geom->GetGlobalID()] = newEdge; + + m_leftEdge[oldEdge->GetGlobalID()] = oldEdge; + m_rightEdge[maxEdgeId] = newEdge; + maxEdgeId++; + + auto toProcess = GetElementsFromVertex(rightDomain, vid[0], vid[1]); + for (auto &elementToProcess : toProcess) + { + elementToDo[elementToProcess->GetGlobalID()] = elementToProcess; + } } - return ret; } - void Interfaces::ReadInterfaces(TiXmlElement *interfaces) + for (auto &elementMap : elementToDo) + { + auto rightGeom = elementMap.second; + + std::vector newEdges(rightGeom->GetNumEdges()); + + // Loop over edges + for (int j = 0; j < newEdges.size(); ++j) { + auto edge = + std::static_pointer_cast(rightGeom->GetEdge(j)); + auto edgeIt = edgeDone.find(edge->GetGlobalID()); + if (edgeIt != edgeDone.end()) + { + newEdges[j] = edgeIt->second; + continue; + } - ASSERTL0(interfaces, "Unable to find INTERFACES tag in file."); + int edgeVids[2] = {edge->GetVid(0), edge->GetVid(1)}; - TiXmlElement *interfaceElement = interfaces->FirstChildElement(); + PointGeomSharedPtr newEdgeVerts[2]; + bool create = false; - while(interfaceElement) + for (int k = 0; k < 2; ++k) + { + auto vertIt = vertDone.find(edgeVids[k]); + if (vertIt != vertDone.end()) { - std::string interfaceType = interfaceElement->Value(); - - int err; - int indx; - - err = interfaceElement->QueryIntAttribute("ID", &indx); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); - - std::string interfaceRightDomainStr; - err = interfaceElement->QueryStringAttribute("RIGHTDOMAIN", - &interfaceRightDomainStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read right interface domain."); - auto rightDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); - - std::string interfaceLeftDomainStr; - err = interfaceElement->QueryStringAttribute("LEFTDOMAIN", - &interfaceLeftDomainStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read left interface domain."); - auto leftDomain = m_meshGraph->GetDomain(stoi(ReadTag(interfaceLeftDomainStr))); - - - std::string interfaceEdgeStr; - int interfaceErr = interfaceElement->QueryStringAttribute("INTERFACE", - &interfaceEdgeStr); - map interfaceEdge; - if(interfaceErr == TIXML_SUCCESS) - { - std::string indxStr = ReadTag(interfaceEdgeStr); - m_meshGraph->GetCompositeList(indxStr, interfaceEdge); - } - - std::string leftEdgeStr; - int leftEdgeErr = interfaceElement->QueryStringAttribute("LEFTEDGE", - &leftEdgeStr); - map leftEdge; - if(leftEdgeErr == TIXML_SUCCESS) - { - std::string indxStr = ReadTag(leftEdgeStr); - m_meshGraph->GetCompositeList(indxStr, leftEdge); - } - - std::string rightEdgeStr; - int rightEdgeErr = interfaceElement->QueryStringAttribute("RIGHTEDGE", - &rightEdgeStr); - map rightEdge; - if(rightEdgeErr == TIXML_SUCCESS) - { - std::string indxStr = ReadTag(rightEdgeStr); - m_meshGraph->GetCompositeList(indxStr, rightEdge); - } - - if(interfaceErr == TIXML_SUCCESS) - { - ASSERTL0(leftEdgeErr !=TIXML_SUCCESS && rightEdgeErr !=TIXML_SUCCESS, - "Choose to define either INTERFACE or both LEFTEDGE " - "and RIGHTEDGE.") - } - else if(leftEdgeErr ==TIXML_SUCCESS && rightEdgeErr ==TIXML_SUCCESS) - { - ASSERTL0(interfaceErr !=TIXML_SUCCESS, - "Choose to define either INTERFACE or both LEFTEDGE " - "and RIGHTEDGE.") - } - else - { - ASSERTL0((interfaceErr + 1) * (leftEdgeErr +1) * (rightEdgeErr +1 ) == 1, - "Choose to define either INTERFACE or both LEFTEDGE " - "and RIGHTEDGE.") - } - - if (interfaceType == "R") - { - std::string originStr; - err = interfaceElement->QueryStringAttribute("ORIGIN", - &originStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read origin."); - std::vector originVec; - ParseUtils::GenerateVector(originStr, originVec); - auto origin = PointGeom(3, 0, originVec[0], originVec[1], originVec[2]); - - std::string axisStr; - err = interfaceElement->QueryStringAttribute("AXIS", - &axisStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read axis."); - std::vector axis; - ParseUtils::GenerateVector(axisStr, axis); - - std::string angularVelStr; - err = interfaceElement->QueryStringAttribute("ANGVEL", - &angularVelStr); - ASSERTL0(err == TIXML_SUCCESS, - "Unable to read angular velocity."); - - NekDouble angularVel = stod(angularVelStr); - - InterfaceShPtr rotatingInterface( - MemoryManager::AllocateSharedPtr( - rightDomain, leftDomain, origin, axis, angularVel)); - - if(interfaceErr == TIXML_SUCCESS) - { - rotatingInterface->SetInterfaceEdge(interfaceEdge); - } - else - { - rotatingInterface->SetEdgeRight(rightEdge); - rotatingInterface->SetEdgeLeft(leftEdge); - } - - m_interfaces[indx] = rotatingInterface; - } - - interfaceElement = interfaceElement->NextSiblingElement(); + newEdgeVerts[k] = graph->GetVertex(vertIt->second); + create = true; } + else + newEdgeVerts[k] = graph->GetVertex(edgeVids[k]); + } + + if (create) + { + auto newEdge = MemoryManager::AllocateSharedPtr( + edge->GetGlobalID(), edge->GetVertex(0)->GetCoordim(), + newEdgeVerts, edge->GetCurve()); + graph->GetAllSegGeoms()[edge->GetGlobalID()] = newEdge; + edgeDone[edge->GetGlobalID()] = newEdge; + newEdges[j] = newEdge; + } + else + { + newEdges[j] = edge; + } } - void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) + GeometrySharedPtr newGeom; + if (rightGeom->GetShapeType() == LibUtilities::eQuadrilateral) { + // Create a new quad + QuadGeomSharedPtr quad = + std::static_pointer_cast(rightGeom); + QuadGeomSharedPtr newQuad = + MemoryManager::AllocateSharedPtr( + quad->GetGlobalID(), &newEdges[0], quad->GetCurve()); + graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; + newGeom = newQuad; + } + else if (rightGeom->GetShapeType() == LibUtilities::eTriangle) + { + // Create a new tri + TriGeomSharedPtr tri = std::static_pointer_cast(rightGeom); + TriGeomSharedPtr newTri = MemoryManager::AllocateSharedPtr( + tri->GetGlobalID(), &newEdges[0], tri->GetCurve()); + graph->GetAllTriGeoms()[tri->GetGlobalID()] = newTri; + newGeom = newTri; + } - auto rightDomain = GetRightDomain(); - auto interfaceEdge = GetInterfaceEdge(); - - int maxVertId = -1; - for (auto &vert : graph->GetAllPointGeoms()) + // Replace this geometry in any composites. + for (auto &comp : graph->GetComposites()) + { + for (int n = 0; n < comp.second->m_geomVec.size(); ++n) + { + if (comp.second->m_geomVec[n]->GetGlobalID() == + newGeom->GetGlobalID() && + comp.second->m_geomVec[n]->GetShapeType() == + newGeom->GetShapeType()) { - maxVertId = std::max(maxVertId, vert.first); + comp.second->m_geomVec[n] = newGeom; } + } + } + } +}; - int maxEdgeId = -1; - for (auto &edge : graph->GetAllSegGeoms()) - { - maxEdgeId = std::max(maxEdgeId, edge.first); - } +void InterfaceBase::SetEdgeLeft(const CompositeMap &leftEdge) +{ + for (auto &compIt : leftEdge) + { + for (auto &elmtIt : compIt.second->m_geomVec) + { + SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); + ASSERTL0(elmt, + "Composite for left edge should only contain segments"); + m_leftEdge[elmt->GetGlobalID()] = elmt; + } + } +} - ++maxVertId; - ++maxEdgeId; +void InterfaceBase::SetEdgeRight(const CompositeMap &rightEdge) +{ + for (auto &compIt : rightEdge) + { + for (auto &elmtIt : compIt.second->m_geomVec) + { + SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); + ASSERTL0(elmt, + "Composite for right edge should only contain segments"); + m_rightEdge[elmt->GetGlobalID()] = elmt; + } + } +} - // Map that stores existing renumbered geometry. - std::map vertDone; - std::map edgeDone; - //Map that stores elements to process for renumbered edges and points - std::map elementToDo; +void InterfaceBase::FillInterfaceBoundingBoxTree() +{ + for (auto &x : m_rightEdge) + { + BgBox b = x.second->GetBoundingBox(); + m_boundingInterfaceRight.insert(std::make_pair(b, x.first)); + } + for (auto &x : m_leftEdge) + { + BgBox b = x.second->GetBoundingBox(); + m_boundingInterfaceLeft.insert(std::make_pair(b, x.first)); + } +} - CurveMap &curvedEdges = graph->GetCurvedEdges(); +std::vector InterfaceBase::GetLeftEdgesContainingPoint( + NekDouble x, NekDouble y, NekDouble z) +{ + if (m_boundingInterfaceLeft.empty()) + { + FillInterfaceBoundingBoxTree(); + } - for (auto &comp : interfaceEdge) - { - for (auto &geom : comp.second->m_geomVec) - { - ASSERTL0(geom->GetShapeType() == LibUtilities::eSegment, - "Unexpected geometry type in composite"); - - GeometryLinkSharedPtr elmtLink = graph->GetElementsFromEdge( - std::static_pointer_cast(geom)); - - size_t numElmts = elmtLink->size(); - if (numElmts == 1) - { - continue; - } - - int vid[2] = {geom->GetVid(0), geom->GetVid(1)}; - PointGeomSharedPtr newVerts[2]; - - for (int i = 0; i < 2; ++i) - { - auto it = vertDone.find(vid[i]); - if (it == vertDone.end()) - { - // Create a new vertex - newVerts[i] = MemoryManager::AllocateSharedPtr( - *geom->GetVertex(i)); - newVerts[i]->SetGlobalID(maxVertId); - graph->GetAllPointGeoms()[maxVertId] = newVerts[i]; - vertDone[vid[i]] = maxVertId++; - } - else - { - newVerts[i] = graph->GetVertex( - it->second); - } - } - - SegGeomSharedPtr oldEdge = std::static_pointer_cast( - geom); - - CurveSharedPtr newCurve; - if (oldEdge->GetCurve()) - { - newCurve = MemoryManager::AllocateSharedPtr( - maxEdgeId, - oldEdge->GetCurve()->m_ptype); - - for (auto &pt : oldEdge->GetCurve()->m_points) - { - newCurve->m_points.push_back( - MemoryManager::AllocateSharedPtr( - *pt)); - } - - curvedEdges[maxEdgeId] = newCurve; - } - - auto newEdge = MemoryManager::AllocateSharedPtr( - maxEdgeId, newVerts[0]->GetCoordim(), newVerts, - newCurve); - - graph->GetAllSegGeoms()[maxEdgeId] = newEdge; - edgeDone[geom->GetGlobalID()] = newEdge; - - m_leftEdge[oldEdge->GetGlobalID()] = oldEdge; - m_rightEdge[maxEdgeId] = newEdge; - maxEdgeId++; - - auto toProcess = - GetElementsFromVertex(rightDomain, vid[0], vid[1]); - for (auto &elementToProcess : toProcess) - { - elementToDo[elementToProcess->GetGlobalID()] = elementToProcess; - } - } - } + std::vector vals; + BgBox b(BgPoint(x, y, z), BgPoint(x, y, z)); - for (auto &elementMap : elementToDo) - { - auto rightGeom = elementMap.second; - - std::vector newEdges( - rightGeom->GetNumEdges()); - - // Loop over edges - for (int j = 0; j < newEdges.size(); ++j) - { - auto edge = std::static_pointer_cast( - rightGeom->GetEdge(j)); - auto edgeIt = edgeDone.find(edge->GetGlobalID()); - if (edgeIt != edgeDone.end()) - { - newEdges[j] = edgeIt->second; - continue; - } - - int edgeVids[2] = {edge->GetVid(0), edge->GetVid(1)}; - - PointGeomSharedPtr newEdgeVerts[2]; - bool create = false; - - for (int k = 0; k < 2; ++k) - { - auto vertIt = vertDone.find(edgeVids[k]); - if (vertIt != vertDone.end()) - { - newEdgeVerts[k] = graph->GetVertex( - vertIt->second); - create = true; - } - else - newEdgeVerts[k] = graph->GetVertex( - edgeVids[k]); - } - - if (create) - { - auto newEdge = MemoryManager::AllocateSharedPtr( - edge->GetGlobalID(), - edge->GetVertex(0)->GetCoordim(), - newEdgeVerts, edge->GetCurve()); - graph->GetAllSegGeoms()[edge->GetGlobalID()] = newEdge; - edgeDone[edge->GetGlobalID()] = newEdge; - newEdges[j] = newEdge; - } - else - { - newEdges[j] = edge; - } - } - - GeometrySharedPtr newGeom; - if (rightGeom->GetShapeType() == - LibUtilities::eQuadrilateral) - { - // Create a new quad - QuadGeomSharedPtr quad = std::static_pointer_cast( - rightGeom); - QuadGeomSharedPtr newQuad = MemoryManager::AllocateSharedPtr( - quad->GetGlobalID(), &newEdges[0], - quad->GetCurve()); - graph->GetAllQuadGeoms()[quad->GetGlobalID()] = newQuad; - newGeom = newQuad; - } - else if (rightGeom->GetShapeType() == - LibUtilities::eTriangle) - { - // Create a new tri - TriGeomSharedPtr tri = std::static_pointer_cast( - rightGeom); - TriGeomSharedPtr newTri = MemoryManager::AllocateSharedPtr( - tri->GetGlobalID(), &newEdges[0], - tri->GetCurve()); - graph->GetAllTriGeoms()[tri->GetGlobalID()] = newTri; - newGeom = newTri; - } - - // Replace this geometry in any composites. - for (auto &comp : graph->GetComposites()) - { - for (int n = 0; n < comp.second->m_geomVec.size(); ++n) - { - if (comp.second->m_geomVec[n]->GetGlobalID() == newGeom->GetGlobalID() && - comp.second->m_geomVec[n]->GetShapeType() == newGeom->GetShapeType()) - { - comp.second->m_geomVec[n] = newGeom; - } - } - } - } - }; + m_boundingInterfaceLeft.query(bg::index::intersects(b), + std::back_inserter(vals)); + + return vals; +} + +std::vector InterfaceBase::GetRightEdgesContainingPoint( + NekDouble x, NekDouble y, NekDouble z) +{ + if (m_boundingInterfaceRight.empty()) + { + FillInterfaceBoundingBoxTree(); } + + std::vector vals; + + BgBox b(BgPoint(x, y, z), BgPoint(x, y, z)); + + m_boundingInterfaceRight.query(bg::index::intersects(b), + std::back_inserter(vals)); + + return vals; } +} // namespace SpatialDomains +} // namespace Nektar diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 87eee026a..199a741f9 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -36,201 +36,174 @@ #ifndef NEKTAR_SPATIALDOMAINS_INTERFACES_H #define NEKTAR_SPATIALDOMAINS_INTERFACES_H -#include #include +#include -#include #include +#include #include namespace Nektar { - struct OneD; +struct OneD; + +namespace SpatialDomains +{ +enum InterfaceType +{ + eFixed, + eRotating, + eSliding, +}; + +const char *const InterfaceTypeMap[] = {"Fixed", "Rotating", "Sliding", + "NotDefined"}; + +struct InterfaceBase +{ + InterfaceBase(InterfaceType type, CompositeMap rightDomain, + CompositeMap leftDomain) + : m_interfaceType(type), m_rightDomain(rightDomain), + m_leftDomain(leftDomain) + { + } + + InterfaceType GetInterfaceType() const + { + return m_interfaceType; + } + + CompositeMap GetRightDomain() const + { + return m_rightDomain; + } - namespace SpatialDomains + CompositeMap GetLeftDomain() const { - enum InterfaceType - { - eFixed, - eRotating, - eSliding, - }; - - const char* const InterfaceTypeMap[] = - { - "Fixed", - "Rotating", - "Sliding", - "NotDefined" - }; - - struct InterfaceBase - { - InterfaceBase( - InterfaceType type, - CompositeMap rightDomain, - CompositeMap leftDomain): - m_interfaceType(type), - m_rightDomain(rightDomain), - m_leftDomain(leftDomain) - { - } - - InterfaceType GetInterfaceType() const - { - return m_interfaceType; - } - - CompositeMap GetRightDomain() const - { - return m_rightDomain; - } - - CompositeMap GetLeftDomain() const - { - return m_leftDomain; - } - - CompositeMap GetInterfaceEdge() const - { - return m_interfaceEdge; - } - - void SetInterfaceEdge(const CompositeMap &interfaceEdge) - { - m_interfaceEdge = interfaceEdge; - } - - std::map const &GetEdgeLeft() const - { - return m_leftEdge; - } - - void SetEdgeLeft(const std::map &leftEdge) - { - m_leftEdge = leftEdge; - } - - void SetEdgeLeft(const CompositeMap &leftEdge) - { - for (auto &compIt : leftEdge) - { - for (auto &elmtIt : compIt.second->m_geomVec) - { - SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); - ASSERTL0(elmt, "Composite for left edge should only contain segments"); - m_leftEdge[elmt->GetGlobalID()] = elmt; - } - } - } - - std::map const &GetEdgeRight() const - { - return m_rightEdge; - } - - void SetEdgeRight(const std::map &rightEdge) - { - m_rightEdge = rightEdge; - } - - void SetEdgeRight(const CompositeMap &rightEdge) - { - for (auto &compIt : rightEdge) - { - for (auto &elmtIt : compIt.second->m_geomVec) - { - SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); - ASSERTL0(elmt, "Composite for right edge should only contain segments"); - m_rightEdge[elmt->GetGlobalID()] = elmt; - } - } - } - - void SeparateGraph(MeshGraphSharedPtr &graph); - - protected: - InterfaceType m_interfaceType; - CompositeMap m_rightDomain; - CompositeMap m_leftDomain; - std::map m_leftEdge; - std::map m_rightEdge; - CompositeMap m_interfaceEdge; - - }; - - struct RotatingInterface : public InterfaceBase - { - RotatingInterface( - const CompositeMap rightDomain, - const CompositeMap leftDomain, - const PointGeom origin, - const std::vector axis, - const NekDouble angularVel) - : InterfaceBase(eRotating, rightDomain, leftDomain), - m_origin(origin), - m_axis(axis), - m_angularVel(angularVel) - { - } - - PointGeom GetOrigin() const - { - return m_origin; - } - - std::vector GetAxis() const - { - return m_axis; - } - - NekDouble GetAngularVel() const - { - return m_angularVel; - } - - protected: - PointGeom m_origin; - std::vector m_axis; - NekDouble m_angularVel; - }; - - - typedef std::shared_ptr InterfaceShPtr; - typedef std::shared_ptr RotatingInterfaceShPtr; - typedef std::map InterfaceCollection; - - - - class Interfaces - { - public: - SPATIAL_DOMAINS_EXPORT Interfaces( - const LibUtilities::SessionReaderSharedPtr &pSession, - const MeshGraphSharedPtr &meshGraph); - - SPATIAL_DOMAINS_EXPORT Interfaces() = default; - - const InterfaceCollection &GetInterfaces(void) const - { - return m_interfaces; - } - - - protected: - /// The mesh graph to use for referencing geometry info. - MeshGraphSharedPtr m_meshGraph; - LibUtilities::SessionReaderSharedPtr m_session; - - InterfaceCollection m_interfaces; - private: - - /// Read segments (and general MeshGraph) given TiXmlDocument. - void Read(TiXmlElement *interfaceTag); - void ReadInterfaces(TiXmlElement *interfaceTag); - }; + return m_leftDomain; + } + + CompositeMap GetInterfaceEdge() const + { + return m_interfaceEdge; + } + void SetInterfaceEdge(const CompositeMap &interfaceEdge) + { + m_interfaceEdge = interfaceEdge; + } + + std::map const &GetEdgeLeft() const + { + return m_leftEdge; } -} -#endif //NEKTAR_SPATIALDOMAINS_INTERFACES_H + void SetEdgeLeft(const std::map &leftEdge) + { + m_leftEdge = leftEdge; + } + + void SetEdgeLeft(const CompositeMap &leftEdge); + + std::map const &GetEdgeRight() const + { + return m_rightEdge; + } + + void SetEdgeRight(const std::map &rightEdge) + { + m_rightEdge = rightEdge; + } + + void SetEdgeRight(const CompositeMap &rightEdge); + + void SeparateGraph(MeshGraphSharedPtr &graph); + + void FillInterfaceBoundingBoxTree(); + + std::vector GetLeftEdgesContainingPoint(NekDouble x, + NekDouble y, + NekDouble z); + + std::vector GetRightEdgesContainingPoint(NekDouble x, + NekDouble y, + NekDouble z); + +protected: + InterfaceType m_interfaceType; + CompositeMap m_rightDomain; + CompositeMap m_leftDomain; + std::map m_leftEdge; + std::map m_rightEdge; + CompositeMap m_interfaceEdge; + BgRtree m_boundingInterfaceLeft; + BgRtree m_boundingInterfaceRight; +}; + +struct RotatingInterface : public InterfaceBase +{ + RotatingInterface(const CompositeMap rightDomain, + const CompositeMap leftDomain, const PointGeom origin, + const std::vector axis, + const NekDouble angularVel) + : InterfaceBase(eRotating, rightDomain, leftDomain), m_origin(origin), + m_axis(axis), m_angularVel(angularVel) + { + } + + PointGeom GetOrigin() const + { + return m_origin; + } + + std::vector GetAxis() const + { + return m_axis; + } + + NekDouble GetAngularVel() const + { + return m_angularVel; + } + +protected: + PointGeom m_origin; + std::vector m_axis; + NekDouble m_angularVel; +}; + +typedef std::shared_ptr InterfaceShPtr; +typedef std::shared_ptr RotatingInterfaceShPtr; +typedef std::map InterfaceCollection; + +class Interfaces +{ +public: + SPATIAL_DOMAINS_EXPORT Interfaces( + const LibUtilities::SessionReaderSharedPtr &pSession, + const MeshGraphSharedPtr &meshGraph); + + SPATIAL_DOMAINS_EXPORT Interfaces() = default; + + const InterfaceCollection &GetInterfaces(void) const + { + return m_interfaces; + } + +protected: + /// The mesh graph to use for referencing geometry info. + MeshGraphSharedPtr m_meshGraph; + LibUtilities::SessionReaderSharedPtr m_session; + + InterfaceCollection m_interfaces; + +private: + /// Read segments (and general MeshGraph) given TiXmlDocument. + void Read(TiXmlElement *interfaceTag); + void ReadInterfaces(TiXmlElement *interfaceTag); +}; + +} // namespace SpatialDomains +} // namespace Nektar + +#endif // NEKTAR_SPATIALDOMAINS_INTERFACES_H diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index 77bcb00a3..4531f60ec 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -185,50 +185,49 @@ void MeshGraph::FillGraph() } } -void MeshGraph::FillBoundingBoxTree(int dimension) +void MeshGraph::FillBoundingBoxTree() { - ASSERTL0(dimension<=m_meshDimension, "Unknown dim, must be less than or equal to mesh dimension"); - m_boundingBoxTree[dimension].clear(); - switch (dimension) { + m_boundingBoxTree.clear(); + switch (m_meshDimension) { case 1: for (auto &x : m_segGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } break; case 2: for (auto &x : m_triGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } for (auto &x : m_quadGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } break; case 3: for (auto &x : m_tetGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } for (auto &x : m_prismGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } for (auto &x : m_pyrGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } for (auto &x : m_hexGeoms) { BgBox b = x.second->GetBoundingBox(); - m_boundingBoxTree[dimension].insert(std::make_pair(b, x.first)); + m_boundingBoxTree.insert(std::make_pair(b, x.first)); } break; default: @@ -237,19 +236,19 @@ void MeshGraph::FillBoundingBoxTree(int dimension) } -std::vector MeshGraph::GetRegionsContainingPoint( - NekDouble &x, NekDouble &y, NekDouble &z, int dimension) +std::vector MeshGraph::GetElementsContainingPoint( + NekDouble x, NekDouble y, NekDouble z) { - if (m_boundingBoxTree[dimension].empty()) + if (m_boundingBoxTree.empty()) { - FillBoundingBoxTree(dimension); + FillBoundingBoxTree(); } std::vector vals; BgBox b( BgPoint(x, y, z), BgPoint(x, y, z) ); - m_boundingBoxTree[dimension].query(bg::index::intersects( b ), + m_boundingBoxTree.query(bg::index::intersects( b ), std::back_inserter( vals )); return vals; diff --git a/library/SpatialDomains/MeshGraph.h b/library/SpatialDomains/MeshGraph.h index 8eef346b4..a2b76b29f 100644 --- a/library/SpatialDomains/MeshGraph.h +++ b/library/SpatialDomains/MeshGraph.h @@ -199,11 +199,11 @@ public: /*transfers the minial data structure to full meshgraph*/ SPATIAL_DOMAINS_EXPORT void FillGraph(); - SPATIAL_DOMAINS_EXPORT void FillBoundingBoxTree(int dimension); + SPATIAL_DOMAINS_EXPORT void FillBoundingBoxTree(); - SPATIAL_DOMAINS_EXPORT std::vector GetRegionsContainingPoint( - PointGeomSharedPtr &p, int dimension) + SPATIAL_DOMAINS_EXPORT std::vector GetElementsContainingPoint( + PointGeomSharedPtr p) { NekDouble x = 0.0; NekDouble y = 0.0; @@ -211,11 +211,11 @@ public: p->GetCoords(x, y, z); - return GetRegionsContainingPoint(x, y, z, dimension); + return GetElementsContainingPoint(x, y, z); }; - SPATIAL_DOMAINS_EXPORT std::vector GetRegionsContainingPoint( - NekDouble &x, NekDouble &y, NekDouble &z, int dimension); + SPATIAL_DOMAINS_EXPORT std::vector GetElementsContainingPoint( + NekDouble x, NekDouble y, NekDouble z); //////////////////// //////////////////// @@ -490,7 +490,7 @@ protected: CompositeOrdering m_compOrder; BndRegionOrdering m_bndRegOrder; - std::map m_boundingBoxTree; + BgRtree m_boundingBoxTree; }; typedef std::shared_ptr MeshGraphSharedPtr; typedef LibUtilities::NekFactory MeshGraphFactory; -- GitLab From 237b1785883bd316345ca4a1735332171edd75fb Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Wed, 10 Apr 2019 13:55:37 +0100 Subject: [PATCH 017/408] Removed test file and improved linear FindDistance --- library/Demos/SpatialDomains/CMakeLists.txt | 5 +- .../SpatialDomains/InterfaceDuplicateEdge.cpp | 245 ------------------ .../Demos/SpatialDomains/InterfaceTest.cpp | 66 +---- library/MultiRegions/DisContField2D.cpp | 51 ++-- library/SpatialDomains/SegGeom.cpp | 4 +- 5 files changed, 42 insertions(+), 329 deletions(-) delete mode 100644 library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp diff --git a/library/Demos/SpatialDomains/CMakeLists.txt b/library/Demos/SpatialDomains/CMakeLists.txt index c35f39c67..618ce18c5 100644 --- a/library/Demos/SpatialDomains/CMakeLists.txt +++ b/library/Demos/SpatialDomains/CMakeLists.txt @@ -1,7 +1,4 @@ ADD_NEKTAR_EXECUTABLE(PartitionAnalyse COMPONENT demos DEPENDS SpatialDomains SOURCES PartitionAnalyse.cpp) ADD_NEKTAR_EXECUTABLE(InterfaceTest - COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceTest.cpp) - -ADD_NEKTAR_EXECUTABLE(InterfaceDuplicateEdge - COMPONENT demos DEPENDS MultiRegions SOURCES InterfaceDuplicateEdge.cpp) \ No newline at end of file + COMPONENT demos DEPENDS SpatialDomains SOURCES InterfaceTest.cpp) \ No newline at end of file diff --git a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp b/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp deleted file mode 100644 index 5bc1f5fab..000000000 --- a/library/Demos/SpatialDomains/InterfaceDuplicateEdge.cpp +++ /dev/null @@ -1,245 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace std; -using namespace Nektar; - -double SearchForPoint(NekDouble xs[2], SpatialDomains::SegGeomSharedPtr &seg) -{ - - - - Array xi(1, 0.0); - const NekDouble c1 = 1e-4, c2 = 0.9; - - auto xmap = seg->GetXmap(); - int nq = xmap->GetTotPoints(); - - Array x(nq), y(nq); - xmap->BwdTrans(seg->GetCoeffs(0), x); - xmap->BwdTrans(seg->GetCoeffs(1), y); - - Array xder(nq), yder(nq); - xmap->PhysDeriv(x, xder); - xmap->PhysDeriv(y, yder); - - Array xder2(nq), yder2(nq); - xmap->PhysDeriv(xder, xder2); - xmap->PhysDeriv(yder, yder2); - - bool opt_succeed = false; - - for (int i = 0; i < 1000; ++i) - { - - // Compute f(x_k) and its derivatives - NekDouble xc = xmap->PhysEvaluate(xi, x); - NekDouble yc = xmap->PhysEvaluate(xi, y); - - NekDouble xc_der = xmap->PhysEvaluate(xi, xder); - NekDouble yc_der = xmap->PhysEvaluate(xi, yder); - - NekDouble xc_der2 = xmap->PhysEvaluate(xi, xder2); - NekDouble yc_der2 = xmap->PhysEvaluate(xi, yder2); - - NekDouble fx = (xc - xs[0])*(xc - xs[0]) + (yc - xs[1])*(yc - xs[1]); - NekDouble fxp = 2.0 * (xc_der * (xc - xs[0]) + yc_der * (yc - xs[1])); - NekDouble fxp2 = 2.0 * (xc_der2 * (xc - xs[0]) + xc_der * xc_der + -yc_der2 * (yc - xs[1]) + yc_der * yc_der); - - std::cout <<"Gradient descent iteration = " << i << "\t xi = " << xi[0] -<< "\t fx = " << fx << "\t grad = " << fxp << "\t hess = " << fxp2 << std::endl; - - // Check for convergence - if (fx < 1e-16) - { - opt_succeed = true; - break; - } - - - NekDouble gamma = 1.0; - bool conv = false; - - // Search direction: quasi-Newton - NekDouble pk = - fxp / fxp2; - - int l =0; - // Backtracking line search - while (gamma > 1e-10) - { - cout << "\tLine search iteration: " << l <<"\t gamma = " << gamma << -endl; l++; Array xi_pk(1); xi_pk[0] = xi[0] + pk * gamma; - - if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0) - { - gamma /= 2.0; - continue; - } - - NekDouble xc_pk = xmap->PhysEvaluate(xi_pk, x); - NekDouble yc_pk = xmap->PhysEvaluate(xi_pk, y); - - NekDouble xc_der_pk = xmap->PhysEvaluate(xi_pk, xder); - NekDouble yc_der_pk = xmap->PhysEvaluate(xi_pk, yder); - - NekDouble fx_pk = (xc_pk - xs[0])*(xc_pk - xs[0]) + (yc_pk - -xs[1])*(yc_pk - xs[1]); NekDouble fxp_pk = 2.0 * (xc_der_pk * (xc_pk - xs[0]) + -yc_der_pk * (yc_pk - xs[1])); - - // Check Wolfe conditions - if (fx_pk <= fx + c1 * gamma * pk * fxp && -pk * fxp_pk <= - c2 * pk -* fxp) - { - conv = true; - break; - } - - gamma /= 2.0; - } - - if (!conv) - { - opt_succeed = false; - break; - } - - xi[0] += gamma * pk; - } - - if (opt_succeed) - { - return xi[0]; - } - else - { - return std::numeric_limits::max(); - } -} - -double rand_float( double low, double high ) { - return ((double)rand() * (high - low)) / (double)RAND_MAX + low; -} - - -int main(int argc, char *argv[]) -{ - LibUtilities::SessionReaderSharedPtr session; - LibUtilities::FieldIOSharedPtr fld; - SpatialDomains::MeshGraphSharedPtr graph; - SpatialDomains::Interfaces interfaceCollection; - MultiRegions::DisContField2DSharedPtr field; -// LibUtilities::EquationSharedPtr icond, ex_sol; -// StdRegions::ConstFactorMap factors; - - session = LibUtilities::SessionReader::CreateInstance(argc, argv); - graph = SpatialDomains::MeshGraph::Read(session); - - interfaceCollection = SpatialDomains::Interfaces(session, graph); - auto interfaces = interfaceCollection.GetInterfaces(); - - //Split interfaces - for (auto &interface : interfaces) - { - auto interfaceProperties = interface.second; - interfaceProperties->SeparateGraph(graph); - } - - fld = LibUtilities::FieldIO::CreateDefault(session); - - /* - string sessionName = session->GetSessionName(); - string outFile = sessionName + ".fld"; - unsigned int nSteps = session->GetParameter("NumSteps"); - NekDouble delta_t = session->GetParameter("TimeStep"); - NekDouble epsilon = session->GetParameter("epsilon" ); - */ - - //field = MemoryManager ::AllocateSharedPtr(session, graph, session->GetVariable(0)); - field = MemoryManager ::AllocateSharedPtr(); - // Write geometry - std::string filename = "out.xml"; - graph->WriteGeometry(filename, true); - - // TESTS for SearchForPoint and the MoveDomain function -#if 0 - auto seg = graph->GetSegGeom(4); - seg->FillGeom(); - - std::map foundPoints; - - for (int i = 0; i < 1000; i++) - { - NekDouble random = rand_float(1.0, 0.5); - NekDouble xs[2] = {0.5, random}; - - auto foundPoint = SearchForPoint(xs, seg); - - foundPoints[random] = foundPoint; - } - - std::ofstream myfile; - myfile.open ("example.csv"); - myfile << "Random number, Found point"<< endl; - for (auto i : foundPoints) - { - myfile << i.first <<"," << i.second << endl; - - } - myfile.close(); - - // MOVE DOMAIN - std::set seenVerts, seenEdges; - - for (auto &comp : interfaceProperties->GetMovingDomain()) - { - for (auto &geom : comp.second->m_geomVec) - { - auto newGeom = graph->GetGeometry2D(geom->GetGlobalID()); - for (int i = 0; i < newGeom->GetNumVerts(); ++i) - { - PointGeomSharedPtr vert = newGeom->GetVertex(i); - - if (seenVerts.find(vert->GetGlobalID()) != seenVerts.end()) - { - continue; - } - - (*vert)(1) += 10.0; - seenVerts.insert(vert->GetGlobalID()); - - } - - for (int i = 0; i < newGeom->GetNumEdges(); ++i) - { - SegGeomSharedPtr edge = -std::static_pointer_cast(newGeom->GetEdge(i)); - - // move curve points - if (seenEdges.find(edge->GetGlobalID()) != seenEdges.end()) - { - continue; - } - - CurveSharedPtr curve = edge->GetCurve(); - if (!curve) - { - continue; - } - - for (auto &pt : curve->m_points) - { - (*pt)(1) += 10.0; - } - - seenEdges.insert(edge->GetGlobalID()); - } - } - } - -} -#endif -} diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index 96ebdf9df..4ebd5bc92 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -6,68 +6,26 @@ #include #include #include +#include + using namespace Nektar; using namespace Nektar::SpatialDomains; int main(int argc, char *argv[]) { - LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); - - MeshGraphSharedPtr graph = MeshGraph::Read(session); - Interfaces interfaceCollection = Interfaces(session, graph); - - auto interfaces = interfaceCollection.GetInterfaces(); - - for (auto &interface : interfaces) - { - InterfaceShPtr movingInterface = interface.second; - auto type = movingInterface->GetInterfaceType(); - int indx = interface.first; - - cout << "INTERFACE INDEX: " + std::to_string(indx) << endl; - - cout << "Type: " << InterfaceTypeMap[type] << endl; - - CompositeMap movingDomainComposites = movingInterface->GetMovingDomain(); - for (auto &movingDomainComposite : movingDomainComposites) - { - cout << "Moving domain composite: " << movingDomainComposite.first << endl; - } - - CompositeMap fixedDomainComposites = movingInterface->GetFixedDomain(); - for (auto &fixedDomainComposite : fixedDomainComposites) - { - cout << "Fixed domain composite: " << fixedDomainComposite.first << endl; - } - - InterfaceEdgeMap interfaceEdgeComposites = movingInterface->GetInterfaceEdge(); - std::vector interfaceEdgeCompositeList; - for (auto &interfaceEdgeComposite : interfaceEdgeComposites) - { - interfaceEdgeCompositeList.emplace_back(interfaceEdgeComposite.first); - } - std::string interfaceEdgeString = ParseUtils::GenerateSeqString(interfaceEdgeCompositeList); - cout << "Interface edge composite: " << interfaceEdgeString << endl; - - if(type == eRotating) - { - RotatingInterfaceShPtr movingInterface = static_pointer_cast(interface.second); - - cout << "Angular vel: " << std::to_string(movingInterface->GetAngularVel()) << endl; + PointGeomSharedPtr verts[2]; + verts[0] = MemoryManager::AllocateSharedPtr(2, 0, 3, 2, 0); + verts[1] = MemoryManager::AllocateSharedPtr(2, 0, 3, 3, 0); + SegGeomSharedPtr seg = MemoryManager::AllocateSharedPtr(0, 2, verts); - std::vector origin(3,0); - movingInterface->GetOrigin().GetCoords(origin[0], origin[1], origin[2]); - cout << "Origin: (" << std::to_string(origin[0]) << ", " << std::to_string(origin[1]) << ", "<< std::to_string(origin[2]) << ")" << endl; + Array xs(2); + xs[0] = 3.00000012; + xs[1] = 2.5; - std::vector axis = movingInterface->GetAxis(); - cout << "Axis: (" << std::to_string(axis[0]) << ", " << std::to_string(axis[1]) << ", "<< std::to_string(axis[2]) << ")" << endl << endl; - } + NekDouble foundPoint; + NekDouble dist = seg->FindDistance(xs, foundPoint); - if(type == eFixed) - { - FixedInterfaceShPtr movingInterface = static_pointer_cast(interface.second); - } + cout << "LOCAL POINT: "<< foundPoint << " | DISTANCE FROM SEG: " << dist << endl; - } } \ No newline at end of file diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 4f1da9b60..a899163a2 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1453,45 +1453,48 @@ void DisContField2D::v_GetFwdBwdTracePhys( } // Interpolate from each side of the interface to the other. + // Edge two -> one interpolation for (auto &interface : m_traceEdgeLeft) { - // Edge two -> one interpolation for (auto edges : interface.second) { auto elmt = edges.second; - cout << "BWD EDGE ID: " << edges.first << endl; - int nq = elmt->GetTotPoints(); + int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); for (int i = 0; i < nq; ++i) { NekDouble zero = 0.0; - auto BgRtree = m_interfaces[interface.first]->GetRightEdgesContainingPoint(xc[i], yc[i], zero); - cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; + auto BgRtree = + m_interfaces[interface.first]->GetRightEdgesContainingPoint( + xc[i], yc[i], zero); bool found = false; for (auto boundaryBoxElement : BgRtree) { if (found == false) { - auto geom = m_traceEdgeRight[interface.first][boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = std::static_pointer_cast(geom->GetGeom1D()); + auto geom = m_traceEdgeRight[interface.first] + [boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast( + geom->GetGeom1D()); Array xs(2); xs[0] = xc[i]; xs[1] = yc[i]; NekDouble foundPoint; NekDouble dist = geomSeg->FindDistance(xs, foundPoint); - cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << " | Distance: " << dist; if (dist > 1e-8) { continue; } - Array edgePhys = Bwd + m_trace->GetPhys_Offset(geom->GetElmtId()); + Array edgePhys = + Bwd + m_trace->GetPhys_Offset(geom->GetElmtId()); Array foundPointArray(1, foundPoint); - Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom->StdPhysEvaluate(foundPointArray, edgePhys); + Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = + geom->StdPhysEvaluate(foundPointArray, edgePhys); found = true; - cout << " | BWD SUCCESS" << endl; break; } } @@ -1500,46 +1503,48 @@ void DisContField2D::v_GetFwdBwdTracePhys( } } } - + // Edge one -> two interpolation for (auto &interface : m_traceEdgeRight) { - // Edge one -> two interpolation for (auto edges : interface.second) { auto elmt = edges.second; - cout << "FWD EDGE ID: " << edges.first << endl; - int nq = elmt->GetTotPoints(); + int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); for (int i = 0; i < nq; ++i) { NekDouble zero = 0.0; - auto BgRtree = m_interfaces[interface.first]->GetLeftEdgesContainingPoint(xc[i], yc[i], zero); - cout << "\tGLOBAL POINT: (" << xc[i] << ", " << yc[i] << ")"; + auto BgRtree = + m_interfaces[interface.first]->GetLeftEdgesContainingPoint( + xc[i], yc[i], zero); bool found = false; for (auto boundaryBoxElement : BgRtree) { if (found == false) { - auto geom = m_traceEdgeLeft[interface.first][boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = std::static_pointer_cast(geom->GetGeom1D()); + auto geom = m_traceEdgeLeft[interface.first] + [boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast( + geom->GetGeom1D()); Array xs(2); xs[0] = xc[i]; xs[1] = yc[i]; NekDouble foundPoint; NekDouble dist = geomSeg->FindDistance(xs, foundPoint); - cout << "EDGE " << geomSeg->GetGlobalID() << " | LOCAL FOUND: " << foundPoint << "\t| Distance: " << dist; if (dist > 1e-8) { continue; } - Array edgePhys = Fwd + m_trace->GetPhys_Offset(geom->GetElmtId()); + Array edgePhys = + Fwd + m_trace->GetPhys_Offset(geom->GetElmtId()); Array foundPointArray(1, foundPoint); - Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom->StdPhysEvaluate(foundPointArray, edgePhys); + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = + geom->StdPhysEvaluate(foundPointArray, edgePhys); found = true; - cout << " | FWD SUCCESS" << endl; break; } } diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index c4c86f71d..1ee4f245a 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -412,14 +412,13 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, if (m_geomFactors->GetGtype() == eRegular) { - cout << " | LINEAR "; // Geometry is linear, so use analytic BOOST function to compute distance. std::vector edgeVertexOne(3,0), edgeVertexTwo(3,0); m_verts[0]->GetCoords(edgeVertexOne[0], edgeVertexOne[1], edgeVertexOne[2]); m_verts[1]->GetCoords(edgeVertexTwo[0], edgeVertexTwo[1], edgeVertexTwo[2]); NekDouble xc = (xs[0]-edgeVertexOne[0])/(edgeVertexTwo[0]-edgeVertexOne[0]); NekDouble yc = (xs[1]-edgeVertexOne[1])/(edgeVertexTwo[1]-edgeVertexOne[1]); - xiOut = 2 * (((isnan(xc)) ? 0 : xc) + ((isnan(yc)) ? 0 : yc)) - 1; + xiOut = 2 * (isnan(xc) ? yc : xc) - 1; typedef boost::geometry::model::d2::point_xy point_type; typedef boost::geometry::model::linestring linestring_type; @@ -431,7 +430,6 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, } else if (m_geomFactors->GetGtype() == eDeformed) { - cout << " | NON-LINEAR "; Array xi(1, 0.0); const NekDouble c1 = 1e-4, c2 = 0.9; -- GitLab From 0da604ff7925be2cc18ebc2daf4a4cc377576f7b Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 16 Apr 2019 15:53:54 +0100 Subject: [PATCH 018/408] Bounding box fixes/linear FindDistance improvement --- .gitignore | 3 + .../Demos/SpatialDomains/InterfaceTest.cpp | 9 +-- library/MultiRegions/DisContField2D.cpp | 12 ++-- library/SpatialDomains/Interface.cpp | 18 ++++-- library/SpatialDomains/Interface.h | 3 +- library/SpatialDomains/SegGeom.cpp | 60 +++++++++++++------ 6 files changed, 67 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index fcf15433c..e0231e730 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ ThirdParty # Kdevelop project files *.kdev4 cmake-build-debug +cmake-build-release +cmake-build-minsizerel +cmake-build-relwithdebinfo diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index 4ebd5bc92..4e105d130 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -15,13 +15,14 @@ using namespace Nektar::SpatialDomains; int main(int argc, char *argv[]) { PointGeomSharedPtr verts[2]; - verts[0] = MemoryManager::AllocateSharedPtr(2, 0, 3, 2, 0); + verts[0] = MemoryManager::AllocateSharedPtr(2, 0, 2, 2, 0); verts[1] = MemoryManager::AllocateSharedPtr(2, 0, 3, 3, 0); SegGeomSharedPtr seg = MemoryManager::AllocateSharedPtr(0, 2, verts); - Array xs(2); - xs[0] = 3.00000012; - xs[1] = 2.5; + Array xs(3); + xs[0] = 2; + xs[1] = 3; + xs[2] = 0; NekDouble foundPoint; NekDouble dist = seg->FindDistance(xs, foundPoint); diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index a899163a2..ff2526684 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1268,14 +1268,10 @@ bool DisContField2D::IsLeftAdjacentEdge(const int n, const int e) if (intIt1 != m_interfaceEdgeLeft.end()) { - std::cout << "ELMT " << n << " EDGE " << e << " left adjacent" - << std::endl; fwd = true; } else if (intIt2 != m_interfaceEdgeRight.end()) { - std::cout << "ELMT " << n << " EDGE " << e << " right adjacent" - << std::endl; fwd = false; } else if (pIt != m_periodicEdges.end() && !pIt->second[0].isLocal) @@ -1480,9 +1476,10 @@ void DisContField2D::v_GetFwdBwdTracePhys( std::static_pointer_cast( geom->GetGeom1D()); - Array xs(2); + Array xs(3); xs[0] = xc[i]; xs[1] = yc[i]; + xs[2] = 0; NekDouble foundPoint; NekDouble dist = geomSeg->FindDistance(xs, foundPoint); if (dist > 1e-8) @@ -1503,6 +1500,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( } } } + // Edge one -> two interpolation for (auto &interface : m_traceEdgeRight) { @@ -1512,7 +1510,6 @@ void DisContField2D::v_GetFwdBwdTracePhys( int nq = elmt->GetTotPoints(); Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); - for (int i = 0; i < nq; ++i) { NekDouble zero = 0.0; @@ -1530,9 +1527,10 @@ void DisContField2D::v_GetFwdBwdTracePhys( std::static_pointer_cast( geom->GetGeom1D()); - Array xs(2); + Array xs(3); xs[0] = xc[i]; xs[1] = yc[i]; + xs[2] = 0; NekDouble foundPoint; NekDouble dist = geomSeg->FindDistance(xs, foundPoint); if (dist > 1e-8) diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 9dae22387..0e7ae1238 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -435,15 +435,21 @@ void InterfaceBase::SetEdgeRight(const CompositeMap &rightEdge) void InterfaceBase::FillInterfaceBoundingBoxTree() { - for (auto &x : m_rightEdge) + if (m_boundingInterfaceRight.empty()) { - BgBox b = x.second->GetBoundingBox(); - m_boundingInterfaceRight.insert(std::make_pair(b, x.first)); + for (auto &x : m_rightEdge) + { + BgBox b = x.second->GetBoundingBox(); + m_boundingInterfaceRight.insert(std::make_pair(b, x.first)); + } } - for (auto &x : m_leftEdge) + if (m_boundingInterfaceLeft.empty()) { - BgBox b = x.second->GetBoundingBox(); - m_boundingInterfaceLeft.insert(std::make_pair(b, x.first)); + for (auto &x : m_leftEdge) + { + BgBox b = x.second->GetBoundingBox(); + m_boundingInterfaceLeft.insert(std::make_pair(b, x.first)); + } } } diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 199a741f9..e471d7242 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -56,8 +56,7 @@ enum InterfaceType eSliding, }; -const char *const InterfaceTypeMap[] = {"Fixed", "Rotating", "Sliding", - "NotDefined"}; +const char *const InterfaceTypeMap[] = {"Fixed", "Rotating", "Sliding"}; struct InterfaceBase { diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index 1ee4f245a..f0b3c2fed 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -358,7 +358,7 @@ NekDouble SegGeom::v_GetLocCoords(const Array &coords, { m_xmap->BwdTrans(m_coeffs[i], pts); len += (pts[npts - 1] - pts[0]) * (pts[npts - 1] - pts[0]); - xi += (coords[i] - pts[0]) * (pts[npts-1] - pts[0]); + xi += (coords[i] - pts[0]) * (pts[npts - 1] - pts[0]); } Lcoords[0] = 2 * xi / len - 1.0; @@ -410,23 +410,45 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, { ASSERTL0(m_coordim == 2, "Need to rewrite for m_coordim != 2"); - if (m_geomFactors->GetGtype() == eRegular) + if (true) //m_geomFactors->GetGtype() == eRegular) { - // Geometry is linear, so use analytic BOOST function to compute distance. - std::vector edgeVertexOne(3,0), edgeVertexTwo(3,0); - m_verts[0]->GetCoords(edgeVertexOne[0], edgeVertexOne[1], edgeVertexOne[2]); - m_verts[1]->GetCoords(edgeVertexTwo[0], edgeVertexTwo[1], edgeVertexTwo[2]); - NekDouble xc = (xs[0]-edgeVertexOne[0])/(edgeVertexTwo[0]-edgeVertexOne[0]); - NekDouble yc = (xs[1]-edgeVertexOne[1])/(edgeVertexTwo[1]-edgeVertexOne[1]); - xiOut = 2 * (isnan(xc) ? yc : xc) - 1; - - typedef boost::geometry::model::d2::point_xy point_type; - typedef boost::geometry::model::linestring linestring_type; - point_type p(xs[0],xs[1]); - linestring_type line; - line.push_back(point_type(edgeVertexOne[0],edgeVertexOne[1])); - line.push_back(point_type(edgeVertexTwo[0],edgeVertexTwo[1])); - return boost::geometry::distance(p, line); + std::vector edgeVertexOne(3, 0), edgeVertexTwo(3, 0); + m_verts[0]->GetCoords( + edgeVertexOne[0], edgeVertexOne[1], edgeVertexOne[2]); + m_verts[1]->GetCoords( + edgeVertexTwo[0], edgeVertexTwo[1], edgeVertexTwo[2]); + + NekDouble px = edgeVertexTwo[0] - edgeVertexOne[0]; + NekDouble py = edgeVertexTwo[1] - edgeVertexOne[1]; + NekDouble pz = edgeVertexTwo[2] - edgeVertexOne[2]; + + NekDouble norm = px * px + py * py + pz * pz; + + NekDouble u = + ((xs[0] - edgeVertexOne[0]) * px + + (xs[1] - edgeVertexOne[1]) * py + + (xs[2] - edgeVertexOne[2]) * pz) / norm; + + if (u > 1) + { + u = 1; + } + else if (u < 0) + { + u = 0; + } + + xiOut = 2 * u - 1; // Local coordinate between -1 and 1 + + NekDouble x = edgeVertexOne[0] + u * px; + NekDouble y = edgeVertexOne[1] + u * py; + NekDouble z = edgeVertexOne[2] + u * pz; + + NekDouble dx = x - xs[0]; + NekDouble dy = y - xs[1]; + NekDouble dz = z - xs[2]; + + return sqrt(dx * dx + dy * dy + dz * dz); } else if (m_geomFactors->GetGtype() == eDeformed) { @@ -548,5 +570,5 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, } } -} -} +} // namespace SpatialDomains +} // namespace Nektar -- GitLab From e42c9bd45fa486306965e856b900b9eefe9577e3 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 26 Apr 2019 21:08:09 +0100 Subject: [PATCH 019/408] Changed to use clock_t For time tracking debug --- library/SolverUtils/DriverStandard.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/SolverUtils/DriverStandard.cpp b/library/SolverUtils/DriverStandard.cpp index ffb2ae284..7dbff618b 100644 --- a/library/SolverUtils/DriverStandard.cpp +++ b/library/SolverUtils/DriverStandard.cpp @@ -77,23 +77,23 @@ namespace Nektar void DriverStandard::v_Execute(ostream &out) { - time_t starttime, endtime; + clock_t starttime, endtime; NekDouble CPUtime; m_equ[0]->PrintSummary(out); - time(&starttime); + starttime = clock(); m_equ[0]->DoInitialise(); m_equ[0]->DoSolve(); - time(&endtime); + endtime = clock(); m_equ[0]->Output(); if (m_comm->GetRank() == 0) { - CPUtime = difftime(endtime, starttime); + CPUtime = (endtime - starttime) / NekDouble(CLOCKS_PER_SEC); cout << "-------------------------------------------" << endl; cout << "Total Computation Time = " << CPUtime << "s" << endl; cout << "-------------------------------------------" << endl; -- GitLab From d7e40cc63999dc4394caf2e4c56fabf77f3e7957 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 29 Apr 2019 14:57:32 +0100 Subject: [PATCH 020/408] Debugging Wolfe conditions --- library/MultiRegions/DisContField2D.cpp | 4 ++++ library/SpatialDomains/SegGeom.cpp | 8 ++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index ff2526684..1fe6ab591 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1481,7 +1481,11 @@ void DisContField2D::v_GetFwdBwdTracePhys( xs[1] = yc[i]; xs[2] = 0; NekDouble foundPoint; + std::cout << "Seg ID in: " << geomSeg->GetGlobalID() << endl; + std::cout << "Point coords in: " << xs[0] << ' ' << xs[1] << endl; NekDouble dist = geomSeg->FindDistance(xs, foundPoint); + std::cout << "Dist out: " << dist << endl; + std::cout << "Local coord out: " << foundPoint << endl << endl; if (dist > 1e-8) { continue; diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index f0b3c2fed..e99850dd8 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -410,7 +410,7 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, { ASSERTL0(m_coordim == 2, "Need to rewrite for m_coordim != 2"); - if (true) //m_geomFactors->GetGtype() == eRegular) + if (m_geomFactors->GetGtype() == eRegular) { std::vector edgeVertexOne(3, 0), edgeVertexTwo(3, 0); m_verts[0]->GetCoords( @@ -473,7 +473,9 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, NekDouble fx_prev = std::numeric_limits::max(); - for (int i = 0; i < 15; ++i) + std::cout << "First seg point: " << x[0] <<" " << y[0] << endl; + std::cout << "Last seg point: " << x[6] <<" " << y[6] << endl; + for (int i = 0; i < 100; ++i) { // Compute f(x_k) and its derivatives NekDouble xc = m_xmap->PhysEvaluate(xi, x); @@ -534,6 +536,8 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, yc_der_pk * (yc_pk - xs[1])); // Check Wolfe conditions + cout << "Condition 1: " << fx_pk << " <= " << fx + c1 * gamma * pk * fxp << endl; + cout << "Condition 2: " << -pk * fxp_pk << " <= " << -c2 * pk * fxp << endl; if (fx_pk <= fx + c1 * gamma * pk * fxp && -pk * fxp_pk <= -c2 * pk * fxp) { -- GitLab From ec3cda7bd3586bb3a58abba7fd8c4f2655b39ac4 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 3 May 2019 17:10:54 +0100 Subject: [PATCH 021/408] Semi-working bbox implementation (Wolfe cond fail) --- library/MultiRegions/DisContField2D.cpp | 4 - library/SpatialDomains/Geometry.cpp | 201 +++++++++++++++++++++--- library/SpatialDomains/Geometry.h | 2 + library/SpatialDomains/Interface.cpp | 61 ++++++- library/SpatialDomains/SegGeom.cpp | 12 +- 5 files changed, 248 insertions(+), 32 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 1fe6ab591..ff2526684 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1481,11 +1481,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( xs[1] = yc[i]; xs[2] = 0; NekDouble foundPoint; - std::cout << "Seg ID in: " << geomSeg->GetGlobalID() << endl; - std::cout << "Point coords in: " << xs[0] << ' ' << xs[1] << endl; NekDouble dist = geomSeg->FindDistance(xs, foundPoint); - std::cout << "Dist out: " << dist << endl; - std::cout << "Local coord out: " << foundPoint << endl << endl; if (dist > 1e-8) { continue; diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index 6600a8e6e..55eee5292 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -51,8 +51,9 @@ GeomFactorsVector Geometry::m_regGeomFactorsManager; * @brief Default constructor. */ Geometry::Geometry() - : m_coordim(0), m_geomFactorsState(eNotFilled), m_state(eNotFilled), m_setupState(false), - m_shapeType(LibUtilities::eNoShapeType), m_globalID(-1) + : m_coordim(0), m_geomFactorsState(eNotFilled), m_state(eNotFilled), + m_setupState(false), m_shapeType(LibUtilities::eNoShapeType), + m_globalID(-1) { } @@ -60,8 +61,9 @@ Geometry::Geometry() * @brief Constructor when supplied a coordinate dimension. */ Geometry::Geometry(const int coordim) - : m_coordim(coordim), m_geomFactorsState(eNotFilled), m_state(eNotFilled), m_setupState(false), - m_shapeType(LibUtilities::eNoShapeType), m_globalID(-1) + : m_coordim(coordim), m_geomFactorsState(eNotFilled), m_state(eNotFilled), + m_setupState(false), m_shapeType(LibUtilities::eNoShapeType), + m_globalID(-1) { } @@ -248,8 +250,7 @@ StdRegions::StdExpansionSharedPtr Geometry::v_GetXmap() const * NekDouble, NekDouble&) */ bool Geometry::v_ContainsPoint(const Array &gloCoord, - Array &locCoord, - NekDouble tol, + Array &locCoord, NekDouble tol, NekDouble &resid) { NEKERROR(ErrorUtil::efatal, @@ -332,7 +333,7 @@ void Geometry::v_FillGeom() void Geometry::v_Reset(CurveMap &curvedEdges, CurveMap &curvedFaces) { // Reset state - m_state = eNotFilled; + m_state = eNotFilled; m_geomFactorsState = eNotFilled; // Junk geometric factors @@ -345,7 +346,6 @@ void Geometry::v_Setup() "This function is only valid for expansion type geometries"); } - /** * @brief Generates the bounding box for the element. * @@ -357,14 +357,16 @@ void Geometry::v_Setup() */ void Geometry::GenBoundingBox() { - //NekDouble minx, miny, minz, maxx, maxy, maxz; + // NekDouble minx, miny, minz, maxx, maxy, maxz; Array min(3), max(3); - if (GetGeomFactors()->GetGtype() == eRegular) { + if (GetGeomFactors()->GetGtype() == eRegular) + { PointGeomSharedPtr p = GetVertex(0); Array x(3, 0.0); p->GetCoords(x[0], x[1], x[2]); - for (int j = 0; j < 3; ++j) { + for (int j = 0; j < 3; ++j) + { min[j] = x[j] - NekConstants::kGeomFactorsTol; max[j] = x[j] + NekConstants::kGeomFactorsTol; } @@ -372,26 +374,32 @@ void Geometry::GenBoundingBox() { p = GetVertex(i); p->GetCoords(x[0], x[1], x[2]); - for (int j = 0; j < 3; ++j) { + for (int j = 0; j < 3; ++j) + { min[j] = (x[j] < min[j] ? x[j] : min[j]); max[j] = (x[j] > max[j] ? x[j] : max[j]); } } } - else { + else + { const int nq = GetXmap()->GetTotPoints(); Array> x(3); - for (int j = 0; j < 3; ++j) { + for (int j = 0; j < 3; ++j) + { x[j] = Array(nq, 0.0); } - for (int j = 0; j < GetCoordim(); ++j) { + for (int j = 0; j < GetCoordim(); ++j) + { GetXmap()->BwdTrans(m_coeffs[j], x[j]); } - for (int j = 0; j < 3; ++j) { + for (int j = 0; j < 3; ++j) + { min[j] = x[j][0] - NekConstants::kGeomFactorsTol; max[j] = x[j][0] + NekConstants::kGeomFactorsTol; - for (int i = 1; i < nq; ++i) { + for (int i = 1; i < nq; ++i) + { min[j] = (x[j][i] < min[j] ? x[j][i] : min[j]); max[j] = (x[j][i] > max[j] ? x[j][i] : max[j]); } @@ -399,16 +407,169 @@ void Geometry::GenBoundingBox() // Add 10% margin to bounding box in case elements have // convex boundaries. const int len = max[j] - min[j]; - max[j] += 0.1*len; - min[j] -= 0.1*len; + max[j] += 0.1 * len; + min[j] -= 0.1 * len; + } + + for (int j = 0; j < GetCoordim(); ++j) + { + //cout << "Dimension: " << j << " | Estimate min coord:" << min[j] << endl; + //cout << "Dimension: " << j << "| Estimate max coord: " << max[j] << endl; + + min[j] = FindMinCoord(j, min[j]); + //max[j] = FindMinCoord(j, max[j]); + + //cout << "Dimension: " << j << " | Real min coord:" << min[j] << endl << endl; + //cout << "Dimension: " << j << "| Real max coord: " << max[j] << endl; } } + BgPoint pmin(min[0], min[1], min[2]); BgPoint pmax(max[0], max[1], max[2]); m_boundingBox = BgBox(pmin, pmax); } +NekDouble Geometry::FindMinCoord(int coordDir, NekDouble xcEst) +{ + Array xi(1, 0.5); + const NekDouble c1 = 1e-4, c2 = 0.9; + const int nq = GetXmap()->GetTotPoints(); + Array x(nq); + m_xmap->BwdTrans(m_coeffs[coordDir], x); + + Array xder(nq, 0.0), yder(nq, 0.0); + m_xmap->PhysDeriv(x, xder);//, yder); + + Array xder2(nq, 0.0), xdery(nq, 0.0); + Array yder2(nq, 0.0), yderx(nq, 0.0); + m_xmap->PhysDeriv(xder, xder2);//, xdery); + //m_xmap->PhysDeriv(yder, yderx, yder2); + + // cout << "Shape type: " << LibUtilities::ShapeTypeMap[m_shapeType] << endl; + // cout << "Shape dim: " << GetShapeDim() << endl; + // cout << "xder: " << xder[0] << endl; + // cout << "yder: " << yder[0] << endl; + // cout << "xder2: " << xder2[0] << endl; + // cout << "xdery: " << xdery[0] << endl; + // cout << "yderx: " << yderx[0] << endl; + // cout << "yder2: " << yder2[0] << endl; + + bool opt_succeed = false; + + NekDouble xc_prev = std::numeric_limits::max(); + + for (int i = 0; i < 100; ++i) + { + + // Compute f(x_k) and its derivatives + NekDouble xc = m_xmap->PhysEvaluate(xi, x); + NekDouble xc_derx = m_xmap->PhysEvaluate(xi, xder); + //NekDouble xc_dery = m_xmap->PhysEvaluate(xi, yder); + NekDouble xc_derxx = m_xmap->PhysEvaluate(xi, xder2); + //NekDouble xc_derxy = m_xmap->PhysEvaluate(xi, xdery); + //NekDouble xc_deryx = m_xmap->PhysEvaluate(xi, yderx); + //NekDouble xc_deryy = m_xmap->PhysEvaluate(xi, yder2); + + cout << "Iteration: " << i << "| xc: " << xc << endl; + // cout << "xc_derx: " << xc_derx << endl; + // cout << "xc_dery: " << xc_dery << endl; + // cout << "xc_derxx: " << xc_derxx << endl; + // cout << "xc_deryy: " << xc_derxy << endl; + // cout << "xc_deryx: " << xc_deryx << endl; + // cout << "xc_deryy: " << xc_deryy << endl; + + // Check for convergence + if (abs(xc - xc_prev) < 1e-16) + { + opt_succeed = true; + xc_prev = xc; + break; + } + else + { + xc_prev = xc; + } + + NekDouble gamma = 1.0; + bool conv = false; + + // Search direction: quasi-Newton, H^{-1}f . \nabla f + NekDouble pk[1]; + NekDouble det; + if (GetShapeDim() == 1) + { + pk[0] = -xc_derx / xc_derxx; + //pk[1] = 0; + } + /* + else if (GetShapeDim() == 2) + { + det = xc_derxx * xc_deryy - xc_derxy * xc_deryx; + pk[0] = (1 / det) * (xc_deryy * xc_derx - xc_derxy * xc_dery); + pk[1] = (1 / det) * (xc_derxx * xc_dery - xc_deryx * xc_derx); + } + else + { + ASSERTL0(false, "Shape dimension is not supported") + } + */ + + // Backtracking line search + while (gamma > 1e-10) + { + Array xi_pk(1); + xi_pk[0] = xi[0] + pk[0] * gamma; + //xi_pk[1] = xi[1] + pk[1] * gamma; + + if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0)// || xi_pk[1] < -1.0 || + //xi_pk[1] > 1.0) + { + gamma /= 2.0; + continue; + } + + NekDouble xc_pk = m_xmap->PhysEvaluate(xi_pk, x); + NekDouble xc_pk_derx = m_xmap->PhysEvaluate(xi_pk, xder); + //NekDouble xc_pk_dery = m_xmap->PhysEvaluate(xi_pk, yder); + + // Check Wolfe conditions + //cout << "Condition 1: " << (xc_pk - (xc + c1 * gamma * pk[0] * xc_derx)) << endl; + //cout << "Condition 2: " << (-pk[0] * xc_pk_derx + c2 * pk[0] * xc_derx) << endl; + //if ((xc_pk - (xc + c1 * gamma * (pk[0] * xc_derx + pk[1] * xc_dery)) < std::numeric_limits::epsilon()) && + // (-(pk[0] * xc_pk_derx + pk[1] * xc_pk_dery) + c2 * (pk[0] * xc_derx + pk[1] * xc_dery) < std::numeric_limits::epsilon())) + if ((xc_pk - (xc + c1 * gamma * pk[0] * xc_derx) < std::numeric_limits::epsilon()) && + (-pk[0] * xc_pk_derx + c2 * pk[0] * xc_derx) < std::numeric_limits::epsilon()) + { + conv = true; + break; + } + + gamma /= 2.0; + } + + if (!conv) + { + opt_succeed = false; + break; + } + + xi[0] += gamma * pk[0]; + //xi[1] += gamma * pk[1]; + } + + if (opt_succeed) + { + std::cout << " success " << xc_prev << std::endl; + return xc_prev; + } + else + { + std::cout << "failed " << std::endl; + return std::numeric_limits::max(); + } } -} + +} // namespace SpatialDomains +} // namespace Nektar diff --git a/library/SpatialDomains/Geometry.h b/library/SpatialDomains/Geometry.h index f0bfaf66d..d617a707b 100644 --- a/library/SpatialDomains/Geometry.h +++ b/library/SpatialDomains/Geometry.h @@ -212,6 +212,8 @@ protected: /// Generates the bounding box of the element. void GenBoundingBox(); + NekDouble FindMinCoord(int, NekDouble); + //--------------------------------------- // Helper functions //--------------------------------------- diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 0e7ae1238..c6a6df58b 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -48,7 +48,15 @@ Interfaces::Interfaces(const LibUtilities::SessionReaderSharedPtr &pSession, const MeshGraphSharedPtr &meshGraph) : m_meshGraph(meshGraph), m_session(pSession) { - ReadInterfaces(m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); + TiXmlElement *xmlDoc = m_session->GetElement("NEKTAR"); + if(xmlDoc->FirstChild("CONDITIONS") != nullptr) + { + if(xmlDoc->FirstChild("CONDITIONS")->FirstChild("INTERFACES") != nullptr) + { + ReadInterfaces( + m_session->GetElement("NEKTAR/CONDITIONS/INTERFACES")); + } + } } std::string ReadTag(std::string &tagStr) @@ -402,6 +410,57 @@ void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) } } } + + //Offset right domain for visualisation +#if 0 + std::set seenVerts, seenEdges; + for (auto &comp : GetRightDomain()) + { + for (auto &geom : comp.second->m_geomVec) + { + auto newGeom = graph->GetGeometry2D(geom->GetGlobalID()); + for (int i = 0; i < newGeom->GetNumVerts(); ++i) + { + PointGeomSharedPtr vert = newGeom->GetVertex(i); + + if (seenVerts.find(vert->GetGlobalID()) != seenVerts.end()) + { + continue; + } + + (*vert)(1) += 0.5; + seenVerts.insert(vert->GetGlobalID()); + + } + + for (int i = 0; i < newGeom->GetNumEdges(); ++i) + { + SegGeomSharedPtr edge = + std::static_pointer_cast(newGeom->GetEdge(i)); + + // move curve points + if (seenEdges.find(edge->GetGlobalID()) != seenEdges.end()) + { + continue; + } + + CurveSharedPtr curve = edge->GetCurve(); + if (!curve) + { + continue; + } + + for (auto &pt : curve->m_points) + { + (*pt)(1) += 0.5; + } + + seenEdges.insert(edge->GetGlobalID()); + } + } + } +#endif + } }; diff --git a/library/SpatialDomains/SegGeom.cpp b/library/SpatialDomains/SegGeom.cpp index e99850dd8..7ca386586 100644 --- a/library/SpatialDomains/SegGeom.cpp +++ b/library/SpatialDomains/SegGeom.cpp @@ -473,8 +473,6 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, NekDouble fx_prev = std::numeric_limits::max(); - std::cout << "First seg point: " << x[0] <<" " << y[0] << endl; - std::cout << "Last seg point: " << x[6] <<" " << y[6] << endl; for (int i = 0; i < 100; ++i) { // Compute f(x_k) and its derivatives @@ -509,7 +507,7 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, NekDouble gamma = 1.0; bool conv = false; - // Search direction: quasi-Newton + // Search direction: Newton's method NekDouble pk = -fxp / fxp2; // Backtracking line search @@ -536,10 +534,10 @@ NekDouble SegGeom::v_FindDistance(const Array &xs, yc_der_pk * (yc_pk - xs[1])); // Check Wolfe conditions - cout << "Condition 1: " << fx_pk << " <= " << fx + c1 * gamma * pk * fxp << endl; - cout << "Condition 2: " << -pk * fxp_pk << " <= " << -c2 * pk * fxp << endl; - if (fx_pk <= fx + c1 * gamma * pk * fxp && - -pk * fxp_pk <= -c2 * pk * fxp) + //cout << "Condition 1: " << fx_pk << " <= " << fx + c1 * gamma * pk * fxp << endl; + //cout << "Condition 2: " << -pk * fxp_pk << " <= " << -c2 * pk * fxp << endl; + if ((fx_pk - (fx + c1 * gamma * pk * fxp)) < std::numeric_limits::epsilon() && + (-pk * fxp_pk + c2 * pk * fxp) < std::numeric_limits::epsilon()) { conv = true; break; -- GitLab From a8bc15474f85ef3d1801a571319f7e0c10f8d3c5 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Sat, 4 May 2019 10:43:51 +0100 Subject: [PATCH 022/408] Newtons method start in BBox setup --- library/SpatialDomains/Geometry.cpp | 144 +++++----------------------- 1 file changed, 22 insertions(+), 122 deletions(-) diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index 55eee5292..b8e012957 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -431,143 +431,43 @@ void Geometry::GenBoundingBox() NekDouble Geometry::FindMinCoord(int coordDir, NekDouble xcEst) { - Array xi(1, 0.5); - const NekDouble c1 = 1e-4, c2 = 0.9; - - const int nq = GetXmap()->GetTotPoints(); - - Array x(nq); + const int nq = m_xmap->GetTotPoints(); + Array x(nq, 0.0), xder(nq, 0.0); m_xmap->BwdTrans(m_coeffs[coordDir], x); + m_xmap->PhysDeriv(x, xder); + std::vector roots; - Array xder(nq, 0.0), yder(nq, 0.0); - m_xmap->PhysDeriv(x, xder);//, yder); - - Array xder2(nq, 0.0), xdery(nq, 0.0); - Array yder2(nq, 0.0), yderx(nq, 0.0); - m_xmap->PhysDeriv(xder, xder2);//, xdery); - //m_xmap->PhysDeriv(yder, yderx, yder2); - - // cout << "Shape type: " << LibUtilities::ShapeTypeMap[m_shapeType] << endl; - // cout << "Shape dim: " << GetShapeDim() << endl; - // cout << "xder: " << xder[0] << endl; - // cout << "yder: " << yder[0] << endl; - // cout << "xder2: " << xder2[0] << endl; - // cout << "xdery: " << xdery[0] << endl; - // cout << "yderx: " << yderx[0] << endl; - // cout << "yder2: " << yder2[0] << endl; - - bool opt_succeed = false; - - NekDouble xc_prev = std::numeric_limits::max(); - - for (int i = 0; i < 100; ++i) + const int n = 10; + Array points(n+1, 0.0); + for (int i = 0; i < n+1; ++i) { + points[i] = i * (2.0 / n) - 1.0; - // Compute f(x_k) and its derivatives - NekDouble xc = m_xmap->PhysEvaluate(xi, x); - NekDouble xc_derx = m_xmap->PhysEvaluate(xi, xder); - //NekDouble xc_dery = m_xmap->PhysEvaluate(xi, yder); - NekDouble xc_derxx = m_xmap->PhysEvaluate(xi, xder2); - //NekDouble xc_derxy = m_xmap->PhysEvaluate(xi, xdery); - //NekDouble xc_deryx = m_xmap->PhysEvaluate(xi, yderx); - //NekDouble xc_deryy = m_xmap->PhysEvaluate(xi, yder2); - - cout << "Iteration: " << i << "| xc: " << xc << endl; - // cout << "xc_derx: " << xc_derx << endl; - // cout << "xc_dery: " << xc_dery << endl; - // cout << "xc_derxx: " << xc_derxx << endl; - // cout << "xc_deryy: " << xc_derxy << endl; - // cout << "xc_deryx: " << xc_deryx << endl; - // cout << "xc_deryy: " << xc_deryy << endl; - - // Check for convergence - if (abs(xc - xc_prev) < 1e-16) - { - opt_succeed = true; - xc_prev = xc; - break; - } - else - { - xc_prev = xc; - } - - NekDouble gamma = 1.0; - bool conv = false; - - // Search direction: quasi-Newton, H^{-1}f . \nabla f - NekDouble pk[1]; - NekDouble det; - if (GetShapeDim() == 1) - { - pk[0] = -xc_derx / xc_derxx; - //pk[1] = 0; - } - /* - else if (GetShapeDim() == 2) - { - det = xc_derxx * xc_deryy - xc_derxy * xc_deryx; - pk[0] = (1 / det) * (xc_deryy * xc_derx - xc_derxy * xc_dery); - pk[1] = (1 / det) * (xc_derxx * xc_dery - xc_deryx * xc_derx); - } - else - { - ASSERTL0(false, "Shape dimension is not supported") - } - */ - - // Backtracking line search - while (gamma > 1e-10) + Array xi(1, points[i]); + NekDouble xi_prev = xi[0]; + bool conv; + cout << "LOCAL COORD IN: " << points[i] << endl; + for (int j = 0; j < 15; ++j) { - Array xi_pk(1); - xi_pk[0] = xi[0] + pk[0] * gamma; - //xi_pk[1] = xi[1] + pk[1] * gamma; - - if (xi_pk[0] < -1.0 || xi_pk[0] > 1.0)// || xi_pk[1] < -1.0 || - //xi_pk[1] > 1.0) - { - gamma /= 2.0; - continue; - } + NekDouble xc = m_xmap->PhysEvaluate(xi, x); + NekDouble xc_derx = m_xmap->PhysEvaluate(xi, xder); - NekDouble xc_pk = m_xmap->PhysEvaluate(xi_pk, x); - NekDouble xc_pk_derx = m_xmap->PhysEvaluate(xi_pk, xder); - //NekDouble xc_pk_dery = m_xmap->PhysEvaluate(xi_pk, yder); - - // Check Wolfe conditions - //cout << "Condition 1: " << (xc_pk - (xc + c1 * gamma * pk[0] * xc_derx)) << endl; - //cout << "Condition 2: " << (-pk[0] * xc_pk_derx + c2 * pk[0] * xc_derx) << endl; - //if ((xc_pk - (xc + c1 * gamma * (pk[0] * xc_derx + pk[1] * xc_dery)) < std::numeric_limits::epsilon()) && - // (-(pk[0] * xc_pk_derx + pk[1] * xc_pk_dery) + c2 * (pk[0] * xc_derx + pk[1] * xc_dery) < std::numeric_limits::epsilon())) - if ((xc_pk - (xc + c1 * gamma * pk[0] * xc_derx) < std::numeric_limits::epsilon()) && - (-pk[0] * xc_pk_derx + c2 * pk[0] * xc_derx) < std::numeric_limits::epsilon()) + xi[0] = xi_prev - xc / xc_derx; + cout << "ITERATION: " << j << " | xc = " << xc << " | xc_derx = " << xc_derx << " | xi_prev = " << xi_prev << " | xi[0] = " << xi[0] << endl; + if (abs(xi[0] - xi_prev) < 1e-16) { + cout << "CONVERGED AT LOCAL COORDINATE = " << xi[0] << endl; conv = true; break; } - gamma /= 2.0; + xi_prev = xi[0]; } - if (!conv) + if (xi[0] >= -1 && xi[0] <= 1 && conv == true) { - opt_succeed = false; - break; + roots.emplace_back(xi[0]); } - - xi[0] += gamma * pk[0]; - //xi[1] += gamma * pk[1]; - } - - if (opt_succeed) - { - std::cout << " success " << xc_prev << std::endl; - return xc_prev; - } - else - { - std::cout << "failed " << std::endl; - return std::numeric_limits::max(); } } -- GitLab From d5cab7aefbbf5e51aea565c7998044cf8af06dc3 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Sun, 5 May 2019 18:21:42 +0100 Subject: [PATCH 023/408] Finished BBox newtons method --- library/SpatialDomains/Geometry.cpp | 81 +++++++++-------------------- library/SpatialDomains/Geometry.h | 2 +- 2 files changed, 27 insertions(+), 56 deletions(-) diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index b8e012957..b408d6d4f 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -383,44 +383,11 @@ void Geometry::GenBoundingBox() } else { - const int nq = GetXmap()->GetTotPoints(); - Array> x(3); - for (int j = 0; j < 3; ++j) - { - x[j] = Array(nq, 0.0); - } for (int j = 0; j < GetCoordim(); ++j) { - GetXmap()->BwdTrans(m_coeffs[j], x[j]); - } - for (int j = 0; j < 3; ++j) - { - min[j] = x[j][0] - NekConstants::kGeomFactorsTol; - max[j] = x[j][0] + NekConstants::kGeomFactorsTol; - - for (int i = 1; i < nq; ++i) - { - min[j] = (x[j][i] < min[j] ? x[j][i] : min[j]); - max[j] = (x[j][i] > max[j] ? x[j][i] : max[j]); - } - - // Add 10% margin to bounding box in case elements have - // convex boundaries. - const int len = max[j] - min[j]; - max[j] += 0.1 * len; - min[j] -= 0.1 * len; - } - - for (int j = 0; j < GetCoordim(); ++j) - { - //cout << "Dimension: " << j << " | Estimate min coord:" << min[j] << endl; - //cout << "Dimension: " << j << "| Estimate max coord: " << max[j] << endl; - - min[j] = FindMinCoord(j, min[j]); - //max[j] = FindMinCoord(j, max[j]); - - //cout << "Dimension: " << j << " | Real min coord:" << min[j] << endl << endl; - //cout << "Dimension: " << j << "| Real max coord: " << max[j] << endl; + auto minMax = FindMinMaxCoord(j); + min[j] = minMax.first; + max[j] = minMax.second; } } @@ -429,46 +396,50 @@ void Geometry::GenBoundingBox() m_boundingBox = BgBox(pmin, pmax); } -NekDouble Geometry::FindMinCoord(int coordDir, NekDouble xcEst) +std::pair Geometry::FindMinMaxCoord(int coordDir) { const int nq = m_xmap->GetTotPoints(); - Array x(nq, 0.0), xder(nq, 0.0); - m_xmap->BwdTrans(m_coeffs[coordDir], x); - m_xmap->PhysDeriv(x, xder); - std::vector roots; + Array x(nq, 0.0), xder(nq, 0.0), xder2(nq, 0.0); + std::unordered_set values; const int n = 10; Array points(n+1, 0.0); + + m_xmap->BwdTrans(m_coeffs[coordDir], x); + m_xmap->PhysDeriv(x, xder); + m_xmap->PhysDeriv(xder, xder2); + for (int i = 0; i < n+1; ++i) { points[i] = i * (2.0 / n) - 1.0; - Array xi(1, points[i]); NekDouble xi_prev = xi[0]; - bool conv; - cout << "LOCAL COORD IN: " << points[i] << endl; - for (int j = 0; j < 15; ++j) + + for (int j = 0; j < 20; ++j) { NekDouble xc = m_xmap->PhysEvaluate(xi, x); NekDouble xc_derx = m_xmap->PhysEvaluate(xi, xder); + NekDouble xc_derxx = m_xmap->PhysEvaluate(xi, xder2); + + xi[0] = xi_prev - xc_derx / xc_derxx; - xi[0] = xi_prev - xc / xc_derx; - cout << "ITERATION: " << j << " | xc = " << xc << " | xc_derx = " << xc_derx << " | xi_prev = " << xi_prev << " | xi[0] = " << xi[0] << endl; - if (abs(xi[0] - xi_prev) < 1e-16) + if ((abs(xi[0] - xi_prev) < 1e-16) && (xi[0] >= -1) && (xi[0] <= 1)) { - cout << "CONVERGED AT LOCAL COORDINATE = " << xi[0] << endl; - conv = true; + values.insert(xc); break; } xi_prev = xi[0]; } - - if (xi[0] >= -1 && xi[0] <= 1 && conv == true) - { - roots.emplace_back(xi[0]); - } } + + const Array minusOne(1, -1); + const Array plusOne(1, 1); + values.insert(m_xmap->PhysEvaluate(minusOne, x)); + values.insert(m_xmap->PhysEvaluate(plusOne, x)); + + const auto res = std::minmax_element(std::begin(values), std::end(values)); + return std::make_pair(*res.first, *res.second); } } // namespace SpatialDomains diff --git a/library/SpatialDomains/Geometry.h b/library/SpatialDomains/Geometry.h index d617a707b..91140067b 100644 --- a/library/SpatialDomains/Geometry.h +++ b/library/SpatialDomains/Geometry.h @@ -212,7 +212,7 @@ protected: /// Generates the bounding box of the element. void GenBoundingBox(); - NekDouble FindMinCoord(int, NekDouble); + std::pair FindMinMaxCoord(int); //--------------------------------------- // Helper functions -- GitLab From e5e9e6256287c513504edbfadb90622e3785f36e Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 7 May 2019 16:41:32 +0100 Subject: [PATCH 024/408] Loop over each edge in 2D bbox calc --- .../Demos/SpatialDomains/InterfaceTest.cpp | 23 +++---- library/SpatialDomains/Geometry.cpp | 65 ++++++++++--------- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index 4e105d130..ef140b478 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -14,19 +14,20 @@ using namespace Nektar::SpatialDomains; int main(int argc, char *argv[]) { - PointGeomSharedPtr verts[2]; - verts[0] = MemoryManager::AllocateSharedPtr(2, 0, 2, 2, 0); - verts[1] = MemoryManager::AllocateSharedPtr(2, 0, 3, 3, 0); - SegGeomSharedPtr seg = MemoryManager::AllocateSharedPtr(0, 2, verts); + LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); + MeshGraphSharedPtr graph = MeshGraph::Read(session); - Array xs(3); - xs[0] = 2; - xs[1] = 3; - xs[2] = 0; + auto bbox = graph->GetAllQuadGeoms()[0]->GetBoundingBox(); - NekDouble foundPoint; - NekDouble dist = seg->FindDistance(xs, foundPoint); + Array min(2), max(2); - cout << "LOCAL POINT: "<< foundPoint << " | DISTANCE FROM SEG: " << dist << endl; + min[0] = boost::geometry::get(bbox); + min[1] = boost::geometry::get(bbox); + + max[0] = boost::geometry::get(bbox); + max[1] = boost::geometry::get(bbox); + + cout << "MINIMUM CORNER IS: (" << min[0] << ", " << min[1] << ")" << endl; + cout << "MAXIMUM CORNER IS: (" << max[0] << ", " << max[1] << ")" << endl; } \ No newline at end of file diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index b408d6d4f..3beee672e 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -398,47 +398,54 @@ void Geometry::GenBoundingBox() std::pair Geometry::FindMinMaxCoord(int coordDir) { - const int nq = m_xmap->GetTotPoints(); - Array x(nq, 0.0), xder(nq, 0.0), xder2(nq, 0.0); std::unordered_set values; - const int n = 10; - Array points(n+1, 0.0); + for (int edgeID = 0; edgeID < GetNumEdges(); ++edgeID) + { + auto edge = GetEdge(edgeID); + const int nq = edge->GetXmap()->GetTotPoints(); + Array x(nq, 0.0), xder(nq, 0.0), xder2(nq, 0.0); - m_xmap->BwdTrans(m_coeffs[coordDir], x); - m_xmap->PhysDeriv(x, xder); - m_xmap->PhysDeriv(xder, xder2); + const int n = 3; + Array points(n + 1, 0.0); - for (int i = 0; i < n+1; ++i) - { - points[i] = i * (2.0 / n) - 1.0; - Array xi(1, points[i]); - NekDouble xi_prev = xi[0]; + edge->GetXmap()->BwdTrans(edge->GetCoeffs(coordDir), x); + edge->GetXmap()->PhysDeriv(x, xder); + edge->GetXmap()->PhysDeriv(xder, xder2); - for (int j = 0; j < 20; ++j) + for (int i = 0; i < n + 1; ++i) { - NekDouble xc = m_xmap->PhysEvaluate(xi, x); - NekDouble xc_derx = m_xmap->PhysEvaluate(xi, xder); - NekDouble xc_derxx = m_xmap->PhysEvaluate(xi, xder2); - - xi[0] = xi_prev - xc_derx / xc_derxx; + Array xi(1, (i * (2.0 / n) - 1.0)); + NekDouble xi_prev = xi[0]; - if ((abs(xi[0] - xi_prev) < 1e-16) && (xi[0] >= -1) && (xi[0] <= 1)) + for (int j = 0; j < 10; ++j) { - values.insert(xc); - break; - } + NekDouble xc = edge->GetXmap()->PhysEvaluate(xi, x); + NekDouble xc_derx = edge->GetXmap()->PhysEvaluate(xi, xder); + NekDouble xc_derxx = edge->GetXmap()->PhysEvaluate(xi, xder2); + - xi_prev = xi[0]; + xi[0] = xi_prev - xc_derx / xc_derxx; + + if ((abs(xi[0] - xi_prev) < 1e-10) && (xi[0] >= -1) && (xi[0] <= 1)) + { + cout << "EDGE: " << edge->GetGlobalID() << " iteration: " << j << " xc: " << xc << " xi: " << xi[0] << " xi_prev:" << xi_prev << endl; + values.insert(xc); + break; + } + + xi_prev = xi[0]; + } } - } - const Array minusOne(1, -1); - const Array plusOne(1, 1); - values.insert(m_xmap->PhysEvaluate(minusOne, x)); - values.insert(m_xmap->PhysEvaluate(plusOne, x)); + const Array minusOne(1, -1); + const Array plusOne(1, 1); + values.insert(edge->GetXmap()->PhysEvaluate(minusOne, x)); + values.insert(edge->GetXmap()->PhysEvaluate(plusOne, x)); + } - const auto res = std::minmax_element(std::begin(values), std::end(values)); + const auto res = + std::minmax_element(std::begin(values), std::end(values)); return std::make_pair(*res.first, *res.second); } -- GitLab From ea05b836d4390ced7a4ca3bbc21bd22e6564fd62 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 7 May 2019 16:43:59 +0100 Subject: [PATCH 025/408] Removed debug code --- library/SpatialDomains/Geometry.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index 3beee672e..e675f12a3 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -429,7 +429,6 @@ std::pair Geometry::FindMinMaxCoord(int coordDir) if ((abs(xi[0] - xi_prev) < 1e-10) && (xi[0] >= -1) && (xi[0] <= 1)) { - cout << "EDGE: " << edge->GetGlobalID() << " iteration: " << j << " xc: " << xc << " xi: " << xi[0] << " xi_prev:" << xi_prev << endl; values.insert(xc); break; } -- GitLab From e33a018188c703fbeedc22499f67fedfaaf0aeba Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 7 May 2019 17:52:05 +0100 Subject: [PATCH 026/408] Added 1D and 2D element support to bbox --- library/SpatialDomains/Geometry.cpp | 50 ++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index e675f12a3..152bb086c 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -398,20 +398,48 @@ void Geometry::GenBoundingBox() std::pair Geometry::FindMinMaxCoord(int coordDir) { + int numEdges = 0; + if (GetShapeDim() == 1) + { + numEdges = 1; + } + else if (GetShapeDim() == 2) + { + numEdges = GetNumEdges(); + } + + ASSERTL0(numEdges != 0, "Shape dimension is not supported.") + + Array> coeffs(numEdges); + Array xmaps(numEdges); + + if (GetShapeDim() == 1) + { + coeffs[0] = m_coeffs[coordDir]; + xmaps[0] = m_xmap; + } + else if (GetShapeDim() == 2) + { + for (int edgeID = 0; edgeID < numEdges; ++edgeID) + { + coeffs[edgeID] = GetEdge(edgeID)->GetCoeffs(coordDir); + xmaps[edgeID] = GetEdge(edgeID)->GetXmap(); + } + } + std::unordered_set values; - for (int edgeID = 0; edgeID < GetNumEdges(); ++edgeID) + for (int edgeID = 0; edgeID < numEdges; ++edgeID) { - auto edge = GetEdge(edgeID); - const int nq = edge->GetXmap()->GetTotPoints(); + const int nq = xmaps[edgeID]->GetTotPoints(); Array x(nq, 0.0), xder(nq, 0.0), xder2(nq, 0.0); const int n = 3; Array points(n + 1, 0.0); - edge->GetXmap()->BwdTrans(edge->GetCoeffs(coordDir), x); - edge->GetXmap()->PhysDeriv(x, xder); - edge->GetXmap()->PhysDeriv(xder, xder2); + xmaps[edgeID]->BwdTrans(coeffs[edgeID], x); + xmaps[edgeID]->PhysDeriv(x, xder); + xmaps[edgeID]->PhysDeriv(xder, xder2); for (int i = 0; i < n + 1; ++i) { @@ -420,9 +448,9 @@ std::pair Geometry::FindMinMaxCoord(int coordDir) for (int j = 0; j < 10; ++j) { - NekDouble xc = edge->GetXmap()->PhysEvaluate(xi, x); - NekDouble xc_derx = edge->GetXmap()->PhysEvaluate(xi, xder); - NekDouble xc_derxx = edge->GetXmap()->PhysEvaluate(xi, xder2); + NekDouble xc = xmaps[edgeID]->PhysEvaluate(xi, x); + NekDouble xc_derx = xmaps[edgeID]->PhysEvaluate(xi, xder); + NekDouble xc_derxx = xmaps[edgeID]->PhysEvaluate(xi, xder2); xi[0] = xi_prev - xc_derx / xc_derxx; @@ -439,8 +467,8 @@ std::pair Geometry::FindMinMaxCoord(int coordDir) const Array minusOne(1, -1); const Array plusOne(1, 1); - values.insert(edge->GetXmap()->PhysEvaluate(minusOne, x)); - values.insert(edge->GetXmap()->PhysEvaluate(plusOne, x)); + values.insert(xmaps[edgeID]->PhysEvaluate(minusOne, x)); + values.insert(xmaps[edgeID]->PhysEvaluate(plusOne, x)); } const auto res = -- GitLab From e64c2ff0331b3a5947d4bd4540c23385974d5d3d Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Wed, 8 May 2019 12:35:30 +0100 Subject: [PATCH 027/408] Syntax - &debug for tri cases --- library/SpatialDomains/Geometry.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index 152bb086c..652fa2c83 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -386,8 +386,8 @@ void Geometry::GenBoundingBox() for (int j = 0; j < GetCoordim(); ++j) { auto minMax = FindMinMaxCoord(j); - min[j] = minMax.first; - max[j] = minMax.second; + min[j] = minMax.first; + max[j] = minMax.second; } } @@ -398,7 +398,7 @@ void Geometry::GenBoundingBox() std::pair Geometry::FindMinMaxCoord(int coordDir) { - int numEdges = 0; + int numEdges = -1; if (GetShapeDim() == 1) { numEdges = 1; @@ -408,27 +408,25 @@ std::pair Geometry::FindMinMaxCoord(int coordDir) numEdges = GetNumEdges(); } - ASSERTL0(numEdges != 0, "Shape dimension is not supported.") + ASSERTL0(numEdges != -1, "Shape dimension is not supported.") Array> coeffs(numEdges); Array xmaps(numEdges); - if (GetShapeDim() == 1) { coeffs[0] = m_coeffs[coordDir]; - xmaps[0] = m_xmap; + xmaps[0] = m_xmap; } else if (GetShapeDim() == 2) { for (int edgeID = 0; edgeID < numEdges; ++edgeID) { coeffs[edgeID] = GetEdge(edgeID)->GetCoeffs(coordDir); - xmaps[edgeID] = GetEdge(edgeID)->GetXmap(); + xmaps[edgeID] = GetEdge(edgeID)->GetXmap(); } } std::unordered_set values; - for (int edgeID = 0; edgeID < numEdges; ++edgeID) { const int nq = xmaps[edgeID]->GetTotPoints(); @@ -445,17 +443,16 @@ std::pair Geometry::FindMinMaxCoord(int coordDir) { Array xi(1, (i * (2.0 / n) - 1.0)); NekDouble xi_prev = xi[0]; - for (int j = 0; j < 10; ++j) { NekDouble xc = xmaps[edgeID]->PhysEvaluate(xi, x); NekDouble xc_derx = xmaps[edgeID]->PhysEvaluate(xi, xder); NekDouble xc_derxx = xmaps[edgeID]->PhysEvaluate(xi, xder2); - xi[0] = xi_prev - xc_derx / xc_derxx; - if ((abs(xi[0] - xi_prev) < 1e-10) && (xi[0] >= -1) && (xi[0] <= 1)) + if ((abs(xi[0] - xi_prev) < 1e-10) && (xi[0] >= -1) && + (xi[0] <= 1)) { values.insert(xc); break; @@ -471,8 +468,7 @@ std::pair Geometry::FindMinMaxCoord(int coordDir) values.insert(xmaps[edgeID]->PhysEvaluate(plusOne, x)); } - const auto res = - std::minmax_element(std::begin(values), std::end(values)); + const auto res = std::minmax_element(std::begin(values), std::end(values)); return std::make_pair(*res.first, *res.second); } -- GitLab From e12c36a0fbf31bef9b69c5bde466f2b1c9e0641c Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Wed, 8 May 2019 12:55:38 +0100 Subject: [PATCH 028/408] Fixed generalisation for 2D test --- library/Demos/SpatialDomains/InterfaceTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/Demos/SpatialDomains/InterfaceTest.cpp b/library/Demos/SpatialDomains/InterfaceTest.cpp index ef140b478..4356e32c9 100644 --- a/library/Demos/SpatialDomains/InterfaceTest.cpp +++ b/library/Demos/SpatialDomains/InterfaceTest.cpp @@ -17,7 +17,7 @@ int main(int argc, char *argv[]) LibUtilities::SessionReaderSharedPtr session = LibUtilities::SessionReader::CreateInstance(argc, argv); MeshGraphSharedPtr graph = MeshGraph::Read(session); - auto bbox = graph->GetAllQuadGeoms()[0]->GetBoundingBox(); + auto bbox = graph->GetGeometry2D(0)->GetBoundingBox(); Array min(2), max(2); -- GitLab From f93621a4770709fb67647aee0ab6d74ec66c5800 Mon Sep 17 00:00:00 2001 From: David Moxey Date: Fri, 10 May 2019 13:05:24 +0100 Subject: [PATCH 029/408] Fix Dave's stupid error --- library/LocalRegions/TriExp.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/library/LocalRegions/TriExp.cpp b/library/LocalRegions/TriExp.cpp index 6befb94e1..cdb178411 100644 --- a/library/LocalRegions/TriExp.cpp +++ b/library/LocalRegions/TriExp.cpp @@ -863,11 +863,6 @@ namespace Nektar } StdRegions::Orientation orient = GetEorient(edge); - if (edge == 2) - { - orient = orient == StdRegions::eForwards ? - StdRegions::eBackwards : StdRegions::eForwards; - } //Reverse data if necessary if(orient == StdRegions::eBackwards) -- GitLab From 6b01c8c1005e42f53814c9fc6a7d1917f1cc6cb3 Mon Sep 17 00:00:00 2001 From: David Moxey Date: Fri, 10 May 2019 14:46:33 +0100 Subject: [PATCH 030/408] Add Lagrange interpolant speedup using barycentric formulation --- library/StdRegions/StdExpansion1D.cpp | 57 ++++++++++++++++++++++----- library/StdRegions/StdExpansion1D.h | 2 + 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/library/StdRegions/StdExpansion1D.cpp b/library/StdRegions/StdExpansion1D.cpp index c7f369980..5e85aeb39 100644 --- a/library/StdRegions/StdExpansion1D.cpp +++ b/library/StdRegions/StdExpansion1D.cpp @@ -49,10 +49,29 @@ namespace Nektar StdExpansion1D::StdExpansion1D(int numcoeffs, const LibUtilities::BasisKey &Ba): StdExpansion(numcoeffs,1,Ba) { + int nq = m_base[0]->GetNumPoints(); + Array z = m_base[0]->GetZ(); + m_bcweights = Array(nq, 1.0); + + for (int i = 0; i < nq; ++i) + { + for (int j = 0; j < nq; ++j) + { + if (i == j) + { + continue; + } + + m_bcweights[i] *= (z[i] - z[j]); + } + + m_bcweights[i] = 1.0 / m_bcweights[i]; + } } StdExpansion1D::StdExpansion1D(const StdExpansion1D &T):StdExpansion(T) { + m_bcweights = T.m_bcweights; } StdExpansion1D::~StdExpansion1D() @@ -88,16 +107,34 @@ namespace Nektar const Array& Lcoord, const Array& physvals) { - int nquad = GetTotPoints(); - NekDouble val; - DNekMatSharedPtr I = m_base[0]->GetI(Lcoord); - - ASSERTL2(Lcoord[0] >= -1 - NekConstants::kNekZeroTol,"Lcoord[0] < -1"); - ASSERTL2(Lcoord[0] <= 1 + NekConstants::kNekZeroTol,"Lcoord[0] > 1"); - - val = Blas::Ddot(nquad, I->GetPtr(), 1, physvals, 1); - - return val; + int nquad = GetTotPoints(); + /* + NekDouble val; + DNekMatSharedPtr I = m_base[0]->GetI(Lcoord); + + ASSERTL2(Lcoord[0] >= -1 - NekConstants::kNekZeroTol,"Lcoord[0] < -1"); + ASSERTL2(Lcoord[0] <= 1 + NekConstants::kNekZeroTol,"Lcoord[0] > 1"); + val = Blas::Ddot(nquad, I->GetPtr(), 1, physvals, 1); + */ + + NekDouble numer = 0.0, denom = 0.0; + + const Array z = m_base[0]->GetZ(); + + for (int i = 0; i < nquad; ++i) + { + NekDouble xdiff = z[i] - Lcoord[0]; + if (xdiff == 0.0) + { + return physvals[i]; + } + + NekDouble tmp = m_bcweights[i] / xdiff; + numer += tmp * physvals[i]; + denom += tmp; + } + + return numer / denom; } void StdExpansion1D::v_SetUpPhysNormals(const int vertex) diff --git a/library/StdRegions/StdExpansion1D.h b/library/StdRegions/StdExpansion1D.h index 71271d9c7..3885b208a 100644 --- a/library/StdRegions/StdExpansion1D.h +++ b/library/StdRegions/StdExpansion1D.h @@ -80,6 +80,8 @@ namespace Nektar private: + Array m_bcweights; + // Virtual Functions ---------------------------------------- virtual int v_GetCoordim(void) -- GitLab From fc46aacc6f0e13da76625b67cb6db0065391d8a3 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 10 May 2019 15:26:19 +0100 Subject: [PATCH 031/408] Proto changed m_domain vector to map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debug @todo’s in future, not tested --- library/SpatialDomains/MeshGraph.h | 6 ++--- library/SpatialDomains/MeshGraphXml.cpp | 23 ++++++++----------- library/SpatialDomains/MeshGraphXml.h | 2 +- .../EquationSystems/PulseWaveSystem.cpp | 7 +++++- .../NekMesh/OutputModules/OutputNekpp.cpp | 18 ++++++++------- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/library/SpatialDomains/MeshGraph.h b/library/SpatialDomains/MeshGraph.h index a2b76b29f..4b9f69652 100644 --- a/library/SpatialDomains/MeshGraph.h +++ b/library/SpatialDomains/MeshGraph.h @@ -277,14 +277,14 @@ public: return m_compositesLabels; } - std::vector> &GetDomain() + std::map> &GetDomain() { return m_domain; } std::map &GetDomain(int domain) { - ASSERTL1(domain < m_domain.size(), + ASSERTL1(m_domain.count(domain) == 1, "Request for domain which does not exist"); return m_domain[domain]; } @@ -476,7 +476,7 @@ protected: CompositeMap m_meshComposites; std::map m_compositesLabels; - std::vector m_domain; + std::map m_domain; DomainRangeShPtr m_domainRange; ExpansionMapShPtrMap m_expansionMapShPtrMap; diff --git a/library/SpatialDomains/MeshGraphXml.cpp b/library/SpatialDomains/MeshGraphXml.cpp index 7fb4253ef..76aba3819 100644 --- a/library/SpatialDomains/MeshGraphXml.cpp +++ b/library/SpatialDomains/MeshGraphXml.cpp @@ -942,7 +942,7 @@ void MeshGraphXml::ReadDomain() if (multidomains) { - int nextDomainNumber = 0; + //int nextDomainNumber = 0; while (multidomains) { int indx; @@ -975,9 +975,9 @@ void MeshGraphXml::ReadDomain() // Parse the composites into a list. map unrollDomain; GetCompositeList(indxStr, unrollDomain); - m_domain.push_back(unrollDomain); + m_domain[indx] = unrollDomain; - ASSERTL0(!m_domain[nextDomainNumber++].empty(), + ASSERTL0(!m_domain[indx].empty(), (std::string( "Unable to obtain domain's referenced composite: ") + indxStr) @@ -1013,7 +1013,7 @@ void MeshGraphXml::ReadDomain() // Parse the composites into a list. map fullDomain; GetCompositeList(indxStr, fullDomain); - m_domain.push_back(fullDomain); + m_domain[0] = fullDomain; ASSERTL0( !m_domain[0].empty(), @@ -2706,31 +2706,28 @@ void MeshGraphXml::WriteComposites(TiXmlElement *geomTag, CompositeMap &comps) } void MeshGraphXml::WriteDomain(TiXmlElement *geomTag, - vector &domainVector) + std::map &domainMap) { TiXmlElement *domTag = new TiXmlElement("DOMAIN"); stringstream domString; - int domainIt =0; - // @todo Fix this to accomodate multi domain output properly (need the domain input to be a map for ID instead of just incrementing domainIt++) vector idxList; - for (CompositeMap &domain : domainVector) + for (auto &domain : domainMap) { TiXmlElement *c = new TiXmlElement("D"); idxList.clear(); stringstream s; s << " " << "C" << "["; - for(const auto &elem : domain) + for(const auto &elem : domain.second) { idxList.push_back(elem.first); } s << ParseUtils::GenerateSeqString(idxList) << "] "; - c->SetAttribute("ID", domainIt); + c->SetAttribute("ID", domain.first); c->LinkEndChild(new TiXmlText(s.str())); domTag->LinkEndChild(c); - domainIt++; } geomTag->LinkEndChild(domTag); @@ -3117,7 +3114,7 @@ void MeshGraphXml::WriteXMLGeometry(std::string outname, WriteComposites(geomTag, localComp); - vector domain; + std::map domain; CompositeMap domMap; for (auto &j : localComp) { @@ -3126,7 +3123,7 @@ void MeshGraphXml::WriteXMLGeometry(std::string outname, domMap[j.first] = j.second; } } - domain.push_back(domMap); + domain[0] = domMap; //@todo potentially error on this line with map for domain partitioner, I don't know what above does - Ed WriteDomain(geomTag, domain); diff --git a/library/SpatialDomains/MeshGraphXml.h b/library/SpatialDomains/MeshGraphXml.h index db14d8b3f..cf3bb2e3c 100644 --- a/library/SpatialDomains/MeshGraphXml.h +++ b/library/SpatialDomains/MeshGraphXml.h @@ -120,7 +120,7 @@ protected: virtual void WriteTets(TiXmlElement *elmtTag, TetGeomMap &tets); virtual void WriteCurves(TiXmlElement *geomTag, CurveMap &edges, CurveMap &faces); void WriteComposites(TiXmlElement *geomTag, CompositeMap &comps); - void WriteDomain(TiXmlElement *geomTag, vector &domain); + void WriteDomain(TiXmlElement *geomTag, std::map &domain); void WriteDefaultExpansion(TiXmlElement *root); CompositeOrdering CreateCompositeOrdering(); diff --git a/solvers/PulseWaveSolver/EquationSystems/PulseWaveSystem.cpp b/solvers/PulseWaveSolver/EquationSystems/PulseWaveSystem.cpp index f07443e98..6dd31126f 100755 --- a/solvers/PulseWaveSolver/EquationSystems/PulseWaveSystem.cpp +++ b/solvers/PulseWaveSolver/EquationSystems/PulseWaveSystem.cpp @@ -104,7 +104,12 @@ namespace Nektar m_fields = Array (m_nVariables); m_vessels = Array (m_nVariables*m_nDomains); - const std::vector domain = m_graph->GetDomain(); + const std::map domainMap = m_graph->GetDomain(); //@todo rewrite all so domain is from map, not vector - Ed) + std::vector domain; + for (auto i : domainMap) + { + domain.emplace_back(i.second); + } SpatialDomains::BoundaryConditions Allbcs(m_session, m_graph); diff --git a/utilities/NekMesh/OutputModules/OutputNekpp.cpp b/utilities/NekMesh/OutputModules/OutputNekpp.cpp index fc10f6bc2..512d09400 100644 --- a/utilities/NekMesh/OutputModules/OutputNekpp.cpp +++ b/utilities/NekMesh/OutputModules/OutputNekpp.cpp @@ -593,14 +593,15 @@ void OutputNekpp::TransferComposites(MeshGraphSharedPtr graph) } } -void OutputNekpp::TransferDomain(MeshGraphSharedPtr graph) +void OutputNekpp::TransferDomain(MeshGraphSharedPtr graph) //@todo Need to have a m_domain in the Mesh class to keep track of numbering - Ed { - vector &domain = graph->GetDomain(); - - string list; + std::map &domain = graph->GetDomain(); + int cnt = 0; for(auto &it : m_mesh->m_composite) { + + string list; if(it.second->m_items[0]->GetDim() == m_mesh->m_expDim) { if(list.length() > 0) @@ -608,12 +609,13 @@ void OutputNekpp::TransferDomain(MeshGraphSharedPtr graph) list += ","; } list += boost::lexical_cast(it.second->m_id); + + SpatialDomains::CompositeMap fullDomain; + graph->GetCompositeList(list, fullDomain); + domain[cnt] = fullDomain; + cnt++; } } - - SpatialDomains::CompositeMap fullDomain; - graph->GetCompositeList(list, fullDomain); - domain.push_back(fullDomain); } } -- GitLab From cfa86575403703d9a2872df9aeea74e407963066 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Wed, 15 May 2019 12:21:37 +0100 Subject: [PATCH 032/408] Further generalisation of FindMinMaxCoord --- library/SpatialDomains/Geometry.cpp | 142 ++++++++++++++++------------ 1 file changed, 84 insertions(+), 58 deletions(-) diff --git a/library/SpatialDomains/Geometry.cpp b/library/SpatialDomains/Geometry.cpp index 652fa2c83..cc83d4572 100644 --- a/library/SpatialDomains/Geometry.cpp +++ b/library/SpatialDomains/Geometry.cpp @@ -358,7 +358,7 @@ void Geometry::v_Setup() void Geometry::GenBoundingBox() { // NekDouble minx, miny, minz, maxx, maxy, maxz; - Array min(3), max(3); + Array min(3, 0.0), max(3, 0.0); if (GetGeomFactors()->GetGtype() == eRegular) { @@ -386,8 +386,8 @@ void Geometry::GenBoundingBox() for (int j = 0; j < GetCoordim(); ++j) { auto minMax = FindMinMaxCoord(j); - min[j] = minMax.first; - max[j] = minMax.second; + min[j] = minMax.first - NekConstants::kGeomFactorsTol; + max[j] = minMax.second + NekConstants::kGeomFactorsTol; } } @@ -398,78 +398,104 @@ void Geometry::GenBoundingBox() std::pair Geometry::FindMinMaxCoord(int coordDir) { - int numEdges = -1; - if (GetShapeDim() == 1) + switch (m_shapeType) { - numEdges = 1; - } - else if (GetShapeDim() == 2) - { - numEdges = GetNumEdges(); - } + case LibUtilities::eSegment: + { + std::unordered_set values; - ASSERTL0(numEdges != -1, "Shape dimension is not supported.") + const int nq = m_xmap->GetTotPoints(); + Array x(nq, 0.0), xder(nq, 0.0), xder2(nq, 0.0); - Array> coeffs(numEdges); - Array xmaps(numEdges); - if (GetShapeDim() == 1) - { - coeffs[0] = m_coeffs[coordDir]; - xmaps[0] = m_xmap; - } - else if (GetShapeDim() == 2) - { - for (int edgeID = 0; edgeID < numEdges; ++edgeID) - { - coeffs[edgeID] = GetEdge(edgeID)->GetCoeffs(coordDir); - xmaps[edgeID] = GetEdge(edgeID)->GetXmap(); - } - } + const int n = 3; + Array points(n + 1, 0.0); - std::unordered_set values; - for (int edgeID = 0; edgeID < numEdges; ++edgeID) - { - const int nq = xmaps[edgeID]->GetTotPoints(); - Array x(nq, 0.0), xder(nq, 0.0), xder2(nq, 0.0); + m_xmap->BwdTrans(m_coeffs[coordDir], x); + m_xmap->PhysDeriv(x, xder); + m_xmap->PhysDeriv(xder, xder2); + + for (int i = 0; i < n + 1; ++i) + { + Array xi(1, (i * (2.0 / n) - 1.0)); + NekDouble xi_prev = xi[0]; + for (int j = 0; j < 10; ++j) + { + NekDouble xc = m_xmap->PhysEvaluate(xi, x); + NekDouble xc_derx = m_xmap->PhysEvaluate(xi, xder); + NekDouble xc_derxx = m_xmap->PhysEvaluate(xi, xder2); + + xi[0] = xi_prev - xc_derx / xc_derxx; - const int n = 3; - Array points(n + 1, 0.0); + if ((abs(xi[0] - xi_prev) < 1e-10) && (xi[0] >= -1) && + (xi[0] <= 1)) + { + values.insert(xc); + break; + } - xmaps[edgeID]->BwdTrans(coeffs[edgeID], x); - xmaps[edgeID]->PhysDeriv(x, xder); - xmaps[edgeID]->PhysDeriv(xder, xder2); + xi_prev = xi[0]; + } + } - for (int i = 0; i < n + 1; ++i) + const Array minusOne(1, -1); + const Array plusOne(1, 1); + values.insert(m_xmap->PhysEvaluate(minusOne, x)); + values.insert(m_xmap->PhysEvaluate(plusOne, x)); + + const auto res = + std::minmax_element(std::begin(values), std::end(values)); + return std::make_pair(*res.first, *res.second); + } + + case LibUtilities::eTriangle: + case LibUtilities::eQuadrilateral: { - Array xi(1, (i * (2.0 / n) - 1.0)); - NekDouble xi_prev = xi[0]; - for (int j = 0; j < 10; ++j) + if (m_coordim == 2) { - NekDouble xc = xmaps[edgeID]->PhysEvaluate(xi, x); - NekDouble xc_derx = xmaps[edgeID]->PhysEvaluate(xi, xder); - NekDouble xc_derxx = xmaps[edgeID]->PhysEvaluate(xi, xder2); - - xi[0] = xi_prev - xc_derx / xc_derxx; + std::unordered_set values; - if ((abs(xi[0] - xi_prev) < 1e-10) && (xi[0] >= -1) && - (xi[0] <= 1)) + for (int edgeID = 0; edgeID < GetNumEdges(); ++edgeID) { - values.insert(xc); - break; + auto edgeMinMax = + GetEdge(edgeID)->FindMinMaxCoord(coordDir); + values.insert(edgeMinMax.first); + values.insert(edgeMinMax.second); } - xi_prev = xi[0]; + const auto res = + std::minmax_element(std::begin(values), std::end(values)); + return std::make_pair(*res.first, *res.second); } } - const Array minusOne(1, -1); - const Array plusOne(1, 1); - values.insert(xmaps[edgeID]->PhysEvaluate(minusOne, x)); - values.insert(xmaps[edgeID]->PhysEvaluate(plusOne, x)); - } + default: // @todo change default method so it solves numerically + { + std::unordered_set values; + + const int nq = m_xmap->GetTotPoints(); + Array x(nq, 0.0); + + m_xmap->BwdTrans(m_coeffs[coordDir], x); - const auto res = std::minmax_element(std::begin(values), std::end(values)); - return std::make_pair(*res.first, *res.second); + for (int i = 0; i < nq; ++i) + { + values.insert(x[i]); + } + + const auto res = + std::minmax_element(std::begin(values), std::end(values)); + auto minMax = std::make_pair(*res.first, *res.second); + + // Add 10% margin to bounding box in case elements have + // convex boundaries. + const int len = minMax.second - minMax.first; + + minMax.first -= 0.1 * len; + minMax.second += 0.1 * len; + + return minMax; + } + } } } // namespace SpatialDomains -- GitLab From 08c7bd5c1875d95aa59135ef784e8ded241daf8c Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 13 Jun 2019 14:21:55 +0100 Subject: [PATCH 033/408] Caching for found segment/local for fwd/bwd trace --- library/MultiRegions/DisContField2D.cpp | 166 ++++++++++++++++-------- library/MultiRegions/DisContField2D.h | 4 + 2 files changed, 114 insertions(+), 56 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index ff2526684..adff0e41d 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1455,48 +1455,74 @@ void DisContField2D::v_GetFwdBwdTracePhys( for (auto edges : interface.second) { auto elmt = edges.second; - int nq = elmt->GetTotPoints(); + int nq = elmt->GetTotPoints(); + LocalRegions::Expansion1DSharedPtr geom; Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); for (int i = 0; i < nq; ++i) { - NekDouble zero = 0.0; - auto BgRtree = - m_interfaces[interface.first]->GetRightEdgesContainingPoint( - xc[i], yc[i], zero); bool found = false; - for (auto boundaryBoxElement : BgRtree) + NekDouble foundPoint; + int segID; + auto coords = std::make_pair(xc[i], yc[i]); + + auto itr = m_rightToLeftMap[interface.first].find( + coords); + if (itr != m_rightToLeftMap[interface.first].end()) + { + segID = itr->second.first; + foundPoint = itr->second.second; + geom = m_traceEdgeRight[interface.first][segID]; + found = true; + } + else { - if (found == false) + NekDouble zero = 0.0; + auto BgRtree = + m_interfaces[interface.first]->GetRightEdgesContainingPoint( + xc[i], yc[i], zero); + for (auto boundaryBoxElement : BgRtree) { - auto geom = m_traceEdgeRight[interface.first] - [boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast( - geom->GetGeom1D()); - - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - NekDouble foundPoint; - NekDouble dist = geomSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) + if (found == false) { - continue; + geom = m_traceEdgeRight[interface.first] + [boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast( + geom->GetGeom1D()); + + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + + NekDouble dist = geomSeg->FindDistance(xs, + foundPoint); + if (dist > 1e-8) + { + continue; + } + + m_rightToLeftMap[interface.first][coords] = std::make_pair( + geomSeg->GetGlobalID(), foundPoint); + + found = true; + break; } - Array edgePhys = - Bwd + m_trace->GetPhys_Offset(geom->GetElmtId()); - Array foundPointArray(1, foundPoint); - Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = - geom->StdPhysEvaluate(foundPointArray, edgePhys); - found = true; - break; } } + ASSERTL1(found, "Couldn't interpolate across interface " "from right to left (bwd)"); + + Array edgePhys = + Bwd + + m_trace->GetPhys_Offset(geom->GetElmtId()); + Array foundPointArray(1, foundPoint); + Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = + geom->StdPhysEvaluate(foundPointArray, + edgePhys); } } } @@ -1507,47 +1533,75 @@ void DisContField2D::v_GetFwdBwdTracePhys( for (auto edges : interface.second) { auto elmt = edges.second; - int nq = elmt->GetTotPoints(); + int nq = elmt->GetTotPoints(); + LocalRegions::Expansion1DSharedPtr geom; Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); + for (int i = 0; i < nq; ++i) { - NekDouble zero = 0.0; - auto BgRtree = - m_interfaces[interface.first]->GetLeftEdgesContainingPoint( - xc[i], yc[i], zero); bool found = false; - for (auto boundaryBoxElement : BgRtree) + NekDouble foundPoint; + int segID; + auto coords = std::make_pair(xc[i], yc[i]); + + auto itr = m_leftToRightMap[interface.first].find( + coords); + if (itr != m_leftToRightMap[interface.first].end()) + { + segID = itr->second.first; + foundPoint = itr->second.second; + geom = m_traceEdgeLeft[interface.first][segID]; + found = true; + } + else { - if (found == false) + NekDouble zero = 0.0; + auto BgRtree = + m_interfaces[interface.first]->GetLeftEdgesContainingPoint( + xc[i], yc[i], zero); + for (auto boundaryBoxElement : BgRtree) { - auto geom = m_traceEdgeLeft[interface.first] - [boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast( - geom->GetGeom1D()); - - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - NekDouble foundPoint; - NekDouble dist = geomSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) + if (found == false) { - continue; + geom = m_traceEdgeLeft[interface.first] + [boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast( + geom->GetGeom1D()); + + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + + NekDouble dist = geomSeg->FindDistance(xs, + foundPoint); + if (dist > 1e-8) + { + continue; + } + + m_leftToRightMap[interface.first][coords] = std::make_pair( + geomSeg->GetGlobalID(), foundPoint); + + found = true; + break; } - Array edgePhys = - Fwd + m_trace->GetPhys_Offset(geom->GetElmtId()); - Array foundPointArray(1, foundPoint); - Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = - geom->StdPhysEvaluate(foundPointArray, edgePhys); - found = true; - break; } } + ASSERTL1(found, "Couldn't interpolate across interface " "from left to right (fwd)"); + + Array edgePhys = + Fwd + + m_trace->GetPhys_Offset(geom->GetElmtId()); + Array foundPointArray(1, foundPoint); + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = + geom->StdPhysEvaluate(foundPointArray, + edgePhys); + } } } diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 81c46e47b..2a7057d0b 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -151,6 +151,10 @@ namespace Nektar std::map> m_traceEdgeRight; std::unordered_set m_interfaceEdgeLeft, m_interfaceEdgeRight; + std::map, std::pair>> m_rightToLeftMap; + std::map, std::pair>> m_leftToRightMap; + + GlobalLinSysMapShPtr m_globalBndMat; ExpListSharedPtr m_trace; AssemblyMapDGSharedPtr m_traceMap; -- GitLab From 49ce1be863ba6ad84948bda1482b9552327a1cf7 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 14 Jun 2019 11:14:53 +0100 Subject: [PATCH 034/408] Tidy of cache --- library/MultiRegions/DisContField2D.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index adff0e41d..556ae74c2 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1464,24 +1464,21 @@ void DisContField2D::v_GetFwdBwdTracePhys( { bool found = false; NekDouble foundPoint; - int segID; auto coords = std::make_pair(xc[i], yc[i]); - auto itr = m_rightToLeftMap[interface.first].find( - coords); + auto itr = m_rightToLeftMap[interface.first].find(coords); if (itr != m_rightToLeftMap[interface.first].end()) { - segID = itr->second.first; foundPoint = itr->second.second; - geom = m_traceEdgeRight[interface.first][segID]; + geom = m_traceEdgeRight[interface.first][itr->second.first]; found = true; } else { NekDouble zero = 0.0; auto BgRtree = - m_interfaces[interface.first]->GetRightEdgesContainingPoint( - xc[i], yc[i], zero); + m_interfaces[interface.first]-> + GetRightEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { if (found == false) @@ -1542,24 +1539,21 @@ void DisContField2D::v_GetFwdBwdTracePhys( { bool found = false; NekDouble foundPoint; - int segID; auto coords = std::make_pair(xc[i], yc[i]); - auto itr = m_leftToRightMap[interface.first].find( - coords); + auto itr = m_leftToRightMap[interface.first].find(coords); if (itr != m_leftToRightMap[interface.first].end()) { - segID = itr->second.first; foundPoint = itr->second.second; - geom = m_traceEdgeLeft[interface.first][segID]; + geom = m_traceEdgeLeft[interface.first][itr->second.first]; found = true; } else { NekDouble zero = 0.0; auto BgRtree = - m_interfaces[interface.first]->GetLeftEdgesContainingPoint( - xc[i], yc[i], zero); + m_interfaces[interface.first]-> + GetLeftEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { if (found == false) -- GitLab From 42d94f32e2f55e385f2f2f19b16a3e84c42a0960 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 14 Jun 2019 11:48:14 +0100 Subject: [PATCH 035/408] Remove meshGraph hack --- library/SpatialDomains/MeshGraph.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index 4531f60ec..a24c12896 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -2608,9 +2608,6 @@ std::string MeshGraph::GetCompositeString(CompositeSharedPtr comp) void MeshGraph::ReadExpansions() { - // Hack? - m_expansionMapShPtrMap.clear(); - // Find the Expansions tag TiXmlElement *expansionTypes = m_session->GetElement("NEKTAR/EXPANSIONS"); ASSERTL0(expansionTypes, "Unable to find EXPANSIONS tag in file."); -- GitLab From 16669db279c7b8f69ba82b9bd6ba5bb1d5cfe444 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Fri, 14 Jun 2019 13:57:42 +0100 Subject: [PATCH 036/408] Change cache structure to vector added recalc flag --- library/MultiRegions/DisContField2D.cpp | 156 +++++++++++------------- library/MultiRegions/DisContField2D.h | 10 +- 2 files changed, 81 insertions(+), 85 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 556ae74c2..ce652367b 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1452,74 +1452,68 @@ void DisContField2D::v_GetFwdBwdTracePhys( // Edge two -> one interpolation for (auto &interface : m_traceEdgeLeft) { + int cnt = 0; + auto &mapCache = m_rightToLeftMap[interface.first]; + auto &traceEdgeCache = m_traceEdgeRight[interface.first]; + auto &interfacesCache = m_interfaces[interface.first]; + for (auto edges : interface.second) { auto elmt = edges.second; int nq = elmt->GetTotPoints(); - LocalRegions::Expansion1DSharedPtr geom; - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - for (int i = 0; i < nq; ++i) + for (int i = 0; i < nq; ++i, ++cnt) { bool found = false; NekDouble foundPoint; - auto coords = std::make_pair(xc[i], yc[i]); + LocalRegions::Expansion1DSharedPtr geom; - auto itr = m_rightToLeftMap[interface.first].find(coords); - if (itr != m_rightToLeftMap[interface.first].end()) + if (m_interfaceCacheFlag) { - foundPoint = itr->second.second; - geom = m_traceEdgeRight[interface.first][itr->second.first]; + auto tmp = mapCache[cnt]; + foundPoint = tmp.second; + geom = traceEdgeCache[tmp.first]; found = true; } else { + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); NekDouble zero = 0.0; - auto BgRtree = - m_interfaces[interface.first]-> + auto BgRtree = interfacesCache-> GetRightEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { - if (found == false) - { - geom = m_traceEdgeRight[interface.first] - [boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast( - geom->GetGeom1D()); - - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - - NekDouble dist = geomSeg->FindDistance(xs, - foundPoint); - if (dist > 1e-8) - { - continue; - } + geom = traceEdgeCache[boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast(geom->GetGeom1D()); - m_rightToLeftMap[interface.first][coords] = std::make_pair( - geomSeg->GetGlobalID(), foundPoint); + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; - found = true; - break; + NekDouble dist = geomSeg->FindDistance(xs,foundPoint); + if (dist > 1e-8) + { + continue; } + + mapCache.push_back(std::make_pair(geomSeg-> + GetGlobalID(), foundPoint)); + found = true; + break; } } - ASSERTL1(found, "Couldn't interpolate across interface " + ASSERTL0(found, "Couldn't interpolate across interface " "from right to left (bwd)"); - Array edgePhys = - Bwd + - m_trace->GetPhys_Offset(geom->GetElmtId()); + Array edgePhys = Bwd + m_trace-> + GetPhys_Offset(geom->GetElmtId()); Array foundPointArray(1, foundPoint); - Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = - geom->StdPhysEvaluate(foundPointArray, - edgePhys); + Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom-> + StdPhysEvaluate(foundPointArray, edgePhys); } } } @@ -1527,79 +1521,75 @@ void DisContField2D::v_GetFwdBwdTracePhys( // Edge one -> two interpolation for (auto &interface : m_traceEdgeRight) { + int cnt = 0; + auto &mapCache = m_leftToRightMap[interface.first]; + auto &traceEdgeCache = m_traceEdgeLeft[interface.first]; + auto &interfacesCache = m_interfaces[interface.first]; + for (auto edges : interface.second) { auto elmt = edges.second; int nq = elmt->GetTotPoints(); - LocalRegions::Expansion1DSharedPtr geom; - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - for (int i = 0; i < nq; ++i) + for (int i = 0; i < nq; ++i, ++cnt) { bool found = false; NekDouble foundPoint; - auto coords = std::make_pair(xc[i], yc[i]); + LocalRegions::Expansion1DSharedPtr geom; - auto itr = m_leftToRightMap[interface.first].find(coords); - if (itr != m_leftToRightMap[interface.first].end()) + if (m_interfaceCacheFlag) { - foundPoint = itr->second.second; - geom = m_traceEdgeLeft[interface.first][itr->second.first]; + auto tmp = mapCache[cnt]; + foundPoint = tmp.second; + geom = traceEdgeCache[tmp.first]; found = true; } else { + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); NekDouble zero = 0.0; - auto BgRtree = - m_interfaces[interface.first]-> + auto BgRtree = interfacesCache-> GetLeftEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { - if (found == false) - { - geom = m_traceEdgeLeft[interface.first] - [boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast( - geom->GetGeom1D()); - - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - - NekDouble dist = geomSeg->FindDistance(xs, - foundPoint); - if (dist > 1e-8) - { - continue; - } + geom = traceEdgeCache[boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast(geom->GetGeom1D()); - m_leftToRightMap[interface.first][coords] = std::make_pair( - geomSeg->GetGlobalID(), foundPoint); + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; - found = true; - break; + NekDouble dist = geomSeg->FindDistance(xs,foundPoint); + if (dist > 1e-8) + { + continue; } + + mapCache.push_back(std::make_pair(geomSeg-> + GetGlobalID(), foundPoint)); + found = true; + break; } } - ASSERTL1(found, "Couldn't interpolate across interface " + ASSERTL0(found, "Couldn't interpolate across interface " "from left to right (fwd)"); - Array edgePhys = - Fwd + - m_trace->GetPhys_Offset(geom->GetElmtId()); + Array edgePhys = Fwd + m_trace-> + GetPhys_Offset(geom->GetElmtId()); Array foundPointArray(1, foundPoint); - Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = - geom->StdPhysEvaluate(foundPointArray, - edgePhys); - + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom-> + StdPhysEvaluate(foundPointArray, edgePhys); } } } + //Flag that cache has been created + m_interfaceCacheFlag = true; + // Do parallel exchange for forwards/backwards spaces. m_traceMap->UniversalTraceAssemble(Fwd); m_traceMap->UniversalTraceAssemble(Bwd); diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 2a7057d0b..0461043c6 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -151,8 +151,14 @@ namespace Nektar std::map> m_traceEdgeRight; std::unordered_set m_interfaceEdgeLeft, m_interfaceEdgeRight; - std::map, std::pair>> m_rightToLeftMap; - std::map, std::pair>> m_leftToRightMap; + // first key is interface ID; contains a vector with each quadrature point + // in the left hand side of seg ID and local coordinate found + typedef std::map>> EdgeCacheMap; + EdgeCacheMap m_rightToLeftMap; + EdgeCacheMap m_leftToRightMap; + + //Flag true if interface cache has been created + bool m_interfaceCacheFlag = false; GlobalLinSysMapShPtr m_globalBndMat; -- GitLab From 30b95c92a6c5b5e96297fffe1cd997656621c68e Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 18 Jun 2019 11:43:32 +0100 Subject: [PATCH 037/408] Generalised interface class structure --- library/MultiRegions/DisContField2D.cpp | 16 +-- library/MultiRegions/ExpList2D.cpp | 4 +- library/SpatialDomains/Interface.cpp | 184 +++++++++--------------- library/SpatialDomains/Interface.h | 83 +++++------ library/SpatialDomains/MeshGraph.cpp | 3 + library/SpatialDomains/MeshGraphXml.cpp | 2 + 6 files changed, 115 insertions(+), 177 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index ce652367b..0107c06ae 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -444,7 +444,7 @@ void DisContField2D::SetUpDG(const std::string variable) // and exterior interface components. for (auto &interface : m_interfaces) { - for (auto &iter : interface.second->GetEdgeRight()) + for (auto &iter : interface.second.second->GetEdge()) { int id = iter.first; auto traceEl = std::dynamic_pointer_cast( @@ -455,7 +455,7 @@ void DisContField2D::SetUpDG(const std::string variable) m_interfaceEdgeRight.insert(id); } - for (auto &iter : interface.second->GetEdgeLeft()) + for (auto &iter : interface.second.first->GetEdge()) { int id = iter.first; auto traceEl = std::dynamic_pointer_cast( @@ -1480,8 +1480,8 @@ void DisContField2D::v_GetFwdBwdTracePhys( Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); NekDouble zero = 0.0; - auto BgRtree = interfacesCache-> - GetRightEdgesContainingPoint(xc[i], yc[i], zero); + auto BgRtree = interfacesCache.second-> + GetEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { geom = traceEdgeCache[boundaryBoxElement.second]; @@ -1499,7 +1499,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( continue; } - mapCache.push_back(std::make_pair(geomSeg-> + mapCache.emplace_back(std::make_pair(geomSeg-> GetGlobalID(), foundPoint)); found = true; break; @@ -1549,8 +1549,8 @@ void DisContField2D::v_GetFwdBwdTracePhys( Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); NekDouble zero = 0.0; - auto BgRtree = interfacesCache-> - GetLeftEdgesContainingPoint(xc[i], yc[i], zero); + auto BgRtree = interfacesCache.first-> + GetEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { geom = traceEdgeCache[boundaryBoxElement.second]; @@ -1568,7 +1568,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( continue; } - mapCache.push_back(std::make_pair(geomSeg-> + mapCache.emplace_back(std::make_pair(geomSeg-> GetGlobalID(), foundPoint)); found = true; break; diff --git a/library/MultiRegions/ExpList2D.cpp b/library/MultiRegions/ExpList2D.cpp index f612b36d3..afc333e7b 100644 --- a/library/MultiRegions/ExpList2D.cpp +++ b/library/MultiRegions/ExpList2D.cpp @@ -144,9 +144,9 @@ namespace Nektar m_interfaces = interfaceCollection.GetInterfaces(); for (auto &inter : m_interfaces) { - if (inter.second->GetEdgeRight().empty()) + if (inter.second.second->GetEdge().empty()) { - inter.second->SeparateGraph(m_graph); + interfaceCollection.SeparateGraph(m_graph, inter.first); } } diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index c6a6df58b..cc8591dbd 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -35,6 +35,7 @@ //////////////////////////////////////////////////////////////////////////////// #include +#include #include #include @@ -102,6 +103,8 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) TiXmlElement *interfaceElement = interfaces->FirstChildElement(); + std::map> tmpInterfaceMap; + while (interfaceElement) { std::string interfaceType = interfaceElement->Value(); @@ -112,24 +115,18 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) err = interfaceElement->QueryIntAttribute("ID", &indx); ASSERTL0(err == TIXML_SUCCESS, "Unable to read interface ID."); - std::string interfaceRightDomainStr; - err = interfaceElement->QueryStringAttribute("RIGHTDOMAIN", - &interfaceRightDomainStr); + std::string interfaceDomainStr; + err = interfaceElement->QueryStringAttribute("DOMAIN", + &interfaceDomainStr); ASSERTL0(err == TIXML_SUCCESS, - "Unable to read right interface domain."); - auto rightDomain = - m_meshGraph->GetDomain(stoi(ReadTag(interfaceRightDomainStr))); + "Unable to read interface domain."); + auto domain = + m_meshGraph->GetDomain(stoi(ReadTag(interfaceDomainStr))); - std::string interfaceLeftDomainStr; - err = interfaceElement->QueryStringAttribute("LEFTDOMAIN", - &interfaceLeftDomainStr); - ASSERTL0(err == TIXML_SUCCESS, "Unable to read left interface domain."); - auto leftDomain = - m_meshGraph->GetDomain(stoi(ReadTag(interfaceLeftDomainStr))); std::string interfaceEdgeStr; int interfaceErr = interfaceElement->QueryStringAttribute( - "INTERFACE", &interfaceEdgeStr); + "INTERFACEEDGE", &interfaceEdgeStr); map interfaceEdge; if (interfaceErr == TIXML_SUCCESS) { @@ -137,48 +134,30 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) m_meshGraph->GetCompositeList(indxStr, interfaceEdge); } - std::string leftEdgeStr; - int leftEdgeErr = - interfaceElement->QueryStringAttribute("LEFTEDGE", &leftEdgeStr); - map leftEdge; - if (leftEdgeErr == TIXML_SUCCESS) - { - std::string indxStr = ReadTag(leftEdgeStr); - m_meshGraph->GetCompositeList(indxStr, leftEdge); - } - - std::string rightEdgeStr; - int rightEdgeErr = - interfaceElement->QueryStringAttribute("RIGHTEDGE", &rightEdgeStr); - map rightEdge; - if (rightEdgeErr == TIXML_SUCCESS) + std::string domainEdgeStr; + int domainEdgeErr = + interfaceElement->QueryStringAttribute("EDGE", &domainEdgeStr); + map domainEdge; + if (domainEdgeErr == TIXML_SUCCESS) { - std::string indxStr = ReadTag(rightEdgeStr); - m_meshGraph->GetCompositeList(indxStr, rightEdge); + std::string indxStr = ReadTag(domainEdgeStr); + m_meshGraph->GetCompositeList(indxStr, domainEdge); } if (interfaceErr == TIXML_SUCCESS) { - ASSERTL0(leftEdgeErr != TIXML_SUCCESS && - rightEdgeErr != TIXML_SUCCESS, - "Choose to define either INTERFACE or both LEFTEDGE " - "and RIGHTEDGE.") + ASSERTL0(domainEdgeErr != TIXML_SUCCESS, + "Choose to define either INTERFACEEDGE or EDGE") } - else if (leftEdgeErr == TIXML_SUCCESS && rightEdgeErr == TIXML_SUCCESS) + else if (domainEdgeErr == TIXML_SUCCESS) { ASSERTL0(interfaceErr != TIXML_SUCCESS, - "Choose to define either INTERFACE or both LEFTEDGE " - "and RIGHTEDGE.") - } - else - { - ASSERTL0((interfaceErr + 1) * (leftEdgeErr + 1) * - (rightEdgeErr + 1) == - 1, - "Choose to define either INTERFACE or both LEFTEDGE " - "and RIGHTEDGE.") + "Choose to define either INTERFACEEDGE or EDGE") + } + InterfaceShPtr interface; + if (interfaceType == "R") { std::string originStr; @@ -202,32 +181,42 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) NekDouble angularVel = stod(angularVelStr); - InterfaceShPtr rotatingInterface( - MemoryManager::AllocateSharedPtr( - rightDomain, leftDomain, origin, axis, angularVel)); - - if (interfaceErr == TIXML_SUCCESS) - { - rotatingInterface->SetInterfaceEdge(interfaceEdge); - } - else - { - rotatingInterface->SetEdgeRight(rightEdge); - rotatingInterface->SetEdgeLeft(leftEdge); - } + interface = RotatingInterfaceShPtr(MemoryManager::AllocateSharedPtr(domain, origin, axis, angularVel)); + } + else if (interfaceType == "F") + { + interface = FixedInterfaceShPtr(MemoryManager::AllocateSharedPtr(domain)); + } - m_interfaces[indx] = rotatingInterface; + if (interfaceErr == TIXML_SUCCESS) + { + interface->SetInterfaceEdge(interfaceEdge); + } + else + { + interface->SetEdge(domainEdge); } + tmpInterfaceMap[indx].emplace_back(interface); + interfaceElement = interfaceElement->NextSiblingElement(); } + + for (auto interfacePair : tmpInterfaceMap) + { + ASSERTL0(interfacePair.second.size() == 2, "Every interface ID must have two domains associated with it") + + m_interfaces[interfacePair.first] = std::make_pair( + interfacePair.second[0], interfacePair.second[1]); + } } -void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) +void Interfaces::SeparateGraph(MeshGraphSharedPtr &graph, int indx) { - - auto rightDomain = GetRightDomain(); - auto interfaceEdge = GetInterfaceEdge(); + auto &keepInterface = m_interfaces[indx].first; + auto &changeInterface = m_interfaces[indx].second; + auto rightDomain = changeInterface->GetDomain(); + auto interfaceEdge = changeInterface->GetInterfaceEdge(); int maxVertId = -1; for (auto &vert : graph->GetAllPointGeoms()) @@ -312,8 +301,8 @@ void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) graph->GetAllSegGeoms()[maxEdgeId] = newEdge; edgeDone[geom->GetGlobalID()] = newEdge; - m_leftEdge[oldEdge->GetGlobalID()] = oldEdge; - m_rightEdge[maxEdgeId] = newEdge; + keepInterface->SetEdge(oldEdge); + changeInterface->SetEdge(newEdge); maxEdgeId++; auto toProcess = GetElementsFromVertex(rightDomain, vid[0], vid[1]); @@ -399,7 +388,8 @@ void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) // Replace this geometry in any composites. for (auto &comp : graph->GetComposites()) { - for (int n = 0; n < comp.second->m_geomVec.size(); ++n) + auto tmp = comp.second->m_geomVec.size(); + for (int n = 0; n < tmp; ++n) { if (comp.second->m_geomVec[n]->GetGlobalID() == newGeom->GetGlobalID() && @@ -464,58 +454,36 @@ void InterfaceBase::SeparateGraph(MeshGraphSharedPtr &graph) } }; -void InterfaceBase::SetEdgeLeft(const CompositeMap &leftEdge) +void InterfaceBase::SetEdge(const CompositeMap &edge) { - for (auto &compIt : leftEdge) + for (auto &compIt : edge) { for (auto &elmtIt : compIt.second->m_geomVec) { SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); ASSERTL0(elmt, "Composite for left edge should only contain segments"); - m_leftEdge[elmt->GetGlobalID()] = elmt; - } - } -} - -void InterfaceBase::SetEdgeRight(const CompositeMap &rightEdge) -{ - for (auto &compIt : rightEdge) - { - for (auto &elmtIt : compIt.second->m_geomVec) - { - SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); - ASSERTL0(elmt, - "Composite for right edge should only contain segments"); - m_rightEdge[elmt->GetGlobalID()] = elmt; + m_edge[elmt->GetGlobalID()] = elmt; } } } void InterfaceBase::FillInterfaceBoundingBoxTree() { - if (m_boundingInterfaceRight.empty()) - { - for (auto &x : m_rightEdge) - { - BgBox b = x.second->GetBoundingBox(); - m_boundingInterfaceRight.insert(std::make_pair(b, x.first)); - } - } - if (m_boundingInterfaceLeft.empty()) + if (m_boundingInterface.empty()) { - for (auto &x : m_leftEdge) + for (auto &x : m_edge) { BgBox b = x.second->GetBoundingBox(); - m_boundingInterfaceLeft.insert(std::make_pair(b, x.first)); + m_boundingInterface.insert(std::make_pair(b, x.first)); } } } -std::vector InterfaceBase::GetLeftEdgesContainingPoint( - NekDouble x, NekDouble y, NekDouble z) +std::vector InterfaceBase::GetEdgesContainingPoint(NekDouble x, + NekDouble y, NekDouble z) { - if (m_boundingInterfaceLeft.empty()) + if (m_boundingInterface.empty()) { FillInterfaceBoundingBoxTree(); } @@ -524,28 +492,10 @@ std::vector InterfaceBase::GetLeftEdgesContainingPoint( BgBox b(BgPoint(x, y, z), BgPoint(x, y, z)); - m_boundingInterfaceLeft.query(bg::index::intersects(b), + m_boundingInterface.query(bg::index::intersects(b), std::back_inserter(vals)); return vals; } - -std::vector InterfaceBase::GetRightEdgesContainingPoint( - NekDouble x, NekDouble y, NekDouble z) -{ - if (m_boundingInterfaceRight.empty()) - { - FillInterfaceBoundingBoxTree(); - } - - std::vector vals; - - BgBox b(BgPoint(x, y, z), BgPoint(x, y, z)); - - m_boundingInterfaceRight.query(bg::index::intersects(b), - std::back_inserter(vals)); - - return vals; } -} // namespace SpatialDomains -} // namespace Nektar +} diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index e471d7242..57ab1eef5 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -41,7 +41,6 @@ #include #include -#include namespace Nektar { @@ -58,28 +57,24 @@ enum InterfaceType const char *const InterfaceTypeMap[] = {"Fixed", "Rotating", "Sliding"}; +struct Composite; +typedef std::map> CompositeMap; + struct InterfaceBase { - InterfaceBase(InterfaceType type, CompositeMap rightDomain, - CompositeMap leftDomain) - : m_interfaceType(type), m_rightDomain(rightDomain), - m_leftDomain(leftDomain) + InterfaceBase(InterfaceType type, CompositeMap domain) + : m_type(type), m_domain(domain) { } InterfaceType GetInterfaceType() const { - return m_interfaceType; - } - - CompositeMap GetRightDomain() const - { - return m_rightDomain; + return m_type; } - CompositeMap GetLeftDomain() const + CompositeMap GetDomain() const { - return m_leftDomain; + return m_domain; } CompositeMap GetInterfaceEdge() const @@ -92,60 +87,37 @@ struct InterfaceBase m_interfaceEdge = interfaceEdge; } - std::map const &GetEdgeLeft() const - { - return m_leftEdge; - } - - void SetEdgeLeft(const std::map &leftEdge) - { - m_leftEdge = leftEdge; - } - - void SetEdgeLeft(const CompositeMap &leftEdge); - - std::map const &GetEdgeRight() const + std::map const &GetEdge() const { - return m_rightEdge; + return m_edge; } - void SetEdgeRight(const std::map &rightEdge) + void SetEdge(const SegGeomSharedPtr &edge) { - m_rightEdge = rightEdge; + m_edge[edge->GetGlobalID()] = edge; } - void SetEdgeRight(const CompositeMap &rightEdge); - - void SeparateGraph(MeshGraphSharedPtr &graph); + void SetEdge(const CompositeMap &edge); void FillInterfaceBoundingBoxTree(); - std::vector GetLeftEdgesContainingPoint(NekDouble x, - NekDouble y, + std::vector GetEdgesContainingPoint(NekDouble x, NekDouble y, NekDouble z); - std::vector GetRightEdgesContainingPoint(NekDouble x, - NekDouble y, - NekDouble z); - protected: - InterfaceType m_interfaceType; - CompositeMap m_rightDomain; - CompositeMap m_leftDomain; - std::map m_leftEdge; - std::map m_rightEdge; + InterfaceType m_type; + CompositeMap m_domain; + std::map m_edge; CompositeMap m_interfaceEdge; - BgRtree m_boundingInterfaceLeft; - BgRtree m_boundingInterfaceRight; + BgRtree m_boundingInterface; }; struct RotatingInterface : public InterfaceBase { - RotatingInterface(const CompositeMap rightDomain, - const CompositeMap leftDomain, const PointGeom origin, + RotatingInterface(const CompositeMap domain, const PointGeom origin, const std::vector axis, const NekDouble angularVel) - : InterfaceBase(eRotating, rightDomain, leftDomain), m_origin(origin), + : InterfaceBase(eRotating, domain), m_origin(origin), m_axis(axis), m_angularVel(angularVel) { } @@ -171,9 +143,19 @@ protected: NekDouble m_angularVel; }; +struct FixedInterface : public InterfaceBase +{ + FixedInterface(const CompositeMap domain) + : InterfaceBase(eFixed, domain) + { + } +}; + typedef std::shared_ptr InterfaceShPtr; typedef std::shared_ptr RotatingInterfaceShPtr; -typedef std::map InterfaceCollection; +typedef std::shared_ptr FixedInterfaceShPtr; + +typedef std::map> InterfaceCollection; class Interfaces { @@ -189,11 +171,12 @@ public: return m_interfaces; } + void SeparateGraph(MeshGraphSharedPtr &graph, int indx); + protected: /// The mesh graph to use for referencing geometry info. MeshGraphSharedPtr m_meshGraph; LibUtilities::SessionReaderSharedPtr m_session; - InterfaceCollection m_interfaces; private: diff --git a/library/SpatialDomains/MeshGraph.cpp b/library/SpatialDomains/MeshGraph.cpp index a24c12896..4531f60ec 100644 --- a/library/SpatialDomains/MeshGraph.cpp +++ b/library/SpatialDomains/MeshGraph.cpp @@ -2608,6 +2608,9 @@ std::string MeshGraph::GetCompositeString(CompositeSharedPtr comp) void MeshGraph::ReadExpansions() { + // Hack? + m_expansionMapShPtrMap.clear(); + // Find the Expansions tag TiXmlElement *expansionTypes = m_session->GetElement("NEKTAR/EXPANSIONS"); ASSERTL0(expansionTypes, "Unable to find EXPANSIONS tag in file."); diff --git a/library/SpatialDomains/MeshGraphXml.cpp b/library/SpatialDomains/MeshGraphXml.cpp index 7e05b7b2e..906c86502 100644 --- a/library/SpatialDomains/MeshGraphXml.cpp +++ b/library/SpatialDomains/MeshGraphXml.cpp @@ -439,6 +439,8 @@ void MeshGraphXml::ReadGeometry( ReadComposites(); ReadDomain(); + + if (fillGraph) { MeshGraph::FillGraph(); -- GitLab From 95b06404a7dac3519d1ec302cea995587f7d1210 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 18 Jun 2019 16:45:04 +0100 Subject: [PATCH 038/408] Further generalisation in DisContField2D --- library/MultiRegions/DisContField2D.cpp | 60 +++++++++++++++---------- library/MultiRegions/DisContField2D.h | 17 +++---- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 0107c06ae..62a64f866 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -441,9 +441,11 @@ void DisContField2D::SetUpDG(const std::string variable) // Loop over all interface edges and then negate edge normals // corresponding to the 'moving' side. Keep track of both interior - // and exterior interface components. + // and exterior interface components. Setup cache flag. for (auto &interface : m_interfaces) { + const int indx = interface.first; + for (auto &iter : interface.second.second->GetEdge()) { int id = iter.first; @@ -451,8 +453,8 @@ void DisContField2D::SetUpDG(const std::string variable) m_trace->GetExp(traceIdToElmt[id])); traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( traceEl->GetLeftAdjacentElementEdge()); - m_traceEdgeRight[interface.first][id] = traceEl; - m_interfaceEdgeRight.insert(id); + m_traceEdgeRight[indx][id] = traceEl; + m_interfaceEdge.second.insert(id); } for (auto &iter : interface.second.first->GetEdge()) @@ -460,9 +462,11 @@ void DisContField2D::SetUpDG(const std::string variable) int id = iter.first; auto traceEl = std::dynamic_pointer_cast( m_trace->GetExp(traceIdToElmt[id])); - m_traceEdgeLeft[interface.first][id] = traceEl; - m_interfaceEdgeLeft.insert(id); + m_traceEdgeLeft[indx][id] = traceEl; + m_interfaceEdge.first.insert(id); } + + m_interfaceCacheFlag[indx] = make_pair(false, false); } int cnt, n, e; @@ -1262,15 +1266,15 @@ bool DisContField2D::IsLeftAdjacentEdge(const int n, const int e) int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); auto pIt = m_periodicEdges.find(traceGeomId); auto intIt1 = - m_interfaceEdgeLeft.find(traceEl->GetGeom()->GetGlobalID()); + m_interfaceEdge.first.find(traceEl->GetGeom()->GetGlobalID()); auto intIt2 = - m_interfaceEdgeRight.find(traceEl->GetGeom()->GetGlobalID()); + m_interfaceEdge.second.find(traceEl->GetGeom()->GetGlobalID()); - if (intIt1 != m_interfaceEdgeLeft.end()) + if (intIt1 != m_interfaceEdge.first.end()) { fwd = true; } - else if (intIt2 != m_interfaceEdgeRight.end()) + else if (intIt2 != m_interfaceEdge.second.end()) { fwd = false; } @@ -1452,11 +1456,13 @@ void DisContField2D::v_GetFwdBwdTracePhys( // Edge two -> one interpolation for (auto &interface : m_traceEdgeLeft) { - int cnt = 0; - auto &mapCache = m_rightToLeftMap[interface.first]; - auto &traceEdgeCache = m_traceEdgeRight[interface.first]; - auto &interfacesCache = m_interfaces[interface.first]; + const int indx = interface.first; + auto &mapCache = m_edgeCacheMap[indx].first; + auto &traceEdgeCache = m_traceEdgeRight[indx]; + auto &interfacesCache = m_interfaces[indx].second; + bool flag = m_interfaceCacheFlag[indx].first; + int cnt = 0; for (auto edges : interface.second) { auto elmt = edges.second; @@ -1468,7 +1474,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( NekDouble foundPoint; LocalRegions::Expansion1DSharedPtr geom; - if (m_interfaceCacheFlag) + if (flag) { auto tmp = mapCache[cnt]; foundPoint = tmp.second; @@ -1480,7 +1486,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); NekDouble zero = 0.0; - auto BgRtree = interfacesCache.second-> + auto BgRtree = interfacesCache-> GetEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { @@ -1516,16 +1522,22 @@ void DisContField2D::v_GetFwdBwdTracePhys( StdPhysEvaluate(foundPointArray, edgePhys); } } + + //Flag that cache has been created + m_interfaceCacheFlag[indx].first = true; + } // Edge one -> two interpolation for (auto &interface : m_traceEdgeRight) { - int cnt = 0; - auto &mapCache = m_leftToRightMap[interface.first]; - auto &traceEdgeCache = m_traceEdgeLeft[interface.first]; - auto &interfacesCache = m_interfaces[interface.first]; + const int indx = interface.first; + auto &mapCache = m_edgeCacheMap[indx].second; + auto &traceEdgeCache = m_traceEdgeLeft[indx]; + auto &interfacesCache = m_interfaces[indx].first; + bool flag = m_interfaceCacheFlag[indx].second; + int cnt = 0; for (auto edges : interface.second) { auto elmt = edges.second; @@ -1537,7 +1549,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( NekDouble foundPoint; LocalRegions::Expansion1DSharedPtr geom; - if (m_interfaceCacheFlag) + if (flag) { auto tmp = mapCache[cnt]; foundPoint = tmp.second; @@ -1549,7 +1561,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( Array xc(nq), yc(nq); elmt->GetCoords(xc, yc); NekDouble zero = 0.0; - auto BgRtree = interfacesCache.first-> + auto BgRtree = interfacesCache-> GetEdgesContainingPoint(xc[i], yc[i], zero); for (auto boundaryBoxElement : BgRtree) { @@ -1585,10 +1597,12 @@ void DisContField2D::v_GetFwdBwdTracePhys( StdPhysEvaluate(foundPointArray, edgePhys); } } + + //Flag that cache has been created + m_interfaceCacheFlag[indx].second = true; + } - //Flag that cache has been created - m_interfaceCacheFlag = true; // Do parallel exchange for forwards/backwards spaces. m_traceMap->UniversalTraceAssemble(Fwd); diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 0461043c6..91c25fe1d 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -147,19 +147,20 @@ namespace Nektar */ Array m_bndConditions; + //typedef std::map TraceEdge; + //std::map> m_traceEdge; std::map> m_traceEdgeLeft; std::map> m_traceEdgeRight; - std::unordered_set m_interfaceEdgeLeft, m_interfaceEdgeRight; - // first key is interface ID; contains a vector with each quadrature point - // in the left hand side of seg ID and local coordinate found - typedef std::map>> EdgeCacheMap; - EdgeCacheMap m_rightToLeftMap; - EdgeCacheMap m_leftToRightMap; + std::pair,std::unordered_set> m_interfaceEdge; - //Flag true if interface cache has been created - bool m_interfaceCacheFlag = false; + // first key is interface ID; contains a pair of vectors with each + // quadrature point giving seg ID and local coordinate found + typedef std::vector> EdgeCacheMap; + std::map> m_edgeCacheMap; + //Flag true if interface cache has been created + std::map> m_interfaceCacheFlag; GlobalLinSysMapShPtr m_globalBndMat; ExpListSharedPtr m_trace; -- GitLab From dbeb9b38a894ce957e70507aef573fba7f82a8b4 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 20 Jun 2019 11:48:54 +0100 Subject: [PATCH 039/408] DisContField2D generalised interpolation loop --- library/MultiRegions/DisContField2D.cpp | 200 +++++++++--------------- library/MultiRegions/DisContField2D.h | 6 +- 2 files changed, 75 insertions(+), 131 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 62a64f866..3b02c6b84 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1453,157 +1453,101 @@ void DisContField2D::v_GetFwdBwdTracePhys( } // Interpolate from each side of the interface to the other. - // Edge two -> one interpolation - for (auto &interface : m_traceEdgeLeft) + for (n = 0; n < 2; ++n) { - const int indx = interface.first; - auto &mapCache = m_edgeCacheMap[indx].first; - auto &traceEdgeCache = m_traceEdgeRight[indx]; - auto &interfacesCache = m_interfaces[indx].second; - bool flag = m_interfaceCacheFlag[indx].first; + auto &traceEdge = (n == 0 ? m_traceEdgeLeft : m_traceEdgeRight); - int cnt = 0; - for (auto edges : interface.second) + for (auto &interface : traceEdge) { - auto elmt = edges.second; - int nq = elmt->GetTotPoints(); - - for (int i = 0; i < nq; ++i, ++cnt) + const int indx = interface.first; + bool &flag = (n == 0 ? m_interfaceCacheFlag[indx].first : m_interfaceCacheFlag[indx].second); + auto &mapCache= (n == 0 ? m_edgeCacheMap[indx].first : m_edgeCacheMap[indx].second); + auto &traceEdgeCache = (n == 0 ? m_traceEdgeRight[indx] : m_traceEdgeLeft[indx]); + auto &interfacesCache = (n == 0 ? m_interfaces[indx].second : m_interfaces[indx].first); + + int cnt = 0; + for (auto edges : interface.second) { - bool found = false; - NekDouble foundPoint; - LocalRegions::Expansion1DSharedPtr geom; + auto elmt = edges.second; + int nq = elmt->GetTotPoints(); - if (flag) - { - auto tmp = mapCache[cnt]; - foundPoint = tmp.second; - geom = traceEdgeCache[tmp.first]; - found = true; - } - else + for (int i = 0; i < nq; ++i, ++cnt) { - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - NekDouble zero = 0.0; - auto BgRtree = interfacesCache-> - GetEdgesContainingPoint(xc[i], yc[i], zero); - for (auto boundaryBoxElement : BgRtree) - { - geom = traceEdgeCache[boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast(geom->GetGeom1D()); + bool found = false; + NekDouble foundPoint; + LocalRegions::Expansion1DSharedPtr geom; - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - - NekDouble dist = geomSeg->FindDistance(xs,foundPoint); - if (dist > 1e-8) - { - continue; - } - - mapCache.emplace_back(std::make_pair(geomSeg-> - GetGlobalID(), foundPoint)); + if (flag) + { + auto tmp = mapCache[cnt]; + foundPoint = tmp.second; + geom = traceEdgeCache[tmp.first]; found = true; - break; } - } - - ASSERTL0(found, "Couldn't interpolate across interface " - "from right to left (bwd)"); - - Array edgePhys = Bwd + m_trace-> - GetPhys_Offset(geom->GetElmtId()); - Array foundPointArray(1, foundPoint); - Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom-> - StdPhysEvaluate(foundPointArray, edgePhys); - } - } - - //Flag that cache has been created - m_interfaceCacheFlag[indx].first = true; - - } + else + { + Array xc(nq), yc(nq); + elmt->GetCoords(xc, yc); + NekDouble zero = 0.0; + auto BgRtree = interfacesCache-> + GetEdgesContainingPoint(xc[i], yc[i], zero); + for (auto boundaryBoxElement : BgRtree) + { + geom = traceEdgeCache[boundaryBoxElement.second]; + SpatialDomains::SegGeomSharedPtr geomSeg = + std::static_pointer_cast(geom->GetGeom1D()); - // Edge one -> two interpolation - for (auto &interface : m_traceEdgeRight) - { - const int indx = interface.first; - auto &mapCache = m_edgeCacheMap[indx].second; - auto &traceEdgeCache = m_traceEdgeLeft[indx]; - auto &interfacesCache = m_interfaces[indx].first; - bool flag = m_interfaceCacheFlag[indx].second; + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; - int cnt = 0; - for (auto edges : interface.second) - { - auto elmt = edges.second; - int nq = elmt->GetTotPoints(); + NekDouble dist = geomSeg->FindDistance(xs,foundPoint); + if (dist > 1e-8) + { + continue; + } - for (int i = 0; i < nq; ++i, ++cnt) - { - bool found = false; - NekDouble foundPoint; - LocalRegions::Expansion1DSharedPtr geom; + mapCache.emplace_back(std::make_pair(geomSeg-> + GetGlobalID(), foundPoint)); + found = true; + break; + } + } - if (flag) - { - auto tmp = mapCache[cnt]; - foundPoint = tmp.second; - geom = traceEdgeCache[tmp.first]; - found = true; - } - else - { - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - NekDouble zero = 0.0; - auto BgRtree = interfacesCache-> - GetEdgesContainingPoint(xc[i], yc[i], zero); - for (auto boundaryBoxElement : BgRtree) + if (n == 0) { - geom = traceEdgeCache[boundaryBoxElement.second]; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast(geom->GetGeom1D()); - - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - NekDouble dist = geomSeg->FindDistance(xs,foundPoint); - if (dist > 1e-8) - { - continue; - } + ASSERTL0(found, "Couldn't interpolate across interface " + "from right to left (bwd)"); - mapCache.emplace_back(std::make_pair(geomSeg-> - GetGlobalID(), foundPoint)); - found = true; - break; + Array edgePhys = Bwd + m_trace-> + GetPhys_Offset(geom->GetElmtId()); + Array foundPointArray(1, foundPoint); + Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + + i] = geom-> + StdPhysEvaluate(foundPointArray, edgePhys); + } + else + { + ASSERTL0(found, "Couldn't interpolate across interface " + "from left to right (fwd)"); + + Array edgePhys = Fwd + m_trace-> + GetPhys_Offset(geom->GetElmtId()); + Array foundPointArray(1, foundPoint); + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom-> + StdPhysEvaluate(foundPointArray, edgePhys); } } - - ASSERTL0(found, "Couldn't interpolate across interface " - "from left to right (fwd)"); - - Array edgePhys = Fwd + m_trace-> - GetPhys_Offset(geom->GetElmtId()); - Array foundPointArray(1, foundPoint); - Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom-> - StdPhysEvaluate(foundPointArray, edgePhys); } - } - //Flag that cache has been created - m_interfaceCacheFlag[indx].second = true; + //Flag that cache has been created + flag = true; + } } - // Do parallel exchange for forwards/backwards spaces. m_traceMap->UniversalTraceAssemble(Fwd); m_traceMap->UniversalTraceAssemble(Bwd); diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 91c25fe1d..b2c79e937 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -147,10 +147,10 @@ namespace Nektar */ Array m_bndConditions; - //typedef std::map TraceEdge; + typedef std::map TraceEdge; + std::map m_traceEdgeLeft; + std::map m_traceEdgeRight; //std::map> m_traceEdge; - std::map> m_traceEdgeLeft; - std::map> m_traceEdgeRight; std::pair,std::unordered_set> m_interfaceEdge; -- GitLab From 42830d6073b67b17d423ac5003ca0039927c8424 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 20 Jun 2019 12:07:53 +0100 Subject: [PATCH 040/408] m_traceEdge change left & right notation to pair --- library/MultiRegions/DisContField2D.cpp | 33 +++++++++++++++---------- library/MultiRegions/DisContField2D.h | 4 +-- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 3b02c6b84..65a9c73ee 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -453,7 +453,7 @@ void DisContField2D::SetUpDG(const std::string variable) m_trace->GetExp(traceIdToElmt[id])); traceEl->GetLeftAdjacentElementExp()->NegateEdgeNormal( traceEl->GetLeftAdjacentElementEdge()); - m_traceEdgeRight[indx][id] = traceEl; + m_traceEdge[indx].second[id] = traceEl; m_interfaceEdge.second.insert(id); } @@ -462,7 +462,7 @@ void DisContField2D::SetUpDG(const std::string variable) int id = iter.first; auto traceEl = std::dynamic_pointer_cast( m_trace->GetExp(traceIdToElmt[id])); - m_traceEdgeLeft[indx][id] = traceEl; + m_traceEdge[indx].first[id] = traceEl; m_interfaceEdge.first.insert(id); } @@ -1455,18 +1455,22 @@ void DisContField2D::v_GetFwdBwdTracePhys( // Interpolate from each side of the interface to the other. for (n = 0; n < 2; ++n) { - auto &traceEdge = (n == 0 ? m_traceEdgeLeft : m_traceEdgeRight); - - for (auto &interface : traceEdge) + for (auto &interface : m_traceEdge) { const int indx = interface.first; - bool &flag = (n == 0 ? m_interfaceCacheFlag[indx].first : m_interfaceCacheFlag[indx].second); - auto &mapCache= (n == 0 ? m_edgeCacheMap[indx].first : m_edgeCacheMap[indx].second); - auto &traceEdgeCache = (n == 0 ? m_traceEdgeRight[indx] : m_traceEdgeLeft[indx]); - auto &interfacesCache = (n == 0 ? m_interfaces[indx].second : m_interfaces[indx].first); + auto &traceEdge = (n == 0 ? interface.second.first + : interface.second.second); + auto &traceEdgeCache (n == 0 ? interface.second.second + : interface.second.first); + bool &flag = (n == 0 ? m_interfaceCacheFlag[indx].first + : m_interfaceCacheFlag[indx].second); + auto &mapCache = (n == 0 ? m_edgeCacheMap[indx].first + : m_edgeCacheMap[indx].second); + auto &interfacesCache = (n == 0 ? m_interfaces[indx].second + : m_interfaces[indx].first); int cnt = 0; - for (auto edges : interface.second) + for (auto edges : traceEdge) { auto elmt = edges.second; int nq = elmt->GetTotPoints(); @@ -1495,14 +1499,16 @@ void DisContField2D::v_GetFwdBwdTracePhys( { geom = traceEdgeCache[boundaryBoxElement.second]; SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast(geom->GetGeom1D()); + std::static_pointer_cast( + geom->GetGeom1D()); Array xs(3); xs[0] = xc[i]; xs[1] = yc[i]; xs[2] = 0; - NekDouble dist = geomSeg->FindDistance(xs,foundPoint); + NekDouble dist = geomSeg->FindDistance(xs, + foundPoint); if (dist > 1e-8) { continue; @@ -1536,7 +1542,8 @@ void DisContField2D::v_GetFwdBwdTracePhys( Array edgePhys = Fwd + m_trace-> GetPhys_Offset(geom->GetElmtId()); Array foundPointArray(1, foundPoint); - Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + i] = geom-> + Fwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) + + i] = geom-> StdPhysEvaluate(foundPointArray, edgePhys); } } diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index b2c79e937..02e89cb3d 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -148,9 +148,7 @@ namespace Nektar Array m_bndConditions; typedef std::map TraceEdge; - std::map m_traceEdgeLeft; - std::map m_traceEdgeRight; - //std::map> m_traceEdge; + std::map> m_traceEdge; std::pair,std::unordered_set> m_interfaceEdge; -- GitLab From 8e4089dbee66892374e9837fca738ccc507f1fe0 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 20 Jun 2019 12:11:54 +0100 Subject: [PATCH 041/408] Fix equals --- library/MultiRegions/DisContField2D.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 65a9c73ee..74d1b8ff8 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1460,8 +1460,8 @@ void DisContField2D::v_GetFwdBwdTracePhys( const int indx = interface.first; auto &traceEdge = (n == 0 ? interface.second.first : interface.second.second); - auto &traceEdgeCache (n == 0 ? interface.second.second - : interface.second.first); + auto &traceEdgeCache = (n == 0 ? interface.second.second + : interface.second.first); bool &flag = (n == 0 ? m_interfaceCacheFlag[indx].first : m_interfaceCacheFlag[indx].second); auto &mapCache = (n == 0 ? m_edgeCacheMap[indx].first @@ -1551,7 +1551,6 @@ void DisContField2D::v_GetFwdBwdTracePhys( //Flag that cache has been created flag = true; - } } -- GitLab From d3b8061ff3ed9992f83bbc51452f354e1e5f6f2f Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 6 Aug 2019 13:15:12 +0100 Subject: [PATCH 042/408] remove blocked routine --- library/MultiRegions/DisContField2D.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 74d1b8ff8..e1a151875 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1351,7 +1351,7 @@ void DisContField2D::v_GetFwdBwdTracePhys( // Basis definition on each element LibUtilities::BasisSharedPtr basis = (*m_exp)[0]->GetBasis(0); - if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange && false) + if (basis->GetBasisType() != LibUtilities::eGauss_Lagrange) { // blocked routine Array edgevals( -- GitLab From 91873a4c2be3b433db0982d365c76f8da47d6f22 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 1 Jun 2020 14:47:42 +0100 Subject: [PATCH 043/408] Interface pair object --- library/MultiRegions/DisContField2D.cpp | 6 ++-- library/MultiRegions/ExpList2D.cpp | 15 ++++---- library/MultiRegions/ExpList2D.h | 2 +- library/SpatialDomains/Interface.cpp | 32 ++++++++++------- library/SpatialDomains/Interface.h | 47 ++++++++++++++++++++----- 5 files changed, 69 insertions(+), 33 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index a8e9f9096..8ec500dc6 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -454,11 +454,11 @@ namespace Nektar traceIdToElmt[traceGeomId] = i; } - for (auto &interface : m_interfaces) + for (auto &interface : m_interfaces->GetInterfaces()) { const int indx = interface.first; - for (auto &iter : interface.second.second->GetEdge()) + for (auto &iter : interface.second->GetRightInterface()->GetEdge()) { int id = iter.first; auto traceEl = std::dynamic_pointer_cast( @@ -467,7 +467,7 @@ namespace Nektar m_interfaceEdge.second.insert(id); } - for (auto &iter : interface.second.first->GetEdge()) + for (auto &iter : interface.second->GetLeftInterface()->GetEdge()) { int id = iter.first; auto traceEl = std::dynamic_pointer_cast( diff --git a/library/MultiRegions/ExpList2D.cpp b/library/MultiRegions/ExpList2D.cpp index b38d890bb..c55fc8f2a 100644 --- a/library/MultiRegions/ExpList2D.cpp +++ b/library/MultiRegions/ExpList2D.cpp @@ -136,18 +136,19 @@ namespace Nektar SetExpType(e2D); // Split up our mesh graph along interfaces if necessary. - SpatialDomains::Interfaces interfaceCollection(m_session, m_graph); - m_interfaces = interfaceCollection.GetInterfaces(); - for (auto &inter : m_interfaces) + m_interfaces = MemoryManager::AllocateSharedPtr(m_session, m_graph); + for (auto &inter : m_interfaces->GetInterfaces()) { - if (inter.second.second->GetEdge().empty()) + auto interfacePair = inter.second; + if (interfacePair->GetRightInterface()->GetEdge().empty()) { - interfaceCollection.SeparateGraph(m_graph, inter.first); + interfacePair->SeparateGraph(m_graph); } } - std::string filename = "out.xml"; - m_graph->WriteGeometry(filename, true); // Write split geometry to use when creating VTU + // Write split geometry to use when creating VTU + std::string filename = m_session->GetSessionName() + "_split.xml"; + m_graph->WriteGeometry(filename, true); // Re-read expansion maps to break our expansions appropriately! m_graph->ReadExpansions(); diff --git a/library/MultiRegions/ExpList2D.h b/library/MultiRegions/ExpList2D.h index e583dff77..15cd6d7ae 100644 --- a/library/MultiRegions/ExpList2D.h +++ b/library/MultiRegions/ExpList2D.h @@ -133,7 +133,7 @@ namespace Nektar MULTI_REGIONS_EXPORT virtual ~ExpList2D(); protected: - SpatialDomains::InterfaceCollection m_interfaces; + SpatialDomains::InterfacesSharedPtr m_interfaces; /// Upwind the \a Fwd and \a Bwd states based on the one- /// dimensional normal velocity field given by \a Vn. diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 387e78331..2814a3841 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -103,7 +103,7 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) TiXmlElement *interfaceElement = interfaces->FirstChildElement(); - std::map> tmpInterfaceMap; + std::map> tmpInterfaceMap; while (interfaceElement) { @@ -156,7 +156,7 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) } - InterfaceShPtr interface; + InterfaceBaseShPtr interface; if (interfaceType == "R") { @@ -204,19 +204,19 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) for (auto interfacePair : tmpInterfaceMap) { - ASSERTL0(interfacePair.second.size() == 2, "Every interface ID must have two domains associated with it") + ASSERTL0(interfacePair.second.size() == 2, + "Every interface ID must have two domains associated with it") - m_interfaces[interfacePair.first] = std::make_pair( - interfacePair.second[0], interfacePair.second[1]); + m_interfaces[interfacePair.first] = + MemoryManager::AllocateSharedPtr( + interfacePair.second[0], interfacePair.second[1]); } } -void Interfaces::SeparateGraph(MeshGraphSharedPtr &graph, int indx) +void InterfacePair::SeparateGraph(MeshGraphSharedPtr &graph) { - auto &keepInterface = m_interfaces[indx].first; - auto &changeInterface = m_interfaces[indx].second; - auto rightDomain = changeInterface->GetDomain(); - auto interfaceEdge = changeInterface->GetInterfaceEdge(); + auto rightDomain = m_rightInterface->GetDomain(); + auto interfaceEdge = m_rightInterface->GetInterfaceEdge(); int maxVertId = -1; for (auto &vert : graph->GetAllPointGeoms()) @@ -301,8 +301,8 @@ void Interfaces::SeparateGraph(MeshGraphSharedPtr &graph, int indx) graph->GetAllSegGeoms()[maxEdgeId] = newEdge; edgeDone[geom->GetGlobalID()] = newEdge; - keepInterface->SetEdge(oldEdge); - changeInterface->SetEdge(newEdge); + m_leftInterface->SetEdge(oldEdge); + m_rightInterface->SetEdge(newEdge); maxEdgeId++; auto toProcess = GetElementsFromVertex(rightDomain, vid[0], vid[1]); @@ -452,7 +452,7 @@ void Interfaces::SeparateGraph(MeshGraphSharedPtr &graph, int indx) #endif } -}; +} void InterfaceBase::SetEdge(const CompositeMap &edge) { @@ -468,5 +468,11 @@ void InterfaceBase::SetEdge(const CompositeMap &edge) } } +void Interfaces::CalculateOpposite() +{ + +} + + } } \ No newline at end of file diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index ec8abb9bf..01e6f0253 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -55,8 +55,6 @@ enum InterfaceType eSliding, }; -const char *const InterfaceTypeMap[] = {"Fixed", "Rotating", "Sliding"}; - struct Composite; typedef std::map> CompositeMap; @@ -108,8 +106,8 @@ protected: struct RotatingInterface : public InterfaceBase { - RotatingInterface(const CompositeMap domain, const PointGeom origin, - const std::vector axis, + RotatingInterface(const CompositeMap &domain, const PointGeom &origin, + const std::vector &axis, const NekDouble angularVel) : InterfaceBase(eRotating, domain), m_origin(origin), m_axis(axis), m_angularVel(angularVel) @@ -139,17 +137,46 @@ protected: struct FixedInterface : public InterfaceBase { - FixedInterface(const CompositeMap domain) + FixedInterface(const CompositeMap &domain) : InterfaceBase(eFixed, domain) { } }; -typedef std::shared_ptr InterfaceShPtr; +typedef std::shared_ptr InterfaceBaseShPtr; typedef std::shared_ptr RotatingInterfaceShPtr; typedef std::shared_ptr FixedInterfaceShPtr; -typedef std::map> InterfaceCollection; +struct InterfacePair +{ + InterfacePair(InterfaceBaseShPtr leftInterface, + InterfaceBaseShPtr rightInterface) + : m_leftInterface(leftInterface), + m_rightInterface(rightInterface) + { + } + + InterfaceBaseShPtr m_leftInterface; + InterfaceBaseShPtr m_rightInterface; + +public: + const InterfaceBaseShPtr &GetLeftInterface() const + { + return m_leftInterface; + } + + const InterfaceBaseShPtr &GetRightInterface() const + { + return m_rightInterface; + } + + void SeparateGraph(MeshGraphSharedPtr &graph); +}; + + +typedef std::shared_ptr InterfacePairShPtr; +typedef std::map InterfaceCollection; +typedef std::shared_ptr InterfaceCollectionShPtr; class Interfaces { @@ -160,12 +187,12 @@ public: SPATIAL_DOMAINS_EXPORT Interfaces() = default; - const InterfaceCollection &GetInterfaces(void) const + const InterfaceCollection &GetInterfaces() const { return m_interfaces; } - void SeparateGraph(MeshGraphSharedPtr &graph, int indx); + SPATIAL_DOMAINS_EXPORT void CalculateOpposite(); protected: /// The mesh graph to use for referencing geometry info. @@ -179,6 +206,8 @@ private: void ReadInterfaces(TiXmlElement *interfaceTag); }; +typedef std::shared_ptr InterfacesSharedPtr; + } // namespace SpatialDomains } // namespace Nektar -- GitLab From 062ae68ae808e64a4abdfda631119a112b49ca8e Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 2 Jun 2020 12:37:19 +0100 Subject: [PATCH 044/408] Start of restructure for interpolation in DisContField --- library/MultiRegions/DisContField2D.cpp | 216 ++++++++++++++---------- library/MultiRegions/DisContField2D.h | 17 +- library/SpatialDomains/Interface.cpp | 15 +- library/SpatialDomains/Interface.h | 19 ++- 4 files changed, 161 insertions(+), 106 deletions(-) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 8ec500dc6..73af9fa6c 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -442,41 +442,11 @@ namespace Nektar // Set up physical normals SetUpPhysNormals(); - // Loop over all interface edges and keep track of both interior - // and exterior interface components. Setup cache flag. - - std::unordered_map traceIdToElmt; + // Loop over all trace edges and create a map from geom ID to + // position in the trace expansion for (int i = 0; i < m_trace->GetExpSize(); ++i) { - LocalRegions::Expansion1DSharedPtr traceEl = - m_trace->GetExp(i)->as(); - int traceGeomId = traceEl->GetGeom1D()->GetGlobalID(); - traceIdToElmt[traceGeomId] = i; - } - - for (auto &interface : m_interfaces->GetInterfaces()) - { - const int indx = interface.first; - - for (auto &iter : interface.second->GetRightInterface()->GetEdge()) - { - int id = iter.first; - auto traceEl = std::dynamic_pointer_cast( - m_trace->GetExp(traceIdToElmt[id])); - m_traceEdge[indx].second[id] = traceEl; - m_interfaceEdge.second.insert(id); - } - - for (auto &iter : interface.second->GetLeftInterface()->GetEdge()) - { - int id = iter.first; - auto traceEl = std::dynamic_pointer_cast( - m_trace->GetExp(traceIdToElmt[id])); - m_traceEdge[indx].first[id] = traceEl; - m_interfaceEdge.first.insert(id); - } - - m_interfaceCacheFlag[indx] = make_pair(false, false); + m_geomIdToTraceId[m_trace->GetExp(i)->GetGeom()->GetGlobalID()] = i; } int cnt, n, e; @@ -1400,63 +1370,50 @@ namespace Nektar DisContField2D::v_PeriodicBwdCopy(Fwd, Bwd); // Interpolate from each side of the interface to the other. - for (size_t n = 0; n < 2; ++n) - { - for (auto &interface : m_traceEdge) - { - auto &traceEdge = (n == 0 ? interface.second.first - : interface.second.second); - auto &traceEdgeCache = (n == 0 ? interface.second.second - : interface.second.first); - - int cnt = 0; - for (auto edges : traceEdge) - { - auto elmt = edges.second; - int nq = elmt->GetTotPoints(); - - for (int i = 0; i < nq; ++i, ++cnt) - { - bool found = false; - NekDouble foundPoint; - LocalRegions::Expansion1DSharedPtr geom; - Array xc(nq), yc(nq); - elmt->GetCoords(xc, yc); - NekDouble zero = 0.0; + CalcMatchLocalCoords(); - SpatialDomains::PointGeomSharedPtr pt = - std::make_shared(3, -1, xc[i], yc[i], zero); - - for (auto elem : traceEdgeCache) - { - geom = elem.second; - SpatialDomains::SegGeomSharedPtr geomSeg = - std::static_pointer_cast< - SpatialDomains::SegGeom>( - geom->GetGeom1D()); - - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - - NekDouble dist = - geomSeg->FindDistance(xs, foundPoint); - if (dist > 1e-8) - { - continue; - } + for (auto &interface : m_interfaces->GetInterfaces()) + { + size_t indx = interface.first; + auto pair = interface.second; - found = true; - break; - } + auto leftEdge = pair->GetLeftInterface()->GetEdgeIds(); + auto rightEdge = pair->GetRightInterface()->GetEdgeIds(); - ASSERTL0(found, "Couldn't interpolate across interface."); + size_t cnt = 0; + for (auto leftId : leftEdge) + { + size_t nq = m_trace->GetExp(m_geomIdToTraceId[leftId]) + ->GetTotPoints(); + for (size_t i = 0; i < nq; ++i) + { + Array edgePhys = + Fwd + m_trace->GetPhys_Offset( + m_locCoordSegIdPair[indx][cnt].second); + Array foundPointArray( + 1, m_locCoordSegIdPair[indx][cnt].first); + Bwd[m_trace->GetPhys_Offset( + m_geomIdToTraceId[leftId]) + i] = m_trace + ->GetExp(m_locCoordSegIdPair[indx][cnt++].second) + ->StdPhysEvaluate(foundPointArray, edgePhys); + } + } - Array edgePhys = Fwd + m_trace->GetPhys_Offset(geom->GetElmtId()); - Array foundPointArray(1, foundPoint); - Bwd[m_trace->GetPhys_Offset(elmt->GetElmtId()) +i] = geom->StdPhysEvaluate(foundPointArray, edgePhys); - } + for (auto rightId : rightEdge) + { + size_t nq = m_trace->GetExp(m_geomIdToTraceId[rightId]) + ->GetTotPoints(); + for (size_t i = 0; i < nq; ++i) + { + Array edgePhys = + Fwd + m_trace->GetPhys_Offset( + m_locCoordSegIdPair[indx][cnt].second); + Array foundPointArray( + 1, m_locCoordSegIdPair[indx][cnt].first); + Bwd[m_trace->GetPhys_Offset( + m_geomIdToTraceId[rightId]) + i] = m_trace + ->GetExp(m_locCoordSegIdPair[indx][cnt++].second) + ->StdPhysEvaluate(foundPointArray, edgePhys); } } } @@ -2594,5 +2551,92 @@ namespace Nektar } } } + + + std::pair CalcGlobPntToLocCoord( + const NekDouble &xc, + const NekDouble &yc, + const std::vector &searchIds, + const SpatialDomains::MeshGraphSharedPtr &graph, + const std::map &geomToTrace) + { + Array xs(3); + xs[0] = xc; + xs[1] = yc; + xs[2] = 0; + + int foundTraceId = -1; + NekDouble foundLocCoord; + bool found = false; + + for (auto id : searchIds) + { + SpatialDomains::SegGeomSharedPtr searchSeg = + std::static_pointer_cast(graph->GetSegGeom(id)); + NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); + + if (dist < 1e-8) + { + foundTraceId = geomToTrace.at(id); + //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; + found = true; + break; + } + } + + ASSERTL0(found, "Couldn't interpolate across interface."); + + return std::make_pair(foundLocCoord, foundTraceId); + } + + std::vector> CalcCoordsOneWay( + const std::vector &childEdge, + const std::vector &parentEdge, + const ExpListSharedPtr &trace, + const SpatialDomains::MeshGraphSharedPtr &graph, + const std::map &geomToTrace) + { + + std::vector> tmp; + for (auto childId : childEdge) + { + LocalRegions::ExpansionSharedPtr childElmt = trace->GetExp(geomToTrace.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq); + childElmt->GetCoords(xc, yc); + + for (int i = 0; i < nq; ++i) + { + std::pair found = + CalcGlobPntToLocCoord(xc[i], yc[i], parentEdge, graph, geomToTrace); + + tmp.emplace_back(found); + } + } + + return tmp; + } + + void DisContField2D::CalcMatchLocalCoords() + { + for (auto &interface : m_interfaces->GetInterfaces()) + { + size_t indx = interface.first; + auto pair = interface.second; + if (pair->GetCalcFlag()) + { + auto leftEdge = pair->GetLeftInterface()->GetEdgeIds(); + auto rightEdge = pair->GetRightInterface()->GetEdgeIds(); + + auto tmp = CalcCoordsOneWay(leftEdge, rightEdge, m_trace, m_graph, m_geomIdToTraceId); + auto tmp2 = CalcCoordsOneWay(rightEdge, leftEdge, m_trace, m_graph, m_geomIdToTraceId); + tmp.insert(tmp.end(), tmp2.begin(), tmp2.end()); + + m_locCoordSegIdPair[indx] = tmp; + pair->SetCalcFlag(false); + } + } + } + } // end of namespace } //end of namespace diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index ce9376646..1971241ac 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -162,18 +162,10 @@ namespace Nektar */ Array m_bndConditions; - typedef std::map TraceEdge; - std::map> m_traceEdge; - std::pair,std::unordered_set> m_interfaceEdge; - - // first key is interface ID; contains a pair of vectors with each - // quadrature point giving seg ID and local coordinate found - typedef std::vector> EdgeCacheMap; - std::map> m_edgeCacheMap; - - //Flag true if interface cache has been created - std::map> m_interfaceCacheFlag; + // Map taking a global geometry ID to the matching trace expansion ID + std::map m_geomIdToTraceId; + std::map>> m_locCoordSegIdPair; GlobalLinSysMapShPtr m_globalBndMat; ExpListSharedPtr m_trace; @@ -386,6 +378,8 @@ namespace Nektar inline virtual const LocTraceToTraceMapSharedPtr &v_GetLocTraceToTraceMap() const; + + void CalcMatchLocalCoords(); }; void DisContField2D::v_GetFwdBwdTracePhys( @@ -473,6 +467,7 @@ namespace Nektar } typedef std::shared_ptr DisContField2DSharedPtr; + } //end of namespace } //end of namespace diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 2814a3841..c76ae8053 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -461,18 +461,19 @@ void InterfaceBase::SetEdge(const CompositeMap &edge) for (auto &elmtIt : compIt.second->m_geomVec) { SegGeomSharedPtr elmt = std::dynamic_pointer_cast(elmtIt); + ASSERTL0(elmt, - "Composite for left edge should only contain segments"); - m_edge[elmt->GetGlobalID()] = elmt; + "Composite for edge on the interface should only contain " + "segments"); + + size_t id = elmt->GetGlobalID(); + m_edge[id] = elmt; + m_edgeIds.emplace_back(id); } } -} - -void Interfaces::CalculateOpposite() -{ + std::sort(m_edgeIds.begin(), m_edgeIds.end()); } - } } \ No newline at end of file diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 01e6f0253..8754d9649 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -90,6 +90,11 @@ struct InterfaceBase return m_edge; } + std::vector const &GetEdgeIds() const + { + return m_edgeIds; + } + void SetEdge(const SegGeomSharedPtr &edge) { m_edge[edge->GetGlobalID()] = edge; @@ -101,6 +106,7 @@ protected: InterfaceType m_type; CompositeMap m_domain; std::map m_edge; + std::vector m_edgeIds; CompositeMap m_interfaceEdge; }; @@ -158,6 +164,7 @@ struct InterfacePair InterfaceBaseShPtr m_leftInterface; InterfaceBaseShPtr m_rightInterface; + bool m_calcFlag = true; public: const InterfaceBaseShPtr &GetLeftInterface() const @@ -170,6 +177,16 @@ public: return m_rightInterface; } + bool GetCalcFlag() + { + return m_calcFlag; + } + + void SetCalcFlag(bool flag) + { + m_calcFlag = flag; + } + void SeparateGraph(MeshGraphSharedPtr &graph); }; @@ -192,8 +209,6 @@ public: return m_interfaces; } - SPATIAL_DOMAINS_EXPORT void CalculateOpposite(); - protected: /// The mesh graph to use for referencing geometry info. MeshGraphSharedPtr m_meshGraph; -- GitLab From f1831636cc360756f3e54996f5b4ec49e7763899 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 4 Jun 2020 15:21:02 +0100 Subject: [PATCH 045/408] Start of messy parallel attempt --- library/LibUtilities/Communication/Comm.h | 22 +++ .../LibUtilities/Communication/CommMpi.cpp | 8 + library/LibUtilities/Communication/CommMpi.h | 2 + .../LibUtilities/Communication/CommSerial.cpp | 6 + .../LibUtilities/Communication/CommSerial.h | 5 + .../AssemblyMap/AssemblyCommDG.cpp | 1 - library/MultiRegions/DisContField2D.cpp | 155 ++++++++++++------ library/MultiRegions/DisContField2D.h | 2 +- library/MultiRegions/ExpList.h | 3 + library/MultiRegions/ExpList2D.cpp | 2 +- library/MultiRegions/ExpList2D.h | 3 - library/SpatialDomains/Interface.cpp | 81 +++++++++ library/SpatialDomains/Interface.h | 62 +++++-- 13 files changed, 280 insertions(+), 72 deletions(-) diff --git a/library/LibUtilities/Communication/Comm.h b/library/LibUtilities/Communication/Comm.h index 8f1d9396b..8a3684cea 100644 --- a/library/LibUtilities/Communication/Comm.h +++ b/library/LibUtilities/Communication/Comm.h @@ -145,6 +145,9 @@ public: void Irsend(int pProc, T &pData, int count, const CommRequestSharedPtr &request, int loc); template + void Isend(int pProc, T &pData, int count, + const CommRequestSharedPtr &request, int loc); + template void SendInit(int pProc, T &pData, int count, const CommRequestSharedPtr &request, int loc); template @@ -232,6 +235,8 @@ protected: virtual void v_Irsend(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, int loc) = 0; + virtual void v_Isend(void *buf, int count, CommDataType dt, int dest, + CommRequestSharedPtr request, int loc) = 0; virtual void v_SendInit(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, int loc) = 0; virtual void v_Irecv(void *buf, int count, CommDataType dt, int source, @@ -595,6 +600,23 @@ void Comm::Irsend(int pProc, T &pData, int count, CommDataTypeTraits::GetDataType(), pProc, request, loc); } +/** + * Starts a nonblocking send + * + * @param pProc Rank of destination + * @param pData Array/vector to send + * @param count Number of elements to send in pData + * @param request Communication request object + * @param loc Location in request to use + */ +template +void Comm::Isend(int pProc, T &pData, int count, + const CommRequestSharedPtr &request, int loc) +{ + v_Irsend(CommDataTypeTraits::GetPointer(pData), count, + CommDataTypeTraits::GetDataType(), pProc, request, loc); +} + /** * Creates a persistent request for a send * diff --git a/library/LibUtilities/Communication/CommMpi.cpp b/library/LibUtilities/Communication/CommMpi.cpp index bd7233ec7..388659258 100644 --- a/library/LibUtilities/Communication/CommMpi.cpp +++ b/library/LibUtilities/Communication/CommMpi.cpp @@ -409,6 +409,14 @@ void CommMpi::v_Irsend(void *buf, int count, CommDataType dt, int dest, MPI_Irsend(buf, count, dt, dest, 0, m_comm, req->GetRequest(loc)); } +void CommMpi::v_Isend(void *buf, int count, CommDataType dt, int dest, + CommRequestSharedPtr request, int loc) +{ + CommRequestMpiSharedPtr req = + std::static_pointer_cast(request); + MPI_Isend(buf, count, dt, dest, 0, m_comm, req->GetRequest(loc)); +} + void CommMpi::v_SendInit(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, int loc) { diff --git a/library/LibUtilities/Communication/CommMpi.h b/library/LibUtilities/Communication/CommMpi.h index 69bec8c3f..951bfa72e 100644 --- a/library/LibUtilities/Communication/CommMpi.h +++ b/library/LibUtilities/Communication/CommMpi.h @@ -167,6 +167,8 @@ protected: CommDataType recvtype) final; virtual void v_Irsend(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, int loc) final; + virtual void v_Isend(void *buf, int count, CommDataType dt, int dest, + CommRequestSharedPtr request, int loc) final; virtual void v_SendInit(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, int loc) final; virtual void v_Irecv(void *buf, int count, CommDataType dt, int source, diff --git a/library/LibUtilities/Communication/CommSerial.cpp b/library/LibUtilities/Communication/CommSerial.cpp index e4e3f8a8e..7f28edc31 100644 --- a/library/LibUtilities/Communication/CommSerial.cpp +++ b/library/LibUtilities/Communication/CommSerial.cpp @@ -255,6 +255,12 @@ void CommSerial::v_Irsend(void *buf, int count, CommDataType dt, int dest, boost::ignore_unused(buf, count, dt, dest, request, loc); } +void CommSerial::v_Isend(void *buf, int count, CommDataType dt, int dest, + CommRequestSharedPtr request, int loc) +{ + boost::ignore_unused(buf, count, dt, dest, request, loc); +} + void CommSerial::v_SendInit(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, int loc) { diff --git a/library/LibUtilities/Communication/CommSerial.h b/library/LibUtilities/Communication/CommSerial.h index 6adec3774..9298cdecb 100644 --- a/library/LibUtilities/Communication/CommSerial.h +++ b/library/LibUtilities/Communication/CommSerial.h @@ -137,6 +137,11 @@ protected: CommRequestSharedPtr request, int loc) final; + LIB_UTILITIES_EXPORT virtual void v_Isend(void *buf, int count, + CommDataType dt, int dest, + CommRequestSharedPtr request, + int loc) final; + LIB_UTILITIES_EXPORT virtual void v_SendInit(void *buf, int count, CommDataType dt, int dest, CommRequestSharedPtr request, diff --git a/library/MultiRegions/AssemblyMap/AssemblyCommDG.cpp b/library/MultiRegions/AssemblyMap/AssemblyCommDG.cpp index 671980401..40742e98e 100644 --- a/library/MultiRegions/AssemblyMap/AssemblyCommDG.cpp +++ b/library/MultiRegions/AssemblyMap/AssemblyCommDG.cpp @@ -695,7 +695,6 @@ void AssemblyCommDG::InitialiseStructure( // Find what edge Ids match with other ranks size_t myRank = comm->GetRank(); - Array perTraceSend(m_nRanks, 0); for (size_t i = 0; i < m_nRanks; ++i) { if (i == myRank) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 73af9fa6c..8ab389acf 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -442,6 +442,7 @@ namespace Nektar // Set up physical normals SetUpPhysNormals(); + // ------ Setting up interfaces ------ // Loop over all trace edges and create a map from geom ID to // position in the trace expansion for (int i = 0; i < m_trace->GetExpSize(); ++i) @@ -449,6 +450,28 @@ namespace Nektar m_geomIdToTraceId[m_trace->GetExp(i)->GetGeom()->GetGlobalID()] = i; } + // Calculate total quadrature points on each interface edge + for (const auto &interface : m_interfaces->GetInterfaces()) + { + int tmp = 0; + auto leftInterface = interface.second->GetLeftInterface(); + for (auto id : leftInterface->GetEdgeIds()) + { + tmp += m_trace->GetExp(m_geomIdToTraceId[id])->GetTotPoints(); + } + leftInterface->SetTotPoints(tmp); + + tmp = 0; + auto rightInterface = interface.second->GetRightInterface(); + for (auto id : leftInterface->GetEdgeIds()) + { + tmp += m_trace->GetExp(m_geomIdToTraceId[id])->GetTotPoints(); + } + rightInterface->SetTotPoints(tmp); + } + + m_interfaces->CommSetup(m_comm); + int cnt, n, e; // Identify boundary edges @@ -1370,7 +1393,7 @@ namespace Nektar DisContField2D::v_PeriodicBwdCopy(Fwd, Bwd); // Interpolate from each side of the interface to the other. - CalcMatchLocalCoords(); + CalcLocalInterfaceCoords(); for (auto &interface : m_interfaces->GetInterfaces()) { @@ -2552,72 +2575,102 @@ namespace Nektar } } - - std::pair CalcGlobPntToLocCoord( - const NekDouble &xc, - const NekDouble &yc, - const std::vector &searchIds, + std::vector> CalcCoordsOneWay( + const SpatialDomains::InterfaceBaseShPtr &child, + const SpatialDomains::InterfaceBaseShPtr &parent, + const ExpListSharedPtr &trace, const SpatialDomains::MeshGraphSharedPtr &graph, - const std::map &geomToTrace) + const std::map &geomToTrace, + LibUtilities::CommSharedPtr &comm) { - Array xs(3); - xs[0] = xc; - xs[1] = yc; - xs[2] = 0; - - int foundTraceId = -1; - NekDouble foundLocCoord; - bool found = false; - for (auto id : searchIds) - { - SpatialDomains::SegGeomSharedPtr searchSeg = - std::static_pointer_cast(graph->GetSegGeom(id)); - NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); - - if (dist < 1e-8) - { - foundTraceId = geomToTrace.at(id); - //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; - found = true; - break; - } - } - - ASSERTL0(found, "Couldn't interpolate across interface."); - - return std::make_pair(foundLocCoord, foundTraceId); - } + int cnt = 0; + //Vector of quad point matching coords {local coord, edge ID, rank} + std::vector> tmp(child->GetTotPoints()); + std::map> missingCoords; - std::vector> CalcCoordsOneWay( - const std::vector &childEdge, - const std::vector &parentEdge, - const ExpListSharedPtr &trace, - const SpatialDomains::MeshGraphSharedPtr &graph, - const std::map &geomToTrace) - { + auto childEdge = child->GetEdgeIds(); + auto parentEdge = parent->GetEdgeIds(); - std::vector> tmp; for (auto childId : childEdge) { + int myRank = comm->GetRank(); + std::cout << "My rank: " << myRank << " child ID" << childId << std::endl; LocalRegions::ExpansionSharedPtr childElmt = trace->GetExp(geomToTrace.at(childId)); size_t nq = childElmt->GetTotPoints(); Array xc(nq), yc(nq); childElmt->GetCoords(xc, yc); + // Check local interface for (int i = 0; i < nq; ++i) { - std::pair found = - CalcGlobPntToLocCoord(xc[i], yc[i], parentEdge, graph, geomToTrace); + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + + bool found = false; + int foundTraceId = -1; + NekDouble foundLocCoord = -1; + + for (auto id : parentEdge) + { + SpatialDomains::SegGeomSharedPtr searchSeg = + std::static_pointer_cast(graph->GetSegGeom(id)); + NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); + + if (dist < 1e-8) + { + foundTraceId = geomToTrace.at(id); + //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; + found = true; + break; + } + } + + if(!found) + { + missingCoords[cnt] = xs; + } + + tmp[cnt] = std::make_tuple(foundLocCoord, foundTraceId, myRank); - tmp.emplace_back(found); + cnt++; } } + std::cout << "Couldn't find locally: "; + for (auto i : missingCoords) + { + std::cout << i.first << " @ " << i.second[0] << ", " << i.second[1] << " | "; + } + std::cout << std::endl; + + // Share how many unknown points to expect on each rank + std::vector oppRanks = child->GetOppRank(); + + Array sendBuff(1, missingCoords.size()); + Array recvBuff(oppRanks.size(), -1); + + LibUtilities::CommRequestSharedPtr recvRequest; + LibUtilities::CommRequestSharedPtr sendRequest; + for (int i = 0; i < oppRanks.size(); ++i) + { + comm->Irecv(oppRanks[i], recvBuff[i], 1, recvRequest, i); + } + + for (int i = 0; i < oppRanks.size(); ++i) + { + comm->Isend(oppRanks[i], sendBuff, 1, sendRequest, i); + } + + comm->WaitAll(sendRequest); + comm->WaitAll(recvRequest); + return tmp; } - void DisContField2D::CalcMatchLocalCoords() + void DisContField2D::CalcLocalInterfaceCoords() { for (auto &interface : m_interfaces->GetInterfaces()) { @@ -2625,14 +2678,14 @@ namespace Nektar auto pair = interface.second; if (pair->GetCalcFlag()) { - auto leftEdge = pair->GetLeftInterface()->GetEdgeIds(); - auto rightEdge = pair->GetRightInterface()->GetEdgeIds(); + auto left = pair->GetLeftInterface(); + auto right = pair->GetRightInterface(); - auto tmp = CalcCoordsOneWay(leftEdge, rightEdge, m_trace, m_graph, m_geomIdToTraceId); - auto tmp2 = CalcCoordsOneWay(rightEdge, leftEdge, m_trace, m_graph, m_geomIdToTraceId); + auto tmp = CalcCoordsOneWay(left, right, m_trace, m_graph, m_geomIdToTraceId, m_comm); + auto tmp2 = CalcCoordsOneWay(right, left, m_trace, m_graph, m_geomIdToTraceId, m_comm); tmp.insert(tmp.end(), tmp2.begin(), tmp2.end()); - m_locCoordSegIdPair[indx] = tmp; + //m_locCoordSegIdPair[indx] = tmp; pair->SetCalcFlag(false); } } diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 1971241ac..eca953258 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -379,7 +379,7 @@ namespace Nektar inline virtual const LocTraceToTraceMapSharedPtr &v_GetLocTraceToTraceMap() const; - void CalcMatchLocalCoords(); + void CalcLocalInterfaceCoords(); }; void DisContField2D::v_GetFwdBwdTracePhys( diff --git a/library/MultiRegions/ExpList.h b/library/MultiRegions/ExpList.h index e87fb1dcc..3040a7e7c 100644 --- a/library/MultiRegions/ExpList.h +++ b/library/MultiRegions/ExpList.h @@ -52,6 +52,7 @@ #include #include #include +#include namespace Nektar { @@ -1083,6 +1084,8 @@ namespace Nektar MULTI_REGIONS_EXPORT inline const LocTraceToTraceMapSharedPtr &GetLocTraceToTraceMap() const; protected: + SpatialDomains::InterfacesSharedPtr m_interfaces; + /// Definition of the total number of degrees of freedom and /// quadrature points and offsets to access data void SetCoeffPhysOffsets(); diff --git a/library/MultiRegions/ExpList2D.cpp b/library/MultiRegions/ExpList2D.cpp index c55fc8f2a..a42ded8a1 100644 --- a/library/MultiRegions/ExpList2D.cpp +++ b/library/MultiRegions/ExpList2D.cpp @@ -140,7 +140,7 @@ namespace Nektar for (auto &inter : m_interfaces->GetInterfaces()) { auto interfacePair = inter.second; - if (interfacePair->GetRightInterface()->GetEdge().empty()) + if (interfacePair->GetRightInterface()->GetEdge().empty() && false) // Disable interface separation as broken with MPI { interfacePair->SeparateGraph(m_graph); } diff --git a/library/MultiRegions/ExpList2D.h b/library/MultiRegions/ExpList2D.h index 15cd6d7ae..ca08be75d 100644 --- a/library/MultiRegions/ExpList2D.h +++ b/library/MultiRegions/ExpList2D.h @@ -39,7 +39,6 @@ #include #include #include -#include namespace Nektar { @@ -133,8 +132,6 @@ namespace Nektar MULTI_REGIONS_EXPORT virtual ~ExpList2D(); protected: - SpatialDomains::InterfacesSharedPtr m_interfaces; - /// Upwind the \a Fwd and \a Bwd states based on the one- /// dimensional normal velocity field given by \a Vn. MULTI_REGIONS_EXPORT void v_Upwind( diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index c76ae8053..6b35b6635 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -213,6 +213,87 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) } } +void Interfaces::CommSetup(LibUtilities::CommSharedPtr &comm) +{ + // myIndxLR contains the info about what interface edges are present on + // current rank with each interface no, i, consisting of: + // [i] = indx + // [i + 1] = 0 (non), = 1 (left only), = 2 (right only), = 3 (both) + + Array myIndxLR(m_interfaces.size() * 2, 0); + std::map myIndxLRMap; + size_t cnt = 0; + for (const auto &interface : m_interfaces) + { + myIndxLR[2 * cnt] = interface.first; + + if(!interface.second->GetLeftInterface()->IsEmpty()) + { + myIndxLR[2 * cnt + 1] += 1; + } + if (!interface.second->GetRightInterface()->IsEmpty()) + { + myIndxLR[2 * cnt + 1] += 2; + } + + myIndxLRMap[interface.first] = myIndxLR[2 * cnt + 1]; + cnt++; + } + + + //Send num of interfaces size so all partitions can prepare buffers + int nRanks = comm->GetSize(); + Array rankNumInterfaces(nRanks); + Array localInterfaceSize(1, myIndxLR.size()); + comm->AllGather(localInterfaceSize, rankNumInterfaces); + + Array rankLocalInterfaceDisp(nRanks, 0); + for (size_t i = 1; i < nRanks; ++i) + { + rankLocalInterfaceDisp[i] = rankLocalInterfaceDisp[i - 1] + rankNumInterfaces[i - 1]; + } + + Array rankLocalInterfaceIds( + std::accumulate(rankNumInterfaces.begin(), rankNumInterfaces.end(), 0), 0); + + // Send all interface IDs to all partitions + comm->AllGatherv(myIndxLR, rankLocalInterfaceIds, rankNumInterfaces, + rankLocalInterfaceDisp); + + // Find what interface Ids match with other ranks, then check if opposite edge + size_t myRank = comm->GetRank(); + for (size_t i = 0; i < nRanks; ++i) + { + if (i == myRank) + { + continue; + } + + for (size_t j = 0; j < rankNumInterfaces[i] / 2; ++j) + { + int otherId = + rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j]; + int otherCode = + rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j + 1]; + if (myIndxLRMap.find(otherId) != myIndxLRMap.end()) + { + // Set interface opposite ranks + int myCode = myIndxLRMap[otherId]; + if ((myCode == 1 && otherCode == 2) || + (myCode == 1 && otherCode == 3)) + { + m_interfaces[otherId]->GetLeftInterface()->AddOppRank(i); + } + else if ((myCode == 2 && otherCode == 1) || + (myCode == 2 && otherCode == 3)) + { + m_interfaces[otherId]->GetRightInterface()->AddOppRank(i); + } + } + } + } +} + void InterfacePair::SeparateGraph(MeshGraphSharedPtr &graph) { auto rightDomain = m_rightInterface->GetDomain(); diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 8754d9649..a2f4c6fee 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -65,49 +65,76 @@ struct InterfaceBase { } - InterfaceType GetInterfaceType() const + inline InterfaceType GetInterfaceType() const { return m_type; } - CompositeMap GetDomain() const + inline CompositeMap GetDomain() const { return m_domain; } - CompositeMap GetInterfaceEdge() const + inline CompositeMap GetInterfaceEdge() const { return m_interfaceEdge; } - void SetInterfaceEdge(const CompositeMap &interfaceEdge) + inline void SetInterfaceEdge(const CompositeMap &interfaceEdge) { m_interfaceEdge = interfaceEdge; } - std::map const &GetEdge() const + inline std::map const &GetEdge() const { return m_edge; } - std::vector const &GetEdgeIds() const + inline std::vector const &GetEdgeIds() const { return m_edgeIds; } - void SetEdge(const SegGeomSharedPtr &edge) + inline bool IsEmpty() const + { + return m_edge.empty(); + } + + inline void SetEdge(const SegGeomSharedPtr &edge) { m_edge[edge->GetGlobalID()] = edge; } void SetEdge(const CompositeMap &edge); + inline std::vector GetOppRank() + { + return m_sharedWithRank; + } + + inline void AddOppRank(int i) + { + m_sharedWithRank.emplace_back(i); + } + + inline int GetTotPoints() const + { + return m_totQuadPts; + } + + inline void SetTotPoints(int i) + { + m_totQuadPts = i; + } + protected: InterfaceType m_type; CompositeMap m_domain; std::map m_edge; std::vector m_edgeIds; + int m_totQuadPts; CompositeMap m_interfaceEdge; + std::vector m_sharedWithRank; }; struct RotatingInterface : public InterfaceBase @@ -120,17 +147,17 @@ struct RotatingInterface : public InterfaceBase { } - PointGeom GetOrigin() const + inline PointGeom GetOrigin() const { return m_origin; } - std::vector GetAxis() const + inline std::vector GetAxis() const { return m_axis; } - NekDouble GetAngularVel() const + inline NekDouble GetAngularVel() const { return m_angularVel; } @@ -167,22 +194,22 @@ struct InterfacePair bool m_calcFlag = true; public: - const InterfaceBaseShPtr &GetLeftInterface() const + inline const InterfaceBaseShPtr &GetLeftInterface() const { return m_leftInterface; } - const InterfaceBaseShPtr &GetRightInterface() const + inline const InterfaceBaseShPtr &GetRightInterface() const { return m_rightInterface; } - bool GetCalcFlag() + inline bool GetCalcFlag() { return m_calcFlag; } - void SetCalcFlag(bool flag) + inline void SetCalcFlag(bool flag) { m_calcFlag = flag; } @@ -204,16 +231,21 @@ public: SPATIAL_DOMAINS_EXPORT Interfaces() = default; - const InterfaceCollection &GetInterfaces() const + inline const InterfaceCollection &GetInterfaces() const { return m_interfaces; } + void CommSetup(LibUtilities::CommSharedPtr &comm); + protected: /// The mesh graph to use for referencing geometry info. MeshGraphSharedPtr m_meshGraph; LibUtilities::SessionReaderSharedPtr m_session; InterfaceCollection m_interfaces; + /// Map of interface ID to ranks sharing that interface (on the other side) + std::map> m_interfacesSharedRank; + private: /// Read segments (and general MeshGraph) given TiXmlDocument. -- GitLab From 8be449075ef7b606e327e7950bdbb1f293e54892 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 8 Jun 2020 16:00:20 +0100 Subject: [PATCH 046/408] New interface comm/exchange classes --- .../AssemblyMap/InterfaceMapDG.cpp | 265 ++++++++++++++++++ .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 90 ++++++ library/MultiRegions/CMakeLists.txt | 2 + library/MultiRegions/DisContField2D.cpp | 126 +-------- library/MultiRegions/DisContField2D.h | 5 +- library/SpatialDomains/Interface.cpp | 16 +- library/SpatialDomains/Interface.h | 33 ++- 7 files changed, 394 insertions(+), 143 deletions(-) create mode 100644 library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp create mode 100644 library/MultiRegions/AssemblyMap/InterfaceMapDG.h diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp new file mode 100644 index 000000000..00023d542 --- /dev/null +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -0,0 +1,265 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File AssemblyCommDG.cpp +// +// For more information, please see: http://www.nektar.info +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: Communication for interfaces +// +/////////////////////////////////////////////////////////////////////////////// + +#include "InterfaceMapDG.h" + +namespace Nektar +{ +namespace MultiRegions +{ + +InterfaceMapDG::InterfaceMapDG( + const SpatialDomains::InterfacesSharedPtr &interfaces, + const ExpList &locExp, const ExpListSharedPtr &trace, + const std::map geomIdToTraceId) +{ + auto comm = trace->GetComm(); + auto interfaceCollection = interfaces->GetInterfaces(); + + // myIndxLR contains the info about what interface edges are present on + // current rank with each interface no, i, consisting of: + // [i] = indx + // [i + 1] = 0 (non), = 1 (left only), = 2 (right only), = 3 (both) + Array myIndxLR(interfaceCollection.size() * 2, 0); + std::map myIndxLRMap; + size_t cnt = 0; + for (const auto &interface : interfaceCollection) + { + myIndxLR[2 * cnt] = interface.first; + + if(!interface.second->GetLeftInterface()->IsEmpty()) + { + myIndxLR[2 * cnt + 1] += 1; + } + if (!interface.second->GetRightInterface()->IsEmpty()) + { + myIndxLR[2 * cnt + 1] += 2; + } + + myIndxLRMap[interface.first] = myIndxLR[2 * cnt + 1]; + cnt++; + } + + + //Send num of interfaces size so all partitions can prepare buffers + int nRanks = comm->GetSize(); + Array rankNumInterfaces(nRanks); + Array localInterfaceSize(1, myIndxLR.size()); + comm->AllGather(localInterfaceSize, rankNumInterfaces); + + Array rankLocalInterfaceDisp(nRanks, 0); + for (size_t i = 1; i < nRanks; ++i) + { + rankLocalInterfaceDisp[i] = rankLocalInterfaceDisp[i - 1] + rankNumInterfaces[i - 1]; + } + + Array rankLocalInterfaceIds( + std::accumulate(rankNumInterfaces.begin(), rankNumInterfaces.end(), 0), 0); + + // Send all interface IDs to all partitions + comm->AllGatherv(myIndxLR, rankLocalInterfaceIds, rankNumInterfaces, + rankLocalInterfaceDisp); + + // Find what interface Ids match with other ranks, then check if opposite edge + size_t myRank = comm->GetRank(); + for (size_t i = 0; i < nRanks; ++i) + { + if (i == myRank) + { + continue; + } + + for (size_t j = 0; j < rankNumInterfaces[i] / 2; ++j) + { + int otherId = + rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j]; + int otherCode = + rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j + 1]; + + InterfaceExchangeSharedPtr exchange; + if (myIndxLRMap.find(otherId) != myIndxLRMap.end()) + { + // `Set` interface opposite ranks (could probably simplify logic + // here but this is easy to understand + int myCode = myIndxLRMap[otherId]; + if ((myCode == 1 && otherCode == 2) || + (myCode == 1 && otherCode == 3) || + (myCode == 3 && otherCode == 2)) + { + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[otherId]->GetLeftInterface(), i)); + } + else if ((myCode == 2 && otherCode == 1) || + (myCode == 2 && otherCode == 3) || + (myCode == 3 && otherCode == 1)) + { + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[otherId]->GetRightInterface(), + i)); + } + else if (myCode == 3 && otherCode == 3) + { + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[otherId]->GetLeftInterface(), i)); + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[otherId]->GetRightInterface(), + i)); + } + } + } + } +} + +std::vector> CalcCoordsOneWay( + const SpatialDomains::InterfaceBaseShPtr &child, + const SpatialDomains::InterfaceBaseShPtr &parent, + const ExpListSharedPtr &trace, + const SpatialDomains::MeshGraphSharedPtr &graph, + const std::map &geomToTrace, + LibUtilities::CommSharedPtr &comm) +{ + + int cnt = 0; + //Vector of quad point matching coords {local coord, edge ID, rank} + std::vector> tmp(child->GetTotPoints()); + std::map> missingCoords; + + auto childEdge = child->GetEdgeIds(); + auto parentEdge = parent->GetEdgeIds(); + + for (auto childId : childEdge) + { + int myRank = comm->GetRank(); + std::cout << "My rank: " << myRank << " child ID" << childId << std::endl; + LocalRegions::ExpansionSharedPtr childElmt = trace->GetExp(geomToTrace.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq); + childElmt->GetCoords(xc, yc); + + // Check local interface + for (int i = 0; i < nq; ++i) + { + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + + bool found = false; + int foundTraceId = -1; + NekDouble foundLocCoord = -1; + + for (auto id : parentEdge) + { + SpatialDomains::SegGeomSharedPtr searchSeg = + std::static_pointer_cast(graph->GetSegGeom(id)); + NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); + + if (dist < 1e-8) + { + foundTraceId = geomToTrace.at(id); + //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; + found = true; + break; + } + } + + if(!found) + { + missingCoords[cnt] = xs; + } + + tmp[cnt] = std::make_tuple(foundLocCoord, foundTraceId, myRank); + + cnt++; + } + } + + std::cout << "Couldn't find locally: "; + for (auto i : missingCoords) + { + std::cout << i.first << " @ " << i.second[0] << ", " << i.second[1] << " | "; + } + std::cout << std::endl; + + // Share how many unknown points to expect on each rank + std::vector oppRanks(child->GetOppRank().begin(), child->GetOppRank().end()); + + Array sendBuff(1, missingCoords.size()); + Array recvBuff(oppRanks.size(), -1); + + LibUtilities::CommRequestSharedPtr recvRequest; + LibUtilities::CommRequestSharedPtr sendRequest; + for (int i = 0; i < oppRanks.size(); ++i) + { + comm->Irecv(oppRanks[i], recvBuff[i], 1, recvRequest, i); + } + + for (int i = 0; i < oppRanks.size(); ++i) + { + comm->Isend(oppRanks[i], sendBuff, 1, sendRequest, i); + } + + comm->WaitAll(sendRequest); + comm->WaitAll(recvRequest); + + return tmp; +} + +void InterfaceExchange::CalcLocalInterfaceCoords() +{ + for (auto &interface : m_interfaces->GetInterfaces()) + { + size_t indx = interface.first; + auto pair = interface.second; + if (pair->GetCalcFlag()) + { + auto left = pair->GetLeftInterface(); + auto right = pair->GetRightInterface(); + + auto tmp = CalcCoordsOneWay(left, right, m_trace, m_graph, m_geomIdToTraceId, m_comm); + auto tmp2 = CalcCoordsOneWay(right, left, m_trace, m_graph, m_geomIdToTraceId, m_comm); + tmp.insert(tmp.end(), tmp2.begin(), tmp2.end()); + + //m_locCoordSegIdPair[indx] = tmp; + pair->SetCalcFlag(false); + } + } +} + +} // namespace MultiRegions +} // namespace Nektar \ No newline at end of file diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h new file mode 100644 index 000000000..6a83cc4bd --- /dev/null +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File AssemblyCommDG.cpp +// +// For more information, please see: http://www.nektar.info +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: Communication for interfaces +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NEKTAR_INTERFACEMAPDG_H +#define NEKTAR_INTERFACEMAPDG_H + +#include +#include + +namespace Nektar +{ +namespace MultiRegions +{ + +class InterfaceExchange +{ + +public: + /// Default destructor + MULTI_REGIONS_EXPORT virtual ~InterfaceExchange() = default; + + /// Default constructor + MULTI_REGIONS_EXPORT InterfaceExchange( + const SpatialDomains::InterfaceBaseShPtr &interface, + const int &rank) + : m_interface(interface), + m_rank(rank) + { + } +private: + SpatialDomains::InterfaceBaseShPtr m_interface; + int m_rank; +}; + +typedef std::shared_ptr InterfaceExchangeSharedPtr; + +class InterfaceMapDG +{ +public: + /// Default destructor + MULTI_REGIONS_EXPORT ~InterfaceMapDG() = default; + + // Constructor for interface communication + MULTI_REGIONS_EXPORT InterfaceMapDG( + const SpatialDomains::InterfacesSharedPtr &interfaces, + const ExpList &locExp, const ExpListSharedPtr &trace, + const std::map geomIdToTraceId); + +private: + std::vector m_exchange; +}; + +typedef std::shared_ptr InterfaceMapDGSharedPtr; + + +} // namespace MultiRegions +} // namespace Nektar + +#endif \ No newline at end of file diff --git a/library/MultiRegions/CMakeLists.txt b/library/MultiRegions/CMakeLists.txt index 7bbc53e0e..e36d45959 100644 --- a/library/MultiRegions/CMakeLists.txt +++ b/library/MultiRegions/CMakeLists.txt @@ -3,6 +3,7 @@ SET(MULTI_REGIONS_SOURCES ./AssemblyMap/AssemblyMap.cpp ./AssemblyMap/AssemblyMapCG.cpp ./AssemblyMap/AssemblyMapDG.cpp +./AssemblyMap/InterfaceMapDG.cpp ./AssemblyMap/LocTraceToTraceMap.cpp ContField1D.cpp ContField2D.cpp @@ -90,6 +91,7 @@ SET(ASSEMBLY_MAP_HEADERS ./AssemblyMap/AssemblyMap.h ./AssemblyMap/AssemblyMapCG.h ./AssemblyMap/AssemblyMapDG.h +./AssemblyMap/InterfaceMapDG.h ./AssemblyMap/LocTraceToTraceMap.h ) diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 8ab389acf..e353b7f60 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -443,13 +443,17 @@ namespace Nektar SetUpPhysNormals(); // ------ Setting up interfaces ------ - // Loop over all trace edges and create a map from geom ID to - // position in the trace expansion + // Map taking a global geometry ID to the matching trace expansion ID + std::map geomIdToTraceId; for (int i = 0; i < m_trace->GetExpSize(); ++i) { - m_geomIdToTraceId[m_trace->GetExp(i)->GetGeom()->GetGlobalID()] = i; + geomIdToTraceId[m_trace->GetExp(i)->GetGeom()->GetGlobalID()] = i; } + + m_interfaceMap = MemoryManager:: + AllocateSharedPtr(m_interfaces, m_trace, geomIdToTraceId); + // Calculate total quadrature points on each interface edge for (const auto &interface : m_interfaces->GetInterfaces()) { @@ -2575,121 +2579,5 @@ namespace Nektar } } - std::vector> CalcCoordsOneWay( - const SpatialDomains::InterfaceBaseShPtr &child, - const SpatialDomains::InterfaceBaseShPtr &parent, - const ExpListSharedPtr &trace, - const SpatialDomains::MeshGraphSharedPtr &graph, - const std::map &geomToTrace, - LibUtilities::CommSharedPtr &comm) - { - - int cnt = 0; - //Vector of quad point matching coords {local coord, edge ID, rank} - std::vector> tmp(child->GetTotPoints()); - std::map> missingCoords; - - auto childEdge = child->GetEdgeIds(); - auto parentEdge = parent->GetEdgeIds(); - - for (auto childId : childEdge) - { - int myRank = comm->GetRank(); - std::cout << "My rank: " << myRank << " child ID" << childId << std::endl; - LocalRegions::ExpansionSharedPtr childElmt = trace->GetExp(geomToTrace.at(childId)); - size_t nq = childElmt->GetTotPoints(); - Array xc(nq), yc(nq); - childElmt->GetCoords(xc, yc); - - // Check local interface - for (int i = 0; i < nq; ++i) - { - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - - bool found = false; - int foundTraceId = -1; - NekDouble foundLocCoord = -1; - - for (auto id : parentEdge) - { - SpatialDomains::SegGeomSharedPtr searchSeg = - std::static_pointer_cast(graph->GetSegGeom(id)); - NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); - - if (dist < 1e-8) - { - foundTraceId = geomToTrace.at(id); - //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; - found = true; - break; - } - } - - if(!found) - { - missingCoords[cnt] = xs; - } - - tmp[cnt] = std::make_tuple(foundLocCoord, foundTraceId, myRank); - - cnt++; - } - } - - std::cout << "Couldn't find locally: "; - for (auto i : missingCoords) - { - std::cout << i.first << " @ " << i.second[0] << ", " << i.second[1] << " | "; - } - std::cout << std::endl; - - // Share how many unknown points to expect on each rank - std::vector oppRanks = child->GetOppRank(); - - Array sendBuff(1, missingCoords.size()); - Array recvBuff(oppRanks.size(), -1); - - LibUtilities::CommRequestSharedPtr recvRequest; - LibUtilities::CommRequestSharedPtr sendRequest; - for (int i = 0; i < oppRanks.size(); ++i) - { - comm->Irecv(oppRanks[i], recvBuff[i], 1, recvRequest, i); - } - - for (int i = 0; i < oppRanks.size(); ++i) - { - comm->Isend(oppRanks[i], sendBuff, 1, sendRequest, i); - } - - comm->WaitAll(sendRequest); - comm->WaitAll(recvRequest); - - return tmp; - } - - void DisContField2D::CalcLocalInterfaceCoords() - { - for (auto &interface : m_interfaces->GetInterfaces()) - { - size_t indx = interface.first; - auto pair = interface.second; - if (pair->GetCalcFlag()) - { - auto left = pair->GetLeftInterface(); - auto right = pair->GetRightInterface(); - - auto tmp = CalcCoordsOneWay(left, right, m_trace, m_graph, m_geomIdToTraceId, m_comm); - auto tmp2 = CalcCoordsOneWay(right, left, m_trace, m_graph, m_geomIdToTraceId, m_comm); - tmp.insert(tmp.end(), tmp2.begin(), tmp2.end()); - - //m_locCoordSegIdPair[indx] = tmp; - pair->SetCalcFlag(false); - } - } - } - } // end of namespace } //end of namespace diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index eca953258..916885967 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -162,9 +163,7 @@ namespace Nektar */ Array m_bndConditions; - - // Map taking a global geometry ID to the matching trace expansion ID - std::map m_geomIdToTraceId; + InterfaceMapDGSharedPtr m_interfaceMap; std::map>> m_locCoordSegIdPair; GlobalLinSysMapShPtr m_globalBndMat; diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 6b35b6635..a96ff1728 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -277,24 +277,32 @@ void Interfaces::CommSetup(LibUtilities::CommSharedPtr &comm) rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j + 1]; if (myIndxLRMap.find(otherId) != myIndxLRMap.end()) { - // Set interface opposite ranks + // Set interface opposite ranks (could probably simplify logic + // here but this is easy to understand int myCode = myIndxLRMap[otherId]; if ((myCode == 1 && otherCode == 2) || - (myCode == 1 && otherCode == 3)) + (myCode == 1 && otherCode == 3) || + (myCode == 3 && otherCode == 2)) { m_interfaces[otherId]->GetLeftInterface()->AddOppRank(i); } else if ((myCode == 2 && otherCode == 1) || - (myCode == 2 && otherCode == 3)) + (myCode == 2 && otherCode == 3) || + (myCode == 3 && otherCode == 1)) { m_interfaces[otherId]->GetRightInterface()->AddOppRank(i); } + else if (myCode == 3 && otherCode == 3) + { + m_interfaces[otherId]->GetLeftInterface()->AddOppRank(i); + m_interfaces[otherId]->GetRightInterface()->AddOppRank(i); + } } } } } -void InterfacePair::SeparateGraph(MeshGraphSharedPtr &graph) +void InterfacePair::SeparateGraph(MeshGraphSharedPtr &graph) const { auto rightDomain = m_rightInterface->GetDomain(); auto interfaceEdge = m_rightInterface->GetInterfaceEdge(); diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index a2f4c6fee..e2c12e3bd 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -48,6 +48,7 @@ struct OneD; namespace SpatialDomains { + enum InterfaceType { eFixed, @@ -55,6 +56,13 @@ enum InterfaceType eSliding, }; +enum InterfaceSide +{ + eNone, + eLeft, + eRight +}; + struct Composite; typedef std::map> CompositeMap; @@ -107,34 +115,23 @@ struct InterfaceBase void SetEdge(const CompositeMap &edge); - inline std::vector GetOppRank() - { - return m_sharedWithRank; - } - - inline void AddOppRank(int i) - { - m_sharedWithRank.emplace_back(i); - } - - inline int GetTotPoints() const + inline InterfaceSide GetSide() const { - return m_totQuadPts; + return m_side; } - inline void SetTotPoints(int i) + inline void SetSide(const InterfaceSide &side) { - m_totQuadPts = i; + m_side = side; } protected: InterfaceType m_type; + InterfaceSide m_side = eNone; CompositeMap m_domain; std::map m_edge; std::vector m_edgeIds; - int m_totQuadPts; CompositeMap m_interfaceEdge; - std::vector m_sharedWithRank; }; struct RotatingInterface : public InterfaceBase @@ -187,6 +184,8 @@ struct InterfacePair : m_leftInterface(leftInterface), m_rightInterface(rightInterface) { + leftInterface->SetSide(eLeft); + rightInterface->SetSide(eRight); } InterfaceBaseShPtr m_leftInterface; @@ -214,7 +213,7 @@ public: m_calcFlag = flag; } - void SeparateGraph(MeshGraphSharedPtr &graph); + void SeparateGraph(MeshGraphSharedPtr &graph) const; }; -- GitLab From 77e90d02214fc9c09ab0ec1f515162a93edfe6c7 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 9 Jun 2020 15:37:08 +0100 Subject: [PATCH 047/408] Integral filter for arbitrary comp == global dim Also some changes to make IsentropicVortex more flexible. --- library/SolverUtils/CMakeLists.txt | 2 + .../SolverUtils/Filters/FilterIntegral.cpp | 271 ++++++++++++++++++ library/SolverUtils/Filters/FilterIntegral.h | 96 +++++++ .../EquationSystems/IsentropicVortex.cpp | 30 +- .../EquationSystems/IsentropicVortex.h | 6 + 5 files changed, 390 insertions(+), 15 deletions(-) create mode 100644 library/SolverUtils/Filters/FilterIntegral.cpp create mode 100644 library/SolverUtils/Filters/FilterIntegral.h diff --git a/library/SolverUtils/CMakeLists.txt b/library/SolverUtils/CMakeLists.txt index 19c6411ed..d0d4af386 100644 --- a/library/SolverUtils/CMakeLists.txt +++ b/library/SolverUtils/CMakeLists.txt @@ -30,6 +30,7 @@ SET(SOLVER_UTILS_SOURCES Filters/FilterEnergy.cpp Filters/FilterError.cpp Filters/FilterHistoryPoints.cpp + Filters/FilterIntegral.cpp Filters/FilterModalEnergy.cpp Filters/FilterMovingAverage.cpp Filters/FilterFieldConvert.cpp @@ -80,6 +81,7 @@ SET(SOLVER_UTILS_HEADERS Filters/FilterEnergy.h Filters/FilterError.h Filters/FilterHistoryPoints.h + Filters/FilterIntegral.h Filters/FilterModalEnergy.h Filters/FilterMovingAverage.h Filters/FilterFieldConvert.h diff --git a/library/SolverUtils/Filters/FilterIntegral.cpp b/library/SolverUtils/Filters/FilterIntegral.cpp new file mode 100644 index 000000000..5e540de7a --- /dev/null +++ b/library/SolverUtils/Filters/FilterIntegral.cpp @@ -0,0 +1,271 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File FilterIntegral.cpp +// +// For more information, please see: http://www.nektar.info +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: Outputs integrals of fields during time-stepping. +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#include + +namespace Nektar +{ +namespace SolverUtils +{ +std::string FilterIntegral::className = + GetFilterFactory().RegisterCreatorFunction("Integral", FilterIntegral::create); + +FilterIntegral::FilterIntegral(const LibUtilities::SessionReaderSharedPtr &pSession, + const std::weak_ptr &pEquation, + const ParamMap &pParams) + : Filter(pSession, pEquation) +{ + std::string outName; + + // OutputFile + auto it = pParams.find("OutputFile"); + if (it == pParams.end()) + { + outName = m_session->GetSessionName(); + } + else + { + ASSERTL0(it->second.length() > 0, "Empty parameter 'OutputFile'."); + outName = it->second; + } + outName += ".int"; + + // Composites (to calculate integrals on) + it = pParams.find("Composites"); + ASSERTL0(it != pParams.end(), "Missing parameter 'Composites'."); + ASSERTL0(it->second.length() > 0, "Empty parameter 'Composites'."); + + std::vector splitComposite; + boost::split(m_splitCompString, it->second, boost::is_any_of(",")); + for (auto &comp : m_splitCompString) + { + size_t first = comp.find_first_of('[') + 1; + size_t last = comp.find_last_of(']') - 1; + auto tmpString = comp.substr(first, last - first + 1); + + std::vector tmpVec; + bool parseGood = ParseUtils::GenerateSeqVector(tmpString, tmpVec); + + ASSERTL0(parseGood && !tmpVec.empty(), + "Unable to read composite regions index range for " + "FilterIntegral: " + comp); + + m_compVector.emplace_back(tmpVec); + } + + // Lock equation system pointer + auto equationSys = m_equ.lock(); + ASSERTL0(equationSys, "Weak pointer expired"); + + m_numVariables = equationSys->GetNvariables(); + + m_comm = pSession->GetComm(); + if (m_comm->GetRank() == 0) + { + m_outFile.open(outName); + ASSERTL0(m_outFile.good(), "Unable to open: '" + outName + "'"); + m_outFile.setf(std::ios::scientific, std::ios::floatfield); + + m_outFile << "Time"; + + for (auto &compName : m_splitCompString) + { + for (size_t j = 0; j < m_numVariables; ++j) + { + std::string varName = equationSys->GetVariable(j); + m_outFile << " " + compName + "_" + varName + "_integral"; + } + } + m_outFile << std::endl; + } + + // OutputFrequency + it = pParams.find("OutputFrequency"); + if (it == pParams.end()) + { + m_outputFrequency = 1; + } + else + { + ASSERTL0(it->second.length() > 0, "Empty parameter 'OutputFrequency'."); + LibUtilities::Equation equ(m_session->GetInterpreter(), it->second); + m_outputFrequency = round(equ.Evaluate()); + } +} + +void FilterIntegral::v_Initialise( + const Array &pFields, + const NekDouble &time) +{ + + // Create map from element ID -> expansion list ID + auto expList = pFields[0]->GetExp(); + for (size_t i = 0; i < expList->size(); ++i) + { + auto exp = (*expList)[i]; + m_geomElmtIdToExpId[exp->GetElmtId()] = i; + } + + std::vector>> + pairDimGeomIds(m_compVector.size()); + + + for (int i = 0; i < m_compVector.size(); ++ i) + { + // Get comp list dimension from first composite & element + auto composites = pFields[0]->GetGraph()->GetComposites(); + size_t dim = composites[m_compVector[0][0]]->m_geomVec[0]->GetShapeDim(); + + + std::vector compGeomIds; + for (auto compNum : m_compVector[i]) + { + ASSERTL0(composites.find(compNum) != composites.end(), + "In FilterIntegral defined composite C[" + + std::to_string(compNum) + + "] does not exist in the mesh.") + + auto compGeom = composites[compNum]->m_geomVec; + + for (auto &geom : compGeom) + { + compGeomIds.emplace_back(geom->GetGlobalID()); + } + + // Only check first element in each comp for dimension + ASSERTL0(dim == compGeom[0]->GetShapeDim(), + "Differing geometry dimensions specified in FilterIntegral '" + + m_splitCompString[i] + "'."); + } + + if (dim == pFields[0]->GetShapeDimension()) + { + LocalRegions::ExpansionVector tmpCompExp(compGeomIds.size()); + + for (size_t j = 0; j < compGeomIds.size(); ++j) + { + tmpCompExp[j] = (*expList)[m_geomElmtIdToExpId[compGeomIds[j]]]; + } + + m_compExpVector.emplace_back(tmpCompExp); + } + else if (dim < pFields[0]->GetShapeDimension()) + { + ASSERTL0(false, "Finding the integral on a composite of dimension" + "smaller than the domain is not currently supported.") + } + } + + v_Update(pFields, time); +} + +void FilterIntegral::v_Update( + const Array &pFields, + const NekDouble &time) +{ + boost::ignore_unused(pFields); + + if (m_index++ % m_outputFrequency > 0) + { + return; + } + + if (m_comm->GetRank() == 0) + { + m_outFile << time; + } + + // Lock equation system pointer + auto equationSys = m_equ.lock(); + ASSERTL0(equationSys, "Weak pointer expired"); + + for (auto &compExp : m_compExpVector) + { + for (size_t i = 0; i < m_numVariables; ++i) + { + // Evaluate integral using improved Kahan–BabuÅ¡ka summation + // algorithm to reduce numerical error from adding floating point + auto phys = pFields[i]->GetPhys(); + + NekDouble sum = 0.0; + NekDouble c = 0.0; + for (auto &exp : compExp) + { + size_t offset = pFields[0]->GetPhys_Offset( + m_geomElmtIdToExpId[exp->GetElmtId()]); + + NekDouble input = exp->Integral(phys + offset); + NekDouble t = sum + input; + c += fabs(sum) >= fabs(input) ? (sum - t) + input + : (input - t) + sum; + sum = t; + } + + Array sumArray(1, sum + c); + m_comm->AllReduce(sumArray, LibUtilities::ReduceSum); + if (m_comm->GetRank() == 0) + { + m_outFile << " " << sumArray[0]; + } + } + } + + if (m_comm->GetRank() == 0) + { + m_outFile << std::endl; + } +} + +void FilterIntegral::v_Finalise( + const Array &pFields, + const NekDouble &time) +{ + boost::ignore_unused(pFields, time); + + if (m_comm->GetRank() == 0) + { + m_outFile.close(); + } +} + +bool FilterIntegral::v_IsTimeDependent() +{ + return true; +} +} // namespace SolverUtils +} // namespace Nektar diff --git a/library/SolverUtils/Filters/FilterIntegral.h b/library/SolverUtils/Filters/FilterIntegral.h new file mode 100644 index 000000000..80c930cb7 --- /dev/null +++ b/library/SolverUtils/Filters/FilterIntegral.h @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File FilterIntegral.h +// +// For more information, please see: http://www.nektar.info +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: Outputs integrals of fields during time-stepping. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef NEKTAR_SOLVERUTILS_FILTERS_FILTERINTEGRAL_H +#define NEKTAR_SOLVERUTILS_FILTERS_FILTERINTEGRAL_H + +#include + +namespace Nektar +{ +namespace SolverUtils +{ +class FilterIntegral : public Filter +{ +public: + friend class MemoryManager; + + /// Creates an instance of this class + static FilterSharedPtr create( + const LibUtilities::SessionReaderSharedPtr &pSession, + const std::weak_ptr &pEquation, + const std::map &pParams) + { + FilterSharedPtr p = MemoryManager::AllocateSharedPtr( + pSession, pEquation, pParams); + return p; + } + + /// Name of the class + static std::string className; + + SOLVER_UTILS_EXPORT FilterIntegral( + const LibUtilities::SessionReaderSharedPtr &pSession, + const std::weak_ptr &pEquation, + const ParamMap &pParams); + SOLVER_UTILS_EXPORT virtual ~FilterIntegral() = default; + +protected: + virtual void v_Initialise( + const Array &pFields, + const NekDouble &time) final; + virtual void v_Update( + const Array &pFields, + const NekDouble &time) final; + virtual void v_Finalise( + const Array &pFields, + const NekDouble &time) final; + virtual bool v_IsTimeDependent() final; + +private: + size_t m_index = 0; + size_t m_outputFrequency; + size_t m_numVariables; + std::ofstream m_outFile; + LibUtilities::CommSharedPtr m_comm; + std::vector m_splitCompString; + std::vector> m_compVector; + std::map m_geomElmtIdToExpId; + std::vector m_compExpVector; + +}; +} // namespace SolverUtils +} // namespace Nektar + +#endif /* NEKTAR_SOLVERUTILS_FILTERS_FILTERIntegral_H */ diff --git a/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.cpp b/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.cpp index 43228d1eb..b94241f0f 100755 --- a/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.cpp +++ b/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.cpp @@ -51,6 +51,11 @@ namespace Nektar : UnsteadySystem(pSession, pGraph), EulerCFE(pSession, pGraph) { + m_session->LoadParameter("IsentropicBeta", m_beta, 5.0); + m_session->LoadParameter("IsentropicU0", m_u0, 1.0); + m_session->LoadParameter("IsentropicV0", m_v0, 0.5); + m_session->LoadParameter("IsentropicX0", m_x0, 5.0); + m_session->LoadParameter("IsentropicY0", m_y0, 0.0); } /** @@ -106,7 +111,8 @@ namespace Nektar if (dumpInitialConditions && m_checksteps) { // Dump initial conditions to file - Checkpoint_Output(0); + Checkpoint_Output(m_nchk); + m_nchk++; } } @@ -150,14 +156,8 @@ namespace Nektar int nq = x.size(); // Flow parameters - const NekDouble x0 = 5.0; - const NekDouble y0 = 0.0; - const NekDouble beta = 5.0; - const NekDouble u0 = 1.0; - const NekDouble v0 = 0.5; - const NekDouble gamma = m_gamma; NekDouble r, xbar, ybar, tmp; - NekDouble fac = 1.0/(16.0*gamma*M_PI*M_PI); + NekDouble fac = 1.0/(16.0*m_gamma*M_PI*M_PI); // In 3D zero rhow field. if (m_spacedim == 3) @@ -168,14 +168,14 @@ namespace Nektar // Fill storage for (int i = 0; i < nq; ++i) { - xbar = x[i] - u0*time - x0; - ybar = y[i] - v0*time - y0; + xbar = x[i] - m_u0*time - m_x0; + ybar = y[i] - m_v0*time - m_y0; r = sqrt(xbar*xbar + ybar*ybar); - tmp = beta*exp(1-r*r); - u[0][i+o] = pow(1.0 - (gamma-1.0)*tmp*tmp*fac, 1.0/(gamma-1.0)); - u[1][i+o] = u[0][i+o]*(u0 - tmp*ybar/(2*M_PI)); - u[2][i+o] = u[0][i+o]*(v0 + tmp*xbar/(2*M_PI)); - u[m_spacedim+1][i+o] = pow(u[0][i+o], gamma)/(gamma-1.0) + + tmp = m_beta*exp(1-r*r); + u[0][i+o] = pow(1.0 - (m_gamma-1.0)*tmp*tmp*fac, 1.0/(m_gamma-1.0)); + u[1][i+o] = u[0][i+o]*(m_u0 - tmp*ybar/(2*M_PI)); + u[2][i+o] = u[0][i+o]*(m_v0 + tmp*xbar/(2*M_PI)); + u[m_spacedim+1][i+o] = pow(u[0][i+o], m_gamma)/(m_gamma-1.0) + 0.5*(u[1][i+o]*u[1][i+o] + u[2][i+o]*u[2][i+o]) / u[0][i+o]; } } diff --git a/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.h b/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.h index 69a3ea96c..ae8aed9e2 100755 --- a/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.h +++ b/solvers/CompressibleFlowSolver/EquationSystems/IsentropicVortex.h @@ -87,6 +87,12 @@ namespace Nektar Array > &u, NekDouble time, const int o = 0); + + NekDouble m_beta; + NekDouble m_u0; + NekDouble m_v0; + NekDouble m_x0; + NekDouble m_y0; }; } #endif -- GitLab From ea46026ee07396a2c80a535ee8c915c09343ff55 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 15 Jun 2020 15:30:27 +0100 Subject: [PATCH 048/408] Integral filter for trace dimension --- .../SolverUtils/Filters/FilterIntegral.cpp | 204 +++++++++++++----- library/SolverUtils/Filters/FilterIntegral.h | 4 +- 2 files changed, 158 insertions(+), 50 deletions(-) diff --git a/library/SolverUtils/Filters/FilterIntegral.cpp b/library/SolverUtils/Filters/FilterIntegral.cpp index 5e540de7a..0724be643 100644 --- a/library/SolverUtils/Filters/FilterIntegral.cpp +++ b/library/SolverUtils/Filters/FilterIntegral.cpp @@ -32,10 +32,13 @@ // /////////////////////////////////////////////////////////////////////////////// -#include -#include #include +#include +#include +#include +#include +#include #include namespace Nektar @@ -43,11 +46,12 @@ namespace Nektar namespace SolverUtils { std::string FilterIntegral::className = - GetFilterFactory().RegisterCreatorFunction("Integral", FilterIntegral::create); + GetFilterFactory().RegisterCreatorFunction("Integral", + FilterIntegral::create); -FilterIntegral::FilterIntegral(const LibUtilities::SessionReaderSharedPtr &pSession, - const std::weak_ptr &pEquation, - const ParamMap &pParams) +FilterIntegral::FilterIntegral( + const LibUtilities::SessionReaderSharedPtr &pSession, + const std::weak_ptr &pEquation, const ParamMap &pParams) : Filter(pSession, pEquation) { std::string outName; @@ -71,11 +75,14 @@ FilterIntegral::FilterIntegral(const LibUtilities::SessionReaderSharedPtr &pSess ASSERTL0(it->second.length() > 0, "Empty parameter 'Composites'."); std::vector splitComposite; - boost::split(m_splitCompString, it->second, boost::is_any_of(",")); + boost::split(m_splitCompString, it->second, boost::is_any_of(","), + boost::token_compress_on); + for (auto &comp : m_splitCompString) { - size_t first = comp.find_first_of('[') + 1; - size_t last = comp.find_last_of(']') - 1; + boost::trim(comp); + size_t first = comp.find_first_of('[') + 1; + size_t last = comp.find_last_of(']') - 1; auto tmpString = comp.substr(first, last - first + 1); std::vector tmpVec; @@ -83,7 +90,8 @@ FilterIntegral::FilterIntegral(const LibUtilities::SessionReaderSharedPtr &pSess ASSERTL0(parseGood && !tmpVec.empty(), "Unable to read composite regions index range for " - "FilterIntegral: " + comp); + "FilterIntegral: " + + comp); m_compVector.emplace_back(tmpVec); } @@ -100,8 +108,7 @@ FilterIntegral::FilterIntegral(const LibUtilities::SessionReaderSharedPtr &pSess m_outFile.open(outName); ASSERTL0(m_outFile.good(), "Unable to open: '" + outName + "'"); m_outFile.setf(std::ios::scientific, std::ios::floatfield); - - m_outFile << "Time"; + m_outFile << "#Time"; for (auto &compName : m_splitCompString) { @@ -134,24 +141,42 @@ void FilterIntegral::v_Initialise( { // Create map from element ID -> expansion list ID - auto expList = pFields[0]->GetExp(); + auto expList = pFields[0]->GetExp(); + auto meshGraph = pFields[0]->GetGraph(); + for (size_t i = 0; i < expList->size(); ++i) { - auto exp = (*expList)[i]; - m_geomElmtIdToExpId[exp->GetElmtId()] = i; + auto exp = (*expList)[i]; + m_geomElmtIdToExpId[exp->GetGeom()->GetGlobalID()] = i; } - std::vector>> - pairDimGeomIds(m_compVector.size()); + // Create a map from geom ID -> trace expansion list ID + std::map geomIdToTraceId; + auto trace = pFields[0]->GetTrace()->GetExp(); + for (size_t i = 0; i < trace->size(); ++i) + { + auto exp = (*trace)[i]; + geomIdToTraceId[exp->GetGeom()->GetGlobalID()] = i; + } + // Get comp list dimension from first composite & element + auto composites = pFields[0]->GetGraph()->GetComposites(); + size_t meshDim = pFields[0]->GetGraph()->GetMeshDimension(); - for (int i = 0; i < m_compVector.size(); ++ i) + for (int i = 0; i < m_compVector.size(); ++i) { - // Get comp list dimension from first composite & element - auto composites = pFields[0]->GetGraph()->GetComposites(); - size_t dim = composites[m_compVector[0][0]]->m_geomVec[0]->GetShapeDim(); + // Check composite is present in the rank + if (composites.find(m_compVector[i][0]) == composites.end()) + { + continue; + } + std::vector> geomVec = + composites[m_compVector[i][0]]->m_geomVec; + size_t dim = + composites[m_compVector[i][0]]->m_geomVec[0]->GetShapeDim(); + // Vector of all geometry IDs contained within the composite list std::vector compGeomIds; for (auto compNum : m_compVector[i]) { @@ -168,27 +193,70 @@ void FilterIntegral::v_Initialise( } // Only check first element in each comp for dimension - ASSERTL0(dim == compGeom[0]->GetShapeDim(), + ASSERTL0( + dim == compGeom[0]->GetShapeDim(), "Differing geometry dimensions specified in FilterIntegral '" + m_splitCompString[i] + "'."); } + std::vector> + tmpCompExp(compGeomIds.size()); + + // If dimension of composite == dimension of mesh then we only need the + // expansion of the element if (dim == pFields[0]->GetShapeDimension()) { - LocalRegions::ExpansionVector tmpCompExp(compGeomIds.size()); - for (size_t j = 0; j < compGeomIds.size(); ++j) { - tmpCompExp[j] = (*expList)[m_geomElmtIdToExpId[compGeomIds[j]]]; + tmpCompExp[j] = std::make_pair( + (*expList)[m_geomElmtIdToExpId[compGeomIds[j]]], -1); } + } + // however if the dimension is less we need the expansion of the element + // containing the global composite geometry and the face/edge local ID + // within that. 3D mesh -> 2D, 2D -> 1D. + else if (meshDim == 3 && dim == 2) + { + for (size_t j = 0; j < compGeomIds.size(); ++j) + { + LocalRegions::ExpansionSharedPtr exp = + (*trace)[geomIdToTraceId[compGeomIds[j]]]; + LocalRegions::Expansion2DSharedPtr exp2D = + std::dynamic_pointer_cast(exp); - m_compExpVector.emplace_back(tmpCompExp); + LocalRegions::ExpansionSharedPtr leftAdjElmtExp = + std::dynamic_pointer_cast( + exp2D->GetLeftAdjacentElementExp()); + int leftAdjElmtFace = exp2D->GetLeftAdjacentElementFace(); + + tmpCompExp[j] = std::make_pair(leftAdjElmtExp, leftAdjElmtFace); + } + } + else if (meshDim == 2 && dim == 1) + { + for (size_t j = 0; j < compGeomIds.size(); ++j) + { + LocalRegions::ExpansionSharedPtr exp = + (*trace)[geomIdToTraceId[compGeomIds[j]]]; + LocalRegions::Expansion1DSharedPtr exp1D = + std::dynamic_pointer_cast(exp); + + LocalRegions::ExpansionSharedPtr leftAdjElmtExp = + std::dynamic_pointer_cast( + exp1D->GetLeftAdjacentElementExp()); + int leftAdjElmtEdge = exp1D->GetLeftAdjacentElementEdge(); + + tmpCompExp[j] = std::make_pair(leftAdjElmtExp, leftAdjElmtEdge); + } } - else if (dim < pFields[0]->GetShapeDimension()) + else { - ASSERTL0(false, "Finding the integral on a composite of dimension" - "smaller than the domain is not currently supported.") + ASSERTL0(false, + "FilterIntegral: Only composite dimensions equal to or " + "one lower than the mesh dimension are supported.") } + + m_compExpMap[i] = tmpCompExp; } v_Update(pFields, time); @@ -198,8 +266,6 @@ void FilterIntegral::v_Update( const Array &pFields, const NekDouble &time) { - boost::ignore_unused(pFields); - if (m_index++ % m_outputFrequency > 0) { return; @@ -210,32 +276,74 @@ void FilterIntegral::v_Update( m_outFile << time; } - // Lock equation system pointer - auto equationSys = m_equ.lock(); - ASSERTL0(equationSys, "Weak pointer expired"); - - for (auto &compExp : m_compExpVector) + for (size_t j = 0; j < m_compVector.size(); ++j) { for (size_t i = 0; i < m_numVariables; ++i) { - // Evaluate integral using improved Kahan–BabuÅ¡ka summation - // algorithm to reduce numerical error from adding floating point - auto phys = pFields[i]->GetPhys(); + Array phys; + phys = pFields[i]->GetPhys(); NekDouble sum = 0.0; NekDouble c = 0.0; - for (auto &exp : compExp) + + // Check if composite is on the rank + if (m_compExpMap.find(j) != m_compExpMap.end()) { - size_t offset = pFields[0]->GetPhys_Offset( - m_geomElmtIdToExpId[exp->GetElmtId()]); - - NekDouble input = exp->Integral(phys + offset); - NekDouble t = sum + input; - c += fabs(sum) >= fabs(input) ? (sum - t) + input - : (input - t) + sum; - sum = t; + auto compExp = m_compExpMap[j]; + size_t dim = compExp[0].first->GetGeom()->GetShapeDim(); + size_t meshDim = pFields[i]->GetGraph()->GetMeshDimension(); + + // Evaluate integral using improved Kahan–BabuÅ¡ka summation + // algorithm to reduce numerical error from adding floating + // points + for (auto &expPair : compExp) + { + NekDouble input = 0; + auto exp = expPair.first; + + if (meshDim == dim) + { + size_t offset = pFields[i]->GetPhys_Offset( + m_geomElmtIdToExpId[exp->GetGeom()->GetGlobalID()]); + input = exp->Integral(phys + offset); + } + else if (meshDim == 3 && dim == 2) + { + Array facePhys; + exp->GetFacePhysVals(expPair.second, exp, phys, + facePhys); + input = + pFields[i] + ->GetTrace() + ->GetExp(exp->GetGeom()->GetTid(expPair.second)) + ->Integral(facePhys); + } + else if (meshDim == 2 && dim == 1) + { + Array edgePhys; + exp->GetEdgePhysVals(expPair.second, phys, edgePhys); + input = + pFields[i] + ->GetTrace() + ->GetExp(exp->GetGeom()->GetTid(expPair.second)) + ->Integral(edgePhys); + } + else + { + ASSERTL0(false, + "FilterIntegral: Only composite dimensions " + "equal to or one lower than the mesh " + "dimension are supported.") + } + + NekDouble t = sum + input; + c += fabs(sum) >= fabs(input) ? (sum - t) + input + : (input - t) + sum; + sum = t; + } } + // Sum integral values from all ranks Array sumArray(1, sum + c); m_comm->AllReduce(sumArray, LibUtilities::ReduceSum); if (m_comm->GetRank() == 0) diff --git a/library/SolverUtils/Filters/FilterIntegral.h b/library/SolverUtils/Filters/FilterIntegral.h index 80c930cb7..5d955e6d9 100644 --- a/library/SolverUtils/Filters/FilterIntegral.h +++ b/library/SolverUtils/Filters/FilterIntegral.h @@ -87,8 +87,8 @@ private: std::vector m_splitCompString; std::vector> m_compVector; std::map m_geomElmtIdToExpId; - std::vector m_compExpVector; - + std::map>> + m_compExpMap; }; } // namespace SolverUtils } // namespace Nektar -- GitLab From 3e302fa9b7b6254c790f0390703dbed1ff184cc3 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 15 Jun 2020 16:08:43 +0100 Subject: [PATCH 049/408] OutputPrecision parameter --- library/SolverUtils/Filters/FilterIntegral.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/library/SolverUtils/Filters/FilterIntegral.cpp b/library/SolverUtils/Filters/FilterIntegral.cpp index 0724be643..2b4ad6bf9 100644 --- a/library/SolverUtils/Filters/FilterIntegral.cpp +++ b/library/SolverUtils/Filters/FilterIntegral.cpp @@ -96,6 +96,19 @@ FilterIntegral::FilterIntegral( m_compVector.emplace_back(tmpVec); } + // OutputPrecision + size_t precision; + it = pParams.find("OutputPrecision"); + if (it == pParams.end()) + { + precision = 7; + } + else + { + ASSERTL0(it->second.length() > 0, "Empty parameter 'OutputPrecision'."); + precision = std::stoi(it->second); + } + // Lock equation system pointer auto equationSys = m_equ.lock(); ASSERTL0(equationSys, "Weak pointer expired"); @@ -108,6 +121,7 @@ FilterIntegral::FilterIntegral( m_outFile.open(outName); ASSERTL0(m_outFile.good(), "Unable to open: '" + outName + "'"); m_outFile.setf(std::ios::scientific, std::ios::floatfield); + m_outFile.precision(precision); m_outFile << "#Time"; for (auto &compName : m_splitCompString) -- GitLab From 7e1da33408412e5a278fac331b37bb0ac7c0de37 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 16 Jun 2020 11:53:21 +0100 Subject: [PATCH 050/408] Changelog and user guide --- CHANGELOG.md | 5 ++++ docs/user-guide/xml/xml-filters.tex | 44 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39ed984be..7e6162246 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ v5.1.0 level. Removed GlobalCeoffs functionality (!963) - Add interior penalty method to DG framework (!1101) - Add an error filter for the time-evolution of the L2 and Linf errors (!1147) +- Add an integral filter for the time-evolution of integrals on composites, + supports dimension equal to or one lower than the mesh dimension. (!1156) **FieldConvert** - Refactored time integration code using factory pattern (!1034) @@ -21,6 +23,9 @@ v5.1.0 **CardiacEPSolver** - Added additional parameter sets to Fenton-Karma model (!1119) +**CompressibleFlowSolver** +- Add additional parameters for the Isentropic Vortex equation system. (!1156) + **NekMesh** - Improved boundary layer splitting and output to CADfix (!938) - Improve .geo reader and support 3D geometries with voids (!1031) diff --git a/docs/user-guide/xml/xml-filters.tex b/docs/user-guide/xml/xml-filters.tex index 86b57cd53..ab2202f69 100644 --- a/docs/user-guide/xml/xml-filters.tex +++ b/docs/user-guide/xml/xml-filters.tex @@ -311,6 +311,50 @@ An example syntax is given below: \end{lstlisting} +\subsection{Integral}\label{filters:Integral} + +This filter produces a file containing the time-evolution of the integral of +the solver variables on user defined composites. By default this file is called +\inltt{session.int} where \inltt{session} is the session name. + +The following parameters are supported: + +\begin{center} + \begin{tabularx}{0.99\textwidth}{lllX} + \toprule + \textbf{Option name} & \textbf{Required} & \textbf{Default} & + \textbf{Description} \\ + \midrule + \inltt{OutputFile} & \xmark & \inltt{session} & + Prefix of the output filename to which the integrals are written.\\ + \inltt{OutputFrequency} & \xmark & 1 & + Number of timesteps after which output is written.\\ + \inltt{OutputPrecision} & \xmark & 7 & + Precision with which the output is written.\\ + \inltt{Composites} & \cmark & - & + Composites on which to calculate the integral.\\ + \bottomrule + \end{tabularx} +\end{center} + +Multiple composites can be defined together by using ranges with each composite +grouping producing a summed output for each variable in the \inltt{OutputFile}. +For example \inltt{C[1,3,5-7]} would produce a single integral output for each +variable whilst \inltt{C[1-3], C[4]} would produce two. + +Only composites of the same or one dimension below the mesh are supported. + +An example syntax is given below: + +\begin{lstlisting}[style=XMLStyle,gobble=2] + + IntegralFile + 10 + 12 + C[1], C[2-4,6] + +\end{lstlisting} + \subsection{FieldConvert checkpoints} This filter applies a sequence of FieldConvert modules to the solution, -- GitLab From c92ba6c3e6aa16da20ebdc0428009fafa076e23f Mon Sep 17 00:00:00 2001 From: vidhi Date: Mon, 6 Jul 2020 18:04:49 -0600 Subject: [PATCH 051/408] 1D derivative implementation --- library/Demos/StdRegions/CMakeLists.txt | 2 + library/Demos/StdRegions/StdInterpDeriv.cpp | 105 ++++++++++++++++ library/StdRegions/StdExpansion.cpp | 10 ++ library/StdRegions/StdExpansion.h | 127 +++++++++++++++++++- library/StdRegions/StdExpansion0D.cpp | 35 +++--- library/StdRegions/StdExpansion1D.cpp | 13 +- library/StdRegions/StdExpansion1D.h | 3 + library/StdRegions/StdExpansion2D.cpp | 10 ++ library/StdRegions/StdExpansion2D.h | 4 + library/StdRegions/StdExpansion3D.cpp | 8 ++ library/StdRegions/StdExpansion3D.h | 3 + library/StdRegions/StdSegExp.cpp | 1 + library/StdRegions/StdTriExp.cpp | 89 +++++++++++++- 13 files changed, 387 insertions(+), 23 deletions(-) create mode 100644 library/Demos/StdRegions/StdInterpDeriv.cpp diff --git a/library/Demos/StdRegions/CMakeLists.txt b/library/Demos/StdRegions/CMakeLists.txt index ab8f333ec..48db67412 100644 --- a/library/Demos/StdRegions/CMakeLists.txt +++ b/library/Demos/StdRegions/CMakeLists.txt @@ -2,6 +2,8 @@ ADD_NEKTAR_EXECUTABLE(StdProject COMPONENT demos DEPENDS StdRegions SOURCES StdProject.cpp) ADD_NEKTAR_EXECUTABLE(StdInterp COMPONENT demos DEPENDS StdRegions SOURCES StdInterp.cpp) +ADD_NEKTAR_EXECUTABLE(StdInterpDeriv + COMPONENT demos DEPENDS StdRegions SOURCES StdInterpDeriv.cpp) ADD_NEKTAR_EXECUTABLE(StdInterpBasis COMPONENT demos DEPENDS StdRegions SOURCES StdInterpBasis.cpp) ADD_NEKTAR_EXECUTABLE(StdEquiToCoeff2D diff --git a/library/Demos/StdRegions/StdInterpDeriv.cpp b/library/Demos/StdRegions/StdInterpDeriv.cpp new file mode 100644 index 000000000..386a17078 --- /dev/null +++ b/library/Demos/StdRegions/StdInterpDeriv.cpp @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File: StdInterp.cpp +// +// For more information, please see: http://www.nektar.info +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: Demo for testing functionality of PhysEvaluateDeriv +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "StdDemoSupport.hpp" + +// Evaluate polynomial for testing and save in ret (size same as pts[0]) if +// tensorp = 0, we need tensorprod else just eval at pts +Array EvalPolyDerivx(Array> &pts) +{ + Array ret(pts[0].size()); + unsigned dim = pts.size(); + + // check if pts[0] and pts[1] have same size + // polynomial = x^2 + y^2 - 3x - 4 + // derivative in x = 2x - 3 + + for (int i = 0; i < pts[0].size(); i++) + { + ret[i] = 2*pts[0][i] - 3.0 + + (dim >= 2 ? pow(pts[1][i], 2) : 0.0) + + (dim >= 3 ? pow(pts[2][i], 2) : 0.0); + } + return ret; +} + +int main(int argc, char *argv[]) +{ + DemoSupport demo; + demo.ParseArguments(argc, argv); + StdExpansion *E = demo.CreateStdExpansion(); + + const auto totPoints = (unsigned) E->GetTotPoints(); + const auto dimension = (unsigned) E->GetShapeDimension(); + + // Create a new element but with the evenly-spaced points type, so that we + // perform a PhysEvaluateDeriv at a different set of nodal points + // (i.e. non-collocated interpolation). + vector &ptypes = demo.GetPointsType(); + for (int i = 0; i < dimension; ++i) + { + ptypes[i] = "PolyEvenlySpaced"; + } + StdExpansion *F = demo.CreateStdExpansion(); + + Array> coordsE = demo.GetCoords(E); + Array> coordsF = demo.GetCoords(F); + Array physIn(totPoints), physOut(totPoints); + Array tmpIn(dimension), sol(totPoints); + + // Evaluate polynomial at the set of elemental solution points. + physIn = EvalPolyDerivx(coordsE); + + for (int i = 0; i < totPoints; ++i) + { + for (int d = 0; d < dimension; ++d) + { + tmpIn[d] = coordsF[d][i]; + } + physOut[i] = E->PhysEvaluateDeriv(tmpIn, physIn); + + } + + + sol = EvalPolyDerivx(coordsF); + + cout << "L infinity error : " << scientific << E->Linf(physOut, sol) << endl; + cout << "L 2 error : " << scientific << E->L2 (physOut, sol) << endl; + + return 0; +} + diff --git a/library/StdRegions/StdExpansion.cpp b/library/StdRegions/StdExpansion.cpp index 57b5db304..dec30a1fe 100644 --- a/library/StdRegions/StdExpansion.cpp +++ b/library/StdRegions/StdExpansion.cpp @@ -1191,6 +1191,16 @@ namespace Nektar return 0; } + NekDouble StdExpansion::v_PhysEvaluateDeriv + (const Array& coords, + const Array& physvals) + { + boost::ignore_unused(coords, physvals); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + NekDouble StdExpansion::v_PhysEvaluate (const Array & I, diff --git a/library/StdRegions/StdExpansion.h b/library/StdRegions/StdExpansion.h index 4badd13dc..4446aeb71 100644 --- a/library/StdRegions/StdExpansion.h +++ b/library/StdRegions/StdExpansion.h @@ -929,6 +929,11 @@ namespace Nektar return v_PhysEvaluate(coords,physvals); } + NekDouble PhysEvaluateDeriv(const Array& coords, + const Array& physvals) + { + return v_PhysEvaluateDeriv(coords,physvals); + } /** \brief This function evaluates the expansion at a single * (arbitrary) point of the domain @@ -975,6 +980,27 @@ namespace Nektar return v_PhysEvaluateBasis(coords, mode); } + + /** + * @brief This function evaluates the derivative of basis function mode + * @p mode at a point @p coords of the domain. + * + * This function uses barycentric interpolation with the tensor + * product separation of the basis function to improve performance. + * + * @param coord The coordinate inside the standard region. + * @param mode The mode number to be evaluated. + * + * @return The value of the derivative of the basis function @p mode at @p coords. + */ + NekDouble PhysEvaluateDerivBasis( + const Array& coords, + int mode) + { + return v_PhysEvaluateBasis(coords, mode); + } + + /** * \brief Convert local cartesian coordinate \a xi into local * collapsed coordinates \a eta @@ -1354,6 +1380,70 @@ namespace Nektar return numer / denom; } +/** + * @brief This function performs the barycentric interpolation of + * the derivative of the polynomial stored in @p coord at a point + * @p physvals using barycentric interpolation weights in direction @tparam DIR. + * + * This method is intended to be used a helper function for + * StdExpansion::PhysDeriv and its elemental instances, so that + * the calling method should provide @p coord for x, y and z + * sequentially and the appropriate @p physvals and @p weights for + * that particular direction. + * + * @param coord The coordinate of the single point. + * @param physvals The polynomial stored at each quadrature point. + * @tparam DIR The direction of evaluation. + * + * @return The value of @p physvals at @p coord in direction @p dir. + */ + template + inline NekDouble BaryEvaluateDeriv( + const NekDouble &coord, + const NekDouble *physvals) + { + NekDouble numer1 = 0.0, denom = 0.0; + NekDouble numer2 = 0.0, numer3 = 0.0, + numer4 = 0.0; + ASSERTL2(DIR < m_base.size(), + "Direction should be less than shape dimension."); + + const Array &z = m_base[DIR]->GetZ(); + const Array &bw = + m_base[DIR]->GetBaryWeights(); + + const auto nquad = z.size(); + + for (int i = 0; i < nquad; ++i) + { + NekDouble xdiff = z[i] - coord; + NekDouble pval = physvals[i]; + + /* + * (in this specific case) you actually + * want to do the comparison exactly + * (believe it or not!) See chapter 7 of + * the paper here: + *https://people.maths.ox.ac.uk/trefethen/barycentric.pdf + */ + if (xdiff == 0.0) + { + return pval; + } + + NekDouble tmp = bw[i] / xdiff; + NekDouble tmp2 = bw[i] / pow(xdiff,2); + numer1 += (tmp2 * pval); + numer2 += (tmp); + numer3 += (tmp * pval); + numer4 += (tmp2); + denom += tmp; + } + + return (numer1*numer2 + numer3*numer4) / pow(denom,2); + } + + /** * @brief This function evaluates the basis function mode @p mode at * a point @p coords of the domain in direction @dir. @@ -1373,7 +1463,25 @@ namespace Nektar return BaryEvaluate( coord, &(m_base[DIR]->GetBdata())[0] + nquad * mode); } - + /** + * @brief This function evaluates the derivative of the basis function + * mode @p mode at a point @p coords of the domain in direction @dir. + * + * @param coord The coordinate inside the standard region. + * @param mode The mode number to be evaluated of #m_base[dir] + * @param dir The direction of interpolation. + * + * @return The value of the basis function @p mode at @p coords in + * direction @p dir. + */ + template + inline NekDouble BaryEvaluateDerivBasis(const NekDouble &coord, + const int &mode) + { + const int nquad = m_base[DIR]->GetNumPoints(); + return BaryEvaluateDeriv( + coord, &(m_base[DIR]->GetBdata())[0] + nquad * mode); + } private: // Virtual functions STD_REGIONS_EXPORT virtual int v_GetNverts() const = 0; @@ -1501,11 +1609,7 @@ namespace Nektar const Array& inarray, Array &outarray); - STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate - (const Array& coords, - const Array & physvals); - + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate (const Array& I, const Array & physvals); @@ -1513,6 +1617,17 @@ namespace Nektar STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateBasis (const Array& coords, int mode); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv + (const Array& coords, + const Array& physvals); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate + (const Array& coords, + const Array& physvals); + + STD_REGIONS_EXPORT virtual void v_LocCoordToLocCollapsed( const Array& xi, Array& eta); diff --git a/library/StdRegions/StdExpansion0D.cpp b/library/StdRegions/StdExpansion0D.cpp index 6efd1426b..f6fba3de5 100644 --- a/library/StdRegions/StdExpansion0D.cpp +++ b/library/StdRegions/StdExpansion0D.cpp @@ -66,21 +66,28 @@ namespace Nektar void StdExpansion0D::PhysTensorDeriv(const Array& inarray, Array& outarray) { - int nquad = GetTotPoints(); - DNekMatSharedPtr D = m_base[0]->GetD(); + + int nquad = GetTotPoints(); + Array wsp(nquad); + wsp = m_base[0]->GetBdata(); + for(int i = 0; i < outarray.size(); i++) + { + outarray[i] = StdExpansion::BaryEvaluateDeriv<0>(inarray[i], &wsp[0]); + } + // DNekMatSharedPtr D = m_base[0]->GetD(); - if( inarray.data() == outarray.data()) - { - Array wsp(nquad); - CopyArray(inarray, wsp); - Blas::Dgemv('N',nquad,nquad,1.0,&(D->GetPtr())[0],nquad, - &wsp[0],1,0.0,&outarray[0],1); - } - else - { - Blas::Dgemv('N',nquad,nquad,1.0,&(D->GetPtr())[0],nquad, - &inarray[0],1,0.0,&outarray[0],1); - } + // if( inarray.data() == outarray.data()) + // { + // Array wsp(nquad); + // CopyArray(inarray, wsp); + // Blas::Dgemv('N',nquad,nquad,1.0,&(D->GetPtr())[0],nquad, + // &wsp[0],1,0.0,&outarray[0],1); + // } + // else + // { + // Blas::Dgemv('N',nquad,nquad,1.0,&(D->GetPtr())[0],nquad, + // &inarray[0],1,0.0,&outarray[0],1); + // } } NekDouble StdExpansion0D::v_PhysEvaluate(const Array& Lcoord, const Array& physvals) diff --git a/library/StdRegions/StdExpansion1D.cpp b/library/StdRegions/StdExpansion1D.cpp index 797854c7b..fbcb4d33e 100644 --- a/library/StdRegions/StdExpansion1D.cpp +++ b/library/StdRegions/StdExpansion1D.cpp @@ -66,6 +66,7 @@ namespace Nektar void StdExpansion1D::PhysTensorDeriv(const Array& inarray, Array& outarray) { + int nquad = GetTotPoints(); DNekMatSharedPtr D = m_base[0]->GetD(); @@ -80,7 +81,16 @@ namespace Nektar { Blas::Dgemv('N',nquad,nquad,1.0,&(D->GetPtr())[0],nquad, &inarray[0],1,0.0,&outarray[0],1); - } + } + } + + NekDouble StdExpansion1D::v_PhysEvaluateDeriv( + const Array& coords, + const Array& physvals) + { + + return StdExpansion::BaryEvaluate<0>(coords[0], &physvals[0]); + } NekDouble StdExpansion1D::v_PhysEvaluate( @@ -93,5 +103,6 @@ namespace Nektar return StdExpansion::BaryEvaluate<0>(Lcoord[0], &physvals[0]); } + }//end namespace }//end namespace diff --git a/library/StdRegions/StdExpansion1D.h b/library/StdRegions/StdExpansion1D.h index e614ac0ca..20d057406 100644 --- a/library/StdRegions/StdExpansion1D.h +++ b/library/StdRegions/StdExpansion1D.h @@ -74,6 +74,9 @@ namespace Nektar STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& coords, const Array& physvals) override; + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv( + const Array& coords, + const Array& physvals) override; private: diff --git a/library/StdRegions/StdExpansion2D.cpp b/library/StdRegions/StdExpansion2D.cpp index cd2ecbd15..181cf7b7b 100644 --- a/library/StdRegions/StdExpansion2D.cpp +++ b/library/StdRegions/StdExpansion2D.cpp @@ -112,6 +112,14 @@ namespace Nektar } } + NekDouble StdExpansion2D::v_PhysEvaluateDeriv( + const Array &coords, + const Array &physvals) + { + boost::ignore_unused(coords, physvals); + return 0.0; + } + NekDouble StdExpansion2D::v_PhysEvaluate( const Array &coords, const Array &physvals) @@ -141,6 +149,8 @@ namespace Nektar return StdExpansion::BaryEvaluate<1>(coll[1], &wsp[0]); } + + NekDouble StdExpansion2D::v_PhysEvaluate( const Array &I, const Array &physvals) diff --git a/library/StdRegions/StdExpansion2D.h b/library/StdRegions/StdExpansion2D.h index c43961606..074e2a047 100644 --- a/library/StdRegions/StdExpansion2D.h +++ b/library/StdRegions/StdExpansion2D.h @@ -144,6 +144,10 @@ namespace StdRegions const Array& coords, const Array& physvals); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv( + const Array& coords, + const Array& physvals) override; + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& I, const Array & physvals); diff --git a/library/StdRegions/StdExpansion3D.cpp b/library/StdRegions/StdExpansion3D.cpp index 4ad2d79bb..d987f74ad 100644 --- a/library/StdRegions/StdExpansion3D.cpp +++ b/library/StdRegions/StdExpansion3D.cpp @@ -139,6 +139,14 @@ namespace Nektar v_IProductWRTBase_SumFacKernel(base0, base1, base2, inarray, outarray, wsp, doCheckCollDir0, doCheckCollDir1, doCheckCollDir2); } + + NekDouble StdExpansion3D::v_PhysEvaluateDeriv( + const Array &coords, + const Array &physvals) + { + boost::ignore_unused(coords, physvals); + return 0.0; + } NekDouble StdExpansion3D::v_PhysEvaluate( const Array &coords, const Array &physvals) diff --git a/library/StdRegions/StdExpansion3D.h b/library/StdRegions/StdExpansion3D.h index f969f236c..88b70fb9f 100644 --- a/library/StdRegions/StdExpansion3D.h +++ b/library/StdRegions/StdExpansion3D.h @@ -180,6 +180,9 @@ namespace Nektar const Array& coords, const Array& physvals); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv( + const Array& coords, + const Array& physvals); STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& I, diff --git a/library/StdRegions/StdSegExp.cpp b/library/StdRegions/StdSegExp.cpp index c67cdac64..9c312df7c 100644 --- a/library/StdRegions/StdSegExp.cpp +++ b/library/StdRegions/StdSegExp.cpp @@ -531,6 +531,7 @@ namespace Nektar return StdExpansion::BaryEvaluateBasis<0>(coords[0], mode); } + void StdSegExp::v_LaplacianMatrixOp( const Array &inarray, Array &outarray, diff --git a/library/StdRegions/StdTriExp.cpp b/library/StdRegions/StdTriExp.cpp index ef6d9e8c5..2e80c4cd0 100644 --- a/library/StdRegions/StdTriExp.cpp +++ b/library/StdRegions/StdTriExp.cpp @@ -136,8 +136,93 @@ namespace Nektar Array& out_d2) { boost::ignore_unused(out_d2); + Array coll(2); + LocCoordToLocCollapsed(inarray,coll); + //coll = inarray; + //const Array& z0 = m_base[0]->GetZ(); + //const Array& z1 = m_base[1]->GetZ(); - int i; + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + //Array wsp(std::max(nq0, nq1)); + Array wsp2(std::max(nq0, nq1)); + //Array wsp3(std::max(nq0, nq1)); + + // set up geometric factor: 2/(1-z1) + //Vmath::Sadd(nq1, -1.0, z1, 1, wsp, 1); + //Vmath::Sdiv(nq1, -2.0, wsp, 1, wsp, 1); + + if (out_d0.size() > 0) + { + + for (int i = 0; i < nq1; ++i) + { + wsp2[i] = StdExpansion::BaryEvaluateDeriv<0>( + coll[0], &inarray[0] + i * nq0); + } + out_d0 = wsp2; + // for (int i = 0; i < nq1; ++i) + // { + // Blas::Dscal(nq0,wsp[i],&out_d0[0]+i*nq1,1); + // } + // if no d1 required do not need to calculate both deriv + if (out_d1.size() > 0) + { + // set up geometric factor: (1_z0)/(1-z1) + // Vmath::Sadd(nq0, 1.0, z0, 1, wsp, 1); + // Vmath::Smul(nq0, 0.5, wsp, 1, wsp, 1); + + // for (int i = 0; i < nq1; ++i) + // { + + // Vmath::Vvtvp(nq0,&wsp[0],1,&out_d0[0]+i*nq0, + // 1,&out_d1[0]+i*nq0, + // 1,&out_d1[0]+i*nq0,1); + // } + + for (int i = 0; i < nq0; ++i) + { + wsp2[i] = StdExpansion::BaryEvaluateDeriv<1>( + coll[0], &inarray[0] + i * nq1); + } + out_d1 = wsp2; + + } + + } + else if (out_d1.size() > 0) + { + + // for (int i = 0; i < nq1; ++i) + // { + // wsp3[i] = StdExpansion::BaryEvaluateDeriv<0>( + // coll[0], &inarray[0] + i * nq0); + // } + + for (int i = 0; i < nq0; ++i) + { + wsp2[i] = StdExpansion::BaryEvaluateDeriv<1>( + coll[0], &inarray[0] + i * nq1); + } + out_d1 = wsp2; + + // for (int i = 0; i < nq1; ++i) + // { + // Blas::Dscal(nq0,wsp[i],&wsp3[0]+i*nq0,1); + // } + + // Vmath::Sadd(nq0, 1.0, z0, 1, wsp, 1); + // Vmath::Smul(nq0, 0.5, wsp, 1, wsp, 1); + + // for (int i = 0; i < nq1; ++i) + // { + // Vmath::Vvtvp(nq0,&wsp[0],1,&wsp3[0]+i*nq0, + // 1,&out_d1[0]+i*nq0, + // 1,&out_d1[0]+i*nq0,1); + // } + } + + /* int i; int nquad0 = m_base[0]->GetNumPoints(); int nquad1 = m_base[1]->GetNumPoints(); Array wsp(std::max(nquad0, nquad1)); @@ -192,7 +277,7 @@ namespace Nektar 1,&out_d1[0]+i*nquad0, 1,&out_d1[0]+i*nquad0,1); } - } + }*/ } void StdTriExp::v_PhysDeriv( -- GitLab From 2669f4dc10c94428e75aac20dcfb5fd349e144c1 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 7 Jul 2020 09:27:28 +0100 Subject: [PATCH 052/408] More parallelisation progress --- .../AssemblyMap/InterfaceMapDG.cpp | 126 ++++++++++++++---- .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 21 ++- library/MultiRegions/DisContField2D.cpp | 17 ++- library/MultiRegions/DisContField2D.h | 2 - library/SpatialDomains/Interface.cpp | 92 +------------ library/SpatialDomains/Interface.h | 37 ++++- 6 files changed, 168 insertions(+), 127 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index 00023d542..ae0fa7c7c 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -41,10 +41,12 @@ namespace MultiRegions InterfaceMapDG::InterfaceMapDG( const SpatialDomains::InterfacesSharedPtr &interfaces, - const ExpList &locExp, const ExpListSharedPtr &trace, + const ExpListSharedPtr &trace, const std::map geomIdToTraceId) + : m_trace(trace), + m_geomIdToTraceId(geomIdToTraceId) { - auto comm = trace->GetComm(); + auto comm = m_trace->GetComm(); auto interfaceCollection = interfaces->GetInterfaces(); // myIndxLR contains the info about what interface edges are present on @@ -92,14 +94,13 @@ InterfaceMapDG::InterfaceMapDG( rankLocalInterfaceDisp); // Find what interface Ids match with other ranks, then check if opposite edge + std::map> leftEdgeOppRanks; // Map of interface Id to vector of ranks with the opposite edge + std::map> rightEdgeOppRanks; + std::map checkLocal; + size_t myRank = comm->GetRank(); for (size_t i = 0; i < nRanks; ++i) { - if (i == myRank) - { - continue; - } - for (size_t j = 0; j < rankNumInterfaces[i] / 2; ++j) { int otherId = @@ -110,42 +111,119 @@ InterfaceMapDG::InterfaceMapDG( InterfaceExchangeSharedPtr exchange; if (myIndxLRMap.find(otherId) != myIndxLRMap.end()) { - // `Set` interface opposite ranks (could probably simplify logic + if (i == myRank) + { + //If contains opposite edge locally then set true + if (otherCode == 3) + { + checkLocal[otherId] = true; + } + + continue; + } + + // Interface opposite ranks (could probably simplify logic // here but this is easy to understand int myCode = myIndxLRMap[otherId]; if ((myCode == 1 && otherCode == 2) || (myCode == 1 && otherCode == 3) || (myCode == 3 && otherCode == 2)) { - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[otherId]->GetLeftInterface(), i)); + leftEdgeOppRanks[otherId].emplace_back(i); } else if ((myCode == 2 && otherCode == 1) || (myCode == 2 && otherCode == 3) || (myCode == 3 && otherCode == 1)) { - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[otherId]->GetRightInterface(), - i)); + rightEdgeOppRanks[otherId].emplace_back(i); } else if (myCode == 3 && otherCode == 3) { - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[otherId]->GetLeftInterface(), i)); - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[otherId]->GetRightInterface(), - i)); + leftEdgeOppRanks[otherId].emplace_back(i); + rightEdgeOppRanks[otherId].emplace_back(i); + } } } } + + // Create individual interface exchange objects + for (auto interface : interfaceCollection) + { + int interfaceId = interface.first; + + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[interfaceId]->GetLeftInterface(), + leftEdgeOppRanks[interfaceId], + checkLocal[interfaceId])); + + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[interfaceId]->GetRightInterface(), + rightEdgeOppRanks[interfaceId], + checkLocal[interfaceId])); + } } -std::vector> CalcCoordsOneWay( +void InterfaceExchange::CalcLocalCoordsReturnTrace(ExpListSharedPtr &trace, std::map geomIdToTraceId) +{ + auto graph = trace->GetGraph(); + Array> geomEdgeIdLocalCoordPair(m_interface->GetTotPoints()); + Array> missingCoords(m_interface->GetTotPoints()); + if(m_checkLocal) + { + int cnt = 0; + auto childEdgeIds = m_interface->GetEdgeIds(); + auto parentEdgeIds = m_interface->GetOppInterface()->GetEdgeIds(); + for (auto childId : childEdgeIds) + { + auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq); + childElmt->GetCoords(xc, yc); + + // Check local interface + for (int i = 0; i < nq; ++i) + { + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + + bool found = false; + int foundEdgeId = -1; + NekDouble foundLocCoord = -1; + + for (auto parentId : parentEdgeIds) + { + SpatialDomains::SegGeomSharedPtr searchSeg = + std::static_pointer_cast(graph->GetSegGeom(parentId)); + NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); + + if (dist < 1e-8) + { + foundEdgeId = parentId; + //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; + found = true; + break; + } + } + + if(!found) + { + missingCoords[cnt] = xs; + } + + geomEdgeIdLocalCoordPair[cnt] = std::make_pair(foundEdgeId, foundLocCoord); + + cnt++; + } + } + } +} + +/*std::vector> CalcCoordsOneWay( const SpatialDomains::InterfaceBaseShPtr &child, const SpatialDomains::InterfaceBaseShPtr &parent, const ExpListSharedPtr &trace, @@ -259,7 +337,7 @@ void InterfaceExchange::CalcLocalInterfaceCoords() pair->SetCalcFlag(false); } } -} +}*/ } // namespace MultiRegions } // namespace Nektar \ No newline at end of file diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h index 6a83cc4bd..aae81df65 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -53,14 +53,24 @@ public: /// Default constructor MULTI_REGIONS_EXPORT InterfaceExchange( const SpatialDomains::InterfaceBaseShPtr &interface, - const int &rank) + const std::vector &ranks, + const bool &checkLocal) : m_interface(interface), - m_rank(rank) + m_ranks(ranks), + m_checkLocal(checkLocal) { } + + void CalcLocalCoordsReturnTrace(ExpListSharedPtr &trace, std::map geomIdToTraceId); + void ReturnTrace(); + + MULTI_REGIONS_EXPORT void PerformExchange(); private: SpatialDomains::InterfaceBaseShPtr m_interface; - int m_rank; + std::vector m_ranks; + bool m_checkLocal; + Array m_localQuadCoords; + }; typedef std::shared_ptr InterfaceExchangeSharedPtr; @@ -74,11 +84,14 @@ public: // Constructor for interface communication MULTI_REGIONS_EXPORT InterfaceMapDG( const SpatialDomains::InterfacesSharedPtr &interfaces, - const ExpList &locExp, const ExpListSharedPtr &trace, + const ExpListSharedPtr &trace, const std::map geomIdToTraceId); + private: + const ExpListSharedPtr m_trace; std::vector m_exchange; + std::map m_geomIdToTraceId; }; typedef std::shared_ptr InterfaceMapDGSharedPtr; diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index e353b7f60..51af335fa 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -450,7 +450,7 @@ namespace Nektar geomIdToTraceId[m_trace->GetExp(i)->GetGeom()->GetGlobalID()] = i; } - + // Create interface exchange object m_interfaceMap = MemoryManager:: AllocateSharedPtr(m_interfaces, m_trace, geomIdToTraceId); @@ -461,7 +461,7 @@ namespace Nektar auto leftInterface = interface.second->GetLeftInterface(); for (auto id : leftInterface->GetEdgeIds()) { - tmp += m_trace->GetExp(m_geomIdToTraceId[id])->GetTotPoints(); + tmp += m_trace->GetExp(geomIdToTraceId[id])->GetTotPoints(); } leftInterface->SetTotPoints(tmp); @@ -469,15 +469,14 @@ namespace Nektar auto rightInterface = interface.second->GetRightInterface(); for (auto id : leftInterface->GetEdgeIds()) { - tmp += m_trace->GetExp(m_geomIdToTraceId[id])->GetTotPoints(); + tmp += m_trace->GetExp(geomIdToTraceId[id])->GetTotPoints(); } rightInterface->SetTotPoints(tmp); } - m_interfaces->CommSetup(m_comm); - int cnt, n, e; + int cnt, n, e; // Identify boundary edges for (cnt = 0, n = 0; n < m_bndCondExpansions.size(); ++n) { @@ -1396,9 +1395,13 @@ namespace Nektar } DisContField2D::v_PeriodicBwdCopy(Fwd, Bwd); - // Interpolate from each side of the interface to the other. + + m_interfaceMap->CalcLocalInterfaceCoords(); + + /* // Interpolate from each side of the interface to the other. CalcLocalInterfaceCoords(); + for (auto &interface : m_interfaces->GetInterfaces()) { size_t indx = interface.first; @@ -1443,7 +1446,7 @@ namespace Nektar ->StdPhysEvaluate(foundPointArray, edgePhys); } } - } + }*/ } void DisContField2D::v_AddTraceQuadPhysToField( diff --git a/library/MultiRegions/DisContField2D.h b/library/MultiRegions/DisContField2D.h index 916885967..c067256df 100644 --- a/library/MultiRegions/DisContField2D.h +++ b/library/MultiRegions/DisContField2D.h @@ -377,8 +377,6 @@ namespace Nektar inline virtual const LocTraceToTraceMapSharedPtr &v_GetLocTraceToTraceMap() const; - - void CalcLocalInterfaceCoords(); }; void DisContField2D::v_GetFwdBwdTracePhys( diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index a96ff1728..74c501764 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -207,101 +207,15 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) ASSERTL0(interfacePair.second.size() == 2, "Every interface ID must have two domains associated with it") + interfacePair.second[0]->SetOppInterface(interfacePair.second[1]); + interfacePair.second[1]->SetOppInterface(interfacePair.second[0]); + m_interfaces[interfacePair.first] = MemoryManager::AllocateSharedPtr( interfacePair.second[0], interfacePair.second[1]); } } -void Interfaces::CommSetup(LibUtilities::CommSharedPtr &comm) -{ - // myIndxLR contains the info about what interface edges are present on - // current rank with each interface no, i, consisting of: - // [i] = indx - // [i + 1] = 0 (non), = 1 (left only), = 2 (right only), = 3 (both) - - Array myIndxLR(m_interfaces.size() * 2, 0); - std::map myIndxLRMap; - size_t cnt = 0; - for (const auto &interface : m_interfaces) - { - myIndxLR[2 * cnt] = interface.first; - - if(!interface.second->GetLeftInterface()->IsEmpty()) - { - myIndxLR[2 * cnt + 1] += 1; - } - if (!interface.second->GetRightInterface()->IsEmpty()) - { - myIndxLR[2 * cnt + 1] += 2; - } - - myIndxLRMap[interface.first] = myIndxLR[2 * cnt + 1]; - cnt++; - } - - - //Send num of interfaces size so all partitions can prepare buffers - int nRanks = comm->GetSize(); - Array rankNumInterfaces(nRanks); - Array localInterfaceSize(1, myIndxLR.size()); - comm->AllGather(localInterfaceSize, rankNumInterfaces); - - Array rankLocalInterfaceDisp(nRanks, 0); - for (size_t i = 1; i < nRanks; ++i) - { - rankLocalInterfaceDisp[i] = rankLocalInterfaceDisp[i - 1] + rankNumInterfaces[i - 1]; - } - - Array rankLocalInterfaceIds( - std::accumulate(rankNumInterfaces.begin(), rankNumInterfaces.end(), 0), 0); - - // Send all interface IDs to all partitions - comm->AllGatherv(myIndxLR, rankLocalInterfaceIds, rankNumInterfaces, - rankLocalInterfaceDisp); - - // Find what interface Ids match with other ranks, then check if opposite edge - size_t myRank = comm->GetRank(); - for (size_t i = 0; i < nRanks; ++i) - { - if (i == myRank) - { - continue; - } - - for (size_t j = 0; j < rankNumInterfaces[i] / 2; ++j) - { - int otherId = - rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j]; - int otherCode = - rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j + 1]; - if (myIndxLRMap.find(otherId) != myIndxLRMap.end()) - { - // Set interface opposite ranks (could probably simplify logic - // here but this is easy to understand - int myCode = myIndxLRMap[otherId]; - if ((myCode == 1 && otherCode == 2) || - (myCode == 1 && otherCode == 3) || - (myCode == 3 && otherCode == 2)) - { - m_interfaces[otherId]->GetLeftInterface()->AddOppRank(i); - } - else if ((myCode == 2 && otherCode == 1) || - (myCode == 2 && otherCode == 3) || - (myCode == 3 && otherCode == 1)) - { - m_interfaces[otherId]->GetRightInterface()->AddOppRank(i); - } - else if (myCode == 3 && otherCode == 3) - { - m_interfaces[otherId]->GetLeftInterface()->AddOppRank(i); - m_interfaces[otherId]->GetRightInterface()->AddOppRank(i); - } - } - } - } -} - void InterfacePair::SeparateGraph(MeshGraphSharedPtr &graph) const { auto rightDomain = m_rightInterface->GetDomain(); diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index e2c12e3bd..91f17a73b 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -66,6 +66,9 @@ enum InterfaceSide struct Composite; typedef std::map> CompositeMap; +struct InterfaceBase; +typedef std::shared_ptr InterfaceBaseShPtr; + struct InterfaceBase { InterfaceBase(InterfaceType type, CompositeMap domain) @@ -125,13 +128,46 @@ struct InterfaceBase m_side = side; } + inline void SetTotPoints(const int &points) + { + m_totPoints = points; + } + + inline int &GetTotPoints() + { + return m_totPoints; + } + + inline void AddOppRank(const int &rank) + { + m_oppRanks.emplace_back(rank); + } + + inline std::vector &GetOppRanks() + { + return m_oppRanks; + } + + inline void SetOppInterface(InterfaceBaseShPtr oppInterface) + { + m_oppInterface = oppInterface; + } + + inline InterfaceBaseShPtr GetOppInterface() + { + return m_oppInterface; + } + protected: + InterfaceBaseShPtr m_oppInterface; InterfaceType m_type; InterfaceSide m_side = eNone; CompositeMap m_domain; std::map m_edge; std::vector m_edgeIds; CompositeMap m_interfaceEdge; + int m_totPoints; + std::vector m_oppRanks; }; struct RotatingInterface : public InterfaceBase @@ -173,7 +209,6 @@ struct FixedInterface : public InterfaceBase } }; -typedef std::shared_ptr InterfaceBaseShPtr; typedef std::shared_ptr RotatingInterfaceShPtr; typedef std::shared_ptr FixedInterfaceShPtr; -- GitLab From 8e81a365c28603df1249033ba811bb753fba9f56 Mon Sep 17 00:00:00 2001 From: vidhi Date: Fri, 10 Jul 2020 16:27:49 -0600 Subject: [PATCH 053/408] quad physeval and physbasiseval derivatives done. Triangle physevalderiv done --- library/Demos/StdRegions/CMakeLists.txt | 2 + library/Demos/StdRegions/StdInterpDeriv.cpp | 88 +++++++-- library/StdRegions/StdExpansion.cpp | 85 ++++++++- library/StdRegions/StdExpansion.h | 95 +++++++++- library/StdRegions/StdExpansion1D.cpp | 13 +- library/StdRegions/StdExpansion1D.h | 6 +- library/StdRegions/StdExpansion2D.cpp | 14 +- library/StdRegions/StdExpansion2D.h | 8 +- library/StdRegions/StdQuadExp.cpp | 184 +++++++++++++++++- library/StdRegions/StdQuadExp.h | 23 +++ library/StdRegions/StdTriExp.cpp | 199 ++++++++++---------- library/StdRegions/StdTriExp.h | 17 ++ 12 files changed, 592 insertions(+), 142 deletions(-) diff --git a/library/Demos/StdRegions/CMakeLists.txt b/library/Demos/StdRegions/CMakeLists.txt index 48db67412..ba7bed537 100644 --- a/library/Demos/StdRegions/CMakeLists.txt +++ b/library/Demos/StdRegions/CMakeLists.txt @@ -6,6 +6,8 @@ ADD_NEKTAR_EXECUTABLE(StdInterpDeriv COMPONENT demos DEPENDS StdRegions SOURCES StdInterpDeriv.cpp) ADD_NEKTAR_EXECUTABLE(StdInterpBasis COMPONENT demos DEPENDS StdRegions SOURCES StdInterpBasis.cpp) +ADD_NEKTAR_EXECUTABLE(StdInterpDerivBasis + COMPONENT demos DEPENDS StdRegions SOURCES StdInterpDerivBasis.cpp) ADD_NEKTAR_EXECUTABLE(StdEquiToCoeff2D COMPONENT demos DEPENDS StdRegions SOURCES StdEquiToCoeff2D.cpp) diff --git a/library/Demos/StdRegions/StdInterpDeriv.cpp b/library/Demos/StdRegions/StdInterpDeriv.cpp index 386a17078..acb7be65a 100644 --- a/library/Demos/StdRegions/StdInterpDeriv.cpp +++ b/library/Demos/StdRegions/StdInterpDeriv.cpp @@ -42,17 +42,47 @@ Array EvalPolyDerivx(Array> &pts) { Array ret(pts[0].size()); - unsigned dim = pts.size(); + // unsigned dim = pts.size(); // check if pts[0] and pts[1] have same size - // polynomial = x^2 + y^2 - 3x - 4 - // derivative in x = 2x - 3 + // polynomial = x^2 + y^2 - z^2 + 3x - 9z + // derivative in x = 2x + 3 for (int i = 0; i < pts[0].size(); i++) { - ret[i] = 2*pts[0][i] - 3.0 - + (dim >= 2 ? pow(pts[1][i], 2) : 0.0) - + (dim >= 3 ? pow(pts[2][i], 2) : 0.0); + ret[i] = 2*pts[0][i] + 3.0; + } + return ret; +} + +Array EvalPolyDerivy(Array> &pts) +{ + Array ret(pts[0].size()); + //unsigned dim = pts.size(); + + // check if pts[0] and pts[1] have same size + // polynomial = x^2 + y^2 - z^2 + 3x - 9z + // derivative in y = 2y + + for (int i = 0; i < pts[0].size(); i++) + { + ret[i] = 2*pts[1][i]; + } + return ret; +} + +Array EvalPolyDerivz(Array> &pts) +{ + Array ret(pts[0].size()); + //unsigned dim = pts.size(); + + // check if pts[0] and pts[1] have same size + // polynomial = x^2 + y^2 - z^2 + 3x - 9z + // derivative in z = -2z - 9 + + for (int i = 0; i < pts[0].size(); i++) + { + ret[i] = -2*pts[2][i] - 9.0; } return ret; } @@ -78,27 +108,55 @@ int main(int argc, char *argv[]) Array> coordsE = demo.GetCoords(E); Array> coordsF = demo.GetCoords(F); - Array physIn(totPoints), physOut(totPoints); - Array tmpIn(dimension), sol(totPoints); + Array physIn(totPoints), physOut0(totPoints), physOut1(totPoints), physOut2(totPoints); + Array tmpIn(dimension), sol0(totPoints), sol1(totPoints), sol2(totPoints); // Evaluate polynomial at the set of elemental solution points. - physIn = EvalPolyDerivx(coordsE); - + //cout<<"\n physout:\n"; for (int i = 0; i < totPoints; ++i) { for (int d = 0; d < dimension; ++d) { tmpIn[d] = coordsF[d][i]; } - physOut[i] = E->PhysEvaluateDeriv(tmpIn, physIn); + if(dimension>2) + { + physIn = EvalPolyDerivz(coordsE); + + physOut2[i] = E->PhysEvaluatedz(tmpIn, physIn); + } + if(dimension>1) + { + physIn = EvalPolyDerivy(coordsE); + + physOut1[i] = E->PhysEvaluatedy(tmpIn, physIn); + } + if(dimension>0) + { + physIn = EvalPolyDerivx(coordsE); + + physOut0[i] = E->PhysEvaluatedx(tmpIn, physIn); + } + + // cout<<" "<2) + sol2 = EvalPolyDerivz(coordsF); + if(dimension>1) + sol1 = EvalPolyDerivy(coordsF); + if(dimension>0) + sol0 = EvalPolyDerivx(coordsF); + // for(int i = 0; iLinf(physOut0, sol0) + E->Linf(physOut1, sol1)+ E->Linf(physOut2, sol2) << endl; + cout << "L 2 error : " << scientific << E->L2 (physOut0, sol0) + E->L2 (physOut1, sol1) + E->L2 (physOut2, sol2) << endl; - sol = EvalPolyDerivx(coordsF); - - cout << "L infinity error : " << scientific << E->Linf(physOut, sol) << endl; - cout << "L 2 error : " << scientific << E->L2 (physOut, sol) << endl; return 0; } diff --git a/library/StdRegions/StdExpansion.cpp b/library/StdRegions/StdExpansion.cpp index dec30a1fe..a35148e31 100644 --- a/library/StdRegions/StdExpansion.cpp +++ b/library/StdRegions/StdExpansion.cpp @@ -934,7 +934,6 @@ namespace Nektar NEKERROR(ErrorUtil::efatal, "This function is not defined for this shape"); } - NekDouble StdExpansion::v_StdPhysEvaluate(const Array &Lcoord, const Array &physvals) @@ -944,6 +943,7 @@ namespace Nektar return 0; } + void StdExpansion::v_LocCoordToLocCollapsed(const Array& xi,Array& eta) { boost::ignore_unused(xi, eta); @@ -1191,8 +1191,8 @@ namespace Nektar return 0; } - NekDouble StdExpansion::v_PhysEvaluateDeriv - (const Array& coords, const Array& physvals) { @@ -1201,6 +1201,36 @@ namespace Nektar return 0; } + NekDouble StdExpansion::v_PhysEvaluatedy + (const Array& coords, + const Array& physvals) + { + boost::ignore_unused(coords, physvals); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + NekDouble StdExpansion::v_PhysEvaluatedz + (const Array& coords, + const Array& physvals) + { + boost::ignore_unused(coords, physvals); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + NekDouble StdExpansion::v_PhysEvaluateDeriv + (int dir, const Array& coords, + const Array& physvals) + { + boost::ignore_unused(coords, physvals, dir); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + NekDouble StdExpansion::v_PhysEvaluate (const Array & I, @@ -1218,6 +1248,30 @@ namespace Nektar return 0; } + + NekDouble StdExpansion::v_PhysEvaluatedxBasis(const Array& coords, int mode) + { + boost::ignore_unused(coords, mode); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + NekDouble StdExpansion::v_PhysEvaluatedyBasis(const Array& coords, int mode) + { + boost::ignore_unused(coords, mode); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + NekDouble StdExpansion::v_PhysEvaluatedzBasis(const Array& coords, int mode) + { + boost::ignore_unused(coords, mode); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + + void StdExpansion::v_FillMode(const int mode, Array &outarray) { boost::ignore_unused(mode, outarray); @@ -1225,6 +1279,30 @@ namespace Nektar "been defined for this shape"); } + + void StdExpansion::v_FillModedy(const int mode, Array &outarray) + { + boost::ignore_unused(mode, outarray); + NEKERROR(ErrorUtil::efatal, "This function has not " + "been defined for this shape"); + } + + + void StdExpansion::v_FillModedx(const int mode, Array &outarray) + { + boost::ignore_unused(mode, outarray); + NEKERROR(ErrorUtil::efatal, "This function has not " + "been defined for this shape"); + } + + + void StdExpansion::v_FillModedz(const int mode, Array &outarray) + { + boost::ignore_unused(mode, outarray); + NEKERROR(ErrorUtil::efatal, "This function has not " + "been defined for this shape"); + } + DNekMatSharedPtr StdExpansion::v_GenMatrix(const StdMatrixKey &mkey) { boost::ignore_unused(mkey); @@ -1234,6 +1312,7 @@ namespace Nektar return returnval; } + DNekMatSharedPtr StdExpansion::v_CreateStdMatrix(const StdMatrixKey &mkey) { boost::ignore_unused(mkey); diff --git a/library/StdRegions/StdExpansion.h b/library/StdRegions/StdExpansion.h index 4446aeb71..9a3ae5ca4 100644 --- a/library/StdRegions/StdExpansion.h +++ b/library/StdRegions/StdExpansion.h @@ -502,6 +502,21 @@ namespace Nektar v_FillMode(mode, outarray); } + void FillModedx(const int mode, Array &outarray) + { + v_FillModedx(mode, outarray); + } + + void FillModedy(const int mode, Array &outarray) + { + v_FillModedy(mode, outarray); + } + + void FillModedz(const int mode, Array &outarray) + { + v_FillModedz(mode, outarray); + } + /** \brief this function calculates the inner product of a given * function \a f with the different modes of the expansion * @@ -929,10 +944,16 @@ namespace Nektar return v_PhysEvaluate(coords,physvals); } - NekDouble PhysEvaluateDeriv(const Array& coords, + NekDouble PhysEvaluatedz(const Array& coords, + const Array& physvals) + { + return v_PhysEvaluatedz(coords,physvals); + } + + NekDouble PhysEvaluateDeriv(int dir, const Array& coords, const Array& physvals) { - return v_PhysEvaluateDeriv(coords,physvals); + return v_PhysEvaluateDeriv(dir, coords,physvals); } /** \brief This function evaluates the expansion at a single @@ -981,6 +1002,21 @@ namespace Nektar } + NekDouble PhysEvaluatedx( + const Array &coords, + const Array &physvals) + { + return v_PhysEvaluatedx(coords, physvals); + } + + + NekDouble PhysEvaluatedy( + const Array &coords, + const Array &physvals) + { + return v_PhysEvaluatedy(coords, physvals); + } + /** * @brief This function evaluates the derivative of basis function mode * @p mode at a point @p coords of the domain. @@ -993,14 +1029,28 @@ namespace Nektar * * @return The value of the derivative of the basis function @p mode at @p coords. */ - NekDouble PhysEvaluateDerivBasis( + NekDouble PhysEvaluatedxBasis( const Array& coords, int mode) { - return v_PhysEvaluateBasis(coords, mode); + return v_PhysEvaluatedxBasis(coords, mode); } + NekDouble PhysEvaluatedyBasis( + const Array& coords, + int mode) + { + return v_PhysEvaluatedyBasis(coords, mode); + } + + NekDouble PhysEvaluatedzBasis( + const Array& coords, + int mode) + { + return v_PhysEvaluatedzBasis(coords, mode); + } + /** * \brief Convert local cartesian coordinate \a xi into local * collapsed coordinates \a eta @@ -1480,7 +1530,7 @@ namespace Nektar { const int nquad = m_base[DIR]->GetNumPoints(); return BaryEvaluateDeriv( - coord, &(m_base[DIR]->GetBdata())[0] + nquad * mode); + coord, &(m_base[DIR]->GetDbdata())[0] + nquad * mode); } private: // Virtual functions @@ -1609,24 +1659,47 @@ namespace Nektar const Array& inarray, Array &outarray); - STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate (const Array& I, const Array & physvals); - + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateBasis (const Array& coords, int mode); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedxBasis + (const Array& coords, int mode); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedyBasis + (const Array& coords, int mode); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedzBasis + (const Array& coords, int mode); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv - (const Array& coords, const Array& physvals); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate (const Array& coords, const Array& physvals); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedx + (const Array& coords, + const Array& physvals); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedy + (const Array& coords, + const Array& physvals); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedz + (const Array& coords, + const Array& physvals); STD_REGIONS_EXPORT virtual void v_LocCoordToLocCollapsed( const Array& xi, @@ -1635,6 +1708,12 @@ namespace Nektar STD_REGIONS_EXPORT virtual void v_FillMode(const int mode, Array &outarray); + STD_REGIONS_EXPORT virtual void v_FillModedx(const int mode, + Array &outarray); + STD_REGIONS_EXPORT virtual void v_FillModedy(const int mode, + Array &outarray); + STD_REGIONS_EXPORT virtual void v_FillModedz(const int mode, + Array &outarray); STD_REGIONS_EXPORT virtual DNekMatSharedPtr v_GenMatrix( const StdMatrixKey &mkey); diff --git a/library/StdRegions/StdExpansion1D.cpp b/library/StdRegions/StdExpansion1D.cpp index fbcb4d33e..344deb645 100644 --- a/library/StdRegions/StdExpansion1D.cpp +++ b/library/StdRegions/StdExpansion1D.cpp @@ -85,10 +85,11 @@ namespace Nektar } NekDouble StdExpansion1D::v_PhysEvaluateDeriv( + int dir, const Array& coords, const Array& physvals) { - + boost::ignore_unused(dir); return StdExpansion::BaryEvaluate<0>(coords[0], &physvals[0]); } @@ -103,6 +104,16 @@ namespace Nektar return StdExpansion::BaryEvaluate<0>(Lcoord[0], &physvals[0]); } + NekDouble StdExpansion1D::v_PhysEvaluatedx( + const Array& Lcoord, + const Array& physvals) + { + ASSERTL2(Lcoord[0] >= -1 - NekConstants::kNekZeroTol,"Lcoord[0] < -1"); + ASSERTL2(Lcoord[0] <= 1 + NekConstants::kNekZeroTol,"Lcoord[0] > 1"); + + return StdExpansion::BaryEvaluateDeriv<0>(Lcoord[0], &physvals[0]); + } + }//end namespace }//end namespace diff --git a/library/StdRegions/StdExpansion1D.h b/library/StdRegions/StdExpansion1D.h index 20d057406..c0f56b103 100644 --- a/library/StdRegions/StdExpansion1D.h +++ b/library/StdRegions/StdExpansion1D.h @@ -74,7 +74,11 @@ namespace Nektar STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& coords, const Array& physvals) override; - STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv( + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedx( + const Array& coords, + const Array& physvals) override; + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv( int dir, const Array& coords, const Array& physvals) override; diff --git a/library/StdRegions/StdExpansion2D.cpp b/library/StdRegions/StdExpansion2D.cpp index 181cf7b7b..f98fa6640 100644 --- a/library/StdRegions/StdExpansion2D.cpp +++ b/library/StdRegions/StdExpansion2D.cpp @@ -111,14 +111,8 @@ namespace Nektar } } } + - NekDouble StdExpansion2D::v_PhysEvaluateDeriv( - const Array &coords, - const Array &physvals) - { - boost::ignore_unused(coords, physvals); - return 0.0; - } NekDouble StdExpansion2D::v_PhysEvaluate( const Array &coords, @@ -142,15 +136,17 @@ namespace Nektar Array wsp(nq1); for (int i = 0; i < nq1; ++i) { - wsp[i] = StdExpansion::BaryEvaluate<0>( + wsp[i] = StdExpansion::BaryEvaluate<1>( coll[0], &physvals[0] + i * nq0); } - return StdExpansion::BaryEvaluate<1>(coll[1], &wsp[0]); + return StdExpansion::BaryEvaluate<0>(coll[1], &wsp[0]); } + + NekDouble StdExpansion2D::v_PhysEvaluate( const Array &I, const Array &physvals) diff --git a/library/StdRegions/StdExpansion2D.h b/library/StdRegions/StdExpansion2D.h index 074e2a047..f17673936 100644 --- a/library/StdRegions/StdExpansion2D.h +++ b/library/StdRegions/StdExpansion2D.h @@ -140,14 +140,12 @@ namespace StdRegions * \param coords the coordinates of the single point * \return returns the value of the expansion at the single point */ + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& coords, const Array& physvals); - - STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv( - const Array& coords, - const Array& physvals) override; - + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& I, const Array & physvals); diff --git a/library/StdRegions/StdQuadExp.cpp b/library/StdRegions/StdQuadExp.cpp index 12a521d4e..9ab81a081 100644 --- a/library/StdRegions/StdQuadExp.cpp +++ b/library/StdRegions/StdQuadExp.cpp @@ -577,14 +577,52 @@ namespace Nektar eta[1] = xi[1]; } + /** \brief Fill outarray with mode \a mode of partial + * derivative in y of expansion + * + * Note for quadrilateral expansions _base[0] (i.e. p) modes run + * fastest + */ + + void StdQuadExp::v_FillModedy(const int mode, + Array &outarray) + { + int i; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + Array base0 = m_base[0]->GetBdata(); + Array base1 = m_base[1]->GetDbdata(); + int btmp0 = m_base[0]->GetNumModes(); + int mode0 = mode%btmp0; + int mode1 = mode/btmp0; + + ASSERTL2(mode1 == (int)floor((1.0*mode)/btmp0), + "Integer Truncation not Equiv to Floor"); + + ASSERTL2(m_ncoeffs > mode, + "calling argument mode is larger than total expansion order"); + + for(i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get() + mode0*nquad0), + 1, &outarray[0]+i*nquad0,1); + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode1*nquad1),1, + &outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + /** \brief Fill outarray with mode \a mode of expansion * * Note for quadrilateral expansions _base[0] (i.e. p) modes run * fastest */ - + void StdQuadExp::v_FillMode(const int mode, - Array &outarray) + Array &outarray) { int i; int nquad0 = m_base[0]->GetNumPoints(); @@ -594,6 +632,45 @@ namespace Nektar int btmp0 = m_base[0]->GetNumModes(); int mode0 = mode%btmp0; int mode1 = mode/btmp0; + + + ASSERTL2(mode1 == (int)floor((1.0*mode)/btmp0), + "Integer Truncation not Equiv to Floor"); + + ASSERTL2(m_ncoeffs <= mode, + "calling argument mode is larger than total expansion order"); + + for(i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get() + mode0*nquad0), + 1, &outarray[0]+i*nquad0,1); + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode1*nquad1),1, + &outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + + /** \brief Fill outarray with mode \a mode of partial + * derivative wrt y of expansion + * + * Note for quadrilateral expansions _base[0] (i.e. p) modes run + * fastest + */ + + void StdQuadExp::v_FillModedx(const int mode, + Array &outarray) + { + int i; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + Array base0 = m_base[0]->GetDbdata(); + Array base1 = m_base[1]->GetBdata(); + int btmp0 = m_base[0]->GetNumModes(); + int mode0 = mode%btmp0; + int mode1 = mode/btmp0; ASSERTL2(mode1 == (int)floor((1.0*mode)/btmp0), "Integer Truncation not Equiv to Floor"); @@ -614,6 +691,7 @@ namespace Nektar } } + ////////////////////// // Helper functions // ////////////////////// @@ -752,6 +830,67 @@ namespace Nektar } } + NekDouble StdQuadExp::v_PhysEvaluatedy( + const Array &coords, + const Array &physvals) + { + ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + ASSERTL2(dir < 1 && dir > 0, "direction can be 0 or 1"); + + Array coll(2); + LocCoordToLocCollapsed(coords,coll); + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + + Array wsp(nq1); + for (int i = 0; i < nq1; ++i) + { + wsp[i] = StdExpansion::BaryEvaluateDeriv<0>( + coll[0], &physvals[0] + i * nq0); + } + + return StdExpansion::BaryEvaluate<1>(coll[1], &wsp[0]); + } + + NekDouble StdQuadExp::v_PhysEvaluatedx( + const Array &coords, + const Array &physvals) + { + ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + + Array coll(2); + LocCoordToLocCollapsed(coords,coll); + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + + Array wsp(nq1); + for (int i = 0; i < nq1; ++i) + { + wsp[i] = StdExpansion::BaryEvaluateDeriv<1>( + coll[0], &physvals[0] + i * nq0); + } + + return StdExpansion::BaryEvaluate<0>(coll[1], &wsp[0]); + } + + + /** * @brief This function evaluates the basis function mode @p mode at a * point @p coords of the domain. @@ -784,6 +923,47 @@ namespace Nektar StdExpansion::BaryEvaluateBasis<1>(coords[1], mode / nm0); } + NekDouble StdQuadExp::v_PhysEvaluatedxBasis( + const Array& coords, + int mode) + { + ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + + const int nm0 = m_base[0]->GetNumModes(); + const int nm1 = m_base[1]->GetNumModes(); + + return StdExpansion::BaryEvaluateDerivBasis<0>(coords[0], mode % nm1) * + StdExpansion::BaryEvaluateBasis<1>(coords[1], mode / nm0); + } + + + NekDouble StdQuadExp::v_PhysEvaluatedyBasis( + const Array& coords, + int mode) + { + ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + + const int nm0 = m_base[0]->GetNumModes(); + const int nm1 = m_base[1]->GetNumModes(); + + return StdExpansion::BaryEvaluateBasis<0>(coords[0], mode % nm1) * + StdExpansion::BaryEvaluateDerivBasis<1>(coords[1], mode / nm0); + } + ////////////// // Mappings // ////////////// diff --git a/library/StdRegions/StdQuadExp.h b/library/StdRegions/StdQuadExp.h index 842e9fa1c..5ae1efb65 100644 --- a/library/StdRegions/StdQuadExp.h +++ b/library/StdRegions/StdQuadExp.h @@ -157,6 +157,12 @@ namespace Nektar STD_REGIONS_EXPORT virtual void v_FillMode( const int mode, Array &array); + STD_REGIONS_EXPORT virtual void v_FillModedx( + const int mode, + Array &array); + STD_REGIONS_EXPORT virtual void v_FillModedy( + const int mode, + Array &array); //--------------------------- // Helper functions @@ -182,6 +188,23 @@ namespace Nektar STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateBasis( const Array& coords, int mode); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedyBasis( + const Array& coords, + int mode); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedxBasis( + const Array& coords, + int mode); + + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedx( + const Array& coords, + const Array& physvals); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedy( + const Array& coords, + const Array& physvals); + + //-------------------------- // Mappings diff --git a/library/StdRegions/StdTriExp.cpp b/library/StdRegions/StdTriExp.cpp index 2e80c4cd0..2a5ea4066 100644 --- a/library/StdRegions/StdTriExp.cpp +++ b/library/StdRegions/StdTriExp.cpp @@ -136,120 +136,35 @@ namespace Nektar Array& out_d2) { boost::ignore_unused(out_d2); - Array coll(2); - LocCoordToLocCollapsed(inarray,coll); - //coll = inarray; - //const Array& z0 = m_base[0]->GetZ(); - //const Array& z1 = m_base[1]->GetZ(); - - const int nq0 = m_base[0]->GetNumPoints(); - const int nq1 = m_base[1]->GetNumPoints(); - //Array wsp(std::max(nq0, nq1)); - Array wsp2(std::max(nq0, nq1)); - //Array wsp3(std::max(nq0, nq1)); - - // set up geometric factor: 2/(1-z1) - //Vmath::Sadd(nq1, -1.0, z1, 1, wsp, 1); - //Vmath::Sdiv(nq1, -2.0, wsp, 1, wsp, 1); - - if (out_d0.size() > 0) - { - - for (int i = 0; i < nq1; ++i) - { - wsp2[i] = StdExpansion::BaryEvaluateDeriv<0>( - coll[0], &inarray[0] + i * nq0); - } - out_d0 = wsp2; - // for (int i = 0; i < nq1; ++i) - // { - // Blas::Dscal(nq0,wsp[i],&out_d0[0]+i*nq1,1); - // } - // if no d1 required do not need to calculate both deriv - if (out_d1.size() > 0) - { - // set up geometric factor: (1_z0)/(1-z1) - // Vmath::Sadd(nq0, 1.0, z0, 1, wsp, 1); - // Vmath::Smul(nq0, 0.5, wsp, 1, wsp, 1); - - // for (int i = 0; i < nq1; ++i) - // { - - // Vmath::Vvtvp(nq0,&wsp[0],1,&out_d0[0]+i*nq0, - // 1,&out_d1[0]+i*nq0, - // 1,&out_d1[0]+i*nq0,1); - // } - - for (int i = 0; i < nq0; ++i) - { - wsp2[i] = StdExpansion::BaryEvaluateDeriv<1>( - coll[0], &inarray[0] + i * nq1); - } - out_d1 = wsp2; - - } - - } - else if (out_d1.size() > 0) - { - - // for (int i = 0; i < nq1; ++i) - // { - // wsp3[i] = StdExpansion::BaryEvaluateDeriv<0>( - // coll[0], &inarray[0] + i * nq0); - // } - - for (int i = 0; i < nq0; ++i) - { - wsp2[i] = StdExpansion::BaryEvaluateDeriv<1>( - coll[0], &inarray[0] + i * nq1); - } - out_d1 = wsp2; - - // for (int i = 0; i < nq1; ++i) - // { - // Blas::Dscal(nq0,wsp[i],&wsp3[0]+i*nq0,1); - // } - - // Vmath::Sadd(nq0, 1.0, z0, 1, wsp, 1); - // Vmath::Smul(nq0, 0.5, wsp, 1, wsp, 1); - - // for (int i = 0; i < nq1; ++i) - // { - // Vmath::Vvtvp(nq0,&wsp[0],1,&wsp3[0]+i*nq0, - // 1,&out_d1[0]+i*nq0, - // 1,&out_d1[0]+i*nq0,1); - // } - } - - /* int i; + + int i; int nquad0 = m_base[0]->GetNumPoints(); int nquad1 = m_base[1]->GetNumPoints(); Array wsp(std::max(nquad0, nquad1)); - + const Array& z0 = m_base[0]->GetZ(); const Array& z1 = m_base[1]->GetZ(); - + // set up geometric factor: 2/(1-z1) Vmath::Sadd(nquad1, -1.0, z1, 1, wsp, 1); Vmath::Sdiv(nquad1, -2.0, wsp, 1, wsp, 1); - + if (out_d0.size() > 0) { PhysTensorDeriv(inarray, out_d0, out_d1); - + for (i = 0; i < nquad1; ++i) { Blas::Dscal(nquad0,wsp[i],&out_d0[0]+i*nquad0,1); } - + // if no d1 required do not need to calculate both deriv if (out_d1.size() > 0) { // set up geometric factor: (1_z0)/(1-z1) Vmath::Sadd(nquad0, 1.0, z0, 1, wsp, 1); Vmath::Smul(nquad0, 0.5, wsp, 1, wsp, 1); - + for (i = 0; i < nquad1; ++i) { Vmath::Vvtvp(nquad0,&wsp[0],1,&out_d0[0]+i*nquad0, @@ -257,27 +172,28 @@ namespace Nektar 1,&out_d1[0]+i*nquad0,1); } } - } + } else if (out_d1.size() > 0) { Array diff0(nquad0*nquad1); PhysTensorDeriv(inarray, diff0, out_d1); - + for (i = 0; i < nquad1; ++i) { Blas::Dscal(nquad0,wsp[i],&diff0[0]+i*nquad0,1); } - + Vmath::Sadd(nquad0, 1.0, z0, 1, wsp, 1); Vmath::Smul(nquad0, 0.5, wsp, 1, wsp, 1); - + for (i = 0; i < nquad1; ++i) { Vmath::Vvtvp(nquad0,&wsp[0],1,&diff0[0]+i*nquad0, 1,&out_d1[0]+i*nquad0, 1,&out_d1[0]+i*nquad0,1); } - }*/ + } + } void StdTriExp::v_PhysDeriv( @@ -822,6 +738,93 @@ namespace Nektar 1,&outarray[0]+i,nquad0,&outarray[0]+i,nquad0); } } + + NekDouble StdTriExp::v_PhysEvaluatedx( + const Array &coords, + const Array &physvals) + { + Array coll(2); + LocCoordToLocCollapsed(coords,coll); + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + + const Array& z1 = m_base[1]->GetZ(); + Array wsp(nq1); + + Array wsp1(nq1); + for (int i = 0; i < nq1; ++i) + { + wsp1[i] = StdExpansion::BaryEvaluate<0>( + coll[0], &physvals[0] + i * nq1); + } + // set up geometric factor: 2/(1-z1) + Vmath::Sadd(nq1, -1.0, z1, 1, wsp, 1); + Vmath::Sdiv(nq1, -2.0, wsp, 1, wsp, 1); + + for (int i = 0; i < nq0; ++i) + { + Blas::Dscal(nq1,wsp[i],&wsp1[0]+i*nq1,1); + } + return StdExpansion::BaryEvaluateDeriv<1>(coll[1], &wsp1[0]); + + } + + NekDouble StdTriExp::v_PhysEvaluatedy( + const Array &coords, + const Array &physvals) + { + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + const Array& z1 = m_base[1]->GetZ(); + + const Array& z0 = m_base[0]->GetZ(); + + + Array coll(2); + LocCoordToLocCollapsed(coords,coll); + Array wsp(nq0); + Array wsp1(nq1); + Array wsp3(nq1); + + + for (int i = 0; i < nq1; ++i) + { + wsp1[i] = StdExpansion::BaryEvaluate<0>( + coll[0], &physvals[0] + i * nq1); + } + + + // set up geometric factor: 2/(1-z1) + Vmath::Sadd(nq1, -1.0, z1, 1, wsp, 1); + Vmath::Sdiv(nq1, -2.0, wsp, 1, wsp, 1); + + + // set up geometric factor: (1_z0)/(1-z1) + Vmath::Sadd(nq0, 1.0, z0, 1, wsp, 1); + Vmath::Smul(nq0, 0.5, wsp, 1, wsp, 1); + + for (int i = 0; i < nq0; ++i) + { + Blas::Dscal(nq1,wsp[i],&wsp1[0]+i*nq1,1); + } + + + for (int i = 0; i < nq0; ++i) + { + wsp3[i] = StdExpansion::BaryEvaluate<1>( + coll[1], &physvals[0] + i * nq1); + } + + // add wsp1 and wsp 3 + Vmath::Vadd(nq1, wsp1, 1, wsp3, 1, wsp3, 1); + + // interpolate derivative in y direction + return StdExpansion::BaryEvaluateDeriv<1>(coll[1], &wsp3[0]); + + } + NekDouble StdTriExp::v_PhysEvaluateBasis( const Array& coords, diff --git a/library/StdRegions/StdTriExp.h b/library/StdRegions/StdTriExp.h index e01c95db9..70dc826e9 100644 --- a/library/StdRegions/StdTriExp.h +++ b/library/StdRegions/StdTriExp.h @@ -156,10 +156,27 @@ namespace Nektar STD_REGIONS_EXPORT virtual void v_FillMode( const int mode, Array &outarray); + STD_REGIONS_EXPORT NekDouble v_PhysEvaluateBasis( const Array& coords, int mode) final; + STD_REGIONS_EXPORT NekDouble v_PhysEvaluatedyBasis( + const Array& coords, + int mode) final; + + STD_REGIONS_EXPORT NekDouble v_PhysEvaluatedxBasis( + const Array& coords, + int mode) final; + + STD_REGIONS_EXPORT NekDouble v_PhysEvaluatedx( + const Array &coords, + const Array &physvals) final; + + STD_REGIONS_EXPORT NekDouble v_PhysEvaluatedy( + const Array &coords, + const Array &physvals) final; + //--------------------------- // Helper functions -- GitLab From a34061c789b26ae50994ab94861c5023ae86af7f Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 13 Jul 2020 15:37:58 +0100 Subject: [PATCH 054/408] List of missing coords for each interface per rank --- .../AssemblyMap/InterfaceMapDG.cpp | 105 +++++++++++++++--- .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 4 +- library/MultiRegions/DisContField2D.cpp | 2 +- library/SpatialDomains/Interface.cpp | 4 +- library/SpatialDomains/Interface.h | 18 ++- 5 files changed, 104 insertions(+), 29 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index ae0fa7c7c..3876e81d6 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -147,32 +147,65 @@ InterfaceMapDG::InterfaceMapDG( } } + /*std::cout << "MY RANK: " << myRank; + for (auto i : leftEdgeOppRanks) + { + std::cout << "\n\t shares interface (left) " << i.first << " with rank: "; + for (auto j : i.second) + { + std::cout << j << " "; + } + } + for (auto i : rightEdgeOppRanks) + { + std::cout << "\n\t shares interface (right) " << i.first << " with rank: "; + for (auto j : i.second) + { + std::cout << j << " "; + } + } + std::cout << std::endl;*/ + // Create individual interface exchange objects for (auto interface : interfaceCollection) { int interfaceId = interface.first; - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[interfaceId]->GetLeftInterface(), - leftEdgeOppRanks[interfaceId], - checkLocal[interfaceId])); - - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[interfaceId]->GetRightInterface(), - rightEdgeOppRanks[interfaceId], - checkLocal[interfaceId])); + if(!leftEdgeOppRanks[interfaceId].empty()) + { + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[interfaceId]->GetLeftInterface(), + leftEdgeOppRanks[interfaceId], checkLocal[interfaceId])); + } + + if(!rightEdgeOppRanks[interfaceId].empty()) + { + m_exchange.emplace_back( + MemoryManager::AllocateSharedPtr( + interfaceCollection[interfaceId]->GetRightInterface(), + rightEdgeOppRanks[interfaceId], checkLocal[interfaceId])); + } + } + + comm->Block(); + + for (auto i : m_exchange) + { + i->CalcLocalCoords(trace, geomIdToTraceId); } + + comm->Block(); + exit(0); } -void InterfaceExchange::CalcLocalCoordsReturnTrace(ExpListSharedPtr &trace, std::map geomIdToTraceId) +void InterfaceExchange::CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId) { - auto graph = trace->GetGraph(); - Array> geomEdgeIdLocalCoordPair(m_interface->GetTotPoints()); - Array> missingCoords(m_interface->GetTotPoints()); if(m_checkLocal) { + auto graph = trace->GetGraph(); + Array> geomEdgeIdLocalCoordPair(m_interface->GetTotPoints()); + int cnt = 0; auto childEdgeIds = m_interface->GetEdgeIds(); auto parentEdgeIds = m_interface->GetOppInterface()->GetEdgeIds(); @@ -204,7 +237,7 @@ void InterfaceExchange::CalcLocalCoordsReturnTrace(ExpListSharedPtr &trace, std: if (dist < 1e-8) { foundEdgeId = parentId; - //std::cout << "Found : "<< xc << " " << yc << " in trace " << foundTraceId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; + //std::cout << "Found : "<< xc[i] << " " << yc[i] << " in trace " << foundEdgeId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; found = true; break; } @@ -212,15 +245,51 @@ void InterfaceExchange::CalcLocalCoordsReturnTrace(ExpListSharedPtr &trace, std: if(!found) { - missingCoords[cnt] = xs; + m_missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); } - geomEdgeIdLocalCoordPair[cnt] = std::make_pair(foundEdgeId, foundLocCoord); + //geomEdgeIdLocalCoordPair[cnt] = std::make_pair(foundEdgeId, foundLocCoord); + cnt++; + } + } + } + else + { + int cnt = 0; + auto childEdgeIds = m_interface->GetEdgeIds(); + for (auto childId : childEdgeIds) + { + auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq); + childElmt->GetCoords(xc, yc); + + // Check local interface + for (int i = 0; i < nq; ++i) + { + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + m_missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); cnt++; } } } + + // Cout missing coords (debug) + std::cout << "MY RANK: " << trace->GetComm()->GetRank() + << " INTERFACE: " << m_interface->GetId() << " MISSING: \n"; + for (auto i : m_missingCoords) + { + std::cout << i.first << "\t" << std::get<0>(i.second) << " " + << std::get<1>(i.second) << " " << std::get<2>(i.second) + << "\n"; + } + std::cout << std::endl; + + } /*std::vector> CalcCoordsOneWay( diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h index aae81df65..28aa1fa42 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -61,7 +61,7 @@ public: { } - void CalcLocalCoordsReturnTrace(ExpListSharedPtr &trace, std::map geomIdToTraceId); + void CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId); void ReturnTrace(); MULTI_REGIONS_EXPORT void PerformExchange(); @@ -70,7 +70,7 @@ private: std::vector m_ranks; bool m_checkLocal; Array m_localQuadCoords; - + std::map> m_missingCoords; }; typedef std::shared_ptr InterfaceExchangeSharedPtr; diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 51af335fa..34ebc7f26 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1396,7 +1396,7 @@ namespace Nektar DisContField2D::v_PeriodicBwdCopy(Fwd, Bwd); - m_interfaceMap->CalcLocalInterfaceCoords(); + //m_interfaceMap->CalcLocalInterfaceCoords(); /* // Interpolate from each side of the interface to the other. CalcLocalInterfaceCoords(); diff --git a/library/SpatialDomains/Interface.cpp b/library/SpatialDomains/Interface.cpp index 74c501764..3f6f4b261 100644 --- a/library/SpatialDomains/Interface.cpp +++ b/library/SpatialDomains/Interface.cpp @@ -181,11 +181,11 @@ void Interfaces::ReadInterfaces(TiXmlElement *interfaces) NekDouble angularVel = stod(angularVelStr); - interface = RotatingInterfaceShPtr(MemoryManager::AllocateSharedPtr(domain, origin, axis, angularVel)); + interface = RotatingInterfaceShPtr(MemoryManager::AllocateSharedPtr(indx, domain, origin, axis, angularVel)); } else if (interfaceType == "F") { - interface = FixedInterfaceShPtr(MemoryManager::AllocateSharedPtr(domain)); + interface = FixedInterfaceShPtr(MemoryManager::AllocateSharedPtr(indx, domain)); } if (interfaceErr == TIXML_SUCCESS) diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 91f17a73b..8150b1ff2 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -71,8 +71,8 @@ typedef std::shared_ptr InterfaceBaseShPtr; struct InterfaceBase { - InterfaceBase(InterfaceType type, CompositeMap domain) - : m_type(type), m_domain(domain) + InterfaceBase(InterfaceType type, int indx, CompositeMap domain) + : m_type(type), m_id(indx), m_domain(domain) { } @@ -158,9 +158,15 @@ struct InterfaceBase return m_oppInterface; } + inline int &GetId() + { + return m_id; + } + protected: InterfaceBaseShPtr m_oppInterface; InterfaceType m_type; + int m_id; InterfaceSide m_side = eNone; CompositeMap m_domain; std::map m_edge; @@ -172,10 +178,10 @@ protected: struct RotatingInterface : public InterfaceBase { - RotatingInterface(const CompositeMap &domain, const PointGeom &origin, + RotatingInterface(int id, const CompositeMap &domain, const PointGeom &origin, const std::vector &axis, const NekDouble angularVel) - : InterfaceBase(eRotating, domain), m_origin(origin), + : InterfaceBase(eRotating, id, domain), m_origin(origin), m_axis(axis), m_angularVel(angularVel) { } @@ -203,8 +209,8 @@ protected: struct FixedInterface : public InterfaceBase { - FixedInterface(const CompositeMap &domain) - : InterfaceBase(eFixed, domain) + FixedInterface(int id, const CompositeMap &domain) + : InterfaceBase(eFixed, id, domain) { } }; -- GitLab From 4e55192d488c259f3b5283bdc84aad5aabe49799 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 13 Jul 2020 17:23:37 +0100 Subject: [PATCH 055/408] Restructure to be rank to rank objects --- .../AssemblyMap/InterfaceMapDG.cpp | 178 ++++++++---------- .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 23 ++- 2 files changed, 96 insertions(+), 105 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index 3876e81d6..eab8ab73f 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -94,8 +94,7 @@ InterfaceMapDG::InterfaceMapDG( rankLocalInterfaceDisp); // Find what interface Ids match with other ranks, then check if opposite edge - std::map> leftEdgeOppRanks; // Map of interface Id to vector of ranks with the opposite edge - std::map> rightEdgeOppRanks; + std::map> oppRankSharedInterface; // Map of rank to map of interfaces to opposite edge std::map checkLocal; size_t myRank = comm->GetRank(); @@ -129,19 +128,18 @@ InterfaceMapDG::InterfaceMapDG( (myCode == 1 && otherCode == 3) || (myCode == 3 && otherCode == 2)) { - leftEdgeOppRanks[otherId].emplace_back(i); + oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetLeftInterface()); } else if ((myCode == 2 && otherCode == 1) || (myCode == 2 && otherCode == 3) || (myCode == 3 && otherCode == 1)) { - rightEdgeOppRanks[otherId].emplace_back(i); + oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetRightInterface()); } else if (myCode == 3 && otherCode == 3) { - leftEdgeOppRanks[otherId].emplace_back(i); - rightEdgeOppRanks[otherId].emplace_back(i); - + oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetLeftInterface()); + oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetRightInterface()); } } } @@ -167,27 +165,12 @@ InterfaceMapDG::InterfaceMapDG( std::cout << std::endl;*/ // Create individual interface exchange objects - for (auto interface : interfaceCollection) + for (auto rank : oppRankSharedInterface) { - int interfaceId = interface.first; - - if(!leftEdgeOppRanks[interfaceId].empty()) - { - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[interfaceId]->GetLeftInterface(), - leftEdgeOppRanks[interfaceId], checkLocal[interfaceId])); - } - - if(!rightEdgeOppRanks[interfaceId].empty()) - { - m_exchange.emplace_back( - MemoryManager::AllocateSharedPtr( - interfaceCollection[interfaceId]->GetRightInterface(), - rightEdgeOppRanks[interfaceId], checkLocal[interfaceId])); - } + m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(rank, checkLocal)); } + comm->Block(); for (auto i : m_exchange) @@ -201,95 +184,100 @@ InterfaceMapDG::InterfaceMapDG( void InterfaceExchange::CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId) { - if(m_checkLocal) + for (auto interface : m_interfaces) { - auto graph = trace->GetGraph(); - Array> geomEdgeIdLocalCoordPair(m_interface->GetTotPoints()); - - int cnt = 0; - auto childEdgeIds = m_interface->GetEdgeIds(); - auto parentEdgeIds = m_interface->GetOppInterface()->GetEdgeIds(); - for (auto childId : childEdgeIds) + if (m_checkLocal[interface->GetId()]) { - auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); - size_t nq = childElmt->GetTotPoints(); - Array xc(nq), yc(nq); - childElmt->GetCoords(xc, yc); - - // Check local interface - for (int i = 0; i < nq; ++i) + auto graph = trace->GetGraph(); + Array> geomEdgeIdLocalCoordPair( + interface->GetTotPoints()); + + int cnt = 0; + auto childEdgeIds = interface->GetEdgeIds(); + auto parentEdgeIds = interface->GetOppInterface()->GetEdgeIds(); + for (auto childId : childEdgeIds) { - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; + auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq); + childElmt->GetCoords(xc, yc); - bool found = false; - int foundEdgeId = -1; - NekDouble foundLocCoord = -1; - - for (auto parentId : parentEdgeIds) + // Check local interface + for (int i = 0; i < nq; ++i) { - SpatialDomains::SegGeomSharedPtr searchSeg = - std::static_pointer_cast(graph->GetSegGeom(parentId)); - NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; + + bool found = false; + int foundEdgeId = -1; + NekDouble foundLocCoord = -1; - if (dist < 1e-8) + for (auto parentId : parentEdgeIds) { - foundEdgeId = parentId; - //std::cout << "Found : "<< xc[i] << " " << yc[i] << " in trace " << foundEdgeId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; - found = true; - break; + SpatialDomains::SegGeomSharedPtr searchSeg = + std::static_pointer_cast( + graph->GetSegGeom(parentId)); + NekDouble dist = + searchSeg->FindDistance(xs, foundLocCoord); + + if (dist < 1e-8) + { + foundEdgeId = parentId; + // std::cout << "Found : "<< xc[i] << " " << yc[i] << " in trace " << foundEdgeId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; + found = true; + break; + } } - } - if(!found) - { - m_missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); - } + if (!found) + { + m_missingCoords[cnt] = + std::make_tuple(xs[0], xs[1], xs[2]); + } - //geomEdgeIdLocalCoordPair[cnt] = std::make_pair(foundEdgeId, foundLocCoord); - cnt++; + m_foundEdgeLocalCoordPair[cnt] = + std::make_pair(foundEdgeId, foundLocCoord); + cnt++; + } } } - } - else - { - int cnt = 0; - auto childEdgeIds = m_interface->GetEdgeIds(); - for (auto childId : childEdgeIds) + else { - auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); - size_t nq = childElmt->GetTotPoints(); - Array xc(nq), yc(nq); - childElmt->GetCoords(xc, yc); - - // Check local interface - for (int i = 0; i < nq; ++i) + int cnt = 0; + auto childEdgeIds = interface->GetEdgeIds(); + for (auto childId : childEdgeIds) { - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; + auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq); + childElmt->GetCoords(xc, yc); + + // Check local interface + for (int i = 0; i < nq; ++i) + { + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = 0; - m_missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); - cnt++; + m_missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); + cnt++; + } } } - } - // Cout missing coords (debug) - std::cout << "MY RANK: " << trace->GetComm()->GetRank() - << " INTERFACE: " << m_interface->GetId() << " MISSING: \n"; - for (auto i : m_missingCoords) - { - std::cout << i.first << "\t" << std::get<0>(i.second) << " " - << std::get<1>(i.second) << " " << std::get<2>(i.second) - << "\n"; + // Cout missing coords (debug) + std::cout << "MY RANK: " << trace->GetComm()->GetRank() << " TO RANK " << m_rank << " INTERFACE: " << interface->GetId() << " MISSING: \n"; + for (auto i : m_missingCoords) + { + std::cout << i.first << "\t" << std::get<0>(i.second) << " " + << std::get<1>(i.second) << " " << std::get<2>(i.second) + << "\n"; + } + std::cout << std::endl; } - std::cout << std::endl; - - } /*std::vector> CalcCoordsOneWay( diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h index 28aa1fa42..09615a508 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -52,24 +52,27 @@ public: /// Default constructor MULTI_REGIONS_EXPORT InterfaceExchange( - const SpatialDomains::InterfaceBaseShPtr &interface, - const std::vector &ranks, - const bool &checkLocal) - : m_interface(interface), - m_ranks(ranks), + std::pair> rankPair, + std::map checkLocal) + : m_rank(rankPair.first), + m_interfaces(rankPair.second), m_checkLocal(checkLocal) { } void CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId); - void ReturnTrace(); + + inline std::map> GetMissing() + { + return m_missingCoords; + } MULTI_REGIONS_EXPORT void PerformExchange(); private: - SpatialDomains::InterfaceBaseShPtr m_interface; - std::vector m_ranks; - bool m_checkLocal; - Array m_localQuadCoords; + int m_rank; + const std::vector m_interfaces; + std::map m_checkLocal; + std::map> m_foundEdgeLocalCoordPair; std::map> m_missingCoords; }; -- GitLab From ad7eb4d013f112c6d14b974792bcf5aad41ed9be Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Tue, 14 Jul 2020 18:57:52 +0100 Subject: [PATCH 056/408] Nearly sharing missing coords --- .../AssemblyMap/InterfaceMapDG.cpp | 131 ++++++++++++++---- .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 32 +++-- library/SpatialDomains/Interface.h | 30 ++++ 3 files changed, 148 insertions(+), 45 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index eab8ab73f..66b6bf038 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -43,11 +43,15 @@ InterfaceMapDG::InterfaceMapDG( const SpatialDomains::InterfacesSharedPtr &interfaces, const ExpListSharedPtr &trace, const std::map geomIdToTraceId) - : m_trace(trace), + : m_interfaces(interfaces), + m_trace(trace), m_geomIdToTraceId(geomIdToTraceId) { + auto comm = m_trace->GetComm(); - auto interfaceCollection = interfaces->GetInterfaces(); + auto interfaceCollection = m_interfaces->GetInterfaces(); + + std::cout << "RANK: " << comm->GetRank() << " BEFORE InterfaceMapDG" << std::endl; // myIndxLR contains the info about what interface edges are present on // current rank with each interface no, i, consisting of: @@ -63,10 +67,12 @@ InterfaceMapDG::InterfaceMapDG( if(!interface.second->GetLeftInterface()->IsEmpty()) { myIndxLR[2 * cnt + 1] += 1; + m_localInterfaces.emplace_back(interface.second->GetLeftInterface()); } if (!interface.second->GetRightInterface()->IsEmpty()) { myIndxLR[2 * cnt + 1] += 2; + m_localInterfaces.emplace_back(interface.second->GetRightInterface()); } myIndxLRMap[interface.first] = myIndxLR[2 * cnt + 1]; @@ -90,12 +96,13 @@ InterfaceMapDG::InterfaceMapDG( std::accumulate(rankNumInterfaces.begin(), rankNumInterfaces.end(), 0), 0); // Send all interface IDs to all partitions + std::cout << "RANK: " << comm->GetRank() << " BEFORE Allgatherv for interface IDs" << std::endl; comm->AllGatherv(myIndxLR, rankLocalInterfaceIds, rankNumInterfaces, rankLocalInterfaceDisp); + std::cout << "RANK: " << comm->GetRank() << " AFTER Allgatherv for interface IDs" << std::endl; // Find what interface Ids match with other ranks, then check if opposite edge std::map> oppRankSharedInterface; // Map of rank to map of interfaces to opposite edge - std::map checkLocal; size_t myRank = comm->GetRank(); for (size_t i = 0; i < nRanks; ++i) @@ -115,7 +122,8 @@ InterfaceMapDG::InterfaceMapDG( //If contains opposite edge locally then set true if (otherCode == 3) { - checkLocal[otherId] = true; + interfaceCollection[otherId]->GetLeftInterface()->SetCheckLocal(true); + interfaceCollection[otherId]->GetRightInterface()->SetCheckLocal(true); } continue; @@ -167,30 +175,97 @@ InterfaceMapDG::InterfaceMapDG( // Create individual interface exchange objects for (auto rank : oppRankSharedInterface) { - m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(rank, checkLocal)); + m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(comm, rank)); } + // Find local seg-coord pairs and missing coords to communicate to other ranks + std::cout << "RANK: " << comm->GetRank() << " BEFORE CalcLocalCoords" << std::endl; + CalcLocalCoords(trace, geomIdToTraceId); + std::cout << "RANK: " << comm->GetRank() << " AFTER CalcLocalCoords" << std::endl; - comm->Block(); + // Combine multiple interfaces on each rank for communication + auto request = comm->CreateRequest(2 * m_exchange.size()); + std::cout << "RANK: " << comm->GetRank() << " BEFORE RankFillSizes()" << std::endl; + for (int i = 0; i < m_exchange.size(); ++i) + { + m_exchange[i]->RankFillSizes(request, i); + } + std::cout << "RANK: " << comm->GetRank() << " AT WAITALL AFTER RankFillSizes()" << std::endl; - for (auto i : m_exchange) + comm->WaitAll(request); + + std::cout << "RANK: " << comm->GetRank() << " BEFORE RankCoordCalc()" << std::endl; + for (int i = 0; i < m_exchange.size(); ++i) { - i->CalcLocalCoords(trace, geomIdToTraceId); + m_exchange[i]->RankCoordCalc(request, i); } + std::cout << "RANK: " << comm->GetRank() << " AT WAITALL AFTER RankCoordCalc()" << std::endl; + comm->WaitAll(request); comm->Block(); exit(0); } -void InterfaceExchange::CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId) +void InterfaceExchange::RankFillSizes(LibUtilities::CommRequestSharedPtr request, int requestNum) { - for (auto interface : m_interfaces) + // Get size of all interfaces missing to communicate + m_sendSize = Array(m_interfaces.size()); + m_recvSize = Array(m_interfaces.size()); + for (int i = 0; i < m_interfaces.size(); ++i) { - if (m_checkLocal[interface->GetId()]) + m_sendSize[i] = m_interfaces[i]->GetMissing().size(); + } + + m_comm->Isend(m_rank, m_sendSize, m_interfaces.size(), request, 2 * requestNum); + m_comm->Irecv(m_rank, m_recvSize, m_interfaces.size(), request, 2 * requestNum + 1); +} + +void InterfaceExchange::RankCoordCalc(LibUtilities::CommRequestSharedPtr request, int requestNum) +{ + m_totSendSize = std::accumulate(m_sendSize.begin(), m_sendSize.end(), 0); + m_totRecvSize = std::accumulate(m_recvSize.begin(), m_recvSize.end(), 0); + m_send = Array(m_totSendSize); + m_recv = Array(m_totRecvSize); + + int cnt = 0; + for (int i = 0; i < m_interfaces.size(); ++i) + { + auto missing = m_interfaces[i]->GetMissing(); + for (auto coord : missing) + { + m_send[3 * cnt] = std::get<0>(coord.second); + m_send[3 * cnt + 1] = std::get<1>(coord.second); + m_send[3 * cnt + 2] = std::get<2>(coord.second); + } + } + + // Debug output + boost::ignore_unused(request, requestNum); + std::ostringstream output; + output << "MYRANK: " << m_comm->GetRank() << " TO RANK: " << m_rank << "\n"; + for (int i = 0; i < m_interfaces.size(); ++i) + { + output << "\tINTERFACE: " << m_interfaces[i]->GetId() << " SEND SIZE: " << m_sendSize[i] << " RECV SIZE: " << m_recvSize[i] << "\n"; + } + output << "\tTOTAL: " << " SEND SIZE: " << m_totSendSize << " RECV SIZE: " << m_totRecvSize << "\n"; + std::cout << output.str() << std::endl; + + m_comm->Isend(m_rank, m_send, m_totSendSize, request, 2 * requestNum); + m_comm->Irecv(m_rank, m_recv, m_totRecvSize, request, 2 * requestNum + 1); +} + +// @TODO: Something funky in here. Sometimes crashes e.g. when n = 3, or v. slow at n = 4 ,for the everything case. +void InterfaceMapDG::CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId) +{ + for (auto interface : m_localInterfaces) + { + std::map> missingCoords; + std::map> foundEdgeLocalCoordPair; + + if (interface->GetCheckLocal()) { auto graph = trace->GetGraph(); - Array> geomEdgeIdLocalCoordPair( - interface->GetTotPoints()); + Array> geomEdgeIdLocalCoordPair(interface->GetTotPoints()); int cnt = 0; auto childEdgeIds = interface->GetEdgeIds(); @@ -233,12 +308,10 @@ void InterfaceExchange::CalcLocalCoords(const ExpListSharedPtr &trace, std::map< if (!found) { - m_missingCoords[cnt] = - std::make_tuple(xs[0], xs[1], xs[2]); + missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); } - m_foundEdgeLocalCoordPair[cnt] = - std::make_pair(foundEdgeId, foundLocCoord); + foundEdgeLocalCoordPair[cnt] = std::make_pair(foundEdgeId, foundLocCoord); cnt++; } } @@ -254,29 +327,27 @@ void InterfaceExchange::CalcLocalCoords(const ExpListSharedPtr &trace, std::map< Array xc(nq), yc(nq); childElmt->GetCoords(xc, yc); - // Check local interface for (int i = 0; i < nq; ++i) { - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; - - m_missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); + missingCoords[cnt] = std::make_tuple(xc[i], yc[i], 0); cnt++; } } } + interface->SetMissing(missingCoords); + // Cout missing coords (debug) - std::cout << "MY RANK: " << trace->GetComm()->GetRank() << " TO RANK " << m_rank << " INTERFACE: " << interface->GetId() << " MISSING: \n"; - for (auto i : m_missingCoords) + /*std::ostringstream output; + output << "MY RANK: " << trace->GetComm()->GetRank() << " INTERFACE: " << interface->GetId() << " " << SpatialDomains::InterfaceSideStr[interface->GetSide()] << " MISSING: \n"; + for (auto i : missingCoords) { - std::cout << i.first << "\t" << std::get<0>(i.second) << " " - << std::get<1>(i.second) << " " << std::get<2>(i.second) - << "\n"; + output << "\t" << i.first << "\t" << std::get<0>(i.second) << " " + << std::get<1>(i.second) << " " << std::get<2>(i.second) + << "\n"; } - std::cout << std::endl; + output << std::endl; + std::cout << output.str();*/ } } diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h index 09615a508..1f909c998 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -52,28 +52,27 @@ public: /// Default constructor MULTI_REGIONS_EXPORT InterfaceExchange( - std::pair> rankPair, - std::map checkLocal) - : m_rank(rankPair.first), - m_interfaces(rankPair.second), - m_checkLocal(checkLocal) + const LibUtilities::CommSharedPtr &comm, + std::pair> rankPair) + : m_comm(comm), + m_rank(rankPair.first), + m_interfaces(rankPair.second) { } - void CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId); - - inline std::map> GetMissing() - { - return m_missingCoords; - } - - MULTI_REGIONS_EXPORT void PerformExchange(); + MULTI_REGIONS_EXPORT void RankFillSizes(LibUtilities::CommRequestSharedPtr request, int requestNum); + MULTI_REGIONS_EXPORT void RankCoordCalc(LibUtilities::CommRequestSharedPtr request, int requestNum); private: + const LibUtilities::CommSharedPtr m_comm; int m_rank; const std::vector m_interfaces; + Array m_sendSize; + Array m_recvSize; + int m_totSendSize = 0; + int m_totRecvSize = 0; + Array m_send; + Array m_recv; std::map m_checkLocal; - std::map> m_foundEdgeLocalCoordPair; - std::map> m_missingCoords; }; typedef std::shared_ptr InterfaceExchangeSharedPtr; @@ -90,8 +89,11 @@ public: const ExpListSharedPtr &trace, const std::map geomIdToTraceId); + void CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId); private: + SpatialDomains::InterfacesSharedPtr m_interfaces; + std::vector m_localInterfaces; const ExpListSharedPtr m_trace; std::vector m_exchange; std::map m_geomIdToTraceId; diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index 8150b1ff2..ba737296f 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -63,6 +63,13 @@ enum InterfaceSide eRight }; +const std::string InterfaceSideStr[] = +{ + "NONE", + "LEFT", + "RIGHT" +}; + struct Composite; typedef std::map> CompositeMap; @@ -163,6 +170,26 @@ struct InterfaceBase return m_id; } + inline bool GetCheckLocal() + { + return m_checkLocal; + } + + inline void SetCheckLocal(bool flag) + { + m_checkLocal = flag; + } + + inline std::map> GetMissing() + { + return m_missingCoords; + } + + inline void SetMissing(std::map> missingCoords) + { + m_missingCoords = missingCoords; + } + protected: InterfaceBaseShPtr m_oppInterface; InterfaceType m_type; @@ -174,6 +201,8 @@ protected: CompositeMap m_interfaceEdge; int m_totPoints; std::vector m_oppRanks; + bool m_checkLocal = false; + std::map> m_missingCoords; }; struct RotatingInterface : public InterfaceBase @@ -232,6 +261,7 @@ struct InterfacePair InterfaceBaseShPtr m_leftInterface; InterfaceBaseShPtr m_rightInterface; bool m_calcFlag = true; + bool m_checkLocal = false; public: inline const InterfaceBaseShPtr &GetLeftInterface() const -- GitLab From 8e10d5f2b9b4e57fef66e6191c8e1ead63d330f2 Mon Sep 17 00:00:00 2001 From: vidhi Date: Wed, 15 Jul 2020 13:39:56 -0600 Subject: [PATCH 057/408] intermediate cehckin before switching gears --- library/Demos/StdRegions/StdInterp.cpp | 2 +- library/Demos/StdRegions/StdInterpDeriv.cpp | 8 +- .../Demos/StdRegions/StdInterpDerivBasis.cpp | 127 ++++++++++++++ library/StdRegions/StdExpansion2D.cpp | 5 +- library/StdRegions/StdTriExp.cpp | 155 ++++++++++++++++++ library/StdRegions/StdTriExp.h | 6 + 6 files changed, 295 insertions(+), 8 deletions(-) create mode 100644 library/Demos/StdRegions/StdInterpDerivBasis.cpp diff --git a/library/Demos/StdRegions/StdInterp.cpp b/library/Demos/StdRegions/StdInterp.cpp index f3ff5e74d..b49263071 100644 --- a/library/Demos/StdRegions/StdInterp.cpp +++ b/library/Demos/StdRegions/StdInterp.cpp @@ -68,6 +68,7 @@ int main(int argc, char *argv[]) // perform a PhysEvaluate at a different set of nodal points // (i.e. non-collocated interpolation). vector &ptypes = demo.GetPointsType(); + for (int i = 0; i < dimension; ++i) { ptypes[i] = "PolyEvenlySpaced"; @@ -91,7 +92,6 @@ int main(int argc, char *argv[]) physOut[i] = E->PhysEvaluate(tmpIn, physIn); } - sol = EvalPoly(coordsF); cout << "L infinity error : " << scientific << E->Linf(physOut, sol) << endl; diff --git a/library/Demos/StdRegions/StdInterpDeriv.cpp b/library/Demos/StdRegions/StdInterpDeriv.cpp index acb7be65a..1cdcd402f 100644 --- a/library/Demos/StdRegions/StdInterpDeriv.cpp +++ b/library/Demos/StdRegions/StdInterpDeriv.cpp @@ -149,10 +149,10 @@ int main(int argc, char *argv[]) sol1 = EvalPolyDerivy(coordsF); if(dimension>0) sol0 = EvalPolyDerivx(coordsF); - // for(int i = 0; iLinf(physOut0, sol0) + E->Linf(physOut1, sol1)+ E->Linf(physOut2, sol2) << endl; cout << "L 2 error : " << scientific << E->L2 (physOut0, sol0) + E->L2 (physOut1, sol1) + E->L2 (physOut2, sol2) << endl; diff --git a/library/Demos/StdRegions/StdInterpDerivBasis.cpp b/library/Demos/StdRegions/StdInterpDerivBasis.cpp new file mode 100644 index 000000000..81ce72ce5 --- /dev/null +++ b/library/Demos/StdRegions/StdInterpDerivBasis.cpp @@ -0,0 +1,127 @@ +/////////////////////////////////////////////////////////////////////////////// +// +// File: StdInterpBasis.cpp +// +// For more information, please see: http://www.nektar.info +// +// The MIT License +// +// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA), +// Department of Aeronautics, Imperial College London (UK), and Scientific +// Computing and Imaging Institute, University of Utah (USA). +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. +// +// Description: Demo for testing functionality of PhysEvaluateBasis +// +/////////////////////////////////////////////////////////////////////////////// + +#include +#include + +#include "StdDemoSupport.hpp" + +int main(int argc, char *argv[]) +{ + DemoSupport demo; + demo.ParseArguments(argc, argv); + StdExpansion *E = demo.CreateStdExpansion(); + + if (E == nullptr) + { + return 1; + } + + int nCoeffs = E->GetNcoeffs(), nPts = E->GetTotPoints(); + int nTot = nCoeffs * nPts, dimension = E->GetShapeDimension(); + + Array> coords = demo.GetCoords(E); + Array sol(nTot), phys(nTot), tmpIn(dimension); + Array sol1(nTot), phys1(nTot), tmpIn1(dimension); + Array sol2(nTot), phys2(nTot), tmpIn2(dimension); + + // For each mode, we follow two approaches: + // + // 1) Evaluate the basis function at each quadrature point using the + // StdExpansion::PhysEvaluateBasis function. + // 2) Evaluate the basis function at all quadrature points using FillMode. + // + // These are then compared to ensure they give the same result. + for (int k = 0; k < nCoeffs; ++k) + { + // Evaluate each mode at the quadrature points. + for (int i = 0; i < nPts; ++i) + { + for (int d = 0; d < dimension; ++d) + { + tmpIn[d] = coords[d][i]; + } + + if(dimension>2) + { + phys2[k * nPts + i] = E->PhysEvaluatedzBasis(tmpIn, k); + } + if(dimension>1) + { + phys1[k * nPts + i] = E->PhysEvaluatedyBasis(tmpIn, k); + } + if(dimension>0) + { + phys[k * nPts + i] = E->PhysEvaluatedxBasis(tmpIn, k); + } + } + + // Fill the 'solution' field with each of the partial der of modes wrt x using FillModedx. + if(dimension>2) + { + Array tmp = sol2 + k * nPts; + E->FillModedz(k, tmp); + } + if(dimension>1) + { + Array tmp = sol1 + k * nPts; + E->FillModedy(k, tmp); + } + // Fill the 'solution' field with each of the partial der of modes wrt y using FillModedx. + if(dimension>0) + { + Array tmp = sol + k * nPts; + E->FillModedx(k, tmp); + + } + } + + cout<<"\n true sol:"; + for (int i = 0; iLinf(phys, sol) + E->Linf(phys1, sol1)+ E->Linf(phys2, sol2) << endl; + //cout << "L 2 error : " << scientific << E->L2 (phys, sol) + E->L2 (phys1, sol1) + E->L2 (phys2, sol2) << endl; + cout << "L infinity error : " << scientific << E->Linf(phys1, sol1)<< endl; + cout << "L 2 error : " << scientific << E->L2 (phys1, sol1) << endl; + + + return 0; +} diff --git a/library/StdRegions/StdExpansion2D.cpp b/library/StdRegions/StdExpansion2D.cpp index f98fa6640..998119f2b 100644 --- a/library/StdRegions/StdExpansion2D.cpp +++ b/library/StdRegions/StdExpansion2D.cpp @@ -129,18 +129,17 @@ namespace Nektar Array coll(2); LocCoordToLocCollapsed(coords,coll); - const int nq0 = m_base[0]->GetNumPoints(); const int nq1 = m_base[1]->GetNumPoints(); Array wsp(nq1); for (int i = 0; i < nq1; ++i) { - wsp[i] = StdExpansion::BaryEvaluate<1>( + wsp[i] = StdExpansion::BaryEvaluate<0>( coll[0], &physvals[0] + i * nq0); } - return StdExpansion::BaryEvaluate<0>(coll[1], &wsp[0]); + return StdExpansion::BaryEvaluate<1>(coll[1], &wsp[0]); } diff --git a/library/StdRegions/StdTriExp.cpp b/library/StdRegions/StdTriExp.cpp index 2a5ea4066..c9eadd5f3 100644 --- a/library/StdRegions/StdTriExp.cpp +++ b/library/StdRegions/StdTriExp.cpp @@ -738,7 +738,162 @@ namespace Nektar 1,&outarray[0]+i,nquad0,&outarray[0]+i,nquad0); } } + + + void StdTriExp::v_FillModedy( + const int mode, Array &outarray) + { + int i,m; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + int order0 = m_base[0]->GetNumModes(); + int order1 = m_base[1]->GetNumModes()-1; + int mode0 = 0; + Array base0 = m_base[0]->GetBdata(); + Array base1 = m_base[1]->GetDbdata(); + + ASSERTL2(mode <= m_ncoeffs, + "calling argument mode is larger than " + "total expansion order"); + + m = order1; + for (i = 0; i < order0; ++i, m+=order1-i) + { + if (m > mode) + { + mode0 = i; + break; + } + } + + // deal with top vertex mode in modified basis + if (mode == 1 && + m_base[0]->GetBasisType() == LibUtilities::eModified_A) + { + Vmath::Fill(nquad0*nquad1 , 1.0, outarray, 1); + } + else + { + for (i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get()+mode0*nquad0), + 1,&outarray[0]+i*nquad0,1); + } + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode*nquad1), + 1,&outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + + + void StdTriExp::v_FillModedx( + const int mode, Array &outarray) + { + int i,m; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + int order0 = m_base[0]->GetNumModes(); + int order1 = m_base[1]->GetNumModes(); + int mode0 = 0; + Array base0 = m_base[0]->GetDbdata(); + Array base1 = m_base[1]->GetBdata(); + + ASSERTL2(mode <= m_ncoeffs, + "calling argument mode is larger than " + "total expansion order"); + + m = order1; + for (i = 0; i < order0; ++i, m+=order1-i) + { + if (m > mode) + { + mode0 = i; + break; + } + } + + // deal with top vertex mode in modified basis + if (mode == 1 && + m_base[0]->GetBasisType() == LibUtilities::eModified_A) + { + Vmath::Fill(nquad0*nquad1 , 1.0, outarray, 1); + } + else + { + for (i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get()+mode0*nquad0), + 1,&outarray[0]+i*nquad0,1); + } + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode*nquad1), + 1,&outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + NekDouble StdTriExp::v_PhysEvaluatedxBasis( + const Array& coords, + int mode) + { + Array coll(2); + LocCoordToLocCollapsed(coords, coll); + + // From mode we need to determine mode0 and mode1 in the (p,q) + // direction. mode1 can be directly inferred from mode. + const int nm1 = m_base[1]->GetNumModes(); + const double c = 1 + 2*nm1; + const int mode0 = floor(0.5*(c - sqrt(c*c - 8*mode))); + if (mode == 1 && + m_base[0]->GetBasisType() == LibUtilities::eModified_A) + { + // Account for collapsed vertex. + return StdExpansion::BaryEvaluateDerivBasis<0>(coll[0], 1); + } + else + { + return + StdExpansion::BaryEvaluateBasis<1>(coll[0], mode0) * + StdExpansion::BaryEvaluateDerivBasis<0>(coll[1], mode); + } + + } + + + NekDouble StdTriExp::v_PhysEvaluatedyBasis( + const Array& coords, + int mode) + { + Array coll(2); + LocCoordToLocCollapsed(coords, coll); + + // From mode we need to determine mode0 and mode1 in the (p,q) + // direction. mode1 can be directly inferred from mode. + const int nm1 = m_base[1]->GetNumModes(); + const double c = 1 + 2*nm1; + const int mode0 = floor(0.5*(c - sqrt(c*c - 8*mode))); + + if (mode == 1 && + m_base[0]->GetBasisType() == LibUtilities::eModified_A) + { + // Account for collapsed vertex. + return StdExpansion::BaryEvaluateBasis<1>(coll[1], 1); + } + else + { + return + StdExpansion::BaryEvaluateDerivBasis<1>(coll[1], mode0) * + StdExpansion::BaryEvaluateBasis<0>(coll[0], mode); + } + + } + + NekDouble StdTriExp::v_PhysEvaluatedx( const Array &coords, const Array &physvals) diff --git a/library/StdRegions/StdTriExp.h b/library/StdRegions/StdTriExp.h index 70dc826e9..976eb830b 100644 --- a/library/StdRegions/StdTriExp.h +++ b/library/StdRegions/StdTriExp.h @@ -156,6 +156,12 @@ namespace Nektar STD_REGIONS_EXPORT virtual void v_FillMode( const int mode, Array &outarray); + STD_REGIONS_EXPORT virtual void v_FillModedx( + const int mode, + Array &outarray) final; + STD_REGIONS_EXPORT virtual void v_FillModedy( + const int mode, + Array &outarray) final; STD_REGIONS_EXPORT NekDouble v_PhysEvaluateBasis( const Array& coords, -- GitLab From f39b742fead727df64a073d9bb8799b81f740682 Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Thu, 16 Jul 2020 09:50:32 +0100 Subject: [PATCH 058/408] Fix bug, before adding object for 'set/get' data --- .../AssemblyMap/InterfaceMapDG.cpp | 25 ++++++++++++++++--- library/MultiRegions/DisContField2D.cpp | 22 ---------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index 66b6bf038..7cebc19ad 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -173,11 +173,31 @@ InterfaceMapDG::InterfaceMapDG( std::cout << std::endl;*/ // Create individual interface exchange objects - for (auto rank : oppRankSharedInterface) + for (auto &rank : oppRankSharedInterface) { m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(comm, rank)); } + // Calculate total quadrature points on each interface edge + for (const auto &interface : m_interfaces->GetInterfaces()) + { + int tmp = 0; + auto leftInterface = interface.second->GetLeftInterface(); + for (auto id : leftInterface->GetEdgeIds()) + { + tmp += m_trace->GetExp(geomIdToTraceId.at(id))->GetTotPoints(); + } + leftInterface->SetTotPoints(tmp); + + tmp = 0; + auto rightInterface = interface.second->GetRightInterface(); + for (auto id : leftInterface->GetEdgeIds()) + { + tmp += m_trace->GetExp(geomIdToTraceId.at(id))->GetTotPoints(); + } + rightInterface->SetTotPoints(tmp); + } + // Find local seg-coord pairs and missing coords to communicate to other ranks std::cout << "RANK: " << comm->GetRank() << " BEFORE CalcLocalCoords" << std::endl; CalcLocalCoords(trace, geomIdToTraceId); @@ -254,10 +274,9 @@ void InterfaceExchange::RankCoordCalc(LibUtilities::CommRequestSharedPtr request m_comm->Irecv(m_rank, m_recv, m_totRecvSize, request, 2 * requestNum + 1); } -// @TODO: Something funky in here. Sometimes crashes e.g. when n = 3, or v. slow at n = 4 ,for the everything case. void InterfaceMapDG::CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId) { - for (auto interface : m_localInterfaces) + for (auto &interface : m_localInterfaces) { std::map> missingCoords; std::map> foundEdgeLocalCoordPair; diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 34ebc7f26..7431cf19d 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -454,28 +454,6 @@ namespace Nektar m_interfaceMap = MemoryManager:: AllocateSharedPtr(m_interfaces, m_trace, geomIdToTraceId); - // Calculate total quadrature points on each interface edge - for (const auto &interface : m_interfaces->GetInterfaces()) - { - int tmp = 0; - auto leftInterface = interface.second->GetLeftInterface(); - for (auto id : leftInterface->GetEdgeIds()) - { - tmp += m_trace->GetExp(geomIdToTraceId[id])->GetTotPoints(); - } - leftInterface->SetTotPoints(tmp); - - tmp = 0; - auto rightInterface = interface.second->GetRightInterface(); - for (auto id : leftInterface->GetEdgeIds()) - { - tmp += m_trace->GetExp(geomIdToTraceId[id])->GetTotPoints(); - } - rightInterface->SetTotPoints(tmp); - } - - - int cnt, n, e; // Identify boundary edges for (cnt = 0, n = 0; n < m_bndCondExpansions.size(); ++n) -- GitLab From a769c49fe5bdc0aa42bde11eabaad7b56d0d864f Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Sat, 18 Jul 2020 15:31:53 +0100 Subject: [PATCH 059/408] Serial working --- .../AssemblyMap/InterfaceMapDG.cpp | 414 +++++++++++------- .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 68 ++- library/MultiRegions/DisContField2D.cpp | 53 +-- library/SpatialDomains/Interface.h | 10 - 4 files changed, 309 insertions(+), 236 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index 7cebc19ad..de28126ce 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -47,18 +47,16 @@ InterfaceMapDG::InterfaceMapDG( m_trace(trace), m_geomIdToTraceId(geomIdToTraceId) { - auto comm = m_trace->GetComm(); auto interfaceCollection = m_interfaces->GetInterfaces(); - std::cout << "RANK: " << comm->GetRank() << " BEFORE InterfaceMapDG" << std::endl; - // myIndxLR contains the info about what interface edges are present on // current rank with each interface no, i, consisting of: // [i] = indx // [i + 1] = 0 (non), = 1 (left only), = 2 (right only), = 3 (both) Array myIndxLR(interfaceCollection.size() * 2, 0); std::map myIndxLRMap; + std::map> localInterfaces; size_t cnt = 0; for (const auto &interface : interfaceCollection) { @@ -67,12 +65,14 @@ InterfaceMapDG::InterfaceMapDG( if(!interface.second->GetLeftInterface()->IsEmpty()) { myIndxLR[2 * cnt + 1] += 1; - m_localInterfaces.emplace_back(interface.second->GetLeftInterface()); + localInterfaces[interface.first][SpatialDomains::eLeft] = MemoryManager::AllocateSharedPtr(trace, interface.second->GetLeftInterface(), geomIdToTraceId); + m_localInterfaces.emplace_back(localInterfaces[interface.first][SpatialDomains::eLeft]); } if (!interface.second->GetRightInterface()->IsEmpty()) { myIndxLR[2 * cnt + 1] += 2; - m_localInterfaces.emplace_back(interface.second->GetRightInterface()); + localInterfaces[interface.first][SpatialDomains::eRight] = MemoryManager::AllocateSharedPtr(trace, interface.second->GetRightInterface(), geomIdToTraceId); + m_localInterfaces.emplace_back(localInterfaces[interface.first][SpatialDomains::eRight]); } myIndxLRMap[interface.first] = myIndxLR[2 * cnt + 1]; @@ -96,18 +96,15 @@ InterfaceMapDG::InterfaceMapDG( std::accumulate(rankNumInterfaces.begin(), rankNumInterfaces.end(), 0), 0); // Send all interface IDs to all partitions - std::cout << "RANK: " << comm->GetRank() << " BEFORE Allgatherv for interface IDs" << std::endl; - comm->AllGatherv(myIndxLR, rankLocalInterfaceIds, rankNumInterfaces, - rankLocalInterfaceDisp); - std::cout << "RANK: " << comm->GetRank() << " AFTER Allgatherv for interface IDs" << std::endl; + comm->AllGatherv(myIndxLR, rankLocalInterfaceIds, rankNumInterfaces,rankLocalInterfaceDisp); // Find what interface Ids match with other ranks, then check if opposite edge - std::map> oppRankSharedInterface; // Map of rank to map of interfaces to opposite edge + std::map> oppRankSharedInterface; // Map of rank to vector of interface traces size_t myRank = comm->GetRank(); for (size_t i = 0; i < nRanks; ++i) { - for (size_t j = 0; j < rankNumInterfaces[i] / 2; ++j) + for (size_t j = 0; j < rankNumInterfaces[ i] / 2; ++j) { int otherId = rankLocalInterfaceIds[rankLocalInterfaceDisp[i] + 2 * j]; @@ -122,252 +119,335 @@ InterfaceMapDG::InterfaceMapDG( //If contains opposite edge locally then set true if (otherCode == 3) { - interfaceCollection[otherId]->GetLeftInterface()->SetCheckLocal(true); - interfaceCollection[otherId]->GetRightInterface()->SetCheckLocal(true); + localInterfaces[otherId][SpatialDomains::eLeft]->SetCheckLocal(true); + localInterfaces[otherId][SpatialDomains::eRight]->SetCheckLocal(true); } continue; } - // Interface opposite ranks (could probably simplify logic - // here but this is easy to understand + // Interface opposite ranks int myCode = myIndxLRMap[otherId]; if ((myCode == 1 && otherCode == 2) || (myCode == 1 && otherCode == 3) || (myCode == 3 && otherCode == 2)) { - oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetLeftInterface()); + oppRankSharedInterface[i].emplace_back(localInterfaces[otherId][SpatialDomains::eLeft]); } else if ((myCode == 2 && otherCode == 1) || (myCode == 2 && otherCode == 3) || (myCode == 3 && otherCode == 1)) { - oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetRightInterface()); + oppRankSharedInterface[i].emplace_back(localInterfaces[otherId][SpatialDomains::eRight]); } else if (myCode == 3 && otherCode == 3) { - oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetLeftInterface()); - oppRankSharedInterface[i].emplace_back(interfaceCollection[otherId]->GetRightInterface()); + oppRankSharedInterface[i].emplace_back(localInterfaces[otherId][SpatialDomains::eLeft]); + oppRankSharedInterface[i].emplace_back(localInterfaces[otherId][SpatialDomains::eRight]); } } } } - /*std::cout << "MY RANK: " << myRank; - for (auto i : leftEdgeOppRanks) + // Create individual interface exchange objects (each object is rank -> rank) + // and contains a vector of interfaceTrace objects + for (auto &rank : oppRankSharedInterface) { - std::cout << "\n\t shares interface (left) " << i.first << " with rank: "; - for (auto j : i.second) - { - std::cout << j << " "; - } + m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(m_trace, comm, rank)); } - for (auto i : rightEdgeOppRanks) + + for (auto &interfaceTrace : m_localInterfaces) { - std::cout << "\n\t shares interface (right) " << i.first << " with rank: "; - for (auto j : i.second) - { - std::cout << j << " "; - } + interfaceTrace->CalcLocalMissing(); } - std::cout << std::endl;*/ - // Create individual interface exchange objects - for (auto &rank : oppRankSharedInterface) + auto request = comm->CreateRequest(2 * m_exchange.size()); + for (int i = 0; i < m_exchange.size(); ++i) { - m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(comm, rank)); + m_exchange[i]->RankFillSizes(request, i); } + comm->WaitAll(request); - // Calculate total quadrature points on each interface edge - for (const auto &interface : m_interfaces->GetInterfaces()) + for (int i = 0; i < m_exchange.size(); ++i) { - int tmp = 0; - auto leftInterface = interface.second->GetLeftInterface(); - for (auto id : leftInterface->GetEdgeIds()) - { - tmp += m_trace->GetExp(geomIdToTraceId.at(id))->GetTotPoints(); - } - leftInterface->SetTotPoints(tmp); - - tmp = 0; - auto rightInterface = interface.second->GetRightInterface(); - for (auto id : leftInterface->GetEdgeIds()) - { - tmp += m_trace->GetExp(geomIdToTraceId.at(id))->GetTotPoints(); - } - rightInterface->SetTotPoints(tmp); + m_exchange[i]->SendMissing(request, i); } + comm->WaitAll(request); - // Find local seg-coord pairs and missing coords to communicate to other ranks - std::cout << "RANK: " << comm->GetRank() << " BEFORE CalcLocalCoords" << std::endl; - CalcLocalCoords(trace, geomIdToTraceId); - std::cout << "RANK: " << comm->GetRank() << " AFTER CalcLocalCoords" << std::endl; + for (int i = 0; i < m_exchange.size(); ++i) + { + m_exchange[i]->CalcRankDistances(); + } +} - // Combine multiple interfaces on each rank for communication +void InterfaceMapDG::ExchangeTrace(Array &Fwd, Array &Bwd) +{ + auto comm = m_trace->GetComm(); auto request = comm->CreateRequest(2 * m_exchange.size()); - std::cout << "RANK: " << comm->GetRank() << " BEFORE RankFillSizes()" << std::endl; for (int i = 0; i < m_exchange.size(); ++i) { - m_exchange[i]->RankFillSizes(request, i); + m_exchange[i]->SendFwdTrace(request, i, Fwd); + } + + // Fill local interface traces + for (int i = 0; i < m_localInterfaces.size(); ++i) + { + m_localInterfaces[i]->FillLocalBwdTrace(Fwd, Bwd); } - std::cout << "RANK: " << comm->GetRank() << " AT WAITALL AFTER RankFillSizes()" << std::endl; comm->WaitAll(request); - std::cout << "RANK: " << comm->GetRank() << " BEFORE RankCoordCalc()" << std::endl; for (int i = 0; i < m_exchange.size(); ++i) { - m_exchange[i]->RankCoordCalc(request, i); + m_exchange[i]->FillRankBwdTrace(request, i, Bwd); } - std::cout << "RANK: " << comm->GetRank() << " AT WAITALL AFTER RankCoordCalc()" << std::endl; comm->WaitAll(request); - - comm->Block(); - exit(0); } -void InterfaceExchange::RankFillSizes(LibUtilities::CommRequestSharedPtr request, int requestNum) +void InterfaceTrace::FillLocalBwdTrace(Array &Fwd, Array &Bwd) { - // Get size of all interfaces missing to communicate - m_sendSize = Array(m_interfaces.size()); - m_recvSize = Array(m_interfaces.size()); - for (int i = 0; i < m_interfaces.size(); ++i) + auto childEdgeIds = m_interfaceBase->GetEdgeIds(); + + // If flagged then fill trace from local coords + if(m_checkLocal) { - m_sendSize[i] = m_interfaces[i]->GetMissing().size(); - } + int cnt = 0; + for (auto childId : childEdgeIds) + { + auto childElmt = m_trace->GetExp(m_geomIdToTraceId.at(childId)); + int nq = childElmt->GetTotPoints(); + int offset = m_trace->GetPhys_Offset(m_geomIdToTraceId.at(childId)); - m_comm->Isend(m_rank, m_sendSize, m_interfaces.size(), request, 2 * requestNum); - m_comm->Irecv(m_rank, m_recvSize, m_interfaces.size(), request, 2 * requestNum + 1); + for (int i = 0; i < nq; ++i, ++cnt) + { + if(m_foundLocalCoords.find(cnt) != m_foundLocalCoords.end()) + { + Array edgePhys = Fwd + m_trace->GetPhys_Offset(m_foundLocalCoords[cnt].first); + Array foundPointArray(1, m_foundLocalCoords[cnt].second); + Bwd[offset + i] = m_trace->GetExp(m_foundLocalCoords[cnt].first)->StdPhysEvaluate(foundPointArray, edgePhys); + } + } + } + } } -void InterfaceExchange::RankCoordCalc(LibUtilities::CommRequestSharedPtr request, int requestNum) +void InterfaceExchange::FillRankBwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Bwd) { - m_totSendSize = std::accumulate(m_sendSize.begin(), m_sendSize.end(), 0); - m_totRecvSize = std::accumulate(m_recvSize.begin(), m_recvSize.end(), 0); - m_send = Array(m_totSendSize); - m_recv = Array(m_totRecvSize); - - int cnt = 0; + boost::ignore_unused(requestNum, request, Bwd); + /*int cnt = 0; for (int i = 0; i < m_interfaces.size(); ++i) { - auto missing = m_interfaces[i]->GetMissing(); - for (auto coord : missing) + Array traceTmp(m_sendSize[i]/3); + for (int j = 0; j < m_sendSize[i]/3; ++j) { - m_send[3 * cnt] = std::get<0>(coord.second); - m_send[3 * cnt + 1] = std::get<1>(coord.second); - m_send[3 * cnt + 2] = std::get<2>(coord.second); + traceTmp[j] = m_recvTrace[cnt]; } - } - // Debug output - boost::ignore_unused(request, requestNum); - std::ostringstream output; - output << "MYRANK: " << m_comm->GetRank() << " TO RANK: " << m_rank << "\n"; - for (int i = 0; i < m_interfaces.size(); ++i) + auto childIds = m_interfaces[i]->GetInterface()->GetEdgeIds(); + for (auto id : childIds) + { + + } + + auto missing = m_interfaces[i]->GetMissingCoords(); + for (int j = 0; j < missing.size(); ++j) + { + auto coord = missing[j]; + for (int k = 0; k < 3; ++k, ++cnt) + { + m_send[cnt] = coord[k]; + } + } + }*/ +} + +void InterfaceExchange::SendFwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Fwd) +{ + m_recvTrace = Array(m_totSendSize/3); + Array sendTrace(m_totSendSize/3, std::numeric_limits::epsilon()); + for (auto i : m_foundRankCoords) { - output << "\tINTERFACE: " << m_interfaces[i]->GetId() << " SEND SIZE: " << m_sendSize[i] << " RECV SIZE: " << m_recvSize[i] << "\n"; + Array locCoord(1, i.second.second); + int edgeId = i.second.first; + + Array edgePhys = Fwd + m_trace->GetPhys_Offset(edgeId); + + std::cout << m_comm->GetRank() << " AFTER GETPHYSOFFSET " << std::endl; + + sendTrace[i.first] = m_trace->GetExp(edgeId)->StdPhysEvaluate(locCoord, edgePhys); } - output << "\tTOTAL: " << " SEND SIZE: " << m_totSendSize << " RECV SIZE: " << m_totRecvSize << "\n"; - std::cout << output.str() << std::endl; - m_comm->Isend(m_rank, m_send, m_totSendSize, request, 2 * requestNum); - m_comm->Irecv(m_rank, m_recv, m_totRecvSize, request, 2 * requestNum + 1); + m_comm->Isend(m_rank, sendTrace, m_totRecvSize, request, 2 * requestNum); + m_comm->Irecv(m_rank, m_recvTrace, m_totSendSize, request, 2 * requestNum + 1); } -void InterfaceMapDG::CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId) +void InterfaceExchange::CalcRankDistances() { - for (auto &interface : m_localInterfaces) + int cnt = 0; + for (int i = 0; i < m_interfaces.size(); ++i) { - std::map> missingCoords; - std::map> foundEdgeLocalCoordPair; + auto parentEdgeIds = m_interfaces[i]->GetInterface()->GetEdgeIds(); - if (interface->GetCheckLocal()) + Array recvTmp(m_recvSize[i]); + for (int j = 0; j < m_recvSize[i]; j+=3, ++cnt) { - auto graph = trace->GetGraph(); - Array> geomEdgeIdLocalCoordPair(interface->GetTotPoints()); + NekDouble foundLocCoord; + Array xs(3); + xs[0] = m_recv[j]; + xs[1] = m_recv[j + 1]; + xs[2] = m_recv[j + 2]; - int cnt = 0; - auto childEdgeIds = interface->GetEdgeIds(); - auto parentEdgeIds = interface->GetOppInterface()->GetEdgeIds(); - for (auto childId : childEdgeIds) + for (auto id : parentEdgeIds) { - auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); - size_t nq = childElmt->GetTotPoints(); - Array xc(nq), yc(nq); - childElmt->GetCoords(xc, yc); + SpatialDomains::SegGeomSharedPtr searchSeg = std::static_pointer_cast(m_trace->GetGraph()->GetSegGeom(id)); + NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); - // Check local interface - for (int i = 0; i < nq; ++i) + if (dist < 1e-8) { - Array xs(3); - xs[0] = xc[i]; - xs[1] = yc[i]; - xs[2] = 0; + std::cout << "RANK: " << m_trace->GetComm()->GetRank() << " INTERFACE " << m_interfaces[i]->GetInterface()->GetId() << " I FOUND A RANK COORDINATE! " << xs[0] << " " << xs[1] << " " << xs[2] << std::endl; + m_foundRankCoords[cnt] = std::make_pair(searchSeg->GetGlobalID(), foundLocCoord); + break; + } + } + } + } +} - bool found = false; - int foundEdgeId = -1; - NekDouble foundLocCoord = -1; +InterfaceTrace::InterfaceTrace( + const ExpListSharedPtr &trace, + const SpatialDomains::InterfaceBaseShPtr &interfaceBaseShPtr, + const std::map &geomIdToTraceId) + : m_trace(trace), + m_interfaceBase(interfaceBaseShPtr), + m_geomIdToTraceId(geomIdToTraceId) +{ + // Calc total quad points + for (auto id : m_interfaceBase->GetEdgeIds()) + { + m_totQuadPnts += m_trace->GetExp(m_geomIdToTraceId.at(id))->GetTotPoints(); + } +} - for (auto parentId : parentEdgeIds) - { - SpatialDomains::SegGeomSharedPtr searchSeg = - std::static_pointer_cast( - graph->GetSegGeom(parentId)); - NekDouble dist = - searchSeg->FindDistance(xs, foundLocCoord); - - if (dist < 1e-8) - { - foundEdgeId = parentId; - // std::cout << "Found : "<< xc[i] << " " << yc[i] << " in trace " << foundEdgeId << " loc coord " << foundLocCoord << " @ dist: " << dist << std::endl; - found = true; - break; - } - } +void InterfaceTrace::CalcLocalMissing() +{ + auto childEdgeIds = m_interfaceBase->GetEdgeIds(); - if (!found) - { - missingCoords[cnt] = std::make_tuple(xs[0], xs[1], xs[2]); - } + // If not flagged check local then all points are missing + if(!m_checkLocal) + { + int cnt = 0; + for (auto childId : childEdgeIds) + { + auto childElmt = m_trace->GetExp(m_geomIdToTraceId.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq), zc(nq); + childElmt->GetCoords(xc, yc, zc); - foundEdgeLocalCoordPair[cnt] = std::make_pair(foundEdgeId, foundLocCoord); - cnt++; - } + for (int i = 0; i < nq; ++i, ++cnt) + { + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = zc[i]; + + m_missingCoords[cnt] = xs; } } - else + } + // Otherwise we need to check to see what points the other side of the + // interface on this rank contains + else + { + auto parentEdgeIds = m_interfaceBase->GetOppInterface()->GetEdgeIds(); + + int cnt = 0; + for (auto childId : childEdgeIds) { - int cnt = 0; - auto childEdgeIds = interface->GetEdgeIds(); - for (auto childId : childEdgeIds) + auto childElmt = m_trace->GetExp(m_geomIdToTraceId.at(childId)); + size_t nq = childElmt->GetTotPoints(); + Array xc(nq), yc(nq), zc(nq); + childElmt->GetCoords(xc, yc, zc); + + for (int i = 0; i < nq; ++i, ++cnt) { - auto childElmt = trace->GetExp(geomIdToTraceId.at(childId)); - size_t nq = childElmt->GetTotPoints(); - Array xc(nq), yc(nq); - childElmt->GetCoords(xc, yc); + bool found = false; + NekDouble foundLocCoord; + Array xs(3); + xs[0] = xc[i]; + xs[1] = yc[i]; + xs[2] = zc[i]; + + for (auto id : parentEdgeIds) + { + SpatialDomains::SegGeomSharedPtr searchSeg = std::static_pointer_cast(m_trace->GetGraph()->GetSegGeom(id)); + NekDouble dist = searchSeg->FindDistance(xs, foundLocCoord); + + if (dist < 1e-8) + { + std::cout << "RANK: " << m_trace->GetComm()->GetRank() << " INTERFACE " << m_interfaceBase->GetId() << " I FOUND A LOCAL COORDINATE! " << xs[0] << " " << xs[1] << " " << xs[2] << std::endl; + found = true; + m_foundLocalCoords[cnt] = std::make_pair(m_geomIdToTraceId[searchSeg->GetGlobalID()], foundLocCoord); + break; + } + } - for (int i = 0; i < nq; ++i) + if (!found) { - missingCoords[cnt] = std::make_tuple(xc[i], yc[i], 0); - cnt++; + ASSERTL0(m_trace->GetComm()->IsSerial(), "Serial interface and missing a coordinate.") + m_missingCoords[cnt] = xs; } } } + } +} - interface->SetMissing(missingCoords); +void InterfaceExchange::RankFillSizes(LibUtilities::CommRequestSharedPtr request, int requestNum) +{ + // Get size of all interfaces missing to communicate + m_sendSize = Array(m_interfaces.size()); + m_recvSize = Array(m_interfaces.size()); + for (int i = 0; i < m_interfaces.size(); ++i) + { + m_sendSize[i] = m_interfaces[i]->GetMissingCoords().size()*3; + } - // Cout missing coords (debug) - /*std::ostringstream output; - output << "MY RANK: " << trace->GetComm()->GetRank() << " INTERFACE: " << interface->GetId() << " " << SpatialDomains::InterfaceSideStr[interface->GetSide()] << " MISSING: \n"; - for (auto i : missingCoords) + m_comm->Isend(m_rank, m_sendSize, m_interfaces.size(), request, 2 * requestNum); + m_comm->Irecv(m_rank, m_recvSize, m_interfaces.size(), request, 2 * requestNum + 1); +} + +void InterfaceExchange::SendMissing(LibUtilities::CommRequestSharedPtr request, int requestNum) +{ + m_totSendSize = std::accumulate(m_sendSize.begin(), m_sendSize.end(), 0); + m_totRecvSize = std::accumulate(m_recvSize.begin(), m_recvSize.end(), 0); + m_send = Array(m_totSendSize); + m_recv = Array(m_totRecvSize); + + int cnt = 0; + for (int i = 0; i < m_interfaces.size(); ++i) + { + auto missing = m_interfaces[i]->GetMissingCoords(); + for (int j = 0; j < missing.size(); ++j) { - output << "\t" << i.first << "\t" << std::get<0>(i.second) << " " - << std::get<1>(i.second) << " " << std::get<2>(i.second) - << "\n"; + auto coord = missing[j]; + for (int k = 0; k < 3; ++k, ++cnt) + { + m_send[cnt] = coord[k]; + } } - output << std::endl; - std::cout << output.str();*/ } + + // Debug output + std::ostringstream output; + output << "MYRANK: " << m_comm->GetRank() << " TO RANK: " << m_rank << "\n"; + for (int i = 0; i < m_interfaces.size(); ++i) + { + output << "\tINTERFACE: " << m_interfaces[i]->GetInterface()->GetId() << " SEND SIZE: " << m_sendSize[i] << " RECV SIZE: " << m_recvSize[i] << "\n"; + } + output << "\tTOTAL: " << " SEND SIZE: " << m_totSendSize << " RECV SIZE: " << m_totRecvSize << "\n"; + std::cout << output.str() << std::endl; + + m_comm->Isend(m_rank, m_send, m_totSendSize, request, 2 * requestNum); + m_comm->Irecv(m_rank, m_recv, m_totRecvSize, request, 2 * requestNum + 1); } /*std::vector> CalcCoordsOneWay( diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h index 1f909c998..432e4572f 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -43,36 +43,88 @@ namespace Nektar namespace MultiRegions { -class InterfaceExchange +class InterfaceTrace { +public: + /// Default constructor + MULTI_REGIONS_EXPORT InterfaceTrace( + const ExpListSharedPtr &trace, + const SpatialDomains::InterfaceBaseShPtr &interfaceBaseShPtr, + const std::map &geomIdToTraceId); + + /// Default destructor + MULTI_REGIONS_EXPORT virtual ~InterfaceTrace() = default; + + inline void SetCheckLocal(bool flag) + { + m_checkLocal = flag; + } + + inline std::map> GetMissingCoords() + { + return m_missingCoords; + } + + void CalcLocalMissing(); + + SpatialDomains::InterfaceBaseShPtr GetInterface() // Debug REMOVE THIS. + { + return m_interfaceBase; + } + + void FillLocalBwdTrace(Array &Fwd, Array &Bwd); + + +private: + ExpListSharedPtr m_trace; + SpatialDomains::InterfaceBaseShPtr m_interfaceBase; + std::map m_geomIdToTraceId; + int m_totQuadPnts = 0; + bool m_checkLocal = false; + std::map> m_missingCoords; + std::map> m_foundLocalCoords; +}; + +typedef std::shared_ptr InterfaceTraceSharedPtr; +class InterfaceExchange +{ public: /// Default destructor MULTI_REGIONS_EXPORT virtual ~InterfaceExchange() = default; /// Default constructor MULTI_REGIONS_EXPORT InterfaceExchange( + const ExpListSharedPtr &trace, const LibUtilities::CommSharedPtr &comm, - std::pair> rankPair) - : m_comm(comm), + std::pair> rankPair) + : m_trace(trace), + m_comm(comm), m_rank(rankPair.first), m_interfaces(rankPair.second) { } MULTI_REGIONS_EXPORT void RankFillSizes(LibUtilities::CommRequestSharedPtr request, int requestNum); - MULTI_REGIONS_EXPORT void RankCoordCalc(LibUtilities::CommRequestSharedPtr request, int requestNum); + MULTI_REGIONS_EXPORT void SendMissing(LibUtilities::CommRequestSharedPtr request, int requestNum); + MULTI_REGIONS_EXPORT void CalcRankDistances(); + MULTI_REGIONS_EXPORT void SendFwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Fwd); + MULTI_REGIONS_EXPORT void FillRankBwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Bwd); + private: + const ExpListSharedPtr m_trace; const LibUtilities::CommSharedPtr m_comm; int m_rank; - const std::vector m_interfaces; + const std::vector m_interfaces; Array m_sendSize; Array m_recvSize; int m_totSendSize = 0; int m_totRecvSize = 0; Array m_send; Array m_recv; - std::map m_checkLocal; + std::map> m_foundRankCoords; + Array m_recvTrace; + }; typedef std::shared_ptr InterfaceExchangeSharedPtr; @@ -90,10 +142,12 @@ public: const std::map geomIdToTraceId); void CalcLocalCoords(const ExpListSharedPtr &trace, std::map geomIdToTraceId); + void ExchangeTrace(Array &Fwd, Array &Bwd); + private: SpatialDomains::InterfacesSharedPtr m_interfaces; - std::vector m_localInterfaces; + std::vector m_localInterfaces; const ExpListSharedPtr m_trace; std::vector m_exchange; std::map m_geomIdToTraceId; diff --git a/library/MultiRegions/DisContField2D.cpp b/library/MultiRegions/DisContField2D.cpp index 7431cf19d..50090c9fc 100644 --- a/library/MultiRegions/DisContField2D.cpp +++ b/library/MultiRegions/DisContField2D.cpp @@ -1373,58 +1373,7 @@ namespace Nektar } DisContField2D::v_PeriodicBwdCopy(Fwd, Bwd); - - //m_interfaceMap->CalcLocalInterfaceCoords(); - - /* // Interpolate from each side of the interface to the other. - CalcLocalInterfaceCoords(); - - - for (auto &interface : m_interfaces->GetInterfaces()) - { - size_t indx = interface.first; - auto pair = interface.second; - - auto leftEdge = pair->GetLeftInterface()->GetEdgeIds(); - auto rightEdge = pair->GetRightInterface()->GetEdgeIds(); - - size_t cnt = 0; - for (auto leftId : leftEdge) - { - size_t nq = m_trace->GetExp(m_geomIdToTraceId[leftId]) - ->GetTotPoints(); - for (size_t i = 0; i < nq; ++i) - { - Array edgePhys = - Fwd + m_trace->GetPhys_Offset( - m_locCoordSegIdPair[indx][cnt].second); - Array foundPointArray( - 1, m_locCoordSegIdPair[indx][cnt].first); - Bwd[m_trace->GetPhys_Offset( - m_geomIdToTraceId[leftId]) + i] = m_trace - ->GetExp(m_locCoordSegIdPair[indx][cnt++].second) - ->StdPhysEvaluate(foundPointArray, edgePhys); - } - } - - for (auto rightId : rightEdge) - { - size_t nq = m_trace->GetExp(m_geomIdToTraceId[rightId]) - ->GetTotPoints(); - for (size_t i = 0; i < nq; ++i) - { - Array edgePhys = - Fwd + m_trace->GetPhys_Offset( - m_locCoordSegIdPair[indx][cnt].second); - Array foundPointArray( - 1, m_locCoordSegIdPair[indx][cnt].first); - Bwd[m_trace->GetPhys_Offset( - m_geomIdToTraceId[rightId]) + i] = m_trace - ->GetExp(m_locCoordSegIdPair[indx][cnt++].second) - ->StdPhysEvaluate(foundPointArray, edgePhys); - } - } - }*/ + m_interfaceMap->ExchangeTrace(Fwd, Bwd); } void DisContField2D::v_AddTraceQuadPhysToField( diff --git a/library/SpatialDomains/Interface.h b/library/SpatialDomains/Interface.h index ba737296f..34f846b2e 100644 --- a/library/SpatialDomains/Interface.h +++ b/library/SpatialDomains/Interface.h @@ -170,16 +170,6 @@ struct InterfaceBase return m_id; } - inline bool GetCheckLocal() - { - return m_checkLocal; - } - - inline void SetCheckLocal(bool flag) - { - m_checkLocal = flag; - } - inline std::map> GetMissing() { return m_missingCoords; -- GitLab From 0b3246072800beebf7760dcde7f6be377bb4da0f Mon Sep 17 00:00:00 2001 From: Ed Laughton Date: Mon, 20 Jul 2020 13:32:09 +0100 Subject: [PATCH 060/408] Before changing comm to include left/right sizes --- .../AssemblyMap/InterfaceMapDG.cpp | 98 ++++++++++--------- .../MultiRegions/AssemblyMap/InterfaceMapDG.h | 11 ++- 2 files changed, 59 insertions(+), 50 deletions(-) diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp index de28126ce..b9961824c 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.cpp @@ -153,12 +153,13 @@ InterfaceMapDG::InterfaceMapDG( // and contains a vector of interfaceTrace objects for (auto &rank : oppRankSharedInterface) { - m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(m_trace, comm, rank)); + m_exchange.emplace_back(MemoryManager::AllocateSharedPtr(m_trace, comm, rank, geomIdToTraceId)); } for (auto &interfaceTrace : m_localInterfaces) { interfaceTrace->CalcLocalMissing(); + std::cout << "RANK: " << comm->GetRank() << " interface " << interfaceTrace->GetInterface()->GetId() << " side " << SpatialDomains::InterfaceSideStr[interfaceTrace->GetInterface()->GetSide()] << " is missing " << interfaceTrace->GetMissingCoords().size() << " coords." << std::endl; } auto request = comm->CreateRequest(2 * m_exchange.size()); @@ -199,9 +200,8 @@ void InterfaceMapDG::ExchangeTrace(Array &Fwd, ArrayFillRankBwdTrace(request, i, Bwd); + m_exchange[i]->FillRankBwdTraceExchange(Bwd); } - comm->WaitAll(request); } void InterfaceTrace::FillLocalBwdTrace(Array &Fwd, Array &Bwd) @@ -231,65 +231,75 @@ void InterfaceTrace::FillLocalBwdTrace(Array &Fwd, Array &Bwd) +void InterfaceExchange::FillRankBwdTraceExchange(Array &Bwd) { - boost::ignore_unused(requestNum, request, Bwd); - /*int cnt = 0; + int cnt = 0; for (int i = 0; i < m_interfaces.size(); ++i) { Array traceTmp(m_sendSize[i]/3); - for (int j = 0; j < m_sendSize[i]/3; ++j) + for (int j = 0; j < m_sendSize[i]/3; ++j, ++cnt) { traceTmp[j] = m_recvTrace[cnt]; + + if(m_comm->GetRank() == 2) + { + std::cout << traceTmp[j] << std::endl; + } } - auto childIds = m_interfaces[i]->GetInterface()->GetEdgeIds(); - for (auto id : childIds) - { + m_interfaces[i]->FillRankBwdTrace(traceTmp, Bwd); + } +} - } +void InterfaceTrace::FillRankBwdTrace(Array &trace, Array &Bwd) +{ + auto childEdgeIds = m_interfaceBase->GetEdgeIds(); - auto missing = m_interfaces[i]->GetMissingCoords(); - for (int j = 0; j < missing.size(); ++j) + int cnt = 0; + for (auto childId : childEdgeIds) + { + auto childElmt = m_trace->GetExp(m_geomIdToTraceId.at(childId)); + int nq = childElmt->GetTotPoints(); + int offset = m_trace->GetPhys_Offset(m_geomIdToTraceId.at(childId)); + + for (int i = 0; i < nq; ++i, ++cnt) { - auto coord = missing[j]; - for (int k = 0; k < 3; ++k, ++cnt) + if(trace[cnt] != std::numeric_limits::epsilon()) { - m_send[cnt] = coord[k]; + Bwd[offset + i] = trace[cnt]; } } - }*/ + } } void InterfaceExchange::SendFwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Fwd) { + boost::ignore_unused(request, requestNum, Fwd); m_recvTrace = Array(m_totSendSize/3); - Array sendTrace(m_totSendSize/3, std::numeric_limits::epsilon()); + Array sendTrace(m_totRecvSize/3, std::numeric_limits::epsilon()); for (auto i : m_foundRankCoords) { Array locCoord(1, i.second.second); int edgeId = i.second.first; - Array edgePhys = Fwd + m_trace->GetPhys_Offset(edgeId); - - std::cout << m_comm->GetRank() << " AFTER GETPHYSOFFSET " << std::endl; - - sendTrace[i.first] = m_trace->GetExp(edgeId)->StdPhysEvaluate(locCoord, edgePhys); + Array edgePhys = Fwd + m_trace->GetPhys_Offset(m_geomIdToTraceId.at(edgeId)); + sendTrace[i.first] = m_trace->GetExp(m_geomIdToTraceId.at(edgeId))->StdPhysEvaluate(locCoord, edgePhys); } - m_comm->Isend(m_rank, sendTrace, m_totRecvSize, request, 2 * requestNum); - m_comm->Irecv(m_rank, m_recvTrace, m_totSendSize, request, 2 * requestNum + 1); + m_comm->Isend(m_rank, sendTrace, m_totRecvSize/3, request, 2 * requestNum); + m_comm->Irecv(m_rank, m_recvTrace, m_totSendSize/3, request, 2 * requestNum + 1); } void InterfaceExchange::CalcRankDistances() { - int cnt = 0; + Array disp(m_recvSize.size() + 1, 0.0); + std::partial_sum(m_recvSize.begin(), m_recvSize.end(), &disp[1]); + for (int i = 0; i < m_interfaces.size(); ++i) { auto parentEdgeIds = m_interfaces[i]->GetInterface()->GetEdgeIds(); - Array recvTmp(m_recvSize[i]); - for (int j = 0; j < m_recvSize[i]; j+=3, ++cnt) + for (int j = disp[i]; j < disp[i + 1]; j+=3) { NekDouble foundLocCoord; Array xs(3); @@ -304,8 +314,11 @@ void InterfaceExchange::CalcRankDistances() if (dist < 1e-8) { - std::cout << "RANK: " << m_trace->GetComm()->GetRank() << " INTERFACE " << m_interfaces[i]->GetInterface()->GetId() << " I FOUND A RANK COORDINATE! " << xs[0] << " " << xs[1] << " " << xs[2] << std::endl; - m_foundRankCoords[cnt] = std::make_pair(searchSeg->GetGlobalID(), foundLocCoord); + if(m_comm->GetRank() == 0 && m_rank == 2) + { + std::cout << j/3 << " coord -> "<< xs[0] << "\t" << xs[1] << "\t found in seg: " << searchSeg->GetGlobalID() << " at loc coord = " << foundLocCoord << std::endl; + } + m_foundRankCoords[j/3] = std::make_pair(searchSeg->GetGlobalID(), foundLocCoord); break; } } @@ -349,7 +362,7 @@ void InterfaceTrace::CalcLocalMissing() xs[0] = xc[i]; xs[1] = yc[i]; xs[2] = zc[i]; - + //std::cout << "Interface: " << m_interfaceBase->GetId() << " side " << m_interfaceBase->GetSide() << "NOT FOUND: " << xs[0] << " " << xs[1] << " " << xs[2] << std::endl; m_missingCoords[cnt] = xs; } } @@ -384,7 +397,7 @@ void InterfaceTrace::CalcLocalMissing() if (dist < 1e-8) { - std::cout << "RANK: " << m_trace->GetComm()->GetRank() << " INTERFACE " << m_interfaceBase->GetId() << " I FOUND A LOCAL COORDINATE! " << xs[0] << " " << xs[1] << " " << xs[2] << std::endl; + //std::cout << "RANK: " << m_trace->GetComm()->GetRank() << " INTERFACE " << m_interfaceBase->GetId() << " I FOUND A LOCAL COORDINATE! " << xs[0] << " " << xs[1] << " " << xs[2] << std::endl; found = true; m_foundLocalCoords[cnt] = std::make_pair(m_geomIdToTraceId[searchSeg->GetGlobalID()], foundLocCoord); break; @@ -393,7 +406,6 @@ void InterfaceTrace::CalcLocalMissing() if (!found) { - ASSERTL0(m_trace->GetComm()->IsSerial(), "Serial interface and missing a coordinate.") m_missingCoords[cnt] = xs; } } @@ -411,6 +423,11 @@ void InterfaceExchange::RankFillSizes(LibUtilities::CommRequestSharedPtr request m_sendSize[i] = m_interfaces[i]->GetMissingCoords().size()*3; } + for (int i = 0; i < m_sendSize.size(); ++i) + { + //std::cout << "RANK: " << m_comm->GetRank() << " TO RANK: " << m_rank << " INTERFACE " << i << " HAS SIZE: " << m_sendSize[i] << std::endl; + } + m_comm->Isend(m_rank, m_sendSize, m_interfaces.size(), request, 2 * requestNum); m_comm->Irecv(m_rank, m_recvSize, m_interfaces.size(), request, 2 * requestNum + 1); } @@ -426,26 +443,15 @@ void InterfaceExchange::SendMissing(LibUtilities::CommRequestSharedPtr request, for (int i = 0; i < m_interfaces.size(); ++i) { auto missing = m_interfaces[i]->GetMissingCoords(); - for (int j = 0; j < missing.size(); ++j) + for (auto coord : missing) { - auto coord = missing[j]; for (int k = 0; k < 3; ++k, ++cnt) { - m_send[cnt] = coord[k]; + m_send[cnt] = coord.second[k]; } } } - // Debug output - std::ostringstream output; - output << "MYRANK: " << m_comm->GetRank() << " TO RANK: " << m_rank << "\n"; - for (int i = 0; i < m_interfaces.size(); ++i) - { - output << "\tINTERFACE: " << m_interfaces[i]->GetInterface()->GetId() << " SEND SIZE: " << m_sendSize[i] << " RECV SIZE: " << m_recvSize[i] << "\n"; - } - output << "\tTOTAL: " << " SEND SIZE: " << m_totSendSize << " RECV SIZE: " << m_totRecvSize << "\n"; - std::cout << output.str() << std::endl; - m_comm->Isend(m_rank, m_send, m_totSendSize, request, 2 * requestNum); m_comm->Irecv(m_rank, m_recv, m_totRecvSize, request, 2 * requestNum + 1); } diff --git a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h index 432e4572f..9c4e2698b 100644 --- a/library/MultiRegions/AssemblyMap/InterfaceMapDG.h +++ b/library/MultiRegions/AssemblyMap/InterfaceMapDG.h @@ -73,6 +73,7 @@ public: } void FillLocalBwdTrace(Array &Fwd, Array &Bwd); + void FillRankBwdTrace(Array &trace, Array &Bwd); private: @@ -97,11 +98,13 @@ public: MULTI_REGIONS_EXPORT InterfaceExchange( const ExpListSharedPtr &trace, const LibUtilities::CommSharedPtr &comm, - std::pair> rankPair) + std::pair> rankPair, + const std::map &geomIdToTraceId) : m_trace(trace), m_comm(comm), m_rank(rankPair.first), - m_interfaces(rankPair.second) + m_interfaces(rankPair.second), + m_geomIdToTraceId(geomIdToTraceId) { } @@ -109,7 +112,7 @@ public: MULTI_REGIONS_EXPORT void SendMissing(LibUtilities::CommRequestSharedPtr request, int requestNum); MULTI_REGIONS_EXPORT void CalcRankDistances(); MULTI_REGIONS_EXPORT void SendFwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Fwd); - MULTI_REGIONS_EXPORT void FillRankBwdTrace(LibUtilities::CommRequestSharedPtr request, int requestNum, Array &Bwd); + MULTI_REGIONS_EXPORT void FillRankBwdTraceExchange(Array &Bwd); private: const ExpListSharedPtr m_trace; @@ -124,7 +127,7 @@ private: Array m_recv; std::map> m_foundRankCoords; Array m_recvTrace; - + std::map m_geomIdToTraceId; }; typedef std::shared_ptr InterfaceExchangeSharedPtr; -- GitLab From a9197d562ef23da31f36a861745ac0f7e5094bc2 Mon Sep 17 00:00:00 2001 From: vidhi Date: Mon, 20 Jul 2020 11:42:19 -0600 Subject: [PATCH 061/408] triangles and quad method2 basis change --- library/StdRegions/StdExpansion.cpp | 54 +++- library/StdRegions/StdExpansion.h | 73 +++++- library/StdRegions/StdExpansion2D.cpp | 3 - library/StdRegions/StdExpansion2D.h | 3 +- library/StdRegions/StdHexExp.cpp | 338 ++++++++++++++++++++++++++ library/StdRegions/StdHexExp.h | 58 +++++ library/StdRegions/StdQuadExp.cpp | 207 ++++++++++------ library/StdRegions/StdQuadExp.h | 29 ++- library/StdRegions/StdTriExp.cpp | 241 ++++++++++-------- library/StdRegions/StdTriExp.h | 26 +- 10 files changed, 828 insertions(+), 204 deletions(-) diff --git a/library/StdRegions/StdExpansion.cpp b/library/StdRegions/StdExpansion.cpp index a35148e31..5819943f2 100644 --- a/library/StdRegions/StdExpansion.cpp +++ b/library/StdRegions/StdExpansion.cpp @@ -1249,6 +1249,31 @@ namespace Nektar } + Array< OneD, Array >StdExpansion::v_GetPhysEvalALL() + { + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return NullNekDoubleArrayofArray; + } + /* + Array StdExpansion::v_GetPhysEvalALLdx() + { + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return NullNekDouble1DArray; + } + + Array StdExpansion::v_GetPhysEvalALLdy() + { + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return NullNekDouble1DArray; + } + + Array StdExpansion::v_GetPhysEvalALLdz() + { + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return NullNekDouble1DArray; + }*/ + + NekDouble StdExpansion::v_PhysEvaluatedxBasis(const Array& coords, int mode) { boost::ignore_unused(coords, mode); @@ -1271,6 +1296,28 @@ namespace Nektar } + NekDouble StdExpansion::v_PhysEvaluatedxBasisBary(const Array& coords, int mode) + { + boost::ignore_unused(coords, mode); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + NekDouble StdExpansion::v_PhysEvaluatedyBasisBary(const Array& coords, int mode) + { + boost::ignore_unused(coords, mode); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + NekDouble StdExpansion::v_PhysEvaluatedzBasisBary(const Array& coords, int mode) + { + boost::ignore_unused(coords, mode); + NEKERROR(ErrorUtil::efatal, "Method does not exist for this shape"); + return 0; + } + + void StdExpansion::v_FillMode(const int mode, Array &outarray) { @@ -1279,23 +1326,20 @@ namespace Nektar "been defined for this shape"); } - - void StdExpansion::v_FillModedy(const int mode, Array &outarray) + void StdExpansion::v_FillModedx(const int mode, Array &outarray) { boost::ignore_unused(mode, outarray); NEKERROR(ErrorUtil::efatal, "This function has not " "been defined for this shape"); } - - void StdExpansion::v_FillModedx(const int mode, Array &outarray) + void StdExpansion::v_FillModedy(const int mode, Array &outarray) { boost::ignore_unused(mode, outarray); NEKERROR(ErrorUtil::efatal, "This function has not " "been defined for this shape"); } - void StdExpansion::v_FillModedz(const int mode, Array &outarray) { boost::ignore_unused(mode, outarray); diff --git a/library/StdRegions/StdExpansion.h b/library/StdRegions/StdExpansion.h index 9a3ae5ca4..0c1cbe513 100644 --- a/library/StdRegions/StdExpansion.h +++ b/library/StdRegions/StdExpansion.h @@ -63,6 +63,12 @@ namespace Nektar { public: + Array > m_physevalall = Array< OneD, Array< OneD, NekDouble> >(4); + // 0 = basis eval + // 1 = dx + // 2 = dy + // 3 = dz + /** \brief Default Constructor */ STD_REGIONS_EXPORT StdExpansion(); @@ -502,16 +508,19 @@ namespace Nektar v_FillMode(mode, outarray); } + void FillModedx(const int mode, Array &outarray) { v_FillModedx(mode, outarray); } + void FillModedy(const int mode, Array &outarray) { v_FillModedy(mode, outarray); } + void FillModedz(const int mode, Array &outarray) { v_FillModedz(mode, outarray); @@ -1000,7 +1009,11 @@ namespace Nektar { return v_PhysEvaluateBasis(coords, mode); } - + + Array< OneD, Array > GetPhysEvalALL() + { + return v_GetPhysEvalALL(); + } NekDouble PhysEvaluatedx( const Array &coords, @@ -1043,7 +1056,9 @@ namespace Nektar { return v_PhysEvaluatedyBasis(coords, mode); } - + + + NekDouble PhysEvaluatedzBasis( const Array& coords, int mode) @@ -1051,6 +1066,30 @@ namespace Nektar return v_PhysEvaluatedzBasis(coords, mode); } + + NekDouble PhysEvaluatedxBasisBary( + const Array& coords, + int mode) + { + return v_PhysEvaluatedxBasisBary(coords, mode); + } + + + NekDouble PhysEvaluatedyBasisBary( + const Array& coords, + int mode) + { + return v_PhysEvaluatedyBasisBary(coords, mode); + } + + + NekDouble PhysEvaluatedzBasisBary( + const Array& coords, + int mode) + { + return v_PhysEvaluatedzBasisBary(coords, mode); + } + /** * \brief Convert local cartesian coordinate \a xi into local * collapsed coordinates \a eta @@ -1530,9 +1569,18 @@ namespace Nektar { const int nquad = m_base[DIR]->GetNumPoints(); return BaryEvaluateDeriv( - coord, &(m_base[DIR]->GetDbdata())[0] + nquad * mode); + coord, &(m_base[DIR]->GetBdata())[0] + nquad * mode); } private: + + STD_REGIONS_EXPORT virtual Array< OneD, Array< OneD, NekDouble> >v_GetPhysEvalALL();/* + STD_REGIONS_EXPORT virtual Array< OneD, NekDouble> v_GetPhysEvalALLdx(); + STD_REGIONS_EXPORT virtual Array< OneD, NekDouble> v_GetPhysEvalALLdy(); + STD_REGIONS_EXPORT virtual Array< OneD, NekDouble> v_GetPhysEvalALLdz();*/ + //Array PhysEvalALLDx; + // Array PhysEvalALLDy; + //Array PhysEvalALLDz; + // Virtual functions STD_REGIONS_EXPORT virtual int v_GetNverts() const = 0; STD_REGIONS_EXPORT virtual int v_GetNtraces() const; @@ -1666,6 +1714,8 @@ namespace Nektar STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateBasis (const Array& coords, int mode); + STD_REGIONS_EXPORT Array< OneD, Array >v_PhysEvalALL(); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedxBasis (const Array& coords, int mode); @@ -1675,6 +1725,21 @@ namespace Nektar STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedzBasis (const Array& coords, int mode); + + // These methods calculate the interpolation of the + // derivatives in respective directions using the + // modified barycentric interpolation formula + // [ Hope is that this will be faster and replace + // current impl of v_PhysEvaluatedxBasis() ] + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedxBasisBary + (const Array& coords, int mode); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedyBasisBary + (const Array& coords, int mode); + + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluatedzBasisBary + (const Array& coords, int mode); + STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluateDeriv (int dir, const Array& coords, @@ -1713,7 +1778,7 @@ namespace Nektar STD_REGIONS_EXPORT virtual void v_FillModedy(const int mode, Array &outarray); STD_REGIONS_EXPORT virtual void v_FillModedz(const int mode, - Array &outarray); + Array &outarray); STD_REGIONS_EXPORT virtual DNekMatSharedPtr v_GenMatrix( const StdMatrixKey &mkey); diff --git a/library/StdRegions/StdExpansion2D.cpp b/library/StdRegions/StdExpansion2D.cpp index 998119f2b..94b03e4af 100644 --- a/library/StdRegions/StdExpansion2D.cpp +++ b/library/StdRegions/StdExpansion2D.cpp @@ -143,9 +143,6 @@ namespace Nektar } - - - NekDouble StdExpansion2D::v_PhysEvaluate( const Array &I, const Array &physvals) diff --git a/library/StdRegions/StdExpansion2D.h b/library/StdRegions/StdExpansion2D.h index f17673936..844f6a355 100644 --- a/library/StdRegions/StdExpansion2D.h +++ b/library/StdRegions/StdExpansion2D.h @@ -144,7 +144,6 @@ namespace StdRegions STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& coords, const Array& physvals); - STD_REGIONS_EXPORT virtual NekDouble v_PhysEvaluate( const Array& I, @@ -179,6 +178,8 @@ namespace StdRegions private: + + // Virtual Functions ---------------------------------------- virtual int v_GetShapeDimension() const { diff --git a/library/StdRegions/StdHexExp.cpp b/library/StdRegions/StdHexExp.cpp index 2e56ac66d..9d2b342fd 100644 --- a/library/StdRegions/StdHexExp.cpp +++ b/library/StdRegions/StdHexExp.cpp @@ -47,6 +47,8 @@ namespace Nektar StdHexExp::StdHexExp() { + m_physevalall = v_GetPhysEvalALL(); + } StdHexExp::StdHexExp(const LibUtilities::BasisKey &Ba, @@ -57,12 +59,16 @@ namespace Nektar StdExpansion3D(Ba.GetNumModes()*Bb.GetNumModes()*Bc.GetNumModes(), Ba, Bb, Bc) { + m_physevalall = v_GetPhysEvalALL(); + } StdHexExp::StdHexExp(const StdHexExp &T): StdExpansion(T), StdExpansion3D(T) { + m_physevalall = v_GetPhysEvalALL(); + } StdHexExp::~StdHexExp() @@ -658,6 +664,181 @@ namespace Nektar } } + Array >StdHexExp::v_GetPhysEvalALL() + { + Array > tmp_ret(4); + NekDouble totPts = GetTotPoints(); + Array tmp(totPts*m_ncoeffs); + Array tmpdx(totPts*m_ncoeffs); + Array tmpdy(totPts*m_ncoeffs); + Array tmpdz(totPts*m_ncoeffs); + for(int i = 0; i < m_ncoeffs; i++) + { + Array k(totPts); + v_FillMode(i,k); + Vmath::Vcopy(totPts, &k[0], 1, &tmp[(i*totPts)], 1); + v_FillModedx(i,k); + Vmath::Vcopy(totPts, &k[0], 1, &tmpdx[(i*totPts)], 1); + v_FillModedy(i,k); + Vmath::Vcopy(totPts, &k[0], 1, &tmpdy[(i*totPts)], 1); + v_FillModedz(i,k); + Vmath::Vcopy(totPts, &k[0], 1, &tmpdz[(i*totPts)], 1); + + } + + tmp_ret[0] = tmp; + tmp_ret[1] = tmpdx; + tmp_ret[2] = tmpdy; + tmp_ret[3] = tmpdz; + return tmp_ret; + } + + NekDouble StdHexExp::v_PhysEvaluatedxBasis( + const Array& coords, + int mode) + { + Array coll(2); + LocCoordToLocCollapsed(coords, coll); + + int tot = GetTotPoints(); + + Array physvals(tot); + Vmath::Vcopy(tot, &m_physevalall[1][0+mode], 1, &physvals[0],1); + + return v_PhysEvaluatedx(coll, physvals); + + } + + NekDouble StdHexExp::v_PhysEvaluatedx( const Array &coords, const Array &physvals) + { + + + Array eta(3); + + WARNINGL2(coords[0] >= -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + WARNINGL2(coords[0] <= 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + WARNINGL2(coords[1] >= -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + WARNINGL2(coords[1] <= 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + WARNINGL2(coords[2] >= -1 - NekConstants::kNekZeroTol, + "coord[2] < -1"); + WARNINGL2(coords[2] <= 1 + NekConstants::kNekZeroTol, + "coord[2] > 1"); + + // Obtain local collapsed corodinate from Cartesian coordinate. + LocCoordToLocCollapsed(coords, eta); + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + const int nq2 = m_base[2]->GetNumPoints(); + + Array wsp1(nq1 * nq2), wsp2(nq2); + + // Construct the 2D square... + const NekDouble *ptr = &physvals[0]; + for (int i = 0; i < nq1 * nq2; ++i, ptr += nq0) + { + wsp1[i] = StdExpansion::BaryEvaluateDeriv<0>(eta[0], ptr); + } + + for (int i = 0; i < nq2; ++i) + { + wsp2[i] = StdExpansion::BaryEvaluate<1>(eta[1], &wsp1[i * nq1]); + } + + return StdExpansion::BaryEvaluate<2>(eta[2], &wsp2[0]); + } + + NekDouble StdHexExp::v_PhysEvaluatedy( const Array &coords, const Array &physvals) + { + + + Array eta(3); + + WARNINGL2(coords[0] >= -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + WARNINGL2(coords[0] <= 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + WARNINGL2(coords[1] >= -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + WARNINGL2(coords[1] <= 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + WARNINGL2(coords[2] >= -1 - NekConstants::kNekZeroTol, + "coord[2] < -1"); + WARNINGL2(coords[2] <= 1 + NekConstants::kNekZeroTol, + "coord[2] > 1"); + + // Obtain local collapsed corodinate from Cartesian coordinate. + LocCoordToLocCollapsed(coords, eta); + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + const int nq2 = m_base[2]->GetNumPoints(); + + Array wsp1(nq1 * nq2), wsp2(nq2); + + // Construct the 2D square... + const NekDouble *ptr = &physvals[0]; + for (int i = 0; i < nq1 * nq2; ++i, ptr += nq0) + { + wsp1[i] = StdExpansion::BaryEvaluate<0>(eta[0], ptr); + } + + for (int i = 0; i < nq2; ++i) + { + wsp2[i] = StdExpansion::BaryEvaluateDeriv<1>(eta[1], &wsp1[i * nq1]); + } + + return StdExpansion::BaryEvaluate<2>(eta[2], &wsp2[0]); + } + + NekDouble StdHexExp::v_PhysEvaluatedz( const Array &coords, const Array &physvals) + { + + + Array eta(3); + + WARNINGL2(coords[0] >= -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + WARNINGL2(coords[0] <= 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + WARNINGL2(coords[1] >= -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + WARNINGL2(coords[1] <= 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + WARNINGL2(coords[2] >= -1 - NekConstants::kNekZeroTol, + "coord[2] < -1"); + WARNINGL2(coords[2] <= 1 + NekConstants::kNekZeroTol, + "coord[2] > 1"); + + // Obtain local collapsed corodinate from Cartesian coordinate. + LocCoordToLocCollapsed(coords, eta); + + const int nq0 = m_base[0]->GetNumPoints(); + const int nq1 = m_base[1]->GetNumPoints(); + const int nq2 = m_base[2]->GetNumPoints(); + + Array wsp1(nq1 * nq2), wsp2(nq2); + + // Construct the 2D square... + const NekDouble *ptr = &physvals[0]; + for (int i = 0; i < nq1 * nq2; ++i, ptr += nq0) + { + wsp1[i] = StdExpansion::BaryEvaluate<0>(eta[0], ptr); + } + + for (int i = 0; i < nq2; ++i) + { + wsp2[i] = StdExpansion::BaryEvaluate<1>(eta[1], &wsp1[i * nq1]); + } + + return StdExpansion::BaryEvaluateDeriv<2>(eta[2], &wsp2[0]); + } + + NekDouble StdHexExp::v_PhysEvaluateBasis( const Array& coords, int mode) @@ -687,6 +868,101 @@ namespace Nektar StdExpansion::BaryEvaluateBasis<2>(coords[2], mode2); } + + void StdHexExp::v_FillModedx(const int mode, + Array &outarray) + { + int i; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + Array base0 = m_base[0]->GetDbdata(); + Array base1 = m_base[1]->GetBdata(); + int btmp0 = m_base[0]->GetNumModes(); + int mode0 = mode%btmp0; + int mode1 = mode/btmp0; + + ASSERTL2(mode1 == (int)floor((1.0*mode)/btmp0), + "Integer Truncation not Equiv to Floor"); + + ASSERTL2(m_ncoeffs > mode, + "calling argument mode is larger than total expansion order"); + + for(i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get() + mode0*nquad0), + 1, &outarray[0]+i*nquad0,1); + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode1*nquad1),1, + &outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + + void StdHexExp::v_FillModedy(const int mode, + Array &outarray) + { + int i; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + Array base0 = m_base[0]->GetDbdata(); + Array base1 = m_base[1]->GetBdata(); + int btmp0 = m_base[0]->GetNumModes(); + int mode0 = mode%btmp0; + int mode1 = mode/btmp0; + + ASSERTL2(mode1 == (int)floor((1.0*mode)/btmp0), + "Integer Truncation not Equiv to Floor"); + + ASSERTL2(m_ncoeffs > mode, + "calling argument mode is larger than total expansion order"); + + for(i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get() + mode0*nquad0), + 1, &outarray[0]+i*nquad0,1); + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode1*nquad1),1, + &outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + + void StdHexExp::v_FillModedz(const int mode, + Array &outarray) + { + int i; + int nquad0 = m_base[0]->GetNumPoints(); + int nquad1 = m_base[1]->GetNumPoints(); + Array base0 = m_base[0]->GetDbdata(); + Array base1 = m_base[1]->GetBdata(); + int btmp0 = m_base[0]->GetNumModes(); + int mode0 = mode%btmp0; + int mode1 = mode/btmp0; + + ASSERTL2(mode1 == (int)floor((1.0*mode)/btmp0), + "Integer Truncation not Equiv to Floor"); + + ASSERTL2(m_ncoeffs > mode, + "calling argument mode is larger than total expansion order"); + + for(i = 0; i < nquad1; ++i) + { + Vmath::Vcopy(nquad0,(NekDouble *)(base0.get() + mode0*nquad0), + 1, &outarray[0]+i*nquad0,1); + } + + for(i = 0; i < nquad0; ++i) + { + Vmath::Vmul(nquad1,(NekDouble *)(base1.get() + mode1*nquad1),1, + &outarray[0]+i,nquad0,&outarray[0]+i,nquad0); + } + } + + int StdHexExp::v_GetNverts() const { return 8; @@ -1234,6 +1510,68 @@ namespace Nektar sort(outarray.get(), outarray.get() + nBndCoeffs); } + NekDouble StdHexExp::v_PhysEvaluatedxBasisBary( + const Array &coords, + int mode) + { + ASSERTL2(coords[0] > -1 - NekConstants::kNekZeroTol, + "coord[0] < -1"); + ASSERTL2(coords[0] < 1 + NekConstants::kNekZeroTol, + "coord[0] > 1"); + ASSERTL2(coords[1] > -1 - NekConstants::kNekZeroTol, + "coord[1] < -1"); + ASSERTL2(coords[1] < 1 + NekConstants::kNekZeroTol, + "coord[1] > 1"); + const int nm0 = m_base[0]->GetNumModes(); + const int nm1 = m_base[1]->GetNumModes(); +