Study for the Validation of

Code Saturne for Turbulent

Flow Simulations

Appendices Jordi Amat Foraster

June 2017

Study for the Validation of Code Saturne for Turbulent Flow Simulations Appendices

by

Jordi Amat Foraster

to obtain the degree of Bachelor of Science

in Aerospace Technology Engineering,

Escola Superior d’Enginyeries Industrial, Aeronàutica i Audiovisual de Terrassa (ESEIAAT)

Universitat Politècnica de Catalunya

Student name: Jordi Amat Foraster Project duration: February 15, 2017 – June 10, 2017 Thesis supervisor/s: Prof. Arnau Miró Jané, ESEIAAT (DFIS), director Prof. Dr. Manel Soria Guerrero, ESEIAAT (DFIS), director

An electronic version of this thesis is available at http://upcommons.upc.edu. Contents

Contents i

List of Figures ii

A An introduction to Code_Saturne 1 A.1 Workflow ...... 1 A.1.1 Meshes ...... 2 A.1.2 Preprocessor ...... 2 A.1.3 Graphical User Interface ...... 3 A.1.4 User Subrutines ...... 3 A.1.5 Kernel ...... 4 A.1.6 Postprocessing ...... 4 A.2 Directory Hierarchy ...... 5 A.3 Setting Up and Running a Calculation ...... 6 A.4 Spatial Discretization ...... 7 A.4.1 Gradient Calculation ...... 8 A.4.2 Convective Scheme ...... 8 A.5 Time Discretization ...... 9 A.5.1 Pressure-based velocity-pressure solver ...... 9 A.6 Turbulence Models ...... 10 A.7 Linear System Resolution ...... 11

B Rates of Strain 12

C Mathematical Proofs 14 .1 Global Kinetic Energy Equation ...... 14 C.2 Velocity-Pressure Coupling of the Taylor-Green Vortex Flow ...... 16

References 18

i List of Figures

A.1 Code_Saturne workflow diagram (inspired by Code_Saturne user’s man- ual[1])...... 1 A.2 Code_Saturne structure diagram...... 5 A.3 Collocated arrangement of discrete variables...... 7

ii A

An introduction to Code_Saturne

The purpose of this appendix is to review the main features of Code_Saturne CFD software, as well as to serve as a simple and summarized guide to start using Code_Saturne.

A.1 Workflow

Code_Saturne workflow is represented in Fig. A.1.

Figure A.1: Code_Saturne workflow diagram (inspired by Code_Saturne user’s man- ual[1]).

1 Appendix A. An introduction to Code_Saturne 2

A.1.1 Meshes

Code_Saturne does not include a mesh generator, however, it supports multiple mesh formats. All of these formats have advantages and disadvantages (in terms of simplicity, functionality, longevity and popularity) when compared to each other. The following formats are currently supported by Code_Saturne :

− .des from SIMAIL package.

− .unv from I-deas universal tool.

− .med from Salomé platform.

− .cgns is a generic format.

− .msh from the Gmsh tool.

− .case from Ensight 6 or Ensight Gold tools.

− .neu from Ansys FLUENT’s GAMBIT meshing tool.

− .ccm from STAR-CCm+ tool.

All these formats are described in greater detail in Code_Saturne user’s manual[1].

A.1.2 Preprocessor

Mesh operations are handled by the Preprocessor, which works independently from the Kernel. The main interesting operations are:

− Mesh import and read.

− Mesh modification operations such as joining, periodicity and smoothing.

− Mesh quality criteria computation to check the mesh consistency.

The resulting data is transferred to the Kernel through specific files, named mesh_input, or placed in a directory of that name when multiple meshes are imported. In Code_Saturne user’s manual[1] it is encouraged to separate the preprocessing and cal- culation runs, as this not only speeds up calculations, but also ensures that the mesh is identical, regardless of the architecture or number of processors it is run on. Appendix A. An introduction to Code_Saturne 3

A.1.3 Graphical User Interface

An optional Graphical User Interface (GUI) is available with Code_Saturne for config- uring the main parameters of the simulation (in .xml file). The GUI manages calcu- lation parameters, standard initialization values and boundary conditions for standard physics, pulverized fuel combustion, gas combustion, atmospheric flows, Lagrangian module, electrical model, compressible model and radiative transfers. If needed, the reader is encouraged to follow the Code_Saturne tutorial[2] to get used to the GUI.

A.1.4 User Subrutines

Code_Saturne provides great capabilities and user customization via C and subroutines. The running script runcase will compile all files in the SRC directory and link them with the existing libraries. Subroutines will have precedence to any settings on the .xml files from the GUI. The user’s subroutines are in the REFERENCE directory inside SRC and among others, some of the most important are:

− cs_user_parameters.f90. Set physical and numerical calculation parameters.

− cs_user_boundary_conditions.f90. Boundary conditions definitions (e.g., slid- ing or non-slip walls).

− cs_user_physical_properties.f90. Definition of physical properties (e.g., vari- able viscosity or density).

− cs_user_initialization.f90. Initialization of variables (e.g., velocity field).

− cs_user_extra_operations.f90. Extra operations, i.e., computation of forces, profiles or probes.

− cs_user_postprocess.f90. Post-processing of extra variables (e.g., vorticity).

− cs_user_periodicity.c. Definition of periodicity conditions.

If the reader wants to program his own subroutines is a must to refer to the Code_Saturne user’s manual[1]. Appendix A. An introduction to Code_Saturne 4

A.1.5 Kernel

The Kernel module is the main program that recompiles the subroutines, reads the .xml and launches the case.

A.1.6 Postprocessing

Code_Saturne generally saves two output meshes:

− Volume: for fluid variables such as pressure, velocity, etc.

− Boundary: for wall defined variables such as efforts, fluxes, etc.

They can all be set through the GUI. Additional output can be achieved through subrou- tines. All the this post-processing output in the .case format (both volume and boundary) is saved on the postprocessing directory and can be opened using Paraview open- source for its visualization. For visualizing the part, the Extract Block filter must be applied and the Fluid domain part must be selected. As Code_Saturne is a finite vol- ume collocated code, the information is on the cell centers. To interpolate the data to the nodes (for a smoother visualization), the celldata2pointdata filter must be used.

Monitoring points can be defined whether in the GUI or in cs_user_parameters.f90. The monitoring points saved in the monitoring directory can be visualized via Matlab or Paraview. Appendix A. An introduction to Code_Saturne 5

A.2 Directory Hierarchy

Code_Saturne is structured into studies that compress several cases as shown in Fig. A.2:

Figure A.2: Code_Saturne structure diagram.

The STUDY directory contains:

− A directory MESH containing the mesh(es) necessary for the study.

− A directory POST for the potential post-processing scripts (not used directly by the code).

− One or several CASE directories for the calculations.

Every CASE directory contains:

− A directory DATA for the calculation data, the user script and the .xml file.

− A directory SRC for the potential user subroutines necessary for the calculation.

− A directory SCRIPTS for the runcase script to launch the calculation.

− A directory RESU for saving the results after the simulation has finished.

The case preparer command code_saturne create automatically creates a study di- rectory according to the typical architecture when typing: code_saturne create -s STUDY -c CASE_NAME1 CASE_NAME2 Appendix A. An introduction to Code_Saturne 6

This syntax creates a study directory STUDY with case subdirectories CASE_NAME1 and CASE_NAME2. If no case name is given, a default case directory called CASE1 is created.

To improve the calculation traceability, the files and directories sent to RESU after a calculation are placed in a subdirectory named after that run’s ”id”, which is by default based on the run date and time, using the format: STUDY/CASE/RESU/YYYYMMDD- hhmm. See Code_Saturne user’s manual[1] for specific information about all the files sent to RESU.

A.3 Setting Up and Running a Calculation

This paragraph summarises the basic steps which are necessary to prepare and run a standard case:

− Open a new terminal and prepare the directories using the code_saturne create command (see Section A.2).

− Place the mesh(es) in the directory MESH. Make sure they are in a format com- pliant with Code_Saturne (see section A.1).

− Go to the directory DATA and launch the GUI using the command ./SaturneGUI.

− If not using the GUI, copy the DATA/REFERENCE/cs_user_scripts.py file to DATA and edit it, so that the correct run options and mesh paths may be set. Just as with user subroutines, settings defined in this file have priority over those defined in the GUI.

− Place the necessary user subroutines in the directory SRC. When not using the Interface, some subroutines are compulsory (see the list in Code_Saturne user’s manual[1]).

− Run the code_saturne run --initialize command to generate a folder in the RESU directory with the solver and the mesh files (it is highly recommended to rename this folder as a mesh folder).

− Go into the directory src_saturne and edit the user subroutines to prepare the calculation. Then, compile them through code_saturne compile and substitute the new cs_solver by the older one.

− Run the ./cs_solver --preprocess command to preprocess the mesh and to generate the files mesh_output and partition_output.

− In the directory DATA, check that cs_user_scripts.py file contains the correct path for the generated mesh files. Appendix A. An introduction to Code_Saturne 7

− Run again the code_saturne run --initialize command to generate another folder in the RESU directory with the updated run options (it is highly recom- mended to rename this folder as a run folder).

− Finally, go to the generated folder with the case and run the calculation executing the solver through the command ./cs_solver. In case you want to parallelize the calculation through MPI, run the command mpirun -np # ./cs_solver --mpi where # is the number of CPU cores you want to use.

− To check how is running the calculation, open a new terminal and use the com- mand tail -f listing | grep INSTANT.

− When the calculation is finished, the results are saved in the postprocessing directory under the name RESULTS.case.

A.4 Spatial Discretization

Discretization in space is achieved using a finite volume approach for a collocated ar- rangement of all variables. Within the framework of the finite volume approach, the equations are integrated over each cell of the mesh (or control volume) and therefore, all the variables are associated with the same point, namely the cell centre. In the col- located mesh scheme (see Fig. A.3), both the pressure and the velocities are stored at the center of the control volume.

v(i, j)

p(i, j) u(i, j)

Figure A.3: Collocated arrangement of discrete variables.

In the collocated arrangement a secondary velocity field at the faces is necessary to en- force mass conservation. Then, the two velocity fields are commonly coupled by means Appendix A. An introduction to Code_Saturne 8 of the interpolation method developed by Rhie and Chow [3]. Rhie and Chow interpola- tion is used when solving the pressure to avoid oscillations caused by the checkerboard- ing effects. The checkerboard problem consists in the obtention of converged velocity fields for unphysical pressure distributions. The Rhie and Chow filter tries to solve this problem by adding the cell gradient of pressure and removing the face gradient of pres- sure during the correction step. However, physics are being altered by introducing an undesirable artificial dissipation.

The Arakawa coefficient arak before the Rhie and Chow filter allows its activation (arak=1) or deactivation (arak=0).

A.4.1 Gradient Calculation

In Code_Saturne several options are available to compute cell gradient for scalar or vector fields:

− Iterative reconstruction of the non-orthogonalities (imrgra=0).

− Least squares method based on the first (imrgra=1), extended (imrgra=2) or partial extended neighborhood (imrgra=3).

− Iterative reconstruction with initialization using least squares method based on the first (imrgra=4), extended (imrgra=5) or partial extended neighborhood (imrgra=6).

The first one uses an iterative process to handle with non-orthogonalities. It is robust but requires computational effort. The second one, the least square method, minimizes a function. It is quick, but it is not the default option because it is less accurate (moreover when this method is applied to the pressure gradient, it does not allow to guarantee the conservatively for the momentum equation).

A.4.2 Convective Scheme

Three different schemes for convective terms are available in Code_Saturne :

− First order upwind scheme (blencv=0).

− Second order linear upwind scheme (blencv=1; ischcv=0).

− Second order centered scheme (blencv=1; ischcv=1).

− Blended scheme between upwind and second order scheme (0

To increase the stability of the second-order schemes, a “slope test” is activated by default: it switches locally and without any explicit warning to the upwind scheme wher- ever oscillations of the solution are detected. This may reduce the order in space. This slope test may be switched off setting isstpc to 1.

During the approximation process of linking face fluxes to cell centered quantities in the convection operator, a weighting factor is defined to measure the distance of the cell center to the face relatively to the next cell center. It can be shown in Verstappen et al.[4] that this factor must be 0.5 to preserve the skew-symmetry of the convection operator. This value can be set in Code_Saturne through the variable pond.

A.5 Time Discretization

Code_Saturne can solve flows in steady or unsteady mode. It uses a theta scheme for the time discretization:   θ = 1 for an implicit first order Euler scheme θ − scheme (A.1)  1 θ = 2 for second order Crank-Nicolson scheme

By default, the standard time scheme is a first-order (ischtp=1). A second-order scheme (ischtp=2) is activated automatically with LES modelling. On the other hand, when ”specific physics” (gas combustion, pulverised coal, compressible module) are activated, the second-order scheme is not allowed.

The time stepping can be selected through idtvar: 0 (uniform and constant), 1 (variable in time, uniform in space), 2 (variable in time and space) and -1 (steady algorithm).

A.5.1 Pressure-based velocity-pressure solver

Time discretization of the incompressible Navier-Stokes equations is achieved through a projection method, that can be associated with the SIMPLEC algorithm:

1. Prediction step: solves the momentum equation with an explicit pressure gradient and obtains a predicted velocity.

2. Correction step: uses the continuity equation to enforce mass conservation and corrects the predicted velocity to take into account the pressure variation.

3. Updating step: updates velocity field using the pressure gradient.

After the velocity has been updated, the resolution of turbulent variables and scalars is done according to their time scheme. Appendix A. An introduction to Code_Saturne 10

The precision of the pressure-velocity coupling can be set through the number of iter- ations nterup and through the relative precision epsup for the convergence test of the iterative process. The default values are set to nterup=1 and epsup=10-5.

For time marching schemes, it is possible to under-relax the pressure increments calculated within the pressure correction step (by default, no relaxation is used: relaxv(ipr)=1). This is useful for distorted meshes and, a priori, it does not affect the quality of the solution. From Code_Saturne user’s manual[1], 30% is a reasonable value for the under-relaxation parameter (i.e. relaxv(ipr)=0.7). For example, this op- tion may be activated if the calculation fails after several time steps for which the number of iterations of the pressure iterative solver has been unusually large or if one suspects that the quality of the mesh is low in a region where large velocity values develop over a few time steps.

A.6 Turbulence Models

Code_Saturne has several turbulence models available that can be activated through the indicator iturb:

− 0: DNS (no model)

− 20: RANS k − ε

− 21: RANS k − ε with linear production (Laurence and Guimet)

− 30: RANS Rij − ε standard LRR (Launder, Reece and Rodi)

− 31: RANS Rij − ε SSG (Speziale, Sarkar and Gatski)

− 32: RANS Rij − ε EBRSM (elliptic blending)

− 40: LES Smagorinsky model

− 41: LES dynamic model

− 42: LES WALE

− 50: RANS v2-f, φ-model version

− 51: RANS v2-f, BL-v2/k version

− 60: RANS k − ω, SST version

− 70: RANS Spart-Allmaras (SA) Appendix A. An introduction to Code_Saturne 11

A.7 Linear System Resolution

Code_Saturne has different ways of solving the linear system:

− Jacobi (default for velocity, temperature, turbulent variables, passive scalars).

− Algebraic multigrid (default for pressure).

− Conjugate gradient.

− Stabilized bi-conjugate gradient (BI-CGSTAB).

The relative precision for the solution of the linear system can be settled up through epsilo(ivar). The default value is epsilo(ivar)=10−8. When there are enough iter- ations on the reconstruction of the right-hand side of the equation (nswrsm), the value may be increased (by default, in case of second-order in time, with nswrsm=5 or 10, epsilo(ivar) is increased to 10−5). B

Rates of Strain

In the study of turbulent flows the strain rate tensor is a physical quantity that describes the rate of change of the deformation of a fluid in the neighborhood of a certain point, at a certain moment of time. It can be defined as the derivative of the strain tensor with respect to time, or as the symmetric component of the gradient of the flow velocity:   ∂u ∂v ∂w  ∂x ∂x ∂x  ∇u  ∂u ∂v ∂w  (B.1) =  ∂y ∂y ∂y  ∂u ∂v ∂w ∂z ∂z ∂z

The purpose of this appendix is to review the main properties of this second-order ten- sor, following a similar procedure to Pope [5].

The unique contraction or expansion of a second-order tensor corresponds to the trace of the matrix ∇u, tr(∇u), i.e., the sum of the diagonal components:

∂u ∂v ∂w tr(∇u) = ∇ · u = + + (B.2) ∂x ∂y ∂z

The velocity-gradient tensor ∇u can be decomposed into an isotropic part ∇uo and a deviatoric part ∇ud ∇u = ∇uo + ∇ud (B.3)

By definition, an isotropic tensor has the same components in every coordinate system. Isotropic second-order tensors are multiples of the identity matrix I. The isotropic part of ∇u is 1 ∇uo = tr(∇u)I (B.4) 3

12 Appendix B. Rates of Strain 13

By definition, a deviatoric tensor has zero trace, so the deviatoric part of ∇u is

1 ∇ud = ∇u − tr(∇u)I (B.5) 3

Thus, ∇u has the decomposition

1 ∇u = tr(∇u)I + ∇ud (B.6) 3

These expressions show that the isotropic tensor is responsible of the change in volume meanwhile the deviatoric tensor is responsible of the change in shape.

The deviatoric part can be further decomposed into symmetric (S) and antisymmetric (R) parts:

1 ( ) 1 S = ∇u + ∇ut − tr(∇u)I = St (B.7) 2 3 1 ( ) R = ∇u − ∇ut = −Rt (B.8) 2

Thus the velocity-gradient second-order tensor ∇u can be decomposed as the sum of an isotropic part so called rate-of-expansion tensor, a traceless symmetric deviatoric part so called rate-of-strain tensor, and an antisymmetric deviatoric part so called rate- of-rotation tensor: 1 ∇u = tr(∇u)I + S + R (B.9) 3

Note that for incompressible flows, tr(∇u) = ∇ · u = 0 preventing a change in volume. Thus, the rate-of-strain tensor is defined as

1 ( ) S = ∇u + ∇ut (B.10) 2 and the velocity-gradient second-order tensor reduces to

∇u = S + R (B.11) C

Mathematical Proofs

C.1 Global Kinetic Energy Equation

The integrated kinetic energy within the domain is computed by ∫ 1 u · u Ek = ρ dΩ (C.1) ρ0Ω Ω 2

The kinetic energy dissipation rate can then be computed by differencing Ek in time ∫ [∫ ∫ ] dE −1 d u · u −1 ∂u ∂u ϵ = − k = dΩ = · u dΩ + u · dΩ (C.2) dt Ω dt Ω 2 2Ω Ω ∂t Ω ∂t

Now, the derivatives can be substituted by the momentum equation ∫ ∫ ∫ −2Ωϵ = − [(u · ∇)u]u dΩ − u[(u · ∇)u] dΩ + ν ∆u · u dΩ ∫ Ω ∫ Ω ∫ Ω 1 1 + ν u · ∆u dΩ − ∇p · u dΩ − u · ∇p dΩ (C.3) Ω ρ0 Ω ρ0 Ω

These terms can be reduced taking into account the following algebraic theorems: ∫ · ∇ Theorem 1. The trilinear form Ω[(u )u]u dΩ is skew-symmetric with respect the last two arguments if boundary terms are ignored and ∇ · u = 0. ∫ ∫ [(u · ∇)u]u dΩ = − [(u · ∇)u]u dΩ Ω Ω

14 Appendix C. Mathematical Proofs 15

∫ ∇ · Theorem 2. The linear form Ω p u dΩ satisfies the identity ∫ ∫ ∇p · u dΩ = − p · (∇ · u) dΩ Ω Ω if the boundary terms are ignored. ∫ ∇ · ∇ · Theorem 3. The linear form Ω( u) u dΩ satisfies the identity ∫ ∫ (∇ · ∇u) · u dΩ = − ∇u · ∇u dΩ Ω Ω if the boundary terms are ignored.

Then, theorem 1 demonstrates that the convective contribution cancels from the global kinetic energy. Using theorem 2, it is also proofed that the pressure does not contribute either (for an incompressible flow). Hence, with the help of theorem 3, the energy equa- tion reduces to ∫ 2ν ∇u · ∇u ϵ = dΩ (C.4) Ω Ω 2 At this point, another algebraic theorem is needed. ∫ · ∇ × ∇ × Theorem 4. The linear form Ω u ( ( u)) dΩ satisfies the identity ∫ ∫ u · (∇ × (∇ × u)) dΩ = (∇ × u) · (∇ × u) dΩ Ω Ω if the boundary terms are ignored.

Taking into account the vorticity ω = ∇ × u and the following algebraic identity together with the continuity condition

 ∇ × (∇ × u) = ∇(∇ · u) − ∆u = −∇ · ∇u (C.5)

theorem 4 reduces to ∫ ∫ ∇u · ∇u dΩ = ω · ω dΩ (C.6) Ω Ω

Finally, applying this condition, it can be shown that for incompressible flow, the enstro- phy is directly related to the kinetic energy dissipation rate through a constant. ∫ dE 2ν ω · ω ϵ(ζ) = − k = dΩ = 2νζ (C.7) dt Ω Ω 2 where the enstrophy integrated on the domain Ω is ∫ 1 ω · ω ζ = ρ dΩ (C.8) ρ0Ω Ω 2 Appendix C. Mathematical Proofs 16

C.2 Velocity-Pressure Coupling of the Taylor-Green Vortex Flow

The pressure Poisson equation can be verified for the Taylor-Green Vortex (TGV) in- compressible flow in order to show the coupling between the velocity and pressure fields.

On the one hand, the right hand side of Poisson equation is developed as follows ( ) ( ) −1 −1 −1 ∂ ∂ ∂ ∂p ∂p ∂p ∇2p = ∇ · ∇p = , , · , , ρ ρ ρ ∂x ∂y ∂z ∂x ∂y ∂z 0 0 ( 0 ) −1 ∂2p ∂2p ∂2p (C.9) = 2 + 2 + 2 ρ0 ∂x ∂y ∂z where taking into account the second derivatives of the TGV pressure field [( ( ) ) ( )] ∂2p −ρ V 2 2z 2x = 0 0 cos + 2 cos (C.10) ∂x2 4L2 L L [( ( ) ) ( )] ∂2p −ρ V 2 2z 2y = 0 0 cos + 2 cos (C.11) ∂y2 4L2 L L [( ( ) ( )) ( )] ∂2p −ρ V 2 2x 2y 2z = 0 0 cos + cos cos (C.12) ∂z2 4L2 L L L the right hand side of the equation can be reduced with some algebra obtaining the following expression [ ( ) ( )] [ ( ) ] −1 V 2 2x 2y 2z ∇2 0 cos cos cos (C.13) p = 2 + + 1 ρ0 2L L L L

On the other hand, the left hand side of Poisson equation is developed as follows

∑3 ∑3 ∂u ∂u ∇u : ∇u = i · j ∂x ∂x i=1 j=1 j i ( ) ( ) ( ) ( ) ( ) ( ) ∂u 2 ∂v 2 ∂w 2 ∂u ∂v ∂u ∂w ∂v ∂w = + +  + 2 + 2  + 2  ∂x ∂x ∂x ∂y ∂x ∂z ∂x ∂z∂y ( ) ( ) ( ) ∂u 2 ∂v 2 ∂u ∂v = + + 2 (C.14) ∂x ∂x ∂y ∂x Appendix C. Mathematical Proofs 17 where taking into account the first derivatives of the TGV velocity field ( ) ( ) ( ) ∂u V x y z = 0 cos cos cos (C.15) ∂x L L( ) L( ) L( ) ∂v V x y z = − 0 cos cos cos (C.16) ∂y L L L L ( ) ( ) ( ) ∂u V x y z = − 0 sin sin cos (C.17) ∂y L L L L ( ) ( ) ( ) ∂v V x y z = 0 sin sin cos (C.18) ∂x L L L L the left hand side of the equation can be reduced with some algebra1 obtaining the following expression ( )[ ( ) ( ) ( ) ( )] 2V 2 z x y x y ∇u : ∇u = 0 cos2 cos2 cos2 − sin2 sin2 L2 [ (L ) L( )] [ L ( ) L] L V 2 2x 2y 2z = 0 cos + cos cos + 1 (C.19) 2L2 L L L

In conclusion, the equality has been proven as the Poisson equation match for the TGV incompressible flow.

1 2 1+cos 2α 2 1−cos 2α Useful identities: cos α = 2 sin α = 2 References

[1] EDF. Code_saturne version 4.0.0 practical user’s guide, 2015.

[2] EDF. version 3.0 tutorial - shear driven cavity flow, 2013.

[3] C. M. Rhie and W. L. Chow. A numerical study of the turbulent flow past an isolated airfoil with training edge separation. AIAA paper, 82-0998, 1982.

[4] R. W. C. P. Verstappen and A. E. P. Veldman. Symmetry-preserving discretization of turbulent flow. Journal of Computational Physics, 187:343–368, 2003.

[5] Stephen B. Pope. Turbulent Flows. Cambridge University Press, 2000.

18