def ode_integrate_rk(fun_rk, x0, time_max, time_step):
    """ Integrate function using Euler method

    - fun: Function df/dt = f(x, t) to integrate
    - x0: Initial state
    - time_tot: Total time to simulate [s]
    - time_step: Time step [s]

    For Runge-Kutta, use:
    solver = ode(fun)
    solver.set_integrator('dopri5')
    solver.set_initial_value(x0, time[0])
    xi = solver.integrate(ti)

    Note that solver.integrate(ti) only integrates for one time step at time ti
    (where ti is the current time), so you will need to use a for loop

    Make sure to use the Result class similarly to the example_integrate
    found above (i.e. Result(x, time))
    """
    time = np.arange(0, time_max, time_step)
    x = np.zeros([len(time), len(x0)])

    solver = ode(fun_rk)
    solver.set_integrator('dopri5')
    solver.set_initial_value(x0, time[0])

    for i, ti in enumerate(time):
        x[i] = solver.integrate(ti)

    return Result(x, time)
Beispiel #2
0
def exercise1(clargs):
    """ Exercise 1 """
    # Setup
    pylog.info("Running exercise 1")

    # Setup
    time_max = 5  # Maximum simulation time
    time_step = 0.2  # Time step for ODE integration in simulation
    x0 = np.array([1.])  # Initial state

    # Integration methods (Exercises 1.a - 1.d)
    pylog.info("Running function integration using different methods")

    # Example
    pylog.debug("Running example plot for integration (remove)")
    example = example_integrate(x0, time_max, time_step)
    example.plot_state(figure="Example", label="Example", marker=".")

    # Analytical (1.a)
    time = np.arange(0, time_max, time_step)  # Time vector
    x_a = analytic_function(time)
    analytical = Result(x_a, time) if x_a is not None else None

    # Euler (1.b)
    euler = euler_integrate(function, x0, time_max, time_step)

    # ODE (1.c)
    ode = ode_integrate(function, x0, time_max, time_step)

    # ODE Runge-Kutta (1.c)
    ode_rk = ode_integrate_rk(function_rk, x0, time_max, time_step)

    # Euler with lower time step (1.d)
    pylog.warning("Euler with smaller ts must be implemented")
    euler_time_step = None
    euler_ts_small = (euler_integrate(function, x0, time_max, euler_time_step)
                      if euler_time_step is not None else None)

    # Plot integration results
    plot_integration_methods(analytical=analytical,
                             euler=euler,
                             ode=ode,
                             ode_rk=ode_rk,
                             euler_ts_small=euler_ts_small,
                             euler_timestep=time_step,
                             euler_timestep_small=euler_time_step)

    # Error analysis (Exercise 1.e)
    pylog.warning("Error analysis must be implemented")

    # Show plots of all results
    if not clargs.save_figures:
        plt.show()
    return
def ode_integrate(fun, x0, time_max, time_step):
    """ Integrate function using Euler method

    - fun: Function df/dt = f(x, t) to integrate
    - x0: Initial state
    - time_tot: Total time to simulate [s]
    - time_step: Time step [s]

    Use odeint from the scipy library for integration

    Make sure to then use the Result class similarly to the example_integrate
    found above (i.e. Result(x, time))
    """
    time = np.arange(0, time_max, time_step)
    x = odeint(fun, x0, time)
    return Result(x, time)
def euler_integrate(fun, x0, time_max, time_step):
    """ Integrate function using Euler method

    - fun: Function df/dt = f(x, t) to integrate
    - x0: Initial state
    - time_tot: Total time to simulate [s]
    - time_step: Time step [s]

    For loop in Python:

    >>> a = [0, 0, 0]  # Same as [0 for _ in range(3)] (List comprehension)
    >>> for i in range(3):
    ...     a[i] = i
    >>> print(a)
    [0, 1, 2]

    Creating a matrix of zeros in python:

    >>> state = np.zeros([3, 2])
    >>> print(state)
    [[0. 0.]
     [0. 0.]
     [0. 0.]]

    For loop for a state in python

    >>> state = np.zeros([3, 2])
    >>> state[0, 0], state[0, 1] = 1, 2
    >>> for i, time in enumerate([0, 0.1, 0.2]):
    ...     state[i, 0] += time
    ...     state[i, 1] -= time
    >>> print(state)
    [[ 1.   2. ]
     [ 0.1 -0.1]
     [ 0.2 -0.2]]

    Make sure to use the Result class similarly to the example_integrate
    found above (i.e. Result(x, time))
    """
    time = np.arange(0, time_max, time_step)
    x = np.zeros([len(time), len(x0)])

    x[0] = x0
    for i, ti in enumerate(time[:-1]):
        x[i + 1] = x[i] + fun(x[i], ti) * time_step

    return Result(x, time)
def example_integrate(x0, time_max, time_step):
    """ Example to show how to use Python

    Note that the Result class takes x and time as input, and is used to
    facilitate the plotting of the results, where x and time are lists or
    arrays

    Additionally, using:

    r = Result(x, t)

    You can then use r.state or r.time to extract the original x and t

    You can then plot the state in function of time with:
    r.plot_state(figure="Name of figure")
    """
    time = np.arange(0, time_max, time_step)
    x = np.zeros([len(time), len(x0)])
    for i, ti in enumerate(time[:-1]):
        x[i + 1] = x[i] + 1e-2 * ti
    # for i in range(len(time[:-1])):  # Also possible
    #     x[i+1] = x[i] + 0.2
    return Result(x, time)
Beispiel #6
0
def exercise1(clargs):
    """ Exercise 1 """
    # Setup
    pylog.info("Running exercise 1")

    # Setup
    time_max = 5  # Maximum simulation time
    time_step = 0.2  # Time step for ODE integration in simulation
    x0 = np.array([1.])  # Initial state

    # Integration methods (Exercises 1.a - 1.d)
    pylog.info("Running function integration using different methods")

    # Analytical (1.a)
    time = np.arange(0, time_max, time_step)  # Time vector
    x_a = analytic_function(time)
    analytical = Result(x_a, time) if x_a is not None else None

    # Euler (1.b)
    euler = euler_integrate(function, x0, time_max, time_step)
    error(euler.state, analytical.state, "Euler")

    # ODE (1.c)
    ode = ode_integrate(function, x0, time_max, time_step)
    error(ode.state, analytical.state, "LSODA")

    # ODE Runge-Kutta (1.c)
    ode_rk = ode_integrate_rk(function_rk, x0, time_max, time_step)
    error(ode_rk.state, analytical.state, "Runge-Kutta")

    # Euler with lower time step (1.d)
    euler_time_step = 0.05
    time_small = np.arange(0, time_max, euler_time_step)  # Time vector
    x_a = analytic_function(time_small)
    analytical_ts_small = Result(x_a, time_small)
    euler_ts_small = (euler_integrate(function, x0, time_max, euler_time_step)
                      if euler_time_step is not None else None)
    error(euler_ts_small.state, analytical_ts_small.state,
          "Euler (smaller ts)")

    # Plot integration results
    plot_integration_methods(analytical=analytical,
                             euler=euler,
                             ode=ode,
                             ode_rk=ode_rk,
                             euler_ts_small=euler_ts_small,
                             euler_timestep=time_step,
                             euler_timestep_small=euler_time_step)

    # Error analysis (Exercise 1.e)
    pylog.info("Studying integration error using different methods")
    dt_list = np.logspace(-3, 0, 20)  # List of timesteps (powers of 10)
    integration_errors = [["L1", 1], ["L2", 2], ["Linf", 0]]
    methods = [["Euler", euler_integrate, function],
               ["Lsoda", ode_integrate, function],
               ["RK", ode_integrate_rk, function_rk]]
    for error_name, error_index in integration_errors:
        for name, integration_function, f in methods:
            compute_error(f,
                          analytic_function,
                          integration_function,
                          x0,
                          dt_list,
                          time_max=time_max,
                          figure=error_name,
                          label=name,
                          n=error_index)

    # Show plots of all results
    if not clargs.save_figures:
        plt.show()
    return