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)