test_elastic_pendulum.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. """Simulate an elastic pendulum.
  2. The trail is colored according to the velocity."""
  3. import numpy as np
  4. from scipy.integrate import solve_ivp
  5. import matplotlib.pyplot as plt
  6. from vedo import Plotter, Axes, Sphere, Spring, Image, mag, sin, cos
  7. from vedo.addons import ProgressBarWidget
  8. a = 2.0 # length of the pendulum
  9. m = 0.5 # mass
  10. k = 10.0 # constant of the spring
  11. g = 9.81 # gravitational constant
  12. # Define the system of ODEs
  13. def system(t, z):
  14. x, dx_dt, y, dy_dt = z # z = [x, x', y, y']
  15. dxdot_dt = (a+x) * dy_dt**2 - k/m * x + g * cos(y)
  16. dydot_dt = -2/(a+x) * dx_dt * dy_dt - g/(a+x) * sin(y)
  17. return [dx_dt, dxdot_dt, dy_dt, dydot_dt]
  18. # Initial conditions: x(0), x'(0), y(0), y'(0)
  19. initial_conditions = [0.0, 0.0, 0.4, 0.0]
  20. # Time span for the solution
  21. t_span = (0, 12)
  22. t_eval = np.linspace(t_span[0], t_span[1], 500) # range to evaluate solution
  23. # Solve the system numerically
  24. solution = solve_ivp(system, t_span, initial_conditions, t_eval=t_eval)
  25. t_values = solution.t
  26. elong_values = solution.y[0]
  27. theta_values = solution.y[2]
  28. # Plot the results using matplotlib as a graph
  29. fig = plt.figure()
  30. plt.plot(t_values, elong_values, label="elongation(t)")
  31. plt.plot(t_values, theta_values, label="angle(t)")
  32. plt.xlabel("Time")
  33. plt.legend()
  34. # Animate the system using the solution of the ODE
  35. plotter = Plotter(bg="blackboard", bg2="blue1", interactive=False)
  36. pbw = ProgressBarWidget(len(t_values))
  37. axes = Axes(xrange=[-2, 2], yrange=[-a*2, 1], xygrid=0, xyframe_line=0, c="w")
  38. img = Image(fig).clone2d("top-right", size=0.5)
  39. sphere = Sphere(r=0.3, c="red5").add_trail(c="k5", lw=4)
  40. plotter.show(axes, sphere, img, pbw, __doc__)
  41. for elong, theta in zip(elong_values, theta_values):
  42. x = (a + elong) * sin(theta)
  43. y = -(a + elong) * cos(theta)
  44. spring = Spring([0, 0], [x, y])
  45. sphere.pos([x, y]).update_trail()
  46. # color the trail according to the lenght of each segment
  47. v = sphere.trail.vertices
  48. lenghts1 = np.array(v[1:])
  49. lenghts2 = np.array(v[:-1])
  50. lenghts = mag(lenghts1 - lenghts2) # lenght of each segment
  51. lenghts = np.append(lenghts, lenghts[-1])
  52. sphere.trail.cmap("Blues_r", lenghts, vmin=0, vmax=0.1)
  53. plotter.remove("Spring").add(spring).render()
  54. pbw.update() # update progress bar
  55. plotter.interactive()