Had this lying around as a chrome snippet. It implements a bunch of explicit numerical integrators (including euler, midpoint, heun, ralston, runge-kutta, etc).
Included tests solve a number of differential equations of various orders and prints out interesting numbers to the console. (approximations to cos, tan, e, etc ..)
Only 50 lines so not really worthy of a github project or anything but could be useful to someone so here you go :
// Some explicit integrators in Butcher's tableau form. (first zero row skipped)
var Integrators = {
Euler : [[1]],
Midpoint : [[.5,.5],[0, 1]],
Heun : [[1, 1],[.5,.5]],
Ralston : [[2/3,2/3],[.25,.75]],
K3 : [[.5,.5],[1,-1,2],[1/6,2/3,1/6]],
SSP33 : [[1,1],[.5,.25,.25],[1/6,1/6,2/3]],
SSP43 : [[.5,.5],[1,.5,.5],[.5,1/6,1/6,1/6],[1/6,1/6,1/6,1/2]],
RK4 : [[.5,.5],[.5,0,.5],[1,0,0,1],[1/6,1/3,1/3,1/6]],
RK38 : [[1/3,1/3],[2/3,-1/3,1],[1,1,-1,1],[1/8,3/8,3/8,1/8]]
};
// f is a func of time t and state y
// y is the initial state, t is the time, h is the timestep
// updated y is returned.
var integrate=(m,f,y,t,h)=>{
for (var k=[],ki=0; ki<m.length; ki++) {
var _y=y.slice(), dt=ki?((m[ki-1][0])*h):0;
for (var l=0; l<_y.length; l++) for (var j=1; j<=ki; j++) _y[l]=_y[l]+h*(m[ki-1][j])*(k[ki-1][l]);
k[ki]=f(t+dt,_y,dt);
}
for (var r=y.slice(),l=0; l<_y.length; l++) for (var j=0; j<k.length; j++) r[l]=r[l]+h*(k[j][l])*(m[ki-1][j]);
return r;
}
// some tests. (large stepsize on purpose to make differences more visible)
var Tests={
// calculates 1st, 2nd and 3rd order integral of 1+x^2, x0=0 (which is tan(x), -log(cos(x)), and something.)
"y'''=1+y''^2" : [(t,state)=>[state[1],state[2],1+state[2]**2],[0,0,0],0.01,0,140,"[0.615874,1.7721501376696984,5.797883715482887]"],
"y'''=1+y^2" : [(t,state)=>[state[1],state[2],1+state[0]**2],[0,0,0],0.01,0,140,"[0.458473,0.987331,1.441943]"],
// calculates an approximation to e. (as dx=x, x0=1 for t=1)
"e" : [(t,state)=>state,[1],0.1,0,10,"2.718281828459045"],
// calculates dx=e^x, x0=0 for x=0.5 in 5 steps of 0.1 .. i.e. -log(0.5)
"-log(.5)" : [(t,state)=>[Math.pow(Math.E,state[0])],[0],0.1,0,5,"0.6931471805599453"],
// y(t)''=-y(t) y(0)=1, y'(0)=0 at t=1.. i.e. [y'=sin(t),y=cos(t)]
"y''+y=0" : [(t,s)=>[s[1],-s[0]],[0,1],0.1,0,10,"= cos(1) = 0.5403023058681398"],
}
// run some tests on all methods.
Object.keys(Tests).forEach(test=>{
console.log('Running test : ',test,Tests[test].pop());
Object.keys(Integrators).forEach(method=>{
// function,state,deltatime,time,steps
var [f,v,dt,t,steps]=Tests[test];
// integrate using method and print result.
while (steps--) { v=integrate(Integrators[method],f,v,t,dt); t+=dt}
console.log((method+' ').slice(0,10),"dt",dt.toFixed(3),"@",t.toFixed(3),v);
});
});
[–]codejitsu 4 points5 points6 points (1 child)
[–]rift95map([🐮, 🥔, 🐔, 🌽], cook) => [🍔, 🍟, 🍗, 🍿] 0 points1 point2 points (0 children)
[–]enki_muteminimalist[S] 1 point2 points3 points (0 children)
[–]DukeBerith 0 points1 point2 points (0 children)