Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gram_schmidt_example3.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 <iostream>
11 #include <iomanip>
12 
13 #include "Stokhos.hpp"
14 #include "Stokhos_Sacado.hpp"
16 
19 
20 // quadrature methods
22 static const int num_quadrature_method = 2;
24  TENSOR, SPARSE };
25 static const char *quadrature_method_names[] = {
26  "Tensor", "Sparse" };
27 
28 // reduced basis methods
30 static const int num_reduced_basis_method = 5;
33 static const char *reduced_basis_method_names[] = {
34  "Lanczos", "Monomial-Proj-GS", "Monomial-Proj-GS2", "Monomial-GS", "Lanczos-GS" };
35 
36 // orthogonalization methods
38 static const int num_orthogonalization_method = 8;
41 static const char *orthogonalization_method_names[] = {
42  "Householder", "Householder without Pivoting", "Classical Gram-Schmidt", "Modified Gram-Schmidt", "Modified Gram-Schmidt with Reorthogonalization", "Modified Gram-Schmidt without Pivoting", "Modified Gram-Schmidt without Pivoting with Reorthogonalization", "SVD" };
43 
44 // quadrature reduction methods
46 static const int num_quad_reduction_method = 4;
49 static const char *quad_reduction_method_names[] = {
50  "None", "Q Squared", "Q Squared2", "Q2" };
51 
52 // solver methods
54 static const int num_solver_method = 7;
57 static const char *solver_method_names[] = {
58  "TRSM", "GLPK", "Clp", "Clp-IP", "qpOASES", "Basis Pursuit", "Orthogonal Matching Pursuit" };
59 
62 
63 template <class ScalarType>
64 inline ScalarType f(const Teuchos::Array<ScalarType>& x,
65  double a, double b) {
66  ScalarType y = a;
67  int n = x.size();
68  for (int i=0; i<n; i++)
69  y += x[i] / (i+1.0);
70  y = b + 1.0/y;
71  return y;
72 }
73 
74 template <class ScalarType>
75 inline ScalarType g(const Teuchos::Array<ScalarType>& x,
76  const ScalarType& y) {
77  ScalarType z = y;
78  //ScalarType z = 0.0;
79  int n = x.size();
80  for (int i=0; i<n; i++)
81  z += x[i];
82  z = std::exp(z);
83  //z = y*z;
84  return z;
85 }
86 
87 double coeff_error(const pce_type& z, const pce_type& z2) {
88  double err_z = 0.0;
89  int n = std::min(z.size(), z2.size());
90  for (int i=0; i<n; i++) {
91  double ew = std::abs(z.coeff(i)-z2.coeff(i));
92  if (ew > err_z) err_z = ew;
93  }
94  return err_z;
95 }
96 
98  const Stokhos::Quadrature<int,double>& quad) {
99  const Teuchos::Array<double>& weights = quad.getQuadWeights();
101  quad.getBasisAtQuadPoints();
102  int nqp = quad.size();
103  int npc = basis.size();
104  double max_err = 0.0;
105 
106  // Loop over all basis function combinations
107  for (int i=0; i<npc; ++i) {
108  for (int j=0; j<npc; ++j) {
109 
110  // Compute inner product of ith and jth basis function
111  double err = 0.0;
112  for (int k=0; k<nqp; ++k)
113  err += weights[k]*vals[k][i]*vals[k][j];
114 
115  // Subtract off what it should be
116  if (i == j)
117  err -= basis.norm_squared(i);
118 
119  // Accumulate max error
120  if (std::abs(err) > max_err)
121  max_err = std::abs(err);
122  }
123  }
124  return max_err;
125 }
126 
127 struct MyOptions {
128  int d;
129  int d2;
130  int p_begin;
131  int p_end;
132  int p_truth;
133  double pole;
134  double shift;
138  bool verbose;
140  int level;
147  bool use_Q;
150  bool project;
152 };
153 
154 class MyResults {
155 public:
162  double mean_error;
164  double coeff_error;
169 };
170 
171 void compute_pces(bool compute_z_red, int p, const MyOptions& options,
172  MyResults& results)
173 {
174  // Create product basis
176  for (int i=0; i<options.d; i++)
177  bases[i] = Teuchos::rcp(new basis_type(p, true));
180 
181  results.basis_size = basis->size();
182 
183  // Quadrature
185  if (options.quad_method == TENSOR)
186  quad =
188  else if (options.quad_method == SPARSE) {
189 #ifdef HAVE_STOKHOS_DAKOTA
190  if (options.level == -1)
191  quad =
192  Teuchos::rcp(new Stokhos::SparseGridQuadrature<int,double>(basis));
193  else
194  quad =
195  Teuchos::rcp(new Stokhos::SparseGridQuadrature<int,double>(
196  basis, p, 1e-12, Pecos::SLOW_RESTRICTED_GROWTH));
197 #else
198  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Sparse grid quadrature only supported when compiled with Dakota!");
199 #endif
200  }
201 
202  results.quad_size = quad->size();
203 
204  // Triple product tensor
206  basis->computeTripleProductTensor();
207 
208  // Quadrature expansion
211  Cijk,
212  quad));
213 
214  // Create approximation
215  Teuchos::Array<double> point(options.d, 1.0);
216  Teuchos::Array<double> basis_vals(basis->size());
217  basis->evaluateBases(point, basis_vals);
218  Teuchos::Array<pce_type> x(options.d);
219  for (int i=0; i<options.d; i++) {
220  x[i].copyForWrite();
221  x[i].reset(quad_exp);
222  x[i].term(i,1) = 1.0 / basis_vals[i+1];
223  }
224  Teuchos::Array<pce_type> x2(options.d2);
225  for (int i=0; i<options.d2; i++) {
226  x2[i] = x[i];
227  }
228 
229  // Compute PCE via quadrature expansion
230  pce_type y = f(x, options.pole, options.shift);
231  results.z = g(x2, y);
232 
233  if (!compute_z_red)
234  return;
235 
236  // Create new basis from (x2,y)
238  for (int i=0; i<options.d2; i++)
239  pces[i] = x2[i].getOrthogPolyApprox();
240  pces[options.d2] = y.getOrthogPolyApprox();
241  Teuchos::ParameterList params;
242  if (options.reduced_basis_method == MONOMIAL_PROJ_GS)
243  params.set("Reduced Basis Method", "Monomial Proj Gram-Schmidt");
244  else if (options.reduced_basis_method == MONOMIAL_PROJ_GS2)
245  params.set("Reduced Basis Method", "Monomial Proj Gram-Schmidt2");
246  else if (options.reduced_basis_method == MONOMIAL_GS)
247  params.set("Reduced Basis Method", "Monomial Gram-Schmidt");
248  else if (options.reduced_basis_method == LANCZOS)
249  params.set("Reduced Basis Method", "Product Lanczos");
250  else if (options.reduced_basis_method == LANCZOS_GS)
251  params.set("Reduced Basis Method", "Product Lanczos Gram-Schmidt");
252  params.set("Verbose", options.verbose);
253  params.set("Project", options.project);
254  //params.set("Normalize", false);
255  params.set("Use Old Stieltjes Method", options.use_stieltjes);
256  params.set("Orthogonalization Method",
258  params.set("Rank Threshold", options.rank_threshold);
259  Teuchos::ParameterList& red_quad_params =
260  params.sublist("Reduced Quadrature");
261  red_quad_params.set(
262  "Reduced Quadrature Method",
264  red_quad_params.set(
265  "Solver Method", solver_method_names[options.solver_method]);
266  red_quad_params.set(
267  "Eliminate Dependent Rows", options.eliminate_dependent_rows);
268  red_quad_params.set("Write MPS File", false);
269  red_quad_params.set("Reduction Tolerance", options.reduction_tolerance);
270  red_quad_params.set("Verbose", options.verbose);
271  red_quad_params.set("Objective Value", options.objective_value);
272  red_quad_params.set("Q2 Rank Threshold", options.rank_threshold2);
273  red_quad_params.set(
274  "Orthogonalization Method",
276  red_quad_params.set("Use Q in LP", options.use_Q);
277  red_quad_params.set("Restrict Rank", options.restrict_r);
278  red_quad_params.set("Order Restriction", 2*p);
281  factory.createReducedBasis(p, pces, quad, Cijk);
283  gs_basis->getReducedQuadrature();
284 
285  results.reduced_basis_size = gs_basis->size();
286  results.reduced_quad_size = gs_quad->size();
287 
288  // Triple product tensor & expansion
292  if (options.reduced_basis_method == LANCZOS)
293  gs_Cijk = gs_basis->computeTripleProductTensor();
294  else {
295  gs_Cijk = Teuchos::null;
296  gs_exp_params->set("Use Quadrature for Times", true);
297  }
300  gs_basis, gs_Cijk, gs_quad, gs_exp_params));
301 
302  // Create new expansions
303  Teuchos::Array<pce_type> x2_gs(options.d2);
304  for (int i=0; i<options.d2; i++) {
305  x2_gs[i].copyForWrite();
306  x2_gs[i].reset(gs_quad_exp);
307  gs_basis->transformFromOriginalBasis(x2[i].coeff(), x2_gs[i].coeff());
308  }
309  pce_type y_gs(gs_quad_exp);
310  gs_basis->transformFromOriginalBasis(y.coeff(), y_gs.coeff());
311 
312  // Compute z_gs = g(x2_gs, y_gs) in Gram-Schmidt basis
313  pce_type z_gs = g(x2_gs, y_gs);
314 
315  // Project z_gs back to original basis
316  pce_type z2(quad_exp);
317  gs_basis->transformToOriginalBasis(z_gs.coeff(), z2.coeff());
318  results.z_red = z2;
319 
320  // Compute discrete orthogonality error
321  results.disc_orthog_error = disc_orthog_error(*gs_basis, *gs_quad);
322 }
323 
324 int main(int argc, char **argv)
325 {
326  try {
327 
328  // Setup command line options
330  CLP.setDocString(
331  "This example runs a Gram-Schmidt-based dimension reduction example.\n");
332  MyOptions options;
333 
334  options.d = 4;
335  CLP.setOption("d", &options.d, "Stochastic dimension");
336 
337  options.d2 = 1;
338  CLP.setOption("d2", &options.d2, "Intermediate stochastic dimension");
339 
340  options.p_begin = 1;
341  CLP.setOption("p_begin", &options.p_begin, "Starting polynomial order");
342 
343  options.p_end = 5;
344  CLP.setOption("p_end", &options.p_end, "Ending polynomial order");
345 
346  options.p_truth = 7;
347  CLP.setOption("p_truth", &options.p_truth, "Truth polynomial order");
348 
349  options.pole = 10.0;
350  CLP.setOption("pole", &options.pole, "Pole location");
351 
352  options.shift = 0.0;
353  CLP.setOption("shift", &options.shift, "Shift location");
354 
355  options.rank_threshold = 1.0e-120;
356  CLP.setOption("rank_threshold", &options.rank_threshold, "Rank threshold");
357 
358  options.rank_threshold2 = 1.0e-120;
359  CLP.setOption("rank_threshold2", &options.rank_threshold2, "Rank threshold for Q2");
360 
361  options.reduction_tolerance = 1.0e-12;
362  CLP.setOption("reduction_tolerance", &options.reduction_tolerance, "Quadrature reduction tolerance");
363 
364  options.verbose = false;
365  CLP.setOption("verbose", "quiet", &options.verbose, "Verbose output");
366 
367  options.quad_method = TENSOR;
368  CLP.setOption("quadrature_method", &options.quad_method,
370  quadrature_method_names, "Quadrature method");
371 
372  options.level = -1;
373  CLP.setOption("level", &options.level,
374  "Sparse grid level (set to -1 to use default)");
375 
377  CLP.setOption("reduced_basis_method", &options.reduced_basis_method,
379  reduced_basis_method_names, "Reduced basis method");
380 
382  CLP.setOption("orthogonalization_method",
383  &options.orthogonalization_method,
387  "Orthogonalization method");
388 
390  CLP.setOption("reduced_quadrature_method", &options.quad_reduction_method,
392  quad_reduction_method_names, "Reduced quadrature method");
393 
394  options.solver_method = TRSM;
395  CLP.setOption("solver_method", &options.solver_method, num_solver_method,
397  "Reduced quadrature solver method");
398 
400  CLP.setOption("quad_orthogonalization_method",
405  "Quadrature Orthogonalization method");
406 
407  options.eliminate_dependent_rows = true;
408  CLP.setOption("cpqr", "no-cpqr", &options.eliminate_dependent_rows,
409  "Eliminate dependent rows in quadrature constraint matrix");
410 
411  options.use_Q = true;
412  CLP.setOption("use-Q", "no-use-Q", &options.use_Q, "Use Q in LP");
413 
414  options.restrict_r = false;
415  CLP.setOption("restrict-rank", "no-restrict-rank", &options.restrict_r,
416  "Restrict rank in LP");
417 
418  options.objective_value = 0.0;
419  CLP.setOption("objective_value", &options.objective_value,
420  "Value for LP objective function");
421 
422  options.project = true;
423  CLP.setOption("project", "no-project", &options.project,
424  "Use Projected Lanczos Method");
425 
426  options.use_stieltjes = false;
427  CLP.setOption("stieltjes", "no-stieltjes", &options.use_stieltjes,
428  "Use Old Stieltjes Method");
429 
430  CLP.parse( argc, argv );
431 
432  std::cout << "Summary of command line options:" << std::endl
433  << "\tquadrature_method = "
435  << std::endl
436  << "\tlevel = " << options.level
437  << std::endl
438  << "\treduced_basis_method = "
440  << std::endl
441  << "\torthogonalization_method = "
443  << std::endl
444  << "\tquadrature_reduction_method = "
446  << std::endl
447  << "\tsolver_method = "
448  << solver_method_names[options.solver_method] << std::endl
449  << "\tquad_orthogonalization_method = "
451  << std::endl
452  << "\tcpqr = " << options.eliminate_dependent_rows
453  << std::endl
454  << "\tuse-Q = " << options.use_Q << std::endl
455  << "\trestrict-rank = " << options.restrict_r << std::endl
456  << "\tobjective_value = " << options.objective_value << std::endl
457  << "\tproject = " << options.project << std::endl
458  << "\tstieljtes = " << options.use_stieltjes << std::endl
459  << "\tp_begin = " << options.p_begin << std::endl
460  << "\tp_end = " << options.p_end << std::endl
461  << "\tp_truth = " << options.p_truth << std::endl
462  << "\td = " << options.d << std::endl
463  << "\td2 = " << options.d2 << std::endl
464  << "\tpole = " << options.pole << std::endl
465  << "\tshift = " << options.shift << std::endl
466  << "\trank_threshold = " << options.rank_threshold << std::endl
467  << "\trank_threshold2 = " << options.rank_threshold2 << std::endl
468  << "\treduction_tolerance = " << options.reduction_tolerance
469  << std::endl
470  << "\tverbose = " << options.verbose << std::endl
471  << std::endl << std::endl;
472 
473  std::stringstream ss;
474  typedef Teuchos::TabularOutputter TO;
475  TO out(ss);
476  out.setFieldTypePrecision(TO::DOUBLE, 5);
477  out.pushFieldSpec("\"Order\"", TO::INT);
478  out.pushFieldSpec("\"Basis Size\"", TO::INT);
479  out.pushFieldSpec("\"Quad. Size\"", TO::INT);
480  out.pushFieldSpec("\"Red. Basis Size\"", TO::INT);
481  out.pushFieldSpec("\"Red. Quad. Size\"", TO::INT);
482  out.pushFieldSpec("\"Coeff. Error\"", TO::DOUBLE);
483  out.pushFieldSpec("\"Red. Coeff. Error\"", TO::DOUBLE);
484  out.pushFieldSpec("\"Disc. Orthog. Error\"", TO::DOUBLE);
485  out.outputHeader();
486 
487  MyResults results_truth;
488  compute_pces(false, options.p_truth, options, results_truth);
489 
490  int n = options.p_end - options.p_begin + 1;
491  Teuchos::Array<MyResults> results(n);
492  for (int i=0; i<n; ++i) {
493  int p = options.p_begin + i;
494  compute_pces(true, p, options, results[i]);
495  results[i].mean_error =
496  std::abs(results_truth.z.mean()-results[i].z.mean()) /
497  std::abs(results_truth.z.mean());
498  results[i].std_dev_error =
499  std::abs(results_truth.z.standard_deviation()-results[i].z.standard_deviation()) / std::abs(results_truth.z.standard_deviation());
500  results[i].coeff_error = coeff_error(results_truth.z,
501  results[i].z);
502 
503  results[i].reduced_mean_error =
504  std::abs(results_truth.z.mean()-results[i].z_red.mean()) /
505  std::abs(results_truth.z.mean());
506  results[i].reduced_std_dev_error =
507  std::abs(results_truth.z.standard_deviation()-results[i].z_red.standard_deviation()) / std::abs(results_truth.z.standard_deviation());
508  results[i].reduced_coeff_error = coeff_error(results_truth.z,
509  results[i].z_red);
510 
511  out.outputField(p);
512  out.outputField(results[i].basis_size);
513  out.outputField(results[i].quad_size);
514  out.outputField(results[i].reduced_basis_size);
515  out.outputField(results[i].reduced_quad_size);
516  out.outputField(results[i].coeff_error);
517  out.outputField(results[i].reduced_coeff_error);
518  out.outputField(results[i].disc_orthog_error);
519  out.nextRow();
520  }
521  std::cout << std::endl << ss.str() << std::endl;
522 
523  }
524  catch (std::exception& e) {
525  std::cout << e.what() << std::endl;
526  }
527 }
static const Reduced_Basis_Method reduced_basis_method_values[]
static const Quadrature_Reduction_Method quad_reduction_method_values[]
Orthogonalization_Method quad_orthogonalization_method
Sacado::ETPCE::OrthogPoly< double, Stokhos::StandardStorage< int, double > > pce_type
static const int num_quadrature_method
static const int num_reduced_basis_method
Generate a basis from a given set of PCE expansions that is orthogonal with respect to the product me...
static const int num_orthogonalization_method
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual ordinal_type size() const =0
Get number of quadrature points.
virtual const Teuchos::Array< Teuchos::Array< value_type > > & getBasisAtQuadPoints() const =0
Get values of basis at quadrature points.
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
static const int num_quad_reduction_method
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Quadrature_Method quad_method
static const char * orthogonalization_method_names[]
static const char * reduced_basis_method_names[]
Stokhos::LegendreBasis< int, double > basis_type
KOKKOS_INLINE_FUNCTION PCE< Storage > min(const typename PCE< Storage >::value_type &a, const PCE< Storage > &b)
virtual const Teuchos::Array< value_type > & getQuadWeights() const =0
Get quadrature weights.
Quadrature_Reduction_Method
Quadrature_Reduction_Method quad_reduction_method
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)
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
KOKKOS_INLINE_FUNCTION PCE< Storage > abs(const PCE< Storage > &a)
double disc_orthog_error(const Stokhos::OrthogPolyBasis< int, double > &basis, const Stokhos::Quadrature< int, double > &quad)
Solver_Method solver_method
virtual const Teuchos::Array< value_type > & norm_squared() const =0
Return array storing norm-squared of each basis polynomial.
KOKKOS_INLINE_FUNCTION PCE< Storage > exp(const PCE< Storage > &a)
virtual Teuchos::RCP< Stokhos::ReducedPCEBasis< ordinal_type, value_type > > createReducedBasis(ordinal_type p, const Teuchos::Array< Stokhos::OrthogPolyApprox< ordinal_type, value_type > > &pce, const Teuchos::RCP< const Stokhos::Quadrature< ordinal_type, value_type > > &quad, const Teuchos::RCP< const Stokhos::Sparse3Tensor< ordinal_type, value_type > > &Cijk) const
Get reduced quadrature object.
Legendre polynomial basis.
Orthogonalization_Method orthogonalization_method
double coeff_error(const pce_type &z, const pce_type &z2)
static const Solver_Method solver_method_values[]
static const int num_solver_method
int main(int argc, char **argv)
static const char * quadrature_method_names[]
static const char * quad_reduction_method_names[]
ScalarType f(const Teuchos::Array< ScalarType > &x, double a, double b)
void setDocString(const char doc_string[])
size_type size() const
static const char * solver_method_names[]
static const Quadrature_Method quadrature_method_values[]
Reduced_Basis_Method
static const Orthogonalization_Method orthogonalization_method_values[]
Orthogonalization_Method
int n
Defines quadrature for a tensor product basis by tensor products of 1-D quadrature rules...
void compute_pces(bool compute_z_red, int p, const MyOptions &options, MyResults &results)
virtual ordinal_type size() const =0
Return total size of basis.
ScalarType g(const Teuchos::Array< ScalarType > &x, const ScalarType &y)
Reduced_Basis_Method reduced_basis_method