13void exponential_decay(
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
22 void operator()(
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
24 dydt[1] = mu_ * (1 - y[0]*y[0]) * y[1] - y[0];
32void lorenz_system(
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
33 const double sigma = 10.0;
34 const double rho = 28.0;
35 const double beta = 8.0/3.0;
37 dydt[0] = sigma * (y[1] - y[0]);
38 dydt[1] = y[0] * (rho - y[2]) - y[1];
39 dydt[2] = y[0] * y[1] - beta * y[2];
43void robertson_kinetics(
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
44 const double k1 = 0.04;
45 const double k2 = 3e7;
46 const double k3 = 1e4;
48 dydt[0] = -k1 * y[0] + k3 * y[1] * y[2];
49 dydt[1] = k1 * y[0] - k2 * y[1] * y[1] - k3 * y[1] * y[2];
50 dydt[2] = k2 * y[1] * y[1];
54template<
typename Integrator>
55double time_integrator(Integrator& integrator, std::vector<double>& y,
56 double t_start,
double dt,
double t_end,
const std::string& name) {
57 auto start = std::chrono::high_resolution_clock::now();
59 integrator.set_time(t_start);
62 const std::chrono::seconds TIMEOUT{30};
63 bool completed = diffeq::integrate_with_timeout(integrator, y, dt, t_end, TIMEOUT);
65 auto end = std::chrono::high_resolution_clock::now();
66 auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
68 std::cout << std::setw(15) << name <<
": y = [";
69 for (
size_t i = 0; i < y.size(); ++i) {
70 std::cout << std::setw(12) << std::scientific << std::setprecision(4) << y[i];
71 if (i < y.size() - 1) std::cout <<
", ";
73 std::cout <<
"] (Time: " << duration.count() <<
" us)";
76 std::cout <<
" [TIMEOUT]";
78 std::cout << std::endl;
80 return static_cast<double>(duration.count());
83void demonstrate_exponential_decay() {
84 std::cout <<
"\n=== Exponential Decay: dy/dt = -y, y(0) = 1 ===" << std::endl;
85 std::cout <<
"Analytical solution: y(t) = exp(-t)" << std::endl;
86 std::cout <<
"At t = 1: y(1) = " << std::exp(-1.0) << std::endl << std::endl;
88 double t_start = 0.0, t_end = 1.0, dt = 0.1;
92 std::vector<double> y = {1.0};
94 time_integrator(integrator, y, t_start, dt, t_end,
"RK4");
98 std::vector<double> y = {1.0};
100 time_integrator(integrator, y, t_start, dt, t_end,
"RK23");
104 std::vector<double> y = {1.0};
106 time_integrator(integrator, y, t_start, dt, t_end,
"RK45");
110 std::vector<double> y = {1.0};
112 time_integrator(integrator, y, t_start, dt, t_end,
"DOP853");
116 std::vector<double> y = {1.0};
118 time_integrator(integrator, y, t_start, dt, t_end,
"BDF");
122 std::vector<double> y = {1.0};
124 time_integrator(integrator, y, t_start, dt, t_end,
"LSODA");
128void demonstrate_van_der_pol() {
129 std::cout <<
"\n=== Van der Pol Oscillator: mu = 5 (moderately stiff) ===" << std::endl;
130 std::cout <<
"x''(t) - mu*(1-x^2)*x'(t) + x(t) = 0" << std::endl;
131 std::cout <<
"Initial conditions: x(0) = 1, x'(0) = 0" << std::endl << std::endl;
134 double t_start = 0.0, t_end = 10.0, dt = 0.1;
137 std::vector<double> y = {1.0, 0.0};
139 [&vdp](
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
142 time_integrator(integrator, y, t_start, dt, t_end,
"RK4");
146 std::vector<double> y = {1.0, 0.0};
148 [&vdp](
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
151 time_integrator(integrator, y, t_start, dt, t_end,
"RK45");
165 std::vector<double> y = {1.0, 0.0};
167 [&vdp](
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
170 time_integrator(integrator, y, t_start, dt, t_end,
"BDF");
174 std::vector<double> y = {1.0, 0.0};
176 [&vdp](
double t,
const std::vector<double>& y, std::vector<double>& dydt) {
179 double timing = time_integrator(integrator, y, t_start, dt, t_end,
"LSODA");
180 std::cout <<
" Final method: " <<
182 "Adams (non-stiff)" :
"BDF (stiff)") << std::endl;
186void demonstrate_lorenz_system() {
187 std::cout <<
"\n=== Lorenz System (Chaotic) ===" << std::endl;
188 std::cout <<
"dx/dt = sigma*(y - x), dy/dt = x*(rho - z) - y, dz/dt = xy - beta*z" << std::endl;
189 std::cout <<
"sigma = 10, rho = 28, beta = 8/3" << std::endl;
190 std::cout <<
"Initial conditions: x(0) = 1, y(0) = 1, z(0) = 1" << std::endl << std::endl;
192 double t_start = 0.0, t_end = 0.5, dt = 0.01;
195 std::vector<double> y = {1.0, 1.0, 1.0};
197 time_integrator(integrator, y, t_start, dt, t_end,
"RK4");
201 std::vector<double> y = {1.0, 1.0, 1.0};
203 time_integrator(integrator, y, t_start, dt, t_end,
"RK45");
207 std::vector<double> y = {1.0, 1.0, 1.0};
209 time_integrator(integrator, y, t_start, dt, t_end,
"DOP853");
213 std::vector<double> y = {1.0, 1.0, 1.0};
215 time_integrator(integrator, y, t_start, dt, t_end,
"LSODA");
219void demonstrate_stiff_robertson() {
220 std::cout <<
"\n=== Robertson Chemical Kinetics (Very Stiff) ===" << std::endl;
221 std::cout <<
"A -> B (k1 = 0.04)" << std::endl;
222 std::cout <<
"B + B -> B + C (k2 = 3e7)" << std::endl;
223 std::cout <<
"B + C -> A + C (k3 = 1e4)" << std::endl;
224 std::cout <<
"Initial conditions: A(0) = 1, B(0) = 0, C(0) = 0" << std::endl << std::endl;
226 double t_start = 0.0, t_end = 1.0, dt = 0.1;
228 std::cout <<
"Note: This is a very stiff system. Explicit methods may fail or be very slow." << std::endl;
229 std::cout <<
"Using shortened time range (t=1.0) for demonstration purposes." << std::endl;
242 std::vector<double> y = {1.0, 0.0, 0.0};
244 time_integrator(integrator, y, t_start, dt, t_end,
"BDF");
245 }
catch (
const std::exception& e) {
246 std::cout << std::setw(15) <<
"BDF" <<
": Failed - " << e.what() << std::endl;
250 std::vector<double> y = {1.0, 0.0, 0.0};
252 double timing = time_integrator(integrator, y, t_start, dt, t_end,
"LSODA");
253 std::cout <<
" Final method: " <<
255 "Adams (non-stiff)" :
"BDF (stiff)") << std::endl;
256 }
catch (
const std::exception& e) {
257 std::cout << std::setw(15) <<
"LSODA" <<
": Failed - " << e.what() << std::endl;
261void demonstrate_adaptive_features() {
262 std::cout <<
"\n=== Adaptive Step Size Control Demonstration ===" << std::endl;
263 std::cout <<
"Using RK45 with different tolerance levels on exponential decay" << std::endl << std::endl;
265 double t_start = 0.0, t_end = 2.0, dt = 0.1;
267 std::vector<std::pair<double, double>> tolerances = {
273 for (
auto [rtol, atol] : tolerances) {
274 std::vector<double> y = {1.0};
277 std::cout <<
"Tolerances: rtol = " << rtol <<
", atol = " << atol << std::endl;
278 time_integrator(integrator, y, t_start, dt, t_end,
"RK45");
280 double exact = std::exp(-t_end);
281 double error = std::abs(y[0] - exact);
282 std::cout <<
" Error: " << std::scientific << error << std::endl << std::endl;
287 std::cout <<
"Advanced ODE Integrators Demonstration" << std::endl;
288 std::cout <<
"======================================" << std::endl;
291 demonstrate_exponential_decay();
292 demonstrate_van_der_pol();
293 demonstrate_lorenz_system();
294 demonstrate_stiff_robertson();
295 demonstrate_adaptive_features();
297 std::cout <<
"\n=== Summary ===" << std::endl;
298 std::cout <<
"[OK] RK4: Simple, fixed-step 4th order method" << std::endl;
299 std::cout <<
"[OK] RK23: Adaptive 3rd order with embedded error estimation" << std::endl;
300 std::cout <<
"[OK] RK45: Adaptive 5th order Dormand-Prince (scipy default)" << std::endl;
301 std::cout <<
"[OK] DOP853: High-accuracy 8th order for demanding problems" << std::endl;
302 std::cout <<
"- Radau: Implicit 5th order for stiff systems (not yet implemented)" << std::endl;
303 std::cout <<
"[OK] BDF: Variable-order implicit multistep for stiff systems" << std::endl;
304 std::cout <<
"[OK] LSODA: Automatic method switching (Adams <-> BDF)" << std::endl;
306 }
catch (
const std::exception& e) {
307 std::cerr <<
"Error: " << e.what() << std::endl;
BDF (Backward Differentiation Formula) integrator.
DOP853 (Dormand-Prince 8(5,3)) adaptive integrator.
LSODA integrator - automatically switches between stiff and non-stiff methods.
RK23 (Bogacki-Shampine) adaptive integrator.
RK45 (Runge-Kutta-Fehlberg 4(5)) adaptive integrator.
Classical 4th-order Runge-Kutta integrator.
Modern C++ ODE Integration Library with Real-time Signal Processing.