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_zoltan_rcb.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 "Teuchos_toString.hpp"
14 
15 #include <fstream>
16 #include <iostream>
17 
18 extern "C" {
19 #include "zoltan.h"
20 }
21 
22 // Growth policies
23 const int num_growth_types = 2;
26 const char *growth_type_names[] = { "slow", "moderate" };
27 
28 // Product Basis types
30 const int num_prod_basis_types = 4;
33 const char *prod_basis_type_names[] = {
34  "complete", "tensor", "total", "smolyak" };
35 
36 // Ordering types
38 const int num_ordering_types = 2;
41 const char *ordering_type_names[] = {
42  "total", "lexicographic" };
43 
44 using Teuchos::rcp;
45 using Teuchos::RCP;
47 using Teuchos::Array;
48 using Teuchos::toString;
49 
50 struct TensorData {
54 };
55 
56 struct CijkData {
57  int gid;
58  int i, j, k;
59 };
60 
61 // Functions implementing Cijk tensor for geometric partitioning
62 namespace CoordPart {
63 
64  // Return number of vertices
65  int get_number_of_objects(void *data, int *ierr) {
66  TensorData *td = static_cast<TensorData*>(data);
67  *ierr = ZOLTAN_OK;
68 
69  return td->Cijk->num_entries();
70  }
71 
72  // Compute IDs and weights of each vertex
73  void get_object_list(void *data, int sizeGID, int sizeLID,
74  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
75  int wgt_dim, float *obj_wgts, int *ierr) {
76  TensorData *td = static_cast<TensorData*>(data);
77  *ierr = ZOLTAN_OK;
78 
79  int n = td->Cijk->num_entries();
80  for (int i=0; i<n; ++i) {
81  globalID[i] = i;
82  localID[i] = i;
83  }
84 
85  // Do not set weights so Zoltan assumes equally weighted vertices
86  }
87 
88  // Geometry dimension -- here 3 for (i,j,k)
89  int get_num_geometry(void *data, int *ierr)
90  {
91  *ierr = ZOLTAN_OK;
92  return 3;
93  }
94 
95  // Get list of (i,j,k) tuples
96  void get_geometry_list(void *data, int sizeGID, int sizeLID,
97  int num_obj,
98  ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID,
99  int num_dim, double *geom_vec, int *ierr)
100  {
101  TensorData *td = static_cast<TensorData*>(data);
102  *ierr = ZOLTAN_OK;
103 
104  int idx = 0;
107  for (TensorData::Cijk_type::k_iterator k_it=k_begin; k_it!=k_end;
108  ++k_it) {
109  int k = index(k_it);
110  TensorData::Cijk_type::kj_iterator j_begin = td->Cijk->j_begin(k_it);
111  TensorData::Cijk_type::kj_iterator j_end = td->Cijk->j_end(k_it);
112  for (TensorData::Cijk_type::kj_iterator j_it = j_begin; j_it != j_end;
113  ++j_it) {
114  int j = index(j_it);
115  TensorData::Cijk_type::kji_iterator i_begin = td->Cijk->i_begin(j_it);
117  for (TensorData::Cijk_type::kji_iterator i_it = i_begin; i_it != i_end;
118  ++i_it) {
119  int i = index(i_it);
120  geom_vec[3*idx ] = i;
121  geom_vec[3*idx+1] = j;
122  geom_vec[3*idx+2] = k;
123  ++idx;
124  }
125  }
126  }
127  }
128 
129 }
130 
131 
132 int main(int argc, char **argv)
133 {
134  try {
135 
136  // Initialize Zoltan
137  float version;
138  int rc = Zoltan_Initialize(argc,argv,&version);
139  TEUCHOS_ASSERT(rc == 0);
140 
141  // Setup command line options
143  CLP.setDocString(
144  "This example generates the sparsity pattern for the block stochastic Galerkin matrix.\n");
145  int d = 5;
146  CLP.setOption("dimension", &d, "Stochastic dimension");
147  int p = 3;
148  CLP.setOption("order", &p, "Polynomial order");
149  double drop = 1.0e-12;
150  CLP.setOption("drop", &drop, "Drop tolerance");
151  bool symmetric = true;
152  CLP.setOption("symmetric", "asymmetric", &symmetric, "Use basis polynomials with symmetric PDF");
154  CLP.setOption("growth", &growth_type,
156  "Growth type");
157  ProductBasisType prod_basis_type = TOTAL;
158  CLP.setOption("product_basis", &prod_basis_type,
161  "Product basis type");
162  OrderingType ordering_type = LEXICOGRAPHIC_ORDERING;
163  CLP.setOption("ordering", &ordering_type,
166  "Product basis ordering");
167  double imbalance_tol = 1.2;
168  CLP.setOption("imbalance", &imbalance_tol, "Imbalance tolerance");
169  bool full = true;
170  CLP.setOption("full", "linear", &full, "Use full or linear expansion");
171  int tile_size = 32;
172  CLP.setOption("tile_size", &tile_size, "Tile size");
173  bool save_3tensor = false;
174  CLP.setOption("save_3tensor", "no-save_3tensor", &save_3tensor,
175  "Save full 3tensor to file");
176  std::string file_3tensor = "Cijk.dat";
177  CLP.setOption("filename_3tensor", &file_3tensor,
178  "Filename to store full 3-tensor");
179 
180  // Parse arguments
181  CLP.parse( argc, argv );
182 
183  // Basis
185  const double alpha = 1.0;
186  const double beta = symmetric ? 1.0 : 2.0 ;
187  for (int i=0; i<d; i++) {
188  bases[i] = rcp(new Stokhos::JacobiBasis<int,double>(
189  p, alpha, beta, true, growth_type));
190  }
194  if (prod_basis_type == COMPLETE)
195  basis =
197  bases, drop));
198  else if (prod_basis_type == TENSOR) {
199  if (ordering_type == TOTAL_ORDERING)
200  basis =
202  bases, drop));
203  else if (ordering_type == LEXICOGRAPHIC_ORDERING)
204  basis =
206  bases, drop));
207  }
208  else if (prod_basis_type == TOTAL) {
209  if (ordering_type == TOTAL_ORDERING)
210  basis =
212  bases, drop));
213  else if (ordering_type == LEXICOGRAPHIC_ORDERING)
214  basis =
216  bases, drop));
217  }
218  else if (prod_basis_type == SMOLYAK) {
219  Stokhos::TotalOrderIndexSet<int> index_set(d, p);
220  if (ordering_type == TOTAL_ORDERING)
221  basis =
223  bases, index_set, drop));
224  else if (ordering_type == LEXICOGRAPHIC_ORDERING)
225  basis =
227  bases, index_set, drop));
228  }
229 
230  // Triple product tensor
232  RCP<Cijk_type> Cijk;
233  if (full)
234  Cijk = basis->computeTripleProductTensor();
235  else
236  Cijk = basis->computeLinearTripleProductTensor();
237 
238  int basis_size = basis->size();
239  std::cout << "basis size = " << basis_size
240  << " num nonzero Cijk entries = " << Cijk->num_entries()
241  << std::endl;
242 
243  // File for saving sparse Cijk tensor and parts
244  std::ofstream cijk_file;
245  if (save_3tensor) {
246  cijk_file.open(file_3tensor.c_str());
247  cijk_file.precision(14);
248  cijk_file.setf(std::ios::scientific);
249  cijk_file << "i, j, k, part" << std::endl;
250  }
251 
252  // Create zoltan
253  Zoltan_Struct *zz = Zoltan_Create(MPI_COMM_WORLD);
254 
255  // Setup Zoltan parameters
256  Zoltan_Set_Param(zz, "DEBUG_LEVEL", "2");
257 
258  // partitioning method
259  Zoltan_Set_Param(zz, "LB_METHOD", "RCB");
260  //Zoltan_Set_Param(zz, "LB_METHOD", "HSFC");
261  Zoltan_Set_Param(zz, "NUM_GID_ENTRIES", "1");// global IDs are integers
262  Zoltan_Set_Param(zz, "NUM_LID_ENTRIES", "1");// local IDs are integers
263  //Zoltan_Set_Param(zz, "RETURN_LISTS", "ALL"); // export AND import lists
264  Zoltan_Set_Param(zz, "RETURN_LISTS", "PARTS");
265  Zoltan_Set_Param(zz, "OBJ_WEIGHT_DIM", "0"); // use Zoltan default vertex weights
266  int num_parts = basis_size / tile_size;
267  if (num_parts * tile_size < basis_size) ++num_parts;
268  Zoltan_Set_Param(zz, "NUM_GLOBAL_PARTS", toString(num_parts).c_str());
269  Zoltan_Set_Param(zz, "NUM_LOCAL_PARTS", toString(num_parts).c_str());
270  Zoltan_Set_Param(zz, "IMBALANCE_TOL", toString(imbalance_tol).c_str());
271 
272  Zoltan_Set_Param(zz, "KEEP_CUTS", "1");
273  Zoltan_Set_Param(zz, "RCB_RECTILINEAR_BLOCKS", "1");
274  Zoltan_Set_Param(zz, "RCB_RECOMPUTE_BOX", "1");
275  Zoltan_Set_Param(zz, "RCB_MAX_ASPECT_RATIO", "3");
276 
277  // Set query functions
278  TensorData td; td.basis = basis; td.Cijk = Cijk;
279 
280  Zoltan_Set_Num_Obj_Fn(zz, CoordPart::get_number_of_objects, &td);
281  Zoltan_Set_Obj_List_Fn(zz, CoordPart::get_object_list, &td);
282  Zoltan_Set_Num_Geom_Fn(zz, CoordPart::get_num_geometry, &td);
283  Zoltan_Set_Geom_Multi_Fn(zz, CoordPart::get_geometry_list, &td);
284 
285  // Partition
286  int changes, numGidEntries, numLidEntries, numImport, numExport;
287  ZOLTAN_ID_PTR importGlobalGids, importLocalGids, exportGlobalGids, exportLocalGids;
288  int *importProcs, *importToPart, *exportProcs, *exportToPart;
289  rc =
290  Zoltan_LB_Partition(
291  zz, // input (all remaining fields are output)
292  &changes, // 1 if partitioning was changed, 0 otherwise
293  &numGidEntries, // Number of integers used for a global ID
294  &numLidEntries, // Number of integers used for a local ID
295  &numImport, // Number of vertices to be sent to me
296  &importGlobalGids, // Global IDs of vertices to be sent to me
297  &importLocalGids, // Local IDs of vertices to be sent to me
298  &importProcs, // Process rank for source of each incoming vertex
299  &importToPart, // New partition for each incoming vertex
300  &numExport, // Number of vertices I must send to other processes*/
301  &exportGlobalGids, // Global IDs of the vertices I must send
302  &exportLocalGids, // Local IDs of the vertices I must send
303  &exportProcs, // Process to which I send each of the vertices
304  &exportToPart); // Partition to which each vertex will belong
305  TEUCHOS_ASSERT(rc == 0);
306 
307  std::cout << "num parts requested = " << num_parts
308  << " changes= " << changes
309  << " num import = " << numImport
310  << " num export = " << numExport << std::endl;
311 
312  // Compute max/min bounding box dimensions
313  // double dim_max = 0.0, dim_min = 0.0;
314  // for (int part=0; part<num_parts; ++part) {
315  // double xmin, ymin, zmin, xmax, ymax, zmax;
316  // int ndim;
317  // rc = Zoltan_RCB_Box(zz, part, &ndim, &xmin, &ymin, &zmin,
318  // &xmax, &ymax, &zmax);
319  // TEUCHOS_ASSERT(rc == 0);
320  // double delta_x = xmax - xmin;
321  // double delta_y = ymax - ymin;
322  // double delta_z = zmax - zmin;
323  // std::cout << delta_x << " " << delta_y << " " << delta_z << std::endl;
324  // if (delta_x > dim_max) dim_max = delta_x;
325  // if (delta_y > dim_max) dim_max = delta_y;
326  // if (delta_z > dim_max) dim_max = delta_z;
327  // if (delta_x < dim_min) dim_min = delta_x;
328  // if (delta_y < dim_min) dim_min = delta_y;
329  // if (delta_z < dim_min) dim_min = delta_z;
330  // }
331  // std::cout << "max part dimension = " << dim_max
332  // << " min part dimension = " << dim_min << std::endl;
333 
334  // Build part list
335  Teuchos::Array< Teuchos::Array<CijkData> > part_list(num_parts);
336  int idx = 0;
337  Cijk_type::k_iterator k_begin = Cijk->k_begin();
338  Cijk_type::k_iterator k_end = Cijk->k_end();
339  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
340  int k = index(k_it);
341  Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it);
342  Cijk_type::kj_iterator j_end = Cijk->j_end(k_it);
343  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
344  int j = index(j_it);
345  Cijk_type::kji_iterator i_begin = Cijk->i_begin(j_it);
346  Cijk_type::kji_iterator i_end = Cijk->i_end(j_it);
347  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
348  int i = index(i_it);
349  int part = exportToPart[idx];
350  CijkData c;
351  c.i = i; c.j = j; c.k = k; c.gid = idx;
352  part_list[part].push_back(c);
353  ++idx;
354  }
355  }
356  }
357 
358  // Compute max/min bounding box dimensions
359  int dim_max = -1, dim_min = basis_size;
360  for (int part=0; part<num_parts; ++part) {
361  int imin = basis_size, jmin = basis_size, kmin = basis_size;
362  int imax = -1, jmax = -1, kmax = -1;
363  for (int idx=0; idx<part_list[part].size(); ++idx) {
364  if (part_list[part][idx].i < imin) imin = part_list[part][idx].i;
365  if (part_list[part][idx].j < jmin) jmin = part_list[part][idx].j;
366  if (part_list[part][idx].k < kmin) kmin = part_list[part][idx].k;
367  if (part_list[part][idx].i > imax) imax = part_list[part][idx].i;
368  if (part_list[part][idx].j > jmax) jmax = part_list[part][idx].j;
369  if (part_list[part][idx].k > kmax) kmax = part_list[part][idx].k;
370  }
371  int delta_i = imax - imin;
372  int delta_j = jmax - jmin;
373  int delta_k = kmax - kmin;
374  if (delta_i < dim_min) dim_min = delta_i;
375  if (delta_j < dim_min) dim_min = delta_j;
376  if (delta_k < dim_min) dim_min = delta_k;
377  if (delta_i > dim_max) dim_max = delta_i;
378  if (delta_j > dim_max) dim_max = delta_j;
379  if (delta_k > dim_max) dim_max = delta_k;
380  }
381  std::cout << "max part dimension = " << dim_max
382  << " min part dimension = " << dim_min << std::endl;
383 
384  if (save_3tensor) {
385  int idx = 0;
386  Cijk_type::k_iterator k_begin = Cijk->k_begin();
387  Cijk_type::k_iterator k_end = Cijk->k_end();
388  for (Cijk_type::k_iterator k_it=k_begin; k_it!=k_end; ++k_it) {
389  int k = index(k_it);
390  Cijk_type::kj_iterator j_begin = Cijk->j_begin(k_it);
391  Cijk_type::kj_iterator j_end = Cijk->j_end(k_it);
392  for (Cijk_type::kj_iterator j_it = j_begin; j_it != j_end; ++j_it) {
393  int j = index(j_it);
394  Cijk_type::kji_iterator i_begin = Cijk->i_begin(j_it);
395  Cijk_type::kji_iterator i_end = Cijk->i_end(j_it);
396  for (Cijk_type::kji_iterator i_it = i_begin; i_it != i_end; ++i_it) {
397  int i = index(i_it);
398  cijk_file << i << ", " << j << ", " << k << ", "
399  << exportToPart[idx++] << std::endl;
400  }
401  }
402  }
403  cijk_file.close();
404  }
405 
406  // Clean-up
407  Zoltan_LB_Free_Part(&importGlobalGids, &importLocalGids,
408  &importProcs, &importToPart);
409  Zoltan_LB_Free_Part(&exportGlobalGids, &exportLocalGids,
410  &exportProcs, &exportToPart);
411  Zoltan_Destroy(&zz);
412 
413  //Teuchos::TimeMonitor::summarize(std::cout);
414 
415  }
416  catch (std::exception& e) {
417  std::cout << e.what() << std::endl;
418  }
419 
420  return 0;
421 }
const ProductBasisType prod_basis_type_values[]
k_iterator k_begin() const
Iterator pointing to first k entry.
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...
void get_object_list(void *data, int sizeGID, int sizeLID, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int wgt_dim, float *obj_wgts, int *ierr)
void get_geometry_list(void *data, int sizeGID, int sizeLID, int num_obj, ZOLTAN_ID_PTR globalID, ZOLTAN_ID_PTR localID, int num_dim, double *geom_vec, int *ierr)
kj_iterator j_begin(const k_iterator &k) const
Iterator pointing to first j entry for given k.
const int num_prod_basis_types
int get_number_of_objects(void *data, int *ierr)
GrowthPolicy
Enumerated type for determining Smolyak growth policies.
const char * growth_type_names[]
const OrderingType ordering_type_values[]
const char * toString(const EReductionType reductType)
const int num_ordering_types
A comparison functor implementing a strict weak ordering based total-order ordering, recursive on the dimension.
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.
RCP< const Stokhos::ProductBasis< int, double > > basis
OrderingType
ProductBasisType
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
std::string toString(const HashSet< Key > &h)
Jacobi polynomial basis.
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
const Stokhos::GrowthPolicy growth_type_values[]
Multivariate orthogonal polynomial basis generated from a Smolyak sparse grid.
k_iterator k_end() const
Iterator pointing to last k entry.
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[])
size_type size() const
A comparison functor implementing a strict weak ordering based lexographic ordering.
int get_num_geometry(void *data, int *ierr)
Stokhos::Sparse3Tensor< int, double > Cijk_type
#define TEUCHOS_ASSERT(assertion_test)
RCP< const Stokhos::Sparse3Tensor< int, double > > Cijk
kji_iterator i_begin(const kj_iterator &j) const
Iterator pointing to first i entry for given j and k.
const char * ordering_type_names[]
kji_iterator i_end(const kj_iterator &j) const
Iterator pointing to last i entry for given j and k.
int n
const char * prod_basis_type_names[]
ordinal_type num_entries() const
Return number of non-zero entries.