26 #include "fmu_function.hpp"
27 #include "casadi_misc.hpp"
28 #include "serializing_stream.hpp"
29 #include "dae_builder_internal.hpp"
30 #include "filesystem_impl.hpp"
41 #ifdef CASADI_WITH_THREAD
42 #ifdef CASADI_WITH_THREAD_MINGW
43 #include <mingw.thread.h>
49 #if defined(CASADI_WITH_THREAD) || defined(WITH_OPENMP)
58 "declares 'canBeInstantiatedOnlyOncePerProcess' to be true. "
59 "Regenerate your FMU with this option set to false.");
64 casadi_assert(mem !=
nullptr,
"Memory is null");
68 casadi_int n_mem = std::max(
static_cast<casadi_int
>(1),
72 for (casadi_int i = 0; i < n_mem; ++i) {
97 casadi_assert(mem !=
nullptr,
"Memory is null");
120 const std::vector<std::string>& name_in,
121 const std::vector<std::string>& name_out)
124 in_.resize(name_in.size());
125 for (
size_t k = 0; k < name_in.size(); ++k) {
128 }
catch (std::exception& e) {
129 casadi_error(
"Cannot process input " + name_in[k] +
": " + std::string(e.what()));
133 out_.resize(name_out.size());
134 for (
size_t k = 0; k < name_out.size(); ++k) {
137 }
catch (std::exception& e) {
138 casadi_error(
"Cannot process output " + name_out[k] +
": " + std::string(e.what()));
143 for (
auto&& i :
out_) {
197 if (option_name ==
"print_progress") {
199 }
else if (option_name ==
"step") {
200 step_ = option_value;
201 }
else if (option_name ==
"fd_method") {
204 }
else if (option_name ==
"uses_directional_derivatives") {
206 bool v = option_value;
208 "FMU does not provide support for analytic derivatives");
210 }
else if (option_name ==
"uses_adjoint_derivatives") {
212 bool v = option_value;
214 "FMU does not provide support for adjoint derivatives");
216 }
else if (option_name ==
"enable_forward_jacobian") {
218 }
else if (option_name ==
"enable_adjoint_hessian") {
219 bool v = option_value;
221 "FMU does not provide support for adjoint derivatives");
223 }
else if (option_name ==
"fd_flip") {
225 }
else if (option_name ==
"make_symmetric") {
227 }
else if (option_name ==
"hessian_coloring") {
228 bool v = option_value;
231 "Can only change Hessian coloring if both colorings are available");
249 "Names of the inputs in the scheme"}},
252 "Names of the outputs in the scheme"}},
255 "Definitions of the scheme variables"}},
258 "Auxilliary variables"}},
261 "[DEPRECATED] Renamed uses_directional_derivatives"}},
264 "Number of forward sensitivities to be calculated [1]"}},
267 "Number of adjoint sensitivities to be calculated [1]"}},
268 {
"uses_directional_derivatives",
270 "Use the analytic forward directional derivative support in the FMU"}},
271 {
"uses_adjoint_derivatives",
273 "Use the analytic adjoint derivative support in the FMU"}},
276 "Compare forward derivatives with finite differences for validation"}},
279 "Validate entries of the Hessian for self-consistency"}},
282 "[DEPRECATED] Renamed 'validate_forward'"}},
285 "Redirect results of Hessian validation to a file instead of generating a warning"}},
288 "[DEPRECATED] Renamed 'validate_hessian'"}},
291 "Ensure Hessian is symmetric"}},
294 "Step size, scaled by nominal value"}},
297 "Allow flipping the sign of the finite difference step to keep it in bounds"}},
300 "Absolute error tolerance, scaled by nominal value"}},
303 "Relative error tolerance"}},
306 "Parallelization [SERIAL|openmp|thread]"}},
309 "Print progress during Jacobian/Hessian evaluation"}},
312 "Use forward AD implementation in class (conversion option, to be removed)"}},
315 "Use Jacobian implementation in class (conversion option, to be removed)"}},
318 "Use Hessian implementation in class (conversion option, to be removed)"}},
321 "Calculate Hessian using symmetry exploiting graph coloring (star coloring)."}},
322 {
"asymmetric_hessian_coloring",
324 "Calculate Hessian using unidirectional graph coloring (star coloring). Ensures that upper "
325 "and lower triangular parts are calculated separately, which may be desirable for "
326 "diagnostics. If both symmetric coloring ('hessian_coloring' option) and asymmetric coloring "
327 "is enabled, the symmetric coloring will be used."}},
328 {
"enable_forward_jacobian",
330 "Allow Jacobian calculation using forward mode AD."}},
331 {
"enable_adjoint_jacobian",
333 "Allow Jacobian calculation using adjoint mode AD."}},
334 {
"enable_adjoint_hessian",
336 "Use finite differencing of adjoints for Hessian calculation."}}
342 for (
auto&& op : opts) {
343 if (op.first==
"enable_ad") {
344 casadi_warning(
"Option 'enable_ad' has been renamed 'uses_directional_derivatives'");
346 }
else if (op.first==
"uses_directional_derivatives") {
348 }
else if (op.first==
"nfwd") {
350 }
else if (op.first==
"nadj") {
352 }
else if (op.first==
"uses_adjoint_derivatives") {
354 }
else if (op.first==
"validate_forward") {
356 }
else if (op.first==
"validate_hessian") {
358 }
else if (op.first==
"validate_ad") {
359 casadi_warning(
"Option 'validate_ad' has been renamed 'validate_forward'");
361 }
else if (op.first==
"check_hessian") {
362 casadi_warning(
"Option 'check_hessian' has been renamed 'validate_hessian'");
364 }
else if (op.first==
"validate_ad_file") {
366 }
else if (op.first==
"make_symmetric") {
368 }
else if (op.first==
"step") {
370 }
else if (op.first==
"fd_flip") {
372 }
else if (op.first==
"abstol") {
374 }
else if (op.first==
"reltol") {
376 }
else if (op.first==
"parallelization") {
378 }
else if (op.first==
"print_progress") {
380 }
else if (op.first==
"new_forward") {
382 }
else if (op.first==
"new_jacobian") {
384 }
else if (op.first==
"new_hessian") {
386 }
else if (op.first==
"hessian_coloring") {
388 }
else if (op.first==
"asymmetric_hessian_coloring") {
390 }
else if (op.first==
"enable_forward_jacobian") {
392 }
else if (op.first==
"enable_adjoint_jacobian") {
394 }
else if (op.first==
"enable_adjoint_hessian") {
407 "FMU does not provide support for analytic derivatives");
410 "FMU does not provide support for adjoint derivatives");
416 std::ostream& valfile = *valfile_ptr;
417 valfile <<
"Output Input Value Nominal Min Max AD FD Step Offset Stencil" << std::endl;
426 if (
verbose_) casadi_message(
"Serial evaluation");
434 #ifdef CASADI_WITH_THREAD
442 +
" not enabled during compilation. Falling back to serial evaluation");
448 std::vector<size_t> in_jac(
fmu_.
n_in(), 0);
451 for (
auto&& i :
out_) {
455 const std::vector<size_t>& iind =
fmu_.
ired(i.wrt);
457 if (iind.empty())
continue;
459 bool exists = in_jac[iind.front()] > 0;
460 for (
size_t j : iind) casadi_assert((in_jac[j] > 0) == exists,
"Jacobian not a block");
463 for (
size_t j : iind) {
470 i.cbegin = in_jac[iind.front()] - 1;
471 i.cend = i.cbegin + iind.size();
475 const std::vector<size_t>& iind =
fmu_.
ired(i.ind);
477 if (iind.empty())
continue;
479 bool exists = in_jac[iind.front()] > 0;
480 for (
size_t j : iind) casadi_assert((in_jac[j] > 0) == exists,
"Hessian not a block");
483 for (
size_t j : iind) {
490 i.rbegin = in_jac[iind.front()] - 1;
491 i.rend = i.rbegin + iind.size();
502 std::fill(in_jac.begin(), in_jac.end(), 0);
504 for (
size_t k = 0; k <
out_.size(); ++k) {
508 const std::vector<size_t>& oind =
fmu_.
ored(i.
ind);
510 if (oind.empty())
continue;
512 bool exists = in_jac[oind.front()] > 0;
513 for (
size_t j : oind) casadi_assert((in_jac[j] > 0) == exists,
"Jacobian not a block");
516 for (
size_t j : oind) {
522 i.
rbegin = in_jac[oind.front()] - 1;
538 for (
auto&& i :
in_) {
541 const std::vector<size_t>& oind =
fmu_.
ored(i.ind);
543 if (oind.empty())
continue;
545 bool exists = in_jac[oind.front()] > 0;
546 for (
size_t j : oind) casadi_assert((in_jac[j] > 0) == exists,
"Jacobian not a block");
549 for (
size_t j : oind) {
579 if (
verbose_) casadi_message(
"Jacobian graph coloring via adjoint derivatives: "
611 std::vector<bool> is_nonlin(
jac_in_.size(),
false);
612 for (casadi_int k = 0; k < hess_nnz; ++k) is_nonlin[hess_row[k]] =
true;
614 std::vector<casadi_int> lin;
615 for (casadi_int c = 0; c <
jac_in_.size(); ++c) {
623 casadi_int max_hessian_colors = 0;
629 +
" -> " +
str(max_hessian_colors) +
" directions");
638 if (
verbose_) casadi_message(
"Hessian unidirectional coloring with "
649 casadi_message(
"Hessian calculation for " +
str(
nonlin_.size()) +
" variables");
672 casadi_int jac_iw, jac_w;
673 casadi_jac_work(&
jac_prob_, &jac_iw, &jac_w);
679 casadi_jac_work(&
adj_prob_, &jac_iw, &jac_w);
689 std::vector<std::string>* scheme_in,
690 std::vector<std::string>* scheme_out,
691 const std::vector<std::string>& name_in,
692 const std::vector<std::string>& name_out) {
694 if (scheme_in) scheme_in->clear();
695 if (scheme_out) scheme_out->clear();
697 for (
const std::string& n : name_in) {
700 }
catch (std::exception& e) {
701 casadi_error(
"Cannot process input " + n +
": " + std::string(e.what()));
705 for (
const std::string& n : name_out) {
708 }
catch (std::exception& e) {
709 casadi_error(
"Cannot process output " + n +
": " + std::string(e.what()));
714 std::set<std::string> s(scheme_in->begin(), scheme_in->end());
715 scheme_in->assign(s.begin(), s.end());
719 std::set<std::string> s(scheme_out->begin(), scheme_out->end());
720 scheme_out->assign(s.begin(), s.end());
725 std::vector<std::string>* name_in, std::vector<std::string>* name_out) {
731 std::string pref, rem;
740 if (name_in) name_in->push_back(rem);
742 casadi_error(
"Cannot process: " + n);
748 if (name_out) name_out->push_back(rem);
750 }
else if (pref ==
"fwd") {
754 if (name_in) name_in->push_back(rem);
755 }
else if (pref ==
"adj") {
759 if (name_out) name_out->push_back(rem);
762 casadi_error(
"No such prefix: " + pref);
768 if (name_in) name_in->push_back(n);
775 std::vector<std::string>* name_in, std::vector<std::string>* name_out) {
781 std::string pref, rem;
785 casadi_assert(
has_prefix(rem),
"Two arguments expected for Jacobian block");
789 casadi_assert(
has_prefix(rem),
"Two arguments expected for Jacobian block");
793 std::string sens = pref;
799 if (name_out) name_out->push_back(rem);
801 if (name_in) name_in->push_back(sens);
802 }
else if (pref ==
"out") {
806 if (name_in) name_in->push_back(sens);
808 if (name_in) name_out->push_back(rem);
810 casadi_error(
"No such prefix: " + pref);
816 if (name_in) name_in->push_back(pref);
818 if (name_in) name_in->push_back(rem);
822 std::string out = pref;
828 if (name_out) name_out->push_back(out);
830 if (name_out) name_out->push_back(rem);
832 casadi_error(
"No such prefix: " + pref);
838 if (name_out) name_out->push_back(pref);
840 if (name_in) name_in->push_back(rem);
843 }
else if (pref ==
"fwd") {
847 if (name_out) name_out->push_back(rem);
848 }
else if (pref ==
"adj") {
852 if (name_in) name_in->push_back(rem);
855 casadi_error(
"No such prefix: " + pref);
861 if (name_out) name_out->push_back(n);
868 switch (
in_.at(i).type) {
885 switch (
out_.at(i).type) {
907 switch (
in_.at(i).type) {
922 switch (
out_.at(i).type) {
929 casadi_warning(
"FmuFunction::get_nominal_out not implemented for OutputType::JAC");
932 casadi_warning(
"FmuFunction::get_nominal_out not implemented for OutputType::JAC_TRANS");
935 casadi_warning(
"FmuFunction::get_nominal_out not implemented for OutputType::JAC_ADJ_OUT");
938 casadi_warning(
"FmuFunction::get_nominal_out not implemented for OutputType::JAC_REG_ADJ");
941 casadi_warning(
"FmuFunction::get_nominal_out not implemented for OutputType::HESS");
952 casadi_assert(m !=
nullptr,
"Memory is null");
953 setup(mem, arg, res, iw, w);
958 bool need_jac =
false, need_fwd =
false, need_adj =
false, need_hess =
false;
959 for (
size_t k = 0; k <
out_.size(); ++k) {
961 switch (
out_[k].type) {
982 double *aseed =
nullptr, *asens =
nullptr, *jac_nz =
nullptr, *hess_nz =
nullptr;
996 for (
size_t i = 0; i <
in_.size(); ++i) {
998 const std::vector<size_t>& oind =
fmu_.
ored(
in_[i].ind);
999 for (casadi_int d = 0; d <
nadj_; ++d) {
1002 for (
size_t k = 0; k < oind.size(); ++k) aseed[oind[k] + aseed_off] = arg[i][k + off];
1013 for (casadi_int task = 0; task <
max_n_tasks_; ++task) {
1036 casadi_message(
"Evaluating regular outputs, forward sens, extended Jacobian");
1054 for (
size_t k = 0; k <
out_.size(); ++k) {
1059 switch (
out_[k].type) {
1061 casadi_get_sub(r,
jac_sp_, jac_nz,
1065 casadi_get_sub(w,
jac_sp_, jac_nz,
1071 for (casadi_int d = 0; d <
nadj_; ++d) {
1072 size_t asens_off = d *
fmu_.
n_in();
1073 for (
size_t id :
fmu_.
ired(
out_[k].wrt)) *r++ = asens[
id + asens_off];
1077 casadi_get_sub(r,
hess_sp_, hess_nz,
1089 bool need_nondiff,
bool need_jac,
bool need_fwd,
bool need_adj,
bool need_hess)
const {
1094 || (!need_jac && !need_adj && !need_hess)) {
1096 flag =
eval_task(m, 0, 1, need_nondiff, need_jac, need_fwd, need_adj, need_hess);
1101 std::fegetenv(&fenv);
1103 #pragma omp parallel reduction(||:flag)
1105 std::fesetenv(&fenv);
1107 casadi_int task = omp_get_thread_num();
1109 casadi_int num_threads = omp_get_num_threads();
1111 casadi_int num_used_threads = std::min(num_threads, n_task);
1113 if (task < num_used_threads) {
1115 flag =
eval_task(s, task, num_used_threads, need_nondiff && task == 0,
1116 need_jac, need_fwd && task <
nfwd_, need_adj, need_hess);
1126 #ifdef CASADI_WITH_THREAD
1128 std::vector<int> flag_task(n_task);
1131 std::fegetenv(&fenv);
1133 std::vector<std::thread> threads;
1134 for (casadi_int task = 0; task < n_task; ++task) {
1135 threads.emplace_back(
1136 [&, task](
int* fl) {
1137 std::fesetenv(&fenv);
1139 *fl =
eval_task(s, task, n_task, need_nondiff && task == 0,
1140 need_jac, need_fwd && task <
nfwd_, need_adj, need_hess);
1141 }, &flag_task[task]);
1144 for (
auto&& th : threads) th.join();
1146 for (
int fl : flag_task) flag = flag || fl;
1158 bool need_nondiff,
bool need_jac,
bool need_fwd,
bool need_adj,
bool need_hess)
const {
1160 for (
size_t k = 0; k <
in_.size(); ++k) {
1166 for (
size_t k = 0; k <
out_.size(); ++k) {
1175 for (
size_t k = 0; k <
out_.size(); ++k) {
1184 casadi_int d_begin = (task *
nfwd_) / n_task;
1185 casadi_int d_end = ((task + 1) *
nfwd_) / n_task;
1187 for (casadi_int d = d_begin; d < d_end; ++d) {
1190 task + 1, n_task, d - d_begin + 1, d_end - d_begin);
1192 for (
size_t k = 0; k <
in_.size(); ++k) {
1198 for (
size_t k = 0; k <
out_.size(); ++k) {
1206 for (
size_t k = 0; k <
out_.size(); ++k) {
1221 for (casadi_int c = c_begin; c < c_end; ++c) {
1224 task + 1, n_task, c - c_begin + 1, c_end - c_begin);
1242 for (casadi_int d = 0; d <
nadj_; ++d) {
1244 size_t asens_off = d *
fmu_.
n_in();
1255 casadi_assert(need_jac,
"Inconsistent options");
1260 for (casadi_int c = c_begin; c < c_end; ++c) {
1263 "Seeding variable %d/%d\n", task + 1, n_task, c - c_begin + 1, c_end - c_begin);
1279 }
else if (need_adj) {
1281 casadi_int d_begin = (task *
nadj_) / n_task;
1282 casadi_int d_end = ((task + 1) *
nadj_) / n_task;
1284 for (casadi_int d = d_begin; d < d_end; ++d) {
1287 task + 1, n_task, d - d_begin + 1, d_end - d_begin);
1289 for (
size_t k = 0; k <
in_.size(); ++k) {
1295 casadi_int wrt_id = -1;
1296 for (casadi_int
id :
jac_in_) {
1302 for (casadi_int
id :
jac_in_) {
1311 casadi_int n_hc = hc.
size2();
1312 const casadi_int *hc_colind = hc.
colind(), *hc_row = hc.
row();
1316 casadi_int c_begin = (task * n_hc) / n_task;
1317 casadi_int c_end = ((task + 1) * n_hc) / n_task;
1319 std::vector<double> x, h;
1321 for (casadi_int c = c_begin; c < c_end; ++c) {
1324 task + 1, n_task, c - c_begin + 1, c_end - c_begin);
1326 casadi_int v_begin = hc_colind[c];
1327 casadi_int v_end = hc_colind[c + 1];
1328 casadi_int nv = v_end - v_begin;
1332 for (casadi_int v = 0; v < nv; ++v) {
1334 casadi_int ind1 = hc_row[v_begin + v];
1335 casadi_int
id =
jac_in_.at(ind1);
1337 x[v] = m->
ibuf_.at(
id);
1352 if (!std::isnan(h[v])) {
1353 m->
ibuf_.at(
id) += h[v];
1371 for (
size_t k = 0; k <
in_.size(); ++k) {
1377 casadi_int wrt_id = -1;
1378 for (casadi_int
id :
jac_in_) {
1384 for (casadi_int
id :
jac_in_) {
1405 for (casadi_int v = 0; v < nv; ++v) {
1407 casadi_int ind1 = hc_row[v_begin + v];
1408 casadi_int
id =
jac_in_.at(ind1);
1410 m->
ibuf_.at(
id) = x[v];
1413 for (casadi_int k = hess_colind[ind1]; k < hess_colind[ind1 + 1]; ++k) {
1416 if (std::isnan(h[v])) {
1421 casadi_int id2 =
jac_in_.at(hess_row[k]);
1440 for (casadi_int c = 0; c < n; ++c) {
1442 for (casadi_int k = colind[c]; k < colind[c + 1]; ++k) {
1444 casadi_int r = row[k];
1446 casadi_int k_tr = iw[r]++;
1453 hess_nz[k] = hess_nz[k_tr];
1456 hess_nz[k_tr] = hess_nz[k];
1465 double nz = hess_nz[k], nz_tr = hess_nz[k_tr];
1467 if (std::isnan(nz) || std::isinf(nz)) {
1468 std::stringstream ss;
1469 ss <<
"Second derivative w.r.t. " <<
fmu_.
desc_in(m, id_r) <<
" and "
1471 casadi_warning(ss.str());
1472 }
else if (std::isnan(nz_tr) || std::isinf(nz_tr)) {
1473 std::stringstream ss;
1474 ss <<
"Second derivative w.r.t. " <<
fmu_.
desc_in(m, id_c) <<
" and "
1476 casadi_warning(ss.str());
1479 double nz_max = std::fmax(std::fabs(nz), std::fabs(nz_tr));
1481 if (nz_max >
abstol_ && std::fabs(nz - nz_tr) > nz_max *
reltol_) {
1482 std::stringstream ss;
1483 ss <<
"Hessian appears nonsymmetric. Got " << nz <<
" vs. " << nz_tr
1484 <<
" for second derivative w.r.t. " <<
fmu_.
desc_in(m, id_r) <<
" and "
1485 <<
fmu_.
desc_in(m, id_c) <<
", hess_nz = " << k <<
"/" << k_tr;
1486 casadi_warning(ss.str());
1491 if (
make_symmetric_) hess_nz[k] = hess_nz[k_tr] = 0.5 * (hess_nz[k] + hess_nz[k_tr]);
1509 return s.find(
'_') < s.size();
1514 casadi_assert_dev(!s.empty());
1515 size_t pos = s.find(
'_');
1516 casadi_assert(pos < s.size(),
"Cannot process \"" + s +
"\"");
1518 std::string r = s.substr(0, pos);
1520 if (rem) *rem = s.substr(pos+1, std::string::npos);
1536 for (
auto&& e :
in_) {
1544 if (
nfwd_ > 1)
return false;
1547 if (
nadj_ > 1)
return false;
1555 for (
auto&& e :
out_) {
1571 const std::vector<std::string>& s_in,
1572 const std::vector<std::string>& s_out,
1574 const Dict& opts)
const {
1583 std::vector<std::string> s_in_mod = s_in, s_out_mod = s_out;
1584 for (std::string& s : s_in_mod) std::replace(s.begin(), s.end(),
':',
'_');
1585 for (std::string& s : s_out_mod) std::replace(s.begin(), s.end(),
':',
'_');
1591 }
catch (std::exception& e) {
1592 casadi_warning(
"FmuFunction::factory call for constructing " + name +
" from " +
name_
1593 +
" failed:\n" + std::string(e.what()) +
"\nFalling back to base class implementation");
1607 const std::vector<std::string>& onames,
const Dict& opts)
const {
1630 const std::vector<std::string>& inames,
1631 const std::vector<std::string>& onames,
1632 const Dict& opts)
const {
1640 opts1[
"nfwd"] = nfwd;
1656 const std::vector<std::string>& inames,
1657 const std::vector<std::string>& onames,
1658 const Dict& opts)
const {
1665 opts1[
"nadj"] = nadj;
1684 bool symmetric)
const {
1700 casadi_error(
"Implementation error");
1721 casadi_assert_dev(
in_.size()==
n_in_);
1723 s.
pack(
"FmuFunction::in::type",
static_cast<int>(e.type));
1724 s.
pack(
"FmuFunction::in::ind", e.ind);
1728 s.
pack(
"FmuFunction::out::type",
static_cast<int>(e.type));
1729 s.
pack(
"FmuFunction::out::ind", e.ind);
1730 s.
pack(
"FmuFunction::out::wrt", e.wrt);
1731 s.
pack(
"FmuFunction::out::rbegin", e.rbegin);
1732 s.
pack(
"FmuFunction::out::rend", e.rend);
1733 s.
pack(
"FmuFunction::out::cbegin", e.cbegin);
1734 s.
pack(
"FmuFunction::out::cend", e.cend);
1769 s.
pack(
"FmuFunction::fd",
static_cast<int>(
fd_));
1791 s.
version(
"FmuFunction", 6, 6);
1798 s.
unpack(
"FmuFunction::in::type", t);
1800 s.
unpack(
"FmuFunction::in::ind", e.ind);
1805 s.
unpack(
"FmuFunction::out::type", t);
1807 s.
unpack(
"FmuFunction::out::ind", e.ind);
1808 s.
unpack(
"FmuFunction::out::wrt", e.wrt);
1809 s.
unpack(
"FmuFunction::out::rbegin", e.rbegin);
1810 s.
unpack(
"FmuFunction::out::rend", e.rend);
1811 s.
unpack(
"FmuFunction::out::cbegin", e.cbegin);
1812 s.
unpack(
"FmuFunction::out::cend", e.cend);
1850 s.
unpack(
"FmuFunction::fd", fd);
1852 int parallelization = 0;
1853 s.
unpack(
"FmuFunction::parallelization", parallelization);
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
static std::unique_ptr< std::ostream > ofstream_ptr(const std::string &path, std::ios_base::openmode mode=std::ios_base::out)
bool has_jacobian() const override
Full Jacobian.
Sparsity hess_uni_colors_
Function get_forward(casadi_int nfwd, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Return function that calculates forward derivatives.
std::vector< InputStruct > in_
casadi_jac_prob< double > jac_prob_
casadi_jac_prob< double > adj_prob_
~FmuFunction() override
Destructor.
Function get_jacobian(const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Full Jacobian.
std::vector< casadi_int > sp_trans_map_
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 override
Function get_reverse(casadi_int nadj, const std::string &name, const std::vector< std::string > &inames, const std::vector< std::string > &onames, const Dict &opts) const override
Reverse mode AD.
int eval(const double **arg, double **res, casadi_int *iw, double *w, void *mem) const override
Evaluate numerically.
void init(const Dict &opts) override
Initialize.
Sparsity get_jac_sparsity(casadi_int oind, casadi_int iind, bool symmetric) const override
Return sparsity of Jacobian of an output respect to an input.
void finalize_hessian(FmuMemory *m, double *hess_nz, casadi_int *iw) const
bool has_forward(casadi_int nfwd) const override
Return function that calculates forward derivatives.
std::vector< casadi_int > nonlin_
Dict get_stats(void *mem) const override
Get all statistics.
Parallelization parallelization_
casadi_int nfwd_
Number of sensitivities.
std::string validate_ad_file_
void check_mem_count(casadi_int n) const override
Check for validatity of memory object count.
bool enable_adjoint_hessian_
bool has_reverse(casadi_int nadj) const override
Reverse mode AD.
std::vector< Sparsity > sp_trans_
static void identify_io(std::vector< std::string > *scheme_in, std::vector< std::string > *scheme_out, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out)
bool has_jac_sparsity(casadi_int oind, casadi_int iind) const override
Return sparsity of Jacobian of an output respect to an input.
bool enable_adjoint_jacobian_
bool asymmetric_hessian_coloring_
Sparsity get_sparsity_in(casadi_int i) override
Retreive sparsities.
std::vector< casadi_int > which_hess_color_
int eval_task(FmuMemory *m, casadi_int task, casadi_int n_task, bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const
static const Options options_
Options.
bool uses_directional_derivatives_
Sparsity get_sparsity_out(casadi_int i) override
Retreive sparsities.
std::vector< OutputStruct > out_
std::vector< double > get_nominal_in(casadi_int i) const override
Retreive nominal values.
casadi_int max_jac_tasks_
casadi_int max_hess_tasks_
FmuFunction(const std::string &name, const Fmu &fmu, const std::vector< std::string > &name_in, const std::vector< std::string > &name_out)
Constructor.
std::vector< size_t > jac_in_
void free_mem(void *mem) const override
Free memory block.
int eval_all(FmuMemory *m, casadi_int n_task, bool need_nondiff, bool need_jac, bool need_fwd, bool need_adj, bool need_hess) const
void change_option(const std::string &option_name, const GenericType &option_value) override
Change option after object creation for debugging.
bool enable_forward_jacobian_
int init_mem(void *mem) const override
Initalize memory block.
std::vector< double > get_nominal_out(casadi_int i) const override
Retreive nominal values.
std::vector< size_t > jac_out_
std::vector< double > jac_nom_in_
bool uses_adjoint_derivatives_
void * alloc_mem() const override
Create memory block.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
size_t index_out(const std::string &n) const
size_t index_in(const std::string &n) const
void set(FmuMemory *m, size_t ind, const double *value) const
void get_fwd(FmuMemory *m, casadi_int nsens, const casadi_int *id, double *v) const
const std::vector< size_t > & ored(size_t ind) const
int eval_adj(FmuMemory *m) const
void get_stats(FmuMemory *m, Dict *stats, const std::vector< std::string > &name_in, const InputStruct *in) const
Get stats.
Sparsity hess_sparsity(const std::vector< size_t > &r, const std::vector< size_t > &c) const
bool can_be_instantiated_only_once_per_process() const
Does the FMU declare restrictions on instantiation?
std::vector< double > all_nominal_out(size_t ind) const
bool provides_adjoint_derivatives() const
Does the FMU provide support for adjoint directional derivatives.
Sparsity jac_sparsity(const std::vector< size_t > &osub, const std::vector< size_t > &isub) const
int eval_fwd(FmuMemory *m, bool independent_seeds) const
double nominal_in(size_t ind) const
FmuMemory * alloc_mem(const FmuFunction &f) const
Create memory block.
void get_adj(FmuMemory *m, casadi_int nsens, const casadi_int *id, double *v) const
double max_in(size_t ind) const
void set_fwd(FmuMemory *m, casadi_int nseed, const casadi_int *id, const double *v) const
size_t n_out() const
Get the number of scheme outputs.
const std::string & instance_name() const
Name of the FMU.
std::vector< double > all_nominal_in(size_t ind) const
double min_in(size_t ind) const
void free_mem(void *mem) const
Free memory block.
FmuInternal * get() const
void set_adj(FmuMemory *m, casadi_int nseed, const casadi_int *id, const double *v) const
int init_mem(FmuMemory *m) const
Initalize memory block.
bool provides_directional_derivatives() const
Does the FMU provide support for forward directional derivatives.
int eval(FmuMemory *m) const
const std::vector< size_t > & ired(size_t ind) const
void request_adj(FmuMemory *m, casadi_int nsens, const casadi_int *id, const casadi_int *wrt_id) const
size_t n_in() const
Get the number of scheme inputs.
void free_instance(void *instance) const
void request(FmuMemory *m, size_t ind) const
void request_fwd(FmuMemory *m, casadi_int nsens, const casadi_int *id, const casadi_int *wrt_id) const
std::string desc_in(FmuMemory *m, size_t id, bool more=true) const
Internal class for Function.
casadi_int size1_in(casadi_int ind) const
Input/output dimensions.
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 bool has_forward(casadi_int nfwd) const
Return function that calculates forward derivatives.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
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 std::vector< double > get_nominal_out(casadi_int ind) const
size_t n_in_
Number of inputs and outputs.
casadi_int size1_out(casadi_int ind) const
Input/output dimensions.
casadi_int nnz_in() const
Number of input/output nonzeros.
static const Options options_
Options.
virtual std::vector< double > get_nominal_in(casadi_int ind) const
const Sparsity & sparsity_out(casadi_int ind) const
Input/output sparsity.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
casadi_int nnz_out() const
Number of input/output nonzeros.
void setup(void *mem, const double **arg, double **res, casadi_int *iw, double *w) const
Set the (persistent and temporary) work vectors.
void change_option(const std::string &option_name, const GenericType &option_value) override
Change option after object creation for debugging.
std::vector< std::string > name_out_
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.
std::vector< std::string > name_in_
Input and output scheme.
std::map< std::string, std::vector< std::string > > AuxOut
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.
void construct(const Dict &opts)
Construct.
virtual int init_mem(void *mem) const
Initalize memory block.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
bool verbose_
Verbose printout.
void clear_mem()
Clear all memory (called from destructor)
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
std::string class_name() const
Get class name.
std::vector< casadi_int > erase(const std::vector< casadi_int > &rr, const std::vector< casadi_int > &cc, bool ind1=false)
Turn the entries with rows rr and columns cc into structural zeros, in place.
casadi_int size1() const
Number of rows.
static Sparsity dense(casadi_int nrow, casadi_int ncol=1)
Create a dense rectangular sparsity pattern.
Sparsity T() const
Transposed pattern.
Sparsity star_coloring_new(std::vector< casadi_int > &which_color, const Dict &opts=Dict()) const
Star coloring of a symmetric pattern, with the color that recovers each nonzero.
casadi_int nnz() const
Number of structural nonzeros.
casadi_int size2() const
Number of columns.
const casadi_int * row() const
Get a reference to row-vector,.
Sparsity uni_coloring(const Sparsity &AT=Sparsity(), casadi_int cutoff=std::numeric_limits< casadi_int >::max()) const
Unidirectional (column) coloring for compressed Jacobian evaluation.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
std::vector< casadi_int > range(casadi_int start, casadi_int stop, casadi_int step, casadi_int len)
Range function.
bool has_prefix(const std::string &s)
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
Parallelization
Type of parallelization.
std::string to_string(TypeFmi2 v)
const double nan
Not a number.
T * get_ptr(std::vector< T > &v)
Get a pointer to the data contained in the vector.
void casadi_trans(const T1 *x, const casadi_int *sp_x, T1 *y, const casadi_int *sp_y, casadi_int *tmp)
TRANS: y <- trans(x) , w work vector (length >= rows x)
std::string pop_prefix(const std::string &s, std::string *rem)
std::vector< size_t > wrt_
casadi_jac_data< double > adj_data
std::vector< bool > omarked_
std::vector< double > ibuf_
casadi_jac_data< double > jac_data
std::vector< FmuMemory * > slaves
std::vector< bool > imarked_
Options metadata for a class.
static OutputStruct parse(const std::string &n, const Fmu *fmu, std::vector< std::string > *name_in=nullptr, std::vector< std::string > *name_out=nullptr)