10#ifndef MUELU_IFPACK2SMOOTHER_DEF_HPP
11#define MUELU_IFPACK2SMOOTHER_DEF_HPP
15#if defined(HAVE_MUELU_IFPACK2)
17#include <Teuchos_ParameterList.hpp>
19#include <Tpetra_RowMatrix.hpp>
21#include <Ifpack2_Chebyshev.hpp>
22#include <Ifpack2_Hiptmair.hpp>
23#include <Ifpack2_RILUK.hpp>
24#include <Ifpack2_Relaxation.hpp>
25#include <Ifpack2_ILUT.hpp>
26#include <Ifpack2_BlockRelaxation.hpp>
27#include <Ifpack2_Factory.hpp>
28#include <Ifpack2_Parameters.hpp>
30#include <Xpetra_BlockedCrsMatrix.hpp>
31#include <Xpetra_CrsMatrix.hpp>
32#include <Xpetra_CrsMatrixWrap.hpp>
33#include <Xpetra_TpetraBlockCrsMatrix.hpp>
34#include <Xpetra_Matrix.hpp>
35#include <Xpetra_MatrixMatrix.hpp>
36#include <Xpetra_MultiVectorFactory.hpp>
37#include <Xpetra_TpetraMultiVector.hpp>
39#include <Tpetra_BlockCrsMatrix_Helpers.hpp>
43#include "MueLu_Utilities.hpp"
45#include "MueLu_Aggregates.hpp"
47#ifdef HAVE_MUELU_INTREPID2
50#include "Intrepid2_Basis.hpp"
51#include "Kokkos_DynRankView.hpp"
56template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
60 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
61 bool isSupported = Ifpack2::Factory::isSupported<tRowMatrix>(
type_) || (
type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
62 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
63 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
64 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
65 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
66 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION" ||
67 type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
68 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
69 type_ ==
"LINESMOOTHING_BANDEDRELAXATION" ||
70 type_ ==
"LINESMOOTHING_BLOCK_RELAXATION" ||
71 type_ ==
"LINESMOOTHING_BLOCK RELAXATION" ||
72 type_ ==
"LINESMOOTHING_BLOCKRELAXATION" ||
73 type_ ==
"TOPOLOGICAL" ||
74 type_ ==
"AGGREGATE");
80template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
91template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
93 std::string prefix = this->
ShortClassName() +
": SetPrecParameters";
95 ParameterList& paramList =
const_cast<ParameterList&
>(this->
GetParameterList());
97 paramList.setParameters(list);
104 if (!precList.is_null() && precList->isParameter(
"partitioner: type") && precList->get<std::string>(
"partitioner: type") ==
"linear" &&
105 !precList->isParameter(
"partitioner: local parts")) {
106 LO matrixBlockSize = 1;
107 int lclSize =
A_->getRangeMap()->getLocalNumElements();
108 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_);
109 if (!matA.is_null()) {
110 lclSize = matA->getLocalNumRows();
111 matrixBlockSize = matA->GetFixedBlockSize();
113 precList->set(
"partitioner: local parts", lclSize / matrixBlockSize);
116 prec_->setParameters(*precList);
118 paramList.setParameters(*precList);
121template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
123 this->
Input(currentLevel,
"A");
125 if (
type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
126 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
127 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
128 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
129 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
130 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION" ||
131 type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
132 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
133 type_ ==
"LINESMOOTHING_BANDEDRELAXATION" ||
134 type_ ==
"LINESMOOTHING_BLOCK_RELAXATION" ||
135 type_ ==
"LINESMOOTHING_BLOCK RELAXATION" ||
136 type_ ==
"LINESMOOTHING_BLOCKRELAXATION") {
137 this->
Input(currentLevel,
"CoarseNumZLayers");
138 this->
Input(currentLevel,
"LineDetection_VertLineIds");
139 }
else if (
type_ ==
"BLOCK RELAXATION" ||
140 type_ ==
"BLOCK_RELAXATION" ||
141 type_ ==
"BLOCKRELAXATION" ||
143 type_ ==
"BANDED_RELAXATION" ||
144 type_ ==
"BANDED RELAXATION" ||
145 type_ ==
"BANDEDRELAXATION" ||
147 type_ ==
"TRIDI_RELAXATION" ||
148 type_ ==
"TRIDI RELAXATION" ||
149 type_ ==
"TRIDIRELAXATION" ||
150 type_ ==
"TRIDIAGONAL_RELAXATION" ||
151 type_ ==
"TRIDIAGONAL RELAXATION" ||
152 type_ ==
"TRIDIAGONALRELAXATION") {
155 if (precList.isParameter(
"partitioner: type") &&
156 precList.get<std::string>(
"partitioner: type") ==
"line") {
157 this->
Input(currentLevel,
"Coordinates");
159 }
else if (
type_ ==
"TOPOLOGICAL") {
161 this->
Input(currentLevel,
"pcoarsen: element to node map");
162 }
else if (
type_ ==
"AGGREGATE") {
164 this->
Input(currentLevel,
"Aggregates");
165 }
else if (
type_ ==
"HIPTMAIR") {
167 this->
Input(currentLevel,
"NodeMatrix");
168 this->
Input(currentLevel,
"D0");
172template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
180 if (paramList.isParameter(
"smoother: use blockcrsmatrix storage") && paramList.get<
bool>(
"smoother: use blockcrsmatrix storage")) {
182 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_);
184 blocksize = matA->GetFixedBlockSize();
188 RCP<CrsMatrixWrap> AcrsWrap = rcp_dynamic_cast<CrsMatrixWrap>(
A_);
189 if (AcrsWrap.is_null())
190 throw std::runtime_error(
"Ifpack2Smoother: Cannot convert matrix A to CrsMatrixWrap object.");
191 RCP<CrsMatrix> Acrs = AcrsWrap->getCrsMatrix();
193 throw std::runtime_error(
"Ifpack2Smoother: Cannot extract CrsMatrix from matrix A.");
194 RCP<TpetraCrsMatrix> At = rcp_dynamic_cast<TpetraCrsMatrix>(Acrs);
196 if (!Xpetra::Helpers<Scalar, LO, GO, Node>::isTpetraBlockCrs(matA))
197 throw std::runtime_error(
"Ifpack2Smoother: Cannot extract CrsMatrix or BlockCrsMatrix from matrix A.");
198 this->
GetOStream(
Statistics0) <<
"Ifpack2Smoother: Using (native) BlockCrsMatrix storage with blocksize " << blocksize << std::endl;
199 paramList.remove(
"smoother: use blockcrsmatrix storage");
201 RCP<Tpetra::BlockCrsMatrix<Scalar, LO, GO, Node>> blockCrs = Tpetra::convertToBlockCrsMatrix(*At->getTpetra_CrsMatrix(), blocksize);
202 RCP<CrsMatrix> blockCrs_as_crs = rcp(
new TpetraBlockCrsMatrix(blockCrs));
203 RCP<CrsMatrixWrap> blockWrap = rcp(
new CrsMatrixWrap(blockCrs_as_crs));
205 this->GetOStream(
Statistics0) <<
"Ifpack2Smoother: Using BlockCrsMatrix storage with blocksize " << blocksize << std::endl;
207 paramList.remove(
"smoother: use blockcrsmatrix storage");
212 if (type_ ==
"SCHWARZ")
213 SetupSchwarz(currentLevel);
215 else if (type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
216 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
217 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
218 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
219 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
220 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION" ||
221 type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
222 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
223 type_ ==
"LINESMOOTHING_BANDEDRELAXATION" ||
224 type_ ==
"LINESMOOTHING_BLOCK_RELAXATION" ||
225 type_ ==
"LINESMOOTHING_BLOCK RELAXATION" ||
226 type_ ==
"LINESMOOTHING_BLOCKRELAXATION")
227 SetupLineSmoothing(currentLevel);
229 else if (type_ ==
"BLOCK_RELAXATION" ||
230 type_ ==
"BLOCK RELAXATION" ||
231 type_ ==
"BLOCKRELAXATION" ||
233 type_ ==
"BANDED_RELAXATION" ||
234 type_ ==
"BANDED RELAXATION" ||
235 type_ ==
"BANDEDRELAXATION" ||
237 type_ ==
"TRIDI_RELAXATION" ||
238 type_ ==
"TRIDI RELAXATION" ||
239 type_ ==
"TRIDIRELAXATION" ||
240 type_ ==
"TRIDIAGONAL_RELAXATION" ||
241 type_ ==
"TRIDIAGONAL RELAXATION" ||
242 type_ ==
"TRIDIAGONALRELAXATION")
243 SetupBlockRelaxation(currentLevel);
245 else if (type_ ==
"CHEBYSHEV")
246 SetupChebyshev(currentLevel);
248 else if (type_ ==
"TOPOLOGICAL") {
249#ifdef HAVE_MUELU_INTREPID2
250 SetupTopological(currentLevel);
252 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"'TOPOLOGICAL' smoother choice requires Intrepid2");
254 }
else if (type_ ==
"AGGREGATE")
255 SetupAggregate(currentLevel);
257 else if (type_ ==
"HIPTMAIR")
258 SetupHiptmair(currentLevel);
261 SetupGeneric(currentLevel);
266 this->GetOStream(
Statistics1) << description() << std::endl;
269template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
271 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
273 bool reusePreconditioner =
false;
276 this->
GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupSchwarz(): Setup() has already been called, assuming reuse" << std::endl;
278 bool isTRowMatrix =
true;
279 RCP<const tRowMatrix> tA;
283 isTRowMatrix =
false;
286 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(
prec_);
287 if (!prec.is_null() && isTRowMatrix) {
289 reusePreconditioner =
true;
291 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupSchwarz(): reuse of this type is not available "
292 "(either failed cast to CanChangeMatrix, or to Tpetra Row Matrix), reverting to full construction"
297 if (!reusePreconditioner) {
298 ParameterList& paramList =
const_cast<ParameterList&
>(this->
GetParameterList());
300 bool isBlockedMatrix =
false;
301 RCP<Matrix> merged2Mat;
303 std::string sublistName =
"subdomain solver parameters";
304 if (paramList.isSublist(sublistName)) {
313 ParameterList& subList = paramList.sublist(sublistName);
315 std::string partName =
"partitioner: type";
321 if (subList.isParameter(partName) && subList.get<std::string>(partName) ==
"vanka user") {
322 isBlockedMatrix =
true;
324 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
326 "Matrix A must be of type BlockedCrsMatrix.");
328 size_t numVels = bA->getMatrix(0, 0)->getLocalNumRows();
329 size_t numPres = bA->getMatrix(1, 0)->getLocalNumRows();
330 size_t numRows = rcp_dynamic_cast<Matrix>(
A_,
true)->getLocalNumRows();
332 ArrayRCP<LocalOrdinal> blockSeeds(numRows, Teuchos::OrdinalTraits<LocalOrdinal>::invalid());
334 size_t numBlocks = 0;
335 for (
size_t rowOfB = numVels; rowOfB < numVels + numPres; ++rowOfB)
336 blockSeeds[rowOfB] = numBlocks++;
338 RCP<BlockedCrsMatrix> bA2 = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
340 "Matrix A must be of type BlockedCrsMatrix.");
342 merged2Mat = bA2->Merge();
346 bool haveBoundary =
false;
347 for (LO i = 0; i < boundaryNodes.size(); i++)
348 if (boundaryNodes[i]) {
352 blockSeeds[i] = numBlocks;
358 subList.set(
"partitioner: type",
"user");
359 subList.set(
"partitioner: map", blockSeeds);
360 subList.set(
"partitioner: local parts", as<int>(numBlocks));
363 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
365 isBlockedMatrix =
true;
366 merged2Mat = bA->Merge();
371 RCP<const tRowMatrix> tA;
372 if (isBlockedMatrix ==
true)
386template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
388 ParameterList& paramList =
const_cast<ParameterList&
>(this->
GetParameterList());
391 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupAggregate(): Setup() has already been called" << std::endl;
392 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupAggregate(): reuse of this type is not available, reverting to full construction" << std::endl;
399 RCP<const LOMultiVector> vertex2AggId = aggregates->GetVertex2AggId();
400 ArrayRCP<LO> aggregate_ids = rcp_const_cast<LOMultiVector>(vertex2AggId)->getDataNonConst(0);
401 ArrayRCP<LO> dof_ids;
405 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_);
407 blocksize = matA->GetFixedBlockSize();
409 dof_ids.resize(aggregate_ids.size() * blocksize);
410 for (LO i = 0; i < (LO)aggregate_ids.size(); i++) {
411 for (LO j = 0; j < (LO)blocksize; j++)
412 dof_ids[i * blocksize + j] = aggregate_ids[i];
415 dof_ids = aggregate_ids;
418 paramList.set(
"partitioner: map", dof_ids);
419 paramList.set(
"partitioner: type",
"user");
420 paramList.set(
"partitioner: overlap", 0);
421 paramList.set(
"partitioner: local parts", (
int)aggregates->GetNumAggregates());
425 type_ =
"BLOCKRELAXATION";
432#ifdef HAVE_MUELU_INTREPID2
433template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
443 if (this->IsSetup() ==
true) {
444 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupTopological(): Setup() has already been called" << std::endl;
445 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupTopological(): reuse of this type is not available, reverting to full construction" << std::endl;
448 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
450 typedef typename Node::device_type::execution_space ES;
452 typedef Kokkos::DynRankView<LocalOrdinal, typename Node::device_type> FCO;
454 LocalOrdinal lo_invalid = Teuchos::OrdinalTraits<LO>::invalid();
460 string basisString = paramList.get<
string>(
"pcoarsen: hi basis");
468 string topologyTypeString = paramList.get<
string>(
"smoother: neighborhood type");
470 if (topologyTypeString ==
"node")
472 else if (topologyTypeString ==
"edge")
474 else if (topologyTypeString ==
"face")
476 else if (topologyTypeString ==
"cell")
477 dimension = basis->getBaseCellTopology().getDimension();
479 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unrecognized smoother neighborhood type. Supported types are node, edge, face.");
480 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_,
true);
481 vector<vector<LocalOrdinal>> seeds;
486 int myNodeCount = matA->getRowMap()->getLocalNumElements();
487 ArrayRCP<LocalOrdinal> nodeSeeds(myNodeCount, lo_invalid);
488 int localPartitionNumber = 0;
490 nodeSeeds[seed] = localPartitionNumber++;
493 paramList.remove(
"smoother: neighborhood type");
494 paramList.remove(
"pcoarsen: hi basis");
496 paramList.set(
"partitioner: map", nodeSeeds);
497 paramList.set(
"partitioner: type",
"user");
498 paramList.set(
"partitioner: overlap", 1);
499 paramList.set(
"partitioner: local parts",
int(seeds[dimension].size()));
503 type_ =
"BLOCKRELAXATION";
511template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
514 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupLineSmoothing(): Setup() has already been called" << std::endl;
515 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupLineSmoothing(): reuse of this type is not available, reverting to full construction" << std::endl;
518 ParameterList& myparamList =
const_cast<ParameterList&
>(this->
GetParameterList());
521 if (CoarseNumZLayers > 0) {
526 for (
size_t k = 0; k < Teuchos::as<size_t>(TVertLineIdSmoo.size()); k++) {
527 if (maxPart < TVertLineIdSmoo[k]) maxPart = TVertLineIdSmoo[k];
529 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_,
true);
530 size_t numLocalRows = matA->getLocalNumRows();
533 "MueLu::Ifpack2Smoother::Setup(): the number of local nodes is incompatible with the TVertLineIdsSmoo.");
538 int actualDofsPerNode = numLocalRows / TVertLineIdSmoo.size();
539 LO matrixBlockSize = matA->GetFixedBlockSize();
540 if (matrixBlockSize > 1 && actualDofsPerNode > 1) {
542 "MueLu::Ifpack2Smoother::Setup(): A is a block matrix but its block size and DOFs/node from partitioner disagree");
543 }
else if (matrixBlockSize > 1) {
544 actualDofsPerNode = matrixBlockSize;
546 myparamList.set(
"partitioner: PDE equations", actualDofsPerNode);
548 if (numLocalRows == Teuchos::as<size_t>(TVertLineIdSmoo.size())) {
549 myparamList.set(
"partitioner: type",
"user");
550 myparamList.set(
"partitioner: map", TVertLineIdSmoo);
551 myparamList.set(
"partitioner: local parts", maxPart + 1);
553 if (myparamList.isParameter(
"partitioner: block size") &&
554 myparamList.get<
int>(
"partitioner: block size") != -1) {
555 int block_size = myparamList.get<
int>(
"partitioner: block size");
557 "MueLu::Ifpack2Smoother::Setup(): the number of local nodes is incompatible with the specified block size.");
558 numLocalRows /= block_size;
562 size_t numDofsPerNode = numLocalRows / TVertLineIdSmoo.size();
565 Teuchos::ArrayRCP<LO> partitionerMap(numLocalRows, Teuchos::OrdinalTraits<LocalOrdinal>::invalid());
566 for (
size_t blockRow = 0; blockRow < Teuchos::as<size_t>(TVertLineIdSmoo.size()); ++blockRow)
567 for (
size_t dof = 0; dof < numDofsPerNode; dof++)
568 partitionerMap[blockRow * numDofsPerNode + dof] = TVertLineIdSmoo[blockRow];
569 myparamList.set(
"partitioner: type",
"user");
570 myparamList.set(
"partitioner: map", partitionerMap);
571 myparamList.set(
"partitioner: local parts", maxPart + 1);
574 if (
type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
575 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
576 type_ ==
"LINESMOOTHING_BANDEDRELAXATION")
577 type_ =
"BANDEDRELAXATION";
578 else if (
type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
579 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
580 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
581 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
582 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
583 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION")
584 type_ =
"TRIDIAGONALRELAXATION";
586 type_ =
"BLOCKRELAXATION";
589 this->
GetOStream(
Runtime0) <<
"Line detection failed: fall back to point-wise relaxation" << std::endl;
590 myparamList.remove(
"partitioner: type",
false);
591 myparamList.remove(
"partitioner: map",
false);
592 myparamList.remove(
"partitioner: local parts",
false);
593 type_ =
"RELAXATION";
604template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
606 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
608 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
614 bool reusePreconditioner =
false;
617 this->
GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupBlockRelaxation(): Setup() has already been called, assuming reuse" << std::endl;
619 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(
prec_);
620 if (!prec.is_null()) {
622 reusePreconditioner =
true;
624 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupBlockRelaxation(): reuse of this type is not available (failed cast to CanChangeMatrix), "
625 "reverting to full construction"
630 if (!reusePreconditioner) {
631 ParameterList& myparamList =
const_cast<ParameterList&
>(this->
GetParameterList());
633 if (myparamList.isParameter(
"partitioner: type") &&
634 myparamList.get<std::string>(
"partitioner: type") ==
"line") {
635 Teuchos::RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>> xCoordinates =
637 Teuchos::RCP<Tpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>> coordinates = Teuchos::rcpFromRef(Xpetra::toTpetra<
typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>(*xCoordinates));
639 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_);
640 size_t lclSize =
A_->getRangeMap()->getLocalNumElements();
642 lclSize = matA->getLocalNumRows();
643 size_t numDofsPerNode = lclSize / xCoordinates->getMap()->getLocalNumElements();
644 myparamList.set(
"partitioner: coordinates", coordinates);
645 myparamList.set(
"partitioner: PDE equations", (
int)numDofsPerNode);
656template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
658 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
659 using STS = Teuchos::ScalarTraits<SC>;
660 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
666 bool reusePreconditioner =
false;
670 this->
GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupChebyshev(): Setup() has already been called, assuming reuse" << std::endl;
672 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(
prec_);
673 if (!prec.is_null()) {
675 reusePreconditioner =
true;
677 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupChebyshev(): reuse of this type is not available (failed cast to CanChangeMatrix), "
678 "reverting to full construction"
684 ParameterList& paramList =
const_cast<ParameterList&
>(this->
GetParameterList());
685 SC negone = -STS::one();
688 if (!reusePreconditioner) {
703 if (lambdaMax == negone) {
704 typedef Tpetra::RowMatrix<SC, LO, GO, NO> MatrixType;
706 Teuchos::RCP<Ifpack2::Chebyshev<MatrixType>> chebyPrec = rcp_dynamic_cast<Ifpack2::Chebyshev<MatrixType>>(
prec_);
707 if (chebyPrec != Teuchos::null) {
708 lambdaMax = chebyPrec->getLambdaMaxForApply();
709 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_);
711 matA->SetMaxEigenvalueEstimate(lambdaMax);
713 <<
" = " << lambdaMax << std::endl;
715 TEUCHOS_TEST_FOR_EXCEPTION(lambdaMax == negone,
Exceptions::RuntimeError,
"MueLu::Ifpack2Smoother::Setup(): no maximum eigenvalue estimate");
719template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
721 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
722 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
728 bool reusePreconditioner =
false;
731 this->
GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupHiptmair(): Setup() has already been called, assuming reuse" << std::endl;
733 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(
prec_);
734 if (!prec.is_null()) {
736 reusePreconditioner =
true;
738 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupHiptmair(): reuse of this type is not available (failed cast to CanChangeMatrix), "
739 "reverting to full construction"
745 SC negone = -Teuchos::ScalarTraits<Scalar>::one();
746 ParameterList& paramList =
const_cast<ParameterList&
>(this->
GetParameterList());
747 std::string smoother1 = paramList.get(
"hiptmair: smoother type 1",
"CHEBYSHEV");
748 std::string smoother2 = paramList.get(
"hiptmair: smoother type 2",
"CHEBYSHEV");
749 SC lambdaMax11 = negone;
751 if (smoother1 ==
"CHEBYSHEV") {
752 ParameterList& list1 = paramList.sublist(
"hiptmair: smoother list 1");
755 if (smoother2 ==
"CHEBYSHEV") {
756 ParameterList& list2 = paramList.sublist(
"hiptmair: smoother list 2");
764 RCP<Operator> NodeMatrix = currentLevel.
Get<RCP<Operator>>(
"NodeMatrix");
765 RCP<Operator> D0 = currentLevel.
Get<RCP<Operator>>(
"D0");
770 Teuchos::ParameterList newlist;
771 newlist.set(
"P", tD0);
772 newlist.set(
"PtAP", tNodeMatrix);
773 if (!reusePreconditioner) {
782 if (smoother1 ==
"CHEBYSHEV" && lambdaMax11 == negone) {
783 using Teuchos::rcp_dynamic_cast;
784 typedef Tpetra::RowMatrix<SC, LO, GO, NO> MatrixType;
785 auto hiptmairPrec = rcp_dynamic_cast<Ifpack2::Hiptmair<MatrixType>>(
prec_);
786 if (hiptmairPrec != Teuchos::null) {
787 auto chebyPrec = rcp_dynamic_cast<Ifpack2::Chebyshev<MatrixType>>(hiptmairPrec->getPrec1());
788 if (chebyPrec != Teuchos::null) {
789 lambdaMax11 = chebyPrec->getLambdaMaxForApply();
790 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(
A_);
792 matA->SetMaxEigenvalueEstimate(lambdaMax11);
794 <<
" = " << lambdaMax11 << std::endl;
796 TEUCHOS_TEST_FOR_EXCEPTION(lambdaMax11 == negone,
Exceptions::RuntimeError,
"MueLu::Ifpack2Smoother::Setup(): no maximum eigenvalue estimate");
801template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
804 typedef Teuchos::ScalarTraits<SC> STS;
805 SC negone = -STS::one();
806 RCP<Operator> currentA = currentLevel.
Get<RCP<Operator>>(matrixName);
807 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(currentA);
808 SC lambdaMax = negone;
810 std::string maxEigString =
"chebyshev: max eigenvalue";
811 std::string eigRatioString =
"chebyshev: ratio eigenvalue";
814 if (paramList.isParameter(maxEigString)) {
815 if (paramList.isType<
double>(maxEigString))
816 lambdaMax = paramList.get<
double>(maxEigString);
818 lambdaMax = paramList.get<SC>(maxEigString);
819 this->
GetOStream(
Statistics1) << label << maxEigString <<
" (cached with smoother parameter list) = " << lambdaMax << std::endl;
821 matA->SetMaxEigenvalueEstimate(lambdaMax);
823 }
else if (!matA.is_null()) {
824 lambdaMax = matA->GetMaxEigenvalueEstimate();
825 if (lambdaMax != negone) {
826 this->
GetOStream(
Statistics1) << label << maxEigString <<
" (cached with matrix) = " << lambdaMax << std::endl;
827 paramList.set(maxEigString, lambdaMax);
832 const SC defaultEigRatio = 20;
834 SC ratio = defaultEigRatio;
835 if (paramList.isParameter(eigRatioString)) {
836 if (paramList.isType<
double>(eigRatioString))
837 ratio = paramList.get<
double>(eigRatioString);
839 ratio = paramList.get<SC>(eigRatioString);
846 RCP<const Operator> fineA = currentLevel.
GetPreviousLevel()->Get<RCP<Operator>>(matrixName);
847 size_t nRowsFine = fineA->getDomainMap()->getGlobalNumElements();
848 size_t nRowsCoarse = currentA->getDomainMap()->getGlobalNumElements();
850 SC levelRatio = as<SC>(as<double>(nRowsFine) / nRowsCoarse);
851 if (STS::magnitude(levelRatio) > STS::magnitude(ratio))
856 paramList.set(eigRatioString, ratio);
858 if (paramList.isParameter(
"chebyshev: use rowsumabs diagonal scaling")) {
859 this->
GetOStream(
Runtime1) <<
"chebyshev: using rowsumabs diagonal scaling" << std::endl;
860 bool doScale =
false;
861 doScale = paramList.get<
bool>(
"chebyshev: use rowsumabs diagonal scaling");
862 paramList.remove(
"chebyshev: use rowsumabs diagonal scaling");
863 double chebyReplaceTol = Teuchos::ScalarTraits<Scalar>::eps() * 100;
864 std::string paramName =
"chebyshev: rowsumabs diagonal replacement tolerance";
865 if (paramList.isParameter(paramName)) {
866 chebyReplaceTol = paramList.get<
double>(paramName);
867 paramList.remove(paramName);
869 double chebyReplaceVal = Teuchos::ScalarTraits<double>::zero();
870 paramName =
"chebyshev: rowsumabs diagonal replacement value";
871 if (paramList.isParameter(paramName)) {
872 chebyReplaceVal = paramList.get<
double>(paramName);
873 paramList.remove(paramName);
875 bool chebyReplaceSingleEntryRowWithZero =
false;
876 paramName =
"chebyshev: rowsumabs replace single entry row with zero";
877 if (paramList.isParameter(paramName)) {
878 chebyReplaceSingleEntryRowWithZero = paramList.get<
bool>(paramName);
879 paramList.remove(paramName);
881 bool useAverageAbsDiagVal =
false;
882 paramName =
"chebyshev: rowsumabs use automatic diagonal tolerance";
883 if (paramList.isParameter(paramName)) {
884 useAverageAbsDiagVal = paramList.get<
bool>(paramName);
885 paramList.remove(paramName);
888 TEUCHOS_ASSERT(!matA.is_null());
889 const bool doReciprocal =
true;
890 RCP<Vector> lumpedDiagonal =
Utilities::GetLumpedMatrixDiagonal(*matA, doReciprocal, chebyReplaceTol, chebyReplaceVal, chebyReplaceSingleEntryRowWithZero, useAverageAbsDiagVal);
891 const Xpetra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& tmpVec =
dynamic_cast<const Xpetra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>&
>(*lumpedDiagonal);
892 paramList.set(
"chebyshev: operator inv diagonal", tmpVec.getTpetra_Vector());
899template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
901 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
902 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(
A_);
908 bool reusePreconditioner =
false;
911 this->
GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupGeneric(): Setup() has already been called, assuming reuse" << std::endl;
913 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(
prec_);
914 if (!prec.is_null()) {
916 reusePreconditioner =
true;
918 this->
GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupGeneric(): reuse of this type is not available (failed cast to CanChangeMatrix), "
919 "reverting to full construction"
924 if (!reusePreconditioner) {
933template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
943 Teuchos::ParameterList paramList;
944 bool supportInitialGuess =
false;
947 if (
prec_->supportsZeroStartingSolution()) {
948 prec_->setZeroStartingSolution(InitialGuessIsZero);
949 supportInitialGuess =
true;
950 }
else if (
type_ ==
"SCHWARZ") {
951 paramList.set(
"schwarz: zero starting solution", InitialGuessIsZero);
956 prec_->setParameters(paramList);
957 supportInitialGuess =
true;
967 if (InitialGuessIsZero || supportInitialGuess) {
968 Tpetra::MultiVector<SC, LO, GO, NO>& tpX = toTpetra(X);
969 const Tpetra::MultiVector<SC, LO, GO, NO>& tpB = toTpetra(B);
970 prec_->apply(tpB, tpX);
972 typedef Teuchos::ScalarTraits<Scalar> TST;
974 RCP<MultiVector> Residual;
977 RCP<TimeMonitor> tM = rcp(
new TimeMonitor(*
this, prefix +
"residual calculation",
Timings0));
981 RCP<MultiVector> Correction = MultiVectorFactory::Build(
A_->getDomainMap(), X.getNumVectors());
983 Tpetra::MultiVector<SC, LO, GO, NO>& tpX = toTpetra(*Correction);
984 const Tpetra::MultiVector<SC, LO, GO, NO>& tpB = toTpetra(*Residual);
986 prec_->apply(tpB, tpX);
988 X.update(TST::one(), *Correction, TST::one());
992template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
999template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1001 std::ostringstream out;
1003 out <<
prec_->description();
1006 out <<
"{type = " <<
type_ <<
"}";
1011template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1016 out0 <<
"Prec. type: " <<
type_ << std::endl;
1019 out0 <<
"Parameter list: " << std::endl;
1020 Teuchos::OSTab tab2(out);
1022 out0 <<
"Overlap: " <<
overlap_ << std::endl;
1026 if (
prec_ != Teuchos::null) {
1027 Teuchos::OSTab tab2(out);
1028 out << *
prec_ << std::endl;
1031 if (verbLevel &
Debug) {
1034 <<
"RCP<prec_>: " <<
prec_ << std::endl;
1038template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1040 typedef Tpetra::RowMatrix<SC, LO, GO, NO> MatrixType;
1042 RCP<Ifpack2::Relaxation<MatrixType>> pr = rcp_dynamic_cast<Ifpack2::Relaxation<MatrixType>>(
prec_);
1043 if (!pr.is_null())
return pr->getNodeSmootherComplexity();
1045 RCP<Ifpack2::Chebyshev<MatrixType>> pc = rcp_dynamic_cast<Ifpack2::Chebyshev<MatrixType>>(
prec_);
1046 if (!pc.is_null())
return pc->getNodeSmootherComplexity();
1048 RCP<Ifpack2::BlockRelaxation<MatrixType>> pb = rcp_dynamic_cast<Ifpack2::BlockRelaxation<MatrixType>>(
prec_);
1049 if (!pb.is_null())
return pb->getNodeSmootherComplexity();
1051 RCP<Ifpack2::ILUT<MatrixType>> pi = rcp_dynamic_cast<Ifpack2::ILUT<MatrixType>>(
prec_);
1052 if (!pi.is_null())
return pi->getNodeSmootherComplexity();
1054 RCP<Ifpack2::RILUK<MatrixType>> pk = rcp_dynamic_cast<Ifpack2::RILUK<MatrixType>>(
prec_);
1055 if (!pk.is_null())
return pk->getNodeSmootherComplexity();
1057 return Teuchos::OrdinalTraits<size_t>::invalid();
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
static Teuchos::RCP< Preconditioner< typename MatrixType::scalar_type, typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type > > create(const std::string &precType, const Teuchos::RCP< const MatrixType > &matrix)
virtual std::string ShortClassName() const
Return the class name of the object, without template parameters and without namespace.
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.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
RCP< ParameterList > RemoveFactoriesFromList(const ParameterList &list) const
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
void SetupSchwarz(Level ¤tLevel)
void Setup(Level ¤tLevel)
Set up the smoother.
Scalar SetupChebyshevEigenvalues(Level ¤tLevel, const std::string &matrixName, const std::string &label, Teuchos::ParameterList ¶mList) const
void SetupAggregate(Level ¤tLevel)
void SetupBlockRelaxation(Level ¤tLevel)
void SetupChebyshev(Level ¤tLevel)
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
void SetParameterList(const Teuchos::ParameterList ¶mList)
Set parameters from a parameter list and return with default values.
RCP< SmootherPrototype > Copy() const
std::string description() const
Return a simple one-line description of this object.
void SetupHiptmair(Level ¤tLevel)
LO overlap_
overlap when using the smoother in additive Schwarz mode
RCP< Ifpack2::Preconditioner< Scalar, LocalOrdinal, GlobalOrdinal, Node > > prec_
pointer to Ifpack2 preconditioner object
void SetPrecParameters(const Teuchos::ParameterList &list=Teuchos::ParameterList()) const
void SetupTopological(Level ¤tLevel)
std::string type_
ifpack2-specific key phrase that denote smoother type
friend class Ifpack2Smoother
Constructor.
void DeclareInput(Level ¤tLevel) const
Input.
RCP< Operator > A_
matrix, used in apply if solving residual equation
void SetupLineSmoothing(Level ¤tLevel)
void SetupGeneric(Level ¤tLevel)
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
Apply the preconditioner.
Class that holds all level-specific information.
RCP< Level > & GetPreviousLevel()
Previous level.
int GetLevelID() const
Return level number.
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
virtual void SetParameterList(const Teuchos::ParameterList ¶mList)=0
Set parameters from a parameter list and return with default values.
void declareConstructionOutcome(bool fail, std::string msg)
bool IsSetup() const
Get the state of a smoother prototype.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Integrates Teuchos::TimeMonitor with MueLu verbosity system.
static Teuchos::ArrayRCP< const bool > DetectDirichletRows(const Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &A, const Magnitude &tol=Teuchos::ScalarTraits< Magnitude >::zero(), bool count_twos_as_dirichlet=false)
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)
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &Op, const MultiVector &X, const MultiVector &RHS)
static RCP< Tpetra::RowMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Op2NonConstTpetraRow(RCP< Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Op)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
void FindGeometricSeedOrdinals(Teuchos::RCP< Basis > basis, const LOFieldContainer &elementToNodeMap, std::vector< std::vector< LocalOrdinal > > &seeds, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &rowMap, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &columnMap)
Teuchos::RCP< Intrepid2::Basis< KokkosExecutionSpace, Scalar, Scalar > > BasisFactory(const std::string &name, int °ree)
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line).
@ Debug
Print additional debugging information.
@ Statistics1
Print more statistics.
@ External
Print external lib objects.
@ Timings0
High level timing information (use Teuchos::TimeMonitor::summarize() to print).
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose).
@ Timings
Print all timing information.
@ Parameters0
Print class parameters.
@ Statistics0
Print statistics that do not involve significant additional computation.
@ Parameters1
Print class parameters (more parameters, more verbose).