def run_degen_geom(set_index=None, set_name=None): """ Runs degen geom on input set :param set_index: set index, will take precendence if both set index and set name are specified :param set_name: name of set, will be used if set index is not specified :return: degen geom manager object """ import degen_geom as dg if set_index is None and set_name is None: raise ValueError("set_index and set_name cannot both be None") # Get set index from name, if set index was not specified if set_index is None: set_index = vsp.GetSetIndex(set_name) # Run degen geom on the input set vsp.SetAnalysisInputDefaults("DegenGeom") vsp.SetIntAnalysisInput("DegenGeom", "Set", [set_index], 0) vsp.SetIntAnalysisInput("DegenGeom", "WriteCSVFlag", [0], 0) vsp.SetIntAnalysisInput("DegenGeom", "WriteMFileFlag", [0], 0) degen_res_id = vsp.ExecAnalysis("DegenGeom") degen_objs = vsp.parse_degen_geom(degen_res_id) degen_mgr = dg.DegenGeomMgr(degen_objs) return degen_mgr
def test_parse_degen_geom(self): vsp.VSPRenew() vsp.ClearVSPModel() wing_id = vsp.AddGeom("WING") vsp.Update() vsp.SetIntAnalysisInput("DegenGeom", "WriteCSVFlag", [0], 0) vsp.SetIntAnalysisInput("DegenGeom", "WriteMFileFlag", [0], 0) degen_results_id = vsp.ExecAnalysis("DegenGeom") for degen_obj in vsp.parse_degen_geom(degen_results_id): print(degen_obj)
def test_degen_transform_mat(self): import degen_geom as dg vsp.VSPRenew() vsp.ClearVSPModel() prop_id = vsp.AddGeom("PROP") vsp.SetParmVal(prop_id, "Y_Rel_Location", "XForm", 60.0) vsp.SetParmVal(prop_id, "Y_Rel_Rotation", "XForm", 90.0) vsp.SetParmVal(prop_id, "X_Rel_Rotation", "XForm", 10.0) vsp.SetParmVal(prop_id, "Sym_Planar_Flag", "Sym", vsp.SYM_XZ) vsp.Update() vsp.SetIntAnalysisInput("DegenGeom", "WriteCSVFlag", [0], 0) vsp.SetIntAnalysisInput("DegenGeom", "WriteMFileFlag", [0], 0) degen_results_id = vsp.ExecAnalysis("DegenGeom") degen_objects = vsp.parse_degen_geom(degen_results_id) degen_mgr = dg.DegenGeomMgr(degen_objects) dg_prop_comp = degen_mgr.degen_objs[prop_id] orig_copy = dg_prop_comp.copies[0] origin = orig_copy[0].transmat.get_translations() self.assertAlmostEqual(origin[0], 0.0, places=6) self.assertAlmostEqual(origin[1], 60.0, places=6) self.assertAlmostEqual(origin[2], 0.0, places=6) angles = orig_copy[0].transmat.get_angles() self.assertAlmostEqual(angles[0], 10.0, places=6) self.assertAlmostEqual(angles[1], 90.0, places=6) self.assertAlmostEqual(angles[2], 0.0, places=6) sym_copy = dg_prop_comp.copies[1] origin = sym_copy[0].transmat.get_translations() self.assertAlmostEqual(origin[0], 0.0, places=6) self.assertAlmostEqual(origin[1], -60.0, places=6) self.assertAlmostEqual(origin[2], 0.0, places=6) angles = sym_copy[0].transmat.get_angles() self.assertAlmostEqual(angles[0], -180.0 + 10.0, places=6) self.assertAlmostEqual(angles[1], 90.0, places=6) self.assertAlmostEqual(angles[2], 0.0, places=6) self.assertTrue(True)
def create_input_from_degen_geom(degen_objects=None, degen_set=None, title="DegenAvl", mach=0.0, Sref=1.0, Bref=1.0, Cref=1.0, cgRef=(0.0, 0.0, 0.0), cdp=0.0): """ Creates an AvlInput object from a list of degen geometry objects The degen objects can be created by passing the vsp set from which to create them :param degen_objects: List of degen geom objects, these can be created from openvsp. If degen_objects is None, degen objects will be created by using OpenVSP on the input degen set :param degen_set: OpenVSP set to create degen objects from if :param degen_objects is None :param title: title of the avl geometry :param mach: mach number :param Sref: reference area :param Bref: span :param Cref: reference chord :param cgRef: moment calculation location :param cdp: fixed parasite drag value to add to computed induced drag :return: AvlInput object """ import degen_geom as dg import numpy as np header = AvlHeader(title, Mach=mach, Sref=Sref, Cref=Cref, Bref=Bref, CGref=cgRef, CDp=cdp) surfaces = [] components = {} # Create degen objects from OpenVSP if no degen objects were passed in. Throw an exception if both degen_objects # and degen_set are None if degen_objects is None and degen_set is None: raise ValueError( "degen_objects and degen_set cannot both be set to None") if degen_objects is None: # Import vsp locally to limit module dependency on openvsp import openvsp as vsp # Turn off file exports vsp.SetIntAnalysisInput("DegenGeom", "WriteCSVFlag", [0], 0) vsp.SetIntAnalysisInput("DegenGeom", "WriteMFileFlag", [0], 0) # Select the appropriate Set vsp.SetIntAnalysisInput("DegenGeom", "Set", [degen_set]) # Run DegenGeom vsp.Update() degen_results_id = vsp.ExecAnalysis("DegenGeom") # Post process the results from the vsp api into more useful objects degen_objects = vsp.parse_degen_geom(degen_results_id) for degen_obj in degen_objects: component = len(components) + 1 if degen_obj.name in components: component = components[degen_obj.name] else: components[degen_obj.name] = component for stick in degen_obj.sticks: surf = AvlSurface(name=degen_obj.name, Nchord=degen_obj.surf.num_pnts, Component=component, Nspan=None, Sspace=None) # TODO: Add support for bodies if degen_obj.type == dg.DegenTypeEnum.LIFTING: # Sort sticks such that increase in y value. If y is constant (e.g. vertical tail) then order from z+ to z- # (top to bottom) le = np.array(stick.le) te = np.array(stick.te) chord = np.array(stick.chord) u = np.array(stick.u) sort_inds = [] uniq_y = np.unique(le[:, 1]) if len(uniq_y) > 1: # y is not constant, so now sort based on y coordinate sort_inds = le[:, 1].argsort() else: sort_inds = le[:, 2].argsort()[::-1] le = le[sort_inds] te = te[sort_inds] chord = chord[sort_inds] u = u[sort_inds] nspan = 1 for i in range(len(le)): nspan += 1 if abs(round(u[i]) - u[i]) > 1.0e-10: continue # Compute ainc x_vec = np.array([1.0, 0.0, 0.0]) chord_vec = te[i, :] - le[i, :] cos_theta = np.dot(chord_vec, x_vec) / np.linalg.norm(chord_vec) rot_axis = np.cross(x_vec, chord_vec) angle_sign = 1.0 if rot_axis[np.argmax(np.abs(rot_axis))] < 0.0: angle_sign = -1.0 ainc = np.rad2deg(np.arccos(np.clip(cos_theta, -1, 1))) * angle_sign sect = AvlSection(le=le[i, :], chord=chord[i], ainc=ainc, Nspan=nspan, Sspace=1.0) surf.addSection(sect) if len(surf.sections) > 1: surf.sections[-2].Nspan = nspan nspan = 2 if degen_obj.type == dg.DegenTypeEnum.BODY: continue surfaces.append(surf) return AvlInput(header, surfaces)