Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_KokkosCrsMatrixUQPCEUnitTest.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 
12 
14 #include "KokkosSparse_CrsMatrix.hpp"
15 #include "KokkosSparse_spmv.hpp"
21 
22 // For computing DeviceConfig
23 #include "Kokkos_Core.hpp"
24 
25 // Helper functions
26 template< typename IntType >
27 inline
28 IntType map_fem_graph_coord( const IntType& N,
29  const IntType& i,
30  const IntType& j,
31  const IntType& k )
32 {
33  return k + N * ( j + N * i );
34 }
35 
36 template < typename ordinal >
37 inline
38 ordinal generate_fem_graph( ordinal N,
39  std::vector< std::vector<ordinal> >& graph )
40 {
41  graph.resize( N * N * N, std::vector<ordinal>() );
42 
43  ordinal total = 0;
44 
45  for ( int i = 0; i < (int) N; ++i ) {
46  for ( int j = 0; j < (int) N; ++j ) {
47  for ( int k = 0; k < (int) N; ++k ) {
48 
49  const ordinal row = map_fem_graph_coord((int)N,i,j,k);
50 
51  graph[row].reserve(27);
52 
53  for ( int ii = -1; ii < 2; ++ii ) {
54  for ( int jj = -1; jj < 2; ++jj ) {
55  for ( int kk = -1; kk < 2; ++kk ) {
56  if ( 0 <= i + ii && i + ii < (int) N &&
57  0 <= j + jj && j + jj < (int) N &&
58  0 <= k + kk && k + kk < (int) N ) {
59  ordinal col = map_fem_graph_coord((int)N,i+ii,j+jj,k+kk);
60 
61  graph[row].push_back(col);
62  }
63  }}}
64  total += graph[row].size();
65  }}}
66 
67  return total;
68 }
69 
70 template <typename scalar, typename ordinal>
71 inline
72 scalar generate_matrix_coefficient( const ordinal nFEM,
73  const ordinal nStoch,
74  const ordinal iRowFEM,
75  const ordinal iColFEM,
76  const ordinal iStoch )
77 {
78  const scalar A_fem = ( 10.0 + scalar(iRowFEM) / scalar(nFEM) ) +
79  ( 5.0 + scalar(iColFEM) / scalar(nFEM) );
80 
81  const scalar A_stoch = ( 1.0 + scalar(iStoch) / scalar(nStoch) );
82 
83  return A_fem + A_stoch;
84  //return 1.0;
85 }
86 
87 template <typename scalar, typename ordinal>
88 inline
89 scalar generate_vector_coefficient( const ordinal nFEM,
90  const ordinal nStoch,
91  const ordinal iColFEM,
92  const ordinal iStoch )
93 {
94  const scalar X_fem = 100.0 + scalar(iColFEM) / scalar(nFEM);
95  const scalar X_stoch = 1.0 + scalar(iStoch) / scalar(nStoch);
96  return X_fem + X_stoch;
97  //return 1.0;
98 }
99 
100 template <typename kokkos_cijk_type, typename ordinal_type>
103 {
104  using Teuchos::RCP;
105  using Teuchos::rcp;
106  using Teuchos::Array;
107 
108  typedef typename kokkos_cijk_type::value_type value_type;
114 
115  // Create product basis
116  Array< RCP<const one_d_basis> > bases(stoch_dim);
117  for (ordinal_type i=0; i<stoch_dim; i++)
118  bases[i] = rcp(new legendre_basis(poly_ord, true));
119  RCP<const product_basis> basis = rcp(new product_basis(bases));
120 
121  // Triple product tensor
122  RCP<Cijk> cijk = basis->computeTripleProductTensor();
123 
124  // Kokkos triple product tensor
125  kokkos_cijk_type kokkos_cijk =
126  Stokhos::create_product_tensor<execution_space>(*basis, *cijk);
127 
128  return kokkos_cijk;
129 }
130 
131 // Reasonable tolerances for common precisions
132 template <typename Scalar> struct ScalarTol {};
133 template <> struct ScalarTol<float> { static float tol() { return 1e-4; } };
134 template <> struct ScalarTol<double> { static double tol() { return 1e-10; } };
135 
136 // Compare two rank-2 views for equality, to given precision
137 template <typename array_type, typename scalar_type>
138 bool compare_rank_2_views(const array_type& y,
139  const array_type& y_exp,
140  const scalar_type rel_tol,
141  const scalar_type abs_tol,
143 {
144  typedef typename array_type::size_type size_type;
145  typename array_type::HostMirror hy = Kokkos::create_mirror_view(y);
146  typename array_type::HostMirror hy_exp = Kokkos::create_mirror_view(y_exp);
147  Kokkos::deep_copy(hy, y);
148  Kokkos::deep_copy(hy_exp, y_exp);
149 
150  size_type num_rows = y.extent(0);
151  size_type num_cols = y.extent(1);
152  bool success = true;
153  for (size_type i=0; i<num_rows; ++i) {
154  for (size_type j=0; j<num_cols; ++j) {
155  scalar_type diff = std::abs( hy(i,j) - hy_exp(i,j) );
156  scalar_type tol = rel_tol*std::abs(hy_exp(i,j)) + abs_tol;
157  bool s = diff < tol;
158  out << "y_expected(" << i << "," << j << ") - "
159  << "y(" << i << "," << j << ") = " << hy_exp(i,j)
160  << " - " << hy(i,j) << " == "
161  << diff << " < " << tol << " : ";
162  if (s)
163  out << "passed";
164  else
165  out << "failed";
166  out << std::endl;
167  success = success && s;
168  }
169  }
170 
171  return success;
172 }
173 
174 template <typename vector_type, typename scalar_type>
175 bool compareRank1(const vector_type& y,
176  const vector_type& y_exp,
177  const scalar_type rel_tol,
178  const scalar_type abs_tol,
180 {
181  typedef typename vector_type::size_type size_type;
182  typename vector_type::HostMirror hy = Kokkos::create_mirror_view(y);
183  typename vector_type::HostMirror hy_exp = Kokkos::create_mirror_view(y_exp);
184  Kokkos::deep_copy(hy, y);
185  Kokkos::deep_copy(hy_exp, y_exp);
186 
187  size_type num_rows = y.extent(0);
188  bool success = true;
189  for (size_type i=0; i<num_rows; ++i) {
190  for (size_type j=0; j<Kokkos::dimension_scalar(y); ++j) {
191  scalar_type diff = std::abs( hy(i).fastAccessCoeff(j) - hy_exp(i).fastAccessCoeff(j) );
192  scalar_type tol = rel_tol*std::abs(hy_exp(i).fastAccessCoeff(j)) + abs_tol;
193  bool s = diff < tol;
194  out << "y_expected(" << i << ").coeff(" << j << ") - "
195  << "y(" << i << ").coeff(" << j << ") = " << hy_exp(i).fastAccessCoeff(j)
196  << " - " << hy(i).fastAccessCoeff(j) << " == "
197  << diff << " < " << tol << " : ";
198  if (s)
199  out << "passed";
200  else
201  out << "failed";
202  out << std::endl;
203  success = success && s;
204  }
205  }
206  return success;
207 }
208 
209 template <typename vector_type, typename scalar_type>
210 bool compareRank2(const vector_type& y,
211  const vector_type& y_exp,
212  const scalar_type rel_tol,
213  const scalar_type abs_tol,
215 {
216  typedef typename vector_type::size_type size_type;
217  typename vector_type::HostMirror hy = Kokkos::create_mirror_view(y);
218  typename vector_type::HostMirror hy_exp = Kokkos::create_mirror_view(y_exp);
219  Kokkos::deep_copy(hy, y);
220  Kokkos::deep_copy(hy_exp, y_exp);
221 
222  size_type num_rows = y.extent(0);
223  size_type num_cols = y.extent(1);
224  bool success = true;
225 
226  for (size_type col = 0; col < num_cols; ++col){
227  for (size_type i=0; i<num_rows; ++i) {
228  for (size_type j=0; j<Kokkos::dimension_scalar(y); ++j) {
229  scalar_type diff = std::abs( hy(i,col).fastAccessCoeff(j) - hy_exp(i,col).fastAccessCoeff(j) );
230  scalar_type tol = rel_tol*std::abs(hy_exp(i,col).fastAccessCoeff(j)) + abs_tol;
231  bool s = diff < tol;
232  out << "y_expected(" << i << ").coeff(" << j << ") - "
233  << "y(" << i << ").coeff(" << j << ") = " << hy_exp(i,col).fastAccessCoeff(j)
234  << " - " << hy(i,col).fastAccessCoeff(j) << " == "
235  << diff << " < " << tol << " : ";
236  if (s)
237  out << "passed";
238  else
239  out << "failed";
240  out << std::endl;
241  success = success && s;
242  }
243  }
244  }
245 
246 
247  return success;
248 }
249 
250 
251 // Helper function to build a diagonal matrix
252 template <typename MatrixType, typename CijkType>
253 MatrixType
255  typename MatrixType::ordinal_type pce_size,
256  const CijkType& cijk) {
257  typedef typename MatrixType::ordinal_type ordinal_type;
258  typedef typename MatrixType::StaticCrsGraphType matrix_graph_type;
259  typedef typename MatrixType::values_type matrix_values_type;
260 
261  std::vector< std::vector<ordinal_type> > graph(nrow);
262  for (ordinal_type i=0; i<nrow; ++i)
263  graph[i] = std::vector<ordinal_type>(1, i);
264  ordinal_type graph_length = nrow;
265 
266  matrix_graph_type matrix_graph =
267  Kokkos::create_staticcrsgraph<matrix_graph_type>("graph", graph);
268  matrix_values_type matrix_values =
269  Kokkos::make_view<matrix_values_type>("values", cijk, graph_length, pce_size);
270 
271  MatrixType matrix("matrix", nrow, matrix_values, matrix_graph);
272  return matrix;
273 }
274 
275 //
276 // Tests
277 //
278 
279 // Kernel to set diagonal of a matrix to prescribed values
280 template <typename MatrixType>
283  typedef typename MatrixType::size_type size_type;
286 
287  const MatrixType m_matrix;
288  ReplaceDiagonalValuesKernel(const MatrixType matrix) : m_matrix(matrix) {};
289 
290  // Replace diagonal entry for row 'i' with a value
291  KOKKOS_INLINE_FUNCTION
292  void operator() (const size_type i) const {
293  const ordinal_type row = i;
294  const ordinal_type col = i;
295  value_type val = value_type(row);
296  m_matrix.replaceValues(row, &col, 1, &val, false, true);
297  }
298 
299  // Kernel launch
300  static void apply(const MatrixType matrix) {
301  const size_type nrow = matrix.numRows();
302  Kokkos::parallel_for( nrow, ReplaceDiagonalValuesKernel(matrix) );
303  }
304 
305  // Check the result is as expected
306  static bool check(const MatrixType matrix,
307  Teuchos::FancyOStream& out) {
308  typedef typename MatrixType::values_type matrix_values_type;
309  typename matrix_values_type::HostMirror host_matrix_values =
310  Kokkos::create_mirror_view(matrix.values);
311  Kokkos::deep_copy(host_matrix_values, matrix.values);
312  const ordinal_type nrow = matrix.numRows();
313  bool success = true;
314  value_type val_expected(Kokkos::cijk(matrix.values));
315  for (ordinal_type row=0; row<nrow; ++row) {
316  val_expected = row;
317  bool s = compareVecs(host_matrix_values(row),
318  "matrix_values(row)",
319  val_expected,
320  "val_expected",
321  0.0, 0.0, out);
322  success = success && s;
323  }
324  return success;
325  }
326 };
327 
328 // Kernel to add values to the diagonal of a matrix
329 template <typename MatrixType>
332  typedef typename MatrixType::size_type size_type;
335 
336  const MatrixType m_matrix;
337  AddDiagonalValuesKernel(const MatrixType matrix) : m_matrix(matrix) {};
338 
339  // Replace diagonal entry for row 'i' with a value
340  KOKKOS_INLINE_FUNCTION
341  void operator() (const size_type i) const {
342  const ordinal_type row = i;
343  const ordinal_type col = i;
344  value_type val = value_type(row);
345  m_matrix.sumIntoValues(row, &col, 1, &val, false, true);
346  }
347 
348  // Kernel launch
349  static void apply(const MatrixType matrix) {
350  const size_type nrow = matrix.numRows();
351  Kokkos::parallel_for( nrow, AddDiagonalValuesKernel(matrix) );
352  }
353 
354  // Check the result is as expected
355  static bool check(const MatrixType matrix,
356  Teuchos::FancyOStream& out) {
357  typedef typename MatrixType::values_type matrix_values_type;
358  typename matrix_values_type::HostMirror host_matrix_values =
359  Kokkos::create_mirror_view(matrix.values);
360  Kokkos::deep_copy(host_matrix_values, matrix.values);
361  const ordinal_type nrow = matrix.numRows();
362  bool success = true;
363  value_type val_expected(Kokkos::cijk(matrix.values));
364  for (ordinal_type row=0; row<nrow; ++row) {
365  val_expected = row;
366  bool s = compareVecs(host_matrix_values(row),
367  "matrix_values(row)",
368  val_expected,
369  "val_expected",
370  0.0, 0.0, out);
371  success = success && s;
372  }
373  return success;
374  }
375 };
376 
377 // Kernel to add values to the diagonal of a matrix where each thread
378 // adds to the same row (checks atomic really works)
379 template <typename MatrixType>
382  typedef typename MatrixType::size_type size_type;
385 
386  const MatrixType m_matrix;
387  AddDiagonalValuesAtomicKernel(const MatrixType matrix) : m_matrix(matrix) {};
388 
389  // Replace diagonal entry for row 'i' with a value
390  KOKKOS_INLINE_FUNCTION
391  void operator() (const size_type i) const {
392  const ordinal_type row = 0;
393  const ordinal_type col = 0;
395  m_matrix.sumIntoValues(row, &col, 1, &val, false, true);
396  }
397 
398  // Kernel launch
399  static void apply(const MatrixType matrix) {
400  const size_type nrow = matrix.numRows();
401  Kokkos::parallel_for( nrow, AddDiagonalValuesAtomicKernel(matrix) );
402  }
403 
404  // Check the result is as expected
405  static bool check(const MatrixType matrix,
406  Teuchos::FancyOStream& out) {
407  typedef typename MatrixType::values_type matrix_values_type;
408  typename matrix_values_type::HostMirror host_matrix_values =
409  Kokkos::create_mirror_view(matrix.values);
410  Kokkos::deep_copy(host_matrix_values, matrix.values);
411  const ordinal_type nrow = matrix.numRows();
412  bool success = true;
413  value_type val_expected(Kokkos::cijk(matrix.values));
414  for (ordinal_type row=0; row<nrow; ++row) {
415  value_type val;
416  if (row == 0)
417  val_expected = nrow*(nrow-1)/2;
418  else
419  val_expected = 0.0;
420  bool s = compareVecs(host_matrix_values(row),
421  "matrix_values(row)",
422  val_expected,
423  "val_expected",
424  0.0, 0.0, out);
425  success = success && s;
426  }
427  return success;
428  }
429 };
430 
432  Kokkos_CrsMatrix_PCE, ReplaceValues, MatrixScalar )
433 {
434  typedef typename MatrixScalar::ordinal_type Ordinal;
435  typedef typename MatrixScalar::execution_space Device;
436  typedef typename MatrixScalar::cijk_type Cijk;
437  typedef KokkosSparse::CrsMatrix<MatrixScalar,Ordinal,Device> Matrix;
438 
439  // Build Cijk tensor
440  const Ordinal stoch_dim = 2;
441  const Ordinal poly_ord = 3;
442  Cijk cijk = build_cijk<Cijk>(stoch_dim, poly_ord);
443 
444  // Build diagonal matrix
445  const Ordinal nrow = 10;
446  const Ordinal pce_size = cijk.dimension();
447  Matrix matrix = buildDiagonalMatrix<Matrix>(nrow, pce_size, cijk);
448 
449  // Launch our kernel
451  kernel::apply(matrix);
452 
453  // Check the result
454  success = kernel::check(matrix, out);
455 }
456 
458  Kokkos_CrsMatrix_PCE, SumIntoValues, MatrixScalar )
459 {
460  typedef typename MatrixScalar::ordinal_type Ordinal;
461  typedef typename MatrixScalar::execution_space Device;
462  typedef typename MatrixScalar::cijk_type Cijk;
463  typedef KokkosSparse::CrsMatrix<MatrixScalar,Ordinal,Device> Matrix;
464 
465  // Build Cijk tensor
466  const Ordinal stoch_dim = 2;
467  const Ordinal poly_ord = 3;
468  Cijk cijk = build_cijk<Cijk>(stoch_dim, poly_ord);
469 
470  // Build diagonal matrix
471  const Ordinal nrow = 10;
472  const Ordinal pce_size = cijk.dimension();
473  Matrix matrix = buildDiagonalMatrix<Matrix>(nrow, pce_size, cijk);
474 
475  // Launch our kernel
476  typedef AddDiagonalValuesKernel<Matrix> kernel;
477  kernel::apply(matrix);
478 
479  // Check the result
480  success = kernel::check(matrix, out);
481 }
482 
484  Kokkos_CrsMatrix_PCE, SumIntoValuesAtomic, MatrixScalar )
485 {
486  typedef typename MatrixScalar::ordinal_type Ordinal;
487  typedef typename MatrixScalar::execution_space Device;
488  typedef typename MatrixScalar::cijk_type Cijk;
489  typedef KokkosSparse::CrsMatrix<MatrixScalar,Ordinal,Device> Matrix;
490 
491  // Build Cijk tensor
492  const Ordinal stoch_dim = 2;
493  const Ordinal poly_ord = 3;
494  Cijk cijk = build_cijk<Cijk>(stoch_dim, poly_ord);
495 
496  // Build diagonal matrix
497  const Ordinal nrow = 10;
498  const Ordinal pce_size = cijk.dimension();
499  Matrix matrix = buildDiagonalMatrix<Matrix>(nrow, pce_size, cijk);
500 
501  // Launch our kernel
503  kernel::apply(matrix);
504 
505  // Check the result
506  success = kernel::check(matrix, out);
507 }
508 
509 template <typename PCEType, typename Multiply>
510 bool test_embedded_pce(const typename PCEType::ordinal_type nGrid,
511  const typename PCEType::ordinal_type stoch_dim,
512  const typename PCEType::ordinal_type poly_ord,
513  KokkosSparse::DeviceConfig dev_config,
514  Multiply multiply_op,
516 {
517  typedef typename PCEType::ordinal_type ordinal_type;
518  typedef typename PCEType::value_type scalar_type;
519  typedef typename PCEType::storage_type storage_type;
520  typedef typename PCEType::cijk_type cijk_type;
522  typedef Kokkos::LayoutLeft Layout;
523  typedef Kokkos::View< PCEType*, Layout, execution_space > block_vector_type;
524  typedef KokkosSparse::CrsMatrix< PCEType, ordinal_type, execution_space > block_matrix_type;
525  typedef typename block_matrix_type::StaticCrsGraphType matrix_graph_type;
526  typedef typename block_matrix_type::values_type matrix_values_type;
527 
528  // Build Cijk tensor
529  cijk_type cijk = build_cijk<cijk_type>(stoch_dim, poly_ord);
530  const ordinal_type stoch_length = cijk.dimension();
531  // const ordinal_type align = 8;
532  // const ordinal_type stoch_length_aligned = (stoch_length+align-1) & ~(align-1);
533  const ordinal_type stoch_length_aligned = stoch_length;
534 
535  // Check pce_length == storage_type::static_size for static storage
537  storage_type::is_static && storage_type::static_size != stoch_length,
538  std::logic_error,
539  "Static storage size must equal pce size");
540 
541  // Generate FEM graph:
542  const ordinal_type fem_length = nGrid * nGrid * nGrid;
543  std::vector< std::vector<ordinal_type> > fem_graph;
544  const ordinal_type fem_graph_length = generate_fem_graph( nGrid, fem_graph );
545 
546  //------------------------------
547  // Generate input/output multivectors -- Sacado dimension is always last,
548  // regardless of LayoutLeft/Right
549 
550  block_vector_type x =
551  Kokkos::make_view<block_vector_type>("x", cijk, fem_length, stoch_length_aligned);
552  block_vector_type y =
553  Kokkos::make_view<block_vector_type>("y", cijk, fem_length, stoch_length_aligned);
554 
555  typename block_vector_type::HostMirror hx = Kokkos::create_mirror_view( x );
556  typename block_vector_type::HostMirror hy = Kokkos::create_mirror_view( y );
557 
558  // View the block vector as an array of the embedded intrinsic type.
559  typename block_vector_type::HostMirror::array_type hax = hx ;
560  typename block_vector_type::HostMirror::array_type hay = hy ;
561 
562  for (ordinal_type iRowFEM=0; iRowFEM<fem_length; ++iRowFEM) {
563  for (ordinal_type iRowStoch=0; iRowStoch<stoch_length; ++iRowStoch) {
564  hax(iRowStoch, iRowFEM) =
565  generate_vector_coefficient<scalar_type>(
566  fem_length, stoch_length, iRowFEM, iRowStoch );
567  hay(iRowStoch, iRowFEM) = 0.0;
568  }
569  }
570 
571  Kokkos::deep_copy( x, hx );
572  Kokkos::deep_copy( y, hy );
573 
574  //------------------------------
575  // Generate block matrix -- it is always LayoutRight (currently)
576 
577  matrix_graph_type matrix_graph =
578  Kokkos::create_staticcrsgraph<matrix_graph_type>(
579  std::string("test crs graph"), fem_graph);
580  matrix_values_type matrix_values =
581  Kokkos::make_view<matrix_values_type>(
582  Kokkos::ViewAllocateWithoutInitializing("matrix"), cijk, fem_graph_length, stoch_length_aligned);
583  block_matrix_type matrix(
584  "block_matrix", fem_length, matrix_values, matrix_graph);
585  matrix.dev_config = dev_config;
586 
587  typename matrix_values_type::HostMirror hM =
588  Kokkos::create_mirror_view( matrix.values );
589 
590  typename matrix_values_type::HostMirror::array_type haM = hM ;
591 
592  for (ordinal_type iRowFEM=0, iEntryFEM=0; iRowFEM<fem_length; ++iRowFEM) {
593  const ordinal_type row_size = fem_graph[iRowFEM].size();
594  for (ordinal_type iRowEntryFEM=0; iRowEntryFEM<row_size;
595  ++iRowEntryFEM, ++iEntryFEM) {
596  const ordinal_type iColFEM = fem_graph[iRowFEM][iRowEntryFEM];
597 
598  for (ordinal_type k=0; k<stoch_length; ++k) {
599  haM(iEntryFEM, k) =
600  generate_matrix_coefficient<scalar_type>(
601  fem_length, stoch_length, iRowFEM, iColFEM, k);
602  }
603  }
604  }
605 
606  Kokkos::deep_copy( matrix.values, hM );
607 
608  //------------------------------
609  // multiply
610 
611  multiply_op( matrix, x, y );
612 
613  //------------------------------
614  // generate correct answer
615 
616  typedef typename block_vector_type::array_type array_type;
617  array_type ay_expected =
618  array_type("ay_expected", stoch_length_aligned, fem_length);
619  typename array_type::HostMirror hay_expected =
620  Kokkos::create_mirror_view(ay_expected);
621  typename cijk_type::HostMirror host_cijk =
623  Kokkos::deep_copy(host_cijk, cijk);
624  for (ordinal_type iRowFEM=0, iEntryFEM=0; iRowFEM<fem_length; ++iRowFEM) {
625  const ordinal_type row_size = fem_graph[iRowFEM].size();
626  for (ordinal_type iRowEntryFEM=0; iRowEntryFEM<row_size;
627  ++iRowEntryFEM, ++iEntryFEM) {
628  const ordinal_type iColFEM = fem_graph[iRowFEM][iRowEntryFEM];
629  for (ordinal_type i=0; i<stoch_length; ++i) {
630  const ordinal_type num_entry = host_cijk.num_entry(i);
631  const ordinal_type entry_beg = host_cijk.entry_begin(i);
632  const ordinal_type entry_end = entry_beg + num_entry;
633  scalar_type tmp = 0;
634  for (ordinal_type entry = entry_beg; entry < entry_end; ++entry) {
635  const ordinal_type j = host_cijk.coord(entry,0);
636  const ordinal_type k = host_cijk.coord(entry,1);
637  const scalar_type a_j =
638  generate_matrix_coefficient<scalar_type>(
639  fem_length, stoch_length, iRowFEM, iColFEM, j);
640  const scalar_type a_k =
641  generate_matrix_coefficient<scalar_type>(
642  fem_length, stoch_length, iRowFEM, iColFEM, k);
643  const scalar_type x_j =
644  generate_vector_coefficient<scalar_type>(
645  fem_length, stoch_length, iColFEM, j);
646  const scalar_type x_k =
647  generate_vector_coefficient<scalar_type>(
648  fem_length, stoch_length, iColFEM, k);
649  tmp += host_cijk.value(entry) * ( a_j * x_k + a_k * x_j );
650  }
651  hay_expected(i, iRowFEM) += tmp;
652  }
653  }
654  }
655  Kokkos::deep_copy( ay_expected, hay_expected );
656 
657  //------------------------------
658  // check
659 
660  typename block_vector_type::array_type ay = y;
661  scalar_type rel_tol = ScalarTol<scalar_type>::tol();
662  scalar_type abs_tol = ScalarTol<scalar_type>::tol();
663  bool success = compare_rank_2_views(ay, ay_expected, rel_tol, abs_tol, out);
664 
665  return success;
666 }
667 
669  Kokkos_CrsMatrix_PCE, Multiply, Scalar, MultiplyOp )
670 {
671  typedef typename Scalar::ordinal_type Ordinal;
672 
673  const Ordinal nGrid = 5;
674  const Ordinal stoch_dim = 2;
675  const Ordinal poly_ord = 3;
676  KokkosSparse::DeviceConfig dev_config;
677 
678  success = test_embedded_pce<Scalar>(
679  nGrid, stoch_dim, poly_ord, dev_config, MultiplyOp(), out);
680 }
681 
682 struct Kokkos_MV_Multiply_Op {
683  template <typename Matrix, typename InputVector, typename OutputVector>
684  void operator() (const Matrix& A,
685  const InputVector& x,
686  OutputVector& y) const {
687  KokkosSparse::spmv("N", typename Matrix::value_type(1.0) , A, x, typename Matrix::value_type(0.0), y);
688  }
689 };
690 
691 template <typename Tag>
692 struct Stokhos_MV_Multiply_Op {
693  Tag tag;
694  Stokhos_MV_Multiply_Op(const Tag& tg = Tag()) : tag(tg) {}
695 
696  template <typename Matrix, typename InputVector, typename OutputVector>
697  void operator() (const Matrix& A,
698  const InputVector& x,
699  OutputVector& y) const {
700  Stokhos::multiply(A, x, y, tag);
701  }
702 };
703 
705  Kokkos_CrsMatrix_PCE, MeanMultiplyRank1, Scalar )
706 {
707  typedef typename Scalar::ordinal_type Ordinal;
708 
709  const Ordinal nGrid = 5;
710  const Ordinal stoch_dim = 5;
711  const Ordinal poly_ord = 3;
712  KokkosSparse::DeviceConfig dev_config;
713 
714  typedef typename Scalar::ordinal_type ordinal_type;
715  typedef typename Scalar::value_type scalar_type;
716  typedef typename Scalar::storage_type storage_type;
717  typedef typename Scalar::cijk_type cijk_type;
719  typedef Kokkos::LayoutLeft Layout;
720  typedef Kokkos::View< Scalar*, Layout, execution_space > block_vector_type;
721  typedef KokkosSparse::CrsMatrix< Scalar, ordinal_type, execution_space > block_matrix_type;
722  typedef typename block_matrix_type::StaticCrsGraphType matrix_graph_type;
723  typedef typename block_matrix_type::values_type matrix_values_type;
724 
725  // Build Cijk tensor
726  cijk_type cijk = build_cijk<cijk_type>(stoch_dim, poly_ord);
727  cijk_type mean_cijk =
728  Stokhos::create_mean_based_product_tensor<execution_space, ordinal_type, scalar_type>();
729  const ordinal_type stoch_length = cijk.dimension();
730  const ordinal_type align = 8;
731  const ordinal_type stoch_length_aligned = (stoch_length+align-1) & ~(align-1);
732 
733  // Generate FEM graph:
734  const ordinal_type fem_length = nGrid * nGrid * nGrid;
735  std::vector< std::vector<ordinal_type> > fem_graph;
736  const ordinal_type fem_graph_length = generate_fem_graph( nGrid, fem_graph );
737 
738  block_vector_type x =
739  Kokkos::make_view<block_vector_type>("x", cijk, fem_length, stoch_length_aligned);
740  block_vector_type y =
741  Kokkos::make_view<block_vector_type>("y", cijk, fem_length, stoch_length_aligned);
742 
743  block_vector_type y_expected =
744  Kokkos::make_view<block_vector_type>("y", cijk, fem_length, stoch_length_aligned);
745 
746  typename block_vector_type::HostMirror hx = Kokkos::create_mirror_view( x );
747  typename block_vector_type::HostMirror hy = Kokkos::create_mirror_view( y );
748  typename block_vector_type::HostMirror hy_expected =
749  Kokkos::create_mirror_view( y_expected );
750 
751  // View the block vector as an array of the embedded intrinsic type.
752  typename block_vector_type::HostMirror::array_type hax = hx ;
753  typename block_vector_type::HostMirror::array_type hay = hy ;
754  typename block_vector_type::HostMirror::array_type hay_expected =
755  hy_expected ;
756 
757  for (ordinal_type iRowFEM=0; iRowFEM<fem_length; ++iRowFEM) {
758  for (ordinal_type iRowStoch=0; iRowStoch<stoch_length; ++iRowStoch) {
759  hax(iRowStoch,iRowFEM) =
760  generate_vector_coefficient<scalar_type>(
761  fem_length, stoch_length, iRowFEM, iRowStoch );
762  hay(iRowStoch,iRowFEM) = 0.0;
763  hay_expected(iRowStoch,iRowFEM) = 0.0;
764  }
765  }
766  Kokkos::deep_copy( x, hx );
767  Kokkos::deep_copy( y, hy );
768  Kokkos::deep_copy( y_expected, hy_expected );
769 
770  //------------------------------
771  // Generate block matrix -- it is always LayoutRight (currently)
772  matrix_graph_type matrix_graph =
773  Kokkos::create_staticcrsgraph<matrix_graph_type>(
774  std::string("test crs graph"), fem_graph);
775  matrix_values_type matrix_values =
776  Kokkos::make_view<matrix_values_type>(
777  Kokkos::ViewAllocateWithoutInitializing("matrix"), mean_cijk, fem_graph_length, ordinal_type(1)); //instead of stoch_length
778  block_matrix_type matrix(
779  "block_matrix", fem_length, matrix_values, matrix_graph);
780  matrix.dev_config = dev_config;
781 
782  typename matrix_values_type::HostMirror hM =
783  Kokkos::create_mirror_view( matrix.values );
784  typename matrix_values_type::HostMirror::array_type haM = hM ;
785 
786  for (ordinal_type iRowFEM=0, iEntryFEM=0; iRowFEM<fem_length; ++iRowFEM) {
787  const ordinal_type row_size = fem_graph[iRowFEM].size();
788  for (ordinal_type iRowEntryFEM=0; iRowEntryFEM<row_size;
789  ++iRowEntryFEM, ++iEntryFEM) {
790  const ordinal_type iColFEM = fem_graph[iRowFEM][iRowEntryFEM];
791 
792  haM(iEntryFEM, 0) =
793  generate_matrix_coefficient<scalar_type>(
794  fem_length, 1, iRowFEM, iColFEM, 0);
795  for (ordinal_type iRowStoch=0; iRowStoch<stoch_length; ++iRowStoch) {
796  hay_expected(iRowStoch,iRowFEM) +=
797  haM(iEntryFEM, 0) * hax(iRowStoch,iColFEM);
798  }
799  }
800  }
801  Kokkos::deep_copy( matrix.values, hM );
802  Kokkos::deep_copy( y_expected, hy_expected );
803 
804  /*
805  //Generate same matrix with stochastic dim = Kokkos::dimension_scalar(x) (i.e. not = 1)
806  matrix_values_type full_matrix_values =
807  Kokkos::make_view<matrix_values_type>(
808  Kokkos::ViewAllocateWithoutInitializing("matrix"), cijk, fem_graph_length, stoch_length_aligned);
809  block_matrix_type full_matrix(
810  "block_matrix", fem_length, full_matrix_values, matrix_graph);
811  matrix.dev_config = dev_config;
812 
813  typename matrix_values_type::HostMirror full_hM =
814  Kokkos::create_mirror_view( full_matrix.values );
815  typename matrix_values_type::HostMirror::array_type full_haM = full_hM ;
816 
817  for (ordinal_type iRowFEM=0, iEntryFEM=0; iRowFEM<fem_length; ++iRowFEM) {
818  const ordinal_type row_size = fem_graph[iRowFEM].size();
819  for (ordinal_type iRowEntryFEM=0; iRowEntryFEM<row_size;
820  ++iRowEntryFEM, ++iEntryFEM) {
821  const ordinal_type iColFEM = fem_graph[iRowFEM][iRowEntryFEM];
822 
823  for (ordinal_type k=0; k<stoch_length; ++k) {
824  if (k == 0)
825  full_haM(iEntryFEM, k) =
826  generate_matrix_coefficient<scalar_type>(
827  fem_length, 1, iRowFEM, iColFEM, k);
828  else
829  full_haM(iEntryFEM, k) = 0.0;
830  }
831  }
832  }
833 
834  Kokkos::deep_copy( full_matrix.values, full_hM );
835  */
836 
837  //------------------------------
838  // multiply
839 
840  KokkosSparse::spmv("N", Scalar(1.0) , matrix, x, Scalar(0.0), y);
841 
842  //------------------------------
843  // multiply with same matrix but with sacado_size = x.sacado_size
844 
845  //Kokkos::MV_Multiply( y_expected, full_matrix, x );
846 
847  //------------------------------
848  // check
849  scalar_type rel_tol = ScalarTol<scalar_type>::tol();
850  scalar_type abs_tol = ScalarTol<scalar_type>::tol();
851  success = compareRank1(y, y_expected, rel_tol, abs_tol, out);
852 }
853 
854 
856  Kokkos_CrsMatrix_PCE, MeanMultiplyRank2, Scalar )
857 {
858  typedef typename Scalar::ordinal_type ordinal_type;
859  typedef typename Scalar::value_type scalar_type;
860  typedef typename Scalar::storage_type storage_type;
861  typedef typename Scalar::cijk_type cijk_type;
863  typedef Kokkos::LayoutLeft Layout;
864  typedef Kokkos::View< Scalar**, Layout, execution_space > block_vector_type;
865  typedef KokkosSparse::CrsMatrix< Scalar, ordinal_type, execution_space > block_matrix_type;
866  typedef typename block_matrix_type::StaticCrsGraphType matrix_graph_type;
867  typedef typename block_matrix_type::values_type matrix_values_type;
868 
869 
870  const ordinal_type nGrid = 5;
871  const ordinal_type stoch_dim = 2;
872  const ordinal_type poly_ord = 3;
873  KokkosSparse::DeviceConfig dev_config;
874 
875  // Build Cijk tensor
876  cijk_type cijk = build_cijk<cijk_type>(stoch_dim, poly_ord);
877  cijk_type mean_cijk =
878  Stokhos::create_mean_based_product_tensor<execution_space, ordinal_type, scalar_type>();
879  const ordinal_type stoch_length = cijk.dimension();
880  const ordinal_type align = 8;
881  const ordinal_type stoch_length_aligned = (stoch_length+align-1) & ~(align-1);
882  const ordinal_type num_cols = 2;
883  // Generate FEM graph:
884  const ordinal_type fem_length = nGrid * nGrid * nGrid;
885  std::vector< std::vector<ordinal_type> > fem_graph;
886  const ordinal_type fem_graph_length = generate_fem_graph( nGrid, fem_graph );
887 
888  block_vector_type x =
889  Kokkos::make_view<block_vector_type>("x", cijk, fem_length, num_cols, stoch_length_aligned);
890  block_vector_type y =
891  Kokkos::make_view<block_vector_type>("y", cijk, fem_length, num_cols, stoch_length_aligned);
892 
893  block_vector_type y_expected =
894  Kokkos::make_view<block_vector_type>("y_expected", cijk, fem_length, num_cols, stoch_length_aligned);
895 
896  typename block_vector_type::HostMirror hx = Kokkos::create_mirror_view( x );
897  typename block_vector_type::HostMirror hy = Kokkos::create_mirror_view( y );
898  typename block_vector_type::HostMirror hy_expected =
899  Kokkos::create_mirror_view( y_expected );
900 
901  for (ordinal_type i=0; i<num_cols; ++i){
902  for (ordinal_type iRowFEM=0; iRowFEM<fem_length; ++iRowFEM) {
903  for (ordinal_type iRowStoch=0; iRowStoch<stoch_length; ++iRowStoch) {
904  hx(iRowFEM,i).fastAccessCoeff(iRowStoch) =
905  generate_vector_coefficient<scalar_type>(
906  fem_length, stoch_length, iRowFEM, iRowStoch );
907  hy(iRowFEM,i).fastAccessCoeff(iRowStoch) = 0.0;
908  hy_expected(iRowFEM,i).fastAccessCoeff(iRowStoch) = 0.0;
909  }
910  }
911  }
912  Kokkos::deep_copy( x, hx );
913  Kokkos::deep_copy( y, hy );
914  Kokkos::deep_copy( y_expected, hy_expected );
915 
916  //------------------------------
917  // Generate matrix with stochastic dimension 1
918  matrix_graph_type matrix_graph =
919  Kokkos::create_staticcrsgraph<matrix_graph_type>(
920  std::string("test crs graph"), fem_graph);
921  matrix_values_type matrix_values =
922  Kokkos::make_view<matrix_values_type>(
923  Kokkos::ViewAllocateWithoutInitializing("matrix"), mean_cijk, fem_graph_length, ordinal_type(1));
924  block_matrix_type matrix(
925  "block_matrix", fem_length, matrix_values, matrix_graph);
926  matrix.dev_config = dev_config;
927 
928  typename matrix_values_type::HostMirror hM =
929  Kokkos::create_mirror_view( matrix.values );
930 
931  typename matrix_values_type::HostMirror::array_type haM = hM ;
932 
933  for (ordinal_type iRowFEM=0, iEntryFEM=0; iRowFEM<fem_length; ++iRowFEM) {
934  const ordinal_type row_size = fem_graph[iRowFEM].size();
935  for (ordinal_type iRowEntryFEM=0; iRowEntryFEM<row_size;
936  ++iRowEntryFEM, ++iEntryFEM) {
937  const ordinal_type iColFEM = fem_graph[iRowFEM][iRowEntryFEM];
938 
939  haM(iEntryFEM, 0) =
940  generate_matrix_coefficient<scalar_type>(
941  fem_length, 1, iRowFEM, iColFEM, 0);
942  for (ordinal_type i=0; i<num_cols; ++i){
943  for (ordinal_type iRowStoch=0; iRowStoch<stoch_length; ++iRowStoch) {
944  hy_expected(iRowFEM,i).fastAccessCoeff(iRowStoch) +=
945  haM(iEntryFEM, 0) * hx(iColFEM,i).fastAccessCoeff(iRowStoch);
946  }
947  }
948  }
949  }
950 
951  Kokkos::deep_copy( matrix.values, hM );
952  Kokkos::deep_copy( y_expected, hy_expected );
953 
954  /*
955  //Generate same matrix with stochastic dim = Kokkos::dimension_scalar(x) (i.e. not = 1)
956  matrix_values_type full_matrix_values =
957  Kokkos::make_view<matrix_values_type>(
958  Kokkos::ViewAllocateWithoutInitializing("matrix"), cijk, fem_graph_length, stoch_length_aligned);
959  block_matrix_type full_matrix(
960  "block_matrix", fem_length, full_matrix_values, matrix_graph);
961  matrix.dev_config = dev_config;
962 
963  typename matrix_values_type::HostMirror full_hM =
964  Kokkos::create_mirror_view( full_matrix.values );
965 
966  typename matrix_values_type::HostMirror::array_type full_haM = full_hM ;
967 
968  for (ordinal_type iRowFEM=0, iEntryFEM=0; iRowFEM<fem_length; ++iRowFEM) {
969  const ordinal_type row_size = fem_graph[iRowFEM].size();
970  for (ordinal_type iRowEntryFEM=0; iRowEntryFEM<row_size;
971  ++iRowEntryFEM, ++iEntryFEM) {
972  const ordinal_type iColFEM = fem_graph[iRowFEM][iRowEntryFEM];
973 
974  for (ordinal_type k=0; k<stoch_length; ++k) {
975  if (k == 0)
976  full_haM(iEntryFEM, k) =
977  generate_matrix_coefficient<scalar_type>(
978  fem_length, 1, iRowFEM, iColFEM, k);
979  else
980  full_haM(iEntryFEM, k) = 0.0;
981  }
982  }
983  }
984 
985  Kokkos::deep_copy( full_matrix.values, full_hM );
986  */
987 
988  //------------------------------
989  // multiply
990 
991  KokkosSparse::spmv("N", Scalar(1.0) , matrix, x, Scalar(0.0), y);
992 
993  //------------------------------
994  // multiply with full matrix
995 
996  //Kokkos::MV_Multiply( y_expected, full_matrix, x );
997 
998  //------------------------------
999  // check
1000 
1001  scalar_type rel_tol = ScalarTol<scalar_type>::tol();
1002  scalar_type abs_tol = ScalarTol<scalar_type>::tol();
1003  success = compareRank2(y, y_expected, rel_tol, abs_tol, out);
1004 }
1005 
1006 
1008 
1009 #define CRSMATRIX_UQ_PCE_TESTS_MATRIXSCALAR( SCALAR ) \
1010  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( \
1011  Kokkos_CrsMatrix_PCE, ReplaceValues, SCALAR ) \
1012  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( \
1013  Kokkos_CrsMatrix_PCE, SumIntoValues, SCALAR ) \
1014  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( \
1015  Kokkos_CrsMatrix_PCE, SumIntoValuesAtomic, SCALAR )
1016 #define CRSMATRIX_UQ_PCE_MEAN_MULTIPLY_TESTS( SCALAR ) \
1017  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( \
1018  Kokkos_CrsMatrix_PCE, MeanMultiplyRank1, SCALAR ) \
1019  TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( \
1020  Kokkos_CrsMatrix_PCE, MeanMultiplyRank2, SCALAR )
1021 #define CRS_MATRIX_UQ_PCE_MULTIPLY_TESTS_SCALAR_OP( SCALAR, OP ) \
1022  TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( \
1023  Kokkos_CrsMatrix_PCE, Multiply, SCALAR, OP )
1024 
1025 #define CRS_MATRIX_UQ_PCE_MULTIPLY_TESTS_SCALAR( SCALAR ) \
1026  CRS_MATRIX_UQ_PCE_MULTIPLY_TESTS_SCALAR_OP( SCALAR, KokkosMultiply )
1027 
1028 #define CRSMATRIX_UQ_PCE_TESTS_STORAGE( STORAGE ) \
1029  typedef Sacado::UQ::PCE<STORAGE> UQ_PCE_ ## STORAGE; \
1030  CRSMATRIX_UQ_PCE_TESTS_MATRIXSCALAR( UQ_PCE_ ## STORAGE ) \
1031  CRS_MATRIX_UQ_PCE_MULTIPLY_TESTS_SCALAR( UQ_PCE_ ## STORAGE ) \
1032  CRSMATRIX_UQ_PCE_MEAN_MULTIPLY_TESTS( UQ_PCE_ ## STORAGE )
1033 
1034 #define CRSMATRIX_UQ_PCE_TESTS_ORDINAL_SCALAR_DEVICE( ORDINAL, SCALAR, DEVICE ) \
1035  typedef Stokhos::DynamicStorage<ORDINAL,SCALAR,DEVICE> DS; \
1036  CRSMATRIX_UQ_PCE_TESTS_STORAGE( DS )
1037 
1038 #define CRSMATRIX_UQ_PCE_TESTS_DEVICE( DEVICE ) \
1039  CRSMATRIX_UQ_PCE_TESTS_ORDINAL_SCALAR_DEVICE( int, double, DEVICE )
KOKKOS_INLINE_FUNCTION void operator()(const size_type i) const
KOKKOS_INLINE_FUNCTION void operator()(const size_type i) const
Stokhos::StandardStorage< int, double > storage_type
bool compareVecs(const VectorType1 &a1, const std::string &a1_name, const VectorType2 &a2, const std::string &a2_name, const ValueType &rel_tol, const ValueType &abs_tol, Teuchos::FancyOStream &out)
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
bool test_embedded_pce(const typename PCEType::ordinal_type nGrid, const typename PCEType::ordinal_type stoch_dim, const typename PCEType::ordinal_type poly_ord, KokkosSparse::DeviceConfig dev_config, Multiply multiply_op, Teuchos::FancyOStream &out)
ordinal generate_fem_graph(ordinal N, std::vector< std::vector< ordinal > > &graph)
Definition: TestEpetra.cpp:45
static bool check(const MatrixType matrix, Teuchos::FancyOStream &out)
Kokkos::DefaultExecutionSpace execution_space
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
MatrixType buildDiagonalMatrix(typename MatrixType::ordinal_type nrow, typename MatrixType::ordinal_type mp_vector_size)
static void apply(const MatrixType matrix)
scalar generate_vector_coefficient(const ordinal nFEM, const ordinal nStoch, const ordinal iColFEM, const ordinal iStoch)
KOKKOS_INLINE_FUNCTION constexpr std::enable_if< is_view_uq_pce< View< T, P...> >::value, unsigned >::type dimension_scalar(const View< T, P...> &view)
bool compareRank2(const vector_type &y, const vector_type &y_exp, const scalar_type rel_tol, const scalar_type abs_tol, Teuchos::FancyOStream &out)
IntType map_fem_graph_coord(const IntType &N, const IntType &i, const IntType &j, const IntType &k)
Definition: TestEpetra.cpp:35
void multiply(const CrsMatrix< MatrixValue, Device, Layout > &A, const InputMultiVectorType &x, OutputMultiVectorType &y, const std::vector< OrdinalType > &col_indices, SingleColumnMultivectorMultiply)
TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL(Kokkos_SG_SpMv, CrsProductTensorCijk, Scalar, Device)
static bool check(const MatrixType matrix, Teuchos::FancyOStream &out)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Kokkos_MV_Multiply_Op KokkosMultiply
void operator()(const Matrix &A, const InputVector &x, OutputVector &y) const
static void apply(const MatrixType matrix)
static bool check(const MatrixType matrix, Teuchos::FancyOStream &out)
void deep_copy(const Stokhos::CrsMatrix< ValueType, DstDevice, Layout > &dst, const Stokhos::CrsMatrix< ValueType, SrcDevice, Layout > &src)
KOKKOS_INLINE_FUNCTION PCE< Storage > abs(const PCE< Storage > &a)
expr1 expr1 expr1 expr2 expr1 expr1 c expr2 expr1 c fastAccessCoeff(j)-expr2.val(j)
Multivariate orthogonal polynomial basis generated from a total-order complete-polynomial tensor prod...
kokkos_cijk_type build_cijk(ordinal_type stoch_dim, ordinal_type poly_ord)
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)
Legendre polynomial basis.
scalar generate_matrix_coefficient(const ordinal nFEM, const ordinal nStoch, const ordinal iRowFEM, const ordinal iColFEM, const ordinal iStoch)
expr val()
KOKKOS_INLINE_FUNCTION void operator()(const size_type i) const
Abstract base class for 1-D orthogonal polynomials.
TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(Kokkos_CrsMatrix_MP, ReplaceValues, MatrixScalar)
std::enable_if< Kokkos::is_view_uq_pce< Kokkos::View< InputType, InputP... > >::value &&Kokkos::is_view_uq_pce< Kokkos::View< OutputType, OutputP... > >::value >::type spmv(KokkosKernels::Experimental::Controls, const char mode[], const AlphaType &a, const MatrixType &A, const Kokkos::View< InputType, InputP... > &x, const BetaType &b, const Kokkos::View< OutputType, OutputP... > &y, const RANK_ONE)
bool compareRank1(const vector_type &y, const vector_type &y_exp, const scalar_type rel_tol, const scalar_type abs_tol, Teuchos::FancyOStream &out)
void operator()(const Matrix &A, const InputVector &x, OutputVector &y) const
bool compare_rank_2_views(const array_type &y, const array_type &y_exp, const scalar_type rel_tol, const scalar_type abs_tol, Teuchos::FancyOStream &out)
static void apply(const MatrixType matrix)
Stokhos::CrsMatrix< ValueType, Device, Layout >::HostMirror create_mirror_view(const Stokhos::CrsMatrix< ValueType, Device, Layout > &A)