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: phase2a include root");
113  SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
114 
115  // From StructuredAggregationFactory
116  SET_VALID_ENTRY("aggregation: coarsening rate");
117  SET_VALID_ENTRY("aggregation: coarsening order");
118  SET_VALID_ENTRY("aggregation: number of spatial dimensions");
119 
120  // From HybridAggregationFactory
121  SET_VALID_ENTRY("aggregation: use interface aggregation");
122 #undef SET_VALID_ENTRY
123 
124  /* From UncoupledAggregation */
125  // general variables needed in AggregationFactory
126  validParamList->set< RCP<const FactoryBase> >("Graph", null, "Generating factory of the graph");
127  validParamList->set< RCP<const FactoryBase> >("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
128  // special variables necessary for OnePtAggregationAlgorithm
129  validParamList->set<std::string> ("OnePt aggregate map name", "",
130  "Name of input map for single node aggregates. (default='')");
131  validParamList->set<std::string> ("OnePt aggregate map factory", "",
132  "Generating factory of (DOF) map for single node aggregates.");
133 
134  // InterfaceAggregation parameters
135  validParamList->set<std::string> ("Interface aggregate map name", "",
136  "Name of input map for interface aggregates. (default='')");
137  validParamList->set<std::string> ("Interface aggregate map factory", "",
138  "Generating factory of (DOF) map for interface aggregates.");
139  validParamList->set<RCP<const FactoryBase> > ("interfacesDimensions", Teuchos::null,
140  "Describes the dimensions of all the interfaces on this rank.");
141  validParamList->set<RCP<const FactoryBase> > ("nodeOnInterface", Teuchos::null,
142  "List the LIDs of the nodes on any interface.");
143 
144  /* From StructuredAggregation */
145  // general variables needed in AggregationFactory
146  validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
147  "Number of spatial dimension provided by CoordinatesTransferFactory.");
148  validParamList->set<RCP<const FactoryBase> >("lNodesPerDim", Teuchos::null,
149  "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
150 
151 
152  // Hybrid Aggregation Params
153  validParamList->set<RCP<const FactoryBase> > ("aggregationRegionType", Teuchos::null,
154  "Type of aggregation to use on the region (\"structured\" or \"uncoupled\")");
155 
156  return validParamList;
157  }
158 
159  template <class LocalOrdinal, class GlobalOrdinal, class Node>
161  DeclareInput(Level& currentLevel) const {
162  Input(currentLevel, "Graph");
163 
164  ParameterList pL = GetParameterList();
165 
166 
167 
168  /* StructuredAggregation */
169 
170  // Request the local number of nodes per dimensions
171  if(currentLevel.GetLevelID() == 0) {
172  if(currentLevel.IsAvailable("aggregationRegionType", NoFactory::get())) {
173  currentLevel.DeclareInput("aggregationRegionType", NoFactory::get(), this);
174  } else {
175  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("aggregationRegionType",NoFactory::get()),
177  "Aggregation region type was not provided by the user!");
178  }
179  if(currentLevel.IsAvailable("numDimensions", NoFactory::get())) {
180  currentLevel.DeclareInput("numDimensions", NoFactory::get(), this);
181  } else {
182  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("numDimensions", NoFactory::get()),
184  "numDimensions was not provided by the user on level0!");
185  }
186  if(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get())) {
187  currentLevel.DeclareInput("lNodesPerDim", NoFactory::get(), this);
188  } else {
189  TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get()),
191  "lNodesPerDim was not provided by the user on level0!");
192  }
193  } else {
194  Input(currentLevel, "aggregationRegionType");
195  Input(currentLevel, "numDimensions");
196  Input(currentLevel, "lNodesPerDim");
197  }
198 
199 
200 
201  /* UncoupledAggregation */
202  Input(currentLevel, "DofsPerNode");
203 
204  // request special data necessary for InterfaceAggregation
205  if (pL.get<bool>("aggregation: use interface aggregation") == true){
206  if(currentLevel.GetLevelID() == 0) {
207  if(currentLevel.IsAvailable("interfacesDimensions", NoFactory::get())) {
208  currentLevel.DeclareInput("interfacesDimensions", NoFactory::get(), this);
209  } else {
210  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("interfacesDimensions", NoFactory::get()),
212  "interfacesDimensions was not provided by the user on level0!");
213  }
214  if(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
215  currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
216  } else {
217  TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
219  "nodeOnInterface was not provided by the user on level0!");
220  }
221  } else {
222  Input(currentLevel, "interfacesDimensions");
223  Input(currentLevel, "nodeOnInterface");
224  }
225  }
226 
227  // request special data necessary for OnePtAggregationAlgorithm
228  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
229  if (mapOnePtName.length() > 0) {
230  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
231  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
232  currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
233  } else {
234  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
235  currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
236  }
237  }
238  } // DeclareInput()
239 
240  template <class LocalOrdinal, class GlobalOrdinal, class Node>
242  Build(Level &currentLevel) const {
243  FactoryMonitor m(*this, "Build", currentLevel);
244 
246  if(const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
247  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
248  out->setShowAllFrontMatter(false).setShowProcRank(true);
249  } else {
250  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
251  }
252 
253  *out << "Entering hybrid aggregation" << std::endl;
254 
255  ParameterList pL = GetParameterList();
256  bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
257 
258  if (pL.get<int>("aggregation: max agg size") == -1)
259  pL.set("aggregation: max agg size", INT_MAX);
260 
261  // define aggregation algorithms
262  RCP<const FactoryBase> graphFact = GetFactory("Graph");
263 
264  // General problem informations are gathered from data stored in the problem matix.
265  RCP<const GraphBase> graph = Get< RCP<GraphBase> >(currentLevel, "Graph");
266  RCP<const Map> fineMap = graph->GetDomainMap();
267  const int myRank = fineMap->getComm()->getRank();
268  const int numRanks = fineMap->getComm()->getSize();
269 
270  out->setProcRankAndSize(graph->GetImportMap()->getComm()->getRank(),
271  graph->GetImportMap()->getComm()->getSize());
272 
273  // Build aggregates
274  RCP<Aggregates> aggregates = rcp(new Aggregates(*graph));
275  aggregates->setObjectLabel("HB");
276 
277  // construct aggStat information
278  const LO numRows = graph->GetNodeNumVertices();
279  std::vector<unsigned> aggStat(numRows, READY);
280 
281  // Get aggregation type for region
282  std::string regionType;
283  if(currentLevel.GetLevelID() == 0) {
284  // On level 0, data is provided by applications and has no associated factory.
285  regionType = currentLevel.Get<std::string>("aggregationRegionType", NoFactory::get());
286  } else {
287  // On level > 0, data is provided directly by generating factories.
288  regionType = Get< std::string >(currentLevel, "aggregationRegionType");
289  }
290 
291  int numDimensions = 0;
292  if(currentLevel.GetLevelID() == 0) {
293  // On level 0, data is provided by applications and has no associated factory.
294  numDimensions = currentLevel.Get<int>("numDimensions", NoFactory::get());
295  } else {
296  // On level > 0, data is provided directly by generating factories.
297  numDimensions = Get<int>(currentLevel, "numDimensions");
298  }
299 
300  // Get the coarsening rate (potentially used for both structured and uncoupled aggregation if interface)
301  std::string coarseningRate = pL.get<std::string>("aggregation: coarsening rate");
302  Teuchos::Array<LO> coarseRate;
303  try {
304  coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
306  GetOStream(Errors,-1) << " *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
307  << std::endl;
308  throw e;
309  }
310  TEUCHOS_TEST_FOR_EXCEPTION((coarseRate.size() > 1) && (coarseRate.size() < numDimensions),
312  "\"aggregation: coarsening rate\" must have at least as many"
313  " components as the number of spatial dimensions in the problem.");
314 
315  algos_.clear();
316  LO numNonAggregatedNodes = numRows;
317  if (regionType == "structured") {
318  // Add AggregationStructuredAlgorithm
319  algos_.push_back(rcp(new AggregationStructuredAlgorithm(graphFact)));
320 
321  // Since we want to operate on nodes and not dof, we need to modify the rowMap in order to
322  // obtain a nodeMap.
323  const int interpolationOrder = pL.get<int>("aggregation: coarsening order");
324  Array<LO> lFineNodesPerDir(3);
325  if(currentLevel.GetLevelID() == 0) {
326  // On level 0, data is provided by applications and has no associated factory.
327  lFineNodesPerDir = currentLevel.Get<Array<LO> >("lNodesPerDim", NoFactory::get());
328  } else {
329  // On level > 0, data is provided directly by generating factories.
330  lFineNodesPerDir = Get<Array<LO> >(currentLevel, "lNodesPerDim");
331  }
332 
333  // Set lFineNodesPerDir to 1 for directions beyond numDimensions
334  for(int dim = numDimensions; dim < 3; ++dim) {
335  lFineNodesPerDir[dim] = 1;
336  }
337 
338  // Now that we have extracted info from the level, create the IndexManager
340  geoData = rcp(new MueLu::UncoupledIndexManager<LO,GO,NO>(fineMap->getComm(),
341  false,
342  numDimensions,
343  interpolationOrder,
344  myRank,
345  numRanks,
346  Array<GO>(3, -1),
347  lFineNodesPerDir,
348  coarseRate));
349 
350  TEUCHOS_TEST_FOR_EXCEPTION(fineMap->getNodeNumElements()
351  != static_cast<size_t>(geoData->getNumLocalFineNodes()),
353  "The local number of elements in the graph's map is not equal to "
354  "the number of nodes given by: lNodesPerDim!");
355 
356  aggregates->SetIndexManager(geoData);
357  aggregates->SetNumAggregates(geoData->getNumLocalCoarseNodes());
358 
359  Set(currentLevel, "lCoarseNodesPerDim", geoData->getLocalCoarseNodesPerDir());
360 
361  } // end structured aggregation setup
362 
363  if (regionType == "uncoupled"){
364  // Add unstructred aggregation phases
365  algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
366  if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm (graphFact)));
367  if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm (graphFact)));
368  if (pL.get<bool>("aggregation: enable phase 1" ) == true) algos_.push_back(rcp(new AggregationPhase1Algorithm (graphFact)));
369  if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm (graphFact)));
370  if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm (graphFact)));
371  if (pL.get<bool>("aggregation: enable phase 3" ) == true) algos_.push_back(rcp(new AggregationPhase3Algorithm (graphFact)));
372 
373  *out << " Build interface aggregates" << std::endl;
374  // interface
375  if (pL.get<bool>("aggregation: use interface aggregation") == true) {
376  BuildInterfaceAggregates(currentLevel, aggregates, aggStat, numNonAggregatedNodes,
377  coarseRate);
378  }
379 
380  *out << "Treat Dirichlet BC" << std::endl;
381  // Dirichlet boundary
382  ArrayRCP<const bool> dirichletBoundaryMap = graph->GetBoundaryNodeMap();
383  if (dirichletBoundaryMap != Teuchos::null)
384  for (LO i = 0; i < numRows; i++)
385  if (dirichletBoundaryMap[i] == true)
386  aggStat[i] = BOUNDARY;
387 
388  // OnePt aggregation
389  std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
390  RCP<Map> OnePtMap = Teuchos::null;
391  if (mapOnePtName.length()) {
392  std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
393  if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
394  OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, NoFactory::get());
395  } else {
396  RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
397  OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
398  }
399  }
400 
401  LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
402  GO indexBase = graph->GetDomainMap()->getIndexBase();
403  if (OnePtMap != Teuchos::null) {
404  for (LO i = 0; i < numRows; i++) {
405  // reconstruct global row id (FIXME only works for contiguous maps)
406  GO grid = (graph->GetDomainMap()->getGlobalElement(i)-indexBase) * nDofsPerNode + indexBase;
407  for (LO kr = 0; kr < nDofsPerNode; kr++)
408  if (OnePtMap->isNodeGlobalElement(grid + kr))
409  aggStat[i] = ONEPT;
410  }
411  }
412 
413  // Create a fake lCoarseNodesPerDir for CoordinatesTranferFactory
414  Array<LO> lCoarseNodesPerDir(3,-1);
415  Set(currentLevel, "lCoarseNodesPerDim", lCoarseNodesPerDir);
416  } // end uncoupled aggregation setup
417 
418  aggregates->AggregatesCrossProcessors(false); // No coupled aggregation
419 
420  *out << "Run all the algorithms on the local rank" << std::endl;
421  for (size_t a = 0; a < algos_.size(); a++) {
422  std::string phase = algos_[a]->description();
423  SubFactoryMonitor sfm(*this, "Algo \"" + phase + "\"", currentLevel);
424  *out << regionType <<" | Executing phase " << a << std::endl;
425 
426  int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
427  algos_[a]->BuildAggregates(pL, *graph, *aggregates, aggStat, numNonAggregatedNodes);
428  algos_[a]->SetProcRankVerbose(oldRank);
429  *out << regionType <<" | Done Executing phase " << a << std::endl;
430  }
431 
432  *out << "Compute statistics on aggregates" << std::endl;
433  aggregates->ComputeAggregateSizes(true/*forceRecompute*/);
434 
435  Set(currentLevel, "Aggregates", aggregates);
436  Set(currentLevel, "numDimensions", numDimensions);
437  Set(currentLevel, "aggregationRegionTypeCoarse", regionType);
438 
439  GetOStream(Statistics1) << aggregates->description() << std::endl;
440  *out << "HybridAggregation done!" << std::endl;
441  }
442 
443  template <class LocalOrdinal, class GlobalOrdinal, class Node>
446  std::vector<unsigned>& aggStat, LO& numNonAggregatedNodes,
447  Array<LO> coarseRate) const {
448  FactoryMonitor m(*this, "BuildInterfaceAggregates", currentLevel);
449 
451  if(const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
452  out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
453  out->setShowAllFrontMatter(false).setShowProcRank(true);
454  } else {
455  out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
456  }
457 
458  // Extract and format input data for algo
459  if(coarseRate.size() == 1) {coarseRate.resize(3, coarseRate[0]);}
460  ArrayRCP<LO> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
461  ArrayRCP<LO> procWinner = aggregates->GetProcWinner() ->getDataNonConst(0);
462  Array<LO> interfacesDimensions = Get<Array<LO> >(currentLevel, "interfacesDimensions");
463  Array<LO> nodesOnInterfaces = Get<Array<LO> >(currentLevel, "nodeOnInterface");
464  const int numInterfaces = interfacesDimensions.size() / 3;
465  const int myRank = aggregates->GetMap()->getComm()->getRank();
466 
467  // Create coarse level container to gather data on the fly
468  Array<LO> coarseInterfacesDimensions(interfacesDimensions.size());
469  Array<LO> nodesOnCoarseInterfaces;
470  { // Scoping the temporary variables...
471  LO endRate, totalNumCoarseNodes = 0, numCoarseNodes;
472  for(int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
473  numCoarseNodes = 1;
474  for(int dim = 0; dim < 3; ++dim) {
475  endRate = (interfacesDimensions[3*interfaceIdx + dim] - 1) % coarseRate[dim];
476  if(interfacesDimensions[3*interfaceIdx + dim] == 1) {
477  coarseInterfacesDimensions[3*interfaceIdx + dim] = 1;
478  } else {
479  coarseInterfacesDimensions[3*interfaceIdx + dim]
480  = (interfacesDimensions[3*interfaceIdx+dim]-1) / coarseRate[dim] + 2;
481  if(endRate==0){ coarseInterfacesDimensions[3*interfaceIdx + dim]--;}
482  }
483  numCoarseNodes *= coarseInterfacesDimensions[3*interfaceIdx + dim];
484  }
485  totalNumCoarseNodes += numCoarseNodes;
486  }
487  nodesOnCoarseInterfaces.resize(totalNumCoarseNodes, -1);
488  }
489 
490  Array<LO> endRate(3);
491  LO interfaceOffset = 0, aggregateCount = 0, coarseNodeCount = 0;
492  for(int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
493  ArrayView<LO> fineNodesPerDim = interfacesDimensions(3*interfaceIdx, 3);
494  ArrayView<LO> coarseNodesPerDim = coarseInterfacesDimensions(3*interfaceIdx, 3);
495  LO numInterfaceNodes = 1, numCoarseNodes = 1;
496  for(int dim = 0; dim < 3; ++dim) {
497  numInterfaceNodes *= fineNodesPerDim[dim];
498  numCoarseNodes *= coarseNodesPerDim[dim];
499  endRate[dim] = fineNodesPerDim[dim] % coarseRate[dim];
500  }
501  ArrayView<LO> interfaceNodes = nodesOnInterfaces(interfaceOffset, numInterfaceNodes);
502 
503  interfaceOffset += numInterfaceNodes;
504 
505  LO rem, rate, fineNodeIdx;
506  Array<LO> nodeIJK(3), coarseIJK(3), rootIJK(3);
507  // First find treat coarse nodes as they generate the aggregate IDs
508  // and they might be repeated on multiple interfaces (think corners and edges).
509  for(LO coarseNodeIdx = 0; coarseNodeIdx < numCoarseNodes; ++coarseNodeIdx) {
510  coarseIJK[2] = coarseNodeIdx / (coarseNodesPerDim[0]*coarseNodesPerDim[1]);
511  rem = coarseNodeIdx % (coarseNodesPerDim[0]*coarseNodesPerDim[1]);
512  coarseIJK[1] = rem / coarseNodesPerDim[0];
513  coarseIJK[0] = rem % coarseNodesPerDim[0];
514 
515  for(LO dim = 0; dim < 3; ++dim) {
516  if(coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
517  nodeIJK[dim] = fineNodesPerDim[dim] - 1;
518  } else {
519  nodeIJK[dim] = coarseIJK[dim]*coarseRate[dim];
520  }
521  }
522  fineNodeIdx = (nodeIJK[2]*fineNodesPerDim[1] + nodeIJK[1])*fineNodesPerDim[0] + nodeIJK[0];
523 
524  if(aggStat[interfaceNodes[fineNodeIdx]] == READY) {
525  vertex2AggId[interfaceNodes[fineNodeIdx]] = aggregateCount;
526  procWinner[interfaceNodes[fineNodeIdx]] = myRank;
527  aggStat[interfaceNodes[fineNodeIdx]] = AGGREGATED;
528  ++aggregateCount;
529  --numNonAggregatedNodes;
530  }
531  nodesOnCoarseInterfaces[coarseNodeCount] = vertex2AggId[interfaceNodes[fineNodeIdx]];
532  ++coarseNodeCount;
533  }
534 
535  // Now loop over all the node on the interface
536  // skip the coarse nodes as they are already aggregated
537  // and find the appropriate aggregate ID for the fine nodes.
538  for(LO nodeIdx = 0; nodeIdx < numInterfaceNodes; ++nodeIdx) {
539 
540  // If the node is already aggregated skip it!
541  if(aggStat[interfaceNodes[nodeIdx]] == AGGREGATED) {continue;}
542 
543  nodeIJK[2] = nodeIdx / (fineNodesPerDim[0]*fineNodesPerDim[1]);
544  rem = nodeIdx % (fineNodesPerDim[0]*fineNodesPerDim[1]);
545  nodeIJK[1] = rem / fineNodesPerDim[0];
546  nodeIJK[0] = rem % fineNodesPerDim[0];
547 
548  for(int dim = 0; dim < 3; ++dim) {
549  coarseIJK[dim] = nodeIJK[dim] / coarseRate[dim];
550  rem = nodeIJK[dim] % coarseRate[dim];
551  if(nodeIJK[dim] < fineNodesPerDim[dim] - endRate[dim]) {
552  rate = coarseRate[dim];
553  } else {
554  rate = endRate[dim];
555  }
556  if(rem > (rate / 2)) {++coarseIJK[dim];}
557  if(coarseNodesPerDim[dim] - coarseIJK[dim] > fineNodesPerDim[dim]-nodeIJK[dim]){
558  ++coarseIJK[dim];
559  }
560  }
561 
562  for(LO dim = 0; dim < 3; ++dim) {
563  if(coarseIJK[dim] == coarseNodesPerDim[dim] - 1) {
564  nodeIJK[dim] = fineNodesPerDim[dim] - 1;
565  } else {
566  nodeIJK[dim] = coarseIJK[dim]*coarseRate[dim];
567  }
568  }
569  fineNodeIdx = (nodeIJK[2]*fineNodesPerDim[1] + nodeIJK[1])*fineNodesPerDim[0] + nodeIJK[0];
570 
571  vertex2AggId[interfaceNodes[nodeIdx]] = vertex2AggId[interfaceNodes[fineNodeIdx]];
572  procWinner[interfaceNodes[nodeIdx]] = myRank;
573  aggStat[interfaceNodes[nodeIdx]] = AGGREGATED;
574  --numNonAggregatedNodes;
575  } // Loop over interface nodes
576  } // Loop over the interfaces
577 
578  // Update aggregates information before subsequent aggregation algorithms
579  aggregates->SetNumAggregates(aggregateCount);
580 
581  // Set coarse data for next level
582  Set(currentLevel, "coarseInterfacesDimensions", coarseInterfacesDimensions);
583  Set(currentLevel, "nodeOnCoarseInterface", nodesOnCoarseInterfaces);
584 
585  } // BuildInterfaceAggregates()
586 
587 } //namespace MueLu
588 
589 
590 #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)
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
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.