44 "complete",
"tensor",
"total",
"smolyak" };
52 "total",
"lexicographic" };
64 template <
typename coord_t>
80 MPI_Init(&argc,&argv);
86 "This example generates the sparsity pattern for the block stochastic Galerkin matrix.\n");
88 CLP.
setOption(
"dimension", &d,
"Stochastic dimension");
90 CLP.
setOption(
"order", &p,
"Polynomial order");
91 double drop = 1.0e-12;
92 CLP.
setOption(
"drop", &drop,
"Drop tolerance");
93 std::string file =
"A.mm";
94 CLP.
setOption(
"filename", &file,
"Matrix Market filename");
95 bool symmetric =
true;
96 CLP.
setOption(
"symmetric",
"asymmetric", &symmetric,
97 "Use basis polynomials with symmetric PDF");
103 CLP.
setOption(
"product_basis", &prod_basis_type,
106 "Product basis type");
108 CLP.
setOption(
"ordering", &ordering_type,
111 "Product basis ordering");
112 int i_tile_size = 128;
113 CLP.
setOption(
"tile_size", &i_tile_size,
"Tile size");
114 bool save_3tensor =
false;
115 CLP.
setOption(
"save_3tensor",
"no-save_3tensor", &save_3tensor,
116 "Save full 3tensor to file");
117 std::string file_3tensor =
"Cijk.dat";
118 CLP.
setOption(
"filename_3tensor", &file_3tensor,
119 "Filename to store full 3-tensor");
122 CLP.
parse( argc, argv );
126 const double alpha = 1.0;
127 const double beta = symmetric ? 1.0 : 2.0 ;
128 for (
int i=0; i<d; i++) {
130 p, alpha, beta,
true, growth_type));
139 else if (prod_basis_type ==
TENSOR) {
150 else if (prod_basis_type ==
TOTAL) {
160 else if (prod_basis_type ==
SMOLYAK) {
165 bases, index_set, drop));
169 bases, index_set, drop));
176 int basis_size = basis->size();
177 std::cout <<
"basis size = " << basis_size
178 <<
" num nonzero Cijk entries = " << Cijk->num_entries()
183 Cijk_type::i_iterator i_begin = Cijk->i_begin();
184 Cijk_type::i_iterator i_end = Cijk->i_end();
185 for (Cijk_type::i_iterator i_it=i_begin; i_it!=i_end; ++i_it) {
187 Cijk_type::ik_iterator k_begin = Cijk->k_begin(i_it);
188 Cijk_type::ik_iterator k_end = Cijk->k_end(i_it);
189 for (Cijk_type::ik_iterator k_it = k_begin; k_it != k_end; ++k_it) {
191 Cijk_type::ikj_iterator j_begin = Cijk->j_begin(k_it);
192 Cijk_type::ikj_iterator j_end = Cijk->j_end(k_it);
193 for (Cijk_type::ikj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
196 double c =
value(j_it);
197 Cijk_sym->add_term(i, j, k, c);
202 Cijk_sym->fillComplete();
205 int j_tile_size = i_tile_size / 2;
206 int num_i_parts = (basis_size + i_tile_size-1) / i_tile_size;
207 int its = basis_size / num_i_parts;
209 for (
int i=0; i<num_i_parts; ++i) {
210 i_tiles[i].lower = i*its;
211 i_tiles[i].upper = (i+1)*its;
212 i_tiles[i].parts.
resize(1);
213 i_tiles[i].parts[0].lower = basis_size;
214 i_tiles[i].parts[0].upper = 0;
218 for (Cijk_type::i_iterator i_it=Cijk_sym->i_begin();
219 i_it!=Cijk_sym->i_end(); ++i_it) {
224 while (idx < num_i_parts && i >= i_tiles[idx].lower) ++idx;
228 Cijk_type::ik_iterator k_begin = Cijk_sym->k_begin(i_it);
229 Cijk_type::ik_iterator k_end = Cijk_sym->k_end(i_it);
230 for (Cijk_type::ik_iterator k_it = k_begin; k_it != k_end; ++k_it) {
233 if (j < i_tiles[idx].parts[0].lower)
234 i_tiles[idx].parts[0].lower =
j;
235 if (j > i_tiles[idx].parts[0].upper)
236 i_tiles[idx].parts[0].upper =
j;
239 for (
int idx=0; idx<num_i_parts; ++idx) {
240 int lower = i_tiles[idx].parts[0].lower;
241 int upper = i_tiles[idx].parts[0].upper;
242 int range = upper - lower + 1;
243 int num_j_parts = (range + j_tile_size-1) / j_tile_size;
244 int jts = range / num_j_parts;
246 for (
int j=0;
j<num_j_parts; ++
j) {
247 j_tiles[
j].lower = lower +
j*jts;
248 j_tiles[
j].upper = lower + (
j+1)*jts;
250 j_tiles[
j].parts[0].lower = basis_size;
251 j_tiles[
j].parts[0].upper = 0;
253 i_tiles[idx].parts.
swap(j_tiles);
257 for (Cijk_type::i_iterator i_it=Cijk_sym->i_begin();
258 i_it!=Cijk_sym->i_end(); ++i_it) {
263 while (idx < num_i_parts && i >= i_tiles[idx].lower) ++idx;
267 Cijk_type::ik_iterator k_begin = Cijk_sym->k_begin(i_it);
268 Cijk_type::ik_iterator k_end = Cijk_sym->k_end(i_it);
269 for (Cijk_type::ik_iterator k_it = k_begin; k_it != k_end; ++k_it) {
273 int num_j_parts = i_tiles[idx].parts.
size();
275 while (jdx < num_j_parts && j >= i_tiles[idx].parts[jdx].lower) ++jdx;
279 Cijk_type::ikj_iterator j_begin = Cijk_sym->j_begin(k_it);
280 Cijk_type::ikj_iterator j_end = Cijk_sym->j_end(k_it);
281 for (Cijk_type::ikj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
286 coord.
i = i; coord.
j =
j; coord.
k = k;
287 i_tiles[idx].parts[jdx].parts[0].parts.
push_back(coord);
288 if (k < i_tiles[idx].parts[jdx].parts[0].lower)
289 i_tiles[idx].parts[jdx].parts[0].lower = k;
290 if (k > i_tiles[idx].parts[jdx].parts[0].upper)
291 i_tiles[idx].parts[jdx].parts[0].upper = k;
300 for (
int idx=0; idx<num_i_parts; ++idx) {
301 int num_j_parts = i_tiles[idx].parts.
size();
302 for (
int jdx=0; jdx<num_j_parts; ++jdx) {
303 int lower = i_tiles[idx].parts[jdx].parts[0].lower;
304 int upper = i_tiles[idx].parts[jdx].parts[0].upper;
305 int range = upper - lower + 1;
306 int num_k_parts = (range + j_tile_size-1) / j_tile_size;
307 int kts = range / num_k_parts;
309 for (
int k=0; k<num_k_parts; ++k) {
310 k_tiles[k].lower = lower + k*kts;
311 k_tiles[k].upper = lower + (k+1)*kts;
313 int num_k = i_tiles[idx].parts[jdx].parts[0].parts.
size();
314 for (
int l=0; l<num_k; ++l) {
315 int i = i_tiles[idx].parts[jdx].parts[0].parts[l].i;
316 int j = i_tiles[idx].parts[jdx].parts[0].parts[l].j;
317 int k = i_tiles[idx].parts[jdx].parts[0].parts[l].k;
321 while (kdx < num_k_parts && k >= k_tiles[kdx].lower) ++kdx;
326 coord.
i = i; coord.
j =
j; coord.
k = k;
329 if (j != k) ++num_coord;
334 for (
int k=0; k<num_k_parts; ++k) {
335 if (k_tiles[k].parts.
size() > 0)
338 num_parts += k_tiles2.
size();
339 i_tiles[idx].parts[jdx].parts.
swap(k_tiles2);
344 std::cout <<
"num parts requested = " << num_parts << std::endl;
348 for (
int i=0; i<num_parts; ++i)
350 std::random_shuffle(part_IDs.
begin(), part_IDs.
end());
354 for (
int idx=0; idx<num_i_parts; ++idx) {
355 int num_j_parts = i_tiles[idx].parts.
size();
356 for (
int jdx=0; jdx<num_j_parts; ++jdx) {
357 int num_k_parts = i_tiles[idx].parts[jdx].parts.
size();
358 for (
int kdx=0; kdx<num_k_parts; ++kdx) {
359 int num_k = i_tiles[idx].parts[jdx].parts[kdx].parts.
size();
360 for (
int l=0; l<num_k; ++l) {
361 i_tiles[idx].parts[jdx].parts[kdx].parts[l].gid = part_IDs[pp];
369 for (
int idx=0; idx<num_i_parts; ++idx) {
370 int num_j_parts = i_tiles[idx].parts.
size();
371 for (
int jdx=0; jdx<num_j_parts; ++jdx) {
372 int num_k_parts = i_tiles[idx].parts[jdx].parts.
size();
373 for (
int kdx=0; kdx<num_k_parts; ++kdx) {
374 std::cout << part++ <<
" : ["
375 << i_tiles[idx].lower <<
","
376 << i_tiles[idx].upper <<
") x ["
377 << i_tiles[idx].parts[jdx].lower <<
","
378 << i_tiles[idx].parts[jdx].upper <<
") x ["
379 << i_tiles[idx].parts[jdx].parts[kdx].lower <<
","
380 << i_tiles[idx].parts[jdx].parts[kdx].upper <<
") : "
381 << i_tiles[idx].parts[jdx].parts[kdx].parts.
size()
388 std::ofstream cijk_file;
390 cijk_file.open(file_3tensor.c_str());
391 cijk_file.precision(14);
392 cijk_file.setf(std::ios::scientific);
393 cijk_file <<
"i, j, k, part" << std::endl;
394 for (
int idx=0; idx<num_i_parts; ++idx) {
395 int num_j_parts = i_tiles[idx].parts.
size();
396 for (
int jdx=0; jdx<num_j_parts; ++jdx) {
397 int num_k_parts = i_tiles[idx].parts[jdx].parts.
size();
398 for (
int kdx=0; kdx<num_k_parts; ++kdx) {
399 int num_k = i_tiles[idx].parts[jdx].parts[kdx].parts.
size();
400 for (
int l=0; l<num_k; ++l) {
401 Coord c = i_tiles[idx].parts[jdx].parts[kdx].parts[l];
402 cijk_file << c.
i <<
", " << c.
j <<
", " << c.
k <<
", " << c.
gid
405 cijk_file << c.
i <<
", " << c.
k <<
", " << c.
j <<
", " << c.
gid
416 catch (std::exception& e) {
417 std::cout << e.what() << std::endl;
const ProductBasisType prod_basis_type_values[]
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 int num_prod_basis_types
GrowthPolicy
Enumerated type for determining Smolyak growth policies.
const char * growth_type_names[]
const OrderingType ordering_type_values[]
const int num_ordering_types
A comparison functor implementing a strict weak ordering based total-order ordering, recursive on the dimension.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
const int num_growth_types
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
friend friend void swap(Array< T2 > &a1, Array< T2 > &a2)
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.
Multivariate orthogonal polynomial basis generated from a tensor product of univariate polynomials...
Stokhos::Sparse3Tensor< int, double > Cijk_type
int main(int argc, char **argv)
void push_back(const value_type &x)
An isotropic total order index set.
void setDocString(const char doc_string[])
SparseArrayIterator< index_iterator, value_iterator >::value_reference value(const SparseArrayIterator< index_iterator, value_iterator > &it)
A comparison functor implementing a strict weak ordering based lexographic ordering.
#define TEUCHOS_ASSERT(assertion_test)
const char * ordering_type_names[]
const char * prod_basis_type_names[]