Every industry is trying to find new ways to improve performance, maximise productivity and increase efficiency. To achieve this, engineers, scientists and programmers are tasked with solving optimisation problems.
The conventional way to optimise something in engineering is to change an input (typically a geometric parameter) and analyse its effect on the output (what we are trying to optimise). This process is repeated in a loop until the optimum design is achieved. In the world of CFD, engineers calculate the flow around an object, modify the object and then recalculate the flow to analyse the effects of the change. However, this approach involves many iterations which can be time consuming and expensive.
A more efficient way to solve optimisation problems is to use the adjoint method. This is a technique which identifies what changes are required to the input to achieve the desired effect on the output. So instead of each CFD calculation predicting how a single design change influences every aspect of the flow, the adjoint method predicts how every design change influences a single aspect of the flow.
“Ultimately, if you know how physics works, then you can predict what’s going to happen. If I drop a cup off a table, I know it’s going to fall off because I understand how gravity works, at least in an approximate manner. That’s what the adjoint method is. Instead of telling you what’s going to happen, the adjoint method tells you how to change the input to achieve a unit change in the output. So if you don’t want the cup to fall, the adjoint would tell you not to push it off the table.”
Eugene de Villiers, Managing Director at ENGYS
How It Works
The adjoint method is essentially a very efficient way of calculating the gradient (first derivative) of a function, and this can be applied to great advantage to perform automatic design optimisation. Adjoint offers a much faster and flexible alternative to calculate the gradient of a function than other more traditional methods such as finite difference.
For example, consider a cost function g(p) where g is what we want to optimise and p represents the parameters we can change. Essentially, to optimise g, we want to choose the right values of p that will achieve a desired result of g.
By calculating the gradient of g with respect to p (dg/dp) we can establish the search direction, or sensitivity of the cost function. This can then be used in combination with a gradient-based type optimisation algorithm to identify a new point, where the gradient is calculated again to work out the next search direction. This process is repeated until the algorithm finds the maximum or minimum of the function where the optimum solution resides.
Assume we have a simple airfoil and we want to find out the combination of camber and angle of attack (AoA) that results in the maximum lift/drag ratio, thus offering the best possible performance that the airfoil can deliver. We identify the camber and AoA as the inputs of our optimisation problem that can be modified and the lift/drag ratio as the output that needs to be optimised.
One typical way of doing this would be to rely on trial and error by changing the camber and AoA multiple times, analysing how these changes affect the lift/drag ratio, and identifying the one airfoil with the maximum lift/drag from the pool of all designs which have been evaluated. However, this approach is slow and inaccurate because the quality of the final design will depend strongly on the total number of designs evaluated, and there will never be any guarantees that the final airfoil is indeed the best possible design within the given range of input parameters.
A more formal approach to optimise the airfoil involves the use of gradient-based optimisation, where the lift/drag ratio is defined as a mathematical function of the inputs, i.e. camber and AoA. The algorithm relies on knowing the value of the output function and its gradients for any given combination of camber and AoA. In the picture below, we start by evaluating an initial airfoil design with camber of 7% and AoA of 6 deg at point f1. Calculating the value and the gradients of the output function at this point reveals the search direction we must pursue to maximise the lift/drag ratio. This leads to a new design at f2 a short distance away from f1, and this process is repeated N times until the value of the lift/drag ratio no longer increases, at which point the maximum of the output function has been found. This happens at fN in our example, where the airfoil with the maximum lift/drag ratio has a camber of 1% and AoA of 4 deg.
The optimisation process based on the gradient-based algorithm described above provides the best design solution using a limited number of design evaluations in comparison to the less reliable trial and error approach. The discovery of the optimum design only requires N iterations, instead of having to evaluate every possible combination of input parameters. However, for the gradient-based algorithm to work, we must be able to calculate the value of the cost function and its first derivative. The value of the lift/drag ratio in our airfoil example can be easily extracted from the results of the CFD model; the gradients of the output function, on the other hand, can be approximated using either finite difference or the adjoint method.
Where the gradients are calculated through finite difference, the “difference quotient” defined below is taken to the limit as h approaches 0 to give the first derivative of the function:
This can be simplified as follows when using discrete values in CFD:
The finite difference approach to calculate gradients is relatively efficient when there are only one or two input parameters that can change, as it is in the case of our airfoil example. However, if there are many input parameters, each gradient calculation will require many CFD computations, which in turn can be very slow and expensive. To put things in perspective, if n represents the number of input parameters, then using finite difference will require n+1 CFD simulations to calculate the gradients for a single design evaluation. If the gradient-based algorithm requires N design evaluations to find the optimal design, then the entire optimisation process will need N·(n+1) CFD simulations to complete.
A much more efficient way to calculate the gradients is to use the adjoint equations. In this way, the same gradient-based optimisation approach can be taken, but each design evaluation only requires two calculations:
1) the value of lift/drag, which we get straight from the standard CFD solution; and
2) the adjoint calculation to work out the gradients, which we get from solving the additional adjoint equations.
The adjoint method can be used to calculate the gradients of the output function quickly and reliably regardless of the number of input parameters involved.
‘If I have a duct and I only have one parameter to change such as the radius, then the cost of the adjoint is the same as the cost of finite difference which is two calculations,’ explains de Villiers. ‘But imagine I have 100 or 1000 parameters that can change. If I want to calculate the gradient for each parameter through finite difference, then the cost will be 100 or 1,000 additional calculations. The cost for the adjoint method is always only one additional calculation, because adjoint gets the gradients by propagating the required information through the computational system in reverse. This means you can explore a much wider design space with a low fixed cost relative to traditional methods which can be hundreds or even thousands of times faster, depending on the complexity of the design and the number of parameters being optimised.’
- For a more detailed walk through of the above example, check out this video from Dr. Matthew Juniper
The adjoint equations are linear differential equations which relate the desired change in output to the required change in inputs. In the context of CFD, the primal equations are the Navier-Stokes system and the corresponding adjoint equations can be derived accordingly by integration by parts, as described in the following video.
Video: Continuous adjoint equations overview
Continuous Adjoint and Discrete Adjoint
The continuous adjoint approach is where the adjoint equations are derived from the primal equations before being discretised and solved. Whereas, the discrete adjoint method discretises the primal equations first, and then (often via automatic numerical differentiation tools) generates the discrete adjoint system directly from the discretised primal system of equations.
‘Essentially, continuous adjoint is the mathematical way and discrete adjoint is the numerical way,’ highlights de Villiers. ‘For a long time we were the first adjoint commercial offering on the market, and we specialise in continuous adjoint. Our competitors later came out with discrete adjoint as it was seen as more general. However, discrete adjoint is less stable and not very flexible so now companies are switching back to continuous adjoint as it gives you more options.’
A History of Adjoint
There is a long history associated to the application of the adjoint method in design optimisation, but the first use of the adjoint equations on optimal design in fluid mechanics is generally attributed to Prof. Oliver Pironneau (1974). Later on, Prof. Antony Jameson et.al. published a series of papers starting in the late 1980’s that pioneered the use of the adjoint equations in the field of CFD for aeronautical applications, including adjoint solutions for potential flow, the Euler equations and the Navier-Stokes equations. A number of other research groups followed this trend during the late 1990’s and early 2000’s to develop various prototypes of adjoint CFD codes for optimisation.
In 2005, Dr. Carsten Othmer, a researcher at Volkswagen, wanted to implement the adjoint method for automotive applications to assess whether it could be used to improve the aerodynamic performance of cars. The implementation work was completed by the founders of ENGYS, and after several years of developments and improvements the HELYX-Adjoint add-on module was launched by ENGYS in 2010 to complement the company’s CFD software tools HELYX and ELEMENTS.
The capabilities of HELYX-Adjoint have been developed further through a variety of projects and work with the Volkswagen group to include topology and shape optimisation engines capable of modifying the original geometry automatically in search of an optimal design, as part of the adjoint CFD computation.
‘We specialise in improving external aerodynamics and this led to the development of our external DES solver,’ highlights de Villiers. ‘It provides the most accurate and consistent results for aerodynamics forces, and we found a way to use adjoint in this context which nobody had figured out at the time.’
How Can Adjoint Improve Performance?
The adjoint method can solve any optimisation problem where a set of inputs directly affect the output, whether that involves reducing the drag of a vehicle, refining the topology of an internal duct or increasing the cooling capacity of a battery.
‘When performance and efficiency matters, the value of adjoint is very high,’ explains de Villiers. ‘Its fundamental principles mean that adjoint gives you the optimum performing solution to the problem, whilst using resources in the most efficient way. You don’t need to be an expert, conduct hundreds of experiments, or think outside the box. Adjoint will solve it for you quickly and efficiently and that’s its real benefit.’
However, implementing the adjoint method requires expanding the way companies currently design and develop parts. Instead of having a group of designers and then a group of analysts, adjoint requires engineers to be both. The constraints and operational parameters still need to be specified as a designer, but the result is a fully optimised design, the performance of which then needs to be analysed.
‘It is not a small change like changing a coefficient,’ says de Villiers. ‘It requires a completely new workflow and chain of responsibility. Currently, a lot of design is reactive, whereas adjoint is very proactive,’ continues de Villiers.
‘By reaching the optimum solution faster and more efficiently, it can save companies a huge amount of time, effort and money. The challenge is to convince companies to disrupt their systems in the short term to benefit from the impressive capabilities of adjoint in the long term.’