LCOV - code coverage report
Current view: top level - src/module - EMDoublePairProduction.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 80.5 % 77 62
Test Date: 2026-07-13 06:03:10 Functions: 73.3 % 15 11

            Line data    Source code
       1              : #include "crpropa/module/EMDoublePairProduction.h"
       2              : #include "crpropa/Units.h"
       3              : #include "crpropa/Random.h"
       4              : #include "crpropa/Common.h"
       5              : 
       6              : #include <vector>
       7              : #include <cmath>
       8              : 
       9              : namespace crpropa {
      10              : 
      11            3 : EMDoublePairProduction::EMDoublePairProduction(ref_ptr<PhotonField> photonField, bool haveElectrons, double thinning, double limit, ref_ptr<Surface> surface) {
      12            6 :         setSurface(surface);
      13            3 :         setPhotonField(photonField);
      14            3 :         setHaveElectrons(haveElectrons);
      15            3 :         setLimit(limit);
      16            3 :         setThinning(thinning);
      17            3 : }
      18              : 
      19           15 : void EMDoublePairProduction::setPhotonField(ref_ptr<PhotonField> photonField) {
      20              :         
      21           15 :         this->photonField = photonField;
      22           15 :         std::string fname = photonField->getFieldName();
      23           30 :         setDescription("EMDoublePairProduction: " + fname);
      24              :         
      25              :         // choose the right interaction rates for the used photon field
      26           15 :         if (!this->photonField->hasPositionDependence()) {
      27              :                 this->interactionRates = new InteractionRatesHomogeneous(
      28           45 :                         getDataPath("EMDoublePairProduction/rate_" + fname + ".txt")
      29           45 :                 );
      30              :         } else {
      31              :                 this->interactionRates = new InteractionRatesPositionDependent(
      32            0 :                         getDataPath("EMDoublePairProduction/"+fname+"/Rate/"),
      33              :                         "",
      34              :                         this->surface
      35            0 :                 );
      36              :         }
      37           15 : }
      38              : 
      39            4 : void EMDoublePairProduction::setHaveElectrons(bool haveElectrons) {
      40            4 :         this->haveElectrons = haveElectrons;
      41            4 : }
      42              : 
      43            3 : void EMDoublePairProduction::setLimit(double limit) {
      44            3 :         this->limit = limit;
      45            3 : }
      46              : 
      47            3 : void EMDoublePairProduction::setThinning(double thinning) {
      48            3 :         this->thinning = thinning;
      49            3 : }
      50              : 
      51            3 : void EMDoublePairProduction::setSurface(ref_ptr<Surface> surface) {
      52            3 :         this->surface = surface;
      53            3 : }
      54              : 
      55            0 : ref_ptr<Surface> EMDoublePairProduction::getSurface() const {
      56            0 :         return this->surface;
      57              : }
      58              : 
      59            0 : void EMDoublePairProduction::setInteractionRates(ref_ptr<InteractionRates> intRates) {
      60            0 :         this->interactionRates = intRates;
      61            0 : }
      62              : 
      63            0 : ref_ptr<InteractionRates> EMDoublePairProduction::getInteractionRates() const {
      64            0 :         return this->interactionRates;
      65              : }
      66              : 
      67            0 : void EMDoublePairProduction::initRate(std::string path) {
      68            0 :         this->interactionRates->initRate(path);
      69            0 : }
      70              : 
      71            1 : double EMDoublePairProduction::getRate(double E, const Vector3d &position, double z) const {
      72            1 :         return this->interactionRates->getProcessRate(E, position) * pow_integer<2>(1 + z) * photonField->getRedshiftScaling(z);
      73              : }
      74              : 
      75            1 : void EMDoublePairProduction::performInteraction(Candidate *candidate) const {
      76              : 
      77              :         // Use assumption of Lee 96 arXiv:9604098
      78              :         // Energy is equally shared between one e+e- pair, but take mass of second e+e- pair into account.
      79              :         // This approximation has been shown to be valid within -1.5%.
      80            1 :         double z = candidate->getRedshift();
      81            1 :         double E = candidate->current.getEnergy() * (1 + z);
      82            1 :         double Ee = (E - 2 * mass_electron * c_squared) / 2;
      83              : 
      84              :         // the photon is lost after the interaction
      85            1 :         candidate->setActive(false);
      86              : 
      87            1 :         if (not haveElectrons)
      88            0 :                 return;
      89              :         
      90            1 :         Random &random = Random::instance();
      91            1 :         Vector3d pos = random.randomInterpolatedPosition(candidate->previous.getPosition(), candidate->current.getPosition());
      92              : 
      93            1 :         double f = Ee / E;
      94              : 
      95            1 :                 if (random.rand() < pow(1 - f, thinning)) {
      96            1 :                         double w = 1. / pow(1 - f, thinning);
      97            1 :                         candidate->addSecondary( 11, Ee / (1 + z), pos, w, interactionTag);
      98              :                 } 
      99            1 :                 if (random.rand() < pow(f, thinning)) {
     100            1 :                         double w = 1. / pow(f, thinning);
     101            1 :                         candidate->addSecondary(-11, Ee / (1 + z), pos, w, interactionTag);
     102              :                 }
     103              : }
     104              : 
     105            1 : void EMDoublePairProduction::process(Candidate *candidate) const {
     106              :         
     107              :         // check if photon
     108            1 :         if (candidate->current.getId() != 22)
     109              :                 return;
     110              : 
     111              :         // scale the electron energy instead of background photons
     112            1 :         double z = candidate->getRedshift();
     113            1 :         double E = (1 + z) * candidate->current.getEnergy();
     114            1 :         Vector3d position = candidate->current.getPosition();
     115              : 
     116              :         // interaction rate
     117            1 :         double rate = getRate(E, position, z);
     118            1 :         if (rate < 0)
     119              :                 return;
     120              :                 
     121              :         // check for interaction
     122            1 :         Random &random = Random::instance();
     123            1 :         double randDistance = -log(random.rand()) / rate;
     124            1 :         double step = candidate->getCurrentStep();
     125            1 :         if (step < randDistance) {
     126            1 :                 candidate->limitNextStep(limit / rate);
     127            1 :                 return;
     128              :         } else { // after performing interaction photon ceases to exist (hence return)
     129            0 :                 performInteraction(candidate);
     130            0 :                 return;
     131              :         }
     132              : 
     133              : }
     134              : 
     135            1 : void EMDoublePairProduction::setInteractionTag(std::string tag) {
     136            1 :         interactionTag = tag;
     137            1 : }
     138              : 
     139            2 : std::string EMDoublePairProduction::getInteractionTag() const {
     140            2 :         return interactionTag;
     141              : }
     142              : 
     143              : 
     144              : } // namespace crpropa
        

Generated by: LCOV version 2.0-1