46 #ifndef MUELU_UNCOUPLEDAGGREGATIONFACTORY_KOKKOS_DEF_HPP_
47 #define MUELU_UNCOUPLEDAGGREGATIONFACTORY_KOKKOS_DEF_HPP_
49 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
53 #include <Xpetra_Map.hpp>
54 #include <Xpetra_Vector.hpp>
55 #include <Xpetra_MultiVectorFactory.hpp>
56 #include <Xpetra_VectorFactory.hpp>
60 #include "MueLu_OnePtAggregationAlgorithm_kokkos.hpp"
61 #include "MueLu_PreserveDirichletAggregationAlgorithm_kokkos.hpp"
62 #include "MueLu_IsolatedNodeAggregationAlgorithm_kokkos.hpp"
64 #include "MueLu_AggregationPhase1Algorithm_kokkos.hpp"
65 #include "MueLu_AggregationPhase2aAlgorithm_kokkos.hpp"
66 #include "MueLu_AggregationPhase2bAlgorithm_kokkos.hpp"
67 #include "MueLu_AggregationPhase3Algorithm_kokkos.hpp"
70 #include "MueLu_LWGraph_kokkos.hpp"
71 #include "MueLu_Aggregates_kokkos.hpp"
74 #include "MueLu_AmalgamationInfo.hpp"
75 #include "MueLu_Utilities.hpp"
77 #include "KokkosGraph_Distance2ColorHandle.hpp"
78 #include "KokkosGraph_Distance2Color.hpp"
82 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
83 UncoupledAggregationFactory_kokkos<LocalOrdinal, GlobalOrdinal, Node>::UncoupledAggregationFactory_kokkos()
84 : bDefinitionPhase_(true)
87 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
88 RCP<const ParameterList> UncoupledAggregationFactory_kokkos<LocalOrdinal, GlobalOrdinal, Node>::GetValidParameterList()
const {
89 RCP<ParameterList> validParamList =
rcp(
new ParameterList());
95 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
100 validParamList->getEntry(
"aggregation: ordering").setValidator(
101 rcp(
new validatorType(Teuchos::tuple<std::string>(
"natural",
"graph",
"random"),
"aggregation: ordering")));
110 SET_VALID_ENTRY(
"aggregation: error on nodes with no on-rank neighbors");
113 #undef SET_VALID_ENTRY
116 validParamList->set< RCP<const FactoryBase> >(
"Graph", null,
"Generating factory of the graph");
117 validParamList->set< RCP<const FactoryBase> >(
"DofsPerNode", null,
"Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
120 validParamList->set< std::string > (
"OnePt aggregate map name",
"",
"Name of input map for single node aggregates. (default='')");
121 validParamList->set< std::string > (
"OnePt aggregate map factory",
"",
"Generating factory of (DOF) map for single node aggregates.");
124 return validParamList;
127 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
128 void UncoupledAggregationFactory_kokkos<LocalOrdinal, GlobalOrdinal, Node>::DeclareInput(Level& currentLevel)
const {
129 Input(currentLevel,
"Graph");
130 Input(currentLevel,
"DofsPerNode");
132 const ParameterList& pL = GetParameterList();
135 std::string mapOnePtName = pL.get<std::string>(
"OnePt aggregate map name");
136 if (mapOnePtName.length() > 0) {
137 std::string mapOnePtFactName = pL.get<std::string>(
"OnePt aggregate map factory");
138 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
139 currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
141 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
142 currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
147 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
148 void UncoupledAggregationFactory_kokkos<LocalOrdinal, GlobalOrdinal, Node>::
149 Build(Level ¤tLevel)
const {
150 using execution_space =
typename LWGraph_kokkos::execution_space;
151 using memory_space =
typename LWGraph_kokkos::memory_space;
152 using local_ordinal_type =
typename LWGraph_kokkos::local_ordinal_type;
153 FactoryMonitor m(*
this,
"Build", currentLevel);
155 ParameterList pL = GetParameterList();
156 bDefinitionPhase_ =
false;
158 if (pL.get<
int>(
"aggregation: max agg size") == -1)
159 pL.set(
"aggregation: max agg size", INT_MAX);
162 RCP<const FactoryBase> graphFact = GetFactory(
"Graph");
166 algos_.push_back(
rcp(
new PreserveDirichletAggregationAlgorithm_kokkos(graphFact)));
167 if (pL.get<
bool>(
"aggregation: allow user-specified singletons") ==
true) algos_.push_back(
rcp(
new OnePtAggregationAlgorithm_kokkos (graphFact)));
168 if (pL.get<
bool>(
"aggregation: enable phase 1" ) ==
true) algos_.push_back(
rcp(
new AggregationPhase1Algorithm_kokkos (graphFact)));
169 if (pL.get<
bool>(
"aggregation: enable phase 2a") ==
true) algos_.push_back(
rcp(
new AggregationPhase2aAlgorithm_kokkos (graphFact)));
170 if (pL.get<
bool>(
"aggregation: enable phase 2b") ==
true) algos_.push_back(
rcp(
new AggregationPhase2bAlgorithm_kokkos (graphFact)));
171 if (pL.get<
bool>(
"aggregation: enable phase 3" ) ==
true) algos_.push_back(
rcp(
new AggregationPhase3Algorithm_kokkos (graphFact)));
173 std::string mapOnePtName = pL.get<std::string>(
"OnePt aggregate map name");
174 RCP<Map> OnePtMap = Teuchos::null;
175 if (mapOnePtName.length()) {
176 std::string mapOnePtFactName = pL.get<std::string>(
"OnePt aggregate map factory");
177 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
178 OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, NoFactory::get());
180 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
181 OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
185 RCP<const LWGraph_kokkos> graph = Get< RCP<LWGraph_kokkos> >(currentLevel,
"Graph");
188 RCP<Aggregates_kokkos> aggregates =
rcp(
new Aggregates_kokkos(*graph));
189 aggregates->setObjectLabel(
"UC");
191 const LO numRows = graph->GetNodeNumVertices();
207 typename LWGraph_kokkos::boundary_nodes_type dirichletBoundaryMap = graph->GetBoundaryNodeMap();
210 KOKKOS_LAMBDA(
const local_ordinal_type nodeIdx) {
211 if (dirichletBoundaryMap(nodeIdx) ==
true) {
217 LO nDofsPerNode = Get<LO>(currentLevel,
"DofsPerNode");
218 GO indexBase = graph->GetDomainMap()->getIndexBase();
219 if (OnePtMap != Teuchos::null) {
221 = Kokkos::create_mirror_view(aggStat);
224 for (LO i = 0; i < numRows; i++) {
226 GO grid = (graph->GetDomainMap()->getGlobalElement(i)-indexBase) * nDofsPerNode + indexBase;
228 for (LO kr = 0; kr < nDofsPerNode; kr++)
229 if (OnePtMap->isNodeGlobalElement(grid + kr))
230 aggStatHost(i) =
ONEPT;
237 const RCP<const Teuchos::Comm<int> > comm = graph->GetComm();
238 GO numGlobalRows = 0;
243 SubFactoryMonitor sfm(*
this,
"Algo \"Graph Coloring\"", currentLevel);
250 using graph_t =
typename LWGraph_kokkos::local_graph_type;
251 using KernelHandle = KokkosKernels::Experimental::
252 KokkosKernelsHandle<
typename graph_t::row_map_type::value_type,
253 typename graph_t::entries_type::value_type,
254 typename graph_t::entries_type::value_type,
255 typename graph_t::device_type::execution_space,
256 typename graph_t::device_type::memory_space,
257 typename graph_t::device_type::memory_space>;
260 kh.create_distance2_graph_coloring_handle();
263 auto coloringHandle = kh.get_distance2_graph_coloring_handle();
273 if(pL.get<
bool>(
"aggregation: deterministic") ==
true) {
274 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_SERIAL );
276 }
else if(pL.get<std::string>(
"aggregation: coloring algorithm") ==
"serial") {
277 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_SERIAL );
279 }
else if(pL.get<std::string>(
"aggregation: coloring algorithm") ==
"default") {
280 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_DEFAULT );
282 }
else if(pL.get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based") {
283 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_VB );
285 }
else if(pL.get<std::string>(
"aggregation: coloring algorithm") ==
"vertex based bit set") {
286 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_VB_BIT );
288 }
else if(pL.get<std::string>(
"aggregation: coloring algorithm") ==
"edge filtering") {
289 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_VB_BIT_EF );
291 }
else if(pL.get<std::string>(
"aggregation: coloring algorithm") ==
"net based bit set") {
292 coloringHandle->set_algorithm( KokkosGraph::COLORING_D2_NB_BIT );
295 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unrecognized distance 2 coloring algorithm, valid options are: serial, default, matrix squared, vertex based, vertex based bit set, edge filtering")
299 typename graph_t::row_map_type aRowptrs = graph->getRowPtrs();
300 typename graph_t::entries_type aColinds = graph->getEntries();
304 KokkosGraph::Experimental::graph_color_distance2(&kh, numRows, aRowptrs, aColinds);
307 aggregates->SetGraphColors(coloringHandle->get_vertex_colors());
308 aggregates->SetGraphNumColors(static_cast<LO>(coloringHandle->get_num_colors()));
311 kh.destroy_distance2_graph_coloring_handle();
314 GetOStream(
Statistics1) <<
" num colors: " << aggregates->GetGraphNumColors() << std::endl;
318 LO numNonAggregatedNodes = numRows;
319 GO numGlobalAggregatedPrev = 0, numGlobalAggsPrev = 0;
320 for (
size_t a = 0; a < algos_.size(); a++) {
321 std::string phase = algos_[a]->description();
322 SubFactoryMonitor sfm(*
this,
"Algo \"" + phase +
"\"", currentLevel);
324 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
325 algos_[a]->BuildAggregates(pL, *graph, *aggregates, aggStat, numNonAggregatedNodes);
326 algos_[a]->SetProcRankVerbose(oldRank);
329 GO numLocalAggregated = numRows - numNonAggregatedNodes, numGlobalAggregated = 0;
330 GO numLocalAggs = aggregates->GetNumAggregates(), numGlobalAggs = 0;
331 MueLu_sumAll(comm, numLocalAggregated, numGlobalAggregated);
334 double aggPercent = 100*as<double>(numGlobalAggregated)/as<double>(numGlobalRows);
335 if (aggPercent > 99.99 && aggPercent < 100.00) {
342 GetOStream(
Statistics1) <<
" aggregated : " << (numGlobalAggregated - numGlobalAggregatedPrev) <<
" (phase), " << std::fixed
343 << std::setprecision(2) << numGlobalAggregated <<
"/" << numGlobalRows <<
" [" << aggPercent <<
"%] (total)\n"
344 <<
" remaining : " << numGlobalRows - numGlobalAggregated <<
"\n"
345 <<
" aggregates : " << numGlobalAggs-numGlobalAggsPrev <<
" (phase), " << numGlobalAggs <<
" (total)" << std::endl;
346 numGlobalAggregatedPrev = numGlobalAggregated;
347 numGlobalAggsPrev = numGlobalAggs;
351 TEUCHOS_TEST_FOR_EXCEPTION(numNonAggregatedNodes, Exceptions::RuntimeError,
"MueLu::UncoupledAggregationFactory::Build: Leftover nodes found! Error!");
353 aggregates->AggregatesCrossProcessors(
false);
354 aggregates->ComputeAggregateSizes(
true);
356 Set(currentLevel,
"Aggregates", aggregates);
358 GetOStream(
Statistics1) << aggregates->description() << std::endl;
363 #endif // HAVE_MUELU_KOKKOS_REFACTOR
#define MueLu_sumAll(rcpComm, in, out)
void deep_copy(const View< DT, DP...> &dst, typename ViewTraits< DT, DP...>::const_value_type &value, typename std::enable_if< std::is_same< typename ViewTraits< DT, DP...>::specialize, void >::value >::type *=nullptr)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void parallel_for(const ExecPolicy &policy, const FunctorType &functor, const std::string &str="", typename std::enable_if< Kokkos::Impl::is_execution_policy< ExecPolicy >::value >::type *=nullptr)
#define SET_VALID_ENTRY(name)