10#ifndef MUELU_IFPACK2SMOOTHER_DEF_HPP
11#define MUELU_IFPACK2SMOOTHER_DEF_HPP
14#include "Xpetra_TpetraRowMatrix.hpp"
16#if defined(HAVE_MUELU_IFPACK2)
18#include <Teuchos_ParameterList.hpp>
20#include <Tpetra_RowMatrix.hpp>
22#include <Ifpack2_Chebyshev.hpp>
23#include <Ifpack2_Hiptmair.hpp>
24#include <Ifpack2_RILUK.hpp>
25#include <Ifpack2_Relaxation.hpp>
26#include <Ifpack2_ILUT.hpp>
27#include <Ifpack2_BlockRelaxation.hpp>
28#include <Ifpack2_Factory.hpp>
29#include <Ifpack2_Parameters.hpp>
31#include <Xpetra_BlockedCrsMatrix.hpp>
32#include <Xpetra_CrsMatrix.hpp>
33#include <Xpetra_CrsMatrixWrap.hpp>
34#include <Xpetra_TpetraBlockCrsMatrix.hpp>
35#include <Xpetra_Matrix.hpp>
36#include <Xpetra_MatrixMatrix.hpp>
37#include <Xpetra_MultiVectorFactory.hpp>
38#include <Xpetra_TpetraMultiVector.hpp>
40#include <Tpetra_BlockCrsMatrix_Helpers.hpp>
44#include "MueLu_Utilities.hpp"
46#include "MueLu_Aggregates.hpp"
48#ifdef HAVE_MUELU_INTREPID2
51#include "Intrepid2_Basis.hpp"
52#include "Kokkos_DynRankView.hpp"
57template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
66 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
67 bool isSupported = Ifpack2::Factory::isSupported<tRowMatrix>(
type_) || (
type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
68 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
69 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
70 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
71 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
72 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION" ||
73 type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
74 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
75 type_ ==
"LINESMOOTHING_BANDEDRELAXATION" ||
76 type_ ==
"LINESMOOTHING_BLOCK_RELAXATION" ||
77 type_ ==
"LINESMOOTHING_BLOCK RELAXATION" ||
78 type_ ==
"LINESMOOTHING_BLOCKRELAXATION" ||
79 type_ ==
"TOPOLOGICAL" ||
80 type_ ==
"AGGREGATE");
86template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
99 std::string prefix = this->ShortClassName() +
": SetPrecParameters";
101 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
103 paramList.setParameters(list);
105 RCP<ParameterList> precList = this->RemoveFactoriesFromList(this->GetParameterList());
108 precList->set(
"timer for apply", this->IsPrint(
Timings));
110 if (!precList.is_null() && precList->isParameter(
"partitioner: type") && precList->get<std::string>(
"partitioner: type") ==
"linear" &&
111 !precList->isParameter(
"partitioner: local parts")) {
112 LO matrixBlockSize = 1;
113 int lclSize = A_->getRangeMap()->getLocalNumElements();
114 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_);
115 if (!matA.is_null()) {
116 lclSize = matA->getLocalNumRows();
117 matrixBlockSize = matA->GetFixedBlockSize();
119 precList->set(
"partitioner: local parts", lclSize / matrixBlockSize);
122 prec_->setParameters(*precList);
124 paramList.setParameters(*precList);
127template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
129 this->Input(currentLevel,
"A");
131 if (type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
132 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
133 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
134 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
135 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
136 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION" ||
137 type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
138 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
139 type_ ==
"LINESMOOTHING_BANDEDRELAXATION" ||
140 type_ ==
"LINESMOOTHING_BLOCK_RELAXATION" ||
141 type_ ==
"LINESMOOTHING_BLOCK RELAXATION" ||
142 type_ ==
"LINESMOOTHING_BLOCKRELAXATION") {
143 this->Input(currentLevel,
"CoarseNumZLayers");
144 this->Input(currentLevel,
"LineDetection_VertLineIds");
145 }
else if (type_ ==
"BLOCK RELAXATION" ||
146 type_ ==
"BLOCK_RELAXATION" ||
147 type_ ==
"BLOCKRELAXATION" ||
149 type_ ==
"BANDED_RELAXATION" ||
150 type_ ==
"BANDED RELAXATION" ||
151 type_ ==
"BANDEDRELAXATION" ||
153 type_ ==
"TRIDI_RELAXATION" ||
154 type_ ==
"TRIDI RELAXATION" ||
155 type_ ==
"TRIDIRELAXATION" ||
156 type_ ==
"TRIDIAGONAL_RELAXATION" ||
157 type_ ==
"TRIDIAGONAL RELAXATION" ||
158 type_ ==
"TRIDIAGONALRELAXATION") {
160 ParameterList precList = this->GetParameterList();
161 if (precList.isParameter(
"partitioner: type") &&
162 precList.get<std::string>(
"partitioner: type") ==
"line") {
163 this->Input(currentLevel,
"Coordinates");
165 }
else if (type_ ==
"TOPOLOGICAL") {
167 this->Input(currentLevel,
"pcoarsen: element to node map");
168 }
else if (type_ ==
"AGGREGATE") {
170 this->Input(currentLevel,
"Aggregates");
171 }
else if (type_ ==
"HIPTMAIR") {
173 this->Input(currentLevel,
"NodeMatrix");
174 this->Input(currentLevel,
"D0");
178template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
181 A_ = Factory::Get<RCP<Operator>>(currentLevel,
"A");
182 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
186 if (paramList.isParameter(
"smoother: use blockcrsmatrix storage") && paramList.get<
bool>(
"smoother: use blockcrsmatrix storage")) {
188 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_);
190 blocksize = matA->GetFixedBlockSize();
194 RCP<CrsMatrixWrap> AcrsWrap = rcp_dynamic_cast<CrsMatrixWrap>(A_);
195 if (AcrsWrap.is_null())
196 throw std::runtime_error(
"Ifpack2Smoother: Cannot convert matrix A to CrsMatrixWrap object.");
197 RCP<CrsMatrix> Acrs = AcrsWrap->getCrsMatrix();
199 throw std::runtime_error(
"Ifpack2Smoother: Cannot extract CrsMatrix from matrix A.");
200 RCP<TpetraCrsMatrix> At = rcp_dynamic_cast<TpetraCrsMatrix>(Acrs);
202 if (!Xpetra::Helpers<Scalar, LO, GO, Node>::isTpetraBlockCrs(matA))
203 throw std::runtime_error(
"Ifpack2Smoother: Cannot extract CrsMatrix or BlockCrsMatrix from matrix A.");
204 this->GetOStream(
Statistics0) <<
"Ifpack2Smoother: Using (native) BlockCrsMatrix storage with blocksize " << blocksize << std::endl;
205 paramList.remove(
"smoother: use blockcrsmatrix storage");
207 RCP<Tpetra::BlockCrsMatrix<Scalar, LO, GO, Node>> blockCrs = Tpetra::convertToBlockCrsMatrix(*At->getTpetra_CrsMatrix(), blocksize);
208 RCP<CrsMatrix> blockCrs_as_crs = rcp(
new TpetraBlockCrsMatrix(blockCrs));
209 RCP<CrsMatrixWrap> blockWrap = rcp(
new CrsMatrixWrap(blockCrs_as_crs));
211 this->GetOStream(
Statistics0) <<
"Ifpack2Smoother: Using BlockCrsMatrix storage with blocksize " << blocksize << std::endl;
213 paramList.remove(
"smoother: use blockcrsmatrix storage");
218 if (type_ ==
"SCHWARZ")
219 SetupSchwarz(currentLevel);
221 else if (type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
222 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
223 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
224 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
225 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
226 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION" ||
227 type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
228 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
229 type_ ==
"LINESMOOTHING_BANDEDRELAXATION" ||
230 type_ ==
"LINESMOOTHING_BLOCK_RELAXATION" ||
231 type_ ==
"LINESMOOTHING_BLOCK RELAXATION" ||
232 type_ ==
"LINESMOOTHING_BLOCKRELAXATION")
233 SetupLineSmoothing(currentLevel);
235 else if (type_ ==
"BLOCK_RELAXATION" ||
236 type_ ==
"BLOCK RELAXATION" ||
237 type_ ==
"BLOCKRELAXATION" ||
239 type_ ==
"BANDED_RELAXATION" ||
240 type_ ==
"BANDED RELAXATION" ||
241 type_ ==
"BANDEDRELAXATION" ||
243 type_ ==
"TRIDI_RELAXATION" ||
244 type_ ==
"TRIDI RELAXATION" ||
245 type_ ==
"TRIDIRELAXATION" ||
246 type_ ==
"TRIDIAGONAL_RELAXATION" ||
247 type_ ==
"TRIDIAGONAL RELAXATION" ||
248 type_ ==
"TRIDIAGONALRELAXATION")
249 SetupBlockRelaxation(currentLevel);
251 else if (type_ ==
"CHEBYSHEV")
252 SetupChebyshev(currentLevel);
254 else if (type_ ==
"TOPOLOGICAL") {
255#ifdef HAVE_MUELU_INTREPID2
256 SetupTopological(currentLevel);
258 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"'TOPOLOGICAL' smoother choice requires Intrepid2");
260 }
else if (type_ ==
"AGGREGATE")
261 SetupAggregate(currentLevel);
263 else if (type_ ==
"HIPTMAIR")
264 SetupHiptmair(currentLevel);
267 SetupGeneric(currentLevel);
272 this->GetOStream(
Statistics1) << description() << std::endl;
275template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
277 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
279 bool reusePreconditioner =
false;
280 if (this->IsSetup() ==
true) {
282 this->GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupSchwarz(): Setup() has already been called, assuming reuse" << std::endl;
284 bool isTRowMatrix =
true;
285 RCP<const tRowMatrix> tA;
287 tA = Xpetra::toTpetraRowMatrix(A_);
289 isTRowMatrix =
false;
292 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(prec_);
293 if (!prec.is_null() && isTRowMatrix) {
295 reusePreconditioner =
true;
297 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupSchwarz(): reuse of this type is not available "
298 "(either failed cast to CanChangeMatrix, or to Tpetra Row Matrix), reverting to full construction"
303 if (!reusePreconditioner) {
304 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
306 bool isBlockedMatrix =
false;
307 RCP<Matrix> merged2Mat;
309 std::string sublistName =
"subdomain solver parameters";
310 if (paramList.isSublist(sublistName)) {
319 ParameterList& subList = paramList.sublist(sublistName);
321 std::string partName =
"partitioner: type";
327 if (subList.isParameter(partName) && subList.get<std::string>(partName) ==
"vanka user") {
328 isBlockedMatrix =
true;
330 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
332 "Matrix A must be of type BlockedCrsMatrix.");
334 size_t numVels = bA->getMatrix(0, 0)->getLocalNumRows();
335 size_t numPres = bA->getMatrix(1, 0)->getLocalNumRows();
336 size_t numRows = rcp_dynamic_cast<Matrix>(A_,
true)->getLocalNumRows();
338 ArrayRCP<LocalOrdinal> blockSeeds(numRows, Teuchos::OrdinalTraits<LocalOrdinal>::invalid());
340 size_t numBlocks = 0;
341 for (
size_t rowOfB = numVels; rowOfB < numVels + numPres; ++rowOfB)
342 blockSeeds[rowOfB] = numBlocks++;
344 RCP<BlockedCrsMatrix> bA2 = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
346 "Matrix A must be of type BlockedCrsMatrix.");
348 merged2Mat = bA2->Merge();
352 bool haveBoundary =
false;
353 for (LO i = 0; i < boundaryNodes.size(); i++)
354 if (boundaryNodes[i]) {
358 blockSeeds[i] = numBlocks;
364 subList.set(
"partitioner: type",
"user");
365 subList.set(
"partitioner: map", blockSeeds);
366 subList.set(
"partitioner: local parts", as<int>(numBlocks));
369 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
371 isBlockedMatrix =
true;
372 merged2Mat = bA->Merge();
377 RCP<const tRowMatrix> tA;
378 if (isBlockedMatrix ==
true)
379 tA = Xpetra::toTpetraRowMatrix(merged2Mat);
381 tA = Xpetra::toTpetraRowMatrix(A_);
392template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
394 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
396 if (this->IsSetup() ==
true) {
397 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupAggregate(): Setup() has already been called" << std::endl;
398 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupAggregate(): reuse of this type is not available, reverting to full construction" << std::endl;
401 this->GetOStream(
Statistics0) <<
"Ifpack2Smoother: Using Aggregate Smoothing" << std::endl;
403 RCP<Aggregates> aggregates = Factory::Get<RCP<Aggregates>>(currentLevel,
"Aggregates");
405 RCP<const LOMultiVector> vertex2AggId = aggregates->GetVertex2AggId();
406 ArrayRCP<LO> aggregate_ids = rcp_const_cast<LOMultiVector>(vertex2AggId)->getDataNonConst(0);
407 ArrayRCP<LO> dof_ids;
411 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_);
413 blocksize = matA->GetFixedBlockSize();
415 dof_ids.resize(aggregate_ids.size() * blocksize);
416 for (LO i = 0; i < (LO)aggregate_ids.size(); i++) {
417 for (LO j = 0; j < (LO)blocksize; j++)
418 dof_ids[i * blocksize + j] = aggregate_ids[i];
421 dof_ids = aggregate_ids;
424 paramList.set(
"partitioner: map", dof_ids);
425 paramList.set(
"partitioner: type",
"user");
426 paramList.set(
"partitioner: overlap", 0);
427 paramList.set(
"partitioner: local parts", (
int)aggregates->GetNumAggregates());
429 RCP<const Tpetra::RowMatrix<SC, LO, GO, NO>> tA = Xpetra::toTpetraRowMatrix(A_);
431 type_ =
"BLOCKRELAXATION";
438#ifdef HAVE_MUELU_INTREPID2
439template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
449 if (this->IsSetup() ==
true) {
450 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupTopological(): Setup() has already been called" << std::endl;
451 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupTopological(): reuse of this type is not available, reverting to full construction" << std::endl;
454 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
456 typedef typename Node::device_type::execution_space ES;
458 typedef Kokkos::DynRankView<LocalOrdinal, typename Node::device_type> FCO;
460 LocalOrdinal lo_invalid = Teuchos::OrdinalTraits<LO>::invalid();
464 const Teuchos::RCP<FCO> elemToNode = Factory::Get<Teuchos::RCP<FCO>>(currentLevel,
"pcoarsen: element to node map");
466 string basisString = paramList.get<
string>(
"pcoarsen: hi basis");
472 auto basis = MueLuIntrepid::BasisFactory<double, ES>(basisString, degree);
474 string topologyTypeString = paramList.get<
string>(
"smoother: neighborhood type");
476 if (topologyTypeString ==
"node")
478 else if (topologyTypeString ==
"edge")
480 else if (topologyTypeString ==
"face")
482 else if (topologyTypeString ==
"cell")
483 dimension = basis->getBaseCellTopology().getDimension();
485 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unrecognized smoother neighborhood type. Supported types are node, edge, face.");
486 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_,
true);
487 vector<vector<LocalOrdinal>> seeds;
492 int myNodeCount = matA->getRowMap()->getLocalNumElements();
493 ArrayRCP<LocalOrdinal> nodeSeeds(myNodeCount, lo_invalid);
494 int localPartitionNumber = 0;
496 nodeSeeds[seed] = localPartitionNumber++;
499 paramList.remove(
"smoother: neighborhood type");
500 paramList.remove(
"pcoarsen: hi basis");
502 paramList.set(
"partitioner: map", nodeSeeds);
503 paramList.set(
"partitioner: type",
"user");
504 paramList.set(
"partitioner: overlap", 1);
505 paramList.set(
"partitioner: local parts",
int(seeds[dimension].size()));
507 RCP<const Tpetra::RowMatrix<SC, LO, GO, NO>> tA = Xpetra::toTpetraRowMatrix(A_);
509 type_ =
"BLOCKRELAXATION";
517template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
519 if (this->IsSetup() ==
true) {
520 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupLineSmoothing(): Setup() has already been called" << std::endl;
521 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupLineSmoothing(): reuse of this type is not available, reverting to full construction" << std::endl;
524 ParameterList& myparamList =
const_cast<ParameterList&
>(this->GetParameterList());
526 LO CoarseNumZLayers = Factory::Get<LO>(currentLevel,
"CoarseNumZLayers");
527 if (CoarseNumZLayers > 0) {
528 Teuchos::ArrayRCP<LO> TVertLineIdSmoo = Factory::Get<Teuchos::ArrayRCP<LO>>(currentLevel,
"LineDetection_VertLineIds");
532 for (
size_t k = 0; k < Teuchos::as<size_t>(TVertLineIdSmoo.size()); k++) {
533 if (maxPart < TVertLineIdSmoo[k]) maxPart = TVertLineIdSmoo[k];
535 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_,
true);
536 size_t numLocalRows = matA->getLocalNumRows();
539 "MueLu::Ifpack2Smoother::Setup(): the number of local nodes is incompatible with the TVertLineIdsSmoo.");
544 int actualDofsPerNode = numLocalRows / TVertLineIdSmoo.size();
545 LO matrixBlockSize = matA->GetFixedBlockSize();
546 if (matrixBlockSize > 1 && actualDofsPerNode > 1) {
548 "MueLu::Ifpack2Smoother::Setup(): A is a block matrix but its block size and DOFs/node from partitioner disagree");
549 }
else if (matrixBlockSize > 1) {
550 actualDofsPerNode = matrixBlockSize;
552 myparamList.set(
"partitioner: PDE equations", actualDofsPerNode);
554 if (numLocalRows == Teuchos::as<size_t>(TVertLineIdSmoo.size())) {
555 myparamList.set(
"partitioner: type",
"user");
556 myparamList.set(
"partitioner: map", TVertLineIdSmoo);
557 myparamList.set(
"partitioner: local parts", maxPart + 1);
559 if (myparamList.isParameter(
"partitioner: block size") &&
560 myparamList.get<
int>(
"partitioner: block size") != -1) {
561 int block_size = myparamList.get<
int>(
"partitioner: block size");
563 "MueLu::Ifpack2Smoother::Setup(): the number of local nodes is incompatible with the specified block size.");
564 numLocalRows /= block_size;
568 size_t numDofsPerNode = numLocalRows / TVertLineIdSmoo.size();
571 Teuchos::ArrayRCP<LO> partitionerMap(numLocalRows, Teuchos::OrdinalTraits<LocalOrdinal>::invalid());
572 for (
size_t blockRow = 0; blockRow < Teuchos::as<size_t>(TVertLineIdSmoo.size()); ++blockRow)
573 for (
size_t dof = 0; dof < numDofsPerNode; dof++)
574 partitionerMap[blockRow * numDofsPerNode + dof] = TVertLineIdSmoo[blockRow];
575 myparamList.set(
"partitioner: type",
"user");
576 myparamList.set(
"partitioner: map", partitionerMap);
577 myparamList.set(
"partitioner: local parts", maxPart + 1);
580 if (type_ ==
"LINESMOOTHING_BANDED_RELAXATION" ||
581 type_ ==
"LINESMOOTHING_BANDED RELAXATION" ||
582 type_ ==
"LINESMOOTHING_BANDEDRELAXATION")
583 type_ =
"BANDEDRELAXATION";
584 else if (type_ ==
"LINESMOOTHING_TRIDI_RELAXATION" ||
585 type_ ==
"LINESMOOTHING_TRIDI RELAXATION" ||
586 type_ ==
"LINESMOOTHING_TRIDIRELAXATION" ||
587 type_ ==
"LINESMOOTHING_TRIDIAGONAL_RELAXATION" ||
588 type_ ==
"LINESMOOTHING_TRIDIAGONAL RELAXATION" ||
589 type_ ==
"LINESMOOTHING_TRIDIAGONALRELAXATION")
590 type_ =
"TRIDIAGONALRELAXATION";
592 type_ =
"BLOCKRELAXATION";
595 this->GetOStream(
Runtime0) <<
"Line detection failed: fall back to point-wise relaxation" << std::endl;
596 myparamList.remove(
"partitioner: type",
false);
597 myparamList.remove(
"partitioner: map",
false);
598 myparamList.remove(
"partitioner: local parts",
false);
599 type_ =
"RELAXATION";
602 RCP<const Tpetra::RowMatrix<SC, LO, GO, NO>> tA = Xpetra::toTpetraRowMatrix(A_);
610template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
612 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
614 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
618 RCP<const tRowMatrix> tA = Xpetra::toTpetraRowMatrix(A_);
620 bool reusePreconditioner =
false;
621 if (this->IsSetup() ==
true) {
623 this->GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupBlockRelaxation(): Setup() has already been called, assuming reuse" << std::endl;
625 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(prec_);
626 if (!prec.is_null()) {
628 reusePreconditioner =
true;
630 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupBlockRelaxation(): reuse of this type is not available (failed cast to CanChangeMatrix), "
631 "reverting to full construction"
636 if (!reusePreconditioner) {
637 ParameterList& myparamList =
const_cast<ParameterList&
>(this->GetParameterList());
639 if (myparamList.isParameter(
"partitioner: type") &&
640 myparamList.get<std::string>(
"partitioner: type") ==
"line") {
641 Teuchos::RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>> xCoordinates =
642 Factory::Get<Teuchos::RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType, LO, GO, NO>>>(currentLevel,
"Coordinates");
643 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));
645 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_);
646 size_t lclSize = A_->getRangeMap()->getLocalNumElements();
648 lclSize = matA->getLocalNumRows();
649 size_t numDofsPerNode = lclSize / xCoordinates->getMap()->getLocalNumElements();
650 myparamList.set(
"partitioner: coordinates", coordinates);
651 myparamList.set(
"partitioner: PDE equations", (
int)numDofsPerNode);
662template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
664 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
665 using STS = Teuchos::ScalarTraits<SC>;
666 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
670 RCP<const tRowMatrix> tA = Xpetra::toTpetraRowMatrix(A_);
672 bool reusePreconditioner =
false;
674 if (this->IsSetup() ==
true) {
676 this->GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupChebyshev(): Setup() has already been called, assuming reuse" << std::endl;
678 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(prec_);
679 if (!prec.is_null()) {
681 reusePreconditioner =
true;
683 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupChebyshev(): reuse of this type is not available (failed cast to CanChangeMatrix), "
684 "reverting to full construction"
690 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
691 SC negone = -STS::one();
692 SC lambdaMax = SetupChebyshevEigenvalues(currentLevel,
"A",
"", paramList);
694 if (!reusePreconditioner) {
709 if (lambdaMax == negone) {
710 typedef Tpetra::RowMatrix<SC, LO, GO, NO> MatrixType;
712 Teuchos::RCP<Ifpack2::Chebyshev<MatrixType>> chebyPrec = rcp_dynamic_cast<Ifpack2::Chebyshev<MatrixType>>(prec_);
713 if (chebyPrec != Teuchos::null) {
714 lambdaMax = chebyPrec->getLambdaMaxForApply();
715 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_);
717 matA->SetMaxEigenvalueEstimate(lambdaMax);
718 this->GetOStream(
Statistics1) <<
"chebyshev: max eigenvalue (calculated by Ifpack2)"
719 <<
" = " << lambdaMax << std::endl;
721 TEUCHOS_TEST_FOR_EXCEPTION(lambdaMax == negone,
Exceptions::RuntimeError,
"MueLu::Ifpack2Smoother::Setup(): no maximum eigenvalue estimate");
725template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
727 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
728 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
732 RCP<const tRowMatrix> tA = Xpetra::toTpetraRowMatrix(A_);
734 bool reusePreconditioner =
false;
735 if (this->IsSetup() ==
true) {
737 this->GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupHiptmair(): Setup() has already been called, assuming reuse" << std::endl;
739 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(prec_);
740 if (!prec.is_null()) {
742 reusePreconditioner =
true;
744 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupHiptmair(): reuse of this type is not available (failed cast to CanChangeMatrix), "
745 "reverting to full construction"
751 SC negone = -Teuchos::ScalarTraits<Scalar>::one();
752 ParameterList& paramList =
const_cast<ParameterList&
>(this->GetParameterList());
753 std::string smoother1 = paramList.get(
"hiptmair: smoother type 1",
"CHEBYSHEV");
754 std::string smoother2 = paramList.get(
"hiptmair: smoother type 2",
"CHEBYSHEV");
755 SC lambdaMax11 = negone;
757 if (smoother1 ==
"CHEBYSHEV") {
758 ParameterList& list1 = paramList.sublist(
"hiptmair: smoother list 1");
759 lambdaMax11 = SetupChebyshevEigenvalues(currentLevel,
"A",
"EdgeMatrix ", list1);
761 if (smoother2 ==
"CHEBYSHEV") {
762 ParameterList& list2 = paramList.sublist(
"hiptmair: smoother list 2");
763 SetupChebyshevEigenvalues(currentLevel,
"NodeMatrix",
"NodeMatrix ", list2);
770 RCP<Operator> NodeMatrix = currentLevel.
Get<RCP<Operator>>(
"NodeMatrix");
771 RCP<Operator> D0 = currentLevel.
Get<RCP<Operator>>(
"D0");
773 RCP<tRowMatrix> tNodeMatrix = Xpetra::toTpetraRowMatrix(NodeMatrix);
774 RCP<tRowMatrix> tD0 = Xpetra::toTpetraRowMatrix(D0);
776 Teuchos::ParameterList newlist;
777 newlist.set(
"P", tD0);
778 newlist.set(
"PtAP", tNodeMatrix);
779 if (!reusePreconditioner) {
781 SetPrecParameters(newlist);
788 if (smoother1 ==
"CHEBYSHEV" && lambdaMax11 == negone) {
789 using Teuchos::rcp_dynamic_cast;
790 typedef Tpetra::RowMatrix<SC, LO, GO, NO> MatrixType;
791 auto hiptmairPrec = rcp_dynamic_cast<Ifpack2::Hiptmair<MatrixType>>(prec_);
792 if (hiptmairPrec != Teuchos::null) {
793 auto chebyPrec = rcp_dynamic_cast<Ifpack2::Chebyshev<MatrixType>>(hiptmairPrec->getPrec1());
794 if (chebyPrec != Teuchos::null) {
795 lambdaMax11 = chebyPrec->getLambdaMaxForApply();
796 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(A_);
798 matA->SetMaxEigenvalueEstimate(lambdaMax11);
799 this->GetOStream(
Statistics1) <<
"chebyshev: max eigenvalue (calculated by Ifpack2)"
800 <<
" = " << lambdaMax11 << std::endl;
802 TEUCHOS_TEST_FOR_EXCEPTION(lambdaMax11 == negone,
Exceptions::RuntimeError,
"MueLu::Ifpack2Smoother::Setup(): no maximum eigenvalue estimate");
807template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
810 typedef Teuchos::ScalarTraits<SC> STS;
811 SC negone = -STS::one();
812 RCP<Operator> currentA = currentLevel.
Get<RCP<Operator>>(matrixName);
813 RCP<Matrix> matA = rcp_dynamic_cast<Matrix>(currentA);
814 SC lambdaMax = negone;
816 std::string maxEigString =
"chebyshev: max eigenvalue";
817 std::string eigRatioString =
"chebyshev: ratio eigenvalue";
820 if (paramList.isParameter(maxEigString)) {
821 if (paramList.isType<
double>(maxEigString))
822 lambdaMax = paramList.get<
double>(maxEigString);
824 lambdaMax = paramList.get<SC>(maxEigString);
825 this->GetOStream(
Statistics1) << label << maxEigString <<
" (cached with smoother parameter list) = " << lambdaMax << std::endl;
827 matA->SetMaxEigenvalueEstimate(lambdaMax);
829 }
else if (!matA.is_null()) {
830 lambdaMax = matA->GetMaxEigenvalueEstimate();
831 if (lambdaMax != negone) {
832 this->GetOStream(
Statistics1) << label << maxEigString <<
" (cached with matrix) = " << lambdaMax << std::endl;
833 paramList.set(maxEigString, lambdaMax);
838 const SC defaultEigRatio = 20;
840 SC ratio = defaultEigRatio;
841 if (paramList.isParameter(eigRatioString)) {
842 if (paramList.isType<
double>(eigRatioString))
843 ratio = paramList.get<
double>(eigRatioString);
845 ratio = paramList.get<SC>(eigRatioString);
852 RCP<const Operator> fineA = currentLevel.
GetPreviousLevel()->Get<RCP<Operator>>(matrixName);
853 size_t nRowsFine = fineA->getDomainMap()->getGlobalNumElements();
854 size_t nRowsCoarse = currentA->getDomainMap()->getGlobalNumElements();
856 SC levelRatio = as<SC>(as<double>(nRowsFine) / nRowsCoarse);
857 if (STS::magnitude(levelRatio) > STS::magnitude(ratio))
861 this->GetOStream(
Statistics1) << label << eigRatioString <<
" (computed) = " << ratio << std::endl;
862 paramList.set(eigRatioString, ratio);
864 if (paramList.isParameter(
"chebyshev: use rowsumabs diagonal scaling")) {
865 this->GetOStream(
Runtime1) <<
"chebyshev: using rowsumabs diagonal scaling" << std::endl;
866 bool doScale =
false;
867 doScale = paramList.get<
bool>(
"chebyshev: use rowsumabs diagonal scaling");
868 paramList.remove(
"chebyshev: use rowsumabs diagonal scaling");
869 double chebyReplaceTol = Teuchos::ScalarTraits<Scalar>::eps() * 100;
870 std::string paramName =
"chebyshev: rowsumabs diagonal replacement tolerance";
871 if (paramList.isParameter(paramName)) {
872 chebyReplaceTol = paramList.get<
double>(paramName);
873 paramList.remove(paramName);
875 double chebyReplaceVal = Teuchos::ScalarTraits<double>::zero();
876 paramName =
"chebyshev: rowsumabs diagonal replacement value";
877 if (paramList.isParameter(paramName)) {
878 chebyReplaceVal = paramList.get<
double>(paramName);
879 paramList.remove(paramName);
881 bool chebyReplaceSingleEntryRowWithZero =
false;
882 paramName =
"chebyshev: rowsumabs replace single entry row with zero";
883 if (paramList.isParameter(paramName)) {
884 chebyReplaceSingleEntryRowWithZero = paramList.get<
bool>(paramName);
885 paramList.remove(paramName);
887 bool useAverageAbsDiagVal =
false;
888 paramName =
"chebyshev: rowsumabs use automatic diagonal tolerance";
889 if (paramList.isParameter(paramName)) {
890 useAverageAbsDiagVal = paramList.get<
bool>(paramName);
891 paramList.remove(paramName);
894 TEUCHOS_ASSERT(!matA.is_null());
895 const bool doReciprocal =
true;
896 RCP<Vector> lumpedDiagonal =
Utilities::GetLumpedMatrixDiagonal(*matA, doReciprocal, chebyReplaceTol, chebyReplaceVal, chebyReplaceSingleEntryRowWithZero, useAverageAbsDiagVal);
897 const Xpetra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& tmpVec =
dynamic_cast<const Xpetra::TpetraVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>&
>(*lumpedDiagonal);
898 paramList.set(
"chebyshev: operator inv diagonal", tmpVec.getTpetra_Vector());
905template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
907 typedef Tpetra::RowMatrix<SC, LO, GO, NO> tRowMatrix;
908 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A_);
912 RCP<const tRowMatrix> tA = Xpetra::toTpetraRowMatrix(A_);
914 bool reusePreconditioner =
false;
915 if (this->IsSetup() ==
true) {
917 this->GetOStream(
Runtime1) <<
"MueLu::Ifpack2Smoother::SetupGeneric(): Setup() has already been called, assuming reuse" << std::endl;
919 RCP<Ifpack2::Details::CanChangeMatrix<tRowMatrix>> prec = rcp_dynamic_cast<Ifpack2::Details::CanChangeMatrix<tRowMatrix>>(prec_);
920 if (!prec.is_null()) {
922 reusePreconditioner =
true;
924 this->GetOStream(
Warnings0) <<
"MueLu::Ifpack2Smoother::SetupGeneric(): reuse of this type is not available (failed cast to CanChangeMatrix), "
925 "reverting to full construction"
930 if (!reusePreconditioner) {
939template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
949 bool supportInitialGuess =
false;
951 if (prec_->supportsZeroStartingSolution()) {
952 prec_->setZeroStartingSolution(InitialGuessIsZero);
953 supportInitialGuess =
true;
954 }
else if (type_ ==
"SCHWARZ") {
955 Teuchos::ParameterList paramList;
956 paramList.set(
"schwarz: zero starting solution", InitialGuessIsZero);
961 prec_->setParameters(paramList);
962 supportInitialGuess =
true;
972 if (InitialGuessIsZero || supportInitialGuess) {
973 Tpetra::MultiVector<SC, LO, GO, NO>& tpX = toTpetra(X);
974 const Tpetra::MultiVector<SC, LO, GO, NO>& tpB = toTpetra(B);
975 prec_->apply(tpB, tpX);
977 using TST = Teuchos::ScalarTraits<Scalar>;
979 RCP<MultiVector> Residual;
981 std::string prefix = this->ShortClassName() +
": Apply: ";
982 RCP<TimeMonitor> tM = rcp(
new TimeMonitor(*
this, prefix +
"residual calculation",
Timings0));
986 RCP<MultiVector> Correction = MultiVectorFactory::Build(A_->getDomainMap(), X.getNumVectors());
988 Tpetra::MultiVector<SC, LO, GO, NO>& tpX = toTpetra(*Correction);
989 const Tpetra::MultiVector<SC, LO, GO, NO>& tpB = toTpetra(*Residual);
991 prec_->apply(tpB, tpX);
993 X.update(TST::one(), *Correction, TST::one());
997template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1000 smoother->SetParameterList(this->GetParameterList());
1004template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1006 std::ostringstream out;
1008 out << prec_->description();
1011 out <<
"{type = " << type_ <<
"}";
1016template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1021 out0 <<
"Prec. type: " << type_ << std::endl;
1024 out0 <<
"Parameter list: " << std::endl;
1025 Teuchos::OSTab tab2(out);
1026 out << this->GetParameterList();
1027 out0 <<
"Overlap: " << overlap_ << std::endl;
1031 if (prec_ != Teuchos::null) {
1032 Teuchos::OSTab tab2(out);
1033 out << *prec_ << std::endl;
1036 if (verbLevel &
Debug) {
1039 <<
"RCP<prec_>: " << prec_ << std::endl;
1043template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1045 typedef Tpetra::RowMatrix<SC, LO, GO, NO> MatrixType;
1047 RCP<Ifpack2::Relaxation<MatrixType>> pr = rcp_dynamic_cast<Ifpack2::Relaxation<MatrixType>>(prec_);
1048 if (!pr.is_null())
return pr->getNodeSmootherComplexity();
1050 RCP<Ifpack2::Chebyshev<MatrixType>> pc = rcp_dynamic_cast<Ifpack2::Chebyshev<MatrixType>>(prec_);
1051 if (!pc.is_null())
return pc->getNodeSmootherComplexity();
1053 RCP<Ifpack2::BlockRelaxation<MatrixType>> pb = rcp_dynamic_cast<Ifpack2::BlockRelaxation<MatrixType>>(prec_);
1054 if (!pb.is_null())
return pb->getNodeSmootherComplexity();
1056 RCP<Ifpack2::ILUT<MatrixType>> pi = rcp_dynamic_cast<Ifpack2::ILUT<MatrixType>>(prec_);
1057 if (!pi.is_null())
return pi->getNodeSmootherComplexity();
1059 RCP<Ifpack2::RILUK<MatrixType>> pk = rcp_dynamic_cast<Ifpack2::RILUK<MatrixType>>(prec_);
1060 if (!pk.is_null())
return pk->getNodeSmootherComplexity();
1062 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 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.
Class that encapsulates Ifpack2 smoothers.
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)
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.
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 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, LocalOrdinal, GlobalOrdinal, Node > &A, const Magnitude &tol=Teuchos::ScalarTraits< Magnitude >::zero(), bool count_twos_as_dirichlet=false)
Detect Dirichlet rows.
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.
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
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)
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)