MueLu  Version of the Day
MueLu_RefMaxwell_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_REFMAXWELL_DEF_HPP
47 #define MUELU_REFMAXWELL_DEF_HPP
48 
49 // TODO move this file to xpetra subfolder
50 
51 #include "MueLu_ConfigDefs.hpp"
52 
53 #include "Xpetra_Map.hpp"
54 #include "Xpetra_MatrixMatrix.hpp"
55 
57 #include "MueLu_UncoupledAggregationFactory.hpp"
58 #include "MueLu_TentativePFactory.hpp"
59 #include "MueLu_SaPFactory.hpp"
60 #include "MueLu_SmootherFactory.hpp"
61 #include "MueLu_Utilities.hpp"
62 #include "MueLu_Monitor.hpp"
63 #include "MueLu_MLParameterListInterpreter.hpp"
64 #include "MueLu_ParameterListInterpreter.hpp"
66 
67 namespace MueLu {
68 
69 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
70 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getDomainMap() const {
71  return SM_Matrix_->getDomainMap();
72 }
73 
74 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
75 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getRangeMap() const {
76  return SM_Matrix_->getRangeMap();
77 }
78 
79 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
81 
82  disable_addon_ = list.get("refmaxwell: disable add-on",true);
83  mode_ = list.get("refmaxwell: mode","additive");
84 
85  if(list.isSublist("refmaxwell: 11list"))
86  precList11_ = list.sublist("refmaxwell: 11list");
87 
88  if(list.isSublist("refmaxwell: 22list"))
89  precList22_ = list.sublist("refmaxwell: 22list");
90 
91  std::string ref("smoother:");
92  std::string replace("coarse:");
93  for(Teuchos::ParameterList::ConstIterator i=list.begin(); i !=list.end(); i++) {
94  const std::string & pname = list.name(i);
95  if(pname.find(ref)!=std::string::npos) {
96  smootherList_.setEntry(pname,list.entry(i));
97  std::string coarsename(pname);
98  coarsename.replace((size_t)0,(size_t)ref.length(),replace);
99  }
100  }
101  if(list.isSublist("smoother: params")) {
102  smootherList_.set("coarse: params",list.sublist("smoother: params"));
103  }
104  smootherList_.set("max levels",1);
105 
106 }
107 
108 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
110 
111  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
112  out.setOutputToRootOnly(0);
113  out.setShowProcRank(true);
114 
115  // clean rows associated with boundary conditions
116  findDirichletRows(SM_Matrix_,BCrows_);
117  findDirichletCols(D0_Matrix_,BCrows_,BCcols_);
118  D0_Matrix_->resumeFill();
119  Apply_BCsToMatrixRows(D0_Matrix_,BCrows_);
120  Apply_BCsToMatrixCols(D0_Matrix_,BCcols_);
121  D0_Matrix_->fillComplete(D0_Matrix_->getDomainMap(),D0_Matrix_->getRangeMap());
122  //D0_Matrix_->describe(out,Teuchos::VERB_EXTREME);
123 
124  // Form TMT_Matrix
125  Teuchos::RCP<Matrix> C1 = MatrixFactory::Build(SM_Matrix_->getRowMap(),0);
126  TMT_Matrix_=MatrixFactory::Build(D0_Matrix_->getDomainMap(),0);
127  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*SM_Matrix_,false,*D0_Matrix_,false,*C1,true,true);
128  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*D0_Matrix_,true,*C1,false,*TMT_Matrix_,true,true);
129  TMT_Matrix_->resumeFill();
130  Remove_Zeroed_Rows(TMT_Matrix_,1.0e-16);
131  TMT_Matrix_->SetFixedBlockSize(1);
132  //TMT_Matrix_->describe(out,Teuchos::VERB_EXTREME);
133 
134  // build nullspace if necessary
135  if(Nullspace_ != Teuchos::null) {
136  // no need to do anything - nullspace is built
137  }
138  else if(Nullspace_ == Teuchos::null && Coords_ != Teuchos::null) {
139  Nullspace_ = MultiVectorFactory::Build(SM_Matrix_->getRowMap(),Coords_->getNumVectors());
140  D0_Matrix_->apply(*Coords_,*Nullspace_);
141  }
142  else {
143  std::cerr << "MueLu::RefMaxwell::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
144  }
145 
146  // build special prolongator for (1,1)-block
147  if(P11_==Teuchos::null) {
148  buildProlongator();
149  }
150 
151  // build coarse grid operator for (1,1)-block
152  formCoarseMatrix();
153 
154  // build fine grid operator for (2,2)-block, D0* M1 D0
155  Teuchos::RCP<Matrix> C = MatrixFactory::Build(M1_Matrix_->getRowMap(),0);
156  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*M1_Matrix_,false,*D0_Matrix_,false,*C,true,true);
157  A22_=MatrixFactory::Build(D0_Matrix_->getDomainMap(),0);
158  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*D0_Matrix_,true,*C,false,*A22_,true,true);
159  A22_->resumeFill();
160  Remove_Zeroed_Rows(A22_,1.0e-16);
161  A22_->SetFixedBlockSize(1);
162 
163  // Use HierarchyManagers to build 11 & 22 Hierarchies
165  RCP<HierarchyManager> Manager11, Manager22, ManagerSmoother;
166  std::string syntaxStr = "parameterlist: syntax";
167  if (parameterList_.isParameter(syntaxStr) && parameterList_.get<std::string>(syntaxStr) == "ml") {
168  parameterList_.remove(syntaxStr);
169  Manager11 = rcp(new MLParameterListInterpreter<SC,LO,GO,NO>(precList11_));
170  Manager22 = rcp(new MLParameterListInterpreter<SC,LO,GO,NO>(precList22_));
171  ManagerSmoother = rcp(new MLParameterListInterpreter<SC,LO,GO,NO>(smootherList_));
172  } else {
173  Manager11 = rcp(new ParameterListInterpreter <SC,LO,GO,NO>(precList11_,A11_->getDomainMap()->getComm()));
174  Manager22 = rcp(new ParameterListInterpreter <SC,LO,GO,NO>(precList22_,A22_->getDomainMap()->getComm()));
175  ManagerSmoother = rcp(new ParameterListInterpreter<SC,LO,GO,NO>(smootherList_,SM_Matrix_->getDomainMap()->getComm()));
176  }
177 
178  Hierarchy11_=Manager11->CreateHierarchy();
179  Hierarchy11_->setlib(Xpetra::UseTpetra);
180  Hierarchy11_->GetLevel(0)->Set("A", A11_);
181  Manager11->SetupHierarchy(*Hierarchy11_);
182 
183  Hierarchy22_=Manager22->CreateHierarchy();
184  Hierarchy22_->setlib(Xpetra::UseTpetra);
185  Hierarchy22_->GetLevel(0)->Set("A", A22_);
186  Manager22->SetupHierarchy(*Hierarchy22_);
187 
188  // build ifpack2 preconditioners for pre and post smoothing
189  HierarchySmoother_=ManagerSmoother->CreateHierarchy();
190  HierarchySmoother_->setlib(Xpetra::UseTpetra);
191  HierarchySmoother_->GetLevel(0)->Set("A", SM_Matrix_);
192  ManagerSmoother->SetupHierarchy(*HierarchySmoother_);
193 
194 }
195 
196 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
198 
199  Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
200  out.setOutputToRootOnly(0);
201  out.setShowProcRank(true);
202 
203  // build prolongator: algorithm 1 in the reference paper
204  // First, aggregate nodal matrix by creating a 2-level hierarchy
205  Teuchos::RCP<Hierarchy> auxHierarchy
206  = Teuchos::rcp( new Hierarchy(TMT_Matrix_) );
207  Teuchos::RCP<FactoryManager> auxManager
208  = Teuchos::rcp( new FactoryManager );
209  Teuchos::RCP<TentativePFactory> TentPfact
210  = Teuchos::rcp( new TentativePFactory );
211  Teuchos::RCP<SaPFactory> Pfact
212  = Teuchos::rcp( new SaPFactory );
213  Teuchos::RCP<UncoupledAggregationFactory> Aggfact
214  = Teuchos::rcp( new UncoupledAggregationFactory() );
215  Teuchos::ParameterList params;
216  params.set("sa: damping factor",0.0);
217  Pfact -> SetParameterList(params);
218  auxManager -> SetFactory("P", Pfact);
219  auxManager -> SetFactory("Ptent", TentPfact);
220  auxManager -> SetFactory("Aggregates", Aggfact);
221  auxManager -> SetFactory("Smoother", Teuchos::null);
222  auxManager -> SetFactory("CoarseSolver", Teuchos::null);
223  auxHierarchy -> Keep("P", Pfact.get());
224  auxHierarchy -> SetMaxCoarseSize(1);
225  auxHierarchy -> Setup(*auxManager, 0, 2);
226 
227  // pull out tentative P
228  Teuchos::RCP<Level> Level1 = auxHierarchy -> GetLevel(1);
229  Teuchos::RCP<Matrix> P = Level1 -> Get< Teuchos::RCP<Matrix> >("P",Pfact.get());
230 
231  // make weighting matrix
232  Teuchos::RCP<Matrix> D0_Matrix_Abs=MatrixFactory2::BuildCopy(D0_Matrix_);
233  D0_Matrix_Abs -> resumeFill();
234  D0_Matrix_Abs -> setAllToScalar((Scalar)0.5);
235  Apply_BCsToMatrixRows(D0_Matrix_Abs,BCrows_);
236  Apply_BCsToMatrixCols(D0_Matrix_Abs,BCcols_);
237  D0_Matrix_Abs -> fillComplete(D0_Matrix_->getDomainMap(),D0_Matrix_->getRangeMap());
238  Teuchos::RCP<Matrix> Ptent = MatrixFactory::Build(D0_Matrix_Abs->getRowMap(),0);
239  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*D0_Matrix_Abs,false,*P,false,*Ptent,true,true);
240 
241  // put in entries to P11
242  size_t dim = Nullspace_->getNumVectors();
243  size_t numLocalRows = SM_Matrix_->getNodeNumRows();
244  Teuchos::RCP<Map> BlockColMap
245  = Xpetra::MapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(Ptent->getColMap(),dim);
246  P11_ = Teuchos::rcp(new CrsMatrixWrap(Ptent->getRowMap(),BlockColMap,0,Xpetra::StaticProfile));
247 
248  std::vector< Teuchos::ArrayRCP<const Scalar> > nullspace(dim);
249  for(size_t i=0; i<dim; i++) {
250  Teuchos::ArrayRCP<const Scalar> datavec = Nullspace_->getData(i);
251  nullspace[i]=datavec;
252  }
253 
254  size_t nnz=0;
255  std::vector<size_t> rowPtrs;
256  std::vector<LocalOrdinal> blockCols;
257  std::vector<Scalar> blockVals;
258  for(size_t i=0; i<numLocalRows; i++) {
259  rowPtrs.push_back(nnz);
260  Teuchos::ArrayView<const LocalOrdinal> localCols;
261  Teuchos::ArrayView<const Scalar> localVals;
262  Ptent->getLocalRowView(i,localCols,localVals);
263  size_t numCols = localCols.size();
264  for(size_t j=0; j<numCols; j++) {
265  for(size_t k=0; k<dim; k++) {
266  blockCols.push_back(localCols[j]*dim+k);
267  blockVals.push_back(localVals[j]*nullspace[k][i]);
268  nnz++;
269  }
270  }
271  }
272  rowPtrs.push_back(nnz);
273 
274  ArrayRCP<size_t> rcpRowPtr;
275  ArrayRCP<LocalOrdinal> rcpColumns;
276  ArrayRCP<Scalar> rcpValues;
277 
278  RCP<CrsMatrix> TP11 = rcp_dynamic_cast<CrsMatrixWrap>(P11_)->getCrsMatrix();
279  TP11->allocateAllValues(nnz, rcpRowPtr, rcpColumns, rcpValues);
280 
281  ArrayView<size_t> rows = rcpRowPtr();
282  ArrayView<LocalOrdinal> columns = rcpColumns();
283  ArrayView<Scalar> values = rcpValues();
284 
285  for (size_t ii = 0; ii < rowPtrs.size(); ii++) rows[ii] = rowPtrs[ii];
286  for (size_t ii = 0; ii < blockCols.size(); ii++) columns[ii] = blockCols[ii];
287  for (size_t ii = 0; ii < blockVals.size(); ii++) values[ii] = blockVals[ii];
288  TP11->setAllValues(rcpRowPtr, rcpColumns, rcpValues);
289  Teuchos::RCP<Map> blockCoarseMap
290  = Xpetra::MapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(Ptent->getDomainMap(),dim);
291  TP11->expertStaticFillComplete(blockCoarseMap,SM_Matrix_->getDomainMap());
292 
293 }
294 
295 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
297 
298  // coarse matrix for P11* (M1 + D1* M2 D1) P11
299  Teuchos::RCP<Matrix> C = MatrixFactory::Build(SM_Matrix_->getRowMap(),0);
300  Teuchos::RCP<Matrix> Matrix1 = MatrixFactory::Build(P11_->getDomainMap(),0);
301 
302  // construct (M1 + D1* M2 D1) P11
303  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*SM_Matrix_,false,*P11_,false,*C,true,true);
304 
305  // construct P11* (M1 + D1* M2 D1) P11
306  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*P11_,true,*C,false,*Matrix1,true,true);
307 
308  if(disable_addon_==true) {
309  // if add-on is not chosen
310  A11_=Matrix1;
311  }
312  else {
313  // catch a failure
314  TEUCHOS_TEST_FOR_EXCEPTION(M0inv_Matrix_==Teuchos::null,std::invalid_argument,
315  "MueLu::RefMaxwell::formCoarseMatrix(): Inverse of "
316  "lumped mass matrix required for add-on (i.e. M0inv_Matrix is null)");
317 
318  // coarse matrix for add-on, i.e P11* (M1 D0 M0inv D0* M1) P11
319  Teuchos::RCP<Matrix> Zaux = MatrixFactory::Build(M1_Matrix_->getRowMap(),0);
320  Teuchos::RCP<Matrix> Z = MatrixFactory::Build(D0_Matrix_->getDomainMap(),0);
321  Teuchos::RCP<Matrix> C2 = MatrixFactory::Build(M0inv_Matrix_->getRowMap(),0);
322  // construct M1 P11
323  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*M1_Matrix_,false,*P11_,false,*Zaux,true,true);
324  // construct Z = D0* M1 P11
325  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*D0_Matrix_,true,*Zaux,false,*Z,true,true);
326  // construct M0inv Z
327  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*M0inv_Matrix_,false,*Z,false,*C2,true,true);
328  // construct Z* M0inv Z
329  Teuchos::RCP<Matrix> Matrix2 = MatrixFactory::Build(Z->getDomainMap(),0);
330  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*Z,true,*C2,false,*Matrix2,true,true);
331  // add matrices together
332  RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
333  Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::TwoMatrixAdd(*Matrix1,false,(Scalar)1.0,*Matrix2,false,(Scalar)1.0,A11_,*out);
334  A11_->fillComplete();
335  }
336 
337  // set fixed block size for vector nodal matrix
338  size_t dim = Nullspace_->getNumVectors();
339  A11_->SetFixedBlockSize(dim);
340 
341 }
342 
343 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
344 void RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::resetMatrix(Teuchos::RCP<Matrix> SM_Matrix_new) {
345  SM_Matrix_ = SM_Matrix_new;
346 }
347 
348 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
349 void RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::applyInverseAdditive(const MultiVector& RHS, MultiVector& X) const {
350 
351  // compute residuals
352  RCP<MultiVector> residual = Utilities::Residual(*SM_Matrix_, X, RHS);
353  RCP<MultiVector> P11res = MultiVectorFactory::Build(P11_->getDomainMap(),X.getNumVectors());
354  RCP<MultiVector> P11x = MultiVectorFactory::Build(P11_->getDomainMap(),X.getNumVectors());
355  RCP<MultiVector> D0res = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(),X.getNumVectors());
356  RCP<MultiVector> D0x = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(),X.getNumVectors());
357  P11_->apply(*residual,*P11res,Teuchos::TRANS);
358  D0_Matrix_->apply(*residual,*D0res,Teuchos::TRANS);
359 
360  // block diagonal preconditioner on 2x2 (V-cycle for diagonal blocks)
361  Hierarchy11_->Iterate(*P11res, *P11x, 1, true);
362  Hierarchy22_->Iterate(*D0res, *D0x, 1, true);
363 
364  // update current solution
365  P11_->apply(*P11x,*residual,Teuchos::NO_TRANS);
366  D0_Matrix_->apply(*D0x,*residual,Teuchos::NO_TRANS,(Scalar)1.0,(Scalar)1.0);
367  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
368 
369 }
370 
371 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
372 void RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::applyInverse121(const MultiVector& RHS, MultiVector& X) const {
373 
374  RCP<MultiVector> P11res = MultiVectorFactory::Build(P11_->getDomainMap(),X.getNumVectors());
375  RCP<MultiVector> P11x = MultiVectorFactory::Build(P11_->getDomainMap(),X.getNumVectors());
376  RCP<MultiVector> D0res = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(),X.getNumVectors());
377  RCP<MultiVector> D0x = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(),X.getNumVectors());
378 
379  // precondition (1,1)-block
380  RCP<MultiVector> residual = Utilities::Residual(*SM_Matrix_, X, RHS);
381  P11_->apply(*residual,*P11res,Teuchos::TRANS);
382  Hierarchy11_->Iterate(*P11res, *P11x, 1, true);
383  P11_->apply(*P11x,*residual,Teuchos::NO_TRANS);
384  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
385 
386  // precondition (2,2)-block
387  residual = Utilities::Residual(*SM_Matrix_, X, RHS);
388  D0_Matrix_->apply(*residual,*D0res,Teuchos::TRANS);
389  Hierarchy22_->Iterate(*D0res, *D0x, 1, true);
390  D0_Matrix_->apply(*D0x,*residual,Teuchos::NO_TRANS);
391  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
392 
393  // precondition (1,1)-block
394  residual = Utilities::Residual(*SM_Matrix_, X, RHS);
395  P11_->apply(*residual,*P11res,Teuchos::TRANS);
396  Hierarchy11_->Iterate(*P11res, *P11x, 1, true);
397  P11_->apply(*P11x,*residual,Teuchos::NO_TRANS);
398  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
399 
400 }
401 
402 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
403 void RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::applyInverse212(const MultiVector& RHS, MultiVector& X) const {
404 
405  RCP<MultiVector> P11res = MultiVectorFactory::Build(P11_->getDomainMap(),X.getNumVectors());
406  RCP<MultiVector> P11x = MultiVectorFactory::Build(P11_->getDomainMap(),X.getNumVectors());
407  RCP<MultiVector> D0res = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(),X.getNumVectors());
408  RCP<MultiVector> D0x = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(),X.getNumVectors());
409 
410  // precondition (2,2)-block
411  RCP<MultiVector> residual = Utilities::Residual(*SM_Matrix_, X, RHS);
412  D0_Matrix_->apply(*residual,*D0res,Teuchos::TRANS);
413  Hierarchy22_->Iterate(*D0res, *D0x, 1, true);
414  D0_Matrix_->apply(*D0x,*residual,Teuchos::NO_TRANS);
415  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
416 
417  // precondition (1,1)-block
418  residual = Utilities::Residual(*SM_Matrix_, X, RHS);
419  P11_->apply(*residual,*P11res,Teuchos::TRANS);
420  Hierarchy11_->Iterate(*P11res, *P11x, 1, true);
421  P11_->apply(*P11x,*residual,Teuchos::NO_TRANS);
422  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
423 
424  // precondition (2,2)-block
425  residual = Utilities::Residual(*SM_Matrix_, X, RHS);
426  D0_Matrix_->apply(*residual,*D0res,Teuchos::TRANS);
427  Hierarchy22_->Iterate(*D0res, *D0x, 1, true);
428  D0_Matrix_->apply(*D0x,*residual,Teuchos::NO_TRANS);
429  X.update((Scalar) 1.0, *residual, (Scalar) 1.0);
430 
431 }
432 
433 
434 /*void RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::apply(const Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& X,
435  Tpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Y,
436  Teuchos::ETransp mode, Scalar alpha, Scalar beta) const {*/
437 
438 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
439 void RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>::apply (const MultiVector& X, MultiVector& Y,
440  Teuchos::ETransp mode,
441  Scalar alpha,
442  Scalar beta) const {
443  try {
444 
445  /*TMV& temp_x = const_cast<TMV &>(X);
446  const XTMV tX(rcpFromRef(temp_x));
447  XTMV tY(rcpFromRef(Y));
448  tY.putScalar(Teuchos::ScalarTraits<Scalar>::zero());*/
449 
450  Y.putScalar(Teuchos::ScalarTraits<Scalar>::zero());
451 
452  // apply pre-smoothing
453  HierarchySmoother_->Iterate(X,Y,1);
454 
455  // do solve for the 2x2 block system
456 
457  if(mode_=="additive")
458  applyInverseAdditive(X,Y);
459  else if(mode_=="121")
460  applyInverse121(X,Y);
461  else if(mode_=="212")
462  applyInverse212(X,Y);
463  else
464  applyInverseAdditive(X,Y);
465 
466  // apply post-smoothing
467  HierarchySmoother_->Iterate(X,Y,1);
468 
469  } catch (std::exception& e) {
470 
471  //FIXME add message and rethrow
472  std::cerr << "Caught an exception in MueLu::RefMaxwell::ApplyInverse():" << std::endl
473  << e.what() << std::endl;
474 
475  }
476 }
477 
478 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
480  return false;
481 }
482 
483 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
485 initialize(const Teuchos::RCP<Matrix> & D0_Matrix,
486  const Teuchos::RCP<Matrix> & M0inv_Matrix,
487  const Teuchos::RCP<Matrix> & M1_Matrix,
488  const Teuchos::RCP<MultiVector> & Nullspace,
489  const Teuchos::RCP<MultiVector> & Coords,
490  Teuchos::ParameterList& List)
491 {
492  // some pre-conditions
493  TEUCHOS_ASSERT(D0_Matrix!=Teuchos::null);
494  TEUCHOS_ASSERT(M1_Matrix!=Teuchos::null);
495 
496  Hierarchy11_ = Teuchos::null;
497  Hierarchy22_ = Teuchos::null;
498  HierarchySmoother_ = Teuchos::null;
499  parameterList_ = List;
500  disable_addon_ = false;
501  mode_ = "additive";
502 
503  // set parameters
504  setParameters(List);
505 
506  D0_Matrix_ = D0_Matrix;
507  M0inv_Matrix_ = M0inv_Matrix;
508  M1_Matrix_ = M1_Matrix;
509  Coords_ = Coords;
510  Nullspace_ = Nullspace;
511 }
512 
513 } // namespace
514 
515 #define MUELU_REFMAXWELL_SHORT
516 #endif //ifdef MUELU_REFMAXWELL_DEF_HPP
This class specifies the default factory that should generate some data on a Level if the data does n...
void initialize(const Teuchos::RCP< Matrix > &D0_Matrix, const Teuchos::RCP< Matrix > &M0inv_Matrix, const Teuchos::RCP< Matrix > &M1_Matrix, const Teuchos::RCP< MultiVector > &Nullspace, const Teuchos::RCP< MultiVector > &Coords, Teuchos::ParameterList &List)
Namespace for MueLu classes and methods.
void setParameters(Teuchos::ParameterList &list)
Set parameters.
void applyInverseAdditive(const MultiVector &RHS, MultiVector &X) const
apply additive algorithm for 2x2 solve
void buildProlongator()
Setup the prolongator for the (1,1)-block.
Factory for building tentative prolongator.
static RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &X, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS)
void applyInverse121(const MultiVector &RHS, MultiVector &X) const
apply 1-2-1 algorithm for 2x2 solve
void compute()
Setup the preconditioner.
Teuchos::RCP< const Map > getRangeMap() const
Returns the Xpetra::Map object associated with the range of this operator.
Always keep data, even accross run. This flag is set by Level::Keep(). This flag is propagated to coa...
Class that accepts ML-style parameters and builds a MueLu preconditioner. This interpreter uses the s...
bool hasTransposeApply() const
Indicates whether this operator supports applying the adjoint operator.
void applyInverse212(const MultiVector &RHS, MultiVector &X) const
apply 2-1-2 algorithm for 2x2 solve
void formCoarseMatrix()
Compute P11^{T}*A*P11 efficiently.
void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=Teuchos::ScalarTraits< Scalar >::one(), Scalar beta=Teuchos::ScalarTraits< Scalar >::zero()) const
Factory for building Smoothed Aggregation prolongators.
Factory for building uncoupled aggregates.
void resetMatrix(Teuchos::RCP< Matrix > SM_Matrix_new)
Reset system matrix.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
Teuchos::RCP< const Map > getDomainMap() const
Returns the Xpetra::Map object associated with the domain of this operator.