Source code for implementations.transfer_classes.TransferMesh_FFT
import numpy as np
from pySDC.core.errors import TransferError
from pySDC.core.space_transfer import SpaceTransfer
[docs]
class mesh_to_mesh_fft(SpaceTransfer):
"""
Custom base_transfer class, implements Transfer.py
This implementation can restrict and prolong between 1d meshes with FFT for periodic boundaries
Attributes:
irfft_object_fine: planned FFT for backward transformation, real-valued output
rfft_object_coarse: planned real-valued FFT for forward transformation
"""
def __init__(self, fine_prob, coarse_prob, params):
"""
Initialization routine
Args:
fine_prob: fine problem
coarse_prob: coarse problem
params: parameters for the transfer operators
"""
# invoke super initialization
super().__init__(fine_prob, coarse_prob, params)
self.ratio = int(self.fine_prob.nvars / self.coarse_prob.nvars)
[docs]
def restrict(self, F):
"""
Restriction implementation
Args:
F: the fine level data (easier to access than via the fine attribute)
"""
G = type(F)(self.coarse_prob.init, val=0.0)
if type(F).__name__ == 'mesh':
G[:] = F[:: self.ratio]
elif type(F).__name__ == 'imex_mesh':
G.impl[:] = F.impl[:: self.ratio]
G.expl[:] = F.expl[:: self.ratio]
else:
raise TransferError('Unknown data type, got %s' % type(F))
return G
[docs]
def prolong(self, G):
"""
Prolongation implementation
Args:
G: the coarse level data (easier to access than via the coarse attribute)
"""
F = type(G)(self.fine_prob.init, val=0.0)
def _prolong(coarse):
coarse_hat = np.fft.rfft(coarse)
fine_hat = np.zeros(self.fine_prob.init[0] // 2 + 1, dtype=np.complex128)
half_idx = self.coarse_prob.init[0] // 2
fine_hat[0:half_idx] = coarse_hat[0:half_idx]
fine_hat[-1] = coarse_hat[-1]
return np.fft.irfft(fine_hat) * self.ratio
if type(G).__name__ == 'mesh':
F[:] = _prolong(G)
elif type(G).__name__ == 'imex_mesh':
F.impl[:] = _prolong(G.impl)
F.expl[:] = _prolong(G.expl)
else:
raise TransferError('Unknown data type, got %s' % type(G))
return F