def get_stage_start(self, istage): """get the starting conditions (a CellCenterData2d object) for stage istage""" if istage == 0: ytmp = self.start else: ytmp = patch.cell_center_data_clone(self.start) for n in range(ytmp.nvar): var = ytmp.get_var_by_index(n) for s in range(istage): var.v()[:, :] += self.dt*a[self.method][istage, s]*self.k[s].v(n=n)[:, :] ytmp.t = self.t + c[self.method][istage]*self.dt return ytmp
def get_stage_start(self, istage): """get the starting conditions (a CellCenterData2d object) for stage istage""" if istage == 0: ytmp = self.start else: ytmp = patch.cell_center_data_clone(self.start) for n in range(ytmp.nvar): var = ytmp.get_var_by_index(n) for s in range(istage): var.v()[:, :] += self.dt * a[self.method][istage, s] * self.k[s].v( n=n)[:, :] ytmp.t = self.t + c[self.method][istage] * self.dt return ytmp
def evolve(self): """ Evolve the equations of compressible hydrodynamics through a timestep dt. """ tm_evolve = self.tc.timer("evolve") tm_evolve.begin() myd = self.cc_data # we need the solution at 3 time points and at the old and # current iteration (except for m = 0 -- that doesn't change). # This copy will initialize the the solution at all time nodes # with the current (old) solution. U_kold = [] U_kold.append(patch.cell_center_data_clone(self.cc_data)) U_kold.append(patch.cell_center_data_clone(self.cc_data)) U_kold.append(patch.cell_center_data_clone(self.cc_data)) U_knew = [] U_knew.append(U_kold[0]) U_knew.append(patch.cell_center_data_clone(self.cc_data)) U_knew.append(patch.cell_center_data_clone(self.cc_data)) # loop over iterations for _ in range(1, 5): # we need the advective term at all time nodes at the old # iteration -- we'll compute this now A_kold = [] for m in range(3): _tmp = self.substep(U_kold[m]) A_kold.append(_tmp) # loop over the time nodes and update for m in range(2): # update m to m+1 for knew # compute A(U_m^{k+1}) A_knew = self.substep(U_knew[m]) # compute the integral over A at the old iteration I = self.sdc_integral(m, m + 1, A_kold) # and the final update for n in range(self.ivars.nvar): U_knew[m+1].data.v(n=n)[:, :] = U_knew[m].data.v(n=n) + \ 0.5*self.dt * (A_knew.v(n=n) - A_kold[m].v(n=n)) + I.v(n=n) # fill ghost cells U_knew[m + 1].fill_BC_all() # store the current iteration as the old iteration for m in range(1, 3): U_kold[m].data[:, :, :] = U_knew[m].data[:, :, :] # store the new solution self.cc_data.data[:, :, :] = U_knew[-1].data[:, :, :] if self.particles is not None: self.particles.update_particles(self.dt) # increment the time myd.t += self.dt self.n += 1 tm_evolve.end()
def preevolve(self): """ preevolve is called before we being the timestepping loop. For the incompressible solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (u, v) is then reset to values before this evolve. """ self.in_preevolve = True myg = self.cc_data.grid u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # next create the multigrid object. We want Neumann BCs on phi # at solid walls and periodic on phi for periodic BCs 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() divU.v()[:, :] = \ 0.5*(u.ip(1) - u.ip(-1))/myg.dx + 0.5*(v.jp(1) - v.jp(-1))/myg.dy # solve L phi = DU # initialize our guess to the solution, set the RHS to divU and # solve mg.init_zeros() mg.init_RHS(divU) mg.solve(rtol=1.e-10) # store the solution in our self.cc_data object -- include a single # ghostcell phi = self.cc_data.get_var("phi") phi[:, :] = mg.get_solution(grid=myg) # compute the cell-centered gradient of phi and update the # velocities gradp_x, gradp_y = mg.get_solution_gradient(grid=myg) u[:, :] -= gradp_x v[:, :] -= gradp_y # fill the ghostcells self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution -- we'll restore it in a bit orig_data = patch.cell_center_data_clone(self.cc_data) # get the timestep self.method_compute_timestep() # evolve self.evolve() # update gradp_x and gradp_y in our main data object new_gp_x = self.cc_data.get_var("gradp_x") new_gp_y = self.cc_data.get_var("gradp_y") orig_gp_x = orig_data.get_var("gradp_x") orig_gp_y = orig_data.get_var("gradp_y") orig_gp_x[:, :] = new_gp_x[:, :] orig_gp_y[:, :] = new_gp_y[:, :] self.cc_data = orig_data if self.verbose > 0: print("done with the pre-evolution") self.in_preevolve = False
def evolve(self): """ Evolve the equations of compressible hydrodynamics through a timestep dt. """ tm_evolve = self.tc.timer("evolve") tm_evolve.begin() myd = self.cc_data # we need the solution at 3 time points and at the old and # current iteration (except for m = 0 -- that doesn't change). # This copy will initialize the the solution at all time nodes # with the current (old) solution. U_kold = [] U_kold.append(patch.cell_center_data_clone(self.cc_data)) U_kold.append(patch.cell_center_data_clone(self.cc_data)) U_kold.append(patch.cell_center_data_clone(self.cc_data)) U_knew = [] U_knew.append(U_kold[0]) U_knew.append(patch.cell_center_data_clone(self.cc_data)) U_knew.append(patch.cell_center_data_clone(self.cc_data)) # loop over iterations for _ in range(1, 5): # we need the advective term at all time nodes at the old # iteration -- we'll compute this now A_kold = [] for m in range(3): _tmp = self.substep(U_kold[m]) A_kold.append(_tmp) # loop over the time nodes and update for m in range(2): # update m to m+1 for knew # compute A(U_m^{k+1}) A_knew = self.substep(U_knew[m]) # compute the integral over A at the old iteration integral = self.sdc_integral(m, m+1, A_kold) # and the final update for n in range(self.ivars.nvar): U_knew[m+1].data.v(n=n)[:, :] = U_knew[m].data.v(n=n) + \ 0.5*self.dt * (A_knew.v(n=n) - A_kold[m].v(n=n)) + integral.v(n=n) # fill ghost cells U_knew[m+1].fill_BC_all() # store the current iteration as the old iteration for m in range(1, 3): U_kold[m].data[:, :, :] = U_knew[m].data[:, :, :] # store the new solution self.cc_data.data[:, :, :] = U_knew[-1].data[:, :, :] if self.particles is not None: self.particles.update_particles(self.dt) # increment the time myd.t += self.dt self.n += 1 tm_evolve.end()
def preevolve(self): """ preevolve is called before we being the timestepping loop. For the low Mach solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (rho, u, v) is then reset to values before this evolve. """ myg = self.cc_data.grid rho = self.cc_data.get_var("density") u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") self.cc_data.fill_BC("density") self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # the coefficent for the elliptic equation is beta_0^2/rho coeff = 1.0/rho[myg.ilo-1:myg.ihi+2,myg.jlo-1:myg.jhi+2] beta0 = self.base["beta0"] coeff = coeff*beta0[np.newaxis,myg.jlo-1:myg.jhi+2]**2 # next create the multigrid object. We defined phi with # the right BCs previously mg = vcMG.VarCoeffCCMG2d(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, coeffs=coeff, coeffs_bc=self.cc_data.BCs["density"], verbose=0) # first compute div{beta_0 U} div_beta_U = mg.soln_grid.scratch_array() # u/v are cell-centered, divU is cell-centered div_beta_U[mg.ilo:mg.ihi+1,mg.jlo:mg.jhi+1] = \ 0.5*beta0[np.newaxis,mg.jlo:mg.jhi+1]* \ (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*(beta0[np.newaxis,myg.jlo+1:myg.jhi+2]* \ v[myg.ilo:myg.ihi+1,myg.jlo+1:myg.jhi+2] - beta0[np.newaxis,myg.jlo-1:myg.jhi ]* v[myg.ilo:myg.ihi+1,myg.jlo-1:myg.jhi ])/myg.dy # solve D (beta_0^2/rho) G (phi/beta_0) = D( beta_0 U ) # set the RHS to divU and solve mg.init_RHS(div_beta_U) mg.solve(rtol=1.e-10) # store the solution in our self.cc_data object -- include a single # ghostcell phi = self.cc_data.get_var("phi") phi[:,:] = mg.get_solution(grid=myg) # get the cell-centered gradient of phi and update the # velocities # FIXME: this update only needs to be done on the interior # cells -- not ghost cells gradp_x, gradp_y = mg.get_solution_gradient(grid=myg) coeff = 1.0/rho[:,:] coeff = coeff*beta0[np.newaxis,:] u[:,:] -= coeff*gradp_x v[:,:] -= coeff*gradp_y # fill the ghostcells self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution -- we'll restore it in a bit orig_data = patch.cell_center_data_clone(self.cc_data) # get the timestep dt = self.timestep() # evolve self.evolve(dt) # update gradp_x and gradp_y in our main data object new_gp_x = self.cc_data.get_var("gradp_x") new_gp_y = self.cc_data.get_var("gradp_y") orig_gp_x = orig_data.get_var("gradp_x") orig_gp_y = orig_data.get_var("gradp_y") orig_gp_x[:,:] = new_gp_x[:,:] orig_gp_y[:,:] = new_gp_y[:,:] self.cc_data = orig_data if self.verbose > 0: print("done with the pre-evolution")
def preevolve(my_data): """ preevolve is called before we being the timestepping loop. For the incompressible solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (u, v) is then reset to values before this evolve. """ myg = my_data.grid u = my_data.get_var("x-velocity") v = my_data.get_var("y-velocity") my_data.fill_BC("x-velocity") my_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # next create the multigrid object. We want Neumann BCs on phi # at solid walls and periodic on phi for periodic BCs MG = multigrid.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() 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 # solve L phi = DU # initialize our guess to the solution MG.init_zeros() # setup the RHS of our Poisson equation MG.init_RHS(divU) # solve MG.solve(rtol=1.e-10) # store the solution in our my_data object -- include a single # ghostcell phi = my_data.get_var("phi") 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 phi and update the # velocities gradp_x = myg.scratch_array() gradp_y = myg.scratch_array() gradp_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 gradp_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[:, :] -= gradp_x v[:, :] -= gradp_y # fill the ghostcells my_data.fill_BC("x-velocity") my_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution copyData = patch.cell_center_data_clone(my_data) # get the timestep dt = timestep.timestep(copyData) # evolve evolve.evolve(copyData, dt) # update gradp_x and gradp_y in our main data object gp_x = my_data.get_var("gradp_x") gp_y = my_data.get_var("gradp_y") new_gp_x = copyData.get_var("gradp_x") new_gp_y = copyData.get_var("gradp_y") gp_x[:, :] = new_gp_x[:, :] gp_y[:, :] = new_gp_y[:, :] print "done with the pre-evolution"
def evolve(self): """ Evolve the linear advection equation through one timestep. We only consider the "density" variable in the CellCenterData2d object that is part of the Simulation. """ tm_evolve = self.tc.timer("evolve") tm_evolve.begin() myg = self.cc_data.grid myd = self.cc_data order = self.rp.get_param("advection.temporal_order") if order == 2: # time-integration -- RK2 myd_nhalf = patch.cell_center_data_clone(myd) # initial slopes and n+1/2 state k1 = self.substep(myd) var = myd_nhalf.get_var("density") var.v()[:,:] += 0.5*self.dt*k1.v()[:,:] myd_nhalf.fill_BC_all() # updated slopes, starting with the n+1/2 state k2 = self.substep(myd_nhalf) # final update var = myd.get_var("density") var.v()[:,:] += self.dt*k2.v()[:,:] elif order == 4: # time-integration -- RK4 # first slope (k1) is f(U^n) k1 = self.substep(myd) # second slope (k2) is f(U^n + 0.5*dt*k1) myd1 = patch.cell_center_data_clone(myd) var = myd1.get_var("density") var.v()[:,:] += 0.5*self.dt*k1.v()[:,:] myd1.fill_BC_all() k2 = self.substep(myd1) # third slope (k3) is f(U^n + 0.5*dt*k2) myd2 = patch.cell_center_data_clone(myd) var = myd2.get_var("density") var.v()[:,:] += 0.5*self.dt*k2.v()[:,:] myd2.fill_BC_all() k3 = self.substep(myd2) # last slope (k4) is f(U^n + dt*k3) myd3 = patch.cell_center_data_clone(myd) var = myd3.get_var("density") var.v()[:,:] += self.dt*k3.v()[:,:] myd3.fill_BC_all() k4 = self.substep(myd3) # final update var = myd.get_var("density") var.v()[:,:] += (self.dt/6.0)*(k1.v()[:,:] + 2.0*k2.v()[:,:] + 2.0*k3.v()[:,:] + k4.v()[:,:]) elif order == 103: # time-integration -- SSP RK3 (from Shu & Osher 1989) # compute u^1 = u^n + dt * L(u^n) k0 = self.substep(myd) u1 = patch.cell_center_data_clone(myd) var1 = u1.get_var("density") var1.v()[:,:] += self.dt*k0.v()[:,:] u1.fill_BC_all() # compute u^2 = (3/4) u^n + (1/4) u^1 + (1/4) dt * L(u^1) k1 = self.substep(u1) u2 = patch.cell_center_data_clone(myd) varn = myd.get_var("density") var1 = u1.get_var("density") var2 = u2.get_var("density") var2.v()[:,:] = 0.75*varn.v()[:,:] + 0.25*var1.v()[:,:] + 0.25*self.dt*k1.v()[:,:] u2.fill_BC_all() # compute u^new = (1/3) u^n + (2/3) u^2 + (2/3) dt L(u^2) k2 = self.substep(u2) var = myd.get_var("density") var2 = u2.get_var("density") var.v()[:,:] = (1.0/3.0)*var.v()[:,:] + (2.0/3.0)*var2.v()[:,:] + (2.0/3.0)*self.dt*k2.v()[:,:] # increment the time myd.t += self.dt self.n += 1 tm_evolve.end()
def preevolve(self): """ preevolve is called before we being the timestepping loop. For the low Mach solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (rho, u, v) is then reset to values before this evolve. """ self.in_preevolve = True myg = self.cc_data.grid rho = self.cc_data.get_var("density") u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") self.cc_data.fill_BC("density") self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # the coefficent for the elliptic equation is beta_0^2/rho coeff = 1/rho beta0 = self.base["beta0"] coeff.v()[:,:] = coeff.v()*beta0.v2d()**2 # next create the multigrid object. We defined phi with # the right BCs previously mg = vcMG.VarCoeffCCMG2d(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, coeffs=coeff, coeffs_bc=self.cc_data.BCs["density"], verbose=0) # first compute div{beta_0 U} div_beta_U = mg.soln_grid.scratch_array() # u/v are cell-centered, divU is cell-centered div_beta_U.v()[:,:] = \ 0.5*beta0.v2d()*(u.ip(1) - u.ip(-1))/myg.dx + \ 0.5*(beta0.v2dp(1)*v.jp(1) - beta0.v2dp(-1)*v.jp(-1))/myg.dy # solve D (beta_0^2/rho) G (phi/beta_0) = D( beta_0 U ) # set the RHS to divU and solve mg.init_RHS(div_beta_U.d) mg.solve(rtol=1.e-10) # store the solution in our self.cc_data object -- include a single # ghostcell phi = self.cc_data.get_var("phi") phi.d[:,:] = mg.get_solution(grid=myg).d # get the cell-centered gradient of phi and update the # velocities # FIXME: this update only needs to be done on the interior # cells -- not ghost cells gradp_x, gradp_y = mg.get_solution_gradient(grid=myg) coeff = 1.0/rho coeff.v()[:,:] = coeff.v()*beta0.v2d() u.v()[:,:] -= coeff.v()*gradp_x.v() v.v()[:,:] -= coeff.v()*gradp_y.v() # fill the ghostcells self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution -- we'll restore it in a bit orig_data = patch.cell_center_data_clone(self.cc_data) # get the timestep self.compute_timestep() # evolve self.evolve() # update gradp_x and gradp_y in our main data object new_gp_x = self.cc_data.get_var("gradp_x") new_gp_y = self.cc_data.get_var("gradp_y") orig_gp_x = orig_data.get_var("gradp_x") orig_gp_y = orig_data.get_var("gradp_y") orig_gp_x.d[:,:] = new_gp_x.d[:,:] orig_gp_y.d[:,:] = new_gp_y.d[:,:] self.cc_data = orig_data if self.verbose > 0: print("done with the pre-evolution") self.in_preevolve = False
def preevolve(self): """ preevolve is called before we being the timestepping loop. For the incompressible solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (u, v) is then reset to values before this evolve. """ myg = self.cc_data.grid u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # next create the multigrid object. We defined phi with # the right BCs previously 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 divU = mg.soln_grid.scratch_array() 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 # solve L phi = DU # initialize our guess to the solution, set the RHS to divU and # solve mg.init_zeros() mg.init_RHS(divU) mg.solve(rtol=1.e-10) # store the solution in our self.cc_data object -- include a single # ghostcell phi = self.cc_data.get_var("phi") 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 phi and update the # velocities gradp_x = myg.scratch_array() gradp_y = myg.scratch_array() gradp_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 gradp_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[:, :] -= gradp_x v[:, :] -= gradp_y # fill the ghostcells self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution -- we'll restore it in a bit orig_data = patch.cell_center_data_clone(self.cc_data) # get the timestep dt = self.timestep() # evolve self.evolve(dt) # update gradp_x and gradp_y in our main data object new_gp_x = self.cc_data.get_var("gradp_x") new_gp_y = self.cc_data.get_var("gradp_y") orig_gp_x = orig_data.get_var("gradp_x") orig_gp_y = orig_data.get_var("gradp_y") orig_gp_x[:, :] = new_gp_x[:, :] orig_gp_y[:, :] = new_gp_y[:, :] self.cc_data = orig_data print("done with the pre-evolution")
def preevolve(my_data): """ preevolve is called before we being the timestepping loop. For the incompressible solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (u, v) is then reset to values before this evolve. """ myg = my_data.grid u = my_data.get_var("x-velocity") v = my_data.get_var("y-velocity") my_data.fill_BC("x-velocity") my_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # next create the multigrid object. We want Neumann BCs on phi # at solid walls and periodic on phi for periodic BCs MG = multigrid.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() 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 # solve L phi = DU # initialize our guess to the solution MG.init_zeros() # setup the RHS of our Poisson equation MG.init_RHS(divU) # solve MG.solve(rtol=1.e-10) # store the solution in our my_data object -- include a single # ghostcell phi = my_data.get_var("phi") 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 phi and update the # velocities gradp_x = myg.scratch_array() gradp_y = myg.scratch_array() gradp_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 gradp_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[:,:] -= gradp_x v[:,:] -= gradp_y # fill the ghostcells my_data.fill_BC("x-velocity") my_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution copyData = patch.cell_center_data_clone(my_data) # get the timestep dt = timestep.timestep(copyData) # evolve evolve.evolve(copyData, dt) # update gradp_x and gradp_y in our main data object gp_x = my_data.get_var("gradp_x") gp_y = my_data.get_var("gradp_y") new_gp_x = copyData.get_var("gradp_x") new_gp_y = copyData.get_var("gradp_y") gp_x[:,:] = new_gp_x[:,:] gp_y[:,:] = new_gp_y[:,:] print "done with the pre-evolution"
def evolve(self): """ Evolve the equations of compressible hydrodynamics through a timestep dt. """ tm_evolve = self.tc.timer("evolve") tm_evolve.begin() myg = self.cc_data.grid myd = self.cc_data order = self.rp.get_param("compressible.temporal_order") if order == 2: # time-integration -- RK2 myd_nhalf = patch.cell_center_data_clone(myd) # initial slopes and n+1/2 state k1 = self.substep(myd) for n in range(self.vars.nvar): var = myd_nhalf.get_var_by_index(n) var.v()[:, :] += 0.5 * self.dt * k1.v(n=n)[:, :] myd_nhalf.fill_BC_all() # updated slopes, starting with the n+1/2 state k2 = self.substep(myd_nhalf) # final update for n in range(self.vars.nvar): var = myd.get_var_by_index(n) var.v()[:, :] += self.dt * k2.v(n=n)[:, :] elif order == 4: # time-integration -- RK4 # first slope (k1) is f(U^n) k1 = self.substep(myd) # second slope (k2) is f(U^n + 0.5*dt*k1) myd1 = patch.cell_center_data_clone(myd) for n in range(self.vars.nvar): var = myd1.get_var_by_index(n) var.v()[:, :] += 0.5 * self.dt * k1.v(n=n)[:, :] myd1.fill_BC_all() k2 = self.substep(myd1) # third slope (k3) is f(U^n + 0.5*dt*k2) myd2 = patch.cell_center_data_clone(myd) for n in range(self.vars.nvar): var = myd2.get_var_by_index(n) var.v()[:, :] += 0.5 * self.dt * k2.v(n=n)[:, :] myd2.fill_BC_all() k3 = self.substep(myd2) # last slope (k4) is f(U^n + dt*k3) myd3 = patch.cell_center_data_clone(myd) for n in range(self.vars.nvar): var = myd3.get_var_by_index(n) var.v()[:, :] += self.dt * k3.v(n=n)[:, :] myd3.fill_BC_all() k4 = self.substep(myd3) # final update for n in range(self.vars.nvar): var = myd.get_var_by_index(n) var.v()[:, :] += ( self.dt / 6.0) * (k1.v(n=n)[:, :] + 2.0 * k2.v(n=n)[:, :] + 2.0 * k3.v(n=n)[:, :] + k4.v(n=n)[:, :]) # increment the time myd.t += self.dt self.n += 1 tm_evolve.end()
def preevolve(self): """ preevolve is called before we being the timestepping loop. For the incompressible solver, this does an initial projection on the velocity field and then goes through the full evolution to get the value of phi. The fluid state (u, v) is then reset to values before this evolve. """ myg = self.cc_data.grid u = self.cc_data.get_var("x-velocity") v = self.cc_data.get_var("y-velocity") self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 1. do the initial projection. This makes sure that our original # velocity field satisties div U = 0 # next create the multigrid object. We defined phi with # the right BCs previously 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 divU = mg.soln_grid.scratch_array() 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 # solve L phi = DU # initialize our guess to the solution, set the RHS to divU and # solve mg.init_zeros() mg.init_RHS(divU) mg.solve(rtol=1.e-10) # store the solution in our self.cc_data object -- include a single # ghostcell phi = self.cc_data.get_var("phi") 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 phi and update the # velocities gradp_x = myg.scratch_array() gradp_y = myg.scratch_array() gradp_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 gradp_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[:,:] -= gradp_x v[:,:] -= gradp_y # fill the ghostcells self.cc_data.fill_BC("x-velocity") self.cc_data.fill_BC("y-velocity") # 2. now get an approximation to gradp at n-1/2 by going through the # evolution. # store the current solution -- we'll restore it in a bit orig_data = patch.cell_center_data_clone(self.cc_data) # get the timestep dt = self.timestep() # evolve self.evolve(dt) # update gradp_x and gradp_y in our main data object new_gp_x = self.cc_data.get_var("gradp_x") new_gp_y = self.cc_data.get_var("gradp_y") orig_gp_x = orig_data.get_var("gradp_x") orig_gp_y = orig_data.get_var("gradp_y") orig_gp_x[:,:] = new_gp_x[:,:] orig_gp_y[:,:] = new_gp_y[:,:] self.cc_data = orig_data print("done with the pre-evolution")