26 #include "sundials_interface.hpp"
28 #include "casadi/core/casadi_misc.hpp"
30 INPUTSCHEME(IntegratorInput)
31 OUTPUTSCHEME(IntegratorOutput)
36 double t0,
const std::vector<double>& tout)
47 "Maximum number of integrator steps"}},
50 "Relative tolerence for the IVP solution"}},
53 "Absolute tolerence for the IVP solution"}},
56 "Linear solver scheme in the Newton method: DIRECT|gmres|bcgstab|tfqmr"}},
59 "Maximum Krylov subspace size"}},
60 {
"sensitivity_method",
62 "Sensitivity method: SIMULTANEOUS|staggered"}},
63 {
"max_multistep_order",
65 "Maximum order for the (variable-order) multistep method"}},
66 {
"use_preconditioner",
68 "Precondition the iterative solver [default: true]"}},
71 "[DEPRECATED] Stop the integrator at the end of the interval"}},
72 {
"disable_internal_warnings",
74 "Disable SUNDIALS internal warning messages"}},
77 "Should the quadratures affect the step size control"}},
80 "include the forward sensitivities in all error controls"}},
81 {
"steps_per_checkpoint",
83 "Number of steps between two consecutive checkpoints"}},
84 {
"interpolation_type",
86 "Type of interpolation for the adjoint sensitivities"}},
89 "A custom linear solver creator function [default: qr]"}},
90 {
"linear_solver_options",
92 "Options to be passed to the linear solver"}},
93 {
"second_order_correction",
95 "Second order correction in the augmented system Jacobian [true]"}},
98 "initial step size [default: 0/estimated]"}},
101 "Max step size [default: 0/inf]"}},
105 {
"nonlin_conv_coeff",
107 "Coefficient in the nonlinear convergence test"}},
110 "Scale absolute tolerance by nominal value"}}
126 std::string newton_scheme =
"direct";
128 std::string interpolation_type =
"hermite";
140 for (
auto&& op : opts) {
141 if (op.first==
"abstol") {
143 }
else if (op.first==
"reltol") {
145 }
else if (op.first==
"max_num_steps") {
147 }
else if (op.first==
"stop_at_end") {
150 casadi_warning(
"The 'stop_at_end' option has been deprecated and is currently ignored");
152 }
else if (op.first==
"use_preconditioner") {
154 }
else if (op.first==
"max_krylov") {
156 }
else if (op.first==
"newton_scheme") {
157 newton_scheme = op.second.to_string();
158 }
else if (op.first==
"linear_solver") {
160 }
else if (op.first==
"linear_solver_options") {
162 }
else if (op.first==
"quad_err_con") {
164 }
else if (op.first==
"interpolation_type") {
165 interpolation_type = op.second.to_string();
166 }
else if (op.first==
"steps_per_checkpoint") {
168 }
else if (op.first==
"disable_internal_warnings") {
170 }
else if (op.first==
"max_multistep_order") {
172 }
else if (op.first==
"second_order_correction") {
174 }
else if (op.first==
"step0") {
176 }
else if (op.first==
"max_step_size") {
178 }
else if (op.first==
"max_order") {
180 }
else if (op.first==
"nonlin_conv_coeff") {
182 }
else if (op.first==
"scale_abstol") {
188 if (newton_scheme==
"direct") {
190 }
else if (newton_scheme==
"gmres") {
192 }
else if (newton_scheme==
"bcgstab") {
194 }
else if (newton_scheme==
"tfqmr") {
197 casadi_error(
"Unknown Newton scheme: " + newton_scheme);
201 if (interpolation_type==
"hermite") {
203 }
else if (interpolation_type==
"polynomial") {
206 casadi_error(
"Unknown interpolation type: " + interpolation_type);
213 casadi_assert_dev(d !=
nullptr);
222 {
"jac:ode:x",
"jac:alg:x",
"jac:ode:z",
"jac:alg:z"});
254 create_function(
"jtimesF", {
"t",
"x",
"z",
"p",
"u",
"fwd:x",
"fwd:z"},
255 {
"fwd:ode",
"fwd:alg"});
276 casadi_int*& iw,
double*& w)
const {
299 m->v_q = N_VNew_Serial(
nq_);
300 m->v_adj_xz = N_VNew_Serial(
nrx_ +
nrz_);
301 m->v_adj_pu = N_VNew_Serial(
nrq_ +
nuq_);
306 m->abstolv = N_VNew_Serial(
nx_ +
nz_);
308 double* abstolv = NV_DATA_S(m->abstolv);
310 for (casadi_int d = 0; d <=
nfwd_; ++d) {
314 for (casadi_int d = 0; d <=
nfwd_; ++d) {
318 casadi_assert_dev(abstolv == NV_DATA_S(m->abstolv) +
nx_ +
nz_);
320 m->abstolv =
nullptr;
393 N_VConst(0., m->v_adj_pu);
397 const double* adj_x,
const double* adj_z,
const double* adj_q)
const {
413 this->
v_xz =
nullptr;
423 if (this->
v_xz) N_VDestroy_Serial(this->
v_xz);
424 if (this->
v_q) N_VDestroy_Serial(this->
v_q);
435 stats[
"nsteps"] =
static_cast<casadi_int
>(m->nsteps);
436 stats[
"nfevals"] =
static_cast<casadi_int
>(m->nfevals);
437 stats[
"nlinsetups"] =
static_cast<casadi_int
>(m->nlinsetups);
438 stats[
"netfails"] =
static_cast<casadi_int
>(m->netfails);
439 stats[
"qlast"] = m->
qlast;
440 stats[
"qcur"] = m->qcur;
441 stats[
"hinused"] = m->hinused;
442 stats[
"hlast"] = m->hlast;
443 stats[
"hcur"] = m->hcur;
444 stats[
"tcur"] = m->tcur;
445 stats[
"nniters"] =
static_cast<casadi_int
>(m->nniters);
446 stats[
"nncfails"] =
static_cast<casadi_int
>(m->nncfails);
449 stats[
"nstepsB"] =
static_cast<casadi_int
>(m->nstepsB);
450 stats[
"nfevalsB"] =
static_cast<casadi_int
>(m->nfevalsB);
451 stats[
"nlinsetupsB"] =
static_cast<casadi_int
>(m->nlinsetupsB);
452 stats[
"netfailsB"] =
static_cast<casadi_int
>(m->netfailsB);
453 stats[
"qlastB"] = m->qlastB;
454 stats[
"qcurB"] = m->qcurB;
455 stats[
"hinusedB"] = m->hinusedB;
456 stats[
"hlastB"] = m->hlastB;
457 stats[
"hcurB"] = m->hcurB;
458 stats[
"tcurB"] = m->tcurB;
459 stats[
"nnitersB"] =
static_cast<casadi_int
>(m->nnitersB);
460 stats[
"nncfailsB"] =
static_cast<casadi_int
>(m->nncfailsB);
466 print(
"FORWARD INTEGRATION:\n");
467 print(
"Number of steps taken by SUNDIALS: %ld\n", m->nsteps);
468 print(
"Number of calls to the user's f function: %ld\n", m->nfevals);
469 print(
"Number of calls made to the linear solver setup function: %ld\n", m->nlinsetups);
470 print(
"Number of error test failures: %ld\n", m->netfails);
471 print(
"Method order used on the last internal step: %d\n", m->qlast);
472 print(
"Method order to be used on the next internal step: %d\n", m->qcur);
473 print(
"Actual value of initial step size: %g\n", m->hinused);
474 print(
"Step size taken on the last internal step: %g\n", m->hlast);
475 print(
"Step size to be attempted on the next internal step: %g\n", m->hcur);
476 print(
"Current internal time reached: %g\n", m->tcur);
477 print(
"Number of nonlinear iterations performed: %ld\n", m->nniters);
478 print(
"Number of nonlinear convergence failures: %ld\n", m->nncfails);
480 print(
"BACKWARD INTEGRATION:\n");
481 print(
"Number of steps taken by SUNDIALS: %ld\n", m->nstepsB);
482 print(
"Number of calls to the user's f function: %ld\n", m->nfevalsB);
483 print(
"Number of calls made to the linear solver setup function: %ld\n", m->nlinsetupsB);
484 print(
"Number of error test failures: %ld\n", m->netfailsB);
485 print(
"Method order used on the last internal step: %d\n" , m->qlastB);
486 print(
"Method order to be used on the next internal step: %d\n", m->qcurB);
487 print(
"Actual value of initial step size: %g\n", m->hinusedB);
488 print(
"Step size taken on the last internal step: %g\n", m->hlastB);
489 print(
"Step size to be attempted on the next internal step: %g\n", m->hcurB);
490 print(
"Current internal time reached: %g\n", m->tcurB);
491 print(
"Number of nonlinear iterations performed: %ld\n", m->nnitersB);
492 print(
"Number of nonlinear convergence failures: %ld\n", m->nncfailsB);
498 int version = s.
version(
"SundialsInterface", 1, 2);
528 s.
unpack(
"SundialsInterface::newton_scheme", newton_scheme);
532 s.
unpack(
"SundialsInterface::interp", interp);
539 s.
version(
"SundialsInterface", 2);
565 s.
pack(
"SundialsInterface::interp",
static_cast<int>(
interp_));
569 double* ode,
double* alg)
const {
596 const double* adj_ode,
const double* adj_alg,
const double* adj_quad,
597 double* adj_x,
double* adj_z)
const {
643 double* quad)
const {
666 const double* adj_ode,
const double* adj_alg,
double* adj_p,
double* adj_u)
const {
711 const double* fwd_x,
const double* fwd_z,
double* fwd_ode,
double* fwd_alg)
const {
743 double* jac_ode_x,
double* jac_alg_x,
double* jac_ode_z,
double* jac_alg_z)
const {
Helper class for Serialization.
void unpack(Sparsity &e)
Reconstruct an object from the input stream.
void version(const std::string &name, int v)
void alloc_iw(size_t sz_iw, bool persistent=false)
Ensure required length of iw field.
static std::string forward_name(const std::string &fcn, casadi_int nfwd)
Helper function: Get name of forward derivative function.
void alloc_w(size_t sz_w, bool persistent=false)
Ensure required length of w field.
Function derivative_of_
If the function is the derivative of another function.
casadi_int nnz_out() const
Get number of output nonzeros.
const Sparsity & sparsity_out(casadi_int ind) const
Get sparsity of a given output.
FunctionInternal * get() const
const std::string & name() const
Name of the function.
bool is_null() const
Is a null pointer?
Internal storage for integrator related data.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
casadi_int nfwd_
Number of sensitivities.
void init(const Dict &opts) override
Initialize.
virtual void reset(IntegratorMemory *mem, bool first_call) const
Reset the forward solver at the start or after an event.
static const Options options_
Options.
std::vector< double > nom_x_
casadi_int nrx_
Number of states for the backward integration.
int init_mem(void *mem) const override
Initalize memory block.
std::vector< double > nom_z_
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
casadi_int nx_
Number of states for the forward integration.
casadi_int checkout() const
Checkout a memory object.
const Sparsity & sparsity() const
Get linear system sparsity.
void set_function(const Function &fcn, const std::string &fname, bool jit=false)
Function create_function(const Function &oracle, const std::string &fname, const std::vector< std::string > &s_in, const std::vector< std::string > &s_out, const Function::AuxOut &aux=Function::AuxOut(), const Dict &opts=Dict())
Function create_forward(const std::string &fname, casadi_int nfwd)
int calc_function(OracleMemory *m, const std::string &fcn, const double *const *arg=nullptr, int thread_id=0) const
std::vector< std::string > get_function() const override
Get list of dependency functions.
Dict get_stats(void *mem) const override
Get all statistics.
void print(const char *fmt,...) const
C-style formatted printing during evaluation.
Helper class for Serialization.
void version(const std::string &name, int v)
void pack(const Sparsity &e)
Serializes an object to the output stream.
static Sparsity diag(casadi_int nrow)
Create diagonal sparsity pattern *.
casadi_int nnz() const
Get the number of (structural) non-zeros.
Linsol linsolF_
Linear solver.
void set_work(void *mem, const double **&arg, double **&res, casadi_int *&iw, double *&w) const override
Set the (persistent) work vectors.
enum casadi::SundialsInterface::InterpType interp_
static SundialsMemory * to_mem(void *mem)
Cast to memory object.
void impulseB(IntegratorMemory *mem, const double *adj_x, const double *adj_z, const double *adj_q) const override
Introduce an impulse into the backwards integration at the current time.
Dict get_stats(void *mem) const override
Get all statistics.
int calc_jacF(SundialsMemory *m, double t, const double *x, const double *z, double *jac_ode_x, double *jac_alg_x, double *jac_ode_z, double *jac_alg_z) const
std::string linear_solver_
NewtonScheme
Supported iterative solvers in Sundials.
void print_stats(IntegratorMemory *mem) const override
Print solver statistics.
double nonlin_conv_coeff_
Dict linear_solver_options_
int calc_quadF(SundialsMemory *m, double t, const double *x, const double *z, double *quad) const
SundialsInterface(const std::string &name, const Function &dae, double t0, const std::vector< double > &tout)
Constructor.
void serialize_body(SerializingStream &s) const override
Serialize an object without type information.
int calc_jtimesF(SundialsMemory *m, double t, const double *x, const double *z, const double *fwd_x, const double *fwd_z, double *fwd_ode, double *fwd_alg) const
enum casadi::SundialsInterface::NewtonScheme newton_scheme_
void reset(IntegratorMemory *mem, bool first_call) const override
Reset the forward solver at the start or after an event.
void reset_stats(SundialsMemory *m) const
Reset stats.
bool disable_internal_warnings_
casadi_int max_multistep_order_
int calc_daeF(SundialsMemory *m, double t, const double *x, const double *z, double *ode, double *alg) const
int init_mem(void *mem) const override
Initalize memory block.
void add_offsets(SundialsMemory *m) const
Add stats offsets to stats.
~SundialsInterface() override=0
Destructor.
int calc_quadB(SundialsMemory *m, double t, const double *x, const double *z, const double *adj_ode, const double *adj_alg, double *adj_p, double *adj_u) const
casadi_int max_num_steps_
bool second_order_correction_
void init(const Dict &opts) override
Initialize.
void resetB(IntegratorMemory *mem) const override
Reset the backward problem and take time to tf.
void save_offsets(SundialsMemory *m) const
Save stats offsets before reset.
casadi_int steps_per_checkpoint_
int calc_daeB(SundialsMemory *m, double t, const double *x, const double *z, const double *adj_ode, const double *adj_alg, const double *adj_quad, double *adj_x, double *adj_z) const
static const Options options_
Options.
void casadi_copy(const T1 *x, casadi_int n, T1 *y)
COPY: y <-x.
GenericType::Dict Dict
C++ equivalent of Python's dict or MATLAB's struct.
const double nan
Not a number.
void casadi_axpy(casadi_int n, T1 alpha, const T1 *x, T1 *y)
AXPY: y <- a*x + y.
void casadi_clear(T1 *x, casadi_int n)
CLEAR: x <- 0.
Options metadata for a class.
SundialsMemory()
Constructor.
~SundialsMemory()
Destructor.
long nstepsB
Stats, backward integration.
long nstepsB_off
Offsets for stats in backward integration.
long nsteps
Stats, forward integration.
int mem_linsolF
Linear solver memory objects.