46 #ifndef MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP_
47 #define MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP_
50 #include <Xpetra_Map.hpp>
52 #include <Xpetra_MultiVectorFactory.hpp>
58 #include "MueLu_InterfaceAggregationAlgorithm.hpp"
59 #include "MueLu_OnePtAggregationAlgorithm.hpp"
60 #include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
61 #include "MueLu_IsolatedNodeAggregationAlgorithm.hpp"
63 #include "MueLu_AggregationPhase1Algorithm.hpp"
64 #include "MueLu_AggregationPhase2aAlgorithm.hpp"
65 #include "MueLu_AggregationPhase2bAlgorithm.hpp"
66 #include "MueLu_AggregationPhase3Algorithm.hpp"
69 #include "MueLu_AggregationStructuredAlgorithm.hpp"
70 #include "MueLu_UncoupledIndexManager.hpp"
77 #include "MueLu_Aggregates.hpp"
80 #include "MueLu_Utilities.hpp"
81 #include "MueLu_AmalgamationInfo.hpp"
86 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
91 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
104 rcp(
new validatorType(Teuchos::tuple<std::string>(
"natural",
"graph",
"random"),
"aggregation: ordering")));
111 SET_VALID_ENTRY(
"aggregation: error on nodes with no on-rank neighbors");
121 #undef SET_VALID_ENTRY
126 validParamList->
set<
RCP<const FactoryBase> >(
"DofsPerNode", null,
"Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
128 validParamList->
set<std::string> (
"OnePt aggregate map name",
"",
129 "Name of input map for single node aggregates. (default='')");
130 validParamList->
set<std::string> (
"OnePt aggregate map factory",
"",
131 "Generating factory of (DOF) map for single node aggregates.");
134 validParamList->
set<std::string> (
"Interface aggregate map name",
"",
135 "Name of input map for interface aggregates. (default='')");
136 validParamList->
set<std::string> (
"Interface aggregate map factory",
"",
137 "Generating factory of (DOF) map for interface aggregates.");
139 "Describes the dimensions of all the interfaces on this rank.");
141 "List the LIDs of the nodes on any interface.");
146 "Number of spatial dimension provided by CoordinatesTransferFactory.");
148 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
153 "Type of aggregation to use on the region (\"structured\" or \"uncoupled\")");
155 return validParamList;
158 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
161 Input(currentLevel,
"Graph");
176 "Aggregation region type was not provided by the user!");
183 "numDimensions was not provided by the user on level0!");
190 "lNodesPerDim was not provided by the user on level0!");
193 Input(currentLevel,
"aggregationRegionType");
194 Input(currentLevel,
"numDimensions");
195 Input(currentLevel,
"lNodesPerDim");
201 Input(currentLevel,
"DofsPerNode");
204 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true){
211 "interfacesDimensions was not provided by the user on level0!");
218 "nodeOnInterface was not provided by the user on level0!");
221 Input(currentLevel,
"interfacesDimensions");
222 Input(currentLevel,
"nodeOnInterface");
227 std::string mapOnePtName = pL.
get<std::string>(
"OnePt aggregate map name");
228 if (mapOnePtName.length() > 0) {
229 std::string mapOnePtFactName = pL.
get<std::string>(
"OnePt aggregate map factory");
230 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
239 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
245 if(
const char* dbg = std::getenv(
"MUELU_HYBRIDAGGREGATION_DEBUG")) {
246 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
252 *out <<
"Entering hybrid aggregation" << std::endl;
255 bDefinitionPhase_ =
false;
257 if (pL.
get<
int>(
"aggregation: max agg size") == -1)
258 pL.
set(
"aggregation: max agg size", INT_MAX);
266 const int myRank = fineMap->getComm()->getRank();
267 const int numRanks = fineMap->getComm()->getSize();
278 std::vector<unsigned> aggStat(numRows,
READY);
281 std::string regionType;
282 if(currentLevel.GetLevelID() == 0) {
284 regionType = currentLevel.Get<std::string>(
"aggregationRegionType",
NoFactory::get());
287 regionType = Get< std::string >(currentLevel,
"aggregationRegionType");
290 int numDimensions = 0;
291 if(currentLevel.GetLevelID() == 0) {
293 numDimensions = currentLevel.Get<
int>(
"numDimensions",
NoFactory::get());
296 numDimensions = Get<int>(currentLevel,
"numDimensions");
300 std::string coarseningRate = pL.
get<std::string>(
"aggregation: coarsening rate");
303 coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
305 GetOStream(
Errors,-1) <<
" *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
311 "\"aggregation: coarsening rate\" must have at least as many"
312 " components as the number of spatial dimensions in the problem.");
315 LO numNonAggregatedNodes = numRows;
316 if (regionType ==
"structured") {
322 const int interpolationOrder = pL.
get<
int>(
"aggregation: coarsening order");
324 if(currentLevel.GetLevelID() == 0) {
329 lFineNodesPerDir = Get<Array<LO> >(currentLevel,
"lNodesPerDim");
333 for(
int dim = numDimensions; dim < 3; ++dim) {
334 lFineNodesPerDir[dim] = 1;
350 !=
static_cast<size_t>(geoData->getNumLocalFineNodes()),
352 "The local number of elements in the graph's map is not equal to "
353 "the number of nodes given by: lNodesPerDim!");
358 Set(currentLevel,
"lCoarseNodesPerDim", geoData->getLocalCoarseNodesPerDir());
362 if (regionType ==
"uncoupled"){
372 *out <<
" Build interface aggregates" << std::endl;
374 if (pL.
get<
bool>(
"aggregation: use interface aggregation") ==
true) {
375 BuildInterfaceAggregates(currentLevel, aggregates, aggStat, numNonAggregatedNodes,
379 *out <<
"Treat Dirichlet BC" << std::endl;
382 if (dirichletBoundaryMap != Teuchos::null)
383 for (
LO i = 0; i < numRows; i++)
384 if (dirichletBoundaryMap[i] ==
true)
388 std::string mapOnePtName = pL.
get<std::string>(
"OnePt aggregate map name");
390 if (mapOnePtName.length()) {
391 std::string mapOnePtFactName = pL.
get<std::string>(
"OnePt aggregate map factory");
392 if (mapOnePtFactName ==
"" || mapOnePtFactName ==
"NoFactory") {
396 OnePtMap = currentLevel.Get<
RCP<Map> >(mapOnePtName, mapOnePtFact.
get());
400 LO nDofsPerNode = Get<LO>(currentLevel,
"DofsPerNode");
402 if (OnePtMap != Teuchos::null) {
403 for (
LO i = 0; i < numRows; i++) {
405 GO grid = (graph->
GetDomainMap()->getGlobalElement(i)-indexBase) * nDofsPerNode + indexBase;
406 for (
LO kr = 0; kr < nDofsPerNode; kr++)
407 if (OnePtMap->isNodeGlobalElement(grid + kr))
414 Set(currentLevel,
"lCoarseNodesPerDim", lCoarseNodesPerDir);
419 *out <<
"Run all the algorithms on the local rank" << std::endl;
420 for (
size_t a = 0; a < algos_.size(); a++) {
421 std::string phase = algos_[a]->description();
423 *out << regionType <<
" | Executing phase " << a << std::endl;
425 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
426 algos_[a]->BuildAggregates(pL, *graph, *aggregates, aggStat, numNonAggregatedNodes);
427 algos_[a]->SetProcRankVerbose(oldRank);
428 *out << regionType <<
" | Done Executing phase " << a << std::endl;
431 *out <<
"Compute statistics on aggregates" << std::endl;
434 Set(currentLevel,
"Aggregates", aggregates);
435 Set(currentLevel,
"numDimensions", numDimensions);
436 Set(currentLevel,
"aggregationRegionTypeCoarse", regionType);
439 *out <<
"HybridAggregation done!" << std::endl;
442 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
445 std::vector<unsigned>& aggStat,
LO& numNonAggregatedNodes,
447 FactoryMonitor m(*
this,
"BuildInterfaceAggregates", currentLevel);
450 if(
const char* dbg = std::getenv(
"MUELU_HYBRIDAGGREGATION_DEBUG")) {
451 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
458 if(coarseRate.
size() == 1) {coarseRate.
resize(3, coarseRate[0]);}
461 Array<LO> interfacesDimensions = Get<Array<LO> >(currentLevel,
"interfacesDimensions");
462 Array<LO> nodesOnInterfaces = Get<Array<LO> >(currentLevel,
"nodeOnInterface");
463 const int numInterfaces = interfacesDimensions.
size() / 3;
464 const int myRank = aggregates->
GetMap()->getComm()->getRank();
467 Array<LO> coarseInterfacesDimensions(interfacesDimensions.
size());
470 LO endRate, totalNumCoarseNodes = 0, numCoarseNodes;
471 for(
int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
473 for(
int dim = 0; dim < 3; ++dim) {
474 endRate = interfacesDimensions[3*interfaceIdx + dim] % coarseRate[dim];
475 if(interfacesDimensions[3*interfaceIdx + dim] == 1) {
476 coarseInterfacesDimensions[3*interfaceIdx + dim] = 1;
478 coarseInterfacesDimensions[3*interfaceIdx + dim]
479 = (interfacesDimensions[3*interfaceIdx + dim] - endRate - 1) / coarseRate[dim] + 2;
481 numCoarseNodes *= coarseInterfacesDimensions[3*interfaceIdx + dim];
483 totalNumCoarseNodes += numCoarseNodes;
485 nodesOnCoarseInterfaces.
resize(totalNumCoarseNodes, -1);
489 LO interfaceOffset = 0, aggregateCount = 0, coarseNodeCount = 0;
490 for(
int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
491 ArrayView<LO> fineNodesPerDim = interfacesDimensions(3*interfaceIdx, 3);
492 ArrayView<LO> coarseNodesPerDim = coarseInterfacesDimensions(3*interfaceIdx, 3);
493 LO numInterfaceNodes = 1, numCoarseNodes = 1;
494 for(
int dim = 0; dim < 3; ++dim) {
495 numInterfaceNodes *= fineNodesPerDim[dim];
496 numCoarseNodes *= coarseNodesPerDim[dim];
497 endRate[dim] = fineNodesPerDim[dim] % coarseRate[dim];
499 ArrayView<LO> interfaceNodes = nodesOnInterfaces(interfaceOffset, numInterfaceNodes);
501 interfaceOffset += numInterfaceNodes;
503 LO rem, rate, fineNodeIdx;
504 Array<LO> nodeIJK(3), coarseIJK(3), rootIJK(3);
507 for(
LO coarseNodeIdx = 0; coarseNodeIdx < numCoarseNodes; ++coarseNodeIdx) {
508 coarseIJK[2] = coarseNodeIdx / (coarseNodesPerDim[0]*coarseNodesPerDim[1]);
509 rem = coarseNodeIdx % (coarseNodesPerDim[0]*coarseNodesPerDim[1]);
510 coarseIJK[1] = rem / coarseNodesPerDim[0];
511 coarseIJK[0] = rem % coarseNodesPerDim[0];
513 for(
LO dim = 0; dim < 3; ++dim) {
514 if(coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
515 nodeIJK[dim] = fineNodesPerDim[dim] - 1;
517 nodeIJK[dim] = coarseIJK[dim]*coarseRate[dim];
520 fineNodeIdx = (nodeIJK[2]*fineNodesPerDim[1] + nodeIJK[1])*fineNodesPerDim[0] + nodeIJK[0];
522 if(aggStat[interfaceNodes[fineNodeIdx]] ==
READY) {
523 vertex2AggId[interfaceNodes[fineNodeIdx]] = aggregateCount;
524 procWinner[interfaceNodes[fineNodeIdx]] = myRank;
525 aggStat[interfaceNodes[fineNodeIdx]] =
AGGREGATED;
527 --numNonAggregatedNodes;
529 nodesOnCoarseInterfaces[coarseNodeCount] = vertex2AggId[interfaceNodes[fineNodeIdx]];
536 for(
LO nodeIdx = 0; nodeIdx < numInterfaceNodes; ++nodeIdx) {
539 if(aggStat[interfaceNodes[nodeIdx]] ==
AGGREGATED) {
continue;}
541 nodeIJK[2] = nodeIdx / (fineNodesPerDim[0]*fineNodesPerDim[1]);
542 rem = nodeIdx % (fineNodesPerDim[0]*fineNodesPerDim[1]);
543 nodeIJK[1] = rem / fineNodesPerDim[0];
544 nodeIJK[0] = rem % fineNodesPerDim[0];
546 for(
int dim = 0; dim < 3; ++dim) {
547 coarseIJK[dim] = nodeIJK[dim] / coarseRate[dim];
548 rem = nodeIJK[dim] % coarseRate[dim];
549 if(nodeIJK[dim] < fineNodesPerDim[dim] - endRate[dim]) {
550 rate = coarseRate[dim];
554 if(rem > (rate / 2)) {++coarseIJK[dim];}
557 for(
LO dim = 0; dim < 3; ++dim) {
558 if(coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
559 nodeIJK[dim] = fineNodesPerDim[dim] - 1;
561 nodeIJK[dim] = coarseIJK[dim]*coarseRate[dim];
564 fineNodeIdx = (nodeIJK[2]*fineNodesPerDim[1] + nodeIJK[1])*fineNodesPerDim[0] + nodeIJK[0];
566 vertex2AggId[interfaceNodes[nodeIdx]] = vertex2AggId[interfaceNodes[fineNodeIdx]];
567 procWinner[interfaceNodes[nodeIdx]] = myRank;
568 aggStat[interfaceNodes[nodeIdx]] =
AGGREGATED;
569 --numNonAggregatedNodes;
577 Set(currentLevel,
"coarseInterfacesDimensions", coarseInterfacesDimensions);
578 Set(currentLevel,
"nodeOnCoarseInterface", nodesOnCoarseInterfaces);
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)
T & get(const std::string &name, T def_value)
virtual size_t GetNodeNumVertices() const =0
Return number of vertices owned by the calling node.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers.
virtual const ArrayRCP< const bool > GetBoundaryNodeMap() const =0
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Algorithm for coarsening a graph with structured aggregation.
virtual const RCP< const Map > GetDomainMap() const =0
const RCP< const Map > GetMap() const
returns (overlapping) map of aggregate/node distribution
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void SetIndexManager(RCP< IndexManager > &geoData)
Get the index manager used by structured aggregation algorithms.
Teuchos::ArrayRCP< LO > ComputeAggregateSizes(bool forceRecompute=false) const
Compute sizes of aggregates.
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.
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())
void Build(Level ¤tLevel) 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.
Add leftovers to existing aggregatesIdeaIn phase 2b non-aggregated nodes are added to existing aggreg...
void DeclareInput(Level ¤tLevel) const
Input.
virtual const RCP< const Map > GetImportMap() const =0
Algorithm for coarsening a graph with uncoupled aggregation.
int GetLevelID() const
Return level number.
Exception throws to report errors in the internal logical of the program.
HybridAggregationFactory()
Constructor.
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 AggregatesCrossProcessors(const bool &flag)
Record whether aggregates include DOFs from other processes.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void SetNumAggregates(LO nAggregates)
Set number of local aggregates on current processor.
void BuildInterfaceAggregates(Level ¤tLevel, RCP< Aggregates > aggregates, std::vector< unsigned > &aggStat, LO &numNonAggregatedNodes, Array< LO > coarseRate) const
Specifically build aggregates along interfaces.