MueLu  Version of the Day
MueLu_UzawaSmoother_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 /*
47  * MueLu_UzawaSmoother_def.hpp
48  *
49  * Created on: 13 May 2014
50  * Author: wiesner
51  */
52 
53 #ifndef MUELU_UZAWASMOOTHER_DEF_HPP_
54 #define MUELU_UZAWASMOOTHER_DEF_HPP_
55 
56 #include "Teuchos_ArrayViewDecl.hpp"
57 #include "Teuchos_ScalarTraits.hpp"
58 
59 #include "MueLu_ConfigDefs.hpp"
60 
61 #include <Xpetra_Matrix.hpp>
62 #include <Xpetra_BlockedCrsMatrix.hpp>
63 #include <Xpetra_MultiVectorFactory.hpp>
64 #include <Xpetra_VectorFactory.hpp>
65 #include <Xpetra_ReorderedBlockedCrsMatrix.hpp>
66 
68 #include "MueLu_Level.hpp"
69 #include "MueLu_Utilities.hpp"
70 #include "MueLu_Monitor.hpp"
71 #include "MueLu_HierarchyUtils.hpp"
72 #include "MueLu_SmootherBase.hpp"
73 #include "MueLu_SubBlockAFactory.hpp"
74 
75 // include files for default FactoryManager
76 #include "MueLu_SchurComplementFactory.hpp"
77 #include "MueLu_DirectSolver.hpp"
78 #include "MueLu_SmootherFactory.hpp"
79 #include "MueLu_FactoryManager.hpp"
80 
81 namespace MueLu {
82 
83  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
85  : type_("Uzawa"), A_(Teuchos::null)
86  {
87  }
88 
89  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
91 
92  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
94  RCP<ParameterList> validParamList = rcp(new ParameterList());
95 
96  validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
97  validParamList->set< Scalar > ("Damping factor", 1.0, "Damping/Scaling factor in SIMPLE");
98  validParamList->set< LocalOrdinal > ("Sweeps", 1, "Number of SIMPLE sweeps (default = 1)");
99 
100  return validParamList;
101  }
102 
104  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
105  void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::AddFactoryManager(RCP<const FactoryManagerBase> FactManager, int pos) {
106  TEUCHOS_TEST_FOR_EXCEPTION(pos < 0, Exceptions::RuntimeError, "MueLu::UzawaSmoother::AddFactoryManager: parameter \'pos\' must not be negative! error.");
107 
108  size_t myPos = Teuchos::as<size_t>(pos);
109 
110  if (myPos < FactManager_.size()) {
111  // replace existing entris in FactManager_ vector
112  FactManager_.at(myPos) = FactManager;
113  } else if( myPos == FactManager_.size()) {
114  // add new Factory manager in the end of the vector
115  FactManager_.push_back(FactManager);
116  } else { // if(myPos > FactManager_.size())
117  RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
118  *out << "Warning: cannot add new FactoryManager at proper position " << pos << ". The FactoryManager is just appended to the end. Check this!" << std::endl;
119 
120  // add new Factory manager in the end of the vector
121  FactManager_.push_back(FactManager);
122  }
123 
124  }
125 
126 
127  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
129  AddFactoryManager(FactManager, 0); // overwrite factory manager for predicting the primary variable
130  }
131 
132  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
134  AddFactoryManager(FactManager, 1); // overwrite factory manager for SchurComplement
135  }
136 
137  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
139  currentLevel.DeclareInput("A",this->GetFactory("A").get());
140 
141  TEUCHOS_TEST_FOR_EXCEPTION(FactManager_.size() != 2, Exceptions::RuntimeError,"MueLu::UzawaSmoother::DeclareInput: You have to declare two FactoryManagers with a \"Smoother\" object: One for predicting the primary variable and one for the SchurComplement system. The smoother for the SchurComplement system needs a SchurComplementFactory as input for variable \"A\". make sure that you use the same proper damping factors for omega both in the SchurComplementFactory and in the SIMPLE smoother!");
142 
143  // loop over all factory managers for the subblocks of blocked operator A
144  std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
145  for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
146  SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
147 
148  // request "Smoother" for current subblock row.
149  currentLevel.DeclareInput("PreSmoother",(*it)->GetFactory("Smoother").get());
150  }
151  }
152 
153  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
155 
156  FactoryMonitor m(*this, "Setup blocked Uzawa Smoother", currentLevel);
157 
158  if (SmootherPrototype::IsSetup() == true)
159  this->GetOStream(Warnings0) << "MueLu::UzawaSmoother::Setup(): Setup() has already been called";
160 
161  // extract blocked operator A from current level
162  A_ = Factory::Get<RCP<Matrix> > (currentLevel, "A");
163 
164  RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
165  TEUCHOS_TEST_FOR_EXCEPTION(bA == Teuchos::null, Exceptions::BadCast, "MueLu::UzawaSmoother::Setup: input matrix A is not of type BlockedCrsMatrix! error.");
166 
167  // store map extractors
168  rangeMapExtractor_ = bA->getRangeMapExtractor();
169  domainMapExtractor_ = bA->getDomainMapExtractor();
170 
171  // Store the blocks in local member variables
172  F_ = bA->getMatrix(0, 0);
173  G_ = bA->getMatrix(0, 1);
174  D_ = bA->getMatrix(1, 0);
175  Z_ = bA->getMatrix(1, 1);
176 
177  // Set the Smoother
178  // carefully switch to the SubFactoryManagers (defined by the users)
179  {
180  RCP<const FactoryManagerBase> velpredictFactManager = FactManager_.at(0);
181  SetFactoryManager currentSFM (rcpFromRef(currentLevel), velpredictFactManager);
182  velPredictSmoo_ = currentLevel.Get< RCP<SmootherBase> >("PreSmoother",velpredictFactManager->GetFactory("Smoother").get());
183  }
184  {
185  RCP<const FactoryManagerBase> schurFactManager = FactManager_.at(1);
186  SetFactoryManager currentSFM (rcpFromRef(currentLevel), schurFactManager);
187  schurCompSmoo_ = currentLevel.Get< RCP<SmootherBase> >("PreSmoother", schurFactManager->GetFactory("Smoother").get());
188  }
189 
191  }
192 
193  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
194  void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool /* InitialGuessIsZero */) const
195  {
196  TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::UzawaSmoother::Apply(): Setup() has not been called");
197 
198  Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout));
199 
200  SC zero = Teuchos::ScalarTraits<SC>::zero(), one = Teuchos::ScalarTraits<SC>::one();
201 
202  bool bRangeThyraMode = rangeMapExtractor_->getThyraMode();
203  bool bDomainThyraMode = domainMapExtractor_->getThyraMode();
204 
205  // extract parameters from internal parameter list
206  const ParameterList & pL = Factory::GetParameterList();
207  LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
208  Scalar omega = pL.get<Scalar>("Damping factor");
209 
210  // wrap current solution vector in RCP
211  RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X);
212  RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
213 
214  // make sure that both rcpX and rcpB are BlockedMultiVector objects
215  bool bCopyResultX = false;
216  RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
217  MUELU_TEST_FOR_EXCEPTION(bA.is_null() == true, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): A_ must be a BlockedCrsMatrix");
218  RCP<BlockedMultiVector> bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
219  RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
220 
221  if(bX.is_null() == true) {
222  RCP<MultiVector> test = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedDomainMap(),rcpX));
223  rcpX.swap(test);
224  bCopyResultX = true;
225  }
226 
227  if(bB.is_null() == true) {
228  RCP<const MultiVector> test = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedRangeMap(),rcpB));
229  rcpB.swap(test);
230  }
231 
232  // we now can guarantee that X and B are blocked multi vectors
233  bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
234  bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
235 
236  // check the type of operator
237  RCP<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rbA = Teuchos::rcp_dynamic_cast<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(bA);
238  if(rbA.is_null() == false) {
239  // A is a ReorderedBlockedCrsMatrix
240  Teuchos::RCP<const Xpetra::BlockReorderManager > brm = rbA->getBlockReorderManager();
241 
242  // check type of X vector
243  if(bX->getBlockedMap()->getNumMaps() != bA->getDomainMapExtractor()->NumMaps()) {
244  // X is a blocked multi vector but incompatible to the reordered blocked operator A
245  Teuchos::RCP<MultiVector> test =
246  buildReorderedBlockedMultiVector(brm, bX);
247  rcpX.swap(test);
248  }
249  if(bB->getBlockedMap()->getNumMaps() != bA->getRangeMapExtractor()->NumMaps()) {
250  // B is a blocked multi vector but incompatible to the reordered blocked operator A
251  Teuchos::RCP<const MultiVector> test =
252  buildReorderedBlockedMultiVector(brm, bB);
253  rcpB.swap(test);
254  }
255  }
256 
257  // Throughout the rest of the algorithm rcpX and rcpB are used for solution vector and RHS
258 
259  // create residual vector
260  // contains current residual of current solution X with rhs B
261  RCP<MultiVector> residual = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
262  RCP<BlockedMultiVector> bresidual = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(residual);
263  Teuchos::RCP<MultiVector> r1 = bresidual->getMultiVector(0,bRangeThyraMode);
264  Teuchos::RCP<MultiVector> r2 = bresidual->getMultiVector(1,bRangeThyraMode);
265 
266  // helper vector 1
267  RCP<MultiVector> xtilde = MultiVectorFactory::Build(rcpX->getMap(), rcpX->getNumVectors());
268  RCP<BlockedMultiVector> bxtilde = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xtilde);
269  RCP<MultiVector> xtilde1 = bxtilde->getMultiVector(0,bDomainThyraMode);
270  RCP<MultiVector> xtilde2 = bxtilde->getMultiVector(1,bDomainThyraMode);
271 
272  // incrementally improve solution vector X
273  for (LocalOrdinal run = 0; run < nSweeps; ++run) {
274  // 1) calculate current residual
275  residual->update(one,*rcpB,zero); // residual = B
276  A_->apply(*rcpX, *residual, Teuchos::NO_TRANS, -one, one);
277 
278  // 2) solve F * \Delta \tilde{x}_1 = r_1
279  // start with zero guess \Delta \tilde{x}_1
280  bxtilde->putScalar(zero);
281  velPredictSmoo_->Apply(*xtilde1,*r1);
282 
283  // 3) calculate rhs for SchurComp equation
284  // r_2 - D \Delta \tilde{x}_1
285  RCP<MultiVector> schurCompRHS = MultiVectorFactory::Build(r2->getMap(),rcpB->getNumVectors());
286  D_->apply(*xtilde1,*schurCompRHS);
287  schurCompRHS->update(one,*r2,-one);
288 
289  // 4) solve SchurComp equation
290  // start with zero guess \Delta \tilde{x}_2
291  schurCompSmoo_->Apply(*xtilde2,*schurCompRHS);
292 
293  rcpX->update(omega,*bxtilde,one);
294  }
295 
296  if (bCopyResultX == true) {
297  RCP<MultiVector> Xmerged = bX->Merge();
298  X.update(one, *Xmerged, zero);
299  }
300  }
301 
302  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
303  RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
305  return rcp( new UzawaSmoother(*this) );
306  }
307 
308  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
310  std::ostringstream out;
312  out << "{type = " << type_ << "}";
313  return out.str();
314  }
315 
316  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
317  void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream &out, const VerbLevel verbLevel) const {
319 
320  if (verbLevel & Parameters0) {
321  out0 << "Prec. type: " << type_ << /*" Sweeps: " << nSweeps_ << " damping: " << omega_ <<*/ std::endl;
322  }
323 
324  if (verbLevel & Debug) {
325  out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
326  }
327  }
328 
329  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
331  // FIXME: This is a placeholder
332  return Teuchos::OrdinalTraits<size_t>::invalid();
333  }
334 
335 } // namespace MueLu
336 
337 
338 #endif /* MUELU_UZAWASMOOTHER_DEF_HPP_ */
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
#define MUELU_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
virtual std::string description() const
Return a simple one-line description of this object.
Exception indicating invalid cast attempted.
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 DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
virtual const Teuchos::ParameterList & GetParameterList() const
An exception safe way to call the method 'Level::SetFactoryManager()'.
bool IsSetup() const
Get the state of a smoother prototype.
Block triangle Uzawa smoother for 2x2 block matrices.
RCP< SmootherPrototype > Copy() const
void Setup(Level &currentLevel)
Setup routine.
RCP< const ParameterList > GetValidParameterList() const
Input.
void AddFactoryManager(RCP< const FactoryManagerBase > FactManager, int pos)
Add a factory manager at a specific position.
void Apply(MultiVector &X, MultiVector const &B, bool InitialGuessIsZero=false) const
Apply the Braess Sarazin smoother.
std::string description() const
Return a simple one-line description of this object.
void SetSchurCompFactoryManager(RCP< FactoryManager > FactManager)
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
void DeclareInput(Level &currentLevel) const
Input.
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
virtual ~UzawaSmoother()
Destructor.
void SetVelocityPredictionFactoryManager(RCP< FactoryManager > FactManager)
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line)
@ Debug
Print additional debugging information.
@ Parameters0
Print class parameters.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.