Program Listing for File rk4_integrator_usage.cpp

Return to documentation for file (examples/rk4_integrator_usage.cpp)

#include <iostream>
#include <vector>
#include <array>
#include <iomanip>
#include <memory>
#include <diffeq.hpp>

// Example 1: Simple exponential decay
// dy/dt = -k*y, where k is the decay constant
void exponential_decay(double t, const std::vector<double>& y, std::vector<double>& dydt) {
    const double k = 0.5; // decay constant
    dydt[0] = -k * y[0];
}

// Example 2: Lorenz attractor (simplified)
// dx/dt = sigma*(y - x)
// dy/dt = x*(rho - z) - y
// dz/dt = xy - beta*z
void lorenz_system(double t, const std::vector<double>& state, std::vector<double>& dydt) {
    const double sigma = 10.0;
    const double rho = 28.0;
    const double beta = 8.0/3.0;

    double x = state[0];
    double y = state[1];
    double z = state[2];

    dydt[0] = sigma * (y - x);
    dydt[1] = x * (rho - z) - y;
    dydt[2] = x * y - beta * z;
}

// Example 3: Damped harmonic oscillator
// d^2x/dt^2 + 2*gamma*(dx/dt) + omega^2*x = 0
// State: [x, dx/dt]
void damped_oscillator(float t, const std::array<float, 2>& state, std::array<float, 2>& dydt) {
    const float gamma = 0.1f; // damping coefficient
    const float omega_sq = 4.0f; // omega^2 = 4

    dydt[0] = state[1]; // dx/dt = v
    dydt[1] = -2.0f * gamma * state[1] - omega_sq * state[0]; // dv/dt = -2*gamma*v - omega^2*x
}

int main() {
    std::cout << "RK4 Integrator Usage Examples" << std::endl;
    std::cout << "==============================" << std::endl;
    std::cout << std::fixed << std::setprecision(6);

    // Example 1: Exponential Decay
    std::cout << "\n1. Exponential Decay (dy/dt = -0.5*y)" << std::endl;
    std::cout << "-------------------------------------" << std::endl;

    diffeq::RK4Integrator<std::vector<double>> decay_integrator(exponential_decay);
    std::vector<double> decay_state = {2.0}; // y(0) = 2

    std::cout << "Time\tValue" << std::endl;
    std::cout << "0.0\t" << decay_state[0] << std::endl;

    for (int i = 0; i < 10; ++i) {
        decay_integrator.step(decay_state, 0.5);
        std::cout << decay_integrator.current_time() << "\t" << decay_state[0] << std::endl;
    }

    // Example 2: Lorenz System
    std::cout << "\n2. Lorenz Attractor (first 20 steps)" << std::endl;
    std::cout << "------------------------------------" << std::endl;

    diffeq::RK4Integrator<std::vector<double>> lorenz_integrator(lorenz_system);
    std::vector<double> lorenz_state = {1.0, 1.0, 1.0}; // Initial conditions

    std::cout << "Time\tX\t\tY\t\tZ" << std::endl;
    std::cout << "0.0\t" << lorenz_state[0] << "\t\t" << lorenz_state[1] << "\t\t" << lorenz_state[2] << std::endl;

    for (int i = 0; i < 20; ++i) {
        lorenz_integrator.step(lorenz_state, 0.01);
        if (i % 5 == 4) { // Print every 5th step
            std::cout << lorenz_integrator.current_time() << "\t"
                      << lorenz_state[0] << "\t\t"
                      << lorenz_state[1] << "\t\t"
                      << lorenz_state[2] << std::endl;
        }
    }

    // Example 3: Damped Harmonic Oscillator with float precision
    std::cout << "\n3. Damped Harmonic Oscillator (float precision)" << std::endl;
    std::cout << "----------------------------------------------" << std::endl;

    diffeq::RK4Integrator<std::array<float, 2>> oscillator_integrator(damped_oscillator);
    std::array<float, 2> oscillator_state = {1.0f, 0.0f}; // x(0) = 1, v(0) = 0

    std::cout << "Time\tPosition\tVelocity" << std::endl;
    std::cout << "0.0\t" << oscillator_state[0] << "\t\t" << oscillator_state[1] << std::endl;

    for (int i = 0; i < 50; ++i) {
        oscillator_integrator.step(oscillator_state, 0.1f);
        if (i % 10 == 9) { // Print every 10th step
            std::cout << oscillator_integrator.current_time() << "\t"
                      << oscillator_state[0] << "\t\t"
                      << oscillator_state[1] << std::endl;
        }
    }

    // Example 4: Using polymorphism
    std::cout << "\n4. Polymorphic Usage" << std::endl;
    std::cout << "-------------------" << std::endl;

    auto integrator = std::make_unique<diffeq::RK4Integrator<std::vector<double>>>(exponential_decay);
    AbstractIntegrator<std::vector<double>>* base_ptr = integrator.get();

    std::vector<double> poly_state = {5.0};
    std::cout << "Initial: t=" << base_ptr->current_time() << ", y=" << poly_state[0] << std::endl;

    base_ptr->integrate(poly_state, 0.1, 2.0); // Integrate from t=0 to t=2 with dt=0.1
    std::cout << "Final: t=" << base_ptr->current_time() << ", y=" << poly_state[0] << std::endl;

    return 0;
}