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_pce_nox.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 // NOX
21 #include "NOX.H"
22 #include "NOX_Epetra.H"
23 
24 // Stokhos Stochastic Galerkin
25 #include "Stokhos_Epetra.hpp"
26 
27 // Timing utilities
28 #include "Teuchos_TimeMonitor.hpp"
29 
30 // I/O utilities
31 #include "EpetraExt_VectorOut.h"
32 
33 int main(int argc, char *argv[]) {
34  int n = 32; // spatial discretization (per dimension)
35  int num_KL = 2; // number of KL terms
36  int p = 3; // polynomial order
37  double mu = 0.1; // mean of exponential random field
38  double s = 0.2; // std. dev. of exponential r.f.
39  bool nonlinear_expansion = false; // nonlinear expansion of diffusion coeff
40  // (e.g., log-normal)
41  bool matrix_free = true; // use matrix-free stochastic operator
42  bool symmetric = false; // use symmetric formulation
43 
44  double g_mean_exp = 0.172988; // expected response mean
45  double g_std_dev_exp = 0.0380007; // expected response std. dev.
46  double g_tol = 1e-6; // tolerance on determining success
47 
48 // Initialize MPI
49 #ifdef HAVE_MPI
50  MPI_Init(&argc,&argv);
51 #endif
52 
53  int MyPID;
54 
55  try {
56 
57  {
58  TEUCHOS_FUNC_TIME_MONITOR("Total PCE Calculation Time");
59 
60  // Create a communicator for Epetra objects
62 #ifdef HAVE_MPI
63  globalComm = Teuchos::rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
64 #else
65  globalComm = Teuchos::rcp(new Epetra_SerialComm);
66 #endif
67  MyPID = globalComm->MyPID();
68 
69  // Create Stochastic Galerkin basis and expansion
71  for (int i=0; i<num_KL; i++)
72  bases[i] = Teuchos::rcp(new Stokhos::LegendreBasis<int,double>(p, true));
75  int sz = basis->size();
77  if (nonlinear_expansion)
78  Cijk = basis->computeTripleProductTensor();
79  else
80  Cijk = basis->computeLinearTripleProductTensor();
83  Cijk));
84  if (MyPID == 0)
85  std::cout << "Stochastic Galerkin expansion size = " << sz << std::endl;
86 
87  // Create stochastic parallel distribution
88  int num_spatial_procs = -1;
89  if (argc > 1)
90  num_spatial_procs = std::atoi(argv[1]);
91  Teuchos::ParameterList parallelParams;
92  parallelParams.set("Number of Spatial Processors", num_spatial_procs);
93  Teuchos::RCP<Stokhos::ParallelData> sg_parallel_data =
94  Teuchos::rcp(new Stokhos::ParallelData(basis, Cijk, globalComm,
95  parallelParams));
97  sg_parallel_data->getMultiComm();
99  sg_parallel_data->getSpatialComm();
100 
101  // Create application
103  Teuchos::rcp(new twoD_diffusion_ME(app_comm, n, num_KL, mu, s, basis,
104  nonlinear_expansion, symmetric));
105 
106  // Setup stochastic Galerkin algorithmic parameters
109  Teuchos::ParameterList& sgOpParams =
110  sgParams->sublist("SG Operator");
111  Teuchos::ParameterList& sgPrecParams =
112  sgParams->sublist("SG Preconditioner");
113  if (!nonlinear_expansion) {
114  sgParams->set("Parameter Expansion Type", "Linear");
115  sgParams->set("Jacobian Expansion Type", "Linear");
116  }
117  if (matrix_free) {
118  sgOpParams.set("Operator Method", "Matrix Free");
119  sgPrecParams.set("Preconditioner Method", "Approximate Gauss-Seidel");
120  sgPrecParams.set("Symmetric Gauss-Seidel", symmetric);
121  sgPrecParams.set("Mean Preconditioner Type", "ML");
122  Teuchos::ParameterList& precParams =
123  sgPrecParams.sublist("Mean Preconditioner Parameters");
124  precParams.set("default values", "SA");
125  precParams.set("ML output", 0);
126  precParams.set("max levels",5);
127  precParams.set("increasing or decreasing","increasing");
128  precParams.set("aggregation: type", "Uncoupled");
129  precParams.set("smoother: type","ML symmetric Gauss-Seidel");
130  precParams.set("smoother: sweeps",2);
131  precParams.set("smoother: pre or post", "both");
132  precParams.set("coarse: max size", 200);
133 #ifdef HAVE_ML_AMESOS
134  precParams.set("coarse: type","Amesos-KLU");
135 #else
136  precParams.set("coarse: type","Jacobi");
137 #endif
138  }
139  else {
140  sgOpParams.set("Operator Method", "Fully Assembled");
141  sgPrecParams.set("Preconditioner Method", "None");
142  }
143 
144  // Create stochastic Galerkin model evaluator
147  expansion, sg_parallel_data,
148  sgParams));
149 
150  // Set up stochastic parameters
151  // The current implementation of the model doesn't actually use these
152  // values, but is hard-coded to certain uncertainty models
153  Teuchos::Array<double> point(num_KL, 1.0);
154  Teuchos::Array<double> basis_vals(sz);
155  basis->evaluateBases(point, basis_vals);
157  sg_model->create_p_sg(0);
158  for (int i=0; i<num_KL; i++) {
159  sg_p_init->term(i,0)[i] = 0.0;
160  sg_p_init->term(i,1)[i] = 1.0 / basis_vals[i+1];
161  }
162  sg_model->set_p_sg_init(0, *sg_p_init);
163 
164  // Setup stochastic initial guess
166  sg_model->create_x_sg();
167  sg_x_init->init(0.0);
168  sg_model->set_x_sg_init(*sg_x_init);
169 
170  // Set up NOX parameters
173 
174  // Set the nonlinear solver method
175  noxParams->set("Nonlinear Solver", "Line Search Based");
176 
177  // Set the printing parameters in the "Printing" sublist
178  Teuchos::ParameterList& printParams = noxParams->sublist("Printing");
179  printParams.set("MyPID", MyPID);
180  printParams.set("Output Precision", 3);
181  printParams.set("Output Processor", 0);
182  printParams.set("Output Information",
183  NOX::Utils::OuterIteration +
184  NOX::Utils::OuterIterationStatusTest +
185  NOX::Utils::InnerIteration +
186  NOX::Utils::LinearSolverDetails +
187  NOX::Utils::Warning +
188  NOX::Utils::Error);
189 
190  // Create printing utilities
191  NOX::Utils utils(printParams);
192 
193  // Sublist for line search
194  Teuchos::ParameterList& searchParams = noxParams->sublist("Line Search");
195  searchParams.set("Method", "Full Step");
196 
197  // Sublist for direction
198  Teuchos::ParameterList& dirParams = noxParams->sublist("Direction");
199  dirParams.set("Method", "Newton");
200  Teuchos::ParameterList& newtonParams = dirParams.sublist("Newton");
201  newtonParams.set("Forcing Term Method", "Constant");
202 
203  // Sublist for linear solver for the Newton method
204  Teuchos::ParameterList& lsParams = newtonParams.sublist("Linear Solver");
205  if (symmetric)
206  lsParams.set("Aztec Solver", "CG");
207  else
208  lsParams.set("Aztec Solver", "GMRES");
209  lsParams.set("Max Iterations", 1000);
210  lsParams.set("Size of Krylov Subspace", 100);
211  lsParams.set("Tolerance", 1e-12);
212  lsParams.set("Output Frequency", 1);
213  if (matrix_free)
214  lsParams.set("Preconditioner", "User Defined");
215  else {
216  lsParams.set("Preconditioner", "ML");
217  Teuchos::ParameterList& precParams =
218  lsParams.sublist("ML");
219  ML_Epetra::SetDefaults("DD", precParams);
220  lsParams.set("Write Linear System", false);
221  }
222 
223  // Sublist for convergence tests
224  Teuchos::ParameterList& statusParams = noxParams->sublist("Status Tests");
225  statusParams.set("Test Type", "Combo");
226  statusParams.set("Number of Tests", 2);
227  statusParams.set("Combo Type", "OR");
228  Teuchos::ParameterList& normF = statusParams.sublist("Test 0");
229  normF.set("Test Type", "NormF");
230  normF.set("Tolerance", 1e-10);
231  normF.set("Scale Type", "Scaled");
232  Teuchos::ParameterList& maxIters = statusParams.sublist("Test 1");
233  maxIters.set("Test Type", "MaxIters");
234  maxIters.set("Maximum Iterations", 1);
235 
236  // Create NOX interface
238  Teuchos::rcp(new NOX::Epetra::ModelEvaluatorInterface(sg_model));
239 
240  // Create NOX linear system object
246  if (matrix_free) {
247  Teuchos::RCP<Epetra_Operator> M = sg_model->create_WPrec()->PrecOp;
249  linsys =
250  Teuchos::rcp(new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams,
251  iJac, A, iPrec, M,
252  *u));
253  }
254  else {
255  linsys =
256  Teuchos::rcp(new NOX::Epetra::LinearSystemAztecOO(printParams, lsParams,
257  iReq, iJac, A,
258  *u));
259  }
260 
261  // Build NOX group
263  Teuchos::rcp(new NOX::Epetra::Group(printParams, iReq, *u, linsys));
264 
265  // Create the Solver convergence test
267  NOX::StatusTest::buildStatusTests(statusParams, utils);
268 
269  // Create the solver
271  NOX::Solver::buildSolver(grp, statusTests, noxParams);
272 
273  // Solve the system
274  NOX::StatusTest::StatusType status = solver->solve();
275 
276  // Get final solution
277  const NOX::Epetra::Group& finalGroup =
278  dynamic_cast<const NOX::Epetra::Group&>(solver->getSolutionGroup());
279  const Epetra_Vector& finalSolution =
280  (dynamic_cast<const NOX::Epetra::Vector&>(finalGroup.getX())).getEpetraVector();
281 
282  // Save final solution to file
283  EpetraExt::VectorToMatrixMarketFile("nox_stochastic_solution.mm",
284  finalSolution);
285 
286  // Save mean and variance to file
288  sg_model->create_x_sg(View, &finalSolution);
289  Epetra_Vector mean(*(model->get_x_map()));
290  Epetra_Vector std_dev(*(model->get_x_map()));
291  sg_x_poly->computeMean(mean);
292  sg_x_poly->computeStandardDeviation(std_dev);
293  EpetraExt::VectorToMatrixMarketFile("mean_gal.mm", mean);
294  EpetraExt::VectorToMatrixMarketFile("std_dev_gal.mm", std_dev);
295 
296  // Evaluate SG responses at SG parameters
297  EpetraExt::ModelEvaluator::InArgs sg_inArgs = sg_model->createInArgs();
298  EpetraExt::ModelEvaluator::OutArgs sg_outArgs =
299  sg_model->createOutArgs();
300  Teuchos::RCP<const Epetra_Vector> sg_p = sg_model->get_p_init(1);
302  Teuchos::rcp(new Epetra_Vector(*(sg_model->get_g_map(0))));
303  sg_inArgs.set_p(1, sg_p);
304  sg_inArgs.set_x(Teuchos::rcp(&finalSolution,false));
305  sg_outArgs.set_g(0, sg_g);
306  sg_model->evalModel(sg_inArgs, sg_outArgs);
307 
308  // Print mean and standard deviation of response
310  sg_model->create_g_sg(0, View, sg_g.get());
311  Epetra_Vector g_mean(*(model->get_g_map(0)));
312  Epetra_Vector g_std_dev(*(model->get_g_map(0)));
313  sg_g_poly->computeMean(g_mean);
314  sg_g_poly->computeStandardDeviation(g_std_dev);
315  std::cout.precision(16);
316  // std::cout << "\nResponse Expansion = " << std::endl;
317  // std::cout.precision(12);
318  // sg_g_poly->print(std::cout);
319  std::cout << std::endl;
320  std::cout << "Response Mean = " << std::endl << g_mean << std::endl;
321  std::cout << "Response Std. Dev. = " << std::endl << g_std_dev << std::endl;
322 
323  // Determine if example passed
324  bool passed = false;
325  if (status == NOX::StatusTest::Converged &&
326  std::abs(g_mean[0]-g_mean_exp) < g_tol &&
327  std::abs(g_std_dev[0]-g_std_dev_exp) < g_tol)
328  passed = true;
329  if (MyPID == 0) {
330  if (passed)
331  std::cout << "Example Passed!" << std::endl;
332  else
333  std::cout << "Example Failed!" << std::endl;
334  }
335 
336  }
337 
340 
341  }
342 
343  catch (std::exception& e) {
344  std::cout << e.what() << std::endl;
345  }
346  catch (std::string& s) {
347  std::cout << s << std::endl;
348  }
349  catch (char *s) {
350  std::cout << s << std::endl;
351  }
352  catch (...) {
353  std::cout << "Caught unknown exception!" << std::endl;
354  }
355 
356 #ifdef HAVE_MPI
357  MPI_Finalize() ;
358 #endif
359 
360 }
Teuchos::RCP< Stokhos::EpetraVectorOrthogPoly > create_x_sg(Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create vector orthog poly using x map and owned sg map.
Teuchos::RCP< Stokhos::EpetraVectorOrthogPoly > create_p_sg(int l, Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create vector orthog poly using p map.
#define TEUCHOS_FUNC_TIME_MONITOR(FUNCNAME)
void computeStandardDeviation(Epetra_Vector &v) const
Compute standard deviation.
Teuchos::RCP< const Epetra_Map > get_g_map(int l) const
Return response map.
Teuchos::RCP< const EpetraExt::MultiComm > getMultiComm() const
Get global comm.
void evalModel(const InArgs &inArgs, const OutArgs &outArgs) const
Evaluate model on InArgs.
void computeMean(Epetra_Vector &v) const
Compute mean.
void init(const value_type &val)
Initialize coefficients.
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)
virtual int MyPID() const =0
Nonlinear, stochastic Galerkin ModelEvaluator.
OutArgs createOutArgs() const
Create OutArgs.
Teuchos::RCP< Stokhos::EpetraVectorOrthogPoly > create_g_sg(int l, Epetra_DataAccess CV=Copy, const Epetra_Vector *v=NULL) const
Create vector orthog poly using g map.
ModelEvaluator for a linear 2-D diffusion problem.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
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)
Teuchos::RCP< const Epetra_Vector > get_x_init() const
Return initial solution.
void set_p_sg_init(int i, const Stokhos::EpetraVectorOrthogPoly &p_sg_in)
Set initial parameter polynomial.
KOKKOS_INLINE_FUNCTION PCE< Storage > abs(const PCE< Storage > &a)
Teuchos::RCP< const Epetra_Map > get_g_map(int j) const
Return response function map.
Legendre polynomial basis.
InArgs createInArgs() const
Create InArgs.
void set_x_sg_init(const Stokhos::EpetraVectorOrthogPoly &x_sg_in)
Set initial solution polynomial.
int main(int argc, char **argv)
Teuchos::RCP< const Epetra_Comm > getSpatialComm() const
Get spatial comm.
Teuchos::RCP< const Epetra_Map > get_x_map() const
Return solution vector map.
Teuchos::RCP< Epetra_Operator > create_W() const
Create W = alpha*M + beta*J matrix.
coeff_type & term(ordinal_type dimension, ordinal_type order)
Get term for dimension dimension and order order.
int n
Teuchos::RCP< const Epetra_Vector > get_p_init(int l) const
Return initial parameters.
Teuchos::RCP< EpetraExt::ModelEvaluator::Preconditioner > create_WPrec() const
Create preconditioner operator.
static void zeroOutTimers()