int main(){ // Test both SX and MX for(int test=0; test<2; ++test){ // Create a simple function FX f; if(test==0){ cout << "SXFunction:" << endl; SXMatrix x = ssym("x",3); SXMatrix z = x[0]*x[0]+x[2] + 3; f = SXFunction(x,z); } else { cout << "MXFunction:" << endl; MX x = msym("x",3); MX z = x[0]*x[0]+x[2] + 3; f = MXFunction(x,z); } f.init(); // Get arrays for the inputs and outputs, reinterpreting the vector of double as an array of unsigned integers bvec_t* f_in = get_bvec_t(f.input().data()); bvec_t* f_out = get_bvec_t(f.output().data()); // Propagate from input to output (forward mode) cout << "forward mode" << endl; int fwd = true; // Make sure that the class is able to support the dependency propagation casadi_assert(f.spCanEvaluate(fwd)); // Pass seeds f_in[0] = bvec_t(1) << 0; // seed in direction 0 f_in[1] = bvec_t(1) << 2; // seed in direction 2 f_in[2] = (bvec_t(1) << 4) | (bvec_t(1) << 63); // seed in direction 4 and 63 // Reset sensitivities f_out[0] = 0; // Propagate dependencies f.spInit(fwd); f.spEvaluate(fwd); // Print the result printBinary(f_out[0]); // Propagate from output to input (adjoint/reverse/backward mode) cout << "backward mode" << endl; fwd = false; // Make sure that the class is able to support the dependency propagation casadi_assert(f.spCanEvaluate(fwd)); // Pass seeds f_out[0] = (bvec_t(1) << 5) | (bvec_t(1) << 6); // seed in direction 5 and 6 // Reset sensitivities f_in[0] = 0; f_in[1] = 0; f_in[2] = 0; // Propagate dependencies f.spInit(fwd); f.spEvaluate(fwd); // Print the result printBinary(f_in[0]); printBinary(f_in[1]); printBinary(f_in[2]); } return 0; }
void EvaluationMX::create(const FX& fcn, const std::vector<MX> &arg, std::vector<MX> &res, const std::vector<std::vector<MX> > &fseed, std::vector<std::vector<MX> > &fsens, const std::vector<std::vector<MX> > &aseed, std::vector<std::vector<MX> > &asens, bool output_given) { // Number inputs and outputs int num_in = fcn.getNumInputs(); int num_out = fcn.getNumOutputs(); // Number of directional derivatives int nfdir = fseed.size(); int nadir = aseed.size(); // Create the evaluation node MX ev; if(nfdir>0 || nadir>0){ // Create derivative function Derivative dfcn(fcn,nfdir,nadir); stringstream ss; ss << "der_" << fcn.getOption("name") << "_" << nfdir << "_" << nadir; dfcn.setOption("verbose",fcn.getOption("verbose")); dfcn.setOption("name",ss.str()); dfcn.init(); // All inputs vector<MX> darg; darg.reserve(num_in*(1+nfdir) + num_out*nadir); darg.insert(darg.end(),arg.begin(),arg.end()); // Forward seeds for(int dir=0; dir<nfdir; ++dir){ darg.insert(darg.end(),fseed[dir].begin(),fseed[dir].end()); } // Adjoint seeds for(int dir=0; dir<nadir; ++dir){ darg.insert(darg.end(),aseed[dir].begin(),aseed[dir].end()); } ev.assignNode(new EvaluationMX(dfcn, darg)); } else { ev.assignNode(new EvaluationMX(fcn, arg)); } // Output index int ind = 0; // Create the output nodes corresponding to the nondifferented function res.resize(num_out); for (int i = 0; i < num_out; ++i, ++ind) { if(!output_given){ if(!fcn.output(i).empty()){ res[i].assignNode(new OutputNode(ev, ind)); } else { res[i] = MX(); } } } // Forward sensitivities fsens.resize(nfdir); for(int dir = 0; dir < nfdir; ++dir){ fsens[dir].resize(num_out); for (int i = 0; i < num_out; ++i, ++ind) { if (!fcn.output(i).empty()){ fsens[dir][i].assignNode(new OutputNode(ev, ind)); } else { fsens[dir][i] = MX(); } } } // Adjoint sensitivities asens.resize(nadir); for (int dir = 0; dir < nadir; ++dir) { asens[dir].resize(num_in); for (int i = 0; i < num_in; ++i, ++ind) { if (!fcn.input(i).empty()) { asens[dir][i].assignNode(new OutputNode(ev, ind)); } else { asens[dir][i] = MX(); } } } }
// Create an IDAS instance (fully implicit integrator) Integrator create_Sundials(){ // Time SX t("t"); // Differential states SX s("s"), v("v"), m("m"); vector<SX> x(3); x[0] = s; x[1] = v; x[2] = m; // State derivatives SX sdot("sdot"), vdot("vdot"), mdot("mdot"); vector<SX> xdot(3); xdot[0] = sdot; xdot[1] = vdot; xdot[2] = mdot; // Control SX u("u"); // Reference trajectory SX u_ref = 3-sin(t); // Square deviation from the state trajectory SX u_dev = u-u_ref; u_dev *= u_dev; // Differential equation (fully implicit form) vector<SX> res(3); res[0] = v - sdot; res[1] = (u-0.02*v*v)/m - vdot; res[2] = -0.01*u*u - mdot; // Input/output of the DAE residual function vector<SXMatrix> ffcn_in = daeIn<SXMatrix>("x",x, "p",u, "t",t, "xdot",xdot); vector<SXMatrix> ffcn_out = daeOut<SXMatrix>("ode",res, "quad",u_dev); // DAE residual function FX ffcn = SXFunction(ffcn_in,ffcn_out); // Overwrite ffcn with a plain c function (avoid this!) if(plain_c){ // Use DAE residual defined in a c-function ffcn = CFunction(dae_res_c_wrapper); // Specify the number of inputs and outputs ffcn.setNumInputs(DAE_NUM_IN); ffcn.setNumOutputs(DAE_NUM_OUT); // Specify dimensions of inputs and outputs ffcn.input(DAE_T) = DMatrix(1,1,0); ffcn.input(DAE_X) = DMatrix(3,1,0); ffcn.input(DAE_XDOT) = DMatrix(3,1,0); ffcn.input(DAE_P) = DMatrix(1,1,0); ffcn.output(DAE_ODE) = DMatrix(3,1,0); ffcn.output(DAE_QUAD) = DMatrix(1,1,0); } if(implicit_integrator){ // Create an IDAS instance IdasIntegrator integrator(ffcn); // Set IDAS specific options integrator.setOption("calc_ic",calc_ic); // Return the integrator return integrator; } else { // Create an CVodes instance CVodesIntegrator integrator(ffcn); // Return the integrator return integrator; } }