MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_PgPFactory_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_PGPFACTORY_DEF_HPP
47 #define MUELU_PGPFACTORY_DEF_HPP
48 
49 #include <vector>
50 
51 #include <Xpetra_Vector.hpp>
52 #include <Xpetra_MultiVectorFactory.hpp>
53 #include <Xpetra_VectorFactory.hpp>
54 #include <Xpetra_Import.hpp>
55 #include <Xpetra_ImportFactory.hpp>
56 #include <Xpetra_Export.hpp>
57 #include <Xpetra_ExportFactory.hpp>
58 #include <Xpetra_Matrix.hpp>
59 #include <Xpetra_MatrixMatrix.hpp>
60 
62 #include "MueLu_Monitor.hpp"
63 #include "MueLu_PerfUtils.hpp"
65 #include "MueLu_Utilities.hpp"
66 
67 namespace MueLu {
68 
69 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
71  RCP<ParameterList> validParamList = rcp(new ParameterList());
72 
73  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A used during the prolongator smoothing process");
74  validParamList->set<RCP<const FactoryBase> >("P", Teuchos::null, "Tentative prolongator factory");
75  validParamList->set<MinimizationNorm>("Minimization norm", DINVANORM, "Norm to be minimized");
76  validParamList->set<bool>("ReUseRowBasedOmegas", false, "Reuse omegas for prolongator for restrictor");
77 
78  return validParamList;
79 }
80 
81 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
83  SetParameter("Minimization norm", ParameterEntry(minnorm)); // revalidate
84 }
85 
86 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
88  const ParameterList& pL = GetParameterList();
89  return pL.get<MueLu::MinimizationNorm>("Minimization norm");
90 }
91 
92 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
94  Input(fineLevel, "A");
95 
96  // Get default tentative prolongator factory
97  // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory.
98  // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere!
99  RCP<const FactoryBase> initialPFact = GetFactory("P");
100  if (initialPFact == Teuchos::null) {
101  initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent");
102  }
103  coarseLevel.DeclareInput("P", initialPFact.get(), this);
104 
105  /* If PgPFactory is reusing the row based damping parameters omega for
106  * restriction, it has to request the data here.
107  * we have the following scenarios:
108  * 1) Reuse omegas:
109  * PgPFactory.DeclareInput for prolongation mode requests A and P0
110  * PgPFactory.DeclareInput for restriction mode requests A, P0 and RowBasedOmega (call triggered by GenericRFactory)
111  * PgPFactory.Build for prolongation mode calculates RowBasedOmega and stores it (as requested)
112  * PgPFactory.Build for restriction mode reuses RowBasedOmega (and Releases the data with the Get call)
113  * 2) do not reuse omegas
114  * PgPFactory.DeclareInput for prolongation mode requests A and P0
115  * PgPFactory.DeclareInput for restriction mode requests A and P0
116  * PgPFactory.Build for prolongation mode calculates RowBasedOmega for prolongation operator
117  * PgPFactory.Build for restriction mode calculates RowBasedOmega for restriction operator
118  */
119  const ParameterList& pL = GetParameterList();
120  bool bReUseRowBasedOmegas = pL.get<bool>("ReUseRowBasedOmegas");
121  if (bReUseRowBasedOmegas == true && restrictionMode_ == true) {
122  coarseLevel.DeclareInput("RowBasedOmega", this, this); // RowBasedOmega is calculated by this PgPFactory and requested by this PgPFactory
123  }
124 }
125 
126 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
128  FactoryMonitor m(*this, "Prolongator smoothing (PG-AMG)", coarseLevel);
129 
130  // Level Get
131  RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
132 
133  // Get default tentative prolongator factory
134  // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory.
135  // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere!
136  RCP<const FactoryBase> initialPFact = GetFactory("P");
137  if (initialPFact == Teuchos::null) {
138  initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent");
139  }
140  RCP<Matrix> Ptent = coarseLevel.Get<RCP<Matrix> >("P", initialPFact.get());
141 
143  if (restrictionMode_) {
144  SubFactoryMonitor m2(*this, "Transpose A", coarseLevel);
145  A = Utilities::Transpose(*A, true); // build transpose of A explicitely
146  }
147 
149  bool doFillComplete = true;
150  bool optimizeStorage = true;
151  RCP<Matrix> DinvAP0 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*A, false, *Ptent, false, GetOStream(Statistics2), doFillComplete, optimizeStorage);
152 
153  doFillComplete = true;
154  optimizeStorage = false;
156  Utilities::MyOldScaleMatrix(*DinvAP0, diag, true, doFillComplete, optimizeStorage); // scale matrix with reciprocal of diag
157 
159 
160  Teuchos::RCP<Vector> RowBasedOmega = Teuchos::null;
161 
162  const ParameterList& pL = GetParameterList();
163  bool bReUseRowBasedOmegas = pL.get<bool>("ReUseRowBasedOmegas");
164  if (restrictionMode_ == false || bReUseRowBasedOmegas == false) {
165  // if in prolongation mode: calculate row based omegas
166  // if in restriction mode: calculate omegas only if row based omegas are not used from prolongation mode
167  ComputeRowBasedOmega(fineLevel, coarseLevel, A, Ptent, DinvAP0, RowBasedOmega);
168  } // if(bReUseRowBasedOmegas == false)
169  else {
170  // reuse row based omegas, calculated by this factory in the run before (with restrictionMode_ == false)
171  RowBasedOmega = coarseLevel.Get<Teuchos::RCP<Vector> >("RowBasedOmega", this);
172 
173  // RowBasedOmega is now based on row map of A (not transposed)
174  // for restriction we use A^T instead of A
175  // -> recommunicate row based omega
176 
177  // exporter: overlapping row map to nonoverlapping domain map (target map is unique)
178  // since A is already transposed we use the RangeMap of A
179  Teuchos::RCP<const Export> exporter =
180  ExportFactory::Build(RowBasedOmega->getMap(), A->getRangeMap());
181 
182  Teuchos::RCP<Vector> noRowBasedOmega =
183  VectorFactory::Build(A->getRangeMap());
184 
185  noRowBasedOmega->doExport(*RowBasedOmega, *exporter, Xpetra::INSERT);
186 
187  // importer: nonoverlapping map to overlapping map
188 
189  // importer: source -> target maps
190  Teuchos::RCP<const Import> importer =
191  ImportFactory::Build(A->getRangeMap(), A->getRowMap());
192 
193  // doImport target->doImport(*source, importer, action)
194  RowBasedOmega->doImport(*noRowBasedOmega, *importer, Xpetra::INSERT);
195  }
196 
197  Teuchos::ArrayRCP<Scalar> RowBasedOmega_local = RowBasedOmega->getDataNonConst(0);
198 
200  RCP<Matrix> P_smoothed = Teuchos::null;
201  Utilities::MyOldScaleMatrix(*DinvAP0, RowBasedOmega_local, false, doFillComplete, optimizeStorage); // scale matrix with reciprocal of diag
202 
204  *DinvAP0, false, -Teuchos::ScalarTraits<Scalar>::one(),
205  P_smoothed, GetOStream(Statistics2));
206  P_smoothed->fillComplete(Ptent->getDomainMap(), Ptent->getRangeMap());
207 
209 
210  RCP<ParameterList> params = rcp(new ParameterList());
211  params->set("printLoadBalancingInfo", true);
212 
213  // Level Set
214  if (!restrictionMode_) {
215  // prolongation factory is in prolongation mode
216  Set(coarseLevel, "P", P_smoothed);
217 
218  // RfromPFactory used to indicate to TogglePFactory that a factory
219  // capable or producing R can be invoked later. TogglePFactory
220  // replaces dummy value with an index into it's array of prolongators
221  // pointing to the correct prolongator factory. This is later used by
222  // RfromP_Or_TransP to invoke the prolongatorfactory in RestrictionMode
223  int dummy = 7;
224  Set(coarseLevel, "RfromPfactory", dummy);
225 
226  if (IsPrint(Statistics1))
227  GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*P_smoothed, "P", params);
228 
229  // NOTE: EXPERIMENTAL
230  if (Ptent->IsView("stridedMaps"))
231  P_smoothed->CreateView("stridedMaps", Ptent);
232 
233  } else {
234  // prolongation factory is in restriction mode
235  RCP<Matrix> R = Utilities::Transpose(*P_smoothed, true);
236  Set(coarseLevel, "R", R);
237 
238  if (IsPrint(Statistics1))
239  GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*R, "P", params);
240 
241  // NOTE: EXPERIMENTAL
242  if (Ptent->IsView("stridedMaps"))
243  R->CreateView("stridedMaps", Ptent, true);
244  }
245 }
246 
247 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
248 void PgPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ComputeRowBasedOmega(Level& /* fineLevel */, Level& coarseLevel, const RCP<Matrix>& A, const RCP<Matrix>& P0, const RCP<Matrix>& DinvAP0, RCP<Vector>& RowBasedOmega) const {
249  FactoryMonitor m(*this, "PgPFactory::ComputeRowBasedOmega", coarseLevel);
250 
251  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Magnitude;
253  Magnitude mZero = Teuchos::ScalarTraits<Scalar>::magnitude(sZero);
254 
255  Teuchos::RCP<Vector> Numerator = Teuchos::null;
256  Teuchos::RCP<Vector> Denominator = Teuchos::null;
257 
258  const ParameterList& pL = GetParameterList();
259  MinimizationNorm min_norm = pL.get<MinimizationNorm>("Minimization norm");
260 
261  switch (min_norm) {
262  case ANORM: {
263  // MUEMAT mode (=paper)
264  // Minimize with respect to the (A)' A norm.
265  // Need to be smart here to avoid the construction of A' A
266  //
267  // diag( P0' (A' A) D^{-1} A P0)
268  // omega = ------------------------------------------
269  // diag( P0' A' D^{-1}' ( A' A) D^{-1} A P0)
270  //
271  // expensive, since we have to recalculate AP0 due to the lack of an explicit scaling routine for DinvAP0
272 
273  // calculate A * P0
274  bool doFillComplete = true;
275  bool optimizeStorage = false;
276  RCP<Matrix> AP0 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*A, false, *P0, false, GetOStream(Statistics2), doFillComplete, optimizeStorage);
277 
278  // compute A * D^{-1} * A * P0
279  RCP<Matrix> ADinvAP0 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*A, false, *DinvAP0, false, GetOStream(Statistics2), doFillComplete, optimizeStorage);
280 
281  Numerator = VectorFactory::Build(ADinvAP0->getColMap(), true);
282  Denominator = VectorFactory::Build(ADinvAP0->getColMap(), true);
283  MultiplyAll(AP0, ADinvAP0, Numerator);
284  MultiplySelfAll(ADinvAP0, Denominator);
285  } break;
286  case L2NORM: {
287  // ML mode 1 (cheapest)
288  // Minimize with respect to L2 norm
289  // diag( P0' D^{-1} A P0)
290  // omega = -----------------------------
291  // diag( P0' A' D^{-1}' D^{-1} A P0)
292  //
293  Numerator = VectorFactory::Build(DinvAP0->getColMap(), true);
294  Denominator = VectorFactory::Build(DinvAP0->getColMap(), true);
295  MultiplyAll(P0, DinvAP0, Numerator);
296  MultiplySelfAll(DinvAP0, Denominator);
297  } break;
298  case DINVANORM: {
299  // ML mode 2
300  // Minimize with respect to the (D^{-1} A)' D^{-1} A norm.
301  // Need to be smart here to avoid the construction of A' A
302  //
303  // diag( P0' ( A' D^{-1}' D^{-1} A) D^{-1} A P0)
304  // omega = --------------------------------------------------------
305  // diag( P0' A' D^{-1}' ( A' D^{-1}' D^{-1} A) D^{-1} A P0)
306  //
307 
308  // compute D^{-1} * A * D^{-1} * A * P0
309  bool doFillComplete = true;
310  bool optimizeStorage = true;
312  RCP<Matrix> DinvADinvAP0 = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*A, false, *DinvAP0, false, GetOStream(Statistics2), doFillComplete, optimizeStorage);
313  Utilities::MyOldScaleMatrix(*DinvADinvAP0, diagA, true, doFillComplete, optimizeStorage); // scale matrix with reciprocal of diag
314  diagA = Teuchos::ArrayRCP<Scalar>();
315 
316  Numerator = VectorFactory::Build(DinvADinvAP0->getColMap(), true);
317  Denominator = VectorFactory::Build(DinvADinvAP0->getColMap(), true);
318  MultiplyAll(DinvAP0, DinvADinvAP0, Numerator);
319  MultiplySelfAll(DinvADinvAP0, Denominator);
320  } break;
321  default:
322  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::PgPFactory::Build: minimization mode not supported. error");
323  }
324 
326  Teuchos::RCP<Vector> ColBasedOmega =
327  VectorFactory::Build(Numerator->getMap() /*DinvAP0->getColMap()*/, true);
328 
329  ColBasedOmega->putScalar(-666 );
330 
331  Teuchos::ArrayRCP<const Scalar> Numerator_local = Numerator->getData(0);
332  Teuchos::ArrayRCP<const Scalar> Denominator_local = Denominator->getData(0);
333  Teuchos::ArrayRCP<Scalar> ColBasedOmega_local = ColBasedOmega->getDataNonConst(0);
334  GlobalOrdinal zero_local = 0; // count negative colbased omegas
335  GlobalOrdinal nan_local = 0; // count NaNs -> set them to zero
336  Magnitude min_local = 1000000.0; // Teuchos::ScalarTraits<Scalar>::one() * (Scalar) 1000000;
337  Magnitude max_local = 0.0;
338  for (LocalOrdinal i = 0; i < Teuchos::as<LocalOrdinal>(Numerator->getLocalLength()); i++) {
339  if (Teuchos::ScalarTraits<Scalar>::magnitude(Denominator_local[i]) == mZero) {
340  ColBasedOmega_local[i] = 0.0; // fallback: nonsmoothed basis function since denominator == 0.0
341  nan_local++;
342  } else {
343  ColBasedOmega_local[i] = Numerator_local[i] / Denominator_local[i]; // default case
344  }
345 
346  if (Teuchos::ScalarTraits<Scalar>::magnitude(ColBasedOmega_local[i]) < mZero) { // negative omegas are not valid. set them to zero
347  ColBasedOmega_local[i] = Teuchos::ScalarTraits<Scalar>::zero();
348  zero_local++; // count zero omegas
349  }
350 
351  // handle case that Nominator == Denominator -> Dirichlet bcs in A?
352  // fallback if ColBasedOmega == 1 -> very strong smoothing may lead to zero rows in P
353  // TAW: this is somewhat nonstandard and a rough fallback strategy to avoid problems
354  // also avoid "overshooting" with omega > 0.8
355  if (Teuchos::ScalarTraits<Scalar>::magnitude(ColBasedOmega_local[i]) >= 0.8) {
356  ColBasedOmega_local[i] = 0.0;
357  }
358 
359  if (Teuchos::ScalarTraits<Scalar>::magnitude(ColBasedOmega_local[i]) < min_local) {
360  min_local = Teuchos::ScalarTraits<Scalar>::magnitude(ColBasedOmega_local[i]);
361  }
362  if (Teuchos::ScalarTraits<Scalar>::magnitude(ColBasedOmega_local[i]) > max_local) {
363  max_local = Teuchos::ScalarTraits<Scalar>::magnitude(ColBasedOmega_local[i]);
364  }
365  }
366 
367  { // be verbose
368  GlobalOrdinal zero_all;
369  GlobalOrdinal nan_all;
370  Magnitude min_all;
371  Magnitude max_all;
372  MueLu_sumAll(A->getRowMap()->getComm(), zero_local, zero_all);
373  MueLu_sumAll(A->getRowMap()->getComm(), nan_local, nan_all);
374  MueLu_minAll(A->getRowMap()->getComm(), min_local, min_all);
375  MueLu_maxAll(A->getRowMap()->getComm(), max_local, max_all);
376 
377  GetOStream(MueLu::Statistics1, 0) << "PgPFactory: smoothed aggregation (scheme: ";
378  switch (min_norm) {
379  case ANORM: GetOStream(Statistics1) << "Anorm)" << std::endl; break;
380  case L2NORM: GetOStream(Statistics1) << "L2norm)" << std::endl; break;
381  case DINVANORM: GetOStream(Statistics1) << "DinvAnorm)" << std::endl; break;
382  default: GetOStream(Statistics1) << "unknown)" << std::endl; break;
383  }
384  GetOStream(Statistics1) << "Damping parameter: min = " << min_all << ", max = " << max_all << std::endl;
385  GetOStream(Statistics) << "# negative omegas: " << zero_all << " out of " << ColBasedOmega->getGlobalLength() << " column-based omegas" << std::endl;
386  GetOStream(Statistics) << "# NaNs: " << nan_all << " out of " << ColBasedOmega->getGlobalLength() << " column-based omegas" << std::endl;
387  }
388 
389  if (coarseLevel.IsRequested("ColBasedOmega", this)) {
390  coarseLevel.Set("ColBasedOmega", ColBasedOmega, this);
391  }
392 
394  // transform column based omegas to row based omegas
395  RowBasedOmega =
396  VectorFactory::Build(DinvAP0->getRowMap(), true);
397 
398  RowBasedOmega->putScalar(-666); // TODO bad programming style
399 
400  bool bAtLeastOneDefined = false;
401  Teuchos::ArrayRCP<Scalar> RowBasedOmega_local = RowBasedOmega->getDataNonConst(0);
402  for (LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(A->getLocalNumRows()); row++) {
405  DinvAP0->getLocalRowView(row, lindices, lvals);
406  bAtLeastOneDefined = false;
407  for (size_t j = 0; j < Teuchos::as<size_t>(lindices.size()); j++) {
408  Scalar omega = ColBasedOmega_local[lindices[j]];
409  if (Teuchos::ScalarTraits<Scalar>::magnitude(omega) != -666) { // TODO bad programming style
410  bAtLeastOneDefined = true;
411  if (Teuchos::ScalarTraits<Scalar>::magnitude(RowBasedOmega_local[row]) == -666)
412  RowBasedOmega_local[row] = omega;
414  RowBasedOmega_local[row] = omega;
415  }
416  }
417  if (bAtLeastOneDefined == true) {
418  if (Teuchos::ScalarTraits<Scalar>::magnitude(RowBasedOmega_local[row]) < mZero)
419  RowBasedOmega_local[row] = sZero;
420  }
421  }
422 
423  if (coarseLevel.IsRequested("RowBasedOmega", this)) {
424  Set(coarseLevel, "RowBasedOmega", RowBasedOmega);
425  }
426 }
427 
428 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
430  // note: InnerProdVec is based on column map of Op
431  TEUCHOS_TEST_FOR_EXCEPTION(!InnerProdVec->getMap()->isSameAs(*Op->getColMap()), Exceptions::RuntimeError, "MueLu::PgPFactory::MultiplySelfAll: map of InnerProdVec must be same as column map of operator. error");
432 
433  Teuchos::ArrayRCP<Scalar> InnerProd_local = InnerProdVec->getDataNonConst(0);
434 
437 
438  for (size_t n = 0; n < Op->getLocalNumRows(); n++) {
439  Op->getLocalRowView(n, lindices, lvals);
440  for (size_t i = 0; i < Teuchos::as<size_t>(lindices.size()); i++) {
441  InnerProd_local[lindices[i]] += lvals[i] * lvals[i];
442  }
443  }
444  InnerProd_local = Teuchos::ArrayRCP<Scalar>();
445 
446  // exporter: overlapping map to nonoverlapping map (target map is unique)
447  Teuchos::RCP<const Export> exporter =
448  ExportFactory::Build(Op->getColMap(), Op->getDomainMap());
449 
450  Teuchos::RCP<Vector> nonoverlap =
451  VectorFactory::Build(Op->getDomainMap());
452 
453  nonoverlap->doExport(*InnerProdVec, *exporter, Xpetra::ADD);
454 
455  // importer: nonoverlapping map to overlapping map
456 
457  // importer: source -> target maps
458  Teuchos::RCP<const Import> importer =
459  ImportFactory::Build(Op->getDomainMap(), Op->getColMap());
460 
461  // doImport target->doImport(*source, importer, action)
462  InnerProdVec->doImport(*nonoverlap, *importer, Xpetra::INSERT);
463 }
464 
465 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
467  TEUCHOS_TEST_FOR_EXCEPTION(!left->getDomainMap()->isSameAs(*right->getDomainMap()), Exceptions::RuntimeError, "MueLu::PgPFactory::MultiplyAll: domain maps of left and right do not match. Error.");
468  TEUCHOS_TEST_FOR_EXCEPTION(!left->getRowMap()->isSameAs(*right->getRowMap()), Exceptions::RuntimeError, "MueLu::PgPFactory::MultiplyAll: row maps of left and right do not match. Error.");
469 #if 1 // 1=new "fast code, 0=old "slow", but safe code
470 #if 0 // not necessary - remove me
471  if(InnerProdVec->getMap()->isSameAs(*left->getColMap())) {
472  // initialize NewRightLocal vector and assign all entries to
473  // left->getColMap()->getLocalNumElements() + 1
474  std::vector<LocalOrdinal> NewRightLocal(right->getColMap()->getLocalNumElements(), Teuchos::as<LocalOrdinal>(left->getColMap()->getLocalNumElements()+1));
475 
476  LocalOrdinal i = 0;
477  for (size_t j=0; j < right->getColMap()->getLocalNumElements(); j++) {
478  while ( (i < Teuchos::as<LocalOrdinal>(left->getColMap()->getLocalNumElements())) &&
479  (left->getColMap()->getGlobalElement(i) < right->getColMap()->getGlobalElement(j)) ) i++;
480  if (left->getColMap()->getGlobalElement(i) == right->getColMap()->getGlobalElement(j)) {
481  NewRightLocal[j] = i;
482  }
483  }
484 
485  Teuchos::ArrayRCP< Scalar > InnerProd_local = InnerProdVec->getDataNonConst(0);
486  std::vector<Scalar> temp_array(left->getColMap()->getLocalNumElements()+1, 0.0);
487 
488  for(size_t n=0; n<right->getLocalNumRows(); n++) {
493 
494  left->getLocalRowView (n, lindices_left, lvals_left);
495  right->getLocalRowView(n, lindices_right, lvals_right);
496 
497  for(size_t j=0; j<Teuchos::as<size_t>(lindices_right.size()); j++) {
498  temp_array[NewRightLocal[lindices_right[j] ] ] = lvals_right[j];
499  }
500  for (size_t j=0; j < Teuchos::as<size_t>(lindices_left.size()); j++) {
501  InnerProd_local[lindices_left[j]] += temp_array[lindices_left[j] ]*lvals_left[j];
502  }
503  for (size_t j=0; j < Teuchos::as<size_t>(lindices_right.size()); j++) {
504  temp_array[NewRightLocal[lindices_right[j] ] ] = 0.0;
505  }
506  }
507  // exporter: overlapping map to nonoverlapping map (target map is unique)
508  Teuchos::RCP<const Export> exporter =
509  ExportFactory::Build(left->getColMap(), left->getDomainMap()); // TODO: change left to right?
510 
511  Teuchos::RCP<Vector > nonoverlap =
512  VectorFactory::Build(left->getDomainMap()); // TODO: change left to right?
513 
514  nonoverlap->doExport(*InnerProdVec, *exporter, Xpetra::ADD);
515 
516  // importer: nonoverlapping map to overlapping map
517 
518  // importer: source -> target maps
519  Teuchos::RCP<const Import > importer =
520  ImportFactory::Build(left->getDomainMap(), left->getColMap()); // TODO: change left to right?
521 
522  // doImport target->doImport(*source, importer, action)
523  InnerProdVec->doImport(*nonoverlap, *importer, Xpetra::INSERT);
524 
525 
526  } else
527 #endif // end remove me
528  if (InnerProdVec->getMap()->isSameAs(*right->getColMap())) {
529  size_t szNewLeftLocal = TEUCHOS_MAX(left->getColMap()->getLocalNumElements(), right->getColMap()->getLocalNumElements());
530  Teuchos::RCP<std::vector<LocalOrdinal> > NewLeftLocal = Teuchos::rcp(new std::vector<LocalOrdinal>(szNewLeftLocal, Teuchos::as<LocalOrdinal>(right->getColMap()->getMaxLocalIndex() + 1)));
531 
532  LocalOrdinal j = 0;
533  for (size_t i = 0; i < left->getColMap()->getLocalNumElements(); i++) {
534  while ((j < Teuchos::as<LocalOrdinal>(right->getColMap()->getLocalNumElements())) &&
535  (right->getColMap()->getGlobalElement(j) < left->getColMap()->getGlobalElement(i))) j++;
536  if (right->getColMap()->getGlobalElement(j) == left->getColMap()->getGlobalElement(i)) {
537  (*NewLeftLocal)[i] = j;
538  }
539  }
540 
541  /*for (size_t i=0; i < right->getColMap()->getLocalNumElements(); i++) {
542  std::cout << "left col map: " << (*NewLeftLocal)[i] << " GID: " << left->getColMap()->getGlobalElement((*NewLeftLocal)[i]) << " GID: " << right->getColMap()->getGlobalElement(i) << " right col map: " << i << std::endl;
543  }*/
544 
545  Teuchos::ArrayRCP<Scalar> InnerProd_local = InnerProdVec->getDataNonConst(0);
546  Teuchos::RCP<std::vector<Scalar> > temp_array = Teuchos::rcp(new std::vector<Scalar>(right->getColMap()->getMaxLocalIndex() + 2, 0.0));
547 
548  for (size_t n = 0; n < left->getLocalNumRows(); n++) {
553 
554  left->getLocalRowView(n, lindices_left, lvals_left);
555  right->getLocalRowView(n, lindices_right, lvals_right);
556 
557  for (size_t i = 0; i < Teuchos::as<size_t>(lindices_left.size()); i++) {
558  (*temp_array)[(*NewLeftLocal)[lindices_left[i]]] = lvals_left[i];
559  }
560  for (size_t i = 0; i < Teuchos::as<size_t>(lindices_right.size()); i++) {
561  InnerProd_local[lindices_right[i]] += (*temp_array)[lindices_right[i]] * lvals_right[i];
562  }
563  for (size_t i = 0; i < Teuchos::as<size_t>(lindices_left.size()); i++) {
564  (*temp_array)[(*NewLeftLocal)[lindices_left[i]]] = 0.0;
565  }
566  }
567  InnerProd_local = Teuchos::ArrayRCP<Scalar>();
568  // exporter: overlapping map to nonoverlapping map (target map is unique)
569  Teuchos::RCP<const Export> exporter =
570  ExportFactory::Build(right->getColMap(), right->getDomainMap()); // TODO: change left to right?
571 
572  Teuchos::RCP<Vector> nonoverlap =
573  VectorFactory::Build(right->getDomainMap()); // TODO: change left to right?
574 
575  nonoverlap->doExport(*InnerProdVec, *exporter, Xpetra::ADD);
576 
577  // importer: nonoverlapping map to overlapping map
578 
579  // importer: source -> target maps
580  Teuchos::RCP<const Import> importer =
581  ImportFactory::Build(right->getDomainMap(), right->getColMap()); // TODO: change left to right?
582  // doImport target->doImport(*source, importer, action)
583  InnerProdVec->doImport(*nonoverlap, *importer, Xpetra::INSERT);
584  } else {
585  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::PgPFactory::MultiplyAll: map of InnerProdVec must be same as column map of left operator? Error.");
586  }
587 
588 #else // old "safe" code
589  if (InnerProdVec->getMap()->isSameAs(*left->getColMap())) {
590  Teuchos::ArrayRCP<Scalar> InnerProd_local = InnerProdVec->getDataNonConst(0);
591 
592  // declare variables
597 
598  for (size_t n = 0; n < left->getLocalNumRows(); n++) {
599  left->getLocalRowView(n, lindices_left, lvals_left);
600  right->getLocalRowView(n, lindices_right, lvals_right);
601 
602  for (size_t i = 0; i < Teuchos::as<size_t>(lindices_left.size()); i++) {
603  GlobalOrdinal left_gid = left->getColMap()->getGlobalElement(lindices_left[i]);
604  for (size_t j = 0; j < Teuchos::as<size_t>(lindices_right.size()); j++) {
605  GlobalOrdinal right_gid = right->getColMap()->getGlobalElement(lindices_right[j]);
606  if (left_gid == right_gid) {
607  InnerProd_local[lindices_left[i]] += lvals_left[i] * lvals_right[j];
608  break; // skip remaining gids of right operator
609  }
610  }
611  }
612  }
613 
614  // exporter: overlapping map to nonoverlapping map (target map is unique)
615  Teuchos::RCP<const Export> exporter =
616  ExportFactory::Build(left->getColMap(), left->getDomainMap()); // TODO: change left to right?
617 
618  Teuchos::RCP<Vector> nonoverlap =
619  VectorFactory::Build(left->getDomainMap()); // TODO: change left to right?
620 
621  nonoverlap->doExport(*InnerProdVec, *exporter, Xpetra::ADD);
622 
623  // importer: nonoverlapping map to overlapping map
624 
625  // importer: source -> target maps
626  Teuchos::RCP<const Import> importer =
627  ImportFactory::Build(left->getDomainMap(), left->getColMap()); // TODO: change left to right?
628 
629  // doImport target->doImport(*source, importer, action)
630  InnerProdVec->doImport(*nonoverlap, *importer, Xpetra::INSERT);
631  } else if (InnerProdVec->getMap()->isSameAs(*right->getColMap())) {
632  Teuchos::ArrayRCP<Scalar> InnerProd_local = InnerProdVec->getDataNonConst(0);
633 
638 
639  for (size_t n = 0; n < left->getLocalNumRows(); n++) {
640  left->getLocalRowView(n, lindices_left, lvals_left);
641  right->getLocalRowView(n, lindices_right, lvals_right);
642 
643  for (size_t i = 0; i < Teuchos::as<size_t>(lindices_left.size()); i++) {
644  GlobalOrdinal left_gid = left->getColMap()->getGlobalElement(lindices_left[i]);
645  for (size_t j = 0; j < Teuchos::as<size_t>(lindices_right.size()); j++) {
646  GlobalOrdinal right_gid = right->getColMap()->getGlobalElement(lindices_right[j]);
647  if (left_gid == right_gid) {
648  InnerProd_local[lindices_right[j]] += lvals_left[i] * lvals_right[j];
649  break; // skip remaining gids of right operator
650  }
651  }
652  }
653  }
654 
655  // exporter: overlapping map to nonoverlapping map (target map is unique)
656  Teuchos::RCP<const Export> exporter =
657  ExportFactory::Build(right->getColMap(), right->getDomainMap()); // TODO: change left to right?
658 
659  Teuchos::RCP<Vector> nonoverlap =
660  VectorFactory::Build(right->getDomainMap()); // TODO: change left to right?
661 
662  nonoverlap->doExport(*InnerProdVec, *exporter, Xpetra::ADD);
663 
664  // importer: nonoverlapping map to overlapping map
665 
666  // importer: source -> target maps
667  Teuchos::RCP<const Import> importer =
668  ImportFactory::Build(right->getDomainMap(), right->getColMap()); // TODO: change left to right?
669 
670  // doImport target->doImport(*source, importer, action)
671  InnerProdVec->doImport(*nonoverlap, *importer, Xpetra::INSERT);
672  } else {
673  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::PgPFactory::MultiplyAll: map of InnerProdVec must be same as column map of left or right operator? Error.");
674  }
675 #endif
676 }
677 
678 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
679 void PgPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildP(Level& /* fineLevel */, Level& /* coarseLevel */) const {
680  std::cout << "TODO: remove me" << std::endl;
681 }
682 
683 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
685  SetParameter("ReUseRowBasedOmegas", ParameterEntry(bReuse));
686 }
687 
688 } // namespace MueLu
689 
690 #endif /* MUELU_PGPFACTORY_DEF_HPP */
#define MueLu_sumAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
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.
static void MyOldScaleMatrix(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const Teuchos::ArrayRCP< const Scalar > &scalingVector, bool doInverse=true, bool doFillComplete=true, bool doOptimizeStorage=true)
#define MueLu_maxAll(rcpComm, in, out)
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
T & get(const std::string &name, T def_value)
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
void ComputeRowBasedOmega(Level &fineLevel, Level &coarseLevel, const RCP< Matrix > &A, const RCP< Matrix > &P0, const RCP< Matrix > &DinvAP0, RCP< Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &RowBasedOmega) const
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Print more statistics.
size_type size() const
T * get() const
#define MueLu_minAll(rcpComm, in, out)
Print all statistics.
Print even more statistics.
void SetMinimizationMode(MinimizationNorm minnorm)
Set minimization mode (L2NORM for cheapest, ANORM more expensive, DINVANORM = default) ...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
void Build(Level &fineLevel, Level &coarseLevel) const
Build method.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
void MultiplySelfAll(const RCP< Matrix > &Op, Teuchos::RCP< Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &InnerProdVec) const
static Teuchos::ArrayRCP< Scalar > GetMatrixDiagonal_arcp(const Matrix &A)
Extract Matrix Diagonal.
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Transpose(Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, bool optimizeTranspose=false, const std::string &label=std::string(), const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null)
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
MinimizationNorm GetMinimizationMode()
return minimization mode
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static void TwoMatrixAdd(const Matrix &A, bool transposeA, SC alpha, Matrix &B, SC beta)
static magnitudeType magnitude(T a)
void ReUseDampingParameters(bool bReuse)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
static void Multiply(const Matrix &A, bool transposeA, const Matrix &B, bool transposeB, Matrix &C, bool call_FillComplete_on_result=true, bool doOptimizeStorage=true, const std::string &label=std::string(), const RCP< ParameterList > &params=null)
const RCP< const FactoryManagerBase > GetFactoryManager()
returns the current factory manager
Definition: MueLu_Level.cpp:96
Exception throws to report errors in the internal logical of the program.
bool IsRequested(const std::string &ename, const FactoryBase *factory=NoFactory::get()) const
Test whether a need has been requested. Note: this tells nothing about whether the need&#39;s value exist...
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
void MultiplyAll(const RCP< Matrix > &left, const RCP< Matrix > &right, Teuchos::RCP< Xpetra::Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > &InnerProdVec) const