MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_StructuredAggregationFactory_kokkos_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef MUELU_STRUCTUREDAGGREGATIONFACTORY_KOKKOS_DEF_HPP
11 #define MUELU_STRUCTUREDAGGREGATIONFACTORY_KOKKOS_DEF_HPP
12 
13 // Xpetra includes
14 #include <Xpetra_Map.hpp>
15 #include <Xpetra_CrsGraph.hpp>
16 
17 // MueLu generic includes
18 #include "MueLu_Level.hpp"
19 #include "MueLu_MasterList.hpp"
20 #include "MueLu_Monitor.hpp"
21 
22 // MueLu specific includes (kokkos version)
23 #include "MueLu_LWGraph_kokkos.hpp"
24 #include "MueLu_Aggregates.hpp"
25 #include "MueLu_IndexManager_kokkos.hpp"
26 #include "MueLu_AggregationStructuredAlgorithm.hpp"
27 
29 
30 namespace MueLu {
31 
32 template <class LocalOrdinal, class GlobalOrdinal, class Node>
35  : bDefinitionPhase_(true) {}
36 
37 template <class LocalOrdinal, class GlobalOrdinal, class Node>
40  RCP<ParameterList> validParamList = rcp(new ParameterList());
41 
42 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
43  SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
44  SET_VALID_ENTRY("aggregation: allow user-specified singletons");
45  SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
46  SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
47 #undef SET_VALID_ENTRY
48 
49  // general variables needed in StructuredAggregationFactory
50  validParamList->set<std::string>("aggregation: output type", "Aggregates",
51  "Type of object holding the aggregation data: Aggregtes or CrsGraph");
52  validParamList->set<std::string>("aggregation: coarsening rate", "{3}",
53  "Coarsening rate per spatial dimensions");
54  validParamList->set<int>("aggregation: coarsening order", 0,
55  "The interpolation order used to construct grid transfer operators based off these aggregates.");
56  validParamList->set<RCP<const FactoryBase> >("Graph", Teuchos::null,
57  "Graph of the matrix after amalgamation but without dropping.");
58  validParamList->set<RCP<const FactoryBase> >("DofsPerNode", Teuchos::null,
59  "Number of degrees of freedom per mesh node, provided by the coalsce drop factory.");
60  validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
61  "Number of spatial dimension provided by CoordinatesTransferFactory.");
62  validParamList->set<RCP<const FactoryBase> >("lNodesPerDim", Teuchos::null,
63  "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
64 
65  return validParamList;
66 } // GetValidParameterList()
67 
68 template <class LocalOrdinal, class GlobalOrdinal, class Node>
70  DeclareInput(Level& currentLevel) const {
71  Input(currentLevel, "Graph");
72  Input(currentLevel, "DofsPerNode");
73 
74  // Request the local number of nodes per dimensions
75  if (currentLevel.GetLevelID() == 0) {
76  if (currentLevel.IsAvailable("numDimensions", NoFactory::get())) {
77  currentLevel.DeclareInput("numDimensions", NoFactory::get(), this);
78  } else {
79  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("numDimensions", NoFactory::get()),
81  "numDimensions was not provided by the user on level0!");
82  }
83  if (currentLevel.IsAvailable("lNodesPerDim", NoFactory::get())) {
84  currentLevel.DeclareInput("lNodesPerDim", NoFactory::get(), this);
85  } else {
86  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get()),
88  "lNodesPerDim was not provided by the user on level0!");
89  }
90  } else {
91  Input(currentLevel, "lNodesPerDim");
92  Input(currentLevel, "numDimensions");
93  }
94 } // DeclareInput()
95 
96 template <class LocalOrdinal, class GlobalOrdinal, class Node>
98  Build(Level& currentLevel) const {
99  FactoryMonitor m(*this, "Build", currentLevel);
100 
102  if (const char* dbg = std::getenv("MUELU_STRUCTUREDAGGREGATION_DEBUG")) {
103  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
104  out->setShowAllFrontMatter(false).setShowProcRank(true);
105  } else {
106  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
107  }
108 
109  using device_type = typename LWGraph_kokkos::local_graph_type::device_type;
110  using execution_space = typename LWGraph_kokkos::local_graph_type::device_type::execution_space;
111  using memory_space = typename LWGraph_kokkos::local_graph_type::device_type::memory_space;
112 
113  *out << "Entering structured aggregation" << std::endl;
114 
115  ParameterList pL = GetParameterList();
116  bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
117 
118  // General problem informations are gathered from data stored in the problem matix.
119  RCP<const LWGraph_kokkos> graph = Get<RCP<LWGraph_kokkos> >(currentLevel, "Graph");
120  RCP<const Map> fineMap = graph->GetDomainMap();
121  const int myRank = fineMap->getComm()->getRank();
122  const LO dofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
123 
124  // Since we want to operate on nodes and not dof, we need to modify the rowMap in order to
125  // obtain a nodeMap.
126  const int interpolationOrder = pL.get<int>("aggregation: coarsening order");
127  std::string outputType = pL.get<std::string>("aggregation: output type");
128  const bool outputAggregates = (outputType == "Aggregates" ? true : false);
129  Array<LO> lFineNodesPerDir(3);
130  int numDimensions;
131  if (currentLevel.GetLevelID() == 0) {
132  // On level 0, data is provided by applications and has no associated factory.
133  lFineNodesPerDir = currentLevel.Get<Array<LO> >("lNodesPerDim", NoFactory::get());
134  numDimensions = currentLevel.Get<int>("numDimensions", NoFactory::get());
135  } else {
136  // On level > 0, data is provided directly by generating factories.
137  lFineNodesPerDir = Get<Array<LO> >(currentLevel, "lNodesPerDim");
138  numDimensions = Get<int>(currentLevel, "numDimensions");
139  }
140 
141  // First make sure that input parameters are set logically based on dimension
142  for (int dim = 0; dim < 3; ++dim) {
143  if (dim >= numDimensions) {
144  lFineNodesPerDir[dim] = 1;
145  }
146  }
147 
148  // Get the coarsening rate
149  std::string coarseningRate = pL.get<std::string>("aggregation: coarsening rate");
150  Teuchos::Array<LO> coarseRate;
151  try {
152  coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
153  } catch (const Teuchos::InvalidArrayStringRepresentation& e) {
154  GetOStream(Errors, -1) << " *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
155  << std::endl;
156  throw e;
157  }
158  TEUCHOS_TEST_FOR_EXCEPTION((coarseRate.size() > 1) && (coarseRate.size() < numDimensions),
160  "\"aggregation: coarsening rate\" must have at least as many"
161  " components as the number of spatial dimensions in the problem.");
162 
163  // Now that we have extracted info from the level, create the IndexManager
164  RCP<IndexManager_kokkos> geoData = rcp(new IndexManager_kokkos(numDimensions,
165  interpolationOrder, myRank,
166  lFineNodesPerDir,
167  coarseRate));
168 
169  *out << "The index manager has now been built" << std::endl;
170  TEUCHOS_TEST_FOR_EXCEPTION(fineMap->getLocalNumElements() != static_cast<size_t>(geoData->getNumLocalFineNodes()),
172  "The local number of elements in the graph's map is not equal to "
173  "the number of nodes given by: lNodesPerDim!");
174 
175  // Now we are ready for the big loop over the fine node that will assign each
176  // node on the fine grid to an aggregate and a processor.
178 
179  if (interpolationOrder == 0 && outputAggregates) {
180  RCP<Aggregates> aggregates = rcp(new Aggregates(graph->GetDomainMap()));
181  aggregates->setObjectLabel("ST");
182  aggregates->SetIndexManagerKokkos(geoData);
183  aggregates->AggregatesCrossProcessors(false);
184  aggregates->SetNumAggregates(geoData->getNumCoarseNodes());
185 
186  LO numNonAggregatedNodes = geoData->getNumLocalFineNodes();
187  Kokkos::View<unsigned*, device_type> aggStat("aggStat", numNonAggregatedNodes);
188  Kokkos::parallel_for(
189  "StructuredAggregation: initialize aggStat",
190  Kokkos::RangePolicy<execution_space>(0, numNonAggregatedNodes),
191  KOKKOS_LAMBDA(const LO nodeIdx) { aggStat(nodeIdx) = READY; });
192 
193  myStructuredAlgorithm->BuildAggregates(pL, *graph, *aggregates, aggStat,
194  numNonAggregatedNodes);
195 
196  *out << "numNonAggregatedNodes: " << numNonAggregatedNodes << std::endl;
197 
199  "MueLu::StructuredAggregationFactory::Build: Leftover nodes found! Error!");
200  aggregates->ComputeAggregateSizes(true /*forceRecompute*/);
201  GetOStream(Statistics1) << aggregates->description() << std::endl;
202  Set(currentLevel, "Aggregates", aggregates);
203 
204  } else {
205  // Create Coarse Data
206  RCP<CrsGraph> myGraph;
207  myStructuredAlgorithm->BuildGraph(*graph, geoData, dofsPerNode, myGraph);
208  Set(currentLevel, "prolongatorGraph", myGraph);
209  }
210 
211  Set(currentLevel, "lCoarseNodesPerDim", geoData->getCoarseNodesPerDirArray());
212  Set(currentLevel, "indexManager", geoData);
213  Set(currentLevel, "structuredInterpolationOrder", interpolationOrder);
214  Set(currentLevel, "numDimensions", numDimensions);
215 
216 } // Build()
217 
218 } // namespace MueLu
219 
220 #endif /* MUELU_STRUCTUREDAGGREGATIONFACTORY_KOKKOS_DEF_HPP */
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void SetIndexManagerKokkos(RCP< IndexManager_kokkos > &geoDataKokkos)
Set the index manager used by structured aggregation algorithms. This has to be done by the aggregati...
Container class for aggregation information.
basic_FancyOStream & setShowProcRank(const bool showProcRank)
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Algorithm for coarsening a graph with structured aggregation.
Print more statistics.
void Build(Level &currentLevel) const
Build aggregates.
LocalOrdinal LO
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
static const NoFactory * get()
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
void BuildAggregates(const Teuchos::ParameterList &params, const LWGraph_kokkos &graph, Aggregates &aggregates, typename AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node >::AggStatType &aggStat, LO &numNonAggregatedNodes) const
Build aggregates object.
virtual void setObjectLabel(const std::string &objectLabel)
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
const RCP< const Map > GetDomainMap() const
KOKKOS_INLINE_FUNCTION void AggregatesCrossProcessors(const bool &flag)
Record whether aggregates include DOFs from other processes.
Container class for mesh layout and indices calculation.
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:51
Exception throws to report errors in the internal logical of the program.
void BuildGraph(const LWGraph_kokkos &graph, RCP< IndexManager_kokkos > &geoData, const LO dofsPerNode, RCP< CrsGraph > &myGraph) const
Build a CrsGraph instead of aggregates.
std::string description() const
Return a simple one-line description of this object.
#define SET_VALID_ENTRY(name)
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
aggregates_sizes_type::const_type ComputeAggregateSizes(bool forceRecompute=false) const
Compute sizes of aggregates.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
void SetNumAggregates(LO nAggregates)
Set number of local aggregates on current processor.