Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
cijk_partition.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"
13 #include "Isorropia_Epetra.hpp"
14 #include "Isorropia_EpetraPartitioner.hpp"
15 
16 #ifdef HAVE_MPI
17 #include "Epetra_MpiComm.h"
18 #else
19 #include "Epetra_SerialComm.h"
20 #endif
21 
22 // sparsity_example
23 //
24 // usage:
25 // sparsity_example [options]
26 //
27 // output:
28 // prints the sparsity of the sparse 3 tensor specified by the basis,
29 // dimension, order, given by summing over the third index, to a matrix
30 // market file. This sparsity pattern yields the sparsity of the block
31 // stochastic Galerkin matrix which can be visualized, e.g., by matlab.
32 // The full/linear flag determines whether the third index ranges over
33 // the full polynomial dimension, or only over the zeroth and first order
34 // terms.
35 
36 // Basis types
38 const int num_basis_types = 6;
41 const char *basis_type_names[] = {
42  "hermite", "legendre", "clenshaw-curtis", "gauss-patterson", "rys", "jacobi" };
43 
44 // Growth policies
45 const int num_growth_types = 2;
48 const char *growth_type_names[] = { "slow", "moderate" };
49 
50 // Product Basis types
52 const int num_prod_basis_types = 4;
55 const char *prod_basis_type_names[] = {
56  "complete", "tensor", "total", "smolyak" };
57 
58 // Ordering types
60 const int num_ordering_types = 2;
63 const char *ordering_type_names[] = {
64  "total", "lexicographic" };
65 
66 // Partitioning types
68 const int num_partitioning_types = 2;
70  RCB, HG_MATRIX };
71 const char *partitioning_type_names[] = {
72  "rcb", "hg_matrix" };
73 
74 using Teuchos::rcp;
75 using Teuchos::RCP;
77 using Teuchos::Array;
78 
79 int main(int argc, char **argv)
80 {
81  try {
82 
83  // Initialize MPI
84 #ifdef HAVE_MPI
85  MPI_Init(&argc,&argv);
86 #endif
87 
88  // Setup command line options
90  CLP.setDocString(
91  "This example generates the sparsity pattern for the block stochastic Galerkin matrix.\n");
92  int d = 3;
93  CLP.setOption("dimension", &d, "Stochastic dimension");
94  int p = 5;
95  CLP.setOption("order", &p, "Polynomial order");
96  double drop = 1.0e-12;
97  CLP.setOption("drop", &drop, "Drop tolerance");
98  std::string file = "A.mm";
99  CLP.setOption("filename", &file, "Matrix Market filename");
101  CLP.setOption("basis", &basis_type,
103  "Basis type");
105  CLP.setOption("growth", &growth_type,
107  "Growth type");
108  ProductBasisType prod_basis_type = TOTAL;
109  CLP.setOption("product_basis", &prod_basis_type,
112  "Product basis type");
113  OrderingType ordering_type = LEXICOGRAPHIC_ORDERING;
114  CLP.setOption("ordering", &ordering_type,
117  "Product basis ordering");
118  PartitioningType partitioning_type = RCB;
119  CLP.setOption("partitioning", &partitioning_type,
122  "Partitioning Method");
123  double imbalance_tol = 1.0;
124  CLP.setOption("imbalance", &imbalance_tol, "Imbalance tolerance");
125  double alpha = 1.0;
126  CLP.setOption("alpha", &alpha, "Jacobi alpha index");
127  double beta = 1.0;
128  CLP.setOption("beta", &beta, "Jacobi beta index");
129  bool full = true;
130  CLP.setOption("full", "linear", &full, "Use full or linear expansion");
131  int tile_size = 128;
132  CLP.setOption("tile_size", &tile_size, "Tile size");
133  bool save_3tensor = false;
134  CLP.setOption("save_3tensor", "no-save_3tensor", &save_3tensor,
135  "Save full 3tensor to file");
136  std::string file_3tensor = "Cijk.dat";
137  CLP.setOption("filename_3tensor", &file_3tensor,
138  "Filename to store full 3-tensor");
139 
140  // Parse arguments
141  CLP.parse( argc, argv );
142 
143  // Basis
145  for (int i=0; i<d; i++) {
146  if (basis_type == HERMITE)
147  bases[i] = rcp(new Stokhos::HermiteBasis<int,double>(
148  p, true, growth_type));
149  else if (basis_type == LEGENDRE)
151  p, true, growth_type));
152  else if (basis_type == CC_LEGENDRE)
153  bases[i] =
155  p, true));
156  else if (basis_type == GP_LEGENDRE)
157  bases[i] =
159  p, true));
160  else if (basis_type == RYS)
161  bases[i] = rcp(new Stokhos::RysBasis<int,double>(
162  p, 1.0, true, growth_type));
163  else if (basis_type == JACOBI)
164  bases[i] = rcp(new Stokhos::JacobiBasis<int,double>(
165  p, alpha, beta, true, growth_type));
166  }
170  if (prod_basis_type == COMPLETE)
171  basis =
173  bases, drop));
174  else if (prod_basis_type == TENSOR) {
175  if (ordering_type == TOTAL_ORDERING)
176  basis =
178  bases, drop));
179  else if (ordering_type == LEXICOGRAPHIC_ORDERING)
180  basis =
182  bases, drop));
183  }
184 
185  else if (prod_basis_type == TOTAL) {
186  if (ordering_type == TOTAL_ORDERING)
187  basis =
189  bases, drop));
190  else if (ordering_type == LEXICOGRAPHIC_ORDERING)
191  basis =
193  bases, drop));
194  }
195  else if (prod_basis_type == SMOLYAK) {
196  Stokhos::TotalOrderIndexSet<int> index_set(d, p);
197  if (ordering_type == TOTAL_ORDERING)
198  basis =
200  bases, index_set, drop));
201  else if (ordering_type == LEXICOGRAPHIC_ORDERING)
202  basis =
204  bases, index_set, drop));
205  }
206 
207  // Triple product tensor
209  RCP<Cijk_type> Cijk;
210  if (full)
211  Cijk = basis->computeTripleProductTensor();
212  else
213  Cijk = basis->computeLinearTripleProductTensor();
214 
215  int basis_size = basis->size();
216  std::cout << "basis size = " << basis_size
217  << " num nonzero Cijk entries = " << Cijk->num_entries()
218  << std::endl;
219 
220 #ifdef HAVE_MPI
221  Epetra_MpiComm comm(MPI_COMM_WORLD);
222 #else
223  Epetra_SerialComm comm;
224 #endif
225 
226  // File for saving sparse Cijk tensor and parts
227  std::ofstream cijk_file;
228  if (save_3tensor) {
229  cijk_file.open(file_3tensor.c_str());
230  cijk_file.precision(14);
231  cijk_file.setf(std::ios::scientific);
232  cijk_file << "i, j, k, part" << std::endl;
233  }
234 
235  Teuchos::Array<int> parts;
236  if (partitioning_type == RCB) {
237  // Store Cijk (i,j,k) triples in Epetra_MultiVector
238  int num_cijk_entries = Cijk->num_entries();
239  Epetra_LocalMap cijk_map(num_cijk_entries, 0, comm);
240  Epetra_MultiVector ijk_triples(cijk_map, 3);
241  int idx = 0;
242  Cijk_type::k_iterator k_begin = Cijk->k_begin();
243  Cijk_type::k_iterator k_end = Cijk->k_end();
244  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
245  int k = index(k_it);
246  Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it);
247  Cijk_type::kj_iterator j_end = Cijk->j_end(k_it);
248  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
249  int j = index(j_it);
250  Cijk_type::kji_iterator i_begin = Cijk->i_begin(j_it);
251  Cijk_type::kji_iterator i_end = Cijk->i_end(j_it);
252  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
253  int i = index(i_it);
254  ijk_triples[0][idx] = i;
255  ijk_triples[1][idx] = j;
256  ijk_triples[2][idx] = k;
257  ++idx;
258  }
259  }
260  }
261 
262  // Partition ijk_triples using isorropia
263  ParameterList params;
264  params.set("partitioning method", "rcb");
265  int num_parts = num_cijk_entries / tile_size;
266  if (num_cijk_entries % tile_size > 0)
267  ++num_parts;
268  std::stringstream ss;
269  ss << num_parts;
270  params.set<std::string>("num parts", ss.str());
271  RCP<const Epetra_MultiVector> ijk_triples_rcp =
272  rcp(&ijk_triples,false);
273  Isorropia::Epetra::Partitioner partitioner(ijk_triples_rcp, params);
274  partitioner.compute();
275 
276  std::cout << "num parts requested = " << num_parts
277  << " num parts computed = " << partitioner.numProperties() << std::endl;
278 
279  parts.resize(num_cijk_entries);
280  int sz;
281  partitioner.extractPartsCopy(num_cijk_entries, sz, &parts[0]);
282  TEUCHOS_ASSERT(sz == num_cijk_entries);
283 
284  // Print full 3-tensor to file
285  if (save_3tensor) {
286  for (int i=0; i<num_cijk_entries; ++i) {
287  cijk_file << ijk_triples[0][i] << ", "
288  << ijk_triples[1][i] << ", "
289  << ijk_triples[2][i] << ", "
290  << parts[i] << std::endl;
291  }
292  }
293  }
294 
295  else if (partitioning_type == HG_MATRIX) {
296  // Build CRS graph from Cijk tensor
298  Stokhos::buildMultiComm(comm, basis_size, 1);
299  Stokhos::EpetraSparse3Tensor epetra_Cijk(basis, Cijk, multiComm);
300  RCP<const Epetra_CrsGraph> graph = epetra_Cijk.getStochasticGraph();
301  // RCP<const Epetra_CrsGraph> graph =
302  // Stokhos::sparse3Tensor2CrsGraph(*basis, *Cijk, comm);
303 
304  // Partition graph using isorropia/zoltan's hypergraph partitioner
305  ParameterList params;
306  params.set("partitioning method", "hypergraph");
307  //int num_parts = basis_size / tile_size;
308  int num_parts = comm.NumProc();
309  std::stringstream ss;
310  ss << num_parts;
311  params.set<std::string>("num parts", ss.str());
312  std::stringstream ss2;
313  ss2 << imbalance_tol;
314  params.set<std::string>("imbalance tol", ss2.str());
315 
316  /*
317  Isorropia::Epetra::Partitioner partitioner(graph, params);
318  partitioner.compute();
319 
320  std::cout << "num parts requested = " << num_parts
321  << " num parts computed = " << partitioner.numProperties() << std::endl;
322 
323  parts.resize(partitioner.numProperties());
324  int sz;
325  partitioner.extractPartsCopy(partitioner.numProperties(), sz, &parts[0]);
326  TEUCHOS_ASSERT(sz == partitioner.numProperties());
327 
328  for (int i=0; i<sz; ++i)
329  std::cout << i << " " << parts[i] << std::endl;
330 
331  // Create the permuted map
332  RCP<Epetra_Map> permuted_map = partitioner.createNewMap();
333  std::cout << *permuted_map << std::endl;
334  */
335  Teuchos::RCP<const Epetra_CrsGraph> rebalanced_graph =
336  Teuchos::rcp(Isorropia::Epetra::createBalancedCopy(
337  *graph, params));
338  Epetra_BlockMap permuted_map = rebalanced_graph->RowMap();
339  std::cout << permuted_map << std::endl;
340 
341  //Epetra_CrsMatrix mat(Copy, *rebalanced_graph);
342  Epetra_CrsMatrix mat(Copy, *graph);
343  mat.FillComplete();
344  mat.PutScalar(1.0);
345  EpetraExt::RowMatrixToMatrixMarketFile(file.c_str(), mat);
346 
347  // Print full 3-tensor to file
348  if (save_3tensor) {
349  Cijk_type::k_iterator k_begin = Cijk->k_begin();
350  Cijk_type::k_iterator k_end = Cijk->k_end();
351  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
352  int k = index(k_it);
353  Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it);
354  Cijk_type::kj_iterator j_end = Cijk->j_end(k_it);
355  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
356  int j = index(j_it);
357  Cijk_type::kji_iterator i_begin = Cijk->i_begin(j_it);
358  Cijk_type::kji_iterator i_end = Cijk->i_end(j_it);
359  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it){
360  int i = index(i_it);
361  cijk_file << i << ", " << j << ", " << k << ", " << parts[i]
362  << std::endl;
363  }
364  }
365  }
366  }
367  }
368 
369  if (save_3tensor) {
370  cijk_file.close();
371  }
372 
373  //Teuchos::TimeMonitor::summarize(std::cout);
374 
375  }
376  catch (std::exception& e) {
377  std::cout << e.what() << std::endl;
378  }
379 
380 #ifdef HAVE_MPI
381  MPI_Finalize() ;
382 #endif
383 
384  return 0;
385 }
const ProductBasisType prod_basis_type_values[]
PartitioningType
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[]
Teuchos::RCP< const Epetra_CrsGraph > getStochasticGraph() const
Get stochastic graph.
const int num_prod_basis_types
GrowthPolicy
Enumerated type for determining Smolyak growth policies.
const char * growth_type_names[]
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
const OrderingType ordering_type_values[]
const char * partitioning_type_names[]
const int num_ordering_types
A comparison functor implementing a strict weak ordering based total-order ordering, recursive on the dimension.
Teuchos::RCP< const EpetraExt::MultiComm > buildMultiComm(const Epetra_Comm &globalComm, int num_global_stochastic_blocks, int num_spatial_procs=-1)
int FillComplete(bool OptimizeDataStorage=true)
OrderingType
int PutScalar(double ScalarConstant)
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
int NumProc() const
void resize(size_type new_size, const value_type &x=value_type())
const int num_partitioning_types
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...
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[])
A comparison functor implementing a strict weak ordering based lexographic ordering.
const int num_basis_types
#define TEUCHOS_ASSERT(assertion_test)
const char * ordering_type_names[]
const char * prod_basis_type_names[]
const PartitioningType partitioning_type_values[]