def evolve(self, dt): """ Evolve the incompressible equations through one timestep. """ u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") gradp_x = self.cc_data.get_var("gradp_x") gradp_y = self.cc_data.get_var("gradp_y") phi = self.cc_data.get_var("phi") myg = self.cc_data.grid dtdx = dt / myg.dx dtdy = dt / myg.dy #--------------------------------------------------------------------- # create the limited slopes of u and v (in both directions) #--------------------------------------------------------------------- limiter = self.rp.get_param("incompressible.limiter") if (limiter == 0): limitFunc = reconstruction_f.nolimit elif (limiter == 1): limitFunc = reconstruction_f.limit2 else: limitFunc = reconstruction_f.limit4 ldelta_ux = limitFunc(1, u, myg.qx, myg.qy, myg.ng) ldelta_vx = limitFunc(1, v, myg.qx, myg.qy, myg.ng) ldelta_uy = limitFunc(2, u, myg.qx, myg.qy, myg.ng) ldelta_vy = limitFunc(2, v, myg.qx, myg.qy, myg.ng) #--------------------------------------------------------------------- # get the advective velocities #--------------------------------------------------------------------- """ the advective velocities are the normal velocity through each cell interface, and are defined on the cell edges, in a MAC type staggered form n+1/2 v i,j+1/2 +------+------+ | | n+1/2 | | n+1/2 u + U + u i-1/2,j | i,j | i+1/2,j | | +------+------+ n+1/2 v i,j-1/2 """ # this returns u on x-interfaces and v on y-interfaces. These # constitute the MAC grid print(" making MAC velocities") u_MAC, v_MAC = incomp_interface_f.mac_vels(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x, gradp_y) #--------------------------------------------------------------------- # do a MAC projection ot make the advective velocities divergence # free #--------------------------------------------------------------------- # we will solve L phi = D U^MAC, where phi is cell centered, and # U^MAC is the MAC-type staggered grid of the advective # velocities. print(" MAC projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type=self.cc_data.BCs["phi-MAC"].xlb, xr_BC_type=self.cc_data.BCs["phi-MAC"].xrb, yl_BC_type=self.cc_data.BCs["phi-MAC"].ylb, yr_BC_type=self.cc_data.BCs["phi-MAC"].yrb, xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU divU = mg.soln_grid.scratch_array() # MAC velocities are edge-centered. divU is cell-centered. divU[mg.ilo:mg.ihi+1,mg.jlo:mg.jhi+1] = \ (u_MAC[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - u_MAC[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx + \ (v_MAC[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - v_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1])/myg.dy # solve the Poisson problem mg.init_zeros() mg.init_RHS(divU) mg.solve(rtol=1.e-12) # update the normal velocities with the pressure gradient -- these # constitute our advective velocities phi_MAC = self.cc_data.get_var("phi-MAC") solution = mg.get_solution() phi_MAC[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] = \ solution[mg.ilo-1:mg.ihi+2,mg.jlo-1:mg.jhi+2] # we need the MAC velocities on all edges of the computational domain u_MAC[myg.ilo:myg.ihi+2,myg.jlo:myg.jhi+1] -= \ (phi_MAC[myg.ilo :myg.ihi+2,myg.jlo:myg.jhi+1] - phi_MAC[myg.ilo-1:myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx v_MAC[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+2] -= \ (phi_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+2] - phi_MAC[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi+1])/myg.dy #--------------------------------------------------------------------- # recompute the interface states, using the advective velocity # from above #--------------------------------------------------------------------- print(" making u, v edge states") u_xint, v_xint, u_yint, v_yint = \ incomp_interface_f.states(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x, gradp_y, u_MAC, v_MAC) #--------------------------------------------------------------------- # update U to get the provisional velocity field #--------------------------------------------------------------------- print(" doing provisional update of u, v") # compute (U.grad)U # we want u_MAC U_x + v_MAC U_y advect_x = myg.scratch_array() advect_y = myg.scratch_array() advect_x[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(u_MAC[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1] + u_MAC[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1]) * \ (u_xint[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - u_xint[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx + \ 0.5*(v_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1] + v_MAC[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2]) * \ (u_yint[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - u_yint[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1])/myg.dy advect_y[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(u_MAC[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1] + u_MAC[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1]) * \ (v_xint[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - v_xint[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx + \ 0.5*(v_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1] + v_MAC[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2]) * \ (v_yint[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - v_yint[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1])/myg.dy proj_type = self.rp.get_param("incompressible.proj_type") if (proj_type == 1): u[:, :] -= (dt * advect_x[:, :] + dt * gradp_x[:, :]) v[:, :] -= (dt * advect_y[:, :] + dt * gradp_y[:, :]) elif (proj_type == 2): u[:, :] -= dt * advect_x[:, :] v[:, :] -= dt * advect_y[:, :] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") #--------------------------------------------------------------------- # project the final velocity #--------------------------------------------------------------------- # now we solve L phi = D (U* /dt) print(" final projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type=self.cc_data.BCs["phi"].xlb, xr_BC_type=self.cc_data.BCs["phi"].xrb, yl_BC_type=self.cc_data.BCs["phi"].ylb, yr_BC_type=self.cc_data.BCs["phi"].yrb, xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU # u/v are cell-centered, divU is cell-centered divU[mg.ilo:mg.ihi+1,mg.jlo:mg.jhi+1] = \ 0.5*(u[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - u[myg.ilo-1:myg.ihi ,myg.jlo:myg.jhi+1])/myg.dx + \ 0.5*(v[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - v[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi ])/myg.dy mg.init_RHS(divU / dt) # use the old phi as our initial guess phiGuess = mg.soln_grid.scratch_array() phiGuess[mg.ilo-1:mg.ihi+2,mg.jlo-1:mg.jhi+2] = \ phi[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] mg.init_solution(phiGuess) # solve mg.solve(rtol=1.e-12) # store the solution solution = mg.get_solution() phi[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] = \ solution[mg.ilo-1:mg.ihi+2,mg.jlo-1:mg.jhi+2] # compute the cell-centered gradient of p and update the velocities # this differs depending on what we projected. gradphi_x = myg.scratch_array() gradphi_y = myg.scratch_array() gradphi_x[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(phi[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - phi[myg.ilo-1:myg.ihi ,myg.jlo:myg.jhi+1])/myg.dx gradphi_y[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(phi[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - phi[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi ])/myg.dy # u = u - grad_x phi dt u[:, :] -= dt * gradphi_x v[:, :] -= dt * gradphi_y # store gradp for the next step if (proj_type == 1): gradp_x[:, :] += gradphi_x[:, :] gradp_y[:, :] += gradphi_y[:, :] elif (proj_type == 2): gradp_x[:, :] = gradphi_x[:, :] gradp_y[:, :] = gradphi_y[:, :] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity")
def evolve(self, dt): """ Evolve the incompressible equations through one timestep. """ u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") gradp_x = self.cc_data.get_var("gradp_x") gradp_y = self.cc_data.get_var("gradp_y") phi = self.cc_data.get_var("phi") myg = self.cc_data.grid dtdx = dt/myg.dx dtdy = dt/myg.dy #--------------------------------------------------------------------- # create the limited slopes of u and v (in both directions) #--------------------------------------------------------------------- limiter = self.rp.get_param("incompressible.limiter") if (limiter == 0): limitFunc = reconstruction_f.nolimit elif (limiter == 1): limitFunc = reconstruction_f.limit2 else: limitFunc = reconstruction_f.limit4 ldelta_ux = limitFunc(1, u, myg.qx, myg.qy, myg.ng) ldelta_vx = limitFunc(1, v, myg.qx, myg.qy, myg.ng) ldelta_uy = limitFunc(2, u, myg.qx, myg.qy, myg.ng) ldelta_vy = limitFunc(2, v, myg.qx, myg.qy, myg.ng) #--------------------------------------------------------------------- # get the advective velocities #--------------------------------------------------------------------- """ the advective velocities are the normal velocity through each cell interface, and are defined on the cell edges, in a MAC type staggered form n+1/2 v i,j+1/2 +------+------+ | | n+1/2 | | n+1/2 u + U + u i-1/2,j | i,j | i+1/2,j | | +------+------+ n+1/2 v i,j-1/2 """ # this returns u on x-interfaces and v on y-interfaces. These # constitute the MAC grid print(" making MAC velocities") u_MAC, v_MAC = incomp_interface_f.mac_vels(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x, gradp_y) #--------------------------------------------------------------------- # do a MAC projection ot make the advective velocities divergence # free #--------------------------------------------------------------------- # we will solve L phi = D U^MAC, where phi is cell centered, and # U^MAC is the MAC-type staggered grid of the advective # velocities. print(" MAC projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type="periodic", xr_BC_type="periodic", yl_BC_type="periodic", yr_BC_type="periodic", xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU divU = mg.soln_grid.scratch_array() # MAC velocities are edge-centered. divU is cell-centered. divU[mg.ilo:mg.ihi+1,mg.jlo:mg.jhi+1] = \ (u_MAC[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - u_MAC[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx + \ (v_MAC[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - v_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1])/myg.dy # solve the Poisson problem mg.init_zeros() mg.init_RHS(divU) mg.solve(rtol=1.e-12) # update the normal velocities with the pressure gradient -- these # constitute our advective velocities phi_MAC = self.cc_data.get_var("phi-MAC") solution = mg.get_solution() phi_MAC[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] = \ solution[mg.ilo-1:mg.ihi+2,mg.jlo-1:mg.jhi+2] # we need the MAC velocities on all edges of the computational domain u_MAC[myg.ilo:myg.ihi+2,myg.jlo:myg.jhi+1] -= \ (phi_MAC[myg.ilo :myg.ihi+2,myg.jlo:myg.jhi+1] - phi_MAC[myg.ilo-1:myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx v_MAC[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+2] -= \ (phi_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+2] - phi_MAC[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi+1])/myg.dy #--------------------------------------------------------------------- # recompute the interface states, using the advective velocity # from above #--------------------------------------------------------------------- print(" making u, v edge states") u_xint, v_xint, u_yint, v_yint = \ incomp_interface_f.states(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x, gradp_y, u_MAC, v_MAC) #--------------------------------------------------------------------- # update U to get the provisional velocity field #--------------------------------------------------------------------- print(" doing provisional update of u, v") # compute (U.grad)U # we want u_MAC U_x + v_MAC U_y advect_x = myg.scratch_array() advect_y = myg.scratch_array() advect_x[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(u_MAC[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1] + u_MAC[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1]) * \ (u_xint[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - u_xint[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx + \ 0.5*(v_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1] + v_MAC[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2]) * \ (u_yint[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - u_yint[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1])/myg.dy advect_y[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(u_MAC[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1] + u_MAC[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1]) * \ (v_xint[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - v_xint[myg.ilo :myg.ihi+1,myg.jlo:myg.jhi+1])/myg.dx + \ 0.5*(v_MAC[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1] + v_MAC[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2]) * \ (v_yint[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - v_yint[myg.ilo:myg.ihi+1,myg.jlo :myg.jhi+1])/myg.dy proj_type = self.rp.get_param("incompressible.proj_type") if (proj_type == 1): u[:,:] -= (dt*advect_x[:,:] + dt*gradp_x[:,:]) v[:,:] -= (dt*advect_y[:,:] + dt*gradp_y[:,:]) elif (proj_type == 2): u[:,:] -= dt*advect_x[:,:] v[:,:] -= dt*advect_y[:,:] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") #--------------------------------------------------------------------- # project the final velocity #--------------------------------------------------------------------- # now we solve L phi = D (U* /dt) print(" final projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type="periodic", xr_BC_type="periodic", yl_BC_type="periodic", yr_BC_type="periodic", xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU # u/v are cell-centered, divU is cell-centered divU[mg.ilo:mg.ihi+1,mg.jlo:mg.jhi+1] = \ 0.5*(u[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - u[myg.ilo-1:myg.ihi ,myg.jlo:myg.jhi+1])/myg.dx + \ 0.5*(v[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - v[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi ])/myg.dy mg.init_RHS(divU/dt) # use the old phi as our initial guess phiGuess = mg.soln_grid.scratch_array() phiGuess[mg.ilo-1:mg.ihi+2,mg.jlo-1:mg.jhi+2] = \ phi[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] mg.init_solution(phiGuess) # solve mg.solve(rtol=1.e-12) # store the solution solution = mg.get_solution() phi[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] = \ solution[mg.ilo-1:mg.ihi+2,mg.jlo-1:mg.jhi+2] # compute the cell-centered gradient of p and update the velocities # this differs depending on what we projected. gradphi_x = myg.scratch_array() gradphi_y = myg.scratch_array() gradphi_x[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(phi[myg.ilo+1:myg.ihi+2,myg.jlo:myg.jhi+1] - phi[myg.ilo-1:myg.ihi ,myg.jlo:myg.jhi+1])/myg.dx gradphi_y[myg.ilo:myg.ihi+1,myg.jlo:myg.jhi+1] = \ 0.5*(phi[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - phi[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi ])/myg.dy # u = u - grad_x phi dt u[:,:] -= dt*gradphi_x v[:,:] -= dt*gradphi_y # store gradp for the next step if (proj_type == 1): gradp_x[:,:] += gradphi_x[:,:] gradp_y[:,:] += gradphi_y[:,:] elif (proj_type == 2): gradp_x[:,:] = gradphi_x[:,:] gradp_y[:,:] = gradphi_y[:,:] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity")
def evolve(self): """ Evolve the incompressible equations through one timestep. """ u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") gradp_x = self.cc_data.get_var("gradp_x") gradp_y = self.cc_data.get_var("gradp_y") phi = self.cc_data.get_var("phi") myg = self.cc_data.grid #--------------------------------------------------------------------- # create the limited slopes of u and v (in both directions) #--------------------------------------------------------------------- limiter = self.rp.get_param("incompressible.limiter") ldelta_ux = reconstruction.limit(u, myg, 1, limiter) ldelta_vx = reconstruction.limit(v, myg, 1, limiter) ldelta_uy = reconstruction.limit(u, myg, 2, limiter) ldelta_vy = reconstruction.limit(v, myg, 2, limiter) #--------------------------------------------------------------------- # get the advective velocities #--------------------------------------------------------------------- """ the advective velocities are the normal velocity through each cell interface, and are defined on the cell edges, in a MAC type staggered form n+1/2 v i,j+1/2 +------+------+ | | n+1/2 | | n+1/2 u + U + u i-1/2,j | i,j | i+1/2,j | | +------+------+ n+1/2 v i,j-1/2 """ # this returns u on x-interfaces and v on y-interfaces. These # constitute the MAC grid if self.verbose > 0: print(" making MAC velocities") _um, _vm = incomp_interface_f.mac_vels(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, self.dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x, gradp_y) u_MAC = ai.ArrayIndexer(d=_um, grid=myg) v_MAC = ai.ArrayIndexer(d=_vm, grid=myg) #--------------------------------------------------------------------- # do a MAC projection ot make the advective velocities divergence # free #--------------------------------------------------------------------- # we will solve L phi = D U^MAC, where phi is cell centered, and # U^MAC is the MAC-type staggered grid of the advective # velocities. if self.verbose > 0: print(" MAC projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type="periodic", xr_BC_type="periodic", yl_BC_type="periodic", yr_BC_type="periodic", xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU divU = mg.soln_grid.scratch_array() # MAC velocities are edge-centered. divU is cell-centered. divU.v()[:, :] = \ (u_MAC.ip(1) - u_MAC.v())/myg.dx + (v_MAC.jp(1) - v_MAC.v())/myg.dy # solve the Poisson problem mg.init_zeros() mg.init_RHS(divU) mg.solve(rtol=1.e-12) # update the normal velocities with the pressure gradient -- these # constitute our advective velocities phi_MAC = self.cc_data.get_var("phi-MAC") solution = mg.get_solution() phi_MAC.v(buf=1)[:, :] = solution.v(buf=1) # we need the MAC velocities on all edges of the computational domain b = (0, 1, 0, 0) u_MAC.v( buf=b)[:, :] -= (phi_MAC.v(buf=b) - phi_MAC.ip(-1, buf=b)) / myg.dx b = (0, 0, 0, 1) v_MAC.v( buf=b)[:, :] -= (phi_MAC.v(buf=b) - phi_MAC.jp(-1, buf=b)) / myg.dy #--------------------------------------------------------------------- # recompute the interface states, using the advective velocity # from above #--------------------------------------------------------------------- if self.verbose > 0: print(" making u, v edge states") _ux, _vx, _uy, _vy = \ incomp_interface_f.states(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, self.dt, u, v, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x, gradp_y, u_MAC, v_MAC) u_xint = ai.ArrayIndexer(d=_ux, grid=myg) v_xint = ai.ArrayIndexer(d=_vx, grid=myg) u_yint = ai.ArrayIndexer(d=_uy, grid=myg) v_yint = ai.ArrayIndexer(d=_vy, grid=myg) #--------------------------------------------------------------------- # update U to get the provisional velocity field #--------------------------------------------------------------------- if self.verbose > 0: print(" doing provisional update of u, v") # compute (U.grad)U # we want u_MAC U_x + v_MAC U_y advect_x = myg.scratch_array() advect_y = myg.scratch_array() # u u_x + v u_y advect_x.v()[:, :] = \ 0.5*(u_MAC.v() + u_MAC.ip(1))*(u_xint.ip(1) - u_xint.v())/myg.dx + \ 0.5*(v_MAC.v() + v_MAC.jp(1))*(u_yint.jp(1) - u_yint.v())/myg.dy # u v_x + v v_y advect_y.v()[:, :] = \ 0.5*(u_MAC.v() + u_MAC.ip(1))*(v_xint.ip(1) - v_xint.v())/myg.dx + \ 0.5*(v_MAC.v() + v_MAC.jp(1))*(v_yint.jp(1) - v_yint.v())/myg.dy proj_type = self.rp.get_param("incompressible.proj_type") if proj_type == 1: u[:, :] -= (self.dt * advect_x[:, :] + self.dt * gradp_x[:, :]) v[:, :] -= (self.dt * advect_y[:, :] + self.dt * gradp_y[:, :]) elif proj_type == 2: u[:, :] -= self.dt * advect_x[:, :] v[:, :] -= self.dt * advect_y[:, :] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") #--------------------------------------------------------------------- # project the final velocity #--------------------------------------------------------------------- # now we solve L phi = D (U* /dt) if self.verbose > 0: print(" final projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type="periodic", xr_BC_type="periodic", yl_BC_type="periodic", yr_BC_type="periodic", xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU # u/v are cell-centered, divU is cell-centered divU.v()[:, :] = \ 0.5*(u.ip(1) - u.ip(-1))/myg.dx + 0.5*(v.jp(1) - v.jp(-1))/myg.dy mg.init_RHS(divU / self.dt) # use the old phi as our initial guess phiGuess = mg.soln_grid.scratch_array() phiGuess.v(buf=1)[:, :] = phi.v(buf=1) mg.init_solution(phiGuess) # solve mg.solve(rtol=1.e-12) # store the solution phi[:, :] = mg.get_solution(grid=myg) # compute the cell-centered gradient of p and update the velocities # this differs depending on what we projected. gradphi_x, gradphi_y = mg.get_solution_gradient(grid=myg) # u = u - grad_x phi dt u[:, :] -= self.dt * gradphi_x v[:, :] -= self.dt * gradphi_y # store gradp for the next step if proj_type == 1: gradp_x[:, :] += gradphi_x[:, :] gradp_y[:, :] += gradphi_y[:, :] elif proj_type == 2: gradp_x[:, :] = gradphi_x[:, :] gradp_y[:, :] = gradphi_y[:, :] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") if self.particles is not None: self.particles.update_particles(self.dt) # increment the time if not self.in_preevolve: self.cc_data.t += self.dt self.n += 1
def evolve(self): """ Evolve the incompressible equations through one timestep. """ u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") gradp_x = self.cc_data.get_var("gradp_x") gradp_y = self.cc_data.get_var("gradp_y") phi = self.cc_data.get_var("phi") myg = self.cc_data.grid #--------------------------------------------------------------------- # create the limited slopes of u and v (in both directions) #--------------------------------------------------------------------- limiter = self.rp.get_param("incompressible.limiter") if (limiter == 0): limitFunc = reconstruction_f.nolimit elif (limiter == 1): limitFunc = reconstruction_f.limit2 else: limitFunc = reconstruction_f.limit4 ldelta_ux = limitFunc(1, u.d, myg.qx, myg.qy, myg.ng) ldelta_vx = limitFunc(1, v.d, myg.qx, myg.qy, myg.ng) ldelta_uy = limitFunc(2, u.d, myg.qx, myg.qy, myg.ng) ldelta_vy = limitFunc(2, v.d, myg.qx, myg.qy, myg.ng) #--------------------------------------------------------------------- # get the advective velocities #--------------------------------------------------------------------- """ the advective velocities are the normal velocity through each cell interface, and are defined on the cell edges, in a MAC type staggered form n+1/2 v i,j+1/2 +------+------+ | | n+1/2 | | n+1/2 u + U + u i-1/2,j | i,j | i+1/2,j | | +------+------+ n+1/2 v i,j-1/2 """ # this returns u on x-interfaces and v on y-interfaces. These # constitute the MAC grid if self.verbose > 0: print(" making MAC velocities") _um, _vm = incomp_interface_f.mac_vels(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, self.dt, u.d, v.d, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x.d, gradp_y.d) u_MAC = patch.ArrayIndexer(d=_um, grid=myg) v_MAC = patch.ArrayIndexer(d=_vm, grid=myg) #--------------------------------------------------------------------- # do a MAC projection ot make the advective velocities divergence # free #--------------------------------------------------------------------- # we will solve L phi = D U^MAC, where phi is cell centered, and # U^MAC is the MAC-type staggered grid of the advective # velocities. if self.verbose > 0: print(" MAC projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type="periodic", xr_BC_type="periodic", yl_BC_type="periodic", yr_BC_type="periodic", xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU divU = mg.soln_grid.scratch_array() # MAC velocities are edge-centered. divU is cell-centered. divU.v()[:,:] = \ (u_MAC.ip(1) - u_MAC.v())/myg.dx + (v_MAC.jp(1) - v_MAC.v())/myg.dy # solve the Poisson problem mg.init_zeros() mg.init_RHS(divU.d) mg.solve(rtol=1.e-12) # update the normal velocities with the pressure gradient -- these # constitute our advective velocities phi_MAC = self.cc_data.get_var("phi-MAC") solution = mg.get_solution() phi_MAC.v(buf=1)[:,:] = solution.v(buf=1) # we need the MAC velocities on all edges of the computational domain b = (0, 1, 0, 0) u_MAC.v(buf=b)[:,:] -= (phi_MAC.v(buf=b) - phi_MAC.ip(-1, buf=b))/myg.dx b = (0, 0, 0, 1) v_MAC.v(buf=b)[:,:] -= (phi_MAC.v(buf=b) - phi_MAC.jp(-1, buf=b))/myg.dy #--------------------------------------------------------------------- # recompute the interface states, using the advective velocity # from above #--------------------------------------------------------------------- if self.verbose > 0: print(" making u, v edge states") _ux, _vx, _uy, _vy = \ incomp_interface_f.states(myg.qx, myg.qy, myg.ng, myg.dx, myg.dy, self.dt, u.d, v.d, ldelta_ux, ldelta_vx, ldelta_uy, ldelta_vy, gradp_x.d, gradp_y.d, u_MAC.d, v_MAC.d) u_xint = patch.ArrayIndexer(d=_ux, grid=myg) v_xint = patch.ArrayIndexer(d=_vx, grid=myg) u_yint = patch.ArrayIndexer(d=_uy, grid=myg) v_yint = patch.ArrayIndexer(d=_vy, grid=myg) #--------------------------------------------------------------------- # update U to get the provisional velocity field #--------------------------------------------------------------------- if self.verbose > 0: print(" doing provisional update of u, v") # compute (U.grad)U # we want u_MAC U_x + v_MAC U_y advect_x = myg.scratch_array() advect_y = myg.scratch_array() # u u_x + v u_y advect_x.v()[:,:] = \ 0.5*(u_MAC.v() + u_MAC.ip(1))*(u_xint.ip(1) - u_xint.v())/myg.dx + \ 0.5*(v_MAC.v() + v_MAC.jp(1))*(u_yint.jp(1) - u_yint.v())/myg.dy # u v_x + v v_y advect_y.v()[:,:] = \ 0.5*(u_MAC.v() + u_MAC.ip(1))*(v_xint.ip(1) - v_xint.v())/myg.dx + \ 0.5*(v_MAC.v() + v_MAC.jp(1))*(v_yint.jp(1) - v_yint.v())/myg.dy proj_type = self.rp.get_param("incompressible.proj_type") if proj_type == 1: u.d[:,:] -= (self.dt*advect_x.d[:,:] + self.dt*gradp_x.d[:,:]) v.d[:,:] -= (self.dt*advect_y.d[:,:] + self.dt*gradp_y.d[:,:]) elif proj_type == 2: u.d[:,:] -= self.dt*advect_x.d[:,:] v.d[:,:] -= self.dt*advect_y.d[:,:] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") #--------------------------------------------------------------------- # project the final velocity #--------------------------------------------------------------------- # now we solve L phi = D (U* /dt) if self.verbose > 0: print(" final projection") # create the multigrid object mg = MG.CellCenterMG2d(myg.nx, myg.ny, xl_BC_type="periodic", xr_BC_type="periodic", yl_BC_type="periodic", yr_BC_type="periodic", xmin=myg.xmin, xmax=myg.xmax, ymin=myg.ymin, ymax=myg.ymax, verbose=0) # first compute divU # u/v are cell-centered, divU is cell-centered divU.v()[:,:] = \ 0.5*(u.ip(1) - u.ip(-1))/myg.dx + 0.5*(v.jp(1) - v.jp(-1))/myg.dy mg.init_RHS(divU.d/self.dt) # use the old phi as our initial guess phiGuess = mg.soln_grid.scratch_array() phiGuess.v(buf=1)[:,:] = phi.v(buf=1) mg.init_solution(phiGuess.d) # solve mg.solve(rtol=1.e-12) # store the solution phi.d[:,:] = mg.get_solution(grid=myg).d # compute the cell-centered gradient of p and update the velocities # this differs depending on what we projected. gradphi_x, gradphi_y = mg.get_solution_gradient(grid=myg) # u = u - grad_x phi dt u.d[:,:] -= self.dt*gradphi_x.d v.d[:,:] -= self.dt*gradphi_y.d # store gradp for the next step if proj_type == 1: gradp_x.d[:,:] += gradphi_x.d[:,:] gradp_y.d[:,:] += gradphi_y.d[:,:] elif proj_type == 2: gradp_x.d[:,:] = gradphi_x.d[:,:] gradp_y.d[:,:] = gradphi_y.d[:,:] self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # increment the time if not self.in_preevolve: self.cc_data.t += self.dt self.n += 1