aboutsummaryrefslogtreecommitdiff
path: root/Source/Particles/ElementaryProcess/QEDPairGeneration.H
blob: 062b78584995adbb15874480ea1d16cfb42be621 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* Copyright 2019 Luca Fedeli
 *
 * This file is part of WarpX.
 *
 * License: BSD-3-Clause-LBNL
 */

#ifndef QED_PAIR_GENERATION_H_
#define QED_PAIR_GENERATION_H_

#include "Utils/WarpXConst.H"
#include "Particles/WarpXParticleContainer.H"
#include "Particles/Gather/GetExternalFields.H"
#include "Particles/Gather/FieldGather.H"
#include "Particles/Pusher/GetAndSetPosition.H"
#include "QEDInternals/BreitWheelerEngineWrapper.H"

/** @file
 *
 * This file contains the implementation of the elementary process
 * functors needed for Breit-Wheeler pair generation (one photon generates
 * and electron-positron pair).
 */

/**
 * \brief Filter functor for the Breit Wheeler process
 */
class PairGenerationFilterFunc
{
public:

    /**
    * \brief Constructor of the PairGenerationFilterFunc functor.
    *
    * @param[in] opt_depth_runtime_comp index of the optical depth component
    */
    PairGenerationFilterFunc(int const opt_depth_runtime_comp)
        : m_opt_depth_runtime_comp(opt_depth_runtime_comp)
        {}

    /**
    * \brief Functor call. This method determines if a given (photon) particle
    * should undergo pair generation.
    *
    * @param[in] ptd particle tile data
    * @param[in] i particle index
    * @return true if a pair has to be generated, false otherwise
    */
    template <typename PData>
    AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
    bool operator() (const PData& ptd, int const i, amrex::RandomEngine const&) const noexcept
    {
        using namespace amrex;

        const amrex::ParticleReal opt_depth =
            ptd.m_runtime_rdata[m_opt_depth_runtime_comp][i];
        return (opt_depth < 0.0_rt);
    }

private:
    int m_opt_depth_runtime_comp = 0; /*!< Index of the optical depth component of the species.*/
};

/**
 * \brief Transform functor for the Breit-Wheeler process
 */
class PairGenerationTransformFunc
{
public:

    /**
    * \brief Constructor of the PairGenerationTransformFunc functor.
    *
    * A BreitWheelerGeneratePairs functor is passed by value. However, it contains
    * only few integer and real parameters and few pointers to the raw data of the
    * lookup tables. Therefore, it should be rather lightweight to copy.
    *
    * @param[in] generate_functor functor to be called to determine the properties of the generated pairs
    */
    PairGenerationTransformFunc(BreitWheelerGeneratePairs const generate_functor,
                                const WarpXParIter& a_pti, int lev, int ngE,
                                amrex::FArrayBox const& exfab,
                                amrex::FArrayBox const& eyfab,
                                amrex::FArrayBox const& ezfab,
                                amrex::FArrayBox const& bxfab,
                                amrex::FArrayBox const& byfab,
                                amrex::FArrayBox const& bzfab,
                                amrex::Array<amrex::Real,3> v_galilean,
                                int a_offset = 0);

    /**
    * \brief Functor call. It determines the properties of the generated pair
    * and it sets to -1 the id of the source photon
    *
    * @param[in,out] dst1 target species 1 (either electrons or positrons)
    * @param[in,out] dst2 target species 2 (either electrons or positrons)
    * @param[in] src source species (photons)
    * @param[in] i_src particle index of the source species
    * @param[in] i_dst1 particle index of target species 1
    * @param[in] i_dst2 particle index of target species 2
    * @param[in] engine random number generator engine
    */
    template <typename DstData, typename SrcData>
    AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
    void operator() (DstData& dst1, DstData& dst2, SrcData& src,
        int const i_src, int const i_dst1, int const i_dst2,
        amrex::RandomEngine const& engine) const noexcept
    {
        using namespace amrex;

        // gather E and B
        amrex::ParticleReal xp, yp, zp;
        m_get_position(i_src, xp, yp, zp);

        amrex::ParticleReal ex = 0._rt, ey = 0._rt, ez = 0._rt;
        m_get_externalE(i_src, ex, ey, ez);

        amrex::ParticleReal bx = 0._rt, by = 0._rt, bz = 0._rt;
        m_get_externalB(i_src, bx, by, bz);

        doGatherShapeN(xp, yp, zp, ex, ey, ez, bx, by, bz,
                       m_ex_arr, m_ey_arr, m_ez_arr, m_bx_arr, m_by_arr, m_bz_arr,
                       m_ex_type, m_ey_type, m_ez_type, m_bx_type, m_by_type, m_bz_type,
                       m_dx_arr, m_xyzmin_arr, m_lo, m_n_rz_azimuthal_modes,
                       m_nox, m_galerkin_interpolation);

        //Despite the names of the variables, positrons and electrons
        //can be exchanged, since the physical process is completely
        //symmetric with respect to this exchange.
        const auto& ux = src.m_rdata[PIdx::ux][i_src];
        const auto& uy = src.m_rdata[PIdx::uy][i_src];
        const auto& uz = src.m_rdata[PIdx::uz][i_src];
        auto& e_ux = dst1.m_rdata[PIdx::ux][i_dst1];
        auto& e_uy = dst1.m_rdata[PIdx::uy][i_dst1];
        auto& e_uz = dst1.m_rdata[PIdx::uz][i_dst1];
        auto& p_ux = dst2.m_rdata[PIdx::ux][i_dst2];
        auto& p_uy = dst2.m_rdata[PIdx::uy][i_dst2];
        auto& p_uz = dst2.m_rdata[PIdx::uz][i_dst2];
        m_generate_functor(
            ux, uy, uz,
            ex, ey, ez,
            bx, by, bz,
            e_ux, e_uy, e_uz,
            p_ux, p_uy, p_uz,
            engine);

        src.m_aos[i_src].id() = -1; //destroy photon after pair generation
    }

private:

    const BreitWheelerGeneratePairs
    m_generate_functor; /*!< A copy of the functor to generate pairs. It contains only pointers to the lookup tables.*/

    GetParticlePosition m_get_position;
    GetExternalEField m_get_externalE;
    GetExternalBField m_get_externalB;

    amrex::Array4<const amrex::Real> m_ex_arr;
    amrex::Array4<const amrex::Real> m_ey_arr;
    amrex::Array4<const amrex::Real> m_ez_arr;
    amrex::Array4<const amrex::Real> m_bx_arr;
    amrex::Array4<const amrex::Real> m_by_arr;
    amrex::Array4<const amrex::Real> m_bz_arr;

    amrex::IndexType m_ex_type;
    amrex::IndexType m_ey_type;
    amrex::IndexType m_ez_type;
    amrex::IndexType m_bx_type;
    amrex::IndexType m_by_type;
    amrex::IndexType m_bz_type;

    amrex::GpuArray<amrex::Real, 3> m_dx_arr;
    amrex::GpuArray<amrex::Real, 3> m_xyzmin_arr;

    bool m_galerkin_interpolation;
    int m_nox;
    int m_n_rz_azimuthal_modes;

    amrex::Dim3 m_lo;
};

#endif //QED_PAIR_GENERATION_H_