318 typedef MatrixType matrix_type;
319 typedef typename MatrixType::scalar_type scalar_type;
320 typedef typename MatrixType::local_ordinal_type local_ordinal_type;
321 typedef typename MatrixType::global_ordinal_type global_ordinal_type;
322 typedef typename MatrixType::node_type node_type;
328 typedef typename KokkosKernels::ArithTraits<impl_scalar_type>::mag_type magnitude_type;
330 typedef typename BlockTridiagScalarType<impl_scalar_type>::type btdm_scalar_type;
331 typedef typename KokkosKernels::ArithTraits<btdm_scalar_type>::mag_type btdm_magnitude_type;
342 typedef typename node_device_type::execution_space node_execution_space;
343 typedef typename node_device_type::memory_space node_memory_space;
345#if defined(KOKKOS_ENABLE_CUDA) && defined(IFPACK2_BLOCKHELPER_USE_CUDA_SPACE)
347 typedef node_execution_space execution_space;
348 typedef typename std::conditional<std::is_same<node_memory_space, Kokkos::CudaUVMSpace>::value,
350 node_memory_space>
::type memory_space;
351 typedef Kokkos::Device<execution_space, memory_space> device_type;
354 typedef node_execution_space execution_space;
355 typedef node_memory_space memory_space;
358 typedef Tpetra::MultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_multivector_type;
359 typedef Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type> tpetra_map_type;
360 typedef Tpetra::Import<local_ordinal_type, global_ordinal_type, node_type> tpetra_import_type;
361 typedef Tpetra::RowMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_row_matrix_type;
362 typedef Tpetra::CrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_crs_matrix_type;
363 typedef Tpetra::CrsGraph<local_ordinal_type, global_ordinal_type, node_type> tpetra_crs_graph_type;
364 typedef Tpetra::BlockCrsMatrix<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_block_crs_matrix_type;
365 typedef typename tpetra_block_crs_matrix_type::little_block_type tpetra_block_access_view_type;
366 typedef Tpetra::BlockMultiVector<scalar_type, local_ordinal_type, global_ordinal_type, node_type> tpetra_block_multivector_type;
367 typedef typename tpetra_block_crs_matrix_type::crs_graph_type::local_graph_device_type local_crs_graph_type;
372 template <
typename T,
int l>
374 template <
typename T>
375 using SIMD = KB::SIMD<T>;
376 template <
typename T,
typename M>
377 using DefaultVectorLength = KB::DefaultVectorLength<T, M>;
378 template <
typename T,
typename M>
379 using DefaultInternalVectorLength = KB::DefaultInternalVectorLength<T, M>;
381 static constexpr int vector_length = DefaultVectorLength<btdm_scalar_type, memory_space>::value;
382 static constexpr int internal_vector_length = DefaultInternalVectorLength<btdm_scalar_type, memory_space>::value;
383 static constexpr int half_vector_length = (vector_length > 1) ? (vector_length / 2) : 1;
391 typedef Kokkos::View<size_type **, device_type> size_type_2d_view;
392 typedef Kokkos::View<int64_t ***, Kokkos::LayoutRight, device_type> i64_3d_view;
393 typedef Kokkos::View<local_ordinal_type *, device_type> local_ordinal_type_1d_view;
394 typedef Kokkos::View<local_ordinal_type **, device_type> local_ordinal_type_2d_view;
396 typedef Kokkos::View<impl_scalar_type *, device_type> impl_scalar_type_1d_view;
397 typedef Kokkos::View<impl_scalar_type *, node_device_type> impl_scalar_type_1d_view_tpetra;
400 typedef Kokkos::View<impl_scalar_type **, Kokkos::LayoutLeft, device_type> impl_scalar_type_2d_view;
401 typedef Kokkos::View<impl_scalar_type **, Kokkos::LayoutLeft, node_device_type> impl_scalar_type_2d_view_tpetra;
402 typedef Kokkos::View<const impl_scalar_type **, Kokkos::LayoutLeft, node_device_type> const_impl_scalar_type_2d_view_tpetra;
405 typedef Kokkos::View<vector_type *, device_type> vector_type_1d_view;
406 typedef Kokkos::View<vector_type ***, Kokkos::LayoutRight, device_type> vector_type_3d_view;
407 typedef Kokkos::View<vector_type ****, Kokkos::LayoutRight, device_type> vector_type_4d_view;
408 typedef Kokkos::View<internal_vector_type ***, Kokkos::LayoutRight, device_type> internal_vector_type_3d_view;
409 typedef Kokkos::View<internal_vector_type ****, Kokkos::LayoutRight, device_type> internal_vector_type_4d_view;
410 typedef Kokkos::View<internal_vector_type *****, Kokkos::LayoutRight, device_type> internal_vector_type_5d_view;
411 typedef Kokkos::View<btdm_scalar_type **, Kokkos::LayoutRight, device_type> btdm_scalar_type_2d_view;
412 typedef Kokkos::View<btdm_scalar_type ***, Kokkos::LayoutRight, device_type> btdm_scalar_type_3d_view;
413 typedef Kokkos::View<btdm_scalar_type ****, Kokkos::LayoutRight, device_type> btdm_scalar_type_4d_view;
414 typedef Kokkos::View<btdm_scalar_type *****, Kokkos::LayoutRight, device_type> btdm_scalar_type_5d_view;
523 using magnitude_type =
typename impl_type::magnitude_type;
527 int sweep_step_, sweep_step_upper_bound_;
528#ifdef HAVE_IFPACK2_MPI
529 MPI_Request mpi_request_;
532 magnitude_type work_[3];
535 NormManager() =
default;
536 NormManager(
const NormManager &b) =
default;
537 NormManager(
const Teuchos::RCP<
const Teuchos::Comm<int>> &comm) {
539 sweep_step_upper_bound_ = 1;
540 collective_ = comm->getSize() > 1;
542#ifdef HAVE_IFPACK2_MPI
543 const auto mpi_comm = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int>>(comm);
544 TEUCHOS_ASSERT(!mpi_comm.is_null());
545 comm_ = *mpi_comm->getRawMpiComm();
548 const magnitude_type zero(0), minus_one(-1);
551 work_[2] = minus_one;
555 void setCheckFrequency(
const int sweep_step) {
556 TEUCHOS_TEST_FOR_EXCEPT_MSG(sweep_step < 1, "sweep step must be >= 1
");
557 sweep_step_upper_bound_ = sweep_step;
561 // Get the buffer into which to store rank-local squared norms.
562 magnitude_type *getBuffer() { return &work_[0]; }
564 // Call MPI_Iallreduce to find the global squared norms.
565 void ireduce(const int sweep, const bool force = false) {
566 if (!force && sweep % sweep_step_) return;
568 IFPACK2_BLOCKHELPER_TIMER("BlockTriDi::NormManager::Ireduce
", Ireduce);
571#ifdef HAVE_IFPACK2_MPI
572 auto send_data = &work_[1];
573 auto recv_data = &work_[0];
575#if defined(IFPACK2_BLOCKTRIDICONTAINER_USE_MPI_3)
576 MPI_Iallreduce(send_data, recv_data, 1,
577 Teuchos::Details::MpiTypeTraits<magnitude_type>::getType(),
578 MPI_SUM, comm_, &mpi_request_);
580 MPI_Allreduce(send_data, recv_data, 1,
581 Teuchos::Details::MpiTypeTraits<magnitude_type>::getType(),
588 // Check if the norm-based termination criterion is met. tol2 is the
589 // tolerance squared. Sweep is the sweep index. If not every iteration is
590 // being checked, this function immediately returns false. If a check must
591 // be done at this iteration, it waits for the reduction triggered by
592 // ireduce to complete, then checks the global norm against the tolerance.
593 bool checkDone(const int sweep, const magnitude_type tol2, const bool force = false) {
595 if (sweep <= 0) return false;
597 IFPACK2_BLOCKHELPER_TIMER("BlockTriDi::NormManager::CheckDone
", CheckDone);
599 TEUCHOS_ASSERT(sweep >= 1);
600 if (!force && (sweep - 1) % sweep_step_) return false;
602#ifdef HAVE_IFPACK2_MPI
603#if defined(IFPACK2_BLOCKTRIDICONTAINER_USE_MPI_3)
604 MPI_Wait(&mpi_request_, MPI_STATUS_IGNORE);
614 r_val = (work_[0] < tol2 * work_[2]);
618 const auto adjusted_sweep_step = 2 * sweep_step_;
619 if (adjusted_sweep_step < sweep_step_upper_bound_) {
620 sweep_step_ = adjusted_sweep_step;
622 sweep_step_ = sweep_step_upper_bound_;
627 // After termination has occurred, finalize the norms for use in
628 // get_norms{0,final}.
630 work_[0] = std::sqrt(work_[0]); // after converged
632 work_[2] = std::sqrt(work_[2]); // first norm
633 // if work_[2] is minus one, then norm is not requested.
636 // Report norms to the caller.
637 const magnitude_type getNorms0() const { return work_[2]; }
638 const magnitude_type getNormsFinal() const { return work_[0]; }