Automated CFD Angle of Attack Sweep for an Airliner

Often in a Computational Fluid Dynamics (CFD) study you will find yourself repeating a series of operations that are prime candidates for automation. For instance, performing an angle of attack (alpha) sweep for an airplane configuration is a great example where automation can be a significant time saver as I will demonstrate.

CFD Simulation of an AirlinerCFD Simulation of an AirlinerAlpha = 6 degrees, velocity contours and arrows

CFD Model

For this example I chose a wing-body-pylon-nacelle-tail geometry provided by NASA for CFD validation. Unfortunately, the geometry was not a consistent solid model, but instead it was an incomplete surface model. E.g., the pylon was not attached to the nacelle or the wing. To get the model into a watertight volume representing the air around the airplane for the CFD simulation required extensive CAD cleanup operations to ensure each edge was consistently connected to only two surfaces.

Original Airliner Geometry

This type of geometry cleanup is often required when geometry for manufacture is repurposed after the fact for analysis. As I've covered previously it is much more efficient to configure the original geometry for simulation and then manufacture. The series of cleanup operations in this case were not candidates for automation, given that I was only considering this single model.

Flow Volume Around AirlinerFlow Volume Around Airliner

Automation

With the model complete, I tried performing a single simulation to ensure I had adequate mesh and solver parameters (e.g., relaxation factors). After minor adjustments I was satisfied that the mesh and solver parameters were good enough to proceed with the study.

Next I recorded a Python script as I performed the sequence of operations for a single alpha increase for the onset flow, i.e., modifying the reference velocity for the boundary conditions.

class Script:
	"""Caedium Script
	"""
	def run(self):
		selection = caedium.select.View(simulation = 'sim', view = 'view', 
		 camera = 'camera')
		selection.select(['flow-volume'])
		property = caedium.frm.Property('UDefaultValue', selection)
		property.appendParent('U').appendParent('Reference').\
		 appendParent('MaterialProperties').appendParent('PropertiesGroup').\
		 appendParent('Air').appendParent('Geometry')
		property.set([247.73, 0, 0])

		selection.select()
		property = caedium.frm.Property('theta', selection)
		property.appendParent('Constants').appendParent('Simulation')
		property.set(0)

		selection.select()
		property = caedium.frm.Property('Duration', selection)
		property.appendParent('Time').appendParent('Simulation')
		property.set(2500)
		
		selection.select()
		tool = caedium.control.Run()
		tool.addTo(selection)

Then I added a loop to the script to change alpha, run the simulation for a certain number of iterations, and save a copy of the simulation. Rather than start each simulation from scratch I used the previous simulation as an initial flow field for each new alpha.

class Script:
	"""Caedium Script
	"""
	def run(self):
		steps = 6
		alphaDeltaDegrees = 2
		simulationDeltaStep = 25
		speed = 247.73
		
		for i in range(0, steps + 1):
			simulationSteps = (i + 1) * simulationDeltaStep
			alphaDegrees = i * alphaDeltaDegrees
			alphaRadians = math.radians(alphaDegrees)
			Ux = speed * math.cos(alphaRadians)
			Uz = speed * math.sin(alphaRadians)
		
			selection = caedium.select.View(simulation = 'sim', view = 'view', 
			 camera = 'camera')
			selection.select(['flow-volume'])
			property = caedium.frm.Property('UDefaultValue', selection)
			property.appendParent('U').appendParent('Reference').\
			 appendParent('MaterialProperties').appendParent('PropertiesGroup').\
			 appendParent('Air').appendParent('Geometry')
			property.set([Ux, 0, Uz])

			selection.select()
			property = caedium.frm.Property('theta', selection)
			property.appendParent('Constants').appendParent('Simulation')
			property.set(alphaRadians)

			selection.select()
			property = caedium.frm.Property('Duration', selection)
			property.appendParent('Time').appendParent('Simulation')
			property.set(simulationSteps)
			
			selection.select()
			tool = caedium.control.Run()
			tool.addTo(selection)

			tool = caedium.file.CopyAs('dpw4-M0-7-Alpha-' \
			 + str(alphaDegrees) + '.sym')
			tool.do()

		tool = caedium.file.SaveAs('dpw4-M0-7-sweep-complete.sym')
		tool.do()

Note I parameterized the script to run from 0 to 12 degrees in 2 degree increments.

Results

CFD Simulation of an AirlinerCFD Simulation of an AirlinerAlpha = 6 degrees, streamlines colored by velocity magnitude

The lift and drag forces at each alpha condition are shown below.

Lift and Drag vs Angle of Attack (alpha)

Conclusion

By using the Python script to automate this incidence sweep I could leave the entire sequence of simulations unattended. I also had the option to watch the simulations as they progressed and intervene (interrupt the script) at any time.

Notes

  • Similar geometry used in this study was also the focus of the 4th AIAA CFD Drag Prediction Workshop
  • The conditions for this study were:
  • The symmetrical half model geometry was imported as STEP (.stp) and configured as a watertight flow volume in Caedium Professional. The CFD simulation was performed using the compressible, steady-state RANS solver, and the k-omega SST turbulence model. Caedium supports the recording and playing of Python-based scripts.