Ejemplo n.º 1
0
    def _enforce_governing_equations(self):
        # Calculate unsteady lift due to pitching
        wagner = wagners_function(self.reduced_time)
        ds = self.reduced_time[1:] - self.reduced_time[:-1]
        da_ds = (self.angles_of_attack[1:] - self.angles_of_attack[:-1]) / ds
        init_term = self.angles_of_attack[0] * wagner[:-1]
        for i in range(self.timesteps - 1):
            integral_term = np.sum(da_ds[j] * wagner[i - j] * ds[j]
                                   for j in range(i))
            self.lift_coefficients[i] = 2 * np.pi * (integral_term +
                                                     init_term[i])

        # Calculate unsteady lift due to transverse gust
        kussner = kussners_function(self.reduced_time)
        dw_ds = (self.gust_profile[1:] - self.gust_profile[:-1]) / ds
        init_term = self.gust_profile[0] * kussner
        for i in range(self.timesteps - 1):
            integral_term = 0
            for j in range(i):
                integral_term += dw_ds[j] * kussner[i - j] * ds[j]
            self.lift_coefficients[i] += 2 * np.pi / self.velocity * (
                init_term[i] + integral_term)

        # Calculate unsteady lift due to added mass
        self.lift_coefficients += np.pi / 2 * np.cos(
            self.angles_of_attack[:-1])**2 * da_ds

        # Integral of lift to be minimized
        lift_squared_integral = np.sum(self.lift_coefficients**2)

        # Constraints and objective to minimize
        self.opti.subject_to(self.angles_of_attack[0] == 0)
        self.opti.minimize(lift_squared_integral)
Ejemplo n.º 2
0
def make_matrix(x):
    matrix = np.ones((len(x), degree + 1))
    for j in range(1, degree - 2):
        matrix[:, j] = matrix[:, j - 1] * x
    matrix[:, degree - 2] = np.cos(x)
    matrix[:, degree - 1] = np.sin(x)
    matrix[:, degree] = np.exp(x)
    return matrix
Ejemplo n.º 3
0
def firefly_CLA_and_CDA_fuse_hybrid(  # TODO remove
    fuse_fineness_ratio,
    fuse_boattail_angle,
    fuse_TE_diameter,
    fuse_length,
    fuse_diameter,
    alpha,
    V,
    mach,
    rho,
    mu,
):
    """
    Estimated equiv. lift area and equiv. drag area of the Firefly fuselage, component buildup.
    :param fuse_fineness_ratio: Fineness ratio of the fuselage nose (length / diameter). 0.5 is hemispherical.
    :param fuse_boattail_angle: Boattail half-angle [deg]
    :param fuse_TE_diameter: Diameter of the fuselage's base at the "trailing edge" [m]
    :param fuse_length: Length of the fuselage [m]
    :param fuse_diameter: Diameter of the fuselage [m]
    :param alpha: Angle of attack [deg]
    :param V: Airspeed [m/s]
    :param mach: Mach number [unitless]
    :param rho: Air density [kg/m^3]
    :param mu: Dynamic viscosity of air [Pa*s]
    :return: A tuple of (CLA, CDA) [m^2]
    """
    alpha_rad = alpha * np.pi / 180
    sin_alpha = np.sin(alpha_rad)
    cos_alpha = np.cos(alpha_rad)
    """
    Lift of a truncated fuselage, following slender body theory.
    """
    separation_location = 0.3  # 0 for separation at trailing edge, 1 for separation at start of boat-tail. Calibrate this.
    diameter_at_separation = (
        1 - separation_location
    ) * fuse_TE_diameter + separation_location * fuse_diameter

    fuse_TE_area = np.pi / 4 * diameter_at_separation**2
    CLA_slender_body = 2 * fuse_TE_area * alpha_rad  # Derived from FVA 6.6.5, Eq. 6.75
    """
    Crossflow force, following the method of Jorgensen, 1977: "Prediction of Static Aero. Chars. for Slender..."
    """
    V_crossflow = V * sin_alpha
    Re_crossflow = rho * np.abs(V_crossflow) * fuse_diameter / mu
    mach_crossflow = mach * np.abs(sin_alpha)
    eta = 1  # TODO make this a function of overall fineness ratio
    Cdn = 0.2  # Taken from suggestion for supercritical cylinders in Hoerner's Fluid Dynamic Drag, pg. 3-11
    S_planform = fuse_diameter * fuse_length
    CNA = eta * Cdn * S_planform * sin_alpha * np.abs(sin_alpha)
    CLA_crossflow = CNA * cos_alpha
    CDA_crossflow = CNA * sin_alpha

    CLA = CLA_slender_body + CLA_crossflow
    r"""
    Zero-lift_force drag_force
    Model derived from high-fidelity data at: C:\Projects\GitHub\firefly_aerodynamics\Design_Opt\studies\Circular Firefly Fuse CFD\Zero-Lift Drag
    """
    c = np.array([
        112.57153128951402720758778741583,
        -7.1720570832587240417410612280946,
        -0.01765596807595304351679033061373,
        0.0026135564778264172743071913629365,
        550.8775012129947299399645999074,
        3.3166868391027000129156476759817,
        11774.081980549422951298765838146,
        3073258.204571904614567756652832,
        0.0299,
    ])  # coefficients
    fuse_Re = rho * np.abs(V) * fuse_length / mu
    CDA_zero_lift = (
        (c[0] * np.exp(c[1] * fuse_fineness_ratio) + c[2] * fuse_boattail_angle
         + c[3] * fuse_boattail_angle**2 + c[4] * fuse_TE_diameter**2 + c[5]) /
        c[6] * (fuse_Re / c[7])**(-1 / 7) * (fuse_length * fuse_diameter) /
        c[8])
    r"""
    Assumes a ring-shaped wake projection into the Trefftz plane with a sinusoidal circulation distribution.
    This results in a uniform grad(phi) within the ring in the Trefftz plane.
    Derivation at C:\Projects\GitHub\firefly_aerodynamics\Gists and Ideas\Ring Wing Potential Flow
    """
    fuse_oswalds_efficiency = 0.5
    CDiA_slender_body = CLA**2 / (
        diameter_at_separation**2 * np.pi *
        fuse_oswalds_efficiency) / 2  # or equivalently, use the next line
    # CDiA_slender_body = fuse_TE_area * alpha_rad ** 2 / 2

    CDA = CDA_crossflow + CDiA_slender_body + CDA_zero_lift

    return CLA, CDA
Ejemplo n.º 4
0
    opti = asb.Opti()
    # v_a = opti.variable(init_guess=15)
    # v_t = opti.variable(init_guess=15)
    # u_a = opti.variable(init_guess=5)
    Psi = opti.variable(init_guess=pi/2)
    # h_ati = opti.variable(init_guess=0.01)
    # f = opti.variable(init_guess=300)
    # F = opti.variable(init_guess=1)
    # gamma = opti.variable(init_guess=1)

    ### Define velocity triangle components
    U_a = airspeed #+ u_a # Axial velocity w/o induced eff. assuming u_a = 0
    U_t = omega * radial_loc  # Tangential velocity w/o induced eff.
    U = (U_a ** 2 + U_t ** 2) ** 0.5  # Velocity magnitude
    W_a = 0.5 * U_a + 0.5 * U * np.sin(Psi)  # Axial velocity w/ induced eff.
    W_t = 0.5 * U_t + 0.5 * U * np.cos(Psi)  # Tangential velocity w/ induced eff.
    v_a = W_a - U_a  # Axial induced velocity
    v_t = U_t - W_t  # Tangential induced velocity
    W = (W_a ** 2 + W_t ** 2) ** 0.5
    Re = air_density * W * chord_local / mu
    Ma = W / speed_of_sound
    v = (v_a ** 2 + v_t ** 2) ** 0.5
    loc_wake_adv_ratio = (radial_loc / tip_radius) * (W_a / W_t)
    f = (n_blades / 2) * (1 - radial_loc / tip_radius) * 1 / loc_wake_adv_ratio
    F = 2 / pi * np.arccos(np.exp(-f))


    ## Compute local blade quantities
    phi_rad = np.arctan2(W_a, W_t) #local flow angle
    phi_deg = phi_rad * 180 / pi
    alpha_rad = twist_local_rad - phi_rad
Ejemplo n.º 5
0
    def performance(
        self,
        speed,
        throttle_state=1,
        grade=0,
        headwind=0,
    ):
        ##### Figure out electric thrust force

        wheel_radius = self.wheel_diameter / 2
        wheel_rads_per_sec = speed / wheel_radius
        wheel_rpm = wheel_rads_per_sec * 30 / np.pi
        motor_rpm = wheel_rpm / self.gear_ratio

        ### Limit performance by either max voltage or max current
        perf_via_max_voltage = self.motor.performance(
            voltage=self.max_voltage,
            rpm=motor_rpm,
        )
        perf_via_throttle = self.motor.performance(
            current=self.max_current * throttle_state,
            rpm=motor_rpm,
        )

        if perf_via_max_voltage['torque'] > perf_via_throttle['torque']:
            perf = perf_via_throttle
        else:
            perf = perf_via_max_voltage

        motor_torque = perf['torque']
        wheel_torque = motor_torque / self.gear_ratio
        wheel_force = wheel_torque / wheel_radius

        thrust = wheel_force

        ##### Gravity

        gravity_drag = 9.81 * np.sin(np.arctan(grade)) * self.mass

        ##### Rolling Resistance

        # Crr = 0.0020  # Concrete
        Crr = 0.0050  # Asphalt
        # Crr = 0.0060  # Gravel
        # Crr = 0.0070  # Grass
        # Crr = 0.0200  # Off-road
        # Crr = 0.0300  # Sand
        rolling_drag = 9.81 * np.cos(np.arctan(grade)) * self.mass * Crr

        ##### Aerodynamics
        # CDA = 0.408  # Tops
        CDA = 0.324  # Hoods
        # CDA = 0.307  # Drops
        # CDA = 0.2914  # Aerobars

        eff_speed = speed + headwind
        air_drag = 0.5 * atmo.density() * eff_speed * np.abs(eff_speed) * CDA

        ##### Summation
        net_force = thrust - gravity_drag - rolling_drag - air_drag
        net_accel = net_force / self.mass

        return {
            "net acceleration": net_accel,
            "motor state": perf,
        }