# Applying Pressure

**Listing 1: Pressure Differential**

for (int x = 0; x < m_w-1; x++) {

for (int y = 0; y < m_h-1; y++) {

int cell = Cell(x,y);

float force_x = mp_p0[cell] - mp_p0[cell+1];

float force_y = mp_p0[cell] - mp_p0[cell+m_w];

mp_xv1[cell] += a * force_x;

mp_xv1[cell+1] += a * force_x;

mp_yv1[cell] += a * force_y;

mp_yv1[cell+m_w] += a * force_y;

}

*The pressure differential between two cells creates an identical force on both cells.*

Listing 1 shows the code for applying pressure. Here mp_p0 is the array that stores the density (which is equivalent to the pressure, so I actually refer to it as pressure in the code). The arrays mp_xv1 and mp_yv1 store the x and y components of the velocity field. The function Cell(x,y) returns a cell index for a given set of x and y coordinates. The loop simply iterates over all horizontal and vertical pairs of cells, finds the difference in pressure, scales it by a constant (also scaled by time), and adds it to both cells.

The logic here is slightly unintuitive, since physics programmers are used to the Newtonian principle that every action has an equal and opposite reaction-yet here when we add a force, there's no opposing force, and we don't subtract a force from anywhere else.

The reason is clear if you consider what's actually happening. We're not dealing with Newtonian mechanics. The force comes from the kinetic energy of the molecules of the fluid, which are randomly traveling in all directions (assuming the fluid is above absolute zero), and the change to the velocity field actually happens evenly across the gradient between the two points. In effect, we're applying the resultant force from a pressure gradient to the area it covers (which is two cells here), and we divide it between them.

Here's an example: Just looking in the x direction, we have a flat pressure field, with one cell denser that the rest. The cell densities are 4, 4, 5, 4, 4. The gradients between the four pairs of cells is 0, -1, 1, and 0 Adding this to each cell (ignoring scaling), we get: 0, -1, 0, 1, and 0 (see Figure 2).

The cells on either side of the high-pressure cell end up with a velocity pointing away from that cell. Consider now what will happen with the advection step. The reverse advection combined with forward advection will move the high-pressure cell outward, reducing the pressure and force. The fluid moves from an area of high pressure to low pressure.

Effectively, this makes the velocity field tend toward being incompressible and mass conserving. If there's a region that's increasing in density, then the resultant increase in pressure will turn the velocity field away from that area, decreasing the density in that area. Eventually, the velocity field will either become mass conserving (mass just circulating without density change) or it will stop (become zero). See Listing 1.

# Ink And Smoke

What we're modeling here is motion within a fluid, such as air swirling around inside a room, and not the overall motion of a volume of water, such as water sloshing around in a cup. This method as it stands does not simulate the surface of the fluid. Visualizing the fluid itself is not very interesting, since a room full of air looks pretty much the same regardless of how the air moves.

What's more visually interesting is the situation in which some substance is suspended by that fluid, carried around by the fluid. With water, we might have silt, sand, ink, or bubbles. In air, we could see dust, steam, or smoke. You can even use the velocity field techniques outlined here to move larger object, like leaves or paper in a highly realistic manner.

It's important that what we're talking about is a suspension of one substance in another. We are generally not so interested in simulating two fluids that do not mix (like oil and water).

Games typically feature burning and exploding things, so smoke is a common graphical effect. Smoke is not a gas, but a suspension of tiny particles in the air. These tiny particles are carried around by the air, and they comprise a very small percent of the volume occupied by the air. So we do not need to be concerned about smoke displacing air.

In order to simulate smoke, we simply add another advected density field, where the value at each cell represents the density of smoke in that region. In the code, I refer to this as "ink." It's similar to the density of air, except the density of smoke or ink is more of a purely visual thing and does not affect the velocity field.