map.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 "map.hpp"
27 #include "serializing_stream.hpp"
28 
29 #ifdef CASADI_WITH_THREAD
30 #ifdef CASADI_WITH_THREAD_MINGW
31 #include <mingw.thread.h>
32 #else // CASADI_WITH_THREAD_MINGW
33 #include <thread>
34 #endif // CASADI_WITH_THREAD_MINGW
35 #endif // CASADI_WITH_THREAD
36 
37 namespace casadi {
38 
39  Function Map::create(const std::string& parallelization, const Function& f, casadi_int n) {
40  // Create instance of the right class
41  std::string suffix = str(n) + "_" + f.name();
42  if (parallelization == "serial") {
43  return Function::create(new Map("map" + suffix, f, n), Dict());
44  } else if (parallelization== "openmp") {
45  return Function::create(new OmpMap("ompmap" + suffix, f, n), Dict());
46  } else if (parallelization== "thread") {
47  return Function::create(new ThreadMap("threadmap" + suffix, f, n), Dict());
48  } else {
49  casadi_error("Unknown parallelization: " + parallelization);
50  }
51  }
52 
53  Map::Map(const std::string& name, const Function& f, casadi_int n)
54  : FunctionInternal(name), f_(f), n_(n) {
55  }
56 
57  bool Map::is_a(const std::string& type, bool recursive) const {
58  return type=="Map"
59  || (recursive && FunctionInternal::is_a(type, recursive));
60  }
61 
62  bool OmpMap::is_a(const std::string& type, bool recursive) const {
63  return type=="OmpMap"
64  || (recursive && Map::is_a(type, recursive));
65  }
66 
67  bool ThreadMap::is_a(const std::string& type, bool recursive) const {
68  return type=="ThreadMap"
69  || (recursive && Map::is_a(type, recursive));
70  }
71 
72  std::vector<std::string> Map::get_function() const {
73  return {"f"};
74  }
75 
76  const Function& Map::get_function(const std::string &name) const {
77  casadi_assert(has_function(name),
78  "No function \"" + name + "\" in " + name_ + ". " +
79  "Available functions: " + join(get_function()) + ".");
80  return f_;
81  }
82 
83  bool Map::has_function(const std::string& fname) const {
84  return fname=="f";
85  }
86 
89  s.pack("Map::f", f_);
90  s.pack("Map::n", n_);
91  }
92 
95  s.pack("Map::class_name", class_name());
96  }
97 
99  s.unpack("Map::f", f_);
100  s.unpack("Map::n", n_);
101  }
102 
104  std::string class_name;
105  s.unpack("Map::class_name", class_name);
106  if (class_name=="Map") {
107  return new Map(s);
108  } else if (class_name=="OmpMap") {
109  return new OmpMap(s);
110  } else if (class_name=="ThreadMap") {
111  return new ThreadMap(s);
112  } else {
113  casadi_error("class name '" + class_name + "' unknown.");
114  }
115  }
116 
118  clear_mem();
119  }
120 
121  void Map::init(const Dict& opts) {
124  // Call the initialization method of the base class
126 
127  // Allocate sufficient memory for serial evaluation
128  alloc_arg(f_.sz_arg());
129  alloc_res(f_.sz_res());
130  alloc_w(f_.sz_w());
131  alloc_iw(f_.sz_iw());
132  }
133 
134  template<typename T>
135  int Map::eval_gen(const T** arg, T** res, casadi_int* iw, T* w, int mem) const {
136  const T** arg1 = arg+n_in_;
137  std::copy_n(arg, n_in_, arg1);
138  T** res1 = res+n_out_;
139  std::copy_n(res, n_out_, res1);
140  for (casadi_int i=0; i<n_; ++i) {
141  if (f_(arg1, res1, iw, w, mem)) return 1;
142  for (casadi_int j=0; j<n_in_; ++j) {
143  if (arg1[j]) arg1[j] += f_.nnz_in(j);
144  }
145  for (casadi_int j=0; j<n_out_; ++j) {
146  if (res1[j]) res1[j] += f_.nnz_out(j);
147  }
148  }
149  return 0;
150  }
151 
152  int Map::eval_sx(const SXElem** arg, SXElem** res, casadi_int* iw, SXElem* w, void* mem,
153  bool always_inline, bool never_inline) const {
154  return eval_gen(arg, res, iw, w);
155  }
156 
157  int Map::sp_forward(const bvec_t** arg, bvec_t** res,
158  casadi_int* iw, bvec_t* w, void* mem) const {
159  return eval_gen(arg, res, iw, w);
160  }
161 
162  int Map::sp_reverse(bvec_t** arg, bvec_t** res, casadi_int* iw, bvec_t* w, void* mem) const {
163  bvec_t** arg1 = arg+n_in_;
164  std::copy_n(arg, n_in_, arg1);
165  bvec_t** res1 = res+n_out_;
166  std::copy_n(res, n_out_, res1);
167  for (casadi_int i=0; i<n_; ++i) {
168  if (f_.rev(arg1, res1, iw, w)) return 1;
169  for (casadi_int j=0; j<n_in_; ++j) {
170  if (arg1[j]) arg1[j] += f_.nnz_in(j);
171  }
172  for (casadi_int j=0; j<n_out_; ++j) {
173  if (res1[j]) res1[j] += f_.nnz_out(j);
174  }
175  }
176  return 0;
177  }
178 
180  g.add_dependency(f_);
181  }
182 
184  g.local("i", "casadi_int");
185  g.local("arg1", "const casadi_real*", "*");
186  g.local("res1", "casadi_real*", "*");
187 
188  // Input buffer
189  g << "arg1 = arg+" << n_in_ << ";\n"
190  << "for (i=0; i<" << n_in_ << "; ++i) arg1[i]=arg[i];\n";
191  // Output buffer
192  g << "res1 = res+" << n_out_ << ";\n"
193  << "for (i=0; i<" << n_out_ << "; ++i) res1[i]=res[i];\n"
194  << "for (i=0; i<" << n_ << "; ++i) {\n";
195  // Evaluate
196  g << "if (" << g(f_, "arg1", "res1", "iw", "w") << ") return 1;\n";
197  // Update input buffers
198  for (casadi_int j=0; j<n_in_; ++j) {
199  if (f_.nnz_in(j))
200  g << "if (arg1[" << j << "]) arg1[" << j << "]+=" << f_.nnz_in(j) << ";\n";
201  }
202  // Update output buffers
203  for (casadi_int j=0; j<n_out_; ++j) {
204  if (f_.nnz_out(j))
205  g << "if (res1[" << j << "]) res1[" << j << "]+=" << f_.nnz_out(j) << ";\n";
206  }
207  g << "}\n";
208  }
209 
211  ::get_forward(casadi_int nfwd, const std::string& name,
212  const std::vector<std::string>& inames,
213  const std::vector<std::string>& onames,
214  const Dict& opts) const {
215  // Generate map of derivative
216  Function df = f_.forward(nfwd);
217  Function dm = df.map(n_, parallelization());
218 
219  // Input expressions
220  std::vector<MX> arg = dm.mx_in();
221 
222  // Need to reorder sensitivity inputs
223  std::vector<MX> res = arg;
224  std::vector<MX>::iterator it=res.begin()+n_in_+n_out_;
225  std::vector<casadi_int> ind;
226  for (casadi_int i=0; i<n_in_; ++i, ++it) {
227  casadi_int sz = f_.size2_in(i);
228  ind.clear();
229  for (casadi_int k=0; k<n_; ++k) {
230  for (casadi_int d=0; d<nfwd; ++d) {
231  for (casadi_int j=0; j<sz; ++j) {
232  ind.push_back((d*n_ + k)*sz + j);
233  }
234  }
235  }
236  *it = (*it)(Slice(), ind); // NOLINT
237  }
238 
239  // Get output expressions
240  res = dm(res);
241 
242  // Reorder sensitivity outputs
243  it = res.begin();
244  for (casadi_int i=0; i<n_out_; ++i, ++it) {
245  casadi_int sz = f_.size2_out(i);
246  ind.clear();
247  for (casadi_int d=0; d<nfwd; ++d) {
248  for (casadi_int k=0; k<n_; ++k) {
249  for (casadi_int j=0; j<sz; ++j) {
250  ind.push_back((k*nfwd + d)*sz + j);
251  }
252  }
253  }
254  *it = (*it)(Slice(), ind); // NOLINT
255  }
256 
257  Dict options = opts;
258  options["allow_duplicate_io_names"] = true;
259 
260  // Construct return function
261  return Function(name, arg, res, inames, onames, options);
262  }
263 
265  ::get_reverse(casadi_int nadj, const std::string& name,
266  const std::vector<std::string>& inames,
267  const std::vector<std::string>& onames,
268  const Dict& opts) const {
269  // Generate map of derivative
270  Function df = f_.reverse(nadj);
271  Function dm = df.map(n_, parallelization());
272 
273  // Input expressions
274  std::vector<MX> arg = dm.mx_in();
275 
276  // Need to reorder sensitivity inputs
277  std::vector<MX> res = arg;
278  std::vector<MX>::iterator it=res.begin()+n_in_+n_out_;
279  std::vector<casadi_int> ind;
280  for (casadi_int i=0; i<n_out_; ++i, ++it) {
281  casadi_int sz = f_.size2_out(i);
282  ind.clear();
283  for (casadi_int k=0; k<n_; ++k) {
284  for (casadi_int d=0; d<nadj; ++d) {
285  for (casadi_int j=0; j<sz; ++j) {
286  ind.push_back((d*n_ + k)*sz + j);
287  }
288  }
289  }
290  *it = (*it)(Slice(), ind); // NOLINT
291  }
292 
293  // Get output expressions
294  res = dm(res);
295 
296  // Reorder sensitivity outputs
297  it = res.begin();
298  for (casadi_int i=0; i<n_in_; ++i, ++it) {
299  casadi_int sz = f_.size2_in(i);
300  ind.clear();
301  for (casadi_int d=0; d<nadj; ++d) {
302  for (casadi_int k=0; k<n_; ++k) {
303  for (casadi_int j=0; j<sz; ++j) {
304  ind.push_back((k*nadj + d)*sz + j);
305  }
306  }
307  }
308  *it = (*it)(Slice(), ind); // NOLINT
309  }
310 
311  Dict options = opts;
312  options["allow_duplicate_io_names"] = true;
313 
314  // Construct return function
315  return Function(name, arg, res, inames, onames, options);
316  }
317 
318  int Map::eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const {
319  // This checkout/release dance is an optimization.
320  // Could also use the thread-safe variant f_(arg1, res1, iw, w)
321  // in Map::eval_gen
322  setup(mem, arg, res, iw, w);
324  return eval_gen(arg, res, iw, w, m);
325  }
326 
328  clear_mem();
329  }
330 
331  int OmpMap::eval(const double** arg, double** res, casadi_int* iw, double* w, void* mem) const {
332 #ifndef WITH_OPENMP
333  return Map::eval(arg, res, iw, w, mem);
334 #else // WITH_OPENMP
335  setup(mem, arg, res, iw, w);
336  size_t sz_arg, sz_res, sz_iw, sz_w;
338 
339  // Error flag
340  casadi_int flag = 0;
341 
342  // Checkout memory objects
343  std::vector< scoped_checkout<Function> > ind; ind.reserve(n_);
344  for (casadi_int i=0; i<n_; ++i) ind.emplace_back(f_);
345 
346  // Evaluate in parallel
347 #pragma omp parallel for reduction(||:flag)
348  for (casadi_int i=0; i<n_; ++i) {
349  // Input buffers
350  const double** arg1 = arg + n_in_ + i*sz_arg;
351  for (casadi_int j=0; j<n_in_; ++j) {
352  arg1[j] = arg[j] ? arg[j] + i*f_.nnz_in(j) : 0;
353  }
354 
355  // Output buffers
356  double** res1 = res + n_out_ + i*sz_res;
357  for (casadi_int j=0; j<n_out_; ++j) {
358  res1[j] = res[j] ? res[j] + i*f_.nnz_out(j) : 0;
359  }
360 
361  // Evaluation
362  try {
363  flag = f_(arg1, res1, iw + i*sz_iw, w + i*sz_w, ind[i]) || flag;
364  } catch (std::exception& e) {
365  flag = 1;
366  casadi_warning("Exception raised: " + std::string(e.what()));
367  } catch (...) {
368  flag = 1;
369  casadi_warning("Uncaught exception.");
370  }
371 
372  }
373 
374  // Return error flag
375  return flag;
376 #endif // WITH_OPENMP
377  }
378 
380  size_t sz_arg, sz_res, sz_iw, sz_w;
382  g << "casadi_int i;\n"
383  << "const double** arg1;\n"
384  << "double** res1;\n"
385  << "casadi_int flag = 0;\n"
386  << "#pragma omp parallel for private(i,arg1,res1) reduction(||:flag)\n"
387  << "for (i=0; i<" << n_ << "; ++i) {\n"
388  << "arg1 = arg + " << n_in_ << "+i*" << sz_arg << ";\n";
389  for (casadi_int j=0; j<n_in_; ++j) {
390  g << "arg1[" << j << "] = arg[" << j << "] ? "
391  << g.arg(j) << "+i*" << f_.nnz_in(j) << ": 0;\n";
392  }
393  g << "res1 = res + " << n_out_ << "+i*" << sz_res << ";\n";
394  for (casadi_int j=0; j<n_out_; ++j) {
395  g << "res1[" << j << "] = res[" << j << "] ?"
396  << g.res(j) << "+i*" << f_.nnz_out(j) << ": 0;\n";
397  }
398  g << "flag = "
399  << g(f_, "arg1", "res1", "iw+i*" + str(sz_iw), "w+i*" + str(sz_w)) << " || flag;\n"
400  << "}\n"
401  << "if (flag) return 1;\n";
402  }
403 
404  void OmpMap::init(const Dict& opts) {
405 #ifndef WITH_OPENMP
406  casadi_warning("CasADi was not compiled with WITH_OPENMP=ON. "
407  "Falling back to serial evaluation.");
408 #endif // WITH_OPENMP
409  // Call the initialization method of the base class
410  Map::init(opts);
411 
412  // Allocate memory for holding memory object references
413  alloc_iw(n_, true);
414 
415  // Allocate sufficient memory for parallel evaluation
416  alloc_arg(f_.sz_arg() * n_);
417  alloc_res(f_.sz_res() * n_);
418  alloc_w(f_.sz_w() * n_);
419  alloc_iw(f_.sz_iw() * n_);
420  }
421 
422 
424  clear_mem();
425  }
426 
427  void ThreadsWork(const Function& f, casadi_int i,
428  const double** arg, double** res,
429  casadi_int* iw, double* w,
430  casadi_int ind, int& ret) {
431 
432  // Function dimensions
433  casadi_int n_in = f.n_in();
434  casadi_int n_out = f.n_out();
435 
436  // Function work sizes
437  size_t sz_arg, sz_res, sz_iw, sz_w;
438  f.sz_work(sz_arg, sz_res, sz_iw, sz_w);
439 
440  // Input buffers
441  const double** arg1 = arg + n_in + i*sz_arg;
442  for (casadi_int j=0; j<n_in; ++j) {
443  arg1[j] = arg[j] ? arg[j] + i*f.nnz_in(j) : nullptr;
444  }
445 
446  // Output buffers
447  double** res1 = res + n_out + i*sz_res;
448  for (casadi_int j=0; j<n_out; ++j) {
449  res1[j] = res[j] ? res[j] + i*f.nnz_out(j) : nullptr;
450  }
451 
452  try {
453  ret = f(arg1, res1, iw + i*sz_iw, w + i*sz_w, ind);
454  } catch (std::exception& e) {
455  ret = 1;
456  casadi_warning("Exception raised: " + std::string(e.what()));
457  } catch (...) {
458  ret = 1;
459  casadi_warning("Uncaught exception.");
460  }
461  }
462 
463  int ThreadMap::eval(const double** arg, double** res, casadi_int* iw, double* w,
464  void* mem) const {
465 #ifndef CASADI_WITH_THREAD
466  return Map::eval(arg, res, iw, w, mem);
467 #else // CASADI_WITH_THREAD
468  setup(mem, arg, res, iw, w);
469  // Checkout memory objects
470  std::vector< scoped_checkout<Function> > ind; ind.reserve(n_);
471  for (casadi_int i=0; i<n_; ++i) ind.emplace_back(f_);
472 
473  // Allocate space for return values
474  std::vector<int> ret_values(n_);
475 
476  // Spawn threads
477  std::vector<std::thread> threads;
478  for (casadi_int i=0; i<n_; ++i) {
479  // Why the lambda function?
480  // Because it was the first iteration to pass tests on MingGW
481  // using mingw-std-threads.
482  threads.emplace_back(
483  [i](const Function& f, const double** arg, double** res,
484  casadi_int* iw, double* w, casadi_int ind, int& ret) {
485  ThreadsWork(f, i, arg, res, iw, w, ind, ret);
486  },
487  std::ref(f_), arg, res, iw, w, casadi_int(ind[i]), std::ref(ret_values[i]));
488  }
489 
490  // Join threads
491  for (auto && th : threads) th.join();
492 
493  // Anticipate success
494  int ret = 0;
495 
496  // Compute aggregate return value
497  for (int e : ret_values) ret = ret || e;
498 
499  return ret;
500 #endif // CASADI_WITH_THREAD
501  }
502 
505  }
506 
507  void ThreadMap::init(const Dict& opts) {
508 #ifndef CASADI_WITH_THREAD
509  casadi_warning("CasADi was not compiled with WITH_THREAD=ON. "
510  "Falling back to serial evaluation.");
511 #endif // CASADI_WITH_THREAD
512  // Call the initialization method of the base class
513  Map::init(opts);
514 
515  // Allocate memory for holding memory object references
516  alloc_iw(n_, true);
517 
518  // Allocate sufficient memory for parallel evaluation
519  alloc_arg(f_.sz_arg() * n_);
520  alloc_res(f_.sz_res() * n_);
521  alloc_w(f_.sz_w() * n_);
522  alloc_iw(f_.sz_iw() * n_);
523  }
524 
525 } // namespace casadi
Helper class for C code generation.
std::string add_dependency(const Function &f)
Add a function dependency.
std::string arg(casadi_int i) const
Refer to argument.
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.
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
Internal class for Function.
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
void init(const Dict &opts) override
Initialize.
std::vector< bool > is_diff_out_
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.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
virtual bool is_a(const std::string &type, bool recursive) const
Check if the function is of a particular type.
size_t n_in_
Number of inputs and outputs.
size_t sz_res() const
Get required length of res field.
void serialize_type(SerializingStream &s) const override
Serialize type information.
size_t sz_w() const
Get required length of w field.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
size_t sz_arg() const
Get required length of arg field.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
std::vector< bool > is_diff_in_
Are inputs and outputs differentiable?
size_t sz_iw() const
Get required length of iw field.
Function object.
Definition: function.hpp:60
Function forward(casadi_int nfwd) const
Get a function that calculates nfwd forward derivatives.
Definition: function.cpp:1135
casadi_int nnz_out() const
Get number of output nonzeros.
Definition: function.cpp:855
void sz_work(size_t &sz_arg, size_t &sz_res, size_t &sz_iw, size_t &sz_w) const
Get number of temporary variables needed.
Definition: function.cpp:1079
size_t sz_res() const
Get required length of res field.
Definition: function.cpp:1085
const MX mx_in(casadi_int ind) const
Get symbolic primitives equivalent to the input expressions.
Definition: function.cpp:1584
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
static Function create(FunctionInternal *node)
Create from node.
Definition: function.cpp:336
bool is_diff_out(casadi_int ind) const
Get differentiability of inputs/output.
Definition: function.cpp:1055
int rev(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, int mem=0) const
Propagate sparsity backward.
Definition: function.cpp:1100
size_t sz_iw() const
Get required length of iw field.
Definition: function.cpp:1087
casadi_int n_out() const
Get the number of function outputs.
Definition: function.cpp:823
casadi_int n_in() const
Get the number of function inputs.
Definition: function.cpp:819
bool is_diff_in(casadi_int ind) const
Get differentiability of inputs/output.
Definition: function.cpp:1047
Function map(casadi_int n, const std::string &parallelization="serial") const
Create a mapped version of this function.
Definition: function.cpp:709
size_t sz_w() const
Get required length of w field.
Definition: function.cpp:1089
size_t sz_arg() const
Get required length of arg field.
Definition: function.cpp:1083
casadi_int nnz_in() const
Get number of input nonzeros.
Definition: function.cpp:851
int eval_gen(const T **arg, T **res, casadi_int *iw, T *w, int mem=0) const
Evaluate or propagate sparsities.
Definition: map.cpp:135
void serialize_type(SerializingStream &s) const override
Serialize type information.
Definition: map.cpp:93
Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Generate a function that calculates nadj adjoint derivatives.
Definition: map.cpp:265
int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity forward.
Definition: map.cpp:157
void init(const Dict &opts) override
Initialize.
Definition: map.cpp:121
~Map() override
Destructor.
Definition: map.cpp:117
bool is_a(const std::string &type, bool recursive) const override
Check if the function is of a particular type.
Definition: map.cpp:57
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate the function numerically.
Definition: map.cpp:318
Function f_
Definition: map.hpp:212
casadi_int n_
Definition: map.hpp:215
void codegen_body(CodeGenerator &g) const override
Generate code for the body of the C function.
Definition: map.cpp:183
bool has_function(const std::string &fname) const override
Definition: map.cpp:83
void codegen_declarations(CodeGenerator &g) const override
Generate code for the declarations of the C function.
Definition: map.cpp:179
int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const override
Propagate sparsity backwards.
Definition: map.cpp:162
std::string class_name() const override
Get type name.
Definition: map.hpp:53
int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w, void *mem, bool always_inline, bool never_inline) const override
evaluate symbolically while also propagating directional derivatives
Definition: map.cpp:152
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
Definition: map.cpp:87
virtual std::vector< std::string > get_function() const override
Definition: map.cpp:72
static Function create(const std::string &parallelization, const Function &f, casadi_int n)
Definition: map.cpp:39
Map(DeserializingStream &s)
Deserializing constructor.
Definition: map.cpp:98
virtual std::string parallelization() const
Type of parallellization.
Definition: map.hpp:112
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
Definition: map.cpp:103
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
Generate a function that calculates nfwd forward derivatives.
Definition: map.cpp:211
void init(const Dict &opts) override
Initialize.
Definition: map.cpp:404
bool is_a(const std::string &type, bool recursive) const override
Check if the function is of a particular type.
Definition: map.cpp:62
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate the function numerically.
Definition: map.cpp:331
void codegen_body(CodeGenerator &g) const override
Generate code for the body of the C function.
Definition: map.cpp:379
~OmpMap() override
Destructor.
Definition: map.cpp:327
Base class for FunctionInternal and LinsolInternal.
void clear_mem()
Clear all memory (called from destructor)
The basic scalar symbolic class of CasADi.
Definition: sx_elem.hpp:75
Helper class for Serialization.
void pack(const Sparsity &e)
Serializes an object to the output stream.
Class representing a Slice.
Definition: slice.hpp:48
void codegen_body(CodeGenerator &g) const override
Generate code for the body of the C function.
Definition: map.cpp:503
~ThreadMap() override
Destructor.
Definition: map.cpp:423
void init(const Dict &opts) override
Initialize.
Definition: map.cpp:507
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate the function numerically.
Definition: map.cpp:463
bool is_a(const std::string &type, bool recursive) const override
Check if the function is of a particular type.
Definition: map.cpp:67
The casadi namespace.
Definition: archiver.cpp:28
void ThreadsWork(const Function &f, casadi_int i, const double **arg, double **res, casadi_int *iw, double *w, casadi_int ind, int &ret)
Definition: map.cpp:427
std::string join(const std::vector< std::string > &l, const std::string &delim)
unsigned long long bvec_t
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.