19 #ifndef AMESOS2_TPETRA_MULTIVEC_ADAPTER_DEF_HPP
20 #define AMESOS2_TPETRA_MULTIVEC_ADAPTER_DEF_HPP
22 #include <type_traits>
29 using Tpetra::MultiVector;
31 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
36 Node> >::MultiVecAdapter(
const Teuchos::RCP<multivec_t>& m )
40 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
50 Node> >::clone()
const
52 using MV = MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
53 Teuchos::RCP<MV> Y (
new MV (mv_->getMap(), mv_->getNumVectors(),
false));
54 Y->setCopyOrView (Teuchos::View);
58 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
59 typename MultiVecAdapter<
63 Node> >::multivec_t::impl_scalar_type *
68 Node> >::getMVPointer_impl()
const
70 TEUCHOS_TEST_FOR_EXCEPTION( this->getGlobalNumVectors() != 1,
71 std::invalid_argument,
72 "Amesos2_TpetraMultiVectorAdapter: getMVPointer_impl should only be called for case with a single vector and single MPI process" );
74 auto contig_local_view_2d = mv_->getLocalViewHost(Tpetra::Access::ReadWrite);
75 auto contig_local_view_1d = Kokkos::subview (contig_local_view_2d, Kokkos::ALL (), 0);
76 return contig_local_view_1d.data();
87 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
93 Node> >::get1dCopy(
const Teuchos::ArrayView<scalar_t>& av,
96 const Tpetra::Map<LocalOrdinal,
98 Node> > distribution_map,
103 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
104 const size_t num_vecs = getGlobalNumVectors ();
106 TEUCHOS_TEST_FOR_EXCEPTION(
107 distribution_map.getRawPtr () == NULL, std::invalid_argument,
108 "Amesos2::MultiVecAdapter::get1dCopy: distribution_map argument is null.");
109 TEUCHOS_TEST_FOR_EXCEPTION(
110 mv_.is_null (), std::logic_error,
111 "Amesos2::MultiVecAdapter::get1dCopy: mv_ is null.");
113 TEUCHOS_TEST_FOR_EXCEPTION(
114 this->getMap ().is_null (), std::logic_error,
115 "Amesos2::MultiVecAdapter::get1dCopy: this->getMap() returns null.");
117 #ifdef HAVE_AMESOS2_DEBUG
118 const size_t requested_vector_length = distribution_map->getLocalNumElements ();
119 TEUCHOS_TEST_FOR_EXCEPTION(
120 lda < requested_vector_length, std::invalid_argument,
121 "Amesos2::MultiVecAdapter::get1dCopy: On process " <<
122 distribution_map->getComm ()->getRank () <<
" of the distribution Map's "
123 "communicator, the given stride lda = " << lda <<
" is not large enough "
124 "for the local vector length " << requested_vector_length <<
".");
125 TEUCHOS_TEST_FOR_EXCEPTION(
126 as<size_t> (av.size ()) < as<size_t> ((num_vecs - 1) * lda + requested_vector_length),
127 std::invalid_argument,
"Amesos2::MultiVector::get1dCopy: MultiVector "
128 "storage not large enough given leading dimension and number of vectors." );
129 #endif // HAVE_AMESOS2_DEBUG
132 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
133 mv_->get1dCopy (av, lda);
140 RCP<const map_type> distMap;
141 if (exporter_.is_null () ||
142 ! exporter_->getSourceMap ()->isSameAs (* (this->getMap ())) ||
143 ! exporter_->getTargetMap ()->isSameAs (* distribution_map)) {
149 distMap = rcp(
new map_type(*distribution_map));
151 exporter_ = rcp (
new export_type (this->getMap (), distMap));
154 distMap = exporter_->getTargetMap ();
157 multivec_t redist_mv (distMap, num_vecs);
160 redist_mv.doExport (*mv_, *exporter_, Tpetra::REPLACE);
162 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
165 redist_mv.get1dCopy (av, lda);
171 auto contig_local_view_2d = redist_mv.getLocalViewHost(Tpetra::Access::ReadOnly);
172 if ( redist_mv.isConstantStride() ) {
173 for (
size_t j = 0; j < num_vecs; ++j) {
174 auto av_j = av(lda*j, lda);
175 for (
size_t i = 0; i < lda; ++i ) {
176 av_j[i] = contig_local_view_2d(i,j);
185 const size_t lclNumRows = redist_mv.getLocalLength();
186 for (
size_t j = 0; j < redist_mv.getNumVectors(); ++j) {
187 auto av_j = av(lda*j, lclNumRows);
188 auto X_lcl_j_2d = redist_mv.getLocalViewHost(Tpetra::Access::ReadOnly);
189 auto X_lcl_j_1d = Kokkos::subview (X_lcl_j_2d, Kokkos::ALL (), j);
191 using val_type =
typename std::remove_const<typename decltype( X_lcl_j_1d )::value_type>::type;
192 Kokkos::View<val_type*, Kokkos::HostSpace> umavj ( const_cast< val_type* > ( reinterpret_cast<const val_type*> ( av_j.getRawPtr () ) ), av_j.size () );
193 Kokkos::deep_copy (umavj, X_lcl_j_1d);
200 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
201 template <
typename KV>
204 MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>
205 >::get1dCopy_kokkos_view(
208 [[maybe_unused]]
size_t lda,
209 Teuchos::Ptr<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > distribution_map,
214 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
215 const size_t num_vecs = getGlobalNumVectors ();
217 TEUCHOS_TEST_FOR_EXCEPTION(
218 distribution_map.getRawPtr () == NULL, std::invalid_argument,
219 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: distribution_map argument is null.");
220 TEUCHOS_TEST_FOR_EXCEPTION(
221 mv_.is_null (), std::logic_error,
222 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: mv_ is null.");
224 TEUCHOS_TEST_FOR_EXCEPTION(
225 this->getMap ().is_null (), std::logic_error,
226 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: this->getMap() returns null.");
228 #ifdef HAVE_AMESOS2_DEBUG
229 const size_t requested_vector_length = distribution_map->getLocalNumElements ();
230 TEUCHOS_TEST_FOR_EXCEPTION(
231 lda < requested_vector_length, std::invalid_argument,
232 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: On process " <<
233 distribution_map->getComm ()->getRank () <<
" of the distribution Map's "
234 "communicator, the given stride lda = " << lda <<
" is not large enough "
235 "for the local vector length " << requested_vector_length <<
".");
239 #endif // HAVE_AMESOS2_DEBUG
242 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
243 if(mv_->isConstantStride()) {
246 deep_copy_only(bInitialize, kokkos_view, mv_->getLocalViewDevice(Tpetra::Access::ReadOnly), bAssigned);
250 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Resolve handling for non-constant stride.");
258 RCP<const map_type> distMap;
259 if (exporter_.is_null () ||
260 ! exporter_->getSourceMap ()->isSameAs (* (this->getMap ())) ||
261 ! exporter_->getTargetMap ()->isSameAs (* distribution_map)) {
267 distMap = rcp(
new map_type(*distribution_map));
269 exporter_ = rcp (
new export_type (this->getMap (), distMap));
272 distMap = exporter_->getTargetMap ();
275 multivec_t redist_mv (distMap, num_vecs);
278 redist_mv.doExport (*mv_, *exporter_, Tpetra::REPLACE);
280 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
284 deep_copy_or_assign_view(bInitialize, kokkos_view, redist_mv.getLocalViewDevice(Tpetra::Access::ReadOnly), bAssigned);
288 if(redist_mv.isConstantStride()) {
290 deep_copy_or_assign_view(bInitialize, kokkos_view, redist_mv.getLocalViewDevice(Tpetra::Access::ReadOnly), bAssigned);
294 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Kokkos adapter non-constant stride not imlemented.");
300 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
301 Teuchos::ArrayRCP<Scalar>
306 Node> >::get1dViewNonConst (
bool local)
312 TEUCHOS_TEST_FOR_EXCEPTION(
313 true, std::logic_error,
"Amesos2::MultiVecAdapter::get1dViewNonConst: "
367 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node>
373 Node> >::put1dData(
const Teuchos::ArrayView<const scalar_t>& new_data,
376 const Tpetra::Map<LocalOrdinal,
382 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
384 TEUCHOS_TEST_FOR_EXCEPTION(
385 source_map.getRawPtr () == NULL, std::invalid_argument,
386 "Amesos2::MultiVecAdapter::put1dData: source_map argument is null.");
387 TEUCHOS_TEST_FOR_EXCEPTION(
388 mv_.is_null (), std::logic_error,
389 "Amesos2::MultiVecAdapter::put1dData: the internal MultiVector mv_ is null.");
391 TEUCHOS_TEST_FOR_EXCEPTION(
392 this->getMap ().is_null (), std::logic_error,
393 "Amesos2::MultiVecAdapter::put1dData: this->getMap() returns null.");
395 const size_t num_vecs = getGlobalNumVectors ();
398 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
400 auto mv_view_to_modify_2d = mv_->getLocalViewHost(Tpetra::Access::OverwriteAll);
401 for (
size_t i = 0; i < lda; ++i ) {
402 mv_view_to_modify_2d(i,0) = new_data[i];
410 RCP<const map_type> srcMap;
411 if (importer_.is_null () ||
412 ! importer_->getSourceMap ()->isSameAs (* source_map) ||
413 ! importer_->getTargetMap ()->isSameAs (* (this->getMap ()))) {
419 srcMap = rcp(
new map_type(*source_map));
420 importer_ = rcp (
new import_type (srcMap, this->getMap ()));
423 srcMap = importer_->getSourceMap ();
426 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
429 const multivec_t source_mv (srcMap, new_data, lda, num_vecs);
430 mv_->doImport (source_mv, *importer_, Tpetra::REPLACE);
433 multivec_t redist_mv (srcMap, num_vecs);
434 if ( redist_mv.isConstantStride() ) {
435 auto contig_local_view_2d = redist_mv.getLocalViewHost(Tpetra::Access::OverwriteAll);
436 for (
size_t j = 0; j < num_vecs; ++j) {
437 auto av_j = new_data(lda*j, lda);
438 for (
size_t i = 0; i < lda; ++i ) {
439 contig_local_view_2d(i,j) = av_j[i];
448 const size_t lclNumRows = redist_mv.getLocalLength();
449 for (
size_t j = 0; j < redist_mv.getNumVectors(); ++j) {
450 auto av_j = new_data(lda*j, lclNumRows);
451 auto X_lcl_j_2d = redist_mv.getLocalViewHost(Tpetra::Access::ReadOnly);
452 auto X_lcl_j_1d = Kokkos::subview (X_lcl_j_2d, Kokkos::ALL (), j);
454 using val_type =
typename std::remove_const<typename decltype( X_lcl_j_1d )::value_type>::type;
455 Kokkos::View<val_type*, Kokkos::HostSpace> umavj ( const_cast< val_type* > ( reinterpret_cast<const val_type*> ( av_j.getRawPtr () ) ), av_j.size () );
456 Kokkos::deep_copy (umavj, X_lcl_j_1d);
463 mv_->doImport (redist_mv, *importer_, Tpetra::REPLACE);
469 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node>
470 template <
typename KV>
476 Node> >::put1dData_kokkos_view(KV& kokkos_new_data,
479 const Tpetra::Map<LocalOrdinal,
485 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
487 TEUCHOS_TEST_FOR_EXCEPTION(
488 source_map.getRawPtr () == NULL, std::invalid_argument,
489 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: source_map argument is null.");
490 TEUCHOS_TEST_FOR_EXCEPTION(
491 mv_.is_null (), std::logic_error,
492 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: the internal MultiVector mv_ is null.");
494 TEUCHOS_TEST_FOR_EXCEPTION(
495 this->getMap ().is_null (), std::logic_error,
496 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: this->getMap() returns null.");
498 const size_t num_vecs = getGlobalNumVectors ();
501 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
506 auto mv_view_to_modify_2d = mv_->getLocalViewDevice(Tpetra::Access::OverwriteAll);
508 deep_copy_only(mv_view_to_modify_2d, kokkos_new_data);
515 RCP<const map_type> srcMap;
516 if (importer_.is_null () ||
517 ! importer_->getSourceMap ()->isSameAs (* source_map) ||
518 ! importer_->getTargetMap ()->isSameAs (* (this->getMap ()))) {
524 srcMap = rcp(
new map_type(*source_map));
525 importer_ = rcp (
new import_type (srcMap, this->getMap ()));
528 srcMap = importer_->getSourceMap ();
531 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
536 typedef typename multivec_t::dual_view_type::t_host::value_type tpetra_mv_view_type;
537 Kokkos::View<tpetra_mv_view_type**,
typename KV::array_layout,
538 Kokkos::HostSpace> convert_kokkos_new_data;
539 deep_copy_or_assign_view(convert_kokkos_new_data, kokkos_new_data);
540 #ifdef HAVE_TEUCHOS_COMPLEX
542 auto pData =
reinterpret_cast<Scalar*
>(convert_kokkos_new_data.data());
544 auto pData = convert_kokkos_new_data.data();
547 const multivec_t source_mv (srcMap, Teuchos::ArrayView<const scalar_t>(
548 pData, kokkos_new_data.size()), lda, num_vecs);
549 mv_->doImport (source_mv, *importer_, Tpetra::REPLACE);
552 multivec_t redist_mv (srcMap, num_vecs);
557 auto host_kokkos_new_data = Kokkos::create_mirror_view(kokkos_new_data);
558 Kokkos::deep_copy(host_kokkos_new_data, kokkos_new_data);
559 if ( redist_mv.isConstantStride() ) {
560 auto contig_local_view_2d = redist_mv.getLocalViewHost(Tpetra::Access::OverwriteAll);
561 for (
size_t j = 0; j < num_vecs; ++j) {
562 auto av_j = Kokkos::subview(host_kokkos_new_data, Kokkos::ALL, j);
563 for (
size_t i = 0; i < lda; ++i ) {
564 contig_local_view_2d(i,j) = av_j(i);
569 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Kokkos adapter "
570 "CONTIGUOUS_AND_ROOTED not implemented for put1dData_kokkos_view "
571 "with non constant stride.");
577 mv_->doImport (redist_mv, *importer_, Tpetra::REPLACE);
583 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
589 Node> >::description()
const
591 std::ostringstream oss;
592 oss <<
"Amesos2 adapter wrapping: ";
593 oss << mv_->description();
598 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
604 Node> >::describe (Teuchos::FancyOStream& os,
605 const Teuchos::EVerbosityLevel verbLevel)
const
607 mv_->describe (os, verbLevel);
611 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
612 const char* MultiVecAdapter<
616 Node> >::name =
"Amesos2 adapter for Tpetra::MultiVector";
620 #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:89