Coverage for pySDC/implementations/transfer_classes/TransferMesh_FFT.py: 100%

25 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-11-02 12:30 +0000

1from scipy.signal import resample 

2 

3from pySDC.core.errors import TransferError 

4from pySDC.core.space_transfer import SpaceTransfer 

5 

6 

7class mesh_to_mesh_fft(SpaceTransfer): 

8 """ 

9 Space transfer between periodic 1d meshes: injection to restrict, Fourier interpolation to prolong. 

10 

11 This implementation can restrict and prolong between 1d meshes with FFT for periodic boundaries 

12 

13 Attributes: 

14 ratio (int): ratio of the fine to the coarse resolution 

15 """ 

16 

17 def __init__(self, fine_prob, coarse_prob, params): 

18 """ 

19 Initialization routine 

20 

21 Args: 

22 fine_prob: fine problem 

23 coarse_prob: coarse problem 

24 params: parameters for the transfer operators 

25 """ 

26 # invoke super initialization 

27 super().__init__(fine_prob, coarse_prob, params) 

28 

29 self.ratio = int(self.fine_prob.nvars / self.coarse_prob.nvars) 

30 

31 def restrict(self, F): 

32 """ 

33 Restriction implementation 

34 

35 Args: 

36 F: the fine level data (easier to access than via the fine attribute) 

37 """ 

38 G = type(F)(self.coarse_prob.init, val=0.0) 

39 

40 if type(F).__name__ == 'mesh': 

41 G[:] = F[:: self.ratio] 

42 elif type(F).__name__ == 'imex_mesh': 

43 G.impl[:] = F.impl[:: self.ratio] 

44 G.expl[:] = F.expl[:: self.ratio] 

45 else: 

46 raise TransferError('Unknown data type, got %s' % type(F)) 

47 return G 

48 

49 def prolong(self, G): 

50 """ 

51 Prolongation implementation 

52 

53 Args: 

54 G: the coarse level data (easier to access than via the coarse attribute) 

55 """ 

56 F = type(G)(self.fine_prob.init, val=0.0) 

57 

58 def _prolong(coarse): 

59 # Fourier interpolation. `resample` also gets the normalisation and the splitting of the 

60 # Nyquist mode right; zero-padding the spectrum by hand placed the coarse Nyquist mode at 

61 # the *fine* Nyquist wavenumber, which is a different function entirely. 

62 return resample(coarse, self.fine_prob.init[0]) 

63 

64 if type(G).__name__ == 'mesh': 

65 F[:] = _prolong(G) 

66 elif type(G).__name__ == 'imex_mesh': 

67 F.impl[:] = _prolong(G.impl) 

68 F.expl[:] = _prolong(G.expl) 

69 else: 

70 raise TransferError('Unknown data type, got %s' % type(G)) 

71 return F