I’ve tried SU2 for a week – should you, too?

Have you ever added a CFD solver to your learning to-do list? I have, and it keeps growing! So, instead of creating a to-do list that will never be completed, I thought I’d spend some time on a solver that has been on it for quite some time and share my experiences with you. I am talking about SU2.

It is an open-source solver mainly focused on aeronautical applications with compressible flows, though it has expanded into other domains. People who have used it seemed to have been really happy with it, so I thought I ought to give it a try. Well, the day has come, and I have decided to spend a week with SU2 and see if I will like it just as much.

The solver is great, and I really enjoyed my week with SU2. I’m sure I will start using it from now on for additional projects in the future. There are a few issues, and we will look at them in detail as well. I have also included a section at the end to give you a quick start into SU2, in case my writing compels you to try it out for yourself.

In this article

Introduction

When I started with CFD, I was under the impression that only ANSYS Fluent existed. I thought everyone was using it. How wrong I was! The somewhat dated list over at CFD online shows us that there are almost as many CFD solvers as stars in the Milky Way. Almost

At some point through my CFD journey, to be precise during my PhD studies, I was introduced to SU2. From what I saw, it was a very capable solver, but I was in the midst of getting my head around OpenFOAM at the time. This was a full-time job! So, I left SU2 on my CFD to-do list to be looked at at some point in the future. Well, the future has arrived!

I thought it would be good to finally give it a test drive and see if it is really as good as I was led to believe. Spoiler alert: I fell in love! SU2 is a very capable solver, but it does have some issues when it comes to its source code, and we will look at both sides. Either way, in terms of using the solver, I have gained nothing but respect for it.

So, for this week’s article, I thought I would spend one (working) week with SU2 and see how it performs. The first part will contain my journey through SU2 and what I’ve learned in a week. There is more to the solver than what you can discover in such a short time frame, but I think I got the jist of it. Afterwards, I’ll show you how to get started with the solver yourself, and you will see it is rather straightforward!

Let’s get started.

A week with SU2 – Here is what I’ve learned

The following section will reflect on my experiences, organised by days. I’ve tried to include a few things from running simulations to compiling the solver. I’ve looked at basic, as well as advanced features and tested some of them more thoroughly than others. Let’s look through them together.

Day 1 – Getting started with tutorials and testing different solver options

The best place to get started is, well, the getting starting section for any CFD solver. SU2 features a quick start guide, and this is the first thing I went through. It runs you through a basic inviscid (Euler) simulation around a NACA 0012 airfoil. You even get to test some of the more advanced features at the end. The quick start finishes off with an adjoint optimisation problem, which is a nice added touch.

The quick start guide asks you to download and install the software first. Upon visiting the installation page, you realise that SU2 comes with precompiled binaries for all platforms, even Windows! No need to compile the solver, so you can simply download the binaries for your platform and get started. It couldn’t be simpler.

With SU2 available on your machine, you can follow the rest of the quick start guide. It isn’t very long, so it definitly get’s you up and running in a few minutes. And, to be fair, that is all you need. At a minimum, SU2 reqires two input files; one for the simulation parameters (the config file), and one for the mesh.

The config file can be as simple as a few lines of instructions, i.e. which schemes to use, what boundary conditions to apply, and so on. A list of all possible inputs are stored in the template config file, and you can look throught the 2000+ lines of code to see them all. There are quite a few.

For the mesh file, there are two supported formats: SU2’s native *.su2 file format and CGNS. I love that CGNS files are supported out of the box, something which not many solvers do. The native *.su2 file format is also rather straightforward. It stores the coordinate of vertices, their connectivity, and finally, the vertices associated with boundaries.

After I finished with the NACA 0012 quick start tutorial, I wanted to switch from a compressible to an incompressible description. This wasn’t very complicated, and I wanted to see how it performs here. Well, as far as I can see, SU2 uses the artificial compressibility method, which can have slow convergence. From what I could observe, this was confirmed by running the solver in incompressible mode.

The first day got me interested in more. I really liked what I saw, and I wanted to explore some more advanced features. This is what I did next on day 2.

Day 2 – A deeper look into advanced solver settings

I started the second day, where I left off on the first. I wanted to explore some of the incompressible options further, only to realise that not all schemes were supported. You start to realise at this point that SU2 is a compressible solver, and incompressible flows were very much an afterthought.

It’s not really a problem, as you can always run incompressible simulations with their compressible solvers. They have implemented low Mach number corrections, which should help with convergence. If you are unfamiliar with the problem: As you approach a Mach number of zero, your accuracy will deteriorate, and convergence will come to a halt. Several low Mach number corrections have been proposed; see Bruel et al. for a good overview.

After that realisation, I picked a scheme that worked for incompressible flows and continued. When I first looked through the config file options, I got really excited when I saw the CFL ramping strategy. CFL ramping allows you to dynamically set the CFL number for each iteration to converge as fast as possible. You may start with a CFL number of 1, but as the iteration progresses, you may get a CFL number as high as 10,000,000,000!

This number may seem rather high, but as a simulation converges, changes between iterations become very small. We simply amplify these minute changes so they can come to a converged state much faster. And it does work rather well. Playing around with it, I got convergence within half the number of iterations compared to no CFL ramping strategy!

The other thing I got excited about was the multigrid, and in particular, the fact that different multigrid cycles were implemented. You can choose between V, W, and full multigrid cycles. You have control over the number of pre and post-smoothing steps, as well as some damping. After playing around with these parameters, you’ll realise that using a multigrid in SU2 can lead to really fast convergence or divergence. Once the multigrid is tamed and combined with CFL ramping, you have a winning combination on your hands!

I can’t stress enough how much I adore SU2 for having these two features implemented and working so well. For example, OpenFOAM uses exclusively semi-implicit algorithms. This means your CFL number will always be restricted, and I am typically near an average CFL number of 1 for my simulations. Having the ability to ramp up the CFL number really does make a difference.

ANSYS Fluent used to have a solution steering algorithm where the CFL number was increased as the residuals dropped. I played around with it a few times, but it didn’t seem to work as expected. In most cases, I got convergence within the same or even more iterations. It is no surprise, then, that this implementation has been quietly retired.

The next thing I did was play around with the input and output sections. I rather liked the fact that I can specify what I want printed to screen and how often during the simulation. For example, when I was using the CFL ramping strategy, I could opt to print the min, max, and average CFL numbers to screen for each iteration. This was really helpful for tuning the CFL ramping strategy parameters, as the default ones are rather conservative.

After spending the last article talking all about convergence and how to measure it, I was rather pleased to see the options for judging convergence. This can be done either based on the residuals, or based on window-averaged quantities, such as lift or drag. And, from my experimentation, it works rather well.

One thing I didn’t like about the config file was that it was over-constrained. It does allow you to specify both an angle of attack, Reynolds, and Mach number, as well as the inflow velocity components in the x, y, and z directions. Depending on what inflow condition type you set, one or the other will be used. This can be confusing for the novice.

At this point, I felt comfortable setting up my own cases, and this is what I did on my third day.

Day 3 – Setting up my own case for compressible and incompressible flows

On day 3, I recreated the NACA 0012 case but using my own mesh. I used Pointwise to generate said mesh, which has native support for writing SU2 mesh file formats. The mesh contained quad-based inflation layers to resolve the boundary layer down to a y^+ value of 1. The remainder of the mesh used triangular elements.

Using my own mesh allowed me (or required me) to set up the boundary conditions myself. I find that there are huge discrepancies between different solvers when it comes to boundary treatments. In Fluent, for example, all you have to do is provide a freestream Mach number or inlet velocity for this case. In OpenFOAM, you have to write a separate boundary file for each variable that is solved. This is really cumbersome (though the most general).

In SU2, we have a middle ground where we use the boundary marker concept. This is another concept I have seen used in some other compressible solvers. A boundary marker represents a specific boundary type. So, you may have an inlet marker, an outlet marker, a wall marker, and so on.

Each of these markers then expects the name of a boundary. So, if you have a boundary patch called inlet, you probably want to assign this to the inlet or farfield marker. If we take a look at the template config file and search for MARKER_HEATFLUX, this is what we see:

% Navier-Stokes (no-slip), constant heat flux wall  marker(s) (NONE = no marker)
% Format: ( marker name, constant heat flux (J/m^2), ... )
MARKER_HEATFLUX= ( NONE )

Here, we need to specify the name of the wall and the heat flux in J/m^2. For our airfoil case, if we have an upper and a lower wall patch in our mesh, and we want to assign a zero heat flux across the walls, then we would have

% Navier-Stokes (no-slip), constant heat flux wall  marker(s) (NONE = no marker)
% Format: ( marker name, constant heat flux (J/m^2), ... )
MARKER_HEATFLUX= ( upper, 0.0, lower, 0.0 )

Here, we can specify more than one boundary patch, but we need to provide the heat flux for each marker separately. If you are dealing with a text-based input file, then I think this is an elegant solution. You don’t have to specify the boundary conditions for the turbulent quantities (unlike OpenFOAM, for example). Instead, these are derived from additional inputs such as the freestream turbulence intensity and the turbulence viscosity ratio.

After setting up the case, I was first running it with an incompressible solver. Due to the lack of available schemes that are implemented for incompressible flows, I decided to go with the Lax-Friedrichs scheme. I’ve had good experiences with it in the past, though in this case, my solutions were rather far away from the reference (over 10%, where I would have expected perhaps a 1% discrepancy at most).

Once I switched to the compressible solver, things were working much better again, and I got the results I was after. The NACA 0012 airfoil example isn’t particularly exciting, but it is one of those examples where you know what to expect. If you have spent any time in academia validating and verifying CFD codes, you’ll likely spend some time on the NACA 0012 airfoil and have an idea of what to expect.

Based on the experience I have gathered over the years with this example, I can say that the incompressible solver, while functional, is probably something that requires further work. I’ve seen attempts of the SIMPLE algorithm being implemented into SU2, but it seems that 5 years on, nothing has been done about it. It’s probably fair to assume that this isn’t a priority.

I did play around more with the numerical schemes and other settings, but nothing spectacular to report here. Apart from the reappearing issues around incompressible flows, SU2 is making a solid impression and again, I really like what I am seeing here.

Day 4 – Inspecting the source code and compiling it

Day 4 was all about the code. I didn’t run any simulations; instead, I wanted to get a feel for the code. Currently, I do all my CFD development in OpenFOAM because it has a rather nice equation syntax. I wanted to see if I could extend this to SU2 as well and use it in the future to write my own extensions.

So, the first part is the code compilation, and I have to say, I am impressed. SU2 comes with pretty much zero dependencies. All you need is a Python installation and a C++ compiler. With that, you can go ahead and compile the code, which currently has just over 1000 files. This will give you a very basic SU2 version.

In most cases, though, you probably want to use at least a few dependencies. You probably want to use the Message Passing Interface (MPI) to parallise your code, or the CGNS file format to read CGNS files. Apart from MPI, which you have to install yourself, all the other dependencies are downloaded automatically and built as part of the compilation process. This automation is really nice!

I have tested that on the latest release of Ubuntu, and it is working like a charm. All you do is go into the root directory of your SU2 folder and type:

python3 meson.py build <options>

The options are listed in the compilation guide. For example, to enable CGNS support, we need to write the following:

python3 meson.py build -Denable-cgns=true

CGNS support is set to true by default, so the above instruction would be redundant, but it does show how to set these options. This file will call the build script Meson in the background, and this will set up your project for compilation. I have a soft spot for Meson, and even though I believe we shouldn’t use it anymore, I still enjoy working with it whenever I have a chance.

After the project has been configured with Meson, we invoke Ninja to compile the source files. This is done with the following command:

ninja -C build install

This will compile SU2 and install it (copy the executable files) into our installation directory. We haven’t given one, so it will just install it into our current directory, but we could also give an installation directory using the --prefix=/path/to/installation/directory/ syntax during the configuration step, e.g.:

python3 meson.py build -Denable-cgns=true --prefix=~/apps/SU2/

This would install SU2 into our home directory (indicated by the ~), and we ask SU2 to be installed into the apps/SU2 directory within the home directory.

On my PC, the compilation took about 15 minutes using 12 cores (Ninja will automatically use all available cores). 15 minutes for a complex code such as SU2 isn’t bad at all! And, everything is build from source, even the dependencies. This is great, and recommended practice.

I have also tried to compile SU2 on Windows. It boasts support for Windows, but after invoking the same steps as above, the compilation failed. First, it failed because it could not find my Microsoft MPI installation and executables. Looking into the issue, it seems it can’t find the default names for the MPI compilers. These are named differently on Windows compared to every other operating system in the solar system. Of course, they are …

Not a problem, I switched off MPI support, but got into another issue with HDF5 this time. This was an issue for which there was no quick fix, so I turned off the CGNS support. Afterwards, I was able to start the compilation, but after a few hundred files were compiled, I got another compilation error. This time, it was terminal!

Microsoft’s cl compiler wasn’t able to compile the code due to an incompatible syntax. Not all C++ compilers will have implemented the C++ standard in the same way, and sometimes, you have cases where one compiler fails while others succeed. This is one of these examples, and it shows that Microsoft’s cl compiler is not used during testing SU2. It is a shame.

Perhaps clang++ could produce different results here, I haven’t tested that, but the only other way (and recommended way by the developers), is to use MinGW. I am not a big fan of MinGW, so I wouldn’t recommend using it. It is a botched approach of desperately trying to get UNIX compilers to work on Windows. If you really need them, use WSL, which has made the MinGW project redundant.

I don’t understand why all scientific tools and programs have such a bad phobia against native Windows compilers. Sure, in the past, developing on Windows was dreadful, but it got a lot better. These days, there is no reason to fear testing your code on Windows (most people will want to run it here!). There are even Docker containers available that allow you to test on Windows natively. Developers no longer have an excuse to ditch Windows!

Anyway, let’s not get side tracked. The next thing I had a look at is the folder structure and some of the files. It is relatively compact, and navigating the code does not seem too difficult. But then I started to look inside some of the files. Oh boy, strap in, this is going to be wild!

Let’s start off easy. One of the files had code like the following:

if (wall_functions) {
    SU2_OMP_SAFE_GLOBAL_ACCESS(SetTau_Wall_WF(geometry, solver_container, config);)
    // nijso: we have to set this as well??
    // seteddyviscfirstpoint
  }

Who is nijso? Is it a person? If so, why is the code including me in a conversation between nijso and whoever wrote the comment? And what is being set here? Is it the command above or below? I have no idea what is going on here, and comments in code like this are a huge red flag. These should be removed from any release.

A better (and apparently accepted) practice would be to have the following during development:

if (wall_functions) {
    SU2_OMP_SAFE_GLOBAL_ACCESS(SetTau_Wall_WF(geometry, solver_container, config);)
    // TODO: we have to set this as well??
    // seteddyviscfirstpoint
  }

Whenever we set a TODO: somewhere in the text, we can search for this string and work on it before we create a new release. This comment just isn’t helpful!

While I almost self-destructed this website talking about documentation (see part 1 and part 2, which I shared with my email list), we need to talk about it again. SU2 has adopted a type of code documentation that can only be produced by a brain-dead person. Take a look at the following code:

/*!
 * \brief Destructor of the class.
 */
~CUpwFDSInc_Flow(void) override;

The ~ on line 4 already clearly communicates that whatever comes next is going to be the destructor. Keywords and special C++ syntax do provide code documentation, and I believe in writing clear, self-documenting code instead of throwing around Doxygen strings.

The code documentation requires three lines of code to tell me what the ~ already communicates. Even worse, the documentation isn’t adding any value here! I know this is the destructor. What I am looking for in documentation is things that are not clear. Simply writing Destructor of the class is as useful of a comment as It's colder and darker at night.

Thanks SU2 for these insights; perhaps someone should tell nijso to remove this!

Then we have an absolute abomination like this:

CNumerics****** numerics_container;   /*!< \brief Description of the numerical method (the way in which the equations
                                           are solved). */

What the hell? I thought we are using C++, not C. Why do we have multidimensional pointers? Who is coming up with this, and who is letting this get through in a code review? Probably there isn’t one …

Since the C++ standard of 2014, there is absolutely no excuse for still using new and delete. Every time we have a pointer, we have a corresponding new and delete call. This is probably the single most common cause of hard-to-trace memory bugs. Instead, we ought to use smart pointers.

We looked at smart pointers before, but I won’t go into detail here. Feel free to read up on why we should favour them over pointers for yourself. I’ll wait here …

In this case, I would encapsulate the memory management of the numerics_container into a class and then expose a get() function to obtain the information required. We see that the type of numerics_container is CNumerics, so we are already using a class. Why can’t the class take care of memory management?

This is really poor code design (can we even speak of a design to begin with?) and suggests a very creative academic at work, where each new line of code is a new improvisation.

Can we also stop for a second and admire the naming standard in SU2? We had:

~CUpwFDSInc_Flow
CNumerics****** numerics_container

We have a good mix of Pascal case and snake case, even in the same class name. While it is fine to have different naming conventions for classes and variables, pascal case and snake case are pretty much orthogonal to each other, i.e. if you use one, you don’t use the other. This is at least true for most major open source projects I have looked through. SU2 likes to set a new standard here …

And then, we have the classes themselves. I invite you to have a look at the solver base class. You can find the header file here and the source file here. The header file has about 1500 lines of code, while the implementation (source) file features nearly 10,000 lines of code!

A class should only ever have a single responsibility. This is to help not just with readability but also with maintainability. Otherwise, if your class does too many things, it becomes a nightmare refactoring it over time.

There is a design pattern that helps us to write clean classes. It is called SOLID. The S in SOLID stands for the single responsibility principle. This is literally the first thing we should be thinking about when designing a class. Thus, if a class only ever takes care of a single thing, you would expect a header file to not go beyond a hundred lines of code (or so).

Do we believe SU2 is following this accepted design pattern? Let’s investigate. These are some of the functions the solver base class is exposing:

class CEulerSolver {
  void SetTime_Step( /* arguments */ ) final;
  inline su2double GetTotal_NetThrust() const final { /* implementation */ }
  inline void SetOmegaOut(/* arguments */) final { /* implementation */ }
  void PrintVerificationError( /* arguments */ ) const final;
};

So we compute the time step within this class (line 2), we can extract the thrust of our calculation (line 3, which is only required for turbomachinery applications!), we set the specific dissipation rate omega at outlets (line 4, though you can run this solver without turbulence where this is irrelevant!), and we deal with verification errors (line 5, even though this is also not required for the simulation).

This solver is doing everything, and then a bit more. The only thing missing here is the weekly grocery shopping list of the author of this class. This is, quite frankly, horrendous, but I suppose the price you have to pay for free and open-source projects. I won’t be making an effort any time soon to sift through this source code to see if I want to implement some features myself.

Finally, we have to talk about testing. Any complex software project should have some form of quality assurance practices in place. I showed you how to do proper software testing for CFD applications a while ago, and I believe each software project should have a testing strategy. There is none as far as I can see with SU2. Honestly, I am surprised that the solver is working as well as it is.

But let’s look at the matter together. Within the main git repository, there is a TestCases folder. This does provide some confidence. Looking through these test cases, these can be classified as system tests. Now I am not sure how these are used. Typically, you want to run your system test before every release to make sure the software is still working as expected. This may be the practice here, in which case, well done SU2.

However, while system tests provide the best protection against software bugs (because we are exercising the entire code base), they are expensive to run. This typically results in system tests not being executed or their results not being thoroughly analysed to identify bugs.

Thankfully, SU2 also comes with some unit tests. I was relieved when I saw that. But then I looked at the unit tests. The unit test folder, contained in the root level directory of SU2 as well, has little to no unit tests. Counting the unit tests for the CFD solver, I can find 8 separate unit tests. Yes, 8. A unit test is supposed to check the functionality of a given function. SU2 has more than 8 functions for their CFD solver.

We have an upside-down software testing pyramid, with more system than unit tests. I appreciate that some effort has been spent on testing, but I think whoever was looking after the testing strategy didn’t really understand software testing in the first place. This is a ticking time bomb, and poor codebase quality, coupled with little to no tests, is a recipe for disaster.

Suffice it to say that going through the source code lowered my respect for SU2. It does seem to work really well, but based on the code I have studied, it shouldn’t. Unless system tests are meticulously used to prevent software bugs from appearing, it is probably just a question of time before more severe bugs make it into their solver.

Even if we don’t have any software bugs to fight with, we have an unmaintainable code base, which perhaps only the original developers understand. This may work for them, but new developers wanting to contribute may be scared off looking at the code. This isn’t great if you want to scale up your code development efforts or just try to get a bigger market share.

In any case, the solver as things stand seems to work quite well, but I wouldn’t be surprised if I stumble upon more subtle bugs after some more usage. Only time will tell.

Day 5 – Exploring advanced features of SU2

On the final day, I wanted to explore some advanced features of SU2. Instead of picking one example and running it, I wanted to get a feel what else is possible. This means I was going through the config file again, advanced tutorials, and the user guide.

One thing I quite liked was the multiphysics capabilities and its implementation. SU2 does not only come with a CFD solver, but also with a few others. If you want to use two or more solvers, simply specify a separate config file for both of them and then create a third config file that simply glues these two together.

It does, for example, come with a structural solver to perform fluid-structure interaction. And, the structural solver does have some nice features. It has capabilities for small and large deformations, as well as multiple materials. I would love to see this extended to composite materials. Perhaps I should put it on my wish list for Santa!

I have mentioned the adjoint optimisation before. While I did run a few examples for it on the first day, this is definitely something to further explore. Optimisation was always something baked into SU2, and I have seen other solvers react to that. ANSYS Fluent now has adjoint optimisation, and so does OpenFOAM.

Closely related are two additional concepts: deep neural networks (DNNs) and reduced order models (ROMs). Both can be used to optimise a given geometry, though DNNs are currently implemented in a limited capacity. DNNs can be used to predict thermodynamic properties only during the combustion process (version 8.1), but that may be generalised in the future. The ROM support is definitely something to test further.

Then, there is uncertainty quantification. This is something I haven’t seen anywhere else and another signal that SU2 is setting a trend that I am sure will emerge at some point in ANSYS Fluent and OpenFOAM as well. They seem to closely monitor SU2’s features and implement those they see as a thread.

I have to have a closer look at the uncertainty quantification module, but essentially, you perturb the system of equations with 5 different modes, where each mode is a different simulation (so 5 simulations in total + the unperturbed simulation). What this allows you to see is the uncertainty in different plots, such as the pressure coefficient or the lift slope. Here are two examples taken from the tutorial case:

On the left, we see the pressure distribution along an airfoil. The different modes are shown as different line colours. The union of all of those lines are shown as the grey area, and we can see that around x/c\approx 0.5, we have very little uncertainty. The solver is very confident about its prediction here, whereas the same can not be said for pressures closer to x/c=0.

For the figure on the right, showing the angle of attack sweep, there is very little uncertainty for the linear lift slope but a rather large uncertainty once separation effects become important. We have a large uncertainty for the stall regime as expected. It would be interesting to test the same simulation with a transitional RANS model, which SU2 does have support for.

Another feature I spotted is support for automatic differentiation. It is not something you will use during your setup; rather, it is something that is used in the code itself. However, I have gathered positive experiences with automatic differentiation before. It allows you to evaluate the derivative of a function exactly as long as you know how the function value was computed. This can produce, for example, an exact flux Jacobian, and this can improve stability at higher CFL numbers.

I also noticed the support for Discontinuous Galerkin (DG), and this went almost unnoticed. I’ve always wanted to have a playground to mess around with DG, and I finally seem to have found it. I have worked quite a bit with the DG method in the past, though I have never really tested it for more complex problems. Well, here is another item for the to-do list.

And finally, let’s finish day 5 by talking about parallelisation. There seems to be a move currently to implement a hybrid MPI+OpenMP parallelisation. If you move around high-performance computing circles, this approach is well established. However, in CFD circles, this is a less explored concept, but has potentially huge benefits in terms of making your parallelisation more efficient. This seems to be a work in progress, so I may wait until the next release before properly testing it.

So there you have it, 5 days with SU2, packed with ups and downs. Overall I am really impressed. While I have my issues with the code, you can completely ignore that aspect and just use the solver. And the solver does work really well, and is something I will explore more of in the future for sure!

How can you get started with SU2 right now?

So, after you heard me talking all about SU2 and what its advantages and disadvantages are, perhaps you want to give it a spin and see it for yourself. This section is intended to get you up and running with SU2 and have your first simulation performed in a few minutes.

Installing SU2

Installing SU2 is pretty straight forward. I would recommend grabbing the precompiled binaries that you can find on the download page of SU2. Download and extract the folders, and open up a terminal. You can navigate into the SU2 folder containing the binaries and then simply execute them. The executable you are looking for is called SU2_CFD.

Alternatively, you can grab the latest release from GitHub and compile it from source yourself. It is rather straightforward. See the details above (Day 4) for how to compile and install it from the source.

In either approach, you may want to add the executable directory to your search path so that you do not need to specify the absolute path to the executable every time you want to use it. It may make sense if you want to install it on a permanent basis, but if you are just playing around, perhaps just use the absolute path.

Your first steps with SU2

OK, so SU2 is installed on your machine and you are ready to launch it. Where should you start? I would follow the quick start guide, it walks you through the entire workflow of a simple simulation and you get the hang of SU2 pretty quickly.

You’ll see that you have 2 files, one config file and one mesh file, and with these, you control the entire simulation. Open up the config file and start playing around with some of the parameters. It will depend on your confidence level in CFD and how much you want to experiment with these parameters. This is the part I enjoyed most in my first week with SU2.

After that, I would recommend stopping by the tutorial sections. It has a detailed write up for all tutorials and it provides some additional explanations that you would otherwise miss. I’ve learned quite a bit by just browsing through some of them. You also get a pretty good idea of what is possible.

After you have gone through the quick start guide and some tutorials, try to set up some simulations yourself. Get a mesh in either the native *.su2 or portable *.cgns format and set up your case. Play around with the schemes, Riemann solvers, boundary conditions, and other settings to improve your simulation results.

The learning curve is really not that steep, and I feel pretty comfortable running simulations after a week. Sure, I don’t feel at home just yet in the config file and still need to scroll a bit, but I have a feeling that I understand what this solver can do and how I can set it up myself. I’m sure you’ll find it easy to use, too!

Outlook

I am really excited about SU2. After playing with some of the tutorial cases, I felt comfortable setting up my own cases in no time. The multigrid works really well and I have seen it perform its magic for a few cases. In addition, the CFL ramping was a treat to explore, something which is implemented in other solvers (Fluent, OpenFOAM) but I have never seen working as expected. SU2 does seem to have an implementation that actually speeds up the computation!

I have only really scratched the surface here; I feel there is a lot more to cover, and I will need some more time to learn the advanced components. But looking at some of the more advanced tutorials, I can’t really see a steep increase in the learning curve. Adding multiphysics components to your simulation is as complicated as adding one additional config file.

I was rather excited about the epistemic uncertainty quantification option. I have only seen results for what is published on their tutorial page, but these are enough for me to want to explore this feature further. Uncertainty quantification of any kind is heavily underrepresented in CFD solvers, and having a baked-in solution is rare but a good step to tackle uncertainties.

The adjoint shape optimisation is also something to explore further. Again, I have seen only the results from their tutorial page, but I first learned about SU2 when people praised its adjoint optimisation capabilities. Adjoint optimisation is all the rage in industries around me, so I probably ought to give it a closer look to know what they are all talking about.

Are you an aerospace engineer interested in flutter or aeroelasticity, all within one solver? SU2 got you covered! I would love to see the multiple-material option pushed to support composites or even sandwich structures! For that, we would need support for anisotropic material properties (which are seemingly not supported at the time of writing), which would give SU2 a competitive advantage over even commercial fluid-structure interaction solutions.

There is a lot to love about SU2, and most of that, for me anyway, is coming from years of abuse by OpenFOAM. The OpenFOAM developers don’t care about you unless you pay them a hefty consultancy sum. SU2 is open-source and driven by academics with purer intentions at heart, and it shows by the love and attention to detail they have put into their homepage, documentation, and tutorials.

The programming side, however, is something which I will shy away from, for the moment at least. The code structure (if there is one to begin with!) is not very readable and classes that have 10,000 lines of code are just pure signs of code smell. I would love to implement some of my own algorithms, but I don’t think I will have the time to learn SU2’s particular (lack of) code structure.

The lack of unit testing and heavy focus on system tests alone was also something which has raised some alarm bells. I’ll probably have to expect some surprises if I continue to use SU2. I hope software quality control will be on the agenda at some point as well!

On the other hand, compilation of SU2 was pretty straightforward, fast, and user-friendly. All you need is a terminal with python support, and you are good to go. You can bring in additional dependencies, such as the CGNS format, or MPI, but SU2 works out of the box without any dependencies. At least they got this design right!

I’ll definitely have to test it further in the future to see how it holds up against some of my more complex test cases. In the end, it is not difficult to write a solver that works for a NACA 0012 airfoil, but applying that to more complex cases is always an entirely different story. But I am optimistic that what I have seen will translate to more realistic flow problems. And who knows, perhaps we will need to have a closer look at SU2 in the future again!


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.