MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_Maxwell1_def.hpp
Go to the documentation of this file.
1 //
2 // ***********************************************************************
3 //
4 // MueLu: A package for multigrid based preconditioning
5 // Copyright 2012 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact
38 // Jonathan Hu (jhu@sandia.gov)
39 // Andrey Prokopenko (aprokop@sandia.gov)
40 // Ray Tuminaro (rstumin@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 #ifndef MUELU_MAXWELL1_DEF_HPP
46 #define MUELU_MAXWELL1_DEF_HPP
47 
48 #include <sstream>
49 #include "MueLu_SmootherBase.hpp"
50 
51 #include "MueLu_ConfigDefs.hpp"
52 
53 #include "Xpetra_Map.hpp"
55 #include "Xpetra_MatrixUtils.hpp"
56 
57 #include "MueLu_Maxwell1_decl.hpp"
58 #include "MueLu_Maxwell_Utils.hpp"
59 
60 #include "MueLu_ReitzingerPFactory.hpp"
61 #include "MueLu_Utilities.hpp"
62 #include "MueLu_Level.hpp"
63 #include "MueLu_Hierarchy.hpp"
64 #include "MueLu_RAPFactory.hpp"
65 #include "MueLu_Monitor.hpp"
66 #include "MueLu_PerfUtils.hpp"
67 #include "MueLu_ParameterListInterpreter.hpp"
69 #include <MueLu_HierarchyUtils.hpp>
70 #include "MueLu_VerbosityLevel.hpp"
73 #include <MueLu_RefMaxwellSmoother.hpp>
74 
75 #ifdef HAVE_MUELU_CUDA
76 #include "cuda_profiler_api.h"
77 #endif
78 
79 namespace MueLu {
80 
81 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
83  return SM_Matrix_->getDomainMap();
84 }
85 
86 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
88  return SM_Matrix_->getRangeMap();
89 }
90 
91 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
93  if (list.isType<std::string>("parameterlist: syntax") && list.get<std::string>("parameterlist: syntax") == "ml") {
94  list.remove("parameterlist: syntax");
95  Teuchos::ParameterList newList;
96 
97  // interpret ML list
98  newList.sublist("maxwell1: 22list") = *Teuchos::getParametersFromXmlString(MueLu::ML2MueLuParameterTranslator::translate(list, "Maxwell"));
99 
100  // Hardwiring options to ensure ML compatibility
101  newList.sublist("maxwell1: 22list").set("use kokkos refactor", false);
102 
103  newList.sublist("maxwell1: 11list").set("use kokkos refactor", false);
104  newList.sublist("maxwell1: 11list").set("tentative: constant column sums", false);
105  newList.sublist("maxwell1: 11list").set("tentative: calculate qr", false);
106 
107  newList.sublist("maxwell1: 11list").set("aggregation: use ml scaling of drop tol", true);
108  newList.sublist("maxwell1: 22list").set("aggregation: use ml scaling of drop tol", true);
109 
110  newList.sublist("maxwell1: 22list").set("aggregation: min agg size", 3);
111  newList.sublist("maxwell1: 22list").set("aggregation: match ML phase1", true);
112  newList.sublist("maxwell1: 22list").set("aggregation: match ML phase2a", true);
113  newList.sublist("maxwell1: 22list").set("aggregation: match ML phase2b", true);
114 
115  if (list.isParameter("aggregation: damping factor") && list.get<double>("aggregation: damping factor") == 0.0)
116  newList.sublist("maxwell1: 11list").set("multigrid algorithm", "unsmoothed reitzinger");
117  else
118  newList.sublist("maxwell1: 11list").set("multigrid algorithm", "smoothed reitzinger");
119  newList.sublist("maxwell1: 11list").set("aggregation: type", "uncoupled");
120 
121  newList.sublist("maxwell1: 22list").set("multigrid algorithm", "unsmoothed");
122  newList.sublist("maxwell1: 22list").set("aggregation: type", "uncoupled");
123 
124  if (newList.sublist("maxwell1: 22list").isType<std::string>("verbosity"))
125  newList.set("verbosity", newList.sublist("maxwell1: 22list").get<std::string>("verbosity"));
126 
127  // Move coarse solver and smoother stuff to 11list
128  std::vector<std::string> convert = {"coarse:", "smoother:", "smoother: pre", "smoother: post"};
129  for (auto it = convert.begin(); it != convert.end(); ++it) {
130  if (newList.sublist("maxwell1: 22list").isType<std::string>(*it + " type")) {
131  newList.sublist("maxwell1: 11list").set(*it + " type", newList.sublist("maxwell1: 22list").get<std::string>(*it + " type"));
132  newList.sublist("maxwell1: 22list").remove(*it + " type");
133  }
134  if (newList.sublist("maxwell1: 22list").isSublist(*it + " params")) {
135  newList.sublist("maxwell1: 11list").set(*it + " params", newList.sublist("maxwell1: 22list").sublist(*it + " params"));
136  newList.sublist("maxwell1: 22list").remove(*it + " params");
137  }
138  }
139 
140  newList.sublist("maxwell1: 22list").set("smoother: type", "none");
141  newList.sublist("maxwell1: 22list").set("coarse: type", "none");
142 
143  newList.set("maxwell1: nodal smoother fix zero diagonal threshold", 1e-10);
144  newList.sublist("maxwell1: 22list").set("rap: fix zero diagonals", true);
145  newList.sublist("maxwell1: 22list").set("rap: fix zero diagonals threshold", 1e-10);
146 
147  list = newList;
148  }
149  std::string mode_string = list.get("maxwell1: mode", MasterList::getDefault<std::string>("maxwell1: mode"));
150  applyBCsTo22_ = list.get("maxwell1: apply BCs to 22", false);
151  dump_matrices_ = list.get("maxwell1: dump matrices", MasterList::getDefault<bool>("maxwell1: dump matrices"));
152 
153  // Default smoother. We'll copy this around.
154  Teuchos::ParameterList defaultSmootherList;
155  defaultSmootherList.set("smoother: type", "CHEBYSHEV");
156  defaultSmootherList.sublist("smoother: params").set("chebyshev: degree", 2);
157  defaultSmootherList.sublist("smoother: params").set("chebyshev: ratio eigenvalue", 7.0);
158  defaultSmootherList.sublist("smoother: params").set("chebyshev: eigenvalue max iterations", 30);
159 
160  // Make sure verbosity gets passed to the sublists
161  std::string verbosity = list.get("verbosity", "high");
163 
164  // Check the validity of the run mode
165  if (mode_ != MODE_GMHD_STANDARD) {
166  if (mode_string == "standard")
167  mode_ = MODE_STANDARD;
168  else if (mode_string == "refmaxwell")
169  mode_ = MODE_REFMAXWELL;
170  else if (mode_string == "edge only")
171  mode_ = MODE_EDGE_ONLY;
172  else {
173  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Must use mode 'standard', 'refmaxwell', 'edge only', or use the GMHD constructor.");
174  }
175  }
176 
177  // If we're in edge only or standard modes, then the (2,2) hierarchy gets built without smoothers.
178  // Otherwise we use the user's smoothers (defaulting to Chebyshev if unspecified)
179  if (list.isSublist("maxwell1: 22list"))
180  precList22_ = list.sublist("maxwell1: 22list");
181  else if (list.isSublist("refmaxwell: 22list"))
182  precList22_ = list.sublist("refmaxwell: 22list");
183  if (mode_ == MODE_EDGE_ONLY || mode_ == MODE_STANDARD || mode_ == MODE_GMHD_STANDARD)
184  precList22_.set("smoother: pre or post", "none");
185  else if (!precList22_.isType<std::string>("Preconditioner Type") &&
186  !precList22_.isType<std::string>("smoother: type") &&
187  !precList22_.isType<std::string>("smoother: pre type") &&
188  !precList22_.isType<std::string>("smoother: post type")) {
189  precList22_ = defaultSmootherList;
190  }
191  precList22_.set("verbosity", precList22_.get("verbosity", verbosity));
192 
193  // For the (1,1) hierarchy we'll use Hiptmair (STANDARD) or Chebyshev (EDGE_ONLY / REFMAXWELL) if
194  // the user doesn't specify things
195  if (list.isSublist("maxwell1: 11list"))
196  precList11_ = list.sublist("maxwell1: 11list");
197  else if (list.isSublist("refmaxwell: 11list"))
198  precList11_ = list.sublist("refmaxwell: 11list");
199 
200  if (mode_ == MODE_GMHD_STANDARD) {
201  precList11_.set("smoother: pre or post", "none");
202  precList11_.set("smoother: type", "none");
203  }
204  if (!precList11_.isType<std::string>("Preconditioner Type") &&
205  !precList11_.isType<std::string>("smoother: type") &&
206  !precList11_.isType<std::string>("smoother: pre type") &&
207  !precList11_.isType<std::string>("smoother: post type")) {
208  if (mode_ == MODE_EDGE_ONLY || mode_ == MODE_REFMAXWELL) {
209  precList11_ = defaultSmootherList;
210  }
211  if (mode_ == MODE_STANDARD) {
212  precList11_.set("smoother: type", "HIPTMAIR");
213  precList11_.set("hiptmair: smoother type 1", "CHEBYSHEV");
214  precList11_.set("hiptmair: smoother type 2", "CHEBYSHEV");
215  precList11_.sublist("hiptmair: smoother list 1") = defaultSmootherList;
216  precList11_.sublist("hiptmair: smoother list 2") = defaultSmootherList;
217  }
218  }
219  precList11_.set("verbosity", precList11_.get("verbosity", verbosity));
220 
221  // Reuse support
222  if (enable_reuse_ &&
223  !precList11_.isType<std::string>("Preconditioner Type") &&
224  !precList11_.isParameter("reuse: type"))
225  precList11_.set("reuse: type", "full");
226  if (enable_reuse_ &&
227  !precList22_.isType<std::string>("Preconditioner Type") &&
228  !precList22_.isParameter("reuse: type"))
229  precList22_.set("reuse: type", "full");
230 
231  // Are we using Kokkos?
232  useKokkos_ = !Node::is_serial;
233  useKokkos_ = list.get("use kokkos refactor", useKokkos_);
234 
235  parameterList_ = list;
236 }
237 
238 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
240  Teuchos::ParameterList precListGmhd;
241 
242  MueLu::HierarchyUtils<SC, LO, GO, NO>::CopyBetweenHierarchies(*Hierarchy11_, *HierarchyGmhd_, "P", "Psubblock", "RCP<Matrix>");
243 
244  HierarchyGmhd_->GetLevel(0)->Set("A", GmhdA_Matrix_);
245  GmhdA_Matrix_->setObjectLabel("GmhdA");
246 
247  TEUCHOS_TEST_FOR_EXCEPTION(!List.isSublist("maxwell1: Gmhdlist"), Exceptions::RuntimeError, "Must provide maxwell1: Gmhdlist for GMHD setup");
248  precListGmhd = List.sublist("maxwell1: Gmhdlist");
249  precListGmhd.set("coarse: max size", 1);
250  precListGmhd.set("max levels", HierarchyGmhd_->GetNumLevels());
251  RCP<MueLu::HierarchyManager<SC, LO, GO, NO> > mueLuFactory = rcp(new MueLu::ParameterListInterpreter<SC, LO, GO, NO>(precListGmhd, GmhdA_Matrix_->getDomainMap()->getComm()));
252  HierarchyGmhd_->setlib(GmhdA_Matrix_->getDomainMap()->lib());
253  HierarchyGmhd_->SetProcRankVerbose(GmhdA_Matrix_->getDomainMap()->getComm()->getRank());
254  mueLuFactory->SetupHierarchy(*HierarchyGmhd_);
255 }
256 
257 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
259  /* Algorithm overview for Maxwell1 construction:
260 
261  1) Create a nodal auxillary hierarchy based on (a) the user's nodal matrix or (b) a matrix constructed
262  by D0^T A D0 if the user doesn't provide a nodal matrix. We call this matrix "NodeAggMatrix."
263 
264  2) If the user provided a node matrix, we use the prolongators from the auxillary nodal hierarchy
265  to generate matrices for smoothers on all levels. We call this "NodeMatrix." Otherwise NodeMatrix = NodeAggMatrix
266 
267  3) We stick all of the nodal P matrices and NodeMatrix objects on the final (1,1) hierarchy and then use the
268  ReitzingerPFactory to generate the edge P and A matrices.
269  */
270 
271 #ifdef HAVE_MUELU_CUDA
272  if (parameterList_.get<bool>("maxwell1: cuda profile setup", false)) cudaProfilerStart();
273 #endif
274 
275  std::string timerLabel;
276  if (reuse)
277  timerLabel = "MueLu Maxwell1: compute (reuse)";
278  else
279  timerLabel = "MueLu Maxwell1: compute";
280  RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
281 
283  // Generate Kn and apply BCs (if needed)
284  bool have_generated_Kn = false;
285  if (Kn_Matrix_.is_null()) {
286  // generate_kn() will do diagonal repair if requested
287  GetOStream(Runtime0) << "Maxwell1::compute(): Kn not provided. Generating." << std::endl;
288  Kn_Matrix_ = generate_kn();
289  have_generated_Kn = true;
290  } else if (parameterList_.get<bool>("rap: fix zero diagonals", true)) {
291  magnitudeType threshold;
292  if (parameterList_.isType<magnitudeType>("rap: fix zero diagonals threshold"))
293  threshold = parameterList_.get<magnitudeType>("rap: fix zero diagonals threshold",
295  else
296  threshold = Teuchos::as<magnitudeType>(parameterList_.get<double>("rap: fix zero diagonals threshold",
298  Scalar replacement = Teuchos::as<Scalar>(parameterList_.get<double>("rap: fix zero diagonals replacement",
299  MasterList::getDefault<double>("rap: fix zero diagonals replacement")));
300  Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(Kn_Matrix_, true, GetOStream(Warnings1), threshold, replacement);
301  }
302 
304  // Generate the (2,2) Hierarchy
305  Kn_Matrix_->setObjectLabel("Maxwell1 (2,2)");
306 
307  /* Critical ParameterList changes */
308  if (!Coords_.is_null())
309  precList22_.sublist("user data").set("Coordinates", Coords_);
310 
311  /* Repartitioning *must* be in sync between hierarchies, but the
312  only thing we need to watch here is the subcomms, since ReitzingerPFactory
313  won't look at all the other stuff */
314  if (precList22_.isParameter("repartition: enable")) {
315  bool repartition = precList22_.get<bool>("repartition: enable");
316  precList11_.set("repartition: enable", repartition);
317 
318  // If we're repartitioning (2,2), we need to rebalance for (1,1) to do the right thing
319  if (repartition)
320  precList22_.set("repartition: rebalance P and R", true);
321 
322  if (precList22_.isParameter("repartition: use subcommunicators")) {
323  precList11_.set("repartition: use subcommunicators", precList22_.get<bool>("repartition: use subcommunicators"));
324 
325  // We do not want (1,1) and (2,2) blocks being repartitioned seperately, so we specify the map that
326  // is going to be used (this is generated in ReitzingerPFactory)
327  if (precList11_.get<bool>("repartition: use subcommunicators") == true)
328  precList11_.set("repartition: use subcommunicators in place", true);
329  } else {
330  // We'll have Maxwell1 default to using subcommunicators if you don't specify
331  precList11_.set("repartition: use subcommunicators", true);
332  precList22_.set("repartition: use subcommunicators", true);
333 
334  // We do not want (1,1) and (2,2) blocks being repartitioned seperately, so we specify the map that
335  // is going to be used (this is generated in ReitzingerPFactory)
336  precList11_.set("repartition: use subcommunicators in place", true);
337  }
338 
339  } else
340  precList11_.remove("repartition: enable", false);
341 
343  // Remove explicit zeros from matrices
344  /*
345  Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(parameterList_,D0_Matrix_,SM_Matrix_);
346 
347 
348  if (IsPrint(Statistics2)) {
349  RCP<ParameterList> params = rcp(new ParameterList());;
350  params->set("printLoadBalancingInfo", true);
351  params->set("printCommInfo", true);
352  GetOStream(Statistics2) << PerfUtils::PrintMatrixInfo(*SM_Matrix_, "SM_Matrix", params);
353  }
354  */
355 
357  // Detect Dirichlet boundary conditions
358  if (!reuse) {
359  magnitudeType rowSumTol = precList11_.get("aggregation: row sum drop tol", -1.0);
360  Maxwell_Utils<SC, LO, GO, NO>::detectBoundaryConditionsSM(SM_Matrix_, D0_Matrix_, rowSumTol,
361  useKokkos_, BCrowsKokkos_, BCcolsKokkos_, BCdomainKokkos_,
362  BCedges_, BCnodes_, BCrows_, BCcols_, BCdomain_,
363  allEdgesBoundary_, allNodesBoundary_);
364  if (IsPrint(Statistics2)) {
365  GetOStream(Statistics2) << "MueLu::Maxwell1::compute(): Detected " << BCedges_ << " BC rows and " << BCnodes_ << " BC columns." << std::endl;
366  }
367  }
368 
369  if (allEdgesBoundary_) {
370  // All edges have been detected as boundary edges.
371  // Do not attempt to construct sub-hierarchies, but just set up a single level preconditioner.
372  GetOStream(Warnings0) << "All edges are detected as boundary edges!" << std::endl;
373  mode_ = MODE_EDGE_ONLY;
374 
375  // Generate single level hierarchy for the edge
376  precList22_.set("max levels", 1);
377  }
378 
379  if (allNodesBoundary_) {
380  // All Nodes have been detected as boundary nodes.
381  // Do not attempt to construct sub-hierarchies, but just set up a single level preconditioner.
382  GetOStream(Warnings0) << "All nodes are detected as boundary nodes!" << std::endl;
383  mode_ = MODE_EDGE_ONLY;
384 
385  // Generate single level hierarchy for the edge
386  precList22_.set("max levels", 1);
387  }
388 
390  // Build (2,2) hierarchy
391  Hierarchy22_ = MueLu::CreateXpetraPreconditioner(Kn_Matrix_, precList22_);
392 
394  // Apply boundary conditions to D0 (if needed)
395  if (!reuse) {
396  D0_Matrix_->resumeFill();
397  Scalar replaceWith;
398  if (D0_Matrix_->getRowMap()->lib() == Xpetra::UseEpetra)
399  replaceWith = Teuchos::ScalarTraits<SC>::eps();
400  else
401  replaceWith = Teuchos::ScalarTraits<SC>::zero();
402 
403  if (applyBCsTo22_) {
404  GetOStream(Runtime0) << "Maxwell1::compute(): nuking BC rows/cols of D0" << std::endl;
405  if (useKokkos_) {
406  Utilities::ZeroDirichletCols(D0_Matrix_, BCcolsKokkos_, replaceWith);
407  } else {
408  Utilities::ZeroDirichletCols(D0_Matrix_, BCcols_, replaceWith);
409  }
410  } else {
411  GetOStream(Runtime0) << "Maxwell1::compute(): nuking BC rows of D0" << std::endl;
412  if (useKokkos_) {
413  Utilities::ZeroDirichletRows(D0_Matrix_, BCrowsKokkos_, replaceWith);
414  } else {
415  Utilities::ZeroDirichletRows(D0_Matrix_, BCrows_, replaceWith);
416  }
417  }
418 
419  D0_Matrix_->fillComplete(D0_Matrix_->getDomainMap(), D0_Matrix_->getRangeMap());
420  }
421 
423  // What ML does is generate nodal prolongators with an auxillary hierarchy based on the
424  // user's (2,2) matrix. The actual nodal matrices for smoothing are generated by the
425  // Hiptmair smoother construction. We're not going to do that --- we'll
426  // do as we insert them into the final (1,1) hierarchy.
427 
428  // Level 0
429  RCP<Matrix> Kn_Smoother_0;
430  if (have_generated_Kn) {
431  Kn_Smoother_0 = Kn_Matrix_;
432  } else {
433  Kn_Smoother_0 = generate_kn();
434  }
435 
437  // Copy the relevant (2,2) data to the (1,1) hierarchy
438  Hierarchy11_ = rcp(new Hierarchy("Maxwell1 (1,1)"));
439  RCP<Matrix> OldSmootherMatrix;
440  RCP<Level> OldEdgeLevel;
441  for (int i = 0; i < Hierarchy22_->GetNumLevels(); i++) {
442  Hierarchy11_->AddNewLevel();
443  RCP<Level> NodeL = Hierarchy22_->GetLevel(i);
444  RCP<Level> EdgeL = Hierarchy11_->GetLevel(i);
445  RCP<Operator> NodeOp = NodeL->Get<RCP<Operator> >("A");
446  RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(NodeOp);
447  std::string labelstr = FormattingHelper::getColonLabel(EdgeL->getObjectLabel());
448 
449  if (i == 0) {
450  EdgeL->Set("A", SM_Matrix_);
451  EdgeL->Set("D0", D0_Matrix_);
452 
453  EdgeL->Set("NodeAggMatrix", NodeAggMatrix);
454  EdgeL->Set("NodeMatrix", Kn_Smoother_0);
455  OldSmootherMatrix = Kn_Smoother_0;
456  OldEdgeLevel = EdgeL;
457  } else {
458  // Set the Nodal P
459  // NOTE: ML uses normalized prolongators for the aggregation hierarchy
460  // and then prolongators of all 1's for doing the Reitzinger prolongator
461  // generation for the edge hierarchy.
462  auto NodalP = NodeL->Get<RCP<Matrix> >("P");
463  auto NodalP_ones = Utilities::ReplaceNonZerosWithOnes(NodalP);
464  TEUCHOS_TEST_FOR_EXCEPTION(NodalP_ones.is_null(), Exceptions::RuntimeError, "Applying ones to prolongator failed");
465  EdgeL->Set("Pnodal", NodalP_ones);
466 
467  // If we repartition a processor away, a RCP<Operator> is stuck
468  // on the level instead of an RCP<Matrix>
469  if (!NodeAggMatrix.is_null()) {
470  EdgeL->Set("NodeAggMatrix", NodeAggMatrix);
471  if (!have_generated_Kn) {
472  // The user gave us a Kn on the fine level, so we're using a seperate aggregation
473  // hierarchy from the smoothing hierarchy.
474 
475  // ML does a *fixed* 1e-10 diagonal repair on the Nodal Smoothing Matrix
476  // This fix is applied *after* the next level is generated, but before the smoother is.
477  // We can see this behavior from ML, though it isn't 100% clear from the code *how* it happens.
478  // So, here we turn the fix off, then once we've generated the new matrix, we fix the old one.
479 
480  // Generate the new matrix
481  Teuchos::ParameterList RAPlist;
482  RAPlist.set("rap: fix zero diagonals", false);
483  RCP<Matrix> NewKn = Maxwell_Utils<SC, LO, GO, NO>::PtAPWrapper(OldSmootherMatrix, NodalP_ones, RAPlist, labelstr);
484  EdgeL->Set("NodeMatrix", NewKn);
485 
486  // Fix the old one
487  double thresh = parameterList_.get("maxwell1: nodal smoother fix zero diagonal threshold", 1e-10);
488  if (thresh > 0.0) {
489  printf("CMS: Reparing diagonal after next level generation\n");
491  Xpetra::MatrixUtils<SC, LO, GO, NO>::CheckRepairMainDiagonal(OldSmootherMatrix, true, GetOStream(Warnings1), thresh, replacement);
492  }
493  OldEdgeLevel->Set("NodeMatrix", OldSmootherMatrix);
494 
495  OldSmootherMatrix = NewKn;
496  } else {
497  // The user didn't give us a Kn, so we aggregate and smooth with the same matrix
498  EdgeL->Set("NodeMatrix", NodeAggMatrix);
499  }
500  } else {
501  // We've partitioned things away.
502  EdgeL->Set("NodeMatrix", NodeOp);
503  EdgeL->Set("NodeAggMatrix", NodeOp);
504  }
505 
506  OldEdgeLevel = EdgeL;
507  }
508 
509  // Get the importer if we have one (for repartitioning)
510  // This will get used in ReitzingerPFactory
511  if (NodeL->IsAvailable("Importer")) {
512  auto importer = NodeL->Get<RCP<const Import> >("Importer");
513  EdgeL->Set("NodeImporter", importer);
514  }
515  } // end Hierarchy22 loop
516 
518  // Generating the (1,1) Hierarchy
519  std::string fine_smoother = precList11_.get<std::string>("smoother: type");
520  {
521  SM_Matrix_->setObjectLabel("A(1,1)");
522  precList11_.set("coarse: max size", 1);
523  precList11_.set("max levels", Hierarchy22_->GetNumLevels());
524 
525  const bool refmaxwellCoarseSolve = (precList11_.get<std::string>("coarse: type",
526  MasterList::getDefault<std::string>("coarse: type")) == "RefMaxwell");
527  if (refmaxwellCoarseSolve) {
528  GetOStream(Runtime0) << "Maxwell1::compute(): Will set up RefMaxwell coarse solver" << std::endl;
529  precList11_.set("coarse: type", "none");
530  }
531 
532  // Rip off non-serializable data before validation
533  Teuchos::ParameterList nonSerialList11, processedPrecList11;
534  MueLu::ExtractNonSerializableData(precList11_, processedPrecList11, nonSerialList11);
535  RCP<HierarchyManager<SC, LO, GO, NO> > mueLuFactory = rcp(new ParameterListInterpreter<SC, LO, GO, NO>(processedPrecList11, SM_Matrix_->getDomainMap()->getComm()));
536  Hierarchy11_->setlib(SM_Matrix_->getDomainMap()->lib());
537  Hierarchy11_->SetProcRankVerbose(SM_Matrix_->getDomainMap()->getComm()->getRank());
538  // Stick the non-serializible data on the hierarchy.
539  HierarchyUtils<SC, LO, GO, NO>::AddNonSerializableDataToHierarchy(*mueLuFactory, *Hierarchy11_, nonSerialList11);
540  mueLuFactory->SetupHierarchy(*Hierarchy11_);
541 
542  if (refmaxwellCoarseSolve) {
543  GetOStream(Runtime0) << "Maxwell1::compute(): Setting up RefMaxwell coarse solver" << std::endl;
544  auto coarseLvl = Hierarchy11_->GetLevel(Hierarchy11_->GetNumLevels() - 1);
546  precList11_.sublist("coarse: params")));
547  coarseSolver->Setup(*coarseLvl);
548  coarseLvl->Set("PreSmoother",
549  rcp_dynamic_cast<SmootherBase>(coarseSolver, true));
550  }
551 
552  if (mode_ == MODE_REFMAXWELL) {
553  if (Hierarchy11_->GetNumLevels() > 1) {
554  RCP<Level> EdgeL = Hierarchy11_->GetLevel(1);
555  P11_ = EdgeL->Get<RCP<Matrix> >("P");
556  }
557  }
558  }
559 
561  // Allocate temporary MultiVectors for solve (only needed for RefMaxwell style)
562  allocateMemory(1);
563 
564  describe(GetOStream(Runtime0));
565 
566 #ifdef MUELU_MAXWELL1_DEBUG
567  for (int i = 0; i < Hierarchy11_->GetNumLevels(); i++) {
568  RCP<Level> L = Hierarchy11_->GetLevel(i);
569  RCP<Matrix> EdgeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("A"));
570  RCP<Matrix> NodeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("NodeMatrix"));
571  RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("NodeAggMatrix"));
572  RCP<Matrix> D0 = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("D0"));
573 
574  auto nrmE = EdgeMatrix->getFrobeniusNorm();
575  auto nrmN = NodeMatrix->getFrobeniusNorm();
576  auto nrmNa = NodeAggMatrix->getFrobeniusNorm();
577  auto nrmD0 = D0->getFrobeniusNorm();
578 
579  std::cout << "DEBUG: Norms on Level " << i << " E/N/NA/D0 = " << nrmE << " / " << nrmN << " / " << nrmNa << " / " << nrmD0 << std::endl;
580  std::cout << "DEBUG: NNZ on Level " << i << " E/N/NA/D0 = " << EdgeMatrix->getGlobalNumEntries() << " / " << NodeMatrix->getGlobalNumEntries() << " / " << NodeAggMatrix->getGlobalNumEntries() << " / " << D0->getGlobalNumEntries() << std::endl;
581  }
582 #endif
583 }
584 
585 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
587  // This is important, as we'll be doing diagonal repair *after* the next-level matrix is generated, not before
588  Teuchos::ParameterList RAPlist;
589  RAPlist.set("rap: fix zero diagonals", false);
590 
591  std::string labelstr = "NodeMatrix (Level 0)";
592  RCP<Matrix> rv = Maxwell_Utils<SC, LO, GO, NO>::PtAPWrapper(SM_Matrix_, D0_Matrix_, RAPlist, labelstr);
593  return rv;
594 }
595 
596 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
598  if (mode_ == MODE_REFMAXWELL) {
599  RCP<Teuchos::TimeMonitor> tmAlloc = getTimer("MueLu Maxwell1: Allocate MVs");
600 
601  residualFine_ = MultiVectorFactory::Build(SM_Matrix_->getRangeMap(), numVectors);
602 
603  if (!Hierarchy11_.is_null() && Hierarchy11_->GetNumLevels() > 1) {
604  RCP<Level> EdgeL = Hierarchy11_->GetLevel(1);
605  RCP<Matrix> A = EdgeL->Get<RCP<Matrix> >("A");
606  residual11c_ = MultiVectorFactory::Build(A->getRangeMap(), numVectors);
607  update11c_ = MultiVectorFactory::Build(A->getDomainMap(), numVectors);
608  }
609 
610  if (!Hierarchy22_.is_null()) {
611  residual22_ = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(), numVectors);
612  update22_ = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(), numVectors);
613  }
614  }
615 }
616 
617 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
618 void Maxwell1<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dump(const Matrix& A, std::string name) const {
619  if (dump_matrices_) {
620  GetOStream(Runtime0) << "Dumping to " << name << std::endl;
622  }
623 }
624 
625 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
627  if (dump_matrices_) {
628  GetOStream(Runtime0) << "Dumping to " << name << std::endl;
630  }
631 }
632 
633 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
635  if (dump_matrices_) {
636  GetOStream(Runtime0) << "Dumping to " << name << std::endl;
638  }
639 }
640 
641 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
643  if (dump_matrices_) {
644  GetOStream(Runtime0) << "Dumping to " << name << std::endl;
645  std::ofstream out(name);
646  for (size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
647  out << v[i] << "\n";
648  }
649 }
650 
651 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
652 void Maxwell1<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dump(const Kokkos::View<bool*, typename Node::device_type>& v, std::string name) const {
653  if (dump_matrices_) {
654  GetOStream(Runtime0) << "Dumping to " << name << std::endl;
655  std::ofstream out(name);
656  auto vH = Kokkos::create_mirror_view(v);
657  Kokkos::deep_copy(vH, v);
658  for (size_t i = 0; i < vH.size(); i++)
659  out << vH[i] << "\n";
660  }
661 }
662 
663 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
665  if (IsPrint(Timings)) {
666  if (!syncTimers_)
668  else {
669  if (comm.is_null())
670  return Teuchos::rcp(new Teuchos::SyncTimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name), SM_Matrix_->getRowMap()->getComm().ptr()));
671  else
673  }
674  } else
675  return Teuchos::null;
676 }
677 
678 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
680  bool reuse = !SM_Matrix_.is_null();
681  SM_Matrix_ = SM_Matrix_new;
682  dump(*SM_Matrix_, "SM.m");
683  if (ComputePrec)
684  compute(reuse);
685 }
686 
687 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
689  // make sure that we have enough temporary memory
690  const SC one = Teuchos::ScalarTraits<SC>::one();
691  if (!allEdgesBoundary_ && X.getNumVectors() != residualFine_->getNumVectors())
692  allocateMemory(X.getNumVectors());
693 
694  TEUCHOS_TEST_FOR_EXCEPTION(Hierarchy11_.is_null() || Hierarchy11_->GetNumLevels() == 0, Exceptions::RuntimeError, "(1,1) Hiearchy is null.");
695 
696  // 1) Run fine pre-smoother using Hierarchy11
697  RCP<Level> Fine = Hierarchy11_->GetLevel(0);
698  if (Fine->IsAvailable("PreSmoother")) {
699  RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: PreSmoother");
700  RCP<SmootherBase> preSmoo = Fine->Get<RCP<SmootherBase> >("PreSmoother");
701  preSmoo->Apply(X, RHS, true);
702  }
703 
704  // 2) Compute residual
705  {
706  RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: residual calculation");
707  Utilities::Residual(*SM_Matrix_, X, RHS, *residualFine_);
708  }
709 
710  // 3a) Restrict residual to (1,1) Hierarchy's level 1 and execute (1,1) hierarchy (use startLevel and InitialGuessIsZero)
711  if (!P11_.is_null()) {
712  RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: (1,1) correction");
713  P11_->apply(*residualFine_, *residual11c_, Teuchos::TRANS);
714  Hierarchy11_->Iterate(*residual11c_, *update11c_, true, 1);
715  }
716 
717  // 3b) Restrict residual to (2,2) Hierarchy's level 0 and execute (2,2) hierarchy (use InitialGuessIsZero)
718  if (!allNodesBoundary_) {
719  RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: (2,2) correction");
720  D0_Matrix_->apply(*residualFine_, *residual22_, Teuchos::TRANS);
721  Hierarchy22_->Iterate(*residual22_, *update22_, true, 0);
722  }
723 
724  // 4) Prolong both updates back into X-vector (Need to do both the P11 null and not null cases
725  {
726  RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: Orolongation");
727  if (!P11_.is_null())
728  P11_->apply(*update11c_, X, Teuchos::NO_TRANS, one, one);
729  if (!allNodesBoundary_)
730  D0_Matrix_->apply(*update22_, X, Teuchos::NO_TRANS, one, one);
731  }
732 
733  // 5) Run fine post-smoother using Hierarchy11
734  if (Fine->IsAvailable("PostSmoother")) {
735  RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: PostSmoother");
736  RCP<SmootherBase> postSmoo = Fine->Get<RCP<SmootherBase> >("PostSmoother");
737  postSmoo->Apply(X, RHS, false);
738  }
739 }
740 
741 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
743  Hierarchy11_->Iterate(RHS, X, 1, true);
744 }
745 
746 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
748  Teuchos::ETransp /* mode */,
749  Scalar /* alpha */,
750  Scalar /* beta */) const {
751  RCP<Teuchos::TimeMonitor> tm = getTimer("MueLu Maxwell1: solve");
752  if (mode_ == MODE_GMHD_STANDARD)
753  HierarchyGmhd_->Iterate(RHS, X, 1, true);
754  else if (mode_ == MODE_STANDARD || mode_ == MODE_EDGE_ONLY)
755  applyInverseStandard(RHS, X);
756  else if (mode_ == MODE_REFMAXWELL)
757  applyInverseRefMaxwellAdditive(RHS, X);
758  else
759  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Must use mode 'standard', 'refmaxwell' or 'edge only' when not doing GMHD.");
760 }
761 
762 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
764  return false;
765 }
766 
767 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
770  const Teuchos::RCP<Matrix>& Kn_Matrix,
771  const Teuchos::RCP<MultiVector>& Nullspace,
773  Teuchos::ParameterList& List) {
774  // some pre-conditions
775  TEUCHOS_ASSERT(D0_Matrix != Teuchos::null);
776 
777 #ifdef HAVE_MUELU_DEBUG
778  if (!Kn_Matrix.is_null()) {
779  TEUCHOS_ASSERT(Kn_Matrix->getDomainMap()->isSameAs(*D0_Matrix->getDomainMap()));
780  TEUCHOS_ASSERT(Kn_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getDomainMap()));
781  }
782 
783  TEUCHOS_ASSERT(D0_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getRowMap()));
784 #endif
785 
786  Hierarchy11_ = Teuchos::null;
787  Hierarchy22_ = Teuchos::null;
788  HierarchyGmhd_ = Teuchos::null;
789  if (mode_ != MODE_GMHD_STANDARD) mode_ = MODE_STANDARD;
790 
791  // Default settings
792  useKokkos_ = false;
793  allEdgesBoundary_ = false;
794  allNodesBoundary_ = false;
795  dump_matrices_ = false;
796  enable_reuse_ = false;
797  syncTimers_ = false;
798  applyBCsTo22_ = false;
799 
800  // set parameters
801  setParameters(List);
802 
803  if (D0_Matrix->getRowMap()->lib() == Xpetra::UseTpetra) {
804  // We will remove boundary conditions from D0, and potentially change maps, so we copy the input.
805  // Fortunately, D0 is quite sparse.
806  // We cannot use the Tpetra copy constructor, since it does not copy the graph.
807 
808  RCP<Matrix> D0copy = MatrixFactory::Build(D0_Matrix->getRowMap(), D0_Matrix->getColMap(), 0);
809  RCP<CrsMatrix> D0copyCrs = rcp_dynamic_cast<CrsMatrixWrap>(D0copy, true)->getCrsMatrix();
810  ArrayRCP<const size_t> D0rowptr_RCP;
811  ArrayRCP<const LO> D0colind_RCP;
812  ArrayRCP<const SC> D0vals_RCP;
813  rcp_dynamic_cast<CrsMatrixWrap>(D0_Matrix, true)->getCrsMatrix()->getAllValues(D0rowptr_RCP, D0colind_RCP, D0vals_RCP);
814 
815  ArrayRCP<size_t> D0copyrowptr_RCP;
816  ArrayRCP<LO> D0copycolind_RCP;
817  ArrayRCP<SC> D0copyvals_RCP;
818  D0copyCrs->allocateAllValues(D0vals_RCP.size(), D0copyrowptr_RCP, D0copycolind_RCP, D0copyvals_RCP);
819  D0copyrowptr_RCP.deepCopy(D0rowptr_RCP());
820  D0copycolind_RCP.deepCopy(D0colind_RCP());
821  D0copyvals_RCP.deepCopy(D0vals_RCP());
822  D0copyCrs->setAllValues(D0copyrowptr_RCP,
823  D0copycolind_RCP,
824  D0copyvals_RCP);
825  D0copyCrs->expertStaticFillComplete(D0_Matrix->getDomainMap(), D0_Matrix->getRangeMap(),
826  rcp_dynamic_cast<CrsMatrixWrap>(D0_Matrix, true)->getCrsMatrix()->getCrsGraph()->getImporter(),
827  rcp_dynamic_cast<CrsMatrixWrap>(D0_Matrix, true)->getCrsMatrix()->getCrsGraph()->getExporter());
828  D0_Matrix_ = D0copy;
829  } else
830  D0_Matrix_ = MatrixFactory::BuildCopy(D0_Matrix);
831 
832  Kn_Matrix_ = Kn_Matrix;
833  Coords_ = Coords;
834  Nullspace_ = Nullspace;
835 
836  if (!Kn_Matrix_.is_null()) dump(*Kn_Matrix_, "Kn.m");
837  if (!Nullspace_.is_null()) dump(*Nullspace_, "nullspace.m");
838  if (!Coords_.is_null()) dumpCoords(*Coords_, "coords.m");
839 }
840 
841 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
843  describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel /* verbLevel */) const {
844  std::ostringstream oss;
845 
846  RCP<const Teuchos::Comm<int> > comm = SM_Matrix_->getDomainMap()->getComm();
847 
848 #ifdef HAVE_MPI
849  int root;
850  if (!Kn_Matrix_.is_null())
851  root = comm->getRank();
852  else
853  root = -1;
854 
855  int actualRoot;
856  reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
857  root = actualRoot;
858 #endif
859 
860  oss << "\n--------------------------------------------------------------------------------\n"
861  << "--- Maxwell1 Summary ---\n"
862  "--------------------------------------------------------------------------------"
863  << std::endl;
864  oss << std::endl;
865 
866  GlobalOrdinal numRows;
867  GlobalOrdinal nnz;
868 
869  SM_Matrix_->getRowMap()->getComm()->barrier();
870 
871  numRows = SM_Matrix_->getGlobalNumRows();
872  nnz = SM_Matrix_->getGlobalNumEntries();
873 
874  Xpetra::global_size_t tt = numRows;
875  int rowspacer = 3;
876  while (tt != 0) {
877  tt /= 10;
878  rowspacer++;
879  }
880  tt = nnz;
881  int nnzspacer = 2;
882  while (tt != 0) {
883  tt /= 10;
884  nnzspacer++;
885  }
886 
887  oss << "block " << std::setw(rowspacer) << " rows " << std::setw(nnzspacer) << " nnz " << std::setw(9) << " nnz/row" << std::endl;
888  oss << "(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
889 
890  if (!Kn_Matrix_.is_null()) {
891  // ToDo: make sure that this is printed correctly
892  numRows = Kn_Matrix_->getGlobalNumRows();
893  nnz = Kn_Matrix_->getGlobalNumEntries();
894 
895  oss << "(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
896  }
897 
898  oss << std::endl;
899 
900  std::string outstr = oss.str();
901 
902 #ifdef HAVE_MPI
903  RCP<const Teuchos::MpiComm<int> > mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm);
904  MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
905 
906  int strLength = outstr.size();
907  MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
908  if (comm->getRank() != root)
909  outstr.resize(strLength);
910  MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
911 #endif
912 
913  out << outstr;
914 
915  if (!Hierarchy11_.is_null())
916  Hierarchy11_->describe(out, GetVerbLevel());
917 
918  if (!Hierarchy22_.is_null())
919  Hierarchy22_->describe(out, GetVerbLevel());
920 
921  if (!HierarchyGmhd_.is_null())
922  HierarchyGmhd_->describe(out, GetVerbLevel());
923 
924  if (IsPrint(Statistics2)) {
925  // Print the grid of processors
926  std::ostringstream oss2;
927 
928  oss2 << "Sub-solver distribution over ranks" << std::endl;
929  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;
930 
931  int numProcs = comm->getSize();
932 #ifdef HAVE_MPI
933  RCP<const Teuchos::MpiComm<int> > tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm);
934 
935  RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > rawMpiComm = tmpic->getRawMpiComm();
936 #endif
937 
938  char status = 0;
939  if (!Kn_Matrix_.is_null())
940  status += 1;
941  std::vector<char> states(numProcs, 0);
942 #ifdef HAVE_MPI
943  MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
944 #else
945  states.push_back(status);
946 #endif
947 
948  int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
949  for (int proc = 0; proc < numProcs; proc += rowWidth) {
950  for (int j = 0; j < rowWidth; j++)
951  if (proc + j < numProcs)
952  if (states[proc + j] == 0)
953  oss2 << ".";
954  else if (states[proc + j] == 1)
955  oss2 << "1";
956  else if (states[proc + j] == 2)
957  oss2 << "2";
958  else
959  oss2 << "B";
960  else
961  oss2 << " ";
962 
963  oss2 << " " << proc << ":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
964  }
965  oss2 << std::endl;
966  GetOStream(Statistics2) << oss2.str();
967  }
968 }
969 
970 } // namespace MueLu
971 
972 #define MUELU_MAXWELL1_SHORT
973 #endif // ifdef MUELU_MAXWELL1_DEF_HPP
Important warning messages (one line)
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > PtAPWrapper(const RCP< Matrix > &A, const RCP< Matrix > &P, Teuchos::ParameterList &params, std::string &label)
Performs an P^T AP.
static void ZeroDirichletCols(Teuchos::RCP< Matrix > &A, const Teuchos::ArrayRCP< const bool > &dirichletCols, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
const Teuchos::RCP< const Map > getDomainMap() const
Returns the Xpetra::Map object associated with the domain of this operator.
Various adapters that will create a MueLu preconditioner that is an Xpetra::Matrix.
virtual std::string getObjectLabel() const
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 dump(const Matrix &A, std::string name) const
dump out matrix
static magnitudeType eps()
static void AddNonSerializableDataToHierarchy(HierarchyManager &HM, Hierarchy &H, const ParameterList &nonSerialList)
Add non-serializable data to Hierarchy.
T & get(const std::string &name, T def_value)
void resetMatrix(Teuchos::RCP< Matrix > SM_Matrix_new, bool ComputePrec=true)
Reset system matrix.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static void Write(const std::string &fileName, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &M)
void GMHDSetupHierarchy(Teuchos::ParameterList &List) const
Sets up hiearchy for GMHD matrices that include generalized Ohms law equations.
void initialize(const Teuchos::RCP< Matrix > &D0_Matrix, const Teuchos::RCP< Matrix > &Kn_Matrix, const Teuchos::RCP< MultiVector > &Nullspace, const Teuchos::RCP< RealValuedMultiVector > &Coords, Teuchos::ParameterList &List)
bool hasTransposeApply() const
Indicates whether this operator supports applying the adjoint operator.
One-liner description of what is happening.
static void ZeroDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const std::vector< LocalOrdinal > &dirichletRows, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > ReplaceNonZerosWithOnes(const RCP< Matrix > &original)
Creates a copy of a matrix where the non-zero entries are replaced by ones.
size_type size() const
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::VERB_HIGH) const
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())
MsgType toVerbLevel(const std::string &verbLevelStr)
static std::string getColonLabel(const std::string &label)
Helper function for object label.
Print even more statistics.
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.
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitudeType
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 setParameters(Teuchos::ParameterList &list)
Set parameters.
static void SetDefaultVerbLevel(const VerbLevel defaultVerbLevel)
Set the default (global) verbosity level.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
bool isSublist(const std::string &name) const
Teuchos::RCP< Teuchos::TimeMonitor > getTimer(std::string name, RCP< const Teuchos::Comm< int > > comm=Teuchos::null) const
get a (synced) timer
void deepCopy(const ArrayView< const T > &av)
Class that encapsulates Operator smoothers.
void applyInverseRefMaxwellAdditive(const MultiVector &RHS, MultiVector &X) const
apply RefMaxwell additive 2x2 style cycle
void allocateMemory(int numVectors) const
allocate multivectors for solve
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.
size_t global_size_t
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
Print all timing information.
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 applyInverseStandard(const MultiVector &RHS, MultiVector &X) const
apply standard Maxwell1 cycle
const Teuchos::RCP< const Map > getRangeMap() const
Returns the Xpetra::Map object associated with the range of this operator.
void compute(bool reuse=false)
Setup the preconditioner.
Scalar SC
bool isType(const std::string &name) const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
virtual size_t getNumVectors() const =0
Teuchos::RCP< Matrix > generate_kn() const
Generates the Kn matrix.
static std::string translate(Teuchos::ParameterList &paramList, const std::string &defaultVals="")
: Translate ML parameters to MueLu parameter XML string
void dumpCoords(const RealValuedMultiVector &X, std::string name) const
dump out real-valued multivector
virtual void Apply(MultiVector &x, const MultiVector &rhs, bool InitialGuessIsZero=false) const =0
Apply smoother.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
bool IsAvailable(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need&#39;s value has been saved.
long ExtractNonSerializableData(const Teuchos::ParameterList &inList, Teuchos::ParameterList &serialList, Teuchos::ParameterList &nonSerialList)
Extract non-serializable data from level-specific sublists and move it to a separate parameter list...
static void CopyBetweenHierarchies(Hierarchy &fromHierarchy, Hierarchy &toHierarchy, const std::string fromLabel, const std::string toLabel, const std::string dataType)
bool is_null() const