""" A simulation of diffusion """importmatplotlib.pyplotaspltimportnumpyasnpfrompyro.meshimportpatchfrompyro.multigridimportMGfrompyro.simulation_nullimportNullSimulation,bc_setup,grid_setupfrompyro.utilimportmsg
[docs]classSimulation(NullSimulation):""" A simulation of diffusion """
[docs]definitialize(self):""" Initialize the grid and variables for diffusion and set the initial conditions for the chosen problem. """# setup the gridmy_grid=grid_setup(self.rp,ng=1)# for MG, we need to be a power of twoifmy_grid.nx!=my_grid.ny:msg.fail("need nx = ny for diffusion problems")n=int(np.log(my_grid.nx)/np.log(2.0))if2**n!=my_grid.nx:msg.fail("grid needs to be a power of 2")# create the variables# first figure out the boundary conditions -- we allow periodic,# Dirichlet, and Neumann.bc,_,_=bc_setup(self.rp)forbndin[bc.xlb,bc.xrb,bc.ylb,bc.yrb]:ifbndnotin["periodic","neumann","dirichlet"]:msg.fail("invalid BC")my_data=patch.CellCenterData2d(my_grid)my_data.register_var("phi",bc)my_data.create()self.cc_data=my_data# now set the initial conditions for the problemself.problem_func(self.cc_data,self.rp)
[docs]defmethod_compute_timestep(self):""" The diffusion timestep() function computes the timestep using the explicit timestep constraint as the starting point. We then multiply by the CFL number to get the timestep. Since we are doing an implicit discretization, we do not require CFL < 1. """cfl=self.rp.get_param("driver.cfl")k=self.rp.get_param("diffusion.k")# the timestep is min(dx**2/k, dy**2/k)xtmp=self.cc_data.grid.dx**2/kytmp=self.cc_data.grid.dy**2/kself.dt=cfl*min(xtmp,ytmp)
[docs]defevolve(self):""" Diffusion through dt using C-N implicit solve with multigrid """self.cc_data.fill_BC_all()phi=self.cc_data.get_var("phi")myg=self.cc_data.grid# diffusion coefficientk=self.rp.get_param("diffusion.k")# setup the MG object -- we want to solve a Helmholtz equation# equation of the form:# (alpha - beta L) phi = f## with alpha = 1# beta = (dt/2) k# f = phi + (dt/2) k L phi## this is the form that arises with a Crank-Nicolson discretization# of the diffusion equation.mg=MG.CellCenterMG2d(myg.nx,myg.ny,xmin=myg.xmin,xmax=myg.xmax,ymin=myg.ymin,ymax=myg.ymax,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,alpha=1.0,beta=0.5*self.dt*k,verbose=0)# form the RHS: f = phi + (dt/2) k L phi (where L is the Laplacian)f=mg.soln_grid.scratch_array()f.v()[:,:]=phi.v()+0.5*self.dt*k*((phi.ip(1)+phi.ip(-1)-2.0*phi.v())/myg.dx**2+(phi.jp(1)+phi.jp(-1)-2.0*phi.v())/myg.dy**2)mg.init_RHS(f)# initial guess is zerosmg.init_zeros()# solve the MG problem for the updated phimg.solve(rtol=1.e-10)# mg.smooth(mg.nlevels-1,100)# update the solutionphi.v()[:,:]=mg.get_solution().v()# increment the timeself.cc_data.t+=self.dtself.n+=1
[docs]defdovis(self):""" Do runtime visualization. """plt.clf()phi=self.cc_data.get_var("phi")myg=self.cc_data.gridimg=plt.imshow(np.transpose(phi.v()),interpolation="nearest",origin="lower",extent=[myg.xmin,myg.xmax,myg.ymin,myg.ymax],cmap=self.cm)plt.xlabel("x")plt.ylabel("y")plt.title("phi")plt.colorbar(img)plt.figtext(0.05,0.0125,f"t = {self.cc_data.t:10.5f}")plt.pause(0.001)plt.draw()