integrator_impl.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_INTEGRATOR_IMPL_HPP
27 #define CASADI_INTEGRATOR_IMPL_HPP
28 
29 #include "integrator.hpp"
30 #include "oracle_function.hpp"
31 #include "plugin_interface.hpp"
32 #include "casadi_enum.hpp"
33 
35 
36 namespace casadi {
37 
41 struct CASADI_EXPORT IntegratorMemory : public OracleMemory {
42  // Work vectors, forward problem
43  double *q, *x, *z, *p, *u, *e, *edot, *old_e, *xdot, *zdot;
44  // Work vectors, backward problem
45  double *adj_x, *adj_z, *adj_p, *adj_q;
46  // Temporary work vectors of length max(nx + nz, nrx, nrz)
47  double *tmp1, *tmp2;
48  // Current control interval
49  casadi_int k;
50  // Current time
51  double t;
52  // Next time to be visited by the integrator
53  double t_next;
54  // Time not to be exceeded by during integrator integration
55  double t_stop;
56  // Time at the beginning of the current control interval
57  double t_start;
58  // Next output time
59  double t_next_out;
60  // Next stop time due to step change in input
61  double t_step;
62  // Which events have been triggered
63  casadi_int *event_triggered;
64  // Do we need to reset the solver?
66  // Number of root-finding iterations for a single event
67  casadi_int event_iter;
68  // Number of events encountered thus far
69  casadi_int num_events;
70  // Index of event last triggered
71  casadi_int event_index;
72 };
73 
75 struct CASADI_EXPORT SpForwardMem {
76  const bvec_t** arg;
78  casadi_int* iw;
80 };
81 
83 struct CASADI_EXPORT SpReverseMem {
86  casadi_int* iw;
88 };
89 
97 class CASADI_EXPORT
98 Integrator : public OracleFunction, public PluginInterface<Integrator> {
99  public:
103  Integrator(const std::string& name, const Function& oracle,
104  double t0, const std::vector<double>& tout);
105 
109  ~Integrator() override=0;
110 
112 
115  size_t get_n_in() override { return INTEGRATOR_NUM_IN;}
116  size_t get_n_out() override { return INTEGRATOR_NUM_OUT;}
118 
120 
123  Sparsity get_sparsity_in(casadi_int i) override;
124  Sparsity get_sparsity_out(casadi_int i) override;
126 
128 
131  std::string get_name_in(casadi_int i) override { return integrator_in(i);}
132  std::string get_name_out(casadi_int i) override { return integrator_out(i);}
134 
138  int init_mem(void* mem) const override;
139 
141 
144  static const Options options_;
145  const Options& get_options() const override { return options_;}
147 
151  void init(const Dict& opts) override;
152 
156  void set_work(void* mem, const double**& arg, double**& res,
157  casadi_int*& iw, double*& w) const override;
158 
160  virtual Function create_advanced(const Dict& opts);
161 
162  virtual MX algebraic_state_init(const MX& x0, const MX& z0) const { return z0; }
163  virtual MX algebraic_state_output(const MX& Z) const { return Z; }
164 
165  // Set the quadrature states
166  void set_q(IntegratorMemory* m, const double* q) const;
167 
168  // Set the differential states
169  void set_x(IntegratorMemory* m, const double* x) const;
170 
171  // Set the algebraic variables
172  void set_z(IntegratorMemory* m, const double* z) const;
173 
174  // Set the parameters
175  void set_p(IntegratorMemory* m, const double* p) const;
176 
177  // Set the controls
178  void set_u(IntegratorMemory* m, const double* u) const;
179 
180  // Get the quadrature states
181  void get_q(IntegratorMemory* m, double* q) const;
182 
183  // Get the differential states
184  void get_x(IntegratorMemory* m, double* x) const;
185 
186  // Get the algebraic variables
187  void get_z(IntegratorMemory* m, double* z) const;
188 
192  virtual void reset(IntegratorMemory* mem, bool first_call) const {}
193 
197  casadi_int next_stop(casadi_int k, const double* u) const;
198 
202  int calc_edot(IntegratorMemory* m) const;
203 
207  int predict_events(IntegratorMemory* m) const;
208 
212  int trigger_event(IntegratorMemory* m, casadi_int* ind) const;
213 
217  int advance(IntegratorMemory* m) const;
218 
222  virtual int advance_noevent(IntegratorMemory* mem) const = 0;
223 
227  virtual void resetB(IntegratorMemory* mem) const = 0;
228 
232  casadi_int next_stopB(casadi_int k, const double* u) const;
233 
237  virtual void impulseB(IntegratorMemory* mem,
238  const double* adj_x, const double* adj_z, const double* adj_q) const = 0;
239 
243  virtual void retreat(IntegratorMemory* mem, const double* u,
244  double* adj_x, double* adj_p, double* adj_u) const = 0;
245 
249  int eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const override;
250 
254  virtual void print_stats(IntegratorMemory* mem) const {}
255 
257  int fdae_sp_forward(SpForwardMem* m, const bvec_t* x,
258  const bvec_t* p, const bvec_t* u, bvec_t* ode, bvec_t* alg) const;
259 
261  int fquad_sp_forward(SpForwardMem* m, const bvec_t* x, const bvec_t* z,
262  const bvec_t* p, const bvec_t* u, bvec_t* quad) const;
263 
265  int bdae_sp_forward(SpForwardMem* m, const bvec_t* x, const bvec_t* z,
266  const bvec_t* p, const bvec_t* u, const bvec_t* adj_ode, const bvec_t* adj_quad,
267  bvec_t* adj_x, bvec_t* adj_z) const;
268 
270  int bquad_sp_forward(SpForwardMem* m, const bvec_t* x, const bvec_t* z,
271  const bvec_t* p, const bvec_t* u, const bvec_t* adj_ode, const bvec_t* adj_alg,
272  const bvec_t* adj_quad, bvec_t* adj_p, bvec_t* adj_u) const;
273 
277  int sp_forward(const bvec_t** arg, bvec_t** res,
278  casadi_int* iw, bvec_t* w, void* mem) const override;
279 
281  int fdae_sp_reverse(SpReverseMem* m, bvec_t* x,
282  bvec_t* p, bvec_t* u, bvec_t* ode, bvec_t* alg) const;
283 
285  int fquad_sp_reverse(SpReverseMem* m, bvec_t* x, bvec_t* z,
286  bvec_t* p, bvec_t* u, bvec_t* quad) const;
287 
289  int bdae_sp_reverse(SpReverseMem* m, bvec_t* x, bvec_t* z,
290  bvec_t* p, bvec_t* u, bvec_t* adj_ode, bvec_t* adj_quad,
291  bvec_t* adj_x, bvec_t* adj_z) const;
292 
294  int bquad_sp_reverse(SpReverseMem* m, bvec_t* x, bvec_t* z,
295  bvec_t* p, bvec_t* u, bvec_t* adj_ode, bvec_t* adj_alg, bvec_t* adj_quad,
296  bvec_t* adj_p, bvec_t* adj_u) const;
297 
301  int sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w, void* mem) const override;
302 
305  bool has_spfwd() const override { return true;}
306  bool has_sprev() const override { return true;}
308 
310 
313  Function get_forward(casadi_int nfwd, const std::string& name,
314  const std::vector<std::string>& inames,
315  const std::vector<std::string>& onames,
316  const Dict& opts) const override;
317  bool has_forward(casadi_int nfwd) const override { return true;}
319 
321 
324  Function get_reverse(casadi_int nadj, const std::string& name,
325  const std::vector<std::string>& inames,
326  const std::vector<std::string>& onames,
327  const Dict& opts) const override;
328  bool has_reverse(casadi_int nadj) const override { return ne_ == 0;}
330 
334  virtual Dict getDerivativeOptions(bool fwd) const;
335 
337 
340  template<typename MatType> Function get_forward_dae(const std::string& name) const;
341  Function augmented_dae() const;
343 
345  static bool all_zero(const double* v, casadi_int n);
346 
348  Sparsity sp_jac_aug(const Sparsity& J, const Sparsity& J1) const;
349 
351  Sparsity sp_jac_dae();
352 
354  Sparsity sp_jac_rdae();
355 
357  Sparsity sp_jac_dae_, sp_jac_rdae_;
358 
360  inline casadi_int nt() const { return tout_.size();}
361 
363 
366  enum DaeOut { DAE_ODE, DAE_ALG, DAE_NUM_OUT};
367  static std::vector<std::string> dae_out() { return {"ode", "alg"}; }
368  enum QuadOut { QUAD_QUAD, QUAD_NUM_OUT};
369  static std::vector<std::string> quad_out() { return {"quad"}; }
370  enum BDynIn { BDYN_T, BDYN_X, BDYN_Z, BDYN_P, BDYN_U,
371  BDYN_OUT_ODE, BDYN_OUT_ALG, BDYN_OUT_QUAD, BDYN_OUT_ZERO,
372  BDYN_ADJ_ODE, BDYN_ADJ_ALG, BDYN_ADJ_QUAD, BDYN_ADJ_ZERO, BDYN_NUM_IN};
373  static std::string bdyn_in(casadi_int i);
374  static std::vector<std::string> bdyn_in();
375  enum BDynOut { BDYN_ADJ_T, BDYN_ADJ_X, BDYN_ADJ_Z, BDYN_ADJ_P, BDYN_ADJ_U, BDYN_NUM_OUT};
376  static std::string bdyn_out(casadi_int i);
377  static std::vector<std::string> bdyn_out();
378  enum DAEBOut { BDAE_ADJ_X, BDAE_ADJ_Z, BDAE_NUM_OUT};
379  static std::vector<std::string> bdae_out() { return {"adj_x", "adj_z"}; }
380  enum QuadBOut { BQUAD_ADJ_P, BQUAD_ADJ_U, BQUAD_NUM_OUT};
381  static std::vector<std::string> bquad_out() { return {"adj_p", "adj_u"}; }
383 
385  double t0_;
386 
388  std::vector<double> tout_;
389 
391  casadi_int nfwd_, nadj_;
392 
395 
397  casadi_int nx_, nz_, nq_, nx1_, nz1_, nq1_;
398 
400  casadi_int nrx_, nrz_, nrq_, nuq_, nrx1_, nrz1_, nrq1_, nuq1_;
401 
403  casadi_int np_, nrp_, np1_, nrp1_;
404 
406  casadi_int nu_, nu1_;
407 
409  casadi_int ne_;
410 
412  casadi_int ntmp_;
413 
414  // Nominal values for states
415  std::vector<double> nom_x_, nom_z_;
416 
419 
422 
425 
428 
430  casadi_int max_event_iter_;
431 
433  casadi_int max_events_;
434 
436  double event_tol_;
437 
440 
441  // Creator function for internal class
442  typedef Integrator* (*Creator)(const std::string& name, const Function& oracle,
443  double t0, const std::vector<double>& tout);
444 
445  // No static functions exposed
446  struct Exposed{ };
447 
449  static std::map<std::string, Plugin> solvers_;
450 
451 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
452  static std::mutex mutex_solvers_;
453 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
454 
456  static const std::string infix_;
457 
459  template<typename XType>
460  static Function map2oracle(const std::string& name, const std::map<std::string, XType>& d);
461 
465  void serialize_body(SerializingStream &s) const override;
469  void serialize_type(SerializingStream &s) const override;
470 
474  static ProtoFunction* deserialize(DeserializingStream& s);
475 
479  std::string serialize_base_function() const override { return "Integrator"; }
480 
482  static bool grid_in(casadi_int i);
483 
485  static bool grid_out(casadi_int i);
486 
488  static casadi_int adjmap_out(casadi_int i);
489 
490  protected:
494  explicit Integrator(DeserializingStream& s);
495 };
496 
498 enum StepIn {
513 };
514 
516 enum StepOut {
525 };
526 
528 enum BStepIn {
542 };
543 
545 enum BStepOut {
553 };
554 
555 struct CASADI_EXPORT FixedStepMemory : public IntegratorMemory {
557  double *v, *v_prev, *q_prev;
558 
560  double *rv, *adj_u, *adj_p_prev, *adj_u_prev;
561 
563  double *x_tape, *v_tape;
564 };
565 
566 class CASADI_EXPORT FixedStepIntegrator : public Integrator {
567  public:
568 
570  explicit FixedStepIntegrator(const std::string& name, const Function& dae,
571  double t0, const std::vector<double>& tout);
572 
574  ~FixedStepIntegrator() override;
575 
577 
580  static const Options options_;
581  const Options& get_options() const override { return options_;}
583 
585  void init(const Dict& opts) override;
586 
590  void set_work(void* mem, const double**& arg, double**& res,
591  casadi_int*& iw, double*& w) const override;
592 
594  Function create_advanced(const Dict& opts) override;
595 
599  void* alloc_mem() const override { return new FixedStepMemory();}
600 
604  int init_mem(void* mem) const override;
605 
609  void free_mem(void *mem) const override { delete static_cast<FixedStepMemory*>(mem);}
610 
612  virtual void setup_step() = 0;
613 
617  void reset(IntegratorMemory* mem, bool first_call) const override;
618 
622  int advance_noevent(IntegratorMemory* mem) const override;
623 
625  void resetB(IntegratorMemory* mem) const override;
626 
628  void impulseB(IntegratorMemory* mem,
629  const double* adj_x, const double* adj_z, const double* adj_q) const override;
630 
634  void retreat(IntegratorMemory* mem, const double* u,
635  double* adj_x, double* adj_p, double* adj_u) const override;
636 
638  void stepF(FixedStepMemory* m, double t, double h,
639  const double* x0, const double* v0, double* xf, double* vf, double* qf) const;
640 
642  void stepB(FixedStepMemory* m, double t, double h,
643  const double* x0, const double* xf, const double* vf,
644  const double* adj_xf, const double* rv0,
645  double* adj_x0, double* adj_p, double* adj_u) const;
646 
647  // Target number of finite elements
648  casadi_int nk_target_;
649 
650  // Number of steps per control interval
651  std::vector<casadi_int> disc_;
652 
654  casadi_int nv_, nv1_, nrv_, nrv1_;
655 
659  void serialize_body(SerializingStream &s) const override;
660 
661 protected:
666 };
667 
668 class CASADI_EXPORT ImplicitFixedStepIntegrator : public FixedStepIntegrator {
669  public:
670 
672  explicit ImplicitFixedStepIntegrator(const std::string& name, const Function& dae,
673  double t0, const std::vector<double>& tout);
674 
676  ~ImplicitFixedStepIntegrator() override;
677 
679 
682  static const Options options_;
683  const Options& get_options() const override { return options_;}
685 
687  void init(const Dict& opts) override;
688 
692  void serialize_body(SerializingStream &s) const override;
693 
694 protected:
699 };
700 
701 } // namespace casadi
703 
704 #endif // CASADI_INTEGRATOR_IMPL_HPP
Helper class for Serialization.
std::vector< casadi_int > disc_
static const Options options_
Options.
void free_mem(void *mem) const override
Free memory block.
const Options & get_options() const override
Options.
void * alloc_mem() const override
Create memory block.
virtual void setup_step()=0
Setup step functions.
Function object.
Definition: function.hpp:60
const Options & get_options() const override
Options.
static const Options options_
Options.
Internal storage for integrator related data.
virtual void reset(IntegratorMemory *mem, bool first_call) const
Reset the forward solver at the start or after an event.
static const Options options_
Options.
virtual void resetB(IntegratorMemory *mem) const =0
Reset the backward problem.
std::string get_name_out(casadi_int i) override
Names of function input and outputs.
const Options & get_options() const override
Options.
QuadOut
IO conventions for continuous time dynamics.
size_t get_n_in() override
Number of function inputs and outputs.
bool has_forward(casadi_int nfwd) const override
Generate a function that calculates nfwd forward derivatives.
BDynOut
IO conventions for continuous time dynamics.
std::vector< double > nom_x_
Function rdae_
Backwards DAE function.
Dict augmented_options_
Augmented user option.
DaeOut
IO conventions for continuous time dynamics.
casadi_int max_events_
Maximum total number of events during the simulation.
Sparsity sp_jac_dae_
Sparsity pattern of the extended Jacobians.
std::string get_name_in(casadi_int i) override
Names of function input and outputs.
virtual MX algebraic_state_output(const MX &Z) const
bool has_sprev() const override
bool has_reverse(casadi_int nadj) const override
Generate a function that calculates nadj adjoint derivatives.
virtual void retreat(IntegratorMemory *mem, const double *u, double *adj_x, double *adj_p, double *adj_u) const =0
Retreat solution in time.
casadi_int nt() const
Number of output times.
bool print_stats_
Options.
casadi_int ntmp_
Length of the tmp1, tmp2 vectors.
virtual void impulseB(IntegratorMemory *mem, const double *adj_x, const double *adj_z, const double *adj_q) const =0
Introduce an impulse into the backwards integration at the current time.
DAEBOut
IO conventions for continuous time dynamics.
static std::vector< std::string > quad_out()
IO conventions for continuous time dynamics.
BDynIn
IO conventions for continuous time dynamics.
virtual MX algebraic_state_init(const MX &x0, const MX &z0) const
virtual void print_stats(IntegratorMemory *mem) const
Print solver statistics.
static std::vector< std::string > bquad_out()
IO conventions for continuous time dynamics.
size_t get_n_out() override
Number of function inputs and outputs.
Dict opts_
Copy of the options.
static std::map< std::string, Plugin > solvers_
Collection of solvers.
std::vector< double > tout_
Output time grid.
double event_tol_
Termination tolerance for the event iteration.
std::string serialize_base_function() const override
String used to identify the immediate FunctionInternal subclass.
static std::vector< std::string > dae_out()
IO conventions for continuous time dynamics.
double t0_
Initial time.
bool has_spfwd() const override
double event_acceptable_tol_
Acceptable tolerance for the event iteration.
virtual int advance_noevent(IntegratorMemory *mem) const =0
Advance solution in time, without events handling.
Function transition_
Function to be called at state events.
static std::vector< std::string > bdae_out()
IO conventions for continuous time dynamics.
casadi_int max_event_iter_
Maximum number of event iterations for a single event.
static const std::string infix_
Infix.
casadi_int ne_
Number of of zero-crossing functions.
QuadBOut
IO conventions for continuous time dynamics.
MX - Matrix expression.
Definition: mx.hpp:92
Base class for functions that perform calculation with an oracle.
Interface for accessing input and output data structures.
Base class for FunctionInternal and LinsolInternal.
Helper class for Serialization.
General sparsity class.
Definition: sparsity.hpp:106
std::vector< std::string > integrator_out()
Get integrator output scheme of integrators.
Definition: integrator.cpp:190
std::vector< std::string > integrator_in()
Get input scheme of integrators.
Definition: integrator.cpp:184
The casadi namespace.
Definition: archiver.cpp:28
StepIn
Input arguments of a forward stepping function.
@ STEP_H
Step size.
@ STEP_T
Current time.
@ STEP_U
Controls.
@ STEP_X0
State vector.
@ STEP_P
Parameter.
@ STEP_NUM_IN
Number of arguments.
@ STEP_V0
Dependent variables.
@ INTEGRATOR_NUM_OUT
Number of output arguments of an integrator.
Definition: integrator.hpp:259
@ INTEGRATOR_NUM_IN
Number of input arguments of an integrator.
Definition: integrator.hpp:239
unsigned long long bvec_t
StepOut
Output arguments of a forward stepping function.
@ STEP_XF
State vector at next time.
@ STEP_QF
Quadrature state contribution.
@ STEP_VF
Dependent variables at next time.
@ STEP_NUM_OUT
Number of arguments.
BStepIn
Input arguments of a backward stepping function.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
BStepOut
Output arguments of a backward stepping function.
Options metadata for a class.
Definition: options.hpp:40
Function memory.
Memory struct, forward sparsity pattern propagation.
Memory struct, backward sparsity pattern propagation.