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"
62#include "cuda_profiler_api.h"
66#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
73T
pop(Teuchos::ParameterList &pl, std::string
const &name_in) {
74 T result = pl.get<T>(name_in);
75 pl.remove(name_in,
true);
80T
pop(Teuchos::ParameterList &pl, std::string
const &name_in, T def_value) {
81 T result = pl.get<T>(name_in, def_value);
82 pl.remove(name_in,
false);
86template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
88 return SM_Matrix_->getDomainMap();
91template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
93 return SM_Matrix_->getRangeMap();
96template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97Teuchos::RCP<Teuchos::ParameterList>
100 bool useKokkosDefault = !Node::is_serial;
102 RCP<ParameterList> params = rcp(
new ParameterList(
"RefMaxwell"));
104 params->set<RCP<Matrix>>(
"Dk_1", Teuchos::null);
105 params->set<RCP<Matrix>>(
"Dk_2", Teuchos::null);
106 params->set<RCP<Matrix>>(
"D0", Teuchos::null);
108 params->set<RCP<Matrix>>(
"M1_beta", Teuchos::null);
109 params->set<RCP<Matrix>>(
"M1_alpha", Teuchos::null);
111 params->set<RCP<Matrix>>(
"Ms", Teuchos::null);
113 params->set<RCP<Matrix>>(
"Mk_one", Teuchos::null);
114 params->set<RCP<Matrix>>(
"Mk_1_one", Teuchos::null);
116 params->set<RCP<Matrix>>(
"M1", Teuchos::null);
118 params->set<RCP<Matrix>>(
"invMk_1_invBeta", Teuchos::null);
119 params->set<RCP<Matrix>>(
"invMk_2_invAlpha", Teuchos::null);
121 params->set<RCP<Matrix>>(
"M0inv", Teuchos::null);
123 params->set<RCP<MultiVector>>(
"Nullspace", Teuchos::null);
124 params->set<RCP<RealValuedMultiVector>>(
"Coordinates", Teuchos::null);
126 auto spaceValidator = rcp(
new Teuchos::EnhancedNumberValidator<int>(1, 2));
127 params->set(
"refmaxwell: space number", 1,
"", spaceValidator);
128 params->set(
"verbosity", MasterList::getDefault<std::string>(
"verbosity"));
129 params->set(
"use kokkos refactor", useKokkosDefault);
130 params->set(
"half precision",
false);
131 params->set(
"parameterlist: syntax", MasterList::getDefault<std::string>(
"parameterlist: syntax"));
132 params->set(
"output filename", MasterList::getDefault<std::string>(
"output filename"));
133 params->set(
"print initial parameters", MasterList::getDefault<bool>(
"print initial parameters"));
134 params->set(
"refmaxwell: disable addon", MasterList::getDefault<bool>(
"refmaxwell: disable addon"));
135 params->set(
"refmaxwell: disable addon 22",
true);
136 params->set(
"refmaxwell: mode", MasterList::getDefault<std::string>(
"refmaxwell: mode"));
137 params->set(
"refmaxwell: use as preconditioner", MasterList::getDefault<bool>(
"refmaxwell: use as preconditioner"));
138 params->set(
"refmaxwell: dump matrices", MasterList::getDefault<bool>(
"refmaxwell: dump matrices"));
139 params->set(
"refmaxwell: enable reuse", MasterList::getDefault<bool>(
"refmaxwell: enable reuse"));
140 params->set(
"refmaxwell: skip first (1,1) level", MasterList::getDefault<bool>(
"refmaxwell: skip first (1,1) level"));
141 params->set(
"refmaxwell: skip first (2,2) level",
false);
142 params->set(
"multigrid algorithm",
"Unsmoothed");
143 params->set(
"transpose: use implicit", MasterList::getDefault<bool>(
"transpose: use implicit"));
144 params->set(
"rap: triple product", MasterList::getDefault<bool>(
"rap: triple product"));
145 params->set(
"rap: fix zero diagonals",
true);
146 params->set(
"rap: fix zero diagonals threshold", MasterList::getDefault<double>(
"rap: fix zero diagonals threshold"));
147 params->set(
"fuse prolongation and update", MasterList::getDefault<bool>(
"fuse prolongation and update"));
148 params->set(
"refmaxwell: async transfers", Node::is_gpu);
149 params->set(
"refmaxwell: subsolves on subcommunicators", MasterList::getDefault<bool>(
"refmaxwell: subsolves on subcommunicators"));
150 params->set(
"refmaxwell: subsolves striding", 1);
151 params->set(
"refmaxwell: row sum drop tol (1,1)", MasterList::getDefault<double>(
"aggregation: row sum drop tol"));
152 params->set(
"sync timers",
false);
153 params->set(
"refmaxwell: num iters coarse 11", 1);
154 params->set(
"refmaxwell: num iters 22", 1);
155 params->set(
"refmaxwell: apply BCs to Anodal",
false);
156 params->set(
"refmaxwell: apply BCs to coarse 11",
true);
157 params->set(
"refmaxwell: apply BCs to 22",
true);
158 params->set(
"refmaxwell: max coarse size", 1);
160 ParameterList &precList11 = params->sublist(
"refmaxwell: 11list");
161 precList11.disableRecursiveValidation();
162 ParameterList &precList22 = params->sublist(
"refmaxwell: 22list");
163 precList22.disableRecursiveValidation();
165 params->set(
"smoother: type",
"CHEBYSHEV");
166 ParameterList &smootherList = params->sublist(
"smoother: params");
167 smootherList.disableRecursiveValidation();
168 params->set(
"smoother: pre type",
"NONE");
169 ParameterList &preSmootherList = params->sublist(
"smoother: pre params");
170 preSmootherList.disableRecursiveValidation();
171 params->set(
"smoother: post type",
"NONE");
172 ParameterList &postSmootherList = params->sublist(
"smoother: post params");
173 postSmootherList.disableRecursiveValidation();
175 ParameterList &matvecParams = params->sublist(
"matvec params");
176 matvecParams.disableRecursiveValidation();
178 ParameterList &importerCoarse11Params = params->sublist(
"refmaxwell: ImporterCoarse11 params");
179 importerCoarse11Params.disableRecursiveValidation();
181 ParameterList &importer22Params = params->sublist(
"refmaxwell: Importer22 params");
182 importer22Params.disableRecursiveValidation();
184 params->set(
"multigrid algorithm",
"unsmoothed");
185 params->set(
"aggregation: type", MasterList::getDefault<std::string>(
"aggregation: type"));
186 params->set(
"aggregation: drop tol", MasterList::getDefault<double>(
"aggregation: drop tol"));
187 params->set(
"aggregation: drop scheme", MasterList::getDefault<std::string>(
"aggregation: drop scheme"));
188 params->set(
"aggregation: distance laplacian algo", MasterList::getDefault<std::string>(
"aggregation: distance laplacian algo"));
189 params->set(
"aggregation: min agg size", MasterList::getDefault<int>(
"aggregation: min agg size"));
190 params->set(
"aggregation: max agg size", MasterList::getDefault<int>(
"aggregation: max agg size"));
191 params->set(
"aggregation: match ML phase1", MasterList::getDefault<bool>(
"aggregation: match ML phase1"));
192 params->set(
"aggregation: match ML phase2a", MasterList::getDefault<bool>(
"aggregation: match ML phase2a"));
193 params->set(
"aggregation: match ML phase2b", MasterList::getDefault<bool>(
"aggregation: match ML phase2b"));
194 params->set(
"aggregation: export visualization data", MasterList::getDefault<bool>(
"aggregation: export visualization data"));
199template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
201 if (list.isType<std::string>(
"parameterlist: syntax") && list.get<std::string>(
"parameterlist: syntax") ==
"ml") {
202 Teuchos::ParameterList newList;
205 RCP<Teuchos::ParameterList> validateParameters = getValidParamterList();
206 for (
auto it = newList2.begin(); it != newList2.end(); ++it) {
207 const std::string &entry_name = it->first;
208 if (validateParameters->isParameter(entry_name)) {
209 ParameterEntry theEntry = newList2.getEntry(entry_name);
210 newList.setEntry(entry_name, theEntry);
215 if (list.isSublist(
"refmaxwell: 11list") && list.sublist(
"refmaxwell: 11list").isSublist(
"edge matrix free: coarse"))
217 if (list.isSublist(
"refmaxwell: 22list"))
222 parameterList_ = list;
223 parameterList_.validateParametersAndSetDefaults(*getValidParamterList());
224 std::string verbosityLevel = parameterList_.get<std::string>(
"verbosity");
226 std::string outputFilename = parameterList_.get<std::string>(
"output filename");
227 if (outputFilename !=
"")
229 if (parameterList_.isType<Teuchos::RCP<Teuchos::FancyOStream>>(
"output stream"))
232 if (parameterList_.get<
bool>(
"print initial parameters"))
233 GetOStream(
static_cast<MsgType>(
Runtime1), 0) << parameterList_ << std::endl;
234 disable_addon_ = parameterList_.get<
bool>(
"refmaxwell: disable addon");
235 disable_addon_22_ = parameterList_.get<
bool>(
"refmaxwell: disable addon 22");
236 mode_ = parameterList_.get<std::string>(
"refmaxwell: mode");
237 use_as_preconditioner_ = parameterList_.get<
bool>(
"refmaxwell: use as preconditioner");
238 dump_matrices_ = parameterList_.get<
bool>(
"refmaxwell: dump matrices");
239 enable_reuse_ = parameterList_.get<
bool>(
"refmaxwell: enable reuse");
240 implicitTranspose_ = parameterList_.get<
bool>(
"transpose: use implicit");
241 fuseProlongationAndUpdate_ = parameterList_.get<
bool>(
"fuse prolongation and update");
242 skipFirst11Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (1,1) level");
243 skipFirst22Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (2,2) level");
244 if (spaceNumber_ == 1)
245 skipFirst22Level_ =
false;
246 syncTimers_ = parameterList_.get<
bool>(
"sync timers");
247 useKokkos_ = parameterList_.get<
bool>(
"use kokkos refactor");
248 numItersCoarse11_ = parameterList_.get<
int>(
"refmaxwell: num iters coarse 11");
249 numIters22_ = parameterList_.get<
int>(
"refmaxwell: num iters 22");
250 applyBCsToAnodal_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to Anodal");
251 applyBCsToCoarse11_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to coarse 11");
252 applyBCsTo22_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to 22");
254 precList11_ = parameterList_.sublist(
"refmaxwell: 11list");
255 if (!precList11_.isType<std::string>(
"Preconditioner Type") &&
256 !precList11_.isType<std::string>(
"smoother: type") &&
257 !precList11_.isType<std::string>(
"smoother: pre type") &&
258 !precList11_.isType<std::string>(
"smoother: post type")) {
259 precList11_.set(
"smoother: type",
"CHEBYSHEV");
260 precList11_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
261 precList11_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 5.4);
262 precList11_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
265 precList22_ = parameterList_.sublist(
"refmaxwell: 22list");
266 if (!precList22_.isType<std::string>(
"Preconditioner Type") &&
267 !precList22_.isType<std::string>(
"smoother: type") &&
268 !precList22_.isType<std::string>(
"smoother: pre type") &&
269 !precList22_.isType<std::string>(
"smoother: post type")) {
270 precList22_.set(
"smoother: type",
"CHEBYSHEV");
271 precList22_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
272 precList22_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 7.0);
273 precList22_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
276 if (!parameterList_.isType<std::string>(
"smoother: type") && !parameterList_.isType<std::string>(
"smoother: pre type") && !parameterList_.isType<std::string>(
"smoother: post type")) {
277 list.set(
"smoother: type",
"CHEBYSHEV");
278 list.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
279 list.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 20.0);
280 list.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
284 !precList11_.isType<std::string>(
"Preconditioner Type") &&
285 !precList11_.isParameter(
"reuse: type"))
286 precList11_.set(
"reuse: type",
"full");
288 !precList22_.isType<std::string>(
"Preconditioner Type") &&
289 !precList22_.isParameter(
"reuse: type"))
290 precList22_.set(
"reuse: type",
"full");
293template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
295 using memory_space =
typename Node::device_type::memory_space;
297#ifdef HAVE_MUELU_CUDA
298 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStart();
301 std::string timerLabel;
303 timerLabel =
"compute (reuse)";
305 timerLabel =
"compute";
306 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
316 RCP<ParameterList> params = rcp(
new ParameterList());
317 params->set(
"printLoadBalancingInfo",
true);
318 params->set(
"printCommInfo",
true);
325 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
327 BCrows11_, BCcols22_, BCdomain22_,
328 globalNumberBoundaryUnknowns11_,
329 globalNumberBoundaryUnknowns22_,
330 onlyBoundary11_, onlyBoundary22_);
331 if (spaceNumber_ == 2) {
332 Kokkos::View<bool *, memory_space> BCcolsEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), Dk_1_->getColMap()->getLocalNumElements());
333 Kokkos::View<bool *, memory_space> BCdomainEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), Dk_1_->getDomainMap()->getLocalNumElements());
336 Kokkos::View<bool *, memory_space> BCcolsNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), D0_->getColMap()->getLocalNumElements());
337 Kokkos::View<bool *, memory_space> BCdomainNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), D0_->getDomainMap()->getLocalNumElements());
339 BCdomain22_ = BCdomainNode;
342 GetOStream(
Statistics2) << solverName_ +
"::compute(): Detected " << globalNumberBoundaryUnknowns11_ <<
" BC rows and " << globalNumberBoundaryUnknowns22_ <<
" BC columns." << std::endl;
344 dump(BCrows11_,
"BCrows11.m");
345 dump(BCcols22_,
"BCcols22.m");
346 dump(BCdomain22_,
"BCdomain22.m");
349 if (onlyBoundary11_) {
352 GetOStream(
Warnings0) <<
"All unknowns of the (1,1) block have been detected as boundary unknowns!" << std::endl;
354 setFineLevelSmoother11();
360 dim_ = NodalCoords_->getNumVectors();
367 if (Nullspace11_ != null) {
368 TEUCHOS_ASSERT(Nullspace11_->getMap()->isCompatible(*(SM_Matrix_->getRowMap())));
369 }
else if (NodalCoords_ != null) {
370 Nullspace11_ = buildNullspace(spaceNumber_, BCrows11_, skipFirst11Level_);
372 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
377 RCP<Matrix> A11_nodal;
378 if (skipFirst11Level_) {
380 std::string label(
"D0^T*M1_beta*D0");
383 if (applyBCsToAnodal_) {
387 A11_nodal->setObjectLabel(solverName_ +
" (1,1) A_nodal");
388 dump(A11_nodal,
"A11_nodal.m");
391 M1_beta_ = Teuchos::null;
394 buildProlongator(spaceNumber_, A11_nodal, Nullspace11_, P11_, NullspaceCoarse11_, CoordsCoarse11_);
401 if (Nullspace22_ != null) {
402 TEUCHOS_ASSERT(Nullspace22_->getMap()->isCompatible(*(Dk_1_->getDomainMap())));
403 }
else if (NodalCoords_ != null)
404 Nullspace22_ = buildNullspace(spaceNumber_ - 1, BCdomain22_, skipFirst22Level_);
406 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
411 RCP<Matrix> A22_nodal;
412 if (skipFirst22Level_) {
414 std::string label(
"D0^T*M1_alpha*D0");
417 if (applyBCsToAnodal_) {
421 A22_nodal->setObjectLabel(solverName_ +
" (2,2) A_nodal");
422 dump(A22_nodal,
"A22_nodal.m");
425 M1_alpha_ = Teuchos::null;
428 buildProlongator(spaceNumber_ - 1, A22_nodal, Nullspace22_, P22_, CoarseNullspace22_, Coords22_);
436 buildCoarse11Matrix();
441 int rebalanceStriding, numProcsCoarseA11, numProcsA22;
443 this->determineSubHierarchyCommSizes(doRebalancing, rebalanceStriding, numProcsCoarseA11, numProcsA22);
445 doRebalancing =
false;
448 if (!reuse && doRebalancing)
449 rebalanceCoarse11Matrix(rebalanceStriding, numProcsCoarseA11);
450 if (!coarseA11_.is_null()) {
451 dump(coarseA11_,
"coarseA11.m");
453 dumpCoords(CoordsCoarse11_,
"CoordsCoarse11.m");
454 dump(NullspaceCoarse11_,
"NullspaceCoarse11.m");
459 if (!implicitTranspose_) {
466 if (!coarseA11_.is_null()) {
468 std::string label(
"coarseA11");
469 setupSubSolve(HierarchyCoarse11_, thyraPrecOpH_, coarseA11_, NullspaceCoarse11_, CoordsCoarse11_, Material_beta_, precList11_, label, reuse);
475 if (!reuse && applyBCsTo22_) {
476 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC columns of Dk_1" << std::endl;
479 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
481 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
486 if (!onlyBoundary22_) {
487 GetOStream(
Runtime0) << solverName_ +
"::compute(): building MG for (2,2)-block" << std::endl;
490 build22Matrix(reuse, doRebalancing, rebalanceStriding, numProcsA22);
492 if (!P22_.is_null()) {
493 std::string label(
"P22^T*A22*P22");
495 coarseA22_->SetFixedBlockSize(A22_->GetFixedBlockSize());
496 coarseA22_->setObjectLabel(solverName_ +
" coarse (2, 2)");
497 dump(coarseA22_,
"coarseA22.m");
500 if (!reuse && !implicitTranspose_) {
506 if (!A22_.is_null()) {
508 std::string label(
"A22");
509 if (!P22_.is_null()) {
510 precList22_.sublist(
"level 1 user data").set(
"A", coarseA22_);
511 precList22_.sublist(
"level 1 user data").set(
"P", P22_);
512 if (!implicitTranspose_)
513 precList22_.sublist(
"level 1 user data").set(
"R", R22_);
514 precList22_.sublist(
"level 1 user data").set(
"Nullspace", CoarseNullspace22_);
515 precList22_.sublist(
"level 1 user data").set(
"Coordinates", Coords22_);
518 int maxCoarseSize = precList22_.get(
"coarse: max size", MasterList::getDefault<int>(
"coarse: max size"));
519 int numRows = Teuchos::as<int>(coarseA22_->getGlobalNumRows());
520 if (maxCoarseSize > numRows)
521 precList22_.set(
"coarse: max size", numRows);
522 int maxLevels = precList22_.get(
"max levels", MasterList::getDefault<int>(
"max levels"));
524 precList22_.set(
"max levels", 2);
525 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, Teuchos::null, Teuchos::null, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
527 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, CoarseNullspace22_, Coords22_, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
535 if (!reuse && !onlyBoundary22_ && applyBCsTo22_) {
536 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC rows of Dk_1" << std::endl;
539 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
541 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
542 dump(Dk_1_,
"Dk_1_nuked.m");
547 setFineLevelSmoother11();
550 if (!ImporterCoarse11_.is_null()) {
551 RCP<const Import> ImporterP11 = ImportFactory::Build(ImporterCoarse11_->getTargetMap(), P11_->getColMap());
552 toCrsMatrix(P11_)->replaceDomainMapAndImporter(ImporterCoarse11_->getTargetMap(), ImporterP11);
555 if (!Importer22_.is_null()) {
557 DorigDomainMap_ = Dk_1_->getDomainMap();
558 DorigImporter_ = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
560 RCP<const Import> ImporterD = ImportFactory::Build(Importer22_->getTargetMap(), Dk_1_->getColMap());
561 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), ImporterD);
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());
572 Dk_1_T_R11_colMapsMatch_ =
false;
573 if (Dk_1_T_R11_colMapsMatch_)
574 GetOStream(
Runtime0) << solverName_ +
"::compute(): Dk_1_T and R11 have matching colMaps" << std::endl;
576 asyncTransfers_ = parameterList_.get<
bool>(
"refmaxwell: async transfers");
582 if (parameterList_.isSublist(
"matvec params")) {
583 RCP<ParameterList> matvecParams = rcpFromRef(parameterList_.sublist(
"matvec params"));
589 if (!ImporterCoarse11_.is_null()) ImporterCoarse11_->setDistributorParameters(matvecParams);
590 if (!Importer22_.is_null()) Importer22_->setDistributorParameters(matvecParams);
592 if (!ImporterCoarse11_.is_null() && parameterList_.isSublist(
"refmaxwell: ImporterCoarse11 params")) {
593 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: ImporterCoarse11 params"));
594 ImporterCoarse11_->setDistributorParameters(importerParams);
596 if (!Importer22_.is_null() && parameterList_.isSublist(
"refmaxwell: Importer22 params")) {
597 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: Importer22 params"));
598 Importer22_->setDistributorParameters(importerParams);
604#ifdef HAVE_MUELU_CUDA
605 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStop();
609template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
612 doRebalancing = parameterList_.get<
bool>(
"refmaxwell: subsolves on subcommunicators");
613 rebalanceStriding = parameterList_.get<
int>(
"refmaxwell: subsolves striding", -1);
614 int numProcs = SM_Matrix_->getDomainMap()->getComm()->getSize();
616 doRebalancing =
false;
628 level.
Set(
"A", coarseA11_);
631 ParameterList repartheurParams;
632 repartheurParams.set(
"repartition: start level", 0);
634 int defaultTargetRows = 10000;
635 repartheurParams.set(
"repartition: min rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
636 repartheurParams.set(
"repartition: target rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
637 repartheurParams.set(
"repartition: min rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
638 repartheurParams.set(
"repartition: target rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
639 repartheurParams.set(
"repartition: max imbalance", precList11_.get<
double>(
"repartition: max imbalance", 1.1));
640 repartheurFactory->SetParameterList(repartheurParams);
642 level.
Request(
"number of partitions", repartheurFactory.get());
643 repartheurFactory->Build(level);
644 numProcsCoarseA11 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
645 numProcsCoarseA11 = std::min(numProcsCoarseA11, numProcs);
655 level.
Set(
"Map", Dk_1_->getDomainMap());
658 ParameterList repartheurParams;
659 repartheurParams.set(
"repartition: start level", 0);
660 repartheurParams.set(
"repartition: use map",
true);
662 int defaultTargetRows = 10000;
663 repartheurParams.set(
"repartition: min rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
664 repartheurParams.set(
"repartition: target rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
665 repartheurParams.set(
"repartition: min rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
666 repartheurParams.set(
"repartition: target rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
668 repartheurFactory->SetParameterList(repartheurParams);
670 level.
Request(
"number of partitions", repartheurFactory.get());
671 repartheurFactory->Build(level);
672 numProcsA22 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
673 numProcsA22 = std::min(numProcsA22, numProcs);
676 if (rebalanceStriding >= 1) {
677 TEUCHOS_ASSERT(rebalanceStriding * numProcsCoarseA11 <= numProcs);
678 TEUCHOS_ASSERT(rebalanceStriding * numProcsA22 <= numProcs);
679 if (rebalanceStriding * (numProcsCoarseA11 + numProcsA22) > numProcs) {
680 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling striding = " << rebalanceStriding <<
", since coarseA11 needs " << numProcsCoarseA11
681 <<
" procs and A22 needs " << numProcsA22 <<
" procs." << std::endl;
682 rebalanceStriding = -1;
684 int lclBadMatrixDistribution = (coarseA11_->getLocalNumEntries() == 0) || (Dk_1_->getDomainMap()->getLocalNumElements() == 0);
685 int gblBadMatrixDistribution =
false;
686 MueLu_maxAll(SM_Matrix_->getDomainMap()->getComm(), lclBadMatrixDistribution, gblBadMatrixDistribution);
687 if (gblBadMatrixDistribution) {
688 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;
689 rebalanceStriding = -1;
693 if ((numProcsCoarseA11 < 0) || (numProcsA22 < 0) || (numProcsCoarseA11 + numProcsA22 > numProcs)) {
694 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling rebalancing of subsolves, since partition heuristic resulted "
695 <<
"in undesirable number of partitions: " << numProcsCoarseA11 <<
", " << numProcsA22 << std::endl;
696 doRebalancing =
false;
700 doRebalancing =
false;
704template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
707 if (spaceNumber == 0)
708 return Teuchos::null;
710 std::string timerLabel;
711 if (spaceNumber == spaceNumber_) {
712 if (skipFirst11Level_)
713 timerLabel =
"Build coarse addon matrix 11";
715 timerLabel =
"Build addon matrix 11";
717 timerLabel =
"Build addon matrix 22";
719 RCP<Teuchos::TimeMonitor> tmAddon = getTimer(timerLabel);
723 RCP<Matrix> lumpedInverse;
724 if (spaceNumber == spaceNumber_) {
726 TEUCHOS_TEST_FOR_EXCEPTION(invMk_1_invBeta_ == Teuchos::null, std::invalid_argument,
728 "::buildCoarse11Matrix(): Inverse of "
729 "lumped mass matrix required for add-on (i.e. invMk_1_invBeta_ is null)");
730 lumpedInverse = invMk_1_invBeta_;
732 if (skipFirst11Level_) {
735 Zaux = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Mk_one_,
false, *P11_,
false, Zaux, GetOStream(
Runtime0),
true,
true);
737 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Zaux,
false, Z, GetOStream(
Runtime0),
true,
true);
740 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Mk_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
743 }
else if (spaceNumber == spaceNumber_ - 1) {
745 TEUCHOS_TEST_FOR_EXCEPTION(invMk_2_invAlpha_ == Teuchos::null, std::invalid_argument,
747 "::buildCoarse11Matrix(): Inverse of "
748 "lumped mass matrix required for add-on (i.e. invMk_2_invAlpha_ is null)");
749 lumpedInverse = invMk_2_invAlpha_;
752 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_2_,
true, *Mk_1_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
756 if (lumpedInverse->getGlobalMaxNumRowEntries() <= 1) {
759 RCP<Vector> diag = VectorFactory::Build(lumpedInverse->getRowMap());
760 lumpedInverse->getLocalDiagCopy(*diag);
762 ArrayRCP<Scalar> diagVals = diag->getDataNonConst(0);
763 for (
size_t j = 0; j < diag->getMap()->getLocalNumElements(); j++) {
764 diagVals[j] = Teuchos::ScalarTraits<Scalar>::squareroot(diagVals[j]);
767 if (Z->getRowMap()->isSameAs(*(diag->getMap())))
770 RCP<Import> importer = ImportFactory::Build(diag->getMap(), Z->getRowMap());
771 RCP<Vector> diag2 = VectorFactory::Build(Z->getRowMap());
772 diag2->doImport(*diag, *importer, Xpetra::INSERT);
773 Z->leftScale(*diag2);
775 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *Z,
false, addon, GetOStream(
Runtime0),
true,
true);
776 }
else if (parameterList_.get<
bool>(
"rap: triple product",
false) ==
false) {
779 C2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*lumpedInverse,
false, *Z,
false, C2, GetOStream(
Runtime0),
true,
true);
781 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *C2,
false, addon, GetOStream(
Runtime0),
true,
true);
783 addon = MatrixFactory::Build(Z->getDomainMap());
785 Xpetra::TripleMatrixMultiply<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
786 MultiplyRAP(*Z,
true, *lumpedInverse,
false, *Z,
false, *addon,
true,
true);
791template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
793 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build coarse (1,1) matrix");
795 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
799 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *P11_,
false, temp, GetOStream(
Runtime0),
true,
true);
800 if (ImporterCoarse11_.is_null())
801 coarseA11_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, coarseA11_, GetOStream(
Runtime0),
true,
true);
804 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
806 RCP<const Map> map = ImporterCoarse11_->getTargetMap()->removeEmptyProcesses();
807 temp2->removeEmptyProcessesInPlace(map);
808 if (!temp2.is_null() && temp2->getRowMap().is_null())
809 temp2 = Teuchos::null;
813 if (!disable_addon_) {
816 if (!coarseA11_.is_null() && Addon11_.is_null()) {
817 addon = buildAddon(spaceNumber_);
824 if (!coarseA11_.is_null()) {
826 RCP<Matrix> newCoarseA11;
827 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*coarseA11_,
false, one, *addon,
false, one, newCoarseA11, GetOStream(
Runtime0));
828 newCoarseA11->fillComplete();
829 coarseA11_ = newCoarseA11;
833 if (!coarseA11_.is_null() && !skipFirst11Level_) {
834 ArrayRCP<bool> coarseA11BCrows;
835 coarseA11BCrows.resize(coarseA11_->getRowMap()->getLocalNumElements());
836 for (
size_t i = 0; i < BCdomain22_.size(); i++)
837 for (
size_t k = 0; k < dim_; k++)
838 coarseA11BCrows[i * dim_ + k] = BCdomain22_(i);
839 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
842 if (applyBCsToCoarse11_)
846 if (!coarseA11_.is_null()) {
852 bool fixZeroDiagonal = !applyBCsToAnodal_;
853 if (precList11_.isParameter(
"rap: fix zero diagonals"))
854 fixZeroDiagonal = precList11_.get<
bool>(
"rap: fix zero diagonals");
856 if (fixZeroDiagonal) {
859 if (precList11_.isType<
magnitudeType>(
"rap: fix zero diagonals threshold"))
860 threshold = precList11_.get<
magnitudeType>(
"rap: fix zero diagonals threshold");
861 else if (precList11_.isType<
double>(
"rap: fix zero diagonals threshold"))
862 threshold = Teuchos::as<magnitudeType>(precList11_.get<
double>(
"rap: fix zero diagonals threshold"));
863 if (precList11_.isType<
double>(
"rap: fix zero diagonals replacement"))
864 replacement = Teuchos::as<Scalar>(precList11_.get<
double>(
"rap: fix zero diagonals replacement"));
865 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(coarseA11_,
true, GetOStream(
Warnings1), threshold, replacement);
869 coarseA11_->SetFixedBlockSize(dim_);
870 if (skipFirst11Level_)
871 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
873 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
877template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
882 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Rebalance coarseA11");
884 Level fineLevel, coarseLevel;
890 coarseLevel.
Set(
"A", coarseA11_);
891 coarseLevel.
Set(
"P", P11_);
892 coarseLevel.
Set(
"Coordinates", CoordsCoarse11_);
893 if (!NullspaceCoarse11_.is_null())
894 coarseLevel.
Set(
"Nullspace", NullspaceCoarse11_);
895 coarseLevel.
Set(
"number of partitions", numProcsCoarseA11);
896 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
898 coarseLevel.
setlib(coarseA11_->getDomainMap()->lib());
899 fineLevel.
setlib(coarseA11_->getDomainMap()->lib());
900 coarseLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
901 fineLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
903 std::string partName = precList11_.get<std::string>(
"repartition: partitioner",
"zoltan2");
904 RCP<Factory> partitioner;
905 if (partName ==
"zoltan") {
906#ifdef HAVE_MUELU_ZOLTAN
913 }
else if (partName ==
"zoltan2") {
914#ifdef HAVE_MUELU_ZOLTAN2
916 ParameterList partParams;
917 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList11_.sublist(
"repartition: params",
false)));
918 partParams.set(
"ParameterList", partpartParams);
919 partitioner->SetParameterList(partParams);
927 ParameterList repartParams;
928 repartParams.set(
"repartition: print partition distribution", precList11_.get<
bool>(
"repartition: print partition distribution",
false));
929 repartParams.set(
"repartition: remap parts", precList11_.get<
bool>(
"repartition: remap parts",
true));
930 if (rebalanceStriding >= 1) {
931 bool acceptPart = (SM_Matrix_->getDomainMap()->getComm()->getRank() % rebalanceStriding) == 0;
932 if (SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsCoarseA11 * rebalanceStriding)
934 repartParams.set(
"repartition: remap accept partition", acceptPart);
936 repartFactory->SetParameterList(repartParams);
938 repartFactory->SetFactory(
"Partition", partitioner);
941 ParameterList newPparams;
942 newPparams.set(
"type",
"Interpolation");
943 newPparams.set(
"repartition: rebalance P and R", precList11_.get<
bool>(
"repartition: rebalance P and R",
false));
944 newPparams.set(
"repartition: use subcommunicators",
true);
945 newPparams.set(
"repartition: rebalance Nullspace", !NullspaceCoarse11_.is_null());
947 if (!NullspaceCoarse11_.is_null())
949 newP->SetParameterList(newPparams);
950 newP->SetFactory(
"Importer", repartFactory);
953 ParameterList rebAcParams;
954 rebAcParams.set(
"repartition: use subcommunicators",
true);
955 newA->SetParameterList(rebAcParams);
956 newA->SetFactory(
"Importer", repartFactory);
958 coarseLevel.
Request(
"P", newP.get());
959 coarseLevel.
Request(
"Importer", repartFactory.get());
960 coarseLevel.
Request(
"A", newA.get());
961 coarseLevel.
Request(
"Coordinates", newP.get());
962 if (!NullspaceCoarse11_.is_null())
963 coarseLevel.
Request(
"Nullspace", newP.get());
964 repartFactory->Build(coarseLevel);
966 if (!precList11_.get<
bool>(
"repartition: rebalance P and R",
false))
967 ImporterCoarse11_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
968 P11_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
969 coarseA11_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
970 CoordsCoarse11_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
971 if (!NullspaceCoarse11_.is_null())
972 NullspaceCoarse11_ = coarseLevel.
Get<RCP<MultiVector>>(
"Nullspace", newP.get());
974 if (!coarseA11_.is_null()) {
976 coarseA11_->SetFixedBlockSize(dim_);
977 if (skipFirst11Level_)
978 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
980 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
983 coarseA11_AP_reuse_data_ = Teuchos::null;
984 coarseA11_RAP_reuse_data_ = Teuchos::null;
986 if (!disable_addon_ && enable_reuse_) {
988 RCP<const Import> ImporterCoarse11 = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
989 RCP<const Map> targetMap = ImporterCoarse11->getTargetMap();
990 ParameterList XpetraList;
991 XpetraList.set(
"Restrict Communicator",
true);
992 Addon11_ = MatrixFactory::Build(Addon11_, *ImporterCoarse11, *ImporterCoarse11, targetMap, targetMap, rcp(&XpetraList,
false));
997template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1000 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1002 Level fineLevel, coarseLevel;
1008 fineLevel.
Set(
"A", SM_Matrix_);
1009 coarseLevel.
Set(
"P", Dk_1_);
1010 coarseLevel.
Set(
"Coordinates", Coords22_);
1012 coarseLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1013 fineLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1014 coarseLevel.setObjectLabel(solverName_ +
" (2,2)");
1015 fineLevel.setObjectLabel(solverName_ +
" (2,2)");
1017 RCP<RAPFactory> rapFact = rcp(
new RAPFactory());
1018 ParameterList rapList = *(rapFact->GetValidParameterList());
1019 rapList.set(
"transpose: use implicit",
true);
1020 rapList.set(
"rap: fix zero diagonals", parameterList_.get<
bool>(
"rap: fix zero diagonals",
true));
1021 rapList.set(
"rap: fix zero diagonals threshold", parameterList_.get<
double>(
"rap: fix zero diagonals threshold", Teuchos::ScalarTraits<double>::eps()));
1022 rapList.set(
"rap: triple product", parameterList_.get<
bool>(
"rap: triple product",
false));
1023 rapFact->SetParameterList(rapList);
1025 if (!A22_AP_reuse_data_.is_null()) {
1026 coarseLevel.
AddKeepFlag(
"AP reuse data", rapFact.get());
1027 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"AP reuse data", A22_AP_reuse_data_, rapFact.get());
1029 if (!A22_RAP_reuse_data_.is_null()) {
1030 coarseLevel.
AddKeepFlag(
"RAP reuse data", rapFact.get());
1031 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"RAP reuse data", A22_RAP_reuse_data_, rapFact.get());
1035 if (doRebalancing) {
1036 coarseLevel.
Set(
"number of partitions", numProcsA22);
1037 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
1039 std::string partName = precList22_.get<std::string>(
"repartition: partitioner",
"zoltan2");
1040 RCP<Factory> partitioner;
1041 if (partName ==
"zoltan") {
1042#ifdef HAVE_MUELU_ZOLTAN
1044 partitioner->SetFactory(
"A", rapFact);
1050 }
else if (partName ==
"zoltan2") {
1051#ifdef HAVE_MUELU_ZOLTAN2
1053 ParameterList partParams;
1054 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList22_.sublist(
"repartition: params",
false)));
1055 partParams.set(
"ParameterList", partpartParams);
1056 partitioner->SetParameterList(partParams);
1057 partitioner->SetFactory(
"A", rapFact);
1065 ParameterList repartParams;
1066 repartParams.set(
"repartition: print partition distribution", precList22_.get<
bool>(
"repartition: print partition distribution",
false));
1067 repartParams.set(
"repartition: remap parts", precList22_.get<
bool>(
"repartition: remap parts",
true));
1068 if (rebalanceStriding >= 1) {
1069 bool acceptPart = ((SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank()) % rebalanceStriding) == 0;
1070 if (SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsA22 * rebalanceStriding)
1073 TEUCHOS_ASSERT(coarseA11_.is_null());
1074 repartParams.set(
"repartition: remap accept partition", acceptPart);
1076 repartParams.set(
"repartition: remap accept partition", coarseA11_.is_null());
1077 repartFactory->SetParameterList(repartParams);
1078 repartFactory->SetFactory(
"A", rapFact);
1080 repartFactory->SetFactory(
"Partition", partitioner);
1083 ParameterList newPparams;
1084 newPparams.set(
"type",
"Interpolation");
1085 newPparams.set(
"repartition: rebalance P and R", precList22_.get<
bool>(
"repartition: rebalance P and R",
false));
1086 newPparams.set(
"repartition: use subcommunicators",
true);
1087 newPparams.set(
"repartition: rebalance Nullspace",
false);
1089 newP->SetParameterList(newPparams);
1090 newP->SetFactory(
"Importer", repartFactory);
1093 ParameterList rebAcParams;
1094 rebAcParams.set(
"repartition: use subcommunicators",
true);
1095 newA->SetParameterList(rebAcParams);
1096 newA->SetFactory(
"A", rapFact);
1097 newA->SetFactory(
"Importer", repartFactory);
1099 coarseLevel.
Request(
"P", newP.get());
1100 coarseLevel.
Request(
"Importer", repartFactory.get());
1101 coarseLevel.
Request(
"A", newA.get());
1102 coarseLevel.
Request(
"Coordinates", newP.get());
1103 rapFact->Build(fineLevel, coarseLevel);
1104 repartFactory->Build(coarseLevel);
1106 if (!precList22_.get<
bool>(
"repartition: rebalance P and R",
false))
1107 Importer22_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1108 Dk_1_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1109 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1110 Coords22_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1112 if (!P22_.is_null()) {
1119 coarseLevel.
Request(
"A", rapFact.get());
1120 if (enable_reuse_) {
1121 coarseLevel.
Request(
"AP reuse data", rapFact.get());
1122 coarseLevel.
Request(
"RAP reuse data", rapFact.get());
1125 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", rapFact.get());
1127 if (enable_reuse_) {
1128 if (coarseLevel.
IsAvailable(
"AP reuse data", rapFact.get()))
1129 A22_AP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"AP reuse data", rapFact.get());
1130 if (coarseLevel.
IsAvailable(
"RAP reuse data", rapFact.get()))
1131 A22_RAP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"RAP reuse data", rapFact.get());
1135 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1136 if (Importer22_.is_null()) {
1138 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1139 if (!implicitTranspose_)
1140 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1142 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1145 RCP<const Import> Dimporter = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
1146 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(DorigDomainMap_, DorigImporter_);
1148 RCP<Matrix> temp, temp2;
1149 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1150 if (!implicitTranspose_)
1151 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1153 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1156 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), Dimporter);
1158 ParameterList XpetraList;
1159 XpetraList.set(
"Restrict Communicator",
true);
1160 XpetraList.set(
"Timer Label",
"MueLu::RebalanceA22");
1161 RCP<const Map> targetMap = Importer22_->getTargetMap();
1162 A22_ = MatrixFactory::Build(temp2, *Importer22_, *Importer22_, targetMap, targetMap, rcp(&XpetraList,
false));
1166 if (not A22_.is_null() and not disable_addon_22_ and spaceNumber_ > 1) {
1167 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1169 RCP<Matrix> addon22 = buildAddon(spaceNumber_ - 1);
1173 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A22_,
false, one, *addon22,
false, one, newA22, GetOStream(
Runtime0));
1174 newA22->fillComplete();
1178 if (!A22_.is_null()) {
1179 dump(A22_,
"A22.m");
1180 A22_->setObjectLabel(solverName_ +
" (2,2)");
1182 if (spaceNumber_ - 1 == 0)
1183 A22_->SetFixedBlockSize(1);
1185 A22_->SetFixedBlockSize(dim_);
1189template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1192 RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(
new FactoryManager());
1195 level.setObjectLabel(solverName_ +
" (1,1)");
1196 level.
Set(
"A", SM_Matrix_);
1197 level.
setlib(SM_Matrix_->getDomainMap()->lib());
1199 level.
Set(
"NodeMatrix", A22_);
1200 level.
Set(
"D0", Dk_1_);
1202 if ((parameterList_.get<std::string>(
"smoother: pre type") !=
"NONE") && (parameterList_.get<std::string>(
"smoother: post type") !=
"NONE")) {
1203 std::string preSmootherType = parameterList_.get<std::string>(
"smoother: pre type");
1204 std::string postSmootherType = parameterList_.get<std::string>(
"smoother: post type");
1206 ParameterList preSmootherList, postSmootherList;
1207 if (parameterList_.isSublist(
"smoother: pre params"))
1208 preSmootherList = parameterList_.sublist(
"smoother: pre params");
1209 if (parameterList_.isSublist(
"smoother: post params"))
1210 postSmootherList = parameterList_.sublist(
"smoother: post params");
1212 RCP<SmootherPrototype> preSmootherPrototype = rcp(
new TrilinosSmoother(preSmootherType, preSmootherList));
1213 RCP<SmootherPrototype> postSmootherPrototype = rcp(
new TrilinosSmoother(postSmootherType, postSmootherList));
1214 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(preSmootherPrototype, postSmootherPrototype));
1216 level.
Request(
"PreSmoother", smootherFact.get());
1217 level.
Request(
"PostSmoother", smootherFact.get());
1218 if (enable_reuse_) {
1219 ParameterList smootherFactoryParams;
1220 smootherFactoryParams.set(
"keep smoother data",
true);
1221 smootherFact->SetParameterList(smootherFactoryParams);
1222 level.
Request(
"PreSmoother data", smootherFact.get());
1223 level.
Request(
"PostSmoother data", smootherFact.get());
1224 if (!PreSmootherData11_.is_null())
1225 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1226 if (!PostSmootherData11_.is_null())
1227 level.
Set(
"PostSmoother data", PostSmootherData11_, smootherFact.get());
1229 smootherFact->Build(level);
1230 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1231 PostSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PostSmoother", smootherFact.get());
1232 if (enable_reuse_) {
1233 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1234 PostSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PostSmoother data", smootherFact.get());
1237 std::string smootherType = parameterList_.get<std::string>(
"smoother: type");
1239 ParameterList smootherList;
1240 if (parameterList_.isSublist(
"smoother: params"))
1241 smootherList = parameterList_.sublist(
"smoother: params");
1243 RCP<SmootherPrototype> smootherPrototype = rcp(
new TrilinosSmoother(smootherType, smootherList));
1244 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(smootherPrototype));
1245 level.
Request(
"PreSmoother", smootherFact.get());
1246 if (enable_reuse_) {
1247 ParameterList smootherFactoryParams;
1248 smootherFactoryParams.set(
"keep smoother data",
true);
1249 smootherFact->SetParameterList(smootherFactoryParams);
1250 level.
Request(
"PreSmoother data", smootherFact.get());
1251 if (!PreSmootherData11_.is_null())
1252 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1254 smootherFact->Build(level);
1255 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1256 PostSmoother11_ = PreSmoother11_;
1258 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1262template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1264 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer(
"Allocate MVs");
1267 if (!R11_.is_null())
1268 P11res_ = MultiVectorFactory::Build(R11_->getRangeMap(), numVectors);
1270 P11res_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1271 P11res_->setObjectLabel(
"P11res");
1273 if (Dk_1_T_R11_colMapsMatch_) {
1274 DTR11Tmp_ = MultiVectorFactory::Build(R11_->getColMap(), numVectors);
1275 DTR11Tmp_->setObjectLabel(
"DTR11Tmp");
1277 if (!ImporterCoarse11_.is_null()) {
1278 P11resTmp_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1279 P11resTmp_->setObjectLabel(
"P11resTmp");
1280 P11x_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1282 P11x_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1283 P11x_->setObjectLabel(
"P11x");
1286 if (!Dk_1_T_.is_null())
1287 Dres_ = MultiVectorFactory::Build(Dk_1_T_->getRangeMap(), numVectors);
1289 Dres_ = MultiVectorFactory::Build(Dk_1_->getDomainMap(), numVectors);
1290 Dres_->setObjectLabel(
"Dres");
1292 if (!Importer22_.is_null()) {
1293 DresTmp_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1294 DresTmp_->setObjectLabel(
"DresTmp");
1295 Dx_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1296 }
else if (!onlyBoundary22_)
1297 Dx_ = MultiVectorFactory::Build(A22_->getDomainMap(), numVectors);
1299 Dx_->setObjectLabel(
"Dx");
1301 if (!coarseA11_.is_null()) {
1302 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
1303 P11resSubComm_ = MultiVectorFactory::Build(P11resTmp_, Teuchos::View);
1305 P11resSubComm_ = MultiVectorFactory::Build(P11res_, Teuchos::View);
1306 P11resSubComm_->replaceMap(coarseA11_->getRangeMap());
1307 P11resSubComm_->setObjectLabel(
"P11resSubComm");
1309 P11xSubComm_ = MultiVectorFactory::Build(P11x_, Teuchos::View);
1310 P11xSubComm_->replaceMap(coarseA11_->getDomainMap());
1311 P11xSubComm_->setObjectLabel(
"P11xSubComm");
1314 if (!A22_.is_null()) {
1315 if (!Importer22_.is_null() && !implicitTranspose_)
1316 DresSubComm_ = MultiVectorFactory::Build(DresTmp_, Teuchos::View);
1318 DresSubComm_ = MultiVectorFactory::Build(Dres_, Teuchos::View);
1319 DresSubComm_->replaceMap(A22_->getRangeMap());
1320 DresSubComm_->setObjectLabel(
"DresSubComm");
1322 DxSubComm_ = MultiVectorFactory::Build(Dx_, Teuchos::View);
1323 DxSubComm_->replaceMap(A22_->getDomainMap());
1324 DxSubComm_->setObjectLabel(
"DxSubComm");
1327 if (asyncTransfers_) {
1328 if (!toCrsMatrix(P11_)->getCrsGraph()->getImporter().is_null())
1329 P11x_colmap_ = MultiVectorFactory::Build(P11_->getColMap(), numVectors);
1330 if (!toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter().is_null())
1331 Dx_colmap_ = MultiVectorFactory::Build(Dk_1_->getColMap(), numVectors);
1334 residual_ = MultiVectorFactory::Build(SM_Matrix_->getDomainMap(), numVectors);
1335 residual_->setObjectLabel(
"residual");
1338template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1340 if (dump_matrices_ && !A.is_null()) {
1341 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1342 Xpetra::IO<SC, LO, GO, NO>::Write(name, *A);
1346template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1348 if (dump_matrices_ && !X.is_null()) {
1349 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1350 Xpetra::IO<SC, LO, GO, NO>::Write(name, *X);
1354template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1356 if (dump_matrices_ && !X.is_null()) {
1357 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1358 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, *X);
1362template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1364 if (dump_matrices_) {
1365 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1366 std::ofstream out(name);
1367 for (
size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
1368 out << v[i] <<
"\n";
1372template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1374 if (dump_matrices_) {
1375 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1376 std::ofstream out(name);
1377 auto vH = Kokkos::create_mirror_view(v);
1378 Kokkos::deep_copy(vH, v);
1379 out <<
"%%MatrixMarket matrix array real general\n"
1380 << vH.extent(0) <<
" 1\n";
1381 for (
size_t i = 0; i < vH.size(); i++)
1382 out << vH[i] <<
"\n";
1386template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1390 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1392 if (comm.is_null()) {
1394 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1395 SM_Matrix_->getRowMap()->getComm()->barrier();
1397 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1400 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1403 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1407 return Teuchos::null;
1410template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1412 buildNullspace(
const int spaceNumber,
const Kokkos::View<bool *, typename Node::device_type> &bcs,
const bool applyBCs) {
1413 std::string spaceLabel;
1414 if (spaceNumber == 0)
1415 spaceLabel =
"nodal";
1416 else if (spaceNumber == 1)
1417 spaceLabel =
"edge";
1418 else if (spaceNumber == 2)
1419 spaceLabel =
"face";
1421 TEUCHOS_ASSERT(
false);
1422 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1425 RCP<Teuchos::TimeMonitor> tm;
1426 if (spaceNumber > 0) {
1427 tm = getTimer(
"nullspace " + spaceLabel);
1428 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" nullspace" << std::endl;
1431 if (spaceNumber == 0) {
1432 return Teuchos::null;
1434 }
else if (spaceNumber == 1) {
1435 RCP<MultiVector> CoordsSC;
1437 RCP<MultiVector> Nullspace = MultiVectorFactory::Build(D0_->getRowMap(), NodalCoords_->getNumVectors());
1438 D0_->apply(*CoordsSC, *Nullspace);
1440 bool normalize = parameterList_.get<
bool>(
"refmaxwell: normalize nullspace", MasterList::getDefault<bool>(
"refmaxwell: normalize nullspace"));
1445 ArrayRCP<ArrayRCP<const Scalar>> localNullspace(dim_);
1446 for (
size_t i = 0; i < dim_; i++)
1447 localNullspace[i] = Nullspace->getData(i);
1448 coordinateType localMinLen = Teuchos::ScalarTraits<coordinateType>::rmax();
1449 coordinateType localMeanLen = Teuchos::ScalarTraits<coordinateType>::zero();
1450 coordinateType localMaxLen = Teuchos::ScalarTraits<coordinateType>::zero();
1451 for (
size_t j = 0; j < Nullspace->getMap()->getLocalNumElements(); j++) {
1452 Scalar lenSC = Teuchos::ScalarTraits<Scalar>::zero();
1453 for (
size_t i = 0; i < dim_; i++)
1454 lenSC += localNullspace[i][j] * localNullspace[i][j];
1455 coordinateType len = Teuchos::as<coordinateType>(Teuchos::ScalarTraits<Scalar>::real(Teuchos::ScalarTraits<Scalar>::squareroot(lenSC)));
1456 localMinLen = std::min(localMinLen, len);
1457 localMaxLen = std::max(localMaxLen, len);
1458 localMeanLen += len;
1461 RCP<const Teuchos::Comm<int>> comm = Nullspace->getMap()->getComm();
1465 meanLen /= Nullspace->getMap()->getGlobalNumElements();
1469 GetOStream(
Statistics2) <<
"Edge length (min/mean/max): " << minLen <<
" / " << meanLen <<
" / " << maxLen << std::endl;
1474 GetOStream(
Runtime0) << solverName_ +
"::compute(): normalizing nullspace" << std::endl;
1476 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1478 Array<Scalar> normsSC(NodalCoords_->getNumVectors(), one / Teuchos::as<Scalar>(meanLen));
1479 Nullspace->scale(normsSC());
1486 dump(Nullspace,
"nullspaceEdge.m");
1490 }
else if (spaceNumber == 2) {
1491 using ATS = KokkosKernels::ArithTraits<Scalar>;
1492 using impl_Scalar =
typename ATS::val_type;
1493 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1494 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1496 RCP<Matrix> facesToNodes;
1498 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1503 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1509 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1516 RCP<RealValuedMultiVector> ghostedNodalCoordinates;
1517 auto importer = facesToNodes->getCrsGraph()->getImporter();
1518 if (!importer.is_null()) {
1519 ghostedNodalCoordinates = Xpetra::MultiVectorFactory<coordinateType, LocalOrdinal, GlobalOrdinal, Node>::Build(importer->getTargetMap(), dim_);
1520 ghostedNodalCoordinates->doImport(*NodalCoords_, *importer, Xpetra::INSERT);
1522 ghostedNodalCoordinates = NodalCoords_;
1524 RCP<MultiVector> Nullspace = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(facesToNodes->getRangeMap(), dim_);
1526 auto facesToNodesLocal = facesToNodes->getLocalMatrixDevice();
1527 auto localNodalCoordinates = ghostedNodalCoordinates->getLocalViewDevice(Tpetra::Access::ReadOnly);
1528 auto localFaceNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1531 Kokkos::parallel_for(
1532 solverName_ +
"::buildFaceProjection_nullspace",
1533 range_type(0, Nullspace->getMap()->getLocalNumElements()),
1534 KOKKOS_LAMBDA(
const size_t f) {
1535 size_t n0 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f));
1536 size_t n1 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 1);
1537 size_t n2 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 2);
1538 impl_Scalar elementNullspace00 = localNodalCoordinates(n1, 0) - localNodalCoordinates(n0, 0);
1539 impl_Scalar elementNullspace10 = localNodalCoordinates(n2, 0) - localNodalCoordinates(n0, 0);
1540 impl_Scalar elementNullspace01 = localNodalCoordinates(n1, 1) - localNodalCoordinates(n0, 1);
1541 impl_Scalar elementNullspace11 = localNodalCoordinates(n2, 1) - localNodalCoordinates(n0, 1);
1542 impl_Scalar elementNullspace02 = localNodalCoordinates(n1, 2) - localNodalCoordinates(n0, 2);
1543 impl_Scalar elementNullspace12 = localNodalCoordinates(n2, 2) - localNodalCoordinates(n0, 2);
1545 localFaceNullspace(f, 0) = impl_ATS::magnitude(elementNullspace01 * elementNullspace12 - elementNullspace02 * elementNullspace11) / 6.0;
1546 localFaceNullspace(f, 1) = impl_ATS::magnitude(elementNullspace02 * elementNullspace10 - elementNullspace00 * elementNullspace12) / 6.0;
1547 localFaceNullspace(f, 2) = impl_ATS::magnitude(elementNullspace00 * elementNullspace11 - elementNullspace01 * elementNullspace10) / 6.0;
1556 dump(Nullspace,
"nullspaceFace.m");
1561 TEUCHOS_ASSERT(
false);
1562 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1566template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1567Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1569 using ATS = KokkosKernels::ArithTraits<Scalar>;
1570 using impl_Scalar =
typename ATS::val_type;
1571 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1572 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1574 typedef typename Matrix::local_matrix_device_type KCRS;
1575 typedef typename KCRS::StaticCrsGraphType graph_t;
1576 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1577 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1578 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1580 const impl_Scalar impl_SC_ONE = impl_ATS::one();
1581 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
1582 const impl_Scalar impl_half = impl_SC_ONE / (impl_SC_ONE + impl_SC_ONE);
1584 std::string spaceLabel;
1585 if (spaceNumber == 0)
1586 spaceLabel =
"nodal";
1587 else if (spaceNumber == 1)
1588 spaceLabel =
"edge";
1589 else if (spaceNumber == 2)
1590 spaceLabel =
"face";
1592 TEUCHOS_ASSERT(
false);
1594 RCP<Teuchos::TimeMonitor> tm;
1595 if (spaceNumber > 0) {
1596 tm = getTimer(
"projection " + spaceLabel);
1597 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" projection" << std::endl;
1600 RCP<Matrix> incidence;
1601 if (spaceNumber == 0) {
1603 return Teuchos::null;
1605 }
else if (spaceNumber == 1) {
1609 }
else if (spaceNumber == 2) {
1612 TEUCHOS_ASSERT(spaceNumber_ == 2);
1614 RCP<Matrix> facesToNodes;
1616 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1619 dump(edgesToNodes,
"edgesToNodes.m");
1621 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1625 dump(facesToEdges,
"facesToEdges.m");
1627 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1632 dump(facesToNodes,
"facesToNodes.m");
1634 incidence = facesToNodes;
1637 TEUCHOS_ASSERT(
false);
1642 RCP<const Map> rowMap = incidence->getRowMap();
1643 RCP<const Map> blockColMap = MapFactory::Build(incidence->getColMap(), dim);
1644 RCP<const Map> blockDomainMap = MapFactory::Build(incidence->getDomainMap(), dim);
1646 auto localIncidence = incidence->getLocalMatrixDevice();
1647 size_t numLocalRows = rowMap->getLocalNumElements();
1648 size_t numLocalColumns = dim * incidence->getColMap()->getLocalNumElements();
1649 size_t nnzEstimate = dim * localIncidence.graph.entries.size();
1650 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"projection_rowptr_" + spaceLabel), numLocalRows + 1);
1651 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"projection_colind_" + spaceLabel), nnzEstimate);
1652 scalar_view_t vals(
"projection_vals_" + spaceLabel, nnzEstimate);
1655 Kokkos::parallel_for(
1656 solverName_ +
"::buildProjection_adjustRowptr_" + spaceLabel,
1657 range_type(0, numLocalRows + 1),
1658 KOKKOS_LAMBDA(
const size_t i) {
1659 rowptr(i) = dim * localIncidence.graph.row_map(i);
1662 auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1666 Kokkos::parallel_for(
1667 solverName_ +
"::buildProjection_enterValues_" + spaceLabel,
1668 range_type(0, numLocalRows),
1669 KOKKOS_LAMBDA(
const size_t f) {
1670 for (
size_t jj = localIncidence.graph.row_map(f); jj < localIncidence.graph.row_map(f + 1); jj++) {
1671 for (
size_t k = 0; k < dim; k++) {
1672 colind(dim * jj + k) = dim * localIncidence.graph.entries(jj) + k;
1673 if (impl_ATS::magnitude(localIncidence.values(jj)) > tol)
1674 vals(dim * jj + k) = impl_half * localNullspace(f, k);
1676 vals(dim * jj + k) = impl_SC_ZERO;
1682 typename CrsMatrix::local_matrix_device_type lclProjection(
"local projection " + spaceLabel,
1683 numLocalRows, numLocalColumns, nnzEstimate,
1684 vals, rowptr, colind);
1685 RCP<Matrix> projection = MatrixFactory::Build(lclProjection,
1686 rowMap, blockColMap,
1687 blockDomainMap, rowMap);
1692template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1694 Teuchos::RCP<Matrix> &P_nodal,
1695 Teuchos::RCP<MultiVector> &Nullspace_nodal,
1696 Teuchos::RCP<RealValuedMultiVector> &CoarseCoords_nodal)
const {
1697 RCP<Teuchos::TimeMonitor> tm = getTimer(
"nodal prolongator");
1698 GetOStream(
Runtime0) << solverName_ +
"::compute(): building nodal prolongator" << std::endl;
1703 const SC SC_ONE = Teuchos::ScalarTraits<SC>::one();
1706 Level fineLevel, coarseLevel;
1712 fineLevel.
Set(
"A", A_nodal);
1713 fineLevel.
Set(
"Coordinates", NodalCoords_);
1714 fineLevel.
Set(
"DofsPerNode", 1);
1715 coarseLevel.
setlib(A_nodal->getDomainMap()->lib());
1716 fineLevel.
setlib(A_nodal->getDomainMap()->lib());
1717 coarseLevel.setObjectLabel(A_nodal->getObjectLabel());
1718 fineLevel.setObjectLabel(A_nodal->getObjectLabel());
1721 RCP<MultiVector> nullSpace = MultiVectorFactory::Build(A_nodal->getRowMap(), NSdim);
1722 nullSpace->putScalar(SC_ONE);
1723 fineLevel.
Set(
"Nullspace", nullSpace);
1725 std::string algo = parameterList_.get<std::string>(
"multigrid algorithm");
1727 RCP<Factory> amalgFact, dropFact, UncoupledAggFact, coarseMapFact, TentativePFact, Tfact, SaPFact;
1741 dropFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1743 double dropTol = parameterList_.get<
double>(
"aggregation: drop tol");
1744 std::string dropScheme = parameterList_.get<std::string>(
"aggregation: drop scheme");
1745 std::string distLaplAlgo = parameterList_.get<std::string>(
"aggregation: distance laplacian algo");
1746 dropFact->SetParameter(
"aggregation: drop tol", Teuchos::ParameterEntry(dropTol));
1747 dropFact->SetParameter(
"aggregation: drop scheme", Teuchos::ParameterEntry(dropScheme));
1748 dropFact->SetParameter(
"aggregation: distance laplacian algo", Teuchos::ParameterEntry(distLaplAlgo));
1750 UncoupledAggFact->SetFactory(
"Graph", dropFact);
1751 int minAggSize = parameterList_.get<
int>(
"aggregation: min agg size");
1752 UncoupledAggFact->SetParameter(
"aggregation: min agg size", Teuchos::ParameterEntry(minAggSize));
1753 int maxAggSize = parameterList_.get<
int>(
"aggregation: max agg size");
1754 UncoupledAggFact->SetParameter(
"aggregation: max agg size", Teuchos::ParameterEntry(maxAggSize));
1755 bool matchMLbehavior1 = parameterList_.get<
bool>(
"aggregation: match ML phase1");
1756 UncoupledAggFact->SetParameter(
"aggregation: match ML phase1", Teuchos::ParameterEntry(matchMLbehavior1));
1757 bool matchMLbehavior2a = parameterList_.get<
bool>(
"aggregation: match ML phase2a");
1758 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2a", Teuchos::ParameterEntry(matchMLbehavior2a));
1759 bool matchMLbehavior2b = parameterList_.get<
bool>(
"aggregation: match ML phase2b");
1760 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2b", Teuchos::ParameterEntry(matchMLbehavior2b));
1762 coarseMapFact->SetFactory(
"Aggregates", UncoupledAggFact);
1764 TentativePFact->SetFactory(
"Aggregates", UncoupledAggFact);
1765 TentativePFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1766 TentativePFact->SetFactory(
"CoarseMap", coarseMapFact);
1768 Tfact->SetFactory(
"Aggregates", UncoupledAggFact);
1769 Tfact->SetFactory(
"CoarseMap", coarseMapFact);
1772 SaPFact->SetFactory(
"P", TentativePFact);
1773 coarseLevel.
Request(
"P", SaPFact.get());
1775 coarseLevel.
Request(
"P", TentativePFact.get());
1776 coarseLevel.
Request(
"Nullspace", TentativePFact.get());
1777 coarseLevel.
Request(
"Coordinates", Tfact.get());
1779 RCP<AggregationExportFactory> aggExport;
1780 bool exportVizData = parameterList_.get<
bool>(
"aggregation: export visualization data");
1781 if (exportVizData) {
1783 ParameterList aggExportParams;
1784 aggExportParams.set(
"aggregation: output filename",
"aggs.vtk");
1785 aggExportParams.set(
"aggregation: output file: agg style",
"Jacks");
1786 aggExport->SetParameterList(aggExportParams);
1788 aggExport->SetFactory(
"Aggregates", UncoupledAggFact);
1789 aggExport->SetFactory(
"UnAmalgamationInfo", amalgFact);
1790 fineLevel.
Request(
"Aggregates", UncoupledAggFact.get());
1791 fineLevel.
Request(
"UnAmalgamationInfo", amalgFact.get());
1795 coarseLevel.
Get(
"P", P_nodal, SaPFact.get());
1797 coarseLevel.
Get(
"P", P_nodal, TentativePFact.get());
1798 coarseLevel.
Get(
"Nullspace", Nullspace_nodal, TentativePFact.get());
1799 coarseLevel.
Get(
"Coordinates", CoarseCoords_nodal, Tfact.get());
1802 aggExport->Build(fineLevel, coarseLevel);
1806template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1807Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1809 RCP<Teuchos::TimeMonitor> tm = getTimer(
"vectorial nodal prolongator");
1810 GetOStream(
Runtime0) << solverName_ +
"::compute(): building vectorial nodal prolongator" << std::endl;
1812 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1814 typedef typename Matrix::local_matrix_device_type KCRS;
1815 typedef typename KCRS::StaticCrsGraphType graph_t;
1816 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1817 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1818 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1823 RCP<Map> blockRowMap = MapFactory::Build(P_nodal->getRowMap(), dim);
1824 RCP<Map> blockColMap = MapFactory::Build(P_nodal->getColMap(), dim);
1825 RCP<Map> blockDomainMap = MapFactory::Build(P_nodal->getDomainMap(), dim);
1828 auto localP_nodal = P_nodal->getLocalMatrixDevice();
1830 size_t numLocalRows = blockRowMap->getLocalNumElements();
1831 size_t numLocalColumns = blockColMap->getLocalNumElements();
1832 size_t nnzEstimate = dim * localP_nodal.graph.entries.size();
1833 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_rowptr"), numLocalRows + 1);
1834 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_colind"), nnzEstimate);
1835 scalar_view_t vals(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_vals"), nnzEstimate);
1838 Kokkos::parallel_for(
1839 solverName_ +
"::buildVectorNodalProlongator_adjustRowptr",
1840 range_type(0, localP_nodal.numRows() + 1),
1842 if (i < localP_nodal.numRows()) {
1843 for (size_t k = 0; k < dim; k++) {
1844 rowptr(dim * i + k) = dim * localP_nodal.graph.row_map(i) + k;
1847 rowptr(dim * localP_nodal.numRows()) = dim * localP_nodal.graph.row_map(i);
1851 Kokkos::parallel_for(
1852 solverName_ +
"::buildVectorNodalProlongator_adjustColind",
1853 range_type(0, localP_nodal.graph.entries.size()),
1854 KOKKOS_LAMBDA(
const size_t jj) {
1855 for (
size_t k = 0; k < dim; k++) {
1856 colind(dim * jj + k) = dim * localP_nodal.graph.entries(jj) + k;
1858 vals(dim * jj + k) = 1.;
1862 typename CrsMatrix::local_matrix_device_type lclVectorNodalP(
"local vector nodal prolongator",
1863 numLocalRows, numLocalColumns, nnzEstimate,
1864 vals, rowptr, colind);
1865 RCP<Matrix> vectorNodalP = MatrixFactory::Build(lclVectorNodalP,
1866 blockRowMap, blockColMap,
1867 blockDomainMap, blockRowMap);
1869 return vectorNodalP;
1872template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1875 const Teuchos::RCP<Matrix> &A_nodal,
1876 const Teuchos::RCP<MultiVector> &Nullspace,
1877 Teuchos::RCP<Matrix> &Prolongator,
1878 Teuchos::RCP<MultiVector> &coarseNullspace,
1879 Teuchos::RCP<RealValuedMultiVector> &coarseNodalCoords)
const {
1880 using ATS = KokkosKernels::ArithTraits<Scalar>;
1881 using impl_Scalar =
typename ATS::val_type;
1882 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1884 std::string typeStr;
1885 switch (spaceNumber) {
1888 TEUCHOS_ASSERT(A_nodal.is_null());
1897 TEUCHOS_ASSERT(
false);
1900 const bool skipFirstLevel = !A_nodal.is_null();
1902 RCP<Teuchos::TimeMonitor> tm;
1903 if (spaceNumber > 0) {
1904 tm = getTimer(
"special prolongator " + typeStr);
1905 GetOStream(
Runtime0) << solverName_ +
"::compute(): building special " + typeStr +
" prolongator" << std::endl;
1908 RCP<Matrix> projection = buildProjection(spaceNumber, Nullspace);
1909 dump(projection, typeStr +
"Projection.m");
1911 if (skipFirstLevel) {
1912 RCP<Matrix> P_nodal;
1913 RCP<MultiVector> coarseNodalNullspace;
1915 buildNodalProlongator(A_nodal, P_nodal, coarseNodalNullspace, coarseNodalCoords);
1917 dump(P_nodal,
"P_nodal_" + typeStr +
".m");
1918 dump(coarseNodalNullspace,
"coarseNullspace_nodal_" + typeStr +
".m");
1920 RCP<Matrix> vectorP_nodal = buildVectorNodalProlongator(P_nodal);
1922 dump(vectorP_nodal,
"vectorP_nodal_" + typeStr +
".m");
1924 Prolongator = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*projection,
false, *vectorP_nodal,
false, Prolongator, GetOStream(
Runtime0),
true,
true);
1973 coarseNullspace = MultiVectorFactory::Build(vectorP_nodal->getDomainMap(), dim);
1975 auto localNullspace_nodal = coarseNodalNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1976 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1977 Kokkos::parallel_for(
1978 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
1979 range_type(0, coarseNodalNullspace->getLocalLength()),
1980 KOKKOS_LAMBDA(
const size_t i) {
1981 impl_Scalar val = localNullspace_nodal(i, 0);
1982 for (
size_t j = 0; j < dim; j++)
1983 localNullspace_coarse(dim * i + j, j) = val;
1987 Prolongator = projection;
1988 coarseNodalCoords = NodalCoords_;
1990 if (spaceNumber == 0) {
1992 }
else if (spaceNumber >= 1) {
1994 coarseNullspace = MultiVectorFactory::Build(projection->getDomainMap(), dim);
1995 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1996 Kokkos::parallel_for(
1997 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
1998 range_type(0, coarseNullspace->getLocalLength() / dim),
1999 KOKKOS_LAMBDA(
const size_t i) {
2000 for (
size_t j = 0; j < dim; j++)
2001 localNullspace_coarse(dim * i + j, j) = 1.0;
2007template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2009 Teuchos::RCP<Operator> &thyraPrecOp,
2010 const Teuchos::RCP<Matrix> &A,
2011 const Teuchos::RCP<MultiVector> &Nullspace,
2012 const Teuchos::RCP<RealValuedMultiVector> &Coords,
2013 const Teuchos::RCP<MultiVector> &Material,
2014 Teuchos::ParameterList ¶ms,
2017 const bool isSingular) {
2018 int oldRank = SetProcRankVerbose(A->getDomainMap()->getComm()->getRank());
2020 RCP<ParameterList> pl = rcp(
new ParameterList());
2021 pl->set(
"printLoadBalancingInfo",
true);
2022 pl->set(
"printCommInfo",
true);
2023 GetOStream(
Statistics2) << PerfUtils::PrintMatrixInfo(*A, label, pl);
2025#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2026 if (params.isType<std::string>(
"Preconditioner Type")) {
2027 TEUCHOS_ASSERT(!reuse);
2029 if (params.get<std::string>(
"Preconditioner Type") ==
"MueLu") {
2030 ParameterList &userParamList = params.sublist(
"Preconditioner Types").sublist(
"MueLu").sublist(
"user data");
2031 if (!Nullspace.is_null())
2032 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2033 if (!Material.is_null())
2034 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2035 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2037 thyraPrecOp = rcp(
new XpetraThyraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(coarseA11_, rcp(¶ms,
false)));
2044 ParameterList &userParamList = params.sublist(
"user data");
2045 if (!Coords.is_null())
2046 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2047 if (!Nullspace.is_null())
2048 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2049 if (!Material.is_null())
2050 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2053 std::string coarseType =
"";
2054 if (params.isParameter(
"coarse: type")) {
2055 coarseType = params.get<std::string>(
"coarse: type");
2057 std::transform(coarseType.begin(), coarseType.end(), coarseType.begin(), ::tolower);
2058 std::transform(coarseType.begin(), ++coarseType.begin(), coarseType.begin(), ::toupper);
2060 if ((coarseType ==
"" ||
2061 coarseType ==
"Klu" ||
2062 coarseType ==
"Klu2" ||
2063 coarseType ==
"Superlu" ||
2064 coarseType ==
"Superlu_dist" ||
2065 coarseType ==
"Superludist" ||
2066 coarseType ==
"Basker" ||
2067 coarseType ==
"Cusolver" ||
2068 coarseType ==
"Tacho") &&
2069 (!params.isSublist(
"coarse: params") ||
2070 !params.sublist(
"coarse: params").isParameter(
"fix nullspace")))
2071 params.sublist(
"coarse: params").set(
"fix nullspace",
true);
2076 RCP<MueLu::Level> level0 = hierarchy->GetLevel(0);
2077 level0->Set(
"A", A);
2078 hierarchy->SetupRe();
2081 SetProcRankVerbose(oldRank);
2084template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2086 bool reuse = !SM_Matrix_.is_null();
2087 SM_Matrix_ = SM_Matrix_new;
2088 dump(SM_Matrix_,
"SM.m");
2093template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2129 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2133 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2134 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2139 if (implicitTranspose_) {
2141 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"restriction coarse (1,1) (implicit)");
2142 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2144 if (!onlyBoundary22_) {
2145 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (implicit)");
2146 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2149 if (Dk_1_T_R11_colMapsMatch_) {
2152 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restrictions import");
2153 DTR11Tmp_->doImport(*residual_, *toCrsMatrix(R11_)->getCrsGraph()->getImporter(), Xpetra::INSERT);
2155 if (!onlyBoundary22_) {
2156 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2157 toTpetra(Dk_1_T_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*Dres_), Teuchos::NO_TRANS);
2160 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2161 toTpetra(R11_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*P11res_), Teuchos::NO_TRANS);
2165 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2166 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2168 if (!onlyBoundary22_) {
2169 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2170 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2177 RCP<Teuchos::TimeMonitor> tmSubSolves = getTimer(
"subsolves");
2181 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2182 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2183 P11resTmp_->beginImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2185 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_) {
2186 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2187 DresTmp_->beginImport(*Dres_, *Importer22_, Xpetra::INSERT);
2191 if (!coarseA11_.is_null()) {
2192 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
2193 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2195 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2197#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2198 if (!thyraPrecOpH_.is_null()) {
2199 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2200 thyraPrecOpH_->apply(*P11resSubComm_, *P11xSubComm_, Teuchos::NO_TRANS, one, zero);
2203 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2207 if (!A22_.is_null()) {
2208 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2209 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2211 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2212#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2213 if (!thyraPrecOp22_.is_null()) {
2214 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2215 thyraPrecOp22_->apply(*DresSubComm_, *DxSubComm_, Teuchos::NO_TRANS, one, zero);
2218 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2221 if (coarseA11_.is_null() && !ImporterCoarse11_.is_null() && !implicitTranspose_)
2222 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2223 if (A22_.is_null() && !onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2224 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2228 RCP<Teuchos::TimeMonitor> tmProlongations = getTimer(
"prolongations");
2230 if (asyncTransfers_) {
2231 using Tpetra_Multivector = Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2232 using Tpetra_Import = Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>;
2234 auto tpP11 = toTpetra(P11_);
2235 auto tpDk_1 = toTpetra(Dk_1_);
2237 RCP<Tpetra_Multivector> tpP11x = toTpetra(P11x_);
2238 RCP<Tpetra_Multivector> tpP11x_colmap;
2239 RCP<Tpetra_Multivector> tpX = toTpetra(Teuchos::rcpFromRef(X));
2240 RCP<Tpetra_Multivector> tpResidual = toTpetra(residual_);
2241 RCP<Tpetra_Multivector> tpDx = toTpetra(Dx_);
2242 RCP<Tpetra_Multivector> tpDx_colmap;
2244 unsigned completedImports = 0;
2245 std::vector<bool> completedImport(2,
false);
2246 auto tpP11importer = tpP11->getCrsGraph()->getImporter();
2247 if (!tpP11importer.is_null()) {
2248 tpP11x_colmap = toTpetra(P11x_colmap_);
2249 tpP11x_colmap->beginImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2252 RCP<const Tpetra_Import> tpDk_1importer;
2253 if (!onlyBoundary22_) {
2254 tpDk_1importer = tpDk_1->getCrsGraph()->getImporter();
2255 if (!tpDk_1importer.is_null()) {
2256 tpDx_colmap = toTpetra(Dx_colmap_);
2257 tpDx_colmap->beginImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2260 completedImport[1] =
true;
2264 if (!fuseProlongationAndUpdate_) {
2265 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2266 tpResidual->putScalar(zero);
2269 while (completedImports < completedImport.size()) {
2270 for (
unsigned i = 0; i < completedImport.size(); i++) {
2271 if (completedImport[i])
continue;
2274 if (!tpP11importer.is_null()) {
2275 if (tpP11x_colmap->transferArrived()) {
2276 tpP11x_colmap->endImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2277 completedImport[i] =
true;
2280 if (fuseProlongationAndUpdate_) {
2281 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2282 tpP11->localApply(*tpP11x_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2284 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2285 tpP11->localApply(*tpP11x_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2289 completedImport[i] =
true;
2292 if (fuseProlongationAndUpdate_) {
2293 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2294 tpP11->localApply(*tpP11x, *tpX, Teuchos::NO_TRANS, one, one);
2296 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2297 tpP11->localApply(*tpP11x, *tpResidual, Teuchos::NO_TRANS, one, one);
2301 if (!tpDk_1importer.is_null()) {
2302 if (tpDx_colmap->transferArrived()) {
2303 tpDx_colmap->endImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2304 completedImport[i] =
true;
2307 if (fuseProlongationAndUpdate_) {
2308 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2309 tpDk_1->localApply(*tpDx_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2311 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2312 tpDk_1->localApply(*tpDx_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2316 completedImport[i] =
true;
2319 if (fuseProlongationAndUpdate_) {
2320 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2321 tpDk_1->localApply(*tpDx, *tpX, Teuchos::NO_TRANS, one, one);
2323 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2324 tpDk_1->localApply(*tpDx, *tpResidual, Teuchos::NO_TRANS, one, one);
2331 if (!fuseProlongationAndUpdate_) {
2332 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2333 X.update(one, *residual_, one);
2336 if (fuseProlongationAndUpdate_) {
2338 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused)");
2339 P11_->apply(*P11x_, X, Teuchos::NO_TRANS, one, one);
2342 if (!onlyBoundary22_) {
2343 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused)");
2344 Dk_1_->apply(*Dx_, X, Teuchos::NO_TRANS, one, one);
2348 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused)");
2349 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2352 if (!onlyBoundary22_) {
2353 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused)");
2354 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS, one, one);
2358 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2359 X.update(one, *residual_, one);
2366template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2368 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2371 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2372 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2373 if (implicitTranspose_)
2374 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2376 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2380 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2381 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2382 P11resTmp_->doImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2384 if (!coarseA11_.is_null()) {
2385 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2386 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2391 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2392 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2393 X.update(one, *residual_, one);
2397template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2399 if (onlyBoundary22_)
2402 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2405 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2406 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2407 if (implicitTranspose_)
2408 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2410 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2414 if (!Importer22_.is_null() && !implicitTranspose_) {
2415 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2416 DresTmp_->doImport(*Dres_, *Importer22_, Xpetra::INSERT);
2418 if (!A22_.is_null()) {
2419 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2420 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2425 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2426 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS);
2427 X.update(one, *residual_, one);
2431template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2436 RCP<Teuchos::TimeMonitor> tm = getTimer(
"solve");
2439 if (!onlyBoundary11_ && X.getNumVectors() != P11res_->getNumVectors())
2440 allocateMemory(X.getNumVectors());
2444 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2446 PreSmoother11_->Apply(X, RHS, use_as_preconditioner_);
2450 if (mode_ ==
"additive")
2451 applyInverseAdditive(RHS, X);
2452 else if (mode_ ==
"121") {
2456 }
else if (mode_ ==
"212") {
2460 }
else if (mode_ ==
"1")
2462 else if (mode_ ==
"2")
2464 else if (mode_ ==
"7") {
2468 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2470 PreSmoother11_->Apply(X, RHS,
false);
2475 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2477 PostSmoother11_->Apply(X, RHS,
false);
2480 }
else if (mode_ ==
"none") {
2483 applyInverseAdditive(RHS, X);
2487 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2489 PostSmoother11_->Apply(X, RHS,
false);
2493template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2498template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2500 RefMaxwell(
const Teuchos::RCP<Matrix> &SM_Matrix,
2501 Teuchos::ParameterList &List,
2503 int spaceNumber = List.get<
int>(
"refmaxwell: space number", 1);
2505 RCP<Matrix> Dk_1, Dk_2, D0;
2506 RCP<Matrix> M1_beta, M1_alpha;
2507 RCP<Matrix> Mk_one, Mk_1_one;
2508 RCP<Matrix> invMk_1_invBeta, invMk_2_invAlpha;
2509 RCP<MultiVector> Nullspace11, Nullspace22;
2510 RCP<RealValuedMultiVector> NodalCoords;
2512 Dk_1 =
pop(List,
"Dk_1", Dk_1);
2513 Dk_2 = pop<RCP<Matrix>>(List,
"Dk_2", Dk_2);
2514 D0 = pop<RCP<Matrix>>(List,
"D0", D0);
2516 M1_beta = pop<RCP<Matrix>>(List,
"M1_beta", M1_beta);
2517 M1_alpha = pop<RCP<Matrix>>(List,
"M1_alpha", M1_alpha);
2519 Mk_one = pop<RCP<Matrix>>(List,
"Mk_one", Mk_one);
2520 Mk_1_one = pop<RCP<Matrix>>(List,
"Mk_1_one", Mk_1_one);
2522 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"invMk_1_invBeta", invMk_1_invBeta);
2523 invMk_2_invAlpha = pop<RCP<Matrix>>(List,
"invMk_2_invAlpha", invMk_2_invAlpha);
2525 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace11", Nullspace11);
2526 Nullspace22 = pop<RCP<MultiVector>>(List,
"Nullspace22", Nullspace22);
2527 NodalCoords = pop<RCP<RealValuedMultiVector>>(List,
"Coordinates", NodalCoords);
2530 if (List.isType<RCP<Matrix>>(
"Ms")) {
2531 if (M1_beta.is_null())
2532 M1_beta =
pop<RCP<Matrix>>(List,
"Ms");
2534 TEUCHOS_ASSERT(
false);
2536 if (List.isType<RCP<Matrix>>(
"M1")) {
2537 if (Mk_one.is_null())
2538 Mk_one = pop<RCP<Matrix>>(List,
"M1");
2540 TEUCHOS_ASSERT(
false);
2542 if (List.isType<RCP<Matrix>>(
"M0inv")) {
2543 if (invMk_1_invBeta.is_null())
2544 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"M0inv");
2546 TEUCHOS_ASSERT(
false);
2548 if (List.isType<RCP<MultiVector>>(
"Nullspace")) {
2549 if (Nullspace11.is_null())
2550 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace");
2552 TEUCHOS_ASSERT(
false);
2555 if (spaceNumber == 1) {
2558 else if (D0.is_null())
2560 if (M1_beta.is_null())
2562 }
else if (spaceNumber == 2) {
2565 else if (D0.is_null())
2569 initialize(spaceNumber,
2573 invMk_1_invBeta, invMk_2_invAlpha,
2574 Nullspace11, Nullspace22,
2576 Teuchos::null, Teuchos::null,
2579 if (SM_Matrix != Teuchos::null)
2580 resetMatrix(SM_Matrix, ComputePrec);
2583template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2585 initialize(
const Teuchos::RCP<Matrix> &D0_Matrix,
2586 const Teuchos::RCP<Matrix> &Ms_Matrix,
2587 const Teuchos::RCP<Matrix> &M0inv_Matrix,
2588 const Teuchos::RCP<Matrix> &M1_Matrix,
2589 const Teuchos::RCP<MultiVector> &Nullspace11,
2590 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2591 const Teuchos::RCP<MultiVector> &Material,
2592 Teuchos::ParameterList &List) {
2594 D0_Matrix, Teuchos::null, D0_Matrix,
2595 Ms_Matrix, Teuchos::null,
2596 M1_Matrix, Teuchos::null,
2597 M0inv_Matrix, Teuchos::null,
2598 Nullspace11, Teuchos::null,
2600 Teuchos::null, Material,
2604template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2607 const Teuchos::RCP<Matrix> &Dk_1,
2608 const Teuchos::RCP<Matrix> &Dk_2,
2609 const Teuchos::RCP<Matrix> &D0,
2610 const Teuchos::RCP<Matrix> &M1_beta,
2611 const Teuchos::RCP<Matrix> &M1_alpha,
2612 const Teuchos::RCP<Matrix> &Mk_one,
2613 const Teuchos::RCP<Matrix> &Mk_1_one,
2614 const Teuchos::RCP<Matrix> &invMk_1_invBeta,
2615 const Teuchos::RCP<Matrix> &invMk_2_invAlpha,
2616 const Teuchos::RCP<MultiVector> &Nullspace11,
2617 const Teuchos::RCP<MultiVector> &Nullspace22,
2618 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2619 const Teuchos::RCP<MultiVector> &Material_beta,
2620 const Teuchos::RCP<MultiVector> &Material_alpha,
2621 Teuchos::ParameterList &List) {
2623 if (spaceNumber_ == 1)
2624 solverName_ =
"RefMaxwell";
2625 else if (spaceNumber_ == 2)
2626 solverName_ =
"RefDarcy";
2628 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
2629 "spaceNumber needs to be 1 (HCurl) or 2 (HDiv)");
2630 HierarchyCoarse11_ = Teuchos::null;
2631 Hierarchy22_ = Teuchos::null;
2632 PreSmoother11_ = Teuchos::null;
2633 PostSmoother11_ = Teuchos::null;
2634 disable_addon_ =
false;
2635 disable_addon_22_ =
true;
2639 setParameters(List);
2642 TEUCHOS_ASSERT((k == 1) || (k == 2));
2644 TEUCHOS_ASSERT(Dk_1 != Teuchos::null);
2646 TEUCHOS_ASSERT(D0 != Teuchos::null);
2649 TEUCHOS_ASSERT(M1_beta != Teuchos::null);
2652 TEUCHOS_ASSERT(M1_alpha != Teuchos::null);
2654 if (!disable_addon_) {
2656 TEUCHOS_ASSERT(Mk_one != Teuchos::null);
2657 TEUCHOS_ASSERT(invMk_1_invBeta != Teuchos::null);
2660 if ((k >= 2) && !disable_addon_22_) {
2662 TEUCHOS_ASSERT(Dk_2 != Teuchos::null);
2663 TEUCHOS_ASSERT(Mk_1_one != Teuchos::null);
2664 TEUCHOS_ASSERT(invMk_2_invAlpha != Teuchos::null);
2667 if (Behavior::debug()) {
2668 TEUCHOS_ASSERT(D0->getRangeMap()->isSameAs(*D0->getRowMap()));
2671 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRangeMap()));
2672 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRowMap()));
2675 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*D0->getRangeMap()));
2679 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRangeMap()));
2680 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRowMap()));
2683 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*D0->getRangeMap()));
2686 if (!disable_addon_) {
2688 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRangeMap()));
2689 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRowMap()));
2692 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2695 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRangeMap()));
2696 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRowMap()));
2699 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2702 if ((k >= 2) && !disable_addon_22_) {
2704 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRangeMap()));
2705 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRowMap()));
2708 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2711 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_2->getRangeMap()));
2714 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRangeMap()));
2715 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRowMap()));
2718 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*Dk_2->getDomainMap()));
2723 if (Dk_1->getRowMap()->lib() == Xpetra::UseTpetra) {
2728 RCP<Matrix> Dk_1copy = MatrixFactory::Build(Dk_1->getRowMap(), Dk_1->getColMap(), 0);
2729 RCP<CrsMatrix> Dk_1copyCrs = toCrsMatrix(Dk_1copy);
2730 ArrayRCP<const size_t> Dk_1rowptr_RCP;
2731 ArrayRCP<const LO> Dk_1colind_RCP;
2732 ArrayRCP<const SC> Dk_1vals_RCP;
2733 toCrsMatrix(Dk_1)->getAllValues(Dk_1rowptr_RCP, Dk_1colind_RCP, Dk_1vals_RCP);
2735 ArrayRCP<size_t> Dk_1copyrowptr_RCP;
2736 ArrayRCP<LO> Dk_1copycolind_RCP;
2737 ArrayRCP<SC> Dk_1copyvals_RCP;
2738 Dk_1copyCrs->allocateAllValues(Dk_1vals_RCP.size(), Dk_1copyrowptr_RCP, Dk_1copycolind_RCP, Dk_1copyvals_RCP);
2739 Dk_1copyrowptr_RCP.deepCopy(Dk_1rowptr_RCP());
2740 Dk_1copycolind_RCP.deepCopy(Dk_1colind_RCP());
2741 Dk_1copyvals_RCP.deepCopy(Dk_1vals_RCP());
2742 Dk_1copyCrs->setAllValues(Dk_1copyrowptr_RCP,
2745 Dk_1copyCrs->expertStaticFillComplete(Dk_1->getDomainMap(), Dk_1->getRangeMap(),
2746 toCrsMatrix(Dk_1)->getCrsGraph()->getImporter(),
2747 toCrsMatrix(Dk_1)->getCrsGraph()->getExporter());
2750 Dk_1_ = MatrixFactory::BuildCopy(Dk_1);
2752 if ((!Dk_2.is_null()) && (Dk_2->getRowMap()->lib() == Xpetra::UseTpetra)) {
2757 RCP<Matrix> Dk_2copy = MatrixFactory::Build(Dk_2->getRowMap(), Dk_2->getColMap(), 0);
2758 RCP<CrsMatrix> Dk_2copyCrs = toCrsMatrix(Dk_2copy);
2759 ArrayRCP<const size_t> Dk_2rowptr_RCP;
2760 ArrayRCP<const LO> Dk_2colind_RCP;
2761 ArrayRCP<const SC> Dk_2vals_RCP;
2762 toCrsMatrix(Dk_2)->getAllValues(Dk_2rowptr_RCP, Dk_2colind_RCP, Dk_2vals_RCP);
2764 ArrayRCP<size_t> Dk_2copyrowptr_RCP;
2765 ArrayRCP<LO> Dk_2copycolind_RCP;
2766 ArrayRCP<SC> Dk_2copyvals_RCP;
2767 Dk_2copyCrs->allocateAllValues(Dk_2vals_RCP.size(), Dk_2copyrowptr_RCP, Dk_2copycolind_RCP, Dk_2copyvals_RCP);
2768 Dk_2copyrowptr_RCP.deepCopy(Dk_2rowptr_RCP());
2769 Dk_2copycolind_RCP.deepCopy(Dk_2colind_RCP());
2770 Dk_2copyvals_RCP.deepCopy(Dk_2vals_RCP());
2771 Dk_2copyCrs->setAllValues(Dk_2copyrowptr_RCP,
2774 Dk_2copyCrs->expertStaticFillComplete(Dk_2->getDomainMap(), Dk_2->getRangeMap(),
2775 toCrsMatrix(Dk_2)->getCrsGraph()->getImporter(),
2776 toCrsMatrix(Dk_2)->getCrsGraph()->getExporter());
2778 }
else if (!Dk_2.is_null())
2779 Dk_2_ = MatrixFactory::BuildCopy(Dk_2);
2782 M1_alpha_ = M1_alpha;
2784 Material_beta_ = Material_beta;
2785 Material_alpha_ = Material_alpha;
2788 Mk_1_one_ = Mk_1_one;
2790 invMk_1_invBeta_ = invMk_1_invBeta;
2791 invMk_2_invAlpha_ = invMk_2_invAlpha;
2793 NodalCoords_ = NodalCoords;
2794 Nullspace11_ = Nullspace11;
2795 Nullspace22_ = Nullspace22;
2798 dump(Dk_1_,
"Dk_1_clean.m");
2799 dump(Dk_2_,
"Dk_2_clean.m");
2801 dump(M1_beta_,
"M1_beta.m");
2802 dump(M1_alpha_,
"M1_alpha.m");
2804 dump(Mk_one_,
"Mk_one.m");
2805 dump(Mk_1_one_,
"Mk_1_one.m");
2807 dump(invMk_1_invBeta_,
"invMk_1_invBeta.m");
2808 dump(invMk_2_invAlpha_,
"invMk_2_invAlpha.m");
2810 dumpCoords(NodalCoords_,
"coords.m");
2813template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2815 describe(Teuchos::FancyOStream &out,
const Teuchos::EVerbosityLevel )
const {
2816 std::ostringstream oss;
2818 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->
getDomainMap()->getComm();
2822 if (!coarseA11_.is_null())
2823 root = comm->getRank();
2828 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
2832 oss <<
"\n--------------------------------------------------------------------------------\n"
2833 <<
"--- " + solverName_ +
2835 "--------------------------------------------------------------------------------"
2842 SM_Matrix_->getRowMap()->getComm()->barrier();
2844 numRows = SM_Matrix_->getGlobalNumRows();
2845 nnz = SM_Matrix_->getGlobalNumEntries();
2847 Xpetra::global_size_t tt = numRows;
2860 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
2861 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2863 if (!A22_.is_null()) {
2864 numRows = A22_->getGlobalNumRows();
2865 nnz = A22_->getGlobalNumEntries();
2867 oss <<
"(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2873 if (PreSmoother11_ != null && PreSmoother11_ == PostSmoother11_)
2874 oss <<
"Smoother 11 both : " << PreSmoother11_->description() << std::endl;
2876 oss <<
"Smoother 11 pre : "
2877 << (PreSmoother11_ != null ? PreSmoother11_->description() :
"no smoother") << std::endl;
2878 oss <<
"Smoother 11 post : "
2879 << (PostSmoother11_ != null ? PostSmoother11_->description() :
"no smoother") << std::endl;
2884 std::string outstr = oss.str();
2887 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2888 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
2890 int strLength = outstr.size();
2891 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
2892 if (comm->getRank() != root)
2893 outstr.resize(strLength);
2894 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
2899 if (!HierarchyCoarse11_.is_null())
2900 HierarchyCoarse11_->describe(out, GetVerbLevel());
2902 if (!Hierarchy22_.is_null())
2903 Hierarchy22_->describe(out, GetVerbLevel());
2907 std::ostringstream oss2;
2909 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
2910 oss2 <<
"( (1,1) block only is indicated by '1', (2,2) block only by '2', and both blocks by 'B' and none by '.')" << std::endl;
2912 int numProcs = comm->getSize();
2914 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2915 TEUCHOS_TEST_FOR_EXCEPTION(tmpic == Teuchos::null,
Exceptions::RuntimeError,
"Cannot cast base Teuchos::Comm to Teuchos::MpiComm object.");
2916 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
2920 if (!coarseA11_.is_null())
2922 if (!A22_.is_null())
2924 std::vector<char> states(numProcs, 0);
2926 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
2928 states.push_back(status);
2931 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
2932 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
2933 for (
int j = 0; j < rowWidth; j++)
2934 if (proc + j < numProcs)
2935 if (states[proc + j] == 0)
2937 else if (states[proc + j] == 1)
2939 else if (states[proc + j] == 2)
2946 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
2955#define MUELU_REFMAXWELL_SHORT
Various adapters that will create a MueLu preconditioner that is an Xpetra::Matrix.
#define MueLu_maxAll(rcpComm, in, out)
#define MueLu_sumAll(rcpComm, in, out)
#define MueLu_minAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Factory to export aggregation info or visualize aggregates using VTK.
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for creating a graph based on a given matrix.
Factory for creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Class for transferring coordinates from a finer level to a coarser one.
Exception throws to report errors in the internal logical of the program.
This class specifies the default factory that should generate some data on a Level if the data does n...
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void setlib(Xpetra::UnderlyingLib lib2)
void SetLevelID(int levelID)
Set level number.
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.
void SetPreviousLevel(const RCP< Level > &previousLevel)
void SetFactoryManager(const RCP< const FactoryManagerBase > &factoryManager)
Set default factories (used internally by Hierarchy::SetLevel()).
static std::string translate(Teuchos::ParameterList ¶mList, const std::string &defaultVals="")
: Translate ML parameters to MueLu parameter XML string
static void detectBoundaryConditionsSM(RCP< Matrix > &SM_Matrix, RCP< Matrix > &D0_Matrix, magnitudeType rowSumTol, bool useKokkos_, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCrowsKokkos, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCcolsKokkos, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCdomainKokkos, int &BCedges, int &BCnodes, Teuchos::ArrayRCP< bool > &BCrows, Teuchos::ArrayRCP< bool > &BCcols, Teuchos::ArrayRCP< bool > &BCdomain, bool &allEdgesBoundary, bool &allNodesBoundary)
Detect Dirichlet boundary conditions.
static void thresholdedAbs(const RCP< Matrix > &A, const magnitudeType thresholded)
static RCP< Matrix > removeExplicitZeros(const RCP< Matrix > &A, const magnitudeType tolerance, const bool keepDiagonal=true)
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,...