26 #include "function_internal.hpp"
27 #include "casadi_call.hpp"
28 #include "call_sx.hpp"
29 #include "casadi_misc.hpp"
30 #include "global_options.hpp"
31 #include "external.hpp"
32 #include "finite_differences.hpp"
33 #include "serializing_stream.hpp"
34 #include "mx_function.hpp"
35 #include "sx_function.hpp"
36 #include "rootfinder_impl.hpp"
40 #include "interpolant_impl.hpp"
41 #include "nlpsol_impl.hpp"
42 #include "conic_impl.hpp"
43 #include "integrator_impl.hpp"
44 #include "external_impl.hpp"
45 #include "fmu_function.hpp"
46 #include "blazing_spline_impl.hpp"
47 #include "filesystem_impl.hpp"
71 casadi_error(
"Function name is not valid. A valid function name is a std::string "
72 "starting with a letter followed by letters, numbers or "
73 "non-consecutive underscores. It may also not match the keywords "
74 "'null', 'jac' or 'hess'. Got '" +
name_ +
"'");
123 for (
void* m : mem_) {
124 if (m!=
nullptr) casadi_warning(
"Memory object has not been properly freed");
132 std::string jit_name = jit_directory +
jit_name_ +
".c";
133 if (
remove(jit_name.c_str())) casadi_warning(
"Failed to remove " + jit_name);
150 }
catch(std::exception& e) {
151 casadi_error(
"Error calling " +
class_name() +
"::init for '" +
name_ +
"':\n"
152 + std::string(e.what()));
158 }
catch(std::exception& e) {
159 casadi_error(
"Error calling " +
class_name() +
"::finalize for '" +
name_ +
"':\n"
160 + std::string(e.what()));
168 "Verbose evaluation -- for debugging"}},
171 "print information about execution time. Implies record_time."}},
174 "record information about execution time, for retrieval with stats()."}},
177 "Throw exceptions when NaN or Inf appears during evaluation"}},
180 "Throw exceptions when function evaluation fails (default true)."}}
188 "Weighting factor for derivative calculation."
189 "When there is an option of either using forward or reverse mode "
190 "directional derivatives, the condition ad_weight*nf<=(1-ad_weight)*na "
191 "is used where nf and na are estimates of the number of forward/reverse "
192 "mode directional derivatives needed. By default, ad_weight is calculated "
193 "automatically, but this can be overridden by setting this option. "
194 "In particular, 0 means forcing forward mode and 1 forcing reverse mode. "
195 "Leave unset for (class specific) heuristics."}},
198 "Weighting factor for sparsity pattern calculation calculation."
199 "Overrides default behavior. Set to 0 and 1 to force forward and "
200 "reverse mode respectively. Cf. option \"ad_weight\". "
201 "When set to -1, sparsity is completely ignored and dense matrices are used."}},
207 "Forbid inlining."}},
210 "When requested for a number of forward/reverse directions, "
211 "it may be cheaper to compute first the full jacobian and then "
212 "multiply with seeds, rather than obtain the requested directions "
213 "in a straightforward manner. "
214 "Casadi uses a heuristic to decide which is cheaper. "
215 "A high value of 'jac_penalty' makes it less likely for the heurstic "
216 "to chose the full Jacobian strategy. "
217 "The special value -1 indicates never to use the full Jacobian strategy"}},
220 "A user-defined field that can be used to identify "
221 "the function or pass additional information"}},
224 "Throw exceptions when the numerical values of the inputs don't make sense"}},
227 "Deprecated option (ignored): Statistics are now always collected."}},
230 "Deprecated option (ignored)"}},
233 "Deprecated option (ignored)"}},
236 "Use just-in-time compiler to speed up the evaluation"}},
239 "Cleanup up the temporary source file that jit creates. Default: true"}},
242 "Specify behaviour when serializing a jitted function: SOURCE|link|embed."}},
245 "The file name used to write out code. "
246 "The actual file names used depend on 'jit_temp_suffix' and include extensions. "
247 "Default: 'jit_tmp'"}},
250 "Use a temporary (seemingly random) filename suffix for generated code and libraries. "
251 "This is desired for thread-safety. "
252 "This behaviour may defeat caching compiler wrappers. "
256 "Just-in-time compiler plugin to be used."}},
259 "Options to be passed to the jit compiler."}},
262 "The function is a derivative of another function. "
263 "The type of derivative (directional derivative, Jacobian) "
264 "is inferred from the function name."}},
267 "Specify the maximum number of directions for derivative functions."
268 " Overrules the builtin optimized_num_dir."}},
271 "Enable derivative calculation using generated functions for"
272 " Jacobian-times-vector products - typically using forward mode AD"
273 " - if available. [default: true]"}},
276 "Enable derivative calculation using generated functions for"
277 " transposed Jacobian-times-vector products - typically using reverse mode AD"
278 " - if available. [default: true]"}},
281 "Enable derivative calculation using generated functions for"
282 " Jacobians of all differentiable outputs with respect to all differentiable inputs"
283 " - if available. [default: true]"}},
286 "Enable derivative calculation by finite differencing. [default: false]]"}},
289 "Options to be passed to the finite difference instance"}},
292 "Method for finite differencing [default 'central']"}},
295 "Print numerical values of inputs [default: false]"}},
298 "Print numerical values of outputs [default: false]"}},
301 "Acceptable number of inputs and outputs. Warn if exceeded."}},
304 "Dump numerical values of inputs to file (readable with DM.from_file) [default: false]"}},
307 "Dump numerical values of outputs to file (readable with DM.from_file) [default: false]"}},
310 "Dump function to file upon first evaluation. [false]"}},
313 "Directory to dump inputs/outputs to. Make sure the directory exists [.]"}},
316 "Choose file format to dump matrices. See DM.from_file [mtx]"}},
319 "Options to be passed to a forward mode constructor"}},
322 "Options to be passed to a reverse mode constructor"}},
325 "Options to be passed to a Jacobian constructor"}},
328 "Default options to be used to populate forward_options, reverse_options, and "
329 "jacobian_options before those options are merged in."}},
332 "Override CasADi's AD. Use together with 'jac_penalty': 0. "
333 "Note: Highly experimental. Syntax may break often."}},
336 "Indicate for each input if it should be differentiable."}},
339 "Indicate for each output if it should be differentiable."}},
342 "After construction, expand this Function. Default: False"}},
343 {
"post_expand_options",
345 "Options to be passed to post-construction expansion. Default: empty"}},
348 "Prepopulate the function cache. Default: empty"}},
349 {
"external_transform",
351 "List of external_transform instruction arguments. Default: empty"}}
357 for (
auto&& op : opts) {
358 if (op.first==
"verbose") {
360 }
else if (op.first==
"print_time") {
362 }
else if (op.first==
"record_time") {
364 }
else if (op.first==
"regularity_check") {
366 }
else if (op.first==
"error_on_fail") {
387 if (target!=
"tmp") opts[
"jit"] =
jit_;
399 if (target==
"clone" || target==
"tmp") {
419 opts[
"dump"] =
dump_;
425 if (option_name ==
"print_in") {
427 }
else if (option_name ==
"print_out") {
429 }
else if (option_name==
"ad_weight") {
431 }
else if (option_name==
"ad_weight_sp") {
433 }
else if (option_name==
"dump") {
434 dump_ = option_value;
435 }
else if (option_name==
"dump_in") {
437 }
else if (option_name==
"dump_out") {
439 }
else if (option_name==
"dump_dir") {
441 }
else if (option_name==
"dump_format") {
457 for (
auto&& op : opts) {
458 if (op.first==
"jac_penalty") {
460 }
else if (op.first==
"user_data") {
462 }
else if (op.first==
"inputs_check") {
464 }
else if (op.first==
"gather_stats") {
465 casadi_warning(
"Deprecated option \"gather_stats\": Always enabled");
466 }
else if (op.first==
"input_scheme") {
467 casadi_warning(
"Deprecated option: \"input_scheme\" set via constructor");
468 }
else if (op.first==
"output_scheme") {
469 casadi_warning(
"Deprecated option: \"output_scheme\" set via constructor");
470 }
else if (op.first==
"jit") {
472 }
else if (op.first==
"jit_cleanup") {
474 }
else if (op.first==
"jit_serialize") {
477 "jit_serialize option not understood. Pick one of source, link, embed.");
478 }
else if (op.first==
"compiler") {
480 }
else if (op.first==
"jit_options") {
482 }
else if (op.first==
"jit_name") {
484 }
else if (op.first==
"jit_temp_suffix") {
486 }
else if (op.first==
"derivative_of") {
488 }
else if (op.first==
"ad_weight") {
490 }
else if (op.first==
"ad_weight_sp") {
492 }
else if (op.first==
"max_num_dir") {
494 }
else if (op.first==
"enable_forward") {
496 }
else if (op.first==
"enable_reverse") {
498 }
else if (op.first==
"enable_jacobian") {
500 }
else if (op.first==
"enable_fd") {
502 }
else if (op.first==
"fd_options") {
504 }
else if (op.first==
"fd_method") {
506 }
else if (op.first==
"print_in") {
508 }
else if (op.first==
"print_out") {
510 }
else if (op.first==
"max_io") {
512 }
else if (op.first==
"dump_in") {
514 }
else if (op.first==
"dump_out") {
516 }
else if (op.first==
"dump") {
518 }
else if (op.first==
"dump_dir") {
520 }
else if (op.first==
"dump_format") {
522 }
else if (op.first==
"forward_options") {
524 }
else if (op.first==
"reverse_options") {
526 }
else if (op.first==
"jacobian_options") {
528 }
else if (op.first==
"der_options") {
530 }
else if (op.first==
"custom_jacobian") {
533 "Inconsistent naming of custom Jacobian, expected: jac_" +
name_);
535 }
else if (op.first==
"always_inline") {
537 }
else if (op.first==
"never_inline") {
539 }
else if (op.first==
"is_diff_in") {
541 }
else if (op.first==
"is_diff_out") {
543 }
else if (op.first==
"cache") {
557 casadi_warning(
"Function " +
name_ +
" has many inputs (" +
str(
n_in_) +
" > "
559 +
"Changing the problem formulation is strongly encouraged.");
565 casadi_warning(
"Function " +
name_ +
" has many outputs (" +
str(
n_out_) +
" > "
567 +
"Changing the problem formulation is strongly encouraged.");
576 +
" inputs, but is_diff_in has length " +
str(
is_diff_in_.size()) +
".");
585 +
" outputs, but is_diff_out has length " +
str(
is_diff_out_.size()) +
".");
594 +
" inputs, but sparsity_in has length " +
str(
sparsity_in_.size()) +
".");
603 +
" outputs, but sparsity_out has length " +
str(
sparsity_out_.size()) +
".");
612 +
" inputs, but name_in has length " +
str(
name_in_.size()) +
".");
621 +
" outputs, but name_out has length " +
str(
name_out_.size()) +
".");
627 if (c.first != f.
name()) {
628 casadi_warning(
"Cannot add '" + c.first +
"' a.k.a. '" + f.
name()
629 +
"' to cache. Mismatching names not implemented.");
636 sz_arg_per_ +=
n_in_;
652 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
673 if (
name_ ==
"jac_" + n) {
677 }
else if (
name_ ==
"adj1_" + n) {
695 if (
verbose_) casadi_message(
"Codegenerating function '" +
name_ +
"'.");
699 opts[
"prefix"] =
"jit";
702 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"'..");
705 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"' done.");
711 casadi_assert(
eval_!=
nullptr,
"Cannot load JIT'ed function.");
728 casadi_assert_dev(mem==0);
738 for (casadi_int i=0; i<
n_in_; ++i) {
739 const double* v = arg[i];
740 for (casadi_int k=0;k<
nnz_in(i);++k) {
754 for (casadi_int i=0; i<
n_out_; ++i) {
755 const double* v = res[i];
756 for (casadi_int k=0;k<
nnz_out(i);++k) {
757 normalized_out(of, v ? v[k] : std::numeric_limits<double>::quiet_NaN());
763 void FunctionInternal::dump_in(casadi_int
id,
const double** arg)
const {
764 std::stringstream ss;
765 ss << std::setfill(
'0') << std::setw(6) << id;
766 std::string count = ss.str();
767 for (casadi_int i=0;i<
n_in_;++i) {
774 void FunctionInternal::dump_out(casadi_int
id,
double** res)
const {
775 std::stringstream ss;
776 ss << std::setfill(
'0') << std::setw(6) << id;
777 std::string count = ss.str();
778 for (casadi_int i=0;i<
n_out_;++i) {
785 void FunctionInternal::dump()
const {
789 casadi_int FunctionInternal::get_dump_id()
const {
797 m->t_total = &m->fstats.at(
"total");
799 m->t_total =
nullptr;
805 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
806 for (casadi_int i=0; i<
n_in_; ++i) {
807 stream <<
"Input " << i <<
" (" <<
name_in_[i] <<
"): ";
812 stream <<
"NULL" << std::endl;
818 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
819 for (casadi_int i=0; i<
n_out_; ++i) {
820 stream <<
"Output " << i <<
" (" <<
name_out_[i] <<
"): ";
825 stream <<
"NULL" << std::endl;
831 eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem,
832 bool always_inline,
bool never_inline)
const {
834 if (
dump_in_) dump_in(dump_id, arg);
835 if (
dump_ && dump_id==0) dump();
840 for (casadi_int i=0;i<
n_in_;++i) {
841 casadi_assert(arg[i]==0 || arg[i]+
nnz_in(i)<=w || arg[i]>=w+
sz_w(),
842 "Memory corruption detected for input " +
name_in_[i] +
".\n"+
844 " intersects with w " +
str(w)+
"-"+
str(w+
sz_w())+
".");
846 for (casadi_int i=0;i<
n_out_;++i) {
847 casadi_assert(res[i]==0 || res[i]+
nnz_out(i)<=w || res[i]>=w+
sz_w(),
848 "Memory corruption detected for output " +
name_out_[i]);
851 for (
auto&& s : m->fstats) s.second.reset();
852 if (m->t_total) m->t_total->tic();
859 #ifdef CASADI_WITH_THREAD
860 std::lock_guard<std::mutex> lock(mtx_);
864 ret =
eval_(arg, res, iw, w, mem_);
866 #ifdef CASADI_WITH_THREAD
867 std::lock_guard<std::mutex> lock(mtx_);
872 ret =
eval(arg, res, iw, w, mem);
874 if (m->t_total) m->t_total->toc();
882 for (casadi_int i = 0; i <
n_out_; ++i) {
884 if (!res[i])
continue;
886 casadi_int nnz = this->
nnz_out(i);
887 for (casadi_int nz = 0; nz < nnz; ++nz) {
888 if (isnan(res[i][nz]) || isinf(res[i][nz])) {
890 casadi_error(
str(res[i][nz]) +
" detected for output " +
name_out_[i] +
" at "
900 stream <<
" Number of inputs: " <<
n_in_ << std::endl;
901 for (casadi_int i=0; i<
n_in_; ++i) {
902 stream <<
" Input " << i <<
" (\"" <<
name_in_[i] <<
"\"): "
905 stream <<
" Number of outputs: " <<
n_out_ << std::endl;
906 for (casadi_int i=0; i<
n_out_; ++i) {
907 stream <<
" Output " << i <<
" (\"" <<
name_out_[i] <<
"\"): "
926 if (option_name ==
"verbose") {
928 }
else if (option_name ==
"regularity_check") {
932 casadi_error(
"Option '" + option_name +
"' cannot be changed");
938 return std::vector<std::string>();
947 for (casadi_int i=0; i<
n_in_; ++i) {
953 for (casadi_int i=0; i<
n_out_; ++i) {
975 std::vector<std::string> keys;
976 std::vector<Function> entries;
977 cache_.cache(keys, entries);
979 for (
size_t i=0; i<keys.size(); ++i) {
981 std::string s = keys[i];
982 casadi_assert_dev(s.size() > 0);
984 std::replace(s.begin(), s.end(),
':',
'_');
986 if (s.back() ==
'_') s.resize(s.size() - 1);
995 const std::string& suffix)
const {
996 return cache_.incache(fname +
":" + suffix, f);
1004 cache_.tocache_if_missing(f.
name() +
":" + suffix, f);
1009 if (parallelization==
"serial") {
1011 std::string fname =
"map" +
str(n) +
"_" +
name_;
1015 casadi_assert_dev(f.
name()==fname);
1027 if (opts.empty())
return shared_from_this<Function>();
1028 std::string fname =
"wrap_" +
name_;
1030 Dict my_opts = opts;
1032 if (my_opts.find(
"ad_weight")==my_opts.end())
1034 if (my_opts.find(
"ad_weight_sp")==my_opts.end())
1036 if (my_opts.find(
"max_num_dir")==my_opts.end())
1039 std::vector<MX> arg =
mx_in();
1040 std::vector<MX> res =
self()(arg);
1046 std::string fname =
"wrap_" +
name_;
1057 std::vector<MX> arg =
mx_in();
1058 std::vector<MX> res =
self()(arg);
1073 for (casadi_int i=begin; i<end; ++i) {
1074 s[i] ^= (
bvec_t(1) << j);
1079 for (casadi_int i=begin; i<end; ++i) {
1087 for (casadi_int i=begin; i<end; ++i) r |= s[i];
1092 template<
bool fwd>
struct JacSparsityTraits {};
1093 template<>
struct JacSparsityTraits<true> {
1094 typedef const bvec_t* arg_t;
1095 static inline void sp(
const FunctionInternal *f,
1097 casadi_int* iw,
bvec_t* w,
void* mem) {
1098 std::vector<const bvec_t*> argm(f->sz_arg(),
nullptr);
1099 std::vector<bvec_t> wm(f->nnz_in(),
bvec_t(0));
1102 for (casadi_int i=0;i<f->n_in_;++i) {
1103 if (f->is_diff_in_[i]) {
1106 argm[i] = arg[i] ? wp :
nullptr;
1110 f->sp_forward(
get_ptr(argm), res, iw, w, mem);
1111 for (casadi_int i=0;i<f->n_out_;++i) {
1112 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1116 template<>
struct JacSparsityTraits<false> {
1118 static inline void sp(
const FunctionInternal *f,
1120 casadi_int* iw,
bvec_t* w,
void* mem) {
1121 for (casadi_int i=0;i<f->n_out_;++i) {
1122 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1124 f->sp_reverse(arg, res, iw, w, mem);
1125 for (casadi_int i=0;i<f->n_in_;++i) {
1126 if (!f->is_diff_in_[i] && arg[i])
casadi_clear(arg[i], f->nnz_in(i));
1138 std::vector<typename JacSparsityTraits<fwd>::arg_t> arg(
sz_arg(),
nullptr);
1139 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1140 std::vector<casadi_int> iw(
sz_iw());
1141 std::vector<bvec_t> w(
sz_w(), 0);
1144 std::vector<bvec_t> seed(
nz_in, 0);
1146 std::vector<bvec_t> sens(
nz_out, 0);
1148 if (!fwd) std::swap(seed, sens);
1151 casadi_int nsweep = seed.size() /
bvec_size;
1156 casadi_message(
str(nsweep) + std::string(fwd ?
" forward" :
" reverse") +
" sweeps "
1157 "needed for " +
str(seed.size()) +
" directions");
1161 casadi_int progress = -10;
1164 std::vector<casadi_int> jcol, jrow;
1167 for (casadi_int s=0; s<nsweep; ++s) {
1171 casadi_int progress_new = (s*100)/nsweep;
1173 if (progress_new / 10 > progress / 10) {
1174 progress = progress_new;
1175 casadi_message(
str(progress) +
" %");
1183 casadi_int ndir_local = seed.size()-offset;
1184 ndir_local = std::min(
static_cast<casadi_int
>(
bvec_size), ndir_local);
1186 for (casadi_int i=0; i<ndir_local; ++i) {
1187 seed[offset+i] |=
bvec_t(1)<<i;
1195 for (casadi_int el=0; el<sens.size(); ++el) {
1198 bvec_t spsens = sens[el];
1209 for (casadi_int i=0; i<ndir_local; ++i) {
1212 if ((
bvec_t(1) << i) & spsens) {
1215 jrow.push_back(i+offset);
1222 for (casadi_int i=0; i<ndir_local; ++i) {
1228 if (!fwd) swap(jrow, jcol);
1231 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(ret.
size()) +
", "
1238 casadi_int iind)
const {
1242 casadi_int nz =
nnz_in(iind);
1243 casadi_assert_dev(nz==
nnz_out(oind));
1246 std::vector<const bvec_t*> arg(
sz_arg(),
nullptr);
1247 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1248 std::vector<casadi_int> iw(
sz_iw());
1249 std::vector<bvec_t> w(
sz_w());
1252 std::vector<bvec_t> seed(nz, 0);
1256 std::vector<bvec_t> sens(nz, 0);
1260 std::vector<casadi_int> jcol, jrow;
1263 std::vector<casadi_int> coarse(2, 0); coarse[1] = nz;
1266 std::vector<casadi_int> fine;
1274 casadi_int granularity = nz;
1276 casadi_int nsweeps = 0;
1278 bool hasrun =
false;
1280 while (!hasrun || coarse.size()!=nz+1) {
1281 if (
verbose_) casadi_message(
"Block size: " +
str(granularity));
1293 casadi_message(
"Star coloring on " +
str(r.
dim()) +
": "
1294 +
str(
D.size2()) +
" <-> " +
str(
D.size1()));
1298 std::fill(seed.begin(), seed.end(), 0);
1301 for (casadi_int k=0; k<coarse.size()-1; ++k) {
1302 casadi_int
diff = coarse[k+1]-coarse[k];
1303 casadi_int new_diff =
diff/subdivision;
1304 if (
diff%subdivision>0) new_diff++;
1305 std::vector<casadi_int> temp =
range(coarse[k], coarse[k+1], new_diff);
1306 fine.insert(fine.end(), temp.begin(), temp.end());
1308 if (fine.back()!=coarse.back()) fine.push_back(coarse.back());
1310 granularity = fine[1] - fine[0];
1313 casadi_int bvec_i = 0;
1316 std::vector<casadi_int> fine_lookup =
lookupvector(fine, nz+1);
1319 std::vector<casadi_int> lookup_col;
1320 std::vector<casadi_int> lookup_row;
1321 std::vector<casadi_int> lookup_value;
1324 casadi_int n_fine_blocks_max = 0;
1325 for (casadi_int i=0;i<coarse.size()-1;++i) {
1326 casadi_int del = fine_lookup[coarse[i+1]]-fine_lookup[coarse[i]];
1327 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1331 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1334 casadi_int fci_offset = 0;
1338 bool f_finished =
false;
1341 while (!f_finished) {
1344 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1345 casadi_int cci =
D.row(k);
1348 casadi_int fci_start = fine_lookup[coarse[cci]];
1349 casadi_int fci_end = fine_lookup[coarse[cci+1]];
1352 casadi_int bvec_i_mod = 0;
1354 casadi_int value = -bvec_i + fci_offset + fci_start;
1359 for (casadi_int fci = fci_offset; fci<std::min(fci_end-fci_start, fci_cap); ++fci) {
1363 for (casadi_int cri=r.
colind(cci);cri<r.
colind(cci+1);++cri) {
1364 lookup_col.push_back(r.
row(cri));
1365 lookup_row.push_back(bvec_i+bvec_i_mod);
1366 lookup_value.push_back(value);
1377 bvec_i += std::min(n_fine_blocks_max, fci_cap);
1387 IM lookup =
IM::triplet(lookup_row, lookup_col, lookup_value,
1390 std::reverse(lookup_col.begin(), lookup_col.end());
1391 std::reverse(lookup_row.begin(), lookup_row.end());
1392 std::reverse(lookup_value.begin(), lookup_value.end());
1396 duplicates = sparsify(duplicates);
1407 for (casadi_int cri=0; cri<coarse.size()-1; ++cri) {
1410 for (casadi_int fri=fine_lookup[coarse[cri]];fri<fine_lookup[coarse[cri+1]];++fri) {
1415 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1416 if (spsens & (
bvec_t(1) << bvec_i)) {
1419 if (ind==-1)
continue;
1420 casadi_int lk = lookup->at(ind);
1422 jrow.push_back(bvec_i+lk);
1423 jcol.push_back(fri);
1424 jrow.push_back(fri);
1425 jcol.push_back(bvec_i+lk);
1433 std::fill(seed.begin(), seed.end(), 0);
1438 lookup_value.clear();
1441 if (n_fine_blocks_max>fci_cap) {
1442 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1464 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1465 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
1480 std::vector<bvec_t> s_in(
nz_in, 0);
1481 std::vector<bvec_t> s_out(
nz_out, 0);
1484 std::vector<const bvec_t*> arg_fwd(
sz_arg(),
nullptr);
1485 std::vector<bvec_t*> arg_adj(
sz_arg(),
nullptr);
1486 arg_fwd[iind] = arg_adj[iind] =
get_ptr(s_in);
1487 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1489 std::vector<casadi_int> iw(
sz_iw());
1490 std::vector<bvec_t> w(
sz_w());
1493 std::vector<casadi_int> jcol, jrow;
1496 std::vector<casadi_int> coarse_col(2, 0); coarse_col[1] =
nz_out;
1498 std::vector<casadi_int> coarse_row(2, 0); coarse_row[1] =
nz_in;
1501 std::vector<casadi_int> fine_col;
1504 std::vector<casadi_int> fine_row;
1512 casadi_int granularity_row =
nz_in;
1513 casadi_int granularity_col =
nz_out;
1515 bool use_fwd =
true;
1517 casadi_int nsweeps = 0;
1519 bool hasrun =
false;
1525 std::vector<bvec_t> bvec_lookup;
1528 bvec_lookup.push_back(
bvec_t(1) << i);
1531 while (!hasrun || coarse_col.size()!=
nz_out+1 || coarse_row.size()!=
nz_in+1) {
1533 casadi_message(
"Block size: " +
str(granularity_col) +
" x " +
str(granularity_row));
1554 casadi_message(
"Coloring on " +
str(r.
dim()) +
" (fwd seeps: " +
str(D1.
size2()) +
1555 " , adj sweeps: " +
str(D2.
size1()) +
")");
1559 double fwd_cost =
static_cast<double>(use_fwd ? granularity_row : granularity_col) *
1560 sp_w*
static_cast<double>(D1.
size2());
1561 double adj_cost =
static_cast<double>(use_fwd ? granularity_col : granularity_row) *
1562 (1-sp_w)*
static_cast<double>(D2.
size2());
1563 use_fwd = fwd_cost <= adj_cost;
1565 casadi_message(std::string(use_fwd ?
"Forward" :
"Reverse") +
" mode chosen "
1566 "(fwd cost: " +
str(fwd_cost) +
", adj cost: " +
str(adj_cost) +
")");
1578 for (casadi_int i=0; i<nz_seed; ++i) seed_v[i]=0;
1585 std::swap(coarse_col, coarse_row);
1586 std::swap(granularity_col, granularity_row);
1591 for (casadi_int k=0;k<coarse_col.size()-1;++k) {
1592 casadi_int
diff = coarse_col[k+1]-coarse_col[k];
1593 casadi_int new_diff =
diff/subdivision;
1594 if (
diff%subdivision>0) new_diff++;
1595 std::vector<casadi_int> temp =
range(coarse_col[k], coarse_col[k+1], new_diff);
1596 fine_col.insert(fine_col.end(), temp.begin(), temp.end());
1599 for (casadi_int k=0;k<coarse_row.size()-1;++k) {
1600 casadi_int
diff = coarse_row[k+1]-coarse_row[k];
1601 casadi_int new_diff =
diff/subdivision;
1602 if (
diff%subdivision>0) new_diff++;
1603 std::vector<casadi_int> temp =
range(coarse_row[k], coarse_row[k+1], new_diff);
1604 fine_row.insert(fine_row.end(), temp.begin(), temp.end());
1606 if (fine_row.back()!=coarse_row.back()) fine_row.push_back(coarse_row.back());
1607 if (fine_col.back()!=coarse_col.back()) fine_col.push_back(coarse_col.back());
1609 granularity_col = fine_col[1] - fine_col[0];
1610 granularity_row = fine_row[1] - fine_row[0];
1613 casadi_int bvec_i = 0;
1616 std::vector<casadi_int> fine_col_lookup =
lookupvector(fine_col, nz_sens+1);
1617 std::vector<casadi_int> fine_row_lookup =
lookupvector(fine_row, nz_seed+1);
1620 std::vector<casadi_int> lookup_col;
1621 std::vector<casadi_int> lookup_row;
1622 std::vector<casadi_int> lookup_value;
1626 casadi_int n_fine_blocks_max = 0;
1627 for (casadi_int i=0;i<coarse_row.size()-1;++i) {
1628 casadi_int del = fine_row_lookup[coarse_row[i+1]]-fine_row_lookup[coarse_row[i]];
1629 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1633 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1635 casadi_int fci_offset = 0;
1639 bool f_finished =
false;
1642 while (!f_finished) {
1645 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1646 casadi_int cci =
D.row(k);
1649 casadi_int fci_start = fine_row_lookup[coarse_row[cci]];
1650 casadi_int fci_end = fine_row_lookup[coarse_row[cci+1]];
1653 casadi_int bvec_i_mod = 0;
1655 casadi_int value = -bvec_i + fci_offset + fci_start;
1658 for (casadi_int fci = fci_offset; fci < std::min(fci_end-fci_start, fci_cap); ++fci) {
1662 for (casadi_int cri=rT.
colind(cci);cri<rT.
colind(cci+1);++cri) {
1663 lookup_col.push_back(rT.
row(cri));
1664 lookup_row.push_back(bvec_i+bvec_i_mod);
1665 lookup_value.push_back(value);
1669 bvec_toggle(seed_v, fine_row[fci+fci_start], fine_row[fci+fci_start+1],
1676 bvec_i+= std::min(n_fine_blocks_max, fci_cap);
1691 JacSparsityTraits<true>::sp(
this,
get_ptr(arg_fwd),
get_ptr(res),
1694 std::fill(w.begin(), w.end(), 0);
1695 JacSparsityTraits<false>::sp(
this,
get_ptr(arg_adj),
get_ptr(res),
1703 for (casadi_int cri=0;cri<coarse_col.size()-1;++cri) {
1706 for (casadi_int fri=fine_col_lookup[coarse_col[cri]];
1707 fri<fine_col_lookup[coarse_col[cri+1]];++fri) {
1709 bvec_or(sens_v, spsens, fine_col[fri], fine_col[fri+1]);
1712 if (!spsens)
continue;
1715 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1716 if (spsens & bvec_lookup[bvec_i]) {
1719 if (ind==-1)
continue;
1720 jrow.push_back(bvec_i+lookup->at(ind));
1721 jcol.push_back(fri);
1728 std::fill(s_in.begin(), s_in.end(), 0);
1731 std::fill(s_out.begin(), s_out.end(), 0);
1736 lookup_value.clear();
1739 if (n_fine_blocks_max>fci_cap) {
1740 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1755 coarse_col = fine_col;
1756 coarse_row = fine_row;
1760 coarse_col = fine_row;
1761 coarse_row = fine_col;
1766 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1767 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
", " +
1779 if (
name_ ==
"adj1_" + n) {
1780 if (iind == oind)
return true;
1788 bool symmetric)
const {
1791 "Symmetry exploitation in Jacobian assumes dense expression. "
1792 "A potential workaround is to apply densify().");
1824 if (w*
static_cast<double>(nsweep_fwd) <= (1-w)*
static_cast<double>(nsweep_adj)) {
1825 sp = get_jac_sparsity_gen<true>(oind, iind);
1827 sp = get_jac_sparsity_gen<false>(oind, iind);
1840 std::vector<casadi_int> mapping;
1863 bool symmetric)
const {
1864 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
1866 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
1869 for (
bool c : {
false,
true}) {
1873 casadi_int ind = iind + oind *
n_in_;
1889 sp_is_compact =
true;
1901 if (sp_is_compact == compact) {
1928 bool compact,
bool symmetric,
1929 bool allow_forward,
bool allow_reverse)
const {
1931 casadi_assert(allow_forward || allow_reverse,
"Inconsistent options");
1940 casadi_assert_dev(allow_forward);
1943 if (
verbose_) casadi_message(
"FunctionInternal::getPartition star_coloring");
1946 casadi_message(
"Star coloring completed: " +
str(D1.
size2())
1947 +
" directional derivatives needed ("
1948 +
str(A.
size1()) +
" without coloring).");
1957 if (w==1) allow_forward =
false;
1958 if (w==0) allow_reverse =
false;
1959 casadi_assert(allow_forward || allow_reverse,
"Conflicting ad weights");
1962 double best_coloring = std::numeric_limits<double>::infinity();
1965 bool test_fwd_first = allow_forward && w*
static_cast<double>(A.
size1()) <=
1966 (1-w)*
static_cast<double>(A.
size2());
1967 casadi_int mode_fwd = test_fwd_first ? 0 : 1;
1970 for (casadi_int mode=0; mode<2; ++mode) {
1972 bool fwd = mode==mode_fwd;
1975 if (!allow_forward && fwd)
continue;
1976 if (!allow_reverse && !fwd)
continue;
1980 if (
verbose_) casadi_message(
"Unidirectional coloring (forward mode)");
1981 bool d = best_coloring>=w*
static_cast<double>(A.
size1());
1982 casadi_int max_colorings_to_test =
1983 d ? A.
size1() :
static_cast<casadi_int
>(floor(best_coloring/w));
1987 casadi_message(
"Forward mode coloring interrupted (more than "
1988 +
str(max_colorings_to_test) +
" needed).");
1992 casadi_message(
"Forward mode coloring completed: "
1993 +
str(D1.
size2()) +
" directional derivatives needed ("
1994 +
str(A.
size1()) +
" without coloring).");
1997 best_coloring = w*
static_cast<double>(D1.
size2());
2000 if (
verbose_) casadi_message(
"Unidirectional coloring (adjoint mode)");
2001 bool d = best_coloring>=(1-w)*
static_cast<double>(A.
size2());
2002 casadi_int max_colorings_to_test =
2003 d ? A.
size2() :
static_cast<casadi_int
>(floor(best_coloring/(1-w)));
2008 casadi_message(
"Adjoint mode coloring interrupted (more than "
2009 +
str(max_colorings_to_test) +
" needed).");
2013 casadi_message(
"Adjoint mode coloring completed: "
2014 +
str(D2.
size2()) +
" directional derivatives needed ("
2015 +
str(A.
size2()) +
" without coloring).");
2018 best_coloring = (1-w)*
static_cast<double>(D2.
size2());
2027 casadi_error(
"'eval_dm' not defined for " +
class_name());
2032 bool always_inline,
bool never_inline)
const {
2037 casadi_assert(!always_inline,
"'eval_sx' not defined for " +
class_name() +
2038 " in combination with always_inline true");
2045 casadi_int highest_index = 0;
2048 for (
const std::string& n : name_io) {
2050 size_t end = n.find(
'_');
2051 if (end >= n.size())
continue;
2053 if (end < prefix.size())
continue;
2055 if (n.compare(0, prefix.size(), prefix) != 0)
continue;
2057 size_t begin = prefix.size();
2059 casadi_int this_index;
2065 this_index = std::stoi(n.substr(begin, end - begin));
2068 if (this_index > highest_index) highest_index = this_index;
2072 if (highest_index == 0) {
2073 return prefix +
"_";
2075 return prefix + std::to_string(highest_index + 1) +
"_";
2080 casadi_assert_dev(nfwd>=0);
2095 std::vector<std::string> inames;
2098 for (i=0; i<
n_in_; ++i) inames.push_back(pref +
name_in_[i]);
2100 std::vector<std::string> onames;
2106 opts[
"derivative_of"] =
self();
2110 f =
get_forward(nfwd, fname, inames, onames, opts);
2122 casadi_error(
"Unknown 'fd_method': " +
fd_method_);
2141 casadi_assert_dev(nadj>=0);
2156 std::vector<std::string> inames;
2161 std::vector<std::string> onames;
2162 for (casadi_int i=0; i<
n_in_; ++i) onames.push_back(pref +
name_in_[i]);
2166 opts[
"derivative_of"] =
self();
2169 f =
get_reverse(nadj, fname, inames, onames, opts);
2186 get_forward(casadi_int nfwd,
const std::string& name,
2187 const std::vector<std::string>& inames,
2188 const std::vector<std::string>& onames,
2189 const Dict& opts)
const {
2190 casadi_error(
"'get_forward' not defined for " +
class_name());
2194 get_reverse(casadi_int nadj,
const std::string& name,
2195 const std::vector<std::string>& inames,
2196 const std::vector<std::string>& onames,
2197 const Dict& opts)
const {
2198 casadi_error(
"'get_reverse' not defined for " +
class_name());
2202 const Dict& options)
const {
2203 casadi_error(
"'export_code' not defined for " +
class_name());
2207 casadi_int n = s.size();
2209 std::stringstream ss;
2210 for (casadi_int i=0;i<n;++i) {
2214 casadi_assert_dev(s==ss.str());
2219 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
nnz_in(iind);
2225 for (casadi_int oind=0; oind<
n_out_; ++oind) ret +=
nnz_out(oind);
2231 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
numel_in(iind);
2242 bool always_inline,
bool never_inline)
const {
2248 if (always_inline) {
2249 casadi_assert(!never_inline,
"Inconsistent options for " +
str(
name_));
2250 return wrap().
call(arg, res,
true);
2262 "Derivatives cannot be calculated for " +
name_);
2267 std::string fname =
"jac_" +
name_;
2270 std::vector<std::string> inames;
2271 for (casadi_int i=0; i<
n_in_; ++i) inames.push_back(
name_in_[i]);
2272 for (casadi_int i=0; i<
n_out_; ++i) inames.push_back(
"out_" +
name_out_[i]);
2274 std::vector<std::string> onames;
2276 for (
size_t oind = 0; oind <
n_out_; ++oind) {
2277 for (
size_t iind = 0; iind <
n_in_; ++iind) {
2283 opts[
"derivative_of"] =
self();
2288 casadi_assert(f.
n_in() == inames.size(),
2289 "Mismatching input signature, expected " +
str(inames));
2290 casadi_assert(f.
n_out() == onames.size(),
2291 "Mismatching output signature, expected " +
str(onames));
2300 const std::vector<std::string>& inames,
2301 const std::vector<std::string>& onames,
2302 const Dict& opts)
const {
2303 casadi_error(
"'get_jacobian' not defined for " +
class_name());
2309 g <<
"static " <<
signature(fname) <<
" {\n";
2330 return "int " + fname +
"(const casadi_real** arg, casadi_real** res, "
2331 "casadi_int* iw, casadi_real* w, int mem)";
2335 std::vector<std::string> args;
2337 args.push_back(
"const casadi_real* " +
str(e));
2340 args.push_back(
"casadi_real* " +
str(e));
2342 args.push_back(
"const casadi_real** arg");
2343 args.push_back(
"casadi_real** res");
2344 args.push_back(
"casadi_int* iw");
2345 args.push_back(
"casadi_real* w");
2346 args.push_back(
"int mem");
2347 return "int " + fname +
"_unrolled(" +
join(args,
", ") +
")";
2358 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2359 g <<
"return " + mem_counter +
"++;\n";
2365 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2366 std::string stack = g.
shorthand(name +
"_unused_stack");
2367 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2368 std::string mem_array = g.
shorthand(name +
"_mem");
2372 g.
auxiliaries <<
"static int " << mem_counter <<
" = 0;\n";
2373 g.
auxiliaries <<
"static int " << stack_counter <<
" = -1;\n";
2374 g.
auxiliaries <<
"static int " << stack <<
"[CASADI_MAX_NUM_THREADS];\n";
2376 " " << mem_array <<
"[CASADI_MAX_NUM_THREADS];\n\n";
2378 g <<
"if (" << stack_counter <<
">=0) {\n";
2379 g <<
"return " << stack <<
"[" << stack_counter <<
"--];\n";
2381 g <<
"if (" << mem_counter <<
"==CASADI_MAX_NUM_THREADS) return -1;\n";
2383 g <<
"if (mid<0) return -1;\n";
2384 g <<
"if(" <<
init_mem <<
"(mid)) return -1;\n";
2385 g <<
"return mid;\n";
2391 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2392 std::string stack = g.
shorthand(name +
"_unused_stack");
2393 g << stack <<
"[++" << stack_counter <<
"] = mem;\n";
2403 g << g.
declare(
"int " +
name_ +
"_alloc_mem(void)") <<
" {\n";
2405 g <<
"return " <<
codegen_name(g) <<
"_alloc_mem();\n";
2411 g << g.
declare(
"int " +
name_ +
"_init_mem(int mem)") <<
" {\n";
2413 g <<
"return " <<
codegen_name(g) <<
"_init_mem(mem);\n";
2419 g << g.
declare(
"void " +
name_ +
"_free_mem(int mem)") <<
" {\n";
2426 g << g.
declare(
"int " +
name_ +
"_checkout(void)") <<
" {\n";
2435 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2438 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2443 g << g.
declare(
"void " +
name_ +
"_incref(void)") <<
" {\n";
2446 << g.
declare(
"void " +
name_ +
"_decref(void)") <<
" {\n";
2452 <<
" { return " <<
n_in_ <<
";}\n\n"
2454 <<
" { return " <<
n_out_ <<
";}\n\n";
2457 g << g.
declare(
"casadi_real " +
name_ +
"_default_in(casadi_int i)") <<
" {\n"
2458 <<
"switch (i) {\n";
2459 for (casadi_int i=0; i<
n_in_; ++i) {
2461 if (def!=0) g <<
"case " << i <<
": return " << g.
constant(def) <<
";\n";
2463 g <<
"default: return 0;\n}\n"
2467 g << g.
declare(
"const char* " +
name_ +
"_name_in(casadi_int i)") <<
" {\n"
2468 <<
"switch (i) {\n";
2469 for (casadi_int i=0; i<
n_in_; ++i) {
2470 g <<
"case " << i <<
": return \"" <<
name_in_[i] <<
"\";\n";
2472 g <<
"default: return 0;\n}\n"
2476 g << g.
declare(
"const char* " +
name_ +
"_name_out(casadi_int i)") <<
" {\n"
2477 <<
"switch (i) {\n";
2478 for (casadi_int i=0; i<
n_out_; ++i) {
2479 g <<
"case " << i <<
": return \"" <<
name_out_[i] <<
"\";\n";
2481 g <<
"default: return 0;\n}\n"
2489 "int " +
name_ +
"_work(casadi_int *sz_arg, casadi_int* sz_res, "
2490 "casadi_int *sz_iw, casadi_int *sz_w)")
2501 "int " +
name_ +
"_work_bytes(casadi_int *sz_arg, casadi_int* sz_res, "
2502 "casadi_int *sz_iw, casadi_int *sz_w)")
2504 <<
"if (sz_arg) *sz_arg = " <<
codegen_sz_arg(g) <<
"*sizeof(const casadi_real*);\n"
2505 <<
"if (sz_res) *sz_res = " <<
codegen_sz_res(g) <<
"*sizeof(casadi_real*);\n"
2506 <<
"if (sz_iw) *sz_iw = " <<
codegen_sz_iw(g) <<
"*sizeof(casadi_int);\n"
2507 <<
"if (sz_w) *sz_w = " <<
codegen_sz_w(g) <<
"*sizeof(casadi_real);\n"
2522 g << g.
declare(
"int " +
name_ +
"_diff_in(casadi_int i)") <<
" {\n"
2523 <<
"switch (i) {\n";
2524 for (casadi_int i=0; i<
n_in_; ++i) {
2525 g <<
"case " << i <<
": return " <<
is_diff_in_[i] <<
";\n";
2527 g <<
"default: return -1;\n}\n"
2533 g << g.
declare(
"int " +
name_ +
"_diff_out(casadi_int i)") <<
" {\n"
2534 <<
"switch (i) {\n";
2535 for (casadi_int i=0; i<
n_out_; ++i) {
2536 g <<
"case " << i <<
": return " <<
is_diff_out_[i] <<
";\n";
2538 g <<
"default: return -1;\n}\n"
2545 g <<
"#ifdef MATLAB_MEX_FILE\n";
2548 g <<
"void mex_" <<
name_
2549 <<
"(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {\n"
2550 <<
"casadi_int i;\n";
2555 for (casadi_int i=0; i<
n_in_; ++i) {
2560 sz_w += i_nnz + o_nnz;
2563 std::string fw =
"w+" +
str(i_nnz + o_nnz);
2566 casadi_int offset=0;
2570 g <<
"casadi_real* res[" <<
sz_res() <<
"] = {0};\n";
2573 g <<
"if (argc>" <<
n_in_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2574 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. Too many input arguments "
2575 <<
"(%d, max " <<
n_in_ <<
")\", argc);\n";
2577 g <<
"if (resc>" <<
n_out_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2578 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. "
2579 <<
"Too many output arguments (%d, max " <<
n_out_ <<
")\", resc);\n";
2581 for (casadi_int i=0; i<
n_in_; ++i) {
2582 std::string p =
"argv[" +
str(i) +
"]";
2583 g <<
"if (--argc>=0) arg[" << i <<
"] = "
2588 for (casadi_int i=0; i<
n_out_; ++i) {
2594 g <<
"if (--resc>=0) ";
2597 g << g.
res(i) <<
" = w+" <<
str(offset) <<
";\n";
2600 g <<
name_ <<
"_incref();\n";
2601 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2604 g <<
"i = " <<
name_ <<
"(arg, res, iw, " << fw <<
", mem);\n"
2605 <<
"if (i) mexErrMsgIdAndTxt(\"Casadi:RuntimeError\",\"Evaluation of \\\"" <<
name_
2606 <<
"\\\" failed.\");\n";
2607 g <<
name_ <<
"_release(mem);\n";
2608 g <<
name_ <<
"_decref();\n";
2611 for (casadi_int i=0; i<
n_out_; ++i) {
2612 g <<
"if (" << g.
res(i) <<
") resv[" << i <<
"] = "
2623 g <<
"casadi_int main_" <<
name_ <<
"(casadi_int argc, char* argv[]) {\n";
2625 g <<
"casadi_int j;\n";
2626 g <<
"casadi_real* a;\n";
2627 g <<
"const casadi_real* r;\n";
2628 g <<
"casadi_int flag;\n";
2629 if (needs_mem) g <<
"int mem;\n";
2639 g <<
"const casadi_real* arg[" <<
sz_arg() <<
"];\n";
2642 g <<
"casadi_real* res[" <<
sz_res() <<
"];\n";
2645 for (casadi_int i=0; i<
n_in_; ++i) {
2646 g <<
"arg[" << i <<
"] = w+" << off <<
";\n";
2649 for (casadi_int i=0; i<
n_out_; ++i) {
2650 g <<
"res[" << i <<
"] = w+" << off <<
";\n";
2656 <<
"for (j=0; j<" <<
nnz_in() <<
"; ++j) "
2657 <<
"if (scanf(\"%lg\", a++)<=0) return 2;\n";
2660 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2664 g <<
"flag = " <<
name_ <<
"(arg, res, iw, w+" << off <<
", ";
2672 g <<
name_ <<
"_release(mem);\n";
2674 g <<
"if (flag) return flag;\n";
2677 g <<
"r = w+" <<
nnz_in() <<
";\n"
2678 <<
"for (j=0; j<" <<
nnz_out() <<
"; ++j) "
2679 << g.
printf(
"%g ",
"*r++") <<
"\n";
2682 g << g.
printf(
"\\n") <<
"\n";
2691 g << g.
declare(
"casadi_functions* " +
name_ +
"_functions(void)") <<
" {\n"
2692 <<
"static casadi_functions fun = {\n"
2693 <<
name_ <<
"_incref,\n"
2694 <<
name_ <<
"_decref,\n"
2695 <<
name_ <<
"_checkout,\n"
2696 <<
name_ <<
"_release,\n"
2697 <<
name_ <<
"_default_in,\n"
2701 <<
name_ <<
"_n_in,\n"
2702 <<
name_ <<
"_n_out,\n"
2703 <<
name_ <<
"_name_in,\n"
2704 <<
name_ <<
"_name_out,\n"
2705 <<
name_ <<
"_sparsity_in,\n"
2706 <<
name_ <<
"_sparsity_out,\n"
2707 <<
name_ <<
"_work,\n"
2721 if (e.f.get()==
this)
return e.codegen_name;
2726 if (e.f.get()==
this)
return "f" +
str(i);
2729 casadi_error(
"Function '" +
name_ +
"' not found");
2734 std::string mem_array = g.
shorthand(name +
"_mem");
2735 return mem_array+
"[" + index +
"]";
2743 casadi_warning(
"The function \"" +
name_ +
"\", which is of type \""
2744 +
class_name() +
"\" cannot be code generated. The generation "
2745 "will proceed, but compilation of the code will not be possible.");
2746 g <<
"#error Code generation not supported for " <<
class_name() <<
"\n";
2751 casadi_error(
"'generate_dependencies' not defined for " +
class_name());
2757 for (casadi_int oind=0; oind<
n_out_; ++oind) {
2759 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
2763 for (casadi_int iind=0; iind<
n_in_; ++iind) {
2765 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
2774 casadi_int* iw,
bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const {
2779 casadi_int d1 = sp.
size2();
2780 const casadi_int *colind = sp.
colind(), *row = sp.
row();
2781 for (casadi_int cc=0; cc<d1; ++cc) {
2782 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
2783 res[oind][row[el]] |= arg[iind][cc];
2792 for (casadi_int oind=0; oind<
n_out_; ++oind) {
2794 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
2797 for (casadi_int iind=0; iind<
n_in_; ++iind) {
2799 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
2806 casadi_int d1 = sp.
size2();
2807 const casadi_int *colind = sp.
colind(), *row = sp.
row();
2808 for (casadi_int cc=0; cc<d1; ++cc) {
2809 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
2810 arg[iind][cc] |= res[oind][row[el]];
2822 size_t& sz_iw,
size_t& sz_w)
const {
2825 sz_iw = this->
sz_iw();
2826 sz_w = this->
sz_w();
2846 sz_arg_tmp_ = std::max(sz_arg_tmp_,
sz_arg);
2854 sz_res_tmp_ = std::max(sz_res_tmp_,
sz_res);
2860 sz_iw_per_ +=
sz_iw;
2862 sz_iw_tmp_ = std::max(sz_iw_tmp_,
sz_iw);
2870 sz_w_tmp_ = std::max(sz_w_tmp_,
sz_w);
2888 for (
const auto& s : m->fstats) {
2889 stats[
"n_call_" +s.first] = s.second.n_call;
2890 stats[
"t_wall_" +s.first] = s.second.t_wall;
2891 stats[
"t_proc_" +s.first] = s.second.t_proc;
2899 casadi_assert(m->stats_available,
2900 "No stats available: Function '" +
name_ +
"' not set up. "
2901 "To get statistics, first evaluate it numerically.");
2946 call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
2947 const std::vector<std::vector<MX> >& fseed,
2948 std::vector<std::vector<MX> >& fsens,
2949 bool always_inline,
bool never_inline)
const {
2950 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
2951 casadi_assert(!always_inline,
"Class " +
class_name() +
2952 " cannot be inlined in an MX expression");
2956 "Derivatives cannot be calculated for " +
name_);
2959 casadi_int nfwd = fseed.size();
2963 if (nfwd==0)
return;
2966 casadi_int npar = 1;
2967 for (
auto&& r : fseed) {
2970 fsens, always_inline, never_inline);
2977 std::vector<MX> darg = arg;
2978 darg.insert(darg.end(), res.begin(), res.end());
2979 std::vector<MX> J =
jacobian()(darg);
2981 std::vector<MX> v(nfwd), all_fseed(
n_in_);
2982 for (
size_t i = 0; i <
n_in_; ++i) {
2983 for (
size_t d = 0; d < nfwd; ++d) v[d] = vec(fseed.at(d).at(i));
2984 all_fseed[i] = horzcat(v);
2987 std::vector<MX> all_fsens(
n_out_);
2988 std::vector<MX>::const_iterator J_it = J.begin();
2989 for (
size_t oind = 0; oind <
n_out_; ++oind) {
2990 for (
size_t iind = 0; iind <
n_in_; ++iind) {
2992 MX a = mtimes(*J_it++, all_fseed[iind]);
2993 all_fsens[oind] = all_fsens[oind].is_empty(
true) ? a : all_fsens[oind] + a;
2997 for (
size_t d = 0; d < nfwd; ++d) fsens[d].resize(
n_out_);
2998 for (
size_t i = 0; i <
n_out_; ++i) {
2999 v = horzsplit(all_fsens[i]);
3000 casadi_assert_dev(v.size() == nfwd);
3001 for (
size_t d = 0; d < nfwd; ++d) fsens[d][i] = reshape(v[d],
size_out(i));
3010 casadi_int offset = 0;
3011 while (offset<nfwd) {
3013 casadi_int nfwd_batch = std::min(nfwd-offset, max_nfwd);
3016 std::vector<MX> darg;
3018 darg.insert(darg.end(), arg.begin(), arg.end());
3019 darg.insert(darg.end(), res.begin(), res.end());
3020 std::vector<MX> v(nfwd_batch);
3021 for (casadi_int i=0; i<
n_in_; ++i) {
3022 for (casadi_int d=0; d<nfwd_batch; ++d) v[d] = fseed[offset+d][i];
3023 darg.push_back(horzcat(v));
3028 std::vector<MX> x = dfcn(darg);
3030 casadi_assert_dev(x.size()==
n_out_);
3033 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d].resize(
n_out_);
3034 for (casadi_int i=0; i<
n_out_; ++i) {
3037 casadi_assert_dev(v.size()==nfwd_batch);
3039 v = std::vector<MX>(nfwd_batch,
MX(
size_out(i)));
3041 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d][i] = v[d];
3045 offset += nfwd_batch;
3051 call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3052 const std::vector<std::vector<MX> >& aseed,
3053 std::vector<std::vector<MX> >& asens,
3054 bool always_inline,
bool never_inline)
const {
3055 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3056 casadi_assert(!always_inline,
"Class " +
class_name() +
3057 " cannot be inlined in an MX expression");
3061 "Derivatives cannot be calculated for " +
name_);
3064 casadi_int nadj = aseed.size();
3068 if (nadj==0)
return;
3071 casadi_int npar = 1;
3072 for (
auto&& r : aseed) {
3075 asens, always_inline, never_inline);
3082 std::vector<MX> darg = arg;
3083 darg.insert(darg.end(), res.begin(), res.end());
3084 std::vector<MX> J =
jacobian()(darg);
3086 std::vector<MX> v(nadj), all_aseed(
n_out_);
3087 for (
size_t i = 0; i <
n_out_; ++i) {
3088 for (
size_t d = 0; d < nadj; ++d) v[d] = vec(aseed.at(d).at(i));
3089 all_aseed[i] = horzcat(v);
3092 std::vector<MX> all_asens(
n_in_);
3093 std::vector<MX>::const_iterator J_it = J.begin();
3094 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3095 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3097 MX a = mtimes((*J_it++).
T(), all_aseed[oind]);
3098 all_asens[iind] = all_asens[iind].is_empty(
true) ? a : all_asens[iind] + a;
3102 for (
size_t d = 0; d < nadj; ++d) asens[d].resize(
n_in_);
3103 for (
size_t i = 0; i <
n_in_; ++i) {
3104 v = horzsplit(all_asens[i]);
3105 casadi_assert_dev(v.size() == nadj);
3106 for (
size_t d = 0; d < nadj; ++d) {
3107 if (asens[d][i].is_empty(
true)) {
3108 asens[d][i] = reshape(v[d],
size_in(i));
3110 asens[d][i] += reshape(v[d],
size_in(i));
3120 casadi_int offset = 0;
3121 while (offset<nadj) {
3123 casadi_int nadj_batch = std::min(nadj-offset, max_nadj);
3126 std::vector<MX> darg;
3128 darg.insert(darg.end(), arg.begin(), arg.end());
3129 darg.insert(darg.end(), res.begin(), res.end());
3130 std::vector<MX> v(nadj_batch);
3131 for (casadi_int i=0; i<
n_out_; ++i) {
3132 for (casadi_int d=0; d<nadj_batch; ++d) v[d] = aseed[offset+d][i];
3133 darg.push_back(horzcat(v));
3138 std::vector<MX> x = dfcn(darg);
3139 casadi_assert_dev(x.size()==
n_in_);
3142 for (casadi_int d=0; d<nadj_batch; ++d) asens[offset+d].resize(
n_in_);
3143 for (casadi_int i=0; i<
n_in_; ++i) {
3146 casadi_assert_dev(v.size()==nadj_batch);
3148 v = std::vector<MX>(nadj_batch,
MX(
size_in(i)));
3150 for (casadi_int d=0; d<nadj_batch; ++d) {
3151 if (asens[offset+d][i].is_empty(
true)) {
3152 asens[offset+d][i] = v[d];
3154 asens[offset+d][i] += v[d];
3159 offset += nadj_batch;
3165 call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3166 const std::vector<std::vector<SX> >& fseed,
3167 std::vector<std::vector<SX> >& fsens,
3168 bool always_inline,
bool never_inline)
const {
3169 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3170 if (fseed.empty()) {
3174 casadi_error(
"'forward' (SX) not defined for " +
class_name());
3178 call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3179 const std::vector<std::vector<SX> >& aseed,
3180 std::vector<std::vector<SX> >& asens,
3181 bool always_inline,
bool never_inline)
const {
3182 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3183 if (aseed.empty()) {
3187 casadi_error(
"'reverse' (SX) not defined for " +
class_name());
3229 std::vector<SX> ret(
n_in_);
3230 for (casadi_int i=0; i<ret.size(); ++i) {
3237 std::vector<SX> ret(
n_out_);
3238 for (casadi_int i=0; i<ret.size(); ++i) {
3245 std::vector<DM> ret(
n_in_);
3246 for (casadi_int i=0; i<ret.size(); ++i) {
3253 std::vector<DM> ret(
n_out_);
3254 for (casadi_int i=0; i<ret.size(); ++i) {
3269 std::vector<MX> ret(
n_in_);
3270 for (casadi_int i=0; i<ret.size(); ++i) {
3277 std::vector<MX> ret(
n_out_);
3278 for (casadi_int i=0; i<ret.size(); ++i) {
3285 return type ==
"FunctionInternal";
3289 std::vector<MX>& subs_from, std::vector<MX>& subs_to)
const {
3294 casadi_error(
"'free_mx' only defined for 'MXFunction'");
3298 casadi_error(
"'free_sx' only defined for 'SXFunction'");
3303 casadi_error(
"'generate_lifted' only defined for 'MXFunction'");
3307 casadi_error(
"'n_instructions' not defined for " +
class_name());
3311 casadi_error(
"'instruction_id' not defined for " +
class_name());
3315 casadi_error(
"'instruction_input' not defined for " +
class_name());
3319 casadi_error(
"'instruction_constant' not defined for " +
class_name());
3323 casadi_error(
"'instruction_output' not defined for " +
class_name());
3327 casadi_error(
"'instruction_MX' not defined for " +
class_name());
3331 casadi_error(
"'instructions_sx' not defined for " +
class_name());
3335 casadi_error(
"'n_nodes' not defined for " +
class_name());
3340 const std::string& parallelization) {
3341 if (x.empty())
return x;
3343 casadi_assert(x.size()==
n_in_,
"mapsum_mx: Wrong number_i of arguments");
3345 casadi_int npar = 1;
3347 std::vector<MX> x_mod(x.size());
3348 for (casadi_int i=0; i<
n_in_; ++i) {
3359 for (casadi_int i=0; i<x_mod.size(); ++i) {
3360 n = std::max(x_mod[i].size2() /
size2_in(i), n);
3363 std::vector<casadi_int> reduce_in;
3364 for (casadi_int i=0; i<x_mod.size(); ++i) {
3365 if (x_mod[i].size2()/
size2_in(i)!=n) {
3366 reduce_in.push_back(i);
3378 if (arg.
size()==inp.
size())
return true;
3388 if (npar==-1)
return false;
3400 casadi_assert(
nnz_in()==arg.size(),
3401 "Dimension mismatch. Expecting " +
str(
nnz_in()) +
3402 ", got " +
str(arg.size()) +
" instead.");
3404 std::vector<DM> ret =
dm_in();
3405 casadi_int offset = 0;
3406 for (casadi_int i=0;i<
n_in_;++i) {
3408 std::copy(arg.begin()+offset, arg.begin()+offset+
nnz_in(i), r.
ptr());
3415 casadi_assert(
nnz_out()==res.size(),
3416 "Dimension mismatch. Expecting " +
str(
nnz_out()) +
3417 ", got " +
str(res.size()) +
" instead.");
3419 std::vector<DM> ret =
dm_out();
3420 casadi_int offset = 0;
3421 for (casadi_int i=0;i<
n_out_;++i) {
3423 std::copy(res.begin()+offset, res.begin()+offset+
nnz_out(i), r.
ptr());
3431 casadi_int npar = -1;
3437 std::vector<double> ret(
nnz_in());
3438 casadi_int offset = 0;
3439 for (casadi_int i=0;i<
n_in_;++i) {
3440 const double* e = arg2.at(i).ptr();
3441 std::copy(e, e+
nnz_in(i), ret.begin()+offset);
3449 casadi_int npar = -1;
3455 std::vector<double> ret(
nnz_out());
3456 casadi_int offset = 0;
3457 for (casadi_int i=0;i<
n_out_;++i) {
3458 const double* e = res2.at(i).ptr();
3459 std::copy(e, e+
nnz_out(i), ret.begin()+offset);
3466 casadi_int* iw,
double* w)
const {
3474 for (
auto&& i : mem_) {
3483 if (
name_ ==
"jac_" + n) {
3485 }
else if (
name_ ==
"adj1_" + n) {
3496 if (
name_ ==
"jac_" + n) {
3498 }
else if (
name_ ==
"adj1_" + n) {
3509 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
3530 if (
name_ ==
"jac_" + n) {
3544 std::vector<casadi_int> row, colind;
3545 row.reserve(sp_out.
nnz() * sp_in.
nnz());
3546 colind.reserve(sp_in.
numel() + 1);
3548 for (casadi_int c1 = 0; c1 < sp_in.
size2(); ++c1) {
3549 for (casadi_int k1 = sp_in.
colind(c1); k1 < sp_in.
colind(c1 + 1); ++k1) {
3550 casadi_int e1 = sp_in.
row(k1) + sp_in.
size1() * c1;
3552 colind.resize(e1 + 1, row.size());
3554 for (casadi_int c2 = 0; c2 < sp_out.
size2(); ++c2) {
3555 for (casadi_int k2 = sp_out.
colind(c2); k2 < sp_out.
colind(c2 + 1); ++k2) {
3556 row.push_back(sp_out.
row(k2) + sp_out.
size1() * c2);
3562 colind.resize(sp_in.
numel() + 1, row.size());
3565 }
else if (
name_ ==
"adj1_" + n) {
3575 #ifdef CASADI_WITH_THREAD
3576 std::lock_guard<std::mutex> lock(mtx_);
3578 return mem_.at(ind);
3582 return ind<mem_.size();
3586 #ifdef CASADI_WITH_THREAD
3587 std::lock_guard<std::mutex> lock(mtx_);
3589 if (unused_.empty()) {
3595 casadi_error(
"Failed to create or initialize memory object");
3597 return static_cast<int>(mem_.size()) - 1;
3600 int m = unused_.top();
3607 #ifdef CASADI_WITH_THREAD
3608 std::lock_guard<std::mutex> lock(mtx_);
3614 factory(
const std::string& name,
3615 const std::vector<std::string>& s_in,
3616 const std::vector<std::string>& s_out,
3618 const Dict& opts)
const {
3619 return wrap().
factory(name, s_in, s_out, aux, opts);
3624 return std::vector<std::string>();
3628 casadi_error(
"'get_function' not defined for " +
class_name());
3634 const Function& dep, casadi_int max_depth)
const {
3636 if (!dep.
is_null() && all_fun.find(dep.
get()) == all_fun.end()) {
3638 all_fun[dep.
get()] = dep;
3640 if (max_depth > 0) dep->
find(all_fun, max_depth - 1);
3645 which_depends(
const std::string& s_in,
const std::vector<std::string>& s_out,
3646 casadi_int order,
bool tr)
const {
3647 Function f = shared_from_this<Function>();
3653 casadi_error(
"'oracle' not defined for " +
class_name());
3659 const std::vector<casadi_int>& order_in,
3660 const std::vector<casadi_int>& order_out,
const Dict& opts)
const {
3661 return wrap().
slice(name, order_in, order_out, opts);
3666 for (casadi_int i=0; i<
n_in_; ++i) {
3670 for (casadi_int i=0; i<
n_out_; ++i) {
3678 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3680 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
3682 casadi_int ind = iind + oind *
n_in_;
3690 eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
3695 std::vector<DM> argv(
n_in_);
3696 for (casadi_int i=0; i<
n_in_; ++i) {
3698 casadi_copy(arg[i], argv[i].nnz(), argv[i].ptr());
3702 std::vector<DM> resv =
eval_dm(argv);
3705 casadi_assert(resv.size()==
n_out_,
3706 "Expected " +
str(
n_out_) +
" outputs, got " +
str(resv.size()) +
".");
3709 for (casadi_int i=0; i<
n_out_; ++i) {
3714 casadi_error(
"Shape mismatch for output " +
str(i) +
": got " + resv[i].dim() +
", "
3718 if (res[i])
casadi_copy(resv[i].ptr(), resv[i].nnz(), res[i]);
3722 }
catch(std::exception& e) {
3723 casadi_error(
"Failed to evaluate 'eval_dm' for " +
name_ +
":\n" + e.what());
3728 casadi_error(
"'eval' not defined for " +
class_name());
3737 for (
auto &&s : fstats) {
3738 name_len = std::max(s.first.size(), name_len);
3740 name_len = std::max(
name_.size(), name_len);
3744 sprint(namefmt,
sizeof(namefmt),
"%%%ds ",
static_cast<casadi_int
>(name_len));
3749 print(
" : %8s %10s %8s %10s %9s\n",
"t_proc",
"(avg)",
"t_wall",
"(avg)",
"n_eval");
3752 char buffer_proc[10];
3753 char buffer_wall[10];
3754 char buffer_proc_avg[10];
3755 char buffer_wall_avg[10];
3758 for (
const auto &s : fstats) {
3759 if (s.second.n_call!=0) {
3760 print(namefmt, s.first.c_str());
3763 format_time(buffer_proc_avg, s.second.t_proc/s.second.n_call);
3764 format_time(buffer_wall_avg, s.second.t_wall/s.second.n_call);
3765 print(
" | %s (%s) %s (%s) %9d\n",
3766 buffer_proc, buffer_proc_avg,
3767 buffer_wall, buffer_wall_avg, s.second.n_call);
3774 casadi_assert_dev(time>=0);
3775 double log_time = log10(time);
3776 int magn =
static_cast<int>(floor(log_time));
3777 int iprefix =
static_cast<int>(floor(log_time/3));
3779 sprint(buffer, 10,
" 0");
3783 sprint(buffer, 10,
" inf");
3786 char prefixes[] =
"TGMk munp";
3787 char prefix = prefixes[4-iprefix];
3789 int rem = magn-3*iprefix;
3790 double time_normalized = time/pow(10, 3*iprefix);
3793 sprint(buffer, 10,
" %1.2f%cs", time_normalized, prefix);
3794 }
else if (rem==1) {
3795 sprint(buffer, 10,
" %2.2f%cs", time_normalized, prefix);
3797 sprint(buffer, 10,
"%3.2f%cs", time_normalized, prefix);
3804 va_start(args, fmt);
3806 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
3810 casadi_assert(n>=0 && n<buf_sz,
"Print failure while processing '" + std::string(fmt) +
"'");
3816 va_start(args, fmt);
3819 size_t buf_sz =
sizeof(buf);
3820 char* buf_dyn =
nullptr;
3822 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
3824 if (n>
static_cast<casadi_int
>(buf_sz)) {
3825 buf_sz =
static_cast<size_t>(n+1);
3826 buf_dyn =
new char[buf_sz];
3827 n = vsnprintf(buf_dyn, buf_sz, fmt, args);
3830 if (n>=0)
uout() << (buf_dyn ? buf_dyn : buf) << std::flush;
3835 casadi_assert(n>=0,
"Print failure while processing '" + std::string(fmt) +
"'");
3840 bool always_inline,
bool never_inline)
const {
3842 eval_mx(arg, res, always_inline, never_inline);
3845 std::vector<std::vector<MX>> v(npar, arg);
3847 for (
int i=0; i<
n_in_; ++i) {
3849 t = horzsplit(arg[i],
size2_in(i));
3850 casadi_assert_dev(t.size()==npar);
3851 for (
int p=0; p<npar; ++p) v[p][i] = t[p];
3855 for (
int p=0; p<npar; ++p) {
3856 eval_mx(v[p], t, always_inline, never_inline);
3862 for (
int i=0; i<
n_out_; ++i) {
3863 for (
int p=0; p<npar; ++p) t[p] = v[p][i];
3864 res[i] = horzcat(t);
3874 default:
return "SOLVER_RET_UNKNOWN";
3879 s.
version(
"ProtoFunction", 2);
3889 int version = s.
version(
"ProtoFunction", 1, 2);
3904 s.
version(
"FunctionInternal", 6);
3912 s.
pack(
"FunctionInternal::jit",
jit_);
3919 casadi_assert(binary.good(),
"Could not open library '" +
compiler_.
library() +
"'.");
3920 s.
pack(
"FunctionInternal::jit_binary", binary);
3969 s.
pack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
3970 s.
pack(
"FunctionInternal::sz_res_per", sz_res_per_);
3971 s.
pack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
3972 s.
pack(
"FunctionInternal::sz_w_per", sz_w_per_);
3973 s.
pack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
3974 s.
pack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
3975 s.
pack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
3976 s.
pack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
3980 int version = s.
version(
"FunctionInternal", 1, 6);
3996 std::string library;
3997 s.
unpack(
"FunctionInternal::jit_library", library);
4000 std::ifstream binary(library, std::ios_base::binary);
4001 if (binary.good()) {
4003 std::stringstream ss;
4004 s.
unpack(
"FunctionInternal::jit_binary", ss);
4006 std::ofstream binary(library, std::ios_base::binary | std::ios_base::out);
4007 s.
unpack(
"FunctionInternal::jit_binary", binary);
4073 s.
unpack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4074 s.
unpack(
"FunctionInternal::sz_res_per", sz_res_per_);
4075 s.
unpack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4076 s.
unpack(
"FunctionInternal::sz_w_per", sz_w_per_);
4077 s.
unpack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4078 s.
unpack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4079 s.
unpack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4080 s.
unpack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4096 std::string base_function;
4097 s.
unpack(
"FunctionInternal::base_function", base_function);
4100 "FunctionInternal::deserialize: not found '" + base_function +
"'");
4103 ret.
own(it->second(s));
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static int eval_sx(const Function &f, const SXElem **arg, SXElem **res)
static std::vector< MX > create(const Function &fcn, const std::vector< MX > &arg)
Create function call node.
Helper class for C code generation.
void add_io_sparsities(const std::string &name, const std::vector< Sparsity > &sp_in, const std::vector< Sparsity > &sp_out)
Add io sparsity patterns of a function.
void scope_enter()
Enter a local scope.
std::string constant(const std::vector< casadi_int > &v)
Represent an array constant; adding it when new.
void add(const Function &f, bool with_jac_sparsity=false)
Add a function (name generated)
void flush(std::ostream &s)
Flush the buffer to a stream of choice.
std::string to_mex(const Sparsity &sp, const std::string &arg)
Create matrix in MATLAB's MEX format.
std::string printf(const std::string &str, const std::vector< std::string > &arg=std::vector< std::string >())
Printf.
static std::string array(const std::string &type, const std::string &name, casadi_int len, const std::string &def=std::string())
std::string generate(const std::string &prefix="")
Generate file(s)
std::string from_mex(std::string &arg, const std::string &res, std::size_t res_off, const Sparsity &sp_res, const std::string &w)
Get matrix from MATLAB's MEX format.
std::string res(casadi_int i) const
Refer to resuly.
std::string declare(std::string s)
Declare a function.
void scope_exit()
Exit a local scope.
std::vector< FunctionMeta > added_functions_
std::string shorthand(const std::string &name) const
Get a shorthand.
std::stringstream auxiliaries
void deserialize(DeserializingStream &s, SDPToSOCPMem &m)
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static void open(std::ofstream &, const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
bool has_refcount_
Reference counting in codegen?
casadi_int size1_in(casadi_int ind) const
Input/output dimensions.
virtual std::string codegen_mem_type() const
Thread-local memory object type.
std::string jit_serialize_
Serialize behaviour.
std::string diff_prefix(const std::string &prefix) const
Determine prefix for differentiated functions.
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
Dict get_stats(void *mem) const override
Get all statistics.
void init(const Dict &opts) override
Initialize.
virtual void call_forward(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &fseed, std::vector< std::vector< MX > > &fsens, bool always_inline, bool never_inline) const
Forward mode AD, virtual functions overloaded in derived classes.
void finalize() override
Finalize the object creation.
std::vector< M > project_arg(const std::vector< M > &arg, casadi_int npar) const
Project sparsities.
Function forward(casadi_int nfwd) const
Return function that calculates forward derivatives.
virtual bool has_sprev() const
Is the class able to propagate seeds through the algorithm?
virtual size_t codegen_sz_res(const CodeGenerator &g) const
Get required lengths, for codegen.
const std::vector< DM > dm_in() const
Get function input(s) and output(s)
virtual Function slice(const std::string &name, const std::vector< casadi_int > &order_in, const std::vector< casadi_int > &order_out, const Dict &opts) const
returns a new function with a selection of inputs/outputs of the original
void tocache_if_missing(Function &f, const std::string &suffix="") const
Save function to cache, only if missing.
Function map(casadi_int n, const std::string ¶llelization) const
Generate/retrieve cached serial map.
double jac_penalty_
Penalty factor for using a complete Jacobian to calculate directional derivatives.
void call_gen(const MXVector &arg, MXVector &res, casadi_int npar, bool always_inline, bool never_inline) const
Call a function, overloaded.
virtual casadi_int n_nodes() const
Number of nodes in the algorithm.
std::vector< Sparsity > sparsity_in_
Input and output sparsity.
std::vector< Sparsity > jac_sparsity_[2]
Cache for sparsities of the Jacobian blocks.
virtual double ad_weight() const
Weighting factor for chosing forward/reverse mode.
virtual const std::vector< SX > sx_in() const
Get function input(s) and output(s)
static Function deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
virtual void export_code(const std::string &lang, std::ostream &stream, const Dict &options) const
Export function in a specific language.
virtual bool has_forward(casadi_int nfwd) const
Return function that calculates forward derivatives.
void print_in(std::ostream &stream, const double **arg, bool truncate) const
Print inputs.
void generate_in(const std::string &fname, const double **arg) const
Export an input file that can be passed to generate C code with a main.
static std::string forward_name(const std::string &fcn, casadi_int nfwd)
Helper function: Get name of forward derivative function.
virtual void jit_dependencies(const std::string &fname)
Jit dependencies.
virtual size_t codegen_sz_arg(const CodeGenerator &g) const
Get required lengths, for codegen.
void check_arg(const std::vector< M > &arg, casadi_int &npar) const
Check if input arguments have correct length and dimensions.
std::vector< std::vector< M > > replace_fseed(const std::vector< std::vector< M >> &fseed, casadi_int npar) const
Replace 0-by-0 forward seeds.
std::vector< bool > is_diff_out_
virtual bool adjViaJac(casadi_int nadj) const
Calculate derivatives by multiplying the full Jacobian and multiplying.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
virtual MX instruction_MX(casadi_int k) const
get MX expression associated with instruction
void alloc_res(size_t sz_res, bool persistent=false)
Ensure required length of res field.
std::string jit_name_
Name if jit source file.
std::string compiler_plugin_
Just-in-time compiler.
virtual Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux, const Dict &opts) const
virtual size_t codegen_sz_iw(const CodeGenerator &g) const
Get required lengths, for codegen.
casadi_release_t release_
Release redirected to a C function.
std::pair< casadi_int, casadi_int > size_in(casadi_int ind) const
Input/output dimensions.
virtual bool has_eval_dm() const
Evaluate with DM matrices.
virtual int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const
Evaluate numerically.
virtual void codegen_incref(CodeGenerator &g) const
Codegen incref for dependencies.
casadi_int numel_out() const
Number of input/output elements.
Function custom_jacobian_
std::string definition() const
Get function signature: name:(inputs)->(outputs)
virtual void find(std::map< FunctionInternal *, Function > &all_fun, casadi_int max_depth) const
const Sparsity & sparsity_in(casadi_int ind) const
Input/output sparsity.
Sparsity to_compact(casadi_int oind, casadi_int iind, const Sparsity &sp) const
Convert to compact Jacobian sparsity pattern.
Sparsity get_jac_sparsity_hierarchical_symm(casadi_int oind, casadi_int iind) const
void * user_data_
User-set field.
std::vector< M > replace_arg(const std::vector< M > &arg, casadi_int npar) const
Replace 0-by-0 inputs.
virtual const std::vector< MX > mx_in() const
Get function input(s) and output(s)
virtual void call_reverse(const std::vector< MX > &arg, const std::vector< MX > &res, const std::vector< std::vector< MX > > &aseed, std::vector< std::vector< MX > > &asens, bool always_inline, bool never_inline) const
Reverse mode, virtual functions overloaded in derived classes.
virtual bool has_jac_sparsity(casadi_int oind, casadi_int iind) const
Get Jacobian sparsity.
void alloc_arg(size_t sz_arg, bool persistent=false)
Ensure required length of arg field.
void print_dimensions(std::ostream &stream) const
Print dimensions of inputs and outputs.
virtual void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const
Set the (persistent) work vectors.
std::string jit_base_name_
std::string signature_unrolled(const std::string &fname) const
Code generate the function.
virtual size_t codegen_sz_w(const CodeGenerator &g) const
Get required lengths, for codegen.
virtual bool is_a(const std::string &type, bool recursive) const
Check if the function is of a particular type.
const std::vector< DM > dm_out() const
Get function input(s) and output(s)
Sparsity & jac_sparsity(casadi_int oind, casadi_int iind, bool compact, bool symmetric) const
Get Jacobian sparsity.
static std::map< std::string, ProtoFunction *(*)(DeserializingStream &)> deserialize_map
double ad_weight_
Weighting factor for derivative calculation and sparsity pattern calculation.
casadi_int numel_in() const
Number of input/output elements.
virtual bool has_jacobian() const
Return Jacobian of all input elements with respect to all output elements.
Sparsity from_compact(casadi_int oind, casadi_int iind, const Sparsity &sp) const
Convert from compact Jacobian sparsity pattern.
~FunctionInternal() override=0
Destructor.
void set_jac_sparsity(casadi_int oind, casadi_int iind, const Sparsity &sp)
Populate jac_sparsity_ and jac_sparsity_compact_ during initialization.
bool inputs_check_
Errors are thrown if numerical values of inputs look bad.
virtual std::vector< SX > free_sx() const
Get free variables (SX)
bool jit_
Use just-in-time compiler.
eval_t eval_
Numerical evaluation redirected to a C function.
bool has_derivative() const
Can derivatives be calculated in any way?
virtual std::vector< std::string > get_free() const
Print free variables.
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
virtual std::vector< MX > free_mx() const
Get free variables (MX)
void * alloc_mem() const override
Create memory block.
virtual bool uses_output() const
Do the derivative functions need nondifferentiated outputs?
virtual double sp_weight() const
Weighting factor for chosing forward/reverse mode,.
std::string codegen_mem(CodeGenerator &g, const std::string &index="mem") const
Get thread-local memory object.
virtual SX instructions_sx() const
get SX expression associated with instructions
Sparsity get_jac_sparsity_hierarchical(casadi_int oind, casadi_int iind) const
A flavor of get_jac_sparsity_gen that does hierarchical block structure recognition.
virtual void generate_lifted(Function &vdef_fcn, Function &vinit_fcn) const
Extract the functions needed for the Lifted Newton method.
bool incache(const std::string &fname, Function &f, const std::string &suffix="") const
Get function in cache.
virtual std::string codegen_name(const CodeGenerator &g, bool ns=true) const
Get name in codegen.
size_t n_in_
Number of inputs and outputs.
void codegen(CodeGenerator &g, const std::string &fname) const
Generate code the function.
virtual casadi_int instruction_id(casadi_int k) const
Get an atomic operation operator index.
size_t sz_res() const
Get required length of res field.
virtual void eval_mx(const MXVector &arg, MXVector &res, bool always_inline, bool never_inline) const
Evaluate with symbolic matrices.
virtual void codegen_release(CodeGenerator &g) const
Codegen for release.
virtual std::vector< casadi_int > instruction_input(casadi_int k) const
Get the (integer) input arguments of an atomic operation.
virtual size_t get_n_out()
Are all inputs and outputs scalar.
virtual void codegen_body(CodeGenerator &g) const
Generate code for the function body.
virtual int eval_sx(const SXElem **arg, SXElem **res, casadi_int *iw, SXElem *w, void *mem, bool always_inline, bool never_inline) const
Evaluate with symbolic scalars.
casadi_int size2_out(casadi_int ind) const
Input/output dimensions.
virtual void codegen_alloc_mem(CodeGenerator &g) const
Codegen decref for alloc_mem.
virtual void set_temp(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (temporary) work vectors.
bool matching_arg(const std::vector< M > &arg, casadi_int &npar) const
Check if input arguments that needs to be replaced.
std::vector< M > project_res(const std::vector< M > &arg, casadi_int npar) const
Project sparsities.
casadi_int size1_out(casadi_int ind) const
Input/output dimensions.
virtual void codegen_checkout(CodeGenerator &g) const
Codegen for checkout.
void get_partition(casadi_int iind, casadi_int oind, Sparsity &D1, Sparsity &D2, bool compact, bool symmetric, bool allow_forward, bool allow_reverse) const
Get the unidirectional or bidirectional partition.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Input/output dimensions.
WeakCache< std::string, Function > cache_
Function cache.
virtual int sp_forward(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const
Propagate sparsity forward.
casadi_checkout_t checkout_
Checkout redirected to a C function.
std::vector< double > nz_in(const std::vector< DM > &arg) const
Convert from/to flat vector of input/output nonzeros.
casadi_int nnz_in() const
Number of input/output nonzeros.
virtual void disp_more(std::ostream &stream) const
Print more.
static const Options options_
Options.
virtual std::vector< DM > eval_dm(const std::vector< DM > &arg) const
Evaluate with DM matrices.
FunctionInternal(const std::string &name)
Constructor.
std::vector< MX > mapsum_mx(const std::vector< MX > &arg, const std::string ¶llelization)
Parallel evaluation.
virtual 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
Return function that calculates adjoint derivatives.
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.
std::vector< Sparsity > sparsity_out_
Function reverse(casadi_int nadj) const
Return function that calculates adjoint derivatives.
std::vector< M > replace_res(const std::vector< M > &res, casadi_int npar) const
Replace 0-by-0 outputs.
virtual const Function & oracle() const
Get oracle.
virtual bool get_diff_in(casadi_int i)
Which inputs are differentiable.
bool jit_temp_suffix_
Use a temporary name.
virtual std::vector< std::string > get_function() const
void serialize_type(SerializingStream &s) const override
Serialize type information.
virtual std::string get_name_out(casadi_int i)
Names of function input and outputs.
casadi_int max_num_dir_
Maximum number of sensitivity directions.
virtual double instruction_constant(casadi_int k) const
Get the floating point output argument of an atomic operation.
virtual bool fwdViaJac(casadi_int nfwd) const
Calculate derivatives by multiplying the full Jacobian and multiplying.
virtual Sparsity get_sparsity_out(casadi_int i)
Get sparsity of a given output.
const Sparsity & sparsity_out(casadi_int ind) const
Input/output sparsity.
bool matching_res(const std::vector< M > &arg, casadi_int &npar) const
Check if output arguments that needs to be replaced.
void disp(std::ostream &stream, bool more) const override
Display object.
size_t sz_w() const
Get required length of w field.
virtual int sp_reverse(bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const
Propagate sparsity backwards.
virtual Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind, bool symmetric) const
Get Jacobian sparsity.
virtual void merge(const std::vector< MX > &arg, std::vector< MX > &subs_from, std::vector< MX > &subs_to) const
List merge opportunitities.
bool jit_cleanup_
Cleanup jit source file.
Sparsity get_jac_sparsity_gen(casadi_int oind, casadi_int iind) const
Get the sparsity pattern via sparsity seed propagation.
virtual Dict info() const
void print_out(std::ostream &stream, double **res, bool truncate) const
Print outputs.
virtual void codegen_declarations(CodeGenerator &g) const
Generate code for the declarations of the C function.
int eval_gen(const double **arg, double **res, casadi_int *iw, double *w, void *mem, bool always_inline, bool never_inline) const
Evaluate numerically.
virtual bool jac_is_symm(casadi_int oind, casadi_int iind) const
Is a Jacobian block known to be symmetric a priori?
virtual const std::vector< MX > mx_out() const
Get function input(s) and output(s)
virtual std::vector< casadi_int > instruction_output(casadi_int k) const
Get the (integer) output argument of an atomic operation.
virtual int sp_forward_block(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem, casadi_int oind, casadi_int iind) const
Propagate sparsity forward, specific block.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
std::string signature(const std::string &fname) const
Code generate the function.
virtual const std::vector< SX > sx_out() const
Get function input(s) and output(s)
bool all_scalar() const
Are all inputs and outputs scalar.
virtual Function get_jacobian(const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const
Return Jacobian of all input elements with respect to all output elements.
std::vector< double > nz_out(const std::vector< DM > &res) const
Convert from/to flat vector of input/output nonzeros.
casadi_int nnz_out() const
Number of input/output nonzeros.
void tocache(const Function &f, const std::string &suffix="") const
Save function to cache.
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.
void generate_out(const std::string &fname, double **res) const
virtual bool has_codegen() const
Is codegen supported?
static bool check_mat(const Sparsity &arg, const Sparsity &inp, casadi_int &npar)
void codegen_meta(CodeGenerator &g) const
Generate meta-information allowing a user to evaluate a generated function.
Function jacobian() const
Return Jacobian of all input elements with respect to all output elements.
virtual void codegen_init_mem(CodeGenerator &g) const
Codegen decref for init_mem.
virtual bool has_free() const
Does the function have free variables.
void alloc(const Function &f, bool persistent=false, int num_threads=1)
Ensure work vectors long enough to evaluate function.
virtual bool has_reverse(casadi_int nadj) const
Return function that calculates adjoint derivatives.
virtual std::string generate_dependencies(const std::string &fname, const Dict &opts) const
Export / Generate C code for the dependency function.
virtual std::vector< MX > symbolic_output(const std::vector< MX > &arg) const
Get a vector of symbolic variables corresponding to the outputs.
std::vector< bool > is_diff_in_
Are inputs and outputs differentiable?
size_t sz_iw() const
Get required length of iw field.
void change_option(const std::string &option_name, const GenericType &option_value) override
Change option after object creation for debugging.
static std::string string_from_UnifiedReturnStatus(UnifiedReturnStatus status)
virtual casadi_int n_instructions() const
Get the number of atomic operations.
virtual void codegen_decref(CodeGenerator &g) const
Codegen decref for dependencies.
Dict cache_init_
Values to prepopulate the function cache with.
std::vector< std::string > name_out_
virtual bool get_diff_out(casadi_int i)
Which outputs are differentiable.
Function derivative_of_
If the function is the derivative of another function.
Dict generate_options(const std::string &target) const override
Reconstruct options dict.
void add_embedded(std::map< FunctionInternal *, Function > &all_fun, const Function &dep, casadi_int max_depth) const
virtual bool has_spfwd() const
Is the class able to propagate seeds through the algorithm?
static std::string reverse_name(const std::string &fcn, casadi_int nadj)
Helper function: Get name of adjoint derivative function.
std::vector< std::vector< M > > replace_aseed(const std::vector< std::vector< M >> &aseed, casadi_int npar) const
Replace 0-by-0 reverse seeds.
Dict cache() const
Get all functions in the cache.
virtual std::string get_name_in(casadi_int i)
Names of function input and outputs.
casadi_int size2_in(casadi_int ind) const
Input/output dimensions.
virtual size_t get_n_in()
Number of function inputs and outputs.
virtual 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
Return function that calculates forward derivatives.
void codegen_sparsities(CodeGenerator &g) const
Codegen sparsities.
virtual double get_default_in(casadi_int ind) const
Get default input value.
std::vector< std::string > name_in_
Input and output scheme.
virtual std::vector< bool > which_depends(const std::string &s_in, const std::vector< std::string > &s_out, casadi_int order, bool tr=false) const
Which variables enter with some order.
virtual Sparsity get_sparsity_in(casadi_int i)
Get sparsity of a given input.
Function wrap_as_needed(const Dict &opts) const
Wrap in an Function instance consisting of only one MX call.
Function forward(casadi_int nfwd) const
Get a function that calculates nfwd forward derivatives.
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.
std::vector< bool > which_depends(const std::string &s_in, const std::vector< std::string > &s_out, casadi_int order=1, bool tr=false) const
Which variables enter with some order.
void assert_size_in(casadi_int i, casadi_int nrow, casadi_int ncol) const
Assert that an input dimension is equal so some given value.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
FunctionInternal * get() const
const std::vector< std::string > & name_in() const
Get input scheme.
const std::string & name() const
Name of the function.
Function wrap() const
Wrap in an Function instance consisting of only one MX call.
Function reverse(casadi_int nadj) const
Get a function that calculates nadj adjoint derivatives.
Function jacobian() const
Calculate all Jacobian blocks.
static Function create(FunctionInternal *node)
Create from node.
static bool check_name(const std::string &name)
Check if a string is a valid function name.
bool is_diff_out(casadi_int ind) const
Get differentiability of inputs/output.
std::pair< casadi_int, casadi_int > size_out(casadi_int ind) const
Get output dimension.
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
void assert_sparsity_out(casadi_int i, const Sparsity &sp, casadi_int n=1, bool allow_all_zero_sparse=true) const
Assert that an output sparsity is a multiple of some given sparsity.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
bool is_diff_in(casadi_int ind) const
Get differentiability of inputs/output.
Function slice(const std::string &name, const std::vector< casadi_int > &order_in, const std::vector< casadi_int > &order_out, const Dict &opts=Dict()) const
returns a new function with a selection of inputs/outputs of the original
void call(const std::vector< DM > &arg, std::vector< DM > &res, bool always_inline=false, bool never_inline=false) const
Evaluate the function symbolically or numerically.
const std::vector< Sparsity > & jac_sparsity(bool compact=false) const
Get, if necessary generate, the sparsity of all Jacobian blocks.
std::map< std::string, std::vector< std::string > > AuxOut
Function factory(const std::string &name, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const AuxOut &aux=AuxOut(), const Dict &opts=Dict()) const
const std::vector< std::string > & name_out() const
Get output scheme.
static Matrix< Scalar > sym(const std::string &name, casadi_int nrow=1, casadi_int ncol=1)
Create an nrow-by-ncol symbolic primitive.
static MatType zeros(casadi_int nrow=1, casadi_int ncol=1)
Create a dense matrix or a matrix with specified sparsity with all entries zero.
bool is_null() const
Is a null pointer?
Generic data type, can hold different types such as bool, casadi_int, std::string etc.
std::string to_string() const
Convert to a type.
static casadi_int getMaxNumDir()
static bool hierarchical_sparsity
std::string library() const
Get library name.
signal_t get_function(const std::string &symname)
Get a function pointer for numerical evaluation.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static Function create(const std::string ¶llelization, const Function &f, casadi_int n)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize with type disambiguation.
static void print_default(std::ostream &stream, const Sparsity &sp, const double *nonzeros, bool truncate=true)
Print default style.
const Sparsity & sparsity() const
Const access the sparsity - reference to data member.
void to_file(const std::string &filename, const std::string &format="") const
static Matrix< casadi_int > triplet(const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, const Matrix< casadi_int > &d)
Construct a sparse matrix from triplet form.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
Base class for FunctionInternal and LinsolInternal.
void print_option(const std::string &name, std::ostream &stream) const
Print all information there is to know about a certain option.
bool error_on_fail_
Throw an exception on failure?
void construct(const Dict &opts)
Construct.
virtual int init_mem(void *mem) const
Initalize memory block.
virtual void serialize_type(SerializingStream &s) const
Serialize type information.
virtual void * alloc_mem() const
Create memory block.
virtual const Options & get_options() const
Options.
bool regularity_check_
Errors are thrown when NaN is produced.
virtual Dict generate_options(const std::string &target) const
Reconstruct options dict.
void serialize(SerializingStream &s) const
Serialize an object.
ProtoFunction(const std::string &name)
Constructor.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
virtual void free_mem(void *mem) const
Free memory block.
virtual void serialize_body(SerializingStream &s) const
Serialize an object without type information.
void print_time(const std::map< std::string, FStats > &fstats) const
Print timing statistics.
int checkout() const
Checkout a memory object.
virtual void init(const Dict &opts)
Initialize.
void format_time(char *buffer, double time) const
Format time in a fixed width 8 format.
virtual Dict get_stats(void *mem) const
Get all statistics.
void * memory(int ind) const
Memory objects.
void print_options(std::ostream &stream) const
Print list of options.
bool has_memory(int ind) const
Check for existance of memory object.
bool verbose_
Verbose printout.
virtual void finalize()
Finalize the object creation.
virtual std::string serialize_base_function() const
String used to identify the immediate FunctionInternal subclass.
virtual void check_mem_count(casadi_int n) const
Check for validatity of memory object count.
void sprint(char *buf, size_t buf_sz, const char *fmt,...) const
C-style formatted printing to string.
void release(int mem) const
Release a memory object.
bool has_option(const std::string &option_name) const
Does a particular option exist.
static const Options options_
Options.
void clear_mem()
Clear all memory (called from destructor)
~ProtoFunction() override=0
Destructor.
virtual void change_option(const std::string &option_name, const GenericType &option_value)
Change option after object creation for debugging.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into MX.
The basic scalar symbolic class of CasADi.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
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.
casadi_int get_nz(casadi_int rr, casadi_int cc) const
Get the index of an existing non-zero element.
bool is_vector() const
Check if the pattern is a row or column vector.
Sparsity sub(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, std::vector< casadi_int > &mapping, bool ind1=false) const
Get a submatrix.
casadi_int numel() const
The total number of elements, including structural zeros, i.e. size2()*size1()
casadi_int size1() const
Get the number of rows.
Sparsity star_coloring(casadi_int ordering=1, casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Perform a star coloring of a symmetric matrix:
std::string dim(bool with_nz=false) const
Get the dimension as a string.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern *.
Sparsity T() const
Transpose the matrix.
bool is_scalar(bool scalar_and_dense=false) const
Is scalar?
void enlargeColumns(casadi_int ncol, const std::vector< casadi_int > &cc, bool ind1=false)
Enlarge the matrix along the second dimension (i.e. insert columns)
void enlargeRows(casadi_int nrow, const std::vector< casadi_int > &rr, bool ind1=false)
Enlarge the matrix along the first dimension (i.e. insert rows)
casadi_int nnz() const
Get the number of (structural) non-zeros.
casadi_int size2() const
Get the number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
static Sparsity scalar(bool dense_scalar=true)
Create a scalar sparsity pattern *.
bool is_empty(bool both=false) const
Check if the sparsity is empty.
double density() const
The percentage of nonzero.
Sparsity uni_coloring(const Sparsity &AT=Sparsity(), casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Perform a unidirectional coloring: A greedy distance-2 coloring algorithm.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
static Sparsity triplet(casadi_int nrow, casadi_int ncol, const std::vector< casadi_int > &row, const std::vector< casadi_int > &col, std::vector< casadi_int > &mapping, bool invert_mapping)
Create a sparsity pattern given the nonzeros in sparse triplet form *.
bool is_symmetric() const
Is symmetric?
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
T get_from_dict(const std::map< std::string, T > &d, const std::string &key, const T &default_value)
std::string join(const std::vector< std::string > &l, const std::string &delim)
unsigned long long bvec_t
int(* casadi_checkout_t)(void)
Function pointer types for the C API.
Dict combine(const Dict &first, const Dict &second, bool recurse)
Combine two dicts. First has priority.
std::string temporary_file(const std::string &prefix, const std::string &suffix)
M replace_mat(const M &arg, const Sparsity &inp, casadi_int npar)
void bvec_clear(bvec_t *s, casadi_int begin, casadi_int end)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
int(* eval_t)(const double **arg, double **res, casadi_int *iw, double *w, int)
Function pointer types for the C API.
std::vector< MX > MXVector
void assert_read(std::istream &stream, const std::string &s)
std::string str(const T &v)
String representation, any type.
std::vector< casadi_int > lookupvector(const std::vector< casadi_int > &v, casadi_int size)
Returns a vector for quickly looking up entries of supplied list.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
void(* casadi_release_t)(int)
Function pointer types for the C API.
void normalized_setup(std::istream &stream)
bool all(const std::vector< bool > &v)
Check if all arguments are true.
std::vector< T > diff(const std::vector< T > &values)
diff
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
bool remove(const std::string &path)
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
bvec_t bvec_or(const bvec_t *arg, casadi_int n)
Bit-wise or operation on bvec_t array.
void normalized_out(std::ostream &stream, double val)
void bvec_toggle(bvec_t *s, casadi_int begin, casadi_int end, casadi_int j)
Function memory with temporary work vectors.
Options metadata for a class.
static bool is_sane(const Dict &opts)
Is the dictionary sane.
void print_all(std::ostream &stream) const
Print list of options.
static Dict sanitize(const Dict &opts, bool top_level=true)
Sanitize a options dictionary.
const Options::Entry * find(const std::string &name) const
void check(const Dict &opts) const
Check if options exist.
void print_one(const std::string &name, std::ostream &stream) const
Print all information there is to know about a certain option.
Function memory with temporary work vectors.
void add_stat(const std::string &s)