コード例 #1
0
ファイル: winds.py プロジェクト: peterdsharpe/AeroSandbox
    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",
        )
コード例 #2
0
def interpolated_model():
    np.random.seed(0)  # Set a seed for repeatability.

    ### Make some data
    x1 = np.linspace(0, 10, 11)
    x2 = np.linspace(0, 10, 21)

    X1, X2 = np.meshgrid(x1, x2, indexing="ij")

    return InterpolatedModel(
        x_data_coordinates={
            "x1": x1,
            "x2": x2,
        },
        y_data_structured=underlying_function_2D(X1, X2),
    )
コード例 #3
0
ファイル: winds.py プロジェクト: peterdsharpe/AeroSandbox
    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",
        )
コード例 #4
0
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
コード例 #5
0
def test_calculate_induced_velocity_panel_coordinates():
    X, Y = np.meshgrid(
        np.linspace(-1, 2, 50),
        np.linspace(-1, 1, 50),
        indexing='ij',
    )
    X = X.flatten()
    Y = Y.flatten()

    U, V = calculate_induced_velocity_line_singularities(
        x_field=X,
        y_field=Y,
        x_panels=np.array([-0.5, 1.5]),
        y_panels=np.array([0, 0]),
        gamma=np.array([1, 1]),
        sigma=np.array([1, 1]),
    )
コード例 #6
0
def test_multidimensional_power_law_fitting():
    np.random.seed(0)  # Set a seed for repeatability.

    ### Make some data z(x,y)
    x = np.logspace(0, 3)
    y = np.logspace(0, 3)
    X, Y = np.meshgrid(x, y, indexing="ij")
    noise = np.random.lognormal(mean=0, sigma=0.05)
    Z = 0.5 * X**0.75 * Y**1.25 * noise

    ### Fit data
    def model(x, p):
        return (p["multiplier"] * x["X"]**p["X_power"] * x["Y"]**p["Y_power"])

    x_data = {
        "X": X.flatten(),
        "Y": Y.flatten(),
    }

    fitted_model = FittedModel(
        model=model,
        x_data=x_data,
        y_data=Z.flatten(),
        parameter_guesses={
            "multiplier": 1,
            "X_power": 1,
            "Y_power": 1,
        },
        parameter_bounds={
            "multiplier": (None, None),
            "X_power": (None, None),
            "Y_power": (None, None),
        },
        put_residuals_in_logspace=True
        # Putting residuals in logspace minimizes the norm of log-error instead of absolute error
    )

    ### Check that the fit is right
    assert fitted_model.parameters["multiplier"] == pytest.approx(0.546105,
                                                                  abs=1e-3)
    assert fitted_model.parameters["X_power"] == pytest.approx(0.750000,
                                                               abs=1e-3)
    assert fitted_model.parameters["Y_power"] == pytest.approx(1.250000,
                                                               abs=1e-3)
コード例 #7
0
ファイル: winds.py プロジェクト: peterdsharpe/AeroSandbox
    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",
        )
コード例 #8
0
def test_interpn_linear_multiple_samples():
    ### NumPy test

    def value_func_3d(x, y, z):
        return 2 * x + 3 * y - z

    x = np.linspace(0, 5, 10)
    y = np.linspace(0, 5, 20)
    z = np.linspace(0, 5, 30)
    points = (x, y, z)
    values = value_func_3d(*np.meshgrid(*points, indexing="ij"))

    point = np.array([
        [2.21, 3.12, 1.15],
        [3.42, 0.81, 2.43]
    ])
    value = np.interpn(
        points, values, point
    )
    assert np.all(
        value == pytest.approx(
            value_func_3d(
                *[
                    point[:, i] for i in range(point.shape[1])
                ]
            )
        )
    )
    assert len(value) == 2

    ### CasADi test
    point = cas.DM(point)
    value = np.interpn(
        points, values, point
    )
    value_actual = value_func_3d(
        *[
            np.array(point[:, i]) for i in range(point.shape[1])
        ]
    )
    for i in range(len(value)):
        assert value[i] == pytest.approx(float(value_actual[i]))
    assert value.shape == (2,)
コード例 #9
0
def test_interpn_bspline_casadi():
    """
    The bspline method should interpolate seperable cubic multidimensional polynomials exactly.
    """

    def func(x, y, z):  # Sphere function
        return x ** 3 + y ** 3 + z ** 3

    x = np.linspace(-5, 5, 10)
    y = np.linspace(-5, 5, 20)
    z = np.linspace(-5, 5, 30)
    points = (x, y, z)
    values = func(
        *np.meshgrid(*points, indexing="ij")
    )

    point = np.array([0.4, 0.5, 0.6])
    value = np.interpn(
        points, values, point, method="bspline"
    )

    assert value == pytest.approx(func(*point))
コード例 #10
0
def test_interpn_bounds_error_one_sample():
    def value_func_3d(x, y, z):
        return 2 * x + 3 * y - z

    x = np.linspace(0, 5, 10)
    y = np.linspace(0, 5, 20)
    z = np.linspace(0, 5, 30)
    points = (x, y, z)
    values = value_func_3d(*np.meshgrid(*points, indexing="ij"))

    point = np.array([5.21, 3.12, 1.15])
    with pytest.raises(ValueError):
        value = np.interpn(
            points, values, point
        )

    ### CasADi test
    point = cas.DM(point)
    with pytest.raises(ValueError):
        value = np.interpn(
            points, values, point
        )
コード例 #11
0
def test_interpn_linear():
    ### NumPy test

    def value_func_3d(x, y, z):
        return 2 * x + 3 * y - z

    x = np.linspace(0, 5, 10)
    y = np.linspace(0, 5, 20)
    z = np.linspace(0, 5, 30)
    points = (x, y, z)
    values = value_func_3d(*np.meshgrid(*points, indexing="ij"))

    point = np.array([2.21, 3.12, 1.15])
    value = np.interpn(
        points, values, point
    )
    assert value == pytest.approx(value_func_3d(*point))

    ### CasADi test
    point = cas.DM(point)
    value = np.interpn(
        points, values, point
    )
    assert value == pytest.approx(float(value_func_3d(point[0], point[1], point[2])))
コード例 #12
0
        x_left=-1,
        y_left=-1,
        z_left=0,
        x_right=-1,
        y_right=1,
        z_right=0,
        gamma=1,
    )
    print(u, v, w)

    ##### Plot grid of single vortex
    args = (-2, 2, 30)
    x = np.linspace(*args)
    y = np.linspace(*args)
    z = np.linspace(*args)
    X, Y, Z = np.meshgrid(x, y, z)

    Xf = X.flatten()
    Yf = Y.flatten()
    Zf = Z.flatten()

    left = [0, -1, 0]
    right = [0, 1, 0]

    Uf, Vf, Wf = calculate_induced_velocity_horseshoe(
        x_field=Xf,
        y_field=Yf,
        z_field=Zf,
        x_left=left[0],
        y_left=left[1],
        z_left=left[2],
コード例 #13
0
    def __init__(self,
                 x_data: Union[np.ndarray, Dict[str, np.ndarray]],
                 y_data: np.ndarray,
                 x_data_resample: Union[int, Dict[str, Union[int, np.ndarray]]] = 10,
                 resampling_interpolator: object = interpolate.RBFInterpolator,
                 resampling_interpolator_kwargs: Dict[str, Any] = None,
                 fill_value=np.NaN,  # Default behavior: return NaN for all inputs outside data range.
                 interpolated_model_kwargs: Dict[str, Any] = None,
                 ):
        """
        Creates the interpolator. Note that data must be unstructured (i.e., point cloud) for general N-dimensional
        interpolation.

        Note that if data is either 1D or structured,

        Args:

            x_data: Values of the dependent variable(s) in the dataset to be fitted. This is a dictionary; syntax is {
            var_name:var_data}.

                * If the model is one-dimensional (e.g. f(x1) instead of f(x1, x2, x3...)), you can instead supply x_data
                as a 1D ndarray. (If you do this, just treat `x` as an array in your model, not a dict.)

            y_data: Values of the independent variable in the dataset to be fitted. [1D ndarray of length n]

            x_data_resample: A parameter that guides how the x_data should be resampled onto a structured grid.

                * If this is an int, we look at each axis of the `x_data` (here, we'll call this `xi`),
                and we resample onto a linearly-spaced grid between `min(xi)` and `max(xi)` with `x_data_resample`
                points.

                * If this is a dict, it must be a dict where the keys are strings matching the keys of (the
                dictionary) `x_data`. The values can either be ints or 1D np.ndarrays.

                    * If the values are ints, then that axis is linearly spaced between `min(xi)` and `max(xi)` with
                    `x_data_resample` points.

                    * If the values are 1D np.ndarrays, then those 1D np.ndarrays are used as the resampled spacing
                    for the given axis.

            resampling_interpolator: Indicates the interpolator to use in order to resample the unstructured data
            onto a structured grid. Should be analogous to scipy.interpolate.RBFInterpolator in __init__ and __call__
            syntax. See reference here:

                * https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.RBFInterpolator.html

            resampling_interpolator_kwargs: Indicates keyword arguments (keyword-value pairs, as a dictionary) to
            pass into the resampling interpolator.

            fill_value: Gives the value that the interpolator should return for points outside of the interpolation
            domain. The interpolation domain is defined as the hypercube bounded by the coordinates specified in
            `x_data_resample`. By default, these coordinates are the tightest axis-aligned hypercube that bounds the
            point cloud data. If fill_value is None, then the interpolator will attempt to extrapolate if the interpolation method allows.

            interpolated_model_kwargs: Indicates keyword arguments to pass into the (structured) InterpolatedModel.
            Also a dictionary. See aerosandbox.InterpolatedModel for documentation on possible inputs here.

        """
        if resampling_interpolator_kwargs is None:
            resampling_interpolator_kwargs = {}
        if interpolated_model_kwargs is None:
            interpolated_model_kwargs = {}

        try:  # Try to use the InterpolatedModel initializer. If it doesn't work, then move on.
            super().__init__(
                x_data_coordinates=x_data,
                y_data_structured=y_data,
            )
            return
        except ValueError:
            pass

        # If it didn't work, this implies that x_data is multidimensional, and hence a dict-like object. Validate this.
        try:  # Determine type of `x_data`
            x_data.keys()
            x_data.values()
            x_data.items()
        except AttributeError:
            raise TypeError("`x_data` must be a dict-like object!")

        # Make the interpolator, based on x_data and y_data.
        if resampling_interpolator == interpolate.RBFInterpolator:
            resampling_interpolator_kwargs = {
                "kernel": "thin_plate_spline",
                "degree": 1,
                **resampling_interpolator_kwargs
            }

        interpolator = resampling_interpolator(
            y=np.stack(tuple(x_data.values()), axis=1),
            d=y_data,
            **resampling_interpolator_kwargs
        )

        # If x_data_resample is an int, make it into a dict that matches x_data.
        if isinstance(x_data_resample, int):
            x_data_resample = {
                k: x_data_resample
                for k in x_data.keys()
            }

        # Now, x_data_resample should be dict-like. Validate this.
        try:
            x_data_resample.keys()
            x_data_resample.values()
            x_data_resample.items()
        except AttributeError:
            raise TypeError("`x_data_resample` must be a dict-like object!")

        # Go through x_data_resample, and replace any values that are ints with linspaced arrays.
        for k, v in x_data_resample.items():
            if isinstance(v, int):
                x_data_resample[k] = np.linspace(
                    np.min(x_data[k]),
                    np.max(x_data[k]),
                    v
                )

        x_data_coordinates: Dict = x_data_resample

        x_data_structured_values = [
            xi.flatten()
            for xi in np.meshgrid(*x_data_coordinates.values(), indexing="ij")
        ]
        x_data_structured = {
            k: xi
            for k, xi in zip(x_data.keys(), x_data_structured_values)
        }

        y_data_structured = interpolator(
            np.stack(tuple(x_data_structured_values), axis=1)
        )
        y_data_structured = y_data_structured.reshape([
            np.length(xi)
            for xi in x_data_coordinates.values()
        ])

        interpolated_model_kwargs = {
            "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
コード例 #14
0
import aerosandbox as asb
import aerosandbox.numpy as np

if __name__ == '__main__':
    af = asb.Airfoil("dae11")
    af.generate_polars()

    alpha = np.linspace(-40, 40, 300)
    re = np.geomspace(1e4, 1e12, 100)
    Alpha, Re = np.meshgrid(alpha, re)
    af.CL_function(alpha=0, Re=1e6)

    CL = af.CL_function(Alpha.flatten(), Re.flatten()).reshape(Alpha.shape)
    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 [-]",
    )
コード例 #15
0
    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]")
コード例 #16
0
            sigma_end=sigma[i + 1],
        )
        if i == 0:
            u_field = u
            v_field = v
        else:
            u_field += u
            v_field += v

    return u_field, v_field


if __name__ == '__main__':

    X, Y = np.meshgrid(
        np.linspace(-2, 2, 50),
        np.linspace(-2, 2, 50),
    )
    X = X.flatten()
    Y = Y.flatten()

    x_panels = np.array([1, -1, -1, 1, 1])
    y_panels = np.array([1, 1, -1, -1, 1])

    U, V = calculate_induced_velocity_line_singularities(
        x_field=X,
        y_field=Y,
        x_panels=x_panels,
        y_panels=y_panels,
        gamma=1 * np.ones_like(x_panels),
        sigma=1 * np.ones_like(x_panels))
コード例 #17
0
        )
        if i == 0:
            u_field = u
            v_field = v
        else:
            u_field += u
            v_field += v

    return u_field, v_field


if __name__ == '__main__':

    X, Y = np.meshgrid(
        np.linspace(-1, 1, 50),
        np.linspace(-1, 1, 50),
        indexing='ij',
    )
    X = X.flatten()
    Y = Y.flatten()

    U, V = calculate_induced_velocity_line_singularities(
        x_field=X,
        y_field=Y,
        x_panels=np.array([-0.5, 0.5, 0.5, -0.5, -0.5]),
        y_panels=np.array([-0.5, -0.5, 0.5, 0.5, -0.5]),
        gamma=np.array([0, 0, 0, 0, 0]),
        sigma=np.array([1, 1, 1, 1, 1]))

    import matplotlib.pyplot as plt
    import seaborn as sns
コード例 #18
0
    def __init__(self,
                 x_data_coordinates: Union[np.ndarray, Dict[str, np.ndarray]],
                 y_data_structured: np.ndarray,
                 method: str = "bspline",
                 fill_value=np.NaN,  # Default behavior: return NaN for all inputs outside data range.
                 ):
        """
        Create the interpolator. Note that data must be structured (i.e., gridded on a hypercube) for general
        N-dimensional interpolation.

        Args:
            x_data_coordinates: The coordinates of each axis of the cube; essentially, the independent variable(s):

                * For the general N-dimensional case, this should be a dictionary where the keys are axis names [str]
                and the values are 1D arrays.

                * For the 1D case, you can optionally alternatively supply this as a single 1D array.

            Usage example for how you might generate this data, along with `y_data_structured`:

            >>> x1 = np.linspace(0, 5, 11)
            >>> x2 = np.linspace(0, 10, 21)
            >>> X1, X2 = np.meshgrid(x1, x2, indexing="ij")
            >>>
            >>> x_data_coordinates = {
            >>>     "x1": x1, # 1D ndarray of length 11
            >>>     "x2": x2, # 1D ndarray of length 21
            >>> }
            >>> y_data_structured = function_to_approximate(X1, X2) # 2D ndarray of shape (11, 21)

            y_data_structured: The dependent variable, expressed as a structured data "cube":

                * For the general N-dimensional case, this should be a single N-dimensional array with axis lengths
                corresponding to the inputs in `x_data_coordinates`. In the 1-dimensional case, this naturally
                reduces down to a single 1D ndarray.

                See usage example along with `x_data_coordinates` above.

            method: The method of interpolation to perform. Options:

                * "bspline" (Note: differentiable and suitable for optimization - made of piecewise-cubics. For other
                applications, other interpolators may be faster. Not monotonicity-preserving - may overshoot. Watch
                out for Runge's phenomenon; on that note, if your data is noisy, consider smoothing it first.)

                * "linear" (Note: differentiable, but not suitable for use in optimization w/o subgradient treatment due
                to C1-discontinuity)

                * "nearest" (Note: NOT differentiable, don't use in optimization. Fast.)

            fill_value: Gives the value that the interpolator should return for points outside of the interpolation
            domain. The interpolation domain is defined as the hypercube bounded by the coordinates specified in
            `x_data_coordinates`. If fill_value is None, then the interpolator will attempt to extrapolate if the interpolation method allows.

        """
        try:
            x_data_coordinates_values = x_data_coordinates.values()
        except AttributeError:  # If x_data_coordinates is not a dict
            x_data_coordinates_values = tuple([x_data_coordinates])

        ### Validate inputs
        for coordinates in x_data_coordinates_values:
            if len(coordinates.shape) != 1:
                raise ValueError("""
                    `x_data_coordinates` must be either: 
                        * In the general N-dimensional case, a dict where values are 1D ndarrays defining the coordinates of each axis.
                        * In the 1D case, can also be a 1D ndarray.
                    """)
        implied_y_data_shape = tuple(len(coordinates) for coordinates in x_data_coordinates_values)
        if not y_data_structured.shape == implied_y_data_shape:
            raise ValueError(f"""
            The shape of `y_data_structured` should be {implied_y_data_shape}
            """)

        ### Store data
        self.x_data_coordinates = x_data_coordinates
        self.x_data_coordinates_values = x_data_coordinates_values
        self.y_data_structured = y_data_structured
        self.method = method
        self.fill_value = fill_value

        ### Create unstructured versions of the data for plotting, etc.
        x_data = x_data_coordinates
        if isinstance(x_data, dict):
            x_data_values = np.meshgrid(*x_data_coordinates_values, indexing="ij")
            x_data = {
                k: v.reshape(-1)
                for k, v in zip(x_data_coordinates.keys(), x_data_values)
            }
        self.x_data = x_data
        self.y_data = np.ravel(y_data_structured, order="F")
コード例 #19
0
    interp = UnstructuredInterpolatedModel(
        x_data={
            "x": X.flatten(),
            "y": Y.flatten(),
        },
        y_data=f.flatten()
    )

    from aerosandbox.tools.pretty_plots import plt, show_plot

    fig = plt.figure()
    ax = fig.add_subplot(projection='3d')
    # ax.plot_surface(X, Y, f, color="blue", alpha=0.2)
    ax.scatter(X.flatten(), Y.flatten(), f.flatten())
    X_plot, Y_plot = np.meshgrid(
        np.linspace(X.min(), X.max(), 500),
        np.linspace(Y.min(), Y.max(), 500),
    )
    F_plot = interp({
        "x": X_plot.flatten(),
        "y": Y_plot.flatten()
    }).reshape(X_plot.shape)
    ax.plot_surface(
        X_plot, Y_plot, F_plot,
        color="red",
        edgecolors=(1, 1, 1, 0.5),
        linewidth=0.5,
        alpha=0.2,
        rcount=40,
        ccount=40,
        shade=True,
    )
コード例 #20
0
ファイル: app.py プロジェクト: plotly/dash-sample-apps
def display_graph(n_clicks, alpha, height, streamline_density,
                  operating_checklist, *kulfan_inputs):
    ### Figure out if a button was pressed
    global n_clicks_last
    if n_clicks is None:
        n_clicks = 0

    analyze_button_pressed = n_clicks > n_clicks_last
    n_clicks_last = n_clicks

    ### Parse the checklist
    ground_effect = "ground_effect" in operating_checklist

    ### Start constructing the figure
    airfoil = asb.Airfoil(coordinates=asb.get_kulfan_coordinates(
        lower_weights=np.array(kulfan_inputs[n_kulfan_inputs_per_side:]),
        upper_weights=np.array(kulfan_inputs[:n_kulfan_inputs_per_side]),
        TE_thickness=0,
        enforce_continuous_LE_radius=False,
        n_points_per_side=200,
    ))

    ### Do coordinates output
    coordinates_output = "\n".join(
        ["```"] + ["AeroSandbox Airfoil"] +
        ["\t%f\t%f" % tuple(coordinate)
         for coordinate in airfoil.coordinates] + ["```"])

    ### Continue doing the airfoil things
    airfoil = airfoil.rotate(angle=-np.radians(alpha))
    airfoil = airfoil.translate(0, height + 0.5 * np.sind(alpha))
    fig = go.Figure()
    fig.add_trace(
        go.Scatter(
            x=airfoil.x(),
            y=airfoil.y(),
            mode="lines",
            name="Airfoil",
            fill="toself",
            line=dict(color="blue"),
        ))

    ### Default text output
    text_output = 'Click "Analyze" to compute aerodynamics!'

    xrng = (-0.5, 1.5)
    yrng = (-0.6, 0.6) if not ground_effect else (0, 1.2)

    if analyze_button_pressed:

        analysis = asb.AirfoilInviscid(
            airfoil=airfoil.repanel(50),
            op_point=asb.OperatingPoint(
                velocity=1,
                alpha=0,
            ),
            ground_effect=ground_effect,
        )

        x = np.linspace(*xrng, 100)
        y = np.linspace(*yrng, 100)
        X, Y = np.meshgrid(x, y)
        u, v = analysis.calculate_velocity(x_field=X.flatten(),
                                           y_field=Y.flatten())
        U = u.reshape(X.shape)
        V = v.reshape(Y.shape)

        streamline_fig = ff.create_streamline(
            x,
            y,
            U,
            V,
            arrow_scale=1e-16,
            density=streamline_density,
            line=dict(color="#ff82a3"),
            name="Streamlines",
        )

        fig = go.Figure(data=streamline_fig.data + fig.data)

        text_output = make_table(
            pd.DataFrame({
                "Engineering Quantity": ["C_L"],
                "Value": [f"{analysis.Cl:.3f}"]
            }))

    fig.update_layout(
        xaxis_title="x/c",
        yaxis_title="y/c",
        showlegend=False,
        yaxis=dict(scaleanchor="x", scaleratio=1),
        margin={"t": 0},
        title=None,
    )

    fig.update_xaxes(range=xrng)
    fig.update_yaxes(range=yrng)

    return fig, text_output, [coordinates_output]
コード例 #21
0
    def draw_streamlines(self, res=200, show=True):
        fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)

        plt.xlim(-0.5, 1.5)
        plt.ylim(-0.5, 0.5)
        xrng = np.diff(np.array(ax.get_xlim()))
        yrng = np.diff(np.array(ax.get_ylim()))

        x = np.linspace(*ax.get_xlim(), int(np.round(res * xrng / yrng)))
        y = np.linspace(*ax.get_ylim(), res)

        X, Y = np.meshgrid(x, y)
        shape = X.shape
        X = X.flatten()
        Y = Y.flatten()

        U, V = self.calculate_velocity(X, Y)
        X = X.reshape(shape)
        Y = Y.reshape(shape)
        U = U.reshape(shape)
        V = V.reshape(shape)

        # NaN out any points inside the airfoil
        for airfoil in self.airfoils:
            contains = airfoil.contains_points(X, Y)
            U[contains] = np.NaN
            V[contains] = np.NaN

        speed = (U**2 + V**2)**0.5
        Cp = 1 - speed**2

        ### Draw the airfoils
        for airfoil in self.airfoils:
            plt.fill(airfoil.x(), airfoil.y(), "k", linewidth=0, zorder=4)

        from palettable.colorbrewer.diverging import RdBu_4 as colormap

        plt.streamplot(
            x,
            y,
            U,
            V,
            color=speed,
            density=2.5,
            arrowsize=0,
            cmap=colormap.mpl_colormap,
        )
        CB = plt.colorbar(
            orientation="horizontal",
            shrink=0.8,
            aspect=40,
        )
        CB.set_label(r"Relative Airspeed ($U/U_\infty$)")
        plt.clim(0.4, 1.6)

        plt.gca().set_aspect('equal', adjustable='box')
        plt.xlabel(r"$x/c$")
        plt.ylabel(r"$y/c$")
        plt.title(rf"Invisicid Airfoil: Flow Field")
        plt.tight_layout()
        if show:
            plt.show()
コード例 #22
0
import aerosandbox as asb
import aerosandbox.numpy as np

from scipy import io
from pathlib import Path

root = Path(__file__).parent

# %%

data = io.loadmat(str(root / "data" / "wind_data_99.mat"))
lats_v = data["lats"].flatten()
alts_v = data["alts"].flatten()
speeds = data["speeds"].reshape(len(alts_v), len(lats_v)).T.flatten()

lats, alts = np.meshgrid(lats_v, alts_v, indexing="ij")
lats = lats.flatten()
alts = alts.flatten()

# %%

lats_scaled = (lats - 37.5) / 11.5
alts_scaled = (alts - 24200) / 24200
speeds_scaled = (speeds - 7) / 56

alt_diff = np.diff(alts_v)
alt_diff_aug = np.hstack((alt_diff[0], alt_diff, alt_diff[-1]))
weights_1d = (alt_diff_aug[:-1] + alt_diff_aug[1:]) / 2
weights_1d = weights_1d / np.mean(weights_1d)
# region_of_interest = np.logical_and(
#     alts_v > 10000,