"""The routines that implement the 4th-order compressible scheme,using SDC time integration"""frompyroimportcompressible_fv4frompyro.meshimportfv,patchfrompyro.utilimportmsg
[docs]classSimulation(compressible_fv4.Simulation):"""Drive the 4th-order compressible solver with SDC time integration"""def__init__(self,solver_name,problem_name,problem_func,rp,*,problem_finalize_func=None,problem_source_func=None,timers=None,data_class=fv.FV2d):super().__init__(solver_name,problem_name,problem_func,rp,problem_finalize_func=problem_finalize_func,problem_source_func=problem_source_func,timers=timers,data_class=data_class)self.n_nodes=3# Gauss-Lobotto temporal nodesself.n_iter=4# 4 SDC iterations for 4th order
[docs]defsdc_integral(self,m_start,m_end,As):"""Compute the integral over the sources from m to m+1 with a Simpson's rule"""integral=self.cc_data.grid.scratch_array(nvar=self.ivars.nvar)ifm_start==0andm_end==1:forninrange(self.ivars.nvar):integral.v(n=n)[:,:]=self.dt/24.0*(5.0*As[0].v(n=n)+8.0*As[1].v(n=n)-As[2].v(n=n))elifm_start==1andm_end==2:forninrange(self.ivars.nvar):integral.v(n=n)[:,:]=self.dt/24.0*(-As[0].v(n=n)+8.0*As[1].v(n=n)+5.0*As[2].v(n=n))else:msg.fail("invalid quadrature range")returnintegral
[docs]defevolve(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))# we need the advective term at all time nodes at the old# iteration -- we'll compute this for the initial state# nowA_kold=[]A_kold.append(self.substep(U_kold[0]))A_kold.append(A_kold[-1].copy())A_kold.append(A_kold[-1].copy())A_knew=[]foradvinA_kold:A_knew.append(adv.copy())# loop over iterationsfor_inrange(self.n_iter):# loop over the time nodes and updateforminrange(self.n_nodes):# update m to m+1 for knew# compute A(U_m^{k+1})# note: for m = 0, the advective term doesn't changeifm>0:A_knew[m]=self.substep(U_knew[m])# only do an update if we are not at the last nodeifm<self.n_nodes-1:# compute the integral over A at the old iterationintegral=self.sdc_integral(m,m+1,A_kold)# and the final updateforninrange(self.ivars.nvar):U_knew[m+1].data.v(n=n)[:,:]=U_knew[m].data.v(n=n)+ \
0.5*self.dt*(A_knew[m].v(n=n)-A_kold[m].v(n=n))+integral.v(n=n)# fill ghost cellsU_knew[m+1].fill_BC_all()# store the current iteration as the old iteration# node m = 0 data doesn't changeforminrange(1,self.n_nodes):U_kold[m].data[:,:,:]=U_knew[m].data[:,:,:]A_kold[m][:,:,:]=A_knew[m][:,:,:]# store the new solutionself.cc_data.data[:,:,:]=U_knew[-1].data[:,:,:]ifself.particlesisnotNone:self.particles.update_particles(self.dt)# increment the timemyd.t+=self.dtself.n+=1tm_evolve.end()