def compareStabilityDomains(self, list_rk_names): xx,yy = self.re_xx, self.im_yy zz = self.eigvals x= self.re y= self.im # ratio_height_over_width = np.abs( (np.max(y)-np.min(y))/(np.max(x)-np.min(x)) ) # fig, ax = plt.subplots(1,1,dpi=80, figsize=(8, 8*ratio_height_over_width)) fig, ax = plt.subplots(1,1,dpi=300) # plot des axes Im et Re ax.plot([np.min(x), np.max(x)], [0,0], color=(0,0,0), linestyle='--', linewidth=0.4) ax.plot([0,0], [np.min(y), np.max(y)], color=(0,0,0), linestyle='--', linewidth=0.4) ## Axis description fig.suptitle(f'Domaines de stabilité') ax.set_xlabel(r'Re$(\lambda\Delta t)$') ax.set_ylabel(r'Im$(\lambda\Delta t)$') colors = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 'tab:brown', 'tab:pink', 'tab:gray', 'tab:olive', 'tab:cyan'] for i,name in enumerate(list_rk_names): print(name) method = rk_coeffs.getButcher(name) A,b,c = method['A'], method['b'], method['c'] if np.size(b)>6: bSympy=False # c'est plus rapide d'éviter Sympy, on dirait qu'il n'arrive pas à calculer les détermiannts analytiquement... else: bSympy=True Rfun, Rsym = self.computeStabilityFunction(A,b,c,bSympy=bSympy) RR = Rfun(zz) rr = np.abs(RR) # ratio d'augmentation current_color=colors[i] # add stability domain ax.contour(xx,yy,rr,levels=[0,1],colors=current_color) # hachurer en rouge la zone instable # rr_sup_1 = np.where(np.abs(rr) >= 1) # temp = np.zeros_like(rr) # temp[rr_sup_1] = 1. # plt.rcParams['hatch.color']=current_color # seul moyen que j'ai trouvé pour avoir des hachures rouges... # cs = ax.contourf(xx,yy, temp, levels=[0,0.5,1.5], #levels=[0., 1.0, 1.5], # hatches=[None,'\\\\', '\\\\'], alpha = 0.) # plt.rcParams['hatch.color']=[0,0,0] # add legend proxy = [plt.Rectangle((0,0),1,1,fc = colors[i]) for i in range(len(list_rk_names))] ax.legend(proxy, list_rk_names)
# ax.axis('equal') if __name__=='__main__': # Setup warnings such that any problem with complex number raises an error import warnings warnings.simplefilter("error", np.ComplexWarning) #to ensure we are not dropping complex perturbations # Choose the area of the complex plane that will be analysed # test = testPrecision(re_min=-100, re_max=100, im_min=0., im_max=100, n_re=1000, n_im=1001) # on aperçoit des formes intriguantes en terme d'iso-contour de précision # test = testPrecision(re_min=-10, re_max=10, im_min=-5, im_max=5, n_re=200, n_im=202) # test = testPrecision(re_min=-20, re_max=20, im_min=-20, im_max=20, n_re=200, n_im=202) # test = testPrecision(re_min=-3, re_max=3, im_min=-3, im_max=3, n_re=200, n_im=202) test = testPrecision(re_min=-6, re_max=6, im_min=-6, im_max=6, n_re=200, n_im=202) #%% Show the precision and stability of a given RK method method = rk_coeffs.getButcher('Radau5') # method = rk_coeffs.getButcher('RK45') A,b,c = method['A'], method['b'], method['c'] # A,b,c = reverseRK(A,b,c) # tracé du contour de la précision par rapport à l'exponentielle pprecision, pprecision2 = test.plotStabilityRegionRK(A,b,c, bSympy=False) R, Rsym = test.computeStabilityFunction(A,b,c, bSympy=False) # calcul du rayon spectral eigvals = np.linalg.eigvals(A) rho = np.max(np.abs(eigvals)) print('spectral radius: rho=', rho) print('R(rho)=', R(rho)) print('R(1/rho)=', R(1/rho))
solref = scipy.integrate.solve_ivp(fun=modelfun, y0=x_0, t_span=T, method='Radau', t_eval=None, vectorized=False, rtol=1e-12, atol=1e-12, jac=None) if solref.status != 0: raise Exception('ODE integration failed: {}'.format(solref.message)) t_end = pytime.time() print('DIRK computed in {} s'.format(t_end - t_start)) #### compute solution with DIRK A, b, c = rk_coeffs.getButcher('L-SDIRK-33') t_start = pytime.time() sol_dirk = DIRK_integration(f=modelfun, y0=x_0, t_span=T, nt=nt_dirk, A=A, b=b, c=c, options=None, gradF=gradF, bRosenbrockApprox=False, bUseCustomNewton=True) t_end = pytime.time() print('DIRK computed in {} s'.format(t_end - t_start))
nt = 20 elif problemtype=='stiff': # Hirschfelder-Curtiss print('Testing time integration routines with Hirschfelder-Curtiss stiff equation') k=100 def modelfun(t,x): """ Mass-spring system""" return -k*(x-np.sin(t)) y0 = np.array((0.3,1)) tf = 5.0 nt = 100 elif problemtype=='dae': # DAE simple : y1'=y1, 0=y1+y2 raise Exception('TODO: DAEs are not yet compatible with the chosen formulation: need to add mass matrix to the problem formulation') elif problemtype=='pde': raise Exception('TODO') method = rk_coeffs.getButcher(name=name) if mod=='DIRK': # DIRK solve sol = DIRK_integration(fun=modelfun, y0=y0, t_span=[0., tf], nt=nt, method=method, jacfun=None) elif mod=='FIRK': # FIRK solve sol = FIRK_integration(fun=modelfun, y0=y0, t_span=[0., tf], nt=nt, method=method, jacfun=None) elif mod=='ERK': # FIRK solve sol = ERK_integration(fun=modelfun, y0=y0, t_span=[0., tf], nt=nt, method=method) elif mod=='reverseERK': sol = inverseERKintegration(fun=modelfun, y0=y0, t_span=[0,tf], nt=nt, method=method, jacfun=None, bPrint=True, fullDebug=True, bPlotSubsteps=True) elif mod=='adapt_ERK': sol = ERK_adapt_integration(fun=modelfun, y0=y0, t_span=[0.,tf], method=method, first_step=1e-2,
t_eval=None, #np.linspace(0,tf,5), dense_output=False, # jac_sparsity=jacSparsity, jac=jacfun, events=None, vectorized=False, args=None) else: from integration_esdirk import FIRK_integration, DIRK_integration, ERK_integration import rk_coeffs method = 'Radau5' mod = 'FIRK' # method='IE'; mod ='DIRK' # method='L-SDIRK-33'; mod ='DIRK' nt = 100 A, b, c = rk_coeffs.getButcher(name=method) if mod == 'DIRK': # DIRK solve out = DIRK_integration( fun=lambda t, x: modelfun(t=t, z=x, options=options), y0=y0, t_span=[0., tf], nt=nt, A=A, b=b, c=c, jacfun=jacfun) elif mod == 'FIRK': # FIRK solve out = FIRK_integration( fun=lambda t, x: modelfun(t=t, z=x, options=options), y0=y0, t_span=[0., tf],
from bruss_1D import brusselator_1d ### SETUP MODEL ### xmin = 0 xmax = 4 nx = 1000 dx = (xmax - xmin) / (nx + 1) x = np.linspace(xmin + dx, xmax - dx, nx) bz1d = brusselator_1d(nx=nx) fcn = bz1d.fcn yini = bz1d.init() nvar = 2 # Setup time integation interval and method tini = 0. tend = 2.0 method = rk_coeffs.getButcher('ESDIRK43B') # Create a function to efficiently compute the system's Jacobian if 0: import scipy.optimize from scipy.sparse import diags width = np.ceil(nvar * 1.5).astype(int) offsets = range( -width, width) # positions of the diagonals with respect to the main diagonal diagonals = [np.ones((nvar * bz1d.nx - abs(i), )) for i in offsets] sparsity = diags(diagonals, offsets) groups = scipy.optimize._numdiff.group_columns(sparsity) def jac_sparse(t, x): return scipy.sparse.csc_matrix(
np.log10(np.abs(expp / self.x0)), levels=map_levels) #, cmap = 'gist_earth') fig2.colorbar(cs) ax.contour(xx, yy, rr, levels=[0, 1], colors='r') ax.set_title('expansion ratio of numerical solution') return pprecision, pprecision2 if __name__ == '__main__': import warnings warnings.simplefilter( "error", np.ComplexWarning ) #to ensure we are not dropping complex perturbations ## test RK stability region N = 200 A, b, c = rk_coeffs.getButcher( 'rk4') #54A-V4') #'RadauIIA-5')#'L-SDIRK-33') #SDIRK4()5L[1]SA-1') # plotStabilityRegionRK_old(A,b,c, re_min=-5, re_max=10, im_min=-5, im_max=5, n_re=N, n_im=N+2 ) test = testPrecision(re_min=-10, re_max=10, im_min=-5, im_max=5, n_re=N, n_im=N + 2, x0=1) # test = testPrecision(re_min=-20, re_max=20, im_min=-20, im_max=20, n_re=N, n_im=N+2, x0=1) pprecision, pprecision2 = test.plotStabilityRegionRK(A, b, c, nt=10) # estimate R(+\infty) R = test.functionStabilityPolynomial(A, b, c)