def test_callcorrect(self): u0 = solution_linear(np.ones(self.ndof), self.A, self.M) nsteps = 13 tp = trapezoidal(0.0, 1.0, nsteps) tp.run(u0) # Compute output through update matrix and compare Rmat = tp.get_update_matrix(u0) yend = Rmat.dot(np.ones((self.ndof,1))) sol_end = solution_linear( yend, self.A, self.M ) sol_end.axpy(-1.0, u0) assert sol_end.norm()<2e-12, ("Output from trapezoidal rule integrator differs from result computed with power of update matrix -- norm of difference: %5.3e" % sol_end.norm())
def test_allconvergedzeromaxiter(self): tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 0) # to allow computing residuals, set initial value, run fine and set end value sol_end = solution_linear( np.ones(1), np.array([[-1.0]]) ) sol_start = solution_linear(np.zeros(1), np.array([[-1.0]]) ) for i in range(0,self.nslices): tm.set_initial_value(sol_start, i) tm.set_end_value(sol_end, i) tm.slices[i].update_fine() # Since iter_max=0, all_converged should return True even though the residual is larger than 1e-10 assert tm.get_max_residual()>1e-10, "Maximum residual is smaller than tolerance, even though set up not to be" assert tm.all_converged, "For iter_max=0, all time slices should be considered converged"
def test_fineequalsmatrix(self): ndof = np.random.randint(25) A = (-2.0)*np.eye(ndof) sol = solution_linear(np.ones(ndof), A) self.ts_default.set_sol_start(sol) self.ts_default.update_fine() sol_ts = self.ts_default.get_sol_fine() assert isinstance(sol_ts, solution_linear), "After running update_fine, object returned by get_sol_fine is of wrong type" Fmat = self.ts_default.get_fine_update_matrix(sol) fine = solution_linear( Fmat.dot(np.ones(ndof)), A) fine.axpy(-1.0, sol_ts) assert fine.norm()<1e-12, "Solution generated with get_fine_update_matrix does not match the one generated by update_fine"
def test_callcorrect(self): u0 = solution_linear(np.ones(self.ndof), self.A, self.M) nsteps = 257 ee = expeuler(0.0, 0.13, nsteps) ee.run(u0) # Compute output through update matrix and compare Rmat = ee.get_update_matrix(u0) yend = Rmat.dot(np.ones((self.ndof, 1))) sol_end = solution_linear(yend, self.A, self.M) sol_end.axpy(-1.0, u0) assert sol_end.norm() < 2e-12, ( "Output from explicit Euler integrator differs from result computed with power of update matrix -- norm of difference: %5.3e" % sol_end.norm())
def test_fineisfixedpointGmatprovided(self): niter = np.random.randint(2, 8) para = parareal(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 0.0, niter, self.u0) Fmat = para.timemesh.get_fine_matrix(self.u0) b = np.zeros((self.ndof * (self.nslices + 1), 1)) b[0:self.ndof, :] = self.u0.y # Solve system u = linalg.spsolve(Fmat, b) u = u.reshape((self.ndof * (self.nslices + 1), 1)) # Build coarse solution with matrix different from fine ucoarse = solution_linear(np.ones((self.ndof, 1)), sparse.eye(self.ndof, format="csc")) # Get Parareal iteration matrices with ucoarse provided Pmat, Bmat = para.get_parareal_matrix(ucoarse=ucoarse) # For comparison also without ucoarse provided and check that both are different Pmat_ref, Bmat_ref = para.get_parareal_matrix() assert np.linalg.norm( Bmat_ref.todense() - Bmat.todense(), np.inf ) > 1e-4, "Parareal iteration matrix Bmat provided with and without ucoarse as argument do not seem to be different." assert np.linalg.norm( Pmat_ref.todense() - Pmat.todense(), np.inf ) > 1e-4, "Parareal iteration matrix Pmat provided with and without ucoarse as argument do not seem to be different." # Apply matrix to fine solution u_para = Pmat.dot(u) + Bmat.dot(b) diff = np.linalg.norm(u_para - u, np.inf) assert diff < 1e-14, ( "Fine solution is not a fixed point of Parareal iteration with provided Gmat matrix - difference %5.3e" % diff)
def test_isconverged(self): ts = timeslice(self.int_fine, self.int_coarse, 1e-14+np.random.rand(), 1+np.random.randint(1)) sol = solution_linear(np.ones(1), np.array([[-1.0]])) ts.set_sol_start(sol) ts.update_fine() ts.set_sol_end(ts.get_sol_fine()) assert ts.is_converged(), "After running F and setting sol_end to the result, the residual should be zero and the time slice converged"
def run_parareal(uhat, D, k): sol = solution_linear(np.asarray([[uhat]]), np.asarray([[D]])) para = parareal(tstart=0.0, tend=tmax, nslices=nproc, fine=intexact, coarse=impeuler, nsteps_fine=nfine, nsteps_coarse=ncoarse, tolerance=0.0, iter_max=k, u0 = sol) stab_coarse = para.timemesh.slices[0].get_coarse_update_matrix(sol) stab_ex = np.exp(D) if artificial_coarse==2: stab_tailor = abs(stab_coarse[0,0])*np.exp(1j*np.angle(stab_ex)) # exact phase speed elif artificial_coarse==1: stab_tailor = abs(stab_ex)*np.exp(1j*np.angle(stab_coarse[0,0])) # exact amplification factor # If some artificial propagator is used, need to re-compute Parareal stability matrix with newly designed # stability matrix if not artificial_coarse == 0: stab_tailor = sp.csc_matrix(np.array([stab_tailor], dtype='complex')) para = parareal(tstart=0.0, tend=tmax, nslices=nproc, fine=intexact, coarse=stab_tailor, nsteps_fine=nfine, nsteps_coarse=1, tolerance=0.0, iter_max=k, u0 = sol) if artificial_fine==1: assert artificial_coarse==0, "Using artifical coarse and fine propagators together is not implemented and probably not working correctly" stab_fine = abs(stab_ex)*np.exp(1j*np.angle(stab_coarse[0,0])) stab_fine = sp.csc_matrix(np.array([stab_fine], dtype='complex')) # Must use nfine=1 in this case para = parareal(tstart=0.0, tend=tmax, nslices=nproc, fine=stab_fine, coarse=impeuler, nsteps_fine=1, nsteps_coarse=ncoarse, tolerance=0.0, iter_max=k, u0 = sol) para.run() temp = para.get_last_end_value() return temp.y[0,0]
def test_solve(self): self.M = sparse.spdiags([ np.random.rand(self.ndof) ], [0], self.ndof, self.ndof)*sparse.identity(self.ndof) self.A = sparse.csc_matrix(self.A) u = np.reshape(np.random.rand(self.ndof), (self.ndof,1)) b = ( self.M - 0.1*self.A ).dot(u) sol_lin = solution_linear(b, self.A, self.M) sol_lin.solve(0.1) assert np.allclose(sol_lin.y, u, rtol=1e-12, atol=1e-12), "Solution provided by solve seems wrong"
def setUp(self): times = np.sort( np.random.rand(2) ) self.tstart = times[0] self.tend = times[1] self.nslices = np.random.randint(2,128) steps = np.sort( np.random.randint(low=1, high=128, size=2) ) self.ncoarse = steps[0] self.nfine = steps[1] self.u0 = solution_linear(np.array([1.0]), np.array([[-1.0]]))
def test_raiseiterconvergence(self): tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 2) sol_end = solution_linear( np.ones(1), np.array([[-1.0]]) ) sol_start = solution_linear(np.zeros(1), np.array([[-1.0]]) ) for i in range(0,self.nslices): tm.set_initial_value(sol_start, i) tm.set_end_value(sol_end, i) tm.slices[i].update_fine() # since iter_max=2, time slices should not yet have converged assert not tm.all_converged(), "All time slices have converged even though initialised not to be" # increase iteration counter for i in range(0,self.nslices): tm.increase_iter(i) # For max_iter=2, timeslices should not yet have converged assert not tm.all_converged(), "Raising iteration counter once with iter_max should not lead to convergence" # increase iteration counter again for i in range(0,self.nslices): tm.increase_iter(i) assert tm.all_converged(), "Raising iteration counter through increase_iter did not lead to convergence"
def test_callcorrectscalar(self): eig = -1.0 u0 = solution_linear(np.array([1.0]), np.array([[eig]])) nsteps = 50 tp = trapezoidal(0.0, 1.0, nsteps) tp.run(u0) assert abs(u0.y - np.exp(-1.0))<5e-3, ("Very wrong solution. Error: %5.2e" % abs(u0.y - np.exp(-1.0))) Rmat = tp.get_update_matrix(u0) Rmat_ie = Rmat[0,0] Rmat_ex = ((1.0 + 0.5*tp.dt*eig)/(1.0 - 0.5*tp.dt*eig))**nsteps assert abs(Rmat_ie - Rmat_ex)<1e-14, ("Update function generated by trapezoidal rule for scalar case does not match exact value. Error: %5.3e" % abs(Rmat_ie - Rmat_ex))
def test_runs(self): tend = np.random.rand(1) * 10.0 tend = tend[0] ex = intexact(0.0, tend, 10) ex.run(self.sol) yex = np.exp(tend * self.A[0, 0] / self.M[0, 0]) * 1.0 uex = solution_linear(np.array([[yex]], dtype='complex'), self.A, self.M) uex.axpy(-1.0, self.sol) diff = uex.norm() assert diff < 1e-14, ( "intexact does not provide exact solution. Error: %5.3e" % diff)
def test_callcorrectscalar(self): eig = -1.0 u0 = solution_linear(np.array([1.0]), np.array([[eig]])) nsteps = 50 ie = impeuler(0.0, 1.0, nsteps) ie.run(u0) assert abs(u0.y - np.exp(-1.0)) < 5e-3, ( "Very wrong solution. Error: %5.2e" % abs(u0.y - np.exp(-1.0))) Rmat = ie.get_update_matrix(u0) Rmat_ie = Rmat[0, 0] Rmat_ex = (1.0 / (1.0 - ie.dt * eig))**nsteps assert abs(Rmat_ie - Rmat_ex) < 1e-14, ( "Update function generated by implicit Euler for scalar case does not match exact value. Error: %5.3e" % abs(Rmat_ie - Rmat_ex))
def setUp(self): self.ndof = np.random.randint(255) self.A = sparse.spdiags([ np.ones(self.ndof), -2.0 * np.ones(self.ndof), np.ones(self.ndof) ], [-1, 0, 1], self.ndof, self.ndof, format="csc") self.M = sparse.spdiags([np.random.rand(self.ndof)], [0], self.ndof, self.ndof, format="csc") self.sol = solution_linear(np.ones(self.ndof), self.A, self.M)
def setUp(self): times = np.sort(np.random.rand(2)) self.tstart = times[0] self.tend = times[1] self.nslices = np.random.randint(2, 32) steps = np.sort(np.random.randint(low=1, high=64, size=2)) self.ncoarse = steps[0] self.nfine = steps[1] self.ndof = np.random.randint(1, 16) #self.ndof = 2 #self.nslices = 3 self.A = sparse.spdiags([ np.ones(self.ndof), -2.0 * np.ones(self.ndof), np.ones(self.ndof) ], [-1, 0, 1], self.ndof, self.ndof, format="csc") self.M = sparse.spdiags([10.0 + np.random.rand(self.ndof)], [0], self.ndof, self.ndof, format="csc") self.u0 = solution_linear(np.ones((self.ndof, 1)), self.A, self.M)
Nsamples = 40 Nk = 6 k_vec = np.linspace(0, np.pi, Nk + 1, endpoint=False) k_vec = k_vec[1:] waveno_v = [k_vec[0], k_vec[1], k_vec[-1]] svds = np.zeros((3, np.size(nslices_v))) for j in range(3): symb = -(1j * U_speed * waveno_v[j] + nu * waveno_v[j]**2) symb_coarse = symb # symb_coarse = -(1.0/dx)*(1.0 - np.exp(-1j*waveno*dx)) # Solution objects define the problem u0 = solution_linear(u0_val, np.array([[symb]], dtype='complex')) ucoarse = solution_linear(u0_val, np.array([[symb_coarse]], dtype='complex')) for i in range(0, np.size(nslices_v)): para = parareal(0.0, float(nslices_v[i]), nslices_v[i], intexact, impeuler, nfine, ncoarse, 0.0, 1, u0) svds[j, i] = para.get_max_svd(ucoarse=ucoarse) rcParams['figure.figsize'] = 3.54, 3.54 fs = 8 fig = plt.figure() plt.plot(nslices_v, svds[0, :], 'b-o', label=(r"$\kappa$=%4.2f" % waveno_v[0]), markersize=fs / 2,
def test_caninstantiate(self): sol_lin = solution_linear(self.y, self.A, self.M)
def test_wrongsizeA(self): A = np.random.rand(self.ndof+1, self.ndof+1) with self.assertRaises(AssertionError): sol_lin = solution_linear(self.y, A, self.M)
def test_cansetinitialtimeslice(self): u0 = solution_linear(np.array([1.0]), np.array([[-1.0]])) tm = timemesh(self.tstart, self.tend, self.nslices, impeuler, impeuler, self.nfine, self.ncoarse, 1e-10, 5) tm.set_initial_value(self.u0, 3)
N_re = 10 N_im = 10 lam_im_max = 50.0 lam_re_max = 1.0 lambda_im = 1j * np.linspace(0.0, lam_im_max, N_im) lambda_re = np.linspace(-lam_re_max, 1.0, N_re) nfine = 10 ncoarse = 1 niter = 3 nslices = 100 stab = np.zeros((N_im, N_re), dtype='complex') for i in range(0, N_re): for j in range(0, N_im): u0 = solution_linear(y=np.array([[1.0]], dtype='complex'), A=np.array([[lambda_re[i] + lambda_im[j]]], dtype='complex')) para = parareal(0.0, 1.0, nslices, impeuler, impeuler, ncoarse, nfine, 0.0, niter, u0) Mat = para.get_parareal_stab_function(niter) stab[j, i] = abs(Mat) ### #rcParams['figure.figsize'] = 2.5, 2.5 fs = 8 fig = plt.figure() #pcol = plt.pcolor(lambda_s.imag, lambda_f.imag, np.absolute(stab), vmin=0.99, vmax=2.01) #pcol.set_edgecolor('face') levels = np.array([0.25, 0.5, 0.75, 0.9, 1.1]) # levels = np.array([1.0]) CS1 = plt.contour(lambda_re, lambda_im.imag,
amp_factor = np.zeros((6,Nsamples)) u0_val = np.array([1.0, 1.0, 1.0], dtype='complex') targets = np.zeros((3,Nsamples)) for i in range(0,np.size(k_vec)): f = 0.1 g = 1.0 H = 1.0 Lmat = -1.0*np.array([[0.0, -f, g*1j*k_vec[i] ], \ [f, 0.0, 0.0], \ [H*1j*k_vec[i], 0, 0]], dtype = 'complex') u0 = solution_linear(u0_val, Lmat) para = parareal(0.0, Tend, nslices, impeuler, impeuler, nfine, ncoarse, 0.0, niter_v[0], u0) # get update matrix for imp Euler over one slice stab_fine = para.timemesh.slices[0].get_fine_update_matrix(u0) stab_coarse = para.timemesh.slices[0].get_coarse_update_matrix(u0) stab_ex = linalg.expm(Lmat) sol_fine = solve_omega(stab_fine) sol_ex = solve_omega(stab_ex) sol_coarse = solve_omega(stab_coarse) phase[0,i] = sol_ex.real/k_vec[i]