Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_LinearSparse3Tensor.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Stokhos Package
4 //
5 // Copyright 2009 NTESS and the Stokhos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef STOKHOS_LINEAR_SPARSE_3_TENSOR_HPP
11 #define STOKHOS_LINEAR_SPARSE_3_TENSOR_HPP
12 
13 #include "Kokkos_Core.hpp"
14 
15 #include "Stokhos_Multiply.hpp"
16 #include "Stokhos_ProductBasis.hpp"
19 #include "Stokhos_TinyVec.hpp"
20 
21 //----------------------------------------------------------------------------
22 //----------------------------------------------------------------------------
23 
24 namespace Stokhos {
25 
29 template< typename ValueType , class ExecutionSpace , int BlockSize >
31 public:
32 
33  typedef ExecutionSpace execution_space ;
34  typedef typename execution_space::size_type size_type ;
35  typedef ValueType value_type ;
36 
37  static const int block_size = BlockSize;
38 
39 private:
40 
41  typedef Kokkos::View< value_type[], execution_space > value_array_type ;
42 
48  bool m_symmetric ;
49 
50 public:
51 
52  inline
54 
55  inline
57  m_value() ,
58  m_dim() ,
59  m_aligned_dim(),
60  m_nnz(0) ,
61  m_flops(0) ,
62  m_symmetric(false) {}
63 
64  inline
66  m_value( rhs.m_value ) ,
67  m_dim( rhs.m_dim ),
69  m_nnz( rhs.m_nnz ) ,
70  m_flops( rhs.m_flops ) ,
71  m_symmetric( rhs.m_symmetric ) {}
72 
73  inline
75  {
76  m_value = rhs.m_value ;
77  m_dim = rhs.m_dim ;
79  m_nnz = rhs.m_nnz;
80  m_flops = rhs.m_flops;
82  return *this ;
83  }
84 
86  KOKKOS_INLINE_FUNCTION
87  size_type dimension() const { return m_dim ; }
88 
90  KOKKOS_INLINE_FUNCTION
92 
94  KOKKOS_INLINE_FUNCTION
96  { return m_value.extent(0); }
97 
99  KOKKOS_INLINE_FUNCTION
100  bool symmetric() const
101  { return m_symmetric; }
102 
104  KOKKOS_INLINE_FUNCTION
105  const value_type & value( const size_type entry ) const
106  { return m_value( entry ); }
107 
109  KOKKOS_INLINE_FUNCTION
111  { return m_nnz; }
112 
114  KOKKOS_INLINE_FUNCTION
116  { return m_flops; }
117 
118  template <typename OrdinalType>
119  static LinearSparse3Tensor
122  const Teuchos::ParameterList& params)
123  {
124  const bool symmetric = params.get<bool>("Symmetric");
125 
126  // Allocate tensor data -- currently assuming isotropic
127  const size_type dim = basis.size();
128  LinearSparse3Tensor tensor ;
129  tensor.m_dim = dim;
130  tensor.m_aligned_dim = dim;
131  if (tensor.m_aligned_dim % block_size)
132  tensor.m_aligned_dim += block_size - tensor.m_aligned_dim % block_size;
133  tensor.m_symmetric = symmetric;
134  tensor.m_nnz = symmetric ? 2 : 3 ;
135  tensor.m_value = value_array_type( "value" , tensor.m_nnz );
136 
137  // Create mirror, is a view if is host memory
138  typename value_array_type::HostMirror
139  host_value = Kokkos::create_mirror_view( tensor.m_value );
140 
141  // Get Cijk values
144  bases[0]->computeTripleProductTensor();
145  // For non-isotropic, need to take products of these over basis components
146  host_value(0) = (*cijk)(0,0,0);
147  host_value(1) = (*cijk)(0,1,1);
148  if (!symmetric)
149  host_value(2) = (*cijk)(1,1,1);
150 
151  // Copy data to device if necessary
152  Kokkos::deep_copy( tensor.m_value , host_value );
153 
154  tensor.m_flops = 8*dim;
155  if (!symmetric)
156  tensor.m_flops += 2*dim ;
157 
158  return tensor ;
159  }
160 };
161 
162 template< class Device , typename OrdinalType , typename ValueType , int BlockSize >
163 LinearSparse3Tensor<ValueType, Device,BlockSize>
167  const Teuchos::ParameterList& params)
168 {
170  basis, Cijk, params );
171 }
172 
173 template < typename ValueType, typename Device, int BlockSize >
174 class BlockMultiply< LinearSparse3Tensor< ValueType , Device , BlockSize > >
175 {
176 public:
177 
178  typedef typename Device::size_type size_type ;
180 
181  template< typename MatrixValue , typename VectorValue >
182  KOKKOS_INLINE_FUNCTION
183  static void apply( const tensor_type & tensor ,
184  const MatrixValue * const a ,
185  const VectorValue * const x ,
186  VectorValue * const y )
187  {
188  const size_type block_size = tensor_type::block_size;
190  const size_type dim = tensor.dimension();
191 
192  const ValueType c0 = tensor.value(0);
193  const ValueType c1 = tensor.value(1);
194  const ValueType a0 = a[0];
195  const ValueType x0 = x[0];
196 
197  if (block_size > 1) {
198 
199  TV vc0(c0), vc1(c1), va0(a0), vx0(x0), vy0;
200  TV ai, ai2, xi, yi;
201 
202  const MatrixValue *aa = a;
203  const VectorValue *xx = x;
204  VectorValue *yy = y;
205  vy0.zero();
206 
207  const size_type nBlock = dim / block_size;
208  const size_type iEnd = nBlock * block_size;
209 
210  if (tensor.symmetric()) {
211 
212  size_type i=0;
213  for ( ; i < iEnd; i+=block_size,aa+=block_size,xx+=block_size,yy+=block_size) {
214  ai.aligned_load(aa);
215  ai2 = ai;
216  xi.aligned_load(xx);
217  yi.aligned_load(yy);
218 
219  // y[i] += c1*(a0*xi + ai*x0);
220  ai.times_equal(vx0);
221  ai2.times_equal(xi);
222  xi.times_equal(va0);
223  xi.plus_equal(ai);
224  xi.times_equal(vc1);
225  yi.plus_equal(xi);
226  yi.aligned_scatter(yy);
227 
228  // y0 += c1*ai*xi;
229  ai2.times_equal(vc1);
230  vy0.plus_equal(ai2);
231  }
232  ValueType y0 = vy0.sum();
233 
234  // Do remaining entries with a scalar loop
235  for ( ; i < dim; ++i) {
236  const ValueType ai = *aa++;
237  const ValueType xi = *xx++;
238  *yy++ += c1*(a0*xi + ai*x0);
239  y0 += c1*ai*xi;
240  }
241  y[0] += y0 + (c0-3.0*c1)*a0*x0;
242  }
243  else {
244 
245  const ValueType c2 = tensor.value(2);
246  TV vc2(c2);
247  size_type i=0;
248  for ( ; i < iEnd; i+=block_size,aa+=block_size,xx+=block_size,yy+=block_size) {
249  ai.aligned_load(aa);
250  ai2 = ai;
251  xi.aligned_load(xx);
252  yi.aligned_load(yy);
253 
254  // y[i] += c1*(a0*xi + ai*x0) + c2*aixi;
255  ai.times_equal(vx0);
256  ai2.times_equal(xi);
257  xi.times_equal(va0);
258  xi.plus_equal(ai);
259  xi.times_equal(vc1);
260  yi.plus_equal(xi);
261  ai = ai2;
262  ai.times_equal(vc2);
263  yi.plus_equal(ai);
264  yi.aligned_scatter(yy);
265 
266  // y0 += c1*aixi;
267  ai2.times_equal(vc1);
268  vy0.plus_equal(ai2);
269  }
270  ValueType y0 = vy0.sum();
271 
272  // Do remaining entries with a scalar loop
273  for ( ; i < dim; ++i) {
274  const ValueType ai = *aa++;
275  const ValueType xi = *xx++;
276  const ValueType aixi = ai*xi;
277  *yy++ += c1*(a0*xi + ai*x0) + c2*aixi;
278  y0 += c1*aixi;
279  }
280  y[0] += y0 + (c0-3.0*c1-c2)*a0*x0;
281 
282  }
283 
284  }
285 
286  else {
287 
288  ValueType y0 = c0*a0*x0;
289 
290  if (tensor.symmetric()) {
291 
292  for ( size_type i = 1; i < dim; ++i) {
293  const ValueType ai = a[i];
294  const ValueType xi = x[i];
295  y[i] += c1*(a0*xi + ai*x0);
296  y0 += c1*ai*xi;
297  }
298  y[0] += y0;
299 
300  }
301  else {
302 
303  const ValueType c2 = tensor.value(2);
304  for ( size_type i = 1; i < dim; ++i) {
305  const ValueType ai = a[i];
306  const ValueType xi = x[i];
307  const ValueType aixi = ai*xi;
308  y[i] += c1*(a0*xi + ai*x0) + c2*aixi;
309  y0 += c1*aixi;
310  }
311  y[0] += y0;
312 
313  }
314 
315  }
316 
317  }
318 
319  KOKKOS_INLINE_FUNCTION
320  static size_type matrix_size( const tensor_type & tensor )
321  { return tensor.dimension(); }
322 
323  KOKKOS_INLINE_FUNCTION
324  static size_type vector_size( const tensor_type & tensor )
325  { return tensor.dimension(); }
326 };
327 
328 } /* namespace Stokhos */
329 
330 //----------------------------------------------------------------------------
331 //----------------------------------------------------------------------------
332 
333 #endif /* #ifndef STOKHOS_LINEAR_SPARSE_3_TENSOR_HPP */
KOKKOS_INLINE_FUNCTION size_type entry_count() const
Number of sparse entries.
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
T & get(ParameterList &l, const std::string &name)
static LinearSparse3Tensor create(const Stokhos::ProductBasis< OrdinalType, ValueType > &basis, const Stokhos::Sparse3Tensor< OrdinalType, ValueType > &Cijk, const Teuchos::ParameterList &params)
KOKKOS_INLINE_FUNCTION size_type num_non_zeros() const
Number of non-zero&#39;s.
Kokkos::View< value_type[], execution_space > value_array_type
static KOKKOS_INLINE_FUNCTION size_type matrix_size(const tensor_type &tensor)
KOKKOS_INLINE_FUNCTION size_type dimension() const
Dimension of the tensor.
KOKKOS_INLINE_FUNCTION bool symmetric() const
Is tensor built from symmetric PDFs.
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
static KOKKOS_INLINE_FUNCTION void apply(const tensor_type &tensor, const MatrixValue *const a, const VectorValue *const x, VectorValue *const y)
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
LinearSparse3Tensor & operator=(const LinearSparse3Tensor &rhs)
virtual Teuchos::Array< Teuchos::RCP< const OneDOrthogPolyBasis< ordinal_type, value_type > > > getCoordinateBases() const =0
Return array of coordinate bases.
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< is_view_uq_pce< view_type >::value, typename CijkType< view_type >::type >::type cijk(const view_type &view)
KOKKOS_INLINE_FUNCTION size_type aligned_dimension() const
Dimension of the tensor.
LinearSparse3Tensor(const LinearSparse3Tensor &rhs)
KOKKOS_INLINE_FUNCTION const value_type & value(const size_type entry) const
Value for entry &#39;entry&#39;.
KOKKOS_INLINE_FUNCTION size_type num_flops() const
Number flop&#39;s per multiply-add.
static KOKKOS_INLINE_FUNCTION size_type vector_size(const tensor_type &tensor)
LinearSparse3Tensor< ValueType, Device, BlockSize > create_linear_sparse_3_tensor(const Stokhos::ProductBasis< OrdinalType, ValueType > &basis, const Stokhos::Sparse3Tensor< OrdinalType, ValueType > &Cijk, const Teuchos::ParameterList &params)
virtual ordinal_type size() const =0
Return total size of basis.
Stokhos::CrsMatrix< ValueType, Device, Layout >::HostMirror create_mirror_view(const Stokhos::CrsMatrix< ValueType, Device, Layout > &A)