Ifpack2 Templated Preconditioning Package Version 1.0
Loading...
Searching...
No Matches
Ifpack2_BlockHelper.hpp
1// @HEADER
2// *****************************************************************************
3// Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
4//
5// Copyright 2009 NTESS and the Ifpack2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef IFPACK2_BLOCKHELPER_IMPL_HPP
11#define IFPACK2_BLOCKHELPER_IMPL_HPP
12
13#include "Ifpack2_BlockHelper_Timers.hpp"
14
15namespace Ifpack2 {
16
17namespace BlockHelperDetails {
18
19namespace KB = KokkosBatched;
20
24using do_not_initialize_tag = Kokkos::ViewAllocateWithoutInitializing;
25
26template <typename MemoryTraitsType, Kokkos::MemoryTraitsFlags flag>
27using MemoryTraits = Kokkos::MemoryTraits<MemoryTraitsType::is_unmanaged |
28 MemoryTraitsType::is_random_access |
29 flag>;
30
31template <typename ViewType>
32using Unmanaged = Kokkos::View<typename ViewType::data_type,
33 typename ViewType::array_layout,
34 typename ViewType::device_type,
35 MemoryTraits<typename ViewType::memory_traits, Kokkos::Unmanaged> >;
36template <typename ViewType>
37using Atomic = Kokkos::View<typename ViewType::data_type,
38 typename ViewType::array_layout,
39 typename ViewType::device_type,
40 MemoryTraits<typename ViewType::memory_traits, Kokkos::Atomic> >;
41template <typename ViewType>
42using Const = Kokkos::View<typename ViewType::const_data_type,
43 typename ViewType::array_layout,
44 typename ViewType::device_type,
45 typename ViewType::memory_traits>;
46template <typename ViewType>
47using ConstUnmanaged = Const<Unmanaged<ViewType> >;
48
49template <typename ViewType>
50using AtomicUnmanaged = Atomic<Unmanaged<ViewType> >;
51
52template <typename ViewType>
53using Unmanaged = Kokkos::View<typename ViewType::data_type,
54 typename ViewType::array_layout,
55 typename ViewType::device_type,
56 MemoryTraits<typename ViewType::memory_traits, Kokkos::Unmanaged> >;
57
58template <typename ViewType>
59using Scratch = Kokkos::View<typename ViewType::data_type,
60 typename ViewType::array_layout,
61 typename ViewType::execution_space::scratch_memory_space,
62 MemoryTraits<typename ViewType::memory_traits, Kokkos::Unmanaged> >;
63
67template <typename LayoutType>
69template <>
70struct TpetraLittleBlock<Kokkos::LayoutLeft> {
71 template <typename T>
72 KOKKOS_INLINE_FUNCTION static T getFlatIndex(const T i, const T j, const T blksize) { return i + j * blksize; }
73};
74template <>
75struct TpetraLittleBlock<Kokkos::LayoutRight> {
76 template <typename T>
77 KOKKOS_INLINE_FUNCTION static T getFlatIndex(const T i, const T j, const T blksize) { return i * blksize + j; }
78};
79
83template <typename T>
85 typedef T type;
86};
87#if defined(IFPACK2_BLOCKHELPER_USE_SMALL_SCALAR_FOR_BLOCKTRIDIAG)
88template <>
89struct BlockTridiagScalarType<double> {
90 typedef float type;
91};
92// template<> struct SmallScalarType<Kokkos::complex<double> > { typedef Kokkos::complex<float> type; };
93#endif
94
98template <typename T>
99struct is_cuda {
100 enum : bool { value = false };
101};
102#if defined(KOKKOS_ENABLE_CUDA)
103template <>
104struct is_cuda<Kokkos::Cuda> {
105 enum : bool { value = true };
106};
107#endif
108
112template <typename T>
113struct is_hip {
114 enum : bool { value = false };
115};
116#if defined(KOKKOS_ENABLE_HIP)
117template <>
118struct is_hip<Kokkos::HIP> {
119 enum : bool { value = true };
120};
121#endif
122
126template <typename T>
127struct is_sycl {
128 enum : bool { value = false };
129};
130#if defined(KOKKOS_ENABLE_SYCL)
131template <>
132struct is_sycl<Kokkos::SYCL> {
133 enum : bool { value = true };
134};
135#endif
136
137template <typename T>
138struct is_device {
139 enum : bool { value = is_cuda<T>::value || is_hip<T>::value || is_sycl<T>::value };
140};
141
145template <typename T>
147 static void createInstance(T &exec_instance) {
148 exec_instance = T();
149 }
150#if defined(KOKKOS_ENABLE_CUDA)
151 static void createInstance(const cudaStream_t &s, T &exec_instance) {
152 exec_instance = T();
153 }
154#endif
155};
156
157#if defined(KOKKOS_ENABLE_CUDA)
158template <>
159struct ExecutionSpaceFactory<Kokkos::Cuda> {
160 static void createInstance(Kokkos::Cuda &exec_instance) {
161 exec_instance = Kokkos::Cuda();
162 }
163 static void createInstance(const cudaStream_t &s, Kokkos::Cuda &exec_instance) {
164 exec_instance = Kokkos::Cuda(s);
165 }
166};
167#endif
168
169#if defined(KOKKOS_ENABLE_HIP)
170template <>
171struct ExecutionSpaceFactory<Kokkos::HIP> {
172 static void createInstance(Kokkos::HIP &exec_instance) {
173 exec_instance = Kokkos::HIP();
174 }
175};
176#endif
177
178#if defined(KOKKOS_ENABLE_SYCL)
179template <>
180struct ExecutionSpaceFactory<Kokkos::SYCL> {
181 static void createInstance(Kokkos::SYCL &exec_instance) {
182 exec_instance = Kokkos::SYCL();
183 }
184};
185#endif
186
187#if defined(KOKKOS_ENABLE_CUDA) && defined(IFPACK2_BLOCKHELPER_ENABLE_PROFILE)
188#define IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN \
189 cudaProfilerStart();
190
191#define IFPACK2_BLOCKHELPER_PROFILER_REGION_END \
192 { cudaProfilerStop(); }
193#else
195#define IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN
196#define IFPACK2_BLOCKHELPER_PROFILER_REGION_END
197#endif
198
202template <typename CommPtrType>
203std::string get_msg_prefix(const CommPtrType &comm) {
204 const auto rank = comm->getRank();
205 const auto nranks = comm->getSize();
206 std::stringstream ss;
207 ss << "Rank " << rank << " of " << nranks << ": ";
208 return ss.str();
209}
210
214template <typename T, int N>
216 T v[N];
217 KOKKOS_INLINE_FUNCTION
219 for (int i = 0; i < N; ++i)
220 this->v[i] = 0;
221 }
222 KOKKOS_INLINE_FUNCTION
224 for (int i = 0; i < N; ++i)
225 this->v[i] = b.v[i];
226 }
227};
228template <typename T, int N>
229static KOKKOS_INLINE_FUNCTION void
230operator+=(ArrayValueType<T, N> &a,
231 const ArrayValueType<T, N> &b) {
232 for (int i = 0; i < N; ++i)
233 a.v[i] += b.v[i];
234}
235
239template <typename T, int N, typename ExecSpace>
241 typedef SumReducer reducer;
243 typedef Kokkos::View<value_type, ExecSpace, Kokkos::MemoryTraits<Kokkos::Unmanaged> > result_view_type;
244 value_type *value;
245
246 KOKKOS_INLINE_FUNCTION
248 : value(&val) {}
249
250 KOKKOS_INLINE_FUNCTION
251 void join(value_type &dst, value_type const &src) const {
252 for (int i = 0; i < N; ++i)
253 dst.v[i] += src.v[i];
254 }
255 KOKKOS_INLINE_FUNCTION
256 void init(value_type &val) const {
257 for (int i = 0; i < N; ++i)
258 val.v[i] = 0;
259 }
260 KOKKOS_INLINE_FUNCTION
261 value_type &reference() {
262 return *value;
263 }
264 KOKKOS_INLINE_FUNCTION
265 result_view_type view() const {
266 return result_view_type(value);
267 }
268};
269
273template <typename MatrixType>
274struct ImplType {
278 typedef size_t size_type;
279 typedef MatrixType matrix_type;
280 typedef typename MatrixType::scalar_type scalar_type;
281 typedef typename MatrixType::local_ordinal_type local_ordinal_type;
282 typedef typename MatrixType::global_ordinal_type global_ordinal_type;
283 typedef typename MatrixType::node_type node_type;
284
288 typedef typename KokkosKernels::ArithTraits<scalar_type>::val_type impl_scalar_type;
289 typedef typename KokkosKernels::ArithTraits<impl_scalar_type>::mag_type magnitude_type;
290
291 typedef typename BlockTridiagScalarType<impl_scalar_type>::type btdm_scalar_type;
292 typedef typename KokkosKernels::ArithTraits<btdm_scalar_type>::mag_type btdm_magnitude_type;
293
297 typedef Kokkos::DefaultHostExecutionSpace host_execution_space;
298
302 typedef typename node_type::device_type node_device_type;
303 typedef typename node_device_type::execution_space node_execution_space;
304 typedef typename node_device_type::memory_space node_memory_space;
305
306#if defined(KOKKOS_ENABLE_CUDA) && defined(IFPACK2_BLOCKHELPER_USE_CUDA_SPACE)
308 typedef node_execution_space execution_space;
309 typedef typename std::conditional<std::is_same<node_memory_space, Kokkos::CudaUVMSpace>::value,
310 Kokkos::CudaSpace,
311 node_memory_space>::type memory_space;
312 typedef Kokkos::Device<execution_space, memory_space> device_type;
313#else
314 typedef node_device_type device_type;
315 typedef node_execution_space execution_space;
316 typedef node_memory_space memory_space;
317#endif
318
319 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_multivector_type;
320 typedef Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> tpetra_map_type;
321 typedef Tpetra::Import<local_ordinal_type, global_ordinal_type, node_type> tpetra_import_type;
322 typedef Tpetra::RowMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_row_matrix_type;
323 typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_crs_matrix_type;
324 typedef Tpetra::CrsGraph<local_ordinal_type, global_ordinal_type, node_type> tpetra_crs_graph_type;
325 typedef Tpetra::BlockCrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_block_crs_matrix_type;
326 typedef typename tpetra_block_crs_matrix_type::little_block_type tpetra_block_access_view_type;
327 typedef Tpetra::BlockMultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_block_multivector_type;
328 typedef typename tpetra_block_crs_matrix_type::crs_graph_type::local_graph_device_type local_crs_graph_type;
329
333 template <typename T, int l>
334 using Vector = KB::Vector<T, l>;
335 template <typename T>
336 using SIMD = KB::SIMD<T>;
337 template <typename T, typename M>
338 using DefaultVectorLength = KB::DefaultVectorLength<T, M>;
339 template <typename T, typename M>
340 using DefaultInternalVectorLength = KB::DefaultInternalVectorLength<T, M>;
341
342 static constexpr int vector_length = DefaultVectorLength<btdm_scalar_type, memory_space>::value;
343 static constexpr int internal_vector_length = DefaultInternalVectorLength<btdm_scalar_type, memory_space>::value;
344 static constexpr int half_vector_length = (vector_length > 1) ? (vector_length / 2) : 1;
345 typedef Vector<SIMD<btdm_scalar_type>, vector_length> vector_type;
346 typedef Vector<SIMD<btdm_scalar_type>, internal_vector_length> internal_vector_type;
347
351 typedef Kokkos::View<size_type *, device_type> size_type_1d_view;
352 typedef Kokkos::View<size_type **, device_type> size_type_2d_view;
353 typedef Kokkos::View<int64_t ***, Kokkos::LayoutRight, device_type> i64_3d_view;
354 typedef Kokkos::View<local_ordinal_type *, device_type> local_ordinal_type_1d_view;
355 typedef Kokkos::View<local_ordinal_type **, device_type> local_ordinal_type_2d_view;
356 // tpetra block crs values
357 typedef Kokkos::View<impl_scalar_type *, device_type> impl_scalar_type_1d_view;
358 typedef Kokkos::View<impl_scalar_type *, node_device_type> impl_scalar_type_1d_view_tpetra;
359
360 // tpetra multivector values (layout left): may need to change the typename more explicitly
361 typedef Kokkos::View<impl_scalar_type **, Kokkos::LayoutLeft, device_type> impl_scalar_type_2d_view;
362 typedef Kokkos::View<impl_scalar_type **, Kokkos::LayoutLeft, node_device_type> impl_scalar_type_2d_view_tpetra;
363 typedef Kokkos::View<const impl_scalar_type **, Kokkos::LayoutLeft, node_device_type> const_impl_scalar_type_2d_view_tpetra;
364
365 // packed data always use layout right
366 typedef Kokkos::View<vector_type *, device_type> vector_type_1d_view;
367 typedef Kokkos::View<vector_type ***, Kokkos::LayoutRight, device_type> vector_type_3d_view;
368 typedef Kokkos::View<vector_type ****, Kokkos::LayoutRight, device_type> vector_type_4d_view;
369 typedef Kokkos::View<internal_vector_type ***, Kokkos::LayoutRight, device_type> internal_vector_type_3d_view;
370 typedef Kokkos::View<internal_vector_type ****, Kokkos::LayoutRight, device_type> internal_vector_type_4d_view;
371 typedef Kokkos::View<internal_vector_type *****, Kokkos::LayoutRight, device_type> internal_vector_type_5d_view;
372 typedef Kokkos::View<btdm_scalar_type **, Kokkos::LayoutRight, device_type> btdm_scalar_type_2d_view;
373 typedef Kokkos::View<btdm_scalar_type ***, Kokkos::LayoutRight, device_type> btdm_scalar_type_3d_view;
374 typedef Kokkos::View<btdm_scalar_type ****, Kokkos::LayoutRight, device_type> btdm_scalar_type_4d_view;
375 typedef Kokkos::View<btdm_scalar_type *****, Kokkos::LayoutRight, device_type> btdm_scalar_type_5d_view;
376};
377
381template <typename MatrixType>
382struct AmD {
384 using local_ordinal_type_1d_view = typename impl_type::local_ordinal_type_1d_view;
385 using size_type_1d_view = typename impl_type::size_type_1d_view;
386 using i64_3d_view = typename impl_type::i64_3d_view;
387 using impl_scalar_type_1d_view_tpetra = Unmanaged<typename impl_type::impl_scalar_type_1d_view_tpetra>;
388 // rowptr points to the start of each row of A_colindsub.
389 size_type_1d_view rowptr, rowptr_remote;
390 // Indices into A's rows giving the blocks to extract. rowptr(i) points to
391 // the i'th row. Thus, g.entries(A_colindsub(rowptr(row) : rowptr(row+1))),
392 // where g is A's graph, are the columns AmD uses. If seq_method_, then
393 // A_colindsub contains all the LIDs and A_colindsub_remote is empty. If !
394 // seq_method_, then A_colindsub contains owned LIDs and A_colindsub_remote
395 // contains the remote ones.
396 local_ordinal_type_1d_view A_colindsub, A_colindsub_remote;
397 // Precomputed direct offsets to A,x blocks, for owned entries (OverlapTag case) or all entries (AsyncTag case)
398 i64_3d_view A_x_offsets;
399 // Precomputed direct offsets to A,x blocks, for non-owned entries (OverlapTag case). For AsyncTag case this is left empty.
400 i64_3d_view A_x_offsets_remote;
401
402 // Currently always true.
403 bool is_tpetra_block_crs;
404
405 // If is_tpetra_block_crs, then this is a pointer to A_'s value data.
406 impl_scalar_type_1d_view_tpetra tpetra_values;
407
408 AmD() = default;
409 AmD(const AmD &b) = default;
410};
411
412template <typename MatrixType>
413struct PartInterface {
414 using local_ordinal_type = typename BlockHelperDetails::ImplType<MatrixType>::local_ordinal_type;
415 using local_ordinal_type_1d_view = typename BlockHelperDetails::ImplType<MatrixType>::local_ordinal_type_1d_view;
416 using local_ordinal_type_2d_view = typename BlockHelperDetails::ImplType<MatrixType>::local_ordinal_type_2d_view;
417
418 PartInterface() = default;
419 PartInterface(const PartInterface &b) = default;
420
421 // Some terms:
422 // The matrix A is split as A = D + R, where D is the matrix of tridiag
423 // blocks and R is the remainder.
424 // A part is roughly a synonym for a tridiag. The distinction is that a part
425 // is the set of rows belonging to one tridiag and, equivalently, the off-diag
426 // rows in R associated with that tridiag. In contrast, the term tridiag is
427 // used to refer specifically to tridiag data, such as the pointer into the
428 // tridiag data array.
429 // Local (lcl) row are the LIDs. lclrow lists the LIDs belonging to each
430 // tridiag, and partptr points to the beginning of each tridiag. This is the
431 // LID space.
432 // Row index (idx) is the ordinal in the tridiag ordering. lclrow is indexed
433 // by this ordinal. This is the 'index' space.
434 // A flat index is the mathematical index into an array. A pack index
435 // accounts for SIMD packing.
436
437 // Local row LIDs. Permutation from caller's index space to tridiag index
438 // space.
439 local_ordinal_type_1d_view lclrow;
440 // partptr_ is the pointer array into lclrow_.
441 local_ordinal_type_1d_view partptr; // np+1
442 local_ordinal_type_2d_view partptr_sub;
443 local_ordinal_type_1d_view partptr_schur;
444 // packptr_(i), for i the pack index, indexes partptr_. partptr_(packptr_(i))
445 // is the start of the i'th pack.
446 local_ordinal_type_1d_view packptr; // npack+1
447 local_ordinal_type_1d_view packptr_sub;
448 local_ordinal_type_1d_view packindices_sub;
449 local_ordinal_type_2d_view packindices_schur;
450 // part2rowidx0_(i) is the flat row index of the start of the i'th part. It's
451 // an alias of partptr_ in the case of no overlap.
452 local_ordinal_type_1d_view part2rowidx0; // np+1
453 local_ordinal_type_1d_view part2rowidx0_sub;
454 // part2packrowidx0_(i) is the packed row index. If vector_length is 1, then
455 // it's the same as part2rowidx0_; if it's > 1, then the value is combined
456 // with i % vector_length to get the location in the packed data.
457 local_ordinal_type_1d_view part2packrowidx0; // np+1
458 local_ordinal_type_2d_view part2packrowidx0_sub;
459 local_ordinal_type part2packrowidx0_back; // So we don't need to grab the array from the GPU.
460 // rowidx2part_ maps the row index to the part index.
461 local_ordinal_type_1d_view rowidx2part; // nr
462 local_ordinal_type_1d_view rowidx2part_sub;
463 // True if lcl{row|col} is at most a constant away from row{idx|col}. In
464 // practice, this knowledge is not particularly useful, as packing for batched
465 // processing is done at the same time as the permutation from LID to index
466 // space. But it's easy to detect, so it's recorded in case an optimization
467 // can be made based on it.
468 bool row_contiguous;
469
470 local_ordinal_type max_partsz;
471 local_ordinal_type max_subpartsz;
472 local_ordinal_type n_subparts_per_part;
473 local_ordinal_type nparts;
474};
475
479template <typename MatrixType>
481 public:
483 using host_execution_space = typename impl_type::host_execution_space;
484 using magnitude_type = typename impl_type::magnitude_type;
485
486 private:
487 bool collective_;
488 int sweep_step_, sweep_step_upper_bound_;
489#ifdef HAVE_IFPACK2_MPI
490 MPI_Request mpi_request_;
491 MPI_Comm comm_;
492#endif
493 magnitude_type work_[3];
494
495 public:
496 NormManager() = default;
497 NormManager(const NormManager &b) = default;
498 NormManager(const Teuchos::RCP<const Teuchos::Comm<int> > &comm) {
499 sweep_step_ = 1;
500 sweep_step_upper_bound_ = 1;
501 collective_ = comm->getSize() > 1;
502 if (collective_) {
503#ifdef HAVE_IFPACK2_MPI
504 const auto mpi_comm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(comm);
505 TEUCHOS_ASSERT(!mpi_comm.is_null());
506 comm_ = *mpi_comm->getRawMpiComm();
507#endif
508 }
509 const magnitude_type zero(0), minus_one(-1);
510 work_[0] = zero;
511 work_[1] = zero;
512 work_[2] = minus_one;
513 }
514
515 // Check the norm every sweep_step sweeps.
516 void setCheckFrequency(const int sweep_step) {
517 TEUCHOS_TEST_FOR_EXCEPT_MSG(sweep_step < 1, "sweep step must be >= 1");
518 sweep_step_upper_bound_ = sweep_step;
519 sweep_step_ = 1;
520 }
521
522 // Get the buffer into which to store rank-local squared norms.
523 magnitude_type *getBuffer() { return &work_[0]; }
524
525 // Call MPI_Iallreduce to find the global squared norms.
526 void ireduce(const int sweep, const bool force = false) {
527 if (!force && sweep % sweep_step_) return;
528
529 IFPACK2_BLOCKHELPER_TIMER("BlockTriDi::NormManager::Ireduce", Ireduce);
530
531 work_[1] = work_[0];
532#ifdef HAVE_IFPACK2_MPI
533 auto send_data = &work_[1];
534 auto recv_data = &work_[0];
535 if (collective_) {
536#if defined(IFPACK2_BLOCKTRIDICONTAINER_USE_MPI_3)
537 MPI_Iallreduce(send_data, recv_data, 1,
538 Teuchos::Details::MpiTypeTraits<magnitude_type>::getType(),
539 MPI_SUM, comm_, &mpi_request_);
540#else
541 MPI_Allreduce(send_data, recv_data, 1,
542 Teuchos::Details::MpiTypeTraits<magnitude_type>::getType(),
543 MPI_SUM, comm_);
544#endif
545 }
546#endif
547 }
548
549 // Check if the norm-based termination criterion is met. tol2 is the
550 // tolerance squared. Sweep is the sweep index. If not every iteration is
551 // being checked, this function immediately returns false. If a check must
552 // be done at this iteration, it waits for the reduction triggered by
553 // ireduce to complete, then checks the global norm against the tolerance.
554 bool checkDone(const int sweep, const magnitude_type tol2, const bool force = false) {
555 // early return
556 if (sweep <= 0) return false;
557
558 IFPACK2_BLOCKHELPER_TIMER("BlockTriDi::NormManager::CheckDone", CheckDone);
559
560 TEUCHOS_ASSERT(sweep >= 1);
561 if (!force && (sweep - 1) % sweep_step_) return false;
562 if (collective_) {
563#ifdef HAVE_IFPACK2_MPI
564#if defined(IFPACK2_BLOCKTRIDICONTAINER_USE_MPI_3)
565 MPI_Wait(&mpi_request_, MPI_STATUS_IGNORE);
566#else
567 // Do nothing.
568#endif
569#endif
570 }
571 bool r_val = false;
572 if (sweep == 1) {
573 work_[2] = work_[0];
574 } else {
575 r_val = (work_[0] < tol2 * work_[2]);
576 }
577
578 // adjust sweep step
579 const auto adjusted_sweep_step = 2 * sweep_step_;
580 if (adjusted_sweep_step < sweep_step_upper_bound_) {
581 sweep_step_ = adjusted_sweep_step;
582 } else {
583 sweep_step_ = sweep_step_upper_bound_;
584 }
585 return r_val;
586 }
587
588 // After termination has occurred, finalize the norms for use in
589 // get_norms{0,final}.
590 void finalize() {
591 work_[0] = std::sqrt(work_[0]); // after converged
592 if (work_[2] >= 0)
593 work_[2] = std::sqrt(work_[2]); // first norm
594 // if work_[2] is minus one, then norm is not requested.
595 }
596
597 // Report norms to the caller.
598 const magnitude_type getNorms0() const { return work_[2]; }
599 const magnitude_type getNormsFinal() const { return work_[0]; }
600};
601
602template <typename MatrixType>
603void reduceVector(const ConstUnmanaged<typename BlockHelperDetails::ImplType<MatrixType>::impl_scalar_type_1d_view> zz,
604 /* */ typename BlockHelperDetails::ImplType<MatrixType>::magnitude_type *vals) {
605 IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN;
606 IFPACK2_BLOCKHELPER_TIMER("BlockTriDi::ReduceVector", ReduceVector);
607
608 using impl_type = BlockHelperDetails::ImplType<MatrixType>;
609 using local_ordinal_type = typename impl_type::local_ordinal_type;
610 using impl_scalar_type = typename impl_type::impl_scalar_type;
611#if 0
612 const auto norm2 = KokkosBlas::nrm1(zz);
613#else
614 impl_scalar_type norm2(0);
615 Kokkos::parallel_reduce(
616 "ReduceMultiVector::Device",
617 Kokkos::RangePolicy<typename impl_type::execution_space>(0, zz.extent(0)),
618 KOKKOS_LAMBDA(const local_ordinal_type &i, impl_scalar_type &update) {
619 update += zz(i);
620 },
621 norm2);
622#endif
623 vals[0] = KokkosKernels::ArithTraits<impl_scalar_type>::abs(norm2);
624
625 IFPACK2_BLOCKHELPER_PROFILER_REGION_END;
626 IFPACK2_BLOCKHELPER_TIMER_FENCE(typename ImplType<MatrixType>::execution_space)
627}
628
629} // namespace BlockHelperDetails
630
631} // namespace Ifpack2
632
633#endif
Preconditioners and smoothers for Tpetra sparse matrices.
Definition Ifpack2_AdditiveSchwarz_decl.hpp:40
Definition Ifpack2_BlockHelper.hpp:382
Definition Ifpack2_BlockHelper.hpp:215
Definition Ifpack2_BlockHelper.hpp:84
Definition Ifpack2_BlockHelper.hpp:146
Definition Ifpack2_BlockHelper.hpp:274
KB::Vector< T, l > Vector
Definition Ifpack2_BlockHelper.hpp:334
size_t size_type
Definition Ifpack2_BlockHelper.hpp:278
node_type::device_type node_device_type
Definition Ifpack2_BlockHelper.hpp:302
Kokkos::DefaultHostExecutionSpace host_execution_space
Definition Ifpack2_BlockHelper.hpp:297
KokkosKernels::ArithTraits< scalar_type >::val_type impl_scalar_type
Definition Ifpack2_BlockHelper.hpp:288
Kokkos::View< size_type *, device_type > size_type_1d_view
Definition Ifpack2_BlockHelper.hpp:351
Definition Ifpack2_BlockHelper.hpp:480
Definition Ifpack2_BlockHelper.hpp:240
Definition Ifpack2_BlockHelper.hpp:68
Definition Ifpack2_BlockHelper.hpp:99
Definition Ifpack2_BlockHelper.hpp:113
Definition Ifpack2_BlockHelper.hpp:127