MueLu Version of the Day
Loading...
Searching...
No Matches
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#ifndef MUELU_UZAWASMOOTHER_DEF_HPP_
48#define MUELU_UZAWASMOOTHER_DEF_HPP_
49
50#include <Teuchos_ArrayViewDecl.hpp>
51#include <Teuchos_ScalarTraits.hpp>
52
53#include "MueLu_ConfigDefs.hpp"
54
55#include <Xpetra_Matrix.hpp>
56#include <Xpetra_BlockedCrsMatrix.hpp>
57#include <Xpetra_MultiVectorFactory.hpp>
58#include <Xpetra_VectorFactory.hpp>
59#include <Xpetra_ReorderedBlockedCrsMatrix.hpp>
60
62#include "MueLu_Level.hpp"
63#include "MueLu_Monitor.hpp"
64#include "MueLu_HierarchyUtils.hpp"
66
67#include "MueLu_FactoryManager.hpp"
68
69namespace MueLu {
70
71 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
73 RCP<ParameterList> validParamList = rcp(new ParameterList());
74
75 validParamList->set<RCP<const FactoryBase>>("A", Teuchos::null, "Generating factory of the matrix A");
76 validParamList->set<Scalar> ("Damping factor", 1.0, "Damping/Scaling factor in SIMPLE");
77 validParamList->set<LocalOrdinal>("Sweeps", 1, "Number of SIMPLE sweeps (default = 1)");
78
79 return validParamList;
80 }
81
82 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
83 void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::AddFactoryManager(RCP<const FactoryManagerBase> FactManager, int pos) {
84 TEUCHOS_TEST_FOR_EXCEPTION(pos < 0, Exceptions::RuntimeError, "MueLu::UzawaSmoother::AddFactoryManager: parameter \'pos\' must not be negative! error.");
85
86 size_t myPos = Teuchos::as<size_t>(pos);
87
88 if (myPos < FactManager_.size()) {
89 // replace existing entris in FactManager_ vector
90 FactManager_.at(myPos) = FactManager;
91 } else if( myPos == FactManager_.size()) {
92 // add new Factory manager in the end of the vector
93 FactManager_.push_back(FactManager);
94 } else { // if(myPos > FactManager_.size())
95 RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
96 *out << "Warning: cannot add new FactoryManager at proper position " << pos << ". The FactoryManager is just appended to the end. Check this!" << std::endl;
97
98 // add new Factory manager in the end of the vector
99 FactManager_.push_back(FactManager);
100 }
101
102 }
103
104
105 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
107 AddFactoryManager(FactManager, 0); // overwrite factory manager for predicting the primary variable
108 }
109
110 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
112 AddFactoryManager(FactManager, 1); // overwrite factory manager for SchurComplement
113 }
114
115 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
117 currentLevel.DeclareInput("A",this->GetFactory("A").get());
118
119 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!");
120
121 // loop over all factory managers for the subblocks of blocked operator A
122 std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
123 for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
124 SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
125
126 // request "Smoother" for current subblock row.
127 currentLevel.DeclareInput("PreSmoother",(*it)->GetFactory("Smoother").get());
128 }
129 }
130
131 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
133
134 FactoryMonitor m(*this, "Setup blocked Uzawa Smoother", currentLevel);
135
136 if (SmootherPrototype::IsSetup() == true)
137 this->GetOStream(Warnings0) << "MueLu::UzawaSmoother::Setup(): Setup() has already been called";
138
139 // extract blocked operator A from current level
140 A_ = Factory::Get<RCP<Matrix> > (currentLevel, "A");
141
142 RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
143 TEUCHOS_TEST_FOR_EXCEPTION(bA == Teuchos::null, Exceptions::BadCast, "MueLu::UzawaSmoother::Setup: input matrix A is not of type BlockedCrsMatrix! error.");
144
145 // store map extractors
146 rangeMapExtractor_ = bA->getRangeMapExtractor();
147 domainMapExtractor_ = bA->getDomainMapExtractor();
148
149 // Store the blocks in local member variables
150 F_ = bA->getMatrix(0, 0);
151 G_ = bA->getMatrix(0, 1);
152 D_ = bA->getMatrix(1, 0);
153 Z_ = bA->getMatrix(1, 1);
154
155 // Set the Smoother
156 // carefully switch to the SubFactoryManagers (defined by the users)
157 {
158 RCP<const FactoryManagerBase> velpredictFactManager = FactManager_.at(0);
159 SetFactoryManager currentSFM (rcpFromRef(currentLevel), velpredictFactManager);
160 velPredictSmoo_ = currentLevel.Get< RCP<SmootherBase> >("PreSmoother",velpredictFactManager->GetFactory("Smoother").get());
161 }
162 {
163 RCP<const FactoryManagerBase> schurFactManager = FactManager_.at(1);
164 SetFactoryManager currentSFM (rcpFromRef(currentLevel), schurFactManager);
165 schurCompSmoo_ = currentLevel.Get< RCP<SmootherBase> >("PreSmoother", schurFactManager->GetFactory("Smoother").get());
166 }
167
169 }
170
171 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
172 void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool /* InitialGuessIsZero */) const
173 {
174 TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::UzawaSmoother::Apply(): Setup() has not been called");
175
176 Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout));
177
178 SC zero = Teuchos::ScalarTraits<SC>::zero(), one = Teuchos::ScalarTraits<SC>::one();
179
180 bool bRangeThyraMode = rangeMapExtractor_->getThyraMode();
181 bool bDomainThyraMode = domainMapExtractor_->getThyraMode();
182
183 // extract parameters from internal parameter list
184 const ParameterList & pL = Factory::GetParameterList();
185 LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
186 Scalar omega = pL.get<Scalar>("Damping factor");
187
188 // wrap current solution vector in RCP
189 RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X);
190 RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
191
192 // make sure that both rcpX and rcpB are BlockedMultiVector objects
193 bool bCopyResultX = false;
194 bool bReorderX = false;
195 bool bReorderB = false;
196 RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
197 MUELU_TEST_FOR_EXCEPTION(bA.is_null() == true, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): A_ must be a BlockedCrsMatrix");
198 RCP<BlockedMultiVector> bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
199 RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
200
201 // check the type of operator
202 RCP<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rbA =
203 Teuchos::rcp_dynamic_cast<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(bA);
204
205 if(rbA.is_null() == false) {
206 // A is a ReorderedBlockedCrsMatrix and thus uses nested maps, retrieve BlockedCrsMatrix and use plain blocked
207 // map for the construction of the blocked multivectors
208
209 // check type of X vector
210 if (bX.is_null() == true) {
211 RCP<MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(rbA->getBlockedCrsMatrix()->getBlockedDomainMap(), rcpX));
212 rcpX.swap(vectorWithBlockedMap);
213 bCopyResultX = true;
214 bReorderX = true;
215 }
216
217 // check type of B vector
218 if (bB.is_null() == true) {
219 RCP<const MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(rbA->getBlockedCrsMatrix()->getBlockedRangeMap(), rcpB));
220 rcpB.swap(vectorWithBlockedMap);
221 bReorderB = true;
222 }
223 }
224 else {
225 // A is a BlockedCrsMatrix and uses a plain blocked map
226 if (bX.is_null() == true) {
227 RCP<MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedDomainMap(), rcpX));
228 rcpX.swap(vectorWithBlockedMap);
229 bCopyResultX = true;
230 }
231
232 if(bB.is_null() == true) {
233 RCP<const MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedRangeMap(),rcpB));
234 rcpB.swap(vectorWithBlockedMap);
235 }
236 }
237
238 // we now can guarantee that X and B are blocked multi vectors
239 bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
240 bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
241
242 // Finally we can do a reordering of the blocked multivectors if A is a ReorderedBlockedCrsMatrix
243 if(rbA.is_null() == false) {
244
245 Teuchos::RCP<const Xpetra::BlockReorderManager > brm = rbA->getBlockReorderManager();
246
247 // check type of X vector
248 if(bX->getBlockedMap()->getNumMaps() != bA->getDomainMapExtractor()->NumMaps() || bReorderX) {
249 // X is a blocked multi vector but incompatible to the reordered blocked operator A
250 Teuchos::RCP<MultiVector> reorderedBlockedVector = buildReorderedBlockedMultiVector(brm, bX);
251 rcpX.swap(reorderedBlockedVector);
252 }
253
254 if(bB->getBlockedMap()->getNumMaps() != bA->getRangeMapExtractor()->NumMaps() || bReorderB) {
255 // B is a blocked multi vector but incompatible to the reordered blocked operator A
256 Teuchos::RCP<const MultiVector> reorderedBlockedVector = buildReorderedBlockedMultiVector(brm, bB);
257 rcpB.swap(reorderedBlockedVector);
258 }
259 }
260
261 // Throughout the rest of the algorithm rcpX and rcpB are used for solution vector and RHS
262
263 // create residual vector
264 // contains current residual of current solution X with rhs B
265 RCP<MultiVector> residual = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
266 RCP<BlockedMultiVector> bresidual = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(residual);
267 Teuchos::RCP<MultiVector> r1 = bresidual->getMultiVector(0,bRangeThyraMode);
268 Teuchos::RCP<MultiVector> r2 = bresidual->getMultiVector(1,bRangeThyraMode);
269
270 // helper vector 1
271 RCP<MultiVector> xtilde = MultiVectorFactory::Build(rcpX->getMap(), rcpX->getNumVectors());
272 RCP<BlockedMultiVector> bxtilde = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(xtilde);
273 RCP<MultiVector> xtilde1 = bxtilde->getMultiVector(0,bDomainThyraMode);
274 RCP<MultiVector> xtilde2 = bxtilde->getMultiVector(1,bDomainThyraMode);
275
276 // incrementally improve solution vector X
277 for (LocalOrdinal run = 0; run < nSweeps; ++run) {
278 // 1) calculate current residual
279 residual->update(one,*rcpB,zero); // residual = B
280 A_->apply(*rcpX, *residual, Teuchos::NO_TRANS, -one, one);
281
282 // 2) solve F * \Delta \tilde{x}_1 = r_1
283 // start with zero guess \Delta \tilde{x}_1
284 bxtilde->putScalar(zero);
285 velPredictSmoo_->Apply(*xtilde1,*r1);
286
287 // 3) calculate rhs for SchurComp equation
288 // r_2 - D \Delta \tilde{x}_1
289 RCP<MultiVector> schurCompRHS = MultiVectorFactory::Build(r2->getMap(),rcpB->getNumVectors());
290 D_->apply(*xtilde1,*schurCompRHS);
291 schurCompRHS->update(one,*r2,-one);
292
293 // 4) solve SchurComp equation
294 // start with zero guess \Delta \tilde{x}_2
295 schurCompSmoo_->Apply(*xtilde2,*schurCompRHS);
296
297 rcpX->update(omega,*bxtilde,one);
298 }
299
300 if (bCopyResultX == true) {
301 RCP<MultiVector> Xmerged = bX->Merge();
302 X.update(one, *Xmerged, zero);
303 }
304 }
305
306 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
307 RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
311
312 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
314 std::ostringstream out;
316 out << "{type = " << type_ << "}";
317 return out.str();
318 }
319
320 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
321 void UzawaSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream &out, const VerbLevel verbLevel) const {
323
324 if (verbLevel & Parameters0) {
325 out0 << "Prec. type: " << type_ << /*" Sweeps: " << nSweeps_ << " damping: " << omega_ <<*/ std::endl;
326 }
327
328 if (verbLevel & Debug) {
329 out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
330 }
331 }
332
333 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
335 // FIXME: This is a placeholder
336 return Teuchos::OrdinalTraits<size_t>::invalid();
337 }
338
339} // namespace MueLu
340
341
342#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.
T Get(Level &level, const std::string &varName) const
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Default implementation of FactoryAcceptor::GetFactory().
Class that holds all level-specific information.
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 =0
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< Matrix > A_
block operator
RCP< SmootherPrototype > Copy() const
void Setup(Level &currentLevel)
Setup routine.
std::vector< Teuchos::RCP< const FactoryManagerBase > > FactManager_
Vector of internal factory managers.
RCP< const ParameterList > GetValidParameterList() const
Input.
Teuchos::RCP< Matrix > D_
divergence operator
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.
Teuchos::RCP< Matrix > Z_
pressure stabilization term or null block
std::string description() const
Return a simple one-line description of this object.
Teuchos::RCP< SmootherBase > velPredictSmoo_
smoother for velocity prediction
void SetSchurCompFactoryManager(RCP< FactoryManager > FactManager)
Set factory manager for internal SchurComplement handling.
Teuchos::RCP< SmootherBase > schurCompSmoo_
smoother for SchurComplement equation
std::string type_
smoother type
RCP< const MapExtractorClass > domainMapExtractor_
domain map extractor (from A_ generated by AFact)
Teuchos::RCP< Matrix > G_
pressure gradient operator
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.
void SetVelocityPredictionFactoryManager(RCP< FactoryManager > FactManager)
Set factory manager for internal velocity prediction.
Teuchos::RCP< Matrix > F_
fluid operator
RCP< const MapExtractorClass > rangeMapExtractor_
range map extractor (from A_ generated by AFact)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line).
@ Debug
Print additional debugging information.
@ Parameters0
Print class parameters.