[Following up his popular recent article, Neversoft co-founder Mick West explains the technical details - including source code - of creating dynamic fluid systems such as smoke for video games.]
In the last article, I gave an overview of the nuts and bolts behind simple two-dimensional fluid dynamics using a grid system. This time, I explain how programmers can achieve a reasonable level of realism with fluid dynamics without too much expensive iteration.
I'll also continue with my goal of explaining how everything works by using nothing more complex than basic algebra.
To recap the last column: we have a velocity field, which is an array of cells, each of which stores the velocity at a particular point. Remember this is a continuous field, and we can get the velocity at any point on the field surface (or in the field volume for 3D), by interpolating between the nearest points on the field.
We also have a matching field of density. The density field represents how much of the fluid or gas is in a particular grid cell. Again, we're dealing with a continuous field, and you can get a density value for any point in the simulated space by interpolating.
I then described the process of advection, which is the moving of values in one field (for example, the density field), over the velocity field. I described both forward advection and reverse advection, where the quantities in the field are respectively pushed out of a cell or pulled into a cell by the velocity at that cell. The advection process worked well if you performed forward advection and then follow it with reverse advection.
Reverse advection in particular only works if the velocity field is in a state termed incompressible. But what does that mean?
You may have heard that "water is incompressible," meaning you can't squeeze water into a smaller volume than it already occupies. Compare this with gasses such as air, which can clearly be compressed. Picture, for example, a diver's air tank. The tank contains a lot more air than the volume occupied by the tank. But if you were to take that tank and fill it with water, and then somehow push in another pint of water, the tank would explode.
Actually, water is in fact compressible, very slightly, since it's physically impossible to have a truly incompressible form of matter. The incompressibility of a material is measured by a metric called a "bulk modulus." Air's bulk modulus is about 142,000, whereas for water, it's 2,200,000,000 or approximately 15,000 times as much.
By comparison, the least compressible substance known to humankind, aggregated diamond nanorods, are just 500 times more incompressible than water. So for most practical purposes, you can imagine water as being incompressible.
Because water is considered incompressible, there cannot be more water in one cell than in another when considering a solid volume of water. If we start out with an equal amount of water in each cell, then after moving the water along the velocity field (advecting), we can't increase or decrease the amount of water in each cell. If this happens, then the velocity field is incompressible or mass conserving.
You can think of the pressure at a particular node as being the difference in density between a cell and its neighbors. The pressure of water will be the same throughout the density field since it's incompressible. If we think of a node as having a series of inputs and outputs during the advection process, then in an incompressible field, the sum of input is equal to the sum of outputs (see Figure 1A). When we move the water along its incompressible velocity field, the density at each node remains constant, and hence the pressure remains constant.
On the other hand, if the velocity field happens to be structured in such a way that for some cells more is going into them than is coming out, the velocity field is compressible (see Figure 1B). When the density of the fluid is advected across a compressible velocity field, the density in individual cells will increase or decrease.
If we simply keep advecting the density, all the matter will eventually be compressed into the cells of the velocity field that have a net gain of input over output. If we were not performing accounting in our advection step (as explained last month), then there would be a net loss in density (the field is not mass conserving).
Let's step back from our abstraction for a second and consider what prevents this situation from happening in real life. If more of a fluid flows into a cell than flows out, then the density of that cell increases relative to its neighbors, and hence the pressure in that cell increases.
High pressure in a cell creates an acceleration force on the neighboring cells, increasing their velocity away from that cell, thereby increasing the outflow rate from the cell and evening out the imbalance. As with the atmosphere, fluid flows from an area of high pressure to an area of low pressure.