After discussing the differences between compiled, interpreted, and just-in-time compiled languages, I want to look at programming languages and discuss which ones are suitable and serious contenders for CFD solver development tasks. This is an opinionated section, and I am not trying to hide it. If you create a wish list of features a programming language should have, and then look at which languages are available, then there is really only one contender in this category. I already mentioned in the previous post that this is C++ in my opinion. Thus, I want to provide my reasoning for this here and show you some nice features C++ offers to help us write clean code.
In this series
- Part 1: Choosing the right programming language for CFD development
- Part 2: Why you should use C++ for CFD development
- Part 3: The complete guide to memory management in C++ for CFD
- Part 4: Object-orientated programming in CFD
- Part 5: How to handle inheritance and class hierarchies in C++
- Part 6: Templates in C++: Boost your CFD solver performance
- Part 7: Enhance readability with operator overloading in C++
- Part 8: The power of the standard template library (STL) in C++
- Part 9: Understanding Lambda expressions and how to use them in C++
- Part 10: Reduce memory bugs with smart pointers in C++
In this article
Choosing the right programming language
I mentioned a wish list of features above that a programming language should have in order to be considered for CFD development. Let’s look at that list and then outline a few contestants and see how they stack up against each other.
- A strong community of active users and steering body
- Allow for object-orientated programming
- Availability of libraries for CFD development
- Tools to automate development tasks
- Allow for compilation and compiler optimisation
Let’s look through these individually.
A strong community of active users and steering body
If we wanted to get a quick overview of which programming languages are currently in use, and which are the more popular ones, then there is the Popularity of Programming Languages, or PYPL index (similar to TIOBE, referred to in the previous part), that tells us how much share each programming language has currently. You can find it here: PYPL index. Obviously, this is a dynamic list and if I referred to any language and stated their position, then this may have changed slightly since I wrote this and the time you are reading this. But we can make some general comments: Python is usually at the top, followed by Java and JavaScript, as well as C-based languages such as C# and C/C++. Other languages to look out for are Matlab and Julia, which appear further down the list (at least at the time of writing). I would say that Python, as well as C/C++, are more general-purpose languages, while the other languages listed in the top part of the table are more application-specific, that is, web and mobile development.
The languages listed here give us an indication that may be useful for us, as an active user community means that this language is likely still in active development and constantly evolving. This is the task of the steering body, which has to ensure that the language itself is being maintained and features are added or removed to keep up with user demands. Programming languages are dynamic, and features will be added to make languages even more feature-rich than they potentially are already. On the other hand, an active user community also means that libraries and tools are constantly being developed and that you as an end-user of the language will have a lot of boilerplate code you can inject into your project, reducing the need to rewrite critical parts from scratch and removing the need to reinvent the wheel.
The languages listed on PYPL that are relevant to CFD solver development are Python, C/C++, Matlab, and Julia. I would also include Fortran here, even though it is not showing up in the list. It is mainly used by scientific applications such as CFD solvers and so has a very low market share and is very niche-specific (hence we don’t see it in the list above).
Allow for object-orientated programming
This one is important because CFD codes require some lines of code before anything useful can be simulated. Think about it, you need to have some form of handling parameters, reading or generating a mesh, discretising partial differential equations, solving a linear system of equations, and outputting the solution into a post-process-friendly format. All of these steps require a certain complexity, so you won’t be able to write code quickly with just a few lines of code (unless you take shortcuts and use libraries or toolboxes that let you get started quickly).
Object-orientated programming has a few features that allow us to write and maintain clean code. This means as your code grows in size, its complexity stays the same. If you use functional programming (i.e. you use functions instead of classes) your functions need to handle both states and implementation logic. There are several reasons why you want to separate these; one reason is that you should keep data management (states) and implementation logic (algorithm) separate, this ensures your code is testable, but also it makes for cleaner code.
In functional programming, you have to pass all variables to the function you want to use (or worth, you declare all variables global and then leave yourself with no hope of tracking down memory bugs, or in fact a reliable way of testing your application). With object-orientated programming, you’ll pass all required variables to the constructor of a class, which will then manage the state (memory) and its methods. Methods are just functions that belong to a class. From now on, I just use the word function for both classes and non-classes and only methods if it is important to distinguish between class and non-class implementations. This is one example of why classes are useful, and you’ll only ever realise this yourself once you are writing your own object-orientated CFD solver. I’ll introduce some more features later, but this should be sufficient for this section.
Applying this filter to our selection of languages removes C from our list. I am being generous here, it could be argued that both Fortran and Julia are either object-orientated or not and, it is up to the reader to decide that. Both have features that look like object-orientated programming (i.e. allowing for class structures), but that is just the starting point and to leverage the true power of object-orientated programming, you’ll need a few more ingredients. Both Python and C++ have a very feature-rich implementation of object-orientated programming principles.
Availability of libraries for CFD development
This is really where things get separated. As alluded to above, we don’t want to reinvent the wheel ourselves but rather rely on code that has already been written by someone else, where we know there is a rigorous software testing practice in place to ensure that their code is not going to introduce bugs into our code once we start using their library. In the beginning, you may be tempted to write everything from scratch yourself; for learning purposes, this is a great idea (and a route I personally went down myself) but once you want to write a production-ready CFD solver (and by production-ready I mean a CFD solver that is fit for your purpose, that can be running some simulations for a thesis, for an industrial application, an academic research project or even a CFD solver that is ready to be sold as a commercial product), you’ll want to use code that is doing a lot of the heavy lifting for you.
If we look at our list, then both Python and C++ have dedicated libraries that are being developed for these languages and that are useful in the development of CFD solvers (and more importantly, both feature package managers that allow for easy dependency management). Matlab has some good toolboxes but is by far not as complete in this respect as Python and C++, so I would personally remove it from the list solely based on this point. Fortran benefits from the fact that some libraries, although written in C/C++, provide interfaces for other programming languages, and Fortran is one of them, so even if there aren’t that many libraries out there written exclusively in Fortran, it still benefits from a rich ecosystem. Julia also features its own package manager and does have a good selection of packages available so should remain on the list.
Tools to automate development tasks
Writing your code is still the most important part of writing any software application, but just concentrating on programming isn’t going to be enough to fit in with modern software development practices. You need to be able to use tools that support you throughout the development process.
For compiled languages, you need to have a way of automating your build and various other tasks that arise as part of the software development process, such as testing your code and packaging it for release. Luckily, we have tools such as CMake available which will take care of that for us and which support a wide range of languages.
Software testing is another important aspect and, we should have tools in place that allow us to automatically detect and run tests to some degree. While CMake does provide support for this, there are more sophisticated packages available that integrate with CMake and do a better job at testing our code, or rather, that provide us with more functionality that CMake does not provide out of the box.
All languages still in the running (Python, C++, Fortran, and Julia) do provide provisions for this, although I feel that tooling support for Fortran is probably a bit limited and, it is beneficial that tools such as CMake do provide support for Fortran, still. This is a personal observation and you, as a diehard Fortran advocate, may know better. But from what I can see what is happening on the Fortran side and what is happening on the Python or C++ side, Fortran does not stack up as well in this respect.
Allow for compilation and compiler optimisation
This one should be a no-brainer; CFD applications are power-hungry applications and require a lot of computational power to run. If all you ever want to do is simulate 2D channel laminar channel flows then this argument may not hold, and you don’t really need the speed (but then again, likely anything else I have said previously may not be true for you then either!).
We looked at the differences between compiled, interpreted, and just-in-time compiled languages in the previous post, so we won’t go deeper into this here again. The advantage of a compiled language, as stated before, is that since it is compiled, the compiler itself is allowed to change the code and optimise it for speed. It will not change what the code is doing, just how it is achieving that. Writing optimised code is not something we as programmers should ever attempt to do, as this will lead to a maintenance nightmare. Our compiler should do this for us. We pay by waiting a bit longer each time we compile the code, but reap the rewards of having a fast code with readable code that is easy to maintane and extend.
C++ and Fortran are both compiled languages and, while on this topic, when I started my CFD career I came across this myth that Fortran is faster than C++ as a language. I bought into this nonsense and exclusively used Fortran for quite some time as a result. A large portion of my PhD project was dedicated to writing code with Fortran. However, I eventually realised that the speed achieved is merely a function of the complexity of the code and the ability of the compiler to understand this complexity and then apply the right optimisation for us. Fortran is a relatively simple language, meaning it is not as feature-rich as C++. If you were to write similar codes, however, i.e. you only use functions, no classes, and you tried to come up with a 1-to-1 translation of a Fortran code in C++, I would be surprised if you actually saw a significant difference in execution speed. This, of course, is down to the optimisation capabilities of the compiler, but I would argue that there is a much stronger C/C++ compiler development community than there is a Fortran one, and so naturally we should expect the same if not better results here.
Python is interpreted and thus should be, at all costs, avoided for CFD solver development, right? Well, the answer is not that simple. Python is interpreted, yes, and thus out of the box slow. However, if we look at performance-hungry packages such as NumPy, then you’ll notice almost no difference in speed compared to a compiled language. Why? Because Python packages such as NumPy are actually implemented in a compiled language, and Python just calls these functions through an interface. This is not surprising, Python itself is written in C and so there is a natural tendency to support compiled languages. There are even solutions to bring C++ code into Python with SWIG (an interface between C++ and Python, but also other languages). Furthermore, Python has support for packages that introduce just-in-time compilation into Python directly, so actually, you could argue that Python sits somewhere along the entire spectrum of compiled, just-in-time compiled, and interpreted languages, and it is just a matter of which packages and implementation you use to select where on that spectrum you want to be. You can even compile Python code into native C code using Cython, to give you manual control over what parts of the code you want compiled. Suffice it to say, that introducing any form of compiled content into Python will increase its coding complexity, but it can be done. A good example of this is PySPH, a general-purpose CFD solver based on the Smooth Particle Hydrodynamics (SPH) framework, which is implemented in Python and uses Cython for performance-critical parts.
An example of a just-in-time compiled language is Julia and C#. While C# is mainly used for application development on Windows (there is no real port to a UNIX-based system), Julia is finding more and more traction in the scientific software development community. This includes CFD as well. It may well be worth a look, though it pales in comparison to C++ when it comes to already available libraries and the user community.
Resources for CFD C++ Development
We have looked at why C++ is an important language to know for you, and I know from personal experience, that learning it is a rather complex task as C++ has a steep learning curve. Learning the basics is straightforward, i.e. how to manage conditional statements and how to loop over a range of numbers, but once you get started with object-orientated programming, you’ll read about so many different concepts that you have barely time to understand what each of them are doing and why you want to use them in the first place. So we will look at concepts in the remaining parts of this module that I think are important to understand when you are getting started with C++ and object-orientated programming. We will look at how to apply these concepts directly to situations where we may want to use them when writing our own CFD solver.
Before we get started, though, if you are looking for a good place to learn C++, the single best place to learn it, in my opinion, is the learncpp. It discusses pretty much everything there is to know about C++ with a wealth of examples that are clear and understandable, and I have used it a fair bit to wrap my head around concepts that are not that straightforward.
If you just want to try a few different C++ code snippets and don’t want to run them locally on your PC, there is an excellent online resource available for you; the compiler explorer. It features pretty much every C++ compiler under the sun and is intended to be used to check small C++ codes with different compilers to see if what you are planning to code is working with a range of compilers (and we should make an effort that our code is working with several compilers, not just a single one, remember, C++ is a growing language and not all compilers support necessarily the latest features). However, we can use the compiler explorer as well to test our codes and get a quick idea of what they are doing. I pretty much use it all the time as a scratch pad and for that, it is really useful; in fact, all examples you will find here are written and tested over there.
Note, by default the compiler explorer is not showing you the output of your code but rather the generated assembly code. This is useful to understand performance but beside the point for our purposes. You’ll want to click on the plus sign above the code editor and select Execution Only, this will bring up another window in which we see the output of our code (or compiler errors if our code is not working).
Summary
So, having gone through our CFD solver development wish list we have towards a programming language, where does it leave us?
I would say, C++ is still king when it comes to CFD solver development and this is the language you should be learning. Based on the arguments we have looked at, you may say that all four remaining languages, i.e. C++, Python, Fortran, and Julia are all good contestants, and you would be right, I invite you to challenge my recommendation. However, there are more things to consider that may not necessarily be part of our wish list but rather follow conventions. What do I mean by that? Look into any CFD solver development project that is going on, or job advertisements that look for CFD developers, which language do they use or need? Well, C++ always comes up. OpenFOAM and SU2, two popular open-source CFD software packages used by many, are written in C++. The commercial CFD solver I worked on was written in C++, though it had some Python bindings as well. Whenever I check what current skills are required as a software engineer on CFD-related job openings, C++ comes up. So in a sense, learning C++ will ensure that you are learning relevant skills, and we have seen from our wish list that this is certainly one language that ticks all the boxes.
Now I wanted to mention a few words on the other languages as well. Fortran is still a good choice in my view, as you can get to results quickly. It is a good platform to learn CFD, but perhaps not the best platform to scale a general-purpose CFD solver from (though it has been done in the past, but that doesn’t mean that it should be done these days when starting out from scratch).
Python is a great choice as well if you are OK with learning a few additional packages like Cython to get speed back. Julia is similar to Python, although it does feature a just-in-time compiler so outright speed is not really an issue. The only reason speaking against it is its generally low uptake in the CFD community. If this doesn’t deter you (i.e. you are working on a thesis or an academic research project), then by all means, use Julia and let me know about your success story with it, I would be very interested in hearing from you!
We dropped Matlab and C from the list before, just to mention a few words on these languages as well. Similar discussions to Fortran can be had about C, it doesn’t scale very well, but it is fast. A good overall choice to get something out quickly for testing but I wouldn’t recommend C for general-purpose solver development (but again, similar to Fortran, it has been done in the past). Matlab is an interpreted language and does not support as much support as Python to make it faster, though there is some provision for speed improvements. In general, I can’t recommend Matlab anymore, mainly because you have to pay to suffer slow execution of your code. Just using Matlab for plotting graphs should also not be a reason for using it, especially since we have packages like Matplotlib available in Python.
So, I hope you can see why I am advocating to learn C++ if you want to get serious about CFD development. In fact, to ease the pain, the remaining posts in this module are looking at concepts in C++ that are perhaps not always well explained, so I’ll show how to use them in a CFD development context which hopefully makes them easier to understand. I want to be clear here, though, as a serious programmer (in any discipline), you likely have your go-to language (like C++ for CFD solver development), but there will be other languages you’ll use for various other tasks. You should always try to make an effort to learn at least the basics of other languages you think will be useful to you. In your case, learning Python should be on your list as well, just because of its sheer power and popularity, even if you don’t have a use case for the moment, there will be one in the future I am sure. Just for data analysis, manipulation, and plotting, Python is an amazing language and needs your attention.

Tom-Robin Teschner is a senior lecturer in computational fluid dynamics and course director for the MSc in computational fluid dynamics and the MSc in aerospace computational engineering at Cranfield University.