Пример #1
0
    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)
Пример #2
0
    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)