コード例 #1
0
def evans_webster_weights(omega, g, d_g, x, basis, *args, **kwds):

    def psi(t, k):
        return d_g(t, *args, **kwds) * basis(t, k)

    j_w = 1j * omega
    n = len(x)
    a_matrix = np.zeros((n, n), dtype=complex)
    rhs = np.zeros((n,), dtype=complex)

    dbasis = basis.derivative
    lim_g = Limit(g)
    b_1 = np.exp(j_w * lim_g(1, *args, **kwds))
    if np.isnan(b_1):
        b_1 = 0.0
    a_1 = np.exp(j_w * lim_g(-1, *args, **kwds))
    if np.isnan(a_1):
        a_1 = 0.0

    lim_psi = Limit(psi)
    for k in range(n):
        rhs[k] = basis(1, k) * b_1 - basis(-1, k) * a_1
        a_matrix[k] = (dbasis(x, k, n=1) + j_w * lim_psi(x, k))

    solution = linalg.lstsq(a_matrix, rhs, rcond=None)
    return solution[0]
コード例 #2
0
def evans_webster_weights(omega, gg, dgg, x, basis, *args, **kwds):
    def Psi(t, k):
        return dgg(t, *args, **kwds) * basis(t, k)

    j_w = 1j * omega
    nn = len(x)
    A = np.zeros((nn, nn), dtype=complex)
    F = np.zeros((nn, ), dtype=complex)

    dbasis = basis.derivative
    lim_gg = Limit(gg)
    b1 = np.exp(j_w * lim_gg(1, *args, **kwds))
    if np.isnan(b1):
        b1 = 0.0
    a1 = np.exp(j_w * lim_gg(-1, *args, **kwds))
    if np.isnan(a1):
        a1 = 0.0

    lim_Psi = Limit(Psi)
    for k in range(nn):
        F[k] = basis(1, k) * b1 - basis(-1, k) * a1
        A[k] = (dbasis(x, k, n=1) + j_w * lim_Psi(x, k))

    LS = linalg.lstsq(A, F)
    return LS[0]
コード例 #3
0
    def test_difficult_limit(self):
        def k(x):
            return (x * np.exp(x) - np.exp(x) + 1) / x**2

        lim, err = Limit(k, full_output=True)(0)
        assert_allclose(lim, 0.5)

        self.assertTrue(err.error_estimate < 1e-8)
コード例 #4
0
    def test_residue(self):
        def h(z):
            return -z / (np.expm1(2 * z))

        lim, err = Limit(h, full_output=True)(0)
        assert_allclose(lim, -0.5)

        self.assertTrue(err.error_estimate < 1e-14)
コード例 #5
0
    def test_residue_1_div_1_minus_exp_x(self):
        def fun(z):
            return -z / (np.expm1(2 * z))

        lim, err = Limit(fun, full_output=True)(0)
        assert_allclose(lim, -0.5)

        self.assertTrue(err.error_estimate < 1e-14)
コード例 #6
0
    def test_derivative_of_cos(self):
        x0 = np.pi / 2

        def g(x):
            return (np.cos(x0 + x) - np.cos(x0)) / x

        lim, err = Limit(g, full_output=True)(0)
        assert_allclose(lim, -1)
        self.assertTrue(err.error_estimate < 1e-14)
コード例 #7
0
    def _quad_osc(self, f, g, dg, a, b, omega, *args, **kwds):
        if a == b:
            Q = b - a
            err = b - a
            return Q, err

        abseps = 10**-self.precision
        max_iter = self.maxiter
        basis = self.basis
        if self.endpoints:
            xq = chebyshev_extrema(self.s)
        else:
            xq = chebyshev_roots(self.s)
            # xq = tanh_sinh_open_nodes(self.s)

        # One interval
        hh = (b - a) / 2
        x = (a + b) / 2 + hh * xq  # Nodes

        dtype = complex
        Q0 = np.zeros((max_iter, 1), dtype=dtype)  # Quadrature
        Q1 = np.zeros((max_iter, 1), dtype=dtype)  # First extrapolation
        Q2 = np.zeros((max_iter, 1), dtype=dtype)  # Second extrapolation

        lim_f = Limit(f)
        ab = np.hstack([a, b])
        wq = osc_weights(omega, g, dg, xq, basis, ab, *args, **kwds)
        Q0[0] = hh * np.sum(wq * lim_f(x, *args, **kwds))

        # Successive bisection of intervals
        nq = len(xq)
        n = nq
        for k in range(1, max_iter):
            n += nq * 2**k

            hh = hh / 2
            x = np.hstack([x + a, x + b]) / 2
            ab = np.hstack([ab + a, ab + b]) / 2
            wq = osc_weights(omega, g, dg, xq, basis, ab, *args, **kwds)

            Q0[k] = hh * np.sum(wq * lim_f(x, *args, **kwds))

            Q, err = self._extrapolate(k, Q0, Q1, Q2)

            convergence = (err <= abseps) | ~np.isfinite(Q)
            if convergence:
                break
        else:
            warnings.warn('Max number of iterations reached '
                          'without convergence.')

        if ~np.isfinite(Q):
            warnings.warn('Integral approximation is Infinite or NaN.')

        # The error estimate should not be zero
        err += 2 * np.finfo(Q).eps
        return Q, self.info(err, n)
コード例 #8
0
    def test_derivative_of_cos(self):
        x0 = np.pi / 2

        def fun(x):
            return (np.cos(x0 + x) - np.cos(x0)) / x

        lim, err = Limit(fun, step=CStepGenerator(), full_output=True)(0)
        assert_allclose(lim, -1)
        assert err.error_estimate < 1e-14
コード例 #9
0
    def test_sinx_divx(self):
        def f(x):
            return np.sin(x) / x

        lim_f = Limit(f, full_output=True)

        x = np.arange(-10, 10) / np.pi
        lim_f0, err = lim_f(x * np.pi)
        assert_array_almost_equal(lim_f0, np.sinc(x))
        self.assertTrue(np.all(err.error_estimate < 1.0e-14))
コード例 #10
0
    def _quad_osc(self, f, g, dg, a, b, omega, *args, **kwds):
        if a == b:
            q_val = b - a
            err = np.abs(b - a)
            return q_val, err

        abseps = 10**-self.precision
        max_iter = self.maxiter
        basis = self.basis
        if self.endpoints:
            x_n = chebyshev_extrema(self.s)
        else:
            x_n = chebyshev_roots(self.s)
            # x_n = tanh_sinh_open_nodes(self.s)

        # One interval
        hh = (b - a) / 2
        x = (a + b) / 2 + hh * x_n      # Nodes

        dtype = complex
        val0 = np.zeros((max_iter, 1), dtype=dtype)  # Quadrature
        val1 = np.zeros((max_iter, 1), dtype=dtype)  # First extrapolation
        val2 = np.zeros((max_iter, 1), dtype=dtype)  # Second extrapolation

        lim_f = Limit(f)
        a_b = np.hstack([a, b])
        wq = osc_weights(omega, g, dg, x_n, basis, a_b, *args, **kwds)
        val0[0] = hh * np.sum(wq * lim_f(x, *args, **kwds))

        # Successive bisection of intervals
        nq = len(x_n)
        n = nq
        for k in range(1, max_iter):
            n += nq * 2**k

            hh = hh / 2
            x = np.hstack([x + a, x + b]) / 2
            a_b = np.hstack([a_b + a, a_b + b]) / 2
            wq = osc_weights(omega, g, dg, x_n, basis, a_b, *args, **kwds)

            val0[k] = hh * np.sum(wq * lim_f(x, *args, **kwds))

            q_val, err = self._extrapolate(k, val0, val1, val2)

            converged = (err <= abseps) | ~np.isfinite(q_val)
            if converged:
                break
        _assert_warn(converged, 'Max number of iterations reached '
                     'without convergence.')
        _assert_warn(np.isfinite(q_val),
                     'Integral approximation is Infinite or NaN.')

        # The error estimate should not be zero
        err += 2 * np.finfo(q_val).eps
        return q_val, self.info(err, n)
コード例 #11
0
    def test_difficult_limit(self):
        def fun(x):
            return (x * np.exp(x) - np.expm1(x)) / x**2

        for path in [
                'radial',
        ]:
            lim, err = Limit(fun, path=path, full_output=True)(0)
            assert_allclose(lim, 0.5)

            self.assertTrue(err.error_estimate < 1e-8)
コード例 #12
0
    def test_sinx_div_x(self):
        def fun(x):
            return np.sin(x) / x

        for path in ['radial', 'spiral']:
            lim_f = Limit(fun, path=path, full_output=True)

            x = np.arange(-10, 10) / np.pi
            lim_f0, err = lim_f(x * np.pi)
            assert_array_almost_equal(lim_f0, np.sinc(x))
            self.assertTrue(np.all(err.error_estimate < 1.0e-14))
コード例 #13
0
    def _a_levin(omega, f, g, d_g, x, s, basis, *args, **kwds):

        def psi(t, k):
            return d_g(t, *args, **kwds) * basis(t, k)

        j_w = 1j * omega
        nu = np.ones((len(x),), dtype=int)
        nu[0] = nu[-1] = s
        S = np.cumsum(np.hstack((nu, 0)))
        S[-1] = 0
        n = int(S[-2])
        a_matrix = np.zeros((n, n), dtype=complex)
        rhs = np.zeros((n,))
        dff = Limit(nda.Derivative(f))
        d_psi = Limit(nda.Derivative(psi))
        dbasis = basis.derivative
        for r, t in enumerate(x):
            for j in range(S[r - 1], S[r]):
                order = ((j - S[r - 1]) % nu[r])  # derivative order
                dff.fun.n = order
                rhs[j] = dff(t, *args, **kwds)
                d_psi.fun.n = order
                for k in range(n):
                    a_matrix[j, k] = (dbasis(t, k, n=order + 1) +
                                      j_w * d_psi(t, k))
        k1 = np.flatnonzero(1 - np.isfinite(rhs))
        if k1.size > 0:  # Remove singularities
            warnings.warn('Singularities detected! ')
            a_matrix[k1] = 0
            rhs[k1] = 0
        solution = linalg.lstsq(a_matrix, rhs)
        v = basis.eval([-1, 1], solution[0])

        lim_g = Limit(g)
        g_b = np.exp(j_w * lim_g(1, *args, **kwds))
        if np.isnan(g_b):
            g_b = 0
        g_a = np.exp(j_w * lim_g(-1, *args, **kwds))
        if np.isnan(g_a):
            g_a = 0
        return v[1] * g_b - v[0] * g_a
コード例 #14
0
    def aLevinTQ(omega, ff, gg, dgg, x, s, basis, *args, **kwds):
        def Psi(t, k):
            return dgg(t, *args, **kwds) * basis(t, k)

        j_w = 1j * omega
        nu = np.ones((len(x), ), dtype=int)
        nu[0] = nu[-1] = s
        S = np.cumsum(np.hstack((nu, 0)))
        S[-1] = 0
        nn = int(S[-2])
        A = np.zeros((nn, nn), dtype=complex)
        F = np.zeros((nn, ))
        dff = Limit(nda.Derivative(ff))
        dPsi = Limit(nda.Derivative(Psi))
        dbasis = basis.derivative
        for r, t in enumerate(x):
            for j in range(S[r - 1], S[r]):
                order = ((j - S[r - 1]) % nu[r])  # derivative order
                dff.f.n = order
                F[j] = dff(t, *args, **kwds)
                dPsi.f.n = order
                for k in range(nn):
                    A[j, k] = (dbasis(t, k, n=order + 1) + j_w * dPsi(t, k))
        k1 = np.flatnonzero(1 - np.isfinite(F))
        if k1.size > 0:  # Remove singularities
            warnings.warn('Singularities detected! ')
            A[k1] = 0
            F[k1] = 0
        LS = linalg.lstsq(A, F)
        v = basis.eval([-1, 1], LS[0])

        lim_gg = Limit(gg)
        gb = np.exp(j_w * lim_gg(1, *args, **kwds))
        if np.isnan(gb):
            gb = 0
        ga = np.exp(j_w * lim_gg(-1, *args, **kwds))
        if np.isnan(ga):
            ga = 0
        NR = (v[1] * gb - v[0] * ga)
        return NR
コード例 #15
0
    def _a_levin(self, omega, ff, gg, dgg, x, s, basis, *args, **kwds):
        w = evans_webster_weights(omega, gg, dgg, x, basis, *args, **kwds)

        f = Limit(ff)(x, *args, **kwds)
        return np.sum(f * w)
コード例 #16
0
    def aLevinTQ(self, omega, ff, gg, dgg, x, s, basis, *args, **kwds):
        w = evans_webster_weights(omega, gg, dgg, x, basis, *args, **kwds)

        f = Limit(ff)(x, *args, **kwds)
        NR = np.sum(f * w)
        return NR