예제 #1
0
def test_legendre_interpolation(show=False):
    """Test the inperpolation routine of LegendreExtremaGrid"""
    from psecas import LegendreExtremaGrid
    import numpy as np

    def psi(x, c):
        from numpy.polynomial.hermite import hermval

        return hermval(x, c) * np.exp(-x**2 / 2)

    N = 40
    zmin = -1.1
    zmax = 1.5
    grid = LegendreExtremaGrid(N, zmin, zmax)

    grid_fine = LegendreExtremaGrid(N * 4, zmin, zmax)
    z = grid_fine.zg

    y = np.exp(grid.zg) * np.sin(5 * grid.zg)
    y_fine = np.exp(z) * np.sin(5 * z)
    y_interpolated = grid.interpolate(z, y)

    if show:
        import matplotlib.pyplot as plt

        plt.figure(2)
        plt.clf()
        plt.title("Interpolation with Legendre")
        plt.plot(z, y_fine, "-")
        plt.plot(z, y_interpolated, "--")
        plt.plot(grid.zg, y, "+")
        plt.show()

    np.testing.assert_allclose(y_fine, y_interpolated, atol=1e-12)
    return (y_fine, y_interpolated)
예제 #2
0
def test_legendre_differentation(show=False):
    """Test the differentation routine of LegendreExtremaGrid"""
    from psecas import LegendreExtremaGrid
    import numpy as np

    N = 20
    zmin = -1
    zmax = 1
    grid = LegendreExtremaGrid(N, zmin, zmax)

    assert grid.zg[0] < grid.zg[-1]

    z = grid.zg
    y = np.exp(z) * np.sin(5 * z)
    yp_exac = np.exp(z) * (np.sin(5 * z) + 5 * np.cos(5 * z))
    yp_num = np.matmul(grid.d1, y)

    if show:
        import matplotlib.pyplot as plt

        plt.figure(1)
        plt.clf()
        plt.title("Differentation with matrix (LegendreExtremaGrid)")
        plt.plot(z, yp_exac, "-")
        plt.plot(z, yp_num, "--")
        plt.show()

    np.testing.assert_allclose(yp_num, yp_exac, atol=1e-16)

    return (yp_num, yp_exac)
예제 #3
0
        """Sorting strategy. E is a list of eigenvalues"""
        # Sort from smallest to largest eigenvalue
        index = np.argsort(np.abs(E))
        return (E, index)


L = 1
hbar = 1
m = 1

# Create grids
N = 32
zmin = 0
grid1 = ChebyshevExtremaGrid(N, zmin, zmax=L, z='x')
grid2 = ChebyshevRootsGrid(N, zmin, zmax=L, z='x')
grid3 = LegendreExtremaGrid(N, zmin, zmax=L, z='x')

grids = list([grid1, grid2, grid3])

# Number of solutions to plot for each grid
modes = 10

# Create figure
plt.figure(1)
plt.clf()
fig, axes = plt.subplots(num=1, ncols=modes, nrows=3, sharey=True, sharex=True)

for j, grid in enumerate(grids):
    # Create system
    system = System(grid, variables='phi', eigenvalue='E')
    system.hbar = hbar
예제 #4
0
def test_bessel_solutions(show=False):
    import numpy as np
    from psecas import Solver, System
    from psecas import (
        ChebyshevExtremaGrid,
        ChebyshevRootsGrid,
        LegendreExtremaGrid,
    )
    from scipy.special import spherical_jn
    """
    We solve the spherical Bessel equation

        r² d²f/dr² + 2 r df/dr +(κ²r² - l(l+1)) f = 0

    on the domain r=[0, 1] with the boundary condition f(1) = 0.
    The exact solutions are the spherical bessel functions of the first kind,
    j_l(κ r).

    The problem is taken from the paper

    Tensor calculus in spherical coordinates using Jacobi polynomials
    Part-II: Implementation and Examples, https://arxiv.org/pdf/1804.09283.pdf

    by Daniel Lecoanet, Geoff Vasil, Keaton Burns, Ben Brown and Jeff Oishi,
    and the results of our script can be compared with their Figure 2.

    A key difference is that we use shifted Chebyshev and Legendre grids, and
    that we enforce the boundary f(0)=0 explicitly. Since we do not treat the
    coordinate singularity at r=0 in using Jacobi polynomials in the clever
    way that Lecoanet+ do, the r^50 scaling shown in their inset is not
    recovered in our calculation.

    Nevertheless, the solutions for the eigenvalues and eigenfunctions are in
    very good agreement with the exact solution, in particular for the extrema
    grids.
    """

    # do_gen_evp = True
    # equation = "sigma*r**2*f = -r**2*dr(dr(f)) -2*r*dr(f) +l*(l+1)*f"

    do_gen_evp = False
    equation = "sigma*f = -dr(dr(f)) -2/r*dr(f) +l*(l+1)/r**2*f"

    # Overwrite the default sorting method in the Solver class
    class Example(Solver):
        def sorting_strategy(self, E):
            """Sorting strategy. E is a list of eigenvalues"""
            # Sort from smallest to largest eigenvalue
            index = np.argsort(np.abs(E))
            return (E, index)

    # Create grids
    N = 500
    zmin = 0
    # grid = ChebyshevRootsGrid(N, zmin, zmax=1, z='r')
    grid1 = ChebyshevExtremaGrid(N, zmin, zmax=1.0, z='r')
    grid2 = ChebyshevRootsGrid(N, zmin, zmax=1.0, z='r')
    grid3 = LegendreExtremaGrid(N, zmin, zmax=1.0, z='r')

    grids = list([grid1, grid2, grid3])

    if show:
        # Create figure
        import matplotlib.pyplot as plt

        plt.figure(1)
        plt.clf()
        fig, axes = plt.subplots(num=1, nrows=3, ncols=2, sharex=True)

    # https://keisan.casio.com/exec/system/1180573465
    kappa_ref = 389.4203848348835221199

    tols = [1e-13, 1e-4, 1e-13]

    for jj, grid in enumerate(grids):

        # Create system
        system = System(grid, variables='f', eigenvalue='sigma')
        system.l = 50

        # Add the first (and only) equation
        system.add_equation(equation, boundary=True)

        # Create a solver object
        solver = Example(grid, system, do_gen_evp=do_gen_evp)

        r = np.linspace(grid.zmin, grid.zmax, 4000)
        E, vec = solver.solve(mode=99)

        kappa = np.sqrt(E)

        # Normalize solution to bessel function exact solution at r = 0.5
        amp = grid.interpolate(0.5, system.result['f'].real) / spherical_jn(
            50, kappa_ref * 0.5)

        # Test statements
        print(grid)
        np.testing.assert_allclose(grid.interpolate(
            r, system.result['f'].real / amp),
                                   spherical_jn(50, kappa_ref * r),
                                   atol=tols[jj])

        np.testing.assert_allclose(kappa,
                                   kappa_ref,
                                   atol=tols[jj],
                                   rtol=tols[jj])

        if show:
            axes[jj, 0].plot(r, grid.interpolate(r, system.result['f'].real))
            axes[jj, 0].plot(r, grid.interpolate(r, system.result['f'].imag))
            axes[jj, 0].set_title(
                type(grid).__name__ +
                r", $\kappa$-error={:1.3e}".format(kappa.real - kappa_ref))

            axes[jj, 1].plot(
                r,
                grid.interpolate(r, system.result['f'].real / amp) -
                spherical_jn(50, kappa_ref * r),
            )
            # axes[jj, 1].plot(z)
            axes[jj, 1].set_title(r'$f(r) - j_\mathcal{l}(\kappa r)$, ' +
                                  type(grid).__name__)

    if show:
        plt.show()
예제 #5
0
# Overwrite the default sorting method in the Solver class
class Example(Solver):
    def sorting_strategy(self, E):
        """Sorting strategy. E is a list of eigenvalues"""
        # Sort from smallest to largest eigenvalue
        index = np.argsort(np.abs(E))
        return (E, index)


# Create grids
N = 500
zmin = 0
# grid = ChebyshevRootsGrid(N, zmin, zmax=1, z='r')
grid1 = ChebyshevExtremaGrid(N, zmin, zmax=1.0, z='r')
grid2 = ChebyshevRootsGrid(N, zmin, zmax=1.0, z='r')
grid3 = LegendreExtremaGrid(N, zmin, zmax=1.0, z='r')

grids = list([grid1, grid2, grid3])

# Create figure
plt.figure(1)
plt.clf()
fig, axes = plt.subplots(num=1, nrows=3, ncols=2, sharex=True)

# https://keisan.casio.com/exec/system/1180573465
kappa_ref = 389.4203848348835221199

for jj, grid in enumerate(grids):

    # Create system
    system = System(grid, variables='f', eigenvalue='sigma')
예제 #6
0
파일: airy.py 프로젝트: tberlok/psecas
    def sorting_strategy(self, E):
        """Sorting strategy. E is a list of eigenvalues"""
        # Sort from smallest to largest eigenvalue
        # We ignore the solutions with negative σ.
        E[E.real < 0.] = np.inf
        index = np.argsort(E)
        return (E, index)


# Create grids
N = 100
zmin = -1
zmax = 1
grid1 = ChebyshevExtremaGrid(N, zmin, zmax)
grid2 = ChebyshevRootsGrid(N, zmin, zmax)
grid3 = LegendreExtremaGrid(N, zmin, zmax)

grids = list([grid1, grid2, grid3])

def get_normalizing_constant(f1, f2):
    """EVP solver return eigenmodes with arbitrary sign"""
    abs_max1_ind = np.argmax(np.abs(f1))
    abs_max2_ind = np.argmax(np.abs(f2))

    val1 = f1[abs_max1_ind] 
    val2 = f2[abs_max2_ind]
    A = val1/val2
    return A


# Create figure
예제 #7
0
def test_infinite_well(show=False):

    import numpy as np
    from psecas import Solver, System
    from psecas import (
        ChebyshevExtremaGrid,
        ChebyshevRootsGrid,
        LegendreExtremaGrid,
    )
    """
    This test solves the Schrödinger equation with three different grids.
    The problem is outlined as follows:

    Solve the Schrödinger equation

        -ħ²/2m ∂²/∂x² Φ + V(x) Φ = E Φ

    for the inifite well potential given by

        V(x) = 0 for 0 < x < L
        V(x) = ∞ otherwise

    For this problem the eigenmodes are sinuisodal and the energies are given
    by

        E = n²ħ²π²/2mL²

    This problem illustrates that the Gauss-Lobatto grids are better at
    handling problems with a boundary conditions since they have grid points
    at z=zmin and z=zmax.

    The test is performed twice, the second time the equation is
    multiplied by minus 1 on both sides. In the first case, Psecas evaluates
    mat2 to be the identity matrix and solves a standard evp.
    The second time, mat2 is not the identity matrix and Psecas therefore
    solves a generalized evp. This is more time consuming, and equation 1
    is therefore the preferred form.

    Psecas does not automatically convert equation 2 to equation 1,
    but simply warns the user that a rewrite of the equations could lead to a
    speed-up.
    """

    equation1 = "E*phi = hbar/(2*m)*dx(dx(phi))"
    equation2 = "-E*phi = -hbar/(2*m)*dx(dx(phi))"

    for equation in [equation1, equation2]:

        # Overwrite the default sorting method in the Solver class
        class Example(Solver):
            def sorting_strategy(self, E):
                """
                Sorting strategy.
                E is a list of eigenvalues
                """
                # Sort from smallest to largest eigenvalue
                index = np.argsort(np.abs(E))
                return (E, index)

        L = 1
        hbar = 1
        m = 1

        # Create grids
        N = 32
        zmin = 0
        grid1 = ChebyshevExtremaGrid(N, zmin, zmax=L, z='x')
        grid2 = ChebyshevRootsGrid(2 * N, zmin, zmax=L, z='x')
        grid3 = LegendreExtremaGrid(N, zmin, zmax=L, z='x')

        grids = list([grid1, grid2, grid3])
        tols = [1e-8, 1e-3, 1e-8]

        # Number of solutions to plot for each grid
        modes = 10

        if show:
            import matplotlib.pyplot as plt
            # Create figure
            plt.figure(1)
            plt.clf()
            fig, axes = plt.subplots(num=1,
                                     ncols=modes,
                                     nrows=3,
                                     sharey=True,
                                     sharex=True)

        for j, grid in enumerate(grids):
            # Create system
            system = System(grid, variables='phi', eigenvalue='E')
            system.hbar = hbar
            system.m = m

            # Add the first (and only) equation
            system.add_equation(equation, boundary=True)

            # Create a solver object
            solver = Example(grid, system)

            z = np.linspace(grid.zmin, grid.zmax, 1000)
            for mode in range(modes):
                E, vec = solver.solve(mode=mode)

                np.testing.assert_allclose(
                    E.real / np.pi**2 * 2,
                    -(mode + 1)**2,
                    atol=tols[j],
                    rtol=tols[j],
                )
                if show:
                    # Plottting
                    axes[j, mode].set_title(r"$E/E_0 = ${:1.5f}".format(
                        E.real / np.pi**2 * 2))
                    axes[j, mode].plot(
                        z, grid.interpolate(z, system.result['phi'].real))
                    axes[j, mode].plot(
                        z, grid.interpolate(z, system.result['phi'].imag))
                    axes[j, 0].set_ylabel(type(grid).__name__)

            if show:
                plt.show()
예제 #8
0
        dvdz_sym = diff(v_sym, z)
        d2vdz_sym = diff(dvdz_sym, z)

        self.v = lambdify(z, v_sym)(zg)
        self.dvdz = lambdify(z, dvdz_sym)(zg)
        self.d2vdz = lambdify(z, d2vdz_sym)(zg)


if __name__ == '__main__':
    import numpy as np
    from psecas import Solver, LegendreExtremaGrid
    import matplotlib.pyplot as plt
    from psecas import plot_solution

    grid = LegendreExtremaGrid(N=200, zmin=-0.5, zmax=0.5)
    system = KelvinHelmholtzMiura(grid, kx=2*np.pi, B=0.2, z1=0, a=1/25.0)
    solver = Solver(grid, system)

    Ns = np.arange(1, 8) * 64
    omega, v, err = solver.iterate_solver(Ns, verbose=True, tol=1e-8)

    print('\nB={:1.2f} has gammma*2a = {:1.6f}'.format(system.B,
                                                       omega.real*system.a*2))

    plot_solution(system, num=1, filename='Ryu_and_Frank1996.pdf')

    # Make figure 4 in Miura & Pritchett (1982)
    # This calculation takes some time.
    if True: