Source code for aerosandbox.geometry.openvsp_io.asb_to_openvsp.wing_vspscript_generator

import aerosandbox.numpy as np
from aerosandbox.geometry.wing import Wing, WingXSec
from aerosandbox.geometry.airfoil.airfoil import Airfoil
from textwrap import indent, dedent
from aerosandbox.geometry.openvsp_io.asb_to_openvsp import _utilities


[docs]def generate_wing( wing: Wing, include_main=True ) -> str: """ Generates a VSPScript file for a Wing object. Args: wing: The Wing object to generate a VSPScript file for. Returns: A VSPScript file as a string. """ script = "" script += f"""\ //==== Add Wing "{wing.name}" ====// string wid = AddGeom("WING"); ChangeXSecShape( GetXSecSurf( wid, 0 ), 0, XS_FILE_AIRFOIL ); ChangeXSecShape( GetXSecSurf( wid, 1 ), 1, XS_FILE_AIRFOIL ); """ script += """//==== Generate Blank Wing Sections ====//\n""" if len(wing.xsecs) < 2: raise ValueError("Wings must have at least 2 cross sections.") else: for i in range(len(wing.xsecs) - 1): script += f"""\ InsertXSec( wid, 1, XS_FILE_AIRFOIL ); // WingXSecs {i} to {i + 1} """ script += f"""\ //===== Cut The Original Section =====// CutXSec( wid, 1 ); //==== Set Overall Wing Options and First Section ====// SetParmVal( wid, "X_Rel_Location", "XForm", {wing.xsecs[0].xyz_le[0]} ); SetParmVal( wid, "Y_Rel_Location", "XForm", {wing.xsecs[0].xyz_le[1]} ); SetParmVal( wid, "Z_Rel_Location", "XForm", {wing.xsecs[0].xyz_le[2]} ); SetParmVal( wid, "Twist", "XSec_0", {wing.xsecs[0].twist} ); SetParmVal( wid, "Twist_Location", "XSec_0", 0.0 ); SetParmVal( wid, "Sym_Ancestor", "Sym", 0.0 ); // Global Origin SetParmVal( wid, "Sym_Planar_Flag", "Sym", {"2.0" if wing.symmetric else "0.0"} ); // 0 = None, 2 = XZ sym. SetParmVal( wid, "RotateAirfoilMatchDideralFlag", "WingGeom", 1.0 ); // sic, typo from OpenVSP Update(); """ script += """//==== Set Wing Section Options ====//\n""" xyz_le = np.stack([xsec.xyz_le for xsec in wing.xsecs], axis=0) dxyz_le = np.diff(xyz_le, axis=0) dx_le = dxyz_le[:, 0] dy_le = dxyz_le[:, 1] dz_le = dxyz_le[:, 2] dyz_le = np.sqrt(dy_le ** 2 + dz_le ** 2) dihedrals = np.arctan2d(dz_le, dy_le) sweep_le = np.arctan2d(dx_le, dyz_le) for i, (xsec_a, xsec_b) in enumerate(zip(wing.xsecs[:-1], wing.xsecs[1:])): script += f"""\ // ASB Section {i}, VSP Section {i + 1} (ASB XSecs {i} to {i + 1}) SetParmVal( wid, "Root_Chord", "XSec_{i + 1}", {xsec_a.chord} ); SetParmVal( wid, "Tip_Chord", "XSec_{i + 1}", {xsec_b.chord} ); SetParmVal( wid, "Span", "XSec_{i + 1}", {dyz_le[i]}); SetParmVal( wid, "Sweep", "XSec_{i + 1}", {sweep_le[i]} ); SetParmVal( wid, "Sweep_Location", "XSec_{i + 1}", 0.0 ); SetParmVal( wid, "Twist", "XSec_{i + 1}", {xsec_b.twist} ); SetParmVal( wid, "Twist_Location", "XSec_{i + 1}", 0.0 ); SetParmVal( wid, "Dihedral", "XSec_{i + 1}", {dihedrals[i]} ); SetParmVal( wid, "SectTess_U", "XSec_{i + 1}", 10 ); Update(); """ script += """\ //==== Set Airfoils ====// """ for i in range(len(wing.xsecs)): xsec = wing.xsecs[i] upper = xsec.airfoil.upper_coordinates()[::-1] # VSP wants front to back order lower = xsec.airfoil.lower_coordinates() # Front to back order up_pnt_vecs = ", ".join([ f"vec3d({p[0]:.8g}, {p[1]:.8g}, 0.0)" for p in upper ]) lo_pnt_vecs = ", ".join([ f"vec3d({p[0]:.8g}, {p[1]:.8g}, 0.0)" for p in lower ]) script += f"""\ {{ array<vec3d> up_pnt_vec = {{ {up_pnt_vecs} }}; array<vec3d> lo_pnt_vec = {{ {lo_pnt_vecs} }}; string xsec_surf = GetXSecSurf( wid, {i} ); xsec_surf = GetXSecSurf( wid, {i} ); string xsec = GetXSec( xsec_surf, {i} ); SetParmVal( wid, "ThickChord", "XSecCurve_{i}", 0.5 ); // This is a hack that triggers VSP to update the curve SetParmVal( wid, "ThickChord", "XSecCurve_{i}", 1.0 ); SetAirfoilPnts( xsec, up_pnt_vec, lo_pnt_vec ); Update(); }} """ script += """\ SetParmVal( wid, "Tess_W", "Shape", 100 ); Update(); """ if include_main: script = _utilities.wrap_script(script) return script
if __name__ == '__main__':
[docs] wing = Wing( name="Main Wing", xsecs=[ WingXSec( xyz_le=[1, 0, 0], chord=1.1, twist=-20, airfoil=Airfoil(name="dae11") ), WingXSec( xyz_le=[1, 2, 0], chord=0.9, twist=40, airfoil=Airfoil(name="NACA4412") ), WingXSec( xyz_le=[2, 5, 0], chord=0.5, twist=0, airfoil=Airfoil(name="NACA3412") ), WingXSec( xyz_le=[2, 10, 5], chord=0.25, twist=0, airfoil=Airfoil(name="NACA2412") ) ] )
print(generate_wing(wing)) with open("test.vspscript", "w") as f: f.write(generate_wing(wing))