def eulerstep(phi, qn, vn, Dt, M): """ This function takes one timestep across a set of equations dq/dt = v, dv/dt = -dphi(q)/dq using the Euler method, where q is a generalised spatial coordinate, v the velocity, t is time and phi is the potential. Parameters phi: A function defining the potential of the system. qn: The initial spatial coordinate at the start of the timestep. vn: The initial velocity at the start of the timestep. Dt: The length of the time step. M: The mass of the particle acting under a force. Returns The function returns the value of the spatial coordinate and velocity after taking a timestep of length Dt using the Euler method. """ qn1 = qn + Dt*vn # ensuring h is an exact machine represenable number (NRiC) # note using the symmetrized for of the numerical derivative (see NRiC) # may want to consider Richardson extrapolation for serious work, again see # NRiC pp. 231 # vn1 = vn - Dt*((phi(qn + h) - phi(qn - h))/(2*h)) useRidders = True if useRidders: dphidq, err = deriv.derivative(phi, qn, np.abs(qn1 - qn), useRidders) else: dphidq = deriv.derivative(phi, qn, np.abs(qn1 - qn), useRidders) vn1 = vn - (1/M)*Dt*dphidq return qn1, vn1
def rk4step(phi, qn, vn, Dt, M): """ This function takes one timestep across a set of equations dq/dt = v, M*dv/dt = -dphi(q)/dq using a fourth order Runge-Kutta method, where q is a generalised spatial coordinate, v the velocity, t is time and phi is the potential. Parameters phi: A function defining the potential of the system. qn: The initial spatial coordinate at the start of the timestep. vn: The initial velocity at the start of the timestep. Dt: The length of the time step. M: The mass of the particle acting under a force. Returns The function returns the value of the spatial coordinate and velocity after taking a timestep of length Dt using a fourth order Runge-Kutta method. """ # Z1 Q1 = qn V1 = vn dphidQ1, err = deriv.derivative(phi, Q1, np.abs(Dt*vn)) # Z2 Q2 = qn + 0.5*Dt*V1 V2 = vn - 0.5*Dt*1.0/M*dphidQ1 dphidQ2, err = deriv.derivative(phi, Q2, np.abs(Dt*vn)) # Z3 Q3 = qn + 0.5*Dt*V2 V3 = vn - 0.5*Dt*1.0/M*dphidQ2 dphidQ3, err = deriv.derivative(phi, Q3, np.abs(Dt*vn)) # Z4 Q4 = qn + Dt*V3 V4 = vn - Dt*1.0/M*dphidQ3 dphidQ4, err = deriv.derivative(phi, Q4, np.abs(Dt*vn)) # final step qn1 = qn + Dt/6.0*(V1 + 2.0*V2 + 2.0*V3 + V4) vn1 = vn - Dt/(6.0*M)*(dphidQ1 + 2.0*dphidQ2 + 2.0*dphidQ3 + dphidQ4) return qn1, vn1
def eulerBstep(phi, qn, vn, Dt, M): """ This function takes one timestep across a set of equations dq/dt = v, M*dv/dt = -dphi(q)/dq using the Euler B method, where q is a generalised spatial coordinate, v the velocity, t is time and phi is the potential. Parameters phi: A function defining the potential of the system. qn: The initial spatial coordinate at the start of the timestep. vn: The initial velocity at the start of the timestep. Dt: The length of the time step. M: The mass of the particle acting under a force. Returns The function returns the value of the spatial coordinate and velocity after taking a timestep of length Dt using the Euler B method. """ dphidq, err = deriv.derivative(phi, qn, np.abs(Dt*vn)) vn1 = vn + (1/M)*Dt*dphidq qn1 = qn - Dt*vn1 return qn1, vn1
e2norm = np.zeros(N + 1, dtype = np.float64) energyError = np.zeros(N + 1, dtype = np.float64) phi = np.zeros(N + 1, dtype = np.float64) dphidq_analytic = np.zeros(N + 1, dtype = np.float64) dphidq_numeric = np.zeros(N + 1, dtype = np.float64) # initial conditions q[0] = 1.9 v[0] = -0.0001 energyConst = 0.5*v[0] + LJ(q[0]) # calcualte phase space for ii in range(0, N): t[ii + 1] = t[ii] + Dt q[ii + 1], v[ii + 1] = step.eulerstep(LJ, q[ii], v[ii], Dt, M) dphidq = -deriv.derivative(LJ, q[ii], np.abs(q[ii + 1] - q[ii]), False)[0] d2phidq2 = -deriv.derivative(LJdiff, q[ii], np.abs(q[ii + 1] - q[ii]), False)[0] a[ii] = np.max([1, d2phidq2]) E = 0.5*v[ii]**2 + LJ(q[ii]) b[ii] = 0.5*np.sqrt(dphidq**2 + 2*d2phidq2**2*(E - LJ(q[ii]))) energyError[ii] = E - energyConst # plot plt.figure(1) plt.clf() ax1 = plt.subplot2grid((3, 2), (0, 0), rowspan = 3) ax1.plot(q, v) plt.title('Phase Plot') plt.xlabel('Generalised Coordainte, $q$') plt.ylabel('Generalised Velocity, $v(q)$') plt.axis([0.5, 2.5, -0.5, 0.5])