def plot_tropopause_altitude(): fig, ax = plt.subplots() day_of_years = np.linspace(0, 365, 250) latitudes = np.linspace(-80, 80, 200) Day_of_years, Latitudes = np.meshgrid(day_of_years, latitudes) trop_alt = tropopause_altitude( Latitudes.flatten(), Day_of_years.flatten() ).reshape(Latitudes.shape) args = [ day_of_years, latitudes, trop_alt / 1e3 ] levels = np.arange(10, 20.1, 1) CS = plt.contour(*args, levels=levels, linewidths=0.5, colors="k", alpha=0.7) CF = plt.contourf(*args, levels=levels, cmap='viridis_r', alpha=0.7, extend="both") cbar = plt.colorbar(label="Tropopause Altitude [km]", extendrect=True) ax.clabel(CS, inline=1, fontsize=9, fmt="%.0f km") plt.xticks( np.linspace(0, 365, 13)[:-1], ( "Jan. 1", "Feb. 1", "Mar. 1", "Apr. 1", "May 1", "June 1", "July 1", "Aug. 1", "Sep. 1", "Oct. 1", "Nov. 1", "Dec. 1" ), rotation=40 ) lat_label_vals = np.arange(-80, 80.1, 20) lat_labels = [] for lat in lat_label_vals: if lat >= 0: lat_labels.append(f"{lat:.0f}N") else: lat_labels.append(f"{-lat:.0f}S") plt.yticks( lat_label_vals, lat_labels ) show_plot( f"Tropopause Altitude by Season and Latitude", xlabel="Day of Year", ylabel="Latitude", )
def draw( self, scalar_to_plot: str = "potential", # "potential", "streamfunction", "xvel", "yvel", "velmag", "Cp" x_points: np.ndarray = np.linspace(-10, 10, 400), y_points: np.ndarray = np.linspace(-10, 10, 300), percentiles_to_include=99.7, show=True, ): X, Y = np.meshgrid(x_points, y_points) X_r = np.reshape(X, -1) Y_r = np.reshape(Y, -1) points = np.vstack((X_r, Y_r)).T if scalar_to_plot == "potential": scalar_to_plot_value = sum( [object.get_potential_at(points) for object in self.objects]) elif scalar_to_plot == "streamfunction": scalar_to_plot_value = sum([ object.get_streamfunction_at(points) for object in self.objects ]) elif scalar_to_plot == "xvel": scalar_to_plot_value = sum( [object.get_x_velocity_at(points) for object in self.objects]) elif scalar_to_plot == "yvel": scalar_to_plot_value = sum( [object.get_y_velocity_at(points) for object in self.objects]) elif scalar_to_plot == "velmag": x_vels = sum( [object.get_x_velocity_at(points) for object in self.objects]) y_vels = sum( [object.get_y_velocity_at(points) for object in self.objects]) scalar_to_plot_value = np.sqrt(x_vels**2 + y_vels**2) elif scalar_to_plot == "Cp": x_vels = sum( [object.get_x_velocity_at(points) for object in self.objects]) y_vels = sum( [object.get_y_velocity_at(points) for object in self.objects]) V = np.sqrt(x_vels**2 + y_vels**2) scalar_to_plot_value = 1 - V**2 else: raise ValueError("Bad value of `scalar_to_plot`!") min = np.nanpercentile(scalar_to_plot_value, 50 - percentiles_to_include / 2) max = np.nanpercentile(scalar_to_plot_value, 50 + percentiles_to_include / 2) contour(x_points, y_points, scalar_to_plot_value.reshape(X.shape), levels=np.linspace(min, max, 80), linelabels=False, cmap=plt.get_cmap("rainbow"), contour_kwargs={ "linestyles": 'solid', "alpha": 0.4 }) plt.gca().set_aspect("equal", adjustable='box') show_plot(f"Potential Flow: {scalar_to_plot}", "$x$", "$y$", show=show)
def get_trajectory(parameterization: type = asb.DynamicsPointMass2DCartesian, gravity=True, drag=True, plot=False): if parameterization is asb.DynamicsPointMass2DCartesian: dyn = parameterization( mass_props=asb.MassProperties(mass=1), x_e=0, z_e=0, u_e=u_e_0, w_e=w_e_0, ) elif parameterization is asb.DynamicsPointMass2DSpeedGamma: dyn = parameterization( mass_props=asb.MassProperties(mass=1), x_e=0, z_e=0, speed=speed_0, gamma=gamma_0, ) else: raise ValueError("Bad value of `parameterization`!") def derivatives(t, y): this_dyn = dyn.get_new_instance_with_state(y) if gravity: this_dyn.add_gravity_force() q = 0.5 * 1.225 * this_dyn.speed**2 if drag: this_dyn.add_force(Fx=-1 * (0.1)**2 * q, axes="wind") return this_dyn.unpack_state(this_dyn.state_derivatives()) res = integrate.solve_ivp( fun=derivatives, t_span=(time[0], time[-1]), t_eval=time, y0=dyn.unpack_state(), method="LSODA", # vectorized=True, rtol=1e-9, atol=1e-9, ) dyn = dyn.get_new_instance_with_state(res.y) if plot: import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p fig, ax = plt.subplots() p.plot_color_by_value(dyn.x_e, dyn.altitude, c=dyn.speed, colorbar=True) p.equal() p.show_plot("Trajectory", "$x_e$", "$z_e$") return dyn
def plot_winds_at_tropopause_altitude(): fig, ax = plt.subplots() day_of_years = np.linspace(0, 365, 150) latitudes = np.linspace(-80, 80, 120) Day_of_years, Latitudes = np.meshgrid(day_of_years, latitudes) winds = wind_speed_world_95( altitude=tropopause_altitude(Latitudes.flatten(), Day_of_years.flatten()), latitude=Latitudes.flatten(), day_of_year=Day_of_years.flatten(), ).reshape(Latitudes.shape) args = [day_of_years, latitudes, winds] levels = np.arange(0, 80.1, 5) CS = plt.contour(*args, levels=levels, linewidths=0.5, colors="k", alpha=0.7) CF = plt.contourf(*args, levels=levels, cmap='viridis_r', alpha=0.7, extend="max") cbar = plt.colorbar(label="Wind Speed [m/s]", extendrect=True) ax.clabel(CS, inline=1, fontsize=9, fmt="%.0f m/s") plt.xticks( np.linspace(0, 365, 13)[:-1], ("Jan. 1", "Feb. 1", "Mar. 1", "Apr. 1", "May 1", "June 1", "July 1", "Aug. 1", "Sep. 1", "Oct. 1", "Nov. 1", "Dec. 1"), rotation=40) lat_label_vals = np.arange(-80, 80.1, 20) lat_labels = [] for lat in lat_label_vals: if lat >= 0: lat_labels.append(f"{lat:.0f}N") else: lat_labels.append(f"{-lat:.0f}S") plt.yticks(lat_label_vals, lat_labels) show_plot( f"95th-Percentile Wind Speeds at Tropopause Altitude", xlabel="Day of Year", ylabel="Latitude", )
def plot_Cf_flat_plates(): from aerosandbox.tools.pretty_plots import plt, show_plot Res = np.geomspace(1e3, 1e8, 500) for method in [ "blasius", "turbulent", "hybrid-cengel", "hybrid-schlichting", "hybrid-sharpe-convex", "hybrid-sharpe-nonconvex", ]: plt.loglog(Res, aero.Cf_flat_plate(Res, method=method), label=method) plt.ylim(1e-3, 1e-1) show_plot( "Models for Mean Skin Friction Coefficient of Flat Plate", r"$Re$", r"$C_f$", )
def plot_winds_at_day(day_of_year=0): fig, ax = plt.subplots() altitudes = np.linspace(0, 30000, 150) latitudes = np.linspace(-80, 80, 120) Altitudes, Latitudes = np.meshgrid(altitudes, latitudes) winds = wind_speed_world_95( altitude=Altitudes.flatten(), latitude=Latitudes.flatten(), day_of_year=day_of_year * np.ones_like(Altitudes.flatten()), ).reshape(Altitudes.shape) args = [altitudes / 1e3, latitudes, winds] levels = np.arange(0, 80.1, 5) CS = plt.contour(*args, levels=levels, linewidths=0.5, colors="k", alpha=0.7) CF = plt.contourf(*args, levels=levels, cmap='viridis_r', alpha=0.7, extend="max") cbar = plt.colorbar(label="Wind Speed [m/s]", extendrect=True) ax.clabel(CS, inline=1, fontsize=9, fmt="%.0f m/s") lat_label_vals = np.arange(-80, 80.1, 20) lat_labels = [] for lat in lat_label_vals: if lat >= 0: lat_labels.append(f"{lat:.0f}N") else: lat_labels.append(f"{-lat:.0f}S") plt.yticks(lat_label_vals, lat_labels) show_plot( f"95th-Percentile Wind Speeds at Day {day_of_year:.0f}", xlabel="Altitude [km]", ylabel="Latitude", )
from scipy import optimize fig, ax = plt.subplots() speeds = np.linspace(0, 30, 500) def get_mileage(speed): bike = Bike() try: perf = bike.steady_state_performance(speed=speed, ) except ValueError: return np.NaN motor = perf['motor state'] power = motor['voltage'] * motor['current'] return power / speed mileage = np.array([get_mileage(speed) for speed in speeds]) # J/m mileage_Wh_per_mile = mileage / 3600 * 1000 * 1.609 plt.plot(speeds * 2.24, mileage_Wh_per_mile) plt.xlim(left=0) plt.ylim(bottom=0, top=50) set_ticks(x_major=5, x_minor=1, y_major=5, y_minor=1) show_plot(f"Electric Bike: Mileage vs. Speed", xlabel="Speed [mph]", ylabel=f"Energy Mileage [Wh per mile]")
def get_trajectory( parameterization: type = asb.DynamicsPointMass3DCartesian, gravity=True, drag=True, sideforce=True, plot=False, verbose=False, ): opti = asb.Opti() if parameterization is asb.DynamicsPointMass3DCartesian: dyn = parameterization( mass_props=asb.MassProperties(mass=1), x_e=opti.variable(np.linspace(0, 300, N)), y_e=opti.variable(np.linspace(0, 0, N), scale=1), z_e=opti.variable(np.linspace(0, 0, N), scale=100), u_e=opti.variable(np.linspace(100, 50, N)), v_e=opti.variable(np.linspace(0, 0, N), scale=1), w_e=opti.variable(np.linspace(-100, 50, N)), ) elif parameterization is asb.DynamicsPointMass3DSpeedGammaTrack: dyn = parameterization( mass_props=asb.MassProperties(mass=1), x_e=opti.variable(np.linspace(0, 300, N)), y_e=opti.variable(np.linspace(0, 0, N), scale=1), z_e=opti.variable(np.linspace(0, 0, N), scale=100), speed=opti.variable(np.linspace(100, 50, N)), gamma=opti.variable(np.linspace(0, 0, N)), track=opti.variable(np.linspace(0, 0, N)), ) else: raise ValueError("Bad value of `parameterization`!") if gravity: dyn.add_gravity_force() q = 0.5 * 1.225 * dyn.speed**2 if drag: dyn.add_force(Fx=-1 * (0.1)**2 * q, axes="wind") if sideforce: strouhal = 0.2 frequency = 5 # strouhal * dyn.speed / 0.1 dyn.add_force(Fy=q * 1 * (0.1)**2 * np.sin(2 * np.pi * frequency * time), axes="wind") dyn.constrain_derivatives( opti=opti, time=time, ) opti.subject_to([ dyn.x_e[0] == 0, dyn.y_e[0] == 0, dyn.z_e[0] == 0, dyn.u_e[0] == 100, dyn.v_e[0] == 0, dyn.w_e[0] == -100, ]) sol = opti.solve(verbose=verbose) dyn.substitute_solution(sol) if plot: import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p fig, ax = plt.subplots() p.plot_color_by_value(dyn.x_e, dyn.altitude, c=dyn.speed, colorbar=True) p.equal() p.show_plot("Trajectory", "$x_e$", "$z_e$") return dyn
##### Tangential force calculation CT = (pt1_star + pt2_star * cosa + pt3_star * cosa**3) * sina**2 ##### Conversion to wind axes CL = CN * cosa + CT * sina CD = CN * sina - CT * cosa CM = np.zeros_like(CL) # TODO return CL, CD, CM if __name__ == '__main__': af = Airfoil("naca0012") alpha = np.linspace(0, 360, 721) CL, CD, CM = airfoil_coefficients_post_stall(af, alpha) from aerosandbox.tools.pretty_plots import plt, show_plot, set_ticks fig, ax = plt.subplots(1, 2, figsize=(8, 5)) plt.sca(ax[0]) plt.plot(alpha, CL) plt.xlabel("AoA") plt.ylabel("CL") set_ticks(45, 15, 0.5, 0.1) plt.sca(ax[1]) plt.plot(alpha, CD) plt.xlabel("AoA") plt.ylabel("CD") set_ticks(45, 15, 0.5, 0.1) show_plot()
# fuselage.draw() def get_aero(xyz_ref): return asb.AeroBuildup(airplane=asb.Airplane(fuselages=[fuselage], xyz_ref=xyz_ref), op_point=asb.OperatingPoint(velocity=10, alpha=5, beta=5)).run() x_cgs = np.linspace(0, 1, 11) aeros = np.array([get_aero(xyz_ref=[x, 0, 0]) for x in x_cgs], dtype="O") import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p fig, ax = plt.subplots(figsize=(4, 4)) plt.plot(x_cgs, np.array([a['m_b'] for a in aeros]), ".-") p.show_plot("Fuselage Pitching Moment", r"$x_{cg} / l$", "Pitching Moment [Nm]") """ Expected result: For CG far forward (0), vehicle should have negative pitching moment. For CG far aft (1), vehicle should have positive pitching moment. """
import aerosandbox.numpy as np np.random.seed(0) # Fix a seed for reproducibility ### Create some data (some fictional system where temperature is a function of time, and we're measuring it) n = 20 time = 100 * np.random.rand(n) actual_temperature = 2 * time + 20 # True physics of the system noise = 10 * np.random.randn(n) measured_temperature = actual_temperature + noise # Measured temperature of the system ### Add in a dropout measurement (say, the sensor wire randomly came loose and gave us a 0 reading) time = np.hstack((time, 90)) measured_temperature = np.hstack((measured_temperature, 0)) if __name__ == '__main__': from aerosandbox.tools.pretty_plots import plt, sns, mpl, show_plot fig, ax = plt.subplots() plt.plot(time, measured_temperature, ".") show_plot(xlabel="Time", ylabel="Measured Temperature")
speeds_plot = fit({ "lats_scaled": (Lats_plot.flatten() - 37.5) / 11.5, "alts_scaled": (Alts_plot.flatten() - 24200) / 24200, }) * 56 + 7 Speeds_plot = speeds_plot.reshape( len(alts_plot), len(lats_plot), ) ax.plot_surface( Lats_plot, Alts_plot / 1e3, Speeds_plot, cmap=plt.cm.viridis, edgecolors=(1, 1, 1, 0.5), linewidth=0.5, alpha=0.7, rcount=40, ccount=40, shade=True, ) ax.view_init(38, -130) ax.set_xlabel("Latitude [deg. N]") ax.set_ylabel("Altitude [km]") ax.set_zlabel("Wind Speed [m/s]") plt.title("99th-Percentile Wind Speeds\nContinental U.S., August, 1979-2020") plt.legend() plt.subplots_adjust(bottom=0.055, left=0, right=1, top=0.90) show_plot(tight_layout=False)
"trans_str": 10, "cd_sub": 1.2, "cd_sup": 1.2, "a_sub": -0.4, "a_sup": -0.4, "s_sub": 4.6, "s_sup": -1.5, }, parameter_bounds={ "s_sub": (0, None), "s_sup": (None, 0), # "cd_sub": (1.2, 1.2), "trans": (0.9, 1.1), "trans_str": (0, None), }, weights=1 + 5 * ((data[:, 0] > 0.9) & (data[:, 0] < 1.1)), verbose=False, # residual_norm_type="LInf", put_residuals_in_logspace=True) from pprint import pprint pprint(fit.parameters) mach = np.linspace(0, 5, 1000) plt.plot(mach, fit(mach), "-k", label="Fit") plt.ylim(1, 2.5) p.show_plot("Mach vs. Cylinder Drag", "Mach [-]", "Cylinder Drag Coefficient $C_d$")
# model=model, # x_data=data[:, 0], # y_data=data[:, 1], # parameter_guesses={ # "cd_0": 0.16, # "pg_hardness": 3, # "pg_power": -0.5, # "cd_offset": 0, # }, # parameter_bounds={ # # "pg_hardness": (1, None), # "pg_power": (None, 0), # # "cd_offset": (-1, 1), # }, # # residual_norm_type="L1", # verbose=False # ) from pprint import pprint pprint(fit.parameters) mach = np.linspace(0, 5, 1000) plt.plot(mach, fit(mach), "-k", label="Fitted Model\nfor AeroBuildup") plt.ylim(0, 0.2) p.set_ticks(0.5, 0.1, 0.05, 0.01) p.show_plot("Fuselage Base Drag Coefficient", "Mach [-]", "Fuselage Base Drag Coefficient [-]")
if __name__ == '__main__': import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p np.random.seed(0) ### Generate data x = np.linspace(0, 10, 101) y_true = np.abs(x - 5) # np.sin(x) y_noisy = y_true + 0.1 * np.random.randn(len(x)) ### Plot spline regression fig, ax = plt.subplots(dpi=300) x_fit, y_bootstrap_fits = plot_with_bootstrapped_uncertainty( x, y_noisy, y_stdev=0.1, label_line="Best Estimate", label_data="Data", label_ci="95% CI", ) ax.plot(x, y_true, "k", label="True Function", alpha=0.2) p.show_plot( "Spline Bootstrapping Test", r"$x$", r"$y$", )
1, probably around 0.5? Certainly no more than 0.6, I imagine. (intuition) """ return 1 - (p["a"] / (fr + p["b"]))**p["c"] fit = asb.FittedModel(model=model, x_data=np.concatenate([sub[:, 0], sup[:, 0]]), y_data=np.concatenate([sub[:, 1], sup[:, 1]]), weights=np.concatenate([ np.ones(len(sub)) / len(sub), np.ones(len(sup)) / len(sup), ]), parameter_guesses={ "a": 0.5, "b": 3, "c": 1, }, parameter_bounds={ "a": (0, None), "b": (0, None), "c": (0, None) }, residual_norm_type="L2") plt.plot(fr, fit(fr), "-k", label="Fit") p.show_plot( "Drag-Divergent Mach Number for Generic\nFuselage of Varying Fineness Ratio", "$2L_n / d$", r"$\mathrm{Mach}_{DD}$ [-]") print(fit.parameters)
plt.plot(alpha, aero["CD"]) plt.xlabel(r"$\alpha$ [deg]") plt.ylabel(r"$C_D$") set_ticks(5, 1, 0.05, 0.01) plt.ylim(bottom=0) plt.sca(ax[1, 0]) plt.plot(alpha, aero["Cm"]) plt.xlabel(r"$\alpha$ [deg]") plt.ylabel(r"$C_m$") set_ticks(5, 1, 0.5, 0.1) plt.sca(ax[1, 1]) plt.plot(alpha, aero["CL"] / aero["CD"]) plt.xlabel(r"$\alpha$ [deg]") plt.ylabel(r"$C_L/C_D$") set_ticks(5, 1, 10, 2) show_plot("`asb.AeroBuildup` Aircraft Aerodynamics") fig, ax = plt.subplots(figsize=(7, 6)) Beta, Alpha = np.meshgrid(np.linspace(-90, 90, 200), np.linspace(-90, 90, 200)) aero = AeroBuildup( airplane=airplane, op_point=OperatingPoint(velocity=10, alpha=Alpha, beta=Beta), ).run() contour(Beta, Alpha, aero["CL"], levels=30) equal() show_plot("AeroBuildup", r"$\beta$ [deg]", r"$\alpha$ [deg]")
import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p fuselage = asb.Fuselage(xsecs=[ asb.FuselageXSec(xyz_c=[xi, 0, 0], radius=asb.Airfoil("naca0010").local_thickness(xi)) for xi in np.cosspace(0, 1, 20) ], ) fig, ax = plt.subplots(figsize=(7, 6)) Beta, Alpha = np.meshgrid(np.linspace(-90, 90, 500), np.linspace(-90, 90, 500)) aero = asb.AeroBuildup(airplane=asb.Airplane(fuselages=[fuselage]), op_point=asb.OperatingPoint( velocity=10, alpha=Alpha, beta=Beta, )).run() from aerosandbox.tools.string_formatting import eng_string p.contour( Beta, Alpha, aero["L"], colorbar_label="Lift $L$ [N]", # levels=100, linelabels_format=lambda s: eng_string(s, unit="N"), cmap=plt.get_cmap("coolwarm")) p.equal() p.show_plot("3D Fuselage Lift", r"$\beta$ [deg]", r"$\alpha$ [deg]")
) * d_ue_dx, # From AVF Eq. 4.51 ) opti.subject_to( logint(theta / H_star) * d_H_star_dx == int(2 * c_D / H_star - c_f / 2) + logint( (H - 1) * theta / ue ) * d_ue_dx ) ### Add initial conditions opti.subject_to([ theta[0] == theta_0, H[0] == H_0 # Equilibrium value ]) ### Solve sol = opti.solve() theta = sol.value(theta) H = sol.value(H) ### Plot from aerosandbox.tools.pretty_plots import plt, show_plot fig, ax = plt.subplots() plt.plot(x, theta) show_plot(r"$\theta$", "$x$", r"$\theta$") fig, ax = plt.subplots() plt.plot(x, H) show_plot("$H$", "$x$", "$H$")
if __name__ == "__main__": # Make AeroSandbox Atmosphere altitude = np.linspace(-5e3, 100e3, 1000) atmo_diff = Atmosphere(altitude=altitude) atmo_isa = Atmosphere(altitude=altitude, method="isa") from aerosandbox.tools.pretty_plots import plt, sns, mpl, show_plot, set_ticks fig, ax = plt.subplots() plt.plot( ((atmo_diff.pressure() - atmo_isa.pressure()) / atmo_isa.pressure()) * 100, altitude / 1e3, ) set_ticks(0.2, 0.1, 20, 10) plt.xlim(-1, 1) show_plot("AeroSandbox Atmosphere vs. ISA Atmosphere", "Pressure, Relative Error [%]", "Altitude [km]") fig, ax = plt.subplots() plt.plot( atmo_diff.temperature() - atmo_isa.temperature(), altitude / 1e3, ) set_ticks(1, 0.5, 20, 10) plt.xlim(-5, 5) show_plot("AeroSandbox Atmosphere vs. ISA Atmosphere", "Temperature, Absolute Error [K]", "Altitude [km]")
from aerosandbox.tools.pretty_plots import plt, show_plot, equal vars_to_plot = { **dyn.state, "alpha" : dyn.alpha, "beta" : dyn.beta, "speed" : dyn.speed, "altitude": dyn.altitude, "CL" : aero["CL"], "CY" : aero["CY"], "CD" : aero["CD"], "Cl" : aero["Cl"], "Cm" : aero["Cm"], "Cn" : aero["Cn"], } fig, axes = plt.subplots(6, 4, figsize=(15, 10), sharex=True) for var_to_plot, ax in zip(vars_to_plot.items(), axes.flatten(order="F")): plt.sca(ax) k, v = var_to_plot plt.plot(dyn.time, v) plt.ylabel(k) show_plot() fig, ax = plt.subplots() plt.plot(dyn.xe, dyn.altitude, "k") sc = plt.scatter(dyn.xe, dyn.altitude, c=dyn.speed, cmap=plt.get_cmap("rainbow"), zorder=4) plt.axis('equal') plt.colorbar(label="Airspeed [m/s]") show_plot("Trajectory using `asb.AeroBuildup` Flight Dynamics", "$x_e$", "$-z_e$")
def simulate( self, t_eval, t_span=(0, 60), initial_position=0, initial_velocity=0, ): res = integrate.solve_ivp( fun=self.equations_of_motion, t_span=t_span, y0=np.array([initial_position, initial_velocity]), t_eval=t_eval, ) return res.y if __name__ == '__main__': bike = Bike() from aerosandbox.tools.pretty_plots import plt, show_plot, set_ticks fig, ax = plt.subplots() t = np.linspace(0, 60, 500) pos, vel = bike.simulate(t) plt.plot(t, vel * 2.24) set_ticks(2, 1, 4, 2) plt.xlim(0, 20) plt.ylim(0, 36) show_plot("Electric Bike", xlabel="Time [s]", ylabel="Speed [mph]")
x = 'mach' y = 'CM' for analysis, data in datas.items(): plt.plot( data[x], data[y], "-", label=analysis, # linewidth=1, # markersize=3, alpha=0.8) # plt.xlim(left=0) # plt.ylim(bottom=0) # plt.xlim(0.7, 0.95) # plt.xlim(0.6, 0.8) # plt.ylim(0, 1) # plt.xlim(0, 1) # plt.ylim(0, 0.02) # p.set_ticks(0.1, 0.02) p.show_plot( "Comparison of Aerodynamic Analysis Methods\nRAE2822 Airfoil, AoA=1 deg, Re=6.5M", x, y, savefig="C:/Users/peter/Downloads/figs/moment.png")
def model(x, p): return 1 - p["1scl"] / (x - p["1cen"]) - (p["2scl"] / (x - p["2cen"]))**2 fit = asb.FittedModel(model=model, x_data=fineness, y_data=eta, parameter_guesses={ "1scl": 1, "1cen": -25, "2scl": -1, "2cen": -25, }, parameter_bounds={ "1scl": (0, None), "1cen": (None, 0), "2scl": (0, None), "2cen": (None, 0), }, residual_norm_type="L2", verbose=False) print(fit.parameters) from aerosandbox.tools.pretty_plots import plt, show_plot fig, ax = plt.subplots() plt.plot(fineness, eta, ".k") fineness_plot = np.linspace(0, 40, 500) plt.plot(fineness_plot, fit(fineness_plot), "-") show_plot(r"$\eta$ Fitting", "Fineness Ratio", r"$\eta$")
mach = np.linspace(0., 2, 10000) drag = drag(mach) ddragdm = np.gradient(drag, np.diff(mach)[0]) dddragdm = np.gradient(ddragdm, np.diff(mach)[0]) plt.sca(ax[0]) plt.title("$C_D$") plt.ylabel("$C_{D, wave} / C_{D, wave, M=1.2}$") plt.plot(mach, drag) plt.ylim(-0.05, 1.5) # plt.ylim(-0.01, 0.05) plt.sca(ax[1]) plt.title("$d(C_D)/d(M)$") plt.ylabel(r"$\frac{d(C_{D, wave})}{dM}$") plt.plot(mach, ddragdm) plt.ylim(-5, 15) plt.sca(ax[2]) plt.title("$d^2(C_D)/d(M)^2$") plt.ylabel(r"$\frac{d^2(C_{D, wave})}{dM^2}$") plt.plot(mach, dddragdm) # plt.ylim(-5, 15) for a in ax: plt.sca(a) plt.xlim(0.5, 1.5) plt.xlabel("Mach [-]") p.show_plot()
import aerosandbox.tools.pretty_plots as p fuselage = asb.Fuselage(xsecs=[ asb.FuselageXSec(xyz_c=[xi, 0, 0], radius=asb.Airfoil("naca0020").local_thickness(xi) / 2) for xi in np.cosspace(0, 1, 20) ], ) fig, ax = plt.subplots(figsize=(7, 6)) V = np.linspace(10, 1000, 1001) op_point = asb.OperatingPoint(velocity=V, ) aero = asb.AeroBuildup( airplane=asb.Airplane(fuselages=[fuselage]), op_point=op_point, ).run() plt.plot(op_point.mach(), aero["CD"], label="Full Model") aero = asb.AeroBuildup(airplane=asb.Airplane(fuselages=[fuselage]), op_point=op_point, include_wave_drag=False).run() plt.plot(op_point.mach(), aero["CD"], zorder=1.9, label="Model without Wave Drag") p.show_plot("Transonic Fuselage Drag", "Mach [-]", "Drag Area $C_D \cdot A$ [m$^2$]") print("%.4g" % aero["CD"][-1])
CD = af.CD_function(Alpha.flatten(), Re.flatten()).reshape(Alpha.shape) CM = af.CM_function(Alpha.flatten(), Re.flatten()).reshape(Alpha.shape) ##### Plot alpha-Re contours from aerosandbox.tools.pretty_plots import plt, show_plot, contour fig, ax = plt.subplots() contour(Alpha, Re, CL, levels=30, colorbar_label=r"$C_L$") plt.scatter(af.xfoil_data["alpha"], af.xfoil_data["Re"], color="k", alpha=0.2) plt.yscale('log') show_plot( f"Auto-generated Polar for {af.name} Airfoil", "Angle of Attack [deg]", "Reynolds Number [-]", ) fig, ax = plt.subplots() contour(Alpha, Re, CD, levels=30, colorbar_label=r"$C_D$", z_log_scale=True) plt.scatter(af.xfoil_data["alpha"], af.xfoil_data["Re"], color="k", alpha=0.2) plt.yscale('log')
import os, sys from pathlib import Path this_dir = Path(__file__).parent sys.path.insert(0, str(this_dir.parent)) from bike import Bike import aerosandbox.numpy as np from aerosandbox.tools.pretty_plots import plt, show_plot, set_ticks fig, ax = plt.subplots() t = np.linspace(0, 10, 500) gear_ratios = np.geomspace(0.020 / 0.700, 0.700 / 0.700, 10) colors = plt.cm.get_cmap('rainbow')(np.linspace(0, 1, len(gear_ratios))) for i, gear_ratio in enumerate(gear_ratios): pos, vel = Bike(gear_ratio=gear_ratio).simulate(t) plt.plot( t, vel * 2.24, label=f"{gear_ratio:.2f}", color=colors[i], ) set_ticks(1, 0.5, 5, 1) show_plot("Electric Bike: Gear Ratios", xlabel="Time [s]", ylabel="Speed [mph]")
def tangent( x_over_L: np.ndarray, ): return haack_series( x_over_L=x_over_L, C=2 / 3 ) if __name__ == '__main__': import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p fig, ax = plt.subplots() x_over_L = np.cosspace(0, 1, 2000) FR = 3 plt.plot(x_over_L * FR, karman(x_over_L), label="$C=0$ (LD-Haack, Karman)") plt.plot(x_over_L * FR, LV_haack(x_over_L), label="$C=1/3$ (LV-Haack)") plt.plot(x_over_L * FR, tangent(x_over_L), label="$C=2/3$ (Tangent)") p.equal() p.show_plot( f"Nosecone Haack Series\nFineness Ratio $FR = {FR}$", "Length $x$", "Radius $r$" )
from scipy import optimize speed = 24 / 2.24 fig, ax = plt.subplots() t = np.linspace(0, 10, 500) gear_ratios = np.geomspace(0.020 / 0.700, 0.700 / 0.700, 300) def get_efficiency(gear_ratio): bike = Bike(gear_ratio=gear_ratio) try: perf = bike.steady_state_performance(speed=speed) except ValueError: return np.NaN return perf['motor state']['efficiency'] eff = np.array([get_efficiency(gear_ratio) for gear_ratio in gear_ratios]) plt.plot(gear_ratios, eff * 100) plt.xlim(gear_ratios[0], gear_ratios[-1]) plt.ylim(0, 100) # plt.xscale('log') set_ticks(x_major=0.1, x_minor=0.025, y_major=10, y_minor=2.5) show_plot(f"Electric Bike: Gear Ratios at {speed * 2.24:.0f} mph", xlabel="Gear Ratio", ylabel=f"Efficiency [%]")