Code:
@name Runge-Kutta Test #2
@inputs
@outputs R:array
@persist T Tick
#constants
@persist G N Skip
@trigger
if(first()|duped()) {
runOnTick(1)
Skip = 3
Tick = 1
G = 6.67259e-10
R:clear()
N=5 #5 entries per body
#"Sun"
R[1,number]=1.989e+16
R[2,vector]=vec(70,70,70) #size
R[3,vector]=vec(255,255,0) #color
R[4,vector]=vec(0,0,0) #initial position
R[5,vector]=vec(0,-3.6,0) #initial velocity
#"Earth"
R[6,number]=5.975e+14
R[7,vector]=vec(20,20,20)
R[8,vector]=vec(0,255,255)
R[9,vector]=vec(1000,0,0)
R[10,vector]=vec(0,120,0)
#"Moon"
R[11,number]=7e12
R[12,vector]=vec(10,10,10)
R[13,vector]=vec(100,100,100)
R[14,vector]=vec(1050,0,0)
R[15,vector]=vec(0,195,30)
#"Mercury"
R[16,number]=7e10
R[17,vector]=vec(8,8,8)
R[18,vector]=vec(100,100,0)
R[19,vector]=vec(0,200,0)
R[20,vector]=vec(-260,0,40)
#"Black Hole"
#R[21,number]=1e19
#R[22,vector]=vec(120,120,120)
#R[23,vector]=vec(0,0,0)
#R[24,vector]=vec(0,-10000,10000)
#R[25,vector]=vec(0,5,5)
T = curtime()
for(I=1,R:count()/N) {
holoCreate(I)
holoModel(I,"hqicosphere2")
holoScaleUnits(I,R[I*N-3,vector])
holoColor(I,R[I*N-2,vector])
holoPos(I,entity():pos()+vec(0,0,300)+R[I*N-1,vector])
holoEntity(I):setTrails(30,30,2,"trails/laser",R[I*N-2,vector],500)
}
}
elseif(Tick == 0) {
Tick++
if(Tick>=Skip) {Tick = 0}
#Simulation
T = curtime()
P1 = array()
for(I=1,R:count()/N) {
P1:pushVector($T*R[I*N,vector])
P1V = vec()
for(J=1,R:count()/N)
{
if(J!=I) {
DX1 = R[J*N-1,vector]-R[I*N-1,vector]
P1V += $T*G*R[J*N-4,number]/(DX1:length())^3*DX1
}
}
P1:pushVector(P1V)
}
P2 = array()
for(I=1,R:count()/N) {
P2:pushVector($T*(R[I*N,vector]+P1[I*2,vector]/2))
P2V = vec()
for(J=1,R:count()/N)
{
if(J!=I) {
DX2 = (R[J*N-1,vector]+P1[J*2-1,vector]/2)-(R[I*N-1,vector]+P1[I*2-1,vector]/2)
P2V += $T*G*R[J*N-4,number]/(DX2:length())^3*DX2
}
}
P2:pushVector(P2V)
}
P3 = array()
for(I=1,R:count()/N) {
P3:pushVector($T*(R[I*N,vector]+P2[I*2,vector]/2))
P3V = vec()
for(J=1,R:count()/N)
{
if(J!=I) {
DX3 = (R[J*N-1,vector]+P2[J*2-1,vector]/2)-(R[I*N-1,vector]+P2[I*2-1,vector]/2)
P3V += $T*G*R[J*N-4,number]/(DX3:length())^3*DX3
}
}
P3:pushVector(P3V)
}
P4 = array()
for(I=1,R:count()/N) {
P4:pushVector($T*(R[I*N,vector]+P3[I*2,vector]))
P4V = vec()
for(J=1,R:count()/N)
{
if(J!=I) {
DX4 = (R[J*N-1,vector]+P3[J*2-1,vector])-(R[I*N-1,vector]+P3[I*2-1,vector])
P4V += $T*G*R[J*N-4,number]/(DX4:length())^3*DX4
}
}
P4:pushVector(P4V)
}
for(I=1,R:count()/N) {
PX = (P1[I*2-1,vector]+P2[I*2-1,vector]*2+P3[I*2-1,vector]*2+P4[I*2-1,vector])/6
PV = (P1[I*2,vector]+P2[I*2,vector]*2+P3[I*2,vector]*2+P4[I*2,vector])/6
R[I*N-1,vector] = R[I*N-1,vector]+PX
R[I*N,vector] = R[I*N,vector]+PV
holoPos(I,entity():pos()+vec(0,0,300)+R[I*N-1,vector])
}
}
else {
Tick++
if(Tick>=Skip) { Tick = 0 }
}
The RK4 simulation part starts at the "#Simulation" comment. It's possible that it could be optimized (multiple for-loops nested in a for-loop), but I'm too sleepy to try it today
Bookmarks