10 #ifndef MUELU_BRAESSSARAZINSMOOTHER_DEF_HPP_
11 #define MUELU_BRAESSSARAZINSMOOTHER_DEF_HPP_
13 #include <Teuchos_ArrayViewDecl.hpp>
20 #include <Xpetra_MultiVectorFactory.hpp>
26 #include "MueLu_Utilities.hpp"
28 #include "MueLu_HierarchyUtils.hpp"
31 #include "MueLu_FactoryManager.hpp"
35 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
38 FactManager_ = FactManager;
41 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
49 validParamList->
set<
bool>(
"lumping",
false,
50 "Use lumping to construct diag(A(0,0)), "
51 "i.e. use row sum of the abs values on the diagonal as approximation of A00 (and A00^{-1})");
52 validParamList->
set<
SC>(
"Damping factor", one,
"Damping/Scaling factor in BraessSarazin (usually has to be chosen > 1, default = 1.0)");
53 validParamList->
set<
LO>(
"Sweeps", 1,
"Number of BraessSarazin sweeps (default = 1)");
54 validParamList->
set<
bool>(
"q2q1 mode",
false,
"Run in the mode matching Q2Q1 matlab code");
56 return validParamList;
59 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
61 this->Input(currentLevel,
"A");
64 "MueLu::BraessSarazinSmoother::DeclareInput: FactManager_ must not be null! "
65 "Introduce a FactoryManager for the SchurComplement equation.");
72 currentLevel.
DeclareInput(
"PreSmoother", FactManager_->GetFactory(
"Smoother").get());
75 currentLevel.
DeclareInput(
"A", FactManager_->GetFactory(
"A").get());
79 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
84 this->GetOStream(
Warnings0) <<
"MueLu::BreaessSarazinSmoother::Setup(): Setup() has already been called";
87 A_ = Factory::Get<RCP<Matrix> >(currentLevel,
"A");
90 "MueLu::BraessSarazinSmoother::Setup: input matrix A is not of type BlockedCrsMatrix! error.");
93 rangeMapExtractor_ = bA->getRangeMapExtractor();
94 domainMapExtractor_ = bA->getDomainMapExtractor();
97 A00_ = bA->getMatrix(0, 0);
98 A01_ = bA->getMatrix(0, 1);
99 A10_ = bA->getMatrix(1, 0);
100 A11_ = bA->getMatrix(1, 1);
103 SC omega = pL.
get<
SC>(
"Damping factor");
107 RCP<Vector> diagFVector = VectorFactory::Build(A00_->getRowMap());
108 if (pL.
get<
bool>(
"lumping") ==
false) {
109 A00_->getLocalDiagCopy(*diagFVector);
113 diagFVector->scale(omega);
118 if (bD.
is_null() ==
false && bD->getBlockedMap()->getNumMaps() == 1) {
119 RCP<Vector> nestedVec = bD->getMultiVector(0, bD->getBlockedMap()->getThyraMode())->getVectorNonConst(0);
127 smoo_ = currentLevel.Get<
RCP<SmootherBase> >(
"PreSmoother", FactManager_->GetFactory(
"Smoother").get());
128 S_ = currentLevel.Get<
RCP<Matrix> >(
"A", FactManager_->GetFactory(
"A").get());
134 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
137 "MueLu::BraessSarazinSmoother::Apply(): Setup() has not been called");
143 bool bCopyResultX =
false;
144 bool bReorderX =
false;
145 bool bReorderB =
false;
155 if (rbA.is_null() ==
false) {
160 if (bX.is_null() ==
true) {
162 rcpX.
swap(vectorWithBlockedMap);
168 if (bB.is_null() ==
true) {
170 rcpB.
swap(vectorWithBlockedMap);
175 if (bX.is_null() ==
true) {
177 rcpX.
swap(vectorWithBlockedMap);
181 if (bB.is_null() ==
true) {
183 rcpB.
swap(vectorWithBlockedMap);
188 bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
189 bB = Teuchos::rcp_dynamic_cast<
const BlockedMultiVector>(rcpB);
192 if (rbA.is_null() ==
false) {
196 if (bX->getBlockedMap()->getNumMaps() != bA->getDomainMapExtractor()->NumMaps() || bReorderX) {
199 rcpX.
swap(reorderedBlockedVector);
202 if (bB->getBlockedMap()->getNumMaps() != bA->getRangeMapExtractor()->NumMaps() || bReorderB) {
205 rcpB.
swap(reorderedBlockedVector);
212 bool bRangeThyraMode = rangeMapExtractor_->getThyraMode();
213 bool bDomainThyraMode = domainMapExtractor_->getThyraMode();
215 RCP<MultiVector> deltaX = MultiVectorFactory::Build(rcpX->getMap(), rcpX->getNumVectors());
220 RCP<MultiVector> Rtmp = rangeMapExtractor_->getVector(1, rcpB->getNumVectors(), bRangeThyraMode);
223 SC one = STS::one(), zero = STS::zero();
227 LO nSweeps = pL.
get<
LO>(
"Sweeps");
230 if (InitialGuessIsZero) {
231 R = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
232 R->update(one, *rcpB, zero);
238 RCP<Vector> diagSVector = VectorFactory::Build(S_->getRowMap());
239 S_->getLocalDiagCopy(*diagSVector);
241 for (
LO run = 0; run < nSweeps; ++run) {
245 RCP<MultiVector> R0 = rangeMapExtractor_->ExtractVector(R, 0, bRangeThyraMode);
246 RCP<MultiVector> R1 = rangeMapExtractor_->ExtractVector(R, 1, bRangeThyraMode);
249 deltaX0->putScalar(zero);
250 deltaX0->elementWiseMultiply(one, *D_, *R0, zero);
251 A10_->apply(*deltaX0, *Rtmp);
252 Rtmp->update(one, *R1, -one);
254 if (!pL.
get<
bool>(
"q2q1 mode")) {
255 deltaX1->putScalar(zero);
258 if (Teuchos::rcp_dynamic_cast<BlockedVector>(diagSVector) == Teuchos::null) {
262 for (
GO row = 0; row < deltaX1data.
size(); row++)
263 deltaX1data[row] = Teuchos::as<SC>(1.1) * Rtmpdata[row] / Sdiag[row];
269 smoo_->Apply(*deltaX1, *Rtmp);
272 deltaX0->putScalar(zero);
273 A01_->apply(*deltaX1, *deltaX0);
274 deltaX0->update(one, *R0, -one);
276 deltaX0->elementWiseMultiply(one, *D_, *R0, zero);
278 RCP<MultiVector> X0 = domainMapExtractor_->ExtractVector(rcpX, 0, bDomainThyraMode);
279 RCP<MultiVector> X1 = domainMapExtractor_->ExtractVector(rcpX, 1, bDomainThyraMode);
282 X0->update(one, *deltaX0, one);
283 X1->update(one, *deltaX1, one);
285 domainMapExtractor_->InsertVector(X0, 0, rcpX, bDomainThyraMode);
286 domainMapExtractor_->InsertVector(X1, 1, rcpX, bDomainThyraMode);
288 if (run < nSweeps - 1) {
293 if (bCopyResultX ==
true) {
295 X.update(one, *Xmerged, zero);
299 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
305 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
308 std::ostringstream out;
310 out <<
"{type = " << type_ <<
"}";
314 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
319 out0 <<
"Prec. type: " << type_ << std::endl;
322 if (verbLevel &
Debug) {
327 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
Important warning messages (one line)
virtual const Teuchos::ParameterList & GetParameterList() const
Exception indicating invalid cast attempted.
BraessSarazin smoother for 2x2 block matrices.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
T & get(const std::string &name, T def_value)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void swap(RCP< T > &r_ptr)
Print additional debugging information.
RCP< SmootherPrototype > Copy() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void DeclareInput(Level ¤tLevel) const
Input.
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Class that holds all level-specific information.
bool IsSetup() const
Get the state of a smoother prototype.
RCP< const ParameterList > GetValidParameterList() const
Input.
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
void AddFactoryManager(RCP< const FactoryManagerBase > FactManager, int pos=0)
Add a factory manager for BraessSarazin internal SchurComplement handling.
void Setup(Level ¤tLevel)
Setup routine.
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
Apply the Braess Sarazin smoother.
Exception throws to report errors in the internal logical of the program.
#define MUELU_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
An exception safe way to call the method 'Level::SetFactoryManager()'.
Teuchos::RCP< const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > buildReorderedBlockedMultiVector(Teuchos::RCP< const Xpetra::BlockReorderManager > brm, Teuchos::RCP< const Xpetra::BlockedMultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > bvec)
static Teuchos::RCP< Vector > GetInverse(Teuchos::RCP< const Vector > v, Magnitude tol=Teuchos::ScalarTraits< Scalar >::eps()*100, Scalar valReplacement=Teuchos::ScalarTraits< Scalar >::zero())
Return vector containing inverse of input vector.
std::string description() const
Return a simple one-line description of this object.
static Teuchos::RCP< Vector > GetLumpedMatrixDiagonal(Matrix const &A, const bool doReciprocal=false, Magnitude tol=Teuchos::ScalarTraits< Scalar >::magnitude(Teuchos::ScalarTraits< Scalar >::zero()), Scalar valReplacement=Teuchos::ScalarTraits< Scalar >::zero(), const bool replaceSingleEntryRowWithZero=false, const bool useAverageAbsDiagVal=false)
Extract Matrix Diagonal of lumped matrix.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
virtual std::string description() const
Return a simple one-line description of this object.
std::string toString(const T &t)