26 #include "integration_tools.hpp"
27 #include "integrator.hpp"
28 #include "rootfinder.hpp"
29 #include "polynomial.hpp"
36 { 0.21132486540518713447, 0.78867513459481286553 };
38 { 0.11270166537925824235, 0.50000000000000000000,
39 0.88729833462074170214 };
41 { 0.06943184420297354720, 0.33000947820757187134,
42 0.66999052179242823968, 0.93056815579702623076 };
44 { 0.04691007703066807366, 0.23076534494715861268,
45 0.49999999999999994449, 0.76923465505284149835, 0.95308992296933192634 };
47 { 0.03376524289842347537, 0.16939530676686742616,
48 0.38069040695840172805, 0.61930959304159849399, 0.83060469323313235179,
49 0.96623475710157580298 };
51 { 0.02544604382862047931, 0.12923440720030288098,
52 0.29707742431130129690, 0.50000000000000000000, 0.70292257568869853657,
53 0.87076559279969734106, 0.97455395617137896558 };
55 { 0.01985507175123157886, 0.10166676129318691357,
56 0.23723379504183561561, 0.40828267875217505445, 0.59171732124782483453,
57 0.76276620495816449541, 0.89833323870681347501, 0.98014492824876797705 };
59 { 0.01591988024618706810, 0.08198444633668211523,
60 0.19331428364970504319, 0.33787328829809543107, 0.49999999999999988898,
61 0.66212671170190451342, 0.80668571635029517886, 0.91801555366331766272,
62 0.98408011975381259884 };
69 { 1.00000000000000000000 };
71 { 0.33333333333333337034, 1.00000000000000000000 };
73 { 0.15505102572168222297, 0.64494897427831787695,
74 1.00000000000000000000 };
76 { 0.08858795951270420632, 0.40946686444073465694,
77 0.78765946176084700170, 1.00000000000000000000 };
79 { 0.05710419611451822419, 0.27684301363812369168,
80 0.58359043236891683382, 0.86024013565621926247, 1.00000000000000000000 };
82 { 0.03980985705146905529, 0.19801341787360787761,
83 0.43797481024738621480, 0.69546427335363603106, 0.90146491420117347282,
84 1.00000000000000000000 };
86 { 0.02931642715978521885, 0.14807859966848435640,
87 0.33698469028115418666, 0.55867151877155019069, 0.76923386203005450490,
88 0.92694567131974103802, 1.00000000000000000000 };
90 { 0.02247938643871305597, 0.11467905316090415413,
91 0.26578982278458951338, 0.45284637366944457959, 0.64737528288683043876,
92 0.81975930826310761113, 0.94373743946307731001, 1.00000000000000000000 };
94 { 0.01777991514736393386, 0.09132360789979432347,
95 0.21430847939563035798, 0.37193216458327238438, 0.54518668480342658000,
96 0.71317524285556954666, 0.85563374295785443735, 0.95536604471003006012,
97 1.00000000000000000000 };
102 template<
typename RealT>
104 if (scheme==
"radau") {
105 casadi_assert(order>0 && order<10,
106 "Error in collocationPoints(order, scheme): "
107 "only order up to 9 supported for scheme 'radau', but got " +
str(order) +
".");
109 }
else if (scheme==
"legendre") {
110 casadi_assert(order>0 && order<10,
111 "Error in collocationPoints(order, scheme): "
112 "only order up to 9 supported for scheme 'legendre', but got " +
str(order) +
".");
115 casadi_error(
"Error in collocationPoints(order, scheme): unknown scheme '"
116 + scheme +
"'. Select one of 'radau', 'legendre'.");
121 return collocation_pointsGen<double>(order, scheme);
125 return collocation_pointsGen<long double>(order, scheme);
131 "Parameter N (number of steps) must be at least 1, but got " +
str(N) +
".");
132 casadi_assert(order==4,
"Only RK order 4 is supported now.");
133 casadi_assert(f.
n_in()==2,
"Function must have two inputs: x and p");
134 casadi_assert(f.
n_out()==1,
"Function must have one outputs: dot(x)");
140 std::vector<double> b(order);
146 std::vector<double> c(order);
152 std::vector< std::vector<double> > A(order-1);
156 A[1][0]=0;A[1][1]=1.0/2;
164 std::vector<MX> k(order);
165 std::vector<MX> f_arg(2);
169 for (casadi_int i=0; i<N; ++i) {
170 for (casadi_int j=0; j<order; ++j) {
172 for (casadi_int jj=0; jj<j; ++jj) {
173 xL += k.at(jj)*A.at(j-1).at(jj);
177 k[j] = dt*f(f_arg).at(0);
180 for (casadi_int j=0; j<order; ++j) {
181 xf += b.at(j)*k.at(j);
186 return Function(
"F", {x0, p, h}, {xf}, {
"x0",
"p",
"h"}, {
"xf"});
190 std::vector< std::vector<double> > &C, std::vector< double > &D) {
192 casadi_int deg = tau.size();
195 std::vector<double> etau_root = tau;
196 etau_root.insert(etau_root.begin(), 0);
200 for (casadi_int i=0;i<deg+1;++i) {
209 for (casadi_int j=0; j<deg+1; ++j) {
212 for (casadi_int j2=0; j2<deg+1; ++j2) {
214 L *= (tau_sym-etau_root[j2])/(etau_root[j]-etau_root[j2]);
218 Function lfcn(
"lfcn", {tau_sym}, {L});
222 D[j] = lfcn(std::vector<DM>{1.}).at(0)->front();
226 Function tfcn(
"tfcn", {tau_sym}, {tangent(L, tau_sym)});
227 for (casadi_int j2=0; j2<deg+1; ++j2) {
228 C[j2][j] = tfcn(std::vector<DM>{etau_root[j2]}).at(0)->front();
236 casadi_int deg = tau.size();
239 std::vector<double> etau_root = tau;
240 etau_root.insert(etau_root.begin(), 0);
243 bool has_end = tau.back()==1;
246 std::vector<std::vector<double> > C_(deg+1, std::vector<double>(deg+1, 0));
249 std::vector<double> D_(deg+1, 0);
252 std::vector<double> B_(deg+1, 0);
255 for (casadi_int j=0; j<deg+1; ++j) {
259 for (casadi_int r=0; r<deg+1; ++r) {
261 p *=
Polynomial(-etau_root[r], 1)/(etau_root[j]-etau_root[r]);
268 D_[j] = j==deg ? 1 : 0;
275 for (casadi_int r=0; r<deg+1; ++r) {
276 C_[j][r] = dp(etau_root[r]);
286 B =
DM(std::vector<double>(B_.begin()+1, B_.end()));
290 const std::string& solver,
291 const Dict& solver_options) {
294 "Parameter N (number of steps) must be at least 1, but got " +
str(N) +
".");
295 casadi_assert(f.
n_in()==2,
"Function must have two inputs: x and p");
296 casadi_assert(f.
n_out()==1,
"Function must have one outputs: dot(x)");
302 std::vector < std::vector <double> >
C;
303 std::vector < double >
D;
316 std::vector<MX> x = vertsplit(v, x0.
size1());
317 x.insert(x.begin(), x0);
320 std::vector<MX> V_eq, f_in(2), f_out;
321 for (casadi_int j=1; j<order+1; ++j) {
324 for (casadi_int r=0; r<=order; ++r) xp_j+=
C[j][r]*x[r];
330 V_eq.push_back(dt*f_out.at(0)-xp_j);
334 Function rfp(
"rfp", {v, x0, p, h}, {vertcat(V_eq)});
341 for (casadi_int k=0; k<N; ++k) {
342 std::vector<MX> ifcn_out = ifcn({repmat(xf, order), xf, p, h});
343 x = vertsplit(ifcn_out[0], xf.
size1());
347 for (casadi_int i=1; i<=order; ++i) {
353 return Function(
"F", {x0, p, h}, {xf}, {
"x0",
"p",
"h"}, {
"xf"});
357 const Dict& plugin_options) {
359 casadi_assert(f.
n_in()==2,
"Function must have two inputs: x and p");
360 casadi_assert(f.
n_out()==1,
"Function must have one outputs: dot(x)");
371 casadi_int u_offset[] = {0, 1, 1+p_sp.
size1()};
372 std::vector<MX> pp = vertsplit(u, std::vector<casadi_int>(u_offset, u_offset+3));
374 MX p = reshape(pp[1], p_sp.
size());
376 MX xdot = f(std::vector<MX>(f_in, f_in+2)).at(0);
380 MXDict dae = {{
"x", x}, {
"p", u}, {
"ode", xdot}};
391 MX xf = ifcn(
MXDict{{
"x0", x0}, {
"p", vertcat(h, vec(p))}}).at(
"xf");
394 return Function(
"F", {x0, p, h}, {xf}, {
"x0",
"p",
"h"}, {
"xf"});
398 std::vector<casadi_int>
invert_lookup(
const std::vector<casadi_int>& lookup) {
399 std::vector<casadi_int> ret(lookup.size(), -1);
400 for (casadi_int i=0;i<lookup.size();++i) {
401 casadi_int e = lookup[i];
409 namespace IndexReduction {
411 struct EquationStruct;
427 struct VariableStruct {
428 std::vector<struct EquationStruct*> eqs;
429 std::vector<struct EquationStruct*> eqs0;
430 struct EquationStruct* assign =
nullptr;
432 struct VariableStruct* der =
nullptr;
434 struct VariableStruct* der_inv =
nullptr;
436 bool visited =
false;
437 bool deleted =
false;
440 struct EquationStruct {
441 std::vector<struct VariableStruct*> vars;
442 std::vector<struct VariableStruct*> vars0;
443 struct VariableStruct* assign =
nullptr;
445 struct EquationStruct* der =
nullptr;
447 struct EquationStruct* der_inv =
nullptr;
449 bool visited =
false;
452 typedef struct VariableStruct
Variable;
453 typedef struct EquationStruct
Equation;
457 std::vector<Variable*> V;
458 std::vector<Equation*> E;
459 casadi_int ncol_orig;
460 casadi_int nrow_orig;
463 typedef struct GraphStruct
Graph;
471 v_new->i = G.V.size()-1;
479 auto it = std::find(e->vars0.begin(), e->vars0.end(), v);
480 if (it==e->vars0.end()) {
481 e->vars0.push_back(v);
483 e->vars.push_back(v);
496 e_new->i = G.E.size()-1;
503 for (
auto* v : e->vars0) {
522 for (
auto* j : i->vars) {
524 if (j->assign==
nullptr) {
528 j->assign = i; i->assign = j;
537 for (
auto j : i->vars) {
550 j->assign = i; i->assign = j;
576 std::vector<casadi_int>& var_map, std::vector<casadi_int>& eq_map,
577 casadi_int max_iter) {
580 casadi_int Np = G.E.size();
582 for (casadi_int k=0;k<Np;++k) {
589 if (iter++ > max_iter)
return false;
592 for (
auto* v : G.V) {
596 for (
auto* e : G.E) {
597 auto it = std::find(e->vars.begin(), e->vars.end(), v);
598 if (it!=e->vars.end()) e->vars.erase(it);
604 for (
auto* v : G.V) v->visited =
false;
605 for (
auto* e : G.E) e->visited =
false;
613 casadi_int n = G.V.size();
615 for (casadi_int jj=0;jj<n;++jj) {
617 if (j->visited && !j->deleted) {
624 for (casadi_int ll=0;ll<n;++ll) {
629 for (casadi_int ll=n;ll<G.E.size();++ll) {
632 for (
auto* v : l->vars0) {
633 if (!v->eqs.empty()) valid =
true;
635 if (!valid)
return false;
640 for (
auto* j : G.V) {
641 if (j->visited && !j->deleted) {
642 j->der->assign = j->assign->der;
643 j->assign->der->assign = j->der;
656 const Sparsity& graph, std::vector<casadi_int>& var_map,
657 std::vector<casadi_int>& eq_map,
658 casadi_int max_iter) {
660 casadi_assert(var_map.size()==graph.
size2(),
661 "var_map size must match graph columns.");
667 G.E.resize(graph.
size1(),
nullptr);
668 G.V.resize(graph.
size2(),
nullptr);
669 G.nrow_orig = graph.
size1();
670 G.ncol_orig = graph.
size2();
672 for (
auto*& e : G.E) e =
new Equation();
673 for (
auto*& v : G.V) v =
new Variable();
677 i=0;
for (
auto* e : G.E) e->i = i++;
678 i=0;
for (
auto* v : G.V) v->i = i++;
681 const casadi_int* colind = graph.
colind();
682 const casadi_int* row = graph.
row();
685 for (casadi_int c=0;c<graph.
size2();++c) {
687 for (casadi_int j=colind[c]; j<colind[c+1]; ++j) {
688 casadi_int r = row[j];
689 G.V[c]->eqs.push_back(G.E[r]);
690 G.E[r]->vars.push_back(G.V[c]);
695 for (casadi_int i=0;i<var_map.size();++i) {
697 casadi_int i_der = var_map[i];
705 for (
auto* v : G.V) v->eqs0 = v->eqs;
706 for (
auto* e : G.E) e->vars0 = e->vars;
709 if (algorithm==
"pantelides") {
713 for (
auto* v : G.V)
delete v;
714 for (
auto* e : G.E)
delete e;
715 casadi_error(
"Algorithm '" + algorithm +
"' not recognized.");
718 for (
auto* v : G.V)
delete v;
719 for (
auto* e : G.E)
delete e;
720 casadi_error(
"Structural detection failed.");
724 var_map.resize(G.V.size());
725 eq_map.resize(G.E.size());
729 for (
auto* v : G.V) {
731 var_map[v->i] = v->der->i;
735 casadi_assert_dev(v->i==k);
741 for (
auto* e : G.E) {
743 eq_map[e->i] = e->der->i;
747 casadi_assert_dev(e->i==k);
752 for (
auto* v : G.V)
delete v;
753 for (
auto* e : G.E)
delete e;
759 using namespace IndexReduction;
762 std::map<std::string, X>
add_defaults(
const std::map<std::string, X>& in,
763 const std::vector<std::string>& keys) {
764 std::map<std::string, X> ret;
765 for (
const std::string& k : keys) {
766 auto it = in.find(k);
777 std::vector<casadi_int>
get_orders(
const std::vector<casadi_int>& map) {
778 std::vector<casadi_int> ret(map.size(), 0);
779 for (casadi_int i=0;i<ret.size();++i) {
780 if (map[i]>=0) ret[map[i]] = ret[i]+1;
785 std::vector<casadi_int>
get_inverse(
const std::vector<casadi_int>& map) {
786 std::vector<casadi_int> ret(map.size(), -1);
787 for (casadi_int i=0;i<ret.size();++i) {
788 if (map[i]>=0) ret[map[i]] = i;
793 std::vector<casadi_int>
path(
const std::vector<casadi_int>& map, casadi_int i_start) {
794 std::vector<casadi_int> ret;
795 casadi_int i = i_start;
797 casadi_int i_next = map[i];
798 if (i_next==-1)
break;
806 const std::map<std::string, X>
808 double baumgarte_pole_ = 0;
809 std::string algorithm =
"pantelides";
810 casadi_int max_iter = 500;
812 for (
auto&& op : opts) {
813 if (op.first==
"baumgarte_pole") {
814 baumgarte_pole_ = op.second;
815 }
else if (op.first==
"algorithm") {
816 algorithm = op.second.to_string();
817 }
else if (op.first==
"max_iter") {
818 max_iter = op.second;
820 casadi_error(
"Unknown option '" + op.first +
"'.");
826 for (
const auto& e : dae) {
827 casadi_assert(e.second.is_column() && e.second.is_dense(),
828 "Dense column vector expected for key '" + e.first +
"'. "
829 "Got " + e.second.dim(
true) +
" instead.");
834 casadi_assert(x.numel()==ode.numel(),
835 "Size of explicit differential state vector (x: " +
str(x.numel()) +
") must "
836 "match size of ode right-hand-side (ode: " +
str(ode.numel()) +
").");
837 casadi_assert(x.size1()==0,
"Explicit differential states not supported yet.");
841 casadi_assert(x_impl.numel()==dx_impl.numel(),
842 "Size of implicit differential state vector (x_impl: " +
str(x_impl.numel()) +
") must "
843 "match size of implicit differential state derivative vector (dx_impl: "
844 +
str(dx_impl.numel()) +
").");
848 casadi_assert(z.numel()+x_impl.numel()==alg.numel(),
849 "Size of algebraic state vector (z: " +
str(z.numel()) +
") + "
850 "size of implicit states (x_impl: " +
str(x_impl.numel()) +
") must "
851 "match size of algebraic equations (alg: " +
str(alg.numel()) +
").");
854 casadi_assert(t.is_scalar(),
"Time must be scalar. Got " + t.dim() +
" instead.");
859 std::vector<bool> dep = X::which_depends(alg, dx_impl);
862 std::vector<X> dx_impl_split = vertsplit(dx_impl);
863 std::vector<std::string> prob;
864 for (casadi_int i=0;i<dep.size();++i) {
865 if (!dep[i]) prob.push_back(dx_impl_split[i].name());
867 casadi_error(
"Found dx_impl variables that do not appear in alg: " +
join(prob,
",") +
868 ". They should be classified as z instead.");
872 bool normal_order =
true;
877 V = vertcat(x_impl, dx_impl, z);
879 V = vertcat(x_impl, z, dx_impl);
882 Function temp(
"temp", {V, p, t}, {alg});
883 Sparsity G = temp.jac_sparsity(0, 0);
886 int nx_impl = x_impl.
numel();
888 std::vector<casadi_int> var_map(V.numel(), -1);
889 for (casadi_int i=0;i<nx_impl;++i) {
890 var_map[i] = i+nx_impl+(normal_order? 0: nz);
894 std::vector<casadi_int> eq_map;
900 casadi_assert_dev(var_map.size()>=2*nx_impl+nz);
903 std::vector<X> var_ext = vertsplit(V);
905 var_ext.resize(var_map.size());
908 for (casadi_int i=0;i<var_map.size();++i) {
909 casadi_int i_der = var_map[i];
911 if (i_der>=V.numel())
913 var_ext[i_der] = X::sym(
"d"+var_ext[i].name());
919 std::vector<X> xs; xs.reserve(var_map.size());
920 std::vector<X> dxs; dxs.reserve(var_map.size());
922 for (casadi_int i=0;i<var_map.size();++i) {
923 casadi_int i_der = var_map[i];
925 xs.push_back(var_ext[i]);
926 dxs.push_back(var_ext[i_der]);
931 X x_cat = vertcat(xs);
932 X dx_cat = vertcat(dxs);
935 X j1 = vertcat(x_cat, t);
936 X j2 = vertcat(dx_cat, 1);
939 std::vector<X> eq_ext = vertsplit(alg);
941 eq_ext.resize(eq_map.size());
944 std::vector<casadi_int> order =
get_orders(eq_map);
945 casadi_int max_order = *std::max_element(order.begin(), order.end());
950 std::map<casadi_int, std::vector<casadi_int> > targets;
951 for (casadi_int i=0;i<eq_map.size();++i) {
953 targets[order[eq_map[i]]].push_back(i);
958 std::vector<bool> active(eq_map.size(),
true);
961 std::vector<X> dropped_constraints;
964 for (casadi_int ord=1;ord<=max_order;++ord) {
965 const std::vector<casadi_int> & target = targets[ord];
968 for (casadi_int i : target) dropped_constraints.push_back(eq_ext[i]);
973 std::vector<X> dblocks = vertsplit(jtimes(block, j1, j2,
false));
975 for (casadi_int i=0;i<target.size();++i) {
976 casadi_int t = target[i];
977 eq_ext[eq_map[t]] = dblocks[i];
982 std::vector<casadi_int> eq_map_inverse =
get_inverse(eq_map);
987 std::vector<X> alg_new;
988 for (casadi_int i=0;i<eq_map.size();++i) {
992 X new_eq = eq_ext[i];
996 for (casadi_int k=0;k<order[i];++k) {
1000 const std::vector<double>& coeff = p.
coeff();
1004 std::vector<casadi_int> gen_i =
path(eq_map_inverse, i);
1007 for (casadi_int k=0;k<gen_i.size();++k) {
1008 new_eq += coeff[k+1]*eq_ext[gen_i[k]];
1012 alg_new.push_back(new_eq);
1016 std::vector<casadi_int> var_order =
get_orders(var_map);
1017 std::vector<casadi_int> var_map_inverse =
get_inverse(var_map);
1021 std::vector<casadi_int> impl_to_expl;
1022 for (casadi_int i=0;i<var_map.size();++i) {
1023 if (var_order[i]>=2) {
1026 std::vector<casadi_int> gen_i =
path(var_map_inverse, i);
1030 impl_to_expl.insert(impl_to_expl.end(), gen_i.begin()+1, gen_i.end());
1036 std::vector<casadi_int> impl_to_expl_compl =
complement(impl_to_expl, xs.size());
1037 std::map<std::string, X> dae_result;
1039 dae_result[
"x"] = vertcat(
vector_slice(xs, impl_to_expl));
1040 dae_result[
"ode"] = vertcat(
vector_slice(dxs, impl_to_expl));
1042 dae_result[
"x_impl"] = vertcat(
vector_slice(xs, impl_to_expl_compl));
1043 dae_result[
"dx_impl"] = vertcat(
vector_slice(dxs, impl_to_expl_compl));
1045 dae_result[
"t"] = t;
1046 dae_result[
"p"] = p;
1049 std::vector<X> z_orig = vertsplit(z);
1050 std::vector<X> z_new;
1051 for (casadi_int i=0;i<var_map.size();++i) {
1053 if (var_order[i]==0 && var_map[i]==-1) {
1054 z_new.push_back(z_orig.at(i-(normal_order?2:1)*nx_impl));
1057 dae_result[
"z"] = vertcat(z_new);
1058 dae_result[
"alg"] = vertcat(alg_new);
1060 dae_result[
"I"] = vertcat(dropped_constraints);
1062 stats[
"index"] = max_order+1;
1077 const std::map<std::string, X>& dae_red,
1080 std::map<std::string, X> dae_se;
1081 dae_se[
"x"] = vertcat(dae_red.at(
"x"), dae_red.at(
"x_impl"));
1082 dae_se[
"z"] = vertcat(dae_red.at(
"dx_impl"), dae_red.at(
"z"));
1083 dae_se[
"ode"] = vertcat(dae_red.at(
"ode"), dae_red.at(
"dx_impl"));
1084 dae_se[
"alg"] = dae_red.at(
"alg");
1085 dae_se[
"t"] = dae_red.at(
"t");
1086 dae_se[
"p"] = dae_red.at(
"p");
1092 Sparsity var_map_sp = jacobian(vertcat(dae_red.at(
"x"), dae_red.at(
"x_impl"),
1093 dae_red.at(
"dx_impl"), dae_red.at(
"z")), vertcat(x_impl, dx_impl, z)).sparsity();
1094 DM var_map(var_map_sp, 1.0);
1096 state_to_orig =
Function(
"state_to_orig",
1097 {dae_se[
"x"], dae_se[
"z"]},
1098 {x_impl, dx_impl, z},
1100 {
"x_impl",
"dx_impl",
"z"});
1103 {dae_se[
"x"], dae_se[
"z"], dae_se[
"p"], dae_se[
"t"]},
1105 {
"x",
"z",
"p",
"t"},
1113 const std::map<std::string, X>& dae_red,
1114 const std::string& init_solver,
const DMDict& init_strength,
const Dict& init_solver_options) {
1122 vertcat(dae_red.at(
"x"), dae_red.at(
"x_impl"), dae_red.at(
"dx_impl"), dae_red.at(
"z")),
1123 vertcat(x_impl, dx_impl, z)).sparsity();
1124 DM var_map(var_map_sp, 1.0);
1127 std::map<std::string, X> nlp;
1129 MX pmx =
MX::sym(
"pmx", p_orig.sparsity());
1132 X init_x_impl_orig = X::sym(
"x_impl_init", x_impl.sparsity());
1133 X init_dx_impl_orig = X::sym(
"dx_impl_init", dx_impl.sparsity());
1134 X init_z_orig = X::sym(
"z_init", z.sparsity());
1136 MX init_x_impl_orig_mx =
MX::sym(
"x_impl_init", x_impl.sparsity());
1137 MX init_dx_impl_orig_mx =
MX::sym(
"dx_impl_init", dx_impl.sparsity());
1138 MX init_z_orig_mx =
MX::sym(
"z_init", z.sparsity());
1140 X init_orig = vertcat(init_x_impl_orig, init_dx_impl_orig, init_z_orig);
1141 MX init_orig_mx = vertcat(init_x_impl_orig_mx, init_dx_impl_orig_mx, init_z_orig_mx);
1143 X init_sym_red = mtimes(
X(var_map), init_orig);
1144 nlp[
"p"] = vertcat(init_orig, dae_red.at(
"p"), dae_red.at(
"t"));
1145 MX p = vertcat(init_orig_mx, pmx, tmx);
1149 for (
const auto& e : init_strength) {
1150 casadi_assert(e.second.is_column() && e.second.is_dense(),
1151 "Dense column vector expected for key '" + e.first +
"' of init_strength. "
1152 "Got " + e.second.dim(
true) +
" instead.");
1156 casadi_assert(x_impl.numel()==init_strength_x_impl.
numel(),
1157 "init_strength 'x_impl' entry should have length " +
str(x_impl.numel()) +
". "
1158 "Got length " +
str(init_strength_x_impl.
numel()) +
" instead.");
1162 casadi_assert(dx_impl.numel()==init_strength_dx_impl.
numel(),
1163 "init_strength 'dx_impl' entry should have length " +
str(dx_impl.numel()) +
". "
1164 "Got length " +
str(init_strength_dx_impl.
numel()) +
" instead.");
1167 casadi_assert(z.numel()==init_strength_z.
numel(),
1168 "init_strength 'z' entry should have length " +
str(z.numel()) +
". "
1169 "Got length " +
str(init_strength_z.
numel()) +
" instead.");
1171 DM init_strength_cat = vertcat(init_strength_x_impl, init_strength_dx_impl, init_strength_z);
1173 DM weights = mtimes(var_map, init_strength_cat);
1175 std::vector<casadi_int> ind = sparsify(weights>0).sparsity().T().get_col();
1177 std::vector<X> x_parts = {dae_red.at(
"x"), dae_red.at(
"x_impl"),
1178 dae_red.at(
"dx_impl"), dae_red.at(
"z")};
1180 nlp[
"x"] = vertcat(x_parts);
1181 nlp[
"g"] = vertcat(dae_red.at(
"I"), dae_red.at(
"alg"));
1182 nlp[
"f"] = sumsqr((nlp[
"x"](ind)-init_sym_red(ind))*
X(weights(ind)));
1185 MX x0 = mtimes(var_map, init_orig_mx);
1190 ind = sparsify(mtimes(var_map, init_strength_cat)==-1).sparsity().T().get_col();
1191 lbx(ind) = ubx(ind) = x0(ind);
1193 Function solver =
nlpsol(
"init_solver", init_solver, nlp, init_solver_options);
1194 MXDict res = solver(
MXDict{{
"x0", x0}, {
"lbg", 0}, {
"ubg", 0},
1195 {
"lbx", lbx}, {
"ubx", ubx}, {
"p", p}});
1197 std::vector<casadi_int> x_parts_offsets = {0};
1198 for (casadi_int i=0;i<x_parts.size();i+=2) {
1199 x_parts_offsets.push_back(x_parts_offsets.back() + x_parts[i].numel() + x_parts[i+1].numel());
1202 std::vector<MX> parts = vertsplit(res[
"x"], x_parts_offsets);
1205 {init_x_impl_orig_mx, init_dx_impl_orig_mx, init_z_orig_mx, pmx, tmx},
1207 {
"x_impl",
"dx_impl",
"z",
"p",
"t"},
1222 const std::string& init_solver,
const DMDict& init_strength,
const Dict& init_solver_options) {
1223 return init_gen(dae, dae_red, init_solver, init_strength, init_solver_options);
1227 const std::string& init_solver,
const DMDict& init_strength,
const Dict& init_solver_options) {
1228 return init_gen(dae, dae_red, init_solver, init_strength, init_solver_options);
const Sparsity & sparsity_in(casadi_int ind) const
Get sparsity of a given input.
casadi_int n_out() const
Get the number of function outputs.
casadi_int n_in() const
Get the number of function inputs.
casadi_int numel() const
Get the number of elements.
std::pair< casadi_int, casadi_int > size() const
Get the shape.
casadi_int size1() const
Get the first dimension (i.e. number of rows)
static MX 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.
const Sparsity & sparsity() const
Get the sparsity pattern.
static MX inf(const Sparsity &sp)
create a matrix with all inf
Sparse matrix class. SX and DM are specializations.
Helper class for differentiating and integrating polynomials.
Polynomial anti_derivative() const
Create a new polynomial for the anti-derivative (primitive function)
Polynomial derivative() const
Create a new polynomial for the derivative.
const std::vector< double > & coeff() const
Coefficients of the polynomial.
Class representing a Slice.
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.
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 *.
const casadi_int * colind() const
Get a reference to the colindex of all column element (see class description)
Function integrator(const std::string &name, const std::string &solver, const SXDict &dae, const Dict &opts)
Function nlpsol(const std::string &name, const std::string &solver, const SXDict &nlp, const Dict &opts)
Function rootfinder(const std::string &name, const std::string &solver, const SXDict &rfp, const Dict &opts)
struct EquationStruct Equation
bool dae_struct_detect_pantelides(Graph &G, std::vector< casadi_int > &var_map, std::vector< casadi_int > &eq_map, casadi_int max_iter)
Perform Pantelides algorithm for DAE index reduction.
void add_variable(Equation *e, Variable *v)
void dae_struct_detect(const std::string &algorithm, const Sparsity &graph, std::vector< casadi_int > &var_map, std::vector< casadi_int > &eq_map, casadi_int max_iter)
bool dfs_match_pantelides(Equation *i)
struct VariableStruct Variable
void graph_add_der(Graph &G, Variable *v)
const long double legendre_points8[]
std::map< std::string, MX > MXDict
void collocation_coeff(const std::vector< double > &tau, DM &C, DM &D, DM &B)
Obtain collocation interpolating matrices.
const long double radau_points9[]
T get_from_dict(const std::map< std::string, T > &d, const std::string &key, const T &default_value)
Function dae_init_gen(const MXDict &dae, const MXDict &dae_red, const std::string &init_solver, const DMDict &init_strength, const Dict &init_solver_options)
Obtain a generator Function for producing consistent initial guesses of a reduced DAE.
std::string join(const std::vector< std::string > &l, const std::string &delim)
Function simpleRK(Function f, casadi_int N, casadi_int order)
Construct an explicit Runge-Kutta integrator.
const long double legendre_points2[]
const long double legendre_points4[]
const long double radau_points3[]
std::vector< RealT > collocation_pointsGen(casadi_int order, const std::string &scheme)
const long double legendre_points6[]
std::map< std::string, X > map_semi_expl(const std::map< std::string, X > &dae, const std::map< std::string, X > &dae_red, Function &state_to_orig, Function &phi)
const long double radau_points1[]
const long double legendre_points9[]
std::map< std::string, X > add_defaults(const std::map< std::string, X > &in, const std::vector< std::string > &keys)
const long double radau_points2[]
const long double radau_points6[]
const long double legendre_points5[]
const long double * legendre_points[]
Function init_gen(const std::map< std::string, X > &dae, const std::map< std::string, X > &dae_red, const std::string &init_solver, const DMDict &init_strength, const Dict &init_solver_options)
const long double radau_points7[]
std::map< std::string, SX > SXDict
MXDict dae_map_semi_expl(const MXDict &dae, const MXDict &dae_red, Function &state_to_orig, Function &phi)
Turn a reduced DAE into a semi explicit form suitable for CasADi integrator.
void collocation_interpolators(const std::vector< double > &tau, std::vector< std::vector< double > > &C, std::vector< double > &D)
Obtain collocation interpolating matrices.
std::string str(const T &v)
String representation, any type.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
const long double radau_points5[]
const long double radau_points8[]
MXDict dae_reduce_index(const MXDict &dae, Dict &stats, const Dict &opts)
Reduce index.
std::vector< casadi_int > get_inverse(const std::vector< casadi_int > &map)
const long double legendre_points1[]
std::vector< casadi_int > invert_lookup(const std::vector< casadi_int > &lookup)
Function simpleIRK(Function f, casadi_int N, casadi_int order, const std::string &scheme, const std::string &solver, const Dict &solver_options)
Construct an implicit Runge-Kutta integrator using a collocation scheme.
const long double radau_points4[]
std::vector< double > collocation_points(casadi_int order, const std::string &scheme)
Obtain collocation points of specific order and scheme.
const std::map< std::string, X > reduce_index_gen(const std::map< std::string, X > &dae, Dict &stats, const Dict &opts)
bool all(const std::vector< bool > &v)
Check if all arguments are true.
std::vector< casadi_int > get_orders(const std::vector< casadi_int > &map)
Function simpleIntegrator(Function f, const std::string &plugin, const Dict &plugin_options)
Simplified wrapper for the Integrator class.
const long double legendre_points3[]
std::vector< T > vector_slice(const std::vector< T > &v, const std::vector< casadi_int > &i)
Slicing vector.
const long double * radau_points[]
std::vector< casadi_int > complement(const std::vector< casadi_int > &v, casadi_int size)
Returns the list of all i in [0, size[ not found in supplied list.
std::vector< long double > collocation_pointsL(casadi_int order, const std::string &scheme)
Obtain collocation points of specific order and scheme.
std::vector< casadi_int > path(const std::vector< casadi_int > &map, casadi_int i_start)
const long double legendre_points7[]
std::map< std::string, DM > DMDict