MueLu Version of the Day
Loading...
Searching...
No Matches
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>
50
51#include "MueLu_ConfigDefs.hpp"
52
53#include "Xpetra_Map.hpp"
54#include "Xpetra_CrsMatrixUtils.hpp"
55#include "Xpetra_MatrixUtils.hpp"
56
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>
73#include <MueLu_RefMaxwellSmoother.hpp>
74
75#ifdef HAVE_MUELU_CUDA
76#include "cuda_profiler_api.h"
77#endif
78
79
80namespace MueLu {
81
82
83 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
84 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getDomainMap() const {
85 return SM_Matrix_->getDomainMap();
86 }
87
88
89 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
90 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getRangeMap() const {
91 return SM_Matrix_->getRangeMap();
92 }
93
94
95 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
97
98 if (list.isType<std::string>("parameterlist: syntax") && list.get<std::string>("parameterlist: syntax") == "ml") {
99 list.remove("parameterlist: syntax");
100 Teuchos::ParameterList newList;
101
102 // interpret ML list
103 newList.sublist("maxwell1: 22list") = *Teuchos::getParametersFromXmlString(MueLu::ML2MueLuParameterTranslator::translate(list,"Maxwell"));
104
105
106
107
108 // Hardwiring options to ensure ML compatibility
109 newList.sublist("maxwell1: 22list").set("use kokkos refactor", false);
110
111 newList.sublist("maxwell1: 11list").set("use kokkos refactor", false);
112 newList.sublist("maxwell1: 11list").set("tentative: constant column sums", false);
113 newList.sublist("maxwell1: 11list").set("tentative: calculate qr", false);
114
115 newList.sublist("maxwell1: 11list").set("aggregation: use ml scaling of drop tol",true);
116 newList.sublist("maxwell1: 22list").set("aggregation: use ml scaling of drop tol",true);
117
118
119 if(list.isParameter("aggregation: damping factor") && list.get<double>("aggregation: damping factor") == 0.0)
120 newList.sublist("maxwell1: 11list").set("multigrid algorithm", "unsmoothed reitzinger");
121 else
122 newList.sublist("maxwell1: 11list").set("multigrid algorithm", "smoothed reitzinger");
123 newList.sublist("maxwell1: 11list").set("aggregation: type", "uncoupled");
124
125 newList.sublist("maxwell1: 22list").set("multigrid algorithm", "unsmoothed");
126 newList.sublist("maxwell1: 22list").set("aggregation: type", "uncoupled");
127
128 if (newList.sublist("maxwell1: 22list").isType<std::string>("verbosity"))
129 newList.set("verbosity", newList.sublist("maxwell1: 22list").get<std::string>("verbosity"));
130
131 // Move coarse solver and smoother stuff to 11list
132 std::vector<std::string> convert = {"coarse:", "smoother:", "smoother: pre", "smoother: post"};
133 for (auto it = convert.begin(); it != convert.end(); ++it) {
134 if (newList.sublist("maxwell1: 22list").isType<std::string>(*it + " type")) {
135 newList.sublist("maxwell1: 11list").set(*it+" type", newList.sublist("maxwell1: 22list").get<std::string>(*it+" type"));
136 newList.sublist("maxwell1: 22list").remove(*it+" type");
137 }
138 if (newList.sublist("maxwell1: 22list").isSublist(*it+" params")) {
139 newList.sublist("maxwell1: 11list").set(*it+" params", newList.sublist("maxwell1: 22list").sublist(*it+" params"));
140 newList.sublist("maxwell1: 22list").remove(*it+" params");
141 }
142 }
143
144 newList.sublist("maxwell1: 22list").set("smoother: type", "none");
145 newList.sublist("maxwell1: 22list").set("coarse: type", "none");
146
147 newList.set("maxwell1: nodal smoother fix zero diagonal threshold",1e-10);
148 newList.sublist("maxwell1: 22list").set("rap: fix zero diagonals", true);
149 newList.sublist("maxwell1: 22list").set("rap: fix zero diagonals threshold",1e-10);
150
151
152 list = newList;
153 }
154 std::string mode_string = list.get("maxwell1: mode", MasterList::getDefault<std::string>("maxwell1: mode"));
155 applyBCsTo22_ = list.get("maxwell1: apply BCs to 22", false);
156 dump_matrices_ = list.get("maxwell1: dump matrices", MasterList::getDefault<bool>("maxwell1: dump matrices"));
157
158 // Default smoother. We'll copy this around.
159 Teuchos::ParameterList defaultSmootherList;
160 defaultSmootherList.set("smoother: type", "CHEBYSHEV");
161 defaultSmootherList.sublist("smoother: params").set("chebyshev: degree",2);
162 defaultSmootherList.sublist("smoother: params").set("chebyshev: ratio eigenvalue",7.0);
163 defaultSmootherList.sublist("smoother: params").set("chebyshev: eigenvalue max iterations",30);
164
165 // Make sure verbosity gets passed to the sublists
166 std::string verbosity = list.get("verbosity","high");
168
169 // Check the validity of the run mode
171 if(mode_string == "standard") mode_ = MODE_STANDARD;
172 else if(mode_string == "refmaxwell") mode_ = MODE_REFMAXWELL;
173 else if(mode_string == "edge only") mode_ = MODE_EDGE_ONLY;
174 else {
175 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Must use mode 'standard', 'refmaxwell', 'edge only', or use the GMHD constructor.");
176 }
177 }
178
179 // If we're in edge only or standard modes, then the (2,2) hierarchy gets built without smoothers.
180 // Otherwise we use the user's smoothers (defaulting to Chebyshev if unspecified)
181 if(list.isSublist("maxwell1: 22list"))
182 precList22_ = list.sublist("maxwell1: 22list");
183 else if(list.isSublist("refmaxwell: 22list"))
184 precList22_ = list.sublist("refmaxwell: 22list");
186 precList22_.set("smoother: pre or post","none");
187 else if(!precList22_.isType<std::string>("Preconditioner Type") &&
188 !precList22_.isType<std::string>("smoother: type") &&
189 !precList22_.isType<std::string>("smoother: pre type") &&
190 !precList22_.isType<std::string>("smoother: post type")) {
191 precList22_ = defaultSmootherList;
192 }
193 precList22_.set("verbosity",precList22_.get("verbosity",verbosity));
194
195
196
197 // For the (1,1) hierarchy we'll use Hiptmair (STANDARD) or Chebyshev (EDGE_ONLY / REFMAXWELL) if
198 // the user doesn't specify things
199 if(list.isSublist("maxwell1: 11list"))
200 precList11_ = list.sublist("maxwell1: 11list");
201 else if(list.isSublist("refmaxwell: 11list"))
202 precList11_ = list.sublist("refmaxwell: 11list");
203
205 precList11_.set("smoother: pre or post","none");
206 precList11_.set("smoother: type", "none");
207 }
208 if(!precList11_.isType<std::string>("Preconditioner Type") &&
209 !precList11_.isType<std::string>("smoother: type") &&
210 !precList11_.isType<std::string>("smoother: pre type") &&
211 !precList11_.isType<std::string>("smoother: post type")) {
213 precList11_ = defaultSmootherList;
214 }
215 if (mode_ == MODE_STANDARD) {
216 precList11_.set("smoother: type", "HIPTMAIR");
217 precList11_.sublist("hiptmair: smoother type 1","CHEBYSHEV");
218 precList11_.sublist("hiptmair: smoother type 2","CHEBYSHEV");
219 precList11_.sublist("hiptmair: smoother list 1") = defaultSmootherList;
220 precList11_.sublist("hiptmair: smoother list 2") = defaultSmootherList;
221 }
222 }
223 precList11_.set("verbosity",precList11_.get("verbosity",verbosity));
224
225 // Reuse support
226 if (enable_reuse_ &&
227 !precList11_.isType<std::string>("Preconditioner Type") &&
228 !precList11_.isParameter("reuse: type"))
229 precList11_.set("reuse: type", "full");
230 if (enable_reuse_ &&
231 !precList22_.isType<std::string>("Preconditioner Type") &&
232 !precList22_.isParameter("reuse: type"))
233 precList22_.set("reuse: type", "full");
234
235
236 // Are we using Kokkos?
237# ifdef HAVE_MUELU_SERIAL
238 if (typeid(Node).name() == typeid(Tpetra::KokkosCompat::KokkosSerialWrapperNode).name())
239 useKokkos_ = false;
240# endif
241# ifdef HAVE_MUELU_OPENMP
242 if (typeid(Node).name() == typeid(Tpetra::KokkosCompat::KokkosOpenMPWrapperNode).name())
243 useKokkos_ = true;
244# endif
245# ifdef HAVE_MUELU_CUDA
246 if (typeid(Node).name() == typeid(Tpetra::KokkosCompat::KokkosCudaWrapperNode).name())
247 useKokkos_ = true;
248# endif
249 useKokkos_ = list.get("use kokkos refactor",useKokkos_);
250
251 parameterList_ = list;
252
253 }
254
255 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
257 Teuchos::ParameterList precListGmhd;
258
260
261 HierarchyGmhd_->GetLevel(0)->Set("A", GmhdA_Matrix_);
262 GmhdA_Matrix_->setObjectLabel("GmhdA");
263
264 TEUCHOS_TEST_FOR_EXCEPTION( !List.isSublist("maxwell1: Gmhdlist"), Exceptions::RuntimeError, "Must provide maxwell1: Gmhdlist for GMHD setup");
265 precListGmhd = List.sublist("maxwell1: Gmhdlist");
266 precListGmhd.set("coarse: max size",1);
267 precListGmhd.set("max levels",HierarchyGmhd_->GetNumLevels());
268 RCP<MueLu::HierarchyManager<SC,LO,GO,NO> > mueLuFactory = rcp(new MueLu::ParameterListInterpreter<SC,LO,GO,NO>(precListGmhd,GmhdA_Matrix_->getDomainMap()->getComm()));
269 HierarchyGmhd_->setlib(GmhdA_Matrix_->getDomainMap()->lib());
270 HierarchyGmhd_->SetProcRankVerbose(GmhdA_Matrix_->getDomainMap()->getComm()->getRank());
271 mueLuFactory->SetupHierarchy(*HierarchyGmhd_);
272 }
273
274 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
276 /* Algorithm overview for Maxwell1 construction:
277
278 1) Create a nodal auxillary hierarchy based on (a) the user's nodal matrix or (b) a matrix constructed
279 by D0^T A D0 if the user doesn't provide a nodal matrix. We call this matrix "NodeAggMatrix."
280
281 2) If the user provided a node matrix, we use the prolongators from the auxillary nodal hierarchy
282 to generate matrices for smoothers on all levels. We call this "NodeMatrix." Otherwise NodeMatrix = NodeAggMatrix
283
284 3) We stick all of the nodal P matrices and NodeMatrix objects on the final (1,1) hierarchy and then use the
285 ReitzingerPFactory to generate the edge P and A matrices.
286 */
287
288
289#ifdef HAVE_MUELU_CUDA
290 if (parameterList_.get<bool>("maxwell1: cuda profile setup", false)) cudaProfilerStart();
291#endif
292
293 std::string timerLabel;
294 if (reuse)
295 timerLabel = "MueLu Maxwell1: compute (reuse)";
296 else
297 timerLabel = "MueLu Maxwell1: compute";
298 RCP<Teuchos::TimeMonitor> tmCompute = getTimer(timerLabel);
299
301 // Generate Kn and apply BCs (if needed)
302 bool have_generated_Kn = false;
303 if(Kn_Matrix_.is_null()) {
304 // generate_kn() will do diagonal repair if requested
305 GetOStream(Runtime0) << "Maxwell1::compute(): Kn not provided. Generating." << std::endl;
307 have_generated_Kn = true;
308 }
309 else if (parameterList_.get<bool>("rap: fix zero diagonals", true)) {
310 magnitudeType threshold;
311 if (parameterList_.isType<magnitudeType>("rap: fix zero diagonals threshold"))
312 threshold = parameterList_.get<magnitudeType>("rap: fix zero diagonals threshold",
313 Teuchos::ScalarTraits<double>::eps());
314 else
315 threshold = Teuchos::as<magnitudeType>(parameterList_.get<double>("rap: fix zero diagonals threshold",
316 Teuchos::ScalarTraits<double>::eps()));
317 Scalar replacement = Teuchos::as<Scalar>(parameterList_.get<double>("rap: fix zero diagonals replacement",
318 MasterList::getDefault<double>("rap: fix zero diagonals replacement")));
319 Xpetra::MatrixUtils<SC,LO,GO,NO>::CheckRepairMainDiagonal(Kn_Matrix_, true, GetOStream(Warnings1), threshold, replacement);
320 }
321
322
324 // Generate the (2,2) Hierarchy
325 Kn_Matrix_->setObjectLabel("Maxwell1 (2,2)");
326
327 /* Critical ParameterList changes */
328 if (!Coords_.is_null())
329 precList22_.sublist("user data").set("Coordinates",Coords_);
330
331 /* Repartitioning *must* be in sync between hierarchies, but the
332 only thing we need to watch here is the subcomms, since ReitzingerPFactory
333 won't look at all the other stuff */
334 if(precList22_.isParameter("repartition: enable")) {
335 bool repartition = precList22_.get<bool>("repartition: enable");
336 precList11_.set("repartition: enable",repartition);
337
338 // If we're repartitioning (2,2), we need to rebalance for (1,1) to do the right thing
339 if(repartition)
340 precList22_.set("repartition: rebalance P and R",true);
341
342 if (precList22_.isParameter("repartition: use subcommunicators")) {
343 precList11_.set("repartition: use subcommunicators", precList22_.get<bool>("repartition: use subcommunicators"));
344
345 // We do not want (1,1) and (2,2) blocks being repartitioned seperately, so we specify the map that
346 // is going to be used (this is generated in ReitzingerPFactory)
347 if(precList11_.get<bool>("repartition: use subcommunicators")==true)
348 precList11_.set("repartition: use subcommunicators in place",true);
349 }
350 else {
351 // We'll have Maxwell1 default to using subcommunicators if you don't specify
352 precList11_.set("repartition: use subcommunicators", true);
353 precList22_.set("repartition: use subcommunicators", true);
354
355 // We do not want (1,1) and (2,2) blocks being repartitioned seperately, so we specify the map that
356 // is going to be used (this is generated in ReitzingerPFactory)
357 precList11_.set("repartition: use subcommunicators in place",true);
358 }
359
360 }
361 else
362 precList11_.remove("repartition: enable", false);
363
364
366 // Remove explicit zeros from matrices
367 /*
368 Maxwell_Utils<SC,LO,GO,NO>::removeExplicitZeros(parameterList_,D0_Matrix_,SM_Matrix_);
369
370
371 if (IsPrint(Statistics2)) {
372 RCP<ParameterList> params = rcp(new ParameterList());;
373 params->set("printLoadBalancingInfo", true);
374 params->set("printCommInfo", true);
375 GetOStream(Statistics2) << PerfUtils::PrintMatrixInfo(*SM_Matrix_, "SM_Matrix", params);
376 }
377 */
378
379
381 // Detect Dirichlet boundary conditions
382 if (!reuse) {
383 magnitudeType rowSumTol = precList11_.get("aggregation: row sum drop tol",-1.0);
388 if (IsPrint(Statistics2)) {
389 GetOStream(Statistics2) << "MueLu::Maxwell1::compute(): Detected " << BCedges_ << " BC rows and " << BCnodes_ << " BC columns." << std::endl;
390 }
391 }
392
393 if (allEdgesBoundary_) {
394 // All edges have been detected as boundary edges.
395 // Do not attempt to construct sub-hierarchies, but just set up a single level preconditioner.
396 GetOStream(Warnings0) << "All edges are detected as boundary edges!" << std::endl;
398
399 // Generate single level hierarchy for the edge
400 precList22_.set("max levels", 1);
401 }
402
403
404 if (allNodesBoundary_) {
405 // All Nodes have been detected as boundary nodes.
406 // Do not attempt to construct sub-hierarchies, but just set up a single level preconditioner.
407 GetOStream(Warnings0) << "All nodes are detected as boundary nodes!" << std::endl;
409
410 // Generate single level hierarchy for the edge
411 precList22_.set("max levels", 1);
412 }
413
415 // Build (2,2) hierarchy
417
418
420 // Apply boundary conditions to D0 (if needed)
421 if(!reuse) {
422 D0_Matrix_->resumeFill();
423 Scalar replaceWith;
424 if (D0_Matrix_->getRowMap()->lib() == Xpetra::UseEpetra)
425 replaceWith= Teuchos::ScalarTraits<SC>::eps();
426 else
427 replaceWith = Teuchos::ScalarTraits<SC>::zero();
428
429 if(applyBCsTo22_) {
430 GetOStream(Runtime0) << "Maxwell1::compute(): nuking BC rows/cols of D0" << std::endl;
431 if (useKokkos_) {
433 } else {
435 }
436 }
437 else {
438 GetOStream(Runtime0) << "Maxwell1::compute(): nuking BC rows of D0" << std::endl;
439 if (useKokkos_) {
441 } else {
443 }
444 }
445
446 D0_Matrix_->fillComplete(D0_Matrix_->getDomainMap(),D0_Matrix_->getRangeMap());
447 }
448
449
451 // What ML does is generate nodal prolongators with an auxillary hierarchy based on the
452 // user's (2,2) matrix. The actual nodal matrices for smoothing are generated by the
453 // Hiptmair smoother construction. We're not going to do that --- we'll
454 // do as we insert them into the final (1,1) hierarchy.
455
456 // Level 0
457 RCP<Matrix> Kn_Smoother_0;
458 if(have_generated_Kn) {
459 Kn_Smoother_0 = Kn_Matrix_;
460 }
461 else {
462 Kn_Smoother_0 = generate_kn();
463 }
464
466 // Copy the relevant (2,2) data to the (1,1) hierarchy
467 Hierarchy11_ = rcp(new Hierarchy("Maxwell1 (1,1)"));
468 RCP<Matrix> OldSmootherMatrix;
469 RCP<Level> OldEdgeLevel;
470 for(int i=0; i<Hierarchy22_->GetNumLevels(); i++) {
471 Hierarchy11_->AddNewLevel();
472 RCP<Level> NodeL = Hierarchy22_->GetLevel(i);
473 RCP<Level> EdgeL = Hierarchy11_->GetLevel(i);
474 RCP<Operator> NodeOp = NodeL->Get<RCP<Operator> >("A");
475 RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(NodeOp);
476 std::string labelstr = FormattingHelper::getColonLabel(EdgeL->getObjectLabel());
477
478 if(i==0) {
479 EdgeL->Set("A", SM_Matrix_);
480 EdgeL->Set("D0", D0_Matrix_);
481
482 EdgeL->Set("NodeAggMatrix",NodeAggMatrix);
483 EdgeL->Set("NodeMatrix",Kn_Smoother_0);
484 OldSmootherMatrix = Kn_Smoother_0;
485 OldEdgeLevel = EdgeL;
486 }
487 else {
488 // Set the Nodal P
489 // NOTE: ML uses normalized prolongators for the aggregation hierarchy
490 // and then prolongators of all 1's for doing the Reitzinger prolongator
491 // generation for the edge hierarchy.
492 auto NodalP = NodeL->Get<RCP<Matrix> >("P");
493 auto NodalP_ones = Utilities::ReplaceNonZerosWithOnes(NodalP);
494 TEUCHOS_TEST_FOR_EXCEPTION(NodalP_ones.is_null(), Exceptions::RuntimeError, "Applying ones to prolongator failed");
495 EdgeL->Set("Pnodal",NodalP_ones);
496
497 // If we repartition a processor away, a RCP<Operator> is stuck
498 // on the level instead of an RCP<Matrix>
499 if(!NodeAggMatrix.is_null()) {
500 EdgeL->Set("NodeAggMatrix",NodeAggMatrix);
501 if(!have_generated_Kn) {
502 // The user gave us a Kn on the fine level, so we're using a seperate aggregation
503 // hierarchy from the smoothing hierarchy.
504
505 // ML does a *fixed* 1e-10 diagonal repair on the Nodal Smoothing Matrix
506 // This fix is applied *after* the next level is generated, but before the smoother is.
507 // We can see this behavior from ML, though it isn't 100% clear from the code *how* it happens.
508 // So, here we turn the fix off, then once we've generated the new matrix, we fix the old one.
509
510 // Generate the new matrix
511 Teuchos::ParameterList RAPlist;
512 RAPlist.set("rap: fix zero diagonals", false);
513 RCP<Matrix> NewKn = Maxwell_Utils<SC,LO,GO,NO>::PtAPWrapper(OldSmootherMatrix,NodalP_ones,RAPlist,labelstr);
514 EdgeL->Set("NodeMatrix",NewKn);
515
516 // Fix the old one
517 double thresh = parameterList_.get("maxwell1: nodal smoother fix zero diagonal threshold",1e-10);
518 if(thresh > 0.0) {
519 printf("CMS: Reparing diagonal after next level generation\n");
520 Scalar replacement = Teuchos::ScalarTraits<Scalar>::one();
521 Xpetra::MatrixUtils<SC,LO,GO,NO>::CheckRepairMainDiagonal(OldSmootherMatrix, true, GetOStream(Warnings1), thresh, replacement);
522 }
523 OldEdgeLevel->Set("NodeMatrix",OldSmootherMatrix);
524
525 OldSmootherMatrix = NewKn;
526 }
527 else {
528 // The user didn't give us a Kn, so we aggregate and smooth with the same matrix
529 EdgeL->Set("NodeMatrix",NodeAggMatrix);
530 }
531 }
532 else {
533 // We've partitioned things away.
534 EdgeL->Set("NodeMatrix",NodeOp);
535 EdgeL->Set("NodeAggMatrix",NodeOp);
536 }
537
538 OldEdgeLevel = EdgeL;
539 }
540
541 // Get the importer if we have one (for repartitioning)
542 // This will get used in ReitzingerPFactory
543 if(NodeL->IsAvailable("Importer")) {
544 auto importer = NodeL->Get<RCP<const Import> >("Importer");
545 EdgeL->Set("NodeImporter",importer);
546 }
547 }// end Hierarchy22 loop
548
549
551 // Generating the (1,1) Hierarchy
552 std::string fine_smoother = precList11_.get<std::string>("smoother: type");
553 {
554 SM_Matrix_->setObjectLabel("A(1,1)");
555 precList11_.set("coarse: max size",1);
556 precList11_.set("max levels",Hierarchy22_->GetNumLevels());
557
558 const bool refmaxwellCoarseSolve = (precList11_.get<std::string>("coarse: type",
559 MasterList::getDefault<std::string>("coarse: type")) == "RefMaxwell");
560 if (refmaxwellCoarseSolve) {
561 GetOStream(Runtime0) << "Maxwell1::compute(): Will set up RefMaxwell coarse solver" << std::endl;
562 precList11_.set("coarse: type", "none");
563 }
564
565 // Rip off non-serializable data before validation
566 Teuchos::ParameterList nonSerialList11, processedPrecList11;
567 MueLu::ExtractNonSerializableData(precList11_, processedPrecList11, nonSerialList11);
568 RCP<HierarchyManager<SC,LO,GO,NO> > mueLuFactory = rcp(new ParameterListInterpreter<SC,LO,GO,NO>(processedPrecList11,SM_Matrix_->getDomainMap()->getComm()));
569 Hierarchy11_->setlib(SM_Matrix_->getDomainMap()->lib());
570 Hierarchy11_->SetProcRankVerbose(SM_Matrix_->getDomainMap()->getComm()->getRank());
571 // Stick the non-serializible data on the hierarchy.
573 mueLuFactory->SetupHierarchy(*Hierarchy11_);
574
575 if (refmaxwellCoarseSolve) {
576 GetOStream(Runtime0) << "Maxwell1::compute(): Setting up RefMaxwell coarse solver" << std::endl;
577 auto coarseLvl = Hierarchy11_->GetLevel(Hierarchy11_->GetNumLevels()-1);
578 auto coarseSolver = rcp(new MueLu::RefMaxwellSmoother<Scalar,LocalOrdinal,GlobalOrdinal,Node>("RefMaxwell",
579 precList11_.sublist("coarse: params")));
580 coarseSolver->Setup(*coarseLvl);
581 coarseLvl->Set("PreSmoother",
582 rcp_dynamic_cast<SmootherBase>(coarseSolver, true));
583 }
584
585 if(mode_ == MODE_REFMAXWELL) {
586 if(Hierarchy11_->GetNumLevels() > 1) {
587 RCP<Level> EdgeL = Hierarchy11_->GetLevel(1);
588 P11_ = EdgeL->Get<RCP<Matrix> >("P");
589 }
590 }
591 }
592
594 // Allocate temporary MultiVectors for solve (only needed for RefMaxwell style)
596
598
599
600#ifdef MUELU_MAXWELL1_DEBUG
601 for(int i=0; i<Hierarchy11_->GetNumLevels(); i++) {
602 RCP<Level> L = Hierarchy11_->GetLevel(i);
603 RCP<Matrix> EdgeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("A"));
604 RCP<Matrix> NodeMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("NodeMatrix"));
605 RCP<Matrix> NodeAggMatrix = rcp_dynamic_cast<Matrix>(L->Get<RCP<Operator> >("NodeAggMatrix"));
606 RCP<Matrix> D0 =rcp_dynamic_cast<Matrix>( L->Get<RCP<Operator> >("D0"));
607
608 auto nrmE = EdgeMatrix->getFrobeniusNorm();
609 auto nrmN = NodeMatrix->getFrobeniusNorm();
610 auto nrmNa = NodeAggMatrix->getFrobeniusNorm();
611 auto nrmD0= D0->getFrobeniusNorm();
612
613 std::cout<<"DEBUG: Norms on Level "<<i<<" E/N/NA/D0 = "<<nrmE<<" / "<<nrmN <<" / "<<nrmNa<<" / "<< nrmD0 <<std::endl;
614 std::cout<<"DEBUG: NNZ on Level "<<i<<" E/N/NA/D0 = "<<
615 EdgeMatrix->getGlobalNumEntries()<<" / "<<
616 NodeMatrix->getGlobalNumEntries()<<" / "<<
617 NodeAggMatrix->getGlobalNumEntries()<<" / "<<
618 D0->getGlobalNumEntries()<<std::endl;
619 }
620#endif
621
622 }
623
624
625 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
626 RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::generate_kn() const {
627
628 // This is important, as we'll be doing diagonal repair *after* the next-level matrix is generated, not before
629 Teuchos::ParameterList RAPlist;
630 RAPlist.set("rap: fix zero diagonals", false);
631
632 std::string labelstr = "NodeMatrix (Level 0)";
633 RCP<Matrix> rv = Maxwell_Utils<SC,LO,GO,NO>::PtAPWrapper(SM_Matrix_,D0_Matrix_,RAPlist,labelstr);
634 return rv;
635 }
636
637
638
639 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
641 if(mode_ == MODE_REFMAXWELL) {
642 RCP<Teuchos::TimeMonitor> tmAlloc = getTimer("MueLu Maxwell1: Allocate MVs");
643
644 residualFine_ = MultiVectorFactory::Build(SM_Matrix_->getRangeMap(), numVectors);
645
646 if(!Hierarchy11_.is_null() && Hierarchy11_->GetNumLevels() > 1) {
647 RCP<Level> EdgeL = Hierarchy11_->GetLevel(1);
648 RCP<Matrix> A = EdgeL->Get<RCP<Matrix> >("A");
649 residual11c_ = MultiVectorFactory::Build(A->getRangeMap(), numVectors);
650 update11c_ = MultiVectorFactory::Build(A->getDomainMap(), numVectors);
651 }
652
653 if(!Hierarchy22_.is_null()) {
654 residual22_ = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(), numVectors);
655 update22_ = MultiVectorFactory::Build(D0_Matrix_->getDomainMap(), numVectors);
656 }
657
658 }
659
660 }
661
662
663 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
664 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::dump(const Matrix& A, std::string name) const {
665 if (dump_matrices_) {
666 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
667 Xpetra::IO<SC, LO, GO, NO>::Write(name, A);
668 }
669 }
670
671
672 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
673 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::dump(const MultiVector& X, std::string name) const {
674 if (dump_matrices_) {
675 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
676 Xpetra::IO<SC, LO, GO, NO>::Write(name, X);
677 }
678 }
679
680
681 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
683 if (dump_matrices_) {
684 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
685 Xpetra::IO<coordinateType, LO, GO, NO>::Write(name, X);
686 }
687 }
688
689
690 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
691 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::dump(const Teuchos::ArrayRCP<bool>& v, std::string name) const {
692 if (dump_matrices_) {
693 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
694 std::ofstream out(name);
695 for (size_t i = 0; i < Teuchos::as<size_t>(v.size()); i++)
696 out << v[i] << "\n";
697 }
698 }
699
700 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
701 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::dump(const Kokkos::View<bool*, typename Node::device_type>& v, std::string name) const {
702 if (dump_matrices_) {
703 GetOStream(Runtime0) << "Dumping to " << name << std::endl;
704 std::ofstream out(name);
705 auto vH = Kokkos::create_mirror_view (v);
706 Kokkos::deep_copy(vH , v);
707 for (size_t i = 0; i < vH.size(); i++)
708 out << vH[i] << "\n";
709 }
710 }
711
712 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
713 Teuchos::RCP<Teuchos::TimeMonitor> Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getTimer(std::string name, RCP<const Teuchos::Comm<int> > comm) const {
714 if (IsPrint(Timings)) {
715 if (!syncTimers_)
716 return Teuchos::rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name)));
717 else {
718 if (comm.is_null())
719 return Teuchos::rcp(new Teuchos::SyncTimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name), SM_Matrix_->getRowMap()->getComm().ptr()));
720 else
721 return Teuchos::rcp(new Teuchos::SyncTimeMonitor(*Teuchos::TimeMonitor::getNewTimer(name), comm.ptr()));
722 }
723 } else
724 return Teuchos::null;
725 }
726
727
728
729
730 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
731 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::resetMatrix(RCP<Matrix> SM_Matrix_new, bool ComputePrec) {
732 bool reuse = !SM_Matrix_.is_null();
733 SM_Matrix_ = SM_Matrix_new;
734 dump(*SM_Matrix_, "SM.m");
735 if (ComputePrec)
736 compute(reuse);
737 }
738
739
740 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
742 // make sure that we have enough temporary memory
743 const SC one = Teuchos::ScalarTraits<SC>::one();
744 if (!allEdgesBoundary_ && X.getNumVectors() != residualFine_->getNumVectors())
745 allocateMemory(X.getNumVectors());
746
747 TEUCHOS_TEST_FOR_EXCEPTION(Hierarchy11_.is_null() || Hierarchy11_->GetNumLevels() == 0, Exceptions::RuntimeError, "(1,1) Hiearchy is null.");
748
749 // 1) Run fine pre-smoother using Hierarchy11
750 RCP<Level> Fine = Hierarchy11_->GetLevel(0);
751 if (Fine->IsAvailable("PreSmoother")) {
752 RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: PreSmoother");
753 RCP<SmootherBase> preSmoo = Fine->Get< RCP<SmootherBase> >("PreSmoother");
754 preSmoo->Apply(X, RHS, true);
755 }
756
757 // 2) Compute residual
758 {
759 RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: residual calculation");
761 }
762
763 // 3a) Restrict residual to (1,1) Hierarchy's level 1 and execute (1,1) hierarchy (use startLevel and InitialGuessIsZero)
764 if(!P11_.is_null()) {
765 RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: (1,1) correction");
766 P11_->apply(*residualFine_,*residual11c_,Teuchos::TRANS);
767 Hierarchy11_->Iterate(*residual11c_,*update11c_,true,1);
768 }
769
770 // 3b) Restrict residual to (2,2) Hierarchy's level 0 and execute (2,2) hierarchy (use InitialGuessIsZero)
771 if (!allNodesBoundary_) {
772 RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: (2,2) correction");
773 D0_Matrix_->apply(*residualFine_,*residual22_,Teuchos::TRANS);
774 Hierarchy22_->Iterate(*residual22_,*update22_,true,0);
775 }
776
777 // 4) Prolong both updates back into X-vector (Need to do both the P11 null and not null cases
778 {
779 RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: Orolongation");
780 if(!P11_.is_null())
781 P11_->apply(*update11c_,X,Teuchos::NO_TRANS,one,one);
783 D0_Matrix_->apply(*update22_,X,Teuchos::NO_TRANS,one,one);
784 }
785
786 // 5) Run fine post-smoother using Hierarchy11
787 if (Fine->IsAvailable("PostSmoother")) {
788 RCP<Teuchos::TimeMonitor> tmRes = getTimer("MueLu Maxwell1: PostSmoother");
789 RCP<SmootherBase> postSmoo = Fine->Get< RCP<SmootherBase> >("PostSmoother");
790 postSmoo->Apply(X, RHS, false);
791 }
792
793
794 }
795
796 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
797 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::applyInverseStandard(const MultiVector& RHS, MultiVector& X) const {
798 Hierarchy11_->Iterate(RHS,X,1,true);
799 }
800
801 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
802 void Maxwell1<Scalar,LocalOrdinal,GlobalOrdinal,Node>::apply (const MultiVector& RHS, MultiVector& X,
803 Teuchos::ETransp /* mode */,
804 Scalar /* alpha */,
805 Scalar /* beta */) const {
806 RCP<Teuchos::TimeMonitor> tm = getTimer("MueLu Maxwell1: solve");
808 HierarchyGmhd_->Iterate(RHS,X,1,true);
809 else if(mode_ == MODE_STANDARD || mode_ == MODE_EDGE_ONLY)
811 else if(mode_ == MODE_REFMAXWELL)
813 else
814 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "Must use mode 'standard', 'refmaxwell' or 'edge only' when not doing GMHD.");
815 }
816
817
818
819 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
823
824
825 template<class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
827 initialize(const Teuchos::RCP<Matrix> & D0_Matrix,
828 const Teuchos::RCP<Matrix> & Kn_Matrix,
829 const Teuchos::RCP<MultiVector> & Nullspace,
830 const Teuchos::RCP<RealValuedMultiVector> & Coords,
831 Teuchos::ParameterList& List)
832 {
833 // some pre-conditions
834 TEUCHOS_ASSERT(D0_Matrix!=Teuchos::null);
835
836#ifdef HAVE_MUELU_DEBUG
837 if(!Kn_Matrix.is_null()) {
838 TEUCHOS_ASSERT(Kn_Matrix->getDomainMap()->isSameAs(*D0_Matrix->getDomainMap()));
839 TEUCHOS_ASSERT(Kn_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getDomainMap()));
840 }
841
842
843 TEUCHOS_ASSERT(D0_Matrix->getRangeMap()->isSameAs(*D0_Matrix->getRowMap()));
844#endif
845
846 Hierarchy11_ = Teuchos::null;
847 Hierarchy22_ = Teuchos::null;
848 HierarchyGmhd_ = Teuchos::null;
850
851 // Default settings
852 useKokkos_=false;
853 allEdgesBoundary_=false;
854 allNodesBoundary_=false;
855 dump_matrices_ = false;
856 enable_reuse_=false;
857 syncTimers_=false;
858 applyBCsTo22_ = false;
859
860
861 // set parameters
862 setParameters(List);
863
864 if (D0_Matrix->getRowMap()->lib() == Xpetra::UseTpetra) {
865 // We will remove boundary conditions from D0, and potentially change maps, so we copy the input.
866 // Fortunately, D0 is quite sparse.
867 // We cannot use the Tpetra copy constructor, since it does not copy the graph.
868
869 RCP<Matrix> D0copy = MatrixFactory::Build(D0_Matrix->getRowMap(), D0_Matrix->getColMap(), 0);
870 RCP<CrsMatrix> D0copyCrs = rcp_dynamic_cast<CrsMatrixWrap>(D0copy,true)->getCrsMatrix();
871 ArrayRCP<const size_t> D0rowptr_RCP;
872 ArrayRCP<const LO> D0colind_RCP;
873 ArrayRCP<const SC> D0vals_RCP;
874 rcp_dynamic_cast<CrsMatrixWrap>(D0_Matrix,true)->getCrsMatrix()->getAllValues(D0rowptr_RCP,
875 D0colind_RCP,
876 D0vals_RCP);
877
878 ArrayRCP<size_t> D0copyrowptr_RCP;
879 ArrayRCP<LO> D0copycolind_RCP;
880 ArrayRCP<SC> D0copyvals_RCP;
881 D0copyCrs->allocateAllValues(D0vals_RCP.size(),D0copyrowptr_RCP,D0copycolind_RCP,D0copyvals_RCP);
882 D0copyrowptr_RCP.deepCopy(D0rowptr_RCP());
883 D0copycolind_RCP.deepCopy(D0colind_RCP());
884 D0copyvals_RCP.deepCopy(D0vals_RCP());
885 D0copyCrs->setAllValues(D0copyrowptr_RCP,
886 D0copycolind_RCP,
887 D0copyvals_RCP);
888 D0copyCrs->expertStaticFillComplete(D0_Matrix->getDomainMap(), D0_Matrix->getRangeMap(),
889 rcp_dynamic_cast<CrsMatrixWrap>(D0_Matrix,true)->getCrsMatrix()->getCrsGraph()->getImporter(),
890 rcp_dynamic_cast<CrsMatrixWrap>(D0_Matrix,true)->getCrsMatrix()->getCrsGraph()->getExporter());
891 D0_Matrix_ = D0copy;
892 } else
893 D0_Matrix_ = MatrixFactory::BuildCopy(D0_Matrix);
894
895
896 Kn_Matrix_ = Kn_Matrix;
897 Coords_ = Coords;
898 Nullspace_ = Nullspace;
899
900 if(!Kn_Matrix_.is_null()) dump(*Kn_Matrix_, "Kn.m");
901 if (!Nullspace_.is_null()) dump(*Nullspace_, "nullspace.m");
902 if (!Coords_.is_null()) dumpCoords(*Coords_, "coords.m");
903
904 }
905
906
907
908 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
910 describe(Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel /* verbLevel */) const {
911
912 std::ostringstream oss;
913
914 RCP<const Teuchos::Comm<int> > comm = SM_Matrix_->getDomainMap()->getComm();
915
916#ifdef HAVE_MPI
917 int root;
918 if (!Kn_Matrix_.is_null())
919 root = comm->getRank();
920 else
921 root = -1;
922
923 int actualRoot;
924 reduceAll(*comm, Teuchos::REDUCE_MAX, root, Teuchos::ptr(&actualRoot));
925 root = actualRoot;
926#endif
927
928
929 oss << "\n--------------------------------------------------------------------------------\n" <<
930 "--- Maxwell1 Summary ---\n"
931 "--------------------------------------------------------------------------------" << std::endl;
932 oss << std::endl;
933
934 GlobalOrdinal numRows;
935 GlobalOrdinal nnz;
936
937 SM_Matrix_->getRowMap()->getComm()->barrier();
938
939 numRows = SM_Matrix_->getGlobalNumRows();
940 nnz = SM_Matrix_->getGlobalNumEntries();
941
942 Xpetra::global_size_t tt = numRows;
943 int rowspacer = 3; while (tt != 0) { tt /= 10; rowspacer++; }
944 tt = nnz;
945 int nnzspacer = 2; while (tt != 0) { tt /= 10; nnzspacer++; }
946
947 oss << "block " << std::setw(rowspacer) << " rows " << std::setw(nnzspacer) << " nnz " << std::setw(9) << " nnz/row" << std::endl;
948 oss << "(1, 1)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
949
950 if (!Kn_Matrix_.is_null()) {
951 // ToDo: make sure that this is printed correctly
952 numRows = Kn_Matrix_->getGlobalNumRows();
953 nnz = Kn_Matrix_->getGlobalNumEntries();
954
955 oss << "(2, 2)" << std::setw(rowspacer) << numRows << std::setw(nnzspacer) << nnz << std::setw(9) << as<double>(nnz) / numRows << std::endl;
956 }
957
958 oss << std::endl;
959
960
961 std::string outstr = oss.str();
962
963#ifdef HAVE_MPI
964 RCP<const Teuchos::MpiComm<int> > mpiComm = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm);
965 MPI_Comm rawComm = (*mpiComm->getRawMpiComm())();
966
967 int strLength = outstr.size();
968 MPI_Bcast(&strLength, 1, MPI_INT, root, rawComm);
969 if (comm->getRank() != root)
970 outstr.resize(strLength);
971 MPI_Bcast(&outstr[0], strLength, MPI_CHAR, root, rawComm);
972#endif
973
974 out << outstr;
975
976 if (!Hierarchy11_.is_null())
977 Hierarchy11_->describe(out, GetVerbLevel());
978
979 if (!Hierarchy22_.is_null())
980 Hierarchy22_->describe(out, GetVerbLevel());
981
982 if (!HierarchyGmhd_.is_null())
983 HierarchyGmhd_->describe(out, GetVerbLevel());
984
985 if (IsPrint(Statistics2)) {
986 // Print the grid of processors
987 std::ostringstream oss2;
988
989 oss2 << "Sub-solver distribution over ranks" << std::endl;
990 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;
991
992 int numProcs = comm->getSize();
993#ifdef HAVE_MPI
994 RCP<const Teuchos::MpiComm<int> > tmpic = rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm);
995
996 RCP<const Teuchos::OpaqueWrapper<MPI_Comm> > rawMpiComm = tmpic->getRawMpiComm();
997#endif
998
999 char status = 0;
1000 if (!Kn_Matrix_.is_null())
1001 status += 1;
1002 std::vector<char> states(numProcs, 0);
1003#ifdef HAVE_MPI
1004 MPI_Gather(&status, 1, MPI_CHAR, &states[0], 1, MPI_CHAR, 0, *rawMpiComm);
1005#else
1006 states.push_back(status);
1007#endif
1008
1009 int rowWidth = std::min(Teuchos::as<int>(ceil(sqrt(numProcs))), 100);
1010 for (int proc = 0; proc < numProcs; proc += rowWidth) {
1011 for (int j = 0; j < rowWidth; j++)
1012 if (proc + j < numProcs)
1013 if (states[proc+j] == 0)
1014 oss2 << ".";
1015 else if (states[proc+j] == 1)
1016 oss2 << "1";
1017 else if (states[proc+j] == 2)
1018 oss2 << "2";
1019 else
1020 oss2 << "B";
1021 else
1022 oss2 << " ";
1023
1024 oss2 << " " << proc << ":" << std::min(proc + rowWidth, numProcs) - 1 << std::endl;
1025 }
1026 oss2 << std::endl;
1027 GetOStream(Statistics2) << oss2.str();
1028 }
1029
1030
1031 }
1032
1033
1034
1035} // namespace
1036
1037#define MUELU_MAXWELL1_SHORT
1038#endif //ifdef MUELU_MAXWELL1_DEF_HPP
Various adapters that will create a MueLu preconditioner that is an Xpetra::Matrix.
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
MueLu::DefaultNode Node
Exception throws to report errors in the internal logical of the program.
static void AddNonSerializableDataToHierarchy(HierarchyManager &HM, Hierarchy &H, const ParameterList &nonSerialList)
Add non-serializable data to Hierarchy.
static void CopyBetweenHierarchies(Hierarchy &fromHierarchy, Hierarchy &toHierarchy, const std::string fromLabel, const std::string toLabel, const std::string dataType)
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
static std::string translate(Teuchos::ParameterList &paramList, const std::string &defaultVals="")
: Translate ML parameters to MueLu parameter XML string
static const T & getDefault(const std::string &name)
Returns default value on the "master" list for a parameter with the specified name and type.
Xpetra::MultiVector< coordinateType, LO, GO, NO > RealValuedMultiVector
bool useKokkos_
Some options.
Teuchos::RCP< Matrix > generate_kn() const
Generates the Kn matrix.
Teuchos::RCP< Hierarchy > Hierarchy11_
Two hierarchies: one for the (1,1)-block, another for the (2,2)-block.
Teuchos::RCP< Hierarchy > HierarchyGmhd_
Teuchos::RCP< MultiVector > residualFine_
Teuchos::ArrayRCP< bool > BCcols_
Teuchos::ArrayRCP< bool > BCrows_
Teuchos::RCP< Matrix > SM_Matrix_
Various matrices.
Teuchos::RCP< Hierarchy > Hierarchy22_
Teuchos::RCP< const Map > getDomainMap() const
Returns the Xpetra::Map object associated with the domain of this operator.
Teuchos::RCP< const Map > getRangeMap() const
Returns the Xpetra::Map object associated with the range of this operator.
void compute(bool reuse=false)
Setup the preconditioner.
void GMHDSetupHierarchy(Teuchos::ParameterList &List) const
Sets up hiearchy for GMHD matrices that include generalized Ohms law equations.
Teuchos::ParameterList parameterList_
ParameterLists.
Teuchos::RCP< MultiVector > residual22_
Teuchos::RCP< RealValuedMultiVector > Coords_
Coordinates.
Teuchos::RCP< Matrix > D0_Matrix_
Teuchos::ScalarTraits< Scalar >::magnitudeType magnitudeType
void applyInverseRefMaxwellAdditive(const MultiVector &RHS, MultiVector &X) const
apply RefMaxwell additive 2x2 style cycle
Teuchos::RCP< MultiVector > Nullspace_
Nullspace.
Kokkos::View< bool *, typename Node::device_type > BCdomainKokkos_
Teuchos::RCP< MultiVector > update11c_
Kokkos::View< bool *, typename Node::device_type > BCcolsKokkos_
void applyInverseStandard(const MultiVector &RHS, MultiVector &X) const
apply standard Maxwell1 cycle
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)
RCP< Matrix > P11_
Temporary memory (cached vectors for RefMaxwell-style).
void dumpCoords(const RealValuedMultiVector &X, std::string name) const
dump out real-valued multivector
Teuchos::RCP< MultiVector > update22_
Teuchos::ArrayRCP< bool > BCdomain_
Teuchos::ParameterList precList11_
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::VERB_HIGH) const
Teuchos::RCP< Matrix > GmhdA_Matrix_
void dump(const Matrix &A, std::string name) const
dump out matrix
Teuchos::ParameterList precList22_
void resetMatrix(Teuchos::RCP< Matrix > SM_Matrix_new, bool ComputePrec=true)
Reset system matrix.
Teuchos::RCP< Matrix > Kn_Matrix_
Teuchos::RCP< MultiVector > residual11c_
bool hasTransposeApply() const
Indicates whether this operator supports applying the adjoint operator.
Kokkos::View< bool *, typename Node::device_type > BCrowsKokkos_
Vectors for BCs.
Teuchos::RCP< Teuchos::TimeMonitor > getTimer(std::string name, RCP< const Teuchos::Comm< int > > comm=Teuchos::null) const
get a (synced) timer
void setParameters(Teuchos::ParameterList &list)
Set parameters.
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 allocateMemory(int numVectors) const
allocate multivectors for solve
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 detectBoundaryConditionsSM(RCP< Matrix > &SM_Matrix, RCP< Matrix > &D0_Matrix, magnitudeType rowSumTol, bool useKokkos_, Kokkos::View< bool *, typename Node::device_type > &BCrowsKokkos, Kokkos::View< bool *, typename Node::device_type > &BCcolsKokkos, Kokkos::View< bool *, typename Node::device_type > &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.
Class that encapsulates Operator smoothers.
static void ZeroDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > &A, const std::vector< DefaultLocalOrdinal > &dirichletRows, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static void ZeroDirichletCols(Teuchos::RCP< Matrix > &A, const Teuchos::ArrayRCP< const bool > &dirichletCols, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static RCP< Xpetra::Matrix< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > > ReplaceNonZerosWithOnes(const RCP< Matrix > &original)
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, DefaultLocalOrdinal, DefaultGlobalOrdinal, DefaultNode > &Op, const MultiVector &X, const MultiVector &RHS)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
VerbLevel GetVerbLevel() const
Get the verbosity level.
bool IsPrint(MsgType type, int thisProcRankOnly=-1) const
Find out whether we need to print out information for a specific message type.
static void SetDefaultVerbLevel(const VerbLevel defaultVerbLevel)
Set the default (global) verbosity level.
Namespace for MueLu classes and methods.
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.
@ Warnings0
Important warning messages (one line).
@ Statistics2
Print even more statistics.
@ Runtime0
One-liner description of what is happening.
@ Warnings1
Additional warnings.
@ Timings
Print all timing information.
MsgType toVerbLevel(const std::string &verbLevelStr)
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,...
static std::string getColonLabel(const std::string &label)
Helper function for object label.