10#ifndef MUELU_MAXWELL1_DEF_HPP
11#define MUELU_MAXWELL1_DEF_HPP
18#include "Xpetra_CrsMatrixWrap_decl.hpp"
19#include "Xpetra_Map.hpp"
21#include "Xpetra_MatrixUtils.hpp"
24#include "MueLu_Maxwell_Utils.hpp"
26#include "MueLu_ReitzingerPFactory.hpp"
27#include "MueLu_Utilities.hpp"
29#include "MueLu_Hierarchy.hpp"
30#include "MueLu_RAPFactory.hpp"
31#include "MueLu_RebalanceAcFactory.hpp"
32#include "MueLu_RebalanceTransferFactory.hpp"
34#include "MueLu_PerfUtils.hpp"
35#include "MueLu_ParameterListInterpreter.hpp"
36#include "MueLu_HierarchyManager.hpp"
37#include <MueLu_HierarchyUtils.hpp>
41#include <MueLu_RefMaxwellSmoother.hpp>
45#include "cuda_profiler_api.h"
50template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
55template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
60template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
62 if (list.isType<std::string>(
"parameterlist: syntax") && list.get<std::string>(
"parameterlist: syntax") ==
"ml") {
72 Teuchos::ParameterList defaultSmootherList;
73 defaultSmootherList.set(
"smoother: type",
"CHEBYSHEV");
74 defaultSmootherList.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
75 defaultSmootherList.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 7.0);
76 defaultSmootherList.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
79 std::string verbosity = list.get(
"verbosity",
"high");
84 if (mode_string ==
"standard")
86 else if (mode_string ==
"refmaxwell")
88 else if (mode_string ==
"edge only")
91 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Must use mode 'standard', 'refmaxwell', 'edge only', or use the GMHD constructor.");
97 if (list.isSublist(
"maxwell1: 22list"))
99 else if (list.isSublist(
"refmaxwell: 22list"))
103 else if (!
precList22_.isType<std::string>(
"Preconditioner Type") &&
104 !
precList22_.isType<std::string>(
"smoother: type") &&
105 !
precList22_.isType<std::string>(
"smoother: pre type") &&
106 !
precList22_.isType<std::string>(
"smoother: post type")) {
113 if (list.isSublist(
"maxwell1: 11list"))
115 else if (list.isSublist(
"refmaxwell: 11list"))
122 if (!
precList11_.isType<std::string>(
"Preconditioner Type") &&
123 !
precList11_.isType<std::string>(
"smoother: type") &&
124 !
precList11_.isType<std::string>(
"smoother: pre type") &&
125 !
precList11_.isType<std::string>(
"smoother: post type")) {
131 precList11_.set(
"hiptmair: smoother type 1",
"CHEBYSHEV");
132 precList11_.set(
"hiptmair: smoother type 2",
"CHEBYSHEV");
133 precList11_.sublist(
"hiptmair: smoother list 1") = defaultSmootherList;
134 precList11_.sublist(
"hiptmair: smoother list 2") = defaultSmootherList;
141 !
precList11_.isType<std::string>(
"Preconditioner Type") &&
145 !
precList22_.isType<std::string>(
"Preconditioner Type") &&
156template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
158 Teuchos::ParameterList precListGmhd;
165 TEUCHOS_TEST_FOR_EXCEPTION(!List.isSublist(
"maxwell1: Gmhdlist"),
Exceptions::RuntimeError,
"Must provide maxwell1: Gmhdlist for GMHD setup");
166 precListGmhd = List.sublist(
"maxwell1: Gmhdlist");
167 precListGmhd.set(
"coarse: max size", 1);
175template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
189#ifdef HAVE_MUELU_CUDA
190 if (
parameterList_.get<
bool>(
"maxwell1: cuda profile setup",
false)) cudaProfilerStart();
193 std::string timerLabel;
195 timerLabel =
"MueLu Maxwell1: compute (reuse)";
197 timerLabel =
"MueLu Maxwell1: compute";
198 RCP<Teuchos::TimeMonitor> tmCompute =
getTimer(timerLabel);
202 bool have_generated_Kn =
false;
205 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Kn not provided. Generating." << std::endl;
207 have_generated_Kn =
true;
208 }
else if (
parameterList_.get<
bool>(
"rap: fix zero diagonals",
true)) {
212 Teuchos::ScalarTraits<double>::eps());
214 threshold = Teuchos::as<magnitudeType>(
parameterList_.get<
double>(
"rap: fix zero diagonals threshold",
215 Teuchos::ScalarTraits<double>::eps()));
216 Scalar replacement = Teuchos::as<Scalar>(
parameterList_.get<
double>(
"rap: fix zero diagonals replacement",
241 auto algo11 =
precList11_.get<std::string>(
"multigrid algorithm");
242 auto algo22 =
precList22_.get<std::string>(
"multigrid algorithm");
256 if (algo11 ==
"unsmoothed reitzinger") {
257 TEUCHOS_ASSERT(algo22 ==
"unsmoothed");
258 }
else if (algo11 ==
"smoothed reitzinger") {
259 TEUCHOS_ASSERT((algo22 ==
"unsmoothed") || (algo22 ==
"sa"));
262 if (algo22 ==
"sa") {
265 if (
precList22_.isType<
double>(
"sa: damping factor")) {
266 nodalDamping =
precList22_.get<
double>(
"sa: damping factor");
270 precList11_.set(
"sa: nodal damping factor", nodalDamping);
271 }
else if (algo22 ==
"unsmoothed")
274 if (algo11 ==
"smoothed reitzinger") {
278 if (
precList11_.isType<
bool>(
"sa: use edge matrix for smoothing"))
279 useEdgeMatrixForSmoothing =
precList11_.get<
bool>(
"sa: use edge matrix for smoothing");
280 if (!
precList11_.sublist(
"user data").isParameter(
"CurlCurl")) {
281 if (
precList11_.isType<
double>(
"sa: damping factor")) {
282 double edgeDamping =
precList11_.get<
double>(
"sa: damping factor");
283 if (edgeDamping != 0) {
284 if (!useEdgeMatrixForSmoothing) {
285 GetOStream(
Warnings0) <<
"\"sa: damping factor\" in \"maxwell1: 11list\" is set to " << std::to_string(edgeDamping) <<
", but no CurlCurl matrix has been passed in \"user data\". Switching off edge-only damping. Set \"sa: use edge matrix for smoothing\" = true in the \"maxwell1: 11list\" to use the edge matrix." << std::endl;
288 GetOStream(
Warnings0) <<
"\"sa: damping factor\" in \"maxwell1: 11list\" is set to " << std::to_string(edgeDamping) <<
". Using the edge matrix for smoothing and violating the commuting relationship." << std::endl;
291 if (!useEdgeMatrixForSmoothing) {
292 GetOStream(
Warnings0) <<
"\"sa: damping factor\" in \"maxwell1: 11list\" is nonzero by default, but no CurlCurl matrix has been passed in \"user data\". Switching off edge-only damping." << std::endl;
295 GetOStream(
Warnings0) <<
"\"sa: damping factor\" in \"maxwell1: 11list\" is nonzero by default. Using the edge matrix for smoothing and violating the commuting relationship." << std::endl;
300 if (!
precList22_.isParameter(
"tentative: constant column sums"))
301 precList22_.set(
"tentative: constant column sums",
false);
302 else if (
precList22_.get<
bool>(
"tentative: constant column sums") !=
false)
303 GetOStream(
Warnings0) <<
"\"tentative: constant column sums\" is set to \"true\". There is no guarantee that this will work." << std::endl;
305 if (!
precList22_.isParameter(
"tentative: calculate qr"))
307 else if (
precList22_.get<
bool>(
"tentative: calculate qr") !=
false)
308 GetOStream(
Warnings0) <<
"\"tentative: calculate qr\" is set to \"true\". There is no guarantee that this will work." << std::endl;
311 if (((
parameterList_.sublist(
"maxwell1: 11list").template get<std::string>(
"multigrid algorithm") ==
"smoothed reitzinger") || (
parameterList_.sublist(
"maxwell1: 11list").template get<std::string>(
"multigrid algorithm") ==
"emin reitzinger")) &&
312 (!
precList22_.isParameter(
"sa: keep tentative prolongator") || !
precList22_.get<
bool>(
"sa: keep tentative prolongator")))
313 precList22_.set(
"sa: keep tentative prolongator",
true);
317 if (
precList22_.isParameter(
"repartition: enable")) {
318 bool repartition =
precList22_.get<
bool>(
"repartition: enable");
319 precList11_.set(
"repartition: enable", repartition);
324 if (!
precList22_.isParameter(
"repartition: save importer"))
325 precList22_.set(
"repartition: save importer",
true);
326 else if (!
precList22_.get<
bool>(
"repartition: save importer")) {
327 GetOStream(
Warnings0) <<
"\"repartition: save importer\" is set to false, but it is required to be true. Changing it." << std::endl;
328 precList22_.set(
"repartition: save importer",
true);
331 if (!
precList22_.isParameter(
"repartition: rebalance P and R"))
332 precList22_.set(
"repartition: rebalance P and R",
true);
333 else if (!
precList22_.get<
bool>(
"repartition: rebalance P and R")) {
334 GetOStream(
Warnings0) <<
"\"repartition: rebalance P and R\" is set to false, but it is required to be true. Changing it." << std::endl;
335 precList22_.set(
"repartition: rebalance P and R",
true);
338 if (!
precList22_.isParameter(
"repartition: use subcommunicators"))
339 precList22_.set(
"repartition: use subcommunicators",
true);
340 else if (!
precList22_.get<
bool>(
"repartition: use subcommunicators")) {
341 GetOStream(
Warnings0) <<
"\"repartition: use subcommunicators\" is set to false, but it is required to be true. Changing it." << std::endl;
342 precList22_.set(
"repartition: use subcommunicators",
true);
346 if (
precList22_.isParameter(
"repartition: use subcommunicators")) {
347 precList11_.set(
"repartition: use subcommunicators",
precList22_.get<
bool>(
"repartition: use subcommunicators"));
351 if (
precList11_.get<
bool>(
"repartition: use subcommunicators") ==
true)
352 precList11_.set(
"repartition: use subcommunicators in place",
true);
355 precList11_.set(
"repartition: use subcommunicators",
true);
356 precList22_.set(
"repartition: use subcommunicators",
true);
360 precList11_.set(
"repartition: use subcommunicators in place",
true);
373 RCP<ParameterList> params = rcp(
new ParameterList());
375 params->set(
"printLoadBalancingInfo",
true);
376 params->set(
"printCommInfo",
true);
421 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
424 GetOStream(
Runtime0) <<
"Maxwell1::compute(): nuking BC rows/cols of D0" << std::endl;
449 RCP<Matrix> Kn_Smoother_0;
450 if (have_generated_Kn) {
459 RCP<Matrix> OldSmootherMatrix;
460 RCP<Level> OldEdgeLevel;
461 for (
int i = 0; i <
Hierarchy22_->GetNumLevels(); i++) {
465 RCP<Operator> NodeAggOp = NodeL->Get<RCP<Operator>>(
"A");
466 RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(NodeAggOp);
473 EdgeL->Set(
"NodeAggMatrix", NodeAggMatrix);
474 EdgeL->Set(
"NodeMatrix", Kn_Smoother_0);
475 OldSmootherMatrix = Kn_Smoother_0;
476 OldEdgeLevel = EdgeL;
479 auto NodalP = NodeL->Get<RCP<Matrix>>(
"P");
486 RCP<const Import> importer;
487 if (NodeL->IsAvailable(
"Importer")) {
488 importer = NodeL->Get<RCP<const Import>>(
"Importer");
489 EdgeL->Set(
"NodeImporter", importer);
493 RCP<Matrix> NodalPtent;
494 if (
parameterList_.sublist(
"maxwell1: 22list").template get<std::string>(
"multigrid algorithm") ==
"unsmoothed")
495 NodalPtent = NodeL->Get<RCP<Matrix>>(
"P");
497 NodalPtent = NodeL->Get<RCP<Matrix>>(
"Ptent");
499 if (!importer.is_null()) {
510 ParameterList rebalTransferParams;
511 rebalTransferParams.set(
"repartition: rebalance P and R",
true);
512 rebalTransferParams.set(
"type",
"Interpolation");
513 rebalTransfer->SetParameterList(rebalTransferParams);
514 coarseLevel.
Set(
"P", NodalPtent);
515 coarseLevel.
Set(
"Importer", importer);
516 rebalTransfer->Build(fineLevel, coarseLevel);
517 NodalPtent = coarseLevel.
Get<RCP<Matrix>>(
"P");
522 TEUCHOS_TEST_FOR_EXCEPTION(P_for_RS_construction.is_null(),
Exceptions::RuntimeError,
"Applying ones to prolongator failed");
525 EdgeL->Set(
"Pnodal", P_for_RS_construction);
527 if (
parameterList_.sublist(
"maxwell1: 11list").template get<std::string>(
"multigrid algorithm") ==
"emin reitzinger") {
530 EdgeL->Set(
"PnodalEmin", NodalP);
535 if (!OldSmootherMatrix.is_null() && !P_for_RS_construction.is_null()) {
536 EdgeL->Set(
"NodeAggMatrix", NodeAggMatrix);
537 if (!have_generated_Kn) {
547 Teuchos::ParameterList RAPlist;
548 RAPlist.set(
"rap: fix zero diagonals",
false);
552 if (!importer.is_null()) {
553 ParameterList rebAcParams;
554 rebAcParams.set(
"repartition: use subcommunicators",
true);
555 rebAcParams.set(
"repartition: use subcommunicators in place",
true);
557 newAfact->SetParameterList(rebAcParams);
558 RCP<const Map> InPlaceMap = NodeAggMatrix.is_null() ? Teuchos::null : NodeAggMatrix->getRowMap();
560 Level fLevel, cLevel;
562 cLevel.
Set(
"InPlaceMap", InPlaceMap);
563 cLevel.
Set(
"A", NewKn);
564 cLevel.
Request(
"A", newAfact.get());
565 newAfact->Build(fLevel, cLevel);
567 NewKn = cLevel.
Get<RCP<Matrix>>(
"A", newAfact.get());
568 EdgeL->Set(
"NodeMatrix", NewKn);
570 EdgeL->Set(
"NodeMatrix", NewKn);
574 double thresh =
parameterList_.get(
"maxwell1: nodal smoother fix zero diagonal threshold", 1e-10);
576 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Fixing zero diagonal for nodal smoother matrix" << std::endl;
577 Scalar replacement = Teuchos::ScalarTraits<Scalar>::one();
578 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(OldSmootherMatrix,
true,
GetOStream(
Warnings1), thresh, replacement);
580 OldEdgeLevel->Set(
"NodeMatrix", OldSmootherMatrix);
582 OldSmootherMatrix = NewKn;
585 EdgeL->Set(
"NodeMatrix", NodeAggMatrix);
589 EdgeL->Set(
"NodeMatrix", NodeAggOp);
590 EdgeL->Set(
"NodeAggMatrix", NodeAggOp);
593 OldEdgeLevel = EdgeL;
605 const bool refmaxwellCoarseSolve = (
precList11_.get<std::string>(
"coarse: type",
607 if (refmaxwellCoarseSolve) {
608 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Will set up RefMaxwell coarse solver" << std::endl;
613 Teuchos::ParameterList nonSerialList11;
614 Teuchos::ParameterList processedPrecList11;
621 if (nonSerialList11.numParams() > 0) {
626 if (refmaxwellCoarseSolve) {
627 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Setting up RefMaxwell coarse solver" << std::endl;
631 coarseSolver->Setup(*coarseLvl);
632 coarseLvl->Set(
"PreSmoother",
633 rcp_dynamic_cast<SmootherBase>(coarseSolver,
true));
639 P11_ = EdgeL->Get<RCP<Matrix>>(
"P");
651 for (
int i = 1; i <
Hierarchy11_->GetNumLevels(); i++) {
656 auto Pe = EdgeL->template Get<RCP<Matrix>>(
"P");
657 auto Pn = NodeL->template Get<RCP<Matrix>>(
"P");
658 auto D0_f = EdgeL_fine->template Get<RCP<Matrix>>(
"D0");
659 auto D0_c = EdgeL->template Get<RCP<Matrix>>(
"D0");
661 if (!Pe.is_null() && !D0_c.is_null() && (Pe->getRowMap()->getComm()->getSize() == D0_c->getRowMap()->getComm()->getSize())) {
662 using XMM = Xpetra::MatrixMatrix<SC, LO, GO, NO>;
663 auto one = Teuchos::ScalarTraits<SC>::one();
666 RCP<Matrix> left = XMM::Multiply(*Pe,
false, *D0_c,
false, dummy,
GetOStream(
Runtime0));
667 RCP<Matrix> right = XMM::Multiply(*D0_f,
false, *Pn,
false, dummy,
GetOStream(
Runtime0));
669 RCP<Matrix> summation;
670 XMM::TwoMatrixAdd(*left,
false, one, *right,
false, -one, summation,
GetOStream(
Runtime0));
671 summation->fillComplete(left->getDomainMap(), left->getRangeMap());
673 auto norm = summation->getFrobeniusNorm();
674 GetOStream(
Runtime0) <<
"CheckCommutingProperty on level " << i - 1 <<
": || Pe D0_c - D0_f Pn || = " << norm << std::endl;
675 }
else if (!Pe.is_null()) {
676 GetOStream(
Runtime0) <<
"Cannot run CheckCommutingProperty on level " << i - 1 <<
" due to rebalancing" << std::endl;
680#ifdef MUELU_MAXWELL1_DEBUG
682 for (
int i = 0; i <
Hierarchy11_->GetNumLevels(); i++) {
684 RCP<Matrix> EdgeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"A"));
685 RCP<Matrix> NodeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"NodeMatrix"));
686 RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"NodeAggMatrix"));
687 RCP<Matrix> D0 = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"D0"));
689 auto nrmE = EdgeMatrix->getFrobeniusNorm();
690 auto nrmN = NodeMatrix->getFrobeniusNorm();
691 auto nrmNa = NodeAggMatrix->getFrobeniusNorm();
692 auto nrmD0 = D0->getFrobeniusNorm();
694 std::cout <<
"DEBUG: Norms on Level " << i <<
" E/N/NA/D0 = " << nrmE <<
" / " << nrmN <<
" / " << nrmNa <<
" / " << nrmD0 << std::endl;
695 std::cout <<
"DEBUG: NNZ on Level " << i <<
" E/N/NA/D0 = " << EdgeMatrix->getGlobalNumEntries() <<
" / " << NodeMatrix->getGlobalNumEntries() <<
" / " << NodeAggMatrix->getGlobalNumEntries() <<
" / " << D0->getGlobalNumEntries() << std::endl;
700template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
703 Teuchos::ParameterList RAPlist;
704 RAPlist.set(
"rap: fix zero diagonals",
false);
706 std::string labelstr =
"NodeMatrix (Level 0)";
711template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
714 RCP<Teuchos::TimeMonitor> tmAlloc =
getTimer(
"MueLu Maxwell1: Allocate MVs");
720 RCP<Matrix> A = EdgeL->Get<RCP<Matrix>>(
"A");
721 residual11c_ = MultiVectorFactory::Build(A->getRangeMap(), numVectors);
722 update11c_ = MultiVectorFactory::Build(A->getDomainMap(), numVectors);
732template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
736 Xpetra::IO<SC, LO, GO, NO>::Write(name, A);
740template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
744 Xpetra::IO<SC, LO, GO, NO>::Write(name, X);
748template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
752 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, X);
756template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
760 std::ofstream out(name);
761 for (
size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
766template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
770 std::ofstream out(name);
771 auto vH = Kokkos::create_mirror_view(v);
772 Kokkos::deep_copy(vH, v);
773 for (
size_t i = 0; i < vH.size(); i++)
774 out << vH[i] <<
"\n";
778template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
782 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name)));
785 return Teuchos::rcp(
new Teuchos::SyncTimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name),
SM_Matrix_->getRowMap()->getComm().ptr()));
787 return Teuchos::rcp(
new Teuchos::SyncTimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name), comm.ptr()));
790 return Teuchos::null;
793template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
802template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
805 const SC one = Teuchos::ScalarTraits<SC>::one();
813 if (Fine->IsAvailable(
"PreSmoother")) {
814 RCP<Teuchos::TimeMonitor> tmRes =
getTimer(
"MueLu Maxwell1: PreSmoother");
815 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
816 preSmoo->Apply(X, RHS,
true);
821 RCP<Teuchos::TimeMonitor> tmRes =
getTimer(
"MueLu Maxwell1: residual calculation");
826 if (!
P11_.is_null()) {
827 RCP<Teuchos::TimeMonitor> tmRes =
getTimer(
"MueLu Maxwell1: (1,1) correction");
834 RCP<Teuchos::TimeMonitor> tmRes =
getTimer(
"MueLu Maxwell1: (2,2) correction");
841 RCP<Teuchos::TimeMonitor> tmRes =
getTimer(
"MueLu Maxwell1: Prolongation");
849 if (Fine->IsAvailable(
"PostSmoother")) {
850 RCP<Teuchos::TimeMonitor> tmRes =
getTimer(
"MueLu Maxwell1: PostSmoother");
851 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
852 postSmoo->Apply(X, RHS,
false);
856template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
861template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
866 RCP<Teuchos::TimeMonitor> tm =
getTimer(
"MueLu Maxwell1: solve");
874 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Must use mode 'standard', 'refmaxwell' or 'edge only' when not doing GMHD.");
877template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
882template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
884 std::set<std::string> requiredUserData;
885 std::set<std::string> optionalUserData;
887 requiredUserData.insert(
"D0");
892 if (requiredUserData22.contains(
"Coordinates"))
893 requiredUserData.insert(
"Coordinates");
894 if (requiredUserData22.contains(
"Material"))
895 requiredUserData.insert(
"Material");
897 if (params.sublist(
"maxwell1: 11list").isType<std::string>(
"multigrid algorithm") &&
898 params.sublist(
"maxwell1: 11list").get<std::string>(
"multigrid algorithm") ==
"smoothed reitzinger" &&
899 (!params.sublist(
"maxwell1: 11list").isType<
double>(
"sa: damping factor") ||
900 params.sublist(
"maxwell1: 11list").get<
double>(
"sa: damping factor") != 0.)) {
901 if (!params.sublist(
"maxwell1: 11list").isType<
bool>(
"sa: use edge matrix for smoothing") ||
902 !params.sublist(
"maxwell1: 11list").get<
bool>(
"sa: use edge matrix for smoothing"))
903 requiredUserData.insert(
"CurlCurl");
906 optionalUserData.insert(
"Nullspace");
907 optionalUserData.insert(
"Kn");
908 optionalUserData.insert(
"GmhdA");
910 return std::make_pair(requiredUserData, optionalUserData);
913template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
914void scaleD0(Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& D0) {
919 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
920 using Matrix = Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
921 using impl_scalar_type =
typename Matrix::impl_scalar_type;
922 using impl_ATS = KokkosKernels::ArithTraits<impl_scalar_type>;
923 using magnitude_type =
typename impl_ATS::magnitudeType;
924 using MinMax = Kokkos::MinMax<magnitude_type>;
926 typename MinMax::value_type result;
928 auto lclD0 = D0.getLocalMatrixDevice();
929 Kokkos::parallel_reduce(
930 "MueLu::Maxwell1::D0_fixup",
931 range_type(0, lclD0.nnz()),
932 KOKKOS_LAMBDA(
const LocalOrdinal k,
typename MinMax::value_type& res) {
933 auto val = impl_ATS::magnitude(lclD0.values(k));
934 res.min_val = Kokkos::min(res.min_val, val);
935 res.max_val = Kokkos::max(res.max_val, val);
940 TEUCHOS_ASSERT_EQUALITY(result.min_val, result.max_val);
942 if (impl_ATS::magnitude(result.max_val - impl_ATS::one()) > impl_ATS::eps()) {
943 Scalar scaling = impl_ATS::one() / result.max_val;
948template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
950 initialize(
const Teuchos::RCP<Matrix>& D0_Matrix,
951 const Teuchos::RCP<Matrix>& Kn_Matrix,
952 const Teuchos::RCP<MultiVector>& Nullspace,
953 const Teuchos::RCP<RealValuedMultiVector>& Coords,
954 const Teuchos::RCP<Matrix>& CurlCurl_Matrix,
955 const Teuchos::RCP<MultiVector>& Material,
956 Teuchos::ParameterList& List) {
958 TEUCHOS_ASSERT(D0_Matrix != Teuchos::null);
961 if (!Kn_Matrix.is_null()) {
962 TEUCHOS_ASSERT(Kn_Matrix->getDomainMap()->isSameAs(*D0_Matrix->getDomainMap()));
963 TEUCHOS_ASSERT(Kn_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getDomainMap()));
966 TEUCHOS_ASSERT(D0_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getRowMap()));
987 if (D0_Matrix->getRowMap()->lib() == Xpetra::UseTpetra) {
992 RCP<Matrix> D0copy = MatrixFactory::Build(D0_Matrix->getRowMap(), D0_Matrix->getColMap(), 0);
993 RCP<CrsMatrix> D0copyCrs = toCrsMatrix(D0copy);
994 ArrayRCP<const size_t> D0rowptr_RCP;
995 ArrayRCP<const LO> D0colind_RCP;
996 ArrayRCP<const SC> D0vals_RCP;
997 toCrsMatrix(D0_Matrix)->getAllValues(D0rowptr_RCP, D0colind_RCP, D0vals_RCP);
999 ArrayRCP<size_t> D0copyrowptr_RCP;
1000 ArrayRCP<LO> D0copycolind_RCP;
1001 ArrayRCP<SC> D0copyvals_RCP;
1002 D0copyCrs->allocateAllValues(D0vals_RCP.size(), D0copyrowptr_RCP, D0copycolind_RCP, D0copyvals_RCP);
1003 D0copyrowptr_RCP.deepCopy(D0rowptr_RCP());
1004 D0copycolind_RCP.deepCopy(D0colind_RCP());
1005 D0copyvals_RCP.deepCopy(D0vals_RCP());
1006 D0copyCrs->setAllValues(D0copyrowptr_RCP,
1009 D0copyCrs->expertStaticFillComplete(D0_Matrix->getDomainMap(), D0_Matrix->getRangeMap(),
1010 toCrsMatrix(D0_Matrix)->getCrsGraph()->getImporter(),
1011 toCrsMatrix(D0_Matrix)->getCrsGraph()->getExporter());
1014 D0_Matrix_ = MatrixFactory::BuildCopy(D0_Matrix);
1024 if (!CurlCurl_Matrix.is_null()) {
1025 precList11_.sublist(
"user data").set(
"CurlCurl", CurlCurl_Matrix);
1026 dump(*CurlCurl_Matrix,
"CurlCurl.m");
1035template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1037 describe(Teuchos::FancyOStream& out,
const Teuchos::EVerbosityLevel )
const {
1038 std::ostringstream oss;
1040 RCP<const Teuchos::Comm<int>> comm =
SM_Matrix_->getDomainMap()->getComm();
1045 root = comm->getRank();
1050 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
1054 oss <<
"\n--------------------------------------------------------------------------------\n"
1055 <<
"--- Maxwell1 Summary ---\n"
1056 "--------------------------------------------------------------------------------"
1063 SM_Matrix_->getRowMap()->getComm()->barrier();
1068 Xpetra::global_size_t tt = numRows;
1081 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
1082 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
1089 oss <<
"(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
1094 std::string outstr = oss.str();
1097 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1098 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1100 int strLength = outstr.size();
1101 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1102 if (comm->getRank() != root)
1103 outstr.resize(strLength);
1104 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1120 std::ostringstream oss2;
1122 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
1123 oss2 <<
"( (1,1) block only is indicated by '1', (2,2) block only by '2', and both blocks by 'B' and none by '.')" << std::endl;
1125 int numProcs = comm->getSize();
1127 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1129 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
1135 std::vector<char> states(numProcs, 0);
1137 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
1139 states.push_back(status);
1142 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
1143 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
1144 for (
int j = 0; j < rowWidth; j++)
1145 if (proc + j < numProcs)
1146 if (states[proc + j] == 0)
1148 else if (states[proc + j] == 1)
1150 else if (states[proc + j] == 2)
1157 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
1166#define MUELU_MAXWELL1_SHORT
Various adapters that will create a MueLu preconditioner that is an Xpetra::Matrix.
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
static bool debug()
Whether MueLu is in debug mode.
Exception throws to report errors in the internal logical of the program.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
static void AddNonSerializableDataToHierarchy(HierarchyManager &HM, Hierarchy &H, const ParameterList &nonSerialList)
Add non-serializable data to Hierarchy.
static void CopyBetweenHierarchies(Hierarchy &fromHierarchy, Hierarchy &toHierarchy, const std::string fromLabel, const std::string toLabel, const std::string dataType)
Class that holds all level-specific information.
void SetLevelID(int levelID)
Set 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)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.
void SetPreviousLevel(const RCP< Level > &previousLevel)
void SetFactoryManager(const RCP< const FactoryManagerBase > &factoryManager)
Set default factories (used internally by Hierarchy::SetLevel()).
static Teuchos::RCP< Teuchos::ParameterList > translate(const Teuchos::ParameterList ¶mList, const std::string &defaultVals="")
: Translate ML parameters to MueLu parameter XML string
static const T & getDefault(const std::string &name)
Returns default value on the "master" list for a parameter with the specified name and type.
const Teuchos::RCP< const Map > getDomainMap() const
Returns the Xpetra::Map object associated with the domain of this operator.
bool useKokkos_
Some options.
Teuchos::RCP< Matrix > generate_kn() const
Generates the Kn matrix.
Teuchos::RCP< Hierarchy > Hierarchy11_
Two hierarchies: one for the (1,1)-block, another for the (2,2)-block.
Teuchos::RCP< Hierarchy > HierarchyGmhd_
Teuchos::RCP< MultiVector > residualFine_
typename Teuchos::ScalarTraits< Scalar >::magnitudeType magnitudeType
Teuchos::ArrayRCP< bool > BCcols_
Teuchos::ArrayRCP< bool > BCrows_
Teuchos::RCP< Matrix > SM_Matrix_
Various matrices.
Teuchos::RCP< Hierarchy > Hierarchy22_
Kokkos::View< bool *, typename Node::device_type::memory_space > BCrowsKokkos_
Vectors for BCs.
void compute(bool reuse=false)
Setup the preconditioner.
void GMHDSetupHierarchy(Teuchos::ParameterList &List) const
Sets up hiearchy for GMHD matrices that include generalized Ohms law equations.
Teuchos::ParameterList parameterList_
ParameterLists.
Teuchos::RCP< MultiVector > residual22_
Kokkos::View< bool *, typename Node::device_type::memory_space > BCdomainKokkos_
Teuchos::RCP< RealValuedMultiVector > Coords_
Coordinates.
Teuchos::RCP< Matrix > D0_Matrix_
const Teuchos::RCP< const Map > getRangeMap() const
Returns the Xpetra::Map object associated with the range of this operator.
void applyInverseRefMaxwellAdditive(const MultiVector &RHS, MultiVector &X) const
apply RefMaxwell additive 2x2 style cycle
Teuchos::RCP< MultiVector > Nullspace_
Nullspace.
Teuchos::RCP< MultiVector > update11c_
void apply(const MultiVector &RHS, MultiVector &X, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=Teuchos::ScalarTraits< Scalar >::one(), Scalar beta=Teuchos::ScalarTraits< Scalar >::zero()) const
void applyInverseStandard(const MultiVector &RHS, MultiVector &X) const
apply standard Maxwell1 cycle
RCP< Matrix > P11_
Temporary memory (cached vectors for RefMaxwell-style).
Teuchos::RCP< MultiVector > Material_
Material.
void dumpCoords(const RealValuedMultiVector &X, std::string name) const
dump out real-valued multivector
Teuchos::RCP< MultiVector > update22_
Teuchos::ArrayRCP< bool > BCdomain_
Teuchos::ParameterList precList11_
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::VERB_HIGH) const
Teuchos::RCP< Matrix > GmhdA_Matrix_
void dump(const Matrix &A, std::string name) const
dump out matrix
typename Xpetra::MultiVector< coordinateType, LO, GO, NO > RealValuedMultiVector
Teuchos::ParameterList precList22_
void resetMatrix(Teuchos::RCP< Matrix > SM_Matrix_new, bool ComputePrec=true)
Reset system matrix.
static std::pair< std::set< std::string >, std::set< std::string > > requiredAndOptionalUserData(const Teuchos::ParameterList ¶ms)
Teuchos::RCP< Matrix > Kn_Matrix_
Teuchos::RCP< MultiVector > residual11c_
bool hasTransposeApply() const
Indicates whether this operator supports applying the adjoint operator.
Teuchos::RCP< Teuchos::TimeMonitor > getTimer(std::string name, RCP< const Teuchos::Comm< int > > comm=Teuchos::null) const
get a (synced) timer
Kokkos::View< bool *, typename Node::device_type::memory_space > BCcolsKokkos_
void initialize(const Teuchos::RCP< Matrix > &D0_Matrix, const Teuchos::RCP< Matrix > &Kn_Matrix, const Teuchos::RCP< MultiVector > &Nullspace, const Teuchos::RCP< RealValuedMultiVector > &Coords, const Teuchos::RCP< Matrix > &CurlCurl_Matrix, const Teuchos::RCP< MultiVector > &Material, Teuchos::ParameterList &List)
void setParameters(Teuchos::ParameterList &list)
Set parameters.
void allocateMemory(int numVectors) const
allocate multivectors for solve
static void detectBoundaryConditionsSM(RCP< Matrix > &SM_Matrix, RCP< Matrix > &D0_Matrix, magnitudeType rowSumTol, bool useKokkos_, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCrowsKokkos, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCcolsKokkos, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCdomainKokkos, int &BCedges, int &BCnodes, Teuchos::ArrayRCP< bool > &BCrows, Teuchos::ArrayRCP< bool > &BCcols, Teuchos::ArrayRCP< bool > &BCdomain, bool &allEdgesBoundary, bool &allNodesBoundary)
Detect Dirichlet boundary conditions.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > PtAPWrapper(const RCP< Matrix > &A, const RCP< Matrix > &P, Teuchos::ParameterList ¶ms, const std::string &label)
Performs an P^T AP.
static std::pair< std::set< std::string >, std::set< std::string > > requiredAndOptionalUserData(const Teuchos::ParameterList ¶mList, Teuchos::RCP< const Teuchos::ParameterList > defaultList=Teuchos::null, int maxLevel=0)
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
Factory for building coarse matrices.
Applies permutation to grid transfer operators.
Class that encapsulates Operator smoothers.
static void ZeroDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &A, const std::vector< DefaultLocalOrdinal > &dirichletRows, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static void ZeroDirichletCols(Teuchos::RCP< Matrix > &A, const Teuchos::ArrayRCP< const bool > &dirichletCols, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > ReplaceNonZerosWithOnes(const RCP< Matrix > &original)
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &Op, const MultiVector &X, const MultiVector &RHS)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
VerbLevel GetVerbLevel() const
Get the verbosity level.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
static void SetDefaultVerbLevel(const VerbLevel defaultVerbLevel)
Set the default (global) verbosity level.
Namespace for MueLu classes and methods.
long ExtractNonSerializableData(const Teuchos::ParameterList &inList, Teuchos::ParameterList &serialList, Teuchos::ParameterList &nonSerialList)
Extract non-serializable data from level-specific sublists and move it to a separate parameter list.
@ Warnings0
Important warning messages (one line).
@ Statistics2
Print even more statistics.
@ Runtime0
One-liner description of what is happening.
@ Warnings1
Additional warnings.
@ Timings
Print all timing information.
MsgType toVerbLevel(const std::string &verbLevelStr)
Teuchos::RCP< MueLu::Hierarchy< Scalar, LocalOrdinal, GlobalOrdinal, Node > > CreateXpetraPreconditioner(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > op, const Teuchos::ParameterList &inParamList)
Helper function to create a MueLu preconditioner that can be used by Xpetra.Given an Xpetra::Matrix,...
void scaleD0(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &D0)