Tpetra parallel linear algebra  Version of the Day
Tpetra_Experimental_BlockView.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
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 #ifndef TPETRA_EXPERIMENTAL_BLOCKVIEW_HPP
43 #define TPETRA_EXPERIMENTAL_BLOCKVIEW_HPP
44 
47 
48 #include "Tpetra_ConfigDefs.hpp"
49 #include "Teuchos_ScalarTraits.hpp"
50 #include "Teuchos_LAPACK.hpp"
51 #ifdef HAVE_TPETRA_INST_FLOAT128
52 # include "Teuchos_BLAS.hpp"
53 #endif // HAVE_TPETRA_INST_FLOAT128
54 
55 #include "Kokkos_ArithTraits.hpp"
56 #include "Kokkos_Complex.hpp"
57 
58 #ifdef HAVE_TPETRA_INST_FLOAT128
59 # include "Teuchos_Details_Lapack128.hpp"
60 #endif // HAVE_TPETRA_INST_FLOAT128
61 
62 namespace Tpetra {
63 namespace Details {
64 
74  template<class Scalar>
75  struct GetLapackType {
76  typedef Scalar lapack_scalar_type;
77  typedef Teuchos::LAPACK<int, Scalar> lapack_type;
78  };
79 
80  template<class T>
81  struct GetLapackType<Kokkos::complex<T> > {
82  typedef std::complex<T> lapack_scalar_type;
83  typedef Teuchos::LAPACK<int, std::complex<T> > lapack_type;
84  };
85 
86 #ifdef HAVE_TPETRA_INST_FLOAT128
87  template<>
88  struct GetLapackType<__float128> {
89  typedef __float128 lapack_scalar_type;
90  // Use the Lapack128 class we declared above to implement the
91  // linear algebra operations needed for small dense blocks and
92  // vectors.
93  typedef Teuchos::Details::Lapack128 lapack_type;
94  };
95 #endif // HAVE_TPETRA_INST_FLOAT128
96 
97 } // namespace Details
98 } // namespace Tpetra
99 
100 
101 namespace Tpetra {
102 
114 namespace Experimental {
115 
130 template<class Scalar, class LO>
131 class LittleBlock {
132 public:
133  typedef Scalar scalar_type;
134  typedef typename Kokkos::Details::ArithTraits<Scalar>::val_type impl_scalar_type;
135 
136 private:
137  typedef Kokkos::Details::ArithTraits<impl_scalar_type> STS;
138 
139 public:
145  LittleBlock (Scalar* const A,
146  const LO blockSize,
147  const LO strideX,
148  const LO strideY) :
149  A_ (reinterpret_cast<impl_scalar_type*> (A)),
150  blockSize_ (blockSize),
151  strideX_ (strideX),
152  strideY_ (strideY)
153  {}
154 
172  template<class T>
173  LittleBlock (T* const A,
174  const LO blockSize,
175  const LO strideX,
176  const LO strideY,
177  typename std::enable_if<
178  ! std::is_same<Scalar, T>::value &&
179  std::is_convertible<Scalar, T>::value &&
180  sizeof (Scalar) == sizeof (T),
181  int*>::type ignoreMe = NULL) :
182  A_ (reinterpret_cast<impl_scalar_type*> (A)),
183  blockSize_ (blockSize),
184  strideX_ (strideX),
185  strideY_ (strideY)
186  {}
187 
189  LO getBlockSize () const {
190  return blockSize_;
191  }
192 
194  Scalar* getRawPtr () const {
195  return reinterpret_cast<Scalar*> (A_);
196  }
197 
208  impl_scalar_type& operator() (const LO i, const LO j) const {
209  return A_[i * strideX_ + j * strideY_];
210  }
211 
213  template<class LittleBlockType>
214  void update (const Scalar& alpha, const LittleBlockType& X) const {
215  const impl_scalar_type theAlpha = static_cast<Scalar> (alpha);
216  for (LO j = 0; j < blockSize_; ++j) {
217  for (LO i = 0; i < blockSize_; ++i) {
218  (*this)(i,j) += theAlpha * X(i,j);
219  }
220  }
221  }
222 
224  template<class LittleBlockType>
225  void assign (const LittleBlockType& X) const {
226  for (LO j = 0; j < blockSize_; ++j) {
227  for (LO i = 0; i < blockSize_; ++i) {
228  (*this)(i,j) = X(i,j);
229  }
230  }
231  }
232 
234  void scale (const Scalar& alpha) const {
235  const impl_scalar_type theAlpha = static_cast<Scalar> (alpha);
236  for (LO j = 0; j < blockSize_; ++j) {
237  for (LO i = 0; i < blockSize_; ++i) {
238  (*this)(i,j) *= theAlpha;
239  }
240  }
241  }
242 
244  void fill (const Scalar& alpha) const {
245  const impl_scalar_type theAlpha = static_cast<Scalar> (alpha);
246  for (LO j = 0; j < blockSize_; ++j) {
247  for (LO i = 0; i < blockSize_; ++i) {
248  (*this)(i,j) = theAlpha;
249  }
250  }
251  }
252 
257  template<class LittleBlockType>
258  void absmax (const LittleBlockType& X) const {
259  for (LO j = 0; j < blockSize_; ++j) {
260  for (LO i = 0; i < blockSize_; ++i) {
261  impl_scalar_type& Y_ij = (*this)(i,j);
262  const impl_scalar_type X_ij = X(i,j);
263  Y_ij = std::max (STS::magnitude (Y_ij), STS::magnitude (X_ij));
264  }
265  }
266  }
267 
268  void factorize (int* ipiv, int & info)
269  {
270  typedef typename Tpetra::Details::GetLapackType<Scalar>::lapack_scalar_type LST;
271  typedef typename Tpetra::Details::GetLapackType<Scalar>::lapack_type lapack_type;
272 
273  LST* const A_raw = reinterpret_cast<LST*> (A_);
274  lapack_type lapack;
275  // NOTE (mfh 03 Jan 2015) This method doesn't check the 'info'
276  // output argument, but it returns info, so the user is
277  // responsible for checking.
278  lapack.GETRF(blockSize_, blockSize_, A_raw, blockSize_, ipiv, &info);
279  }
280 
281  template<class LittleVectorType>
282  void solve (LittleVectorType & X, const int* ipiv) const
283  {
284  typedef typename Tpetra::Details::GetLapackType<Scalar>::lapack_scalar_type LST;
285  typedef typename Tpetra::Details::GetLapackType<Scalar>::lapack_type lapack_type;
286 
287  // FIXME (mfh 03 Jan 2015) Check using enable_if that Scalar can
288  // be safely converted to LST.
289 
290  lapack_type lapack;
291  LST* const A_raw = reinterpret_cast<LST*> (A_);
292  LST* const X_raw = reinterpret_cast<LST*> (X.getRawPtr ());
293  int info = 0;
294  char trans = 'T';
295  // FIXME (mfh 03 Jan 2015) Either check the 'info' output
296  // argument, or return it.
297  lapack.GETRS(trans, blockSize_, 1, A_raw, blockSize_, ipiv, X_raw, blockSize_, &info);
298  }
299 
300 private:
301  impl_scalar_type* const A_;
302  const LO blockSize_;
303  const LO strideX_;
304  const LO strideY_;
305 };
306 
307 
324 template<class Scalar, class LO>
326 public:
327  typedef Scalar scalar_type;
328  typedef typename Kokkos::Details::ArithTraits<Scalar>::val_type impl_scalar_type;
329 
330 private:
331  typedef Kokkos::Details::ArithTraits<impl_scalar_type> STS;
332 
333 public:
338  LittleVector (Scalar* const A, const LO blockSize, const LO stride) :
339  A_ (reinterpret_cast<impl_scalar_type*> (A)),
340  blockSize_ (blockSize),
341  strideX_ (stride)
342  {}
343 
360  template<class T>
361  LittleVector (T* const A,
362  const LO blockSize,
363  const LO stride,
364  typename std::enable_if<
365  ! std::is_same<Scalar, T>::value &&
366  std::is_convertible<Scalar, T>::value &&
367  sizeof (Scalar) == sizeof (T),
368  int*>::type ignoreMe = NULL) :
369  A_ (reinterpret_cast<impl_scalar_type*> (A)),
370  blockSize_ (blockSize),
371  strideX_ (stride)
372  {}
373 
375  Scalar* getRawPtr () const {
376  return reinterpret_cast<Scalar*> (A_);
377  }
378 
380  LO getBlockSize () const {
381  return blockSize_;
382  }
383 
385  LO getStride () const {
386  return strideX_;
387  }
388 
399  impl_scalar_type& operator() (const LO i) const {
400  return A_[i * strideX_];
401  }
402 
404  template<class LittleVectorType>
405  void update (const Scalar& alpha, const LittleVectorType& X) const {
406  const impl_scalar_type theAlpha = static_cast<impl_scalar_type> (alpha);
407  for (LO i = 0; i < blockSize_; ++i) {
408  (*this)(i) += theAlpha * X(i);
409  }
410  }
411 
413  template<class LittleVectorType>
414  void assign (const LittleVectorType& X) const {
415  for (LO i = 0; i < blockSize_; ++i) {
416  (*this)(i) = X(i);
417  }
418  }
419 
421  void scale (const Scalar& alpha) const {
422  const impl_scalar_type theAlpha = static_cast<impl_scalar_type> (alpha);
423  for (LO i = 0; i < blockSize_; ++i) {
424  (*this)(i) *= theAlpha;
425  }
426  }
427 
429  void fill (const Scalar& alpha) const {
430  const impl_scalar_type theAlpha = static_cast<impl_scalar_type> (alpha);
431  for (LO i = 0; i < blockSize_; ++i) {
432  (*this)(i) = theAlpha;
433  }
434  }
435 
440  template<class LittleVectorType>
441  void absmax (const LittleVectorType& X) const {
442  for (LO i = 0; i < blockSize_; ++i) {
443  impl_scalar_type& Y_i = (*this)(i);
444  Y_i = std::max (STS::magnitude (Y_i), STS::magnitude (X (i)));
445  }
446  }
447 
449  template<class LittleVectorType>
450  bool equal (const LittleVectorType& X) const {
451  if (getBlockSize () != X.getBlockSize ()) {
452  return false;
453  }
454  for (LO i = 0; i < blockSize_; ++i) {
455  if ((*this)(i) != X(i)) {
456  return false;
457  }
458  }
459  return true;
460  }
461 
463  template<class LittleBlockType, class LittleVectorType>
464  void
465  matvecUpdate (const Scalar& alpha,
466  const LittleBlockType& A,
467  const LittleVectorType& X) const
468  {
469  const impl_scalar_type theAlpha = static_cast<impl_scalar_type> (alpha);
470  // FIXME (mfh 07 May 2014) This is suitable for column major, not
471  // for row major. Of course, we'll have to change other loops
472  // above as well to make row major faster.
473  for (LO i = 0; i < blockSize_; ++i) {
474  for (LO j = 0; j < blockSize_; ++j) {
475  (*this)(i) += theAlpha * A(i,j) * X(j);
476  }
477  }
478  }
479 
480 private:
481  impl_scalar_type* const A_;
482  const LO blockSize_;
483  const LO strideX_;
484 };
485 
486 } // namespace Experimental
487 } // namespace Tpetra
488 
489 #endif // TPETRA_EXPERIMENTAL_BLOCKVIEW_HPP
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void fill(const Scalar &alpha) const
(*this)(i,j) := alpha for all (i,j).
void scale(const Scalar &alpha) const
(*this)(i,j) := alpha * (*this)(i,j) for all (i,j).
Scalar * getRawPtr() const
Pointer to the block&#39;s entries, as Scalar*.
void matvecUpdate(const Scalar &alpha, const LittleBlockType &A, const LittleVectorType &X) const
(*this) := (*this) + alpha * A * X (matrix-vector multiply).
void absmax(const LittleBlockType &X) const
(*this)(i,j) := max(abs((*this)(i,j)), abs(X(i,j))) for all (i,j).
Nonowning view of a square dense block in a block matrix.
void scale(const Scalar &alpha) const
(*this)(i,j) := alpha * (*this)(i,j) for all (i,j).
LO getStride() const
Stride between consecutive entries.
void assign(const LittleVectorType &X) const
*this := X.
LittleVector(T *const A, const LO blockSize, const LO stride, typename std::enable_if< !std::is_same< Scalar, T >::value &&std::is_convertible< Scalar, T >::value &&sizeof(Scalar)==sizeof(T), int * >::type ignoreMe=NULL)
Constructor that takes an impl_scalar_type pointer.
bool equal(const LittleVectorType &X) const
true if and only if all entries of this equal all entries of X.
Implementation details of Tpetra.
LittleBlock(Scalar *const A, const LO blockSize, const LO strideX, const LO strideY)
Constructor.
void update(const Scalar &alpha, const LittleBlockType &X) const
*this := *this + alpha * X.
Scalar * getRawPtr() const
Pointer to the block&#39;s entries.
Nonowning view of a set of degrees of freedom corresponding to a mesh point in a block vector or mult...
LO getBlockSize() const
The block size (number of rows, and number of columns).
void fill(const Scalar &alpha) const
(*this)(i,j) := alpha for all (i,j).
LittleVector(Scalar *const A, const LO blockSize, const LO stride)
Constructor.
LO getBlockSize() const
The block size (number of degrees of freedom per mesh point).
void update(const Scalar &alpha, const LittleVectorType &X) const
*this := *this + alpha * X.
void assign(const LittleBlockType &X) const
*this := X.
Return the Teuchos::LAPACK specialization corresponding to the given Scalar type. ...
LittleBlock(T *const A, const LO blockSize, const LO strideX, const LO strideY, typename std::enable_if< !std::is_same< Scalar, T >::value &&std::is_convertible< Scalar, T >::value &&sizeof(Scalar)==sizeof(T), int * >::type ignoreMe=NULL)
Constructor that takes an impl_scalar_type pointer.
void absmax(const LittleVectorType &X) const
(*this)(i,j) := max(abs((*this)(i,j)), abs(X(i,j))) for all (i,j).