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 "onnx_function_impl.hpp"
48 #include "filesystem_impl.hpp"
72 casadi_error(
"Function name is not valid. A valid function name is a std::string "
73 "starting with a letter followed by letters, numbers or "
74 "non-consecutive underscores. It may also not match the keywords "
75 "'null', 'jac' or 'hess'. Got '" +
name_ +
"'");
127 for (
void* m : mem_) {
128 if (m!=
nullptr) casadi_warning(
"Memory object has not been properly freed");
137 if (
remove(jit_name.c_str())) casadi_warning(
"Failed to remove " + jit_name);
155 }
catch(std::exception& e) {
156 casadi_error(
"Error calling " +
class_name() +
"::init for '" +
name_ +
"':\n"
157 + std::string(e.what()));
163 }
catch(std::exception& e) {
164 casadi_error(
"Error calling " +
class_name() +
"::finalize for '" +
name_ +
"':\n"
165 + std::string(e.what()));
173 "Verbose evaluation -- for debugging"}},
176 "print information about execution time. Implies record_time."}},
179 "record information about execution time, for retrieval with stats()."}},
182 "Throw exceptions when NaN or Inf appears during evaluation"}},
185 "Throw exceptions when function evaluation fails (default true)."}}
193 "Weighting factor for derivative calculation."
194 "When there is an option of either using forward or reverse mode "
195 "directional derivatives, the condition ad_weight*nf<=(1-ad_weight)*na "
196 "is used where nf and na are estimates of the number of forward/reverse "
197 "mode directional derivatives needed. By default, ad_weight is calculated "
198 "automatically, but this can be overridden by setting this option. "
199 "In particular, 0 means forcing forward mode and 1 forcing reverse mode. "
200 "Leave unset for (class specific) heuristics."}},
203 "Weighting factor for sparsity pattern calculation calculation."
204 "Overrides default behavior. Set to 0 and 1 to force forward and "
205 "reverse mode respectively. Cf. option \"ad_weight\". "
206 "When set to -1, sparsity is completely ignored and dense matrices are used."}},
212 "Forbid inlining."}},
215 "When requested for a number of forward/reverse directions, "
216 "it may be cheaper to compute first the full jacobian and then "
217 "multiply with seeds, rather than obtain the requested directions "
218 "in a straightforward manner. "
219 "Casadi uses a heuristic to decide which is cheaper. "
220 "A high value of 'jac_penalty' makes it less likely for the heurstic "
221 "to chose the full Jacobian strategy. "
222 "The special value -1 indicates never to use the full Jacobian strategy"}},
225 "A user-defined field that can be used to identify "
226 "the function or pass additional information"}},
229 "Throw exceptions when the numerical values of the inputs don't make sense"}},
232 "Deprecated option (ignored): Statistics are now always collected."}},
235 "Use just-in-time compiler to speed up the evaluation"}},
238 "Cleanup up the temporary source file that jit creates. Default: true"}},
241 "Specify behaviour when serializing a jitted function: SOURCE|link|embed."}},
244 "The file name used to write out code. "
245 "The actual file names used depend on 'jit_temp_suffix' and include extensions. "
246 "Default: 'jit_tmp'"}},
249 "Use a temporary (seemingly random) filename suffix for generated code and libraries. "
250 "This is desired for thread-safety. "
251 "This behaviour may defeat caching compiler wrappers. "
255 "Just-in-time compiler plugin to be used."}},
258 "Options to be passed to the jit compiler."}},
261 "The function is a derivative of another function. "
262 "The type of derivative (directional derivative, Jacobian) "
263 "is inferred from the function name."}},
266 "Specify the maximum number of directions for derivative functions."
267 " Overrules the builtin optimized_num_dir."}},
270 "Enable derivative calculation using generated functions for"
271 " Jacobian-times-vector products - typically using forward mode AD"
272 " - if available. [default: true]"}},
275 "Enable derivative calculation using generated functions for"
276 " transposed Jacobian-times-vector products - typically using reverse mode AD"
277 " - if available. [default: true]"}},
280 "Enable derivative calculation using generated functions for"
281 " Jacobians of all differentiable outputs with respect to all differentiable inputs"
282 " - if available. [default: true]"}},
285 "Enable derivative calculation by finite differencing. [default: false]]"}},
288 "Options to be passed to the finite difference instance"}},
291 "Method for finite differencing [default 'central']"}},
294 "Print numerical values of inputs [default: false]"}},
297 "Print numerical values of outputs [default: false]"}},
300 "When printing numerical matrices, use a format that is "
301 "exact and reproducible in generated C code."}},
304 "Acceptable number of inputs and outputs. Warn if exceeded."}},
307 "Dump numerical values of inputs to file (readable with DM.from_file) [default: false] "
308 "A counter is used to generate unique names. "
309 "The counter may be reset using reset_dump_count."}},
312 "Dump numerical values of outputs to file (readable with DM.from_file) [default: false] "
313 "A counter is used to generate unique names. "
314 "The counter may be reset using reset_dump_count."}},
317 "Dump function to file upon first evaluation. [false]"}},
320 "Directory to dump inputs/outputs to. Make sure the directory exists [.]"}},
323 "Choose file format to dump matrices. See DM.from_file [mtx]"}},
326 "Options to be passed to a forward mode constructor"}},
329 "Options to be passed to a reverse mode constructor"}},
332 "Options to be passed to a Jacobian constructor"}},
335 "Default options to be used to populate forward_options, reverse_options, and "
336 "jacobian_options before those options are merged in."}},
339 "Override CasADi's AD. Use together with 'jac_penalty': 0. "
340 "Note: Highly experimental. Syntax may break often."}},
343 "Indicate for each input if it should be differentiable."}},
346 "Indicate for each output if it should be differentiable."}},
349 "After construction, expand this Function. Default: False"}},
350 {
"post_expand_options",
352 "Options to be passed to post-construction expansion. Default: empty"}},
355 "Prepopulate the function cache. Default: empty"}},
356 {
"external_transform",
358 "List of external_transform instruction arguments. Default: empty"}}
364 for (
auto&& op : opts) {
365 if (op.first==
"verbose") {
367 }
else if (op.first==
"print_time") {
369 }
else if (op.first==
"record_time") {
371 }
else if (op.first==
"regularity_check") {
373 }
else if (op.first==
"error_on_fail") {
394 if (target!=
"tmp") opts[
"jit"] =
jit_;
406 if (target==
"clone" || target==
"tmp") {
427 opts[
"dump"] =
dump_;
428 if (target==
"clone") {
432 if (target==
"forward") {
436 if (target==
"reverse") {
445 if (option_name ==
"print_in") {
447 }
else if (option_name ==
"print_out") {
449 }
else if (option_name ==
"print_canonical") {
451 }
else if (option_name==
"ad_weight") {
453 }
else if (option_name==
"ad_weight_sp") {
455 }
else if (option_name==
"dump") {
456 dump_ = option_value;
457 }
else if (option_name==
"dump_in") {
459 }
else if (option_name==
"dump_out") {
461 }
else if (option_name==
"dump_dir") {
463 }
else if (option_name==
"dump_format") {
483 for (
auto&& op : opts) {
484 if (op.first==
"jac_penalty") {
486 }
else if (op.first==
"user_data") {
488 }
else if (op.first==
"inputs_check") {
490 }
else if (op.first==
"gather_stats") {
491 casadi_warning(
"Deprecated option \"gather_stats\": Always enabled");
492 }
else if (op.first==
"jit") {
494 }
else if (op.first==
"jit_cleanup") {
496 }
else if (op.first==
"jit_serialize") {
499 "jit_serialize option not understood. Pick one of source, link, embed.");
500 }
else if (op.first==
"compiler") {
502 }
else if (op.first==
"jit_options") {
504 }
else if (op.first==
"jit_name") {
506 }
else if (op.first==
"jit_temp_suffix") {
508 }
else if (op.first==
"derivative_of") {
510 }
else if (op.first==
"ad_weight") {
512 }
else if (op.first==
"ad_weight_sp") {
514 }
else if (op.first==
"max_num_dir") {
516 }
else if (op.first==
"enable_forward") {
518 }
else if (op.first==
"enable_reverse") {
520 }
else if (op.first==
"enable_jacobian") {
522 }
else if (op.first==
"enable_fd") {
524 }
else if (op.first==
"fd_options") {
526 }
else if (op.first==
"fd_method") {
528 }
else if (op.first==
"print_in") {
530 }
else if (op.first==
"print_out") {
532 }
else if (op.first==
"print_canonical") {
534 }
else if (op.first==
"max_io") {
536 }
else if (op.first==
"dump_in") {
538 }
else if (op.first==
"dump_out") {
540 }
else if (op.first==
"dump") {
542 }
else if (op.first==
"dump_dir") {
544 }
else if (op.first==
"dump_format") {
546 }
else if (op.first==
"forward_options") {
548 }
else if (op.first==
"reverse_options") {
550 }
else if (op.first==
"jacobian_options") {
552 }
else if (op.first==
"der_options") {
554 }
else if (op.first==
"custom_jacobian") {
557 "Inconsistent naming of custom Jacobian, expected: jac_" +
name_);
559 }
else if (op.first==
"always_inline") {
561 }
else if (op.first==
"never_inline") {
563 }
else if (op.first==
"is_diff_in") {
565 }
else if (op.first==
"is_diff_out") {
567 }
else if (op.first==
"cache") {
581 casadi_warning(
"Function " +
name_ +
" has many inputs (" +
str(
n_in_) +
" > "
583 +
"Changing the problem formulation is strongly encouraged.");
589 casadi_warning(
"Function " +
name_ +
" has many outputs (" +
str(
n_out_) +
" > "
591 +
"Changing the problem formulation is strongly encouraged.");
600 +
" inputs, but is_diff_in has length " +
str(
is_diff_in_.size()) +
".");
609 +
" outputs, but is_diff_out has length " +
str(
is_diff_out_.size()) +
".");
618 +
" inputs, but sparsity_in has length " +
str(
sparsity_in_.size()) +
".");
627 +
" outputs, but sparsity_out has length " +
str(
sparsity_out_.size()) +
".");
636 +
" inputs, but name_in has length " +
str(
name_in_.size()) +
".");
645 +
" outputs, but name_out has length " +
str(
name_out_.size()) +
".");
651 if (c.first != f.
name()) {
652 casadi_warning(
"Cannot add '" + c.first +
"' a.k.a. '" + f.
name()
653 +
"' to cache. Mismatching names not implemented.");
660 sz_arg_per_ +=
n_in_;
676 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
697 if (
name_ ==
"jac_" + n) {
701 }
else if (
name_ ==
"adj1_" + n) {
715 std::string directory;
716 directory =
get_from_dict(jit_options,
"directory", std::string(
""));
721 jit_directory = directory;
723 jit_directory = jit_directory + directory;
739 for (
const Function& f : shared_from_this<Function>().find_functions(0)) {
740 if (f->has_refcount_in_deps_) {
756 if (
verbose_) casadi_message(
"Codegenerating function '" +
name_ +
"'.");
760 opts[
"prefix"] =
"jit";
763 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"'..");
765 if (
verbose_) casadi_message(
"Compiling function '" +
name_ +
"' done.");
773 casadi_assert(
eval_!=
nullptr,
"Cannot load JIT'ed function.");
791 casadi_assert_dev(mem==0);
797 std::ostream& of = *of_ptr;
801 for (casadi_int i=0; i<
n_in_; ++i) {
802 const double* v = arg[i];
803 for (casadi_int k=0;k<
nnz_in(i);++k) {
813 std::ostream& of = *of_ptr;
817 for (casadi_int i=0; i<
n_out_; ++i) {
818 const double* v = res[i];
819 for (casadi_int k=0;k<
nnz_out(i);++k) {
820 normalized_out(of, v ? v[k] : std::numeric_limits<double>::quiet_NaN());
826 void FunctionInternal::dump_in(casadi_int
id,
const double** arg)
const {
827 std::stringstream ss;
828 ss << std::setfill(
'0') << std::setw(6) << id;
829 std::string count = ss.str();
830 for (casadi_int i=0;i<
n_in_;++i) {
836 casadi_message(
"dump_in for " +
name_ +
" -> " + name);
841 void FunctionInternal::dump_out(casadi_int
id,
double** res)
const {
842 std::stringstream ss;
843 ss << std::setfill(
'0') << std::setw(6) << id;
844 std::string count = ss.str();
845 for (casadi_int i=0;i<
n_out_;++i) {
851 casadi_message(
"dump_out for " +
name_ +
" -> " + name);
856 void FunctionInternal::dump()
const {
860 casadi_int FunctionInternal::get_dump_id()
const {
868 m->t_total = &m->fstats.at(
"total");
870 m->t_total =
nullptr;
876 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
877 for (casadi_int i=0; i<
n_in_; ++i) {
878 stream <<
"Input " << i <<
" (" <<
name_in_[i] <<
"): ";
887 stream <<
"NULL" << std::endl;
893 stream <<
"Function " <<
name_ <<
" (" <<
this <<
")" << std::endl;
894 for (casadi_int i=0; i<
n_out_; ++i) {
895 stream <<
"Output " << i <<
" (" <<
name_out_[i] <<
"): ";
904 stream <<
"NULL" << std::endl;
914 for (casadi_int i=0; i<sz; ++i) {
915 if (i>0) stream <<
", ";
925 const Sparsity& sp,
const double* nz) {
930 stream << sp.
dim(
false) <<
": ";
933 for (casadi_int i=0; i<sp.
nnz(); ++i) {
934 if (i>0) stream <<
", ";
940 stream <<
", colind: [";
941 for (casadi_int i=0; i<sp.
size2()+1; ++i) {
942 if (i>0) stream <<
", ";
946 stream <<
", row: [";
947 for (casadi_int i=0; i<sp.
nnz(); ++i) {
948 if (i>0) stream <<
", ";
949 stream << sp.
row()[i];
966 eval_gen(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem,
967 bool always_inline,
bool never_inline)
const {
969 if (
dump_in_) dump_in(dump_id, arg);
970 if (
dump_ && dump_id==0) dump();
975 for (casadi_int i=0;i<
n_in_;++i) {
976 casadi_assert(arg[i]==
nullptr || arg[i]+
nnz_in(i)<=w || arg[i]>=w+
sz_w(),
977 "Memory corruption detected for input " +
name_in_[i] +
".\n"+
979 " intersects with w " +
str(w)+
"-"+
str(w+
sz_w())+
".");
981 for (casadi_int i=0;i<
n_out_;++i) {
982 casadi_assert(res[i]==
nullptr || res[i]+
nnz_out(i)<=w || res[i]>=w+
sz_w(),
983 "Memory corruption detected for output " +
name_out_[i]);
986 for (
auto&& s : m->fstats) s.second.reset();
987 if (m->t_total) m->t_total->tic();
994 #ifdef CASADI_WITH_THREAD
995 std::lock_guard<std::mutex> lock(mtx_);
999 ret =
eval_(arg, res, iw, w, mem_);
1001 #ifdef CASADI_WITH_THREAD
1002 std::lock_guard<std::mutex> lock(mtx_);
1007 ret =
eval(arg, res, iw, w, mem);
1009 if (m->t_total) m->t_total->toc();
1017 for (casadi_int i = 0; i <
n_out_; ++i) {
1019 if (!res[i])
continue;
1021 casadi_int nnz = this->
nnz_out(i);
1022 for (casadi_int nz = 0; nz < nnz; ++nz) {
1023 if (isnan(res[i][nz]) || isinf(res[i][nz])) {
1025 casadi_error(
str(res[i][nz]) +
" detected for output " +
name_out_[i] +
" at "
1035 stream <<
" Number of inputs: " <<
n_in_ << std::endl;
1036 for (casadi_int i=0; i<
n_in_; ++i) {
1037 stream <<
" Input " << i <<
" (\"" <<
name_in_[i] <<
"\"): "
1040 stream <<
" Number of outputs: " <<
n_out_ << std::endl;
1041 for (casadi_int i=0; i<
n_out_; ++i) {
1042 stream <<
" Output " << i <<
" (\"" <<
name_out_[i] <<
"\"): "
1061 if (option_name ==
"verbose") {
1063 }
else if (option_name ==
"regularity_check") {
1067 casadi_error(
"Option '" + option_name +
"' cannot be changed");
1073 return std::vector<std::string>();
1077 std::stringstream s;
1082 for (casadi_int i=0; i<
n_in_; ++i) {
1088 for (casadi_int i=0; i<
n_out_; ++i) {
1100 stream << std::endl;
1110 std::vector<std::string> keys;
1111 std::vector<Function> entries;
1112 cache_.cache(keys, entries);
1114 for (
size_t i=0; i<keys.size(); ++i) {
1116 std::string s = keys[i];
1117 casadi_assert_dev(s.size() > 0);
1119 std::replace(s.begin(), s.end(),
':',
'_');
1121 if (s.back() ==
'_') s.resize(s.size() - 1);
1123 ret[s] = entries[i];
1130 const std::string& suffix)
const {
1131 return cache_.incache(fname +
":" + suffix, f);
1139 cache_.tocache_if_missing(f.
name() +
":" + suffix, f);
1144 if (parallelization==
"serial") {
1146 std::string fname =
"map" +
str(n) +
"_" +
name_;
1150 casadi_assert_dev(f.
name()==fname);
1166 if (opts.empty() && name==
name_)
return shared_from_this<Function>();
1168 Dict my_opts = opts;
1170 if (my_opts.find(
"ad_weight")==my_opts.end())
1172 if (my_opts.find(
"ad_weight_sp")==my_opts.end())
1174 if (my_opts.find(
"max_num_dir")==my_opts.end())
1177 std::vector<MX> arg =
mx_in();
1178 std::vector<MX> res =
self()(arg);
1198 std::vector<MX> arg =
mx_in();
1199 std::vector<MX> res =
self()(arg);
1214 for (casadi_int i=begin; i<end; ++i) {
1215 s[i] ^= (
bvec_t(1) << j);
1220 for (casadi_int i=begin; i<end; ++i) {
1228 for (casadi_int i=begin; i<end; ++i) r |= s[i];
1233 template<
bool fwd>
struct JacSparsityTraits {};
1234 template<>
struct JacSparsityTraits<true> {
1235 typedef const bvec_t* arg_t;
1236 static inline void sp(
const FunctionInternal *f,
1238 casadi_int* iw,
bvec_t* w,
void* mem) {
1239 std::vector<const bvec_t*> argm(f->sz_arg(),
nullptr);
1240 std::vector<bvec_t> wm(f->nnz_in(),
bvec_t(0));
1243 for (casadi_int i=0;i<f->n_in_;++i) {
1244 if (f->is_diff_in_[i]) {
1247 argm[i] = arg[i] ? wp :
nullptr;
1251 f->sp_forward(
get_ptr(argm), res, iw, w, mem);
1252 for (casadi_int i=0;i<f->n_out_;++i) {
1253 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1257 template<>
struct JacSparsityTraits<false> {
1259 static inline void sp(
const FunctionInternal *f,
1261 casadi_int* iw,
bvec_t* w,
void* mem) {
1262 for (casadi_int i=0;i<f->n_out_;++i) {
1263 if (!f->is_diff_out_[i] && res[i])
casadi_clear(res[i], f->nnz_out(i));
1265 f->sp_reverse(arg, res, iw, w, mem);
1266 for (casadi_int i=0;i<f->n_in_;++i) {
1267 if (!f->is_diff_in_[i] && arg[i])
casadi_clear(arg[i], f->nnz_in(i));
1279 std::vector<typename JacSparsityTraits<fwd>::arg_t> arg(
sz_arg(),
nullptr);
1280 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1281 std::vector<casadi_int> iw(
sz_iw());
1282 std::vector<bvec_t> w(
sz_w(), 0);
1285 std::vector<bvec_t> seed(
nz_in, 0);
1287 std::vector<bvec_t> sens(
nz_out, 0);
1289 if (!fwd) std::swap(seed, sens);
1292 casadi_int nsweep = seed.size() /
bvec_size;
1297 casadi_message(
str(nsweep) + std::string(fwd ?
" forward" :
" reverse") +
" sweeps "
1298 "needed for " +
str(seed.size()) +
" directions");
1302 casadi_int progress = -10;
1305 std::vector<casadi_int> jcol, jrow;
1308 for (casadi_int s=0; s<nsweep; ++s) {
1312 casadi_int progress_new = (s*100)/nsweep;
1314 if (progress_new / 10 > progress / 10) {
1315 progress = progress_new;
1316 casadi_message(
str(progress) +
" %");
1324 casadi_int ndir_local = seed.size()-offset;
1325 ndir_local = std::min(
static_cast<casadi_int
>(
bvec_size), ndir_local);
1327 for (casadi_int i=0; i<ndir_local; ++i) {
1328 seed[offset+i] |=
bvec_t(1)<<i;
1336 for (casadi_int el=0; el<sens.size(); ++el) {
1339 bvec_t spsens = sens[el];
1350 for (casadi_int i=0; i<ndir_local; ++i) {
1353 if ((
bvec_t(1) << i) & spsens) {
1356 jrow.push_back(i+offset);
1363 for (casadi_int i=0; i<ndir_local; ++i) {
1369 if (!fwd) swap(jrow, jcol);
1372 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(ret.
size()) +
", "
1379 casadi_int iind)
const {
1383 casadi_int nz =
nnz_in(iind);
1384 casadi_assert_dev(nz==
nnz_out(oind));
1387 std::vector<const bvec_t*> arg(
sz_arg(),
nullptr);
1388 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1389 std::vector<casadi_int> iw(
sz_iw());
1390 std::vector<bvec_t> w(
sz_w());
1393 std::vector<bvec_t> seed(nz, 0);
1397 std::vector<bvec_t> sens(nz, 0);
1401 std::vector<casadi_int> jcol, jrow;
1404 std::vector<casadi_int> coarse(2, 0); coarse[1] = nz;
1407 std::vector<casadi_int> fine;
1415 casadi_int granularity = nz;
1417 casadi_int nsweeps = 0;
1419 bool hasrun =
false;
1421 while (!hasrun || coarse.size()!=nz+1) {
1422 if (
verbose_) casadi_message(
"Block size: " +
str(granularity));
1434 casadi_message(
"Star coloring on " +
str(r.
dim()) +
": "
1435 +
str(
D.size2()) +
" <-> " +
str(
D.size1()));
1439 std::fill(seed.begin(), seed.end(), 0);
1442 for (casadi_int k=0; k<coarse.size()-1; ++k) {
1443 casadi_int
diff = coarse[k+1]-coarse[k];
1444 casadi_int new_diff =
diff/subdivision;
1445 if (
diff%subdivision>0) new_diff++;
1446 std::vector<casadi_int> temp =
range(coarse[k], coarse[k+1], new_diff);
1447 fine.insert(fine.end(), temp.begin(), temp.end());
1449 if (fine.back()!=coarse.back()) fine.push_back(coarse.back());
1451 granularity = fine[1] - fine[0];
1454 casadi_int bvec_i = 0;
1457 std::vector<casadi_int> fine_lookup =
lookupvector(fine, nz+1);
1460 std::vector<casadi_int> lookup_col;
1461 std::vector<casadi_int> lookup_row;
1462 std::vector<casadi_int> lookup_value;
1465 casadi_int n_fine_blocks_max = 0;
1466 for (casadi_int i=0;i<coarse.size()-1;++i) {
1467 casadi_int del = fine_lookup[coarse[i+1]]-fine_lookup[coarse[i]];
1468 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1472 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1475 casadi_int fci_offset = 0;
1479 bool f_finished =
false;
1482 while (!f_finished) {
1485 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1486 casadi_int cci =
D.row(k);
1489 casadi_int fci_start = fine_lookup[coarse[cci]];
1490 casadi_int fci_end = fine_lookup[coarse[cci+1]];
1493 casadi_int bvec_i_mod = 0;
1495 casadi_int value = -bvec_i + fci_offset + fci_start;
1500 for (casadi_int fci = fci_offset; fci<std::min(fci_end-fci_start, fci_cap); ++fci) {
1504 for (casadi_int cri=r.
colind(cci);cri<r.
colind(cci+1);++cri) {
1505 lookup_col.push_back(r.
row(cri));
1506 lookup_row.push_back(bvec_i+bvec_i_mod);
1507 lookup_value.push_back(value);
1518 bvec_i += std::min(n_fine_blocks_max, fci_cap);
1528 IM lookup =
IM::triplet(lookup_row, lookup_col, lookup_value,
1531 std::reverse(lookup_col.begin(), lookup_col.end());
1532 std::reverse(lookup_row.begin(), lookup_row.end());
1533 std::reverse(lookup_value.begin(), lookup_value.end());
1537 duplicates = sparsify(duplicates);
1548 for (casadi_int cri=0; cri<coarse.size()-1; ++cri) {
1551 for (casadi_int fri=fine_lookup[coarse[cri]];fri<fine_lookup[coarse[cri+1]];++fri) {
1556 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1557 if (spsens & (
bvec_t(1) << bvec_i)) {
1560 if (ind==-1)
continue;
1561 casadi_int lk = lookup->at(ind);
1563 jrow.push_back(bvec_i+lk);
1564 jcol.push_back(fri);
1565 jrow.push_back(fri);
1566 jcol.push_back(bvec_i+lk);
1574 std::fill(seed.begin(), seed.end(), 0);
1579 lookup_value.clear();
1582 if (n_fine_blocks_max>fci_cap) {
1583 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1605 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1606 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
1621 std::vector<bvec_t> s_in(
nz_in, 0);
1622 std::vector<bvec_t> s_out(
nz_out, 0);
1625 std::vector<const bvec_t*> arg_fwd(
sz_arg(),
nullptr);
1626 std::vector<bvec_t*> arg_adj(
sz_arg(),
nullptr);
1627 arg_fwd[iind] = arg_adj[iind] =
get_ptr(s_in);
1628 std::vector<bvec_t*> res(
sz_res(),
nullptr);
1630 std::vector<casadi_int> iw(
sz_iw());
1631 std::vector<bvec_t> w(
sz_w());
1634 std::vector<casadi_int> jcol, jrow;
1637 std::vector<casadi_int> coarse_col(2, 0); coarse_col[1] =
nz_out;
1639 std::vector<casadi_int> coarse_row(2, 0); coarse_row[1] =
nz_in;
1642 std::vector<casadi_int> fine_col;
1645 std::vector<casadi_int> fine_row;
1653 casadi_int granularity_row =
nz_in;
1654 casadi_int granularity_col =
nz_out;
1656 bool use_fwd =
true;
1658 casadi_int nsweeps = 0;
1660 bool hasrun =
false;
1666 std::vector<bvec_t> bvec_lookup;
1669 bvec_lookup.push_back(
bvec_t(1) << i);
1672 while (!hasrun || coarse_col.size()!=
nz_out+1 || coarse_row.size()!=
nz_in+1) {
1674 casadi_message(
"Block size: " +
str(granularity_col) +
" x " +
str(granularity_row));
1695 casadi_message(
"Coloring on " +
str(r.
dim()) +
" (fwd seeps: " +
str(D1.
size2()) +
1696 " , adj sweeps: " +
str(D2.
size1()) +
")");
1700 double fwd_cost =
static_cast<double>(use_fwd ? granularity_row : granularity_col) *
1701 sp_w*
static_cast<double>(D1.
size2());
1702 double adj_cost =
static_cast<double>(use_fwd ? granularity_col : granularity_row) *
1703 (1-sp_w)*
static_cast<double>(D2.
size2());
1704 use_fwd = fwd_cost <= adj_cost;
1706 casadi_message(std::string(use_fwd ?
"Forward" :
"Reverse") +
" mode chosen "
1707 "(fwd cost: " +
str(fwd_cost) +
", adj cost: " +
str(adj_cost) +
")");
1719 for (casadi_int i=0; i<nz_seed; ++i) seed_v[i]=0;
1726 std::swap(coarse_col, coarse_row);
1727 std::swap(granularity_col, granularity_row);
1732 for (casadi_int k=0;k<coarse_col.size()-1;++k) {
1733 casadi_int
diff = coarse_col[k+1]-coarse_col[k];
1734 casadi_int new_diff =
diff/subdivision;
1735 if (
diff%subdivision>0) new_diff++;
1736 std::vector<casadi_int> temp =
range(coarse_col[k], coarse_col[k+1], new_diff);
1737 fine_col.insert(fine_col.end(), temp.begin(), temp.end());
1740 for (casadi_int k=0;k<coarse_row.size()-1;++k) {
1741 casadi_int
diff = coarse_row[k+1]-coarse_row[k];
1742 casadi_int new_diff =
diff/subdivision;
1743 if (
diff%subdivision>0) new_diff++;
1744 std::vector<casadi_int> temp =
range(coarse_row[k], coarse_row[k+1], new_diff);
1745 fine_row.insert(fine_row.end(), temp.begin(), temp.end());
1747 if (fine_row.back()!=coarse_row.back()) fine_row.push_back(coarse_row.back());
1748 if (fine_col.back()!=coarse_col.back()) fine_col.push_back(coarse_col.back());
1750 granularity_col = fine_col[1] - fine_col[0];
1751 granularity_row = fine_row[1] - fine_row[0];
1754 casadi_int bvec_i = 0;
1757 std::vector<casadi_int> fine_col_lookup =
lookupvector(fine_col, nz_sens+1);
1758 std::vector<casadi_int> fine_row_lookup =
lookupvector(fine_row, nz_seed+1);
1761 std::vector<casadi_int> lookup_col;
1762 std::vector<casadi_int> lookup_row;
1763 std::vector<casadi_int> lookup_value;
1767 casadi_int n_fine_blocks_max = 0;
1768 for (casadi_int i=0;i<coarse_row.size()-1;++i) {
1769 casadi_int del = fine_row_lookup[coarse_row[i+1]]-fine_row_lookup[coarse_row[i]];
1770 n_fine_blocks_max = std::max(n_fine_blocks_max, del);
1774 for (casadi_int csd=0; csd<
D.size2(); ++csd) {
1776 casadi_int fci_offset = 0;
1780 bool f_finished =
false;
1783 while (!f_finished) {
1786 for (casadi_int k=
D.colind(csd); k<
D.colind(csd+1); ++k) {
1787 casadi_int cci =
D.row(k);
1790 casadi_int fci_start = fine_row_lookup[coarse_row[cci]];
1791 casadi_int fci_end = fine_row_lookup[coarse_row[cci+1]];
1794 casadi_int bvec_i_mod = 0;
1796 casadi_int value = -bvec_i + fci_offset + fci_start;
1799 for (casadi_int fci = fci_offset; fci < std::min(fci_end-fci_start, fci_cap); ++fci) {
1803 for (casadi_int cri=rT.
colind(cci);cri<rT.
colind(cci+1);++cri) {
1804 lookup_col.push_back(rT.
row(cri));
1805 lookup_row.push_back(bvec_i+bvec_i_mod);
1806 lookup_value.push_back(value);
1810 bvec_toggle(seed_v, fine_row[fci+fci_start], fine_row[fci+fci_start+1],
1817 bvec_i+= std::min(n_fine_blocks_max, fci_cap);
1832 JacSparsityTraits<true>::sp(
this,
get_ptr(arg_fwd),
get_ptr(res),
1835 std::fill(w.begin(), w.end(), 0);
1836 JacSparsityTraits<false>::sp(
this,
get_ptr(arg_adj),
get_ptr(res),
1844 for (casadi_int cri=0;cri<coarse_col.size()-1;++cri) {
1847 for (casadi_int fri=fine_col_lookup[coarse_col[cri]];
1848 fri<fine_col_lookup[coarse_col[cri+1]];++fri) {
1850 bvec_or(sens_v, spsens, fine_col[fri], fine_col[fri+1]);
1853 if (!spsens)
continue;
1856 for (casadi_int bvec_i=0;bvec_i<
bvec_size;++bvec_i) {
1857 if (spsens & bvec_lookup[bvec_i]) {
1860 if (ind==-1)
continue;
1861 jrow.push_back(bvec_i+lookup->at(ind));
1862 jcol.push_back(fri);
1869 std::fill(s_in.begin(), s_in.end(), 0);
1872 std::fill(s_out.begin(), s_out.end(), 0);
1877 lookup_value.clear();
1880 if (n_fine_blocks_max>fci_cap) {
1881 fci_offset += std::min(n_fine_blocks_max, fci_cap);
1896 coarse_col = fine_col;
1897 coarse_row = fine_row;
1901 coarse_col = fine_row;
1902 coarse_row = fine_col;
1907 casadi_message(
"Number of sweeps: " +
str(nsweeps));
1908 casadi_message(
"Formed Jacobian sparsity pattern (dimension " +
str(r.
size()) +
", " +
1920 if (
name_ ==
"adj1_" + n) {
1921 if (iind == oind)
return true;
1929 bool symmetric)
const {
1932 "Symmetry exploitation in Jacobian assumes dense expression. "
1933 "A potential workaround is to apply densify().");
1965 if (w*
static_cast<double>(nsweep_fwd) <= (1-w)*
static_cast<double>(nsweep_adj)) {
1966 sp = get_jac_sparsity_gen<true>(oind, iind);
1968 sp = get_jac_sparsity_gen<false>(oind, iind);
1981 std::vector<casadi_int> mapping;
2004 bool symmetric)
const {
2005 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
2007 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
2010 for (
bool c : {
false,
true}) {
2014 casadi_int ind = iind + oind *
n_in_;
2030 sp_is_compact =
true;
2042 if (sp_is_compact == compact) {
2069 bool compact,
bool symmetric,
2070 bool allow_forward,
bool allow_reverse)
const {
2072 casadi_assert(allow_forward || allow_reverse,
"Inconsistent options");
2081 casadi_assert_dev(allow_forward);
2084 if (
verbose_) casadi_message(
"FunctionInternal::getPartition star_coloring");
2087 casadi_message(
"Star coloring completed: " +
str(D1.
size2())
2088 +
" directional derivatives needed ("
2089 +
str(A.
size1()) +
" without coloring).");
2098 if (w==1) allow_forward =
false;
2099 if (w==0) allow_reverse =
false;
2100 casadi_assert(allow_forward || allow_reverse,
"Conflicting ad weights");
2103 double best_coloring = std::numeric_limits<double>::infinity();
2106 bool test_fwd_first = allow_forward && w*
static_cast<double>(A.
size1()) <=
2107 (1-w)*
static_cast<double>(A.
size2());
2108 casadi_int mode_fwd = test_fwd_first ? 0 : 1;
2111 for (casadi_int mode=0; mode<2; ++mode) {
2113 bool fwd = mode==mode_fwd;
2116 if (!allow_forward && fwd)
continue;
2117 if (!allow_reverse && !fwd)
continue;
2121 if (
verbose_) casadi_message(
"Unidirectional coloring (forward mode)");
2122 bool d = best_coloring>=w*
static_cast<double>(A.
size1());
2123 casadi_int max_colorings_to_test =
2124 d ? A.
size1() :
static_cast<casadi_int
>(floor(best_coloring/w));
2128 casadi_message(
"Forward mode coloring interrupted (more than "
2129 +
str(max_colorings_to_test) +
" needed).");
2133 casadi_message(
"Forward mode coloring completed: "
2134 +
str(D1.
size2()) +
" directional derivatives needed ("
2135 +
str(A.
size1()) +
" without coloring).");
2138 best_coloring = w*
static_cast<double>(D1.
size2());
2141 if (
verbose_) casadi_message(
"Unidirectional coloring (adjoint mode)");
2142 bool d = best_coloring>=(1-w)*
static_cast<double>(A.
size2());
2143 casadi_int max_colorings_to_test =
2144 d ? A.
size2() :
static_cast<casadi_int
>(floor(best_coloring/(1-w)));
2149 casadi_message(
"Adjoint mode coloring interrupted (more than "
2150 +
str(max_colorings_to_test) +
" needed).");
2154 casadi_message(
"Adjoint mode coloring completed: "
2155 +
str(D2.
size2()) +
" directional derivatives needed ("
2156 +
str(A.
size2()) +
" without coloring).");
2159 best_coloring = (1-w)*
static_cast<double>(D2.
size2());
2168 casadi_error(
"'eval_dm' not defined for " +
class_name());
2173 bool always_inline,
bool never_inline)
const {
2178 casadi_assert(!always_inline,
"'eval_sx' not defined for " +
class_name() +
2179 " in combination with always_inline true");
2186 casadi_int highest_index = 0;
2189 for (
const std::string& n : name_io) {
2191 size_t end = n.find(
'_');
2192 if (end >= n.size())
continue;
2194 if (end < prefix.size())
continue;
2196 if (n.compare(0, prefix.size(), prefix) != 0)
continue;
2198 size_t begin = prefix.size();
2200 casadi_int this_index;
2206 this_index = std::stoi(n.substr(begin, end - begin));
2209 if (this_index > highest_index) highest_index = this_index;
2213 if (highest_index == 0) {
2214 return prefix +
"_";
2216 return prefix + std::to_string(highest_index + 1) +
"_";
2221 casadi_assert_dev(nfwd>=0);
2236 std::vector<std::string> inames;
2239 for (i=0; i<
n_in_; ++i) inames.push_back(pref +
name_in_[i]);
2241 std::vector<std::string> onames;
2250 opts[
"derivative_of"] =
self();
2254 f =
get_forward(nfwd, fname, inames, onames, opts);
2267 casadi_error(
"Unknown 'fd_method': " +
fd_method_);
2286 casadi_assert_dev(nadj>=0);
2301 std::vector<std::string> inames;
2306 std::vector<std::string> onames;
2307 for (casadi_int i=0; i<
n_in_; ++i) onames.push_back(pref +
name_in_[i]);
2311 opts[
"derivative_of"] =
self();
2314 f =
get_reverse(nadj, fname, inames, onames, opts);
2331 get_forward(casadi_int nfwd,
const std::string& name,
2332 const std::vector<std::string>& inames,
2333 const std::vector<std::string>& onames,
2334 const Dict& opts)
const {
2335 casadi_error(
"'get_forward' not defined for " +
class_name());
2339 get_reverse(casadi_int nadj,
const std::string& name,
2340 const std::vector<std::string>& inames,
2341 const std::vector<std::string>& onames,
2342 const Dict& opts)
const {
2343 casadi_error(
"'get_reverse' not defined for " +
class_name());
2347 const Dict& options)
const {
2348 casadi_error(
"'export_code' not defined for " +
class_name());
2352 casadi_int n = s.size();
2354 std::stringstream ss;
2355 for (casadi_int i=0;i<n;++i) {
2359 casadi_assert_dev(s==ss.str());
2364 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
nnz_in(iind);
2370 for (casadi_int oind=0; oind<
n_out_; ++oind) ret +=
nnz_out(oind);
2376 for (casadi_int iind=0; iind<
n_in_; ++iind) ret +=
numel_in(iind);
2387 bool always_inline,
bool never_inline)
const {
2393 if (always_inline) {
2394 casadi_assert(!never_inline,
"Inconsistent options for " +
str(
name_));
2408 "Derivatives cannot be calculated for " +
name_);
2413 std::string fname =
"jac_" +
name_;
2416 std::vector<std::string> inames;
2417 for (casadi_int i=0; i<
n_in_; ++i) inames.push_back(
name_in_[i]);
2418 for (casadi_int i=0; i<
n_out_; ++i) inames.push_back(
"out_" +
name_out_[i]);
2420 std::vector<std::string> onames;
2422 for (
size_t oind = 0; oind <
n_out_; ++oind) {
2423 for (
size_t iind = 0; iind <
n_in_; ++iind) {
2429 opts[
"derivative_of"] =
self();
2434 casadi_assert(f.
n_in() == inames.size(),
2435 "Mismatching input signature, expected " +
str(inames));
2436 casadi_assert(f.
n_out() == onames.size(),
2437 "Mismatching output signature, expected " +
str(onames));
2446 const std::vector<std::string>& inames,
2447 const std::vector<std::string>& onames,
2448 const Dict& opts)
const {
2449 casadi_error(
"'get_jacobian' not defined for " +
class_name());
2455 g <<
"static " <<
signature(fname) <<
" {\n";
2463 Function F = shared_from_this<Function>();
2465 std::string dump_counter = g.
shorthand(cg_name +
"_dump_counter");
2466 g.
auxiliaries <<
"static int " << dump_counter <<
" = 0;\n";
2469 std::string dump_mutex = g.
local_mutex(F, cg_name +
"_dump_mutex");
2470 g <<
"CASADI_MUTEX_LOCK(&" << dump_mutex <<
");\n";
2471 g <<
"int dump_id_local = " << dump_counter <<
"++;\n";
2472 g <<
"CASADI_MUTEX_UNLOCK(&" << dump_mutex <<
");\n";
2474 g <<
"int dump_id_local = " << dump_counter <<
"++;\n";
2498 return "int " + fname +
"(const casadi_real** arg, casadi_real** res, "
2499 "casadi_int* iw, casadi_real* w, int mem)";
2503 std::vector<std::string> args;
2505 args.push_back(
"const casadi_real* " +
str(e));
2508 args.push_back(
"casadi_real* " +
str(e));
2510 args.push_back(
"const casadi_real** arg");
2511 args.push_back(
"casadi_real** res");
2512 args.push_back(
"casadi_int* iw");
2513 args.push_back(
"casadi_real* w");
2514 args.push_back(
"int mem");
2515 return "int " + fname +
"_unrolled(" +
join(args,
", ") +
")";
2521 std::string ref_counter = g.
shorthand(name +
"_ref_counter");
2522 g.
auxiliaries <<
"static int " << ref_counter <<
" = 0;\n";
2524 Function F = shared_from_this<Function>();
2528 g <<
"#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
2529 g <<
"if (" << ref_counter <<
"==0) CASADI_MUTEX_INIT(&" << mtx <<
");\n";
2533 g << ref_counter <<
"++;\n";
2537 std::set<void*> added;
2538 Function F = shared_from_this<Function>();
2540 if (f->has_refcount_in_deps_) {
2541 std::string cg_name = f->codegen_name(g,
false);
2542 auto i = added.insert(f.get());
2544 std::string incref = g.
shorthand(cg_name +
"_incref");
2545 g << incref <<
"();\n";
2554 std::set<void*> added;
2555 Function F = shared_from_this<Function>();
2557 if (f->has_refcount_in_deps_) {
2558 std::string cg_name = f->codegen_name(g,
false);
2559 auto i = added.insert(f.get());
2561 std::string decref = g.
shorthand(cg_name +
"_decref");
2562 g << decref <<
"();\n";
2569 std::string ref_counter = g.
shorthand(name +
"_ref_counter");
2570 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2572 g << ref_counter <<
"--;\n";
2573 g <<
"if (" << ref_counter <<
"==0) {\n";
2575 g <<
"while (" << mem_counter <<
">0) {\n";
2576 g <<
free_mem <<
"(--" << mem_counter <<
");\n";
2580 Function F = shared_from_this<Function>();
2583 g <<
"#if CASADI_MUTEX_USE_STATIC_INIT == 0\n";
2584 g <<
"CASADI_MUTEX_DESTROY(&" << mtx <<
");\n";
2600 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2601 g <<
"return " + mem_counter +
"++;\n";
2607 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2608 std::string stack = g.
shorthand(name +
"_unused_stack");
2609 std::string mem_counter = g.
shorthand(name +
"_mem_counter");
2610 std::string mem_array = g.
shorthand(name +
"_mem");
2615 g.
auxiliaries <<
"static int " << mem_counter <<
" = 0;\n";
2616 g.
auxiliaries <<
"static int " << stack_counter <<
" = -1;\n";
2617 g.
auxiliaries <<
"static int " << stack <<
"[CASADI_MAX_NUM_THREADS];\n";
2619 " " << mem_array <<
"[CASADI_MAX_NUM_THREADS];\n\n";
2622 Function F = shared_from_this<Function>();
2624 std::string mem_mutex = g.
local_mutex(F, name +
"_mem_mutex");
2625 g <<
"CASADI_MUTEX_LOCK(&" << mem_mutex <<
");\n";
2629 g.
local(
"mid",
"int");
2631 g <<
"if (" << stack_counter <<
">=0) {\n";
2634 g <<
"if (" << mem_counter <<
"==CASADI_MAX_NUM_THREADS) {\n";
2638 g <<
"if (mid<0) {\n";
2641 g <<
"if (" <<
init_mem <<
"(mid)) {\n";
2650 std::string stack_counter = g.
shorthand(name +
"_unused_stack_counter");
2651 std::string stack = g.
shorthand(name +
"_unused_stack");
2654 Function F = shared_from_this<Function>();
2655 std::string mem_mutex = g.
local_mutex(F, name +
"_mem_mutex");
2656 g <<
"CASADI_MUTEX_LOCK(&" << mem_mutex <<
");\n";
2660 g << stack <<
"[++" << stack_counter <<
"] = mem;\n";
2673 g << g.
declare(
"int " +
name_ +
"_checkout(void)") <<
" {\n";
2676 g <<
"return " <<
checkout <<
"();\n";
2683 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2687 g << g.
declare(
"void " +
name_ +
"_release(int mem)") <<
" {\n";
2692 g << g.
declare(
"void " +
name_ +
"_incref(void)") <<
" {\n";
2694 std::string incref = g.
shorthand(name +
"_incref");
2695 g << incref <<
"();\n";
2698 << g.
declare(
"void " +
name_ +
"_decref(void)") <<
" {\n";
2700 std::string decref = g.
shorthand(name +
"_decref");
2701 g << decref <<
"();\n";
2707 <<
" { return " <<
n_in_ <<
";}\n\n"
2709 <<
" { return " <<
n_out_ <<
";}\n\n";
2712 g << g.
declare(
"casadi_real " +
name_ +
"_default_in(casadi_int i)") <<
" {\n"
2713 <<
"switch (i) {\n";
2714 for (casadi_int i=0; i<
n_in_; ++i) {
2716 if (def!=0) g <<
"case " << i <<
": return " << g.
constant(def) <<
";\n";
2718 g <<
"default: return 0;\n}\n"
2722 g << g.
declare(
"const char* " +
name_ +
"_name_in(casadi_int i)") <<
" {\n"
2723 <<
"switch (i) {\n";
2724 for (casadi_int i=0; i<
n_in_; ++i) {
2725 g <<
"case " << i <<
": return \"" <<
name_in_[i] <<
"\";\n";
2727 g <<
"default: return 0;\n}\n"
2731 g << g.
declare(
"const char* " +
name_ +
"_name_out(casadi_int i)") <<
" {\n"
2732 <<
"switch (i) {\n";
2733 for (casadi_int i=0; i<
n_out_; ++i) {
2734 g <<
"case " << i <<
": return \"" <<
name_out_[i] <<
"\";\n";
2736 g <<
"default: return 0;\n}\n"
2744 "int " +
name_ +
"_work(casadi_int *sz_arg, casadi_int* sz_res, "
2745 "casadi_int *sz_iw, casadi_int *sz_w)")
2756 "int " +
name_ +
"_work_bytes(casadi_int *sz_arg, casadi_int* sz_res, "
2757 "casadi_int *sz_iw, casadi_int *sz_w)")
2759 <<
"if (sz_arg) *sz_arg = " <<
codegen_sz_arg(g) <<
"*sizeof(const casadi_real*);\n"
2760 <<
"if (sz_res) *sz_res = " <<
codegen_sz_res(g) <<
"*sizeof(casadi_real*);\n"
2761 <<
"if (sz_iw) *sz_iw = " <<
codegen_sz_iw(g) <<
"*sizeof(casadi_int);\n"
2762 <<
"if (sz_w) *sz_w = " <<
codegen_sz_w(g) <<
"*sizeof(casadi_real);\n"
2777 g << g.
declare(
"int " +
name_ +
"_diff_in(casadi_int i)") <<
" {\n"
2778 <<
"switch (i) {\n";
2779 for (casadi_int i=0; i<
n_in_; ++i) {
2780 g <<
"case " << i <<
": return " <<
is_diff_in_[i] <<
";\n";
2782 g <<
"default: return -1;\n}\n"
2788 g << g.
declare(
"int " +
name_ +
"_diff_out(casadi_int i)") <<
" {\n"
2789 <<
"switch (i) {\n";
2790 for (casadi_int i=0; i<
n_out_; ++i) {
2791 g <<
"case " << i <<
": return " <<
is_diff_out_[i] <<
";\n";
2793 g <<
"default: return -1;\n}\n"
2800 g <<
"#ifdef MATLAB_MEX_FILE\n";
2803 g <<
"void mex_" <<
name_
2804 <<
"(int resc, mxArray *resv[], int argc, const mxArray *argv[]) {\n"
2805 <<
"casadi_int i;\n";
2810 for (casadi_int i=0; i<
n_in_; ++i) {
2815 sz_w += i_nnz + o_nnz;
2818 std::string fw =
"w+" +
str(i_nnz + o_nnz);
2821 casadi_int offset=0;
2825 g <<
"casadi_real* res[" <<
sz_res() <<
"] = {0};\n";
2828 g <<
"if (argc>" <<
n_in_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2829 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. Too many input arguments "
2830 <<
"(%d, max " <<
n_in_ <<
")\", argc);\n";
2832 g <<
"if (resc>" <<
n_out_ <<
") mexErrMsgIdAndTxt(\"Casadi:RuntimeError\","
2833 <<
"\"Evaluation of \\\"" <<
name_ <<
"\\\" failed. "
2834 <<
"Too many output arguments (%d, max " <<
n_out_ <<
")\", resc);\n";
2836 for (casadi_int i=0; i<
n_in_; ++i) {
2837 std::string p =
"argv[" +
str(i) +
"]";
2838 g <<
"if (--argc>=0) arg[" << i <<
"] = "
2843 for (casadi_int i=0; i<
n_out_; ++i) {
2849 g <<
"if (--resc>=0) ";
2852 g << g.
res(i) <<
" = w+" <<
str(offset) <<
";\n";
2855 g <<
name_ <<
"_incref();\n";
2856 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2859 g <<
"i = " <<
name_ <<
"(arg, res, iw, " << fw <<
", mem);\n"
2860 <<
"if (i) mexErrMsgIdAndTxt(\"Casadi:RuntimeError\",\"Evaluation of \\\"" <<
name_
2861 <<
"\\\" failed.\");\n";
2862 g <<
name_ <<
"_release(mem);\n";
2863 g <<
name_ <<
"_decref();\n";
2866 for (casadi_int i=0; i<
n_out_; ++i) {
2867 g <<
"if (" << g.
res(i) <<
") resv[" << i <<
"] = "
2878 g <<
"casadi_int main_" <<
name_ <<
"(casadi_int argc, char* argv[]) {\n";
2880 g <<
"casadi_int j;\n";
2881 g <<
"casadi_real* a;\n";
2882 g <<
"const casadi_real* r;\n";
2883 g <<
"casadi_int flag;\n";
2884 if (needs_mem) g <<
"int mem;\n";
2894 g <<
"const casadi_real* arg[" <<
sz_arg() <<
"];\n";
2897 g <<
"casadi_real* res[" <<
sz_res() <<
"];\n";
2900 for (casadi_int i=0; i<
n_in_; ++i) {
2901 g <<
"arg[" << i <<
"] = w+" << off <<
";\n";
2904 for (casadi_int i=0; i<
n_out_; ++i) {
2905 g <<
"res[" << i <<
"] = w+" << off <<
";\n";
2911 <<
"for (j=0; j<" <<
nnz_in() <<
"; ++j) "
2912 <<
"if (scanf(\"%lg\", a++)<=0) return 2;\n";
2915 g <<
name_ <<
"_incref();\n";
2919 g <<
"mem = " <<
name_ <<
"_checkout();\n";
2923 g <<
"flag = " <<
name_ <<
"(arg, res, iw, w+" << off <<
", ";
2931 g <<
name_ <<
"_release(mem);\n";
2935 g <<
name_ <<
"_decref();\n";
2938 g <<
"if (flag) return flag;\n";
2941 g <<
"r = w+" <<
nnz_in() <<
";\n"
2942 <<
"for (j=0; j<" <<
nnz_out() <<
"; ++j) "
2943 << g.
printf(
"%.16e ",
"*r++") <<
"\n";
2946 g << g.
printf(
"\\n") <<
"\n";
2955 g << g.
declare(
"casadi_functions* " +
name_ +
"_functions(void)") <<
" {\n"
2956 <<
"static casadi_functions fun = {\n"
2957 <<
name_ <<
"_incref,\n"
2958 <<
name_ <<
"_decref,\n"
2959 <<
name_ <<
"_checkout,\n"
2960 <<
name_ <<
"_release,\n"
2961 <<
name_ <<
"_default_in,\n"
2962 <<
name_ <<
"_n_in,\n"
2963 <<
name_ <<
"_n_out,\n"
2964 <<
name_ <<
"_name_in,\n"
2965 <<
name_ <<
"_name_out,\n"
2966 <<
name_ <<
"_sparsity_in,\n"
2967 <<
name_ <<
"_sparsity_out,\n"
2968 <<
name_ <<
"_work,\n"
2982 if (e.f.get()==
this)
return e.codegen_name;
2987 if (e.f.get()==
this)
return "f" +
str(i);
2990 casadi_error(
"Function '" +
name_ +
"' not found");
2995 std::string mem_array = g.
shorthand(name +
"_mem");
2996 return mem_array+
"[" + index +
"]";
3004 casadi_warning(
"The function \"" +
name_ +
"\", which is of type \""
3005 +
class_name() +
"\" cannot be code generated. The generation "
3006 "will proceed, but compilation of the code will not be possible.");
3007 g <<
"#error Code generation not supported for " <<
class_name() <<
"\n";
3012 casadi_error(
"'generate_dependencies' not defined for " +
class_name());
3018 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3019 if (res[oind]==
nullptr)
continue;
3020 std::fill_n(res[oind],
nnz_out(oind), ~
static_cast<bvec_t>(0));
3028 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3030 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
3034 for (casadi_int iind=0; iind<
n_in_; ++iind) {
3036 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
3045 casadi_int* iw,
bvec_t* w,
void* mem, casadi_int oind, casadi_int iind)
const {
3050 casadi_int d1 = sp.
size2();
3051 const casadi_int *colind = sp.
colind(), *row = sp.
row();
3052 for (casadi_int cc=0; cc<d1; ++cc) {
3053 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
3054 res[oind][row[el]] |= arg[iind][cc];
3063 for (casadi_int oind=0; oind<
n_out_; ++oind) {
3065 if (res[oind]==
nullptr ||
nnz_out(oind)==0)
continue;
3068 for (casadi_int iind=0; iind<
n_in_; ++iind) {
3070 if (arg[iind]==
nullptr ||
nnz_in(iind)==0)
continue;
3077 casadi_int d1 = sp.
size2();
3078 const casadi_int *colind = sp.
colind(), *row = sp.
row();
3079 for (casadi_int cc=0; cc<d1; ++cc) {
3080 for (casadi_int el = colind[cc]; el < colind[cc+1]; ++el) {
3081 arg[iind][cc] |= res[oind][row[el]];
3093 size_t& sz_iw,
size_t& sz_w)
const {
3096 sz_iw = this->
sz_iw();
3097 sz_w = this->
sz_w();
3117 sz_arg_tmp_ = std::max(sz_arg_tmp_,
sz_arg);
3125 sz_res_tmp_ = std::max(sz_res_tmp_,
sz_res);
3131 sz_iw_per_ +=
sz_iw;
3133 sz_iw_tmp_ = std::max(sz_iw_tmp_,
sz_iw);
3141 sz_w_tmp_ = std::max(sz_w_tmp_,
sz_w);
3160 for (
const auto& s : m->fstats) {
3161 stats[
"n_call_" +s.first] = s.second.n_call;
3162 stats[
"t_wall_" +s.first] = s.second.t_wall;
3163 stats[
"t_proc_" +s.first] = s.second.t_proc;
3171 casadi_assert(m->stats_available,
3172 "No stats available: Function '" +
name_ +
"' not set up. "
3173 "To get statistics, first evaluate it numerically.");
3218 call_forward(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3219 const std::vector<std::vector<MX> >& fseed,
3220 std::vector<std::vector<MX> >& fsens,
3221 bool always_inline,
bool never_inline)
const {
3222 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3223 casadi_assert(!always_inline,
"Class " +
class_name() +
3224 " cannot be inlined in an MX expression");
3228 "Derivatives cannot be calculated for " +
name_);
3231 casadi_int nfwd = fseed.size();
3235 if (nfwd==0)
return;
3238 casadi_int npar = 1;
3239 for (
auto&& r : fseed) {
3242 fsens, always_inline, never_inline);
3250 std::vector<MX> darg = arg;
3251 darg.insert(darg.end(), res.begin(), res.end());
3252 std::vector<MX> J =
jacobian()(darg);
3254 std::vector<MX> v(nfwd), all_fseed(
n_in_);
3255 for (
size_t i = 0; i <
n_in_; ++i) {
3256 for (
size_t d = 0; d < nfwd; ++d) v[d] = vec(fseed.at(d).at(i));
3257 all_fseed[i] = horzcat(v);
3260 std::vector<MX> all_fsens(
n_out_);
3261 std::vector<MX>::const_iterator J_it = J.begin();
3262 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3263 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3265 MX a = mtimes(*J_it++, all_fseed[iind]);
3266 all_fsens[oind] = all_fsens[oind].is_empty(
true) ? a : all_fsens[oind] + a;
3270 for (
size_t d = 0; d < nfwd; ++d) fsens[d].resize(
n_out_);
3271 for (
size_t i = 0; i <
n_out_; ++i) {
3272 v = horzsplit(all_fsens[i]);
3273 casadi_assert_dev(v.size() == nfwd);
3274 for (
size_t d = 0; d < nfwd; ++d) fsens[d][i] = reshape(v[d],
size_out(i));
3283 casadi_int offset = 0;
3284 while (offset<nfwd) {
3286 casadi_int nfwd_batch = std::min(nfwd-offset, max_nfwd);
3289 std::vector<MX> darg;
3291 darg.insert(darg.end(), arg.begin(), arg.end());
3292 darg.insert(darg.end(), res.begin(), res.end());
3293 std::vector<MX> v(nfwd_batch);
3294 for (casadi_int i=0; i<
n_in_; ++i) {
3295 for (casadi_int d=0; d<nfwd_batch; ++d) v[d] = fseed[offset+d][i];
3296 darg.push_back(horzcat(v));
3301 std::vector<MX> x = dfcn(darg);
3303 casadi_assert_dev(x.size()==
n_out_);
3306 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d].resize(
n_out_);
3307 for (casadi_int i=0; i<
n_out_; ++i) {
3310 casadi_assert_dev(v.size()==nfwd_batch);
3312 v = std::vector<MX>(nfwd_batch,
MX(
size_out(i)));
3314 for (casadi_int d=0; d<nfwd_batch; ++d) fsens[offset+d][i] = v[d];
3318 offset += nfwd_batch;
3324 call_reverse(
const std::vector<MX>& arg,
const std::vector<MX>& res,
3325 const std::vector<std::vector<MX> >& aseed,
3326 std::vector<std::vector<MX> >& asens,
3327 bool always_inline,
bool never_inline)
const {
3328 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3329 casadi_assert(!always_inline,
"Class " +
class_name() +
3330 " cannot be inlined in an MX expression");
3334 "Derivatives cannot be calculated for " +
name_);
3337 casadi_int nadj = aseed.size();
3341 if (nadj==0)
return;
3344 casadi_int npar = 1;
3345 for (
auto&& r : aseed) {
3348 asens, always_inline, never_inline);
3356 std::vector<MX> darg = arg;
3357 darg.insert(darg.end(), res.begin(), res.end());
3358 std::vector<MX> J =
jacobian()(darg);
3360 std::vector<MX> v(nadj), all_aseed(
n_out_);
3361 for (
size_t i = 0; i <
n_out_; ++i) {
3362 for (
size_t d = 0; d < nadj; ++d) v[d] = vec(aseed.at(d).at(i));
3363 all_aseed[i] = horzcat(v);
3366 std::vector<MX> all_asens(
n_in_);
3367 std::vector<MX>::const_iterator J_it = J.begin();
3368 for (
size_t oind = 0; oind <
n_out_; ++oind) {
3369 for (
size_t iind = 0; iind <
n_in_; ++iind) {
3371 MX a = mtimes((*J_it++).
T(), all_aseed[oind]);
3372 all_asens[iind] = all_asens[iind].is_empty(
true) ? a : all_asens[iind] + a;
3376 for (
size_t d = 0; d < nadj; ++d) asens[d].resize(
n_in_);
3377 for (
size_t i = 0; i <
n_in_; ++i) {
3378 v = horzsplit(all_asens[i]);
3379 casadi_assert_dev(v.size() == nadj);
3380 for (
size_t d = 0; d < nadj; ++d) {
3381 if (asens[d][i].is_empty(
true)) {
3382 asens[d][i] = reshape(v[d],
size_in(i));
3384 asens[d][i] += reshape(v[d],
size_in(i));
3394 casadi_int offset = 0;
3395 while (offset<nadj) {
3397 casadi_int nadj_batch = std::min(nadj-offset, max_nadj);
3400 std::vector<MX> darg;
3402 darg.insert(darg.end(), arg.begin(), arg.end());
3403 darg.insert(darg.end(), res.begin(), res.end());
3404 std::vector<MX> v(nadj_batch);
3405 for (casadi_int i=0; i<
n_out_; ++i) {
3406 for (casadi_int d=0; d<nadj_batch; ++d) v[d] = aseed[offset+d][i];
3407 darg.push_back(horzcat(v));
3412 std::vector<MX> x = dfcn(darg);
3413 casadi_assert_dev(x.size()==
n_in_);
3416 for (casadi_int d=0; d<nadj_batch; ++d) asens[offset+d].resize(
n_in_);
3417 for (casadi_int i=0; i<
n_in_; ++i) {
3420 casadi_assert_dev(v.size()==nadj_batch);
3422 v = std::vector<MX>(nadj_batch,
MX(
size_in(i)));
3424 for (casadi_int d=0; d<nadj_batch; ++d) {
3425 if (asens[offset+d][i].is_empty(
true)) {
3426 asens[offset+d][i] = v[d];
3428 asens[offset+d][i] += v[d];
3433 offset += nadj_batch;
3439 call_forward(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3440 const std::vector<std::vector<SX> >& fseed,
3441 std::vector<std::vector<SX> >& fsens,
3442 bool always_inline,
bool never_inline)
const {
3443 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3444 if (fseed.empty()) {
3448 casadi_error(
"'forward' (SX) not defined for " +
class_name());
3452 call_reverse(
const std::vector<SX>& arg,
const std::vector<SX>& res,
3453 const std::vector<std::vector<SX> >& aseed,
3454 std::vector<std::vector<SX> >& asens,
3455 bool always_inline,
bool never_inline)
const {
3456 casadi_assert(!(always_inline && never_inline),
"Inconsistent options");
3457 if (aseed.empty()) {
3461 casadi_error(
"'reverse' (SX) not defined for " +
class_name());
3503 std::vector<SX> ret(
n_in_);
3504 for (casadi_int i=0; i<ret.size(); ++i) {
3511 std::vector<SX> ret(
n_out_);
3512 for (casadi_int i=0; i<ret.size(); ++i) {
3519 std::vector<DM> ret(
n_in_);
3520 for (casadi_int i=0; i<ret.size(); ++i) {
3527 std::vector<DM> ret(
n_out_);
3528 for (casadi_int i=0; i<ret.size(); ++i) {
3543 std::vector<MX> ret(
n_in_);
3544 for (casadi_int i=0; i<ret.size(); ++i) {
3551 std::vector<MX> ret(
n_out_);
3552 for (casadi_int i=0; i<ret.size(); ++i) {
3559 return type ==
"FunctionInternal";
3563 std::vector<MX>& subs_from, std::vector<MX>& subs_to)
const {
3567 casadi_error(
"'free_mx' only defined for 'MXFunction'");
3571 casadi_error(
"'free_sx' only defined for 'SXFunction'");
3576 casadi_error(
"'generate_lifted' only defined for 'MXFunction'");
3580 casadi_error(
"'n_instructions' not defined for " +
class_name());
3584 casadi_error(
"'instruction_id' not defined for " +
class_name());
3588 casadi_error(
"'instruction_input' not defined for " +
class_name());
3592 casadi_error(
"'instruction_constant' not defined for " +
class_name());
3596 casadi_error(
"'instruction_output' not defined for " +
class_name());
3600 casadi_error(
"'instruction_MX' not defined for " +
class_name());
3604 casadi_error(
"'instructions_sx' not defined for " +
class_name());
3608 casadi_error(
"'n_nodes' not defined for " +
class_name());
3613 const std::string& parallelization) {
3614 if (x.empty())
return x;
3616 casadi_assert(x.size()==
n_in_,
"mapsum_mx: Wrong number_i of arguments");
3618 casadi_int npar = 1;
3620 std::vector<MX> x_mod(x.size());
3621 for (casadi_int i=0; i<
n_in_; ++i) {
3632 for (casadi_int i=0; i<x_mod.size(); ++i) {
3633 n = std::max(x_mod[i].size2() /
size2_in(i), n);
3636 std::vector<casadi_int> reduce_in;
3637 for (casadi_int i=0; i<x_mod.size(); ++i) {
3638 if (x_mod[i].size2()/
size2_in(i)!=n) {
3639 reduce_in.push_back(i);
3651 if (arg.
size()==inp.
size())
return true;
3673 casadi_assert(
nnz_in()==arg.size(),
3674 "Dimension mismatch. Expecting " +
str(
nnz_in()) +
3675 ", got " +
str(arg.size()) +
" instead.");
3677 std::vector<DM> ret =
dm_in();
3678 casadi_int offset = 0;
3679 for (casadi_int i=0;i<
n_in_;++i) {
3681 std::copy(arg.begin()+offset, arg.begin()+offset+
nnz_in(i), r.
ptr());
3688 casadi_assert(
nnz_out()==res.size(),
3689 "Dimension mismatch. Expecting " +
str(
nnz_out()) +
3690 ", got " +
str(res.size()) +
" instead.");
3692 std::vector<DM> ret =
dm_out();
3693 casadi_int offset = 0;
3694 for (casadi_int i=0;i<
n_out_;++i) {
3696 std::copy(res.begin()+offset, res.begin()+offset+
nnz_out(i), r.
ptr());
3704 casadi_int npar = -1;
3710 std::vector<double> ret(
nnz_in());
3711 casadi_int offset = 0;
3712 for (casadi_int i=0;i<
n_in_;++i) {
3713 const double* e = arg2.at(i).ptr();
3714 std::copy(e, e+
nnz_in(i), ret.begin()+offset);
3722 casadi_int npar = -1;
3728 std::vector<double> ret(
nnz_out());
3729 casadi_int offset = 0;
3730 for (casadi_int i=0;i<
n_out_;++i) {
3731 const double* e = res2.at(i).ptr();
3732 std::copy(e, e+
nnz_out(i), ret.begin()+offset);
3739 casadi_int* iw,
double* w)
const {
3747 for (
auto&& i : mem_) {
3756 if (
name_ ==
"jac_" + n) {
3758 }
else if (
name_ ==
"adj1_" + n) {
3769 if (
name_ ==
"jac_" + n) {
3771 }
else if (
name_ ==
"adj1_" + n) {
3782 if (
name_ ==
"jac_" + n ||
name_ ==
"adj1_" + n) {
3803 if (
name_ ==
"jac_" + n) {
3817 std::vector<casadi_int> row, colind;
3818 row.reserve(sp_out.
nnz() * sp_in.
nnz());
3819 colind.reserve(sp_in.
numel() + 1);
3821 for (casadi_int c1 = 0; c1 < sp_in.
size2(); ++c1) {
3822 for (casadi_int k1 = sp_in.
colind(c1); k1 < sp_in.
colind(c1 + 1); ++k1) {
3823 casadi_int e1 = sp_in.
row(k1) + sp_in.
size1() * c1;
3825 colind.resize(e1 + 1, row.size());
3827 for (casadi_int c2 = 0; c2 < sp_out.
size2(); ++c2) {
3828 for (casadi_int k2 = sp_out.
colind(c2); k2 < sp_out.
colind(c2 + 1); ++k2) {
3829 row.push_back(sp_out.
row(k2) + sp_out.
size1() * c2);
3835 colind.resize(sp_in.
numel() + 1, row.size());
3838 }
else if (
name_ ==
"adj1_" + n) {
3848 #ifdef CASADI_WITH_THREAD
3849 std::lock_guard<std::mutex> lock(mtx_);
3851 return mem_.at(ind);
3855 return ind<mem_.size();
3859 #ifdef CASADI_WITH_THREAD
3860 std::lock_guard<std::mutex> lock(mtx_);
3862 if (unused_.empty()) {
3868 casadi_error(
"Failed to create or initialize memory object");
3870 return static_cast<int>(mem_.size()) - 1;
3873 int m = unused_.top();
3880 #ifdef CASADI_WITH_THREAD
3881 std::lock_guard<std::mutex> lock(mtx_);
3887 factory(
const std::string& name,
3888 const std::vector<std::string>& s_in,
3889 const std::vector<std::string>& s_out,
3891 const Dict& opts)
const {
3892 return wrap().
factory(name, s_in, s_out, aux, opts);
3897 return std::vector<std::string>();
3901 casadi_error(
"'get_function' not defined for " +
class_name());
3908 const Function& dep, casadi_int max_depth)
const {
3910 if (!dep.
is_null() && all_fun.find(dep.
get()) == all_fun.end()) {
3912 all_fun[dep.
get()] = std::make_pair(dep, all_fun.size());
3914 if (max_depth > 0) dep->
find(all_fun, max_depth - 1);
3919 casadi_int max_depth)
const {
3926 which_depends(
const std::string& s_in,
const std::vector<std::string>& s_out,
3927 casadi_int order,
bool tr)
const {
3928 Function f = shared_from_this<Function>();
3934 const std::vector<std::pair<std::string, casadi_int> >& tasks)
const {
3935 casadi_assert(tasks.empty(),
"simplify passes not supported for " +
class_name());
3940 casadi_error(
"'oracle' not defined for " +
class_name());
3946 const std::vector<casadi_int>& order_in,
3947 const std::vector<casadi_int>& order_out,
const Dict& opts)
const {
3948 return wrap().
slice(name, order_in, order_out, opts);
3953 for (casadi_int i=0; i<
n_in_; ++i) {
3957 for (casadi_int i=0; i<
n_out_; ++i) {
3965 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
3967 std::lock_guard<std::mutex> lock(jac_sparsity_mtx_);
3969 casadi_int ind = iind + oind *
n_in_;
3977 eval(
const double** arg,
double** res, casadi_int* iw,
double* w,
void* mem)
const {
3982 std::vector<DM> argv(
n_in_);
3983 for (casadi_int i=0; i<
n_in_; ++i) {
3985 casadi_copy(arg[i], argv[i].nnz(), argv[i].ptr());
3989 std::vector<DM> resv =
eval_dm(argv);
3992 casadi_assert(resv.size()==
n_out_,
3993 "Expected " +
str(
n_out_) +
" outputs, got " +
str(resv.size()) +
".");
3996 for (casadi_int i=0; i<
n_out_; ++i) {
4001 casadi_error(
"Shape mismatch for output " +
str(i) +
": got " + resv[i].dim() +
", "
4005 if (res[i])
casadi_copy(resv[i].ptr(), resv[i].nnz(), res[i]);
4009 }
catch(std::exception& e) {
4010 casadi_error(
"Failed to evaluate 'eval_dm' for " +
name_ +
":\n" + e.what());
4015 casadi_error(
"'eval' not defined for " +
class_name());
4024 for (
auto &&s : fstats) {
4025 name_len = std::max(s.first.size(), name_len);
4027 name_len = std::max(
name_.size(), name_len);
4031 sprint(namefmt,
sizeof(namefmt),
"%%%ds ",
static_cast<casadi_int
>(name_len));
4036 print(
" : %8s %10s %8s %10s %9s\n",
"t_proc",
"(avg)",
"t_wall",
"(avg)",
"n_eval");
4039 char buffer_proc[10];
4040 char buffer_wall[10];
4041 char buffer_proc_avg[10];
4042 char buffer_wall_avg[10];
4045 for (
const auto &s : fstats) {
4046 if (s.second.n_call!=0) {
4047 print(namefmt, s.first.c_str());
4050 format_time(buffer_proc_avg, s.second.t_proc/s.second.n_call);
4051 format_time(buffer_wall_avg, s.second.t_wall/s.second.n_call);
4052 print(
" | %s (%s) %s (%s) %9d\n",
4053 buffer_proc, buffer_proc_avg,
4054 buffer_wall, buffer_wall_avg, s.second.n_call);
4061 casadi_assert_dev(time>=0);
4062 double log_time = log10(time);
4063 int magn =
static_cast<int>(floor(log_time));
4064 int iprefix =
static_cast<int>(floor(log_time/3));
4066 sprint(buffer, 10,
" 0");
4070 sprint(buffer, 10,
" inf");
4073 char prefixes[] =
"TGMk munp";
4074 char prefix = prefixes[4-iprefix];
4076 int rem = magn-3*iprefix;
4077 double time_normalized = time/pow(10, 3*iprefix);
4080 sprint(buffer, 10,
" %1.2f%cs", time_normalized, prefix);
4081 }
else if (rem==1) {
4082 sprint(buffer, 10,
" %2.2f%cs", time_normalized, prefix);
4084 sprint(buffer, 10,
"%3.2f%cs", time_normalized, prefix);
4091 va_start(args, fmt);
4093 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
4097 casadi_assert(n>=0 && n<buf_sz,
"Print failure while processing '" + std::string(fmt) +
"'");
4103 va_start(args, fmt);
4106 size_t buf_sz =
sizeof(buf);
4107 char* buf_dyn =
nullptr;
4109 casadi_int n = vsnprintf(buf, buf_sz, fmt, args);
4111 if (n>
static_cast<casadi_int
>(buf_sz)) {
4112 buf_sz =
static_cast<size_t>(n+1);
4113 buf_dyn =
new char[buf_sz];
4114 n = vsnprintf(buf_dyn, buf_sz, fmt, args);
4117 if (n>=0)
uout() << (buf_dyn ? buf_dyn : buf) << std::flush;
4122 casadi_assert(n>=0,
"Print failure while processing '" + std::string(fmt) +
"'");
4127 bool always_inline,
bool never_inline)
const {
4129 eval_mx(arg, res, always_inline, never_inline);
4132 std::vector<std::vector<MX>> v(npar, arg);
4134 for (
int i=0; i<
n_in_; ++i) {
4136 t = horzsplit(arg[i],
size2_in(i));
4137 casadi_assert_dev(t.size()==npar);
4138 for (
int p=0; p<npar; ++p) v[p][i] = t[p];
4142 for (
int p=0; p<npar; ++p) {
4143 eval_mx(v[p], t, always_inline, never_inline);
4149 for (
int i=0; i<
n_out_; ++i) {
4150 for (
int p=0; p<npar; ++p) t[p] = v[p][i];
4151 res[i] = horzcat(t);
4161 default:
return "SOLVER_RET_UNKNOWN";
4166 s.
version(
"ProtoFunction", 2);
4176 int version = s.
version(
"ProtoFunction", 1, 2);
4191 s.
version(
"FunctionInternal", 8);
4199 s.
pack(
"FunctionInternal::jit",
jit_);
4207 casadi_assert(binary_ptr,
"Could not open library '" +
compiler_.
library() +
"'.");
4208 s.
pack(
"FunctionInternal::jit_binary", *binary_ptr);
4259 s.
pack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4260 s.
pack(
"FunctionInternal::sz_res_per", sz_res_per_);
4261 s.
pack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4262 s.
pack(
"FunctionInternal::sz_w_per", sz_w_per_);
4263 s.
pack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4264 s.
pack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4265 s.
pack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4266 s.
pack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4275 int version = s.
version(
"FunctionInternal", 1, 8);
4291 std::string library;
4292 s.
unpack(
"FunctionInternal::jit_library", library);
4298 std::stringstream ss;
4299 s.
unpack(
"FunctionInternal::jit_binary", ss);
4302 s.
unpack(
"FunctionInternal::jit_binary", *binary_ptr);
4376 s.
unpack(
"FunctionInternal::sz_arg_per", sz_arg_per_);
4377 s.
unpack(
"FunctionInternal::sz_res_per", sz_res_per_);
4378 s.
unpack(
"FunctionInternal::sz_iw_per", sz_iw_per_);
4379 s.
unpack(
"FunctionInternal::sz_w_per", sz_w_per_);
4380 s.
unpack(
"FunctionInternal::sz_arg_tmp", sz_arg_tmp_);
4381 s.
unpack(
"FunctionInternal::sz_res_tmp", sz_res_tmp_);
4382 s.
unpack(
"FunctionInternal::sz_iw_tmp", sz_iw_tmp_);
4383 s.
unpack(
"FunctionInternal::sz_w_tmp", sz_w_tmp_);
4399 std::string base_function;
4400 s.
unpack(
"FunctionInternal::base_function", base_function);
4403 "FunctionInternal::deserialize: not found '" + base_function +
"'");
4406 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 scope_add_cleanup(const std::string &code)
Add cleanup code to be executed upon scope exit.
const std::set< std::string > & local_mutexes(const Function &f) const
Get all mutex names associated with a function.
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.
bool thread_safe() const
Emit thead safe code chekout/release?
static std::string array(const std::string &type, const std::string &name, casadi_int len, const std::string &def=std::string())
void generate_dump(const Function &f, const std::string &arr, bool is_input)
Generate dump_in or dump_out code for a function call.
std::string generate(const std::string &prefix="")
Generate file(s)
void generate_print(const Function &f, const std::string &arr, bool is_input)
Generate print_in or print_out code for a function call.
void local(const std::string &name, const std::string &type, const std::string &ref="")
Declare a local variable.
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::string local_mutex(const Function &f, const std::string &name) const
Access a static mutex associated with a function.
std::vector< FunctionMeta > added_functions_
std::string shorthand(const std::string &name) const
Get a shorthand.
void scope_return(const std::string &value)
Return from a scope with a value.
std::stringstream auxiliaries
void define_local_mutex(const Function &f, const std::string &name)
Declare a static mutex associated with a function.
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 std::string absolute(const std::string &path)
static bool is_absolute(const std::string &path)
static std::string ensure_trailing_slash(const std::string &path)
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
static std::unique_ptr< std::istream > ifstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::in, bool fail=true)
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize without type information.
Internal class for Function.
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 codegen_decref(CodeGenerator &g) const
Codegen decref for dependencies.
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.
casadi_int numel_out() const
Number of input/output elements.
Function custom_jacobian_
std::string definition() const
Get function signature: name:(inputs)->(outputs)
const Sparsity & sparsity_in(casadi_int ind) const
Input/output sparsity.
static std::string get_jit_directory(const Dict &jit_options)
Get JIT directory from options.
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.
std::vector< Function > registered_functions_
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)
static void print_canonical(std::ostream &stream, const Sparsity &sp, const double *nz)
Print canonical representation of a numeric matrix.
bool jit_
Use just-in-time compiler.
void add_embedded(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, const Function &dep, casadi_int max_depth) const
eval_t eval_
Numerical evaluation redirected to a C function.
bool has_refcount_in_deps_
Reference counting in dependent functions.
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 void find(std::map< FunctionInternal *, std::pair< Function, size_t > > &all_fun, casadi_int max_depth) const
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 Function simplify_passes(const std::vector< std::pair< std::string, casadi_int > > &tasks) const
Apply an ordered list of simplify passes (used by transform)
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.
virtual int eval_activity(const bvec_t **arg, bvec_t **res, casadi_int *iw, bvec_t *w, void *mem) const
Propagate signal activity forward.
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.
Function wrap_as_needed(const std::string &name, const Dict &opts) const
Wrap in an Function instance consisting of only one MX call.
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
signal_t incref_
Incref/decref redirected to C functions.
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.
virtual bool codegen_needs_mem() const
Is thread-local memory object needed?
Sparsity get_jac_sparsity_gen(casadi_int oind, casadi_int iind) const
Get the sparsity pattern via sparsity seed propagation.
std::string jit_directory_
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.
void reset_dump_count()
Reset the counter used to name dump files.
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.
Dict cache_init_
Values to prepopulate the function cache with.
void free_mem(void *mem) const override
Free memory block.
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.
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 void codegen_incref(CodeGenerator &g) const
Codegen incref for dependencies.
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 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.
std::vector< Function > find_functions(casadi_int max_depth=-1) const
Get all functions embedded in the expression graphs.
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 std::string getTempWorkDir()
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.
static ProtoFunction * deserialize(DeserializingStream &s)
Deserialize into a plugin instance (dispatches on the plugin name)
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)
bool is_dense() const
Is dense?
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.
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)
void(* signal_t)(void)
Function pointer types for the C API.
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.
std::string temporary_file(const std::string &prefix, const std::string &suffix, const std::string &directory)
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)