Program Listing for File ElasticScattering.cpp
↰ Return to documentation for file (src/module/ElasticScattering.cpp
)
#include "crpropa/module/ElasticScattering.h"
#include "crpropa/Units.h"
#include "crpropa/ParticleID.h"
#include "crpropa/ParticleMass.h"
#include "crpropa/Random.h"
#include <cmath>
#include <limits>
#include <sstream>
#include <fstream>
#include <stdexcept>
namespace crpropa {
const double ElasticScattering::lgmin = 6.; // minimum log10(Lorentz-factor)
const double ElasticScattering::lgmax = 14.; // maximum log10(Lorentz-factor)
const size_t ElasticScattering::nlg = 201; // number of Lorentz-factor steps
const double ElasticScattering::epsmin = log10(2 * eV) + 3; // log10 minimum photon background energy in nucleus rest frame for elastic scattering
const double ElasticScattering::epsmax = log10(2 * eV) + 8.12; // log10 maximum photon background energy in nucleus rest frame for elastic scattering
const size_t ElasticScattering::neps = 513; // number of photon background energies in nucleus rest frame
ElasticScattering::ElasticScattering(ref_ptr<PhotonField> f) {
setPhotonField(f);
}
void ElasticScattering::setPhotonField(ref_ptr<PhotonField> photonField) {
this->photonField = photonField;
std::string fname = photonField->getFieldName();
setDescription("ElasticScattering: " + fname);
initRate(getDataPath("ElasticScattering/rate_" + fname.substr(0,3) + ".txt"));
initCDF(getDataPath("ElasticScattering/cdf_" + fname.substr(0,3) + ".txt"));
}
void ElasticScattering::initRate(std::string filename) {
std::ifstream infile(filename.c_str());
if (not infile.good())
throw std::runtime_error("ElasticScattering: could not open file " + filename);
tabRate.clear();
while (infile.good()) {
if (infile.peek() == '#') {
infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
continue;
}
double r;
infile >> r;
if (!infile)
break;
tabRate.push_back(r / Mpc);
}
infile.close();
}
void ElasticScattering::initCDF(std::string filename) {
std::ifstream infile(filename.c_str());
if (not infile.good())
throw std::runtime_error("ElasticScattering: could not open file " + filename);
tabCDF.clear();
std::string line;
double a;
while (std::getline(infile, line)) {
if (line[0] == '#')
continue;
std::stringstream lineStream(line);
lineStream >> a;
std::vector<double> cdf(neps);
for (size_t i = 0; i < neps; i++) {
lineStream >> a;
cdf[i] = a;
}
tabCDF.push_back(cdf);
}
infile.close();
}
void ElasticScattering::process(Candidate *candidate) const {
int id = candidate->current.getId();
double z = candidate->getRedshift();
if (not isNucleus(id))
return;
double lg = log10(candidate->current.getLorentzFactor() * (1 + z));
if ((lg < lgmin) or (lg > lgmax))
return;
int A = massNumber(id);
int Z = chargeNumber(id);
int N = A - Z;
double step = candidate->getCurrentStep();
while (step > 0) {
double rate = interpolateEquidistant(lg, lgmin, lgmax, tabRate);
rate *= Z * N / double(A); // TRK scaling
rate *= pow_integer<2>(1 + z) * photonField->getRedshiftScaling(z); // cosmological scaling
// check for interaction
Random &random = Random::instance();
double randDist = -log(random.rand()) / rate;
if (step < randDist)
return;
// draw random background photon energy from CDF
size_t i = floor((lg - lgmin) / (lgmax - lgmin) * (nlg - 1)); // index of closest gamma tabulation point
size_t j = random.randBin(tabCDF[i]) - 1; // index of next lower tabulated eps value
double binWidth = (epsmax - epsmin) / (neps - 1); // logarithmic bin width
double eps = pow(10, epsmin + (j + random.rand()) * binWidth);
// boost to lab frame
double cosTheta = 2 * random.rand() - 1;
double E = eps * candidate->current.getLorentzFactor() * (1. - cosTheta);
Vector3d pos = random.randomInterpolatedPosition(candidate->previous.getPosition(), candidate->current.getPosition());
candidate->addSecondary(22, E, pos, 1., interactionTag);
// repeat with remaining step
step -= randDist;
}
}
void ElasticScattering::setInteractionTag(std::string tag) {
this -> interactionTag = tag;
}
std::string ElasticScattering::getInteractionTag() const {
return interactionTag;
}
} // namespace crpropa