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 
77 namespace 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
void CheckCommutingProperty(const Matrix &Pe, const Matrix &D0_c, const Matrix &D0_f, const Matrix &Pn) const
Utility method.
Timer to be used in factories. Similar to Monitor but with additional timers.
User data are always kept. This flag is set automatically when Level::Set("data", data) is used...
Namespace for MueLu classes and methods.
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
static const NoFactory * get()
Print statistics that do not involve significant additional computation.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
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)
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.
Exception throws to report errors in the internal logical of the program.