virtual void fetchDims (const multivector_type& A, local_ordinal_type& nrowsLocal, local_ordinal_type& ncols, local_ordinal_type& LDA) const { nrowsLocal = A.getLocalLength(); ncols = A.getNumVectors(); if (nrowsLocal < ncols) { std::ostringstream os; os << "The local component of the input matrix has fewer row" "s (" << nrowsLocal << ") than columns (" << ncols << "). " "TSQR::Trilinos::TpetraRandomizer does not support this case."; throw std::runtime_error (os.str()); } if (! A.isConstantStride()) { // FIXME (mfh 14 June 2010) Storage of A uses nonconstant // stride internally, but that doesn't necessarily mean we // can't run TSQR. It depends on what get1dViewNonConst() // returns. If it's copied and packed into a matrix with // constant stride, then we are free to run TSQR. std::ostringstream os; os << "TSQR::Trilinos::TpetraRandomizer does not support " "Tpetra::MultiVector inputs that do not have constant stride."; throw std::runtime_error (os.str()); } LDA = A.getStride(); }
virtual void fetchDims (const multivector_type& A, local_ordinal_type& nrowsLocal, local_ordinal_type& ncols, local_ordinal_type& LDA) const { nrowsLocal = A.MyLength(); ncols = A.NumVectors(); if (nrowsLocal < ncols) { std::ostringstream os; os << "TSQR: The local component of the input matrix has fewer row" "s (" << nrowsLocal << ") than columns (" << ncols << "). TSQR " "does not support this case."; throw std::runtime_error (os.str()); } if (! A.ConstantStride()) { std::ostringstream os; os << "TSQR does not support Epetra_MultiVector inputs that do not" " have constant stride."; throw std::runtime_error (os.str()); } LDA = A.Stride(); }
virtual Teuchos::ArrayRCP< scalar_type > fetchNonConstView (multivector_type& A) const { // This won't be efficient if the entries of A live in a // different memory space (e.g., GPU node), but it will be // correct for any Tpetra::MultiVector type. return A.get1dViewNonConst(); }
virtual void fetchMessengers (const multivector_type& mv, scalar_messenger_ptr& pScalarMessenger, ordinal_messenger_ptr& pOrdinalMessenger) const { typedef TpetraCommFactory< S, LO, GO, NodeType > comm_factory_type; comm_ptr pComm = mv.getMap()->getComm(); comm_factory_type factory; factory.makeMessengers (pComm, pScalarMessenger, pOrdinalMessenger); }
virtual Teuchos::ArrayRCP< scalar_type > fetchNonConstView (multivector_type& A) const { using Teuchos::arcpFromArrayView; using Teuchos::arrayView; typedef Teuchos::ArrayView< scalar_type >::size_type size_type; const size_type nelts = fetchArrayLength (A); // The returned ArrayRCP does NOT own A.Values(). return arcpFromArrayView (arrayView (A.Values(), nelts)); }
virtual void fetchMessengers (const multivector_type& mv, scalar_messenger_ptr& pScalarMessenger, ordinal_messenger_ptr& pOrdinalMessenger) const { typedef EpetraCommFactory comm_factory_type; // mv.Comm() returns a "const Epetra_Comm&". rcpFromRef() // makes a non-owning (weak) RCP out of it. This requires // that the mv's Epetra_Comm object not fall out of scope, // which it shouldn't as long as we are computing with // multivectors distributed according to that communicator. comm_ptr pComm = Teuchos::rcpFromRef (mv.Comm()); comm_factory_type factory; factory.makeMessengers (pComm, pScalarMessenger, pOrdinalMessenger); }
virtual Teuchos::ArrayRCP< const scalar_type > fetchConstView (const multivector_type& A) const { using Teuchos::arcpFromArrayView; using Teuchos::arrayView; using Teuchos::ArrayView; typedef ArrayView< scalar_type >::size_type size_type; const size_type nelts = fetchArrayLength (A); const scalar_type* A_ptr = A.Values(); ArrayView< const scalar_type > A_view = arrayView (A_ptr, nelts); // The returned ArrayRCP does NOT own A.Values(). return arcpFromArrayView (A_view); }
static double factorization( const multivector_type Q_ , const multivector_type R_ ) { #if defined( KOKKOS_USING_EXPERIMENTAL_VIEW ) using Kokkos::Experimental::ALL ; #else const Kokkos::ALL ALL ; #endif const size_type count = Q_.dimension_1(); value_view tmp("tmp"); value_view one("one"); Kokkos::deep_copy( one , (Scalar) 1 ); Kokkos::Impl::Timer timer ; for ( size_type j = 0 ; j < count ; ++j ) { // Reduction : tmp = dot( Q(:,j) , Q(:,j) ); // PostProcess : tmp = sqrt( tmp ); R(j,j) = tmp ; tmp = 1 / tmp ; const vector_type Qj = Kokkos::subview( Q_ , ALL , j ); const value_view Rjj = Kokkos::subview( R_ , j , j ); invnorm2( Qj , Rjj , tmp ); // Q(:,j) *= ( 1 / R(j,j) ); => Q(:,j) *= tmp ; Kokkos::scale( tmp , Qj ); for ( size_t k = j + 1 ; k < count ; ++k ) { const vector_type Qk = Kokkos::subview( Q_ , ALL , k ); const value_view Rjk = Kokkos::subview( R_ , j , k ); // Reduction : R(j,k) = dot( Q(:,j) , Q(:,k) ); // PostProcess : tmp = - R(j,k); dot_neg( Qj , Qk , Rjk , tmp ); // Q(:,k) -= R(j,k) * Q(:,j); => Q(:,k) += tmp * Q(:,j) Kokkos::axpby( tmp , Qj , one , Qk ); } } execution_space::fence(); return timer.seconds(); }
static double factorization( const multivector_type Q , const multivector_type R ) { const size_type count = Q.dimension_1(); value_view tmp("tmp"); value_view one("one"); KokkosArray::deep_copy( one , (Scalar) 1 ); KokkosArray::Impl::Timer timer ; for ( size_type j = 0 ; j < count ; ++j ) { // Reduction : tmp = dot( Q(:,j) , Q(:,j) ); // PostProcess : tmp = sqrt( tmp ); R(j,j) = tmp ; tmp = 1 / tmp ; const vector_type Qj( Q , j ); const value_view Rjj( R , j , j ); KokkosArray::dot( Qj , InvNorm2( Rjj , tmp ) ); // Q(:,j) *= ( 1 / R(j,j) ); => Q(:,j) *= tmp ; KokkosArray::scale( tmp , Qj ); for ( size_t k = j + 1 ; k < count ; ++k ) { const vector_type Qk( Q , k ); const value_view Rjk( R , j , k ); // Reduction : R(j,k) = dot( Q(:,j) , Q(:,k) ); // PostProcess : tmp = - R(j,k); KokkosArray::dot( Qj , Qk , DotM( Rjk , tmp ) ); // Q(:,k) -= R(j,k) * Q(:,j); => Q(:,k) += tmp * Q(:,j) KokkosArray::axpby( tmp , Qj , one , Qk ); } } device_type::fence(); return timer.seconds(); }
/*! * \brief Given a multivector, get a single non-const vector of a given * id. */ static Teuchos::RCP<vector_type> getVectorNonConst( multivector_type& multivector, const int id ) { return multivector.getVectorNonConst( id ); }