CS 482 Lecture, Dr. Lawlor

In the  Navier-Stokes equations, "v · ∇ v" is the term that represents moving fluid--this is called various things like convection (when driven by heat), advection (when driven by anything else), or just "wind" or "bulk transport".

Now, "∇ v" is the  gradient of the velocity: vec3( ∂v/∂x, ∂v/∂y, ∂v/∂z).  This is a little odd, because velocity is already a vector, so taking the gradient gives us a vector of vectors (a matrix, or tensor).  Dotting this vector of vectors in "v · ∇ v" gives us a vector again (this is good because it gets added to dv/dt, which is also a vector).  The bottom line is:
v · ∇ v = dot(v,vec3( ∂v/∂x, ∂v/∂y, ∂v/∂z)) = v.x * ∂v/∂x + v.y * ∂v/∂y + v.z * ∂v/∂z

In English, we're dotting our vector field with its own gradient.  This tells us how similar the vectors are to their direction of greatest change, which in turn says how much the value of the vector will change when moving in that direction.  This is how "v · ∇ v" simulates fluid transport.

Now, we could implement this by actually taking some finite difference approximation of ∂v/∂x and actually computing the vector v · ∇ v at each pixel:

V-=50.0*VgV*dt;

The problem with this approach is it tends to break down and go unstable if the velocity gets too big.  The problem with the differential approximation to transport is that it fits a linear model to the local velocity neighborhood; moving by more than one pixel is essentially using linear extrapolation, which will amplify small waves in the mesh and explode first in zebra stripes and then NaN.  (Curious?  Read about the
Courant-Fredrichs-Lewy (CFL) stability condition.)