Beispiel #1
0
class ShenDirichletBasis(ChebyshevBase):
    """Shen basis for Dirichlet boundary conditions

    Parameters
    ----------
        N : int, optional
            Number of quadrature points
        quad : str, optional
               Type of quadrature

               - GL - Chebyshev-Gauss-Lobatto
               - GC - Chebyshev-Gauss

        bc : 2-tuple of floats, optional
             Boundary conditions at x=(1,-1). For Poisson eq.
        plan : bool, optional
               Plan transforms on __init__ or not. If basis is part of a
               TensorProductSpace, then planning needs to be delayed.
        domain : 2-tuple of floats, optional
                 The computational domain
        scaled : bool, optional
                 Whether or not to use scaled basis
    """

    def __init__(self, N=0, quad="GC", bc=(0, 0), plan=False,
                 domain=(-1., 1.), scaled=False):
        ChebyshevBase.__init__(self, N, quad, domain=domain)
        from shenfun.tensorproductspace import BoundaryValues
        self.CT = Basis(N, quad, plan=plan)
        self._scaled = scaled
        self._factor = np.ones(1)
        if plan:
            self.plan(N, 0, np.float, {})
        self.bc = BoundaryValues(self, bc=bc)

    def get_vandermonde_basis(self, V):
        P = np.zeros(V.shape)
        P[:, :-2] = V[:, :-2] - V[:, 2:]
        P[:, -2] = (V[:, 0] + V[:, 1])/2
        P[:, -1] = (V[:, 0] - V[:, 1])/2
        return P

    def is_scaled(self):
        """Return True if scaled basis is used, otherwise False"""
        return False

    def evaluate_scalar_product(self, input_array, output_array, fast_transform=True):
        if fast_transform is False:
            self.vandermonde_scalar_product(input_array, output_array)
            return
        output = self.CT.scalar_product(fast_transform=fast_transform)
        s0 = self.sl(0)
        s1 = self.sl(1)
        c0 = 0.5*(output[s0] + output[s1])
        c1 = 0.5*(output[s0] - output[s1])
        s0[self.axis] = slice(0, -2)
        s1[self.axis] = slice(2, None)
        output[s0] -= output[s1]
        s0[self.axis] = -2
        output[s0] = c0
        s0[self.axis] = -1
        output[s0] = c1

    def evaluate_expansion_all(self, input_array, output_array, fast_transform=True):
        if fast_transform is False:
            SpectralBase.evaluate_expansion_all(self, input_array, output_array, False)
            return
        w_hat = work[(input_array, 0)]
        s0 = self.sl(slice(0, -2))
        s1 = self.sl(slice(2, None))
        w_hat[s0] = input_array[s0]
        w_hat[s1] -= input_array[s0]
        self.bc.apply_before(w_hat, False, (0.5, 0.5))
        self.CT.backward(w_hat)
        assert output_array is self.CT.backward.output_array

    def slice(self):
        return slice(0, self.N-2)

    def eval(self, x, fk, output_array=None):
        if output_array is None:
            output_array = np.zeros(x.shape)
        x = self.map_reference_domain(x)
        w_hat = work[(fk, 0)]
        output_array[:] = n_cheb.chebval(x, fk[:-2])
        w_hat[2:] = fk[:-2]
        output_array -= n_cheb.chebval(x, w_hat)
        output_array += 0.5*(fk[-1]*(1+x)+fk[-2]*(1-x))
        return output_array

    def plan(self, shape, axis, dtype, options):
        if isinstance(axis, tuple):
            axis = axis[0]

        if isinstance(self.forward, Transform):
            if self.forward.input_array.shape == shape and self.axis == axis:
                # Already planned
                return

        self.CT.plan(shape, axis, dtype, options)
        self.axis = self.CT.axis
        xfftn_fwd = self.CT.forward.xfftn
        xfftn_bck = self.CT.backward.xfftn
        U = xfftn_fwd.input_array
        V = xfftn_fwd.output_array
        self.forward = Transform(self.forward, xfftn_fwd, U, V, V)
        self.backward = Transform(self.backward, xfftn_bck, V, V, U)
        self.scalar_product = Transform(self.scalar_product, xfftn_fwd, U, V, V)
Beispiel #2
0
class ShenDirichletBasis(ChebyshevBase):
    """Shen basis for Dirichlet boundary conditions

    Parameters
    ----------
        N : int, optional
            Number of quadrature points
        quad : str, optional
               Type of quadrature

               - GL - Chebyshev-Gauss-Lobatto
               - GC - Chebyshev-Gauss

        bc : 2-tuple of floats, optional
             Boundary conditions at x=(1,-1). For Poisson eq.
        domain : 2-tuple of floats, optional
                 The computational domain
        scaled : bool, optional
                 Whether or not to use scaled basis
    """

    def __init__(self, N=0, quad="GC", bc=(0, 0),
                 domain=(-1., 1.), scaled=False):
        ChebyshevBase.__init__(self, N, quad, domain=domain)
        from shenfun.tensorproductspace import BoundaryValues
        self.CT = Basis(N, quad)
        self._scaled = scaled
        self._factor = np.ones(1)
        self.plan(N, 0, np.float, {})
        self.bc = BoundaryValues(self, bc=bc)

    @staticmethod
    def boundary_condition():
        return 'Dirichlet'

    def _composite_basis(self, V):
        P = np.zeros(V.shape)
        P[:, :-2] = V[:, :-2] - V[:, 2:]
        P[:, -2] = (V[:, 0] + V[:, 1])/2
        P[:, -1] = (V[:, 0] - V[:, 1])/2
        return P

    def sympy_basis(self, i=0):
        x = sympy.symbols('x')
        return sympy.chebyshevt(i, x) - sympy.chebyshevt(i+2, x)

    def evaluate_basis(self, x, i=0, output_array=None):
        x = np.atleast_1d(x)
        if output_array is None:
            output_array = np.zeros(x.shape)
        if i < self.N-2:
            w = np.arccos(x)
            output_array[:] = np.cos(i*w) - np.cos((i+2)*w)
        elif i == self.N-2:
            output_array[:] = 0.5*(1+x)
        elif i == self.N-1:
            output_array[:] = 0.5*(1-x)
        return output_array

    def is_scaled(self):
        """Return True if scaled basis is used, otherwise False"""
        return False

    def evaluate_scalar_product(self, input_array, output_array, fast_transform=True):
        if fast_transform is False:
            self.vandermonde_scalar_product(input_array, output_array)
            return
        output = self.CT.scalar_product(fast_transform=fast_transform)
        s0 = self.si[0]
        s1 = self.si[1]
        c0 = 0.5*(output[s0] + output[s1])
        c1 = 0.5*(output[s0] - output[s1])
        s0 = self.sl[slice(0, -2)]
        s1 = self.sl[slice(2, None)]
        output[s0] -= output[s1]
        output[self.si[-2]] = c0
        output[self.si[-1]] = c1

    def evaluate_expansion_all(self, input_array, output_array, fast_transform=True):
        if fast_transform is False:
            SpectralBase.evaluate_expansion_all(self, input_array, output_array, False)
            return
        w_hat = work[(input_array, 0, True)]
        s0 = self.sl[slice(0, -2)]
        s1 = self.sl[slice(2, None)]
        w_hat[s0] = input_array[s0]
        w_hat[s1] -= input_array[s0]
        self.bc.apply_before(w_hat, False, (0.5, 0.5))
        self.CT.backward(w_hat)
        assert output_array is self.CT.backward.output_array

    def slice(self):
        return slice(0, self.N-2)

    def eval(self, x, u, output_array=None):
        if output_array is None:
            output_array = np.zeros(x.shape)
        x = self.map_reference_domain(x)
        w_hat = work[(u, 0, True)]
        output_array[:] = n_cheb.chebval(x, u[:-2])
        w_hat[2:] = u[:-2]
        output_array -= n_cheb.chebval(x, w_hat)
        output_array += 0.5*(u[-1]*(1-x)+u[-2]*(1+x))
        return output_array

    def plan(self, shape, axis, dtype, options):
        if isinstance(axis, tuple):
            assert len(axis) == 1
            axis = axis[-1]

        if isinstance(self.forward, Transform):
            if self.forward.input_array.shape == shape and self.axis == axis:
                # Already planned
                return

        self.CT.plan(shape, axis, dtype, options)
        self.CT.tensorproductspace = self.tensorproductspace
        xfftn_fwd = self.CT.forward.xfftn
        xfftn_bck = self.CT.backward.xfftn
        U = xfftn_fwd.input_array
        V = xfftn_fwd.output_array
        self.axis = axis
        self.forward = Transform(self.forward, xfftn_fwd, U, V, V)
        self.backward = Transform(self.backward, xfftn_bck, V, V, U)
        self.scalar_product = Transform(self.scalar_product, xfftn_fwd, U, V, V)
        self.si = islicedict(axis=self.axis, dimensions=self.dimensions())
        self.sl = slicedict(axis=self.axis, dimensions=self.dimensions())