A script to create the Sandia blade from its definition CSV file.


In [1]:
cd D:\Dropbox\ucla\research\perry\github-desktop\spardesign2


D:\Dropbox\ucla\research\perry\github-desktop\spardesign2

Before starting, we have created a path called "sandia_blade".


In [2]:
ls


 Volume in drive D is Storage
 Volume Serial Number is 3685-CB1A

 Directory of D:\Dropbox\ucla\research\perry\github-desktop\spardesign2

07/26/2013  10:31 AM    <DIR>          .
07/26/2013  10:31 AM    <DIR>          ..
07/24/2013  07:27 PM    <DIR>          .git
07/23/2013  01:05 PM                30 .gitignore
07/26/2013  11:33 AM           569,419 2013-07-26_demo.ipynb
07/24/2013  02:19 PM             3,968 airfoil_script.py
07/26/2013  11:27 AM           335,240 blade.log
07/24/2013  07:24 PM               599 clean.py
07/24/2013  07:16 PM               767 create_blade.py
07/23/2013  01:05 PM             1,001 README.md
07/23/2013  01:05 PM           162,301 reorg_flowchart.pdf
07/23/2013  01:05 PM           303,616 reorg_flowchart.vsd
07/26/2013  11:27 AM    <DIR>          sandia_blade
07/26/2013  11:20 AM    <DIR>          scripts
07/26/2013  11:27 AM         2,143,332 station.log
              10 File(s)      3,520,273 bytes
               5 Dir(s)  537,104,678,912 bytes free

Inside the path "sandia_blade", there is (1) a blade definition file "blade_definition.csv", and (2) a path "airfoils" that contains nondimensional airfoil coordinates.


In [3]:
ls sandia_blade


 Volume in drive D is Storage
 Volume Serial Number is 3685-CB1A

 Directory of D:\Dropbox\ucla\research\perry\github-desktop\spardesign2\sandia_blade

07/26/2013  11:27 AM    <DIR>          .
07/26/2013  11:27 AM    <DIR>          ..
07/23/2013  01:05 PM    <DIR>          airfoils
07/24/2013  07:26 PM             3,832 blade_definition.csv
07/26/2013  11:27 AM    <DIR>          stn01
07/26/2013  11:27 AM    <DIR>          stn02
07/26/2013  11:27 AM    <DIR>          stn03
07/26/2013  11:27 AM    <DIR>          stn04
07/26/2013  11:27 AM    <DIR>          stn05
07/26/2013  11:27 AM    <DIR>          stn06
07/26/2013  11:27 AM    <DIR>          stn07
07/26/2013  11:27 AM    <DIR>          stn08
07/26/2013  11:27 AM    <DIR>          stn09
07/26/2013  11:27 AM    <DIR>          stn10
07/26/2013  11:27 AM    <DIR>          stn11
07/26/2013  11:27 AM    <DIR>          stn12
07/26/2013  11:27 AM    <DIR>          stn13
07/26/2013  11:27 AM    <DIR>          stn14
07/26/2013  11:27 AM    <DIR>          stn15
07/26/2013  11:27 AM    <DIR>          stn16
07/26/2013  11:27 AM    <DIR>          stn17
07/26/2013  11:27 AM    <DIR>          stn18
07/26/2013  11:27 AM    <DIR>          stn19
07/26/2013  11:27 AM    <DIR>          stn20
07/26/2013  11:27 AM    <DIR>          stn21
07/26/2013  11:27 AM    <DIR>          stn22
07/26/2013  11:27 AM    <DIR>          stn23
07/26/2013  11:27 AM    <DIR>          stn24
07/26/2013  11:27 AM    <DIR>          stn25
07/26/2013  11:27 AM    <DIR>          stn26
07/26/2013  11:27 AM    <DIR>          stn27
07/26/2013  11:27 AM    <DIR>          stn28
07/26/2013  11:27 AM    <DIR>          stn29
07/26/2013  11:27 AM    <DIR>          stn30
07/26/2013  11:27 AM    <DIR>          stn31
07/26/2013  11:27 AM    <DIR>          stn32
07/26/2013  11:27 AM    <DIR>          stn33
07/26/2013  11:27 AM    <DIR>          stn34
               1 File(s)          3,832 bytes
              37 Dir(s)  537,104,678,912 bytes free

In [4]:
import scripts.blade as bl
b = bl.Blade(name='Sandia blade SNL100-00', blade_path='sandia_blade')


[WindowsError] The station path 'stn01' already exists!
 Created blade station #1
[WindowsError] The station path 'stn02' already exists!
 Created blade station #2
[WindowsError] The station path 'stn03' already exists!
 Created blade station #3
[WindowsError] The station path 'stn04' already exists!
 Created blade station #4
[WindowsError] The station path 'stn05' already exists!
 Created blade station #5
[WindowsError] The station path 'stn06' already exists!
 Created blade station #6
[WindowsError] The station path 'stn07' already exists!
 Created blade station #7
[WindowsError] The station path 'stn08' already exists!
 Created blade station #8
[WindowsError] The station path 'stn09' already exists!
 Created blade station #9
[WindowsError] The station path 'stn10' already exists!
 Created blade station #10
[WindowsError] The station path 'stn11' already exists!
 Created blade station #11
[WindowsError] The station path 'stn12' already exists!
 Created blade station #12
[WindowsError] The station path 'stn13' already exists!
 Created blade station #13
[WindowsError] The station path 'stn14' already exists!
 Created blade station #14
[WindowsError] The station path 'stn15' already exists!
 Created blade station #15
[WindowsError] The station path 'stn16' already exists!
 Created blade station #16
[WindowsError] The station path 'stn17' already exists!
 Created blade station #17
[WindowsError] The station path 'stn18' already exists!
 Created blade station #18
[WindowsError] The station path 'stn19' already exists!
 Created blade station #19
[WindowsError] The station path 'stn20' already exists!
 Created blade station #20
[WindowsError] The station path 'stn21' already exists!
 Created blade station #21
[WindowsError] The station path 'stn22' already exists!
 Created blade station #22
[WindowsError] The station path 'stn23' already exists!
 Created blade station #23
[WindowsError] The station path 'stn24' already exists!
 Created blade station #24
[WindowsError] The station path 'stn25' already exists!
 Created blade station #25
[WindowsError] The station path 'stn26' already exists!
 Created blade station #26
[WindowsError] The station path 'stn27' already exists!
 Created blade station #27
[WindowsError] The station path 'stn28' already exists!
 Created blade station #28
[WindowsError] The station path 'stn29' already exists!
 Created blade station #29
[WindowsError] The station path 'stn30' already exists!
 Created blade station #30
[WindowsError] The station path 'stn31' already exists!
 Created blade station #31
[WindowsError] The station path 'stn32' already exists!
 Created blade station #32
[WindowsError] The station path 'stn33' already exists!
 Created blade station #33
[WindowsError] The station path 'stn34' already exists!
 Created blade station #34

This creates a blade name "Sandia blade SNL100-00", and looks in the path "sandia_blade" for the blade definition file "blade_definition.csv". It also creates a new folder for each blade station (station paths), located inside the path "sandia_blade".


In [5]:
ls sandia_blade


 Volume in drive D is Storage
 Volume Serial Number is 3685-CB1A

 Directory of D:\Dropbox\ucla\research\perry\github-desktop\spardesign2\sandia_blade

07/26/2013  11:27 AM    <DIR>          .
07/26/2013  11:27 AM    <DIR>          ..
07/23/2013  01:05 PM    <DIR>          airfoils
07/24/2013  07:26 PM             3,832 blade_definition.csv
07/26/2013  11:27 AM    <DIR>          stn01
07/26/2013  11:27 AM    <DIR>          stn02
07/26/2013  11:27 AM    <DIR>          stn03
07/26/2013  11:27 AM    <DIR>          stn04
07/26/2013  11:27 AM    <DIR>          stn05
07/26/2013  11:27 AM    <DIR>          stn06
07/26/2013  11:27 AM    <DIR>          stn07
07/26/2013  11:27 AM    <DIR>          stn08
07/26/2013  11:27 AM    <DIR>          stn09
07/26/2013  11:27 AM    <DIR>          stn10
07/26/2013  11:27 AM    <DIR>          stn11
07/26/2013  11:27 AM    <DIR>          stn12
07/26/2013  11:27 AM    <DIR>          stn13
07/26/2013  11:27 AM    <DIR>          stn14
07/26/2013  11:27 AM    <DIR>          stn15
07/26/2013  11:27 AM    <DIR>          stn16
07/26/2013  11:27 AM    <DIR>          stn17
07/26/2013  11:27 AM    <DIR>          stn18
07/26/2013  11:27 AM    <DIR>          stn19
07/26/2013  11:27 AM    <DIR>          stn20
07/26/2013  11:27 AM    <DIR>          stn21
07/26/2013  11:27 AM    <DIR>          stn22
07/26/2013  11:27 AM    <DIR>          stn23
07/26/2013  11:27 AM    <DIR>          stn24
07/26/2013  11:27 AM    <DIR>          stn25
07/26/2013  11:27 AM    <DIR>          stn26
07/26/2013  11:27 AM    <DIR>          stn27
07/26/2013  11:27 AM    <DIR>          stn28
07/26/2013  11:27 AM    <DIR>          stn29
07/26/2013  11:27 AM    <DIR>          stn30
07/26/2013  11:27 AM    <DIR>          stn31
07/26/2013  11:27 AM    <DIR>          stn32
07/26/2013  11:27 AM    <DIR>          stn33
07/26/2013  11:27 AM    <DIR>          stn34
               1 File(s)          3,832 bytes
              37 Dir(s)  537,104,637,952 bytes free

If our blade definition file was named something else, we could have called:
b = bl.Blade(name='Sandia blade SNL100-00', blade_path='sandia_blade', defn_filename='some_file.csv')

Next, we'll copy all the airfoil coordinates from "sandia_blade/airfoils" into the appropriate station path.


In [6]:
b.copy_all_airfoil_coords()


 Copied station #1 airfoil: Cylinder
 ... Assigned station.airfoil.path!
 Copied station #2 airfoil: Cylinder
 ... Assigned station.airfoil.path!
 Copied station #3 airfoil: SNL-100m-0pt007
 ... Assigned station.airfoil.path!
 Copied station #4 airfoil: SNL-100m-0pt009
 ... Assigned station.airfoil.path!
 Copied station #5 airfoil: SNL-100m-0pt011
 ... Assigned station.airfoil.path!
 Copied station #6 airfoil: SNL-100m-Ellipse97
 ... Assigned station.airfoil.path!
 Copied station #7 airfoil: SNL-100m-Ellipse93pt1
 ... Assigned station.airfoil.path!
 Copied station #8 airfoil: SNL-100m-Ellipse92pt5
 ... Assigned station.airfoil.path!
 Copied station #9 airfoil: SNL-100m-Transition84
 ... Assigned station.airfoil.path!
 Copied station #10 airfoil: SNL-100m-Transition76
 ... Assigned station.airfoil.path!
 Copied station #11 airfoil: SNL-100m-Transition68
 ... Assigned station.airfoil.path!
 Copied station #12 airfoil: SNL-100m-Transition60
 ... Assigned station.airfoil.path!
 Copied station #13 airfoil: SNL-100m-Transition51
 ... Assigned station.airfoil.path!
 Copied station #14 airfoil: SNL-100m-Transition47
 ... Assigned station.airfoil.path!
 Copied station #15 airfoil: SNL-100m-Transition43pt5
 ... Assigned station.airfoil.path!
 Copied station #16 airfoil: DU99-W-405
 ... Assigned station.airfoil.path!
 Copied station #17 airfoil: DU99-W-405_38
 ... Assigned station.airfoil.path!
 Copied station #18 airfoil: DU99-W-350_36
 ... Assigned station.airfoil.path!
 Copied station #19 airfoil: DU99-W-350_34
 ... Assigned station.airfoil.path!
 Copied station #20 airfoil: DU97-W-300
 ... Assigned station.airfoil.path!
 Copied station #21 airfoil: DU91-W2-250_26
 ... Assigned station.airfoil.path!
 Copied station #22 airfoil: DU93-W-210_23
 ... Assigned station.airfoil.path!
 Copied station #23 airfoil: DU93-W-210
 ... Assigned station.airfoil.path!
 Copied station #24 airfoil: NACA_64-618_19
 ... Assigned station.airfoil.path!
 Copied station #25 airfoil: NACA_64-618_18pt5
 ... Assigned station.airfoil.path!
 Copied station #26 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #27 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #28 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #29 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #30 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #31 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #32 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #33 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!
 Copied station #34 airfoil: NACA_64-618
 ... Assigned station.airfoil.path!

Next, we can plot the (dimensional) airfoils at each blade station.


In [7]:
for station in b.list_of_stations:
    station.read_airfoil_coords()
    station.plot_airfoil_coords(show_flag=True, savefig_flag=True)
    # show_flag : bool, show plots on the screen
    # save_fig_flag : bool (default is True), save airfoil plots to each station path


<matplotlib.figure.Figure at 0x8213a58>
<matplotlib.figure.Figure at 0x7d26f28>
<matplotlib.figure.Figure at 0x8e27278>
<matplotlib.figure.Figure at 0x90a9668>
<matplotlib.figure.Figure at 0x8e38550>
<matplotlib.figure.Figure at 0x90a30f0>
<matplotlib.figure.Figure at 0x2630978>
<matplotlib.figure.Figure at 0x2630860>
<matplotlib.figure.Figure at 0x2630be0>
<matplotlib.figure.Figure at 0x836afd0>
<matplotlib.figure.Figure at 0x836afd0>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x836afd0>
<matplotlib.figure.Figure at 0x836afd0>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x836a860>
<matplotlib.figure.Figure at 0x836a860>
<matplotlib.figure.Figure at 0x836a860>
<matplotlib.figure.Figure at 0x836a860>
<matplotlib.figure.Figure at 0x836a780>
<matplotlib.figure.Figure at 0x82139e8>
<matplotlib.figure.Figure at 0x8213a58>
<matplotlib.figure.Figure at 0x82139e8>
<matplotlib.figure.Figure at 0x909c1d0>
<matplotlib.figure.Figure at 0x2630860>
<matplotlib.figure.Figure at 0x82139e8>
<matplotlib.figure.Figure at 0x8213a90>
<matplotlib.figure.Figure at 0x2630978>
<matplotlib.figure.Figure at 0x2630860>
<matplotlib.figure.Figure at 0x7d26f28>

Now, let's explore all the blade definition data that we've imported into the variable b.
We can see how many blade stations there are:


In [8]:
b.number_of_stations


Out[8]:
34

Each of the blade stations can be accessed from the list b.list_of_stations


In [9]:
b.list_of_stations


Out[9]:
[<scripts.station.Station instance at 0x0000000008E08288>,
 <scripts.station.Station instance at 0x0000000008E085C8>,
 <scripts.station.Station instance at 0x0000000008E088C8>,
 <scripts.station.Station instance at 0x0000000008E08BC8>,
 <scripts.station.Station instance at 0x0000000008E08EC8>,
 <scripts.station.Station instance at 0x0000000008E081C8>,
 <scripts.station.Station instance at 0x0000000008E09508>,
 <scripts.station.Station instance at 0x0000000008E09848>,
 <scripts.station.Station instance at 0x0000000008E09B88>,
 <scripts.station.Station instance at 0x0000000008E09EC8>,
 <scripts.station.Station instance at 0x0000000008E09208>,
 <scripts.station.Station instance at 0x0000000008E0A588>,
 <scripts.station.Station instance at 0x0000000008E0A8C8>,
 <scripts.station.Station instance at 0x0000000008E0AC08>,
 <scripts.station.Station instance at 0x0000000008E0AF48>,
 <scripts.station.Station instance at 0x0000000008E0A248>,
 <scripts.station.Station instance at 0x0000000008E0B5C8>,
 <scripts.station.Station instance at 0x0000000008E0B8C8>,
 <scripts.station.Station instance at 0x0000000008E0BBC8>,
 <scripts.station.Station instance at 0x0000000008E0BEC8>,
 <scripts.station.Station instance at 0x0000000008E0B2C8>,
 <scripts.station.Station instance at 0x0000000008E0C508>,
 <scripts.station.Station instance at 0x0000000008E0C808>,
 <scripts.station.Station instance at 0x0000000008E0CB08>,
 <scripts.station.Station instance at 0x0000000008E0CE08>,
 <scripts.station.Station instance at 0x0000000008E0C208>,
 <scripts.station.Station instance at 0x0000000008E0D448>,
 <scripts.station.Station instance at 0x0000000008E0D748>,
 <scripts.station.Station instance at 0x0000000008E0DA48>,
 <scripts.station.Station instance at 0x0000000008E0DD48>,
 <scripts.station.Station instance at 0x0000000008E0D148>,
 <scripts.station.Station instance at 0x0000000008E0DFC8>,
 <scripts.station.Station instance at 0x0000000008E10688>,
 <scripts.station.Station instance at 0x0000000008E10988>]

This may look like nonsense, but each item in the list is a Python object. Notice that there are 34 items in the list above.
We can access individual blade station objects by specifying an index:


In [10]:
b.list_of_stations[25]


Out[10]:
<scripts.station.Station instance at 0x0000000008E0C208>

There are many attributes for each blade station.
We can access the station number:


In [11]:
b.list_of_stations[25].station_num


Out[11]:
26

Notice that the index of list_of_stations is one off from the attribute .station_num. This is because Python lists start indexing at zero.
We can also access the station path:


In [12]:
b.list_of_stations[25].station_path


Out[12]:
'D:\\Dropbox\\ucla\\research\\perry\\github-desktop\\spardesign2\\sandia_blade\\stn26'

The attributes for each blade station are organized into three categories:

1. coordinates : `<station>.coords` (where the station is located)  
2. airfoil properties : `<station>.airfoil` (external airfoil dimensions)  
3. structure properties : `<station>.structure` (internal structure dimensions)  

Station coordinates

We can access the coordinates of a blade station:


In [13]:
print b.list_of_stations[25].coords


x1:   73.200 (meters)
x2:    0.000 (meters)
x3:    0.000 (meters)

In [14]:
print (b.list_of_stations[25].coords.x1, b.list_of_stations[25].coords.x2, b.list_of_stations[25].coords.x3)


(73.200000000000003, 0, 0)

Here, x1 is the spanwise coordinate, x2 is the edgewise coordinate, and x3 is the flapwise coordinate.

Station airfoil properties

We can print a summary of the airfoil properties:


In [15]:
print b.list_of_stations[25].airfoil


Airfoil:     NACA_64-618
Filename:    NACA_64-618.txt
Pitch axis:   0.375 (chord fraction)
Chord:        4.621 (meters)
Twist:        2.735 (degrees)

We can access individual attributes, like the airfoil name, pitch axis fraction, chord length, and twist:


In [16]:
b.list_of_stations[25].airfoil.name


Out[16]:
'NACA_64-618'

In [17]:
b.list_of_stations[25].airfoil.pitch_axis


Out[17]:
0.375

In [18]:
b.list_of_stations[25].airfoil.chord


Out[18]:
4.6210000000000004

In [19]:
b.list_of_stations[25].airfoil.twist


Out[19]:
2.7349999999999999

We can also access the path of the nondimensional airfoil coordinates:


In [20]:
b.list_of_stations[25].airfoil.path


Out[20]:
'D:\\Dropbox\\ucla\\research\\perry\\github-desktop\\spardesign2\\sandia_blade\\stn26\\NACA_64-618.txt'

Station structure properties

We can print a summary of dimensions for each structural component at this station


In [21]:
print b.list_of_stations[25].structure


--- ROOT BUILDUP ---
base:    nan (meters)
height:  nan (meters)
--- SPAR CAP ---
base:    1.5 (meters)
height:  0.047 (meters)
--- SHEAR WEB 1 ---
base:     0.086 (meters)
|-> base_biax:   0.003 (meters)
|-> base_foam:   0.080 (meters)
height:  nan (meters)
--- SHEAR WEB 2 ---
base:     0.086 (meters)
|-> base_biax:   0.003 (meters)
|-> base_foam:   0.080 (meters)
height:  nan (meters)
--- SHEAR WEB 3 ---
base:       nan (meters)
|-> base_biax:     nan (meters)
|-> base_foam:     nan (meters)
height:  nan (meters)
---TE REINFORCEMENT ---
base:     1.000 (meters)
height:   0.014 (meters)
|-> height_uniax:   0.004 (meters)
|-> height_foam:    0.010 (meters)
--- LE PANEL ---
base:    nan (meters)
height:  0.045 (meters)
--- AFT PANEL ---
base:    nan (meters)
height:  0.045 (meters)

We can access individual dimensions, too.
For example, we can access the spar cap height:


In [22]:
b.list_of_stations[25].structure.spar_cap.height


Out[22]:
0.047

Or, we can access the height of the uniaxial GFRP layer in the trailing edge reinforcement:


In [23]:
b.list_of_stations[25].structure.TE_reinforcement.height_uniax


Out[23]:
0.0040000000000000001

Plots of chord and twist schedule

Finally, we can also look at some plots of the blade as a whole.

For example, we can plot the chord vs. span, which almost give us a flapwise view of the blade.


In [24]:
b.plot_chord_schedule()


We can also plot the twist vs. span:


In [25]:
b.plot_twist_schedule()



In [25]: