MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_RefMaxwell_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_REFMAXWELL_DEF_HPP
11#define MUELU_REFMAXWELL_DEF_HPP
12
13#include <sstream>
14
15#include "MueLu_ConfigDefs.hpp"
16
17#include "Teuchos_CompilerCodeTweakMacros.hpp"
18#include "Tpetra_CrsMatrix.hpp"
19#include "Xpetra_CrsMatrix.hpp"
20#include "Xpetra_Map.hpp"
21#include "Xpetra_MatrixMatrix.hpp"
22#include "Xpetra_MultiVector.hpp"
23#include "Xpetra_TripleMatrixMultiply.hpp"
25#include "Xpetra_MatrixUtils.hpp"
26
28
29#include "MueLu_AmalgamationFactory.hpp"
30#include "MueLu_RAPFactory.hpp"
31#include "MueLu_SmootherFactory.hpp"
32
33#include "MueLu_CoalesceDropFactory.hpp"
34#include "MueLu_CoarseMapFactory.hpp"
35#include "MueLu_CoordinatesTransferFactory.hpp"
36#include "MueLu_UncoupledAggregationFactory.hpp"
37#include "MueLu_TentativePFactory.hpp"
38#include "MueLu_SaPFactory.hpp"
39#include "MueLu_AggregationExportFactory.hpp"
40#include "MueLu_Utilities.hpp"
41#include "MueLu_Maxwell_Utils.hpp"
42
43#include "MueLu_CoalesceDropFactory_kokkos.hpp"
44#include "MueLu_TentativePFactory_kokkos.hpp"
45#include <Kokkos_Core.hpp>
46#include <KokkosSparse_CrsMatrix.hpp>
47
48#include "MueLu_ZoltanInterface.hpp"
49#include "MueLu_Zoltan2Interface.hpp"
50#include "MueLu_RepartitionHeuristicFactory.hpp"
51#include "MueLu_RepartitionFactory.hpp"
52#include "MueLu_RebalanceAcFactory.hpp"
53#include "MueLu_RebalanceTransferFactory.hpp"
54
56
59
60#ifdef HAVE_MUELU_CUDA
61#include "cuda_profiler_api.h"
62#endif
63
64// Stratimikos
65#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
67#endif
68
69namespace MueLu {
70
71template <typename T>
72T pop(Teuchos::ParameterList &pl, std::string const &name_in) {
73 T result = pl.get<T>(name_in);
74 pl.remove(name_in, true);
75 return result;
76}
77
78template <typename T>
79T pop(Teuchos::ParameterList &pl, std::string const &name_in, T def_value) {
80 T result = pl.get<T>(name_in, def_value);
81 pl.remove(name_in, false);
82 return result;
83}
84
85template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
86const Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::getDomainMap() const {
87 return SM_Matrix_->getDomainMap();
88}
89
90template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
91const Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::getRangeMap() const {
92 return SM_Matrix_->getRangeMap();
93}
94
95template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
96Teuchos::RCP<Teuchos::ParameterList>
99 bool useKokkosDefault = !Node::is_serial;
100
101 RCP<ParameterList> params = rcp(new ParameterList("RefMaxwell"));
102
103 params->set<RCP<Matrix>>("Dk_1", Teuchos::null);
104 params->set<RCP<Matrix>>("Dk_2", Teuchos::null);
105 params->set<RCP<Matrix>>("D0", Teuchos::null);
106
107 params->set<RCP<Matrix>>("M1_beta", Teuchos::null);
108 params->set<RCP<Matrix>>("M1_alpha", Teuchos::null);
109 // for backwards compatibility
110 params->set<RCP<Matrix>>("Ms", Teuchos::null);
111
112 params->set<RCP<Matrix>>("Mk_one", Teuchos::null);
113 params->set<RCP<Matrix>>("Mk_1_one", Teuchos::null);
114 // for backwards compatibility
115 params->set<RCP<Matrix>>("M1", Teuchos::null);
116
117 params->set<RCP<Matrix>>("invMk_1_invBeta", Teuchos::null);
118 params->set<RCP<Matrix>>("invMk_2_invAlpha", Teuchos::null);
119 // for backwards compatibility
120 params->set<RCP<Matrix>>("M0inv", Teuchos::null);
121
122 params->set<RCP<MultiVector>>("Nullspace", Teuchos::null);
123 params->set<RCP<RealValuedMultiVector>>("Coordinates", Teuchos::null);
124
125 auto spaceValidator = rcp(new Teuchos::EnhancedNumberValidator<int>(1, 2));
126 params->set("refmaxwell: space number", 1, "", spaceValidator);
127 params->set("verbosity", MasterList::getDefault<std::string>("verbosity"));
128 params->set("use kokkos refactor", useKokkosDefault);
129 params->set("half precision", false);
130 params->set("parameterlist: syntax", MasterList::getDefault<std::string>("parameterlist: syntax"));
131 params->set("output filename", MasterList::getDefault<std::string>("output filename"));
132 params->set("print initial parameters", MasterList::getDefault<bool>("print initial parameters"));
133 params->set("refmaxwell: disable addon", MasterList::getDefault<bool>("refmaxwell: disable addon"));
134 params->set("refmaxwell: disable addon 22", true);
135 params->set("refmaxwell: mode", MasterList::getDefault<std::string>("refmaxwell: mode"));
136 params->set("refmaxwell: use as preconditioner", MasterList::getDefault<bool>("refmaxwell: use as preconditioner"));
137 params->set("refmaxwell: dump matrices", MasterList::getDefault<bool>("refmaxwell: dump matrices"));
138 params->set("refmaxwell: enable reuse", MasterList::getDefault<bool>("refmaxwell: enable reuse"));
139 params->set("refmaxwell: skip first (1,1) level", MasterList::getDefault<bool>("refmaxwell: skip first (1,1) level"));
140 params->set("refmaxwell: skip first (2,2) level", false);
141 params->set("multigrid algorithm", "Unsmoothed");
142 params->set("transpose: use implicit", MasterList::getDefault<bool>("transpose: use implicit"));
143 params->set("rap: triple product", MasterList::getDefault<bool>("rap: triple product"));
144 params->set("rap: fix zero diagonals", true);
145 params->set("rap: fix zero diagonals threshold", MasterList::getDefault<double>("rap: fix zero diagonals threshold"));
146 params->set("fuse prolongation and update", MasterList::getDefault<bool>("fuse prolongation and update"));
147 params->set("refmaxwell: async transfers", Node::is_gpu);
148 params->set("refmaxwell: subsolves on subcommunicators", MasterList::getDefault<bool>("refmaxwell: subsolves on subcommunicators"));
149 params->set("refmaxwell: subsolves striding", 1);
150 params->set("refmaxwell: row sum drop tol (1,1)", MasterList::getDefault<double>("aggregation: row sum drop tol"));
151 params->set("sync timers", false);
152 params->set("refmaxwell: num iters coarse 11", 1);
153 params->set("refmaxwell: num iters 22", 1);
154 params->set("refmaxwell: apply BCs to Anodal", false);
155 params->set("refmaxwell: apply BCs to coarse 11", true);
156 params->set("refmaxwell: apply BCs to 22", true);
157 params->set("refmaxwell: max coarse size", 1);
158
159 ParameterList &precList11 = params->sublist("refmaxwell: 11list");
160 precList11.disableRecursiveValidation();
161 ParameterList &precList22 = params->sublist("refmaxwell: 22list");
162 precList22.disableRecursiveValidation();
163
164 params->set("smoother: type", "CHEBYSHEV");
165 ParameterList &smootherList = params->sublist("smoother: params");
166 smootherList.disableRecursiveValidation();
167 params->set("smoother: pre type", "NONE");
168 ParameterList &preSmootherList = params->sublist("smoother: pre params");
169 preSmootherList.disableRecursiveValidation();
170 params->set("smoother: post type", "NONE");
171 ParameterList &postSmootherList = params->sublist("smoother: post params");
172 postSmootherList.disableRecursiveValidation();
173
174 ParameterList &matvecParams = params->sublist("matvec params");
175 matvecParams.disableRecursiveValidation();
176
177 ParameterList &importerCoarse11Params = params->sublist("refmaxwell: ImporterCoarse11 params");
178 importerCoarse11Params.disableRecursiveValidation();
179
180 ParameterList &importer22Params = params->sublist("refmaxwell: Importer22 params");
181 importer22Params.disableRecursiveValidation();
182
183 params->set("multigrid algorithm", "unsmoothed");
184 params->set("aggregation: type", MasterList::getDefault<std::string>("aggregation: type"));
185 params->set("aggregation: drop tol", MasterList::getDefault<double>("aggregation: drop tol"));
186 params->set("aggregation: drop scheme", MasterList::getDefault<std::string>("aggregation: drop scheme"));
187 params->set("aggregation: distance laplacian algo", MasterList::getDefault<std::string>("aggregation: distance laplacian algo"));
188 params->set("aggregation: min agg size", MasterList::getDefault<int>("aggregation: min agg size"));
189 params->set("aggregation: max agg size", MasterList::getDefault<int>("aggregation: max agg size"));
190 params->set("aggregation: match ML phase1", MasterList::getDefault<bool>("aggregation: match ML phase1"));
191 params->set("aggregation: match ML phase2a", MasterList::getDefault<bool>("aggregation: match ML phase2a"));
192 params->set("aggregation: match ML phase2b", MasterList::getDefault<bool>("aggregation: match ML phase2b"));
193 params->set("aggregation: export visualization data", MasterList::getDefault<bool>("aggregation: export visualization data"));
194
195 return params;
196}
197
198template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
200 if (list.isType<std::string>("parameterlist: syntax") && list.get<std::string>("parameterlist: syntax") == "ml") {
201 Teuchos::ParameterList newList;
202 {
203 Teuchos::ParameterList newList2 = *Teuchos::getParametersFromXmlString(MueLu::ML2MueLuParameterTranslator::translate(list, "refmaxwell"));
204 RCP<Teuchos::ParameterList> validateParameters = getValidParamterList();
205 for (auto it = newList2.begin(); it != newList2.end(); ++it) {
206 const std::string &entry_name = it->first;
207 if (validateParameters->isParameter(entry_name)) {
208 ParameterEntry theEntry = newList2.getEntry(entry_name);
209 newList.setEntry(entry_name, theEntry);
210 }
211 }
212 }
213
214 if (list.isSublist("refmaxwell: 11list") && list.sublist("refmaxwell: 11list").isSublist("edge matrix free: coarse"))
215 newList.sublist("refmaxwell: 11list") = *Teuchos::getParametersFromXmlString(MueLu::ML2MueLuParameterTranslator::translate(list.sublist("refmaxwell: 11list").sublist("edge matrix free: coarse"), "SA"));
216 if (list.isSublist("refmaxwell: 22list"))
217 newList.sublist("refmaxwell: 22list") = *Teuchos::getParametersFromXmlString(MueLu::ML2MueLuParameterTranslator::translate(list.sublist("refmaxwell: 22list"), "SA"));
218 list = newList;
219 }
220
221 parameterList_ = list;
222 parameterList_.validateParametersAndSetDefaults(*getValidParamterList());
223 std::string verbosityLevel = parameterList_.get<std::string>("verbosity");
225 std::string outputFilename = parameterList_.get<std::string>("output filename");
226 if (outputFilename != "")
228 if (parameterList_.isType<Teuchos::RCP<Teuchos::FancyOStream>>("output stream"))
229 VerboseObject::SetMueLuOStream(parameterList_.get<Teuchos::RCP<Teuchos::FancyOStream>>("output stream"));
230
231 if (parameterList_.get<bool>("print initial parameters"))
232 GetOStream(static_cast<MsgType>(Runtime1), 0) << parameterList_ << std::endl;
233 disable_addon_ = parameterList_.get<bool>("refmaxwell: disable addon");
234 disable_addon_22_ = parameterList_.get<bool>("refmaxwell: disable addon 22");
235 mode_ = parameterList_.get<std::string>("refmaxwell: mode");
236 use_as_preconditioner_ = parameterList_.get<bool>("refmaxwell: use as preconditioner");
237 dump_matrices_ = parameterList_.get<bool>("refmaxwell: dump matrices");
238 enable_reuse_ = parameterList_.get<bool>("refmaxwell: enable reuse");
239 implicitTranspose_ = parameterList_.get<bool>("transpose: use implicit");
240 fuseProlongationAndUpdate_ = parameterList_.get<bool>("fuse prolongation and update");
241 skipFirst11Level_ = parameterList_.get<bool>("refmaxwell: skip first (1,1) level");
242 skipFirst22Level_ = parameterList_.get<bool>("refmaxwell: skip first (2,2) level");
243 if (spaceNumber_ == 1)
244 skipFirst22Level_ = false;
245 syncTimers_ = parameterList_.get<bool>("sync timers");
246 useKokkos_ = parameterList_.get<bool>("use kokkos refactor");
247 numItersCoarse11_ = parameterList_.get<int>("refmaxwell: num iters coarse 11");
248 numIters22_ = parameterList_.get<int>("refmaxwell: num iters 22");
249 applyBCsToAnodal_ = parameterList_.get<bool>("refmaxwell: apply BCs to Anodal");
250 applyBCsToCoarse11_ = parameterList_.get<bool>("refmaxwell: apply BCs to coarse 11");
251 applyBCsTo22_ = parameterList_.get<bool>("refmaxwell: apply BCs to 22");
252
253 precList11_ = parameterList_.sublist("refmaxwell: 11list");
254 if (!precList11_.isType<std::string>("Preconditioner Type") &&
255 !precList11_.isType<std::string>("smoother: type") &&
256 !precList11_.isType<std::string>("smoother: pre type") &&
257 !precList11_.isType<std::string>("smoother: post type")) {
258 precList11_.set("smoother: type", "CHEBYSHEV");
259 precList11_.sublist("smoother: params").set("chebyshev: degree", 2);
260 precList11_.sublist("smoother: params").set("chebyshev: ratio eigenvalue", 5.4);
261 precList11_.sublist("smoother: params").set("chebyshev: eigenvalue max iterations", 30);
262 }
263
264 precList22_ = parameterList_.sublist("refmaxwell: 22list");
265 if (!precList22_.isType<std::string>("Preconditioner Type") &&
266 !precList22_.isType<std::string>("smoother: type") &&
267 !precList22_.isType<std::string>("smoother: pre type") &&
268 !precList22_.isType<std::string>("smoother: post type")) {
269 precList22_.set("smoother: type", "CHEBYSHEV");
270 precList22_.sublist("smoother: params").set("chebyshev: degree", 2);
271 precList22_.sublist("smoother: params").set("chebyshev: ratio eigenvalue", 7.0);
272 precList22_.sublist("smoother: params").set("chebyshev: eigenvalue max iterations", 30);
273 }
274
275 if (!parameterList_.isType<std::string>("smoother: type") && !parameterList_.isType<std::string>("smoother: pre type") && !parameterList_.isType<std::string>("smoother: post type")) {
276 list.set("smoother: type", "CHEBYSHEV");
277 list.sublist("smoother: params").set("chebyshev: degree", 2);
278 list.sublist("smoother: params").set("chebyshev: ratio eigenvalue", 20.0);
279 list.sublist("smoother: params").set("chebyshev: eigenvalue max iterations", 30);
280 }
281
282 if (enable_reuse_ &&
283 !precList11_.isType<std::string>("Preconditioner Type") &&
284 !precList11_.isParameter("reuse: type"))
285 precList11_.set("reuse: type", "full");
286 if (enable_reuse_ &&
287 !precList22_.isType<std::string>("Preconditioner Type") &&
288 !precList22_.isParameter("reuse: type"))
289 precList22_.set("reuse: type", "full");
290}
291
292template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
294 using memory_space = typename Node::device_type::memory_space;
295
296#ifdef HAVE_MUELU_CUDA
297 if (parameterList_.get<bool>("refmaxwell: cuda profile setup", false)) cudaProfilerStart();
298#endif
299
300 std::string timerLabel;
301 if (reuse)
302 timerLabel = "compute (reuse)";
303 else
304 timerLabel = "compute";
305 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
306
308 // COMMENTED OUT SINCE WE SHOULD NOT NEED THIS ANYMORE.
309 // Remove explicit zeros from matrices
310 // Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(parameterList_,D0_,SM_Matrix_,Mk_one_,M1_beta_);
311 // if (!Dk_1_.is_null())
312 // Dk_1_ = Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(Dk_1_, 1e-10, false);
313
314 if (IsPrint(Statistics2)) {
315 RCP<ParameterList> params = rcp(new ParameterList());
316 params->set("printLoadBalancingInfo", true);
317 params->set("printCommInfo", true);
319 }
320
322 // Detect Dirichlet boundary conditions
323 if (!reuse) {
324 magnitudeType rowSumTol = parameterList_.get<double>("refmaxwell: row sum drop tol (1,1)");
330 if (spaceNumber_ == 2) {
331 Kokkos::View<bool *, memory_space> BCcolsEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing("dirichletCols"), Dk_1_->getColMap()->getLocalNumElements());
332 Kokkos::View<bool *, memory_space> BCdomainEdge = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing("dirichletDomains"), Dk_1_->getDomainMap()->getLocalNumElements());
333 Utilities::DetectDirichletColsAndDomains(*Dk_1_, BCrows11_, BCcolsEdge, BCdomainEdge);
334
335 Kokkos::View<bool *, memory_space> BCcolsNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing("dirichletCols"), D0_->getColMap()->getLocalNumElements());
336 Kokkos::View<bool *, memory_space> BCdomainNode = Kokkos::View<bool *, memory_space>(Kokkos::ViewAllocateWithoutInitializing("dirichletDomains"), D0_->getDomainMap()->getLocalNumElements());
337 Utilities::DetectDirichletColsAndDomains(*D0_, BCdomainEdge, BCcolsNode, BCdomainNode);
338 BCdomain22_ = BCdomainNode;
339 }
340 if (IsPrint(Statistics2)) {
341 GetOStream(Statistics2) << solverName_ + "::compute(): Detected " << globalNumberBoundaryUnknowns11_ << " BC rows and " << globalNumberBoundaryUnknowns22_ << " BC columns." << std::endl;
342 }
343 dump(BCrows11_, "BCrows11.m");
344 dump(BCcols22_, "BCcols22.m");
345 dump(BCdomain22_, "BCdomain22.m");
346 }
347
348 if (onlyBoundary11_) {
349 // All unknowns of the (1,1) block have been detected as boundary unknowns.
350 // Do not attempt to construct sub-hierarchies, but just set up a single level preconditioner.
351 GetOStream(Warnings0) << "All unknowns of the (1,1) block have been detected as boundary unknowns!" << std::endl;
352 mode_ = "none";
354 return;
355 }
356
358
359 dim_ = NodalCoords_->getNumVectors();
360
362 // build special prolongators
363 if (!reuse) {
365 // build nullspace for (1,1)-block (if necessary)
366 if (Nullspace11_ != null) { // no need to do anything - nullspace is built
367 TEUCHOS_ASSERT(Nullspace11_->getMap()->isCompatible(*(SM_Matrix_->getRowMap())));
368 } else if (NodalCoords_ != null) {
370 } else {
371 GetOStream(Errors) << solverName_ + "::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
372 }
373
374 // build special prolongator for (1,1)-block
375 {
376 RCP<Matrix> A11_nodal;
377 if (skipFirst11Level_) {
378 // Form A11_nodal = D0^T * M1_beta * D0 (aka TMT_agg)
379 std::string label("D0^T*M1_beta*D0");
381
382 if (applyBCsToAnodal_) {
383 // Apply boundary conditions to A11_nodal
385 }
386 A11_nodal->setObjectLabel(solverName_ + " (1,1) A_nodal");
387 dump(A11_nodal, "A11_nodal.m");
388 }
389 // release it because we won't need it anymore
390 M1_beta_ = Teuchos::null;
391
392 // build special prolongator
394
395 dump(P11_, "P11.m");
396 }
397
399 // build nullspace for (2,2)-block (if necessary)
400 if (Nullspace22_ != null) {
401 TEUCHOS_ASSERT(Nullspace22_->getMap()->isCompatible(*(Dk_1_->getDomainMap())));
402 } else if (NodalCoords_ != null)
404 else {
405 GetOStream(Errors) << solverName_ + "::compute(): either the nullspace or the nodal coordinates must be provided." << std::endl;
406 }
407
408 // build special prolongator for (2,2)-block
409 {
410 RCP<Matrix> A22_nodal;
411 if (skipFirst22Level_) {
412 // Form A22_nodal = D0^T * M1_alpha * D0
413 std::string label("D0^T*M1_alpha*D0");
415
416 if (applyBCsToAnodal_) {
417 // Apply boundary conditions to A22_nodal
419 }
420 A22_nodal->setObjectLabel(solverName_ + " (2,2) A_nodal");
421 dump(A22_nodal, "A22_nodal.m");
422 }
423 // release it because we won't need it anymore
424 M1_alpha_ = Teuchos::null;
425
426 // build special prolongator
428
429 dump(P22_, "P22.m");
430 }
431 }
432
434 // build coarse grid operator for (1,1)-block
436
438 // determine the communicator sizes for (1,1)- and (2,2)-blocks
439 bool doRebalancing;
440 int rebalanceStriding, numProcsCoarseA11, numProcsA22;
441 if (!reuse)
442 this->determineSubHierarchyCommSizes(doRebalancing, rebalanceStriding, numProcsCoarseA11, numProcsA22);
443 else
444 doRebalancing = false;
445
446 // rebalance the coarse A11 matrix, as well as P11, CoordsCoarse11 and Addon11
447 if (!reuse && doRebalancing)
448 rebalanceCoarse11Matrix(rebalanceStriding, numProcsCoarseA11);
449 if (!coarseA11_.is_null()) {
450 dump(coarseA11_, "coarseA11.m");
451 if (!reuse) {
452 dumpCoords(CoordsCoarse11_, "CoordsCoarse11.m");
453 dump(NullspaceCoarse11_, "NullspaceCoarse11.m");
454 }
455 }
456
457 if (!reuse) {
458 if (!implicitTranspose_) {
460 dump(R11_, "R11.m");
461 }
462 }
464 // build multigrid for coarse (1,1)-block
465 if (!coarseA11_.is_null()) {
467 std::string label("coarseA11");
470 }
471
473 // Apply BCs to columns of Dk_1
474 if (!reuse && applyBCsTo22_) {
475 GetOStream(Runtime0) << solverName_ + "::compute(): nuking BC columns of Dk_1" << std::endl;
476
477 Dk_1_->resumeFill();
478 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
480 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
481 }
482
484 // Build A22 = Dk_1^T SM Dk_1 and hierarchy for A22
485 if (!onlyBoundary22_) {
486 GetOStream(Runtime0) << solverName_ + "::compute(): building MG for (2,2)-block" << std::endl;
487
488 // Build A22 = Dk_1^T * SM * Dk_1 and rebalance it, as well as Dk_1_ and P22_ and Coords22_
489 build22Matrix(reuse, doRebalancing, rebalanceStriding, numProcsA22);
490
491 if (!P22_.is_null()) {
492 std::string label("P22^T*A22*P22");
494 coarseA22_->SetFixedBlockSize(A22_->GetFixedBlockSize());
495 coarseA22_->setObjectLabel(solverName_ + " coarse (2, 2)");
496 dump(coarseA22_, "coarseA22.m");
497 }
498
499 if (!reuse && !implicitTranspose_) {
501 if (!P22_.is_null())
503 }
504
505 if (!A22_.is_null()) {
507 std::string label("A22");
508 if (!P22_.is_null()) {
509 precList22_.sublist("level 1 user data").set("A", coarseA22_);
510 precList22_.sublist("level 1 user data").set("P", P22_);
512 precList22_.sublist("level 1 user data").set("R", R22_);
513 precList22_.sublist("level 1 user data").set("Nullspace", CoarseNullspace22_);
514 precList22_.sublist("level 1 user data").set("Coordinates", Coords22_);
515 // A22 is singular, we want to coarsen at least once.
516 // So we make sure coarseA22 is not just ignored.
517 int maxCoarseSize = precList22_.get("coarse: max size", MasterList::getDefault<int>("coarse: max size"));
518 int numRows = Teuchos::as<int>(coarseA22_->getGlobalNumRows());
519 if (maxCoarseSize > numRows)
520 precList22_.set("coarse: max size", numRows);
521 int maxLevels = precList22_.get("max levels", MasterList::getDefault<int>("max levels"));
522 if (maxLevels < 2)
523 precList22_.set("max levels", 2);
524 setupSubSolve(Hierarchy22_, thyraPrecOp22_, A22_, Teuchos::null, Teuchos::null, Material_alpha_, precList22_, label, reuse, /*isSingular=*/globalNumberBoundaryUnknowns11_ == 0);
525 } else
527
529 }
530 }
531
533 // Apply BCs to rows of Dk_1
534 if (!reuse && !onlyBoundary22_ && applyBCsTo22_) {
535 GetOStream(Runtime0) << solverName_ + "::compute(): nuking BC rows of Dk_1" << std::endl;
536
537 Dk_1_->resumeFill();
538 Scalar replaceWith = Teuchos::ScalarTraits<SC>::zero();
540 Dk_1_->fillComplete(Dk_1_->getDomainMap(), Dk_1_->getRangeMap());
541 dump(Dk_1_, "Dk_1_nuked.m");
542 }
543
545 // Set up the smoother on the finest level
547
548 if (!reuse) {
549 if (!ImporterCoarse11_.is_null()) {
550 RCP<const Import> ImporterP11 = ImportFactory::Build(ImporterCoarse11_->getTargetMap(), P11_->getColMap());
551 toCrsMatrix(P11_)->replaceDomainMapAndImporter(ImporterCoarse11_->getTargetMap(), ImporterP11);
552 }
553
554 if (!Importer22_.is_null()) {
555 if (enable_reuse_) {
556 DorigDomainMap_ = Dk_1_->getDomainMap();
557 DorigImporter_ = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
558 }
559 RCP<const Import> ImporterD = ImportFactory::Build(Importer22_->getTargetMap(), Dk_1_->getColMap());
560 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), ImporterD);
561 }
562
563 if ((!Dk_1_T_.is_null()) &&
564 (!R11_.is_null()) &&
565 (!toCrsMatrix(Dk_1_T_)->getCrsGraph()->getImporter().is_null()) &&
566 (!toCrsMatrix(R11_)->getCrsGraph()->getImporter().is_null()) &&
567 (Dk_1_T_->getColMap()->lib() == Xpetra::UseTpetra) &&
568 (R11_->getColMap()->lib() == Xpetra::UseTpetra))
569 Dk_1_T_R11_colMapsMatch_ = Dk_1_T_->getColMap()->isSameAs(*R11_->getColMap());
570 else
573 GetOStream(Runtime0) << solverName_ + "::compute(): Dk_1_T and R11 have matching colMaps" << std::endl;
574
575 asyncTransfers_ = parameterList_.get<bool>("refmaxwell: async transfers");
576
577 // Allocate MultiVectors for solve
579
580 // apply matvec params
581 if (parameterList_.isSublist("matvec params")) {
582 RCP<ParameterList> matvecParams = rcpFromRef(parameterList_.sublist("matvec params"));
586 if (!Dk_1_T_.is_null()) Maxwell_Utils<SC, LO, GO, NO>::setMatvecParams(*Dk_1_T_, matvecParams);
587 if (!R11_.is_null()) Maxwell_Utils<SC, LO, GO, NO>::setMatvecParams(*R11_, matvecParams);
588 if (!ImporterCoarse11_.is_null()) ImporterCoarse11_->setDistributorParameters(matvecParams);
589 if (!Importer22_.is_null()) Importer22_->setDistributorParameters(matvecParams);
590 }
591 if (!ImporterCoarse11_.is_null() && parameterList_.isSublist("refmaxwell: ImporterCoarse11 params")) {
592 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist("refmaxwell: ImporterCoarse11 params"));
593 ImporterCoarse11_->setDistributorParameters(importerParams);
594 }
595 if (!Importer22_.is_null() && parameterList_.isSublist("refmaxwell: Importer22 params")) {
596 RCP<ParameterList> importerParams = rcpFromRef(parameterList_.sublist("refmaxwell: Importer22 params"));
597 Importer22_->setDistributorParameters(importerParams);
598 }
599 }
600
602
603#ifdef HAVE_MUELU_CUDA
604 if (parameterList_.get<bool>("refmaxwell: cuda profile setup", false)) cudaProfilerStop();
605#endif
606}
607
608template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
610 determineSubHierarchyCommSizes(bool &doRebalancing, int &rebalanceStriding, int &numProcsCoarseA11, int &numProcsA22) {
611 doRebalancing = parameterList_.get<bool>("refmaxwell: subsolves on subcommunicators");
612 rebalanceStriding = parameterList_.get<int>("refmaxwell: subsolves striding", -1);
613 int numProcs = SM_Matrix_->getDomainMap()->getComm()->getSize();
614 if (numProcs == 1) {
615 doRebalancing = false;
616 return;
617 }
618
619#ifdef HAVE_MPI
620 if (doRebalancing) {
621 {
622 // decide on number of ranks for coarse (1, 1) problem
623
624 Level level;
625 level.SetFactoryManager(null);
626 level.SetLevelID(0);
627 level.Set("A", coarseA11_);
628
629 auto repartheurFactory = rcp(new RepartitionHeuristicFactory());
630 ParameterList repartheurParams;
631 repartheurParams.set("repartition: start level", 0);
632 // Setting min == target on purpose.
633 int defaultTargetRows = 10000;
634 repartheurParams.set("repartition: min rows per proc", precList11_.get<int>("repartition: target rows per proc", defaultTargetRows));
635 repartheurParams.set("repartition: target rows per proc", precList11_.get<int>("repartition: target rows per proc", defaultTargetRows));
636 repartheurParams.set("repartition: min rows per thread", precList11_.get<int>("repartition: target rows per thread", defaultTargetRows));
637 repartheurParams.set("repartition: target rows per thread", precList11_.get<int>("repartition: target rows per thread", defaultTargetRows));
638 repartheurParams.set("repartition: max imbalance", precList11_.get<double>("repartition: max imbalance", 1.1));
639 repartheurFactory->SetParameterList(repartheurParams);
640
641 level.Request("number of partitions", repartheurFactory.get());
642 repartheurFactory->Build(level);
643 numProcsCoarseA11 = level.Get<int>("number of partitions", repartheurFactory.get());
644 numProcsCoarseA11 = std::min(numProcsCoarseA11, numProcs);
645 }
646
647 {
648 // decide on number of ranks for (2, 2) problem
649
650 Level level;
651 level.SetFactoryManager(null);
652 level.SetLevelID(0);
653
654 level.Set("Map", Dk_1_->getDomainMap());
655
656 auto repartheurFactory = rcp(new RepartitionHeuristicFactory());
657 ParameterList repartheurParams;
658 repartheurParams.set("repartition: start level", 0);
659 repartheurParams.set("repartition: use map", true);
660 // Setting min == target on purpose.
661 int defaultTargetRows = 10000;
662 repartheurParams.set("repartition: min rows per proc", precList22_.get<int>("repartition: target rows per proc", defaultTargetRows));
663 repartheurParams.set("repartition: target rows per proc", precList22_.get<int>("repartition: target rows per proc", defaultTargetRows));
664 repartheurParams.set("repartition: min rows per thread", precList22_.get<int>("repartition: target rows per thread", defaultTargetRows));
665 repartheurParams.set("repartition: target rows per thread", precList22_.get<int>("repartition: target rows per thread", defaultTargetRows));
666 // repartheurParams.set("repartition: max imbalance", precList22_.get<double>("repartition: max imbalance", 1.1));
667 repartheurFactory->SetParameterList(repartheurParams);
668
669 level.Request("number of partitions", repartheurFactory.get());
670 repartheurFactory->Build(level);
671 numProcsA22 = level.Get<int>("number of partitions", repartheurFactory.get());
672 numProcsA22 = std::min(numProcsA22, numProcs);
673 }
674
675 if (rebalanceStriding >= 1) {
676 TEUCHOS_ASSERT(rebalanceStriding * numProcsCoarseA11 <= numProcs);
677 TEUCHOS_ASSERT(rebalanceStriding * numProcsA22 <= numProcs);
678 if (rebalanceStriding * (numProcsCoarseA11 + numProcsA22) > numProcs) {
679 GetOStream(Warnings0) << solverName_ + "::compute(): Disabling striding = " << rebalanceStriding << ", since coarseA11 needs " << numProcsCoarseA11
680 << " procs and A22 needs " << numProcsA22 << " procs." << std::endl;
681 rebalanceStriding = -1;
682 }
683 int lclBadMatrixDistribution = (coarseA11_->getLocalNumEntries() == 0) || (Dk_1_->getDomainMap()->getLocalNumElements() == 0);
684 int gblBadMatrixDistribution = false;
685 MueLu_maxAll(SM_Matrix_->getDomainMap()->getComm(), lclBadMatrixDistribution, gblBadMatrixDistribution);
686 if (gblBadMatrixDistribution) {
687 GetOStream(Warnings0) << solverName_ + "::compute(): Disabling striding = " << rebalanceStriding << ", since coarseA11 has no entries on at least one rank or Dk_1's domain map has no entries on at least one rank." << std::endl;
688 rebalanceStriding = -1;
689 }
690 }
691
692 if ((numProcsCoarseA11 < 0) || (numProcsA22 < 0) || (numProcsCoarseA11 + numProcsA22 > numProcs)) {
693 GetOStream(Warnings0) << solverName_ + "::compute(): Disabling rebalancing of subsolves, since partition heuristic resulted "
694 << "in undesirable number of partitions: " << numProcsCoarseA11 << ", " << numProcsA22 << std::endl;
695 doRebalancing = false;
696 }
697 }
698#else
699 doRebalancing = false;
700#endif // HAVE_MPI
701}
702
703template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
704RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>> RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
705 buildAddon(const int spaceNumber) {
706 if (spaceNumber == 0)
707 return Teuchos::null;
708
709 std::string timerLabel;
710 if (spaceNumber == spaceNumber_) {
712 timerLabel = "Build coarse addon matrix 11";
713 else
714 timerLabel = "Build addon matrix 11";
715 } else
716 timerLabel = "Build addon matrix 22";
717
718 RCP<Teuchos::TimeMonitor> tmAddon = getTimer(timerLabel);
719
720 RCP<Matrix> addon;
721 RCP<Matrix> Z;
722 RCP<Matrix> lumpedInverse;
723 if (spaceNumber == spaceNumber_) {
724 // catch a failure
725 TEUCHOS_TEST_FOR_EXCEPTION(invMk_1_invBeta_ == Teuchos::null, std::invalid_argument,
727 "::buildCoarse11Matrix(): Inverse of "
728 "lumped mass matrix required for add-on (i.e. invMk_1_invBeta_ is null)");
729 lumpedInverse = invMk_1_invBeta_;
730
731 if (skipFirst11Level_) {
732 // construct Zaux = M1 P11
733 RCP<Matrix> Zaux;
734 Zaux = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Mk_one_, false, *P11_, false, Zaux, GetOStream(Runtime0), true, true);
735 // construct Z = D* M1 P11 = D^T Zaux
736 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_, true, *Zaux, false, Z, GetOStream(Runtime0), true, true);
737 } else {
738 // construct Z = D* M1 P11 = D^T Zaux
739 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_, true, *Mk_one_, false, Z, GetOStream(Runtime0), true, true);
740 }
741
742 } else if (spaceNumber == spaceNumber_ - 1) {
743 // catch a failure
744 TEUCHOS_TEST_FOR_EXCEPTION(invMk_2_invAlpha_ == Teuchos::null, std::invalid_argument,
746 "::buildCoarse11Matrix(): Inverse of "
747 "lumped mass matrix required for add-on (i.e. invMk_2_invAlpha_ is null)");
748 lumpedInverse = invMk_2_invAlpha_;
749
750 // construct Z = Dk_2^T Mk_1_one
751 Z = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_2_, true, *Mk_1_one_, false, Z, GetOStream(Runtime0), true, true);
752 }
753
754 // construct Z^T lumpedInverse Z
755 if (lumpedInverse->getGlobalMaxNumRowEntries() <= 1) {
756 // We assume that if lumpedInverse has at most one entry per row then
757 // these are all diagonal entries.
758 RCP<Vector> diag = VectorFactory::Build(lumpedInverse->getRowMap());
759 lumpedInverse->getLocalDiagCopy(*diag);
760 {
761 ArrayRCP<Scalar> diagVals = diag->getDataNonConst(0);
762 for (size_t j = 0; j < diag->getMap()->getLocalNumElements(); j++) {
763 diagVals[j] = Teuchos::ScalarTraits<Scalar>::squareroot(diagVals[j]);
764 }
765 }
766 if (Z->getRowMap()->isSameAs(*(diag->getMap())))
767 Z->leftScale(*diag);
768 else {
769 RCP<Import> importer = ImportFactory::Build(diag->getMap(), Z->getRowMap());
770 RCP<Vector> diag2 = VectorFactory::Build(Z->getRowMap());
771 diag2->doImport(*diag, *importer, Xpetra::INSERT);
772 Z->leftScale(*diag2);
773 }
774 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z, true, *Z, false, addon, GetOStream(Runtime0), true, true);
775 } else if (parameterList_.get<bool>("rap: triple product", false) == false) {
776 RCP<Matrix> C2;
777 // construct C2 = lumpedInverse Z
778 C2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*lumpedInverse, false, *Z, false, C2, GetOStream(Runtime0), true, true);
779 // construct Matrix2 = Z* M0inv Z = Z* C2
780 addon = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Z, true, *C2, false, addon, GetOStream(Runtime0), true, true);
781 } else {
782 addon = MatrixFactory::Build(Z->getDomainMap());
783 // construct Matrix2 = Z^T lumpedInverse Z
784 Xpetra::TripleMatrixMultiply<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
785 MultiplyRAP(*Z, true, *lumpedInverse, false, *Z, false, *addon, true, true);
786 }
787 return addon;
788}
789
790template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
792 RCP<Teuchos::TimeMonitor> tm = getTimer("Build coarse (1,1) matrix");
793
794 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
795
796 // coarse matrix for P11* (M1 + D1* M2 D1) P11
797 RCP<Matrix> temp;
798 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_, false, *P11_, false, temp, GetOStream(Runtime0), true, true);
799 if (ImporterCoarse11_.is_null())
800 coarseA11_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_, true, *temp, false, coarseA11_, GetOStream(Runtime0), true, true);
801 else {
802 RCP<Matrix> temp2;
803 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*P11_, true, *temp, false, temp2, GetOStream(Runtime0), true, true);
804
805 RCP<const Map> map = ImporterCoarse11_->getTargetMap()->removeEmptyProcesses();
806 temp2->removeEmptyProcessesInPlace(map);
807 if (!temp2.is_null() && temp2->getRowMap().is_null())
808 temp2 = Teuchos::null;
809 coarseA11_ = temp2;
810 }
811
812 if (!disable_addon_) {
813 RCP<Matrix> addon;
814
815 if (!coarseA11_.is_null() && Addon11_.is_null()) {
816 addon = buildAddon(spaceNumber_);
817 // Should we keep the addon for next setup?
818 if (enable_reuse_)
819 Addon11_ = addon;
820 } else
821 addon = Addon11_;
822
823 if (!coarseA11_.is_null()) {
824 // add matrices together
825 RCP<Matrix> newCoarseA11;
826 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*coarseA11_, false, one, *addon, false, one, newCoarseA11, GetOStream(Runtime0));
827 newCoarseA11->fillComplete();
828 coarseA11_ = newCoarseA11;
829 }
830 }
831
832 if (!coarseA11_.is_null() && !skipFirst11Level_) {
833 ArrayRCP<bool> coarseA11BCrows;
834 coarseA11BCrows.resize(coarseA11_->getRowMap()->getLocalNumElements());
835 for (size_t i = 0; i < BCdomain22_.size(); i++)
836 for (size_t k = 0; k < dim_; k++)
837 coarseA11BCrows[i * dim_ + k] = BCdomain22_(i);
838 magnitudeType rowSumTol = parameterList_.get<double>("refmaxwell: row sum drop tol (1,1)");
839 if (rowSumTol > 0.)
840 Utilities::ApplyRowSumCriterion(*coarseA11_, rowSumTol, coarseA11BCrows);
843 }
844
845 if (!coarseA11_.is_null()) {
846 // If we already applied BCs to A_nodal, we likely do not need
847 // to fix up coarseA11.
848 // If we did not apply BCs to A_nodal, we now need to correct
849 // the zero diagonals of coarseA11, since we did nuke the nullspace.
850
851 bool fixZeroDiagonal = !applyBCsToAnodal_;
852 if (precList11_.isParameter("rap: fix zero diagonals"))
853 fixZeroDiagonal = precList11_.get<bool>("rap: fix zero diagonals");
854
855 if (fixZeroDiagonal) {
856 magnitudeType threshold = 1e-16;
857 Scalar replacement = 1.0;
858 if (precList11_.isType<magnitudeType>("rap: fix zero diagonals threshold"))
859 threshold = precList11_.get<magnitudeType>("rap: fix zero diagonals threshold");
860 else if (precList11_.isType<double>("rap: fix zero diagonals threshold"))
861 threshold = Teuchos::as<magnitudeType>(precList11_.get<double>("rap: fix zero diagonals threshold"));
862 if (precList11_.isType<double>("rap: fix zero diagonals replacement"))
863 replacement = Teuchos::as<Scalar>(precList11_.get<double>("rap: fix zero diagonals replacement"));
864 Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(coarseA11_, true, GetOStream(Warnings1), threshold, replacement);
865 }
866
867 // Set block size
868 coarseA11_->SetFixedBlockSize(dim_);
870 coarseA11_->setObjectLabel(solverName_ + " coarse (1,1)");
871 else
872 coarseA11_->setObjectLabel(solverName_ + " (1,1)");
873 }
874}
875
876template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
878 rebalanceCoarse11Matrix(const int rebalanceStriding, const int numProcsCoarseA11) {
879#ifdef HAVE_MPI
880 // rebalance coarseA11
881 RCP<Teuchos::TimeMonitor> tm = getTimer("Rebalance coarseA11");
882
883 Level fineLevel, coarseLevel;
884 fineLevel.SetFactoryManager(null);
885 coarseLevel.SetFactoryManager(null);
886 coarseLevel.SetPreviousLevel(rcpFromRef(fineLevel));
887 fineLevel.SetLevelID(0);
888 coarseLevel.SetLevelID(1);
889 coarseLevel.Set("A", coarseA11_);
890 coarseLevel.Set("P", P11_);
891 coarseLevel.Set("Coordinates", CoordsCoarse11_);
892 if (!NullspaceCoarse11_.is_null())
893 coarseLevel.Set("Nullspace", NullspaceCoarse11_);
894 coarseLevel.Set("number of partitions", numProcsCoarseA11);
895 coarseLevel.Set("repartition: heuristic target rows per process", 1000);
896
897 coarseLevel.setlib(coarseA11_->getDomainMap()->lib());
898 fineLevel.setlib(coarseA11_->getDomainMap()->lib());
899 coarseLevel.setObjectLabel(solverName_ + " coarse (1,1)");
900 fineLevel.setObjectLabel(solverName_ + " coarse (1,1)");
901
902 std::string partName = precList11_.get<std::string>("repartition: partitioner", "zoltan2");
903 RCP<Factory> partitioner;
904 if (partName == "zoltan") {
905#ifdef HAVE_MUELU_ZOLTAN
906 partitioner = rcp(new ZoltanInterface());
907 // NOTE: ZoltanInteface ("zoltan") does not support external parameters through ParameterList
908 // partitioner->SetFactory("number of partitions", repartheurFactory);
909#else
910 throw Exceptions::RuntimeError("Zoltan interface is not available");
911#endif
912 } else if (partName == "zoltan2") {
913#ifdef HAVE_MUELU_ZOLTAN2
914 partitioner = rcp(new Zoltan2Interface());
915 ParameterList partParams;
916 RCP<const ParameterList> partpartParams = rcp(new ParameterList(precList11_.sublist("repartition: params", false)));
917 partParams.set("ParameterList", partpartParams);
918 partitioner->SetParameterList(partParams);
919 // partitioner->SetFactory("number of partitions", repartheurFactory);
920#else
921 throw Exceptions::RuntimeError("Zoltan2 interface is not available");
922#endif
923 }
924
925 auto repartFactory = rcp(new RepartitionFactory());
926 ParameterList repartParams;
927 repartParams.set("repartition: print partition distribution", precList11_.get<bool>("repartition: print partition distribution", false));
928 repartParams.set("repartition: remap parts", precList11_.get<bool>("repartition: remap parts", true));
929 if (rebalanceStriding >= 1) {
930 bool acceptPart = (SM_Matrix_->getDomainMap()->getComm()->getRank() % rebalanceStriding) == 0;
931 if (SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsCoarseA11 * rebalanceStriding)
932 acceptPart = false;
933 repartParams.set("repartition: remap accept partition", acceptPart);
934 }
935 repartFactory->SetParameterList(repartParams);
936 // repartFactory->SetFactory("number of partitions", repartheurFactory);
937 repartFactory->SetFactory("Partition", partitioner);
938
939 auto newP = rcp(new RebalanceTransferFactory());
940 ParameterList newPparams;
941 newPparams.set("type", "Interpolation");
942 newPparams.set("repartition: rebalance P and R", precList11_.get<bool>("repartition: rebalance P and R", false));
943 newPparams.set("repartition: use subcommunicators", true);
944 newPparams.set("repartition: rebalance Nullspace", !NullspaceCoarse11_.is_null());
945 newP->SetFactory("Coordinates", NoFactory::getRCP());
946 if (!NullspaceCoarse11_.is_null())
947 newP->SetFactory("Nullspace", NoFactory::getRCP());
948 newP->SetParameterList(newPparams);
949 newP->SetFactory("Importer", repartFactory);
950
951 auto newA = rcp(new RebalanceAcFactory());
952 ParameterList rebAcParams;
953 rebAcParams.set("repartition: use subcommunicators", true);
954 newA->SetParameterList(rebAcParams);
955 newA->SetFactory("Importer", repartFactory);
956
957 coarseLevel.Request("P", newP.get());
958 coarseLevel.Request("Importer", repartFactory.get());
959 coarseLevel.Request("A", newA.get());
960 coarseLevel.Request("Coordinates", newP.get());
961 if (!NullspaceCoarse11_.is_null())
962 coarseLevel.Request("Nullspace", newP.get());
963 repartFactory->Build(coarseLevel);
964
965 if (!precList11_.get<bool>("repartition: rebalance P and R", false))
966 ImporterCoarse11_ = coarseLevel.Get<RCP<const Import>>("Importer", repartFactory.get());
967 P11_ = coarseLevel.Get<RCP<Matrix>>("P", newP.get());
968 coarseA11_ = coarseLevel.Get<RCP<Matrix>>("A", newA.get());
969 CoordsCoarse11_ = coarseLevel.Get<RCP<RealValuedMultiVector>>("Coordinates", newP.get());
970 if (!NullspaceCoarse11_.is_null())
971 NullspaceCoarse11_ = coarseLevel.Get<RCP<MultiVector>>("Nullspace", newP.get());
972
973 if (!coarseA11_.is_null()) {
974 // Set block size
975 coarseA11_->SetFixedBlockSize(dim_);
977 coarseA11_->setObjectLabel(solverName_ + " coarse (1,1)");
978 else
979 coarseA11_->setObjectLabel(solverName_ + " (1,1)");
980 }
981
982 coarseA11_AP_reuse_data_ = Teuchos::null;
983 coarseA11_RAP_reuse_data_ = Teuchos::null;
984
986 // Rebalance the addon for next setup
987 RCP<const Import> ImporterCoarse11 = coarseLevel.Get<RCP<const Import>>("Importer", repartFactory.get());
988 RCP<const Map> targetMap = ImporterCoarse11->getTargetMap();
989 ParameterList XpetraList;
990 XpetraList.set("Restrict Communicator", true);
991 Addon11_ = MatrixFactory::Build(Addon11_, *ImporterCoarse11, *ImporterCoarse11, targetMap, targetMap, rcp(&XpetraList, false));
992 }
993#endif
994}
995
996template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
997void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::build22Matrix(const bool reuse, const bool doRebalancing, const int rebalanceStriding, const int numProcsA22) {
998 if (!reuse) { // build fine grid operator for (2,2)-block, Dk_1^T SM Dk_1 (aka TMT)
999 RCP<Teuchos::TimeMonitor> tm = getTimer("Build A22");
1000
1001 Level fineLevel, coarseLevel;
1002 fineLevel.SetFactoryManager(null);
1003 coarseLevel.SetFactoryManager(null);
1004 coarseLevel.SetPreviousLevel(rcpFromRef(fineLevel));
1005 fineLevel.SetLevelID(0);
1006 coarseLevel.SetLevelID(1);
1007 fineLevel.Set("A", SM_Matrix_);
1008 coarseLevel.Set("P", Dk_1_);
1009 coarseLevel.Set("Coordinates", Coords22_);
1010
1011 coarseLevel.setlib(SM_Matrix_->getDomainMap()->lib());
1012 fineLevel.setlib(SM_Matrix_->getDomainMap()->lib());
1013 coarseLevel.setObjectLabel(solverName_ + " (2,2)");
1014 fineLevel.setObjectLabel(solverName_ + " (2,2)");
1015
1016 RCP<RAPFactory> rapFact = rcp(new RAPFactory());
1017 ParameterList rapList = *(rapFact->GetValidParameterList());
1018 rapList.set("transpose: use implicit", true);
1019 rapList.set("rap: fix zero diagonals", parameterList_.get<bool>("rap: fix zero diagonals", true));
1020 rapList.set("rap: fix zero diagonals threshold", parameterList_.get<double>("rap: fix zero diagonals threshold", Teuchos::ScalarTraits<double>::eps()));
1021 rapList.set("rap: triple product", parameterList_.get<bool>("rap: triple product", false));
1022 rapFact->SetParameterList(rapList);
1023
1024 if (!A22_AP_reuse_data_.is_null()) {
1025 coarseLevel.AddKeepFlag("AP reuse data", rapFact.get());
1026 coarseLevel.Set<Teuchos::RCP<Teuchos::ParameterList>>("AP reuse data", A22_AP_reuse_data_, rapFact.get());
1027 }
1028 if (!A22_RAP_reuse_data_.is_null()) {
1029 coarseLevel.AddKeepFlag("RAP reuse data", rapFact.get());
1030 coarseLevel.Set<Teuchos::RCP<Teuchos::ParameterList>>("RAP reuse data", A22_RAP_reuse_data_, rapFact.get());
1031 }
1032
1033#ifdef HAVE_MPI
1034 if (doRebalancing) {
1035 coarseLevel.Set("number of partitions", numProcsA22);
1036 coarseLevel.Set("repartition: heuristic target rows per process", 1000);
1037
1038 std::string partName = precList22_.get<std::string>("repartition: partitioner", "zoltan2");
1039 RCP<Factory> partitioner;
1040 if (partName == "zoltan") {
1041#ifdef HAVE_MUELU_ZOLTAN
1042 partitioner = rcp(new ZoltanInterface());
1043 partitioner->SetFactory("A", rapFact);
1044 // partitioner->SetFactory("number of partitions", repartheurFactory);
1045 // NOTE: ZoltanInteface ("zoltan") does not support external parameters through ParameterList
1046#else
1047 throw Exceptions::RuntimeError("Zoltan interface is not available");
1048#endif
1049 } else if (partName == "zoltan2") {
1050#ifdef HAVE_MUELU_ZOLTAN2
1051 partitioner = rcp(new Zoltan2Interface());
1052 ParameterList partParams;
1053 RCP<const ParameterList> partpartParams = rcp(new ParameterList(precList22_.sublist("repartition: params", false)));
1054 partParams.set("ParameterList", partpartParams);
1055 partitioner->SetParameterList(partParams);
1056 partitioner->SetFactory("A", rapFact);
1057 // partitioner->SetFactory("number of partitions", repartheurFactory);
1058#else
1059 throw Exceptions::RuntimeError("Zoltan2 interface is not available");
1060#endif
1061 }
1062
1063 auto repartFactory = rcp(new RepartitionFactory());
1064 ParameterList repartParams;
1065 repartParams.set("repartition: print partition distribution", precList22_.get<bool>("repartition: print partition distribution", false));
1066 repartParams.set("repartition: remap parts", precList22_.get<bool>("repartition: remap parts", true));
1067 if (rebalanceStriding >= 1) {
1068 bool acceptPart = ((SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank()) % rebalanceStriding) == 0;
1069 if (SM_Matrix_->getDomainMap()->getComm()->getSize() - 1 - SM_Matrix_->getDomainMap()->getComm()->getRank() >= numProcsA22 * rebalanceStriding)
1070 acceptPart = false;
1071 if (acceptPart)
1072 TEUCHOS_ASSERT(coarseA11_.is_null());
1073 repartParams.set("repartition: remap accept partition", acceptPart);
1074 } else
1075 repartParams.set("repartition: remap accept partition", coarseA11_.is_null());
1076 repartFactory->SetParameterList(repartParams);
1077 repartFactory->SetFactory("A", rapFact);
1078 // repartFactory->SetFactory("number of partitions", repartheurFactory);
1079 repartFactory->SetFactory("Partition", partitioner);
1080
1081 auto newP = rcp(new RebalanceTransferFactory());
1082 ParameterList newPparams;
1083 newPparams.set("type", "Interpolation");
1084 newPparams.set("repartition: rebalance P and R", precList22_.get<bool>("repartition: rebalance P and R", false));
1085 newPparams.set("repartition: use subcommunicators", true);
1086 newPparams.set("repartition: rebalance Nullspace", false);
1087 newP->SetFactory("Coordinates", NoFactory::getRCP());
1088 newP->SetParameterList(newPparams);
1089 newP->SetFactory("Importer", repartFactory);
1090
1091 auto newA = rcp(new RebalanceAcFactory());
1092 ParameterList rebAcParams;
1093 rebAcParams.set("repartition: use subcommunicators", true);
1094 newA->SetParameterList(rebAcParams);
1095 newA->SetFactory("A", rapFact);
1096 newA->SetFactory("Importer", repartFactory);
1097
1098 coarseLevel.Request("P", newP.get());
1099 coarseLevel.Request("Importer", repartFactory.get());
1100 coarseLevel.Request("A", newA.get());
1101 coarseLevel.Request("Coordinates", newP.get());
1102 rapFact->Build(fineLevel, coarseLevel);
1103 repartFactory->Build(coarseLevel);
1104
1105 if (!precList22_.get<bool>("repartition: rebalance P and R", false))
1106 Importer22_ = coarseLevel.Get<RCP<const Import>>("Importer", repartFactory.get());
1107 Dk_1_ = coarseLevel.Get<RCP<Matrix>>("P", newP.get());
1108 A22_ = coarseLevel.Get<RCP<Matrix>>("A", newA.get());
1109 Coords22_ = coarseLevel.Get<RCP<RealValuedMultiVector>>("Coordinates", newP.get());
1110
1111 if (!P22_.is_null()) {
1112 // Todo
1113 }
1114
1115 } else
1116#endif // HAVE_MPI
1117 {
1118 coarseLevel.Request("A", rapFact.get());
1119 if (enable_reuse_) {
1120 coarseLevel.Request("AP reuse data", rapFact.get());
1121 coarseLevel.Request("RAP reuse data", rapFact.get());
1122 }
1123
1124 A22_ = coarseLevel.Get<RCP<Matrix>>("A", rapFact.get());
1125
1126 if (enable_reuse_) {
1127 if (coarseLevel.IsAvailable("AP reuse data", rapFact.get()))
1128 A22_AP_reuse_data_ = coarseLevel.Get<RCP<ParameterList>>("AP reuse data", rapFact.get());
1129 if (coarseLevel.IsAvailable("RAP reuse data", rapFact.get()))
1130 A22_RAP_reuse_data_ = coarseLevel.Get<RCP<ParameterList>>("RAP reuse data", rapFact.get());
1131 }
1132 }
1133 } else {
1134 RCP<Teuchos::TimeMonitor> tm = getTimer("Build A22");
1135 if (Importer22_.is_null()) {
1136 RCP<Matrix> temp;
1137 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_, false, *Dk_1_, false, temp, GetOStream(Runtime0), true, true);
1138 if (!implicitTranspose_)
1139 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_, false, *temp, false, A22_, GetOStream(Runtime0), true, true);
1140 else
1141 A22_ = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_, true, *temp, false, A22_, GetOStream(Runtime0), true, true);
1142 } else {
1143 // we replaced domain map and importer on D, reverse that
1144 RCP<const Import> Dimporter = toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter();
1145 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(DorigDomainMap_, DorigImporter_);
1146
1147 RCP<Matrix> temp, temp2;
1148 temp = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*SM_Matrix_, false, *Dk_1_, false, temp, GetOStream(Runtime0), true, true);
1149 if (!implicitTranspose_)
1150 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_T_, false, *temp, false, temp2, GetOStream(Runtime0), true, true);
1151 else
1152 temp2 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Dk_1_, true, *temp, false, temp2, GetOStream(Runtime0), true, true);
1153
1154 // and back again
1155 toCrsMatrix(Dk_1_)->replaceDomainMapAndImporter(Importer22_->getTargetMap(), Dimporter);
1156
1157 ParameterList XpetraList;
1158 XpetraList.set("Restrict Communicator", true);
1159 XpetraList.set("Timer Label", "MueLu::RebalanceA22");
1160 RCP<const Map> targetMap = Importer22_->getTargetMap();
1161 A22_ = MatrixFactory::Build(temp2, *Importer22_, *Importer22_, targetMap, targetMap, rcp(&XpetraList, false));
1162 }
1163 }
1164
1165 if (not A22_.is_null() and not disable_addon_22_ and spaceNumber_ > 1) {
1166 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1167
1168 RCP<Matrix> addon22 = buildAddon(spaceNumber_ - 1);
1169
1170 // add matrices together
1171 RCP<Matrix> newA22;
1172 Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TwoMatrixAdd(*A22_, false, one, *addon22, false, one, newA22, GetOStream(Runtime0));
1173 newA22->fillComplete();
1174 A22_ = newA22;
1175 }
1176
1177 if (!A22_.is_null()) {
1178 dump(A22_, "A22.m");
1179 A22_->setObjectLabel(solverName_ + " (2,2)");
1180 // Set block size
1181 if (spaceNumber_ - 1 == 0)
1182 A22_->SetFixedBlockSize(1);
1183 else
1184 A22_->SetFixedBlockSize(dim_);
1185 }
1186}
1187
1188template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1190 Level level;
1191 RCP<MueLu::FactoryManagerBase> factoryHandler = rcp(new FactoryManager());
1192 level.SetFactoryManager(factoryHandler);
1193 level.SetLevelID(0);
1194 level.setObjectLabel(solverName_ + " (1,1)");
1195 level.Set("A", SM_Matrix_);
1196 level.setlib(SM_Matrix_->getDomainMap()->lib());
1197 // For Hiptmair
1198 level.Set("NodeMatrix", A22_);
1199 level.Set("D0", Dk_1_);
1200
1201 if ((parameterList_.get<std::string>("smoother: pre type") != "NONE") && (parameterList_.get<std::string>("smoother: post type") != "NONE")) {
1202 std::string preSmootherType = parameterList_.get<std::string>("smoother: pre type");
1203 std::string postSmootherType = parameterList_.get<std::string>("smoother: post type");
1204
1205 ParameterList preSmootherList, postSmootherList;
1206 if (parameterList_.isSublist("smoother: pre params"))
1207 preSmootherList = parameterList_.sublist("smoother: pre params");
1208 if (parameterList_.isSublist("smoother: post params"))
1209 postSmootherList = parameterList_.sublist("smoother: post params");
1210
1211 RCP<SmootherPrototype> preSmootherPrototype = rcp(new TrilinosSmoother(preSmootherType, preSmootherList));
1212 RCP<SmootherPrototype> postSmootherPrototype = rcp(new TrilinosSmoother(postSmootherType, postSmootherList));
1213 RCP<SmootherFactory> smootherFact = rcp(new SmootherFactory(preSmootherPrototype, postSmootherPrototype));
1214
1215 level.Request("PreSmoother", smootherFact.get());
1216 level.Request("PostSmoother", smootherFact.get());
1217 if (enable_reuse_) {
1218 ParameterList smootherFactoryParams;
1219 smootherFactoryParams.set("keep smoother data", true);
1220 smootherFact->SetParameterList(smootherFactoryParams);
1221 level.Request("PreSmoother data", smootherFact.get());
1222 level.Request("PostSmoother data", smootherFact.get());
1223 if (!PreSmootherData11_.is_null())
1224 level.Set("PreSmoother data", PreSmootherData11_, smootherFact.get());
1225 if (!PostSmootherData11_.is_null())
1226 level.Set("PostSmoother data", PostSmootherData11_, smootherFact.get());
1227 }
1228 smootherFact->Build(level);
1229 PreSmoother11_ = level.Get<RCP<SmootherBase>>("PreSmoother", smootherFact.get());
1230 PostSmoother11_ = level.Get<RCP<SmootherBase>>("PostSmoother", smootherFact.get());
1231 if (enable_reuse_) {
1232 PreSmootherData11_ = level.Get<RCP<SmootherPrototype>>("PreSmoother data", smootherFact.get());
1233 PostSmootherData11_ = level.Get<RCP<SmootherPrototype>>("PostSmoother data", smootherFact.get());
1234 }
1235 } else {
1236 std::string smootherType = parameterList_.get<std::string>("smoother: type");
1237
1238 ParameterList smootherList;
1239 if (parameterList_.isSublist("smoother: params"))
1240 smootherList = parameterList_.sublist("smoother: params");
1241
1242 RCP<SmootherPrototype> smootherPrototype = rcp(new TrilinosSmoother(smootherType, smootherList));
1243 RCP<SmootherFactory> smootherFact = rcp(new SmootherFactory(smootherPrototype));
1244 level.Request("PreSmoother", smootherFact.get());
1245 if (enable_reuse_) {
1246 ParameterList smootherFactoryParams;
1247 smootherFactoryParams.set("keep smoother data", true);
1248 smootherFact->SetParameterList(smootherFactoryParams);
1249 level.Request("PreSmoother data", smootherFact.get());
1250 if (!PreSmootherData11_.is_null())
1251 level.Set("PreSmoother data", PreSmootherData11_, smootherFact.get());
1252 }
1253 smootherFact->Build(level);
1254 PreSmoother11_ = level.Get<RCP<SmootherBase>>("PreSmoother", smootherFact.get());
1256 if (enable_reuse_)
1257 PreSmootherData11_ = level.Get<RCP<SmootherPrototype>>("PreSmoother data", smootherFact.get());
1258 }
1259}
1260
1261template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1263 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer("Allocate MVs");
1264
1265 // 11 block
1266 if (!R11_.is_null())
1267 P11res_ = MultiVectorFactory::Build(R11_->getRangeMap(), numVectors);
1268 else
1269 P11res_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1270 P11res_->setObjectLabel("P11res");
1271
1273 DTR11Tmp_ = MultiVectorFactory::Build(R11_->getColMap(), numVectors);
1274 DTR11Tmp_->setObjectLabel("DTR11Tmp");
1275 }
1276 if (!ImporterCoarse11_.is_null()) {
1277 P11resTmp_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1278 P11resTmp_->setObjectLabel("P11resTmp");
1279 P11x_ = MultiVectorFactory::Build(ImporterCoarse11_->getTargetMap(), numVectors);
1280 } else
1281 P11x_ = MultiVectorFactory::Build(P11_->getDomainMap(), numVectors);
1282 P11x_->setObjectLabel("P11x");
1283
1284 // 22 block
1285 if (!Dk_1_T_.is_null())
1286 Dres_ = MultiVectorFactory::Build(Dk_1_T_->getRangeMap(), numVectors);
1287 else
1288 Dres_ = MultiVectorFactory::Build(Dk_1_->getDomainMap(), numVectors);
1289 Dres_->setObjectLabel("Dres");
1290
1291 if (!Importer22_.is_null()) {
1292 DresTmp_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1293 DresTmp_->setObjectLabel("DresTmp");
1294 Dx_ = MultiVectorFactory::Build(Importer22_->getTargetMap(), numVectors);
1295 } else if (!onlyBoundary22_)
1296 Dx_ = MultiVectorFactory::Build(A22_->getDomainMap(), numVectors);
1297 if (!Dx_.is_null())
1298 Dx_->setObjectLabel("Dx");
1299
1300 if (!coarseA11_.is_null()) {
1301 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
1302 P11resSubComm_ = MultiVectorFactory::Build(P11resTmp_, Teuchos::View);
1303 else
1304 P11resSubComm_ = MultiVectorFactory::Build(P11res_, Teuchos::View);
1305 P11resSubComm_->replaceMap(coarseA11_->getRangeMap());
1306 P11resSubComm_->setObjectLabel("P11resSubComm");
1307
1308 P11xSubComm_ = MultiVectorFactory::Build(P11x_, Teuchos::View);
1309 P11xSubComm_->replaceMap(coarseA11_->getDomainMap());
1310 P11xSubComm_->setObjectLabel("P11xSubComm");
1311 }
1312
1313 if (!A22_.is_null()) {
1314 if (!Importer22_.is_null() && !implicitTranspose_)
1315 DresSubComm_ = MultiVectorFactory::Build(DresTmp_, Teuchos::View);
1316 else
1317 DresSubComm_ = MultiVectorFactory::Build(Dres_, Teuchos::View);
1318 DresSubComm_->replaceMap(A22_->getRangeMap());
1319 DresSubComm_->setObjectLabel("DresSubComm");
1320
1321 DxSubComm_ = MultiVectorFactory::Build(Dx_, Teuchos::View);
1322 DxSubComm_->replaceMap(A22_->getDomainMap());
1323 DxSubComm_->setObjectLabel("DxSubComm");
1324 }
1325
1326 if (asyncTransfers_) {
1327 if (!toCrsMatrix(P11_)->getCrsGraph()->getImporter().is_null())
1328 P11x_colmap_ = MultiVectorFactory::Build(P11_->getColMap(), numVectors);
1329 if (!toCrsMatrix(Dk_1_)->getCrsGraph()->getImporter().is_null())
1330 Dx_colmap_ = MultiVectorFactory::Build(Dk_1_->getColMap(), numVectors);
1331 }
1332
1333 residual_ = MultiVectorFactory::Build(SM_Matrix_->getDomainMap(), numVectors);
1334 residual_->setObjectLabel("residual");
1335}
1336
1337template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1338void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dump(const RCP<Matrix> &A, std::string name) const {
1339 if (dump_matrices_ && !A.is_null()) {
1340 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
1341 Xpetra::IO<SC, LO, GO, NO>::Write(name, *A);
1342 }
1343}
1344
1345template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1346void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dump(const RCP<MultiVector> &X, std::string name) const {
1347 if (dump_matrices_ && !X.is_null()) {
1348 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
1349 Xpetra::IO<SC, LO, GO, NO>::Write(name, *X);
1350 }
1351}
1352
1353template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1354void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dumpCoords(const RCP<RealValuedMultiVector> &X, std::string name) const {
1355 if (dump_matrices_ && !X.is_null()) {
1356 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
1357 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, *X);
1358 }
1359}
1360
1361template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1362void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dump(const Teuchos::ArrayRCP<bool> &v, std::string name) const {
1363 if (dump_matrices_) {
1364 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
1365 std::ofstream out(name);
1366 for (size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
1367 out << v[i] << "\n";
1368 }
1369}
1370
1371template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1372void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dump(const Kokkos::View<bool *, typename Node::device_type> &v, std::string name) const {
1373 if (dump_matrices_) {
1374 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
1375 std::ofstream out(name);
1376 auto vH = Kokkos::create_mirror_view(v);
1377 Kokkos::deep_copy(vH, v);
1378 out << "%%MatrixMarket matrix array real general\n"
1379 << vH.extent(0) << " 1\n";
1380 for (size_t i = 0; i < vH.size(); i++)
1381 out << vH[i] << "\n";
1382 }
1383}
1384
1385template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1386Teuchos::RCP<Teuchos::TimeMonitor> RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::getTimer(std::string name, RCP<const Teuchos::Comm<int>> comm) const {
1387 if (IsPrint(Timings)) {
1388 if (!syncTimers_)
1389 return Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer("MueLu " + solverName_ + ": " + name)));
1390 else {
1391 if (comm.is_null()) {
1392 {
1393 Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer("MueLu " + solverName_ + ": " + name + "_barrier")));
1394 SM_Matrix_->getRowMap()->getComm()->barrier();
1395 }
1396 return Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer("MueLu " + solverName_ + ": " + name)));
1397 } else {
1398 {
1399 Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer("MueLu " + solverName_ + ": " + name + "_barrier")));
1400 comm->barrier();
1401 }
1402 return Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer("MueLu " + solverName_ + ": " + name)));
1403 }
1404 }
1405 } else
1406 return Teuchos::null;
1407}
1408
1409template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1410RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1411 buildNullspace(const int spaceNumber, const Kokkos::View<bool *, typename Node::device_type> &bcs, const bool applyBCs) {
1412 std::string spaceLabel;
1413 if (spaceNumber == 0)
1414 spaceLabel = "nodal";
1415 else if (spaceNumber == 1)
1416 spaceLabel = "edge";
1417 else if (spaceNumber == 2)
1418 spaceLabel = "face";
1419 else {
1420 TEUCHOS_ASSERT(false);
1421 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1422 }
1423
1424 RCP<Teuchos::TimeMonitor> tm;
1425 if (spaceNumber > 0) {
1426 tm = getTimer("nullspace " + spaceLabel);
1427 GetOStream(Runtime0) << solverName_ + "::compute(): building " + spaceLabel + " nullspace" << std::endl;
1428 }
1429
1430 if (spaceNumber == 0) {
1431 return Teuchos::null;
1432
1433 } else if (spaceNumber == 1) {
1434 RCP<MultiVector> CoordsSC;
1436 RCP<MultiVector> Nullspace = MultiVectorFactory::Build(D0_->getRowMap(), NodalCoords_->getNumVectors());
1437 D0_->apply(*CoordsSC, *Nullspace);
1438
1439 bool normalize = parameterList_.get<bool>("refmaxwell: normalize nullspace", MasterList::getDefault<bool>("refmaxwell: normalize nullspace"));
1440
1441 coordinateType minLen, maxLen, meanLen;
1442 if (IsPrint(Statistics2) || normalize) {
1443 // compute edge lengths
1444 ArrayRCP<ArrayRCP<const Scalar>> localNullspace(dim_);
1445 for (size_t i = 0; i < dim_; i++)
1446 localNullspace[i] = Nullspace->getData(i);
1447 coordinateType localMinLen = Teuchos::ScalarTraits<coordinateType>::rmax();
1448 coordinateType localMeanLen = Teuchos::ScalarTraits<coordinateType>::zero();
1449 coordinateType localMaxLen = Teuchos::ScalarTraits<coordinateType>::zero();
1450 for (size_t j = 0; j < Nullspace->getMap()->getLocalNumElements(); j++) {
1451 Scalar lenSC = Teuchos::ScalarTraits<Scalar>::zero();
1452 for (size_t i = 0; i < dim_; i++)
1453 lenSC += localNullspace[i][j] * localNullspace[i][j];
1454 coordinateType len = Teuchos::as<coordinateType>(Teuchos::ScalarTraits<Scalar>::real(Teuchos::ScalarTraits<Scalar>::squareroot(lenSC)));
1455 localMinLen = std::min(localMinLen, len);
1456 localMaxLen = std::max(localMaxLen, len);
1457 localMeanLen += len;
1458 }
1459
1460 RCP<const Teuchos::Comm<int>> comm = Nullspace->getMap()->getComm();
1461 MueLu_minAll(comm, localMinLen, minLen);
1462 MueLu_sumAll(comm, localMeanLen, meanLen);
1463 MueLu_maxAll(comm, localMaxLen, maxLen);
1464 meanLen /= Nullspace->getMap()->getGlobalNumElements();
1465 }
1466
1467 if (IsPrint(Statistics2)) {
1468 GetOStream(Statistics2) << "Edge length (min/mean/max): " << minLen << " / " << meanLen << " / " << maxLen << std::endl;
1469 }
1470
1471 if (normalize) {
1472 // normalize the nullspace
1473 GetOStream(Runtime0) << solverName_ + "::compute(): normalizing nullspace" << std::endl;
1474
1475 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1476
1477 Array<Scalar> normsSC(NodalCoords_->getNumVectors(), one / Teuchos::as<Scalar>(meanLen));
1478 Nullspace->scale(normsSC());
1479 }
1480
1481 if (applyBCs) {
1482 // Nuke the BC edges in nullspace
1483 Utilities::ZeroDirichletRows(Nullspace, bcs);
1484 }
1485 dump(Nullspace, "nullspaceEdge.m");
1486
1487 return Nullspace;
1488
1489 } else if (spaceNumber == 2) {
1490#if KOKKOS_VERSION >= 40799
1491 using ATS = KokkosKernels::ArithTraits<Scalar>;
1492#else
1493 using ATS = Kokkos::ArithTraits<Scalar>;
1494#endif
1495 using impl_Scalar = typename ATS::val_type;
1496#if KOKKOS_VERSION >= 40799
1497 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1498#else
1499 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
1500#endif
1501 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1502
1503 RCP<Matrix> facesToNodes;
1504 {
1505 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1507
1508 // dump(edgesToNodes, "edgesToNodes.m");
1509
1510 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1512 facesToEdges = Maxwell_Utils<SC, LO, GO, NO>::removeExplicitZeros(facesToEdges, 1e-3, false);
1513
1514 // dump(facesToEdges, "facesToEdges.m");
1515
1516 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges, false, *edgesToNodes, false, facesToNodes, GetOStream(Runtime0), true, true);
1518 facesToNodes = Maxwell_Utils<SC, LO, GO, NO>::removeExplicitZeros(facesToNodes, 1e-3, false);
1519 }
1520
1521 // dump(facesToNodes, "facesToNodes.m");
1522
1523 RCP<RealValuedMultiVector> ghostedNodalCoordinates;
1524 auto importer = facesToNodes->getCrsGraph()->getImporter();
1525 if (!importer.is_null()) {
1526 ghostedNodalCoordinates = Xpetra::MultiVectorFactory<coordinateType, LocalOrdinal, GlobalOrdinal, Node>::Build(importer->getTargetMap(), dim_);
1527 ghostedNodalCoordinates->doImport(*NodalCoords_, *importer, Xpetra::INSERT);
1528 } else
1529 ghostedNodalCoordinates = NodalCoords_;
1530
1531 RCP<MultiVector> Nullspace = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(facesToNodes->getRangeMap(), dim_);
1532 {
1533 auto facesToNodesLocal = facesToNodes->getLocalMatrixDevice();
1534 auto localNodalCoordinates = ghostedNodalCoordinates->getLocalViewDevice(Tpetra::Access::ReadOnly);
1535 auto localFaceNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1536
1537 // enter values
1538 Kokkos::parallel_for(
1539 solverName_ + "::buildFaceProjection_nullspace",
1540 range_type(0, Nullspace->getMap()->getLocalNumElements()),
1541 KOKKOS_LAMBDA(const size_t f) {
1542 size_t n0 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f));
1543 size_t n1 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 1);
1544 size_t n2 = facesToNodesLocal.graph.entries(facesToNodesLocal.graph.row_map(f) + 2);
1545 impl_Scalar elementNullspace00 = localNodalCoordinates(n1, 0) - localNodalCoordinates(n0, 0);
1546 impl_Scalar elementNullspace10 = localNodalCoordinates(n2, 0) - localNodalCoordinates(n0, 0);
1547 impl_Scalar elementNullspace01 = localNodalCoordinates(n1, 1) - localNodalCoordinates(n0, 1);
1548 impl_Scalar elementNullspace11 = localNodalCoordinates(n2, 1) - localNodalCoordinates(n0, 1);
1549 impl_Scalar elementNullspace02 = localNodalCoordinates(n1, 2) - localNodalCoordinates(n0, 2);
1550 impl_Scalar elementNullspace12 = localNodalCoordinates(n2, 2) - localNodalCoordinates(n0, 2);
1551
1552 localFaceNullspace(f, 0) = impl_ATS::magnitude(elementNullspace01 * elementNullspace12 - elementNullspace02 * elementNullspace11) / 6.0;
1553 localFaceNullspace(f, 1) = impl_ATS::magnitude(elementNullspace02 * elementNullspace10 - elementNullspace00 * elementNullspace12) / 6.0;
1554 localFaceNullspace(f, 2) = impl_ATS::magnitude(elementNullspace00 * elementNullspace11 - elementNullspace01 * elementNullspace10) / 6.0;
1555 });
1556 }
1557
1558 if (applyBCs) {
1559 // Nuke the BC faces in nullspace
1560 Utilities::ZeroDirichletRows(Nullspace, bcs);
1561 }
1562
1563 dump(Nullspace, "nullspaceFace.m");
1564
1565 return Nullspace;
1566
1567 } else {
1568 TEUCHOS_ASSERT(false);
1569 TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
1570 }
1571}
1572
1573template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1574Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1575RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::buildProjection(const int spaceNumber, const RCP<MultiVector> &Nullspace) const {
1576#if KOKKOS_VERSION >= 40799
1577 using ATS = KokkosKernels::ArithTraits<Scalar>;
1578#else
1579 using ATS = Kokkos::ArithTraits<Scalar>;
1580#endif
1581 using impl_Scalar = typename ATS::val_type;
1582#if KOKKOS_VERSION >= 40799
1583 using impl_ATS = KokkosKernels::ArithTraits<impl_Scalar>;
1584#else
1585 using impl_ATS = Kokkos::ArithTraits<impl_Scalar>;
1586#endif
1587 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1588
1589 typedef typename Matrix::local_matrix_device_type KCRS;
1590 typedef typename KCRS::StaticCrsGraphType graph_t;
1591 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1592 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1593 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1594
1595 const impl_Scalar impl_SC_ONE = impl_ATS::one();
1596 const impl_Scalar impl_SC_ZERO = impl_ATS::zero();
1597 const impl_Scalar impl_half = impl_SC_ONE / (impl_SC_ONE + impl_SC_ONE);
1598
1599 std::string spaceLabel;
1600 if (spaceNumber == 0)
1601 spaceLabel = "nodal";
1602 else if (spaceNumber == 1)
1603 spaceLabel = "edge";
1604 else if (spaceNumber == 2)
1605 spaceLabel = "face";
1606 else
1607 TEUCHOS_ASSERT(false);
1608
1609 RCP<Teuchos::TimeMonitor> tm;
1610 if (spaceNumber > 0) {
1611 tm = getTimer("projection " + spaceLabel);
1612 GetOStream(Runtime0) << solverName_ + "::compute(): building " + spaceLabel + " projection" << std::endl;
1613 }
1614
1615 RCP<Matrix> incidence;
1616 if (spaceNumber == 0) {
1617 // identity projection
1618 return Teuchos::null;
1619
1620 } else if (spaceNumber == 1) {
1621 // D0 is incidence from nodes to edges
1622 incidence = D0_;
1623
1624 } else if (spaceNumber == 2) {
1625 // get incidence from nodes to faces by multiplying D0 and D1
1626
1627 TEUCHOS_ASSERT(spaceNumber_ == 2);
1628
1629 RCP<Matrix> facesToNodes;
1630 {
1631 RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(D0_);
1633
1634 dump(edgesToNodes, "edgesToNodes.m");
1635
1636 RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(Dk_1_);
1638 // facesToEdges = Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(facesToEdges, 1e-2, false);
1639
1640 dump(facesToEdges, "facesToEdges.m");
1641
1642 facesToNodes = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*facesToEdges, false, *edgesToNodes, false, facesToNodes, GetOStream(Runtime0), true, true);
1644 facesToNodes = Maxwell_Utils<SC, LO, GO, NO>::removeExplicitZeros(facesToNodes, 1e-2, false);
1645 }
1646
1647 dump(facesToNodes, "facesToNodes.m");
1648
1649 incidence = facesToNodes;
1650
1651 } else
1652 TEUCHOS_ASSERT(false);
1653
1654 size_t dim = dim_;
1655
1656 // Create maps
1657 RCP<const Map> rowMap = incidence->getRowMap();
1658 RCP<const Map> blockColMap = MapFactory::Build(incidence->getColMap(), dim);
1659 RCP<const Map> blockDomainMap = MapFactory::Build(incidence->getDomainMap(), dim);
1660
1661 auto localIncidence = incidence->getLocalMatrixDevice();
1662 size_t numLocalRows = rowMap->getLocalNumElements();
1663 size_t numLocalColumns = dim * incidence->getColMap()->getLocalNumElements();
1664 size_t nnzEstimate = dim * localIncidence.graph.entries.size();
1665 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing("projection_rowptr_" + spaceLabel), numLocalRows + 1);
1666 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing("projection_colind_" + spaceLabel), nnzEstimate);
1667 scalar_view_t vals("projection_vals_" + spaceLabel, nnzEstimate);
1668
1669 // set rowpointer
1670 Kokkos::parallel_for(
1671 solverName_ + "::buildProjection_adjustRowptr_" + spaceLabel,
1672 range_type(0, numLocalRows + 1),
1673 KOKKOS_LAMBDA(const size_t i) {
1674 rowptr(i) = dim * localIncidence.graph.row_map(i);
1675 });
1676
1677 auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1678
1679 // set column indices and values
1680 magnitudeType tol = 1e-5;
1681 Kokkos::parallel_for(
1682 solverName_ + "::buildProjection_enterValues_" + spaceLabel,
1683 range_type(0, numLocalRows),
1684 KOKKOS_LAMBDA(const size_t f) {
1685 for (size_t jj = localIncidence.graph.row_map(f); jj < localIncidence.graph.row_map(f + 1); jj++) {
1686 for (size_t k = 0; k < dim; k++) {
1687 colind(dim * jj + k) = dim * localIncidence.graph.entries(jj) + k;
1688 if (impl_ATS::magnitude(localIncidence.values(jj)) > tol)
1689 vals(dim * jj + k) = impl_half * localNullspace(f, k);
1690 else
1691 vals(dim * jj + k) = impl_SC_ZERO;
1692 }
1693 }
1694 });
1695
1696 // Create matrix
1697 typename CrsMatrix::local_matrix_device_type lclProjection("local projection " + spaceLabel,
1698 numLocalRows, numLocalColumns, nnzEstimate,
1699 vals, rowptr, colind);
1700 RCP<Matrix> projection = MatrixFactory::Build(lclProjection,
1701 rowMap, blockColMap,
1702 blockDomainMap, rowMap);
1703
1704 return projection;
1705}
1706
1707template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1709 Teuchos::RCP<Matrix> &P_nodal,
1710 Teuchos::RCP<MultiVector> &Nullspace_nodal,
1711 Teuchos::RCP<RealValuedMultiVector> &CoarseCoords_nodal) const {
1712 RCP<Teuchos::TimeMonitor> tm = getTimer("nodal prolongator");
1713 GetOStream(Runtime0) << solverName_ + "::compute(): building nodal prolongator" << std::endl;
1714
1715 // build prolongator: algorithm 1 in the reference paper
1716 // First, build nodal unsmoothed prolongator using the matrix A_nodal
1717
1718 const SC SC_ONE = Teuchos::ScalarTraits<SC>::one();
1719
1720 {
1721 Level fineLevel, coarseLevel;
1722 fineLevel.SetFactoryManager(null);
1723 coarseLevel.SetFactoryManager(null);
1724 coarseLevel.SetPreviousLevel(rcpFromRef(fineLevel));
1725 fineLevel.SetLevelID(0);
1726 coarseLevel.SetLevelID(1);
1727 fineLevel.Set("A", A_nodal);
1728 fineLevel.Set("Coordinates", NodalCoords_);
1729 fineLevel.Set("DofsPerNode", 1);
1730 coarseLevel.setlib(A_nodal->getDomainMap()->lib());
1731 fineLevel.setlib(A_nodal->getDomainMap()->lib());
1732 coarseLevel.setObjectLabel(A_nodal->getObjectLabel());
1733 fineLevel.setObjectLabel(A_nodal->getObjectLabel());
1734
1735 LocalOrdinal NSdim = 1;
1736 RCP<MultiVector> nullSpace = MultiVectorFactory::Build(A_nodal->getRowMap(), NSdim);
1737 nullSpace->putScalar(SC_ONE);
1738 fineLevel.Set("Nullspace", nullSpace);
1739
1740 std::string algo = parameterList_.get<std::string>("multigrid algorithm");
1741
1742 RCP<Factory> amalgFact, dropFact, UncoupledAggFact, coarseMapFact, TentativePFact, Tfact, SaPFact;
1743 amalgFact = rcp(new AmalgamationFactory());
1744 coarseMapFact = rcp(new CoarseMapFactory());
1745 Tfact = rcp(new CoordinatesTransferFactory());
1746 UncoupledAggFact = rcp(new UncoupledAggregationFactory());
1747 if (useKokkos_) {
1748 dropFact = rcp(new CoalesceDropFactory_kokkos());
1749 TentativePFact = rcp(new TentativePFactory_kokkos());
1750 } else {
1751 dropFact = rcp(new CoalesceDropFactory());
1752 TentativePFact = rcp(new TentativePFactory());
1753 }
1754 if (algo == "sa")
1755 SaPFact = rcp(new SaPFactory());
1756 dropFact->SetFactory("UnAmalgamationInfo", amalgFact);
1757
1758 double dropTol = parameterList_.get<double>("aggregation: drop tol");
1759 std::string dropScheme = parameterList_.get<std::string>("aggregation: drop scheme");
1760 std::string distLaplAlgo = parameterList_.get<std::string>("aggregation: distance laplacian algo");
1761 dropFact->SetParameter("aggregation: drop tol", Teuchos::ParameterEntry(dropTol));
1762 dropFact->SetParameter("aggregation: drop scheme", Teuchos::ParameterEntry(dropScheme));
1763 dropFact->SetParameter("aggregation: distance laplacian algo", Teuchos::ParameterEntry(distLaplAlgo));
1764
1765 UncoupledAggFact->SetFactory("Graph", dropFact);
1766 int minAggSize = parameterList_.get<int>("aggregation: min agg size");
1767 UncoupledAggFact->SetParameter("aggregation: min agg size", Teuchos::ParameterEntry(minAggSize));
1768 int maxAggSize = parameterList_.get<int>("aggregation: max agg size");
1769 UncoupledAggFact->SetParameter("aggregation: max agg size", Teuchos::ParameterEntry(maxAggSize));
1770 bool matchMLbehavior1 = parameterList_.get<bool>("aggregation: match ML phase1");
1771 UncoupledAggFact->SetParameter("aggregation: match ML phase1", Teuchos::ParameterEntry(matchMLbehavior1));
1772 bool matchMLbehavior2a = parameterList_.get<bool>("aggregation: match ML phase2a");
1773 UncoupledAggFact->SetParameter("aggregation: match ML phase2a", Teuchos::ParameterEntry(matchMLbehavior2a));
1774 bool matchMLbehavior2b = parameterList_.get<bool>("aggregation: match ML phase2b");
1775 UncoupledAggFact->SetParameter("aggregation: match ML phase2b", Teuchos::ParameterEntry(matchMLbehavior2b));
1776
1777 coarseMapFact->SetFactory("Aggregates", UncoupledAggFact);
1778
1779 TentativePFact->SetFactory("Aggregates", UncoupledAggFact);
1780 TentativePFact->SetFactory("UnAmalgamationInfo", amalgFact);
1781 TentativePFact->SetFactory("CoarseMap", coarseMapFact);
1782
1783 Tfact->SetFactory("Aggregates", UncoupledAggFact);
1784 Tfact->SetFactory("CoarseMap", coarseMapFact);
1785
1786 if (algo == "sa") {
1787 SaPFact->SetFactory("P", TentativePFact);
1788 coarseLevel.Request("P", SaPFact.get());
1789 } else
1790 coarseLevel.Request("P", TentativePFact.get());
1791 coarseLevel.Request("Nullspace", TentativePFact.get());
1792 coarseLevel.Request("Coordinates", Tfact.get());
1793
1794 RCP<AggregationExportFactory> aggExport;
1795 bool exportVizData = parameterList_.get<bool>("aggregation: export visualization data");
1796 if (exportVizData) {
1797 aggExport = rcp(new AggregationExportFactory());
1798 ParameterList aggExportParams;
1799 aggExportParams.set("aggregation: output filename", "aggs.vtk");
1800 aggExportParams.set("aggregation: output file: agg style", "Jacks");
1801 aggExport->SetParameterList(aggExportParams);
1802
1803 aggExport->SetFactory("Aggregates", UncoupledAggFact);
1804 aggExport->SetFactory("UnAmalgamationInfo", amalgFact);
1805 fineLevel.Request("Aggregates", UncoupledAggFact.get());
1806 fineLevel.Request("UnAmalgamationInfo", amalgFact.get());
1807 }
1808
1809 if (algo == "sa")
1810 coarseLevel.Get("P", P_nodal, SaPFact.get());
1811 else
1812 coarseLevel.Get("P", P_nodal, TentativePFact.get());
1813 coarseLevel.Get("Nullspace", Nullspace_nodal, TentativePFact.get());
1814 coarseLevel.Get("Coordinates", CoarseCoords_nodal, Tfact.get());
1815
1816 if (exportVizData)
1817 aggExport->Build(fineLevel, coarseLevel);
1818 }
1819}
1820
1821template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1822Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
1824 RCP<Teuchos::TimeMonitor> tm = getTimer("vectorial nodal prolongator");
1825 GetOStream(Runtime0) << solverName_ + "::compute(): building vectorial nodal prolongator" << std::endl;
1826
1827 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1828
1829 typedef typename Matrix::local_matrix_device_type KCRS;
1830 typedef typename KCRS::StaticCrsGraphType graph_t;
1831 typedef typename graph_t::row_map_type::non_const_type lno_view_t;
1832 typedef typename graph_t::entries_type::non_const_type lno_nnz_view_t;
1833 typedef typename KCRS::values_type::non_const_type scalar_view_t;
1834
1835 size_t dim = dim_;
1836
1837 // Create the matrix object
1838 RCP<Map> blockRowMap = MapFactory::Build(P_nodal->getRowMap(), dim);
1839 RCP<Map> blockColMap = MapFactory::Build(P_nodal->getColMap(), dim);
1840 RCP<Map> blockDomainMap = MapFactory::Build(P_nodal->getDomainMap(), dim);
1841
1842 // Get data out of P_nodal.
1843 auto localP_nodal = P_nodal->getLocalMatrixDevice();
1844
1845 size_t numLocalRows = blockRowMap->getLocalNumElements();
1846 size_t numLocalColumns = blockColMap->getLocalNumElements();
1847 size_t nnzEstimate = dim * localP_nodal.graph.entries.size();
1848 lno_view_t rowptr(Kokkos::ViewAllocateWithoutInitializing("vectorPNodal_rowptr"), numLocalRows + 1);
1849 lno_nnz_view_t colind(Kokkos::ViewAllocateWithoutInitializing("vectorPNodal_colind"), nnzEstimate);
1850 scalar_view_t vals(Kokkos::ViewAllocateWithoutInitializing("vectorPNodal_vals"), nnzEstimate);
1851
1852 // fill rowpointer
1853 Kokkos::parallel_for(
1854 solverName_ + "::buildVectorNodalProlongator_adjustRowptr",
1855 range_type(0, localP_nodal.numRows() + 1),
1856 KOKKOS_LAMBDA(const LocalOrdinal i) {
1857 if (i < localP_nodal.numRows()) {
1858 for (size_t k = 0; k < dim; k++) {
1859 rowptr(dim * i + k) = dim * localP_nodal.graph.row_map(i) + k;
1860 }
1861 } else
1862 rowptr(dim * localP_nodal.numRows()) = dim * localP_nodal.graph.row_map(i);
1863 });
1864
1865 // fill column indices and values
1866 Kokkos::parallel_for(
1867 solverName_ + "::buildVectorNodalProlongator_adjustColind",
1868 range_type(0, localP_nodal.graph.entries.size()),
1869 KOKKOS_LAMBDA(const size_t jj) {
1870 for (size_t k = 0; k < dim; k++) {
1871 colind(dim * jj + k) = dim * localP_nodal.graph.entries(jj) + k;
1872 // vals(dim*jj+k) = localP_nodal.values(jj);
1873 vals(dim * jj + k) = 1.;
1874 }
1875 });
1876
1877 typename CrsMatrix::local_matrix_device_type lclVectorNodalP("local vector nodal prolongator",
1878 numLocalRows, numLocalColumns, nnzEstimate,
1879 vals, rowptr, colind);
1880 RCP<Matrix> vectorNodalP = MatrixFactory::Build(lclVectorNodalP,
1881 blockRowMap, blockColMap,
1882 blockDomainMap, blockRowMap);
1883
1884 return vectorNodalP;
1885}
1886
1887template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1889 buildProlongator(const int spaceNumber,
1890 const Teuchos::RCP<Matrix> &A_nodal,
1891 const Teuchos::RCP<MultiVector> &Nullspace,
1892 Teuchos::RCP<Matrix> &Prolongator,
1893 Teuchos::RCP<MultiVector> &coarseNullspace,
1894 Teuchos::RCP<RealValuedMultiVector> &coarseNodalCoords) const {
1895#if KOKKOS_VERSION >= 40799
1896 using ATS = KokkosKernels::ArithTraits<Scalar>;
1897#else
1898 using ATS = Kokkos::ArithTraits<Scalar>;
1899#endif
1900 using impl_Scalar = typename ATS::val_type;
1901 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1902
1903 std::string typeStr;
1904 switch (spaceNumber) {
1905 case 0:
1906 typeStr = "node";
1907 TEUCHOS_ASSERT(A_nodal.is_null());
1908 break;
1909 case 1:
1910 typeStr = "edge";
1911 break;
1912 case 2:
1913 typeStr = "face";
1914 break;
1915 default:
1916 TEUCHOS_ASSERT(false);
1917 }
1918
1919 const bool skipFirstLevel = !A_nodal.is_null();
1920
1921 RCP<Teuchos::TimeMonitor> tm;
1922 if (spaceNumber > 0) {
1923 tm = getTimer("special prolongator " + typeStr);
1924 GetOStream(Runtime0) << solverName_ + "::compute(): building special " + typeStr + " prolongator" << std::endl;
1925 }
1926
1927 RCP<Matrix> projection = buildProjection(spaceNumber, Nullspace);
1928 dump(projection, typeStr + "Projection.m");
1929
1930 if (skipFirstLevel) {
1931 RCP<Matrix> P_nodal;
1932 RCP<MultiVector> coarseNodalNullspace;
1933
1934 buildNodalProlongator(A_nodal, P_nodal, coarseNodalNullspace, coarseNodalCoords);
1935
1936 dump(P_nodal, "P_nodal_" + typeStr + ".m");
1937 dump(coarseNodalNullspace, "coarseNullspace_nodal_" + typeStr + ".m");
1938
1939 RCP<Matrix> vectorP_nodal = buildVectorNodalProlongator(P_nodal);
1940
1941 dump(vectorP_nodal, "vectorP_nodal_" + typeStr + ".m");
1942
1943 Prolongator = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*projection, false, *vectorP_nodal, false, Prolongator, GetOStream(Runtime0), true, true);
1944
1945 // This is how ML computes P22 for Darcy.
1946 // The difference is the scaling by nonzeros. I don't think that that is actually needed.
1947 //
1948 // if (spaceNumber==2) {
1949
1950 // RCP<Matrix> facesToNodes, aggsToFaces;
1951 // {
1952 // RCP<Matrix> edgesToNodes = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::BuildCopy(D0_);
1953 // Maxwell_Utils<SC,LO,GO,NO>::thresholdedAbs(edgesToNodes, 1e-10);
1954
1955 // dump(edgesToNodes, "edgesToNodes.m");
1956
1957 // RCP<Matrix> facesToEdges = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::BuildCopy(Dk_1_);
1958 // Maxwell_Utils<SC,LO,GO,NO>::thresholdedAbs(facesToEdges, 1e-10);
1959 // // facesToEdges = Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(facesToEdges, 1e-2, false);
1960
1961 // dump(facesToEdges, "facesToEdges.m");
1962
1963 // facesToNodes = Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*facesToEdges,false,*edgesToNodes,false,facesToNodes,GetOStream(Runtime0),true,true);
1964 // Maxwell_Utils<SC,LO,GO,NO>::thresholdedAbs(facesToNodes, 1e-10);
1965 // facesToNodes = Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(facesToNodes, 1e-2, false);
1966 // }
1967 // aggsToFaces = Xpetra::MatrixMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Multiply(*facesToNodes,false,*P_nodal,false,aggsToFaces,GetOStream(Runtime0),true,true);
1968
1969 // auto localP = Prolongator->getLocalMatrixDevice();
1970 // auto localAggsToFaces = aggsToFaces->getLocalMatrixDevice();
1971 // auto localNullspace = Nullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1972
1973 // size_t dim = dim_;
1974 // Kokkos::parallel_for(solverName_+"::buildVectorNodalProlongator_adjustRowptr",
1975 // range_type(0,localP.numRows()),
1976 // KOKKOS_LAMBDA(const LocalOrdinal i) {
1977 // LocalOrdinal nonzeros = localAggsToFaces.graph.row_map(i+1)-localAggsToFaces.graph.row_map(i);
1978 // for (LocalOrdinal jj = localAggsToFaces.graph.row_map(i); jj < localAggsToFaces.graph.row_map(i+1); jj++ ) {
1979 // LocalOrdinal j = localAggsToFaces.graph.entries(jj);
1980 // for (LocalOrdinal k = 0; k<dim; k++)
1981 // for (LocalOrdinal kk = localP.graph.row_map(i); kk < localP.graph.row_map(i+1); kk++)
1982 // if (localP.graph.entries(kk) == (dim * j+k)) {
1983 // localP.values(kk) = localNullspace(i, k) / nonzeros;
1984 // break;
1985 // }
1986 // }
1987 // });
1988 // }
1989 //
1990
1991 size_t dim = dim_;
1992 coarseNullspace = MultiVectorFactory::Build(vectorP_nodal->getDomainMap(), dim);
1993
1994 auto localNullspace_nodal = coarseNodalNullspace->getLocalViewDevice(Tpetra::Access::ReadOnly);
1995 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
1996 Kokkos::parallel_for(
1997 solverName_ + "::buildProlongator_nullspace_" + typeStr,
1998 range_type(0, coarseNodalNullspace->getLocalLength()),
1999 KOKKOS_LAMBDA(const size_t i) {
2000 impl_Scalar val = localNullspace_nodal(i, 0);
2001 for (size_t j = 0; j < dim; j++)
2002 localNullspace_coarse(dim * i + j, j) = val;
2003 });
2004
2005 } else {
2006 Prolongator = projection;
2007 coarseNodalCoords = NodalCoords_;
2008
2009 if (spaceNumber == 0) {
2010 // nothing, just use the default constant vector
2011 } else if (spaceNumber >= 1) {
2012 size_t dim = dim_;
2013 coarseNullspace = MultiVectorFactory::Build(projection->getDomainMap(), dim);
2014 auto localNullspace_coarse = coarseNullspace->getLocalViewDevice(Tpetra::Access::ReadWrite);
2015 Kokkos::parallel_for(
2016 solverName_ + "::buildProlongator_nullspace_" + typeStr,
2017 range_type(0, coarseNullspace->getLocalLength() / dim),
2018 KOKKOS_LAMBDA(const size_t i) {
2019 for (size_t j = 0; j < dim; j++)
2020 localNullspace_coarse(dim * i + j, j) = 1.0;
2021 });
2022 }
2023 }
2024}
2025
2026template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2028 Teuchos::RCP<Operator> &thyraPrecOp,
2029 const Teuchos::RCP<Matrix> &A,
2030 const Teuchos::RCP<MultiVector> &Nullspace,
2031 const Teuchos::RCP<RealValuedMultiVector> &Coords,
2032 const Teuchos::RCP<MultiVector> &Material,
2033 Teuchos::ParameterList &params,
2034 std::string &label,
2035 const bool reuse,
2036 const bool isSingular) {
2037 int oldRank = SetProcRankVerbose(A->getDomainMap()->getComm()->getRank());
2038 if (IsPrint(Statistics2)) {
2039 RCP<ParameterList> pl = rcp(new ParameterList());
2040 pl->set("printLoadBalancingInfo", true);
2041 pl->set("printCommInfo", true);
2043 }
2044#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2045 if (params.isType<std::string>("Preconditioner Type")) {
2046 TEUCHOS_ASSERT(!reuse);
2047 // build a Stratimikos preconditioner
2048 if (params.get<std::string>("Preconditioner Type") == "MueLu") {
2049 ParameterList &userParamList = params.sublist("Preconditioner Types").sublist("MueLu").sublist("user data");
2050 if (!Nullspace.is_null())
2051 userParamList.set<RCP<MultiVector>>("Nullspace", Nullspace);
2052 if (!Material.is_null())
2053 userParamList.set<RCP<MultiVector>>("Material", Material);
2054 userParamList.set<RCP<RealValuedMultiVector>>("Coordinates", Coords);
2055 }
2056 thyraPrecOp = rcp(new XpetraThyraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(coarseA11_, rcp(&params, false)));
2057 } else
2058#endif
2059 {
2060 // build a MueLu hierarchy
2061
2062 if (!reuse) {
2063 ParameterList &userParamList = params.sublist("user data");
2064 if (!Coords.is_null())
2065 userParamList.set<RCP<RealValuedMultiVector>>("Coordinates", Coords);
2066 if (!Nullspace.is_null())
2067 userParamList.set<RCP<MultiVector>>("Nullspace", Nullspace);
2068 if (!Material.is_null())
2069 userParamList.set<RCP<MultiVector>>("Material", Material);
2070
2071 if (isSingular) {
2072 std::string coarseType = "";
2073 if (params.isParameter("coarse: type")) {
2074 coarseType = params.get<std::string>("coarse: type");
2075 // Transform string to "Abcde" notation
2076 std::transform(coarseType.begin(), coarseType.end(), coarseType.begin(), ::tolower);
2077 std::transform(coarseType.begin(), ++coarseType.begin(), coarseType.begin(), ::toupper);
2078 }
2079 if ((coarseType == "" ||
2080 coarseType == "Klu" ||
2081 coarseType == "Klu2" ||
2082 coarseType == "Superlu" ||
2083 coarseType == "Superlu_dist" ||
2084 coarseType == "Superludist" ||
2085 coarseType == "Basker" ||
2086 coarseType == "Cusolver" ||
2087 coarseType == "Tacho") &&
2088 (!params.isSublist("coarse: params") ||
2089 !params.sublist("coarse: params").isParameter("fix nullspace")))
2090 params.sublist("coarse: params").set("fix nullspace", true);
2091 }
2092
2093 hierarchy = MueLu::CreateXpetraPreconditioner(A, params);
2094 } else {
2095 RCP<MueLu::Level> level0 = hierarchy->GetLevel(0);
2096 level0->Set("A", A);
2097 hierarchy->SetupRe();
2098 }
2099 }
2100 SetProcRankVerbose(oldRank);
2101}
2102
2103template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2104void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::resetMatrix(RCP<Matrix> SM_Matrix_new, bool ComputePrec) {
2105 bool reuse = !SM_Matrix_.is_null();
2106 SM_Matrix_ = SM_Matrix_new;
2107 dump(SM_Matrix_, "SM.m");
2108 if (ComputePrec)
2109 compute(reuse);
2110}
2111
2112template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2114 // residual(SM_Matrix_, X, RHS, residual_)
2115 //
2116 // P11res_ = P11_^T*residual_ or P11res_ = R11_*residual_
2117 //
2118 // Dres_ = Dk_1_^T*residual or Dres_ = Dk_1_T_*residual
2119 //
2120 // if ImporterCoarse11_ is not null
2121 // ImporterCoarse11: P11res_ -> P11resTmp_
2122 // if Importer22_ is not null
2123 // Importer22: Dres_ -> DresTmp_
2124 //
2125 // if coarseA11 is not null
2126 //
2127 // Hierarchy11(P11resSubComm, P11xSubComm) P11resSubComm aliases P11res or P11resTmp
2128 // P11xSubComm aliases P11x
2129 //
2130 // if A22 is not null
2131 //
2132 // Hierarchy22(DresSubComm, DxSubComm) DresSubComm aliases Dres or DresTmp
2133 // DxSubComm aliases Dx
2134 //
2135 // if ImporterCoarse11_ is not null
2136 // ImporterCoarse11: P11xTmp_ -> P11x
2137 // if Importer22_ is not null
2138 // Importer22: DxTmp_ -> Dx_
2139 //
2140 // if fuse
2141 // X += P11*P11x
2142 // X += P11*Dx
2143 // else
2144 // residual = P11*P11x
2145 // residual += Dk_1*Dx
2146 // X += residual
2147
2148 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2149
2150 { // compute residual
2151
2152 RCP<Teuchos::TimeMonitor> tmRes = getTimer("residual calculation");
2154 }
2155
2156 { // restrict residual to sub-hierarchies
2157
2158 if (implicitTranspose_) {
2159 {
2160 RCP<Teuchos::TimeMonitor> tmRes = getTimer("restriction coarse (1,1) (implicit)");
2161 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2162 }
2163 if (!onlyBoundary22_) {
2164 RCP<Teuchos::TimeMonitor> tmD = getTimer("restriction (2,2) (implicit)");
2165 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2166 }
2167 } else {
2169 // Column maps of D_T and R11 match, and we're running Tpetra
2170 {
2171 RCP<Teuchos::TimeMonitor> tmD = getTimer("restrictions import");
2172 DTR11Tmp_->doImport(*residual_, *toCrsMatrix(R11_)->getCrsGraph()->getImporter(), Xpetra::INSERT);
2173 }
2174 if (!onlyBoundary22_) {
2175 RCP<Teuchos::TimeMonitor> tmD = getTimer("restriction (2,2) (explicit)");
2176 toTpetra(Dk_1_T_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*Dres_), Teuchos::NO_TRANS);
2177 }
2178 {
2179 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("restriction coarse (1,1) (explicit)");
2180 toTpetra(R11_)->localApply(toTpetra(*DTR11Tmp_), toTpetra(*P11res_), Teuchos::NO_TRANS);
2181 }
2182 } else {
2183 {
2184 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("restriction coarse (1,1) (explicit)");
2185 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2186 }
2187 if (!onlyBoundary22_) {
2188 RCP<Teuchos::TimeMonitor> tmD = getTimer("restriction (2,2) (explicit)");
2189 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2190 }
2191 }
2192 }
2193 }
2194
2195 {
2196 RCP<Teuchos::TimeMonitor> tmSubSolves = getTimer("subsolves");
2197
2198 // block diagonal preconditioner on 2x2 (V-cycle for diagonal blocks)
2199
2200 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2201 RCP<Teuchos::TimeMonitor> tmH = getTimer("import coarse (1,1)");
2202 P11resTmp_->beginImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2203 }
2204 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_) {
2205 RCP<Teuchos::TimeMonitor> tm22 = getTimer("import (2,2)");
2206 DresTmp_->beginImport(*Dres_, *Importer22_, Xpetra::INSERT);
2207 }
2208
2209 // iterate on coarse (1, 1) block
2210 if (!coarseA11_.is_null()) {
2211 if (!ImporterCoarse11_.is_null() && !implicitTranspose_)
2212 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2213
2214 RCP<Teuchos::TimeMonitor> tmH = getTimer("solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2215
2216#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2217 if (!thyraPrecOpH_.is_null()) {
2218 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2219 thyraPrecOpH_->apply(*P11resSubComm_, *P11xSubComm_, Teuchos::NO_TRANS, one, zero);
2220 } else
2221#endif
2223 }
2224
2225 // iterate on (2, 2) block
2226 if (!A22_.is_null()) {
2227 if (!onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2228 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2229
2230 RCP<Teuchos::TimeMonitor> tm22 = getTimer("solve (2,2)", A22_->getRowMap()->getComm());
2231#if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
2232 if (!thyraPrecOp22_.is_null()) {
2233 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2234 thyraPrecOp22_->apply(*DresSubComm_, *DxSubComm_, Teuchos::NO_TRANS, one, zero);
2235 } else
2236#endif
2237 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_, true);
2238 }
2239
2240 if (coarseA11_.is_null() && !ImporterCoarse11_.is_null() && !implicitTranspose_)
2241 P11resTmp_->endImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2242 if (A22_.is_null() && !onlyBoundary22_ && !Importer22_.is_null() && !implicitTranspose_)
2243 DresTmp_->endImport(*Dres_, *Importer22_, Xpetra::INSERT);
2244 }
2245
2246 {
2247 RCP<Teuchos::TimeMonitor> tmProlongations = getTimer("prolongations");
2248
2249 if (asyncTransfers_) {
2250 using Tpetra_Multivector = Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
2251 using Tpetra_Import = Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>;
2252
2253 auto tpP11 = toTpetra(P11_);
2254 auto tpDk_1 = toTpetra(Dk_1_);
2255
2256 RCP<Tpetra_Multivector> tpP11x = toTpetra(P11x_);
2257 RCP<Tpetra_Multivector> tpP11x_colmap;
2258 RCP<Tpetra_Multivector> tpX = toTpetra(Teuchos::rcpFromRef(X));
2259 RCP<Tpetra_Multivector> tpResidual = toTpetra(residual_);
2260 RCP<Tpetra_Multivector> tpDx = toTpetra(Dx_);
2261 RCP<Tpetra_Multivector> tpDx_colmap;
2262
2263 unsigned completedImports = 0;
2264 std::vector<bool> completedImport(2, false);
2265 auto tpP11importer = tpP11->getCrsGraph()->getImporter();
2266 if (!tpP11importer.is_null()) {
2267 tpP11x_colmap = toTpetra(P11x_colmap_);
2268 tpP11x_colmap->beginImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2269 }
2270
2271 RCP<const Tpetra_Import> tpDk_1importer;
2272 if (!onlyBoundary22_) {
2273 tpDk_1importer = tpDk_1->getCrsGraph()->getImporter();
2274 if (!tpDk_1importer.is_null()) {
2275 tpDx_colmap = toTpetra(Dx_colmap_);
2276 tpDx_colmap->beginImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2277 }
2278 } else {
2279 completedImport[1] = true;
2280 completedImports++;
2281 }
2282
2284 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
2285 tpResidual->putScalar(zero);
2286 }
2287
2288 while (completedImports < completedImport.size()) {
2289 for (unsigned i = 0; i < completedImport.size(); i++) {
2290 if (completedImport[i]) continue;
2291
2292 if (i == 0) {
2293 if (!tpP11importer.is_null()) {
2294 if (tpP11x_colmap->transferArrived()) {
2295 tpP11x_colmap->endImport(*tpP11x, *tpP11importer, Tpetra::INSERT);
2296 completedImport[i] = true;
2297 completedImports++;
2298
2300 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("prolongation coarse (1,1) (fused, local)");
2301 tpP11->localApply(*tpP11x_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2302 } else {
2303 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("prolongation coarse (1,1) (unfused, local)");
2304 tpP11->localApply(*tpP11x_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2305 }
2306 }
2307 } else {
2308 completedImport[i] = true;
2309 completedImports++;
2310
2312 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("prolongation coarse (1,1) (fused, local)");
2313 tpP11->localApply(*tpP11x, *tpX, Teuchos::NO_TRANS, one, one);
2314 } else {
2315 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("prolongation coarse (1,1) (unfused, local)");
2316 tpP11->localApply(*tpP11x, *tpResidual, Teuchos::NO_TRANS, one, one);
2317 }
2318 }
2319 } else {
2320 if (!tpDk_1importer.is_null()) {
2321 if (tpDx_colmap->transferArrived()) {
2322 tpDx_colmap->endImport(*tpDx, *tpDk_1importer, Tpetra::INSERT);
2323 completedImport[i] = true;
2324 completedImports++;
2325
2327 RCP<Teuchos::TimeMonitor> tmD = getTimer("prolongation (2,2) (fused, local)");
2328 tpDk_1->localApply(*tpDx_colmap, *tpX, Teuchos::NO_TRANS, one, one);
2329 } else {
2330 RCP<Teuchos::TimeMonitor> tmD = getTimer("prolongation (2,2) (unfused, local)");
2331 tpDk_1->localApply(*tpDx_colmap, *tpResidual, Teuchos::NO_TRANS, one, one);
2332 }
2333 }
2334 } else {
2335 completedImport[i] = true;
2336 completedImports++;
2337
2339 RCP<Teuchos::TimeMonitor> tmD = getTimer("prolongation (2,2) (fused, local)");
2340 tpDk_1->localApply(*tpDx, *tpX, Teuchos::NO_TRANS, one, one);
2341 } else {
2342 RCP<Teuchos::TimeMonitor> tmD = getTimer("prolongation (2,2) (unfused, local)");
2343 tpDk_1->localApply(*tpDx, *tpResidual, Teuchos::NO_TRANS, one, one);
2344 }
2345 }
2346 }
2347 }
2348 }
2349
2350 if (!fuseProlongationAndUpdate_) { // update current solution
2351 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer("update");
2352 X.update(one, *residual_, one);
2353 }
2354 } else {
2356 { // prolongate (1,1) block
2357 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("prolongation coarse (1,1) (fused)");
2358 P11_->apply(*P11x_, X, Teuchos::NO_TRANS, one, one);
2359 }
2360
2361 if (!onlyBoundary22_) { // prolongate (2,2) block
2362 RCP<Teuchos::TimeMonitor> tmD = getTimer("prolongation (2,2) (fused)");
2363 Dk_1_->apply(*Dx_, X, Teuchos::NO_TRANS, one, one);
2364 }
2365 } else {
2366 { // prolongate (1,1) block
2367 RCP<Teuchos::TimeMonitor> tmP11 = getTimer("prolongation coarse (1,1) (unfused)");
2368 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2369 }
2370
2371 if (!onlyBoundary22_) { // prolongate (2,2) block
2372 RCP<Teuchos::TimeMonitor> tmD = getTimer("prolongation (2,2) (unfused)");
2373 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS, one, one);
2374 }
2375
2376 { // update current solution
2377 RCP<Teuchos::TimeMonitor> tmUpdate = getTimer("update");
2378 X.update(one, *residual_, one);
2379 }
2380 }
2381 }
2382 }
2383}
2384
2385template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2386void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::solveH(const MultiVector &RHS, MultiVector &X) const {
2387 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2388
2389 { // compute residual
2390 RCP<Teuchos::TimeMonitor> tmRes = getTimer("residual calculation");
2393 P11_->apply(*residual_, *P11res_, Teuchos::TRANS);
2394 else
2395 R11_->apply(*residual_, *P11res_, Teuchos::NO_TRANS);
2396 }
2397
2398 { // solve coarse (1,1) block
2399 if (!ImporterCoarse11_.is_null() && !implicitTranspose_) {
2400 RCP<Teuchos::TimeMonitor> tmH = getTimer("import coarse (1,1)");
2401 P11resTmp_->doImport(*P11res_, *ImporterCoarse11_, Xpetra::INSERT);
2402 }
2403 if (!coarseA11_.is_null()) {
2404 RCP<Teuchos::TimeMonitor> tmH = getTimer("solve coarse (1,1)", coarseA11_->getRowMap()->getComm());
2406 }
2407 }
2408
2409 { // update current solution
2410 RCP<Teuchos::TimeMonitor> tmUp = getTimer("update");
2411 P11_->apply(*P11x_, *residual_, Teuchos::NO_TRANS);
2412 X.update(one, *residual_, one);
2413 }
2414}
2415
2416template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2417void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::solve22(const MultiVector &RHS, MultiVector &X) const {
2418 if (onlyBoundary22_)
2419 return;
2420
2421 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
2422
2423 { // compute residual
2424 RCP<Teuchos::TimeMonitor> tmRes = getTimer("residual calculation");
2427 Dk_1_->apply(*residual_, *Dres_, Teuchos::TRANS);
2428 else
2429 Dk_1_T_->apply(*residual_, *Dres_, Teuchos::NO_TRANS);
2430 }
2431
2432 { // solve (2,2) block
2433 if (!Importer22_.is_null() && !implicitTranspose_) {
2434 RCP<Teuchos::TimeMonitor> tm22 = getTimer("import (2,2)");
2435 DresTmp_->doImport(*Dres_, *Importer22_, Xpetra::INSERT);
2436 }
2437 if (!A22_.is_null()) {
2438 RCP<Teuchos::TimeMonitor> tm22 = getTimer("solve (2,2)", A22_->getRowMap()->getComm());
2439 Hierarchy22_->Iterate(*DresSubComm_, *DxSubComm_, numIters22_, true);
2440 }
2441 }
2442
2443 { // update current solution
2444 RCP<Teuchos::TimeMonitor> tmUp = getTimer("update");
2445 Dk_1_->apply(*Dx_, *residual_, Teuchos::NO_TRANS);
2446 X.update(one, *residual_, one);
2447 }
2448}
2449
2450template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2451void RefMaxwell<Scalar, LocalOrdinal, GlobalOrdinal, Node>::apply(const MultiVector &RHS, MultiVector &X,
2452 Teuchos::ETransp /* mode */,
2453 Scalar /* alpha */,
2454 Scalar /* beta */) const {
2455 RCP<Teuchos::TimeMonitor> tm = getTimer("solve");
2456
2457 // make sure that we have enough temporary memory
2458 if (!onlyBoundary11_ && X.getNumVectors() != P11res_->getNumVectors())
2459 allocateMemory(X.getNumVectors());
2460
2461 { // apply pre-smoothing
2462
2463 RCP<Teuchos::TimeMonitor> tmSm = getTimer("smoothing");
2464
2465 PreSmoother11_->Apply(X, RHS, use_as_preconditioner_);
2466 }
2467
2468 // do solve for the 2x2 block system
2469 if (mode_ == "additive")
2470 applyInverseAdditive(RHS, X);
2471 else if (mode_ == "121") {
2472 solveH(RHS, X);
2473 solve22(RHS, X);
2474 solveH(RHS, X);
2475 } else if (mode_ == "212") {
2476 solve22(RHS, X);
2477 solveH(RHS, X);
2478 solve22(RHS, X);
2479 } else if (mode_ == "1")
2480 solveH(RHS, X);
2481 else if (mode_ == "2")
2482 solve22(RHS, X);
2483 else if (mode_ == "7") {
2484 solveH(RHS, X);
2485 { // apply pre-smoothing
2486
2487 RCP<Teuchos::TimeMonitor> tmSm = getTimer("smoothing");
2488
2489 PreSmoother11_->Apply(X, RHS, false);
2490 }
2491 solve22(RHS, X);
2492 { // apply post-smoothing
2493
2494 RCP<Teuchos::TimeMonitor> tmSm = getTimer("smoothing");
2495
2496 PostSmoother11_->Apply(X, RHS, false);
2497 }
2498 solveH(RHS, X);
2499 } else if (mode_ == "none") {
2500 // do nothing
2501 } else
2502 applyInverseAdditive(RHS, X);
2503
2504 { // apply post-smoothing
2505
2506 RCP<Teuchos::TimeMonitor> tmSm = getTimer("smoothing");
2507
2508 PostSmoother11_->Apply(X, RHS, false);
2509 }
2510}
2511
2512template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2516
2517template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2519 RefMaxwell(const Teuchos::RCP<Matrix> &SM_Matrix,
2520 Teuchos::ParameterList &List,
2521 bool ComputePrec) {
2522 int spaceNumber = List.get<int>("refmaxwell: space number", 1);
2523
2524 RCP<Matrix> Dk_1, Dk_2, D0;
2525 RCP<Matrix> M1_beta, M1_alpha;
2526 RCP<Matrix> Mk_one, Mk_1_one;
2527 RCP<Matrix> invMk_1_invBeta, invMk_2_invAlpha;
2528 RCP<MultiVector> Nullspace11, Nullspace22;
2529 RCP<RealValuedMultiVector> NodalCoords;
2530
2531 Dk_1 = pop(List, "Dk_1", Dk_1);
2532 Dk_2 = pop<RCP<Matrix>>(List, "Dk_2", Dk_2);
2533 D0 = pop<RCP<Matrix>>(List, "D0", D0);
2534
2535 M1_beta = pop<RCP<Matrix>>(List, "M1_beta", M1_beta);
2536 M1_alpha = pop<RCP<Matrix>>(List, "M1_alpha", M1_alpha);
2537
2538 Mk_one = pop<RCP<Matrix>>(List, "Mk_one", Mk_one);
2539 Mk_1_one = pop<RCP<Matrix>>(List, "Mk_1_one", Mk_1_one);
2540
2541 invMk_1_invBeta = pop<RCP<Matrix>>(List, "invMk_1_invBeta", invMk_1_invBeta);
2542 invMk_2_invAlpha = pop<RCP<Matrix>>(List, "invMk_2_invAlpha", invMk_2_invAlpha);
2543
2544 Nullspace11 = pop<RCP<MultiVector>>(List, "Nullspace11", Nullspace11);
2545 Nullspace22 = pop<RCP<MultiVector>>(List, "Nullspace22", Nullspace22);
2546 NodalCoords = pop<RCP<RealValuedMultiVector>>(List, "Coordinates", NodalCoords);
2547
2548 // old parameter names
2549 if (List.isType<RCP<Matrix>>("Ms")) {
2550 if (M1_beta.is_null())
2551 M1_beta = pop<RCP<Matrix>>(List, "Ms");
2552 else
2553 TEUCHOS_ASSERT(false);
2554 }
2555 if (List.isType<RCP<Matrix>>("M1")) {
2556 if (Mk_one.is_null())
2557 Mk_one = pop<RCP<Matrix>>(List, "M1");
2558 else
2559 TEUCHOS_ASSERT(false);
2560 }
2561 if (List.isType<RCP<Matrix>>("M0inv")) {
2562 if (invMk_1_invBeta.is_null())
2563 invMk_1_invBeta = pop<RCP<Matrix>>(List, "M0inv");
2564 else
2565 TEUCHOS_ASSERT(false);
2566 }
2567 if (List.isType<RCP<MultiVector>>("Nullspace")) {
2568 if (Nullspace11.is_null())
2569 Nullspace11 = pop<RCP<MultiVector>>(List, "Nullspace");
2570 else
2571 TEUCHOS_ASSERT(false);
2572 }
2573
2574 if (spaceNumber == 1) {
2575 if (Dk_1.is_null())
2576 Dk_1 = D0;
2577 else if (D0.is_null())
2578 D0 = Dk_1;
2579 if (M1_beta.is_null())
2580 M1_beta = Mk_one;
2581 } else if (spaceNumber == 2) {
2582 if (Dk_2.is_null())
2583 Dk_2 = D0;
2584 else if (D0.is_null())
2585 D0 = Dk_2;
2586 }
2587
2588 initialize(spaceNumber,
2589 Dk_1, Dk_2, D0,
2590 M1_beta, M1_alpha,
2591 Mk_one, Mk_1_one,
2592 invMk_1_invBeta, invMk_2_invAlpha,
2593 Nullspace11, Nullspace22,
2594 NodalCoords,
2595 Teuchos::null, Teuchos::null,
2596 List);
2597
2598 if (SM_Matrix != Teuchos::null)
2599 resetMatrix(SM_Matrix, ComputePrec);
2600}
2601
2602template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2604 initialize(const Teuchos::RCP<Matrix> &D0_Matrix,
2605 const Teuchos::RCP<Matrix> &Ms_Matrix,
2606 const Teuchos::RCP<Matrix> &M0inv_Matrix,
2607 const Teuchos::RCP<Matrix> &M1_Matrix,
2608 const Teuchos::RCP<MultiVector> &Nullspace11,
2609 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2610 const Teuchos::RCP<MultiVector> &Material,
2611 Teuchos::ParameterList &List) {
2612 initialize(1,
2613 D0_Matrix, Teuchos::null, D0_Matrix,
2614 Ms_Matrix, Teuchos::null,
2615 M1_Matrix, Teuchos::null,
2616 M0inv_Matrix, Teuchos::null,
2617 Nullspace11, Teuchos::null,
2618 NodalCoords,
2619 Teuchos::null, Material,
2620 List);
2621}
2622
2623template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2625 initialize(const int k,
2626 const Teuchos::RCP<Matrix> &Dk_1,
2627 const Teuchos::RCP<Matrix> &Dk_2,
2628 const Teuchos::RCP<Matrix> &D0,
2629 const Teuchos::RCP<Matrix> &M1_beta,
2630 const Teuchos::RCP<Matrix> &M1_alpha,
2631 const Teuchos::RCP<Matrix> &Mk_one,
2632 const Teuchos::RCP<Matrix> &Mk_1_one,
2633 const Teuchos::RCP<Matrix> &invMk_1_invBeta,
2634 const Teuchos::RCP<Matrix> &invMk_2_invAlpha,
2635 const Teuchos::RCP<MultiVector> &Nullspace11,
2636 const Teuchos::RCP<MultiVector> &Nullspace22,
2637 const Teuchos::RCP<RealValuedMultiVector> &NodalCoords,
2638 const Teuchos::RCP<MultiVector> &Material_beta,
2639 const Teuchos::RCP<MultiVector> &Material_alpha,
2640 Teuchos::ParameterList &List) {
2641 spaceNumber_ = k;
2642 if (spaceNumber_ == 1)
2643 solverName_ = "RefMaxwell";
2644 else if (spaceNumber_ == 2)
2645 solverName_ = "RefDarcy";
2646 else
2647 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
2648 "spaceNumber needs to be 1 (HCurl) or 2 (HDiv)");
2649 HierarchyCoarse11_ = Teuchos::null;
2650 Hierarchy22_ = Teuchos::null;
2651 PreSmoother11_ = Teuchos::null;
2652 PostSmoother11_ = Teuchos::null;
2653 disable_addon_ = false;
2654 disable_addon_22_ = true;
2655 mode_ = "additive";
2656
2657 // set parameters
2658 setParameters(List);
2659
2660 // some pre-conditions
2661 TEUCHOS_ASSERT((k == 1) || (k == 2));
2662 // Need Dk_1
2663 TEUCHOS_ASSERT(Dk_1 != Teuchos::null);
2664 // Need D0 for aggregation
2665 TEUCHOS_ASSERT(D0 != Teuchos::null);
2666
2667 // Need M1_beta for aggregation
2668 TEUCHOS_ASSERT(M1_beta != Teuchos::null);
2669 // Need M1_alpha for aggregation if k>=1
2670 if (k >= 2)
2671 TEUCHOS_ASSERT(M1_alpha != Teuchos::null);
2672
2673 if (!disable_addon_) {
2674 // Need Mk_one and invMk_1_invBeta for addon11
2675 TEUCHOS_ASSERT(Mk_one != Teuchos::null);
2676 TEUCHOS_ASSERT(invMk_1_invBeta != Teuchos::null);
2677 }
2678
2679 if ((k >= 2) && !disable_addon_22_) {
2680 // Need Dk_2, Mk_1_one and invMk_2_invAlpha for addon22
2681 TEUCHOS_ASSERT(Dk_2 != Teuchos::null);
2682 TEUCHOS_ASSERT(Mk_1_one != Teuchos::null);
2683 TEUCHOS_ASSERT(invMk_2_invAlpha != Teuchos::null);
2684 }
2685
2686#ifdef HAVE_MUELU_DEBUG
2687
2688 TEUCHOS_ASSERT(D0->getRangeMap()->isSameAs(*D0->getRowMap()));
2689
2690 // M1_beta is square
2691 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRangeMap()));
2692 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*M1_beta->getRowMap()));
2693
2694 // M1_beta is consistent with D0
2695 TEUCHOS_ASSERT(M1_beta->getDomainMap()->isSameAs(*D0->getRangeMap()));
2696
2697 if (k >= 2) {
2698 // M1_alpha is square
2699 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRangeMap()));
2700 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*M1_alpha->getRowMap()));
2701
2702 // M1_alpha is consistent with D0
2703 TEUCHOS_ASSERT(M1_alpha->getDomainMap()->isSameAs(*D0->getRangeMap()))
2704 }
2705
2706 if (!disable_addon_) {
2707 // Mk_one is square
2708 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRangeMap()));
2709 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Mk_one->getRowMap()));
2710
2711 // Mk_one is consistent with Dk_1
2712 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2713
2714 // invMk_1_invBeta is square
2715 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRangeMap()));
2716 TEUCHOS_ASSERT(invMk_1_invBeta->getDomainMap()->isSameAs(*invMk_1_invBeta->getRowMap()));
2717
2718 // invMk_1_invBeta is consistent with Dk_1
2719 TEUCHOS_ASSERT(Mk_one->getDomainMap()->isSameAs(*Dk_1->getRangeMap()));
2720 }
2721
2722 if ((k >= 2) && !disable_addon_22_) {
2723 // Mk_1_one is square
2724 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRangeMap()));
2725 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Mk_1_one->getRowMap()));
2726
2727 // Mk_1_one is consistent with Dk_1
2728 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_1->getDomainMap()));
2729
2730 // Mk_1_one is consistent with Dk_2
2731 TEUCHOS_ASSERT(Mk_1_one->getDomainMap()->isSameAs(*Dk_2->getRangeMap()));
2732
2733 // invMk_2_invAlpha is square
2734 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRangeMap()));
2735 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*invMk_2_invAlpha->getRowMap()));
2736
2737 // invMk_2_invAlpha is consistent with Dk_2
2738 TEUCHOS_ASSERT(invMk_2_invAlpha->getDomainMap()->isSameAs(*Dk_2->getDomainMap()));
2739 }
2740#endif
2741
2742 D0_ = D0;
2743 if (Dk_1->getRowMap()->lib() == Xpetra::UseTpetra) {
2744 // We will remove boundary conditions from Dk_1, and potentially change maps, so we copy the input.
2745 // Fortunately, Dk_1 is quite sparse.
2746 // We cannot use the Tpetra copy constructor, since it does not copy the graph.
2747
2748 RCP<Matrix> Dk_1copy = MatrixFactory::Build(Dk_1->getRowMap(), Dk_1->getColMap(), 0);
2749 RCP<CrsMatrix> Dk_1copyCrs = toCrsMatrix(Dk_1copy);
2750 ArrayRCP<const size_t> Dk_1rowptr_RCP;
2751 ArrayRCP<const LO> Dk_1colind_RCP;
2752 ArrayRCP<const SC> Dk_1vals_RCP;
2753 toCrsMatrix(Dk_1)->getAllValues(Dk_1rowptr_RCP, Dk_1colind_RCP, Dk_1vals_RCP);
2754
2755 ArrayRCP<size_t> Dk_1copyrowptr_RCP;
2756 ArrayRCP<LO> Dk_1copycolind_RCP;
2757 ArrayRCP<SC> Dk_1copyvals_RCP;
2758 Dk_1copyCrs->allocateAllValues(Dk_1vals_RCP.size(), Dk_1copyrowptr_RCP, Dk_1copycolind_RCP, Dk_1copyvals_RCP);
2759 Dk_1copyrowptr_RCP.deepCopy(Dk_1rowptr_RCP());
2760 Dk_1copycolind_RCP.deepCopy(Dk_1colind_RCP());
2761 Dk_1copyvals_RCP.deepCopy(Dk_1vals_RCP());
2762 Dk_1copyCrs->setAllValues(Dk_1copyrowptr_RCP,
2763 Dk_1copycolind_RCP,
2764 Dk_1copyvals_RCP);
2765 Dk_1copyCrs->expertStaticFillComplete(Dk_1->getDomainMap(), Dk_1->getRangeMap(),
2766 toCrsMatrix(Dk_1)->getCrsGraph()->getImporter(),
2767 toCrsMatrix(Dk_1)->getCrsGraph()->getExporter());
2768 Dk_1_ = Dk_1copy;
2769 } else
2770 Dk_1_ = MatrixFactory::BuildCopy(Dk_1);
2771
2772 if ((!Dk_2.is_null()) && (Dk_2->getRowMap()->lib() == Xpetra::UseTpetra)) {
2773 // We will remove boundary conditions from Dk_2, and potentially change maps, so we copy the input.
2774 // Fortunately, Dk_2 is quite sparse.
2775 // We cannot use the Tpetra copy constructor, since it does not copy the graph.
2776
2777 RCP<Matrix> Dk_2copy = MatrixFactory::Build(Dk_2->getRowMap(), Dk_2->getColMap(), 0);
2778 RCP<CrsMatrix> Dk_2copyCrs = toCrsMatrix(Dk_2copy);
2779 ArrayRCP<const size_t> Dk_2rowptr_RCP;
2780 ArrayRCP<const LO> Dk_2colind_RCP;
2781 ArrayRCP<const SC> Dk_2vals_RCP;
2782 toCrsMatrix(Dk_2)->getAllValues(Dk_2rowptr_RCP, Dk_2colind_RCP, Dk_2vals_RCP);
2783
2784 ArrayRCP<size_t> Dk_2copyrowptr_RCP;
2785 ArrayRCP<LO> Dk_2copycolind_RCP;
2786 ArrayRCP<SC> Dk_2copyvals_RCP;
2787 Dk_2copyCrs->allocateAllValues(Dk_2vals_RCP.size(), Dk_2copyrowptr_RCP, Dk_2copycolind_RCP, Dk_2copyvals_RCP);
2788 Dk_2copyrowptr_RCP.deepCopy(Dk_2rowptr_RCP());
2789 Dk_2copycolind_RCP.deepCopy(Dk_2colind_RCP());
2790 Dk_2copyvals_RCP.deepCopy(Dk_2vals_RCP());
2791 Dk_2copyCrs->setAllValues(Dk_2copyrowptr_RCP,
2792 Dk_2copycolind_RCP,
2793 Dk_2copyvals_RCP);
2794 Dk_2copyCrs->expertStaticFillComplete(Dk_2->getDomainMap(), Dk_2->getRangeMap(),
2795 toCrsMatrix(Dk_2)->getCrsGraph()->getImporter(),
2796 toCrsMatrix(Dk_2)->getCrsGraph()->getExporter());
2797 Dk_2_ = Dk_2copy;
2798 } else if (!Dk_2.is_null())
2799 Dk_2_ = MatrixFactory::BuildCopy(Dk_2);
2800
2801 M1_beta_ = M1_beta;
2802 M1_alpha_ = M1_alpha;
2803
2804 Material_beta_ = Material_beta;
2805 Material_alpha_ = Material_alpha;
2806
2807 Mk_one_ = Mk_one;
2808 Mk_1_one_ = Mk_1_one;
2809
2810 invMk_1_invBeta_ = invMk_1_invBeta;
2811 invMk_2_invAlpha_ = invMk_2_invAlpha;
2812
2813 NodalCoords_ = NodalCoords;
2814 Nullspace11_ = Nullspace11;
2815 Nullspace22_ = Nullspace22;
2816
2817 dump(D0_, "D0.m");
2818 dump(Dk_1_, "Dk_1_clean.m");
2819 dump(Dk_2_, "Dk_2_clean.m");
2820
2821 dump(M1_beta_, "M1_beta.m");
2822 dump(M1_alpha_, "M1_alpha.m");
2823
2824 dump(Mk_one_, "Mk_one.m");
2825 dump(Mk_1_one_, "Mk_1_one.m");
2826
2827 dump(invMk_1_invBeta_, "invMk_1_invBeta.m");
2828 dump(invMk_2_invAlpha_, "invMk_2_invAlpha.m");
2829
2830 dumpCoords(NodalCoords_, "coords.m");
2831}
2832
2833template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2835 describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel /* verbLevel */) const {
2836 std::ostringstream oss;
2837
2838 RCP<const Teuchos::Comm<int>> comm = SM_Matrix_->getDomainMap()->getComm();
2839
2840#ifdef HAVE_MPI
2841 int root;
2842 if (!coarseA11_.is_null())
2843 root = comm->getRank();
2844 else
2845 root = -1;
2846
2847 int actualRoot;
2848 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
2849 root = actualRoot;
2850#endif
2851
2852 oss << "\n--------------------------------------------------------------------------------\n"
2853 << "--- " + solverName_ +
2854 " Summary ---\n"
2855 "--------------------------------------------------------------------------------"
2856 << std::endl;
2857 oss << std::endl;
2858
2859 GlobalOrdinal numRows;
2860 GlobalOrdinal nnz;
2861
2862 SM_Matrix_->getRowMap()->getComm()->barrier();
2863
2864 numRows = SM_Matrix_->getGlobalNumRows();
2865 nnz = SM_Matrix_->getGlobalNumEntries();
2866
2867 Xpetra::global_size_t tt = numRows;
2868 int rowspacer = 3;
2869 while (tt != 0) {
2870 tt /= 10;
2871 rowspacer++;
2872 }
2873 tt = nnz;
2874 int nnzspacer = 2;
2875 while (tt != 0) {
2876 tt /= 10;
2877 nnzspacer++;
2878 }
2879
2880 oss << "block " << std::setw(rowspacer) << " rows " << std::setw(nnzspacer) << " nnz " << std::setw(9) << " nnz/row" << std::endl;
2881 oss << "(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2882
2883 if (!A22_.is_null()) {
2884 numRows = A22_->getGlobalNumRows();
2885 nnz = A22_->getGlobalNumEntries();
2886
2887 oss << "(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
2888 }
2889
2890 oss << std::endl;
2891
2892 {
2894 oss << "Smoother 11 both : " << PreSmoother11_->description() << std::endl;
2895 else {
2896 oss << "Smoother 11 pre : "
2897 << (PreSmoother11_ != null ? PreSmoother11_->description() : "no smoother") << std::endl;
2898 oss << "Smoother 11 post : "
2899 << (PostSmoother11_ != null ? PostSmoother11_->description() : "no smoother") << std::endl;
2900 }
2901 }
2902 oss << std::endl;
2903
2904 std::string outstr = oss.str();
2905
2906#ifdef HAVE_MPI
2907 RCP<const Teuchos::MpiComm<int>> mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2908 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
2909
2910 int strLength = outstr.size();
2911 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
2912 if (comm->getRank() != root)
2913 outstr.resize(strLength);
2914 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
2915#endif
2916
2917 out << outstr;
2918
2919 if (!HierarchyCoarse11_.is_null())
2920 HierarchyCoarse11_->describe(out, GetVerbLevel());
2921
2922 if (!Hierarchy22_.is_null())
2923 Hierarchy22_->describe(out, GetVerbLevel());
2924
2925 if (IsPrint(Statistics2)) {
2926 // Print the grid of processors
2927 std::ostringstream oss2;
2928
2929 oss2 << "Sub-solver distribution over ranks" << std::endl;
2930 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;
2931
2932 int numProcs = comm->getSize();
2933#ifdef HAVE_MPI
2934 RCP<const Teuchos::MpiComm<int>> tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
2935 TEUCHOS_TEST_FOR_EXCEPTION(tmpic == Teuchos::null, Exceptions::RuntimeError, "Cannot cast base Teuchos::Comm to Teuchos::MpiComm object.");
2936 RCP<const Teuchos::OpaqueWrapper<MPI_Comm>> rawMpiComm = tmpic->getRawMpiComm();
2937#endif
2938
2939 char status = 0;
2940 if (!coarseA11_.is_null())
2941 status += 1;
2942 if (!A22_.is_null())
2943 status += 2;
2944 std::vector<char> states(numProcs, 0);
2945#ifdef HAVE_MPI
2946 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
2947#else
2948 states.push_back(status);
2949#endif
2950
2951 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
2952 for (int proc = 0; proc < numProcs; proc += rowWidth) {
2953 for (int j = 0; j < rowWidth; j++)
2954 if (proc + j < numProcs)
2955 if (states[proc + j] == 0)
2956 oss2 << ".";
2957 else if (states[proc + j] == 1)
2958 oss2 << "1";
2959 else if (states[proc + j] == 2)
2960 oss2 << "2";
2961 else
2962 oss2 << "B";
2963 else
2964 oss2 << " ";
2965
2966 oss2 << " " << proc << ":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
2967 }
2968 oss2 << std::endl;
2969 GetOStream(Statistics2) << oss2.str();
2970 }
2971}
2972
2973} // namespace MueLu
2974
2975#define MUELU_REFMAXWELL_SHORT
2976#endif // ifdef MUELU_REFMAXWELL_DEF_HPP
Various adapters that will create a MueLu preconditioner that is an Xpetra::Matrix.
#define MueLu_maxAll(rcpComm, in, out)
#define MueLu_sumAll(rcpComm, in, out)
#define MueLu_minAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Factory to export aggregation info or visualize aggregates using VTK.
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for creating a graph based on a given matrix.
Factory for creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Class for transferring coordinates from a finer level to a coarser one.
Exception throws to report errors in the internal logical of the program.
This class specifies the default factory that should generate some data on a Level if the data does n...
Class that holds all level-specific information.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need's value has been saved.
void setlib(Xpetra::UnderlyingLib lib2)
void SetLevelID(int levelID)
Set level number.
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void Request(const FactoryBase &factory)
Increment the storage counter for all the inputs of a factory.
void SetPreviousLevel(const RCP< Level > &previousLevel)
void SetFactoryManager(const RCP< const FactoryManagerBase > &factoryManager)
Set default factories (used internally by Hierarchy::SetLevel()).
static std::string translate(Teuchos::ParameterList &paramList, const std::string &defaultVals="")
: Translate ML parameters to MueLu parameter XML string
static const T & getDefault(const std::string &name)
Returns default value on the "master" list for a parameter with the specified name and type.
static void detectBoundaryConditionsSM(RCP< Matrix > &SM_Matrix, RCP< Matrix > &D0_Matrix, magnitudeType rowSumTol, bool useKokkos_, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCrowsKokkos, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCcolsKokkos, Kokkos::View< bool *, typename Node::device_type::memory_space > &BCdomainKokkos, int &BCedges, int &BCnodes, Teuchos::ArrayRCP< bool > &BCrows, Teuchos::ArrayRCP< bool > &BCcols, Teuchos::ArrayRCP< bool > &BCdomain, bool &allEdgesBoundary, bool &allNodesBoundary)
Detect Dirichlet boundary conditions.
static void thresholdedAbs(const RCP< Matrix > &A, const magnitudeType thresholded)
static RCP< Matrix > removeExplicitZeros(const RCP< Matrix > &A, const magnitudeType tolerance, const bool keepDiagonal=true, const size_t expectedNNZperRow=0)
Remove explicit zeros.
static void setMatvecParams(Matrix &A, RCP< ParameterList > matvecParams)
Sets matvec params on a matrix.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > PtAPWrapper(const RCP< Matrix > &A, const RCP< Matrix > &P, Teuchos::ParameterList &params, 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.
Teuchos::RCP< MultiVector > P11resTmp_
Teuchos::RCP< Matrix > Mk_1_one_
Teuchos::RCP< RealValuedMultiVector > NodalCoords_
Coordinates.
Teuchos::RCP< MultiVector > Material_beta_
material for first space
Teuchos::RCP< MultiVector > P11x_
Teuchos::RCP< MultiVector > Nullspace22_
Teuchos::RCP< MultiVector > residual_
Teuchos::RCP< Matrix > M1_beta_
mass matrices on first space with weights beta and alpha respectively
Teuchos::RCP< MultiVector > Dx_colmap_
Teuchos::RCP< Teuchos::ParameterList > coarseA11_AP_reuse_data_
Kokkos::View< bool *, typename Node::device_type::memory_space > BCrows11_
Vectors for BCs.
void setupSubSolve(Teuchos::RCP< Hierarchy > &hierarchy, Teuchos::RCP< Operator > &thyraPrecOp, const Teuchos::RCP< Matrix > &A, const Teuchos::RCP< MultiVector > &Nullspace, const Teuchos::RCP< RealValuedMultiVector > &Coords, const Teuchos::RCP< MultiVector > &Material, Teuchos::ParameterList &params, std::string &label, const bool reuse, const bool isSingular=false)
Setup a subsolve.
Teuchos::RCP< Teuchos::ParameterList > A22_AP_reuse_data_
Teuchos::RCP< Matrix > coarseA22_
Teuchos::RCP< MultiVector > P11res_
Temporary memory.
Teuchos::RCP< Matrix > coarseA11_
coarse 11, 22 and coarse 22 blocks
Teuchos::RCP< Matrix > Mk_one_
mass matrices with unit weight on k-th and (k-1)-th spaces
Teuchos::RCP< Matrix > Dk_1_T_
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
Teuchos::RCP< const Map > DorigDomainMap_
Teuchos::RCP< Matrix > SM_Matrix_
The system that is getting preconditioned.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::VERB_HIGH) const
Teuchos::RCP< Matrix > invMk_1_invBeta_
inverse of mass matrices on (k-1)-th and (k-2)-th space with weights 1/beta and 1/alpha respectively
Kokkos::View< bool *, typename Node::device_type::memory_space > BCcols22_
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.
void apply(const MultiVector &X, MultiVector &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, Scalar alpha=Teuchos::ScalarTraits< Scalar >::one(), Scalar beta=Teuchos::ScalarTraits< Scalar >::zero()) const
Teuchos::RCP< SmootherPrototype > PostSmootherData11_
Teuchos::RCP< Teuchos::ParameterList > A22_RAP_reuse_data_
RCP< MultiVector > buildNullspace(const int spaceNumber, const Kokkos::View< bool *, typename Node::device_type > &bcs, const bool applyBCs)
Builds a nullspace.
bool hasTransposeApply() const
Indicates whether this operator supports applying the adjoint operator.
void determineSubHierarchyCommSizes(bool &doRebalancing, int &rebalanceStriding, int &numProcsCoarseA11, int &numProcsA22)
Determine how large the sub-communicators for the two hierarchies should be.
Teuchos::RCP< RealValuedMultiVector > Coords22_
bool disable_addon_
Some options.
Kokkos::View< bool *, typename Node::device_type::memory_space > BCdomain22_
void solveH(const MultiVector &RHS, MultiVector &X) const
apply solve to 1-1 block only
Teuchos::ParameterList precList22_
Teuchos::RCP< Matrix > A22_
typename Teuchos::ScalarTraits< Scalar >::coordinateType coordinateType
Teuchos::RCP< SmootherBase > PostSmoother11_
Teuchos::RCP< MultiVector > NullspaceCoarse11_
Nullspace for coarse (1,1) problem.
Teuchos::RCP< Matrix > Dk_2_
D_{k-2} matrix.
void setFineLevelSmoother11()
Set the fine level smoother.
Teuchos::RCP< Matrix > R11_
std::string solverName_
The name of the solver.
void dumpCoords(const RCP< RealValuedMultiVector > &X, std::string name) const
dump out real-valued multivector
Teuchos::RCP< Matrix > D0_
D_0 matrix.
Teuchos::RCP< const Import > Importer22_
const Teuchos::RCP< const Map > getDomainMap() const
Returns the Xpetra::Map object associated with the domain of this operator.
Teuchos::RCP< MultiVector > Dx_
Teuchos::RCP< Matrix > M1_alpha_
Teuchos::RCP< Matrix > P11_
special prolongator for 11 block and its transpose
Teuchos::RCP< MultiVector > DresTmp_
Teuchos::RCP< MultiVector > P11resSubComm_
Teuchos::RCP< MultiVector > P11xSubComm_
Teuchos::RCP< Hierarchy > Hierarchy22_
Teuchos::RCP< Teuchos::ParameterList > getValidParamterList()
Teuchos::RCP< Matrix > P22_
special prolongator for 22 block and its transpose
Teuchos::RCP< Hierarchy > HierarchyCoarse11_
Two hierarchies: one for the coarse (1,1)-block, another for the (2,2)-block.
Teuchos::RCP< MultiVector > CoarseNullspace22_
Nullspace for coarse (2,2) problem.
Teuchos::RCP< MultiVector > DTR11Tmp_
Teuchos::RCP< SmootherPrototype > PreSmootherData11_
int spaceNumber_
The number of the space in the deRham complex.
Teuchos::RCP< MultiVector > Dres_
void applyInverseAdditive(const MultiVector &RHS, MultiVector &X) const
apply additive algorithm for 2x2 solve
Teuchos::RCP< RealValuedMultiVector > CoordsCoarse11_
Teuchos::RCP< const Import > DorigImporter_
void buildProlongator(const int spaceNumber, const Teuchos::RCP< Matrix > &A_nodal_Matrix, const RCP< MultiVector > &EdgeNullspace, Teuchos::RCP< Matrix > &edgeProlongator, Teuchos::RCP< MultiVector > &coarseEdgeNullspace, Teuchos::RCP< RealValuedMultiVector > &coarseNodalCoords) const
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.
Teuchos::ParameterList precList11_
Teuchos::RCP< Matrix > Dk_1_
D_{k-1} matrix and its transpose.
Teuchos::RCP< Teuchos::ParameterList > coarseA11_RAP_reuse_data_
void initialize(const Teuchos::RCP< Matrix > &D0_Matrix, const Teuchos::RCP< Matrix > &Ms_Matrix, const Teuchos::RCP< Matrix > &M0inv_Matrix, const Teuchos::RCP< Matrix > &M1_Matrix, const Teuchos::RCP< MultiVector > &Nullspace11, const Teuchos::RCP< RealValuedMultiVector > &NodalCoords, const Teuchos::RCP< MultiVector > &Material, Teuchos::ParameterList &List)
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 > Addon11_
the addon for the 11 block
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.
Teuchos::ParameterList parameterList_
Parameter lists.
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
Teuchos::RCP< MultiVector > Nullspace11_
Nullspace for (1.1) block.
size_t dim_
The spatial dimension.
Teuchos::RCP< MultiVector > P11x_colmap_
Teuchos::RCP< MultiVector > DresSubComm_
void resetMatrix(Teuchos::RCP< Matrix > SM_Matrix_new, bool ComputePrec=true)
Reset system matrix.
void setParameters(Teuchos::ParameterList &list)
Set parameters.
typename Teuchos::ScalarTraits< Scalar >::magnitudeType magnitudeType
Teuchos::RCP< SmootherBase > PreSmoother11_
Teuchos::RCP< MultiVector > Material_alpha_
Teuchos::RCP< const Import > ImporterCoarse11_
Importer to coarse (1,1) hierarchy.
Teuchos::RCP< Matrix > R22_
RCP< Matrix > buildAddon(const int spaceNumber)
void solve22(const MultiVector &RHS, MultiVector &X) const
apply solve to 2-2 block only
Teuchos::RCP< Matrix > invMk_2_invAlpha_
Teuchos::RCP< MultiVector > DxSubComm_
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.
static void ZeroDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &A, const std::vector< DefaultLocalOrdinal > &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, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &A, const Magnitude rowSumTol, Teuchos::ArrayRCP< bool > &dirichletRows)
static void ApplyOAZToMatrixRows(Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &A, const std::vector< DefaultLocalOrdinal > &dirichletRows)
static void DetectDirichletColsAndDomains(const Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &A, const Teuchos::ArrayRCP< bool > &dirichletRows, Teuchos::ArrayRCP< bool > dirichletCols, Teuchos::ArrayRCP< bool > dirichletDomain)
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &Op, const MultiVector &X, const MultiVector &RHS)
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 > &params=Teuchos::null)
static RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > RealValuedToScalarMultiVector(RCP< Xpetra::MultiVector< typename Teuchos::ScalarTraits< Scalar >::coordinateType, LocalOrdinal, GlobalOrdinal, Node > > X)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
VerbLevel GetVerbLevel() const
Get the verbosity level.
int SetProcRankVerbose(int procRank) const
Set proc rank used for printing.
static VerbLevel GetDefaultVerbLevel()
Get the default (global) verbosity level.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
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,...