This blog serves as a friendly yet practical guide to understanding inviscid compressible fluid dynamics, progressing from the governing mathematical equations to a core challenge in this field: the Riemann problem. The following content, heavily inspired by Professor Eleuterio Toro's book [1], will answer two key questions:
"Big whorls have little whorls Which feed on their velocity And little whorls have lesser whorls, And so on to viscosity." --- Lewis Fry Richardson
Consider this one-second evolution of whorls prepared by Jacob [2]. What do you see?
"Beautiful eddies, good-looking flows π. And... (Shrug) That's all." --- a guy named Zian Huang
Eddies, and the smaller eddies within them, represent a complex natural phenomenon. It's challenging to describe the intricate motion of a fluid using words alone.
We therefore need a deterministic and systematic way to describe a fluid at a given time (). One powerful method is discretisation, where we approximate our continuous reality. Think of it as applying a mosaic effect to the snapshots above. This approach gives us a way to quantify what we see. For example, we can now say that at the box located at on the plane β 10 boxes to the right and 14 boxes up from the bottom left β the colour intensity fades as time passes. Notice how each mosaic box is represented by a single colour, which is an average of all the colours inside that box. This representation, where each box holds a single value for a fluid attribute, is known as a piece-wise constant configuration.
As the size of these boxes shrinks, (), we're moving from a 240p fluid to a 4K fluid and beyond! As the time step drops from second towards zero (), it's like we're blinking our eyes faster than a machine gun. As these discrete elements get smaller, our mosaic animation becomes a more realistic representation of the actual flow.
Since we've discretised space and time into boxes and frames, this is the perfect moment to introduce the concept of a control volume. Imagine the fluid we wish to model lives within 3D blocks like those in Minecraft, also known as Cartesian grids. In the example above, these boxes carry information about colour intensity (decreasing from orange to yellow to white). For our purposes, we'll replace colour with the key physical properties of fluid that interest us: density (), momentum (), and total energy ().
We now have our canvas: a grid of boxes, each filled with fluid properties, waiting to evolve. The next step is to define the mathematical model that governs how these properties change over time.
Our first objective, compressibility, means that density can vary in space. By assuming there are no chemical reactions and that the total mass of the fluid system is conserved, we arrive at the continuity equation:
where the grad operator is defined as . The superscript indicates the transpose of a matrix.
Term is the local rate of change of density at a fixed point. Term accounts for the change in density due to fluid moving past that point (advection). Finally, term is the essence of compressibility, representing density change due to the divergence of the velocity field. With the help of a negative scaling, intuitively, this expression means that if fluid is gathering (negative ), the density in that region should rise. Conversely, if fluid is spreading out (positive ), the density should fall. This change must be balanced by either a local density variation () or the advection of fluid from neighbouring regions (). The presence of to the first power means that as fluid accumulates, density increases linearly.
Using the vector identity , we can rewrite the above to have the conservative continuity equation:
With density defined, we next consider momentum. This brings us to the holy grail of fluid mechanics: the Navier-Stokes equations. Here, we present the conservative and inviscid form of this equation, known as the Euler equation [3]. The momentum at a point in space changes according to:
where: is a velocity component; is pressure; and is a body force (like gravity). The terms are: , the local rate of change of momentum; , the rate of momentum advection; , body forces; and , the force due to pressure gradients.
Assuming no body forces, we can rearrange this into the final form of the momentum equation:
Here, is the identity matrix, representing isotropic pressure contribution in all directions, while is the outer product operator applied on two matrices.
Let's quickly recap. We now have two equations modelling the change in density and momentum:
A sharp-eyed reader will notice we have a problem: we have three unknown variables but only two equations! To close the system, we need a third equation for energy. We define the total energy per unit volume () as the sum of kinetic and internal energy:
where is the specific internal energy. To relate this back to our other variables, we assume the fluid is an ideal gas, which follows the ideal gas law:
where is the specific volume, is the ideal gas constant scaled to the number of moles of gas in the specific volume, and is temperature.
If we further assume the gas is calorically ideal, its internal energy is directly proportional to its temperature. This allows us to establish the relationship:
where is the ratio of specific heats, a constant that depends on the gas. For a diatomic gas like nitrogen, if one dives deep into its molecular structure, one finds .
Drawing inspiration from our first two conservation laws, we can write the energy equation as:
Here, term has the same implication as in the continuity equation: as fluid accumulates, its energy adds up linearly. Term represents the work done by pressure forces.
At this point, we have a complete model governing the dynamics of a compressible, inviscid, and calorically ideal gas:
with an equation of state that expresses pressure as a function of our three conserved variables:
"This is indeed quite a journey from that first little whorl π₯΅..." --- a guy named Zian Huang
We now have two key pieces: a discretised domain (our 'Minecraft' world) with initial fluid properties contained in each box, and the system of equations that governs them. The goal of this section is to bring them together by discretising the governing equations to fit our gridded space.
Conservation is a fundamental principle in physics, and we've already seen its importance in our equations. The central philosophy of the finite volume method, which we'll apply to each box, is based on two key ideas:
(1) Within a control volume, the rate of change of a conserved quantity must equal the net flux of that quantity across the volume's boundaries.
(2) Each control volume is treated as a distinct entity, and the fluid properties within it are represented by a single, volume-averaged value.
From principle (2), we consider the value within each box to be piece-wise constant and uniformly distributed. This is a necessary compromise for modelling the continuous reality of nature on a discrete computer. To implement this, we transform our continuous differential equations into an integral form that applies over a finite volume. Taking the density equation as an example:
We apply the divergence theorem, , where is a vector field and is the surface of the control volume (the 6 faces of the box):
These two terms perfectly echo principle (1): the first is the rate of change of mass inside the volume, and the second is the net mass flux across its surface.
This processβapproximating field values within a volume by a single representative value and enforcing conservation via fluxes at the boundariesβis the essence of the finite volume method.
Since a divergence term appears in all three of our governing equations, we can first rewrite the entire system in a compact vector form [1]:
where is the vector of conserved variables, and , , and are the corresponding flux vectors in the , , and directions:
Let's then consider a single control volume indexed by at its centre:
Integrating the vector equation over this control volume and applying the divergence theorem gives:
Because our values are piece-wise constant, the volume integral becomes the volume-averaged value multiplied by the volume, and the surface integrals become the sum of fluxes over the six faces:
Here, ββ represents the flux on the face between cell and cell . Now, we approximate the time derivative with a first-order scheme, β, where the superscript denotes the current time frame. indicates the state of fluid attributes at a future time frame . Rearranging to solve for the state at the next time frame, , gives our final update formula:
This approach is known as an explicit time scheme because the future state can be calculated directly from the current state .
There is one crucial constraint on the size of our time step, , known as the CFL (Courant-Friedrichs-Lewy) condition:
where β depends on the numerical scheme. For the simple scheme we're using, we generally need to ensure the simulation is stable and doesn't 'blow up'. A CFL number close to its maximum stable value helps to minimise numerical diffusion, which keeps sharp features in the flow, like shock waves, from smearing out over time.
Our update equation shows that we can find the state of a cell at the next time frame, , based on its current state, , if and only if we can determine the flux terms (ββ, etc.) at the cell boundaries.
We are just one step away. The final piece of the puzzle is to determine the flux at the boundary between two cells. Let's focus on the boundary between cell and cell in the x-direction:
A simple approximate solution is the Lax-Friedrichs flux:
with
Term is a simple average of the fluxes from the left and right cells. Term is a crucial stabilising term, often called a numerical dissipation or diffusion term. It smooths the sharp jump at the interface by taking an average (), then scales it by the maximum speed at which information can travel away from the discontinuity (β).
One should easily get the remaining and by considering symmetry, and complete our quest to model the compressible inviscid fluid.
Solving the Riemann problem accurately and efficiently remains an active field of research. For those curious minds wanting more than this simple (but diffusive) approximation, let's look at the structure of the solution to a typical Riemann problem. In practice, it's often more intuitive to think in terms of "primitive" variables: density (), velocity (), and pressure (). The solution evolving from an initial discontinuity develops a distinct wave pattern:
The solution to the Riemann problem typically involves three distinct wave structures moving away from the initial discontinuity:
If you've made it this far, thank you for reading! I hope you now feel a bit more knowledgeable about, and interested in, the art of fluid modelling. Lastly, I want to point out the other paths on the broader roadmap of computational fluid dynamics that we didn't take. Some of the choices we made are modular, meaning you can swap in a more sophisticated numerical method for higher accuracy. Others are rabbit holes that lead to entirely new fields of analysis, such as viscous or incompressible flows.
Bon voyage in your fluid modelling quest β΅.
[1] E. F. Toro, Riemann Solvers and Numerical Methods for Fluid Dynamics: A Practical Introduction. Berlin, Heidelberg: Springer, 2009. doi: 10.1007/b79761.
[2] Jacob Albright, Flow Visualization in a Water Channel, (Nov. 20, 2017). [Online Video]. Available: https://www.youtube.com/watch?v=30_aADFVL9M
[3] J. H. Ferziger, M. PeriΔ, and R. L. Street, βBasic Concepts of Fluid Flow,β in Computational Methods for Fluid Dynamics, J. H. Ferziger, M. PeriΔ, and R. L. Street, Eds., Cham: Springer International Publishing, 2020, pp. 1β21. doi: 10.1007/978-3-319-99693-6_1.