53 #ifndef AMESOS2_TPETRA_MULTIVEC_ADAPTER_DEF_HPP
54 #define AMESOS2_TPETRA_MULTIVEC_ADAPTER_DEF_HPP
56 #include <type_traits>
63 using Tpetra::MultiVector;
65 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
70 Node> >::MultiVecAdapter(
const Teuchos::RCP<multivec_t>& m )
74 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
84 Node> >::clone()
const
86 using MV = MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
87 Teuchos::RCP<MV> Y (
new MV (mv_->getMap(), mv_->getNumVectors(),
false));
88 Y->setCopyOrView (Teuchos::View);
92 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
93 typename MultiVecAdapter<
97 Node> >::multivec_t::impl_scalar_type *
102 Node> >::getMVPointer_impl()
const
104 TEUCHOS_TEST_FOR_EXCEPTION( this->getGlobalNumVectors() != 1,
105 std::invalid_argument,
106 "Amesos2_TpetraMultiVectorAdapter: getMVPointer_impl should only be called for case with a single vector and single MPI process" );
108 auto contig_local_view_2d = mv_->getLocalViewHost(Tpetra::Access::ReadWrite);
109 auto contig_local_view_1d = Kokkos::subview (contig_local_view_2d, Kokkos::ALL (), 0);
110 return contig_local_view_1d.data();
121 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
127 Node> >::get1dCopy(
const Teuchos::ArrayView<scalar_t>& av,
130 const Tpetra::Map<LocalOrdinal,
132 Node> > distribution_map,
137 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
138 const size_t num_vecs = getGlobalNumVectors ();
140 TEUCHOS_TEST_FOR_EXCEPTION(
141 distribution_map.getRawPtr () == NULL, std::invalid_argument,
142 "Amesos2::MultiVecAdapter::get1dCopy: distribution_map argument is null.");
143 TEUCHOS_TEST_FOR_EXCEPTION(
144 mv_.is_null (), std::logic_error,
145 "Amesos2::MultiVecAdapter::get1dCopy: mv_ is null.");
147 TEUCHOS_TEST_FOR_EXCEPTION(
148 this->getMap ().is_null (), std::logic_error,
149 "Amesos2::MultiVecAdapter::get1dCopy: this->getMap() returns null.");
151 #ifdef HAVE_AMESOS2_DEBUG
152 const size_t requested_vector_length = distribution_map->getLocalNumElements ();
153 TEUCHOS_TEST_FOR_EXCEPTION(
154 lda < requested_vector_length, std::invalid_argument,
155 "Amesos2::MultiVecAdapter::get1dCopy: On process " <<
156 distribution_map->getComm ()->getRank () <<
" of the distribution Map's "
157 "communicator, the given stride lda = " << lda <<
" is not large enough "
158 "for the local vector length " << requested_vector_length <<
".");
159 TEUCHOS_TEST_FOR_EXCEPTION(
160 as<size_t> (av.size ()) < as<size_t> ((num_vecs - 1) * lda + requested_vector_length),
161 std::invalid_argument,
"Amesos2::MultiVector::get1dCopy: MultiVector "
162 "storage not large enough given leading dimension and number of vectors." );
163 #endif // HAVE_AMESOS2_DEBUG
166 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
167 mv_->get1dCopy (av, lda);
174 RCP<const map_type> distMap;
175 if (exporter_.is_null () ||
176 ! exporter_->getSourceMap ()->isSameAs (* (this->getMap ())) ||
177 ! exporter_->getTargetMap ()->isSameAs (* distribution_map)) {
183 distMap = rcp(
new map_type(*distribution_map));
185 exporter_ = rcp (
new export_type (this->getMap (), distMap));
188 distMap = exporter_->getTargetMap ();
191 multivec_t redist_mv (distMap, num_vecs);
194 redist_mv.doExport (*mv_, *exporter_, Tpetra::REPLACE);
196 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
199 redist_mv.get1dCopy (av, lda);
205 auto contig_local_view_2d = redist_mv.getLocalViewHost(Tpetra::Access::ReadOnly);
206 if ( redist_mv.isConstantStride() ) {
207 for (
size_t j = 0; j < num_vecs; ++j) {
208 auto av_j = av(lda*j, lda);
209 for (
size_t i = 0; i < lda; ++i ) {
210 av_j[i] = contig_local_view_2d(i,j);
219 const size_t lclNumRows = redist_mv.getLocalLength();
220 for (
size_t j = 0; j < redist_mv.getNumVectors(); ++j) {
221 auto av_j = av(lda*j, lclNumRows);
222 auto X_lcl_j_2d = redist_mv.getLocalViewHost(Tpetra::Access::ReadOnly);
223 auto X_lcl_j_1d = Kokkos::subview (X_lcl_j_2d, Kokkos::ALL (), j);
225 using val_type =
typename std::remove_const<typename decltype( X_lcl_j_1d )::value_type>::type;
226 Kokkos::View<val_type*, Kokkos::HostSpace> umavj ( const_cast< val_type* > ( reinterpret_cast<const val_type*> ( av_j.getRawPtr () ) ), av_j.size () );
227 Kokkos::deep_copy (umavj, X_lcl_j_1d);
234 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
235 template <
typename KV>
238 MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>
239 >::get1dCopy_kokkos_view(
242 [[maybe_unused]]
size_t lda,
243 Teuchos::Ptr<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > distribution_map,
248 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
249 const size_t num_vecs = getGlobalNumVectors ();
251 TEUCHOS_TEST_FOR_EXCEPTION(
252 distribution_map.getRawPtr () == NULL, std::invalid_argument,
253 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: distribution_map argument is null.");
254 TEUCHOS_TEST_FOR_EXCEPTION(
255 mv_.is_null (), std::logic_error,
256 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: mv_ is null.");
258 TEUCHOS_TEST_FOR_EXCEPTION(
259 this->getMap ().is_null (), std::logic_error,
260 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: this->getMap() returns null.");
262 #ifdef HAVE_AMESOS2_DEBUG
263 const size_t requested_vector_length = distribution_map->getLocalNumElements ();
264 TEUCHOS_TEST_FOR_EXCEPTION(
265 lda < requested_vector_length, std::invalid_argument,
266 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: On process " <<
267 distribution_map->getComm ()->getRank () <<
" of the distribution Map's "
268 "communicator, the given stride lda = " << lda <<
" is not large enough "
269 "for the local vector length " << requested_vector_length <<
".");
273 #endif // HAVE_AMESOS2_DEBUG
276 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
277 if(mv_->isConstantStride()) {
280 deep_copy_only(bInitialize, kokkos_view, mv_->getLocalViewDevice(Tpetra::Access::ReadOnly), bAssigned);
284 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Resolve handling for non-constant stride.");
292 RCP<const map_type> distMap;
293 if (exporter_.is_null () ||
294 ! exporter_->getSourceMap ()->isSameAs (* (this->getMap ())) ||
295 ! exporter_->getTargetMap ()->isSameAs (* distribution_map)) {
301 distMap = rcp(
new map_type(*distribution_map));
303 exporter_ = rcp (
new export_type (this->getMap (), distMap));
306 distMap = exporter_->getTargetMap ();
309 multivec_t redist_mv (distMap, num_vecs);
312 redist_mv.doExport (*mv_, *exporter_, Tpetra::REPLACE);
314 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
318 deep_copy_or_assign_view(bInitialize, kokkos_view, redist_mv.getLocalViewDevice(Tpetra::Access::ReadOnly), bAssigned);
322 if(redist_mv.isConstantStride()) {
324 deep_copy_or_assign_view(bInitialize, kokkos_view, redist_mv.getLocalViewDevice(Tpetra::Access::ReadOnly), bAssigned);
328 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Kokkos adapter non-constant stride not imlemented.");
334 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
335 Teuchos::ArrayRCP<Scalar>
340 Node> >::get1dViewNonConst (
bool local)
346 TEUCHOS_TEST_FOR_EXCEPTION(
347 true, std::logic_error,
"Amesos2::MultiVecAdapter::get1dViewNonConst: "
401 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node>
407 Node> >::put1dData(
const Teuchos::ArrayView<const scalar_t>& new_data,
410 const Tpetra::Map<LocalOrdinal,
416 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
418 TEUCHOS_TEST_FOR_EXCEPTION(
419 source_map.getRawPtr () == NULL, std::invalid_argument,
420 "Amesos2::MultiVecAdapter::put1dData: source_map argument is null.");
421 TEUCHOS_TEST_FOR_EXCEPTION(
422 mv_.is_null (), std::logic_error,
423 "Amesos2::MultiVecAdapter::put1dData: the internal MultiVector mv_ is null.");
425 TEUCHOS_TEST_FOR_EXCEPTION(
426 this->getMap ().is_null (), std::logic_error,
427 "Amesos2::MultiVecAdapter::put1dData: this->getMap() returns null.");
429 const size_t num_vecs = getGlobalNumVectors ();
432 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
434 auto mv_view_to_modify_2d = mv_->getLocalViewHost(Tpetra::Access::OverwriteAll);
435 for (
size_t i = 0; i < lda; ++i ) {
436 mv_view_to_modify_2d(i,0) = new_data[i];
444 RCP<const map_type> srcMap;
445 if (importer_.is_null () ||
446 ! importer_->getSourceMap ()->isSameAs (* source_map) ||
447 ! importer_->getTargetMap ()->isSameAs (* (this->getMap ()))) {
453 srcMap = rcp(
new map_type(*source_map));
454 importer_ = rcp (
new import_type (srcMap, this->getMap ()));
457 srcMap = importer_->getSourceMap ();
460 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
463 const multivec_t source_mv (srcMap, new_data, lda, num_vecs);
464 mv_->doImport (source_mv, *importer_, Tpetra::REPLACE);
467 multivec_t redist_mv (srcMap, num_vecs);
468 if ( redist_mv.isConstantStride() ) {
469 auto contig_local_view_2d = redist_mv.getLocalViewHost(Tpetra::Access::OverwriteAll);
470 for (
size_t j = 0; j < num_vecs; ++j) {
471 auto av_j = new_data(lda*j, lda);
472 for (
size_t i = 0; i < lda; ++i ) {
473 contig_local_view_2d(i,j) = av_j[i];
482 const size_t lclNumRows = redist_mv.getLocalLength();
483 for (
size_t j = 0; j < redist_mv.getNumVectors(); ++j) {
484 auto av_j = new_data(lda*j, lclNumRows);
485 auto X_lcl_j_2d = redist_mv.getLocalViewHost(Tpetra::Access::ReadOnly);
486 auto X_lcl_j_1d = Kokkos::subview (X_lcl_j_2d, Kokkos::ALL (), j);
488 using val_type =
typename std::remove_const<typename decltype( X_lcl_j_1d )::value_type>::type;
489 Kokkos::View<val_type*, Kokkos::HostSpace> umavj ( const_cast< val_type* > ( reinterpret_cast<const val_type*> ( av_j.getRawPtr () ) ), av_j.size () );
490 Kokkos::deep_copy (umavj, X_lcl_j_1d);
497 mv_->doImport (redist_mv, *importer_, Tpetra::REPLACE);
503 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node>
504 template <
typename KV>
510 Node> >::put1dData_kokkos_view(KV& kokkos_new_data,
513 const Tpetra::Map<LocalOrdinal,
519 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
521 TEUCHOS_TEST_FOR_EXCEPTION(
522 source_map.getRawPtr () == NULL, std::invalid_argument,
523 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: source_map argument is null.");
524 TEUCHOS_TEST_FOR_EXCEPTION(
525 mv_.is_null (), std::logic_error,
526 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: the internal MultiVector mv_ is null.");
528 TEUCHOS_TEST_FOR_EXCEPTION(
529 this->getMap ().is_null (), std::logic_error,
530 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: this->getMap() returns null.");
532 const size_t num_vecs = getGlobalNumVectors ();
535 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
540 auto mv_view_to_modify_2d = mv_->getLocalViewDevice(Tpetra::Access::OverwriteAll);
542 deep_copy_only(mv_view_to_modify_2d, kokkos_new_data);
549 RCP<const map_type> srcMap;
550 if (importer_.is_null () ||
551 ! importer_->getSourceMap ()->isSameAs (* source_map) ||
552 ! importer_->getTargetMap ()->isSameAs (* (this->getMap ()))) {
558 srcMap = rcp(
new map_type(*source_map));
559 importer_ = rcp (
new import_type (srcMap, this->getMap ()));
562 srcMap = importer_->getSourceMap ();
565 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
570 typedef typename multivec_t::dual_view_type::t_host::value_type tpetra_mv_view_type;
571 Kokkos::View<tpetra_mv_view_type**,
typename KV::array_layout,
572 Kokkos::HostSpace> convert_kokkos_new_data;
573 deep_copy_or_assign_view(convert_kokkos_new_data, kokkos_new_data);
574 #ifdef HAVE_TEUCHOS_COMPLEX
576 auto pData =
reinterpret_cast<Scalar*
>(convert_kokkos_new_data.data());
578 auto pData = convert_kokkos_new_data.data();
581 const multivec_t source_mv (srcMap, Teuchos::ArrayView<const scalar_t>(
582 pData, kokkos_new_data.size()), lda, num_vecs);
583 mv_->doImport (source_mv, *importer_, Tpetra::REPLACE);
586 multivec_t redist_mv (srcMap, num_vecs);
591 auto host_kokkos_new_data = Kokkos::create_mirror_view(kokkos_new_data);
592 Kokkos::deep_copy(host_kokkos_new_data, kokkos_new_data);
593 if ( redist_mv.isConstantStride() ) {
594 auto contig_local_view_2d = redist_mv.getLocalViewHost(Tpetra::Access::OverwriteAll);
595 for (
size_t j = 0; j < num_vecs; ++j) {
596 auto av_j = Kokkos::subview(host_kokkos_new_data, Kokkos::ALL, j);
597 for (
size_t i = 0; i < lda; ++i ) {
598 contig_local_view_2d(i,j) = av_j(i);
603 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Kokkos adapter "
604 "CONTIGUOUS_AND_ROOTED not implemented for put1dData_kokkos_view "
605 "with non constant stride.");
611 mv_->doImport (redist_mv, *importer_, Tpetra::REPLACE);
617 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
623 Node> >::description()
const
625 std::ostringstream oss;
626 oss <<
"Amesos2 adapter wrapping: ";
627 oss << mv_->description();
632 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
638 Node> >::describe (Teuchos::FancyOStream& os,
639 const Teuchos::EVerbosityLevel verbLevel)
const
641 mv_->describe (os, verbLevel);
645 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
646 const char* MultiVecAdapter<
650 Node> >::name =
"Amesos2 adapter for Tpetra::MultiVector";
654 #endif // AMESOS2_TPETRA_MULTIVEC_ADAPTER_DEF_HPP
Copy or assign views based on memory spaces.
Amesos2::MultiVecAdapter specialization for the Tpetra::MultiVector class.
EDistribution
Definition: Amesos2_TypeDecl.hpp:123