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.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
void Set(Level &level, const std::string &varName, const T &data) const
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory().
std::vector< RCP< MueLu::AggregationAlgorithmBase< LO, GO, Node > > > algos_
aggregation algorithms
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...
virtual const Teuchos::ParameterList & GetParameterList() const
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.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
int GetProcRankVerbose() const
Get proc rank used for printing. Do not use this information for any other purpose....
Namespace for MueLu classes and methods.
@ Statistics1
Print more statistics.