40 #include <boost/algorithm/string/replace.hpp>
41 #include <boost/config.hpp>
42 #include <boost/graph/adjacency_list.hpp>
43 #include <boost/graph/bandwidth.hpp>
44 #include <boost/graph/cuthill_mckee_ordering.hpp>
45 #include <boost/graph/properties.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
101 int npatch = numLocalBndCondPerPatch.size();
106 bndoffset[0] = intoffset[0] = 0;
107 for (
int i = 1; i <= npatch; ++i)
109 bndoffset[i] = bndoffset[i - 1] + numLocalBndCondPerPatch[i - 1];
110 intoffset[i] = intoffset[i - 1] + numLocalIntCondPerPatch[i - 1];
115 for (
int i = 0; i <
m_dofId.size(); ++i)
151 returnval += g->GetTotDofs();
160 static int level = 0;
161 static int offset = 0;
166 g->SetGlobalNumberingOffset();
181 static int level = 0;
183 cout <<
"LEVEL " <<
level <<
" " <<
m_BndDofs->GetNverts() << endl;
194 std::vector<SubGraphSharedPtr> &leaves)
const
200 g->CollectLeaves(leaves);
207 leaves.push_back(leave);
214 static int level = 0;
215 static int nLeaves = 0;
228 if (g->GetNdaughterGraphs() == 0 &&
229 g->GetBndDofsGraph()->GetNverts() == 0)
255 static int level = 0;
256 static int nLeaves = 0;
269 if (g->GetNdaughterGraphs() == 0)
293 : m_IntBlocks(), m_daughterGraph()
300 for (
int i = 0; i < nVerts; i++)
309 : m_IntBlocks(), m_daughterGraph()
321 graph->SetGlobalNumberingOffset();
324 graph->CutEmptyLeaves();
326 ncuts = graph->CutLeaves();
341 static int nIntDofs = 0;
342 static int level = 0;
357 returnval = nIntDofs;
370 static int level = 0;
373 cout <<
"LEVEL " <<
level << endl;
374 cout <<
"interior blocks" << endl;
377 cout <<
" " << i <<
"/" <<
m_IntBlocks.size() - 1 <<
": "
407 for (
int i = 0; i < nDofs; i++)
409 iperm[i] = iperm1[iperm[i]];
417 static int offset = 0;
418 static int level = 0;
430 for (
int j = 0; j <
m_IntBlocks[i]->GetNverts(); j++)
432 iperm[GlobIdOffset + j] = offset;
447 static int offset = 0;
448 static int level = 0;
458 int OrigGlobIdOffset =
m_IntBlocks[i]->GetIdOffset();
463 for (
int j = 0; j <
m_IntBlocks[i]->GetNverts(); j++)
465 newNverts += wgts[OrigGlobIdOffset + j];
466 offset += wgts[OrigGlobIdOffset + j];
494 static int level = 0;
497 if (
level < leveltomask)
501 else if (
level == leveltomask)
509 for (
int j = 0; j < nVerts; j++)
511 maskarray[GlobIdOffset + j] = (
NekDouble)i;
524 const int whichlevel)
const
527 static int level = 0;
530 if (
level < whichlevel)
534 else if (
level == whichlevel)
551 static int level = 0;
554 if (
level < whichlevel)
558 else if (
level == whichlevel)
561 "Array dimension not sufficient");
565 outarray[i] = (
unsigned int)
m_IntBlocks[i]->GetNverts();
577 const int patch)
const
580 static int level = 0;
583 if (
level < whichlevel)
587 else if (
level == whichlevel)
602 const int whichlevel)
const
604 std::vector<SubGraphSharedPtr> returnval;
605 static int level = 0;
608 if (
level < whichlevel)
612 else if (
level == whichlevel)
628 static int level = 0;
631 if (
level < whichlevel)
635 else if (
level == whichlevel)
653 static int level = 0;
660 returnval = max(returnval,
level);
669 return g->GetNverts() == 0;
679 typedef boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS>
681 typedef boost::graph_traits<BoostGraph>::vertex_descriptor BoostVertex;
687 int nGraphVerts = boost::num_vertices(graph);
689 ASSERTL1(perm.size() >= nGraphVerts && iperm.size() >= nGraphVerts,
690 "Non-matching dimensions");
694 std::vector<BoostVertex> reorderedVerts(nGraphVerts);
695 boost::cuthill_mckee_ordering(graph, reorderedVerts.rbegin());
698 for (
int i = 0; i < nGraphVerts; i++)
700 perm[i] = reorderedVerts[i];
701 iperm[reorderedVerts[i]] = i;
708 std::set<int> partVerts,
int mdswitch)
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.size() >= nGraphVerts && iperm.size() >= nGraphVerts,
720 "Non-matching dimensions");
739 int acnt = 0, vcnt = 0, i, cnt;
740 int nPartition = partVerts.size();
741 int nNonPartition = nGraphVerts - partVerts.size();
753 for (i = cnt = 0; i < nGraphVerts; ++i)
755 if (partVerts.count(i) == 0)
757 initial_perm[i] = cnt;
758 iinitial_perm[cnt++] = i;
762 for (i = 0; i < nGraphVerts; ++i)
764 if (partVerts.count(i) > 0)
766 initial_perm[i] = cnt;
767 iinitial_perm[cnt++] = i;
772 boost::property_map<BoostGraph, boost::vertex_index_t>::type index =
773 get(boost::vertex_index, graph);
777 auto verts = boost::vertices(graph);
778 for (
auto vertit = verts.first; vertit != verts.second; ++vertit)
780 if (partVerts.count(index[*vertit]) > 0)
785 auto adjverts = boost::adjacent_vertices(*vertit, graph);
786 for (
auto adjvertit = adjverts.first; adjvertit != adjverts.second;
789 if (partVerts.count(index[*adjvertit]) > 0)
793 adjncy[acnt++] = initial_perm[*adjvertit];
804 SCOTCH_Graph *scGraph = SCOTCH_graphAlloc();
806 (scGraph, 0, nNonPartition, &xadj[0], &xadj[1], NULL, NULL,
807 xadj[nNonPartition], &adjncy[0], NULL));
821 std::string strat_str =
822 "c{rat=0.7,cpr=n{sep=/(<TSTS>)?m{rat=0.7,vert=100,low="
823 "h{pass=10},asc=b{width=3,bnd=f{bal=<BBAL>},"
824 "org=(|h{pass=10})f{bal=<BBAL>}}}<SEPA>;,"
825 "ole=<OLEA>,ose=<OSEP>},unc=n{sep=/(<TSTS>)?m{rat=0.7,"
826 "vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=<BBAL>},"
827 "org=(|h{pass=10})f{bal=<BBAL>}}}<SEPA>;"
828 ",ole=<OLEA>,ose=<OSEP>}}";
831 boost::replace_all(strat_str,
"<SEPA>",
832 "|m{rat=0.7,vert=100,low=h{pass=10},"
833 "asc=b{width=3,bnd=f{bal=<BBAL>},"
834 "org=(|h{pass=10})f{bal=<BBAL>}}}");
835 boost::replace_all(strat_str,
"<OSEP>",
"s");
836 boost::replace_all(strat_str,
"<OLEA>",
"s");
837 boost::replace_all(strat_str,
"<BBAL>",
"0.1");
838 boost::replace_all(strat_str,
"<TSTS>",
839 "vert>" + std::to_string(mdswitch));
844 SCOTCH_CALL(SCOTCH_stratGraphOrder, (&strat, strat_str.c_str()));
863 (scGraph, &strat, &iperm_tmp[0], &perm_tmp[0], &cblknbr,
864 &rangtab[0], &treetab[0]));
867 SCOTCH_graphExit(scGraph);
868 SCOTCH_stratExit(&strat);
877 std::vector<MultiLevelBisectedGraphSharedPtr> graphs(cblknbr);
883 for (i = cblknbr - 1; i >= 0; --i)
888 rangtab[i + 1] - rangtab[i]);
892 if (treetab[i] == -1)
907 std::vector<MultiLevelBisectedGraphSharedPtr> &daughters =
908 tmp->GetDaughterGraphs();
909 daughters.insert(daughters.begin(), graphs[i]);
914 for (i = 0; i < nGraphVerts; ++i)
916 if (partVerts.count(i) == 0)
918 iperm[i] = iperm_tmp[initial_perm[i]];
923 auto it = partVerts.begin(), it2 = partVerts.end();
924 for (i = nNonPartition; it != it2; ++it, ++i)
930 for (i = 0; i < nGraphVerts; ++i)
932 ASSERTL1(perm[iperm[i]] == i,
"Perm error " + std::to_string(i));
937 std::vector<int> rootBlocks;
938 for (i = 0; i < cblknbr; ++i)
940 if (treetab[i] == -1)
942 rootBlocks.push_back(i);
947 if (rootBlocks.size() == 1)
949 root = graphs[rootBlocks[0]];
955 for (
int i = 0; i < rootBlocks.size(); ++i)
957 root->GetDaughterGraphs().push_back(graphs[rootBlocks[i]]);
964 ASSERTL0(root->GetTotDofs() == nNonPartition,
965 "Error in constructing Scotch graph for multi-level"
966 " static condensation.");
974 root, nPartition,
true);
990 substructgraph->UpdateBottomUpReordering(perm, iperm);
996 for (
int i = 0; i < nGraphVerts; i++)
1011 int nGraphVerts = boost::num_vertices(graph);
1013 ASSERTL1(perm.size() >= nGraphVerts && iperm.size() >= nGraphVerts,
1014 "Non-matching dimensions");
1016 for (
int i = 0; i < nGraphVerts; i++)
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
#define SCOTCH_CALL(scotchFunc, args)
#define sign(a, b)
return the sign(b)*a
General purpose memory allocation routines with the ability to allocate from thread specific memory p...
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
void GetNintDofsPerPatch(const int whichlevel, Array< OneD, unsigned int > &outarray) const
void ExpandGraphWithVertexWeights(const Array< OneD, const int > &wgts)
int GetNumGlobalDofs(const int whichlevel) const
std::vector< SubGraphSharedPtr > GetInteriorBlocks() const
std::vector< SubGraphSharedPtr > m_IntBlocks
void SetBottomUpReordering(Array< OneD, int > &iperm) const
int GetInteriorOffset(const int whichlevel, const int patch=0) const
BottomUpSubStructuredGraph(MultiLevelBisectedGraphSharedPtr graph, int nPartition=0, bool globaloffset=false)
void UpdateBottomUpReordering(Array< OneD, int > &perm, Array< OneD, int > &iperm) const
BottomUpSubStructuredGraphSharedPtr m_daughterGraph
~BottomUpSubStructuredGraph(void)
void MaskPatches(const int leveltomask, Array< OneD, NekDouble > &maskarray) const
int GetNpatchesWithInterior(const int whichlevel) const
MultiLevelBisectedGraph(MultiLevelBisectedGraphSharedPtr oldLevel, const int nPartition)
void DumpNBndDofs(void) const
void SetGlobalNumberingOffset()
void CollectLeaves(std::vector< SubGraphSharedPtr > &leaves) const
SubGraphSharedPtr m_BndDofs
~MultiLevelBisectedGraph(void)
std::vector< MultiLevelBisectedGraphSharedPtr > m_daughterGraphs
Array< OneD, unsigned int > m_bndPatch
void SetPatchMap(const int n, const int patchId, const int dofId, const unsigned int bndPatch, const NekDouble sign)
void SetNewLevelMap(Array< OneD, const unsigned int > numLocalBndCondPerPatch, Array< OneD, const unsigned int > numLocalIntCondPerPatch)
Array< OneD, NekDouble > m_sign
Array< OneD, int > m_patchId
Array< OneD, int > m_dofId
Array< OneD, int > m_newLevelMap
void NoReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm)
void CuthillMckeeReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm)
void MultiLevelBisectionReordering(const BoostGraph &graph, Array< OneD, int > &perm, Array< OneD, int > &iperm, BottomUpSubStructuredGraphSharedPtr &substructgraph, std::set< int > partVerts, int mdswitch)
std::shared_ptr< BottomUpSubStructuredGraph > BottomUpSubStructuredGraphSharedPtr
bool SubGraphWithoutVerts(const SubGraphSharedPtr g)
std::shared_ptr< MultiLevelBisectedGraph > MultiLevelBisectedGraphSharedPtr
std::shared_ptr< SubGraph > SubGraphSharedPtr
The above copyright notice and this permission notice shall be included.