Example #1
0
def find_fuse_u_coordinate(x_target, fuse_id, fuel_tank_tag):
    """Determines the u coordinate of an OpenVSP fuselage that matches an x coordinate
    
    Assumptions:
    Fuselage is aligned with the x axis

    Source:
    N/A

    Inputs:
    x_target      [m]
    fuse_id       <str>
    fuel_tank_tag <str>

    Outputs:
    u_current     [-] u coordinate for the requests x position

    Properties Used:
    N/A
    """
    tol = 1e-3
    diff = 1000
    u_min = 0
    u_max = 1
    while np.abs(diff) > tol:
        u_current = (u_max + u_min) / 2
        probe_id = vsp.AddProbe(fuse_id, 0, u_current, 0,
                                fuel_tank_tag + '_probe')
        vsp.Update()
        x_id = vsp.FindParm(probe_id, 'X', 'Measure')
        x_pos = vsp.GetParmVal(x_id)
        diff = x_target - x_pos
        if diff > 0:
            u_min = u_current
        else:
            u_max = u_current
        vsp.DelProbe(probe_id)
    return u_current
Example #2
0
    def addVariable(self,
                    component,
                    group,
                    parm,
                    value=None,
                    lower=None,
                    upper=None,
                    scale=1.0,
                    scaledStep=True,
                    dh=1e-6):
        """
        Add a design variable definition.

        Parameters
        ----------
        component : str
            Name of the VSP component
        group : str
            Name of the VSP group
        parm : str
            Name of the VSP parameter
        value : float or None
            The design variable. If this value is not supplied (None), then
            the current value in the VSP model will be queried and used
        lower : float or None
            Lower bound for the design variable. Use None for no lower bound
        upper : float or None
            Upper bound for the design variable. Use None for no upper bound
        scale : float
            Scale factor
        scaledStep : bool
            Flag to use a scaled step sized based on the initial value of the
            variable. It will remain constant thereafter.
        dh : float
            Step size. When scaledStep is True, the actual step is dh*value. Otherwise
            this actual step is used.
        """

        container_id = vsp.FindContainer(component, 0)
        if container_id == "":
            raise Error('Bad component for DV: %s' % component)

        parm_id = vsp.FindParm(container_id, parm, group)
        if parm_id == "":
            raise Error('Bad group or parm: %s %s' % (group, parm))

        # Now we know the parmID is ok. So we just get the value
        val = vsp.GetParmVal(parm_id)

        dvName = '%s:%s:%s' % (component, group, parm)

        if value is None:
            value = val

        if scaledStep:
            dh = dh * value

            if value == 0:
                raise Error(
                    'Initial value is exactly 0. scaledStep option cannot be used'
                    'Specify an explicit dh with scaledStep=False')

        self.DVs[dvName] = vspDV(parm_id, component, group, parm, value, lower,
                                 upper, scale, dh)
Example #3
0
def write_fuselage_conformal_fuel_tank(fuse_id,fuel_tank,fuel_tank_set_ind):
    """This writes a conformal fuel tank in a fuselage.
    
    Assumptions:
    Fuselage is aligned with the x axis

    Source:
    N/A

    Inputs:
    fuse_id                                     <str>
    fuel_tank.
      inward_offset                             [m]
      start_length_percent                      [-] .1 is 10%
      end_length_percent                        [-]
      fuel_type.density                         [kg/m^3]
    fuel_tank_set_ind                           <int>

    Outputs:
    Operates on the active OpenVSP model, no direct output

    Properties Used:
    N/A
    """        
    
    
    #stdout = vsp.cvar.cstdout
    #errorMgr = vsp.ErrorMgrSingleton_getInstance()
    #errorMgr.PopErrorAndPrint(stdout)
    
    # Unpack
    try:
        offset         = fuel_tank.inward_offset
        len_trim_max   = fuel_tank.end_length_percent
        len_trim_min   = fuel_tank.start_length_percent  
        density        = fuel_tank.fuel_type.density
    except:
        print('Fuel tank does not contain parameters needed for OpenVSP geometry. Tag: '+fuel_tank.tag)
        return        
    
    tank_id = vsp.AddGeom('CONFORMAL',fuse_id)
    vsp.SetGeomName(tank_id, fuel_tank.tag)    
    
    # Search for proper x position
    # Get min x
    probe_id = vsp.AddProbe(fuse_id,0,0,0,fuel_tank.tag+'_probe')
    vsp.Update()
    x_id  = vsp.FindParm(probe_id,'X','Measure')
    x_pos = vsp.GetParmVal(x_id)    
    fuse_x_min = x_pos
    vsp.DelProbe(probe_id)
    # Get min x
    probe_id = vsp.AddProbe(fuse_id,0,1,0,fuel_tank.tag+'_probe')
    vsp.Update()
    x_id  = vsp.FindParm(probe_id,'X','Measure')
    x_pos = vsp.GetParmVal(x_id)    
    fuse_x_max = x_pos 
    vsp.DelProbe(probe_id)
    # Search for u values
    x_target_start  = (fuse_x_max-fuse_x_min)*fuel_tank.start_length_percent
    x_target_end    = (fuse_x_max-fuse_x_min)*fuel_tank.end_length_percent
    u_start = find_fuse_u_coordinate(x_target_start, fuse_id, fuel_tank.tag)
    u_end   = find_fuse_u_coordinate(x_target_end, fuse_id, fuel_tank.tag)
    # Offset
    vsp.SetParmVal(tank_id,'Offset','Design',offset)      
    
    # Fuel tank length bounds
    vsp.SetParmVal(tank_id,'UTrimFlag','Design',1.)
    vsp.SetParmVal(tank_id,'UTrimMax','Design',u_end)
    vsp.SetParmVal(tank_id,'UTrimMin','Design',u_start)  
    
    # Set density
    vsp.SetParmVal(tank_id,'Density','Mass_Props',density)  
    
    # Add to the full fuel tank set
    vsp.SetSetFlag(tank_id, fuel_tank_set_ind, True)
    
    return
Example #4
0
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
Example #5
0
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')