WaveBEM: Unsteady Nonlinear Potential Flow Solver for Ship-Wave Interaction.
newton_solver.cc
Go to the documentation of this file.
1 #include "../include/newton_solver.h"
2 #include "../include/newton_argument.h"
5 
6 
8 #include <iostream>
9 
10 using namespace dealii;
11 using namespace std;
12 
13 
14 
16  solver(bubble),
17  y(solver.n_dofs()),
18  comm(MPI_COMM_WORLD),
19  map((int)solver.n_dofs(), 0, comm)
20 
21 {
24  // assigning default values to solver options
25  linear_solver_name = "GMRES";
26  provide_jac = true;
27  provide_jac_prec = true;
28  linear_rel_tol = 1e-8;
29  rel_tol = 1e-7;
30 
31 
32 }
33 
34 
36 {
37 }
38 
39 
41 {
42  prm.enter_subsection("Newton Solver Params");
43  {
44  prm.declare_entry("Linear solver kind", "GMRES", Patterns::Selection("GMRES|CG|CGS|TFQMR|BiCGStab|LU"));
45  prm.declare_entry("Provide jacobian product", "false", Patterns::Bool());
46  prm.declare_entry("Provide jacobian preconditioner", "false", Patterns::Bool());
47  prm.declare_entry("Relative nonlinear error tolerance", "1e-5", Patterns::Double());
48  prm.declare_entry("Relative linear error tolerance", "1e-8", Patterns::Double());
49  }
50  prm.leave_subsection();
51  prm.enter_subsection("Solver");
53  prm.leave_subsection();
54 }
55 
56 
58 {
59  prm.enter_subsection("Newton Solver Params");
60  {
61  linear_solver_name = prm.get("Linear solver kind");
62  provide_jac = prm.get_bool("Provide jacobian product");
63  provide_jac_prec = prm.get_bool("Provide jacobian preconditioner");
64  rel_tol = prm.get_double("Relative nonlinear error tolerance");
65  linear_rel_tol = prm.get_double("Relative linear error tolerance");
66  }
67  prm.leave_subsection();
68  prm.enter_subsection("Solver");
70  prm.leave_subsection();
71 }
72 
73 unsigned int NewtonSolver::solve(Vector<double> &solution,
74  const unsigned int max_steps)
75 {
76 
77 
78  AssertThrow(solution.size() == solver.n_dofs(),
79  ExcDimensionMismatch(solution.size(), solver.n_dofs()));
80 
81 
82 
83 
84  using Teuchos::ParameterList;
85  using Teuchos::parameterList;
86  using Teuchos::RCP;
87  using Teuchos::rcp;
88 
89 
90  //Let's resize the Epetra Map (if the solution)
91  map = Epetra_Map((int)solver.n_dofs(), 0, comm);
92  Epetra_Vector sol(map);
93  Epetra_Vector init_guess(map);
94 
95  y = solution;
96  for (unsigned int i=0; i<solver.n_dofs(); ++i)
97  {
98  init_guess[i] = solution(i);
99  sol[i] = solution(i);
100  }
101 
102 
103 
104  // Set up the problem interface. Your application will define
105  // its own problem interface. ProblemInterface is our
106  // example interface, which you can use as a model.
107  //
108  // Our ProblemInterface makes a deep copy of the initial
109  // guess.
110  Teuchos::RCP<ProblemInterface> interface =
111  Teuchos::rcp(new ProblemInterface(solver, y, *preconditioner_operator, *jacobian_operator) );
112 
113  RCP<Epetra_Operator> preconditioner(preconditioner_operator);
114  RCP<Epetra_Operator> jacobian(jacobian_operator);
115  /*
116  cout<<"========================================================="<<endl;
117  cout<<"Deal test"<<endl;
118  SolverGMRES<Vector<double> > gmres(solver_control,
119  SolverGMRES<Vector<double> >::AdditionalData(100));
120 
121  Vector<double> res(solver.n_dofs());
122  solver.residual(res,solution);
123  res *= -1.0;
124 
125  gmres.solve (*(interface->jacobian_operator), solution, res, PreconditionIdentity());// *(interface->preconditioner_operator));
126  cout<<"Passed"<<endl;
127  cout<<"========================================================="<<endl;
128  */
129 
130 
131 
132 
133 
134  // Create the top-level parameter list to control NOX.
135  //
136  // "parameterList" (lowercase initial "p") is a "nonmember
137  // constructor" that returns an RCP<ParameterList> with the
138  // given name.
139  RCP<ParameterList> params = parameterList ("NOX");
140 
141  // Tell the nonlinear solver to use line search.
142  params->set ("Nonlinear Solver", "Line Search Based");
143 
144  //
145  // Set the printing parameters in the "Printing" sublist.
146  //
147  ParameterList &printParams = params->sublist ("Printing");
148  printParams.set ("MyPID", comm.MyPID ());
149  printParams.set ("Output Precision", 3);
150  printParams.set ("Output Processor", 0);
151 
152  // Set verbose=true to see a whole lot of intermediate status
153  // output, during both linear and nonlinear iterations.
154  const bool verbose = false;
155  if (verbose)
156  {
157  printParams.set ("Output Information",
158  NOX::Utils::OuterIteration +
159  NOX::Utils::OuterIterationStatusTest +
160  NOX::Utils::InnerIteration +
161  NOX::Utils::Parameters +
162  NOX::Utils::Details +
163  NOX::Utils::Warning);
164  }
165  else
166  {
167  printParams.set ("Output Information", NOX::Utils::Warning);
168  }
169 
170  //
171  // Set the nonlinear solver parameters.
172  //
173 
174  // Line search parameters.
175  ParameterList &searchParams = params->sublist ("Line Search");
176  searchParams.set ("Method", "Full Step");
177 
178  // Parameters for picking the search direction.
179  ParameterList &dirParams = params->sublist ("Direction");
180  // Use Newton's method to pick the search direction.
181  dirParams.set ("Method", "Newton");
182 
183  // Parameters for Newton's method.
184  ParameterList &newtonParams = dirParams.sublist ("Newton");
185  newtonParams.set ("Forcing Term Method", "Constant");
186 
187  //
188  // Newton's method invokes a linear solver repeatedly.
189  // Set the parameters for the linear solver.
190  //
191  ParameterList &lsParams = newtonParams.sublist ("Linear Solver");
192 
193  // Use Aztec's implementation of GMRES, with at most 800
194  // iterations, a residual tolerance of 1.0e-4, with output every
195  // 50 iterations, and Aztec's native ILU preconditioner.
196  lsParams.set ("Aztec Solver", linear_solver_name);
197  lsParams.set ("Max Iterations", 800);
198  lsParams.set ("Tolerance", linear_rel_tol);
199  lsParams.set ("Output Frequency", 1);
200  lsParams.set ("Preconditioner Operator", "Finite Difference");
201  lsParams.set ("Aztec Preconditioner", "ilu");
202  //lsParams.set("Preconditioner", "User Defined");
203  lsParams.set("Preconditioner", "User Defined");
204  //lsParams.set("Preconditioner Reuse Policy", "Reuse");
205 
206 
207  // Our ProblemInterface implements both Required and
208  // Jacobian, so we can use the same object for each.
209  RCP<NOX::Epetra::Interface::Required> iReq = interface;
210  RCP<NOX::Epetra::Interface::Jacobian> iJac = interface;
211  RCP<NOX::Epetra::Interface::Preconditioner> iPrec = interface;
212 
213 
214  RCP<NOX::Epetra::LinearSystemAztecOO> linSys;
215 
216  if ((provide_jac==false) && (provide_jac_prec==false) )
217  linSys = rcp (new NOX::Epetra::LinearSystemAztecOO (printParams, lsParams,
218  iReq, init_guess));
219  else if ((provide_jac==true) && (provide_jac_prec==false) )
220  linSys = rcp (new NOX::Epetra::LinearSystemAztecOO (printParams, lsParams,
221  iReq, iJac, jacobian, init_guess));
222  else if ((provide_jac==false) && (provide_jac_prec==true) )
223  linSys = rcp (new NOX::Epetra::LinearSystemAztecOO (printParams, lsParams,
224  iReq, iPrec, preconditioner, init_guess));
225  else if ((provide_jac==true) && (provide_jac_prec==true) )
226  {
227  linSys = rcp (new NOX::Epetra::LinearSystemAztecOO (printParams, lsParams,
228  iJac, jacobian, iPrec, preconditioner, init_guess));
229  }
230 
231  // Need a NOX::Epetra::Vector for constructor.
232  NOX::Epetra::Vector noxInitGuess (init_guess, NOX::DeepCopy);
233 
234 
235  RCP<NOX::Epetra::Group> group =
236  rcp (new NOX::Epetra::Group (printParams, iReq, noxInitGuess, linSys));
237 
238  //
239  // Set up NOX's iteration stopping criteria ("status tests").
240  //
241 
242  // ||F(X)||_2 / N < 1.0e-4, where N is the length of F(X).
243  //
244  // NormF has many options for setting up absolute vs. relative
245  // (scaled by the norm of the initial guess) tolerances, scaling
246  // or not scaling by the length of F(X), and choosing a
247  // different norm (we use the 2-norm here).
248  RCP<NOX::StatusTest::NormF> testNormF =
249  rcp (new NOX::StatusTest::NormF (rel_tol));
250 
251  // At most 20 (nonlinear) iterations.
252  RCP<NOX::StatusTest::MaxIters> testMaxIters =
253  rcp (new NOX::StatusTest::MaxIters (max_steps));
254 
255  // Combine the above two stopping criteria (normwise
256  // convergence, and maximum number of nonlinear iterations).
257  // The result tells NOX to stop if at least one of them is
258  // satisfied.
259  RCP<NOX::StatusTest::Combo> combo =
260  rcp (new NOX::StatusTest::Combo (NOX::StatusTest::Combo::OR,
261  testNormF, testMaxIters));
262 
263  // Create the NOX nonlinear solver.
264  RCP<NOX::Solver::Generic> solver =
265  NOX::Solver::buildSolver (group, combo, params);
266 
267  // Solve the nonlinear system.
268  NOX::StatusTest::StatusType status = solver->solve();
269 
270  // Print the result.
271  //
272  // For this particular example, Comm contains only one MPI
273  // process. However, we check for Comm.MyPID() == 0 here just
274  // so that the example is fully general. (If you're solving a
275  // larger nonlinear problem, you could safely use the code
276  // below.)
277  if (comm.MyPID() == 0)
278  {
279  cout << endl << "-- Parameter List From Solver --" << endl;
280  solver->getList ().print (cout);
281  }
282 
283  // Get the Epetra_Vector with the final solution from the solver.
284  const NOX::Epetra::Group &finalGroup =
285  dynamic_cast<const NOX::Epetra::Group &>(solver->getSolutionGroup());
286 
287  const Epetra_Vector &finalSolution =
288  dynamic_cast<const NOX::Epetra::Vector &> (finalGroup.getX ()).getEpetraVector ();
289 
290  for (unsigned int i=0; i<solution.size(); ++i)
291  {
292  solution(i) = finalSolution[i];
293  }
294 
295  //if (Comm.MyPID() == 0) {
296  //cout << "Computed solution: " << endl;
297  //}
298  // Epetra objects know how to print themselves politely when
299  // their operator<<(std::ostream&) is invoked on all MPI
300  // process(es) in the communicator to which they are associated.
301  //cout << finalSolution;
302 
303  return 0;
304 }
305 
306 
307 
void parse_parameters(ParameterHandler &prm)
Parse a parameter handler.
static void declare_parameters(ParameterHandler &param)
virtual unsigned int n_dofs() const =0
Returns the number of degrees of freedom.
STL namespace.
bool provide_jac_prec
#define AssertThrow(cond, exc)
NewtonArgument & solver
The bubble membrane poperties.
std::string get(const std::string &entry_string) const
void enter_subsection(const std::string &subsection)
NewtonSolver(NewtonArgument &solver)
Constructor for the NewtonSolver class.
std::string linear_solver_name
Epetra_SerialComm comm
Vector< double > y
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
SolverControl solver_control
Epetra_Map map
std::size_t size() const
double linear_rel_tol
void leave_subsection()
bool get_bool(const std::string &entry_name) const
Base class that needs to be inherited by any function that wants to use the newton solver class...
unsigned int solve(Vector< double > &solution, const unsigned int max_steps)
Solve.
PreconditionerOperator * preconditioner_operator
double get_double(const std::string &entry_name) const
static void declare_parameters(ParameterHandler &prm)
Declare parameters for this class to function properly.
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
void parse_parameters(ParameterHandler &param)
~NewtonSolver()
House cleaning.
JacobianOperator * jacobian_operator