xplot = np.empty((nsteps, len(state)))


def wilber_derivs(s, t, params):
	''' Returns the derivative of the state vector '''
	m, I, k, delta, eps = params
	derivs = np.empty(len(s))
	derivs[0] = s[2]
	derivs[1] = s[3]
	derivs[2] = -k/m*s[0] - eps/(2*m)*s[1]
	derivs[3] = -delta/I*s[1] - eps/(2*I)*s[0]

	return derivs

for i in range(nsteps):
	state = rk4(state, time, tau, wilber_derivs, params)
	time += tau
	xplot[i, :] = np.copy(state)
	tplot[i] = time

plt.figure()
plt.plot(tplot, xplot[:, 0], '-', label='Longitudinal Displacement')
plt.xlabel('Time')
plt.ylabel('Longitudinal Displacement (m)')
plt.figure()
plt.plot(tplot, xplot[:, 1]*180/(np.pi), '-', label='Torsional Displacement')
plt.xlabel('Time')
plt.ylabel('Torsional Displacement (degrees)')

f = np.arange(nsteps)/(tau*nsteps)
x1 = xplot[:, 0]
def main(pos, param_r):
    state = pos
    r = param_r
    sigma = 10.
    b = 8. / 3.
    param = np.array([r, sigma, b])
    tau = 0.04
    err = 1e-3

    # loop over desired number of steps
    time = 0.
    nsteps = 500
    tplot = np.empty(nsteps)
    tauplot = np.empty(nsteps)
    diffplot = np.empty((3, nsteps))
    x1plot, y1plot, z1plot = np.empty(nsteps), np.empty(nsteps), np.empty(nsteps)
    x2plot, y2plot, z2plot = np.empty(nsteps), np.empty(nsteps), np.empty(nsteps)

    for istep in range(nsteps):
        # Record values for plotting
        x1, y1, z1 = state[0], state[1], state[2]
        x2, y2, z2 = state[3], state[4], state[5]
        tplot[istep] = time
        x1plot[istep] = x1
        y1plot[istep] = y1
        z1plot[istep] = z1
        x2plot[istep] = x2
        y2plot[istep] = y2
        z2plot[istep] = z2
        diffplot[0, istep] = np.abs(x2 - x1)
        diffplot[1, istep] = np.abs(y2 - y1)
        diffplot[2, istep] = np.abs(z2 - z1)

        total_diff = np.linalg.norm(diffplot, axis=0)

        if (istep + 1) % 50 == 0:
            print(f'Completed {istep} steps out of {nsteps}')

        # Find new state using adaptive Runge-Kutta
        state = rk4(state, time, tau, lorzrk, param)
        time += tau

    # Graph the time series x(t)
    fig = plt.figure()
    plt.plot(tplot, x1plot, 'g-')
    plt.plot(tplot, x2plot, 'r--')
    plt.xlabel('Time')
    plt.ylabel('x(t)')
    plt.title(f'Lorenz model time series, r = {r}')

    fig = plt.figure()
    plt.semilogy(tplot, diffplot[0, :])
    plt.xlabel('time')
    plt.ylabel('Absolute difference in x-coordinates')
    plt.grid(True, which='both')

    fig=plt.figure()
    plt.semilogy(tplot, total_diff)
    plt.xlabel('time')
    plt.ylabel('Norm difference')
    plt.grid(True, which='both')

    # Graph the x, y, z, phase space trajectory
    # Mark the location of the three stredy states
    x_ss, y_ss, z_ss = np.empty(3), np.empty(3), np.empty(3)
    x_ss[0] = 0.
    y_ss[0] = 0.
    z_ss[0] = 0.
    x_ss[1] = np.sqrt(b*(r-1))
    y_ss[1] = x_ss[1]
    z_ss[1] = r - 1
    x_ss[2] = -np.sqrt(b*(r-1))
    y_ss[2] = x_ss[2]
    z_ss[2] = r - 1

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.plot(x1plot, y1plot, z1plot, 'g-')
    ax.plot(x2plot, y2plot, z2plot, 'r--')
    ax.plot(x_ss, y_ss, z_ss, '*')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_zlabel('z')
    ax.set_title(f'Lorenz model phase space, r = {r}')
    print(state)
    plt.show()
x = np.array([0.3, 0., 0.])    # Initial positions (m)
v = np.array([0., 0., 0.])     # Initial velocities (m/s)
state = np.array([x[0], x[1], x[2], v[0], v[1], v[2]])
tau = 0.5                      # Time step (sec)
k_over_m = 1.                  # Spring constant divided by mass (N/(kg-m))

time = 0.
nsteps = 256
nprint = nsteps/8               # Number of steps between printing process
tplot = np.empty(nsteps)
xplot = np.empty((nsteps, 3))

### MAIN LOOP ###
for i in range(nsteps):
	# Use Runge-Kutta to find new mass displacements
	state = rk4(state, time, tau, sprrk, k_over_m)
	time += tau

	# Record positions for plotting
	tplot[i] = time
	xplot[i, :] = np.copy(state[:3])
	if i % nprint < 1:
		print(f'Finished {i} out of {nsteps} steps')

# Graph displacements
plt.figure()
plt.plot(tplot, xplot[:, 0], '-', label='Mass 1')
plt.plot(tplot, xplot[:, 1], '-', label='Mass 2')
plt.plot(tplot, xplot[:, 2], '-', label='Mass 3')
plt.title('Displacement of masses relative to rest position')
plt.xlabel('Time')
nsteps = 100
params = np.array([k1, k2, k3, k4, L1, L2, L3, L4, Lw, m1, m2, m3])
state = np.array([x1_0, x2_0, x3_0, v1_0, v2_0, v3_0])
xplot = np.empty((3, nsteps))
vplot = np.empty((3, nsteps))
tplot = np.empty(nsteps)

for i in range(nsteps):
    xplot[0, i] = state[0]
    xplot[1, i] = state[1]
    xplot[2, i] = state[2]
    vplot[0, i] = state[3]
    vplot[1, i] = state[4]
    vplot[2, i] = state[5]
    tplot[i] = time
    state = rk4(state, time, tau, params)
    time += tau

plt.figure(1)
plt.plot(tplot, xplot[0, :], 'b-', label='mass 1 position')
plt.plot(tplot, xplot[1, :], 'g--', label='mass 2 position')
plt.plot(tplot, xplot[2, :], 'r-.', label='mass 3 position')
plt.hlines(disp[0], tplot[0], tplot[-1], 'k', '--')
plt.hlines(disp[1], tplot[0], tplot[-1], 'k', '--')
plt.hlines(disp[2], tplot[0], tplot[-1], 'k', '--')
plt.xlabel('time (sec)')
plt.ylabel('mass position (m)')

plt.legend()

plt.figure(2)