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)