private void ComputeKernelTilde() { //Evaluate the kernel at the interpolation nodes and form the embedded generating kernel vector for a circulant matrix int n_fft_coeffs = 2 * n_interpolation_points_1d; for (int i = 0; i < n_interpolation_points_1d; i++) { for (int j = 0; j < n_interpolation_points_1d; j++) { for (int k = 0; k < n_interpolation_points_1d; k++) { fft[((n_interpolation_points_1d + i) * n_fft_coeffs + n_interpolation_points_1d + j) * n_fft_coeffs + n_interpolation_points_1d + k] = fft[((n_interpolation_points_1d - i) * n_fft_coeffs + n_interpolation_points_1d + j) * n_fft_coeffs + n_interpolation_points_1d + k] = fft[((n_interpolation_points_1d + i) * n_fft_coeffs + n_interpolation_points_1d - j) * n_fft_coeffs + n_interpolation_points_1d + k] = fft[((n_interpolation_points_1d - i) * n_fft_coeffs + n_interpolation_points_1d - j) * n_fft_coeffs + n_interpolation_points_1d + k] = fft[((n_interpolation_points_1d + i) * n_fft_coeffs + n_interpolation_points_1d + j) * n_fft_coeffs + n_interpolation_points_1d - k] = fft[((n_interpolation_points_1d - i) * n_fft_coeffs + n_interpolation_points_1d + j) * n_fft_coeffs + n_interpolation_points_1d - k] = fft[((n_interpolation_points_1d + i) * n_fft_coeffs + n_interpolation_points_1d - j) * n_fft_coeffs + n_interpolation_points_1d - k] = fft[((n_interpolation_points_1d - i) * n_fft_coeffs + n_interpolation_points_1d - j) * n_fft_coeffs + n_interpolation_points_1d - k] = SquaredCauchy(tilde[0], tilde[i], tilde[j], tilde[k]); } } } // Precompute the FFT of the kernel generating matrix Fourier.ForwardMultiDim(fft, new int[] { n_fft_coeffs, n_fft_coeffs, n_fft_coeffs }, FourierOptions.NoScaling); for (int i = fft.Length - 1; i >= 0; i--) { kernel_tilde[i] = fft[i].Real; } }
private void NBodyFFT() { //Compute the values v_{m, n} at the equispaced nodes, multiply the kernel matrix with the coefficients w int n_fft_coeffs = 2 * n_interpolation_points_1d; for (int d = 0; d < n_terms; d += 2) { Array.Clear(fft, 0, fft.Length); for (int i = 0; i < n_interpolation_points_1d; i++) { for (int j = 0; j < n_interpolation_points_1d; j++) { for (int k = 0; k < n_interpolation_points_1d; k++) { fft[(i * n_fft_coeffs + j) * n_fft_coeffs + k] = new Complex(tilde_values[((i * n_interpolation_points_1d + j) * n_interpolation_points_1d + k) * n_terms + d], (d == n_terms - 1) ? 0 : tilde_values[((i * n_interpolation_points_1d + j) * n_interpolation_points_1d + k) * n_terms + d + 1]); } } } Fourier.ForwardMultiDim(fft, new int[] { n_fft_coeffs, n_fft_coeffs, n_fft_coeffs }); // Take the Hadamard product of two complex vectors for (int i = kernel_tilde.Length - 1; i >= 0; i--) { fft[i] *= kernel_tilde[i]; } // Invert the computed values at the interpolated nodes Fourier.InverseMultiDim(fft, new int[] { n_fft_coeffs, n_fft_coeffs, n_fft_coeffs }); for (int i = 0; i < n_interpolation_points_1d; i++) { for (int j = 0; j < n_interpolation_points_1d; j++) { for (int k = 0; k < n_interpolation_points_1d; k++) { tilde_values[((i * n_interpolation_points_1d + j) * n_interpolation_points_1d + k) * n_terms + d] = fft[((n_interpolation_points_1d + i) * n_fft_coeffs + n_interpolation_points_1d + j) * n_fft_coeffs + n_interpolation_points_1d + k].Real; if (d != n_terms - 1) { tilde_values[((i * n_interpolation_points_1d + j) * n_interpolation_points_1d + k) * n_terms + d + 1] = fft[((n_interpolation_points_1d + i) * n_fft_coeffs + n_interpolation_points_1d + j) * n_fft_coeffs + n_interpolation_points_1d + k].Imaginary; } } } } } }