Questions about accessing index of Gekko array in Python - python

I'm currently having some issue regarding accessing indices in Gekko array. I'm trying to convert following code:
m = GEKKO()
s42 = m.Array(m.Var, 8)
s44 = m.Array(m.Var, 8)
m.Equation(s42[0] == p42_raw[0] / (n34 + n44) * (n34 * (p34_norm[0] + p34_norm[4]) + n44 * (s44[0] + s44[4]) / np.sum(s44)))
m.Equation(s42[1] == p42_raw[1] / (n34 + n44) * (n34 * (p34_norm[0] + p34_norm[4]) + n44 * (s44[0] + s44[4]) / np.sum(s44)))
m.Equation(s42[2] == p42_raw[2] / (n34 + n44) * (n34 * (p34_norm[1] + p34_norm[5]) + n44 * (s44[1] + s44[5]) / np.sum(s44)))
m.Equation(s42[3] == p42_raw[3] / (n34 + n44) * (n34 * (p34_norm[1] + p34_norm[5]) + n44 * (s44[1] + s44[5]) / np.sum(s44)))
m.Equation(s42[4] == p42_raw[4] / (n34 + n44) * (n34 * (p34_norm[2] + p34_norm[6]) + n44 * (s44[2] + s44[6]) / np.sum(s44)))
m.Equation(s42[5] == p42_raw[5] / (n34 + n44) * (n34 * (p34_norm[2] + p34_norm[6]) + n44 * (s44[2] + s44[6]) / np.sum(s44)))
m.Equation(s42[6] == p42_raw[6] / (n34 + n44) * (n34 * (p34_norm[3] + p34_norm[7]) + n44 * (s44[3] + s44[7]) / np.sum(s44)))
m.Equation(s42[7] == p42_raw[7] / (n34 + n44) * (n34 * (p34_norm[3] + p34_norm[7]) + n44 * (s44[3] + s44[7]) / np.sum(s44)))
...
to something shorter like below:
m.Equation([s42[i] for i in range(8)] ==
[p42_raw[i] / (n34 + n44) * (n34 * (p34_norm[np.uint(i / 2)] + p34_norm[np.uint(4 + i / 2)])
+ n44 * (s44[np.uint(i / 2)] + s44[np.uint(4 + i / 2)]) / sum(s44))
for i in range(8)])
but currently getting following errors:
File "/Users/tomino/opt/anaconda3/lib/python3.7/site-packages/gekko/gk_operators.py", line 144, in __len__
return len(self.value)
TypeError: object of type 'int' has no len()
I've been stuck in this problem for a while but cannot find any suitable solution yet. Can anyone please help me resolving this issue?

Isn't this what you're after?
for i in range(8):
h = i // 2
m.Equation(s42[i] == p42_raw[i] / (n34 + n44) * (n34 * (p34_norm[h] + p34_norm[h+4]) + n44 * (s44[h] + s44[h+4]) / np.sum(s44)))

Related

How i can shorten code for neural-network?

I wrote a neural network and after that, i want to write neural network bigger than it, and i dont want to write too big code
input[0] = (player_x - Game_logic.block_1x)
input[1] = (player_y - Game_logic.block_1y)
input[2] = (player_x - Game_logic.block_2x)
input[3] = (player_y - Game_logic.block_2y)
input[4] = (player_x - Game_logic.block_3x)
input[5] = (player_y - Game_logic.block_3y)
snk[0] = (((input[0] * weights[0])/10) + ((input[1] * weights[1])/10) + ((input[2] * weights[2])/10) + ((input[3] * weights[3])/10) + ((input[4] * weights[4])/10) + ((input[5] * weights[5])/10) +1)
snk[1] = (((input[0] * weights[6])/10) + ((input[1] * weights[7])/10) + ((input[2] * weights[8])/10) + ((input[3] * weights[9])/10) + ((input[4] * weights[10])/10) + ((input[5] * weights[11])/10) +1)
snk[2] = (((input[0] * weights[12])/10) + ((input[1] * weights[13])/10) + ((input[2] * weights[14])/10) + ((input[3] * weights[15])/10) + ((input[4] * weights[16])/10) + ((input[5] * weights[17])/10) +1)
snk[3] = (((input[0] * weights[18])/10) + ((input[1] * weights[19])/10) + ((input[2] * weights[20])/10) + ((input[3] * weights[21])/10) + ((input[4] * weights[22])/10) + ((input[5] * weights[23])/10) +1)
snk[4] = (((input[0] * weights[24])/10) + ((input[1] * weights[25])/10) + ((input[2] * weights[26])/10) + ((input[3] * weights[27])/10) + ((input[4] * weights[28])/10) + ((input[5] * weights[29])/10) +1)
output[0] = ((snake_layer_1[0] * weights[30])/10) + ((snake_layer_1[1] * weights[31])/10) + ((snake_layer_1[2] * weights[32])/10) + ((snake_layer_1[3] * weights[33])/10) + ((snake_layer_1[4] * weights[34])/10)
output[1] = ((snake_layer_1[0] * weights[35])/10) + ((snake_layer_1[1] * weights[36])/10) + ((snake_layer_1[2] * weights[37])/10) + ((snake_layer_1[3] * weights[38])/10) + ((snake_layer_1[4] * weights[39])/10)
output[3] = ((snake_layer_1[0] * weights[40])/10) + ((snake_layer_1[1] * weights[41])/10) + ((snake_layer_1[2] * weights[42])/10) + ((snake_layer_1[3] * weights[43])/10) + ((snake_layer_1[4] * weights[44])/10)

How to print following empty up side down pattern

I am trying to print this following pattern , But not able to frame logic
My code :
for i in range(1,row+1):
if i == 1:
print(row * '* ')
elif i<row:
print( '* ' + ((row - 3) * 2) * ' ' + '*')
row = row - 1
else:
print('*')
Expected output :
* * * * * * * *
* *
* *
* *
* *
* *
* *
*
But my code gives me abnormal output :
* * * * * * * *
* *
* *
* *
*
*
*
*
#stacker's answer is nifty but mathematically a little overkill. This should do the trick just as well:
row = 8
print(row * '* ')
for i in range(1,row - 1):
rowlength = (row - i) * 2 - 3
print('*', end='')
print(rowlength * ' ', end='')
print('*')
print('*')
import math
row = 8;
for i in range(1,row+1):
if i == 1:
print(row * '* ')
elif i<(row * row) / (math.pi / math.sqrt(7)):
print( '* ' + ((row - 3) * 2) * ' ' + '*')
row = row - 1
else:
print('*')
Output:
* * * * * * * *
* *
* *
* *
* *
* *
* *
*
row=10
for i in range(1,row):
if i == 1:
print(row * '* ')
elif i < row:
print('* ' + (row-2)*2 * ' ' + '*')
row = row-1
elif i > row-2:
print('* ' + (row - 2) * 2 * ' ' + '*')
row = row - 1
Output:
* * * * * * * * * *
* *
* *
* *
* *
* *
* *
* *
* *
Process finished with exit code 0
Hope this helps

Understanding timesteps in scipy.integrate.odeint

I am trying to solve a PDE using odeint and the method of lines. My code is definitely wrong - and I'm trying to figure out where it is going wrong.
I am calling the ode solver using odeint(odefunc,y0,tspan) where tspan = np.linspace(0.0, 0.5, 5) & y0 = 1.0*np.ones(3).
I tried printing t within odefunc and am confused by the output. Despite the fact that I am solving up to t=0.5, the last t-value to print is 0.015081203121127767. The number of outputs matches tspan, but I cannot see how it could possibly be solving up to t = 0.5 when the last time in the de function is 0.015. What am I missing?
My DE is time dependent - so this is making it very hard to figure out where things are going wrong because I don't seem to be seeing the times where everything fails.
ETA - this is failing, but running this without some of the irrelevant stuff I am getting the warning ODEintWarning: Excess work done on this call (perhaps wrong Dfun type). Run with full_output = 1 to get quantitative information., which I'm assuming is part of the issue - but it doesn't appear to be halting the code.
MWE
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
import math
import sys
plt.interactive(False)
sigma = 2320
rho = 1000
gravity = 9.81 # [m/s^2]
g = gravity*3600*3600 # [m/hour^2]
S = 0.01
settlingVelocity = 0.02 # [m/s]
ws = settlingVelocity*3600 # [m/hour]
n = 0.04 # [SI]
J = 400 # [Ws/m]
k = 0.02
Cstar = 0.2 * sigma # [kg/m^3]
W = 2 # [m]
D0 = 1.2
Lw = 20
L = 100
tend = 0.5 # in hours
tspan = np.linspace(0.0, tend, 5)
def d(t): # metres
if t < 50: # hours
return 0.5
else:
return 0.05
def Q(t):
return 3600 * (math.sqrt(S)/n)*((W*d(t))**(5/3))/((2*d(t) + W)**(2/3))
def h(t):
return d(t)/2
def beta(t):
return (sigma - rho) * g * h(t)/sigma
def Omega(t):
return rho * g * S * Q(t) # [W/m]
def PsiTime(t):
return rho * g * Q(t) * (D0 - d(t))/(Lw)
N = 10
X = np.linspace(0, L, N)
delX = L/ (N-1)
def odefunc(y, t):
def zetaEh(t):
return k * (PsiTime(t) + Omega(t)) / (J + beta(t))
def zetaEW(t):
return (2*d(t)/(W + 2*d(t))) * k * Omega(t)/(J + beta(t))
def zetaR(t):
return (W/(W + 2*d(t))) * k*Omega(t)/(beta(t))
def zetaEF(t,i):
return (W/(W + 2*d(t))) * k * Omega(t) / (J + beta(t))
C = y[:N]
M = y[N:]
print("time: ", t)
dCdt = np.zeros(X.shape)
dMdt = np.zeros(X.shape)
dCdt[0] = ( # forward difference for dCdx
-Q(t) / (W*d(t)) * (C[1] - C[0]) / delX
+ (zetaEh(t) / (W * d(t))) * ((Cstar - C[0]) / Cstar)
- (ws * C[0] * (beta(t))) / (d(t) * (J + beta(t)))
)
dMdt[0] = 0
# gully channel
for i in range (1, N-1): # central difference
if M[i] + W *C[i] * ws - zetaR(t) * (Cstar - C[i]) / Cstar < 0:
reMass = M[i] + W * C[i] * ws
dCdt[i] = (
-Q(t) / (W*d(t)) * (C[i+1] - C[i - 1]) / (2*delX)
+ 1 / (W * d(t)) * ((zetaEW(t) + zetaEF(t,i)) * (Cstar - C[i]) / Cstar
+ reMass * (1 - (beta(t))/ (J + beta(t))))
- C[i] * ws/d(t)
)
dMdt[i] = -M[i]
else:
dCdt[i] = (
-Q(t) / (W*d(t)) * (C[i+1] - C[i - 1]) / (2*delX)
+ 1 / (W * d(t)) * (zetaEW(t) + zetaR(t)) * (Cstar - C[i]) / Cstar
- C[i] * ws / d(t)
)
dMdt[i] = W * C[i] * ws - zetaR(t) * (Cstar - C[i]) / Cstar
# Final node - backward difference
if M[N-1] + W * C[N-1] * ws - zetaR(t) * (Cstar - C[N-1]) / Cstar < 0:
reMass = M[N-1] + W * C[N-1] * ws
dCdt[N-1] = (
-Q(t) / (W * d(t)) * (C[N-1] - C[N-2]) / delX
+ 1 / (W * d(t)) * ((zetaEW(t) + zetaEF(t, i)) * (Cstar - C[N-1]) / Cstar
+ reMass * (1 - (beta(t)) / (J + beta(t))))
- C[i] * ws / d(t)
)
dMdt[N-1] = -M[N-1]
else:
dCdt[N-1] = (
-Q(t) / (W * d(t)) * (C[N-2] - C[N - 1]) / delX
+ 1 / (W * d(t)) * (zetaEW(t) + zetaR(t)) * (Cstar - C[N-1]) / Cstar
- C[N-1] * ws / d(t)
)
dMdt[N-1] = W * C[N-1] * ws - zetaR(t) * (Cstar - C[N-1]) / Cstar
dydt = np.ravel([dCdt, dMdt])
return dydt
init_C = 0.0 * np.ones(X.shape)
init_M = 0.0 * np.ones(X.shape)
init= np.ravel([init_C, init_M])
sol = odeint(odefunc, init, tspan)
conc = sol[:, :N]

How to Check if Jacobian is Correct

I am happily integrating a simple ODE with scipy.odeint. This is my integration fuction:
def f(self, x, t_0):
h = x[0:3]
f = x[3:6]
der = []
der.append((self.q_0 - f[0] * self.u[0] * self.k[0] * numpy.sign(h[0] - h[1]) * numpy.sqrt(abs(h[0] - h[1]))) / self.A[0])
der.append((f[0] * self.u[0] * self.k[0] * numpy.sign(h[0] - h[1]) * numpy.sqrt(abs(h[0] - h[1])) -
f[1] * self.u[1] * self.k[1] * numpy.sign(h[1]) * numpy.sqrt(abs(h[1]))) / self.A[1])
der.append((f[1] * self.u[1] * self.k[1] * numpy.sign(h[1] - h[2]) * numpy.sqrt(abs(h[1] - h[2])) -
f[2] * self.u[2] * self.k[2] * numpy.sign(h[2]) * numpy.sqrt(abs(h[2]))) / self.A[2])
der.append(0)
der.append(0)
der.append(0)
return numpy.array(der)
Everything works fine if I call scipy.integrate.odeint except I decided to provide the Jacobian so I can do the integration faster. This is the Jacobian which I figured out by hand:
def F(self, x, t_0):
h = x[0:3]
f = x[3:6]
u = self.u
k = self.k
A = self.A
result = numpy.zeros((6, 6))
sqrt_diff_h0_h1 = numpy.sign(h[0] - h[1]) * numpy.sqrt(abs(h[0] - h[1]))
sqrt_diff_h1_h2 = numpy.sign(h[1] - h[2]) * numpy.sqrt(abs(h[1] - h[2]))
sqrt_diff_h1 = numpy.sign(h[1]) * numpy.sqrt(abs(h[1]))
sqrt_diff_h2 = numpy.sign(h[2]) * numpy.sqrt(abs(h[2]))
result[0][0] = -(u[0] * f[0] * k[0]) / (2 * A[0] * sqrt_diff_h0_h1)
result[0][1] = (u[0] * f[0] * k[0]) / (2 * A[0] * sqrt_diff_h0_h1)
result[0][3] = -(u[0] * k[0] * sqrt_diff_h0_h1) / A[0]
result[1][0] = (u[0] * f[0] * k[0]) / (2 * A[1] * sqrt_diff_h0_h1)
result[1][1] = -((u[0] * f[0] * k[0] * A[1]) / (2 * sqrt_diff_h0_h1)) - \
((u[1] * f[1] * k[1] * A[1]) / (2 * sqrt_diff_h1))
result[1][3] = (u[0] * k[0] * sqrt_diff_h0_h1) / A[1]
result[1][4] = -(u[1] * k[1] * sqrt_diff_h1) / A[1]
result[2][1] = (u[1] * f[1] * k[1]) / (2 * A[2] * sqrt_diff_h1_h2)
result[2][2] = -((u[1] * f[1] * k[1] * A[2]) / (2 * sqrt_diff_h1_h2)) - \
((u[2] * f[2] * k[2] * A[2]) / (2 * sqrt_diff_h2))
result[2][4] = (u[1] * k[1] * sqrt_diff_h1_h2) / A[2]
result[2][5] = -(u[2] * k[2] * sqrt_diff_h2) / A[2]
return result
If I supply F to scipy.odeint.integrate, it actually takes more time. This, of course, doesn't mean much but I am wondering how to determine if the Jacobian is correct? I need it for other purposes of linearization.

Satellite position computation using Runge-Kutta 4

my issue is related to Runge-Kutta 4 (RK4) method and the correct iteration steps required for the state vector of an orbiting satellite.
The below code (in Python) describes the motion based on the description as per this link (http://www.navipedia.net/index.php/GLONASS_Satellite_Coordinates_Computation):
if total_step_number != 0:
for i in range(1, total_step_number+1):
#Calculate k1
k1[0] = (-cs.GM_GLONASS * XYZ[0] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ[0] * (1 - (5*(XYZ[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[0] + (cs.OMEGAE_DOT**2 * XYZ[0]) + (2 * cs.OMEGAE_DOT * XYZDot[1])
k1[1] = (-cs.GM_GLONASS * XYZ[1] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ[1] * (1 - (5*(XYZ[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[1] + (cs.OMEGAE_DOT**2 * XYZ[1]) - (2 * cs.OMEGAE_DOT * XYZDot[0])
k1[2] = (-cs.GM_GLONASS * XYZ[2] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ[2] * (3 - (5*(XYZ[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[2]
#Intermediate step to bridge k1 to k2
XYZ2[0] = XYZ[0] + (XYZDot[0] * h / 2) + (k1[0] * h**2 / 8)
XYZDot2[0] = XYZDot[0] + (k1[0] * h / 2)
XYZ2[1] = XYZ[1] + (XYZDot[1] * h / 2) + (k1[1] * h**2 / 8)
XYZDot2[1] = XYZDot[1] + (k1[1] * h / 2)
XYZ2[2] = XYZ[2] + (XYZDot[2] * h / 2) + (k1[2] * h**2 / 8)
XYZDot2[2] = XYZDot[2] + (k1[2] * h / 2)
radius = np.sqrt((XYZ2[0]**2)+(XYZ2[1]**2)+(XYZ2[2]**2))
....
There is more code however I want to limit what I show for now since it's the intermediate steps I'm most interested in resolving. Basically, for those familiar with state vectors and using RK4, you can see that the position and velocity is updated in the intermediate step, but not the acceleration. My question is related to the calculation required in order to update too the acceleration. It would begin:
XYZDDot[0] = ...
XYZDDot[1] = ...
XYZDDot[2] = ...
...but what exactly comes after is not very clear. Any advice welcome.
Below is the full code:
for j in h_step_values:
h = j
if h > 0:
one_way_iteration_steps = one_way_iteration_steps -1
elif h < 0:
one_way_iteration_steps = one_way_iteration_steps +1
XYZ = initial_XYZ
#if total_step_number != 0:
for i in range(0, one_way_iteration_steps):
#Calculate k1
k1[0] = (-cs.GM_GLONASS * XYZ[0] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ[0] * (1 - (5*(XYZ[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[0] + (cs.OMEGAE_DOT**2 * XYZ[0]) + (2 * cs.OMEGAE_DOT * XYZDot[1])
k1[1] = (-cs.GM_GLONASS * XYZ[1] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ[1] * (1 - (5*(XYZ[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[1] + (cs.OMEGAE_DOT**2 * XYZ[1]) - (2 * cs.OMEGAE_DOT * XYZDot[0])
k1[2] = (-cs.GM_GLONASS * XYZ[2] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ[2] * (3 - (5*(XYZ[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[2]
#Intermediate step to bridge k1 to k2
XYZ2[0] = XYZ[0] + (XYZDot[0] * h / 2) + (k1[0] * h**2 / 8)
XYZDot2[0] = XYZDot[0] + (k1[0] * h / 2)
XYZDDot2[0] = XYZDDot[0] + (k1[0] * h / 2)
XYZ2[1] = XYZ[1] + (XYZDot[1] * h / 2) + (k1[1] * h**2 / 8)
XYZDot2[1] = XYZDot[1] + (k1[1] * h / 2)
XYZ2[2] = XYZ[2] + (XYZDot[2] * h / 2) + (k1[2] * h**2 / 8)
XYZDot2[2] = XYZDot[2] + (k1[2] * h / 2)
radius = np.sqrt((XYZ2[0]**2)+(XYZ2[1]**2)+(XYZ2[2]**2))
#Calculate k2
k2[0] = (-cs.GM_GLONASS * XYZ2[0] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[0] * (1 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[0] + (cs.OMEGAE_DOT**2 * XYZ2[0]) + (2 * cs.OMEGAE_DOT * XYZDot2[1])
k2[1] = (-cs.GM_GLONASS * XYZ2[1] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[1] * (1 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[1] + (cs.OMEGAE_DOT**2 * XYZ2[1]) - (2 * cs.OMEGAE_DOT * XYZDot2[0])
k2[2] = (-cs.GM_GLONASS * XYZ2[2] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[2] * (3 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[2]
#Intermediate step to bridge k2 to k3
XYZ2[0] = XYZ[0] + (XYZDot[0] * h / 2) + (k2[0] * h**2 / 8)
XYZDot2[0] = XYZDot[0] + (k2[0] * h / 2)
XYZ2[1] = XYZ[1] + (XYZDot[1] * h / 2) + (k2[1] * h**2 / 8)
XYZDot2[1] = XYZDot[1] + (k2[1] * h / 2)
XYZ2[2] = XYZ[2] + (XYZDot[2] * h / 2) + (k2[2] * h**2 / 8)
XYZDot2[2] = XYZDot[2] + (k2[2] * h / 2)
radius = np.sqrt((XYZ2[0]**2)+(XYZ2[1]**2)+(XYZ2[2]**2))
#Calculate k3
k3[0] = (-cs.GM_GLONASS * XYZ2[0] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[0] * (1 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[0] + (cs.OMEGAE_DOT**2 * XYZ2[0]) + (2 * cs.OMEGAE_DOT * XYZDot2[1])
k3[1] = (-cs.GM_GLONASS * XYZ2[1] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[1] * (1 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[1] + (cs.OMEGAE_DOT**2 * XYZ2[1]) - (2 * cs.OMEGAE_DOT * XYZDot2[0])
k3[2] = (-cs.GM_GLONASS * XYZ2[2] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[2] * (3 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[2]
#Intermediate step to bridge k3 to k4
XYZ2[0] = XYZ[0] + (XYZDot[0] * h) + (k3[0] * h**2 / 2)
XYZDot2[0] = XYZDot[0] + (k3[0] * h)
XYZ2[1] = XYZ[1] + (XYZDot[1] * h) + (k3[1] * h**2 / 2)
XYZDot2[1] = XYZDot[1] + (k3[1] * h)
XYZ2[2] = XYZ[2] + (XYZDot[2] * h) + (k3[2] * h**2 / 2)
XYZDot2[2] = XYZDot[2] + (k3[2] * h)
radius = np.sqrt((XYZ2[0]**2)+(XYZ2[1]**2)+(XYZ2[2]**2))
#Calculate k4
k4[0] = (-cs.GM_GLONASS * XYZ2[0] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[0] * (1 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[0] + (cs.OMEGAE_DOT**2 * XYZ2[0]) + (2 * cs.OMEGAE_DOT * XYZDot2[1])
k4[1] = (-cs.GM_GLONASS * XYZ2[1] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[1] * (1 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[1] + (cs.OMEGAE_DOT**2 * XYZ2[1]) - (2 * cs.OMEGAE_DOT * XYZDot2[0])
k4[2] = (-cs.GM_GLONASS * XYZ2[2] / radius**3) \
+ ((3/2) * cs.C_20 * cs.GM_GLONASS * cs.SEMI_MAJOR_AXIS_GLONASS**2 * XYZ2[2] * (3 - (5*(XYZ2[2]**2) / (radius**2))) / radius**5) \
+ XYZDDot[2]
for p in range(3):
XYZ[p] = XYZ[p] + XYZDot[p] * h + h**2 * ((k1[p] + 2*k2[p] + 2*k3[p] + k4[p]) / 12)
XYZDot[p] = XYZDot[p] + (h * (k1[p] + 2*k2[p] + 2*k3[p] + k4[p]) / 6)
radius = np.sqrt((XYZ[0])**2 + (XYZ[0])**2 + (XYZ[0])**2)
The equation you are solving is of the type
ddot x = a(x)
where a(x) is the acceleration which is computed in your k1 computation. Indeed, the first order system would be
dot v = a(x)
dot x = v
The RK4 implementation thus starts with
k1 = a(x)
l1 = v
k2 = a(x+l1*h/2) = a(x+v*h/2)
l2 = v+k1*h/2
etc. The use of the l1,l2,... seems implicit in the code, inserting these linear combinations directly where they occur.
In short, you are not missing the acceleration computation, it is the main part of the code fragment.
Update: (8/22) To come closer to the intention of the intermediate bridge steps, the abstract code should read ( with (* .. *) denoting comments or unnecessary computations)
k1 = a(x) (* l1 = v *)
x2 = x + v*h/2 (* v2 = v + k1*h/2 *)
k2 = a(x2) (* l2 = v2 *)
x3 (* = x + l2*h/2 *)
= x + v*h/2 + k1*h^2/4 (* v3 = v + k2*h/2 *)
k3 = a(x3) (* l3 = v3 *)
x4 (* = x + l3*h *)
= x + v*h + k2*h^2/2 (* v4 = v + k3*h *)
k4 = a(x4) (* l4 = v4 *)
delta_v = ( k1+2*(k2+k3)+k4 ) * h/6
delta_x (* = ( l1+2*(l2+l3)+l4 ) * h/6 *)
= v*h + (k1+k2+k3) * h^2/6

Categories

Resources