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 )
75 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
76 typename MultiVecAdapter<
80 Node> >::multivec_t::impl_scalar_type *
85 Node> >::getMVPointer_impl()
const
87 TEUCHOS_TEST_FOR_EXCEPTION( this->getGlobalNumVectors() != 1,
88 std::invalid_argument,
89 "Amesos2_TpetraMultiVectorAdapter: getMVPointer_impl should only be called for case with a single vector and single MPI process" );
91 typedef typename multivec_t::dual_view_type dual_view_type;
92 typedef typename dual_view_type::host_mirror_space host_execution_space;
93 mv_->template sync<host_execution_space> ();
94 auto contig_local_view_2d = mv_->template getLocalView<host_execution_space>();
95 auto contig_local_view_1d = Kokkos::subview (contig_local_view_2d, Kokkos::ALL (), 0);
96 return contig_local_view_1d.data();
107 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
113 Node> >::get1dCopy(
const Teuchos::ArrayView<scalar_t>& av,
116 const Tpetra::Map<LocalOrdinal,
118 Node> > distribution_map,
123 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
124 const size_t num_vecs = getGlobalNumVectors ();
126 TEUCHOS_TEST_FOR_EXCEPTION(
127 distribution_map.getRawPtr () == NULL, std::invalid_argument,
128 "Amesos2::MultiVecAdapter::get1dCopy: distribution_map argument is null.");
129 TEUCHOS_TEST_FOR_EXCEPTION(
130 mv_.is_null (), std::logic_error,
131 "Amesos2::MultiVecAdapter::get1dCopy: mv_ is null.");
133 TEUCHOS_TEST_FOR_EXCEPTION(
134 this->getMap ().is_null (), std::logic_error,
135 "Amesos2::MultiVecAdapter::get1dCopy: this->getMap() returns null.");
137 #ifdef HAVE_AMESOS2_DEBUG
138 const size_t requested_vector_length = distribution_map->getNodeNumElements ();
139 TEUCHOS_TEST_FOR_EXCEPTION(
140 lda < requested_vector_length, std::invalid_argument,
141 "Amesos2::MultiVecAdapter::get1dCopy: On process " <<
142 distribution_map->getComm ()->getRank () <<
" of the distribution Map's "
143 "communicator, the given stride lda = " << lda <<
" is not large enough "
144 "for the local vector length " << requested_vector_length <<
".");
145 TEUCHOS_TEST_FOR_EXCEPTION(
146 as<size_t> (av.size ()) < as<size_t> ((num_vecs - 1) * lda + requested_vector_length),
147 std::invalid_argument,
"Amesos2::MultiVector::get1dCopy: MultiVector "
148 "storage not large enough given leading dimension and number of vectors." );
149 #endif // HAVE_AMESOS2_DEBUG
152 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
153 mv_->get1dCopy (av, lda);
160 RCP<const map_type> distMap;
161 if (exporter_.is_null () ||
162 ! exporter_->getSourceMap ()->isSameAs (* (this->getMap ())) ||
163 ! exporter_->getTargetMap ()->isSameAs (* distribution_map)) {
169 distMap = rcp(
new map_type(*distribution_map));
171 exporter_ = rcp (
new export_type (this->getMap (), distMap));
174 distMap = exporter_->getTargetMap ();
177 multivec_t redist_mv (distMap, num_vecs);
180 redist_mv.doExport (*mv_, *exporter_, Tpetra::REPLACE);
182 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
185 redist_mv.get1dCopy (av, lda);
190 typedef typename multivec_t::dual_view_type dual_view_type;
191 typedef typename dual_view_type::host_mirror_space host_execution_space;
192 redist_mv.template sync < host_execution_space > ();
194 auto contig_local_view_2d = redist_mv.template getLocalView<host_execution_space>();
195 if ( redist_mv.isConstantStride() ) {
196 for (
size_t j = 0; j < num_vecs; ++j) {
197 auto av_j = av(lda*j, lda);
198 for (
size_t i = 0; i < lda; ++i ) {
199 av_j[i] = contig_local_view_2d(i,j);
208 const size_t lclNumRows = redist_mv.getLocalLength();
209 for (
size_t j = 0; j < redist_mv.getNumVectors(); ++j) {
210 auto av_j = av(lda*j, lclNumRows);
211 auto X_lcl_j_2d = redist_mv.template getLocalView<host_execution_space> ();
212 auto X_lcl_j_1d = Kokkos::subview (X_lcl_j_2d, Kokkos::ALL (), j);
214 using val_type =
typename decltype( X_lcl_j_1d )::value_type;
215 Kokkos::View<val_type*, Kokkos::HostSpace> umavj ( const_cast< val_type* > ( reinterpret_cast<const val_type*> ( av_j.getRawPtr () ) ), av_j.size () );
216 Kokkos::deep_copy (umavj, X_lcl_j_1d);
223 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
224 template <
typename KV>
230 Node> >::get1dCopy_kokkos_view(KV& kokkos_view,
233 const Tpetra::Map<LocalOrdinal,
235 Node> > distribution_map,
240 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
241 const size_t num_vecs = getGlobalNumVectors ();
243 TEUCHOS_TEST_FOR_EXCEPTION(
244 distribution_map.getRawPtr () == NULL, std::invalid_argument,
245 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: distribution_map argument is null.");
246 TEUCHOS_TEST_FOR_EXCEPTION(
247 mv_.is_null (), std::logic_error,
248 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: mv_ is null.");
250 TEUCHOS_TEST_FOR_EXCEPTION(
251 this->getMap ().is_null (), std::logic_error,
252 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: this->getMap() returns null.");
254 #ifdef HAVE_AMESOS2_DEBUG
255 const size_t requested_vector_length = distribution_map->getNodeNumElements ();
256 TEUCHOS_TEST_FOR_EXCEPTION(
257 lda < requested_vector_length, std::invalid_argument,
258 "Amesos2::MultiVecAdapter::get1dCopy_kokkos_view: On process " <<
259 distribution_map->getComm ()->getRank () <<
" of the distribution Map's "
260 "communicator, the given stride lda = " << lda <<
" is not large enough "
261 "for the local vector length " << requested_vector_length <<
".");
265 #endif // HAVE_AMESOS2_DEBUG
268 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
269 if(mv_->isConstantStride()) {
270 deep_copy_or_assign_view(kokkos_view, mv_->getLocalViewDevice());
273 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Resolve handling for non-constant stride.");
281 RCP<const map_type> distMap;
282 if (exporter_.is_null () ||
283 ! exporter_->getSourceMap ()->isSameAs (* (this->getMap ())) ||
284 ! exporter_->getTargetMap ()->isSameAs (* distribution_map)) {
290 distMap = rcp(
new map_type(*distribution_map));
292 exporter_ = rcp (
new export_type (this->getMap (), distMap));
295 distMap = exporter_->getTargetMap ();
298 multivec_t redist_mv (distMap, num_vecs);
301 redist_mv.doExport (*mv_, *exporter_, Tpetra::REPLACE);
303 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
306 deep_copy_or_assign_view(kokkos_view, redist_mv.getLocalViewDevice());
309 if(redist_mv.isConstantStride()) {
310 deep_copy_or_assign_view(kokkos_view, redist_mv.getLocalViewDevice());
313 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Kokkos adapter non-constant stride not imlemented.");
319 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
320 Teuchos::ArrayRCP<Scalar>
325 Node> >::get1dViewNonConst (
bool local)
331 TEUCHOS_TEST_FOR_EXCEPTION(
332 true, std::logic_error,
"Amesos2::MultiVecAdapter::get1dViewNonConst: "
386 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node>
392 Node> >::put1dData(
const Teuchos::ArrayView<const scalar_t>& new_data,
395 const Tpetra::Map<LocalOrdinal,
401 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
403 TEUCHOS_TEST_FOR_EXCEPTION(
404 source_map.getRawPtr () == NULL, std::invalid_argument,
405 "Amesos2::MultiVecAdapter::put1dData: source_map argument is null.");
406 TEUCHOS_TEST_FOR_EXCEPTION(
407 mv_.is_null (), std::logic_error,
408 "Amesos2::MultiVecAdapter::put1dData: the internal MultiVector mv_ is null.");
410 TEUCHOS_TEST_FOR_EXCEPTION(
411 this->getMap ().is_null (), std::logic_error,
412 "Amesos2::MultiVecAdapter::put1dData: this->getMap() returns null.");
414 const size_t num_vecs = getGlobalNumVectors ();
417 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
418 typedef typename multivec_t::dual_view_type::host_mirror_space host_execution_space;
420 auto mv_view_to_modify_2d = mv_->template getLocalView<host_execution_space>();
421 for (
size_t i = 0; i < lda; ++i ) {
422 mv_view_to_modify_2d(i,0) = new_data[i];
430 RCP<const map_type> srcMap;
431 if (importer_.is_null () ||
432 ! importer_->getSourceMap ()->isSameAs (* source_map) ||
433 ! importer_->getTargetMap ()->isSameAs (* (this->getMap ()))) {
439 srcMap = rcp(
new map_type(*source_map));
440 importer_ = rcp (
new import_type (srcMap, this->getMap ()));
443 srcMap = importer_->getSourceMap ();
446 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
449 const multivec_t source_mv (srcMap, new_data, lda, num_vecs);
450 mv_->doImport (source_mv, *importer_, Tpetra::REPLACE);
453 multivec_t redist_mv (srcMap, num_vecs);
454 typedef typename multivec_t::dual_view_type dual_view_type;
455 typedef typename dual_view_type::host_mirror_space host_execution_space;
456 redist_mv.template modify< host_execution_space > ();
458 if ( redist_mv.isConstantStride() ) {
459 auto contig_local_view_2d = redist_mv.template getLocalView<host_execution_space>();
460 for (
size_t j = 0; j < num_vecs; ++j) {
461 auto av_j = new_data(lda*j, lda);
462 for (
size_t i = 0; i < lda; ++i ) {
463 contig_local_view_2d(i,j) = av_j[i];
472 const size_t lclNumRows = redist_mv.getLocalLength();
473 for (
size_t j = 0; j < redist_mv.getNumVectors(); ++j) {
474 auto av_j = new_data(lda*j, lclNumRows);
475 auto X_lcl_j_2d = redist_mv.template getLocalView<host_execution_space> ();
476 auto X_lcl_j_1d = Kokkos::subview (X_lcl_j_2d, Kokkos::ALL (), j);
478 using val_type =
typename decltype( X_lcl_j_1d )::value_type;
479 Kokkos::View<val_type*, Kokkos::HostSpace> umavj ( const_cast< val_type* > ( reinterpret_cast<const val_type*> ( av_j.getRawPtr () ) ), av_j.size () );
480 Kokkos::deep_copy (umavj, X_lcl_j_1d);
484 typedef typename multivec_t::node_type::memory_space memory_space;
485 redist_mv.template sync <memory_space> ();
487 mv_->doImport (redist_mv, *importer_, Tpetra::REPLACE);
493 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node>
494 template <
typename KV>
500 Node> >::put1dData_kokkos_view(KV& kokkos_new_data,
503 const Tpetra::Map<LocalOrdinal,
509 typedef Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> map_type;
511 TEUCHOS_TEST_FOR_EXCEPTION(
512 source_map.getRawPtr () == NULL, std::invalid_argument,
513 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: source_map argument is null.");
514 TEUCHOS_TEST_FOR_EXCEPTION(
515 mv_.is_null (), std::logic_error,
516 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: the internal MultiVector mv_ is null.");
518 TEUCHOS_TEST_FOR_EXCEPTION(
519 this->getMap ().is_null (), std::logic_error,
520 "Amesos2::MultiVecAdapter::put1dData_kokkos_view: this->getMap() returns null.");
522 const size_t num_vecs = getGlobalNumVectors ();
525 if ( num_vecs == 1 && this->getComm()->getRank() == 0 && this->getComm()->getSize() == 1 ) {
530 auto mv_view_to_modify_2d = mv_->getLocalViewDevice();
531 deep_copy_or_assign_view(mv_view_to_modify_2d, kokkos_new_data);
538 RCP<const map_type> srcMap;
539 if (importer_.is_null () ||
540 ! importer_->getSourceMap ()->isSameAs (* source_map) ||
541 ! importer_->getTargetMap ()->isSameAs (* (this->getMap ()))) {
547 srcMap = rcp(
new map_type(*source_map));
548 importer_ = rcp (
new import_type (srcMap, this->getMap ()));
551 srcMap = importer_->getSourceMap ();
554 if ( distribution != CONTIGUOUS_AND_ROOTED ) {
559 typedef typename multivec_t::dual_view_type::t_host::value_type tpetra_mv_view_type;
560 Kokkos::View<tpetra_mv_view_type**,
typename KV::array_layout,
561 Kokkos::HostSpace> convert_kokkos_new_data;
562 deep_copy_or_assign_view(convert_kokkos_new_data, kokkos_new_data);
563 #ifdef HAVE_TEUCHOS_COMPLEX
565 auto pData =
reinterpret_cast<Scalar*
>(convert_kokkos_new_data.data());
567 auto pData = convert_kokkos_new_data.data();
570 const multivec_t source_mv (srcMap, Teuchos::ArrayView<const scalar_t>(
571 pData, kokkos_new_data.size()), lda, num_vecs);
572 mv_->doImport (source_mv, *importer_, Tpetra::REPLACE);
575 multivec_t redist_mv (srcMap, num_vecs);
576 typedef typename multivec_t::dual_view_type dual_view_type;
577 typedef typename dual_view_type::host_mirror_space host_execution_space;
578 redist_mv.template modify< host_execution_space > ();
584 auto host_kokkos_new_data = Kokkos::create_mirror_view(kokkos_new_data);
585 Kokkos::deep_copy(host_kokkos_new_data, kokkos_new_data);
586 if ( redist_mv.isConstantStride() ) {
587 auto contig_local_view_2d = redist_mv.template getLocalView<host_execution_space>();
588 for (
size_t j = 0; j < num_vecs; ++j) {
589 auto av_j = Kokkos::subview(host_kokkos_new_data, Kokkos::ALL, j);
590 for (
size_t i = 0; i < lda; ++i ) {
591 contig_local_view_2d(i,j) = av_j(i);
596 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::runtime_error,
"Kokkos adapter "
597 "CONTIGUOUS_AND_ROOTED not implemented for put1dData_kokkos_view "
598 "with non constant stride.");
601 typedef typename multivec_t::node_type::memory_space memory_space;
602 redist_mv.template sync <memory_space> ();
604 mv_->doImport (redist_mv, *importer_, Tpetra::REPLACE);
610 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
616 Node> >::description()
const
618 std::ostringstream oss;
619 oss <<
"Amesos2 adapter wrapping: ";
620 oss << mv_->description();
625 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
631 Node> >::describe (Teuchos::FancyOStream& os,
632 const Teuchos::EVerbosityLevel verbLevel)
const
634 mv_->describe (os, verbLevel);
638 template <
typename Scalar,
typename LocalOrdinal,
typename GlobalOrdinal,
class Node >
639 const char* MultiVecAdapter<
643 Node> >::name =
"Amesos2 adapter for Tpetra::MultiVector";
647 #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