19 #if(defined HAVE_NOX && defined HAVE_EPETRA && defined HAVE_TEUCHOS)
25 static Epetra_SerialComm seq_comm;
27 template<
typename Scalar>
28 DiscreteProblemNOX<Scalar>::DiscreteProblemNOX(DiscreteProblemInterface<Scalar>* problem) : dp(problem)
30 this->precond = Teuchos::null;
31 if(!this->dp->is_matrix_free())
32 this->dp->create_sparse_structure(&jacobian);
35 template<
typename Scalar>
36 bool DiscreteProblemNOX<Scalar>::computeF(
const Epetra_Vector &x, Epetra_Vector &f, FillType flag)
38 EpetraVector<Scalar> xx(x);
39 EpetraVector<Scalar> rhs(f);
43 Scalar* coeff_vec =
new Scalar[xx.length()];
44 xx.extract(coeff_vec);
45 this->dp->assemble(coeff_vec, NULL, &rhs);
51 template<
typename Scalar>
52 bool DiscreteProblemNOX<Scalar>::computeJacobian(
const Epetra_Vector &x, Epetra_Operator &op)
54 Epetra_RowMatrix *jac =
dynamic_cast<Epetra_RowMatrix *
>(&op);
57 EpetraVector<Scalar> xx(x);
58 EpetraMatrix<Scalar> jacob(*jac);
62 Scalar* coeff_vec =
new Scalar[xx.length()];
63 xx.extract(coeff_vec);
64 this->dp->assemble(coeff_vec, &jacob, NULL);
71 template<
typename Scalar>
72 bool DiscreteProblemNOX<Scalar>::computePreconditioner(
const Epetra_Vector &x, Epetra_Operator &m,
73 Teuchos::ParameterList *precParams)
75 assert(precond != Teuchos::null);
76 EpetraVector<Scalar> xx(x);
80 Scalar* coeff_vec =
new Scalar[xx.length()];
81 xx.extract(coeff_vec);
82 this->dp->assemble(coeff_vec, &jacobian, NULL);
86 precond->create(&jacobian);
88 m = *precond->get_obj();
93 template<
typename Scalar>
94 Teuchos::RCP<Precond<Scalar> > DiscreteProblemNOX<Scalar>::get_precond()
99 template<
typename Scalar>
100 EpetraMatrix<Scalar> *DiscreteProblemNOX<Scalar>::get_jacobian()
105 template<
typename Scalar>
106 NewtonSolverNOX<Scalar>::NewtonSolverNOX(DiscreteProblemInterface<Scalar>* problem) : NonlinearSolver<Scalar>(problem), ndp(problem)
111 conv.abs_resid = 1.0e-6;
112 conv.rel_resid = 1.0e-2;
113 conv.norm_type = NOX::Abstract::Vector::TwoNorm;
114 conv.stype = NOX::StatusTest::NormF::Scaled;
115 conv.update = 1.0e-5;
116 conv.wrms_rtol = 1.0e-2;
117 conv.wrms_atol = 1.0e-8;
119 conv_flag.absresid = 1;
120 conv_flag.relresid = 0;
121 conv_flag.update = 0;
124 nl_pars = Teuchos::rcp(
new Teuchos::ParameterList);
126 nl_pars->set(
"Nonlinear Solver",
"Line Search Based");
127 nl_pars->sublist(
"Printing").set(
"Output Information", NOX::Utils::Error);
130 Teuchos::ParameterList &search_pars = nl_pars->sublist(
"Line Search");
131 search_pars.set(
"Method",
"Full Step");
134 Teuchos::ParameterList &dir_pars = nl_pars->sublist(
"Direction");
135 dir_pars.set(
"Method",
"Newton");
136 Teuchos::ParameterList &newton_pars = dir_pars.sublist(
"Newton");
138 newton_pars.set(
"Forcing Term Method",
"Constant");
141 Teuchos::ParameterList &ls_pars = newton_pars.sublist(
"Linear Solver");
142 ls_pars.set(
"Aztec Solver",
"GMRES");
143 ls_pars.set(
"Max Iterations", 800);
144 ls_pars.set(
"Tolerance", 1e-8);
145 ls_pars.set(
"Size of Krylov Subspace", 50);
146 ls_pars.set(
"Preconditioner Reuse Policy",
"Recompute");
147 ls_pars.set(
"Output Frequency", AZ_all);
148 ls_pars.set(
"Max Age Of Prec", 999);
151 template<
typename Scalar>
152 void NewtonSolverNOX<Scalar>::set_time(
double time)
156 template<
typename Scalar>
157 void NewtonSolverNOX<Scalar>::set_time_step(
double time_step)
161 template<
typename Scalar>
162 NewtonSolverNOX<Scalar>::~NewtonSolverNOX()
168 template<
typename Scalar>
169 void DiscreteProblemNOX<Scalar>::set_precond(Teuchos::RCP<Precond<Scalar> > &pc)
172 this->dp->create_sparse_structure(&jacobian);
175 template<
typename Scalar>
176 void NewtonSolverNOX<Scalar>::set_precond(Precond<Scalar> &pc)
178 Teuchos::RCP<Precond<Scalar> > tpc = Teuchos::rcpFromRef(pc);
179 ndp.set_precond(tpc);
180 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Preconditioner",
"User Defined");
183 template<
typename Scalar>
184 void NewtonSolverNOX<Scalar>::set_precond(
const char *pc)
186 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Preconditioner", pc);
189 template<
typename Scalar>
190 void NewtonSolverNOX<Scalar>::set_output_flags(
int flags)
192 nl_pars->sublist(
"Printing").set(
"Output Information", flags);
195 template<
typename Scalar>
196 void NewtonSolverNOX<Scalar>::set_ls_type(
const char *type)
198 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Aztec Solver", type);
201 template<
typename Scalar>
202 void NewtonSolverNOX<Scalar>::set_ls_max_iters(
int iters)
204 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Max Iterations", iters);
207 template<
typename Scalar>
208 void NewtonSolverNOX<Scalar>::set_ls_tolerance(
double tolerance)
210 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Tolerance", tolerance);
213 template<
typename Scalar>
214 void NewtonSolverNOX<Scalar>::set_ls_sizeof_krylov_subspace(
int size)
216 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Size of Krylov Subspace", size);
219 template<
typename Scalar>
220 void NewtonSolverNOX<Scalar>::set_precond_reuse(
const char * pc_reuse)
222 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Preconditioner Reuse Policy", pc_reuse);
224 template<
typename Scalar>
225 void NewtonSolverNOX<Scalar>::set_precond_max_age(
int max_age)
227 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Max Age Of Prec", max_age);
230 template<
typename Scalar>
231 void NewtonSolverNOX<Scalar>::solve(Scalar* coeff_vec)
234 Hermes::Algebra::EpetraVector<Scalar> temp_init_sln;
235 temp_init_sln.alloc(this->dp->get_num_dofs());
236 for (
int i = 0; i < this->dp->get_num_dofs(); i++)
237 temp_init_sln.set(i, coeff_vec[i]);
238 NOX::Epetra::Vector init_sln(*temp_init_sln.vec);
242 Teuchos::ParameterList &print_pars = nl_pars->sublist(
"Printing");
244 Teuchos::ParameterList &ls_pars = nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver");
246 Teuchos::RCP<Precond<Scalar> > precond = ndp.get_precond();
248 Teuchos::RCP<NOX::Epetra::LinearSystemAztecOO> lin_sys;
250 Teuchos::RCP<NOX::Epetra::Interface::Required> i_req = Teuchos::rcpFromRef(ndp);
252 Teuchos::RCP<Epetra_RowMatrix> jac_mat;
255 if(this->dp->is_matrix_free())
257 if(precond == Teuchos::null)
259 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars, i_req, init_sln));
263 Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> i_prec = Teuchos::rcpFromRef(ndp);
264 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars, i_req,
265 i_prec, precond, init_sln));
270 Teuchos::RCP<NOX::Epetra::Interface::Jacobian> i_jac = Teuchos::rcpFromRef(ndp);
271 jac_mat = Teuchos::rcp(ndp.get_jacobian()->mat);
272 if(precond == Teuchos::null)
274 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars, i_req,
275 i_jac, jac_mat, init_sln));
279 Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> i_prec = Teuchos::rcpFromRef(ndp);
280 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars,
281 i_jac, jac_mat, i_prec, precond, init_sln));
286 Teuchos::RCP<NOX::Epetra::Group> grp =
287 Teuchos::rcp(
new NOX::Epetra::Group(print_pars, i_req, init_sln, lin_sys));
290 Teuchos::RCP<NOX::StatusTest::Combo> converged =
291 Teuchos::rcp(
new NOX::StatusTest::Combo(NOX::StatusTest::Combo::AND));
293 if(conv_flag.absresid)
295 Teuchos::RCP<NOX::StatusTest::NormF> absresid =
296 Teuchos::rcp(
new NOX::StatusTest::NormF(conv.abs_resid, conv.norm_type, conv.stype));
297 converged->addStatusTest(absresid);
300 if(conv_flag.relresid)
302 Teuchos::RCP<NOX::StatusTest::NormF> relresid =
303 Teuchos::rcp(
new NOX::StatusTest::NormF(*grp.get(), conv.rel_resid));
304 converged->addStatusTest(relresid);
309 Teuchos::RCP<NOX::StatusTest::NormUpdate> update =
310 Teuchos::rcp(
new NOX::StatusTest::NormUpdate(conv.update));
311 converged->addStatusTest(update);
316 Teuchos::RCP<NOX::StatusTest::NormWRMS> wrms =
317 Teuchos::rcp(
new NOX::StatusTest::NormWRMS(conv.wrms_rtol, conv.wrms_atol));
318 converged->addStatusTest(wrms);
321 Teuchos::RCP<NOX::StatusTest::MaxIters> maxiters =
322 Teuchos::rcp(
new NOX::StatusTest::MaxIters(conv.max_iters));
324 Teuchos::RCP<NOX::StatusTest::FiniteValue> fv =
325 Teuchos::rcp(
new NOX::StatusTest::FiniteValue);
327 Teuchos::RCP<NOX::StatusTest::Combo> cmb =
328 Teuchos::rcp(
new NOX::StatusTest::Combo(NOX::StatusTest::Combo::OR));
330 cmb->addStatusTest(fv);
331 cmb->addStatusTest(converged);
332 cmb->addStatusTest(maxiters);
335 Teuchos::RCP<Teuchos::ParameterList> final_pars = nl_pars;
338 Teuchos::RCP<NOX::Solver::Generic> solver = NOX::Solver::buildSolver(grp, cmb, final_pars);
341 NOX::StatusTest::StatusType status = solver->solve();
343 if(!this->dp->is_matrix_free())
346 if(status == NOX::StatusTest::Converged)
349 num_iters = solver->getNumIterations();
350 residual = solver->getSolutionGroup().getNormF();
351 num_lin_iters = final_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").sublist(
"Output").get(
"Total Number of Linear Iterations", -1);
352 achieved_tol = final_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").sublist(
"Output").get(
"Achieved Tolerance", 0.0);
355 const NOX::Epetra::Group &f_grp =
356 dynamic_cast<const NOX::Epetra::Group &
>(solver->getSolutionGroup());
357 const Epetra_Vector &f_sln =
358 (
dynamic_cast<const NOX::Epetra::Vector &
>(f_grp.getX())).getEpetraVector();
360 int n = this->dp->get_num_dofs();
361 delete [] this->sln_vector;
362 this->sln_vector =
new double[n];
363 memset(this->sln_vector, 0, n *
sizeof(
double));
364 f_sln.ExtractCopy(this->sln_vector);
369 throw Exceptions::Exception(
"Nox solver did not converge");
373 template<
typename Scalar>
374 int NewtonSolverNOX<Scalar>::get_num_iters()
379 template<
typename Scalar>
380 double NewtonSolverNOX<Scalar>::get_residual()
385 template<
typename Scalar>
386 int NewtonSolverNOX<Scalar>::get_num_lin_iters()
388 return num_lin_iters;
391 template<
typename Scalar>
392 double NewtonSolverNOX<Scalar>::get_achieved_tol()
397 template<
typename Scalar>
398 void NewtonSolverNOX<Scalar>::set_norm_type(NOX::Abstract::Vector::NormType type)
400 conv.norm_type = type;
403 template<
typename Scalar>
404 void NewtonSolverNOX<Scalar>::set_scale_type(NOX::StatusTest::NormF::ScaleType type)
409 template<
typename Scalar>
410 void NewtonSolverNOX<Scalar>::set_conv_iters(
int iters)
412 conv.max_iters = iters;
415 template<
typename Scalar>
416 void NewtonSolverNOX<Scalar>::set_conv_abs_resid(
double resid)
418 conv_flag.absresid = 1;
419 conv.abs_resid = resid;
422 template<
typename Scalar>
423 void NewtonSolverNOX<Scalar>::set_conv_rel_resid(
double resid)
425 conv_flag.relresid = 1;
426 conv.rel_resid = resid;
429 template<
typename Scalar>
430 void NewtonSolverNOX<Scalar>::disable_abs_resid()
432 conv_flag.absresid = 0;
435 template<
typename Scalar>
436 void NewtonSolverNOX<Scalar>::disable_rel_resid()
438 conv_flag.relresid = 0;
441 template<
typename Scalar>
442 void NewtonSolverNOX<Scalar>::set_conv_update(
double update)
444 conv_flag.update = 1;
445 conv.update = update;
448 template<
typename Scalar>
449 void NewtonSolverNOX<Scalar>::set_conv_wrms(
double rtol,
double atol)
452 conv.wrms_rtol = rtol;
453 conv.wrms_atol = atol;
456 template class HERMES_API DiscreteProblemNOX<double>;
458 template class HERMES_API NewtonSolverNOX<double>;