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)
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)
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() 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,
"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) # Overwrite the standard sorting strategy with the function defined above solver.sorting_strategy = sorting_strategy # Solve the full matrix problem keeping all eigenvalues and vectors # results are stored in solver.E (a 1D array with the eigenvalues) and solver.v # (a 2D array of the eigenvectors). solver.solve(saveall=True) """ The approximation to the physical eigenvalue problem is a matrix eigenvalue problem. The matrix has size d times N (where d is the number of linearized equations and N is the number of grid points). There are thus d times N eigenvalues. Obviously, the number of physical eigenvalues cannot depend on the number of grid points. Some of the solutions found above are therefore not physical (see e.g. the book by Boyd). The solutions were also calculated at fixed number of grid points, N. Convergent solutions are found by increasing N and discarding the eigenvalues that are not present at higher N.