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