62 if (list.isType<std::string>(
"parameterlist: syntax") && list.get<std::string>(
"parameterlist: syntax") ==
"ml") {
63 list.remove(
"parameterlist: syntax");
64 Teuchos::ParameterList newList;
70 newList.sublist(
"maxwell1: 22list").set(
"use kokkos refactor",
false);
72 newList.sublist(
"maxwell1: 11list").set(
"use kokkos refactor",
false);
73 newList.sublist(
"maxwell1: 11list").set(
"tentative: constant column sums",
false);
74 newList.sublist(
"maxwell1: 11list").set(
"tentative: calculate qr",
false);
76 newList.sublist(
"maxwell1: 11list").set(
"aggregation: use ml scaling of drop tol",
true);
77 newList.sublist(
"maxwell1: 22list").set(
"aggregation: use ml scaling of drop tol",
true);
79 newList.sublist(
"maxwell1: 22list").set(
"aggregation: min agg size", 3);
80 newList.sublist(
"maxwell1: 22list").set(
"aggregation: match ML phase1",
true);
81 newList.sublist(
"maxwell1: 22list").set(
"aggregation: match ML phase2a",
true);
82 newList.sublist(
"maxwell1: 22list").set(
"aggregation: match ML phase2b",
true);
84 if (!list.sublist(
"maxwell1: 11list").isParameter(
"multigrid algorithm") || (list.sublist(
"maxwell1: 11list").get<std::string>(
"multigrid algorithm") !=
"emin reitzinger")) {
85 if (list.isParameter(
"aggregation: damping factor") && list.get<
double>(
"aggregation: damping factor") == 0.0)
86 newList.sublist(
"maxwell1: 11list").set(
"multigrid algorithm",
"unsmoothed reitzinger");
88 newList.sublist(
"maxwell1: 11list").set(
"multigrid algorithm",
"smoothed reitzinger");
90 newList.sublist(
"maxwell1: 11list").set(
"aggregation: type",
"uncoupled");
92 newList.sublist(
"maxwell1: 22list").set(
"multigrid algorithm",
"unsmoothed");
93 newList.sublist(
"maxwell1: 22list").set(
"aggregation: type",
"uncoupled");
95 if (newList.sublist(
"maxwell1: 22list").isType<std::string>(
"verbosity"))
96 newList.set(
"verbosity", newList.sublist(
"maxwell1: 22list").get<std::string>(
"verbosity"));
99 std::vector<std::string> convert = {
"coarse:",
"smoother:",
"smoother: pre",
"smoother: post"};
100 for (
auto it = convert.begin(); it != convert.end(); ++it) {
101 if (newList.sublist(
"maxwell1: 22list").isType<std::string>(*it +
" type")) {
102 newList.sublist(
"maxwell1: 11list").set(*it +
" type", newList.sublist(
"maxwell1: 22list").get<std::string>(*it +
" type"));
103 newList.sublist(
"maxwell1: 22list").remove(*it +
" type");
105 if (newList.sublist(
"maxwell1: 22list").isSublist(*it +
" params")) {
106 newList.sublist(
"maxwell1: 11list").set(*it +
" params", newList.sublist(
"maxwell1: 22list").sublist(*it +
" params"));
107 newList.sublist(
"maxwell1: 22list").remove(*it +
" params");
111 newList.sublist(
"maxwell1: 22list").set(
"smoother: type",
"none");
112 newList.sublist(
"maxwell1: 22list").set(
"coarse: type",
"none");
114 newList.set(
"maxwell1: nodal smoother fix zero diagonal threshold", 1e-10);
115 newList.sublist(
"maxwell1: 22list").set(
"rap: fix zero diagonals",
true);
116 newList.sublist(
"maxwell1: 22list").set(
"rap: fix zero diagonals threshold", 1e-10);
121 std::string mode_string = list.get(
"maxwell1: mode", MasterList::getDefault<std::string>(
"maxwell1: mode"));
122 applyBCsTo22_ = list.get(
"maxwell1: apply BCs to 22",
false);
123 dump_matrices_ = list.get(
"maxwell1: dump matrices", MasterList::getDefault<bool>(
"maxwell1: dump matrices"));
124 check_D0_scaling_ = list.get(
"maxwell1: check and fix D0 scaling", MasterList::getDefault<bool>(
"maxwell1: check and fix D0 scaling"));
127 Teuchos::ParameterList defaultSmootherList;
128 defaultSmootherList.set(
"smoother: type",
"CHEBYSHEV");
129 defaultSmootherList.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
130 defaultSmootherList.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 7.0);
131 defaultSmootherList.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
134 std::string verbosity = list.get(
"verbosity",
"high");
138 if (mode_ != MODE_GMHD_STANDARD) {
139 if (mode_string ==
"standard")
140 mode_ = MODE_STANDARD;
141 else if (mode_string ==
"refmaxwell")
142 mode_ = MODE_REFMAXWELL;
143 else if (mode_string ==
"edge only")
144 mode_ = MODE_EDGE_ONLY;
146 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"Must use mode 'standard', 'refmaxwell', 'edge only', or use the GMHD constructor.");
152 if (list.isSublist(
"maxwell1: 22list"))
153 precList22_ = list.sublist(
"maxwell1: 22list");
154 else if (list.isSublist(
"refmaxwell: 22list"))
155 precList22_ = list.sublist(
"refmaxwell: 22list");
156 if (mode_ == MODE_EDGE_ONLY || mode_ == MODE_STANDARD || mode_ == MODE_GMHD_STANDARD)
157 precList22_.set(
"smoother: pre or post",
"none");
158 else if (!precList22_.isType<std::string>(
"Preconditioner Type") &&
159 !precList22_.isType<std::string>(
"smoother: type") &&
160 !precList22_.isType<std::string>(
"smoother: pre type") &&
161 !precList22_.isType<std::string>(
"smoother: post type")) {
162 precList22_ = defaultSmootherList;
164 precList22_.set(
"verbosity", precList22_.get(
"verbosity", verbosity));
168 if (list.isSublist(
"maxwell1: 11list"))
169 precList11_ = list.sublist(
"maxwell1: 11list");
170 else if (list.isSublist(
"refmaxwell: 11list"))
171 precList11_ = list.sublist(
"refmaxwell: 11list");
173 if (mode_ == MODE_GMHD_STANDARD) {
174 precList11_.set(
"smoother: pre or post",
"none");
175 precList11_.set(
"smoother: type",
"none");
177 if (!precList11_.isType<std::string>(
"Preconditioner Type") &&
178 !precList11_.isType<std::string>(
"smoother: type") &&
179 !precList11_.isType<std::string>(
"smoother: pre type") &&
180 !precList11_.isType<std::string>(
"smoother: post type")) {
181 if (mode_ == MODE_EDGE_ONLY || mode_ == MODE_REFMAXWELL) {
182 precList11_ = defaultSmootherList;
184 if (mode_ == MODE_STANDARD) {
185 precList11_.set(
"smoother: type",
"HIPTMAIR");
186 precList11_.set(
"hiptmair: smoother type 1",
"CHEBYSHEV");
187 precList11_.set(
"hiptmair: smoother type 2",
"CHEBYSHEV");
188 precList11_.sublist(
"hiptmair: smoother list 1") = defaultSmootherList;
189 precList11_.sublist(
"hiptmair: smoother list 2") = defaultSmootherList;
192 precList11_.set(
"verbosity", precList11_.get(
"verbosity", verbosity));
196 !precList11_.isType<std::string>(
"Preconditioner Type") &&
197 !precList11_.isParameter(
"reuse: type"))
198 precList11_.set(
"reuse: type",
"full");
200 !precList22_.isType<std::string>(
"Preconditioner Type") &&
201 !precList22_.isParameter(
"reuse: type"))
202 precList22_.set(
"reuse: type",
"full");
205 useKokkos_ = !Node::is_serial;
206 useKokkos_ = list.get(
"use kokkos refactor", useKokkos_);
208 parameterList_ = list;
244#ifdef HAVE_MUELU_CUDA
245 if (parameterList_.get<
bool>(
"maxwell1: cuda profile setup",
false)) cudaProfilerStart();
248 std::string timerLabel;
250 timerLabel =
"MueLu Maxwell1: compute (reuse)";
252 timerLabel =
"MueLu Maxwell1: compute";
253 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
257 bool have_generated_Kn =
false;
258 if (Kn_Matrix_.is_null()) {
260 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Kn not provided. Generating." << std::endl;
261 Kn_Matrix_ = generate_kn();
262 have_generated_Kn =
true;
263 }
else if (parameterList_.get<
bool>(
"rap: fix zero diagonals",
true)) {
265 if (parameterList_.isType<
magnitudeType>(
"rap: fix zero diagonals threshold"))
266 threshold = parameterList_.get<
magnitudeType>(
"rap: fix zero diagonals threshold",
267 Teuchos::ScalarTraits<double>::eps());
269 threshold = Teuchos::as<magnitudeType>(parameterList_.get<
double>(
"rap: fix zero diagonals threshold",
270 Teuchos::ScalarTraits<double>::eps()));
271 Scalar replacement = Teuchos::as<Scalar>(parameterList_.get<
double>(
"rap: fix zero diagonals replacement",
272 MasterList::getDefault<double>(
"rap: fix zero diagonals replacement")));
273 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(Kn_Matrix_,
true, GetOStream(
Warnings1), threshold, replacement);
278 Kn_Matrix_->setObjectLabel(
"Maxwell1 (2,2)");
281 if (!Coords_.is_null())
282 precList22_.sublist(
"user data").set(
"Coordinates", Coords_);
283 if (!Material_.is_null())
284 precList22_.sublist(
"user data").set(
"Material", Material_);
286 if (mode_ == MODE_STANDARD) {
288 if (!precList22_.isParameter(
"smoother: type") && !precList22_.isParameter(
"smoother: pre type") && !precList22_.isParameter(
"smoother: post type")) {
289 precList22_.set(
"smoother: type",
"none");
291 if (!precList22_.isParameter(
"coarse: type")) {
292 precList22_.set(
"coarse: type",
"none");
296 auto algo11 = precList11_.get<std::string>(
"multigrid algorithm");
297 auto algo22 = precList22_.get<std::string>(
"multigrid algorithm");
311 if (algo11 ==
"unsmoothed reitzinger") {
312 TEUCHOS_ASSERT(algo22 ==
"unsmoothed");
313 }
else if (algo11 ==
"smoothed reitzinger") {
314 TEUCHOS_ASSERT((algo22 ==
"unsmoothed") || (algo22 ==
"sa"));
317 if (algo22 ==
"sa") {
320 if (precList22_.isType<
double>(
"sa: damping factor")) {
321 nodalDamping = precList22_.get<
double>(
"sa: damping factor");
323 nodalDamping = MasterList::getDefault<double>(
"sa: damping factor");
325 precList11_.set(
"sa: nodal damping factor", nodalDamping);
326 }
else if (algo22 ==
"unsmoothed")
327 precList11_.set(
"sa: nodal damping factor", 0.0);
329 if (algo11 ==
"smoothed reitzinger") {
330 precList11_.set(
"sa: use filtered matrix",
false);
331 precList22_.set(
"sa: use filtered matrix",
false);
332 if (!precList11_.sublist(
"user data").isParameter(
"CurlCurl")) {
333 if (precList11_.isType<
double>(
"sa: damping factor")) {
334 double edgeDamping = precList11_.get<
double>(
"sa: damping factor");
335 if (edgeDamping != 0) {
336 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." << std::endl;
337 precList11_.set(
"sa: damping factor", 0.);
340 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;
341 precList11_.set(
"sa: damping factor", 0.);
346 if (!precList22_.isParameter(
"tentative: constant column sums"))
347 precList22_.set(
"tentative: constant column sums",
false);
348 else if (precList22_.get<
bool>(
"tentative: constant column sums") !=
false)
349 GetOStream(
Warnings0) <<
"\"tentative: constant column sums\" is set to \"true\". There is no guarantee that this will work." << std::endl;
351 if (!precList22_.isParameter(
"tentative: calculate qr"))
352 precList22_.set(
"tentative: calculate qr",
false);
353 else if (precList22_.get<
bool>(
"tentative: calculate qr") !=
false)
354 GetOStream(
Warnings0) <<
"\"tentative: calculate qr\" is set to \"true\". There is no guarantee that this will work." << std::endl;
357 if (((parameterList_.sublist(
"maxwell1: 11list").get<std::string>(
"multigrid algorithm") ==
"smoothed reitzinger") || (parameterList_.sublist(
"maxwell1: 11list").get<std::string>(
"multigrid algorithm") ==
"emin reitzinger")) &&
358 (!precList22_.isParameter(
"sa: keep tentative prolongator") || !precList22_.get<
bool>(
"sa: keep tentative prolongator")))
359 precList22_.set(
"sa: keep tentative prolongator",
true);
363 if (precList22_.isParameter(
"repartition: enable")) {
364 bool repartition = precList22_.get<
bool>(
"repartition: enable");
365 precList11_.set(
"repartition: enable", repartition);
370 if (!precList22_.isParameter(
"repartition: save importer"))
371 precList22_.set(
"repartition: save importer",
true);
372 else if (!precList22_.get<
bool>(
"repartition: save importer")) {
373 GetOStream(
Warnings0) <<
"\"repartition: save importer\" is set to false, but it is required to be true. Changing it." << std::endl;
374 precList22_.set(
"repartition: save importer",
true);
377 if (!precList22_.isParameter(
"repartition: rebalance P and R"))
378 precList22_.set(
"repartition: rebalance P and R",
true);
379 else if (!precList22_.get<
bool>(
"repartition: rebalance P and R")) {
380 GetOStream(
Warnings0) <<
"\"repartition: rebalance P and R\" is set to false, but it is required to be true. Changing it." << std::endl;
381 precList22_.set(
"repartition: rebalance P and R",
true);
384 if (!precList22_.isParameter(
"repartition: use subcommunicators"))
385 precList22_.set(
"repartition: use subcommunicators",
true);
386 else if (!precList22_.get<
bool>(
"repartition: use subcommunicators")) {
387 GetOStream(
Warnings0) <<
"\"repartition: use subcommunicators\" is set to false, but it is required to be true. Changing it." << std::endl;
388 precList22_.set(
"repartition: use subcommunicators",
true);
392 if (precList22_.isParameter(
"repartition: use subcommunicators")) {
393 precList11_.set(
"repartition: use subcommunicators", precList22_.get<
bool>(
"repartition: use subcommunicators"));
397 if (precList11_.get<
bool>(
"repartition: use subcommunicators") ==
true)
398 precList11_.set(
"repartition: use subcommunicators in place",
true);
401 precList11_.set(
"repartition: use subcommunicators",
true);
402 precList22_.set(
"repartition: use subcommunicators",
true);
406 precList11_.set(
"repartition: use subcommunicators in place",
true);
410 precList11_.remove(
"repartition: enable",
false);
419 RCP<ParameterList> params = rcp(
new ParameterList());
421 params->set(
"printLoadBalancingInfo",
true);
422 params->set(
"printCommInfo",
true);
429 magnitudeType rowSumTol = precList11_.get(
"aggregation: row sum drop tol", -1.0);
431 useKokkos_, BCrowsKokkos_, BCcolsKokkos_, BCdomainKokkos_,
432 BCedges_, BCnodes_, BCrows_, BCcols_, BCdomain_,
433 allEdgesBoundary_, allNodesBoundary_);
435 GetOStream(
Statistics2) <<
"MueLu::Maxwell1::compute(): Detected " << BCedges_ <<
" BC rows and " << BCnodes_ <<
" BC columns." << std::endl;
439 if (allEdgesBoundary_) {
442 GetOStream(
Warnings0) <<
"All edges are detected as boundary edges!" << std::endl;
443 mode_ = MODE_EDGE_ONLY;
446 precList22_.set(
"max levels", 1);
449 if (allNodesBoundary_) {
452 GetOStream(
Warnings0) <<
"All nodes are detected as boundary nodes!" << std::endl;
453 mode_ = MODE_EDGE_ONLY;
456 precList22_.set(
"max levels", 1);
466 D0_Matrix_->resumeFill();
467 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
470 GetOStream(
Runtime0) <<
"Maxwell1::compute(): nuking BC rows/cols of D0" << std::endl;
477 GetOStream(
Runtime0) <<
"Maxwell1::compute(): nuking BC rows of D0" << std::endl;
485 D0_Matrix_->fillComplete(D0_Matrix_->getDomainMap(), D0_Matrix_->getRangeMap());
495 RCP<Matrix> Kn_Smoother_0;
496 if (have_generated_Kn) {
497 Kn_Smoother_0 = Kn_Matrix_;
499 Kn_Smoother_0 = generate_kn();
504 Hierarchy11_ = rcp(
new Hierarchy(
"Maxwell1 (1,1)"));
505 RCP<Matrix> OldSmootherMatrix;
506 RCP<Level> OldEdgeLevel;
507 for (
int i = 0; i < Hierarchy22_->GetNumLevels(); i++) {
508 Hierarchy11_->AddNewLevel();
509 RCP<Level> NodeL = Hierarchy22_->GetLevel(i);
510 RCP<Level> EdgeL = Hierarchy11_->GetLevel(i);
511 RCP<Operator> NodeAggOp = NodeL->Get<RCP<Operator>>(
"A");
512 RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(NodeAggOp);
516 EdgeL->Set(
"A", SM_Matrix_);
517 EdgeL->Set(
"D0", D0_Matrix_);
519 EdgeL->Set(
"NodeAggMatrix", NodeAggMatrix);
520 EdgeL->Set(
"NodeMatrix", Kn_Smoother_0);
521 OldSmootherMatrix = Kn_Smoother_0;
522 OldEdgeLevel = EdgeL;
525 auto NodalP = NodeL->Get<RCP<Matrix>>(
"P");
532 RCP<const Import> importer;
533 if (NodeL->IsAvailable(
"Importer")) {
534 importer = NodeL->Get<RCP<const Import>>(
"Importer");
535 EdgeL->Set(
"NodeImporter", importer);
539 RCP<Matrix> NodalPtent;
540 if (parameterList_.sublist(
"maxwell1: 22list").get<std::string>(
"multigrid algorithm") ==
"unsmoothed")
541 NodalPtent = NodeL->Get<RCP<Matrix>>(
"P");
543 NodalPtent = NodeL->Get<RCP<Matrix>>(
"Ptent");
545 if (!importer.is_null()) {
556 ParameterList rebalTransferParams;
557 rebalTransferParams.set(
"repartition: rebalance P and R",
true);
558 rebalTransferParams.set(
"type",
"Interpolation");
559 rebalTransfer->SetParameterList(rebalTransferParams);
560 coarseLevel.
Set(
"P", NodalPtent);
561 coarseLevel.
Set(
"Importer", importer);
562 rebalTransfer->Build(fineLevel, coarseLevel);
563 NodalPtent = coarseLevel.
Get<RCP<Matrix>>(
"P");
568 TEUCHOS_TEST_FOR_EXCEPTION(P_for_RS_construction.is_null(),
Exceptions::RuntimeError,
"Applying ones to prolongator failed");
571 EdgeL->Set(
"Pnodal", P_for_RS_construction);
573 if (parameterList_.sublist(
"maxwell1: 11list").get<std::string>(
"multigrid algorithm") ==
"emin reitzinger") {
576 EdgeL->Set(
"PnodalEmin", NodalP);
581 if (!OldSmootherMatrix.is_null() && !P_for_RS_construction.is_null()) {
582 EdgeL->Set(
"NodeAggMatrix", NodeAggMatrix);
583 if (!have_generated_Kn) {
593 Teuchos::ParameterList RAPlist;
594 RAPlist.set(
"rap: fix zero diagonals",
false);
598 if (!importer.is_null()) {
599 ParameterList rebAcParams;
600 rebAcParams.set(
"repartition: use subcommunicators",
true);
601 rebAcParams.set(
"repartition: use subcommunicators in place",
true);
603 newAfact->SetParameterList(rebAcParams);
604 RCP<const Map> InPlaceMap = NodeAggMatrix.is_null() ? Teuchos::null : NodeAggMatrix->getRowMap();
606 Level fLevel, cLevel;
608 cLevel.
Set(
"InPlaceMap", InPlaceMap);
609 cLevel.
Set(
"A", NewKn);
610 cLevel.
Request(
"A", newAfact.get());
611 newAfact->Build(fLevel, cLevel);
613 NewKn = cLevel.
Get<RCP<Matrix>>(
"A", newAfact.get());
614 EdgeL->Set(
"NodeMatrix", NewKn);
616 EdgeL->Set(
"NodeMatrix", NewKn);
620 double thresh = parameterList_.get(
"maxwell1: nodal smoother fix zero diagonal threshold", 1e-10);
622 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Fixing zero diagonal for nodal smoother matrix" << std::endl;
623 Scalar replacement = Teuchos::ScalarTraits<Scalar>::one();
624 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(OldSmootherMatrix,
true, GetOStream(
Warnings1), thresh, replacement);
626 OldEdgeLevel->Set(
"NodeMatrix", OldSmootherMatrix);
628 OldSmootherMatrix = NewKn;
631 EdgeL->Set(
"NodeMatrix", NodeAggMatrix);
635 EdgeL->Set(
"NodeMatrix", NodeAggOp);
636 EdgeL->Set(
"NodeAggMatrix", NodeAggOp);
639 OldEdgeLevel = EdgeL;
647 SM_Matrix_->setObjectLabel(
"A(1,1)");
648 precList11_.set(
"coarse: max size", 1);
649 precList11_.set(
"max levels", Hierarchy22_->GetNumLevels());
651 const bool refmaxwellCoarseSolve = (precList11_.get<std::string>(
"coarse: type",
652 MasterList::getDefault<std::string>(
"coarse: type")) ==
"RefMaxwell");
653 if (refmaxwellCoarseSolve) {
654 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Will set up RefMaxwell coarse solver" << std::endl;
655 precList11_.set(
"coarse: type",
"none");
659 Teuchos::ParameterList nonSerialList11;
660 Teuchos::ParameterList processedPrecList11;
663 Hierarchy11_->setlib(SM_Matrix_->getDomainMap()->lib());
664 Hierarchy11_->SetProcRankVerbose(SM_Matrix_->getDomainMap()->getComm()->getRank());
667 if (nonSerialList11.numParams() > 0) {
670 mueLuFactory->SetupHierarchy(*Hierarchy11_);
672 if (refmaxwellCoarseSolve) {
673 GetOStream(
Runtime0) <<
"Maxwell1::compute(): Setting up RefMaxwell coarse solver" << std::endl;
674 auto coarseLvl = Hierarchy11_->GetLevel(Hierarchy11_->GetNumLevels() - 1);
676 precList11_.sublist(
"coarse: params")));
677 coarseSolver->Setup(*coarseLvl);
678 coarseLvl->Set(
"PreSmoother",
679 rcp_dynamic_cast<SmootherBase>(coarseSolver,
true));
682 if (mode_ == MODE_REFMAXWELL) {
683 if (Hierarchy11_->GetNumLevels() > 1) {
684 RCP<Level> EdgeL = Hierarchy11_->GetLevel(1);
685 P11_ = EdgeL->Get<RCP<Matrix>>(
"P");
697 for (
int i = 1; i < Hierarchy11_->GetNumLevels(); i++) {
698 auto EdgeL = Hierarchy11_->GetLevel(i);
699 auto EdgeL_fine = Hierarchy11_->GetLevel(i - 1);
700 auto NodeL = Hierarchy22_->GetLevel(i);
702 auto Pe = EdgeL->template Get<RCP<Matrix>>(
"P");
703 auto Pn = NodeL->template Get<RCP<Matrix>>(
"P");
704 auto D0_f = EdgeL_fine->template Get<RCP<Matrix>>(
"D0");
705 auto D0_c = EdgeL->template Get<RCP<Matrix>>(
"D0");
707 if (!Pe.is_null() && !D0_c.is_null() && (Pe->getRowMap()->getComm()->getSize() == D0_c->getRowMap()->getComm()->getSize())) {
708 using XMM = Xpetra::MatrixMatrix<SC, LO, GO, NO>;
709 auto one = Teuchos::ScalarTraits<SC>::one();
712 RCP<Matrix> left = XMM::Multiply(*Pe,
false, *D0_c,
false, dummy, GetOStream(
Runtime0));
713 RCP<Matrix> right = XMM::Multiply(*D0_f,
false, *Pn,
false, dummy, GetOStream(
Runtime0));
715 RCP<Matrix> summation;
716 XMM::TwoMatrixAdd(*left,
false, one, *right,
false, -one, summation, GetOStream(
Runtime0));
717 summation->fillComplete(left->getDomainMap(), left->getRangeMap());
719 auto norm = summation->getFrobeniusNorm();
720 GetOStream(
Runtime0) <<
"CheckCommutingProperty on level " << i - 1 <<
": || Pe D0_c - D0_f Pn || = " << norm << std::endl;
721 }
else if (!Pe.is_null()) {
722 GetOStream(
Runtime0) <<
"Cannot run CheckCommutingProperty on level " << i - 1 <<
" due to rebalancing" << std::endl;
726#ifdef MUELU_MAXWELL1_DEBUG
728 for (
int i = 0; i < Hierarchy11_->GetNumLevels(); i++) {
729 RCP<Level> L = Hierarchy11_->GetLevel(i);
730 RCP<Matrix> EdgeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"A"));
731 RCP<Matrix> NodeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"NodeMatrix"));
732 RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"NodeAggMatrix"));
733 RCP<Matrix> D0 = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator>>(
"D0"));
735 auto nrmE = EdgeMatrix->getFrobeniusNorm();
736 auto nrmN = NodeMatrix->getFrobeniusNorm();
737 auto nrmNa = NodeAggMatrix->getFrobeniusNorm();
738 auto nrmD0 = D0->getFrobeniusNorm();
740 std::cout <<
"DEBUG: Norms on Level " << i <<
" E/N/NA/D0 = " << nrmE <<
" / " << nrmN <<
" / " << nrmNa <<
" / " << nrmD0 << std::endl;
741 std::cout <<
"DEBUG: NNZ on Level " << i <<
" E/N/NA/D0 = " << EdgeMatrix->getGlobalNumEntries() <<
" / " << NodeMatrix->getGlobalNumEntries() <<
" / " << NodeAggMatrix->getGlobalNumEntries() <<
" / " << D0->getGlobalNumEntries() << std::endl;
851 const SC one = Teuchos::ScalarTraits<SC>::one();
852 if (!allEdgesBoundary_ && X.getNumVectors() != residualFine_->getNumVectors())
853 allocateMemory(X.getNumVectors());
855 TEUCHOS_TEST_FOR_EXCEPTION(Hierarchy11_.is_null() || Hierarchy11_->GetNumLevels() == 0,
Exceptions::RuntimeError,
"(1,1) Hierarchy is null.");
858 RCP<Level> Fine = Hierarchy11_->GetLevel(0);
859 if (Fine->IsAvailable(
"PreSmoother")) {
860 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"MueLu Maxwell1: PreSmoother");
861 RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase>>(
"PreSmoother");
862 preSmoo->Apply(X, RHS,
true);
867 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"MueLu Maxwell1: residual calculation");
872 if (!P11_.is_null()) {
873 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"MueLu Maxwell1: (1,1) correction");
874 P11_->apply(*residualFine_, *residual11c_, Teuchos::TRANS);
875 Hierarchy11_->Iterate(*residual11c_, *update11c_, 1,
true, 1);
879 if (!allNodesBoundary_) {
880 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"MueLu Maxwell1: (2,2) correction");
881 D0_Matrix_->apply(*residualFine_, *residual22_, Teuchos::TRANS);
882 Hierarchy22_->Iterate(*residual22_, *update22_, 1,
true, 0);
887 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"MueLu Maxwell1: Orolongation");
889 P11_->apply(*update11c_, X, Teuchos::NO_TRANS, one, one);
890 if (!allNodesBoundary_)
891 D0_Matrix_->apply(*update22_, X, Teuchos::NO_TRANS, one, one);
895 if (Fine->IsAvailable(
"PostSmoother")) {
896 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"MueLu Maxwell1: PostSmoother");
897 RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase>>(
"PostSmoother");
898 postSmoo->Apply(X, RHS,
false);
965 initialize(
const Teuchos::RCP<Matrix>& D0_Matrix,
966 const Teuchos::RCP<Matrix>& Kn_Matrix,
967 const Teuchos::RCP<MultiVector>& Nullspace,
968 const Teuchos::RCP<RealValuedMultiVector>& Coords,
969 const Teuchos::RCP<Matrix>& CurlCurl_Matrix,
970 const Teuchos::RCP<MultiVector>& Material,
971 Teuchos::ParameterList& List) {
973 TEUCHOS_ASSERT(D0_Matrix != Teuchos::null);
976 if (!Kn_Matrix.is_null()) {
977 TEUCHOS_ASSERT(Kn_Matrix->getDomainMap()->isSameAs(*D0_Matrix->getDomainMap()));
978 TEUCHOS_ASSERT(Kn_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getDomainMap()));
981 TEUCHOS_ASSERT(D0_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getRowMap()));
984 Hierarchy11_ = Teuchos::null;
985 Hierarchy22_ = Teuchos::null;
986 HierarchyGmhd_ = Teuchos::null;
987 if (mode_ != MODE_GMHD_STANDARD) mode_ = MODE_STANDARD;
991 allEdgesBoundary_ =
false;
992 allNodesBoundary_ =
false;
993 dump_matrices_ =
false;
994 check_D0_scaling_ =
false;
995 enable_reuse_ =
false;
997 applyBCsTo22_ =
false;
1000 setParameters(List);
1002 if (D0_Matrix->getRowMap()->lib() == Xpetra::UseTpetra) {
1007 RCP<Matrix> D0copy = MatrixFactory::Build(D0_Matrix->getRowMap(), D0_Matrix->getColMap(), 0);
1008 RCP<CrsMatrix> D0copyCrs = toCrsMatrix(D0copy);
1009 ArrayRCP<const size_t> D0rowptr_RCP;
1010 ArrayRCP<const LO> D0colind_RCP;
1011 ArrayRCP<const SC> D0vals_RCP;
1012 toCrsMatrix(D0_Matrix)->getAllValues(D0rowptr_RCP, D0colind_RCP, D0vals_RCP);
1014 ArrayRCP<size_t> D0copyrowptr_RCP;
1015 ArrayRCP<LO> D0copycolind_RCP;
1016 ArrayRCP<SC> D0copyvals_RCP;
1017 D0copyCrs->allocateAllValues(D0vals_RCP.size(), D0copyrowptr_RCP, D0copycolind_RCP, D0copyvals_RCP);
1018 D0copyrowptr_RCP.deepCopy(D0rowptr_RCP());
1019 D0copycolind_RCP.deepCopy(D0colind_RCP());
1020 D0copyvals_RCP.deepCopy(D0vals_RCP());
1021 D0copyCrs->setAllValues(D0copyrowptr_RCP,
1024 D0copyCrs->expertStaticFillComplete(D0_Matrix->getDomainMap(), D0_Matrix->getRangeMap(),
1025 toCrsMatrix(D0_Matrix)->getCrsGraph()->getImporter(),
1026 toCrsMatrix(D0_Matrix)->getCrsGraph()->getExporter());
1027 D0_Matrix_ = D0copy;
1029 D0_Matrix_ = MatrixFactory::BuildCopy(D0_Matrix);
1031 if (check_D0_scaling_)
1034 Kn_Matrix_ = Kn_Matrix;
1036 Material_ = Material;
1037 Nullspace_ = Nullspace;
1039 if (!CurlCurl_Matrix.is_null()) {
1040 precList11_.sublist(
"user data").set(
"CurlCurl", CurlCurl_Matrix);
1041 dump(*CurlCurl_Matrix,
"CurlCurl.m");
1044 dump(*D0_Matrix_,
"D0.m");
1045 if (!Kn_Matrix_.is_null()) dump(*Kn_Matrix_,
"Kn.m");
1046 if (!Nullspace_.is_null()) dump(*Nullspace_,
"nullspace.m");
1047 if (!Coords_.is_null()) dumpCoords(*Coords_,
"coords.m");
1052 describe(Teuchos::FancyOStream& out,
const Teuchos::EVerbosityLevel )
const {
1053 std::ostringstream oss;
1055 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->getDomainMap()->getComm();
1059 if (!Kn_Matrix_.is_null())
1060 root = comm->getRank();
1065 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
1069 oss <<
"\n--------------------------------------------------------------------------------\n"
1070 <<
"--- Maxwell1 Summary ---\n"
1071 "--------------------------------------------------------------------------------"
1078 SM_Matrix_->getRowMap()->getComm()->barrier();
1080 numRows = SM_Matrix_->getGlobalNumRows();
1081 nnz = SM_Matrix_->getGlobalNumEntries();
1083 Xpetra::global_size_t tt = numRows;
1096 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
1097 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
1099 if (!Kn_Matrix_.is_null()) {
1101 numRows = Kn_Matrix_->getGlobalNumRows();
1102 nnz = Kn_Matrix_->getGlobalNumEntries();
1104 oss <<
"(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
1109 std::string outstr = oss.str();
1112 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1113 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
1115 int strLength = outstr.size();
1116 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
1117 if (comm->getRank() != root)
1118 outstr.resize(strLength);
1119 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
1124 if (!Hierarchy11_.is_null())
1125 Hierarchy11_->describe(out, GetVerbLevel());
1127 if (!Hierarchy22_.is_null())
1128 Hierarchy22_->describe(out, GetVerbLevel());
1130 if (!HierarchyGmhd_.is_null())
1131 HierarchyGmhd_->describe(out, GetVerbLevel());
1135 std::ostringstream oss2;
1137 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
1138 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;
1140 int numProcs = comm->getSize();
1142 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
1144 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
1148 if (!Kn_Matrix_.is_null())
1150 std::vector<char> states(numProcs, 0);
1152 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
1154 states.push_back(status);
1157 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
1158 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
1159 for (
int j = 0; j < rowWidth; j++)
1160 if (proc + j < numProcs)
1161 if (states[proc + j] == 0)
1163 else if (states[proc + j] == 1)
1165 else if (states[proc + j] == 2)
1172 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;