MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_HybridAggregationFactory_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_HYBRIDAGGREGATIONFACTORY_DEF_HPP_
11 #define MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP_
12 
13 #include <Xpetra_Matrix.hpp>
14 #include <Xpetra_Map.hpp>
15 #include <Xpetra_Vector.hpp>
16 #include <Xpetra_MultiVectorFactory.hpp>
17 #include <Xpetra_VectorFactory.hpp>
18 
20 
21 // Uncoupled Agg
22 #include "MueLu_InterfaceAggregationAlgorithm.hpp"
23 #include "MueLu_OnePtAggregationAlgorithm.hpp"
24 #include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
25 
26 #include "MueLu_AggregationPhase1Algorithm.hpp"
27 #include "MueLu_AggregationPhase2aAlgorithm.hpp"
28 #include "MueLu_AggregationPhase2bAlgorithm.hpp"
29 #include "MueLu_AggregationPhase3Algorithm.hpp"
30 
31 // Structured Agg
32 #include "MueLu_AggregationStructuredAlgorithm.hpp"
33 #include "MueLu_UncoupledIndexManager.hpp"
34 //#include "MueLu_LocalLexicographicIndexManager.hpp"
35 //#include "MueLu_GlobalLexicographicIndexManager.hpp"
36 
37 // Shared
38 #include "MueLu_Level.hpp"
39 #include "MueLu_LWGraph.hpp"
40 #include "MueLu_Aggregates.hpp"
41 #include "MueLu_MasterList.hpp"
42 #include "MueLu_Monitor.hpp"
43 
44 namespace MueLu {
45 
46 template <class LocalOrdinal, class GlobalOrdinal, class Node>
49  : bDefinitionPhase_(true) {}
50 
51 template <class LocalOrdinal, class GlobalOrdinal, class Node>
54  RCP<ParameterList> validParamList = rcp(new ParameterList());
55 
56 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
57  // From UncoupledAggregationFactory
58  SET_VALID_ENTRY("aggregation: max agg size");
59  SET_VALID_ENTRY("aggregation: min agg size");
60  SET_VALID_ENTRY("aggregation: max selected neighbors");
61  SET_VALID_ENTRY("aggregation: ordering");
62  validParamList->getEntry("aggregation: ordering").setValidator(rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("natural", "graph", "random"))));
63  SET_VALID_ENTRY("aggregation: enable phase 1");
64  SET_VALID_ENTRY("aggregation: enable phase 2a");
65  SET_VALID_ENTRY("aggregation: enable phase 2b");
66  SET_VALID_ENTRY("aggregation: enable phase 3");
67  SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
68  SET_VALID_ENTRY("aggregation: allow user-specified singletons");
69  SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
70  SET_VALID_ENTRY("aggregation: match ML phase1");
71  SET_VALID_ENTRY("aggregation: match ML phase2a");
72  SET_VALID_ENTRY("aggregation: match ML phase2b");
73  SET_VALID_ENTRY("aggregation: phase2a agg factor");
74  SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
75 
76  // From StructuredAggregationFactory
77  SET_VALID_ENTRY("aggregation: coarsening rate");
78  SET_VALID_ENTRY("aggregation: coarsening order");
79  SET_VALID_ENTRY("aggregation: number of spatial dimensions");
80 
81  // From HybridAggregationFactory
82  SET_VALID_ENTRY("aggregation: use interface aggregation");
83 #undef SET_VALID_ENTRY
84 
85  /* From UncoupledAggregation */
86  // general variables needed in AggregationFactory
87  validParamList->set<RCP<const FactoryBase> >("Graph", null, "Generating factory of the graph");
88  validParamList->set<RCP<const FactoryBase> >("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
89  // special variables necessary for OnePtAggregationAlgorithm
90  validParamList->set<std::string>("OnePt aggregate map name", "",
91  "Name of input map for single node aggregates. (default='')");
92  validParamList->set<std::string>("OnePt aggregate map factory", "",
93  "Generating factory of (DOF) map for single node aggregates.");
94 
95  // InterfaceAggregation parameters
96  validParamList->set<std::string>("Interface aggregate map name", "",
97  "Name of input map for interface aggregates. (default='')");
98  validParamList->set<std::string>("Interface aggregate map factory", "",
99  "Generating factory of (DOF) map for interface aggregates.");
100  validParamList->set<RCP<const FactoryBase> >("interfacesDimensions", Teuchos::null,
101  "Describes the dimensions of all the interfaces on this rank.");
102  validParamList->set<RCP<const FactoryBase> >("nodeOnInterface", Teuchos::null,
103  "List the LIDs of the nodes on any interface.");
104 
105  /* From StructuredAggregation */
106  // general variables needed in AggregationFactory
107  validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
108  "Number of spatial dimension provided by CoordinatesTransferFactory.");
109  validParamList->set<RCP<const FactoryBase> >("lNodesPerDim", Teuchos::null,
110  "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
111 
112  // Hybrid Aggregation Params
113  validParamList->set<RCP<const FactoryBase> >("aggregationRegionType", Teuchos::null,
114  "Type of aggregation to use on the region (\"structured\" or \"uncoupled\")");
115 
116  return validParamList;
117 }
118 
119 template <class LocalOrdinal, class GlobalOrdinal, class Node>
121  DeclareInput(Level& currentLevel) const {
122  Input(currentLevel, "Graph");
123 
124  ParameterList pL = GetParameterList();
125 
126  /* StructuredAggregation */
127 
128  // Request the local number of nodes per dimensions
129  if (currentLevel.GetLevelID() == 0) {
130  if (currentLevel.IsAvailable("aggregationRegionType", NoFactory::get())) {
131  currentLevel.DeclareInput("aggregationRegionType", NoFactory::get(), this);
132  } else {
133  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("aggregationRegionType", NoFactory::get()),
135  "Aggregation region type was not provided by the user!");
136  }
137  if (currentLevel.IsAvailable("numDimensions", NoFactory::get())) {
138  currentLevel.DeclareInput("numDimensions", NoFactory::get(), this);
139  } else {
140  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("numDimensions", NoFactory::get()),
142  "numDimensions was not provided by the user on level0!");
143  }
144  if (currentLevel.IsAvailable("lNodesPerDim", NoFactory::get())) {
145  currentLevel.DeclareInput("lNodesPerDim", NoFactory::get(), this);
146  } else {
147  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get()),
149  "lNodesPerDim was not provided by the user on level0!");
150  }
151  } else {
152  Input(currentLevel, "aggregationRegionType");
153  Input(currentLevel, "numDimensions");
154  Input(currentLevel, "lNodesPerDim");
155  }
156 
157  /* UncoupledAggregation */
158  Input(currentLevel, "DofsPerNode");
159 
160  // request special data necessary for InterfaceAggregation
161  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
162  if (currentLevel.GetLevelID() == 0) {
163  if (currentLevel.IsAvailable("interfacesDimensions", NoFactory::get())) {
164  currentLevel.DeclareInput("interfacesDimensions", NoFactory::get(), this);
165  } else {
166  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("interfacesDimensions", NoFactory::get()),
168  "interfacesDimensions was not provided by the user on level0!");
169  }
170  if (currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
171  currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
172  } else {
173  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
175  "nodeOnInterface was not provided by the user on level0!");
176  }
177  } else {
178  Input(currentLevel, "interfacesDimensions");
179  Input(currentLevel, "nodeOnInterface");
180  }
181  }
182 
183  // request special data necessary for OnePtAggregationAlgorithm
184  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
185  if (mapOnePtName.length() > 0) {
186  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
187  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
188  currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
189  } else {
190  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
191  currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
192  }
193  }
194 } // DeclareInput()
195 
196 template <class LocalOrdinal, class GlobalOrdinal, class Node>
198  Build(Level& currentLevel) const {
199  FactoryMonitor m(*this, "Build", currentLevel);
200 
202  if (const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
203  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
204  out->setShowAllFrontMatter(false).setShowProcRank(true);
205  } else {
206  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
207  }
208 
209  *out << "Entering hybrid aggregation" << std::endl;
210 
211  ParameterList pL = GetParameterList();
212  bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
213 
214  if (pL.get<int>("aggregation: max agg size") == -1)
215  pL.set("aggregation: max agg size", INT_MAX);
216 
217  // define aggregation algorithms
218  RCP<const FactoryBase> graphFact = GetFactory("Graph");
219 
220  // General problem informations are gathered from data stored in the problem matix.
221  RCP<const LWGraph> graph = Get<RCP<LWGraph> >(currentLevel, "Graph");
222  RCP<const Map> fineMap = graph->GetDomainMap();
223  const int myRank = fineMap->getComm()->getRank();
224  const int numRanks = fineMap->getComm()->getSize();
225 
226  out->setProcRankAndSize(graph->GetImportMap()->getComm()->getRank(),
227  graph->GetImportMap()->getComm()->getSize());
228 
229  // Build aggregates
230  RCP<Aggregates> aggregates = rcp(new Aggregates(*graph));
231  aggregates->setObjectLabel("HB");
232 
233  // construct aggStat information
234  const LO numRows = graph->GetNodeNumVertices();
236  AggStatHostType aggStat(Kokkos::ViewAllocateWithoutInitializing("aggregation status"), numRows);
237  Kokkos::deep_copy(aggStat, READY);
238 
239  // Get aggregation type for region
240  std::string regionType;
241  if (currentLevel.GetLevelID() == 0) {
242  // On level 0, data is provided by applications and has no associated factory.
243  regionType = currentLevel.Get<std::string>("aggregationRegionType", NoFactory::get());
244  } else {
245  // On level > 0, data is provided directly by generating factories.
246  regionType = Get<std::string>(currentLevel, "aggregationRegionType");
247  }
248 
249  int numDimensions = 0;
250  if (currentLevel.GetLevelID() == 0) {
251  // On level 0, data is provided by applications and has no associated factory.
252  numDimensions = currentLevel.Get<int>("numDimensions", NoFactory::get());
253  } else {
254  // On level > 0, data is provided directly by generating factories.
255  numDimensions = Get<int>(currentLevel, "numDimensions");
256  }
257 
258  // Get the coarsening rate (potentially used for both structured and uncoupled aggregation if interface)
259  std::string coarseningRate = pL.get<std::string>("aggregation: coarsening rate");
260  Teuchos::Array<LO> coarseRate;
261  try {
262  coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
263  } catch (const Teuchos::InvalidArrayStringRepresentation& e) {
264  GetOStream(Errors, -1) << " *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
265  << std::endl;
266  throw e;
267  }
268  TEUCHOS_TEST_FOR_EXCEPTION((coarseRate.size() > 1) && (coarseRate.size() < numDimensions),
270  "\"aggregation: coarsening rate\" must have at least as many"
271  " components as the number of spatial dimensions in the problem.");
272 
273  algos_.clear();
274  LO numNonAggregatedNodes = numRows;
275  if (regionType == "structured") {
276  // Add AggregationStructuredAlgorithm
277  algos_.push_back(rcp(new AggregationStructuredAlgorithm(graphFact)));
278 
279  // Since we want to operate on nodes and not dof, we need to modify the rowMap in order to
280  // obtain a nodeMap.
281  const int interpolationOrder = pL.get<int>("aggregation: coarsening order");
282  Array<LO> lFineNodesPerDir(3);
283  if (currentLevel.GetLevelID() == 0) {
284  // On level 0, data is provided by applications and has no associated factory.
285  lFineNodesPerDir = currentLevel.Get<Array<LO> >("lNodesPerDim", NoFactory::get());
286  } else {
287  // On level > 0, data is provided directly by generating factories.
288  lFineNodesPerDir = Get<Array<LO> >(currentLevel, "lNodesPerDim");
289  }
290 
291  // Set lFineNodesPerDir to 1 for directions beyond numDimensions
292  for (int dim = numDimensions; dim < 3; ++dim) {
293  lFineNodesPerDir[dim] = 1;
294  }
295 
296  // Now that we have extracted info from the level, create the IndexManager
298  geoData = rcp(new MueLu::UncoupledIndexManager<LO, GO, NO>(fineMap->getComm(),
299  false,
300  numDimensions,
301  interpolationOrder,
302  myRank,
303  numRanks,
304  Array<GO>(3, -1),
305  lFineNodesPerDir,
306  coarseRate, false));
307 
308  TEUCHOS_TEST_FOR_EXCEPTION(fineMap->getLocalNumElements() != static_cast<size_t>(geoData->getNumLocalFineNodes()),
310  "The local number of elements in the graph's map is not equal to "
311  "the number of nodes given by: lNodesPerDim!");
312 
313  aggregates->SetIndexManager(geoData);
314  aggregates->SetNumAggregates(geoData->getNumLocalCoarseNodes());
315 
316  Set(currentLevel, "lCoarseNodesPerDim", geoData->getLocalCoarseNodesPerDir());
317 
318  } // end structured aggregation setup
319 
320  if (regionType == "uncoupled") {
321  // Add unstructred aggregation phases
322  algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
323  if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm(graphFact)));
324  if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm(graphFact)));
325  if (pL.get<bool>("aggregation: enable phase 1") == true) algos_.push_back(rcp(new AggregationPhase1Algorithm(graphFact)));
326  if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm(graphFact)));
327  if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm(graphFact)));
328  if (pL.get<bool>("aggregation: enable phase 3") == true) algos_.push_back(rcp(new AggregationPhase3Algorithm(graphFact)));
329 
330  *out << " Build interface aggregates" << std::endl;
331  // interface
332  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
333  BuildInterfaceAggregates(currentLevel, aggregates, aggStat, numNonAggregatedNodes,
334  coarseRate);
335  }
336 
337  *out << "Treat Dirichlet BC" << std::endl;
338  // Dirichlet boundary
339  auto dirichletBoundaryMap = graph->GetBoundaryNodeMap();
340  for (LO i = 0; i < numRows; i++)
341  if (dirichletBoundaryMap[i] == true)
342  aggStat[i] = BOUNDARY;
343 
344  // OnePt aggregation
345  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
346  RCP<Map> OnePtMap = Teuchos::null;
347  if (mapOnePtName.length()) {
348  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
349  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
350  OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, NoFactory::get());
351  } else {
352  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
353  OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
354  }
355  }
356 
357  LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
358  GO indexBase = graph->GetDomainMap()->getIndexBase();
359  if (OnePtMap != Teuchos::null) {
360  for (LO i = 0; i < numRows; i++) {
361  // reconstruct global row id (FIXME only works for contiguous maps)
362  GO grid = (graph->GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
363  for (LO kr = 0; kr < nDofsPerNode; kr++)
364  if (OnePtMap->isNodeGlobalElement(grid + kr))
365  aggStat[i] = ONEPT;
366  }
367  }
368 
369  // Create a fake lCoarseNodesPerDir for CoordinatesTranferFactory
370  Array<LO> lCoarseNodesPerDir(3, -1);
371  Set(currentLevel, "lCoarseNodesPerDim", lCoarseNodesPerDir);
372  } // end uncoupled aggregation setup
373 
374  aggregates->AggregatesCrossProcessors(false); // No coupled aggregation
375 
376  *out << "Run all the algorithms on the local rank" << std::endl;
377  for (size_t a = 0; a < algos_.size(); a++) {
378  std::string phase = algos_[a]->description();
379  SubFactoryMonitor sfm(*this, "Algo \"" + phase + "\"", currentLevel);
380  *out << regionType << " | Executing phase " << a << std::endl;
381 
382  int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
383  algos_[a]->BuildAggregatesNonKokkos(pL, *graph, *aggregates, aggStat, numNonAggregatedNodes);
384  algos_[a]->SetProcRankVerbose(oldRank);
385  *out << regionType << " | Done Executing phase " << a << std::endl;
386  }
387 
388  *out << "Compute statistics on aggregates" << std::endl;
389  aggregates->ComputeAggregateSizes(true /*forceRecompute*/);
390 
391  Set(currentLevel, "Aggregates", aggregates);
392  Set(currentLevel, "numDimensions", numDimensions);
393  Set(currentLevel, "aggregationRegionTypeCoarse", regionType);
394 
395  GetOStream(Statistics1) << aggregates->description() << std::endl;
396  *out << "HybridAggregation done!" << std::endl;
397 }
398 
399 template <class LocalOrdinal, class GlobalOrdinal, class Node>
403  Array<LO> coarseRate) const {
404  FactoryMonitor m(*this, "BuildInterfaceAggregates", currentLevel);
405 
407  if (const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
408  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
409  out->setShowAllFrontMatter(false).setShowProcRank(true);
410  } else {
411  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
412  }
413 
414  // Extract and format input data for algo
415  if (coarseRate.size() == 1) {
416  coarseRate.resize(3, coarseRate[0]);
417  }
418  ArrayRCP<LO> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
419  ArrayRCP<LO> procWinner = aggregates->GetProcWinner()->getDataNonConst(0);
420  Array<LO> interfacesDimensions = Get<Array<LO> >(currentLevel, "interfacesDimensions");
421  Array<LO> nodesOnInterfaces = Get<Array<LO> >(currentLevel, "nodeOnInterface");
422  const int numInterfaces = interfacesDimensions.size() / 3;
423  const int myRank = aggregates->GetMap()->getComm()->getRank();
424 
425  // Create coarse level container to gather data on the fly
426  Array<LO> coarseInterfacesDimensions(interfacesDimensions.size());
427  Array<LO> nodesOnCoarseInterfaces;
428  { // Scoping the temporary variables...
429  LO endRate, totalNumCoarseNodes = 0, numCoarseNodes;
430  for (int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
431  numCoarseNodes = 1;
432  for (int dim = 0; dim < 3; ++dim) {
433  endRate = (interfacesDimensions[3 * interfaceIdx + dim] - 1) % coarseRate[dim];
434  if (interfacesDimensions[3 * interfaceIdx + dim] == 1) {
435  coarseInterfacesDimensions[3 * interfaceIdx + dim] = 1;
436  } else {
437  coarseInterfacesDimensions[3 * interfaceIdx + dim] = (interfacesDimensions[3 * interfaceIdx + dim] - 1) / coarseRate[dim] + 2;
438  if (endRate == 0) {
439  coarseInterfacesDimensions[3 * interfaceIdx + dim]--;
440  }
441  }
442  numCoarseNodes *= coarseInterfacesDimensions[3 * interfaceIdx + dim];
443  }
444  totalNumCoarseNodes += numCoarseNodes;
445  }
446  nodesOnCoarseInterfaces.resize(totalNumCoarseNodes, -1);
447  }
448 
449  Array<LO> endRate(3);
450  LO interfaceOffset = 0, aggregateCount = 0, coarseNodeCount = 0;
451  for (int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
452  ArrayView<LO> fineNodesPerDim = interfacesDimensions(3 * interfaceIdx, 3);
453  ArrayView<LO> coarseNodesPerDim = coarseInterfacesDimensions(3 * interfaceIdx, 3);
454  LO numInterfaceNodes = 1, numCoarseNodes = 1;
455  for (int dim = 0; dim < 3; ++dim) {
456  numInterfaceNodes *= fineNodesPerDim[dim];
457  numCoarseNodes *= coarseNodesPerDim[dim];
458  endRate[dim] = (fineNodesPerDim[dim] - 1) % coarseRate[dim];
459  }
460  ArrayView<LO> interfaceNodes = nodesOnInterfaces(interfaceOffset, numInterfaceNodes);
461 
462  interfaceOffset += numInterfaceNodes;
463 
464  LO rem, rate, fineNodeIdx;
465  Array<LO> nodeIJK(3), coarseIJK(3), rootIJK(3);
466  // First find treat coarse nodes as they generate the aggregate IDs
467  // and they might be repeated on multiple interfaces (think corners and edges).
468  for (LO coarseNodeIdx = 0; coarseNodeIdx < numCoarseNodes; ++coarseNodeIdx) {
469  coarseIJK[2] = coarseNodeIdx / (coarseNodesPerDim[0] * coarseNodesPerDim[1]);
470  rem = coarseNodeIdx % (coarseNodesPerDim[0] * coarseNodesPerDim[1]);
471  coarseIJK[1] = rem / coarseNodesPerDim[0];
472  coarseIJK[0] = rem % coarseNodesPerDim[0];
473 
474  for (LO dim = 0; dim < 3; ++dim) {
475  if (coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
476  nodeIJK[dim] = fineNodesPerDim[dim] - 1;
477  } else {
478  nodeIJK[dim] = coarseIJK[dim] * coarseRate[dim];
479  }
480  }
481  fineNodeIdx = (nodeIJK[2] * fineNodesPerDim[1] + nodeIJK[1]) * fineNodesPerDim[0] + nodeIJK[0];
482 
483  if (aggStat[interfaceNodes[fineNodeIdx]] == READY) {
484  vertex2AggId[interfaceNodes[fineNodeIdx]] = aggregateCount;
485  procWinner[interfaceNodes[fineNodeIdx]] = myRank;
486  aggStat[interfaceNodes[fineNodeIdx]] = AGGREGATED;
487  ++aggregateCount;
488  --numNonAggregatedNodes;
489  }
490  nodesOnCoarseInterfaces[coarseNodeCount] = vertex2AggId[interfaceNodes[fineNodeIdx]];
491  ++coarseNodeCount;
492  }
493 
494  // Now loop over all the node on the interface
495  // skip the coarse nodes as they are already aggregated
496  // and find the appropriate aggregate ID for the fine nodes.
497  for (LO nodeIdx = 0; nodeIdx < numInterfaceNodes; ++nodeIdx) {
498  // If the node is already aggregated skip it!
499  if (aggStat[interfaceNodes[nodeIdx]] == AGGREGATED) {
500  continue;
501  }
502 
503  nodeIJK[2] = nodeIdx / (fineNodesPerDim[0] * fineNodesPerDim[1]);
504  rem = nodeIdx % (fineNodesPerDim[0] * fineNodesPerDim[1]);
505  nodeIJK[1] = rem / fineNodesPerDim[0];
506  nodeIJK[0] = rem % fineNodesPerDim[0];
507 
508  for (int dim = 0; dim < 3; ++dim) {
509  coarseIJK[dim] = nodeIJK[dim] / coarseRate[dim];
510  rem = nodeIJK[dim] % coarseRate[dim];
511  if (nodeIJK[dim] < fineNodesPerDim[dim] - endRate[dim]) {
512  rate = coarseRate[dim];
513  } else {
514  rate = endRate[dim];
515  }
516  if (rem > (rate / 2)) {
517  ++coarseIJK[dim];
518  }
519  }
520 
521  for (LO dim = 0; dim < 3; ++dim) {
522  if (coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
523  nodeIJK[dim] = fineNodesPerDim[dim] - 1;
524  } else {
525  nodeIJK[dim] = coarseIJK[dim] * coarseRate[dim];
526  }
527  }
528  fineNodeIdx = (nodeIJK[2] * fineNodesPerDim[1] + nodeIJK[1]) * fineNodesPerDim[0] + nodeIJK[0];
529 
530  vertex2AggId[interfaceNodes[nodeIdx]] = vertex2AggId[interfaceNodes[fineNodeIdx]];
531  procWinner[interfaceNodes[nodeIdx]] = myRank;
532  aggStat[interfaceNodes[nodeIdx]] = AGGREGATED;
533  --numNonAggregatedNodes;
534  } // Loop over interface nodes
535  } // Loop over the interfaces
536 
537  // Update aggregates information before subsequent aggregation algorithms
538  aggregates->SetNumAggregates(aggregateCount);
539 
540  // Set coarse data for next level
541  Set(currentLevel, "coarseInterfacesDimensions", coarseInterfacesDimensions);
542  Set(currentLevel, "nodeOnCoarseInterface", nodesOnCoarseInterfaces);
543 
544 } // BuildInterfaceAggregates()
545 
546 } // namespace MueLu
547 
548 #endif /* MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP */
Kokkos::View< unsigned *, typename LWGraphHostType::device_type > AggStatHostType
basic_FancyOStream & setProcRankAndSize(const int procRank, const int numProcs)
Algorithm for coarsening a graph with uncoupled aggregation. keep special marked nodes as singleton n...
const RCP< LOVector > & GetProcWinner() const
Returns constant vector that maps local node IDs to owning processor IDs.
Container class for aggregation information.
void setValidator(RCP< const ParameterEntryValidator > const &validator)
basic_FancyOStream & setShowProcRank(const bool showProcRank)
GlobalOrdinal GO
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 BuildInterfaceAggregates(Level &currentLevel, RCP< Aggregates > aggregates, typename AggregationAlgorithmBase< LocalOrdinal, GlobalOrdinal, Node >::AggStatHostType &aggStat, LO &numNonAggregatedNodes, Array< LO > coarseRate) const
Specifically build aggregates along interfaces.
const RCP< const Map > GetMap() const
returns (overlapping) map of aggregate/node distribution
LocalOrdinal LO
T * get() const
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
KOKKOS_INLINE_FUNCTION const boundary_nodes_type GetBoundaryNodeMap() const
Returns map with global ids of boundary nodes.
void SetIndexManager(RCP< IndexManager > &geoData)
Set the index manager used by various aggregation algorithms. This has to be done by the aggregation ...
static const NoFactory * get()
Algorithm for coarsening a graph with uncoupled aggregation. creates aggregates along an interface us...
Builds one-to-one aggregates for all Dirichlet boundary nodes. For some applications this might be ne...
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
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
virtual void setObjectLabel(const std::string &objectLabel)
basic_FancyOStream & setShowAllFrontMatter(const bool showAllFrontMatter)
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
void resize(size_type new_size, const value_type &x=value_type())
const RCP< const Map > GetImportMap() const
Return overlapping import map (nodes).
void Build(Level &currentLevel) const
Build aggregates.
Among unaggregated points, see if we can make a reasonable size aggregate out of it.IdeaAmong unaggregated points, see if we can make a reasonable size aggregate out of it. We do this by looking at neighbors and seeing how many are unaggregated and on my processor. Loosely, base the number of new aggregates created on the percentage of unaggregated nodes.
size_type size() const
Add leftovers to existing aggregatesIdeaIn phase 2b non-aggregated nodes are added to existing aggreg...
void DeclareInput(Level &currentLevel) const
Input.
const RCP< const Map > GetDomainMap() const
KOKKOS_INLINE_FUNCTION void AggregatesCrossProcessors(const bool &flag)
Record whether aggregates include DOFs from other processes.
Algorithm for coarsening a graph with uncoupled aggregation.
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:51
Exception throws to report errors in the internal logical of the program.
Handle leftover nodes. Try to avoid singleton nodesIdeaIn phase 3 we try to stick unaggregated nodes ...
#define SET_VALID_ENTRY(name)
ParameterEntry & getEntry(const std::string &name)
std::string description() const
Return a simple one-line description of this object.
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.