wave_equation2d.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. """Solve the wave equation using finite differences and the Euler method"""
  2. import numpy as np
  3. from scipy.ndimage import gaussian_filter
  4. from vedo import Plotter, Grid, Text2D
  5. N = 400 # grid resolution
  6. A, B = 5, 4 # box sides
  7. end = 5 # end time
  8. nframes = 150
  9. X, Y = np.mgrid[-A:A:N*1j, -B:B:N*1j]
  10. dx = X[1,0] - X[0,0]
  11. dt = 0.1 * dx
  12. time = np.arange(0, end, dt)
  13. m = int(len(time)/nframes)
  14. # initial condition (a ring-like wave)
  15. Z0 = np.ones_like(X)
  16. Z0[X**2+Y**2 < 1] = 0
  17. Z0[X**2+Y**2 > 2] = 0
  18. Z0 = gaussian_filter(Z0, sigma=4)
  19. Z1 = np.array(Z0)
  20. grid = Grid(s=(X[:,0], Y[0])).linewidth(0).lighting('glossy')
  21. txt = Text2D(font='Brachium', pos='bottom-left', bg='yellow5')
  22. cam = dict(
  23. pos=(5.715, -10.54, 12.72),
  24. focal_point=(0.1380, -0.7437, -0.5408),
  25. viewup=(-0.2242, 0.7363, 0.6384),
  26. distance=17.40,
  27. )
  28. plt = Plotter(axes=1, size=(1000,700), interactive=False)
  29. plt.show(grid, txt, __doc__, camera=cam)
  30. for i in range(nframes):
  31. # iterate m times before showing the frame
  32. for _ in range(m):
  33. ZC = Z1.copy()
  34. Z1[1:N-1, 1:N-1] = (
  35. 2*Z1[1:N-1, 1:N-1]
  36. - Z0[1:N-1, 1:N-1]
  37. + (dt/dx)**2
  38. * ( Z1[2:N, 1:N-1]
  39. + Z1[0:N-2, 1:N-1]
  40. + Z1[1:N-1, 0:N-2]
  41. + Z1[1:N-1, 2:N ]
  42. - 4*Z1[1:N-1, 1:N-1] )
  43. )
  44. Z0[:] = ZC[:]
  45. wave = Z1.ravel()
  46. txt.text(f"frame: {i}/{nframes}, height_max = {wave.max()}")
  47. grid.cmap("Blues", wave, vmin=-2, vmax=2)
  48. newpts = grid.points
  49. newpts[:,2] = wave
  50. grid.points = newpts # update the z component
  51. plt.render()
  52. plt.interactive()
  53. plt.close()