Anasazi  Version of the Day
AnasaziTpetraAdapter.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Anasazi: Block Eigensolvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef ANASAZI_TPETRA_ADAPTER_HPP
43 #define ANASAZI_TPETRA_ADAPTER_HPP
44 
81 
82 #include <Tpetra_MultiVector.hpp>
83 #include <Tpetra_Operator.hpp>
84 
85 #include <Teuchos_Array.hpp>
86 #include <Teuchos_Assert.hpp>
87 #include <Teuchos_DefaultSerialComm.hpp>
88 #include <Teuchos_ScalarTraits.hpp>
89 
90 #include <AnasaziConfigDefs.hpp>
91 #include <AnasaziTypes.hpp>
94 
95 #ifdef HAVE_ANASAZI_TSQR
96 # include <Tpetra_TsqrAdaptor.hpp>
97 #endif // HAVE_ANASAZI_TSQR
98 
99 
100 namespace Anasazi {
101 
113  template<class Scalar, class LO, class GO, class Node>
114  class MultiVecTraits<Scalar, Tpetra::MultiVector<Scalar,LO,GO,Node> > {
115  typedef Tpetra::MultiVector<Scalar, LO, GO, Node> MV;
116  public:
122  static Teuchos::RCP<MV> Clone (const MV& X, const int numVecs) {
123  Teuchos::RCP<MV> Y (new MV (X.getMap (), numVecs, false));
124  Y->setCopyOrView (Teuchos::View);
125  return Y;
126  }
127 
129  static Teuchos::RCP<MV> CloneCopy (const MV& X)
130  {
131  // Make a deep copy of X. The one-argument copy constructor
132  // does a shallow copy by default; the second argument tells it
133  // to do a deep copy.
134  Teuchos::RCP<MV> X_copy (new MV (X, Teuchos::Copy));
135  // Make Tpetra::MultiVector use the new view semantics. This is
136  // a no-op for the Kokkos refactor version of Tpetra; it only
137  // does something for the "classic" version of Tpetra. This
138  // shouldn't matter because Belos only handles MV through RCP
139  // and through this interface anyway, but it doesn't hurt to set
140  // it and make sure that it works.
141  X_copy->setCopyOrView (Teuchos::View);
142  return X_copy;
143  }
144 
156  static Teuchos::RCP<MV>
157  CloneCopy (const MV& mv, const std::vector<int>& index)
158  {
159 #ifdef HAVE_TPETRA_DEBUG
160  const char fnName[] = "Anasazi::MultiVecTraits::CloneCopy(mv,index)";
161  const size_t inNumVecs = mv.getNumVectors ();
162  TEUCHOS_TEST_FOR_EXCEPTION(
163  index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
164  std::runtime_error, fnName << ": All indices must be nonnegative.");
165  TEUCHOS_TEST_FOR_EXCEPTION(
166  index.size () > 0 &&
167  static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= inNumVecs,
168  std::runtime_error,
169  fnName << ": All indices must be strictly less than the number of "
170  "columns " << inNumVecs << " of the input multivector mv.");
171 #endif // HAVE_TPETRA_DEBUG
172 
173  // Tpetra wants an array of size_t, not of int.
174  Teuchos::Array<size_t> columns (index.size ());
175  for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
176  columns[j] = index[j];
177  }
178  // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
179  // continuous column index range in MultiVector::subCopy, so we
180  // don't have to check here.
181  Teuchos::RCP<MV> X_copy = mv.subCopy (columns ());
182  X_copy->setCopyOrView (Teuchos::View);
183  return X_copy;
184  }
185 
192  static Teuchos::RCP<MV>
193  CloneCopy (const MV& mv, const Teuchos::Range1D& index)
194  {
195  const bool validRange = index.size() > 0 &&
196  index.lbound() >= 0 &&
197  index.ubound() < GetNumberVecs(mv);
198  if (! validRange) { // invalid range; generate error message
199  std::ostringstream os;
200  os << "Anasazi::MultiVecTraits::CloneCopy(mv,index=["
201  << index.lbound() << "," << index.ubound() << "]): ";
202  TEUCHOS_TEST_FOR_EXCEPTION(
203  index.size() == 0, std::invalid_argument,
204  os.str() << "Empty index range is not allowed.");
205  TEUCHOS_TEST_FOR_EXCEPTION(
206  index.lbound() < 0, std::invalid_argument,
207  os.str() << "Index range includes negative index/ices, which is not "
208  "allowed.");
209  TEUCHOS_TEST_FOR_EXCEPTION(
210  index.ubound() >= GetNumberVecs(mv), std::invalid_argument,
211  os.str() << "Index range exceeds number of vectors "
212  << mv.getNumVectors() << " in the input multivector.");
213  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
214  os.str() << "Should never get here!");
215  }
216  Teuchos::RCP<MV> X_copy = mv.subCopy (index);
217  X_copy->setCopyOrView (Teuchos::View);
218  return X_copy;
219  }
220 
221  static Teuchos::RCP<MV>
222  CloneViewNonConst (MV& mv, const std::vector<int>& index)
223  {
224 #ifdef HAVE_TPETRA_DEBUG
225  const char fnName[] = "Anasazi::MultiVecTraits::CloneViewNonConst(mv,index)";
226  const size_t numVecs = mv.getNumVectors ();
227  TEUCHOS_TEST_FOR_EXCEPTION(
228  index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
229  std::invalid_argument,
230  fnName << ": All indices must be nonnegative.");
231  TEUCHOS_TEST_FOR_EXCEPTION(
232  index.size () > 0 &&
233  static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
234  std::invalid_argument,
235  fnName << ": All indices must be strictly less than the number of "
236  "columns " << numVecs << " in the input MultiVector mv.");
237 #endif // HAVE_TPETRA_DEBUG
238 
239  // Tpetra wants an array of size_t, not of int.
240  Teuchos::Array<size_t> columns (index.size ());
241  for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
242  columns[j] = index[j];
243  }
244  // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
245  // continuous column index range in
246  // MultiVector::subViewNonConst, so we don't have to check here.
247  Teuchos::RCP<MV> X_view = mv.subViewNonConst (columns ());
248  X_view->setCopyOrView (Teuchos::View);
249  return X_view;
250  }
251 
252  static Teuchos::RCP<MV>
253  CloneViewNonConst (MV& mv, const Teuchos::Range1D& index)
254  {
255  // NOTE (mfh 11 Jan 2011) We really should check for possible
256  // overflow of int here. However, the number of columns in a
257  // multivector typically fits in an int.
258  const int numCols = static_cast<int> (mv.getNumVectors());
259  const bool validRange = index.size() > 0 &&
260  index.lbound() >= 0 && index.ubound() < numCols;
261  if (! validRange) {
262  std::ostringstream os;
263  os << "Belos::MultiVecTraits::CloneViewNonConst(mv,index=["
264  << index.lbound() << ", " << index.ubound() << "]): ";
265  TEUCHOS_TEST_FOR_EXCEPTION(
266  index.size() == 0, std::invalid_argument,
267  os.str() << "Empty index range is not allowed.");
268  TEUCHOS_TEST_FOR_EXCEPTION(
269  index.lbound() < 0, std::invalid_argument,
270  os.str() << "Index range includes negative inde{x,ices}, which is "
271  "not allowed.");
272  TEUCHOS_TEST_FOR_EXCEPTION(
273  index.ubound() >= numCols, std::invalid_argument,
274  os.str() << "Index range exceeds number of vectors " << numCols
275  << " in the input multivector.");
276  TEUCHOS_TEST_FOR_EXCEPTION(
277  true, std::logic_error,
278  os.str() << "Should never get here!");
279  }
280  Teuchos::RCP<MV> X_view = mv.subViewNonConst (index);
281  X_view->setCopyOrView (Teuchos::View);
282  return X_view;
283  }
284 
285  static Teuchos::RCP<const MV>
286  CloneView (const MV& mv, const std::vector<int>& index)
287  {
288 #ifdef HAVE_TPETRA_DEBUG
289  const char fnName[] = "Belos::MultiVecTraits<Scalar, "
290  "Tpetra::MultiVector<...> >::CloneView(mv,index)";
291  const size_t numVecs = mv.getNumVectors ();
292  TEUCHOS_TEST_FOR_EXCEPTION(
293  *std::min_element (index.begin (), index.end ()) < 0,
294  std::invalid_argument,
295  fnName << ": All indices must be nonnegative.");
296  TEUCHOS_TEST_FOR_EXCEPTION(
297  static_cast<size_t> (*std::max_element (index.begin (), index.end ())) >= numVecs,
298  std::invalid_argument,
299  fnName << ": All indices must be strictly less than the number of "
300  "columns " << numVecs << " in the input MultiVector mv.");
301 #endif // HAVE_TPETRA_DEBUG
302 
303  // Tpetra wants an array of size_t, not of int.
304  Teuchos::Array<size_t> columns (index.size ());
305  for (std::vector<int>::size_type j = 0; j < index.size (); ++j) {
306  columns[j] = index[j];
307  }
308  // mfh 14 Aug 2014: Tpetra already detects and optimizes for a
309  // continuous column index range in MultiVector::subView, so we
310  // don't have to check here.
311  Teuchos::RCP<const MV> X_view = mv.subView (columns);
312  Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
313  return X_view;
314  }
315 
316  static Teuchos::RCP<const MV>
317  CloneView (const MV& mv, const Teuchos::Range1D& index)
318  {
319  // NOTE (mfh 11 Jan 2011) We really should check for possible
320  // overflow of int here. However, the number of columns in a
321  // multivector typically fits in an int.
322  const int numCols = static_cast<int> (mv.getNumVectors());
323  const bool validRange = index.size() > 0 &&
324  index.lbound() >= 0 && index.ubound() < numCols;
325  if (! validRange) {
326  std::ostringstream os;
327  os << "Anasazi::MultiVecTraits::CloneView(mv, index=["
328  << index.lbound () << ", " << index.ubound() << "]): ";
329  TEUCHOS_TEST_FOR_EXCEPTION(index.size() == 0, std::invalid_argument,
330  os.str() << "Empty index range is not allowed.");
331  TEUCHOS_TEST_FOR_EXCEPTION(index.lbound() < 0, std::invalid_argument,
332  os.str() << "Index range includes negative index/ices, which is not "
333  "allowed.");
334  TEUCHOS_TEST_FOR_EXCEPTION(
335  index.ubound() >= numCols, std::invalid_argument,
336  os.str() << "Index range exceeds number of vectors " << numCols
337  << " in the input multivector.");
338  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
339  os.str() << "Should never get here!");
340  }
341  Teuchos::RCP<const MV> X_view = mv.subView (index);
342  Teuchos::rcp_const_cast<MV> (X_view)->setCopyOrView (Teuchos::View);
343  return X_view;
344  }
345 
346  static ptrdiff_t GetGlobalLength( const MV& mv ) {
347  return static_cast<ptrdiff_t> (mv.getGlobalLength ());
348  }
349 
350  static int GetNumberVecs (const MV& mv) {
351  return static_cast<int> (mv.getNumVectors ());
352  }
353 
354  static void
355  MvTimesMatAddMv (Scalar alpha,
356  const MV& A,
357  const Teuchos::SerialDenseMatrix<int, Scalar>& B,
358  Scalar beta,
359  MV& mv)
360  {
361  using Teuchos::ArrayView;
362  using Teuchos::Comm;
363  using Teuchos::rcpFromRef;
364  typedef Tpetra::Map<LO, GO, Node> map_type;
365 
366 #ifdef HAVE_ANASAZI_TPETRA_TIMERS
367  const std::string timerName ("Anasazi::MVT::MvTimesMatAddMv");
368  Teuchos::RCP<Teuchos::Time> timer =
369  Teuchos::TimeMonitor::lookupCounter (timerName);
370  if (timer.is_null ()) {
371  timer = Teuchos::TimeMonitor::getNewCounter (timerName);
372  }
373  TEUCHOS_TEST_FOR_EXCEPTION(
374  timer.is_null (), std::logic_error,
375  "Anasazi::MultiVecTraits::MvTimesMatAddMv: "
376  "Failed to look up timer \"" << timerName << "\". "
377  "Please report this bug to the Belos developers.");
378 
379  // This starts the timer. It will be stopped on scope exit.
380  Teuchos::TimeMonitor timeMon (*timer);
381 #endif
382 
383  // Check if B is 1-by-1, in which case we can just call update()
384  if (B.numRows () == 1 && B.numCols () == 1) {
385  mv.update (alpha*B(0,0), A, beta);
386  return;
387  }
388 
389  // Create local map
390  Teuchos::SerialComm<int> serialComm;
391  map_type LocalMap (B.numRows (), A.getMap ()->getIndexBase (),
392  rcpFromRef<const Comm<int> > (serialComm),
393  Tpetra::LocallyReplicated, A.getMap ()->getNode ());
394  // encapsulate Teuchos::SerialDenseMatrix data in ArrayView
395  ArrayView<const Scalar> Bvalues (B.values (), B.stride () * B.numCols ());
396  // create locally replicated MultiVector with a copy of this data
397  MV B_mv (rcpFromRef (LocalMap), Bvalues, B.stride (), B.numCols ());
398  mv.multiply (Teuchos::NO_TRANS, Teuchos::NO_TRANS, alpha, A, B_mv, beta);
399  }
400 
408  static void
409  MvAddMv (Scalar alpha,
410  const MV& A,
411  Scalar beta,
412  const MV& B,
413  MV& mv)
414  {
415  mv.update (alpha, A, beta, B, Teuchos::ScalarTraits<Scalar>::zero ());
416  }
417 
418  static void MvScale (MV& mv, Scalar alpha) {
419  mv.scale (alpha);
420  }
421 
422  static void MvScale (MV& mv, const std::vector<Scalar>& alphas) {
423  mv.scale (alphas);
424  }
425 
426  static void
427  MvTransMv (const Scalar alpha,
428  const MV& A,
429  const MV& B,
430  Teuchos::SerialDenseMatrix<int,Scalar>& C)
431  {
432  using Tpetra::LocallyReplicated;
433  using Teuchos::Comm;
434  using Teuchos::RCP;
435  using Teuchos::rcp;
436  using Teuchos::TimeMonitor;
437  typedef Tpetra::Map<LO,GO,Node> map_type;
438 
439 #ifdef HAVE_ANASAZI_TPETRA_TIMERS
440  const std::string timerName ("Anasazi::MVT::MvTransMv");
441  RCP<Teuchos::Time> timer = TimeMonitor::lookupCounter (timerName);
442  if (timer.is_null ()) {
443  timer = TimeMonitor::getNewCounter (timerName);
444  }
445  TEUCHOS_TEST_FOR_EXCEPTION(
446  timer.is_null (), std::logic_error, "Anasazi::MvTransMv: "
447  "Failed to look up timer \"" << timerName << "\". "
448  "Please report this bug to the Belos developers.");
449 
450  // This starts the timer. It will be stopped on scope exit.
451  TimeMonitor timeMon (*timer);
452 #endif // HAVE_ANASAZI_TPETRA_TIMERS
453 
454  // Form alpha * A^H * B, then copy into the SerialDenseMatrix.
455  // We will create a multivector C_mv from a a local map. This
456  // map has a serial comm, the purpose being to short-circuit the
457  // MultiVector::reduce() call at the end of
458  // MultiVector::multiply(). Otherwise, the reduced multivector
459  // data would be copied back to the GPU, only to turn around and
460  // have to get it back here. This saves us a round trip for
461  // this data.
462  const int numRowsC = C.numRows ();
463  const int numColsC = C.numCols ();
464  const int strideC = C.stride ();
465 
466  // Check if numRowsC == numColsC == 1, in which case we can call dot()
467  if (numRowsC == 1 && numColsC == 1) {
468  if (alpha == Teuchos::ScalarTraits<Scalar>::zero ()) {
469  // Short-circuit, as required by BLAS semantics.
470  C(0,0) = alpha;
471  return;
472  }
473  A.dot (B, Teuchos::ArrayView<Scalar> (C.values (), 1));
474  if (alpha != Teuchos::ScalarTraits<Scalar>::one ()) {
475  C(0,0) *= alpha;
476  }
477  return;
478  }
479 
480  // get comm
481  RCP<const Comm<int> > pcomm = A.getMap ()->getComm ();
482 
483  // create local map with comm
484  RCP<const map_type> LocalMap =
485  rcp (new map_type (numRowsC, 0, pcomm, LocallyReplicated,
486  A.getMap ()->getNode ()));
487  // create local multivector to hold the result
488  const bool INIT_TO_ZERO = true;
489  MV C_mv (LocalMap, numColsC, INIT_TO_ZERO);
490 
491  // multiply result into local multivector
492  C_mv.multiply (Teuchos::CONJ_TRANS, Teuchos::NO_TRANS, alpha, A, B,
493  Teuchos::ScalarTraits<Scalar>::zero ());
494 
495  // create arrayview encapsulating the Teuchos::SerialDenseMatrix
496  Teuchos::ArrayView<Scalar> C_view (C.values (), strideC * numColsC);
497 
498  // No accumulation to do; simply extract the multivector data
499  // into C. Extract a copy of the result into the array view
500  // (and therefore, the SerialDenseMatrix).
501  C_mv.get1dCopy (C_view, strideC);
502  }
503 
505  static void
506  MvDot (const MV& A, const MV& B, std::vector<Scalar> &dots)
507  {
508  const size_t numVecs = A.getNumVectors ();
509  TEUCHOS_TEST_FOR_EXCEPTION(
510  numVecs != B.getNumVectors (), std::invalid_argument,
511  "Anasazi::MultiVecTraits::MvDot(A,B,dots): "
512  "A and B must have the same number of columns. "
513  "A has " << numVecs << " column(s), "
514  "but B has " << B.getNumVectors () << " column(s).");
515 #ifdef HAVE_TPETRA_DEBUG
516  TEUCHOS_TEST_FOR_EXCEPTION(
517  dots.size() < numVecs, std::invalid_argument,
518  "Anasazi::MultiVecTraits::MvDot(A,B,dots): "
519  "The output array 'dots' must have room for all dot products. "
520  "A and B each have " << numVecs << " column(s), "
521  "but 'dots' only has " << dots.size() << " entry(/ies).");
522 #endif // HAVE_TPETRA_DEBUG
523 
524  Teuchos::ArrayView<Scalar> av (dots);
525  A.dot (B, av (0, numVecs));
526  }
527 
529  static void
530  MvNorm (const MV& mv,
531  std::vector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType> &normvec)
532  {
533  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitude_type;
534 #ifdef HAVE_TPETRA_DEBUG
535  TEUCHOS_TEST_FOR_EXCEPTION(
536  normvec.size () < static_cast<std::vector<int>::size_type> (mv.getNumVectors ()),
537  std::invalid_argument,
538  "Anasazi::MultiVecTraits::MvNorm(mv,normvec): The normvec output "
539  "argument must have at least as many entries as the number of vectors "
540  "(columns) in the MultiVector mv. normvec.size() = " << normvec.size ()
541  << " < mv.getNumVectors() = " << mv.getNumVectors () << ".");
542 #endif // HAVE_TPETRA_DEBUG
543  Teuchos::ArrayView<magnitude_type> av (normvec);
544  mv.norm2 (av (0, mv.getNumVectors ()));
545  }
546 
547  static void
548  SetBlock (const MV& A, const std::vector<int>& index, MV& mv)
549  {
550  using Teuchos::Range1D;
551  using Teuchos::RCP;
552  const size_t inNumVecs = A.getNumVectors ();
553 #ifdef HAVE_TPETRA_DEBUG
554  TEUCHOS_TEST_FOR_EXCEPTION(
555  inNumVecs < static_cast<size_t> (index.size ()), std::invalid_argument,
556  "Anasazi::MultiVecTraits::SetBlock(A,index,mv): 'index' argument must "
557  "have no more entries as the number of columns in the input MultiVector"
558  " A. A.getNumVectors() = " << inNumVecs << " < index.size () = "
559  << index.size () << ".");
560 #endif // HAVE_TPETRA_DEBUG
561  RCP<MV> mvsub = CloneViewNonConst (mv, index);
562  if (inNumVecs > static_cast<size_t> (index.size ())) {
563  RCP<const MV> Asub = A.subView (Range1D (0, index.size () - 1));
564  Tpetra::deep_copy (*mvsub, *Asub);
565  } else {
566  Tpetra::deep_copy (*mvsub, A);
567  }
568  }
569 
570  static void
571  SetBlock (const MV& A, const Teuchos::Range1D& index, MV& mv)
572  {
573  // Range1D bounds are signed; size_t is unsigned.
574  // Assignment of Tpetra::MultiVector is a deep copy.
575 
576  // Tpetra::MultiVector::getNumVectors() returns size_t. It's
577  // fair to assume that the number of vectors won't overflow int,
578  // since the typical use case of multivectors involves few
579  // columns, but it's friendly to check just in case.
580  const size_t maxInt =
581  static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
582  const bool overflow =
583  maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
584  if (overflow) {
585  std::ostringstream os;
586  os << "Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
587  << ", " << index.ubound () << "], mv): ";
588  TEUCHOS_TEST_FOR_EXCEPTION(
589  maxInt < A.getNumVectors (), std::range_error, os.str () << "Number "
590  "of columns (size_t) in the input MultiVector 'A' overflows int.");
591  TEUCHOS_TEST_FOR_EXCEPTION(
592  maxInt < mv.getNumVectors (), std::range_error, os.str () << "Number "
593  "of columns (size_t) in the output MultiVector 'mv' overflows int.");
594  }
595  // We've already validated the static casts above.
596  const int numColsA = static_cast<int> (A.getNumVectors ());
597  const int numColsMv = static_cast<int> (mv.getNumVectors ());
598  // 'index' indexes into mv; it's the index set of the target.
599  const bool validIndex =
600  index.lbound () >= 0 && index.ubound () < numColsMv;
601  // We can't take more columns out of A than A has.
602  const bool validSource = index.size () <= numColsA;
603 
604  if (! validIndex || ! validSource) {
605  std::ostringstream os;
606  os << "Anasazi::MultiVecTraits::SetBlock(A, index=[" << index.lbound ()
607  << ", " << index.ubound () << "], mv): ";
608  TEUCHOS_TEST_FOR_EXCEPTION(
609  index.lbound() < 0, std::invalid_argument,
610  os.str() << "Range lower bound must be nonnegative.");
611  TEUCHOS_TEST_FOR_EXCEPTION(
612  index.ubound() >= numColsMv, std::invalid_argument,
613  os.str() << "Range upper bound must be less than the number of "
614  "columns " << numColsA << " in the 'mv' output argument.");
615  TEUCHOS_TEST_FOR_EXCEPTION(
616  index.size() > numColsA, std::invalid_argument,
617  os.str() << "Range must have no more elements than the number of "
618  "columns " << numColsA << " in the 'A' input argument.");
619  TEUCHOS_TEST_FOR_EXCEPTION(
620  true, std::logic_error, "Should never get here!");
621  }
622 
623  // View of the relevant column(s) of the target multivector mv.
624  // We avoid view creation overhead by only creating a view if
625  // the index range is different than [0, (# columns in mv) - 1].
626  Teuchos::RCP<MV> mv_view;
627  if (index.lbound () == 0 && index.ubound () + 1 == numColsMv) {
628  mv_view = Teuchos::rcpFromRef (mv); // Non-const, non-owning RCP
629  } else {
630  mv_view = CloneViewNonConst (mv, index);
631  }
632 
633  // View of the relevant column(s) of the source multivector A.
634  // If A has fewer columns than mv_view, then create a view of
635  // the first index.size() columns of A.
636  Teuchos::RCP<const MV> A_view;
637  if (index.size () == numColsA) {
638  A_view = Teuchos::rcpFromRef (A); // Const, non-owning RCP
639  } else {
640  A_view = CloneView (A, Teuchos::Range1D (0, index.size () - 1));
641  }
642 
643  Tpetra::deep_copy (*mv_view, *A_view);
644  }
645 
646  static void Assign (const MV& A, MV& mv)
647  {
648  const char errPrefix[] = "Anasazi::MultiVecTraits::Assign(A, mv): ";
649 
650  // Range1D bounds are signed; size_t is unsigned.
651  // Assignment of Tpetra::MultiVector is a deep copy.
652 
653  // Tpetra::MultiVector::getNumVectors() returns size_t. It's
654  // fair to assume that the number of vectors won't overflow int,
655  // since the typical use case of multivectors involves few
656  // columns, but it's friendly to check just in case.
657  const size_t maxInt =
658  static_cast<size_t> (Teuchos::OrdinalTraits<int>::max ());
659  const bool overflow =
660  maxInt < A.getNumVectors () && maxInt < mv.getNumVectors ();
661  if (overflow) {
662  TEUCHOS_TEST_FOR_EXCEPTION(
663  maxInt < A.getNumVectors(), std::range_error,
664  errPrefix << "Number of columns in the input multivector 'A' "
665  "(a size_t) overflows int.");
666  TEUCHOS_TEST_FOR_EXCEPTION(
667  maxInt < mv.getNumVectors(), std::range_error,
668  errPrefix << "Number of columns in the output multivector 'mv' "
669  "(a size_t) overflows int.");
670  TEUCHOS_TEST_FOR_EXCEPTION(
671  true, std::logic_error, "Should never get here!");
672  }
673  // We've already validated the static casts above.
674  const int numColsA = static_cast<int> (A.getNumVectors ());
675  const int numColsMv = static_cast<int> (mv.getNumVectors ());
676  if (numColsA > numColsMv) {
677  TEUCHOS_TEST_FOR_EXCEPTION(
678  numColsA > numColsMv, std::invalid_argument,
679  errPrefix << "Input multivector 'A' has " << numColsA << " columns, "
680  "but output multivector 'mv' has only " << numColsMv << " columns.");
681  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Should never get here!");
682  }
683  if (numColsA == numColsMv) {
684  Tpetra::deep_copy (mv, A);
685  } else {
686  Teuchos::RCP<MV> mv_view =
687  CloneViewNonConst (mv, Teuchos::Range1D (0, numColsA - 1));
688  Tpetra::deep_copy (*mv_view, A);
689  }
690  }
691 
692  static void MvRandom (MV& mv) {
693  mv.randomize ();
694  }
695 
696  static void
697  MvInit (MV& mv, const Scalar alpha = Teuchos::ScalarTraits<Scalar>::zero ())
698  {
699  mv.putScalar (alpha);
700  }
701 
702  static void MvPrint (const MV& mv, std::ostream& os) {
703  mv.print (os);
704  }
705 
706 #ifdef HAVE_ANASAZI_TSQR
707  typedef Tpetra::TsqrAdaptor<Tpetra::MultiVector<Scalar, LO, GO, Node> > tsqr_adaptor_type;
710 #endif // HAVE_ANASAZI_TSQR
711  };
712 
713 
715  template <class Scalar, class LO, class GO, class Node>
716  class OperatorTraits<Scalar,
717  Tpetra::MultiVector<Scalar,LO,GO,Node>,
718  Tpetra::Operator<Scalar,LO,GO,Node> >
719  {
720  public:
721  static void
722  Apply (const Tpetra::Operator<Scalar,LO,GO,Node>& Op,
723  const Tpetra::MultiVector<Scalar,LO,GO,Node>& X,
724  Tpetra::MultiVector<Scalar,LO,GO,Node>& Y)
725  {
726  Op.apply (X, Y, Teuchos::NO_TRANS);
727  }
728  };
729 
730 } // end of Anasazi namespace
731 
732 #endif
733 // end of file ANASAZI_TPETRA_ADAPTER_HPP
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
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.
Virtual base class which defines basic traits for the operator type.
static void Assign(const MV &A, MV &mv)
mv := A
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.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package...
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...
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.
Types and exceptions used within Anasazi solvers and interfaces.
static void MvPrint(const MV &mv, std::ostream &os)
Print the mv multi-vector to the os output stream.
static Teuchos::RCP< MV > CloneCopy(const MV &mv, const Teuchos::Range1D &index)
Create and return a deep copy of the given columns of mv.