Janus 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 Janus public API.
JanusVector< Scalar > rk4_step(Func &&f, const JanusVector< Scalar > &x, Scalar t, Scalar dt)
Classic 4th-order Runge-Kutta integration step.
Definition IntegratorStep.hpp:131
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
Core API
Step Integrators
Trajectory Solvers
- janus::solve_ivp(dynamics, t_span, y0, n_eval): Full trajectory integration for first-order systems.
- janus::solve_second_order_ivp(accel, t_span, q0, v0, n_eval, opts): Trajectory integration for second-order systems with separate coordinates and velocities.
- janus::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 JanusVector< 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 JanusVector< Scalar > &q, const JanusVector< Scalar > &v, Scalar t, Scalar dt)
Stormer-Verlet / velocity-Verlet step for q'' = a(t, q).
Definition IntegratorStep.hpp:167
- janus::stormer_verlet_step(...) is symplectic and keeps long-horizon energy error bounded for separable Hamiltonian systems.
- janus::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
);
@ StormerVerlet
Symplectic Stormer-Verlet / velocity-Verlet.
Definition Integrate.hpp:73
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
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), Janus 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
);
JanusMatrix< NumericScalar > NumericMatrix
Eigen::MatrixXd equivalent.
Definition JanusTypes.hpp:66
@ 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
Options for stiff mass-matrix integration.
Definition Integrate.hpp:121
int substeps
Definition Integrate.hpp:123
MassMatrixIntegratorMethod method
Definition Integrate.hpp:122
- 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
);
JanusVector< SymbolicScalar > SymbolicVector
Eigen vector of MX elements.
Definition JanusTypes.hpp:72
SymbolicVector sym_vec(const std::string &name, int size)
Create a symbolic vector preserving the CasADi primitive connection.
Definition JanusTypes.hpp:137
casadi::MX to_mx(const Eigen::MatrixBase< Derived > &e)
Convert Eigen matrix of MX (or numeric) to CasADi MX.
Definition JanusTypes.hpp:189
SymbolicScalar sym(const std::string &name)
Create a named symbolic scalar variable.
Definition JanusTypes.hpp:90
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 JanusVector<Scalar> get_state() const = 0;
virtual void set_state(const JanusVector<Scalar>& s) = 0;
virtual JanusVector<Scalar> compute_derivative(Scalar t) const = 0;
};
class RigidBody : public IntegrableState<double> {
Vec3<double> position, velocity, acceleration;
JanusVector<double> get_state() const override { }
void set_state(const JanusVector<double>& s) override { }
JanusVector<double> compute_derivative(double t) const override {
dydt << velocity, acceleration;
return dydt;
}
};
JanusVector< NumericScalar > NumericVector
Eigen::VectorXd equivalent.
Definition JanusTypes.hpp:67
See Also