aboutsummaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/FieldSolver/WarpXPushFieldsEM.cpp14
-rw-r--r--Source/FieldSolver/WarpX_FDTD.H154
2 files changed, 137 insertions, 31 deletions
diff --git a/Source/FieldSolver/WarpXPushFieldsEM.cpp b/Source/FieldSolver/WarpXPushFieldsEM.cpp
index 1df05bc0f..dfb9f0211 100644
--- a/Source/FieldSolver/WarpXPushFieldsEM.cpp
+++ b/Source/FieldSolver/WarpXPushFieldsEM.cpp
@@ -175,20 +175,21 @@ WarpX::EvolveB (int lev, PatchType patch_type, amrex::Real a_dt)
warpx_push_bz_nodal(j,k,l,Bzfab,Exfab,Eyfab,dtsdx,dtsdy);
});
} else if (WarpX::maxwell_fdtd_solver_id == 0) {
+ const long nmodes = n_rz_azimuthal_modes;
amrex::ParallelFor(tbx,
[=] AMREX_GPU_DEVICE (int j, int k, int l)
{
- warpx_push_bx_yee(j,k,l,Bxfab,Eyfab,Ezfab,dtsdy,dtsdz);
+ warpx_push_bx_yee(j,k,l,Bxfab,Eyfab,Ezfab,dtsdx,dtsdy,dtsdz,dxinv,xmin,nmodes);
});
amrex::ParallelFor(tby,
[=] AMREX_GPU_DEVICE (int j, int k, int l)
{
- warpx_push_by_yee(j,k,l,Byfab,Exfab,Ezfab,dtsdx,dtsdz);
+ warpx_push_by_yee(j,k,l,Byfab,Exfab,Ezfab,dtsdx,dtsdz,nmodes);
});
amrex::ParallelFor(tbz,
[=] AMREX_GPU_DEVICE (int j, int k, int l)
{
- warpx_push_bz_yee(j,k,l,Bzfab,Exfab,Eyfab,dtsdx,dtsdy,dxinv,xmin);
+ warpx_push_bz_yee(j,k,l,Bzfab,Exfab,Eyfab,dtsdx,dtsdy,dxinv,xmin,nmodes);
});
} else if (WarpX::maxwell_fdtd_solver_id == 1) {
Real betaxy, betaxz, betayx, betayz, betazx, betazy;
@@ -372,20 +373,21 @@ WarpX::EvolveE (int lev, PatchType patch_type, amrex::Real a_dt)
warpx_push_ez_nodal(j,k,l,Ezfab,Bxfab,Byfab,jzfab,mu_c2_dt,dtsdx_c2,dtsdy_c2);
});
} else {
+ const long nmodes = n_rz_azimuthal_modes;
amrex::ParallelFor(tex,
[=] AMREX_GPU_DEVICE (int j, int k, int l)
{
- warpx_push_ex_yee(j,k,l,Exfab,Byfab,Bzfab,jxfab,mu_c2_dt,dtsdy_c2,dtsdz_c2);
+ warpx_push_ex_yee(j,k,l,Exfab,Byfab,Bzfab,jxfab,mu_c2_dt,dtsdx_c2,dtsdy_c2,dtsdz_c2,dxinv,xmin,nmodes);
});
amrex::ParallelFor(tey,
[=] AMREX_GPU_DEVICE (int j, int k, int l)
{
- warpx_push_ey_yee(j,k,l,Eyfab,Bxfab,Bzfab,jyfab,mu_c2_dt,dtsdx_c2,dtsdz_c2,xmin);
+ warpx_push_ey_yee(j,k,l,Eyfab,Bxfab,Bzfab,jyfab,Exfab,mu_c2_dt,dtsdx_c2,dtsdz_c2,xmin,nmodes);
});
amrex::ParallelFor(tez,
[=] AMREX_GPU_DEVICE (int j, int k, int l)
{
- warpx_push_ez_yee(j,k,l,Ezfab,Bxfab,Byfab,jzfab,mu_c2_dt,dtsdx_c2,dtsdy_c2,dxinv,xmin);
+ warpx_push_ez_yee(j,k,l,Ezfab,Bxfab,Byfab,jzfab,mu_c2_dt,dtsdx_c2,dtsdy_c2,dxinv,xmin,nmodes);
});
}
diff --git a/Source/FieldSolver/WarpX_FDTD.H b/Source/FieldSolver/WarpX_FDTD.H
index e2d40f4c2..4a5139d50 100644
--- a/Source/FieldSolver/WarpX_FDTD.H
+++ b/Source/FieldSolver/WarpX_FDTD.H
@@ -8,36 +8,75 @@ using namespace amrex;
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
void warpx_push_bx_yee(int i, int j, int k, Array4<Real> const& Bx,
Array4<Real const> const& Ey, Array4<Real const> const& Ez,
- Real dtsdy, Real dtsdz)
+ Real dtsdx, Real dtsdy, Real dtsdz, Real dxinv, Real rmin, const long nmodes)
{
#if defined WARPX_DIM_3D
Bx(i,j,k) += - dtsdy * (Ez(i,j+1,k ) - Ez(i,j,k))
+ dtsdz * (Ey(i,j ,k+1) - Ey(i,j,k));
-#elif (defined WARPX_DIM_2D) || (defined WARPX_DIM_RZ)
- // Note that the 2D Cartesian and RZ versions are the same
+#elif (defined WARPX_DIM_2D)
Bx(i,j,0) += + dtsdz * (Ey(i,j+1,0) - Ey(i,j,0));
+#if (defined WARPX_DIM_RZ)
+ if (i != 0 || rmin != 0.) {
+ Bx(i,j,0,0) += + dtsdz * (Ey(i,j+1,0,0) - Ey(i,j,0,0));
+ } else {
+ Bx(i,j,0,0) = 0.;
+ }
+ for (int imode=1 ; imode < nmodes ; imode++) {
+ if (i == 0 && rmin == 0) {
+ if (imode == 1) {
+ // For the mode m = 1, the bulk equation diverges on axis
+ // (due to the 1/r terms). The following expressions regularize
+ // these divergences by assuming, on axis :
+ // Ez/r = 0/r + dEz/dr
+ Bx(i,j,2*imode) = Bx(i,j,0,2*imode) - imode*dtsdx*Ez(i+1,j,0,2*imode+1) &
+ + dtsdz*(Ey(i,j+1,0,2*imode) - Ey(i,j,0,2*imode));
+ Bx(i,j,2*imode+1) = Bx(i,j,0,2*imode+1) + imode*dtsdx*Ez(i+1,j,0,2*imode) &
+ + dtsdz*(Ey(i,j+1,0,2*imode+1) - Ey(i,j,0,2*imode+1));
+ } else {
+ Bx(i,j,0,2*imode) = 0.;
+ Bx(i,j,0,2*imode+1) = 0.;
+ }
+ } else {
+ // Br(i,j,m) = Br(i,j,m) + I*m*dt*Ez(i,j,m)/r + dtsdz*(Et(i,j+1,m) - Et(i,j,m))
+ const Real r = rmin*dxinv + i;
+ Bx(i,j,2*imode) = Bx(i,j,0,2*imode) - imode*dtsdx*Ez(i,j,0,2*imode+1)/r &
+ + dtsdz*(Ey(i,j+1,0,2*imode) - Ey(i,j,0,2*imode));
+ Bx(i,j,2*imode+1) = Bx(i,j,0,2*imode+1) + imode*dtsdx*Ez(i,j,0,2*imode)/r &
+ + dtsdz*(Ey(i,j+1,0,2*imode+1) - Ey(i,j,0,2*imode+1));
+ }
+ }
+#endif
#endif
}
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
void warpx_push_by_yee(int i, int j, int k, Array4<Real> const& By,
Array4<Real const> const& Ex, Array4<Real const> const& Ez,
- Real dtsdx, Real dtsdz)
+ Real dtsdx, Real dtsdz, const long nmodes)
{
#if defined WARPX_DIM_3D
By(i,j,k) += + dtsdx * (Ez(i+1,j,k ) - Ez(i,j,k))
- dtsdz * (Ex(i ,j,k+1) - Ex(i,j,k));
#elif (defined WARPX_DIM_2D) || (defined WARPX_DIM_RZ)
- // Note that the 2D Cartesian and RZ versions are the same
- By(i,j,0) += + dtsdx * (Ez(i+1,j ,0) - Ez(i,j,0))
- - dtsdz * (Ex(i ,j+1,0) - Ex(i,j,0));
+ // Note that the 2D Cartesian and RZ mode 0 are the same
+ By(i,j,0,0) += + dtsdx * (Ez(i+1,j ,0,0) - Ez(i,j,0,0))
+ - dtsdz * (Ex(i ,j+1,0,0) - Ex(i,j,0,0));
+#if (defined WARPX_DIM_RZ)
+ for (int imode=1 ; imode < nmodes ; imode++) {
+ // Bt(i,j,m) = Bt(i,j,m) + dtsdr*(Ez(i+1,j,m) - Ez(i,j,m)) - dtsdz*(Er(i,j+1,m) - Er(i,j,m))
+ By(i,j,0,2*imode) += + dtsdx*(Ez(i+1,j ,0,2*imode) - Ez(i,j,0,2*imode))
+ - dtsdz*(Ex(i ,j+1,0,2*imode) - Ex(i,j,0,2*imode));
+ By(i,j,0,2*imode+1) += + dtsdx*(Ez(i+1,j ,0,2*imode+1) - Ez(i,j,0,2*imode+1))
+ - dtsdz*(Ex(i ,j+1,0,2*imode+1) - Ex(i,j,0,2*imode+1));
+ }
+#endif
#endif
}
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
void warpx_push_bz_yee(int i, int j, int k, Array4<Real> const& Bz,
Array4<Real const> const& Ex, Array4<Real const> const& Ey,
- Real dtsdx, Real dtsdy, Real dxinv, Real rmin)
+ Real dtsdx, Real dtsdy, Real dxinv, Real rmin, const long nmodes)
{
#if defined WARPX_DIM_3D
Bz(i,j,k) += - dtsdx * (Ey(i+1,j ,k) - Ey(i,j,k))
@@ -45,46 +84,94 @@ void warpx_push_bz_yee(int i, int j, int k, Array4<Real> const& Bz,
#elif defined WARPX_DIM_2D
Bz(i,j,0) += - dtsdx * (Ey(i+1,j,0) - Ey(i,j,0));
#elif defined WARPX_DIM_RZ
+ const Real r = rmin*dxinv + i + 0.5;
const Real ru = 1. + 0.5/(rmin*dxinv + i + 0.5);
const Real rd = 1. - 0.5/(rmin*dxinv + i + 0.5);
- Bz(i,j,0) += - dtsdx * (ru*Ey(i+1,j,0) - rd*Ey(i,j,0));
+ Bz(i,j,0,0) += - dtsdx*(ru*Ey(i+1,j,0,0) - rd*Ey(i,j,0,0));
+ for (int imode=1 ; imode < nmodes ; imode++) {
+ // Bz(i,j,m) = Bz(i,j,m) - dtsdr*(ru*Et(i+1,j,m) - rd*Et(i,j,m)) - I*m*dt*Er(i,j,m)/r
+ Bz(i,j,0,2*imode) += - dtsdx*(ru*Ey(i+1,j,0,2*imode) - rd*Ey(i,j,0,2*imode)) + imode*dtsdx*Ex(i,j,2*imode+1)/r;
+ Bz(i,j,0,2*imode+1) += - dtsdx*(ru*Ey(i+1,j,0,2*imode+1) - rd*Ey(i,j,0,2*imode+1)) - imode*dtsdx*Ex(i,j,2*imode)/r;
+ }
#endif
}
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
void warpx_push_ex_yee(int i, int j, int k, Array4<Real> const& Ex,
Array4<Real const> const& By, Array4<Real const> const& Bz, Array4<Real const> const& Jx,
- Real mu_c2_dt, Real dtsdy_c2, Real dtsdz_c2)
+ Real mu_c2_dt, Real dtsdx_c2, Real dtsdy_c2, Real dtsdz_c2, Real dxinv, Real rmin, const long nmodes)
{
#if defined WARPX_DIM_3D
Ex(i,j,k) += + dtsdy_c2 * (Bz(i,j,k) - Bz(i,j-1,k ))
- dtsdz_c2 * (By(i,j,k) - By(i,j ,k-1))
- mu_c2_dt * Jx(i,j,k);
#elif (defined WARPX_DIM_2D) || (defined WARPX_DIM_RZ)
- // Note that the 2D Cartesian and RZ versions are the same
- Ex(i,j,0) += - dtsdz_c2 * (By(i,j,0) - By(i,j-1,0))
- - mu_c2_dt * Jx(i,j,0);
+ // Note that the 2D Cartesian and RZ mode 0 are the same
+ Ex(i,j,0,0) += - dtsdz_c2 * (By(i,j,0,0) - By(i,j-1,0,0))
+ - mu_c2_dt * Jx(i,j,0,0);
+#if (defined WARPX_DIM_RZ)
+ const Real r = rmin*dxinv+ i + 0.5;
+ for (int imode=1 ; imode < nmodes ; imode++) {
+ // Er(i,j,m) = Er(i,j,m) - I*m*dt*Bz(i,j,m)/r - dtsdz*(Bt(i,j,m) - Bt(i,j-1,m)) - mudt*Jr(i,j,m)
+ Ex(i,j,0,2*imode) += - dtsdz_c2*(By(i,j,0,2*imode) - By(i,j-1,0,2*imode)) + imode*dtsdx_c2*Bz(i,j,0,2*imode+1)/r
+ - mu_c2_dt*Jx(i,j,0,2*imode);
+ Ex(i,j,0,2*imode+1) += - dtsdz_c2*(By(i,j,0,2*imode+1) - By(i,j-1,0,2*imode+1)) - imode*dtsdx_c2*Bz(i,j,0,2*imode)/r
+ - mu_c2_dt*Jx(i,j,0,2*imode+1);
+ }
+#endif
#endif
}
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
void warpx_push_ey_yee(int i, int j, int k, Array4<Real> const& Ey,
Array4<Real const> const& Bx, Array4<Real const> const& Bz, Array4<Real const> const& Jy,
- Real mu_c2_dt, Real dtsdx_c2, Real dtsdz_c2, Real rmin)
+ Array4<Real> const& Ex,
+ Real mu_c2_dt, Real dtsdx_c2, Real dtsdz_c2, Real rmin, const long nmodes)
{
#if defined WARPX_DIM_3D
Ey(i,j,k) += - dtsdx_c2 * (Bz(i,j,k) - Bz(i-1,j,k))
+ dtsdz_c2 * (Bx(i,j,k) - Bx(i,j,k-1))
- mu_c2_dt * Jy(i,j,k);
-#elif (defined WARPX_DIM_2D) || (defined WARPX_DIM_RZ)
- // 2D Cartesian and RZ are the same, except that the axis is skipped with RZ
-#ifdef WARPX_DIM_RZ
- if (i != 0 || rmin != 0.)
-#endif
- {
+#elif (defined WARPX_DIM_2D)
Ey(i,j,0) += - dtsdx_c2 * (Bz(i,j,0) - Bz(i-1,j,0))
+ dtsdz_c2 * (Bx(i,j,0) - Bx(i,j-1,0))
- mu_c2_dt * Jy(i,j,0);
+#elif (defined WARPX_DIM_RZ)
+ if (i != 0 || rmin != 0.) {
+ Ey(i,j,0,0) += - dtsdx_c2 * (Bz(i,j,0,0) - Bz(i-1,j,0,0))
+ + dtsdz_c2 * (Bx(i,j,0,0) - Bx(i,j-1,0,0))
+ - mu_c2_dt * Jy(i,j,0,0);
+ } else {
+ Ey(i,j,0,0) = 0.;
+ }
+ for (int imode=1 ; imode < nmodes ; imode++) {
+ if (i == 0 && rmin == 0) {
+ if (imode == 1) {
+ // The bulk equation could in principle be used here since it does not diverge
+ // on axis. However, it typically gives poor results e.g. for the propagation
+ // of a laser pulse (the field is spuriously reduced on axis). For this reason
+ // a modified on-axis condition is used here: we use the fact that
+ // Etheta(r=0,m=1) should equal -iEr(r=0,m=1), for the fields Er and Et to be
+ // independent of theta at r=0. Now with linear interpolation:
+ // Er(r=0,m=1) = 0.5*[Er(r=dr/2,m=1) + Er(r=-dr/2,m=1)]
+ // And using the rule applying for the guards cells
+ // Er(r=-dr/2,m=1) = Er(r=dr/2,m=1). Thus: Et(i,j,m) = -i*Er(i,j,m)
+ Ey(i,j,0,2*imode) = Ex(i,j,0,2*imode+1);
+ Ey(i,j,0,2*imode+1) = -Ex(i,0,j,2*imode);
+ } else {
+ // Etheta should remain 0 on axis, for modes different than m=1
+ Ey(i,j,0,2*imode) = 0.;
+ Ey(i,j,0,2*imode+1) = 0.;
+ }
+ } else {
+ // Et(i,j,m) = Et(i,j,m) - dtsdr*(Bz(i,j,m) - Bz(i-1,j,m)) + dtsdz*(Br(i,j,m) - Br(i,j-1,m)) - mudt*Jt(i,j,m)
+ Ey(i,j,0,2*imode) += - dtsdx_c2 * (Bz(i,j,0,2*imode) - Bz(i-1,j,0,2*imode))
+ + dtsdz_c2 * (Bx(i,j,0,2*imode) - Bx(i,j-1,0,2*imode))
+ - mu_c2_dt * Jy(i,j,0,2*imode);
+ Ey(i,j,0,2*imode+1) += - dtsdx_c2 * (Bz(i,j,0,2*imode+1) - Bz(i-1,j,0,2*imode+1))
+ + dtsdz_c2 * (Bx(i,j,0,2*imode+1) - Bx(i,j-1,0,2*imode+1))
+ - mu_c2_dt * Jy(i,j,0,2*imode+1);
+ }
}
#endif
}
@@ -92,7 +179,7 @@ void warpx_push_ey_yee(int i, int j, int k, Array4<Real> const& Ey,
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
void warpx_push_ez_yee(int i, int j, int k, Array4<Real> const& Ez,
Array4<Real const> const& Bx, Array4<Real const> const& By, Array4<Real const> const& Jz,
- Real mu_c2_dt, Real dtsdx_c2, Real dtsdy_c2, Real dxinv, Real rmin)
+ Real mu_c2_dt, Real dtsdx_c2, Real dtsdy_c2, Real dxinv, Real rmin, const long nmodes)
{
#if defined WARPX_DIM_3D
Ez(i,j,k) += + dtsdx_c2 * (By(i,j,k) - By(i-1,j ,k))
@@ -105,11 +192,28 @@ void warpx_push_ez_yee(int i, int j, int k, Array4<Real> const& Ez,
if (i != 0 || rmin != 0.) {
const Real ru = 1. + 0.5/(rmin*dxinv + i);
const Real rd = 1. - 0.5/(rmin*dxinv + i);
- Ez(i,j,0) += + dtsdx_c2 * (ru*By(i,j,0) - rd*By(i-1,j,0))
- - mu_c2_dt * Jz(i,j,0);
+ Ez(i,j,0,0) += + dtsdx_c2 * (ru*By(i,j,0,0) - rd*By(i-1,j,0,0))
+ - mu_c2_dt * Jz(i,j,0,0);
} else {
- Ez(i,j,0) += + 4.*dtsdx_c2 * By(i,j,0)
- - mu_c2_dt * Jz(i,j,0);
+ Ez(i,j,0,0) += + 4.*dtsdx_c2 * By(i,j,0,0)
+ - mu_c2_dt * Jz(i,j,0,0);
+ }
+ for (int imode=1 ; imode < nmodes ; imode++) {
+ if (i == 0 && rmin == 0) {
+ Ez(i,j,0,2*imode) = 0.;
+ Ez(i,j,0,2*imode+1) = 0.;
+ } else {
+ const Real r = rmin*dxinv + i + 0.5;
+ const Real ru = 1. + 0.5/(rmin*dxinv + i);
+ const Real rd = 1. - 0.5/(rmin*dxinv + i);
+ // Ez(i,j,m) = Ez(i,j,m) + dtsdr*(ru*Bt(i,j,m) - rd*Bt(i-1,j,m)) + I*m*dt*Br(i,j,m)/r - mudt*Jz(i,j,m)
+ Ez(i,j,0,2*imode) += + dtsdx_c2 * (ru*By(i,j,0,2*imode) - rd*By(i-1,j,0,2*imode))
+ - imode*dtsdx_c2*Bx(i,j,0,2*imode+1)/r
+ - mu_c2_dt * Jz(i,j,0,2*imode);
+ Ez(i,j,0,2*imode+1) += + dtsdx_c2 * (ru*By(i,j,0,2*imode+1) - rd*By(i-1,j,0,2*imode+1))
+ + imode*dtsdx_c2*Bx(i,j,0,2*imode)/r
+ - mu_c2_dt * Jz(i,j,0,2*imode+1);
+ }
}
#endif
}