18 #include "solver/nox_solver.h"
19 #include "projections/ogprojection.h"
21 #if(defined HAVE_NOX && defined HAVE_EPETRA && defined HAVE_TEUCHOS)
27 static Epetra_SerialComm seq_comm;
29 template<
typename Scalar>
30 DiscreteProblemNOX<Scalar>::DiscreteProblemNOX() : DiscreteProblem<Scalar>(), jacobian(nullptr)
32 this->precond = Teuchos::null;
35 template<
typename Scalar>
36 DiscreteProblemNOX<Scalar>::DiscreteProblemNOX(WeakFormSharedPtr<Scalar> wf, std::vector<SpaceSharedPtr<Scalar> > spaces) : DiscreteProblem<Scalar>(wf, spaces), jacobian(new EpetraMatrix<Scalar>())
38 this->precond = Teuchos::null;
39 this->jacobian->prealloc(Space<Scalar>::get_num_dofs(spaces));
42 template<
typename Scalar>
43 DiscreteProblemNOX<Scalar>::DiscreteProblemNOX(WeakFormSharedPtr<Scalar> wf, SpaceSharedPtr<Scalar> space) : DiscreteProblem<Scalar>(wf, space), jacobian(new EpetraMatrix<Scalar>())
45 this->precond = Teuchos::null;
46 this->jacobian->prealloc(Space<Scalar>::get_num_dofs(space));
49 template<
typename Scalar>
50 DiscreteProblemNOX<Scalar>::~DiscreteProblemNOX()
52 delete this->jacobian;
55 template<
typename Scalar>
56 bool DiscreteProblemNOX<Scalar>::computeF(
const Epetra_Vector &x, Epetra_Vector &f, FillType flag)
59 EpetraVector<Scalar> xx(x);
60 EpetraVector<Scalar> rhs(f);
64 Scalar* coeff_vec = malloc_with_check<Scalar>(xx.get_size());
65 xx.extract(coeff_vec);
67 this->assemble(coeff_vec,
nullptr, &rhs);
68 free_with_check(coeff_vec);
73 template<
typename Scalar>
74 bool DiscreteProblemNOX<Scalar>::computeJacobian(
const Epetra_Vector &x, Epetra_Operator &op)
76 Epetra_RowMatrix *jac =
dynamic_cast<Epetra_RowMatrix *
>(&op);
77 assert(jac !=
nullptr);
80 EpetraVector<Scalar> xx(x);
81 EpetraMatrix<Scalar> jacob(*jac);
85 Scalar* coeff_vec = malloc_with_check<Scalar>(xx.get_size());
86 xx.extract(coeff_vec);
88 this->assemble(coeff_vec, &jacob,
nullptr);
89 free_with_check(coeff_vec);
95 template<
typename Scalar>
96 bool DiscreteProblemNOX<Scalar>::computePreconditioner(
const Epetra_Vector &x, Epetra_Operator &m,
97 Teuchos::ParameterList *precParams)
100 EpetraVector<Scalar> xx(x);
102 Scalar* coeff_vec = malloc_with_check<Scalar>(xx.get_size());
103 xx.extract(coeff_vec);
104 this->assemble(coeff_vec, jacobian);
105 free_with_check(coeff_vec);
107 precond->create(jacobian);
109 m = *precond->get_obj();
114 template<
typename Scalar>
115 Teuchos::RCP<Hermes::Preconditioners::EpetraPrecond<Scalar> > DiscreteProblemNOX<Scalar>::get_precond()
120 template<
typename Scalar>
121 EpetraMatrix<Scalar> *DiscreteProblemNOX<Scalar>::get_jacobian()
126 template<
typename Scalar>
127 Scalar* NewtonSolverNOX<Scalar>::get_sln_vector()
129 return this->sln_vector;
132 template<
typename Scalar>
133 NewtonSolverNOX<Scalar>::NewtonSolverNOX(DiscreteProblemNOX<Scalar>* problem) : dp(problem), sln_vector(nullptr), own_dp(false)
138 template<
typename Scalar>
139 NewtonSolverNOX<Scalar>::NewtonSolverNOX(WeakFormSharedPtr<Scalar> wf, std::vector<SpaceSharedPtr<Scalar> > spaces) : dp(new DiscreteProblemNOX<Scalar>(wf, spaces)), sln_vector(nullptr), own_dp(true)
144 template<
typename Scalar>
145 NewtonSolverNOX<Scalar>::NewtonSolverNOX(WeakFormSharedPtr<Scalar> wf, SpaceSharedPtr<Scalar> space) : dp(new DiscreteProblemNOX<Scalar>(wf, space)), sln_vector(nullptr), own_dp(true)
150 template<
typename Scalar>
151 void NewtonSolverNOX<Scalar>::init()
156 conv.abs_resid = 1.0e-6;
157 conv.rel_resid = 1.0e-2;
158 conv.norm_type = NOX::Abstract::Vector::TwoNorm;
159 conv.stype = NOX::StatusTest::NormF::Scaled;
160 conv.update = 1.0e-5;
161 conv.wrms_rtol = 1.0e-2;
162 conv.wrms_atol = 1.0e-8;
164 conv_flag.absresid = 1;
165 conv_flag.relresid = 0;
166 conv_flag.update = 0;
169 nl_pars = Teuchos::rcp(
new Teuchos::ParameterList);
171 nl_pars->set(
"Nonlinear Solver",
"Line Search Based");
172 nl_pars->sublist(
"Printing").set(
"Output Information", NOX::Utils::Error);
175 Teuchos::ParameterList &search_pars = nl_pars->sublist(
"Line Search");
176 search_pars.set(
"Method",
"Full Step");
179 Teuchos::ParameterList &dir_pars = nl_pars->sublist(
"Direction");
180 dir_pars.set(
"Method",
"Newton");
181 Teuchos::ParameterList &newton_pars = dir_pars.sublist(
"Newton");
183 newton_pars.set(
"Forcing Term Method",
"Constant");
186 Teuchos::ParameterList &ls_pars = newton_pars.sublist(
"Linear Solver");
187 ls_pars.set(
"Aztec Solver",
"GMRES");
188 ls_pars.set(
"Max Iterations", 800);
189 ls_pars.set(
"Tolerance", 1e-8);
190 ls_pars.set(
"Size of Krylov Subspace", 50);
191 ls_pars.set(
"Preconditioner Reuse Policy",
"Recompute");
192 ls_pars.set(
"Output Frequency", AZ_all);
193 ls_pars.set(
"Max Age Of Prec", 999);
196 template<
typename Scalar>
197 void NewtonSolverNOX<Scalar>::set_time(
double time)
201 template<
typename Scalar>
202 void NewtonSolverNOX<Scalar>::set_time_step(
double time_step)
206 template<
typename Scalar>
207 NewtonSolverNOX<Scalar>::~NewtonSolverNOX()
215 template<
typename Scalar>
216 void DiscreteProblemNOX<Scalar>::set_precond(Teuchos::RCP<Hermes::Preconditioners::EpetraPrecond<Scalar> > &pc)
221 template<
typename Scalar>
222 void NewtonSolverNOX<Scalar>::set_precond(Hermes::Preconditioners::EpetraPrecond<Scalar> &pc)
224 Teuchos::RCP<Hermes::Preconditioners::EpetraPrecond<Scalar> > tpc = Teuchos::rcpFromRef(pc);
225 dp->set_precond(tpc);
226 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Preconditioner",
"User Defined");
229 template<
typename Scalar>
230 void NewtonSolverNOX<Scalar>::set_precond(
const char *pc)
232 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Preconditioner", pc);
235 template<
typename Scalar>
236 void NewtonSolverNOX<Scalar>::set_output_flags(
int flags)
238 nl_pars->sublist(
"Printing").set(
"Output Information", flags);
241 template<
typename Scalar>
242 void NewtonSolverNOX<Scalar>::set_ls_type(
const char *
type)
244 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Aztec Solver", type);
247 template<
typename Scalar>
248 void NewtonSolverNOX<Scalar>::set_ls_max_iters(
int iters)
250 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Max Iterations", iters);
253 template<
typename Scalar>
254 void NewtonSolverNOX<Scalar>::set_ls_tolerance(
double tolerance)
256 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Tolerance", tolerance);
259 template<
typename Scalar>
260 void NewtonSolverNOX<Scalar>::set_ls_sizeof_krylov_subspace(
int size)
262 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Size of Krylov Subspace", size);
265 template<
typename Scalar>
266 void NewtonSolverNOX<Scalar>::set_precond_reuse(
const char * pc_reuse)
268 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Preconditioner Reuse Policy", pc_reuse);
270 template<
typename Scalar>
271 void NewtonSolverNOX<Scalar>::set_precond_max_age(
int max_age)
273 nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").set(
"Max Age Of Prec", max_age);
276 template<
typename Scalar>
277 void NewtonSolverNOX<Scalar>::solve(std::vector<MeshFunctionSharedPtr<Scalar> > initial_guess)
281 this->solve(coeff_vec);
282 free_with_check(coeff_vec);
285 template<
typename Scalar>
286 void NewtonSolverNOX<Scalar>::solve(MeshFunctionSharedPtr<Scalar> initial_guess)
290 this->solve(coeff_vec);
291 free_with_check(coeff_vec);
294 template<
typename Scalar>
295 void NewtonSolverNOX<Scalar>::solve(Scalar* coeff_vec)
298 Hermes::Algebra::EpetraVector<Scalar> temp_init_sln;
300 temp_init_sln.alloc(ndofs);
302 temp_init_sln.zero();
305 for (
int i = 0; i < ndofs; i++)
306 temp_init_sln.set(i, coeff_vec[i]);
309 NOX::Epetra::Vector init_sln(*temp_init_sln.vec);
313 Teuchos::ParameterList &print_pars = nl_pars->sublist(
"Printing");
315 Teuchos::ParameterList &ls_pars = nl_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver");
317 Teuchos::RCP<Hermes::Preconditioners::EpetraPrecond<Scalar> > precond = dp->get_precond();
319 Teuchos::RCP<NOX::Epetra::LinearSystemAztecOO> lin_sys;
321 Teuchos::RCP<NOX::Epetra::Interface::Required> i_req = Teuchos::rcpFromRef(*dp);
323 Teuchos::RCP<Epetra_RowMatrix> jac_mat;
326 if (this->dp->get_weak_formulation()->is_matrix_free())
328 if (precond == Teuchos::null)
330 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars, i_req, init_sln));
334 Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> i_prec = Teuchos::rcpFromRef(*dp);
335 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars, i_req,
336 i_prec, precond, init_sln));
341 Teuchos::RCP<NOX::Epetra::Interface::Jacobian> i_jac = Teuchos::rcpFromRef(*dp);
342 jac_mat = Teuchos::rcp(dp->get_jacobian()->mat);
343 if (precond == Teuchos::null)
345 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars, i_req,
346 i_jac, jac_mat, init_sln));
350 Teuchos::RCP<NOX::Epetra::Interface::Preconditioner> i_prec = Teuchos::rcpFromRef(*dp);
351 lin_sys = Teuchos::rcp(
new NOX::Epetra::LinearSystemAztecOO(print_pars, ls_pars,
352 i_jac, jac_mat, i_prec, precond, init_sln));
357 Teuchos::RCP<NOX::Epetra::Group> grp =
358 Teuchos::rcp(
new NOX::Epetra::Group(print_pars, i_req, init_sln, lin_sys));
361 Teuchos::RCP<NOX::StatusTest::Combo> converged =
362 Teuchos::rcp(
new NOX::StatusTest::Combo(NOX::StatusTest::Combo::AND));
364 if (conv_flag.absresid)
366 Teuchos::RCP<NOX::StatusTest::NormF> absresid =
367 Teuchos::rcp(
new NOX::StatusTest::NormF(conv.abs_resid, conv.norm_type, conv.stype));
368 converged->addStatusTest(absresid);
371 if (conv_flag.relresid)
373 Teuchos::RCP<NOX::StatusTest::NormF> relresid =
374 Teuchos::rcp(
new NOX::StatusTest::NormF(*grp.get(), conv.rel_resid));
375 converged->addStatusTest(relresid);
378 if (conv_flag.update)
380 Teuchos::RCP<NOX::StatusTest::NormUpdate> update =
381 Teuchos::rcp(
new NOX::StatusTest::NormUpdate(conv.update));
382 converged->addStatusTest(update);
387 Teuchos::RCP<NOX::StatusTest::NormWRMS> wrms =
388 Teuchos::rcp(
new NOX::StatusTest::NormWRMS(conv.wrms_rtol, conv.wrms_atol));
389 converged->addStatusTest(wrms);
392 Teuchos::RCP<NOX::StatusTest::MaxIters> maxiters =
393 Teuchos::rcp(
new NOX::StatusTest::MaxIters(conv.max_iters));
395 Teuchos::RCP<NOX::StatusTest::FiniteValue> fv =
396 Teuchos::rcp(
new NOX::StatusTest::FiniteValue);
398 Teuchos::RCP<NOX::StatusTest::Combo> cmb =
399 Teuchos::rcp(
new NOX::StatusTest::Combo(NOX::StatusTest::Combo::OR));
401 cmb->addStatusTest(fv);
402 cmb->addStatusTest(converged);
403 cmb->addStatusTest(maxiters);
406 Teuchos::RCP<Teuchos::ParameterList> final_pars = nl_pars;
409 Teuchos::RCP<NOX::Solver::Generic> solver = NOX::Solver::buildSolver(grp, cmb, final_pars);
412 NOX::StatusTest::StatusType status = solver->solve();
414 if (!this->dp->get_weak_formulation()->is_matrix_free())
418 if (status == NOX::StatusTest::Converged)
421 num_iters = solver->getNumIterations();
422 residual = solver->getSolutionGroup().getNormF();
423 num_lin_iters = final_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").sublist(
"Output").get(
"Total Number of Linear Iterations", -1);
424 achieved_tol = final_pars->sublist(
"Direction").sublist(
"Newton").sublist(
"Linear Solver").sublist(
"Output").get(
"Achieved Tolerance", 0.0);
427 const NOX::Epetra::Group &f_grp =
428 dynamic_cast<const NOX::Epetra::Group &
>(solver->getSolutionGroup());
429 const Epetra_Vector &f_sln =
430 (
dynamic_cast<const NOX::Epetra::Vector &
>(f_grp.getX())).getEpetraVector();
432 if (this->sln_vector)
433 free_with_check(this->sln_vector);
434 this->sln_vector = (Scalar*)calloc(ndofs,
sizeof(Scalar));
436 f_sln.ExtractCopy(this->sln_vector);
441 throw Exceptions::Exception(
"Nox solver did not converge");
445 template<
typename Scalar>
446 int NewtonSolverNOX<Scalar>::get_num_iters()
451 template<
typename Scalar>
452 double NewtonSolverNOX<Scalar>::get_residual()
457 template<
typename Scalar>
458 int NewtonSolverNOX<Scalar>::get_num_lin_iters()
460 return num_lin_iters;
463 template<
typename Scalar>
464 double NewtonSolverNOX<Scalar>::get_achieved_tol()
469 template<
typename Scalar>
472 conv.norm_type =
type;
475 template<
typename Scalar>
476 void NewtonSolverNOX<Scalar>::set_scale_type(NOX::StatusTest::NormF::ScaleType type)
481 template<
typename Scalar>
482 void NewtonSolverNOX<Scalar>::set_conv_iters(
int iters)
484 conv.max_iters = iters;
487 template<
typename Scalar>
488 void NewtonSolverNOX<Scalar>::set_conv_abs_resid(
double resid)
490 conv_flag.absresid = 1;
491 conv.abs_resid = resid;
494 template<
typename Scalar>
495 void NewtonSolverNOX<Scalar>::set_conv_rel_resid(
double resid)
497 conv_flag.relresid = 1;
498 conv.rel_resid = resid;
501 template<
typename Scalar>
502 void NewtonSolverNOX<Scalar>::disable_abs_resid()
504 conv_flag.absresid = 0;
507 template<
typename Scalar>
508 void NewtonSolverNOX<Scalar>::disable_rel_resid()
510 conv_flag.relresid = 0;
513 template<
typename Scalar>
514 void NewtonSolverNOX<Scalar>::set_conv_update(
double update)
516 conv_flag.update = 1;
517 conv.update = update;
520 template<
typename Scalar>
521 void NewtonSolverNOX<Scalar>::set_conv_wrms(
double rtol,
double atol)
524 conv.wrms_rtol = rtol;
525 conv.wrms_atol = atol;
528 template class HERMES_API DiscreteProblemNOX < double > ;
531 template class HERMES_API NewtonSolverNOX < double > ;
::xsd::cxx::tree::flags flags
Parsing and serialization flags.
::xsd::cxx::tree::time< char, simple_type > time
C++ type corresponding to the time XML Schema built-in type.
::xsd::cxx::tree::type type
C++ type corresponding to the anyType XML Schema built-in type.
int get_num_dofs() const
Returns the number of basis functions contained in the space.
static void project_global(SpaceSharedPtr< Scalar > space, MatrixFormVol< Scalar > *custom_projection_jacobian, VectorFormVol< Scalar > *custom_projection_residual, Scalar *target_vec)
This method allows to specify your own OG-projection form.