Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_FlatSparse3Tensor_kji.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_FLAT_SPARSE_3_TENSOR_KJI_HPP
11 #define STOKHOS_FLAT_SPARSE_3_TENSOR_KJI_HPP
12 
13 #include "Kokkos_Core.hpp"
14 
15 #include "Stokhos_Multiply.hpp"
16 #include "Stokhos_ProductBasis.hpp"
19 
20 //----------------------------------------------------------------------------
21 //----------------------------------------------------------------------------
22 
23 namespace Stokhos {
24 
28 template< typename ValueType , class ExecutionSpace >
30 public:
31 
32  typedef ExecutionSpace execution_space ;
33  typedef typename execution_space::size_type size_type ;
34  typedef ValueType value_type ;
35 
36 private:
37 
38  typedef Kokkos::View< size_type[] , execution_space > coord_array_type ;
39  typedef Kokkos::View< value_type[], execution_space > value_array_type ;
40  typedef Kokkos::View< size_type[], execution_space > entry_array_type ;
41  typedef Kokkos::View< size_type[], execution_space > row_map_array_type ;
42 
53 
54 
55 public:
56 
57  inline
59 
60  inline
62  m_j_coord() ,
63  m_i_coord() ,
64  m_value() ,
65  m_num_j() ,
66  m_num_i() ,
67  m_j_row_map() ,
68  m_i_row_map() ,
69  m_nnz(0) ,
70  m_dim(0) ,
71  m_flops(0) {}
72 
73  inline
75  m_j_coord( rhs.m_j_coord ) ,
76  m_i_coord( rhs.m_i_coord ) ,
77  m_value( rhs.m_value ) ,
78  m_num_j( rhs.m_num_j ) ,
79  m_num_i( rhs.m_num_i ) ,
80  m_j_row_map( rhs.m_j_row_map ) ,
81  m_i_row_map( rhs.m_i_row_map ) ,
82  m_nnz( rhs.m_nnz ) ,
83  m_dim( rhs.m_dim ) ,
84  m_flops( rhs.m_flops ) {}
85 
86  inline
88  {
89  m_j_coord = rhs.m_j_coord ;
90  m_i_coord = rhs.m_i_coord ;
91  m_value = rhs.m_value ;
92  m_num_j = rhs.m_num_j ;
93  m_num_i = rhs.m_num_i ;
94  m_j_row_map = rhs.m_j_row_map ;
95  m_i_row_map = rhs.m_i_row_map ;
96  m_nnz = rhs.m_nnz;
97  m_dim = rhs.m_dim ;
98  m_flops = rhs.m_flops ;
99  return *this ;
100  }
101 
103  KOKKOS_INLINE_FUNCTION
104  size_type dimension() const { return m_dim ; }
105 
107  KOKKOS_INLINE_FUNCTION
108  size_type num_k() const { return m_j_row_map.extent(0) - 1 ; }
109 
111  KOKKOS_INLINE_FUNCTION
113  { return m_i_coord.extent(0); }
114 
116  KOKKOS_INLINE_FUNCTION
118  { return m_j_row_map[k]; }
119 
121  KOKKOS_INLINE_FUNCTION
123  { return m_j_row_map[k] + m_num_j(k); }
124 
126  KOKKOS_INLINE_FUNCTION
128  { return m_num_j(k); }
129 
131  KOKKOS_INLINE_FUNCTION
132  const size_type& j_coord( const size_type jEntry ) const
133  { return m_j_coord( jEntry ); }
134 
136  KOKKOS_INLINE_FUNCTION
137  size_type i_begin( size_type jEntry ) const
138  { return m_i_row_map[jEntry]; }
139 
141  KOKKOS_INLINE_FUNCTION
142  size_type i_end( size_type jEntry ) const
143  { return m_i_row_map[jEntry] + m_num_i(jEntry); }
144 
146  KOKKOS_INLINE_FUNCTION
147  size_type num_i( size_type jEntry ) const
148  { return m_num_i(jEntry); }
149 
151  KOKKOS_INLINE_FUNCTION
152  const size_type& i_coord( const size_type iEntry ) const
153  { return m_i_coord( iEntry ); }
154 
156  KOKKOS_INLINE_FUNCTION
157  const value_type & value( const size_type iEntry ) const
158  { return m_value( iEntry ); }
159 
161  KOKKOS_INLINE_FUNCTION
163  { return m_nnz; }
164 
166  KOKKOS_INLINE_FUNCTION
168  { return m_flops; }
169 
170  template <typename OrdinalType>
171  static FlatSparse3Tensor_kji
175  {
177 
178  // Compute number of j's for each k
179  const size_type dimension = basis.size();
180  const size_type nk = Cijk.num_k();
181  std::vector< size_t > j_coord_work( nk , (size_t) 0 );
182  size_type j_entry_count = 0 ;
183  for (typename Cijk_type::k_iterator k_it=Cijk.k_begin();
184  k_it!=Cijk.k_end(); ++k_it) {
185  OrdinalType k = index(k_it);
186  for (typename Cijk_type::kj_iterator j_it = Cijk.j_begin(k_it);
187  j_it != Cijk.j_end(k_it); ++j_it) {
188  OrdinalType j = index(j_it);
189  if (j >= k) {
190  ++j_coord_work[k];
191  ++j_entry_count;
192  }
193  }
194  }
195 
196  // Compute number of i's for each k and j
197  std::vector< size_t > i_coord_work( j_entry_count , (size_t) 0 );
198  size_type i_entry_count = 0 ;
199  size_type j_entry = 0 ;
200  for (typename Cijk_type::k_iterator k_it=Cijk.k_begin();
201  k_it!=Cijk.k_end(); ++k_it) {
202  OrdinalType k = index(k_it);
203  for (typename Cijk_type::kj_iterator j_it = Cijk.j_begin(k_it);
204  j_it != Cijk.j_end(k_it); ++j_it) {
205  OrdinalType j = index(j_it);
206  if (j >= k) {
207  for (typename Cijk_type::kji_iterator i_it = Cijk.i_begin(j_it);
208  i_it != Cijk.i_end(j_it); ++i_it) {
209  ++i_coord_work[j_entry];
210  ++i_entry_count;
211  }
212  ++j_entry;
213  }
214  }
215  }
216 
217  /*
218  // Pad each row to have size divisible by alignment size
219  enum { Align = std::is_same<ExecutionSpace,Kokkos::Cuda>::value ? 32 : 2 };
220  for ( size_type i = 0 ; i < dimension ; ++i ) {
221  const size_t rem = coord_work[i] % Align;
222  if (rem > 0) {
223  const size_t pad = Align - rem;
224  coord_work[i] += pad;
225  entry_count += pad;
226  }
227  }
228  */
229 
230  // Allocate tensor data
231  FlatSparse3Tensor_kji tensor ;
232  tensor.m_dim = dimension;
233  tensor.m_j_coord = coord_array_type( "j_coord" , j_entry_count );
234  tensor.m_i_coord = coord_array_type( "i_coord" , i_entry_count );
235  tensor.m_value = value_array_type( "value" , i_entry_count );
236  tensor.m_num_j = entry_array_type( "num_j" , nk );
237  tensor.m_num_i = entry_array_type( "num_i" , j_entry_count );
238  tensor.m_j_row_map = row_map_array_type( "j_row_map" , nk+1 );
239  tensor.m_i_row_map = row_map_array_type( "i_row_map" , j_entry_count+1 );
240  tensor.m_flops = 3*j_entry_count + 2*i_entry_count;
241 
242  // Create mirror, is a view if is host memory
243  typename coord_array_type::HostMirror
244  host_j_coord = Kokkos::create_mirror_view( tensor.m_j_coord );
245  typename coord_array_type::HostMirror
246  host_i_coord = Kokkos::create_mirror_view( tensor.m_i_coord );
247  typename value_array_type::HostMirror
248  host_value = Kokkos::create_mirror_view( tensor.m_value );
249  typename entry_array_type::HostMirror
250  host_num_j = Kokkos::create_mirror_view( tensor.m_num_j );
251  typename entry_array_type::HostMirror
252  host_num_i = Kokkos::create_mirror_view( tensor.m_num_i );
253  typename entry_array_type::HostMirror
254  host_j_row_map = Kokkos::create_mirror_view( tensor.m_j_row_map );
255  typename entry_array_type::HostMirror
256  host_i_row_map = Kokkos::create_mirror_view( tensor.m_i_row_map );
257 
258  // Compute j row map
259  size_type sum = 0;
260  host_j_row_map(0) = 0;
261  for ( size_type k = 0 ; k < nk ; ++k ) {
262  sum += j_coord_work[k];
263  host_j_row_map(k+1) = sum;
264  host_num_j(k) = 0;
265  }
266 
267  // Compute i row map
268  sum = 0;
269  host_i_row_map(0) = 0;
270  for ( size_type j = 0 ; j < j_entry_count ; ++j ) {
271  sum += i_coord_work[j];
272  host_i_row_map(j+1) = sum;
273  host_num_i(j) = 0;
274  }
275 
276  for ( size_type k = 0 ; k < nk ; ++k ) {
277  j_coord_work[k] = host_j_row_map[k];
278  }
279  for ( size_type j = 0 ; j < j_entry_count ; ++j ) {
280  i_coord_work[j] = host_i_row_map[j];
281  }
282 
283  for (typename Cijk_type::k_iterator k_it=Cijk.k_begin();
284  k_it!=Cijk.k_end(); ++k_it) {
285  OrdinalType k = index(k_it);
286  for (typename Cijk_type::kj_iterator j_it = Cijk.j_begin(k_it);
287  j_it != Cijk.j_end(k_it); ++j_it) {
288  OrdinalType j = index(j_it);
289  if (j >= k) {
290  const size_type jEntry = j_coord_work[k];
291  ++j_coord_work[k];
292  host_j_coord(jEntry) = j ;
293  ++host_num_j(k);
294  for (typename Cijk_type::kji_iterator i_it = Cijk.i_begin(j_it);
295  i_it != Cijk.i_end(j_it); ++i_it) {
296  OrdinalType i = index(i_it);
297  ValueType c = Stokhos::value(i_it);
298  const size_type iEntry = i_coord_work[jEntry];
299  ++i_coord_work[jEntry];
300  host_value(iEntry) = (j != k) ? c : 0.5*c;
301  host_i_coord(iEntry) = i ;
302  ++host_num_i(jEntry);
303  ++tensor.m_nnz;
304  }
305  }
306  }
307  }
308 
309  // Copy data to device if necessary
310  Kokkos::deep_copy( tensor.m_j_coord , host_j_coord );
311  Kokkos::deep_copy( tensor.m_i_coord , host_i_coord );
312  Kokkos::deep_copy( tensor.m_value , host_value );
313  Kokkos::deep_copy( tensor.m_num_j , host_num_j );
314  Kokkos::deep_copy( tensor.m_num_i , host_num_i );
315  Kokkos::deep_copy( tensor.m_j_row_map , host_j_row_map );
316  Kokkos::deep_copy( tensor.m_i_row_map , host_i_row_map );
317 
318  return tensor ;
319  }
320 };
321 
322 template< class Device , typename OrdinalType , typename ValueType >
323 FlatSparse3Tensor_kji<ValueType, Device>
328 {
330  basis, Cijk, params );
331 }
332 
333 template < typename ValueType, typename Device >
334 class BlockMultiply< FlatSparse3Tensor_kji< ValueType , Device > >
335 {
336 public:
337 
338  typedef typename Device::size_type size_type ;
340 
341  template< typename MatrixValue , typename VectorValue >
342  KOKKOS_INLINE_FUNCTION
343  static void apply( const tensor_type & tensor ,
344  const MatrixValue * const a ,
345  const VectorValue * const x ,
346  VectorValue * const y )
347  {
348  const size_type nk = tensor.num_k();
349 
350  // Loop over k
351  for ( size_type k = 0; k < nk; ++k) {
352  const MatrixValue ak = a[k];
353  const VectorValue xk = x[k];
354 
355  // Loop over j for this k
356  const size_type nj = tensor.num_j(k);
357  const size_type jBeg = tensor.j_begin(k);
358  const size_type jEnd = jBeg + nj;
359  for (size_type jEntry = jBeg; jEntry < jEnd; ++jEntry) {
360  const size_type j = tensor.j_coord(jEntry);
361  VectorValue tmp = a[j] * xk + ak * x[j];
362 
363  // Loop over i for this k,j
364  const size_type ni = tensor.num_i(jEntry);
365  const size_type iBeg = tensor.i_begin(jEntry);
366  const size_type iEnd = iBeg + ni;
367  for (size_type iEntry = iBeg; iEntry < iEnd; ++iEntry) {
368  const size_type i = tensor.i_coord(iEntry);
369  y[i] += tensor.value(iEntry) * tmp;
370  }
371  }
372  }
373  }
374 
375  KOKKOS_INLINE_FUNCTION
376  static size_type matrix_size( const tensor_type & tensor )
377  { return tensor.dimension(); }
378 
379  KOKKOS_INLINE_FUNCTION
380  static size_type vector_size( const tensor_type & tensor )
381  { return tensor.dimension(); }
382 };
383 
384 } /* namespace Stokhos */
385 
386 //----------------------------------------------------------------------------
387 //----------------------------------------------------------------------------
388 
389 #endif /* #ifndef STOKHOS_FLAT_SPARSE_3_TENSOR_KJI_HPP */
static KOKKOS_INLINE_FUNCTION size_type matrix_size(const tensor_type &tensor)
KOKKOS_INLINE_FUNCTION const size_type & i_coord(const size_type iEntry) const
i coordinate for i entry &#39;iEntry&#39;
k_iterator k_begin() const
Iterator pointing to first k entry.
static KOKKOS_INLINE_FUNCTION size_type vector_size(const tensor_type &tensor)
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
KOKKOS_INLINE_FUNCTION size_type i_end(size_type jEntry) const
End i entries with a j entry &#39;jEntry&#39;.
Kokkos::View< size_type[], execution_space > coord_array_type
ordinal_type num_k() const
Number of k entries in C(i,j,k)
kj_iterator j_begin(const k_iterator &k) const
Iterator pointing to first j entry for given k.
Kokkos::View< value_type[], execution_space > value_array_type
FlatSparse3Tensor_kji< ValueType, Device > create_flat_sparse_3_tensor_kji(const Stokhos::ProductBasis< OrdinalType, ValueType > &basis, const Stokhos::Sparse3Tensor< OrdinalType, ValueType > &Cijk, const Teuchos::ParameterList &params=Teuchos::ParameterList())
FlatSparse3Tensor_kji(const FlatSparse3Tensor_kji &rhs)
KOKKOS_INLINE_FUNCTION size_type num_flops() const
Number flop&#39;s per multiply-add.
kj_iterator j_end(const k_iterator &k) const
Iterator pointing to last j entry for given k.
Kokkos::View< size_type[], execution_space > row_map_array_type
KOKKOS_INLINE_FUNCTION const size_type & j_coord(const size_type jEntry) const
j coordinate for j entry &#39;jEntry&#39;
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
KOKKOS_INLINE_FUNCTION size_type num_j(size_type k) const
Number of j entries with a coordinate &#39;k&#39;.
KOKKOS_INLINE_FUNCTION size_type i_begin(size_type jEntry) const
Begin i entries with a j entry &#39;jEntry&#39;.
KOKKOS_INLINE_FUNCTION size_type num_k() const
Number of k entries.
KOKKOS_INLINE_FUNCTION size_type num_i(size_type jEntry) const
Number of i entries with a j entry &#39;jEntry&#39;.
KOKKOS_INLINE_FUNCTION size_type dimension() const
Dimension of the tensor.
KOKKOS_INLINE_FUNCTION const value_type & value(const size_type iEntry) const
Value for i entry &#39;iEntry&#39;.
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
KOKKOS_INLINE_FUNCTION size_type j_begin(size_type k) const
Begin j entries with a coordinate &#39;k&#39;.
k_iterator k_end() const
Iterator pointing to last k entry.
static KOKKOS_INLINE_FUNCTION void apply(const tensor_type &tensor, const MatrixValue *const a, const VectorValue *const x, VectorValue *const y)
Stokhos::Sparse3Tensor< int, double > Cijk_type
Kokkos::View< size_type[], execution_space > entry_array_type
static FlatSparse3Tensor_kji create(const Stokhos::ProductBasis< OrdinalType, ValueType > &basis, const Stokhos::Sparse3Tensor< OrdinalType, ValueType > &Cijk, const Teuchos::ParameterList &params=Teuchos::ParameterList())
FlatSparse3Tensor_kji & operator=(const FlatSparse3Tensor_kji &rhs)
kji_iterator i_begin(const kj_iterator &j) const
Iterator pointing to first i entry for given j and k.
kji_iterator i_end(const kj_iterator &j) const
Iterator pointing to last i entry for given j and k.
KOKKOS_INLINE_FUNCTION size_type j_end(size_type k) const
End j entries with a coordinate &#39;k&#39;.
std::enable_if< Kokkos::is_view_uq_pce< Kokkos::View< RD, RP...> >::value &&Kokkos::is_view_uq_pce< Kokkos::View< XD, XP...> >::value >::type sum(const Kokkos::View< RD, RP...> &r, const Kokkos::View< XD, XP...> &x)
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)
KOKKOS_INLINE_FUNCTION size_type num_non_zeros() const
Number of non-zero&#39;s.
KOKKOS_INLINE_FUNCTION size_type entry_count() const
Number of sparse entries.