Example #1
0
def second_derivative_convergence_figure(fun, point, real_value):
    # making different intervals and empty array for y coordinates
    dx = np.linspace(1, 10e-3, 100)
    y = np.zeros((len(dx)))
    # calculating difference to analytical value for all intervals
    for i in range(len(dx)):
        diff = abs(real_value - second_derivative(fun, point, dx[i]))
        y[i] = diff
    # plotting figure
    my_plot(dx, y, "second_derivative_error_figure.pdf")
def conv_plot(fun, number, correct, fun_str):
    # fun      : function to be tested with
    # number   : number for names and titles
    # correct  : correct answer
    # fun_str  : function as a string

    # Takes a function and plots its convergence
    # to a figure and saves it with name and title
    # specified in funciton parameters

    # logarithmic values to check convergence
    dx = 10**(-np.linspace(1, 5, 21))

    value1 = np.zeros(21)
    value2 = np.zeros(21)
    value3 = np.zeros(21)

    # values for certain intervals
    for n in range(0, 21):
        value1[n] = first_derivative(fun, 5, dx[n]) - correct[0]
        value2[n] = second_derivative(fun, 5, dx[n]) - correct[1]
        value3[n] = num_simpson(fun, 0, 5, int(
            2 * round(1 / dx[n] / 2))) - correct[2]

    fig = plt.figure()
    ax = fig.add_subplot(111)

    # specify logaritmhic scale
    plt.yscale('log')
    plt.xscale('log')

    ax.plot(dx, abs(value1), label='first derivative', marker='o')
    ax.plot(dx, abs(value2), label='second derivative', marker='o')
    ax.plot(dx, abs(value3), label='simpson integral', marker='o')

    plt.legend(loc='upper right', ncol=1, borderaxespad=0.)

    # x axis limit and axis labels
    ax.set_xlim(dx.max(), dx.min())
    ax.set_xlabel('interval length')
    ax.set_ylabel('convergence')

    title = 'Convergence figure: ' + fun_str
    fig.suptitle(title)

    name = 'convergence' + str(number) + '.pdf'

    # save and show figures
    fig.savefig(name, dpi=200)
    plt.show()

    return
def my_plot1():
    fig = plt.figure()
    ax = fig.add_subplot(111)

    #  calculate numerical derivatives for sine function at x = pi/2 with different spacings
    #  correct first derivative is 0
    #  correct second derivative is -1
    x = np.pi / 2
    f = np.sin(x)

    correct_der1 = 0
    correct_der2 = -1
    dx_spacing = np.linspace(0.001, 1, 100)

    first_derivative_abs_err = []
    second_derivative_abs_err = []

    # save absolute error for each spacing into array first_derivative_abs_err
    for i in range(dx_spacing.shape[0]):
        err = abs(first_derivative(np.sin, x, dx_spacing[i]) - correct_der1)
        first_derivative_abs_err.append(err)

    # same for second derivative
    for i in range(dx_spacing.shape[0]):
        err = abs(second_derivative(np.sin, x, dx_spacing[i]) - correct_der2)
        second_derivative_abs_err.append(err)

    # plot and add label if legend desired
    ax.plot(dx_spacing,
            first_derivative_abs_err,
            label=r'first_derivative abs error')
    ax.plot(dx_spacing,
            second_derivative_abs_err,
            label=r'second_derivative abs error')

    ax.legend(loc=0)

    # set axes labels and limits
    ax.set_xlabel(r'x spacing')
    ax.set_ylabel(r'Absolute error')
    ax.set_xlim(dx_spacing.min(), dx_spacing.max())
    ax.set_ylim(bottom=0)

    plt.title(
        'Absolute error as a function of x spacing. \nEvaluated derivative of function sin(x) at x=pi/2'
    )
    fig.tight_layout(pad=1)
    # save figure as pdf with 200dpi resolution
    fig.savefig('derivative_error.pdf', dpi=200)
    plt.show()
def calculate_derivative_errors():
    # Calculates the numerical first and second order derivatives
    # and compares them to analytical values
    f = lambda x: np.sin(x)
    f_dot = lambda x: np.cos(x)
    f_dot2 = lambda x: -np.sin(x)
    x = 1.5
    errors1 = []
    errors2 = []
    dxs = np.linspace(1e-6, 1e-1, 1000)
    for dx in dxs:
        errors1.append(abs(first_derivative(f, x, dx) - f_dot(x)))
        errors2.append(abs(second_derivative(f, x, dx) - f_dot2(x)))
    plot_derivative_errors(dxs, errors1, errors2)
def compute_derivatives(test_func: Callable, x_point: float, grid_spacing: list) -> tuple:
    """
    Compute the first and second derivatives of the given 1D function at the given
    point, using different values of grid spacing.

    :param test_func: Function for which derivatives are approximated
    :param x_point: Point in x-axis where derivative is approximated
    :param num_grids: List of grid spacing values to use
    :returns: Tuple of first derivate approximations and second derivative
    approximations in respective indices of the tuple.
    """

    # With each grid spacing value, get the approximation of first and second
    # derivatives
    first_derivatives = [num_calculus.first_derivative(test_func, x_point, dx)
                         for dx in grid_spacing]
    second_derivatives = [num_calculus.second_derivative(test_func, x_point, dx)
                         for dx in grid_spacing]

    return first_derivatives, second_derivatives
# Analytical solutions for each function
analytical_fd = der_test_function(x)
analytical_sd = sec_der_test_function(x)
analytical_rs = int_test_function(xmin, xmax)

errors_fd = []  # errors for first derivative
errors_sd = []  # errors for second derivative
errors_rs = []  # errors for riemann_sum integration

# Calculate errors for derivatives
for dx in dxs:
    numerical_fd = first_derivative(test_function, x, dx)
    error_fd = np.abs(numerical_fd - analytical_fd)

    numerical_sd = second_derivative(test_function, x, dx)
    error_sd = np.abs(numerical_sd - analytical_sd)

    errors_fd.append(error_fd)
    errors_sd.append(error_sd)

# Calculate errors for integration
for intervals in range(2, 50):
    x_range = np.linspace(xmin, xmax, num=intervals)
    numerical_rs = riemann_sum(x_range, test_function)
    error_rs = np.abs(numerical_rs - analytical_rs)
    errors_rs.append(error_rs)

# Plot first derivative
fig_fd = plt.figure(1)
ax = fig_fd.add_subplot(111)