#include #include #include using namespace amrex; using namespace Gpu; SpectralKSpace::SpectralKSpace( const BoxArray& realspace_ba, const DistributionMapping& dm, const RealVect realspace_dx ) { // Store the cell size dx = realspace_dx; // Create the box array that corresponds to spectral space BoxList spectral_bl; // Create empty box list // Loop over boxes and fill the box list for (int i=0; i < realspace_ba.size(); i++ ) { // For local FFTs, boxes in spectral space start at 0 in each direction // and have the same number of points as the real space box // TODO: this will be different for the hybrid FFT scheme Box realspace_bx = realspace_ba[i]; Box bx = Box( IntVect::TheZeroVector(), realspace_bx.bigEnd() - realspace_bx.smallEnd() ); spectral_bl.push_back( bx ); } spectralspace_ba.define( spectral_bl ); // Allocate the components of the k vector: kx, ky (only in 3D), kz for (int i_dim=0; i_dim& k = k_comp[mfi]; // Allocate k to the right size int N = bx.length( i_dim ); k.resize( N ); // Fill the k vector const Real dk = 2*MathConst::pi/(N*dx[i_dim]); AMREX_ALWAYS_ASSERT_WITH_MESSAGE( bx.smallEnd(i_dim) == 0, "Expected box to start at 0, in spectral space."); AMREX_ALWAYS_ASSERT_WITH_MESSAGE( bx.bigEnd(i_dim) == N-1, "Expected different box end index in spectral space."); // Fill positive values of k (FFT conventions: first half is positive) for (int i=0; i<(N+1)/2; i++ ){ k[i] = i*dk; } // Fill negative values of k (FFT conventions: second half is negative) for (int i=(N+1)/2; i& k = k_vec[i_dim][mfi]; ManagedVector& shift = shift_factor[mfi]; // Allocate shift coefficients shift.resize( k.size() ); // Fill the shift coefficients Real sign = 0; switch (shift_type){ case ShiftType::TransformFromCellCentered: sign = 1.; break; case ShiftType::TransformToCellCentered: sign = -1.; } constexpr Complex I{0,1}; for (int i=0; i stencil_coef = getFonbergStencilCoefficients(n_order, nodal); // Loop over boxes for ( MFIter mfi(spectralspace_ba, dm); mfi.isValid(); ++mfi ){ Real delta_x = dx[i_dim]; const ManagedVector& k = k_vec[i_dim][mfi]; ManagedVector& modified_k = modified_k_comp[mfi]; // Allocate modified_k to the same size as k modified_k.resize( k.size() ); // Fill the modified k vector for (int i=0; i getFonbergStencilCoefficients( const int n_order, const bool nodal ) { AMREX_ALWAYS_ASSERT_WITH_MESSAGE( n_order%2 == 0, "n_order should be even."); const int m = n_order/2; Vector coefs; coefs.resize( m+1 ); // Coefficients for nodal (a.k.a. centered) finite-difference if (nodal == true) { coefs[0] = -2.; // First coefficient for (int n=1; n