10#ifndef MUELU_REFMAXWELL_DEF_HPP
11#define MUELU_REFMAXWELL_DEF_HPP
17#include "Teuchos_Assert.hpp"
18#include "Teuchos_CompilerCodeTweakMacros.hpp"
19#include "Tpetra_CrsMatrix.hpp"
20#include "Xpetra_CrsMatrix.hpp"
21#include "Xpetra_Map.hpp"
22#include "Xpetra_MatrixMatrix.hpp"
23#include "Xpetra_MultiVector.hpp"
24#include "Xpetra_TripleMatrixMultiply.hpp"
26#include "Xpetra_MatrixUtils.hpp"
30#include "MueLu_AmalgamationFactory.hpp"
31#include "MueLu_RAPFactory.hpp"
32#include "MueLu_SmootherFactory.hpp"
34#include "MueLu_CoalesceDropFactory.hpp"
35#include "MueLu_CoarseMapFactory.hpp"
36#include "MueLu_CoordinatesTransferFactory.hpp"
37#include "MueLu_UncoupledAggregationFactory.hpp"
38#include "MueLu_TentativePFactory.hpp"
39#include "MueLu_SaPFactory.hpp"
40#include "MueLu_AggregationExportFactory.hpp"
41#include "MueLu_Utilities.hpp"
42#include "MueLu_Maxwell_Utils.hpp"
44#include "MueLu_CoalesceDropFactory_kokkos.hpp"
45#include "MueLu_TentativePFactory_kokkos.hpp"
46#include <Kokkos_Core.hpp>
47#include <KokkosSparse_CrsMatrix.hpp>
49#include "MueLu_ZoltanInterface.hpp"
50#include "MueLu_Zoltan2Interface.hpp"
51#include "MueLu_RepartitionHeuristicFactory.hpp"
52#include "MueLu_RepartitionFactory.hpp"
53#include "MueLu_RebalanceAcFactory.hpp"
54#include "MueLu_RebalanceTransferFactory.hpp"
63#include "cuda_profiler_api.h"
67#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
74T
pop(Teuchos::ParameterList &pl, std::string
const &name_in) {
75 T result = pl.get<T>(name_in);
76 pl.remove(name_in,
true);
81T
pop(Teuchos::ParameterList &pl, std::string
const &name_in, T def_value) {
82 T result = pl.get<T>(name_in, def_value);
83 pl.remove(name_in,
false);
87template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
89 return SM_Matrix_->getDomainMap();
92template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
94 return SM_Matrix_->getRangeMap();
97template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
98Teuchos::RCP<Teuchos::ParameterList>
101 bool useKokkosDefault = !Node::is_serial;
103 RCP<ParameterList> params = rcp(
new ParameterList(
"RefMaxwell"));
105 params->set<RCP<Matrix>>(
"Dk_1", Teuchos::null);
106 params->set<RCP<Matrix>>(
"Dk_2", Teuchos::null);
107 params->set<RCP<Matrix>>(
"D0", Teuchos::null);
109 params->set<RCP<Matrix>>(
"M1_beta", Teuchos::null);
110 params->set<RCP<Matrix>>(
"M1_alpha", Teuchos::null);
112 params->set<RCP<Matrix>>(
"Ms", Teuchos::null);
114 params->set<RCP<Matrix>>(
"Mk_one", Teuchos::null);
115 params->set<RCP<Matrix>>(
"Mk_1_one", Teuchos::null);
117 params->set<RCP<Matrix>>(
"M1", Teuchos::null);
119 params->set<RCP<Matrix>>(
"invMk_1_invBeta", Teuchos::null);
120 params->set<RCP<Matrix>>(
"invMk_2_invAlpha", Teuchos::null);
122 params->set<RCP<Matrix>>(
"M0inv", Teuchos::null);
124 params->set<RCP<MultiVector>>(
"Nullspace", Teuchos::null);
125 params->set<RCP<RealValuedMultiVector>>(
"Coordinates", Teuchos::null);
127 auto spaceValidator = rcp(
new Teuchos::EnhancedNumberValidator<int>(1, 2));
128 params->set(
"refmaxwell: space number", 1,
"", spaceValidator);
129 params->set(
"verbosity", MasterList::getDefault<std::string>(
"verbosity"));
130 params->set(
"use kokkos refactor", useKokkosDefault);
131 params->set(
"half precision",
false);
132 params->set(
"parameterlist: syntax", MasterList::getDefault<std::string>(
"parameterlist: syntax"));
133 params->set(
"output filename", MasterList::getDefault<std::string>(
"output filename"));
134 params->set(
"print initial parameters", MasterList::getDefault<bool>(
"print initial parameters"));
135 params->set(
"refmaxwell: disable addon", MasterList::getDefault<bool>(
"refmaxwell: disable addon"));
136 params->set(
"refmaxwell: disable addon 22",
true);
137 params->set(
"refmaxwell: mode", MasterList::getDefault<std::string>(
"refmaxwell: mode"));
138 params->set(
"refmaxwell: use as preconditioner", MasterList::getDefault<bool>(
"refmaxwell: use as preconditioner"));
139 params->set(
"refmaxwell: dump matrices", MasterList::getDefault<bool>(
"refmaxwell: dump matrices"));
140 params->set(
"refmaxwell: enable reuse", MasterList::getDefault<bool>(
"refmaxwell: enable reuse"));
141 params->set(
"refmaxwell: skip first (1,1) level", MasterList::getDefault<bool>(
"refmaxwell: skip first (1,1) level"));
142 params->set(
"refmaxwell: skip first (2,2) level",
false);
143 params->set(
"multigrid algorithm",
"Unsmoothed");
144 params->set(
"transpose: use implicit", MasterList::getDefault<bool>(
"transpose: use implicit"));
145 params->set(
"rap: triple product", MasterList::getDefault<bool>(
"rap: triple product"));
146 params->set(
"rap: fix zero diagonals",
true);
147 params->set(
"rap: fix zero diagonals threshold", MasterList::getDefault<double>(
"rap: fix zero diagonals threshold"));
148 params->set(
"fuse prolongation and update", MasterList::getDefault<bool>(
"fuse prolongation and update"));
149 params->set(
"refmaxwell: async transfers", Node::is_gpu);
150 params->set(
"refmaxwell: subsolves on subcommunicators", MasterList::getDefault<bool>(
"refmaxwell: subsolves on subcommunicators"));
151 params->set(
"refmaxwell: subsolves striding", 1);
152 params->set(
"refmaxwell: row sum drop tol (1,1)", MasterList::getDefault<double>(
"aggregation: row sum drop tol"));
153 params->set(
"sync timers",
false);
154 params->set(
"refmaxwell: num iters coarse 11", 1);
155 params->set(
"refmaxwell: num iters 22", 1);
156 params->set(
"refmaxwell: apply BCs to Anodal",
false);
157 params->set(
"refmaxwell: apply BCs to coarse 11",
true);
158 params->set(
"refmaxwell: apply BCs to 22",
true);
159 params->set(
"refmaxwell: max coarse size", 1);
161 ParameterList &precList11 = params->sublist(
"refmaxwell: 11list");
162 precList11.disableRecursiveValidation();
163 ParameterList &precList22 = params->sublist(
"refmaxwell: 22list");
164 precList22.disableRecursiveValidation();
166 params->set(
"smoother: type",
"CHEBYSHEV");
167 ParameterList &smootherList = params->sublist(
"smoother: params");
168 smootherList.disableRecursiveValidation();
169 params->set(
"smoother: pre type",
"NONE");
170 ParameterList &preSmootherList = params->sublist(
"smoother: pre params");
171 preSmootherList.disableRecursiveValidation();
172 params->set(
"smoother: post type",
"NONE");
173 ParameterList &postSmootherList = params->sublist(
"smoother: post params");
174 postSmootherList.disableRecursiveValidation();
176 ParameterList &matvecParams = params->sublist(
"matvec params");
177 matvecParams.disableRecursiveValidation();
179 ParameterList &importerCoarse11Params = params->sublist(
"refmaxwell: ImporterCoarse11 params");
180 importerCoarse11Params.disableRecursiveValidation();
182 ParameterList &importer22Params = params->sublist(
"refmaxwell: Importer22 params");
183 importer22Params.disableRecursiveValidation();
185 params->set(
"multigrid algorithm",
"unsmoothed");
186 params->set(
"aggregation: type", MasterList::getDefault<std::string>(
"aggregation: type"));
187 params->set(
"aggregation: drop tol", MasterList::getDefault<double>(
"aggregation: drop tol"));
188 params->set(
"aggregation: drop scheme", MasterList::getDefault<std::string>(
"aggregation: drop scheme"));
189 params->set(
"aggregation: distance laplacian algo", MasterList::getDefault<std::string>(
"aggregation: distance laplacian algo"));
190 params->set(
"aggregation: min agg size", MasterList::getDefault<int>(
"aggregation: min agg size"));
191 params->set(
"aggregation: max agg size", MasterList::getDefault<int>(
"aggregation: max agg size"));
192 params->set(
"aggregation: match ML phase1", MasterList::getDefault<bool>(
"aggregation: match ML phase1"));
193 params->set(
"aggregation: match ML phase2a", MasterList::getDefault<bool>(
"aggregation: match ML phase2a"));
194 params->set(
"aggregation: match ML phase2b", MasterList::getDefault<bool>(
"aggregation: match ML phase2b"));
195 params->set(
"aggregation: export visualization data", MasterList::getDefault<bool>(
"aggregation: export visualization data"));
200template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
202 if (list.isType<std::string>(
"parameterlist: syntax") && list.get<std::string>(
"parameterlist: syntax") ==
"ml") {
203 Teuchos::ParameterList newList;
206 RCP<Teuchos::ParameterList> validateParameters = getValidParamterList();
207 for (
auto it = newList2.begin(); it != newList2.end(); ++it) {
208 const std::string &entry_name = it->first;
209 if (validateParameters->isParameter(entry_name)) {
210 ParameterEntry theEntry = newList2.getEntry(entry_name);
211 newList.setEntry(entry_name, theEntry);
216 if (list.isSublist(
"refmaxwell: 11list") && list.sublist(
"refmaxwell: 11list").isSublist(
"edge matrix free: coarse"))
218 if (list.isSublist(
"refmaxwell: 22list"))
223 parameterList_ = list;
224 parameterList_.validateParametersAndSetDefaults(*getValidParamterList());
225 std::string verbosityLevel = parameterList_.get<std::string>(
"verbosity");
227 std::string outputFilename = parameterList_.get<std::string>(
"output filename");
228 if (outputFilename !=
"")
230 if (parameterList_.isType<Teuchos::RCP<Teuchos::FancyOStream>>(
"output stream"))
233 if (parameterList_.get<
bool>(
"print initial parameters"))
234 GetOStream(
static_cast<MsgType>(
Runtime1), 0) << parameterList_ << std::endl;
235 disable_addon_ = parameterList_.get<
bool>(
"refmaxwell: disable addon");
236 disable_addon_22_ = parameterList_.get<
bool>(
"refmaxwell: disable addon 22");
237 mode_ = parameterList_.get<std::string>(
"refmaxwell: mode");
238 use_as_preconditioner_ = parameterList_.get<
bool>(
"refmaxwell: use as preconditioner");
239 dump_matrices_ = parameterList_.get<
bool>(
"refmaxwell: dump matrices");
240 enable_reuse_ = parameterList_.get<
bool>(
"refmaxwell: enable reuse");
241 implicitTranspose_ = parameterList_.get<
bool>(
"transpose: use implicit");
242 fuseProlongationAndUpdate_ = parameterList_.get<
bool>(
"fuse prolongation and update");
243 skipFirst11Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (1,1) level");
244 skipFirst22Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (2,2) level");
245 if (spaceNumber_ == 1)
246 skipFirst22Level_ =
false;
247 syncTimers_ = parameterList_.get<
bool>(
"sync timers");
248 useKokkos_ = parameterList_.get<
bool>(
"use kokkos refactor");
249 numItersCoarse11_ = parameterList_.get<
int>(
"refmaxwell: num iters coarse 11");
250 numIters22_ = parameterList_.get<
int>(
"refmaxwell: num iters 22");
251 applyBCsToAnodal_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to Anodal");
252 applyBCsToCoarse11_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to coarse 11");
253 applyBCsTo22_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to 22");
255 precList11_ = parameterList_.sublist(
"refmaxwell: 11list");
256 if (!precList11_.isType<std::string>(
"Preconditioner Type") &&
257 !precList11_.isType<std::string>(
"smoother: type") &&
258 !precList11_.isType<std::string>(
"smoother: pre type") &&
259 !precList11_.isType<std::string>(
"smoother: post type")) {
260 precList11_.set(
"smoother: type",
"CHEBYSHEV");
261 precList11_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
262 precList11_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 5.4);
263 precList11_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
266 precList22_ = parameterList_.sublist(
"refmaxwell: 22list");
267 if (!precList22_.isType<std::string>(
"Preconditioner Type") &&
268 !precList22_.isType<std::string>(
"smoother: type") &&
269 !precList22_.isType<std::string>(
"smoother: pre type") &&
270 !precList22_.isType<std::string>(
"smoother: post type")) {
271 precList22_.set(
"smoother: type",
"CHEBYSHEV");
272 precList22_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
273 precList22_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 7.0);
274 precList22_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
277 if (!parameterList_.isType<std::string>(
"smoother: type") && !parameterList_.isType<std::string>(
"smoother: pre type") && !parameterList_.isType<std::string>(
"smoother: post type")) {
278 list.set(
"smoother: type",
"CHEBYSHEV");
279 list.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
280 list.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 20.0);
281 list.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
285 !precList11_.isType<std::string>(
"Preconditioner Type") &&
286 !precList11_.isParameter(
"reuse: type"))
287 precList11_.set(
"reuse: type",
"full");
289 !precList22_.isType<std::string>(
"Preconditioner Type") &&
290 !precList22_.isParameter(
"reuse: type"))
291 precList22_.set(
"reuse: type",
"full");
294template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
296 using memory_space =
typename Node::device_type::memory_space;
298#ifdef HAVE_MUELU_CUDA
299 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStart();
302 std::string timerLabel;
304 timerLabel =
"compute (reuse)";
306 timerLabel =
"compute";
307 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
317 RCP<ParameterList> params = rcp(
new ParameterList());
318 params->set(
"printLoadBalancingInfo",
true);
319 params->set(
"printCommInfo",
true);
326 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
328 BCrows11_, BCcols22_, BCdomain22_,
329 globalNumberBoundaryUnknowns11_,
330 globalNumberBoundaryUnknowns22_,
331 onlyBoundary11_, onlyBoundary22_);
332 if (spaceNumber_ == 2) {
333 Kokkos::View<bool *, memory_space> BCcolsEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), Dk_1_->getColMap()->getLocalNumElements());
334 Kokkos::View<bool *, memory_space> BCdomainEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), Dk_1_->getDomainMap()->getLocalNumElements());
337 Kokkos::View<bool *, memory_space> BCcolsNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), D0_->getColMap()->getLocalNumElements());
338 Kokkos::View<bool *, memory_space> BCdomainNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), D0_->getDomainMap()->getLocalNumElements());
340 BCdomain22_ = BCdomainNode;
343 GetOStream(
Statistics2) << solverName_ +
"::compute(): Detected " << globalNumberBoundaryUnknowns11_ <<
" BC rows and " << globalNumberBoundaryUnknowns22_ <<
" BC columns." << std::endl;
345 dump(BCrows11_,
"BCrows11.m");
346 dump(BCcols22_,
"BCcols22.m");
347 dump(BCdomain22_,
"BCdomain22.m");
350 if (onlyBoundary11_) {
353 GetOStream(
Warnings0) <<
"All unknowns of the (1,1) block have been detected as boundary unknowns!" << std::endl;
355 setFineLevelSmoother11();
361 dim_ = NodalCoords_->getNumVectors();
368 if (Nullspace11_ != null) {
369 TEUCHOS_ASSERT(Nullspace11_->getMap()->isCompatible(*(SM_Matrix_->getRowMap())));
370 }
else if (NodalCoords_ != null) {
371 Nullspace11_ = buildNullspace(spaceNumber_, BCrows11_, skipFirst11Level_);
373 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
378 RCP<Matrix> A11_nodal;
379 if (skipFirst11Level_) {
381 std::string label(
"D0^T*M1_beta*D0");
384 if (applyBCsToAnodal_) {
388 A11_nodal->setObjectLabel(solverName_ +
" (1,1) A_nodal");
389 dump(A11_nodal,
"A11_nodal.m");
392 M1_beta_ = Teuchos::null;
395 buildProlongator(spaceNumber_, A11_nodal, Nullspace11_, P11_, NullspaceCoarse11_, CoordsCoarse11_);
402 if (Nullspace22_ != null) {
403 TEUCHOS_ASSERT(Nullspace22_->getMap()->isCompatible(*(Dk_1_->getDomainMap())));
404 }
else if (NodalCoords_ != null)
405 Nullspace22_ = buildNullspace(spaceNumber_ - 1, BCdomain22_, skipFirst22Level_);
407 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
412 RCP<Matrix> A22_nodal;
413 if (skipFirst22Level_) {
415 std::string label(
"D0^T*M1_alpha*D0");
418 if (applyBCsToAnodal_) {
422 A22_nodal->setObjectLabel(solverName_ +
" (2,2) A_nodal");
423 dump(A22_nodal,
"A22_nodal.m");
426 M1_alpha_ = Teuchos::null;
429 buildProlongator(spaceNumber_ - 1, A22_nodal, Nullspace22_, P22_, CoarseNullspace22_, Coords22_);
437 buildCoarse11Matrix();
442 int rebalanceStriding, numProcsCoarseA11, numProcsA22;
444 this->determineSubHierarchyCommSizes(doRebalancing, rebalanceStriding, numProcsCoarseA11, numProcsA22);
446 doRebalancing =
false;
449 if (!reuse && doRebalancing)
450 rebalanceCoarse11Matrix(rebalanceStriding, numProcsCoarseA11);
451 if (!coarseA11_.is_null()) {
452 dump(coarseA11_,
"coarseA11.m");
454 dumpCoords(CoordsCoarse11_,
"CoordsCoarse11.m");
455 dump(NullspaceCoarse11_,
"NullspaceCoarse11.m");
460 if (!implicitTranspose_) {
467 if (!coarseA11_.is_null()) {
469 std::string label(
"coarseA11");
470 if (!precList11_.isType<std::string>(
"hierarchy label"))
471 precList11_.set(
"hierarchy label", solverName_ +
" coarse (1,1)");
472 setupSubSolve(HierarchyCoarse11_, thyraPrecOpH_, coarseA11_, NullspaceCoarse11_, CoordsCoarse11_, Material_beta_, precList11_, label, reuse);
478 if (!reuse && applyBCsTo22_) {
479 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC columns of Dk_1" << std::endl;
482 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
484 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
489 if (!onlyBoundary22_) {
490 GetOStream(
Runtime0) << solverName_ +
"::compute(): building MG for (2,2)-block" << std::endl;
493 build22Matrix(reuse, doRebalancing, rebalanceStriding, numProcsA22);
495 if (!P22_.is_null()) {
496 std::string label(
"P22^T*A22*P22");
498 coarseA22_->SetFixedBlockSize(A22_->GetFixedBlockSize());
499 coarseA22_->setObjectLabel(solverName_ +
" coarse (2, 2)");
500 dump(coarseA22_,
"coarseA22.m");
503 if (!reuse && !implicitTranspose_) {
509 if (!A22_.is_null()) {
511 std::string label(
"A22");
512 if (!precList22_.isType<std::string>(
"hierarchy label"))
513 precList22_.set(
"hierarchy label", solverName_ +
" (2,2)");
514 if (!P22_.is_null()) {
515 precList22_.sublist(
"level 1 user data").set(
"A", coarseA22_);
516 precList22_.sublist(
"level 1 user data").set(
"P", P22_);
517 if (!implicitTranspose_)
518 precList22_.sublist(
"level 1 user data").set(
"R", R22_);
519 precList22_.sublist(
"level 1 user data").set(
"Nullspace", CoarseNullspace22_);
520 precList22_.sublist(
"level 1 user data").set(
"Coordinates", Coords22_);
523 int maxCoarseSize = precList22_.get(
"coarse: max size", MasterList::getDefault<int>(
"coarse: max size"));
524 int numRows = Teuchos::as<int>(coarseA22_->getGlobalNumRows());
525 if (maxCoarseSize > numRows)
526 precList22_.set(
"coarse: max size", numRows);
527 int maxLevels = precList22_.get(
"max levels", MasterList::getDefault<int>(
"max levels"));
529 precList22_.set(
"max levels", 2);
530 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, Teuchos::null, Teuchos::null, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
532 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, CoarseNullspace22_, Coords22_, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
540 if (!reuse && !onlyBoundary22_ && applyBCsTo22_) {
541 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC rows of Dk_1" << std::endl;
544 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
546 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
547 dump(Dk_1_,
"Dk_1_nuked.m");
552 setFineLevelSmoother11();
555 if (!ImporterCoarse11_.is_null()) {
556 RCP<const Import> ImporterP11 = ImportFactory::Build(ImporterCoarse11_->getTargetMap(), P11_->getColMap());
557 toCrsMatrix(P11_)->replaceDomainMapAndImporter(ImporterCoarse11_->getTargetMap(), ImporterP11);
560 if (!Importer22_.is_null()) {
562 DorigDomainMap_ = Dk_1_->getDomainMap();
563 DorigImporter_ = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
565 RCP<const Import> ImporterD = ImportFactory::Build(Importer22_->getTargetMap(), Dk_1_->getColMap());
566 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), ImporterD);
569 if ((!Dk_1_T_.is_null()) &&
571 (!toCrsMatrix(Dk_1_T_)->getCrsGraph()->getImporter().is_null()) &&
572 (!toCrsMatrix(R11_)->getCrsGraph()->getImporter().is_null()) &&
573 (Dk_1_T_->getColMap()->lib() == Xpetra::UseTpetra) &&
574 (R11_->getColMap()->lib() == Xpetra::UseTpetra))
575 Dk_1_T_R11_colMapsMatch_ = Dk_1_T_->getColMap()->isSameAs(*R11_->getColMap());
577 Dk_1_T_R11_colMapsMatch_ =
false;
578 if (Dk_1_T_R11_colMapsMatch_)
579 GetOStream(
Runtime0) << solverName_ +
"::compute(): Dk_1_T and R11 have matching colMaps" << std::endl;
581 asyncTransfers_ = parameterList_.get<
bool>(
"refmaxwell: async transfers");
587 if (parameterList_.isSublist(
"matvec params")) {
588 RCP<ParameterList> matvecParams = rcpFromRef(parameterList_.sublist(
"matvec params"));
594 if (!ImporterCoarse11_.is_null()) ImporterCoarse11_->setDistributorParameters(matvecParams);
595 if (!Importer22_.is_null()) Importer22_->setDistributorParameters(matvecParams);
597 if (!ImporterCoarse11_.is_null() && parameterList_.isSublist(
"refmaxwell: ImporterCoarse11 params")) {
598 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: ImporterCoarse11 params"));
599 ImporterCoarse11_->setDistributorParameters(importerParams);
601 if (!Importer22_.is_null() && parameterList_.isSublist(
"refmaxwell: Importer22 params")) {
602 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: Importer22 params"));
603 Importer22_->setDistributorParameters(importerParams);
609#ifdef HAVE_MUELU_CUDA
610 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStop();
614template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
617 doRebalancing = parameterList_.get<
bool>(
"refmaxwell: subsolves on subcommunicators");
618 rebalanceStriding = parameterList_.get<
int>(
"refmaxwell: subsolves striding", -1);
619 int numProcs = SM_Matrix_->getDomainMap()->getComm()->getSize();
621 doRebalancing =
false;
633 level.
Set(
"A", coarseA11_);
636 ParameterList repartheurParams;
637 repartheurParams.set(
"repartition: start level", 0);
639 int defaultTargetRows = 10000;
640 repartheurParams.set(
"repartition: min rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
641 repartheurParams.set(
"repartition: target rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
642 repartheurParams.set(
"repartition: min rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
643 repartheurParams.set(
"repartition: target rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
644 repartheurParams.set(
"repartition: max imbalance", precList11_.get<
double>(
"repartition: max imbalance", 1.1));
645 repartheurFactory->SetParameterList(repartheurParams);
647 level.
Request(
"number of partitions", repartheurFactory.get());
648 repartheurFactory->Build(level);
649 numProcsCoarseA11 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
650 numProcsCoarseA11 = std::min(numProcsCoarseA11, numProcs);
660 level.
Set(
"Map", Dk_1_->getDomainMap());
663 ParameterList repartheurParams;
664 repartheurParams.set(
"repartition: start level", 0);
665 repartheurParams.set(
"repartition: use map",
true);
667 int defaultTargetRows = 10000;
668 repartheurParams.set(
"repartition: min rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
669 repartheurParams.set(
"repartition: target rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
670 repartheurParams.set(
"repartition: min rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
671 repartheurParams.set(
"repartition: target rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
673 repartheurFactory->SetParameterList(repartheurParams);
675 level.
Request(
"number of partitions", repartheurFactory.get());
676 repartheurFactory->Build(level);
677 numProcsA22 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
678 numProcsA22 = std::min(numProcsA22, numProcs);
681 if (rebalanceStriding >= 1) {
682 TEUCHOS_ASSERT(rebalanceStriding * numProcsCoarseA11 <= numProcs);
683 TEUCHOS_ASSERT(rebalanceStriding * numProcsA22 <= numProcs);
684 if (rebalanceStriding * (numProcsCoarseA11 + numProcsA22) > numProcs) {
685 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling striding = " << rebalanceStriding <<
", since coarseA11 needs " << numProcsCoarseA11
686 <<
" procs and A22 needs " << numProcsA22 <<
" procs." << std::endl;
687 rebalanceStriding = -1;
689 int lclBadMatrixDistribution = (coarseA11_->getLocalNumEntries() == 0) || (Dk_1_->getDomainMap()->getLocalNumElements() == 0);
690 int gblBadMatrixDistribution =
false;
691 MueLu_maxAll(SM_Matrix_->getDomainMap()->getComm(), lclBadMatrixDistribution, gblBadMatrixDistribution);
692 if (gblBadMatrixDistribution) {
693 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling striding = " << rebalanceStriding <<
", since coarseA11 has no entries on at least one rank or Dk_1's domain map has no entries on at least one rank." << std::endl;
694 rebalanceStriding = -1;
698 if ((numProcsCoarseA11 < 0) || (numProcsA22 < 0) || (numProcsCoarseA11 + numProcsA22 > numProcs)) {
699 std::stringstream ss;
700 ss << solverName_ +
"::compute(): Partition heuristic resulted "
701 <<
"in undesirable number of partitions: " << numProcsCoarseA11 <<
", " << numProcsA22 <<
".";
703 if (numProcsCoarseA11 < 0)
704 numProcsCoarseA11 = numProcs;
706 numProcsA22 = numProcs;
708 double ratioCoarseA11 = ((double)numProcsCoarseA11) / ((double)(numProcsCoarseA11 + numProcsA22));
709 double ratioA22 = ((double)numProcsA22) / ((double)(numProcsCoarseA11 + numProcsA22));
710 numProcsCoarseA11 = std::round(ratioCoarseA11 * numProcs);
711 numProcsA22 = std::round(ratioA22 * numProcs);
713 if (numProcsCoarseA11 == 0) {
714 numProcsCoarseA11 = 1;
715 numProcsA22 = numProcs - 1;
717 if (numProcsA22 == 0) {
718 numProcsCoarseA11 = numProcs - 1;
722 ss <<
". Adjusting to fit: " << numProcsCoarseA11 <<
", " << numProcsA22 << std::endl;
725 TEUCHOS_ASSERT_INEQUALITY(numProcsCoarseA11, >, 0);
726 TEUCHOS_ASSERT_INEQUALITY(numProcsA22, >, 0);
727 TEUCHOS_ASSERT_EQUALITY(numProcsCoarseA11 + numProcsA22, numProcs);
731 doRebalancing =
false;
735template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
738 if (spaceNumber == 0)
739 return Teuchos::null;
741 std::string timerLabel;
742 if (spaceNumber == spaceNumber_) {
743 if (skipFirst11Level_)
744 timerLabel =
"Build coarse addon matrix 11";
746 timerLabel =
"Build addon matrix 11";
748 timerLabel =
"Build addon matrix 22";
750 RCP<Teuchos::TimeMonitor> tmAddon = getTimer(timerLabel);
754 RCP<Matrix> lumpedInverse;
755 if (spaceNumber == spaceNumber_) {
757 TEUCHOS_TEST_FOR_EXCEPTION(invMk_1_invBeta_ == Teuchos::null, std::invalid_argument,
759 "::buildCoarse11Matrix(): Inverse of "
760 "lumped mass matrix required for add-on (i.e. invMk_1_invBeta_ is null)");
761 lumpedInverse = invMk_1_invBeta_;
763 if (skipFirst11Level_) {
766 Zaux = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Mk_one_,
false, *P11_,
false, Zaux, GetOStream(
Runtime0),
true,
true);
768 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Zaux,
false, Z, GetOStream(
Runtime0),
true,
true);
771 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Mk_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
774 }
else if (spaceNumber == spaceNumber_ - 1) {
776 TEUCHOS_TEST_FOR_EXCEPTION(invMk_2_invAlpha_ == Teuchos::null, std::invalid_argument,
778 "::buildCoarse11Matrix(): Inverse of "
779 "lumped mass matrix required for add-on (i.e. invMk_2_invAlpha_ is null)");
780 lumpedInverse = invMk_2_invAlpha_;
783 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_2_,
true, *Mk_1_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
787 if (lumpedInverse->getGlobalMaxNumRowEntries() <= 1) {
790 RCP<Vector> diag = VectorFactory::Build(lumpedInverse->getRowMap());
791 lumpedInverse->getLocalDiagCopy(*diag);
793 ArrayRCP<Scalar> diagVals = diag->getDataNonConst(0);
794 for (
size_t j = 0; j < diag->getMap()->getLocalNumElements(); j++) {
795 diagVals[j] = Teuchos::ScalarTraits<Scalar>::squareroot(diagVals[j]);
798 if (Z->getRowMap()->isSameAs(*(diag->getMap())))
801 RCP<Import> importer = ImportFactory::Build(diag->getMap(), Z->getRowMap());
802 RCP<Vector> diag2 = VectorFactory::Build(Z->getRowMap());
803 diag2->doImport(*diag, *importer, Xpetra::INSERT);
804 Z->leftScale(*diag2);
806 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *Z,
false, addon, GetOStream(
Runtime0),
true,
true);
807 }
else if (parameterList_.get<
bool>(
"rap: triple product",
false) ==
false) {
810 C2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*lumpedInverse,
false, *Z,
false, C2, GetOStream(
Runtime0),
true,
true);
812 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *C2,
false, addon, GetOStream(
Runtime0),
true,
true);
814 addon = MatrixFactory::Build(Z->getDomainMap());
816 Xpetra::TripleMatrixMultiply<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
817 MultiplyRAP(*Z,
true, *lumpedInverse,
false, *Z,
false, *addon,
true,
true);
822template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
824 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build coarse (1,1) matrix");
826 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
830 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *P11_,
false, temp, GetOStream(
Runtime0),
true,
true);
831 if (ImporterCoarse11_.is_null())
832 coarseA11_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, coarseA11_, GetOStream(
Runtime0),
true,
true);
835 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
837 RCP<const Map> map = ImporterCoarse11_->getTargetMap()->removeEmptyProcesses();
838 temp2->removeEmptyProcessesInPlace(map);
839 if (!temp2.is_null() && temp2->getRowMap().is_null())
840 temp2 = Teuchos::null;
844 if (!disable_addon_) {
847 if (!coarseA11_.is_null() && Addon11_.is_null()) {
848 addon = buildAddon(spaceNumber_);
855 if (!coarseA11_.is_null()) {
857 RCP<Matrix> newCoarseA11;
858 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*coarseA11_,
false, one, *addon,
false, one, newCoarseA11, GetOStream(
Runtime0));
859 newCoarseA11->fillComplete();
860 coarseA11_ = newCoarseA11;
864 if (!coarseA11_.is_null() && !skipFirst11Level_) {
865 ArrayRCP<bool> coarseA11BCrows;
866 coarseA11BCrows.resize(coarseA11_->getRowMap()->getLocalNumElements());
867 for (
size_t i = 0; i < BCdomain22_.size(); i++)
868 for (
size_t k = 0; k < dim_; k++)
869 coarseA11BCrows[i * dim_ + k] = BCdomain22_(i);
870 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
873 if (applyBCsToCoarse11_)
877 if (!coarseA11_.is_null()) {
883 bool fixZeroDiagonal = !applyBCsToAnodal_;
884 if (precList11_.isParameter(
"rap: fix zero diagonals"))
885 fixZeroDiagonal = precList11_.get<
bool>(
"rap: fix zero diagonals");
887 if (fixZeroDiagonal) {
890 if (precList11_.isType<
magnitudeType>(
"rap: fix zero diagonals threshold"))
891 threshold = precList11_.get<
magnitudeType>(
"rap: fix zero diagonals threshold");
892 else if (precList11_.isType<
double>(
"rap: fix zero diagonals threshold"))
893 threshold = Teuchos::as<magnitudeType>(precList11_.get<
double>(
"rap: fix zero diagonals threshold"));
894 if (precList11_.isType<
double>(
"rap: fix zero diagonals replacement"))
895 replacement = Teuchos::as<Scalar>(precList11_.get<
double>(
"rap: fix zero diagonals replacement"));
896 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(coarseA11_,
true, GetOStream(
Warnings1), threshold, replacement);
900 coarseA11_->SetFixedBlockSize(dim_);
901 if (skipFirst11Level_)
902 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
904 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
908template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
913 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Rebalance coarseA11");
915 Level fineLevel, coarseLevel;
921 coarseLevel.
Set(
"A", coarseA11_);
922 coarseLevel.
Set(
"P", P11_);
923 coarseLevel.
Set(
"Coordinates", CoordsCoarse11_);
924 if (!NullspaceCoarse11_.is_null())
925 coarseLevel.
Set(
"Nullspace", NullspaceCoarse11_);
926 coarseLevel.
Set(
"number of partitions", numProcsCoarseA11);
927 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
929 coarseLevel.
setlib(coarseA11_->getDomainMap()->lib());
930 fineLevel.
setlib(coarseA11_->getDomainMap()->lib());
931 coarseLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
932 fineLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
934 std::string partName = precList11_.get<std::string>(
"repartition: partitioner",
"zoltan2");
935 RCP<Factory> partitioner;
936 if (partName ==
"zoltan") {
937#ifdef HAVE_MUELU_ZOLTAN
944 }
else if (partName ==
"zoltan2") {
945#ifdef HAVE_MUELU_ZOLTAN2
947 ParameterList partParams;
948 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList11_.sublist(
"repartition: params",
false)));
949 partParams.set(
"ParameterList", partpartParams);
950 partitioner->SetParameterList(partParams);
958 ParameterList repartParams;
959 repartParams.set(
"repartition: print partition distribution", precList11_.get<
bool>(
"repartition: print partition distribution",
false));
960 repartParams.set(
"repartition: remap parts", precList11_.get<
bool>(
"repartition: remap parts",
true));
961 if (rebalanceStriding >= 1) {
962 bool acceptPart = (SM_Matrix_->getDomainMap()->getComm()->getRank() % rebalanceStriding) == 0;
963 if (SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsCoarseA11 * rebalanceStriding)
965 repartParams.set(
"repartition: remap accept partition", acceptPart);
967 repartFactory->SetParameterList(repartParams);
969 repartFactory->SetFactory(
"Partition", partitioner);
972 ParameterList newPparams;
973 newPparams.set(
"type",
"Interpolation");
974 newPparams.set(
"repartition: rebalance P and R", precList11_.get<
bool>(
"repartition: rebalance P and R",
false));
975 newPparams.set(
"repartition: use subcommunicators",
true);
976 newPparams.set(
"repartition: rebalance Nullspace", !NullspaceCoarse11_.is_null());
978 if (!NullspaceCoarse11_.is_null())
980 newP->SetParameterList(newPparams);
981 newP->SetFactory(
"Importer", repartFactory);
984 ParameterList rebAcParams;
985 rebAcParams.set(
"repartition: use subcommunicators",
true);
986 newA->SetParameterList(rebAcParams);
987 newA->SetFactory(
"Importer", repartFactory);
989 coarseLevel.
Request(
"P", newP.get());
990 coarseLevel.
Request(
"Importer", repartFactory.get());
991 coarseLevel.
Request(
"A", newA.get());
992 coarseLevel.
Request(
"Coordinates", newP.get());
993 if (!NullspaceCoarse11_.is_null())
994 coarseLevel.
Request(
"Nullspace", newP.get());
995 repartFactory->Build(coarseLevel);
997 if (!precList11_.get<
bool>(
"repartition: rebalance P and R",
false))
998 ImporterCoarse11_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
999 P11_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1000 coarseA11_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1001 CoordsCoarse11_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1002 if (!NullspaceCoarse11_.is_null())
1003 NullspaceCoarse11_ = coarseLevel.
Get<RCP<MultiVector>>(
"Nullspace", newP.get());
1005 if (!coarseA11_.is_null()) {
1007 coarseA11_->SetFixedBlockSize(dim_);
1008 if (skipFirst11Level_)
1009 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
1011 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
1014 coarseA11_AP_reuse_data_ = Teuchos::null;
1015 coarseA11_RAP_reuse_data_ = Teuchos::null;
1017 if (!disable_addon_ && enable_reuse_) {
1019 RCP<const Import> ImporterCoarse11 = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1020 RCP<const Map> targetMap = ImporterCoarse11->getTargetMap();
1021 ParameterList XpetraList;
1022 XpetraList.set(
"Restrict Communicator",
true);
1023 Addon11_ = MatrixFactory::Build(Addon11_, *ImporterCoarse11, *ImporterCoarse11, targetMap, targetMap, rcp(&XpetraList,
false));
1028template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1031 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1033 Level fineLevel, coarseLevel;
1039 fineLevel.
Set(
"A", SM_Matrix_);
1040 coarseLevel.
Set(
"P", Dk_1_);
1041 coarseLevel.
Set(
"Coordinates", Coords22_);
1043 coarseLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1044 fineLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1045 coarseLevel.setObjectLabel(solverName_ +
" (2,2)");
1046 fineLevel.setObjectLabel(solverName_ +
" (2,2)");
1048 RCP<RAPFactory> rapFact = rcp(
new RAPFactory());
1049 ParameterList rapList = *(rapFact->GetValidParameterList());
1050 rapList.set(
"transpose: use implicit",
true);
1051 rapList.set(
"rap: fix zero diagonals", parameterList_.get<
bool>(
"rap: fix zero diagonals",
true));
1052 rapList.set(
"rap: fix zero diagonals threshold", parameterList_.get<
double>(
"rap: fix zero diagonals threshold", Teuchos::ScalarTraits<double>::eps()));
1053 rapList.set(
"rap: triple product", parameterList_.get<
bool>(
"rap: triple product",
false));
1054 rapFact->SetParameterList(rapList);
1056 if (!A22_AP_reuse_data_.is_null()) {
1057 coarseLevel.
AddKeepFlag(
"AP reuse data", rapFact.get());
1058 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"AP reuse data", A22_AP_reuse_data_, rapFact.get());
1060 if (!A22_RAP_reuse_data_.is_null()) {
1061 coarseLevel.
AddKeepFlag(
"RAP reuse data", rapFact.get());
1062 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"RAP reuse data", A22_RAP_reuse_data_, rapFact.get());
1066 if (doRebalancing) {
1067 coarseLevel.
Set(
"number of partitions", numProcsA22);
1068 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
1070 std::string partName = precList22_.get<std::string>(
"repartition: partitioner",
"zoltan2");
1071 RCP<Factory> partitioner;
1072 if (partName ==
"zoltan") {
1073#ifdef HAVE_MUELU_ZOLTAN
1075 partitioner->SetFactory(
"A", rapFact);
1081 }
else if (partName ==
"zoltan2") {
1082#ifdef HAVE_MUELU_ZOLTAN2
1084 ParameterList partParams;
1085 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList22_.sublist(
"repartition: params",
false)));
1086 partParams.set(
"ParameterList", partpartParams);
1087 partitioner->SetParameterList(partParams);
1088 partitioner->SetFactory(
"A", rapFact);
1096 ParameterList repartParams;
1097 repartParams.set(
"repartition: print partition distribution", precList22_.get<
bool>(
"repartition: print partition distribution",
false));
1098 repartParams.set(
"repartition: remap parts", precList22_.get<
bool>(
"repartition: remap parts",
true));
1099 if (rebalanceStriding >= 1) {
1100 bool acceptPart = ((SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank()) % rebalanceStriding) == 0;
1101 if (SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsA22 * rebalanceStriding)
1104 TEUCHOS_ASSERT(coarseA11_.is_null());
1105 repartParams.set(
"repartition: remap accept partition", acceptPart);
1107 repartParams.set(
"repartition: remap accept partition", coarseA11_.is_null());
1108 repartFactory->SetParameterList(repartParams);
1109 repartFactory->SetFactory(
"A", rapFact);
1111 repartFactory->SetFactory(
"Partition", partitioner);
1114 ParameterList newPparams;
1115 newPparams.set(
"type",
"Interpolation");
1116 newPparams.set(
"repartition: rebalance P and R", precList22_.get<
bool>(
"repartition: rebalance P and R",
false));
1117 newPparams.set(
"repartition: use subcommunicators",
true);
1118 newPparams.set(
"repartition: rebalance Nullspace",
false);
1120 newP->SetParameterList(newPparams);
1121 newP->SetFactory(
"Importer", repartFactory);
1124 ParameterList rebAcParams;
1125 rebAcParams.set(
"repartition: use subcommunicators",
true);
1126 newA->SetParameterList(rebAcParams);
1127 newA->SetFactory(
"A", rapFact);
1128 newA->SetFactory(
"Importer", repartFactory);
1130 coarseLevel.
Request(
"P", newP.get());
1131 coarseLevel.
Request(
"Importer", repartFactory.get());
1132 coarseLevel.
Request(
"A", newA.get());
1133 coarseLevel.
Request(
"Coordinates", newP.get());
1134 rapFact->Build(fineLevel, coarseLevel);
1135 repartFactory->Build(coarseLevel);
1137 if (!precList22_.get<
bool>(
"repartition: rebalance P and R",
false))
1138 Importer22_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1139 Dk_1_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1140 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1141 Coords22_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1143 if (!P22_.is_null()) {
1150 coarseLevel.
Request(
"A", rapFact.get());
1151 if (enable_reuse_) {
1152 coarseLevel.
Request(
"AP reuse data", rapFact.get());
1153 coarseLevel.
Request(
"RAP reuse data", rapFact.get());
1156 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", rapFact.get());
1158 if (enable_reuse_) {
1159 if (coarseLevel.
IsAvailable(
"AP reuse data", rapFact.get()))
1160 A22_AP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"AP reuse data", rapFact.get());
1161 if (coarseLevel.
IsAvailable(
"RAP reuse data", rapFact.get()))
1162 A22_RAP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"RAP reuse data", rapFact.get());
1166 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1167 if (Importer22_.is_null()) {
1169 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1170 if (!implicitTranspose_)
1171 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1173 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1176 RCP<const Import> Dimporter = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
1177 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(DorigDomainMap_, DorigImporter_);
1179 RCP<Matrix> temp, temp2;
1180 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1181 if (!implicitTranspose_)
1182 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1184 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1187 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), Dimporter);
1189 ParameterList XpetraList;
1190 XpetraList.set(
"Restrict Communicator",
true);
1191 XpetraList.set(
"Timer Label",
"MueLu::RebalanceA22");
1192 RCP<const Map> targetMap = Importer22_->getTargetMap();
1193 A22_ = MatrixFactory::Build(temp2, *Importer22_, *Importer22_, targetMap, targetMap, rcp(&XpetraList,
false));
1197 if (not A22_.is_null() and not disable_addon_22_ and spaceNumber_ > 1) {
1198 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1200 RCP<Matrix> addon22 = buildAddon(spaceNumber_ - 1);
1204 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A22_,
false, one, *addon22,
false, one, newA22, GetOStream(
Runtime0));
1205 newA22->fillComplete();
1209 if (!A22_.is_null()) {
1210 dump(A22_,
"A22.m");
1211 A22_->setObjectLabel(solverName_ +
" (2,2)");
1213 if (spaceNumber_ - 1 == 0)
1214 A22_->SetFixedBlockSize(1);
1216 A22_->SetFixedBlockSize(dim_);
1220template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1223 RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(
new FactoryManager());
1226 level.setObjectLabel(solverName_ +
" (1,1)");
1227 level.
Set(
"A", SM_Matrix_);
1228 level.
setlib(SM_Matrix_->getDomainMap()->lib());
1230 level.
Set(
"NodeMatrix", A22_);
1231 level.
Set(
"D0", Dk_1_);
1233 if ((parameterList_.get<std::string>(
"smoother: pre type") !=
"NONE") && (parameterList_.get<std::string>(
"smoother: post type") !=
"NONE")) {
1234 std::string preSmootherType = parameterList_.get<std::string>(
"smoother: pre type");
1235 std::string postSmootherType = parameterList_.get<std::string>(
"smoother: post type");
1237 ParameterList preSmootherList, postSmootherList;
1238 if (parameterList_.isSublist(
"smoother: pre params"))
1239 preSmootherList = parameterList_.sublist(
"smoother: pre params");
1240 if (parameterList_.isSublist(
"smoother: post params"))
1241 postSmootherList = parameterList_.sublist(
"smoother: post params");
1243 RCP<SmootherPrototype> preSmootherPrototype = rcp(
new TrilinosSmoother(preSmootherType, preSmootherList));
1244 RCP<SmootherPrototype> postSmootherPrototype = rcp(
new TrilinosSmoother(postSmootherType, postSmootherList));
1245 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(preSmootherPrototype, postSmootherPrototype));
1247 level.
Request(
"PreSmoother", smootherFact.get());
1248 level.
Request(
"PostSmoother", smootherFact.get());
1249 if (enable_reuse_) {
1250 ParameterList smootherFactoryParams;
1251 smootherFactoryParams.set(
"keep smoother data",
true);
1252 smootherFact->SetParameterList(smootherFactoryParams);
1253 level.
Request(
"PreSmoother data", smootherFact.get());
1254 level.
Request(
"PostSmoother data", smootherFact.get());
1255 if (!PreSmootherData11_.is_null())
1256 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1257 if (!PostSmootherData11_.is_null())
1258 level.
Set(
"PostSmoother data", PostSmootherData11_, smootherFact.get());
1260 smootherFact->Build(level);
1261 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1262 PostSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PostSmoother", smootherFact.get());
1263 if (enable_reuse_) {
1264 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1265 PostSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PostSmoother data", smootherFact.get());
1268 std::string smootherType = parameterList_.get<std::string>(
"smoother: type");
1270 ParameterList smootherList;
1271 if (parameterList_.isSublist(
"smoother: params"))
1272 smootherList = parameterList_.sublist(
"smoother: params");
1274 RCP<SmootherPrototype> smootherPrototype = rcp(
new TrilinosSmoother(smootherType, smootherList));
1275 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(smootherPrototype));
1276 level.
Request(
"PreSmoother", smootherFact.get());
1277 if (enable_reuse_) {
1278 ParameterList smootherFactoryParams;
1279 smootherFactoryParams.set(
"keep smoother data",
true);
1280 smootherFact->SetParameterList(smootherFactoryParams);
1281 level.
Request(
"PreSmoother data", smootherFact.get());
1282 if (!PreSmootherData11_.is_null())
1283 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1285 smootherFact->Build(level);
1286 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1287 PostSmoother11_ = PreSmoother11_;
1289 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1293template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1295 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer(
"Allocate MVs");
1298 if (!R11_.is_null())
1299 P11res_ = MultiVectorFactory::Build(R11_->getRangeMap(), numVectors);
1301 P11res_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1302 P11res_->setObjectLabel(
"P11res");
1304 if (Dk_1_T_R11_colMapsMatch_) {
1305 DTR11Tmp_ = MultiVectorFactory::Build(R11_->getColMap(), numVectors);
1306 DTR11Tmp_->setObjectLabel(
"DTR11Tmp");
1308 if (!ImporterCoarse11_.is_null()) {
1309 P11resTmp_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1310 P11resTmp_->setObjectLabel(
"P11resTmp");
1311 P11x_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1313 P11x_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1314 P11x_->setObjectLabel(
"P11x");
1317 if (!Dk_1_T_.is_null())
1318 Dres_ = MultiVectorFactory::Build(Dk_1_T_->getRangeMap(), numVectors);
1320 Dres_ = MultiVectorFactory::Build(Dk_1_->getDomainMap(), numVectors);
1321 Dres_->setObjectLabel(
"Dres");
1323 if (!Importer22_.is_null()) {
1324 DresTmp_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1325 DresTmp_->setObjectLabel(
"DresTmp");
1326 Dx_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1327 }
else if (!onlyBoundary22_)
1328 Dx_ = MultiVectorFactory::Build(A22_->getDomainMap(), numVectors);
1330 Dx_->setObjectLabel(
"Dx");
1332 if (!coarseA11_.is_null()) {
1333 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
1334 P11resSubComm_ = MultiVectorFactory::Build(P11resTmp_, Teuchos::View);
1336 P11resSubComm_ = MultiVectorFactory::Build(P11res_, Teuchos::View);
1337 P11resSubComm_->replaceMap(coarseA11_->getRangeMap());
1338 P11resSubComm_->setObjectLabel(
"P11resSubComm");
1340 P11xSubComm_ = MultiVectorFactory::Build(P11x_, Teuchos::View);
1341 P11xSubComm_->replaceMap(coarseA11_->getDomainMap());
1342 P11xSubComm_->setObjectLabel(
"P11xSubComm");
1345 if (!A22_.is_null()) {
1346 if (!Importer22_.is_null() && !implicitTranspose_)
1347 DresSubComm_ = MultiVectorFactory::Build(DresTmp_, Teuchos::View);
1349 DresSubComm_ = MultiVectorFactory::Build(Dres_, Teuchos::View);
1350 DresSubComm_->replaceMap(A22_->getRangeMap());
1351 DresSubComm_->setObjectLabel(
"DresSubComm");
1353 DxSubComm_ = MultiVectorFactory::Build(Dx_, Teuchos::View);
1354 DxSubComm_->replaceMap(A22_->getDomainMap());
1355 DxSubComm_->setObjectLabel(
"DxSubComm");
1358 if (asyncTransfers_) {
1359 if (!toCrsMatrix(P11_)->getCrsGraph()->getImporter().is_null())
1360 P11x_colmap_ = MultiVectorFactory::Build(P11_->getColMap(), numVectors);
1361 if (!toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter().is_null())
1362 Dx_colmap_ = MultiVectorFactory::Build(Dk_1_->getColMap(), numVectors);
1365 residual_ = MultiVectorFactory::Build(SM_Matrix_->getDomainMap(), numVectors);
1366 residual_->setObjectLabel(
"residual");
1369template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1371 if (dump_matrices_ && !A.is_null()) {
1372 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1373 Xpetra::IO<SC, LO, GO, NO>::Write(name, *A);
1377template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1379 if (dump_matrices_ && !X.is_null()) {
1380 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1381 Xpetra::IO<SC, LO, GO, NO>::Write(name, *X);
1385template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1387 if (dump_matrices_ && !X.is_null()) {
1388 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1389 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, *X);
1393template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1395 if (dump_matrices_) {
1396 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1397 std::ofstream out(name);
1398 for (
size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
1399 out << v[i] <<
"\n";
1403template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1405 if (dump_matrices_) {
1406 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1407 std::ofstream out(name);
1408 auto vH = Kokkos::create_mirror_view(v);
1409 Kokkos::deep_copy(vH, v);
1410 out <<
"%%MatrixMarket matrix array real general\n"
1411 << vH.extent(0) <<
" 1\n";
1412 for (
size_t i = 0; i < vH.size(); i++)
1413 out << vH[i] <<
"\n";
1417template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1421 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1423 if (comm.is_null()) {
1425 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1426 SM_Matrix_->getRowMap()->getComm()->barrier();
1428 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1431 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1434 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1438 return Teuchos::null;
1441template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1443 buildNullspace(
const int spaceNumber,
const Kokkos::View<bool *, typename Node::device_type> &bcs,
const bool applyBCs) {
1444 std::string spaceLabel;
1445 if (spaceNumber == 0)
1446 spaceLabel =
"nodal";
1447 else if (spaceNumber == 1)
1448 spaceLabel =
"edge";
1449 else if (spaceNumber == 2)
1450 spaceLabel =
"face";
1452 TEUCHOS_ASSERT(
false);
1453 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1456 RCP<Teuchos::TimeMonitor> tm;
1457 if (spaceNumber > 0) {
1458 tm = getTimer(
"nullspace " + spaceLabel);
1459 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" nullspace" << std::endl;
1462 if (spaceNumber == 0) {
1463 return Teuchos::null;
1465 }
else if (spaceNumber == 1) {
1466 RCP<MultiVector> CoordsSC;
1468 RCP<MultiVector> Nullspace = MultiVectorFactory::Build(D0_->getRowMap(), NodalCoords_->getNumVectors());
1469 D0_->apply(*CoordsSC, *Nullspace);
1471 bool normalize = parameterList_.get<
bool>(
"refmaxwell: normalize nullspace", MasterList::getDefault<bool>(
"refmaxwell: normalize nullspace"));
1476 ArrayRCP<ArrayRCP<const Scalar>> localNullspace(dim_);
1477 for (
size_t i = 0; i < dim_; i++)
1478 localNullspace[i] = Nullspace->getData(i);
1479 coordinateType localMinLen = Teuchos::ScalarTraits<coordinateType>::rmax();
1480 coordinateType localMeanLen = Teuchos::ScalarTraits<coordinateType>::zero();
1481 coordinateType localMaxLen = Teuchos::ScalarTraits<coordinateType>::zero();
1482 for (
size_t j = 0; j < Nullspace->getMap()->getLocalNumElements(); j++) {
1483 Scalar lenSC = Teuchos::ScalarTraits<Scalar>::zero();
1484 for (
size_t i = 0; i < dim_; i++)
1485 lenSC += localNullspace[i][j] * localNullspace[i][j];
1486 coordinateType len = Teuchos::as<coordinateType>(Teuchos::ScalarTraits<Scalar>::real(Teuchos::ScalarTraits<Scalar>::squareroot(lenSC)));
1487 localMinLen = std::min(localMinLen, len);
1488 localMaxLen = std::max(localMaxLen, len);
1489 localMeanLen += len;
1492 RCP<const Teuchos::Comm<int>> comm = Nullspace->getMap()->getComm();
1496 meanLen /= Nullspace->getMap()->getGlobalNumElements();
1500 GetOStream(
Statistics2) <<
"Edge length (min/mean/max): " << minLen <<
" / " << meanLen <<
" / " << maxLen << std::endl;
1505 GetOStream(
Runtime0) << solverName_ +
"::compute(): normalizing nullspace" << std::endl;
1507 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1509 Array<Scalar> normsSC(NodalCoords_->getNumVectors(), one / Teuchos::as<Scalar>(meanLen));
1510 Nullspace->scale(normsSC());
1517 dump(Nullspace,
"nullspaceEdge.m");
1521 }
else if (spaceNumber == 2) {
1522 using ATS = KokkosKernels::ArithTraits<Scalar>;
1523 using impl_Scalar =
typename ATS::val_type;
1524 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1525 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1527 RCP<Matrix> facesToNodes;
1529 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1534 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1540 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1547 RCP<RealValuedMultiVector> ghostedNodalCoordinates;
1548 auto importer = facesToNodes->getCrsGraph()->getImporter();
1549 if (!importer.is_null()) {
1550 ghostedNodalCoordinates = Xpetra::MultiVectorFactory<coordinateType, LocalOrdinal, GlobalOrdinal, Node>::Build(importer->getTargetMap(), dim_);
1551 ghostedNodalCoordinates->doImport(*NodalCoords_, *importer, Xpetra::INSERT);
1553 ghostedNodalCoordinates = NodalCoords_;
1555 RCP<MultiVector> Nullspace = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(facesToNodes->getRangeMap(), dim_);
1557 auto facesToNodesLocal = facesToNodes->getLocalMatrixDevice();
1558 auto localNodalCoordinates = ghostedNodalCoordinates->getLocalViewDevice(Tpetra::Access::ReadOnly);
1559 auto localFaceNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1562 Kokkos::parallel_for(
1563 solverName_ +
"::buildFaceProjection_nullspace",
1564 range_type(0, Nullspace->getMap()->getLocalNumElements()),
1565 KOKKOS_LAMBDA(
const size_t f) {
1566 size_t n0 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f));
1567 size_t n1 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 1);
1568 size_t n2 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 2);
1569 impl_Scalar elementNullspace00 = localNodalCoordinates(n1, 0) - localNodalCoordinates(n0, 0);
1570 impl_Scalar elementNullspace10 = localNodalCoordinates(n2, 0) - localNodalCoordinates(n0, 0);
1571 impl_Scalar elementNullspace01 = localNodalCoordinates(n1, 1) - localNodalCoordinates(n0, 1);
1572 impl_Scalar elementNullspace11 = localNodalCoordinates(n2, 1) - localNodalCoordinates(n0, 1);
1573 impl_Scalar elementNullspace02 = localNodalCoordinates(n1, 2) - localNodalCoordinates(n0, 2);
1574 impl_Scalar elementNullspace12 = localNodalCoordinates(n2, 2) - localNodalCoordinates(n0, 2);
1576 localFaceNullspace(f, 0) = impl_ATS::magnitude(elementNullspace01 * elementNullspace12 - elementNullspace02 * elementNullspace11) / 6.0;
1577 localFaceNullspace(f, 1) = impl_ATS::magnitude(elementNullspace02 * elementNullspace10 - elementNullspace00 * elementNullspace12) / 6.0;
1578 localFaceNullspace(f, 2) = impl_ATS::magnitude(elementNullspace00 * elementNullspace11 - elementNullspace01 * elementNullspace10) / 6.0;
1587 dump(Nullspace,
"nullspaceFace.m");
1592 TEUCHOS_ASSERT(
false);
1593 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1597template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1598Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1600 using ATS = KokkosKernels::ArithTraits<Scalar>;
1601 using impl_Scalar =
typename ATS::val_type;
1602 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1603 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1605 typedef typename Matrix::local_matrix_device_type KCRS;
1606 typedef typename KCRS::StaticCrsGraphType graph_t;
1607 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1608 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1609 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1611 const impl_Scalar impl_SC_ONE = impl_ATS::one();
1612 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
1613 const impl_Scalar impl_half = impl_SC_ONE / (impl_SC_ONE + impl_SC_ONE);
1615 std::string spaceLabel;
1616 if (spaceNumber == 0)
1617 spaceLabel =
"nodal";
1618 else if (spaceNumber == 1)
1619 spaceLabel =
"edge";
1620 else if (spaceNumber == 2)
1621 spaceLabel =
"face";
1623 TEUCHOS_ASSERT(
false);
1625 RCP<Teuchos::TimeMonitor> tm;
1626 if (spaceNumber > 0) {
1627 tm = getTimer(
"projection " + spaceLabel);
1628 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" projection" << std::endl;
1631 RCP<Matrix> incidence;
1632 if (spaceNumber == 0) {
1634 return Teuchos::null;
1636 }
else if (spaceNumber == 1) {
1640 }
else if (spaceNumber == 2) {
1643 TEUCHOS_ASSERT(spaceNumber_ == 2);
1645 RCP<Matrix> facesToNodes;
1647 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1650 dump(edgesToNodes,
"edgesToNodes.m");
1652 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1656 dump(facesToEdges,
"facesToEdges.m");
1658 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1663 dump(facesToNodes,
"facesToNodes.m");
1665 incidence = facesToNodes;
1668 TEUCHOS_ASSERT(
false);
1673 RCP<const Map> rowMap = incidence->getRowMap();
1674 RCP<const Map> blockColMap = MapFactory::Build(incidence->getColMap(), dim);
1675 RCP<const Map> blockDomainMap = MapFactory::Build(incidence->getDomainMap(), dim);
1677 auto localIncidence = incidence->getLocalMatrixDevice();
1678 size_t numLocalRows = rowMap->getLocalNumElements();
1679 size_t numLocalColumns = dim * incidence->getColMap()->getLocalNumElements();
1680 size_t nnzEstimate = dim * localIncidence.graph.entries.size();
1681 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"projection_rowptr_" + spaceLabel), numLocalRows + 1);
1682 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"projection_colind_" + spaceLabel), nnzEstimate);
1683 scalar_view_t vals(
"projection_vals_" + spaceLabel, nnzEstimate);
1686 Kokkos::parallel_for(
1687 solverName_ +
"::buildProjection_adjustRowptr_" + spaceLabel,
1688 range_type(0, numLocalRows + 1),
1689 KOKKOS_LAMBDA(
const size_t i) {
1690 rowptr(i) = dim * localIncidence.graph.row_map(i);
1693 auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1697 Kokkos::parallel_for(
1698 solverName_ +
"::buildProjection_enterValues_" + spaceLabel,
1699 range_type(0, numLocalRows),
1700 KOKKOS_LAMBDA(
const size_t f) {
1701 for (
size_t jj = localIncidence.graph.row_map(f); jj < localIncidence.graph.row_map(f + 1); jj++) {
1702 for (
size_t k = 0; k < dim; k++) {
1703 colind(dim * jj + k) = dim * localIncidence.graph.entries(jj) + k;
1704 if (impl_ATS::magnitude(localIncidence.values(jj)) > tol)
1705 vals(dim * jj + k) = impl_half * localNullspace(f, k);
1707 vals(dim * jj + k) = impl_SC_ZERO;
1713 typename CrsMatrix::local_matrix_device_type lclProjection(
"local projection " + spaceLabel,
1714 numLocalRows, numLocalColumns, nnzEstimate,
1715 vals, rowptr, colind);
1716 RCP<Matrix> projection = MatrixFactory::Build(lclProjection,
1717 rowMap, blockColMap,
1718 blockDomainMap, rowMap);
1723template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1725 Teuchos::RCP<Matrix> &P_nodal,
1726 Teuchos::RCP<MultiVector> &Nullspace_nodal,
1727 Teuchos::RCP<RealValuedMultiVector> &CoarseCoords_nodal)
const {
1728 RCP<Teuchos::TimeMonitor> tm = getTimer(
"nodal prolongator");
1729 GetOStream(
Runtime0) << solverName_ +
"::compute(): building nodal prolongator" << std::endl;
1734 const SC SC_ONE = Teuchos::ScalarTraits<SC>::one();
1737 Level fineLevel, coarseLevel;
1743 fineLevel.
Set(
"A", A_nodal);
1744 fineLevel.
Set(
"Coordinates", NodalCoords_);
1745 fineLevel.
Set(
"DofsPerNode", 1);
1746 coarseLevel.
setlib(A_nodal->getDomainMap()->lib());
1747 fineLevel.
setlib(A_nodal->getDomainMap()->lib());
1748 coarseLevel.setObjectLabel(A_nodal->getObjectLabel());
1749 fineLevel.setObjectLabel(A_nodal->getObjectLabel());
1752 RCP<MultiVector> nullSpace = MultiVectorFactory::Build(A_nodal->getRowMap(), NSdim);
1753 nullSpace->putScalar(SC_ONE);
1754 fineLevel.
Set(
"Nullspace", nullSpace);
1756 std::string algo = parameterList_.get<std::string>(
"multigrid algorithm");
1758 RCP<Factory> amalgFact, dropFact, UncoupledAggFact, coarseMapFact, TentativePFact, Tfact, SaPFact;
1772 dropFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1774 double dropTol = parameterList_.get<
double>(
"aggregation: drop tol");
1775 std::string dropScheme = parameterList_.get<std::string>(
"aggregation: drop scheme");
1776 std::string distLaplAlgo = parameterList_.get<std::string>(
"aggregation: distance laplacian algo");
1777 dropFact->SetParameter(
"aggregation: drop tol", Teuchos::ParameterEntry(dropTol));
1778 dropFact->SetParameter(
"aggregation: drop scheme", Teuchos::ParameterEntry(dropScheme));
1779 dropFact->SetParameter(
"aggregation: distance laplacian algo", Teuchos::ParameterEntry(distLaplAlgo));
1781 UncoupledAggFact->SetFactory(
"Graph", dropFact);
1782 int minAggSize = parameterList_.get<
int>(
"aggregation: min agg size");
1783 UncoupledAggFact->SetParameter(
"aggregation: min agg size", Teuchos::ParameterEntry(minAggSize));
1784 int maxAggSize = parameterList_.get<
int>(
"aggregation: max agg size");
1785 UncoupledAggFact->SetParameter(
"aggregation: max agg size", Teuchos::ParameterEntry(maxAggSize));
1786 bool matchMLbehavior1 = parameterList_.get<
bool>(
"aggregation: match ML phase1");
1787 UncoupledAggFact->SetParameter(
"aggregation: match ML phase1", Teuchos::ParameterEntry(matchMLbehavior1));
1788 bool matchMLbehavior2a = parameterList_.get<
bool>(
"aggregation: match ML phase2a");
1789 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2a", Teuchos::ParameterEntry(matchMLbehavior2a));
1790 bool matchMLbehavior2b = parameterList_.get<
bool>(
"aggregation: match ML phase2b");
1791 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2b", Teuchos::ParameterEntry(matchMLbehavior2b));
1793 coarseMapFact->SetFactory(
"Aggregates", UncoupledAggFact);
1795 TentativePFact->SetFactory(
"Aggregates", UncoupledAggFact);
1796 TentativePFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1797 TentativePFact->SetFactory(
"CoarseMap", coarseMapFact);
1799 Tfact->SetFactory(
"Aggregates", UncoupledAggFact);
1800 Tfact->SetFactory(
"CoarseMap", coarseMapFact);
1803 SaPFact->SetFactory(
"P", TentativePFact);
1804 coarseLevel.
Request(
"P", SaPFact.get());
1806 coarseLevel.
Request(
"P", TentativePFact.get());
1807 coarseLevel.
Request(
"Nullspace", TentativePFact.get());
1808 coarseLevel.
Request(
"Coordinates", Tfact.get());
1810 RCP<AggregationExportFactory> aggExport;
1811 bool exportVizData = parameterList_.get<
bool>(
"aggregation: export visualization data");
1812 if (exportVizData) {
1814 ParameterList aggExportParams;
1815 aggExportParams.set(
"aggregation: output filename",
"aggs.vtk");
1816 aggExportParams.set(
"aggregation: output file: agg style",
"Jacks");
1817 aggExport->SetParameterList(aggExportParams);
1819 aggExport->SetFactory(
"Aggregates", UncoupledAggFact);
1820 aggExport->SetFactory(
"UnAmalgamationInfo", amalgFact);
1821 fineLevel.
Request(
"Aggregates", UncoupledAggFact.get());
1822 fineLevel.
Request(
"UnAmalgamationInfo", amalgFact.get());
1826 coarseLevel.
Get(
"P", P_nodal, SaPFact.get());
1828 coarseLevel.
Get(
"P", P_nodal, TentativePFact.get());
1829 coarseLevel.
Get(
"Nullspace", Nullspace_nodal, TentativePFact.get());
1830 coarseLevel.
Get(
"Coordinates", CoarseCoords_nodal, Tfact.get());
1833 aggExport->Build(fineLevel, coarseLevel);
1837template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1838Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1840 RCP<Teuchos::TimeMonitor> tm = getTimer(
"vectorial nodal prolongator");
1841 GetOStream(
Runtime0) << solverName_ +
"::compute(): building vectorial nodal prolongator" << std::endl;
1843 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1845 typedef typename Matrix::local_matrix_device_type KCRS;
1846 typedef typename KCRS::StaticCrsGraphType graph_t;
1847 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1848 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1849 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1854 RCP<Map> blockRowMap = MapFactory::Build(P_nodal->getRowMap(), dim);
1855 RCP<Map> blockColMap = MapFactory::Build(P_nodal->getColMap(), dim);
1856 RCP<Map> blockDomainMap = MapFactory::Build(P_nodal->getDomainMap(), dim);
1859 auto localP_nodal = P_nodal->getLocalMatrixDevice();
1861 size_t numLocalRows = blockRowMap->getLocalNumElements();
1862 size_t numLocalColumns = blockColMap->getLocalNumElements();
1863 size_t nnzEstimate = dim * localP_nodal.graph.entries.size();
1864 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_rowptr"), numLocalRows + 1);
1865 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_colind"), nnzEstimate);
1866 scalar_view_t vals(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_vals"), nnzEstimate);
1869 Kokkos::parallel_for(
1870 solverName_ +
"::buildVectorNodalProlongator_adjustRowptr",
1871 range_type(0, localP_nodal.numRows() + 1),
1873 if (i < localP_nodal.numRows()) {
1874 for (size_t k = 0; k < dim; k++) {
1875 rowptr(dim * i + k) = dim * localP_nodal.graph.row_map(i) + k;
1878 rowptr(dim * localP_nodal.numRows()) = dim * localP_nodal.graph.row_map(i);
1882 Kokkos::parallel_for(
1883 solverName_ +
"::buildVectorNodalProlongator_adjustColind",
1884 range_type(0, localP_nodal.graph.entries.size()),
1885 KOKKOS_LAMBDA(
const size_t jj) {
1886 for (
size_t k = 0; k < dim; k++) {
1887 colind(dim * jj + k) = dim * localP_nodal.graph.entries(jj) + k;
1889 vals(dim * jj + k) = 1.;
1893 typename CrsMatrix::local_matrix_device_type lclVectorNodalP(
"local vector nodal prolongator",
1894 numLocalRows, numLocalColumns, nnzEstimate,
1895 vals, rowptr, colind);
1896 RCP<Matrix> vectorNodalP = MatrixFactory::Build(lclVectorNodalP,
1897 blockRowMap, blockColMap,
1898 blockDomainMap, blockRowMap);
1900 return vectorNodalP;
1903template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1906 const Teuchos::RCP<Matrix> &A_nodal,
1907 const Teuchos::RCP<MultiVector> &Nullspace,
1908 Teuchos::RCP<Matrix> &Prolongator,
1909 Teuchos::RCP<MultiVector> &coarseNullspace,
1910 Teuchos::RCP<RealValuedMultiVector> &coarseNodalCoords)
const {
1911 using ATS = KokkosKernels::ArithTraits<Scalar>;
1912 using impl_Scalar =
typename ATS::val_type;
1913 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1915 std::string typeStr;
1916 switch (spaceNumber) {
1919 TEUCHOS_ASSERT(A_nodal.is_null());
1928 TEUCHOS_ASSERT(
false);
1931 const bool skipFirstLevel = !A_nodal.is_null();
1933 RCP<Teuchos::TimeMonitor> tm;
1934 if (spaceNumber > 0) {
1935 tm = getTimer(
"special prolongator " + typeStr);
1936 GetOStream(
Runtime0) << solverName_ +
"::compute(): building special " + typeStr +
" prolongator" << std::endl;
1939 RCP<Matrix> projection = buildProjection(spaceNumber, Nullspace);
1940 dump(projection, typeStr +
"Projection.m");
1942 if (skipFirstLevel) {
1943 RCP<Matrix> P_nodal;
1944 RCP<MultiVector> coarseNodalNullspace;
1946 buildNodalProlongator(A_nodal, P_nodal, coarseNodalNullspace, coarseNodalCoords);
1948 dump(P_nodal,
"P_nodal_" + typeStr +
".m");
1949 dump(coarseNodalNullspace,
"coarseNullspace_nodal_" + typeStr +
".m");
1951 RCP<Matrix> vectorP_nodal = buildVectorNodalProlongator(P_nodal);
1953 dump(vectorP_nodal,
"vectorP_nodal_" + typeStr +
".m");
1955 Prolongator = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*projection,
false, *vectorP_nodal,
false, Prolongator, GetOStream(
Runtime0),
true,
true);
2004 coarseNullspace = MultiVectorFactory::Build(vectorP_nodal->getDomainMap(), dim);
2006 auto localNullspace_nodal = coarseNodalNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
2007 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
2008 Kokkos::parallel_for(
2009 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
2010 range_type(0, coarseNodalNullspace->getLocalLength()),
2011 KOKKOS_LAMBDA(
const size_t i) {
2012 impl_Scalar val = localNullspace_nodal(i, 0);
2013 for (
size_t j = 0; j < dim; j++)
2014 localNullspace_coarse(dim * i + j, j) = val;
2018 Prolongator = projection;
2019 coarseNodalCoords = NodalCoords_;
2021 if (spaceNumber == 0) {
2023 }
else if (spaceNumber >= 1) {
2025 coarseNullspace = MultiVectorFactory::Build(projection->getDomainMap(), dim);
2026 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
2027 Kokkos::parallel_for(
2028 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
2029 range_type(0, coarseNullspace->getLocalLength() / dim),
2030 KOKKOS_LAMBDA(
const size_t i) {
2031 for (
size_t j = 0; j < dim; j++)
2032 localNullspace_coarse(dim * i + j, j) = 1.0;
2038template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2040 Teuchos::RCP<Operator> &thyraPrecOp,
2041 const Teuchos::RCP<Matrix> &A,
2042 const Teuchos::RCP<MultiVector> &Nullspace,
2043 const Teuchos::RCP<RealValuedMultiVector> &Coords,
2044 const Teuchos::RCP<MultiVector> &Material,
2045 Teuchos::ParameterList ¶ms,
2048 const bool isSingular) {
2049 int oldRank = SetProcRankVerbose(A->getDomainMap()->getComm()->getRank());
2051 RCP<ParameterList> pl = rcp(
new ParameterList());
2052 pl->set(
"printLoadBalancingInfo",
true);
2053 pl->set(
"printCommInfo",
true);
2054 GetOStream(
Statistics2) << PerfUtils::PrintMatrixInfo(*A, label, pl);
2056#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2057 if (params.isType<std::string>(
"Preconditioner Type")) {
2058 TEUCHOS_ASSERT(!reuse);
2060 if (params.get<std::string>(
"Preconditioner Type") ==
"MueLu") {
2061 ParameterList &userParamList = params.sublist(
"Preconditioner Types").sublist(
"MueLu").sublist(
"user data");
2062 if (!Nullspace.is_null())
2063 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2064 if (!Material.is_null())
2065 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2066 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2068 thyraPrecOp = rcp(
new XpetraThyraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(coarseA11_, rcp(¶ms,
false)));
2075 ParameterList &userParamList = params.sublist(
"user data");
2076 if (!Coords.is_null())
2077 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2078 if (!Nullspace.is_null())
2079 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2080 if (!Material.is_null())
2081 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2084 std::string coarseType =
"";
2085 if (params.isParameter(
"coarse: type")) {
2086 coarseType = params.get<std::string>(
"coarse: type");
2088 std::transform(coarseType.begin(), coarseType.end(), coarseType.begin(), ::tolower);
2089 std::transform(coarseType.begin(), ++coarseType.begin(), coarseType.begin(), ::toupper);
2091 if ((coarseType ==
"" ||
2092 coarseType ==
"Klu" ||
2093 coarseType ==
"Klu2" ||
2094 coarseType ==
"Superlu" ||
2095 coarseType ==
"Superlu_dist" ||
2096 coarseType ==
"Superludist" ||
2097 coarseType ==
"Basker" ||
2098 coarseType ==
"Cusolver" ||
2099 coarseType ==
"Tacho") &&
2100 (!params.isSublist(
"coarse: params") ||
2101 !params.sublist(
"coarse: params").isParameter(
"fix nullspace")))
2102 params.sublist(
"coarse: params").set(
"fix nullspace",
true);
2107 RCP<MueLu::Level> level0 = hierarchy->GetLevel(0);
2108 level0->Set(
"A", A);
2109 hierarchy->SetupRe();
2112 SetProcRankVerbose(oldRank);
2115template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2117 bool reuse = !SM_Matrix_.is_null();
2118 SM_Matrix_ = SM_Matrix_new;
2119 dump(SM_Matrix_,
"SM.m");
2124template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2160 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2164 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2165 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2170 if (implicitTranspose_) {
2172 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"restriction coarse (1,1) (implicit)");
2173 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2175 if (!onlyBoundary22_) {
2176 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (implicit)");
2177 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2180 if (Dk_1_T_R11_colMapsMatch_) {
2183 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restrictions import");
2184 DTR11Tmp_->doImport(*residual_, *toCrsMatrix(R11_)->getCrsGraph()->getImporter(), Xpetra::INSERT);
2186 if (!onlyBoundary22_) {
2187 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2188 toTpetra(Dk_1_T_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*Dres_), Teuchos::NO_TRANS);
2191 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2192 toTpetra(R11_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*P11res_), Teuchos::NO_TRANS);
2196 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2197 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2199 if (!onlyBoundary22_) {
2200 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2201 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2208 RCP<Teuchos::TimeMonitor> tmSubSolves = getTimer(
"subsolves");
2212 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2213 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2214 P11resTmp_->beginImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2216 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_) {
2217 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2218 DresTmp_->beginImport(*Dres_, *Importer22_, Xpetra::INSERT);
2222 if (!coarseA11_.is_null()) {
2223 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
2224 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2226 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2228#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2229 if (!thyraPrecOpH_.is_null()) {
2230 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2231 thyraPrecOpH_->apply(*P11resSubComm_, *P11xSubComm_, Teuchos::NO_TRANS, one, zero);
2234 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2238 if (!A22_.is_null()) {
2239 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2240 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2242 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2243#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2244 if (!thyraPrecOp22_.is_null()) {
2245 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2246 thyraPrecOp22_->apply(*DresSubComm_, *DxSubComm_, Teuchos::NO_TRANS, one, zero);
2249 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2252 if (coarseA11_.is_null() && !ImporterCoarse11_.is_null() && !implicitTranspose_)
2253 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2254 if (A22_.is_null() && !onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2255 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2259 RCP<Teuchos::TimeMonitor> tmProlongations = getTimer(
"prolongations");
2261 if (asyncTransfers_) {
2262 using Tpetra_Multivector = Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2263 using Tpetra_Import = Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>;
2265 auto tpP11 = toTpetra(P11_);
2266 auto tpDk_1 = toTpetra(Dk_1_);
2268 RCP<Tpetra_Multivector> tpP11x = toTpetra(P11x_);
2269 RCP<Tpetra_Multivector> tpP11x_colmap;
2270 RCP<Tpetra_Multivector> tpX = toTpetra(Teuchos::rcpFromRef(X));
2271 RCP<Tpetra_Multivector> tpResidual = toTpetra(residual_);
2272 RCP<Tpetra_Multivector> tpDx = toTpetra(Dx_);
2273 RCP<Tpetra_Multivector> tpDx_colmap;
2275 unsigned completedImports = 0;
2276 std::vector<bool> completedImport(2,
false);
2277 auto tpP11importer = tpP11->getCrsGraph()->getImporter();
2278 if (!tpP11importer.is_null()) {
2279 tpP11x_colmap = toTpetra(P11x_colmap_);
2280 tpP11x_colmap->beginImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2283 RCP<const Tpetra_Import> tpDk_1importer;
2284 if (!onlyBoundary22_) {
2285 tpDk_1importer = tpDk_1->getCrsGraph()->getImporter();
2286 if (!tpDk_1importer.is_null()) {
2287 tpDx_colmap = toTpetra(Dx_colmap_);
2288 tpDx_colmap->beginImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2291 completedImport[1] =
true;
2295 if (!fuseProlongationAndUpdate_) {
2296 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2297 tpResidual->putScalar(zero);
2300 while (completedImports < completedImport.size()) {
2301 for (
unsigned i = 0; i < completedImport.size(); i++) {
2302 if (completedImport[i])
continue;
2305 if (!tpP11importer.is_null()) {
2306 if (tpP11x_colmap->transferArrived()) {
2307 tpP11x_colmap->endImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2308 completedImport[i] =
true;
2311 if (fuseProlongationAndUpdate_) {
2312 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2313 tpP11->localApply(*tpP11x_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2315 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2316 tpP11->localApply(*tpP11x_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2320 completedImport[i] =
true;
2323 if (fuseProlongationAndUpdate_) {
2324 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2325 tpP11->localApply(*tpP11x, *tpX, Teuchos::NO_TRANS, one, one);
2327 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2328 tpP11->localApply(*tpP11x, *tpResidual, Teuchos::NO_TRANS, one, one);
2332 if (!tpDk_1importer.is_null()) {
2333 if (tpDx_colmap->transferArrived()) {
2334 tpDx_colmap->endImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2335 completedImport[i] =
true;
2338 if (fuseProlongationAndUpdate_) {
2339 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2340 tpDk_1->localApply(*tpDx_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2342 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2343 tpDk_1->localApply(*tpDx_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2347 completedImport[i] =
true;
2350 if (fuseProlongationAndUpdate_) {
2351 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2352 tpDk_1->localApply(*tpDx, *tpX, Teuchos::NO_TRANS, one, one);
2354 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2355 tpDk_1->localApply(*tpDx, *tpResidual, Teuchos::NO_TRANS, one, one);
2362 if (!fuseProlongationAndUpdate_) {
2363 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2364 X.update(one, *residual_, one);
2367 if (fuseProlongationAndUpdate_) {
2369 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused)");
2370 P11_->apply(*P11x_, X, Teuchos::NO_TRANS, one, one);
2373 if (!onlyBoundary22_) {
2374 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused)");
2375 Dk_1_->apply(*Dx_, X, Teuchos::NO_TRANS, one, one);
2379 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused)");
2380 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2383 if (!onlyBoundary22_) {
2384 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused)");
2385 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS, one, one);
2389 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2390 X.update(one, *residual_, one);
2397template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2399 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2402 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2403 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2404 if (implicitTranspose_)
2405 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2407 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2411 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2412 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2413 P11resTmp_->doImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2415 if (!coarseA11_.is_null()) {
2416 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2417 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2422 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2423 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2424 X.update(one, *residual_, one);
2428template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2430 if (onlyBoundary22_)
2433 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2436 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2437 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2438 if (implicitTranspose_)
2439 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2441 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2445 if (!Importer22_.is_null() && !implicitTranspose_) {
2446 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2447 DresTmp_->doImport(*Dres_, *Importer22_, Xpetra::INSERT);
2449 if (!A22_.is_null()) {
2450 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2451 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2456 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2457 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS);
2458 X.update(one, *residual_, one);
2462template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2467 RCP<Teuchos::TimeMonitor> tm = getTimer(
"solve");
2470 if (!onlyBoundary11_ && X.getNumVectors() != P11res_->getNumVectors())
2471 allocateMemory(X.getNumVectors());
2475 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2477 PreSmoother11_->Apply(X, RHS, use_as_preconditioner_);
2481 if (mode_ ==
"additive")
2482 applyInverseAdditive(RHS, X);
2483 else if (mode_ ==
"121") {
2487 }
else if (mode_ ==
"212") {
2491 }
else if (mode_ ==
"1")
2493 else if (mode_ ==
"2")
2495 else if (mode_ ==
"7") {
2499 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2501 PreSmoother11_->Apply(X, RHS,
false);
2506 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2508 PostSmoother11_->Apply(X, RHS,
false);
2511 }
else if (mode_ ==
"none") {
2514 applyInverseAdditive(RHS, X);
2518 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2520 PostSmoother11_->Apply(X, RHS,
false);
2524template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2529template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2531 RefMaxwell(
const Teuchos::RCP<Matrix> &SM_Matrix,
2532 Teuchos::ParameterList &List,
2534 int spaceNumber = List.get<
int>(
"refmaxwell: space number", 1);
2536 RCP<Matrix> Dk_1, Dk_2, D0;
2537 RCP<Matrix> M1_beta, M1_alpha;
2538 RCP<Matrix> Mk_one, Mk_1_one;
2539 RCP<Matrix> invMk_1_invBeta, invMk_2_invAlpha;
2540 RCP<MultiVector> Nullspace11, Nullspace22;
2541 RCP<RealValuedMultiVector> NodalCoords;
2543 Dk_1 =
pop(List,
"Dk_1", Dk_1);
2544 Dk_2 = pop<RCP<Matrix>>(List,
"Dk_2", Dk_2);
2545 D0 = pop<RCP<Matrix>>(List,
"D0", D0);
2547 M1_beta = pop<RCP<Matrix>>(List,
"M1_beta", M1_beta);
2548 M1_alpha = pop<RCP<Matrix>>(List,
"M1_alpha", M1_alpha);
2550 Mk_one = pop<RCP<Matrix>>(List,
"Mk_one", Mk_one);
2551 Mk_1_one = pop<RCP<Matrix>>(List,
"Mk_1_one", Mk_1_one);
2553 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"invMk_1_invBeta", invMk_1_invBeta);
2554 invMk_2_invAlpha = pop<RCP<Matrix>>(List,
"invMk_2_invAlpha", invMk_2_invAlpha);
2556 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace11", Nullspace11);
2557 Nullspace22 = pop<RCP<MultiVector>>(List,
"Nullspace22", Nullspace22);
2558 NodalCoords = pop<RCP<RealValuedMultiVector>>(List,
"Coordinates", NodalCoords);
2561 if (List.isType<RCP<Matrix>>(
"Ms")) {
2562 if (M1_beta.is_null())
2563 M1_beta =
pop<RCP<Matrix>>(List,
"Ms");
2565 TEUCHOS_ASSERT(
false);
2567 if (List.isType<RCP<Matrix>>(
"M1")) {
2568 if (Mk_one.is_null())
2569 Mk_one = pop<RCP<Matrix>>(List,
"M1");
2571 TEUCHOS_ASSERT(
false);
2573 if (List.isType<RCP<Matrix>>(
"M0inv")) {
2574 if (invMk_1_invBeta.is_null())
2575 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"M0inv");
2577 TEUCHOS_ASSERT(
false);
2579 if (List.isType<RCP<MultiVector>>(
"Nullspace")) {
2580 if (Nullspace11.is_null())
2581 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace");
2583 TEUCHOS_ASSERT(
false);
2586 if (spaceNumber == 1) {
2589 else if (D0.is_null())
2591 if (M1_beta.is_null())
2593 }
else if (spaceNumber == 2) {
2596 else if (D0.is_null())
2600 initialize(spaceNumber,
2604 invMk_1_invBeta, invMk_2_invAlpha,
2605 Nullspace11, Nullspace22,
2607 Teuchos::null, Teuchos::null,
2610 if (SM_Matrix != Teuchos::null)
2611 resetMatrix(SM_Matrix, ComputePrec);
2614template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2616 initialize(
const Teuchos::RCP<Matrix> &D0_Matrix,
2617 const Teuchos::RCP<Matrix> &Ms_Matrix,
2618 const Teuchos::RCP<Matrix> &M0inv_Matrix,
2619 const Teuchos::RCP<Matrix> &M1_Matrix,
2620 const Teuchos::RCP<MultiVector> &Nullspace11,
2621 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2622 const Teuchos::RCP<MultiVector> &Material,
2623 Teuchos::ParameterList &List) {
2625 D0_Matrix, Teuchos::null, D0_Matrix,
2626 Ms_Matrix, Teuchos::null,
2627 M1_Matrix, Teuchos::null,
2628 M0inv_Matrix, Teuchos::null,
2629 Nullspace11, Teuchos::null,
2631 Teuchos::null, Material,
2635template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2638 const Teuchos::RCP<Matrix> &Dk_1,
2639 const Teuchos::RCP<Matrix> &Dk_2,
2640 const Teuchos::RCP<Matrix> &D0,
2641 const Teuchos::RCP<Matrix> &M1_beta,
2642 const Teuchos::RCP<Matrix> &M1_alpha,
2643 const Teuchos::RCP<Matrix> &Mk_one,
2644 const Teuchos::RCP<Matrix> &Mk_1_one,
2645 const Teuchos::RCP<Matrix> &invMk_1_invBeta,
2646 const Teuchos::RCP<Matrix> &invMk_2_invAlpha,
2647 const Teuchos::RCP<MultiVector> &Nullspace11,
2648 const Teuchos::RCP<MultiVector> &Nullspace22,
2649 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2650 const Teuchos::RCP<MultiVector> &Material_beta,
2651 const Teuchos::RCP<MultiVector> &Material_alpha,
2652 Teuchos::ParameterList &List) {
2654 if (spaceNumber_ == 1)
2655 solverName_ =
"RefMaxwell";
2656 else if (spaceNumber_ == 2)
2657 solverName_ =
"RefDarcy";
2659 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
2660 "spaceNumber needs to be 1 (HCurl) or 2 (HDiv)");
2661 HierarchyCoarse11_ = Teuchos::null;
2662 Hierarchy22_ = Teuchos::null;
2663 PreSmoother11_ = Teuchos::null;
2664 PostSmoother11_ = Teuchos::null;
2665 disable_addon_ =
false;
2666 disable_addon_22_ =
true;
2670 setParameters(List);
2673 TEUCHOS_ASSERT((k == 1) || (k == 2));
2675 TEUCHOS_ASSERT(Dk_1 != Teuchos::null);
2677 TEUCHOS_ASSERT(D0 != Teuchos::null);
2680 TEUCHOS_ASSERT(M1_beta != Teuchos::null);
2683 TEUCHOS_ASSERT(M1_alpha != Teuchos::null);
2685 if (!disable_addon_) {
2687 TEUCHOS_ASSERT(Mk_one != Teuchos::null);
2688 TEUCHOS_ASSERT(invMk_1_invBeta != Teuchos::null);
2691 if ((k >= 2) && !disable_addon_22_) {
2693 TEUCHOS_ASSERT(Dk_2 != Teuchos::null);
2694 TEUCHOS_ASSERT(Mk_1_one != Teuchos::null);
2695 TEUCHOS_ASSERT(invMk_2_invAlpha != Teuchos::null);
2698 if (Behavior::debug()) {
2699 TEUCHOS_ASSERT(D0->getRangeMap()->isSameAs(*D0->getRowMap()));
2702 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRangeMap()));
2703 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRowMap()));
2706 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*D0->getRangeMap()));
2710 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRangeMap()));
2711 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRowMap()));
2714 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*D0->getRangeMap()));
2717 if (!disable_addon_) {
2719 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRangeMap()));
2720 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRowMap()));
2723 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2726 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRangeMap()));
2727 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRowMap()));
2730 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2733 if ((k >= 2) && !disable_addon_22_) {
2735 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRangeMap()));
2736 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRowMap()));
2739 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2742 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_2->getRangeMap()));
2745 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRangeMap()));
2746 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRowMap()));
2749 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*Dk_2->getDomainMap()));
2754 if (Dk_1->getRowMap()->lib() == Xpetra::UseTpetra) {
2759 RCP<Matrix> Dk_1copy = MatrixFactory::Build(Dk_1->getRowMap(), Dk_1->getColMap(), 0);
2760 RCP<CrsMatrix> Dk_1copyCrs = toCrsMatrix(Dk_1copy);
2761 ArrayRCP<const size_t> Dk_1rowptr_RCP;
2762 ArrayRCP<const LO> Dk_1colind_RCP;
2763 ArrayRCP<const SC> Dk_1vals_RCP;
2764 toCrsMatrix(Dk_1)->getAllValues(Dk_1rowptr_RCP, Dk_1colind_RCP, Dk_1vals_RCP);
2766 ArrayRCP<size_t> Dk_1copyrowptr_RCP;
2767 ArrayRCP<LO> Dk_1copycolind_RCP;
2768 ArrayRCP<SC> Dk_1copyvals_RCP;
2769 Dk_1copyCrs->allocateAllValues(Dk_1vals_RCP.size(), Dk_1copyrowptr_RCP, Dk_1copycolind_RCP, Dk_1copyvals_RCP);
2770 Dk_1copyrowptr_RCP.deepCopy(Dk_1rowptr_RCP());
2771 Dk_1copycolind_RCP.deepCopy(Dk_1colind_RCP());
2772 Dk_1copyvals_RCP.deepCopy(Dk_1vals_RCP());
2773 Dk_1copyCrs->setAllValues(Dk_1copyrowptr_RCP,
2776 Dk_1copyCrs->expertStaticFillComplete(Dk_1->getDomainMap(), Dk_1->getRangeMap(),
2777 toCrsMatrix(Dk_1)->getCrsGraph()->getImporter(),
2778 toCrsMatrix(Dk_1)->getCrsGraph()->getExporter());
2781 Dk_1_ = MatrixFactory::BuildCopy(Dk_1);
2783 if ((!Dk_2.is_null()) && (Dk_2->getRowMap()->lib() == Xpetra::UseTpetra)) {
2788 RCP<Matrix> Dk_2copy = MatrixFactory::Build(Dk_2->getRowMap(), Dk_2->getColMap(), 0);
2789 RCP<CrsMatrix> Dk_2copyCrs = toCrsMatrix(Dk_2copy);
2790 ArrayRCP<const size_t> Dk_2rowptr_RCP;
2791 ArrayRCP<const LO> Dk_2colind_RCP;
2792 ArrayRCP<const SC> Dk_2vals_RCP;
2793 toCrsMatrix(Dk_2)->getAllValues(Dk_2rowptr_RCP, Dk_2colind_RCP, Dk_2vals_RCP);
2795 ArrayRCP<size_t> Dk_2copyrowptr_RCP;
2796 ArrayRCP<LO> Dk_2copycolind_RCP;
2797 ArrayRCP<SC> Dk_2copyvals_RCP;
2798 Dk_2copyCrs->allocateAllValues(Dk_2vals_RCP.size(), Dk_2copyrowptr_RCP, Dk_2copycolind_RCP, Dk_2copyvals_RCP);
2799 Dk_2copyrowptr_RCP.deepCopy(Dk_2rowptr_RCP());
2800 Dk_2copycolind_RCP.deepCopy(Dk_2colind_RCP());
2801 Dk_2copyvals_RCP.deepCopy(Dk_2vals_RCP());
2802 Dk_2copyCrs->setAllValues(Dk_2copyrowptr_RCP,
2805 Dk_2copyCrs->expertStaticFillComplete(Dk_2->getDomainMap(), Dk_2->getRangeMap(),
2806 toCrsMatrix(Dk_2)->getCrsGraph()->getImporter(),
2807 toCrsMatrix(Dk_2)->getCrsGraph()->getExporter());
2809 }
else if (!Dk_2.is_null())
2810 Dk_2_ = MatrixFactory::BuildCopy(Dk_2);
2813 M1_alpha_ = M1_alpha;
2815 Material_beta_ = Material_beta;
2816 Material_alpha_ = Material_alpha;
2819 Mk_1_one_ = Mk_1_one;
2821 invMk_1_invBeta_ = invMk_1_invBeta;
2822 invMk_2_invAlpha_ = invMk_2_invAlpha;
2824 NodalCoords_ = NodalCoords;
2825 Nullspace11_ = Nullspace11;
2826 Nullspace22_ = Nullspace22;
2829 dump(Dk_1_,
"Dk_1_clean.m");
2830 dump(Dk_2_,
"Dk_2_clean.m");
2832 dump(M1_beta_,
"M1_beta.m");
2833 dump(M1_alpha_,
"M1_alpha.m");
2835 dump(Mk_one_,
"Mk_one.m");
2836 dump(Mk_1_one_,
"Mk_1_one.m");
2838 dump(invMk_1_invBeta_,
"invMk_1_invBeta.m");
2839 dump(invMk_2_invAlpha_,
"invMk_2_invAlpha.m");
2841 dumpCoords(NodalCoords_,
"coords.m");
2844template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2846 describe(Teuchos::FancyOStream &out,
const Teuchos::EVerbosityLevel )
const {
2847 std::ostringstream oss;
2849 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->
getDomainMap()->getComm();
2853 if (!coarseA11_.is_null())
2854 root = comm->getRank();
2859 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
2863 oss <<
"\n--------------------------------------------------------------------------------\n"
2864 <<
"--- " + solverName_ +
2866 "--------------------------------------------------------------------------------"
2873 SM_Matrix_->getRowMap()->getComm()->barrier();
2875 numRows = SM_Matrix_->getGlobalNumRows();
2876 nnz = SM_Matrix_->getGlobalNumEntries();
2878 Xpetra::global_size_t tt = numRows;
2891 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
2892 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2898 if (!A22_.is_null()) {
2899 numRows = A22_->getGlobalNumRows();
2900 nnz = A22_->getGlobalNumEntries();
2902 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numRows, Teuchos::ptr(&numRowsGlobal));
2903 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, nnz, Teuchos::ptr(&numNNZGlobal));
2905 oss <<
"(2, 2)" << std::setw(rowspacer) << numRowsGlobal << std::setw(nnzspacer) << numNNZGlobal << std::setw(9) << as<double>(numNNZGlobal) / numRowsGlobal << std::endl;
2910 if (PreSmoother11_ != null && PreSmoother11_ == PostSmoother11_)
2911 oss <<
"Smoother 11 both : " << PreSmoother11_->description() << std::endl;
2913 oss <<
"Smoother 11 pre : "
2914 << (PreSmoother11_ != null ? PreSmoother11_->description() :
"no smoother") << std::endl;
2915 oss <<
"Smoother 11 post : "
2916 << (PostSmoother11_ != null ? PostSmoother11_->description() :
"no smoother") << std::endl;
2921 std::string outstr = oss.str();
2924 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2925 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
2927 int strLength = outstr.size();
2928 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
2929 if (comm->getRank() != root)
2930 outstr.resize(strLength);
2931 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
2936 if (!HierarchyCoarse11_.is_null())
2937 HierarchyCoarse11_->describe(out, GetVerbLevel());
2939 if (!Hierarchy22_.is_null())
2940 Hierarchy22_->describe(out, GetVerbLevel());
2944 std::ostringstream oss2;
2946 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
2947 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;
2949 int numProcs = comm->getSize();
2951 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2952 TEUCHOS_TEST_FOR_EXCEPTION(tmpic == Teuchos::null,
Exceptions::RuntimeError,
"Cannot cast base Teuchos::Comm to Teuchos::MpiComm object.");
2953 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
2957 if (!coarseA11_.is_null())
2959 if (!A22_.is_null())
2961 std::vector<char> states(numProcs, 0);
2963 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
2965 states.push_back(status);
2968 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
2969 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
2970 for (
int j = 0; j < rowWidth; j++)
2971 if (proc + j < numProcs)
2972 if (states[proc + j] == 0)
2974 else if (states[proc + j] == 1)
2976 else if (states[proc + j] == 2)
2983 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
2992#define MUELU_REFMAXWELL_SHORT
Various adapters that will create a MueLu preconditioner that is an Xpetra::Matrix.
#define MueLu_maxAll(rcpComm, in, out)
#define MueLu_sumAll(rcpComm, in, out)
#define MueLu_minAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Factory to export aggregation info or visualize aggregates using VTK.
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for creating a graph based on a given matrix.
Factory for creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Class for transferring coordinates from a finer level to a coarser one.
Exception throws to report errors in the internal logical of the program.
This class specifies the default factory that should generate some data on a Level if the data does n...
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void setlib(Xpetra::UnderlyingLib lib2)
void SetLevelID(int levelID)
Set level number.
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
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 std::string translate(Teuchos::ParameterList ¶mList, const std::string &defaultVals="")
: Translate ML parameters to MueLu parameter XML string
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 void thresholdedAbs(const RCP< Matrix > &A, const magnitudeType thresholded)
static RCP< Matrix > removeExplicitZeros(const RCP< Matrix > &A, const magnitudeType tolerance, const bool keepDiagonal=true)
Remove explicit zeros.
static void setMatvecParams(Matrix &A, RCP< ParameterList > matvecParams)
Sets matvec params on a matrix.
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 const RCP< const NoFactory > getRCP()
Static Get() functions.
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
Factory for building coarse matrices.
Factory for building coarse matrices.
Applies permutation to grid transfer operators.
Preconditioner (wrapped as a Xpetra::Operator) for Maxwell's equations in curl-curl form.
Teuchos::RCP< Teuchos::TimeMonitor > getTimer(std::string name, RCP< const Teuchos::Comm< int > > comm=Teuchos::null) const
get a (synced) timer
void allocateMemory(int numVectors) const
allocate multivectors for solve
RCP< Matrix > buildVectorNodalProlongator(const Teuchos::RCP< Matrix > &P_nodal) const
void build22Matrix(const bool reuse, const bool doRebalancing, const int rebalanceStriding, const int numProcsA22)
Setup A22 = D0^T SM D0 and rebalance it, as well as D0 and Coords_.
void buildCoarse11Matrix()
Compute coarseA11 = P11^{T}*SM*P11 + addon efficiently.
RCP< MultiVector > buildNullspace(const int spaceNumber, const Kokkos::View< bool *, typename Node::device_type > &bcs, const bool applyBCs)
Builds a nullspace.
void determineSubHierarchyCommSizes(bool &doRebalancing, int &rebalanceStriding, int &numProcsCoarseA11, int &numProcsA22)
Determine how large the sub-communicators for the two hierarchies should be.
typename Teuchos::ScalarTraits< Scalar >::coordinateType coordinateType
void setFineLevelSmoother11()
Set the fine level smoother.
void dumpCoords(const RCP< RealValuedMultiVector > &X, std::string name) const
dump out real-valued multivector
const Teuchos::RCP< const Map > getDomainMap() const
Returns the Xpetra::Map object associated with the domain of this operator.
Teuchos::RCP< Teuchos::ParameterList > getValidParamterList()
const Teuchos::RCP< const Map > getRangeMap() const
Returns the Xpetra::Map object associated with the range of this operator.
void compute(bool reuse=false)
Setup the preconditioner.
void buildNodalProlongator(const Teuchos::RCP< Matrix > &A_nodal, Teuchos::RCP< Matrix > &P_nodal, Teuchos::RCP< MultiVector > &Nullspace_nodal, Teuchos::RCP< RealValuedMultiVector > &Coords_nodal) const
Teuchos::RCP< Matrix > buildProjection(const int spaceNumber, const RCP< MultiVector > &EdgeNullspace) const
Builds a projection from a vector values space into a vector valued nodal space.
void dump(const RCP< Matrix > &A, std::string name) const
dump out matrix
void rebalanceCoarse11Matrix(const int rebalanceStriding, const int numProcsCoarseA11)
rebalance the coarse A11 matrix, as well as P11, CoordsCoarse11 and Addon11
void setParameters(Teuchos::ParameterList &list)
Set parameters.
typename Teuchos::ScalarTraits< Scalar >::magnitudeType magnitudeType
RCP< Matrix > buildAddon(const int spaceNumber)
Factory for building permutation matrix that can be be used to shuffle data (matrices,...
Factory for determing the number of partitions for rebalancing.
Factory for building Smoothed Aggregation prolongators.
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
Factory for building tentative prolongator.
Class that encapsulates external library smoothers.
Factory for building uncoupled aggregates.
static void ZeroDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &A, const std::vector< LocalOrdinal > &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 void ApplyRowSumCriterion(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Magnitude rowSumTol, Teuchos::ArrayRCP< bool > &dirichletRows)
Apply Rowsum Criterion.
static void ApplyOAZToMatrixRows(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &A, const std::vector< LocalOrdinal > &dirichletRows)
static void DetectDirichletColsAndDomains(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Teuchos::ArrayRCP< bool > &dirichletRows, Teuchos::ArrayRCP< bool > dirichletCols, Teuchos::ArrayRCP< bool > dirichletDomain)
Detects Dirichlet columns & domains from a list of Dirichlet rows.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > ¶ms=Teuchos::null)
static RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > RealValuedToScalarMultiVector(RCP< Xpetra::MultiVector< typename Teuchos::ScalarTraits< Scalar >::coordinateType, LocalOrdinal, GlobalOrdinal, Node > > X)
static VerbLevel GetDefaultVerbLevel()
Get the default (global) verbosity level.
static void SetMueLuOStream(const Teuchos::RCP< Teuchos::FancyOStream > &mueluOStream)
static void SetDefaultVerbLevel(const VerbLevel defaultVerbLevel)
Set the default (global) verbosity level.
static void SetMueLuOFileStream(const std::string &filename)
Interface to Zoltan2 library.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line)
@ Statistics2
Print even more statistics.
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose)
@ Warnings1
Additional warnings.
@ Timings
Print all timing information.
MsgType toVerbLevel(const std::string &verbLevelStr)
T pop(Teuchos::ParameterList &pl, std::string const &name_in)
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,...