[docs]defgrid_setup(rp,ng=1):nx=rp.get_param("mesh.nx")ny=rp.get_param("mesh.ny")try:xmin=rp.get_param("mesh.xmin")exceptKeyError:xmin=0.0msg.warning("mesh.xmin not set, defaulting to 0.0")try:xmax=rp.get_param("mesh.xmax")exceptKeyError:xmax=1.0msg.warning("mesh.xmax not set, defaulting to 1.0")try:ymin=rp.get_param("mesh.ymin")exceptKeyError:ymin=0.0msg.warning("mesh.ymin not set, defaulting to 0.0")try:ymax=rp.get_param("mesh.ymax")exceptKeyError:ymax=1.0msg.warning("mesh.ymax not set, defaulting to 1.0")try:grid_type=rp.get_param("mesh.grid_type")exceptKeyError:grid_type="Cartesian2d"msg.warning("mesh.grid_type not set, defaulting to Cartesian2D")ifgrid_type=="Cartesian2d":create_grid=patch.Cartesian2delifgrid_type=="SphericalPolar":create_grid=patch.SphericalPolarelse:raiseValueError("Unsupported grid type!")my_grid=create_grid(nx,ny,xmin=xmin,xmax=xmax,ymin=ymin,ymax=ymax,ng=ng)# Make sure y-boundary condition is reflect when# ymin = 0 and ymax = piifgrid_type=="SphericalPolar":ifymin<=0.05:rp.set_param("mesh.ylboundary","reflect")msg.warning("With SphericalPolar grid,"+" mesh.ylboundary auto set to reflect when ymin ~ 0")ifabs(np.pi-ymax)<=0.05:rp.set_param("mesh.yrboundary","reflect")msg.warning("With SphericalPolar grid,"+" mesh.yrboundary auto set to reflect when ymax ~ pi")returnmy_grid
[docs]defbc_setup(rp):# first figure out the BCstry:xlb_type=rp.get_param("mesh.xlboundary")exceptKeyError:xlb_type="periodic"msg.warning("mesh.xlboundary is not set, defaulting to periodic")try:xrb_type=rp.get_param("mesh.xrboundary")exceptKeyError:xrb_type="periodic"msg.warning("mesh.xrboundary is not set, defaulting to periodic")try:ylb_type=rp.get_param("mesh.ylboundary")exceptKeyError:ylb_type="periodic"msg.warning("mesh.ylboundary is not set, defaulting to periodic")try:yrb_type=rp.get_param("mesh.yrboundary")exceptKeyError:yrb_type="periodic"msg.warning("mesh.yrboundary is not set, defaulting to periodic")bc=bnd.BC(xlb=xlb_type,xrb=xrb_type,ylb=ylb_type,yrb=yrb_type)# if we are reflecting, we need odd reflection in the normal# directions for the velocitybc_xodd=bnd.BC(xlb=xlb_type,xrb=xrb_type,ylb=ylb_type,yrb=yrb_type,odd_reflect_dir="x")bc_yodd=bnd.BC(xlb=xlb_type,xrb=xrb_type,ylb=ylb_type,yrb=yrb_type,odd_reflect_dir="y")returnbc,bc_xodd,bc_yodd
[docs]classNullSimulation:def__init__(self,solver_name,problem_name,problem_func,rp,*,problem_finalize_func=None,problem_source_func=None,timers=None,data_class=patch.CellCenterData2d):""" Initialize the Simulation object Parameters ---------- solver_name : str The name of the solver we are using problem_name : str The descriptive name for the problem (used in output) problem_func : function The function to call to initialize the problem rp : RuntimeParameters object The runtime parameters for the simulation problem_finalize_func : function An (optional) function to call when the simulation is over. problem_source_func : function An (optional) function to call to get source terms for the state. timers : TimerCollection object, optional The timers used for profiling this simulation. data_class : CellCenterData2d or FV2d The class that manages the data. """self.n=0self.dt=-1.e33self.dt_old=-1.e33self.data_class=data_classtry:self.tmax=rp.get_param("driver.tmax")except(AttributeError,KeyError):self.tmax=Nonetry:self.max_steps=rp.get_param("driver.max_steps")except(AttributeError,KeyError):self.max_steps=Noneself.rp=rpself.cc_data=Noneself.particles=Noneself.SMALL=1.e-12self.solver_name=solver_nameself.problem_name=problem_nameself.problem_func=problem_funcself.problem_finalize=problem_finalize_funcself.problem_source=problem_source_funciftimersisNone:self.tc=profile.TimerCollection()else:self.tc=timerstry:self.verbose=self.rp.get_param("driver.verbose")except(AttributeError,KeyError):self.verbose=0self.n_num_out=0# plottingself.cm="viridis"def__str__(self):ostr="pyro Simulation:\n"ostr+=f" solver: {self.solver_name}\n"ostr+=f" problem: {self.problem_name}\n"returnostr
[docs]deffinished(self):""" is the simulation finished based on time or the number of steps """returnself.cc_data.t>=self.tmaxorself.n>=self.max_steps
[docs]defdo_output(self):""" is it time to output? """dt_out=self.rp.get_param("io.dt_out")n_out=self.rp.get_param("io.n_out")do_io=self.rp.get_param("io.do_io")is_time=self.cc_data.t>=(self.n_num_out+1)*dt_outorself.n%n_out==0ifis_timeanddo_io==1:self.n_num_out+=1returnTruereturnFalse
[docs]defmethod_compute_timestep(self):""" the method-specific timestep code """
[docs]defcompute_timestep(self):""" a generic wrapper for computing the timestep that respects the driver parameters on timestepping """init_tstep_factor=self.rp.get_param("driver.init_tstep_factor")max_dt_change=self.rp.get_param("driver.max_dt_change")fix_dt=self.rp.get_param("driver.fix_dt")# get the timestepiffix_dt>0.0:self.dt=fix_dtelse:self.method_compute_timestep()ifself.n==0:self.dt=init_tstep_factor*self.dtelse:self.dt=min(max_dt_change*self.dt_old,self.dt)self.dt_old=self.dtifself.cc_data.t+self.dt>self.tmax:self.dt=self.tmax-self.cc_data.t
[docs]defpreevolve(self):""" Do any necessary evolution before the main evolve loop. This is not needed for advection """
[docs]defevolve(self):# increment the timeself.cc_data.t+=self.dtself.n+=1
[docs]deffinalize(self):""" Do any final clean-ups for the simulation and call the problem's finalize() method. """ifself.problem_finalize:self.problem_finalize()
[docs]defwrite(self,filename):""" Output the state of the simulation to an HDF5 file for plotting """ifnotfilename.endswith(".h5"):filename+=".h5"withh5py.File(filename,"w")asf:# main attributesf.attrs["solver"]=self.solver_namef.attrs["problem"]=self.problem_namef.attrs["time"]=self.cc_data.tf.attrs["nsteps"]=self.nself.cc_data.write_data(f)ifself.particlesisnotNone:self.particles.write_particles(f)self.rp.write_params(f)self.write_extras(f)
[docs]defwrite_extras(self,f):""" write out any extra simulation-specific stuff """
[docs]defread_extras(self,f):""" read in any simulation-specific data from an h5py file object f """