10#ifndef MUELU_REFMAXWELL_DEF_HPP
11#define MUELU_REFMAXWELL_DEF_HPP
17#include "Teuchos_CompilerCodeTweakMacros.hpp"
18#include "Tpetra_CrsMatrix.hpp"
19#include "Xpetra_CrsMatrix.hpp"
20#include "Xpetra_Map.hpp"
21#include "Xpetra_MatrixMatrix.hpp"
22#include "Xpetra_MultiVector.hpp"
23#include "Xpetra_TripleMatrixMultiply.hpp"
25#include "Xpetra_MatrixUtils.hpp"
29#include "MueLu_AmalgamationFactory.hpp"
30#include "MueLu_RAPFactory.hpp"
31#include "MueLu_SmootherFactory.hpp"
33#include "MueLu_CoalesceDropFactory.hpp"
34#include "MueLu_CoarseMapFactory.hpp"
35#include "MueLu_CoordinatesTransferFactory.hpp"
36#include "MueLu_UncoupledAggregationFactory.hpp"
37#include "MueLu_TentativePFactory.hpp"
38#include "MueLu_SaPFactory.hpp"
39#include "MueLu_AggregationExportFactory.hpp"
40#include "MueLu_Utilities.hpp"
41#include "MueLu_Maxwell_Utils.hpp"
43#include "MueLu_CoalesceDropFactory_kokkos.hpp"
44#include "MueLu_TentativePFactory_kokkos.hpp"
45#include <Kokkos_Core.hpp>
46#include <KokkosSparse_CrsMatrix.hpp>
48#include "MueLu_ZoltanInterface.hpp"
49#include "MueLu_Zoltan2Interface.hpp"
50#include "MueLu_RepartitionHeuristicFactory.hpp"
51#include "MueLu_RepartitionFactory.hpp"
52#include "MueLu_RebalanceAcFactory.hpp"
53#include "MueLu_RebalanceTransferFactory.hpp"
61#include "cuda_profiler_api.h"
65#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
72T
pop(Teuchos::ParameterList &pl, std::string
const &name_in) {
73 T result = pl.get<T>(name_in);
74 pl.remove(name_in,
true);
79T
pop(Teuchos::ParameterList &pl, std::string
const &name_in, T def_value) {
80 T result = pl.get<T>(name_in, def_value);
81 pl.remove(name_in,
false);
85template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
87 return SM_Matrix_->getDomainMap();
90template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
92 return SM_Matrix_->getRangeMap();
95template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
96Teuchos::RCP<Teuchos::ParameterList>
99 bool useKokkosDefault = !Node::is_serial;
101 RCP<ParameterList> params = rcp(
new ParameterList(
"RefMaxwell"));
103 params->set<RCP<Matrix>>(
"Dk_1", Teuchos::null);
104 params->set<RCP<Matrix>>(
"Dk_2", Teuchos::null);
105 params->set<RCP<Matrix>>(
"D0", Teuchos::null);
107 params->set<RCP<Matrix>>(
"M1_beta", Teuchos::null);
108 params->set<RCP<Matrix>>(
"M1_alpha", Teuchos::null);
110 params->set<RCP<Matrix>>(
"Ms", Teuchos::null);
112 params->set<RCP<Matrix>>(
"Mk_one", Teuchos::null);
113 params->set<RCP<Matrix>>(
"Mk_1_one", Teuchos::null);
115 params->set<RCP<Matrix>>(
"M1", Teuchos::null);
117 params->set<RCP<Matrix>>(
"invMk_1_invBeta", Teuchos::null);
118 params->set<RCP<Matrix>>(
"invMk_2_invAlpha", Teuchos::null);
120 params->set<RCP<Matrix>>(
"M0inv", Teuchos::null);
122 params->set<RCP<MultiVector>>(
"Nullspace", Teuchos::null);
123 params->set<RCP<RealValuedMultiVector>>(
"Coordinates", Teuchos::null);
125 auto spaceValidator = rcp(
new Teuchos::EnhancedNumberValidator<int>(1, 2));
126 params->set(
"refmaxwell: space number", 1,
"", spaceValidator);
127 params->set(
"verbosity", MasterList::getDefault<std::string>(
"verbosity"));
128 params->set(
"use kokkos refactor", useKokkosDefault);
129 params->set(
"half precision",
false);
130 params->set(
"parameterlist: syntax", MasterList::getDefault<std::string>(
"parameterlist: syntax"));
131 params->set(
"output filename", MasterList::getDefault<std::string>(
"output filename"));
132 params->set(
"print initial parameters", MasterList::getDefault<bool>(
"print initial parameters"));
133 params->set(
"refmaxwell: disable addon", MasterList::getDefault<bool>(
"refmaxwell: disable addon"));
134 params->set(
"refmaxwell: disable addon 22",
true);
135 params->set(
"refmaxwell: mode", MasterList::getDefault<std::string>(
"refmaxwell: mode"));
136 params->set(
"refmaxwell: use as preconditioner", MasterList::getDefault<bool>(
"refmaxwell: use as preconditioner"));
137 params->set(
"refmaxwell: dump matrices", MasterList::getDefault<bool>(
"refmaxwell: dump matrices"));
138 params->set(
"refmaxwell: enable reuse", MasterList::getDefault<bool>(
"refmaxwell: enable reuse"));
139 params->set(
"refmaxwell: skip first (1,1) level", MasterList::getDefault<bool>(
"refmaxwell: skip first (1,1) level"));
140 params->set(
"refmaxwell: skip first (2,2) level",
false);
141 params->set(
"multigrid algorithm",
"Unsmoothed");
142 params->set(
"transpose: use implicit", MasterList::getDefault<bool>(
"transpose: use implicit"));
143 params->set(
"rap: triple product", MasterList::getDefault<bool>(
"rap: triple product"));
144 params->set(
"rap: fix zero diagonals",
true);
145 params->set(
"rap: fix zero diagonals threshold", MasterList::getDefault<double>(
"rap: fix zero diagonals threshold"));
146 params->set(
"fuse prolongation and update", MasterList::getDefault<bool>(
"fuse prolongation and update"));
147 params->set(
"refmaxwell: async transfers", Node::is_gpu);
148 params->set(
"refmaxwell: subsolves on subcommunicators", MasterList::getDefault<bool>(
"refmaxwell: subsolves on subcommunicators"));
149 params->set(
"refmaxwell: subsolves striding", 1);
150 params->set(
"refmaxwell: row sum drop tol (1,1)", MasterList::getDefault<double>(
"aggregation: row sum drop tol"));
151 params->set(
"sync timers",
false);
152 params->set(
"refmaxwell: num iters coarse 11", 1);
153 params->set(
"refmaxwell: num iters 22", 1);
154 params->set(
"refmaxwell: apply BCs to Anodal",
false);
155 params->set(
"refmaxwell: apply BCs to coarse 11",
true);
156 params->set(
"refmaxwell: apply BCs to 22",
true);
157 params->set(
"refmaxwell: max coarse size", 1);
159 ParameterList &precList11 = params->sublist(
"refmaxwell: 11list");
160 precList11.disableRecursiveValidation();
161 ParameterList &precList22 = params->sublist(
"refmaxwell: 22list");
162 precList22.disableRecursiveValidation();
164 params->set(
"smoother: type",
"CHEBYSHEV");
165 ParameterList &smootherList = params->sublist(
"smoother: params");
166 smootherList.disableRecursiveValidation();
167 params->set(
"smoother: pre type",
"NONE");
168 ParameterList &preSmootherList = params->sublist(
"smoother: pre params");
169 preSmootherList.disableRecursiveValidation();
170 params->set(
"smoother: post type",
"NONE");
171 ParameterList &postSmootherList = params->sublist(
"smoother: post params");
172 postSmootherList.disableRecursiveValidation();
174 ParameterList &matvecParams = params->sublist(
"matvec params");
175 matvecParams.disableRecursiveValidation();
177 ParameterList &importerCoarse11Params = params->sublist(
"refmaxwell: ImporterCoarse11 params");
178 importerCoarse11Params.disableRecursiveValidation();
180 ParameterList &importer22Params = params->sublist(
"refmaxwell: Importer22 params");
181 importer22Params.disableRecursiveValidation();
183 params->set(
"multigrid algorithm",
"unsmoothed");
184 params->set(
"aggregation: type", MasterList::getDefault<std::string>(
"aggregation: type"));
185 params->set(
"aggregation: drop tol", MasterList::getDefault<double>(
"aggregation: drop tol"));
186 params->set(
"aggregation: drop scheme", MasterList::getDefault<std::string>(
"aggregation: drop scheme"));
187 params->set(
"aggregation: distance laplacian algo", MasterList::getDefault<std::string>(
"aggregation: distance laplacian algo"));
188 params->set(
"aggregation: min agg size", MasterList::getDefault<int>(
"aggregation: min agg size"));
189 params->set(
"aggregation: max agg size", MasterList::getDefault<int>(
"aggregation: max agg size"));
190 params->set(
"aggregation: match ML phase1", MasterList::getDefault<bool>(
"aggregation: match ML phase1"));
191 params->set(
"aggregation: match ML phase2a", MasterList::getDefault<bool>(
"aggregation: match ML phase2a"));
192 params->set(
"aggregation: match ML phase2b", MasterList::getDefault<bool>(
"aggregation: match ML phase2b"));
193 params->set(
"aggregation: export visualization data", MasterList::getDefault<bool>(
"aggregation: export visualization data"));
198template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
200 if (list.isType<std::string>(
"parameterlist: syntax") && list.get<std::string>(
"parameterlist: syntax") ==
"ml") {
201 Teuchos::ParameterList newList;
204 RCP<Teuchos::ParameterList> validateParameters = getValidParamterList();
205 for (
auto it = newList2.begin(); it != newList2.end(); ++it) {
206 const std::string &entry_name = it->first;
207 if (validateParameters->isParameter(entry_name)) {
208 ParameterEntry theEntry = newList2.getEntry(entry_name);
209 newList.setEntry(entry_name, theEntry);
214 if (list.isSublist(
"refmaxwell: 11list") && list.sublist(
"refmaxwell: 11list").isSublist(
"edge matrix free: coarse"))
216 if (list.isSublist(
"refmaxwell: 22list"))
221 parameterList_ = list;
222 parameterList_.validateParametersAndSetDefaults(*getValidParamterList());
223 std::string verbosityLevel = parameterList_.get<std::string>(
"verbosity");
225 std::string outputFilename = parameterList_.get<std::string>(
"output filename");
226 if (outputFilename !=
"")
228 if (parameterList_.isType<Teuchos::RCP<Teuchos::FancyOStream>>(
"output stream"))
231 if (parameterList_.get<
bool>(
"print initial parameters"))
232 GetOStream(
static_cast<MsgType>(
Runtime1), 0) << parameterList_ << std::endl;
233 disable_addon_ = parameterList_.get<
bool>(
"refmaxwell: disable addon");
234 disable_addon_22_ = parameterList_.get<
bool>(
"refmaxwell: disable addon 22");
235 mode_ = parameterList_.get<std::string>(
"refmaxwell: mode");
236 use_as_preconditioner_ = parameterList_.get<
bool>(
"refmaxwell: use as preconditioner");
237 dump_matrices_ = parameterList_.get<
bool>(
"refmaxwell: dump matrices");
238 enable_reuse_ = parameterList_.get<
bool>(
"refmaxwell: enable reuse");
239 implicitTranspose_ = parameterList_.get<
bool>(
"transpose: use implicit");
240 fuseProlongationAndUpdate_ = parameterList_.get<
bool>(
"fuse prolongation and update");
241 skipFirst11Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (1,1) level");
242 skipFirst22Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (2,2) level");
243 if (spaceNumber_ == 1)
244 skipFirst22Level_ =
false;
245 syncTimers_ = parameterList_.get<
bool>(
"sync timers");
246 useKokkos_ = parameterList_.get<
bool>(
"use kokkos refactor");
247 numItersCoarse11_ = parameterList_.get<
int>(
"refmaxwell: num iters coarse 11");
248 numIters22_ = parameterList_.get<
int>(
"refmaxwell: num iters 22");
249 applyBCsToAnodal_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to Anodal");
250 applyBCsToCoarse11_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to coarse 11");
251 applyBCsTo22_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to 22");
253 precList11_ = parameterList_.sublist(
"refmaxwell: 11list");
254 if (!precList11_.isType<std::string>(
"Preconditioner Type") &&
255 !precList11_.isType<std::string>(
"smoother: type") &&
256 !precList11_.isType<std::string>(
"smoother: pre type") &&
257 !precList11_.isType<std::string>(
"smoother: post type")) {
258 precList11_.set(
"smoother: type",
"CHEBYSHEV");
259 precList11_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
260 precList11_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 5.4);
261 precList11_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
264 precList22_ = parameterList_.sublist(
"refmaxwell: 22list");
265 if (!precList22_.isType<std::string>(
"Preconditioner Type") &&
266 !precList22_.isType<std::string>(
"smoother: type") &&
267 !precList22_.isType<std::string>(
"smoother: pre type") &&
268 !precList22_.isType<std::string>(
"smoother: post type")) {
269 precList22_.set(
"smoother: type",
"CHEBYSHEV");
270 precList22_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
271 precList22_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 7.0);
272 precList22_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
275 if (!parameterList_.isType<std::string>(
"smoother: type") && !parameterList_.isType<std::string>(
"smoother: pre type") && !parameterList_.isType<std::string>(
"smoother: post type")) {
276 list.set(
"smoother: type",
"CHEBYSHEV");
277 list.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
278 list.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 20.0);
279 list.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
283 !precList11_.isType<std::string>(
"Preconditioner Type") &&
284 !precList11_.isParameter(
"reuse: type"))
285 precList11_.set(
"reuse: type",
"full");
287 !precList22_.isType<std::string>(
"Preconditioner Type") &&
288 !precList22_.isParameter(
"reuse: type"))
289 precList22_.set(
"reuse: type",
"full");
292template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
294 using memory_space =
typename Node::device_type::memory_space;
296#ifdef HAVE_MUELU_CUDA
297 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStart();
300 std::string timerLabel;
302 timerLabel =
"compute (reuse)";
304 timerLabel =
"compute";
305 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
315 RCP<ParameterList> params = rcp(
new ParameterList());
316 params->set(
"printLoadBalancingInfo",
true);
317 params->set(
"printCommInfo",
true);
324 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
326 BCrows11_, BCcols22_, BCdomain22_,
327 globalNumberBoundaryUnknowns11_,
328 globalNumberBoundaryUnknowns22_,
329 onlyBoundary11_, onlyBoundary22_);
330 if (spaceNumber_ == 2) {
331 Kokkos::View<bool *, memory_space> BCcolsEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), Dk_1_->getColMap()->getLocalNumElements());
332 Kokkos::View<bool *, memory_space> BCdomainEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), Dk_1_->getDomainMap()->getLocalNumElements());
335 Kokkos::View<bool *, memory_space> BCcolsNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), D0_->getColMap()->getLocalNumElements());
336 Kokkos::View<bool *, memory_space> BCdomainNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), D0_->getDomainMap()->getLocalNumElements());
338 BCdomain22_ = BCdomainNode;
341 GetOStream(
Statistics2) << solverName_ +
"::compute(): Detected " << globalNumberBoundaryUnknowns11_ <<
" BC rows and " << globalNumberBoundaryUnknowns22_ <<
" BC columns." << std::endl;
343 dump(BCrows11_,
"BCrows11.m");
344 dump(BCcols22_,
"BCcols22.m");
345 dump(BCdomain22_,
"BCdomain22.m");
348 if (onlyBoundary11_) {
351 GetOStream(
Warnings0) <<
"All unknowns of the (1,1) block have been detected as boundary unknowns!" << std::endl;
353 setFineLevelSmoother11();
359 dim_ = NodalCoords_->getNumVectors();
366 if (Nullspace11_ != null) {
367 TEUCHOS_ASSERT(Nullspace11_->getMap()->isCompatible(*(SM_Matrix_->getRowMap())));
368 }
else if (NodalCoords_ != null) {
369 Nullspace11_ = buildNullspace(spaceNumber_, BCrows11_, skipFirst11Level_);
371 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
376 RCP<Matrix> A11_nodal;
377 if (skipFirst11Level_) {
379 std::string label(
"D0^T*M1_beta*D0");
382 if (applyBCsToAnodal_) {
386 A11_nodal->setObjectLabel(solverName_ +
" (1,1) A_nodal");
387 dump(A11_nodal,
"A11_nodal.m");
390 M1_beta_ = Teuchos::null;
393 buildProlongator(spaceNumber_, A11_nodal, Nullspace11_, P11_, NullspaceCoarse11_, CoordsCoarse11_);
400 if (Nullspace22_ != null) {
401 TEUCHOS_ASSERT(Nullspace22_->getMap()->isCompatible(*(Dk_1_->getDomainMap())));
402 }
else if (NodalCoords_ != null)
403 Nullspace22_ = buildNullspace(spaceNumber_ - 1, BCdomain22_, skipFirst22Level_);
405 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
410 RCP<Matrix> A22_nodal;
411 if (skipFirst22Level_) {
413 std::string label(
"D0^T*M1_alpha*D0");
416 if (applyBCsToAnodal_) {
420 A22_nodal->setObjectLabel(solverName_ +
" (2,2) A_nodal");
421 dump(A22_nodal,
"A22_nodal.m");
424 M1_alpha_ = Teuchos::null;
427 buildProlongator(spaceNumber_ - 1, A22_nodal, Nullspace22_, P22_, CoarseNullspace22_, Coords22_);
435 buildCoarse11Matrix();
440 int rebalanceStriding, numProcsCoarseA11, numProcsA22;
442 this->determineSubHierarchyCommSizes(doRebalancing, rebalanceStriding, numProcsCoarseA11, numProcsA22);
444 doRebalancing =
false;
447 if (!reuse && doRebalancing)
448 rebalanceCoarse11Matrix(rebalanceStriding, numProcsCoarseA11);
449 if (!coarseA11_.is_null()) {
450 dump(coarseA11_,
"coarseA11.m");
452 dumpCoords(CoordsCoarse11_,
"CoordsCoarse11.m");
453 dump(NullspaceCoarse11_,
"NullspaceCoarse11.m");
458 if (!implicitTranspose_) {
465 if (!coarseA11_.is_null()) {
467 std::string label(
"coarseA11");
468 setupSubSolve(HierarchyCoarse11_, thyraPrecOpH_, coarseA11_, NullspaceCoarse11_, CoordsCoarse11_, Material_beta_, precList11_, label, reuse);
474 if (!reuse && applyBCsTo22_) {
475 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC columns of Dk_1" << std::endl;
478 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
480 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
485 if (!onlyBoundary22_) {
486 GetOStream(
Runtime0) << solverName_ +
"::compute(): building MG for (2,2)-block" << std::endl;
489 build22Matrix(reuse, doRebalancing, rebalanceStriding, numProcsA22);
491 if (!P22_.is_null()) {
492 std::string label(
"P22^T*A22*P22");
494 coarseA22_->SetFixedBlockSize(A22_->GetFixedBlockSize());
495 coarseA22_->setObjectLabel(solverName_ +
" coarse (2, 2)");
496 dump(coarseA22_,
"coarseA22.m");
499 if (!reuse && !implicitTranspose_) {
505 if (!A22_.is_null()) {
507 std::string label(
"A22");
508 if (!P22_.is_null()) {
509 precList22_.sublist(
"level 1 user data").set(
"A", coarseA22_);
510 precList22_.sublist(
"level 1 user data").set(
"P", P22_);
511 if (!implicitTranspose_)
512 precList22_.sublist(
"level 1 user data").set(
"R", R22_);
513 precList22_.sublist(
"level 1 user data").set(
"Nullspace", CoarseNullspace22_);
514 precList22_.sublist(
"level 1 user data").set(
"Coordinates", Coords22_);
517 int maxCoarseSize = precList22_.get(
"coarse: max size", MasterList::getDefault<int>(
"coarse: max size"));
518 int numRows = Teuchos::as<int>(coarseA22_->getGlobalNumRows());
519 if (maxCoarseSize > numRows)
520 precList22_.set(
"coarse: max size", numRows);
521 int maxLevels = precList22_.get(
"max levels", MasterList::getDefault<int>(
"max levels"));
523 precList22_.set(
"max levels", 2);
524 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, Teuchos::null, Teuchos::null, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
526 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, CoarseNullspace22_, Coords22_, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
534 if (!reuse && !onlyBoundary22_ && applyBCsTo22_) {
535 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC rows of Dk_1" << std::endl;
538 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
540 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
541 dump(Dk_1_,
"Dk_1_nuked.m");
546 setFineLevelSmoother11();
549 if (!ImporterCoarse11_.is_null()) {
550 RCP<const Import> ImporterP11 = ImportFactory::Build(ImporterCoarse11_->getTargetMap(), P11_->getColMap());
551 toCrsMatrix(P11_)->replaceDomainMapAndImporter(ImporterCoarse11_->getTargetMap(), ImporterP11);
554 if (!Importer22_.is_null()) {
556 DorigDomainMap_ = Dk_1_->getDomainMap();
557 DorigImporter_ = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
559 RCP<const Import> ImporterD = ImportFactory::Build(Importer22_->getTargetMap(), Dk_1_->getColMap());
560 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), ImporterD);
563 if ((!Dk_1_T_.is_null()) &&
565 (!toCrsMatrix(Dk_1_T_)->getCrsGraph()->getImporter().is_null()) &&
566 (!toCrsMatrix(R11_)->getCrsGraph()->getImporter().is_null()) &&
567 (Dk_1_T_->getColMap()->lib() == Xpetra::UseTpetra) &&
568 (R11_->getColMap()->lib() == Xpetra::UseTpetra))
569 Dk_1_T_R11_colMapsMatch_ = Dk_1_T_->getColMap()->isSameAs(*R11_->getColMap());
571 Dk_1_T_R11_colMapsMatch_ =
false;
572 if (Dk_1_T_R11_colMapsMatch_)
573 GetOStream(
Runtime0) << solverName_ +
"::compute(): Dk_1_T and R11 have matching colMaps" << std::endl;
575 asyncTransfers_ = parameterList_.get<
bool>(
"refmaxwell: async transfers");
581 if (parameterList_.isSublist(
"matvec params")) {
582 RCP<ParameterList> matvecParams = rcpFromRef(parameterList_.sublist(
"matvec params"));
588 if (!ImporterCoarse11_.is_null()) ImporterCoarse11_->setDistributorParameters(matvecParams);
589 if (!Importer22_.is_null()) Importer22_->setDistributorParameters(matvecParams);
591 if (!ImporterCoarse11_.is_null() && parameterList_.isSublist(
"refmaxwell: ImporterCoarse11 params")) {
592 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: ImporterCoarse11 params"));
593 ImporterCoarse11_->setDistributorParameters(importerParams);
595 if (!Importer22_.is_null() && parameterList_.isSublist(
"refmaxwell: Importer22 params")) {
596 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: Importer22 params"));
597 Importer22_->setDistributorParameters(importerParams);
603#ifdef HAVE_MUELU_CUDA
604 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStop();
608template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
611 doRebalancing = parameterList_.get<
bool>(
"refmaxwell: subsolves on subcommunicators");
612 rebalanceStriding = parameterList_.get<
int>(
"refmaxwell: subsolves striding", -1);
613 int numProcs = SM_Matrix_->getDomainMap()->getComm()->getSize();
615 doRebalancing =
false;
627 level.
Set(
"A", coarseA11_);
630 ParameterList repartheurParams;
631 repartheurParams.set(
"repartition: start level", 0);
633 int defaultTargetRows = 10000;
634 repartheurParams.set(
"repartition: min rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
635 repartheurParams.set(
"repartition: target rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
636 repartheurParams.set(
"repartition: min rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
637 repartheurParams.set(
"repartition: target rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
638 repartheurParams.set(
"repartition: max imbalance", precList11_.get<
double>(
"repartition: max imbalance", 1.1));
639 repartheurFactory->SetParameterList(repartheurParams);
641 level.
Request(
"number of partitions", repartheurFactory.get());
642 repartheurFactory->Build(level);
643 numProcsCoarseA11 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
644 numProcsCoarseA11 = std::min(numProcsCoarseA11, numProcs);
654 level.
Set(
"Map", Dk_1_->getDomainMap());
657 ParameterList repartheurParams;
658 repartheurParams.set(
"repartition: start level", 0);
659 repartheurParams.set(
"repartition: use map",
true);
661 int defaultTargetRows = 10000;
662 repartheurParams.set(
"repartition: min rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
663 repartheurParams.set(
"repartition: target rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
664 repartheurParams.set(
"repartition: min rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
665 repartheurParams.set(
"repartition: target rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
667 repartheurFactory->SetParameterList(repartheurParams);
669 level.
Request(
"number of partitions", repartheurFactory.get());
670 repartheurFactory->Build(level);
671 numProcsA22 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
672 numProcsA22 = std::min(numProcsA22, numProcs);
675 if (rebalanceStriding >= 1) {
676 TEUCHOS_ASSERT(rebalanceStriding * numProcsCoarseA11 <= numProcs);
677 TEUCHOS_ASSERT(rebalanceStriding * numProcsA22 <= numProcs);
678 if (rebalanceStriding * (numProcsCoarseA11 + numProcsA22) > numProcs) {
679 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling striding = " << rebalanceStriding <<
", since coarseA11 needs " << numProcsCoarseA11
680 <<
" procs and A22 needs " << numProcsA22 <<
" procs." << std::endl;
681 rebalanceStriding = -1;
683 int lclBadMatrixDistribution = (coarseA11_->getLocalNumEntries() == 0) || (Dk_1_->getDomainMap()->getLocalNumElements() == 0);
684 int gblBadMatrixDistribution =
false;
685 MueLu_maxAll(SM_Matrix_->getDomainMap()->getComm(), lclBadMatrixDistribution, gblBadMatrixDistribution);
686 if (gblBadMatrixDistribution) {
687 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;
688 rebalanceStriding = -1;
692 if ((numProcsCoarseA11 < 0) || (numProcsA22 < 0) || (numProcsCoarseA11 + numProcsA22 > numProcs)) {
693 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling rebalancing of subsolves, since partition heuristic resulted "
694 <<
"in undesirable number of partitions: " << numProcsCoarseA11 <<
", " << numProcsA22 << std::endl;
695 doRebalancing =
false;
699 doRebalancing =
false;
703template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
706 if (spaceNumber == 0)
707 return Teuchos::null;
709 std::string timerLabel;
710 if (spaceNumber == spaceNumber_) {
711 if (skipFirst11Level_)
712 timerLabel =
"Build coarse addon matrix 11";
714 timerLabel =
"Build addon matrix 11";
716 timerLabel =
"Build addon matrix 22";
718 RCP<Teuchos::TimeMonitor> tmAddon = getTimer(timerLabel);
722 RCP<Matrix> lumpedInverse;
723 if (spaceNumber == spaceNumber_) {
725 TEUCHOS_TEST_FOR_EXCEPTION(invMk_1_invBeta_ == Teuchos::null, std::invalid_argument,
727 "::buildCoarse11Matrix(): Inverse of "
728 "lumped mass matrix required for add-on (i.e. invMk_1_invBeta_ is null)");
729 lumpedInverse = invMk_1_invBeta_;
731 if (skipFirst11Level_) {
734 Zaux = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Mk_one_,
false, *P11_,
false, Zaux, GetOStream(
Runtime0),
true,
true);
736 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Zaux,
false, Z, GetOStream(
Runtime0),
true,
true);
739 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Mk_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
742 }
else if (spaceNumber == spaceNumber_ - 1) {
744 TEUCHOS_TEST_FOR_EXCEPTION(invMk_2_invAlpha_ == Teuchos::null, std::invalid_argument,
746 "::buildCoarse11Matrix(): Inverse of "
747 "lumped mass matrix required for add-on (i.e. invMk_2_invAlpha_ is null)");
748 lumpedInverse = invMk_2_invAlpha_;
751 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_2_,
true, *Mk_1_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
755 if (lumpedInverse->getGlobalMaxNumRowEntries() <= 1) {
758 RCP<Vector> diag = VectorFactory::Build(lumpedInverse->getRowMap());
759 lumpedInverse->getLocalDiagCopy(*diag);
761 ArrayRCP<Scalar> diagVals = diag->getDataNonConst(0);
762 for (
size_t j = 0; j < diag->getMap()->getLocalNumElements(); j++) {
763 diagVals[j] = Teuchos::ScalarTraits<Scalar>::squareroot(diagVals[j]);
766 if (Z->getRowMap()->isSameAs(*(diag->getMap())))
769 RCP<Import> importer = ImportFactory::Build(diag->getMap(), Z->getRowMap());
770 RCP<Vector> diag2 = VectorFactory::Build(Z->getRowMap());
771 diag2->doImport(*diag, *importer, Xpetra::INSERT);
772 Z->leftScale(*diag2);
774 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *Z,
false, addon, GetOStream(
Runtime0),
true,
true);
775 }
else if (parameterList_.get<
bool>(
"rap: triple product",
false) ==
false) {
778 C2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*lumpedInverse,
false, *Z,
false, C2, GetOStream(
Runtime0),
true,
true);
780 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *C2,
false, addon, GetOStream(
Runtime0),
true,
true);
782 addon = MatrixFactory::Build(Z->getDomainMap());
784 Xpetra::TripleMatrixMultiply<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
785 MultiplyRAP(*Z,
true, *lumpedInverse,
false, *Z,
false, *addon,
true,
true);
790template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
792 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build coarse (1,1) matrix");
794 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
798 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *P11_,
false, temp, GetOStream(
Runtime0),
true,
true);
799 if (ImporterCoarse11_.is_null())
800 coarseA11_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, coarseA11_, GetOStream(
Runtime0),
true,
true);
803 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
805 RCP<const Map> map = ImporterCoarse11_->getTargetMap()->removeEmptyProcesses();
806 temp2->removeEmptyProcessesInPlace(map);
807 if (!temp2.is_null() && temp2->getRowMap().is_null())
808 temp2 = Teuchos::null;
812 if (!disable_addon_) {
815 if (!coarseA11_.is_null() && Addon11_.is_null()) {
816 addon = buildAddon(spaceNumber_);
823 if (!coarseA11_.is_null()) {
825 RCP<Matrix> newCoarseA11;
826 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*coarseA11_,
false, one, *addon,
false, one, newCoarseA11, GetOStream(
Runtime0));
827 newCoarseA11->fillComplete();
828 coarseA11_ = newCoarseA11;
832 if (!coarseA11_.is_null() && !skipFirst11Level_) {
833 ArrayRCP<bool> coarseA11BCrows;
834 coarseA11BCrows.resize(coarseA11_->getRowMap()->getLocalNumElements());
835 for (
size_t i = 0; i < BCdomain22_.size(); i++)
836 for (
size_t k = 0; k < dim_; k++)
837 coarseA11BCrows[i * dim_ + k] = BCdomain22_(i);
838 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
841 if (applyBCsToCoarse11_)
845 if (!coarseA11_.is_null()) {
851 bool fixZeroDiagonal = !applyBCsToAnodal_;
852 if (precList11_.isParameter(
"rap: fix zero diagonals"))
853 fixZeroDiagonal = precList11_.get<
bool>(
"rap: fix zero diagonals");
855 if (fixZeroDiagonal) {
858 if (precList11_.isType<
magnitudeType>(
"rap: fix zero diagonals threshold"))
859 threshold = precList11_.get<
magnitudeType>(
"rap: fix zero diagonals threshold");
860 else if (precList11_.isType<
double>(
"rap: fix zero diagonals threshold"))
861 threshold = Teuchos::as<magnitudeType>(precList11_.get<
double>(
"rap: fix zero diagonals threshold"));
862 if (precList11_.isType<
double>(
"rap: fix zero diagonals replacement"))
863 replacement = Teuchos::as<Scalar>(precList11_.get<
double>(
"rap: fix zero diagonals replacement"));
864 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(coarseA11_,
true, GetOStream(
Warnings1), threshold, replacement);
868 coarseA11_->SetFixedBlockSize(dim_);
869 if (skipFirst11Level_)
870 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
872 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
876template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
881 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Rebalance coarseA11");
883 Level fineLevel, coarseLevel;
889 coarseLevel.
Set(
"A", coarseA11_);
890 coarseLevel.
Set(
"P", P11_);
891 coarseLevel.
Set(
"Coordinates", CoordsCoarse11_);
892 if (!NullspaceCoarse11_.is_null())
893 coarseLevel.
Set(
"Nullspace", NullspaceCoarse11_);
894 coarseLevel.
Set(
"number of partitions", numProcsCoarseA11);
895 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
897 coarseLevel.
setlib(coarseA11_->getDomainMap()->lib());
898 fineLevel.
setlib(coarseA11_->getDomainMap()->lib());
899 coarseLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
900 fineLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
902 std::string partName = precList11_.get<std::string>(
"repartition: partitioner",
"zoltan2");
903 RCP<Factory> partitioner;
904 if (partName ==
"zoltan") {
905#ifdef HAVE_MUELU_ZOLTAN
912 }
else if (partName ==
"zoltan2") {
913#ifdef HAVE_MUELU_ZOLTAN2
915 ParameterList partParams;
916 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList11_.sublist(
"repartition: params",
false)));
917 partParams.set(
"ParameterList", partpartParams);
918 partitioner->SetParameterList(partParams);
926 ParameterList repartParams;
927 repartParams.set(
"repartition: print partition distribution", precList11_.get<
bool>(
"repartition: print partition distribution",
false));
928 repartParams.set(
"repartition: remap parts", precList11_.get<
bool>(
"repartition: remap parts",
true));
929 if (rebalanceStriding >= 1) {
930 bool acceptPart = (SM_Matrix_->getDomainMap()->getComm()->getRank() % rebalanceStriding) == 0;
931 if (SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsCoarseA11 * rebalanceStriding)
933 repartParams.set(
"repartition: remap accept partition", acceptPart);
935 repartFactory->SetParameterList(repartParams);
937 repartFactory->SetFactory(
"Partition", partitioner);
940 ParameterList newPparams;
941 newPparams.set(
"type",
"Interpolation");
942 newPparams.set(
"repartition: rebalance P and R", precList11_.get<
bool>(
"repartition: rebalance P and R",
false));
943 newPparams.set(
"repartition: use subcommunicators",
true);
944 newPparams.set(
"repartition: rebalance Nullspace", !NullspaceCoarse11_.is_null());
946 if (!NullspaceCoarse11_.is_null())
948 newP->SetParameterList(newPparams);
949 newP->SetFactory(
"Importer", repartFactory);
952 ParameterList rebAcParams;
953 rebAcParams.set(
"repartition: use subcommunicators",
true);
954 newA->SetParameterList(rebAcParams);
955 newA->SetFactory(
"Importer", repartFactory);
957 coarseLevel.
Request(
"P", newP.get());
958 coarseLevel.
Request(
"Importer", repartFactory.get());
959 coarseLevel.
Request(
"A", newA.get());
960 coarseLevel.
Request(
"Coordinates", newP.get());
961 if (!NullspaceCoarse11_.is_null())
962 coarseLevel.
Request(
"Nullspace", newP.get());
963 repartFactory->Build(coarseLevel);
965 if (!precList11_.get<
bool>(
"repartition: rebalance P and R",
false))
966 ImporterCoarse11_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
967 P11_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
968 coarseA11_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
969 CoordsCoarse11_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
970 if (!NullspaceCoarse11_.is_null())
971 NullspaceCoarse11_ = coarseLevel.
Get<RCP<MultiVector>>(
"Nullspace", newP.get());
973 if (!coarseA11_.is_null()) {
975 coarseA11_->SetFixedBlockSize(dim_);
976 if (skipFirst11Level_)
977 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
979 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
982 coarseA11_AP_reuse_data_ = Teuchos::null;
983 coarseA11_RAP_reuse_data_ = Teuchos::null;
985 if (!disable_addon_ && enable_reuse_) {
987 RCP<const Import> ImporterCoarse11 = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
988 RCP<const Map> targetMap = ImporterCoarse11->getTargetMap();
989 ParameterList XpetraList;
990 XpetraList.set(
"Restrict Communicator",
true);
991 Addon11_ = MatrixFactory::Build(Addon11_, *ImporterCoarse11, *ImporterCoarse11, targetMap, targetMap, rcp(&XpetraList,
false));
996template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
999 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1001 Level fineLevel, coarseLevel;
1007 fineLevel.
Set(
"A", SM_Matrix_);
1008 coarseLevel.
Set(
"P", Dk_1_);
1009 coarseLevel.
Set(
"Coordinates", Coords22_);
1011 coarseLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1012 fineLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1013 coarseLevel.setObjectLabel(solverName_ +
" (2,2)");
1014 fineLevel.setObjectLabel(solverName_ +
" (2,2)");
1016 RCP<RAPFactory> rapFact = rcp(
new RAPFactory());
1017 ParameterList rapList = *(rapFact->GetValidParameterList());
1018 rapList.set(
"transpose: use implicit",
true);
1019 rapList.set(
"rap: fix zero diagonals", parameterList_.get<
bool>(
"rap: fix zero diagonals",
true));
1020 rapList.set(
"rap: fix zero diagonals threshold", parameterList_.get<
double>(
"rap: fix zero diagonals threshold", Teuchos::ScalarTraits<double>::eps()));
1021 rapList.set(
"rap: triple product", parameterList_.get<
bool>(
"rap: triple product",
false));
1022 rapFact->SetParameterList(rapList);
1024 if (!A22_AP_reuse_data_.is_null()) {
1025 coarseLevel.
AddKeepFlag(
"AP reuse data", rapFact.get());
1026 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"AP reuse data", A22_AP_reuse_data_, rapFact.get());
1028 if (!A22_RAP_reuse_data_.is_null()) {
1029 coarseLevel.
AddKeepFlag(
"RAP reuse data", rapFact.get());
1030 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"RAP reuse data", A22_RAP_reuse_data_, rapFact.get());
1034 if (doRebalancing) {
1035 coarseLevel.
Set(
"number of partitions", numProcsA22);
1036 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
1038 std::string partName = precList22_.get<std::string>(
"repartition: partitioner",
"zoltan2");
1039 RCP<Factory> partitioner;
1040 if (partName ==
"zoltan") {
1041#ifdef HAVE_MUELU_ZOLTAN
1043 partitioner->SetFactory(
"A", rapFact);
1049 }
else if (partName ==
"zoltan2") {
1050#ifdef HAVE_MUELU_ZOLTAN2
1052 ParameterList partParams;
1053 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList22_.sublist(
"repartition: params",
false)));
1054 partParams.set(
"ParameterList", partpartParams);
1055 partitioner->SetParameterList(partParams);
1056 partitioner->SetFactory(
"A", rapFact);
1064 ParameterList repartParams;
1065 repartParams.set(
"repartition: print partition distribution", precList22_.get<
bool>(
"repartition: print partition distribution",
false));
1066 repartParams.set(
"repartition: remap parts", precList22_.get<
bool>(
"repartition: remap parts",
true));
1067 if (rebalanceStriding >= 1) {
1068 bool acceptPart = ((SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank()) % rebalanceStriding) == 0;
1069 if (SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsA22 * rebalanceStriding)
1072 TEUCHOS_ASSERT(coarseA11_.is_null());
1073 repartParams.set(
"repartition: remap accept partition", acceptPart);
1075 repartParams.set(
"repartition: remap accept partition", coarseA11_.is_null());
1076 repartFactory->SetParameterList(repartParams);
1077 repartFactory->SetFactory(
"A", rapFact);
1079 repartFactory->SetFactory(
"Partition", partitioner);
1082 ParameterList newPparams;
1083 newPparams.set(
"type",
"Interpolation");
1084 newPparams.set(
"repartition: rebalance P and R", precList22_.get<
bool>(
"repartition: rebalance P and R",
false));
1085 newPparams.set(
"repartition: use subcommunicators",
true);
1086 newPparams.set(
"repartition: rebalance Nullspace",
false);
1088 newP->SetParameterList(newPparams);
1089 newP->SetFactory(
"Importer", repartFactory);
1092 ParameterList rebAcParams;
1093 rebAcParams.set(
"repartition: use subcommunicators",
true);
1094 newA->SetParameterList(rebAcParams);
1095 newA->SetFactory(
"A", rapFact);
1096 newA->SetFactory(
"Importer", repartFactory);
1098 coarseLevel.
Request(
"P", newP.get());
1099 coarseLevel.
Request(
"Importer", repartFactory.get());
1100 coarseLevel.
Request(
"A", newA.get());
1101 coarseLevel.
Request(
"Coordinates", newP.get());
1102 rapFact->Build(fineLevel, coarseLevel);
1103 repartFactory->Build(coarseLevel);
1105 if (!precList22_.get<
bool>(
"repartition: rebalance P and R",
false))
1106 Importer22_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1107 Dk_1_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1108 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1109 Coords22_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1111 if (!P22_.is_null()) {
1118 coarseLevel.
Request(
"A", rapFact.get());
1119 if (enable_reuse_) {
1120 coarseLevel.
Request(
"AP reuse data", rapFact.get());
1121 coarseLevel.
Request(
"RAP reuse data", rapFact.get());
1124 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", rapFact.get());
1126 if (enable_reuse_) {
1127 if (coarseLevel.
IsAvailable(
"AP reuse data", rapFact.get()))
1128 A22_AP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"AP reuse data", rapFact.get());
1129 if (coarseLevel.
IsAvailable(
"RAP reuse data", rapFact.get()))
1130 A22_RAP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"RAP reuse data", rapFact.get());
1134 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1135 if (Importer22_.is_null()) {
1137 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1138 if (!implicitTranspose_)
1139 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1141 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1144 RCP<const Import> Dimporter = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
1145 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(DorigDomainMap_, DorigImporter_);
1147 RCP<Matrix> temp, temp2;
1148 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1149 if (!implicitTranspose_)
1150 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1152 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1155 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), Dimporter);
1157 ParameterList XpetraList;
1158 XpetraList.set(
"Restrict Communicator",
true);
1159 XpetraList.set(
"Timer Label",
"MueLu::RebalanceA22");
1160 RCP<const Map> targetMap = Importer22_->getTargetMap();
1161 A22_ = MatrixFactory::Build(temp2, *Importer22_, *Importer22_, targetMap, targetMap, rcp(&XpetraList,
false));
1165 if (not A22_.is_null() and not disable_addon_22_ and spaceNumber_ > 1) {
1166 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1168 RCP<Matrix> addon22 = buildAddon(spaceNumber_ - 1);
1172 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A22_,
false, one, *addon22,
false, one, newA22, GetOStream(
Runtime0));
1173 newA22->fillComplete();
1177 if (!A22_.is_null()) {
1178 dump(A22_,
"A22.m");
1179 A22_->setObjectLabel(solverName_ +
" (2,2)");
1181 if (spaceNumber_ - 1 == 0)
1182 A22_->SetFixedBlockSize(1);
1184 A22_->SetFixedBlockSize(dim_);
1188template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1191 RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(
new FactoryManager());
1194 level.setObjectLabel(solverName_ +
" (1,1)");
1195 level.
Set(
"A", SM_Matrix_);
1196 level.
setlib(SM_Matrix_->getDomainMap()->lib());
1198 level.
Set(
"NodeMatrix", A22_);
1199 level.
Set(
"D0", Dk_1_);
1201 if ((parameterList_.get<std::string>(
"smoother: pre type") !=
"NONE") && (parameterList_.get<std::string>(
"smoother: post type") !=
"NONE")) {
1202 std::string preSmootherType = parameterList_.get<std::string>(
"smoother: pre type");
1203 std::string postSmootherType = parameterList_.get<std::string>(
"smoother: post type");
1205 ParameterList preSmootherList, postSmootherList;
1206 if (parameterList_.isSublist(
"smoother: pre params"))
1207 preSmootherList = parameterList_.sublist(
"smoother: pre params");
1208 if (parameterList_.isSublist(
"smoother: post params"))
1209 postSmootherList = parameterList_.sublist(
"smoother: post params");
1211 RCP<SmootherPrototype> preSmootherPrototype = rcp(
new TrilinosSmoother(preSmootherType, preSmootherList));
1212 RCP<SmootherPrototype> postSmootherPrototype = rcp(
new TrilinosSmoother(postSmootherType, postSmootherList));
1213 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(preSmootherPrototype, postSmootherPrototype));
1215 level.
Request(
"PreSmoother", smootherFact.get());
1216 level.
Request(
"PostSmoother", smootherFact.get());
1217 if (enable_reuse_) {
1218 ParameterList smootherFactoryParams;
1219 smootherFactoryParams.set(
"keep smoother data",
true);
1220 smootherFact->SetParameterList(smootherFactoryParams);
1221 level.
Request(
"PreSmoother data", smootherFact.get());
1222 level.
Request(
"PostSmoother data", smootherFact.get());
1223 if (!PreSmootherData11_.is_null())
1224 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1225 if (!PostSmootherData11_.is_null())
1226 level.
Set(
"PostSmoother data", PostSmootherData11_, smootherFact.get());
1228 smootherFact->Build(level);
1229 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1230 PostSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PostSmoother", smootherFact.get());
1231 if (enable_reuse_) {
1232 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1233 PostSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PostSmoother data", smootherFact.get());
1236 std::string smootherType = parameterList_.get<std::string>(
"smoother: type");
1238 ParameterList smootherList;
1239 if (parameterList_.isSublist(
"smoother: params"))
1240 smootherList = parameterList_.sublist(
"smoother: params");
1242 RCP<SmootherPrototype> smootherPrototype = rcp(
new TrilinosSmoother(smootherType, smootherList));
1243 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(smootherPrototype));
1244 level.
Request(
"PreSmoother", smootherFact.get());
1245 if (enable_reuse_) {
1246 ParameterList smootherFactoryParams;
1247 smootherFactoryParams.set(
"keep smoother data",
true);
1248 smootherFact->SetParameterList(smootherFactoryParams);
1249 level.
Request(
"PreSmoother data", smootherFact.get());
1250 if (!PreSmootherData11_.is_null())
1251 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1253 smootherFact->Build(level);
1254 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1255 PostSmoother11_ = PreSmoother11_;
1257 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1261template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1263 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer(
"Allocate MVs");
1266 if (!R11_.is_null())
1267 P11res_ = MultiVectorFactory::Build(R11_->getRangeMap(), numVectors);
1269 P11res_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1270 P11res_->setObjectLabel(
"P11res");
1272 if (Dk_1_T_R11_colMapsMatch_) {
1273 DTR11Tmp_ = MultiVectorFactory::Build(R11_->getColMap(), numVectors);
1274 DTR11Tmp_->setObjectLabel(
"DTR11Tmp");
1276 if (!ImporterCoarse11_.is_null()) {
1277 P11resTmp_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1278 P11resTmp_->setObjectLabel(
"P11resTmp");
1279 P11x_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1281 P11x_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1282 P11x_->setObjectLabel(
"P11x");
1285 if (!Dk_1_T_.is_null())
1286 Dres_ = MultiVectorFactory::Build(Dk_1_T_->getRangeMap(), numVectors);
1288 Dres_ = MultiVectorFactory::Build(Dk_1_->getDomainMap(), numVectors);
1289 Dres_->setObjectLabel(
"Dres");
1291 if (!Importer22_.is_null()) {
1292 DresTmp_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1293 DresTmp_->setObjectLabel(
"DresTmp");
1294 Dx_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1295 }
else if (!onlyBoundary22_)
1296 Dx_ = MultiVectorFactory::Build(A22_->getDomainMap(), numVectors);
1298 Dx_->setObjectLabel(
"Dx");
1300 if (!coarseA11_.is_null()) {
1301 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
1302 P11resSubComm_ = MultiVectorFactory::Build(P11resTmp_, Teuchos::View);
1304 P11resSubComm_ = MultiVectorFactory::Build(P11res_, Teuchos::View);
1305 P11resSubComm_->replaceMap(coarseA11_->getRangeMap());
1306 P11resSubComm_->setObjectLabel(
"P11resSubComm");
1308 P11xSubComm_ = MultiVectorFactory::Build(P11x_, Teuchos::View);
1309 P11xSubComm_->replaceMap(coarseA11_->getDomainMap());
1310 P11xSubComm_->setObjectLabel(
"P11xSubComm");
1313 if (!A22_.is_null()) {
1314 if (!Importer22_.is_null() && !implicitTranspose_)
1315 DresSubComm_ = MultiVectorFactory::Build(DresTmp_, Teuchos::View);
1317 DresSubComm_ = MultiVectorFactory::Build(Dres_, Teuchos::View);
1318 DresSubComm_->replaceMap(A22_->getRangeMap());
1319 DresSubComm_->setObjectLabel(
"DresSubComm");
1321 DxSubComm_ = MultiVectorFactory::Build(Dx_, Teuchos::View);
1322 DxSubComm_->replaceMap(A22_->getDomainMap());
1323 DxSubComm_->setObjectLabel(
"DxSubComm");
1326 if (asyncTransfers_) {
1327 if (!toCrsMatrix(P11_)->getCrsGraph()->getImporter().is_null())
1328 P11x_colmap_ = MultiVectorFactory::Build(P11_->getColMap(), numVectors);
1329 if (!toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter().is_null())
1330 Dx_colmap_ = MultiVectorFactory::Build(Dk_1_->getColMap(), numVectors);
1333 residual_ = MultiVectorFactory::Build(SM_Matrix_->getDomainMap(), numVectors);
1334 residual_->setObjectLabel(
"residual");
1337template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1339 if (dump_matrices_ && !A.is_null()) {
1340 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1341 Xpetra::IO<SC, LO, GO, NO>::Write(name, *A);
1345template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1347 if (dump_matrices_ && !X.is_null()) {
1348 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1349 Xpetra::IO<SC, LO, GO, NO>::Write(name, *X);
1353template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1355 if (dump_matrices_ && !X.is_null()) {
1356 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1357 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, *X);
1361template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1363 if (dump_matrices_) {
1364 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1365 std::ofstream out(name);
1366 for (
size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
1367 out << v[i] <<
"\n";
1371template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1373 if (dump_matrices_) {
1374 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1375 std::ofstream out(name);
1376 auto vH = Kokkos::create_mirror_view(v);
1377 Kokkos::deep_copy(vH, v);
1378 out <<
"%%MatrixMarket matrix array real general\n"
1379 << vH.extent(0) <<
" 1\n";
1380 for (
size_t i = 0; i < vH.size(); i++)
1381 out << vH[i] <<
"\n";
1385template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1389 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1391 if (comm.is_null()) {
1393 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1394 SM_Matrix_->getRowMap()->getComm()->barrier();
1396 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1399 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1402 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1406 return Teuchos::null;
1409template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1411 buildNullspace(
const int spaceNumber,
const Kokkos::View<bool *, typename Node::device_type> &bcs,
const bool applyBCs) {
1412 std::string spaceLabel;
1413 if (spaceNumber == 0)
1414 spaceLabel =
"nodal";
1415 else if (spaceNumber == 1)
1416 spaceLabel =
"edge";
1417 else if (spaceNumber == 2)
1418 spaceLabel =
"face";
1420 TEUCHOS_ASSERT(
false);
1421 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1424 RCP<Teuchos::TimeMonitor> tm;
1425 if (spaceNumber > 0) {
1426 tm = getTimer(
"nullspace " + spaceLabel);
1427 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" nullspace" << std::endl;
1430 if (spaceNumber == 0) {
1431 return Teuchos::null;
1433 }
else if (spaceNumber == 1) {
1434 RCP<MultiVector> CoordsSC;
1436 RCP<MultiVector> Nullspace = MultiVectorFactory::Build(D0_->getRowMap(), NodalCoords_->getNumVectors());
1437 D0_->apply(*CoordsSC, *Nullspace);
1439 bool normalize = parameterList_.get<
bool>(
"refmaxwell: normalize nullspace", MasterList::getDefault<bool>(
"refmaxwell: normalize nullspace"));
1444 ArrayRCP<ArrayRCP<const Scalar>> localNullspace(dim_);
1445 for (
size_t i = 0; i < dim_; i++)
1446 localNullspace[i] = Nullspace->getData(i);
1447 coordinateType localMinLen = Teuchos::ScalarTraits<coordinateType>::rmax();
1448 coordinateType localMeanLen = Teuchos::ScalarTraits<coordinateType>::zero();
1449 coordinateType localMaxLen = Teuchos::ScalarTraits<coordinateType>::zero();
1450 for (
size_t j = 0; j < Nullspace->getMap()->getLocalNumElements(); j++) {
1451 Scalar lenSC = Teuchos::ScalarTraits<Scalar>::zero();
1452 for (
size_t i = 0; i < dim_; i++)
1453 lenSC += localNullspace[i][j] * localNullspace[i][j];
1454 coordinateType len = Teuchos::as<coordinateType>(Teuchos::ScalarTraits<Scalar>::real(Teuchos::ScalarTraits<Scalar>::squareroot(lenSC)));
1455 localMinLen = std::min(localMinLen, len);
1456 localMaxLen = std::max(localMaxLen, len);
1457 localMeanLen += len;
1460 RCP<const Teuchos::Comm<int>> comm = Nullspace->getMap()->getComm();
1464 meanLen /= Nullspace->getMap()->getGlobalNumElements();
1468 GetOStream(
Statistics2) <<
"Edge length (min/mean/max): " << minLen <<
" / " << meanLen <<
" / " << maxLen << std::endl;
1473 GetOStream(
Runtime0) << solverName_ +
"::compute(): normalizing nullspace" << std::endl;
1475 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1477 Array<Scalar> normsSC(NodalCoords_->getNumVectors(), one / Teuchos::as<Scalar>(meanLen));
1478 Nullspace->scale(normsSC());
1485 dump(Nullspace,
"nullspaceEdge.m");
1489 }
else if (spaceNumber == 2) {
1490 using ATS = KokkosKernels::ArithTraits<Scalar>;
1491 using impl_Scalar =
typename ATS::val_type;
1492 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1493 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1495 RCP<Matrix> facesToNodes;
1497 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1502 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1508 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1515 RCP<RealValuedMultiVector> ghostedNodalCoordinates;
1516 auto importer = facesToNodes->getCrsGraph()->getImporter();
1517 if (!importer.is_null()) {
1518 ghostedNodalCoordinates = Xpetra::MultiVectorFactory<coordinateType, LocalOrdinal, GlobalOrdinal, Node>::Build(importer->getTargetMap(), dim_);
1519 ghostedNodalCoordinates->doImport(*NodalCoords_, *importer, Xpetra::INSERT);
1521 ghostedNodalCoordinates = NodalCoords_;
1523 RCP<MultiVector> Nullspace = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(facesToNodes->getRangeMap(), dim_);
1525 auto facesToNodesLocal = facesToNodes->getLocalMatrixDevice();
1526 auto localNodalCoordinates = ghostedNodalCoordinates->getLocalViewDevice(Tpetra::Access::ReadOnly);
1527 auto localFaceNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1530 Kokkos::parallel_for(
1531 solverName_ +
"::buildFaceProjection_nullspace",
1532 range_type(0, Nullspace->getMap()->getLocalNumElements()),
1533 KOKKOS_LAMBDA(
const size_t f) {
1534 size_t n0 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f));
1535 size_t n1 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 1);
1536 size_t n2 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 2);
1537 impl_Scalar elementNullspace00 = localNodalCoordinates(n1, 0) - localNodalCoordinates(n0, 0);
1538 impl_Scalar elementNullspace10 = localNodalCoordinates(n2, 0) - localNodalCoordinates(n0, 0);
1539 impl_Scalar elementNullspace01 = localNodalCoordinates(n1, 1) - localNodalCoordinates(n0, 1);
1540 impl_Scalar elementNullspace11 = localNodalCoordinates(n2, 1) - localNodalCoordinates(n0, 1);
1541 impl_Scalar elementNullspace02 = localNodalCoordinates(n1, 2) - localNodalCoordinates(n0, 2);
1542 impl_Scalar elementNullspace12 = localNodalCoordinates(n2, 2) - localNodalCoordinates(n0, 2);
1544 localFaceNullspace(f, 0) = impl_ATS::magnitude(elementNullspace01 * elementNullspace12 - elementNullspace02 * elementNullspace11) / 6.0;
1545 localFaceNullspace(f, 1) = impl_ATS::magnitude(elementNullspace02 * elementNullspace10 - elementNullspace00 * elementNullspace12) / 6.0;
1546 localFaceNullspace(f, 2) = impl_ATS::magnitude(elementNullspace00 * elementNullspace11 - elementNullspace01 * elementNullspace10) / 6.0;
1555 dump(Nullspace,
"nullspaceFace.m");
1560 TEUCHOS_ASSERT(
false);
1561 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1565template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1566Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1568 using ATS = KokkosKernels::ArithTraits<Scalar>;
1569 using impl_Scalar =
typename ATS::val_type;
1570 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1571 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1573 typedef typename Matrix::local_matrix_device_type KCRS;
1574 typedef typename KCRS::StaticCrsGraphType graph_t;
1575 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1576 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1577 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1579 const impl_Scalar impl_SC_ONE = impl_ATS::one();
1580 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
1581 const impl_Scalar impl_half = impl_SC_ONE / (impl_SC_ONE + impl_SC_ONE);
1583 std::string spaceLabel;
1584 if (spaceNumber == 0)
1585 spaceLabel =
"nodal";
1586 else if (spaceNumber == 1)
1587 spaceLabel =
"edge";
1588 else if (spaceNumber == 2)
1589 spaceLabel =
"face";
1591 TEUCHOS_ASSERT(
false);
1593 RCP<Teuchos::TimeMonitor> tm;
1594 if (spaceNumber > 0) {
1595 tm = getTimer(
"projection " + spaceLabel);
1596 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" projection" << std::endl;
1599 RCP<Matrix> incidence;
1600 if (spaceNumber == 0) {
1602 return Teuchos::null;
1604 }
else if (spaceNumber == 1) {
1608 }
else if (spaceNumber == 2) {
1611 TEUCHOS_ASSERT(spaceNumber_ == 2);
1613 RCP<Matrix> facesToNodes;
1615 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1618 dump(edgesToNodes,
"edgesToNodes.m");
1620 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1624 dump(facesToEdges,
"facesToEdges.m");
1626 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1631 dump(facesToNodes,
"facesToNodes.m");
1633 incidence = facesToNodes;
1636 TEUCHOS_ASSERT(
false);
1641 RCP<const Map> rowMap = incidence->getRowMap();
1642 RCP<const Map> blockColMap = MapFactory::Build(incidence->getColMap(), dim);
1643 RCP<const Map> blockDomainMap = MapFactory::Build(incidence->getDomainMap(), dim);
1645 auto localIncidence = incidence->getLocalMatrixDevice();
1646 size_t numLocalRows = rowMap->getLocalNumElements();
1647 size_t numLocalColumns = dim * incidence->getColMap()->getLocalNumElements();
1648 size_t nnzEstimate = dim * localIncidence.graph.entries.size();
1649 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"projection_rowptr_" + spaceLabel), numLocalRows + 1);
1650 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"projection_colind_" + spaceLabel), nnzEstimate);
1651 scalar_view_t vals(
"projection_vals_" + spaceLabel, nnzEstimate);
1654 Kokkos::parallel_for(
1655 solverName_ +
"::buildProjection_adjustRowptr_" + spaceLabel,
1656 range_type(0, numLocalRows + 1),
1657 KOKKOS_LAMBDA(
const size_t i) {
1658 rowptr(i) = dim * localIncidence.graph.row_map(i);
1661 auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1665 Kokkos::parallel_for(
1666 solverName_ +
"::buildProjection_enterValues_" + spaceLabel,
1667 range_type(0, numLocalRows),
1668 KOKKOS_LAMBDA(
const size_t f) {
1669 for (
size_t jj = localIncidence.graph.row_map(f); jj < localIncidence.graph.row_map(f + 1); jj++) {
1670 for (
size_t k = 0; k < dim; k++) {
1671 colind(dim * jj + k) = dim * localIncidence.graph.entries(jj) + k;
1672 if (impl_ATS::magnitude(localIncidence.values(jj)) > tol)
1673 vals(dim * jj + k) = impl_half * localNullspace(f, k);
1675 vals(dim * jj + k) = impl_SC_ZERO;
1681 typename CrsMatrix::local_matrix_device_type lclProjection(
"local projection " + spaceLabel,
1682 numLocalRows, numLocalColumns, nnzEstimate,
1683 vals, rowptr, colind);
1684 RCP<Matrix> projection = MatrixFactory::Build(lclProjection,
1685 rowMap, blockColMap,
1686 blockDomainMap, rowMap);
1691template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1693 Teuchos::RCP<Matrix> &P_nodal,
1694 Teuchos::RCP<MultiVector> &Nullspace_nodal,
1695 Teuchos::RCP<RealValuedMultiVector> &CoarseCoords_nodal)
const {
1696 RCP<Teuchos::TimeMonitor> tm = getTimer(
"nodal prolongator");
1697 GetOStream(
Runtime0) << solverName_ +
"::compute(): building nodal prolongator" << std::endl;
1702 const SC SC_ONE = Teuchos::ScalarTraits<SC>::one();
1705 Level fineLevel, coarseLevel;
1711 fineLevel.
Set(
"A", A_nodal);
1712 fineLevel.
Set(
"Coordinates", NodalCoords_);
1713 fineLevel.
Set(
"DofsPerNode", 1);
1714 coarseLevel.
setlib(A_nodal->getDomainMap()->lib());
1715 fineLevel.
setlib(A_nodal->getDomainMap()->lib());
1716 coarseLevel.setObjectLabel(A_nodal->getObjectLabel());
1717 fineLevel.setObjectLabel(A_nodal->getObjectLabel());
1720 RCP<MultiVector> nullSpace = MultiVectorFactory::Build(A_nodal->getRowMap(), NSdim);
1721 nullSpace->putScalar(SC_ONE);
1722 fineLevel.
Set(
"Nullspace", nullSpace);
1724 std::string algo = parameterList_.get<std::string>(
"multigrid algorithm");
1726 RCP<Factory> amalgFact, dropFact, UncoupledAggFact, coarseMapFact, TentativePFact, Tfact, SaPFact;
1740 dropFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1742 double dropTol = parameterList_.get<
double>(
"aggregation: drop tol");
1743 std::string dropScheme = parameterList_.get<std::string>(
"aggregation: drop scheme");
1744 std::string distLaplAlgo = parameterList_.get<std::string>(
"aggregation: distance laplacian algo");
1745 dropFact->SetParameter(
"aggregation: drop tol", Teuchos::ParameterEntry(dropTol));
1746 dropFact->SetParameter(
"aggregation: drop scheme", Teuchos::ParameterEntry(dropScheme));
1747 dropFact->SetParameter(
"aggregation: distance laplacian algo", Teuchos::ParameterEntry(distLaplAlgo));
1749 UncoupledAggFact->SetFactory(
"Graph", dropFact);
1750 int minAggSize = parameterList_.get<
int>(
"aggregation: min agg size");
1751 UncoupledAggFact->SetParameter(
"aggregation: min agg size", Teuchos::ParameterEntry(minAggSize));
1752 int maxAggSize = parameterList_.get<
int>(
"aggregation: max agg size");
1753 UncoupledAggFact->SetParameter(
"aggregation: max agg size", Teuchos::ParameterEntry(maxAggSize));
1754 bool matchMLbehavior1 = parameterList_.get<
bool>(
"aggregation: match ML phase1");
1755 UncoupledAggFact->SetParameter(
"aggregation: match ML phase1", Teuchos::ParameterEntry(matchMLbehavior1));
1756 bool matchMLbehavior2a = parameterList_.get<
bool>(
"aggregation: match ML phase2a");
1757 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2a", Teuchos::ParameterEntry(matchMLbehavior2a));
1758 bool matchMLbehavior2b = parameterList_.get<
bool>(
"aggregation: match ML phase2b");
1759 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2b", Teuchos::ParameterEntry(matchMLbehavior2b));
1761 coarseMapFact->SetFactory(
"Aggregates", UncoupledAggFact);
1763 TentativePFact->SetFactory(
"Aggregates", UncoupledAggFact);
1764 TentativePFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1765 TentativePFact->SetFactory(
"CoarseMap", coarseMapFact);
1767 Tfact->SetFactory(
"Aggregates", UncoupledAggFact);
1768 Tfact->SetFactory(
"CoarseMap", coarseMapFact);
1771 SaPFact->SetFactory(
"P", TentativePFact);
1772 coarseLevel.
Request(
"P", SaPFact.get());
1774 coarseLevel.
Request(
"P", TentativePFact.get());
1775 coarseLevel.
Request(
"Nullspace", TentativePFact.get());
1776 coarseLevel.
Request(
"Coordinates", Tfact.get());
1778 RCP<AggregationExportFactory> aggExport;
1779 bool exportVizData = parameterList_.get<
bool>(
"aggregation: export visualization data");
1780 if (exportVizData) {
1782 ParameterList aggExportParams;
1783 aggExportParams.set(
"aggregation: output filename",
"aggs.vtk");
1784 aggExportParams.set(
"aggregation: output file: agg style",
"Jacks");
1785 aggExport->SetParameterList(aggExportParams);
1787 aggExport->SetFactory(
"Aggregates", UncoupledAggFact);
1788 aggExport->SetFactory(
"UnAmalgamationInfo", amalgFact);
1789 fineLevel.
Request(
"Aggregates", UncoupledAggFact.get());
1790 fineLevel.
Request(
"UnAmalgamationInfo", amalgFact.get());
1794 coarseLevel.
Get(
"P", P_nodal, SaPFact.get());
1796 coarseLevel.
Get(
"P", P_nodal, TentativePFact.get());
1797 coarseLevel.
Get(
"Nullspace", Nullspace_nodal, TentativePFact.get());
1798 coarseLevel.
Get(
"Coordinates", CoarseCoords_nodal, Tfact.get());
1801 aggExport->Build(fineLevel, coarseLevel);
1805template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1806Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1808 RCP<Teuchos::TimeMonitor> tm = getTimer(
"vectorial nodal prolongator");
1809 GetOStream(
Runtime0) << solverName_ +
"::compute(): building vectorial nodal prolongator" << std::endl;
1811 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1813 typedef typename Matrix::local_matrix_device_type KCRS;
1814 typedef typename KCRS::StaticCrsGraphType graph_t;
1815 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1816 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1817 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1822 RCP<Map> blockRowMap = MapFactory::Build(P_nodal->getRowMap(), dim);
1823 RCP<Map> blockColMap = MapFactory::Build(P_nodal->getColMap(), dim);
1824 RCP<Map> blockDomainMap = MapFactory::Build(P_nodal->getDomainMap(), dim);
1827 auto localP_nodal = P_nodal->getLocalMatrixDevice();
1829 size_t numLocalRows = blockRowMap->getLocalNumElements();
1830 size_t numLocalColumns = blockColMap->getLocalNumElements();
1831 size_t nnzEstimate = dim * localP_nodal.graph.entries.size();
1832 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_rowptr"), numLocalRows + 1);
1833 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_colind"), nnzEstimate);
1834 scalar_view_t vals(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_vals"), nnzEstimate);
1837 Kokkos::parallel_for(
1838 solverName_ +
"::buildVectorNodalProlongator_adjustRowptr",
1839 range_type(0, localP_nodal.numRows() + 1),
1841 if (i < localP_nodal.numRows()) {
1842 for (size_t k = 0; k < dim; k++) {
1843 rowptr(dim * i + k) = dim * localP_nodal.graph.row_map(i) + k;
1846 rowptr(dim * localP_nodal.numRows()) = dim * localP_nodal.graph.row_map(i);
1850 Kokkos::parallel_for(
1851 solverName_ +
"::buildVectorNodalProlongator_adjustColind",
1852 range_type(0, localP_nodal.graph.entries.size()),
1853 KOKKOS_LAMBDA(
const size_t jj) {
1854 for (
size_t k = 0; k < dim; k++) {
1855 colind(dim * jj + k) = dim * localP_nodal.graph.entries(jj) + k;
1857 vals(dim * jj + k) = 1.;
1861 typename CrsMatrix::local_matrix_device_type lclVectorNodalP(
"local vector nodal prolongator",
1862 numLocalRows, numLocalColumns, nnzEstimate,
1863 vals, rowptr, colind);
1864 RCP<Matrix> vectorNodalP = MatrixFactory::Build(lclVectorNodalP,
1865 blockRowMap, blockColMap,
1866 blockDomainMap, blockRowMap);
1868 return vectorNodalP;
1871template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1874 const Teuchos::RCP<Matrix> &A_nodal,
1875 const Teuchos::RCP<MultiVector> &Nullspace,
1876 Teuchos::RCP<Matrix> &Prolongator,
1877 Teuchos::RCP<MultiVector> &coarseNullspace,
1878 Teuchos::RCP<RealValuedMultiVector> &coarseNodalCoords)
const {
1879 using ATS = KokkosKernels::ArithTraits<Scalar>;
1880 using impl_Scalar =
typename ATS::val_type;
1881 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1883 std::string typeStr;
1884 switch (spaceNumber) {
1887 TEUCHOS_ASSERT(A_nodal.is_null());
1896 TEUCHOS_ASSERT(
false);
1899 const bool skipFirstLevel = !A_nodal.is_null();
1901 RCP<Teuchos::TimeMonitor> tm;
1902 if (spaceNumber > 0) {
1903 tm = getTimer(
"special prolongator " + typeStr);
1904 GetOStream(
Runtime0) << solverName_ +
"::compute(): building special " + typeStr +
" prolongator" << std::endl;
1907 RCP<Matrix> projection = buildProjection(spaceNumber, Nullspace);
1908 dump(projection, typeStr +
"Projection.m");
1910 if (skipFirstLevel) {
1911 RCP<Matrix> P_nodal;
1912 RCP<MultiVector> coarseNodalNullspace;
1914 buildNodalProlongator(A_nodal, P_nodal, coarseNodalNullspace, coarseNodalCoords);
1916 dump(P_nodal,
"P_nodal_" + typeStr +
".m");
1917 dump(coarseNodalNullspace,
"coarseNullspace_nodal_" + typeStr +
".m");
1919 RCP<Matrix> vectorP_nodal = buildVectorNodalProlongator(P_nodal);
1921 dump(vectorP_nodal,
"vectorP_nodal_" + typeStr +
".m");
1923 Prolongator = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*projection,
false, *vectorP_nodal,
false, Prolongator, GetOStream(
Runtime0),
true,
true);
1972 coarseNullspace = MultiVectorFactory::Build(vectorP_nodal->getDomainMap(), dim);
1974 auto localNullspace_nodal = coarseNodalNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1975 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1976 Kokkos::parallel_for(
1977 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
1978 range_type(0, coarseNodalNullspace->getLocalLength()),
1979 KOKKOS_LAMBDA(
const size_t i) {
1980 impl_Scalar val = localNullspace_nodal(i, 0);
1981 for (
size_t j = 0; j < dim; j++)
1982 localNullspace_coarse(dim * i + j, j) = val;
1986 Prolongator = projection;
1987 coarseNodalCoords = NodalCoords_;
1989 if (spaceNumber == 0) {
1991 }
else if (spaceNumber >= 1) {
1993 coarseNullspace = MultiVectorFactory::Build(projection->getDomainMap(), dim);
1994 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1995 Kokkos::parallel_for(
1996 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
1997 range_type(0, coarseNullspace->getLocalLength() / dim),
1998 KOKKOS_LAMBDA(
const size_t i) {
1999 for (
size_t j = 0; j < dim; j++)
2000 localNullspace_coarse(dim * i + j, j) = 1.0;
2006template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2008 Teuchos::RCP<Operator> &thyraPrecOp,
2009 const Teuchos::RCP<Matrix> &A,
2010 const Teuchos::RCP<MultiVector> &Nullspace,
2011 const Teuchos::RCP<RealValuedMultiVector> &Coords,
2012 const Teuchos::RCP<MultiVector> &Material,
2013 Teuchos::ParameterList ¶ms,
2016 const bool isSingular) {
2017 int oldRank = SetProcRankVerbose(A->getDomainMap()->getComm()->getRank());
2019 RCP<ParameterList> pl = rcp(
new ParameterList());
2020 pl->set(
"printLoadBalancingInfo",
true);
2021 pl->set(
"printCommInfo",
true);
2022 GetOStream(
Statistics2) << PerfUtils::PrintMatrixInfo(*A, label, pl);
2024#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2025 if (params.isType<std::string>(
"Preconditioner Type")) {
2026 TEUCHOS_ASSERT(!reuse);
2028 if (params.get<std::string>(
"Preconditioner Type") ==
"MueLu") {
2029 ParameterList &userParamList = params.sublist(
"Preconditioner Types").sublist(
"MueLu").sublist(
"user data");
2030 if (!Nullspace.is_null())
2031 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2032 if (!Material.is_null())
2033 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2034 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2036 thyraPrecOp = rcp(
new XpetraThyraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(coarseA11_, rcp(¶ms,
false)));
2043 ParameterList &userParamList = params.sublist(
"user data");
2044 if (!Coords.is_null())
2045 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2046 if (!Nullspace.is_null())
2047 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2048 if (!Material.is_null())
2049 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2052 std::string coarseType =
"";
2053 if (params.isParameter(
"coarse: type")) {
2054 coarseType = params.get<std::string>(
"coarse: type");
2056 std::transform(coarseType.begin(), coarseType.end(), coarseType.begin(), ::tolower);
2057 std::transform(coarseType.begin(), ++coarseType.begin(), coarseType.begin(), ::toupper);
2059 if ((coarseType ==
"" ||
2060 coarseType ==
"Klu" ||
2061 coarseType ==
"Klu2" ||
2062 coarseType ==
"Superlu" ||
2063 coarseType ==
"Superlu_dist" ||
2064 coarseType ==
"Superludist" ||
2065 coarseType ==
"Basker" ||
2066 coarseType ==
"Cusolver" ||
2067 coarseType ==
"Tacho") &&
2068 (!params.isSublist(
"coarse: params") ||
2069 !params.sublist(
"coarse: params").isParameter(
"fix nullspace")))
2070 params.sublist(
"coarse: params").set(
"fix nullspace",
true);
2075 RCP<MueLu::Level> level0 = hierarchy->GetLevel(0);
2076 level0->Set(
"A", A);
2077 hierarchy->SetupRe();
2080 SetProcRankVerbose(oldRank);
2083template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2085 bool reuse = !SM_Matrix_.is_null();
2086 SM_Matrix_ = SM_Matrix_new;
2087 dump(SM_Matrix_,
"SM.m");
2092template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2128 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2132 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2133 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2138 if (implicitTranspose_) {
2140 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"restriction coarse (1,1) (implicit)");
2141 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2143 if (!onlyBoundary22_) {
2144 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (implicit)");
2145 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2148 if (Dk_1_T_R11_colMapsMatch_) {
2151 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restrictions import");
2152 DTR11Tmp_->doImport(*residual_, *toCrsMatrix(R11_)->getCrsGraph()->getImporter(), Xpetra::INSERT);
2154 if (!onlyBoundary22_) {
2155 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2156 toTpetra(Dk_1_T_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*Dres_), Teuchos::NO_TRANS);
2159 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2160 toTpetra(R11_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*P11res_), Teuchos::NO_TRANS);
2164 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2165 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2167 if (!onlyBoundary22_) {
2168 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2169 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2176 RCP<Teuchos::TimeMonitor> tmSubSolves = getTimer(
"subsolves");
2180 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2181 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2182 P11resTmp_->beginImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2184 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_) {
2185 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2186 DresTmp_->beginImport(*Dres_, *Importer22_, Xpetra::INSERT);
2190 if (!coarseA11_.is_null()) {
2191 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
2192 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2194 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2196#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2197 if (!thyraPrecOpH_.is_null()) {
2198 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2199 thyraPrecOpH_->apply(*P11resSubComm_, *P11xSubComm_, Teuchos::NO_TRANS, one, zero);
2202 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2206 if (!A22_.is_null()) {
2207 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2208 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2210 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2211#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2212 if (!thyraPrecOp22_.is_null()) {
2213 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2214 thyraPrecOp22_->apply(*DresSubComm_, *DxSubComm_, Teuchos::NO_TRANS, one, zero);
2217 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2220 if (coarseA11_.is_null() && !ImporterCoarse11_.is_null() && !implicitTranspose_)
2221 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2222 if (A22_.is_null() && !onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2223 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2227 RCP<Teuchos::TimeMonitor> tmProlongations = getTimer(
"prolongations");
2229 if (asyncTransfers_) {
2230 using Tpetra_Multivector = Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2231 using Tpetra_Import = Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>;
2233 auto tpP11 = toTpetra(P11_);
2234 auto tpDk_1 = toTpetra(Dk_1_);
2236 RCP<Tpetra_Multivector> tpP11x = toTpetra(P11x_);
2237 RCP<Tpetra_Multivector> tpP11x_colmap;
2238 RCP<Tpetra_Multivector> tpX = toTpetra(Teuchos::rcpFromRef(X));
2239 RCP<Tpetra_Multivector> tpResidual = toTpetra(residual_);
2240 RCP<Tpetra_Multivector> tpDx = toTpetra(Dx_);
2241 RCP<Tpetra_Multivector> tpDx_colmap;
2243 unsigned completedImports = 0;
2244 std::vector<bool> completedImport(2,
false);
2245 auto tpP11importer = tpP11->getCrsGraph()->getImporter();
2246 if (!tpP11importer.is_null()) {
2247 tpP11x_colmap = toTpetra(P11x_colmap_);
2248 tpP11x_colmap->beginImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2251 RCP<const Tpetra_Import> tpDk_1importer;
2252 if (!onlyBoundary22_) {
2253 tpDk_1importer = tpDk_1->getCrsGraph()->getImporter();
2254 if (!tpDk_1importer.is_null()) {
2255 tpDx_colmap = toTpetra(Dx_colmap_);
2256 tpDx_colmap->beginImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2259 completedImport[1] =
true;
2263 if (!fuseProlongationAndUpdate_) {
2264 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2265 tpResidual->putScalar(zero);
2268 while (completedImports < completedImport.size()) {
2269 for (
unsigned i = 0; i < completedImport.size(); i++) {
2270 if (completedImport[i])
continue;
2273 if (!tpP11importer.is_null()) {
2274 if (tpP11x_colmap->transferArrived()) {
2275 tpP11x_colmap->endImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2276 completedImport[i] =
true;
2279 if (fuseProlongationAndUpdate_) {
2280 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2281 tpP11->localApply(*tpP11x_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2283 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2284 tpP11->localApply(*tpP11x_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2288 completedImport[i] =
true;
2291 if (fuseProlongationAndUpdate_) {
2292 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2293 tpP11->localApply(*tpP11x, *tpX, Teuchos::NO_TRANS, one, one);
2295 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2296 tpP11->localApply(*tpP11x, *tpResidual, Teuchos::NO_TRANS, one, one);
2300 if (!tpDk_1importer.is_null()) {
2301 if (tpDx_colmap->transferArrived()) {
2302 tpDx_colmap->endImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2303 completedImport[i] =
true;
2306 if (fuseProlongationAndUpdate_) {
2307 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2308 tpDk_1->localApply(*tpDx_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2310 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2311 tpDk_1->localApply(*tpDx_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2315 completedImport[i] =
true;
2318 if (fuseProlongationAndUpdate_) {
2319 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2320 tpDk_1->localApply(*tpDx, *tpX, Teuchos::NO_TRANS, one, one);
2322 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2323 tpDk_1->localApply(*tpDx, *tpResidual, Teuchos::NO_TRANS, one, one);
2330 if (!fuseProlongationAndUpdate_) {
2331 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2332 X.update(one, *residual_, one);
2335 if (fuseProlongationAndUpdate_) {
2337 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused)");
2338 P11_->apply(*P11x_, X, Teuchos::NO_TRANS, one, one);
2341 if (!onlyBoundary22_) {
2342 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused)");
2343 Dk_1_->apply(*Dx_, X, Teuchos::NO_TRANS, one, one);
2347 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused)");
2348 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2351 if (!onlyBoundary22_) {
2352 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused)");
2353 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS, one, one);
2357 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2358 X.update(one, *residual_, one);
2365template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2367 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2370 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2371 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2372 if (implicitTranspose_)
2373 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2375 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2379 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2380 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2381 P11resTmp_->doImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2383 if (!coarseA11_.is_null()) {
2384 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2385 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2390 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2391 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2392 X.update(one, *residual_, one);
2396template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2398 if (onlyBoundary22_)
2401 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2404 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2405 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2406 if (implicitTranspose_)
2407 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2409 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2413 if (!Importer22_.is_null() && !implicitTranspose_) {
2414 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2415 DresTmp_->doImport(*Dres_, *Importer22_, Xpetra::INSERT);
2417 if (!A22_.is_null()) {
2418 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2419 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2424 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2425 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS);
2426 X.update(one, *residual_, one);
2430template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2435 RCP<Teuchos::TimeMonitor> tm = getTimer(
"solve");
2438 if (!onlyBoundary11_ && X.getNumVectors() != P11res_->getNumVectors())
2439 allocateMemory(X.getNumVectors());
2443 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2445 PreSmoother11_->Apply(X, RHS, use_as_preconditioner_);
2449 if (mode_ ==
"additive")
2450 applyInverseAdditive(RHS, X);
2451 else if (mode_ ==
"121") {
2455 }
else if (mode_ ==
"212") {
2459 }
else if (mode_ ==
"1")
2461 else if (mode_ ==
"2")
2463 else if (mode_ ==
"7") {
2467 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2469 PreSmoother11_->Apply(X, RHS,
false);
2474 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2476 PostSmoother11_->Apply(X, RHS,
false);
2479 }
else if (mode_ ==
"none") {
2482 applyInverseAdditive(RHS, X);
2486 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2488 PostSmoother11_->Apply(X, RHS,
false);
2492template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2497template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2499 RefMaxwell(
const Teuchos::RCP<Matrix> &SM_Matrix,
2500 Teuchos::ParameterList &List,
2502 int spaceNumber = List.get<
int>(
"refmaxwell: space number", 1);
2504 RCP<Matrix> Dk_1, Dk_2, D0;
2505 RCP<Matrix> M1_beta, M1_alpha;
2506 RCP<Matrix> Mk_one, Mk_1_one;
2507 RCP<Matrix> invMk_1_invBeta, invMk_2_invAlpha;
2508 RCP<MultiVector> Nullspace11, Nullspace22;
2509 RCP<RealValuedMultiVector> NodalCoords;
2511 Dk_1 =
pop(List,
"Dk_1", Dk_1);
2512 Dk_2 = pop<RCP<Matrix>>(List,
"Dk_2", Dk_2);
2513 D0 = pop<RCP<Matrix>>(List,
"D0", D0);
2515 M1_beta = pop<RCP<Matrix>>(List,
"M1_beta", M1_beta);
2516 M1_alpha = pop<RCP<Matrix>>(List,
"M1_alpha", M1_alpha);
2518 Mk_one = pop<RCP<Matrix>>(List,
"Mk_one", Mk_one);
2519 Mk_1_one = pop<RCP<Matrix>>(List,
"Mk_1_one", Mk_1_one);
2521 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"invMk_1_invBeta", invMk_1_invBeta);
2522 invMk_2_invAlpha = pop<RCP<Matrix>>(List,
"invMk_2_invAlpha", invMk_2_invAlpha);
2524 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace11", Nullspace11);
2525 Nullspace22 = pop<RCP<MultiVector>>(List,
"Nullspace22", Nullspace22);
2526 NodalCoords = pop<RCP<RealValuedMultiVector>>(List,
"Coordinates", NodalCoords);
2529 if (List.isType<RCP<Matrix>>(
"Ms")) {
2530 if (M1_beta.is_null())
2531 M1_beta =
pop<RCP<Matrix>>(List,
"Ms");
2533 TEUCHOS_ASSERT(
false);
2535 if (List.isType<RCP<Matrix>>(
"M1")) {
2536 if (Mk_one.is_null())
2537 Mk_one = pop<RCP<Matrix>>(List,
"M1");
2539 TEUCHOS_ASSERT(
false);
2541 if (List.isType<RCP<Matrix>>(
"M0inv")) {
2542 if (invMk_1_invBeta.is_null())
2543 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"M0inv");
2545 TEUCHOS_ASSERT(
false);
2547 if (List.isType<RCP<MultiVector>>(
"Nullspace")) {
2548 if (Nullspace11.is_null())
2549 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace");
2551 TEUCHOS_ASSERT(
false);
2554 if (spaceNumber == 1) {
2557 else if (D0.is_null())
2559 if (M1_beta.is_null())
2561 }
else if (spaceNumber == 2) {
2564 else if (D0.is_null())
2568 initialize(spaceNumber,
2572 invMk_1_invBeta, invMk_2_invAlpha,
2573 Nullspace11, Nullspace22,
2575 Teuchos::null, Teuchos::null,
2578 if (SM_Matrix != Teuchos::null)
2579 resetMatrix(SM_Matrix, ComputePrec);
2582template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2584 initialize(
const Teuchos::RCP<Matrix> &D0_Matrix,
2585 const Teuchos::RCP<Matrix> &Ms_Matrix,
2586 const Teuchos::RCP<Matrix> &M0inv_Matrix,
2587 const Teuchos::RCP<Matrix> &M1_Matrix,
2588 const Teuchos::RCP<MultiVector> &Nullspace11,
2589 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2590 const Teuchos::RCP<MultiVector> &Material,
2591 Teuchos::ParameterList &List) {
2593 D0_Matrix, Teuchos::null, D0_Matrix,
2594 Ms_Matrix, Teuchos::null,
2595 M1_Matrix, Teuchos::null,
2596 M0inv_Matrix, Teuchos::null,
2597 Nullspace11, Teuchos::null,
2599 Teuchos::null, Material,
2603template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2606 const Teuchos::RCP<Matrix> &Dk_1,
2607 const Teuchos::RCP<Matrix> &Dk_2,
2608 const Teuchos::RCP<Matrix> &D0,
2609 const Teuchos::RCP<Matrix> &M1_beta,
2610 const Teuchos::RCP<Matrix> &M1_alpha,
2611 const Teuchos::RCP<Matrix> &Mk_one,
2612 const Teuchos::RCP<Matrix> &Mk_1_one,
2613 const Teuchos::RCP<Matrix> &invMk_1_invBeta,
2614 const Teuchos::RCP<Matrix> &invMk_2_invAlpha,
2615 const Teuchos::RCP<MultiVector> &Nullspace11,
2616 const Teuchos::RCP<MultiVector> &Nullspace22,
2617 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2618 const Teuchos::RCP<MultiVector> &Material_beta,
2619 const Teuchos::RCP<MultiVector> &Material_alpha,
2620 Teuchos::ParameterList &List) {
2622 if (spaceNumber_ == 1)
2623 solverName_ =
"RefMaxwell";
2624 else if (spaceNumber_ == 2)
2625 solverName_ =
"RefDarcy";
2627 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
2628 "spaceNumber needs to be 1 (HCurl) or 2 (HDiv)");
2629 HierarchyCoarse11_ = Teuchos::null;
2630 Hierarchy22_ = Teuchos::null;
2631 PreSmoother11_ = Teuchos::null;
2632 PostSmoother11_ = Teuchos::null;
2633 disable_addon_ =
false;
2634 disable_addon_22_ =
true;
2638 setParameters(List);
2641 TEUCHOS_ASSERT((k == 1) || (k == 2));
2643 TEUCHOS_ASSERT(Dk_1 != Teuchos::null);
2645 TEUCHOS_ASSERT(D0 != Teuchos::null);
2648 TEUCHOS_ASSERT(M1_beta != Teuchos::null);
2651 TEUCHOS_ASSERT(M1_alpha != Teuchos::null);
2653 if (!disable_addon_) {
2655 TEUCHOS_ASSERT(Mk_one != Teuchos::null);
2656 TEUCHOS_ASSERT(invMk_1_invBeta != Teuchos::null);
2659 if ((k >= 2) && !disable_addon_22_) {
2661 TEUCHOS_ASSERT(Dk_2 != Teuchos::null);
2662 TEUCHOS_ASSERT(Mk_1_one != Teuchos::null);
2663 TEUCHOS_ASSERT(invMk_2_invAlpha != Teuchos::null);
2666#ifdef HAVE_MUELU_DEBUG
2668 TEUCHOS_ASSERT(D0->getRangeMap()->isSameAs(*D0->getRowMap()));
2671 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRangeMap()));
2672 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRowMap()));
2675 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*D0->getRangeMap()));
2679 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRangeMap()));
2680 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRowMap()));
2683 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*D0->getRangeMap()))
2686 if (!disable_addon_) {
2688 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRangeMap()));
2689 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRowMap()));
2692 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2695 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRangeMap()));
2696 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRowMap()));
2699 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2702 if ((k >= 2) && !disable_addon_22_) {
2704 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRangeMap()));
2705 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRowMap()));
2708 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2711 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_2->getRangeMap()));
2714 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRangeMap()));
2715 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRowMap()));
2718 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*Dk_2->getDomainMap()));
2723 if (Dk_1->getRowMap()->lib() == Xpetra::UseTpetra) {
2728 RCP<Matrix> Dk_1copy = MatrixFactory::Build(Dk_1->getRowMap(), Dk_1->getColMap(), 0);
2729 RCP<CrsMatrix> Dk_1copyCrs = toCrsMatrix(Dk_1copy);
2730 ArrayRCP<const size_t> Dk_1rowptr_RCP;
2731 ArrayRCP<const LO> Dk_1colind_RCP;
2732 ArrayRCP<const SC> Dk_1vals_RCP;
2733 toCrsMatrix(Dk_1)->getAllValues(Dk_1rowptr_RCP, Dk_1colind_RCP, Dk_1vals_RCP);
2735 ArrayRCP<size_t> Dk_1copyrowptr_RCP;
2736 ArrayRCP<LO> Dk_1copycolind_RCP;
2737 ArrayRCP<SC> Dk_1copyvals_RCP;
2738 Dk_1copyCrs->allocateAllValues(Dk_1vals_RCP.size(), Dk_1copyrowptr_RCP, Dk_1copycolind_RCP, Dk_1copyvals_RCP);
2739 Dk_1copyrowptr_RCP.deepCopy(Dk_1rowptr_RCP());
2740 Dk_1copycolind_RCP.deepCopy(Dk_1colind_RCP());
2741 Dk_1copyvals_RCP.deepCopy(Dk_1vals_RCP());
2742 Dk_1copyCrs->setAllValues(Dk_1copyrowptr_RCP,
2745 Dk_1copyCrs->expertStaticFillComplete(Dk_1->getDomainMap(), Dk_1->getRangeMap(),
2746 toCrsMatrix(Dk_1)->getCrsGraph()->getImporter(),
2747 toCrsMatrix(Dk_1)->getCrsGraph()->getExporter());
2750 Dk_1_ = MatrixFactory::BuildCopy(Dk_1);
2752 if ((!Dk_2.is_null()) && (Dk_2->getRowMap()->lib() == Xpetra::UseTpetra)) {
2757 RCP<Matrix> Dk_2copy = MatrixFactory::Build(Dk_2->getRowMap(), Dk_2->getColMap(), 0);
2758 RCP<CrsMatrix> Dk_2copyCrs = toCrsMatrix(Dk_2copy);
2759 ArrayRCP<const size_t> Dk_2rowptr_RCP;
2760 ArrayRCP<const LO> Dk_2colind_RCP;
2761 ArrayRCP<const SC> Dk_2vals_RCP;
2762 toCrsMatrix(Dk_2)->getAllValues(Dk_2rowptr_RCP, Dk_2colind_RCP, Dk_2vals_RCP);
2764 ArrayRCP<size_t> Dk_2copyrowptr_RCP;
2765 ArrayRCP<LO> Dk_2copycolind_RCP;
2766 ArrayRCP<SC> Dk_2copyvals_RCP;
2767 Dk_2copyCrs->allocateAllValues(Dk_2vals_RCP.size(), Dk_2copyrowptr_RCP, Dk_2copycolind_RCP, Dk_2copyvals_RCP);
2768 Dk_2copyrowptr_RCP.deepCopy(Dk_2rowptr_RCP());
2769 Dk_2copycolind_RCP.deepCopy(Dk_2colind_RCP());
2770 Dk_2copyvals_RCP.deepCopy(Dk_2vals_RCP());
2771 Dk_2copyCrs->setAllValues(Dk_2copyrowptr_RCP,
2774 Dk_2copyCrs->expertStaticFillComplete(Dk_2->getDomainMap(), Dk_2->getRangeMap(),
2775 toCrsMatrix(Dk_2)->getCrsGraph()->getImporter(),
2776 toCrsMatrix(Dk_2)->getCrsGraph()->getExporter());
2778 }
else if (!Dk_2.is_null())
2779 Dk_2_ = MatrixFactory::BuildCopy(Dk_2);
2782 M1_alpha_ = M1_alpha;
2784 Material_beta_ = Material_beta;
2785 Material_alpha_ = Material_alpha;
2788 Mk_1_one_ = Mk_1_one;
2790 invMk_1_invBeta_ = invMk_1_invBeta;
2791 invMk_2_invAlpha_ = invMk_2_invAlpha;
2793 NodalCoords_ = NodalCoords;
2794 Nullspace11_ = Nullspace11;
2795 Nullspace22_ = Nullspace22;
2798 dump(Dk_1_,
"Dk_1_clean.m");
2799 dump(Dk_2_,
"Dk_2_clean.m");
2801 dump(M1_beta_,
"M1_beta.m");
2802 dump(M1_alpha_,
"M1_alpha.m");
2804 dump(Mk_one_,
"Mk_one.m");
2805 dump(Mk_1_one_,
"Mk_1_one.m");
2807 dump(invMk_1_invBeta_,
"invMk_1_invBeta.m");
2808 dump(invMk_2_invAlpha_,
"invMk_2_invAlpha.m");
2810 dumpCoords(NodalCoords_,
"coords.m");
2813template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2815 describe(Teuchos::FancyOStream &out,
const Teuchos::EVerbosityLevel )
const {
2816 std::ostringstream oss;
2818 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->
getDomainMap()->getComm();
2822 if (!coarseA11_.is_null())
2823 root = comm->getRank();
2828 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
2832 oss <<
"\n--------------------------------------------------------------------------------\n"
2833 <<
"--- " + solverName_ +
2835 "--------------------------------------------------------------------------------"
2842 SM_Matrix_->getRowMap()->getComm()->barrier();
2844 numRows = SM_Matrix_->getGlobalNumRows();
2845 nnz = SM_Matrix_->getGlobalNumEntries();
2847 Xpetra::global_size_t tt = numRows;
2860 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
2861 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2863 if (!A22_.is_null()) {
2864 numRows = A22_->getGlobalNumRows();
2865 nnz = A22_->getGlobalNumEntries();
2867 oss <<
"(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2873 if (PreSmoother11_ != null && PreSmoother11_ == PostSmoother11_)
2874 oss <<
"Smoother 11 both : " << PreSmoother11_->description() << std::endl;
2876 oss <<
"Smoother 11 pre : "
2877 << (PreSmoother11_ != null ? PreSmoother11_->description() :
"no smoother") << std::endl;
2878 oss <<
"Smoother 11 post : "
2879 << (PostSmoother11_ != null ? PostSmoother11_->description() :
"no smoother") << std::endl;
2884 std::string outstr = oss.str();
2887 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2888 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
2890 int strLength = outstr.size();
2891 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
2892 if (comm->getRank() != root)
2893 outstr.resize(strLength);
2894 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
2899 if (!HierarchyCoarse11_.is_null())
2900 HierarchyCoarse11_->describe(out, GetVerbLevel());
2902 if (!Hierarchy22_.is_null())
2903 Hierarchy22_->describe(out, GetVerbLevel());
2907 std::ostringstream oss2;
2909 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
2910 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;
2912 int numProcs = comm->getSize();
2914 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2915 TEUCHOS_TEST_FOR_EXCEPTION(tmpic == Teuchos::null,
Exceptions::RuntimeError,
"Cannot cast base Teuchos::Comm to Teuchos::MpiComm object.");
2916 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
2920 if (!coarseA11_.is_null())
2922 if (!A22_.is_null())
2924 std::vector<char> states(numProcs, 0);
2926 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
2928 states.push_back(status);
2931 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
2932 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
2933 for (
int j = 0; j < rowWidth; j++)
2934 if (proc + j < numProcs)
2935 if (states[proc + j] == 0)
2937 else if (states[proc + j] == 1)
2939 else if (states[proc + j] == 2)
2946 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
2955#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, const size_t expectedNNZperRow=0)
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,...