/* Copyright 2019 Luca Fedeli * * This file is part of WarpX. * * License: BSD-3-Clause-LBNL */ #ifndef WARPX_quantum_sync_engine_wrapper_h_ #define WARPX_quantum_sync_engine_wrapper_h_ #include "BreitWheelerEngineWrapper_fwd.H" #include "QedChiFunctions.H" #include "QedWrapperCommons.H" #include "Utils/WarpXConst.H" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace amrex { struct RandomEngine; } // Aliases ============================= using QS_dndt_table_params = picsar::multi_physics::phys::quantum_sync:: dndt_lookup_table_params; using QS_dndt_table = picsar::multi_physics::phys::quantum_sync:: dndt_lookup_table< amrex::Real, amrex::Gpu::DeviceVector>; using QS_dndt_table_view = QS_dndt_table::view_type; using QS_phot_em_table_params = picsar::multi_physics::phys::quantum_sync:: photon_emission_lookup_table_params; using QS_phot_em_table = picsar::multi_physics::phys::quantum_sync:: photon_emission_lookup_table< amrex::Real, amrex::Gpu::DeviceVector>; using QS_phot_em_table_view = QS_phot_em_table::view_type; struct PicsarQuantumSyncCtrl { QS_dndt_table_params dndt_params; QS_phot_em_table_params phot_em_params; }; // Functors ================================== // These functors allow using the core elementary functions of the library. // They are generated by a factory class (QuantumSynchrotronEngine, see below). // They can be included in GPU kernels. /** * Functor to initialize the optical depth of leptons for the * Quantum Synchrotron process */ class QuantumSynchrotronGetOpticalDepth { public: /** * Constructor does nothing because optical depth initialization * does not require control parameters or lookup tables. */ QuantumSynchrotronGetOpticalDepth () = default; /** * () operator is just a thin wrapper around a very simple function to * generate the optical depth. It can be used on GPU. */ AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE amrex::Real operator() (amrex::RandomEngine const& engine) const noexcept { namespace pxr_qs = picsar::multi_physics::phys::quantum_sync; //A random number in [0,1) should be provided as an argument. return pxr_qs::get_optical_depth(amrex::Random(engine)); } }; //____________________________________________ /** * Functor to evolve the optical depth of leptons due to the * Quantum Synchrotron process */ class QuantumSynchrotronEvolveOpticalDepth { public: /** * Default constructor: it leaves the functor in a non-initialized state. */ QuantumSynchrotronEvolveOpticalDepth () = default; /** * Constructor to be used to initialize the functor. * * @param[in] table_view a view of a QS_dndt_table lookup table * @param[in] qs_minimum_chi_part the minimum quantum parameter to evolve the optical depth */ QuantumSynchrotronEvolveOpticalDepth ( const QS_dndt_table_view table_view, const amrex::ParticleReal qs_minimum_chi_part): m_table_view{table_view}, m_qs_minimum_chi_part{qs_minimum_chi_part}{} /** * Evolves the optical depth. It can be used on GPU. * If the quantum parameter parameter of the particle is * < qs_minimum_chi_part, the method returns immediately. * * @param[in] ux,uy,uz gamma*v components of the lepton. * @param[in] ex,ey,ez electric field components (SI units) * @param[in] bx,by,bz magnetic field components (SI units) * @param[in] dt timestep (SI units) * @param[in,out] opt_depth optical depth of the particle. * @return a flag which is 1 if chi_part was out of table. */ AMREX_GPU_DEVICE AMREX_FORCE_INLINE int operator()( const amrex::Real ux, const amrex::Real uy, const amrex::Real uz, const amrex::Real ex, const amrex::Real ey, const amrex::Real ez, const amrex::Real bx, const amrex::Real by, const amrex::Real bz, const amrex::Real dt, amrex::Real& opt_depth) const noexcept { using namespace amrex::literals; namespace pxr_p = picsar::multi_physics::phys; namespace pxr_qs = picsar::multi_physics::phys::quantum_sync; constexpr amrex::Real m_e = PhysConst::m_e; constexpr amrex::Real inv_c2 = 1._rt/(PhysConst::c*PhysConst::c); const amrex::Real gamma = std::sqrt(1._rt + (ux*ux + uy*uy + uz*uz)*inv_c2); const auto energy = gamma*m_e*PhysConst::c*PhysConst::c; const auto chi_part = QedUtils::chi_ele_pos( m_e*ux, m_e*uy, m_e*uz, ex, ey, ez, bx, by, bz); if (chi_part < m_qs_minimum_chi_part) return 0; const auto is_out = pxr_qs::evolve_optical_depth< amrex::Real, QS_dndt_table_view, pxr_p::unit_system::SI>( energy, chi_part, dt, opt_depth, m_table_view); return is_out; } private: QS_dndt_table_view m_table_view; amrex::ParticleReal m_qs_minimum_chi_part; }; /** * Functor to generate a photon via the Quantum Synchrotron process * and to update momentum accordingly */ class QuantumSynchrotronPhotonEmission { public: /** * Default constructor: it leaves the functor in a non-initialized state. */ QuantumSynchrotronPhotonEmission () = default; /** * Constructor acquires pointers to control parameters and * lookup tables data. * lookup_table uses non-owning vectors under the hood. So no new data * allocations should be triggered on GPU * * @param[in] table_view a view of a QS_phot_em_table lookup table */ QuantumSynchrotronPhotonEmission ( const QS_phot_em_table_view table_view): m_table_view{table_view}{} /** * Generates photons according to Quantum Synchrotron process. * It can be used on GPU. * * @param[in,out] ux,uy,uz gamma*v components of the lepton. They are modified (SI units) * @param[in] ex,ey,ez electric field components (SI units) * @param[in] bx,by,bz magnetic field components (SI units) * @param[out] g_ux,g_uy,g_uz gamma*v components of the generated photon (SI units) * @param[in] engine random number generator engine * @return a flag which is 1 if chi_photon was out of table */ AMREX_GPU_DEVICE AMREX_FORCE_INLINE bool operator()( 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, amrex::ParticleReal& g_ux, amrex::ParticleReal& g_uy, amrex::ParticleReal& g_uz, amrex::RandomEngine const& engine) const noexcept { using namespace amrex; namespace pxr_m = picsar::multi_physics::math; namespace pxr_p = picsar::multi_physics::phys; namespace pxr_qs = picsar::multi_physics::phys::quantum_sync; const auto rand_zero_one_minus_epsi = amrex::Random(engine); constexpr ParticleReal me = PhysConst::m_e; constexpr ParticleReal one_over_me = 1._prt/me; // Particle momentum is stored as gamma * velocity. // Convert to m * gamma * velocity auto px = ux*me; auto py = uy*me; auto pz = uz*me; const auto chi_particle = QedUtils::chi_ele_pos( px, py, pz, ex, ey, ez, bx, by, bz); auto momentum_particle = pxr_m::vec3{px, py, pz}; auto momentum_photon = pxr_m::vec3(); const auto is_out = pxr_qs::generate_photon_update_momentum< amrex::ParticleReal, QS_phot_em_table_view, pxr_p::unit_system::SI>( chi_particle, momentum_particle, rand_zero_one_minus_epsi, m_table_view, momentum_photon); ux = momentum_particle[0]*one_over_me; uy = momentum_particle[1]*one_over_me; uz = momentum_particle[2]*one_over_me; g_ux = momentum_photon[0]*one_over_me; g_uy = momentum_photon[1]*one_over_me; g_uz = momentum_photon[2]*one_over_me; return is_out; } private: QS_phot_em_table_view m_table_view; }; // Factory class ============================= /** * Wrapper for the Quantum Synchrotron engine of the PICSAR library */ class QuantumSynchrotronEngine { public: /** * Constructor requires no arguments. */ QuantumSynchrotronEngine () = default; /** * Builds the functor to initialize the optical depth */ QuantumSynchrotronGetOpticalDepth build_optical_depth_functor (); /** * Builds the functor to evolve the optical depth */ QuantumSynchrotronEvolveOpticalDepth build_evolve_functor (); /** * Builds the functor to generate photons */ QuantumSynchrotronPhotonEmission build_phot_em_functor (); /** * Checks if the optical tables are properly initialized */ bool are_lookup_tables_initialized () const; /** * Export lookup tables data into a raw binary Vector * * @return the data in binary format. The Vector is empty if tables were * not previously initialized. */ std::vector export_lookup_tables_data () const; /** * Init lookup tables from raw binary data. * * @param[in] raw_data a vector of char * @param[in] qs_minimum_chi_part minimum chi parameter to evolve the optical depth of a particle. * @return true if it succeeds, false if it cannot parse raw_data */ bool init_lookup_tables_from_raw_data (const std::vector& raw_data, const amrex::Real qs_minimum_chi_part); /** * Init lookup tables using built-in (low resolution) tables * * @param[in] qs_minimum_chi_part minimum chi parameter to evolve the optical depth of a particle. */ void init_builtin_tables(const amrex::Real qs_minimum_chi_part); /** * Computes the lookup tables. It does nothing unless WarpX is compiled with QED_TABLE_GEN=TRUE * * @param[in] ctrl control params to generate the tables * @param[in] qs_minimum_chi_part minimum chi parameter to evolve the optical depth of a particle. */ void compute_lookup_tables (PicsarQuantumSyncCtrl ctrl, const amrex::Real qs_minimum_chi_part); /** * gets default values for the control parameters * * @return default control params to generate the tables */ PicsarQuantumSyncCtrl get_default_ctrl() const; amrex::Real get_minimum_chi_part() const; private: bool m_lookup_tables_initialized = false; //Variables to store the minimum chi parameters to enable //Quantum Synchrotron process amrex::Real m_qs_minimum_chi_part; QS_dndt_table m_dndt_table; QS_phot_em_table m_phot_em_table; void init_builtin_dndt_table(); void init_builtin_phot_em_table(); }; //============================================ #endif //WARPX_quantum_sync_engine_wrapper_h_