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);
206 out = Teuchos::getFancyOStream(rcp(
new Teuchos::oblackholestream()));
209 *out <<
"Entering hybrid aggregation" << std::endl;
211 ParameterList pL = GetParameterList();
212 bDefinitionPhase_ =
false;
214 if (pL.get<
int>(
"aggregation: max agg size") == -1)
215 pL.set(
"aggregation: max agg size", INT_MAX);
218 RCP<const FactoryBase> graphFact = GetFactory(
"Graph");
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();
226 out->setProcRankAndSize(graph->GetImportMap()->getComm()->getRank(),
227 graph->GetImportMap()->getComm()->getSize());
230 RCP<Aggregates> aggregates = rcp(
new Aggregates(*graph));
231 aggregates->setObjectLabel(
"HB");
234 const LO numRows = graph->GetNodeNumVertices();
236 AggStatHostType aggStat(Kokkos::ViewAllocateWithoutInitializing(
"aggregation status"), numRows);
237 Kokkos::deep_copy(aggStat,
READY);
240 std::string regionType;
243 regionType = currentLevel.
Get<std::string>(
"aggregationRegionType",
NoFactory::get());
246 regionType = Get<std::string>(currentLevel,
"aggregationRegionType");
249 int numDimensions = 0;
255 numDimensions = Get<int>(currentLevel,
"numDimensions");
259 std::string coarseningRate = pL.get<std::string>(
"aggregation: coarsening rate");
260 Teuchos::Array<LO> coarseRate;
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! *** "
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.");
274 LO numNonAggregatedNodes = numRows;
275 if (regionType ==
"structured") {
281 const int interpolationOrder = pL.get<
int>(
"aggregation: coarsening order");
282 Array<LO> lFineNodesPerDir(3);
285 lFineNodesPerDir = currentLevel.
Get<Array<LO> >(
"lNodesPerDim",
NoFactory::get());
288 lFineNodesPerDir = Get<Array<LO> >(currentLevel,
"lNodesPerDim");
292 for (
int dim = numDimensions; dim < 3; ++dim) {
293 lFineNodesPerDir[dim] = 1;
297 RCP<MueLu::IndexManager<LO, GO, NO> > geoData;
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!");
313 aggregates->SetIndexManager(geoData);
314 aggregates->SetNumAggregates(geoData->getNumLocalCoarseNodes());
316 Set(currentLevel,
"lCoarseNodesPerDim", geoData->getLocalCoarseNodesPerDir());
320 if (regionType ==
"uncoupled") {
324 if (pL.get<
bool>(
"aggregation: allow user-specified singletons") ==
true) algos_.push_back(rcp(
new OnePtAggregationAlgorithm(graphFact)));
330 *out <<
" Build interface aggregates" << std::endl;
332 if (pL.get<
bool>(
"aggregation: use interface aggregation") ==
true) {
333 BuildInterfaceAggregates(currentLevel, aggregates, aggStat, numNonAggregatedNodes,
337 *out <<
"Treat Dirichlet BC" << std::endl;
339 auto dirichletBoundaryMap = graph->GetBoundaryNodeMap();
340 for (LO i = 0; i < numRows; i++)
341 if (dirichletBoundaryMap[i] ==
true)
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") {
352 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
353 OnePtMap = currentLevel.
Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
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++) {
362 GO grid = (graph->GetDomainMap()->getGlobalElement(i) - indexBase) * nDofsPerNode + indexBase;
363 for (LO kr = 0; kr < nDofsPerNode; kr++)
364 if (OnePtMap->isNodeGlobalElement(grid + kr))
370 Array<LO> lCoarseNodesPerDir(3, -1);
371 Set(currentLevel,
"lCoarseNodesPerDim", lCoarseNodesPerDir);
374 aggregates->AggregatesCrossProcessors(
false);
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();
380 *out << regionType <<
" | Executing phase " << a << std::endl;
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;
388 *out <<
"Compute statistics on aggregates" << std::endl;
389 aggregates->ComputeAggregateSizes(
true );
391 Set(currentLevel,
"Aggregates", aggregates);
392 Set(currentLevel,
"numDimensions", numDimensions);
393 Set(currentLevel,
"aggregationRegionTypeCoarse", regionType);
395 GetOStream(
Statistics1) << aggregates->description() << std::endl;
396 *out <<
"HybridAggregation done!" << std::endl;
403 Array<LO> coarseRate)
const {
404 FactoryMonitor m(*
this,
"BuildInterfaceAggregates", currentLevel);
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);
411 out = Teuchos::getFancyOStream(rcp(
new Teuchos::oblackholestream()));
415 if (coarseRate.size() == 1) {
416 coarseRate.resize(3, coarseRate[0]);
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();
426 Array<LO> coarseInterfacesDimensions(interfacesDimensions.size());
427 Array<LO> nodesOnCoarseInterfaces;
429 LO endRate, totalNumCoarseNodes = 0, numCoarseNodes;
430 for (
int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
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;
437 coarseInterfacesDimensions[3 * interfaceIdx + dim] = (interfacesDimensions[3 * interfaceIdx + dim] - 1) / coarseRate[dim] + 2;
439 coarseInterfacesDimensions[3 * interfaceIdx + dim]--;
442 numCoarseNodes *= coarseInterfacesDimensions[3 * interfaceIdx + dim];
444 totalNumCoarseNodes += numCoarseNodes;
446 nodesOnCoarseInterfaces.resize(totalNumCoarseNodes, -1);
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];
460 ArrayView<LO> interfaceNodes = nodesOnInterfaces(interfaceOffset, numInterfaceNodes);
462 interfaceOffset += numInterfaceNodes;
464 LO rem, rate, fineNodeIdx;
465 Array<LO> nodeIJK(3), coarseIJK(3), rootIJK(3);
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];
474 for (LO dim = 0; dim < 3; ++dim) {
475 if (coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
476 nodeIJK[dim] = fineNodesPerDim[dim] - 1;
478 nodeIJK[dim] = coarseIJK[dim] * coarseRate[dim];
481 fineNodeIdx = (nodeIJK[2] * fineNodesPerDim[1] + nodeIJK[1]) * fineNodesPerDim[0] + nodeIJK[0];
483 if (aggStat[interfaceNodes[fineNodeIdx]] ==
READY) {
484 vertex2AggId[interfaceNodes[fineNodeIdx]] = aggregateCount;
485 procWinner[interfaceNodes[fineNodeIdx]] = myRank;
486 aggStat[interfaceNodes[fineNodeIdx]] =
AGGREGATED;
488 --numNonAggregatedNodes;
490 nodesOnCoarseInterfaces[coarseNodeCount] = vertex2AggId[interfaceNodes[fineNodeIdx]];
497 for (LO nodeIdx = 0; nodeIdx < numInterfaceNodes; ++nodeIdx) {
499 if (aggStat[interfaceNodes[nodeIdx]] ==
AGGREGATED) {
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];
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];
516 if (rem > (rate / 2)) {
521 for (LO dim = 0; dim < 3; ++dim) {
522 if (coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
523 nodeIJK[dim] = fineNodesPerDim[dim] - 1;
525 nodeIJK[dim] = coarseIJK[dim] * coarseRate[dim];
528 fineNodeIdx = (nodeIJK[2] * fineNodesPerDim[1] + nodeIJK[1]) * fineNodesPerDim[0] + nodeIJK[0];
530 vertex2AggId[interfaceNodes[nodeIdx]] = vertex2AggId[interfaceNodes[fineNodeIdx]];
531 procWinner[interfaceNodes[nodeIdx]] = myRank;
532 aggStat[interfaceNodes[nodeIdx]] =
AGGREGATED;
533 --numNonAggregatedNodes;
538 aggregates->SetNumAggregates(aggregateCount);
541 Set(currentLevel,
"coarseInterfacesDimensions", coarseInterfacesDimensions);
542 Set(currentLevel,
"nodeOnCoarseInterface", nodesOnCoarseInterfaces);