Source code for openaerostruct.functionals.equilibrium

import openmdao.api as om
from openaerostruct.utils.constants import grav_constant


[docs] class Equilibrium(om.ExplicitComponent): """ Computes L_equals_W, which is a normalized measure of the weight of the aircraft minus the total generated lift. So if L_equals_W is positive, the aircraft weighs more than the amount of lift it's producing. Generally we use this measure to ensure that lift equals weight for a cruise fligth condition. Note that we add information from each lifting surface. Parameters ---------- structural_mass : float Total weight of the structural spar for a given surface. fuelburn : float Computed fuel burn in kg based on the Breguet range equation. W0 : float The operating empty weight of the aircraft, without fuel or structural mass. Supplied in kg despite being a 'weight' due to convention. load_factor : float Multiplicative factor on gravity. 1.0 is normal flight; 2.5 would be for a 2.5g manuever. CL : float Total coefficient of lift (CL) for the entire aircraft. S_ref_total : float Total surface area of the aircraft based on the sum of individual surface areas. v : float Freestream air velocity in m/s. rho : float Air density in kg/m^3. Returns ------- L_equals_W : float Equality constraint for lift = total weight. L_equals_W = 0 for the constraint to be satisfied. total_weight : float Total weight of the entire aircraft, including W0, all structural weights, and fuel. """ def initialize(self): self.options.declare("surfaces", types=list) def setup(self): for surface in self.options["surfaces"]: name = surface["name"] self.add_input(name + "_structural_mass", val=1.0, units="kg") self.declare_partials("L_equals_W", name + "_structural_mass") self.declare_partials("total_weight", name + "_structural_mass") self.add_input("fuelburn", val=123.0, units="kg") self.add_input("W0", val=1000.0, units="kg") self.add_input("load_factor", val=1.05) self.add_input("CL", val=0.7) self.add_input("S_ref_total", val=15.0, units="m**2") self.add_input("v", val=100.0, units="m/s") self.add_input("rho", val=1.2, units="kg/m**3") self.add_output("L_equals_W", val=1.0) self.add_output("total_weight", val=1.0, units="N") self.declare_partials("L_equals_W", "CL") self.declare_partials("L_equals_W", "S_ref_total") self.declare_partials("L_equals_W", "W0") self.declare_partials("L_equals_W", "fuelburn") self.declare_partials("L_equals_W", "load_factor") self.declare_partials("L_equals_W", "rho") self.declare_partials("L_equals_W", "v") self.declare_partials("total_weight", "W0") self.declare_partials("total_weight", "fuelburn") self.declare_partials("total_weight", "load_factor") def compute(self, inputs, outputs): g = grav_constant * inputs["load_factor"] W0 = inputs["W0"] rho = inputs["rho"] v = inputs["v"] structural_mass = 0.0 for surface in self.options["surfaces"]: name = surface["name"] structural_mass += inputs[name + "_structural_mass"] S_ref_tot = inputs["S_ref_total"] tot_weight = (structural_mass + inputs["fuelburn"] + W0) * g outputs["total_weight"] = tot_weight outputs["L_equals_W"] = 1 - (0.5 * rho * v**2 * S_ref_tot) * inputs["CL"] / tot_weight def compute_partials(self, inputs, partials): g = grav_constant * inputs["load_factor"] W0 = inputs["W0"] rho = inputs["rho"] v = inputs["v"] structural_mass = 0.0 for surface in self.options["surfaces"]: name = surface["name"] structural_mass += inputs[name + "_structural_mass"] S_ref_tot = inputs["S_ref_total"] tot_weight = (structural_mass + inputs["fuelburn"] + W0) * g L = inputs["CL"] * (0.5 * rho * v**2 * S_ref_tot) partials["total_weight", "fuelburn"] = g partials["total_weight", "W0"] = g partials["total_weight", "load_factor"] = (inputs["fuelburn"] + inputs["W0"] + structural_mass) * grav_constant partials["L_equals_W", "fuelburn"] = L / tot_weight**2 * g partials["L_equals_W", "W0"] = L / tot_weight**2 * g partials["L_equals_W", "load_factor"] = ( L / tot_weight**2 * (inputs["fuelburn"] + inputs["W0"] + structural_mass) * grav_constant ) partials["L_equals_W", "rho"] = -0.5 * S_ref_tot * v**2 * inputs["CL"] / tot_weight partials["L_equals_W", "v"] = -rho * S_ref_tot * v * inputs["CL"] / tot_weight partials["L_equals_W", "CL"] = -0.5 * rho * v**2 * S_ref_tot / tot_weight partials["L_equals_W", "S_ref_total"] = -0.5 * rho * v**2 * inputs["CL"] / tot_weight for surface in self.options["surfaces"]: name = surface["name"] partials["total_weight", name + "_structural_mass"] = 1.0 * g partials["L_equals_W", name + "_structural_mass"] = L / tot_weight**2 * g