42 #include <boost/config.hpp>    43 #include <boost/graph/adjacency_list.hpp>    44 #include <boost/graph/cuthill_mckee_ordering.hpp>    45 #include <boost/graph/properties.hpp>    46 #include <boost/graph/bandwidth.hpp>    47 #include <boost/algorithm/string/replace.hpp>    53 #ifdef NEKTAR_USE_SCOTCH    60 #define SCOTCH_CALL(scotchFunc, args)                                   \    62         ASSERTL0(scotchFunc args == 0,                                  \    63                  std::string("Error in Scotch calling function ")       \    64                  + std::string(#scotchFunc));                           \    70     namespace MultiRegions
    94             const unsigned int bndPatch,
   105             const int                        nPartition)
   107             m_daughterGraphs.push_back(oldLevel);
   126                 returnval += g->GetTotDofs();
   135             static int level = 0;
   136             static int offset = 0;
   141                 g->SetGlobalNumberingOffset();
   156             static int level = 0;
   158             cout << 
"LEVEL " << level << 
" " << 
m_BndDofs->GetNverts() << endl;
   169             std::vector<SubGraphSharedPtr>& leaves)
 const   175                 g->CollectLeaves(leaves);
   182                 leaves.push_back(leave);
   189             static int level = 0;
   190             static int nLeaves = 0;
   203                 if (g->GetNdaughterGraphs() == 0 &&
   204                     g->GetBndDofsGraph()->GetNverts() == 0)
   230             static int level = 0;
   231             static int nLeaves = 0;
   244                 if (g->GetNdaughterGraphs() == 0)
   269             const int nVerts) : m_IntBlocks(), m_daughterGraph()
   276             for (
int i = 0 ; i < nVerts; i++)
   300                 graph->SetGlobalNumberingOffset();
   303             graph->CutEmptyLeaves();
   305             ncuts = graph->CutLeaves();
   320             static int nIntDofs = 0;
   321             static int level = 0;
   336             returnval = nIntDofs;
   349             static int level = 0;
   352             cout << 
"LEVEL " << level << endl;
   353             cout << 
"interior blocks" << endl;
   388             for (
int i=0; i < nDofs; i++)
   390                 iperm[i]       = iperm1[iperm[i]];
   398             static int offset = 0;
   399             static int level = 0;
   411                 for(
int j = 0; j < 
m_IntBlocks[i]->GetNverts(); j++)
   413                     iperm[GlobIdOffset+j] = offset;
   428             static int offset = 0;
   429             static int level = 0;
   439                 int OrigGlobIdOffset = 
m_IntBlocks[i]->GetIdOffset();
   444                 for(
int j = 0; j < 
m_IntBlocks[i]->GetNverts(); j++)
   446                     newNverts += wgts[OrigGlobIdOffset+j];
   447                     offset    += wgts[OrigGlobIdOffset+j];
   475             const int               leveltomask, 
   478             static int level = 0;
   481             if(level < leveltomask)
   485             else if(level == leveltomask)
   493                     for(
int j = 0; j < nVerts; j++)
   495                         maskarray[GlobIdOffset+j] = (
NekDouble) i;
   502                          "If statement should not arrive here");
   509             const int whichlevel)
 const   512             static int level = 0;
   515             if(level < whichlevel)
   520             else if(level == whichlevel)
   527                          "If statement should not arrive here");
   536             const int                  whichlevel, 
   539             static int level = 0;
   542             if(level < whichlevel)
   546             else if(level == whichlevel)
   549                          "Array dimension not sufficient");
   553                     outarray[i] = (
unsigned int) 
m_IntBlocks[i]->GetNverts();
   559                          "If statement should not arrive here");
   566             const int whichlevel, 
const int patch)
 const   569             static int level = 0;
   572             if(level < whichlevel)
   576             else if(level == whichlevel)
   583                          "If statement should not arrive here");
   594             std::vector<SubGraphSharedPtr> returnval;
   595             static int level = 0;
   598             if(level < whichlevel)
   602             else if(level == whichlevel)
   609                          "If statement should not arrive here");
   617             const int whichlevel)
 const   620             static int level = 0;
   623             if(level < whichlevel)
   627             else if(level == whichlevel)
   635                          "If statement should not arrive here");
   646             static int level = 0;
   653             returnval = max(returnval,level);
   663             return g->GetNverts() == 0;
   673             typedef boost::adjacency_list<
   674                 boost::setS, boost::vecS, boost::undirectedS> BoostGraph;
   675             typedef boost::graph_traits<BoostGraph>::vertex_descriptor
   683             int nGraphVerts = boost::num_vertices(graph);
   685             ASSERTL1(perm. num_elements() >= nGraphVerts &&
   686                      iperm.num_elements() >= nGraphVerts,
   687                      "Non-matching dimensions");
   691             std::vector<BoostVertex> reorderedVerts(nGraphVerts);
   692             boost::cuthill_mckee_ordering(graph, reorderedVerts.rbegin());
   695             for(
int i = 0; i < nGraphVerts; i++)
   697                 perm[i] = reorderedVerts[i];
   698                 iperm[ reorderedVerts[i] ] = i;
   703             const BoostGraph                    &graph,
   707             std::set<int>                        partVerts,
   710 #ifndef NEKTAR_USE_SCOTCH   711             boost::ignore_unused(graph, perm, iperm, substructgraph, partVerts,
   713             ASSERTL0(
false, 
"Multi-level static condensation requires Nektar++"   714                             " to be built with SCOTCH.");
   716             int nGraphVerts = boost::num_vertices(graph);
   717             int nGraphEdges = boost::num_edges   (graph);
   719             ASSERTL1(perm. num_elements() >= nGraphVerts &&
   720                      iperm.num_elements() >= nGraphVerts,
   721                      "Non-matching dimensions");
   740                 int acnt = 0, vcnt = 0, i, cnt;
   741                 int nPartition    = partVerts.size();
   742                 int nNonPartition = nGraphVerts - partVerts.size();
   754                 for (i = cnt = 0; i < nGraphVerts; ++i)
   756                     if (partVerts.count(i) == 0)
   758                         initial_perm [i]     = cnt;
   759                         iinitial_perm[cnt++] = i;
   763                 for (i = 0; i < nGraphVerts; ++i)
   765                     if (partVerts.count(i) > 0)
   767                         initial_perm [i]     = cnt;
   768                         iinitial_perm[cnt++] = i;
   773                 boost::property_map<BoostGraph, boost::vertex_index_t>::type
   774                     index = 
get(boost::vertex_index, graph);
   778                 auto verts = boost::vertices(graph);
   779                 for (
auto vertit = verts.first; vertit != verts.second; ++vertit)
   781                     if (partVerts.count(index[*vertit]) > 0)
   786                     auto adjverts = boost::adjacent_vertices(*vertit,graph);
   787                     for (
auto adjvertit = adjverts.first;
   788                          adjvertit != adjverts.second; ++adjvertit)
   790                         if (partVerts.count(index[*adjvertit]) > 0)
   794                         adjncy[acnt++] = initial_perm[*adjvertit];
   805                 SCOTCH_Graph scGraph;
   807                             (&scGraph, 0, nNonPartition, &xadj[0], &xadj[1],
   808                              NULL, NULL, xadj[nNonPartition], &adjncy[0], NULL));
   822                 std::string strat_str =
   823                     "c{rat=0.7,cpr=n{sep=/(<TSTS>)?m{rat=0.7,vert=100,low="   824                     "h{pass=10},asc=b{width=3,bnd=f{bal=<BBAL>},"   825                     "org=(|h{pass=10})f{bal=<BBAL>}}}<SEPA>;,"   826                     "ole=<OLEA>,ose=<OSEP>},unc=n{sep=/(<TSTS>)?m{rat=0.7,"   827                     "vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=<BBAL>},"   828                     "org=(|h{pass=10})f{bal=<BBAL>}}}<SEPA>;"   829                     ",ole=<OLEA>,ose=<OSEP>}}";
   833                     strat_str, 
"<SEPA>", 
"|m{rat=0.7,vert=100,low=h{pass=10},"   834                     "asc=b{width=3,bnd=f{bal=<BBAL>},"   835                     "org=(|h{pass=10})f{bal=<BBAL>}}}");
   836                 boost::replace_all(strat_str, 
"<OSEP>", 
"s");
   837                 boost::replace_all(strat_str, 
"<OLEA>", 
"s");
   838                 boost::replace_all(strat_str, 
"<BBAL>", 
"0.1");
   841                     "vert>"+std::to_string(mdswitch));
   846                 SCOTCH_CALL(SCOTCH_stratGraphOrder, (&strat, strat_str.c_str()));
   865                             (&scGraph, &strat, &iperm_tmp[0], &perm_tmp[0],
   866                              &cblknbr, &rangtab[0], &treetab[0]));
   869                 SCOTCH_graphExit(&scGraph);
   870                 SCOTCH_stratExit(&strat);
   879                 std::vector<MultiLevelBisectedGraphSharedPtr> graphs(cblknbr);
   885                 for (i = cblknbr-1; i >= 0; --i)
   893                     if (treetab[i] == -1)
   908                     std::vector<MultiLevelBisectedGraphSharedPtr> &daughters =
   909                         tmp->GetDaughterGraphs();
   910                     daughters.insert(daughters.begin(), graphs[i]);
   915                 for (i = 0; i < nGraphVerts; ++i)
   917                     if (partVerts.count(i) == 0)
   919                         iperm[i] = iperm_tmp[initial_perm[i]];
   924                 auto it = partVerts.begin(), it2 = partVerts.end();
   925                 for (i = nNonPartition; it != it2; ++it, ++i)
   931                 for (i = 0; i < nGraphVerts; ++i)
   933                     ASSERTL1(perm[iperm[i]] == i, 
"Perm error "   934                              + std::to_string(i));
   939                 std::vector<int> rootBlocks;
   940                 for (i = 0; i < cblknbr; ++i)
   942                     if (treetab[i] == -1)
   944                         rootBlocks.push_back(i);
   949                 if (rootBlocks.size() == 1)
   951                     root = graphs[rootBlocks[0]];
   958                     for (
int i = 0; i < rootBlocks.size(); ++i)
   960                         root->GetDaughterGraphs().push_back(graphs[rootBlocks[i]]);
   967                 ASSERTL0(root->GetTotDofs() == nNonPartition,
   968                          "Error in constructing Scotch graph for multi-level"   969                          " static condensation.");
   992                 substructgraph->UpdateBottomUpReordering(perm,iperm);
   998                 for(
int i = 0; i < nGraphVerts; i++)
  1013             int nGraphVerts = boost::num_vertices(graph);
  1015             ASSERTL1(perm. num_elements() >= nGraphVerts &&
  1016                      iperm.num_elements() >= nGraphVerts,
  1017                      "Non-matching dimensions");
  1019             for (
int i = 0; i < nGraphVerts; i++)
 Array< OneD, NekDouble > m_sign
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
void MultiLevelBisectionReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm, BottomUpSubStructuredGraphSharedPtr &substructgraph, std::set< int > partVerts, int mdswitch)
#define sign(a, b)
return the sign(b)*a 
std::vector< MultiLevelBisectedGraphSharedPtr > m_daughterGraphs
#define SCOTCH_CALL(scotchFunc, args)
std::vector< SubGraphSharedPtr > GetInteriorBlocks() const
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
void UpdateBottomUpReordering(Array< OneD, int > &perm, Array< OneD, int > &iperm) const
void GetNintDofsPerPatch(const int whichlevel, Array< OneD, unsigned int > &outarray) const
void CuthillMckeeReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm)
void CollectLeaves(std::vector< SubGraphSharedPtr > &leaves) const
int GetNumGlobalDofs(const int whichlevel) const
SubGraphSharedPtr m_BndDofs
Array< OneD, unsigned int > m_bndPatch
void ExpandGraphWithVertexWeights(const Array< OneD, const int > &wgts)
std::shared_ptr< SubGraph > SubGraphSharedPtr
BottomUpSubStructuredGraph(MultiLevelBisectedGraphSharedPtr graph, int nPartition=0, bool globaloffset=false)
void SetGlobalNumberingOffset()
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool. 
std::vector< SubGraphSharedPtr > m_IntBlocks
BottomUpSubStructuredGraphSharedPtr m_daughterGraph
MultiLevelBisectedGraph(MultiLevelBisectedGraphSharedPtr oldLevel, const int nPartition)
std::shared_ptr< MultiLevelBisectedGraph > MultiLevelBisectedGraphSharedPtr
Array< OneD, int > m_dofId
void DumpNBndDofs(void) const
bool SubGraphWithoutVerts(const SubGraphSharedPtr g)
Array< OneD, int > m_patchId
int GetInteriorOffset(const int whichlevel, const int patch=0) const
~MultiLevelBisectedGraph(void)
~BottomUpSubStructuredGraph(void)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
void SetPatchMap(const int n, const int patchId, const int dofId, const unsigned int bndPatch, const NekDouble sign)
std::shared_ptr< BottomUpSubStructuredGraph > BottomUpSubStructuredGraphSharedPtr
void SetBottomUpReordering(Array< OneD, int > &iperm) const
void MaskPatches(const int leveltomask, Array< OneD, NekDouble > &maskarray) const
int GetNpatchesWithInterior(const int whichlevel) const
void NoReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm)