Beispiel #1
0
def test_kh_uniform_solution(show=False, verbose=False):
    """Test eigenvalue solver using FourierGrid"""
    import numpy as np
    from psecas import Solver, FourierGrid
    from psecas.systems.kh_uniform import KelvinHelmholtzUniform

    grid = FourierGrid(N=64, zmin=0, zmax=2)

    system = KelvinHelmholtzUniform(grid, beta=1e4, nu=1e-2, kx=3.52615254237)
    system.u0 = 1.

    solver = Solver(grid, system)

    Ns = np.hstack((np.arange(2, 16) * 32, np.arange(2, 12) * 64))
    for useOPinv in [True, False]:
        omega, v, err = solver.iterate_solver(Ns,
                                              tol=1e-5,
                                              useOPinv=useOPinv,
                                              verbose=verbose)
    np.testing.assert_allclose(1.66548246011, omega, atol=1e-5)

    if show:
        from psecas import plot_solution

        plot_solution(system, smooth=True, num=2)

    # Check that information converged is set to False when solver does not converge
    solver.iterate_solver(np.arange(1, 3) * 16,
                          tol=1e-16,
                          useOPinv=useOPinv,
                          verbose=verbose)
    assert solver.system.result['converged'] is False

    return err
Beispiel #2
0
def test_channel(show=False, verbose=False):
    """Test eigenvalue solver using ChebyshevRationalGrid"""
    import numpy as np
    from psecas import Solver, ChebyshevRationalGrid, System

    grid = ChebyshevRationalGrid(N=199, z='z')

    class Channel(System):
        def make_background(self):
            import numpy as np

            zg = self.grid.zg
            self.h = np.exp(-zg**2 / 2)

    # Create the Channel system
    system = Channel(grid, variables='G', eigenvalue='K2')

    # Add the first (and only) equation
    system.add_equation("-h*K2*G = dz(dz(G)) +z*dz(G)", boundary=True)
    solver = Solver(grid, system, do_gen_evp=True)

    # Number of modes to test
    modes = 3
    results = np.zeros(modes, dtype=np.complex128)
    checks = np.array([85.08037778, 69.4741069099, 55.4410282999])

    def sorting_strategy(E):
        """Sorting strategy for channel modes"""
        E[E.real > 100.0] = 0
        E[E.real < -10.0] = 0
        index = np.argsort(np.real(E))[::-1]
        return (E, index)

    solver.sorting_strategy = sorting_strategy

    if show:
        import matplotlib.pyplot as plt

        plt.figure(3)
        plt.clf()
        fig, axes = plt.subplots(num=3, ncols=modes, sharey=True)
    for mode in range(modes):
        Ns = np.arange(1, 6) * 32
        omega, vec, err = solver.iterate_solver(Ns, mode=mode, verbose=True)
        results[mode] = omega
        if show:
            phi = np.arctan(vec[2].imag / vec[2].real)
            solver.keep_result(omega, vec * np.exp(-1j * phi), mode)
            axes[mode].set_title(r"$\sigma = ${:1.4f}".format(omega.real),
                                 fontsize=10)
            axes[mode].plot(grid.zg, system.result['G'].real)
            axes[mode].plot(grid.zg, system.result['G'].imag)
            axes[mode].set_xlim(-4, 4)

    if show:
        plt.show()

    np.testing.assert_allclose(results, checks, rtol=1e-6)
Beispiel #3
0
    def f(kx):
        grid = FourierGrid(N=64, zmin=0.0, zmax=2.0)
        system = KelvinHelmholtzHydroOnly(grid, u0=1.0, delta=1.0, kx=kx)
        solver = Solver(grid, system)

        Ns = np.hstack((np.arange(1, 5) * 16, np.arange(3, 12) * 32))
        omega, v, err = solver.iterate_solver(Ns, verbose=False, tol=1e-8)

        return -omega.real
Beispiel #4
0
    def f(kx):
        grid = FourierGrid(N=64, zmin=0.0, zmax=2.0)
        system = KelvinHelmholtzUniform(grid, beta=5, nu=0, kx=kx)
        solver = Solver(grid, system)

        Ns = np.hstack((np.arange(4, 5) * 16, np.arange(3, 16) * 32))
        omega, v, err = solver.iterate_solver(Ns, verbose=True, tol=1e-8)

        return -omega.real
Beispiel #5
0
def f(kx, **kwargs):

    # Set up a grid
    grid = FourierGrid(N=64, zmin=0, zmax=2)
    system = KelvinHelmholtzUniform(grid, beta=1e3, nu=0, kx=kx)

    if 'nu' in kwargs.keys():
        system.nu = kwargs['nu']

    # Set up a solver
    solver = Solver(grid, system)

    # Iteratively solve
    Ns = np.hstack((np.arange(1, 5) * 16, np.arange(3, 12) * 32))
    omega, v, err = solver.iterate_solver(Ns, verbose=False, tol=1e-4)

    return -omega.real
Beispiel #6
0
def test_mti_solution(show=False, verbose=False):
    """Test eigenvalue solver using ChebyshevExtremaGrid"""
    import numpy as np
    from psecas import Solver, ChebyshevExtremaGrid
    from psecas.systems.mti import MagnetoThermalInstability

    grid = ChebyshevExtremaGrid(N=64, zmin=0, zmax=1)

    system = MagnetoThermalInstability(grid, beta=1e5, Kn0=200, kx=4 * np.pi)
    system.beta = 1e5
    system.Kn0 = 200

    assert system.Kn0 == 200
    assert system.beta == 1e5

    solver = Solver(grid, system)

    Ns = np.hstack(np.arange(1, 10) * 16)
    mode = 0
    omega, vec, err = solver.iterate_solver(Ns,
                                            mode=mode,
                                            tol=1e-8,
                                            verbose=verbose)

    system.get_bx_and_by()

    if show:
        from psecas import plot_solution

        phi = np.arctan(vec[2].imag / vec[2].real)
        solver.keep_result(omega, vec * np.exp(-1j * phi), mode=mode)

        plot_solution(system, smooth=True, num=1)

    np.testing.assert_allclose(1.7814514515967603, omega, atol=1e-8)

    return err
Beispiel #7
0
    a = 3.512831867406509
    b = 3.512831875508205
    (a, b) = golden_section(f, a, b, tol=1e-8)

# Create initial conditions for Athena simulation
if True:
    from psecas import save_system

    kxmax = 3.5128319
    grid = FourierGrid(N=256, zmin=0.0, zmax=2.0)
    system = KelvinHelmholtzHydroOnly(grid, u0=1.0, delta=1.0, kx=kxmax)
    solver = Solver(grid, system)

    Ns = np.hstack((np.arange(1, 5) * 16, np.arange(3, 12) * 32))
    omega, v, err = solver.iterate_solver(Ns, verbose=True, tol=1e-8)

    # Normalize eigenmodes
    y = np.vstack([
        system.result["dvx"].real,
        system.result["dvx"].imag,
        system.result["dvz"].real,
        system.result["dvz"].imag,
    ])

    val = np.max(np.abs(y))
    for key in system.variables:
        system.result[key] /= val

    # Save system pickle object
    save_system(system, "./khi_hydro_delta.p")
Beispiel #8
0
# Overwrite the default sorting strategy in the Solver class
ch.sorting_strategy = sorting_strategy

plt.figure(1)
plt.clf()
modes = 11
fig, axes = plt.subplots(num=1,
                         nrows=2,
                         ncols=modes,
                         sharex=True,
                         sharey='row')
for mode in range(modes):
    Ns = np.hstack((np.arange(3, 6) * 32, np.arange(4, 12) * 64))
    K2, vec, err = ch.iterate_solver(Ns,
                                     mode=mode,
                                     tol=1e-4,
                                     verbose=True,
                                     guess_tol=5e-3)
    K = np.sqrt(K2.real)
    phi = np.arctan(vec[2].imag / vec[2].real)
    A = np.max(np.abs(vec))
    ch.keep_result(K2, vec * np.exp(-1j * phi) / A, mode=mode)
    axes[0, mode].set_title(r"$\sigma = ${:1.4f}".format(K), fontsize=10)
    axes[0, mode].plot(grid.zg, system.result["F"].real)
    axes[0, mode].plot(grid.zg, system.result["F"].imag)
    axes[0, mode].set_xlim(-4, 4)
    axes[1, mode].set_xlabel(r'$z$')

    G = grid.der(system.result['F']) / K
    axes[1, mode].plot(grid.zg, G.real)
    axes[1, mode].plot(grid.zg, G.imag)
Beispiel #9
0
from psecas.systems.kh_uniform import KelvinHelmholtzUniform
"""
    This example shows how the eigenmodes can be stored in text format which
    can be loaded into the MHD code Athena (Stone, J. et al, 2008).

    It also shows how to save a system using Python's pickle package.
"""

# Set up a grid
grid = FourierGrid(N=64, zmin=0, zmax=2)

# Set up the system of equations
kx = 4.627762711864407
# kx = 2*np.pi
system = KelvinHelmholtzUniform(grid, beta=1e3, nu=1e-2, kx=kx)

# Set up a solver
solver = Solver(grid, system)

# Iteratively solve
Ns = np.hstack((np.arange(1, 5) * 32, np.arange(3, 12) * 64))
solver.iterate_solver(Ns, verbose=True, tol=1e-10)

# Write files for loading into Athena
write_athena(system, Nz=256, Lz=2.0)

# Write directly to the Athena directory
write_athena(system, Nz=256, Lz=2.0, path='/Users/berlok/codes/athena/bin/')

save_system(system, '/Users/berlok/codes/athena/bin/kh-visc.p')
Beispiel #10
0
The solver class in Psecas contains a different method, iterate_solver,
which increases N until one eigenvalue agrees with the value found at the
previous value of N (to within relative and absolute tolerances, tol & atol).
This method can only find one eigenmode at a time (unlike the solve method
which finds all eigenvalues but is unable to check for convergence and can be
very expensive to call at high N). Most often, one is only interested in the
fastest growing mode (or the first few). This can be controlled with the
input 'mode' in the call to iterate_solver.
"""

# Let us find converged solutions

# Define a range of grid resolutions to try
Ns = np.hstack((np.arange(1, 5) * 32, np.arange(3, 20) * 64))

# Solve for the fastest growing mode (mode=0)
omega, v, err = solver.iterate_solver(Ns, verbose=True, tol=1e-6, mode=0)

# Solve for the second fastest growing mode (mode=1)
omega, v, err = solver.iterate_solver(Ns, verbose=True, tol=1e-6, mode=1)

"""
The sorting_strategy function is necessary to weed out the worst of the
numerical eigenvalues. For some physical systems, infinite or nan solutions
are returned. These are discarded by the sorting_strategy function.
The solver class is initialized with a standard sorting_strategy that has
worked well on the problems I have considered so far.
One should however be careful not to remove physical eigenvalues and for
some problems it is probably necessary to define a new sorting_strategy.
"""
Beispiel #11
0
system.add_equation(
    "-r*r*sigma*bphi = - 1j*kz*r*r*vphi - 1j*kz*q*r**(2-q)*Aphi - eta*(Drbphi) - lh*va*1j*kz*(DrAphi)"
)

# The boundary conditions
Aphi_bound = 'r**2*dr(dr(Aphi)) + r*dr(Aphi) - Aphi = 0'
system.add_boundary('vr', 'Dirichlet', 'Dirichlet')
system.add_boundary('vphi', 'Dirichlet', 'Dirichlet')
system.add_boundary('vz', 'Neumann', 'Neumann')
system.add_boundary('Aphi', Aphi_bound, Aphi_bound)
system.add_boundary('bphi', 'Dirichlet', 'Dirichlet')

system.add_substitution(
    'DrAphi = r*r*dr(dr(Aphi)) + r*dr(Aphi) - Aphi - kz**2*r*r*Aphi')
system.add_substitution(
    'Drbphi = r*r*dr(dr(bphi)) + r*dr(bphi) - bphi - kz**2*r*r*bphi')

solver = Solver(grid, system)

mode = 0
Ns = np.arange(1, 32) * 32 - 1
omega, vec, err = solver.iterate_solver(Ns, mode=mode, verbose=True, tol=1e-4)
phi = np.arctan(vec[2].imag / vec[2].real)
solver.keep_result(omega, vec * np.exp(-1j * phi), mode=mode)

if isinstance(grid, ChebyshevTLnGrid):
    plot_solution(system, limits=[0, 1.5])
    plt.xlim(0, 1.5)
else:
    plot_solution(system)
Beispiel #12
0
def test_mri_solution(show=False, verbose=False):
    """Test eigenvalue solver using ChebyshevExtremaGrid"""
    import numpy as np
    from psecas import Solver, ChebyshevExtremaGrid, System

    class HallMRI(System):
        def __init__(self, grid, kz, variables, eigenvalue):
            # Set parameters
            self.q = 1.5
            self.eta = 0.003
            self.lh = 1
            self.h = 0.25
            self.va = 0.002
            self.kz = kz

            super().__init__(grid, variables, eigenvalue)

    # Create a grid
    grid = ChebyshevExtremaGrid(N=128, zmin=1, zmax=2, z='r')

    variables = ['rho', 'vr', 'vphi', 'vz', 'Aphi', 'bphi']

    kz = 2 * np.pi

    # Create the system
    system = HallMRI(grid, kz, variables=variables, eigenvalue='sigma')

    # The linearized equations
    system.add_equation("-r*sigma*rho = r*dr(vr) + vr + 1j*kz*r*vz")
    system.add_equation(
        "-r*r*sigma*vr = - 2*r**(2-q)*vphi + h**2*r*r*dr(rho) + va**2*(DrAphi)"
    )
    system.add_equation("-sigma*vphi = + (2-q)*r**(-q)*vr - va**2*1j*kz*bphi")
    system.add_equation("-sigma*vz = h**2*1j*kz*rho")
    system.add_equation(
        "-r*r*sigma*Aphi = + r*r*vr - eta*(DrAphi) + lh*va*1j*kz*r*r*bphi")
    system.add_equation(
        "-r*r*sigma*bphi = - 1j*kz*r*r*vphi - 1j*kz*q*r**(2-q)*Aphi - eta*(Drbphi) - lh*va*1j*kz*(DrAphi)"
    )

    # The boundary conditions
    Aphi_bound = 'r**2*dr(dr(Aphi)) + r*dr(Aphi) - Aphi = 0'
    system.add_boundary('vr', 'Dirichlet', 'Dirichlet')
    system.add_boundary('vphi', 'Dirichlet', 'Dirichlet')
    system.add_boundary('vz', 'Neumann', 'Neumann')
    system.add_boundary('Aphi', Aphi_bound, Aphi_bound)
    system.add_boundary('bphi', 'Dirichlet', 'Dirichlet')

    # Short hands for long expressions for derivatives
    system.add_substitution(
        'DrAphi = r*r*dr(dr(Aphi)) + r*dr(Aphi) - Aphi - kz**2*r*r*Aphi')
    system.add_substitution(
        'Drbphi = r*r*dr(dr(bphi)) + r*dr(bphi) - bphi - kz**2*r*r*bphi')

    solver = Solver(grid, system)

    mode = 0
    Ns = np.hstack(np.arange(1, 10) * 32)
    omega, vec, err = solver.iterate_solver(Ns,
                                            mode=mode,
                                            tol=1e-8,
                                            verbose=verbose)

    if show:
        from psecas import plot_solution

        phi = np.arctan(vec[2].imag / vec[2].real)
        solver.keep_result(omega, vec * np.exp(-1j * phi), mode=mode)

        plot_solution(system, smooth=True, num=1)

    np.testing.assert_allclose(0.09892641, omega, atol=1e-8)

    return err
Beispiel #13
0
        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:

        # The iterative solver is more precise but slow at high kx
        # Set fast=True to instead run with a fixed grid size and get a figure
        # much faster. The result looks okay but is imprecise at high k!
        fast = False
Beispiel #14
0
        return -omega.real

    (a, b) = golden_section(f, 3.512295, 3.513135, tol=1e-5)

# Create initial conditions for Athena simulation
if False:
    from psecas import write_athena, save_system

    kxmax = 3.5128286141291243
    grid = FourierGrid(N=64, zmin=0.0, zmax=2.0)
    system = KelvinHelmholtzHydroOnly(grid, u0=1.0, delta=1.0, kx=kxmax)
    solver = Solver(grid, system)

    Ns = np.hstack((np.arange(1, 5) * 16, np.arange(3, 12) * 32))
    omega, v, err = solver.iterate_solver(Ns, verbose=False, tol=1e-6)

    # Write files for loading into Athena
    # write_athena(system, Nz=256, Lz=2.0)

    # Write directly to the Athena directory
    write_athena(
        system, Nz=256, Lz=2.0, path='/Users/berlok/codes/athena/bin/'
    )

    save_system(system, '/Users/berlok/codes/athena/bin/kh-with-delta.p')

    plt.figure(1)
    plt.plot(kxmax, omega.real, '+')

    Lx = 2 * np.pi / system.kx
Beispiel #15
0
"""

grid = ChebyshevRationalGrid(N=32, C=0.4)

u0 = 1.0
delta = 1.0
kx = 5.1540899
kx = 3.5128310

system = KelvinHelmholtzHydroOnlySlab(grid, u0, delta, kx)
system.boundaries = [True, True, True, True]

solver = Solver(grid, system)

Ns = np.arange(1, 32) * 32 - 1
omega, vec, err = solver.iterate_solver(Ns, mode=0, verbose=True)

xmin = 0
xmax = 2 * np.pi / kx
zmin = -4
zmax = 4

Nx = 256
Nz = 1024

plt.rc("image", origin="lower", cmap="RdBu", interpolation="None")

extent = [xmin, xmax, zmin, zmax]

phi = np.arctan(vec[2].imag / vec[2].real)
solver.keep_result(omega, vec * np.exp(-1j * phi), mode=0)