aboutsummaryrefslogtreecommitdiff
path: root/Source/Diagnostics/ComputeDiagFunctors/BackTransformParticleFunctor.H
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Diagnostics/ComputeDiagFunctors/BackTransformParticleFunctor.H')
-rw-r--r--Source/Diagnostics/ComputeDiagFunctors/BackTransformParticleFunctor.H237
1 files changed, 237 insertions, 0 deletions
diff --git a/Source/Diagnostics/ComputeDiagFunctors/BackTransformParticleFunctor.H b/Source/Diagnostics/ComputeDiagFunctors/BackTransformParticleFunctor.H
new file mode 100644
index 000000000..59ceb12cc
--- /dev/null
+++ b/Source/Diagnostics/ComputeDiagFunctors/BackTransformParticleFunctor.H
@@ -0,0 +1,237 @@
+/* Copyright 2021 Revathi Jambunathan
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+#ifndef WARPX_BACKTRANSFORMPARTICLEFUNCTOR_H_
+#define WARPX_BACKTRANSFORMPARTICLEFUNCTOR_H_
+
+#include "ComputeParticleDiagFunctor.H"
+#include "Particles/Pusher/GetAndSetPosition.H"
+
+#include <AMReX.H>
+#include <AMReX_AmrParticles.H>
+
+
+
+
+/**
+ * \brief Filter to select particles that correspond to a z-slice of the corresponding lab-frame.
+ */
+struct SelectParticles
+{
+ using TmpParticles = WarpXParticleContainer::TmpParticles;
+
+ /**
+ * \brief Constructor of SelectParticles functor.
+ *
+ * @param[in] a_pti WarpX particle iterator
+ * @param[in] tmp_particle_data temporary particle data
+ * @param[in] current_z_boost current z-position of the slice in boosted frame
+ * @param[in] old_z_boost previous z-position of the slice in boosted frame
+ */
+ SelectParticles( const WarpXParIter& a_pti, TmpParticles& tmp_particle_data,
+ amrex::Real current_z_boost, amrex::Real old_z_boost,
+ int a_offset = 0);
+
+ /**
+ * \brief Functor call. This method determines if a given particle should be selected
+ * for Lorentz transformation in obtaining the lab-frame data. The particles that
+ * with positions that correspond to the specific z-slice in boosted frame are selected.
+ *
+ * @param[in] SrcData particle tile data
+ * @param[in] i particle index
+ * @return 1 if particles is selected for transformation, else 0
+ */
+ template <typename SrcData>
+ AMREX_GPU_HOST_DEVICE
+ int operator() (const SrcData& src, int i) const noexcept
+ {
+ amrex::ignore_unused(src);
+ amrex::ParticleReal xp, yp, zp;
+ m_get_position(i, xp, yp, zp);
+ int Flag = 0;
+ if ( ( (zp >= m_current_z_boost) && (zpold[i] <= m_old_z_boost) ) ||
+ ( (zp <= m_current_z_boost) && (zpold[i] >= m_old_z_boost) ))
+ { Flag = 1;
+ }
+ return Flag;
+ }
+
+ /** Object to extract the positions of the macroparticles inside a ParallelFor kernel */
+ GetParticlePosition m_get_position;
+ /** Z coordinate in boosted frame that corresponds to a give snapshot*/
+ amrex::Real m_current_z_boost;
+ /** Previous Z coordinate in boosted frame that corresponds to a give snapshot*/
+ amrex::Real m_old_z_boost;
+ /** Particle z coordinate in boosted frame*/
+ amrex::ParticleReal* AMREX_RESTRICT zpold = nullptr;
+};
+
+/**
+ * \brief Transform functor to Lorentz-transform particles and obtain lab-frame data.
+ */
+struct LorentzTransformParticles
+{
+
+ using TmpParticles = WarpXParticleContainer::TmpParticles;
+
+ /**
+ * \brief Constructor of the LorentzTransformParticles functor.
+ *
+ * @param[in] a_pti WarpX particle iterator
+ * @param[in] tmp_particle_data temporary particle data
+ * @param[in] t_boost time in boosted frame
+ * @param[in] dt timestep in boosted-frame
+ * @param[in] t_lab time in lab-frame
+ */
+ LorentzTransformParticles ( const WarpXParIter& a_pti, TmpParticles& tmp_particle_data,
+ amrex::Real t_boost, amrex::Real dt,
+ amrex::Real t_lab, int a_offset = 0);
+
+ /**
+ * \brief Functor call. This method computes the Lorentz-transform for particle
+ * attributes to obtain the lab-frame snapshot data.
+ *
+ * @param[out] DstData particle tile data that stores the transformed particle data
+ * @param[in] SrcData particle tile data that is selected for transformation
+ * @param[in] i_src particle index of the source particles
+ * @param[in] i_dst particle index of the target particles (transformed data).
+ */
+ template <typename DstData, typename SrcData>
+ AMREX_GPU_HOST_DEVICE
+ void operator () (const DstData& dst, const SrcData& src, int i_src, int i_dst) const noexcept
+ {
+ amrex::ignore_unused(src);
+ using namespace amrex::literals;
+ // get current src position
+ amrex::ParticleReal xpnew, ypnew, zpnew;
+ m_get_position(i_src, xpnew, ypnew, zpnew);
+ const amrex::Real gamma_new_p = std::sqrt(1.0_rt + m_inv_c2*
+ ( m_uxpnew[i_src] * m_uxpnew[i_src]
+ + m_uypnew[i_src] * m_uypnew[i_src]
+ + m_uzpnew[i_src] * m_uzpnew[i_src]));
+ const amrex::Real gamma_old_p = std::sqrt(1.0_rt + m_inv_c2*
+ ( m_uxpold[i_src] * m_uxpold[i_src]
+ + m_uypold[i_src] * m_uypold[i_src]
+ + m_uzpold[i_src] * m_uzpold[i_src]));
+ const amrex::Real t_new_p = m_gammaboost * m_t_boost - m_uzfrm * zpnew * m_inv_c2;
+ const amrex::Real z_new_p = m_gammaboost* ( zpnew + m_betaboost * m_Phys_c * m_t_boost);
+ const amrex::Real uz_new_p = m_gammaboost * m_uzpnew[i_src] - gamma_new_p * m_uzfrm;
+ const amrex::Real t_old_p = m_gammaboost * (m_t_boost - m_dt)
+ - m_uzfrm * m_zpold[i_src] * m_inv_c2;
+ const amrex::Real z_old_p = m_gammaboost * ( m_zpold[i_src] + m_betaboost
+ * m_Phys_c * (m_t_boost - m_dt ) );
+ const amrex::Real uz_old_p = m_gammaboost * m_uzpold[i_src] - gamma_old_p * m_uzfrm;
+ // interpolate in time to t_lab
+ const amrex::Real weight_old = (t_new_p - m_t_lab)
+ / (t_new_p - t_old_p);
+ const amrex::Real weight_new = (m_t_lab - t_old_p)
+ / (t_new_p - t_old_p);
+ // weighted sum of old and new values
+ const amrex::ParticleReal xp = m_xpold[i_src] * weight_old + xpnew * weight_new;
+ const amrex::ParticleReal yp = m_ypold[i_src] * weight_old + ypnew * weight_new;
+ const amrex::ParticleReal zp = z_old_p * weight_old + z_new_p * weight_new;
+ const amrex::ParticleReal uxp = m_uxpold[i_src] * weight_old
+ + m_uxpnew[i_src] * weight_new;
+ const amrex::ParticleReal uyp = m_uypold[i_src] * weight_old
+ + m_uypnew[i_src] * weight_new;
+ const amrex::ParticleReal uzp = uz_old_p * weight_old
+ + uz_new_p * weight_new;
+#if defined (WARPX_DIM_3D)
+ dst.m_aos[i_dst].pos(0) = xp;
+ dst.m_aos[i_dst].pos(1) = yp;
+ dst.m_aos[i_dst].pos(2) = zp;
+#elif defined (WARPX_DIM_XZ)
+ dst.m_aos[i_dst].pos(0) = xp;
+ dst.m_aos[i_dst].pos(1) = zp;
+ amrex::ignore_unused(yp);
+#elif defined (WARPX_DIM_1D)
+ dst.m_aos[i_dst].pos(0) = zp;
+ amrex::ignore_unused(xp, yp);
+#else
+ amrex::ignore_unused(xp, yp, zp);
+#endif
+ dst.m_rdata[PIdx::w][i_dst] = m_wpnew[i_src];
+ dst.m_rdata[PIdx::ux][i_dst] = uxp;
+ dst.m_rdata[PIdx::uy][i_dst] = uyp;
+ dst.m_rdata[PIdx::uz][i_dst] = uzp;
+ }
+
+ GetParticlePosition m_get_position;
+
+ amrex::ParticleReal* AMREX_RESTRICT m_xpold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT m_ypold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT m_zpold = nullptr;
+
+ amrex::ParticleReal* AMREX_RESTRICT m_uxpold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT m_uypold = nullptr;
+ amrex::ParticleReal* AMREX_RESTRICT m_uzpold = nullptr;
+
+ const amrex::ParticleReal* AMREX_RESTRICT m_uxpnew = nullptr;
+ const amrex::ParticleReal* AMREX_RESTRICT m_uypnew = nullptr;
+ const amrex::ParticleReal* AMREX_RESTRICT m_uzpnew = nullptr;
+ const amrex::ParticleReal* AMREX_RESTRICT m_wpnew = nullptr;
+
+ amrex::Real m_gammaboost;
+ amrex::Real m_betaboost;
+ amrex::Real m_Phys_c;
+ amrex::Real m_uzfrm;
+ amrex::Real m_inv_c2;
+ amrex::Real m_t_boost;
+ amrex::Real m_dt;
+ amrex::Real m_t_lab;
+};
+
+/**
+ * \brief BackTransform functor to select particles and Lorentz Transform them
+ * and store in particle buffers
+ */
+class
+BackTransformParticleFunctor final : public ComputeParticleDiagFunctor
+{
+public:
+ BackTransformParticleFunctor(WarpXParticleContainer *pc_src, std::string species_name, int num_buffers);
+ /** Computes the Lorentz transform of source particles to obtain lab-frame data in pc_dst*/
+ void operator () (ParticleContainer& pc_dst, int &TotalParticleCounter, int i_buffer) const override;
+ void InitData() override;
+ /** \brief Prepare data required to back-transform particle attribtutes for lab-frame snapshot, i_buffer
+ *
+ * \param[in] i_buffer index of the snapshot
+ * \param[in] z_slice_in_domain if the z-slice at current_z_boost is within the bounds of
+ * the boosted-frame and lab-frame domain. The particles are transformed
+ * only if this value is true.
+ * \param[in] current_z_boost z co-ordinate of the slice selected in boosted-frame.
+ * \param[in] t_lab current time in lab-frame for snapshot, i_buffer.
+ * \param[in] snapshot_full if the current snapshot, with index, i_buffer, is
+ * full (1) or not (0). If it is full, then Lorentz-transform is not performed
+ * by setting m_perform_backtransform to 0 for the corresponding ith snapshot.
+ */
+ void PrepareFunctorData ( int i_buffer, bool z_slice_in_domain, amrex::Real old_z_boost,
+ amrex::Real current_z_boost, amrex::Real t_lab,
+ int snapshot_full) override;
+private:
+ /** Source particle container */
+ WarpXParticleContainer* m_pc_src = nullptr;
+ /** String containing species name of particles being transformed*/
+ std::string m_species_name;
+ /** Number of buffers or snapshots*/
+ int m_num_buffers;
+ /** Vector of current z co-ordinate in the boosted frame for each snapshot*/
+ amrex::Vector<amrex::Real> m_current_z_boost;
+ /** Vector of previous z co-ordinate in the boosted frame for each snapshot*/
+ amrex::Vector<amrex::Real> m_old_z_boost;
+ /** Vector of lab-frame time for each snapshot*/
+ amrex::Vector<amrex::Real> m_t_lab;
+ /** Vector of 0s and 1s stored to check if back-transformation is to be performed for
+ * the ith snapshot. The value is set to 0 (false) or 1 (true) using the
+ * boolean ZSliceInDomain in PrepareFunctorData()
+ */
+ amrex::Vector<int> m_perform_backtransform;
+};
+
+
+
+
+#endif //