Nektar++
Classes | Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | List of all members
Nektar::SpatialDomains::MeshPartition Class Referenceabstract

#include <MeshPartition.h>

Inheritance diagram for Nektar::SpatialDomains::MeshPartition:
[legend]

Classes

struct  GraphEdgeProperties
 
struct  GraphVertexProperties
 

Public Member Functions

 MeshPartition (const LibUtilities::SessionReaderSharedPtr session, LibUtilities::CommSharedPtr comm, int meshDim, std::map< int, MeshEntity > element, CompositeDescriptor compMap)
 
virtual ~MeshPartition ()
 
void PartitionMesh (int nParts, bool shared=false, bool overlapping=false, int nLocal=0)
 
void PrintPartInfo (std::ostream &out)
 
void GetElementIDs (const int procid, std::vector< unsigned int > &tmp)
 

Protected Types

typedef std::vector< unsigned int > MultiWeight
 
typedef boost::adjacency_list< boost::setS, boost::vecS, boost::undirectedS, GraphVertexProperties, boost::property< boost::edge_index_t, unsigned int, GraphEdgeProperties > > BoostGraph
 
typedef boost::graph_traits< BoostGraph >::vertex_descriptor BoostVertex
 
typedef boost::graph_traits< BoostGraph >::edge_descriptor BoostEdge
 
typedef boost::graph_traits< BoostGraph >::edge_iterator BoostEdgeIterator
 
typedef boost::graph_traits< BoostGraph >::vertex_iterator BoostVertexIterator
 
typedef boost::graph_traits< BoostGraph >::adjacency_iterator BoostAdjacencyIterator
 
typedef std::vector< unsigned int > NumModes
 
typedef std::map< std::string, NumModesNummodesPerField
 

Protected Member Functions

void ReadExpansions ()
 
void ReadConditions ()
 
void WeightElements ()
 
void CreateGraph ()
 
void PartitionGraph (int nParts, bool overlapping=false)
 Partition the graph. More...
 
void CheckPartitions (int nParts, Array< OneD, int > &pPart)
 
int CalculateElementWeight (LibUtilities::ShapeType elmtType, bool bndWeight, int na, int nb, int nc)
 
int CalculateEdgeWeight (LibUtilities::ShapeType elmtType, int na, int nb, int nc)
 
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
 

Protected Attributes

LibUtilities::SessionReaderSharedPtr m_session
 
LibUtilities::CommSharedPtr m_comm
 
int m_dim
 
int m_numFields
 
std::map< int, MeshEntitym_elements
 
std::map< int, MeshEntitym_ghostElmts
 
CompositeDescriptor m_compMap
 
std::map< int, NummodesPerFieldm_expansions
 
std::map< int, LibUtilities::ShapeTypem_shape
 
std::map< std::string, int > m_fieldNameToId
 
std::map< int, MultiWeightm_vertWeights
 
std::map< int, MultiWeightm_vertBndWeights
 
std::map< int, MultiWeightm_edgeWeights
 
BoostGraph m_graph
 
std::map< int, std::vector< unsigned int > > m_localPartition
 
bool m_weightingRequired
 
bool m_weightBnd
 
bool m_weightDofs
 
bool m_shared
 
bool m_parallel
 

Detailed Description

Definition at line 66 of file MeshPartition.h.

Member Typedef Documentation

◆ BoostAdjacencyIterator

typedef boost::graph_traits<BoostGraph>::adjacency_iterator Nektar::SpatialDomains::MeshPartition::BoostAdjacencyIterator
protected

Definition at line 118 of file MeshPartition.h.

◆ BoostEdge

typedef boost::graph_traits<BoostGraph>::edge_descriptor Nektar::SpatialDomains::MeshPartition::BoostEdge
protected

Definition at line 113 of file MeshPartition.h.

◆ BoostEdgeIterator

typedef boost::graph_traits<BoostGraph>::edge_iterator Nektar::SpatialDomains::MeshPartition::BoostEdgeIterator
protected

Definition at line 114 of file MeshPartition.h.

◆ BoostGraph

typedef boost::adjacency_list< boost::setS, boost::vecS, boost::undirectedS, GraphVertexProperties, boost::property<boost::edge_index_t, unsigned int, GraphEdgeProperties> > Nektar::SpatialDomains::MeshPartition::BoostGraph
protected

Definition at line 110 of file MeshPartition.h.

◆ BoostVertex

typedef boost::graph_traits<BoostGraph>::vertex_descriptor Nektar::SpatialDomains::MeshPartition::BoostVertex
protected

Definition at line 112 of file MeshPartition.h.

◆ BoostVertexIterator

typedef boost::graph_traits<BoostGraph>::vertex_iterator Nektar::SpatialDomains::MeshPartition::BoostVertexIterator
protected

Definition at line 116 of file MeshPartition.h.

◆ MultiWeight

typedef std::vector<unsigned int> Nektar::SpatialDomains::MeshPartition::MultiWeight
protected

Definition at line 86 of file MeshPartition.h.

◆ NumModes

typedef std::vector<unsigned int> Nektar::SpatialDomains::MeshPartition::NumModes
protected

Definition at line 120 of file MeshPartition.h.

◆ NummodesPerField

typedef std::map<std::string, NumModes> Nektar::SpatialDomains::MeshPartition::NummodesPerField
protected

Definition at line 121 of file MeshPartition.h.

Constructor & Destructor Documentation

◆ MeshPartition()

Nektar::SpatialDomains::MeshPartition::MeshPartition ( const LibUtilities::SessionReaderSharedPtr  session,
LibUtilities::CommSharedPtr  comm,
int  meshDim,
std::map< int, MeshEntity element,
CompositeDescriptor  compMap 
)

Definition at line 76 of file MeshPartition.cpp.

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),
83  m_parallel(false)
84 {
85  // leave the meshpartition method of reading expansions and conditions
88 
89  for (auto elIt = m_elements.cbegin(); elIt != m_elements.cend();)
90  {
91  if (elIt->second.ghost)
92  {
93  m_ghostElmts[elIt->first] = elIt->second;
94  elIt = m_elements.erase(elIt);
95  }
96  else
97  {
98  ++elIt;
99  }
100  }
101 }
std::map< std::string, int > m_fieldNameToId
std::map< int, MeshEntity > m_ghostElmts
LibUtilities::SessionReaderSharedPtr m_session
std::map< int, MeshEntity > m_elements
LibUtilities::CommSharedPtr m_comm

References m_elements, m_ghostElmts, ReadConditions(), and ReadExpansions().

◆ ~MeshPartition()

Nektar::SpatialDomains::MeshPartition::~MeshPartition ( )
virtual

Definition at line 103 of file MeshPartition.cpp.

104 {
105 }

Member Function Documentation

◆ CalculateEdgeWeight()

int Nektar::SpatialDomains::MeshPartition::CalculateEdgeWeight ( LibUtilities::ShapeType  elmtType,
int  na,
int  nb,
int  nc 
)
protected

Calculate the number of modes needed for communication when in partition boundary, to be used as weighting for edges. Since we do not know exactly which face this refers to, assume the max order and quad face (for prisms) as arbitrary choices

Definition at line 926 of file MeshPartition.cpp.

928 {
929  int weight = 0;
930  int n = std::max(na, std::max(nb, nc));
931  switch (elmtType)
932  {
935  break;
938  break;
941  break;
944  break;
947  weight = n;
948  break;
950  weight = 1;
951  break;
952  default:
953  break;
954  }
955 
956  return weight;
957 }
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:138
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:114

References Nektar::LibUtilities::eHexahedron, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, Nektar::LibUtilities::StdTriData::getNumberOfCoefficients(), and Nektar::LibUtilities::StdQuadData::getNumberOfCoefficients().

Referenced by WeightElements().

◆ CalculateElementWeight()

int Nektar::SpatialDomains::MeshPartition::CalculateElementWeight ( LibUtilities::ShapeType  elmtType,
bool  bndWeight,
int  na,
int  nb,
int  nc 
)
protected

Definition at line 852 of file MeshPartition.cpp.

855 {
856  int weight = 0;
857 
858  switch (elmtType)
859  {
861  weight = bndWeight
863  na, nb, nc)
864  : LibUtilities::StdTetData::getNumberOfCoefficients(
865  na, nb, nc);
866  break;
868  weight =
869  bndWeight
871  na, nb, nc)
872  : LibUtilities::StdPrismData::getNumberOfCoefficients(
873  na, nb, nc);
874  break;
876  weight = bndWeight
878  na, nb, nc)
879  : LibUtilities::StdHexData::getNumberOfCoefficients(
880  na, nb, nc);
881  break;
883  weight = bndWeight
885  na, nb, nc)
886  : LibUtilities::StdPyrData::getNumberOfCoefficients(
887  na, nb, nc);
888  break;
890  weight =
891  bndWeight
893  nb)
894  : LibUtilities::StdQuadData::getNumberOfCoefficients(na,
895  nb);
896  break;
898  weight =
899  bndWeight
901  nb)
902  : LibUtilities::StdTriData::getNumberOfCoefficients(na, nb);
903  break;
905  weight =
906  bndWeight
908  : LibUtilities::StdSegData::getNumberOfCoefficients(na);
909  break;
911  weight = 1;
912  break;
913  default:
914  break;
915  }
916 
917  return weight;
918 }
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:166
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:295
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:264
int getNumberOfBndCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:148
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:215
int getNumberOfBndCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:126

References Nektar::LibUtilities::eHexahedron, Nektar::LibUtilities::ePoint, Nektar::LibUtilities::ePrism, Nektar::LibUtilities::ePyramid, Nektar::LibUtilities::eQuadrilateral, Nektar::LibUtilities::eSegment, Nektar::LibUtilities::eTetrahedron, Nektar::LibUtilities::eTriangle, Nektar::LibUtilities::StdSegData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdTriData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdQuadData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdHexData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdTetData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdPyrData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdPrismData::getNumberOfBndCoefficients(), Nektar::LibUtilities::StdSegData::getNumberOfCoefficients(), Nektar::LibUtilities::StdTriData::getNumberOfCoefficients(), Nektar::LibUtilities::StdQuadData::getNumberOfCoefficients(), Nektar::LibUtilities::StdHexData::getNumberOfCoefficients(), Nektar::LibUtilities::StdTetData::getNumberOfCoefficients(), Nektar::LibUtilities::StdPyrData::getNumberOfCoefficients(), and Nektar::LibUtilities::StdPrismData::getNumberOfCoefficients().

Referenced by PrintPartInfo(), and WeightElements().

◆ CheckPartitions()

void Nektar::SpatialDomains::MeshPartition::CheckPartitions ( int  nParts,
Array< OneD, int > &  pPart 
)
protected

Definition at line 810 of file MeshPartition.cpp.

811 {
812  unsigned int i = 0;
813  unsigned int cnt = 0;
814  bool valid = true;
815 
816  // Check that every process has at least one element assigned
817  for (i = 0; i < nParts; ++i)
818  {
819  cnt = std::count(pPart.begin(), pPart.end(), i);
820  if (cnt == 0)
821  {
822  valid = false;
823  }
824  }
825 
826  // If the graph partitioner produced an invalid partition, repartition
827  // naively. Elements are assigned to processes in a round-robin fashion.
828  // It is assumed that graph partitioner failure only occurs when the number
829  // of elements is approx. the number of processes, so this approach should
830  // not be too inefficient communication-wise.
831  if (!valid)
832  {
833  for (i = 0; i < pPart.size(); ++i)
834  {
835  pPart[i] = i % nParts;
836  }
837  }
838 }

Referenced by PartitionGraph().

◆ CreateGraph()

void Nektar::SpatialDomains::MeshPartition::CreateGraph ( )
protected

Definition at line 509 of file MeshPartition.cpp.

510 {
511  // Maps edge/face to first mesh element id.
512  // On locating second mesh element id, graph edge is created instead.
513  std::unordered_map<int, std::vector<int>> vGraphEdges;
514  int vcnt = 0;
515 
516  for (auto &elmt : m_elements)
517  {
518  auto vert = boost::add_vertex(m_graph);
519  m_graph[vert].id = elmt.first;
520  m_graph[vert].partition = 0;
521 
523  {
524  m_graph[vert].weight = m_vertWeights[elmt.second.origId];
525  m_graph[vert].bndWeight = m_vertBndWeights[elmt.second.origId];
526  m_graph[vert].edgeWeight = m_edgeWeights[elmt.second.origId];
527  }
528 
529  // Process element entries and add graph edges
530  for (auto &eId : elmt.second.list)
531  {
532  // Look to see if we've examined this edge/face before
533  // If so, we've got both graph vertices so add edge
534  auto edgeIt = vGraphEdges.find(eId);
535  if (edgeIt != vGraphEdges.end())
536  {
537  for (auto &iId : edgeIt->second)
538  {
539  BoostEdge e = boost::add_edge(vcnt, iId, m_graph).first;
540  m_graph[e].id = vcnt;
541  }
542  vGraphEdges[eId].push_back(vcnt);
543  }
544  else
545  {
546  std::vector<int> Id;
547  Id.push_back(vcnt);
548  vGraphEdges[eId] = Id;
549  }
550  }
551 
552  // Increment counter for graph vertex id.
553  ++vcnt;
554  }
555 
556  // Now process ghost elements.
557  for (auto &ghost : m_ghostElmts)
558  {
559  auto vert = boost::add_vertex(m_graph);
560  m_graph[vert].id = ghost.first;
561  m_graph[vert].partition = -1;
562 
563  for (auto &facet : ghost.second.list)
564  {
565  auto edgeIt = vGraphEdges.find(facet);
566  if (edgeIt != vGraphEdges.end())
567  {
568  for (auto &iId : edgeIt->second)
569  {
570  BoostEdge e = boost::add_edge(vcnt, iId, m_graph).first;
571  m_graph[e].id = vcnt;
572  }
573  vGraphEdges[facet].push_back(vcnt);
574  }
575  }
576 
577  // Increment counter for graph vertex id.
578  ++vcnt;
579  }
580 }
std::map< int, MultiWeight > m_edgeWeights
std::map< int, MultiWeight > m_vertBndWeights
std::map< int, MultiWeight > m_vertWeights
boost::graph_traits< BoostGraph >::edge_descriptor BoostEdge

References m_edgeWeights, m_elements, m_ghostElmts, m_graph, m_vertBndWeights, m_vertWeights, and m_weightingRequired.

Referenced by PartitionMesh().

◆ GetElementIDs()

void Nektar::SpatialDomains::MeshPartition::GetElementIDs ( const int  procid,
std::vector< unsigned int > &  tmp 
)

Definition at line 840 of file MeshPartition.cpp.

842 {
843  BoostVertexIterator vertit, vertit_end;
844 
845  auto it = m_localPartition.find(procid);
846 
847  ASSERTL0(it != m_localPartition.end(), "Unable to find local partition");
848 
849  elmtid = m_localPartition[procid];
850 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
boost::graph_traits< BoostGraph >::vertex_iterator BoostVertexIterator
std::map< int, std::vector< unsigned int > > m_localPartition

References ASSERTL0, and m_localPartition.

◆ PartitionGraph()

void Nektar::SpatialDomains::MeshPartition::PartitionGraph ( int  nParts,
bool  overlapping = false 
)
protected

Partition the graph.

This routine partitions the graph pGraph into nParts, producing subgraphs that are populated in pLocalPartition. If the overlapping option is set (which is used for post-processing purposes), the resulting partitions are extended to cover neighbouring elements by additional vertex on the dual graph, which produces overlapping partitions (i.e. the intersection of two connected partitions is non-empty).

Parameters
nPartsNumber of partitions.
pLocalPartitionVector of sub-graphs representing each
overlappingTrue if resulting partitions should overlap.

Definition at line 597 of file MeshPartition.cpp.

598 {
599  int i;
600  int nGraphVerts = boost::num_vertices(m_graph);
601  int nGhost = m_ghostElmts.size();
602  int nLocal = nGraphVerts - nGhost;
603 
604  int ncon = 1;
605  if (m_weightDofs && m_weightBnd)
606  {
607  ncon = 2;
608  }
609 
610  // Convert boost graph into CSR format
611  BoostVertexIterator vertit, vertit_end;
612  BoostAdjacencyIterator adjvertit, adjvertit_end;
613  Array<OneD, int> part(nGraphVerts, 0);
614 
615  if (m_comm->GetRowComm()->TreatAsRankZero() || m_parallel)
616  {
617  int acnt = 0;
618  int vcnt = 0;
619  int nWeight = ncon * nLocal;
620 
621  Array<OneD, int> xadj(nLocal + 1);
622  std::vector<int> adjncy_tmp, adjwgt_tmp;
623  Array<OneD, int> vwgt(nWeight, 1);
624  Array<OneD, int> vsize(nLocal, 1);
625 
626  // Initialise starting point of adjacency array.
627  xadj[0] = 0;
628 
629  for (boost::tie(vertit, vertit_end) = boost::vertices(m_graph);
630  vertit != vertit_end && vcnt < nLocal; ++vertit)
631  {
632  for (boost::tie(adjvertit, adjvertit_end) =
633  boost::adjacent_vertices(*vertit, m_graph);
634  adjvertit != adjvertit_end; ++adjvertit, ++acnt)
635  {
636  adjncy_tmp.push_back(m_graph[*adjvertit].id);
638  {
639  adjwgt_tmp.push_back(m_graph[*vertit].edgeWeight[0]);
640  }
641  else
642  {
643  adjwgt_tmp.push_back(1);
644  }
645  }
646 
647  xadj[++vcnt] = acnt;
648 
650  {
651  int ccnt = 0;
652  if (m_weightDofs)
653  {
654  vwgt[ncon * (vcnt - 1) + ccnt] = m_graph[*vertit].weight[0];
655  ccnt++;
656  }
657  if (m_weightBnd)
658  {
659  vwgt[ncon * (vcnt - 1) + ccnt] =
660  m_graph[*vertit].bndWeight[0];
661  }
662  }
663  }
664 
665  Array<OneD, int> adjncy(adjncy_tmp.size(), &adjncy_tmp[0]);
666  Array<OneD, int> adjwgt(adjwgt_tmp.size(), &adjwgt_tmp[0]);
667 
668  // Call partitioner to partition graph
669  int vol = 0;
670 
671  try
672  {
673  //////////////////////////////////////////////////////
674  // On a cartesian communicator do mesh partiotion just on the first
675  // column
676  // so there is no doubt the partitions are all the same in all the
677  // columns
678  if (m_comm->GetColumnComm()->GetRank() == 0)
679  {
680  // Attempt partitioning.
681  v_PartitionGraphImpl(nLocal, ncon, xadj, adjncy, vwgt, vsize,
682  adjwgt, nParts, vol, part);
683 
684  // Check the partitioner produced a valid partition and fix if
685  // not.
686  if (!m_parallel)
687  {
688  CheckPartitions(nParts, part);
689  }
690 
691  if (!m_shared)
692  {
693  // distribute among columns
694  for (i = 1; i < m_comm->GetColumnComm()->GetSize(); ++i)
695  {
696  m_comm->GetColumnComm()->Send(i, part);
697  }
698  }
699  }
700  else
701  {
702  m_comm->GetColumnComm()->Recv(0, part);
703  }
704  }
705  catch (...)
706  {
707  NEKERROR(ErrorUtil::efatal, "Error in calling graph partitioner.");
708  }
709  }
710  else if (!m_parallel)
711  {
712  m_comm->GetRowComm()->Recv(0, part);
713  }
714 
715  // Create storage for this (and possibly other) process's partitions.
716  i = 0;
717 
718  if (!m_parallel)
719  {
720  // Populate subgraph(s) for each rank.
721  for (boost::tie(vertit, vertit_end) = boost::vertices(m_graph);
722  vertit != vertit_end; ++vertit, ++i)
723  {
724  m_localPartition[part[i]].push_back(m_graph[*vertit].id);
725  }
726  }
727  else
728  {
729  // Figure out how many vertices we're going to get from each processor.
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;
733 
734  for (boost::tie(vertit, vertit_end) = boost::vertices(m_graph);
735  vertit != vertit_end && i < nLocal; ++vertit, ++i)
736  {
737  int toProc = part[i];
738  numToSend[toProc]++;
739  procMap[toProc].push_back(m_graph[*vertit].id);
740  }
741 
742  m_comm->AlltoAll(numToSend, numToRecv);
743 
744  // Build offsets for all-to-all communication
745  std::vector<int> sendOffsetMap(nproc), recvOffsetMap(nproc);
746 
747  sendOffsetMap[0] = 0;
748  recvOffsetMap[0] = 0;
749  for (int i = 1; i < nproc; ++i)
750  {
751  sendOffsetMap[i] = sendOffsetMap[i - 1] + numToSend[i - 1];
752  recvOffsetMap[i] = recvOffsetMap[i - 1] + numToRecv[i - 1];
753  }
754 
755  // Build data to send
756  int totalSend = Vmath::Vsum(nproc, &numToSend[0], 1);
757  int totalRecv = Vmath::Vsum(nproc, &numToRecv[0], 1);
758 
759  std::vector<int> sendData(totalSend), recvData(totalRecv);
760 
761  int cnt = 0;
762  for (auto &verts : procMap)
763  {
764  for (auto &vert : verts.second)
765  {
766  sendData[cnt++] = vert;
767  }
768  }
769 
770  // Send ID map to processors
771  m_comm->AlltoAllv(sendData, numToSend, sendOffsetMap, recvData,
772  numToRecv, recvOffsetMap);
773 
774  // Finally, populate m_localPartition for this processor. Could contain
775  // duplicates so erase those first.
776  std::unordered_set<int> uniqueIDs;
777  for (auto &id : recvData)
778  {
779  uniqueIDs.insert(id);
780  }
781 
782  m_localPartition[rank].insert(m_localPartition[rank].begin(),
783  uniqueIDs.begin(), uniqueIDs.end());
784  }
785 
786  // If the overlapping option is set (for post-processing purposes),
787  // add vertices that correspond to the neighbouring elements.
788  if (overlapping)
789  {
790  ASSERTL0(!m_parallel, "Overlapping partitioning not supported in "
791  "parallel execution");
792 
793  for (boost::tie(vertit, vertit_end) = boost::vertices(m_graph);
794  vertit != vertit_end; ++vertit)
795  {
796  for (boost::tie(adjvertit, adjvertit_end) =
797  boost::adjacent_vertices(*vertit, m_graph);
798  adjvertit != adjvertit_end; ++adjvertit)
799  {
800  if (part[*adjvertit] != part[*vertit])
801  {
802  m_localPartition[part[*vertit]].push_back(
803  m_graph[*adjvertit].id);
804  }
805  }
806  }
807  }
808 }
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
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
boost::graph_traits< BoostGraph >::adjacency_iterator BoostAdjacencyIterator
void CheckPartitions(int nParts, Array< OneD, int > &pPart)
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:895

References ASSERTL0, CheckPartitions(), Nektar::ErrorUtil::efatal, m_comm, m_ghostElmts, m_graph, m_localPartition, m_parallel, m_shared, m_weightBnd, m_weightDofs, m_weightingRequired, NEKERROR, v_PartitionGraphImpl(), and Vmath::Vsum().

Referenced by PartitionMesh().

◆ PartitionMesh()

void Nektar::SpatialDomains::MeshPartition::PartitionMesh ( int  nParts,
bool  shared = false,
bool  overlapping = false,
int  nLocal = 0 
)

Definition at line 107 of file MeshPartition.cpp.

109 {
110  boost::ignore_unused(nLocal);
111 
112  ASSERTL0(m_parallel || m_elements.size() >= nParts,
113  "Too few elements for this many processes.");
114  m_shared = shared;
115 
116  ASSERTL0(!m_parallel || shared,
117  "Parallel partitioning requires shared filesystem.");
118 
120  {
121  WeightElements();
122  }
123  CreateGraph();
124 
125  PartitionGraph(nParts, overlapping);
126 }
void PartitionGraph(int nParts, bool overlapping=false)
Partition the graph.

References ASSERTL0, CreateGraph(), m_elements, m_parallel, m_shared, m_weightingRequired, PartitionGraph(), and WeightElements().

◆ PrintPartInfo()

void Nektar::SpatialDomains::MeshPartition::PrintPartInfo ( std::ostream &  out)

Definition at line 309 of file MeshPartition.cpp.

310 {
311  int nElmt = boost::num_vertices(m_graph);
312  int nPart = m_localPartition.size();
313 
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;
318 
319  BoostVertexIterator vertit, vertit_end;
320  std::vector<int> partElmtCount(nPart, 0);
321  std::vector<int> partLocCount(nPart, 0);
322  std::vector<int> partBndCount(nPart, 0);
323 
324  std::map<int, int> elmtSizes;
325  std::map<int, int> elmtBndSizes;
326 
327  for (std::map<int, NummodesPerField>::iterator expIt = m_expansions.begin();
328  expIt != m_expansions.end(); ++expIt)
329  {
330  int elid = expIt->first;
331  NummodesPerField npf = expIt->second;
332 
333  for (NummodesPerField::iterator it = npf.begin(); it != npf.end(); ++it)
334  {
335  ASSERTL0(it->second.size() == m_dim,
336  " Number of directional"
337  " modes in expansion spec for element id = " +
338  boost::lexical_cast<std::string>(elid) +
339  " and field " +
340  boost::lexical_cast<std::string>(it->first) +
341  " does not correspond to mesh dimension");
342 
343  int na = it->second[0];
344  int nb = 0;
345  int nc = 0;
346  if (m_dim >= 2)
347  {
348  nb = it->second[1];
349  }
350  if (m_dim == 3)
351  {
352  nc = it->second[2];
353  }
354 
355  elmtSizes[elid] =
356  CalculateElementWeight(m_shape[elid], false, na, nb, nc);
357  elmtBndSizes[elid] =
358  CalculateElementWeight(m_shape[elid], true, na, nb, nc);
359  }
360  }
361 
362  for (boost::tie(vertit, vertit_end) = boost::vertices(m_graph);
363  vertit != vertit_end; ++vertit)
364  {
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];
369  }
370 
371  for (int i = 0; i < nPart; ++i)
372  {
373  out << i << " " << partElmtCount[i] << " " << partLocCount[i] << " "
374  << partBndCount[i] << std::endl;
375  }
376 }
std::map< int, NummodesPerField > m_expansions
int CalculateElementWeight(LibUtilities::ShapeType elmtType, bool bndWeight, int na, int nb, int nc)
std::map< std::string, NumModes > NummodesPerField
std::map< int, LibUtilities::ShapeType > m_shape

References ASSERTL0, CalculateElementWeight(), m_dim, m_expansions, m_graph, m_localPartition, and m_shape.

◆ ReadConditions()

void Nektar::SpatialDomains::MeshPartition::ReadConditions ( )
protected

Definition at line 378 of file MeshPartition.cpp.

379 {
380  if (!m_session->DefinesElement("Nektar/Conditions/SolverInfo"))
381  {
382  // No SolverInfo = no change of default action to weight
383  // mesh graph.
384  return;
385  }
386 
387  TiXmlElement *solverInfoElement =
388  m_session->GetElement("Nektar/Conditions/SolverInfo");
389 
390  TiXmlElement *solverInfo = solverInfoElement->FirstChildElement("I");
391  ASSERTL0(solverInfo, "Cannot read SolverInfo tags");
392 
393  while (solverInfo)
394  {
395  // read the property name
396  ASSERTL0(solverInfo->Attribute("PROPERTY"),
397  "Missing PROPERTY attribute in solver info "
398  "section. ");
399  std::string solverProperty = solverInfo->Attribute("PROPERTY");
400  ASSERTL0(!solverProperty.empty(),
401  "Solver info properties must have a non-empty "
402  "name. ");
403  // make sure that solver property is capitalised
404  std::string solverPropertyUpper = boost::to_upper_copy(solverProperty);
405 
406  // read the value
407  ASSERTL0(solverInfo->Attribute("VALUE"),
408  "Missing VALUE attribute in solver info section. ");
409  std::string solverValue = solverInfo->Attribute("VALUE");
410  ASSERTL0(!solverValue.empty(),
411  "Solver info properties must have a non-empty value");
412  // make sure that property value is capitalised
413  std::string propertyValueUpper = boost::to_upper_copy(solverValue);
414 
415  if (solverPropertyUpper == "WEIGHTPARTITIONS")
416  {
417  if (propertyValueUpper == "DOF")
418  {
419  m_weightingRequired = true;
420  m_weightDofs = true;
421  }
422  else if (propertyValueUpper == "BOUNDARY")
423  {
424  m_weightingRequired = true;
425  m_weightBnd = true;
426  }
427  else if (propertyValueUpper == "BOTH")
428  {
429  m_weightingRequired = true;
430  m_weightDofs = true;
431  m_weightBnd = true;
432  }
433  return;
434  }
435  solverInfo = solverInfo->NextSiblingElement("I");
436  }
437 }

References ASSERTL0, m_session, m_weightBnd, m_weightDofs, and m_weightingRequired.

Referenced by MeshPartition().

◆ ReadExpansions()

void Nektar::SpatialDomains::MeshPartition::ReadExpansions ( )
protected

Definition at line 128 of file MeshPartition.cpp.

129 {
130  // Find the Expansions tag
131  TiXmlElement *expansionTypes = m_session->GetElement("Nektar/Expansions");
132 
133  // Find the Expansion type
134  TiXmlElement *expansion = expansionTypes->FirstChildElement();
135  std::string expType = expansion->Value();
136 
137  // Expansiontypes will contain plenty of data, where relevant at this stage
138  // are composite ID(s) that this expansion type describes, nummodes and a
139  // list of fields that this expansion relates to. If this does not exist the
140  // variable is only set to "DefaultVar".
141  if (expType == "E")
142  {
143  while (expansion)
144  {
145  std::vector<unsigned int> composite;
146  std::vector<unsigned int> nummodes;
147  std::vector<std::string> fieldName;
148 
149  const char *nModesStr = expansion->Attribute("NUMMODES");
150  ASSERTL0(nModesStr,
151  "NUMMODES was not defined in EXPANSION section of input");
152  std::string numModesStr = nModesStr;
153  bool valid =
154  ParseUtils::GenerateVector(numModesStr.c_str(), nummodes);
155  ASSERTL0(valid, "Unable to correctly parse the number of modes.");
156 
157  if (nummodes.size() == 1)
158  {
159  for (int i = 1; i < m_dim; i++)
160  {
161  nummodes.push_back(nummodes[0]);
162  }
163  }
164  ASSERTL0(nummodes.size() == m_dim,
165  "Number of modes should match mesh dimension");
166 
167  const char *fStr = expansion->Attribute("FIELDS");
168  if (fStr)
169  {
170  std::string fieldStr = fStr;
171  bool valid =
172  ParseUtils::GenerateVector(fieldStr.c_str(), fieldName);
173  ASSERTL0(valid, "Unable to correctly parse the field string in "
174  "ExpansionTypes.");
175 
176  for (int i = 0; i < fieldName.size(); ++i)
177  {
178  if (m_fieldNameToId.count(fieldName[i]) == 0)
179  {
180  int k = m_fieldNameToId.size();
181  m_fieldNameToId[fieldName[i]] = k;
182  m_numFields++;
183  }
184  }
185  }
186  else
187  {
188  fieldName.push_back("DefaultVar");
189  int k = m_fieldNameToId.size();
190 
191  if (m_fieldNameToId.count("DefaultVar") == 0)
192  {
193  ASSERTL0(
194  k == 0,
195  "Omitting field variables and explicitly listing "
196  "them in different ExpansionTypes is wrong practise");
197 
198  m_fieldNameToId["DefaultVar"] = k;
199  m_numFields++;
200  }
201  }
202 
203  std::string compositeStr = expansion->Attribute("COMPOSITE");
204  ASSERTL0(compositeStr.length() > 3,
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);
210  bool parseGood = ParseUtils::GenerateSeqVector(
211  compositeListStr.c_str(), composite);
212  ASSERTL0(parseGood && !composite.empty(),
213  (std::string("Unable to read composite index range: ") +
214  compositeListStr)
215  .c_str());
216 
217  // construct mapping (elmt id, field name) -> nummodes
218  for (int i = 0; i < composite.size(); ++i)
219  {
220  auto &shapeType = m_compMap[composite[i]].first;
221  auto &elmtIds = m_compMap[composite[i]].second;
222 
223  for (int j = 0; j < fieldName.size(); j++)
224  {
225  for (auto &elid : elmtIds)
226  {
227  m_expansions[elid][fieldName[j]] = nummodes;
228  m_shape[elid] = shapeType;
229  }
230  }
231  }
232 
233  expansion = expansion->NextSiblingElement("E");
234  }
235  }
236  else if (expType == "F")
237  {
238  ASSERTL0(expansion->Attribute("FILE"),
239  "Attribute FILE expected for type F expansion");
240  std::string filenameStr = expansion->Attribute("FILE");
241  ASSERTL0(!filenameStr.empty(),
242  "A filename must be specified for the FILE "
243  "attribute of expansion");
244 
245  // Create fieldIO object to load file
246  // need a serial communicator to avoid problems with
247  // shared file system
250  std::string iofmt =
251  LibUtilities::FieldIO::GetFileType(filenameStr, comm);
254  iofmt, comm, m_session->GetSharedFilesystem());
255 
256  // Load field definitions from file
257  std::vector<LibUtilities::FieldDefinitionsSharedPtr> fielddefs;
258  f->Import(filenameStr, fielddefs);
259 
260  // Parse field definitions
261  for (int i = 0; i < fielddefs.size(); ++i)
262  {
263  // Name of fields
264  for (int j = 0; j < fielddefs[i]->m_fields.size(); ++j)
265  {
266  std::string fieldName = fielddefs[i]->m_fields[j];
267  if (m_fieldNameToId.count(fieldName) == 0)
268  {
269  int k = m_fieldNameToId.size();
270  m_fieldNameToId[fieldName] = k;
271  m_numFields++;
272  }
273  }
274  // Number of modes and shape for each element
275  int numHomoDir = fielddefs[i]->m_numHomogeneousDir;
276  int cnt = 0;
277  for (int j = 0; j < fielddefs[i]->m_elementIDs.size(); ++j)
278  {
279  int elid = fielddefs[i]->m_elementIDs[j];
280  std::vector<unsigned int> nummodes;
281  for (int k = 0; k < m_dim; k++)
282  {
283  nummodes.push_back(fielddefs[i]->m_numModes[cnt++]);
284  }
285  if (fielddefs[i]->m_uniOrder)
286  {
287  cnt = 0;
288  }
289  else
290  {
291  cnt += numHomoDir;
292  }
293  for (int k = 0; k < fielddefs[i]->m_fields.size(); k++)
294  {
295  std::string fieldName = fielddefs[i]->m_fields[k];
296  m_expansions[elid][fieldName] = nummodes;
297  }
298  m_shape[elid] = fielddefs[i]->m_shapeType;
299  }
300  }
301  }
302  else
303  {
304  ASSERTL0(false,
305  "Expansion type not defined or not supported at the moment");
306  }
307 }
static const std::string GetFileType(const std::string &filename, CommSharedPtr comm)
Determine file type of given input file.
Definition: FieldIO.cpp:97
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
Definition: ParseUtils.cpp:131
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.
Definition: ParseUtils.cpp:105
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:327
FieldIOFactory & GetFieldIOFactory()
Returns the FieldIO factory.
Definition: FieldIO.cpp:72
CommFactory & GetCommFactory()
std::shared_ptr< Comm > CommSharedPtr
Pointer to a Communicator object.
Definition: Comm.h:54

References ASSERTL0, Nektar::LibUtilities::NekFactory< tKey, tBase, tParam >::CreateInstance(), Nektar::ParseUtils::GenerateSeqVector(), Nektar::ParseUtils::GenerateVector(), Nektar::LibUtilities::GetCommFactory(), Nektar::LibUtilities::GetFieldIOFactory(), Nektar::LibUtilities::FieldIO::GetFileType(), m_compMap, m_dim, m_expansions, m_fieldNameToId, m_numFields, m_session, and m_shape.

Referenced by MeshPartition().

◆ v_PartitionGraphImpl()

virtual void Nektar::SpatialDomains::MeshPartition::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 
)
protectedpure virtual

◆ WeightElements()

void Nektar::SpatialDomains::MeshPartition::WeightElements ( )
protected

Definition at line 453 of file MeshPartition.cpp.

454 {
455  std::vector<unsigned int> weight(m_numFields, 1);
456  std::map<int, MeshEntity>::iterator eIt;
457  for (eIt = m_elements.begin(); eIt != m_elements.end(); ++eIt)
458  {
459  m_vertWeights[eIt->second.origId] = weight;
460  m_vertBndWeights[eIt->second.origId] = weight;
461  m_edgeWeights[eIt->second.origId] = weight;
462  }
463 
464  for (std::map<int, NummodesPerField>::iterator expIt = m_expansions.begin();
465  expIt != m_expansions.end(); ++expIt)
466  {
467  int elid = expIt->first;
468  NummodesPerField npf = expIt->second;
469 
470  for (NummodesPerField::iterator it = npf.begin(); it != npf.end(); ++it)
471  {
472  ASSERTL0(it->second.size() == m_dim,
473  " Number of directional"
474  " modes in expansion spec for element id = " +
475  boost::lexical_cast<std::string>(elid) +
476  " and field " +
477  boost::lexical_cast<std::string>(it->first) +
478  " does not correspond to mesh dimension");
479 
480  int na = it->second[0];
481  int nb = 0;
482  int nc = 0;
483  if (m_dim >= 2)
484  {
485  nb = it->second[1];
486  }
487  if (m_dim == 3)
488  {
489  nc = it->second[2];
490  }
491 
492  // Assume for parallel partitioning that this is just missing from
493  // our partition.
494  if (m_vertWeights.find(elid) == m_vertWeights.end())
495  {
496  continue;
497  }
498 
499  m_vertWeights[elid][m_fieldNameToId[it->first]] =
500  CalculateElementWeight(m_shape[elid], false, na, nb, nc);
501  m_vertBndWeights[elid][m_fieldNameToId[it->first]] =
502  CalculateElementWeight(m_shape[elid], true, na, nb, nc);
503  m_edgeWeights[elid][m_fieldNameToId[it->first]] =
504  CalculateEdgeWeight(m_shape[elid], na, nb, nc);
505  }
506  } // for i
507 }
int CalculateEdgeWeight(LibUtilities::ShapeType elmtType, int na, int nb, int nc)

References ASSERTL0, CalculateEdgeWeight(), CalculateElementWeight(), m_dim, m_edgeWeights, m_elements, m_expansions, m_fieldNameToId, m_numFields, m_shape, m_vertBndWeights, and m_vertWeights.

Referenced by PartitionMesh().

Member Data Documentation

◆ m_comm

LibUtilities::CommSharedPtr Nektar::SpatialDomains::MeshPartition::m_comm
protected

◆ m_compMap

CompositeDescriptor Nektar::SpatialDomains::MeshPartition::m_compMap
protected

Definition at line 131 of file MeshPartition.h.

Referenced by ReadExpansions().

◆ m_dim

int Nektar::SpatialDomains::MeshPartition::m_dim
protected

Definition at line 126 of file MeshPartition.h.

Referenced by PrintPartInfo(), ReadExpansions(), and WeightElements().

◆ m_edgeWeights

std::map<int, MultiWeight> Nektar::SpatialDomains::MeshPartition::m_edgeWeights
protected

Definition at line 143 of file MeshPartition.h.

Referenced by CreateGraph(), and WeightElements().

◆ m_elements

std::map<int, MeshEntity> Nektar::SpatialDomains::MeshPartition::m_elements
protected

Definition at line 129 of file MeshPartition.h.

Referenced by CreateGraph(), MeshPartition(), PartitionMesh(), and WeightElements().

◆ m_expansions

std::map<int, NummodesPerField> Nektar::SpatialDomains::MeshPartition::m_expansions
protected

Definition at line 135 of file MeshPartition.h.

Referenced by PrintPartInfo(), ReadExpansions(), and WeightElements().

◆ m_fieldNameToId

std::map<std::string, int> Nektar::SpatialDomains::MeshPartition::m_fieldNameToId
protected

Definition at line 140 of file MeshPartition.h.

Referenced by ReadExpansions(), and WeightElements().

◆ m_ghostElmts

std::map<int, MeshEntity> Nektar::SpatialDomains::MeshPartition::m_ghostElmts
protected

Definition at line 130 of file MeshPartition.h.

Referenced by CreateGraph(), MeshPartition(), and PartitionGraph().

◆ m_graph

BoostGraph Nektar::SpatialDomains::MeshPartition::m_graph
protected

Definition at line 145 of file MeshPartition.h.

Referenced by CreateGraph(), PartitionGraph(), and PrintPartInfo().

◆ m_localPartition

std::map<int, std::vector<unsigned int> > Nektar::SpatialDomains::MeshPartition::m_localPartition
protected

Definition at line 146 of file MeshPartition.h.

Referenced by GetElementIDs(), PartitionGraph(), and PrintPartInfo().

◆ m_numFields

int Nektar::SpatialDomains::MeshPartition::m_numFields
protected

Definition at line 127 of file MeshPartition.h.

Referenced by ReadExpansions(), and WeightElements().

◆ m_parallel

bool Nektar::SpatialDomains::MeshPartition::m_parallel
protected

◆ m_session

LibUtilities::SessionReaderSharedPtr Nektar::SpatialDomains::MeshPartition::m_session
protected

Definition at line 123 of file MeshPartition.h.

Referenced by ReadConditions(), and ReadExpansions().

◆ m_shape

std::map<int, LibUtilities::ShapeType> Nektar::SpatialDomains::MeshPartition::m_shape
protected

Definition at line 138 of file MeshPartition.h.

Referenced by PrintPartInfo(), ReadExpansions(), and WeightElements().

◆ m_shared

bool Nektar::SpatialDomains::MeshPartition::m_shared
protected

Definition at line 151 of file MeshPartition.h.

Referenced by PartitionGraph(), and PartitionMesh().

◆ m_vertBndWeights

std::map<int, MultiWeight> Nektar::SpatialDomains::MeshPartition::m_vertBndWeights
protected

Definition at line 142 of file MeshPartition.h.

Referenced by CreateGraph(), and WeightElements().

◆ m_vertWeights

std::map<int, MultiWeight> Nektar::SpatialDomains::MeshPartition::m_vertWeights
protected

Definition at line 141 of file MeshPartition.h.

Referenced by CreateGraph(), and WeightElements().

◆ m_weightBnd

bool Nektar::SpatialDomains::MeshPartition::m_weightBnd
protected

Definition at line 149 of file MeshPartition.h.

Referenced by PartitionGraph(), and ReadConditions().

◆ m_weightDofs

bool Nektar::SpatialDomains::MeshPartition::m_weightDofs
protected

Definition at line 150 of file MeshPartition.h.

Referenced by PartitionGraph(), and ReadConditions().

◆ m_weightingRequired

bool Nektar::SpatialDomains::MeshPartition::m_weightingRequired
protected

Definition at line 148 of file MeshPartition.h.

Referenced by CreateGraph(), PartitionGraph(), PartitionMesh(), and ReadConditions().