/RungeKutta

ODE solver based on Runge-Kutta method

Primary LanguageC++

RungeKutta v0.1.0

RungeKutta is a library for finding approximate solutions of ordinary differential equations.

RungeKutta Methods

2nd Order Methods
  • RK2HeunSolve
  • RK2MidpointSolve
  • RK2RalstonSolve
  • RK2GenericSolve
3rd Order Methods
  • RK3Solve
  • RK3GenericSolve
  • SSPRK3Solve
  • RK3HeunSolve
  • RK3RalstonSolve
4th Order Methods
  • RK4Solve
  • RK4ClassicSolve
  • RK4RalstonSolve
  • SSPRK4Solve
5th Order Methods
  • SSPRK5Solve
Adaptive Methods
  • ASRKBogackiShampineSolve
  • ASRKFehlbergSolve
  • ASRKCashKarpSolve
  • ASRKDormandPrinceSolve
Master Functions
  • RKMasterSolve
  • RKMasterSystemSolve
  • ASRKMasterSolve
  • ASRKMasterSystemSolve

Examples

rk::Expression

rk::Expression is a main template class for storing and managing functions in RungeKutta library. All calculations are performed using the type Value.

rk::Expression::parse

Using this method you can create rk::Expression from string

#include <iostream>
#include "RungeKutta.h"

int main() {
    rk::Expression<double> expression;
    expression.parse("6 * 7");
    std::cout << expression.evaluate() << std::endl;
    return 0;
}
~ 42

rk::Expression::setFunction

Using this method you can create rk::Expression from your own function, presented as Value (*function)(const Value*).

#include <iostream>
#include "RungeKutta.h"

double myFunction(const double* data) {
    return data[0] + data[1];
}

int main() {
    rk::Expression<double> expression;
    expression.setFunction(myFunction);
    std::cout << expression.evaluate({1, 2}) << std::endl;
}
~ 3

rk::Expression::compile

Any rk::Expression can be compiled into byte code, which will magnificently increase performance, up to 1000%.

#include <iostream>
#include "RungeKutta.h"

int main() {
    rk::Expression<double> expression;
    expression.parse("x + sin(y)", {"x", "y"});
    expression.compile();
    std::cout << expression.evaluate({1, 2}) << std::endl;
    return 0;
}
~ 1.9093

rk::Expression::evaluate

You can evaluate your function, providing all variables values in the very same order as in parse.

#include <iostream>
#include "RungeKutta.h"

int main() {
    rk::Expression<double> expression;
    expression.parse("x + sin(y) - cos(x) * 10 + pow(1.5, 3.2)", {"x", "y"});
    std::cout << expression.evaluate({1, 2}) << std::endl;
    return 0;
}
~ 0.166367

rk::Expression::addFunctionToken

Maybe, you will also need your own function, used inside expression, for that, you can use this method to add new <math.h> function token into token pool, which will be used in parse and compile methods.

#include <iostream>
#include "RungeKutta.h"

template<typename Value>
class AddToken: public FunctionToken<Value> {
public:
    void evaluate(std::stack<Value>& s, const std::vector<Value>& vars) const override {
        Value a = s.top();
        s.pop();
        Value b = s.top();
        s.pop();
        s.push(a + b);
    }
    [[nodiscard]] std::string cname() const override { return "add"; }
};

int main() {
    rk::Expression<double> expression;
    rk::Expression<double>::addFunctionToken("add", std::make_shared<AddToken<double>>());
    expression.parse("add(x, y)", {"x", "y"});
    std::cout << expression.evaluate({6, 3}) << std::endl;
    return 0;
}
~ 9