Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-07-13 08:21:03

0001 #ifndef G4HepEmElectronData_HH
0002 #define G4HepEmElectronData_HH
0003 
0004 /**
0005  * @file    G4HepEmElectronData.hh
0006  * @struct  G4HepEmElectronData
0007  * @author  M. Novak
0008  * @date    2020
0009  *
0010  * @brief All energy loss process related data used for \f$e^-/e+\f$ simulations by `G4HepEm`.
0011  *
0012  * Energy loss processes are the *Ionisation* and *Bremsstrahlung* interactions
0013  * described by using the **condensed history** approach. It means, that *sub-threshold*
0014  * *interactions* are modelled as **continous energy losses** along the particle steps
0015  * while *super-threshold interactions*, i.e. **generation of secondary** \f$e^-/\gamma\f$
0016  * *particles* in case of ionisation/bremsstrahlung with intitial energy above the
0017  * secondary production threshold, are modelled explicitly as point like, **discrete**
0018  * **interactions**. This data structure contains all the data required to account these
0019  * interactions at run-time.
0020  *
0021  * The **continous energy loss** is characterised by the **restricted stopping power**, which
0022  * is the mean value of the energy losses due to the sub-threshold interactions
0023  * along a unit step lenght, and other related quantities such as the corresponding
0024  * **restricted range** or **restricted inverse range** values. The
0025  * *restricted* (ionisation - electronic)/(bremsstrahlung - radiative) *stopping power*
0026  * depend on the primary particle type, kinetic energy, target material and secondary
0027  * \f$e^-\f$(electronic)/\f$\gamma\f$(radiative) production threshold values. Therefore,
0028  * such tables are built separately \f$e^-\f$ and \f$e^+\f$, over a wide enough range of
0029  * primary particle kinetic energy (100 [eV] - 100 [TeV] by default) for all
0030  * material and secondary prodcution threshold pairs, or according to the Geant4 terminology,
0031  * for all material - cuts couples. The tables contain the *sum of the electronic and radiative*
0032  * contributions. These tables, stored in this data structure,
0033  * are **used to determine the continous** part of the **step limit** and **to compute the**
0034  * sub-threshold realted, **continous energy losses** at each step done by \f$e^-/e^+\f$.
0035  *
0036  * The rate of the **dicrete** super-threshold ionisation and bremsstrahlung
0037  * interactions are characterised by the corresponding **restricted macroscopic cross sections**.
0038  * These also depend on the primary particle type, kinetic energy, target material -cuts
0039  * couple. Moreover, the minimum value of the kinetic energy grid is determined by the
0040  * secondary \f$e^-\f$(ionisation)\f$/\gamma\f$(bremsstrahlung) production energy thresholds
0041  * that (since Geant4 rquires the user to specify these in lenght) is diffrent in case of
0042  * each material-cuts couple whenever wither the material or the cut value (in length)
0043  * is different. Therefore, these *restricted macroscopic cross sction* tables are
0044  * *built* separately for \f$e^-/e^+\f$ primary particles, separately for *ionisation*
0045  * and *bremsstrahlung* for all different material - cuts couples with individual
0046  * kinetic energy grids. These tables are **used to determine the discrete** part of the
0047  * **step limit**, i.e. the length that the primary \f$e^-/e^+\f$ travels till the next
0048  * ionisation/bremsstrahlung interaction in the given material - cuts couple,
0049  * resulting in secondary \f$e^-/\gamma\f$ particle production with initial energy
0050  * above the secondary \f$e^-/\gamma\f$ production cut in the given material - cuts
0051  * couple.
0052  *
0053  * The *macroscopic cross section* determines the (mean) path length, the primary
0054  * particles travels, till the next *discrete* interaction in the given *material*
0055  * (actually material - cuts couple in case of ioni. and brem. since we use the
0056  * condensed history approach).
0057  * The *discrete* bremsstrahlung interaction takes place in the vicinity of one
0058  * of the *elements of the material*. A so-called **target atom selector** is
0059  * constructed for each model (also for ionisation though its not used), based
0060  * on the partial contribution of the individual elements of a given
0061  * material - cuts to the corresponding macroscopic cross section. These data
0062  * are **used to select the target atom for discrete interaction** at run-time.
0063  *
0064  *
0065  *
0066  * @note
0067  * Other interactions, beyond ionisation and bremsstrahlung, are also active
0068  * in case of \f$e^-/e^+\f$ like Coulomb scattering or annihilation into two
0069  * \f$\gamma\f$-s in case of \f$e^+\f$. However, their descriptions are rather
0070  * different compared to these two energy loss processes:
0071  *    - Coulomb scattering is described by a so-called *multiple scattering model*
0072  *    - while \f$e^+\f$ annihilation is a discrete process, so similar to the discrete
0073  *      ionisation and bremsstrahlung interactions, the corresponding cross section
0074  *      doesn't depend neither the secondary production thresholds nor the element
0075  *      composition (directly). Unlike ionisation or even more bremsstrahlung, the
0076  *      cross section for annihilation can be easily computed on-the-fly so there
0077  *      is no need to pre-compute and store values in tables.
0078  *
0079  */
0080 
0081 struct G4HepEmElectronData {
0082   /** Number of G4HepEm material - cuts: number of G4HepEmMCCData structures stored in the G4HepEmMatCutData::fMatCutData array. */
0083   int        fNumMatCuts   = 0;
0084   /** Number of G4HepEm material : number of G4HepEmMatData structures stored in the G4HepEmMaterialData::fMaterialData array. */
0085   int        fNumMaterials = 0;
0086 
0087 
0088 //// === ENERGY LOSS DATA
0089   /**
0090    * @name Energy loss related data members:
0091    * These members are used to store all continuous energy loss related data (there
0092    * is a single primary kinetic energy grid for all material - cuts equally spaced
0093    * in log-scale).
0094    */
0095 ///@{
0096   /** Number of discrete kinetic energy values in the grid (\f$N\f$). */
0097   int        fELossEnergyGridSize = 0;
0098   /** Logarithm of the minimum kinetic energy value of the grid (\f$\ln(E_0)\f$)*/
0099   double     fELossLogMinEkin = 0.0;     // log of the E_0
0100   /** Inverse of the log-scale delta value (\f$ 1/[log(E_{N-1}/E_0)/(N-1)]\f$). */
0101   double     fELossEILDelta = 0.0;
0102   /** The grid of the discrete kinetic energy values (\f$E_0, E_1,\ldots, E_{N-1}\f$).*/
0103   double*    fELossEnergyGrid = nullptr; // [fELossEnergyGridSize]
0104   /** The energy loss data: **restricted dE/dx, range and inverse range** data.
0105     *
0106     * The restricted dE/dx, range (and corresponding inverse range) data values,
0107     * over the above kinetic energy grid for all material - cuts couples, are
0108     * stored continuously in this G4HepEmElectronData::fELossData single array.
0109     * The second derivative values, required for the run-time spline interpolation,
0110     * are also stored together with the data.
0111     *
0112     * The data are stored in the following format for each of the G4HepEmMCCData material - cuts couples,
0113     * stored in the G4HepEmMatCutData::fMatCutData array:
0114     *   - for each material - cuts couple, there are \f$N := \f$ G4HepEmElectronData::fELossEnergyGridSize **range** values associated to the primary
0115     *     \f$e^-/e^+\f$ kinetic energy values stored in G4HepEmElectronData::fELossEnergyGrid. These
0116     *     \f$R_i, i=0,\ldots,N-1\f$ **range values are stored**
0117     *     with the corresponding \f$R_i^{''}, i=0,\ldots,N-1\f$
0118     *     **second derivatives** in the form of \f$R_0,R_0^{''},R_{1},R_{1}^{''},\ldots,R_{N-1},R_{N-1}^{''}\f$
0119     *     in order **to resonate the best with the run-time access pattern**.
0120     *   - **then the corresponding** \f$N\f$, \f$dE/dx\f$ **values are stored** in
0121     *     a similar way  \f$dE/dx_0,dE/dx_0^{''},dE/dx_{1},dE/dx_{1}^{''},\ldots,dE/dx_{N-1},dE/dx_{N-1}^{''}\f$
0122     *   - since both the range, and the kinetic energy values
0123     *     are already stored (see above), **only** the corresponding \f$N\f$
0124     *     **second derivative values associated to the inverse range are stored then** as
0125     *     \f$S_0,S_1,\ldots,S_{N-1}\f$
0126     *   - it means, that **there are** \f$5\times N\f$ **energy loss realted data values stored continuously in
0127     *     the** G4HepEmElectronData::fELossData **array for each material - cuts couples**. Therefore, in the case
0128     *     of a G4HepEmMCCData material - cuts couple data with the index of \f$\texttt{imc}\f$ (i.e. in the case of
0129     *     the G4HepEmMCCData, stored at G4HepEmMatCutData::fMatCutData[\f$\texttt{imc}\f$]), the start indices of
0130     *     the corresponding energy loss related data in the G4HepEmElectronData::fELossData array:
0131     *     - **range data** starts at the index of \f$\texttt{imc}\times(5\times N\f$)
0132     *     - **dE/dx data** starts at the index of \f$\texttt{imc}\times(5\times N\f$) + \f$2\times N\f$
0133     *     - **inverse range data** starts at the index of \f$\texttt{imc}\times(5\times N\f$) + \f$4\times N\f$
0134     *
0135     * The total number of data stored in the G4HepEmElectronData::fELossData array is
0136     * G4HepEmElectronData::fNumMatCuts\f$\times5\times\f$G4HepEmElectronData::fELossEnergyGridSize
0137     *
0138     * At run-time, for a given \f$E\f$ primary kinetic energy G4HepEmElectronData::fELossLogMinEkin
0139     * and G4HepEmElectronData::fELossEILDelta are used to compute the energy bin index \f$i\f$ such that
0140     * \f$ E_i \leq E < E_{i+1}, i=0,\ldots,N-1\f$. Then for the given material - cuts couple index,
0141     * the above starts indices can be used to access the corresponding energy loss data and second derivatives
0142     * associated to the primary kinetic energies of \f$ E_i, E_{i+1}\f$ needed to perform the spline interpolation.
0143     *
0144     *
0145     * @note
0146     * There is a spline interpolation function in G4HepEmRunUtils, specialised
0147     * for the above pattern used to store the dE/dx and range data. Using this
0148     * function **ensures optimal** data **cache utilisation at run-time**.
0149     * A separate, more traditional spline interpolation function is used for
0150     * run-time inverse range data interpolation. These are utilised in the
0151     * G4HepEmElectronManager to ensure the optimal run-time performance (both in
0152     * terms of memory consumption and speed) when accessing the restricted energy loss
0153     * related, i.e. stopping power, range and inverse range data in the \f$e^-/e^+\f$ stepping.
0154     */
0155   double*    fELossData = nullptr; // [5xfELossEnergyGridSize x fNumMatCuts]
0156 /// @} */ // end: eloss
0157   //
0158 
0159 //// === MACROSCOPIC CROSS SECTION DATA
0160   /**
0161    * @name Restricted macroscopic cross section related data members:
0162    * These members are used to store all restricted macroscopic cross section related data both for
0163    * **ionisation** and **bremsstrahlung** for all material - cuts couples.
0164    */
0165 ///@{
0166   /** Total number of restricted macroscopic cross sections realted data stored in the single G4HepEmElectronData::fResMacXSecData array.*/
0167   int        fResMacXSecNumData = 0;
0168   /** Start index of the macroscopic cross section data, for the material - cuts couple with the given index, in the G4HepEmElectronData::fResMacXSecData array.*/
0169   int*       fResMacXSecStartIndexPerMatCut = nullptr;  // [fNumMatCuts]
0170   /** The restricted macroscopic cross section data for **ionisation** and **bremsstrahlung** for all material - cuts couples.
0171    *
0172    * All the restricted macroscopic cross section data are stored continuously in this G4HepEmElectronData::fResMacXSecData single array.
0173    * The *restricted macroscopic cross sections* go to *zero at primary kinetic energies lower than or equal to the secondary
0174    * production threshold*: at the secondary \f$e^-\f$ production threshold in the case of \f$e^+\f$ and \f$2\times\f$ of it in the case
0175    * of \f$e^-\f$ ionisation, while the secondary \f$\gamma\f$ production threshold energy in case of bremsstrahlung. It means that,
0176    * the minimum value of *the primary kinetic energy grid depends on the type of the interaction* (ioni. or brem.) as well as
0177    * *the production cut values*. Therefore, an individual primary kinetic energy grid is generated, and stored together with the
0178    * corresponding restricted macroscopic cross section values, for each individual material - cuts couples, separately for
0179    * ionisation and for bremsstrahlung in each cases.
0180    *
0181    * The data are stored in the following format for each of the G4HepEmMCCData material - cuts couples (stored in the
0182    * G4HepEmMatCutData::fMatCutData array):
0183    *   - for a G4HepEmMCCData material - cuts couple data with the index of \f$\texttt{imc}\f$ (i.e.
0184    *     stored at G4HepEmMatCutData::fMatCutData[\f$\texttt{imc}\f$]), the macroscopic scross section realted
0185    *     data starts at G4HepEmElectronData::fResMacXSecData[\f$\texttt{ioniStarts}\f$], where \f$\texttt{ioniStarts}=\f$G4HepEmElectronData::fResMacXSecStartIndexPerMatCut [\f$\texttt{imc}\f$]
0186    *   - then relative to this \f$\texttt{ioniStarts}\f$ start index, **first** the restricted macroscopic cross section data for **ionisation**:
0187    *       - ``[0]``: \f$M:=M^{\text{(ioni)}\texttt{-imc}}\f$: **number of** \f$E_i, i=0,\ldots,M-1\f$ **primary kinetic energy points** over
0188    *         which the \f$\Sigma:=\Sigma^{\text{(ioni)}\texttt{-imc}}(E_i)\f$ restricted macroscopic cross section **for ionisation**
0189    *         is computed and stored **for this material - cuts couple** with the index of \f$\texttt{imc}\f$.
0190    *       - ``[1]``: \f$\texttt{argmax}\{\Sigma(E_i)\}, i=0,\ldots,M-1\f$
0191    *       - ``[2]``: \f$\texttt{max}\{\Sigma(E_i)\}, i=0,\ldots,M-1\f$
0192    *       - ``[3]``: \f$\log(E_0)\f$
0193    *       - ``[4]``: \f$1/[log(E_{M-1}/E_0)/(M-1)]\f$
0194    *       - ``[5 : 5 + 3xM-1]``: \f$E_0,\Sigma(E_0),\Sigma(E_0)^{''},E_1,\Sigma(E_1),\Sigma(E_1)^{''},\ldots,E_{M-1},\Sigma(E_{M-1}), \Sigma(E_{M-1})^{''}\f$
0195    *         where \f$^{''}\f$ denotes the second derivatives.
0196    *   - then continuously from the \f$\texttt{bremStarts} = \texttt{ioniStarts} + 3\times M+5 \f$ index,
0197    *     the restricted macroscopic cross section data for **bremsstrahlung**:
0198    *       - ``[0]``: \f$N:=N^{\text{(brem)}\texttt{-imc}}\f$: **number of** \f$E_i, i=0,\ldots,N-1\f$ **primary kinetic energy points** over
0199    *         which the \f$\Sigma:=\Sigma^{\text{(brem)}\texttt{-imc}}(E_i)\f$ restricted macroscopic cross section **for bremsstrahlung**
0200    *         is computed and stored **for this material - cuts couple** with the index of \f$\texttt{imc}\f$.
0201    *       - ``[1]``: \f$\texttt{argmax}\{\Sigma(E_i)\}, i=0,\ldots,N-1\f$
0202    *       - ``[2]``: \f$\texttt{max}\{\Sigma(E_i)\}, i=0,\ldots,N-1\f$
0203    *       - ``[3]``: \f$\log(E_0)\f$
0204    *       - ``[4]``: \f$1/[log(E_{N-1}/E_0)/(N-1)]\f$
0205    *       - ``[5 : 5 + 3xN-1]``: \f$E_0,\Sigma(E_0),\Sigma(E_0)^{''},E_1,\Sigma(E_1),\Sigma(E_1)^{''},\ldots,E_{N-1},\Sigma(E_{N-1}), \Sigma(E_{N-1})^{''}\f$
0206    *         where \f$^{''}\f$ denotes again the second derivatives.
0207    *
0208    * The total number of data, i.e. the length of the G4HepEmElectronData::fResMacXSecData array,
0209    * is stored in G4HepEmElectronData::fResMacXSecData.
0210    *
0211    * At run-time, for a given \f$E\f$ primary kinetic energy and material - cuts couple with the index of \f$\texttt{imc}\f$,
0212    *  - the start index of the **macroscopic cross section data for ionisation** is given by
0213    *    \f$\texttt{ioniStarts}\f$=G4HepEmElectronData::fResMacXSecStartIndexPerMatCut[\f$\texttt{imc}\f$]
0214    *  - then G4HepEmElectronData::fResMacXSecData[\f$\texttt{ioniStarts}\f$+3] and
0215    *    G4HepEmElectronData::fResMacXSecData[\f$\texttt{ioniStarts}\f$+4] can be used to compute the
0216    *    kinetic energy bin index \f$i\f$ such that \f$ E_i \leq E < E_{i+1}, i=0,\ldots,\f$G4HepEmElectronData::fResMacXSecData[\f$\texttt{ioniStarts}\f$]\f$-1\f$.
0217    *  - then the kinetic energies, macroscopic cross sections and their second derivatives,
0218    *    associated to the primary kinetic energies of \f$ E_i, E_{i+1}\f$ are used to perform the spline interpolation
0219    *  - the start index of the corresponding **macroscopic cross section data for bremsstrahlung** is given by
0220    *    \f$\texttt{bremStarts} = \texttt{ioniStarts} + 5 + 3\times\f$G4HepEmElectronData::fResMacXSecData[\f$\texttt{ioniStarts}\f$]
0221    *  - then the same procedure can be applied as above to compute the kinetic energy bin index and perform the interpolation,
0222    *    but now relative to \f$\texttt{bremStarts}\f$ instead of the above \f$\texttt{ioniStarts}\f$
0223    *
0224    * @note
0225    * Note, that all the 6 data, that are needed for the run-time interpolation of the restricted macroscopic scross sections
0226    * are stored next to each other in the memory for both interactions (ionisation and bremsstrahlung). Moreover, for a given
0227    * material - cuts couple, the data for the two interactions are stored one after the other. Together with the corresponding
0228    * special spline interpolation function of G4HepEmRunUtils, that ensures a maximal profit of this memory layout, it makes
0229    * **optimal utilisation of the** data **cache at run-time**. This special spline interpolation is utilised in the
0230    * G4HepEmElectronManager to ensure the optimal run-time performance (both in terms of memory consumption and speed) when
0231    * accessing the restricted macroscopic cross section data in the \f$e^-/e^+\f$ stepping.
0232    *
0233    */
0234   double*    fResMacXSecData = nullptr; // [fResMacXSecNumData]
0235 /// @} */ // end: restricted macroscopic cross section
0236 
0237   //
0238   // Electron - and positron - nuclear cross sections per material:
0239   // --- Grid: 127 bins form 100 MeV - 100 TeV
0240   const int     fENucEnergyGridSize = 128;
0241   double        fENucLogMinEkin = 0.0;    // = 4.605170185988092;  // log(100.0)
0242   double        fENucEILDelta = 0.0;      // = 9.192566533618830;  // 1./[log(emax/emin)/127]
0243   double*       fENucEnergyGrid = nullptr;    // [fENucEnergyGrid]
0244 
0245   double*       fENucMacXsecData = nullptr;   // [#materials*2*fENucEnergyGridSize]
0246 
0247 
0248   /**
0249    * @name Macroscopic first transport corss section related data members:
0250    * These members are used to store all macroscopic first transport cross section related data
0251    * for all materials. The discrete energy grid, above which that disceret cross section
0252    * values are computed and stored, is the same as used for the energy loss data.
0253    */
0254 ///@{
0255   /** The macroscopic first transport cross section.
0256    *
0257    * The data are stored in the following format for each of the G4HepEmMatData material
0258    * (stored in the G4HepEmMaterialData::fMaterialData array):
0259    *   - there are \f$N := \f$ G4HepEmElectronData::fELossEnergyGridSize **(macroscopic) first transport cross section
0260    *     values** associated to the primary \f$e^-/e^+\f$ kinetic energy values stored
0261    *     in G4HepEmElectronData::fELossEnergyGrid. These \f$TR1_i, i=0,\ldots,N-1\f$ **values** are stored
0262    *     with the corresponding \f$TR1_i^{''}, i=0,\ldots,N-1\f$
0263    *     **second derivatives** in the form of \f$TR1_0,TR1_0^{''},TR1_{1},TR1_{1}^{''},\ldots,TR1_{N-1},TR1_{N-1}^{''}\f$
0264    *     in order **to resonate the best with the run-time access pattern**.
0265    *   - for a G4HepEmMatData material data with the index of \f$\texttt{im}\f$ (i.e.
0266    *     stored at G4HepEmMaterialData::fMaterialData[\f$\texttt{im}\f$]), the macroscopic first
0267    *     transport cross section realted data starts at \f$\texttt{iStart} = 2\times\f$G4HepEmElectronData::fELossEnergyGridSize\f$\times\texttt{im}\f$
0268    *     in the G4HepEmElectronData::fTr1MacXSecData array
0269    *   - the total number of data in the array is \f$2\times\f$G4HepEmElectronData::fELossEnergyGridSize\f$\times\f$G4HepEmElectronData::fNumMaterials
0270    *
0271    * @note
0272    * There is a spline interpolation function in G4HepEmRunUtils, specialised
0273    * for the above pattern used to store the dE/dx and range data. Using this
0274    * function **ensures optimal** data **cache utilisation at run-time**.
0275    */
0276   double*    fTr1MacXSecData = nullptr; // [2xfELossEnergyGridSize x fNumMaterials]
0277 /// @} */ // end: macroscopic first transport cross section
0278 
0279 
0280 //// === TARGET ELEMENT SELECTOR
0281   /**
0282    * @name Target element selector related data members:
0283    * These members store data utilised at run-time for the selection of the target
0284    * elements (in case of multi element atoms) on which the interaction takes palce.
0285    * Data are stored for all the interaction models used to describe both **ionisation** and
0286    * **bremsstrahlung** and for all material - cuts couples.
0287    *
0288    * These data are the normalised, element-wise contributions to the corresonding
0289    * macroscopic cross sections in case of multi element materials. Therefore,
0290    * similarly to the above restricted macroscopic cross sections, different energy
0291    * grids are generated for the the different material - cuts couples. The data
0292    * are also stored in a separate, single continuous array per interaction model.
0293    * The total number of data, i.e. the size of this single array as well as the start indices
0294    * of the data, related to the different material - cuts couples, are stored for each
0295    * of the three interaction models.
0296    *
0297    * The data are stored in the following format for each of the individual interaction models,
0298    * for each the G4HepEmMCCData material - cuts couples (stored in the G4HepEmMatCutData::fMatCutData array):
0299    *   - for a G4HepEmMCCData material - cuts couple data with the index of \f$\texttt{imc}\f$ (i.e.
0300    *     stored at G4HepEmMatCutData::fMatCutData[\f$\texttt{imc}\f$]), the element selector
0301    *     data starts at the index \f$\texttt{iStarts}=\texttt{fElemSelectorXYStartIndexPerMatCut[imc]}\f$ where
0302    *     \f$XY\f$ is one of the three models, i.e. \f$\{\texttt{Ioni, BremSB, BremRB}\}\f$ for the
0303    *     *Moller-Bhabha ionisation*, *Seltzer-Berger* or the *relativistic bremsstrahlung models*.
0304    *   - if the material, associated to this material - cuts couple, is composed of a single element,
0305    *     \f$\texttt{iStarts}=-1\f$
0306    *   - the following data are stored otherwise continuously in the appropriate \f$\texttt{fElemSelectorXYData}\f$
0307    *     array relative to this \f$\texttt{iStarts}\f$ index
0308    *       - ``[0]``: \f$K:=\f$ *number of discrte* \f$E_i, i=0,\ldots,K-1\f$ *primary particle kinetic energy values* used to compute and store
0309    *           the \f$P(Z_j,E_i):=\Sigma^{Z_j}(E_i)/\Sigma(E_i)\f$ normalised, element-wise contributions to the macroscopic cross section of the material.
0310    *       - ``[1]``: \f$Q:=\f$ *number of elements the given material is composed of*. So above, \f$Z_j, j=0,\ldots,Q-1\f$ at each individual
0311    *           \f$E_i\f$ kinetic energy values. However, since \f$P(Z_{j=Q-1},E_i)=\Sigma^{Z_{Q-1}}(E_i)/\Sigma(E_i) = 1\f$ for all \f$i=0,\ldots,K-1\f$
0312    *           due to the normalisation, data are computed and stored only for element indices of \f$j=0,\ldots,Q-2\f$.
0313    *       - ``[2]``: \f$\log(E_0)\f$
0314    *       - ``[3]``: \f$1/[log(E_{K-1}/E_0)/(K-1)]\f$
0315    *       - ``[4 : 4 + QxK-1]``: \f$E_0,P(j=0,E_0),P(j=1,E_0),\ldots,P(j=Q-2,E_0), \ldots,\f$ \f$E_{K-1},P(j=0,E_{K-1}),P(j=1,E_{K-1}),\ldots,P(j=Q-2,E_{K-1})\f$
0316    *
0317    * At run-time, when performing an interaction described by model \f$XY \in \{\texttt{Ioni, BremSB, BremRB}\}\f$,
0318    * with primary particle kinetic energy of \f$E\f$ in the material, related to the material - cuts couple with the index of \f$\texttt{imc}\f$,
0319    *  - the **start index of the** corresponding element selector **data** is \f$\texttt{iStarts}=\texttt{fElemSelectorXYStartIndexPerMatCut[imc]}\f$
0320    *  - the the corresonding \f$\texttt{fElemSelectorXYData[iStart+2]}\f$ and \f$\texttt{fElemSelectorXYData[iStart+3]}\f$ values can be used to compute the
0321    *    kinetic energy bin index \f$i\f$ such that \f$ E_i \leq E < E_{i+1}, i=0,\ldots,\texttt{fElemSelectorXYData[iStart]}-1\f$.
0322    *  - then the kinetic energies and normalised element-wise partial macroscopic cross sections,
0323    *    associated to the primary kinetic energies of \f$ E_i, E_{i+1}\f$ are used to perform the linear interpolation (smooth function) and
0324    *    and to sample the target element index from this discrete distribution.
0325    *
0326    * @note
0327    * Note, that all the data, that are needed for the run-time interpolation and for the target element index sampling are stored next to each other in the memory.
0328    * The implementations of the individual interaction models, that utilise these data for the run-time target atom selection (if needed), make sure that this
0329    * memory layout is maximally exploited. These ensure the optimal performance, both in terms of memory consumption and speed, when
0330    * accessing these data performing the correspondign \f$e^-/e^+\f$ interactions.
0331    */
0332 ///@{
0333   /** Total number of element selector data for the Moller-Bhabha model for e-/e+ ionisation.*/
0334   int       fElemSelectorIoniNumData = 0;
0335   /** Indices, at which data starts for a given material - cuts couple.*/
0336   int*      fElemSelectorIoniStartIndexPerMatCut = nullptr;     // [fNumMatCuts]
0337   /** Element selector data for all material - cuts couples with multiple element material.*/
0338   double*   fElemSelectorIoniData = nullptr;                    // [fElemSelectorIoniNumData]
0339 
0340   /** Total number of element selector data for the Seltzer-Berger model for e-/e+ bremsstrahlung.*/
0341   int       fElemSelectorBremSBNumData = 0;
0342   /** Indices, at which data starts for a given material - cuts couple.*/
0343   int*      fElemSelectorBremSBStartIndexPerMatCut = nullptr;   // [fNumMatCuts]
0344   /** Element selector data for all material - cuts couples with multiple element material.*/
0345   double*   fElemSelectorBremSBData = nullptr;                  // [fElemSelectorBremSBNumData]
0346 
0347   /** Total number of element selector data for the relativistic (improved Bethe-Heitler) model for e-/e+ bremsstrahlung.*/
0348   int       fElemSelectorBremRBNumData = 0;
0349   /** Indices, at which data starts for a given material - cuts couple.*/
0350   int*      fElemSelectorBremRBStartIndexPerMatCut = nullptr;   // [fNumMatCuts]
0351   /** Element selector data for all material - cuts couples with multiple element material.*/
0352   double*   fElemSelectorBremRBData = nullptr;                  // [fElemSelectorBremRBNumData]
0353 /// @} */ // end: target element selectors
0354 };
0355 
0356 
0357 /**
0358   * Allocates and pre-initialises the G4HepEmElectronData structure.
0359   *
0360   * This method is invoked from the InitElectronData() function declared
0361   * in the G4HepEmElectronInit header file. The input argument address of the
0362   * G4HepEmElectronData structure pointer is the one stored in the G4HepEmData
0363   * member of the `master` G4HepEmRunManager and the initialisation should be
0364   * done by the master G4HepEmRunManager by invoking the InitElectronData() function
0365   * for \f$e^-/e^+\f$ particles.
0366   *
0367   * @param theElectronData address of a G4HepEmElectronData structure pointer. At termination,
0368   *   the correspondig pointer will be set to a memory location with a freshly allocated
0369   *   G4HepEmElectronData structure with all its pointer members set to nullprt.
0370   *   If the input pointer was not null at input, the pointed memory, including all
0371   *   dynamic memory members, is freed before the new allocation.
0372   */
0373 void AllocateElectronData (struct G4HepEmElectronData** theElectronData);
0374 
0375 /**
0376  * Initializes a new @ref G4HepEmElectronData structure
0377  *
0378  * This function default constructs an instance of G4HepEmElectronData and returns
0379  * a pointer to the freshly constructed instance. It is the callees responsibility
0380  * to free the instance using @ref FreeElectronData.
0381  *
0382  * @return Pointer to instance of @ref G4HepEmElectronData
0383  */
0384 G4HepEmElectronData* MakeElectronData();
0385 
0386 /**
0387   * Frees a G4HepEmElectronData structure.
0388   *
0389   * This function deallocates all dynamically allocated memory stored in the
0390   * input argument related G4HepEmElectronData structure, deallocates the structure
0391   * itself and sets the input address to store a pointer to null. This makes the
0392   * corresponding input stucture cleared, freed and ready to be re-initialised.
0393   * The input argument is supposed to be the address of the corresponding pointer
0394   * member of the G4HepEmData member of the `master` G4HepEmRunManager.
0395   *
0396   * @param theElectronData memory address that stores pointer to a G4HepEmElectronData
0397   *  structure. The memory is freed and the input address will store a null pointer
0398   *  at termination.
0399   */
0400 void FreeElectronData (struct G4HepEmElectronData** theElectronData);
0401 
0402 
0403 #ifdef G4HepEm_CUDA_BUILD
0404   /**
0405     * Allocates memory for and copies the G4HepEmElectronData structure from the
0406     * host to the device.
0407     *
0408     * The input arguments are supposed to be the corresponding members of the
0409     * G4HepEmData, top level data structure, stored in the `master` G4HepEmRunManager.
0410     *
0411     * @param onHOST    pointer to the host side, already initialised G4HepEmElectronData structure.
0412     * @param onDEVICE  host side address of a pointer to a device side G4HepEmElectronData
0413     *   structure. The pointed device side memory is cleaned (if not null at input) and
0414     *   points to the device side memory at termination containing all the copied
0415     *   G4HepEmElectronData structure members.
0416     */
0417   void CopyElectronDataToDevice(struct G4HepEmElectronData* onHOST, struct G4HepEmElectronData** onDEVICE);
0418 
0419   /**
0420     * Frees all memory related to the device side G4HepEmElectronData structure referred
0421     * by the pointer stored on the host side input argument address.
0422     *
0423     * @param onDEVICE host side address of a G4HepEmElectronDataOnDevice structure located on the device side memory.
0424     *   The correspondig device memory will be freed and the input argument address will be set to null.
0425     */
0426   void FreeElectronDataOnDevice(struct G4HepEmElectronData** onDEVICE);
0427 #endif // DG4HepEm_CUDA_BUILD
0428 
0429 #endif // G4HepEmElementData_HH