Ifpack2 Templated Preconditioning Package  Version 1.0
Ifpack2_OverlappingRowMatrix_def.hpp
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack2: Tempated Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
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 Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 #ifndef IFPACK2_OVERLAPPINGROWMATRIX_DEF_HPP
44 #define IFPACK2_OVERLAPPINGROWMATRIX_DEF_HPP
45 
46 #include <sstream>
47 
48 #include <Ifpack2_OverlappingRowMatrix_decl.hpp>
49 #include <Ifpack2_Details_OverlappingRowGraph.hpp>
50 #include <Tpetra_CrsMatrix.hpp>
51 #include <Teuchos_CommHelpers.hpp>
52 
53 namespace Ifpack2 {
54 
55 template<class MatrixType>
57 OverlappingRowMatrix (const Teuchos::RCP<const row_matrix_type>& A,
58  const int overlapLevel) :
59  A_ (A),
60  OverlapLevel_ (overlapLevel)
61 {
62  using Teuchos::RCP;
63  using Teuchos::rcp;
64  using Teuchos::Array;
65  using Teuchos::outArg;
66  using Teuchos::rcp_const_cast;
67  using Teuchos::rcp_dynamic_cast;
68  using Teuchos::rcp_implicit_cast;
69  using Teuchos::REDUCE_SUM;
70  using Teuchos::reduceAll;
71  typedef Tpetra::global_size_t GST;
72  typedef Tpetra::CrsGraph<local_ordinal_type,
73  global_ordinal_type, node_type> crs_graph_type;
74  TEUCHOS_TEST_FOR_EXCEPTION(
75  OverlapLevel_ <= 0, std::runtime_error,
76  "Ifpack2::OverlappingRowMatrix: OverlapLevel must be > 0.");
77  TEUCHOS_TEST_FOR_EXCEPTION(
78  A_->getComm()->getSize() == 1, std::runtime_error,
79  "Ifpack2::OverlappingRowMatrix: Matrix must be "
80  "distributed over more than one MPI process.");
81 
82  RCP<const crs_matrix_type> ACRS =
83  rcp_dynamic_cast<const crs_matrix_type, const row_matrix_type> (A_);
84  TEUCHOS_TEST_FOR_EXCEPTION(
85  ACRS.is_null (), std::runtime_error,
86  "Ifpack2::OverlappingRowMatrix: The input matrix must be a Tpetra::"
87  "CrsMatrix with matching template parameters. This class currently "
88  "requires that CrsMatrix's fifth template parameter be the default.");
89  RCP<const crs_graph_type> A_crsGraph = ACRS->getCrsGraph ();
90 
91  const size_t numMyRowsA = A_->getNodeNumRows ();
92  const global_ordinal_type global_invalid =
93  Teuchos::OrdinalTraits<global_ordinal_type>::invalid ();
94 
95  // Temp arrays
96  Array<global_ordinal_type> ExtElements;
97  RCP<map_type> TmpMap;
98  RCP<crs_graph_type> TmpGraph;
99  RCP<import_type> TmpImporter;
100  RCP<const map_type> RowMap, ColMap;
101 
102  // The big import loop
103  for (int overlap = 0 ; overlap < OverlapLevel_ ; ++overlap) {
104  // Get the current maps
105  if (overlap == 0) {
106  RowMap = A_->getRowMap ();
107  ColMap = A_->getColMap ();
108  }
109  else {
110  RowMap = TmpGraph->getRowMap ();
111  ColMap = TmpGraph->getColMap ();
112  }
113 
114  const size_t size = ColMap->getNodeNumElements () - RowMap->getNodeNumElements ();
115  Array<global_ordinal_type> mylist (size);
116  size_t count = 0;
117 
118  // define the set of rows that are in ColMap but not in RowMap
119  for (local_ordinal_type i = 0 ; (size_t) i < ColMap->getNodeNumElements() ; ++i) {
120  const global_ordinal_type GID = ColMap->getGlobalElement (i);
121  if (A_->getRowMap ()->getLocalElement (GID) == global_invalid) {
122  typedef typename Array<global_ordinal_type>::iterator iter_type;
123  const iter_type end = ExtElements.end ();
124  const iter_type pos = std::find (ExtElements.begin (), end, GID);
125  if (pos == end) {
126  ExtElements.push_back (GID);
127  mylist[count] = GID;
128  ++count;
129  }
130  }
131  }
132 
133  // mfh 24 Nov 2013: We don't need TmpMap, TmpGraph, or
134  // TmpImporter after this loop, so we don't have to construct them
135  // on the last round.
136  if (overlap + 1 < OverlapLevel_) {
137  // Allocate & import new matrices, maps, etc.
138  //
139  // FIXME (mfh 24 Nov 2013) Do we always want to use index base
140  // zero? It doesn't really matter, since the actual index base
141  // (in the current implementation of Map) will always be the
142  // globally least GID.
143  TmpMap = rcp (new map_type (global_invalid, mylist (0, count),
144  Teuchos::OrdinalTraits<global_ordinal_type>::zero (),
145  A_->getComm (), A_->getNode ()));
146  TmpGraph = rcp (new crs_graph_type (TmpMap, 0));
147  TmpImporter = rcp (new import_type (A_->getRowMap (), TmpMap));
148 
149  TmpGraph->doImport (*A_crsGraph, *TmpImporter, Tpetra::INSERT);
150  TmpGraph->fillComplete (A_->getDomainMap (), TmpMap);
151  }
152  }
153 
154  // build the map containing all the nodes (original
155  // matrix + extended matrix)
156  Array<global_ordinal_type> mylist (numMyRowsA + ExtElements.size ());
157  for (local_ordinal_type i = 0; (size_t)i < numMyRowsA; ++i) {
158  mylist[i] = A_->getRowMap ()->getGlobalElement (i);
159  }
160  for (local_ordinal_type i = 0; i < ExtElements.size (); ++i) {
161  mylist[i + numMyRowsA] = ExtElements[i];
162  }
163 
164  RowMap_ = rcp (new map_type (global_invalid, mylist (),
165  Teuchos::OrdinalTraits<global_ordinal_type>::zero (),
166  A_->getComm (), A_->getNode ()));
167  ColMap_ = RowMap_;
168 
169  // now build the map corresponding to all the external nodes
170  // (with respect to A().RowMatrixRowMap().
171  ExtMap_ = rcp (new map_type (global_invalid, ExtElements (),
172  Teuchos::OrdinalTraits<global_ordinal_type>::zero (),
173  A_->getComm (), A_->getNode ()));
174  ExtMatrix_ = rcp (new crs_matrix_type (ExtMap_, ColMap_, 0));
175  ExtImporter_ = rcp (new import_type (A_->getRowMap (), ExtMap_));
176 
177  RCP<crs_matrix_type> ExtMatrixCRS =
178  rcp_dynamic_cast<crs_matrix_type, row_matrix_type> (ExtMatrix_);
179  ExtMatrixCRS->doImport (*ACRS, *ExtImporter_, Tpetra::INSERT);
180  ExtMatrixCRS->fillComplete (A_->getDomainMap (), RowMap_);
181 
182  Importer_ = rcp (new import_type (A_->getRowMap (), RowMap_));
183 
184  // fix indices for overlapping matrix
185  const size_t numMyRowsB = ExtMatrix_->getNodeNumRows ();
186 
187  GST NumMyNonzeros_tmp = A_->getNodeNumEntries () + ExtMatrix_->getNodeNumEntries ();
188  GST NumMyRows_tmp = numMyRowsA + numMyRowsB;
189  {
190  GST inArray[2], outArray[2];
191  inArray[0] = NumMyNonzeros_tmp;
192  inArray[1] = NumMyRows_tmp;
193  outArray[0] = 0;
194  outArray[1] = 0;
195  reduceAll<int, GST> (* (A_->getComm ()), REDUCE_SUM, 2, inArray, outArray);
196  NumGlobalNonzeros_ = outArray[0];
197  NumGlobalRows_ = outArray[1];
198  }
199  // reduceAll<int, GST> (* (A_->getComm ()), REDUCE_SUM, NumMyNonzeros_tmp,
200  // outArg (NumGlobalNonzeros_));
201  // reduceAll<int, GST> (* (A_->getComm ()), REDUCE_SUM, NumMyRows_tmp,
202  // outArg (NumGlobalRows_));
203 
204  MaxNumEntries_ = A_->getNodeMaxNumRowEntries ();
205  if (MaxNumEntries_ < ExtMatrix_->getNodeMaxNumRowEntries ()) {
206  MaxNumEntries_ = ExtMatrix_->getNodeMaxNumRowEntries ();
207  }
208 
209  // Create the graph (returned by getGraph()).
210  typedef Details::OverlappingRowGraph<row_graph_type> row_graph_impl_type;
211  RCP<row_graph_impl_type> graph =
212  rcp (new row_graph_impl_type (A_->getGraph (),
213  ExtMatrix_->getGraph (),
214  RowMap_,
215  ColMap_,
216  NumGlobalRows_,
217  NumGlobalRows_, // # global cols == # global rows
218  NumGlobalNonzeros_,
219  MaxNumEntries_,
220  rcp_const_cast<const import_type> (Importer_),
221  rcp_const_cast<const import_type> (ExtImporter_)));
222  graph_ = rcp_const_cast<const row_graph_type> (rcp_implicit_cast<row_graph_type> (graph));
223  // Resize temp arrays
224  Indices_.resize (MaxNumEntries_);
225  Values_.resize (MaxNumEntries_);
226 }
227 
228 
229 template<class MatrixType>
231 
232 
233 template<class MatrixType>
234 Teuchos::RCP<const Teuchos::Comm<int> >
236 {
237  return A_->getComm ();
238 }
239 
240 
241 template<class MatrixType>
242 Teuchos::RCP<typename MatrixType::node_type>
244 {
245  return A_->getNode();
246 }
247 
248 
249 template<class MatrixType>
250 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
252 {
253  // FIXME (mfh 12 July 2013) Is this really the right Map to return?
254  return RowMap_;
255 }
256 
257 
258 template<class MatrixType>
259 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
261 {
262  // FIXME (mfh 12 July 2013) Is this really the right Map to return?
263  return ColMap_;
264 }
265 
266 
267 template<class MatrixType>
268 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
270 {
271  // The original matrix's domain map is irrelevant; we want the map associated
272  // with the overlap. This can then be used by LocalFilter, for example, while
273  // letting LocalFilter still filter based on domain and range maps (instead of
274  // column and row maps).
275  // FIXME Ideally, this would be the same map but restricted to a local
276  // communicator. If replaceCommWithSubset were free, that would be the way to
277  // go. That would require a new Map ctor. For now, we'll stick with ColMap_'s
278  // global communicator.
279  return ColMap_;
280 }
281 
282 
283 template<class MatrixType>
284 Teuchos::RCP<const Tpetra::Map<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
286 {
287  return RowMap_;
288 }
289 
290 
291 template<class MatrixType>
292 Teuchos::RCP<const Tpetra::RowGraph<typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
294 {
295  return graph_;
296 }
297 
298 
299 template<class MatrixType>
301 {
302  return NumGlobalRows_;
303 }
304 
305 
306 template<class MatrixType>
308 {
309  return NumGlobalRows_;
310 }
311 
312 
313 template<class MatrixType>
315 {
316  return A_->getNodeNumRows () + ExtMatrix_->getNodeNumRows ();
317 }
318 
319 
320 template<class MatrixType>
322 {
323  return this->getNodeNumRows ();
324 }
325 
326 
327 template<class MatrixType>
328 typename MatrixType::global_ordinal_type
330 {
331  return A_->getIndexBase();
332 }
333 
334 
335 template<class MatrixType>
337 {
338  return NumGlobalNonzeros_;
339 }
340 
341 
342 template<class MatrixType>
344 {
345  return A_->getNodeNumEntries () + ExtMatrix_->getNodeNumEntries ();
346 }
347 
348 
349 template<class MatrixType>
350 size_t
352 getNumEntriesInGlobalRow (global_ordinal_type globalRow) const
353 {
354  const local_ordinal_type localRow = RowMap_->getLocalElement (globalRow);
355  if (localRow == Teuchos::OrdinalTraits<local_ordinal_type>::invalid ()) {
356  return Teuchos::OrdinalTraits<size_t>::invalid();
357  } else {
358  return getNumEntriesInLocalRow (localRow);
359  }
360 }
361 
362 
363 template<class MatrixType>
364 size_t
366 getNumEntriesInLocalRow (local_ordinal_type localRow) const
367 {
368  using Teuchos::as;
369  const size_t numMyRowsA = A_->getNodeNumRows ();
370  if (as<size_t> (localRow) < numMyRowsA) {
371  return A_->getNumEntriesInLocalRow (localRow);
372  } else {
373  return ExtMatrix_->getNumEntriesInLocalRow (as<local_ordinal_type> (localRow - numMyRowsA));
374  }
375 }
376 
377 
378 template<class MatrixType>
380 {
381  throw std::runtime_error("Ifpack2::OverlappingRowMatrix::getGlobalNumDiags() not supported.");
382 }
383 
384 
385 template<class MatrixType>
387 {
388  return A_->getNodeNumDiags();
389 }
390 
391 
392 template<class MatrixType>
394 {
395  throw std::runtime_error("Ifpack2::OverlappingRowMatrix::getGlobalMaxNumRowEntries() not supported.");
396 }
397 
398 
399 template<class MatrixType>
401 {
402  return MaxNumEntries_;
403 }
404 
405 
406 template<class MatrixType>
408 {
409  return true;
410 }
411 
412 
413 template<class MatrixType>
415 {
416  return A_->isLowerTriangular();
417 }
418 
419 
420 template<class MatrixType>
422 {
423  return A_->isUpperTriangular();
424 }
425 
426 
427 template<class MatrixType>
429 {
430  return true;
431 }
432 
433 
434 template<class MatrixType>
436 {
437  return false;
438 }
439 
440 
441 template<class MatrixType>
443 {
444  return true;
445 }
446 
447 
448 template<class MatrixType>
449 void
451 getGlobalRowCopy (global_ordinal_type GlobalRow,
452  const Teuchos::ArrayView<global_ordinal_type> &Indices,
453  const Teuchos::ArrayView<scalar_type>& Values,
454  size_t& NumEntries) const
455 {
456  const local_ordinal_type LocalRow = RowMap_->getLocalElement (GlobalRow);
457  if (LocalRow == Teuchos::OrdinalTraits<local_ordinal_type>::invalid ()) {
458  NumEntries = Teuchos::OrdinalTraits<size_t>::invalid ();
459  } else {
460  if (Teuchos::as<size_t> (LocalRow) < A_->getNodeNumRows ()) {
461  A_->getGlobalRowCopy (GlobalRow, Indices, Values, NumEntries);
462  } else {
463  ExtMatrix_->getGlobalRowCopy (GlobalRow, Indices, Values, NumEntries);
464  }
465  }
466 }
467 
468 
469 template<class MatrixType>
470 void
472 getLocalRowCopy (local_ordinal_type LocalRow,
473  const Teuchos::ArrayView<local_ordinal_type> &Indices,
474  const Teuchos::ArrayView<scalar_type> &Values,
475  size_t &NumEntries) const
476 {
477  using Teuchos::as;
478  const size_t numMyRowsA = A_->getNodeNumRows ();
479  if (as<size_t> (LocalRow) < numMyRowsA) {
480  A_->getLocalRowCopy (LocalRow, Indices, Values, NumEntries);
481  } else {
482  ExtMatrix_->getLocalRowCopy (LocalRow - as<local_ordinal_type> (numMyRowsA),
483  Indices, Values, NumEntries);
484  }
485 }
486 
487 
488 template<class MatrixType>
489 void
491 getGlobalRowView (global_ordinal_type GlobalRow,
492  Teuchos::ArrayView<const global_ordinal_type>& indices,
493  Teuchos::ArrayView<const scalar_type>& values) const
494 {
495  const local_ordinal_type LocalRow = RowMap_->getLocalElement (GlobalRow);
496  if (LocalRow == Teuchos::OrdinalTraits<local_ordinal_type>::invalid()) {
497  indices = Teuchos::null;
498  values = Teuchos::null;
499  } else {
500  if (Teuchos::as<size_t> (LocalRow) < A_->getNodeNumRows ()) {
501  A_->getGlobalRowView (GlobalRow, indices, values);
502  } else {
503  ExtMatrix_->getGlobalRowView (GlobalRow, indices, values);
504  }
505  }
506 }
507 
508 
509 template<class MatrixType>
510 void
512 getLocalRowView (local_ordinal_type LocalRow,
513  Teuchos::ArrayView<const local_ordinal_type>& indices,
514  Teuchos::ArrayView<const scalar_type>& values) const
515 {
516  using Teuchos::as;
517  const size_t numMyRowsA = A_->getNodeNumRows ();
518  if (as<size_t> (LocalRow) < numMyRowsA) {
519  A_->getLocalRowView (LocalRow, indices, values);
520  } else {
521  ExtMatrix_->getLocalRowView (LocalRow - as<local_ordinal_type> (numMyRowsA),
522  indices, values);
523  }
524 }
525 
526 
527 template<class MatrixType>
528 void
530 getLocalDiagCopy (Tpetra::Vector<scalar_type,local_ordinal_type,global_ordinal_type,node_type>& diag) const
531 {
532  using Teuchos::Array;
533 
534  //extract diagonal of original matrix
535  vector_type baseDiag(A_->getRowMap()); // diagonal of original matrix A_
536  A_->getLocalDiagCopy(baseDiag);
537  Array<scalar_type> baseDiagVals(baseDiag.getLocalLength());
538  baseDiag.get1dCopy(baseDiagVals());
539  //extra diagonal of ghost matrix
540  vector_type extDiag(ExtMatrix_->getRowMap());
541  ExtMatrix_->getLocalDiagCopy(extDiag);
542  Array<scalar_type> extDiagVals(extDiag.getLocalLength());
543  extDiag.get1dCopy(extDiagVals());
544 
545  Teuchos::ArrayRCP<scalar_type> allDiagVals = diag.getDataNonConst();
546  if (allDiagVals.size() != baseDiagVals.size() + extDiagVals.size()) {
547  std::ostringstream errStr;
548  errStr << "Ifpack2::OverlappingRowMatrix::getLocalDiagCopy : Mismatch in diagonal lengths, "
549  << allDiagVals.size() << " != " << baseDiagVals.size() << "+" << extDiagVals.size();
550  throw std::runtime_error(errStr.str());
551  }
552  for (Teuchos::Ordinal i=0; i<baseDiagVals.size(); ++i)
553  allDiagVals[i] = baseDiagVals[i];
554  Teuchos_Ordinal offset=baseDiagVals.size();
555  for (Teuchos::Ordinal i=0; i<extDiagVals.size(); ++i)
556  allDiagVals[i+offset] = extDiagVals[i];
557 }
558 
559 
560 template<class MatrixType>
561 void
563 leftScale (const Tpetra::Vector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& x)
564 {
565  throw std::runtime_error("Ifpack2::OverlappingRowMatrix does not support leftScale.");
566 }
567 
568 
569 template<class MatrixType>
570 void
572 rightScale (const Tpetra::Vector<scalar_type, local_ordinal_type, global_ordinal_type, node_type>& x)
573 {
574  throw std::runtime_error("Ifpack2::OverlappingRowMatrix does not support leftScale.");
575 }
576 
577 
578 template<class MatrixType>
579 typename OverlappingRowMatrix<MatrixType>::mag_type
581 {
582  throw std::runtime_error("Ifpack2::OverlappingRowMatrix does not support getFrobeniusNorm.");
583 }
584 
585 
586 template<class MatrixType>
587 void
589 apply (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &X,
590  Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &Y,
591  Teuchos::ETransp mode,
592  scalar_type alpha,
593  scalar_type beta) const
594 {
595  using Teuchos::ArrayRCP;
596  using Teuchos::as;
597  typedef scalar_type RangeScalar;
598  typedef scalar_type DomainScalar;
599  typedef Teuchos::ScalarTraits<RangeScalar> STRS;
600 
601  TEUCHOS_TEST_FOR_EXCEPTION(
602  alpha != Teuchos::ScalarTraits<scalar_type>::one () ||
603  beta != Teuchos::ScalarTraits<scalar_type>::zero (), std::logic_error,
604  "Ifpack2::ReorderFilter::apply is only implemented for alpha = 1 and "
605  "beta = 0. You set alpha = " << alpha << " and beta = " << beta << ".");
606  TEUCHOS_TEST_FOR_EXCEPTION(
607  X.getNumVectors() != Y.getNumVectors(), std::runtime_error,
608  "Ifpack2::OverlappingRowMatrix::apply: The input X and the output Y must "
609  "have the same number of columns. X.getNumVectors() = "
610  << X.getNumVectors() << " != Y.getNumVectors() = " << Y.getNumVectors()
611  << ".");
612 
613  // FIXME (mfh 13 July 2013) This would be a good candidate for a
614  // local parallel operator implementation. That would obviate the
615  // need for getting views of the data and make the code below a lot
616  // simpler.
617 
618  const RangeScalar zero = STRS::zero ();
619  ArrayRCP<ArrayRCP<const DomainScalar> > x_ptr = X.get2dView();
620  ArrayRCP<ArrayRCP<RangeScalar> > y_ptr = Y.get2dViewNonConst();
621  Y.putScalar(zero);
622  size_t NumVectors = Y.getNumVectors();
623 
624  const size_t numMyRowsA = A_->getNodeNumRows ();
625  for (size_t i = 0; i < numMyRowsA; ++i) {
626  size_t Nnz;
627  // Use this class's getrow to make the below code simpler
628  A_->getLocalRowCopy (i, Indices_ (),Values_ (), Nnz);
629  if (mode == Teuchos::NO_TRANS) {
630  for (size_t j = 0; j < Nnz; ++j)
631  for (size_t k = 0; k < NumVectors; ++k)
632  y_ptr[k][i] += as<RangeScalar> (Values_[j]) *
633  as<RangeScalar> (x_ptr[k][Indices_[j]]);
634  }
635  else if (mode == Teuchos::TRANS){
636  for (size_t j = 0; j < Nnz; ++j)
637  for (size_t k = 0; k < NumVectors; ++k)
638  y_ptr[k][Indices_[j]] += as<RangeScalar> (Values_[j]) *
639  as<RangeScalar> (x_ptr[k][i]);
640  }
641  else { // mode == Teuchos::CONJ_TRANS
642  for (size_t j = 0; j < Nnz; ++j)
643  for (size_t k = 0; k < NumVectors; ++k)
644  y_ptr[k][Indices_[j]] +=
645  STRS::conjugate (as<RangeScalar> (Values_[j])) *
646  as<RangeScalar> (x_ptr[k][i]);
647  }
648  }
649 
650  const size_t numMyRowsB = ExtMatrix_->getNodeNumRows ();
651  for (size_t i = 0 ; i < numMyRowsB ; ++i) {
652  size_t Nnz;
653  // Use this class's getrow to make the below code simpler
654  ExtMatrix_->getLocalRowCopy (i, Indices_ (), Values_ (), Nnz);
655  if (mode == Teuchos::NO_TRANS) {
656  for (size_t j = 0; j < Nnz; ++j)
657  for (size_t k = 0; k < NumVectors; ++k)
658  y_ptr[k][numMyRowsA+i] += as<RangeScalar> (Values_[j]) *
659  as<RangeScalar> (x_ptr[k][Indices_[j]]);
660  }
661  else if (mode == Teuchos::TRANS) {
662  for (size_t j = 0; j < Nnz; ++j)
663  for (size_t k = 0; k < NumVectors; ++k)
664  y_ptr[k][numMyRowsA+Indices_[j]] += as<RangeScalar> (Values_[j]) *
665  as<RangeScalar> (x_ptr[k][i]);
666  }
667  else { // mode == Teuchos::CONJ_TRANS
668  for (size_t j = 0; j < Nnz; ++j)
669  for (size_t k = 0; k < NumVectors; ++k)
670  y_ptr[k][numMyRowsA+Indices_[j]] +=
671  STRS::conjugate (as<RangeScalar> (Values_[j])) *
672  as<RangeScalar> (x_ptr[k][i]);
673  }
674  }
675 }
676 
677 
678 template<class MatrixType>
679 void
681 importMultiVector (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &X,
682  Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &OvX,
683  Tpetra::CombineMode CM)
684 {
685  OvX.doImport (X, *Importer_, CM);
686 }
687 
688 
689 template<class MatrixType>
690 void
692 exportMultiVector (const Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &OvX,
693  Tpetra::MultiVector<scalar_type,local_ordinal_type,global_ordinal_type,node_type> &X,
694  Tpetra::CombineMode CM)
695 {
696  X.doExport (OvX, *Importer_, CM);
697 }
698 
699 
700 template<class MatrixType>
702 {
703  return true;
704 }
705 
706 
707 template<class MatrixType>
709 {
710  return false;
711 }
712 
713 template<class MatrixType>
715 {
716  std::ostringstream oss;
717  if (isFillComplete()) {
718  oss << "{ isFillComplete: true"
719  << ", global rows: " << getGlobalNumRows()
720  << ", global columns: " << getGlobalNumCols()
721  << ", global entries: " << getGlobalNumEntries()
722  << " }";
723  }
724  else {
725  oss << "{ isFillComplete: false"
726  << ", global rows: " << getGlobalNumRows()
727  << " }";
728  }
729  return oss.str();
730 }
731 
732 template<class MatrixType>
733 void OverlappingRowMatrix<MatrixType>::describe(Teuchos::FancyOStream &out,
734  const Teuchos::EVerbosityLevel verbLevel) const
735 {
736  using std::endl;
737  using std::setw;
738  using Teuchos::as;
739  using Teuchos::VERB_DEFAULT;
740  using Teuchos::VERB_NONE;
741  using Teuchos::VERB_LOW;
742  using Teuchos::VERB_MEDIUM;
743  using Teuchos::VERB_HIGH;
744  using Teuchos::VERB_EXTREME;
745  using Teuchos::RCP;
746  using Teuchos::null;
747  using Teuchos::ArrayView;
748 
749  Teuchos::EVerbosityLevel vl = verbLevel;
750  if (vl == VERB_DEFAULT) {
751  vl = VERB_LOW;
752  }
753  RCP<const Teuchos::Comm<int> > comm = this->getComm();
754  const int myRank = comm->getRank();
755  const int numProcs = comm->getSize();
756  size_t width = 1;
757  for (size_t dec=10; dec<getGlobalNumRows(); dec *= 10) {
758  ++width;
759  }
760  width = std::max<size_t> (width, as<size_t> (11)) + 2;
761  Teuchos::OSTab tab(out);
762  // none: print nothing
763  // low: print O(1) info from node 0
764  // medium: print O(P) info, num entries per process
765  // high: print O(N) info, num entries per row
766  // extreme: print O(NNZ) info: print indices and values
767  //
768  // for medium and higher, print constituent objects at specified verbLevel
769  if (vl != VERB_NONE) {
770  if (myRank == 0) {
771  out << this->description() << std::endl;
772  }
773  // O(1) globals, minus what was already printed by description()
774  //if (isFillComplete() && myRank == 0) {
775  // out << "Global number of diagonal entries: " << getGlobalNumDiags() << std::endl;
776  // out << "Global max number of entries in a row: " << getGlobalMaxNumRowEntries() << std::endl;
777  //}
778  // constituent objects
779  if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
780  if (myRank == 0) {
781  out << endl << "Row map:" << endl;
782  }
783  getRowMap()->describe(out,vl);
784  //
785  if (getColMap() != null) {
786  if (getColMap() == getRowMap()) {
787  if (myRank == 0) {
788  out << endl << "Column map is row map.";
789  }
790  }
791  else {
792  if (myRank == 0) {
793  out << endl << "Column map:" << endl;
794  }
795  getColMap()->describe(out,vl);
796  }
797  }
798  if (getDomainMap() != null) {
799  if (getDomainMap() == getRowMap()) {
800  if (myRank == 0) {
801  out << endl << "Domain map is row map.";
802  }
803  }
804  else if (getDomainMap() == getColMap()) {
805  if (myRank == 0) {
806  out << endl << "Domain map is column map.";
807  }
808  }
809  else {
810  if (myRank == 0) {
811  out << endl << "Domain map:" << endl;
812  }
813  getDomainMap()->describe(out,vl);
814  }
815  }
816  if (getRangeMap() != null) {
817  if (getRangeMap() == getDomainMap()) {
818  if (myRank == 0) {
819  out << endl << "Range map is domain map." << endl;
820  }
821  }
822  else if (getRangeMap() == getRowMap()) {
823  if (myRank == 0) {
824  out << endl << "Range map is row map." << endl;
825  }
826  }
827  else {
828  if (myRank == 0) {
829  out << endl << "Range map: " << endl;
830  }
831  getRangeMap()->describe(out,vl);
832  }
833  }
834  if (myRank == 0) {
835  out << endl;
836  }
837  }
838  // O(P) data
839  if (vl == VERB_MEDIUM || vl == VERB_HIGH || vl == VERB_EXTREME) {
840  for (int curRank = 0; curRank < numProcs; ++curRank) {
841  if (myRank == curRank) {
842  out << "Process rank: " << curRank << std::endl;
843  out << " Number of entries: " << getNodeNumEntries() << std::endl;
844  if (isFillComplete()) {
845  out << " Number of diagonal entries: " << getNodeNumDiags() << std::endl;
846  }
847  out << " Max number of entries per row: " << getNodeMaxNumRowEntries() << std::endl;
848  }
849  comm->barrier();
850  comm->barrier();
851  comm->barrier();
852  }
853  }
854  // O(N) and O(NNZ) data
855  if (vl == VERB_HIGH || vl == VERB_EXTREME) {
856  for (int curRank = 0; curRank < numProcs; ++curRank) {
857  if (myRank == curRank) {
858  out << std::setw(width) << "Proc Rank"
859  << std::setw(width) << "Global Row"
860  << std::setw(width) << "Num Entries";
861  if (vl == VERB_EXTREME) {
862  out << std::setw(width) << "(Index,Value)";
863  }
864  out << endl;
865  for (size_t r = 0; r < getNodeNumRows (); ++r) {
866  const size_t nE = getNumEntriesInLocalRow(r);
867  typename MatrixType::global_ordinal_type gid = getRowMap()->getGlobalElement(r);
868  out << std::setw(width) << myRank
869  << std::setw(width) << gid
870  << std::setw(width) << nE;
871  if (vl == VERB_EXTREME) {
872  if (isGloballyIndexed()) {
873  ArrayView<const typename MatrixType::global_ordinal_type> rowinds;
874  ArrayView<const typename MatrixType::scalar_type> rowvals;
875  getGlobalRowView (gid, rowinds, rowvals);
876  for (size_t j = 0; j < nE; ++j) {
877  out << " (" << rowinds[j]
878  << ", " << rowvals[j]
879  << ") ";
880  }
881  }
882  else if (isLocallyIndexed()) {
883  ArrayView<const typename MatrixType::local_ordinal_type> rowinds;
884  ArrayView<const typename MatrixType::scalar_type> rowvals;
885  getLocalRowView (r, rowinds, rowvals);
886  for (size_t j=0; j < nE; ++j) {
887  out << " (" << getColMap()->getGlobalElement(rowinds[j])
888  << ", " << rowvals[j]
889  << ") ";
890  }
891  } // globally or locally indexed
892  } // vl == VERB_EXTREME
893  out << endl;
894  } // for each row r on this process
895 
896  } // if (myRank == curRank)
897  comm->barrier();
898  comm->barrier();
899  comm->barrier();
900  }
901 
902  out.setOutputToRootOnly(0);
903  out << "===========\nlocal matrix\n=================" << std::endl;
904  out.setOutputToRootOnly(-1);
905  A_->describe(out,Teuchos::VERB_EXTREME);
906  out.setOutputToRootOnly(0);
907  out << "===========\nend of local matrix\n=================" << std::endl;
908  comm->barrier();
909  out.setOutputToRootOnly(0);
910  out << "=================\nghost matrix\n=================" << std::endl;
911  out.setOutputToRootOnly(-1);
912  ExtMatrix_->describe(out,Teuchos::VERB_EXTREME);
913  out.setOutputToRootOnly(0);
914  out << "===========\nend of ghost matrix\n=================" << std::endl;
915  }
916  }
917 }
918 
919 template<class MatrixType>
920 Teuchos::RCP<const Tpetra::RowMatrix<typename MatrixType::scalar_type, typename MatrixType::local_ordinal_type, typename MatrixType::global_ordinal_type, typename MatrixType::node_type> >
922 {
923  return A_;
924 }
925 
926 
927 } // namespace Ifpack2
928 
929 #define IFPACK2_OVERLAPPINGROWMATRIX_INSTANT(S,LO,GO,N) \
930  template class Ifpack2::OverlappingRowMatrix< Tpetra::RowMatrix<S, LO, GO, N> >;
931 
932 #endif // IFPACK2_OVERLAPPINGROWMATRIX_DEF_HPP
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getDomainMap() const
The Map that describes the domain of this matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:269
virtual global_size_t getGlobalNumDiags() const
The global number of diagonal entries.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:379
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRangeMap() const
The Map that describes the range of this matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:285
virtual Teuchos::RCP< const Tpetra::RowGraph< local_ordinal_type, global_ordinal_type, node_type > > getGraph() const
This matrix&#39;s graph.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:293
virtual void getGlobalRowView(global_ordinal_type GlobalRow, Teuchos::ArrayView< const global_ordinal_type > &indices, Teuchos::ArrayView< const scalar_type > &values) const
Extract a const, non-persisting view of global indices in a specified row of the matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:491
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getColMap() const
The Map that describes the distribution of columns over processes.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:260
virtual bool hasTransposeApply() const
Whether this operator&#39;s apply() method can apply the adjoint (transpose).
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:701
virtual mag_type getFrobeniusNorm() const
Returns the Frobenius norm of the matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:580
virtual size_t getNumEntriesInGlobalRow(global_ordinal_type globalRow) const
The number of entries in the given global row that are owned by the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:352
virtual Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
The communicator over which the matrix is distributed.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:235
virtual bool isUpperTriangular() const
Whether this matrix is upper triangular.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:421
virtual bool isLocallyIndexed() const
Whether this matrix is locally indexed.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:428
virtual global_size_t getGlobalNumCols() const
The global number of columns in this matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:307
virtual void leftScale(const Tpetra::Vector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &x)
Scales the RowMatrix on the left with the Vector x.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:563
virtual bool isFillComplete() const
true if fillComplete() has been called, else false.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:442
virtual bool isGloballyIndexed() const
Whether this matrix is globally indexed.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:435
virtual Teuchos::RCP< const Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > > getRowMap() const
The Map that describes the distribution of rows over processes.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:251
virtual bool hasColMap() const
Whether this matrix has a column Map.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:407
virtual Teuchos::RCP< node_type > getNode() const
The matrix&#39;s Node instance.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:243
virtual bool isLowerTriangular() const
Whether this matrix is lower triangular.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:414
virtual size_t getNodeNumEntries() const
The number of entries in this matrix owned by the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:343
virtual void getLocalRowView(local_ordinal_type LocalRow, Teuchos::ArrayView< const local_ordinal_type > &indices, Teuchos::ArrayView< const scalar_type > &values) const
Extract a const, non-persisting view of local indices in a specified row of the matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:512
virtual void getLocalRowCopy(local_ordinal_type LocalRow, const Teuchos::ArrayView< local_ordinal_type > &Indices, const Teuchos::ArrayView< scalar_type > &Values, size_t &NumEntries) const
Extract a list of entries in a specified local row of the graph. Put into storage allocated by callin...
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:472
virtual bool supportsRowViews() const
true if row views are supported, else false.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:708
Sparse graph (Tpetra::RowGraph subclass) with ghost rows.
Definition: Ifpack2_Details_OverlappingRowGraph_decl.hpp:65
virtual size_t getNodeNumCols() const
The number of columns owned by the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:321
virtual size_t getGlobalMaxNumRowEntries() const
The maximum number of entries in any row on any process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:393
~OverlappingRowMatrix()
Destructor.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:230
virtual void rightScale(const Tpetra::Vector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &x)
Scales the RowMatrix on the right with the Vector x.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:572
virtual size_t getNodeNumDiags() const
The number of diagonal entries owned by the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:386
Sparse matrix (Tpetra::RowMatrix subclass) with ghost rows.
Definition: Ifpack2_OverlappingRowMatrix_decl.hpp:59
virtual size_t getNodeMaxNumRowEntries() const
The maximum number of entries in any row on the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:400
OverlappingRowMatrix(const Teuchos::RCP< const row_matrix_type > &A, const int overlapLevel)
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:57
virtual size_t getNodeNumRows() const
The number of rows owned by the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:314
virtual void apply(const Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &X, Tpetra::MultiVector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, scalar_type alpha=Teuchos::ScalarTraits< scalar_type >::one(), scalar_type beta=Teuchos::ScalarTraits< scalar_type >::zero()) const
Computes the operator-multivector application.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:589
Preconditioners and smoothers for Tpetra sparse matrices.
Definition: Ifpack2_AdditiveSchwarz_decl.hpp:72
virtual global_size_t getGlobalNumEntries() const
The global number of entries in this matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:336
virtual void getGlobalRowCopy(global_ordinal_type GlobalRow, const Teuchos::ArrayView< global_ordinal_type > &Indices, const Teuchos::ArrayView< scalar_type > &Values, size_t &NumEntries) const
Extract a list of entries in a specified global row of this matrix. Put into pre-allocated storage...
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:451
virtual size_t getNumEntriesInLocalRow(local_ordinal_type localRow) const
The number of entries in the given local row that are owned by the calling process.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:366
virtual global_ordinal_type getIndexBase() const
The index base for global indices for this matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:329
virtual global_size_t getGlobalNumRows() const
The global number of rows in this matrix.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:300
virtual void getLocalDiagCopy(Tpetra::Vector< scalar_type, local_ordinal_type, global_ordinal_type, node_type > &diag) const
Get a copy of the diagonal entries owned by this node, with local row indices.
Definition: Ifpack2_OverlappingRowMatrix_def.hpp:530