Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
linear2d_diffusion_collocation_strat.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 // ModelEvaluator implementing our problem
11 #include "twoD_diffusion_ME.hpp"
12 
13 // Epetra communicator
14 #ifdef HAVE_MPI
15 #include "Epetra_MpiComm.h"
16 #else
17 #include "Epetra_SerialComm.h"
18 #endif
19 
20 // Stratimikos stuff
21 #include "Stratimikos_DefaultLinearSolverBuilder.hpp"
22 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
23 #include "Thyra_PreconditionerBase.hpp"
24 #include "Thyra_PreconditionerFactoryBase.hpp"
25 #include "Thyra_EpetraThyraWrappers.hpp"
26 #include "Thyra_EpetraLinearOp.hpp"
27 
28 // Stokhos Stochastic Galerkin
29 #include "Stokhos.hpp"
30 
31 // Timing utilities
33 #include "Teuchos_TimeMonitor.hpp"
34 
35 // I/O utilities
36 #include "EpetraExt_VectorOut.h"
37 
38 // Linear solvers
40 const int num_krylov_solver = 2;
42 const char *krylov_solver_names[] = { "AztecOO", "Belos" };
43 
44 // Krylov methods
46 const int num_krylov_method = 4;
48 const char *krylov_method_names[] = { "GMRES", "CG", "FGMRES", "RGMRES" };
49 
50 // Collocation preconditioning strategies
52 const int num_prec_strategy = 2;
54 const char *prec_strategy_names[] = { "Mean", "Rebuild" };
55 
56 // Random field types
58 const int num_sg_rf = 4;
60 const char *sg_rf_names[] = { "Uniform", "CC-Uniform", "Rys", "Log-Normal" };
61 
62 // Sparse grid growth rules
64 const int num_sg_growth = 3;
67 const char *sg_growth_names[] = {
68  "Slow Restricted", "Moderate Restricted", "Unrestricted" };
69 
70 int main(int argc, char *argv[]) {
71 
72 // Initialize MPI
73 #ifdef HAVE_MPI
74  MPI_Init(&argc,&argv);
75 #endif
76 
77  // Create a communicator for Epetra objects
79 #ifdef HAVE_MPI
80  Comm = Teuchos::rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
81 #else
82  Comm = Teuchos::rcp(new Epetra_SerialComm);
83 #endif
84 
85  int MyPID = Comm->MyPID();
86 
87  try {
88 
89  // Setup command line options
91  CLP.setDocString(
92  "This example runs a stochastic collocation method.\n");
93 
94  int n = 32;
95  CLP.setOption("num_mesh", &n, "Number of mesh points in each direction");
96 
97  SG_RF randField = UNIFORM;
98  CLP.setOption("rand_field", &randField,
100  "Random field type");
101 
102  double mean = 0.2;
103  CLP.setOption("mean", &mean, "Mean");
104 
105  double sigma = 0.1;
106  CLP.setOption("std_dev", &sigma, "Standard deviation");
107 
108  double weightCut = 1.0;
109  CLP.setOption("weight_cut", &weightCut, "Weight cut");
110 
111  int num_KL = 2;
112  CLP.setOption("num_kl", &num_KL, "Number of KL terms");
113 
114  int p = 3;
115  CLP.setOption("order", &p, "Polynomial order");
116 
117  bool normalize_basis = true;
118  CLP.setOption("normalize", "unnormalize", &normalize_basis,
119  "Normalize PC basis");
120 
121  Krylov_Solver krylov_solver = AZTECOO;
122  CLP.setOption("krylov_solver", &krylov_solver,
124  "Linear solver");
125 
126  Krylov_Method krylov_method = CG;
127  CLP.setOption("krylov_method", &krylov_method,
129  "Krylov method");
130 
131  PrecStrategy precStrategy = MEAN;
132  CLP.setOption("prec_strategy", &precStrategy,
134  "Preconditioner strategy");
135 
136  double tol = 1e-12;
137  CLP.setOption("tol", &tol, "Solver tolerance");
138 
139  SG_GROWTH sg_growth = MODERATE_RESTRICTED;
140  CLP.setOption("sg_growth", &sg_growth,
142  "Sparse grid growth rule");
143 
144  CLP.parse( argc, argv );
145 
146  if (MyPID == 0) {
147  std::cout << "Summary of command line options:" << std::endl
148  << "\tnum_mesh = " << n << std::endl
149  << "\trand_field = " << sg_rf_names[randField] << std::endl
150  << "\tmean = " << mean << std::endl
151  << "\tstd_dev = " << sigma << std::endl
152  << "\tweight_cut = " << weightCut << std::endl
153  << "\tnum_kl = " << num_KL << std::endl
154  << "\torder = " << p << std::endl
155  << "\tnormalize_basis = " << normalize_basis << std::endl
156  << "\tkrylov_solver = " << krylov_solver_names[krylov_solver]
157  << std::endl
158  << "\tkrylov_method = " << krylov_method_names[krylov_method]
159  << std::endl
160  << "\tprec_strategy = " << prec_strategy_names[precStrategy]
161  << std::endl
162  << "\ttol = " << tol << std::endl
163  << "\tsg_growth = " << sg_growth_names[sg_growth]
164  << std::endl;
165  }
166 
167  bool nonlinear_expansion = false;
168  if (randField == LOGNORMAL)
169  nonlinear_expansion = true;
170 
171  {
172  TEUCHOS_FUNC_TIME_MONITOR("Total Collocation Calculation Time");
173 
174  // Create Stochastic Galerkin basis
176  for (int i=0; i<num_KL; i++) {
178  if (randField == UNIFORM) {
180  p, normalize_basis));
181  }
182  else if (randField == CC_UNIFORM) {
183  b =
185  p, normalize_basis, true));
186  }
187  else if (randField == RYS) {
189  p, weightCut, normalize_basis));
190  }
191  else if (randField == LOGNORMAL) {
193  p, normalize_basis));
194  }
195  bases[i] = b;
196  }
199 
200  // Create sparse grid
201  int sparse_grid_growth = Pecos::MODERATE_RESTRICTED_GROWTH;
202  if (sg_growth == SLOW_RESTRICTED)
203  sparse_grid_growth = Pecos::SLOW_RESTRICTED_GROWTH;
204  else if (sg_growth == MODERATE_RESTRICTED)
205  sparse_grid_growth = Pecos::MODERATE_RESTRICTED_GROWTH;
206  else if (sg_growth == UNRESTRICTED)
207  sparse_grid_growth = Pecos::UNRESTRICTED_GROWTH;
208  Stokhos::SparseGridQuadrature<int,double> quad(basis,p,1e-12,sg_growth);
209  const Teuchos::Array< Teuchos::Array<double> >& quad_points =
210  quad.getQuadPoints();
211  const Teuchos::Array<double>& quad_weights =
212  quad.getQuadWeights();
213  int nqp = quad_weights.size();
214 
215  // Create application
216  twoD_diffusion_ME model(Comm, n, num_KL, sigma, mean,
217  basis, nonlinear_expansion);
218 
219  // Model data
221  Teuchos::rcp(new Epetra_Vector(*(model.get_p_map(0))));
223  Teuchos::rcp(new Epetra_Vector(*(model.get_x_map())));
225  Teuchos::rcp(new Epetra_Vector(*(model.get_f_map())));
227  Teuchos::rcp(new Epetra_Vector(*(model.get_g_map(0))));
229  Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(model.create_W());
230  EpetraExt::ModelEvaluator::InArgs inArgs = model.createInArgs();
231  EpetraExt::ModelEvaluator::OutArgs outArgs = model.createOutArgs();
232  EpetraExt::ModelEvaluator::OutArgs outArgs2 = model.createOutArgs();
233 
234  // Data to compute/store mean & variance
235  Epetra_Vector x2(*(model.get_x_map()));
236  Epetra_Vector x_mean(*(model.get_x_map()));
237  Epetra_Vector x_var(*(model.get_x_map()));
238  Epetra_Vector g2(*(model.get_g_map(0)));
239  Epetra_Vector g_mean(*(model.get_g_map(0)));
240  Epetra_Vector g_var(*(model.get_g_map(0)));
241 
242  // Create ParameterList controlling Stratimikos
243  Teuchos::ParameterList stratParams;
244  if (krylov_solver == AZTECOO) {
245  stratParams.set("Linear Solver Type", "AztecOO");
246  Teuchos::ParameterList& aztecParams =
247  stratParams.sublist("Linear Solver Types").sublist("AztecOO").sublist("Forward Solve");
248  aztecParams.set("Max Iterations", 1000);
249  aztecParams.set("Tolerance", tol);
250  Teuchos::ParameterList& aztecSettings =
251  aztecParams.sublist("AztecOO Settings");
252  if (krylov_method == GMRES)
253  aztecSettings.set("Aztec Solver", "GMRES");
254  else if (krylov_method == CG)
255  aztecSettings.set("Aztec Solver", "CG");
256  aztecSettings.set("Aztec Preconditioner", "none");
257  aztecSettings.set("Size of Krylov Subspace", 100);
258  aztecSettings.set("Convergence Test", "r0");
259  aztecSettings.set("Output Frequency", 10);
260  Teuchos::ParameterList& verbParams =
261  stratParams.sublist("Linear Solver Types").sublist("AztecOO").sublist("VerboseObject");
262  verbParams.set("Verbosity Level", "none");
263  }
264  else if (krylov_solver == BELOS) {
265  stratParams.set("Linear Solver Type", "Belos");
266  Teuchos::ParameterList& belosParams =
267  stratParams.sublist("Linear Solver Types").sublist("Belos");
268  Teuchos::ParameterList* belosSolverParams = NULL;
269  if (krylov_method == GMRES || krylov_method == FGMRES) {
270  belosParams.set("Solver Type","Block GMRES");
271  belosSolverParams =
272  &(belosParams.sublist("Solver Types").sublist("Block GMRES"));
273  if (krylov_method == FGMRES)
274  belosSolverParams->set("Flexible Gmres", true);
275  }
276  else if (krylov_method == RGMRES) {
277  belosParams.set("Solver Type","GCRODR");
278  belosSolverParams =
279  &(belosParams.sublist("Solver Types").sublist("GCRODR"));
280  belosSolverParams->set("Num Recycled Blocks", 10);
281  }
282  else if (krylov_method == CG) {
283  belosParams.set("Solver Type","Block CG");
284  belosSolverParams =
285  &(belosParams.sublist("Solver Types").sublist("Block CG"));
286  }
287 
288  belosSolverParams->set("Convergence Tolerance", tol);
289  belosSolverParams->set("Maximum Iterations", 1000);
290  belosSolverParams->set("Num Blocks", 100);
291  belosSolverParams->set("Output Frequency",10);
292  Teuchos::ParameterList& verbParams = belosParams.sublist("VerboseObject");
293  verbParams.set("Verbosity Level", "none");
294  }
295  stratParams.set("Preconditioner Type", "ML");
296  Teuchos::ParameterList& precParams =
297  stratParams.sublist("Preconditioner Types").sublist("ML").sublist("ML Settings");
298  precParams.set("default values", "SA");
299  precParams.set("ML output", 0);
300  precParams.set("max levels",5);
301  precParams.set("increasing or decreasing","increasing");
302  precParams.set("aggregation: type", "Uncoupled");
303  precParams.set("smoother: type","ML symmetric Gauss-Seidel");
304  precParams.set("smoother: sweeps",2);
305  precParams.set("smoother: pre or post", "both");
306  precParams.set("coarse: max size", 200);
307 #ifdef HAVE_ML_AMESOS
308  precParams.set("coarse: type","Amesos-KLU");
309 #else
310  precParams.set("coarse: type","Jacobi");
311 #endif
312 
313  // Create Stratimikos linear solver builder
314  Stratimikos::DefaultLinearSolverBuilder linearSolverBuilder;
315  linearSolverBuilder.setParameterList(Teuchos::rcp(&stratParams, false));
316 
317  // Create a linear solver factory given information read from the
318  // parameter list.
320  linearSolverBuilder.createLinearSolveStrategy("");
322  Teuchos::VerboseObjectBase::getDefaultOStream();
323  lowsFactory->setOStream(out);
324  lowsFactory->setVerbLevel(Teuchos::VERB_LOW);
325 
326  // Initialize the LinearOpWithSolve
328  lowsFactory->createOp();
330  lowsFactory->getPreconditionerFactory();
332  precFactory->createPrec();
333 
334  // Wrap Thyra objects around Epetra objects
336  Thyra::epetraLinearOp(A);
338  rcp(new Thyra::DefaultLinearOpSource<double>(A_thyra));
339 
340  // Create solver convergence criteria
342  if (!(krylov_solver == BELOS && krylov_method == CG)) {
343  // For some reason, Belos' Block-CG doesn't support this
344  Thyra::SolveMeasureType solveMeasure(
345  Thyra::SOLVE_MEASURE_NORM_RESIDUAL,
346  Thyra::SOLVE_MEASURE_NORM_INIT_RESIDUAL);
347  solveCriteria =
348  Teuchos::rcp(new Thyra::SolveCriteria<double>(solveMeasure, tol));
349  }
350 
351  // Computation of prec happens here:
352  if (precStrategy == MEAN) {
353  TEUCHOS_FUNC_TIME_MONITOR("Deterministic Preconditioner Calculation");
354  *A = *(model.get_mean());
355  precFactory->initializePrec(losb, M_thyra.get());
356  Thyra::initializePreconditionedOp<double>(
357  *lowsFactory, A_thyra, M_thyra, lows.ptr());
358  }
359 
360  x_mean.PutScalar(0.0);
361  x_var.PutScalar(0.0);
362  // Loop over colloction points
363  for (int qp=0; qp<nqp; qp++) {
364  TEUCHOS_FUNC_TIME_MONITOR("Collocation Loop");
365 
366  // Set parameters
367  for (int i=0; i<num_KL; i++)
368  (*p)[i] = quad_points[qp][i];
369 
370  // Set in/out args
371  inArgs.set_p(0, p);
372  inArgs.set_x(x);
373  outArgs.set_f(f);
374  outArgs.set_W(A);
375 
376  // Evaluate model at collocation point
377  x->PutScalar(0.0);
378  model.evalModel(inArgs, outArgs);
379  f->Scale(-1.0);
380 
382  Thyra::create_Vector(x, A_thyra->domain());
384  Thyra::create_Vector(f, A_thyra->range());
385 
386  // Compute preconditioner
387  if (precStrategy != MEAN) {
388  TEUCHOS_FUNC_TIME_MONITOR("Deterministic Preconditioner Calculation");
389  precFactory->initializePrec(losb, M_thyra.get());
390  Thyra::initializePreconditionedOp<double>(
391  *lowsFactory, A_thyra, M_thyra, lows.ptr());
392  }
393 
394  // Solve linear system
395  {
396  TEUCHOS_FUNC_TIME_MONITOR("Deterministic Solve");
397  Thyra::SolveStatus<double> solveStatus =
398  lows->solve(Thyra::NOTRANS, *f_thyra, x_thyra.ptr(),
399  solveCriteria.ptr());
400  if (MyPID == 0) {
401  std::cout << "Collocation point " << qp+1 <<'/' << nqp << ": "
402  << solveStatus.message << std::endl;
403  }
404  }
405 
406  x_thyra = Teuchos::null;
407  f_thyra = Teuchos::null;
408 
409  // Compute responses
410  outArgs2.set_g(0, g);
411  model.evalModel(inArgs, outArgs2);
412 
413  // Sum contributions to mean and variance
414  x2.Multiply(1.0, *x, *x, 0.0);
415  g2.Multiply(1.0, *g, *g, 0.0);
416  x_mean.Update(quad_weights[qp], *x, 1.0);
417  x_var.Update(quad_weights[qp], x2, 1.0);
418  g_mean.Update(quad_weights[qp], *g, 1.0);
419  g_var.Update(quad_weights[qp], g2, 1.0);
420 
421  }
422  x2.Multiply(1.0, x_mean, x_mean, 0.0);
423  g2.Multiply(1.0, g_mean, g_mean, 0.0);
424  x_var.Update(-1.0, x2, 1.0);
425  g_var.Update(-1.0, g2, 1.0);
426 
427  // Compute standard deviations
428  for (int i=0; i<x_var.MyLength(); i++)
429  x_var[i] = std::sqrt(x_var[i]);
430  for (int i=0; i<g_var.MyLength(); i++)
431  g_var[i] = std::sqrt(g_var[i]);
432 
433  std::cout.precision(16);
434  std::cout << "\nResponse Mean = " << std::endl << g_mean << std::endl;
435  std::cout << "Response Std. Dev. = " << std::endl << g_var << std::endl;
436 
437  // Save mean and variance to file
438  EpetraExt::VectorToMatrixMarketFile("mean_col.mm", x_mean);
439  EpetraExt::VectorToMatrixMarketFile("std_dev_col.mm", x_var);
440 
441  }
442 
445 
446  }
447 
448  catch (std::exception& e) {
449  std::cout << e.what() << std::endl;
450  }
451  catch (std::string& s) {
452  std::cout << s << std::endl;
453  }
454  catch (char *s) {
455  std::cout << s << std::endl;
456  }
457  catch (...) {
458  std::cout << "Caught unknown exception!" <<std:: endl;
459  }
460 
461 #ifdef HAVE_MPI
462  MPI_Finalize() ;
463 #endif
464 
465 }
const char * prec_strategy_names[]
KOKKOS_INLINE_FUNCTION PCE< Storage > sqrt(const PCE< Storage > &a)
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
Hermite polynomial basis.
const Krylov_Method krylov_method_values[]
void evalModel(const InArgs &inArgs, const OutArgs &outArgs) const
Evaluate model on InArgs.
Teuchos::RCP< Epetra_CrsMatrix > get_mean() const
Get mean matrix.
const int num_prec_strategy
RCP< ParameterList > sublist(const RCP< ParameterList > &paramList, const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
T * get() const
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
const char * krylov_solver_names[]
virtual int MyPID() const =0
const SG_GROWTH sg_growth_values[]
const char * sg_growth_names[]
ModelEvaluator for a linear 2-D diffusion problem.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Rys polynomial basis.
const int num_krylov_method
static void summarize(Ptr< const Comm< int > > comm, std::ostream &out=std::cout, const bool alwaysWriteLocal=false, const bool writeGlobalStats=true, const bool writeZeroTimers=true, const ECounterSetOp setOp=Intersection, const std::string &filter="", const bool ignoreZeroTimers=false)
void setOption(const char option_true[], const char option_false[], bool *option_val, const char documentation[]=NULL)
Ptr< T > ptr() const
const SG_RF sg_rf_values[]
EParseCommandLineReturn parse(int argc, char *argv[], std::ostream *errout=&std::cerr) const
const int num_sg_rf
Teuchos::RCP< const Epetra_Map > get_p_map(int l) const
Return parameter vector map.
Teuchos::RCP< const Epetra_Map > get_g_map(int j) const
Return response function map.
Legendre polynomial basis.
int main(int argc, char **argv)
Teuchos::RCP< Epetra_Operator > create_W() const
Create W = alpha*M + beta*J matrix.
InArgs createInArgs() const
Create InArgs.
const char * sg_rf_names[]
OutArgs createOutArgs() const
Create OutArgs.
ScalarType f(const Teuchos::Array< ScalarType > &x, double a, double b)
Legendre polynomial basis using Clenshaw-Curtis quadrature points.
void setDocString(const char doc_string[])
const int num_sg_growth
size_type size() const
Teuchos::RCP< const Epetra_Map > get_x_map() const
Return solution vector map.
const PrecStrategy prec_strategy_values[]
const Krylov_Solver krylov_solver_values[]
int n
ScalarType g(const Teuchos::Array< ScalarType > &x, const ScalarType &y)
static void zeroOutTimers()
Teuchos::RCP< const Epetra_Map > get_f_map() const
Return residual vector map.
const char * krylov_method_names[]