MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_BlockedGaussSeidelSmoother_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_BLOCKEDGAUSSSEIDELSMOOTHER_DEF_HPP_
48#define MUELU_BLOCKEDGAUSSSEIDELSMOOTHER_DEF_HPP_
49
50#include "Teuchos_ArrayViewDecl.hpp"
51#include "Teuchos_ScalarTraits.hpp"
52
53#include "MueLu_ConfigDefs.hpp"
54
55#include <Xpetra_BlockReorderManager.hpp>
56#include <Xpetra_Matrix.hpp>
57#include <Xpetra_BlockedCrsMatrix.hpp>
58#include <Xpetra_ReorderedBlockedCrsMatrix.hpp>
59#include <Xpetra_ReorderedBlockedMultiVector.hpp>
60#include <Xpetra_MultiVectorFactory.hpp>
61
63#include "MueLu_Level.hpp"
64#include "MueLu_Monitor.hpp"
65#include "MueLu_HierarchyUtils.hpp"
67
68namespace MueLu {
69
70 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
72 : type_("blocked GaussSeidel"), A_(Teuchos::null)
73 {
74 FactManager_.reserve(10); // TODO fix me!
75 }
76
77 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
79
80 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
82 RCP<ParameterList> validParamList = rcp(new ParameterList());
83
84 validParamList->set< RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
85 validParamList->set< Scalar > ("Damping factor", 1.0, "Damping/Scaling factor in BGS");
86 validParamList->set< LocalOrdinal > ("Sweeps", 1, "Number of BGS sweeps (default = 1)");
87
88 return validParamList;
89 }
90
91 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
93 TEUCHOS_TEST_FOR_EXCEPTION(pos < 0, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::AddFactoryManager: parameter \'pos\' must not be negative! error.");
94
95 size_t myPos = Teuchos::as<size_t>(pos);
96
97 if (myPos < FactManager_.size()) {
98 // replace existing entries in FactManager_ vector
99 FactManager_.at(myPos) = FactManager;
100 } else if(myPos == FactManager_.size()) {
101 // append new Factory manager at the end of the vector
102 FactManager_.push_back(FactManager);
103 } else { // if(myPos > FactManager_.size())
104 RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
105 *out << "Warning: cannot add new FactoryManager at proper position " << pos << ". The FactoryManager is just appended to the end. Check this!" << std::endl;
106
107 // add new Factory manager in the end of the vector
108 FactManager_.push_back(FactManager);
109 }
110 }
111
112 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
114 //this->Input(currentLevel, "A");
115 // TODO: check me: why is this->Input not freeing properly A in release mode?
116 currentLevel.DeclareInput("A",this->GetFactory("A").get());
117
118 // loop over all factory managers for the subblocks of blocked operator A
119 std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
120 for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
121 SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
122
123 // request "Smoother" for current subblock row.
124 currentLevel.DeclareInput("PreSmoother",(*it)->GetFactory("Smoother").get());
125
126 // request "A" for current subblock row (only needed for Thyra mode)
127 currentLevel.DeclareInput("A",(*it)->GetFactory("A").get());
128 }
129 }
130
131 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
133
134 RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
135
136 FactoryMonitor m(*this, "Setup blocked Gauss-Seidel Smoother", currentLevel);
137 if (SmootherPrototype::IsSetup() == true) this->GetOStream(Warnings0) << "MueLu::BlockedGaussSeidelSmoother::Setup(): Setup() has already been called";
138
139 // extract blocked operator A from current level
140 A_ = Factory::Get< RCP<Matrix> >(currentLevel, "A"); // A needed for extracting map extractors
141 RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
142 TEUCHOS_TEST_FOR_EXCEPTION(bA==Teuchos::null, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: input matrix A is not of type BlockedCrsMatrix! error.");
143
144 // plausibility check
145 TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Setup: number of block rows of A is " << bA->Rows() << " and does not match number of SubFactoryManagers " << FactManager_.size() << ". error.");
146 TEUCHOS_TEST_FOR_EXCEPTION(bA->Cols() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Setup: number of block cols of A is " << bA->Cols() << " and does not match number of SubFactoryManagers " << FactManager_.size() << ". error.");
147
148 // store map extractors
149 rangeMapExtractor_ = bA->getRangeMapExtractor();
150 domainMapExtractor_ = bA->getDomainMapExtractor();
151
152 // loop over all factory managers for the subblocks of blocked operator A
153 std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
154 for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
155 SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
156
157 // extract Smoother for current block row (BGS ordering)
158 RCP<const SmootherBase> Smoo = currentLevel.Get< RCP<SmootherBase> >("PreSmoother",(*it)->GetFactory("Smoother").get());
159 Inverse_.push_back(Smoo);
160
161 // store whether subblock matrix is blocked or not!
162 RCP<Matrix> Aii = currentLevel.Get< RCP<Matrix> >("A",(*it)->GetFactory("A").get());
163 bIsBlockedOperator_.push_back(Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Aii)!=Teuchos::null);
164 }
165
167 }
168
169 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
170 void BlockedGaussSeidelSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector &X, const MultiVector& B, bool InitialGuessIsZero) const
171 {
172 TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): Setup() has not been called");
173
174#if 0 // def HAVE_MUELU_DEBUG
175 // TODO simplify this debug check
176 RCP<MultiVector> rcpDebugX = Teuchos::rcpFromRef(X);
177 RCP<const MultiVector> rcpDebugB = Teuchos::rcpFromRef(B);
178 RCP<BlockedMultiVector> rcpBDebugX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpDebugX);
179 RCP<const BlockedMultiVector> rcpBDebugB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpDebugB);
180 //RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
181 if(rcpBDebugB.is_null() == false) {
182 //this->GetOStream(Runtime1) << "BlockedGaussSeidel: B is a BlockedMultiVector of size " << B.getMap()->getGlobalNumElements() << " with " << rcpBDebugB->getBlockedMap()->getNumMaps() << " blocks." << std::endl;
183 //TEUCHOS_TEST_FOR_EXCEPTION(A_->getRangeMap()->isSameAs(*(B.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): The map of RHS vector B is not the same as range map of the blocked operator A. Please check the map of B and A.");
184 } else {
185 //this->GetOStream(Runtime1) << "BlockedGaussSeidel: B is a MultiVector of size " << B.getMap()->getGlobalNumElements() << std::endl;
186 //TEUCHOS_TEST_FOR_EXCEPTION(bA->getFullRangeMap()->isSameAs(*(B.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): The map of RHS vector B is not the same as range map of the blocked operator A. Please check the map of B and A.");
187 }
188 if(rcpBDebugX.is_null() == false) {
189 //this->GetOStream(Runtime1) << "BlockedGaussSeidel: X is a BlockedMultiVector of size " << X.getMap()->getGlobalNumElements() << " with " << rcpBDebugX->getBlockedMap()->getNumMaps() << " blocks." << std::endl;
190 //TEUCHOS_TEST_FOR_EXCEPTION(A_->getDomainMap()->isSameAs(*(X.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): The map of the solution vector X is not the same as domain map of the blocked operator A. Please check the map of X and A.");
191 } else {
192 //this->GetOStream(Runtime1) << "BlockedGaussSeidel: X is a MultiVector of size " << X.getMap()->getGlobalNumElements() << std::endl;
193 //TEUCHOS_TEST_FOR_EXCEPTION(bA->getFullDomainMap()->isSameAs(*(X.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): The map of the solution vector X is not the same as domain map of the blocked operator A. Please check the map of X and A.");
194 }
195#endif
196 SC zero = Teuchos::ScalarTraits<SC>::zero(), one = Teuchos::ScalarTraits<SC>::one();
197
198 // Input variables used for the rest of the algorithm
199 RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X);
200 RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
201
202 // make sure that both rcpX and rcpB are BlockedMultiVector objects
203 bool bCopyResultX = false;
204 bool bReorderX = false;
205 bool bReorderB = false;
206 RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
207 MUELU_TEST_FOR_EXCEPTION(bA.is_null() == true, Exceptions::RuntimeError, "MueLu::BlockedGaussSeidelSmoother::Apply(): A_ must be a BlockedCrsMatrix");
208 RCP<BlockedMultiVector> bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
209 RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
210
211 // check the type of operator
212 RCP<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rbA =
213 Teuchos::rcp_dynamic_cast<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(bA);
214
215 if(rbA.is_null() == false) {
216 // A is a ReorderedBlockedCrsMatrix and thus uses nested maps, retrieve BlockedCrsMatrix and use plain blocked
217 // map for the construction of the blocked multivectors
218
219 // check type of X vector
220 if (bX.is_null() == true) {
221 RCP<MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(rbA->getBlockedCrsMatrix()->getBlockedDomainMap(), rcpX));
222 rcpX.swap(vectorWithBlockedMap);
223 bCopyResultX = true;
224 bReorderX = true;
225 }
226
227 // check type of B vector
228 if (bB.is_null() == true) {
229 RCP<const MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(rbA->getBlockedCrsMatrix()->getBlockedRangeMap(), rcpB));
230 rcpB.swap(vectorWithBlockedMap);
231 bReorderB = true;
232 }
233 }
234 else {
235 // A is a BlockedCrsMatrix and uses a plain blocked map
236 if (bX.is_null() == true) {
237 RCP<MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedDomainMap(), rcpX));
238 rcpX.swap(vectorWithBlockedMap);
239 bCopyResultX = true;
240 }
241
242 if(bB.is_null() == true) {
243 RCP<const MultiVector> vectorWithBlockedMap = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedRangeMap(),rcpB));
244 rcpB.swap(vectorWithBlockedMap);
245 }
246 }
247
248 // we now can guarantee that X and B are blocked multi vectors
249 bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
250 bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
251
252 // Finally we can do a reordering of the blocked multivectors if A is a ReorderedBlockedCrsMatrix
253 if(rbA.is_null() == false) {
254
255 Teuchos::RCP<const Xpetra::BlockReorderManager > brm = rbA->getBlockReorderManager();
256
257 // check type of X vector
258 if(bX->getBlockedMap()->getNumMaps() != bA->getDomainMapExtractor()->NumMaps() || bReorderX) {
259 // X is a blocked multi vector but incompatible to the reordered blocked operator A
260 Teuchos::RCP<MultiVector> reorderedBlockedVector = buildReorderedBlockedMultiVector(brm, bX);
261 rcpX.swap(reorderedBlockedVector);
262 }
263
264 if(bB->getBlockedMap()->getNumMaps() != bA->getRangeMapExtractor()->NumMaps() || bReorderB) {
265 // B is a blocked multi vector but incompatible to the reordered blocked operator A
266 Teuchos::RCP<const MultiVector> reorderedBlockedVector = buildReorderedBlockedMultiVector(brm, bB);
267 rcpB.swap(reorderedBlockedVector);
268 }
269 }
270
271 // Throughout the rest of the algorithm rcpX and rcpB are used for solution vector and RHS
272
273 RCP<MultiVector> residual = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
274 RCP<MultiVector> tempres = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
275
276 // extract parameters from internal parameter list
277 const ParameterList & pL = Factory::GetParameterList();
278 LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
279 Scalar omega = pL.get<Scalar>("Damping factor");
280
281
282 // Clear solution from previos V cycles in case it is still stored
283 if( InitialGuessIsZero==true )
284 rcpX->putScalar(Teuchos::ScalarTraits<Scalar>::zero());
285
286
287 // outer Richardson loop
288 for (LocalOrdinal run = 0; run < nSweeps; ++run) {
289 // one BGS sweep
290 // loop over all block rows
291 for(size_t i = 0; i<Inverse_.size(); i++) {
292
293 // calculate block residual r = B-A*X
294 // note: A_ is the full blocked operator
295 residual->update(1.0,*rcpB,0.0); // r = B
296 if(InitialGuessIsZero == false || i > 0 || run > 0)
297 bA->bgs_apply(*rcpX, *residual, i, Teuchos::NO_TRANS, -1.0, 1.0);
298
299 // extract corresponding subvectors from X and residual
300 bool bRangeThyraMode = rangeMapExtractor_->getThyraMode();
301 bool bDomainThyraMode = domainMapExtractor_->getThyraMode();
302 Teuchos::RCP<MultiVector> Xi = domainMapExtractor_->ExtractVector(rcpX, i, bDomainThyraMode);
303 Teuchos::RCP<MultiVector> ri = rangeMapExtractor_->ExtractVector(residual, i, bRangeThyraMode);
304 Teuchos::RCP<MultiVector> tXi = domainMapExtractor_->getVector(i, X.getNumVectors(), bDomainThyraMode);
305
306 // apply solver/smoother
307 Inverse_.at(i)->Apply(*tXi, *ri, false);
308
309 // update vector
310 Xi->update(omega,*tXi,1.0); // X_{i+1} = X_i + omega \Delta X_i
311
312 }
313 }
314
315 if (bCopyResultX == true) {
316 RCP<MultiVector> Xmerged = bX->Merge();
317 X.update(one, *Xmerged, zero);
318 }
319 }
320
321 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
322 RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> > BlockedGaussSeidelSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Copy() const {
323 return rcp( new BlockedGaussSeidelSmoother(*this) );
324 }
325
326 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
328 std::ostringstream out;
330 out << "{type = " << type_ << "}";
331 return out.str();
332 }
333
334 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
335 void BlockedGaussSeidelSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream &out, const VerbLevel verbLevel) const {
337
338 // extract parameters from internal parameter list
339 const ParameterList & pL = Factory::GetParameterList();
340 LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
341 Scalar omega = pL.get<Scalar>("Damping factor");
342
343 if (verbLevel & Parameters0) {
344 out0 << "Prec. type: " << type_ << " Sweeps: " << nSweeps << " damping: " << omega << std::endl;
345 }
346
347 if (verbLevel & Debug) {
348 out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
349 }
350 }
351 template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
353 // FIXME: This is a placeholder
354 return Teuchos::OrdinalTraits<size_t>::invalid();
355 }
356
357} // namespace MueLu
358
359#endif /* MUELU_BLOCKEDGAUSSSEIDELSMOOTHER_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
void DeclareInput(Level &currentLevel) const
Input.
std::vector< Teuchos::RCP< const FactoryManagerBase > > FactManager_
vector of factory managers
std::vector< Teuchos::RCP< const SmootherBase > > Inverse_
vector of smoother/solver factories
RCP< const MapExtractorClass > domainMapExtractor_
domain map extractor (from A_ generated by AFact)
std::string description() const
Return a simple one-line description of this object.
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
void AddFactoryManager(RCP< const FactoryManagerBase > FactManager, int pos)
Add a factory manager.
RCP< const ParameterList > GetValidParameterList() const
Input.
RCP< const MapExtractorClass > rangeMapExtractor_
range map extractor (from A_ generated by AFact)
std::vector< bool > bIsBlockedOperator_
vector storing whether sub-block is a blocked operator (needed for nested blocked smoothers using Thy...
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
Apply the direct solver. Solves the linear system AX=B using the constructed solver.
RCP< Matrix > A_
internal blocked operator "A" generated by AFact_
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level verbLevel to an FancyOStream object out.
void Setup(Level &currentLevel)
Setup routine In the Setup method the Inverse_ vector is filled with the corresponding SmootherBase o...
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.
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.