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 test_uniform_forward_difference_first_degree(): assert np.finite_difference_coefficients( x=np.arange(2), x0=0, derivative_degree=1) == pytest.approx(np.array([-1, 1])) assert np.finite_difference_coefficients( x=np.arange(9), x0=0, derivative_degree=1) == pytest.approx( np.array([ -761 / 280, 8, -14, 56 / 3, -35 / 2, 56 / 5, -14 / 3, 8 / 7, -1 / 8 ]))
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 spy( matrix, show=True, ): """ Plots the sparsity pattern of a matrix. :param matrix: The matrix to plot the sparsity pattern of. [2D ndarray or CasADi array] :param show: Whether or not to show the sparsity plot. [boolean] :return: The figure to be plotted [go.Figure] """ try: matrix = matrix.toarray() except: pass abs_m = np.abs(matrix) sparsity_pattern = abs_m >= 1e-16 matrix[sparsity_pattern] = np.log10(abs_m[sparsity_pattern] + 1e-16) j_index_map, i_index_map = np.meshgrid(np.arange(matrix.shape[1]), np.arange(matrix.shape[0])) i_index = i_index_map[sparsity_pattern] j_index = j_index_map[sparsity_pattern] val = matrix[sparsity_pattern] val = np.ones_like(i_index) fig = go.Figure( data=go.Heatmap( y=i_index, x=j_index, z=val, # type='heatmap', colorscale='RdBu', showscale=False, ), ) fig.update_layout( plot_bgcolor="black", xaxis=dict(showgrid=False, zeroline=False), yaxis=dict(showgrid=False, zeroline=False, autorange="reversed", scaleanchor="x", scaleratio=1), width=800, height=800 * (matrix.shape[0] / matrix.shape[1]), ) if show: fig.show() return fig
def shape(w, x): # Class function C = x**N1 * (1 - x)**N2 # Shape function (Bernstein polynomials) n = len(w) - 1 # Order of Bernstein polynomials K = comb(n, np.arange(n + 1)) # Bernstein polynomial coefficients S_matrix = (w * K * np.expand_dims(x, 1)**np.arange(n + 1) * np.expand_dims(1 - x, 1)**(n - np.arange(n + 1)) ) # Polynomial coefficient * weight matrix S = np.sum(S_matrix, axis=1) # Calculate y output y = C * S return y
def test_norm_2D(): a = np.arange(9).reshape(3, 3) cas_a = cas.DM(a) assert np.linalg.norm(cas_a) == np.linalg.norm(a) assert np.all(np.linalg.norm(cas_a, axis=0) == np.linalg.norm(a, axis=0)) assert np.all(np.linalg.norm(cas_a, axis=1) == np.linalg.norm(a, axis=1))
def test_rocket_control_problem(plot=False): ### Constants T = 100 d = 50 delta = 1e-3 f = 1000 c = np.ones(T) ### Optimization opti = asb.Opti() # set up an optimization environment x = opti.variable(init_guess=np.linspace(0, d, T)) # position v = opti.variable(init_guess=d / T, n_vars=T) # velocity a = opti.variable(init_guess=0, n_vars=T) # acceleration gamma = opti.variable(init_guess=0, n_vars=T) # instantaneous fuel consumption a_max = opti.variable(init_guess=0) # maximum acceleration opti.subject_to([ cas.diff(x) == v[:-1], # physics cas.diff(v) == a[:-1], # physics x[0] == 0, # boundary condition v[0] == 0, # boundary condition x[-1] == d, # boundary condition v[-1] == 0, # boundary condition gamma >= c * a, # lower bound on instantaneous fuel consumption gamma >= -c * a, # lower bound on instantaneous fuel consumption cas.sum1(gamma) <= f, # fuel consumption limit cas.diff(a) <= delta, # jerk limits cas.diff(a) >= -delta, # jerk limits a_max >= a, # lower bound on maximum acceleration a_max >= -a, # lower bound on maximum acceleration ]) opti.minimize(a_max) # minimize the peak acceleration sol = opti.solve() # solve assert sol.value(a_max) == pytest.approx( 0.02181991952, rel=1e-3) # solved externally with Julia JuMP if plot: import matplotlib.pyplot as plt import seaborn as sns sns.set(palette=sns.color_palette("husl")) fig, ax = plt.subplots(1, 1, figsize=(8, 6), dpi=200) for i, val, lab in zip(np.arange(3), [x, v, a], ["$x$", "$v$", "$a$"]): plt.subplot(3, 1, i + 1) plt.plot(sol.value(val), label=lab) plt.xlabel(r"Time [s]") plt.ylabel(lab) plt.legend() plt.suptitle(r"Rocket Trajectory") plt.tight_layout() plt.show()
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", )
def test_concatenate(): n = np.arange(10) c = cas.DM(n) assert concatenate((n, n)).shape == (20, ) assert concatenate((n, c)).shape == (20, 1) assert concatenate((c, n)).shape == (20, 1) assert concatenate((c, c)).shape == (20, 1) assert concatenate((n, n, n)).shape == (30, ) assert concatenate((c, c, c)).shape == (30, 1)
def test_stack(): n = np.arange(10) c = cas.DM(n) assert stack((n, n)).shape == (2, 10) assert stack((n, n), axis=-1).shape == (10, 2) assert stack((n, c)).shape == (2, 10) assert stack((n, c), axis=-1).shape == (10, 2) assert stack((c, c)).shape == (2, 10) assert stack((c, c), axis=-1).shape == (10, 2) with pytest.raises(Exception): assert stack((n, n), axis=2) with pytest.raises(Exception): stack((c, c), axis=2)
def test_interp(): x_np = np.arange(5) y_np = x_np + 10 for x, y in zip( [x_np, x_np], [y_np, cas.DM(y_np)] ): assert np.interp(0, x, y) == pytest.approx(10) assert np.interp(4, x, y) == pytest.approx(14) assert np.interp(0.5, x, y) == pytest.approx(10.5) assert np.interp(-1, x, y) == pytest.approx(10) assert np.interp(5, x, y) == pytest.approx(14) assert np.interp(-1, x, y, left=-10) == pytest.approx(-10) assert np.interp(5, x, y, right=-10) == pytest.approx(-10) assert np.interp(5, x, y, period=4) == pytest.approx(11)
def add_quad( self, points, intensity=0, outline=True, mirror=False, ): """ Adds a quadrilateral face to draw. All points should be (approximately) coplanar if you want it to look right. :param points: an iterable with 4 items. Each item is a 3D point, represented as an iterable of length 3. Points should be given in sequential order. :param intensity: Intensity associated with this face :param outline: Do you want to outline this quad? [boolean] :param mirror: Should we also draw a version that's mirrored over the XZ plane? [boolean] :return: None E.g. add_face([(0, 0, 0), (1, 0, 0), (0, 1, 0)]) """ if not len(points) == 4: raise ValueError("'points' must have exactly 4 items!") for p in points: self.x_face.append(float(p[0])) self.y_face.append(float(p[1])) self.z_face.append(float(p[2])) self.intensity_face.append(intensity) indices_added = np.arange(len(self.x_face) - 4, len(self.x_face)) self.i_face.append(indices_added[0]) self.j_face.append(indices_added[1]) self.k_face.append(indices_added[2]) self.i_face.append(indices_added[0]) self.j_face.append(indices_added[2]) self.k_face.append(indices_added[3]) if outline: self.add_line(list(points) + [points[0]]) if mirror: reflected_points = [ reflect_over_XZ_plane(point) for point in points ] self.add_quad(points=reflected_points, intensity=intensity, outline=outline, mirror=False)
def add_tri( self, points, intensity=0, outline=False, mirror=False, ): """ Adds a triangular face to draw. :param points: an iterable with 3 items. Each item is a 3D point, represented as an iterable of length 3. :param intensity: Intensity associated with this face :param outline: Do you want to outline this triangle? [boolean] :param mirror: Should we also draw a version that's mirrored over the XZ plane? [boolean] :return: None E.g. add_face([(0, 0, 0), (1, 0, 0), (0, 1, 0)]) """ if not len(points) == 3: raise ValueError("'points' must have exactly 3 items!") for p in points: self.x_face.append(float(p[0])) self.y_face.append(float(p[1])) self.z_face.append(float(p[2])) self.intensity_face.append(intensity) indices_added = np.arange(len(self.x_face) - 3, len(self.x_face)) self.i_face.append(indices_added[0]) self.j_face.append(indices_added[1]) self.k_face.append(indices_added[2]) if outline: self.add_line(list(points) + [points[0]]) if mirror: reflected_points = [ reflect_over_XZ_plane(point) for point in points ] self.add_tri(points=reflected_points, intensity=intensity, outline=outline, mirror=False)
Args: power: Power of MPPT [watts] Returns: Estimated MPPT mass [kg] """ constant = 0.066343 exponent = 0.515140 return constant * power ** exponent if __name__ == "__main__": # Run some checks latitudes = np.linspace(26, 49, 200) day_of_years = np.arange(0, 365) + 1 times = np.linspace(0, 86400, 400) # Times, Latitudes = np.meshgrid(times, latitudes, indexing="ij") # fluxes = np.array(solar_flux_on_horizontal(Latitudes, 244, Times)) # fig = go.Figure( # data=[ # go.Surface( # x=Times / 3600, # y=Latitudes, # z=fluxes, # ) # ], # ) # fig.update_layout( # scene=dict(
def test_uniform_forward_difference_higher_order(): assert np.finite_difference_coefficients( x=np.arange(5), x0=0, derivative_degree=3) == pytest.approx( np.array([-5 / 2, 9, -12, 7, -3 / 2]))
def test_sum(): a = np.arange(101) assert np.sum(a) == 5050 # Gauss would be proud.
output = {k: v[sort_order] for k, v in output.items()} return output return self._run_xfoil("\n".join([f"a {a}" for a in alphas])) def cl(self, cl: Union[float, np.ndarray]) -> Dict[str, np.ndarray]: """ Execute XFoil at a given lift coefficient, or at a sequence of lift coefficients. Args: cl: The lift coefficient [-]. Can be either a float or an iterable of floats, such as an array. Returns: A dictionary with the XFoil results. Dictionary values are arrays; they may not be the same shape as your input array if some points did not converge. """ cls = np.array(cl).reshape(-1) return self._run_xfoil("\n".join([f"cl {c}" for c in cls])) if __name__ == '__main__': xf = XFoil( airfoil=Airfoil("naca2412").repanel(n_points_per_side=100), Re=1e6, ) # result_at_single_alpha = xf.alpha(5) # result_at_several_CLs = xf.cl([0.5, 0.7, 0.8, 0.9]) # result_at_multiple_alphas = xf.alpha([3, 5, 60]) # Note: if a result does xf.alpha(np.arange(-5, 5))
error = np.sum((y_model - y_data)**2) abs_coeffs = opti.variable(init_guess=np.zeros(degree + 1)) opti.subject_to([abs_coeffs > coeffs, abs_coeffs > -coeffs]) opti.minimize(error + 1e-4 * np.sum(abs_coeffs)) sol = opti.solve(verbose=False) if __name__ == '__main__': import matplotlib.pyplot as plt import seaborn as sns sns.set(palette=sns.color_palette("husl")) fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200) x_plot = np.linspace(x[0], x[-1], 100) vandermonde_plot = np.ones((len(x_plot), degree + 1)) for j in range(1, degree + 1): vandermonde_plot[:, j] = vandermonde_plot[:, j - 1] * x_plot y_plot = vandermonde_plot @ sol.value(coeffs) plt.plot(x, y_data, ".") plt.plot(x_plot, sol.value(y_plot), "-") plt.show() fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200) plt.bar(x=np.arange(degree + 1), height=sol.value(coeffs)) plt.show()
if __name__ == '__main__': n, coeffs = branch_and_bound(obj, lower_bound, branch, init, term, eta, guess) print(n, coeffs) import matplotlib.pyplot as plt import seaborn as sns sns.set(palette=sns.color_palette("husl")) fig, ax = plt.subplots(1, 1, figsize=(3, 2), dpi=200) x_plot = np.linspace(x[0], x[-1], 100) # vandermonde_plot = np.ones((len(x_plot), degree + 1)) # for j in range(1, degree + 1): # vandermonde_plot[:, j] = vandermonde_plot[:, j - 1] * x_plot y_plot = make_matrix(x_plot) @ (coeffs * n).T x_extrapolate = np.linspace(x[0], x[-1] + 10, 100) y_extrapolate = make_matrix(x_extrapolate) @ (coeffs * n).T plt.plot(x, y_data, ".") plt.plot(x_plot, y_plot, "-") # plt.plot(x_extrapolate, f(x_extrapolate)) # plt.plot(x_extrapolate, y_extrapolate) plt.show() fig, ax = plt.subplots(1, 1, figsize=(3, 2), dpi=200) plt.bar(x=np.arange(degree + 1), height=coeffs) plt.show()
def test_trapz(): a = np.arange(100) assert np.diff(np.trapz(a)) == pytest.approx(1)
def test_cumsum(): n = np.arange(6).reshape((3, 2)) c = cas.DM(n) assert np.all(np.cumsum(n) == np.array([0, 1, 3, 6, 10, 15]))
import aerosandbox.numpy as np # import matplotlib.pyplot as plt # import aerosandbox.tools.pretty_plots as p from tqdm import tqdm # p.mpl.use('WebAgg') # fig, ax = plt.subplots(figsize=(6.4, 4.8), dpi=150) airfoil = asb.Airfoil("rae2822") Re = 6.5e6 alpha = 1 machs = np.concatenate([ np.arange(0.1, 0.5, 0.05), np.arange(0.5, 0.6, 0.01), np.arange(0.6, 0.8, 0.003), ]) # # ##### XFoil v6 # xfoil6 = {} # for mach in tqdm(machs[machs < 1], desc="XFoil 6"): # xfoil6[mach] = asb.XFoil( # airfoil=airfoil, # Re=Re, # mach=mach, # # verbose=True, # ).alpha(alpha) # xfoil6_Cds = {k: v['CD'] for k, v in xfoil6.items() if len(v['CD']) != 0} #
def test_diff(): a = np.arange(100) assert np.all(np.diff(a) == pytest.approx(1))
def test_invertability_of_diff_trapz(): a = np.sin(np.arange(10)) assert np.all(np.trapz(np.diff(a)) == pytest.approx(np.diff(np.trapz(a))))
from aerosandbox.geometry.common import reflect_over_XZ_plane import aerosandbox.numpy as np import pytest import casadi as cas vec = np.arange(3) square = np.arange(9).reshape((3, 3)) rectangular_tall = np.arange(12).reshape((4, 3)) rectangular_wide = np.arange(12).reshape((3, 4)) def test_np_vector(): assert np.all( reflect_over_XZ_plane(vec) == np.array([0, -1, 2]) ) def test_cas_vector(): output = reflect_over_XZ_plane(cas.DM(vec)) assert isinstance(output, cas.DM) assert np.all( output == np.array([0, -1, 2]) ) def test_np_vector_2D_wide(): assert np.all( reflect_over_XZ_plane(np.expand_dims(vec, 0)) == np.array([0, -1, 2])
"fill_value": fill_value, **interpolated_model_kwargs } super().__init__( x_data_coordinates=x_data_coordinates, y_data_structured=y_data_structured, **interpolated_model_kwargs, ) self.x_data_raw_unstructured = x_data self.y_data_raw = y_data if __name__ == '__main__': x = np.arange(10) y = x ** 3 interp = UnstructuredInterpolatedModel( x_data=x, y_data=y ) def randspace(start, stop, n=50): vals = (stop - start) * np.random.rand(n) + start vals = np.concatenate((vals[:-2], np.array([start, stop]))) # vals = np.sort(vals) return vals np.random.seed(4)
def test_np_3D(): with pytest.raises(ValueError): reflect_over_XZ_plane(np.arange(2 * 3 * 4).reshape(2, 3, 4))
def _run_xfoil( self, run_command: str, ) -> Dict[str, np.ndarray]: """ Private function to run XFoil. Args: run_command: A string with any XFoil keystroke inputs that you'd like. By default, you start off within the OPER menu. All of the inputs indicated in the constructor have been set already, but you can override them here (for this run only) if you want. Returns: A dictionary containing all converged solutions obtained with your inputs. """ # Set up a temporary directory with tempfile.TemporaryDirectory() as directory: directory = Path(directory) ### Alternatively, work in another directory: if self.working_directory is not None: directory = Path(self.working_directory) # For debugging # Designate an intermediate file for file I/O output_filename = "output.txt" # Handle the airfoil file airfoil_file = "airfoil.dat" self.airfoil.write_dat(directory / airfoil_file) # Handle the keystroke file keystroke_file_contents = self._default_keystroke_file_contents() keystroke_file_contents += [run_command] keystroke_file_contents += [ "pwrt", f"{output_filename}", "y", "", "quit" ] keystroke_file = "keystroke_file.txt" with open(directory / keystroke_file, "w+") as f: f.write("\n".join(keystroke_file_contents)) ### Set up the run command command = f'{self.xfoil_command} {airfoil_file} < {keystroke_file}' ### Execute subprocess.call( command, shell=True, cwd=directory, stdout=None if self.verbose else subprocess.DEVNULL) ### Parse the polar columns = [ "alpha", "CL", "CD", "CDp", "CM", "xtr_upper", "xtr_lower" ] with warnings.catch_warnings(): warnings.simplefilter("ignore") output_data = np.genfromtxt( directory / output_filename, skip_header=12, usecols=np.arange(len(columns))).reshape(-1, len(columns)) has_valid_inputs = len(output_data) != 0 return { k: output_data[:, index] if has_valid_inputs else np.array([]) for index, k in enumerate(columns) }
if __name__ == '__main__': from pathlib import Path from pprint import pprint ms = MSES( airfoil=Airfoil("rae2822"), # .repanel(n_points_per_side=30), working_directory="/mnt/c/Users/peter/Downloads/msestest/", # max_iter=120, verbosity=1, behavior_after_unconverged_run="terminate", mset_n=300, max_iter=100, # verbose=False ) res = ms.run( alpha=3, mach=np.arange(0.55, 0.8, 0.005), # Re=1e6, ) pprint(res) import matplotlib matplotlib.use("WebAgg") import matplotlib.pyplot as plt import aerosandbox.tools.pretty_plots as p fig, ax = plt.subplots() plt.plot(res['mach'], res['CD'], ".-") p.show_plot()