[Mirror] MueLu: Correct TekoSmoother::Apply when InitialGuessIsZero is false#98
[Mirror] MueLu: Correct TekoSmoother::Apply when InitialGuessIsZero is false#98
Conversation
Signed-off-by: malphil <malphil@sandia.gov>
Signed-off-by: malphil <malphil@sandia.gov>
Signed-off-by: malphil <malphil@sandia.gov>
|
CDash for AT1 results [Only accessible from Sandia networks] |
There was a problem hiding this comment.
Code Review
This pull request updates the TekoSmoother::Apply method to correctly handle the InitialGuessIsZero flag by implementing separate logic for zero and non-zero initial guesses. It also adds a comprehensive unit test for the TekoSmoother. Feedback includes moving a null check for rgMapExtractor to cover all code paths, removing a redundant vector copy when the initial guess is zero, and cleaning up an unused variable in the residual-based application path.
| auto rgMapExtractor = bA_->getRangeMapExtractor(); | ||
|
|
||
| Teuchos::RCP<const MapExtractor> rgMapExtractor = bA_->getRangeMapExtractor(); | ||
| TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(rgMapExtractor)); | ||
| if (InitialGuessIsZero) { | ||
| TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(rgMapExtractor)); |
There was a problem hiding this comment.
The null check for rgMapExtractor should be moved outside the if (InitialGuessIsZero) block. It is required for both branches, as rgMapExtractor is used at line 292 in the else branch to update the Thyra residual vector.
| auto rgMapExtractor = bA_->getRangeMapExtractor(); | |
| Teuchos::RCP<const MapExtractor> rgMapExtractor = bA_->getRangeMapExtractor(); | |
| TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(rgMapExtractor)); | |
| if (InitialGuessIsZero) { | |
| TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(rgMapExtractor)); | |
| auto rgMapExtractor = bA_->getRangeMapExtractor(); | |
| TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(rgMapExtractor)); | |
| if (InitialGuessIsZero) { |
| auto 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); |
There was a problem hiding this comment.
| auto 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."); |
Signed-off-by: malphil <malphil@sandia.gov>
Signed-off-by: malphil <malphil@sandia.gov>
Signed-off-by: malphil <malphil@sandia.gov>
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the Apply method in MueLu_TekoSmoother_decl.hpp to support non-zero initial guesses and improves code maintainability by introducing local lambdas for Thyra vector operations. Additionally, it adds unit tests for the Teko smoother and updates template syntax for C++11 compatibility. Review feedback suggests qualifying the MueLu::Utilities namespace to prevent compilation errors, adjusting the type of alphaX for consistency with the MultiVector update signature, and removing a redundant vector copy when the initial guess is zero.
| return; | ||
| } | ||
|
|
||
| auto residual = Utilities::Residual(*A_, X, B); |
There was a problem hiding this comment.
The Utilities class is likely not defined in this scope without a full namespace qualification or a local alias. Given that other utility classes in this file (like Xpetra::ThyraUtils) are fully qualified, you should use the fully qualified name for MueLu::Utilities to ensure successful compilation.
| auto residual = Utilities::Residual(*A_, X, B); | |
| auto residual = MueLu::Utilities<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Residual(*A_, X, B); |
|
|
||
| auto solveWithThyra = [&](const Teuchos::RCP<const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> &rhs, | ||
| bool initializeFromX, | ||
| const typename STS::magnitudeType alphaX) { |
There was a problem hiding this comment.
| }; | ||
|
|
||
| if (InitialGuessIsZero) { | ||
| solveWithThyra(Teuchos::rcpFromRef(B), /*initializeFromX=*/true, STS::zero()); |
There was a problem hiding this comment.
When InitialGuessIsZero is true, initializing the Thyra vector from X is unnecessary. Since inverseOp_->apply is called with beta=0.0 (line 285), the initial content of the output vector is ignored. Setting initializeFromX to false avoids a redundant copy of X (which might contain garbage or NaNs).
| solveWithThyra(Teuchos::rcpFromRef(B), /*initializeFromX=*/true, STS::zero()); | |
| solveWithThyra(Teuchos::rcpFromRef(B), /*initializeFromX=*/false, STS::zero()); |
Automated mirror of upstream PR trilinos#15173 @trilinos/muelu