10#ifndef MUELU_REFMAXWELL_DEF_HPP
11#define MUELU_REFMAXWELL_DEF_HPP
17#include "Teuchos_Assert.hpp"
18#include "Teuchos_CompilerCodeTweakMacros.hpp"
19#include "Tpetra_CrsMatrix.hpp"
20#include "Xpetra_CrsMatrix.hpp"
21#include "Xpetra_Map.hpp"
22#include "Xpetra_MatrixMatrix.hpp"
23#include "Xpetra_MultiVector.hpp"
24#include "Xpetra_TripleMatrixMultiply.hpp"
26#include "Xpetra_MatrixUtils.hpp"
30#include "MueLu_AmalgamationFactory.hpp"
31#include "MueLu_RAPFactory.hpp"
32#include "MueLu_SmootherFactory.hpp"
34#include "MueLu_CoalesceDropFactory.hpp"
35#include "MueLu_CoarseMapFactory.hpp"
36#include "MueLu_CoordinatesTransferFactory.hpp"
37#include "MueLu_UncoupledAggregationFactory.hpp"
38#include "MueLu_TentativePFactory.hpp"
39#include "MueLu_SaPFactory.hpp"
40#include "MueLu_AggregationExportFactory.hpp"
41#include "MueLu_Utilities.hpp"
42#include "MueLu_Maxwell_Utils.hpp"
44#include "MueLu_CoalesceDropFactory_kokkos.hpp"
45#include "MueLu_TentativePFactory_kokkos.hpp"
46#include <Kokkos_Core.hpp>
47#include <KokkosSparse_CrsMatrix.hpp>
49#include "MueLu_ZoltanInterface.hpp"
50#include "MueLu_Zoltan2Interface.hpp"
51#include "MueLu_RepartitionHeuristicFactory.hpp"
52#include "MueLu_RepartitionFactory.hpp"
53#include "MueLu_RebalanceAcFactory.hpp"
54#include "MueLu_RebalanceTransferFactory.hpp"
63#include "cuda_profiler_api.h"
67#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
74T
pop(Teuchos::ParameterList &pl, std::string
const &name_in) {
75 T result = pl.get<T>(name_in);
76 pl.remove(name_in,
true);
81T
pop(Teuchos::ParameterList &pl, std::string
const &name_in, T def_value) {
82 T result = pl.get<T>(name_in, def_value);
83 pl.remove(name_in,
false);
88T
pop(Teuchos::ParameterList &pl1, Teuchos::ParameterList &pl2, std::string
const &name_in, T def_value) {
89 return pop(pl2, name_in,
pop(pl1, name_in, def_value));
92template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
94 return SM_Matrix_->getDomainMap();
97template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
99 return SM_Matrix_->getRangeMap();
102template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
103Teuchos::RCP<Teuchos::ParameterList>
106 bool useKokkosDefault = !Node::is_serial;
108 RCP<ParameterList> params = rcp(
new ParameterList(
"RefMaxwell"));
110 params->set<RCP<Matrix>>(
"Dk_1", Teuchos::null);
111 params->set<RCP<Matrix>>(
"Dk_2", Teuchos::null);
112 params->set<RCP<Matrix>>(
"D0", Teuchos::null);
114 params->set<RCP<Matrix>>(
"M1_beta", Teuchos::null);
115 params->set<RCP<Matrix>>(
"M1_alpha", Teuchos::null);
117 params->set<RCP<Matrix>>(
"Ms", Teuchos::null);
119 params->set<RCP<Matrix>>(
"Mk_one", Teuchos::null);
120 params->set<RCP<Matrix>>(
"Mk_1_one", Teuchos::null);
122 params->set<RCP<Matrix>>(
"M1", Teuchos::null);
124 params->set<RCP<Matrix>>(
"invMk_1_invBeta", Teuchos::null);
125 params->set<RCP<Matrix>>(
"invMk_2_invAlpha", Teuchos::null);
127 params->set<RCP<Matrix>>(
"M0inv", Teuchos::null);
129 params->set<RCP<MultiVector>>(
"Nullspace", Teuchos::null);
130 params->set<RCP<RealValuedMultiVector>>(
"Coordinates", Teuchos::null);
132 auto spaceValidator = rcp(
new Teuchos::EnhancedNumberValidator<int>(1, 2));
133 params->set(
"refmaxwell: space number", 1,
"", spaceValidator);
134 params->set(
"verbosity", MasterList::getDefault<std::string>(
"verbosity"));
135 params->set(
"use kokkos refactor", useKokkosDefault);
136 params->set(
"half precision",
false);
137 params->set(
"parameterlist: syntax", MasterList::getDefault<std::string>(
"parameterlist: syntax"));
138 params->set(
"output filename", MasterList::getDefault<std::string>(
"output filename"));
139 params->set(
"print initial parameters", MasterList::getDefault<bool>(
"print initial parameters"));
140 params->set(
"refmaxwell: disable addon", MasterList::getDefault<bool>(
"refmaxwell: disable addon"));
141 params->set(
"refmaxwell: disable addon 22",
true);
142 params->set(
"refmaxwell: mode", MasterList::getDefault<std::string>(
"refmaxwell: mode"));
143 params->set(
"refmaxwell: use as preconditioner", MasterList::getDefault<bool>(
"refmaxwell: use as preconditioner"));
144 params->set(
"refmaxwell: dump matrices", MasterList::getDefault<bool>(
"refmaxwell: dump matrices"));
145 params->set(
"refmaxwell: enable reuse", MasterList::getDefault<bool>(
"refmaxwell: enable reuse"));
146 params->set(
"refmaxwell: skip first (1,1) level", MasterList::getDefault<bool>(
"refmaxwell: skip first (1,1) level"));
147 params->set(
"refmaxwell: skip first (2,2) level",
false);
148 params->set(
"multigrid algorithm",
"Unsmoothed");
149 params->set(
"transpose: use implicit", MasterList::getDefault<bool>(
"transpose: use implicit"));
150 params->set(
"rap: triple product", MasterList::getDefault<bool>(
"rap: triple product"));
151 params->set(
"rap: fix zero diagonals",
true);
152 params->set(
"rap: fix zero diagonals threshold", MasterList::getDefault<double>(
"rap: fix zero diagonals threshold"));
153 params->set(
"fuse prolongation and update", MasterList::getDefault<bool>(
"fuse prolongation and update"));
154 params->set(
"refmaxwell: async transfers", Node::is_gpu);
155 params->set(
"refmaxwell: subsolves on subcommunicators", MasterList::getDefault<bool>(
"refmaxwell: subsolves on subcommunicators"));
156 params->set(
"refmaxwell: subsolves striding", 1);
157 params->set(
"refmaxwell: row sum drop tol (1,1)", MasterList::getDefault<double>(
"aggregation: row sum drop tol"));
158 params->set(
"sync timers",
false);
159 params->set(
"refmaxwell: num iters coarse 11", 1);
160 params->set(
"refmaxwell: num iters 22", 1);
161 params->set(
"refmaxwell: apply BCs to Anodal",
false);
162 params->set(
"refmaxwell: apply BCs to coarse 11",
true);
163 params->set(
"refmaxwell: apply BCs to 22",
true);
164 params->set(
"refmaxwell: max coarse size", 1);
166 ParameterList &precList11 = params->sublist(
"refmaxwell: 11list");
167 precList11.disableRecursiveValidation();
168 ParameterList &precList22 = params->sublist(
"refmaxwell: 22list");
169 precList22.disableRecursiveValidation();
170 ParameterList &userData = params->sublist(
"user data");
171 userData.disableRecursiveValidation();
173 params->set(
"smoother: type",
"CHEBYSHEV");
174 ParameterList &smootherList = params->sublist(
"smoother: params");
175 smootherList.disableRecursiveValidation();
176 params->set(
"smoother: pre type",
"NONE");
177 ParameterList &preSmootherList = params->sublist(
"smoother: pre params");
178 preSmootherList.disableRecursiveValidation();
179 params->set(
"smoother: post type",
"NONE");
180 ParameterList &postSmootherList = params->sublist(
"smoother: post params");
181 postSmootherList.disableRecursiveValidation();
183 ParameterList &matvecParams = params->sublist(
"matvec params");
184 matvecParams.disableRecursiveValidation();
186 ParameterList &importerCoarse11Params = params->sublist(
"refmaxwell: ImporterCoarse11 params");
187 importerCoarse11Params.disableRecursiveValidation();
189 ParameterList &importer22Params = params->sublist(
"refmaxwell: Importer22 params");
190 importer22Params.disableRecursiveValidation();
192 params->set(
"multigrid algorithm",
"unsmoothed");
193 params->set(
"aggregation: type", MasterList::getDefault<std::string>(
"aggregation: type"));
194 params->set(
"aggregation: drop tol", MasterList::getDefault<double>(
"aggregation: drop tol"));
195 params->set(
"aggregation: drop scheme", MasterList::getDefault<std::string>(
"aggregation: drop scheme"));
196 params->set(
"aggregation: distance laplacian algo", MasterList::getDefault<std::string>(
"aggregation: distance laplacian algo"));
197 params->set(
"aggregation: min agg size", MasterList::getDefault<int>(
"aggregation: min agg size"));
198 params->set(
"aggregation: max agg size", MasterList::getDefault<int>(
"aggregation: max agg size"));
199 params->set(
"aggregation: match ML phase1", MasterList::getDefault<bool>(
"aggregation: match ML phase1"));
200 params->set(
"aggregation: match ML phase2a", MasterList::getDefault<bool>(
"aggregation: match ML phase2a"));
201 params->set(
"aggregation: match ML phase2b", MasterList::getDefault<bool>(
"aggregation: match ML phase2b"));
202 params->set(
"aggregation: export visualization data", MasterList::getDefault<bool>(
"aggregation: export visualization data"));
207template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
209 if (list.isType<std::string>(
"parameterlist: syntax") && list.get<std::string>(
"parameterlist: syntax") ==
"ml") {
210 Teuchos::ParameterList newList;
213 RCP<Teuchos::ParameterList> validateParameters = getValidParamterList();
214 for (
auto it = newList2.begin(); it != newList2.end(); ++it) {
215 const std::string &entry_name = it->first;
216 if (validateParameters->isParameter(entry_name)) {
217 ParameterEntry theEntry = newList2.getEntry(entry_name);
218 newList.setEntry(entry_name, theEntry);
223 if (list.isSublist(
"refmaxwell: 11list") && list.sublist(
"refmaxwell: 11list").isSublist(
"edge matrix free: coarse"))
225 if (list.isSublist(
"refmaxwell: 22list"))
230 parameterList_ = list;
231 parameterList_.validateParametersAndSetDefaults(*getValidParamterList());
232 std::string verbosityLevel = parameterList_.get<std::string>(
"verbosity");
234 std::string outputFilename = parameterList_.get<std::string>(
"output filename");
235 if (outputFilename !=
"")
237 if (parameterList_.isType<Teuchos::RCP<Teuchos::FancyOStream>>(
"output stream"))
240 if (parameterList_.get<
bool>(
"print initial parameters"))
241 GetOStream(
static_cast<MsgType>(
Runtime1), 0) << parameterList_ << std::endl;
242 disable_addon_ = parameterList_.get<
bool>(
"refmaxwell: disable addon");
243 disable_addon_22_ = parameterList_.get<
bool>(
"refmaxwell: disable addon 22");
244 mode_ = parameterList_.get<std::string>(
"refmaxwell: mode");
245 use_as_preconditioner_ = parameterList_.get<
bool>(
"refmaxwell: use as preconditioner");
246 dump_matrices_ = parameterList_.get<
bool>(
"refmaxwell: dump matrices");
247 enable_reuse_ = parameterList_.get<
bool>(
"refmaxwell: enable reuse");
248 implicitTranspose_ = parameterList_.get<
bool>(
"transpose: use implicit");
249 fuseProlongationAndUpdate_ = parameterList_.get<
bool>(
"fuse prolongation and update");
250 skipFirst11Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (1,1) level");
251 skipFirst22Level_ = parameterList_.get<
bool>(
"refmaxwell: skip first (2,2) level");
252 if (spaceNumber_ == 1)
253 skipFirst22Level_ =
false;
254 syncTimers_ = parameterList_.get<
bool>(
"sync timers");
255 useKokkos_ = parameterList_.get<
bool>(
"use kokkos refactor");
256 numItersCoarse11_ = parameterList_.get<
int>(
"refmaxwell: num iters coarse 11");
257 numIters22_ = parameterList_.get<
int>(
"refmaxwell: num iters 22");
258 applyBCsToAnodal_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to Anodal");
259 applyBCsToCoarse11_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to coarse 11");
260 applyBCsTo22_ = parameterList_.get<
bool>(
"refmaxwell: apply BCs to 22");
262 precList11_ = parameterList_.sublist(
"refmaxwell: 11list");
263 if (!precList11_.isType<std::string>(
"Preconditioner Type") &&
264 !precList11_.isType<std::string>(
"smoother: type") &&
265 !precList11_.isType<std::string>(
"smoother: pre type") &&
266 !precList11_.isType<std::string>(
"smoother: post type")) {
267 precList11_.set(
"smoother: type",
"CHEBYSHEV");
268 precList11_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
269 precList11_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 5.4);
270 precList11_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
273 precList22_ = parameterList_.sublist(
"refmaxwell: 22list");
274 if (!precList22_.isType<std::string>(
"Preconditioner Type") &&
275 !precList22_.isType<std::string>(
"smoother: type") &&
276 !precList22_.isType<std::string>(
"smoother: pre type") &&
277 !precList22_.isType<std::string>(
"smoother: post type")) {
278 precList22_.set(
"smoother: type",
"CHEBYSHEV");
279 precList22_.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
280 precList22_.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 7.0);
281 precList22_.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
284 if (!parameterList_.isType<std::string>(
"smoother: type") && !parameterList_.isType<std::string>(
"smoother: pre type") && !parameterList_.isType<std::string>(
"smoother: post type")) {
285 list.set(
"smoother: type",
"CHEBYSHEV");
286 list.sublist(
"smoother: params").set(
"chebyshev: degree", 2);
287 list.sublist(
"smoother: params").set(
"chebyshev: ratio eigenvalue", 20.0);
288 list.sublist(
"smoother: params").set(
"chebyshev: eigenvalue max iterations", 30);
292 !precList11_.isType<std::string>(
"Preconditioner Type") &&
293 !precList11_.isParameter(
"reuse: type"))
294 precList11_.set(
"reuse: type",
"full");
296 !precList22_.isType<std::string>(
"Preconditioner Type") &&
297 !precList22_.isParameter(
"reuse: type"))
298 precList22_.set(
"reuse: type",
"full");
301template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
303 using memory_space =
typename Node::device_type::memory_space;
305#ifdef HAVE_MUELU_CUDA
306 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStart();
309 std::string timerLabel;
311 timerLabel =
"compute (reuse)";
313 timerLabel =
"compute";
314 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
324 RCP<ParameterList> params = rcp(
new ParameterList());
325 params->set(
"printLoadBalancingInfo",
true);
326 params->set(
"printCommInfo",
true);
333 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
335 BCrows11_, BCcols22_, BCdomain22_,
336 globalNumberBoundaryUnknowns11_,
337 globalNumberBoundaryUnknowns22_,
338 onlyBoundary11_, onlyBoundary22_);
339 if (spaceNumber_ == 2) {
340 Kokkos::View<bool *, memory_space> BCcolsEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), Dk_1_->getColMap()->getLocalNumElements());
341 Kokkos::View<bool *, memory_space> BCdomainEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), Dk_1_->getDomainMap()->getLocalNumElements());
344 Kokkos::View<bool *, memory_space> BCcolsNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), D0_->getColMap()->getLocalNumElements());
345 Kokkos::View<bool *, memory_space> BCdomainNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"dirichletDomains"), D0_->getDomainMap()->getLocalNumElements());
347 BCdomain22_ = BCdomainNode;
350 GetOStream(
Statistics2) << solverName_ +
"::compute(): Detected " << globalNumberBoundaryUnknowns11_ <<
" BC rows and " << globalNumberBoundaryUnknowns22_ <<
" BC columns." << std::endl;
352 dump(BCrows11_,
"BCrows11.m");
353 dump(BCcols22_,
"BCcols22.m");
354 dump(BCdomain22_,
"BCdomain22.m");
357 if (onlyBoundary11_) {
360 GetOStream(
Warnings0) <<
"All unknowns of the (1,1) block have been detected as boundary unknowns!" << std::endl;
362 setFineLevelSmoother11();
368 dim_ = NodalCoords_->getNumVectors();
375 if (Nullspace11_ != null) {
376 TEUCHOS_ASSERT(Nullspace11_->getMap()->isCompatible(*(SM_Matrix_->getRowMap())));
377 }
else if (NodalCoords_ != null) {
378 Nullspace11_ = buildNullspace(spaceNumber_, BCrows11_, skipFirst11Level_);
380 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
385 RCP<Matrix> A11_nodal;
386 if (skipFirst11Level_) {
388 std::string label(
"D0^T*M1_beta*D0");
391 if (applyBCsToAnodal_) {
395 A11_nodal->setObjectLabel(solverName_ +
" (1,1) A_nodal");
396 dump(A11_nodal,
"A11_nodal.m");
399 M1_beta_ = Teuchos::null;
402 buildProlongator(spaceNumber_, A11_nodal, Nullspace11_, P11_, NullspaceCoarse11_, CoordsCoarse11_);
409 if (Nullspace22_ != null) {
410 TEUCHOS_ASSERT(Nullspace22_->getMap()->isCompatible(*(Dk_1_->getDomainMap())));
411 }
else if (NodalCoords_ != null)
412 Nullspace22_ = buildNullspace(spaceNumber_ - 1, BCdomain22_, skipFirst22Level_);
414 GetOStream(
Errors) << solverName_ +
"::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
419 RCP<Matrix> A22_nodal;
420 if (skipFirst22Level_) {
422 std::string label(
"D0^T*M1_alpha*D0");
425 if (applyBCsToAnodal_) {
429 A22_nodal->setObjectLabel(solverName_ +
" (2,2) A_nodal");
430 dump(A22_nodal,
"A22_nodal.m");
433 M1_alpha_ = Teuchos::null;
436 buildProlongator(spaceNumber_ - 1, A22_nodal, Nullspace22_, P22_, CoarseNullspace22_, Coords22_);
444 buildCoarse11Matrix();
449 int rebalanceStriding, numProcsCoarseA11, numProcsA22;
451 this->determineSubHierarchyCommSizes(doRebalancing, rebalanceStriding, numProcsCoarseA11, numProcsA22);
453 doRebalancing =
false;
456 if (!reuse && doRebalancing)
457 rebalanceCoarse11Matrix(rebalanceStriding, numProcsCoarseA11);
458 if (!coarseA11_.is_null()) {
459 dump(coarseA11_,
"coarseA11.m");
461 dumpCoords(CoordsCoarse11_,
"CoordsCoarse11.m");
462 dump(NullspaceCoarse11_,
"NullspaceCoarse11.m");
467 if (!implicitTranspose_) {
474 if (!coarseA11_.is_null()) {
476 std::string label(
"coarseA11");
477 if (!precList11_.isType<std::string>(
"hierarchy label"))
478 precList11_.set(
"hierarchy label", solverName_ +
" coarse (1,1)");
479 setupSubSolve(HierarchyCoarse11_, thyraPrecOpH_, coarseA11_, NullspaceCoarse11_, CoordsCoarse11_, Material_beta_, precList11_, label, reuse);
485 if (!reuse && applyBCsTo22_) {
486 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC columns of Dk_1" << std::endl;
489 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
491 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
496 if (!onlyBoundary22_) {
497 GetOStream(
Runtime0) << solverName_ +
"::compute(): building MG for (2,2)-block" << std::endl;
500 build22Matrix(reuse, doRebalancing, rebalanceStriding, numProcsA22);
502 if (!P22_.is_null()) {
503 std::string label(
"P22^T*A22*P22");
505 coarseA22_->SetFixedBlockSize(A22_->GetFixedBlockSize());
506 coarseA22_->setObjectLabel(solverName_ +
" coarse (2, 2)");
507 dump(coarseA22_,
"coarseA22.m");
510 if (!reuse && !implicitTranspose_) {
516 if (!A22_.is_null()) {
518 std::string label(
"A22");
519 if (!precList22_.isType<std::string>(
"hierarchy label"))
520 precList22_.set(
"hierarchy label", solverName_ +
" (2,2)");
521 if (!P22_.is_null()) {
522 precList22_.sublist(
"level 1 user data").set(
"A", coarseA22_);
523 precList22_.sublist(
"level 1 user data").set(
"P", P22_);
524 if (!implicitTranspose_)
525 precList22_.sublist(
"level 1 user data").set(
"R", R22_);
526 precList22_.sublist(
"level 1 user data").set(
"Nullspace", CoarseNullspace22_);
527 precList22_.sublist(
"level 1 user data").set(
"Coordinates", Coords22_);
530 int maxCoarseSize = precList22_.get(
"coarse: max size", MasterList::getDefault<int>(
"coarse: max size"));
531 int numRows = Teuchos::as<int>(coarseA22_->getGlobalNumRows());
532 if (maxCoarseSize > numRows)
533 precList22_.set(
"coarse: max size", numRows);
534 int maxLevels = precList22_.get(
"max levels", MasterList::getDefault<int>(
"max levels"));
536 precList22_.set(
"max levels", 2);
537 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, Teuchos::null, Teuchos::null, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
539 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, CoarseNullspace22_, Coords22_, Material_alpha_, precList22_, label, reuse, globalNumberBoundaryUnknowns11_ == 0);
547 if (!reuse && !onlyBoundary22_ && applyBCsTo22_) {
548 GetOStream(
Runtime0) << solverName_ +
"::compute(): nuking BC rows of Dk_1" << std::endl;
551 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
553 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
554 dump(Dk_1_,
"Dk_1_nuked.m");
559 setFineLevelSmoother11();
562 if (!ImporterCoarse11_.is_null()) {
563 RCP<const Import> ImporterP11 = ImportFactory::Build(ImporterCoarse11_->getTargetMap(), P11_->getColMap());
564 toCrsMatrix(P11_)->replaceDomainMapAndImporter(ImporterCoarse11_->getTargetMap(), ImporterP11);
567 if (!Importer22_.is_null()) {
569 DorigDomainMap_ = Dk_1_->getDomainMap();
570 DorigImporter_ = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
572 RCP<const Import> ImporterD = ImportFactory::Build(Importer22_->getTargetMap(), Dk_1_->getColMap());
573 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), ImporterD);
576 if ((!Dk_1_T_.is_null()) &&
578 (!toCrsMatrix(Dk_1_T_)->getCrsGraph()->getImporter().is_null()) &&
579 (!toCrsMatrix(R11_)->getCrsGraph()->getImporter().is_null()) &&
580 (Dk_1_T_->getColMap()->lib() == Xpetra::UseTpetra) &&
581 (R11_->getColMap()->lib() == Xpetra::UseTpetra))
582 Dk_1_T_R11_colMapsMatch_ = Dk_1_T_->getColMap()->isSameAs(*R11_->getColMap());
584 Dk_1_T_R11_colMapsMatch_ =
false;
585 if (Dk_1_T_R11_colMapsMatch_)
586 GetOStream(
Runtime0) << solverName_ +
"::compute(): Dk_1_T and R11 have matching colMaps" << std::endl;
588 asyncTransfers_ = parameterList_.get<
bool>(
"refmaxwell: async transfers");
594 if (parameterList_.isSublist(
"matvec params")) {
595 RCP<ParameterList> matvecParams = rcpFromRef(parameterList_.sublist(
"matvec params"));
601 if (!ImporterCoarse11_.is_null()) ImporterCoarse11_->setDistributorParameters(matvecParams);
602 if (!Importer22_.is_null()) Importer22_->setDistributorParameters(matvecParams);
604 if (!ImporterCoarse11_.is_null() && parameterList_.isSublist(
"refmaxwell: ImporterCoarse11 params")) {
605 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: ImporterCoarse11 params"));
606 ImporterCoarse11_->setDistributorParameters(importerParams);
608 if (!Importer22_.is_null() && parameterList_.isSublist(
"refmaxwell: Importer22 params")) {
609 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist(
"refmaxwell: Importer22 params"));
610 Importer22_->setDistributorParameters(importerParams);
617#ifdef HAVE_MUELU_CUDA
618 if (parameterList_.get<
bool>(
"refmaxwell: cuda profile setup",
false)) cudaProfilerStop();
622template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
625 doRebalancing = parameterList_.get<
bool>(
"refmaxwell: subsolves on subcommunicators");
626 rebalanceStriding = parameterList_.get<
int>(
"refmaxwell: subsolves striding", -1);
627 int numProcs = SM_Matrix_->getDomainMap()->getComm()->getSize();
629 doRebalancing =
false;
641 level.
Set(
"A", coarseA11_);
644 ParameterList repartheurParams;
645 repartheurParams.set(
"repartition: start level", 0);
647 int defaultTargetRows = 10000;
648 repartheurParams.set(
"repartition: min rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
649 repartheurParams.set(
"repartition: target rows per proc", precList11_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
650 repartheurParams.set(
"repartition: min rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
651 repartheurParams.set(
"repartition: target rows per thread", precList11_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
652 repartheurParams.set(
"repartition: max imbalance", precList11_.get<
double>(
"repartition: max imbalance", 1.1));
653 repartheurFactory->SetParameterList(repartheurParams);
655 level.
Request(
"number of partitions", repartheurFactory.get());
656 repartheurFactory->Build(level);
657 numProcsCoarseA11 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
658 numProcsCoarseA11 = std::min(numProcsCoarseA11, numProcs);
668 level.
Set(
"Map", Dk_1_->getDomainMap());
671 ParameterList repartheurParams;
672 repartheurParams.set(
"repartition: start level", 0);
673 repartheurParams.set(
"repartition: use map",
true);
675 int defaultTargetRows = 10000;
676 repartheurParams.set(
"repartition: min rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
677 repartheurParams.set(
"repartition: target rows per proc", precList22_.get<
int>(
"repartition: target rows per proc", defaultTargetRows));
678 repartheurParams.set(
"repartition: min rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
679 repartheurParams.set(
"repartition: target rows per thread", precList22_.get<
int>(
"repartition: target rows per thread", defaultTargetRows));
681 repartheurFactory->SetParameterList(repartheurParams);
683 level.
Request(
"number of partitions", repartheurFactory.get());
684 repartheurFactory->Build(level);
685 numProcsA22 = level.
Get<
int>(
"number of partitions", repartheurFactory.get());
686 numProcsA22 = std::min(numProcsA22, numProcs);
689 if (rebalanceStriding >= 1) {
690 TEUCHOS_ASSERT(rebalanceStriding * numProcsCoarseA11 <= numProcs);
691 TEUCHOS_ASSERT(rebalanceStriding * numProcsA22 <= numProcs);
692 if (rebalanceStriding * (numProcsCoarseA11 + numProcsA22) > numProcs) {
693 GetOStream(
Warnings0) << solverName_ +
"::compute(): Disabling striding = " << rebalanceStriding <<
", since coarseA11 needs " << numProcsCoarseA11
694 <<
" procs and A22 needs " << numProcsA22 <<
" procs." << std::endl;
695 rebalanceStriding = -1;
697 int lclBadMatrixDistribution = (coarseA11_->getLocalNumEntries() == 0) || (Dk_1_->getDomainMap()->getLocalNumElements() == 0);
698 int gblBadMatrixDistribution =
false;
699 MueLu_maxAll(SM_Matrix_->getDomainMap()->getComm(), lclBadMatrixDistribution, gblBadMatrixDistribution);
700 if (gblBadMatrixDistribution) {
701 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;
702 rebalanceStriding = -1;
706 if ((numProcsCoarseA11 < 0) || (numProcsA22 < 0) || (numProcsCoarseA11 + numProcsA22 > numProcs)) {
707 std::stringstream ss;
708 ss << solverName_ +
"::compute(): Partition heuristic resulted "
709 <<
"in undesirable number of partitions: " << numProcsCoarseA11 <<
", " << numProcsA22 <<
".";
711 if (numProcsCoarseA11 < 0)
712 numProcsCoarseA11 = numProcs;
714 numProcsA22 = numProcs;
716 double ratioCoarseA11 = ((double)numProcsCoarseA11) / ((double)(numProcsCoarseA11 + numProcsA22));
717 double ratioA22 = ((double)numProcsA22) / ((double)(numProcsCoarseA11 + numProcsA22));
718 numProcsCoarseA11 = std::round(ratioCoarseA11 * numProcs);
719 numProcsA22 = std::round(ratioA22 * numProcs);
721 if (numProcsCoarseA11 == 0) {
722 numProcsCoarseA11 = 1;
723 numProcsA22 = numProcs - 1;
725 if (numProcsA22 == 0) {
726 numProcsCoarseA11 = numProcs - 1;
730 ss <<
". Adjusting to fit: " << numProcsCoarseA11 <<
", " << numProcsA22 << std::endl;
733 TEUCHOS_ASSERT_INEQUALITY(numProcsCoarseA11, >, 0);
734 TEUCHOS_ASSERT_INEQUALITY(numProcsA22, >, 0);
735 TEUCHOS_ASSERT_EQUALITY(numProcsCoarseA11 + numProcsA22, numProcs);
739 doRebalancing =
false;
743template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
746 if (spaceNumber == 0)
747 return Teuchos::null;
749 std::string timerLabel;
750 if (spaceNumber == spaceNumber_) {
751 if (skipFirst11Level_)
752 timerLabel =
"Build coarse addon matrix 11";
754 timerLabel =
"Build addon matrix 11";
756 timerLabel =
"Build addon matrix 22";
758 RCP<Teuchos::TimeMonitor> tmAddon = getTimer(timerLabel);
762 RCP<Matrix> lumpedInverse;
763 if (spaceNumber == spaceNumber_) {
765 TEUCHOS_TEST_FOR_EXCEPTION(invMk_1_invBeta_ == Teuchos::null, std::invalid_argument,
767 "::buildCoarse11Matrix(): Inverse of "
768 "lumped mass matrix required for add-on (i.e. invMk_1_invBeta_ is null)");
769 lumpedInverse = invMk_1_invBeta_;
771 if (skipFirst11Level_) {
774 Zaux = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Mk_one_,
false, *P11_,
false, Zaux, GetOStream(
Runtime0),
true,
true);
776 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Zaux,
false, Z, GetOStream(
Runtime0),
true,
true);
779 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *Mk_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
782 }
else if (spaceNumber == spaceNumber_ - 1) {
784 TEUCHOS_TEST_FOR_EXCEPTION(invMk_2_invAlpha_ == Teuchos::null, std::invalid_argument,
786 "::buildCoarse11Matrix(): Inverse of "
787 "lumped mass matrix required for add-on (i.e. invMk_2_invAlpha_ is null)");
788 lumpedInverse = invMk_2_invAlpha_;
791 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_2_,
true, *Mk_1_one_,
false, Z, GetOStream(
Runtime0),
true,
true);
795 if (lumpedInverse->getGlobalMaxNumRowEntries() <= 1) {
798 RCP<Vector> diag = VectorFactory::Build(lumpedInverse->getRowMap());
799 lumpedInverse->getLocalDiagCopy(*diag);
801 ArrayRCP<Scalar> diagVals = diag->getDataNonConst(0);
802 for (
size_t j = 0; j < diag->getMap()->getLocalNumElements(); j++) {
803 diagVals[j] = Teuchos::ScalarTraits<Scalar>::squareroot(diagVals[j]);
806 if (Z->getRowMap()->isSameAs(*(diag->getMap())))
809 RCP<Import> importer = ImportFactory::Build(diag->getMap(), Z->getRowMap());
810 RCP<Vector> diag2 = VectorFactory::Build(Z->getRowMap());
811 diag2->doImport(*diag, *importer, Xpetra::INSERT);
812 Z->leftScale(*diag2);
814 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *Z,
false, addon, GetOStream(
Runtime0),
true,
true);
815 }
else if (parameterList_.get<
bool>(
"rap: triple product",
false) ==
false) {
818 C2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*lumpedInverse,
false, *Z,
false, C2, GetOStream(
Runtime0),
true,
true);
820 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z,
true, *C2,
false, addon, GetOStream(
Runtime0),
true,
true);
822 addon = MatrixFactory::Build(Z->getDomainMap());
824 Xpetra::TripleMatrixMultiply<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
825 MultiplyRAP(*Z,
true, *lumpedInverse,
false, *Z,
false, *addon,
true,
true);
830template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
832 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build coarse (1,1) matrix");
834 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
838 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *P11_,
false, temp, GetOStream(
Runtime0),
true,
true);
839 if (ImporterCoarse11_.is_null())
840 coarseA11_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, coarseA11_, GetOStream(
Runtime0),
true,
true);
843 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
845 RCP<const Map> map = ImporterCoarse11_->getTargetMap()->removeEmptyProcesses();
846 temp2->removeEmptyProcessesInPlace(map);
847 if (!temp2.is_null() && temp2->getRowMap().is_null())
848 temp2 = Teuchos::null;
852 if (!disable_addon_) {
855 if (!coarseA11_.is_null() && Addon11_.is_null()) {
856 addon = buildAddon(spaceNumber_);
863 if (!coarseA11_.is_null()) {
865 RCP<Matrix> newCoarseA11;
866 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*coarseA11_,
false, one, *addon,
false, one, newCoarseA11, GetOStream(
Runtime0));
867 newCoarseA11->fillComplete();
868 coarseA11_ = newCoarseA11;
872 if (!coarseA11_.is_null() && !skipFirst11Level_) {
873 ArrayRCP<bool> coarseA11BCrows;
874 coarseA11BCrows.resize(coarseA11_->getRowMap()->getLocalNumElements());
875 for (
size_t i = 0; i < BCdomain22_.size(); i++)
876 for (
size_t k = 0; k < dim_; k++)
877 coarseA11BCrows[i * dim_ + k] = BCdomain22_(i);
878 magnitudeType rowSumTol = parameterList_.get<
double>(
"refmaxwell: row sum drop tol (1,1)");
881 if (applyBCsToCoarse11_)
885 if (!coarseA11_.is_null()) {
891 bool fixZeroDiagonal = !applyBCsToAnodal_;
892 if (precList11_.isParameter(
"rap: fix zero diagonals"))
893 fixZeroDiagonal = precList11_.get<
bool>(
"rap: fix zero diagonals");
895 if (fixZeroDiagonal) {
898 if (precList11_.isType<
magnitudeType>(
"rap: fix zero diagonals threshold"))
899 threshold = precList11_.get<
magnitudeType>(
"rap: fix zero diagonals threshold");
900 else if (precList11_.isType<
double>(
"rap: fix zero diagonals threshold"))
901 threshold = Teuchos::as<magnitudeType>(precList11_.get<
double>(
"rap: fix zero diagonals threshold"));
902 if (precList11_.isType<
double>(
"rap: fix zero diagonals replacement"))
903 replacement = Teuchos::as<Scalar>(precList11_.get<
double>(
"rap: fix zero diagonals replacement"));
904 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(coarseA11_,
true, GetOStream(
Warnings1), threshold, replacement);
908 coarseA11_->SetFixedBlockSize(dim_);
909 if (skipFirst11Level_)
910 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
912 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
916template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
921 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Rebalance coarseA11");
923 Level fineLevel, coarseLevel;
929 coarseLevel.
Set(
"A", coarseA11_);
930 coarseLevel.
Set(
"P", P11_);
931 coarseLevel.
Set(
"Coordinates", CoordsCoarse11_);
932 if (!NullspaceCoarse11_.is_null())
933 coarseLevel.
Set(
"Nullspace", NullspaceCoarse11_);
934 coarseLevel.
Set(
"number of partitions", numProcsCoarseA11);
935 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
937 coarseLevel.
setlib(coarseA11_->getDomainMap()->lib());
938 fineLevel.
setlib(coarseA11_->getDomainMap()->lib());
939 coarseLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
940 fineLevel.setObjectLabel(solverName_ +
" coarse (1,1)");
942 std::string partName = precList11_.get<std::string>(
"repartition: partitioner",
"zoltan2");
943 RCP<Factory> partitioner;
944 if (partName ==
"zoltan") {
945#ifdef HAVE_MUELU_ZOLTAN
952 }
else if (partName ==
"zoltan2") {
953#ifdef HAVE_MUELU_ZOLTAN2
955 ParameterList partParams;
956 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList11_.sublist(
"repartition: params",
false)));
957 partParams.set(
"ParameterList", partpartParams);
958 partitioner->SetParameterList(partParams);
966 ParameterList repartParams;
967 repartParams.set(
"repartition: print partition distribution", precList11_.get<
bool>(
"repartition: print partition distribution",
false));
968 repartParams.set(
"repartition: remap parts", precList11_.get<
bool>(
"repartition: remap parts",
true));
969 if (rebalanceStriding >= 1) {
970 bool acceptPart = (SM_Matrix_->getDomainMap()->getComm()->getRank() % rebalanceStriding) == 0;
971 if (SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsCoarseA11 * rebalanceStriding)
973 repartParams.set(
"repartition: remap accept partition", acceptPart);
975 repartFactory->SetParameterList(repartParams);
977 repartFactory->SetFactory(
"Partition", partitioner);
980 ParameterList newPparams;
981 newPparams.set(
"type",
"Interpolation");
982 newPparams.set(
"repartition: rebalance P and R", precList11_.get<
bool>(
"repartition: rebalance P and R",
false));
983 newPparams.set(
"repartition: use subcommunicators",
true);
984 newPparams.set(
"repartition: rebalance Nullspace", !NullspaceCoarse11_.is_null());
986 if (!NullspaceCoarse11_.is_null())
988 newP->SetParameterList(newPparams);
989 newP->SetFactory(
"Importer", repartFactory);
992 ParameterList rebAcParams;
993 rebAcParams.set(
"repartition: use subcommunicators",
true);
994 newA->SetParameterList(rebAcParams);
995 newA->SetFactory(
"Importer", repartFactory);
997 coarseLevel.
Request(
"P", newP.get());
998 coarseLevel.
Request(
"Importer", repartFactory.get());
999 coarseLevel.
Request(
"A", newA.get());
1000 coarseLevel.
Request(
"Coordinates", newP.get());
1001 if (!NullspaceCoarse11_.is_null())
1002 coarseLevel.
Request(
"Nullspace", newP.get());
1003 repartFactory->Build(coarseLevel);
1005 if (!precList11_.get<
bool>(
"repartition: rebalance P and R",
false))
1006 ImporterCoarse11_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1007 P11_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1008 coarseA11_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1009 CoordsCoarse11_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1010 if (!NullspaceCoarse11_.is_null())
1011 NullspaceCoarse11_ = coarseLevel.
Get<RCP<MultiVector>>(
"Nullspace", newP.get());
1013 if (!coarseA11_.is_null()) {
1015 coarseA11_->SetFixedBlockSize(dim_);
1016 if (skipFirst11Level_)
1017 coarseA11_->setObjectLabel(solverName_ +
" coarse (1,1)");
1019 coarseA11_->setObjectLabel(solverName_ +
" (1,1)");
1022 coarseA11_AP_reuse_data_ = Teuchos::null;
1023 coarseA11_RAP_reuse_data_ = Teuchos::null;
1025 if (!disable_addon_ && enable_reuse_) {
1027 RCP<const Import> ImporterCoarse11 = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1028 RCP<const Map> targetMap = ImporterCoarse11->getTargetMap();
1029 ParameterList XpetraList;
1030 XpetraList.set(
"Restrict Communicator",
true);
1031 Addon11_ = MatrixFactory::Build(Addon11_, *ImporterCoarse11, *ImporterCoarse11, targetMap, targetMap, rcp(&XpetraList,
false));
1036template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1039 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1041 Level fineLevel, coarseLevel;
1047 fineLevel.
Set(
"A", SM_Matrix_);
1048 coarseLevel.
Set(
"P", Dk_1_);
1049 coarseLevel.
Set(
"Coordinates", Coords22_);
1051 coarseLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1052 fineLevel.
setlib(SM_Matrix_->getDomainMap()->lib());
1053 coarseLevel.setObjectLabel(solverName_ +
" (2,2)");
1054 fineLevel.setObjectLabel(solverName_ +
" (2,2)");
1056 RCP<RAPFactory> rapFact = rcp(
new RAPFactory());
1057 ParameterList rapList = *(rapFact->GetValidParameterList());
1058 rapList.set(
"transpose: use implicit",
true);
1059 rapList.set(
"rap: fix zero diagonals", parameterList_.get<
bool>(
"rap: fix zero diagonals",
true));
1060 rapList.set(
"rap: fix zero diagonals threshold", parameterList_.get<
double>(
"rap: fix zero diagonals threshold", Teuchos::ScalarTraits<double>::eps()));
1061 rapList.set(
"rap: triple product", parameterList_.get<
bool>(
"rap: triple product",
false));
1062 rapFact->SetParameterList(rapList);
1064 if (!A22_AP_reuse_data_.is_null()) {
1065 coarseLevel.
AddKeepFlag(
"AP reuse data", rapFact.get());
1066 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"AP reuse data", A22_AP_reuse_data_, rapFact.get());
1068 if (!A22_RAP_reuse_data_.is_null()) {
1069 coarseLevel.
AddKeepFlag(
"RAP reuse data", rapFact.get());
1070 coarseLevel.
Set<Teuchos::RCP<Teuchos::ParameterList>>(
"RAP reuse data", A22_RAP_reuse_data_, rapFact.get());
1074 if (doRebalancing) {
1075 coarseLevel.
Set(
"number of partitions", numProcsA22);
1076 coarseLevel.
Set(
"repartition: heuristic target rows per process", 1000);
1078 std::string partName = precList22_.get<std::string>(
"repartition: partitioner",
"zoltan2");
1079 RCP<Factory> partitioner;
1080 if (partName ==
"zoltan") {
1081#ifdef HAVE_MUELU_ZOLTAN
1083 partitioner->SetFactory(
"A", rapFact);
1089 }
else if (partName ==
"zoltan2") {
1090#ifdef HAVE_MUELU_ZOLTAN2
1092 ParameterList partParams;
1093 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(precList22_.sublist(
"repartition: params",
false)));
1094 partParams.set(
"ParameterList", partpartParams);
1095 partitioner->SetParameterList(partParams);
1096 partitioner->SetFactory(
"A", rapFact);
1104 ParameterList repartParams;
1105 repartParams.set(
"repartition: print partition distribution", precList22_.get<
bool>(
"repartition: print partition distribution",
false));
1106 repartParams.set(
"repartition: remap parts", precList22_.get<
bool>(
"repartition: remap parts",
true));
1107 if (rebalanceStriding >= 1) {
1108 bool acceptPart = ((SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank()) % rebalanceStriding) == 0;
1109 if (SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsA22 * rebalanceStriding)
1112 TEUCHOS_ASSERT(coarseA11_.is_null());
1113 repartParams.set(
"repartition: remap accept partition", acceptPart);
1115 repartParams.set(
"repartition: remap accept partition", coarseA11_.is_null());
1116 repartFactory->SetParameterList(repartParams);
1117 repartFactory->SetFactory(
"A", rapFact);
1119 repartFactory->SetFactory(
"Partition", partitioner);
1122 ParameterList newPparams;
1123 newPparams.set(
"type",
"Interpolation");
1124 newPparams.set(
"repartition: rebalance P and R", precList22_.get<
bool>(
"repartition: rebalance P and R",
false));
1125 newPparams.set(
"repartition: use subcommunicators",
true);
1126 newPparams.set(
"repartition: rebalance Nullspace",
false);
1128 newP->SetParameterList(newPparams);
1129 newP->SetFactory(
"Importer", repartFactory);
1132 ParameterList rebAcParams;
1133 rebAcParams.set(
"repartition: use subcommunicators",
true);
1134 newA->SetParameterList(rebAcParams);
1135 newA->SetFactory(
"A", rapFact);
1136 newA->SetFactory(
"Importer", repartFactory);
1138 coarseLevel.
Request(
"P", newP.get());
1139 coarseLevel.
Request(
"Importer", repartFactory.get());
1140 coarseLevel.
Request(
"A", newA.get());
1141 coarseLevel.
Request(
"Coordinates", newP.get());
1142 rapFact->Build(fineLevel, coarseLevel);
1143 repartFactory->Build(coarseLevel);
1145 if (!precList22_.get<
bool>(
"repartition: rebalance P and R",
false))
1146 Importer22_ = coarseLevel.
Get<RCP<const Import>>(
"Importer", repartFactory.get());
1147 Dk_1_ = coarseLevel.
Get<RCP<Matrix>>(
"P", newP.get());
1148 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", newA.get());
1149 Coords22_ = coarseLevel.
Get<RCP<RealValuedMultiVector>>(
"Coordinates", newP.get());
1151 if (!P22_.is_null()) {
1158 coarseLevel.
Request(
"A", rapFact.get());
1159 if (enable_reuse_) {
1160 coarseLevel.
Request(
"AP reuse data", rapFact.get());
1161 coarseLevel.
Request(
"RAP reuse data", rapFact.get());
1164 A22_ = coarseLevel.
Get<RCP<Matrix>>(
"A", rapFact.get());
1166 if (enable_reuse_) {
1167 if (coarseLevel.
IsAvailable(
"AP reuse data", rapFact.get()))
1168 A22_AP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"AP reuse data", rapFact.get());
1169 if (coarseLevel.
IsAvailable(
"RAP reuse data", rapFact.get()))
1170 A22_RAP_reuse_data_ = coarseLevel.
Get<RCP<ParameterList>>(
"RAP reuse data", rapFact.get());
1174 RCP<Teuchos::TimeMonitor> tm = getTimer(
"Build A22");
1175 if (Importer22_.is_null()) {
1177 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1178 if (!implicitTranspose_)
1179 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1181 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, A22_, GetOStream(
Runtime0),
true,
true);
1184 RCP<const Import> Dimporter = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
1185 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(DorigDomainMap_, DorigImporter_);
1187 RCP<Matrix> temp, temp2;
1188 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_,
false, *Dk_1_,
false, temp, GetOStream(
Runtime0),
true,
true);
1189 if (!implicitTranspose_)
1190 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_,
false, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1192 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_,
true, *temp,
false, temp2, GetOStream(
Runtime0),
true,
true);
1195 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), Dimporter);
1197 ParameterList XpetraList;
1198 XpetraList.set(
"Restrict Communicator",
true);
1199 XpetraList.set(
"Timer Label",
"MueLu::RebalanceA22");
1200 RCP<const Map> targetMap = Importer22_->getTargetMap();
1201 A22_ = MatrixFactory::Build(temp2, *Importer22_, *Importer22_, targetMap, targetMap, rcp(&XpetraList,
false));
1205 if (not A22_.is_null() and not disable_addon_22_ and spaceNumber_ > 1) {
1206 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1208 RCP<Matrix> addon22 = buildAddon(spaceNumber_ - 1);
1212 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A22_,
false, one, *addon22,
false, one, newA22, GetOStream(
Runtime0));
1213 newA22->fillComplete();
1217 if (!A22_.is_null()) {
1218 dump(A22_,
"A22.m");
1219 A22_->setObjectLabel(solverName_ +
" (2,2)");
1221 if (spaceNumber_ - 1 == 0)
1222 A22_->SetFixedBlockSize(1);
1224 A22_->SetFixedBlockSize(dim_);
1228template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1231 RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(
new FactoryManager());
1234 level.setObjectLabel(solverName_ +
" (1,1)");
1235 level.
Set(
"A", SM_Matrix_);
1236 level.
setlib(SM_Matrix_->getDomainMap()->lib());
1238 level.
Set(
"NodeMatrix", A22_);
1239 level.
Set(
"D0", Dk_1_);
1241 if ((parameterList_.get<std::string>(
"smoother: pre type") !=
"NONE") && (parameterList_.get<std::string>(
"smoother: post type") !=
"NONE")) {
1242 std::string preSmootherType = parameterList_.get<std::string>(
"smoother: pre type");
1243 std::string postSmootherType = parameterList_.get<std::string>(
"smoother: post type");
1245 ParameterList preSmootherList, postSmootherList;
1246 if (parameterList_.isSublist(
"smoother: pre params"))
1247 preSmootherList = parameterList_.sublist(
"smoother: pre params");
1248 if (parameterList_.isSublist(
"smoother: post params"))
1249 postSmootherList = parameterList_.sublist(
"smoother: post params");
1251 RCP<SmootherPrototype> preSmootherPrototype = rcp(
new TrilinosSmoother(preSmootherType, preSmootherList));
1252 RCP<SmootherPrototype> postSmootherPrototype = rcp(
new TrilinosSmoother(postSmootherType, postSmootherList));
1253 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(preSmootherPrototype, postSmootherPrototype));
1255 level.
Request(
"PreSmoother", smootherFact.get());
1256 level.
Request(
"PostSmoother", smootherFact.get());
1257 if (enable_reuse_) {
1258 ParameterList smootherFactoryParams;
1259 smootherFactoryParams.set(
"keep smoother data",
true);
1260 smootherFact->SetParameterList(smootherFactoryParams);
1261 level.
Request(
"PreSmoother data", smootherFact.get());
1262 level.
Request(
"PostSmoother data", smootherFact.get());
1263 if (!PreSmootherData11_.is_null())
1264 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1265 if (!PostSmootherData11_.is_null())
1266 level.
Set(
"PostSmoother data", PostSmootherData11_, smootherFact.get());
1268 smootherFact->Build(level);
1269 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1270 PostSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PostSmoother", smootherFact.get());
1271 if (enable_reuse_) {
1272 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1273 PostSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PostSmoother data", smootherFact.get());
1276 std::string smootherType = parameterList_.get<std::string>(
"smoother: type");
1278 ParameterList smootherList;
1279 if (parameterList_.isSublist(
"smoother: params"))
1280 smootherList = parameterList_.sublist(
"smoother: params");
1282 RCP<SmootherPrototype> smootherPrototype = rcp(
new TrilinosSmoother(smootherType, smootherList));
1283 RCP<SmootherFactory> smootherFact = rcp(
new SmootherFactory(smootherPrototype));
1284 level.
Request(
"PreSmoother", smootherFact.get());
1285 if (enable_reuse_) {
1286 ParameterList smootherFactoryParams;
1287 smootherFactoryParams.set(
"keep smoother data",
true);
1288 smootherFact->SetParameterList(smootherFactoryParams);
1289 level.
Request(
"PreSmoother data", smootherFact.get());
1290 if (!PreSmootherData11_.is_null())
1291 level.
Set(
"PreSmoother data", PreSmootherData11_, smootherFact.get());
1293 smootherFact->Build(level);
1294 PreSmoother11_ = level.
Get<RCP<SmootherBase>>(
"PreSmoother", smootherFact.get());
1295 PostSmoother11_ = PreSmoother11_;
1297 PreSmootherData11_ = level.
Get<RCP<SmootherPrototype>>(
"PreSmoother data", smootherFact.get());
1301template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1303 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer(
"Allocate MVs");
1306 if (!R11_.is_null())
1307 P11res_ = MultiVectorFactory::Build(R11_->getRangeMap(), numVectors);
1309 P11res_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1310 P11res_->setObjectLabel(
"P11res");
1312 if (Dk_1_T_R11_colMapsMatch_) {
1313 DTR11Tmp_ = MultiVectorFactory::Build(R11_->getColMap(), numVectors);
1314 DTR11Tmp_->setObjectLabel(
"DTR11Tmp");
1316 if (!ImporterCoarse11_.is_null()) {
1317 P11resTmp_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1318 P11resTmp_->setObjectLabel(
"P11resTmp");
1319 P11x_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1321 P11x_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1322 P11x_->setObjectLabel(
"P11x");
1325 if (!Dk_1_T_.is_null())
1326 Dres_ = MultiVectorFactory::Build(Dk_1_T_->getRangeMap(), numVectors);
1328 Dres_ = MultiVectorFactory::Build(Dk_1_->getDomainMap(), numVectors);
1329 Dres_->setObjectLabel(
"Dres");
1331 if (!Importer22_.is_null()) {
1332 DresTmp_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1333 DresTmp_->setObjectLabel(
"DresTmp");
1334 Dx_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1335 }
else if (!onlyBoundary22_)
1336 Dx_ = MultiVectorFactory::Build(A22_->getDomainMap(), numVectors);
1338 Dx_->setObjectLabel(
"Dx");
1340 if (!coarseA11_.is_null()) {
1341 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
1342 P11resSubComm_ = MultiVectorFactory::Build(P11resTmp_, Teuchos::View);
1344 P11resSubComm_ = MultiVectorFactory::Build(P11res_, Teuchos::View);
1345 P11resSubComm_->replaceMap(coarseA11_->getRangeMap());
1346 P11resSubComm_->setObjectLabel(
"P11resSubComm");
1348 P11xSubComm_ = MultiVectorFactory::Build(P11x_, Teuchos::View);
1349 P11xSubComm_->replaceMap(coarseA11_->getDomainMap());
1350 P11xSubComm_->setObjectLabel(
"P11xSubComm");
1353 if (!A22_.is_null()) {
1354 if (!Importer22_.is_null() && !implicitTranspose_)
1355 DresSubComm_ = MultiVectorFactory::Build(DresTmp_, Teuchos::View);
1357 DresSubComm_ = MultiVectorFactory::Build(Dres_, Teuchos::View);
1358 DresSubComm_->replaceMap(A22_->getRangeMap());
1359 DresSubComm_->setObjectLabel(
"DresSubComm");
1361 DxSubComm_ = MultiVectorFactory::Build(Dx_, Teuchos::View);
1362 DxSubComm_->replaceMap(A22_->getDomainMap());
1363 DxSubComm_->setObjectLabel(
"DxSubComm");
1366 if (asyncTransfers_) {
1367 if (!toCrsMatrix(P11_)->getCrsGraph()->getImporter().is_null())
1368 P11x_colmap_ = MultiVectorFactory::Build(P11_->getColMap(), numVectors);
1369 if (!toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter().is_null())
1370 Dx_colmap_ = MultiVectorFactory::Build(Dk_1_->getColMap(), numVectors);
1373 residual_ = MultiVectorFactory::Build(SM_Matrix_->getDomainMap(), numVectors);
1374 residual_->setObjectLabel(
"residual");
1377template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1379 if (dump_matrices_ && !A.is_null()) {
1380 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1381 Xpetra::IO<SC, LO, GO, NO>::Write(name, *A);
1385template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1387 if (dump_matrices_ && !X.is_null()) {
1388 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1389 Xpetra::IO<SC, LO, GO, NO>::Write(name, *X);
1393template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1395 if (dump_matrices_ && !X.is_null()) {
1396 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1397 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, *X);
1401template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1403 if (dump_matrices_) {
1404 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1405 std::ofstream out(name);
1406 for (
size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
1407 out << v[i] <<
"\n";
1411template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1413 if (dump_matrices_) {
1414 GetOStream(
Runtime0) <<
"Dumping to " << name << std::endl;
1415 std::ofstream out(name);
1416 auto vH = Kokkos::create_mirror_view(v);
1417 Kokkos::deep_copy(vH, v);
1418 out <<
"%%MatrixMarket matrix array real general\n"
1419 << vH.extent(0) <<
" 1\n";
1420 for (
size_t i = 0; i < vH.size(); i++)
1421 out << vH[i] <<
"\n";
1425template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1429 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1431 if (comm.is_null()) {
1433 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1434 SM_Matrix_->getRowMap()->getComm()->barrier();
1436 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1439 Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name +
"_barrier")));
1442 return Teuchos::rcp(
new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(
"MueLu " + solverName_ +
": " + name)));
1446 return Teuchos::null;
1449template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1451 buildNullspace(
const int spaceNumber,
const Kokkos::View<bool *, typename Node::device_type> &bcs,
const bool applyBCs) {
1452 std::string spaceLabel;
1453 if (spaceNumber == 0)
1454 spaceLabel =
"nodal";
1455 else if (spaceNumber == 1)
1456 spaceLabel =
"edge";
1457 else if (spaceNumber == 2)
1458 spaceLabel =
"face";
1460 TEUCHOS_ASSERT(
false);
1461 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1464 RCP<Teuchos::TimeMonitor> tm;
1465 if (spaceNumber > 0) {
1466 tm = getTimer(
"nullspace " + spaceLabel);
1467 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" nullspace" << std::endl;
1470 if (spaceNumber == 0) {
1471 return Teuchos::null;
1473 }
else if (spaceNumber == 1) {
1474 RCP<MultiVector> CoordsSC;
1476 RCP<MultiVector> Nullspace = MultiVectorFactory::Build(D0_->getRowMap(), NodalCoords_->getNumVectors());
1477 D0_->apply(*CoordsSC, *Nullspace);
1479 bool normalize = parameterList_.get<
bool>(
"refmaxwell: normalize nullspace", MasterList::getDefault<bool>(
"refmaxwell: normalize nullspace"));
1484 ArrayRCP<ArrayRCP<const Scalar>> localNullspace(dim_);
1485 for (
size_t i = 0; i < dim_; i++)
1486 localNullspace[i] = Nullspace->getData(i);
1487 coordinateType localMinLen = Teuchos::ScalarTraits<coordinateType>::rmax();
1488 coordinateType localMeanLen = Teuchos::ScalarTraits<coordinateType>::zero();
1489 coordinateType localMaxLen = Teuchos::ScalarTraits<coordinateType>::zero();
1490 for (
size_t j = 0; j < Nullspace->getMap()->getLocalNumElements(); j++) {
1491 Scalar lenSC = Teuchos::ScalarTraits<Scalar>::zero();
1492 for (
size_t i = 0; i < dim_; i++)
1493 lenSC += localNullspace[i][j] * localNullspace[i][j];
1494 coordinateType len = Teuchos::as<coordinateType>(Teuchos::ScalarTraits<Scalar>::real(Teuchos::ScalarTraits<Scalar>::squareroot(lenSC)));
1495 localMinLen = std::min(localMinLen, len);
1496 localMaxLen = std::max(localMaxLen, len);
1497 localMeanLen += len;
1500 RCP<const Teuchos::Comm<int>> comm = Nullspace->getMap()->getComm();
1504 meanLen /= Nullspace->getMap()->getGlobalNumElements();
1508 GetOStream(
Statistics2) <<
"Edge length (min/mean/max): " << minLen <<
" / " << meanLen <<
" / " << maxLen << std::endl;
1513 GetOStream(
Runtime0) << solverName_ +
"::compute(): normalizing nullspace" << std::endl;
1515 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1517 Array<Scalar> normsSC(NodalCoords_->getNumVectors(), one / Teuchos::as<Scalar>(meanLen));
1518 Nullspace->scale(normsSC());
1525 dump(Nullspace,
"nullspaceEdge.m");
1529 }
else if (spaceNumber == 2) {
1530 using ATS = KokkosKernels::ArithTraits<Scalar>;
1531 using impl_Scalar =
typename ATS::val_type;
1532 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1533 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1535 RCP<Matrix> facesToNodes;
1537 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1542 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1548 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1555 RCP<RealValuedMultiVector> ghostedNodalCoordinates;
1556 auto importer = facesToNodes->getCrsGraph()->getImporter();
1557 if (!importer.is_null()) {
1558 ghostedNodalCoordinates = Xpetra::MultiVectorFactory<coordinateType, LocalOrdinal, GlobalOrdinal, Node>::Build(importer->getTargetMap(), dim_);
1559 ghostedNodalCoordinates->doImport(*NodalCoords_, *importer, Xpetra::INSERT);
1561 ghostedNodalCoordinates = NodalCoords_;
1563 RCP<MultiVector> Nullspace = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(facesToNodes->getRangeMap(), dim_);
1565 auto facesToNodesLocal = facesToNodes->getLocalMatrixDevice();
1566 auto localNodalCoordinates = ghostedNodalCoordinates->getLocalViewDevice(Tpetra::Access::ReadOnly);
1567 auto localFaceNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1570 Kokkos::parallel_for(
1571 solverName_ +
"::buildFaceProjection_nullspace",
1572 range_type(0, Nullspace->getMap()->getLocalNumElements()),
1573 KOKKOS_LAMBDA(
const size_t f) {
1574 size_t n0 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f));
1575 size_t n1 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 1);
1576 size_t n2 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 2);
1577 impl_Scalar elementNullspace00 = localNodalCoordinates(n1, 0) - localNodalCoordinates(n0, 0);
1578 impl_Scalar elementNullspace10 = localNodalCoordinates(n2, 0) - localNodalCoordinates(n0, 0);
1579 impl_Scalar elementNullspace01 = localNodalCoordinates(n1, 1) - localNodalCoordinates(n0, 1);
1580 impl_Scalar elementNullspace11 = localNodalCoordinates(n2, 1) - localNodalCoordinates(n0, 1);
1581 impl_Scalar elementNullspace02 = localNodalCoordinates(n1, 2) - localNodalCoordinates(n0, 2);
1582 impl_Scalar elementNullspace12 = localNodalCoordinates(n2, 2) - localNodalCoordinates(n0, 2);
1584 localFaceNullspace(f, 0) = impl_ATS::magnitude(elementNullspace01 * elementNullspace12 - elementNullspace02 * elementNullspace11) / 6.0;
1585 localFaceNullspace(f, 1) = impl_ATS::magnitude(elementNullspace02 * elementNullspace10 - elementNullspace00 * elementNullspace12) / 6.0;
1586 localFaceNullspace(f, 2) = impl_ATS::magnitude(elementNullspace00 * elementNullspace11 - elementNullspace01 * elementNullspace10) / 6.0;
1595 dump(Nullspace,
"nullspaceFace.m");
1600 TEUCHOS_ASSERT(
false);
1601 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1605template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1606Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1608 using ATS = KokkosKernels::ArithTraits<Scalar>;
1609 using impl_Scalar =
typename ATS::val_type;
1610 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1611 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1613 typedef typename Matrix::local_matrix_device_type KCRS;
1614 typedef typename KCRS::StaticCrsGraphType graph_t;
1615 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1616 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1617 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1619 const impl_Scalar impl_SC_ONE = impl_ATS::one();
1620 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
1621 const impl_Scalar impl_half = impl_SC_ONE / (impl_SC_ONE + impl_SC_ONE);
1623 std::string spaceLabel;
1624 if (spaceNumber == 0)
1625 spaceLabel =
"nodal";
1626 else if (spaceNumber == 1)
1627 spaceLabel =
"edge";
1628 else if (spaceNumber == 2)
1629 spaceLabel =
"face";
1631 TEUCHOS_ASSERT(
false);
1633 RCP<Teuchos::TimeMonitor> tm;
1634 if (spaceNumber > 0) {
1635 tm = getTimer(
"projection " + spaceLabel);
1636 GetOStream(
Runtime0) << solverName_ +
"::compute(): building " + spaceLabel +
" projection" << std::endl;
1639 RCP<Matrix> incidence;
1640 if (spaceNumber == 0) {
1642 return Teuchos::null;
1644 }
else if (spaceNumber == 1) {
1648 }
else if (spaceNumber == 2) {
1651 TEUCHOS_ASSERT(spaceNumber_ == 2);
1653 RCP<Matrix> facesToNodes;
1655 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1658 dump(edgesToNodes,
"edgesToNodes.m");
1660 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1664 dump(facesToEdges,
"facesToEdges.m");
1666 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges,
false, *edgesToNodes,
false, facesToNodes, GetOStream(
Runtime0),
true,
true);
1671 dump(facesToNodes,
"facesToNodes.m");
1673 incidence = facesToNodes;
1676 TEUCHOS_ASSERT(
false);
1681 RCP<const Map> rowMap = incidence->getRowMap();
1682 RCP<const Map> blockColMap = MapFactory::Build(incidence->getColMap(), dim);
1683 RCP<const Map> blockDomainMap = MapFactory::Build(incidence->getDomainMap(), dim);
1685 auto localIncidence = incidence->getLocalMatrixDevice();
1686 size_t numLocalRows = rowMap->getLocalNumElements();
1687 size_t numLocalColumns = dim * incidence->getColMap()->getLocalNumElements();
1688 size_t nnzEstimate = dim * localIncidence.graph.entries.size();
1689 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"projection_rowptr_" + spaceLabel), numLocalRows + 1);
1690 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"projection_colind_" + spaceLabel), nnzEstimate);
1691 scalar_view_t vals(
"projection_vals_" + spaceLabel, nnzEstimate);
1694 Kokkos::parallel_for(
1695 solverName_ +
"::buildProjection_adjustRowptr_" + spaceLabel,
1696 range_type(0, numLocalRows + 1),
1697 KOKKOS_LAMBDA(
const size_t i) {
1698 rowptr(i) = dim * localIncidence.graph.row_map(i);
1701 auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1705 Kokkos::parallel_for(
1706 solverName_ +
"::buildProjection_enterValues_" + spaceLabel,
1707 range_type(0, numLocalRows),
1708 KOKKOS_LAMBDA(
const size_t f) {
1709 for (
size_t jj = localIncidence.graph.row_map(f); jj < localIncidence.graph.row_map(f + 1); jj++) {
1710 for (
size_t k = 0; k < dim; k++) {
1711 colind(dim * jj + k) = dim * localIncidence.graph.entries(jj) + k;
1712 if (impl_ATS::magnitude(localIncidence.values(jj)) > tol)
1713 vals(dim * jj + k) = impl_half * localNullspace(f, k);
1715 vals(dim * jj + k) = impl_SC_ZERO;
1721 typename CrsMatrix::local_matrix_device_type lclProjection(
"local projection " + spaceLabel,
1722 numLocalRows, numLocalColumns, nnzEstimate,
1723 vals, rowptr, colind);
1724 RCP<Matrix> projection = MatrixFactory::Build(lclProjection,
1725 rowMap, blockColMap,
1726 blockDomainMap, rowMap);
1731template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1733 Teuchos::RCP<Matrix> &P_nodal,
1734 Teuchos::RCP<MultiVector> &Nullspace_nodal,
1735 Teuchos::RCP<RealValuedMultiVector> &CoarseCoords_nodal)
const {
1736 RCP<Teuchos::TimeMonitor> tm = getTimer(
"nodal prolongator");
1737 GetOStream(
Runtime0) << solverName_ +
"::compute(): building nodal prolongator" << std::endl;
1742 const SC SC_ONE = Teuchos::ScalarTraits<SC>::one();
1745 Level fineLevel, coarseLevel;
1751 fineLevel.
Set(
"A", A_nodal);
1752 fineLevel.
Set(
"Coordinates", NodalCoords_);
1753 fineLevel.
Set(
"DofsPerNode", 1);
1754 coarseLevel.
setlib(A_nodal->getDomainMap()->lib());
1755 fineLevel.
setlib(A_nodal->getDomainMap()->lib());
1756 coarseLevel.setObjectLabel(A_nodal->getObjectLabel());
1757 fineLevel.setObjectLabel(A_nodal->getObjectLabel());
1760 RCP<MultiVector> nullSpace = MultiVectorFactory::Build(A_nodal->getRowMap(), NSdim);
1761 nullSpace->putScalar(SC_ONE);
1762 fineLevel.
Set(
"Nullspace", nullSpace);
1764 std::string algo = parameterList_.get<std::string>(
"multigrid algorithm");
1766 RCP<Factory> amalgFact, dropFact, UncoupledAggFact, coarseMapFact, TentativePFact, Tfact, SaPFact;
1780 dropFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1782 double dropTol = parameterList_.get<
double>(
"aggregation: drop tol");
1783 std::string dropScheme = parameterList_.get<std::string>(
"aggregation: drop scheme");
1784 std::string distLaplAlgo = parameterList_.get<std::string>(
"aggregation: distance laplacian algo");
1785 dropFact->SetParameter(
"aggregation: drop tol", Teuchos::ParameterEntry(dropTol));
1786 dropFact->SetParameter(
"aggregation: drop scheme", Teuchos::ParameterEntry(dropScheme));
1787 dropFact->SetParameter(
"aggregation: distance laplacian algo", Teuchos::ParameterEntry(distLaplAlgo));
1789 UncoupledAggFact->SetFactory(
"Graph", dropFact);
1790 int minAggSize = parameterList_.get<
int>(
"aggregation: min agg size");
1791 UncoupledAggFact->SetParameter(
"aggregation: min agg size", Teuchos::ParameterEntry(minAggSize));
1792 int maxAggSize = parameterList_.get<
int>(
"aggregation: max agg size");
1793 UncoupledAggFact->SetParameter(
"aggregation: max agg size", Teuchos::ParameterEntry(maxAggSize));
1794 bool matchMLbehavior1 = parameterList_.get<
bool>(
"aggregation: match ML phase1");
1795 UncoupledAggFact->SetParameter(
"aggregation: match ML phase1", Teuchos::ParameterEntry(matchMLbehavior1));
1796 bool matchMLbehavior2a = parameterList_.get<
bool>(
"aggregation: match ML phase2a");
1797 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2a", Teuchos::ParameterEntry(matchMLbehavior2a));
1798 bool matchMLbehavior2b = parameterList_.get<
bool>(
"aggregation: match ML phase2b");
1799 UncoupledAggFact->SetParameter(
"aggregation: match ML phase2b", Teuchos::ParameterEntry(matchMLbehavior2b));
1801 coarseMapFact->SetFactory(
"Aggregates", UncoupledAggFact);
1803 TentativePFact->SetFactory(
"Aggregates", UncoupledAggFact);
1804 TentativePFact->SetFactory(
"UnAmalgamationInfo", amalgFact);
1805 TentativePFact->SetFactory(
"CoarseMap", coarseMapFact);
1807 Tfact->SetFactory(
"Aggregates", UncoupledAggFact);
1808 Tfact->SetFactory(
"CoarseMap", coarseMapFact);
1811 SaPFact->SetFactory(
"P", TentativePFact);
1812 coarseLevel.
Request(
"P", SaPFact.get());
1814 coarseLevel.
Request(
"P", TentativePFact.get());
1815 coarseLevel.
Request(
"Nullspace", TentativePFact.get());
1816 coarseLevel.
Request(
"Coordinates", Tfact.get());
1818 RCP<AggregationExportFactory> aggExport;
1819 bool exportVizData = parameterList_.get<
bool>(
"aggregation: export visualization data");
1820 if (exportVizData) {
1822 ParameterList aggExportParams;
1823 aggExportParams.set(
"aggregation: output filename",
"aggs.vtk");
1824 aggExportParams.set(
"aggregation: output file: agg style",
"Jacks");
1825 aggExport->SetParameterList(aggExportParams);
1827 aggExport->SetFactory(
"Aggregates", UncoupledAggFact);
1828 aggExport->SetFactory(
"UnAmalgamationInfo", amalgFact);
1829 fineLevel.
Request(
"Aggregates", UncoupledAggFact.get());
1830 fineLevel.
Request(
"UnAmalgamationInfo", amalgFact.get());
1834 coarseLevel.
Get(
"P", P_nodal, SaPFact.get());
1836 coarseLevel.
Get(
"P", P_nodal, TentativePFact.get());
1837 coarseLevel.
Get(
"Nullspace", Nullspace_nodal, TentativePFact.get());
1838 coarseLevel.
Get(
"Coordinates", CoarseCoords_nodal, Tfact.get());
1841 aggExport->Build(fineLevel, coarseLevel);
1845template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1846Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1848 RCP<Teuchos::TimeMonitor> tm = getTimer(
"vectorial nodal prolongator");
1849 GetOStream(
Runtime0) << solverName_ +
"::compute(): building vectorial nodal prolongator" << std::endl;
1851 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1853 typedef typename Matrix::local_matrix_device_type KCRS;
1854 typedef typename KCRS::StaticCrsGraphType graph_t;
1855 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1856 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1857 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1862 RCP<Map> blockRowMap = MapFactory::Build(P_nodal->getRowMap(), dim);
1863 RCP<Map> blockColMap = MapFactory::Build(P_nodal->getColMap(), dim);
1864 RCP<Map> blockDomainMap = MapFactory::Build(P_nodal->getDomainMap(), dim);
1867 auto localP_nodal = P_nodal->getLocalMatrixDevice();
1869 size_t numLocalRows = blockRowMap->getLocalNumElements();
1870 size_t numLocalColumns = blockColMap->getLocalNumElements();
1871 size_t nnzEstimate = dim * localP_nodal.graph.entries.size();
1872 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_rowptr"), numLocalRows + 1);
1873 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_colind"), nnzEstimate);
1874 scalar_view_t vals(Kokkos::ViewAllocateWithoutInitializing(
"vectorPNodal_vals"), nnzEstimate);
1877 Kokkos::parallel_for(
1878 solverName_ +
"::buildVectorNodalProlongator_adjustRowptr",
1879 range_type(0, localP_nodal.numRows() + 1),
1881 if (i < localP_nodal.numRows()) {
1882 for (size_t k = 0; k < dim; k++) {
1883 rowptr(dim * i + k) = dim * localP_nodal.graph.row_map(i) + k;
1886 rowptr(dim * localP_nodal.numRows()) = dim * localP_nodal.graph.row_map(i);
1890 Kokkos::parallel_for(
1891 solverName_ +
"::buildVectorNodalProlongator_adjustColind",
1892 range_type(0, localP_nodal.graph.entries.size()),
1893 KOKKOS_LAMBDA(
const size_t jj) {
1894 for (
size_t k = 0; k < dim; k++) {
1895 colind(dim * jj + k) = dim * localP_nodal.graph.entries(jj) + k;
1897 vals(dim * jj + k) = 1.;
1901 typename CrsMatrix::local_matrix_device_type lclVectorNodalP(
"local vector nodal prolongator",
1902 numLocalRows, numLocalColumns, nnzEstimate,
1903 vals, rowptr, colind);
1904 RCP<Matrix> vectorNodalP = MatrixFactory::Build(lclVectorNodalP,
1905 blockRowMap, blockColMap,
1906 blockDomainMap, blockRowMap);
1908 return vectorNodalP;
1911template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1914 const Teuchos::RCP<Matrix> &A_nodal,
1915 const Teuchos::RCP<MultiVector> &Nullspace,
1916 Teuchos::RCP<Matrix> &Prolongator,
1917 Teuchos::RCP<MultiVector> &coarseNullspace,
1918 Teuchos::RCP<RealValuedMultiVector> &coarseNodalCoords)
const {
1919 using ATS = KokkosKernels::ArithTraits<Scalar>;
1920 using impl_Scalar =
typename ATS::val_type;
1921 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1923 std::string typeStr;
1924 switch (spaceNumber) {
1927 TEUCHOS_ASSERT(A_nodal.is_null());
1936 TEUCHOS_ASSERT(
false);
1939 const bool skipFirstLevel = !A_nodal.is_null();
1941 RCP<Teuchos::TimeMonitor> tm;
1942 if (spaceNumber > 0) {
1943 tm = getTimer(
"special prolongator " + typeStr);
1944 GetOStream(
Runtime0) << solverName_ +
"::compute(): building special " + typeStr +
" prolongator" << std::endl;
1947 RCP<Matrix> projection = buildProjection(spaceNumber, Nullspace);
1948 dump(projection, typeStr +
"Projection.m");
1950 if (skipFirstLevel) {
1951 RCP<Matrix> P_nodal;
1952 RCP<MultiVector> coarseNodalNullspace;
1954 buildNodalProlongator(A_nodal, P_nodal, coarseNodalNullspace, coarseNodalCoords);
1956 dump(P_nodal,
"P_nodal_" + typeStr +
".m");
1957 dump(coarseNodalNullspace,
"coarseNullspace_nodal_" + typeStr +
".m");
1959 RCP<Matrix> vectorP_nodal = buildVectorNodalProlongator(P_nodal);
1961 dump(vectorP_nodal,
"vectorP_nodal_" + typeStr +
".m");
1963 Prolongator = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*projection,
false, *vectorP_nodal,
false, Prolongator, GetOStream(
Runtime0),
true,
true);
2012 coarseNullspace = MultiVectorFactory::Build(vectorP_nodal->getDomainMap(), dim);
2014 auto localNullspace_nodal = coarseNodalNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
2015 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
2016 Kokkos::parallel_for(
2017 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
2018 range_type(0, coarseNodalNullspace->getLocalLength()),
2019 KOKKOS_LAMBDA(
const size_t i) {
2020 impl_Scalar val = localNullspace_nodal(i, 0);
2021 for (
size_t j = 0; j < dim; j++)
2022 localNullspace_coarse(dim * i + j, j) = val;
2026 Prolongator = projection;
2027 coarseNodalCoords = NodalCoords_;
2029 if (spaceNumber == 0) {
2031 }
else if (spaceNumber >= 1) {
2033 coarseNullspace = MultiVectorFactory::Build(projection->getDomainMap(), dim);
2034 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
2035 Kokkos::parallel_for(
2036 solverName_ +
"::buildProlongator_nullspace_" + typeStr,
2037 range_type(0, coarseNullspace->getLocalLength() / dim),
2038 KOKKOS_LAMBDA(
const size_t i) {
2039 for (
size_t j = 0; j < dim; j++)
2040 localNullspace_coarse(dim * i + j, j) = 1.0;
2046template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2048 Teuchos::RCP<Operator> &thyraPrecOp,
2049 const Teuchos::RCP<Matrix> &A,
2050 const Teuchos::RCP<MultiVector> &Nullspace,
2051 const Teuchos::RCP<RealValuedMultiVector> &Coords,
2052 const Teuchos::RCP<MultiVector> &Material,
2053 Teuchos::ParameterList ¶ms,
2056 const bool isSingular) {
2057 int oldRank = SetProcRankVerbose(A->getDomainMap()->getComm()->getRank());
2059 RCP<ParameterList> pl = rcp(
new ParameterList());
2060 pl->set(
"printLoadBalancingInfo",
true);
2061 pl->set(
"printCommInfo",
true);
2062 GetOStream(
Statistics2) << PerfUtils::PrintMatrixInfo(*A, label, pl);
2064#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2065 if (params.isType<std::string>(
"Preconditioner Type")) {
2066 TEUCHOS_ASSERT(!reuse);
2068 if (params.get<std::string>(
"Preconditioner Type") ==
"MueLu") {
2069 ParameterList &userParamList = params.sublist(
"Preconditioner Types").sublist(
"MueLu").sublist(
"user data");
2070 if (!Nullspace.is_null())
2071 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2072 if (!Material.is_null())
2073 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2074 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2076 thyraPrecOp = rcp(
new XpetraThyraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(coarseA11_, rcp(¶ms,
false)));
2083 ParameterList &userParamList = params.sublist(
"user data");
2084 if (!Coords.is_null())
2085 userParamList.set<RCP<RealValuedMultiVector>>(
"Coordinates", Coords);
2086 if (!Nullspace.is_null())
2087 userParamList.set<RCP<MultiVector>>(
"Nullspace", Nullspace);
2088 if (!Material.is_null())
2089 userParamList.set<RCP<MultiVector>>(
"Material", Material);
2092 std::string coarseType =
"";
2093 if (params.isParameter(
"coarse: type")) {
2094 coarseType = params.get<std::string>(
"coarse: type");
2096 std::transform(coarseType.begin(), coarseType.end(), coarseType.begin(), ::tolower);
2097 std::transform(coarseType.begin(), ++coarseType.begin(), coarseType.begin(), ::toupper);
2099 if ((coarseType ==
"" ||
2100 coarseType ==
"Klu" ||
2101 coarseType ==
"Klu2" ||
2102 coarseType ==
"Superlu" ||
2103 coarseType ==
"Superlu_dist" ||
2104 coarseType ==
"Superludist" ||
2105 coarseType ==
"Basker" ||
2106 coarseType ==
"Cusolver" ||
2107 coarseType ==
"Tacho") &&
2108 (!params.isSublist(
"coarse: params") ||
2109 !params.sublist(
"coarse: params").isParameter(
"fix nullspace")))
2110 params.sublist(
"coarse: params").set(
"fix nullspace",
true);
2115 RCP<MueLu::Level> level0 = hierarchy->GetLevel(0);
2116 level0->Set(
"A", A);
2117 hierarchy->SetupRe();
2120 SetProcRankVerbose(oldRank);
2123template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2125 bool reuse = !SM_Matrix_.is_null();
2126 SM_Matrix_ = SM_Matrix_new;
2127 dump(SM_Matrix_,
"SM.m");
2132template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2168 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2172 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2173 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2178 if (implicitTranspose_) {
2180 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"restriction coarse (1,1) (implicit)");
2181 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2183 if (!onlyBoundary22_) {
2184 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (implicit)");
2185 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2188 if (Dk_1_T_R11_colMapsMatch_) {
2191 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restrictions import");
2192 DTR11Tmp_->doImport(*residual_, *toCrsMatrix(R11_)->getCrsGraph()->getImporter(), Xpetra::INSERT);
2194 if (!onlyBoundary22_) {
2195 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2196 toTpetra(Dk_1_T_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*Dres_), Teuchos::NO_TRANS);
2199 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2200 toTpetra(R11_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*P11res_), Teuchos::NO_TRANS);
2204 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"restriction coarse (1,1) (explicit)");
2205 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2207 if (!onlyBoundary22_) {
2208 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"restriction (2,2) (explicit)");
2209 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2216 RCP<Teuchos::TimeMonitor> tmSubSolves = getTimer(
"subsolves");
2220 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2221 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2222 P11resTmp_->beginImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2224 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_) {
2225 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2226 DresTmp_->beginImport(*Dres_, *Importer22_, Xpetra::INSERT);
2230 if (!coarseA11_.is_null()) {
2231 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
2232 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2234 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2236#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2237 if (!thyraPrecOpH_.is_null()) {
2238 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2239 thyraPrecOpH_->apply(*P11resSubComm_, *P11xSubComm_, Teuchos::NO_TRANS, one, zero);
2242 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2246 if (!A22_.is_null()) {
2247 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2248 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2250 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2251#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2252 if (!thyraPrecOp22_.is_null()) {
2253 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2254 thyraPrecOp22_->apply(*DresSubComm_, *DxSubComm_, Teuchos::NO_TRANS, one, zero);
2257 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2260 if (coarseA11_.is_null() && !ImporterCoarse11_.is_null() && !implicitTranspose_)
2261 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2262 if (A22_.is_null() && !onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2263 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2267 RCP<Teuchos::TimeMonitor> tmProlongations = getTimer(
"prolongations");
2269 if (asyncTransfers_) {
2270 using Tpetra_Multivector = Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2271 using Tpetra_Import = Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>;
2273 auto tpP11 = toTpetra(P11_);
2274 auto tpDk_1 = toTpetra(Dk_1_);
2276 RCP<Tpetra_Multivector> tpP11x = toTpetra(P11x_);
2277 RCP<Tpetra_Multivector> tpP11x_colmap;
2278 RCP<Tpetra_Multivector> tpX = toTpetra(Teuchos::rcpFromRef(X));
2279 RCP<Tpetra_Multivector> tpResidual = toTpetra(residual_);
2280 RCP<Tpetra_Multivector> tpDx = toTpetra(Dx_);
2281 RCP<Tpetra_Multivector> tpDx_colmap;
2283 unsigned completedImports = 0;
2284 std::vector<bool> completedImport(2,
false);
2285 auto tpP11importer = tpP11->getCrsGraph()->getImporter();
2286 if (!tpP11importer.is_null()) {
2287 tpP11x_colmap = toTpetra(P11x_colmap_);
2288 tpP11x_colmap->beginImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2291 RCP<const Tpetra_Import> tpDk_1importer;
2292 if (!onlyBoundary22_) {
2293 tpDk_1importer = tpDk_1->getCrsGraph()->getImporter();
2294 if (!tpDk_1importer.is_null()) {
2295 tpDx_colmap = toTpetra(Dx_colmap_);
2296 tpDx_colmap->beginImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2299 completedImport[1] =
true;
2303 if (!fuseProlongationAndUpdate_) {
2304 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2305 tpResidual->putScalar(zero);
2308 while (completedImports < completedImport.size()) {
2309 for (
unsigned i = 0; i < completedImport.size(); i++) {
2310 if (completedImport[i])
continue;
2313 if (!tpP11importer.is_null()) {
2314 if (tpP11x_colmap->transferArrived()) {
2315 tpP11x_colmap->endImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2316 completedImport[i] =
true;
2319 if (fuseProlongationAndUpdate_) {
2320 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2321 tpP11->localApply(*tpP11x_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2323 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2324 tpP11->localApply(*tpP11x_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2328 completedImport[i] =
true;
2331 if (fuseProlongationAndUpdate_) {
2332 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused, local)");
2333 tpP11->localApply(*tpP11x, *tpX, Teuchos::NO_TRANS, one, one);
2335 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused, local)");
2336 tpP11->localApply(*tpP11x, *tpResidual, Teuchos::NO_TRANS, one, one);
2340 if (!tpDk_1importer.is_null()) {
2341 if (tpDx_colmap->transferArrived()) {
2342 tpDx_colmap->endImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2343 completedImport[i] =
true;
2346 if (fuseProlongationAndUpdate_) {
2347 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2348 tpDk_1->localApply(*tpDx_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2350 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2351 tpDk_1->localApply(*tpDx_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2355 completedImport[i] =
true;
2358 if (fuseProlongationAndUpdate_) {
2359 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused, local)");
2360 tpDk_1->localApply(*tpDx, *tpX, Teuchos::NO_TRANS, one, one);
2362 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused, local)");
2363 tpDk_1->localApply(*tpDx, *tpResidual, Teuchos::NO_TRANS, one, one);
2370 if (!fuseProlongationAndUpdate_) {
2371 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2372 X.update(one, *residual_, one);
2375 if (fuseProlongationAndUpdate_) {
2377 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (fused)");
2378 P11_->apply(*P11x_, X, Teuchos::NO_TRANS, one, one);
2381 if (!onlyBoundary22_) {
2382 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (fused)");
2383 Dk_1_->apply(*Dx_, X, Teuchos::NO_TRANS, one, one);
2387 RCP<Teuchos::TimeMonitor> tmP11 = getTimer(
"prolongation coarse (1,1) (unfused)");
2388 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2391 if (!onlyBoundary22_) {
2392 RCP<Teuchos::TimeMonitor> tmD = getTimer(
"prolongation (2,2) (unfused)");
2393 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS, one, one);
2397 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer(
"update");
2398 X.update(one, *residual_, one);
2405template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2407 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2410 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2411 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2412 if (implicitTranspose_)
2413 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2415 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2419 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2420 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"import coarse (1,1)");
2421 P11resTmp_->doImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2423 if (!coarseA11_.is_null()) {
2424 RCP<Teuchos::TimeMonitor> tmH = getTimer(
"solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2425 HierarchyCoarse11_->Iterate(*P11resSubComm_, *P11xSubComm_, numItersCoarse11_,
true);
2430 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2431 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2432 X.update(one, *residual_, one);
2436template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2438 if (onlyBoundary22_)
2441 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2444 RCP<Teuchos::TimeMonitor> tmRes = getTimer(
"residual calculation");
2445 Utilities::Residual(*SM_Matrix_, X, RHS, *residual_);
2446 if (implicitTranspose_)
2447 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2449 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2453 if (!Importer22_.is_null() && !implicitTranspose_) {
2454 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"import (2,2)");
2455 DresTmp_->doImport(*Dres_, *Importer22_, Xpetra::INSERT);
2457 if (!A22_.is_null()) {
2458 RCP<Teuchos::TimeMonitor> tm22 = getTimer(
"solve (2,2)", A22_->getRowMap()->getComm());
2459 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_,
true);
2464 RCP<Teuchos::TimeMonitor> tmUp = getTimer(
"update");
2465 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS);
2466 X.update(one, *residual_, one);
2470template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2475 RCP<Teuchos::TimeMonitor> tm = getTimer(
"solve");
2478 if (!onlyBoundary11_ && X.getNumVectors() != P11res_->getNumVectors())
2479 allocateMemory(X.getNumVectors());
2483 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2485 PreSmoother11_->Apply(X, RHS, use_as_preconditioner_);
2489 if (mode_ ==
"additive")
2490 applyInverseAdditive(RHS, X);
2491 else if (mode_ ==
"121") {
2495 }
else if (mode_ ==
"212") {
2499 }
else if (mode_ ==
"1")
2501 else if (mode_ ==
"2")
2503 else if (mode_ ==
"7") {
2507 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2509 PreSmoother11_->Apply(X, RHS,
false);
2514 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2516 PostSmoother11_->Apply(X, RHS,
false);
2519 }
else if (mode_ ==
"none") {
2522 applyInverseAdditive(RHS, X);
2526 RCP<Teuchos::TimeMonitor> tmSm = getTimer(
"smoothing");
2528 PostSmoother11_->Apply(X, RHS,
false);
2532template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2537template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2538std::pair<std::set<std::string>, std::set<std::string>>
2541 std::set<std::string> requiredUserData;
2542 int spaceNumber = 1;
2543 if (params.isType<
int>(
"refmaxwell: space number"))
2544 spaceNumber = params.get<
int>(
"refmaxwell: space number");
2545 bool disable_addon = MasterList::getDefault<bool>(
"refmaxwell: disable addon");
2546 if (params.isType<
bool>(
"refmaxwell: disable addon"))
2547 disable_addon = params.get<
bool>(
"refmaxwell: disable addon");
2548 bool disable_addon22 =
true;
2549 if (params.isType<
bool>(
"refmaxwell: disable addon 22"))
2550 disable_addon22 = params.get<
bool>(
"refmaxwell: disable addon 22");
2552 requiredUserData.insert(
"Coordinates");
2553 requiredUserData.insert(
"Dk_1");
2555 requiredUserData.insert(
"M1_beta");
2556 if (spaceNumber >= 2)
2557 requiredUserData.insert(
"M1_alpha");
2559 if (!disable_addon) {
2560 requiredUserData.insert(
"Mk_one");
2561 requiredUserData.insert(
"invMk_1_invBeta");
2564 if ((spaceNumber >= 2) && (!disable_addon22)) {
2565 requiredUserData.insert(
"Dk_2");
2566 requiredUserData.insert(
"Mk_1_one");
2567 requiredUserData.insert(
"invMk_2_invAlpha");
2573 if (requiredUserData11.contains(
"Material") || requiredUserData22.contains(
"Material"))
2574 requiredUserData.insert(
"Material");
2576 std::set<std::string> optionalUserData;
2577 optionalUserData.insert(
"Nullspace11");
2578 optionalUserData.insert(
"Nullspace22");
2580 return std::make_pair(requiredUserData, optionalUserData);
2583template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2585 RefMaxwell(
const Teuchos::RCP<Matrix> &SM_Matrix,
2586 Teuchos::ParameterList &List,
2588 int spaceNumber = List.get<
int>(
"refmaxwell: space number", 1);
2590 RCP<Matrix> Dk_1, Dk_2, D0;
2591 RCP<Matrix> M1_beta, M1_alpha;
2592 RCP<Matrix> Mk_one, Mk_1_one;
2593 RCP<Matrix> invMk_1_invBeta, invMk_2_invAlpha;
2594 RCP<MultiVector> Nullspace11, Nullspace22;
2595 RCP<RealValuedMultiVector> NodalCoords;
2597 auto &userData = List.sublist(
"user data");
2599 Dk_1 =
pop(List, userData,
"Dk_1", Dk_1);
2600 Dk_2 =
pop(List, userData,
"Dk_2", Dk_2);
2601 D0 =
pop(List, userData,
"D0", D0);
2603 M1_beta =
pop(List, userData,
"M1_beta", M1_beta);
2604 M1_alpha =
pop(List, userData,
"M1_alpha", M1_alpha);
2606 Mk_one =
pop(List, userData,
"Mk_one", Mk_one);
2607 Mk_1_one =
pop(List, userData,
"Mk_1_one", Mk_1_one);
2609 invMk_1_invBeta =
pop(List, userData,
"invMk_1_invBeta", invMk_1_invBeta);
2610 invMk_2_invAlpha =
pop(List, userData,
"invMk_2_invAlpha", invMk_2_invAlpha);
2612 Nullspace11 =
pop(List, userData,
"Nullspace11", Nullspace11);
2613 Nullspace22 =
pop(List, userData,
"Nullspace22", Nullspace22);
2614 NodalCoords =
pop(List, userData,
"Coordinates", NodalCoords);
2617 if (List.isType<RCP<Matrix>>(
"Ms")) {
2618 if (M1_beta.is_null())
2619 M1_beta = pop<RCP<Matrix>>(List,
"Ms");
2621 TEUCHOS_ASSERT(
false);
2623 if (List.isType<RCP<Matrix>>(
"M1")) {
2624 if (Mk_one.is_null())
2625 Mk_one = pop<RCP<Matrix>>(List,
"M1");
2627 TEUCHOS_ASSERT(
false);
2629 if (List.isType<RCP<Matrix>>(
"M0inv")) {
2630 if (invMk_1_invBeta.is_null())
2631 invMk_1_invBeta = pop<RCP<Matrix>>(List,
"M0inv");
2633 TEUCHOS_ASSERT(
false);
2635 if (List.isType<RCP<MultiVector>>(
"Nullspace")) {
2636 if (Nullspace11.is_null())
2637 Nullspace11 = pop<RCP<MultiVector>>(List,
"Nullspace");
2639 TEUCHOS_ASSERT(
false);
2642 if (spaceNumber == 1) {
2645 else if (D0.is_null())
2647 if (M1_beta.is_null())
2649 }
else if (spaceNumber == 2) {
2652 else if (D0.is_null())
2656 initialize(spaceNumber,
2660 invMk_1_invBeta, invMk_2_invAlpha,
2661 Nullspace11, Nullspace22,
2663 Teuchos::null, Teuchos::null,
2666 if (SM_Matrix != Teuchos::null)
2667 resetMatrix(SM_Matrix, ComputePrec);
2670template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2672 initialize(
const Teuchos::RCP<Matrix> &D0_Matrix,
2673 const Teuchos::RCP<Matrix> &Ms_Matrix,
2674 const Teuchos::RCP<Matrix> &M0inv_Matrix,
2675 const Teuchos::RCP<Matrix> &M1_Matrix,
2676 const Teuchos::RCP<MultiVector> &Nullspace11,
2677 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2678 const Teuchos::RCP<MultiVector> &Material,
2679 Teuchos::ParameterList &List) {
2681 D0_Matrix, Teuchos::null, D0_Matrix,
2682 Ms_Matrix, Teuchos::null,
2683 M1_Matrix, Teuchos::null,
2684 M0inv_Matrix, Teuchos::null,
2685 Nullspace11, Teuchos::null,
2687 Teuchos::null, Material,
2691template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2694 const Teuchos::RCP<Matrix> &Dk_1,
2695 const Teuchos::RCP<Matrix> &Dk_2,
2696 const Teuchos::RCP<Matrix> &D0,
2697 const Teuchos::RCP<Matrix> &M1_beta,
2698 const Teuchos::RCP<Matrix> &M1_alpha,
2699 const Teuchos::RCP<Matrix> &Mk_one,
2700 const Teuchos::RCP<Matrix> &Mk_1_one,
2701 const Teuchos::RCP<Matrix> &invMk_1_invBeta,
2702 const Teuchos::RCP<Matrix> &invMk_2_invAlpha,
2703 const Teuchos::RCP<MultiVector> &Nullspace11,
2704 const Teuchos::RCP<MultiVector> &Nullspace22,
2705 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2706 const Teuchos::RCP<MultiVector> &Material_beta,
2707 const Teuchos::RCP<MultiVector> &Material_alpha,
2708 Teuchos::ParameterList &List) {
2710 if (spaceNumber_ == 1)
2711 solverName_ =
"RefMaxwell";
2712 else if (spaceNumber_ == 2)
2713 solverName_ =
"RefDarcy";
2715 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
2716 "spaceNumber needs to be 1 (HCurl) or 2 (HDiv)");
2717 HierarchyCoarse11_ = Teuchos::null;
2718 Hierarchy22_ = Teuchos::null;
2719 PreSmoother11_ = Teuchos::null;
2720 PostSmoother11_ = Teuchos::null;
2721 disable_addon_ =
false;
2722 disable_addon_22_ =
true;
2726 setParameters(List);
2729 TEUCHOS_ASSERT((k == 1) || (k == 2));
2731 TEUCHOS_ASSERT(Dk_1 != Teuchos::null);
2733 TEUCHOS_ASSERT(D0 != Teuchos::null);
2736 TEUCHOS_ASSERT(M1_beta != Teuchos::null);
2739 TEUCHOS_ASSERT(M1_alpha != Teuchos::null);
2741 if (!disable_addon_) {
2743 TEUCHOS_ASSERT(Mk_one != Teuchos::null);
2744 TEUCHOS_ASSERT(invMk_1_invBeta != Teuchos::null);
2747 if ((k >= 2) && !disable_addon_22_) {
2749 TEUCHOS_ASSERT(Dk_2 != Teuchos::null);
2750 TEUCHOS_ASSERT(Mk_1_one != Teuchos::null);
2751 TEUCHOS_ASSERT(invMk_2_invAlpha != Teuchos::null);
2754 if (Behavior::debug()) {
2755 TEUCHOS_ASSERT(D0->getRangeMap()->isSameAs(*D0->getRowMap()));
2758 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRangeMap()));
2759 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRowMap()));
2762 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*D0->getRangeMap()));
2766 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRangeMap()));
2767 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRowMap()));
2770 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*D0->getRangeMap()));
2773 if (!disable_addon_) {
2775 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRangeMap()));
2776 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRowMap()));
2779 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2782 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRangeMap()));
2783 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRowMap()));
2786 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2789 if ((k >= 2) && !disable_addon_22_) {
2791 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRangeMap()));
2792 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRowMap()));
2795 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2798 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_2->getRangeMap()));
2801 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRangeMap()));
2802 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRowMap()));
2805 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*Dk_2->getDomainMap()));
2810 if (Dk_1->getRowMap()->lib() == Xpetra::UseTpetra) {
2815 RCP<Matrix> Dk_1copy = MatrixFactory::Build(Dk_1->getRowMap(), Dk_1->getColMap(), 0);
2816 RCP<CrsMatrix> Dk_1copyCrs = toCrsMatrix(Dk_1copy);
2817 ArrayRCP<const size_t> Dk_1rowptr_RCP;
2818 ArrayRCP<const LO> Dk_1colind_RCP;
2819 ArrayRCP<const SC> Dk_1vals_RCP;
2820 toCrsMatrix(Dk_1)->getAllValues(Dk_1rowptr_RCP, Dk_1colind_RCP, Dk_1vals_RCP);
2822 ArrayRCP<size_t> Dk_1copyrowptr_RCP;
2823 ArrayRCP<LO> Dk_1copycolind_RCP;
2824 ArrayRCP<SC> Dk_1copyvals_RCP;
2825 Dk_1copyCrs->allocateAllValues(Dk_1vals_RCP.size(), Dk_1copyrowptr_RCP, Dk_1copycolind_RCP, Dk_1copyvals_RCP);
2826 Dk_1copyrowptr_RCP.deepCopy(Dk_1rowptr_RCP());
2827 Dk_1copycolind_RCP.deepCopy(Dk_1colind_RCP());
2828 Dk_1copyvals_RCP.deepCopy(Dk_1vals_RCP());
2829 Dk_1copyCrs->setAllValues(Dk_1copyrowptr_RCP,
2832 Dk_1copyCrs->expertStaticFillComplete(Dk_1->getDomainMap(), Dk_1->getRangeMap(),
2833 toCrsMatrix(Dk_1)->getCrsGraph()->getImporter(),
2834 toCrsMatrix(Dk_1)->getCrsGraph()->getExporter());
2837 Dk_1_ = MatrixFactory::BuildCopy(Dk_1);
2839 if ((!Dk_2.is_null()) && (Dk_2->getRowMap()->lib() == Xpetra::UseTpetra)) {
2844 RCP<Matrix> Dk_2copy = MatrixFactory::Build(Dk_2->getRowMap(), Dk_2->getColMap(), 0);
2845 RCP<CrsMatrix> Dk_2copyCrs = toCrsMatrix(Dk_2copy);
2846 ArrayRCP<const size_t> Dk_2rowptr_RCP;
2847 ArrayRCP<const LO> Dk_2colind_RCP;
2848 ArrayRCP<const SC> Dk_2vals_RCP;
2849 toCrsMatrix(Dk_2)->getAllValues(Dk_2rowptr_RCP, Dk_2colind_RCP, Dk_2vals_RCP);
2851 ArrayRCP<size_t> Dk_2copyrowptr_RCP;
2852 ArrayRCP<LO> Dk_2copycolind_RCP;
2853 ArrayRCP<SC> Dk_2copyvals_RCP;
2854 Dk_2copyCrs->allocateAllValues(Dk_2vals_RCP.size(), Dk_2copyrowptr_RCP, Dk_2copycolind_RCP, Dk_2copyvals_RCP);
2855 Dk_2copyrowptr_RCP.deepCopy(Dk_2rowptr_RCP());
2856 Dk_2copycolind_RCP.deepCopy(Dk_2colind_RCP());
2857 Dk_2copyvals_RCP.deepCopy(Dk_2vals_RCP());
2858 Dk_2copyCrs->setAllValues(Dk_2copyrowptr_RCP,
2861 Dk_2copyCrs->expertStaticFillComplete(Dk_2->getDomainMap(), Dk_2->getRangeMap(),
2862 toCrsMatrix(Dk_2)->getCrsGraph()->getImporter(),
2863 toCrsMatrix(Dk_2)->getCrsGraph()->getExporter());
2865 }
else if (!Dk_2.is_null())
2866 Dk_2_ = MatrixFactory::BuildCopy(Dk_2);
2869 M1_alpha_ = M1_alpha;
2871 Material_beta_ = Material_beta;
2872 Material_alpha_ = Material_alpha;
2875 Mk_1_one_ = Mk_1_one;
2877 invMk_1_invBeta_ = invMk_1_invBeta;
2878 invMk_2_invAlpha_ = invMk_2_invAlpha;
2880 NodalCoords_ = NodalCoords;
2881 Nullspace11_ = Nullspace11;
2882 Nullspace22_ = Nullspace22;
2885 dump(Dk_1_,
"Dk_1_clean.m");
2886 dump(Dk_2_,
"Dk_2_clean.m");
2888 dump(M1_beta_,
"M1_beta.m");
2889 dump(M1_alpha_,
"M1_alpha.m");
2891 dump(Mk_one_,
"Mk_one.m");
2892 dump(Mk_1_one_,
"Mk_1_one.m");
2894 dump(invMk_1_invBeta_,
"invMk_1_invBeta.m");
2895 dump(invMk_2_invAlpha_,
"invMk_2_invAlpha.m");
2897 dumpCoords(NodalCoords_,
"coords.m");
2900template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2902 describe(Teuchos::FancyOStream &out,
const Teuchos::EVerbosityLevel )
const {
2903 std::ostringstream oss;
2905 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->
getDomainMap()->getComm();
2909 if (!coarseA11_.is_null())
2910 root = comm->getRank();
2915 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
2919 oss <<
"\n--------------------------------------------------------------------------------\n"
2920 <<
"--- " + solverName_ +
2922 "--------------------------------------------------------------------------------"
2929 SM_Matrix_->getRowMap()->getComm()->barrier();
2931 numRows = SM_Matrix_->getGlobalNumRows();
2932 nnz = SM_Matrix_->getGlobalNumEntries();
2934 Xpetra::global_size_t tt = numRows;
2947 oss <<
"block " << std::setw(rowspacer) <<
" rows " << std::setw(nnzspacer) <<
" nnz " << std::setw(9) <<
" nnz/row" << std::endl;
2948 oss <<
"(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2954 if (!A22_.is_null()) {
2955 numRows = A22_->getGlobalNumRows();
2956 if (Xpetra::toTpetra(A22_)->haveGlobalConstants())
2957 nnz = A22_->getGlobalNumEntries();
2959 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, numRows, Teuchos::ptr(&numRowsGlobal));
2960 Teuchos::reduceAll(*comm, Teuchos::REDUCE_MAX, nnz, Teuchos::ptr(&numNNZGlobal));
2962 if (numRowsGlobal > 0)
2963 oss <<
"(2, 2)" << std::setw(rowspacer) << numRowsGlobal << std::setw(nnzspacer) << numNNZGlobal << std::setw(9) << as<double>(numNNZGlobal) / numRowsGlobal << std::endl;
2965 oss <<
"(2, 2)" << std::setw(rowspacer) << numRowsGlobal << std::setw(nnzspacer) << numNNZGlobal << std::endl;
2970 if (PreSmoother11_ != null && PreSmoother11_ == PostSmoother11_)
2971 oss <<
"Smoother 11 both : " << PreSmoother11_->description() << std::endl;
2973 oss <<
"Smoother 11 pre : "
2974 << (PreSmoother11_ != null ? PreSmoother11_->description() :
"no smoother") << std::endl;
2975 oss <<
"Smoother 11 post : "
2976 << (PostSmoother11_ != null ? PostSmoother11_->description() :
"no smoother") << std::endl;
2981 std::string outstr = oss.str();
2984 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2985 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
2987 int strLength = outstr.size();
2988 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
2989 if (comm->getRank() != root)
2990 outstr.resize(strLength);
2991 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
2996 if (!HierarchyCoarse11_.is_null())
2997 HierarchyCoarse11_->describe(out, GetVerbLevel());
2999 if (!Hierarchy22_.is_null())
3000 Hierarchy22_->describe(out, GetVerbLevel());
3004 std::ostringstream oss2;
3006 oss2 <<
"Sub-solver distribution over ranks" << std::endl;
3007 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;
3009 int numProcs = comm->getSize();
3011 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
3012 TEUCHOS_TEST_FOR_EXCEPTION(tmpic == Teuchos::null,
Exceptions::RuntimeError,
"Cannot cast base Teuchos::Comm to Teuchos::MpiComm object.");
3013 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
3017 if (!coarseA11_.is_null())
3019 if (!A22_.is_null())
3021 std::vector<char> states(numProcs, 0);
3023 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
3025 states.push_back(status);
3028 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
3029 for (
int proc = 0; proc < numProcs; proc += rowWidth) {
3030 for (
int j = 0; j < rowWidth; j++)
3031 if (proc + j < numProcs)
3032 if (states[proc + j] == 0)
3034 else if (states[proc + j] == 1)
3036 else if (states[proc + j] == 2)
3043 oss2 <<
" " << proc <<
":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
3052#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 Teuchos::RCP< Teuchos::ParameterList > 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,...