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...
 
virtual void 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 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)
 

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 67 of file MeshPartition.h.

Member Typedef Documentation

◆ BoostAdjacencyIterator

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

Definition at line 123 of file MeshPartition.h.

◆ BoostEdge

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

Definition at line 118 of file MeshPartition.h.

◆ BoostEdgeIterator

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

Definition at line 119 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 115 of file MeshPartition.h.

◆ BoostVertex

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

Definition at line 117 of file MeshPartition.h.

◆ BoostVertexIterator

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

Definition at line 121 of file MeshPartition.h.

◆ MultiWeight

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

Definition at line 91 of file MeshPartition.h.

◆ NumModes

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

Definition at line 125 of file MeshPartition.h.

◆ NummodesPerField

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

Definition at line 126 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.

81  : m_session(session), m_comm(comm), m_dim(meshDim), m_numFields(0),
82  m_elements(element), m_compMap(compMap), m_fieldNameToId(),
83  m_weightingRequired(false), m_weightBnd(false), m_weightDofs(false),
84  m_parallel(false)
85 {
86  // leave the meshpartition method of reading expansions and conditions
89 
90  for (auto elIt = m_elements.cbegin(); elIt != m_elements.cend();)
91  {
92  if (elIt->second.ghost)
93  {
94  m_ghostElmts[elIt->first] = elIt->second;
95  elIt = m_elements.erase(elIt);
96  }
97  else
98  {
99  ++elIt;
100  }
101  }
102 }
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 104 of file MeshPartition.cpp.

105 {
106 }

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 918 of file MeshPartition.cpp.

920 {
921  int weight = 0;
922  int n = std::max(na, std::max(nb, nc));
923  switch (elmtType)
924  {
927  break;
930  break;
933  break;
936  break;
939  weight = n;
940  break;
942  weight = 1;
943  break;
944  default:
945  break;
946  }
947 
948  return weight;
949 }
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:137
int getNumberOfCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:113

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 844 of file MeshPartition.cpp.

847 {
848  int weight = 0;
849 
850  switch (elmtType)
851  {
853  weight = bndWeight
855  na, nb, nc)
856  : LibUtilities::StdTetData::getNumberOfCoefficients(
857  na, nb, nc);
858  break;
860  weight =
861  bndWeight
863  na, nb, nc)
864  : LibUtilities::StdPrismData::getNumberOfCoefficients(
865  na, nb, nc);
866  break;
868  weight = bndWeight
870  na, nb, nc)
871  : LibUtilities::StdHexData::getNumberOfCoefficients(
872  na, nb, nc);
873  break;
875  weight = bndWeight
877  na, nb, nc)
878  : LibUtilities::StdPyrData::getNumberOfCoefficients(
879  na, nb, nc);
880  break;
882  weight =
883  bndWeight
885  nb)
886  : LibUtilities::StdQuadData::getNumberOfCoefficients(na,
887  nb);
888  break;
890  weight =
891  bndWeight
893  nb)
894  : LibUtilities::StdTriData::getNumberOfCoefficients(na, nb);
895  break;
897  weight =
898  bndWeight
900  : LibUtilities::StdSegData::getNumberOfCoefficients(na);
901  break;
903  weight = 1;
904  break;
905  default:
906  break;
907  }
908 
909  return weight;
910 }
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:167
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:298
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:267
int getNumberOfBndCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:147
int getNumberOfBndCoefficients(int Na, int Nb, int Nc)
Definition: ShapeType.hpp:217
int getNumberOfBndCoefficients(int Na, int Nb)
Definition: ShapeType.hpp:125

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 802 of file MeshPartition.cpp.

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

Referenced by PartitionGraph().

◆ CreateGraph()

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

Definition at line 508 of file MeshPartition.cpp.

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

834 {
835  BoostVertexIterator vertit, vertit_end;
836 
837  auto it = m_localPartition.find(procid);
838 
839  ASSERTL0(it != m_localPartition.end(), "Unable to find local partition");
840 
841  elmtid = m_localPartition[procid];
842 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
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 588 of file MeshPartition.cpp.

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

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, PartitionGraphImpl(), and Vmath::Vsum().

Referenced by PartitionMesh().

◆ PartitionGraphImpl()

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

◆ PartitionMesh()

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

Definition at line 108 of file MeshPartition.cpp.

110 {
111  boost::ignore_unused(nLocal);
112 
113  ASSERTL0(m_parallel || m_elements.size() >= nParts,
114  "Too few elements for this many processes.");
115  m_shared = shared;
116 
117  ASSERTL0(!m_parallel || shared,
118  "Parallel partitioning requires shared filesystem.");
119 
121  {
122  WeightElements();
123  }
124  CreateGraph();
125 
126  PartitionGraph(nParts, overlapping);
127 }
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 308 of file MeshPartition.cpp.

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

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

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

Referenced by MeshPartition().

◆ ReadExpansions()

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

Definition at line 129 of file MeshPartition.cpp.

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

◆ WeightElements()

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

Definition at line 452 of file MeshPartition.cpp.

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

Referenced by ReadExpansions().

◆ m_dim

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

Definition at line 131 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 148 of file MeshPartition.h.

Referenced by CreateGraph(), and WeightElements().

◆ m_elements

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

Definition at line 134 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 140 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 145 of file MeshPartition.h.

Referenced by ReadExpansions(), and WeightElements().

◆ m_ghostElmts

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

Definition at line 135 of file MeshPartition.h.

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

◆ m_graph

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

Definition at line 150 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 151 of file MeshPartition.h.

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

◆ m_numFields

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

Definition at line 132 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 128 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 143 of file MeshPartition.h.

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

◆ m_shared

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

Definition at line 156 of file MeshPartition.h.

Referenced by PartitionGraph(), and PartitionMesh().

◆ m_vertBndWeights

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

Definition at line 147 of file MeshPartition.h.

Referenced by CreateGraph(), and WeightElements().

◆ m_vertWeights

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

Definition at line 146 of file MeshPartition.h.

Referenced by CreateGraph(), and WeightElements().

◆ m_weightBnd

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

Definition at line 154 of file MeshPartition.h.

Referenced by PartitionGraph(), and ReadConditions().

◆ m_weightDofs

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

Definition at line 155 of file MeshPartition.h.

Referenced by PartitionGraph(), and ReadConditions().

◆ m_weightingRequired

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

Definition at line 153 of file MeshPartition.h.

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