Anasazi Version of the Day
Loading...
Searching...
No Matches
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
71namespace 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 ();
133 TEUCHOS_TEST_FOR_EXCEPTION(
134 index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
135 std::runtime_error, fnName << ": All indices must be nonnegative.");
136 TEUCHOS_TEST_FOR_EXCEPTION(
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() << "]): ";
173 TEUCHOS_TEST_FOR_EXCEPTION(
174 index.size() == 0, std::invalid_argument,
175 os.str() << "Empty index range is not allowed.");
176 TEUCHOS_TEST_FOR_EXCEPTION(
177 index.lbound() < 0, std::invalid_argument,
178 os.str() << "Index range includes negative index/ices, which is not "
179 "allowed.");
180 TEUCHOS_TEST_FOR_EXCEPTION(
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 ();
198 TEUCHOS_TEST_FOR_EXCEPTION(
199 index.size () > 0 && *std::min_element (index.begin (), index.end ()) < 0,
200 std::invalid_argument,
201 fnName << ": All indices must be nonnegative.");
202 TEUCHOS_TEST_FOR_EXCEPTION(
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() << "]): ";
236 TEUCHOS_TEST_FOR_EXCEPTION(
237 index.size() == 0, std::invalid_argument,
238 os.str() << "Empty index range is not allowed.");
239 TEUCHOS_TEST_FOR_EXCEPTION(
240 index.lbound() < 0, std::invalid_argument,
241 os.str() << "Index range includes negative inde{x,ices}, which is "
242 "not allowed.");
243 TEUCHOS_TEST_FOR_EXCEPTION(
244 index.ubound() >= numCols, std::invalid_argument,
245 os.str() << "Index range exceeds number of vectors " << numCols
246 << " in the input multivector.");
247 TEUCHOS_TEST_FOR_EXCEPTION(
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
256 static Teuchos::RCP<const MV>
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 ();
263 TEUCHOS_TEST_FOR_EXCEPTION(
264 *std::min_element (index.begin (), index.end ()) < 0,
265 std::invalid_argument,
266 fnName << ": All indices must be nonnegative.");
267 TEUCHOS_TEST_FOR_EXCEPTION(
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
287 static Teuchos::RCP<const MV>
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.");
305 TEUCHOS_TEST_FOR_EXCEPTION(
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,
328 const Teuchos::SerialDenseMatrix<int, Scalar>& B,
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");
339 Teuchos::RCP<Teuchos::Time> timer =
340 Teuchos::TimeMonitor::lookupCounter (timerName);
341 if (timer.is_null ()) {
342 timer = Teuchos::TimeMonitor::getNewCounter (timerName);
343 }
344 TEUCHOS_TEST_FOR_EXCEPTION(
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,
401 Teuchos::SerialDenseMatrix<int,Scalar>& C)
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 }
416 TEUCHOS_TEST_FOR_EXCEPTION(
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,
463 Teuchos::ScalarTraits<Scalar>::zero ());
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 ();
479 TEUCHOS_TEST_FOR_EXCEPTION(
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
486 TEUCHOS_TEST_FOR_EXCEPTION(
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
505 TEUCHOS_TEST_FOR_EXCEPTION(
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
513 Teuchos::ArrayView<magnitude_type> av (normvec);
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
524 TEUCHOS_TEST_FOR_EXCEPTION(
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): ";
558 TEUCHOS_TEST_FOR_EXCEPTION(
559 maxInt < A.getNumVectors (), std::range_error, os.str () << "Number "
560 "of columns (size_t) in the input MultiVector 'A' overflows int.");
561 TEUCHOS_TEST_FOR_EXCEPTION(
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): ";
578 TEUCHOS_TEST_FOR_EXCEPTION(
579 index.lbound() < 0, std::invalid_argument,
580 os.str() << "Range lower bound must be nonnegative.");
581 TEUCHOS_TEST_FOR_EXCEPTION(
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.");
585 TEUCHOS_TEST_FOR_EXCEPTION(
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.");
589 TEUCHOS_TEST_FOR_EXCEPTION(
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) {
632 TEUCHOS_TEST_FOR_EXCEPTION(
633 maxInt < A.getNumVectors(), std::range_error,
634 errPrefix << "Number of columns in the input multivector 'A' "
635 "(a size_t) overflows int.");
636 TEUCHOS_TEST_FOR_EXCEPTION(
637 maxInt < mv.getNumVectors(), std::range_error,
638 errPrefix << "Number of columns in the output multivector 'mv' "
639 "(a size_t) overflows int.");
640 TEUCHOS_TEST_FOR_EXCEPTION(
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) {
647 TEUCHOS_TEST_FOR_EXCEPTION(
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
680 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
702template<class ST, class LO, class GO, class NT>
703struct OutputStreamTraits<Tpetra::Operator<ST, LO, GO, NT> > {
704 typedef Tpetra::Operator<ST, LO, GO, NT> operator_type;
705
706 static Teuchos::RCP<Teuchos::FancyOStream>
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
Anasazi header file which uses auto-configuration information to include necessary C++ headers.
Declaration of basic traits for the multivector type.
Virtual base class which defines basic traits for the operator type.
Abstract class definition for Anasazi output stream.
Types and exceptions used within Anasazi solvers and interfaces.
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 Teuchos::RCP< MV > CloneCopy(const MV &mv, const Teuchos::Range1D &index)
Create and return a deep copy of the given columns of mv.
static Teuchos::RCP< MV > Clone(const MV &X, const int numVecs)
Create a new MultiVector with numVecs columns.
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.
static void MvAddMv(Scalar alpha, const MV &A, Scalar beta, const MV &B, MV &mv)
mv := alpha*A + beta*B
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 int GetNumberVecs(const MV &mv)
Obtain the number of vectors in mv.
static void MvPrint(const MV &mv, std::ostream &os)
Print the mv multi-vector to the os output stream.
static void MvInit(MV &mv, const ScalarType alpha=Teuchos::ScalarTraits< ScalarType >::zero())
Replace each element of the vectors in mv with alpha.
static void MvScale(MV &mv, const ScalarType alpha)
Scale each element of the vectors in mv with alpha.
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 Assign(const MV &A, MV &mv)
mv := A
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
static void MvTransMv(const ScalarType alpha, const MV &A, const MV &B, Teuchos::SerialDenseMatrix< int, ScalarType > &C)
Compute C := alpha * A^H B.
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 > CloneViewNonConst(MV &mv, const std::vector< int > &index)
Creates a new 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.
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...
Anasazi's templated virtual class for constructing an operator that can interface with the OperatorTr...
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.
Output managers remove the need for the eigensolver to know any information about the required output...