MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_CoupledAggregationCommHelper_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_COUPLEDAGGREGATIONCOMMHELPER_DEF_HPP
47#define MUELU_COUPLEDAGGREGATIONCOMMHELPER_DEF_HPP
48
49#include <Xpetra_MapFactory.hpp>
50#include <Xpetra_BlockedMultiVector.hpp>
51#include <Xpetra_BlockedVector.hpp>
52#include <Xpetra_VectorFactory.hpp>
53#include <Xpetra_MultiVectorFactory.hpp>
54#include <Xpetra_ImportFactory.hpp>
55#include <Xpetra_ExportFactory.hpp>
56
58
59#include "MueLu_Utilities.hpp" // MueLu_maxAll
60
61namespace MueLu {
62
63 template <class LocalOrdinal, class GlobalOrdinal, class Node>
64 CoupledAggregationCommHelper<LocalOrdinal, GlobalOrdinal, Node>::CoupledAggregationCommHelper(const RCP<const Map> & uniqueMap, const RCP<const Map> & nonUniqueMap) {
65 import_ = ImportFactory::Build(uniqueMap, nonUniqueMap);
66 tempVec_ = VectorFactory::Build(uniqueMap,false); //zeroed out before use
67 numMyWinners_ = 0;
68 numCalls_ = 0;
69 myPID_ = uniqueMap->getComm()->getRank();
70 }
71
72 template <class LocalOrdinal, class GlobalOrdinal, class Node>
73 void CoupledAggregationCommHelper<LocalOrdinal, GlobalOrdinal, Node>::ArbitrateAndCommunicate(Vector &weight_, LOVector &procWinner_, LOMultiVector *companion, const bool perturb) const {
74 const RCP<const Map> weightMap = weight_.getMap();
75 const size_t nodeNumElements = weightMap->getLocalNumElements();
76 const RCP<const Teuchos::Comm<int> > & comm = weightMap->getComm();
77 int MyPid = comm->getRank(); // TODO:remove the getMap() step
78 ++numCalls_;
79
80 //short-circuit if only one process
81 if (comm->getSize() == 1) {
82 ArrayRCP<SC> serialWeight = weight_.getDataNonConst(0);
83 ArrayRCP<LO> serialProcWinner = procWinner_.getDataNonConst(0);
84 for (size_t i=0; i < nodeNumElements; ++i) {
85 if (serialWeight[i] > 0) {
86 serialWeight[i] = 0;
87 serialProcWinner[i] = MyPid;
88 }
89 }
90 //companion doesn't change
91 return;
92 }
93
94#ifdef COMPARE_IN_OUT_VECTORS
95 RCP<Vector> in_weight_ = VectorFactory::Build(weight_.getMap());
96 {
97 ArrayRCP<SC> in_weight = in_weight_->getDataNonConst(0);
98 ArrayRCP<SC> weight = weight_.getDataNonConst(0);
99 for (size_t i=0; i < nodeNumElements; ++i) in_weight[i] = weight[i];
100 }
101 RCP<LOVector> in_procWinner_ = LOVectorFactory::Build(procWinner_.getMap());
102 {
103 ArrayRCP<LO> in_procWinner = in_procWinner_->getDataNonConst(0);
104 ArrayRCP<LO> procWinner = procWinner_.getDataNonConst(0);
105 for (size_t i=0; i < nodeNumElements; ++i) in_procWinner[i] = procWinner[i];
106 }
107 RCP<LOMultiVector> in_companion;
108 {
109 if (companion != NULL) {
110 in_companion = LOMultiVectorFactory::Build(companion->getMap(), companion->getNumVectors());
111 ArrayRCP<LO> in_comp = in_companion->getDataNonConst(0);
112 ArrayRCP<LO> comp = companion->getDataNonConst(0);
113 for (size_t i=0; i < nodeNumElements; ++i) in_comp[i] = comp[i];
114 }
115 }
116#endif
117
118 typedef Teuchos::ScalarTraits<SC> ST;
119
120 if (perturb) {
121 if (perturbWt_ == Teuchos::null || !perturbWt_->getMap()->isSameAs(*weightMap)) {
122 perturbWt_ = VectorFactory::Build(weightMap,false); //no need to zero out because this will be randomized
123
124 // Modify seed of the random algorithm used by perturbWt_->randomize()
125 {
126 ST::seedrandom( Teuchos::as<unsigned int>(MyPid*47) );
127 for (int i = 0; i < 10; ++i) ST::random();
128 }
129 //Note that we must not use perturbWt_->randomize(). This produces the same
130 //local random vector on each processor. The whole point of the weights
131 //is to provide tie-breaking that isn't based on the highest PID.
132 ArrayRCP<SC> lperturbWt = perturbWt_->getDataNonConst(0);
133 for (size_t i=0; i < nodeNumElements; ++i)
134 lperturbWt[i] = 1e-7*fabs(ST::random()); //FIXME this won't work for general SC
135#ifdef COMPARE_IN_OUT_VECTORS
136 ArrayRCP<SC> locperturbWt = perturbWt_->getDataNonConst(0);
137 for (size_t i=0; i < nodeNumElements; ++i)
138 printf("perturbWt[%d] = %15.10e\n",i,locperturbWt[i]);
139#endif
140 } //if (perturbWt_ == Teuchos::null || ...
141
142 ArrayRCP<SC> weight = weight_.getDataNonConst(0); // TODO: const?
143 ArrayRCP<SC> perturbWt = perturbWt_->getDataNonConst(0);
144
145 // Note: maxValue() not available for Tpetra
146 //SC largestGlobalWeight = weight_.maxValue();
147 SC largestGlobalWeight = weight_.normInf();
148 for (size_t i=0; i < nodeNumElements; ++i) {
149 if (weight[i] != 0.) {
150 weight[i] += largestGlobalWeight*perturbWt[i];
151 }
152 }
153 //TODO is it necessary to return the *perturbed* weights?
154 } //if (perturb)
155
156 // Communicate weights and store results in PostComm (which will be copied
157 // back into weights later. When multiple processors have different weights
158 // for the same GID, we take the largest weight. After this fragment every
159 // processor should have the same value for PostComm[] even when multiple
160 // copies of the same Gid are involved.
161
162 if (postComm_ == Teuchos::null || !postComm_->getMap()->isSameAs(*weightMap) )
163 postComm_ = VectorFactory::Build(weightMap);
164
165 //note: postComm_ is zeroed either in build above, or in loop below upon last touch.
166
167 NonUnique2NonUnique(weight_, *postComm_, Xpetra::ABSMAX);
168
169 // Let every processor know who is the procWinner. For nonunique
170 // copies of the same Gid, this corresponds to the processor with
171 // the highest Wt[]. When several processors have the same positive value
172 // for weight[] (which is also the maximum value), the highest proc id
173 // is declared the procWinner.
174 //
175 // Note:This is accomplished by filling a vector with MyPid+1 if weight[k] is
176 // nonzero and PostComm[k]==weight[k]. NonUnique2NonUnique(...,AbsMax)
177 // is invoked to let everyone know the procWinner.
178 // One is then subtracted so that procWinner[i] indicates the
179 // Pid of the winning processor.
180 // When all weight's for a GID are zero, the associated procWinner's
181 // are left untouched.
182
183 if (candidateWinners_ == Teuchos::null || !candidateWinners_->getMap()->isSameAs(*weightMap) )
184 candidateWinners_ = VectorFactory::Build(weightMap,false);
185 //note: candidateWinners_ is initialized below
186
187 ArrayRCP<SC> weight = weight_.getDataNonConst(0);
188
189 {
190 ArrayRCP<SC> candidateWinners = candidateWinners_->getDataNonConst(0);
191 ArrayRCP<SC> postComm = postComm_->getDataNonConst(0);
192 for (size_t i=0; i < nodeNumElements; ++i) {
193 if (postComm[i] == weight[i]) candidateWinners[i] = (SC) MyPid+1;
194 else candidateWinners[i] = 0;
195 weight[i]=postComm[i];
196 }
197 }
198 NonUnique2NonUnique(*candidateWinners_, *postComm_, Xpetra::ABSMAX);
199
200 // Note:
201 // associated CandidateWinners[]
202 // weight[i]!=0 ==> on some proc is equal to its ==> postComm[i]!=0
203 // MyPid+1.
204 //
205 int numMyWinners = 0;
206 ArrayRCP<LO> procWinner = procWinner_.getDataNonConst(0);
207 {
208 ArrayRCP<SC> postComm = postComm_->getDataNonConst(0);
209 for (size_t i=0; i < nodeNumElements; ++i) {
210 if ( weight[i] != 0.) procWinner[i] = ((int) (postComm[i])) - 1;
211 weight[i] = 0.; //we are done with weight
212 postComm[i] = 0.; //avoids having to initialize postComm_ on next call to ArbitrateAndCommunicate
213 if (procWinner[i] == MyPid) ++numMyWinners;
214 }
215 }
216
217 weight = Teuchos::null; //TODO why do we do this?
218
219 if (companion != NULL) {
220 // Now build a new Map, WinnerMap which just consists of procWinners.
221 // This is done by extracting the Gids for Wt, and shoving
222 // the subset that correspond to procWinners in MyWinners.
223 // WinnerMap is then constructed using MyWinners.
224 //
225 // In order to avoid regenerating winnerMap_, the following are checked:
226 // 1) Do the local number of entries in MyWinners differ? If so, regenerate/repopulate MyWinners and regenerate winnerMap_.
227 // 2) If the local number of entries in MyWinners are the same, do any entries differ? If so, repopulate MyWinners and
228 // regenerate winnerMap_.
229
230 ArrayView<const GO> myGids = weightMap->getLocalElementList(); //== weightMap->MyGlobalElements(myGids);
231 bool realloc=false;
232 if (numMyWinners != numMyWinners_ || winnerMap_ == Teuchos::null) {
233 // The local number of entries in MyWinners_ have changed since the last invocation, so reallocate myWinners_.
234 myWinners_ = ArrayRCP<GO>(numMyWinners);
235 realloc=true;
236 //std::cout << MyPid << ": numMyWinners has changed : (old) " << numMyWinners_ << ", (new) " << numMyWinners << std::endl;
237 numMyWinners_ = numMyWinners;
238 }
239
240#ifdef JG_DEBUG
241 procWinner = Teuchos::null;
242 std::cout << MyPid << ": nodeNumElements=" << nodeNumElements << std::endl;
243 std::cout << MyPid << ": procWinner=" << procWinner_ << std::endl;
244 procWinner = procWinner_.getDataNonConst(0);
245#endif
246
247 if (realloc==true) {
248 // The local number of entries in MyWinners have changed since the last invocation, so repopulate MyWinners_.
249 numMyWinners = 0;
250 for (size_t i = 0; i < nodeNumElements; ++i) {
251 if (procWinner[i] == MyPid) {
252 myWinners_[numMyWinners++] = myGids[i];
253 }
254 }
255 } else {
256 // The local number of entries in MyWinners are the same as the last invocation, but
257 // we still must check if any entries differ from the last invocation.
258 bool entryMismatch=false;
259 numMyWinners = 0;
260 for (size_t i = 0; i < nodeNumElements; ++i) {
261 if (procWinner[i] == MyPid) {
262 if (myWinners_[numMyWinners++] != myGids[i]) {
263 entryMismatch=true;
264 break;
265 }
266 }
267 }
268
269 if (entryMismatch == true) {
270 // Entries differ from last invocation, so repopulate myWinners_.
271 realloc=true;
272 numMyWinners = 0;
273 for (size_t i = 0; i < nodeNumElements; ++i) {
274 if (procWinner[i] == MyPid) {
275 myWinners_[numMyWinners++] = myGids[i];
276 }
277 }
278 }
279 } //if (realloc==true) ... else
280
281 procWinner = Teuchos::null;
282
283#ifdef JG_DEBUG
284 std::cout << MyPid << ": numMyWinners=" << numMyWinners << std::endl;
285 std::cout << MyPid << ": myWinners_" << myWinners_ << std::endl;
286 for(int i=0;i<numMyWinners; i++)
287 std::cout << MyPid << ": myWinners_[locId=" << i << "] = " << myWinners_[i] << std::endl;
288
289#endif
290
291#ifdef HAVE_MPI
292 //See whether any process has determined that winnerMap_ must be regenerated.
293 int irealloc,orealloc;
294 if (realloc) irealloc=1;
295 else irealloc=0;
296 MueLu_maxAll(comm,irealloc,orealloc);
297 if (orealloc == 1) realloc=true;
298 else realloc=false;
299#endif
300
301 if (realloc) {
302 // Either the number of entries or the value have changed since the last invocation, so reallocation the map.
303 const Xpetra::global_size_t GSTI = Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid();
304 winnerMap_ = MapFactory::Build(weightMap->lib(), GSTI, myWinners_(), 0, weightMap->getComm());
305 }
306
307 // Pull the Winners out of companion
308 // JustWinners <-- companion[Winners];
309
310 RCP<LOMultiVector> justWinners = LOMultiVectorFactory::Build(winnerMap_, companion->getNumVectors());
311
312#ifdef JG_DEBUG
313 RCP<Teuchos::FancyOStream> out = rcp(new Teuchos::FancyOStream(rcp(&std::cout,false)));
314 std::cout << MyPid << ": justWinners(Vector in)=" << *justWinners << std::endl;
315 justWinners->describe(*out, Teuchos::VERB_EXTREME);
316#endif
317
318 if ( winnerImport_ == Teuchos::null
319 || !winnerImport_->getSourceMap()->isSameAs(*weightMap)
320 || !winnerImport_->getTargetMap()->isSameAs(*winnerMap_) )
321 winnerImport_ = ImportFactory::Build(weightMap, winnerMap_);
322 RCP<const Import> winnerImport = winnerImport_;
323 try
324 {
325 justWinners->doImport(*companion, *winnerImport, Xpetra::INSERT);
326 }
327 catch(std::exception& e)
328 {
329 std::cout << MyPid << ": ERR2: An exception occurred." << std::endl;
330 throw e;
331 }
332
333 // Put the JustWinner values back into companion so that
334 // all nonunique copies of the same Gid have the procWinner's
335 // version of the companion.
336 //#define JG_DEBUG
337#ifdef JG_DEBUG
338 RCP<Teuchos::FancyOStream> fos = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
339 fos->setOutputToRootOnly(-1);
340 if (!weightMap->getComm()->getRank())
341 std::cout << "------ winnerMap_ ------" << std::endl;
342 winnerMap_->describe(*fos,Teuchos::VERB_EXTREME);
343 if (!weightMap->getComm()->getRank())
344 std::cout << "------ weightMap ------" << std::endl;
345 weightMap->getComm()->barrier();
346 weightMap->describe(*fos,Teuchos::VERB_EXTREME);
347 //std::cout << *winnerMap_ << std::endl;
348 //std::cout << *weightMap << std::endl;
349 sleep(5);
350 exit(1);
351#endif
352#ifdef JG_DEBUG
353#undef JG_DEBUG
354#endif
355
356 if ( pushWinners_ == Teuchos::null
357 || !pushWinners_->getSourceMap()->isSameAs(*winnerMap_)
358 || !pushWinners_->getTargetMap()->isSameAs(*weightMap) )
359 pushWinners_ = ImportFactory::Build(winnerMap_,weightMap);
360 RCP<Import> pushWinners = pushWinners_;
361 //RCP<Import> pushWinners = ImportFactory::Build(winnerMap_, weightMap); // VERSION1
362 //RCP<Export> pushWinners = ExportFactory::Build(winnerMap_, weightMap); // VERSION4
363 try
364 {
365 companion->doImport(*justWinners, *pushWinners, Xpetra::INSERT); // VERSION1 Slow
366 //companion->doExport(*justWinners, *winnerImport_, Xpetra::INSERT); // JJH this should work... but exception
367 // if (weightMap->lib() == Xpetra::UseEpetra)
368 // justWinners->doExport(*companion, *winnerImport, Xpetra::INSERT); // VERSION2 Tpetra doc is wrong
369 // else if (weightMap->lib() == Xpetra::UseTpetra)
370 // companion->doExport(*justWinners, *winnerImport, Xpetra::INSERT); // VERSION3 - TODO: will certainly not work with Epetra? (change Xpetra?)
371 //companion->doExport(*justWinners, *pushWinners, Xpetra::INSERT); // VERSION4
372 // else throw "lib()";
373 }
374 catch(std::exception& e)
375 {
376 throw e;
377 }
378 //#define JG_DEBUG
379#ifdef JG_DEBUG
380 // RCP<Teuchos::FancyOStream> out = rcp(new Teuchos::FancyOStream(rcp(&std::cout,false)));
381 //->describe(*out, Teuchos::VERB_EXTREME);
382
383 // std::cout << MyPid << ": ERR3: An exception occurred." << std::endl;
384
385 std::cout << MyPid << ": numMyWinners=" << numMyWinners << std::endl;
386
387 std::cout << MyPid << ": justWinners(Vector in)=" << std::endl;
388 justWinners->describe(*out, Teuchos::VERB_EXTREME);
389
390 std::cout << MyPid << ": companion(Vector out)=" << std::endl;
391 companion->describe(*out, Teuchos::VERB_EXTREME);
392
393 // std::cout << MyPid << ": pushWinners(Import(winnerMap_, weight_.Map))=" << *pushWinners << std::endl;
394 std::cout << MyPid << ": winnerMap_=" << *winnerMap_ << std::endl;
395 std::cout << MyPid << ": weight_.Map=" << *weightMap << std::endl;
396#endif
397 // throw e;
398 // throw 1;
399 }
400
401#ifdef COMPARE_IN_OUT_VECTORS
402 if (MyPid == 0) {
403 std::cout << "==============" << std::endl;
404 std::cout << "call #" << numCalls << " (1-based)" << std::endl;
405 std::cout << "==============" << std::endl;
406 }
407 /*
408 bool sameWeight=true;
409 bool sameWinner=true;
410 bool sameComp=true;
411 */
412 std::string sameOrDiff;
413 {
414 ArrayRCP<SC> in_weight = in_weight_->getDataNonConst(0);
415 ArrayRCP<SC> weight = weight_.getDataNonConst(0);
416 if (MyPid == 0) std::cout << "==============\nweight\n==============\n" << std::endl;
417 for (size_t i=0; i < weight_.getLocalLength(); ++i) {
418 if (in_weight[i] - weight[i] != 0) sameOrDiff = " <<<<";
419 else sameOrDiff = " ";
420 std::cout << std::setw(3) << i<<": " << in_weight[i] << " " << weight[i] << sameOrDiff << in_weight[i] - weight[i] << std::endl;
421 /*
422 if (in_weight[i] != weight[i]) {
423 sameWeight=false;
424 std::cout << "\n\nin and out weight DIFFER\n\n" << std::endl;
425 std::cout << "i="<<i<<", in=" << in_weight[i] << " , out=" << weight[i] << std::endl;
426 break;
427 }
428 */
429 }
430 }
431
432 {
433 ArrayRCP<LO> in_procWinner = in_procWinner_->getDataNonConst(0);
434 ArrayRCP<LO> procWinner = procWinner_.getDataNonConst(0);
435 if (MyPid == 0) std::cout << "==============\nprocWinner\n==============\n" << std::endl;
436 for (size_t i=0; i < procWinner_.getLocalLength(); ++i) {
437 if (in_procWinner[i] != procWinner[i]) sameOrDiff = " <<<<";
438 else sameOrDiff = " ";
439 std::cout << std::setw(3) << i<<": " << in_procWinner[i] << " " << procWinner[i] << sameOrDiff << std::endl;
440 /*
441 if (in_procWinner[i] != procWinner[i]) {
442 sameWinner=false;
443 std::cout << "\n\nin and out procWinner DIFFER\n\n" << std::endl;
444 std::cout << "i="<<i<<", in=" << in_procWinner[i] << ", out=" << procWinner[i] << std::endl;
445 break;
446 }
447 */
448 }
449 }
450
451 {
452 if (companion != NULL) {
453 ArrayRCP<LO> in_comp = in_companion->getDataNonConst(0);
454 ArrayRCP<LO> comp = companion->getDataNonConst(0);
455 if (MyPid == 0) std::cout << "==============\ncompanion\n==============\n" << std::endl;
456 for (size_t i=0; i < companion->getLocalLength(); ++i) {
457 if (in_comp[i] != comp[i]) sameOrDiff = " <<<<";
458 else sameOrDiff = " ";
459 std::cout << std::setw(3) << i<<": " << in_comp[i] << " " << comp[i] << sameOrDiff << std::endl;
460 /*
461 if (in_comp[i] != comp[i]) {
462 sameComp=false;
463 std::cout << "\n\nin and out companion DIFFER\n\n" << std::endl;
464 std::cout << "i="<<i<<", in=" << in_comp[i] << ", out=" << comp[i] << std::endl;
465 break;
466 }
467 */
468 }
469 }
470 }
471#endif
472 } //ArbitrateAndCommunicate(Vector&, LOVector &, LOVector *, const bool) const
473
474 template <class LocalOrdinal, class GlobalOrdinal, class Node>
475 void CoupledAggregationCommHelper<LocalOrdinal, GlobalOrdinal, Node>::NonUnique2NonUnique(const Vector &source, Vector &dest, const Xpetra::CombineMode what) const {
476 tempVec_->putScalar(0.);
477
478 try
479 {
480 tempVec_->doExport(source, *import_, what);
481 dest.doImport(*tempVec_, *import_, Xpetra::INSERT);
482 }
483 catch(std::exception& e)
484 {
485 int MyPid = tempVec_->getMap()->getComm()->getRank();
486 std::cout << MyPid << ": ERR1: An exception occurred." << std::endl;
487 throw e;
488 }
489 }
490
491}
492
493#endif // MUELU_COUPLEDAGGREGATIONCOMMHELPER_DEF_HPP
494
#define MueLu_maxAll(rcpComm, in, out)
void NonUnique2NonUnique(const Vector &source, Vector &dest, const Xpetra::CombineMode what) const
Redistribute data in source to dest where both source and dest might have multiple copies of the same...
CoupledAggregationCommHelper(const RCP< const Map > &uniqueMap, const RCP< const Map > &nonUniqueMap)
Constructor.
void ArbitrateAndCommunicate(Vector &weights, Aggregates &aggregates, const bool perturb) const
This method assigns unknowns to aggregates.
Namespace for MueLu classes and methods.