def error_channel_flow_RK2_unsteady_inlet(steps=3, return_stability=False, name='heun', guess=None, project=[], theta=None): probDescription = sc.ProbDescription() f = func(probDescription) dt = probDescription.get_dt() μ = probDescription.get_mu() nx, ny = probDescription.get_gridPoints() dx, dy = probDescription.get_differential_elements() t = 0.0 tend = steps count = 0 print('dt=', dt) xcc, ycc = probDescription.get_cell_centered() xu, yu = probDescription.get_XVol() xv, yv = probDescription.get_YVol() # initialize velocities - we stagger everything in the negative direction. A scalar cell owns its minus face, only. # Then, for example, the u velocity field has a ghost cell at x0 - dx and the plus ghost cell at lx np.random.seed(123) u0 = np.random.rand(ny + 2, nx + 2) / 10000 # include ghost cells # u0 = np.ones([ny +2, nx+2])# include ghost cells # same thing for the y-velocity component v0 = np.random.rand(ny + 2, nx + 2) / 10000 # include ghost cells # v0 = np.ones([ny +2, nx+2]) # include ghost cells at = lambda t: (np.pi / 6) * np.sin(t / 2) u_bc_top_wall = lambda xv: 0 u_bc_bottom_wall = lambda xv: 0 u_bc_right_wall = lambda u: lambda yv: u u_bc_left_wall = lambda t: lambda yv: np.cos(at(t)) v_bc_top_wall = lambda xv: 0 v_bc_bottom_wall = lambda xv: 0 v_bc_right_wall = lambda yv: 0 v_bc_left_wall = lambda t: lambda yv: np.sin(at(t)) # pressure def pressure_right_wall(p): # pressure on the right wall p[1:-1, -1] = -p[1:-1, -2] p_bcs = lambda p: pressure_right_wall(p) # apply bcs f.top_wall(u0, v0, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u0, v0, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u0, v0, u_bc_right_wall(u0[1:-1, -1]), v_bc_right_wall) f.left_wall(u0, v0, u_bc_left_wall(t), v_bc_left_wall(t)) Coef = f.A_channel_flow() u0_free, v0_free, _, _ = f.ImQ_bcs(u0, v0, Coef, 0, p_bcs) f.top_wall(u0_free, v0_free, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u0_free, v0_free, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u0_free, v0_free, u_bc_right_wall(u0_free[1:-1, -1]), v_bc_right_wall) f.left_wall(u0_free, v0_free, u_bc_left_wall(t), v_bc_left_wall(t)) print('div_u0=', np.linalg.norm(f.div(u0_free, v0_free).ravel())) # initialize the pressure p0 = np.zeros([nx + 2, ny + 2]) # include ghost cells #declare unp1 unp1 = np.zeros_like(u0) vnp1 = np.zeros_like(v0) div_np1 = np.zeros_like(p0) # a bunch of lists for animation purposes usol = [] # usol.append(u0) usol.append(u0_free) vsol = [] # vsol.append(v0) vsol.append(v0_free) psol = [] psol.append(p0) iterations = [0] while count < tend: print('timestep:{}'.format(count + 1)) print('-----------') # rk coefficients RK2 = sc.RK2(name, theta) a21 = RK2.a21 b1 = RK2.b1 b2 = RK2.b2 u = usol[-1].copy() v = vsol[-1].copy() pn = np.zeros_like(u) pnm1 = np.zeros_like(u) # pnm2 = np.zeros_like(u) # only needed for high accurate pressure if count > 1: # change the count for 2 if high accurate pressure at time np1 is needed pn = psol[-1].copy() pnm1 = psol[-2].copy() # pnm2 = psol[-3].copy() # only needed for high accurate pressure f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name, theta=theta) d2, = project elif count <= 1: # compute pressures for 2 time steps # change the count for 2 if high accurate pressure at time np1 is needed d2 = 1 f1x, f1y = f.Guess([pn, pnm1], order=None, integ='RK2', type=name, theta=theta) ## stage 1 print(' Stage 1:') print(' --------') time_start = time.clock() u1 = u.copy() v1 = v.copy() # Au1 # apply boundary conditions before the computation of the rhs f.top_wall(u1, v1, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u1, v1, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u1, v1, u_bc_right_wall(u1[1:-1, -1]), v_bc_right_wall) # this won't change anything for u2 f.left_wall(u1, v1, u_bc_left_wall(t), v_bc_left_wall(t)) urhs1 = f.urhs_bcs(u1, v1) vrhs1 = f.vrhs_bcs(u1, v1) # divergence of u1 div_n = np.linalg.norm(f.div(u1, v1).ravel()) print(' divergence of u1 = ', div_n) ## stage 2 print(' Stage 2:') print(' --------') uh2 = u + a21 * dt * (urhs1 - f1x) vh2 = v + a21 * dt * (vrhs1 - f1y) f.top_wall(uh2, vh2, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(uh2, vh2, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(uh2, vh2, u_bc_right_wall(uh2[1:-1, -2]), v_bc_right_wall) # this won't change anything for u2 f.left_wall(uh2, vh2, u_bc_left_wall(t + a21 * dt), v_bc_left_wall(t + a21 * dt)) if d2 == 1: print(' pressure projection stage{} = True'.format(2)) u2, v2, _, iter1 = f.ImQ_bcs(uh2, vh2, Coef, pn, p_bcs) print(' iterations stage 2 = ', iter1) elif d2 == 0: u2 = uh2 v2 = vh2 # apply bcs f.top_wall(u2, v2, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u2, v2, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u2, v2, u_bc_right_wall(u2[1:-1, -1]), v_bc_right_wall) # this won't change anything for u2 f.left_wall(u2, v2, u_bc_left_wall(t + a21 * dt), v_bc_left_wall(t + a21 * dt)) div2 = np.linalg.norm(f.div(u2, v2).ravel()) print(' divergence of u2 = ', div2) urhs2 = f.urhs_bcs(u2, v2) vrhs2 = f.vrhs_bcs(u2, v2) uhnp1 = u + dt * b1 * (urhs1) + dt * b2 * (urhs2) vhnp1 = v + dt * b1 * (vrhs1) + dt * b2 * (vrhs2) f.top_wall(uhnp1, vhnp1, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(uhnp1, vhnp1, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(uhnp1, vhnp1, u_bc_right_wall(uhnp1[1:-1, -2]), v_bc_right_wall) # this won't change anything for u2 f.left_wall(uhnp1, vhnp1, u_bc_left_wall(t + dt), v_bc_left_wall(t + dt)) unp1, vnp1, press, iter2 = f.ImQ_bcs(uhnp1, vhnp1, Coef, pn, p_bcs) # apply bcs f.top_wall(unp1, vnp1, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(unp1, vnp1, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(unp1, vnp1, u_bc_right_wall(unp1[1:-1, -1]), v_bc_right_wall) # this won't change anything for unp1 f.left_wall(unp1, vnp1, u_bc_left_wall(t + dt), v_bc_left_wall(t + dt)) time_end = time.clock() psol.append(press) # new_press = 4 * pn - 9 * pnm1 / 2 + 3 * pnm2 / 2 # second order (working) cpu_time = time_end - time_start print(' cpu_time=', cpu_time) # Check mass residual div_np1 = np.linalg.norm(f.div(unp1, vnp1).ravel()) residual = div_np1 # if residual > 1e-12: print(' Mass residual:', residual) print('iterations:', iter) # save new solutions usol.append(unp1) vsol.append(vnp1) iterations.append(iter) Min = np.sum(unp1[1:ny + 1, 1]) Mout = np.sum(unp1[1:ny + 1, nx + 1]) print("Min=", Min) print("Mout=", Mout) t += dt # plot of the pressure gradient in order to make sure the solution is correct # # plt.contourf(usol[-1][1:-1,1:]) # if count % 10 ==0: # # divu = f.div(u0_free,v0_free) # # plt.imshow(divu[1:-1,1:-1], origin='bottom') # # plt.colorbar() # ucc = 0.5 * (u[1:-1, 2:] + u[1:-1, 1:-1]) # vcc = 0.5 * (v[2:, 1:-1] + v[1:-1, 1:-1]) # speed = np.sqrt(ucc * ucc + vcc * vcc) # # uexact = 4 * 1.5 * ycc * (1 - ycc) # # plt.plot(uexact, ycc, '-k', label='exact') # # plt.plot(ucc[:, int(8 / dx)], ycc, '--', label='x = {}'.format(8)) # plt.contourf(xcc, ycc, speed) # plt.colorbar() # # plt.streamplot(xcc, ycc, ucc, vcc, color='black', density=0.75, linewidth=1.5) # # plt.contourf(xcc, ycc, psol[-1][1:-1, 1:-1]) # # plt.colorbar() # plt.show() count += 1 if return_stability: return True else: return True, [div_np1], True, unp1[1:-1, 1:-1].ravel() # from singleton_classes import ProbDescription # # # Uinlet = 1 # ν = 0.01 # probDescription = ProbDescription(N=[4*32,32],L=[10,1],μ =ν,dt = 0.005) # dx,dy = probDescription.dx, probDescription.dy # dt = min(0.25*dx*dx/ν,0.25*dy*dy/ν, 4.0*ν/Uinlet/Uinlet) # probDescription.set_dt(dt) # error_channel_flow_RK2_unsteady_inlet (steps = 100,return_stability=False, name='midpoint', guess=None, project=[1],theta=None)
def error_lid_driven_cavity_RK2(steps=3, return_stability=False, name='heun', guess=None, project=[], alpha=0.99): probDescription = sc.ProbDescription() f = func(probDescription) dt = probDescription.get_dt() μ = probDescription.get_mu() nx, ny = probDescription.get_gridPoints() dx, dy = probDescription.get_differential_elements() t = 0.0 tend = steps count = 0 print('dt=', dt) xcc, ycc = probDescription.get_cell_centered() xu, yu = probDescription.get_XVol() xv, yv = probDescription.get_YVol() # initialize velocities - we stagger everything in the negative direction. A scalar cell owns its minus face, only. # Then, for example, the u velocity field has a ghost cell at x0 - dx and the plus ghost cell at lx np.random.seed(123) u0 = np.random.rand(ny + 2, nx + 2) # include ghost cells # u0 = np.ones([ny +2, nx+2])# include ghost cells # same thing for the y-velocity component v0 = np.zeros([ny + 2, nx + 2]) # include ghost cells u_bc_top_wall = lambda xv: 1 u_bc_bottom_wall = lambda xv: 0 u_bc_right_wall = lambda yv: 0 u_bc_left_wall = lambda yv: 0 v_bc_top_wall = lambda xv: 0 v_bc_bottom_wall = lambda xv: 0 v_bc_right_wall = lambda yv: 0 v_bc_left_wall = lambda yv: 0 # pressure p_bcs = lambda p: p # apply bcs f.top_wall(u0, v0, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u0, v0, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u0, v0, u_bc_right_wall, v_bc_right_wall) f.left_wall(u0, v0, u_bc_left_wall, v_bc_left_wall) Coef = f.A_Lid_driven_cavity() # to make the initial condition divergence free. u0_free, v0_free, _, _ = f.ImQ_bcs(u0, v0, Coef, 0, p_bcs) f.top_wall(u0_free, v0_free, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u0_free, v0_free, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u0_free, v0_free, u_bc_right_wall, v_bc_right_wall) f.left_wall(u0_free, v0_free, u_bc_left_wall, v_bc_left_wall) print('div_u0=', np.linalg.norm(f.div(u0_free, v0_free).ravel())) # initialize the pressure p0 = np.zeros([nx + 2, ny + 2]) # include ghost cells #declare unp1 unp1 = np.zeros_like(u0) vnp1 = np.zeros_like(v0) div_np1 = np.zeros_like(p0) # a bunch of lists for animation purposes usol = [] usol.append(u0_free) vsol = [] vsol.append(v0_free) psol = [] psol.append(p0) iterations = [0] while count < tend: print('timestep:{}'.format(count + 1)) print('-----------') # rk coefficients RK2 = sc.RK2(name) a21 = RK2.a21 b1 = RK2.b1 b2 = RK2.b2 u = usol[-1].copy() v = vsol[-1].copy() pn = np.zeros_like(u) pnm1 = np.zeros_like(u) if count > 1: pn = psol[-1].copy() pnm1 = psol[-2].copy() f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name) d2, = project elif count <= 1: # compute pressures for 2 time steps d2 = 1 f1x, f1y = f.Guess([pn, pnm1], order=None, integ='RK2', type=name) ## stage 1 print(' Stage 1:') print(' --------') time_start = time.clock() u1 = u.copy() v1 = v.copy() # Au1 urhs1 = f.urhs_bcs(u1, v1) vrhs1 = f.vrhs_bcs(u1, v1) # divergence of u1 div_n = np.linalg.norm(f.div(u1, v1).ravel()) print(' divergence of u1 = ', div_n) ## stage 2 print(' Stage 2:') print(' --------') uh2 = u + a21 * dt * (urhs1 - f1x) vh2 = v + a21 * dt * (vrhs1 - f1y) if d2 == 1: print(' pressure projection stage{} = True'.format(2)) u2, v2, _, iter1 = f.ImQ_bcs(uh2, vh2, Coef, pn, p_bcs) print(' iterations stage 2 = ', iter1) elif d2 == 0: u2 = uh2 v2 = vh2 # apply bcs f.top_wall(u2, v2, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u2, v2, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u2, v2, u_bc_right_wall, v_bc_right_wall) f.left_wall(u2, v2, u_bc_left_wall, v_bc_left_wall) div2 = np.linalg.norm(f.div(u2, v2).ravel()) print(' divergence of u2 = ', div2) urhs2 = f.urhs_bcs(u2, v2) vrhs2 = f.vrhs_bcs(u2, v2) uhnp1 = u + dt * b1 * (urhs1) + dt * b2 * (urhs2) vhnp1 = v + dt * b1 * (vrhs1) + dt * b2 * (vrhs2) unp1, vnp1, press, iter2 = f.ImQ_bcs(uhnp1, vhnp1, Coef, pn, p_bcs) # apply bcs f.top_wall(unp1, vnp1, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(unp1, vnp1, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(unp1, vnp1, u_bc_right_wall, v_bc_right_wall) f.left_wall(unp1, vnp1, u_bc_left_wall, v_bc_left_wall) time_end = time.clock() psol.append(press) cpu_time = time_end - time_start print(' cpu_time=', cpu_time) # Check mass residual div_np1 = np.linalg.norm(f.div(unp1, vnp1).ravel()) residual = div_np1 # if residual > 1e-12: print(' Mass residual:', residual) print('iterations:', iter) # save new solutions usol.append(unp1) vsol.append(vnp1) iterations.append(iter) t += dt # plot of the pressure gradient in order to make sure the solution is correct # # plt.contourf(usol[-1][1:-1,1:]) # if count % 100 ==0: # divu = f.div(unp1,vnp1) # plt.imshow(divu[1:-1,1:-1], origin='bottom') # plt.colorbar() # # ucc = 0.5 * (u[1:-1, 2:] + u[1:-1, 1:-1]) # # vcc = 0.5 * (v[2:, 1:-1] + v[1:-1, 1:-1]) # # speed = np.sqrt(ucc * ucc + vcc * vcc) # # uexact = 4 * 1.5 * ycc * (1 - ycc) # # plt.plot(uexact, ycc, '-k', label='exact') # # plt.plot(ucc[:, int(8 / dx)], ycc, '--', label='x = {}'.format(8)) # # plt.contourf(xcc, ycc, speed) # # plt.colorbar() # # plt.streamplot(xcc, ycc, ucc, vcc, color='black', density=0.75, linewidth=1.5) # # plt.contourf(xcc, ycc, psol[-1][1:-1, 1:-1]) # # plt.colorbar() # plt.show() count += 1 if return_stability: return True else: return True, [div_np1], True, unp1[1:-1, 2:-1].ravel() # from singleton_classes import ProbDescription # # # Uinlet = 1 # ν = 0.01 # probDescription = ProbDescription(N=[32,32],L=[1,1],μ =ν,dt = 0.005) # dx,dy = probDescription.dx, probDescription.dy # dt = min(0.25*dx*dx/ν,0.25*dy*dy/ν, 4.0*ν/Uinlet/Uinlet) # probDescription.set_dt(dt) # error_lid_driven_cavity_RK2 (steps = 2000,return_stability=False, name='heun', guess=None, project=[1],alpha=0.99)
def error_tv_time_dependent_bcs_RK2(steps=3, return_stability=False, name='', guess=None, project=[], theta=None): probDescription = sc.ProbDescription() f = func(probDescription) dt = probDescription.get_dt() μ = probDescription.get_mu() nx, ny = probDescription.get_gridPoints() dx, dy = probDescription.get_differential_elements() a = 2 * np.pi b = 2 * np.pi uexact = lambda a, b, x, y, t: 1 - np.cos(a * (x - t)) * np.sin(b * ( y - t)) * np.exp(-(a**2 + b**2) * μ * t) vexact = lambda a, b, x, y, t: 1 + np.sin(a * (x - t)) * np.cos(b * ( y - t)) * np.exp(-(a**2 + b**2) * μ * t) pexact = lambda x, y, t: ( -8 * np.sin(np.pi * t)**4 * np.sin(np.pi * y)**4 - 2 * np .sin(np.pi * t)**4 - 2 * np.sin(np.pi * y)**4 - 5 * np.cos( 2 * np.pi * t) / 2 + 5 * np.cos(4 * np.pi * t) / 8 - 5 * np.cos( 2 * np.pi * y) / 2 + 5 * np.cos(4 * np.pi * y) / 8 - np.cos( np.pi * (2 * t - 4 * y)) / 4 + np.cos(np.pi * (2 * t - 2 * y)) + np .cos(np.pi * (2 * t + 2 * y)) - np.cos(np.pi * (2 * t + 4 * y)) / 4 - 3 * np.cos(np.pi * (4 * t - 4 * y)) / 16 - np.cos(np.pi * (4 * t - 2 * y)) / 4 - np.cos(np.pi * (4 * t + 2 * y)) / 4 + np.cos(np.pi * (4 * t + 4 * y)) / 16 + 27 / 8) * np.exp(-16 * np.pi**2 * μ * t) - np.exp( -16 * np.pi**2 * μ * t) * np.cos(np.pi * (-4 * t + 4 * x)) / 4 t = 0.0 tend = steps count = 0 print('dt=', dt) xcc, ycc = probDescription.get_cell_centered() xu, yu = probDescription.get_XVol() xv, yv = probDescription.get_YVol() # initialize velocities - we stagger everything in the negative direction. A scalar cell owns its minus face, only. # Then, for example, the u velocity field has a ghost cell at x0 - dx and the plus ghost cell at lx u0 = np.zeros([ny + 2, nx + 2]) # include ghost cells u0[1:-1, 1:] = uexact(a, b, xu, yu, t) # initialize the interior of u0 # same thing for the y-velocity component v0 = np.zeros([ny + 2, nx + 2]) # include ghost cells v0[1:, 1:-1] = vexact(a, b, xv, yv, t) print('div_before_bcs= {}'.format(np.linalg.norm(f.div(u0, v0)))) # print('right wall :, yv= {}'.format(yv[:,-1])) u_bc_top_wall = lambda t: lambda xv: uexact(a, b, xu[-1, :], np.ones_like(xu[-1, :]), t) u_bc_bottom_wall = lambda t: lambda xv: uexact(a, b, xu[0, :], np.zeros_like(xu[0, :]), t) u_bc_right_wall = lambda t: lambda yv: uexact(a, b, xu[:, -1], yu[:, -1], t ) u_bc_left_wall = lambda t: lambda yv: uexact(a, b, xu[:, 0], yu[:, 0], t) v_bc_top_wall = lambda t: lambda xv: vexact(a, b, xv[-1, :], yv[-1, :], t) v_bc_bottom_wall = lambda t: lambda xv: vexact(a, b, xv[0, :], yv[0, :], t) v_bc_right_wall = lambda t: lambda yv: vexact(a, b, np.ones_like( yv[:, -1]), yv[:, -1], t) v_bc_left_wall = lambda t: lambda yv: vexact(a, b, np.zeros_like(yv[:, 0]), yv[:, 0], t) # plt.imshow(u0,origin='bottom') # plt.show() # pressure def pressure_bcs(p, t): # # right wall # p[1:-1,-1] = 2*pexact(np.ones_like(ycc[:,-1]),ycc[:,-1],t)/ np.sum(pexact(np.ones_like(ycc[:,-2]),ycc[:,-2],t).ravel()) *np.sum(p[1:-1,-2].ravel()) -p[1:-1,-2] # # left wall # p[1:-1,0] = 2*pexact(np.zeros_like(ycc[:,0]),ycc[:,0],t)/np.sum(pexact(np.zeros_like(ycc[:,1]),ycc[:,1],t).ravel())*np.sum(p[1:-1,1].ravel()) -p[1:-1,1] # # top wall # p[-1,1:-1] = 2*pexact(np.ones_like(ycc[-1,:]),ycc[-1,:],t)/np.sum(pexact(np.ones_like(ycc[-2,:]),ycc[-2,:],t).ravel())*np.sum(p[-2,1:-1].ravel()) - p[-2,1:-1] # # bottom wall # p[0, 1:-1] = 2 * pexact(np.zeros_like(ycc[0,:]),ycc[0,:],t)/np.sum(pexact(np.zeros_like(ycc[1,:]),ycc[1,:],t).ravel())*np.sum(p[1, 1:-1].ravel()) - p[1, 1:-1] # # try extrapolation # right wall p[1:-1, -1] = (p[1:-1, -2] - p[1:-1, -3]) + p[1:-1, -2] # left wall p[1:-1, 0] = -(p[1:-1, 2] - p[1:-1, 1]) + p[1:-1, 1] # top wall p[-1, 1:-1] = (p[-2, 1:-1] - p[-3, 1:-1]) + p[-2, 1:-1] # bottom wall p[0, 1:-1] = -(p[2, 1:-1] - p[1, 1:-1]) + p[1, 1:-1] p_bcs = lambda t: lambda p: pressure_bcs(p, t) # apply bcs f.top_wall(u0, v0, u_bc_top_wall(t), v_bc_top_wall(t)) f.bottom_wall(u0, v0, u_bc_bottom_wall(t), v_bc_bottom_wall(t)) f.right_wall(u0, v0, u_bc_right_wall(t), v_bc_right_wall(t)) f.left_wall(u0, v0, u_bc_left_wall(t), v_bc_left_wall(t)) print('div_after_bcs= {}'.format(np.linalg.norm(f.div(u0, v0)))) # plt.imshow(u0, origin='bottom') # plt.show() # initialize the pressure p0 = np.zeros([nx + 2, ny + 2]) # include ghost cells #declare unp1 unp1 = np.zeros_like(u0) vnp1 = np.zeros_like(v0) div_np1 = np.zeros_like(p0) # a bunch of lists for animation purposes usol = [] usol.append(u0) vsol = [] vsol.append(v0) psol = [] psol.append(p0) iterations = [0] Coef = f.A_Lid_driven_cavity() while count < tend: print('timestep:{}'.format(count + 1)) print('-----------') # rk coefficients RK2 = sc.RK2(name, theta=theta) a21 = RK2.a21 b1 = RK2.b1 b2 = RK2.b2 u = usol[-1].copy() v = vsol[-1].copy() pn = np.zeros_like(u) pnm1 = np.zeros_like(u) if count > 1: pn = psol[-1].copy() pnm1 = psol[-2].copy() f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name) d2, = project elif count <= 1: # compute pressures for 2 time steps d2 = 1 f1x, f1y = f.Guess([pn, pnm1], order=None, integ='RK2', type=name) ## stage 1 print(' Stage 1:') print(' --------') time_start = time.clock() u1 = u.copy() v1 = v.copy() # Au1 urhs1 = f.urhs_bcs(u1, v1) vrhs1 = f.vrhs_bcs(u1, v1) # divergence of u1 div_n = np.linalg.norm(f.div(u1, v1).ravel()) print(' divergence of u1 = ', div_n) ## stage 2 print(' Stage 2:') print(' --------') uh2 = u + a21 * dt * (urhs1 - f1x) vh2 = v + a21 * dt * (vrhs1 - f1y) f.top_wall(uh2, vh2, u_bc_top_wall(t + a21 * dt), v_bc_top_wall(t + a21 * dt)) f.bottom_wall(uh2, vh2, u_bc_bottom_wall(t + a21 * dt), v_bc_bottom_wall(t + a21 * dt)) f.right_wall(uh2, vh2, u_bc_right_wall(t + a21 * dt), v_bc_right_wall(t + a21 * dt)) f.left_wall(uh2, vh2, u_bc_left_wall(t + a21 * dt), v_bc_left_wall(t + a21 * dt)) if d2 == 1: print(' pressure projection stage{} = True'.format(2)) u2, v2, _, iter1 = f.ImQ_bcs(uh2, vh2, Coef, pn, p_bcs((t + a21 * dt))) print(' iterations stage 2 = ', iter1) elif d2 == 0: u2 = uh2 v2 = vh2 # apply bcs f.top_wall(u2, v2, u_bc_top_wall(t + a21 * dt), v_bc_top_wall(t + a21 * dt)) f.bottom_wall(u2, v2, u_bc_bottom_wall(t + a21 * dt), v_bc_bottom_wall(t + a21 * dt)) f.right_wall(u2, v2, u_bc_right_wall(t + a21 * dt), v_bc_right_wall(t + a21 * dt)) f.left_wall(u2, v2, u_bc_left_wall(t + a21 * dt), v_bc_left_wall(t + a21 * dt)) div2 = np.linalg.norm(f.div(u2, v2).ravel()) print(' divergence of u2 = ', div2) urhs2 = f.urhs_bcs(u2, v2) vrhs2 = f.vrhs_bcs(u2, v2) uhnp1 = u + dt * b1 * (urhs1) + dt * b2 * (urhs2) vhnp1 = v + dt * b1 * (vrhs1) + dt * b2 * (vrhs2) f.top_wall(uhnp1, vhnp1, u_bc_top_wall(t + dt), v_bc_top_wall(t + dt)) f.bottom_wall(uhnp1, vhnp1, u_bc_bottom_wall(t + dt), v_bc_bottom_wall(t + dt)) f.right_wall(uhnp1, vhnp1, u_bc_right_wall(t + dt), v_bc_right_wall(t + dt)) f.left_wall(uhnp1, vhnp1, u_bc_left_wall(t + dt), v_bc_left_wall(t + dt)) unp1, vnp1, press, iter2 = f.ImQ_bcs(uhnp1, vhnp1, Coef, pn, p_bcs(t + dt)) # apply bcs f.top_wall(unp1, vnp1, u_bc_top_wall(t + dt), v_bc_top_wall(t + dt)) f.bottom_wall(unp1, vnp1, u_bc_bottom_wall(t + dt), v_bc_bottom_wall(t + dt)) f.right_wall(unp1, vnp1, u_bc_right_wall(t + dt), v_bc_right_wall(t + dt)) f.left_wall(unp1, vnp1, u_bc_left_wall(t + dt), v_bc_left_wall(t + dt)) time_end = time.clock() psol.append(press) cpu_time = time_end - time_start print(' cpu_time=', cpu_time) # Check mass residual div_np1 = np.linalg.norm(f.div(unp1, vnp1).ravel()) residual = div_np1 # if residual > 1e-12: print(' Mass residual:', residual) print('iterations:', iter) # save new solutions usol.append(unp1) vsol.append(vnp1) iterations.append(iter) t += dt # plot of the pressure gradient in order to make sure the solution is correct # # plt.contourf(usol[-1][1:-1,1:]) # if count % 1 ==0: # # plt.imshow(unp1[1:-1,1:]-uexact(a,b,xu,yu,t),origin='bottom') # plt.imshow(unp1[1:-1,1:],origin='bottom') # plt.colorbar() # # divu = f.div(unp1,vnp1) # # plt.imshow(divu[1:-1,1:-1], origin='bottom') # # plt.colorbar() # # ucc = 0.5 * (u[1:-1, 2:] + u[1:-1, 1:-1]) # # vcc = 0.5 * (v[2:, 1:-1] + v[1:-1, 1:-1]) # # speed = np.sqrt(ucc * ucc + vcc * vcc) # # uexact = 4 * 1.5 * ycc * (1 - ycc) # # plt.plot(uexact, ycc, '-k', label='exact') # # plt.plot(ucc[:, int(8 / dx)], ycc, '--', label='x = {}'.format(8)) # # plt.contourf(xcc, ycc, speed) # # plt.colorbar() # # plt.streamplot(xcc, ycc, ucc, vcc, color='black', density=0.75, linewidth=1.5) # # plt.contourf(xcc, ycc, psol[-1][1:-1, 1:-1]) # # plt.colorbar() # plt.show() count += 1 if return_stability: return True else: return True, [div_np1], True, unp1[1:-1, 1:-1].ravel() # from singleton_classes import ProbDescription # # # Uinlet = 1 # ν = 0.01 # probDescription = ProbDescription(N=[32,32],L=[1,1],μ =ν,dt = 0.005) # dx,dy = probDescription.dx, probDescription.dy # dt = min(0.25*dx*dx/ν,0.25*dy*dy/ν, 4.0*ν/Uinlet/Uinlet) # print('dt = ',dt) # probDescription.set_dt(0.001) # error_tv_time_dependent_bcs_RK2(steps = 200,return_stability=False, name='midpoint', guess=None, project=[1],theta=None)
def error_normal_velocity_bcs_RK2(steps=3, return_stability=False, name='heun', guess=None, project=[], theta=None): probDescription = sc.ProbDescription() f = func(probDescription) dt = probDescription.get_dt() μ = probDescription.get_mu() nx, ny = probDescription.get_gridPoints() dx, dy = probDescription.get_differential_elements() t = 0.0 tend = steps count = 0 print('dt=', dt) xcc, ycc = probDescription.get_cell_centered() xu, yu = probDescription.get_XVol() xv, yv = probDescription.get_YVol() # initialize velocities - we stagger everything in the negative direction. A scalar cell owns its minus face, only. # Then, for example, the u velocity field has a ghost cell at x0 - dx and the plus ghost cell at lx np.random.seed(123) mag = 10 u0 = np.random.rand(ny + 2, nx + 2) * mag # include ghost cells print(np.max(np.max(u0))) # u0 = np.zeros([ny +2, nx+2])# include ghost cells # same thing for the y-velocity component # v0 = np.zeros([ny + 2, nx + 2]) # include ghost cells v0 = np.random.rand(ny + 2, nx + 2) * mag # include ghost cells Min = np.sum(np.ones_like(u0[1:ny + 1, 1])) Mout = np.sum(8 * (yu[:ny + 1, 1] - yu[:ny + 1, 1]**2)) u_bc_top_wall = lambda xv: 0 u_bc_bottom_wall = lambda xv: 0 # u_bc_right_wall = lambda Mout:lambda yv: 8*(yu[:ny+1,1]-yu[:ny+1,1]**2)*Min/Mout u_bc_right_wall = lambda yv: 8 * (yu[:ny + 1, 1] - yu[:ny + 1, 1]**2 ) * Min / np.sum(8 * (yu[:ny + 1, 1] - yu[:ny + 1, 1]**2)) # u_bc_left_wall = lambda yv: 8*(yu[:ny+1,1]-yu[:ny+1,1]**2) u_bc_left_wall = lambda yv: 1 v_bc_top_wall = lambda xv: 0 v_bc_bottom_wall = lambda xv: 0 v_bc_right_wall = lambda yv: 0 v_bc_left_wall = lambda yv: 0 # pressure def p_bcs(p): p[1:ny + 1, nx + 1] = p[1:ny + 1, nx] p[1:ny + 1, 0] = p[1:ny + 1, 1] # apply bcs f.top_wall(u0, v0, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u0, v0, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u0, v0, u_bc_right_wall, v_bc_right_wall) f.left_wall(u0, v0, u_bc_left_wall, v_bc_left_wall) Coef = f.A_Lid_driven_cavity() # # plot # # ------------------------------------------- # ucc0 = 0.5 * (u0[1:-1, 2:] + u0[1:-1, 1:-1]) # vcc0 = 0.5 * (v0[2:, 1:-1] + v0[1:-1, 1:-1]) # speed0 = np.sqrt(ucc0 * ucc0 + vcc0 * vcc0) # # fig = plt.figure(figsize=(6.5, 4.01)) # ax = plt.axes() # # velocity_mag0 = ax.pcolormesh(xcc, ycc, speed0) # div0 = ax.pcolormesh(xcc, ycc, f.div(u0, v0)[1:-1, 1:-1]) # # add_colorbar(velocity_mag0,aspect=5 ) # add_colorbar(div0, aspect=5) # # name = 'vel_mag.pdf' # name = 'div_non_div_free_Ic.pdf' # # vel = True # vel = False # # if vel: # Q = ax.quiver(xcc[::1, ::10], ycc[::1, ::10], ucc0[::1, ::10], vcc0[::1, ::10], # pivot='mid', units='inches', scale=5) # key = ax.quiverkey(Q, X=0.3, Y=1.05, U=1, # label='Quiver key, length = 1m/s', labelpos='E') # # plt.savefig('./initial_cond/poisseille_flow/mag_{}/{}'.format(mag,name),dpi=300) # plt.show() u0_free, v0_free, phi, _ = f.ImQ_bcs(u0, v0, Coef, 0, p_bcs) f.top_wall(u0_free, v0_free, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u0_free, v0_free, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u0_free, v0_free, u_bc_right_wall, v_bc_right_wall) f.left_wall(u0_free, v0_free, u_bc_left_wall, v_bc_left_wall) print('div_u0=', np.linalg.norm(f.div(u0_free, v0_free).ravel())) # # plot # # ------------------------------------------- # ucc0 = 0.5 * (u0_free[1:-1, 2:] + u0_free[1:-1, 1:-1]) # vcc0 = 0.5 * (v0_free[2:, 1:-1] + v0_free[1:-1, 1:-1]) # speed0 = np.sqrt(ucc0 * ucc0 + vcc0 * vcc0) # # fig = plt.figure(figsize=(6.5, 4.01)) # ax = plt.axes() # # velocity_mag0 = ax.pcolormesh(xcc, ycc, speed0) # # div0 = ax.pcolormesh(xcc, ycc,f.div(u0_free, v0_free)[1:-1,1:-1]) # phi_free = ax.pcolormesh(xcc, ycc, phi[1:-1, 1:-1]) # # add_colorbar(velocity_mag0, aspect=5) # # add_colorbar(div0, aspect=5) # add_colorbar(phi_free, aspect=5) # # vel = True # vel = False # # name = 'div_free_vel.pdf' # # name = "divergence_new_vel.pdf" # name = 'phi.pdf' # # for velocity mag only # if vel: # Q = ax.quiver(xcc[::1, ::10], ycc[::1, ::10], ucc0[::1, ::10], vcc0[::1, ::10], # pivot='mid', units='inches', scale=5) # key = ax.quiverkey(Q, X=0.3, Y=1.05, U=1, # label='Quiver key, length = 1m/s', labelpos='E') # # plt.savefig('./initial_cond/poisseille_flow/mag_{}/{}'.format(mag, name), dpi=300) # plt.show() # # ------------------------------------------------------------------------ # initialize the pressure p0 = np.zeros([nx + 2, ny + 2]) # include ghost cells #declare unp1 unp1 = np.zeros_like(u0) vnp1 = np.zeros_like(v0) div_np1 = np.zeros_like(p0) # a bunch of lists for animation purposes usol = [] # usol.append(u0) usol.append(u0_free) vsol = [] # vsol.append(v0) vsol.append(v0_free) psol = [] psol.append(p0) iterations = [0] while count < tend: print('timestep:{}'.format(count + 1)) print('-----------') # rk coefficients RK2 = sc.RK2(name, theta=theta) a21 = RK2.a21 b1 = RK2.b1 b2 = RK2.b2 print('a21={}, b1={}, b2={}'.format(a21, b1, b2)) u = usol[-1].copy() v = vsol[-1].copy() pn = np.zeros_like(u) pnm1 = np.zeros_like(u) if count > 1: pn = psol[-1].copy() pnm1 = psol[-2].copy() f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name) d2, = project elif count <= 1: # compute pressures for 2 time steps d2 = 1 f1x, f1y = f.Guess([pn, pnm1], order=None, integ='RK2', type=name) ## stage 1 print(' Stage 1:') print(' --------') time_start = time.clock() u1 = u.copy() v1 = v.copy() # Au1 urhs1 = f.urhs_bcs(u1, v1) vrhs1 = f.vrhs_bcs(u1, v1) # divergence of u1 div_n = np.linalg.norm(f.div(u1, v1).ravel()) print(' divergence of u1 = ', div_n) ## stage 2 print(' Stage 2:') print(' --------') uh2 = u + a21 * dt * (urhs1 - f1x) vh2 = v + a21 * dt * (vrhs1 - f1y) f.top_wall(uh2, vh2, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(uh2, vh2, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(uh2, vh2, u_bc_right_wall, v_bc_right_wall) f.left_wall(uh2, vh2, u_bc_left_wall, v_bc_left_wall) if d2 == 1: print(' pressure projection stage{} = True'.format(2)) u2, v2, _, iter1 = f.ImQ_bcs(uh2, vh2, Coef, pn, p_bcs) print(' iterations stage 2 = ', iter1) elif d2 == 0: u2 = uh2 v2 = vh2 # apply bcs f.top_wall(u2, v2, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(u2, v2, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(u2, v2, u_bc_right_wall, v_bc_right_wall) f.left_wall(u2, v2, u_bc_left_wall, v_bc_left_wall) div2 = np.linalg.norm(f.div(u2, v2).ravel()) print(' divergence of u2 = ', div2) urhs2 = f.urhs_bcs(u2, v2) vrhs2 = f.vrhs_bcs(u2, v2) uhnp1 = u + dt * b1 * (urhs1) + dt * b2 * (urhs2) vhnp1 = v + dt * b1 * (vrhs1) + dt * b2 * (vrhs2) # apply bcs f.top_wall(uhnp1, vhnp1, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(uhnp1, vhnp1, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(uhnp1, vhnp1, u_bc_right_wall, v_bc_right_wall) f.left_wall(uhnp1, vhnp1, u_bc_left_wall, v_bc_left_wall) unp1, vnp1, press, iter2 = f.ImQ_bcs(uhnp1, vhnp1, Coef, pn, p_bcs) # apply bcs f.top_wall(unp1, vnp1, u_bc_top_wall, v_bc_top_wall) f.bottom_wall(unp1, vnp1, u_bc_bottom_wall, v_bc_bottom_wall) f.right_wall(unp1, vnp1, u_bc_right_wall, v_bc_right_wall) f.left_wall(unp1, vnp1, u_bc_left_wall, v_bc_left_wall) time_end = time.clock() psol.append(press) cpu_time = time_end - time_start print(' cpu_time=', cpu_time) # Check mass residual div_np1 = np.linalg.norm(f.div(unp1, vnp1).ravel()) residual = div_np1 # if residual > 1e-12: print(' Mass residual:', residual) print('iterations:', iter) # save new solutions usol.append(unp1) vsol.append(vnp1) iterations.append(iter) print("Min=", Min) print("Mout=", np.sum(unp1[1:ny + 1, nx + 1])) # print('dp/dx=', (press[16,nx] - press[16,1])/10) t += dt # plot of the pressure gradient in order to make sure the solution is correct # # plt.contourf(usol[-1][1:-1,1:]) # if count % 100 ==0: # divu = f.div(u0_free,v0_free) # # plt.imshow(divu[1:-1,1:-1], origin='bottom') # # plt.colorbar() # ucc = 0.5 * (u[1:-1, 2:] + u[1:-1, 1:-1]) # vcc = 0.5 * (v[2:, 1:-1] + v[1:-1, 1:-1]) # speed = np.sqrt(ucc * ucc + vcc * vcc) # # uexact = 4 * 1.5 * ycc * (1 - ycc) # # plt.plot(uexact, ycc, '-k', label='exact') # # plt.plot(ucc[:, int(8 / dx)], ycc, '--', label='x = {}'.format(8)) # # plt.contourf(xcc, ycc, press[1:-1,1:-1]) # plt.contourf(xcc, ycc, speed) # plt.colorbar() # # plt.streamplot(xcc, ycc, ucc, vcc, color='black', density=0.75, linewidth=1.5) # # plt.contourf(xcc, ycc, psol[-1][1:-1, 1:-1]) # # plt.colorbar() # plt.show() count += 1 if return_stability: return True else: return True, [div_np1], True, unp1[1:-1, 1:-1].ravel() # # from singleton_classes import ProbDescription # # # Uinlet = 1 # ν = 0.1 # probDescription = ProbDescription(N=[4*32,32],L=[10,1],μ =ν,dt = 0.005) # dx,dy = probDescription.dx, probDescription.dy # dt = min(0.25*dx*dx/ν,0.25*dy*dy/ν, 4.0*ν/Uinlet/Uinlet) # probDescription.set_dt(dt) # error_normal_velocity_bcs_RK2 (steps = 1,return_stability=False, name='heun', guess=None, project=[1])
def error_RK2(steps=3, return_stability=False, name='heun', guess=None, project=[1],alpha=0.9,theta=None): # problem description probDescription = sc.ProbDescription() f = func(probDescription,'periodic') dt = probDescription.get_dt() μ = probDescription.get_mu() nx, ny = probDescription.get_gridPoints() dx, dy = probDescription.get_differential_elements() # define exact solutions a = 2 * np.pi b = 2 * np.pi uf = 1 vf = 1 uexact = lambda a, b, x, y, t: uf - np.cos(a * (x - uf * t)) * np.sin(b * (y - vf * t)) * np.exp( -(a ** 2 + b ** 2) * μ * t) vexact = lambda a, b, x, y, t: vf + np.sin(a * (x - uf * t)) * np.cos(b * (y - vf * t)) * np.exp( -(a ** 2 + b ** 2) * μ * t) pexact=lambda x,y,t: (-8 * np.sin(np.pi * t) ** 4 * np.sin(np.pi * y) ** 4 - 2 * np.sin(np.pi * t) ** 4 - 2 * np.sin(np.pi * y) ** 4 - 5 * np.cos( 2 * np.pi * t) / 2 + 5 * np.cos(4 * np.pi * t) / 8 - 5 * np.cos(2 * np.pi * y) / 2 + 5 * np.cos(4 * np.pi * y) / 8 - np.cos( np.pi * (2 * t - 4 * y)) / 4 + np.cos(np.pi * (2 * t - 2 * y)) + np.cos(np.pi * (2 * t + 2 * y)) - np.cos( np.pi * (2 * t + 4 * y)) / 4 - 3 * np.cos(np.pi * (4 * t - 4 * y)) / 16 - np.cos(np.pi * (4 * t - 2 * y)) / 4 - np.cos( np.pi * (4 * t + 2 * y)) / 4 + np.cos(np.pi * (4 * t + 4 * y)) / 16 + 27 / 8) * np.exp(-16 * np.pi ** 2 * μ * t) - np.exp( -16 * np.pi ** 2 * μ * t) * np.cos(np.pi * (-4 * t + 4 * x)) / 4 dpdxexact = lambda x,t:-np.pi*np.exp(-16*np.pi**2*μ*t)*np.sin(np.pi*(4*t - 4*x)) # # define some boiler plate t = 0.0 tend = steps count = 0 print('dt=', dt) xcc, ycc = probDescription.get_cell_centered() xu, yu = probDescription.get_XVol() xv, yv = probDescription.get_YVol() # initialize velocities - we stagger everything in the negative direction. A scalar cell owns its minus face, only. # Then, for example, the u velocity field has a ghost cell at x0 - dx and the plus ghost cell at lx u0 = np.zeros([ny + 2, nx + 2]) # include ghost cells u0[1:-1, 1:] = uexact(a, b, xu, yu, 0) # initialize the interior of u0 # same thing for the y-velocity component v0 = np.zeros([ny + 2, nx + 2]) # include ghost cells v0[1:, 1:-1] = vexact(a, b, xv, yv, 0) f.periodic_u(u0) f.periodic_v(v0) # initialize the pressure p0 = np.zeros([nx + 2, ny + 2]); # include ghost cells # declare unp1 unp1 = np.zeros_like(u0) vnp1 = np.zeros_like(v0) div_np1 = np.zeros_like(p0) # a bunch of lists for animation purposes usol = [] usol.append(u0) vsol = [] vsol.append(v0) psol = [] psol.append(p0) iterations = [] Coef = scipy.sparse.csr_matrix.toarray(f.A()) is_stable = True # # u and v num cell centered ucc = 0.5 * (u0[1:-1, 2:] + u0[1:-1, 1:-1]) vcc = 0.5 * (v0[2:, 1:-1] + v0[1:-1, 1:-1]) uexc = uexact(a, b, xu, yu, t) vexc = vexact(a, b, xv, yv, t) # u and v exact cell centered uexc_cc = 0.5 * (uexc[:, :-1] + uexc[:, 1:]) vexc_cc = 0.5 * (vexc[:-1, :] + vexc[1:, :]) # compute of kinetic energy ken_new = np.sum(ucc.ravel() ** 2 + vcc.ravel() ** 2) / 2 ken_exact = np.sum(uexc_cc.ravel() ** 2 + vexc_cc.ravel() ** 2) / 2 ken_old = ken_new final_KE = nx * ny target_ke = ken_exact - alpha * (ken_exact - final_KE) print('time = ', t) print('ken_new = ', ken_new) print('ken_exc = ', ken_exact) stability_counter = 0 iteration_i_2 = 0 iteration_np1 = 0 while count < tend: print('timestep:{}'.format(count + 1)) print('-----------') # rk coefficients RK2 = sc.RK2(name,theta) a21 = RK2.a21 b1 = RK2.b1 b2 = RK2.b2 u = usol[-1].copy() v = vsol[-1].copy() pn = np.zeros_like(u) pnm1 = np.zeros_like(u) # pnm2 = np.zeros_like(u) if count > 1: # change to 2 if high order pressure is needed pn = psol[-1].copy() pnm1 = psol[-2].copy() # pnm2 = psol[-3].copy()# only needed for high order pressure f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name,theta=theta) d2, = project elif count <= 1: # compute pressures for 2 time steps # change to 2 if high order pressure is needed d2 = 1 f1x, f1y = f.Guess([pn, pnm1], order=None, integ='RK2', type=name,theta=theta) iteration_i_2 = 0 iteration_np1 = 0 ## stage 1 print(' Stage 1:') print(' --------') time_start = time.clock() u1 = u.copy() v1 = v.copy() # Au1 urhs1 = f.urhs(u1, v1) vrhs1 = f.vrhs(u1, v1) # divergence of u1 div_n = np.linalg.norm(f.div(u1, v1).ravel()) print(' divergence of u1 = ', div_n) ## stage 2 print(' Stage 2:') print(' --------') uh2 = u + a21 * dt * (urhs1 - f1x) vh2 = v + a21 * dt * (vrhs1 - f1y) if d2 == 1: print(' pressure projection stage{} = True'.format(2)) u2, v2, press_stage_2, iter1 = f.ImQ(uh2, vh2, Coef, pn) # u2, v2, press_stage_2, iter1 = f.ImQ(uh2, vh2, Coef, (3*pn-pnm1)/2,tol=1e-10) iteration_i_2 +=iter1 print(' iterations stage 2 = ', iter1) elif d2 == 0: u2 = uh2 v2 = vh2 div2 = np.linalg.norm(f.div(u2, v2).ravel()) print(' divergence of u2 = ', div2) urhs2 = f.urhs(u2, v2) vrhs2 = f.vrhs(u2, v2) uhnp1 = u + dt * b1 * (urhs1) + dt * b2 * (urhs2) vhnp1 = v + dt * b1 * (vrhs1) + dt * b2 * (vrhs2) unp1, vnp1, press, iter2 = f.ImQ(uhnp1, vhnp1, Coef, pn,tol=1e-10) # unp1, vnp1, press, iter2 = f.ImQ(uhnp1, vhnp1, Coef, (3*pn-pnm1)/2,atol=1e-6,tol=1e-16) # midpoint # unp1, vnp1, press, iter2 = f.ImQ(uhnp1, vhnp1, Coef, press_stage_2) # new_press = 4*pn -9*pnm1/ 2 +3 * pnm2 / 2 #second order (working) iteration_np1+=iter2 # # post processing projection # unp1r = dt * f.urhs(unp1, vnp1) # vnp1r = dt * f.vrhs(unp1, vnp1) # # _, _, press, _ = f.ImQ_post_processing(unp1r, vnp1r, Coef, press) time_end = time.clock() psol.append(press) cpu_time = time_end - time_start print('cpu_time=', cpu_time) # Check mass residual div_np1 = np.linalg.norm(f.div(unp1, vnp1).ravel()) residual = div_np1 # if residual > 1e-12: print('Mass residual:', residual) print('iterations last stage:', iter2) # save new solutions usol.append(unp1) vsol.append(vnp1) iterations.append(iter1 + iter2) # # u and v num cell centered ucc = 0.5 * (u[1:-1, 2:] + u[1:-1, 1:-1]) vcc = 0.5 * (v[2:, 1:-1] + v[1:-1, 1:-1]) uexc = uexact(a, b, xu, yu, t) vexc = vexact(a, b, xv, yv, t) # u and v exact cell centered uexc_cc = 0.5 * (uexc[:, :-1] + uexc[:, 1:]) vexc_cc = 0.5 * (vexc[:-1, :] + vexc[1:, :]) t += dt # compute of kinetic energy ken_new = np.sum(ucc.ravel() ** 2 + vcc.ravel() ** 2) / 2 ken_exact = np.sum(uexc_cc.ravel() ** 2 + vexc_cc.ravel() ** 2) / 2 print('time = ', t) print('ken_new = ', ken_new) print('target_ken=', target_ke) print('ken_exc = ', ken_exact) print('(ken_new - ken_old)/ken_old = ', (ken_new - ken_old) / ken_old) if (((ken_new - ken_old) / ken_old) > 0 and count > 1) or np.isnan(ken_new): is_stable = False print('is_stable = ', is_stable) if stability_counter > 5: print('not stable !!!!!!!!') break else: stability_counter += 1 else: is_stable = True print('is_stable = ', is_stable) if ken_new < target_ke and count > 30: break ken_old = ken_new.copy() print('is_stable = ', is_stable) # plot of the pressure gradient in order to make sure the solution is correct # # plt.contourf(usol[-1][1:-1,1:]) gradpx = (psol[-1][1:-1, 1:] - psol[-1][1:-1, :-1]) / dx maxbound = max(gradpx[1:-1, 1:].ravel()) minbound = min(gradpx[1:-1, 1:].ravel()) # plot of the pressure gradient in order to make sure the solution is correct # if count%10 == 0: # plt.imshow(gradpx[1:-1,1:],origin='bottom',cmap='jet',vmax=maxbound, vmin=minbound) # # plt.contourf((psol[-1][1:-1,1:] - psol[-1][1:-1,:-1])/dx) # v = np.linspace(minbound, maxbound, 4, endpoint=True) # plt.colorbar(ticks=v) # plt.title('time: {}'.format(t)) # plt.show() count += 1 diff = np.linalg.norm(uexact(a, b, xu, yu, t).ravel() - unp1[1:-1, 1:].ravel(), np.inf) print(' error={}'.format(diff)) if return_stability: return is_stable else: return diff, [iteration_i_2, iteration_np1], is_stable, unp1[1:-1, 1:].ravel()
def error_RK2_with_post_projection(steps=3, return_stability=False, name='heun', guess=None, project=[1], alpha=0.9, post_projection=False, save_to=None, refNum=None, ml_model=None, ml_weights=None): # problem description probDescription = sc.ProbDescription() f = func(probDescription, 'periodic') dt = probDescription.get_dt() μ = probDescription.get_mu() nx, ny = probDescription.get_gridPoints() dx, dy = probDescription.get_differential_elements() # define exact solutions a = 2 * np.pi b = 2 * np.pi uf = 1 vf = 1 uexact = lambda a, b, x, y, t: uf - np.cos(a * (x - uf * t)) * np.sin(b * ( y - vf * t)) * np.exp(-(a**2 + b**2) * μ * t) vexact = lambda a, b, x, y, t: vf + np.sin(a * (x - uf * t)) * np.cos(b * ( y - vf * t)) * np.exp(-(a**2 + b**2) * μ * t) # # define some boiler plate t = 0.0 tend = steps count = 0 print('dt=', dt) xcc, ycc = probDescription.get_cell_centered() xu, yu = probDescription.get_XVol() xv, yv = probDescription.get_YVol() # initialize velocities - we stagger everything in the negative direction. A scalar cell owns its minus face, only. # Then, for example, the u velocity field has a ghost cell at x0 - dx and the plus ghost cell at lx u0 = np.zeros([ny + 2, nx + 2]) # include ghost cells u0[1:-1, 1:] = uexact(a, b, xu, yu, 0) # initialize the interior of u0 # same thing for the y-velocity component v0 = np.zeros([ny + 2, nx + 2]) # include ghost cells v0[1:, 1:-1] = vexact(a, b, xv, yv, 0) f.periodic_u(u0) f.periodic_v(v0) # initialize the pressure p0 = np.zeros([nx + 2, ny + 2]) # include ghost cells # declare unp1 unp1 = np.zeros_like(u0) vnp1 = np.zeros_like(v0) div_np1 = np.zeros_like(p0) # a bunch of lists for animation purposes usol = [] usol.append(u0) vsol = [] vsol.append(v0) psol = [] psol.append(p0) iterations = [] Coef = f.A() is_stable = True # # u and v num cell centered ucc = 0.5 * (u0[1:-1, 2:] + u0[1:-1, 1:-1]) vcc = 0.5 * (v0[2:, 1:-1] + v0[1:-1, 1:-1]) uexc = uexact(a, b, xu, yu, t) vexc = vexact(a, b, xv, yv, t) # u and v exact cell centered uexc_cc = 0.5 * (uexc[:, :-1] + uexc[:, 1:]) vexc_cc = 0.5 * (vexc[:-1, :] + vexc[1:, :]) # compute of kinetic energy ken_new = np.sum(ucc.ravel()**2 + vcc.ravel()**2) / 2 ken_exact = np.sum(uexc_cc.ravel()**2 + vexc_cc.ravel()**2) / 2 ken_old = ken_new final_KE = nx * ny target_ke = ken_exact - alpha * (ken_exact - final_KE) print('time = ', t) print('ken_new = ', ken_new) print('ken_exc = ', ken_exact) stability_counter = 0 while count < tend: print('timestep:{}'.format(count + 1)) print('-----------') # rk coefficients RK2 = sc.RK2(name) a21 = RK2.a21 b1 = RK2.b1 b2 = RK2.b2 u = usol[-1].copy() v = vsol[-1].copy() pn = np.zeros_like(u) pnm1 = np.zeros_like(u) if count > 1: pn = psol[-1].copy() pnm1 = psol[-2].copy() if ml_model != None and ml_weights != None: f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name, ml_model=ml_model, ml_weights=ml_weights) else: f1x, f1y = f.Guess([pn, pnm1], order=guess, integ='RK2', type=name) d2, = project elif count <= 1: # compute pressures for 2 time steps d2 = 1 f1x, f1y = f.Guess([pn, pnm1], order=None, integ='RK2', type=name) ## stage 1 print(' Stage 1:') print(' --------') time_start = time.clock() u1 = u.copy() v1 = v.copy() # Au1 urhs1 = f.urhs(u1, v1) vrhs1 = f.vrhs(u1, v1) # divergence of u1 div_n = np.linalg.norm(f.div(u1, v1).ravel()) print(' divergence of u1 = ', div_n) ## stage 2 print(' Stage 2:') print(' --------') uh2 = u + a21 * dt * (urhs1 - f1x) vh2 = v + a21 * dt * (vrhs1 - f1y) if d2 == 1: print(' pressure projection stage{} = True'.format(2)) u2, v2, _, iter1 = f.ImQ(uh2, vh2, Coef, pn) print(' iterations stage 2 = ', iter1) elif d2 == 0: u2 = uh2 v2 = vh2 div2 = np.linalg.norm(f.div(u2, v2).ravel()) print(' divergence of u2 = ', div2) urhs2 = f.urhs(u2, v2) vrhs2 = f.vrhs(u2, v2) uhnp1 = u + dt * b1 * (urhs1) + dt * b2 * (urhs2) vhnp1 = v + dt * b1 * (vrhs1) + dt * b2 * (vrhs2) unp1, vnp1, press, iter2 = f.ImQ(uhnp1, vhnp1, Coef, pn) if save_to != None and refNum != None: path = save_to + "/" + str(refNum) + "/p" pathlib.Path(path).mkdir(parents=True, exist_ok=True) np.save(path + "/{:04d}.npy".format(count + 1), press[1:-1, 1:-1].ravel()) if post_projection: # post processing projection uhnp1_star = u + dt * (f.urhs(unp1, vnp1)) vhnp1_star = v + dt * (f.vrhs(unp1, vnp1)) _, _, post_press, _ = f.ImQ(uhnp1_star, vhnp1_star, Coef, pn) if save_to != None and refNum != None: path = save_to + "/" + str(refNum) + "/p_star" pathlib.Path(path).mkdir(parents=True, exist_ok=True) np.save(path + "/{:04d}.npy".format(count + 1), post_press[1:-1, 1:-1].ravel()) time_end = time.clock() psol.append(press) cpu_time = time_end - time_start print('cpu_time=', cpu_time) # Check mass residual div_np1 = np.linalg.norm(f.div(unp1, vnp1).ravel()) residual = div_np1 # if residual > 1e-12: print('Mass residual:', residual) print('iterations last stage:', iter2) # save new solutions usol.append(unp1) vsol.append(vnp1) iterations.append(iter1 + iter2) # # u and v num cell centered ucc = 0.5 * (u[1:-1, 2:] + u[1:-1, 1:-1]) vcc = 0.5 * (v[2:, 1:-1] + v[1:-1, 1:-1]) uexc = uexact(a, b, xu, yu, t) vexc = vexact(a, b, xv, yv, t) # u and v exact cell centered uexc_cc = 0.5 * (uexc[:, :-1] + uexc[:, 1:]) vexc_cc = 0.5 * (vexc[:-1, :] + vexc[1:, :]) t += dt # compute of kinetic energy ken_new = np.sum(ucc.ravel()**2 + vcc.ravel()**2) / 2 ken_exact = np.sum(uexc_cc.ravel()**2 + vexc_cc.ravel()**2) / 2 print('time = ', t) print('ken_new = ', ken_new) print('target_ken=', target_ke) print('ken_exc = ', ken_exact) print('(ken_new - ken_old)/ken_old = ', (ken_new - ken_old) / ken_old) if (((ken_new - ken_old) / ken_old) > 0 and count > 1) or np.isnan(ken_new): is_stable = False print('is_stable = ', is_stable) if stability_counter > 5: print('not stable !!!!!!!!') break else: stability_counter += 1 else: is_stable = True print('is_stable = ', is_stable) if ken_new < target_ke and count > 30: break ken_old = ken_new.copy() print('is_stable = ', is_stable) ken_old = ken_new.copy() print('is_stable = ', is_stable) # plot of the pressure gradient in order to make sure the solution is correct # # plt.contourf(usol[-1][1:-1,1:]) gradpx = (psol[-1][1:-1, 1:] - psol[-1][1:-1, :-1]) / dx maxbound = max(gradpx[1:-1, 1:].ravel()) minbound = min(gradpx[1:-1, 1:].ravel()) # plot of the pressure gradient in order to make sure the solution is correct # if count%10 == 0: # plt.imshow(gradpx[1:-1,1:],origin='bottom',cmap='jet',vmax=maxbound, vmin=minbound) # # plt.contourf((psol[-1][1:-1,1:] - psol[-1][1:-1,:-1])/dx) # v = np.linspace(minbound, maxbound, 4, endpoint=True) # plt.colorbar(ticks=v) # plt.title('time: {}'.format(t)) # plt.show() count += 1 diff = np.linalg.norm( uexact(a, b, xu, yu, t).ravel() - unp1[1:-1, 1:].ravel(), np.inf) print(' error={}'.format(diff)) if return_stability: return is_stable else: return diff, [div_n, div2, div_np1], is_stable, unp1[1:-1, 1:].ravel()