# ==== Use Case 2 ====# vsp.VSPRenew() errorMgr.PopErrorAndPrint(stdout) geoms = vsp.FindGeoms() print("All geoms in Vehicle.") print(geoms) # Add Fuse fuse_id = vsp.AddGeom("FUSELAGE") # Get XSec Surf ID xsurf_id = vsp.GetXSecSurf(fuse_id, 0) # Change Type of First XSec vsp.ChangeXSecShape(xsurf_id, 0, vsp.XS_SUPER_ELLIPSE) errorMgr.PopErrorAndPrint(stdout) # Change Type First XSec Properties xsec_id = vsp.GetXSec(xsurf_id, 0) width_id = vsp.GetXSecParm(xsec_id, "Super_Width") height_id = vsp.GetXSecParm(xsec_id, "Super_Height") vsp.SetParmVal(width_id, 4.0) vsp.SetParmVal(height_id, 2.0) # Copy Cross-Section to Clipboard vsp.CopyXSec(fuse_id, 0)
def vsp_read_fuselage(fuselage_id, units_type='SI', fineness=True): """This reads an OpenVSP fuselage geometry and writes it to a SUAVE fuselage format. Assumptions: 1. OpenVSP fuselage is "conventionally shaped" (generally narrow at nose and tail, wider in center). 2. Fuselage is designed in VSP as it appears in real life. That is, the VSP model does not rely on superficial elements such as canopies, stacks, or additional fuselages to cover up internal lofting oddities. 3. This program will NOT account for multiple geometries comprising the fuselage. For example: a wingbox mounted beneath is a separate geometry and will NOT be processed. 4. Fuselage origin is located at nose. VSP file origin can be located anywhere, preferably at the forward tip of the vehicle or in front (to make all X-coordinates of vehicle positive). 5. Written for OpenVSP 3.16.1 Source: N/A Inputs: 0. Pre-loaded VSP vehicle in memory, via vsp_read. 1. VSP 10-digit geom ID for fuselage. 2. Units_type set to 'SI' (default) or 'Imperial'. 3. Boolean for whether or not to compute fuselage finenesses (default = True). 4. Uses exterior function get_vsp_areas, in SUAVE/trunk/SUAVE/Input_Output/OpenVSP. Outputs: Writes SUAVE fuselage, with these geometries: (all defaults are SI, but user may specify Imperial) Fuselages.Fuselage. origin [m] in all three dimensions width [m] lengths. total [m] nose [m] tail [m] heights. maximum [m] at_quarter_length [m] at_three_quarters_length [m] effective_diameter [m] fineness.nose [-] ratio of nose section length to fuselage effective diameter fineness.tail [-] ratio of tail section length to fuselage effective diameter areas.wetted [m^2] tag <string> segment[]. (segments are in ordered container and callable by number) vsp.shape [point,circle,round_rect,general_fuse,fuse_file] vsp.xsec_id <10 digit string> percent_x_location percent_z_location height width length effective_diameter tag vsp.xsec_num <integer of fuselage segment quantity> vsp.xsec_surf_id <10 digit string> Properties Used: N/A """ fuselage = SUAVE.Components.Fuselages.Fuselage() if units_type == 'SI': units_factor = Units.meter * 1. else: units_factor = Units.foot * 1. if vsp.GetGeomName(fuselage_id): fuselage.tag = vsp.GetGeomName(fuselage_id) else: fuselage.tag = 'FuselageGeom' fuselage.origin[0][0] = vsp.GetParmVal(fuselage_id, 'X_Location', 'XForm') * units_factor fuselage.origin[0][1] = vsp.GetParmVal(fuselage_id, 'Y_Location', 'XForm') * units_factor fuselage.origin[0][2] = vsp.GetParmVal(fuselage_id, 'Z_Location', 'XForm') * units_factor fuselage.lengths.total = vsp.GetParmVal(fuselage_id, 'Length', 'Design') * units_factor fuselage.vsp_data.xsec_surf_id = vsp.GetXSecSurf( fuselage_id, 0) # There is only one XSecSurf in geom. fuselage.vsp_data.xsec_num = vsp.GetNumXSec( fuselage.vsp_data.xsec_surf_id) # Number of xsecs in fuselage. x_locs = [] heights = [] widths = [] eff_diams = [] lengths = [] # ----------------- # Fuselage segments # ----------------- for ii in range(0, fuselage.vsp_data.xsec_num): segment = SUAVE.Components.Fuselages.Segment() segment.vsp_data.xsec_id = vsp.GetXSec(fuselage.vsp_data.xsec_surf_id, ii) # VSP XSec ID. segment.tag = 'segment_' + str(ii) segment.percent_x_location = vsp.GetParmVal( fuselage_id, 'XLocPercent', 'XSec_' + str(ii)) # Along fuselage length. segment.percent_z_location = vsp.GetParmVal( fuselage_id, 'ZLocPercent', 'XSec_' + str(ii)) # Vertical deviation of fuselage center. segment.height = vsp.GetXSecHeight( segment.vsp_data.xsec_id) * units_factor segment.width = vsp.GetXSecWidth( segment.vsp_data.xsec_id) * units_factor segment.effective_diameter = (segment.height + segment.width) / 2. x_locs.append(segment.percent_x_location ) # Save into arrays for later computation. heights.append(segment.height) widths.append(segment.width) eff_diams.append(segment.effective_diameter) if ii != ( fuselage.vsp_data.xsec_num - 1 ): # Segment length: stored as length since previous segment. (First segment will have length 0.0.) segment.length = fuselage.lengths.total * ( fuselage.Segments[ii + 1].percent_x_location - segment.percent_x_location) * units_factor else: segment.length = 0.0 lengths.append(segment.length) shape = vsp.GetXSecShape(segment.vsp_data.xsec_id) shape_dict = { 0: 'point', 1: 'circle', 2: 'ellipse', 3: 'super ellipse', 4: 'rounded rectangle', 5: 'general fuse', 6: 'fuse file' } segment.vsp_data.shape = shape_dict[shape] fuselage.Segments.append(segment) fuselage.heights.at_quarter_length = get_fuselage_height( fuselage, .25) # Calls get_fuselage_height function (below). fuselage.heights.at_three_quarters_length = get_fuselage_height( fuselage, .75) fuselage.heights.at_wing_root_quarter_chord = get_fuselage_height( fuselage, .4) fuselage.heights.maximum = max(heights) # Max segment height. fuselage.width = max(widths) # Max segment width. fuselage.effective_diameter = max(eff_diams) # Max segment effective diam. fuselage.areas.front_projected = np.pi * ( (fuselage.effective_diameter) / 2)**2 eff_diam_gradients_fwd = np.array(eff_diams[1:]) - np.array( eff_diams[:-1]) # Compute gradients of segment effective diameters. eff_diam_gradients_fwd = np.multiply(eff_diam_gradients_fwd, lengths[:-1]) fuselage = compute_fuselage_fineness(fuselage, x_locs, eff_diams, eff_diam_gradients_fwd) return fuselage
def vsp_read_wing(wing_id, units_type='SI'): """This reads an OpenVSP wing vehicle geometry and writes it into a SUAVE wing format. Assumptions: 1. OpenVSP wing is divided into segments ("XSecs" in VSP). 2. Written for OpenVSP 3.16.1 Source: N/A Inputs: 0. Pre-loaded VSP vehicle in memory, via vsp_read. 1. VSP 10-digit geom ID for wing. 2. units_type set to 'SI' (default) or 'Imperial'. Outputs: Writes SUAVE wing object, with these geometries, from VSP: Wings.Wing. (* is all keys) origin [m] in all three dimensions spans.projected [m] chords.root [m] chords.tip [m] aspect_ratio [-] sweeps.quarter_chord [radians] twists.root [radians] twists.tip [radians] thickness_to_chord [-] dihedral [radians] symmetric <boolean> tag <string> areas.exposed [m^2] areas.reference [m^2] areas.wetted [m^2] Segments. tag <string> twist [radians] percent_span_location [-] .1 is 10% root_chord_percent [-] .1 is 10% dihedral_outboard [radians] sweeps.quarter_chord [radians] thickness_to_chord [-] airfoil <NACA 4-series, 6 series, or airfoil file> Properties Used: N/A """ if units_type == 'SI': units_factor = Units.meter * 1. else: units_factor = Units.foot * 1. wing = SUAVE.Components.Wings.Wing() if vsp.GetGeomName(wing_id): wing.tag = vsp.GetGeomName(wing_id) else: wing.tag = 'WingGeom' wing.origin[0] = vsp.GetParmVal(wing_id, 'X_Location', 'XForm') * units_factor wing.origin[1] = vsp.GetParmVal(wing_id, 'Y_Location', 'XForm') * units_factor wing.origin[2] = vsp.GetParmVal(wing_id, 'Z_Location', 'XForm') * units_factor sym_planar = vsp.GetParmVal(wing_id, 'Sym_Planar_Flag', 'Sym') sym_origin = vsp.GetParmVal(wing_id, 'Sym_Ancestor', 'Sym') # Get the initial rotation to get the dihedral angles x_rot = vsp.GetParmVal(wing_id, 'X_Rotation', 'XForm') # Check if this is vertical tail and get the rotation if x_rot >= 70: wing.vertical = True if sym_planar == 2. and sym_origin == 2.: #origin at wing, not vehicle wing.symmetric == True else: wing.symmetric == False wing.aspect_ratio = vsp.GetParmVal(wing_id, 'TotalAR', 'WingGeom') xsec_surf_id = vsp.GetXSecSurf(wing_id, 0) # This is how VSP stores surfaces. segment_num = vsp.GetNumXSec( xsec_surf_id ) # Get number of wing segments (is one more than the VSP GUI shows). total_chord = vsp.GetParmVal(wing_id, 'Root_Chord', 'XSec_1') * units_factor total_proj_span = vsp.GetParmVal(wing_id, 'TotalProjectedSpan', 'WingGeom') * units_factor span_sum = 0. # Non-projected. proj_span_sum = 0. # Projected. segment_spans = [None] * (segment_num) # Non-projected. segment_dihedral = [None] * (segment_num) segment_sweeps_quarter_chord = [None] * (segment_num) # Check for wing segment *inside* fuselage, then skip XSec_0 to start at first exposed segment. if vsp.GetParmVal(wing_id, 'Root_Chord', 'XSec_0') == 1.: start = 1 else: start = 0 # ------------- # Wing segments # ------------- # Convert VSP XSecs to SUAVE segments. (Wing segments are defined by outboard sections in VSP, but inboard sections in SUAVE.) for i in range(start, segment_num + 1): segment = SUAVE.Components.Wings.Segment() segment.tag = 'Section_' + str(i) thick_cord = vsp.GetParmVal(wing_id, 'ThickChord', 'XSecCurve_' + str(i - 1)) segment.thickness_to_chord = thick_cord # Thick_cord stored for use in airfoil, below. segment_root_chord = vsp.GetParmVal(wing_id, 'Root_Chord', 'XSec_' + str(i)) * units_factor segment.root_chord_percent = segment_root_chord / total_chord segment.percent_span_location = proj_span_sum / (total_proj_span / 2) segment.twist = vsp.GetParmVal(wing_id, 'Twist', 'XSec_' + str(i - 1)) * Units.deg if i == start: wing.thickness_to_chord = thick_cord if i < segment_num: # This excludes the tip xsec, but we need a segment in SUAVE to store airfoil. sweep = vsp.GetParmVal(wing_id, 'Sweep', 'XSec_' + str(i)) * Units.deg sweep_loc = vsp.GetParmVal(wing_id, 'Sweep_Location', 'XSec_' + str(i)) AR = vsp.GetParmVal(wing_id, 'Aspect', 'XSec_' + str(i)) taper = vsp.GetParmVal(wing_id, 'Taper', 'XSec_' + str(i)) segment_sweeps_quarter_chord[i] = convert_sweep( sweep, sweep_loc, 0.25, AR, taper) segment.sweeps.quarter_chord = segment_sweeps_quarter_chord[ i] # Used again, below # Used for dihedral computation, below. segment_dihedral[i] = vsp.GetParmVal(wing_id, 'Dihedral', 'XSec_' + str(i)) * Units.deg segment.dihedral_outboard = segment_dihedral[i] segment_spans[i] = vsp.GetParmVal(wing_id, 'Span', 'XSec_' + str(i)) * units_factor proj_span_sum += segment_spans[i] * np.cos(segment_dihedral[i]) span_sum += segment_spans[i] else: segment.root_chord_percent = (vsp.GetParmVal( wing_id, 'Tip_Chord', 'XSec_' + str(i - 1))) * units_factor / total_chord # XSec airfoil jj = i - 1 # Airfoil index i-1 because VSP airfoils and sections are one index off relative to SUAVE. xsec_id = str(vsp.GetXSec(xsec_surf_id, jj)) airfoil = Airfoil() if vsp.GetXSecShape( xsec_id) == vsp.XS_FOUR_SERIES: # XSec shape: NACA 4-series camber = vsp.GetParmVal(wing_id, 'Camber', 'XSecCurve_' + str(jj)) if camber == 0.: camber_loc = 0. else: camber_loc = vsp.GetParmVal(wing_id, 'CamberLoc', 'XSecCurve_' + str(jj)) airfoil.thickness_to_chord = thick_cord camber_round = int(np.around(camber * 100)) camber_loc_round = int(np.around(camber_loc * 10)) thick_cord_round = int(np.around(thick_cord * 100)) airfoil.tag = 'NACA ' + str(camber_round) + str( camber_loc_round) + str(thick_cord_round) elif vsp.GetXSecShape( xsec_id) == vsp.XS_SIX_SERIES: # XSec shape: NACA 6-series thick_cord_round = int(np.around(thick_cord * 100)) a_value = vsp.GetParmVal(wing_id, 'A', 'XSecCurve_' + str(jj)) ideal_CL = int( np.around( vsp.GetParmVal(wing_id, 'IdealCl', 'XSecCurve_' + str(jj)) * 10)) series_vsp = int( vsp.GetParmVal(wing_id, 'Series', 'XSecCurve_' + str(jj))) series_dict = { 0: '63', 1: '64', 2: '65', 3: '66', 4: '67', 5: '63A', 6: '64A', 7: '65A' } # VSP series values. series = series_dict[series_vsp] airfoil.tag = 'NACA ' + series + str(ideal_CL) + str( thick_cord_round) + ' a=' + str(np.around(a_value, 1)) elif vsp.GetXSecShape( xsec_id ) == vsp.XS_FILE_AIRFOIL: # XSec shape: 12 is type AF_FILE airfoil.thickness_to_chord = thick_cord airfoil.points = vsp.GetAirfoilCoordinates(wing_id, float(jj / segment_num)) # VSP airfoil API calls get coordinates and write files with the final argument being the fraction of segment position, regardless of relative spans. # (Write the root airfoil with final arg = 0. Write 4th airfoil of 5 segments with final arg = .8) vsp.WriteSeligAirfoil( str(wing.tag) + '_airfoil_XSec_' + str(jj) + '.dat', wing_id, float(jj / segment_num)) airfoil.coordinate_file = 'str(wing.tag)' + '_airfoil_XSec_' + str( jj) + '.dat' airfoil.tag = 'AF_file' segment.append_airfoil(airfoil) wing.Segments.append(segment) # Wing dihedral proj_span_sum_alt = 0. span_sum_alt = 0. sweeps_sum = 0. for ii in range(start, segment_num): span_sum_alt += segment_spans[ii] proj_span_sum_alt += segment_spans[ii] * np.cos( segment_dihedral[ii] ) # Use projected span to find total wing dihedral. sweeps_sum += segment_spans[ii] * np.tan( segment_sweeps_quarter_chord[ii]) wing.dihedral = np.arccos(proj_span_sum_alt / span_sum_alt) wing.sweeps.quarter_chord = -np.arctan( sweeps_sum / span_sum_alt) # Minus sign makes it positive sweep. # Wing spans if wing.symmetric == True: wing.spans.projected = 2 * proj_span_sum else: wing.spans.projected = proj_span_sum # Areas wing.areas.reference = vsp.GetParmVal(wing_id, 'TotalArea', 'WingGeom') * units_factor**2 # Chords wing.chords.root = vsp.GetParmVal(wing_id, 'Tip_Chord', 'XSec_0') * units_factor wing.chords.tip = vsp.GetParmVal( wing_id, 'Tip_Chord', 'XSec_' + str(segment_num - 1)) * units_factor wing.chords.mean_geometric = wing.areas.reference / wing.spans.projected # Twists wing.twists.root = vsp.GetParmVal(wing_id, 'Twist', 'XSec_0') * Units.deg wing.twists.tip = vsp.GetParmVal( wing_id, 'Twist', 'XSec_' + str(segment_num - 1)) * Units.deg return wing
def write(vehicle, tag): # Reset OpenVSP to avoid including a previous vehicle try: vsp.ClearVSPModel() except NameError: print 'VSP import failed' return -1 area_tags = dict() # for wetted area assignment # ------------- # Wings # ------------- for wing in vehicle.wings: wing_x = wing.origin[0] wing_y = wing.origin[1] wing_z = wing.origin[2] if wing.symmetric == True: span = wing.spans.projected / 2. # span of one side else: span = wing.spans.projected root_chord = wing.chords.root tip_chord = wing.chords.tip sweep = wing.sweeps.quarter_chord / Units.deg sweep_loc = 0.25 root_twist = wing.twists.root / Units.deg tip_twist = wing.twists.tip / Units.deg root_tc = wing.thickness_to_chord tip_tc = wing.thickness_to_chord dihedral = wing.dihedral / Units.deg # Check to see if segments are defined. Get count if len(wing.Segments.keys()) > 0: n_segments = len(wing.Segments.keys()) else: n_segments = 0 # Create the wing wing_id = vsp.AddGeom("WING") vsp.SetGeomName(wing_id, wing.tag) area_tags[wing.tag] = ['wings', wing.tag] # Make names for each section and insert them into the wing if necessary x_secs = [] x_sec_curves = [] # n_segments + 2 will create an extra segment if the root segment is # included in the list of segments. This is not used and the tag is # removed when the segments are checked for this case. for i_segs in xrange(0, n_segments + 2): x_secs.append('XSec_' + str(i_segs)) x_sec_curves.append('XSecCurve_' + str(i_segs)) # Apply the basic characteristics of the wing to root and tip if wing.symmetric == False: vsp.SetParmVal(wing_id, 'Sym_Planar_Flag', 'Sym', 0) if wing.vertical == True: vsp.SetParmVal(wing_id, 'X_Rel_Rotation', 'XForm', 90) vsp.SetParmVal(wing_id, 'X_Rel_Location', 'XForm', wing_x) vsp.SetParmVal(wing_id, 'Y_Rel_Location', 'XForm', wing_y) vsp.SetParmVal(wing_id, 'Z_Rel_Location', 'XForm', wing_z) # This ensures that the other VSP parameters are driven properly vsp.SetDriverGroup(wing_id, 1, vsp.SPAN_WSECT_DRIVER, vsp.ROOTC_WSECT_DRIVER, vsp.TIPC_WSECT_DRIVER) # Root chord vsp.SetParmVal(wing_id, 'Root_Chord', x_secs[1], root_chord) # Sweep of the first section vsp.SetParmVal(wing_id, 'Sweep', x_secs[1], sweep) vsp.SetParmVal(wing_id, 'Sweep_Location', x_secs[1], sweep_loc) # Twists vsp.SetParmVal(wing_id, 'Twist', x_secs[0], tip_twist) # tip vsp.SetParmVal(wing_id, 'Twist', x_secs[0], root_twist) # root # Figure out if there is an airfoil provided # Airfoils should be in Lednicer format # i.e. : # #EXAMPLE AIRFOIL # 3. 3. # # 0.0 0.0 # 0.5 0.1 # 1.0 0.0 # # 0.0 0.0 # 0.5 -0.1 # 1.0 0.0 # Note this will fail silently if airfoil is not in correct format # check geometry output if n_segments == 0: if len(wing.Airfoil) != 0: xsecsurf = vsp.GetXSecSurf(wing_id, 0) vsp.ChangeXSecShape(xsecsurf, 0, vsp.XS_FILE_AIRFOIL) vsp.ChangeXSecShape(xsecsurf, 1, vsp.XS_FILE_AIRFOIL) xsec1 = vsp.GetXSec(xsecsurf, 0) xsec2 = vsp.GetXSec(xsecsurf, 1) vsp.ReadFileAirfoil(xsec1, wing.Airfoil['airfoil'].coordinate_file) vsp.ReadFileAirfoil(xsec2, wing.Airfoil['airfoil'].coordinate_file) vsp.Update() else: # The wing airfoil is still used for the root segment if the first added segment does not begin there # This could be combined with above, but is left here for clarity if (len(wing.Airfoil) != 0) and (wing.Segments[0].percent_span_location != 0.): xsecsurf = vsp.GetXSecSurf(wing_id, 0) vsp.ChangeXSecShape(xsecsurf, 0, vsp.XS_FILE_AIRFOIL) vsp.ChangeXSecShape(xsecsurf, 1, vsp.XS_FILE_AIRFOIL) xsec1 = vsp.GetXSec(xsecsurf, 0) xsec2 = vsp.GetXSec(xsecsurf, 1) vsp.ReadFileAirfoil(xsec1, wing.Airfoil['airfoil'].coordinate_file) vsp.ReadFileAirfoil(xsec2, wing.Airfoil['airfoil'].coordinate_file) vsp.Update() elif len(wing.Segments[0].Airfoil) != 0: xsecsurf = vsp.GetXSecSurf(wing_id, 0) vsp.ChangeXSecShape(xsecsurf, 0, vsp.XS_FILE_AIRFOIL) vsp.ChangeXSecShape(xsecsurf, 1, vsp.XS_FILE_AIRFOIL) xsec1 = vsp.GetXSec(xsecsurf, 0) xsec2 = vsp.GetXSec(xsecsurf, 1) vsp.ReadFileAirfoil( xsec1, wing.Segments[0].Airfoil['airfoil'].coordinate_file) vsp.ReadFileAirfoil( xsec2, wing.Segments[0].Airfoil['airfoil'].coordinate_file) vsp.Update() # Thickness to chords vsp.SetParmVal(wing_id, 'ThickChord', 'XSecCurve_0', root_tc) vsp.SetParmVal(wing_id, 'ThickChord', 'XSecCurve_1', tip_tc) # Dihedral vsp.SetParmVal(wing_id, 'Dihedral', x_secs[1], dihedral) # Span and tip of the section if n_segments > 1: local_span = span * wing.Segments[0].percent_span_location sec_tip_chord = root_chord * wing.Segments[0].root_chord_percent vsp.SetParmVal(wing_id, 'Span', x_secs[1], local_span) vsp.SetParmVal(wing_id, 'Tip_Chord', x_secs[1], sec_tip_chord) else: vsp.SetParmVal(wing_id, 'Span', x_secs[1], span) vsp.Update() if n_segments > 0: if wing.Segments[0].percent_span_location == 0.: x_secs[-1] = [] # remove extra section tag (for clarity) segment_0_is_root_flag = True adjust = 0 # used for indexing else: segment_0_is_root_flag = False adjust = 1 else: adjust = 1 # Loop for the number of segments left over for i_segs in xrange(1, n_segments + 1): # Unpack dihedral_i = wing.Segments[i_segs - 1].dihedral_outboard / Units.deg chord_i = root_chord * wing.Segments[i_segs - 1].root_chord_percent twist_i = wing.Segments[i_segs - 1].twist / Units.deg sweep_i = wing.Segments[i_segs - 1].sweeps.quarter_chord / Units.deg # Calculate the local span if i_segs == n_segments: span_i = span * ( 1 - wing.Segments[i_segs - 1].percent_span_location ) / np.cos(dihedral_i * Units.deg) else: span_i = span * ( wing.Segments[i_segs].percent_span_location - wing.Segments[i_segs - 1].percent_span_location) / np.cos( dihedral_i * Units.deg) # Insert the new wing section with specified airfoil if available if len(wing.Segments[i_segs - 1].Airfoil) != 0: vsp.InsertXSec(wing_id, i_segs - 1 + adjust, vsp.XS_FILE_AIRFOIL) xsecsurf = vsp.GetXSecSurf(wing_id, 0) xsec = vsp.GetXSec(xsecsurf, i_segs + adjust) vsp.ReadFileAirfoil( xsec, wing.Segments[i_segs - 1].Airfoil['airfoil'].coordinate_file) else: vsp.InsertXSec(wing_id, i_segs - 1 + adjust, vsp.XS_FOUR_SERIES) # Set the parms vsp.SetParmVal(wing_id, 'Span', x_secs[i_segs + adjust], span_i) vsp.SetParmVal(wing_id, 'Dihedral', x_secs[i_segs + adjust], dihedral_i) vsp.SetParmVal(wing_id, 'Sweep', x_secs[i_segs + adjust], sweep_i) vsp.SetParmVal(wing_id, 'Sweep_Location', x_secs[i_segs + adjust], sweep_loc) vsp.SetParmVal(wing_id, 'Root_Chord', x_secs[i_segs + adjust], chord_i) vsp.SetParmVal(wing_id, 'Twist', x_secs[i_segs + adjust], twist_i) vsp.SetParmVal(wing_id, 'ThickChord', x_sec_curves[i_segs + adjust], tip_tc) vsp.Update() vsp.SetParmVal(wing_id, 'Tip_Chord', x_secs[-1 - (1 - adjust)], tip_chord) vsp.SetParmVal(wing_id, 'CapUMaxOption', 'EndCap', 2.) vsp.SetParmVal(wing_id, 'CapUMaxStrength', 'EndCap', 1.) vsp.Update() # to fix problems with chords not matching up if wing.tag == 'main_wing': main_wing_id = wing_id ## Skeleton code for props and pylons can be found in previous commits (~Dec 2016) if desired ## This was a place to start and may not still be functional # ------------- # Engines # ------------- if vehicle.propulsors.has_key('turbofan'): print 'Warning: no meshing sources are currently implemented for the nacelle' # Unpack turbofan = vehicle.propulsors.turbofan n_engines = turbofan.number_of_engines length = turbofan.engine_length width = turbofan.nacelle_diameter origins = turbofan.origin bpr = turbofan.bypass_ratio for ii in xrange(0, int(n_engines)): origin = origins[ii] x = origin[0] y = origin[1] z = origin[2] nac_id = vsp.AddGeom("FUSELAGE") vsp.SetGeomName(nac_id, 'turbofan') # Length and overall diameter vsp.SetParmVal(nac_id, "Length", "Design", length) vsp.SetParmVal(nac_id, 'Abs_Or_Relitive_flag', 'XForm', vsp.ABS) vsp.SetParmVal(nac_id, 'OrderPolicy', 'Design', 1.) vsp.SetParmVal(nac_id, 'X_Location', 'XForm', x) vsp.SetParmVal(nac_id, 'Y_Location', 'XForm', y) vsp.SetParmVal(nac_id, 'Z_Location', 'XForm', z) vsp.SetParmVal(nac_id, 'Origin', 'XForm', 0.5) vsp.SetParmVal(nac_id, 'Z_Rotation', 'XForm', 180.) xsecsurf = vsp.GetXSecSurf(nac_id, 0) vsp.ChangeXSecShape(xsecsurf, 0, vsp.XS_ELLIPSE) vsp.Update() vsp.SetParmVal(nac_id, "Ellipse_Width", "XSecCurve_0", width - .2) vsp.SetParmVal(nac_id, "Ellipse_Width", "XSecCurve_1", width) vsp.SetParmVal(nac_id, "Ellipse_Width", "XSecCurve_2", width) vsp.SetParmVal(nac_id, "Ellipse_Width", "XSecCurve_3", width) vsp.SetParmVal(nac_id, "Ellipse_Height", "XSecCurve_0", width - .2) vsp.SetParmVal(nac_id, "Ellipse_Height", "XSecCurve_1", width) vsp.SetParmVal(nac_id, "Ellipse_Height", "XSecCurve_2", width) vsp.SetParmVal(nac_id, "Ellipse_Height", "XSecCurve_3", width) vsp.Update() # ------------- # Fuselage # ------------- if vehicle.fuselages.has_key('fuselage'): # Unpack fuselage = vehicle.fuselages.fuselage width = fuselage.width length = fuselage.lengths.total hmax = fuselage.heights.maximum height1 = fuselage.heights.at_quarter_length height2 = fuselage.heights.at_wing_root_quarter_chord height3 = fuselage.heights.at_three_quarters_length effdia = fuselage.effective_diameter n_fine = fuselage.fineness.nose t_fine = fuselage.fineness.tail w_ac = wing.aerodynamic_center w_origin = vehicle.wings.main_wing.origin w_c_4 = vehicle.wings.main_wing.chords.root / 4. # Figure out the location x location of each section, 3 sections, end of nose, wing origin, and start of tail x1 = n_fine * width / length x2 = (w_origin[0] + w_c_4) / length x3 = 1 - t_fine * width / length fuse_id = vsp.AddGeom("FUSELAGE") vsp.SetGeomName(fuse_id, fuselage.tag) area_tags[fuselage.tag] = ['fuselages', fuselage.tag] if fuselage.has_key('OpenVSP_values'): vals = fuselage.OpenVSP_values # Nose vsp.SetParmVal(fuse_id, "TopLAngle", "XSec_0", vals.nose.top.angle) vsp.SetParmVal(fuse_id, "TopLStrength", "XSec_0", vals.nose.top.strength) vsp.SetParmVal(fuse_id, "RightLAngle", "XSec_0", vals.nose.side.angle) vsp.SetParmVal(fuse_id, "RightLStrength", "XSec_0", vals.nose.side.strength) vsp.SetParmVal(fuse_id, "TBSym", "XSec_0", vals.nose.TB_Sym) vsp.SetParmVal(fuse_id, "ZLocPercent", "XSec_0", vals.nose.z_pos) # Tail vsp.SetParmVal(fuse_id, "TopLAngle", "XSec_4", vals.tail.top.angle) vsp.SetParmVal(fuse_id, "TopLStrength", "XSec_4", vals.tail.top.strength) # Below can be enabled if AllSym (below) is removed #vsp.SetParmVal(fuse_id,"RightLAngle","XSec_4",vals.tail.side.angle) #vsp.SetParmVal(fuse_id,"RightLStrength","XSec_4",vals.tail.side.strength) #vsp.SetParmVal(fuse_id,"TBSym","XSec_4",vals.tail.TB_Sym) #vsp.SetParmVal(fuse_id,"BottomLAngle","XSec_4",vals.tail.bottom.angle) #vsp.SetParmVal(fuse_id,"BottomLStrength","XSec_4",vals.tail.bottom.strength) if vals.tail.has_key('z_pos'): tail_z_pos = vals.tail.z_pos else: tail_z_pos = 0.02 vsp.SetParmVal(fuse_id, "AllSym", "XSec_4", 1) vsp.SetParmVal(fuse_id, "Length", "Design", length) vsp.SetParmVal(fuse_id, "Diameter", "Design", width) vsp.SetParmVal(fuse_id, "XLocPercent", "XSec_1", x1) vsp.SetParmVal(fuse_id, "XLocPercent", "XSec_2", x2) vsp.SetParmVal(fuse_id, "XLocPercent", "XSec_3", x3) vsp.SetParmVal(fuse_id, "ZLocPercent", "XSec_4", tail_z_pos) vsp.SetParmVal(fuse_id, "Ellipse_Width", "XSecCurve_1", width) vsp.SetParmVal(fuse_id, "Ellipse_Width", "XSecCurve_2", width) vsp.SetParmVal(fuse_id, "Ellipse_Width", "XSecCurve_3", width) vsp.SetParmVal(fuse_id, "Ellipse_Height", "XSecCurve_1", height1) vsp.SetParmVal(fuse_id, "Ellipse_Height", "XSecCurve_2", height2) vsp.SetParmVal(fuse_id, "Ellipse_Height", "XSecCurve_3", height3) # Write the vehicle to the file vsp.WriteVSPFile(tag + ".vsp3") return area_tags