Metis provides explicit ODE integrators for simulation with dual-mode (numeric/symbolic) support, plus structure-preserving and stiff mass-matrix integrators for the cases where generic RK integration is the wrong tool. All step functions work in both numeric and symbolic modes, making them suitable for simulation, trajectory optimization, and sensitivity analysis.
Quick Start
return -0.5 * y;
};
y(0) = 1.0;
double t = 0.0, dt = 0.1;
Umbrella header that includes the entire Metis public API.
MetisVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition MetisTypes.hpp:67
MetisVector< Scalar > rk4_step(Func &&f, const MetisVector< Scalar > &x, Scalar t, Scalar dt)
Classic 4th-order Runge-Kutta integration step.
Definition IntegratorStep.hpp:131
Core API
Step Integrators
Trajectory Solvers
- metis::solve_ivp(dynamics, t_span, y0, n_eval): Full trajectory integration for first-order systems.
- metis::solve_second_order_ivp(accel, t_span, q0, v0, n_eval, opts): Trajectory integration for second-order systems with separate coordinates and velocities.
- metis::solve_ivp_mass_matrix(rhs, mass, t_span, y0, n_eval, opts): Stiff and mass-matrix systems M(t,y) y' = f(t,y).
Usage Patterns
RK4 Step (Recommended)
double omega = 2.0;
ds << s(1), -omega * omega * s(0);
return ds;
};
state << 1.0, 0.0;
double t = 0.0;
for (int i = 0; i < 100; ++i) {
t += 0.01;
}
Adaptive Stepping with RK45
double dt = 0.1;
double tol = 1e-6;
while (t < t_final) {
if (result.error < tol) {
y = result.y5;
t += dt;
dt *= 1.5;
} else {
dt *= 0.5;
}
}
RK45Result< Scalar > rk45_step(Func &&f, const MetisVector< Scalar > &x, Scalar t, Scalar dt)
Dormand-Prince RK45 integration step with embedded error estimate.
Definition IntegratorStep.hpp:250
Structure-Preserving Second-Order Steppers
When your dynamics are naturally written as q'' = a(t, q), it is better to integrate that form directly than to augment it into a generic first-order state and run plain RK4.
q << 1.0;
v << 0.0;
return (-q_state).eval();
};
q = step.q;
v = step.v;
SecondOrderStepResult< Scalar > stormer_verlet_step(AccelFunc &&acceleration, const MetisVector< Scalar > &q, const MetisVector< Scalar > &v, Scalar t, Scalar dt)
Stormer-Verlet / velocity-Verlet step for q'' = a(t, q).
Definition IntegratorStep.hpp:167
- metis::stormer_verlet_step(...) is symplectic and keeps long-horizon energy error bounded for separable Hamiltonian systems.
- metis::rkn4_step(...) is a higher-order Runge-Kutta-Nystrom method for the same q'' = a(t, q) API.
Trajectory Solver
For full trajectory integration, use solve_ivp:
dynamics,
{0.0, 10.0},
{1.0},
100
);
OdeResult< double > solve_ivp(Func &&fun, std::pair< double, double > t_span, const NumericVector &y0, int n_eval=100, double abstol=1e-8, double reltol=1e-6)
Solve initial value problem: dy/dt = f(t, y), y(t0) = y0.
Definition Integrate.hpp:481
For second-order systems, use solve_second_order_ivp(...) to keep coordinates and velocities separate:
accel,
{0.0, 100.0},
{1.0},
{0.0},
1000,
opts
);
SecondOrderOdeResult< double > solve_second_order_ivp(AccelFunc &&acceleration, std::pair< double, double > t_span, const NumericVector &q0, const NumericVector &v0, int n_eval=100, const SecondOrderIvpOptions &opts={})
Solve a second-order IVP q'' = a(t, q), q(t0) = q0, v(t0) = v0.
Definition Integrate.hpp:558
@ StormerVerlet
Symplectic Stormer-Verlet / velocity-Verlet.
Definition Integrate.hpp:73
Options for second-order structure-preserving trajectory integration.
Definition Integrate.hpp:113
SecondOrderIntegratorMethod method
Definition Integrate.hpp:114
Stiff and Mass-Matrix Systems
For systems of the form M(t, y) y' = f(t, y), Metis provides a dedicated solver surface:
rhs << y(1), 1.0 - y(0) - y(1);
return rhs;
},
M(0, 0) = 1.0;
return M;
},
{0.0, 1.0},
{0.0, 1.0},
50,
opts
);
@ Bdf1
Backward Euler / first-order BDF with Newton iterations.
Definition Integrate.hpp:82
OdeResult< double > solve_ivp_mass_matrix(RhsFunc &&rhs, MassFunc &&mass_matrix, std::pair< double, double > t_span, const NumericVector &y0, int n_eval=100, const MassMatrixIvpOptions &opts={})
Solve M(t, y) y' = f(t, y) with a native numeric stiff integrator.
Definition Integrate.hpp:638
MetisMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition MetisTypes.hpp:66
Options for stiff mass-matrix integration.
Definition Integrate.hpp:121
MassMatrixIntegratorMethod method
Definition Integrate.hpp:122
int substeps
Definition Integrate.hpp:123
- MassMatrixIntegratorMethod::RosenbrockEuler is a one-stage linearly implicit stiff integrator.
- MassMatrixIntegratorMethod::Bdf1 solves the backward-Euler residual directly and can handle simple singular mass-matrix systems.
- solve_ivp_mass_matrix_expr(...) uses CasADi IDAS on the symbolic expression path by rewriting the mass-matrix system into a semi-explicit DAE.
Symbolic Mode
All step functions work with symbolic types for optimization:
[](auto t, const auto& x) {
dx << x(1), -4.0 * x(0);
return dx;
},
x, t, dt
);
MetisVector< SymbolicScalar > SymbolicVector
Eigen vector of MX elements.
Definition MetisTypes.hpp:72
SymbolicVector sym_vec(const std::string &name, int size)
Create a symbolic vector preserving the CasADi primitive connection.
Definition MetisTypes.hpp:154
SymbolicScalar sym(const std::string &name)
Create a named symbolic scalar variable.
Definition MetisTypes.hpp:107
casadi::MX to_mx(const Eigen::MatrixBase< Derived > &e)
Convert Eigen matrix of MX (or numeric) to CasADi MX.
Definition MetisTypes.hpp:206
The structure-preserving step APIs are also symbolic-safe:
[](auto time, const auto& q_state) { return (-q_state).eval(); },
q, v, t, dt
);
Component-Based Integration (Icarus Pattern)
For simulation frameworks with component models:
template <typename Scalar>
class IntegrableState {
public:
virtual MetisVector<Scalar> get_state() const = 0;
virtual void set_state(const MetisVector<Scalar>& s) = 0;
virtual MetisVector<Scalar> compute_derivative(Scalar t) const = 0;
};
class RigidBody : public IntegrableState<double> {
Vec3<double> position, velocity, acceleration;
MetisVector<double> get_state() const override { }
void set_state(const MetisVector<double>& s) override { }
MetisVector<double> compute_derivative(double t) const override {
dydt << velocity, acceleration;
return dydt;
}
};
MetisVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition MetisTypes.hpp:67
See Also