aboutsummaryrefslogtreecommitdiff
path: root/Source/FieldSolver/SpectralSolver
diff options
context:
space:
mode:
authorGravatar Remi Lehe <remi.lehe@normalesup.org> 2019-04-23 13:19:08 -0700
committerGravatar Remi Lehe <remi.lehe@normalesup.org> 2019-04-23 13:19:08 -0700
commit37f932323e7e3381cf7eee72a9e45e0304754e10 (patch)
tree4ee6454c3ee5dc78cfd2b90ec05fbc83569d249d /Source/FieldSolver/SpectralSolver
parenteb5ee68612afe016afd47a621937ee57006c135c (diff)
downloadWarpX-37f932323e7e3381cf7eee72a9e45e0304754e10.tar.gz
WarpX-37f932323e7e3381cf7eee72a9e45e0304754e10.tar.zst
WarpX-37f932323e7e3381cf7eee72a9e45e0304754e10.zip
Switch and rename the shift factors
Diffstat (limited to 'Source/FieldSolver/SpectralSolver')
-rw-r--r--Source/FieldSolver/SpectralSolver/SpectralFieldData.H10
-rw-r--r--Source/FieldSolver/SpectralSolver/SpectralFieldData.cpp67
-rw-r--r--Source/FieldSolver/SpectralSolver/SpectralKSpace.H9
-rw-r--r--Source/FieldSolver/SpectralSolver/SpectralKSpace.cpp58
4 files changed, 83 insertions, 61 deletions
diff --git a/Source/FieldSolver/SpectralSolver/SpectralFieldData.H b/Source/FieldSolver/SpectralSolver/SpectralFieldData.H
index 63a7c7520..be1765ca0 100644
--- a/Source/FieldSolver/SpectralSolver/SpectralFieldData.H
+++ b/Source/FieldSolver/SpectralSolver/SpectralFieldData.H
@@ -31,7 +31,7 @@ class SpectralFieldData
const SpectralKSpace& k_space,
const amrex::DistributionMapping& dm );
SpectralFieldData() = default; // Default constructor
- SpectralFieldData& operator=(SpectralFieldData&& field_data) = default; // Default move assignment
+ SpectralFieldData& operator=(SpectralFieldData&& field_data) = default;
~SpectralFieldData();
void ForwardTransform( const amrex::MultiFab& mf,
const int field_index, const int i_comp );
@@ -42,10 +42,12 @@ class SpectralFieldData
SpectralField Ex, Ey, Ez, Bx, By, Bz, Jx, Jy, Jz, rho_old, rho_new;
SpectralField tmpRealField, tmpSpectralField; // Store fields before/after transform
FFTplans forward_plan, backward_plan;
- // Factors that shift the fields between nodal and cell-centered, in spectral space
- SpectralShiftFactor xshift_N2C, xshift_C2N, zshift_N2C, zshift_C2N;
+ // Correcting "shift" factors when performing FFT from/to
+ // a cell-centered grid in real space, instead of a nodal grid
+ SpectralShiftFactor xshift_FFTfromCell, xshift_FFTtoCell,
+ zshift_FFTfromCell, zshift_FFTtoCell;
#if (AMREX_SPACEDIM==3)
- SpectralShiftFactor yshift_N2C, yshift_C2N;
+ SpectralShiftFactor yshift_FFTfromCell, yshift_FFTtoCell;
#endif
SpectralField& getSpectralField( const int field_index );
};
diff --git a/Source/FieldSolver/SpectralSolver/SpectralFieldData.cpp b/Source/FieldSolver/SpectralSolver/SpectralFieldData.cpp
index 31390127e..ca5e338e5 100644
--- a/Source/FieldSolver/SpectralSolver/SpectralFieldData.cpp
+++ b/Source/FieldSolver/SpectralSolver/SpectralFieldData.cpp
@@ -21,21 +21,32 @@ SpectralFieldData::SpectralFieldData( const BoxArray& realspace_ba,
rho_old = SpectralField(spectralspace_ba, dm, 1, 0);
rho_new = SpectralField(spectralspace_ba, dm, 1, 0);
- // Allocate temporary arrays - over different boxarrays
+ // Allocate temporary arrays - in real space and spectral space
+ // These arrays will store the data just before/after the FFT
tmpRealField = SpectralField(realspace_ba, dm, 1, 0);
tmpSpectralField = SpectralField(spectralspace_ba, dm, 1, 0);
- // Allocate the coefficients that allow to shift between nodal and cell-centered
- xshift_C2N = k_space.getSpectralShiftFactor(dm, 0, ShiftType::CenteredToNodal);
- xshift_N2C = k_space.getSpectralShiftFactor(dm, 0, ShiftType::NodalToCentered);
+ // By default, we assume the FFT is done from/to a nodal grid in real space
+ // It the FFT is performed from/to a cell-centered grid in real space,
+ // a correcting "shift" factor must be applied in spectral space.
+ xshift_FFTfromCell = k_space.getSpectralShiftFactor(dm, 0,
+ ShiftType::TransformFromCellCentered);
+ xshift_FFTtoCell = k_space.getSpectralShiftFactor(dm, 0,
+ ShiftType::TransformToCellCentered);
#if (AMREX_SPACEDIM == 3)
- yshift_C2N = k_space.getSpectralShiftFactor(dm, 1, ShiftType::CenteredToNodal);
- yshift_N2C = k_space.getSpectralShiftFactor(dm, 1, ShiftType::NodalToCentered);
- zshift_C2N = k_space.getSpectralShiftFactor(dm, 2, ShiftType::CenteredToNodal);
- zshift_N2C = k_space.getSpectralShiftFactor(dm, 2, ShiftType::NodalToCentered);
+ yshift_FFTfromCell = k_space.getSpectralShiftFactor(dm, 1,
+ ShiftType::TransformFromCellCentered);
+ yshift_FFTtoCell = k_space.getSpectralShiftFactor(dm, 1,
+ ShiftType::TransformToCellCentered);
+ zshift_FFTfromCell = k_space.getSpectralShiftFactor(dm, 2,
+ ShiftType::TransformFromCellCentered);
+ zshift_FFTtoCell = k_space.getSpectralShiftFactor(dm, 2,
+ ShiftType::TransformToCellCentered);
#else
- zshift_C2N = k_space.getSpectralShiftFactor(dm, 1, ShiftType::CenteredToNodal);
- zshift_N2C = k_space.getSpectralShiftFactor(dm, 1, ShiftType::NodalToCentered);
+ zshift_FFTfromCell = k_space.getSpectralShiftFactor(dm, 1,
+ ShiftType::TransformFromCellCentered);
+ zshift_FFTtoCell = k_space.getSpectralShiftFactor(dm, 1,
+ ShiftType::TransformToCellCentered);
#endif
// Allocate and initialize the FFT plans
@@ -131,28 +142,30 @@ SpectralFieldData::ForwardTransform( const MultiFab& mf,
fftw_execute( forward_plan[mfi] );
#endif
- // Copy the spectral-space field `tmpSpectralField` to the appropriate field
- // (specified by the input argument field_index )
+ // Copy the spectral-space field `tmpSpectralField` to the appropriate
+ // field (specified by the input argument field_index )
+ // and apply correcting shift factor if the real space data comes
+ // from a cell-centered grid in real space instead of a nodal grid.
{
SpectralField& field = getSpectralField( field_index );
Array4<Complex> field_arr = field[mfi].array();
Array4<const Complex> tmp_arr = tmpSpectralField[mfi].array();
- const Complex* xshift_C2N_arr = xshift_C2N[mfi].dataPtr();
+ const Complex* xshift_arr = xshift_FFTfromCell[mfi].dataPtr();
#if (AMREX_SPACEDIM == 3)
- const Complex* yshift_C2N_arr = yshift_C2N[mfi].dataPtr();
+ const Complex* yshift_arr = yshift_FFTfromCell[mfi].dataPtr();
#endif
- const Complex* zshift_C2N_arr = zshift_C2N[mfi].dataPtr();
+ const Complex* zshift_arr = zshift_FFTfromCell[mfi].dataPtr();
// Loop over indices within one box
const Box spectralspace_bx = tmpSpectralField[mfi].box();
ParallelFor( spectralspace_bx,
[=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
Complex spectral_field_value = tmp_arr(i,j,k);
// Apply proper shift in each dimension
- if (is_nodal_x==false) spectral_field_value *= xshift_C2N_arr[i];
+ if (is_nodal_x==false) spectral_field_value *= xshift_arr[i];
#if (AMREX_SPACEDIM == 3)
- if (is_nodal_y==false) spectral_field_value *= yshift_C2N_arr[j];
+ if (is_nodal_y==false) spectral_field_value *= yshift_arr[j];
#endif
- if (is_nodal_z==false) spectral_field_value *= zshift_C2N_arr[k];
+ if (is_nodal_z==false) spectral_field_value *= zshift_arr[k];
// Copy field into temporary array
field_arr(i,j,k) = spectral_field_value;
});
@@ -179,28 +192,30 @@ SpectralFieldData::BackwardTransform( MultiFab& mf,
// Loop over boxes
for ( MFIter mfi(mf); mfi.isValid(); ++mfi ){
- // Copy the appropriate field (specified by the input argument field_index)
- // to the spectral-space field `tmpSpectralField`
+ // Copy the spectral-space field `tmpSpectralField` to the appropriate
+ // field (specified by the input argument field_index )
+ // and apply correcting shift factor if the field is to be transformed
+ // to a cell-centered grid in real space instead of a nodal grid.
{
SpectralField& field = getSpectralField( field_index );
Array4<const Complex> field_arr = field[mfi].array();
Array4<Complex> tmp_arr = tmpSpectralField[mfi].array();
- const Complex* xshift_N2C_arr = xshift_N2C[mfi].dataPtr();
+ const Complex* xshift_arr = xshift_FFTtoCell[mfi].dataPtr();
#if (AMREX_SPACEDIM == 3)
- const Complex* yshift_N2C_arr = yshift_N2C[mfi].dataPtr();
+ const Complex* yshift_arr = yshift_FFTtoCell[mfi].dataPtr();
#endif
- const Complex* zshift_N2C_arr = zshift_N2C[mfi].dataPtr();
+ const Complex* zshift_arr = zshift_FFTtoCell[mfi].dataPtr();
// Loop over indices within one box
const Box spectralspace_bx = tmpSpectralField[mfi].box();
ParallelFor( spectralspace_bx,
[=] AMREX_GPU_DEVICE(int i, int j, int k) noexcept {
Complex spectral_field_value = field_arr(i,j,k);
// Apply proper shift in each dimension
- if (is_nodal_x==false) spectral_field_value *= xshift_N2C_arr[i];
+ if (is_nodal_x==false) spectral_field_value *= xshift_arr[i];
#if (AMREX_SPACEDIM == 3)
- if (is_nodal_y==false) spectral_field_value *= yshift_N2C_arr[j];
+ if (is_nodal_y==false) spectral_field_value *= yshift_arr[j];
#endif
- if (is_nodal_z==false) spectral_field_value *= zshift_N2C_arr[k];
+ if (is_nodal_z==false) spectral_field_value *= zshift_arr[k];
// Copy field into temporary array
tmp_arr(i,j,k) = spectral_field_value;
});
diff --git a/Source/FieldSolver/SpectralSolver/SpectralKSpace.H b/Source/FieldSolver/SpectralSolver/SpectralKSpace.H
index fd77bb7b8..c71cf2643 100644
--- a/Source/FieldSolver/SpectralSolver/SpectralKSpace.H
+++ b/Source/FieldSolver/SpectralSolver/SpectralKSpace.H
@@ -5,11 +5,11 @@
#include <AMReX_BoxArray.H>
#include <AMReX_LayoutData.H>
-using KVectorComponent = amrex::LayoutData< amrex::Gpu::ManagedVector <amrex::Real> >;
-using SpectralShiftFactor = amrex::LayoutData< amrex::Gpu::ManagedVector <Complex> >;
+using KVectorComponent = amrex::LayoutData<amrex::Gpu::ManagedVector<amrex::Real>>;
+using SpectralShiftFactor = amrex::LayoutData<amrex::Gpu::ManagedVector<Complex>>;
struct ShiftType {
- enum{ NodalToCentered=0, CenteredToNodal=1 };
+ enum{ TransformFromCellCentered=0, TransformToCellCentered=1 };
};
/* TODO Documentation: class represent k space, and how it is distribution
@@ -28,7 +28,8 @@ class SpectralKSpace
const amrex::DistributionMapping& dm, const int i_dim,
const int n_order, const bool nodal ) const;
SpectralShiftFactor getSpectralShiftFactor(
- const amrex::DistributionMapping& dm, const int i_dim, const int shift_type ) const;
+ const amrex::DistributionMapping& dm, const int i_dim,
+ const int shift_type ) const;
private:
amrex::Array<KVectorComponent, AMREX_SPACEDIM> k_vec;
diff --git a/Source/FieldSolver/SpectralSolver/SpectralKSpace.cpp b/Source/FieldSolver/SpectralSolver/SpectralKSpace.cpp
index 111643197..4852c7d2b 100644
--- a/Source/FieldSolver/SpectralSolver/SpectralKSpace.cpp
+++ b/Source/FieldSolver/SpectralSolver/SpectralKSpace.cpp
@@ -16,10 +16,12 @@ SpectralKSpace::SpectralKSpace( const BoxArray& realspace_ba,
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, each box in spectral space starts at 0 in each direction
- // and has the same number of points as the real space box (including guard cells)
+ // 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() );
+ Box bx = Box( IntVect::TheZeroVector(),
+ realspace_bx.bigEnd() - realspace_bx.smallEnd() );
spectral_bl.push_back( bx );
}
spectralspace_ba.define( spectral_bl );
@@ -31,7 +33,8 @@ SpectralKSpace::SpectralKSpace( const BoxArray& realspace_ba,
}
KVectorComponent
-SpectralKSpace::getKComponent( const DistributionMapping& dm, const int i_dim ) const
+SpectralKSpace::getKComponent( const DistributionMapping& dm,
+ const int i_dim ) const
{
// Initialize an empty ManagedVector in each box
KVectorComponent k_comp = KVectorComponent(spectralspace_ba, dm);
@@ -58,17 +61,16 @@ SpectralKSpace::getKComponent( const DistributionMapping& dm, const int i_dim )
for (int i=(N+1)/2; i<N; i++){
k[i] = (N-i)*dk;
}
- // TODO: This should be quite different for the hybrid spectral code:
- // In that case we should take into consideration the actual indices of the box
- // and distinguish the size of the local box and that of the global FFT
- // This will also be different for the real-to-complex transform
+ // TODO: this will also be different for the real-to-complex transform
+ // TODO: this will be different for the hybrid FFT scheme
}
return k_comp;
}
SpectralShiftFactor
-SpectralKSpace::getSpectralShiftFactor(
- const DistributionMapping& dm, const int i_dim, const int shift_type ) const
+SpectralKSpace::getSpectralShiftFactor( const DistributionMapping& dm,
+ const int i_dim,
+ const int shift_type ) const
{
// Initialize an empty ManagedVector in each box
SpectralShiftFactor shift_factor = SpectralShiftFactor( spectralspace_ba, dm );
@@ -83,8 +85,8 @@ SpectralKSpace::getSpectralShiftFactor(
// Fill the shift coefficients
Real sign = 0;
switch (shift_type){
- case ShiftType::CenteredToNodal: sign = -1.; break;
- case ShiftType::NodalToCentered: sign = 1.;
+ case ShiftType::TransformFromCellCentered: sign = 1.; break;
+ case ShiftType::TransformToCellCentered: sign = -1.;
}
constexpr Complex I{0,1};
for (int i=0; i<k.size(); i++ ){
@@ -95,9 +97,10 @@ SpectralKSpace::getSpectralShiftFactor(
}
KVectorComponent
-SpectralKSpace::getModifiedKComponent(
- const DistributionMapping& dm, const int i_dim,
- const int n_order, const bool nodal ) const
+SpectralKSpace::getModifiedKComponent( const DistributionMapping& dm,
+ const int i_dim,
+ const int n_order,
+ const bool nodal ) const
{
// Initialize an empty ManagedVector in each box
KVectorComponent modified_k_comp = KVectorComponent( spectralspace_ba, dm );
@@ -118,11 +121,11 @@ SpectralKSpace::getModifiedKComponent(
for (int i=0; i<k.size(); i++ ){
for (int n=1; n<stencil_coef.size(); n++){
if (nodal){
- modified_k[i] = \
- stencil_coef[n]*std::sin( k[i]*n*delta_x )/( n*delta_x );
+ modified_k[i] = stencil_coef[n]* \
+ std::sin( k[i]*n*delta_x )/( n*delta_x );
} else {
- modified_k[i] = \
- stencil_coef[n]*std::sin( k[i]*(n-0.5)*delta_x )/( (n-0.5)*delta_x );
+ modified_k[i] = stencil_coef[n]* \
+ std::sin( k[i]*(n-0.5)*delta_x )/( (n-0.5)*delta_x );
}
}
}
@@ -135,16 +138,17 @@ SpectralKSpace::getModifiedKComponent(
Vector<Real>
getFonbergStencilCoefficients( const int n_order, const bool nodal )
{
- AMREX_ALWAYS_ASSERT_WITH_MESSAGE( n_order%2 == 0, "n_order should be even.");
+ AMREX_ALWAYS_ASSERT_WITH_MESSAGE( n_order%2 == 0,
+ "n_order should be even.");
const int m = n_order/2;
- Vector<Real> stencil_coef;
- stencil_coef.resize( m+1 );
+ Vector<Real> coefs;
+ coefs.resize( m+1 );
// Coefficients for nodal (a.k.a. centered) finite-difference
if (nodal == true) {
- stencil_coef[0] = -2.; // First coefficient
+ coefs[0] = -2.; // First coefficient
for (int n=1; n<m+1; n++){ // Get the other coefficients by recurrence
- stencil_coef[n] = - (m+1-n)*1./(m+n)*stencil_coef[n-1];
+ coefs[n] = - (m+1-n)*1./(m+n)*coefs[n-1];
}
}
// Coefficients for staggered finite-difference
@@ -153,10 +157,10 @@ getFonbergStencilCoefficients( const int n_order, const bool nodal )
for (int k=1; k<m+1; k++){
prod *= (m+k)*1./(4*k);
}
- stencil_coef[0] = 4*m*prod*prod; // First coefficient
+ coefs[0] = 4*m*prod*prod; // First coefficient
for (int n=1; n<m+1; n++){ // Get the other coefficients by recurrence
- stencil_coef[n] = - ((2*n-3)*(m+1-n))*1./((2*n-1)*(m-1+n))*stencil_coef[n-1];
+ coefs[n] = - ((2*n-3)*(m+1-n))*1./((2*n-1)*(m-1+n))*coefs[n-1];
}
}
- return stencil_coef;
+ return coefs;
}