Source code for helpers.ParaDiagHelper
import numpy as np
import scipy.sparse as sp
[docs]
def get_FFT_matrix(N):
"""
Get matrix for computing FFT of size N. Normalization is like "ortho" in numpy.
Compute inverse FFT by multiplying by the complex conjugate (numpy.conjugate) of this matrix
Args:
N (int): Size of the data to be transformed
Returns:
numpy.ndarray: Dense square matrix to compute forward transform
"""
idx_1d = np.arange(N, dtype=complex)
i1, i2 = np.meshgrid(idx_1d, idx_1d)
return np.exp(-2 * np.pi * 1j * i1 * i2 / N) / np.sqrt(N)
[docs]
def get_E_matrix(N, alpha=0):
"""
Get NxN matrix with -1 on the lower subdiagonal, -alpha in the top right and 0 elsewhere
Args:
N (int): Size of the matrix
alpha (float): Negative of value in the top right
Returns:
sparse E matrix
"""
E = sp.diags(
[
-1.0,
]
* (N - 1),
offsets=-1,
).tolil()
E[0, -1] = -alpha
return E
[docs]
def get_J_matrix(N, alpha):
"""
Get matrix for weights in the weighted inverse FFT
Args:
N (int): Size of the matrix
alpha (float): alpha parameter in ParaDiag
Returns:
sparse J matrix
"""
gamma = alpha ** (-np.arange(N) / N)
return sp.diags(gamma)
[docs]
def get_J_inv_matrix(N, alpha):
"""
Get matrix for weights in the weighted FFT
Args:
N (int): Size of the matrix
alpha (float): alpha parameter in ParaDiag
Returns:
sparse J_inv matrix
"""
gamma = alpha ** (-np.arange(N) / N)
return sp.diags(1 / gamma)
[docs]
def get_weighted_FFT_matrix(N, alpha):
"""
Get matrix for the weighted FFT
Args:
N (int): Size of the matrix
alpha (float): alpha parameter in ParaDiag
Returns:
Dense weighted FFT matrix
"""
return get_FFT_matrix(N) @ get_J_inv_matrix(N, alpha)
[docs]
def get_weighted_iFFT_matrix(N, alpha):
"""
Get matrix for the weighted inverse FFT
Args:
N (int): Size of the matrix
alpha (float): alpha parameter in ParaDiag
Returns:
Dense weighted FFT matrix
"""
return get_J_matrix(N, alpha) @ np.conjugate(get_FFT_matrix(N))
[docs]
def get_H_matrix(N, sweeper_params):
"""
Get sparse matrix for computing the collocation update. Requires not to do a collocation update!
Args:
N (int): Number of collocation nodes
sweeper_params (dict): Parameters for the sweeper
Returns:
Sparse matrix for collocation update
"""
assert sweeper_params['quad_type'] == 'RADAU-RIGHT'
H = sp.eye(N).tolil() * 0
H[:, -1] = 1
return H
[docs]
def get_G_inv_matrix(l, L, alpha, sweeper_params):
M = sweeper_params['num_nodes']
I_M = sp.eye(M)
E_alpha = get_E_matrix(L, alpha)
H = get_H_matrix(M, sweeper_params)
gamma = alpha ** (-np.arange(L) / L)
diags = np.fft.fft(1 / gamma * E_alpha[:, 0].toarray().flatten(), norm='backward')
G = (diags[l] * H + I_M).tocsc()
if M > 1:
return sp.linalg.inv(G).toarray()
else:
return 1 / G.toarray()