finite_differences.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 "finite_differences.hpp"
27 
28 namespace casadi {
29 
30 std::string to_string(FdMode v) {
31  switch (v) {
32  case FdMode::FORWARD: return "forward";
33  case FdMode::BACKWARD: return "backward";
34  case FdMode::CENTRAL: return "central";
35  case FdMode::SMOOTHING: return "smoothing";
36  default: break;
37  }
38  return "";
39 }
40 
41 casadi_int n_fd_points(FdMode v) {
42  switch (v) {
43  case FdMode::FORWARD:
44  case FdMode::BACKWARD: return 2;
45  case FdMode::CENTRAL: return 3;
46  case FdMode::SMOOTHING: return 5;
47  default: break;
48  }
49  return -1;
50 }
51 
52 casadi_int fd_offset(FdMode v) {
53  switch (v) {
54  case FdMode::FORWARD: return 0;
55  case FdMode::BACKWARD:
56  case FdMode::CENTRAL: return 1;
57  case FdMode::SMOOTHING: return 2;
58  default: break;
59  }
60  return -1;
61 }
62 
63 FiniteDiff::FiniteDiff(const std::string& name, casadi_int n)
64  : FunctionInternal(name), n_(n) {
65 }
66 
69  s.version("FiniteDiff", 1);
70  s.pack("FiniteDiff::n", n_);
71  s.pack("FiniteDiff::h_iter", h_iter_);
72  s.pack("FiniteDiff::h", h_);
73  s.pack("FiniteDiff::n_z", n_z_);
74  s.pack("FiniteDiff::n_y", n_y_);
75  s.pack("FiniteDiff::u_aim", u_aim_);
76  s.pack("FiniteDiff::h_min", h_min_);
77  s.pack("FiniteDiff::h_max", h_max_);
78  s.pack("FiniteDiff::reltol", m_.reltol);
79  s.pack("FiniteDiff::abstol", m_.abstol);
80  s.pack("FiniteDiff::smoothing", m_.smoothing);
81 }
82 
84  s.version("FiniteDiff", 1);
85  s.unpack("FiniteDiff::n", n_);
86  s.unpack("FiniteDiff::h_iter", h_iter_);
87  s.unpack("FiniteDiff::h", h_);
88  s.unpack("FiniteDiff::n_z", n_z_);
89  s.unpack("FiniteDiff::n_y", n_y_);
90  s.unpack("FiniteDiff::u_aim", u_aim_);
91  s.unpack("FiniteDiff::h_min", h_min_);
92  s.unpack("FiniteDiff::h_max", h_max_);
93  s.unpack("FiniteDiff::reltol", m_.reltol);
94  s.unpack("FiniteDiff::abstol", m_.abstol);
95  s.unpack("FiniteDiff::smoothing", m_.smoothing);
96 }
97 
99  clear_mem();
100 }
101 
104  {{"second_order_stepsize",
105  {OT_DOUBLE,
106  "Second order perturbation size [default: 1e-3]"}},
107  {"h",
108  {OT_DOUBLE,
109  "Step size [default: computed from abstol]"}},
110  {"h_max",
111  {OT_DOUBLE,
112  "Maximum step size [default 0]"}},
113  {"h_min",
114  {OT_DOUBLE,
115  "Minimum step size [default inf]"}},
116  {"smoothing",
117  {OT_DOUBLE,
118  "Smoothing regularization [default: machine precision]"}},
119  {"reltol",
120  {OT_DOUBLE,
121  "Accuracy of function inputs [default: query object]"}},
122  {"abstol",
123  {OT_DOUBLE,
124  "Accuracy of function outputs [default: query object]"}},
125  {"u_aim",
126  {OT_DOUBLE,
127  "Target ratio of roundoff error to truncation error [default: 100.]"}},
128  {"h_iter",
129  {OT_INT,
130  "Number of iterations to improve on the step-size "
131  "[default: 1 if error estimate available, otherwise 0]"}},
132  }
133 };
134 
135 void FiniteDiff::init(const Dict& opts) {
136  // Call the initialization method of the base class
138 
139  // Default options
140  h_min_ = 0;
141  h_max_ = inf;
142  m_.smoothing = eps;
146  u_aim_ = 100;
147  h_iter_ = has_err() ? 1 : 0;
148 
149  // Read options
150  for (auto&& op : opts) {
151  if (op.first=="h") {
152  h_ = op.second;
153  } else if (op.first=="h_min") {
154  h_min_ = op.second;
155  } else if (op.first=="h_max") {
156  h_max_ = op.second;
157  } else if (op.first=="reltol") {
158  m_.reltol = op.second;
159  } else if (op.first=="abstol") {
160  m_.abstol = op.second;
161  } else if (op.first=="smoothing") {
162  m_.smoothing = op.second;
163  } else if (op.first=="u_aim") {
164  u_aim_ = op.second;
165  } else if (op.first=="h_iter") {
166  h_iter_ = op.second;
167  }
168  }
169 
170  // Check h_iter for consistency
171  if (h_iter_!=0 && !has_err()) {
172  casadi_error("Perturbation size refinement requires an error estimate, "
173  "which is not available for the class '" + class_name() + "'. "
174  "Choose a different differencing scheme.");
175  }
176 
177  // Allocate work vector for (perturbed) inputs and outputs
180  alloc_res(n_pert(), true); // yk
181  alloc_w((n_pert() + 3) * n_y_, true); // yk[:], y0, y, J
182  alloc_w(n_z_, true); // z
183 
184  // Dimensions
185  if (verbose_) {
186  casadi_message("Finite differences (" + class_name() + ") with "
187  + str(n_z_) + " inputs, " + str(n_y_)
188  + " outputs and " + str(n_) + " directional derivatives.");
189  }
190 
191  // Allocate sufficient temporary memory for function evaluation
193 }
194 
196  casadi_int n_in = derivative_of_.n_in(), n_out = derivative_of_.n_out();
197  if (i<n_in) {
198  // Non-differentiated input
199  return derivative_of_.sparsity_in(i);
200  } else if (i<n_in+n_out) {
201  // Non-differentiated output
202  return derivative_of_.sparsity_out(i-n_in);
203  } else {
204  // Seeds
205  casadi_int ii = i - n_in - n_out;
206  if (is_diff_in_[i]) {
207  return repmat(derivative_of_.sparsity_in(ii), 1, n_);
208  } else {
209  return Sparsity(derivative_of_.size1_in(ii),
211  }
212  }
213 }
214 
216  return repmat(derivative_of_.sparsity_out(i), 1, n_);
217 }
218 
219 double FiniteDiff::get_default_in(casadi_int ind) const {
220  if (ind<derivative_of_.n_in()) {
221  return derivative_of_.default_in(ind);
222  } else {
223  return 0;
224  }
225 }
226 
229 }
230 
232  return derivative_of_.n_out();
233 }
234 
235 std::string FiniteDiff::get_name_in(casadi_int i) {
236  casadi_int n_in = derivative_of_.n_in(), n_out = derivative_of_.n_out();
237  if (i<n_in) {
238  return derivative_of_.name_in(i);
239  } else if (i<n_in+n_out) {
240  return "out_" + derivative_of_.name_out(i-n_in);
241  } else {
242  return "fwd_" + derivative_of_.name_in(i-n_in-n_out);
243  }
244 }
245 
246 std::string FiniteDiff::get_name_out(casadi_int i) {
247  return "fwd_" + derivative_of_.name_out(i);
248 }
249 
250 Function CentralDiff::get_forward(casadi_int nfwd, const std::string& name,
251  const std::vector<std::string>& inames,
252  const std::vector<std::string>& onames,
253  const Dict& opts) const {
254  // Commented out, does not work well
255 #if 0
256  // The second order derivative is calculated as the backwards derivative
257  // of the forward derivative, which is equivalent to central differences
258  // of second order
259  std::string f_name = "fd_" + name;
260  Dict f_opts = {{"derivative_of", derivative_of_}};
261  Function f = Function::create(new ForwardDiff(f_name, n_, h_), f_opts);
262  // Calculate backwards derivative of f
263  f_opts["derivative_of"] = f;
264  return Function::create(new ForwardDiff(name, nfwd, -h_), f_opts);
265 #endif
266  return Function::create(new CentralDiff(name, nfwd), opts);
267 }
268 
269 int FiniteDiff::eval(const double** arg, double** res,
270  casadi_int* iw, double* w, void* mem) const {
271  setup(mem, arg, res, iw, w);
272  // Shorthands
273  casadi_int n_in = derivative_of_.n_in(), n_out = derivative_of_.n_out();
274  casadi_int n_pert = this->n_pert();
275 
276  // Non-differentiated input
277  const double** x0 = arg;
278  arg += n_in;
279 
280  // Non-differentiated output
281  double* y0 = w;
282  for (casadi_int j=0; j<n_out; ++j) {
283  const casadi_int nnz = derivative_of_.nnz_out(j);
284  casadi_copy(*arg++, nnz, w);
285  w += nnz;
286  }
287 
288  // Forward seeds
289  const double** seed = arg;
290  arg += n_in;
291 
292  // Forward sensitivities
293  double** sens = res;
294  res += n_out;
295 
296  // Finite difference approximation
297  double* J = w;
298  w += n_y_;
299 
300  // Perturbed function values
301  double** yk = res;
302  res += n_pert;
303  for (casadi_int j=0; j<n_pert; ++j) {
304  yk[j] = w, w += n_y_;
305  }
306 
307  // Setup arg and z for evaluation
308  double *z = w;
309  for (casadi_int j=0; j<n_in; ++j) {
310  arg[j] = w;
311  w += derivative_of_.nnz_in(j);
312  }
313 
314  // Setup res and y for evaluation
315  double *y = w;
316  for (casadi_int j=0; j<n_out; ++j) {
317  res[j] = w;
318  w += derivative_of_.nnz_out(j);
319  }
320 
321  // For all sensitivity directions
322  for (casadi_int i=0; i<n_; ++i) {
323  // Initial stepsize
324  double h = h_;
325  // Perform finite difference algorithm with different step sizes
326  for (casadi_int iter=0; iter<1+h_iter_; ++iter) {
327  // Calculate perturbed function values
328  for (casadi_int k=0; k<n_pert; ++k) {
329  // Perturb inputs
330  casadi_int off = 0;
331  for (casadi_int j=0; j<n_in; ++j) {
332  casadi_int nnz = derivative_of_.nnz_in(j);
333  casadi_copy(x0[j], nnz, z + off);
334  if (seed[j] && is_diff_in_[j]) casadi_axpy(nnz, pert(k, h), seed[j] + i*nnz, z + off);
335  off += nnz;
336  }
337  // Evaluate
338  if (derivative_of_(arg, res, iw, w)) return 1;
339  // Save outputs
340  casadi_copy(y, n_y_, yk[k]);
341  }
342  // Finite difference calculation with error estimate
343  double u = calc_fd(yk, y0, J, h);
344  if (iter==h_iter_) break;
345 
346  // Update step size
347  if (u < 0) {
348  // Perturbation failed, try a smaller step size
349  h /= u_aim_;
350  } else {
351  // Update h to get u near the target ratio
352  h *= sqrt(u_aim_ / fmax(1., u));
353  }
354  // Make sure h stays in the range [h_min_,h_max_]
355  h = fmin(fmax(h, h_min_), h_max_);
356  }
357 
358  // Gather sensitivities
359  casadi_int off = 0;
360  for (casadi_int j=0; j<n_out; ++j) {
361  casadi_int nnz = derivative_of_.nnz_out(j);
362  if (sens[j]) casadi_copy(J + off, nnz, sens[j] + i*nnz);
363  off += nnz;
364  }
365  }
366  return 0;
367 }
368 
369 double ForwardDiff::calc_fd(double** yk, double* y0, double* J, double h) const {
370  return casadi_forward_diff_old(yk, y0, J, h, n_y_, &m_);
371 }
372 
373 double CentralDiff::calc_fd(double** yk, double* y0, double* J, double h) const {
374  return casadi_central_diff_old(yk, y0, J, h, n_y_, &m_);
375 }
376 
380 }
381 
383  // Shorthands
384  casadi_int n_in = derivative_of_.n_in(), n_out = derivative_of_.n_out();
385  casadi_int n_pert = this->n_pert();
386 
387  g.comment("Non-differentiated input");
388  g.local("x0", "const casadi_real", "**");
389  g << "x0 = arg, arg += " << n_in << ";\n";
390 
391  g.comment("Non-differentiated output");
392  g.local("y0", "casadi_real", "*");
393  g << "y0 = w;\n";
394  for (casadi_int j=0; j<n_out; ++j) {
395  const casadi_int nnz = derivative_of_.nnz_out(j);
396  g << g.copy("*arg++", nnz, "w") << " w += " << nnz << ";\n";
397  }
398 
399  g.comment("Forward seeds");
400  g.local("seed", "const casadi_real", "**");
401  g << "seed = arg, arg += " << n_in << ";\n";
402 
403  g.comment("Forward sensitivities");
404  g.local("sens", "casadi_real", "**");
405  g << "sens = res, res += " << n_out << ";\n";
406 
407  g.comment("Finite difference approximation");
408  g.local("J", "casadi_real", "*");
409  g << "J = w, w += " << n_y_ << ";\n";
410 
411  g.comment("Perturbed function value");
412  g.local("yk", "casadi_real", "**");
413  g << "yk = res, res += " << n_pert << ";\n";
414  g.local("j", "casadi_int");
415  g << "for (j=0; j<" << n_pert << "; ++j) yk[j] = w, w += " << n_y_ << ";\n";
416 
417  g.comment("Setup arg and z for evaluation");
418  g.local("z", "casadi_real", "*");
419  g << "z = w;\n";
420  for (casadi_int j=0; j<n_in; ++j) {
421  g << g.arg(j) << " = w, w += " << derivative_of_.nnz_in(j) << ";\n";
422  }
423 
424  g.comment("Setup res and y for evaluation");
425  g.local("y", "casadi_real", "*");
426  g << "y = w;\n";
427  for (casadi_int j=0; j<n_out; ++j) {
428  g << g.res(j) << " = w, w += " << derivative_of_.nnz_out(j) << ";\n";
429  }
430 
431  g.comment("For all sensitivity directions");
432  g.local("i", "casadi_int");
433  g << "for (i=0; i<" << n_ << "; ++i) {\n";
434 
435  g.comment("Initial stepsize");
436  g.local("h", "casadi_real");
437  g << "h = " << g.constant(h_) << ";\n";
438 
439  g.comment("Perform finite difference algorithm with different step sizes");
440  g.local("iter", "casadi_int");
441  g << "for (iter=0; iter<" << 1+h_iter_ << "; ++iter) {\n";
442 
443  g.comment("Calculate perturbed function values");
444  g.local("k", "casadi_int");
445  g << "for (k=0; k<" << n_pert << "; ++k) {\n";
446 
447  g.comment("Perturb inputs");
448  casadi_int off=0;
449  for (casadi_int j=0; j<n_in; ++j) {
450  casadi_int nnz = derivative_of_.nnz_in(j);
451  std::string s = "seed[" + str(j) + "]";
452  g << g.copy("x0[" + str(j) + "]", nnz, "z+" + str(off)) << "\n";
453  if (is_diff_in_[j]) {
454  g << "if ("+s+") " << g.axpy(nnz, pert("k", "h"),
455  s+"+i*"+str(nnz), "z+" + str(off)) << "\n";
456  }
457  off += nnz;
458  }
459 
460  g.comment("Evaluate");
461  g << "if (" << g(derivative_of_, "arg", "res", "iw", "w") << ") return 1;\n";
462 
463  g.comment("Save outputs");
464  g << g.copy("y", n_y_, "yk[k]") << "\n";
465 
466  g << "}\n"; // for (k=0, ...)
467 
468  g.comment("Finite difference calculation with error estimate");
469  g.local("u", "casadi_real");
470  g.local("m", "const struct casadi_finite_diff_mem");
471  g.init_local("m", "{" + g.constant(m_.reltol) + ", "
472  + g.constant(m_.abstol) + ", "
473  + g.constant(m_.smoothing) + "}");
474  g << "u = " << calc_fd() << "(yk, y0, J, h, " << n_y_ << ", &m);\n";
475  g << "if (iter==" << h_iter_ << ") break;\n";
476 
477  g.comment("Update step size");
478  g << "if (u < 0) {\n";
479  // Perturbation failed, try a smaller step size
480  g << "h /= " << u_aim_ << ";\n";
481  g << "} else {\n";
482  // Update h to get u near the target ratio
483  g << "h *= sqrt(" << u_aim_ << " / fmax(1., u));\n";
484  g << "}\n";
485  // Make sure h stays in the range [h_min_,h_max_]
486  if (h_min_>0 || isfinite(h_max_)) {
487  std::string h = "h";
488  if (h_min_>0) h = "fmax(" + h + ", " + g.constant(h_min_) + ")";
489  if (isfinite(h_max_)) h = "fmin(" + h + ", " + g.constant(h_max_) + ")";
490  g << "h = " << h << ";\n";
491  }
492 
493  g << "}\n"; // for (iter=0, ...)
494 
495  g.comment("Gather sensitivities");
496  off = 0;
497  for (casadi_int j=0; j<n_out; ++j) {
498  casadi_int nnz = derivative_of_.nnz_out(j);
499  std::string s = "sens[" + str(j) + "]";
500  g << "if (" << s << ") " << g.copy("J+" + str(off), nnz, s + "+i*" + str(nnz)) << "\n";
501  off += nnz;
502  }
503  g << "}\n"; // for (i=0, ...)
504 }
505 
506 std::string Smoothing::pert(const std::string& k, const std::string& h) const {
507  std::string sign = "(2*(" + k + "/2)-1)";
508  std::string len = "(" + k + "%2+1)";
509  return len + "*" + sign + "*" + h;
510 }
511 
512 double Smoothing::pert(casadi_int k, double h) const {
513  casadi_int sign = 2*(k/2)-1;
514  casadi_int len = k%2+1;
515  return static_cast<double>(len*sign)*h;
516 }
517 
518 double Smoothing::calc_fd(double** yk, double* y0, double* J, double h) const {
519  return casadi_smoothing_diff_old(yk, y0, J, h, n_y_, &m_);
520 }
521 
522 Function ForwardDiff::get_forward(casadi_int nfwd, const std::string& name,
523  const std::vector<std::string>& inames,
524  const std::vector<std::string>& onames,
525  const Dict& opts) const {
526  return Function::create(new ForwardDiff(name, nfwd), opts);
527 }
528 
529 Function Smoothing::get_forward(casadi_int nfwd, const std::string& name,
530  const std::vector<std::string>& inames,
531  const std::vector<std::string>& onames,
532  const Dict& opts) const {
533  return Function::create(new Smoothing(name, nfwd), opts);
534 }
535 
536 } // namespace casadi
CentralDiff(const std::string &name, casadi_int n)
std::string calc_fd() const override
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Second order derivatives.
Helper class for C code generation.
std::string axpy(casadi_int n, const std::string &a, const std::string &x, const std::string &y)
Codegen axpy: y += a*x.
std::string add_dependency(const Function &f)
Add a function dependency.
std::string arg(casadi_int i) const
Refer to argument.
std::string copy(const std::string &arg, std::size_t n, const std::string &res)
Create a copy operation.
void comment(const std::string &s)
Write a comment line (ignored if not verbose)
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
std::string res(casadi_int i) const
Refer to resuly.
void init_local(const std::string &name, const std::string &def)
Specify the default value for a local variable.
void add_auxiliary(Auxiliary f, const std::vector< std::string > &inst={"casadi_real"})
Add a built-in auxiliary function.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
size_t get_n_in() override
Number of function inputs and outputs.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
virtual casadi_int n_pert() const =0
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
virtual double calc_stepsize(double abstol) const =0
void init(const Dict &opts) override
Initialize.
void codegen_body(CodeGenerator &g) const override
Generate code for the body of the C function.
Sparsity get_sparsity_in(casadi_int i) override
Sparsities of function inputs and outputs.
virtual std::string pert(const std::string &k, const std::string &h) const =0
std::string get_name_in(casadi_int i) override
Names of function input and outputs.
double get_default_in(casadi_int ind) const override
Get default input value.
~FiniteDiff() override
Destructor.
virtual casadi_int has_err() const =0
std::string get_name_out(casadi_int i) override
Names of function input and outputs.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
virtual std::string calc_fd() const =0
static const Options options_
Options.
size_t get_n_out() override
Number of function inputs and outputs.
Sparsity get_sparsity_out(casadi_int i) override
Sparsities of function inputs and outputs.
casadi_finite_diff_mem< double > m_
FiniteDiff(const std::string &name, casadi_int n)
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Second order derivatives.
std::string calc_fd() const override
ForwardDiff(const std::string &name, casadi_int n)
Internal class for Function.
void init(const Dict &opts) override
Initialize.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
static const Options options_
Options.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
virtual double get_abstol() const
Get absolute tolerance.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
virtual double get_reltol() const
Get relative tolerance.
std::vector< bool > is_diff_in_
Are inputs and outputs differentiable?
Function derivative_of_
If the function is the derivative of another function.
Function object.
Definition: function.hpp:60
casadi_int nnz_out() const
Get number of output nonzeros.
Definition: function.cpp:1007
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
Definition: function.cpp:1183
casadi_int size1_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:979
const std::vector< std::string > & name_in() const
Get input scheme.
Definition: function.cpp:1113
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:488
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
Definition: function.cpp:1167
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:975
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:971
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:1003
casadi_int size2_in(casadi_int ind) const
Get input dimension.
Definition: function.cpp:983
const std::vector< std::string > & name_out() const
Get output scheme.
Definition: function.cpp:1117
double default_in(casadi_int ind) const
Get default input value.
Definition: function.cpp:1677
bool verbose_
Verbose printout.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
virtual std::string class_name() const =0
Readable name of the internal class.
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Second order derivatives.
std::string calc_fd() const override
std::string pert(const std::string &k, const std::string &h) const override
Smoothing(const std::string &name, casadi_int n)
General sparsity class.
Definition: sparsity.hpp:106
The casadi namespace.
Definition: archiver.cpp:28
FdMode
Variable type.
const double eps
Machine epsilon.
Definition: calculus.hpp:56
casadi_int n_fd_points(FdMode v)
Length of FD stencil, including unperturbed input.
casadi_int fd_offset(FdMode v)
Offset for FD stencil, i.e. index of unperturbed input.
double sign(double x)
Sign function, note that sign(nan) == nan.
Definition: calculus.hpp:270
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
const double inf
infinity
Definition: calculus.hpp:50
std::string to_string(TypeFmi2 v)
void casadi_axpy(casadi_int n, T1 alpha, const T1 *x, T1 *y)
AXPY: y <- a*x + y.
Options metadata for a class.
Definition: options.hpp:40