def genarray(shape): fft = randn(shape, dtype) + 1j * randn(shape, dtype) k = fftfreq(shape[1:-1], mode='absolute') shape_fac = math.sqrt(math.mean(shape[1:-1])) # 16: 4, 64: 8, 256: 24, fft *= (1 / (k + 1))**power * power * shape_fac array = math.real(math.ifft(fft)).astype(dtype) return array
def fourier_poisson(tensor, times=1): """ Inverse operation to `fourier_laplace`. """ frequencies = math.fft(math.to_complex(tensor)) k = fftfreq(math.staticshape(tensor)[1:-1], mode='square') fft_laplace = -(2 * np.pi)**2 * k fft_laplace[(0, ) * math.ndims(k)] = np.inf inv_fft_laplace = 1 / fft_laplace inv_fft_laplace[(0, ) * math.ndims(k)] = 0 return math.real(math.ifft(frequencies * inv_fft_laplace**times))
def fourier_laplace(tensor, times=1): """ Applies the spatial laplce operator to the given tensor with periodic boundary conditions. *Note:* The results of `fourier_laplace` and `laplace` are close but not identical. This implementation computes the laplace operator in Fourier space. The result for periodic fields is exact, i.e. no numerical instabilities can occur, even for higher-order derivatives. :param tensor: tensor, assumed to have periodic boundary conditions :param times: number of times the laplace operator is applied. The computational cost is independent of this parameter. :return: tensor of same shape as `tensor` """ frequencies = math.fft(math.to_complex(tensor)) k = fftfreq(math.staticshape(tensor)[1:-1], mode='square') fft_laplace = -(2 * np.pi)**2 * k return math.real(math.ifft(frequencies * fft_laplace**times))
def abs_square(complex): return math.imag(complex)**2 + math.real(complex)**2
def fourier_laplace(tensor): frequencies = math.fft(math.to_complex(tensor)) k = fftfreq(math.staticshape(tensor)[1:-1], mode='square') fft_laplace = -(2 * np.pi)**2 * k return math.real(math.ifft(frequencies * fft_laplace))