/* Copyright 2019 Luca Fedeli * * This file is part of WarpX. * * License: BSD-3-Clause-LBNL */ #ifndef WARPX_PARTICLES_PUSHER_UPDATEMOMENTUM_BORIS_WITHRR_H_ #define WARPX_PARTICLES_PUSHER_UPDATEMOMENTUM_BORIS_WITHRR_H_ #include "UpdateMomentumBoris.H" #include /** * Push the particle's positions over one timestep, * given the value of its momenta `ux`, `uy`, `uz`. * Includes Radiation Reaction according to * https://doi.org/10.1088/1367-2630/12/12/123005 */ AMREX_GPU_HOST_DEVICE AMREX_INLINE void UpdateMomentumBorisWithRadiationReaction( amrex::ParticleReal& ux, amrex::ParticleReal& uy, amrex::ParticleReal& uz, const amrex::ParticleReal Ex, const amrex::ParticleReal Ey, const amrex::ParticleReal Ez, const amrex::ParticleReal Bx, const amrex::ParticleReal By, const amrex::ParticleReal Bz, const amrex::ParticleReal q, const amrex::ParticleReal m, const amrex::Real dt ) { using namespace amrex::literals; //RR algorithm needs to store old value of the normalized momentum const amrex::ParticleReal ux_old = ux; const amrex::ParticleReal uy_old = uy; const amrex::ParticleReal uz_old = uz; //Useful constant constexpr amrex::ParticleReal inv_c2 = 1._prt/(PhysConst::c*PhysConst::c); //Call to regular Boris pusher UpdateMomentumBoris( ux, uy, uz, Ex, Ey, Ez, Bx, By, Bz, q, m, dt ); //Estimation of the normalized momentum at intermediate (integer) time const amrex::ParticleReal ux_n = (ux+ux_old)*0.5_prt; const amrex::ParticleReal uy_n = (uy+uy_old)*0.5_prt; const amrex::ParticleReal uz_n = (uz+uz_old)*0.5_prt; // Compute Lorentz factor (and inverse) at intermediate (integer) time const amrex::ParticleReal gamma_n = std::sqrt( 1._prt + (ux_n*ux_n + uy_n*uy_n + uz_n*uz_n)*inv_c2); const amrex::ParticleReal inv_gamma_n = 1.0_prt/gamma_n; //Estimation of the velocity at intermediate (integer) time const amrex::ParticleReal vx_n = ux_n*inv_gamma_n; const amrex::ParticleReal vy_n = uy_n*inv_gamma_n; const amrex::ParticleReal vz_n = uz_n*inv_gamma_n; const amrex::ParticleReal bx_n = vx_n/PhysConst::c; const amrex::ParticleReal by_n = vy_n/PhysConst::c; const amrex::ParticleReal bz_n = vz_n/PhysConst::c; //Lorentz force over charge const amrex::ParticleReal flx_q = (Ex + vy_n*Bz - vz_n*By); const amrex::ParticleReal fly_q = (Ey + vz_n*Bx - vx_n*Bz); const amrex::ParticleReal flz_q = (Ez + vx_n*By - vy_n*Bx); const amrex::ParticleReal fl_q2 = flx_q*flx_q + fly_q*fly_q + flz_q*flz_q; //Calculation of auxiliary quantities const amrex::ParticleReal bdotE = (bx_n*Ex + by_n*Ey + bz_n*Ez); const amrex::ParticleReal bdotE2 = bdotE*bdotE; const amrex::ParticleReal coeff = gamma_n*gamma_n*(fl_q2-bdotE2); //Radiation reaction constant const amrex::ParticleReal q_over_mc = q/(m*PhysConst::c); const amrex::ParticleReal RRcoeff = (2.0_prt/3.0_prt)*PhysConst::r_e*q_over_mc*q_over_mc; //Compute the components of the RR force const amrex::ParticleReal frx = RRcoeff*(PhysConst::c*(fly_q*Bz - flz_q*By) + bdotE*Ex - coeff*bx_n); const amrex::ParticleReal fry = RRcoeff*(PhysConst::c*(flz_q*Bx - flx_q*Bz) + bdotE*Ey - coeff*by_n); const amrex::ParticleReal frz = RRcoeff*(PhysConst::c*(flx_q*By - fly_q*Bx) + bdotE*Ez - coeff*bz_n); //Update momentum using the RR force ux += frx*dt; uy += fry*dt; uz += frz*dt; } #endif // WARPX_PARTICLES_PUSHER_UPDATEMOMENTUM_BORIS_WITHRR_H_