Genair is a specialized CAD package for the purpose of creating 3D aircraft configurations. It was created by Hugo Gagnon.

The user manual for Genair can be found here:
genair_user_manual.pdf

On the new machines, you may need to install the conda maplotlib package, which sometimes necessitates a re-install of anaconda. This is described here.


Below is a list of instructions on how to do various things with this tool.



Create Airfoil Object
Create Wing Segment

Rotate View


Left click and hold while moving mouse. Make sure numlock is off

Load a Previously Created Aircraft Object


In [5]: pwd

Out[5]: u'/nfs/kris/d1/people/howard/genair/play'
In [6]: ls

BCC_geometry.20130307/ BCC_geometry.20130515/ BCC_geometry_no_fuse/ foils/ tutorial_w_hugo/
In [7]: cd BCC_geometry.20130515/

In [8]: ls

bcc.dat bcc.igs bcc.p bcc.tin foils.p fus.p merged_wing.p tmp.dat wingSections.p

In [10]: load(fn='bcc.p')
Out[10]: [<geom.aircraft.Aircraft at 0x3da0b50>]

In [11]: bcc = _[0]

In [13]: bcc.blowup()
Out[13]:

[('tail', <geom.wing.Wing at 0x3d1c950>),

('wing', <geom.wing.WingMerger at 0x44432d0>),

('fuselage', <geom.fuselage.Fuselage at 0x7c49210>)]

Load Previously Created Wing Sections and Merge To Form A Wing

In [1]: cd BCC_geometry.20130515/
/nfs/kris/d1/people/howard/genair/play/BCC_geometry.20130515

In [2]: load(fn='wingSections.p')
Out[2]:
[<geom.wing.Wing at 0x45f4210>,
<geom.wing.Wing at 0x471b590>,
<geom.wing.Wing at 0x4735990>,
<geom.wing.Wing at 0x4884410>]

In [3]: ws1 = _[0]
In [4]: ws2 = _[1]
In [5]: ws3 = _[2]
In [6]: ws4 = _[3]

In [7]: wing_untrimmed = WingMerger(ws1,ws2,ws3,ws4)

In [9]: wing_untrimmed.merge(None)
geom.wing.WingMerger.merge :: Wing object translated by array([ 12.02794262, 15.6727326 , 0.27356857])
geom.wing.WingMerger.merge :: Wing object scaled (X) by 1.0000000000000002
geom.wing.WingMerger.merge :: Wing object scaled (Z) by 1.0
geom.wing.WingMerger.merge :: Wing object translated by array([ 18.83327359, 24.54026183, 0.42835186])
geom.wing.WingMerger.merge :: Wing object scaled (X) by 1.0000000000000004
geom.wing.WingMerger.merge :: Wing object scaled (Z) by 1.0000000000000127
geom.wing.WingMerger.merge :: Wing object translated by array([ 36.09107141, 47.02763637, 0.82087045])
geom.wing.WingMerger.merge :: Wing object scaled (X) by 1.0000000000000018
geom.wing.WingMerger.merge :: Wing object scaled (Z) by 1.0
Out[9]: <plot.figure.Figure at 0x49c02d0>

In [10]: wing_untrimmed.glue()

In [12]: save(wing_untrimmed,fn='wing_untrimmed.p')

Add a Wing Tip Cap to Merged Wing


In [16]: ws1m,ws2m,ws3m,ws4m = wing_untrimmed.merged_wings
In [17]: tip = ws4m.generate_tip()
In [18]: tip.fill(l=5,dl=3)
In [20]: draw(wing_untrimmed)
In [21]: wing_untrimmed.glue()
In [12]: save(wing_untrimmed,fn='wing_untrimmed.p')

Translate Wing

In [29]: sec1m = wing_untrimmed.merged_wings[0]
In [30]: sec1m.LE.eval_point(0)
Out[30]: array([ 0., 0., 0.])
In [32]: wing_untrimmed.translate([28.446,0,-3.8] - _[0])

Trim Wing at Intersection With Fuselage

In [91]: jnc = sec1m.generate_trimmed_junction(fuselage.nurbs)

In [93]: jnc.extend()
Out[93]: <plot.figure.Figure at 0xebdb9d0>

In [112]: jnc.intersect(CRT=5e-3, ANT=1e-2, show=True)

geom.junction.TrimmedJunction.intersect :: LE starting point found: [ 16.5871038 4.0929427 -3.62855742]

nurbs.surface.surface_surface_intersect :: marched 100 points
nurbs.surface.surface_surface_intersect :: marched 200 points
nurbs.surface.surface_surface_intersect :: marched 300 points
....
nurbs.surface.surface_surface_intersect :: marched 4300 points

nurbs.surface.surface_surface_intersect :: marched 100 points
nurbs.surface.surface_surface_intersect :: marched 200 points
nurbs.surface.surface_surface_intersect :: marched 300 points
.....
nurbs.surface.surface_surface_intersect :: marched 4300 points

Out[112]: <plot.figure.Figure at 0x10c85f90>

In [113]: jnc.trim()
Out[113]: <plot.figure.Figure at 0x1194e2d0>

Script for Forming Wing Objects from Wing Sections Read from Files



NOTE: The script can be found here:
/nfs/kris/d1/people/howard/genair/play/BCC_geometry_flying_shape

      • run -i datsToWings.py
      • w0, w1, w2, w3 = wis

      • w3.T = w3.LE # since the sweep is relative to the trajectory curve, which is set to the TE curve in the script
      • w3.glue()
      • w3.sweep = 48.5

      • draw(w0, w1, w2, w3)

You can see the fitting winglet:

      • figX.inject(deflected_wing)

You can create a WingMerger object:

      • wm = WingMerger(w0, w1, w2, w3)
      • wm.merged_wings = list(wm.wings)

Don't forget to create a Wingtip using w3!

Move Objects With Mouse

Turn on 'translate NUBRBS mode' when viewing drawn objects:
Ctrl + Alt + n

Pick any surface to move with mouse:
Ctrl + Shift + <hold down left mouse>

Move Individual FFD-Volume Control Points

Disable Num Lock key if you are on a Linux platform.

Pick an FFD-volume control point from the openGL window:
Ctrl + Alt + Left Click

The properties of this object will now be stored (temporarily) in: last_picked_xyz and last_picked_object. From here, you can assign the Point object and its coordinates to a set of variables:
ln[1]: p0 = last_picked_object
ln[2]: p0_xyz = last_picked_xyz

Change its coordinates via translation:
ln[3]: p0.translate([p0_xyz[0] + dx, p0_xyz[1] + dy, p0_xyz[2] + dz])

To undo:
Ctrl + Alt + U

These changes will take effect immediately in the openGL window. Following these changes, write out the FFD-volume files, axial.con, axial.b, and ffd.b as per usual.

Create an Aircraft Object

In [98]: bcc = Aircraft(fuselage=fuselage,main_wing=wm,tail=tail)
In [100]: bcc.colorize
In [99]: draw(bcc)
In [103]: save(bcc,fn='bcc_flying_wing_shape.p')

Write Out Aircraft Geometry in IGES Format

In [104]: geom.io.save_IGES(bcc)

Trim a Wing/Tail Object at Symmetry Plane

In [10]: load(fn='bcc.p')
Out[10]: [<geom.aircraft.Aircraft at 0x3da0b50>]

In [11]: bcc = _[0]

In [13]: bcc.blowup()
Out[13]:

[('tail', <geom.wing.Wing at 0x3d1c950>),

('wing', <geom.wing.WingMerger at 0x44432d0>),

('fuselage', <geom.fuselage.Fuselage at 0x7c49210>)]

In [14]: tail.snap()

Redo Fuselage Fairing Molder


Each time you generate a new molder the fuselage's last nurbs surface is saved on the molder object. So, for example, if you have three molders and assuming the last one is called "mfair", mfair.nurbs holds the previous fuselage Surface. So if you want to undo a molder, do the following:
First list the existing fuselage molders:

In [125]: fuselage.molders
Out[125]:
[<geom.fuselage.FuselageMolder at 0xdae57d0>,
<geom.fuselage.FuselageMolder at 0xe1bc250>,
<geom.fuselage.FairingMolder at 0xe3f3310>]

Put the fairing molder object into a variable called "mfair":

In [129]: mfair = fuselage.molders[2]
In [130]: mfair
Out[130]: <geom.fuselage.FairingMolder at 0xe3f3310>

Reset the fuselage surface to that before fairing molder

In [131]: fuselage.nurbs = mfair.nurbs

Discard existing fairing molder:

In [132]: fuselage.molders.pop()
Out[132]: <geom.fuselage.FairingMolder at 0xe3f3310>

Create a new fairing molder:

In [141]: mfair = fuselage.mold_fairing(21.08*1.5,0.5)

Translate the fairing molder:

In [145]: mfair.translate([26.85,0,0])

Embed the fairing molder into the fuselage object:

In [184]: mfair.embed(fuselage)

Manually adjust yellow "pilot" points to modify fairing geometry


Setup An FFD Optimization

The basic workflow for setting up an FFD optimization is as follows:
1. Create a wing geometry using GENAIR
2. Create a grid around the wing geometry using ICEMCFD
3. Fit the grid using JETSTREAM
4. Create FFD volume and axial curve using GENAIR
5. Check to see if FFD volume is large enough to enclose wing geometry and corresponding surface patches
6. Create files using GENAIR that define axial curve and FFD volume to be used by JETSTREAM for an FFD optimization
7. Manually modify "axial.con" file to assign DOF's to FFD sections and axial control points

Click here for a script to perform above steps 4 - 6.

The following JETSTREAM input parameters must be used for an FFD optimization:
JTSTRM% FFD = .TRUE.
JTSTRM% AXLFFD = .TRUE.
JTSTRM% LIN_TWIST_CNSTRNT
JTSTRM% LIN_TAPER_CNSTRNT
JTSTRM% AXLILPNT_CNSTRNT
JTSTRM% GEO_LOW
JTSTRM% GEO_UPP

Assume that you are using an updated version of GENAIR;
GENAIR GIT ID: c5e186...

Assume that you have installed Anaconda Python by Continuum Analytics. Hugo switched Python distro that GENAIR uses from EPD to Anaconda in early 2014
!-- Go to top-level GENAIR directory
[howard@drno genair]$ cd ~/genair/

!-- Switch to bash shell if not currently in one
[howard@drno genair]$ bash

!-- Activate GENAIR directory in a bash shell
[howard@drno genair]$ source activate genair

!-- Start GENAIR
(genair)[howard@drno genair]$ ./main.py

!-- Copy grid files to GENAIR working directory (.g, .con, .map, patch.con)
!-- GENAIR working directory is typically a subdirectory under ~/genair/play/
!--
!--
!--
gd = Grid()
gd.read_grid()
gd.read_connectivity()
gd.read_map()
gd.read_patch()
save(gd, fn=‘grid.p’)

!-- Displays some info about usage of make_axial_from_wing
opti.axial.make_axial_from_wing?

!-- The following command assumes that a wing object named "wi" exists
ax = opti.axial.make_axial_from_ wing(wi, 'QC', 2, 1, (10,5,2), (3,3,1), [(0.005,0.005), (0,0), (0.005,0.005)])
ax.snap_ffd() # optional, only if ffd falls on the symmetry plane


Scale An Airfoil


af.glue()
af.scale(scaling_factor, L=[0,0,1])