Source code for RCAIDE.Framework.External_Interfaces.OpenVSP.export_vsp_vehicle

# RCAIDE/Framework/External_Interfaces/OpenVSP/export_vsp_vehicle.py
# 
# Created:  Jul 2025, M. Clarke 

# ----------------------------------------------------------------------------------------------------------------------
#  IMPORT
# ----------------------------------------------------------------------------------------------------------------------  
# RCAIDE imports 
import RCAIDE 
from RCAIDE.Library.Methods.Geometry.Planform                   import  fuselage_planform, wing_planform 
from RCAIDE.Framework.External_Interfaces.OpenVSP.vsp_rotor     import write_vsp_rotor_bem
from RCAIDE.Framework.External_Interfaces.OpenVSP.vsp_fuselage  import write_vsp_fuselage
from RCAIDE.Framework.External_Interfaces.OpenVSP.vsp_wing      import write_vsp_wing
from RCAIDE.Framework.External_Interfaces.OpenVSP.vsp_nacelle   import write_vsp_nacelle

try:
    import vsp as vsp
except ImportError:
    try:
        import openvsp as vsp
    except ImportError:
        # This allows RCAIDE to build without OpenVSP
        pass
import numpy as np
import os
from copy import deepcopy

# ---------------------------------------------------------------------------------------------------------------------- 
# export_vsp_vehicle
# ---------------------------------------------------------------------------------------------------------------------- 
[docs] def export_vsp_vehicle(vehicle, vehicle_tag, fuel_tank_set_ind=3, verbose=True, write_file=True, OML_set_ind = 4, write_igs = False): """This writes a RCAIDE 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 networks. Any network 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 [-] networks.turbofan. (optional) number_of_engines [-] 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 """ geometry = deepcopy(vehicle) # ------------------------------------------------------------------------- # Preprocess geometry # ------------------------------------------------------------------------- # update fuselage properties for fuselage in geometry.fuselages: fuselage_planform(fuselage) # update wing properties for wing in geometry.wings: wing_planform(wing) geometry.reference_area = wing.areas.reference if isinstance(wing, RCAIDE.Library.Components.Wings.Main_Wing): geometry.reference_area = wing.areas.reference # ------------------------------------------------------------------------- # Reset OpenVSP to avoid including a previous geometry # ------------------------------------------------------------------------- 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 geometry.wings: if verbose: print('Writing '+wing.tag+' to OpenVSP Model') area_tags, wing_id = write_vsp_wing(geometry,wing,area_tags, fuel_tank_set_ind, OML_set_ind) # ------------------------------------------------------------------------- # Engines # ------------------------------------------------------------------------- for network in geometry.networks: for propulsor in network.propulsors: for tag , item in propulsor.items(): if isinstance(item, RCAIDE.Library.Components.Powertrain.Converters.Rotor): if item.radius_distribution is not None and len(item.airfoil_polar_stations) != 0: vsp_bem_filename = item.tag + '.bem' write_vsp_rotor_bem(vsp_bem_filename,item) if propulsor.nacelle != None: nacelle = propulsor.nacelle if verbose: print('Writing '+ nacelle.tag +' to OpenVSP Model') write_vsp_nacelle(nacelle, OML_set_ind) # ------------------------------------------------------------------------- # Fuselage # ------------------------------------------------------------------------- for fuselage in geometry.fuselages: if verbose: print('Writing '+fuselage.tag+' to OpenVSP Model') try: area_tags = write_vsp_fuselage(fuselage, area_tags, geometry.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) # ------------------------------------------------------------------------- # Boom # ------------------------------------------------------------------------- for boom in geometry.booms: if verbose: print('Writing '+boom.tag+' to OpenVSP Model') try: area_tags = write_vsp_fuselage(boom, area_tags, geometry.wings.main_wing, fuel_tank_set_ind, OML_set_ind) except AttributeError: area_tags = write_vsp_fuselage(boom, area_tags, None, fuel_tank_set_ind, OML_set_ind) # ------------------------------------------------------------------------- # Write the geometry to the file # ------------------------------------------------------------------------- if write_file ==True: cwd = os.getcwd() filename = vehicle_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') geometry_id = vsp.FindContainersWithName('Vehicle')[0] parm_id = vsp.FindParm(geometry_id,'LabelID','IGESSettings') vsp.SetParmVal(parm_id, 0.) vsp.ExportFile(vehicle_tag + ".igs", OML_set_ind, vsp.EXPORT_IGES) return area_tags