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 = (Dk_1_->getRowMap()->lib() == Xpetra::UseEpetra) ? Teuchos::ScalarTraits<SC>::eps() : 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 = (Dk_1_->getRowMap()->lib() == Xpetra::UseEpetra) ? Teuchos::ScalarTraits<SC>::eps() : 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#ifdef HAVE_MUELU_TPETRA
564 if ((!Dk_1_T_.is_null()) &&
566 (!toCrsMatrix(Dk_1_T_)->getCrsGraph()->getImporter().is_null()) &&
567 (!toCrsMatrix(R11_)->getCrsGraph()->getImporter().is_null()) &&
568 (Dk_1_T_->getColMap()->lib() == Xpetra::UseTpetra) &&
569 (R11_->getColMap()->lib() == Xpetra::UseTpetra))
570 Dk_1_T_R11_colMapsMatch_ = Dk_1_T_->getColMap()->isSameAs(*R11_->getColMap());
573 Dk_1_T_R11_colMapsMatch_ =
false;
574 if (Dk_1_T_R11_colMapsMatch_)
575 GetOStream(
Runtime0) << solverName_ +
"::compute(): Dk_1_T and R11 have matching colMaps" << std::endl;
577 asyncTransfers_ = parameterList_.get<
bool>(
"refmaxwell: async transfers");
583 if (parameterList_.isSublist(
"matvec params")) {
584 RCP<ParameterList> matvecParams = rcpFromRef(parameterList_.sublist(
"matvec params"));
590 if (!ImporterCoarse11_.is_null()) ImporterCoarse11_->setDistributorParameters(matvecParams);
591 if (!Importer22_.is_null()) Importer22_->setDistributorParameters(matvecParams);
593 if (!ImporterCoarse11_.is_null() && parameterList_.isSublist(
"refmaxwell: ImporterCoarse11 params")) {
594 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: ImporterCoarse11 params"));
595 ImporterCoarse11_->setDistributorParameters(importerParams);
597 if (!Importer22_.is_null() && parameterList_.isSublist(
"refmaxwell: Importer22 params")) {
598 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: Importer22 params"));
599 Importer22_->setDistributorParameters(importerParams);
605#ifdef HAVE_MUELU_CUDA
606 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStop();
610template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
613 doRebalancing = parameterList_.get<
bool>(
"refmaxwell: subsolves on subcommunicators");
614 rebalanceStriding = parameterList_.get<
int>(
"refmaxwell: subsolves striding", -1);
615 int numProcs = SM_Matrix_->getDomainMap()->getComm()->getSize();
617 doRebalancing =
false;
629 level.
Set(
"A", coarseA11_);
632 ParameterList repartheurParams;
633 repartheurParams.set(
"repartition: start level", 0);
635 int defaultTargetRows = 10000;
636 repartheurParams.set(
"repartition: min rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
637 repartheurParams.set(
"repartition: target rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
638 repartheurParams.set(
"repartition: min rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
639 repartheurParams.set(
"repartition: target rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
640 repartheurParams.set(
"repartition: max imbalance", precList11_.get<
double>(
"repartition: max imbalance", 1.1));
641 repartheurFactory->SetParameterList(repartheurParams);
643 level.
Request(
"number of partitions", repartheurFactory.get());
644 repartheurFactory->Build(level);
645 numProcsCoarseA11 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
646 numProcsCoarseA11 = std::min(numProcsCoarseA11, numProcs);
656 level.
Set(
"Map", Dk_1_->getDomainMap());
659 ParameterList repartheurParams;
660 repartheurParams.set(
"repartition: start level", 0);
661 repartheurParams.set(
"repartition: use map",
true);
663 int defaultTargetRows = 10000;
664 repartheurParams.set(
"repartition: min rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
665 repartheurParams.set(
"repartition: target rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
666 repartheurParams.set(
"repartition: min rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
667 repartheurParams.set(
"repartition: target rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
669 repartheurFactory->SetParameterList(repartheurParams);
671 level.
Request(
"number of partitions", repartheurFactory.get());
672 repartheurFactory->Build(level);
673 numProcsA22 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
674 numProcsA22 = std::min(numProcsA22, numProcs);
677 if (rebalanceStriding >= 1) {
678 TEUCHOS_ASSERT(rebalanceStriding * numProcsCoarseA11 <= numProcs);
679 TEUCHOS_ASSERT(rebalanceStriding * numProcsA22 <= numProcs);
680 if (rebalanceStriding * (numProcsCoarseA11 + numProcsA22) > numProcs) {
681 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling striding = " << rebalanceStriding <<
", since coarseA11 needs " << numProcsCoarseA11
682 <<
" procs and A22 needs " << numProcsA22 <<
" procs." << std::endl;
683 rebalanceStriding = -1;
685 int lclBadMatrixDistribution = (coarseA11_->getLocalNumEntries() == 0) || (Dk_1_->getDomainMap()->getLocalNumElements() == 0);
686 int gblBadMatrixDistribution =
false;
687 MueLu_maxAll(SM_Matrix_->getDomainMap()->getComm(), lclBadMatrixDistribution, gblBadMatrixDistribution);
688 if (gblBadMatrixDistribution) {
689 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;
690 rebalanceStriding = -1;
694 if ((numProcsCoarseA11 < 0) || (numProcsA22 < 0) || (numProcsCoarseA11 + numProcsA22 > numProcs)) {
695 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling rebalancing of subsolves, since partition heuristic resulted "
696 <<
"in undesirable number of partitions: " << numProcsCoarseA11 <<
", " << numProcsA22 << std::endl;
697 doRebalancing =
false;
701 doRebalancing =
false;
705template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
708 if (spaceNumber == 0)
709 return Teuchos::null;
711 std::string timerLabel;
712 if (spaceNumber == spaceNumber_) {
713 if (skipFirst11Level_)
714 timerLabel =
"Build coarse addon matrix 11";
716 timerLabel =
"Build addon matrix 11";
718 timerLabel =
"Build addon matrix 22";
720 RCP<Teuchos::TimeMonitor> tmAddon = getTimer(timerLabel);
724 RCP<Matrix> lumpedInverse;
725 if (spaceNumber == spaceNumber_) {
727 TEUCHOS_TEST_FOR_EXCEPTION(invMk_1_invBeta_ == Teuchos::null, std::invalid_argument,
729 "::buildCoarse11Matrix(): Inverse of "
730 "lumped mass matrix required for add-on (i.e. invMk_1_invBeta_ is null)");
731 lumpedInverse = invMk_1_invBeta_;
733 if (skipFirst11Level_) {
736 Zaux = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Mk_one_,
false, *P11_,
false, Zaux, GetOStream(
Runtime0),
true,
true);
738 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Zaux,
false, Z, GetOStream(
Runtime0),
true,
true);
741 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Mk_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
744 }
else if (spaceNumber == spaceNumber_ - 1) {
746 TEUCHOS_TEST_FOR_EXCEPTION(invMk_2_invAlpha_ == Teuchos::null, std::invalid_argument,
748 "::buildCoarse11Matrix(): Inverse of "
749 "lumped mass matrix required for add-on (i.e. invMk_2_invAlpha_ is null)");
750 lumpedInverse = invMk_2_invAlpha_;
753 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_2_,
true, *Mk_1_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
757 if (lumpedInverse->getGlobalMaxNumRowEntries() <= 1) {
760 RCP<Vector> diag = VectorFactory::Build(lumpedInverse->getRowMap());
761 lumpedInverse->getLocalDiagCopy(*diag);
763 ArrayRCP<Scalar> diagVals = diag->getDataNonConst(0);
764 for (
size_t j = 0; j < diag->getMap()->getLocalNumElements(); j++) {
765 diagVals[j] = Teuchos::ScalarTraits<Scalar>::squareroot(diagVals[j]);
768 if (Z->getRowMap()->isSameAs(*(diag->getMap())))
771 RCP<Import> importer = ImportFactory::Build(diag->getMap(), Z->getRowMap());
772 RCP<Vector> diag2 = VectorFactory::Build(Z->getRowMap());
773 diag2->doImport(*diag, *importer, Xpetra::INSERT);
774 Z->leftScale(*diag2);
776 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *Z,
false, addon, GetOStream(
Runtime0),
true,
true);
777 }
else if (parameterList_.get<
bool>(
"rap: triple product",
false) ==
false) {
780 C2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*lumpedInverse,
false, *Z,
false, C2, GetOStream(
Runtime0),
true,
true);
782 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *C2,
false, addon, GetOStream(
Runtime0),
true,
true);
784 addon = MatrixFactory::Build(Z->getDomainMap());
786 Xpetra::TripleMatrixMultiply<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
787 MultiplyRAP(*Z,
true, *lumpedInverse,
false, *Z,
false, *addon,
true,
true);
792template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
794 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build coarse (1,1) matrix");
796 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
800 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *P11_,
false, temp, GetOStream(
Runtime0),
true,
true);
801 if (ImporterCoarse11_.is_null())
802 coarseA11_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, coarseA11_, GetOStream(
Runtime0),
true,
true);
805 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
807 RCP<const Map> map = ImporterCoarse11_->getTargetMap()->removeEmptyProcesses();
808 temp2->removeEmptyProcessesInPlace(map);
809 if (!temp2.is_null() && temp2->getRowMap().is_null())
810 temp2 = Teuchos::null;
814 if (!disable_addon_) {
817 if (!coarseA11_.is_null() && Addon11_.is_null()) {
818 addon = buildAddon(spaceNumber_);
825 if (!coarseA11_.is_null()) {
827 RCP<Matrix> newCoarseA11;
828 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*coarseA11_,
false, one, *addon,
false, one, newCoarseA11, GetOStream(
Runtime0));
829 newCoarseA11->fillComplete();
830 coarseA11_ = newCoarseA11;
834 if (!coarseA11_.is_null() && !skipFirst11Level_) {
835 ArrayRCP<bool> coarseA11BCrows;
836 coarseA11BCrows.resize(coarseA11_->getRowMap()->getLocalNumElements());
837 for (
size_t i = 0; i < BCdomain22_.size(); i++)
838 for (
size_t k = 0; k < dim_; k++)
839 coarseA11BCrows[i * dim_ + k] = BCdomain22_(i);
840 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
843 if (applyBCsToCoarse11_)
847 if (!coarseA11_.is_null()) {
853 bool fixZeroDiagonal = !applyBCsToAnodal_;
854 if (precList11_.isParameter(
"rap: fix zero diagonals"))
855 fixZeroDiagonal = precList11_.get<
bool>(
"rap: fix zero diagonals");
857 if (fixZeroDiagonal) {
860 if (precList11_.isType<
magnitudeType>(
"rap: fix zero diagonals threshold"))
861 threshold = precList11_.get<
magnitudeType>(
"rap: fix zero diagonals threshold");
862 else if (precList11_.isType<
double>(
"rap: fix zero diagonals threshold"))
863 threshold = Teuchos::as<magnitudeType>(precList11_.get<
double>(
"rap: fix zero diagonals threshold"));
864 if (precList11_.isType<
double>(
"rap: fix zero diagonals replacement"))
865 replacement = Teuchos::as<Scalar>(precList11_.get<
double>(
"rap: fix zero diagonals replacement"));
866 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(coarseA11_,
true, GetOStream(
Warnings1), threshold, replacement);
870 coarseA11_->SetFixedBlockSize(dim_);
871 if (skipFirst11Level_)
872 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
874 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
878template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
883 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Rebalance coarseA11");
885 Level fineLevel, coarseLevel;
891 coarseLevel.
Set(
"A", coarseA11_);
892 coarseLevel.
Set(
"P", P11_);
893 coarseLevel.
Set(
"Coordinates", CoordsCoarse11_);
894 if (!NullspaceCoarse11_.is_null())
895 coarseLevel.
Set(
"Nullspace", NullspaceCoarse11_);
896 coarseLevel.
Set(
"number of partitions", numProcsCoarseA11);
897 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
899 coarseLevel.
setlib(coarseA11_->getDomainMap()->lib());
900 fineLevel.
setlib(coarseA11_->getDomainMap()->lib());
901 coarseLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
902 fineLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
904 std::string partName = precList11_.get<std::string>(
"repartition: partitioner",
"zoltan2");
905 RCP<Factory> partitioner;
906 if (partName ==
"zoltan") {
907#ifdef HAVE_MUELU_ZOLTAN
914 }
else if (partName ==
"zoltan2") {
915#ifdef HAVE_MUELU_ZOLTAN2
917 ParameterList partParams;
918 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList11_.sublist(
"repartition: params",
false)));
919 partParams.set(
"ParameterList", partpartParams);
920 partitioner->SetParameterList(partParams);
928 ParameterList repartParams;
929 repartParams.set(
"repartition: print partition distribution", precList11_.get<
bool>(
"repartition: print partition distribution",
false));
930 repartParams.set(
"repartition: remap parts", precList11_.get<
bool>(
"repartition: remap parts",
true));
931 if (rebalanceStriding >= 1) {
932 bool acceptPart = (SM_Matrix_->getDomainMap()->getComm()->getRank() % rebalanceStriding) == 0;
933 if (SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsCoarseA11 * rebalanceStriding)
935 repartParams.set(
"repartition: remap accept partition", acceptPart);
937 repartFactory->SetParameterList(repartParams);
939 repartFactory->SetFactory(
"Partition", partitioner);
942 ParameterList newPparams;
943 newPparams.set(
"type",
"Interpolation");
944 newPparams.set(
"repartition: rebalance P and R", precList11_.get<
bool>(
"repartition: rebalance P and R",
false));
945 newPparams.set(
"repartition: use subcommunicators",
true);
946 newPparams.set(
"repartition: rebalance Nullspace", !NullspaceCoarse11_.is_null());
948 if (!NullspaceCoarse11_.is_null())
950 newP->SetParameterList(newPparams);
951 newP->SetFactory(
"Importer", repartFactory);
954 ParameterList rebAcParams;
955 rebAcParams.set(
"repartition: use subcommunicators",
true);
956 newA->SetParameterList(rebAcParams);
957 newA->SetFactory(
"Importer", repartFactory);
959 coarseLevel.
Request(
"P", newP.get());
960 coarseLevel.
Request(
"Importer", repartFactory.get());
961 coarseLevel.
Request(
"A", newA.get());
962 coarseLevel.
Request(
"Coordinates", newP.get());
963 if (!NullspaceCoarse11_.is_null())
964 coarseLevel.
Request(
"Nullspace", newP.get());
965 repartFactory->Build(coarseLevel);
967 if (!precList11_.get<
bool>(
"repartition: rebalance P and R",
false))
968 ImporterCoarse11_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
969 P11_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
970 coarseA11_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
971 CoordsCoarse11_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
972 if (!NullspaceCoarse11_.is_null())
973 NullspaceCoarse11_ = coarseLevel.
Get<RCP<MultiVector>>(
"Nullspace", newP.get());
975 if (!coarseA11_.is_null()) {
977 coarseA11_->SetFixedBlockSize(dim_);
978 if (skipFirst11Level_)
979 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
981 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
984 coarseA11_AP_reuse_data_ = Teuchos::null;
985 coarseA11_RAP_reuse_data_ = Teuchos::null;
987 if (!disable_addon_ && enable_reuse_) {
989 RCP<const Import> ImporterCoarse11 = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
990 RCP<const Map> targetMap = ImporterCoarse11->getTargetMap();
991 ParameterList XpetraList;
992 XpetraList.set(
"Restrict Communicator",
true);
993 Addon11_ = MatrixFactory::Build(Addon11_, *ImporterCoarse11, *ImporterCoarse11, targetMap, targetMap, rcp(&XpetraList,
false));
998template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1001 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1003 Level fineLevel, coarseLevel;
1009 fineLevel.
Set(
"A", SM_Matrix_);
1010 coarseLevel.
Set(
"P", Dk_1_);
1011 coarseLevel.
Set(
"Coordinates", Coords22_);
1013 coarseLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1014 fineLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1015 coarseLevel.setObjectLabel(solverName_ +
" (2,2)");
1016 fineLevel.setObjectLabel(solverName_ +
" (2,2)");
1018 RCP<RAPFactory> rapFact = rcp(
new RAPFactory());
1019 ParameterList rapList = *(rapFact->GetValidParameterList());
1020 rapList.set(
"transpose: use implicit",
true);
1021 rapList.set(
"rap: fix zero diagonals", parameterList_.get<
bool>(
"rap: fix zero diagonals",
true));
1022 rapList.set(
"rap: fix zero diagonals threshold", parameterList_.get<
double>(
"rap: fix zero diagonals threshold", Teuchos::ScalarTraits<double>::eps()));
1023 rapList.set(
"rap: triple product", parameterList_.get<
bool>(
"rap: triple product",
false));
1024 rapFact->SetParameterList(rapList);
1026 if (!A22_AP_reuse_data_.is_null()) {
1027 coarseLevel.
AddKeepFlag(
"AP reuse data", rapFact.get());
1028 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"AP reuse data", A22_AP_reuse_data_, rapFact.get());
1030 if (!A22_RAP_reuse_data_.is_null()) {
1031 coarseLevel.
AddKeepFlag(
"RAP reuse data", rapFact.get());
1032 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"RAP reuse data", A22_RAP_reuse_data_, rapFact.get());
1036 if (doRebalancing) {
1037 coarseLevel.
Set(
"number of partitions", numProcsA22);
1038 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
1040 std::string partName = precList22_.get<std::string>(
"repartition: partitioner",
"zoltan2");
1041 RCP<Factory> partitioner;
1042 if (partName ==
"zoltan") {
1043#ifdef HAVE_MUELU_ZOLTAN
1045 partitioner->SetFactory(
"A", rapFact);
1051 }
else if (partName ==
"zoltan2") {
1052#ifdef HAVE_MUELU_ZOLTAN2
1054 ParameterList partParams;
1055 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList22_.sublist(
"repartition: params",
false)));
1056 partParams.set(
"ParameterList", partpartParams);
1057 partitioner->SetParameterList(partParams);
1058 partitioner->SetFactory(
"A", rapFact);
1066 ParameterList repartParams;
1067 repartParams.set(
"repartition: print partition distribution", precList22_.get<
bool>(
"repartition: print partition distribution",
false));
1068 repartParams.set(
"repartition: remap parts", precList22_.get<
bool>(
"repartition: remap parts",
true));
1069 if (rebalanceStriding >= 1) {
1070 bool acceptPart = ((SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank()) % rebalanceStriding) == 0;
1071 if (SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsA22 * rebalanceStriding)
1074 TEUCHOS_ASSERT(coarseA11_.is_null());
1075 repartParams.set(
"repartition: remap accept partition", acceptPart);
1077 repartParams.set(
"repartition: remap accept partition", coarseA11_.is_null());
1078 repartFactory->SetParameterList(repartParams);
1079 repartFactory->SetFactory(
"A", rapFact);
1081 repartFactory->SetFactory(
"Partition", partitioner);
1084 ParameterList newPparams;
1085 newPparams.set(
"type",
"Interpolation");
1086 newPparams.set(
"repartition: rebalance P and R", precList22_.get<
bool>(
"repartition: rebalance P and R",
false));
1087 newPparams.set(
"repartition: use subcommunicators",
true);
1088 newPparams.set(
"repartition: rebalance Nullspace",
false);
1090 newP->SetParameterList(newPparams);
1091 newP->SetFactory(
"Importer", repartFactory);
1094 ParameterList rebAcParams;
1095 rebAcParams.set(
"repartition: use subcommunicators",
true);
1096 newA->SetParameterList(rebAcParams);
1097 newA->SetFactory(
"A", rapFact);
1098 newA->SetFactory(
"Importer", repartFactory);
1100 coarseLevel.
Request(
"P", newP.get());
1101 coarseLevel.
Request(
"Importer", repartFactory.get());
1102 coarseLevel.
Request(
"A", newA.get());
1103 coarseLevel.
Request(
"Coordinates", newP.get());
1104 rapFact->Build(fineLevel, coarseLevel);
1105 repartFactory->Build(coarseLevel);
1107 if (!precList22_.get<
bool>(
"repartition: rebalance P and R",
false))
1108 Importer22_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1109 Dk_1_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1110 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1111 Coords22_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1113 if (!P22_.is_null()) {
1120 coarseLevel.
Request(
"A", rapFact.get());
1121 if (enable_reuse_) {
1122 coarseLevel.
Request(
"AP reuse data", rapFact.get());
1123 coarseLevel.
Request(
"RAP reuse data", rapFact.get());
1126 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", rapFact.get());
1128 if (enable_reuse_) {
1129 if (coarseLevel.
IsAvailable(
"AP reuse data", rapFact.get()))
1130 A22_AP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"AP reuse data", rapFact.get());
1131 if (coarseLevel.
IsAvailable(
"RAP reuse data", rapFact.get()))
1132 A22_RAP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"RAP reuse data", rapFact.get());
1136 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1137 if (Importer22_.is_null()) {
1139 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1140 if (!implicitTranspose_)
1141 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1143 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1146 RCP<const Import> Dimporter = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
1147 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(DorigDomainMap_, DorigImporter_);
1149 RCP<Matrix> temp, temp2;
1150 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1151 if (!implicitTranspose_)
1152 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1154 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1157 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), Dimporter);
1159 ParameterList XpetraList;
1160 XpetraList.set(
"Restrict Communicator",
true);
1161 XpetraList.set(
"Timer Label",
"MueLu::RebalanceA22");
1162 RCP<const Map> targetMap = Importer22_->getTargetMap();
1163 A22_ = MatrixFactory::Build(temp2, *Importer22_, *Importer22_, targetMap, targetMap, rcp(&XpetraList,
false));
1167 if (not A22_.is_null() and not disable_addon_22_ and spaceNumber_ > 1) {
1168 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1170 RCP<Matrix> addon22 = buildAddon(spaceNumber_ - 1);
1174 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A22_,
false, one, *addon22,
false, one, newA22, GetOStream(
Runtime0));
1175 newA22->fillComplete();
1179 if (!A22_.is_null()) {
1180 dump(A22_,
"A22.m");
1181 A22_->setObjectLabel(solverName_ +
" (2,2)");
1183 if (spaceNumber_ - 1 == 0)
1184 A22_->SetFixedBlockSize(1);
1186 A22_->SetFixedBlockSize(dim_);
1190template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1193 RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(
new FactoryManager());
1196 level.setObjectLabel(solverName_ +
" (1,1)");
1197 level.
Set(
"A", SM_Matrix_);
1198 level.
setlib(SM_Matrix_->getDomainMap()->lib());
1200 level.
Set(
"NodeMatrix", A22_);
1201 level.
Set(
"D0", Dk_1_);
1203 if ((parameterList_.get<std::string>(
"smoother: pre type") !=
"NONE") && (parameterList_.get<std::string>(
"smoother: post type") !=
"NONE")) {
1204 std::string preSmootherType = parameterList_.get<std::string>(
"smoother: pre type");
1205 std::string postSmootherType = parameterList_.get<std::string>(
"smoother: post type");
1207 ParameterList preSmootherList, postSmootherList;
1208 if (parameterList_.isSublist(
"smoother: pre params"))
1209 preSmootherList = parameterList_.sublist(
"smoother: pre params");
1210 if (parameterList_.isSublist(
"smoother: post params"))
1211 postSmootherList = parameterList_.sublist(
"smoother: post params");
1213 RCP<SmootherPrototype> preSmootherPrototype = rcp(
new TrilinosSmoother(preSmootherType, preSmootherList));
1214 RCP<SmootherPrototype> postSmootherPrototype = rcp(
new TrilinosSmoother(postSmootherType, postSmootherList));
1215 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(preSmootherPrototype, postSmootherPrototype));
1217 level.
Request(
"PreSmoother", smootherFact.get());
1218 level.
Request(
"PostSmoother", smootherFact.get());
1219 if (enable_reuse_) {
1220 ParameterList smootherFactoryParams;
1221 smootherFactoryParams.set(
"keep smoother data",
true);
1222 smootherFact->SetParameterList(smootherFactoryParams);
1223 level.
Request(
"PreSmoother data", smootherFact.get());
1224 level.
Request(
"PostSmoother data", smootherFact.get());
1225 if (!PreSmootherData11_.is_null())
1226 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1227 if (!PostSmootherData11_.is_null())
1228 level.
Set(
"PostSmoother data", PostSmootherData11_, smootherFact.get());
1230 smootherFact->Build(level);
1231 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1232 PostSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PostSmoother", smootherFact.get());
1233 if (enable_reuse_) {
1234 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1235 PostSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PostSmoother data", smootherFact.get());
1238 std::string smootherType = parameterList_.get<std::string>(
"smoother: type");
1240 ParameterList smootherList;
1241 if (parameterList_.isSublist(
"smoother: params"))
1242 smootherList = parameterList_.sublist(
"smoother: params");
1244 RCP<SmootherPrototype> smootherPrototype = rcp(
new TrilinosSmoother(smootherType, smootherList));
1245 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(smootherPrototype));
1246 level.
Request(
"PreSmoother", smootherFact.get());
1247 if (enable_reuse_) {
1248 ParameterList smootherFactoryParams;
1249 smootherFactoryParams.set(
"keep smoother data",
true);
1250 smootherFact->SetParameterList(smootherFactoryParams);
1251 level.
Request(
"PreSmoother data", smootherFact.get());
1252 if (!PreSmootherData11_.is_null())
1253 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1255 smootherFact->Build(level);
1256 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1257 PostSmoother11_ = PreSmoother11_;
1259 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1263template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1265 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer(
"Allocate MVs");
1268 if (!R11_.is_null())
1269 P11res_ = MultiVectorFactory::Build(R11_->getRangeMap(), numVectors);
1271 P11res_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1272 P11res_->setObjectLabel(
"P11res");
1274 if (Dk_1_T_R11_colMapsMatch_) {
1275 DTR11Tmp_ = MultiVectorFactory::Build(R11_->getColMap(), numVectors);
1276 DTR11Tmp_->setObjectLabel(
"DTR11Tmp");
1278 if (!ImporterCoarse11_.is_null()) {
1279 P11resTmp_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1280 P11resTmp_->setObjectLabel(
"P11resTmp");
1281 P11x_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1283 P11x_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1284 P11x_->setObjectLabel(
"P11x");
1287 if (!Dk_1_T_.is_null())
1288 Dres_ = MultiVectorFactory::Build(Dk_1_T_->getRangeMap(), numVectors);
1290 Dres_ = MultiVectorFactory::Build(Dk_1_->getDomainMap(), numVectors);
1291 Dres_->setObjectLabel(
"Dres");
1293 if (!Importer22_.is_null()) {
1294 DresTmp_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1295 DresTmp_->setObjectLabel(
"DresTmp");
1296 Dx_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1297 }
else if (!onlyBoundary22_)
1298 Dx_ = MultiVectorFactory::Build(A22_->getDomainMap(), numVectors);
1300 Dx_->setObjectLabel(
"Dx");
1302 if (!coarseA11_.is_null()) {
1303 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
1304 P11resSubComm_ = MultiVectorFactory::Build(P11resTmp_, Teuchos::View);
1306 P11resSubComm_ = MultiVectorFactory::Build(P11res_, Teuchos::View);
1307 P11resSubComm_->replaceMap(coarseA11_->getRangeMap());
1308 P11resSubComm_->setObjectLabel(
"P11resSubComm");
1310 P11xSubComm_ = MultiVectorFactory::Build(P11x_, Teuchos::View);
1311 P11xSubComm_->replaceMap(coarseA11_->getDomainMap());
1312 P11xSubComm_->setObjectLabel(
"P11xSubComm");
1315 if (!A22_.is_null()) {
1316 if (!Importer22_.is_null() && !implicitTranspose_)
1317 DresSubComm_ = MultiVectorFactory::Build(DresTmp_, Teuchos::View);
1319 DresSubComm_ = MultiVectorFactory::Build(Dres_, Teuchos::View);
1320 DresSubComm_->replaceMap(A22_->getRangeMap());
1321 DresSubComm_->setObjectLabel(
"DresSubComm");
1323 DxSubComm_ = MultiVectorFactory::Build(Dx_, Teuchos::View);
1324 DxSubComm_->replaceMap(A22_->getDomainMap());
1325 DxSubComm_->setObjectLabel(
"DxSubComm");
1328 if (asyncTransfers_) {
1329 if (!toCrsMatrix(P11_)->getCrsGraph()->getImporter().is_null())
1330 P11x_colmap_ = MultiVectorFactory::Build(P11_->getColMap(), numVectors);
1331 if (!toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter().is_null())
1332 Dx_colmap_ = MultiVectorFactory::Build(Dk_1_->getColMap(), numVectors);
1335 residual_ = MultiVectorFactory::Build(SM_Matrix_->getDomainMap(), numVectors);
1336 residual_->setObjectLabel(
"residual");
1339template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1341 if (dump_matrices_ && !A.is_null()) {
1342 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1343 Xpetra::IO<SC, LO, GO, NO>::Write(name, *A);
1347template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1349 if (dump_matrices_ && !X.is_null()) {
1350 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1351 Xpetra::IO<SC, LO, GO, NO>::Write(name, *X);
1355template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1357 if (dump_matrices_ && !X.is_null()) {
1358 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1359 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, *X);
1363template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1365 if (dump_matrices_) {
1366 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1367 std::ofstream out(name);
1368 for (
size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
1369 out << v[i] <<
"\n";
1373template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1375 if (dump_matrices_) {
1376 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1377 std::ofstream out(name);
1378 auto vH = Kokkos::create_mirror_view(v);
1379 Kokkos::deep_copy(vH, v);
1380 out <<
"%%MatrixMarket matrix array real general\n"
1381 << vH.extent(0) <<
" 1\n";
1382 for (
size_t i = 0; i < vH.size(); i++)
1383 out << vH[i] <<
"\n";
1387template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1391 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1393 if (comm.is_null()) {
1395 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1396 SM_Matrix_->getRowMap()->getComm()->barrier();
1398 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1401 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1404 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1408 return Teuchos::null;
1411template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1413 buildNullspace(
const int spaceNumber,
const Kokkos::View<bool *, typename Node::device_type> &bcs,
const bool applyBCs) {
1414 std::string spaceLabel;
1415 if (spaceNumber == 0)
1416 spaceLabel =
"nodal";
1417 else if (spaceNumber == 1)
1418 spaceLabel =
"edge";
1419 else if (spaceNumber == 2)
1420 spaceLabel =
"face";
1422 TEUCHOS_ASSERT(
false);
1423 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1426 RCP<Teuchos::TimeMonitor> tm;
1427 if (spaceNumber > 0) {
1428 tm = getTimer(
"nullspace " + spaceLabel);
1429 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" nullspace" << std::endl;
1432 if (spaceNumber == 0) {
1433 return Teuchos::null;
1435 }
else if (spaceNumber == 1) {
1436 RCP<MultiVector> CoordsSC;
1438 RCP<MultiVector> Nullspace = MultiVectorFactory::Build(D0_->getRowMap(), NodalCoords_->getNumVectors());
1439 D0_->apply(*CoordsSC, *Nullspace);
1441 bool normalize = parameterList_.get<
bool>(
"refmaxwell: normalize nullspace", MasterList::getDefault<bool>(
"refmaxwell: normalize nullspace"));
1446 ArrayRCP<ArrayRCP<const Scalar>> localNullspace(dim_);
1447 for (
size_t i = 0; i < dim_; i++)
1448 localNullspace[i] = Nullspace->getData(i);
1449 coordinateType localMinLen = Teuchos::ScalarTraits<coordinateType>::rmax();
1450 coordinateType localMeanLen = Teuchos::ScalarTraits<coordinateType>::zero();
1451 coordinateType localMaxLen = Teuchos::ScalarTraits<coordinateType>::zero();
1452 for (
size_t j = 0; j < Nullspace->getMap()->getLocalNumElements(); j++) {
1453 Scalar lenSC = Teuchos::ScalarTraits<Scalar>::zero();
1454 for (
size_t i = 0; i < dim_; i++)
1455 lenSC += localNullspace[i][j] * localNullspace[i][j];
1456 coordinateType len = Teuchos::as<coordinateType>(Teuchos::ScalarTraits<Scalar>::real(Teuchos::ScalarTraits<Scalar>::squareroot(lenSC)));
1457 localMinLen = std::min(localMinLen, len);
1458 localMaxLen = std::max(localMaxLen, len);
1459 localMeanLen += len;
1462 RCP<const Teuchos::Comm<int>> comm = Nullspace->getMap()->getComm();
1466 meanLen /= Nullspace->getMap()->getGlobalNumElements();
1470 GetOStream(
Statistics2) <<
"Edge length (min/mean/max): " << minLen <<
" / " << meanLen <<
" / " << maxLen << std::endl;
1475 GetOStream(
Runtime0) << solverName_ +
"::compute(): normalizing nullspace" << std::endl;
1477 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1479 Array<Scalar> normsSC(NodalCoords_->getNumVectors(), one / Teuchos::as<Scalar>(meanLen));
1480 Nullspace->scale(normsSC());
1487 dump(Nullspace,
"nullspaceEdge.m");
1491 }
else if (spaceNumber == 2) {
1492#if KOKKOS_VERSION >= 40799
1493 using ATS = KokkosKernels::ArithTraits<Scalar>;
1495 using ATS = Kokkos::ArithTraits<Scalar>;
1497 using impl_Scalar =
typename ATS::val_type;
1498#if KOKKOS_VERSION >= 40799
1499 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1501 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
1503 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1505 RCP<Matrix> facesToNodes;
1507 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1512 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1518 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1525 RCP<RealValuedMultiVector> ghostedNodalCoordinates;
1526 auto importer = facesToNodes->getCrsGraph()->getImporter();
1527 if (!importer.is_null()) {
1528 ghostedNodalCoordinates = Xpetra::MultiVectorFactory<coordinateType, LocalOrdinal, GlobalOrdinal, Node>::Build(importer->getTargetMap(), dim_);
1529 ghostedNodalCoordinates->doImport(*NodalCoords_, *importer, Xpetra::INSERT);
1531 ghostedNodalCoordinates = NodalCoords_;
1533 RCP<MultiVector> Nullspace = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(facesToNodes->getRangeMap(), dim_);
1535 auto facesToNodesLocal = facesToNodes->getLocalMatrixDevice();
1536 auto localNodalCoordinates = ghostedNodalCoordinates->getLocalViewDevice(Tpetra::Access::ReadOnly);
1537 auto localFaceNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1540 Kokkos::parallel_for(
1541 solverName_ +
"::buildFaceProjection_nullspace",
1542 range_type(0, Nullspace->getMap()->getLocalNumElements()),
1543 KOKKOS_LAMBDA(
const size_t f) {
1544 size_t n0 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f));
1545 size_t n1 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 1);
1546 size_t n2 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 2);
1547 impl_Scalar elementNullspace00 = localNodalCoordinates(n1, 0) - localNodalCoordinates(n0, 0);
1548 impl_Scalar elementNullspace10 = localNodalCoordinates(n2, 0) - localNodalCoordinates(n0, 0);
1549 impl_Scalar elementNullspace01 = localNodalCoordinates(n1, 1) - localNodalCoordinates(n0, 1);
1550 impl_Scalar elementNullspace11 = localNodalCoordinates(n2, 1) - localNodalCoordinates(n0, 1);
1551 impl_Scalar elementNullspace02 = localNodalCoordinates(n1, 2) - localNodalCoordinates(n0, 2);
1552 impl_Scalar elementNullspace12 = localNodalCoordinates(n2, 2) - localNodalCoordinates(n0, 2);
1554 localFaceNullspace(f, 0) = impl_ATS::magnitude(elementNullspace01 * elementNullspace12 - elementNullspace02 * elementNullspace11) / 6.0;
1555 localFaceNullspace(f, 1) = impl_ATS::magnitude(elementNullspace02 * elementNullspace10 - elementNullspace00 * elementNullspace12) / 6.0;
1556 localFaceNullspace(f, 2) = impl_ATS::magnitude(elementNullspace00 * elementNullspace11 - elementNullspace01 * elementNullspace10) / 6.0;
1565 dump(Nullspace,
"nullspaceFace.m");
1570 TEUCHOS_ASSERT(
false);
1571 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1575template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1576Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1578#if KOKKOS_VERSION >= 40799
1579 using ATS = KokkosKernels::ArithTraits<Scalar>;
1581 using ATS = Kokkos::ArithTraits<Scalar>;
1583 using impl_Scalar =
typename ATS::val_type;
1584#if KOKKOS_VERSION >= 40799
1585 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1587 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
1589 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1591 typedef typename Matrix::local_matrix_device_type KCRS;
1592 typedef typename KCRS::StaticCrsGraphType graph_t;
1593 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1594 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1595 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1597 const impl_Scalar impl_SC_ONE = impl_ATS::one();
1598 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
1599 const impl_Scalar impl_half = impl_SC_ONE / (impl_SC_ONE + impl_SC_ONE);
1601 std::string spaceLabel;
1602 if (spaceNumber == 0)
1603 spaceLabel =
"nodal";
1604 else if (spaceNumber == 1)
1605 spaceLabel =
"edge";
1606 else if (spaceNumber == 2)
1607 spaceLabel =
"face";
1609 TEUCHOS_ASSERT(
false);
1611 RCP<Teuchos::TimeMonitor> tm;
1612 if (spaceNumber > 0) {
1613 tm = getTimer(
"projection " + spaceLabel);
1614 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" projection" << std::endl;
1617 RCP<Matrix> incidence;
1618 if (spaceNumber == 0) {
1620 return Teuchos::null;
1622 }
else if (spaceNumber == 1) {
1626 }
else if (spaceNumber == 2) {
1629 TEUCHOS_ASSERT(spaceNumber_ == 2);
1631 RCP<Matrix> facesToNodes;
1633 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1636 dump(edgesToNodes,
"edgesToNodes.m");
1638 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1642 dump(facesToEdges,
"facesToEdges.m");
1644 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1649 dump(facesToNodes,
"facesToNodes.m");
1651 incidence = facesToNodes;
1654 TEUCHOS_ASSERT(
false);
1659 RCP<const Map> rowMap = incidence->getRowMap();
1660 RCP<const Map> blockColMap = MapFactory::Build(incidence->getColMap(), dim);
1661 RCP<const Map> blockDomainMap = MapFactory::Build(incidence->getDomainMap(), dim);
1663 auto localIncidence = incidence->getLocalMatrixDevice();
1664 size_t numLocalRows = rowMap->getLocalNumElements();
1665 size_t numLocalColumns = dim * incidence->getColMap()->getLocalNumElements();
1666 size_t nnzEstimate = dim * localIncidence.graph.entries.size();
1667 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"projection_rowptr_" + spaceLabel), numLocalRows + 1);
1668 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"projection_colind_" + spaceLabel), nnzEstimate);
1669 scalar_view_t vals(
"projection_vals_" + spaceLabel, nnzEstimate);
1672 Kokkos::parallel_for(
1673 solverName_ +
"::buildProjection_adjustRowptr_" + spaceLabel,
1674 range_type(0, numLocalRows + 1),
1675 KOKKOS_LAMBDA(
const size_t i) {
1676 rowptr(i) = dim * localIncidence.graph.row_map(i);
1679 auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1683 Kokkos::parallel_for(
1684 solverName_ +
"::buildProjection_enterValues_" + spaceLabel,
1685 range_type(0, numLocalRows),
1686 KOKKOS_LAMBDA(
const size_t f) {
1687 for (
size_t jj = localIncidence.graph.row_map(f); jj < localIncidence.graph.row_map(f + 1); jj++) {
1688 for (
size_t k = 0; k < dim; k++) {
1689 colind(dim * jj + k) = dim * localIncidence.graph.entries(jj) + k;
1690 if (impl_ATS::magnitude(localIncidence.values(jj)) > tol)
1691 vals(dim * jj + k) = impl_half * localNullspace(f, k);
1693 vals(dim * jj + k) = impl_SC_ZERO;
1699 typename CrsMatrix::local_matrix_device_type lclProjection(
"local projection " + spaceLabel,
1700 numLocalRows, numLocalColumns, nnzEstimate,
1701 vals, rowptr, colind);
1702 RCP<Matrix> projection = MatrixFactory::Build(lclProjection,
1703 rowMap, blockColMap,
1704 blockDomainMap, rowMap);
1709template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1711 Teuchos::RCP<Matrix> &P_nodal,
1712 Teuchos::RCP<MultiVector> &Nullspace_nodal,
1713 Teuchos::RCP<RealValuedMultiVector> &CoarseCoords_nodal)
const {
1714 RCP<Teuchos::TimeMonitor> tm = getTimer(
"nodal prolongator");
1715 GetOStream(
Runtime0) << solverName_ +
"::compute(): building nodal prolongator" << std::endl;
1720 const SC SC_ONE = Teuchos::ScalarTraits<SC>::one();
1723 Level fineLevel, coarseLevel;
1729 fineLevel.
Set(
"A", A_nodal);
1730 fineLevel.
Set(
"Coordinates", NodalCoords_);
1731 fineLevel.
Set(
"DofsPerNode", 1);
1732 coarseLevel.
setlib(A_nodal->getDomainMap()->lib());
1733 fineLevel.
setlib(A_nodal->getDomainMap()->lib());
1734 coarseLevel.setObjectLabel(A_nodal->getObjectLabel());
1735 fineLevel.setObjectLabel(A_nodal->getObjectLabel());
1738 RCP<MultiVector> nullSpace = MultiVectorFactory::Build(A_nodal->getRowMap(), NSdim);
1739 nullSpace->putScalar(SC_ONE);
1740 fineLevel.
Set(
"Nullspace", nullSpace);
1742 std::string algo = parameterList_.get<std::string>(
"multigrid algorithm");
1744 RCP<Factory> amalgFact, dropFact, UncoupledAggFact, coarseMapFact, TentativePFact, Tfact, SaPFact;
1758 dropFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1760 double dropTol = parameterList_.get<
double>(
"aggregation: drop tol");
1761 std::string dropScheme = parameterList_.get<std::string>(
"aggregation: drop scheme");
1762 std::string distLaplAlgo = parameterList_.get<std::string>(
"aggregation: distance laplacian algo");
1763 dropFact->SetParameter(
"aggregation: drop tol", Teuchos::ParameterEntry(dropTol));
1764 dropFact->SetParameter(
"aggregation: drop scheme", Teuchos::ParameterEntry(dropScheme));
1765 dropFact->SetParameter(
"aggregation: distance laplacian algo", Teuchos::ParameterEntry(distLaplAlgo));
1767 UncoupledAggFact->SetFactory(
"Graph", dropFact);
1768 int minAggSize = parameterList_.get<
int>(
"aggregation: min agg size");
1769 UncoupledAggFact->SetParameter(
"aggregation: min agg size", Teuchos::ParameterEntry(minAggSize));
1770 int maxAggSize = parameterList_.get<
int>(
"aggregation: max agg size");
1771 UncoupledAggFact->SetParameter(
"aggregation: max agg size", Teuchos::ParameterEntry(maxAggSize));
1772 bool matchMLbehavior1 = parameterList_.get<
bool>(
"aggregation: match ML phase1");
1773 UncoupledAggFact->SetParameter(
"aggregation: match ML phase1", Teuchos::ParameterEntry(matchMLbehavior1));
1774 bool matchMLbehavior2a = parameterList_.get<
bool>(
"aggregation: match ML phase2a");
1775 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2a", Teuchos::ParameterEntry(matchMLbehavior2a));
1776 bool matchMLbehavior2b = parameterList_.get<
bool>(
"aggregation: match ML phase2b");
1777 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2b", Teuchos::ParameterEntry(matchMLbehavior2b));
1779 coarseMapFact->SetFactory(
"Aggregates", UncoupledAggFact);
1781 TentativePFact->SetFactory(
"Aggregates", UncoupledAggFact);
1782 TentativePFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1783 TentativePFact->SetFactory(
"CoarseMap", coarseMapFact);
1785 Tfact->SetFactory(
"Aggregates", UncoupledAggFact);
1786 Tfact->SetFactory(
"CoarseMap", coarseMapFact);
1789 SaPFact->SetFactory(
"P", TentativePFact);
1790 coarseLevel.
Request(
"P", SaPFact.get());
1792 coarseLevel.
Request(
"P", TentativePFact.get());
1793 coarseLevel.
Request(
"Nullspace", TentativePFact.get());
1794 coarseLevel.
Request(
"Coordinates", Tfact.get());
1796 RCP<AggregationExportFactory> aggExport;
1797 bool exportVizData = parameterList_.get<
bool>(
"aggregation: export visualization data");
1798 if (exportVizData) {
1800 ParameterList aggExportParams;
1801 aggExportParams.set(
"aggregation: output filename",
"aggs.vtk");
1802 aggExportParams.set(
"aggregation: output file: agg style",
"Jacks");
1803 aggExport->SetParameterList(aggExportParams);
1805 aggExport->SetFactory(
"Aggregates", UncoupledAggFact);
1806 aggExport->SetFactory(
"UnAmalgamationInfo", amalgFact);
1807 fineLevel.
Request(
"Aggregates", UncoupledAggFact.get());
1808 fineLevel.
Request(
"UnAmalgamationInfo", amalgFact.get());
1812 coarseLevel.
Get(
"P", P_nodal, SaPFact.get());
1814 coarseLevel.
Get(
"P", P_nodal, TentativePFact.get());
1815 coarseLevel.
Get(
"Nullspace", Nullspace_nodal, TentativePFact.get());
1816 coarseLevel.
Get(
"Coordinates", CoarseCoords_nodal, Tfact.get());
1819 aggExport->Build(fineLevel, coarseLevel);
1823template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1824Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1826 RCP<Teuchos::TimeMonitor> tm = getTimer(
"vectorial nodal prolongator");
1827 GetOStream(
Runtime0) << solverName_ +
"::compute(): building vectorial nodal prolongator" << std::endl;
1829 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1831 typedef typename Matrix::local_matrix_device_type KCRS;
1832 typedef typename KCRS::StaticCrsGraphType graph_t;
1833 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1834 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1835 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1840 RCP<Map> blockRowMap = MapFactory::Build(P_nodal->getRowMap(), dim);
1841 RCP<Map> blockColMap = MapFactory::Build(P_nodal->getColMap(), dim);
1842 RCP<Map> blockDomainMap = MapFactory::Build(P_nodal->getDomainMap(), dim);
1845 auto localP_nodal = P_nodal->getLocalMatrixDevice();
1847 size_t numLocalRows = blockRowMap->getLocalNumElements();
1848 size_t numLocalColumns = blockColMap->getLocalNumElements();
1849 size_t nnzEstimate = dim * localP_nodal.graph.entries.size();
1850 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_rowptr"), numLocalRows + 1);
1851 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_colind"), nnzEstimate);
1852 scalar_view_t vals(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_vals"), nnzEstimate);
1855 Kokkos::parallel_for(
1856 solverName_ +
"::buildVectorNodalProlongator_adjustRowptr",
1857 range_type(0, localP_nodal.numRows() + 1),
1859 if (i < localP_nodal.numRows()) {
1860 for (size_t k = 0; k < dim; k++) {
1861 rowptr(dim * i + k) = dim * localP_nodal.graph.row_map(i) + k;
1864 rowptr(dim * localP_nodal.numRows()) = dim * localP_nodal.graph.row_map(i);
1868 Kokkos::parallel_for(
1869 solverName_ +
"::buildVectorNodalProlongator_adjustColind",
1870 range_type(0, localP_nodal.graph.entries.size()),
1871 KOKKOS_LAMBDA(
const size_t jj) {
1872 for (
size_t k = 0; k < dim; k++) {
1873 colind(dim * jj + k) = dim * localP_nodal.graph.entries(jj) + k;
1875 vals(dim * jj + k) = 1.;
1879 typename CrsMatrix::local_matrix_device_type lclVectorNodalP(
"local vector nodal prolongator",
1880 numLocalRows, numLocalColumns, nnzEstimate,
1881 vals, rowptr, colind);
1882 RCP<Matrix> vectorNodalP = MatrixFactory::Build(lclVectorNodalP,
1883 blockRowMap, blockColMap,
1884 blockDomainMap, blockRowMap);
1886 return vectorNodalP;
1889template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1892 const Teuchos::RCP<Matrix> &A_nodal,
1893 const Teuchos::RCP<MultiVector> &Nullspace,
1894 Teuchos::RCP<Matrix> &Prolongator,
1895 Teuchos::RCP<MultiVector> &coarseNullspace,
1896 Teuchos::RCP<RealValuedMultiVector> &coarseNodalCoords)
const {
1897#if KOKKOS_VERSION >= 40799
1898 using ATS = KokkosKernels::ArithTraits<Scalar>;
1900 using ATS = Kokkos::ArithTraits<Scalar>;
1902 using impl_Scalar =
typename ATS::val_type;
1903 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1905 std::string typeStr;
1906 switch (spaceNumber) {
1909 TEUCHOS_ASSERT(A_nodal.is_null());
1918 TEUCHOS_ASSERT(
false);
1921 const bool skipFirstLevel = !A_nodal.is_null();
1923 RCP<Teuchos::TimeMonitor> tm;
1924 if (spaceNumber > 0) {
1925 tm = getTimer(
"special prolongator " + typeStr);
1926 GetOStream(
Runtime0) << solverName_ +
"::compute(): building special " + typeStr +
" prolongator" << std::endl;
1929 RCP<Matrix> projection = buildProjection(spaceNumber, Nullspace);
1930 dump(projection, typeStr +
"Projection.m");
1932 if (skipFirstLevel) {
1933 RCP<Matrix> P_nodal;
1934 RCP<MultiVector> coarseNodalNullspace;
1936 buildNodalProlongator(A_nodal, P_nodal, coarseNodalNullspace, coarseNodalCoords);
1938 dump(P_nodal,
"P_nodal_" + typeStr +
".m");
1939 dump(coarseNodalNullspace,
"coarseNullspace_nodal_" + typeStr +
".m");
1941 RCP<Matrix> vectorP_nodal = buildVectorNodalProlongator(P_nodal);
1943 dump(vectorP_nodal,
"vectorP_nodal_" + typeStr +
".m");
1945 Prolongator = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*projection,
false, *vectorP_nodal,
false, Prolongator, GetOStream(
Runtime0),
true,
true);
1994 coarseNullspace = MultiVectorFactory::Build(vectorP_nodal->getDomainMap(), dim);
1996 auto localNullspace_nodal = coarseNodalNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1997 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1998 Kokkos::parallel_for(
1999 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
2000 range_type(0, coarseNodalNullspace->getLocalLength()),
2001 KOKKOS_LAMBDA(
const size_t i) {
2002 impl_Scalar val = localNullspace_nodal(i, 0);
2003 for (
size_t j = 0; j < dim; j++)
2004 localNullspace_coarse(dim * i + j, j) = val;
2008 Prolongator = projection;
2009 coarseNodalCoords = NodalCoords_;
2011 if (spaceNumber == 0) {
2013 }
else if (spaceNumber >= 1) {
2015 coarseNullspace = MultiVectorFactory::Build(projection->getDomainMap(), dim);
2016 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
2017 Kokkos::parallel_for(
2018 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
2019 range_type(0, coarseNullspace->getLocalLength() / dim),
2020 KOKKOS_LAMBDA(
const size_t i) {
2021 for (
size_t j = 0; j < dim; j++)
2022 localNullspace_coarse(dim * i + j, j) = 1.0;
2028template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2030 Teuchos::RCP<Operator> &thyraPrecOp,
2031 const Teuchos::RCP<Matrix> &A,
2032 const Teuchos::RCP<MultiVector> &Nullspace,
2033 const Teuchos::RCP<RealValuedMultiVector> &Coords,
2034 const Teuchos::RCP<MultiVector> &Material,
2035 Teuchos::ParameterList ¶ms,
2038 const bool isSingular) {
2039 int oldRank = SetProcRankVerbose(A->getDomainMap()->getComm()->getRank());
2041 RCP<ParameterList> pl = rcp(
new ParameterList());
2042 pl->set(
"printLoadBalancingInfo",
true);
2043 pl->set(
"printCommInfo",
true);
2044 GetOStream(
Statistics2) << PerfUtils::PrintMatrixInfo(*A, label, pl);
2046#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2047 if (params.isType<std::string>(
"Preconditioner Type")) {
2048 TEUCHOS_ASSERT(!reuse);
2050 if (params.get<std::string>(
"Preconditioner Type") ==
"MueLu") {
2051 ParameterList &userParamList = params.sublist(
"Preconditioner Types").sublist(
"MueLu").sublist(
"user data");
2052 if (!Nullspace.is_null())
2053 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2054 if (!Material.is_null())
2055 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2056 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2058 thyraPrecOp = rcp(
new XpetraThyraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(coarseA11_, rcp(¶ms,
false)));
2065 ParameterList &userParamList = params.sublist(
"user data");
2066 if (!Coords.is_null())
2067 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2068 if (!Nullspace.is_null())
2069 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2070 if (!Material.is_null())
2071 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2074 std::string coarseType =
"";
2075 if (params.isParameter(
"coarse: type")) {
2076 coarseType = params.get<std::string>(
"coarse: type");
2078 std::transform(coarseType.begin(), coarseType.end(), coarseType.begin(), ::tolower);
2079 std::transform(coarseType.begin(), ++coarseType.begin(), coarseType.begin(), ::toupper);
2081 if ((coarseType ==
"" ||
2082 coarseType ==
"Klu" ||
2083 coarseType ==
"Klu2" ||
2084 coarseType ==
"Superlu" ||
2085 coarseType ==
"Superlu_dist" ||
2086 coarseType ==
"Superludist" ||
2087 coarseType ==
"Basker" ||
2088 coarseType ==
"Cusolver" ||
2089 coarseType ==
"Tacho") &&
2090 (!params.isSublist(
"coarse: params") ||
2091 !params.sublist(
"coarse: params").isParameter(
"fix nullspace")))
2092 params.sublist(
"coarse: params").set(
"fix nullspace",
true);
2097 RCP<MueLu::Level> level0 = hierarchy->GetLevel(0);
2098 level0->Set(
"A", A);
2099 hierarchy->SetupRe();
2102 SetProcRankVerbose(oldRank);
2105template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2107 bool reuse = !SM_Matrix_.is_null();
2108 SM_Matrix_ = SM_Matrix_new;
2109 dump(SM_Matrix_,
"SM.m");
2114template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2150 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2154 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2155 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2160 if (implicitTranspose_) {
2162 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"restriction coarse (1,1) (implicit)");
2163 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2165 if (!onlyBoundary22_) {
2166 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (implicit)");
2167 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2170 if (Dk_1_T_R11_colMapsMatch_) {
2173 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restrictions import");
2174 DTR11Tmp_->doImport(*residual_, *toCrsMatrix(R11_)->getCrsGraph()->getImporter(), Xpetra::INSERT);
2176 if (!onlyBoundary22_) {
2177 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2178 toTpetra(Dk_1_T_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*Dres_), Teuchos::NO_TRANS);
2181 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2182 toTpetra(R11_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*P11res_), Teuchos::NO_TRANS);
2186 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2187 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2189 if (!onlyBoundary22_) {
2190 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2191 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2198 RCP<Teuchos::TimeMonitor> tmSubSolves = getTimer(
"subsolves");
2202 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2203 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2204 P11resTmp_->beginImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2206 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_) {
2207 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2208 DresTmp_->beginImport(*Dres_, *Importer22_, Xpetra::INSERT);
2212 if (!coarseA11_.is_null()) {
2213 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
2214 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2216 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2218#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2219 if (!thyraPrecOpH_.is_null()) {
2220 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2221 thyraPrecOpH_->apply(*P11resSubComm_, *P11xSubComm_, Teuchos::NO_TRANS, one, zero);
2224 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2228 if (!A22_.is_null()) {
2229 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2230 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2232 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2233#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2234 if (!thyraPrecOp22_.is_null()) {
2235 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2236 thyraPrecOp22_->apply(*DresSubComm_, *DxSubComm_, Teuchos::NO_TRANS, one, zero);
2239 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2242 if (coarseA11_.is_null() && !ImporterCoarse11_.is_null() && !implicitTranspose_)
2243 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2244 if (A22_.is_null() && !onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2245 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2249 RCP<Teuchos::TimeMonitor> tmProlongations = getTimer(
"prolongations");
2251 if (asyncTransfers_) {
2252 using Tpetra_Multivector = Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2253 using Tpetra_Import = Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>;
2255 auto tpP11 = toTpetra(P11_);
2256 auto tpDk_1 = toTpetra(Dk_1_);
2258 RCP<Tpetra_Multivector> tpP11x = toTpetra(P11x_);
2259 RCP<Tpetra_Multivector> tpP11x_colmap;
2260 RCP<Tpetra_Multivector> tpX = toTpetra(Teuchos::rcpFromRef(X));
2261 RCP<Tpetra_Multivector> tpResidual = toTpetra(residual_);
2262 RCP<Tpetra_Multivector> tpDx = toTpetra(Dx_);
2263 RCP<Tpetra_Multivector> tpDx_colmap;
2265 unsigned completedImports = 0;
2266 std::vector<bool> completedImport(2,
false);
2267 auto tpP11importer = tpP11->getCrsGraph()->getImporter();
2268 if (!tpP11importer.is_null()) {
2269 tpP11x_colmap = toTpetra(P11x_colmap_);
2270 tpP11x_colmap->beginImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2273 RCP<const Tpetra_Import> tpDk_1importer;
2274 if (!onlyBoundary22_) {
2275 tpDk_1importer = tpDk_1->getCrsGraph()->getImporter();
2276 if (!tpDk_1importer.is_null()) {
2277 tpDx_colmap = toTpetra(Dx_colmap_);
2278 tpDx_colmap->beginImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2281 completedImport[1] =
true;
2285 if (!fuseProlongationAndUpdate_) {
2286 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2287 tpResidual->putScalar(zero);
2290 while (completedImports < completedImport.size()) {
2291 for (
unsigned i = 0; i < completedImport.size(); i++) {
2292 if (completedImport[i])
continue;
2295 if (!tpP11importer.is_null()) {
2296 if (tpP11x_colmap->transferArrived()) {
2297 tpP11x_colmap->endImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2298 completedImport[i] =
true;
2301 if (fuseProlongationAndUpdate_) {
2302 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2303 tpP11->localApply(*tpP11x_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2305 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2306 tpP11->localApply(*tpP11x_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2310 completedImport[i] =
true;
2313 if (fuseProlongationAndUpdate_) {
2314 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2315 tpP11->localApply(*tpP11x, *tpX, Teuchos::NO_TRANS, one, one);
2317 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2318 tpP11->localApply(*tpP11x, *tpResidual, Teuchos::NO_TRANS, one, one);
2322 if (!tpDk_1importer.is_null()) {
2323 if (tpDx_colmap->transferArrived()) {
2324 tpDx_colmap->endImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2325 completedImport[i] =
true;
2328 if (fuseProlongationAndUpdate_) {
2329 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2330 tpDk_1->localApply(*tpDx_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2332 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2333 tpDk_1->localApply(*tpDx_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2337 completedImport[i] =
true;
2340 if (fuseProlongationAndUpdate_) {
2341 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2342 tpDk_1->localApply(*tpDx, *tpX, Teuchos::NO_TRANS, one, one);
2344 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2345 tpDk_1->localApply(*tpDx, *tpResidual, Teuchos::NO_TRANS, one, one);
2352 if (!fuseProlongationAndUpdate_) {
2353 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2354 X.update(one, *residual_, one);
2357 if (fuseProlongationAndUpdate_) {
2359 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused)");
2360 P11_->apply(*P11x_, X, Teuchos::NO_TRANS, one, one);
2363 if (!onlyBoundary22_) {
2364 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused)");
2365 Dk_1_->apply(*Dx_, X, Teuchos::NO_TRANS, one, one);
2369 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused)");
2370 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2373 if (!onlyBoundary22_) {
2374 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused)");
2375 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS, one, one);
2379 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2380 X.update(one, *residual_, one);
2387template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2389 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2392 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2393 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2394 if (implicitTranspose_)
2395 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2397 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2401 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2402 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2403 P11resTmp_->doImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2405 if (!coarseA11_.is_null()) {
2406 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2407 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2412 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2413 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2414 X.update(one, *residual_, one);
2418template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2420 if (onlyBoundary22_)
2423 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2426 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2427 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2428 if (implicitTranspose_)
2429 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2431 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2435 if (!Importer22_.is_null() && !implicitTranspose_) {
2436 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2437 DresTmp_->doImport(*Dres_, *Importer22_, Xpetra::INSERT);
2439 if (!A22_.is_null()) {
2440 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2441 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2446 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2447 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS);
2448 X.update(one, *residual_, one);
2452template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2457 RCP<Teuchos::TimeMonitor> tm = getTimer(
"solve");
2460 if (!onlyBoundary11_ && X.getNumVectors() != P11res_->getNumVectors())
2461 allocateMemory(X.getNumVectors());
2465 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2467 PreSmoother11_->Apply(X, RHS, use_as_preconditioner_);
2471 if (mode_ ==
"additive")
2472 applyInverseAdditive(RHS, X);
2473 else if (mode_ ==
"121") {
2477 }
else if (mode_ ==
"212") {
2481 }
else if (mode_ ==
"1")
2483 else if (mode_ ==
"2")
2485 else if (mode_ ==
"7") {
2489 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2491 PreSmoother11_->Apply(X, RHS,
false);
2496 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2498 PostSmoother11_->Apply(X, RHS,
false);
2501 }
else if (mode_ ==
"none") {
2504 applyInverseAdditive(RHS, X);
2508 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2510 PostSmoother11_->Apply(X, RHS,
false);
2514template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2519template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2521 RefMaxwell(
const Teuchos::RCP<Matrix> &SM_Matrix,
2522 Teuchos::ParameterList &List,
2524 int spaceNumber = List.get<
int>(
"refmaxwell: space number", 1);
2526 RCP<Matrix> Dk_1, Dk_2, D0;
2527 RCP<Matrix> M1_beta, M1_alpha;
2528 RCP<Matrix> Mk_one, Mk_1_one;
2529 RCP<Matrix> invMk_1_invBeta, invMk_2_invAlpha;
2530 RCP<MultiVector> Nullspace11, Nullspace22;
2531 RCP<RealValuedMultiVector> NodalCoords;
2533 Dk_1 =
pop(List,
"Dk_1", Dk_1);
2534 Dk_2 = pop<RCP<Matrix>>(List,
"Dk_2", Dk_2);
2535 D0 = pop<RCP<Matrix>>(List,
"D0", D0);
2537 M1_beta = pop<RCP<Matrix>>(List,
"M1_beta", M1_beta);
2538 M1_alpha = pop<RCP<Matrix>>(List,
"M1_alpha", M1_alpha);
2540 Mk_one = pop<RCP<Matrix>>(List,
"Mk_one", Mk_one);
2541 Mk_1_one = pop<RCP<Matrix>>(List,
"Mk_1_one", Mk_1_one);
2543 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"invMk_1_invBeta", invMk_1_invBeta);
2544 invMk_2_invAlpha = pop<RCP<Matrix>>(List,
"invMk_2_invAlpha", invMk_2_invAlpha);
2546 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace11", Nullspace11);
2547 Nullspace22 = pop<RCP<MultiVector>>(List,
"Nullspace22", Nullspace22);
2548 NodalCoords = pop<RCP<RealValuedMultiVector>>(List,
"Coordinates", NodalCoords);
2551 if (List.isType<RCP<Matrix>>(
"Ms")) {
2552 if (M1_beta.is_null())
2553 M1_beta =
pop<RCP<Matrix>>(List,
"Ms");
2555 TEUCHOS_ASSERT(
false);
2557 if (List.isType<RCP<Matrix>>(
"M1")) {
2558 if (Mk_one.is_null())
2559 Mk_one = pop<RCP<Matrix>>(List,
"M1");
2561 TEUCHOS_ASSERT(
false);
2563 if (List.isType<RCP<Matrix>>(
"M0inv")) {
2564 if (invMk_1_invBeta.is_null())
2565 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"M0inv");
2567 TEUCHOS_ASSERT(
false);
2569 if (List.isType<RCP<MultiVector>>(
"Nullspace")) {
2570 if (Nullspace11.is_null())
2571 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace");
2573 TEUCHOS_ASSERT(
false);
2576 if (spaceNumber == 1) {
2579 else if (D0.is_null())
2581 if (M1_beta.is_null())
2583 }
else if (spaceNumber == 2) {
2586 else if (D0.is_null())
2590 initialize(spaceNumber,
2594 invMk_1_invBeta, invMk_2_invAlpha,
2595 Nullspace11, Nullspace22,
2597 Teuchos::null, Teuchos::null,
2600 if (SM_Matrix != Teuchos::null)
2601 resetMatrix(SM_Matrix, ComputePrec);
2604template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2606 initialize(
const Teuchos::RCP<Matrix> &D0_Matrix,
2607 const Teuchos::RCP<Matrix> &Ms_Matrix,
2608 const Teuchos::RCP<Matrix> &M0inv_Matrix,
2609 const Teuchos::RCP<Matrix> &M1_Matrix,
2610 const Teuchos::RCP<MultiVector> &Nullspace11,
2611 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2612 const Teuchos::RCP<MultiVector> &Material,
2613 Teuchos::ParameterList &List) {
2615 D0_Matrix, Teuchos::null, D0_Matrix,
2616 Ms_Matrix, Teuchos::null,
2617 M1_Matrix, Teuchos::null,
2618 M0inv_Matrix, Teuchos::null,
2619 Nullspace11, Teuchos::null,
2621 Teuchos::null, Material,
2625template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2628 const Teuchos::RCP<Matrix> &Dk_1,
2629 const Teuchos::RCP<Matrix> &Dk_2,
2630 const Teuchos::RCP<Matrix> &D0,
2631 const Teuchos::RCP<Matrix> &M1_beta,
2632 const Teuchos::RCP<Matrix> &M1_alpha,
2633 const Teuchos::RCP<Matrix> &Mk_one,
2634 const Teuchos::RCP<Matrix> &Mk_1_one,
2635 const Teuchos::RCP<Matrix> &invMk_1_invBeta,
2636 const Teuchos::RCP<Matrix> &invMk_2_invAlpha,
2637 const Teuchos::RCP<MultiVector> &Nullspace11,
2638 const Teuchos::RCP<MultiVector> &Nullspace22,
2639 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2640 const Teuchos::RCP<MultiVector> &Material_beta,
2641 const Teuchos::RCP<MultiVector> &Material_alpha,
2642 Teuchos::ParameterList &List) {
2644 if (spaceNumber_ == 1)
2645 solverName_ =
"RefMaxwell";
2646 else if (spaceNumber_ == 2)
2647 solverName_ =
"RefDarcy";
2649 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
2650 "spaceNumber needs to be 1 (HCurl) or 2 (HDiv)");
2651 HierarchyCoarse11_ = Teuchos::null;
2652 Hierarchy22_ = Teuchos::null;
2653 PreSmoother11_ = Teuchos::null;
2654 PostSmoother11_ = Teuchos::null;
2655 disable_addon_ =
false;
2656 disable_addon_22_ =
true;
2660 setParameters(List);
2663 TEUCHOS_ASSERT((k == 1) || (k == 2));
2665 TEUCHOS_ASSERT(Dk_1 != Teuchos::null);
2667 TEUCHOS_ASSERT(D0 != Teuchos::null);
2670 TEUCHOS_ASSERT(M1_beta != Teuchos::null);
2673 TEUCHOS_ASSERT(M1_alpha != Teuchos::null);
2675 if (!disable_addon_) {
2677 TEUCHOS_ASSERT(Mk_one != Teuchos::null);
2678 TEUCHOS_ASSERT(invMk_1_invBeta != Teuchos::null);
2681 if ((k >= 2) && !disable_addon_22_) {
2683 TEUCHOS_ASSERT(Dk_2 != Teuchos::null);
2684 TEUCHOS_ASSERT(Mk_1_one != Teuchos::null);
2685 TEUCHOS_ASSERT(invMk_2_invAlpha != Teuchos::null);
2688#ifdef HAVE_MUELU_DEBUG
2690 TEUCHOS_ASSERT(D0->getRangeMap()->isSameAs(*D0->getRowMap()));
2693 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRangeMap()));
2694 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRowMap()));
2697 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*D0->getRangeMap()));
2701 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRangeMap()));
2702 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRowMap()));
2705 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*D0->getRangeMap()))
2708 if (!disable_addon_) {
2710 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRangeMap()));
2711 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRowMap()));
2714 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2717 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRangeMap()));
2718 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRowMap()));
2721 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2724 if ((k >= 2) && !disable_addon_22_) {
2726 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRangeMap()));
2727 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRowMap()));
2730 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2733 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_2->getRangeMap()));
2736 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRangeMap()));
2737 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRowMap()));
2740 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*Dk_2->getDomainMap()));
2745 if (Dk_1->getRowMap()->lib() == Xpetra::UseTpetra) {
2750 RCP<Matrix> Dk_1copy = MatrixFactory::Build(Dk_1->getRowMap(), Dk_1->getColMap(), 0);
2751 RCP<CrsMatrix> Dk_1copyCrs = toCrsMatrix(Dk_1copy);
2752 ArrayRCP<const size_t> Dk_1rowptr_RCP;
2753 ArrayRCP<const LO> Dk_1colind_RCP;
2754 ArrayRCP<const SC> Dk_1vals_RCP;
2755 toCrsMatrix(Dk_1)->getAllValues(Dk_1rowptr_RCP, Dk_1colind_RCP, Dk_1vals_RCP);
2757 ArrayRCP<size_t> Dk_1copyrowptr_RCP;
2758 ArrayRCP<LO> Dk_1copycolind_RCP;
2759 ArrayRCP<SC> Dk_1copyvals_RCP;
2760 Dk_1copyCrs->allocateAllValues(Dk_1vals_RCP.size(), Dk_1copyrowptr_RCP, Dk_1copycolind_RCP, Dk_1copyvals_RCP);
2761 Dk_1copyrowptr_RCP.deepCopy(Dk_1rowptr_RCP());
2762 Dk_1copycolind_RCP.deepCopy(Dk_1colind_RCP());
2763 Dk_1copyvals_RCP.deepCopy(Dk_1vals_RCP());
2764 Dk_1copyCrs->setAllValues(Dk_1copyrowptr_RCP,
2767 Dk_1copyCrs->expertStaticFillComplete(Dk_1->getDomainMap(), Dk_1->getRangeMap(),
2768 toCrsMatrix(Dk_1)->getCrsGraph()->getImporter(),
2769 toCrsMatrix(Dk_1)->getCrsGraph()->getExporter());
2772 Dk_1_ = MatrixFactory::BuildCopy(Dk_1);
2774 if ((!Dk_2.is_null()) && (Dk_2->getRowMap()->lib() == Xpetra::UseTpetra)) {
2779 RCP<Matrix> Dk_2copy = MatrixFactory::Build(Dk_2->getRowMap(), Dk_2->getColMap(), 0);
2780 RCP<CrsMatrix> Dk_2copyCrs = toCrsMatrix(Dk_2copy);
2781 ArrayRCP<const size_t> Dk_2rowptr_RCP;
2782 ArrayRCP<const LO> Dk_2colind_RCP;
2783 ArrayRCP<const SC> Dk_2vals_RCP;
2784 toCrsMatrix(Dk_2)->getAllValues(Dk_2rowptr_RCP, Dk_2colind_RCP, Dk_2vals_RCP);
2786 ArrayRCP<size_t> Dk_2copyrowptr_RCP;
2787 ArrayRCP<LO> Dk_2copycolind_RCP;
2788 ArrayRCP<SC> Dk_2copyvals_RCP;
2789 Dk_2copyCrs->allocateAllValues(Dk_2vals_RCP.size(), Dk_2copyrowptr_RCP, Dk_2copycolind_RCP, Dk_2copyvals_RCP);
2790 Dk_2copyrowptr_RCP.deepCopy(Dk_2rowptr_RCP());
2791 Dk_2copycolind_RCP.deepCopy(Dk_2colind_RCP());
2792 Dk_2copyvals_RCP.deepCopy(Dk_2vals_RCP());
2793 Dk_2copyCrs->setAllValues(Dk_2copyrowptr_RCP,
2796 Dk_2copyCrs->expertStaticFillComplete(Dk_2->getDomainMap(), Dk_2->getRangeMap(),
2797 toCrsMatrix(Dk_2)->getCrsGraph()->getImporter(),
2798 toCrsMatrix(Dk_2)->getCrsGraph()->getExporter());
2800 }
else if (!Dk_2.is_null())
2801 Dk_2_ = MatrixFactory::BuildCopy(Dk_2);
2804 M1_alpha_ = M1_alpha;
2806 Material_beta_ = Material_beta;
2807 Material_alpha_ = Material_alpha;
2810 Mk_1_one_ = Mk_1_one;
2812 invMk_1_invBeta_ = invMk_1_invBeta;
2813 invMk_2_invAlpha_ = invMk_2_invAlpha;
2815 NodalCoords_ = NodalCoords;
2816 Nullspace11_ = Nullspace11;
2817 Nullspace22_ = Nullspace22;
2820 dump(Dk_1_,
"Dk_1_clean.m");
2821 dump(Dk_2_,
"Dk_2_clean.m");
2823 dump(M1_beta_,
"M1_beta.m");
2824 dump(M1_alpha_,
"M1_alpha.m");
2826 dump(Mk_one_,
"Mk_one.m");
2827 dump(Mk_1_one_,
"Mk_1_one.m");
2829 dump(invMk_1_invBeta_,
"invMk_1_invBeta.m");
2830 dump(invMk_2_invAlpha_,
"invMk_2_invAlpha.m");
2832 dumpCoords(NodalCoords_,
"coords.m");
2835template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2837 describe(Teuchos::FancyOStream &out,
const Teuchos::EVerbosityLevel )
const {
2838 std::ostringstream oss;
2840 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->
getDomainMap()->getComm();
2844 if (!coarseA11_.is_null())
2845 root = comm->getRank();
2850 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
2854 oss <<
"\n--------------------------------------------------------------------------------\n"
2855 <<
"--- " + solverName_ +
2857 "--------------------------------------------------------------------------------"
2864 SM_Matrix_->getRowMap()->getComm()->barrier();
2866 numRows = SM_Matrix_->getGlobalNumRows();
2867 nnz = SM_Matrix_->getGlobalNumEntries();
2869 Xpetra::global_size_t tt = numRows;
2882 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
2883 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2885 if (!A22_.is_null()) {
2886 numRows = A22_->getGlobalNumRows();
2887 nnz = A22_->getGlobalNumEntries();
2889 oss <<
"(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2895 if (PreSmoother11_ != null && PreSmoother11_ == PostSmoother11_)
2896 oss <<
"Smoother 11 both : " << PreSmoother11_->description() << std::endl;
2898 oss <<
"Smoother 11 pre : "
2899 << (PreSmoother11_ != null ? PreSmoother11_->description() :
"no smoother") << std::endl;
2900 oss <<
"Smoother 11 post : "
2901 << (PostSmoother11_ != null ? PostSmoother11_->description() :
"no smoother") << std::endl;
2906 std::string outstr = oss.str();
2909 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2910 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
2912 int strLength = outstr.size();
2913 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
2914 if (comm->getRank() != root)
2915 outstr.resize(strLength);
2916 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
2921 if (!HierarchyCoarse11_.is_null())
2922 HierarchyCoarse11_->describe(out, GetVerbLevel());
2924 if (!Hierarchy22_.is_null())
2925 Hierarchy22_->describe(out, GetVerbLevel());
2929 std::ostringstream oss2;
2931 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
2932 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;
2934 int numProcs = comm->getSize();
2936 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2937 TEUCHOS_TEST_FOR_EXCEPTION(tmpic == Teuchos::null,
Exceptions::RuntimeError,
"Cannot cast base Teuchos::Comm to Teuchos::MpiComm object.");
2938 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
2942 if (!coarseA11_.is_null())
2944 if (!A22_.is_null())
2946 std::vector<char> states(numProcs, 0);
2948 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
2950 states.push_back(status);
2953 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
2954 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
2955 for (
int j = 0; j < rowWidth; j++)
2956 if (proc + j < numProcs)
2957 if (states[proc + j] == 0)
2959 else if (states[proc + j] == 1)
2961 else if (states[proc + j] == 2)
2968 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
2977#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,...