MueLu Version of the Day
MueLu_ReitzingerPFactory_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_REITZINGERPFACTORY_DEF_HPP
47#define MUELU_REITZINGERPFACTORY_DEF_HPP
48
49#include <Xpetra_MapFactory.hpp>
50#include <Xpetra_Map.hpp>
51#include <Xpetra_CrsMatrix.hpp>
52#include <Xpetra_Matrix.hpp>
53#include <Xpetra_MatrixMatrix.hpp>
54#include <Xpetra_MultiVector.hpp>
55#include <Xpetra_MultiVectorFactory.hpp>
56#include <Xpetra_VectorFactory.hpp>
57#include <Xpetra_Import.hpp>
58#include <Xpetra_ImportUtils.hpp>
59#include <Xpetra_ImportFactory.hpp>
60#include <Xpetra_CrsMatrixWrap.hpp>
61#include <Xpetra_StridedMap.hpp>
62#include <Xpetra_StridedMapFactory.hpp>
63#include <Xpetra_IO.hpp>
64
66
67#include "MueLu_Aggregates.hpp"
68#include "MueLu_AmalgamationFactory.hpp"
69#include "MueLu_AmalgamationInfo.hpp"
70#include "MueLu_CoarseMapFactory.hpp"
71#include "MueLu_MasterList.hpp"
72#include "MueLu_Monitor.hpp"
73#include "MueLu_NullspaceFactory.hpp"
74#include "MueLu_PerfUtils.hpp"
75#include "MueLu_Utilities.hpp"
76
77namespace MueLu {
78
79 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
81 RCP<ParameterList> validParamList = rcp(new ParameterList());
82
83#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
84
85
86#undef SET_VALID_ENTRY
87
88 validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
89 validParamList->set< RCP<const FactoryBase> >("D0", Teuchos::null, "Generating factory of the matrix D0");
90 validParamList->set< RCP<const FactoryBase> >("NodeMatrix", Teuchos::null, "Generating factory of the matrix NodeMatrix");
91 validParamList->set< RCP<const FactoryBase> >("Pnodal", Teuchos::null, "Generating factory of the matrix P");
92
93 // Make sure we don't recursively validate options for the matrixmatrix kernels
94 ParameterList norecurse;
95 norecurse.disableRecursiveValidation();
96 validParamList->set<ParameterList> ("matrixmatrix: kernel params", norecurse, "MatrixMatrix kernel parameters");
97
98 return validParamList;
99 }
100
101 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
103 Input(fineLevel, "A");
104 Input(fineLevel, "D0");
105 Input(fineLevel, "NodeMatrix");
106 Input(coarseLevel, "Pnodal");
107
108 }
109
110 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
112 return BuildP(fineLevel, coarseLevel);
113 }
114
115 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
117 FactoryMonitor m(*this, "Build", coarseLevel);
118 using MT = typename Teuchos::ScalarTraits<SC>::magnitudeType;
119 using XMM = Xpetra::MatrixMatrix<SC,LO,GO,NO>;
120 Teuchos::FancyOStream& out0=GetBlackHole();
121 const ParameterList& pL = GetParameterList();
122
123 RCP<Matrix> EdgeMatrix = Get< RCP<Matrix> > (fineLevel, "A");
124 RCP<Matrix> D0 = Get< RCP<Matrix> > (fineLevel, "D0");
125 RCP<Matrix> NodeMatrix = Get< RCP<Matrix> > (fineLevel, "NodeMatrix");
126 RCP<Matrix> Pn = Get< RCP<Matrix> > (coarseLevel, "Pnodal");
127 const GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
128 const LO LO_INVALID = Teuchos::OrdinalTraits<LO>::invalid();
129 int MyPID = D0->getRowMap()->getComm()->getRank();
130
131 // Matrix matrix params
132 RCP<ParameterList> mm_params = rcp(new ParameterList);;
133 if(pL.isSublist("matrixmatrix: kernel params"))
134 mm_params->sublist("matrixmatrix: kernel params") = pL.sublist("matrixmatrix: kernel params");
135
136
137 // TODO: We need to make sure Pn isn't normalized. Right now this has to be done explicitly by the user
138
139 // TODO: We need to look through and see which of these really need importers and which ones don't
140
141 /* Generate the Pn * D0 matrix and its transpose */
142 RCP<Matrix> D0_Pn, PnT_D0T, D0_Pn_nonghosted;
143 Teuchos::Array<int> D0_Pn_col_pids;
144 {
145 RCP<Matrix> dummy;
146 SubFactoryMonitor m2(*this, "Generate D0*Pn", coarseLevel);
147 D0_Pn = XMM::Multiply(*D0,false,*Pn,false,dummy,out0,true,true,"D0*Pn",mm_params);
148
149 // Save this so we don't need to do the multiplication again later
150 D0_Pn_nonghosted = D0_Pn;
151
152 // Get owning PID information on columns for tie-breaking
153 if(!D0_Pn->getCrsGraph()->getImporter().is_null()) {
154 Xpetra::ImportUtils<LO,GO,NO> utils;
155 utils.getPids(*D0_Pn->getCrsGraph()->getImporter(),D0_Pn_col_pids,false);
156 }
157 else {
158 D0_Pn_col_pids.resize(D0_Pn->getCrsGraph()->getColMap()->getNodeNumElements(),MyPID);
159 }
160 }
161
162
163 {
164 // Get the transpose
165 SubFactoryMonitor m2(*this, "Transpose D0*Pn", coarseLevel);
166 PnT_D0T = Utilities::Transpose(*D0_Pn, true);
167 }
168
169 // We really need a ghosted version of D0_Pn here.
170 // The reason is that if there's only one fine edge between two coarse nodes, somebody is going
171 // to own the associated coarse edge. The sum/sign rule doesn't guarantee the fine owner is the coarse owner.
172 // So you can wind up with a situation that only guy who *can* register the coarse edge isn't the sum/sign
173 // owner. Adding more ghosting fixes that.
174 if(!PnT_D0T->getCrsGraph()->getImporter().is_null()) {
175 RCP<const Import> Importer = PnT_D0T->getCrsGraph()->getImporter();
176 RCP<const CrsMatrix> D0_Pn_crs = rcp_dynamic_cast<const CrsMatrixWrap>(D0_Pn)->getCrsMatrix();
177 RCP<Matrix> D0_Pn_new = rcp(new CrsMatrixWrap(CrsMatrixFactory::Build(D0_Pn_crs,*Importer,D0_Pn->getDomainMap(),Importer->getTargetMap())));
178 D0_Pn = D0_Pn_new;
179 // Get owning PID information on columns for tie-breaking
180 if(!D0_Pn->getCrsGraph()->getImporter().is_null()) {
181 Xpetra::ImportUtils<LO,GO,NO> utils;
182 utils.getPids(*D0_Pn->getCrsGraph()->getImporter(),D0_Pn_col_pids,false);
183 }
184 else {
185 D0_Pn_col_pids.resize(D0_Pn->getCrsGraph()->getColMap()->getNodeNumElements(),MyPID);
186 }
187 }
188
189
190 // FIXME: This is using deprecated interfaces
191 ArrayView<const LO> colind_E, colind_N;
192 ArrayView<const SC> values_E, values_N;
193
194 size_t Ne=EdgeMatrix->getNodeNumRows();
195 size_t Nn=NodeMatrix->getNodeNumRows();
196
197 // Upper bound on local number of coarse edges
198 size_t max_edges = (NodeMatrix->getNodeNumEntries() + Nn +1) / 2;
199 ArrayRCP<size_t> D0_rowptr(Ne+1);
200 ArrayRCP<LO> D0_colind(max_edges);
201 ArrayRCP<SC> D0_values(max_edges);
202 D0_rowptr[0] = 0;
203
204 LO current = 0;
205 LO Nnc = PnT_D0T->getRowMap()->getNodeNumElements();
206
207 for(LO i=0; i<(LO)Nnc; i++) {
208 // GO global_i = PnT_D0T->getRowMap()->getGlobalElement(i);
209
210 // FIXME: We don't really want an std::map here. This is just a first cut implementation
211 using value_type = bool;
212 std::map<LO, value_type> ce_map;
213
214 // FIXME: This is using deprecated interfaces
215 PnT_D0T->getLocalRowView(i,colind_E,values_E);
216
217 for(LO j=0; j<(LO)colind_E.size(); j++) {
218
219 // NOTE: Edges between procs will be via handled via the a version
220 // of ML's odd/even rule
221 // For this to function correctly, we make two assumptions:
222 // (a) The processor that owns a fine edge owns at least one of the attached nodes.
223 // (b) Aggregation is uncoupled.
224
225 // TODO: Add some debug code to check the assumptions
226
227 // Check to see if we own this edge and continue if we don't
228 GO edge_gid = PnT_D0T->getColMap()->getGlobalElement(colind_E[j]);
229 LO j_row = D0_Pn->getRowMap()->getLocalElement(edge_gid);
230 int pid0, pid1;
231 D0_Pn->getLocalRowView(j_row,colind_N,values_N);
232
233 // Skip incomplete rows
234 if(colind_N.size() != 2) continue;
235
236 pid0 = D0_Pn_col_pids[colind_N[0]];
237 pid1 = D0_Pn_col_pids[colind_N[1]];
238 // printf("[%d] Row %d considering edge (%d)%d -> (%d)%d\n",MyPID,global_i,colind_N[0],D0_Pn->getColMap()->getGlobalElement(colind_N[0]),colind_N[1],D0_Pn->getColMap()->getGlobalElement(colind_N[1]));
239
240 // Check to see who owns these nodes
241 // If the sum of owning procs is odd, the lower ranked proc gets it
242
243 bool zero_matches = pid0 == MyPID;
244 bool one_matches = pid1 == MyPID;
245 bool keep_shared_edge = false, own_both_nodes = false;
246 if(zero_matches && one_matches) {own_both_nodes=true;}
247 else {
248 int sum_is_odd = (pid0 + pid1) % 2;
249 int i_am_smaller = MyPID == std::min(pid0,pid1);
250 if(sum_is_odd && i_am_smaller) keep_shared_edge=true;
251 if(!sum_is_odd && !i_am_smaller) keep_shared_edge=true;
252 }
253 // printf("[%d] - matches %d/%d keep_shared = %d own_both = %d\n",MyPID,(int)zero_matches,(int)one_matches,(int)keep_shared_edge,(int)own_both_nodes);
254 if(!keep_shared_edge && !own_both_nodes) continue;
255
256
257 // We're doing this in GID space, but only only because it allows us to explain
258 // the edge orientation as "always goes from lower GID to higher GID". This could
259 // be done entirely in local GIDs, but then the ordering is a little more confusing.
260 // This could be done in local indices later if we need the extra performance.
261 for(LO k=0; k<(LO)colind_N.size(); k++) {
262 LO my_colind = colind_N[k];
263 if(my_colind!=LO_INVALID && ((keep_shared_edge && my_colind != i) || (own_both_nodes && my_colind > i)) ) {
264 ce_map.emplace(std::make_pair(my_colind,true));
265 }
266 }//end for k < colind_N.size()
267 }// end for j < colind_E.size()
268
269
270 // std::map is sorted, so we'll just iterate through this
271 for(auto iter=ce_map.begin(); iter != ce_map.end(); iter++) {
272 LO col = iter->first;
273 // This shouldn't happen. But in case it did...
274 if(col == i) {
275 continue;
276 }
277
278 // ASSUMPTION: "i" is a valid local column id
279 D0_colind[current] = i;
280 D0_values[current] = -1;
281 current++;
282 D0_colind[current] = col;
283 D0_values[current] = 1;
284 current++;
285 D0_rowptr[current / 2] = current;
286 }
287
288 }// end for i < Nn
289
290 LO num_coarse_edges = current / 2;
291 D0_rowptr.resize(num_coarse_edges+1);
292 D0_colind.resize(current);
293 D0_values.resize(current);
294
295 // Count the total number of edges
296 // NOTE: Since we solve the ownership issue above, this should do what we want
297 RCP<const Map> ownedCoarseEdgeMap = Xpetra::MapFactory<LO,GO,NO>::Build(EdgeMatrix->getRowMap()->lib(), GO_INVALID, num_coarse_edges,EdgeMatrix->getRowMap()->getIndexBase(),EdgeMatrix->getRowMap()->getComm());
298
299
300 // NOTE: This only works because of the assumptions above
301 RCP<const Map> ownedCoarseNodeMap = Pn->getDomainMap();
302 RCP<const Map> ownedPlusSharedCoarseNodeMap = D0_Pn->getCrsGraph()->getColMap();
303
304 // Create the coarse D0
305 RCP<CrsMatrix> D0_coarse;
306 {
307 SubFactoryMonitor m2(*this, "Build D0", coarseLevel);
308 // FIXME: We can be smarter with memory here
309 // TODO: Is there a smarter way to get this importer?
310 D0_coarse = CrsMatrixFactory::Build(ownedCoarseEdgeMap,ownedPlusSharedCoarseNodeMap,0);
311 TEUCHOS_TEST_FOR_EXCEPTION(D0_coarse.is_null(), Exceptions::RuntimeError, "MueLu::ReitzingerPFactory: CrsMatrixFatory failed.");
312
313 // FIXME: Deprecated code
314 ArrayRCP<size_t> ia;
315 ArrayRCP<LO> ja;
316 ArrayRCP<SC> val;
317 D0_coarse->allocateAllValues(current, ia, ja, val);
318 std::copy(D0_rowptr.begin(),D0_rowptr.end(),ia.begin());
319 std::copy(D0_colind.begin(),D0_colind.end(),ja.begin());
320 std::copy(D0_values.begin(),D0_values.end(),val.begin());
321 D0_coarse->setAllValues(ia, ja, val);
322
323#if 0
324 {
325 char fname[80];
326 printf("[%d] D0: ia.size() = %d ja.size() = %d\n",MyPID,(int)ia.size(),(int)ja.size());
327 printf("[%d] D0: ia :",MyPID);
328 for(int i=0; i<(int)ia.size(); i++)
329 printf("%d ",(int)ia[i]);
330 printf("\n[%d] D0: global ja :",MyPID);
331 for(int i=0; i<(int)ja.size(); i++)
332 printf("%d ",(int)ownedPlusSharedCoarseNodeMap->getGlobalElement(ja[i]));
333 printf("\n[%d] D0: local ja :",MyPID);
334 for(int i=0; i<(int)ja.size(); i++)
335 printf("%d ",(int)ja[i]);
336 printf("\n");
337
338 sprintf(fname,"D0_global_ja_%d_%d.dat",MyPID,fineLevel.GetLevelID());
339 FILE * f = fopen(fname,"w");
340 for(int i=0; i<(int)ja.size(); i++)
341 fprintf(f,"%d ",(int)ownedPlusSharedCoarseNodeMap->getGlobalElement(ja[i]));
342 fclose(f);
343
344 sprintf(fname,"D0_local_ja_%d_%d.dat",MyPID,fineLevel.GetLevelID());
345 f = fopen(fname,"w");
346 for(int i=0; i<(int)ja.size(); i++)
347 fprintf(f,"%d ",(int)ja[i]);
348 fclose(f);
349
350 }
351#endif
352 fflush(stdout);
353
354 D0_coarse->expertStaticFillComplete(ownedCoarseNodeMap,ownedCoarseEdgeMap);
355 }
356 RCP<Matrix> D0_coarse_m = rcp(new CrsMatrixWrap(D0_coarse));
357 RCP<Teuchos::FancyOStream> fout = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
358
359
360 // Create the Pe matrix, but with the extra entries. From ML's notes:
361 /* The general idea is that the matrix */
362 /* T_h P_n T_H^* */
363 /* is almost Pe. If we make sure that P_n contains 1's and -1's, the*/
364 /* matrix triple product will yield a matrix with +/- 1 and +/- 2's.*/
365 /* If we remove all the 1's and divide the 2's by 2. we arrive at Pe*/
366 RCP<Matrix> Pe;
367 {
368 SubFactoryMonitor m2(*this, "Generate Pe (pre-fix)", coarseLevel);
369 RCP<Matrix> dummy;
370
371 RCP<Matrix> Pn_D0cT = XMM::Multiply(*Pn,false,*D0_coarse_m,true,dummy,out0,true,true,"Pn*D0c'",mm_params);
372 Pe = XMM::Multiply(*D0,false,*Pn_D0cT,false,dummy,out0,true,true,"D0*(Pn*D0c')",mm_params);
373
374 // TODO: Something like this *might* work. But this specifically, doesn;'t
375 // Pe = XMM::Multiply(*D0_Pn_nonghosted,false,*D0_coarse_m,true,dummy,out0,true,true,"(D0*Pn)*D0c'",mm_params);
376 }
377
378 /* Weed out the +/- entries */
379 {
380 SubFactoryMonitor m2(*this, "Generate Pe (post-fix)", coarseLevel);
381 Pe->resumeFill();
382 SC one = Teuchos::ScalarTraits<SC>::one();
383 MT two = 2*Teuchos::ScalarTraits<MT>::one();
384 SC zero = Teuchos::ScalarTraits<SC>::zero();
385 SC neg_one = - one;
386 // FIXME: Deprecated code
387 for(LO i=0; i<(LO) Ne; i++) {
388 ArrayView<const LO> columns;
389 ArrayView<const SC> values;
390 Pe->getLocalRowView(i,columns,values);
391 // FIXME: This won't work on fancy nodes
392 ArrayView<SC> values_nc = Teuchos::av_const_cast<SC>(values);
393 for (LO j=0; j<(LO)values.size(); j++)
394 if ((values_nc[j] == one || values_nc[j] == neg_one))
395 values_nc[j] = zero;
396 else
397 values_nc[j] /= two;
398 }//end for i < Ne
399 Pe->fillComplete(Pe->getDomainMap(),Pe->getRangeMap());
400 }
401
402 /* Check commuting property */
403 CheckCommutingProperty(*Pe,*D0_coarse_m,*D0,*Pn);
404
405 /* Set output on the level */
406 Set(coarseLevel,"P",Pe);
407 Set(coarseLevel,"Ptent",Pe);
408
409 Set(coarseLevel,"D0",D0_coarse_m);
410 coarseLevel.Set("D0",D0_coarse_m,NoFactory::get());
411 coarseLevel.AddKeepFlag("D0",NoFactory::get(), MueLu::Final);
412 coarseLevel.RemoveKeepFlag("D0",NoFactory::get(), MueLu::UserData);
413
414#if 0
415 {
416 int numProcs = Pe->getRowMap()->getComm()->getSize();
417 char fname[80];
418
419 sprintf(fname,"Pe_%d_%d.mat",numProcs,fineLevel.GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*Pe);
420 sprintf(fname,"Pn_%d_%d.mat",numProcs,fineLevel.GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*Pn);
421 sprintf(fname,"D0c_%d_%d.mat",numProcs,fineLevel.GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*D0_coarse_m);
422 sprintf(fname,"D0f_%d_%d.mat",numProcs,fineLevel.GetLevelID()); Xpetra::IO<SC,LO,GO,NO>::Write(fname,*D0);
423 }
424#endif
425
426 }// end Build
427
428 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
430 CheckCommutingProperty(const Matrix & Pe, const Matrix & D0_c, const Matrix& D0_f, const Matrix & Pn) const {
431 if(IsPrint(Statistics0)) {
432 using XMM = Xpetra::MatrixMatrix<SC,LO,GO,NO>;
433 using MT = typename Teuchos::ScalarTraits<SC>::magnitudeType;
434 SC one = Teuchos::ScalarTraits<SC>::one();
435 SC zero = Teuchos::ScalarTraits<SC>::zero();
436
437 RCP<Matrix> dummy;
438 Teuchos::FancyOStream &out0=GetBlackHole();
439 RCP<Matrix> left = XMM::Multiply(Pe,false,D0_c,false,dummy,out0);
440 RCP<Matrix> right = XMM::Multiply(D0_f,false,Pn,false,dummy,out0);
441
442 // We need a non-FC matrix for the add, sadly
443 RCP<CrsMatrix> sum_c = CrsMatrixFactory::Build(left->getRowMap(),left->getNodeMaxNumRowEntries()+right->getNodeMaxNumRowEntries());
444 RCP<Matrix> summation = rcp(new CrsMatrixWrap(sum_c));
445 XMM::TwoMatrixAdd(*left, false, one, *summation, zero);
446 XMM::TwoMatrixAdd(*right, false, -one, *summation, one);
447
448 MT norm = summation->getFrobeniusNorm();
449 GetOStream(Statistics0) << "CheckCommutingProperty: ||Pe D0_c - D0_f Pn || = "<<norm<<std::endl;
450
451 }
452
453 }//end CheckCommutingProperty
454
455
456
457} //namespace MueLu
458
459
460
461#define MUELU_REITZINGERPFACTORY_SHORT
462#endif // MUELU_REITZINGERPFACTORY_DEF_HPP
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.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
int GetLevelID() const
Return level number.
Definition: MueLu_Level.cpp:76
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static const NoFactory * get()
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
void CheckCommutingProperty(const Matrix &Pe, const Matrix &D0_c, const Matrix &D0_f, const Matrix &Pn) const
Utility method.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
Namespace for MueLu classes and methods.
@ Final
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
@ UserData
User data are always kept. This flag is set automatically when Level::Set("data", data) is used....
@ Statistics0
Print statistics that do not involve significant additional computation.