10#ifndef IFPACK2_BLOCKCOMPUTERES_AND_SOLVE_DEF_HPP
11#define IFPACK2_BLOCKCOMPUTERES_AND_SOLVE_DEF_HPP
13#include "Ifpack2_BlockComputeResidualAndSolve_decl.hpp"
15namespace Ifpack2::BlockHelperDetails {
17template <
typename MatrixType,
int B>
18struct ComputeResidualAndSolve_SinglePass_Impl {
19 using impl_type = BlockHelperDetails::ImplType<MatrixType>;
21 using execution_space =
typename impl_type::execution_space;
22 using memory_space =
typename impl_type::memory_space;
24 using local_ordinal_type =
typename impl_type::local_ordinal_type;
27 using magnitude_type =
typename impl_type::magnitude_type;
29 using local_ordinal_type_1d_view =
30 typename impl_type::local_ordinal_type_1d_view;
32 using tpetra_block_access_view_type =
33 typename impl_type::tpetra_block_access_view_type;
35 using impl_scalar_type_1d_view =
typename impl_type::impl_scalar_type_1d_view;
36 using impl_scalar_type_2d_view_tpetra =
37 typename impl_type::impl_scalar_type_2d_view_tpetra;
39 using btdm_scalar_type_3d_view =
typename impl_type::btdm_scalar_type_3d_view;
40 using btdm_scalar_type_4d_view =
typename impl_type::btdm_scalar_type_4d_view;
41 using i64_3d_view =
typename impl_type::i64_3d_view;
44 using member_type =
typename Kokkos::TeamPolicy<execution_space>::member_type;
47 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> b;
48 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> x;
49 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> x_remote;
50 Unmanaged<impl_scalar_type_2d_view_tpetra> y;
53 const ConstUnmanaged<impl_scalar_type_1d_view> tpetra_values;
56 const local_ordinal_type blocksize_requested;
59 const ConstUnmanaged<i64_3d_view> A_x_offsets;
60 const ConstUnmanaged<i64_3d_view> A_x_offsets_remote;
63 const ConstUnmanaged<btdm_scalar_type_3d_view> d_inv;
66 const Unmanaged<impl_scalar_type_1d_view> W;
68 impl_scalar_type damping_factor;
71 ComputeResidualAndSolve_SinglePass_Impl(
const AmD<MatrixType>& amd,
72 const btdm_scalar_type_3d_view& d_inv_,
73 const impl_scalar_type_1d_view& W_,
74 const local_ordinal_type& blocksize_requested_,
75 const impl_scalar_type& damping_factor_)
76 : tpetra_values(amd.tpetra_values)
77 , blocksize_requested(blocksize_requested_)
78 , A_x_offsets(amd.A_x_offsets)
79 , A_x_offsets_remote(amd.A_x_offsets_remote)
82 , damping_factor(damping_factor_) {}
84 KOKKOS_INLINE_FUNCTION
85 void operator()(
const member_type& member)
const {
86 const local_ordinal_type blocksize = (B == 0 ? blocksize_requested : B);
87 const local_ordinal_type rowidx = member.league_rank();
88 const local_ordinal_type row = rowidx * blocksize;
89 const local_ordinal_type num_vectors = b.extent(1);
90 const local_ordinal_type num_local_rows = d_inv.extent(0);
92 const impl_scalar_type* xx;
93 auto A_block_cst = ConstUnmanaged<tpetra_block_access_view_type>(
94 tpetra_values.data(), blocksize, blocksize);
97 impl_scalar_type* local_residual =
reinterpret_cast<impl_scalar_type*
>(
98 member.team_scratch(0).get_shmem(blocksize *
sizeof(impl_scalar_type)));
99 impl_scalar_type* local_Dinv_residual =
reinterpret_cast<impl_scalar_type*
>(
100 member.team_scratch(0).get_shmem(blocksize *
sizeof(impl_scalar_type)));
101 impl_scalar_type* local_x =
102 reinterpret_cast<impl_scalar_type*
>(member.thread_scratch(0).get_shmem(
103 blocksize *
sizeof(impl_scalar_type)));
105 magnitude_type norm = 0;
106 for (local_ordinal_type col = 0; col < num_vectors; ++col) {
107 if (col) member.team_barrier();
110 Kokkos::parallel_for(Kokkos::TeamVectorRange(member, blocksize),
111 [&](
const local_ordinal_type& i) {
112 local_Dinv_residual[i] = 0;
113 local_residual[i] = b(row + i, col);
115 member.team_barrier();
117 int numEntries = A_x_offsets.extent(2);
119 Kokkos::parallel_for(
120 Kokkos::TeamThreadRange(member, 0, numEntries), [&](
const int k) {
121 int64_t A_offset = A_x_offsets(rowidx, 0, k);
122 int64_t x_offset = A_x_offsets(rowidx, 1, k);
123 if (A_offset != KokkosKernels::ArithTraits<int64_t>::min()) {
124 A_block_cst.assign_data(tpetra_values.data() + A_offset);
126 int64_t remote_cutoff = blocksize * num_local_rows;
127 if (x_offset >= remote_cutoff)
128 xx = &x_remote(x_offset - remote_cutoff, col);
130 xx = &x(x_offset, col);
132 Kokkos::parallel_for(
133 Kokkos::ThreadVectorRange(member, blocksize),
134 [&](
const local_ordinal_type& i) { local_x[i] = xx[i]; });
137 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
139 impl_scalar_type val = 0;
140 for (
int k1 = 0; k1 < blocksize; k1++)
141 val += A_block_cst(k0, k1) * local_x[k1];
142 Kokkos::atomic_add(local_residual + k0, -val);
146 member.team_barrier();
148 Kokkos::parallel_for(
149 Kokkos::TeamThreadRange(member, blocksize),
150 [&](
const local_ordinal_type& k0) {
151 Kokkos::parallel_reduce(
152 Kokkos::ThreadVectorRange(member, blocksize),
153 [&](
const local_ordinal_type& k1, impl_scalar_type& update) {
154 update += d_inv(rowidx, k0, k1) * local_residual[k1];
156 local_Dinv_residual[k0]);
158 member.team_barrier();
161 magnitude_type colNorm;
162 Kokkos::parallel_reduce(
163 Kokkos::TeamVectorRange(member, blocksize),
164 [&](
const local_ordinal_type& k, magnitude_type& update) {
167 impl_scalar_type old_y = x(row + k, col);
168 impl_scalar_type y_update = local_Dinv_residual[k] - old_y;
169 if constexpr (KokkosKernels::ArithTraits<impl_scalar_type>::is_complex) {
170 magnitude_type ydiff =
171 KokkosKernels::ArithTraits<impl_scalar_type>::abs(y_update);
172 update += ydiff * ydiff;
174 update += y_update * y_update;
176 y(row + k, col) = old_y + damping_factor * y_update;
181 Kokkos::single(Kokkos::PerTeam(member), [&]() { W(rowidx) = norm; });
184 void run(
const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& b_,
185 const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& x_,
186 const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& x_remote_,
187 const Unmanaged<impl_scalar_type_2d_view_tpetra>& y_) {
188 IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN;
189 IFPACK2_BLOCKHELPER_TIMER_WITH_FENCE(
190 "BlockTriDi::ComputeResidualAndSolve::RunSinglePass",
191 ComputeResidualAndSolve0, execution_space);
196 x_remote = x_remote_;
198 const local_ordinal_type blocksize = blocksize_requested;
199 const local_ordinal_type nrows = d_inv.extent(0);
201 const local_ordinal_type team_size = 8;
202 const local_ordinal_type vector_size = 8;
204 const size_t shmem_team_size = 2 * blocksize *
sizeof(impl_scalar_type);
206 const size_t shmem_thread_size = blocksize *
sizeof(impl_scalar_type);
207 Kokkos::TeamPolicy<execution_space> policy(nrows, team_size, vector_size);
208 policy.set_scratch_size(0, Kokkos::PerTeam(shmem_team_size),
209 Kokkos::PerThread(shmem_thread_size));
210 Kokkos::parallel_for(
"ComputeResidualAndSolve::TeamPolicy::SinglePass",
213 IFPACK2_BLOCKHELPER_PROFILER_REGION_END;
214 IFPACK2_BLOCKHELPER_TIMER_FENCE(execution_space)
218template <
typename MatrixType,
int B>
219struct ComputeResidualAndSolve_2Pass_Impl {
220 using impl_type = BlockHelperDetails::ImplType<MatrixType>;
222 using execution_space =
typename impl_type::execution_space;
223 using memory_space =
typename impl_type::memory_space;
225 using local_ordinal_type =
typename impl_type::local_ordinal_type;
228 using magnitude_type =
typename impl_type::magnitude_type;
230 using local_ordinal_type_1d_view =
231 typename impl_type::local_ordinal_type_1d_view;
233 using tpetra_block_access_view_type =
234 typename impl_type::tpetra_block_access_view_type;
236 using impl_scalar_type_1d_view =
typename impl_type::impl_scalar_type_1d_view;
237 using impl_scalar_type_2d_view_tpetra =
238 typename impl_type::impl_scalar_type_2d_view_tpetra;
240 using btdm_scalar_type_3d_view =
typename impl_type::btdm_scalar_type_3d_view;
241 using btdm_scalar_type_4d_view =
typename impl_type::btdm_scalar_type_4d_view;
242 using i64_3d_view =
typename impl_type::i64_3d_view;
245 using member_type =
typename Kokkos::TeamPolicy<execution_space>::member_type;
252 struct NonownedTag {};
255 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> b;
256 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> x;
257 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> x_remote;
258 Unmanaged<impl_scalar_type_2d_view_tpetra> y;
261 const ConstUnmanaged<impl_scalar_type_1d_view> tpetra_values;
264 const local_ordinal_type blocksize_requested;
267 const ConstUnmanaged<i64_3d_view> A_x_offsets;
268 const ConstUnmanaged<i64_3d_view> A_x_offsets_remote;
271 const ConstUnmanaged<btdm_scalar_type_3d_view> d_inv;
274 const Unmanaged<impl_scalar_type_1d_view> W;
276 impl_scalar_type damping_factor;
279 ComputeResidualAndSolve_2Pass_Impl(
280 const AmD<MatrixType>& amd,
281 const btdm_scalar_type_3d_view& d_inv_,
282 const impl_scalar_type_1d_view& W_,
283 const local_ordinal_type& blocksize_requested_,
284 const impl_scalar_type& damping_factor_)
285 : tpetra_values(amd.tpetra_values)
286 , blocksize_requested(blocksize_requested_)
287 , A_x_offsets(amd.A_x_offsets)
288 , A_x_offsets_remote(amd.A_x_offsets_remote)
291 , damping_factor(damping_factor_) {}
293 KOKKOS_INLINE_FUNCTION
294 void operator()(
const OwnedTag,
const member_type& member)
const {
295 const local_ordinal_type blocksize = (B == 0 ? blocksize_requested : B);
296 const local_ordinal_type rowidx = member.league_rank();
297 const local_ordinal_type row = rowidx * blocksize;
298 const local_ordinal_type num_vectors = b.extent(1);
300 auto A_block_cst = ConstUnmanaged<tpetra_block_access_view_type>(
301 tpetra_values.data(), blocksize, blocksize);
304 impl_scalar_type* local_residual =
reinterpret_cast<impl_scalar_type*
>(
305 member.team_scratch(0).get_shmem(blocksize *
sizeof(impl_scalar_type)));
306 impl_scalar_type* local_x =
307 reinterpret_cast<impl_scalar_type*
>(member.thread_scratch(0).get_shmem(
308 blocksize *
sizeof(impl_scalar_type)));
310 for (local_ordinal_type col = 0; col < num_vectors; ++col) {
311 if (col) member.team_barrier();
314 Kokkos::parallel_for(
315 Kokkos::TeamVectorRange(member, blocksize),
316 [&](
const local_ordinal_type& i) { local_residual[i] = b(row + i, col); });
317 member.team_barrier();
319 int numEntries = A_x_offsets.extent(2);
321 Kokkos::parallel_for(
322 Kokkos::TeamThreadRange(member, 0, numEntries), [&](
const int k) {
323 int64_t A_offset = A_x_offsets(rowidx, 0, k);
324 int64_t x_offset = A_x_offsets(rowidx, 1, k);
325 if (A_offset != KokkosKernels::ArithTraits<int64_t>::min()) {
326 A_block_cst.assign_data(tpetra_values.data() + A_offset);
328 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
329 [&](
const local_ordinal_type& i) {
330 local_x[i] = x(x_offset + i, col);
334 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
335 [&](
const local_ordinal_type& k0) {
336 impl_scalar_type val = 0;
337 for (
int k1 = 0; k1 < blocksize; k1++)
338 val += A_block_cst(k0, k1) * local_x[k1];
339 Kokkos::atomic_add(local_residual + k0, -val);
343 member.team_barrier();
345 if (member.team_rank() == 0) {
346 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
347 [&](
const local_ordinal_type& k) {
348 y(row + k, col) = local_residual[k];
354 KOKKOS_INLINE_FUNCTION
355 void operator()(
const NonownedTag,
const member_type& member)
const {
356 const local_ordinal_type blocksize = (B == 0 ? blocksize_requested : B);
357 const local_ordinal_type rowidx = member.league_rank();
358 const local_ordinal_type row = rowidx * blocksize;
359 const local_ordinal_type num_vectors = y.extent(1);
361 auto A_block_cst = ConstUnmanaged<tpetra_block_access_view_type>(
362 tpetra_values.data(), blocksize, blocksize);
365 impl_scalar_type* local_residual =
reinterpret_cast<impl_scalar_type*
>(
366 member.team_scratch(0).get_shmem(blocksize *
sizeof(impl_scalar_type)));
367 impl_scalar_type* local_Dinv_residual =
reinterpret_cast<impl_scalar_type*
>(
368 member.team_scratch(0).get_shmem(blocksize *
sizeof(impl_scalar_type)));
369 impl_scalar_type* local_x =
370 reinterpret_cast<impl_scalar_type*
>(member.thread_scratch(0).get_shmem(
371 blocksize *
sizeof(impl_scalar_type)));
373 magnitude_type norm = 0;
374 for (local_ordinal_type col = 0; col < num_vectors; ++col) {
375 if (col) member.team_barrier();
378 Kokkos::parallel_for(Kokkos::TeamVectorRange(member, blocksize),
379 [&](
const local_ordinal_type& i) {
380 local_Dinv_residual[i] = 0;
381 local_residual[i] = y(row + i, col);
383 member.team_barrier();
385 int numEntries = A_x_offsets_remote.extent(2);
387 Kokkos::parallel_for(
388 Kokkos::TeamThreadRange(member, 0, numEntries), [&](
const int k) {
389 int64_t A_offset = A_x_offsets_remote(rowidx, 0, k);
390 int64_t x_offset = A_x_offsets_remote(rowidx, 1, k);
391 if (A_offset != KokkosKernels::ArithTraits<int64_t>::min()) {
392 A_block_cst.assign_data(tpetra_values.data() + A_offset);
394 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
395 [&](
const local_ordinal_type& i) {
396 local_x[i] = x_remote(x_offset + i, col);
400 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
402 impl_scalar_type val = 0;
403 for (
int k1 = 0; k1 < blocksize; k1++)
404 val += A_block_cst(k0, k1) * local_x[k1];
405 Kokkos::atomic_add(local_residual + k0, -val);
409 member.team_barrier();
411 Kokkos::parallel_for(
412 Kokkos::TeamThreadRange(member, blocksize),
413 [&](
const local_ordinal_type& k0) {
414 Kokkos::parallel_reduce(
415 Kokkos::ThreadVectorRange(member, blocksize),
416 [&](
const local_ordinal_type& k1, impl_scalar_type& update) {
417 update += d_inv(rowidx, k0, k1) * local_residual[k1];
419 local_Dinv_residual[k0]);
421 member.team_barrier();
424 magnitude_type colNorm;
425 Kokkos::parallel_reduce(
426 Kokkos::TeamVectorRange(member, blocksize),
427 [&](
const local_ordinal_type& k, magnitude_type& update) {
430 impl_scalar_type old_y = x(row + k, col);
431 impl_scalar_type y_update = local_Dinv_residual[k] - old_y;
432 if constexpr (KokkosKernels::ArithTraits<impl_scalar_type>::is_complex) {
433 magnitude_type ydiff =
434 KokkosKernels::ArithTraits<impl_scalar_type>::abs(y_update);
435 update += ydiff * ydiff;
437 update += y_update * y_update;
439 y(row + k, col) = old_y + damping_factor * y_update;
444 Kokkos::single(Kokkos::PerTeam(member), [&]() { W(rowidx) = norm; });
449 void run_pass1(
const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& b_,
450 const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& x_,
451 const Unmanaged<impl_scalar_type_2d_view_tpetra>& y_) {
452 IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN;
453 IFPACK2_BLOCKHELPER_TIMER_WITH_FENCE(
454 "BlockTriDi::ComputeResidualAndSolve::RunPass1",
455 ComputeResidualAndSolve0, execution_space);
461 const local_ordinal_type blocksize = blocksize_requested;
462 const local_ordinal_type nrows = d_inv.extent(0);
464 const local_ordinal_type team_size = 8;
465 const local_ordinal_type vector_size = 8;
466 const size_t shmem_team_size = blocksize *
sizeof(impl_scalar_type);
467 const size_t shmem_thread_size = blocksize *
sizeof(impl_scalar_type);
468 Kokkos::TeamPolicy<execution_space, OwnedTag> policy(nrows, team_size,
470 policy.set_scratch_size(0, Kokkos::PerTeam(shmem_team_size),
471 Kokkos::PerThread(shmem_thread_size));
472 Kokkos::parallel_for(
"ComputeResidualAndSolve::TeamPolicy::Pass1", policy,
474 IFPACK2_BLOCKHELPER_PROFILER_REGION_END;
475 IFPACK2_BLOCKHELPER_TIMER_FENCE(execution_space)
482 const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& x_,
483 const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& x_remote_,
484 const Unmanaged<impl_scalar_type_2d_view_tpetra>& y_) {
485 IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN;
486 IFPACK2_BLOCKHELPER_TIMER_WITH_FENCE(
487 "BlockTriDi::ComputeResidualAndSolve::RunPass2",
488 ComputeResidualAndSolve0, execution_space);
491 x_remote = x_remote_;
494 const local_ordinal_type blocksize = blocksize_requested;
495 const local_ordinal_type nrows = d_inv.extent(0);
497 const local_ordinal_type team_size = 8;
498 const local_ordinal_type vector_size = 8;
499 const size_t shmem_team_size = 2 * blocksize *
sizeof(impl_scalar_type);
500 const size_t shmem_thread_size = blocksize *
sizeof(impl_scalar_type);
501 Kokkos::TeamPolicy<execution_space, NonownedTag> policy(nrows, team_size,
503 policy.set_scratch_size(0, Kokkos::PerTeam(shmem_team_size),
504 Kokkos::PerThread(shmem_thread_size));
505 Kokkos::parallel_for(
"ComputeResidualAndSolve::TeamPolicy::Pass2", policy,
507 IFPACK2_BLOCKHELPER_PROFILER_REGION_END;
508 IFPACK2_BLOCKHELPER_TIMER_FENCE(execution_space)
512template <
typename MatrixType,
int B>
513struct ComputeResidualAndSolve_YZero_Impl {
514 using impl_type = BlockHelperDetails::ImplType<MatrixType>;
516 using execution_space =
typename impl_type::execution_space;
517 using memory_space =
typename impl_type::memory_space;
519 using local_ordinal_type =
typename impl_type::local_ordinal_type;
522 using magnitude_type =
typename impl_type::magnitude_type;
524 using local_ordinal_type_1d_view =
525 typename impl_type::local_ordinal_type_1d_view;
527 using tpetra_block_access_view_type =
528 typename impl_type::tpetra_block_access_view_type;
530 using impl_scalar_type_1d_view =
typename impl_type::impl_scalar_type_1d_view;
531 using impl_scalar_type_2d_view_tpetra =
532 typename impl_type::impl_scalar_type_2d_view_tpetra;
534 using btdm_scalar_type_3d_view =
typename impl_type::btdm_scalar_type_3d_view;
535 using btdm_scalar_type_4d_view =
typename impl_type::btdm_scalar_type_4d_view;
536 using i64_3d_view =
typename impl_type::i64_3d_view;
539 using member_type =
typename Kokkos::TeamPolicy<execution_space>::member_type;
542 ConstUnmanaged<impl_scalar_type_2d_view_tpetra> b;
543 Unmanaged<impl_scalar_type_2d_view_tpetra> y;
546 const ConstUnmanaged<impl_scalar_type_1d_view> tpetra_values;
549 const local_ordinal_type blocksize_requested;
552 const ConstUnmanaged<i64_3d_view> A_x_offsets;
553 const ConstUnmanaged<i64_3d_view> A_x_offsets_remote;
556 const ConstUnmanaged<btdm_scalar_type_3d_view> d_inv;
559 const Unmanaged<impl_scalar_type_1d_view> W;
561 impl_scalar_type damping_factor;
564 ComputeResidualAndSolve_YZero_Impl(
565 const AmD<MatrixType>& amd,
const btdm_scalar_type_3d_view& d_inv_,
566 const impl_scalar_type_1d_view& W_,
567 const local_ordinal_type& blocksize_requested_,
568 const impl_scalar_type& damping_factor_)
569 : tpetra_values(amd.tpetra_values)
570 , blocksize_requested(blocksize_requested_)
571 , A_x_offsets(amd.A_x_offsets)
572 , A_x_offsets_remote(amd.A_x_offsets_remote)
575 , damping_factor(damping_factor_) {}
577 KOKKOS_INLINE_FUNCTION
578 void operator()(
const member_type& member)
const {
579 const local_ordinal_type blocksize = (B == 0 ? blocksize_requested : B);
580 const local_ordinal_type rowidx =
581 member.league_rank() * member.team_size() + member.team_rank();
582 const local_ordinal_type row = rowidx * blocksize;
583 const local_ordinal_type num_vectors = b.extent(1);
586 impl_scalar_type* local_Dinv_residual =
587 reinterpret_cast<impl_scalar_type*
>(member.thread_scratch(0).get_shmem(
588 blocksize *
sizeof(impl_scalar_type)));
590 if (rowidx >= (local_ordinal_type)d_inv.extent(0))
return;
592 magnitude_type norm = 0;
593 for (local_ordinal_type col = 0; col < num_vectors; ++col) {
595 Kokkos::parallel_for(Kokkos::ThreadVectorRange(member, blocksize),
596 [&](
const local_ordinal_type& k0) {
597 impl_scalar_type val = 0;
598 for (local_ordinal_type k1 = 0; k1 < blocksize;
600 val += d_inv(rowidx, k0, k1) * b(row + k1, col);
602 local_Dinv_residual[k0] = val;
605 magnitude_type colNorm;
606 Kokkos::parallel_reduce(
607 Kokkos::ThreadVectorRange(member, blocksize),
608 [&](
const local_ordinal_type& k, magnitude_type& update) {
611 impl_scalar_type y_update = local_Dinv_residual[k];
612 if constexpr (KokkosKernels::ArithTraits<impl_scalar_type>::is_complex) {
613 magnitude_type ydiff =
614 KokkosKernels::ArithTraits<impl_scalar_type>::abs(y_update);
615 update += ydiff * ydiff;
617 update += y_update * y_update;
619 y(row + k, col) = damping_factor * y_update;
624 Kokkos::single(Kokkos::PerThread(member), [&]() { W(rowidx) = norm; });
631 void run(
const ConstUnmanaged<impl_scalar_type_2d_view_tpetra>& b_,
632 const Unmanaged<impl_scalar_type_2d_view_tpetra>& y_) {
633 IFPACK2_BLOCKHELPER_PROFILER_REGION_BEGIN;
634 IFPACK2_BLOCKHELPER_TIMER_WITH_FENCE(
635 "BlockTriDi::ComputeResidualAndSolve::Run_Y_Zero",
636 ComputeResidualAndSolve0, execution_space);
641 const local_ordinal_type blocksize = blocksize_requested;
642 const local_ordinal_type nrows = d_inv.extent(0);
644 const local_ordinal_type team_size = 8;
645 const local_ordinal_type vector_size = 8;
646 const size_t shmem_thread_size = blocksize *
sizeof(impl_scalar_type);
647 Kokkos::TeamPolicy<execution_space> policy(
648 (nrows + team_size - 1) / team_size, team_size, vector_size);
649 policy.set_scratch_size(0, Kokkos::PerThread(shmem_thread_size));
650 Kokkos::parallel_for(
"ComputeResidualAndSolve::TeamPolicy::y_zero", policy, *
this);
651 IFPACK2_BLOCKHELPER_PROFILER_REGION_END;
652 IFPACK2_BLOCKHELPER_TIMER_FENCE(execution_space)
660template <
typename MatrixType>
661void ComputeResidualAndSolve<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>::run_y_zero(
662 const Const<impl_scalar_type_2d_view_tpetra>& b_,
663 const impl_scalar_type_2d_view_tpetra& y_) {
666 ComputeResidualAndSolve_YZero_Impl<MatrixType, B> functor(amd, d_inv, W, blocksize_requested, damping_factor); \
667 functor.run(b_, y_); \
671 switch (blocksize_requested) {
676 case 10: RUN_CASE(10);
677 case 11: RUN_CASE(11);
678 case 16: RUN_CASE(16);
679 case 17: RUN_CASE(17);
680 case 18: RUN_CASE(18);
681 default: RUN_CASE(0);
686template <
typename MatrixType>
687void ComputeResidualAndSolve<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>::run_single_pass(
688 const Const<impl_scalar_type_2d_view_tpetra>& b_,
689 const impl_scalar_type_2d_view_tpetra& x_,
690 const impl_scalar_type_2d_view_tpetra& x_remote_,
691 const impl_scalar_type_2d_view_tpetra& y_) {
694 ComputeResidualAndSolve_SinglePass_Impl<MatrixType, B> functor(amd, d_inv, W, blocksize_requested, damping_factor); \
695 functor.run(b_, x_, x_remote_, y_); \
699 switch (blocksize_requested) {
704 case 10: RUN_CASE(10);
705 case 11: RUN_CASE(11);
706 case 16: RUN_CASE(16);
707 case 17: RUN_CASE(17);
708 case 18: RUN_CASE(18);
709 default: RUN_CASE(0);
714template <
typename MatrixType>
715void ComputeResidualAndSolve<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>::run_pass1_of_2(
716 const Const<impl_scalar_type_2d_view_tpetra>& b_,
717 const impl_scalar_type_2d_view_tpetra& x_,
718 const impl_scalar_type_2d_view_tpetra& y_) {
721 ComputeResidualAndSolve_2Pass_Impl<MatrixType, B> functor(amd, d_inv, W, blocksize_requested, damping_factor); \
722 functor.run_pass1(b_, x_, y_); \
726 switch (blocksize_requested) {
731 case 10: RUN_CASE(10);
732 case 11: RUN_CASE(11);
733 case 16: RUN_CASE(16);
734 case 17: RUN_CASE(17);
735 case 18: RUN_CASE(18);
736 default: RUN_CASE(0);
741template <
typename MatrixType>
742void ComputeResidualAndSolve<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>::run_pass2_of_2(
743 const impl_scalar_type_2d_view_tpetra& x_,
744 const impl_scalar_type_2d_view_tpetra& x_remote_,
745 const impl_scalar_type_2d_view_tpetra& y_) {
748 ComputeResidualAndSolve_2Pass_Impl<MatrixType, B> functor(amd, d_inv, W, blocksize_requested, damping_factor); \
749 functor.run_pass2(x_, x_remote_, y_); \
753 switch (blocksize_requested) {
758 case 10: RUN_CASE(10);
759 case 11: RUN_CASE(11);
760 case 16: RUN_CASE(16);
761 case 17: RUN_CASE(17);
762 case 18: RUN_CASE(18);
763 default: RUN_CASE(0);
770#define IFPACK2_BLOCKCOMPUTERESIDUALANDSOLVE_INSTANT(S, LO, GO, N) \
771 template class Ifpack2::BlockHelperDetails::ComputeResidualAndSolve<Tpetra::RowMatrix<S, LO, GO, N> >;
size_t size_type
Definition Ifpack2_BlockHelper.hpp:278
node_type::device_type node_device_type
Definition Ifpack2_BlockHelper.hpp:302
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