Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cijk_nonzeros.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 "Stokhos_Epetra.hpp"
12 
13 #ifdef HAVE_MPI
14 #include "Epetra_MpiComm.h"
15 #else
16 #include "Epetra_SerialComm.h"
17 #endif
18 
19 // sparsity_example
20 //
21 // usage:
22 // sparsity_example [options]
23 //
24 // output:
25 // prints the sparsity of the sparse 3 tensor specified by the basis,
26 // dimension, order, given by summing over the third index, to a matrix
27 // market file. This sparsity pattern yields the sparsity of the block
28 // stochastic Galerkin matrix which can be visualized, e.g., by matlab.
29 // The full/linear flag determines whether the third index ranges over
30 // the full polynomial dimension, or only over the zeroth and first order
31 // terms.
32 
33 // Basis types
35 const int num_basis_types = 6;
38 const char *basis_type_names[] = {
39  "hermite", "legendre", "clenshaw-curtis", "gauss-patterson", "rys", "jacobi" };
40 
41 // Growth policies
42 const int num_growth_types = 2;
45 const char *growth_type_names[] = { "slow", "moderate" };
46 
47 // Product Basis types
49 const int num_prod_basis_types = 4;
52 const char *prod_basis_type_names[] = {
53  "complete", "tensor", "total", "smolyak" };
54 
55 using Teuchos::Array;
56 using Teuchos::RCP;
57 using Teuchos::rcp;
58 
59 struct CijkNonzeros {
60  int i, total_nz;
62 };
63 
64 struct NZCompare {
65  bool operator() (const CijkNonzeros& a,
66  const CijkNonzeros& b) const {
67  return (a.total_nz == b.total_nz) ? (a.i < b.i) : (a.total_nz > b.total_nz) ;
68  }
69 };
70 
71 struct NZPairCompare {
72  bool operator() (const std::pair<int,int>& a,
73  const std::pair<int,int>& b) const {
74  return (a.second == b.second) ? (a.first < b.first) : (a.second > b.second);
75  }
76 };
77 
78 int main(int argc, char **argv)
79 {
80  try {
81 
82  // Initialize MPI
83 #ifdef HAVE_MPI
84  MPI_Init(&argc,&argv);
85 #endif
86 
87  // Setup command line options
89  CLP.setDocString(
90  "This example generates the sparsity pattern for the block stochastic Galerkin matrix.\n");
91  int d = 3;
92  CLP.setOption("dimension", &d, "Stochastic dimension");
93  int p = 5;
94  CLP.setOption("order", &p, "Polynomial order");
95  double drop = 1.0e-12;
96  CLP.setOption("drop", &drop, "Drop tolerance");
97  std::string file = "A.mm";
98  CLP.setOption("filename", &file, "Matrix Market filename");
100  CLP.setOption("basis", &basis_type,
102  "Basis type");
104  CLP.setOption("growth", &growth_type,
106  "Growth type");
107  ProductBasisType prod_basis_type = COMPLETE;
108  CLP.setOption("product_basis", &prod_basis_type,
111  "Product basis type");
112  double alpha = 1.0;
113  CLP.setOption("alpha", &alpha, "Jacobi alpha index");
114  double beta = 1.0;
115  CLP.setOption("beta", &beta, "Jacobi beta index");
116  bool full = true;
117  CLP.setOption("full", "linear", &full, "Use full or linear expansion");
118  bool use_old = false;
119  CLP.setOption("old", "new", &use_old, "Use old or new Cijk algorithm");
120  int tile_size = 100;
121  CLP.setOption("tile_size", &tile_size, "Tile size");
122 
123  // Parse arguments
124  CLP.parse( argc, argv );
125 
126  // Basis
128  for (int i=0; i<d; i++) {
129  if (basis_type == HERMITE)
131  p, true, growth_type));
132  else if (basis_type == LEGENDRE)
134  p, true, growth_type));
135  else if (basis_type == CC_LEGENDRE)
136  bases[i] =
138  p, true));
139  else if (basis_type == GP_LEGENDRE)
140  bases[i] =
142  p, true));
143  else if (basis_type == RYS)
145  p, 1.0, true, growth_type));
146  else if (basis_type == JACOBI)
148  p, alpha, beta, true, growth_type));
149  }
151  if (prod_basis_type == COMPLETE)
152  basis =
154  bases, drop, use_old));
155  else if (prod_basis_type == TENSOR)
156  basis =
158  bases, drop));
159  else if (prod_basis_type == TOTAL)
160  basis =
162  bases, drop));
163  else if (prod_basis_type == SMOLYAK) {
164  Stokhos::TotalOrderIndexSet<int> index_set(d, p);
165  basis =
167  bases, index_set, drop));
168  }
169 
170  // Triple product tensor
172  RCP<Cijk_type> Cijk;
173  if (full)
174  Cijk = basis->computeTripleProductTensor();
175  else
176  Cijk = basis->computeLinearTripleProductTensor();
177 
178  int sz = basis->size();
179  std::cout << "basis size = " << sz
180  << " num nonzero Cijk entries = " << Cijk->num_entries()
181  << std::endl;
182 
183  // Setup tiles
184  if (tile_size > sz)
185  tile_size = sz;
186  int j_sz = sz;
187  int k_sz = sz;
188  if (!full)
189  k_sz = basis->dimension()+1;
190  int nj_tiles = j_sz / tile_size;
191  int nk_tiles = k_sz / tile_size;
192  if (j_sz - nj_tiles*tile_size > 0)
193  ++nj_tiles;
194  if (k_sz - nk_tiles*tile_size > 0)
195  ++nk_tiles;
196  Array<CijkNonzeros> nz(sz);
197  for (int i=0; i<sz; ++i) {
198  nz[i].i = i;
199  nz[i].nz_tiles.resize(nj_tiles);
200  for (int j=0; j<nj_tiles; ++j)
201  nz[i].nz_tiles[j].resize(nk_tiles);
202  }
203 
204  // Get number of nonzeros in Cijk for each i
205  Cijk_type::k_iterator k_begin = Cijk->k_begin();
206  Cijk_type::k_iterator k_end = Cijk->k_end();
207  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
208  int k = index(k_it);
209  int k_tile = k / tile_size;
210  Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it);
211  Cijk_type::kj_iterator j_end = Cijk->j_end(k_it);
212  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
213  int j = index(j_it);
214  int j_tile = j / tile_size;
215  Cijk_type::kji_iterator i_begin = Cijk->i_begin(j_it);
216  Cijk_type::kji_iterator i_end = Cijk->i_end(j_it);
217  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
218  int i = index(i_it);
219  ++nz[i].total_nz;
220  ++nz[i].nz_tiles[j_tile][k_tile];
221  }
222  }
223  }
224 
225  // Sort based on total number of nonzeros
226  std::sort(nz.begin(), nz.end(), NZCompare());
227 
228  // Print nonzeros
229  int w_index = 3;
230  int w_nz = 5;
231  int w_tile = 4;
232  for (int i=0; i<nz.size(); ++i) {
233  int idx = nz[i].i;
234  std::cout << std::setw(w_index) << idx << " "
235  << basis->term(idx) << ": "
236  << std::setw(w_nz) << nz[i].total_nz
237  << ", ";
238  for (int j=0; j<nj_tiles; ++j)
239  for (int k=0; k<nk_tiles; ++k)
240  std::cout << std::setw(w_tile) << nz[i].nz_tiles[j][k] << " ";
241  std::cout << std::endl;
242  }
243 
244  // Add up the nonzeros for each (j,k) tile
245  Array< Array<int> > total_nz_tiles(nj_tiles);
246  int total_nz = 0;
247  for (int j=0; j<nj_tiles; ++j)
248  total_nz_tiles[j].resize(nk_tiles);
249  for (int i=0; i<nz.size(); ++i) {
250  total_nz += nz[i].total_nz;
251  for (int j=0; j<nj_tiles; ++j)
252  for (int k=0; k<nk_tiles; ++k)
253  total_nz_tiles[j][k] += nz[i].nz_tiles[j][k];
254  }
255  int w_total = (w_index+1) + (2*basis->dimension()+5) + w_nz;
256  std::cout << std::endl << std::setw(w_total) << total_nz << ", ";
257  for (int j=0; j<nj_tiles; ++j)
258  for (int k=0; k<nk_tiles; ++k)
259  std::cout << std::setw(w_tile) << total_nz_tiles[j][k] << " ";
260  std::cout << std::endl;
261 
262  // Now partition Cijk for each tile
263  Array< Array< RCP<Cijk_type> > > Cijk_tile(nj_tiles);
264  for (int j=0; j<nj_tiles; ++j) {
265  Cijk_tile[j].resize(nk_tiles);
266  for (int k=0; k<nk_tiles; ++k)
267  Cijk_tile[j][k] = rcp(new Cijk_type);
268  }
269  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
270  int k = index(k_it);
271  int k_tile = k / tile_size;
272  Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it);
273  Cijk_type::kj_iterator j_end = Cijk->j_end(k_it);
274  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
275  int j = index(j_it);
276  int j_tile = j / tile_size;
277  Cijk_type::kji_iterator i_begin = Cijk->i_begin(j_it);
278  Cijk_type::kji_iterator i_end = Cijk->i_end(j_it);
279  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
280  int i = index(i_it);
281  double c = value(i_it);
282  Cijk_tile[j_tile][k_tile]->add_term(i,j,k,c);
283  }
284  }
285  }
286  for (int j=0; j<nj_tiles; ++j)
287  for (int k=0; k<nk_tiles; ++k)
288  Cijk_tile[j][k]->fillComplete();
289 
290 
291  Array< Array< std::map<int,int> > > nz_tile(nj_tiles);
292  Array< Array< Array< std::pair<int,int> > > > sorted_nz_tile(nj_tiles);
293  for (int j_tile=0; j_tile<nj_tiles; ++j_tile) {
294  nz_tile[j_tile].resize(nk_tiles);
295  sorted_nz_tile[j_tile].resize(nk_tiles);
296  for (int k_tile=0; k_tile<nk_tiles; ++k_tile) {
297 
298  // Count nonzeros for each i, for each tile
299  Cijk_type::k_iterator k_begin = Cijk_tile[j_tile][k_tile]->k_begin();
300  Cijk_type::k_iterator k_end = Cijk_tile[j_tile][k_tile]->k_end();
301  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
302  //int k = index(k_it);
303  Cijk_type::kj_iterator j_begin =
304  Cijk_tile[j_tile][k_tile]->j_begin(k_it);
305  Cijk_type::kj_iterator j_end =
306  Cijk_tile[j_tile][k_tile]->j_end(k_it);
307  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
308  //int j = index(j_it);
309  Cijk_type::kji_iterator i_begin =
310  Cijk_tile[j_tile][k_tile]->i_begin(j_it);
311  Cijk_type::kji_iterator i_end =
312  Cijk_tile[j_tile][k_tile]->i_end(j_it);
313  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it){
314  int i = index(i_it);
315  if (nz_tile[j_tile][k_tile].count(i) == 0)
316  nz_tile[j_tile][k_tile][i] = 1;
317  else
318  ++(nz_tile[j_tile][k_tile][i]);
319  }
320  }
321  }
322 
323  // Sort based on non-zeros for each i, for each tile
324  sorted_nz_tile[j_tile][k_tile].resize(nz_tile[j_tile][k_tile].size());
325  int idx=0;
326  for (std::map<int,int>::iterator it = nz_tile[j_tile][k_tile].begin();
327  it != nz_tile[j_tile][k_tile].end(); ++it) {
328  sorted_nz_tile[j_tile][k_tile][idx] =
329  std::make_pair(it->first, it->second);
330  ++idx;
331  }
332  std::sort( sorted_nz_tile[j_tile][k_tile].begin(),
333  sorted_nz_tile[j_tile][k_tile].end(),
334  NZPairCompare() );
335 
336  // Print number of non-zeros for each i, for each tile
337  std::cout << std::endl
338  << "Tile (" << j_tile << ", " << k_tile << "):" << std::endl;
339  for (int i=0; i<sorted_nz_tile[j_tile][k_tile].size(); ++i) {
340  int idx = sorted_nz_tile[j_tile][k_tile][i].first;
341  std::cout << std::setw(w_index) << idx << " "
342  << basis->term(idx) << ": "
343  << std::setw(w_nz) << sorted_nz_tile[j_tile][k_tile][i].second
344  << std::endl;
345  if (i % 32 == 31)
346  std::cout << std::endl;
347  }
348  }
349  }
350 
351  }
352  catch (std::exception& e) {
353  std::cout << e.what() << std::endl;
354  }
355 
356  return 0;
357 }
const ProductBasisType prod_basis_type_values[]
Hermite polynomial basis.
SparseArrayIterator< index_iterator, value_iterator >::value_type index(const SparseArrayIterator< index_iterator, value_iterator > &it)
Multivariate orthogonal polynomial basis generated from a total order tensor product of univariate po...
const char * basis_type_names[]
const BasisType basis_type_values[]
const int num_prod_basis_types
GrowthPolicy
Enumerated type for determining Smolyak growth policies.
const char * growth_type_names[]
bool operator()(const CijkNonzeros &a, const CijkNonzeros &b) const
bool operator()(const std::pair< int, int > &a, const std::pair< int, int > &b) const
Legendre polynomial basis using Gauss-Patterson quadrature points.
ProductBasisType
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Rys polynomial basis.
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
const int num_growth_types
Jacobi polynomial basis.
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
BasisType
void resize(size_type new_size, const value_type &x=value_type())
const Stokhos::GrowthPolicy growth_type_values[]
Multivariate orthogonal polynomial basis generated from a Smolyak sparse grid.
iterator end()
Multivariate orthogonal polynomial basis generated from a tensor product of univariate polynomials...
Legendre polynomial basis.
Stokhos::Sparse3Tensor< int, double > Cijk_type
int main(int argc, char **argv)
An isotropic total order index set.
Legendre polynomial basis using Clenshaw-Curtis quadrature points.
void setDocString(const char doc_string[])
SparseArrayIterator< index_iterator, value_iterator >::value_reference value(const SparseArrayIterator< index_iterator, value_iterator > &it)
size_type size() const
const int num_basis_types
Array< Array< int > > nz_tiles
iterator begin()
const char * prod_basis_type_names[]