aboutsummaryrefslogtreecommitdiff
path: root/Source/Particles/Pusher
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Particles/Pusher')
-rw-r--r--Source/Particles/Pusher/CopyParticleAttribs.H94
-rw-r--r--Source/Particles/Pusher/PushSelector.H144
2 files changed, 238 insertions, 0 deletions
diff --git a/Source/Particles/Pusher/CopyParticleAttribs.H b/Source/Particles/Pusher/CopyParticleAttribs.H
new file mode 100644
index 000000000..1f8a190ea
--- /dev/null
+++ b/Source/Particles/Pusher/CopyParticleAttribs.H
@@ -0,0 +1,94 @@
+/* Copyright 2020 Andrew Myers
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+#ifndef WARPX_PARTICLES_PUSHER_COPYPARTICLEATTRIBS_H_
+#define WARPX_PARTICLES_PUSHER_COPYPARTICLEATTRIBS_H_
+
+#include "Particles/WarpXParticleContainer.H"
+
+#include <AMReX_REAL.H>
+
+#include <limits>
+
+
+/** \brief Functor that creates copies of the current particle
+ * positions and momenta for later use. This is needed
+ * by the back-transformed diagnostics.
+ *
+ * \param a_pti iterator to the tile containing the macroparticles
+ * \param a_tmp holder for the temporary particle data
+*/
+struct CopyParticleAttribs
+{
+ using TmpParticles = WarpXParticleContainer::TmpParticles;
+
+ GetParticlePosition m_get_position;
+
+ const amrex::ParticleReal* AMREX_RESTRICT uxp = nullptr;
+ const amrex::ParticleReal* AMREX_RESTRICT uyp = nullptr;
+ const amrex::ParticleReal* AMREX_RESTRICT uzp = nullptr;
+
+ amrex::ParticleReal* AMREX_RESTRICT xpold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT ypold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT zpold = nullptr;
+
+ amrex::ParticleReal* AMREX_RESTRICT uxpold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT uypold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT uzpold = nullptr;
+
+ CopyParticleAttribs (const WarpXParIter& a_pti, TmpParticles& tmp_particle_data) noexcept
+ {
+ if (tmp_particle_data.size() == 0) return;
+
+ auto& attribs = a_pti.GetAttribs();
+ uxp = attribs[PIdx::ux].dataPtr();
+ uyp = attribs[PIdx::uy].dataPtr();
+ uzp = attribs[PIdx::uz].dataPtr();
+
+ const auto lev = a_pti.GetLevel();
+ const auto index = a_pti.GetPairIndex();
+ xpold = tmp_particle_data[lev][index][TmpIdx::xold ].dataPtr();
+ ypold = tmp_particle_data[lev][index][TmpIdx::yold ].dataPtr();
+ zpold = tmp_particle_data[lev][index][TmpIdx::zold ].dataPtr();
+ uxpold = tmp_particle_data[lev][index][TmpIdx::uxold].dataPtr();
+ uypold = tmp_particle_data[lev][index][TmpIdx::uyold].dataPtr();
+ uzpold = tmp_particle_data[lev][index][TmpIdx::uzold].dataPtr();
+
+ m_get_position = GetParticlePosition(a_pti);
+ }
+
+ /** \brief copy the position and momentum of particle i to the
+ * temporary data holder
+ */
+ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
+ void operator() (const int i) const noexcept
+ {
+ AMREX_ASSERT(uxp != nullptr);
+ AMREX_ASSERT(uyp != nullptr);
+ AMREX_ASSERT(uzp != nullptr);
+
+ AMREX_ASSERT(xpold != nullptr);
+ AMREX_ASSERT(ypold != nullptr);
+ AMREX_ASSERT(zpold != nullptr);
+
+ AMREX_ASSERT(uxpold != nullptr);
+ AMREX_ASSERT(uypold != nullptr);
+ AMREX_ASSERT(uzpold != nullptr);
+
+ amrex::ParticleReal x, y, z;
+ m_get_position(i, x, y, z);
+
+ xpold[i] = x;
+ ypold[i] = y;
+ zpold[i] = z;
+
+ uxpold[i] = uxp[i];
+ uypold[i] = uyp[i];
+ uzpold[i] = uzp[i];
+ }
+};
+
+#endif // WARPX_PARTICLES_PUSHER_COPYPARTICLEATTRIBS_H_
diff --git a/Source/Particles/Pusher/PushSelector.H b/Source/Particles/Pusher/PushSelector.H
new file mode 100644
index 000000000..149342b74
--- /dev/null
+++ b/Source/Particles/Pusher/PushSelector.H
@@ -0,0 +1,144 @@
+/* Copyright 2020 Andrew Myers
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+#ifndef WARPX_PARTICLES_PUSHER_PUSHSELECTOR_H_
+#define WARPX_PARTICLES_PUSHER_PUSHSELECTOR_H_
+
+// Import low-level single-particle kernels
+#include "Particles/Pusher/UpdatePosition.H"
+#include "Particles/Pusher/UpdateMomentumBoris.H"
+#include "Particles/Pusher/UpdateMomentumVay.H"
+#include "Particles/Pusher/UpdateMomentumBorisWithRadiationReaction.H"
+#include "Particles/Pusher/UpdateMomentumHigueraCary.H"
+#include "Particles/WarpXParticleContainer.H"
+
+#include <AMReX_REAL.H>
+
+#include <limits>
+
+/**
+ * \brief Push position and momentum for a single particle
+ *
+ * /param GetPosition : A functor for returning the particle position.
+ * /param GetPosition : A functor for setting the particle position.
+ * /param copyAttribs : A functor for storing the old u and x
+ * /param i : The index of the particle to work on
+ * \param ux, uy, uz : Particle momentum
+ * \param Ex, Ey, Ez : Electric field on particles.
+ * \param Bx, By, Bz : Magnetic field on particles.
+ * \param ion_lev : Ionization level of this particle (0 if ioniziation not on)
+ * \param m : Mass of this species.
+ * \param q : Charge of this species.
+ * \param pusher_algo : 0: Boris, 1: Vay, 2: HigueraCary
+ * \param do_crr : Whether to do the classical radiation reaction
+ * \param do_crr : 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
+ */
+AMREX_GPU_DEVICE AMREX_FORCE_INLINE
+void doParticlePush(const GetParticlePosition& GetPosition,
+ const SetParticlePosition& SetPosition,
+ const CopyParticleAttribs& copyAttribs,
+ const long i,
+ 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 int ion_lev,
+ const amrex::Real m,
+ const amrex::Real 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)
+{
+ if (do_copy) copyAttribs(i);
+ if (do_crr) {
+#ifdef WARPX_QED
+ if (do_sync) {
+ auto chi = QedUtils::chi_lepton(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);
+ }
+ else {
+ UpdateMomentumBoris( ux, uy, uz,
+ Ex, Ey, Ez, Bx,
+ By, Bz, q, 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 {
+ UpdateMomentumBorisWithRadiationReaction(ux, uy, uz,
+ Ex, Ey, Ez, Bx,
+ By, Bz, q, 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::Real 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::Real qp = q;
+ if (ion_lev) { qp *= ion_lev; }
+ UpdateMomentumBoris( 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);
+ } else if (pusher_algo == ParticlePusherAlgo::Vay) {
+ amrex::Real qp = q;
+ if (ion_lev){ qp *= ion_lev; }
+ UpdateMomentumVay( 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);
+ } else if (pusher_algo == ParticlePusherAlgo::HigueraCary) {
+ amrex::Real qp = q;
+ if (ion_lev){ qp *= ion_lev; }
+ UpdateMomentumHigueraCary( 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);
+ } else {
+ amrex::Abort("Unknown particle pusher");
+ }
+}
+
+#endif // WARPX_PARTICLES_PUSHER_SELECTOR_H_