Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AnasaziTpetraAdapter.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Anasazi: Block Eigensolvers Package
4 //
5 // Copyright 2004 NTESS and the Anasazi contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef ANASAZI_TPETRA_ADAPTER_HPP
11 #define ANASAZI_TPETRA_ADAPTER_HPP
12 
49 
50 #include <Tpetra_MultiVector.hpp>
51 #include <Tpetra_Operator.hpp>
52 
53 #include <Teuchos_Array.hpp>
54 #include <Teuchos_Assert.hpp>
55 #include <Teuchos_DefaultSerialComm.hpp>
56 #include <Teuchos_CommHelpers.hpp>
57 #include <Teuchos_ScalarTraits.hpp>
58 #include <Teuchos_FancyOStream.hpp>
59 
60 #include <AnasaziConfigDefs.hpp>
61 #include <AnasaziTypes.hpp>
65 
66 #ifdef HAVE_ANASAZI_TSQR
67 # include <Tpetra_TsqrAdaptor.hpp>
68 #endif // HAVE_ANASAZI_TSQR
69 
70 
71 namespace Anasazi {
72 
84  template<class Scalar, class LO, class GO, class Node>
85  class MultiVecTraits<Scalar, Tpetra::MultiVector<Scalar,LO,GO,Node> > {
86  typedef Tpetra::MultiVector<Scalar, LO, GO, Node> MV;
87  public:
93  static Teuchos::RCP<MV> Clone (const MV& X, const int numVecs) {
94  Teuchos::RCP<MV> Y (new MV (X.getMap (), numVecs, false));
95  Y->setCopyOrView (Teuchos::View);
96  return Y;
97  }
98 
100  static Teuchos::RCP<MV> CloneCopy (const MV& X)
101  {
102  // Make a deep copy of X. The one-argument copy constructor
103  // does a shallow copy by default; the second argument tells it
104  // to do a deep copy.
105  Teuchos::RCP<MV> X_copy (new MV (X, Teuchos::Copy));
106  // Make Tpetra::MultiVector use the new view semantics. This is
107  // a no-op for the Kokkos refactor version of Tpetra; it only
108  // does something for the "classic" version of Tpetra. This
109  // shouldn't matter because Belos only handles MV through RCP
110  // and through this interface anyway, but it doesn't hurt to set
111  // it and make sure that it works.
112  X_copy->setCopyOrView (Teuchos::View);
113  return X_copy;
114  }
115 
127  static Teuchos::RCP<MV>
128  CloneCopy (const MV& mv, const std::vector<int>& index)
129  {
130 #ifdef HAVE_TPETRA_DEBUG
131  const char fnName[] = "Anasazi::MultiVecTraits::CloneCopy(mv,index)";
132  const size_t inNumVecs = mv.getNumVectors ();
134  index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
135  std::runtime_error, fnName << ": All indices must be nonnegative.");
137  index.size () > 0 &&
138  static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= inNumVecs,
139  std::runtime_error,
140  fnName << ": All indices must be strictly less than the number of "
141  "columns " << inNumVecs << " of the input multivector mv.");
142 #endif // HAVE_TPETRA_DEBUG
143 
144  // Tpetra wants an array of size_t, not of int.
145  Teuchos::Array<size_t> columns (index.size ());
146  for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
147  columns[j] = index[j];
148  }
149  // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
150  // continuous column index range in MultiVector::subCopy, so we
151  // don't have to check here.
152  Teuchos::RCP<MV> X_copy = mv.subCopy (columns ());
153  X_copy->setCopyOrView (Teuchos::View);
154  return X_copy;
155  }
156 
163  static Teuchos::RCP<MV>
164  CloneCopy (const MV& mv, const Teuchos::Range1D& index)
165  {
166  const bool validRange = index.size() > 0 &&
167  index.lbound() >= 0 &&
168  index.ubound() < GetNumberVecs(mv);
169  if (! validRange) { // invalid range; generate error message
170  std::ostringstream os;
171  os << "Anasazi::MultiVecTraits::CloneCopy(mv,index=["
172  << index.lbound() << "," << index.ubound() << "]): ";
174  index.size() == 0, std::invalid_argument,
175  os.str() << "Empty index range is not allowed.");
177  index.lbound() < 0, std::invalid_argument,
178  os.str() << "Index range includes negative index/ices, which is not "
179  "allowed.");
181  index.ubound() >= GetNumberVecs(mv), std::invalid_argument,
182  os.str() << "Index range exceeds number of vectors "
183  << mv.getNumVectors() << " in the input multivector.");
184  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
185  os.str() << "Should never get here!");
186  }
187  Teuchos::RCP<MV> X_copy = mv.subCopy (index);
188  X_copy->setCopyOrView (Teuchos::View);
189  return X_copy;
190  }
191 
192  static Teuchos::RCP<MV>
193  CloneViewNonConst (MV& mv, const std::vector<int>& index)
194  {
195 #ifdef HAVE_TPETRA_DEBUG
196  const char fnName[] = "Anasazi::MultiVecTraits::CloneViewNonConst(mv,index)";
197  const size_t numVecs = mv.getNumVectors ();
199  index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
200  std::invalid_argument,
201  fnName << ": All indices must be nonnegative.");
203  index.size () > 0 &&
204  static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
205  std::invalid_argument,
206  fnName << ": All indices must be strictly less than the number of "
207  "columns " << numVecs << " in the input MultiVector mv.");
208 #endif // HAVE_TPETRA_DEBUG
209 
210  // Tpetra wants an array of size_t, not of int.
211  Teuchos::Array<size_t> columns (index.size ());
212  for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
213  columns[j] = index[j];
214  }
215  // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
216  // continuous column index range in
217  // MultiVector::subViewNonConst, so we don't have to check here.
218  Teuchos::RCP<MV> X_view = mv.subViewNonConst (columns ());
219  X_view->setCopyOrView (Teuchos::View);
220  return X_view;
221  }
222 
223  static Teuchos::RCP<MV>
224  CloneViewNonConst (MV& mv, const Teuchos::Range1D& index)
225  {
226  // NOTE (mfh 11 Jan 2011) We really should check for possible
227  // overflow of int here. However, the number of columns in a
228  // multivector typically fits in an int.
229  const int numCols = static_cast<int> (mv.getNumVectors());
230  const bool validRange = index.size() > 0 &&
231  index.lbound() >= 0 && index.ubound() < numCols;
232  if (! validRange) {
233  std::ostringstream os;
234  os << "Belos::MultiVecTraits::CloneViewNonConst(mv,index=["
235  << index.lbound() << ", " << index.ubound() << "]): ";
237  index.size() == 0, std::invalid_argument,
238  os.str() << "Empty index range is not allowed.");
240  index.lbound() < 0, std::invalid_argument,
241  os.str() << "Index range includes negative inde{x,ices}, which is "
242  "not allowed.");
244  index.ubound() >= numCols, std::invalid_argument,
245  os.str() << "Index range exceeds number of vectors " << numCols
246  << " in the input multivector.");
248  true, std::logic_error,
249  os.str() << "Should never get here!");
250  }
251  Teuchos::RCP<MV> X_view = mv.subViewNonConst (index);
252  X_view->setCopyOrView (Teuchos::View);
253  return X_view;
254  }
255 
257  CloneView (const MV& mv, const std::vector<int>& index)
258  {
259 #ifdef HAVE_TPETRA_DEBUG
260  const char fnName[] = "Belos::MultiVecTraits<Scalar, "
261  "Tpetra::MultiVector<...> >::CloneView(mv,index)";
262  const size_t numVecs = mv.getNumVectors ();
264  *std::min_element (index.begin (), index.end ()) < 0,
265  std::invalid_argument,
266  fnName << ": All indices must be nonnegative.");
268  static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
269  std::invalid_argument,
270  fnName << ": All indices must be strictly less than the number of "
271  "columns " << numVecs << " in the input MultiVector mv.");
272 #endif // HAVE_TPETRA_DEBUG
273 
274  // Tpetra wants an array of size_t, not of int.
275  Teuchos::Array<size_t> columns (index.size ());
276  for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
277  columns[j] = index[j];
278  }
279  // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
280  // continuous column index range in MultiVector::subView, so we
281  // don't have to check here.
282  Teuchos::RCP<const MV> X_view = mv.subView (columns);
283  Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
284  return X_view;
285  }
286 
288  CloneView (const MV& mv, const Teuchos::Range1D& index)
289  {
290  // NOTE (mfh 11 Jan 2011) We really should check for possible
291  // overflow of int here. However, the number of columns in a
292  // multivector typically fits in an int.
293  const int numCols = static_cast<int> (mv.getNumVectors());
294  const bool validRange = index.size() > 0 &&
295  index.lbound() >= 0 && index.ubound() < numCols;
296  if (! validRange) {
297  std::ostringstream os;
298  os << "Anasazi::MultiVecTraits::CloneView(mv, index=["
299  << index.lbound () << ", " << index.ubound() << "]): ";
300  TEUCHOS_TEST_FOR_EXCEPTION(index.size() == 0, std::invalid_argument,
301  os.str() << "Empty index range is not allowed.");
302  TEUCHOS_TEST_FOR_EXCEPTION(index.lbound() < 0, std::invalid_argument,
303  os.str() << "Index range includes negative index/ices, which is not "
304  "allowed.");
306  index.ubound() >= numCols, std::invalid_argument,
307  os.str() << "Index range exceeds number of vectors " << numCols
308  << " in the input multivector.");
309  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
310  os.str() << "Should never get here!");
311  }
312  Teuchos::RCP<const MV> X_view = mv.subView (index);
313  Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
314  return X_view;
315  }
316 
317  static ptrdiff_t GetGlobalLength( const MV& mv ) {
318  return static_cast<ptrdiff_t> (mv.getGlobalLength ());
319  }
320 
321  static int GetNumberVecs (const MV& mv) {
322  return static_cast<int> (mv.getNumVectors ());
323  }
324 
325  static void
326  MvTimesMatAddMv (Scalar alpha,
327  const MV& A,
329  Scalar beta,
330  MV& mv)
331  {
332  using Teuchos::ArrayView;
333  using Teuchos::Comm;
334  using Teuchos::rcpFromRef;
335  typedef Tpetra::Map<LO, GO, Node> map_type;
336 
337 #ifdef HAVE_ANASAZI_TPETRA_TIMERS
338  const std::string timerName ("Anasazi::MVT::MvTimesMatAddMv");
341  if (timer.is_null ()) {
342  timer = Teuchos::TimeMonitor::getNewCounter (timerName);
343  }
345  timer.is_null (), std::logic_error,
346  "Anasazi::MultiVecTraits::MvTimesMatAddMv: "
347  "Failed to look up timer \"" << timerName << "\". "
348  "Please report this bug to the Belos developers.");
349 
350  // This starts the timer. It will be stopped on scope exit.
351  Teuchos::TimeMonitor timeMon (*timer);
352 #endif
353 
354  // Check if B is 1-by-1, in which case we can just call update()
355  if (B.numRows () == 1 && B.numCols () == 1) {
356  mv.update (alpha*B(0,0), A, beta);
357  return;
358  }
359 
360  // Create local map
361  Teuchos::SerialComm<int> serialComm;
362  map_type LocalMap (B.numRows (), A.getMap ()->getIndexBase (),
363  rcpFromRef<const Comm<int> > (serialComm),
364  Tpetra::LocallyReplicated);
365  // encapsulate Teuchos::SerialDenseMatrix data in ArrayView
366  ArrayView<const Scalar> Bvalues (B.values (), B.stride () * B.numCols ());
367  // create locally replicated MultiVector with a copy of this data
368  MV B_mv (rcpFromRef (LocalMap), Bvalues, B.stride (), B.numCols ());
369  mv.multiply (Teuchos::NO_TRANS, Teuchos::NO_TRANS, alpha, A, B_mv, beta);
370  }
371 
379  static void
380  MvAddMv (Scalar alpha,
381  const MV& A,
382  Scalar beta,
383  const MV& B,
384  MV& mv)
385  {
386  mv.update (alpha, A, beta, B, Teuchos::ScalarTraits<Scalar>::zero ());
387  }
388 
389  static void MvScale (MV& mv, Scalar alpha) {
390  mv.scale (alpha);
391  }
392 
393  static void MvScale (MV& mv, const std::vector<Scalar>& alphas) {
394  mv.scale (alphas);
395  }
396 
397  static void
398  MvTransMv (const Scalar alpha,
399  const MV& A,
400  const MV& B,
402  {
403  using Tpetra::LocallyReplicated;
404  using Teuchos::Comm;
405  using Teuchos::RCP;
406  using Teuchos::rcp;
407  using Teuchos::TimeMonitor;
408  typedef Tpetra::Map<LO,GO,Node> map_type;
409 
410 #ifdef HAVE_ANASAZI_TPETRA_TIMERS
411  const std::string timerName ("Anasazi::MVT::MvTransMv");
412  RCP<Teuchos::Time> timer = TimeMonitor::lookupCounter (timerName);
413  if (timer.is_null ()) {
414  timer = TimeMonitor::getNewCounter (timerName);
415  }
417  timer.is_null (), std::logic_error, "Anasazi::MvTransMv: "
418  "Failed to look up timer \"" << timerName << "\". "
419  "Please report this bug to the Belos developers.");
420 
421  // This starts the timer. It will be stopped on scope exit.
422  TimeMonitor timeMon (*timer);
423 #endif // HAVE_ANASAZI_TPETRA_TIMERS
424 
425  // Form alpha * A^H * B, then copy into the SerialDenseMatrix.
426  // We will create a multivector C_mv from a a local map. This
427  // map has a serial comm, the purpose being to short-circuit the
428  // MultiVector::reduce() call at the end of
429  // MultiVector::multiply(). Otherwise, the reduced multivector
430  // data would be copied back to the GPU, only to turn around and
431  // have to get it back here. This saves us a round trip for
432  // this data.
433  const int numRowsC = C.numRows ();
434  const int numColsC = C.numCols ();
435  const int strideC = C.stride ();
436 
437  // Check if numRowsC == numColsC == 1, in which case we can call dot()
438  if (numRowsC == 1 && numColsC == 1) {
439  if (alpha == Teuchos::ScalarTraits<Scalar>::zero ()) {
440  // Short-circuit, as required by BLAS semantics.
441  C(0,0) = alpha;
442  return;
443  }
444  A.dot (B, Teuchos::ArrayView<Scalar> (C.values (), 1));
445  if (alpha != Teuchos::ScalarTraits<Scalar>::one ()) {
446  C(0,0) *= alpha;
447  }
448  return;
449  }
450 
451  // get comm
452  RCP<const Comm<int> > pcomm = A.getMap ()->getComm ();
453 
454  // create local map with comm
455  RCP<const map_type> LocalMap =
456  rcp (new map_type (numRowsC, 0, pcomm, LocallyReplicated));
457  // create local multivector to hold the result
458  const bool INIT_TO_ZERO = true;
459  MV C_mv (LocalMap, numColsC, INIT_TO_ZERO);
460 
461  // multiply result into local multivector
462  C_mv.multiply (Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, alpha, A, B,
464 
465  // create arrayview encapsulating the Teuchos::SerialDenseMatrix
466  Teuchos::ArrayView<Scalar> C_view (C.values (), strideC * numColsC);
467 
468  // No accumulation to do; simply extract the multivector data
469  // into C. Extract a copy of the result into the array view
470  // (and therefore, the SerialDenseMatrix).
471  C_mv.get1dCopy (C_view, strideC);
472  }
473 
475  static void
476  MvDot (const MV& A, const MV& B, std::vector<Scalar> &dots)
477  {
478  const size_t numVecs = A.getNumVectors ();
480  numVecs != B.getNumVectors (), std::invalid_argument,
481  "Anasazi::MultiVecTraits::MvDot(A,B,dots): "
482  "A and B must have the same number of columns. "
483  "A has " << numVecs << " column(s), "
484  "but B has " << B.getNumVectors () << " column(s).");
485 #ifdef HAVE_TPETRA_DEBUG
487  dots.size() < numVecs, std::invalid_argument,
488  "Anasazi::MultiVecTraits::MvDot(A,B,dots): "
489  "The output array 'dots' must have room for all dot products. "
490  "A and B each have " << numVecs << " column(s), "
491  "but 'dots' only has " << dots.size() << " entry(/ies).");
492 #endif // HAVE_TPETRA_DEBUG
493 
494  Teuchos::ArrayView<Scalar> av (dots);
495  A.dot (B, av (0, numVecs));
496  }
497 
499  static void
500  MvNorm (const MV& mv,
501  std::vector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &normvec)
502  {
503  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
504 #ifdef HAVE_TPETRA_DEBUG
506  normvec.size () < static_cast<std::vector<int>::size_type> (mv.getNumVectors ()),
507  std::invalid_argument,
508  "Anasazi::MultiVecTraits::MvNorm(mv,normvec): The normvec output "
509  "argument must have at least as many entries as the number of vectors "
510  "(columns) in the MultiVector mv. normvec.size() = " << normvec.size ()
511  << " < mv.getNumVectors() = " << mv.getNumVectors () << ".");
512 #endif // HAVE_TPETRA_DEBUG
514  mv.norm2 (av (0, mv.getNumVectors ()));
515  }
516 
517  static void
518  SetBlock (const MV& A, const std::vector<int>& index, MV& mv)
519  {
520  using Teuchos::Range1D;
521  using Teuchos::RCP;
522  const size_t inNumVecs = A.getNumVectors ();
523 #ifdef HAVE_TPETRA_DEBUG
525  inNumVecs < static_cast<size_t> (index.size ()), std::invalid_argument,
526  "Anasazi::MultiVecTraits::SetBlock(A,index,mv): 'index' argument must "
527  "have no more entries as the number of columns in the input MultiVector"
528  " A. A.getNumVectors() = " << inNumVecs << " < index.size () = "
529  << index.size () << ".");
530 #endif // HAVE_TPETRA_DEBUG
531  RCP<MV> mvsub = CloneViewNonConst (mv, index);
532  if (inNumVecs > static_cast<size_t> (index.size ())) {
533  RCP<const MV> Asub = A.subView (Range1D (0, index.size () - 1));
534  Tpetra::deep_copy (*mvsub, *Asub);
535  } else {
536  Tpetra::deep_copy (*mvsub, A);
537  }
538  }
539 
540  static void
541  SetBlock (const MV& A, const Teuchos::Range1D& index, MV& mv)
542  {
543  // Range1D bounds are signed; size_t is unsigned.
544  // Assignment of Tpetra::MultiVector is a deep copy.
545 
546  // Tpetra::MultiVector::getNumVectors() returns size_t. It's
547  // fair to assume that the number of vectors won't overflow int,
548  // since the typical use case of multivectors involves few
549  // columns, but it's friendly to check just in case.
550  const size_t maxInt =
551  static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
552  const bool overflow =
553  maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
554  if (overflow) {
555  std::ostringstream os;
556  os << "Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
557  << ", " << index.ubound () << "], mv): ";
559  maxInt < A.getNumVectors (), std::range_error, os.str () << "Number "
560  "of columns (size_t) in the input MultiVector 'A' overflows int.");
562  maxInt < mv.getNumVectors (), std::range_error, os.str () << "Number "
563  "of columns (size_t) in the output MultiVector 'mv' overflows int.");
564  }
565  // We've already validated the static casts above.
566  const int numColsA = static_cast<int> (A.getNumVectors ());
567  const int numColsMv = static_cast<int> (mv.getNumVectors ());
568  // 'index' indexes into mv; it's the index set of the target.
569  const bool validIndex =
570  index.lbound () >= 0 && index.ubound () < numColsMv;
571  // We can't take more columns out of A than A has.
572  const bool validSource = index.size () <= numColsA;
573 
574  if (! validIndex || ! validSource) {
575  std::ostringstream os;
576  os << "Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
577  << ", " << index.ubound () << "], mv): ";
579  index.lbound() < 0, std::invalid_argument,
580  os.str() << "Range lower bound must be nonnegative.");
582  index.ubound() >= numColsMv, std::invalid_argument,
583  os.str() << "Range upper bound must be less than the number of "
584  "columns " << numColsA << " in the 'mv' output argument.");
586  index.size() > numColsA, std::invalid_argument,
587  os.str() << "Range must have no more elements than the number of "
588  "columns " << numColsA << " in the 'A' input argument.");
590  true, std::logic_error, "Should never get here!");
591  }
592 
593  // View of the relevant column(s) of the target multivector mv.
594  // We avoid view creation overhead by only creating a view if
595  // the index range is different than [0, (# columns in mv) - 1].
596  Teuchos::RCP<MV> mv_view;
597  if (index.lbound () == 0 && index.ubound () + 1 == numColsMv) {
598  mv_view = Teuchos::rcpFromRef (mv); // Non-const, non-owning RCP
599  } else {
600  mv_view = CloneViewNonConst (mv, index);
601  }
602 
603  // View of the relevant column(s) of the source multivector A.
604  // If A has fewer columns than mv_view, then create a view of
605  // the first index.size() columns of A.
606  Teuchos::RCP<const MV> A_view;
607  if (index.size () == numColsA) {
608  A_view = Teuchos::rcpFromRef (A); // Const, non-owning RCP
609  } else {
610  A_view = CloneView (A, Teuchos::Range1D (0, index.size () - 1));
611  }
612 
613  Tpetra::deep_copy (*mv_view, *A_view);
614  }
615 
616  static void Assign (const MV& A, MV& mv)
617  {
618  const char errPrefix[] = "Anasazi::MultiVecTraits::Assign(A, mv): ";
619 
620  // Range1D bounds are signed; size_t is unsigned.
621  // Assignment of Tpetra::MultiVector is a deep copy.
622 
623  // Tpetra::MultiVector::getNumVectors() returns size_t. It's
624  // fair to assume that the number of vectors won't overflow int,
625  // since the typical use case of multivectors involves few
626  // columns, but it's friendly to check just in case.
627  const size_t maxInt =
628  static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
629  const bool overflow =
630  maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
631  if (overflow) {
633  maxInt < A.getNumVectors(), std::range_error,
634  errPrefix << "Number of columns in the input multivector 'A' "
635  "(a size_t) overflows int.");
637  maxInt < mv.getNumVectors(), std::range_error,
638  errPrefix << "Number of columns in the output multivector 'mv' "
639  "(a size_t) overflows int.");
641  true, std::logic_error, "Should never get here!");
642  }
643  // We've already validated the static casts above.
644  const int numColsA = static_cast<int> (A.getNumVectors ());
645  const int numColsMv = static_cast<int> (mv.getNumVectors ());
646  if (numColsA > numColsMv) {
648  numColsA > numColsMv, std::invalid_argument,
649  errPrefix << "Input multivector 'A' has " << numColsA << " columns, "
650  "but output multivector 'mv' has only " << numColsMv << " columns.");
651  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Should never get here!");
652  }
653  if (numColsA == numColsMv) {
654  Tpetra::deep_copy (mv, A);
655  } else {
656  Teuchos::RCP<MV> mv_view =
657  CloneViewNonConst (mv, Teuchos::Range1D (0, numColsA - 1));
658  Tpetra::deep_copy (*mv_view, A);
659  }
660  }
661 
662  static void MvRandom (MV& mv) {
663  mv.randomize ();
664  }
665 
666  static void
667  MvInit (MV& mv, const Scalar alpha = Teuchos::ScalarTraits<Scalar>::zero ())
668  {
669  mv.putScalar (alpha);
670  }
671 
672  static void MvPrint (const MV& mv, std::ostream& os) {
673  Teuchos::FancyOStream fos (Teuchos::rcpFromRef (os));
674  mv.describe (fos, Teuchos::VERB_EXTREME);
675  }
676 
677 #ifdef HAVE_ANASAZI_TSQR
678  typedef Tpetra::TsqrAdaptor<Tpetra::MultiVector<Scalar, LO, GO, Node> > tsqr_adaptor_type;
681 #endif // HAVE_ANASAZI_TSQR
682  };
683 
684 
686  template <class Scalar, class LO, class GO, class Node>
687  class OperatorTraits<Scalar,
688  Tpetra::MultiVector<Scalar,LO,GO,Node>,
689  Tpetra::Operator<Scalar,LO,GO,Node> >
690  {
691  public:
692  static void
693  Apply (const Tpetra::Operator<Scalar,LO,GO,Node>& Op,
694  const Tpetra::MultiVector<Scalar,LO,GO,Node>& X,
695  Tpetra::MultiVector<Scalar,LO,GO,Node>& Y)
696  {
697  Op.apply (X, Y, Teuchos::NO_TRANS);
698  }
699  };
700 
701 
702 template<class ST, class LO, class GO, class NT>
703 struct OutputStreamTraits<Tpetra::Operator<ST, LO, GO, NT> > {
704  typedef Tpetra::Operator<ST, LO, GO, NT> operator_type;
705 
707  getOutputStream (const operator_type& op, int rootRank = 0)
708  {
709  Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout));
710  Teuchos::RCP<const Teuchos::Comm<int> > comm = (op.getDomainMap())->getComm ();
711 
712  // Select minimum MPI rank as the root rank for printing.
713  const int myRank = comm.is_null () ? 0 : comm->getRank ();
714  const int numProcs = comm.is_null () ? 1 : comm->getSize ();
715  if (rootRank < 0)
716  {
717  Teuchos::reduceAll(*comm,Teuchos::REDUCE_SUM,1,&myRank,&rootRank);
718  }
719 
720  // This is irreversible, but that's only a problem if the input std::ostream
721  // is actually a Teuchos::FancyOStream on which this method has been
722  // called before, with a different root rank.
723  fos->setProcRankAndSize (myRank, numProcs);
724  fos->setOutputToRootOnly (rootRank);
725  return fos;
726  }
727 };
728 
729 
730 } // end of Anasazi namespace
731 
732 #endif
733 // end of file ANASAZI_TPETRA_ADAPTER_HPP
ScalarType * values() const
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
basic_FancyOStream & setProcRankAndSize(const int procRank, const int numProcs)
static void MvDot(const MV &A, const MV &B, std::vector< Scalar > &dots)
For all columns j of A, set dots[j] := A[j]^T * B[j].
static void MvInit(MV &mv, const ScalarType alpha=Teuchos::ScalarTraits< ScalarType >::zero())
Replace each element of the vectors in mv with alpha.
static void MvRandom(MV &mv)
Replace the vectors in mv with random vectors.
static void MvTimesMatAddMv(const ScalarType alpha, const MV &A, const Teuchos::SerialDenseMatrix< int, ScalarType > &B, const ScalarType beta, MV &mv)
Update mv with .
static Teuchos::RCP< MV > Clone(const MV &X, const int numVecs)
Create a new MultiVector with numVecs columns.
static void MvAddMv(Scalar alpha, const MV &A, Scalar beta, const MV &B, MV &mv)
mv := alpha*A + beta*B
Declaration of basic traits for the multivector type.
static RCP< Time > getNewCounter(const std::string &name)
static RCP< Time > lookupCounter(const std::string &name)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Virtual base class which defines basic traits for the operator type.
static void Apply(const OP &Op, const MV &x, MV &y)
Application method which performs operation y = Op*x. An OperatorError exception is thrown if there i...
static void Assign(const MV &A, MV &mv)
mv := A
Output managers remove the need for the eigensolver to know any information about the required output...
static Teuchos::RCP< MV > CloneCopy(const MV &mv, const std::vector< int > &index)
Create and return a deep copy of the given columns of mv.
Ordinal ubound() const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
static void MvNorm(const MV &mv, std::vector< typename Teuchos::ScalarTraits< Scalar >::magnitudeType > &normvec)
For all columns j of mv, set normvec[j] = norm(mv[j]).
static Teuchos::RCP< MV > CloneCopy(const MV &X)
Create and return a deep copy of X.
Traits class which defines basic operations on multivectors.
static void MvTransMv(const ScalarType alpha, const MV &A, const MV &B, Teuchos::SerialDenseMatrix< int, ScalarType > &C)
Compute C := alpha * A^H B.
Virtual base class which defines basic traits for the operator type.
static void MvScale(MV &mv, const ScalarType alpha)
Scale each element of the vectors in mv with alpha.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
Creates a new MV that shares the selected contents of mv (shallow copy).
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
Creates a new const MV that shares the selected contents of mv (shallow copy).
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index...
static int GetNumberVecs(const MV &mv)
Obtain the number of vectors in mv.
Ordinal lbound() const
OrdinalType numCols() const
Ordinal size() const
Types and exceptions used within Anasazi solvers and interfaces.
Abstract class definition for Anasazi output stream.
static void MvPrint(const MV &mv, std::ostream &os)
Print the mv multi-vector to the os output stream.
Anasazi&#39;s templated virtual class for constructing an operator that can interface with the OperatorTr...
static Teuchos::RCP< MV > CloneCopy(const MV &mv, const Teuchos::Range1D &index)
Create and return a deep copy of the given columns of mv.
OrdinalType stride() const
OrdinalType numRows() const
bool is_null() const