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
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
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
def test_fourier_interpolation(show=False): """Test the inperpolation routine of FourierGrid""" import numpy as np from psecas import FourierGrid N = 16 zmin = 0 zmax = np.pi * np.sqrt(2) grid = FourierGrid(N, zmin, zmax) grid_fine = FourierGrid(N * 4, zmin, zmax) z = grid_fine.zg # y = np.sin(5 * 2 * np.pi * grid.zg / grid.L) # y_fine = np.sin(5 * 2 * np.pi * z / grid.L) y = (np.sin(5 * 2 * np.pi * grid.zg / grid.L) * np.cos(2 * np.pi * grid.zg / grid.L)**2) y_fine = (np.sin(5 * 2 * np.pi * z / grid.L) * np.cos(2 * np.pi * z / grid.L)**2) y_interpolated = grid.interpolate(z, y) if show: import matplotlib.pyplot as plt plt.figure(1) plt.clf() plt.title("Interpolation with Fourier series") 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)
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
def test_fourier_differentation(show=False): """Test the differentation routine of FourierGrid""" import numpy as np from psecas import FourierGrid N = 256 zmin = 0 zmax = 2 grid = FourierGrid(128, -20, 30) # Use the setter methods grid.zmin = zmin grid.zmax = zmax grid.N = N assert grid.zmin == zmin assert grid.zmax == zmax assert grid.N == N assert grid.zg[0] < grid.zg[-1] z = grid.zg y = np.tanh((z - 1.5) / 0.05) - np.tanh((z - 0.5) / 0.05) + 1.0 yp_exac = (-np.tanh((z - 1.5) / 0.05)**2 / 0.05 + np.tanh( (z - 0.5) / 0.05)**2 / 0.05) yp_num = np.matmul(grid.d1, y) np.testing.assert_allclose(yp_num, grid.der(y), atol=1e-16) if show: import matplotlib.pyplot as plt plt.figure(1) plt.clf() plt.title("Differentation with matrix (FourierGrid)") plt.plot(z, yp_exac, "-") plt.plot(z, yp_num, "--") plt.show() np.testing.assert_allclose(yp_num, yp_exac, atol=1e-7) return (yp_num, yp_exac)
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 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))
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()
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)
""" The Mathieu equation is given by -uₓₓ + 2 q cos(2x) = σ u where σ is the eigenvalue and q is a parameter. We solve for u(x) and σ by using the Fourier grid. This example is taken from the book *Spectral methods in Matlab* 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)