Source code for aerodynamics

import pdb
import numpy as np
import openmdao
import openmdao.api as om
from pyNA.src.aircraft import Aircraft


[docs]class Aerodynamics(om.ExplicitComponent): """ Computes aerodynamic forces and Mach number along the trajectory. The *Aerodynamics* component requires the following inputs: * ``inputs['c_l']``: aircraft lift coefficient [-] * ``inputs['c_d']``: aircraft drag coefficient [-] * ``inputs['rho_0']``: ambient density [kg/m3] * ``inputs['c_0']``: ambient speed of sound [m/s] * ``inputs['v']``: aircraft velocity [m/s] The *Aerodynamics* component computes the following outputs: * ``outputs['q']``: ambient dynamic pressure [Pa] * ``outputs['L']``: aircraft lift [N] * ``outputs['D']``: aircraft drag [N] * ``outputs['M_0']``: ambient Mach number [-] """
[docs] def initialize(self): self.options.declare('num_nodes', types=int, desc='Number of nodes to be evaluated in the RHS') self.options.declare('ac', types=Aircraft)
[docs] def setup(self): # Load options nn = self.options['num_nodes'] # Inputs self.add_input('c_l', shape=(nn,), desc='lift coefficient', units=None) self.add_input('c_d', shape=(nn,), desc='lift coefficient', units=None) self.add_input(name='rho_0', shape=(nn,), desc='atmospheric density', units='kg/m**3') self.add_input(name='c_0', shape=(nn,), desc='atmospheric speed of sound', units='m/s') self.add_input(name='v', shape=(nn,), desc='air-relative velocity', units='m/s') # Outputs self.add_output(name='q', shape=(nn,), desc='dynamic pressure', units='N/m**2') self.add_output(name='L', shape=(nn,), desc='aerodynamic lift force', units='N') self.add_output(name='D', shape=(nn,), desc='aerodynamic drag force', units='N') self.add_output(name='M_0', shape=(nn,), desc='Mach number', units=None) # Partials ar = np.arange(nn) self.declare_partials(of='q', wrt='rho_0', rows=ar, cols=ar) self.declare_partials(of='q', wrt='v', rows=ar, cols=ar) self.declare_partials(of='L', wrt='c_l', dependent=True, rows=ar, cols=ar) self.declare_partials(of='L', wrt='rho_0', dependent=True, rows=ar, cols=ar) self.declare_partials(of='L', wrt='v', dependent=True, rows=ar, cols=ar) self.declare_partials(of='D', wrt='c_d', dependent=True, rows=ar, cols=ar) self.declare_partials(of='D', wrt='rho_0', dependent=True, rows=ar, cols=ar) self.declare_partials(of='D', wrt='v', dependent=True, rows=ar, cols=ar) self.declare_partials(of='M_0', wrt='v', rows=ar, cols=ar, val=1.0) self.declare_partials(of='M_0', wrt='c_0', rows=ar, cols=ar, val=1.0)
[docs] def compute(self, inputs: openmdao.vectors.default_vector.DefaultVector, outputs: openmdao.vectors.default_vector.DefaultVector): # Load options ac = self.options['ac'] # Dynamic pressure outputs['q'] = 0.5 * inputs['rho_0'] * inputs['v'] ** 2 # Mach number outputs['M_0'] = inputs['v'] / inputs['c_0'] # Forces outputs['L'] = outputs['q'] * ac.af_S_w * inputs['c_l'] outputs['D'] = outputs['q'] * ac.af_S_w * inputs['c_d']
[docs] def compute_partials(self, inputs:openmdao.vectors.default_vector.DefaultVector, partials: openmdao.vectors.default_vector.DefaultVector): # Load options ac = self.options['ac'] # Compute dynamic pressure q = 0.5 * inputs['rho_0'] * inputs['v'] ** 2 partials['q', 'rho_0'] = 0.5 * inputs['v'] ** 2 partials['q', 'v'] = inputs['rho_0'] * inputs['v'] partials['L', 'c_l'] = q * ac.af_S_w partials['L', 'rho_0'] = inputs['c_l'] * 1/2. * inputs['v']**2 * ac.af_S_w partials['L', 'v'] = inputs['c_l'] * inputs['rho_0'] * inputs['v'] * ac.af_S_w partials['D', 'c_d'] = q * ac.af_S_w partials['D', 'rho_0'] = inputs['c_d'] * 1/2. * inputs['v']**2 * ac.af_S_w partials['D', 'v'] = inputs['c_d'] * inputs['rho_0'] * inputs['v'] * ac.af_S_w partials['M_0', 'v'] = 1.0 / inputs['c_0'] partials['M_0', 'c_0'] = -inputs['v'] / inputs['c_0'] ** 2