def step_hyperbolic(self,solution): r""" Take one time step on the homogeneous hyperbolic system. :Input: - *solution* - (:class:`~pyclaw.solution.Solution`) Solution that will be evolved """ import numpy as np state = solution.states[0] grid = state.grid self._apply_q_bcs(state) if state.num_aux > 0: self._apply_aux_bcs(state) num_eqn,num_ghost = state.num_eqn,self.num_ghost if(self.kernel_language == 'Fortran'): mx = grid.num_cells[0] dx,dt = grid.delta[0],self.dt dtdx = np.zeros( (mx+2*num_ghost) ) + dt/dx rp1 = self.rp.rp1._cpointer self.qbc,cfl = self.fmod.step1(num_ghost,mx,self.qbc,self.auxbc,dx,dt,self._method,self._mthlim,self.fwave,rp1) elif(self.kernel_language == 'Python'): q = self.qbc aux = self.auxbc # Limiter to use in the pth family limiter = np.array(self._mthlim,ndmin=1) dtdx = np.zeros( (2*self.num_ghost+grid.num_cells[0]) ) # Find local value for dt/dx if state.index_capa>=0: dtdx = self.dt / (grid.delta[0] * state.aux[state.index_capa,:]) else: dtdx += self.dt/grid.delta[0] # Solve Riemann problem at each interface q_l=q[:,:-1] q_r=q[:,1:] if state.aux is not None: aux_l=aux[:,:-1] aux_r=aux[:,1:] else: aux_l = None aux_r = None wave,s,amdq,apdq = self.rp(q_l,q_r,aux_l,aux_r,state.problem_data) # Update loop limits, these are the limits for the Riemann solver # locations, which then update a grid cell value # We include the Riemann problem just outside of the grid so we can # do proper limiting at the grid edges # LL | | UL # | LL | | | | ... | | | UL | | # | | LL = self.num_ghost - 1 UL = self.num_ghost + grid.num_cells[0] + 1 # Update q for Godunov update for m in xrange(num_eqn): q[m,LL:UL] -= dtdx[LL:UL]*apdq[m,LL-1:UL-1] q[m,LL-1:UL-1] -= dtdx[LL-1:UL-1]*amdq[m,LL-1:UL-1] # Compute maximum wave speed cfl = 0.0 for mw in xrange(wave.shape[1]): smax1 = np.max(dtdx[LL:UL]*s[mw,LL-1:UL-1]) smax2 = np.max(-dtdx[LL-1:UL-1]*s[mw,LL-1:UL-1]) cfl = max(cfl,smax1,smax2) # If we are doing slope limiting we have more work to do if self.order == 2: # Initialize flux corrections f = np.zeros( (num_eqn,grid.num_cells[0] + 2*self.num_ghost) ) # Apply Limiters to waves if (limiter > 0).any(): wave = tvd.limit(state.num_eqn,wave,s,limiter,dtdx) # Compute correction fluxes for second order q_{xx} terms dtdxave = 0.5 * (dtdx[LL-1:UL-1] + dtdx[LL:UL]) if self.fwave: for mw in xrange(wave.shape[1]): sabs = np.abs(s[mw,LL-1:UL-1]) om = 1.0 - sabs*dtdxave[:UL-LL] ssign = np.sign(s[mw,LL-1:UL-1]) for m in xrange(num_eqn): f[m,LL:UL] += 0.5 * ssign * om * wave[m,mw,LL-1:UL-1] else: for mw in xrange(wave.shape[1]): sabs = np.abs(s[mw,LL-1:UL-1]) om = 1.0 - sabs*dtdxave[:UL-LL] for m in xrange(num_eqn): f[m,LL:UL] += 0.5 * sabs * om * wave[m,mw,LL-1:UL-1] # Update q by differencing correction fluxes for m in xrange(num_eqn): q[m,LL:UL-1] -= dtdx[LL:UL-1] * (f[m,LL+1:UL] - f[m,LL:UL-1]) else: raise Exception("Unrecognized kernel_language; choose 'Fortran' or 'Python'") self.cfl.update_global_max(cfl) state.set_q_from_qbc(num_ghost,self.qbc) if state.num_aux > 0: state.set_aux_from_auxbc(num_ghost,self.auxbc)
def step_hyperbolic(self, solution): r""" Take one time step on the homogeneous hyperbolic system. :Input: - *solution* - (:class:`~pyclaw.solution.Solution`) Solution that will be evolved """ import numpy as np state = solution.states[0] grid = state.grid self._apply_q_bcs(state) if state.num_aux > 0: self._apply_aux_bcs(state) num_eqn, num_ghost = state.num_eqn, self.num_ghost if (self.kernel_language == 'Fortran'): mx = grid.num_cells[0] dx, dt = grid.delta[0], self.dt dtdx = np.zeros((mx + 2 * num_ghost)) + dt / dx rp1 = self.rp.rp1._cpointer self.qbc, cfl = self.fmod.step1(num_ghost, mx, self.qbc, self.auxbc, dx, dt, self._method, self._mthlim, self.fwave, rp1) elif (self.kernel_language == 'Python'): q = self.qbc aux = self.auxbc # Limiter to use in the pth family limiter = np.array(self._mthlim, ndmin=1) dtdx = np.zeros((2 * self.num_ghost + grid.num_cells[0])) # Find local value for dt/dx if state.index_capa >= 0: dtdx = self.dt / (grid.delta[0] * state.aux[state.index_capa, :]) else: dtdx += self.dt / grid.delta[0] # Solve Riemann problem at each interface q_l = q[:, :-1] q_r = q[:, 1:] if state.aux is not None: aux_l = aux[:, :-1] aux_r = aux[:, 1:] else: aux_l = None aux_r = None wave, s, amdq, apdq = self.rp(q_l, q_r, aux_l, aux_r, state.problem_data) # Update loop limits, these are the limits for the Riemann solver # locations, which then update a grid cell value # We include the Riemann problem just outside of the grid so we can # do proper limiting at the grid edges # LL | | UL # | LL | | | | ... | | | UL | | # | | LL = self.num_ghost - 1 UL = self.num_ghost + grid.num_cells[0] + 1 # Update q for Godunov update for m in xrange(num_eqn): q[m, LL:UL] -= dtdx[LL:UL] * apdq[m, LL - 1:UL - 1] q[m, LL - 1:UL - 1] -= dtdx[LL - 1:UL - 1] * amdq[m, LL - 1:UL - 1] # Compute maximum wave speed cfl = 0.0 for mw in xrange(wave.shape[1]): smax1 = np.max(dtdx[LL:UL] * s[mw, LL - 1:UL - 1]) smax2 = np.max(-dtdx[LL - 1:UL - 1] * s[mw, LL - 1:UL - 1]) cfl = max(cfl, smax1, smax2) # If we are doing slope limiting we have more work to do if self.order == 2: # Initialize flux corrections f = np.zeros((num_eqn, grid.num_cells[0] + 2 * self.num_ghost)) # Apply Limiters to waves if (limiter > 0).any(): wave = tvd.limit(state.num_eqn, wave, s, limiter, dtdx) # Compute correction fluxes for second order q_{xx} terms dtdxave = 0.5 * (dtdx[LL - 1:UL - 1] + dtdx[LL:UL]) if self.fwave: for mw in xrange(wave.shape[1]): sabs = np.abs(s[mw, LL - 1:UL - 1]) om = 1.0 - sabs * dtdxave[:UL - LL] ssign = np.sign(s[mw, LL - 1:UL - 1]) for m in xrange(num_eqn): f[m, LL:UL] += 0.5 * ssign * om * wave[m, mw, LL - 1:UL - 1] else: for mw in xrange(wave.shape[1]): sabs = np.abs(s[mw, LL - 1:UL - 1]) om = 1.0 - sabs * dtdxave[:UL - LL] for m in xrange(num_eqn): f[m, LL:UL] += 0.5 * sabs * om * wave[m, mw, LL - 1:UL - 1] # Update q by differencing correction fluxes for m in xrange(num_eqn): q[m, LL:UL - 1] -= dtdx[LL:UL - 1] * (f[m, LL + 1:UL] - f[m, LL:UL - 1]) else: raise Exception( "Unrecognized kernel_language; choose 'Fortran' or 'Python'") self.cfl.update_global_max(cfl) state.set_q_from_qbc(num_ghost, self.qbc) if state.num_aux > 0: state.set_aux_from_auxbc(num_ghost, self.auxbc)