LCOV - code coverage report
Current view: top level - src/module - ElasticScattering.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 63 70 90.0 %
Date: 2024-04-29 14:43:01 Functions: 5 7 71.4 %

          Line data    Source code
       1             : #include "crpropa/module/ElasticScattering.h"
       2             : #include "crpropa/Units.h"
       3             : #include "crpropa/ParticleID.h"
       4             : #include "crpropa/ParticleMass.h"
       5             : #include "crpropa/Random.h"
       6             : 
       7             : #include <cmath>
       8             : #include <limits>
       9             : #include <sstream>
      10             : #include <fstream>
      11             : #include <stdexcept>
      12             : 
      13             : namespace crpropa {
      14             : 
      15             : const double ElasticScattering::lgmin = 6.;  // minimum log10(Lorentz-factor)
      16             : const double ElasticScattering::lgmax = 14.; // maximum log10(Lorentz-factor)
      17             : const size_t ElasticScattering::nlg = 201;   // number of Lorentz-factor steps
      18             : const double ElasticScattering::epsmin = log10(2 * eV) + 3;    // log10 minimum photon background energy in nucleus rest frame for elastic scattering
      19             : const double ElasticScattering::epsmax = log10(2 * eV) + 8.12; // log10 maximum photon background energy in nucleus rest frame for elastic scattering
      20             : const size_t ElasticScattering::neps = 513; // number of photon background energies in nucleus rest frame
      21             : 
      22           2 : ElasticScattering::ElasticScattering(ref_ptr<PhotonField> f) {
      23           2 :         setPhotonField(f);
      24           2 : }
      25             : 
      26           4 : void ElasticScattering::setPhotonField(ref_ptr<PhotonField> photonField) {
      27           4 :         this->photonField = photonField;
      28           4 :         std::string fname = photonField->getFieldName();
      29           4 :         setDescription("ElasticScattering: " + fname);
      30          12 :         initRate(getDataPath("ElasticScattering/rate_" + fname.substr(0,3) + ".txt"));
      31          12 :         initCDF(getDataPath("ElasticScattering/cdf_" + fname.substr(0,3) + ".txt"));
      32           4 : }
      33             : 
      34           4 : void ElasticScattering::initRate(std::string filename) {
      35           4 :         std::ifstream infile(filename.c_str());
      36           4 :         if (not infile.good())
      37           0 :                 throw std::runtime_error("ElasticScattering: could not open file " + filename);
      38             : 
      39           4 :         tabRate.clear();
      40             : 
      41         824 :         while (infile.good()) {
      42         824 :                 if (infile.peek() == '#') {
      43          16 :                         infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
      44          16 :                         continue;
      45             :                 }
      46             :                 double r;
      47             :                 infile >> r;
      48         808 :                 if (!infile)
      49             :                         break;
      50         804 :                 tabRate.push_back(r / Mpc);
      51             :         }
      52             : 
      53           4 :         infile.close();
      54           4 : }
      55             : 
      56           4 : void ElasticScattering::initCDF(std::string filename) {
      57           4 :         std::ifstream infile(filename.c_str());
      58           4 :         if (not infile.good())
      59           0 :                 throw std::runtime_error("ElasticScattering: could not open file " + filename);
      60             : 
      61           4 :         tabCDF.clear();
      62             :         std::string line;
      63             :         double a;
      64         820 :         while (std::getline(infile, line)) {
      65         816 :                 if (line[0] == '#')
      66          12 :                         continue;
      67             : 
      68         804 :                 std::stringstream lineStream(line);
      69             :                 lineStream >> a;
      70             : 
      71         804 :                 std::vector<double> cdf(neps);
      72      413256 :                 for (size_t i = 0; i < neps; i++) {
      73             :                         lineStream >> a;
      74      412452 :                         cdf[i] = a;
      75             :                 }
      76         804 :                 tabCDF.push_back(cdf);
      77         804 :         }
      78             : 
      79           4 :         infile.close();
      80           4 : }
      81             : 
      82           1 : void ElasticScattering::process(Candidate *candidate) const {
      83           1 :         int id = candidate->current.getId();
      84           1 :         double z = candidate->getRedshift();
      85             : 
      86           1 :         if (not isNucleus(id))
      87             :                 return;
      88             : 
      89           1 :         double lg = log10(candidate->current.getLorentzFactor() * (1 + z));
      90           1 :         if ((lg < lgmin) or (lg > lgmax))
      91             :                 return;
      92             : 
      93           1 :         int A = massNumber(id);
      94           1 :         int Z = chargeNumber(id);
      95           1 :         int N = A - Z;
      96             : 
      97           1 :         double step = candidate->getCurrentStep();
      98           7 :         while (step > 0) {
      99             : 
     100           7 :                 double rate = interpolateEquidistant(lg, lgmin, lgmax, tabRate);
     101           7 :                 rate *= Z * N / double(A);  // TRK scaling
     102           7 :                 rate *= pow_integer<2>(1 + z) * photonField->getRedshiftScaling(z);  // cosmological scaling
     103             : 
     104             :                 // check for interaction
     105           7 :                 Random &random = Random::instance();
     106           7 :                 double randDist = -log(random.rand()) / rate;
     107           7 :                 if (step < randDist)
     108           1 :                         return;
     109             : 
     110             :                 // draw random background photon energy from CDF
     111           6 :                 size_t i = floor((lg - lgmin) / (lgmax - lgmin) * (nlg - 1)); // index of closest gamma tabulation point
     112           6 :                 size_t j = random.randBin(tabCDF[i]) - 1; // index of next lower tabulated eps value
     113             :                 double binWidth = (epsmax - epsmin) / (neps - 1); // logarithmic bin width
     114           6 :                 double eps = pow(10, epsmin + (j + random.rand()) * binWidth);
     115             : 
     116             :                 // boost to lab frame
     117           6 :                 double cosTheta = 2 * random.rand() - 1;
     118           6 :                 double E = eps * candidate->current.getLorentzFactor() * (1. - cosTheta);
     119             : 
     120           6 :                 Vector3d pos = random.randomInterpolatedPosition(candidate->previous.getPosition(), candidate->current.getPosition());
     121           6 :                 candidate->addSecondary(22, E, pos, 1., interactionTag);
     122             : 
     123             :                 // repeat with remaining step
     124           6 :                 step -= randDist;
     125             :         }
     126             : }
     127             : 
     128           0 : void ElasticScattering::setInteractionTag(std::string tag) {
     129           0 :         this -> interactionTag = tag;
     130           0 : }
     131             : 
     132           0 : std::string ElasticScattering::getInteractionTag() const {
     133           0 :         return interactionTag;
     134             : }
     135             : 
     136             : } // namespace crpropa

Generated by: LCOV version 1.14