def _load_from_file(self, filename): vsp.ClearVSPModel() vsp.ReadVSPFile(filename) for geom_id in vsp.FindGeoms(): geom_name_raw = vsp.GetGeomName(geom_id) geom_name, geom_idx = regex_listname.findall(geom_name_raw)[0] if geom_name not in self: if geom_idx: self[geom_name] = [] else: self[geom_name] = VspElement() if geom_idx != '': geom = self._update_list(self[geom_name], geom_idx) else: geom = self[geom_name] geom._id = geom_id for param_id in vsp.GetGeomParmIDs(geom_id): group_name_raw = vsp.GetParmDisplayGroupName(param_id) group_name, group_idx = regex_listname.findall( group_name_raw)[0] if group_name not in EXCLUDE_GROUPS: if group_name not in geom: if group_idx: geom[group_name] = [] else: geom[group_name] = VspElement() if group_idx != '': geom[group_name], group = self._update_list( geom[group_name], group_idx) else: group = geom[group_name] param = self._make_parameter(param_id) if param['name'] in group: raise ValueError("{} already in <{}:{}>".format( param.name, geom_name, group_name)) group[param['name']] = param
def __init__(self, vspFile, comm=MPI.COMM_WORLD, scale=1.0, comps=[], intersectedComps=None, debug=False): self.points = OrderedDict() self.pointSets = OrderedDict() self.updated = {} self.vspScale = scale self.comm = comm self.vspFile = vspFile self.debug = debug self.jac = None # Load in the VSP model vsp.ClearVSPModel() vsp.ReadVSPFile(vspFile) # Setup the export group set (0) with just the sets we want. self.exportSet = 9 # List of all componets returned from VSP. Note that this # order is important...it is the order the comps will be # written out in plot3d format. allComps = vsp.FindGeoms() # If we were not given comps, use all of them if comps == []: for c in allComps: comps.append(vsp.GetContainerName(c)) # First set the export flag for exportSet to False for everyone for comp in allComps: vsp.SetSetFlag(comp, self.exportSet, False) self.exportComps = [] for comp in allComps: # Check if this one is in our list: compName = vsp.GetContainerName(comp) if compName in comps: vsp.SetSetFlag(comp, self.exportSet, True) self.exportComps.append(compName) # Create a directory in which we will put the temporary files # we need. We *should* use something like tmepfile.mkdtemp() # but that behaves badly on pleiades. tmpDir = None if self.comm.rank == 0: tmpDir = './tmpDir_%d_%s' % (MPI.COMM_WORLD.rank, time.time()) print('Temp dir is: %s' % tmpDir) if not os.path.exists(tmpDir): os.makedirs(tmpDir) self.tmpDir = self.comm.bcast(tmpDir) # Initial list of DVs self.DVs = OrderedDict() # Run the update. This will also set the conn on the first pass self.conn = None self.pts0 = None self.cumSizes = None self.sizes = None if self.comm.rank == 0: self.pts0, self.conn, self.cumSizes, self.sizes = self._getUpdatedSurface( ) self.pts0 = self.comm.bcast(self.pts0) self.conn = self.comm.bcast(self.conn) self.cumSizes = self.comm.bcast(self.cumSizes) self.sizes = self.comm.bcast(self.sizes) self.pts = self.pts0.copy() # Finally process theintersection information. We had to wait # until all processors have the surface information. self.intersectComps = [] if intersectedComps is None: intersectedComps = [] for i in range(len(intersectedComps)): c = intersectedComps[i] # Get the index of each of the two comps: compIndexA = self.exportComps.index(c[0]) compIndexB = self.exportComps.index(c[1]) direction = c[2] dStar = c[3] extraComps = [] if len(c) == 5: for j in range(len(c[4])): extraComps.append(self.exportComps.index(c[4][j])) self.intersectComps.append( CompIntersection(compIndexA, compIndexB, extraComps, direction, dStar, self.pts, self.cumSizes, self.sizes, self.tmpDir))
def get_fuel_tank_properties(vehicle, tag, fuel_tank_set_index=3, slices_for_calculation=100): """This function computes the center of gravity, total possible fuel mass, the available volume of each fuel tank in the vehicle through a mass properties computation in OpenVSP. Assumptions: Fuel tanks exists in the fuselage and wings only All fuel tanks have unique names Source: N/A Inputs: vehicle.fuselages.*.Fuel_Tanks.*.tag [-] vehicle.wings.*.Fuel_Tanks.*.tag [-] Outputs: vehicle.fuselages.*.Fuel_Tanks.*.mass_properties. center_of_gravity [m] fuel_mass_when_full [kg] fuel_volume_when_full [m^3] vehicle.wings.*.Fuel_Tanks.*.mass_properties. center_of_gravity [m] fuel_mass_when_full [kg] fuel_volume_when_full [m^3] Properties Used: N/A """ # Reset OpenVSP to avoid including a previous vehicle vsp.ClearVSPModel() vsp.ReadVSPFile(tag + '.vsp3') # Extract fuel tanks from vehicle fuel_tanks = get_fuel_tanks(vehicle) num_slices = slices_for_calculation # Slices used to estimate mass distribution from areas in OpenVSP mass_props_output_file = tag + '_mass_props.txt' vsp.SetComputationFileName(vsp.MASS_PROP_TXT_TYPE, mass_props_output_file) print('Computing Fuel Tank Mass Properties... ') vsp.ComputeMassProps(fuel_tank_set_index, num_slices) print('Done') # Extract full tank mass properties from OpenVSP output file fo = open(mass_props_output_file) for line in fo: prop_list = line.split() try: if prop_list[0] in fuel_tanks: # Indices based on position in OpenVSP output (may change in the future) cg_x = float(prop_list[2]) cg_y = float(prop_list[3]) cg_z = float(prop_list[4]) mass = float(prop_list[1]) vol = float(prop_list[-1]) if 'center_of_gravity' not in fuel_tanks[prop_list[ 0]]: # assumes at most two identical tank names fuel_tanks[prop_list[0]].center_of_gravity = np.array( [cg_x, cg_y, cg_z]) fuel_tanks[prop_list[0]].fuel_mass_when_full = mass fuel_tanks[prop_list[0]].volume = vol else: fuel_tanks[prop_list[0]].center_of_gravity = \ (fuel_tanks[prop_list[0]].center_of_gravity+np.array([cg_x,cg_y,cg_z]))/2. fuel_tanks[prop_list[0]].fuel_mass_when_full += mass fuel_tanks[prop_list[0]].volume += vol except IndexError: # in case line is empty pass # Apply fuel tank properties to the vehicle vehicle = apply_properties(vehicle, fuel_tanks) return vehicle
def vsp_read(tag, units_type='SI',specified_network=None): """This reads an OpenVSP vehicle geometry and writes it into a SUAVE vehicle format. Includes wings, fuselages, and propellers. Assumptions: 1. OpenVSP vehicle is composed of conventionally shaped fuselages, wings, and propellers. 1a. OpenVSP fuselage: generally narrow at nose and tail, wider in center). 1b. 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. 1c. 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. 2. 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). 3. Written for OpenVSP 3.21.1 Source: N/A Inputs: 1. A tag for an XML file in format .vsp3. 2. Units_type set to 'SI' (default) or 'Imperial' 3. User-specified network Outputs: Writes SUAVE vehicle with these geometries from VSP: (All values default to SI. Any other 2nd argument outputs Imperial.) 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.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> 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> Propellers.Propeller. location[X,Y,Z] [radians] rotation[X,Y,Z] [radians] tip_radius [m] hub_radius [m] thrust_angle [radians] Properties Used: N/A """ vsp.ClearVSPModel() vsp.ReadVSPFile(tag) vsp_fuselages = [] vsp_wings = [] vsp_props = [] vsp_nacelles = [] vsp_nacelle_type = [] vsp_geoms = vsp.FindGeoms() geom_names = [] vehicle = SUAVE.Vehicle() vehicle.tag = tag if units_type == 'SI': units_type = 'SI' elif units_type == 'inches': units_type = 'inches' else: units_type = 'imperial' # The two for-loops below are in anticipation of an OpenVSP API update with a call for GETGEOMTYPE. # This print function allows user to enter VSP GeomID manually as first argument in vsp_read functions. print("VSP geometry IDs: ") # Label each geom type by storing its VSP geom ID. for geom in vsp_geoms: geom_name = vsp.GetGeomName(geom) geom_names.append(geom_name) print(str(geom_name) + ': ' + geom) # -------------------------------- # AUTOMATIC VSP ENTRY & PROCESSING # -------------------------------- for geom in vsp_geoms: geom_name = vsp.GetGeomName(geom) geom_type = vsp.GetGeomTypeName(str(geom)) if geom_type == 'Fuselage': vsp_fuselages.append(geom) if geom_type == 'Wing': vsp_wings.append(geom) if geom_type == 'Propeller': vsp_props.append(geom) if (geom_type == 'Stack') or (geom_type == 'BodyOfRevolution'): vsp_nacelle_type.append(geom_type) vsp_nacelles.append(geom) # -------------------------------------------------- # Read Fuselages # -------------------------------------------------- for fuselage_id in vsp_fuselages: sym_planar = vsp.GetParmVal(fuselage_id, 'Sym_Planar_Flag', 'Sym') # Check for symmetry sym_origin = vsp.GetParmVal(fuselage_id, 'Sym_Ancestor_Origin_Flag', 'Sym') if sym_planar == 2. and sym_origin == 1.: num_fus = 2 sym_flag = [1,-1] else: num_fus = 1 sym_flag = [1] for fux_idx in range(num_fus): # loop through fuselages on aircraft fuselage = read_vsp_fuselage(fuselage_id,fux_idx,sym_flag[fux_idx],units_type) vehicle.append_component(fuselage) # -------------------------------------------------- # Read Wings # -------------------------------------------------- for wing_id in vsp_wings: wing = read_vsp_wing(wing_id, units_type) vehicle.append_component(wing) # -------------------------------------------------- # Read Nacelles # -------------------------------------------------- for nac_id, nacelle_id in enumerate(vsp_nacelles): nacelle = read_vsp_nacelle(nacelle_id,vsp_nacelle_type[nac_id], units_type) vehicle.append_component(nacelle) # -------------------------------------------------- # Read Propellers/Rotors and assign to a network # -------------------------------------------------- # Initialize rotor network elements number_of_lift_rotor_engines = 0 number_of_propeller_engines = 0 lift_rotors = Data() propellers = Data() for prop_id in vsp_props: prop = read_vsp_propeller(prop_id,units_type) prop.tag = vsp.GetGeomName(prop_id) if prop.orientation_euler_angles[1] >= 70 * Units.degrees: lift_rotors.append(prop) number_of_lift_rotor_engines += 1 else: propellers.append(prop) number_of_propeller_engines += 1 if specified_network == None: # If no network specified, assign a network if number_of_lift_rotor_engines>0 and number_of_propeller_engines>0: net = Lift_Cruise() else: net = Battery_Propeller() else: net = specified_network # Create the rotor network if net.tag == "Lift_Cruise": # Lift + Cruise network for i in range(number_of_lift_rotor_engines): net.lift_rotors.append(lift_rotors[list(lift_rotors.keys())[i]]) net.number_of_lift_rotor_engines = number_of_lift_rotor_engines for i in range(number_of_propeller_engines): net.propellers.append(propellers[list(propellers.keys())[i]]) net.number_of_propeller_engines = number_of_propeller_engines elif net.tag == "Battery_Propeller": # Append all rotors as propellers for the battery propeller network for i in range(number_of_lift_rotor_engines): # Accounts for multicopter configurations net.propellers.append(lift_rotors[list(lift_rotors.keys())[i]]) for i in range(number_of_propeller_engines): net.propellers.append(propellers[list(propellers.keys())[i]]) net.number_of_propeller_engines = number_of_lift_rotor_engines + number_of_propeller_engines vehicle.networks.append(net) return vehicle
def write(vehicle, tag, fuel_tank_set_ind=3, verbose=True, write_file=True, OML_set_ind = 4, write_igs = False): """This writes a SUAVE vehicle to OpenVSP format. It will take wing segments into account if they are specified in the vehicle setup file. Assumptions: Vehicle is composed of conventional shape fuselages, wings, and propulsors. Any propulsor that should be created is tagged as 'turbofan'. Source: N/A Inputs: vehicle. tag [-] wings.*. (* is all keys) origin [m] in all three dimensions spans.projected [m] chords.root [m] chords.tip [m] sweeps.quarter_chord [radians] twists.root [radians] twists.tip [radians] thickness_to_chord [-] dihedral [radians] tag <string> Segments.*. (optional) twist [radians] percent_span_location [-] .1 is 10% root_chord_percent [-] .1 is 10% dihedral_outboard [radians] sweeps.quarter_chord [radians] thickness_to_chord [-] propulsors.turbofan. (optional) number_of_engines [-] engine_length [m] nacelle_diameter [m] origin [m] in all three dimension, should have as many origins as engines OpenVSP_simple (optional) <boolean> if False (default) create a flow through nacelle, if True creates a roughly biparabolic shape fuselages.fuselage (optional) width [m] lengths.total [m] heights. maximum [m] at_quarter_length [m] at_wing_root_quarter_chord [m] at_three_quarters_length [m] effective_diameter [m] fineness.nose [-] ratio of nose section length to fuselage width fineness.tail [-] ratio of tail section length to fuselage width tag <string> OpenVSP_values. (optional) nose.top.angle [degrees] nose.top.strength [-] this determines how much the specified angle influences that shape nose.side.angle [degrees] nose.side.strength [-] nose.TB_Sym <boolean> determines if top angle is mirrored on bottom nose.z_pos [-] z position of the nose as a percentage of fuselage length (.1 is 10%) tail.top.angle [degrees] tail.top.strength [-] tail.z_pos (optional, 0.02 default) [-] z position of the tail as a percentage of fuselage length (.1 is 10%) fuel_tank_set_index <int> OpenVSP object set containing the fuel tanks Outputs: <tag>.vsp3 This is the OpenVSP representation of the aircraft Properties Used: N/A """ # Reset OpenVSP to avoid including a previous vehicle if verbose: print('Reseting OpenVSP Model in Memory') try: vsp.ClearVSPModel() except NameError: print('VSP import failed') return -1 area_tags = dict() # for wetted area assignment # ------------- # Wings # ------------- # Default Set_0 in OpenVSP is index 3 vsp.SetSetName(fuel_tank_set_ind, 'fuel_tanks') vsp.SetSetName(OML_set_ind, 'OML') for wing in vehicle.wings: if verbose: print('Writing '+wing.tag+' to OpenVSP Model') area_tags, wing_id = write_vsp_wing(wing,area_tags, fuel_tank_set_ind, OML_set_ind) if wing.tag == 'main_wing': main_wing_id = wing_id # ------------- # Engines # ------------- ## 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 if 'turbofan' in vehicle.propulsors: if verbose: print('Writing '+vehicle.propulsors.turbofan.tag+' to OpenVSP Model') turbofan = vehicle.propulsors.turbofan write_vsp_turbofan(turbofan, OML_set_ind) if 'turbojet' in vehicle.propulsors: turbofan = vehicle.propulsors.turbojet write_vsp_turbofan(turbofan, OML_set_ind) # ------------- # Fuselage # ------------- for key, fuselage in vehicle.fuselages.items(): if verbose: print('Writing '+fuselage.tag+' to OpenVSP Model') try: area_tags = write_vsp_fuselage(fuselage, area_tags, vehicle.wings.main_wing, fuel_tank_set_ind, OML_set_ind) except AttributeError: area_tags = write_vsp_fuselage(fuselage, area_tags, None, fuel_tank_set_ind, OML_set_ind) vsp.Update() # Write the vehicle to the file if write_file ==True: cwd = os.getcwd() filename = tag + ".vsp3" if verbose: print('Saving OpenVSP File at '+ cwd + '/' + filename) vsp.WriteVSPFile(filename) elif verbose: print('Not Saving OpenVSP File') if write_igs: if verbose: print('Exporting IGS File') vehicle_id = vsp.FindContainersWithName('Vehicle')[0] parm_id = vsp.FindParm(vehicle_id,'LabelID','IGESSettings') vsp.SetParmVal(parm_id, 0.) vsp.ExportFile(tag + ".igs", OML_set_ind, vsp.EXPORT_IGES) return area_tags
def write_vsp_mesh(geometry, tag, half_mesh_flag, growth_ratio, growth_limiting_flag): """This create an .stl surface mesh based on a vehicle stored in a .vsp3 file. Assumptions: None Source: N/A Inputs: geometry. - Also passed to set_sources wings.main_wing.chords.mean_aerodynamic [m] half_mesh_flag <boolean> determines if a symmetry plane is created growth_ratio [-] growth ratio for the mesh growth_limiting_flag <boolean> determines if 3D growth limiting is used Outputs: <tag>.stl Properties Used: N/A """ # Reset OpenVSP to avoid including a previous vehicle vsp.ClearVSPModel() if 'turbofan' in geometry.networks: print( 'Warning: no meshing sources are currently implemented for the nacelle' ) # Turn on symmetry plane splitting to improve robustness of meshing process if half_mesh_flag == True: f = fileinput.input(tag + '.vsp3', inplace=1) for line in f: if 'SymmetrySplitting' in line: print(line[0:34] + '1' + line[35:-1]) else: print(line) vsp.ReadVSPFile(tag + '.vsp3') # Set output file types and what will be meshed file_type = vsp.CFD_STL_TYPE + vsp.CFD_KEY_TYPE set_int = vsp.SET_ALL vsp.SetComputationFileName(vsp.CFD_STL_TYPE, tag + '.stl') vsp.SetComputationFileName(vsp.CFD_KEY_TYPE, tag + '.key') # Set to create a tagged STL mesh file vehicle_cont = vsp.FindContainer('Vehicle', 0) STL_multi = vsp.FindParm(vehicle_cont, 'MultiSolid', 'STLSettings') vsp.SetParmVal(STL_multi, 1.0) vsp.SetCFDMeshVal(vsp.CFD_FAR_FIELD_FLAG, 1) if half_mesh_flag == True: vsp.SetCFDMeshVal(vsp.CFD_HALF_MESH_FLAG, 1) # Figure out the size of the bounding box vehicle_id = vsp.FindContainersWithName('Vehicle')[0] xlen = vsp.GetParmVal(vsp.FindParm(vehicle_id, "X_Len", "BBox")) ylen = vsp.GetParmVal(vsp.FindParm(vehicle_id, "Y_Len", "BBox")) zlen = vsp.GetParmVal(vsp.FindParm(vehicle_id, "Z_Len", "BBox")) # Max length max_len = np.max([xlen, ylen, zlen]) far_length = 10. * max_len vsp.SetCFDMeshVal(vsp.CFD_FAR_SIZE_ABS_FLAG, 1) vsp.SetCFDMeshVal(vsp.CFD_FAR_LENGTH, far_length) vsp.SetCFDMeshVal(vsp.CFD_FAR_WIDTH, far_length) vsp.SetCFDMeshVal(vsp.CFD_FAR_HEIGHT, far_length) vsp.SetCFDMeshVal(vsp.CFD_FAR_MAX_EDGE_LEN, max_len) vsp.SetCFDMeshVal(vsp.CFD_GROWTH_RATIO, growth_ratio) if growth_limiting_flag == True: vsp.SetCFDMeshVal(vsp.CFD_LIMIT_GROWTH_FLAG, 1.0) # Set the max edge length so we have on average 50 elements per chord length MAC = geometry.wings.main_wing.chords.mean_aerodynamic min_len = MAC / 50. vsp.SetCFDMeshVal(vsp.CFD_MAX_EDGE_LEN, min_len) # vsp.AddDefaultSources() set_sources(geometry) vsp.Update() vsp.WriteVSPFile(tag + '_premesh.vsp3') print('Starting mesh for ' + tag + ' (This may take several minutes)') ti = time.time() vsp.ComputeCFDMesh(set_int, file_type) tf = time.time() dt = tf - ti print('VSP meshing for ' + tag + ' completed in ' + str(dt) + ' s')
def vsp_read(tag, units_type='SI'): """This reads an OpenVSP vehicle geometry and writes it into a SUAVE vehicle format. Includes wings, fuselages, and propellers. Assumptions: 1. OpenVSP vehicle is composed of conventionally shaped fuselages, wings, and propellers. 1a. OpenVSP fuselage: generally narrow at nose and tail, wider in center). 1b. 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. 1c. 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. 2. 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). 3. Written for OpenVSP 3.16.1 Source: N/A Inputs: 1. A tag for an XML file in format .vsp3. 2. Units_type set to 'SI' (default) or 'Imperial' Outputs: Writes SUAVE vehicle with these geometries from VSP: (All values default to SI. Any other 2nd argument outputs Imperial.) 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> 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> Propellers.Propeller. location[X,Y,Z] [radians] rotation[X,Y,Z] [radians] tip_radius [m] hub_radius [m] thrust_angle [radians] Properties Used: N/A """ vsp.ClearVSPModel() vsp.ReadVSPFile(tag) vsp_fuselages = [] vsp_wings = [] vsp_props = [] vsp_geoms = vsp.FindGeoms() geom_names = [] vehicle = SUAVE.Vehicle() vehicle.tag = tag if units_type == 'SI': units_type = 'SI' else: units_type = 'Imperial' # The two for-loops below are in anticipation of an OpenVSP API update with a call for GETGEOMTYPE. # This print function allows user to enter VSP GeomID manually as first argument in vsp_read functions. print("VSP geometry IDs: ") # Label each geom type by storing its VSP geom ID. (The API call for GETGEOMTYPE was not released as of 8/9/18, v 3.16.1) for geom in vsp_geoms: geom_name = vsp.GetGeomName(geom) geom_names.append(geom_name) print(str(geom_name) + ': ' + geom) # ----------------------------- # MANUAL VSP ENTRY & PROCESSING # ----------------------------- #fuselage = read_vsp_fuselage(fuselage_id, units_type=units_type) # Replace fuselage_id manually. #vehicle.append_component(fuselage) #wing = read_vsp_wing(wing_id, units_type=units_type) # Replace wing_id manually. #vehicle.append_component(wing) #prop = read_vsp_prop(prop_id, units_type=units_type) # Replace prop_id manually. #vehicle.append_component(prop) # -------------------------------- # AUTOMATIC VSP ENTRY & PROCESSING # -------------------------------- #for geom in vsp_geoms: #if vsp.GETGEOMTYPE(str(geom)) == 'FUSELAGE': #vsp_fuselages.append(geom) #if vsp.GETGEOMTYPE(str(geom)) == 'WING': #vsp_wings.append(geom) #if vsp.GETGEOMTYPE(str(geom)) == 'PROP': #vsp_props.append(geom) # Read VSP geoms and store in SUAVE components. #for vsp_fuselage in vsp_fuselages: #fuselage_id = vsp_fuselages[vsp_fuselage] #fuselage = read_vsp_fuselage(fuselage_id, units_type) #vehicle.append_component(fuselage) #for vsp_wing in vsp_wings: #wing_id = vsp_wings[vsp_wing] #wing = read_vsp_wing(wing_id, units_type) #vehicle.append_component(wing) #for vsp_prop in vsp_props: #prop_id = vsp_props[vsp_prop] #prop = read_vsp_prop(prop_id, units_type) #vehicle.append_component(prop) return vehicle