-
Notifications
You must be signed in to change notification settings - Fork 0
[Mirror] MueLu: Correct TekoSmoother::Apply when InitialGuessIsZero is false #98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
6dce540
3097d02
30697c6
d9e28c6
5a844a4
c981eae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -174,7 +174,7 @@ class TekoSmoother<double, int, GlobalOrdinal, Node> : public SmootherPrototype< | |||||
| RCP<const ParameterList> GetValidParameterList() const { | ||||||
| RCP<ParameterList> validParamList = rcp(new ParameterList()); | ||||||
|
|
||||||
| validParamList->set<RCP<const FactoryBase> >("A", null, "Generating factory of the matrix A"); | ||||||
| validParamList->set<RCP<const FactoryBase>>("A", null, "Generating factory of the matrix A"); | ||||||
| validParamList->set<std::string>("Inverse Type", "", "Name of parameter list within 'Teko parameters' containing the Teko smoother parameters."); | ||||||
|
|
||||||
| return validParamList; | ||||||
|
|
@@ -200,7 +200,7 @@ class TekoSmoother<double, int, GlobalOrdinal, Node> : public SmootherPrototype< | |||||
| this->GetOStream(Warnings0) << "MueLu::TekoSmoother::Setup(): Setup() has already been called"; | ||||||
|
|
||||||
| // extract blocked operator A from current level | ||||||
| A_ = Factory::Get<RCP<Matrix> >(currentLevel, "A"); // A needed for extracting map extractors | ||||||
| A_ = Factory::Get<RCP<Matrix>>(currentLevel, "A"); // A needed for extracting map extractors | ||||||
| bA_ = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_); | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(bA_.is_null(), Exceptions::BadCast, | ||||||
| "MueLu::TekoSmoother::Build: input matrix A is not of type BlockedCrsMatrix."); | ||||||
|
|
@@ -209,7 +209,7 @@ class TekoSmoother<double, int, GlobalOrdinal, Node> : public SmootherPrototype< | |||||
| TEUCHOS_TEST_FOR_EXCEPTION(bThyOp_.is_null(), Exceptions::BadCast, | ||||||
| "MueLu::TekoSmoother::Build: Could not extract thyra operator from BlockedCrsMatrix."); | ||||||
|
|
||||||
| Teuchos::RCP<const Thyra::LinearOpBase<Scalar> > thyOp = Teuchos::rcp_dynamic_cast<const Thyra::LinearOpBase<Scalar> >(bThyOp_); | ||||||
| Teuchos::RCP<const Thyra::LinearOpBase<Scalar>> thyOp = Teuchos::rcp_dynamic_cast<const Thyra::LinearOpBase<Scalar>>(bThyOp_); | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(thyOp.is_null(), Exceptions::BadCast, | ||||||
| "MueLu::TekoSmoother::Build: Downcast of Thyra::BlockedLinearOpBase to Teko::LinearOp failed."); | ||||||
|
|
||||||
|
|
@@ -237,51 +237,64 @@ class TekoSmoother<double, int, GlobalOrdinal, Node> : public SmootherPrototype< | |||||
|
|
||||||
| @param X initial guess | ||||||
| @param B right-hand side | ||||||
| @param InitialGuessIsZero This option has no effect. | ||||||
| @param InitialGuessIsZero whether the initial guess is zero | ||||||
| */ | ||||||
| void Apply(MultiVector &X, const MultiVector &B, bool /* InitialGuessIsZero */ = false) const { | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(this->IsSetup() == false, Exceptions::RuntimeError, | ||||||
| void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero = false) const { | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(!this->IsSetup(), Exceptions::RuntimeError, | ||||||
| "MueLu::TekoSmoother::Apply(): Setup() has not been called"); | ||||||
|
|
||||||
| Teuchos::RCP<const Teuchos::Comm<int> > comm = X.getMap()->getComm(); | ||||||
|
|
||||||
| Teuchos::RCP<const MapExtractor> rgMapExtractor = bA_->getRangeMapExtractor(); | ||||||
| auto comm = X.getMap()->getComm(); | ||||||
| auto rgMapExtractor = bA_->getRangeMapExtractor(); | ||||||
| TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(rgMapExtractor)); | ||||||
|
|
||||||
| // copy initial solution vector X to Ptr<Thyra::MultiVectorBase> YY | ||||||
|
|
||||||
| // create a Thyra RHS vector | ||||||
| Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > thyB = Thyra::createMembers(Teuchos::rcp_dynamic_cast<const Thyra::VectorSpaceBase<Scalar> >(bThyOp_->productRange()), Teuchos::as<int>(B.getNumVectors())); | ||||||
| Teuchos::RCP<Thyra::ProductMultiVectorBase<Scalar> > thyProdB = | ||||||
| Teuchos::rcp_dynamic_cast<Thyra::ProductMultiVectorBase<Scalar> >(thyB); | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(thyProdB.is_null(), Exceptions::BadCast, | ||||||
| "MueLu::TekoSmoother::Apply: Failed to cast range space to product range space."); | ||||||
|
|
||||||
| // copy RHS vector B to Thyra::MultiVectorBase thyProdB | ||||||
| Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::updateThyra(Teuchos::rcpFromRef(B), rgMapExtractor, thyProdB); | ||||||
|
|
||||||
| // create a Thyra SOL vector | ||||||
| Teuchos::RCP<Thyra::MultiVectorBase<Scalar> > thyX = Thyra::createMembers(Teuchos::rcp_dynamic_cast<const Thyra::VectorSpaceBase<Scalar> >(bThyOp_->productDomain()), Teuchos::as<int>(X.getNumVectors())); | ||||||
| Teuchos::RCP<Thyra::ProductMultiVectorBase<Scalar> > thyProdX = | ||||||
| Teuchos::rcp_dynamic_cast<Thyra::ProductMultiVectorBase<Scalar> >(thyX); | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(thyProdX.is_null(), Exceptions::BadCast, | ||||||
| "MueLu::TekoSmoother::Apply: Failed to cast domain space to product domain space."); | ||||||
|
|
||||||
| // copy RHS vector X to Thyra::MultiVectorBase thyProdX | ||||||
| Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::updateThyra(Teuchos::rcpFromRef(X), rgMapExtractor, thyProdX); | ||||||
|
|
||||||
| inverseOp_->apply( | ||||||
| Thyra::NOTRANS, | ||||||
| *thyB, // const MultiVectorBase<Scalar> &X, | ||||||
| thyX.ptr(), // const Ptr<MultiVectorBase<Scalar> > &Y, | ||||||
| 1.0, | ||||||
| 0.0); | ||||||
|
|
||||||
| // copy back content of Ptr<Thyra::MultiVectorBase> thyX into X | ||||||
| Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > XX = | ||||||
| Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toXpetra(thyX, comm); | ||||||
|
|
||||||
| X.update(Teuchos::ScalarTraits<Scalar>::one(), *XX, Teuchos::ScalarTraits<Scalar>::zero()); | ||||||
| using STS = Teuchos::ScalarTraits<Scalar>; | ||||||
|
|
||||||
| auto createProductMultiVector = [](const Teuchos::RCP<const Thyra::VectorSpaceBase<Scalar>> &space, | ||||||
| int numVecs, | ||||||
| const char *castErrorMsg) { | ||||||
| auto mv = Thyra::createMembers(space, numVecs); | ||||||
| auto prodMv = Teuchos::rcp_dynamic_cast<Thyra::ProductMultiVectorBase<Scalar>>(mv); | ||||||
| TEUCHOS_TEST_FOR_EXCEPTION(prodMv.is_null(), Exceptions::BadCast, castErrorMsg); | ||||||
| return std::make_pair(mv, prodMv); | ||||||
| }; | ||||||
|
|
||||||
| auto solveWithThyra = [&](const Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> &rhs, | ||||||
| bool initializeFromX, | ||||||
| const typename STS::magnitudeType alphaX) { | ||||||
| auto [thyB, thyProdB] = createProductMultiVector( | ||||||
| Teuchos::rcp_dynamic_cast<const Thyra::VectorSpaceBase<Scalar>>(bThyOp_->productRange()), | ||||||
| Teuchos::as<int>(rhs->getNumVectors()), | ||||||
| "MueLu::TekoSmoother::Apply: Failed to cast range space to product range space."); | ||||||
|
|
||||||
| Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::updateThyra(rhs, rgMapExtractor, thyProdB); | ||||||
|
|
||||||
| auto [thyX, thyProdX] = createProductMultiVector( | ||||||
| Teuchos::rcp_dynamic_cast<const Thyra::VectorSpaceBase<Scalar>>(bThyOp_->productDomain()), | ||||||
| Teuchos::as<int>(X.getNumVectors()), | ||||||
| "MueLu::TekoSmoother::Apply: Failed to cast domain space to product domain space."); | ||||||
|
|
||||||
| if (initializeFromX) { | ||||||
| Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::updateThyra(Teuchos::rcpFromRef(X), rgMapExtractor, thyProdX); | ||||||
| } | ||||||
|
|
||||||
| inverseOp_->apply( | ||||||
| Thyra::NOTRANS, | ||||||
| *thyB, | ||||||
| thyX.ptr(), | ||||||
| STS::one(), | ||||||
| STS::zero()); | ||||||
|
|
||||||
| auto XX = Xpetra::ThyraUtils<Scalar, LocalOrdinal, GlobalOrdinal, Node>::toXpetra(thyX, comm); | ||||||
| X.update(STS::one(), *XX, alphaX); | ||||||
| }; | ||||||
|
|
||||||
| if (InitialGuessIsZero) { | ||||||
| solveWithThyra(Teuchos::rcpFromRef(B), /*initializeFromX=*/true, STS::zero()); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When
Suggested change
|
||||||
| return; | ||||||
| } | ||||||
|
|
||||||
| auto residual = Utilities::Residual(*A_, X, B); | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||
| solveWithThyra(residual, /*initializeFromX=*/false, STS::one()); | ||||||
| } | ||||||
| //@} | ||||||
|
|
||||||
|
|
@@ -325,7 +338,7 @@ class TekoSmoother<double, int, GlobalOrdinal, Node> : public SmootherPrototype< | |||||
| //! block operator | ||||||
| RCP<Matrix> A_; // < ! internal blocked operator "A" generated by AFact_ | ||||||
| RCP<BlockedCrsMatrix> bA_; | ||||||
| RCP<const Thyra::BlockedLinearOpBase<Scalar> > bThyOp_; | ||||||
| RCP<const Thyra::BlockedLinearOpBase<Scalar>> bThyOp_; | ||||||
|
|
||||||
| //! Teko parameters | ||||||
| RCP<ParameterList> tekoParams_; // < ! parameter list containing Teko parameters. These parameters are not administrated by the factory and not validated. | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter
alphaXshould be of typeScalarto be consistent with theXpetra::MultiVector::updatesignature and the values passed to the lambda (STS::zero()andSTS::one()).