Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Stokhos_KokkosArrayKernelsUnitTest.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_KOKKOS_CORE_KERNELS_UNIT_TEST_HPP
11 #define STOKHOS_KOKKOS_CORE_KERNELS_UNIT_TEST_HPP
12 
16 
17 #include "Stokhos_Epetra.hpp"
19 #include "EpetraExt_BlockUtility.h"
21 
22 #ifdef HAVE_MPI
23 #include "Epetra_MpiComm.h"
24 #else
25 #include "Epetra_SerialComm.h"
26 #endif
27 
28 #include "Kokkos_Macros.hpp"
29 
30 #include "Stokhos_Update.hpp"
31 #include "Stokhos_CrsMatrix.hpp"
43 
44 #ifdef HAVE_STOKHOS_KOKKOSLINALG
45 #include "KokkosSparse_CrsMatrix.hpp"
46 #include "KokkosSparse_spmv.hpp"
47 #include "KokkosBlas1_update.hpp"
48 #endif
49 
50 namespace KokkosKernelsUnitTest {
51 
52 using Teuchos::rcp;
53 using Teuchos::RCP;
54 using Teuchos::Array;
56 
57 template< typename IntType >
58 inline
59 IntType map_fem_graph_coord( const IntType & N ,
60  const IntType & i ,
61  const IntType & j ,
62  const IntType & k )
63 {
64  return k + N * ( j + N * i );
65 }
66 
67 template < typename ordinal >
68 inline
69 ordinal generate_fem_graph( ordinal N ,
70  std::vector< std::vector<ordinal> > & graph )
71 {
72  graph.resize( N * N * N , std::vector<ordinal>() );
73 
74  ordinal total = 0 ;
75 
76  for ( int i = 0 ; i < (int) N ; ++i ) {
77  for ( int j = 0 ; j < (int) N ; ++j ) {
78  for ( int k = 0 ; k < (int) N ; ++k ) {
79 
80  const ordinal row = map_fem_graph_coord((int)N,i,j,k);
81 
82  graph[row].reserve(27);
83 
84  for ( int ii = -1 ; ii < 2 ; ++ii ) {
85  for ( int jj = -1 ; jj < 2 ; ++jj ) {
86  for ( int kk = -1 ; kk < 2 ; ++kk ) {
87  if ( 0 <= i + ii && i + ii < (int) N &&
88  0 <= j + jj && j + jj < (int) N &&
89  0 <= k + kk && k + kk < (int) N ) {
90  ordinal col = map_fem_graph_coord((int)N,i+ii,j+jj,k+kk);
91 
92  graph[row].push_back(col);
93  }
94  }}}
95  total += graph[row].size();
96  }}}
97 
98  return total ;
99 }
100 
101 template <typename scalar, typename ordinal>
102 inline
103 scalar generate_matrix_coefficient( const ordinal nFEM ,
104  const ordinal nStoch ,
105  const ordinal iRowFEM ,
106  const ordinal iColFEM ,
107  const ordinal iStoch )
108 {
109  const scalar A_fem = ( 10.0 + scalar(iRowFEM) / scalar(nFEM) ) +
110  ( 5.0 + scalar(iColFEM) / scalar(nFEM) );
111 
112  const scalar A_stoch = ( 1.0 + scalar(iStoch) / scalar(nStoch) );
113 
114  return A_fem + A_stoch ;
115  //return 1.0;
116 }
117 
118 template <typename scalar, typename ordinal>
119 inline
120 scalar generate_vector_coefficient( const ordinal nFEM ,
121  const ordinal nStoch ,
122  const ordinal iColFEM ,
123  const ordinal iStoch )
124 {
125  const scalar X_fem = 100.0 + scalar(iColFEM) / scalar(nFEM);
126  const scalar X_stoch = 1.0 + scalar(iStoch) / scalar(nStoch);
127  return X_fem + X_stoch ;
128  //return 1.0;
129 }
130 
131 template <typename Device>
133  typedef double value_type ;
136  //typedef Stokhos::CompletePolynomialBasis<int,value_type> product_basis_type;
140 
142  double rel_tol, abs_tol;
143  std::vector< std::vector<int> > fem_graph ;
150 
151  // Can't be a constructor because MPI will not be initialized
152  void setup(int p_ = 5, int d_ = 2) {
153 
154  p = p_;
155  d = d_;
156  nGrid = 3;
157  rel_tol = 1e-12;
158  abs_tol = 1e-12;
159 
160  // Create a communicator for Epetra objects
161 #ifdef HAVE_MPI
162  globalComm = rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
163 #else
165 #endif
166  //int MyPID = globalComm->MyPID();
167 
168  //------------------------------
169  // Generate FEM graph:
170 
171  fem_length = nGrid * nGrid * nGrid ;
173 
174  // Create Stochastic Galerkin basis and expansion
176  for (int i=0; i<d; i++)
177  bases[i] = rcp(new basis_type(p,true));
178  basis = rcp(new product_basis_type(bases, 1e-12));
179  stoch_length = basis->size();
180  Cijk = basis->computeTripleProductTensor();
181 
182  // Create stochastic parallel distribution
183  ParameterList parallelParams;
184  RCP<Stokhos::ParallelData> sg_parallel_data =
185  rcp(new Stokhos::ParallelData(basis, Cijk, globalComm, parallelParams));
187  sg_parallel_data->getMultiComm();
188  RCP<const Epetra_Comm> app_comm =
189  sg_parallel_data->getSpatialComm();
191  sg_parallel_data->getEpetraCijk();
192  RCP<const Epetra_BlockMap> stoch_row_map =
193  epetraCijk->getStochasticRowMap();
194 
195  //------------------------------
196 
197  // Generate Epetra objects
198  RCP<const Epetra_Map> x_map =
199  rcp(new Epetra_Map(fem_length, 0, *app_comm));
200  RCP<const Epetra_Map> sg_x_map =
201  rcp(EpetraExt::BlockUtility::GenerateBlockMap(
202  *x_map, *stoch_row_map, *sg_comm));
203 
204  RCP<Epetra_CrsGraph> graph = rcp(new Epetra_CrsGraph(Copy, *x_map, 27));
205  int *my_GIDs = x_map->MyGlobalElements();
206  int num_my_GIDs = x_map->NumMyElements();
207  for (int i=0; i<num_my_GIDs; ++i) {
208  int row = my_GIDs[i];
209  int num_indices = fem_graph[row].size();
210  int *indices = &(fem_graph[row][0]);
211  graph->InsertGlobalIndices(row, num_indices, indices);
212  }
213  graph->FillComplete();
214 
215  RCP<ParameterList> sg_op_params = rcp(new ParameterList);
217  rcp(new Stokhos::MatrixFreeOperator(sg_comm, basis, epetraCijk,
218  x_map, x_map, sg_x_map, sg_x_map,
219  sg_op_params));
220  RCP<Epetra_BlockMap> sg_A_overlap_map =
221  rcp(new Epetra_LocalMap(
222  stoch_length, 0, *(sg_parallel_data->getStochasticComm())));
225  basis, sg_A_overlap_map, x_map, x_map, sg_x_map, sg_comm));
226  for (int i=0; i<stoch_length; i++) {
228 
229  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < fem_length ; ++iRowFEM ) {
230  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
231  const int iColFEM = fem_graph[iRowFEM][iRowEntryFEM] ;
232 
233  double v = generate_matrix_coefficient<double>(
234  fem_length , stoch_length , iRowFEM , iColFEM , i );
235  A->ReplaceGlobalValues(iRowFEM, 1, &v, &iColFEM);
236  }
237  }
238  A->FillComplete();
239  A_sg_blocks->setCoeffPtr(i, A);
240  }
241  sg_A->setupOperator(A_sg_blocks);
242 
244  basis, stoch_row_map, x_map, sg_x_map, sg_comm));
246  basis, stoch_row_map, x_map, sg_x_map, sg_comm));
247 
248  // Initialize vectors
249  for (int iColFEM=0; iColFEM < fem_length; ++iColFEM ) {
250  for (int iColStoch=0 ; iColStoch < stoch_length; ++iColStoch ) {
251  (*sg_x)[iColStoch][iColFEM] = generate_vector_coefficient<double>(
252  fem_length , stoch_length , iColFEM , iColStoch );
253  }
254  }
255  sg_y->init(0.0);
256 
257  // Apply operator
258  sg_A->Apply( *(sg_x->getBlockVector()), *(sg_y->getBlockVector()) );
259 
260  // Transpose y to commuted layout
262  x_map, stoch_row_map, sg_comm));
263  for (int block=0; block<stoch_length; ++block) {
264  for (int i=0; i<fem_length; ++i)
265  (*sg_y_commuted)[i][block] = (*sg_y)[block][i];
266  }
267 
268  typedef typename Kokkos::ViewTraits<value_type,Device,void,void>::host_mirror_space host_device;
270  typedef Stokhos::StochasticProductTensor< value_type , tensor_type ,
271  host_device > stoch_tensor_type ;
272 
273  stoch_tensor_type tensor =
274  Stokhos::create_stochastic_product_tensor< tensor_type >( *basis, *Cijk );
275  stoch_length_aligned = tensor.aligned_dimension();
276 
277  perm.resize(stoch_length);
278  inv_perm.resize(stoch_length);
279  for (int i=0; i<stoch_length; ++i) {
280  Stokhos::MultiIndex<int> term(d);
281  for (int j=0; j<d; ++j)
282  term[j] = tensor.bases_degree(i,j);
283  int idx = basis->index(term);
284  perm[idx] = i;
285  inv_perm[i] = idx;
286  }
287  }
288 
289  template <typename vec_type>
290  bool test_original(const std::vector<vec_type>& y,
291  Teuchos::FancyOStream& out) const {
292  bool success = true;
293  for (int block=0; block<stoch_length; ++block) {
294  for (int i=0; i<fem_length; ++i) {
295  double diff = std::abs( (*sg_y)[block][i] - y[block][i] );
296  double tol = rel_tol*std::abs((*sg_y)[block][i]) + abs_tol;
297  bool s = diff < tol;
298  if (!s) {
299  out << "y_expected[" << block << "][" << i << "] - "
300  << "y[" << block << "][" << i << "] = " << (*sg_y)[block][i]
301  << " - " << y[block][i] << " == "
302  << diff << " < " << tol << " : failed"
303  << std::endl;
304  }
305  success = success && s;
306  }
307  }
308 
309  return success;
310  }
311 
312  template <typename multi_vec_type>
313  bool test_original(const multi_vec_type& y,
314  Teuchos::FancyOStream& out) const {
315  bool success = true;
316  for (int block=0; block<stoch_length; ++block) {
317  for (int i=0; i<fem_length; ++i) {
318  double diff = std::abs( (*sg_y)[block][i] - y(i,block) );
319  double tol = rel_tol*std::abs((*sg_y)[block][i]) + abs_tol;
320  bool s = diff < tol;
321  if (!s) {
322  out << "y_expected[" << block << "][" << i << "] - "
323  << "y(" << i << "," << block << ") = " << (*sg_y)[block][i]
324  << " - " << y(i,block) << " == "
325  << diff << " < " << tol << " : failed"
326  << std::endl;
327  }
328  success = success && s;
329  }
330  }
331 
332  return success;
333  }
334 
335  template <typename vec_type>
337  Teuchos::FancyOStream& out) const {
338  bool success = true;
339  for (int block=0; block<stoch_length; ++block) {
340  int b = perm[block];
341  for (int i=0; i<fem_length; ++i) {
342  double diff = std::abs( (*sg_y)[block][i] - y(b,i) );
343  double tol = rel_tol*std::abs((*sg_y)[block][i]) + abs_tol;
344  bool s = diff < tol;
345  if (!s) {
346  out << "y_expected[" << block << "][" << i << "] - "
347  << "y(" << b << "," << i << ") = " << (*sg_y)[block][i]
348  << " - " << y(b,i) << " == "
349  << diff << " < " << tol << " : failed"
350  << std::endl;
351  }
352  success = success && s;
353  }
354  }
355 
356  return success;
357  }
358 
359  template <typename vec_type>
360  bool test_commuted(const vec_type& y,
361  Teuchos::FancyOStream& out) const {
362  bool success = true;
363  for (int block=0; block<stoch_length; ++block) {
364  int b = block;
365  for (int i=0; i<fem_length; ++i) {
366  double diff = std::abs( (*sg_y)[block][i] - y(b,i) );
367  double tol = rel_tol*std::abs((*sg_y)[block][i]) + abs_tol;
368  bool s = diff < tol;
369  if (!s) {
370  out << "y_expected[" << block << "][" << i << "] - "
371  << "y(" << b << "," << i << ") = " << (*sg_y)[block][i] << " - "
372  << y(b,i) << " == "
373  << diff << " < " << tol << " : failed"
374  << std::endl;
375  }
376  success = success && s;
377  }
378  }
379 
380  return success;
381  }
382 
383  template <typename vec_type>
385  Teuchos::FancyOStream& out) const {
386  bool success = true;
387  for (int block=0; block<stoch_length; ++block) {
388  int b = block;
389  for (int i=0; i<fem_length; ++i) {
390  double diff = std::abs( (*sg_y)[block][i] - y(i*stoch_length+b) );
391  double tol = rel_tol*std::abs((*sg_y)[block][i]) + abs_tol;
392  bool s = diff < tol;
393  if (!s) {
394  out << "y_expected[" << block << "][" << i << "] - "
395  << "y(" << b << "," << i << ") == "
396  << diff << " < " << tol << " : failed"
397  << std::endl;
398  }
399  success = success && s;
400  }
401  }
402 
403  return success;
404  }
405 
406  template <typename vec_type>
408  Teuchos::FancyOStream& out) const {
409  bool success = true;
410  for (int block=0; block<stoch_length; ++block) {
411  int b = block;
412  for (int i=0; i<fem_length; ++i) {
413  double diff = std::abs( (*sg_y)[block][i] - y(b*fem_length+i) );
414  double tol = rel_tol*std::abs((*sg_y)[block][i]) + abs_tol;
415  bool s = diff < tol;
416  if (!s) {
417  out << "y_expected[" << block << "][" << i << "] - "
418  << "y(" << b << "," << i << ") == "
419  << diff << " < " << tol << " : failed"
420  << std::endl;
421  }
422  success = success && s;
423  }
424  }
425 
426  return success;
427  }
428 
429 };
430 
431 template <typename value_type, typename Device, typename SparseMatOps>
433  Teuchos::FancyOStream& out) {
434  typedef Stokhos::CrsMatrix<value_type,Device> matrix_type;
435  typedef typename matrix_type::values_type matrix_values_type;
436  typedef typename matrix_type::graph_type matrix_graph_type;
437  typedef Kokkos::View<value_type*,Device> vec_type;
438 
439  //------------------------------
440 
441  std::vector<matrix_type> matrix( setup.stoch_length ) ;
442  std::vector<vec_type> x( setup.stoch_length ) ;
443  std::vector<vec_type> y( setup.stoch_length ) ;
444  std::vector<vec_type> tmp( setup.stoch_length ) ;
445 
446  for (int block=0; block<setup.stoch_length; ++block) {
447  matrix[block].graph = Kokkos::create_staticcrsgraph<matrix_graph_type>(
448  std::string("testing") , setup.fem_graph );
449 
450  matrix[block].values =
451  matrix_values_type( "matrix" , setup.fem_graph_length );
452 
453  x[block] = vec_type( "x" , setup.fem_length );
454  y[block] = vec_type( "y" , setup.fem_length );
455  tmp[block] = vec_type( "tmp" , setup.fem_length );
456 
457  typename matrix_values_type::HostMirror hM =
458  Kokkos::create_mirror( matrix[block].values );
459 
460  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
461  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
462  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM] ;
463 
464  hM(iEntryFEM) = generate_matrix_coefficient<value_type>(
465  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , block );
466  }
467  }
468 
469  Kokkos::deep_copy( matrix[block].values , hM );
470 
471  typename vec_type::HostMirror hx =
472  Kokkos::create_mirror( x[block] );
473  typename vec_type::HostMirror hy =
474  Kokkos::create_mirror( y[block] );
475 
476  for ( int i = 0 ; i < setup.fem_length ; ++i ) {
477  hx(i) = generate_vector_coefficient<value_type>(
478  setup.fem_length , setup.stoch_length , i , block );
479  hy(i) = 0.0;
480  }
481 
482  Kokkos::deep_copy( x[block] , hx );
483  Kokkos::deep_copy( y[block] , hy );
484  }
485 
486  // Original matrix-free multiply algorithm using a block apply
487  SparseMatOps smo;
489  setup.Cijk->k_begin();
491  setup.Cijk->k_end();
492  for (typename UnitTestSetup<Device>::Cijk_type::k_iterator k_it=k_begin;
493  k_it!=k_end; ++k_it) {
494  int nj = setup.Cijk->num_j(k_it);
495  if (nj > 0) {
496  int k = index(k_it);
498  setup.Cijk->j_begin(k_it);
500  setup.Cijk->j_end(k_it);
501  std::vector<vec_type> xx(nj), yy(nj);
502  int jdx = 0;
503  for (typename UnitTestSetup<Device>::Cijk_type::kj_iterator j_it = j_begin;
504  j_it != j_end;
505  ++j_it) {
506  int j = index(j_it);
507  xx[jdx] = x[j];
508  yy[jdx] = tmp[j];
509  jdx++;
510  }
511  Stokhos::multiply( matrix[k] , xx , yy, smo );
512  jdx = 0;
513  for (typename UnitTestSetup<Device>::Cijk_type::kj_iterator j_it = j_begin;
514  j_it != j_end; ++j_it) {
516  setup.Cijk->i_begin(j_it);
518  setup.Cijk->i_end(j_it);
519  for (typename UnitTestSetup<Device>::Cijk_type::kji_iterator i_it = i_begin;
520  i_it != i_end;
521  ++i_it) {
522  int i = index(i_it);
523  value_type c = value(i_it);
524  Stokhos::update( value_type(1.0) , y[i] , c , yy[jdx] );
525  }
526  jdx++;
527  }
528  }
529  }
530 
531  std::vector<typename vec_type::HostMirror> hy(setup.stoch_length);
532  for (int i=0; i<setup.stoch_length; ++i) {
533  hy[i] = Kokkos::create_mirror( y[i] );
534  Kokkos::deep_copy( hy[i] , y[i] );
535  }
536  bool success = setup.test_original(hy, out);
537 
538  return success;
539 }
540 
541 template <typename value_type, typename Device, typename SparseMatOps>
543  Teuchos::FancyOStream& out) {
544  typedef Stokhos::CrsMatrix<value_type,Device> matrix_type;
545  typedef typename matrix_type::values_type matrix_values_type;
546  typedef typename matrix_type::graph_type matrix_graph_type;
547  typedef Kokkos::View<value_type*, Kokkos::LayoutLeft, Device, Kokkos::MemoryUnmanaged> vec_type;
548  typedef Kokkos::View<value_type**, Kokkos::LayoutLeft, Device> multi_vec_type;
549 
550  //------------------------------
551 
552  std::vector<matrix_type> matrix( setup.stoch_length ) ;
553  multi_vec_type x( "x", setup.fem_length, setup.stoch_length ) ;
554  multi_vec_type y( "y", setup.fem_length, setup.stoch_length ) ;
555  multi_vec_type tmp_x( "tmp_x", setup.fem_length, setup.stoch_length ) ;
556  multi_vec_type tmp_y( "tmp_y", setup.fem_length, setup.stoch_length ) ;
557 
558  typename multi_vec_type::HostMirror hx = Kokkos::create_mirror( x );
559  typename multi_vec_type::HostMirror hy = Kokkos::create_mirror( y );
560 
561  for (int block=0; block<setup.stoch_length; ++block) {
562  matrix[block].graph = Kokkos::create_staticcrsgraph<matrix_graph_type>(
563  std::string("testing") , setup.fem_graph );
564 
565  matrix[block].values =
566  matrix_values_type( "matrix" , setup.fem_graph_length );
567 
568  typename matrix_values_type::HostMirror hM =
569  Kokkos::create_mirror( matrix[block].values );
570 
571  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
572  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
573  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM] ;
574 
575  hM(iEntryFEM) = generate_matrix_coefficient<value_type>(
576  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , block );
577  }
578  }
579 
580  Kokkos::deep_copy( matrix[block].values , hM );
581 
582  for ( int i = 0 ; i < setup.fem_length ; ++i ) {
583  hx(i, block) = generate_vector_coefficient<value_type>(
584  setup.fem_length , setup.stoch_length , i , block );
585  hy(i, block) = 0.0;
586  }
587 
588  }
589 
590  Kokkos::deep_copy( x , hx );
591  Kokkos::deep_copy( y , hy );
592 
593  // Original matrix-free multiply algorithm using a block apply
594  typedef typename UnitTestSetup<Device>::Cijk_type::k_iterator k_iterator;
595  typedef typename UnitTestSetup<Device>::Cijk_type::kj_iterator kj_iterator;
596  typedef typename UnitTestSetup<Device>::Cijk_type::kji_iterator kji_iterator;
597  SparseMatOps smo;
598  k_iterator k_begin = setup.Cijk->k_begin();
599  k_iterator k_end = setup.Cijk->k_end();
600  for (k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
601  unsigned nj = setup.Cijk->num_j(k_it);
602  if (nj > 0) {
603  int k = index(k_it);
604  kj_iterator j_begin = setup.Cijk->j_begin(k_it);
605  kj_iterator j_end = setup.Cijk->j_end(k_it);
606  std::vector<int> j_indices(nj);
607  unsigned jdx = 0;
608  for (kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
609  int j = index(j_it);
610  vec_type xx = Kokkos::subview( x, Kokkos::ALL(), j );
611  vec_type tt = Kokkos::subview( tmp_x, Kokkos::ALL(), jdx++ );
612  Kokkos::deep_copy(tt, xx);
613  }
614  multi_vec_type tmp_x_view =
615  Kokkos::subview( tmp_x, Kokkos::ALL(),
616  std::make_pair(0u,nj));
617  multi_vec_type tmp_y_view =
618  Kokkos::subview( tmp_y, Kokkos::ALL(),
619  std::make_pair(0u,nj));
620  Stokhos::multiply( matrix[k] , tmp_x_view , tmp_y_view, smo );
621  jdx = 0;
622  for (kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
623  vec_type tmp_y_view =
624  Kokkos::subview( tmp_y, Kokkos::ALL(), jdx++ );
625  kji_iterator i_begin = setup.Cijk->i_begin(j_it);
626  kji_iterator i_end = setup.Cijk->i_end(j_it);
627  for (kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
628  int i = index(i_it);
629  value_type c = value(i_it);
630  vec_type y_view = Kokkos::subview( y, Kokkos::ALL(), i );
631  Stokhos::update( value_type(1.0) , y_view , c , tmp_y_view );
632  }
633  }
634  }
635  }
636 
637  Kokkos::deep_copy( hy , y );
638  bool success = setup.test_original(hy, out);
639 
640  return success;
641 }
642 
643 #ifdef HAVE_STOKHOS_KOKKOSLINALG
644 
645 template <typename value_type, typename Device>
646 bool test_crs_matrix_free_kokkos(const UnitTestSetup<Device>& setup,
647  Teuchos::FancyOStream& out) {
648  typedef int ordinal_type;
649  typedef KokkosSparse::CrsMatrix<value_type,ordinal_type,Device> matrix_type;
650  typedef typename matrix_type::values_type matrix_values_type;
651  typedef typename matrix_type::StaticCrsGraphType matrix_graph_type;
652  typedef Kokkos::View<value_type*, Kokkos::LayoutLeft, Device, Kokkos::MemoryUnmanaged> vec_type;
653  typedef Kokkos::View<value_type**, Kokkos::LayoutLeft, Device> multi_vec_type;
654 
655  //------------------------------
656 
657  std::vector<matrix_type> matrix( setup.stoch_length ) ;
658  multi_vec_type x( "x", setup.fem_length, setup.stoch_length ) ;
659  multi_vec_type y( "y", setup.fem_length, setup.stoch_length ) ;
660  multi_vec_type tmp_x( "tmp_x", setup.fem_length, setup.stoch_length ) ;
661  multi_vec_type tmp_y( "tmp_y", setup.fem_length, setup.stoch_length ) ;
662 
663  typename multi_vec_type::HostMirror hx = Kokkos::create_mirror( x );
664  typename multi_vec_type::HostMirror hy = Kokkos::create_mirror( y );
665 
666  for (int block=0; block<setup.stoch_length; ++block) {
667  matrix_graph_type matrix_graph =
668  Kokkos::create_staticcrsgraph<matrix_graph_type>(
669  std::string("test crs graph"), setup.fem_graph);
670  matrix_values_type matrix_values =
671  matrix_values_type( "matrix" , setup.fem_graph_length );
672  typename matrix_values_type::HostMirror hM =
673  Kokkos::create_mirror( matrix_values );
674 
675  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
676  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
677  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM] ;
678 
679  hM(iEntryFEM) = generate_matrix_coefficient<value_type>(
680  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , block );
681  }
682  }
683 
684  Kokkos::deep_copy( matrix_values , hM );
685  matrix[block] = matrix_type("matrix", setup.fem_length, matrix_values,
686  matrix_graph);
687 
688  for ( int i = 0 ; i < setup.fem_length ; ++i ) {
689  hx(i, block) = generate_vector_coefficient<value_type>(
690  setup.fem_length , setup.stoch_length , i , block );
691  hy(i, block) = 0.0;
692  }
693 
694  }
695 
696  Kokkos::deep_copy( x , hx );
697  Kokkos::deep_copy( y , hy );
698 
699  // Original matrix-free multiply algorithm using a block apply
700  typedef typename UnitTestSetup<Device>::Cijk_type::k_iterator k_iterator;
701  typedef typename UnitTestSetup<Device>::Cijk_type::kj_iterator kj_iterator;
702  typedef typename UnitTestSetup<Device>::Cijk_type::kji_iterator kji_iterator;
703  k_iterator k_begin = setup.Cijk->k_begin();
704  k_iterator k_end = setup.Cijk->k_end();
705  for (k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
706  int nj = setup.Cijk->num_j(k_it);
707  if (nj > 0) {
708  int k = index(k_it);
709  kj_iterator j_begin = setup.Cijk->j_begin(k_it);
710  kj_iterator j_end = setup.Cijk->j_end(k_it);
711  unsigned jdx = 0;
712  for (kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
713  int j = index(j_it);
714  vec_type xx = Kokkos::subview( x, Kokkos::ALL(), j );
715  vec_type tt = Kokkos::subview( tmp_x, Kokkos::ALL(), jdx++ );
716  Kokkos::deep_copy(tt, xx);
717  }
718  multi_vec_type tmp_x_view =
719  Kokkos::subview( tmp_x, Kokkos::ALL(),
720  std::make_pair(0u,jdx));
721  multi_vec_type tmp_y_view =
722  Kokkos::subview( tmp_y, Kokkos::ALL(),
723  std::make_pair(0u,jdx));
724  KokkosSparse::spmv( "N", value_type(1.0), matrix[k] , tmp_x_view , value_type(0.0) , tmp_y_view );
725  jdx = 0;
726  for (kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
727  vec_type tmp_y_view =
728  Kokkos::subview( tmp_y, Kokkos::ALL(), jdx++ );
729  kji_iterator i_begin = setup.Cijk->i_begin(j_it);
730  kji_iterator i_end = setup.Cijk->i_end(j_it);
731  for (kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
732  int i = index(i_it);
733  value_type c = value(i_it);
734  vec_type y_view = Kokkos::subview( y, Kokkos::ALL(), i );
735  //Stokhos::update( value_type(1.0) , y_view , c , tmp_y_view );
736  KokkosBlas::update(c, tmp_y_view, value_type(1.0), y_view, value_type(0.0), y_view);
737  }
738  }
739  }
740  }
741 
742  Kokkos::deep_copy( hy , y );
743  bool success = setup.test_original(hy, out);
744 
745  return success;
746 }
747 
748 #endif
749 
750 template< typename ScalarType , class Device >
751 bool
754 {
755  typedef ScalarType value_type ;
756  typedef Kokkos::View< value_type**, Kokkos::LayoutLeft , Device > block_vector_type ;
757 
758  //------------------------------
759 
761 
762  typedef typename matrix_type::graph_type graph_type ;
763 
764  // Convert sparse Cijk to dense for faster assembly
765  typedef typename UnitTestSetup<Device>::Cijk_type::k_iterator k_iterator;
766  typedef typename UnitTestSetup<Device>::Cijk_type::kj_iterator kj_iterator;
767  typedef typename UnitTestSetup<Device>::Cijk_type::kji_iterator kji_iterator;
769  for (k_iterator k_it=setup.Cijk->k_begin();
770  k_it!=setup.Cijk->k_end(); ++k_it) {
771  int k = index(k_it);
772  for (kj_iterator j_it = setup.Cijk->j_begin(k_it);
773  j_it != setup.Cijk->j_end(k_it); ++j_it) {
774  int j = index(j_it);
775  for (kji_iterator i_it = setup.Cijk->i_begin(j_it);
776  i_it != setup.Cijk->i_end(j_it); ++i_it) {
777  int i = index(i_it);
778  double c = value(i_it);
779  dense_cijk(i,j,k) = c;
780  }
781  }
782  }
783 
784  //------------------------------
785  // Generate input multivector:
786 
787  block_vector_type x =
788  block_vector_type( "x" , setup.stoch_length , setup.fem_length );
789  block_vector_type y =
790  block_vector_type( "y" , setup.stoch_length , setup.fem_length );
791 
792  typename block_vector_type::HostMirror hx = Kokkos::create_mirror( x );
793 
794  for ( int iColFEM = 0 ; iColFEM < setup.fem_length ; ++iColFEM ) {
795  for ( int iColStoch = 0 ; iColStoch < setup.stoch_length ; ++iColStoch ) {
796  hx(iColStoch,iColFEM) =
797  generate_vector_coefficient<ScalarType>(
798  setup.fem_length , setup.stoch_length , iColFEM , iColStoch );
799  }
800  }
801 
802  Kokkos::deep_copy( x , hx );
803 
804  //------------------------------
805  // Generate CRS matrix of blocks with symmetric diagonal storage
806 
807  matrix_type matrix ;
808 
809  matrix.block =
811  matrix.graph = Kokkos::create_staticcrsgraph<graph_type>(
812  std::string("test crs graph") , setup.fem_graph );
813  matrix.values = block_vector_type(
814  "matrix" , matrix.block.matrix_size() , setup.fem_graph_length );
815 
816  {
817  typename block_vector_type::HostMirror hM =
818  Kokkos::create_mirror( matrix.values );
819 
820  for ( int iRowStoch = 0 ; iRowStoch < setup.stoch_length ; ++iRowStoch ) {
821  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
822 
823  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
824  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM];
825 
826  for ( int iColStoch = 0 ; iColStoch < setup.stoch_length ; ++iColStoch ) {
827 
828  const size_t offset =
829  matrix.block.matrix_offset( iRowStoch , iColStoch );
830 
831  ScalarType value = 0 ;
832 
833  for ( int k = 0 ; k < setup.stoch_length ; ++k ) {
834  value += dense_cijk( iRowStoch , iColStoch , k ) *
835  generate_matrix_coefficient<ScalarType>(
836  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , k );
837  }
838 
839  hM( offset , iEntryFEM ) = value ;
840  }
841  }
842 
843  }
844  }
845 
846  Kokkos::deep_copy( matrix.values , hM );
847  }
848 
849  //------------------------------
850 
851  Stokhos::multiply( matrix , x , y );
852 
853  typename block_vector_type::HostMirror hy = Kokkos::create_mirror( y );
854  Kokkos::deep_copy( hy , y );
855 
856  bool success = setup.test_commuted(hy, out);
857 
858  return success;
859 }
860 
861 template< typename ScalarType , class Device >
862 bool
865 {
866  typedef ScalarType value_type ;
867  typedef Kokkos::View< value_type* , Device > vector_type ;
868 
869  //------------------------------
870 
871  typedef Stokhos::CrsMatrix<value_type,Device> matrix_type;
872  typedef typename matrix_type::values_type matrix_values_type;
873  typedef typename matrix_type::graph_type matrix_graph_type;
874 
875  // Build stochastic graph
876  std::vector< std::vector< int > > stoch_graph( setup.stoch_length );
878  *setup.basis, *setup.Cijk, *setup.globalComm);
879  for ( int i = 0 ; i < setup.stoch_length ; ++i ) {
880  int len = cijk_graph->NumGlobalIndices(i);
881  stoch_graph[i].resize(len);
882  int len2;
883  cijk_graph->ExtractGlobalRowCopy(i, len, len2, &stoch_graph[i][0]);
884  }
885 
886  // Convert sparse Cijk to dense for faster assembly in debug builds
887  typedef typename UnitTestSetup<Device>::Cijk_type::k_iterator k_iterator;
888  typedef typename UnitTestSetup<Device>::Cijk_type::kj_iterator kj_iterator;
889  typedef typename UnitTestSetup<Device>::Cijk_type::kji_iterator kji_iterator;
891  for (k_iterator k_it=setup.Cijk->k_begin();
892  k_it!=setup.Cijk->k_end(); ++k_it) {
893  int k = index(k_it);
894  for (kj_iterator j_it = setup.Cijk->j_begin(k_it);
895  j_it != setup.Cijk->j_end(k_it); ++j_it) {
896  int j = index(j_it);
897  for (kji_iterator i_it = setup.Cijk->i_begin(j_it);
898  i_it != setup.Cijk->i_end(j_it); ++i_it) {
899  int i = index(i_it);
900  double c = value(i_it);
901  dense_cijk(i,j,k) = c;
902  }
903  }
904  }
905 
906  //------------------------------
907  // Generate flattened graph with FEM outer and stochastic inner
908 
909  const int flat_length = setup.fem_length * setup.stoch_length ;
910 
911  std::vector< std::vector<int> > flat_graph( flat_length );
912 
913  for ( int iOuterRow = 0 ; iOuterRow < setup.fem_length ; ++iOuterRow ) {
914 
915  const size_t iOuterRowNZ = setup.fem_graph[iOuterRow].size();
916 
917  for ( int iInnerRow = 0 ; iInnerRow < setup.stoch_length ; ++iInnerRow ) {
918 
919  const size_t iInnerRowNZ = stoch_graph[ iInnerRow ].size(); ;
920  const int iFlatRowNZ = iOuterRowNZ * iInnerRowNZ ;
921  const int iFlatRow = iInnerRow + iOuterRow * setup.stoch_length ;
922 
923  flat_graph[iFlatRow].resize( iFlatRowNZ );
924 
925  int iFlatEntry = 0 ;
926 
927  for ( size_t iOuterEntry = 0 ; iOuterEntry < iOuterRowNZ ; ++iOuterEntry ) {
928 
929  const int iOuterCol = setup.fem_graph[iOuterRow][iOuterEntry];
930 
931  for ( size_t iInnerEntry = 0 ; iInnerEntry < iInnerRowNZ ; ++iInnerEntry ) {
932 
933  const int iInnerCol = stoch_graph[iInnerRow][iInnerEntry] ;
934  const int iFlatColumn = iInnerCol + iOuterCol * setup.stoch_length ;
935 
936  flat_graph[iFlatRow][iFlatEntry] = iFlatColumn ;
937 
938  ++iFlatEntry ;
939  }
940  }
941  }
942  }
943 
944  //------------------------------
945 
946  vector_type x = vector_type( "x" , flat_length );
947  vector_type y = vector_type( "y" , flat_length );
948 
949  typename vector_type::HostMirror hx = Kokkos::create_mirror( x );
950 
951  for ( int iColFEM = 0 ; iColFEM < setup.fem_length ; ++iColFEM ) {
952  for ( int iColStoch = 0 ; iColStoch < setup.stoch_length ; ++iColStoch ) {
953  hx(iColStoch + iColFEM*setup.stoch_length) =
954  generate_vector_coefficient<ScalarType>(
955  setup.fem_length , setup.stoch_length , iColFEM , iColStoch );
956  }
957  }
958 
959  Kokkos::deep_copy( x , hx );
960 
961  //------------------------------
962 
963  matrix_type matrix ;
964 
965  matrix.graph = Kokkos::create_staticcrsgraph<matrix_graph_type>(
966  std::string("testing") , flat_graph );
967 
968  const size_t flat_graph_length = matrix.graph.entries.extent(0);
969 
970  matrix.values = matrix_values_type( "matrix" , flat_graph_length );
971  {
972  typename matrix_values_type::HostMirror hM =
973  Kokkos::create_mirror( matrix.values );
974 
975  for ( int iRow = 0 , iEntry = 0 ; iRow < flat_length ; ++iRow ) {
976  const int iRowFEM = iRow / setup.stoch_length ;
977  const int iRowStoch = iRow % setup.stoch_length ;
978 
979  for ( size_t iRowEntry = 0 ; iRowEntry < flat_graph[ iRow ].size() ; ++iRowEntry , ++iEntry ) {
980  const int iCol = flat_graph[ iRow ][ iRowEntry ];
981  const int iColFEM = iCol / setup.stoch_length ;
982  const int iColStoch = iCol % setup.stoch_length ;
983 
984  double value = 0 ;
985  for ( int k = 0 ; k < setup.stoch_length ; ++k ) {
986  const double A_fem_k =
987  generate_matrix_coefficient<ScalarType>(
988  setup.fem_length , setup.stoch_length , iRowFEM, iColFEM, k );
989  value += dense_cijk(iRowStoch,iColStoch,k) * A_fem_k ;
990  }
991  hM( iEntry ) = value ;
992  }
993  }
994 
995  Kokkos::deep_copy( matrix.values , hM );
996  }
997 
998  //------------------------------
999 
1000 
1001  Stokhos::multiply( matrix , x , y );
1002 
1003  typename vector_type::HostMirror hy = Kokkos::create_mirror( y );
1004  Kokkos::deep_copy( hy , y );
1005 
1006  bool success = setup.test_commuted_flat(hy, out);
1007  return success;
1008 }
1009 
1010 template< typename ScalarType , class Device >
1011 bool
1013  Teuchos::FancyOStream& out)
1014 {
1015  typedef ScalarType value_type ;
1016  typedef Kokkos::View< value_type* , Device > vector_type ;
1017 
1018  //------------------------------
1019 
1020  typedef Stokhos::CrsMatrix<value_type,Device> matrix_type;
1021  typedef typename matrix_type::values_type matrix_values_type;
1022  typedef typename matrix_type::graph_type matrix_graph_type;
1023 
1024  // Build stochastic graph
1025  std::vector< std::vector< int > > stoch_graph( setup.stoch_length );
1027  *setup.basis, *setup.Cijk, *setup.globalComm);
1028  for ( int i = 0 ; i < setup.stoch_length ; ++i ) {
1029  int len = cijk_graph->NumGlobalIndices(i);
1030  stoch_graph[i].resize(len);
1031  int len2;
1032  cijk_graph->ExtractGlobalRowCopy(i, len, len2, &stoch_graph[i][0]);
1033  }
1034 
1035  // Convert sparse Cijk to dense for faster assembly in debug builds
1036  typedef typename UnitTestSetup<Device>::Cijk_type::k_iterator k_iterator;
1037  typedef typename UnitTestSetup<Device>::Cijk_type::kj_iterator kj_iterator;
1038  typedef typename UnitTestSetup<Device>::Cijk_type::kji_iterator kji_iterator;
1040  for (k_iterator k_it=setup.Cijk->k_begin();
1041  k_it!=setup.Cijk->k_end(); ++k_it) {
1042  int k = index(k_it);
1043  for (kj_iterator j_it = setup.Cijk->j_begin(k_it);
1044  j_it != setup.Cijk->j_end(k_it); ++j_it) {
1045  int j = index(j_it);
1046  for (kji_iterator i_it = setup.Cijk->i_begin(j_it);
1047  i_it != setup.Cijk->i_end(j_it); ++i_it) {
1048  int i = index(i_it);
1049  double c = value(i_it);
1050  dense_cijk(i,j,k) = c;
1051  }
1052  }
1053  }
1054 
1055  //------------------------------
1056  // Generate flattened graph with stochastic outer and FEM inner
1057 
1058  const size_t flat_length = setup.fem_length * setup.stoch_length ;
1059 
1060  std::vector< std::vector<int> > flat_graph( flat_length );
1061 
1062  for ( int iOuterRow = 0 ; iOuterRow < setup.stoch_length ; ++iOuterRow ) {
1063 
1064  const size_t iOuterRowNZ = stoch_graph[iOuterRow].size();
1065 
1066  for ( int iInnerRow = 0 ; iInnerRow < setup.fem_length ; ++iInnerRow ) {
1067 
1068  const size_t iInnerRowNZ = setup.fem_graph[iInnerRow].size();
1069  const int iFlatRowNZ = iOuterRowNZ * iInnerRowNZ ;
1070  const int iFlatRow = iInnerRow + iOuterRow * setup.fem_length ;
1071 
1072  flat_graph[iFlatRow].resize( iFlatRowNZ );
1073 
1074  int iFlatEntry = 0 ;
1075 
1076  for ( size_t iOuterEntry = 0 ; iOuterEntry < iOuterRowNZ ; ++iOuterEntry ) {
1077 
1078  const int iOuterCol = stoch_graph[ iOuterRow ][ iOuterEntry ];
1079 
1080  for ( size_t iInnerEntry = 0 ; iInnerEntry < iInnerRowNZ ; ++iInnerEntry ) {
1081 
1082  const int iInnerCol = setup.fem_graph[ iInnerRow][iInnerEntry];
1083  const int iFlatColumn = iInnerCol + iOuterCol * setup.fem_length ;
1084 
1085  flat_graph[iFlatRow][iFlatEntry] = iFlatColumn ;
1086  ++iFlatEntry ;
1087  }
1088  }
1089  }
1090  }
1091 
1092  //------------------------------
1093 
1094  vector_type x = vector_type( "x" , flat_length );
1095  vector_type y = vector_type( "y" , flat_length );
1096 
1097  typename vector_type::HostMirror hx = Kokkos::create_mirror( x );
1098 
1099  for ( size_t iCol = 0 ; iCol < flat_length ; ++iCol ) {
1100  const int iColStoch = iCol / setup.fem_length ;
1101  const int iColFEM = iCol % setup.fem_length ;
1102 
1103  hx(iCol) = generate_vector_coefficient<ScalarType>(
1104  setup.fem_length , setup.stoch_length , iColFEM , iColStoch );
1105  }
1106 
1107  Kokkos::deep_copy( x , hx );
1108 
1109  //------------------------------
1110 
1111  matrix_type matrix ;
1112 
1113  matrix.graph = Kokkos::create_staticcrsgraph<matrix_graph_type>( std::string("testing") , flat_graph );
1114 
1115  const size_t flat_graph_length = matrix.graph.entries.extent(0);
1116 
1117  matrix.values = matrix_values_type( "matrix" , flat_graph_length );
1118  {
1119  typename matrix_values_type::HostMirror hM =
1120  Kokkos::create_mirror( matrix.values );
1121 
1122  for ( size_t iRow = 0 , iEntry = 0 ; iRow < flat_length ; ++iRow ) {
1123  const int iRowStoch = iRow / setup.fem_length ;
1124  const int iRowFEM = iRow % setup.fem_length ;
1125 
1126  for ( size_t iRowEntry = 0 ; iRowEntry < flat_graph[ iRow ].size() ; ++iRowEntry , ++iEntry ) {
1127  const int iCol = flat_graph[ iRow ][ iRowEntry ];
1128  const int iColStoch = iCol / setup.fem_length ;
1129  const int iColFEM = iCol % setup.fem_length ;
1130 
1131  double value = 0 ;
1132  for ( int k = 0 ; k < setup.stoch_length ; ++k ) {
1133  const double A_fem_k =
1134  generate_matrix_coefficient<ScalarType>(
1135  setup.fem_length , setup.stoch_length ,
1136  iRowFEM , iColFEM , k );
1137  value += dense_cijk(iRowStoch,iColStoch,k) * A_fem_k ;
1138  }
1139  hM( iEntry ) = value ;
1140 
1141  }
1142 
1143  }
1144 
1145  Kokkos::deep_copy( matrix.values , hM );
1146  }
1147 
1148  Stokhos::multiply( matrix , x , y );
1149 
1150  typename vector_type::HostMirror hy = Kokkos::create_mirror( y );
1151  Kokkos::deep_copy( hy , y );
1152 
1153  bool success = setup.test_original_flat(hy, out);
1154  return success;
1155 }
1156 
1157 template< typename ScalarType , typename TensorType, class Device >
1159  const UnitTestSetup<Device>& setup,
1160  Teuchos::FancyOStream& out,
1161  const Teuchos::ParameterList& params = Teuchos::ParameterList()) {
1162  typedef ScalarType value_type ;
1163  typedef Kokkos::View< value_type** , Kokkos::LayoutLeft ,
1164  Device > block_vector_type ;
1165 
1167 
1169  typedef typename matrix_type::graph_type graph_type ;
1170 
1171  //------------------------------
1172  // Generate input multivector:
1173 
1174  block_vector_type x =
1175  block_vector_type( "x" , setup.stoch_length_aligned , setup.fem_length );
1176  block_vector_type y =
1177  block_vector_type( "y" , setup.stoch_length_aligned , setup.fem_length );
1178 
1179  typename block_vector_type::HostMirror hx =
1180  Kokkos::create_mirror( x );
1181 
1182  for ( int iColFEM = 0 ; iColFEM < setup.fem_length ; ++iColFEM ) {
1183  for ( int iColStoch = 0 ; iColStoch < setup.stoch_length ; ++iColStoch ) {
1184  hx(setup.perm[iColStoch],iColFEM) =
1185  generate_vector_coefficient<ScalarType>(
1186  setup.fem_length , setup.stoch_length , iColFEM , iColStoch );
1187  }
1188  }
1189 
1190  Kokkos::deep_copy( x , hx );
1191 
1192  //------------------------------
1193 
1194  matrix_type matrix ;
1195 
1196  matrix.block =
1197  Stokhos::create_stochastic_product_tensor< TensorType >( *setup.basis,
1198  *setup.Cijk,
1199  params);
1200 
1201  matrix.graph = Kokkos::create_staticcrsgraph<graph_type>(
1202  std::string("test crs graph") , setup.fem_graph );
1203 
1204  matrix.values = block_vector_type(
1205  "matrix" , setup.stoch_length_aligned , setup.fem_graph_length );
1206 
1207  typename block_vector_type::HostMirror hM =
1208  Kokkos::create_mirror( matrix.values );
1209 
1210  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
1211  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
1212  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM] ;
1213 
1214  for ( int k = 0 ; k < setup.stoch_length ; ++k ) {
1215  hM(setup.perm[k],iEntryFEM) =
1216  generate_matrix_coefficient<ScalarType>(
1217  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , k );
1218  //hM(k,iEntryFEM) = 1.0;
1219  }
1220  }
1221  }
1222 
1223  Kokkos::deep_copy( matrix.values , hM );
1224 
1225  //------------------------------
1226 
1227  Stokhos::multiply( matrix , x , y );
1228 
1229  typename block_vector_type::HostMirror hy = Kokkos::create_mirror( y );
1230  Kokkos::deep_copy( hy , y );
1231 
1232  bool success = setup.test_commuted_perm(hy, out);
1233  //bool success = true;
1234  return success;
1235 }
1236 
1237 template< typename ScalarType , class Device , int BlockSize >
1239  Teuchos::FancyOStream& out,
1240  const bool symmetric) {
1241  typedef ScalarType value_type ;
1242  typedef Kokkos::View< value_type** , Kokkos::LayoutLeft ,
1243  Device > block_vector_type ;
1246 
1248  typedef typename matrix_type::graph_type graph_type ;
1249 
1250  // Build tensor
1251  matrix_type matrix ;
1252 
1253  Teuchos::ParameterList params;
1254  params.set("Symmetric",symmetric);
1255  matrix.block =
1256  Stokhos::create_stochastic_product_tensor< TensorType >( *setup.basis,
1257  *setup.Cijk,
1258  params );
1259  int aligned_stoch_length = matrix.block.tensor().aligned_dimension();
1260 
1261  //------------------------------
1262  // Generate input multivector:
1263 
1264  block_vector_type x =
1265  block_vector_type( "x" , aligned_stoch_length , setup.fem_length );
1266  block_vector_type y =
1267  block_vector_type( "y" , aligned_stoch_length , setup.fem_length );
1268 
1269  typename block_vector_type::HostMirror hx =
1270  Kokkos::create_mirror( x );
1271 
1272  for ( int iColFEM = 0 ; iColFEM < setup.fem_length ; ++iColFEM ) {
1273  for ( int iColStoch = 0 ; iColStoch < setup.stoch_length ; ++iColStoch ) {
1274  hx(iColStoch,iColFEM) =
1275  generate_vector_coefficient<ScalarType>(
1276  setup.fem_length , setup.stoch_length , iColFEM , iColStoch );
1277  //hx(iColStoch,iColFEM) = 1.0;
1278  }
1279  }
1280 
1281  Kokkos::deep_copy( x , hx );
1282 
1283  //------------------------------
1284 
1285  matrix.graph = Kokkos::create_staticcrsgraph<graph_type>(
1286  std::string("test crs graph") , setup.fem_graph );
1287 
1288  matrix.values = block_vector_type(
1289  "matrix" , aligned_stoch_length , setup.fem_graph_length );
1290 
1291  typename block_vector_type::HostMirror hM =
1292  Kokkos::create_mirror( matrix.values );
1293 
1294  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
1295  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
1296  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM] ;
1297 
1298  for ( int k = 0 ; k < setup.stoch_length ; ++k ) {
1299  hM(k,iEntryFEM) =
1300  generate_matrix_coefficient<ScalarType>(
1301  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , k );
1302  //hM(k,iEntryFEM) = 1.0;
1303  }
1304  }
1305  }
1306 
1307  Kokkos::deep_copy( matrix.values , hM );
1308 
1309  //------------------------------
1310 
1311  Stokhos::multiply( matrix , x , y );
1312 
1313  typename block_vector_type::HostMirror hy = Kokkos::create_mirror( y );
1314  Kokkos::deep_copy( hy , y );
1315 
1316  bool success = setup.test_commuted(hy, out);
1317  //bool success = true;
1318  return success;
1319 }
1320 
1321 template< typename ScalarType , class Device >
1323  Teuchos::FancyOStream& out) {
1324  typedef ScalarType value_type ;
1325  typedef int ordinal_type;
1326  typedef Kokkos::View< value_type** , Kokkos::LayoutLeft ,
1327  Device > block_vector_type ;
1330 
1332  typedef typename matrix_type::graph_type graph_type ;
1333 
1334  //------------------------------
1335  // Generate input multivector:
1336 
1337  block_vector_type x =
1338  block_vector_type( "x" , setup.stoch_length , setup.fem_length );
1339  block_vector_type y =
1340  block_vector_type( "y" , setup.stoch_length , setup.fem_length );
1341 
1342  typename block_vector_type::HostMirror hx =
1343  Kokkos::create_mirror( x );
1344 
1345  for ( int iColFEM = 0 ; iColFEM < setup.fem_length ; ++iColFEM ) {
1346  for ( int iColStoch = 0 ; iColStoch < setup.stoch_length ; ++iColStoch ) {
1347  hx(iColStoch,iColFEM) =
1348  generate_vector_coefficient<ScalarType>(
1349  setup.fem_length , setup.stoch_length , iColFEM , iColStoch );
1350  }
1351  }
1352 
1353  Kokkos::deep_copy( x , hx );
1354 
1355  //------------------------------
1356 
1357  matrix_type matrix ;
1358 
1359  /*
1360  typedef UnitTestSetup<Device>::abstract_basis_type abstract_basis_type;
1361  typedef UnitTestSetup<Device>::basis_type basis_type;
1362  typedef Stokhos::LexographicLess< Stokhos::MultiIndex<int> > less_type;
1363  typedef Stokhos::TotalOrderBasis<ordinal_type,value_type,less_type> product_basis_type;
1364  Teuchos::Array< Teuchos::RCP<const abstract_basis_type> > bases(setup.d);
1365  for (int i=0; i<setup.d; i++)
1366  bases[i] = rcp(new basis_type(setup.p,true));
1367  product_basis_type basis(bases, 1e-12);
1368  */
1369  const bool symmetric = true;
1372 
1373  matrix.block =
1374  Stokhos::create_stochastic_product_tensor< TensorType >( *setup.basis,
1375  *Cijk );
1376 
1377  matrix.graph = Kokkos::create_staticcrsgraph<graph_type>(
1378  std::string("test crs graph") , setup.fem_graph );
1379 
1380  matrix.values = block_vector_type(
1381  "matrix" , setup.stoch_length , setup.fem_graph_length );
1382 
1383  typename block_vector_type::HostMirror hM =
1384  Kokkos::create_mirror( matrix.values );
1385 
1386  for ( int iRowFEM = 0 , iEntryFEM = 0 ; iRowFEM < setup.fem_length ; ++iRowFEM ) {
1387  for ( size_t iRowEntryFEM = 0 ; iRowEntryFEM < setup.fem_graph[iRowFEM].size() ; ++iRowEntryFEM , ++iEntryFEM ) {
1388  const int iColFEM = setup.fem_graph[iRowFEM][iRowEntryFEM] ;
1389 
1390  for ( int k = 0 ; k < setup.stoch_length ; ++k ) {
1391  hM(k,iEntryFEM) =
1392  generate_matrix_coefficient<ScalarType>(
1393  setup.fem_length , setup.stoch_length , iRowFEM , iColFEM , k );
1394  }
1395  }
1396  }
1397 
1398  Kokkos::deep_copy( matrix.values , hM );
1399 
1400  //------------------------------
1401 
1402  Stokhos::multiply( matrix , x , y );
1403 
1404  typename block_vector_type::HostMirror hy = Kokkos::create_mirror( y );
1405  Kokkos::deep_copy( hy , y );
1406 
1407  bool success = setup.test_commuted(hy, out);
1408  return success;
1409 }
1410 
1411 }
1412 
1413 #endif
IntType map_fem_graph_coord(const IntType &N, const IntType &i, const IntType &j, const IntType &k)
Stokhos::Sparse3Tensor< int, value_type > Cijk_type
An Epetra operator representing the block stochastic Galerkin operator.
Bases defined by combinatorial product of polynomial bases.
A container class storing an orthogonal polynomial whose coefficients are vectors, operators, or in general any type that would have an expensive copy constructor.
k_iterator k_begin() const
Iterator pointing to first k entry.
Multivariate orthogonal polynomial basis generated from a total order tensor product of univariate po...
int NumGlobalIndices(long long Row) const
bool test_lexo_block_tensor(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)
Teuchos::RCP< const EpetraExt::MultiComm > getMultiComm() const
Get global comm.
ordinal_type num_j(const k_iterator &k) const
Number of j entries in C(i,j,k) for given k.
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
int MyGlobalElements(int *MyGlobalElementList) const
void init(const value_type &val)
Initialize coefficients.
Teuchos::RCP< EpetraExt::BlockVector > getBlockVector()
Get block vector.
bool test_crs_product_tensor(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out, const Teuchos::ParameterList &params=Teuchos::ParameterList())
kj_iterator j_begin(const k_iterator &k) const
Iterator pointing to first j entry for given k.
bool test_crs_flat_commuted(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)
bool test_original_flat(const vec_type &y, Teuchos::FancyOStream &out) const
bool test_commuted(const vec_type &y, Teuchos::FancyOStream &out) const
Stokhos::OneDOrthogPolyBasis< int, value_type > abstract_basis_type
Symmetric diagonal storage for a dense matrix.
scalar generate_vector_coefficient(const ordinal nFEM, const ordinal nStoch, const ordinal iColFEM, const ordinal iStoch)
Teuchos::Array< ordinal_type > index
index terms
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Stokhos::TotalOrderBasis< int, value_type, less_type > product_basis_type
Teuchos::RCP< LTBSparse3Tensor< ordinal_type, value_type > > computeTripleProductTensorLTBBlockLeaf(const TotalOrderBasis< ordinal_type, value_type, LexographicLess< MultiIndex< ordinal_type > > > &product_basis, bool symmetric=false)
int InsertGlobalIndices(int_type GlobalRow, int NumIndices, int_type *Indices)
Teuchos::RCP< const Epetra_Comm > getStochasticComm() const
Get stochastic comm.
int FillComplete(bool OptimizeDataStorage=true)
Teuchos::RCP< const Stokhos::EpetraSparse3Tensor > getEpetraCijk() const
Get Epetra Cijk.
kj_iterator j_end(const k_iterator &k) const
Iterator pointing to last j entry for given k.
Bi-directional iterator for traversing a sparse array.
bool test_linear_tensor(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out, const bool symmetric)
void multiply(const CrsMatrix< MatrixValue, Device, Layout > &A, const InputMultiVectorType &x, OutputMultiVectorType &y, const std::vector< OrdinalType > &col_indices, SingleColumnMultivectorMultiply)
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
int NumMyElements() const
A multidimensional index.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Teuchos::RCP< const Epetra_BlockMap > getStochasticRowMap() const
Get stochastic row map.
A container class storing an orthogonal polynomial whose coefficients are vectors, operators, or in general any type that would have an expensive copy constructor.
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
A container class for products of Epetra_Vector&#39;s.
bool test_crs_flat_original(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)
Sparse product tensor with replicated entries to provide subsets with a given coordinate.
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)
virtual int Apply(const Epetra_MultiVector &Input, Epetra_MultiVector &Result) const
Returns the result of a Epetra_Operator applied to a Epetra_MultiVector Input in Result as described ...
void resize(size_type new_size, const value_type &x=value_type())
bool test_original(const std::vector< vec_type > &y, Teuchos::FancyOStream &out) const
Stokhos::LexographicLess< Stokhos::MultiIndex< int > > less_type
k_iterator k_end() const
Iterator pointing to last k entry.
Legendre polynomial basis.
scalar generate_matrix_coefficient(const ordinal nFEM, const ordinal nStoch, const ordinal iRowFEM, const ordinal iColFEM, const ordinal iStoch)
bool test_original(const multi_vec_type &y, Teuchos::FancyOStream &out) const
Abstract base class for 1-D orthogonal polynomials.
Teuchos::RCP< Epetra_CrsGraph > sparse3Tensor2CrsGraph(const Stokhos::OrthogPolyBasis< ordinal_type, value_type > &basis, const Stokhos::Sparse3Tensor< ordinal_type, value_type > &Cijk, const Epetra_Comm &comm)
Build an Epetra_CrsGraph from a sparse 3 tensor.
ordinal generate_fem_graph(ordinal N, std::vector< std::vector< ordinal > > &graph)
std::enable_if< Kokkos::is_view_uq_pce< Kokkos::View< XD, XP...> >::value &&Kokkos::is_view_uq_pce< Kokkos::View< YD, YP...> >::value &&Kokkos::is_view_uq_pce< Kokkos::View< ZD, ZP...> >::value >::type update(const typename Kokkos::View< XD, XP...>::array_type::non_const_value_type &alpha, const Kokkos::View< XD, XP...> &x, const typename Kokkos::View< YD, YP...>::array_type::non_const_value_type &beta, const Kokkos::View< YD, YP...> &y, const typename Kokkos::View< ZD, ZP...>::array_type::non_const_value_type &gamma, const Kokkos::View< ZD, ZP...> &z)
CRS matrix of dense blocks.
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)
A comparison functor implementing a strict weak ordering based lexographic ordering.
Teuchos::RCP< const Epetra_Comm > getSpatialComm() const
Get spatial comm.
Stokhos::LegendreBasis< int, value_type > basis_type
Sacado::MP::Vector< storage_type > vec_type
int ExtractGlobalRowCopy(int_type Row, int LenOfIndices, int &NumIndices, int_type *Indices) const
virtual void setupOperator(const Teuchos::RCP< Stokhos::EpetraOperatorOrthogPoly > &poly)
Setup operator.
bool test_commuted_perm(const vec_type &y, Teuchos::FancyOStream &out) const
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.
virtual int ReplaceGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
Stokhos::CrsMatrix< ValueType, Device, Layout >::HostMirror create_mirror(const Stokhos::CrsMatrix< ValueType, Device, Layout > &A)
void update(const ValueType &alpha, VectorType &x, const ValueType &beta, const VectorType &y)
bool test_commuted_flat(const vec_type &y, Teuchos::FancyOStream &out) const
bool test_crs_matrix_free(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)
RCP< Stokhos::Sparse3Tensor< int, double > > Cijk
bool test_crs_matrix_free_view(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)
bool test_crs_dense_block(const UnitTestSetup< Device > &setup, Teuchos::FancyOStream &out)