codexmean-aerodynamic-chord.py
mean-aerodynamic-chord.py
"""Original trapezoidal planform and chord-weighted mean; PNG in cwd."""
from pathlib import Path
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
def main():
span, root, tip = 10., 2., 1.
lam = tip/root
area = span*(root+tip)/2
mac = 2*root/3*(1+lam+lam**2)/(1+lam)
ymac = span/6*(1+2*lam)/(1+lam)
grid = np.linspace(-span/2,span/2,10001)
chord = root-(root-tip)*2*np.abs(grid)/span
np.testing.assert_allclose(np.trapezoid(chord,grid),area)
np.testing.assert_allclose(np.trapezoid(chord**2,grid)/area,mac,atol=1e-8)
np.testing.assert_allclose(mac,14/9)
np.testing.assert_allclose(root-(root-tip)*2*ymac/span,mac)
assert mac >= area/span
fig, axes = plt.subplots(1,2,figsize=(8.6,3.2),dpi=100,facecolor='white',gridspec_kw={'width_ratios':[2.3,1]})
ax=axes[0]
ax.add_patch(Polygon([(-5,0),(5,0),(5,1),(0,2),(-5,1)],facecolor='#deedf7',edgecolor='#2475ad',lw=2))
ax.plot([0,0],[0,root],color='#555555',ls='--')
ax.plot([ymac,ymac],[0,mac],color='#b63f32',lw=3,label='Mean aerodynamic chord')
ax.annotate(f'{mac:.4f} m',xy=(ymac,mac*.6),xytext=(3.2,1.9),arrowprops=dict(arrowstyle='->',color='#b63f32'),color='#b63f32',fontsize=11)
ax.set(xlim=(-5.5,5.5),ylim=(2.4,-.25),xlabel='Spanwise coordinate y (m)',ylabel='Chordwise coordinate x (m)',title='Unswept symmetric trapezoidal wing')
ax.set_aspect('equal', adjustable='box')
ax.grid(alpha=.2)
ax.legend(fontsize=9,loc='lower left')
axes[1].axis('off')
axes[1].text(.02,.9,'Constructed planform\n\nSpan: 10 m\nRoot chord: 2 m\nTip chord: 1 m\nArea: 15 m²\n\nSpan average: 1.5000 m\nChord-weighted mean:\n1.5556 m',va='top',fontsize=10,linespacing=1.25)
fig.tight_layout()
fig.savefig(Path.cwd()/(Path(__file__).stem+'.png'),facecolor='white')
plt.close(fig)
if __name__=='__main__':
main()