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 //
4 // Ifpack2: Templated Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2009) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 #ifndef IFPACK2_BLOCKTRIDICONTAINER_DEF_HPP
44 #define IFPACK2_BLOCKTRIDICONTAINER_DEF_HPP
45 
47 
48 #include <Tpetra_Distributor.hpp>
49 #include <Tpetra_BlockMultiVector.hpp>
50 #include <Tpetra_BlockCrsMatrix_Helpers.hpp>
51 
52 #include <Kokkos_ArithTraits.hpp>
53 #include <KokkosBatched_Util.hpp>
54 #include <KokkosBatched_Vector.hpp>
55 #include <KokkosBatched_AddRadial_Decl.hpp>
56 #include <KokkosBatched_AddRadial_Impl.hpp>
57 #include <KokkosBatched_Gemm_Decl.hpp>
58 #include <KokkosBatched_Gemm_Serial_Impl.hpp>
59 #include <KokkosBatched_Gemv_Decl.hpp>
60 #include <KokkosBatched_Trsm_Decl.hpp>
61 #include <KokkosBatched_Trsm_Serial_Impl.hpp>
62 #include <KokkosBatched_Trsv_Decl.hpp>
63 #include <KokkosBatched_Trsv_Serial_Impl.hpp>
64 #include <KokkosBatched_LU_Decl.hpp>
65 #include <KokkosBatched_LU_Serial_Impl.hpp>
66 
68 #include "Ifpack2_BlockTriDiContainer_impl.hpp"
69 
70 #include <memory>
71 
72 
73 namespace Ifpack2 {
74 
78 
79  template <typename MatrixType>
80  void
81  BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>
82  ::initInternal (const Teuchos::RCP<const row_matrix_type>& matrix,
83  const Teuchos::RCP<const import_type>& importer,
84  const bool overlapCommAndComp,
85  const bool useSeqMethod,
86  const int block_size)
87  {
88  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::initInternal");
89 
90  // create pointer of impl
91  {
92  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createImpl");
93  impl_ = Teuchos::rcp(new BlockTriDiContainerDetails::ImplObject<MatrixType>());
94  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
95  }
96 
97  using impl_type = BlockHelperDetails::ImplType<MatrixType>;
98  // using block_crs_matrix_type = typename impl_type::tpetra_block_crs_matrix_type;
99 
100  {
101  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::setA");
102  impl_->A = Teuchos::rcp_dynamic_cast<const block_crs_matrix_type>(matrix);
103  if (impl_->A.is_null()) {
105  (block_size == -1, "A pointwise matrix and block_size = -1 were given as inputs.");
106  {
107  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::setA::convertToBlockCrsMatrix");
108  impl_->A = Tpetra::convertToBlockCrsMatrix(*Teuchos::rcp_dynamic_cast<const crs_matrix_type>(matrix), block_size, false);
109  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
110  }
111  }
112  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
113  }
114 
115  impl_->tpetra_importer = Teuchos::null;
116  impl_->async_importer = Teuchos::null;
117 
118  if (useSeqMethod)
119  {
120  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createBlockCrsTpetraImporter useSeqMethod");
121  if (importer.is_null()) // there is no given importer, then create one
122  impl_->tpetra_importer = BlockTriDiContainerDetails::createBlockCrsTpetraImporter<MatrixType>(impl_->A);
123  else
124  impl_->tpetra_importer = importer; // if there is a given importer, use it
125  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
126  }
127  else
128  {
129  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createBlockCrsTpetraImporter");
130  //Leave tpetra_importer null even if user provided an importer.
131  //It is not used in the performant codepath (!useSeqMethod)
132  impl_->async_importer = BlockTriDiContainerDetails::createBlockCrsAsyncImporter<MatrixType>(impl_->A);
133  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
134  }
135 
136  // as a result, there are
137  // 1) tpetra_importer is null , async_importer is null (no need for importer)
138  // 2) tpetra_importer is NOT null , async_importer is null (sequential method is used)
139  // 3) tpetra_importer is null , async_importer is NOT null (async method is used)
140 
141  // temporary disabling
142  impl_->overlap_communication_and_computation = overlapCommAndComp;
143 
144  {
145  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createZ");
146  impl_->Z = typename impl_type::tpetra_multivector_type();
147  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
148  }
149  {
150  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createW");
151  impl_->W = typename impl_type::impl_scalar_type_1d_view();
152  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
153  }
154 
155  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
156  }
157 
158  template <typename MatrixType>
159  void
160  BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>
161  ::clearInternal ()
162  {
163  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::clearInternal");
164  using impl_type = BlockHelperDetails::ImplType<MatrixType>;
165  using part_interface_type = BlockHelperDetails::PartInterface<MatrixType>;
166  using block_tridiags_type = BlockTriDiContainerDetails::BlockTridiags<MatrixType>;
167  using amd_type = BlockHelperDetails::AmD<MatrixType>;
168  using norm_manager_type = BlockHelperDetails::NormManager<MatrixType>;
169 
170  impl_->A = Teuchos::null;
171  impl_->tpetra_importer = Teuchos::null;
172  impl_->async_importer = Teuchos::null;
173 
174  impl_->Z = typename impl_type::tpetra_multivector_type();
175  impl_->W = typename impl_type::impl_scalar_type_1d_view();
176 
177  impl_->part_interface = part_interface_type();
178  impl_->block_tridiags = block_tridiags_type();
179  impl_->a_minus_d = amd_type();
180  impl_->work = typename impl_type::vector_type_1d_view();
181  impl_->norm_manager = norm_manager_type();
182 
183  impl_ = Teuchos::null;
184  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
185  }
186 
187  template <typename MatrixType>
191  const Teuchos::RCP<const import_type>& importer,
192  bool pointIndexed)
193  : Container<MatrixType>(matrix, partitions, pointIndexed), partitions_(partitions)
194  {
195  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::BlockTriDiContainer");
196  const bool useSeqMethod = false;
197  const bool overlapCommAndComp = false;
198  initInternal(matrix, importer, overlapCommAndComp, useSeqMethod);
199  n_subparts_per_part_ = -1;
200  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
201  }
202 
203  template <typename MatrixType>
207  const int n_subparts_per_part,
208  const bool overlapCommAndComp,
209  const bool useSeqMethod,
210  const int block_size)
211  : Container<MatrixType>(matrix, partitions, false), partitions_(partitions)
212  {
213  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::BlockTriDiContainer");
214  initInternal(matrix, Teuchos::null, overlapCommAndComp, useSeqMethod, block_size);
215  n_subparts_per_part_ = n_subparts_per_part;
216  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
217  }
218 
219  template <typename MatrixType>
222  {
223  }
224 
225  template <typename MatrixType>
226  void
229  {
230  if (List.isType<int>("partitioner: subparts per part"))
231  n_subparts_per_part_ = List.get<int>("partitioner: subparts per part");
232  }
233 
234  template <typename MatrixType>
235  void
238  {
239  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::initialize");
240  this->IsInitialized_ = true;
241  {
242  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::createPartInterfaceBlockTridiagsNormManager");
243  impl_->part_interface = BlockTriDiContainerDetails::createPartInterface<MatrixType>(impl_->A, partitions_, n_subparts_per_part_);
244  impl_->block_tridiags = BlockTriDiContainerDetails::createBlockTridiags<MatrixType>(impl_->part_interface);
245  impl_->norm_manager = BlockHelperDetails::NormManager<MatrixType>(impl_->A->getComm());
246  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
247  }
248  // We assume that if you called this method, you intend to recompute
249  // everything.
250  this->IsComputed_ = false;
251  TEUCHOS_ASSERT(!impl_->A.is_null()); // when initInternal is called, A_ must be set
252  {
253  BlockTriDiContainerDetails::performSymbolicPhase<MatrixType>
254  (impl_->A,
255  impl_->part_interface, impl_->block_tridiags,
256  impl_->a_minus_d,
257  impl_->overlap_communication_and_computation);
258  }
259  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
260  }
261 
262  template <typename MatrixType>
263  void
266  {
267  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::compute");
268  this->IsComputed_ = false;
269  if (!this->isInitialized())
270  this->initialize();
271  {
272  BlockTriDiContainerDetails::performNumericPhase<MatrixType>
273  (impl_->A,
274  impl_->part_interface, impl_->block_tridiags,
275  Kokkos::ArithTraits<magnitude_type>::zero());
276  }
277  this->IsComputed_ = true;
278  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
279  }
280 
281  template <typename MatrixType>
282  void
285  {
286  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::clearBlocks");
287  clearInternal();
288  this->IsInitialized_ = false;
289  this->IsComputed_ = false;
291  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
292  }
293 
294  template <typename MatrixType>
295  void
296  BlockTriDiContainer<MatrixType, BlockTriDiContainerDetails::ImplSimdTag>
297  ::applyInverseJacobi (const mv_type& X, mv_type& Y, scalar_type dampingFactor,
298  bool zeroStartingSolution, int numSweeps) const
299  {
300  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::applyInverseJacobi");
301  const magnitude_type tol = Kokkos::ArithTraits<magnitude_type>::zero();
302  const int check_tol_every = 1;
303 
304  BlockTriDiContainerDetails::applyInverseJacobi<MatrixType>
305  (impl_->A,
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");
335  this->IsComputed_ = false;
336  if (!this->isInitialized())
337  this->initialize();
338  {
339  BlockTriDiContainerDetails::performNumericPhase<MatrixType>
340  (impl_->A,
341  impl_->part_interface, impl_->block_tridiags,
342  in.addRadiallyToDiagonal);
343  }
344  this->IsComputed_ = true;
345  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
346  }
347 
348  template <typename MatrixType>
352  {
353  ApplyParameters in;
354  in.dampingFactor = Teuchos::ScalarTraits<scalar_type>::one();
355  return in;
356  }
357 
358  template <typename MatrixType>
359  int
361  ::applyInverseJacobi (const mv_type& X, mv_type& Y,
362  const ApplyParameters& in) const
363  {
364  IFPACK2_BLOCKHELPER_TIMER("BlockTriDiContainer::applyInverseJacobi");
365  int r_val = 0;
366  {
367  r_val = BlockTriDiContainerDetails::applyInverseJacobi<MatrixType>
368  (impl_->A,
369  impl_->tpetra_importer,
370  impl_->async_importer,
371  impl_->overlap_communication_and_computation,
372  X, Y, impl_->Z, impl_->W,
373  impl_->part_interface, impl_->block_tridiags, impl_->a_minus_d,
374  impl_->work,
375  impl_->norm_manager,
376  in.dampingFactor,
377  in.zeroStartingSolution,
378  in.maxNumSweeps,
379  in.tolerance,
380  in.checkToleranceEvery);
381  }
382  IFPACK2_BLOCKHELPER_TIMER_FENCE(typename BlockHelperDetails::ImplType<MatrixType>::execution_space)
383  return r_val;
384  }
385 
386  template <typename MatrixType>
389  ::getNorms0 () const {
390  return impl_->norm_manager.getNorms0();
391  }
392 
393  template <typename MatrixType>
397  return impl_->norm_manager.getNormsFinal();
398  }
399 
400  template <typename MatrixType>
401  void
403  ::apply (ConstHostView /* X */, HostView /* Y */, int /* blockIndex */, Teuchos::ETransp /* mode */,
404  scalar_type /* alpha */, scalar_type /* beta */) const
405  {
406  TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "BlockTriDiContainer::apply is not implemented. You may have reached this message "
407  << "because you want to use this container's performance-portable Jacobi iteration. In "
408  << "that case, set \"relaxation: type\" to \"MT Split Jacobi\" rather than \"Jacobi\".");
409  }
410 
411  template <typename MatrixType>
412  void
414  ::weightedApply (ConstHostView /* X */, HostView /* Y */, ConstHostView /* D */, int /* blockIndex */,
415  Teuchos::ETransp /* mode */, scalar_type /* alpha */, scalar_type /* beta */) const
416  {
417  TEUCHOS_TEST_FOR_EXCEPT_MSG(true, "BlockTriDiContainer::weightedApply is not implemented.");
418  }
419 
420  template <typename MatrixType>
421  std::ostream&
423  ::print (std::ostream& os) const
424  {
425  Teuchos::FancyOStream fos(Teuchos::rcp(&os,false));
426  fos.setOutputToRootOnly(0);
427  describe(fos);
428  return os;
429  }
430 
431  template <typename MatrixType>
432  std::string
435  {
436  std::ostringstream oss;
438  if (this->isInitialized()) {
439  if (this->isComputed()) {
440  oss << "{status = initialized, computed";
441  }
442  else {
443  oss << "{status = initialized, not computed";
444  }
445  }
446  else {
447  oss << "{status = not initialized, not computed";
448  }
449 
450  oss << "}";
451  return oss.str();
452  }
453 
454  template <typename MatrixType>
455  void
458  const Teuchos::EVerbosityLevel verbLevel) const
459  {
460  using std::endl;
461  if(verbLevel==Teuchos::VERB_NONE) return;
462  os << "================================================================================" << endl
463  << "Ifpack2::BlockTriDiContainer" << endl
464  << "Number of blocks = " << this->numBlocks_ << endl
465  << "isInitialized() = " << this->IsInitialized_ << endl
466  << "isComputed() = " << this->IsComputed_ << endl
467  << "================================================================================" << endl
468  << endl;
469  }
470 
471  template <typename MatrixType>
472  std::string
474  ::getName() { return "Ifpack2::BlockTriDiContainer::ImplSimdTag"; }
475 
476 #define IFPACK2_BLOCKTRIDICONTAINER_INSTANT(S,LO,GO,N) \
477  template class Ifpack2::BlockTriDiContainer< Tpetra::RowMatrix<S, LO, GO, N> >;
478 }
479 #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:134
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:388
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:189
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:112
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