MueLu Version of the Day
Loading...
Searching...
No Matches
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
44namespace MueLu {
45
46template <class LocalOrdinal, class GlobalOrdinal, class Node>
50
51template <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
119template <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
196template <class LocalOrdinal, class GlobalOrdinal, class Node>
198 Build(Level& currentLevel) const {
199 FactoryMonitor m(*this, "Build", currentLevel);
200
201 RCP<Teuchos::FancyOStream> out;
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
297 RCP<MueLu::IndexManager<LO, GO, NO> > geoData;
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
399template <class LocalOrdinal, class GlobalOrdinal, class Node>
401 BuildInterfaceAggregates(Level& currentLevel, RCP<Aggregates> aggregates,
402 typename AggregationAlgorithmBase<LocalOrdinal, GlobalOrdinal, Node>::AggStatHostType& aggStat, LO& numNonAggregatedNodes,
403 Array<LO> coarseRate) const {
404 FactoryMonitor m(*this, "BuildInterfaceAggregates", currentLevel);
405
406 RCP<Teuchos::FancyOStream> out;
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 */
#define SET_VALID_ENTRY(name)
Container class for aggregation information.
Kokkos::View< unsigned *, typename LWGraphHostType::device_type > AggStatHostType
Algorithm for coarsening a graph with uncoupled aggregation.
Among unaggregated points, see if we can make a reasonable size aggregate out of it.
Handle leftover nodes. Try to avoid singleton nodes.
Algorithm for coarsening a graph with structured aggregation.
Exception throws to report errors in the internal logical of the program.
Timer to be used in factories. Similar to Monitor but with additional timers.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
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.
void DeclareInput(Level &currentLevel) const
Input.
void Build(Level &currentLevel) const
Build aggregates.
Algorithm for coarsening a graph with uncoupled aggregation. creates aggregates along an interface us...
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
int GetLevelID() const
Return level number.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
static const NoFactory * get()
Algorithm for coarsening a graph with uncoupled aggregation. keep special marked nodes as singleton n...
Builds one-to-one aggregates for all Dirichlet boundary nodes. For some applications this might be ne...
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.