runge_kutta.cpp
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 #include "runge_kutta.hpp"
27 
28 namespace casadi {
29 
30  extern "C"
31  int CASADI_INTEGRATOR_RK_EXPORT
32  casadi_register_integrator_rk(Integrator::Plugin* plugin) {
33  plugin->creator = RungeKutta::creator;
34  plugin->name = "rk";
35  plugin->doc = RungeKutta::meta_doc.c_str();
36  plugin->version = CASADI_VERSION;
37  plugin->options = &RungeKutta::options_;
38  plugin->deserialize = &RungeKutta::deserialize;
39  return 0;
40  }
41 
42  extern "C"
43  void CASADI_INTEGRATOR_RK_EXPORT casadi_load_integrator_rk() {
45  }
46 
47  RungeKutta::RungeKutta(const std::string& name, const Function& dae, double t0,
48  const std::vector<double>& tout)
49  : FixedStepIntegrator(name, dae, t0, tout) {
50  }
51 
53  }
54 
55  void RungeKutta::init(const Dict& opts) {
56  // Call the base class init
58 
59  // Algebraic variables not supported
60  casadi_assert(nz_==0 && nrz_==0,
61  "Explicit Runge-Kutta integrators do not support algebraic variables");
62  }
63 
65  // Continuous-time dynamics, forward problem
66  Function f = get_function("dae");
67 
68  // Symbolic inputs
69  MX t0 = MX::sym("t0", f.sparsity_in(DYN_T));
70  MX h = MX::sym("h");
71  MX x0 = MX::sym("x0", f.sparsity_in(DYN_X));
72  MX p = MX::sym("p", f.sparsity_in(DYN_P));
73  MX u = MX::sym("u", f.sparsity_in(DYN_U));
74 
75  // Half a step, 6-th of a step
76  MX h_half = h / 2, h_sixth = h / 6;
77 
78  // Arguments when calling f
79  std::vector<MX> f_arg(DYN_NUM_IN);
80  std::vector<MX> f_res;
81  f_arg[DYN_P] = p;
82  f_arg[DYN_U] = u;
83 
84  // k1
85  f_arg[DYN_T] = t0;
86  f_arg[DYN_X] = x0;
87  f_res = f(f_arg);
88  MX k1 = f_res[DYN_ODE];
89  MX k1q = f_res[DYN_QUAD];
90 
91  // k2
92  f_arg[DYN_T] = t0 + h_half;
93  f_arg[DYN_X] = x0 + h_half * k1;
94  f_res = f(f_arg);
95  MX k2 = f_res[DYN_ODE];
96  MX k2q = f_res[DYN_QUAD];
97 
98  // k3
99  f_arg[DYN_X] = x0 + h_half * k2;
100  f_res = f(f_arg);
101  MX k3 = f_res[DYN_ODE];
102  MX k3q = f_res[DYN_QUAD];
103 
104  // k4
105  f_arg[DYN_T] = t0 + h;
106  f_arg[DYN_X] = x0 + h * k3;
107  f_res = f(f_arg);
108  MX k4 = f_res[DYN_ODE];
109  MX k4q = f_res[DYN_QUAD];
110 
111  // Take step
112  MX xf = x0 + h_sixth * (k1 + 2*k2 + 2*k3 + k4);
113  MX qf = h_sixth * (k1q + 2*k2q + 2*k3q + k4q);
114 
115  // Define discrete time dynamics
116  f_arg.resize(STEP_NUM_IN);
117  f_arg[STEP_T] = t0;
118  f_arg[STEP_H] = h;
119  f_arg[STEP_X0] = x0;
120  f_arg[STEP_V0] = MX(0, 1);
121  f_arg[STEP_P] = p;
122  f_arg[STEP_U] = u;
123  f_res.resize(STEP_NUM_OUT);
124  f_res[STEP_XF] = xf;
125  f_res[STEP_QF] = qf;
126  f_res[STEP_VF] = MX(0, 1);
127  Function F("step", f_arg, f_res,
128  {"t", "h", "x0", "v0", "p", "u"}, {"xf", "vf", "qf"});
129  set_function(F, F.name(), true);
130  if (nfwd_ > 0) create_forward("step", nfwd_);
131 
132  // Backward integration
133  if (nadj_ > 0) {
134  Function adj_F = F.reverse(nadj_);
135  set_function(adj_F, adj_F.name(), true);
136  if (nfwd_ > 0) {
137  create_forward(adj_F.name(), nfwd_);
138  }
139  }
140  }
141 
143  s.version("RungeKutta", 2);
144  }
145 
148  s.version("RungeKutta", 2);
149  }
150 
151 } // namespace casadi
Helper class for Serialization.
void version(const std::string &name, int v)
static const Options options_
Options.
void init(const Dict &opts) override
Initialize stage.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Function object.
Definition: function.hpp:60
const std::string & name() const
Name of the function.
Definition: function.cpp:1307
Function reverse(casadi_int nadj) const
Get a function that calculates nadj adjoint derivatives.
Definition: function.cpp:1143
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
Definition: function.cpp:1015
static MX sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
casadi_int nfwd_
Number of sensitivities.
MX - Matrix expression.
Definition: mx.hpp:92
void set_function(const Function &fcn, const std::string &fname, bool jit=false)
Function create_forward(const std::string &fname, casadi_int nfwd)
std::vector< std::string > get_function() const override
Get list of dependency functions.
static void registerPlugin(const Plugin &plugin, bool needs_lock=true)
Register an integrator in the factory.
static const std::string meta_doc
A documentation string.
Definition: runge_kutta.hpp:84
void setup_step() override
Setup step functions.
Definition: runge_kutta.cpp:64
RungeKutta(const std::string &name, const Function &dae, double t0, const std::vector< double > &tout)
Constructor.
Definition: runge_kutta.cpp:47
void init(const Dict &opts) override
Initialize stage.
Definition: runge_kutta.cpp:55
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
Definition: runge_kutta.hpp:90
static Integrator * creator(const std::string &name, const Function &dae, double t0, const std::vector< double > &tout)
Create a new integrator.
Definition: runge_kutta.hpp:63
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
~RungeKutta() override
Destructor.
Definition: runge_kutta.cpp:52
Helper class for Serialization.
void version(const std::string &name, int v)
The casadi namespace.
Definition: archiver.cpp:28
@ 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.
@ 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.
void CASADI_INTEGRATOR_RK_EXPORT casadi_load_integrator_rk()
Definition: runge_kutta.cpp:43
@ DYN_NUM_IN
Definition: integrator.hpp:196
int CASADI_INTEGRATOR_RK_EXPORT casadi_register_integrator_rk(Integrator::Plugin *plugin)
Definition: runge_kutta.cpp:32
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.