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>
64 #include <Xpetra_VectorFactory.hpp>
65 
67 #include "MueLu_Level.hpp"
68 #include "MueLu_Utilities.hpp"
69 #include "MueLu_Monitor.hpp"
70 #include "MueLu_HierarchyUtils.hpp"
71 #include "MueLu_SmootherBase.hpp"
72 #include "MueLu_SubBlockAFactory.hpp"
73 
74 // include files for default FactoryManager
75 #include "MueLu_SchurComplementFactory.hpp"
76 #include "MueLu_DirectSolver.hpp"
77 #include "MueLu_SmootherFactory.hpp"
78 #include "MueLu_FactoryManager.hpp"
79 
80 namespace MueLu {
81 
82  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
84  : type_("Uzawa"), A_(Teuchos::null)
85  {
86  }
87 
88  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
90 
91  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
93  RCP<ParameterList> validParamList = rcp(new ParameterList());
94 
95  validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
96  validParamList->set< Scalar > ("Damping factor", 1.0, "Damping/Scaling factor in SIMPLE");
97  validParamList->set< LocalOrdinal > ("Sweeps", 1, "Number of SIMPLE sweeps (default = 1)");
98 
99  return validParamList;
100  }
101 
103  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
105  TEUCHOS_TEST_FOR_EXCEPTION(pos < 0, Exceptions::RuntimeError, "MueLu::UzawaSmoother::AddFactoryManager: parameter \'pos\' must not be negative! error.");
106 
107  size_t myPos = Teuchos::as<size_t>(pos);
108 
109  if (myPos < FactManager_.size()) {
110  // replace existing entris in FactManager_ vector
111  FactManager_.at(myPos) = FactManager;
112  } else if( myPos == FactManager_.size()) {
113  // add new Factory manager in the end of the vector
114  FactManager_.push_back(FactManager);
115  } else { // if(myPos > FactManager_.size())
116  RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
117  *out << "Warning: cannot add new FactoryManager at proper position " << pos << ". The FactoryManager is just appended to the end. Check this!" << std::endl;
118 
119  // add new Factory manager in the end of the vector
120  FactManager_.push_back(FactManager);
121  }
122 
123  }
124 
125 
126  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
128  AddFactoryManager(FactManager, 0); // overwrite factory manager for predicting the primary variable
129  }
130 
131  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
133  AddFactoryManager(FactManager, 1); // overwrite factory manager for SchurComplement
134  }
135 
136  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
138  currentLevel.DeclareInput("A",this->GetFactory("A").get());
139 
140  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!");
141 
142  // loop over all factory managers for the subblocks of blocked operator A
143  std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
144  for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
145  SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
146 
147  // request "Smoother" for current subblock row.
148  currentLevel.DeclareInput("PreSmoother",(*it)->GetFactory("Smoother").get());
149  }
150  }
151 
152  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
154 
155  FactoryMonitor m(*this, "Setup blocked Uzawa Smoother", currentLevel);
156 
157  if (SmootherPrototype::IsSetup() == true)
158  this->GetOStream(Warnings0) << "MueLu::UzawaSmoother::Setup(): Setup() has already been called";
159 
160  // extract blocked operator A from current level
161  A_ = Factory::Get<RCP<Matrix> > (currentLevel, "A");
162 
163  RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
164  TEUCHOS_TEST_FOR_EXCEPTION(bA == Teuchos::null, Exceptions::BadCast, "MueLu::UzawaSmoother::Setup: input matrix A is not of type BlockedCrsMatrix! error.");
165 
166  // store map extractors
167  rangeMapExtractor_ = bA->getRangeMapExtractor();
168  domainMapExtractor_ = bA->getDomainMapExtractor();
169 
170  // Store the blocks in local member variables
171  F_ = bA->getMatrix(0, 0);
172  G_ = bA->getMatrix(0, 1);
173  D_ = bA->getMatrix(1, 0);
174  Z_ = bA->getMatrix(1, 1);
175 
176  // Set the Smoother
177  // carefully switch to the SubFactoryManagers (defined by the users)
178  {
179  RCP<const FactoryManagerBase> velpredictFactManager = FactManager_.at(0);
180  SetFactoryManager currentSFM (rcpFromRef(currentLevel), velpredictFactManager);
181  velPredictSmoo_ = currentLevel.Get< RCP<SmootherBase> >("PreSmoother",velpredictFactManager->GetFactory("Smoother").get());
182  }
183  {
184  RCP<const FactoryManagerBase> schurFactManager = FactManager_.at(1);
185  SetFactoryManager currentSFM (rcpFromRef(currentLevel), schurFactManager);
186  schurCompSmoo_ = currentLevel.Get< RCP<SmootherBase> >("PreSmoother", schurFactManager->GetFactory("Smoother").get());
187  }
188 
190  }
191 
192  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
193  void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const
194  {
195  TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::UzawaSmoother::Apply(): Setup() has not been called");
196 
197  Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout));
198 
200 
201  // The following boolean flags catch the case where we need special transformation
202  // for the GIDs when calling the subsmoothers.
203  RCP<BlockedCrsMatrix> bA00 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(F_);
204  RCP<BlockedCrsMatrix> bA11 = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Z_);
205  bool bFThyraSpecialTreatment = false;
206  bool bZThyraSpecialTreatment = false;
207  if (bA00 != Teuchos::null) {
208  if(bA00->Rows() == 1 && bA00->Cols() == 1 && rangeMapExtractor_->getThyraMode() == true) bFThyraSpecialTreatment = true;
209  }
210  if (bA11 != Teuchos::null) {
211  if(bA11->Rows() == 1 && bA11->Cols() == 1 && rangeMapExtractor_->getThyraMode() == true) bZThyraSpecialTreatment = true;
212  }
213 
214  // extract parameters from internal parameter list
216  LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
217  Scalar omega = pL.get<Scalar>("Damping factor");
218 
219  // wrap current solution vector in RCP
220  RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X);
221 
222  // create residual vector
223  // contains current residual of current solution X with rhs B
224  RCP<MultiVector> residual = MultiVectorFactory::Build(B.getMap(), B.getNumVectors());
225 
226  // incrementally improve solution vector X
227  for (LocalOrdinal run = 0; run < nSweeps; ++run) {
228  // 1) calculate current residual
229  residual->update(one,B,zero); // residual = B
230  A_->apply(*rcpX, *residual, Teuchos::NO_TRANS, -one, one);
231 
232  // split residual vector
233  Teuchos::RCP<MultiVector> r1 = rangeMapExtractor_->ExtractVector(residual, 0);
234  Teuchos::RCP<MultiVector> r2 = rangeMapExtractor_->ExtractVector(residual, 1);
235 
236  // 2) solve F * \Delta \tilde{x}_1 = r_1
237  // start with zero guess \Delta \tilde{x}_1
238  RCP<MultiVector> xtilde1 = MultiVectorFactory::Build(F_->getRowMap(),X.getNumVectors(),true);
239 
240  // Special handling if SchurComplement operator was a 1x1 blocked operator in Thyra mode
241  // Then, we have to translate the Xpetra offset GIDs to plain Thyra GIDs and vice versa
242  if(bFThyraSpecialTreatment == true) {
243  RCP<MultiVector> xtilde1_thyra = domainMapExtractor_->getVector(0, X.getNumVectors(), true);
244  RCP<MultiVector> r1_thyra = rangeMapExtractor_->getVector(0, B.getNumVectors(), true);
245  // transform vector
246  for(size_t k=0; k < r1->getNumVectors(); k++) {
247  Teuchos::ArrayRCP<const Scalar> xpetraVecData = r1->getData(k);
248  Teuchos::ArrayRCP<Scalar> thyraVecData = r1_thyra->getDataNonConst(k);
249  for(size_t i=0; i < r1->getLocalLength(); i++) {
250  thyraVecData[i] = xpetraVecData[i];
251  }
252  }
253 
254  velPredictSmoo_->Apply(*xtilde1_thyra,*r1_thyra);
255 
256  for(size_t k=0; k < xtilde1_thyra->getNumVectors(); k++) {
257  Teuchos::ArrayRCP<Scalar> xpetraVecData = xtilde1->getDataNonConst(k);
258  Teuchos::ArrayRCP<const Scalar> thyraVecData = xtilde1_thyra->getData(k);
259  for(size_t i=0; i < xtilde1_thyra->getLocalLength(); i++) {
260  xpetraVecData[i] = thyraVecData[i];
261  }
262  }
263  } else {
264  velPredictSmoo_->Apply(*xtilde1,*r1);
265  }
266 
267  // 3) calculate rhs for SchurComp equation
268  // r_2 - D \Delta \tilde{x}_1
269  RCP<MultiVector> schurCompRHS = MultiVectorFactory::Build(Z_->getRowMap(),B.getNumVectors());
270  D_->apply(*xtilde1,*schurCompRHS);
271  schurCompRHS->update(one,*r2,-one);
272 
273  // 4) solve SchurComp equation
274  // start with zero guess \Delta \tilde{x}_2
275  RCP<MultiVector> xtilde2 = MultiVectorFactory::Build(Z_->getRowMap(),X.getNumVectors(),true);
276 
277  // Special handling if SchurComplement operator was a 1x1 blocked operator in Thyra mode
278  // Then, we have to translate the Xpetra offset GIDs to plain Thyra GIDs and vice versa
279  if(bZThyraSpecialTreatment == true) {
280  RCP<MultiVector> xtilde2_thyra = domainMapExtractor_->getVector(1, X.getNumVectors(), true);
281  RCP<MultiVector> schurCompRHS_thyra = rangeMapExtractor_->getVector(1, B.getNumVectors(), true);
282  // transform vector
283  for(size_t k=0; k < schurCompRHS->getNumVectors(); k++) {
284  Teuchos::ArrayRCP<const Scalar> xpetraVecData = schurCompRHS->getData(k);
285  Teuchos::ArrayRCP<Scalar> thyraVecData = schurCompRHS_thyra->getDataNonConst(k);
286  for(size_t i=0; i < schurCompRHS->getLocalLength(); i++) {
287  thyraVecData[i] = xpetraVecData[i];
288  }
289  }
290 
291  schurCompSmoo_->Apply(*xtilde2_thyra,*schurCompRHS_thyra);
292 
293  for(size_t k=0; k < xtilde2_thyra->getNumVectors(); k++) {
294  Teuchos::ArrayRCP<Scalar> xpetraVecData = xtilde2->getDataNonConst(k);
295  Teuchos::ArrayRCP<const Scalar> thyraVecData = xtilde2_thyra->getData(k);
296  for(size_t i=0; i < xtilde2_thyra->getLocalLength(); i++) {
297  xpetraVecData[i] = thyraVecData[i];
298  }
299  }
300  } else {
301  schurCompSmoo_->Apply(*xtilde2,*schurCompRHS);
302  }
303 
304  // 5) extract parts of solution vector X
305  Teuchos::RCP<MultiVector> x1 = domainMapExtractor_->ExtractVector(rcpX, 0);
306  Teuchos::RCP<MultiVector> x2 = domainMapExtractor_->ExtractVector(rcpX, 1);
307 
308  // 6) update solution vector with increments xhat1 and xhat2
309  // rescale increment for x2 with omega_
310  x1->update(omega,*xtilde1,one); // x1 = x1_old + omega xtilde1
311  x2->update(omega,*xtilde2,one); // x2 = x2_old + omega xtilde2
312 
313  // write back solution in global vector X
314  domainMapExtractor_->InsertVector(x1, 0, rcpX);
315  domainMapExtractor_->InsertVector(x2, 1, rcpX);
316  }
317  }
318 
319  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
322  return rcp( new UzawaSmoother(*this) );
323  }
324 
325  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
327  std::ostringstream out;
329  out << "{type = " << type_ << "}";
330  return out.str();
331  }
332 
333  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
336 
337  if (verbLevel & Parameters0) {
338  out0 << "Prec. type: " << type_ << /*" Sweeps: " << nSweeps_ << " damping: " << omega_ <<*/ std::endl;
339  }
340 
341  if (verbLevel & Debug) {
342  out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
343  }
344  }
345 
346 } // namespace MueLu
347 
348 
349 #endif /* MUELU_UZAWASMOOTHER_DEF_HPP_ */
Important warning messages (one line)
std::string description() const
Return a simple one-line description of this object.
Exception indicating invalid cast attempted.
void Setup(Level &currentLevel)
Setup routine.
bool IsSetup() const
Get the state of a smoother prototype.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Print additional debugging information.
void DeclareInput(Level &currentLevel) const
Input.
Namespace for MueLu classes and methods.
void SetVelocityPredictionFactoryManager(RCP< FactoryManager > FactManager)
RCP< const ParameterList > GetValidParameterList() const
Input.
virtual const RCP< const FactoryBase > GetFactory(const std::string &varName) const =0
Get.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
Block triangle Uzawa smoother for 2x2 block matrices.
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
virtual const Teuchos::ParameterList & GetParameterList() const
Print class parameters.
RCP< SmootherPrototype > Copy() const
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.
Scalar SC
void AddFactoryManager(RCP< const FactoryManagerBase > FactManager, int pos)
Add a factory manager at a specific position.
Exception throws to report errors in the internal logical of the program.
An exception safe way to call the method &#39;Level::SetFactoryManager()&#39;.
void Apply(MultiVector &X, MultiVector const &B, bool InitialGuessIsZero=false) const
Apply the Braess Sarazin smoother.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
virtual ~UzawaSmoother()
Destructor.
virtual std::string description() const
Return a simple one-line description of this object.
std::string toString(const T &t)