RANS CFD on 2D High-Lift System Configuration Using the Flow360 Python Client#

In this tutorial, we will look at a 2D multi-element airfoil which consists of a slat, wing, and flap. We will demonstrate how to create a general multi-element configuration model in ESP and use the Flow360 Python Client to run a RANS simulation. On this page you will find step-by-step instructions on how to:

  1. Build a general quasi-3D multi-element configuration model in ESP

  2. Set up automatic meshing and execute a RANS simulation

  3. Use the Flow360 Python Client to automatically update the configuration and re-submit a case

Firstly, we will explain how to build a general multi-element configuration model in Engineering Sketch Pad (ESP) and how to use edge, face, and group attributes to prepare that model for automatic meshing. Then we will use that general model to build three standard test cases. The first case is a 3-element airfoil that is a cross-section of the NASA CRM-HL configuration and is used in a special session at AIAA Aviation 2020 called Mesh Effects for CFD Solutions. There is no experimental data for this case and we only compare CFD results. The second case is 30P30N High-Lift Configuration, for which we have experimental data to compare to. The third case is the GA(W)-2 airfoil with a 30% fowler flap for which we also have experimental data.

Finally, we will set up the automatic meshing input files and use the Flow360 Python Client to run a RANS simulation. The results of these simulations will then be validated against computational and experimental data.

quasi-3D model in ESP for a high-lift system configuration

Fig. 205 quasi-3D high-lift system configuration generated in ESP#

Note

In this tutorial, we demonstrate how to build a quasi-3D model for a general high-lift system configuration in ESP. The quasi-3D model here means extrusion of the 2D configuration.

Modeling Multi-element Configurations in ESP#

ESP uses the OpenCSM (Open-source Constructive Solid Modeller) system which is a feature-based, associative, parametric solid modeler. More information about ESP installation is available here. To build the geometry through ESP, we use a series of statements and commands in a script. All ESP statements and commands are held in a *.csm file. In this tutorial, we follow a ā€œbottom-upā€ approach to build a general model for a multi-element configuration including wing, flap and slat. To build the model, we start by defining the design, configuration and constant parameters.

Defining Geometry Parameters#

The design parameter in this tutorial is the flap deflection angle. To define a design parameter, we use DESPMTR. Design parameters describe any particular instance of the geometry model. They can be single-valued, 1D vectors, or 2D arrays of numbers. Each design value has a current value, upper- and lower-bounds. ESP allows to compute the sensitivity of any part of a geometry model with respect to any design parameter.

DESPMTR $pmtrName values use: define a design Parameter

For the multi-element configuration, we also need to define the flap deflection axis location as a configuration parameter. Since this is a quasi-3D model, the span of the quasi-3D model is also a configuration parameter. To define a configuration parameter, we use CFGPMTR. Values for the configuration parameters are declared in the top-level include-type .udc file. They must contain one or more numbers. They must be dimension-ed, in case they are multi-valued. They have lower- and upper-bounds. Their values can be changed and sensitivities cannot be computed for them.

CFGPMTR $pmtrName value use: define a configuration Parameter

To build a general model for the multi-element configuration, we need to consider that we may not have flaps, or slats or either. Therefore, their presence in configuration parameters can be defined as a constant parameter for each. To define a constant parameter in a build process, we use CONPMTR. Constant parameters contain only one number. Their values are declared in the top-level include-type .udc file and are visible from any .csm or .udc file. Their values cannot be changed and sensitivities cannot be computed for constant parameters.

CONPMTR $pmtrName values use: define a constant Parameter

The example below shows how to put these statements all together in a CSM file.

In this example, DIMENSION indicates the size of the array used to define the flap deflection axis location.

DIMENSION $pmtrName nrow ncol use: set up or redimensions an array Parameter

DESPMTR flapDeflection 0
DIMENSION flapDefAxis 1 3 1
CFGPMTR flapDefAxis "0.84;0.0;0.0109;"
CFGPMTR span 0.01
CONPMTR slatStatus 1
CONPMTR flapStatus 1

The flap deflection angle is defined in degrees. The span is in meters. The status parameter for the flap and slat indicates if they are present in the configuration. Any value other than zero indicates that they are present in the configuration.

Here you can find the complete CSM file for this step: multielementStep1.csm.

3D Sketches of Multi-element Configuration#

In this section, we define a wire body for each element in the configuration. Then, we create a face (e.g. a higher type) from that wire body.

This section is similar to creating 3D sketches for airfoils in the ONERA M6 Wing Geometry Modeling. To create a sketch body for each element, we use the following format:

mark
skbeg   up_x_TE  up_y_TE  up_z_TE
spline  up_x_p1  up_y_p1  up_z_p1
.
.
.
spline  up_x_LE  up_y_LE  up_z_LE
skend

skbeg   low_x_LE  low_y_LE  low_z_LE
spline  low_x_p1  low_y_p1  low_z_p1
.
.
.
spline  low_x_TE  low_y_TE  low_z_TE
skend
group
store airfoil

The above CSM example shows how to put together a 3D sketch for an airfoil. These 3D sketches are later used to build a face body and then face bodies are used to be extruded into a solid body. In this example, we follow a simple concept to define a 2D curve. We define all the curves directly in global 3D space. In case, we need them on a plane, we define 3D data as needed. For example, we define the multi-element configuration on the xz-plane. Therefore, we create all splines in the global 3D space by setting all y-coordinates of the 3D points to zero.

As shown in the above example, all 3D sketches start from the upper trailing-edge point to the leading-edge point and back to the lower trailing-edge point. This means the points definition is counter-clockwise.

In a multi-element configuration, we have three elements including the wing, which is the main element, the slat in front of the wing, and the flap in the back. The wing element profiles can have two curves defined through two splines, when there is a concave region in the back where the flap closes in. It can have more curves when the flap element is present. Since we define a generic multi-element modeler, we include all possible situations. Therefore, wing element profiles always include two curves defined by two splines connected at the leading-edge. If the flap element is present in the configuration, we define a curve using a single spline in a separate sketch for the concave region in the back of the wing.

For the flap element, we have two curves defined by two splines in one sketch. For the slat element, we have two curves: the front and back curves. The front curve is defined with two spline in one sketch. The back curve is defined with one spline in a different sketch. Please note that when we define a single spline in a sketch, we donā€™t need to group it.

Here you can find the complete CSM file for this step including the sketches for three elements in the configuration: multielementStep2.csm.

Building the Wing Face Body#

In this section, we restore the sketch body for each element and create a face from them.

RESTORE $name index=0 use: restores Body(s) that was/were previously stored

In the above description, ā€œ=ā€ indicates an optional argument for the statement. When the optional argument is not indicated, the default value after the equal sign is taken.

To create a face body from a wire body, we use combine.

COMBINE toler=0 use: combine Bodys since Mark into next higher type

In this tutorial, we close the wire body and then use join to have one single wire body before calling the combine statement.

JOIN toler=0 toMark=0 use: join two Bodys at a common Edge or Face

Because we create a general model for multi-element configuration, to close a wire body for each element, we have different scenarios. Two possible scenarios to create a closed wire body for the wing element are explained below.

Note

  1. Wing Element Scenario A:

The flap status is not equal to 1, which means there is no flap element in the configuration. Therefore, the wing wire body only includes the upper and the lower curves forming an airfoil. To close the wire body, we can connect the upper and the lower trailing-edge points with a line sketch.

../../_images/rae2822.png
  1. Wing Element Scenario B:

The flap status is equal to 1, which means there is a flap element in the configuration. Therefore, the wing wire body includes three spline curves forming the upper wing, the lower wing and the concave curve in the rear portion of the wing. Based on the format explained in the 3D Sketch Format:

  • The concave curve starts from the lower trailing-edge point and it ends up connected to the lower curve of the wing. In the figure below, as an example, the wing element for the 2D CRM high-lift configuration is shown. In this configuration, we have a flap element and the concave curve in the back of the wing is connected to the lower curve of the wing element, which creates a sharp point in the connection.

../../_images/crmWire.png
  • The concave curve starts from the lower trailing-edge point and it does not end up connected to the wing lower curve. In the figure below, as an example, the wing element for the 30p30n high-lift configuration is shown. In this configuration, we have a flap element and as you see, the concave line in the back of the wing element is not connected to the lower curve of the wing. To create a closed wire body for the wing element, we need to connect the ending point of the concave curve to the ending point of the lower curve of the wing element.

../../_images/30p30nWire.png

In the figure below, the wing element for the GA(W)-2 high-lift configuration is shown. As you see, we have a flap element in this configuration and the concave curve in the back of the wing is not connected to the lower curve of the wing. To create a close wire-body, we have to connect the ending point of the concave curve to the ending point of the lower curve of the wing. This is the second item in scenario B and it creates a blunt trailing-edge in the connection.

../../_images/gaw2Wire.png

To cover both types of curves in the concave rear part of the wing, first we connect the upper trailing-edge point to the lower trailing-edge point and then in case the concave curve is not connected to the wing lower curve, we use a line sketch to connect it and close the wire body for the wing.

Based on the above-mentioned scenarios, first we restore the wing sketch group and join it. Therefore, we have one wire body including two edges and three nodes.

restore wing
join

Then, we must find the coordinates of these three nodes representing the leading-edge and the upper and lower trailing-edge. To find their coordinates, we loop over all the nodes in the current body and detect the leading-edge node and the trailing-edge nodes based on their x and z values. The leading-edge node and the trailing-edge nodes for a wing wire with flap is shown below.

leading-edge and trailing-edge nodes for a wing profile

Fig. 206 Leading-edge and trailing-edge nodes for a wing profile#

# defining arrays with one row and three columns
dimension wingLE 1 3
dimension wingUpTE 1 3
dimension wingLowTE 1 3

# initializing xmin, zmin, zmax with their opposite extremes
set xmin @xmax
set zmin @zmax
set zmax @zmin

# looping over nodes to find the LE
set nNodes @nnode
patbeg inode nNodes
   evaluate node @ibody inode
   IFTHEN @edata[1] LT xmin
      set xmin @edata[1]
      set wingLE    "xmin;@edata[2];@edata[3];"
      set leadingNodeID inode
   ENDIF
patend

# looping over nodes to find the TE
patbeg inode nNodes
   IFTHEN inode NE leadingNodeID
      evaluate node @ibody inode
      IFTHEN @edata[3] GT zmax
            set zmax @edata[3]
            set wingUpTE   "@edata[1];@edata[2];zmax;"
      ENDIF

      IFTHEN @edata[3] LT zmin
            set zmin @edata[3]
            set wingLowTE   "@edata[1];@edata[2];zmin;"
      ENDIF
   ENDIF
patend

Note

In this tutorial, a ā€œbottom upā€ approach is provided. The solid body is built up from nodes, to curves, to edges, to surfaces, to faces, to shells, and finally bodies. The term ā€˜nodeā€™ here refers to the nodes at the ends of each edge, which differs from the airfoil data points used to define the upper and lower curves.

In the above code, first we define arrays for the leading-edge and trailing-edge nodes. Then we assign the maximum value of the x-axis in this current body as the initial value for the xmin variable, the maximum value of the z-axis in this current body as the initial value for the zmin variable, and the minimum value of the z-axis in this current body as the initial value for the zmax variable.

Then we collect the total number of nodes in this current body by using node, loop over them, evaluate them, and compare the x value of their coordinates with the xmin to find the leading-edge node. When x coordinate of a node has a value less than xmin, the value of xmin is updated with that x value. We also store the nodeID at each update in the leadingNodeID. In this case, the leading-edge node is the most forward one, hence with the lowest x coordinate. Each wire body is composed of only edges and each edge has two nodes including the begin and end nodes. When we collect all the nodes in the current body, we collect all the ending nodes for all of the edges. Please note the node here refers to the node as one of the topological entities and it is different from the airfoil data points used to create the spline.

Then we loop over all nodes again and if the nodeID is not equal to leadingNodeID, we evaluate and compare the value of z coordinate to find the upper trailing-edge node with maximum z and the lower trailing-edge node with minimum z. The way we find the leading-edge and trailing-edge nodes in this example is similar to adding edge attributes based on node coordinates in the ONERA M6 Wing Geometry Modeling. For a detailed description you can refer to that tutorial.

After restoring the wing wire body, we restore the sketch spline for the concave line in the rear of the wing, if the flap status is not equal to zero.

Just like we did for the upper and lower curves above, we will now find the begin and end points of the concave spline. Therefore, after we restore the concave spline sketch, we define two arrays for the coordinates of the starting and ending points, then we initialize the xmin and xmax variables with the maximum and minimum x values of the current sketch body. To find the starting point, which has minimum x value, and the ending point, which has the maximum x value, we loop over all the nodes and evaluate the coordinates of each node. If the value for the x coordinate were less than the xmin variable, we update the xmin variable. We follow the same technique to find then ending point with the xmax variable. The ending nodes of the concave spline is shown below in comparison to ending nodes of the wing profile.

ending nodes of the concave spline

Fig. 207 Ending nodes of the concave spline for a wing profile.#

patbeg then ifzero(flapStatus,0,1)
   # restoring sketch
   restore wingConcave

   # defining arrays for the ending nodes
   dimension concaveEnd 1 3
   dimension concaveBegin 1 3

   # initializing xmin and xmax with their opposite extremes
   set xmax @xmin
   set xmin @xmax

   # looping over nodes to find the ending points
   patbeg inode @nnode
      evaluate node @ibody inode
      IFTHEN @edata[1] GT xmax
            set xmax @edata[1]
            set concaveEnd "xmax;@edata[2];@edata[3];"
      ENDIF

      IFTHEN @edata[1] LT xmin
            set xmin @edata[1]
            set concaveBegin "xmin;@edata[2];@edata[3];"
      ENDIF
   patend

   # connecting the wing upper TE node to the ending node of the wing concave curve with line segment
   skbeg concaveEnd[1] concaveEnd[2] concaveEnd[3]
      linseg wingUpTE[1] wingUpTE[2] wingUpTE[3]
   skend

   # calculating the distance between the wing lower TE node and starting node of the wing concave line
   set sum 0
   patbeg i 3
      set sum sum+(concaveBegin[i]-wingLowTE[i])^2
   patend
   set distance sqrt(sum)

   IFTHEN distance GT 1e-04
      # connecting the wing lower TE node to the starting node of the wing concave curve with line segment
      skbeg concaveBegin[1] concaveBegin[2] concaveBegin[3]
            linseg wingLowTE[1] wingLowTE[2] wingLowTE[3]
      skend
   ENDIF
patend

After we have obtained the starting and ending point of the concave spline sketch, we connect the upper trailing-edge point of the wing to the ending node of the concave curve with a sketch and a line segment. Then we need to find out if the concave spline sketch is connected to the lower trailing-edge node of the wing spline sketch or not. For that purpose, we calculate the distance between two nodes: the lower trailing-edge node of the wing spline sketch and the starting node of the concave spline sketch. When this distance is zero, these two splines sketches are connected and share the same node; otherwise we define a sketch and use a line segment to connect them and close the wire body.

Finally we use combine to elevate the wire body into a face, and then store it as a face.

combine
store wingFace

Here you can find the complete CSM file for this step: multielementStep3.csm.

Building the Flap and Slat Face Bodies#

After we built the wing face, we check the flap and slat status. If they are set to be present in the configuration, we build their faces.

patbeg then ifzero(flapStatus,0,1)
   restore flap
   join

   # defining arrays for the leading-edge and trailing-edge nodes
   dimension flapLE 1 3
   dimension flapUpTE 1 3
   dimension flapLowTE 1 3

   # initializing xmin, zmin and zmax with their opposite extremes
   set xmin @xmax
   set zmin @zmax
   set zmax @zmin

   # looping over nodes to find the leading-edge node
   set nNodes @nnode
   patbeg inode nNodes
      evaluate node @ibody inode
      IFTHEN @edata[1] LT xmin
            set xmin @edata[1]
            set flapLE    "xmin;@edata[2];@edata[3];"
            set leadingNodeID inode
      ENDIF
   patend

   # looping over nodes to find the trailing-edge nodes
   patbeg inode nNodes
      IFTHEN inode NE leadingNodeID
            evaluate node @ibody inode
            IFTHEN @edata[3] GT zmax
               set zmax @edata[3]
               set flapUpTE   "@edata[1];@edata[2];zmax;"
            ENDIF

            IFTHEN @edata[3] LT zmin
               set zmin @edata[3]
               set flapLowTE   "@edata[1];@edata[2];zmin;"
            ENDIF
      ENDIF
   patend

   # closing the flap wire body by a line segment
   skbeg flapLowTE[1] flapLowTE[2] flapLowTE[3]
      linseg flapUpTE[1] flapUpTE[2] flapUpTE[3]
   skend

   # creating a face body from the wire body
   combine
   store flapFace
patend

Like the wing face example, after we restore the flap sketch group, we use join to have a single wire body. Then, we use dimension to define arrays for the coordinates of the leading-edge and trailing-edge nodes. The we initialize xmin, zmin and zmax variables for the nodes in the flap wire body with the maximum value of x, maximum value of z and minimum value of z for the current body. Then we loop over all the nodes, evaluate at each node, and compare the x value of the node to find the leading-edge node. We use the same technique to find the trailing-edge nodes. Then, we close the flap wire body with a line segment and finally elevate the wire body to the face and store it.

For the slat wire body, we follow the same approach. In comparison to the flap, the only difference is that the slat has two-spline sketches forming the front curve and one spline sketch in the back.

patbeg then ifzero(slatStatus,0,1)
   # restore the front spline sketch
   restore slatFront
   join

   # defining arrays for the leading-edge and trailing-edge nodes
   dimension slatFrontLE 1 3 1
   dimension slatFrontUpTE 1 3 1
   dimension slatFrontLowTE 1 3 1

   # initializing xmin, zmin and zmax with their opposite extremes
   set xmin @xmax
   set zmin @zmax
   set zmax @zmin

   # looping over nodes to find the leading-edge node
   set nNodes @nnode
   patbeg inode nNodes
      evaluate node @ibody inode
      IFTHEN @edata[1] LT xmin
            set xmin @edata
            set slatFrontLE    "xmin;@edata[2];@edata[3];"
            set leadingNodeID inode
      ENDIF
   patend

   patbeg inode nNodes
      IFTHEN  inode NE  leadingNodeID
            evaluate node @ibody inode
            IFTHEN @edata[3] GT zmax
               set zmax @edata[3]
               set slatFrontUpTE   "@edata[1];@edata[2];zmax;"
            ENDIF

            IFTHEN @edata[3] LT zmin
               set zmin @edata[3]
               set slatFrontLowTE   "@edata[1];@edata[2];zmin;"
            ENDIF
      ENDIF
   patend

   # restore the back spline sketch
   restore slatBack

   # defining arrays for the trailing-edge nodes
   dimension slatBackUpTE 1 3 1
   dimension slatBackLowTE 1 3 1

   # initializing xmin, zmin and zmax with their opposite extremes
   set zmin @zmax
   set zmax @zmin

   # looping over nodes to find the trailing-edge nodes
   set nNodes @nnode
   patbeg inode nNodes
      evaluate node @ibody inode
      IFTHEN @edata[3] GT zmax
            set zmax @edata[3]
            set slatBackUpTE   "@edata[1];@edata[2];zmax;"
      ENDIF

      IFTHEN @edata[3] LT zmin
            set zmin @edata[3]
            set slatBackLowTE   "@edata[1];@edata[2];zmin;"
      ENDIF
   patend

   # closing the trailing edge at the bottom side of the slat
   skbeg slatFrontLowTE[1] slatFrontLowTE[2] slatFrontLowTE[3]
      linseg slatBackLowTE[1] slatBackLowTE[2] slatBackLowTE[3]
   skend

   # closing the trailing edge at the top side of the slat
   skbeg slatFrontUpTE[1] slatFrontUpTE[2] slatFrontUpTE[3]
      linseg slatBackUpTE[1] slatBackUpTE[2] slatBackUpTE[3]
   skend

   # creating a face body from the wire body
   combine
   store slatFace
patend

For the slat element, we have two edges defining the front curve and connected at the leading-edge, and one edge in the back. In the above code, we use the same technique we used for the wing and flap elements to find the leading-edge and trailing-edge nodes for the slat element. After that, we restore the slatā€™s back spline sketch. It is a single spline; therefore we donā€™t need to join. Then, we define two arrays to find the upper and the lower nodes, initialize zmin and zmax variables, and loop over the nodes to find the upper and the lower nodes. At the end, we use a line segment sketch to connect the trailing-edge nodes at the top of the slat and at the bottom side of the slat. Now that the wire body is closed, we use combine to elevate the wire body into a face body.

Here you can find the complete CSM file for this step: multielementStep4.csm.

Multi-element Configuration Solid Body#

In this section, we build the solid body for the each element from their face bodies.

# restoring faces to build solid body | wing
restore wingFace
extrude 0 span 0
store wingBody

# restoring faces to build solid body | flap
patbeg then ifzero(flapStatus,0,1)
   restore flapFace
   extrude 0 span 0
   rotatey flapDeflection flapDefAxis[3] flapDefAxis[1]
   store flapBody
patend

# restoring faces to build solid body | slat
patbeg then ifzero(slatStatus,0,1)
   restore slatFace
   extrude 0 span 0
   store slatBody
patend

In the above code, for each element we restore their face and then we use the extrude statement to build the solid body. After the extrusion, we store the body. The span parameter is defined in the preamble.

EXTRUDE dx dy dz use: create a Body by extruding an Xsect

Since we are building a generic model for a multi-element configuration and we have defined a flap deflection angle as a design parameter, after extruding the flap face body, we rotate the flap solid body around the flap deflection axis by using the rotatey statement.

ROTATEY angDeg zaxis=0 xaxis=0 use: rotates Group on top of Stack around an axis that passes through (xaxis, 0, zaxis) and is parallel to the y-axis

Here you can find the complete CSM file for this step: multielementStep5.csm.

Adding Edge Attribute#

After building the solid models for the multi-element configuration, we must add edge attributes to each element and prepare them for automatic meshing. To add the edge attribute, we use the node coordinates that were obtained above when we elevated the wire body into a face body. To add edge attributes, we use EdgeAttr udprim. This udprim is shipped with the pre-built version of the ESP on Flexcomputeā€™s GitHub page.

We add edge attributes for each element after the extrusion and before the restore. For example for the wing element, we have two symmetric edges, one leading-edge and two trailing-edges.

# restoring faces to build solid body | wing
restore wingFace
extrude 0 span 0

# adding edge attributes | wing
dimension ySymm 2 1
set ySymm "0;span;"

patbeg i 2
   udparg edgeAttr attrname $edgeName  attrstr $symmetry
   udprim edgeAttr xyzs "wingLE[1];ySymm[i];wingLE[3];wingUpTE[1];ySymm[i];wingUpTE[3];"
   udparg edgeAttr attrname $edgeName  attrstr $symmetry
   udprim edgeAttr xyzs "wingLE[1];ySymm[i];wingLE[3];wingLowTE[1];ySymm[i];wingLowTE[3];"
   patbeg then ifzero(flapStatus,0,1)
      udparg edgeAttr attrname $edgeName  attrstr $symmetry
      udprim edgeAttr xyzs "concaveBegin[1];ySymm[i];concaveBegin[3];concaveEnd[1];ySymm[i];concaveEnd[3];"
      udparg edgeAttr attrname $edgeName  attrstr $symmetry
      udprim edgeAttr xyzs "wingUpTE[1];ySymm[i];wingUpTE[3];concaveEnd[1];ySymm[i];concaveEnd[3];"

      IFTHEN distance GT 1e-04
            udparg edgeAttr attrname $edgeName  attrstr $symmetry
            udprim edgeAttr xyzs "concaveBegin[1];ySymm[i];concaveBegin[3];wingLowTE[1];ySymm[i];wingLowTE[3];"
      ENDIF
   patend
patend

udparg edgeAttr attrname $edgeName  attrstr $wingleadingEdge
udprim edgeAttr xyzs "wingLE[1];wingLE[2];wingLE[3];wingLE[1];span;wingLE[3];"
udparg edgeAttr attrname $edgeName  attrstr $wingtrailingEdge
udprim edgeAttr xyzs "wingUpTE[1];wingUpTE[2];wingUpTE[3];wingUpTE[1];span;wingUpTE[3];"
udparg edgeAttr attrname $edgeName  attrstr $wingtrailingEdge
udprim edgeAttr xyzs "wingLowTE[1];wingLowTE[2];wingLowTE[3];wingLowTE[1];span;wingLowTE[3];"

patbeg then ifzero(flapStatus,0,1)
   udparg edgeAttr attrname $edgeName  attrstr $wingtrailingEdge
   udprim edgeAttr xyzs "concaveEnd[1];concaveEnd[2];concaveEnd[3];concaveEnd[1];span;concaveEnd[3];"
   udparg edgeAttr attrname $edgeName  attrstr $wingtrailingEdge
   udprim edgeAttr xyzs "concaveBegin[1];concaveBegin[2];concaveBegin[3];concaveBegin[1];span;concaveBegin[3];"
patend

store wingBody

For the wing element, we have three types of edges including: leading-edge, trailing-edge and symmetric. We consider edges associated with the concave region of the multi-element configuration as trailing-edges when the flap status is nonzero. Therefore, in the above code, we define an array with two elements including zero and span. These two elements define two symmetric planes for the multi-element configuration quasi-3D model. For the symmetric edges, we call the edgeAttr udprim twice. When the flap status is nonzero, we must also add the edge attribute for edges associated with the concave region. In the Building the Wing Face Body, we defined and calculated a distance parameter to find out if the concave spline was connected to the wing lower trailing-edge node. We use the same parameter here to add the edge attributes to associated edges in the concave rear part. This is for when the wing lower trailing-edge node is not connected to the starting node of the concave sketch spline.

For the leading-edge, we use the wingLE array defined in the above sections to add the edge attribute. For the trailing-edge, we use wingUpTE and wingLowTE arrays to add the edge attributes. When the flap status is nonzero, we use concaveBegin and concaveEnd arrays to add edge attributes to concave spanwise lines associated with the rear concave region of the wing element.

For the flap and slat elements, we follow the same procedure to add edge attributes to the leading-edge and trailing-edge.

Here you can find the complete CSM file for this step: multielementStep6.csm.

Adding Face and Group Attributes#

After we added the edge attributes for each element, we must add the face and group attributes and prepare the model for the automatic meshing.

# restoring bodies to add face and group attributes | wing
restore wingBody

# adding face and group attributes to the entire solid body
attribute faceName $wing
attribute groupName $wing

set nWingFaces @nface
set sumWingArea @area
set minArea sumWingArea

# finding the face with min are | wing trailing edge face
patbeg i nWingFaces
   select face i
   IFTHEN @area LT minArea
      set minArea @area
      set trailingFaceID i
   ENDIF
patend

# adding face and group attributes to the wing trailing face
select face trailingFaceID
attribute faceName $wingTrailing
attribute groupName $wing

In the above example, we restore the wing solid body and then we use attribute statement to add a string value ā€˜wingā€™ to the attribute name faceName and to add the same string value to the attribute name ā€˜groupNameā€™. The statement attribute is defined below. When the first letter of the attribute value is a string, then it must be started with ā€˜$ā€™.

ATTRIBUTE $attrName attrValue use: sets an Attribute for the Group on top of Stack

After adding the ā€˜$wingā€™ as the attribute value to the attribute ā€˜faceNameā€™ and ā€˜groupNameā€™, we find the face with the minimum area and add ā€˜$wingTrailingā€™ as the string value for the ā€˜faceNameā€™ attribute. Like this, we can specify the maximum edge length for the surface mesh in the automatic meshing. The ā€˜groupNameā€™ attribute is same.

To find the face with the minimum area, we define a variable minArea and initialize it with the sum of all faces. Then, we loop over all faces and compare their face area. When their face area is less than the value of the minArea, we update the minArea variable and we store the faceID.

We follow the same procedure to add a string value to the ā€˜faceNameā€™ and ā€˜groupNameā€™ attributes.

Here you can find the complete CSM file for the multi-element configuration: multielementStep7.csm.

Using Python to Add Coordinates and Build Parameters#

So far, we have used ESP statements and written a script to build a general model for the multi-element configuration. Now, we use a python script that lets us add the build parameters and data point coordinates for each element into the CSM script.

For this purpose, we divide the geometry modeling script with ESP statements into two parts: preamble and body. The preamble includes the build parameters and the sketch splines. The body includes the rest of the build process: restore sketch bodies, build the solid model, and add attributes to the solid body. Then, we save the body into a separate file and call it multielement.model.

The generateModel.py takes a JSON input file (ie, input_configuration.json) that holds the build parameters and path to the data point coordinates for each element. Then, it adds them to the preamble of the multielement.model and saves the CSM file corresponding to the input JSON file. This CSM file later can be passed to ESP to build the model.

To execute the build process using the python script, make sure the generateModel.py and multielement.model are in the same directory, then run:

python3 generateModel.py -json input_configuration.json -csm this_configuration.csm

The ā€œinput_configuration.jsonā€ holds input build parameters and the configurationā€™s data coordinates. These data coordinates define the concave line in the rear part of the wing, the wing, flap, and slat. Each elementā€™s data coordinates is defined in a separate file. For example, for the 2D CRM configuration, the input configuration JSON is:

Configuration JSON Example for 2D CRM System Configuration
{
   "coordinates": {
      "wing": "data/crmwing.dat",
      "concave": "data/crmconcave.dat",
      "flap": "data/crmflap.dat",
      "slat": "data/crmslat.dat"
   },
   "configuration": {
      "span": 0.01,
      "flapDeflection": 0,
      "deflectionAxis": [0.76,0.0,-0.1],
      "slat": true,
      "flap": true
   }
}


The ā€œthis_configuration.csmā€ is the output of the generateModel.py. This file holds the build prescription for the configuration corresponding to the input configuration JSON file. Users can later use it with ESP to build the complete model and check the build process.

When the slat and flap options are set to false in the input configuration JSON, only the quasi-3D model for the wing profile is created, which can be used to build a quasi-3D model for an airfoil. All the associated files with this tutorial, including the input configuration JSON files, are available in multielement_tutorials.tar.gz. By executing the generateModel.py with different input configuration JSON files, you can build different multi-element models in ESP. Below we can see the three standard test cases that will be used for the simulations.

quasi-3D model in ESP for 30p30n system configuration

Fig. 208 Quasi-3D model generated in ESP 30p30n system configuration#

quasi-3D model in ESP for 2D CRM system configuration

Fig. 209 Quasi-3D model generated in ESP for 2D CRM system configuration#

quasi-3D model in ESP for GA(W)-2 system configuration

Fig. 210 Quasi-3D model generated in ESP GA(W)-2 system configuration#

RUN CFD on multi-element configurations using Flow360#

In this section, we show how to run CFD simulations using the Flow360 Python API for different multi-element configurations with different design parameters. After using the generateModel.py to create the build prescription, we need to set up the input surface mesh JSON file and input volume mesh JSON file. Then, we set up the case JSON and submit the simulation.

Mesh Setup#

To control the meshā€™s density in a particular region of the model, we use attributes defined in ESP. For a body, we have edge and face attributes. The edge attribute indicates how to treat the surface mesh at that particular edge. The face attribute defines the maximum edge length for the unstructured surface mesh over that face. In addition, for the entire surface mesh, there are three global parameters: ā€˜maxEdgeLengthā€™, ā€˜curvatureResolutionAngleā€™ and ā€˜growthRateā€™. These parameters generate the surface mesh where edge and face attributes are not specified. The ā€˜curvatureResolutionAngleā€™ defines how well the curved region of the model is captured by the unstructured mesh. For example, for the 2D CRM configuration, the surface mesh JSON is:

Surface Mesh JSON Example for 2D CRM System Configuration
{
   "maxEdgeLength": 1.1,
   "curvatureResolutionAngle": 12,
   "growthRate": 1.17,
   "edges": {
      "wingleadingEdge":  {
            "type": "aniso",
            "method": "height",
            "value": 7e-4
      },
      "wingtrailingEdge":  {
            "type": "aniso",
            "method": "height",
            "value": 7e-4
      },
      "flapleadingEdge":  {
            "type": "aniso",
            "method": "height",
            "value": 7e-4
      },
      "flaptrailingEdge":  {
            "type": "aniso",
            "method": "height",
            "value": 7e-4
      },
      "slatleadingEdge":  {
            "type": "aniso",
            "method": "height",
            "value": 7e-4
      },
      "slattrailingEdge":  {
            "type": "aniso",
            "method": "height",
            "value": 7e-4
      },
      "symmetry":  {
            "type": "projectAnisoSpacing"
      }
   },
   "faces": {
      "wing": {
            "maxEdgeLength": 0.74
      },
      "flap": {
            "maxEdgeLength": 0.55
      },
      "slat": {
            "maxEdgeLength": 0.55
      },
      "wingTrailing": {
            "maxEdgeLength": 0.36
      },
      "flapTrailing": {
            "maxEdgeLength": 0.36
      },
      "slatTrailing": {
            "maxEdgeLength": 0.36
      }
   }
}


We use five cylindrical volume-mesh constraints for the volume mesh to let the unstructured mesh gradually grow out in the space surrounding the high-lift configuration. For the volume mesh over the wall, we specify the initial height of the high-aspect-ratio anisotropic mesh and the growth ratio. For example, for the 2D CRM configuration, the volume mesh JSON is:

Volume Mesh JSON Example for 2D CRM System Configuration
{
   "refinementFactor": 1.35,
   "farfield": {
      "type": "quasi-3d"
   },
   "refinement": [
      {
            "type": "cylinder",
            "radius": 1.1,
            "length": 1.0,
            "spacing": 0.1,
            "axis": [0,1,0],
            "center": [0.7,0.5,0]
      },
      {
            "type": "cylinder",
            "radius": 2.2,
            "length": 1.0,
            "spacing": 0.15,
            "axis": [0,1,0],
            "center": [0.7,0.5,0]
      },
      {
            "type": "cylinder",
            "radius": 3.3,
            "length": 1.0,
            "spacing": 0.225,
            "axis": [0,1,0],
            "center": [0.7,0.5,0]
      },
      {
            "type": "cylinder",
            "radius": 4.5,
            "length": 1.0,
            "spacing": 0.275,
            "axis": [0,1,0],
            "center": [0.7,0.5,0]
      },
      {
            "type": "cylinder",
            "radius": 6.5,
            "length": 10,
            "spacing": 0.325,
            "axis": [-1,0,0],
            "center": [6.5,0.5,0]
      }
   ],
   "volume": {
      "firstLayerThickness": 1.8487111e-06,
      "growthRate": 1.17,
      "gapTreatmentStrength": 0.5
   }
}


Case Setup#

The case JSON file includes 8 sections:

  • ā€œgeometryā€

  • ā€œvolumeOutputā€

  • ā€œsurfaceOutputā€

  • ā€œnavierStokesSolverā€

  • ā€œturbulenceModelSolverā€

  • ā€œfreestreamā€

  • ā€œboundariesā€

  • ā€œtimeSteppingā€

The ā€œgeometryā€ indicates the reference value used to report forces, ā€œvolumeOutputā€ and ā€œsurfaceOutputā€ are used to export surface and volume solutions, ā€œnavierStokesSolverā€ and ā€œturbulenceModelSolverā€ set the solver parameters, ā€œfreestreamā€ is the flow conditions, ā€œboundariesā€ is for clarifying types of boundaries marked in the mesh, and ā€œtimeSteppingā€ is for setting up the simulation parameters. Users can find a detailed description of these parameters in the Solver Configuration documentation page.

For example, for the 2D CRM multi-element configuration, the case JSON is:

Case JSON Example for 2D CRM System Configuration
{
   "geometry": {
      "refArea": 0.01,
      "momentCenter": [0.25,0,0],
      "momentLength": [1,1,1]
   },
   "volumeOutput": {
      "outputFormat": "tecplot",
      "primitiveVars": true,
      "vorticity": true,
      "residualNavierStokes": true,
      "residualTurbulence": true,
      "T": false,
      "s": false,
      "Cp": true,
      "Mach": true,
      "qcriterion": true,
      "mut": true,
      "VelocityRelative": false,
      "nuHat": false,
      "mutRatio": false
   },
   "surfaceOutput": {
      "outputFormat": "tecplot",
      "primitiveVars": true,
      "Cp": true,
      "Cf": true,
      "CfVec": true,
      "yPlus": true,
      "wallDistance": false
   },
   "navierStokesSolver": {
      "absoluteTolerance": 1e-11,
      "relativeTolerance": 1e-2,
      "linearSolverConfig": {
         "maxIterations": 35
      },
      "kappaMUSCL": 0.33,
      "orderOfAccuracy": 2,
      "updateJacobianFrequency": 4,
      "equationEvalFrequency": 1
   },
   "turbulenceModelSolver": {
      "modelType": "SpalartAllmaras",
      "absoluteTolerance": 1e-10,
      "relativeTolerance": 1e-2,
      "linearSolverConfig": {
         "maxIterations": 25
      },
      "kappaMUSCL": -1,
      "orderOfAccuracy": 2,
      "updateJacobianFrequency": 4,
      "equationEvalFrequency": 1
   },
   "freestream": {
      "Reynolds": 5.00000e+06,
      "Mach": 2.00000e-01,
      "Temperature": 2.7210000e+02,
      "alphaAngle": 16,
      "betaAngle": 0
   },
   "boundaries": {
      "fluid/symmetric-1": {
            "type": "SlipWall"
      },
      "fluid/symmetric-2": {
            "type": "SlipWall"
      },
      "fluid/flap": {
            "type": "NoSlipWall"
      },
      "fluid/slat": {
            "type": "NoSlipWall"
      },
      "fluid/wing": {
            "type": "NoSlipWall"
      },
      "fluid/farfield": {
            "type": "Freestream"
      }
   },
   "timeStepping": {
      "maxPhysicalSteps": 1,
      "timeStepSize": "inf",
      "maxPseudoSteps": 3000,
      "CFL": {
            "initial": 20,
            "final": 300,
            "rampSteps": 500
      }
   }
}


Run a Case#

Now we will show you how to leverage the Flow360 Python API and ESPā€™s scripting capabilities to conduct a parametric design and simulation study for a general high-lift system configuration with three standard examples.

All the files used to run this tutorial are available for download in multielement_tutorials.tar.gz.

To start running a case, download and untar the file, then from the main tutorial directory:

  1. To generate the CSM file:
    • For the 2D CRM configuration:

      python3 generateModel.py -json configuration/2dcrmConfiguration.json -csm 2dcrm.csm
      
    • For the 2D NASA 30p30n configuration:

      python3 generateModel.py -json configuration/30p30nConfiguration.json -csm 30p30n.csm
      
    • For the 2D GA(W)-2 configuration:

      python3 generateModel.py -json configuration/gaw2Configuration.json -csm gaw2.csm
      
    • For any other multi-element configuration: a. put data coordinate files in the ā€œdataā€ directory. b. copy a configuration JSON file and modify it according to your configuration of interest. c. generate the model by using the same python script:

      python3 generateModel.py -json configuration/my_configuration.json -csm MyConfigurationBuild.csm
      
  2. To run the case:
    • For the 2D CRM configuration:

      python3 runCase.py -json 2dCRMSim.json
      

    The ā€˜2dCRMSim.jsonā€™, for example, here holds the path to the CSM, surface, and volume and Flow360 case JSON to submit the simulation.

    • For the 2D NASA 30p30n configuration:

      python3 runCase.py -json 30p30nSim.json
      
    • For the 2D GA(W)-2 configuration:

      python3 runCase.py -json gaw2Sim.json
      
    • For a customized case: a. copy and modify the surface and volume JSON files according to your configuration. b. copy and modify the Flow360 case JSON file for your simulation. c. copy and modify the case JSON file according to the surface, volume and Flow360 case JSON files and run:

      python3 runCase.py -json my_simulation.json
      

Download the Results#

We use the Flow360 Python API client to download the surface and volume solutions for postprocessing purposes.

The downloadCase.py script downloads the solution files for the ā€˜caseIdā€™ specified in the input JSON file. The input JSON file has the following contents:

Case-ID JSON Example to Download Results for 2D CRM System Configuration
{
   "flow360": {
      "caseId": "case_id",
      "caseName": "multielement_tutorial"
   }
}


You will need to update it with the caseId alphanumeric string returned by the runCase.py call above. To download the solutions, you can run the Python script:

python3 downloadCase.py -json caseID.json

Visualize the Result#

You can always find the convergence histogram on the Flow360 website, under your account, by clicking on your case name and selecting Convergence and Forces tabs.

For example, for the 2D CRM multi-element configuration, the convergence histories of forces are:

../../_images/CL_CD1.png
../../_images/CF4.png
../../_images/CM3.png


Validate the Solution#

  1. 2D CRM High-Lift System Configuration:

The surface pressure coefficient and skin friction coefficient from FUN3D on their finest grids are shown compared to Flow360 on the finest grid that is automatically generated using the Flow360 Python Client. The results agree well with each other.

cp comparison

Fig. 211 Surface pressure coefficient over the airfoil elements.#

cf comparison

Fig. 212 Skin friction coefficient over the airfoil elements.#

  1. 2D NASA 30p30n System Configuration:

The surface pressure coefficient and skin friction coefficient from FUN3D on their finest grids are compared to Flow360 on the finest grid, which is automatically generated using the Flow360 Python Client. The results agree well with each other.

cp comparison with experiment

Fig. 213 Surface pressure coefficient over the airfoil elements.#

  1. 2D GA(W)-2 System Configuration with 30% Fowler Flap

cp comparison with experiment

Fig. 214 Surface pressure coefficient over the airfoil elements.#