MueLu Version of the Day
Loading...
Searching...
No Matches
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
62#include "MueLu_AggregationPhase1Algorithm.hpp"
63#include "MueLu_AggregationPhase2aAlgorithm.hpp"
64#include "MueLu_AggregationPhase2bAlgorithm.hpp"
65#include "MueLu_AggregationPhase3Algorithm.hpp"
66
67// Structured Agg
68#include "MueLu_AggregationStructuredAlgorithm.hpp"
69#include "MueLu_UncoupledIndexManager.hpp"
70//#include "MueLu_LocalLexicographicIndexManager.hpp"
71//#include "MueLu_GlobalLexicographicIndexManager.hpp"
72
73// Shared
74#include "MueLu_Level.hpp"
75#include "MueLu_GraphBase.hpp"
76#include "MueLu_Aggregates.hpp"
77#include "MueLu_MasterList.hpp"
78#include "MueLu_Monitor.hpp"
79
80
81namespace MueLu {
82
83 template <class LocalOrdinal, class GlobalOrdinal, class Node>
87
88 template <class LocalOrdinal, class GlobalOrdinal, class Node>
91 RCP<ParameterList> validParamList = rcp(new ParameterList());
92
93 typedef Teuchos::StringToIntegralParameterEntryValidator<int> validatorType;
94#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
95 // From UncoupledAggregationFactory
96 SET_VALID_ENTRY("aggregation: max agg size");
97 SET_VALID_ENTRY("aggregation: min agg size");
98 SET_VALID_ENTRY("aggregation: max selected neighbors");
99 SET_VALID_ENTRY("aggregation: ordering");
100 validParamList->getEntry("aggregation: ordering").setValidator(
101 rcp(new validatorType(Teuchos::tuple<std::string>("natural", "graph", "random"), "aggregation: ordering")));
102 SET_VALID_ENTRY("aggregation: enable phase 1");
103 SET_VALID_ENTRY("aggregation: enable phase 2a");
104 SET_VALID_ENTRY("aggregation: enable phase 2b");
105 SET_VALID_ENTRY("aggregation: enable phase 3");
106 SET_VALID_ENTRY("aggregation: preserve Dirichlet points");
107 SET_VALID_ENTRY("aggregation: allow user-specified singletons");
108 SET_VALID_ENTRY("aggregation: error on nodes with no on-rank neighbors");
109 SET_VALID_ENTRY("aggregation: match ML phase2a");
110 SET_VALID_ENTRY("aggregation: phase2a agg factor");
111 SET_VALID_ENTRY("aggregation: phase3 avoid singletons");
112
113 // From StructuredAggregationFactory
114 SET_VALID_ENTRY("aggregation: coarsening rate");
115 SET_VALID_ENTRY("aggregation: coarsening order");
116 SET_VALID_ENTRY("aggregation: number of spatial dimensions");
117
118 // From HybridAggregationFactory
119 SET_VALID_ENTRY("aggregation: use interface aggregation");
120#undef SET_VALID_ENTRY
121
122 /* From UncoupledAggregation */
123 // general variables needed in AggregationFactory
124 validParamList->set< RCP<const FactoryBase> >("Graph", null, "Generating factory of the graph");
125 validParamList->set< RCP<const FactoryBase> >("DofsPerNode", null, "Generating factory for variable \'DofsPerNode\', usually the same as for \'Graph\'");
126 // special variables necessary for OnePtAggregationAlgorithm
127 validParamList->set<std::string> ("OnePt aggregate map name", "",
128 "Name of input map for single node aggregates. (default='')");
129 validParamList->set<std::string> ("OnePt aggregate map factory", "",
130 "Generating factory of (DOF) map for single node aggregates.");
131
132 // InterfaceAggregation parameters
133 validParamList->set<std::string> ("Interface aggregate map name", "",
134 "Name of input map for interface aggregates. (default='')");
135 validParamList->set<std::string> ("Interface aggregate map factory", "",
136 "Generating factory of (DOF) map for interface aggregates.");
137 validParamList->set<RCP<const FactoryBase> > ("interfacesDimensions", Teuchos::null,
138 "Describes the dimensions of all the interfaces on this rank.");
139 validParamList->set<RCP<const FactoryBase> > ("nodeOnInterface", Teuchos::null,
140 "List the LIDs of the nodes on any interface.");
141
142 /* From StructuredAggregation */
143 // general variables needed in AggregationFactory
144 validParamList->set<RCP<const FactoryBase> >("numDimensions", Teuchos::null,
145 "Number of spatial dimension provided by CoordinatesTransferFactory.");
146 validParamList->set<RCP<const FactoryBase> >("lNodesPerDim", Teuchos::null,
147 "Number of nodes per spatial dimmension provided by CoordinatesTransferFactory.");
148
149
150 // Hybrid Aggregation Params
151 validParamList->set<RCP<const FactoryBase> > ("aggregationRegionType", Teuchos::null,
152 "Type of aggregation to use on the region (\"structured\" or \"uncoupled\")");
153
154 return validParamList;
155 }
156
157 template <class LocalOrdinal, class GlobalOrdinal, class Node>
159 DeclareInput(Level& currentLevel) const {
160 Input(currentLevel, "Graph");
161
162 ParameterList pL = GetParameterList();
163
164
165
166 /* StructuredAggregation */
167
168 // Request the local number of nodes per dimensions
169 if(currentLevel.GetLevelID() == 0) {
170 if(currentLevel.IsAvailable("aggregationRegionType", NoFactory::get())) {
171 currentLevel.DeclareInput("aggregationRegionType", NoFactory::get(), this);
172 } else {
173 TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("aggregationRegionType",NoFactory::get()),
175 "Aggregation region type was not provided by the user!");
176 }
177 if(currentLevel.IsAvailable("numDimensions", NoFactory::get())) {
178 currentLevel.DeclareInput("numDimensions", NoFactory::get(), this);
179 } else {
180 TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("numDimensions", NoFactory::get()),
182 "numDimensions was not provided by the user on level0!");
183 }
184 if(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get())) {
185 currentLevel.DeclareInput("lNodesPerDim", NoFactory::get(), this);
186 } else {
187 TEUCHOS_TEST_FOR_EXCEPTION(currentLevel.IsAvailable("lNodesPerDim", NoFactory::get()),
189 "lNodesPerDim was not provided by the user on level0!");
190 }
191 } else {
192 Input(currentLevel, "aggregationRegionType");
193 Input(currentLevel, "numDimensions");
194 Input(currentLevel, "lNodesPerDim");
195 }
196
197
198
199 /* UncoupledAggregation */
200 Input(currentLevel, "DofsPerNode");
201
202 // request special data necessary for InterfaceAggregation
203 if (pL.get<bool>("aggregation: use interface aggregation") == true){
204 if(currentLevel.GetLevelID() == 0) {
205 if(currentLevel.IsAvailable("interfacesDimensions", NoFactory::get())) {
206 currentLevel.DeclareInput("interfacesDimensions", NoFactory::get(), this);
207 } else {
208 TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("interfacesDimensions", NoFactory::get()),
210 "interfacesDimensions was not provided by the user on level0!");
211 }
212 if(currentLevel.IsAvailable("nodeOnInterface", NoFactory::get())) {
213 currentLevel.DeclareInput("nodeOnInterface", NoFactory::get(), this);
214 } else {
215 TEUCHOS_TEST_FOR_EXCEPTION(!currentLevel.IsAvailable("nodeOnInterface", NoFactory::get()),
217 "nodeOnInterface was not provided by the user on level0!");
218 }
219 } else {
220 Input(currentLevel, "interfacesDimensions");
221 Input(currentLevel, "nodeOnInterface");
222 }
223 }
224
225 // request special data necessary for OnePtAggregationAlgorithm
226 std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
227 if (mapOnePtName.length() > 0) {
228 std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
229 if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
230 currentLevel.DeclareInput(mapOnePtName, NoFactory::get());
231 } else {
232 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
233 currentLevel.DeclareInput(mapOnePtName, mapOnePtFact.get());
234 }
235 }
236 } // DeclareInput()
237
238 template <class LocalOrdinal, class GlobalOrdinal, class Node>
240 Build(Level &currentLevel) const {
241 FactoryMonitor m(*this, "Build", currentLevel);
242
243 RCP<Teuchos::FancyOStream> out;
244 if(const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
245 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
246 out->setShowAllFrontMatter(false).setShowProcRank(true);
247 } else {
248 out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
249 }
250
251 *out << "Entering hybrid aggregation" << std::endl;
252
253 ParameterList pL = GetParameterList();
254 bDefinitionPhase_ = false; // definition phase is finished, now all aggregation algorithm information is fixed
255
256 if (pL.get<int>("aggregation: max agg size") == -1)
257 pL.set("aggregation: max agg size", INT_MAX);
258
259 // define aggregation algorithms
260 RCP<const FactoryBase> graphFact = GetFactory("Graph");
261
262 // General problem informations are gathered from data stored in the problem matix.
263 RCP<const GraphBase> graph = Get< RCP<GraphBase> >(currentLevel, "Graph");
264 RCP<const Map> fineMap = graph->GetDomainMap();
265 const int myRank = fineMap->getComm()->getRank();
266 const int numRanks = fineMap->getComm()->getSize();
267
268 out->setProcRankAndSize(graph->GetImportMap()->getComm()->getRank(),
269 graph->GetImportMap()->getComm()->getSize());
270
271 // Build aggregates
272 RCP<Aggregates> aggregates = rcp(new Aggregates(*graph));
273 aggregates->setObjectLabel("HB");
274
275 // construct aggStat information
276 const LO numRows = graph->GetNodeNumVertices();
277 std::vector<unsigned> aggStat(numRows, READY);
278
279 // Get aggregation type for region
280 std::string regionType;
281 if(currentLevel.GetLevelID() == 0) {
282 // On level 0, data is provided by applications and has no associated factory.
283 regionType = currentLevel.Get<std::string>("aggregationRegionType", NoFactory::get());
284 } else {
285 // On level > 0, data is provided directly by generating factories.
286 regionType = Get< std::string >(currentLevel, "aggregationRegionType");
287 }
288
289 int numDimensions = 0;
290 if(currentLevel.GetLevelID() == 0) {
291 // On level 0, data is provided by applications and has no associated factory.
292 numDimensions = currentLevel.Get<int>("numDimensions", NoFactory::get());
293 } else {
294 // On level > 0, data is provided directly by generating factories.
295 numDimensions = Get<int>(currentLevel, "numDimensions");
296 }
297
298 // Get the coarsening rate (potentially used for both structured and uncoupled aggregation if interface)
299 std::string coarseningRate = pL.get<std::string>("aggregation: coarsening rate");
300 Teuchos::Array<LO> coarseRate;
301 try {
302 coarseRate = Teuchos::fromStringToArray<LO>(coarseningRate);
303 } catch(const Teuchos::InvalidArrayStringRepresentation& e) {
304 GetOStream(Errors,-1) << " *** \"aggregation: coarsening rate\" must be a string convertible into an array! *** "
305 << std::endl;
306 throw e;
307 }
308 TEUCHOS_TEST_FOR_EXCEPTION((coarseRate.size() > 1) && (coarseRate.size() < numDimensions),
310 "\"aggregation: coarsening rate\" must have at least as many"
311 " components as the number of spatial dimensions in the problem.");
312
313 algos_.clear();
314 LO numNonAggregatedNodes = numRows;
315 if (regionType == "structured") {
316 // Add AggregationStructuredAlgorithm
317 algos_.push_back(rcp(new AggregationStructuredAlgorithm(graphFact)));
318
319 // Since we want to operate on nodes and not dof, we need to modify the rowMap in order to
320 // obtain a nodeMap.
321 const int interpolationOrder = pL.get<int>("aggregation: coarsening order");
322 Array<LO> lFineNodesPerDir(3);
323 if(currentLevel.GetLevelID() == 0) {
324 // On level 0, data is provided by applications and has no associated factory.
325 lFineNodesPerDir = currentLevel.Get<Array<LO> >("lNodesPerDim", NoFactory::get());
326 } else {
327 // On level > 0, data is provided directly by generating factories.
328 lFineNodesPerDir = Get<Array<LO> >(currentLevel, "lNodesPerDim");
329 }
330
331 // Set lFineNodesPerDir to 1 for directions beyond numDimensions
332 for(int dim = numDimensions; dim < 3; ++dim) {
333 lFineNodesPerDir[dim] = 1;
334 }
335
336 // Now that we have extracted info from the level, create the IndexManager
337 RCP<MueLu::IndexManager<LO,GO,NO> > geoData;
338 geoData = rcp(new MueLu::UncoupledIndexManager<LO,GO,NO>(fineMap->getComm(),
339 false,
340 numDimensions,
341 interpolationOrder,
342 myRank,
343 numRanks,
344 Array<GO>(3, -1),
345 lFineNodesPerDir,
346 coarseRate, false));
347
348 TEUCHOS_TEST_FOR_EXCEPTION(fineMap->getLocalNumElements()
349 != static_cast<size_t>(geoData->getNumLocalFineNodes()),
351 "The local number of elements in the graph's map is not equal to "
352 "the number of nodes given by: lNodesPerDim!");
353
354 aggregates->SetIndexManager(geoData);
355 aggregates->SetNumAggregates(geoData->getNumLocalCoarseNodes());
356
357 Set(currentLevel, "lCoarseNodesPerDim", geoData->getLocalCoarseNodesPerDir());
358
359 } // end structured aggregation setup
360
361 if (regionType == "uncoupled"){
362 // Add unstructred aggregation phases
363 algos_.push_back(rcp(new PreserveDirichletAggregationAlgorithm(graphFact)));
364 if (pL.get<bool>("aggregation: use interface aggregation") == true) algos_.push_back(rcp(new InterfaceAggregationAlgorithm (graphFact)));
365 if (pL.get<bool>("aggregation: allow user-specified singletons") == true) algos_.push_back(rcp(new OnePtAggregationAlgorithm (graphFact)));
366 if (pL.get<bool>("aggregation: enable phase 1" ) == true) algos_.push_back(rcp(new AggregationPhase1Algorithm (graphFact)));
367 if (pL.get<bool>("aggregation: enable phase 2a") == true) algos_.push_back(rcp(new AggregationPhase2aAlgorithm (graphFact)));
368 if (pL.get<bool>("aggregation: enable phase 2b") == true) algos_.push_back(rcp(new AggregationPhase2bAlgorithm (graphFact)));
369 if (pL.get<bool>("aggregation: enable phase 3" ) == true) algos_.push_back(rcp(new AggregationPhase3Algorithm (graphFact)));
370
371 *out << " Build interface aggregates" << std::endl;
372 // interface
373 if (pL.get<bool>("aggregation: use interface aggregation") == true) {
374 BuildInterfaceAggregates(currentLevel, aggregates, aggStat, numNonAggregatedNodes,
375 coarseRate);
376 }
377
378 *out << "Treat Dirichlet BC" << std::endl;
379 // Dirichlet boundary
380 ArrayRCP<const bool> dirichletBoundaryMap = graph->GetBoundaryNodeMap();
381 if (dirichletBoundaryMap != Teuchos::null)
382 for (LO i = 0; i < numRows; i++)
383 if (dirichletBoundaryMap[i] == true)
384 aggStat[i] = BOUNDARY;
385
386 // OnePt aggregation
387 std::string mapOnePtName = pL.get<std::string>("OnePt aggregate map name");
388 RCP<Map> OnePtMap = Teuchos::null;
389 if (mapOnePtName.length()) {
390 std::string mapOnePtFactName = pL.get<std::string>("OnePt aggregate map factory");
391 if (mapOnePtFactName == "" || mapOnePtFactName == "NoFactory") {
392 OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, NoFactory::get());
393 } else {
394 RCP<const FactoryBase> mapOnePtFact = GetFactory(mapOnePtFactName);
395 OnePtMap = currentLevel.Get<RCP<Map> >(mapOnePtName, mapOnePtFact.get());
396 }
397 }
398
399 LO nDofsPerNode = Get<LO>(currentLevel, "DofsPerNode");
400 GO indexBase = graph->GetDomainMap()->getIndexBase();
401 if (OnePtMap != Teuchos::null) {
402 for (LO i = 0; i < numRows; i++) {
403 // reconstruct global row id (FIXME only works for contiguous maps)
404 GO grid = (graph->GetDomainMap()->getGlobalElement(i)-indexBase) * nDofsPerNode + indexBase;
405 for (LO kr = 0; kr < nDofsPerNode; kr++)
406 if (OnePtMap->isNodeGlobalElement(grid + kr))
407 aggStat[i] = ONEPT;
408 }
409 }
410
411 // Create a fake lCoarseNodesPerDir for CoordinatesTranferFactory
412 Array<LO> lCoarseNodesPerDir(3,-1);
413 Set(currentLevel, "lCoarseNodesPerDim", lCoarseNodesPerDir);
414 } // end uncoupled aggregation setup
415
416 aggregates->AggregatesCrossProcessors(false); // No coupled aggregation
417
418 *out << "Run all the algorithms on the local rank" << std::endl;
419 for (size_t a = 0; a < algos_.size(); a++) {
420 std::string phase = algos_[a]->description();
421 SubFactoryMonitor sfm(*this, "Algo \"" + phase + "\"", currentLevel);
422 *out << regionType <<" | Executing phase " << a << std::endl;
423
424 int oldRank = algos_[a]->SetProcRankVerbose(this->GetProcRankVerbose());
425 algos_[a]->BuildAggregates(pL, *graph, *aggregates, aggStat, numNonAggregatedNodes);
426 algos_[a]->SetProcRankVerbose(oldRank);
427 *out << regionType <<" | Done Executing phase " << a << std::endl;
428 }
429
430 *out << "Compute statistics on aggregates" << std::endl;
431 aggregates->ComputeAggregateSizes(true/*forceRecompute*/);
432
433 Set(currentLevel, "Aggregates", aggregates);
434 Set(currentLevel, "numDimensions", numDimensions);
435 Set(currentLevel, "aggregationRegionTypeCoarse", regionType);
436
437 GetOStream(Statistics1) << aggregates->description() << std::endl;
438 *out << "HybridAggregation done!" << std::endl;
439 }
440
441 template <class LocalOrdinal, class GlobalOrdinal, class Node>
443 BuildInterfaceAggregates(Level& currentLevel, RCP<Aggregates> aggregates,
444 std::vector<unsigned>& aggStat, LO& numNonAggregatedNodes,
445 Array<LO> coarseRate) const {
446 FactoryMonitor m(*this, "BuildInterfaceAggregates", currentLevel);
447
448 RCP<Teuchos::FancyOStream> out;
449 if(const char* dbg = std::getenv("MUELU_HYBRIDAGGREGATION_DEBUG")) {
450 out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
451 out->setShowAllFrontMatter(false).setShowProcRank(true);
452 } else {
453 out = Teuchos::getFancyOStream(rcp(new Teuchos::oblackholestream()));
454 }
455
456 // Extract and format input data for algo
457 if(coarseRate.size() == 1) {coarseRate.resize(3, coarseRate[0]);}
458 ArrayRCP<LO> vertex2AggId = aggregates->GetVertex2AggId()->getDataNonConst(0);
459 ArrayRCP<LO> procWinner = aggregates->GetProcWinner() ->getDataNonConst(0);
460 Array<LO> interfacesDimensions = Get<Array<LO> >(currentLevel, "interfacesDimensions");
461 Array<LO> nodesOnInterfaces = Get<Array<LO> >(currentLevel, "nodeOnInterface");
462 const int numInterfaces = interfacesDimensions.size() / 3;
463 const int myRank = aggregates->GetMap()->getComm()->getRank();
464
465 // Create coarse level container to gather data on the fly
466 Array<LO> coarseInterfacesDimensions(interfacesDimensions.size());
467 Array<LO> nodesOnCoarseInterfaces;
468 { // Scoping the temporary variables...
469 LO endRate, totalNumCoarseNodes = 0, numCoarseNodes;
470 for(int interfaceIdx = 0; interfaceIdx < numInterfaces; ++interfaceIdx) {
471 numCoarseNodes = 1;
472 for(int dim = 0; dim < 3; ++dim) {
473 endRate = (interfacesDimensions[3*interfaceIdx + dim] - 1) % coarseRate[dim];
474 if(interfacesDimensions[3*interfaceIdx + dim] == 1) {
475 coarseInterfacesDimensions[3*interfaceIdx + dim] = 1;
476 } else {
477 coarseInterfacesDimensions[3*interfaceIdx + dim]
478 = (interfacesDimensions[3*interfaceIdx+dim]-1) / coarseRate[dim] + 2;
479 if(endRate==0){ coarseInterfacesDimensions[3*interfaceIdx + dim]--;}
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]-1) % 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 */
#define SET_VALID_ENTRY(name)
Container class for aggregation information.
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
MueLu::PreserveDirichletAggregationAlgorithm< LocalOrdinal, GlobalOrdinal, Node > PreserveDirichletAggregationAlgorithm
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
MueLu::InterfaceAggregationAlgorithm< LocalOrdinal, GlobalOrdinal, Node > InterfaceAggregationAlgorithm
void DeclareInput(Level &currentLevel) const
Input.
MueLu::AggregationPhase1Algorithm< LocalOrdinal, GlobalOrdinal, Node > AggregationPhase1Algorithm
MueLu::AggregationPhase2bAlgorithm< LocalOrdinal, GlobalOrdinal, Node > AggregationPhase2bAlgorithm
MueLu::AggregationPhase2aAlgorithm< LocalOrdinal, GlobalOrdinal, Node > AggregationPhase2aAlgorithm
void Build(Level &currentLevel) const
Build aggregates.
MueLu::AggregationStructuredAlgorithm< LocalOrdinal, GlobalOrdinal, Node > AggregationStructuredAlgorithm
MueLu::AggregationPhase3Algorithm< LocalOrdinal, GlobalOrdinal, Node > AggregationPhase3Algorithm
void BuildInterfaceAggregates(Level &currentLevel, RCP< Aggregates > aggregates, std::vector< unsigned > &aggStat, LO &numNonAggregatedNodes, Array< LO > coarseRate) const
Specifically build aggregates along interfaces.
MueLu::OnePtAggregationAlgorithm< LocalOrdinal, GlobalOrdinal, Node > OnePtAggregationAlgorithm
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()
virtual const Teuchos::ParameterList & GetParameterList() const
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.