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 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP_
47 #define MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP_
48 
49 #include <Xpetra_Matrix.hpp>
50 #include <Xpetra_Map.hpp>
51 #include <Xpetra_Vector.hpp>
52 #include <Xpetra_MultiVectorFactory.hpp>
53 #include <Xpetra_VectorFactory.hpp>
54 
56 
57 // Uncoupled Agg
58 #include "MueLu_InterfaceAggregationAlgorithm.hpp"
59 #include "MueLu_OnePtAggregationAlgorithm.hpp"
60 #include "MueLu_PreserveDirichletAggregationAlgorithm.hpp"
61 #include "MueLu_IsolatedNodeAggregationAlgorithm.hpp"
62 
63 #include "MueLu_AggregationPhase1Algorithm.hpp"
64 #include "MueLu_AggregationPhase2aAlgorithm.hpp"
65 #include "MueLu_AggregationPhase2bAlgorithm.hpp"
66 #include "MueLu_AggregationPhase3Algorithm.hpp"
67 
68 // Structured Agg
69 #include "MueLu_AggregationStructuredAlgorithm.hpp"
70 #include "MueLu_UncoupledIndexManager.hpp"
71 //#include "MueLu_LocalLexicographicIndexManager.hpp"
72 //#include "MueLu_GlobalLexicographicIndexManager.hpp"
73 
74 // Shared
75 #include "MueLu_Level.hpp"
76 #include "MueLu_GraphBase.hpp"
77 #include "MueLu_Aggregates.hpp"
78 #include "MueLu_MasterList.hpp"
79 #include "MueLu_Monitor.hpp"
80 #include "MueLu_Utilities.hpp"
81 #include "MueLu_AmalgamationInfo.hpp"
82 
83 
84 namespace MueLu {
85 
86  template <class LocalOrdinal, class GlobalOrdinal, class Node>
88  HybridAggregationFactory() : bDefinitionPhase_(true)
89  { }
90 
91  template <class LocalOrdinal, class GlobalOrdinal, class Node>
94  RCP<ParameterList> validParamList = rcp(new ParameterList());
95 
97 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
98  // From UncoupledAggregationFactory
99  SET_VALID_ENTRY("aggregation: max agg size");
100  SET_VALID_ENTRY("aggregation: min agg size");
101  SET_VALID_ENTRY("aggregation: max selected neighbors");
102  SET_VALID_ENTRY("aggregation: ordering");
103  validParamList->getEntry("aggregation: ordering").setValidator(
104  rcp(new validatorType(Teuchos::tuple<std::string>("natural", "graph", "random"), "aggregation: ordering")));
105  SET_VALID_ENTRY("aggregation: enable phase 1");
106  SET_VALID_ENTRY("aggregation: enable phase 2a");
107  SET_VALID_ENTRY("aggregation: enable phase 2b");
108  SET_VALID_ENTRY("aggregation: enable phase 3");
109  SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
110  SET_VALID_ENTRY("aggregation: allow user-specified singletons");
111  SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
112  SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
113 
114  // From StructuredAggregationFactory
115  SET_VALID_ENTRY("aggregation: coarsening rate");
116  SET_VALID_ENTRY("aggregation: coarsening order");
117  SET_VALID_ENTRY("aggregation: number of spatial dimensions");
118 
119  // From HybridAggregationFactory
120  SET_VALID_ENTRY("aggregation: use interface aggregation");
121 #undef SET_VALID_ENTRY
122 
123  /* From UncoupledAggregation */
124  // general variables needed in AggregationFactory
125  validParamList->set< RCP<const FactoryBase> >("Graph", null, "Generating factory of the graph");
126  validParamList->set< RCP<const FactoryBase> >("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
127  // special variables necessary for OnePtAggregationAlgorithm
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.");
132 
133  // InterfaceAggregation parameters
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.");
138  validParamList->set<RCP<const FactoryBase> > ("interfacesDimensions", Teuchos::null,
139  "Describes the dimensions of all the interfaces on this rank.");
140  validParamList->set<RCP<const FactoryBase> > ("nodeOnInterface", Teuchos::null,
141  "List the LIDs of the nodes on any interface.");
142 
143  /* From StructuredAggregation */
144  // general variables needed in AggregationFactory
145  validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
146  "Number of spatial dimension provided by CoordinatesTransferFactory.");
147  validParamList->set<RCP<const FactoryBase> >("lNodesPerDim", Teuchos::null,
148  "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
149 
150 
151  // Hybrid Aggregation Params
152  validParamList->set<RCP<const FactoryBase> > ("aggregationRegionType", Teuchos::null,
153  "Type of aggregation to use on the region (\"structured\" or \"uncoupled\")");
154 
155  return validParamList;
156  }
157 
158  template <class LocalOrdinal, class GlobalOrdinal, class Node>
160  DeclareInput(Level& currentLevel) const {
161  Input(currentLevel, "Graph");
162 
163  ParameterList pL = GetParameterList();
164 
165 
166 
167  /* StructuredAggregation */
168 
169  // Request the local number of nodes per dimensions
170  if(currentLevel.GetLevelID() == 0) {
171  if(currentLevel.IsAvailable("aggregationRegionType", NoFactory::get())) {
172  currentLevel.DeclareInput("aggregationRegionType", NoFactory::get(), this);
173  } else {
174  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("aggregationRegionType",NoFactory::get()),
176  "Aggregation region type was not provided by the user!");
177  }
178  if(currentLevel.IsAvailable("numDimensions", NoFactory::get())) {
179  currentLevel.DeclareInput("numDimensions", NoFactory::get(), this);
180  } else {
181  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("numDimensions", NoFactory::get()),
183  "numDimensions was not provided by the user on level0!");
184  }
185  if(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get())) {
186  currentLevel.DeclareInput("lNodesPerDim", NoFactory::get(), this);
187  } else {
188  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get()),
190  "lNodesPerDim was not provided by the user on level0!");
191  }
192  } else {
193  Input(currentLevel, "aggregationRegionType");
194  Input(currentLevel, "numDimensions");
195  Input(currentLevel, "lNodesPerDim");
196  }
197 
198 
199 
200  /* UncoupledAggregation */
201  Input(currentLevel, "DofsPerNode");
202 
203  // request special data necessary for InterfaceAggregation
204  if (pL.get<bool>("aggregation: use interface aggregation") == true){
205  if(currentLevel.GetLevelID() == 0) {
206  if(currentLevel.IsAvailable("interfacesDimensions", NoFactory::get())) {
207  currentLevel.DeclareInput("interfacesDimensions", NoFactory::get(), this);
208  } else {
209  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("interfacesDimensions", NoFactory::get()),
211  "interfacesDimensions was not provided by the user on level0!");
212  }
213  if(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
214  currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
215  } else {
216  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
218  "nodeOnInterface was not provided by the user on level0!");
219  }
220  } else {
221  Input(currentLevel, "interfacesDimensions");
222  Input(currentLevel, "nodeOnInterface");
223  }
224  }
225 
226  // request special data necessary for OnePtAggregationAlgorithm
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") {
231  currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
232  } else {
233  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
234  currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
235  }
236  }
237  } // DeclareInput()
238 
239  template <class LocalOrdinal, class GlobalOrdinal, class Node>
241  Build(Level &currentLevel) const {
242  FactoryMonitor m(*this, "Build", currentLevel);
243 
245  if(const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
246  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
247  out->setShowAllFrontMatter(false).setShowProcRank(true);
248  } else {
249  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
250  }
251 
252  *out << "Entering hybrid aggregation" << std::endl;
253 
254  ParameterList pL = GetParameterList();
255  bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
256 
257  if (pL.get<int>("aggregation: max agg size") == -1)
258  pL.set("aggregation: max agg size", INT_MAX);
259 
260  // define aggregation algorithms
261  RCP<const FactoryBase> graphFact = GetFactory("Graph");
262 
263  // General problem informations are gathered from data stored in the problem matix.
264  RCP<const GraphBase> graph = Get< RCP<GraphBase> >(currentLevel, "Graph");
265  RCP<const Map> fineMap = graph->GetDomainMap();
266  const int myRank = fineMap->getComm()->getRank();
267  const int numRanks = fineMap->getComm()->getSize();
268 
269  out->setProcRankAndSize(graph->GetImportMap()->getComm()->getRank(),
270  graph->GetImportMap()->getComm()->getSize());
271 
272  // Build aggregates
273  RCP<Aggregates> aggregates = rcp(new Aggregates(*graph));
274  aggregates->setObjectLabel("HB");
275 
276  // construct aggStat information
277  const LO numRows = graph->GetNodeNumVertices();
278  std::vector<unsigned> aggStat(numRows, READY);
279 
280  // Get aggregation type for region
281  std::string regionType;
282  if(currentLevel.GetLevelID() == 0) {
283  // On level 0, data is provided by applications and has no associated factory.
284  regionType = currentLevel.Get<std::string>("aggregationRegionType", NoFactory::get());
285  } else {
286  // On level > 0, data is provided directly by generating factories.
287  regionType = Get< std::string >(currentLevel, "aggregationRegionType");
288  }
289 
290  int numDimensions = 0;
291  if(currentLevel.GetLevelID() == 0) {
292  // On level 0, data is provided by applications and has no associated factory.
293  numDimensions = currentLevel.Get<int>("numDimensions", NoFactory::get());
294  } else {
295  // On level > 0, data is provided directly by generating factories.
296  numDimensions = Get<int>(currentLevel, "numDimensions");
297  }
298 
299  // Get the coarsening rate (potentially used for both structured and uncoupled aggregation if interface)
300  std::string coarseningRate = pL.get<std::string>("aggregation: coarsening rate");
301  Teuchos::Array<LO> coarseRate;
302  try {
303  coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
305  GetOStream(Errors,-1) << " *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
306  << std::endl;
307  throw e;
308  }
309  TEUCHOS_TEST_FOR_EXCEPTION((coarseRate.size() > 1) && (coarseRate.size() < numDimensions),
311  "\"aggregation: coarsening rate\" must have at least as many"
312  " components as the number of spatial dimensions in the problem.");
313 
314  algos_.clear();
315  LO numNonAggregatedNodes = numRows;
316  if (regionType == "structured") {
317  // Add AggregationStructuredAlgorithm
318  algos_.push_back(rcp(new AggregationStructuredAlgorithm(graphFact)));
319 
320  // Since we want to operate on nodes and not dof, we need to modify the rowMap in order to
321  // obtain a nodeMap.
322  const int interpolationOrder = pL.get<int>("aggregation: coarsening order");
323  Array<LO> lFineNodesPerDir(3);
324  if(currentLevel.GetLevelID() == 0) {
325  // On level 0, data is provided by applications and has no associated factory.
326  lFineNodesPerDir = currentLevel.Get<Array<LO> >("lNodesPerDim", NoFactory::get());
327  } else {
328  // On level > 0, data is provided directly by generating factories.
329  lFineNodesPerDir = Get<Array<LO> >(currentLevel, "lNodesPerDim");
330  }
331 
332  // Set lFineNodesPerDir to 1 for directions beyond numDimensions
333  for(int dim = numDimensions; dim < 3; ++dim) {
334  lFineNodesPerDir[dim] = 1;
335  }
336 
337  // Now that we have extracted info from the level, create the IndexManager
339  geoData = rcp(new MueLu::UncoupledIndexManager<LO,GO,NO>(fineMap->getComm(),
340  false,
341  numDimensions,
342  interpolationOrder,
343  myRank,
344  numRanks,
345  Array<GO>(3, -1),
346  lFineNodesPerDir,
347  coarseRate));
348 
349  TEUCHOS_TEST_FOR_EXCEPTION(fineMap->getNodeNumElements()
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!");
354 
355  aggregates->SetIndexManager(geoData);
356  aggregates->SetNumAggregates(geoData->getNumLocalCoarseNodes());
357 
358  Set(currentLevel, "lCoarseNodesPerDim", geoData->getLocalCoarseNodesPerDir());
359 
360  } // end structured aggregation setup
361 
362  if (regionType == "uncoupled"){
363  // Add unstructred aggregation phases
364  algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
365  if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm (graphFact)));
366  if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm (graphFact)));
367  if (pL.get<bool>("aggregation: enable phase 1" ) == true) algos_.push_back(rcp(new AggregationPhase1Algorithm (graphFact)));
368  if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm (graphFact)));
369  if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm (graphFact)));
370  if (pL.get<bool>("aggregation: enable phase 3" ) == true) algos_.push_back(rcp(new AggregationPhase3Algorithm (graphFact)));
371 
372  *out << " Build interface aggregates" << std::endl;
373  // interface
374  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
375  BuildInterfaceAggregates(currentLevel, aggregates, aggStat, numNonAggregatedNodes,
376  coarseRate);
377  }
378 
379  *out << "Treat Dirichlet BC" << std::endl;
380  // Dirichlet boundary
381  ArrayRCP<const bool> dirichletBoundaryMap = graph->GetBoundaryNodeMap();
382  if (dirichletBoundaryMap != Teuchos::null)
383  for (LO i = 0; i < numRows; i++)
384  if (dirichletBoundaryMap[i] == true)
385  aggStat[i] = BOUNDARY;
386 
387  // OnePt aggregation
388  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
389  RCP<Map> OnePtMap = Teuchos::null;
390  if (mapOnePtName.length()) {
391  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
392  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
393  OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, NoFactory::get());
394  } else {
395  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
396  OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
397  }
398  }
399 
400  LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
401  GO indexBase = graph->GetDomainMap()->getIndexBase();
402  if (OnePtMap != Teuchos::null) {
403  for (LO i = 0; i < numRows; i++) {
404  // reconstruct global row id (FIXME only works for contiguous maps)
405  GO grid = (graph->GetDomainMap()->getGlobalElement(i)-indexBase) * nDofsPerNode + indexBase;
406  for (LO kr = 0; kr < nDofsPerNode; kr++)
407  if (OnePtMap->isNodeGlobalElement(grid + kr))
408  aggStat[i] = ONEPT;
409  }
410  }
411 
412  // Create a fake lCoarseNodesPerDir for CoordinatesTranferFactory
413  Array<LO> lCoarseNodesPerDir(3,-1);
414  Set(currentLevel, "lCoarseNodesPerDim", lCoarseNodesPerDir);
415  } // end uncoupled aggregation setup
416 
417  aggregates->AggregatesCrossProcessors(false); // No coupled aggregation
418 
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();
422  SubFactoryMonitor sfm(*this, "Algo \"" + phase + "\"", currentLevel);
423  *out << regionType <<" | Executing phase " << a << std::endl;
424 
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;
429  }
430 
431  *out << "Compute statistics on aggregates" << std::endl;
432  aggregates->ComputeAggregateSizes(true/*forceRecompute*/);
433 
434  Set(currentLevel, "Aggregates", aggregates);
435  Set(currentLevel, "numDimensions", numDimensions);
436  Set(currentLevel, "aggregationRegionTypeCoarse", regionType);
437 
438  GetOStream(Statistics1) << aggregates->description() << std::endl;
439  *out << "HybridAggregation done!" << std::endl;
440  }
441 
442  template <class LocalOrdinal, class GlobalOrdinal, class Node>
445  std::vector<unsigned>& aggStat, LO& numNonAggregatedNodes,
446  Array<LO> coarseRate) const {
447  FactoryMonitor m(*this, "BuildInterfaceAggregates", currentLevel);
448 
450  if(const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
451  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
452  out->setShowAllFrontMatter(false).setShowProcRank(true);
453  } else {
454  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
455  }
456 
457  // Extract and format input data for algo
458  if(coarseRate.size() == 1) {coarseRate.resize(3, coarseRate[0]);}
459  ArrayRCP<LO> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
460  ArrayRCP<LO> procWinner = aggregates->GetProcWinner() ->getDataNonConst(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();
465 
466  // Create coarse level container to gather data on the fly
467  Array<LO> coarseInterfacesDimensions(interfacesDimensions.size());
468  Array<LO> nodesOnCoarseInterfaces;
469  { // Scoping the temporary variables...
470  LO endRate, totalNumCoarseNodes = 0, numCoarseNodes;
471  for(int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
472  numCoarseNodes = 1;
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;
477  } else {
478  coarseInterfacesDimensions[3*interfaceIdx + dim]
479  = (interfacesDimensions[3*interfaceIdx + dim] - endRate - 1) / coarseRate[dim] + 2;
480  }
481  numCoarseNodes *= coarseInterfacesDimensions[3*interfaceIdx + dim];
482  }
483  totalNumCoarseNodes += numCoarseNodes;
484  }
485  nodesOnCoarseInterfaces.resize(totalNumCoarseNodes, -1);
486  }
487 
488  Array<LO> endRate(3);
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];
498  }
499  ArrayView<LO> interfaceNodes = nodesOnInterfaces(interfaceOffset, numInterfaceNodes);
500 
501  interfaceOffset += numInterfaceNodes;
502 
503  LO rem, rate, fineNodeIdx;
504  Array<LO> nodeIJK(3), coarseIJK(3), rootIJK(3);
505  // First find treat coarse nodes as they generate the aggregate IDs
506  // and they might be repeated on multiple interfaces (think corners and edges).
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];
512 
513  for(LO dim = 0; dim < 3; ++dim) {
514  if(coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
515  nodeIJK[dim] = fineNodesPerDim[dim] - 1;
516  } else {
517  nodeIJK[dim] = coarseIJK[dim]*coarseRate[dim];
518  }
519  }
520  fineNodeIdx = (nodeIJK[2]*fineNodesPerDim[1] + nodeIJK[1])*fineNodesPerDim[0] + nodeIJK[0];
521 
522  if(aggStat[interfaceNodes[fineNodeIdx]] == READY) {
523  vertex2AggId[interfaceNodes[fineNodeIdx]] = aggregateCount;
524  procWinner[interfaceNodes[fineNodeIdx]] = myRank;
525  aggStat[interfaceNodes[fineNodeIdx]] = AGGREGATED;
526  ++aggregateCount;
527  --numNonAggregatedNodes;
528  }
529  nodesOnCoarseInterfaces[coarseNodeCount] = vertex2AggId[interfaceNodes[fineNodeIdx]];
530  ++coarseNodeCount;
531  }
532 
533  // Now loop over all the node on the interface
534  // skip the coarse nodes as they are already aggregated
535  // and find the appropriate aggregate ID for the fine nodes.
536  for(LO nodeIdx = 0; nodeIdx < numInterfaceNodes; ++nodeIdx) {
537 
538  // If the node is already aggregated skip it!
539  if(aggStat[interfaceNodes[nodeIdx]] == AGGREGATED) {continue;}
540 
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];
545 
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];
551  } else {
552  rate = endRate[dim];
553  }
554  if(rem > (rate / 2)) {++coarseIJK[dim];}
555  }
556 
557  for(LO dim = 0; dim < 3; ++dim) {
558  if(coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
559  nodeIJK[dim] = fineNodesPerDim[dim] - 1;
560  } else {
561  nodeIJK[dim] = coarseIJK[dim]*coarseRate[dim];
562  }
563  }
564  fineNodeIdx = (nodeIJK[2]*fineNodesPerDim[1] + nodeIJK[1])*fineNodesPerDim[0] + nodeIJK[0];
565 
566  vertex2AggId[interfaceNodes[nodeIdx]] = vertex2AggId[interfaceNodes[fineNodeIdx]];
567  procWinner[interfaceNodes[nodeIdx]] = myRank;
568  aggStat[interfaceNodes[nodeIdx]] = AGGREGATED;
569  --numNonAggregatedNodes;
570  } // Loop over interface nodes
571  } // Loop over the interfaces
572 
573  // Update aggregates information before subsequent aggregation algorithms
574  aggregates->SetNumAggregates(aggregateCount);
575 
576  // Set coarse data for next level
577  Set(currentLevel, "coarseInterfacesDimensions", coarseInterfacesDimensions);
578  Set(currentLevel, "nodeOnCoarseInterface", nodesOnCoarseInterfaces);
579 
580  } // BuildInterfaceAggregates()
581 
582 } //namespace MueLu
583 
584 
585 #endif /* MUELU_HYBRIDAGGREGATIONFACTORY_DEF_HPP */
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)
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.
Print more statistics.
virtual const RCP< const Map > GetDomainMap() const =0
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.
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.
Definition: MueLu_Level.hpp:99
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 &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.
virtual const RCP< const Map > GetImportMap() const =0
Algorithm for coarsening a graph with uncoupled aggregation.
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:76
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 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&#39;s value has been saved.
void SetNumAggregates(LO nAggregates)
Set number of local aggregates on current processor.
void BuildInterfaceAggregates(Level &currentLevel, RCP< Aggregates > aggregates, std::vector< unsigned > &aggStat, LO &numNonAggregatedNodes, Array< LO > coarseRate) const
Specifically build aggregates along interfaces.