Ifpack2 Templated Preconditioning Package  Version 1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Ifpack2_BlockTriDiContainer_def.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_BLOCKTRIDICONTAINER_DEF_HPP
11 #define IFPACK2_BLOCKTRIDICONTAINER_DEF_HPP
12 
14 
15 #include <Tpetra_Distributor.hpp>
16 #include <Tpetra_BlockMultiVector.hpp>
17 #include <Tpetra_BlockCrsMatrix_Helpers.hpp>
18 
19 #include <Kokkos_ArithTraits.hpp>
20 #include <KokkosBatched_Util.hpp>
21 #include <KokkosBatched_Vector.hpp>
22 #include <KokkosBatched_AddRadial_Decl.hpp>
23 #include <KokkosBatched_AddRadial_Impl.hpp>
24 #include <KokkosBatched_Gemm_Decl.hpp>
25 #include <KokkosBatched_Gemm_Serial_Impl.hpp>
26 #include <KokkosBatched_Gemv_Decl.hpp>
27 #include <KokkosBatched_Trsm_Decl.hpp>
28 #include <KokkosBatched_Trsm_Serial_Impl.hpp>
29 #include <KokkosBatched_Trsv_Decl.hpp>
30 #include <KokkosBatched_Trsv_Serial_Impl.hpp>
31 #include <KokkosBatched_LU_Decl.hpp>
32 #include <KokkosBatched_LU_Serial_Impl.hpp>
33 
35 #include "Ifpack2_BlockTriDiContainer_impl.hpp"
36 
37 #include <memory>
38 
39 
40 namespace Ifpack2 {
41 
45 
46  template <typename MatrixType>
47  void
48  BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>
49  ::initInternal (const Teuchos::RCP<const row_matrix_type>& matrix,
50  const Teuchos::RCP<const import_type>& importer,
51  const bool overlapCommAndComp,
52  const bool useSeqMethod,
53  const int block_size,
54  const bool explicitConversion)
55  {
56  IFPACK2_BLOCKHELPER_TIMER_WITH_FENCE("BlockTriDiContainer::initInternal", initInternal, typename BlockHelperDetails::ImplType<MatrixType>::execution_space);
57 
58  // create pointer of impl
59  {
60  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createImpl", createImpl);
61  impl_ = Teuchos::rcp(new BlockTriDiContainerDetails::ImplObject<MatrixType>());
62  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
63  }
64 
65  using impl_type = BlockHelperDetails::ImplType<MatrixType>;
66  // using block_crs_matrix_type = typename impl_type::tpetra_block_crs_matrix_type;
67 
68  {
69  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::setA", setA);
70  if (explicitConversion) {
71  impl_->A = Teuchos::rcp_dynamic_cast<const block_crs_matrix_type>(matrix);
72  if (impl_->A.is_null()) {
74  (block_size == -1, "A pointwise matrix and block_size = -1 were given as inputs.");
75  {
76  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::setA::convertToBlockCrsMatrix", convertToBlockCrsMatrix);
77  impl_->A = Tpetra::convertToBlockCrsMatrix(*Teuchos::rcp_dynamic_cast<const crs_matrix_type>(matrix), block_size, true);
78  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
79  }
80  }
81  }
82  else {
83  impl_->A = matrix;
84  }
85  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
86  }
87 
88  impl_->tpetra_importer = Teuchos::null;
89  impl_->async_importer = Teuchos::null;
90 
91  if (useSeqMethod)
92  {
93  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createBlockCrsTpetraImporter useSeqMethod", useSeqMethod);
94  if (importer.is_null()) // there is no given importer, then create one
95  impl_->tpetra_importer = BlockTriDiContainerDetails::createBlockCrsTpetraImporter<MatrixType>(impl_->A);
96  else
97  impl_->tpetra_importer = importer; // if there is a given importer, use it
98  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
99  }
100  else
101  {
102  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createBlockCrsTpetraImporter", createBlockCrsTpetraImporter);
103  //Leave tpetra_importer null even if user provided an importer.
104  //It is not used in the performant codepath (!useSeqMethod)
105  impl_->async_importer = BlockTriDiContainerDetails::createBlockCrsAsyncImporter<MatrixType>(impl_->A);
106  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
107  }
108 
109  // as a result, there are
110  // 1) tpetra_importer is null , async_importer is null (no need for importer)
111  // 2) tpetra_importer is NOT null , async_importer is null (sequential method is used)
112  // 3) tpetra_importer is null , async_importer is NOT null (async method is used)
113 
114  // temporary disabling
115  impl_->overlap_communication_and_computation = overlapCommAndComp;
116 
117  {
118  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createZ", createZ);
119  impl_->Z = typename impl_type::tpetra_multivector_type();
120  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
121  }
122  {
123  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createW", createW);
124  impl_->W = typename impl_type::impl_scalar_type_1d_view();
125  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
126  }
127 
128  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
129  }
130 
131  template <typename MatrixType>
132  void
133  BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>
134  ::clearInternal ()
135  {
136  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::clearInternal", clearInternal);
137  using impl_type = BlockHelperDetails::ImplType<MatrixType>;
138  using part_interface_type = BlockHelperDetails::PartInterface<MatrixType>;
139  using block_tridiags_type = BlockTriDiContainerDetails::BlockTridiags<MatrixType>;
140  using amd_type = BlockHelperDetails::AmD<MatrixType>;
141  using norm_manager_type = BlockHelperDetails::NormManager<MatrixType>;
142 
143  impl_->A = Teuchos::null;
144  impl_->tpetra_importer = Teuchos::null;
145  impl_->async_importer = Teuchos::null;
146 
147  impl_->Z = typename impl_type::tpetra_multivector_type();
148  impl_->W = typename impl_type::impl_scalar_type_1d_view();
149 
150  impl_->part_interface = part_interface_type();
151  impl_->block_tridiags = block_tridiags_type();
152  impl_->a_minus_d = amd_type();
153  impl_->work = typename impl_type::vector_type_1d_view();
154  impl_->norm_manager = norm_manager_type();
155 
156  impl_ = Teuchos::null;
157  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
158  }
159 
160  template <typename MatrixType>
164  const Teuchos::RCP<const import_type>& importer,
165  bool pointIndexed)
166  : Container<MatrixType>(matrix, partitions, pointIndexed), partitions_(partitions)
167  {
168  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::BlockTriDiContainer", BlockTriDiContainer);
169  const bool useSeqMethod = false;
170  const bool overlapCommAndComp = false;
171  initInternal(matrix, importer, overlapCommAndComp, useSeqMethod);
172  n_subparts_per_part_ = -1;
173  block_size_ = -1;
174  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
175  }
176 
177  template <typename MatrixType>
181  const int n_subparts_per_part,
182  const bool overlapCommAndComp,
183  const bool useSeqMethod,
184  const int block_size,
185  const bool explicitConversion)
186  : Container<MatrixType>(matrix, partitions, false), partitions_(partitions)
187  {
188  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::BlockTriDiContainer", BlockTriDiContainer);
189  initInternal(matrix, Teuchos::null, overlapCommAndComp, useSeqMethod, block_size, explicitConversion);
190  n_subparts_per_part_ = n_subparts_per_part;
191  block_size_ = block_size;
192  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
193  }
194 
195  template <typename MatrixType>
198  {
199  }
200 
201  template <typename MatrixType>
202  void
205  {
206  if (List.isType<int>("partitioner: subparts per part"))
207  n_subparts_per_part_ = List.get<int>("partitioner: subparts per part");
208  if (List.isType<int>("partitioner: block size"))
209  block_size_ = List.get<int>("partitioner: block size");
210  }
211 
212  template <typename MatrixType>
213  void
216  {
217  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::initialize", initialize);
218  this->IsInitialized_ = true;
219  {
220  auto bA = Teuchos::rcp_dynamic_cast<const block_crs_matrix_type>(impl_->A);
221  if (bA.is_null()) {
223  (block_size_ == -1, "A pointwise matrix and block_size = -1 were given as inputs.");
224  {
225  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::initialize::getBlockCrsGraph", getBlockCrsGraph);
226  auto A = Teuchos::rcp_dynamic_cast<const crs_matrix_type>(impl_->A);
227  impl_->blockGraph = Tpetra::getBlockCrsGraph(*A, block_size_, true);
228  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
229  }
230  }
231  else {
232  impl_->blockGraph = Teuchos::rcpFromRef(bA->getCrsGraph());
233  }
234  }
235 
236  {
237  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createPartInterfaceBlockTridiagsNormManager", createPartInterfaceBlockTridiagsNormManager);
238  impl_->part_interface = BlockTriDiContainerDetails::createPartInterface<MatrixType>(impl_->A, impl_->blockGraph, partitions_, n_subparts_per_part_);
239  impl_->block_tridiags = BlockTriDiContainerDetails::createBlockTridiags<MatrixType>(impl_->part_interface);
240  impl_->norm_manager = BlockHelperDetails::NormManager<MatrixType>(impl_->A->getComm());
241  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
242  }
243 
244  // We assume that if you called this method, you intend to recompute
245  // everything.
246  this->IsComputed_ = false;
247  TEUCHOS_ASSERT(!impl_->A.is_null()); // when initInternal is called, A_ must be set
248  {
249  BlockTriDiContainerDetails::performSymbolicPhase<MatrixType>
250  (impl_->A,
251  impl_->blockGraph,
252  impl_->part_interface,
253  impl_->block_tridiags,
254  impl_->a_minus_d,
255  impl_->overlap_communication_and_computation);
256  }
257  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
258  }
259 
260  template <typename MatrixType>
261  void
264  {
265  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::compute", compute);
266  this->IsComputed_ = false;
267  if (!this->isInitialized())
268  this->initialize();
269  {
270  BlockTriDiContainerDetails::performNumericPhase<MatrixType>
271  (impl_->A,
272  impl_->blockGraph,
273  impl_->part_interface, impl_->block_tridiags,
274  Kokkos::ArithTraits<magnitude_type>::zero());
275  }
276  this->IsComputed_ = true;
277  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
278  }
279 
280  template <typename MatrixType>
281  void
284  {
285  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::clearBlocks", clearBlocks);
286  clearInternal();
287  this->IsInitialized_ = false;
288  this->IsComputed_ = false;
290  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
291  }
292 
293  template <typename MatrixType>
294  void
295  BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>
296  ::applyInverseJacobi (const mv_type& X, mv_type& Y, scalar_type dampingFactor,
297  bool zeroStartingSolution, int numSweeps) const
298  {
299  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::applyInverseJacobi", applyInverseJacobi);
300  const magnitude_type tol = Kokkos::ArithTraits<magnitude_type>::zero();
301  const int check_tol_every = 1;
302 
303  BlockTriDiContainerDetails::applyInverseJacobi<MatrixType>
304  (impl_->A,
305  impl_->blockGraph,
306  impl_->tpetra_importer,
307  impl_->async_importer,
308  impl_->overlap_communication_and_computation,
309  X, Y, impl_->Z, impl_->W,
310  impl_->part_interface, impl_->block_tridiags, impl_->a_minus_d,
311  impl_->work,
312  impl_->norm_manager,
313  dampingFactor,
314  zeroStartingSolution,
315  numSweeps,
316  tol,
317  check_tol_every);
318  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
319  }
320 
321  template <typename MatrixType>
322  typename BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>::ComputeParameters
325  {
326  return ComputeParameters();
327  }
328 
329  template <typename MatrixType>
330  void
332  ::compute (const ComputeParameters& in)
333  {
334  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::compute", compute);
335  this->IsComputed_ = false;
336  if (!this->isInitialized())
337  this->initialize();
338  {
339  BlockTriDiContainerDetails::performNumericPhase<MatrixType>
340  (impl_->A,
341  impl_->blockGraph,
342  impl_->part_interface, impl_->block_tridiags,
343  in.addRadiallyToDiagonal);
344  }
345  this->IsComputed_ = true;
346  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
347  }
348 
349  template <typename MatrixType>
353  {
354  ApplyParameters in;
355  in.dampingFactor = Teuchos::ScalarTraits<scalar_type>::one();
356  return in;
357  }
358 
359  template <typename MatrixType>
360  int
362  ::applyInverseJacobi (const mv_type& X, mv_type& Y,
363  const ApplyParameters& in) const
364  {
365  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::applyInverseJacobi", applyInverseJacobi);
366  int r_val = 0;
367  {
368  r_val = BlockTriDiContainerDetails::applyInverseJacobi<MatrixType>
369  (impl_->A,
370  impl_->blockGraph,
371  impl_->tpetra_importer,
372  impl_->async_importer,
373  impl_->overlap_communication_and_computation,
374  X, Y, impl_->Z, impl_->W,
375  impl_->part_interface, impl_->block_tridiags, impl_->a_minus_d,
376  impl_->work,
377  impl_->norm_manager,
378  in.dampingFactor,
379  in.zeroStartingSolution,
380  in.maxNumSweeps,
381  in.tolerance,
382  in.checkToleranceEvery);
383  }
384  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
385  return r_val;
386  }
387 
388  template <typename MatrixType>
391  ::getNorms0 () const {
392  return impl_->norm_manager.getNorms0();
393  }
394 
395  template <typename MatrixType>
399  return impl_->norm_manager.getNormsFinal();
400  }
401 
402  template <typename MatrixType>
403  void
405  ::apply (ConstHostView /* X */, HostView /* Y */, int /* blockIndex */, Teuchos::ETransp /* mode */,
406  scalar_type /* alpha */, scalar_type /* beta */) const
407  {
408  TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "BlockTriDiContainer::apply is not implemented. You may have reached this message "
409  << "because you want to use this container's performance-portable Jacobi iteration. In "
410  << "that case, set \"relaxation: type\" to \"MT Split Jacobi\" rather than \"Jacobi\".");
411  }
412 
413  template <typename MatrixType>
414  void
416  ::weightedApply (ConstHostView /* X */, HostView /* Y */, ConstHostView /* D */, int /* blockIndex */,
417  Teuchos::ETransp /* mode */, scalar_type /* alpha */, scalar_type /* beta */) const
418  {
419  TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "BlockTriDiContainer::weightedApply is not implemented.");
420  }
421 
422  template <typename MatrixType>
423  std::ostream&
425  ::print (std::ostream& os) const
426  {
427  Teuchos::FancyOStream fos(Teuchos::rcp(&os,false));
428  fos.setOutputToRootOnly(0);
429  describe(fos);
430  return os;
431  }
432 
433  template <typename MatrixType>
434  std::string
437  {
438  std::ostringstream oss;
440  if (this->isInitialized()) {
441  if (this->isComputed()) {
442  oss << "{status = initialized, computed";
443  }
444  else {
445  oss << "{status = initialized, not computed";
446  }
447  }
448  else {
449  oss << "{status = not initialized, not computed";
450  }
451 
452  oss << "}";
453  return oss.str();
454  }
455 
456  template <typename MatrixType>
457  void
460  const Teuchos::EVerbosityLevel verbLevel) const
461  {
462  using std::endl;
463  if(verbLevel==Teuchos::VERB_NONE) return;
464  os << "================================================================================" << endl
465  << "Ifpack2::BlockTriDiContainer" << endl
466  << "Number of blocks = " << this->numBlocks_ << endl
467  << "isInitialized() = " << this->IsInitialized_ << endl
468  << "isComputed() = " << this->IsComputed_ << endl
469  << "================================================================================" << endl
470  << endl;
471  }
472 
473  template <typename MatrixType>
474  std::string
476  ::getName() { return "Ifpack2::BlockTriDiContainer::ImplSimdTag"; }
477 
478 #define IFPACK2_BLOCKTRIDICONTAINER_INSTANT(S,LO,GO,N) \
479  template class Ifpack2::BlockTriDiContainer< Tpetra::RowMatrix<S, LO, GO, N> >;
480 }
481 #endif
Ifpack2::BlockTriDiContainer class declaration.
T & get(const std::string &name, T def_value)
Store and solve local block tridiagonal linear problems.
Definition: Ifpack2_BlockTriDiContainer_decl.hpp:101
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
#define TEUCHOS_TEST_FOR_EXCEPT_MSG(throw_exception_test, msg)
Definition: Ifpack2_BlockHelper.hpp:350
BlockTriDiContainer(const Teuchos::RCP< const row_matrix_type > &matrix, const Teuchos::Array< Teuchos::Array< local_ordinal_type > > &partitions, const Teuchos::RCP< const import_type > &importer, bool pointIndexed)
Constructor.
Definition: Ifpack2_BlockTriDiContainer_def.hpp:162
virtual std::string description() const
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Interface for creating and solving a set of local linear problems.
Definition: Ifpack2_Container_decl.hpp:79
bool isType(const std::string &name) const
ComputeParameters createDefaultComputeParameters() const
Create a ComputeParameters struct with default values.
Definition: Ifpack2_BlockTriDiContainer_def.hpp:324
#define TEUCHOS_ASSERT(assertion_test)
bool is_null() const