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>
67 namespace 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");
134 TiXmlElement *expansion = expansionTypes->FirstChildElement();
135 std::string expType = expansion->Value();
145 std::vector<unsigned int> composite;
146 std::vector<unsigned int> nummodes;
147 std::vector<std::string> fieldName;
149 const char *nModesStr = expansion->Attribute(
"NUMMODES");
151 "NUMMODES was not defined in EXPANSION section of input");
152 std::string numModesStr = nModesStr;
155 ASSERTL0(valid,
"Unable to correctly parse the number of modes.");
157 if (nummodes.size() == 1)
159 for (
int i = 1; i <
m_dim; i++)
161 nummodes.push_back(nummodes[0]);
165 "Number of modes should match mesh dimension");
167 const char *fStr = expansion->Attribute(
"FIELDS");
170 std::string fieldStr = fStr;
173 ASSERTL0(valid,
"Unable to correctly parse the field string in "
176 for (
int i = 0; i < fieldName.size(); ++i)
188 fieldName.push_back(
"DefaultVar");
195 "Omitting field variables and explicitly listing "
196 "them in different ExpansionTypes is wrong practise");
203 std::string compositeStr = expansion->Attribute(
"COMPOSITE");
205 "COMPOSITE must be specified in expansion definition");
206 int beg = compositeStr.find_first_of(
"[");
207 int end = compositeStr.find_first_of(
"]");
208 std::string compositeListStr =
209 compositeStr.substr(beg + 1, end - beg - 1);
211 compositeListStr.c_str(), composite);
212 ASSERTL0(parseGood && !composite.empty(),
213 (std::string(
"Unable to read composite index range: ") +
218 for (
int i = 0; i < composite.size(); ++i)
220 auto &shapeType =
m_compMap[composite[i]].first;
221 auto &elmtIds =
m_compMap[composite[i]].second;
223 for (
int j = 0; j < fieldName.size(); j++)
225 for (
auto &elid : elmtIds)
233 expansion = expansion->NextSiblingElement(
"E");
236 else if (expType ==
"F")
238 ASSERTL0(expansion->Attribute(
"FILE"),
239 "Attribute FILE expected for type F expansion");
240 std::string filenameStr = expansion->Attribute(
"FILE");
242 "A filename must be specified for the FILE "
243 "attribute of expansion");
254 iofmt, comm,
m_session->GetSharedFilesystem());
257 std::vector<LibUtilities::FieldDefinitionsSharedPtr> fielddefs;
258 f->Import(filenameStr, fielddefs);
261 for (
int i = 0; i < fielddefs.size(); ++i)
264 for (
int j = 0; j < fielddefs[i]->m_fields.size(); ++j)
266 std::string fieldName = fielddefs[i]->m_fields[j];
275 int numHomoDir = fielddefs[i]->m_numHomogeneousDir;
277 for (
int j = 0; j < fielddefs[i]->m_elementIDs.size(); ++j)
279 int elid = fielddefs[i]->m_elementIDs[j];
280 std::vector<unsigned int> nummodes;
281 for (
int k = 0; k <
m_dim; k++)
283 nummodes.push_back(fielddefs[i]->m_numModes[cnt++]);
285 if (fielddefs[i]->m_uniOrder)
293 for (
int k = 0; k < fielddefs[i]->m_fields.size(); k++)
295 std::string fieldName = fielddefs[i]->m_fields[k];
298 m_shape[elid] = fielddefs[i]->m_shapeType;
305 "Expansion type not defined or not supported at the moment");
311 int nElmt = boost::num_vertices(
m_graph);
314 out <<
"# Partition information:" << std::endl;
315 out <<
"# No. elements : " << nElmt << std::endl;
316 out <<
"# No. partitions: " << nPart << std::endl;
317 out <<
"# ID nElmt nLocDof nBndDof" << std::endl;
320 std::vector<int> partElmtCount(nPart, 0);
321 std::vector<int> partLocCount(nPart, 0);
322 std::vector<int> partBndCount(nPart, 0);
324 std::map<int, int> elmtSizes;
325 std::map<int, int> elmtBndSizes;
327 for (std::map<int, NummodesPerField>::iterator expIt =
m_expansions.begin();
330 int elid = expIt->first;
333 for (NummodesPerField::iterator it = npf.begin(); it != npf.end(); ++it)
336 " Number of directional"
337 " modes in expansion spec for element id = " +
338 boost::lexical_cast<std::string>(elid) +
340 boost::lexical_cast<std::string>(it->first) +
341 " does not correspond to mesh dimension");
343 int na = it->second[0];
362 for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
363 vertit != vertit_end; ++vertit)
365 int partId =
m_graph[*vertit].partition;
366 partElmtCount[partId]++;
367 partLocCount[partId] += elmtSizes[
m_graph[*vertit].id];
368 partBndCount[partId] += elmtBndSizes[
m_graph[*vertit].id];
371 for (
int i = 0; i < nPart; ++i)
373 out << i <<
" " << partElmtCount[i] <<
" " << partLocCount[i] <<
" "
374 << partBndCount[i] << std::endl;
380 if (!
m_session->DefinesElement(
"Nektar/Conditions/SolverInfo"))
387 TiXmlElement *solverInfoElement =
388 m_session->GetElement(
"Nektar/Conditions/SolverInfo");
390 TiXmlElement *solverInfo = solverInfoElement->FirstChildElement(
"I");
391 ASSERTL0(solverInfo,
"Cannot read SolverInfo tags");
396 ASSERTL0(solverInfo->Attribute(
"PROPERTY"),
397 "Missing PROPERTY attribute in solver info "
399 std::string solverProperty = solverInfo->Attribute(
"PROPERTY");
401 "Solver info properties must have a non-empty "
404 std::string solverPropertyUpper = boost::to_upper_copy(solverProperty);
407 ASSERTL0(solverInfo->Attribute(
"VALUE"),
408 "Missing VALUE attribute in solver info section. ");
409 std::string solverValue = solverInfo->Attribute(
"VALUE");
411 "Solver info properties must have a non-empty value");
413 std::string propertyValueUpper = boost::to_upper_copy(solverValue);
415 if (solverPropertyUpper ==
"WEIGHTPARTITIONS")
417 if (propertyValueUpper ==
"DOF")
422 else if (propertyValueUpper ==
"BOUNDARY")
427 else if (propertyValueUpper ==
"BOTH")
435 solverInfo = solverInfo->NextSiblingElement(
"I");
456 std::map<int, MeshEntity>::iterator eIt;
464 for (std::map<int, NummodesPerField>::iterator expIt =
m_expansions.begin();
467 int elid = expIt->first;
470 for (NummodesPerField::iterator it = npf.begin(); it != npf.end(); ++it)
473 " Number of directional"
474 " modes in expansion spec for element id = " +
475 boost::lexical_cast<std::string>(elid) +
477 boost::lexical_cast<std::string>(it->first) +
478 " does not correspond to mesh dimension");
480 int na = it->second[0];
513 std::unordered_map<int, std::vector<int>> vGraphEdges;
518 auto vert = boost::add_vertex(
m_graph);
530 for (
auto &eId : elmt.second.list)
534 auto edgeIt = vGraphEdges.find(eId);
535 if (edgeIt != vGraphEdges.end())
537 for (
auto &iId : edgeIt->second)
542 vGraphEdges[eId].push_back(vcnt);
548 vGraphEdges[eId] = Id;
559 auto vert = boost::add_vertex(
m_graph);
560 m_graph[vert].id = ghost.first;
563 for (
auto &facet : ghost.second.list)
565 auto edgeIt = vGraphEdges.find(facet);
566 if (edgeIt != vGraphEdges.end())
568 for (
auto &iId : edgeIt->second)
573 vGraphEdges[facet].push_back(vcnt);
600 int nGraphVerts = boost::num_vertices(
m_graph);
602 int nLocal = nGraphVerts - nGhost;
619 int nWeight = ncon * nLocal;
622 std::vector<int> adjncy_tmp, adjwgt_tmp;
629 for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
630 vertit != vertit_end && vcnt < nLocal; ++vertit)
632 for (boost::tie(adjvertit, adjvertit_end) =
633 boost::adjacent_vertices(*vertit,
m_graph);
634 adjvertit != adjvertit_end; ++adjvertit, ++acnt)
636 adjncy_tmp.push_back(
m_graph[*adjvertit].
id);
639 adjwgt_tmp.push_back(
m_graph[*vertit].edgeWeight[0]);
643 adjwgt_tmp.push_back(1);
654 vwgt[ncon * (vcnt - 1) + ccnt] =
m_graph[*vertit].weight[0];
659 vwgt[ncon * (vcnt - 1) + ccnt] =
678 if (
m_comm->GetColumnComm()->GetRank() == 0)
682 adjwgt, nParts, vol, part);
694 for (i = 1; i <
m_comm->GetColumnComm()->GetSize(); ++i)
696 m_comm->GetColumnComm()->Send(i, part);
702 m_comm->GetColumnComm()->Recv(0, part);
712 m_comm->GetRowComm()->Recv(0, part);
721 for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
722 vertit != vertit_end; ++vertit, ++i)
730 int nproc =
m_comm->GetSize(), rank =
m_comm->GetRank();
731 std::vector<int> numToSend(nproc, 0), numToRecv(nproc);
732 std::map<int, std::vector<int>> procMap;
734 for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
735 vertit != vertit_end && i < nLocal; ++vertit, ++i)
737 int toProc = part[i];
739 procMap[toProc].push_back(
m_graph[*vertit].
id);
742 m_comm->AlltoAll(numToSend, numToRecv);
745 std::vector<int> sendOffsetMap(nproc), recvOffsetMap(nproc);
747 sendOffsetMap[0] = 0;
748 recvOffsetMap[0] = 0;
749 for (
int i = 1; i < nproc; ++i)
751 sendOffsetMap[i] = sendOffsetMap[i - 1] + numToSend[i - 1];
752 recvOffsetMap[i] = recvOffsetMap[i - 1] + numToRecv[i - 1];
756 int totalSend =
Vmath::Vsum(nproc, &numToSend[0], 1);
757 int totalRecv =
Vmath::Vsum(nproc, &numToRecv[0], 1);
759 std::vector<int> sendData(totalSend), recvData(totalRecv);
762 for (
auto &verts : procMap)
764 for (
auto &vert : verts.second)
766 sendData[cnt++] = vert;
771 m_comm->AlltoAllv(sendData, numToSend, sendOffsetMap, recvData,
772 numToRecv, recvOffsetMap);
776 std::unordered_set<int> uniqueIDs;
777 for (
auto &
id : recvData)
779 uniqueIDs.insert(
id);
783 uniqueIDs.begin(), uniqueIDs.end());
791 "parallel execution");
793 for (boost::tie(vertit, vertit_end) = boost::vertices(
m_graph);
794 vertit != vertit_end; ++vertit)
796 for (boost::tie(adjvertit, adjvertit_end) =
797 boost::adjacent_vertices(*vertit,
m_graph);
798 adjvertit != adjvertit_end; ++adjvertit)
800 if (part[*adjvertit] != part[*vertit])
813 unsigned int cnt = 0;
817 for (i = 0; i < nParts; ++i)
819 cnt = std::count(pPart.begin(), pPart.end(), i);
833 for (i = 0; i < pPart.size(); ++i)
835 pPart[i] = i % nParts;
841 std::vector<unsigned int> &elmtid)
853 bool bndWeight,
int na,
int nb,
930 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 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)