finite_differences.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_FINITE_DIFFERENCES_HPP
27 #define CASADI_FINITE_DIFFERENCES_HPP
28 
29 #include "function_internal.hpp"
30 
32 
33 namespace casadi {
34 
36 enum class FdMode {FORWARD, BACKWARD, CENTRAL, SMOOTHING, NUMEL};
37 
39 CASADI_EXPORT std::string to_string(FdMode v);
40 
42 CASADI_EXPORT casadi_int n_fd_points(FdMode v);
43 
45 CASADI_EXPORT casadi_int fd_offset(FdMode v);
46 
48 template<typename T1>
49 CASADI_EXPORT void finite_diff(FdMode v, const T1** yk, T1* J, T1 h, casadi_int n_y,
50  T1 smoothing) {
51  switch (v) {
52  case FdMode::FORWARD:
53  case FdMode::BACKWARD:
54  return casadi_forward_diff(yk, J, h, n_y);
55  case FdMode::CENTRAL:
56  return casadi_central_diff(yk, J, h, n_y);
57  case FdMode::SMOOTHING:
58  return casadi_smoothing_diff(yk, J, h, n_y, eps);
59  default:
60  casadi_error("FD mode " + to_string(v) + " not implemented");
61  }
62 }
63 
68 class CASADI_EXPORT FiniteDiff : public FunctionInternal {
69 public:
70  // Constructor (protected, use create function)
71  FiniteDiff(const std::string& name, casadi_int n);
72  explicit FiniteDiff(DeserializingStream& s);
73  void serialize_body(SerializingStream& s) const override;
74 
78  ~FiniteDiff() override;
79 
81 
84  static const Options options_;
85  const Options& get_options() const override { return options_;}
87 
89 
92  Sparsity get_sparsity_in(casadi_int i) override;
93  Sparsity get_sparsity_out(casadi_int i) override;
95 
99  double get_default_in(casadi_int ind) const override;
100 
102 
105  size_t get_n_in() override;
106  size_t get_n_out() override;
108 
110 
113  std::string get_name_in(casadi_int i) override;
114  std::string get_name_out(casadi_int i) override;
116 
120  void init(const Dict& opts) override;
121 
122  // Evaluate numerically
123  int eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const override;
124 
128  bool uses_output() const override {return true;}
129 
133  bool has_codegen() const override { return true;}
134 
138  void codegen_declarations(CodeGenerator& g) const override;
139 
143  void codegen_body(CodeGenerator& g) const override;
144 
145 protected:
146  // Number of function evaluations needed
147  virtual casadi_int n_pert() const = 0;
148 
149  // Get perturbation expression
150  virtual std::string pert(const std::string& k, const std::string& h) const = 0;
151 
152  // Get perturbation expression
153  virtual double pert(casadi_int k, double h) const = 0;
154 
155  // Calculate finite difference approximation
156  virtual double calc_fd(double** yk, double* y0, double* J, double h) const = 0;
157 
158  // Codegen finite difference approximation
159  virtual std::string calc_fd() const = 0;
160 
161  // Is an error estimate available?
162  virtual casadi_int has_err() const = 0;
163 
164  // Calculate step size from absolute tolerance
165  virtual double calc_stepsize(double abstol) const = 0;
166 
167  // Number of directional derivatives
168  casadi_int n_;
169 
170  // Iterations to improve h
171  casadi_int h_iter_;
172 
173  // Perturbation
174  double h_;
175 
176  // Dimensions
177  casadi_int n_z_, n_y_;
178 
179  // Target ratio of truncation error to roundoff error
180  double u_aim_;
181 
182  // Allowed step size range
183  double h_min_, h_max_;
184 
185  // Memory object
187 };
188 
193 class CASADI_EXPORT ForwardDiff : public FiniteDiff {
194 public:
195  // Constructor
196  ForwardDiff(const std::string& name, casadi_int n) : FiniteDiff(name, n) {}
197  explicit ForwardDiff(DeserializingStream& s) : FiniteDiff(s) {}
198  static ProtoFunction* deserialize(DeserializingStream& s) { return new ForwardDiff(s); }
199 
203  ~ForwardDiff() override {}
204 
208  std::string class_name() const override {return "ForwardDiff";}
209 
210  // Number of function evaluations needed
211  casadi_int n_pert() const override {return 1;};
212 
213  // Get perturbation expression
214  std::string pert(const std::string& k, const std::string& h) const override {
215  return h;
216  }
217 
218  // Get perturbation expression
219  double pert(casadi_int k, double h) const override {
220  return h;
221  }
222 
223  // Calculate finite difference approximation
224  double calc_fd(double** yk, double* y0, double* J, double h) const override;
225 
226  // Codegen finite difference approximation
227  std::string calc_fd() const override {return "casadi_forward_diff_old";}
228 
229  // Is an error estimate available?
230  casadi_int has_err() const override {return false;}
231 
232  // Calculate step size from absolute tolerance
233  double calc_stepsize(double abstol) const override { return sqrt(abstol);}
234 
238  double get_abstol() const override { return h_;}
239 
241 
244  bool has_forward(casadi_int nfwd) const override { return true;}
245  Function get_forward(casadi_int nfwd, const std::string& name,
246  const std::vector<std::string>& inames,
247  const std::vector<std::string>& onames,
248  const Dict& opts) const override;
250 };
251 
256 class CASADI_EXPORT BackwardDiff : public ForwardDiff {
257 public:
258  // Constructor
259  BackwardDiff(const std::string& name, casadi_int n) : ForwardDiff(name, n) {}
260  explicit BackwardDiff(DeserializingStream& s) : ForwardDiff(s) {}
261  static ProtoFunction* deserialize(DeserializingStream& s) { return new BackwardDiff(s); }
262 
266  ~BackwardDiff() override {}
267 
271  std::string class_name() const override {return "BackwardDiff";}
272 
273  // Calculate step size from absolute tolerance
274  double calc_stepsize(double abstol) const override {
275  return -ForwardDiff::calc_stepsize(abstol);
276  }
277 };
278 
283 class CASADI_EXPORT CentralDiff : public FiniteDiff {
284 public:
285  // Constructor
286  CentralDiff(const std::string& name, casadi_int n) : FiniteDiff(name, n) {}
287  explicit CentralDiff(DeserializingStream& s) : FiniteDiff(s) {}
288  static ProtoFunction* deserialize(DeserializingStream& s) { return new CentralDiff(s); }
289 
293  ~CentralDiff() override {}
294 
298  std::string class_name() const override {return "CentralDiff";}
299 
300  // Number of function evaluations needed
301  casadi_int n_pert() const override {return 2;};
302 
303  // Get perturbation expression
304  std::string pert(const std::string& k, const std::string& h) const override {
305  return "(2*" + k + "-1)*" + h;
306  }
307 
308  // Get perturbation expression
309  double pert(casadi_int k, double h) const override {
310  return (2*static_cast<double>(k)-1)*h;
311  }
312 
313  // Calculate finite difference approximation
314  double calc_fd(double** yk, double* y0, double* J, double h) const override;
315 
316  // Codegen finite difference approximation
317  std::string calc_fd() const override {return "casadi_central_diff_old";}
318 
319  // Is an error estimate available?
320  casadi_int has_err() const override {return true;}
321 
322  // Calculate step size from absolute tolerance
323  double calc_stepsize(double abstol) const override { return pow(abstol, 1./3);}
324 
328  double get_abstol() const override { return h_*h_;}
329 
331 
334  bool has_forward(casadi_int nfwd) const override { return true;}
335  Function get_forward(casadi_int nfwd, const std::string& name,
336  const std::vector<std::string>& inames,
337  const std::vector<std::string>& onames,
338  const Dict& opts) const override;
340 };
341 
346 class CASADI_EXPORT Smoothing : public FiniteDiff {
347 public:
348  // Constructor
349  Smoothing(const std::string& name, casadi_int n) : FiniteDiff(name, n) {}
350  explicit Smoothing(DeserializingStream& s) : FiniteDiff(s) {}
351  static ProtoFunction* deserialize(DeserializingStream& s) { return new Smoothing(s); }
352 
356  ~Smoothing() override {}
357 
361  std::string class_name() const override {return "Smoothing";}
362 
363  // Number of function evaluations needed
364  casadi_int n_pert() const override {return 4;};
365 
366  // Get perturbation expression
367  std::string pert(const std::string& k, const std::string& h) const override;
368 
369  // Get perturbation expression
370  double pert(casadi_int k, double h) const override;
371 
372  // Calculate finite difference approximation
373  double calc_fd(double** yk, double* y0, double* J, double h) const override;
374 
375  // Codegen finite difference approximation
376  std::string calc_fd() const override {return "casadi_smoothing_diff_old";}
377 
378  // Is an error estimate available?
379  casadi_int has_err() const override {return true;}
380 
381  // Calculate step size from absolute tolerance
382  double calc_stepsize(double abstol) const override { return pow(abstol, 1./3);}
383 
387  double get_abstol() const override { return h_*h_;}
388 
390 
393  bool has_forward(casadi_int nfwd) const override { return true;}
394  Function get_forward(casadi_int nfwd, const std::string& name,
395  const std::vector<std::string>& inames,
396  const std::vector<std::string>& onames,
397  const Dict& opts) const override;
399 };
400 
401 
402 } // namespace casadi
404 
405 #endif // CASADI_FINITE_DIFFERENCES_HPP
The casadi namespace.
Definition: archiver.hpp:32
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.