704 [[maybe_unused]]
const BoostGraph &graph,
708 [[maybe_unused]] std::set<int> partVerts, [[maybe_unused]]
int mdswitch)
710#ifndef NEKTAR_USE_SCOTCH
711 ASSERTL0(
false,
"Multi-level static condensation requires Nektar++"
712 " to be built with SCOTCH.");
714 int nGraphVerts = boost::num_vertices(graph);
715 int nGraphEdges = boost::num_edges(graph);
717 ASSERTL1(perm.size() >= nGraphVerts && iperm.size() >= nGraphVerts,
718 "Non-matching dimensions");
737 int acnt = 0, vcnt = 0, i, cnt;
738 int nPartition = partVerts.size();
739 int nNonPartition = nGraphVerts - partVerts.size();
751 for (i = cnt = 0; i < nGraphVerts; ++i)
753 if (partVerts.count(i) == 0)
755 initial_perm[i] = cnt;
756 iinitial_perm[cnt++] = i;
760 for (i = 0; i < nGraphVerts; ++i)
762 if (partVerts.count(i) > 0)
764 initial_perm[i] = cnt;
765 iinitial_perm[cnt++] = i;
770 boost::property_map<BoostGraph, boost::vertex_index_t>::type index =
771 get(boost::vertex_index, graph);
775 auto verts = boost::vertices(graph);
776 for (
auto vertit = verts.first; vertit != verts.second; ++vertit)
778 if (partVerts.count(index[*vertit]) > 0)
783 auto adjverts = boost::adjacent_vertices(*vertit, graph);
784 for (
auto adjvertit = adjverts.first; adjvertit != adjverts.second;
787 if (partVerts.count(index[*adjvertit]) > 0)
791 adjncy[acnt++] = initial_perm[*adjvertit];
802 SCOTCH_Graph *scGraph = SCOTCH_graphAlloc();
804 "Failed to allocate Scotch graph for substructuring.");
806 ASSERTL0(SCOTCH_graphInit(scGraph) == 0,
807 "Failed to initialise Scotch graph for substructuring.");
810 (scGraph, 0, nNonPartition, &xadj[0], &xadj[1],
nullptr,
811 nullptr, xadj[nNonPartition], &adjncy[0],
nullptr));
825 std::string strat_str =
826 "c{rat=0.7,cpr=n{sep=/(<TSTS>)?m{rat=0.7,vert=100,low="
827 "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>},unc=n{sep=/(<TSTS>)?m{rat=0.7,"
830 "vert=100,low=h{pass=10},asc=b{width=3,bnd=f{bal=<BBAL>},"
831 "org=(|h{pass=10})f{bal=<BBAL>}}}<SEPA>;"
832 ",ole=<OLEA>,ose=<OSEP>}}";
835 boost::replace_all(strat_str,
"<SEPA>",
836 "|m{rat=0.7,vert=100,low=h{pass=10},"
837 "asc=b{width=3,bnd=f{bal=<BBAL>},"
838 "org=(|h{pass=10})f{bal=<BBAL>}}}");
839 boost::replace_all(strat_str,
"<OSEP>",
"s");
840 boost::replace_all(strat_str,
"<OLEA>",
"s");
841 boost::replace_all(strat_str,
"<BBAL>",
"0.1");
842 boost::replace_all(strat_str,
"<TSTS>",
843 "vert>" + std::to_string(mdswitch));
848 SCOTCH_CALL(SCOTCH_stratGraphOrder, (&strat, strat_str.c_str()));
867 (scGraph, &strat, &iperm_tmp[0], &perm_tmp[0], &cblknbr,
868 &rangtab[0], &treetab[0]));
871 SCOTCH_graphExit(scGraph);
872 SCOTCH_stratExit(&strat);
881 std::vector<MultiLevelBisectedGraphSharedPtr> graphs(cblknbr);
887 for (i = cblknbr - 1; i >= 0; --i)
892 rangtab[i + 1] - rangtab[i]);
896 if (treetab[i] == -1)
911 std::vector<MultiLevelBisectedGraphSharedPtr> &daughters =
912 tmp->GetDaughterGraphs();
913 daughters.insert(daughters.begin(), graphs[i]);
918 for (i = 0; i < nGraphVerts; ++i)
920 if (partVerts.count(i) == 0)
922 iperm[i] = iperm_tmp[initial_perm[i]];
927 auto it = partVerts.begin(), it2 = partVerts.end();
928 for (i = nNonPartition; it != it2; ++it, ++i)
934 for (i = 0; i < nGraphVerts; ++i)
936 ASSERTL1(perm[iperm[i]] == i,
"Perm error " + std::to_string(i));
941 std::vector<int> rootBlocks;
942 for (i = 0; i < cblknbr; ++i)
944 if (treetab[i] == -1)
946 rootBlocks.push_back(i);
951 if (rootBlocks.size() == 1)
953 root = graphs[rootBlocks[0]];
959 for (
int i = 0; i < rootBlocks.size(); ++i)
961 root->GetDaughterGraphs().push_back(graphs[rootBlocks[i]]);
968 ASSERTL0(root->GetTotDofs() == nNonPartition,
969 "Error in constructing Scotch graph for multi-level"
970 " static condensation.");
978 root, nPartition,
true);
994 substructgraph->UpdateBottomUpReordering(perm, iperm);
1000 for (
int i = 0; i < nGraphVerts; i++)