UNPKG

keplerian-core

Version:

High-performance TypeScript library for orbital mechanics calculations, providing numerical integration, state propagation, and perturbation modeling for Keplerian orbits.

63 lines (62 loc) 3.01 kB
export const dormandPrince = { name: 'dormand-prince', displayName: 'Dormand-Prince 5(4)', description: 'Adaptive step-size Runge-Kutta method for high accuracy.', order: 5, recommended: true, function: (initialState, params, accelerationFn, time, dt) => { // Dormand-Prince 5(4) method coefficients const a = [ [0], [1 / 5], [3 / 40, 9 / 40], [44 / 45, -56 / 15, 32 / 9], [19372 / 6561, -25360 / 2187, 64448 / 6561, -212 / 729], [9017 / 3168, -355 / 33, 46732 / 5247, 49 / 176, -5103 / 18656], [35 / 384, 0, 500 / 1113, 125 / 192, -2187 / 6784, 11 / 84] ]; const b = [ 35 / 384, 0, 500 / 1113, 125 / 192, -2187 / 6784, 11 / 84, 0 ]; const b_star = [ 5179 / 57600, 0, 7571 / 16695, 393 / 640, -92097 / 339200, 187 / 2100, 1 / 40 ]; const c = [0, 1 / 5, 3 / 10, 4 / 5, 8 / 9, 1, 1]; const k = Array(7).fill(null).map(() => [{ x: 0, y: 0 }, { x: 0, y: 0 }]); const { position, velocity } = initialState; // k1 k[0][0] = velocity; k[0][1] = accelerationFn(position, velocity, params); for (let i = 1; i < 7; i++) { let pos_i = { x: position.x, y: position.y }; let vel_i = { x: velocity.x, y: velocity.y }; for (let j = 0; j < i; j++) { pos_i.x += dt * a[i][j] * k[j][0].x; pos_i.y += dt * a[i][j] * k[j][0].y; vel_i.x += dt * a[i][j] * k[j][1].x; vel_i.y += dt * a[i][j] * k[j][1].y; } k[i][0] = vel_i; k[i][1] = accelerationFn(pos_i, vel_i, params); } let newPosition = { x: position.x, y: position.y }; let newVelocity = { x: velocity.x, y: velocity.y }; let newPosition_star = { x: position.x, y: position.y }; let newVelocity_star = { x: velocity.x, y: velocity.y }; for (let i = 0; i < 7; i++) { newPosition.x += dt * b[i] * k[i][0].x; newPosition.y += dt * b[i] * k[i][0].y; newVelocity.x += dt * b[i] * k[i][1].x; newVelocity.y += dt * b[i] * k[i][1].y; newPosition_star.x += dt * b_star[i] * k[i][0].x; newPosition_star.y += dt * b_star[i] * k[i][0].y; newVelocity_star.x += dt * b_star[i] * k[i][1].x; newVelocity_star.y += dt * b_star[i] * k[i][1].y; } // Error estimation (for adaptive step-size, not fully implemented here yet) // const errorPos = { x: newPosition.x - newPosition_star.x, y: newPosition.y - newPosition_star.y }; // const errorVel = { x: newVelocity.x - newVelocity_star.x, y: newVelocity.y - newVelocity_star.y }; // const error = Math.sqrt(errorPos.x * errorPos.x + errorPos.y * errorPos.y + errorVel.x * errorVel.x + errorVel.y * errorVel.y); return { position: newPosition, velocity: newVelocity }; } };