In the fluid simulation based on a paper by Stam, fluid is modeled as a grid of densities. The densities "usually take a value between zero and one", but can be greater. Boundaries are implemented essentially as described in the paper:
A simple way of implementing internal boundaries is to allocate a Boolean grid which indicates which cells are occupied by an object or not. Then we simply have to add some code to the set_bnd() routine to fill in values for the occupied cells from the values of their direct neighbors.
int surround = !bound[IX(i+1,j)] + !bound[IX(i-1,j)] + !bound[IX(i,j+1)] + !bound[IX(i,j-1)];
if (!surround) x[IX(i,j)] = 0;
else
x[IX(i,j)] = ((bound[IX(i+1,j)] ? 0 : x[IX(i+1,j)]) +
(bound[IX(i-1,j)] ? 0 : x[IX(i-1,j)]) +
(bound[IX(i,j+1)] ? 0 : x[IX(i,j+1)]) +
(bound[IX(i,j-1)] ? 0 : x[IX(i,j-1)])) / surround;
The density method works well for compressible fluids like air, fire, or smoke. Is there a method to change boundary routines so density (limited to one fluid) is limited to a value, such as 1? This would represent say a cell completely full of water particles. Density that would be greater than one would have to be pushed away to neighboring cells. Stam lists ideas for extension but does not include how:
Another extension is to use this solver as a basis to animate water flows. In this case there are two fluids with different densities: water and air. The air is usually not modeled and the solver is harder to implement for the following reason: the domain of the water fluid changes over time and has to be tracked somehow and the correct boundary conditions have to be applied at the interface. The water region can be tracked using particles which simply move through the fluid as done by Foster and Metaxas [Foster96] or can be tracked with a combination of particles and level sets [Foster01,Enright02].