40#include <boost/core/ignore_unused.hpp> 
   59#include <boost/algorithm/string.hpp> 
   60#include <boost/format.hpp> 
   61#include <boost/graph/adjacency_iterator.hpp> 
   62#include <boost/graph/adjacency_list.hpp> 
   63#include <boost/graph/detail/edge.hpp> 
   67namespace SpatialDomains
 
   78                             std::map<int, MeshEntity> element,
 
   80    : m_session(session), m_comm(comm), m_dim(meshDim), m_numFields(0),
 
   81      m_elements(element), m_compMap(compMap), m_fieldNameToId(),
 
   82      m_weightingRequired(false), m_weightBnd(false), m_weightDofs(false),
 
   91        if (elIt->second.ghost)
 
  110    boost::ignore_unused(nLocal);
 
  113             "Too few elements for this many processes.");
 
  117             "Parallel partitioning requires shared filesystem.");
 
  131    TiXmlElement *expansionTypes = 
m_session->GetElement(
"Nektar/Expansions");
 
  137    TiXmlElement *expansion = expansionTypes->FirstChildElement();
 
  139    std::string expType = expansion->Value();
 
  149            std::vector<unsigned int> composite;
 
  150            std::vector<unsigned int> nummodes;
 
  151            std::vector<std::string> fieldName;
 
  153            const char *nModesStr = expansion->Attribute(
"NUMMODES");
 
  155                     "NUMMODES was not defined in EXPANSION section of input");
 
  156            std::string numModesStr = nModesStr;
 
  159            ASSERTL0(valid, 
"Unable to correctly parse the number of modes.");
 
  161            if (nummodes.size() == 1)
 
  163                for (
int i = 1; i < 
m_dim; i++)
 
  165                    nummodes.push_back(nummodes[0]);
 
  169                     "Number of modes should match mesh dimension");
 
  171            const char *fStr = expansion->Attribute(
"FIELDS");
 
  174                std::string fieldStr = fStr;
 
  177                ASSERTL0(valid, 
"Unable to correctly parse the field string in " 
  180                for (
int i = 0; i < fieldName.size(); ++i)
 
  192                fieldName.push_back(
"DefaultVar");
 
  199                        "Omitting field variables and explicitly listing " 
  200                        "them in different ExpansionTypes is wrong practise");
 
  207            std::string compositeStr = expansion->Attribute(
"COMPOSITE");
 
  209                     "COMPOSITE must be specified in expansion definition");
 
  210            int beg = compositeStr.find_first_of(
"[");
 
  211            int end = compositeStr.find_first_of(
"]");
 
  212            std::string compositeListStr =
 
  213                compositeStr.substr(beg + 1, end - beg - 1);
 
  215                compositeListStr.c_str(), composite);
 
  216            ASSERTL0(parseGood && !composite.empty(),
 
  217                     (std::string(
"Unable to read composite index range: ") +
 
  222            for (
int i = 0; i < composite.size(); ++i)
 
  224                auto &shapeType = 
m_compMap[composite[i]].first;
 
  225                auto &elmtIds   = 
m_compMap[composite[i]].second;
 
  227                for (
int j = 0; j < fieldName.size(); j++)
 
  229                    for (
auto &elid : elmtIds)
 
  237            expansion = expansion->NextSiblingElement(
"E");
 
  240    else if (expType == 
"F")
 
  242        ASSERTL0(expansion->Attribute(
"FILE"),
 
  243                 "Attribute FILE expected for type F expansion");
 
  244        std::string filenameStr = expansion->Attribute(
"FILE");
 
  246                 "A filename must be specified for the FILE " 
  247                 "attribute of expansion");
 
  258                iofmt, comm, 
m_session->GetSharedFilesystem());
 
  261        std::vector<LibUtilities::FieldDefinitionsSharedPtr> fielddefs;
 
  262        f->Import(filenameStr, fielddefs);
 
  265        for (
int i = 0; i < fielddefs.size(); ++i)
 
  268            for (
int j = 0; j < fielddefs[i]->m_fields.size(); ++j)
 
  270                std::string fieldName = fielddefs[i]->m_fields[j];
 
  279            int numHomoDir = fielddefs[i]->m_numHomogeneousDir;
 
  281            for (
int j = 0; j < fielddefs[i]->m_elementIDs.size(); ++j)
 
  283                int elid = fielddefs[i]->m_elementIDs[j];
 
  284                std::vector<unsigned int> nummodes;
 
  285                for (
int k = 0; k < 
m_dim; k++)
 
  287                    nummodes.push_back(fielddefs[i]->m_numModes[cnt++]);
 
  289                if (fielddefs[i]->m_uniOrder)
 
  297                for (
int k = 0; k < fielddefs[i]->m_fields.size(); k++)
 
  299                    std::string fieldName         = fielddefs[i]->m_fields[k];
 
  302                m_shape[elid] = fielddefs[i]->m_shapeType;
 
  309                 "Expansion type not defined or not supported at the moment");
 
  315    int nElmt = boost::num_vertices(
m_graph);
 
  318    out << 
"# Partition information:" << std::endl;
 
  319    out << 
"# No. elements  : " << nElmt << std::endl;
 
  320    out << 
"# No. partitions: " << nPart << std::endl;
 
  321    out << 
"# ID  nElmt  nLocDof  nBndDof" << std::endl;
 
  324    std::vector<int> partElmtCount(nPart, 0);
 
  325    std::vector<int> partLocCount(nPart, 0);
 
  326    std::vector<int> partBndCount(nPart, 0);
 
  328    std::map<int, int> elmtSizes;
 
  329    std::map<int, int> elmtBndSizes;
 
  331    for (std::map<int, NummodesPerField>::iterator expIt = 
m_expansions.begin();
 
  334        int elid             = expIt->first;
 
  337        for (NummodesPerField::iterator it = npf.begin(); it != npf.end(); ++it)
 
  340                     " Number of directional" 
  341                     " modes in expansion spec for element id = " +
 
  342                         boost::lexical_cast<std::string>(elid) +
 
  344                         boost::lexical_cast<std::string>(it->first) +
 
  345                         " does not correspond to mesh dimension");
 
  347            int na = it->second[0];
 
  366    for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
 
  367         vertit != vertit_end; ++vertit)
 
  369        int partId = 
m_graph[*vertit].partition;
 
  370        partElmtCount[partId]++;
 
  371        partLocCount[partId] += elmtSizes[
m_graph[*vertit].id];
 
  372        partBndCount[partId] += elmtBndSizes[
m_graph[*vertit].id];
 
  375    for (
int i = 0; i < nPart; ++i)
 
  377        out << i << 
" " << partElmtCount[i] << 
" " << partLocCount[i] << 
" " 
  378            << partBndCount[i] << std::endl;
 
  384    if (!
m_session->DefinesElement(
"Nektar/Conditions/SolverInfo"))
 
  391    TiXmlElement *solverInfoElement =
 
  392        m_session->GetElement(
"Nektar/Conditions/SolverInfo");
 
  397    TiXmlElement *solverInfo = solverInfoElement->FirstChildElement(
"I");
 
  398    ASSERTL0(solverInfo, 
"Cannot read SolverInfo tags");
 
  403        ASSERTL0(solverInfo->Attribute(
"PROPERTY"),
 
  404                 "Missing PROPERTY attribute in solver info " 
  406        std::string solverProperty = solverInfo->Attribute(
"PROPERTY");
 
  408                 "Solver info properties must have a non-empty " 
  411        std::string solverPropertyUpper = boost::to_upper_copy(solverProperty);
 
  414        ASSERTL0(solverInfo->Attribute(
"VALUE"),
 
  415                 "Missing VALUE attribute in solver info section. ");
 
  416        std::string solverValue = solverInfo->Attribute(
"VALUE");
 
  418                 "Solver info properties must have a non-empty value");
 
  420        std::string propertyValueUpper = boost::to_upper_copy(solverValue);
 
  422        if (solverPropertyUpper == 
"WEIGHTPARTITIONS")
 
  424            if (propertyValueUpper == 
"DOF")
 
  429            else if (propertyValueUpper == 
"BOUNDARY")
 
  434            else if (propertyValueUpper == 
"BOTH")
 
  442        solverInfo = solverInfo->NextSiblingElement(
"I");
 
  463    std::map<int, MeshEntity>::iterator eIt;
 
  471    for (std::map<int, NummodesPerField>::iterator expIt = 
m_expansions.begin();
 
  474        int elid             = expIt->first;
 
  477        for (NummodesPerField::iterator it = npf.begin(); it != npf.end(); ++it)
 
  480                     " Number of directional" 
  481                     " modes in expansion spec for element id = " +
 
  482                         boost::lexical_cast<std::string>(elid) +
 
  484                         boost::lexical_cast<std::string>(it->first) +
 
  485                         " does not correspond to mesh dimension");
 
  487            int na = it->second[0];
 
  520    std::unordered_map<int, std::vector<int>> vGraphEdges;
 
  525        auto vert               = boost::add_vertex(
m_graph);
 
  537        for (
auto &eId : elmt.second.list)
 
  541            auto edgeIt = vGraphEdges.find(eId);
 
  542            if (edgeIt != vGraphEdges.end())
 
  544                for (
auto &iId : edgeIt->second)
 
  549                vGraphEdges[eId].push_back(vcnt);
 
  555                vGraphEdges[eId] = Id;
 
  566        auto vert               = boost::add_vertex(
m_graph);
 
  567        m_graph[vert].id        = ghost.first;
 
  570        for (
auto &facet : ghost.second.list)
 
  572            auto edgeIt = vGraphEdges.find(facet);
 
  573            if (edgeIt != vGraphEdges.end())
 
  575                for (
auto &iId : edgeIt->second)
 
  580                vGraphEdges[facet].push_back(vcnt);
 
  607    int nGraphVerts = boost::num_vertices(
m_graph);
 
  609    int nLocal      = nGraphVerts - nGhost;
 
  626        int nWeight = ncon * nLocal;
 
  629        std::vector<int> adjncy_tmp, adjwgt_tmp;
 
  636        for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
 
  637             vertit != vertit_end && vcnt < nLocal; ++vertit)
 
  639            for (boost::tie(adjvertit, adjvertit_end) =
 
  640                     boost::adjacent_vertices(*vertit, 
m_graph);
 
  641                 adjvertit != adjvertit_end; ++adjvertit, ++acnt)
 
  643                adjncy_tmp.push_back(
m_graph[*adjvertit].
id);
 
  646                    adjwgt_tmp.push_back(
m_graph[*vertit].edgeWeight[0]);
 
  650                    adjwgt_tmp.push_back(1);
 
  661                    vwgt[ncon * (vcnt - 1) + ccnt] = 
m_graph[*vertit].weight[0];
 
  666                    vwgt[ncon * (vcnt - 1) + ccnt] =
 
  685            if (
m_comm->GetColumnComm()->GetRank() == 0)
 
  689                                     adjwgt, nParts, vol, part);
 
  701                    for (i = 1; i < 
m_comm->GetColumnComm()->GetSize(); ++i)
 
  703                        m_comm->GetColumnComm()->Send(i, part);
 
  709                m_comm->GetColumnComm()->Recv(0, part);
 
  719        m_comm->GetRowComm()->Recv(0, part);
 
  728        for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
 
  729             vertit != vertit_end; ++vertit, ++i)
 
  737        int nproc = 
m_comm->GetSpaceComm()->GetSize(),
 
  738            rank  = 
m_comm->GetSpaceComm()->GetRank();
 
  739        std::vector<int> numToSend(nproc, 0), numToRecv(nproc);
 
  740        std::map<int, std::vector<int>> procMap;
 
  742        for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
 
  743             vertit != vertit_end && i < nLocal; ++vertit, ++i)
 
  745            int toProc = part[i];
 
  747            procMap[toProc].push_back(
m_graph[*vertit].
id);
 
  750        m_comm->GetSpaceComm()->AlltoAll(numToSend, numToRecv);
 
  753        std::vector<int> sendOffsetMap(nproc), recvOffsetMap(nproc);
 
  755        sendOffsetMap[0] = 0;
 
  756        recvOffsetMap[0] = 0;
 
  757        for (
int i = 1; i < nproc; ++i)
 
  759            sendOffsetMap[i] = sendOffsetMap[i - 1] + numToSend[i - 1];
 
  760            recvOffsetMap[i] = recvOffsetMap[i - 1] + numToRecv[i - 1];
 
  764        int totalSend = 
Vmath::Vsum(nproc, &numToSend[0], 1);
 
  765        int totalRecv = 
Vmath::Vsum(nproc, &numToRecv[0], 1);
 
  767        std::vector<int> sendData(totalSend), recvData(totalRecv);
 
  770        for (
auto &verts : procMap)
 
  772            for (
auto &vert : verts.second)
 
  774                sendData[cnt++] = vert;
 
  779        m_comm->GetSpaceComm()->AlltoAllv(sendData, numToSend, sendOffsetMap,
 
  780                                          recvData, numToRecv, recvOffsetMap);
 
  784        std::unordered_set<int> uniqueIDs;
 
  785        for (
auto &
id : recvData)
 
  787            uniqueIDs.insert(
id);
 
  791                                      uniqueIDs.begin(), uniqueIDs.end());
 
  799                              "parallel execution");
 
  801        for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
 
  802             vertit != vertit_end; ++vertit)
 
  804            for (boost::tie(adjvertit, adjvertit_end) =
 
  805                     boost::adjacent_vertices(*vertit, 
m_graph);
 
  806                 adjvertit != adjvertit_end; ++adjvertit)
 
  808                if (part[*adjvertit] != part[*vertit])
 
  821    unsigned int cnt = 0;
 
  825    for (i = 0; i < nParts; ++i)
 
  827        cnt = std::count(pPart.begin(), pPart.end(), i);
 
  841        for (i = 0; i < pPart.size(); ++i)
 
  843            pPart[i] = i % nParts;
 
  849                                  std::vector<unsigned int> &elmtid)
 
  861                                          bool bndWeight, 
int na, 
int nb,
 
  938    int n      = std::max(na, std::max(nb, nc));
 
#define ASSERTL0(condition, msg)
 
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
 
#define SPATIAL_DOMAINS_EXPORT
 
static const std::string GetFileType(const std::string &filename, CommSharedPtr comm)
Determine file type of given input file.
 
Provides a generic Factory class.
 
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
 
static void GetXMLElementTimeLevel(TiXmlElement *&element, const size_t timeLevel, const bool disableCheck=true)
Get XML elment time level (Parallel-in-Time)
 
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
 
static bool GenerateSeqVector(const std::string &str, std::vector< unsigned int > &out)
Takes a comma-separated compressed string and converts it to entries in a vector.
 
boost::graph_traits< BoostGraph >::vertex_iterator BoostVertexIterator
 
virtual void v_PartitionGraphImpl(int &nVerts, int &nVertConds, Nektar::Array< Nektar::OneD, int > &xadj, Nektar::Array< Nektar::OneD, int > &adjcy, Nektar::Array< Nektar::OneD, int > &vertWgt, Nektar::Array< Nektar::OneD, int > &vertSize, Nektar::Array< Nektar::OneD, int > &edgeWgt, int &nparts, int &volume, Nektar::Array< Nektar::OneD, int > &part)=0
 
void PartitionGraph(int nParts, bool overlapping=false)
Partition the graph.
 
std::map< int, NummodesPerField > m_expansions
 
boost::graph_traits< BoostGraph >::adjacency_iterator BoostAdjacencyIterator
 
std::map< int, MultiWeight > m_edgeWeights
 
CompositeDescriptor m_compMap
 
std::map< std::string, int > m_fieldNameToId
 
std::map< int, MeshEntity > m_ghostElmts
 
LibUtilities::SessionReaderSharedPtr m_session
 
std::map< int, MultiWeight > m_vertBndWeights
 
std::map< int, MultiWeight > m_vertWeights
 
void PrintPartInfo(std::ostream &out)
 
void GetElementIDs(const int procid, std::vector< unsigned int > &tmp)
 
boost::graph_traits< BoostGraph >::edge_descriptor BoostEdge
 
std::map< int, std::vector< unsigned int > > m_localPartition
 
int CalculateElementWeight(LibUtilities::ShapeType elmtType, bool bndWeight, int na, int nb, int nc)
 
std::map< std::string, NumModes > NummodesPerField
 
int CalculateEdgeWeight(LibUtilities::ShapeType elmtType, int na, int nb, int nc)
 
void PartitionMesh(int nParts, bool shared=false, bool overlapping=false, int nLocal=0)
 
std::map< int, MeshEntity > m_elements
 
MeshPartition(const LibUtilities::SessionReaderSharedPtr session, LibUtilities::CommSharedPtr comm, int meshDim, std::map< int, MeshEntity > element, CompositeDescriptor compMap)
 
LibUtilities::CommSharedPtr m_comm
 
void CheckPartitions(int nParts, Array< OneD, int > &pPart)
 
std::map< int, LibUtilities::ShapeType > m_shape
 
int getNumberOfCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfCoefficients(int Na, int Nb)
 
int getNumberOfBndCoefficients(int Na, int Nb)
 
int getNumberOfCoefficients(int Na)
 
int getNumberOfBndCoefficients(int Na)
 
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfCoefficients(int Na, int Nb, int Nc)
 
int getNumberOfCoefficients(int Na, int Nb)
 
int getNumberOfBndCoefficients(int Na, int Nb)
 
std::shared_ptr< FieldIO > FieldIOSharedPtr
 
std::shared_ptr< SessionReader > SessionReaderSharedPtr
 
FieldIOFactory & GetFieldIOFactory()
Returns the FieldIO factory.
 
CommFactory & GetCommFactory()
 
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
 
std::map< int, std::pair< LibUtilities::ShapeType, std::vector< int > > > CompositeDescriptor
 
MeshPartitionFactory & GetMeshPartitionFactory()
 
The above copyright notice and this permission notice shall be included.
 
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)