Amesos2 - Direct Sparse Solver Interfaces Version of the Day
Amesos2_MultiVecAdapter_def.hpp
1// @HEADER
2// *****************************************************************************
3// Amesos2: Templated Direct Sparse Solver Package
4//
5// Copyright 2011 NTESS and the Amesos2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10
11#ifndef AMESOS2_MULTIVECADAPTER_DEF_HPP
12#define AMESOS2_MULTIVECADAPTER_DEF_HPP
13
16
17#include "Amesos2_Util.hpp" // for getDistributionMap
18
19namespace Amesos2{
20
21 namespace Util {
22
24 // Pointer-getting utilities //
26
27 template <typename MV, typename V>
28 typename vector_pointer_helper<MV, V>::ptr_return_type *
29 vector_pointer_helper<MV, V>::get_pointer_to_vector ( const Teuchos::Ptr< MV > &mv ) {
30 return mv->getMVPointer_impl();
31 }
32
33 template <typename MV, typename V>
34 typename vector_pointer_helper<MV, V>::ptr_return_type *
35 vector_pointer_helper<MV, V>::get_pointer_to_vector ( Teuchos::Ptr< MV > &mv ) {
36 return mv->getMVPointer_impl();
37 }
38
39 template <typename MV, typename V>
40 typename vector_pointer_helper<MV, V>::ptr_return_type *
41 vector_pointer_helper<MV, V>::get_pointer_to_vector ( const Teuchos::Ptr< const MV > &mv ) {
42 return mv->getMVPointer_impl();
43 }
44
45 template <typename MV, typename V>
46 typename vector_pointer_helper<MV, V>::ptr_return_type *
47 vector_pointer_helper<MV, V>::get_pointer_to_vector ( Teuchos::Ptr< const MV > &mv ) {
48 return mv->getMVPointer_impl();
49 }
50
51
53 // Copy-getting utilities //
55
56 /*
57 * If the multivector scalar type and the desired scalar tpye are
58 * the same, then we can do a simple straight copy.
59 */
60 template <typename MV>
61 void same_type_get_copy<MV>::apply(const Teuchos::Ptr<const MV> mv,
62 const Teuchos::ArrayView<typename MV::scalar_t>& v,
63 const size_t ldx,
64 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
65 EDistribution distribution )
66 {
67 mv->get1dCopy (v, ldx, distribution_map, distribution);
68 }
69
70 /*
71 * In the case where the scalar type of the multi-vector and the
72 * corresponding S type are different, then we need to first get a
73 * copy of the scalar values, then convert each one into the S
74 * type before inserting into the vals array.
75 */
76 template <typename MV, typename S>
77 void diff_type_get_copy<MV,S>::
78 apply (const Teuchos::Ptr<const MV> mv,
79 const Teuchos::ArrayView<S>& v,
80 const size_t ldx,
81 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
82 EDistribution distribution )
83 {
84 typedef typename MV::scalar_t mv_scalar_t;
85 typedef typename Teuchos::Array<mv_scalar_t>::size_type size_type;
86
87 TEUCHOS_TEST_FOR_EXCEPTION(
88 mv.getRawPtr () == NULL, std::invalid_argument,
89 "Amesos2::diff_type_get_copy::apply: mv is null.");
90 TEUCHOS_TEST_FOR_EXCEPTION(
91 distribution_map.getRawPtr () == NULL, std::invalid_argument,
92 "Amesos2::diff_type_get_copy::apply: distribution_map is null.");
93
94 const size_type vals_length = v.size ();
95 Teuchos::Array<mv_scalar_t> vals_tmp (vals_length);
96
97 mv->get1dCopy (vals_tmp (), ldx, distribution_map, distribution);
98 for (size_type i = 0; i < vals_length; ++i) {
99 v[i] = Teuchos::as<S> (vals_tmp[i]);
100 }
101 }
102
109 template <class MV, typename S>
111 do_get (const Teuchos::Ptr<const MV>& mv,
112 const Teuchos::ArrayView<S>& vals,
113 const size_t ldx,
114 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
115 EDistribution distribution)
116 {
117 // Dispatch to the copy function appropriate for the type
118 std::conditional_t<std::is_same_v<typename MV::scalar_t,S>,
119 same_type_get_copy<MV>,
120 diff_type_get_copy<MV,S> >::apply (mv, vals, ldx, distribution_map, distribution);
121 }
122
123 template <class MV, typename S>
125 do_get (const Teuchos::Ptr<const MV>& mv,
126 const Teuchos::ArrayView<S>& vals,
127 const size_t ldx,
128 EDistribution distribution,
129 typename MV::global_ordinal_t indexBase)
130 {
131 typedef typename MV::local_ordinal_t lo_t;
132 typedef typename MV::global_ordinal_t go_t;
133 typedef typename MV::global_size_t gs_t;
134 typedef typename MV::node_t node_t;
135
136 TEUCHOS_TEST_FOR_EXCEPTION(
137 mv.getRawPtr () == NULL, std::invalid_argument,
138 "Amesos2::get_1d_copy_helper::do_get(5 args): mv is null.");
139
140 Teuchos::RCP<const Tpetra::Map<lo_t,go_t,node_t> > map
141 = Amesos2::Util::getDistributionMap<lo_t,go_t,gs_t,node_t> (distribution,
142 mv->getGlobalLength (),
143 mv->getComm (),
144 indexBase,
145 mv->getMap());
146
147 do_get (mv, vals, ldx, Teuchos::ptrInArg (*map), distribution);
148 }
149
150 template <class MV, typename S>
151 void get_1d_copy_helper<MV,S>::do_get(const Teuchos::Ptr<const MV>& mv,
152 const Teuchos::ArrayView<S>& vals,
153 const size_t ldx)
154 {
155 typedef Tpetra::Map<typename MV::local_ordinal_t,
156 typename MV::global_ordinal_t,
157 typename MV::node_t> map_type;
158 TEUCHOS_TEST_FOR_EXCEPTION(
159 mv.getRawPtr () == NULL, std::invalid_argument,
160 "Amesos2::get_1d_copy_helper::do_get(3 args): mv is null.");
161
162 Teuchos::RCP<const map_type> map = mv->getMap ();
163 TEUCHOS_TEST_FOR_EXCEPTION(
164 map.is_null (), std::invalid_argument,
165 "Amesos2::get_1d_copy_helper::do_get(3 args): mv->getMap() is null.");
166
167 do_get (mv, vals, ldx, Teuchos::ptrInArg (*map), ROOTED); // ROOTED the default here for now
168 }
169
170 // KV
171 template <class MV, typename KV>
172 bool diff_type_get_view<MV, KV>::
173 apply (bool bInitialize,
174 const Teuchos::Ptr<const MV>& mv,
175 KV& kokkos_vals,
176 const size_t ldx,
177 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
178 EDistribution distribution)
179 {
180 using input_scalar_type = typename MV::scalar_t;
181 using output_scalar_type = typename KV::non_const_value_type;
182 using execution_space = typename KV::execution_space;
183 using memory_space = typename execution_space::memory_space;
184
185 // copy to workspace (of same type as input scalar type)
186 Kokkos::View<input_scalar_type**, Kokkos::LayoutLeft, memory_space> output_view;
187 bool bAssigned = mv->get1dCopy_kokkos_view(bInitialize, output_view, ldx, distribution_map, distribution);
188
189 // copy back (of the output scalar type)
190 const size_t nrows = output_view.extent(0);
191 const size_t ncols = output_view.extent(1);
192 Kokkos::resize(kokkos_vals, ldx, ncols);
193
194 #if 1
195 auto h_output_view = Kokkos::create_mirror_view(output_view);
196 auto h_kokkos_vals = Kokkos::create_mirror_view(kokkos_vals);
197 Kokkos::deep_copy(output_view, h_output_view);
198 for (size_t j=0; j<ncols; j++) {
199 for (size_t i=0; i<nrows; i++) h_kokkos_vals(i,j) = Teuchos::as<output_scalar_type> (h_output_view(i,j));
200 }
201 Kokkos::deep_copy(kokkos_vals, h_kokkos_vals);
202 #else
203 //Kokkos::parallel_for("Amesos2::MultiVecAdapter::diff_type_get_view::apply", Kokkos::RangePolicy<execution_space>(0, nrows),
204 // KOKKOS_LAMBDA(const int i) { for (size_t j=0; j<ncols; j++) kokkos_vals(i,j) = Teuchos::as<output_scalar_type> (output_view(i,j)); });
205 #endif
206
207 // made a copy, instead of assigning input pointer (so safe to shallow-copy, which won't over-write the original memory space)
208 bAssigned = false;
209 return bAssigned;
210 }
211
212 template <class MV, class KV>
213 bool same_type_get_view<MV, KV>::
214 apply (bool bInitialize,
215 const Teuchos::Ptr<const MV>& mv,
216 KV& kokkos_vals,
217 const size_t ldx,
218 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
219 EDistribution distribution)
220 {
221 return mv->get1dCopy_kokkos_view(bInitialize, kokkos_vals, ldx, distribution_map, distribution);
222 }
223
224 // > entry point
225 template <class MV, typename KV>
226 bool get_1d_copy_helper_kokkos_view<MV,KV>::
227 do_get (bool bInitialize,
228 const Teuchos::Ptr<const MV>& mv,
229 KV& kokkos_vals,
230 const size_t ldx,
231 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
232 EDistribution distribution)
233 {
234 // TODO: check input-scalar (host vs non-host)
235 //using input_scalar_type = typename MV::scalar_t;
236 using input_scalar_type = typename MV::host_value_t;
237 using output_scalar_type = typename KV::non_const_value_type;
238
239 // call appropriate apply based on if the input and output scalar types are the same or different
240 bool bAssigned = std::conditional_t<std::is_same_v<input_scalar_type, output_scalar_type>,
241 same_type_get_view<MV, KV>,
242 diff_type_get_view<MV, KV>>::apply (bInitialize, mv, kokkos_vals, ldx, distribution_map, distribution);
243 return bAssigned;
244 }
245
246 template <class MV, typename KV>
247 bool get_1d_copy_helper_kokkos_view<MV,KV>::
248 do_get (bool bInitialize,
249 const Teuchos::Ptr<const MV>& mv,
250 KV& kokkos_vals,
251 const size_t ldx,
252 EDistribution distribution,
253 typename MV::global_ordinal_t indexBase)
254 {
255 typedef typename MV::local_ordinal_t lo_t;
256 typedef typename MV::global_ordinal_t go_t;
257 typedef typename MV::global_size_t gs_t;
258 typedef typename MV::node_t node_t;
259
260 TEUCHOS_TEST_FOR_EXCEPTION(
261 mv.getRawPtr () == NULL, std::invalid_argument,
262 "Amesos2::get_1d_copy_helper_kokkos_view::do_get(5 args): mv is null.");
263
264 Teuchos::RCP<const Tpetra::Map<lo_t,go_t,node_t> > map
265 = Amesos2::Util::getDistributionMap<lo_t,go_t,gs_t,node_t> (distribution,
266 mv->getGlobalLength (),
267 mv->getComm (),
268 indexBase,
269 mv->getMap());
270
271 return do_get (bInitialize, mv, kokkos_vals, ldx, Teuchos::ptrInArg (*map), distribution);
272 }
273
274 template <class MV, typename KV>
275 bool get_1d_copy_helper_kokkos_view<MV,KV>::
276 do_get (bool bInitialize,
277 const Teuchos::Ptr<const MV>& mv,
278 KV& kokkos_vals,
279 const size_t ldx)
280 {
281 typedef Tpetra::Map<typename MV::local_ordinal_t,
282 typename MV::global_ordinal_t,
283 typename MV::node_t> map_type;
284 TEUCHOS_TEST_FOR_EXCEPTION(
285 mv.getRawPtr () == NULL, std::invalid_argument,
286 "Amesos2::get_1d_copy_helper::do_get(3 args): mv is null.");
287
288 Teuchos::RCP<const map_type> map = mv->getMap ();
289 //NOTE: KokkosMultiVecAdapter returns null map
290 //TEUCHOS_TEST_FOR_EXCEPTION(
291 // map.is_null (), std::invalid_argument,
292 // "Amesos2::get_1d_copy_helper_kokkos_view::do_get(3 args): mv->getMap() is null.");
293
294 return do_get (bInitialize, mv, kokkos_vals, ldx, Teuchos::ptrInArg (*map), ROOTED); // ROOTED the default here for now
295 }
296
297
299 // Copy-puting utilities //
301
302 template <typename MV>
303 void same_type_data_put<MV>::apply(const Teuchos::Ptr<MV>& mv,
304 const Teuchos::ArrayView<typename MV::scalar_t>& data,
305 const size_t ldx,
306 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
307 EDistribution distribution )
308 {
309 mv->put1dData (data, ldx, distribution_map, distribution);
310 }
311
312 /*
313 * In the case where the scalar type of the multi-vector and the
314 * corresponding S type are different, then we need to first get a
315 * copy of the scalar values, then convert each one into the S
316 * type before inserting into the vals array.
317 */
318 template <typename MV, typename S>
319 void diff_type_data_put<MV,S>::apply(const Teuchos::Ptr<MV>& mv,
320 const Teuchos::ArrayView<S>& data,
321 const size_t ldx,
322 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
323 EDistribution distribution )
324 {
325 typedef typename MV::scalar_t mv_scalar_t;
326 typedef typename Teuchos::Array<mv_scalar_t>::size_type size_type;
327
328 TEUCHOS_TEST_FOR_EXCEPTION(
329 mv.getRawPtr () == NULL, std::invalid_argument,
330 "Amesos2::diff_type_data_put(4 args): mv is null.");
331
332 const size_type vals_length = data.size ();
333 Teuchos::Array<mv_scalar_t> data_tmp (vals_length);
334
335 for (size_type i = 0; i < vals_length; ++i) {
336 data_tmp[i] = Teuchos::as<mv_scalar_t> (data[i]);
337 }
338
339 mv->put1dData (data_tmp (), ldx, distribution_map, distribution);
340 }
341
342
349 template <class MV, typename S>
350 void put_1d_data_helper<MV,S>::do_put(const Teuchos::Ptr<MV>& mv,
351 const Teuchos::ArrayView<S>& data,
352 const size_t ldx,
353 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
354 EDistribution distribution )
355 {
356 // Dispatch to the copy function appropriate for the type
357 std::conditional_t<std::is_same_v<typename MV::scalar_t,S>,
358 same_type_data_put<MV>,
359 diff_type_data_put<MV,S> >::apply(mv, data, ldx, distribution_map, distribution);
360 }
361
362 template <class MV, typename S>
363 void put_1d_data_helper<MV,S>::do_put(const Teuchos::Ptr<MV>& mv,
364 const Teuchos::ArrayView<S>& data,
365 const size_t ldx,
366 EDistribution distribution, typename MV::global_ordinal_t indexBase)
367 {
368 typedef typename MV::local_ordinal_t lo_t;
369 typedef typename MV::global_ordinal_t go_t;
370 typedef typename MV::global_size_t gs_t;
371 typedef typename MV::node_t node_t;
372
373 const Teuchos::RCP<const Tpetra::Map<lo_t,go_t,node_t> > map
374 = Amesos2::Util::getDistributionMap<lo_t,go_t,gs_t,node_t>(distribution,
375 mv->getGlobalLength(),
376 mv->getComm(),
377 indexBase,
378 mv->getMap());
379
380 do_put(mv, data, ldx, Teuchos::ptrInArg(*map), distribution);
381 }
382
383 template <class MV, typename S>
384 void put_1d_data_helper<MV,S>::do_put (const Teuchos::Ptr<MV>& mv,
385 const Teuchos::ArrayView<S>& data,
386 const size_t ldx)
387 {
388 const Teuchos::RCP<const Tpetra::Map<typename MV::local_ordinal_t,
389 typename MV::global_ordinal_t,
390 typename MV::node_t> > map
391 = mv->getMap();
392 do_put (mv, data, ldx, Teuchos::ptrInArg (*map), ROOTED); // Default as ROOTED for now
393 }
394
395 // KV
396 template <class MV, class KV>
397 void same_type_put_view<MV,KV>::apply(const Teuchos::Ptr<MV>& mv,
398 KV& kokkos_data,
399 const size_t ldx,
400 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
401 EDistribution distribution )
402 {
403 mv->put1dData_kokkos_view(kokkos_data, ldx, distribution_map, distribution);
404 }
405
406 template <class MV, class KV>
407 void diff_type_put_view<MV,KV>::apply(const Teuchos::Ptr<MV>& mv,
408 KV& kokkos_data,
409 const size_t ldx,
410 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
411 EDistribution distribution )
412 {
413 // TODO: check input-scalar (host vs non-host)
414 //using output_scalar_type = typename MV::scalar_t;
415 using output_scalar_type = typename MV::host_value_t;
416 using execution_space = typename KV::execution_space;
417 using memory_space = typename execution_space::memory_space;
418
419 // copy to input workspace (of same type as output scalar type)
420 const size_t nrows = kokkos_data.extent(0);
421 const size_t ncols = kokkos_data.extent(1);
422 Kokkos::View<output_scalar_type**, Kokkos::LayoutLeft, memory_space> output_view ("output_view", ldx, ncols);
423
424 #if 1
425 auto h_output_view = Kokkos::create_mirror_view(output_view);
426 auto h_kokkos_data = Kokkos::create_mirror_view(kokkos_data);
427 Kokkos::deep_copy(h_kokkos_data, kokkos_data);
428 for (size_t j=0; j<ncols; j++) {
429 for (size_t i=0; i<nrows; i++) h_output_view(i,j) = Teuchos::as<output_scalar_type> (h_kokkos_data(i,j));
430 }
431 Kokkos::deep_copy(output_view, h_output_view);
432 #else
433 // TODO: how to custom-cast within parallel-for
434 Kokkos::parallel_for("Amesos2::MultiVecAdapter::diff_type_get_view::apply", Kokkos::RangePolicy<execution_space>(0, nrows),
435 KOKKOS_LAMBDA(const int i) { for (size_t j=0; j<ncols; j++) output_view(i,j) = Teuchos::as<output_scalar_type> (kokkos_data(i,j)); });
436 #endif
437
438 // put to output (of output scalar type)
439 mv->put1dData_kokkos_view(output_view, ldx, distribution_map, distribution);
440 }
441
442 template <class MV, typename KV>
443 void put_1d_data_helper_kokkos_view<MV,KV>::do_put(const Teuchos::Ptr<MV>& mv,
444 KV& kokkos_data,
445 const size_t ldx,
446 Teuchos::Ptr<const Tpetra::Map<typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t> > distribution_map,
447 EDistribution distribution )
448 {
449 // call appropriate apply based on if the input and output scalar types are the same or different
450 using input_scalar_type = typename KV::non_const_value_type;
451 using output_scalar_type = typename MV::scalar_t;
452 std::conditional_t<std::is_same_v<input_scalar_type, output_scalar_type>,
453 same_type_put_view<MV, KV>,
454 diff_type_put_view<MV, KV>>::apply (mv, kokkos_data, ldx, distribution_map, distribution);
455 }
456
457 template <class MV, typename KV>
458 void put_1d_data_helper_kokkos_view<MV,KV>::do_put(const Teuchos::Ptr<MV>& mv,
459 KV& kokkos_data,
460 const size_t ldx,
461 EDistribution distribution, typename MV::global_ordinal_t indexBase)
462 {
463 typedef typename MV::local_ordinal_t lo_t;
464 typedef typename MV::global_ordinal_t go_t;
465 typedef typename MV::global_size_t gs_t;
466 typedef typename MV::node_t node_t;
467
468 const Teuchos::RCP<const Tpetra::Map<lo_t,go_t,node_t> > map
469 = Amesos2::Util::getDistributionMap<lo_t,go_t,gs_t,node_t>(distribution,
470 mv->getGlobalLength(),
471 mv->getComm(),
472 indexBase,
473 mv->getMap());
474
475 do_put(mv, kokkos_data, ldx, Teuchos::ptrInArg(*map), distribution);
476 }
477
478 template <class MV, typename KV>
479 void put_1d_data_helper_kokkos_view<MV,KV>::do_put (const Teuchos::Ptr<MV>& mv,
480 KV& kokkos_data,
481 const size_t ldx)
482 {
483 const Teuchos::RCP<const Tpetra::Map<typename MV::local_ordinal_t,
484 typename MV::global_ordinal_t,
485 typename MV::node_t> > map
486 = mv->getMap();
487 do_put (mv, kokkos_data, ldx, Teuchos::ptrInArg (*map), ROOTED); // Default as ROOTED for now
488 }
489
490 } // end namespace Util
491
492} // end namespace Amesos2
493
494#endif // AMESOS2_MULTIVECADAPTER_DEF_HPP
Amesos2::MultiVecAdapter specialization for the Kokkos::View class.
Amesos2::MultiVecAdapter specialization for the Tpetra::MultiVector class.
EDistribution
Definition Amesos2_TypeDecl.hpp:89
Utility functions for Amesos2.
static void do_get(const Teuchos::Ptr< const MV > &mv, const Teuchos::ArrayView< S > &vals, const size_t ldx, Teuchos::Ptr< const Tpetra::Map< typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t > > distribution_map, EDistribution distribution=ROOTED)
Helper class for getting 1-D copies of multivectors.
Definition Amesos2_MultiVecAdapter_def.hpp:111
static void do_put(const Teuchos::Ptr< MV > &mv, const Teuchos::ArrayView< S > &data, const size_t ldx, Teuchos::Ptr< const Tpetra::Map< typename MV::local_ordinal_t, typename MV::global_ordinal_t, typename MV::node_t > > distribution_map, EDistribution distribution=ROOTED)
Helper class for putting 1-D data arrays into multivectors.
Definition Amesos2_MultiVecAdapter_def.hpp:350