def first_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 - first_derivative(fun, point, dx[i])) y[i] = diff # plotting figure my_plot(dx, y, "first_derivative_error_figure.pdf")
def first_derivative_convergence(): x = 0.3 dx = np.linspace(0.001, 0.5, 10) df = [] for i in range(len(dx)): df.append( abs( first_derivative(test_function, x, dx[i]) - test_function_derivative(x))) df = np.array(df) simple_plot(dx, df, ['$x$', '$f(x)$'], None) plt.show()
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
def minimum(fun, x, xl=0, dl=0): """ :param: fun is the function to be checked :param: x is the value around which the ectremum is looked for :param: xl is last x value used in recursion :param: dl is the last derivative used in recursion :return: itself or extremum and corresponding x (prints the outcome) calculates recursively the minimum of the function near the given point x """ derivative = nc.first_derivative(fun, x, 0.001) gamma = -abs((x - xl) / (derivative - dl)) if abs(derivative) > 1e-6: return minimum(fun, x + gamma * derivative, x, derivative) else: print("The minimum for the function is {} at x = {}".format(fun(x), x)) return x, fun(x)
xmin = 0 xmax = np.pi / 2 rs_x = np.linspace(2, 50, num=48) # 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)