Skip to content

Commit e78ee7f

Browse files
Added implementations of Runga kutta method along with test cases
1 parent 9010481 commit e78ee7f

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

Maths/RungaKutta.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @function rungeKuttaStep
3+
* @description Runge-Kutta step function to calculate the next y-value based on the current x-value, y-value, step size and differential equation.
4+
* @param {number} xCurrent - The current x-value
5+
* @param {number} stepSize - The step size
6+
* @param {number} yCurrent - The current y-value
7+
* @param {function} differentialEquation - The differential equation to solve
8+
* @returns {number} - The next y-value
9+
* @example rungeKuttaStep(0, 0.1, 1, function (x, y) { return Math.sin(x) + y; }); // returns 1.10517
10+
* @example rungeKuttaStep(0.5, 0.1, 1, function (x, y) { return Math.exp(x) - y; }); // returns 1.15233
11+
*/
12+
export function rungeKuttaStep(xCurrent, stepSize, yCurrent, differentialEquation) {
13+
// Calculate the four slopes: k1, k2, k3, k4
14+
const k1 = stepSize * differentialEquation(xCurrent, yCurrent);
15+
const k2 = stepSize * differentialEquation(xCurrent + stepSize / 2, yCurrent + k1 / 2);
16+
const k3 = stepSize * differentialEquation(xCurrent + stepSize / 2, yCurrent + k2 / 2);
17+
const k4 = stepSize * differentialEquation(xCurrent + stepSize, yCurrent + k3);
18+
19+
// Calculate the next y-value using the weighted average of the four slopes
20+
return yCurrent + (1 / 6) * (k1 + 2 * k2 + 2 * k3 + k4);
21+
}
22+
23+
/**
24+
* @description Runge-Kutta method for solving ordinary differential equations (ODEs) with a given initial value. It is a numerical procedure for solving ODEs. The method proceeds in a series of steps. At each step the y-value is calculated by evaluating the differential equation at the previous step, multiplying the result with the step-size and adding it to the last y-value.
25+
* @param {number} xStart - The starting x-value
26+
* @param {number} xEnd - The ending x-value
27+
* @param {number} stepSize - The step size
28+
* @param {number} yStart - The starting y-value
29+
* @param {function} differentialEquation - The differential equation to solve
30+
* @returns {Array} - An array of points (x, y) for the complete iteration from xStart to xEnd
31+
* @see https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods
32+
* @example rungeKuttaFull(0, 1, 0.2, 1, function (x, y) { return Math.sin(x) + y; });
33+
* [{ x: 0, y: 1 },
34+
* { x: 0.2, y: 1.22140 },
35+
* { x: 0.4, y: 1.53659 },
36+
* { x: 0.6, y: 1.95837 },
37+
* { x: 0.8, y: 2.50487 },
38+
* { x: 1.0, y: 3.20155 }]
39+
*/
40+
export function rungeKuttaFull(xStart, xEnd, stepSize, yStart, differentialEquation) {
41+
// Collect all the points (x, y) for the complete iteration from xStart to xEnd
42+
const points = [{ x: xStart, y: yStart }];
43+
let yCurrent = yStart;
44+
let xCurrent = xStart;
45+
46+
while (xCurrent < xEnd) {
47+
// Runge-Kutta method for the next step
48+
yCurrent = rungeKuttaStep(xCurrent, stepSize, yCurrent, differentialEquation);
49+
xCurrent += stepSize;
50+
51+
// Push the new point to the points array
52+
points.push({ x: xCurrent, y: yCurrent });
53+
}
54+
55+
return points;
56+
}
57+

Maths/test/RungaKutta.test.js

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { rungeKuttaStep, rungeKuttaFull } from '../RungeKuttaMethod';
2+
3+
describe('rungeKuttaStep', () => {
4+
it('should calculate the next y value correctly for trigonometric function', () => {
5+
expect(
6+
rungeKuttaStep(0, 0.1, 1, function (x, y) {
7+
return Math.sin(x) + y;
8+
})
9+
).toBeCloseTo(1.10517, 5);
10+
});
11+
12+
it('should calculate the next y value correctly for exponential function', () => {
13+
expect(
14+
rungeKuttaStep(0.5, 0.1, 1, function (x, y) {
15+
return Math.exp(x) - y;
16+
})
17+
).toBeCloseTo(1.15233, 5);
18+
});
19+
});
20+
21+
describe('rungeKuttaFull', () => {
22+
it('should return all the points found for trigonometric function', () => {
23+
expect(
24+
rungeKuttaFull(0, 1, 0.2, 1, function (x, y) {
25+
return Math.sin(x) + y;
26+
})
27+
).toEqual([
28+
{ x: 0, y: 1 },
29+
{ x: 0.2, y: 1.22140 },
30+
{ x: 0.4, y: 1.53659 },
31+
{ x: 0.6, y: 1.95837 },
32+
{ x: 0.8, y: 2.50487 },
33+
{ x: 1.0, y: 3.20155 }
34+
]);
35+
});
36+
37+
it('should return all the points found for exponential function', () => {
38+
expect(
39+
rungeKuttaFull(0, 1, 0.25, 1, function (x, y) {
40+
return Math.exp(-x) * y;
41+
})
42+
).toEqual([
43+
{ x: 0, y: 1 },
44+
{ x: 0.25, y: 1.24238 },
45+
{ x: 0.5, y: 1.51460 },
46+
{ x: 0.75, y: 1.82186 },
47+
{ x: 1.0, y: 2.16955 }
48+
]);
49+
});
50+
});

0 commit comments

Comments
 (0)