Ejemplo n.º 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
Ejemplo n.º 2
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
Ejemplo n.º 3
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
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def test_parser_boundaries(verbose=False):
    """
    Here we add the value B
    to the boundary without setting it in the system.
    This should return a NameError
    """
    # Create system
    system = System(grid, variables='f', eigenvalue='sigma')

    # Add the first (and only) equation
    system.add_equation("sigma*z*f = dz(dz(f))")
    
    system.add_boundary('f', 'Dirichlet', 'B*f = 0')

    solver = Solver(grid, system)

    with pytest.raises(NameError) as e_info:
        # The error is found when the solve method is called
        solver.solve()

    if verbose:
        print(str(e_info.value))
Ejemplo n.º 6
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)
Ejemplo n.º 7
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
Ejemplo n.º 8
0
def test_solver_methods(verbose=False):
    """Show how the solver class methods can be called directly,
       using the MTI as an example.
       This can be useful when setting up a new problem.
    """
    import numpy as np
    from psecas import Solver, ChebyshevExtremaGrid
    from psecas.systems.mti import MagnetoThermalInstability
    from scipy.linalg import eig

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

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

    solver = Solver(grid, system)

    solver.get_matrix1(verbose=verbose)

    solver.get_matrix2(verbose=verbose)

    E, V = eig(solver.mat1.toarray(), solver.mat2.toarray())

    # Sort the eigenvalues
    E, index = solver.sorting_strategy(E)

    mode = 0

    # Choose the eigenvalue mode value only
    sigma = E[index[mode]]
    v = V[:, index[mode]]

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

    # Compare with solve without using OPinv
    solver.solve(useOPinv=False, saveall=True)
    np.testing.assert_allclose(solver.E[mode], sigma, atol=1e-8)
Ejemplo n.º 9
0
def test_parser_findmatrices(verbose=False):
    """
    Here we add the value A
    to the equation without setting it in the system.
    This should return a NameError
    """
    
    # Create system
    system = System(grid, variables='f', eigenvalue='sigma')

    # Add the first (and only) equation
    system.add_equation("sigma*z*f = dz(dz(f)) + 2*A*f")

    with pytest.raises(NameError) as e_info:

        solver = Solver(grid, system)

    if verbose:
        print(str(e_info.value))
Ejemplo n.º 10
0
        omega, v, err = solver.iterate_solver(Ns, verbose=False, tol=1e-8)

        return -omega.real

    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
Ejemplo n.º 11
0
        drhodz_sym = sym.diff(rho_sym, z)
        domgdz_sym = sym.diff(Omg_sym, z)

        zg = self.grid.zg
        self.rho = np.ones_like(zg) * lambdify(z, rho_sym)(zg)
        self.Omg = np.ones_like(zg) * lambdify(z, Omg_sym)(zg)
        self.shr = np.ones_like(zg) * lambdify(z, shr_sym)(zg)
        self.drhodz = np.ones_like(zg) * lambdify(z, drhodz_sym)(zg)
        self.domgdz = np.ones_like(zg) * lambdify(z, domgdz_sym)(zg)


# Create a grid
grid = ChebyshevRationalGrid(N=200, C=0.2)
# grid = ChebyshevExtremaGrid(N=199, zmin=-5, zmax=5)

# Create the system
system = VerticalShearInstability(grid,
                                  variables=['rh', 'wx', 'wy', 'wz'],
                                  eigenvalue='sigma')

# The linearized equations
system.add_equation("-sigma*rh = - 1j*kx*wx - 1/h*dz(wz) - 1/h*drhodz/rho*wz")
system.add_equation("-sigma*wx = + 2*Omg*wy - 1j*kx*(h/O0)**2*rh")
system.add_equation("-sigma*wy = - (2*Omg + shr)*wx - 1/h*domgdz*wz")
system.add_equation("-sigma*wz = - h/O0**2*dz(rh)", boundary=True)

solver = Solver(grid, system, do_gen_evp=True)

omega, vec = solver.solve(mode=0, verbose=True)
plot_solution(system)
Ejemplo n.º 12
0
    Berlok, T. & Pfrommer, C. (2019). *On the Kelvin-Helmholtz instability 
    with smooth initial conditions – Linear theory and simulations*, MNRAS,
    485, 908

    Another reference for the KHI with anisotropic viscosity is

    Suzuki, K., Ogawa, T., Matsumoto, Y., & Matsumoto, R. (2013).
    Magnetohydrodynamic simulations of the formation of cold fronts in
    clusters of galaxies: Effects of anisotropic viscosity. Astrophysical
    Journal, 768(2). https://doi.org/10.1088/0004-637X/768/2/175
"""

directory = './data/'
kx_global = np.linspace(3, 4, 5)
kx_local = kx_global[comm.rank :: comm.size]

grid = FourierGrid(N=64, zmin=0, zmax=2)
system = KelvinHelmholtzUniform(grid, beta=1e4, nu=1e-2, kx=0)
io = IO(system, directory, __file__, len(kx_global))

solver = Solver(grid, system)

for i in range(len(kx_local)):
    t1 = time.time()
    system.kx = kx_local[i]
    omega, v = solver.solve()
    io.save_system(i)
    io.log(i, time.time() - t1, 'kx = {:1.4e}'.format(system.kx))

io.finished()
Ejemplo n.º 13
0
and is solved  by employing a Neumann boundary condition on F.

One of the modes obtained here, with KH=3.1979, is not found
when solving 

    -h K² G = z G' + G'' 
    
Visual inspection reveals that the extra mode is numerical garbage.
Automated detection of such modes would be a good feature to implement.
"""

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

ch = Solver(grid, system)


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)


# Overwrite the default sorting strategy in the Solver class
ch.sorting_strategy = sorting_strategy

plt.figure(1)
plt.clf()
Ejemplo n.º 14
0
        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:

        # 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
Ejemplo n.º 15
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')
Ejemplo n.º 16
0
import numpy as np
from psecas import Solver, FourierGrid
from psecas.systems.kh_uniform import KelvinHelmholtzUniform
from psecas import save_system
from psecas import plot_solution
import matplotlib.pyplot as plt

kxmax = 4.54704305
# omega = 1.7087545
grid = FourierGrid(N=64, zmin=0, zmax=2)
system = KelvinHelmholtzUniform(grid, beta=1e3, nu=1e-2, kx=kxmax)
# Set up a solver
solver = Solver(grid, system)
# Iteratively solve
Ns = np.hstack((np.arange(1, 5) * 16, np.arange(3, 24) * 32))
omega, vec, err = solver.iterate_solver(Ns, verbose=True, tol=1e-8)
phi = np.arctan(vec[2].imag / vec[2].real)
solver.keep_result(omega, vec * np.exp(-1j * phi), mode=0)

# 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
Ejemplo n.º 17
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
Ejemplo n.º 18
0
    485, 908

    and the equilibrium has been previously been used for simulations in

    Lecoanet, D., McCourt, M., Quataert, E., Burns, K. J., Vasil, G. M.,
    Oishi, J. S., O’Leary, R. M. (2016).
    A validated non-linear kelvin-helmholtz benchmark for numerical
    hydrodynamics, MNRAS, 455(4), 4274–4288.
    https://doi.org/10.1093/mnras/stv2564
"""

# Plot omega vs kx
if True:
    grid = FourierGrid(N=64, zmin=0.0, zmax=2.0)
    system = KelvinHelmholtzHydroOnly(grid, u0=1.0, delta=1.0, kx=0)
    solver = Solver(grid, system)

    omega_vec = []
    kx_vec = np.linspace(0.1, 8, 15)
    for kx in kx_vec:
        t1 = time.time()
        system.kx = kx
        (omega, v) = solver.solve()
        omega_vec.append(omega)
        print(kx, omega)
        t2 = time.time()
        print("Solver took {} seconds".format(t2 - t1))
    omega_vec = np.array(omega_vec)

    plt.figure(1)
    # plt.clf()
Ejemplo n.º 19
0
by Lloyd Trefethen and this Python script reproduces the figure on
page 89.
"""

# Create grid
grid = FourierGrid(64, zmin=0, zmax=2*np.pi, z='x')

# Create the system
system = System(grid, variables='u', eigenvalue='sigma')
system.q = 1

# Add the first (and only) equation
system.add_equation("sigma*u = 2*q*np.cos(2*x)*u - dx(dx(u))")

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

def sorting_strategy(E):
    """Sorting strategy. E is a list of eigenvalues"""
    # Sort from smallest to largest eigenvalue
    index = np.argsort(E)
    return (E, index)

solver.sorting_strategy = sorting_strategy

sigmas = []
for q in np.arange(0, 15, 0.2):

    # Set q in system object
    system.q = q
Ejemplo n.º 20
0
import numpy as np
from psecas import Solver, FourierGrid
from psecas.systems.kh_hydro import KelvinHelmholtzHydroOnly
import time
import matplotlib.pyplot as plt

# Initialize grid, system and solver for hydrodynamic KHI
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)

# Define a sorting strategy for the eigenvalues
# This function depends on the physical system
def sorting_strategy(E):
    """
    The default sorting strategy.

    "Large" real and imaginary eigenvalues are removed and the eigenvalues
    are sorted from largest to smallest
    """
    import numpy as np

    # Set large values to zero, as they are presumably numerical artifact
    # and unphysical.
    E[np.abs(E.real) > 20.0] = 0
    E[np.abs(E.imag) > 20.0] = 0
    # Sort from largest to smallest eigenvalue
    index = np.argsort(np.real(E))[::-1]
    return (E, index)