diff options
-rw-r--r-- | Source/Particles/Gather/GetExternalFields.H | 6 | ||||
-rw-r--r-- | Source/Particles/PhysicalParticleContainer.cpp | 73 | ||||
-rw-r--r-- | Source/Particles/Pusher/PushSelector.H | 47 |
3 files changed, 80 insertions, 46 deletions
diff --git a/Source/Particles/Gather/GetExternalFields.H b/Source/Particles/Gather/GetExternalFields.H index 92f1a21bc..ff107dce5 100644 --- a/Source/Particles/Gather/GetExternalFields.H +++ b/Source/Particles/Gather/GetExternalFields.H @@ -13,13 +13,12 @@ #include <AMReX_Parser.H> #include <AMReX_REAL.H> -enum ExternalFieldInitType { None, Constant, Parser, RepeatedPlasmaLens, Unknown }; - /** \brief Functor class that assigns external * field values (E and B) to particles. */ struct GetExternalEBField { + enum ExternalFieldInitType { None, Constant, Parser, RepeatedPlasmaLens, Unknown }; GetExternalEBField () = default; @@ -56,6 +55,9 @@ struct GetExternalEBField const amrex::ParticleReal* AMREX_RESTRICT m_uz = nullptr; AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE + bool isNoOp () const { return (m_Etype == None && m_Btype == None); } + + AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void operator () (long i, amrex::ParticleReal& field_Ex, amrex::ParticleReal& field_Ey, diff --git a/Source/Particles/PhysicalParticleContainer.cpp b/Source/Particles/PhysicalParticleContainer.cpp index f37ea5ea3..62d4df594 100644 --- a/Source/Particles/PhysicalParticleContainer.cpp +++ b/Source/Particles/PhysicalParticleContainer.cpp @@ -2624,7 +2624,24 @@ PhysicalParticleContainer::PushPX (WarpXParIter& pti, const auto t_do_not_gather = do_not_gather; - amrex::ParallelFor( np_to_push, [=] AMREX_GPU_DEVICE (long ip) + enum exteb_flags : int { no_exteb, has_exteb }; + enum qed_flags : int { no_qed, has_qed }; + + int exteb_runtime_flag = getExternalEB.isNoOp() ? no_exteb : has_exteb; +#ifdef WARPX_QED + int qed_runtime_flag = (local_has_quantum_sync || do_sync) ? has_qed : no_qed; +#else + int qed_runtime_flag = no_qed; +#endif + + // Using this version of ParallelFor with compile time options + // improves performance when qed or external EB are not used by reducing + // register pressure. + amrex::ParallelFor(TypeList<CompileTimeOptions<no_exteb,has_exteb>, + CompileTimeOptions<no_qed ,has_qed>>{}, + {exteb_runtime_flag, qed_runtime_flag}, + np_to_push, [=] AMREX_GPU_DEVICE (long ip, auto exteb_control, + [[maybe_unused]] auto qed_control) { amrex::ParticleReal xp, yp, zp; getPosition(ip, xp, yp, zp); @@ -2650,30 +2667,54 @@ PhysicalParticleContainer::PushPX (WarpXParIter& pti, dx_arr, xyzmin_arr, lo, n_rz_azimuthal_modes, nox, galerkin_interpolation); } - // Externally applied E and B-field in Cartesian co-ordinates - getExternalEB(ip, Exp, Eyp, Ezp, Bxp, Byp, Bzp); + + auto const& externeb_fn = getExternalEB; // Have to do this for nvcc + if constexpr (exteb_control == has_exteb) { + externeb_fn(ip, Exp, Eyp, Ezp, Bxp, Byp, Bzp); + } scaleFields(xp, yp, zp, Exp, Eyp, Ezp, Bxp, Byp, Bzp); - doParticlePush(getPosition, setPosition, copyAttribs, ip, - ux[ip], uy[ip], uz[ip], - Exp, Eyp, Ezp, Bxp, Byp, Bzp, - ion_lev ? ion_lev[ip] : 0, - m, q, pusher_algo, do_crr, do_copy, #ifdef WARPX_QED - do_sync, - t_chi_max, + if (!do_sync) #endif - dt); - + { + doParticlePush<0>(getPosition, setPosition, copyAttribs, ip, + ux[ip], uy[ip], uz[ip], + Exp, Eyp, Ezp, Bxp, Byp, Bzp, + ion_lev ? ion_lev[ip] : 0, + m, q, pusher_algo, do_crr, do_copy, #ifdef WARPX_QED - if (local_has_quantum_sync) { - evolve_opt(ux[ip], uy[ip], uz[ip], - Exp, Eyp, Ezp,Bxp, Byp, Bzp, - dt, p_optical_depth_QSR[ip]); + t_chi_max, +#endif + dt); + } +#ifdef WARPX_QED + else { + if constexpr (qed_control == has_qed) { + doParticlePush<1>(getPosition, setPosition, copyAttribs, ip, + ux[ip], uy[ip], uz[ip], + Exp, Eyp, Ezp, Bxp, Byp, Bzp, + ion_lev ? ion_lev[ip] : 0, + m, q, pusher_algo, do_crr, do_copy, + t_chi_max, + dt); + } } #endif +#ifdef WARPX_QED + auto foo_local_has_quantum_sync = local_has_quantum_sync; + auto foo_podq = p_optical_depth_QSR; + auto& evolve_opt_fn = evolve_opt; // have to do all these for nvcc + if constexpr (qed_control == has_qed) { + if (foo_local_has_quantum_sync) { + evolve_opt_fn(ux[ip], uy[ip], uz[ip], + Exp, Eyp, Ezp,Bxp, Byp, Bzp, + dt, foo_podq[ip]); + } + } +#endif }); } diff --git a/Source/Particles/Pusher/PushSelector.H b/Source/Particles/Pusher/PushSelector.H index ed439b4b3..a56dda2b9 100644 --- a/Source/Particles/Pusher/PushSelector.H +++ b/Source/Particles/Pusher/PushSelector.H @@ -23,6 +23,7 @@ /** * \brief Push position and momentum for a single particle * + * \tparam do_sync Whether to include quantum synchrotron radiation (QSR) * \param GetPosition A functor for returning the particle position. * \param SetPosition A functor for setting the particle position. * \param copyAttribs A functor for storing the old u and x @@ -36,10 +37,11 @@ * \param pusher_algo 0: Boris, 1: Vay, 2: HigueraCary * \param do_crr Whether to do the classical radiation reaction * \param do_copy Whether to copy the old x and u for the BTD - * \param do_sync Whether to include quantum synchrotron radiation (QSR) * \param t_chi_max Cutoff chi for QSR * \param dt Time step size */ + +template <int do_sync> AMREX_GPU_DEVICE AMREX_FORCE_INLINE void doParticlePush(const GetParticlePosition& GetPosition, const SetParticlePosition& SetPosition, @@ -56,60 +58,53 @@ void doParticlePush(const GetParticlePosition& GetPosition, const amrex::ParticleReal Bz, const int ion_lev, const amrex::ParticleReal m, - const amrex::ParticleReal q, + const amrex::ParticleReal a_q, const int pusher_algo, const int do_crr, const int do_copy, #ifdef WARPX_QED - const int do_sync, const amrex::Real t_chi_max, #endif const amrex::Real dt) { + amrex::ParticleReal qp = a_q; + if (ion_lev) { qp *= ion_lev; } + if (do_copy) copyAttribs(i); if (do_crr) { #ifdef WARPX_QED - if (do_sync) { + amrex::ignore_unused(t_chi_max); + if constexpr (do_sync) { auto chi = QedUtils::chi_ele_pos(m*ux, m*uy, m*uz, Ex, Ey, Ez, Bx, By, Bz); if (chi < t_chi_max) { UpdateMomentumBorisWithRadiationReaction(ux, uy, uz, Ex, Ey, Ez, Bx, - By, Bz, q, m, dt); + By, Bz, qp, m, dt); } else { UpdateMomentumBoris( ux, uy, uz, Ex, Ey, Ez, Bx, - By, Bz, q, m, dt); + By, Bz, qp, m, dt); } amrex::ParticleReal x, y, z; GetPosition(i, x, y, z); UpdatePosition(x, y, z, ux, uy, uz, dt ); SetPosition(i, x, y, z); - } else { + } else +#endif + { + UpdateMomentumBorisWithRadiationReaction(ux, uy, uz, Ex, Ey, Ez, Bx, - By, Bz, q, m, dt); + By, Bz, qp, m, dt); amrex::ParticleReal x, y, z; GetPosition(i, x, y, z); UpdatePosition(x, y, z, ux, uy, uz, dt ); SetPosition(i, x, y, z); } -#else - amrex::ParticleReal qp = q; - if (ion_lev) { qp *= ion_lev; } - UpdateMomentumBorisWithRadiationReaction(ux, uy, uz, - Ex, Ey, Ez, Bx, - By, Bz, qp, m, dt); - amrex::ParticleReal x, y, z; - GetPosition(i, x, y, z); - UpdatePosition(x, y, z, ux, uy, uz, dt ); - SetPosition(i, x, y, z); -#endif } else if (pusher_algo == ParticlePusherAlgo::Boris) { - amrex::ParticleReal qp = q; - if (ion_lev) { qp *= ion_lev; } UpdateMomentumBoris( ux, uy, uz, Ex, Ey, Ez, Bx, By, Bz, qp, m, dt); @@ -118,8 +113,6 @@ void doParticlePush(const GetParticlePosition& GetPosition, UpdatePosition(x, y, z, ux, uy, uz, dt ); SetPosition(i, x, y, z); } else if (pusher_algo == ParticlePusherAlgo::Vay) { - amrex::ParticleReal qp = q; - if (ion_lev){ qp *= ion_lev; } UpdateMomentumVay( ux, uy, uz, Ex, Ey, Ez, Bx, By, Bz, qp, m, dt); @@ -128,8 +121,6 @@ void doParticlePush(const GetParticlePosition& GetPosition, UpdatePosition(x, y, z, ux, uy, uz, dt ); SetPosition(i, x, y, z); } else if (pusher_algo == ParticlePusherAlgo::HigueraCary) { - amrex::ParticleReal qp = q; - if (ion_lev){ qp *= ion_lev; } UpdateMomentumHigueraCary( ux, uy, uz, Ex, Ey, Ez, Bx, By, Bz, qp, m, dt); @@ -137,9 +128,9 @@ void doParticlePush(const GetParticlePosition& GetPosition, GetPosition(i, x, y, z); UpdatePosition(x, y, z, ux, uy, uz, dt ); SetPosition(i, x, y, z); - } else { - amrex::Abort("Unknown particle pusher"); - } + } //else { +// amrex::Abort("Unknown particle pusher"); +// } } #endif // WARPX_PARTICLES_PUSHER_SELECTOR_H_ |