aboutsummaryrefslogtreecommitdiff
path: root/Source/Particles/ElementaryProcess/QEDInternals/BreitWheelerEngineWrapper.H
blob: 0598d0b34d97435bf6d5188f811b3278ee4f4feb (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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
/* Copyright 2019 Luca Fedeli
 *
 * This file is part of WarpX.
 *
 * License: BSD-3-Clause-LBNL
 */
#ifndef WARPX_breit_wheeler_engine_wrapper_h_
#define WARPX_breit_wheeler_engine_wrapper_h_

#include "QedWrapperCommons.H"
#include "QedChiFunctions.H"
#include "Utils/WarpXConst.H"

#include <AMReX_Array.H>
#include <AMReX_Vector.H>
#include <AMReX_Gpu.H>

#include <picsar_qed/physics/breit_wheeler/breit_wheeler_engine_tables.hpp>
#include <picsar_qed/physics/breit_wheeler/breit_wheeler_engine_core.hpp>

#include <string>
#include <vector>

// Aliases =============================
using BW_dndt_table_params =
    picsar::multi_physics::phys::breit_wheeler::
    dndt_lookup_table_params<amrex::Real>;

using BW_dndt_table =
    picsar::multi_physics::phys::breit_wheeler::
    dndt_lookup_table<
    amrex::Real,
    amrex::Gpu::DeviceVector<amrex::Real>>;

using BW_dndt_table_view = BW_dndt_table::view_type;

using BW_pair_prod_table_params =
    picsar::multi_physics::phys::breit_wheeler::
    pair_prod_lookup_table_params<amrex::Real>;

using BW_pair_prod_table =
    picsar::multi_physics::phys::breit_wheeler::
    pair_prod_lookup_table<
    amrex::Real,
    amrex::Gpu::DeviceVector<amrex::Real>>;

using BW_pair_prod_table_view = BW_pair_prod_table::view_type;

struct PicsarBreitWheelerCtrl
{
    BW_dndt_table_params dndt_params;
    BW_pair_prod_table_params pair_prod_params;
};

// Functors ==================================

// These functors allow using the core elementary functions of the library.
// They are generated by a factory class (BreitWheelerEngine, see below).
// They can be included in GPU kernels.

/**
 * Functor to initialize the optical depth of photons for the
 * Breit-Wheeler process
 */
class BreitWheelerGetOpticalDepth
{
public:
    /**
     * Constructor does nothing because optical depth initialization
     * does not require control parameters or lookup tables.
     */
    BreitWheelerGetOpticalDepth ()
    {}

    /**
     * () 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_bw = picsar::multi_physics::phys::breit_wheeler;

        //A random number in [0,1) should be provided as an argument.
        return pxr_bw::get_optical_depth(amrex::Random(engine));
    }
};
//____________________________________________

/**
 * Functor to evolve the optical depth of photons due to the
 * Breit-Wheeler process
 */
class BreitWheelerEvolveOpticalDepth
{
public:

    /**
     * Default constructor: it leaves the functor in a non-initialized state.
     */
    BreitWheelerEvolveOpticalDepth (){}


    /**
     * Constructor to be used to initialize the functor.
     *
     * @param[in] table_view a view of a BW_dndt_table lookup table
     * @param[in] bw_minimum_chi_phot the minimum quantum parameter to evolve the optical depth
     */
    BreitWheelerEvolveOpticalDepth (
        const BW_dndt_table_view table_view,
        const amrex::ParticleReal bw_minimum_chi_phot):
        m_table_view{table_view}, m_bw_minimum_chi_phot{bw_minimum_chi_phot}{}

    /**
     * Evolves the optical depth. It can be used on GPU.
     * If the  quantum parameter parameter of the photon is
     * < bw_minimum_chi_phot, the method returns immediately.
     * The method returns also if the energy of the photon is insufficient
     * to generate a pair.
     *
     * @param[in] ux,uy,uz gamma*v components of the photon.
     * @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 photon.
     * @return a flag which is 1 if chi_phot 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
    {
        namespace pxr_m = picsar::multi_physics::math;
        namespace pxr_p = picsar::multi_physics::phys;
        namespace pxr_bw = picsar::multi_physics::phys::breit_wheeler;

        constexpr amrex::Real m_e = PhysConst::m_e;
        const auto u_norm = std::sqrt(ux*ux + uy*uy + uz*uz);
        const auto energy = u_norm*m_e*PhysConst::c;

        const auto chi_phot = QedUtils::chi_photon(
            m_e*ux, m_e*uy, m_e*uz, ex, ey, ez, bx, by, bz);

        //Optical depth is not evolved for photons having less energy than what is
        //required to generate a pair or a quantum parameter smaller than
        //m_bw_minimum_chi_phot
        const auto gamma_photon = u_norm/PhysConst::c;
        if (gamma_photon < pxr_m::two<amrex::Real> ||
            chi_phot < m_bw_minimum_chi_phot)
            return 0;

        const auto is_out = pxr_bw::evolve_optical_depth<
            amrex::Real,
            BW_dndt_table_view,
            pxr_p::unit_system::SI>(
                energy, chi_phot, dt, opt_depth, m_table_view);

        return is_out;
    }

private:
    BW_dndt_table_view m_table_view;
    amrex::ParticleReal m_bw_minimum_chi_phot;
};

/**
 * Functor to generate a pair via the
 * Breit-Wheeler process
 */
class BreitWheelerGeneratePairs
{
public:

    /**
     * Default constructor: it leaves the functor in a non-initialized state.
     */
    BreitWheelerGeneratePairs (){}

    /**
     * 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 BW_pair_prod_table_view
     */
    BreitWheelerGeneratePairs (const BW_pair_prod_table_view table_view):
        m_table_view{table_view}{}

    /**
     * Generates pairs according to Breit Wheeler process.
     * It can be used on GPU.
     * Warning: the energy of the photon must be > 2mec^2, but it is not checked
     * in this method.
     *
     * @param[in] ux,uy,uz gamma*v components of the photon (SI units)
     * @param[in] ex,ey,ez electric field components (SI units)
     * @param[in] bx,by,bz magnetic field components (SI units)
     * @param[out] e_ux,e_uy,e_uz gamma*v components of generated electron (SI units)
     * @param[out] p_ux,p_uy,p_uz gamma*v components of generated positron (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
    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,
    amrex::Real& e_ux, amrex::Real& e_uy, amrex::Real& e_uz,
    amrex::Real& p_ux, amrex::Real& p_uy, amrex::Real& p_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_bw = picsar::multi_physics::phys::breit_wheeler;

        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_photon = QedUtils::chi_photon(
            px, py, pz, ex, ey, ez, bx, by, bz);

        const auto momentum_photon = pxr_m::vec3<amrex::Real>{px, py, pz};
        auto momentum_ele = pxr_m::vec3<amrex::Real>();
        auto momentum_pos = pxr_m::vec3<amrex::Real>();

        const auto is_out = pxr_bw::generate_breit_wheeler_pairs<
            amrex::Real,
            BW_pair_prod_table_view,
            pxr_p::unit_system::SI>(
                chi_photon, momentum_photon,
                rand_zero_one_minus_epsi,
                m_table_view,
                momentum_ele, momentum_pos);

        e_ux = momentum_ele[0]*one_over_me;
        e_uy = momentum_ele[1]*one_over_me;
        e_uz = momentum_ele[2]*one_over_me;
        p_ux = momentum_pos[0]*one_over_me;
        p_uy = momentum_pos[1]*one_over_me;
        p_uz = momentum_pos[2]*one_over_me;

        return is_out;
    }

private:
    BW_pair_prod_table_view m_table_view;
};

// Factory class =============================

/**
 * Wrapper for the Breit Wheeler engine of the PICSAR library
 */
class BreitWheelerEngine
{
public:
    /**
     * Constructor requires no arguments.
     */
    BreitWheelerEngine ();

    /**
     * Builds the functor to initialize the optical depth
     */
    BreitWheelerGetOpticalDepth build_optical_depth_functor () const;

    /**
     * Builds the functor to evolve the optical depth
     */
    BreitWheelerEvolveOpticalDepth build_evolve_functor () const;

    /**
     * Builds the functor to generate the pairs
     */
    BreitWheelerGeneratePairs build_pair_functor () const;

    /**
     * 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<char> export_lookup_tables_data () const;

    /**
     * Init lookup tables from raw binary data.
     *
     * @param[in] raw_data a vector of char
     * @param[in] bw_minimum_chi_phot minimum chi parameter to evolve the optical depth of a photon
     * @return true if it succeeds, false if it cannot parse raw_data
     */
    bool init_lookup_tables_from_raw_data (
        const std::vector<char>& raw_data,
        const amrex::Real bw_minimum_chi_phot);

    /**
     * Init lookup tables using built-in (low resolution) tables
     *
     * @param[in] bw_minimum_chi_phot minimum chi parameter to evolve the optical depth of a photon
     */
    void init_builtin_tables(const amrex::Real bw_minimum_chi_phot);

    /**
     * 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] bw_minimum_chi_phot minimum chi parameter to evolve the optical depth of a photon
     */
    void compute_lookup_tables (const PicsarBreitWheelerCtrl ctrl,
        const amrex::Real bw_minimum_chi_phot);

    /**
     * gets default values for the control parameters
     *
     * @return default control params to generate the tables
     */
    PicsarBreitWheelerCtrl get_default_ctrl() const;

    amrex::Real get_minimum_chi_phot() const;

private:
    bool m_lookup_tables_initialized = false;

    //Variables to store the minimum chi parameters to enable
    //Quantum Synchrotron process
    amrex::Real m_bw_minimum_chi_phot;

    BW_dndt_table m_dndt_table;
    BW_pair_prod_table m_pair_prod_table;

    void init_builtin_dndt_table();
    void init_builtin_pair_prod_table();


};

//============================================

#endif //WARPX_breit_wheeler_engine_wrapper_H_