Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>All given answers provide a (great) deal of useful information. What you must do is:</p> <ul> <li>use ja72´s observation for performing the updates - you need to be coherent and compute the acceleration at a node based on the positions from the same iteration batch (i.e. do not mix $x⁽k⁾$ and $x⁽k+1⁾$ in the same expression of the acceleration as these are amounts belonging to different iteration steps)</li> <li>forget about your original positions as tom10 said - you need to consider only relative positions - the behaviour of this wave equation is like a laplacian smoothing filter applied to a polygonal line - a point is relaxed using its two directly connected neighbours, being pulled towards the middle of the segment determined by those neighbours</li> <li>finally, if you want your energy to be conserved (i.e. not have the water surface stop from vibrating), it's worth using a symplectic integrator. Symplectic/semi-implicit Euler will do. You don't need higher order integrators for this kind of simulation, but if you have the time, consider using Verlet or Ruth-Forest as they're both symplectic and of order 2 or 3 in terms of accuracy. Runge-Kutta will, like implicit Euler, draw energy (much slower) from the system, thus you'll get inherent damping. Explicit Euler will spell doom for you eventually - that's a bad choice - always (esp for stiff or undamped systems). There are tons of other integrators out there, so go ahead and experiment.</li> </ul> <p><strong>P.S.</strong> you did not implement true implicit Euler since that one requires simultaneously affecting all particles. For that, you must use a projected conjugate gradient method, derive Jacobians and solve sparse linear systems for your string of particles. Explicit or semi-implicit methods will get you the "follow the leader" behaviour you expect for an animation.</p> <p>Now, if you want more, I implemented and tested this answer in SciLab (too lazy to program it in C++):</p> <pre><code>n=50; for i=1:n x(i) = 1; end dt = 0.02; k = 0.05; x(20) = 1.1; xold = x; v = 0 * x; plot(x, 'r'); plot(x*0,'r'); for iteration=1:10000 for i = 1:n if (i&gt;1 &amp; i &lt; n) then acc = k*(0.5*(xold(i-1) + xold(i+1)) - xold(i)); v(i) = v(i) + dt * acc; x(i) = xold(i) + v(i) *dt; end end if (iteration/500 == round(iteration / 500) ) then plot(x - iteration/10000,'g'); end xold = x; end plot(x,'b'); </code></pre> <p>The wave evolution is seen in the stacked graphs below: <img src="https://i.stack.imgur.com/U184i.png" alt="enter image description here"></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload