diff options
Diffstat (limited to 'Source/FieldSolver')
-rw-r--r-- | Source/FieldSolver/SpectralSolver/SpectralFieldDataRZ.cpp | 80 | ||||
-rw-r--r-- | Source/FieldSolver/WarpXPushFieldsEM.cpp | 71 |
2 files changed, 113 insertions, 38 deletions
diff --git a/Source/FieldSolver/SpectralSolver/SpectralFieldDataRZ.cpp b/Source/FieldSolver/SpectralSolver/SpectralFieldDataRZ.cpp index f62eaaa16..a87bfdb54 100644 --- a/Source/FieldSolver/SpectralSolver/SpectralFieldDataRZ.cpp +++ b/Source/FieldSolver/SpectralSolver/SpectralFieldDataRZ.cpp @@ -545,7 +545,7 @@ SpectralFieldDataRZ::BackwardTransform (const int lev, } amrex::Real wt = amrex::second(); - amrex::Box const& realspace_bx = tempHTransformed[mfi].box(); + amrex::Box realspace_bx = tempHTransformed[mfi].box(); FABZBackwardTransform(mfi, realspace_bx, field_index, tempHTransformedSplit, is_nodal_z); @@ -553,7 +553,43 @@ SpectralFieldDataRZ::BackwardTransform (const int lev, // tempHTransformedSplit includes the imaginary component of mode 0. // field_mf does not. multi_spectral_hankel_transformer[mfi].SpectralToPhysical_Scalar(tempHTransformedSplit[mfi], field_mf_copy[mfi]); - field_mf[mfi].copy<amrex::RunOn::Device>(field_mf_copy[mfi], 0, i_comp*ncomp, ncomp); + + amrex::Array4<amrex::Real> const & field_mf_array = field_mf[mfi].array(); + amrex::Array4<amrex::Real> const & field_mf_copy_array = field_mf_copy[mfi].array(); + + // The box will be extended to include the guards cells below the axis + // so that they can be filled in. This will not be a simple copy of the + // fields since the signs will change when there is anti-symmetry. + amrex::Box const& realspace_bx_with_guards = field_mf[mfi].box(); + const int* lo_with_guards = realspace_bx_with_guards.loVect(); + + // Grow the lower side of realspace_bx by the number of guard cells. + // This assumes that the box extends over the full extent radially, so + // lo_with_guards[0] will be equal to minus the number of guard cells radially. + const int nguard_r = -lo_with_guards[0]; + realspace_bx.growLo(0, nguard_r); + + // Get the intersection of the two boxes in case the field_mf has fewer z-guard cells + realspace_bx &= realspace_bx_with_guards; + + ParallelFor(realspace_bx, ncomp, + [=] AMREX_GPU_DEVICE(int i, int j, int k, int icomp) noexcept { + int ii = i; + amrex::Real sign = +1._rt; + if (i < 0) { + ii = -i - 1; + if (icomp == 0) { + // Mode zero is symmetric + sign = +1._rt; + } else { + // Odd modes are anti-symmetric + int imode = (icomp + 1)/2; + sign = std::pow(-1._rt, imode); + } + } + int ic = icomp + i_comp; + field_mf_array(i,j,k,ic) = sign*field_mf_copy_array(ii,j,k,icomp); + }); if (cost && WarpX::load_balance_costs_update_algo == LoadBalanceCostsUpdateAlgo::Timers) { @@ -593,7 +629,7 @@ SpectralFieldDataRZ::BackwardTransform (const int lev, } amrex::Real wt = amrex::second(); - amrex::Box const& realspace_bx = tempHTransformed[mfi].box(); + amrex::Box realspace_bx = tempHTransformed[mfi].box(); FABZBackwardTransform(mfi, realspace_bx, field_index_r, tempHTransformedSplit_p, is_nodal_z); FABZBackwardTransform(mfi, realspace_bx, field_index_t, tempHTransformedSplit_m, is_nodal_z); @@ -610,15 +646,43 @@ SpectralFieldDataRZ::BackwardTransform (const int lev, amrex::Array4<amrex::Real> const & field_mf_r_copy_array = field_mf_r_copy[mfi].array(); amrex::Array4<amrex::Real> const & field_mf_t_copy_array = field_mf_t_copy[mfi].array(); + // The box will be extended to include the guards cells below the axis + // so that they can be filled in. This will not be a simple copy of the + // fields since the signs will change when there is anti-symmetry. + amrex::Box const& realspace_bx_with_guards = field_mf_r[mfi].box(); + const int* lo_with_guards = realspace_bx_with_guards.loVect(); + + // Grow the lower side of realspace_bx by the number of guard cells. + // This assumes that the box extends over the full extent radially, so + // lo_with_guards[0] will be equal to minus the number of guard cells radially. + const int nguard_r = -lo_with_guards[0]; + realspace_bx.growLo(0, nguard_r); + + // Get the intersection of the two boxes in case the field_mf has fewer z-guard cells + realspace_bx &= realspace_bx_with_guards; + ParallelFor(realspace_bx, 2*n_rz_azimuthal_modes-1, [=] AMREX_GPU_DEVICE(int i, int j, int k, int icomp) noexcept { + int ii = i; + amrex::Real sign = +1._rt; + if (i < 0) { + ii = -i - 1; + if (icomp == 0) { + // Mode zero is anti-symmetric + sign = -1._rt; + } else { + // Even modes are anti-symmetric + int imode = (icomp + 1)/2; + sign = std::pow(-1._rt, imode+1); + } + } if (icomp == 0) { - // mode 0 - field_mf_r_array(i,j,k,icomp) = field_mf_r_copy_array(i,j,k,icomp); - field_mf_t_array(i,j,k,icomp) = field_mf_t_copy_array(i,j,k,icomp); + // mode zero + field_mf_r_array(i,j,k,icomp) = sign*field_mf_r_copy_array(ii,j,k,icomp); + field_mf_t_array(i,j,k,icomp) = sign*field_mf_t_copy_array(ii,j,k,icomp); } else { - field_mf_r_array(i,j,k,icomp) = field_mf_r_copy_array(i,j,k,icomp+1); - field_mf_t_array(i,j,k,icomp) = field_mf_t_copy_array(i,j,k,icomp+1); + field_mf_r_array(i,j,k,icomp) = sign*field_mf_r_copy_array(ii,j,k,icomp+1); + field_mf_t_array(i,j,k,icomp) = sign*field_mf_t_copy_array(ii,j,k,icomp+1); } }); diff --git a/Source/FieldSolver/WarpXPushFieldsEM.cpp b/Source/FieldSolver/WarpXPushFieldsEM.cpp index 1e375f0eb..15ce940d6 100644 --- a/Source/FieldSolver/WarpXPushFieldsEM.cpp +++ b/Source/FieldSolver/WarpXPushFieldsEM.cpp @@ -751,7 +751,7 @@ WarpX::DampFieldsInGuards(std::array<std::unique_ptr<amrex::MultiFab>,3>& Efield void WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, MultiFab* Jz, int lev) { - const long ngJ = Jx->nGrow(); + const amrex::IntVect ngJ = Jx->nGrowVect(); const std::array<Real,3>& dx = WarpX::CellSize(lev); const Real dr = dx[0]; @@ -793,16 +793,16 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu // Grow the tileboxes to include the guard cells, except for the // guard cells at negative radius. if (rmin > 0.) { - tbr.growLo(0, ngJ); - tbt.growLo(0, ngJ); - tbz.growLo(0, ngJ); + tbr.growLo(0, ngJ[0]); + tbt.growLo(0, ngJ[0]); + tbz.growLo(0, ngJ[0]); } - tbr.growHi(0, ngJ); - tbt.growHi(0, ngJ); - tbz.growHi(0, ngJ); - tbr.grow(1, ngJ); - tbt.grow(1, ngJ); - tbz.grow(1, ngJ); + tbr.growHi(0, ngJ[0]); + tbt.growHi(0, ngJ[0]); + tbz.growHi(0, ngJ[0]); + tbr.grow(1, ngJ[1]); + tbt.grow(1, ngJ[1]); + tbz.grow(1, ngJ[1]); // Rescale current in r-z mode since the inverse volume factor was not // included in the current deposition. @@ -812,7 +812,7 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu // Wrap the current density deposited in the guard cells around // to the cells above the axis. // Note that Jr(i==0) is at 1/2 dr. - if (rmin == 0. && 0 <= i && i < ngJ) { + if (rmin == 0. && 0 <= i && i < ngJ[0]) { Jr_arr(i,j,0,0) -= Jr_arr(-1-i,j,0,0); } // Apply the inverse volume scaling @@ -825,9 +825,9 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu // Wrap the current density deposited in the guard cells around // to the cells above the axis. // Note that Jr(i==0) is at 1/2 dr. - if (rmin == 0. && 0 <= i && i < ngJ) { - Jr_arr(i,j,0,2*imode-1) -= Jr_arr(-1-i,j,0,2*imode-1); - Jr_arr(i,j,0,2*imode) -= Jr_arr(-1-i,j,0,2*imode); + if (rmin == 0. && 0 <= i && i < ngJ[0]) { + Jr_arr(i,j,0,2*imode-1) += std::pow(-1, imode+1)*Jr_arr(-1-i,j,0,2*imode-1); + Jr_arr(i,j,0,2*imode) += std::pow(-1, imode+1)*Jr_arr(-1-i,j,0,2*imode); } // Apply the inverse volume scaling // Since Jr is never node centered in r, no need for distinction @@ -842,7 +842,7 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu // to the cells above the axis. // If Jt is node centered, Jt[0] is located on the boundary. // If Jt is cell centered, Jt[0] is at 1/2 dr. - if (rmin == 0. && 1-ishift_t <= i && i <= ngJ-ishift_t) { + if (rmin == 0. && 1-ishift_t <= i && i <= ngJ[0]-ishift_t) { Jt_arr(i,j,0,0) -= Jt_arr(-ishift_t-i,j,0,0); } @@ -858,9 +858,9 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu for (int imode=1 ; imode < nmodes ; imode++) { // Wrap the current density deposited in the guard cells around // to the cells above the axis. - if (rmin == 0. && 1-ishift_t <= i && i <= ngJ-ishift_t) { - Jt_arr(i,j,0,2*imode-1) -= Jt_arr(-ishift_t-i,j,0,2*imode-1); - Jt_arr(i,j,0,2*imode) -= Jt_arr(-ishift_t-i,j,0,2*imode); + if (rmin == 0. && 1-ishift_t <= i && i <= ngJ[0]-ishift_t) { + Jt_arr(i,j,0,2*imode-1) += std::pow(-1, imode+1)*Jt_arr(-ishift_t-i,j,0,2*imode-1); + Jt_arr(i,j,0,2*imode) += std::pow(-1, imode+1)*Jt_arr(-ishift_t-i,j,0,2*imode); } // Apply the inverse volume scaling @@ -880,8 +880,8 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu // to the cells above the axis. // If Jz is node centered, Jt[0] is located on the boundary. // If Jz is cell centered, Jt[0] is at 1/2 dr. - if (rmin == 0. && 1-ishift_z <= i && i <= ngJ-ishift_z) { - Jz_arr(i,j,0,0) -= Jz_arr(-ishift_z-i,j,0,0); + if (rmin == 0. && 1-ishift_z <= i && i <= ngJ[0]-ishift_z) { + Jz_arr(i,j,0,0) += Jz_arr(-ishift_z-i,j,0,0); } // Apply the inverse volume scaling @@ -896,9 +896,9 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu for (int imode=1 ; imode < nmodes ; imode++) { // Wrap the current density deposited in the guard cells around // to the cells above the axis. - if (rmin == 0. && 1-ishift_z <= i && i <= ngJ-ishift_z) { - Jz_arr(i,j,0,2*imode-1) -= Jz_arr(-ishift_z-i,j,0,2*imode-1); - Jz_arr(i,j,0,2*imode) -= Jz_arr(-ishift_z-i,j,0,2*imode); + if (rmin == 0. && 1-ishift_z <= i && i <= ngJ[0]-ishift_z) { + Jz_arr(i,j,0,2*imode-1) -= std::pow(-1, imode+1)*Jz_arr(-ishift_z-i,j,0,2*imode-1); + Jz_arr(i,j,0,2*imode) -= std::pow(-1, imode+1)*Jz_arr(-ishift_z-i,j,0,2*imode); } // Apply the inverse volume scaling @@ -919,7 +919,7 @@ WarpX::ApplyInverseVolumeScalingToCurrentDensity (MultiFab* Jx, MultiFab* Jy, Mu void WarpX::ApplyInverseVolumeScalingToChargeDensity (MultiFab* Rho, int lev) { - const long ngRho = Rho->nGrow(); + const amrex::IntVect ngRho = Rho->nGrowVect(); const std::array<Real,3>& dx = WarpX::CellSize(lev); const Real dr = dx[0]; @@ -949,23 +949,34 @@ WarpX::ApplyInverseVolumeScalingToChargeDensity (MultiFab* Rho, int lev) // Grow the tilebox to include the guard cells, except for the // guard cells at negative radius. if (rmin > 0.) { - tb.growLo(0, ngRho); + tb.growLo(0, ngRho[0]); } - tb.growHi(0, ngRho); - tb.grow(1, ngRho); + tb.growHi(0, ngRho[0]); + tb.grow(1, ngRho[1]); // Rescale charge in r-z mode since the inverse volume factor was not // included in the charge deposition. // Note that the loop is also over ncomps, which takes care of the RZ modes, // as well as the old and new rho. - amrex::ParallelFor(tb, Rho->nComp(), + int const ncomp = Rho->nComp(); + amrex::ParallelFor(tb, ncomp, [=] AMREX_GPU_DEVICE (int i, int j, int /*k*/, int icomp) { // Wrap the charge density deposited in the guard cells around // to the cells above the axis. // Rho is located on the boundary - if (rmin == 0. && 1-ishift <= i && i <= ngRho-ishift) { - Rho_arr(i,j,0,icomp) -= Rho_arr(-ishift-i,j,0,icomp); + if (rmin == 0. && 1-ishift <= i && i <= ngRho[0]-ishift) { + int imode; + if (icomp == 0 || icomp == ncomp/2) { + imode = 0; + } + else if (icomp < ncomp/2) { + imode = (icomp+1)/2; + } + else { + imode = (icomp - ncomp/2 + 1)/2; + } + Rho_arr(i,j,0,icomp) -= std::pow(-1, imode+1)*Rho_arr(-ishift-i,j,0,icomp); } // Apply the inverse volume scaling |