Пример #1
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)

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

        plt.gca().set_aspect('equal', adjustable='box')
        plt.xlabel(r"$x/c$")
        plt.ylabel(r"$y/c$")
        plt.title(rf"Inviscid Airfoil: Flow Field")
        plt.tight_layout()
        if show:
            plt.show()
Пример #2
0
    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)
Пример #3
0
def test_interpn_fill_value():
    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])

    value = np.interpn(
        points, values, point,
        method="bspline",
        bounds_error=False,
        fill_value=-17
    )
    assert value == pytest.approx(-17)

    value = np.interpn(
        points, values, point,
        method="bspline",
        bounds_error=False,
    )
    assert np.isnan(value)

    value = np.interpn(
        points, values, point,
        method="bspline",
        bounds_error=None,
        fill_value=None
    )
    assert value == pytest.approx(value_func_3d(5, 3.12, 1.15))
Пример #4
0
def test_interpn_bounds_error_multiple_samples():
    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, 5.81, 2.43]
    ])
    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
        )
Пример #5
0
    def plot(self, resolution=250):

        def axis_range(x_data_axis: np.ndarray) -> Tuple[float, float]:
            """
            Given the entries of one axis of the dependent variable, determine a min/max range over which to plot the fit.
            Args:
                x_data_axis: The entries of one axis of the dependent variable, i.e. x_data["x1"].

            Returns: A tuple representing the (min, max) value over which to plot that axis.
            """
            minval = np.min(x_data_axis)
            maxval = np.max(x_data_axis)

            return (minval, maxval)

        if self.input_dimensionality() == 1:

            ### Parse the x_data
            if self.input_names() is not None:
                x_name = self.x_data.keys()[0]
                x_data = self.x_data.values()[0]

                minval, maxval = axis_range(x_data)

                x_fit = {x_name: np.linspace(minval, maxval, resolution)}
                y_fit = self(x_fit)
            else:
                x_name = "x"
                x_data = self.x_data

                minval, maxval = axis_range(x_data)

                x_fit = np.linspace(minval, maxval, resolution)
                y_fit = self(x_fit)

            ### Plot the 2D figure
            fig = plt.figure(dpi=200)
            plt.plot(
                x_data,
                self.y_data,
                ".k",
                label="Data",
            )
            plt.plot(
                x_fit,
                y_fit,
                "-",
                color="#cb3bff",
                label="Fit",
                zorder=4,
            )
            plt.xlabel(x_name)
            plt.ylabel(rf"$f({x_name})$")
            plt.title(r"Fit of FittedModel")
            plt.tight_layout()
            plt.legend()
            plt.show()

        else:
            raise NotImplementedError()
Пример #6
0
    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",
        )
Пример #7
0
def test_opti_hanging_chain_with_callback(plot=False):
    N = 40
    m = 40 / N
    D = 70 * N
    g = 9.81
    L = 1

    opti = asb.Opti()

    x = opti.variable(init_guess=np.linspace(-2, 2, N))
    y = opti.variable(
        init_guess=1,
        n_vars=N,
    )

    distance = np.sqrt(  # Distance from one node to the next
        np.diff(x)**2 + np.diff(y)**2)

    potential_energy_spring = 0.5 * D * np.sum((distance - L / N)**2)
    potential_energy_gravity = g * m * np.sum(y)
    potential_energy = potential_energy_spring + potential_energy_gravity

    opti.minimize(potential_energy)

    # Add end point constraints
    opti.subject_to([x[0] == -2, y[0] == 1, x[-1] == 2, y[-1] == 1])

    # Add a ground constraint
    opti.subject_to(y >= np.cos(0.1 * x) - 0.5)

    # Add a callback

    if plot:

        def my_callback(iter: int):
            plt.plot(opti.debug.value(x),
                     opti.debug.value(y),
                     ".-",
                     label=f"Iter {iter}",
                     zorder=3 + iter)

        fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)
        x_ground = np.linspace(-2, 2, N)
        y_ground = np.cos(0.1 * x_ground) - 0.5
        plt.plot(x_ground, y_ground, "--k", zorder=2)

    else:

        def my_callback(iter: int):
            print(f"Iter {iter}")
            print(f"\tx = {opti.debug.value(x)}")
            print(f"\ty = {opti.debug.value(y)}")

    sol = opti.solve(callback=my_callback)

    assert sol.value(potential_energy) == pytest.approx(626.462, abs=1e-3)

    if plot:
        plt.show()
Пример #8
0
def test_quadcopter_navigation():
    opti = asb.Opti()

    N = 300
    time_final = 1
    time = np.linspace(0, time_final, N)

    left_thrust = opti.variable(init_guess=0.5, scale=1, n_vars=N, lower_bound=0, upper_bound=1)
    right_thrust = opti.variable(init_guess=0.5, scale=1, n_vars=N, lower_bound=0, upper_bound=1)

    mass = 0.1

    dyn = asb.FreeBodyDynamics(
        opti_to_add_constraints_to=opti,
        time=time,
        xe=opti.variable(init_guess=np.linspace(0, 1, N)),
        ze=opti.variable(init_guess=np.linspace(0, -1, N)),
        u=opti.variable(init_guess=0, n_vars=N),
        w=opti.variable(init_guess=0, n_vars=N),
        theta=opti.variable(init_guess=np.linspace(np.pi / 2, np.pi / 2, N)),
        q=opti.variable(init_guess=0, n_vars=N),
        X=left_thrust + right_thrust,
        M=(right_thrust - left_thrust) * 0.1 / 2,
        mass=mass,
        Iyy=0.5 * mass * 0.1 ** 2,
        g=9.81,
    )

    opti.subject_to([  # Starting state
        dyn.xe[0] == 0,
        dyn.ze[0] == 0,
        dyn.u[0] == 0,
        dyn.w[0] == 0,
        dyn.theta[0] == np.radians(90),
        dyn.q[0] == 0,
    ])

    opti.subject_to([  # Final state
        dyn.xe[-1] == 1,
        dyn.ze[-1] == -1,
        dyn.u[-1] == 0,
        dyn.w[-1] == 0,
        dyn.theta[-1] == np.radians(90),
        dyn.q[-1] == 0,
    ])

    effort = np.sum(  # The average "effort per second", where effort is integrated as follows:
        np.trapz(left_thrust ** 2 + right_thrust ** 2) * np.diff(time)
    ) / time_final

    opti.minimize(effort)

    sol = opti.solve()
    dyn.substitute_solution(sol)

    assert sol.value(effort) == pytest.approx(0.714563, rel=0.01)

    print(sol.value(effort))
Пример #9
0
def test_block_move_fixed_time():
    opti = asb.Opti()

    n_timesteps = 300

    time = np.linspace(0, 1, n_timesteps)

    dyn = asb.DynamicsPointMass1DHorizontal(
        mass_props=asb.MassProperties(mass=1),
        x_e=opti.variable(init_guess=np.linspace(0, 1, n_timesteps)),
        u_e=opti.variable(init_guess=1, n_vars=n_timesteps),
    )

    u = opti.variable(init_guess=np.linspace(1, -1, n_timesteps))

    dyn.add_force(
        Fx=u
    )

    dyn.constrain_derivatives(
        opti=opti,
        time=time
    )

    opti.subject_to([
        dyn.x_e[0] == 0,
        dyn.x_e[-1] == 1,
        dyn.u_e[0] == 0,
        dyn.u_e[-1] == 0,
    ])

    # effort = np.sum(
    #     np.trapz(dyn.X ** 2) * np.diff(time)
    # )

    effort = np.sum(  # More sophisticated integral-of-squares integration (closed form correct)
        np.diff(time) / 3 *
        (u[:-1] ** 2 + u[:-1] * u[1:] + u[1:] ** 2)
    )

    opti.minimize(effort)

    sol = opti.solve()

    dyn.substitute_solution(sol)

    assert dyn.x_e[0] == pytest.approx(0)
    assert dyn.x_e[-1] == pytest.approx(1)
    assert dyn.u_e[0] == pytest.approx(0)
    assert dyn.u_e[-1] == pytest.approx(0)
    assert np.max(dyn.u_e) == pytest.approx(1.5, abs=0.01)
    assert sol.value(u)[0] == pytest.approx(6, abs=0.05)
    assert sol.value(u)[-1] == pytest.approx(-6, abs=0.05)
Пример #10
0
def test_quadcopter_flip():
    opti = asb.Opti()

    N = 300
    time_final = opti.variable(init_guess=1, lower_bound=0)
    time = np.linspace(0, time_final, N)

    left_thrust = opti.variable(init_guess=0.7, scale=1, n_vars=N, lower_bound=0, upper_bound=1)
    right_thrust = opti.variable(init_guess=0.6, scale=1, n_vars=N, lower_bound=0, upper_bound=1)

    mass = 0.1

    dyn = asb.FreeBodyDynamics(
        opti_to_add_constraints_to=opti,
        time=time,
        xe=opti.variable(init_guess=np.linspace(0, 1, N)),
        ze=opti.variable(init_guess=0, n_vars=N),
        u=opti.variable(init_guess=0, n_vars=N),
        w=opti.variable(init_guess=0, n_vars=N),
        theta=opti.variable(init_guess=np.linspace(np.pi / 2, np.pi / 2 - 2 * np.pi, N)),
        q=opti.variable(init_guess=0, n_vars=N),
        X=left_thrust + right_thrust,
        M=(right_thrust - left_thrust) * 0.1 / 2,
        mass=mass,
        Iyy=0.5 * mass * 0.1 ** 2,
        g=9.81,
    )

    opti.subject_to([  # Starting state
        dyn.xe[0] == 0,
        dyn.ze[0] == 0,
        dyn.u[0] == 0,
        dyn.w[0] == 0,
        dyn.theta[0] == np.radians(90),
        dyn.q[0] == 0,
    ])

    opti.subject_to([  # Final state
        dyn.xe[-1] == 1,
        dyn.ze[-1] == 0,
        dyn.u[-1] == 0,
        dyn.w[-1] == 0,
        dyn.theta[-1] == np.radians(90 - 360),
        dyn.q[-1] == 0,
    ])

    opti.minimize(time_final)

    sol = opti.solve(verbose=False)
    dyn.substitute_solution(sol)

    assert sol.value(time_final) == pytest.approx(0.824, abs=0.01)
Пример #11
0
def test_block_move_minimum_time():
    opti = asb.Opti()

    n_timesteps = 300

    time = np.linspace(
        0,
        opti.variable(init_guess=1, lower_bound=0),
        n_timesteps,
    )

    dyn = asb.DynamicsPointMass1DHorizontal(
        mass_props=asb.MassProperties(mass=1),
        x_e=opti.variable(init_guess=np.linspace(0, 1, n_timesteps)),
        u_e=opti.variable(init_guess=1, n_vars=n_timesteps),
    )

    u = opti.variable(init_guess=np.linspace(1, -1, n_timesteps), lower_bound=-1, upper_bound=1)

    dyn.add_force(
        Fx=u
    )

    dyn.constrain_derivatives(
        opti=opti,
        time=time
    )

    opti.subject_to([
        dyn.x_e[0] == 0,
        dyn.x_e[-1] == 1,
        dyn.u_e[0] == 0,
        dyn.u_e[-1] == 0,
    ])

    opti.minimize(
        time[-1]
    )

    sol = opti.solve()

    dyn.substitute_solution(sol)

    assert dyn.x_e[0] == pytest.approx(0)
    assert dyn.x_e[-1] == pytest.approx(1)
    assert dyn.u_e[0] == pytest.approx(0)
    assert dyn.u_e[-1] == pytest.approx(0)
    assert np.max(dyn.u_e) == pytest.approx(1, abs=0.01)
    assert sol.value(u)[0] == pytest.approx(1, abs=0.05)
    assert sol.value(u)[-1] == pytest.approx(-1, abs=0.05)
    assert np.mean(np.abs(sol.value(u))) == pytest.approx(1, abs=0.01)
Пример #12
0
    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",
        )
Пример #13
0
def test_fit_model_weighting():
    x = np.linspace(0, 10)
    y = np.sin(x)

    fm = FittedModel(
        model=lambda x, p: p["m"] * x + p["b"],
        x_data=x,
        y_data=y,
        parameter_guesses={
            "m": 0,
            "b": 0,
        },
        weights=None
    )  # Fit a model with no weighting

    assert fm(10) != pytest.approx(5, abs=1) # Doesn't give a high value at x = 10

    fm = FittedModel(
        model=lambda x, p: p["m"] * x + p["b"],
        x_data=x,
        y_data=y,
        parameter_guesses={
            "m": 0,
            "b": 0,
        },
        weights=(x > 0) & (x < 2)
    )  # Fit a model with weighting

    assert fm(10) == pytest.approx(5, abs=1) # Gives a high value at x = 10

    fm.plot()
Пример #14
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),
    )
def test_rosenbrock_constrained(plot=False):
    opti = asb.Opti()

    x = opti.variable(init_guess=0)
    y = opti.variable(init_guess=0)
    r = opti.parameter()

    f = (1 - x)**2 + (y - x**2)**2
    opti.minimize(f)
    con = x**2 + y**2 <= r
    dual = opti.subject_to(con)

    r_values = np.linspace(1, 3)

    sols = [opti.solve({r: r_value}) for r_value in r_values]
    fs = [sol.value(f) for sol in sols]
    duals = [
        sol.value(dual)  # Ensure the dual can be evaluated
        for sol in sols
    ]

    if plot:
        fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)
        plt.plot(r_values, fs, label="$f$")
        plt.plot(r_values, duals, label=r"Dual var. ($\frac{df}{dr}$)")
        plt.legend()
        plt.xlabel("$r$")
        plt.show()

    assert dual is not None  # The dual should be a real value
    assert r_values[0] == pytest.approx(1)
    assert duals[0] == pytest.approx(0.10898760051521068, abs=1e-6)
Пример #16
0
def test_Linf_without_x_in_dict():
    np.random.seed(0)  # Set a seed for repeatability

    ### Making data
    hour = np.linspace(1, 10, 100)
    noise = 0.1 * np.random.randn(len(hour))
    temperature_c = np.log(hour) + noise

    ### Fit
    def model(x, p):
        return p["m"] * x + p["b"]

    x_data = hour
    y_data = temperature_c

    fitted_model = FittedModel(
        model=model,
        x_data=x_data,
        y_data=y_data,
        parameter_guesses={
            "m": 0,
            "b": 0,
        },
        residual_norm_type="Linf",
    )

    # Check that the fit is right
    assert fitted_model.parameters["m"] == pytest.approx(0.247116, abs=1e-5)
    assert fitted_model.parameters["b"] == pytest.approx(0.227797, abs=1e-5)
def test_softmax(plot=False):
    # Test softmax
    x = np.linspace(-10, 10, 100)
    y1 = x
    y2 = -2 * x - 3
    hardness = 0.5

    y_soft = np.softmax(y1, y2, hardness=hardness)

    assert np.softmax(0, 0, hardness=1) == np.log(2)

    if plot:
        import matplotlib.pyplot as plt
        import seaborn as sns

        sns.set(font_scale=1)

        fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)
        plt.plot(x, y1, label="y1")
        plt.plot(x, y2, label="y2")
        plt.plot(x, y_soft, label="softmax")
        plt.xlabel(r"x")
        plt.ylabel(r"y")
        plt.title(r"Softmax")
        plt.tight_layout()
        plt.legend()
        plt.show()
Пример #18
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]),
    )
Пример #19
0
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()
Пример #20
0
def interpolated_model():
    np.random.seed(0)  # Set a seed for repeatability.

    ### Make some data
    x = np.linspace(0, 10, 11)

    return InterpolatedModel(
        x_data_coordinates=x,
        y_data_structured=underlying_function_1D(x),
    )
Пример #21
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,)
Пример #22
0
    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 plot_underlying_function():
    import matplotlib.pyplot as plt
    import seaborn as sns
    sns.set(palette=sns.color_palette("husl"))
    x = np.linspace(-10, 10, 500)
    f = underlying_function(x)

    fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)
    plt.plot(x, f)
    plt.title("Underlying Function")
    plt.show()
Пример #24
0
def contour(
        func: Callable,
        x_range: Tuple[Union[float,int],Union[float,int]],
        y_range: Tuple[Union[float,int],Union[float,int]],
        resolution:int =50,
        show:bool=True,  # type: bool
):
    """
    Makes a contour plot of a function of 2 variables. Can also plot a list of functions.
    :param func: function of form f(x,y) to plot.
    :param x_range: Range of x values to plot, expressed as a tuple (x_min, x_max)
    :param y_range: Range of y values to plot, expressed as a tuple (y_min, y_max)
    :param resolution: Resolution in x and y to plot. [int]
    :param show: Should we show the plot?
    :return:
    """
    fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)
    x = np.linspace(x_range[0], x_range[1], resolution)
    y = np.linspace(y_range[0], y_range[1], resolution)
    # TODO finish function
Пример #25
0
def main():
    time = np.linspace(0, 10, 100)  # Time in seconds
    wing_velocity = 2  # Wing horizontal velocity in m/s
    chord = 2
    reduced_time = calculate_reduced_time(
        time, wing_velocity, chord)  # Number of semi chords travelled

    # Visualize the gust profiles as well as the pitch maneuvers
    fig, ax1 = plt.subplots(dpi=300)
    ln1 = ax1.plot(reduced_time,
                   np.array([top_hat_gust(s) for s in reduced_time]),
                   label="Top-Hat Gust",
                   lw=3)
    ln2 = ax1.plot(reduced_time,
                   np.array([sine_squared_gust(s) for s in reduced_time]),
                   label="Sine-Squared Gust",
                   lw=3)
    ax1.set_xlabel("Reduced time")
    ax1.set_ylabel("Velocity (m/s)")
    ax2 = ax1.twinx()
    ln3 = ax2.plot(reduced_time,
                   np.array([gaussian_pitch(s) for s in reduced_time]),
                   label="Guassian Pitch",
                   c="red",
                   ls="--",
                   lw=3)
    ax2.set_ylabel("Angle of Attack, degrees")
    lns = ln1 + ln2 + ln3
    labs = [l.get_label() for l in lns]
    ax2.legend(lns, labs, loc="lower right")
    plt.title("Gust and pitch example profiles")

    total_lift = pitching_through_transverse_gust(reduced_time, top_hat_gust,
                                                  wing_velocity,
                                                  gaussian_pitch)
    gust_lift = calculate_lift_due_to_transverse_gust(reduced_time,
                                                      top_hat_gust,
                                                      wing_velocity,
                                                      gaussian_pitch)
    pitch_lift = calculate_lift_due_to_pitching_profile(
        reduced_time, gaussian_pitch)
    added_mass_lift = added_mass_due_to_pitching(reduced_time, gaussian_pitch)

    # Visualize the different sources of lift
    plt.figure(dpi=300)
    plt.plot(reduced_time, total_lift, label="Total Lift", lw=2)
    plt.plot(reduced_time, gust_lift, label="Gust Lift", lw=2)
    plt.plot(reduced_time, pitch_lift, label="Pitching Lift", lw=2)
    plt.plot(reduced_time, added_mass_lift, label="Added Mass Lift", lw=2)
    plt.legend()
    plt.xlabel("Reduced time")
    plt.ylabel("$C_\ell$")
    plt.title("Guassian Pitch Maneuver Through Top-Hat Gust")
Пример #26
0
    def max_thickness(
        self, x_over_c_sample: np.ndarray = np.linspace(0, 1, 101)) -> float:
        """
        Returns the maximum thickness of the airfoil.

        Args:
            x_over_c_sample: Where should the airfoil be sampled to determine the max thickness?

        Returns: The maximum thickness, as a fraction of chord.

        """
        return np.max(self.local_thickness(x_over_c=x_over_c_sample))
Пример #27
0
    def draw(self, draw_mcl=True, backend="matplotlib", show=True):
        """
        Draw the airfoil object.
        :param draw_mcl: Should we draw the mean camber line (MCL)? [boolean]
        :param backend: Which backend should we use? "plotly" or "matplotlib"
        :return: None
        """
        x = np.array(self.x()).reshape(-1)
        y = np.array(self.y()).reshape(-1)
        if draw_mcl:
            x_mcl = np.linspace(np.min(x), np.max(x), len(x))
            y_mcl = self.local_camber(x_mcl)

        if backend == "matplotlib":
            color = '#280887'
            plt.plot(x, y, ".-", zorder=11, color=color)
            plt.fill(x, y, zorder=10, color=color, alpha=0.2)
            if draw_mcl:
                plt.plot(x_mcl, y_mcl, "-", zorder=4, color=color, alpha=0.4)
            plt.axis("equal")
            plt.xlabel(r"$x/c$")
            plt.ylabel(r"$y/c$")
            plt.title(f"{self.name} Airfoil")
            plt.tight_layout()
            if show:
                plt.show()

        elif backend == "plotly":
            from aerosandbox.visualization.plotly import go
            fig = go.Figure()
            fig.add_trace(
                go.Scatter(x=x,
                           y=y,
                           mode="lines+markers",
                           name="Airfoil",
                           fill="toself",
                           line=dict(color="blue")), )
            if draw_mcl:
                fig.add_trace(
                    go.Scatter(x=x_mcl,
                               y=y_mcl,
                               mode="lines+markers",
                               name="Mean Camber Line (MCL)",
                               line=dict(color="navy")))
            fig.update_layout(xaxis_title="x/c",
                              yaxis_title="y/c",
                              yaxis=dict(scaleanchor="x", scaleratio=1),
                              title=f"{self.name} Airfoil")
            if show:
                fig.show()
            else:
                return fig
Пример #28
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))
Пример #29
0
def test_diff_atmosphere():
    altitudes = np.linspace(-50e2, 150e3, 1000)
    atmo_isa = Atmosphere(altitude=altitudes, method='isa')
    atmo_diff = Atmosphere(altitude=altitudes)
    temp_isa = atmo_isa.temperature()
    pressure_isa = atmo_isa.pressure()
    temp_diff = atmo_diff.temperature()
    pressure_diff = atmo_diff.pressure()
    assert max(abs(
        (temp_isa - temp_diff) /
        temp_isa)) < 0.025, "temperature failed for differentiable model"
    assert max(abs(
        (pressure_isa - pressure_diff) /
        pressure_isa)) < 0.01, "pressure failed for differentiable model"
Пример #30
0
 def draw(self, draw_mcl=True, backend="plotly", show=True):
     """
     Draw the airfoil object.
     :param draw_mcl: Should we draw the mean camber line (MCL)? [boolean]
     :param backend: Which backend should we use? "plotly" or "matplotlib"
     :return: None
     """
     x = np.array(self.x()).reshape(-1)
     y = np.array(self.y()).reshape(-1)
     if draw_mcl:
         x_mcl = np.linspace(np.min(x), np.max(x), len(x))
         y_mcl = self.local_camber(x_mcl)
     if backend == "plotly":
         fig = go.Figure()
         fig.add_trace(
             go.Scatter(x=x,
                        y=y,
                        mode="lines+markers",
                        name="Airfoil",
                        fill="toself",
                        line=dict(color="blue")), )
         if draw_mcl:
             fig.add_trace(
                 go.Scatter(x=x_mcl,
                            y=y_mcl,
                            mode="lines+markers",
                            name="Mean Camber Line (MCL)",
                            line=dict(color="navy")))
         fig.update_layout(xaxis_title="x/c",
                           yaxis_title="y/c",
                           yaxis=dict(scaleanchor="x", scaleratio=1),
                           title="%s Airfoil" % self.name)
         if show:
             fig.show()
         else:
             return fig
     elif backend == "matplotlib":
         fig, ax = plt.subplots(1, 1, figsize=(6.4, 4.8), dpi=200)
         plt.plot(x, y, ".-", zorder=11, color='#280887')
         if draw_mcl:
             plt.plot(x_mcl, y_mcl, "-", zorder=4, color='#28088744')
         plt.axis("equal")
         plt.xlabel(r"$x/c$")
         plt.ylabel(r"$y/c$")
         plt.title("%s Airfoil" % self.name)
         plt.tight_layout()
         if show:
             plt.show()
         else:
             return fig, ax