algorithmic differentiation of general purpose cfd code

1 downloads 0 Views 444KB Size Report
of algorithmic differentiation in a general purpose CFD code. We also ..... In order to have the chain rule of differentiation implemented systematically through-.
European Congress on Computational Methods in Applied Sciences and Engineering ECCOMAS 2004 P. Neittaanm¨ aki, T. Rossi, K. Majava, and O. Pironneau (eds.) I. Lasiecka (assoc. ed.) Jyv¨ askyl¨ a, 24–28 July 2004

ALGORITHMIC DIFFERENTIATION OF GENERAL PURPOSE CFD CODE: IMPLEMENTATION AND VERIFICATION Aleksandar Jemcov! and Sanjay Mathur† ! Development

Department, Fluent Inc. 10 Cavendish Court, Centerra Resource Park, Lebanon, NH, 03766, USA e-mail: [email protected], web page: http://www.fluent.com Development Department, Fluent Inc. 10 Cavendish Court, Centerra Resource Park, Lebanon, NH, 03766, USA e-mail: [email protected]

Key words: CFD, Algorithmic Differentiation, Sensitivity, Tangent Code Abstract. This paper describes the implementation of algorithmic differentiation in a general purpose CFD code for calculation of forward sensitivities with respect to input parameters. In addition, new techniques for tangent code verification that use special properties of non-dimensional forms of inviscid compressible equations and thermodynamic relationships are presented. Results of calculation of the forward sensitivities with respect to boundary conditions for the compressible inviscid flow over airfoil are presented as an illustration of the general applicability of the newly developed framework.

1

A. Jemcov, S. Mathur

1

INTRODUCTION

The use of numerical methods for fluid flow and related phenomena is now routine in many industries. A variety of methods have been developed for computing solutions for specific geometries and boundary conditions. Such analyses are of great benefit in any design cycle and can substantially reduce the need for experimental evaluation of prototypes. However, the ultimate goal of a typical industrial design optimization cycle is not just to evaluate the performance of specific configurations but rather it is to find the optimal values of certain controlling parameters (controls) that will minimize or maximize specific performance measures. In aerodynamics, for example, the design goals include minimal drag, maximal lift [1, 2, 3, 4, 5, 6, 7], and prescribed pressure drop [8]. Many other quantitative measures of performance can be formulated in other engineering disciplines [9, 10]. The controls can include device geometries, operating conditions and material properties. The implementation of design optimization algorithms for such devices requires estimation of accurate directional derivatives of model outputs with respect to model inputs in addition to the calculation of performance measures for specific configurations. Other areas that require knowledge of directional derivatives include parameter estimation [11], uncertainty propagation [12, 13] and sensitivity analysis [14, 15]. These new areas are of great interest in modern engineering analysis because they offer guidance in analysis and additional information that is not usually available from the raw computational data. Questions regarding the sensitivity of the particular computational outputs with respect to certain parameters or the impact of the lack of precise knowledge of input data on computed performance of the device are very important in making certain design decisions. Furthermore, the ability to compute nearby solutions by extrapolation from a base solution for small parameter changes has a great value in understanding the operation of the device in practice since no device maintains exact values of parameters in reality. Additionally, derivatives are needed for linearization of nonlinear equations and expressions and for error analysis [16] in the course of approximating problems described by nonlinear partial differential and algebraic equations. Several techniques for computation of derivatives have been devised. Traditionally, symbolic differentiation and numerical differentiation have been widely used; lately algorithmic differentiation has emerged as an efficient and accurate alternative to traditional approaches [17, 18, 19]. Some of the problems with symbolic differentiation approach include lengthy expressions due to its analytical nature, implementation that requires nontrivial modifications to the code and limitations with respect to the choice of independent variables. Difficulties associated with numerical differentiation are related to problems with truncation errors of associated divided differences and the cost of directional derivative evaluation [5, 6, 18, 19]. Algorithmic differentiation in forward and reverse mode offers significant advantages over these traditional methods due to its non-intrusive implementation and absence of truncation errors. Furthermore, with algorithmic differentiation, the efficiency of the forward derivative evaluation is linear in the number of

2

A. Jemcov, S. Mathur

independent variables with a constant of proportionality that is less than 1. For reverse mode it can be shown to be bounded in terms of number of floating point operations with the bound being independent of the number of variables [18]. Algorithmic differentiation is usually accomplished by tools such as ADIFOR [20] which parse the computer code that implements a numerical solution method and generate new code that has additional statements inserted to allow the simultaneous evaluation of the derivatives. In this paper, we describe an alternative approach that uses the operator overloading and template features of the C++ programming language to achieve similar results. In the next section, we first describe the concept of the derivative and the general principles behind algorithmic differentiation. This is followed by a description of the current approach and comparisons with other approaches. In the following section we describe some innovative ideas, based on the known non-dimensional characteristics of the problem, that can be used to verify, in a non-trivial manner, the implementation of algorithmic differentiation in a general purpose CFD code. We also present some illustrative examples of the calculated derivatives. 2

ALGORITHMIC DIFFERENTIATION

If f : x → y, y ∈ Rm is a vector valued function of a vector valued variable x ∈ R n , then the derivative of this function in the direction of vector r ∈ R n is ! d !! δr (f ) = f (x + hr(x)) (1) dh !h=0 Since f is a vector valued function of vector argument x, the directional derivative can be written in the following form: δr (f ) = J · r (2)

where J is a m × n Jacobian matrix   J =

∂y1 ∂x1

.. .

∂ym ∂x1

···

∂y1 ∂xn

···

∂ym ∂xn

With this notation, the directional derivative can be    δr (y1 )    .. =J ·   . δr (ym )

m×1

  

(3)

m×n

written as  e1 ..  . 

en

(4)

n×1

where ei is the i-th component of the direction vector r = (e1 , e2 , . . . , en ). An example of a vector valued function f in CFD applications is the force experienced by a solid body in fluid flow. In this case the components of the force vector in the 3

A. Jemcov, S. Mathur

spatial coordinate directions will be the yi components of the vector function f . The vector function f does not have to be made up of homogeneous components yi , however. In general it can contain any components that are of importance in the application. For example, if heat transfer is being modeled, then f can contain a component that represents heat flux on a particular boundary in addition to the force on that or some other boundary. This view of the vector function f is of great importance in algorithmic differentiation when the whole code that implements the solution algorithm for the problem at hand can be viewed as a composition of elementary functions that evaluate the vector function f . Any physical problem in general depends on a set of input parameters that uniquely determine a particular solution. This set forms the basis of the space for the vector x. In CFD applications, the input parameters include physical quantities such as pressure, temperature, mass flow rates, species concentrations etc. at boundaries and interior of the computational domain that are needed in order to define a well posed problem. The device geometry and material properties are also input parameters. For a numerical method, the inputs do not have to be limited to physical quantities. Solution control parameters such as CFL number, underrelaxation factors and any empirical model constants etc. are all included in the list of input parameters. For the specific case of the Euler equation based model considered later, the basis of this space can be selected to be: x = (p∞ , M∞ , T∞ , α, C, R)

(5)

Here C is the CFL number, α is the angle of attack, R is the gas constant and subscript “∞” is used to denote far field values of pressure, Mach number and temperature. One particular selection of control parameters fully defines a CFD model. This selection can be thought of as a point in the space x. Analogous to the control space, we can define a tangent control space for our problem by selecting the following unit vectors to form the basis of the space: δx = (δp∞ , δM∞ , δT∞ , δα, δC, δR)

(6)

We can define the derivative of the vector function f along any direction r that is formed by a linear combination of the basis vectors of this tangent space r=

n .

βi δxi

(7)

i=1

Here δxi are components of vector δx in a particular coordinate direction and βi is the coefficient along that direction. It is clear from Equation (7) that the direction r can be chosen arbitrarily by selecting different coefficients βi and if the directional derivative is desired in some other directions, repeated application of the scalar product between Jacobian matrix and each new direction vector is needed. In general, this can be written in a matrix notation by allowing vector r 4

A. Jemcov, S. Mathur

to become a matrix R of directions with dimension n × l where l corresponds of directions that are used for evaluation of directional derivatives    ∂y1   (1) ∂y1 (l) · · · δr(1) (y1 ) · · · δr(l) (y1 ) e1 · · · e1 ∂x1 ∂xn      .. .. .. .. =  ...     . . . . δr(1) (ym ) · · · δr(l) (ym )

m×l

∂ym ∂x1

···

∂ym ∂xn

m×n

(1) en

···

(l) en

to number   

(8)

n×l

In order to perform operations in Equation (4) or (8), the Jacobian matrix J must be available. Therefore, components ∂yi /∂xj must be calculated somehow. If the function is known analytically, in principle it is very easy to obtain the derivatives by hand or by the use of symbolic differentiation tools. This works well for functions that are known explicitly and that are not too complicated [17, 18]. If the function is defined implicitly through some expression that involves differential operators, use of symbolic differentiation is limited and it will usually require numerical evaluation. In this case differentiation is performed as a separate step that yields analytical expressions for derivatives that will have to be incorporated in numerical codes through separate code segments [6]. Furthermore, some degree of human intervention is needed in order to produce efficient code because expressions obtained by analytical differentiation may not be suitable for direct code implementation. In spite of these shortcomings, analytical differentiation can be of great help in linearization of different expressions and if good care is taken to obtain efficient implementation of derivatives, this approach may result in good performance and flexibility. Another possible way of obtaining the directional derivatives is the use of divided differences in accordance to central difference approximation of Equation (1): f (x + hr) − f (x − hr) (9) h→0 2h In this approach the Jacobian J is not obtained directly, instead the vector function f is evaluated for two values of vector argument x and then the divided difference is evaluated from Equation (9). The downside of this approach is that two additional function evaluations are needed to form the divided difference and if the function f is nonlinear and numerically stiff, this can be quite expensive. Furthermore, if step h is not chosen carefully, the resulting directional derivative may suffer from large truncation errors thus decreasing the accuracy of the computations [6, 17, 18]. Too small a step size also presents a problem because of round-off errors. It is possible to minimize the impact of the choice of the step h by using a complex variables approach [6] wherein all variables in the code are specified to be complex numbers. In this approach, second order accuracy of directional derivatives can be maintained irrespective of the chosen step h. An alternative to traditional approaches for calculating the derivatives is the use of algorithmic differentiation [5, 6, 17, 18, 19] The main idea of algorithmic differentiation is to view the computer program that implements the solution process as a set of elementary functions that are executed in a certain order. Assuming the differentiability of all δr (f ) ≈ lim

5

A. Jemcov, S. Mathur

elementary functions, the systematic application of the chain rule of differentiation on all elementary functions produces the desired derivatives without the truncation errors that are inherent in other approaches. As an illustration, consider a scalar valued function f ∈ R of vector argument x ∈ R 2 : y = f (x1 , x2 ) The Jacobian J associated with this function is 0 / ∂y ∂y J = ∂x1 ∂x2

(10)

1×2

The corresponding directional derivative is given by 1 2 e1 δr (f ) = J · e2 2×1

(11)

(12)

More complex functions that appear in CFD and numerical codes in general can be directionally differentiated in this way if we adopt the notion of elemental functions. If function f is a composition of two functions f (g(x)) = y(z(x1 , x2 )) then the chain rule of differentiation will consist of the two following steps: ∂z ∂z e1 + e2 ∂x1 ∂x2 ∂f δr (f ) = δr (g) ∂g δr (g) =

(13)

In this case we have two elemental functions f and g and we can see that directional derivatives can be propagated forward if Jacobians Jf,g = ∂f /∂g, and Jz,x = ∂z/∂x are known during calculations. It is possible to generalize this notation to large compositions of elemental functions f (((. . . (fi (fj )) . . .))), (i = 1, n ; j = 0, n − 1) by introducing elemental Jacobians Ji,j = ∂fi /∂fj : f = fn ◦ fn−1 ◦ · · · ◦ f2 ◦ f1 ◦ f0 δr (f ) = Jn,n−1 Jn−1,n−2 · · · J1,0 δr (f0 )

(14)

In this manner, directional derivatives of very complex compositions can be obtained in the same way that the directional derivative of a simple function is obtained in Equation (13). An important observation about the function and its directional derivative is that the directional derivative can be evaluated at the same time as the function is evaluated. This suggests that in the code that implements the function evaluation, additional lines of code that correspond to Equation (14) need to be inserted in order to evaluate the function and its directional derivative at the same time. A computer code that implement a CFD solution algorithm can be thought of as a large composition of elemental functions [18, 19]. In the so called forward mode of directional 6

A. Jemcov, S. Mathur

differentiation we start by initializing the derivative δr (f0 ) to an appropriate value that describes the particular direction r and we evaluate all subsequent directional derivatives δr (fi ) together with the values of the elemental functions fj . In the reverse mode we start with proper initialization of the derivative of the function fn that corresponds to the final result of function evaluation f = f0 ◦f1 ◦f3 · · ·◦fn in forward mode and then we propagate directional derivatives of this quantity with respect to intermediate results in reverse order [17, 18]. The approach developed for differentiating the scalar valued function f by evaluating elemental function values together with their derivatives can be generalized to vector valued function f by extending the notation of elemental functions in Equation (14) to vector valued elemental functions and corresponding directional derivatives. The key element of forward differentiation of codes is the augmentation of existing codes with statements that implement derivative evaluations. In the past, this code insertion was achieved by code translation tools, which parse a given code and generate new code by inserting appropriate statements and storage such that both the original variables and their derivatives are computed for each statement of the original code [20, 21]. This obviously requires sophisticated code parsing capabilities and is prone to error if unorthodox coding styles are used. 2.1

Implementation using C++

Modern programming languages offer an alternative approach to augmenting the code through high level language constructs. In C++, for example, new data types can be defined using classes or structs. Through the concept of overloading we can define binary arithmetic operations as well as standard mathematical operations for these new data types. Finally, the idea of templates can be used to write generic code that can be specialized by the compiler for different data types. Using these ingredients it is possible to implement algorithmic differentiation in a very easy and general manner, without the use of external parsers but with the same end results. In the present implementation we define a new fundamental type as a class that has for its private data two floating point numbers. The first component of a variable of this new type represents the usual value the variable would have in a normal code while the second component represents the derivative of this value in the direction of differentiation. The binary arithmetic operations for variables of this class are defined so that the first component of the result contains the usual result of the binary operation between the first components of the operands. The second component of the result is evaluated using the chain rule such that it will contain the derivative of the result, also in the direction of differentiation. Similarly, all the exponential and trigonometric functions are defined for this new class to yield the analytical derivative of the function in the second component of the result. All the numerical functions of the code are written as templates with an arbitrary type T instead of a floating point type. When these templated functions are instantiated by specifying T to be float, we get an executable code that is identical to the normal code 7

A. Jemcov, S. Mathur

that is capable of computing the solution. However, the same template can be instantiated using the new class as T and in this case, the executable we obtain is identical to the one that would be produced by a differentiation tool such as ADIFOR [20]. In this version all derivatives are propagated together with the values of elementary functions, constraining the derivative evaluation to stay tangent to the path that is defined by the values of all elementary functions. The resulting code will effectively have the derivative inserted in the code for each elementary function defining the so called tangent code. In contrast to the standard tools for algorithmic differentiation, this insertion is performed as template instantiation by the compiler itself, obviating the need for a separate parser. Both the normal code as well as the derivative computing code are produced from the same template. This eliminates the need to maintain separate codes. Also, this approach can work with all the normal programming idioms such as the use of pointers, references, aliases etc. Another advantage of this approach is that once such a framework is in place, it can be exploited to create other versions of the code, for example, using interval or complex arithmetic. In order to have the chain rule of differentiation implemented systematically throughout the code, we must address the issue of boolean and relational operators in addition to the binary operations and library functions. One example of such an operation occurs in calculation of convective fluxes, which typically use some form of upwinding based on the signs of characteristics. In such cases, we must ensure that the derivative code stays tangent to the original code, including the branching based on characteristics. Further requirements include proper handling of non-smooth functions that are Lipschitz continuous by considering them to be piecewise continuous [18]. In our C++ implementation such issues are handled using the traits mechanism [22] which allows compile time specification of the exact behavior of code in such situations, depending upon the variable type the code is being instantiated for. We use similar mechanisms to redefine concepts such as residual norms and convergence criteria. 2.2

Comparison of differentiation methodologies

The different approaches for calculating derivatives discussed in previous section have their own merits and demerits. In this section we evaluate them from the accuracy, implementation and efficiency points of view. There are several possible sources of errors in derivative calculation. As discussed above, the method of divided differences suffers from a step size dependence. For large step sizes, the truncation error increases but if the step size is decreased too much, the calculation will be polluted by cancellation errors due to finite floating point precision. The complex variable approach avoids this problem but truncation error is still present. Analytical differentiation does not suffer from truncation errors since all derivatives are exact at continuous level. However, these analytical expressions still have to be discretized since all functions in general are defined implicitly through PDEs and this will introduce discretization errors. A more serious problem with this approach is the inconsistency of 8

A. Jemcov, S. Mathur

the derivatives with respect to the discretization that is used to obtain numerical values. This is because in general the operations of differentiation and discretization do not commute if non-smooth functions are used to facilitate numerical solutions. Examples of non-smooth functions include limiter functions that are introduced in the discretization scheme in order to maintain stability of computations. Algorithmic differentiation, whether implemented by external tools or using C++ as in the present work, avoids the problem of consistency of derivatives even when limiter functions are present because these functions are implemented in the code by elemental functions that are directionally differentiable [18]. Discretization error is unavoidable even in this approach since discretized forms of the original functions are used to obtain derivatives but the results of differentiation will be free of truncation errors. From the implementation point of view, finite difference representation is the easiest one to use since the CFD code can be considered as a black box and only input parameters have to be perturbed in order to obtain derivatives. The complex variable approach requires some code modification because all variables must be promoted to complex type and all intrinsic functions in mathematical library must be treated as complex functions. Use of complex numbers does create a problem with Boolean operations, for example those used in implementing a upwind scheme and this issue must be handled appropriately. Derivative calculations using analytical representations will require discretization and solution of the derivative equations. This may be straightforward if the derivative equations are not so different from the original equations. For more complex equations, the equations may contain extra terms with different mathematical characteristics and specialized treatment may be required. Boundary conditions also need to be formulated for the derivative equations. The main problem with this approach is that every new derivative requires its own equation and this is not very practical for general purpose CFD codes. If the requirement is to be able to evaluate derivatives of practically any output quantity with respect to any input quantity and if we wish to have an implementation with minimal impact on the overall code structure, then the only alternative is algorithmic differentiation. The generality of the C++ based approach outlined above allows for very flexible implementation through the introduction of a new type that will compute values and derivatives of the expressions at the same time. Another alternative is to use code transformation tools [20, 21] for augmenting the code to calculate derivatives. However, these tools have not progressed to the point when they can be used with languages such as C++ that requires high level of programming abstraction and the definition of the new type seem to be the best alternative for general purpose CFD codes. The efficiency of different methodologies can be measured in terms of work ratio q(f ), defined as the ratio between the number of arithmetic operations required to evaluate the function and the derivative and that required to evaluate the function alone q(f ) =

work(f , δr (f )) work(f ) 9

(15)

A. Jemcov, S. Mathur

In general, the theoretical work ratio for any forward differentiation method is q(f ) = 1 + cn

(16)

where c is a positive constant that can be obtained empirically and n is the number of independent variables in differentiation [18, 19]. For the methods of divided differences and analytical differentiation, the constant c is very close to 1 and for algorithmic differentiation it ranges between 0.2 and 1 depending on efficiency of implementation. It is obvious that the work ratio for forward differentiation grows linearly with the number of independent variables. The only way to keep the work ratio independent of the number of variables is to use the reverse mode of differentiation. In that case it can be shown that the upper bound of work ratio is 5 but the memory requirements increase substantially making this approach impractical for large problems. Work ratio is a good indicator of the efficiency of the implementation but in CFD and especially in the context of design optimization, we are often interested only in steady state solutions. In such cases there is no need to carry derivative calculations from the beginning. Instead, the steady state solution is usually obtained first and only then the derivatives are evaluated. The advantage of this approach is in the fact that once a converged solution is obtained, it takes much fewer iterations to obtain derivatives since the tangent problem is linear by its nature. 3

VERIFICATION

Verification of a derivative calculation implementation is a challenging task. To verify a CFD code one can compare the solutions obtained numerically with known analytical solutions. Typically this is only possible for very simplified geometries. For more complex configurations, the only recourse is comparison with experimental data. However, derivatives are usually not very easy to obtain analytically, even for the simple cases where the solution might be known and they are certainly not available from experimental data. Therefore some indirect means must be used to verify the derivative calculation procedure. An obvious approach is to use the derivatives to extrapolate nearby solutions and then compare them with the results of direct computation of the nonlinear state. This approach is straightforward and offers a quantitative measure of the accuracy of derivative calculations. However, it suffers from the same issues that were discussed above for the divided differences approach in that the calculations are dependent on the increments of the independent parameters. In this approach, we are not verifying the accuracy of the derivatives per se, but instead we are verifying the accuracy of the extrapolation process. Since this will inevitably involve truncation errors, it is difficult using this process to verify the correctness of the derivative calculation by itself. To overcome the difficulties mentioned above, we have devised a couple of alternative approaches to verify the derivative calculations directly. The first idea involves choosing the direction r such that some specific property of the directional derivative is preserved throughout the calculations. Here the physical relationship among dependent variables 10

A. Jemcov, S. Mathur

is exploited to produce known values of derivatives. In the second approach fundamental properties of the non-dimensional form of the governing equations are used to test the implementation of the derivative calculations. In this section we present details of both approaches but we begin with a verification using linear extrapolation. 3.1

Verification using extrapolation based on tangent linear model

We use the solution of external inviscid transonic flow over NACA 0012 airfoil for this exercise. The computational domain consists of far field pressure boundaries and inviscid airfoil discretized by C-like unstructured mesh with quadrilateral cells as shown on Figure 1. The flow is governed by Euler equations

(a) Airfoil far field

(b) Airfoil near field

Figure 1: Discretization of the computational domain for NACA 0012 airfoil in inviscid transonic flow

∂Q ∂E + + ∂t ∂x where Q is is the vector of conserved variables  ρ  ρu Q=  ρv ρe0

∂F =0 ∂y    

and E and F are vectors of inviscid fluxes    ρu ρv  ρu2 + p   ρuv   E=  ρuv  , F =  ρv 2 + p ρuh0 ρvh0 11

(17)

   

A. Jemcov, S. Mathur

and u, v, p, e0 , h0 are Cartesian components of velocity, static pressure, total energy and total enthalpy, respectively. The Euler equation is supplemented by the no flux boundary condition on the airfoil surface and far field boundary condition is specified on inflow and outflow boundaries. The solution to the baseline problem is obtained for an angle of attack α = 0o , free stream Mach number M = 0.7, far field pressure p∞ = 57342.6 P a and ambient temperature T = 300o K. The corresponding pressure distribution is shown in Figure 2. If

7.25e+04 7.00e+04 6.75e+04 6.50e+04

p, AOA=0

6.25e+04

Static Pressure (pascal)

6.00e+04 5.75e+04 5.50e+04 5.25e+04 5.00e+04 4.75e+04 0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

Position (m)

Figure 2: Pressure distribution over NACA 0012 at α = 0o , and M = 0.7

the directional derivative of pressure p = f (Q(α)) is calculated with respect to angle of attack, then it is possible to extrapolate solutions corresponding to angles of attack in the neighborhood of α0 = 0o using the following expression: p(Q(α)) = p(Q(α0 )) + (α − α0 )Jp,Q JQ,αδα

(18)

Here directional derivatives were taken in the direction r = δα with coefficient of direction βα = 1. Rules of directional differentiation of composition function are used in Equation (18) in accordance with Equation (14) where elemental Jacobians are given by Jp,Q = ∂p/∂Q and JQ,α = ∂Q/∂α. The extrapolated value of pressure distribution over airfoil for α = 0.1o is shown in Figure 3 and the relative error between calculated and extrapolated solution at α = 0.1o is shown in Figure 4 It can be easily seen that the maximum relative error for the change of (α = 0.1o is &max = 0.15%. Reducing the increment of the angle of attack reduces the corresponding 12

A. Jemcov, S. Mathur

7.25e+04

7.25e+04

7.00e+04

7.00e+04

6.75e+04

6.75e+04

6.50e+04

6.50e+04

Static Pressure (pascal)

p

p

6.25e+04

6.25e+04

6.00e+04

Static Pressure (pascal)

5.75e+04 5.50e+04

6.00e+04 5.75e+04 5.50e+04

5.25e+04

5.25e+04

5.00e+04

5.00e+04

4.75e+04

4.75e+04 4.50e+04

4.50e+04 0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

1

0

0.1

0.2

0.3

Position (m)

0.4

0.5

0.6

0.7

0.8

0.9

1

Position (m)

(a) Extrapolated pressure

(b) Calculated pressure

Figure 3: Comparison of calculated and extrapolated pressure distributions over NACA 0012 for α = 0.1 o and M = 0.7

1.20e-03

1.00e-03 relative error 8.00e-04

error

6.00e-04

4.00e-04

2.00e-04

0.00e+00 0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

1

Position (m)

Figure 4: Relative error between extrapolated and calculated solutions at α = 0.1 o , and M = 0.7

13

A. Jemcov, S. Mathur

maximum relative error. While this exercise is useful in verifying the derivative calculations, practical use of solution extrapolation is limited because of truncation errors. However, the derivative field can offer a greater insight into the physics of the problem. It can also be very useful for the calculations of better initial guesses for new nonlinear solutions with modified input parameters. 3.2

Verification by selection of particular directions

From the definition of the directional derivative in Equation (4), it is clear that there are no limitations on the way that the direction r is chosen. Thus derivative in any arbitrary direction can be evaluated. This particular property of directional derivatives can be used to verify an implementation of algorithmic differentiation by evaluating derivatives in certain directions for which the derivative of function f that is known analytically. In the case of inviscid flows, the relationship among primitive variables in vector Q of conserved variables can used to determine such a direction r. For example consider the density field. Just as we evaluated the derivative of pressure field with respect to the inlet angle of attack, we can compute the derivative of the density field with respect to the inlet pressure, p∞ , or inlet temperature T∞ . These two derivatives can be independently evaluated and this would correspond to choosing r to be along the directions of the inlet pressure or temperature. In terms of the C++ implementation described above this would mean that either the second component of the inlet pressure or that of the inlet temperature is set to unity while all the other input parameters have a zero second component However, as we noted above, we can choose a direction which is a linear combination of these two directions, say r = βp∞ δp∞ + βT∞ δT∞ . In implementation terms, this means that the second components of both inlet pressure and temperatures are non-zero. The computed derivative along r will be δr (ρ) = Jρ,p∞ βp∞ δp∞ + Jρ,T∞ βT∞ δT∞

(19)

For arbitrary values of βp∞ and βT∞ , the above derivative will be nonzero everywhere since, in general, Jρ,p∞ and Jρ,T∞ are nonzero. However, for an ideal gas, since p∞ = ρ∞ RT∞ , if we select βp∞ = 1 and βT∞ = Tp∞ , then we should find δr (ρ) to be identi∞ cally zero everywhere. As shown in Figure 5 the directional derivative of density in the chosen direction is indeed equal to zero everywhere on the airfoil surface within roundoff error. Moreover, as expected, the zero value of this derivative is recovered throughout the computational domain and this is independent of the choice of boundary conditions used. We should also note here that this behavior is not just a trivial case of a zero derivative that results from none of the inlet parameters having a nonzero second component. For the particular choice of direction described above, all the other computed solution fields, i.e, pressure, velocity etc. do indeed have nonzero derivatives. It is only the density field that exhibits zero derivative because of the particular choice of direction. This exercise therefore is a very good test of the implementation and verifies that all the derivatives are being propagated correctly throughout the solution process. 14

A. Jemcov, S. Mathur

7.00e-15 6.00e-15 5.00e-15 airfoil

4.00e-15 3.00e-15

rho-der 2.00e-15 1.00e-15 0.00e+00 -1.00e-15 -2.00e-15 0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

1

Position (m)

Figure 5: Directional derivative of δr ρ on the airfoil surface at α = 0o and M = 0.7

3.3

Verification by use of nondimensional form of governing equations

Another way to verify the implementation of automatic differentiation is to use properties of the original partial differential equation. In particular, for inviscid flows around the airfoil, the results of the calculations are dependent only on the Mach number as a similarity parameter and the angle of attack. This property is apparent when the original equations are nondimensionalized and this property should be maintained at the discrete level. For illustration purposes, we select the following non-dimensionalization t∗ =

tu∞ ρ p T , ρ∗ = , p∗ = , T∗ = L ρ∞ p∞ T∞

(20)

Here, L is a characteristic length scale, and p∞ , T∞ and ρ∞ are characteristic pressure, temperature and density defined by the free stream conditions. From the properties of the governing equations, we know that even though the solution obtained in terms of the dimensional variables, p, ρ etc. will change if the input parameters p∞ or T∞ are changed, the non-dimensionalized values of these variables, p∗ or ρ∗ etc. should remain invariant. In terms of the derivatives, this means that the derivatives of the non-dimensional quantities should turn out to be zero even though the derivatives of the dimensional variables are not. We verify this by calculating the derivatives in the direction δp∞ . In our implementation, this means we specify the second component of the free stream pressure to be unity. The code, which uses dimensional variables, propagates this through the solution process so that at convergence, we have the derivative of the pressure at every point in this 15

A. Jemcov, S. Mathur

direction. Because we are using dimensional variables, this derivative is nonzero. We then calculate the non-dimensional pressure, as defined by Equation 20. In terms of C++ implementation, this means dividing the pressure field, which is of the new data type we have defined, by the free stream pressure value, which is also of the new data type, using the division operator defined for this type. The derivative of the non-dimensional pressure, which is obtained in the second component of the variable, is indeed found to be zero, as shown along the airfoil surface in Figure 6. As expected, the derivative of p∗ is also found to be zero in all other directions that are orthogonal to δM∞ and δα. As in the previous section, this test is also not a trivial result of zero derivative being propagated and serves to verify the correctness of the implementation.

6.00e-11

4.00e-11

airfoil

2.00e-11

0.00e+00

p*-der -2.00e-11

-4.00e-11

-6.00e-11

-8.00e-11 0

0.1

0.2

0.3

0.4

0.5

0.6

0.7

0.8

0.9

1

Position (m)

Figure 6: Directional derivative of δr p∗ on the airfoil surface at α = 0o and M = 0.7

4

CONCLUSION

Techniques for forward mode algorithmic differentiation of a general purpose CFD code were discussed in this paper. Several alternative approaches to algorithmic differentiation were evaluated from the accuracy, implementation and efficiency point of view in order to find the most suitable approach for implementation in a general purpose CFD code. It was found that the forward mode implemented through C++ language through operator overloading and template metaprogramming satisfies the accuracy and efficiency requirements and proved to be the most suitable approach in general purpose CFD code due to its inherent generality. Three techniques for the verification of the implementation of the algorithmic code 16

A. Jemcov, S. Mathur

differentiation were proposed. The classical approach of the solution extrapolation based on local Taylor series expansion, selection of particular direction for the differentiation and non-dimensional form of governing equations were used to verify implementation of the C++ implementation. Performance measurements based on running times indicate that calculating the derivatives in addition to the values of expressions increases the run time by 50% to 100%.

17

A. Jemcov, S. Mathur

REFERENCES [1] A. Jameson. Aerodynamic Design Via Control Theory. Journal of Scientific Computing, 3:233-260, 1988 [2] A. Jameson and S. Kim. Reduction of the Adjoint Gradient Formula for Aerodynamic Shape Optimization Problems. AIAA Journal, Vol. 41, No. 11, November 2003 [3] S. Kim, J. J. Alonso and A. Jameson. Design of High Lift Configurations Using a Viscous Continuous Adjoint Method. AIAA 2002-0844, 40th AIAA Aerospace Sciences Meeting and Exhibit, January 14-17, 2002/Reno, NV [4] M. Giles. The Adjoint Approach to Design Data Assimilation and Error Analysis. ICFD Workshop on Adjoint Methods, Oxford University Computing Laboratory, 1998 [5] M. Giles. An Introduction to the Adjoint Approach to Design. ERCOFTAC Workshop on Adjoint Methods, Toulouse, June 21-23, 1999 [6] B. Mohammadi and O. Pironneau. Applied Shape Optimal Design for Fluids. Oxford University Press, 2001 [7] M. Gunzburger. Adjoint Equation-Based Methods for Control Problems in Incompressible, Viscous Flows. Flow, Turbulence and Combustion 65: 249-272, 2000, Kluwer Academic Publishers [8] H. Cabuk, C.-H. Sung, and V. Modi. Adjoint Operator Approach to Shape Design for Internal Incompressible Flows. Third International Conference on Inverse Design and Optimization in Engineering Sciences (ICIDES-III), Editor: G. S. Dulikravich, Washington D.C., October 23-25, 1991 [9] E. H. Brummelen and A. Segal. Numerical Solution of Steady Free-Surface Flows by the Adjoint Optimal Shape Design Method. International Journal for Numerical Methods in Fluids, 2003;41:3-27, John Wiley & Sons, 2003 [10] A. K. Alekseev. On Estimation of Entrance Boundary Parameters From Downstream Measurements Using Adjoint Approach. International Journal for Numerical Methods in Fluids, 2001;36: 971-982, John Wiley & Sons, 2001 [11] J. V. Beck and B. Blackwell. Inverse Problems, Handbook of Numerical Heat Transfer, W. J. Minkowycz, E. M. Sparrow, G. E. Schneider and R. H. Pletcher, John Wiley and Sons, 1988 [12] J. V. Beck and K. J. Arnold. Parameter Estimation in Engineering and Science, John Wiley and Sons, 1977 18

A. Jemcov, S. Mathur

[13] M. M. Putko, P. A. Newman, A. C. Taylor, and L. L. Green. Approach for Uncertainty Propagation and Robust Design in CFD Using Sensitivity Derivatives, AIAA 20012528, American Institute for Aeronautics and Astronautics 2001 ´ Turgeon, D. Pelletier, S. Etienne ´ [14] E. and J. Borggaard. Sensitivity and Uncertainty Analysis for Turbulent Flows. AIAA 2002-0985, 40th AIAA Aerospace Sciences Meeting and Exhibit, 14-17 January 2002/Reno, NV [15] J. Borggaard and J. Burns. A PDE Sensitivity Equation Method for Optimal Aerodynamic Design. ICASE-1994-8, ICASE Technical Report, 1994 [16] M. B. Giles and E. S¨ uli. Adjoint Methods for PDEs: A Posteriori Error Analysis and Postprocessing by Duality. Acta Numerica (2002), pp. 145-236, Cambridge University Press, 2002 [17] C. Bischof and A. Griewank. Computational Differentiation and Multidisciplinary Design, Inverse Problems and Optimal design in Industry. H. Engl and J. McLaughlin (eds.), pp 187-211, Teubner Verlag, Stuttgart, 1994 [18] A. Griewank. Evaluating Derivatives - Principles and Techniques of Algorithmic Differentiation. Frontiers in Applied Mathematics, SIAM, Philadelphia, 2000 [19] A. Griewank. On Automatic Differentiation. Preprint ANL/MCS-P10-1088, Mathematics and Computer Science Division, Argonne National Laboratory, 1988 [20] C. H. Bischof and A. Carle. Automatic Differentiation: Obtaining Fast and Reliable derivatives - Fast. Argonne Preprint MCS-P484-1194 [21] A. Griewank, D. Juedes and J. Srinivasan. ADOL-C, a Package for the Automatic Differentiation of Algorithms Written in C/C++. Technical Report MCS-P180-1190, Mathematics and Computer Science Division, Argonne National Laboratory, 1990 [22] D. Vandevoorde, and N.M. Josuttis, C++ Templates - The Complete Guide, Addison Wesley, 2003

19