WaveBEM: Unsteady Nonlinear Potential Flow Solver for Ship-Wave Interaction.
dae_time_integrator.cc
Go to the documentation of this file.
1 #include "../include/dae_time_integrator.h"
2 #include "../include/ode_argument.h"
3 
5 #include <iostream>
6 
7 using namespace dealii;
8 using namespace std;
9 
10 int dae_residual(realtype tt, N_Vector yy, N_Vector yp,
11  N_Vector rr, void *user_data)
12 {
13  OdeArgument &solver = *static_cast<OdeArgument *>(user_data);
14  Assert(NV_LENGTH_S(yy) == solver.n_dofs(),
15  ExcDimensionMismatch(NV_LENGTH_S(yy), solver.n_dofs()));
16  Assert(NV_LENGTH_S(yp) == solver.n_dofs(),
17  ExcDimensionMismatch(NV_LENGTH_S(yp), solver.n_dofs()));
18 // if ((NV_LENGTH_S(yy) == NV_LENGTH_S(yp)) & (NV_LENGTH_S(yy) =! NV_LENGTH_S(rr)))
19  NV_LENGTH_S(rr) = NV_LENGTH_S(yy);
20 
21  Assert(NV_LENGTH_S(rr) == solver.n_dofs(),
22  ExcDimensionMismatch(NV_LENGTH_S(rr), solver.n_dofs()));
23 
24  const VectorView<double> src_yy(solver.n_dofs(), NV_DATA_S(yy));
25  const VectorView<double> src_yp(solver.n_dofs(), NV_DATA_S(yp));
26  VectorView<double> residual(solver.n_dofs(), NV_DATA_S(rr));
27  return solver.residual(tt, residual, src_yy, src_yp);
28 }
29 
30 int dae_setup_prec(realtype tt, // time
31  N_Vector yy,
32  N_Vector yp,
33  N_Vector rr, // Current residual
34  realtype alpha, // J = dG/dyy + alpha dG/dyp
35  void *user_data, // the pointer to the correct class
36  N_Vector /*tmp1*/, // temporary storage
37  N_Vector /*tmp2*/,
38  N_Vector /*tmp3*/)
39 {
40  OdeArgument &solver = *static_cast<OdeArgument *>(user_data);
41  Assert(NV_LENGTH_S(yy) == solver.n_dofs(),
42  ExcDimensionMismatch(NV_LENGTH_S(yy), solver.n_dofs()));
43  Assert(NV_LENGTH_S(yp) == solver.n_dofs(),
44  ExcDimensionMismatch(NV_LENGTH_S(yp), solver.n_dofs()));
45  Assert(NV_LENGTH_S(rr) == solver.n_dofs(),
46  ExcDimensionMismatch(NV_LENGTH_S(rr), solver.n_dofs()));
47  // A previous call to residual has already been done.
48  const VectorView<double> src_yy(solver.n_dofs(), NV_DATA_S(yy));
49  const VectorView<double> src_yp(solver.n_dofs(), NV_DATA_S(yp));
50  const VectorView<double> residual(solver.n_dofs(), NV_DATA_S(rr));
51  return solver.setup_jacobian_prec(tt, src_yy, src_yp, alpha);
52 }
53 
54 int dae_jtimes(realtype tt, N_Vector yy, N_Vector yp,
55  N_Vector rr, // Current residual
56  N_Vector src, // right hand side to solve for
57  N_Vector dst, // computed output
58  realtype alpha, // J = dG/dyy + alpha dG/dyp
59  void *user_data, // the pointer to the correct class
60  N_Vector /*tmp*/,
61  N_Vector /*tmp2*/) // Storage
62 {
63  //double* a = NV_DATA_S(src);
64  //for (unsigned int i=0; i<NV_LENGTH_S(src); ++i)
65  // if (!(numbers::is_finite(a[i])))
66  // cout<<i<<endl;
67  OdeArgument &solver = *static_cast<OdeArgument *>(user_data);
68  Assert(NV_LENGTH_S(yy) == solver.n_dofs(),
69  ExcDimensionMismatch(NV_LENGTH_S(yy), solver.n_dofs()));
70  Assert(NV_LENGTH_S(yp) == solver.n_dofs(),
71  ExcDimensionMismatch(NV_LENGTH_S(yp), solver.n_dofs()));
72  Assert(NV_LENGTH_S(src) == solver.n_dofs(),
73  ExcDimensionMismatch(NV_LENGTH_S(src), solver.n_dofs()));
74  Assert(NV_LENGTH_S(dst) == solver.n_dofs(),
75  ExcDimensionMismatch(NV_LENGTH_S(dst), solver.n_dofs()));
76 
77  // A previous call to residual has already been done.
78  const VectorView<double> src_yy(solver.n_dofs(), NV_DATA_S(yy));
79  const VectorView<double> src_yp(solver.n_dofs(), NV_DATA_S(yp));
80  const VectorView<double> residual(solver.n_dofs(), NV_DATA_S(rr));
81  const VectorView<double> src_v(solver.n_dofs(), NV_DATA_S(src));
82  VectorView<double> dst_v(solver.n_dofs(), NV_DATA_S(dst));
83  return solver.jacobian(tt, dst_v, src_yy, src_yp, src_v, alpha);
84 }
85 
86 
87 int dae_prec(realtype tt, N_Vector yy, N_Vector yp,
88  N_Vector rr, // Current residual
89  N_Vector rvec, // right hand side to solve for
90  N_Vector zvec, // computed output
91  realtype alpha, // J = dG/dyy + alpha dG/dyp
92  realtype /*delta*/, // input tolerance. The residual rr - Pz has to be smaller than delta
93  void *user_data, // the pointer to the correct class
94  N_Vector /*tmp*/) // Storage
95 {
96  OdeArgument &solver = *static_cast<OdeArgument *>(user_data);
97  Assert(NV_LENGTH_S(yy) == solver.n_dofs(),
98  ExcDimensionMismatch(NV_LENGTH_S(yy), solver.n_dofs()));
99  Assert(NV_LENGTH_S(yp) == solver.n_dofs(),
100  ExcDimensionMismatch(NV_LENGTH_S(yp), solver.n_dofs()));
101  Assert(NV_LENGTH_S(rr) == solver.n_dofs(),
102  ExcDimensionMismatch(NV_LENGTH_S(rr), solver.n_dofs()));
103  // A previous call to residual has already been done.
104  const VectorView<double> src_yy(solver.n_dofs(), NV_DATA_S(yy));
105  const VectorView<double> src_yp(solver.n_dofs(), NV_DATA_S(yp));
106  const VectorView<double> residual(solver.n_dofs(), NV_DATA_S(rr));
107  const VectorView<double> rhs(solver.n_dofs(), NV_DATA_S(rvec));
108  VectorView<double> output(solver.n_dofs(), NV_DATA_S(zvec));
109  return solver.jacobian_prec(tt, output, src_yy, src_yp, rhs, alpha);
110 }
111 
112 
113 
115  solver(bubble),
116  is_initialized(false)
117 {
118  initial_step_size = 1e-4;
119  min_step_size = 1e-6;
120 
121  abs_tol = 1e-6;
122  rel_tol = 1e-8;
123 
124  ida_mem = IDACreate();
125  is_initialized = true;
126 
127 }
128 
129 
131  double initial_step_size,
132  double min_step_size,
133  double initial_time,
134  double final_time,
135  double abs_tol,
136  double rel_tol,
137  unsigned int max_n_steps,
138  double outputs_period,
139  unsigned int ic_type,
140  bool use_iterative,
141  bool provide_jac,
142  bool provide_jac_prec) :
143  final_time(final_time),
144  initial_time(initial_time),
145  solver(bubble),
146  initial_step_size(initial_step_size),
147  min_step_size(min_step_size),
148  abs_tol(abs_tol),
149  rel_tol(rel_tol),
150  max_n_steps(max_n_steps),
151  outputs_period(outputs_period),
152  ic_type(ic_type),
153  is_initialized(false),
154  use_iterative(use_iterative),
155  provide_jac(provide_jac),
156  provide_jac_prec(provide_jac_prec)
157 {
158 
159  ida_mem = IDACreate();
160  is_initialized = true;
161 
162 }
163 
164 
165 
167 {
168  if (ida_mem)
169  IDAFree(&ida_mem);
170 }
171 
172 
174 {
175  prm.enter_subsection("IDA Solver Params");
176  {
177  prm.declare_entry("Use iterative algorithm", "false", Patterns::Bool());
178  prm.declare_entry("Provide jacobian product", "false", Patterns::Bool());
179  prm.declare_entry("Provide jacobian preconditioner", "false", Patterns::Bool());
180  prm.declare_entry("Initial step size", "1e-4", Patterns::Double());
181  prm.declare_entry("Min step size", "5e-5", Patterns::Double());
182  prm.declare_entry("Absolute error tolerance", "1e-4", Patterns::Double());
183  prm.declare_entry("Relative error tolerance", "1e-3", Patterns::Double());
184  prm.declare_entry("Initial time", "0", Patterns::Double());
185  prm.declare_entry("Final time", "100000", Patterns::Double());
186  prm.declare_entry("Seconds between each output", "1e-1", Patterns::Double());
187  prm.declare_entry("Initial condition type", "0", Patterns::Integer());
188  }
189  prm.leave_subsection();
190 }
191 
192 
194 {
195  prm.enter_subsection("IDA Solver Params");
196  {
197  use_iterative = prm.get_bool("Use iterative algorithm");
198  provide_jac = prm.get_bool("Provide jacobian product");
199  provide_jac_prec = prm.get_bool("Provide jacobian preconditioner");
200  initial_step_size = prm.get_double("Initial step size");
201  min_step_size = prm.get_double("Min step size");
202  abs_tol = prm.get_double("Absolute error tolerance");
203  rel_tol = prm.get_double("Relative error tolerance");
204  initial_time = prm.get_double("Initial time");
205  final_time = prm.get_double("Final time");
206  outputs_period = prm.get_double("Seconds between each output");
207  ic_type = prm.get_integer("Initial condition type");
208  }
209  prm.leave_subsection();
210 }
211 
213  Vector<double> &solution_dot,
214  const unsigned int max_steps)
215 {
216 
217 
218  AssertThrow(solution.size() == solver.n_dofs(),
219  ExcDimensionMismatch(solution.size(), solver.n_dofs()));
220 
221  AssertThrow(is_initialized, ExcMessage("Not Initialized!"));
222 
223  double t = initial_time;
224  double h = initial_step_size;
225  unsigned int step_number = 0;
226 
227  int status;
228 
229  // The solution is stored in
230  // solution. Here we take only a
231  // view of it.
232 
233  yy = N_VNewEmpty_Serial(solver.n_dofs());
234  NV_DATA_S(yy) = solution.begin();
235 
236  yp = N_VNewEmpty_Serial(solver.n_dofs());
237  NV_DATA_S(yp) = solution_dot.begin();
238 
239  diff_id = N_VNewEmpty_Serial(solver.n_dofs());
240  NV_DATA_S(diff_id) = solver.differential_components().begin();
241 
242  Vector<double> tolerances = solver.get_diameters();
243  tolerances*=(1/tolerances.linfty_norm()*abs_tol);
244  abs_tolls = N_VNewEmpty_Serial(solver.n_dofs());
245  NV_DATA_S(abs_tolls) = tolerances.begin();
246 
247  status = IDAInit(ida_mem, dae_residual, initial_time, yy, yp);
248  //status += IDASStolerances(ida_mem, rel_tol, abs_tol);
249  status += IDASVtolerances(ida_mem, rel_tol, abs_tolls);
250  status += IDASetInitStep(ida_mem, step_number);
251  status += IDASetUserData(ida_mem, (void *) &solver);
252  //status += IDASetMaxNonlinIters(ida_mem, 60);
253 //AssertThrow(status == 0, ExcMessage("Error in IDA Solver"));
254 // status += IDASetNonlinConvCoef(ida_mem, 10.0);
255  //status += IDASetMaxOrd(ida_mem, 2);
256 
257  reset_ode(solution, solution_dot, initial_time, initial_step_size, max_steps);
258 
259  double next_time = 0;
260  while ((t<final_time) && (step_number < max_steps))
261  {
262 
263  next_time += outputs_period;
264  cout << t <<"---->"<<next_time<<endl;
265  status = IDASolve(ida_mem, next_time, &t, yy, yp, IDA_NORMAL);
266 
267  status = IDAGetLastStep(ida_mem, &h);
268  AssertThrow(status == 0, ExcMessage("Error in IDA Solver"));
269  cout << "Step " << step_number
270  << ", t = " << t
271  << ", h = " << h << endl;
272 
273  // Check the solution
274  bool reset = solver.solution_check(solution, solution_dot, t, step_number, h);
275 
276 
277  solver.output_step(solution, solution_dot, t, step_number, h);
278 
279  if ( reset == true )
280  {
281  NV_LENGTH_S(yy) = solution.size();
282  NV_DATA_S(yy) = solution.begin();
283  NV_LENGTH_S(yp) = solution_dot.size();
284  NV_DATA_S(yp) = solution_dot.begin();
285 
286  double frac = 0;
287  int k = 0;
288  IDAGetLastOrder(ida_mem, &k);
289  frac = std::pow((double)k,2.);
290  reset_ode(solution, solution_dot, t,
291  h/frac, max_steps);
292  }
293 
294 
295  step_number++;
296  }
297 
298  // Free the vectors which are no longer used.
299  N_VDestroy_Serial(yy);
300  N_VDestroy_Serial(yp);
301  N_VDestroy_Serial(abs_tolls);
302  N_VDestroy_Serial(diff_id);
303 
304  return step_number;
305 }
306 
307 
309  Vector<double> &solution_dot,
310  double current_time,
311  double current_time_step,
312  unsigned int max_steps)
313 {
314  if (ida_mem)
315  IDAFree(&ida_mem);
316 
317  ida_mem = IDACreate();
318 
319  int status;
320  Assert(solution.size() == solver.n_dofs(),
321  ExcDimensionMismatch(solution.size(), solver.n_dofs()));
322 
323  Assert(solution_dot.size() == solver.n_dofs(),
324  ExcDimensionMismatch(solution_dot.size(), solver.n_dofs()));
325 
326  // Free the vectors which are no longer used.
327  if (yy)
328  N_VDestroy_Serial(yy);
329  if (yp)
330  N_VDestroy_Serial(yp);
331  if (abs_tolls)
332  N_VDestroy_Serial(abs_tolls);
333  if (diff_id)
334  N_VDestroy_Serial(diff_id);
335 
336 
337  // The solution is stored in
338  // solution. Here we take only a
339  // view of it.
340  yy = N_VNewEmpty_Serial(solver.n_dofs());
341  NV_DATA_S(yy) = solution.begin();
342 
343  //N_VPrint_Serial(yy);
344  //solution_dot.print();
345  yp = N_VNewEmpty_Serial(solver.n_dofs());
346  NV_DATA_S(yp) = solution_dot.begin();
347  //N_VPrint_Serial(yp);
348 
349  diff_id = N_VNewEmpty_Serial(solver.n_dofs());
350  NV_DATA_S(diff_id) = solver.differential_components().begin();
351 
352  Vector<double> tolerances = solver.get_diameters();
353  tolerances*=(1/tolerances.linfty_norm()*abs_tol);
354  abs_tolls = N_VNewEmpty_Serial(solver.n_dofs());
355  NV_DATA_S(abs_tolls) = tolerances.begin();
356  //N_VPrint_Serial(abs_tolls);
357 
358  status = IDAInit(ida_mem, dae_residual, current_time, yy, yp);
359  //status += IDASStolerances(ida_mem, rel_tol, abs_tol);
360  status += IDASVtolerances(ida_mem, rel_tol, abs_tolls);
361  status += IDASetInitStep(ida_mem, current_time_step);
362  status += IDASetUserData(ida_mem, (void *) &solver);
363 
364  status += IDASetId(ida_mem, diff_id);
365  status += IDASetSuppressAlg(ida_mem, TRUE);
366 
367  status += IDASetMaxNumSteps(ida_mem, max_steps);
368  status += IDASetStopTime(ida_mem, final_time);
369 
370  status += IDASetMaxNonlinIters(ida_mem, 10);
371 
372 
373  if (use_iterative == true)
374  {
375  status += IDASpgmr(ida_mem, solver.n_dofs());
376  if (provide_jac)
377  status += IDASpilsSetJacTimesVecFn(ida_mem, dae_jtimes);
378  if (provide_jac_prec)
379  status += IDASpilsSetPreconditioner(ida_mem, dae_setup_prec, dae_prec);
380  }
381  else
382  {
383  status += IDALapackDense(ida_mem, solver.n_dofs());
384  }
385 
386  status += IDASetMaxOrd(ida_mem, 5);
387  //std::cout<<"???1"<<std::endl;
388 
389  AssertThrow(status == 0, ExcMessage("Error initializing IDA."));
390  //std::cout<<"???1"<<std::endl;
391  if (ic_type == 2)
392  {
393  // (re)initialization of the vectors
394  //solution_dot = 0;
395  if (current_time !=0)
396  IDACalcIC(ida_mem, IDA_Y_INIT, current_time+current_time_step);
397  IDAGetConsistentIC(ida_mem, yy, yp);
398  }
399  else if (ic_type == 1)
400  {
401  IDACalcIC(ida_mem, IDA_YA_YDP_INIT, current_time+current_time_step);
402  IDAGetConsistentIC(ida_mem, yy, yp);
403  }
404  else if (ic_type == 3)
405  {
406  IDAGetConsistentIC(ida_mem, yy, yp);
407  std::cout << "Using consistent conditions type 3" << std::endl;
408  }
409  Vector<double> resid(solver.n_dofs());
410  solver.residual(current_time,resid,solution,solution_dot);
411 
412  //solution_dot.reinit(solver.n_dofs());
413  //Vector<double> res(solver.n_dofs());
414  //solver.residual(0,res,solution_dot,solution);
415  //solution_dot -= res;
416  //solver.output_step(solution, solution_dot, 0, 0, current_time_step);
417 }
int dae_jtimes(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, N_Vector src, N_Vector dst, realtype alpha, void *user_data, N_Vector, N_Vector)
int dae_residual(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
double rel_tol
Relative error tolerance for adaptive time stepping.
#define TRUE
virtual unsigned int n_dofs() const =0
Returns the number of degrees of freedom.
bool use_iterative
If true, we use preconditioned gmres.
N_Vector diff_id
Ida differential components vector.
bool is_initialized
Initialization flag.
void parse_parameters(ParameterHandler &prm)
Parse a parameter handler.
double final_time
Final time.
unsigned int start_ode(Vector< double > &solution, Vector< double > &solution_dot, const unsigned int max_steps)
Evolve.
virtual Vector< double > & differential_components()
And an identification of the differential components.
Definition: ode_argument.cc:34
bool provide_jac_prec
Provide preconditioning for Jacobian.
STL namespace.
virtual void output_step(Vector< double > &solution, Vector< double > &solution_dot, const double t, const unsigned int step_number, const double h)=0
This function is called at the end of each iteration step for the ode solver.
void * ida_mem
Ida memory object.
#define AssertThrow(cond, exc)
virtual int residual(const double t, Vector< double > &dst, const Vector< double > &src_yy, const Vector< double > &src_yp)=0
For dae problems, we need a residual function.
N_Vector abs_tolls
Ida absolute tolerances vector.
real_type linfty_norm() const
void enter_subsection(const std::string &subsection)
virtual bool solution_check(Vector< double > &solution, Vector< double > &solution_dot, const double t, const unsigned int step_number, const double h)=0
This function will check the behaviour of the solution.
static::ExceptionBase & ExcMessage(std::string arg1)
DAETimeIntegrator(OdeArgument &solver)
Constructor for the DAETimeIntegrator class.
N_Vector yy
Ida solution vector.
virtual Vector< double > & get_diameters()
Definition: ode_argument.cc:42
#define Assert(cond, exc)
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
double initial_step_size
Initial step size.
double min_step_size
Minimum step size.
virtual int setup_jacobian_prec(const double t, const Vector< double > &src_yy, const Vector< double > &src_yp, const double alpha)
Setup Jacobian preconditioner.
Definition: ode_argument.cc:3
std::size_t size() const
bool provide_jac
Provides the Jacobian vector product.
iterator begin()
virtual int jacobian_prec(const double t, Vector< double > &dst, const Vector< double > &src_yy, const Vector< double > &src_yp, const Vector< double > &src, const double alpha)
Jacobian preconditioner vector product.
Definition: ode_argument.cc:12
void leave_subsection()
bool get_bool(const std::string &entry_name) const
~DAETimeIntegrator()
House cleaning.
int dae_prec(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, N_Vector rvec, N_Vector zvec, realtype alpha, realtype, void *user_data, N_Vector)
void reset_ode(Vector< double > &y, Vector< double > &yp, double t, double h, unsigned int max_steps)
Clear internal memory, and start with clean objects.
double get_double(const std::string &entry_name) const
double abs_tol
Absolute error tolerance for adaptive time stepping.
double initial_time
Initial time for the ode.
void declare_entry(const std::string &entry, const std::string &default_value, const Patterns::PatternBase &pattern=Patterns::Anything(), const std::string &documentation=std::string())
N_Vector yp
Ida solution derivative vector.
virtual int jacobian(const double t, Vector< double > &dst, const Vector< double > &src_yy, const Vector< double > &src_yp, const Vector< double > &src, const double alpha)
Jacobian vector product.
Definition: ode_argument.cc:22
Base class that needs to be inherited by any function that wants to use the time integrator class...
Definition: ode_argument.h:12
int dae_setup_prec(realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, realtype alpha, void *user_data, N_Vector, N_Vector, N_Vector)
long int get_integer(const std::string &entry_string) const
static void declare_parameters(ParameterHandler &prm)
Declare parameters for this class to function properly.
OdeArgument & solver
The bubble membrane poperties.