This is a walkthrough for using FUN3D AIM to analyze a three-dimensional two-wing configuration.
Prerequisites
It is presumed that ESP and CAPS have been already installed, as well as FUN3D. In this example the open-source, tetrahedral mesh generator, TetGen, is coupled to the FUN3D AIM to provide a volumetric mesh.
Script files
Two scripts are used for this illustration:
- cfdMultiBody.csm: Creates geometry, as described in following section.
- fun3d_and_Tetgen_PyTest.py: pyCAPS script for performing analysis, as described in Performing analysis using pyCAPS.
Creating Geometry using ESP
The CSM script generates Bodies which are designed to be used by specific AIMs. The AIMs that the Body is designed for is communicated to the CAPS framework via the “capsAIM” string attribute. This is a semicolon-separated string with the list of AIM names. Thus, the CSM author can give a clear indication to which AIMs should use the Body. In this example, the list contains the list of mesh generators and CFD solvers that can consume the body:
ATTRIBUTE capsAIM $fun3dAIM;su2AIM;egadsTessAIM;aflr4AIM;pointwiseAIM;tetgenAIM;aflr3AIM;flightstreamAIM #CFD Analysis
A typical geometry model can be created and interactively modified using design parameters. These design parameters are either design- or geometry- based. In this example, a two wing configuration is created using following design parameters,
DESPMTR area 40.00000
DESPMTR aspect 5.00000
DESPMTR taper 0.50000
DESPMTR twist 15.00000
DESPMTR lesweep 30.00000
DESPMTR dihedral 1.00000
as well as the following configuration paramters. Configuration quantities cannot be used with sensitivities.
CFGPMTR series 8412
CFGPMTR series2 0020
CFGPMTR sharpte 0
CFGPMTR wake 1
CFGPMTR farfield 1
Next, internal CAPS reference attributes are set.
# Set reference values
ATTRIBUTE capsReferenceArea area
ATTRIBUTE capsReferenceChord sqrt(area/aspect)
ATTRIBUTE capsReferenceSpan sqrt(area/aspect)*aspect
ATTRIBUTE capsReferenceX sqrt(area/aspect)/2
ATTRIBUTE capsReferenceY 0
ATTRIBUTE capsReferenceZ 0
After our design parameters are defined they are used to setup other local variables (analytically) for the wing.
SET cmean sqrt(area/aspect)
SET span cmean*aspect
SET sspan span/2
SET croot 2*cmean/(1+taper)
SET ctip croot*taper
SET xtip sspan*tand(lesweep)
SET ytip sspan*tand(dihedral)
SET ybot -0.1*croot
SET ytop +0.2*croot+ytip
SET extend 0.02*cmean
Once all design and locale variables are defined, a half span, solid model is created by "ruling" together NACA series airfoils (following a series of scales, rotations, and translations).
MARK
UDPRIM naca Series series sharpte sharpte
SCALE croot
UDPRIM naca Series series2 sharpte sharpte
SCALE ctip
ROTATEZ -twist 0 0
TRANSLATE xtip ytip -sspan
RULE
A full span model is then created by mirroring and joining the half-span model.
# Store half of wing and keep a copy on the stack
STORE HalfWing 0 1
# Restore and mirror the half wing
RESTORE HalfWing 0
MIRROR 0 0 1 0
# Combine halfs into a whole
JOIN 0
Once the desired model obtained it needs to be rotated so that it is in the expected aero-coordinated system (y- out the right wing, x- in the flow direction, and +z- up).
# Get body into a typical aero-system
ROTATEX 90 0 0
Next, an attribute is then placed in the geometry so that the geometry components may be reference by the FUN3D AIM.
# Store the wing
STORE Wing 0 0
# Wing 1 - Restore
RESTORE Wing 0
ATTRIBUTE capsGroup $Wing1
ATTRIBUTE capsMesh $Wing1
ATTRIBUTE _name $Wing1
ATTRIBUTE AFLR4_Cmp_ID 1
ATTRIBUTE AFLR4_Edge_Refinement_Weight 0.1
ATTRIBUTE capsMeshLength cmean #Charachteristic length for meshing
Following the completion of the first wing, a second wing is created and scaled using the store/restore operations.
# Wing 2 - Restore and scale, translate
RESTORE Wing 0
ATTRIBUTE capsGroup $Wing2
ATTRIBUTE capsMesh $Wing2
ATTRIBUTE _name $Wing2
ATTRIBUTE AFLR4_Scale_Factor 10
ATTRIBUTE AFLR4_Cmp_ID 2
SCALE 0.4
TRANSLATE 10 0 0
Finally, for three-dimensional CFD analysis with the FUN3D AIM a "farfield" or "bounding box" boundary needs to be provided. In this example, a simple sphere is created and tagged as a farfield boundary using the capsGroup attribute.
SPHERE 0 0 0 80
ATTRIBUTE capsGroup $Farfield
ATTRIBUTE capsMesh $Farfield
ATTRIBUTE _name $Farfield
ATTRIBUTE AFLR_GBC $FARFIELD_UG3_GBC
ATTRIBUTE AFLR4_Cmp_ID 4
ATTRIBUTE .tParam "30.;5.;30;"
Performing analysis using pyCAPS
The first step in the pyCAPS script is to import the required modules. For this example, the following modules are used,
import pyCAPS
import os
import argparse
Similarly, local variables used throughout the script may be defined.
workDir = os.path.join(str(args.workDir[0]), "FUN3DTetgenAnalysisTest")
Once the required modules have been loaded, a pyCAPS.Problem can be instantiated with the desired geometry file.
geometryScript = os.path.join("..","csmData","cfdMultiBody.csm")
myProblem = pyCAPS.Problem(problemName=workDir,
capsFile=geometryScript,
outLevel=args.outLevel)
Any design parameters available in *.csm file are also available within the pyCAPS script. The following snippet changes the despmtr "area" which will force a rebuild of the geometry that FUN3D will now use.
myProblem.geometry.despmtr.area = 50
myProblem.geometry.cfgpmtr.wake = 0
A typical high-fidelity CFD analysis requires meshing AIMs to be coupled to the analysis AIM (unless a mesh already exists).For surface meshing, the face tessellation from the ESP geometry can be directly used as the surface mesh. If the face tessellation is not satisfactory, a surface meshing AIM may be coupled to the volume meshing AIM. In this example, the face tessellation is used as the surface mesh and TetGen for volumetric mesh generation. The TetGen AIM in loaded using the following
myProblem.analysis.create(aim = "egadsTessAIM", name = "egadsTess")
meshAIM = myProblem.analysis.create(aim = "tetgenAIM", name = "tetgen")
Once loaded, the appropriate inputs to the mesh generator required to generate mesh with adequate mesh quality are set. Refer TetGen AIM documentation for the list of all the available options.
myProblem.analysis["egadsTess"].input.Tess_Params = [1.0, 0.01, 20.0]
meshAIM.input.Preserve_Surf_Mesh = True
meshAIM.input["Surface_Mesh"].link(myProblem.analysis["egadsTess"].output["Surface_Mesh"])
In the case, the EGADS and TetGen AIMs execute in memory automatically.
Next the FUN3D AIM needs to be loaded.
fun3dAIM = myProblem.analysis.create(aim = "fun3dAIM",
name = "fun3d")
Once loaded analysis parameters specific to FUN3D need to be set (see AIM Inputs). These parameters are automatically converted into FUN3D specific format and transferred into the FUN3D configuration file. In this example, the Volume_Mesh from TetGen AIM is linked to the FUN3D Mesh input. This allows the volume mesh generated by the TetGen AIM to be transferred by the FUN3D AIM, in which case FUN3D will write out the mesh in its preferred, native format.
Note in the following snippet the instance of the AIM is referenced in two different manners: 1. Using the returned object from load call and 2. Using the "name" reference in the analysis dictionary. While syntactically different, these two forms are essentially identical.
fun3dAIM.input.Proj_Name = "fun3dTetgenTest"
fun3dAIM.input["Mesh"].link(meshAIM.output["Volume_Mesh"])
myProblem.analysis["fun3d"].input.Alpha = 1.0
myProblem.analysis["fun3d"].input.Mach = 0.5901
fun3dAIM.input.Equation_Type = "compressible"
myProblem.analysis["fun3d"].input.Viscous = "inviscid"
myProblem.analysis["fun3d"].input.Num_Iter = 10
myProblem.analysis["fun3d"].input.CFL_Schedule = [0.5, 3.0]
fun3dAIM.input.Restart_Read = "off"
myProblem.analysis["fun3d"].input.CFL_Schedule_Iter = [1, 40]
myProblem.analysis["fun3d"].input.Overwrite_NML = True
Along the same lines of setting the other input values the "Boundary_Condition" tuple is used to set the boundary conditions (CFD Boundary Conditions). These boundary tags (which reference capsGroup attributes in the *.csm file) and associated boundary conditions are converted into FUN3D specific boundary conditions and set in the FUN3D configuration file.
inviscidBC1 = {"bcType" : "Inviscid", "wallTemperature" : 1}
inviscidBC2 = {"bcType" : "Inviscid", "wallTemperature" : 1.2}
fun3dAIM.input.Boundary_Condition = {"Wing1" : inviscidBC1,
"Wing2" : inviscidBC2,
"Farfield": "farfield"}
Again, after all desired options are set aimPreAnalysis needs to be executed.
At this point the required files necessary run FUN3D should have be created and placed in the specified analysis working directory. Next FUN3D needs to executed either through its Python interface module (not shown) or an OS system call such as,
print ("\n\nRunning FUN3D......")
fun3d.system("nodet_mpi --animation_freq -1 --write_aero_loads_to_file> Info.out");
After FUN3D is finished running aimPostAnalysis needs to be executed.
Finally, available AIM outputs (see AIM Outputs) may be retrieved, for example:
print ("Total Force - Pressure + Viscous")
print ("Cl = " , fun3dAIM.output.CLtot,
"Cd = " , fun3dAIM.output.CDtot)
print ("Cmx = " , fun3dAIM.output.CMXtot,
"Cmy = " , fun3dAIM.output.CMYtot,
"Cmz = " , fun3dAIM.output.CMZtot)
print ("Cx = " , fun3dAIM.output.CXtot,
"Cy = " , fun3dAIM.output.CYtot,
"Cz = " , fun3dAIM.output.CZtot)
print ("Pressure Contribution")
print ("Cl_p = " , fun3dAIM.output.CLtot_p,
"Cd_p = " , fun3dAIM.output.CDtot_p)
print ("Cmx_p = " , fun3dAIM.output.CMXtot_p,
"Cmy_p = " , fun3dAIM.output.CMYtot_p,
"Cmz_p = " , fun3dAIM.output.CMZtot_p)
print ("Cx_p = " , fun3dAIM.output.CXtot_p,
"Cy_p = " , fun3dAIM.output.CYtot_p,
"Cz_p = " , fun3dAIM.output.CZtot_p)
print ("Viscous Contribution")
print ("Cl_v = " , fun3dAIM.output.CLtot_v,
"Cd_v = " , fun3dAIM.output.CDtot_v)
print ("Cmx_v = " , fun3dAIM.output.CMXtot_v,
"Cmy_v = " , fun3dAIM.output.CMYtot_v,
"Cmz_v = " , fun3dAIM.output.CMZtot_v)
print ("Cx_v = " , fun3dAIM.output.CXtot_v,
"Cy_v = " , fun3dAIM.output.CYtot_v,
"Cz_v = " , fun3dAIM.output.CZtot_v)
results in,
Total Force - Pressure + Viscous
Cl = 0.671595 Cd = 0.517818
Cmx = -0.002830832 Cmy = -1.342669 Cmz = -0.0020397
Cx = 0.5060182 Cy = -0.004986118 Cz = 0.6805299
Pressure Contribution
Cl_p = 0.671595 Cd_p = 0.517818
Cmx_p = -0.002830832 Cmy_p = -1.342669 Cmz_p = -0.0020397
Cx_p = 0.5060182 Cy_p = -0.004986118 Cz_p = 0.6805299
Viscous Contribution
Cl_v = 0.0 Cd_v = 0.0
Cmx_v = 0.0 Cmy_v = 0.0 Cmz_v = 0.0
Cx_v = 0.0 Cy_v = 0.0 Cz_v = 0.0
Executing pyCAPS script
Issuing the following command executes the script:
python fun3d_and_Tetgen_PyTest.py
Below are representative result images generated by the above script:
FUN3D coupled to TetGen example