Program Listing for File EMDoublePairProduction.cpp
↰ Return to documentation for file (src/module/EMDoublePairProduction.cpp)
#include "crpropa/module/EMDoublePairProduction.h"
#include "crpropa/Units.h"
#include "crpropa/Random.h"
#include "crpropa/Common.h"
#include <vector>
#include <cmath>
namespace crpropa {
EMDoublePairProduction::EMDoublePairProduction(ref_ptr<PhotonField> photonField, bool haveElectrons, double thinning, double limit, ref_ptr<Surface> surface) {
setSurface(surface);
setPhotonField(photonField);
setHaveElectrons(haveElectrons);
setLimit(limit);
setThinning(thinning);
}
void EMDoublePairProduction::setPhotonField(ref_ptr<PhotonField> photonField) {
this->photonField = photonField;
std::string fname = photonField->getFieldName();
setDescription("EMDoublePairProduction: " + fname);
// choose the right interaction rates for the used photon field
if (!this->photonField->hasPositionDependence()) {
this->interactionRates = new InteractionRatesHomogeneous(
getDataPath("EMDoublePairProduction/rate_" + fname + ".txt")
);
} else {
this->interactionRates = new InteractionRatesPositionDependent(
getDataPath("EMDoublePairProduction/"+fname+"/Rate/"),
"",
this->surface
);
}
}
void EMDoublePairProduction::setHaveElectrons(bool haveElectrons) {
this->haveElectrons = haveElectrons;
}
void EMDoublePairProduction::setLimit(double limit) {
this->limit = limit;
}
void EMDoublePairProduction::setThinning(double thinning) {
this->thinning = thinning;
}
void EMDoublePairProduction::setSurface(ref_ptr<Surface> surface) {
this->surface = surface;
}
ref_ptr<Surface> EMDoublePairProduction::getSurface() const {
return this->surface;
}
void EMDoublePairProduction::setInteractionRates(ref_ptr<InteractionRates> intRates) {
this->interactionRates = intRates;
}
ref_ptr<InteractionRates> EMDoublePairProduction::getInteractionRates() const {
return this->interactionRates;
}
void EMDoublePairProduction::initRate(std::string path) {
this->interactionRates->initRate(path);
}
double EMDoublePairProduction::getRate(double E, const Vector3d &position, double z) const {
return this->interactionRates->getProcessRate(E, position) * pow_integer<2>(1 + z) * photonField->getRedshiftScaling(z);
}
void EMDoublePairProduction::performInteraction(Candidate *candidate) const {
// Use assumption of Lee 96 arXiv:9604098
// Energy is equally shared between one e+e- pair, but take mass of second e+e- pair into account.
// This approximation has been shown to be valid within -1.5%.
double z = candidate->getRedshift();
double E = candidate->current.getEnergy() * (1 + z);
double Ee = (E - 2 * mass_electron * c_squared) / 2;
// the photon is lost after the interaction
candidate->setActive(false);
if (not haveElectrons)
return;
Random &random = Random::instance();
Vector3d pos = random.randomInterpolatedPosition(candidate->previous.getPosition(), candidate->current.getPosition());
double f = Ee / E;
if (random.rand() < pow(1 - f, thinning)) {
double w = 1. / pow(1 - f, thinning);
candidate->addSecondary( 11, Ee / (1 + z), pos, w, interactionTag);
}
if (random.rand() < pow(f, thinning)) {
double w = 1. / pow(f, thinning);
candidate->addSecondary(-11, Ee / (1 + z), pos, w, interactionTag);
}
}
void EMDoublePairProduction::process(Candidate *candidate) const {
// check if photon
if (candidate->current.getId() != 22)
return;
// scale the electron energy instead of background photons
double z = candidate->getRedshift();
double E = (1 + z) * candidate->current.getEnergy();
Vector3d position = candidate->current.getPosition();
// interaction rate
double rate = getRate(E, position, z);
if (rate < 0)
return;
// check for interaction
Random &random = Random::instance();
double randDistance = -log(random.rand()) / rate;
double step = candidate->getCurrentStep();
if (step < randDistance) {
candidate->limitNextStep(limit / rate);
return;
} else { // after performing interaction photon ceases to exist (hence return)
performInteraction(candidate);
return;
}
}
void EMDoublePairProduction::setInteractionTag(std::string tag) {
interactionTag = tag;
}
std::string EMDoublePairProduction::getInteractionTag() const {
return interactionTag;
}
} // namespace crpropa