From: Andy D. <dou...@la...> - 2002-01-07 21:11:59
|
I've been considering using Vpython in a course to illustrate the propagation of wave packets with dispersion. The problem is it's just too slow. I'm hoping someone on this list with experience with the Numeric module might be able to help me speed it up. I think I'm spending way too much time explicitly looping over arrays. Sorry for the length of what follows, but it might be helpful to be specific: Here's my original naive attempt: #!/usr/bin/python # Show propagation of a wave pulse with dispersion. from visual.graph import * def w(k): "Dispersion relation w(k), gives v ~ 1/sqrt(k)." return sqrt(k) def yt(x,t): "Total wave obtained by superimposing sinusoids with k from 1 to 4." ytotal = 0.0 for k in arange(1.0, 4.0, 0.05): ytotal = ytotal + sin(k * x - w(k) * t) return ytotal gdisplay(xtitle='x', ytitle='ytotal', title='Wave', xmin = -10.0, ymin = -60.0, xmax =100.0, ymax = 60.0) pulse = gcurve() t = 0.0 # Make initial plot for x in arange(-10.0, 100.0, 0.2): pulse.plot(pos=(x, yt(x,t))) npts = len(pulse.gcurve.pos) while 1: t = t + 0.5 for n in range(npts): x = pulse.gcurve.pos[n][0] pulse.gcurve.pos[n][1] = yt(x, t) This would be rather simple for my students to follow (I hope!), but it is painfully slow. I was able to speed it up considerably by doing some obvious things: 1. Precomputing the dispersion relationship w(k) once and storing it 2. storing each set of points in a temporary array and updating the display only once per time step (instead of every x value) 3. Calling math.sin() directly instead of the overloaded Numeric sin() but it's still too slow. (Obviously, I can reduce the spatial and temporal resolution, but that's beside the point here.) To be specific, here's what I ended up with. #!/usr/bin/python # Show propagation of a wave pulse with dispersion. from visual.graph import * def w(k): "Dispersion relation w(k), gives v ~ 1/sqrt(k)." return sqrt(k) # Range of wavenumbers 'k' to include. ka = arange(1.0, 4.0, 0.05) wk = w(ka) nkmax = len(ka) def yt(x,t): "Total wave obtained by superimposing sinusoids with k from 1 to 4." ytotal = 0.0 for nk in range(nkmax): ytotal = ytotal + math.sin(ka[nk] * x - wk[nk] * t) return ytotal gdisplay(xtitle='x', ytitle='ytotal', title='Wave', xmin = -10.0, ymin = -60.0, xmax =100.0, ymax = 60.0) pulse = gcurve() t = 0.0 for x in arange(-10.0, 100.0, 0.2): pulse.plot(pos=(x, yt(x,t))) # Make a temporary copy -- see below temp = array(pulse.gcurve.pos) npts = len(pulse.gcurve.pos) while 1: t = t + 0.5 # Compute the new values in a temp array that isn't displayed, then # copy to the pulse.gcurve.pos array to update the display all at once. for n in arange(npts): temp[n][1] = yt(temp[n][0], t) pulse.gcurve.pos = temp Does anyone have any suggestions for how to significantly speed this up? All the looping over arrays seems to me to be the sort of thing that I ought to be able to get the Numeric extension to do for me efficiently, but I confess I'm new to it and haven't seen how to do it yet. Thanks for any advice, Andrew Dougherty dou...@la... Dept. of Physics Lafayette College, Easton PA 18042 |