### Added explicit SDC minimal example + toolbox

parent 73ce15d3
SDC_explicit.py 0 → 100644
 from functions import fcs as fcs import numpy as np import matplotlib.pyplot as plt from copy import deepcopy # ################################## Vars ################################### # l = -1j*(1) # lambda a = 0 # t_start b = 1 # t_end y0 = 1 # initial condition M = 4 # number of quadrature nodes K = 5 # number of iterations t_plot = np.linspace(a, b, 100) # array of times for plotting analytical solution # The size of y and t is M+2 because they include t_start + nodes + t_end y = np.zeros(M+2, dtype=complex) # allocate memory for solution vector t = np.zeros(M+2) # allocate memory for time vector # some control variables fin_u = 1 # calculate final update if fin_u = 1 radau = 0 # use radau IIA nodes, if 0 use Gauss-Legendre nodes check = 0 # use collocation solution to check for correct # # application of SDC # ################################## RHS #################################### # # Dahlquist Equation def f(y, ld=l): return l*y # ################################## SOL #################################### # def F(t, ld=l): return np.exp(l*t) # ################################## Init ################################### # # Calculate first guess y = y0 # set initial condition t = a # set initial time t[-1] = b # set final time # calculate quadrature nodes and weights for final update if radau: nodes, weights = fcs.rnw_r(M, a, b) else: nodes, weights = fcs.nodes_weights(M, a, b) # write nodes to time array t[1:-1] = nodes # calculate delta_tau d_tau = np.diff(t) # use euler explicit for initial guess for i in range(M): y[i+1] = y[i] + d_tau[i]*f(y[i]) #y[:] = y0 # set initial guess to y0 # ################################## SDC #################################### # # generate matrices Q and S needed for SDC iterations Q = fcs.Qmatrix(nodes, a) S = fcs.Smatrix(Q) for j in range(K): y_old = deepcopy(y) quad = S@(l*y_old[1:-1]) for i in range(M): y[i+1] = y[i] + d_tau[i]*(f(y[i]) - f(y_old[i])) + quad[i] # calculate residual (needs to go to 0 if k-> inf) residual = y + Q@f(y[1:-1]) - y[1:-1] # ################################## Check ################################## # # This is not necessary for SDC it is just to check wether SDC and collocation # solutions match if check: # Use collocation solution to check if SDC works correctly # This is not needed for SDC, we only check for the correct solution Id = np.eye(len(Q)) A = (Id - l*Q) B = np.zeros(len(Q)) B[:] = np.exp(0) Sol = np.linalg.solve(A, B) # works and returns correct solution print('') print('Errors at collocation nodes are:') print(Sol - y[1:-1]) # if K is large difference should be ~1e-15 print('M='+str(M)+' iterations were used') # ############################## Final Update ############################### # # calcualte final update if fin_u: y[-1] = y0 + np.dot(weights, f(y[1:-1])) # ################################## Plot ################################### # # plot results (only real part) plt.plot(t_plot, F(t_plot), linestyle='--', color='C0', label=r'$F(x)$') plt.plot(t, y, linestyle='', marker='x', color='C1', label=r'$y(a)$') plt.plot(t[1:-1], y[1:-1], linestyle='', marker='o', color='C3', label=r'$y(\tau_m)$') if fin_u: plt.plot(t[-1], y[-1], linestyle='', color='C7', marker='D', markersize=10, label=r'$y(b)$') if check: plt.plot(t[1:-1], Sol, linestyle='', marker='.', color='C4', label='Collocation Solution') plt.legend()
functions.py 0 → 100755