Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TestEpetraMatrixFreeApply.cpp
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 #include <string>
11 #include <iostream>
12 #include <cstdlib>
13 
14 #include "Epetra_config.h"
15 #ifdef HAVE_MPI
16 # include "Epetra_MpiComm.h"
17 #else
18 # include "Epetra_SerialComm.h"
19 #endif
20 
21 // Stokhos Stochastic Galerkin
22 #include "Stokhos_Epetra.hpp"
23 #include "EpetraExt_BlockUtility.h"
24 
29 
30 template< typename IntType >
31 inline
32 IntType map_fem_graph_coord( const IntType & N ,
33  const IntType & i ,
34  const IntType & j ,
35  const IntType & k )
36 {
37  return k + N * ( j + N * i );
38 }
39 
40 template < typename ordinal >
41 inline
42 ordinal generate_fem_graph( ordinal N ,
44 {
45  graph.resize( N * N * N , Teuchos::Array<ordinal>() );
46 
47  ordinal total = 0 ;
48 
49  for ( int i = 0 ; i < (int) N ; ++i ) {
50  for ( int j = 0 ; j < (int) N ; ++j ) {
51  for ( int k = 0 ; k < (int) N ; ++k ) {
52 
53  const ordinal row = map_fem_graph_coord((int)N,i,j,k);
54 
55  graph[row].reserve(27);
56 
57  for ( int ii = -1 ; ii < 2 ; ++ii ) {
58  for ( int jj = -1 ; jj < 2 ; ++jj ) {
59  for ( int kk = -1 ; kk < 2 ; ++kk ) {
60  if ( 0 <= i + ii && i + ii < (int) N &&
61  0 <= j + jj && j + jj < (int) N &&
62  0 <= k + kk && k + kk < (int) N ) {
63  ordinal col = map_fem_graph_coord((int)N,i+ii,j+jj,k+kk);
64 
65  graph[row].push_back(col);
66  }
67  }}}
68  total += graph[row].size();
69  }}}
70 
71  return total ;
72 }
73 
76  const Teuchos::Array<int> & var_degree ,
77  const int nGrid ,
78  const int iterCount ,
79  const bool print_flag ,
80  const bool test_block ,
81  const bool check )
82 {
83  typedef double value_type ;
84  typedef Stokhos::OneDOrthogPolyBasis<int,value_type> abstract_basis_type;
86  typedef Stokhos::CompletePolynomialBasis<int,value_type> product_basis_type;
88 
89  using Teuchos::rcp;
90  using Teuchos::RCP;
91  using Teuchos::Array;
93 
94  // Create a communicator for Epetra objects
95  RCP<const Epetra_Comm> globalComm;
96 #ifdef HAVE_MPI
97  RCP<const Epetra_MpiComm> globalMpiComm =
98  rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
99  //globalMpiComm->Print(std::cout);
100  globalComm = globalMpiComm;
101 #else
102  RCP<const Epetra_SerialComm> globalSerialComm =
103  rcp(new Epetra_SerialComm);
104  //globalSerialComm->Print(std::cout);
105  globalComm = globalSerialComm;
106 #endif
107 
108  //int MyPID = globalComm->MyPID();
109 
110  // Create Stochastic Galerkin basis and expansion
111  const size_t num_KL = var_degree.size();
112  Array< RCP<const abstract_basis_type> > bases(num_KL);
113  for (size_t i=0; i<num_KL; i++)
114  bases[i] = rcp(new basis_type(var_degree[i],true));
115  RCP<const product_basis_type> basis =
116  rcp(new product_basis_type(bases, 1e-12));
117  const size_t stoch_length = basis->size();
118  RCP<Cijk_type> Cijk = basis->computeTripleProductTensor();
119 
120  // Create stochastic parallel distribution
121  ParameterList parallelParams;
122  RCP<Stokhos::ParallelData> sg_parallel_data =
123  rcp(new Stokhos::ParallelData(basis, Cijk, globalComm, parallelParams));
124  RCP<const EpetraExt::MultiComm> sg_comm =
125  sg_parallel_data->getMultiComm();
126  RCP<const Epetra_Comm> app_comm =
127  sg_parallel_data->getSpatialComm();
128  RCP<const Stokhos::EpetraSparse3Tensor> epetraCijk =
129  sg_parallel_data->getEpetraCijk();
130  RCP<const Epetra_BlockMap> stoch_row_map =
131  epetraCijk->getStochasticRowMap();
132 
133  //------------------------------
134  // Generate FEM graph:
135 
137 
138  const size_t fem_length = nGrid * nGrid * nGrid ;
139  generate_fem_graph( nGrid , fem_graph );
140 
141  //------------------------------
142 
143  // Generate Epetra objects
144  RCP<const Epetra_Map> x_map = rcp(new Epetra_Map(static_cast<int>(fem_length), 0, *app_comm));
145  RCP<const Epetra_Map> sg_x_map =
146  rcp(EpetraExt::BlockUtility::GenerateBlockMap(
147  *x_map, *stoch_row_map, *sg_comm));
148 
149  RCP<Epetra_CrsGraph> graph = rcp(new Epetra_CrsGraph(Copy, *x_map, 27));
150  int *my_GIDs = x_map->MyGlobalElements();
151  int num_my_GIDs = x_map->NumMyElements();
152  for (int i=0; i<num_my_GIDs; ++i) {
153  int row = my_GIDs[i];
154  int num_indices = fem_graph[row].size();
155  int *indices = &(fem_graph[row][0]);
156  graph->InsertGlobalIndices(row, num_indices, indices);
157  }
158  graph->FillComplete();
159  int nnz = graph->NumGlobalNonzeros();
160 
161  RCP<ParameterList> sg_op_params = rcp(new ParameterList);
162  RCP<Stokhos::MatrixFreeOperator> sg_A =
163  rcp(new Stokhos::MatrixFreeOperator(sg_comm, basis, epetraCijk,
164  x_map, x_map, sg_x_map, sg_x_map,
165  sg_op_params));
166  RCP<Epetra_BlockMap> sg_A_overlap_map =
167  rcp(new Epetra_LocalMap(
168  static_cast<int>(stoch_length), 0, *(sg_parallel_data->getStochasticComm())));
169  RCP< Stokhos::EpetraOperatorOrthogPoly > A_sg_blocks =
171  basis, sg_A_overlap_map, x_map, x_map, sg_x_map, sg_comm));
172  for (unsigned int i=0; i<stoch_length; i++) {
173  RCP<Epetra_CrsMatrix> A = rcp(new Epetra_CrsMatrix(Copy, *graph));
174  A->FillComplete();
175  A->PutScalar(1.0);
176  A_sg_blocks->setCoeffPtr(i, A);
177  }
178  sg_A->setupOperator(A_sg_blocks);
179 
180  RCP<Stokhos::EpetraVectorOrthogPoly> sg_x =
182  basis, stoch_row_map, x_map, sg_x_map, sg_comm));
183  RCP<Stokhos::EpetraVectorOrthogPoly> sg_y =
185  basis, stoch_row_map, x_map, sg_x_map, sg_comm));
186  sg_x->init(1.0);
187  sg_y->init(0.0);
188 
189 
190  // Time apply
191  Teuchos::Time clock("apply") ;
192  clock.start();
193  for ( int iter = 0 ; iter < iterCount ; ++iter ) {
194  sg_A->Apply( *(sg_x->getBlockVector()), *(sg_y->getBlockVector()) );
195  }
196  clock.stop();
197  double seconds_per_iter =
198  clock.totalElapsedTime() / ((double) iterCount );
199 
200  // Averge time across proc's
201  double average_seconds_per_iter;
202  globalComm->SumAll(&seconds_per_iter, &average_seconds_per_iter, 1);
203  average_seconds_per_iter /= globalComm->NumProc();
204 
205  // Compute number of fem mat-vec's
206  int n_apply = 0;
207  int n_add = 0;
208  for (Cijk_type::k_iterator k_it=Cijk->k_begin();
209  k_it!=Cijk->k_end(); ++k_it) {
210  for (Cijk_type::kj_iterator j_it = Cijk->j_begin(k_it);
211  j_it != Cijk->j_end(k_it); ++j_it) {
212  ++n_apply;
213  for (Cijk_type::kji_iterator i_it = Cijk->i_begin(j_it);
214  i_it != Cijk->i_end(j_it); ++i_it) {
215  ++n_add;
216  }
217  }
218  }
219 
220  const double flops = 1.0e-9*(2.0*static_cast<double>(n_apply)*nnz +
221  static_cast<double>(n_add)*fem_length);
222 
223  //------------------------------
224 
225  Teuchos::Array<double> perf(8);
226  perf[0] = stoch_length;
227  perf[1] = fem_length;
228  perf[2] = stoch_length * fem_length;
229  perf[3] = Cijk->num_entries();
230  perf[4] = nnz;
231  perf[5] = average_seconds_per_iter ;
232  perf[6] = flops/average_seconds_per_iter;
233  perf[7] = flops;
234 
235  return perf;
236 }
237 
238 void performance_test_driver_epetra( const int pdeg ,
239  const int minvar ,
240  const int maxvar ,
241  const int nGrid ,
242  const int nIter ,
243  const bool print ,
244  const bool test_block ,
245  const bool check ,
247 {
248  out.precision(8);
249 
250  //------------------------------
251 
252  out << std::endl
253  << "\"#nGrid\" , \"NNZ\" "
254  << "\"#Variable\" , \"PolyDegree\" , \"#Bases\" , "
255  << "\"#TensorEntry\" , "
256  << "\"VectorSize\" , "
257  << "\"Original-Matrix-Free-Block-MXV-Time\" , "
258  << "\"Original-Matrix-Free-Block-MXV-GFLOPS\" , "
259  << std::endl ;
260 
261  for ( int nvar = minvar ; nvar <= maxvar ; ++nvar ) {
262  Teuchos::Array<int> var_degree( nvar , pdeg );
263 
264  const Teuchos::Array<double> perf_original_mat_free_epetra =
265  test_original_matrix_free_epetra( var_degree , nGrid , nIter , print , test_block , check );
266 
267  out << nGrid << " , "
268  << perf_original_mat_free_epetra[4] << " , "
269  << nvar << " , " << pdeg << " , "
270  << perf_original_mat_free_epetra[0] << " , "
271  << perf_original_mat_free_epetra[3] << " , "
272  << perf_original_mat_free_epetra[2] << " , "
273  << perf_original_mat_free_epetra[5] << " , "
274  << perf_original_mat_free_epetra[6] << " , "
275  << std::endl ;
276 
277  }
278 
279 
280 }
281 
282 int main(int argc, char *argv[])
283 {
284  bool success = true;
285 
286  try {
287  Teuchos::GlobalMPISession mpiSession(&argc, &argv, NULL);
289  Teuchos::VerboseObjectBase::getDefaultOStream();
290 
291  // Setup command line options
293  int p = 3;
294  CLP.setOption("p", &p, "Polynomial order");
295  int d_min = 1;
296  CLP.setOption("dmin", &d_min, "Starting stochastic dimension");
297  int d_max = 12;
298  CLP.setOption("dmax", &d_max, "Ending stochastic dimension");
299  int nGrid = 64;
300  CLP.setOption("n", &nGrid, "Number of spatial grid points in each dimension");
301  int nIter = 1;
302  CLP.setOption("niter", &nIter, "Number of iterations");
303  bool test_block = true;
304  CLP.setOption("block", "no-block", &test_block, "Use block algorithm");
305  CLP.parse( argc, argv );
306 
307  bool print = false ;
308  bool check = false;
310  p , d_min , d_max , nGrid , nIter , print , test_block , check , *out );
311  }
312  TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, success);
313 
314  if (!success)
315  return -1;
316  return 0;
317 }
318 
An Epetra operator representing the block stochastic Galerkin operator.
A container class storing an orthogonal polynomial whose coefficients are vectors, operators, or in general any type that would have an expensive copy constructor.
Data structure storing a sparse 3-tensor C(i,j,k) in a a compressed format.
ordinal generate_fem_graph(ordinal N, std::vector< std::vector< ordinal > > &graph)
Definition: TestEpetra.cpp:45
IntType map_fem_graph_coord(const IntType &N, const IntType &i, const IntType &j, const IntType &k)
Definition: TestEpetra.cpp:35
int check(Epetra_CrsGraph &A, int NumMyRows1, int NumGlobalRows1, int NumMyNonzeros1, int NumGlobalNonzeros1, int *MyGlobalElements, bool verbose)
Stokhos::LegendreBasis< int, double > basis_type
void start(bool reset=false)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
double stop()
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
A container class storing an orthogonal polynomial whose coefficients are vectors, operators, or in general any type that would have an expensive copy constructor.
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
Multivariate orthogonal polynomial basis generated from a total-order complete-polynomial tensor prod...
Legendre polynomial basis.
Stokhos::Sparse3Tensor< int, double > Cijk_type
int main(int argc, char **argv)
Teuchos::Array< double > test_original_matrix_free_epetra(const Teuchos::Array< int > &var_degree, const int nGrid, const int iterCount, const bool print_flag, const bool test_block, const bool check)
void performance_test_driver_epetra(const int pdeg, const int minvar, const int maxvar, const int nGrid, const int nIter, const bool print, const bool test_block, const bool check, Teuchos::FancyOStream &out)
Abstract base class for 1-D orthogonal polynomials.
size_type size() const
double totalElapsedTime(bool readCurrentTime=false) const