zCFDproto - Zig CFD Prototype

Numerically modelling fluid behavior is complex, and so Computational Fluid Dynamics packages often utilize many schemes and algorithms to simulate fluids accurately, efficiently and robustly. Depending on the specific simulation case, many choices need to be made on what schemes and algorithms should be used to perform the simulation and often there is no one combination that works for all cases.

It is therefore important when performing simulations to understand what the different schemes and algorithms do, when they perform best and when not to use them so that as a modeler you can simulate the physics reliably and diagnose any encountered issues with efficiency. Breaking down the black-box that are popular CFD packages is a bit difficult however, and so I chose to begin a side project to code my own solver from the ground up so that I can learn the fundamentals of CFD at a deeper level.

To code the solver, I chose to follow some concepts from the books by both Moukalled et al. [1] and Blazek [2]. I chose to program a compressible solver because it interested me more and gave me exposure to shock capturing, Riemann solvers and gradient limiters. Additionally, I took inspiration from the OpenFOAM case setup and mesh format as it was simpler to work with ASCII files rather than CGNS files which were more complex to code readers and writers for from scratch.

To code the solver I choose to use the new Zig programming language rather than simpler languages like Python and MATLAB. There are a number of reasons for this:

  • I wanted to learn a low level and statically typed language
  • I wanted to learn more about memory management, allocation strategies and some basic multicore and multi-thread processing
  • I did not want to deal with the complexity of C++ an C build systems (CMake)
  • Zig while a less mature language, has a far simpler build system and useful modern features like comptime
  • Coding using a newer language like Zig would force me to learn everything from the ground up rather than being tempted to look at other people’s code

When coding the solver, I focused on learning the fundamentals of CFD and so the solver focuses on and uses the following:

  • Cell-centered collocation for flow variables using the Finite Volume Method, due to it being the most standard approach in CFD packages
  • Compressible transonic and supersonic flow because it was more interesting to me, and it forced me to learn about convection schemes, Riemann solvers and shock capturing
  • Unstructured meshes as it more useful, in particular following the OpenFOAM format
  • Different gradient and interpolation schemes such as least squares gradients and piece wise linear interpolation due to it being fundamental to solving for the fluxes at faces
  • Explicit time integration and fully explicit schemes to avoid having to solve large linear systems which makes it easier to parallelize in the code
  • While the Navier Stokes equations is fully solved and a DNS simulation could technically be formed, most simulations are either inviscid or under resolved DNS as turbulence models were not implemented yet

Due to coding everything from the ground up, exporting and post-processing was a challenge to code from scratch, especially due to the cell-centered format of the solver and converting the cell data to the paraview vtk format. So the verification simulations that are presented will unfortunately only be pretty pictures for now before the solver is refactored to make post-processing and exporting to Paraview easier.

Simulation Details

  • Invisid
  • Ideal Gas - Air
  • Supersonic Inlet - Mach 3, 300K, 101kPa
  • Supersonic Outlet
  • HLLC Riemann Solver
  • Least Squares Gradient
  • Venkatakrishnan Gradient Limiter
  • Multistage Runge Kutta time stepping - 1st order - 3 stages
  • Local time-stepping
  • Number of cells: 5625
  • Number of cores: 16

Simulation Details

  • Invisid
  • Ideal Gas - Air
  • Supersonic Inlet - Mach 3, 300K, 101kPa
  • Supersonic Outlet
  • HLLC Riemann Solver
  • Least Squares Gradient
  • Venkatakrishnan Gradient Limiter
  • Multistage Runge Kutta time stepping - 1st order - 3 stages
  • Number of cells: 336000 (while a less refined mesh would have worked fine, I wanted to stress test the multicore parallel processing implementation)
  • Number of cores: 16

While the simulation did not reach a full steady state, it was good to see that the simulation remained stable and that the implementation of parallel processing is functional. This simulation was just to check for functionality and so the foundation of the code is good to move on to refactoring it to make proper simulation verification easier.

The code of the current prototype solver is available on my GitHub [3], however it’s likely that most of the original solver will be changed. While the original solver allowed me to learn a great deal, there were many pain points that made the project difficult. Most of the issues funnily enough stemmed from mesh formatting and post-processing and not coding the solver itself. While OpenFOAM and Paraview are powerful open source tools, using the case and mesh format of OpenFOAM made it difficult to easily create new meshes for new cases and the cell-centered face based data-structures don’t easily integrate with Paraview when the exporting of results needs to be coded manually.

Therefore, before any extensions to the project is made, the approach used for the project will be changed to make it easier to use more commonly used mesh formats such as CGNS or the even the grids made available on the NASA Turbulence Modelling Resource website. This will make it easier to create, simulate and really interpret simulation results critically and quantitatively rather than qualitatively with contours and animations. Thus, the project will most likely be refactored to do the following:

  • Use a Cell-Vertex based approach with median-dual control volumes rather than Cell-Centered approach
  • While less commonly used, it is easier to generate meshes for and post-process due to its vertex/node based approach rather than face based data structures
  • Incorporate dual-time stepping to handle time integration so that low-mach preconditioning can be used

Once these changes are made, it should make it easier to add the following extensions

  • RANS based turbulence modelling (ideally simpler ones like Spalart-Allmaras)
  • Simplified LES turbulence models like the Smagorinsky model, due to its explicit nature
  • GPU parallel processing rather than CPU based parallel processing, which would be easier to implement due to the explicit nature of the solver:
    • explicit time integration
    • compressible flow with low-mach preconditioning rather than pressure velocity coupling like SIMPLE

The initial changes will also make it much easier to critically analyse results and also extend the solver with more advanced features.

This project allowed me to learn a great deal and I now have a greater appreciation for the work that goes behind the scenes to create CFD and any other computational mechanics software, especially open source software like OpenFOAM and Paraview which provide all of their functionality for free. It also sensitized me to how sensitive simulations can be to initial and boundary conditions and especially there implementation subletities and how it affects the results.

Additionally, I learned a great deal about lower level programming and memory management, especially about data-orientated software design and allocating memory in such a way to optimize memory transfer through CPU caches and system RAM such as the differences between Arrays of Structs vs Struct of Arrays. This learning process was also enhanced by using the Zig programming language, as its lack of documentation and examples really forced me to learn and implement things on my own, while not allowing complex build systems like CMake to get in the way of the project.

  1. The Finite Volume Method in Computational Fluid Dynamics: An Advanced Introduction with OpenFOAM and Matlab - F. Moukalled, L. Mangani, and M. Darwish
  2. Computational Fluid Dynamics: Principles and Applications - J. Blazek
  3. zCFD-proto GitHub - https://github.com/MyrenRajh/zCFD-proto - _M. Rajh