Program Listing for File CandidateSplitting.cpp

Return to documentation for file (src/module/CandidateSplitting.cpp)

#include "crpropa/module/CandidateSplitting.h"

namespace crpropa {

CandidateSplitting::CandidateSplitting() {
        // no particle splitting if EnergyBins and NSplit are not specified
        setNsplit(0);
        setMinimalWeight(1.);
}

CandidateSplitting::CandidateSplitting(int nSplit, double Emin, double Emax,  double nBins, double minWeight, bool log) {
        setNsplit(nSplit);
        setEnergyBins(Emin, Emax, nBins, log);
        setMinimalWeight(minWeight);
}

CandidateSplitting::CandidateSplitting(double spectralIndex, double Emin, int nBins)  {
        // to use with Diffusive Shock Acceleration
        if (spectralIndex > 0){
                throw std::runtime_error(
                                "CandidateSplitting: spectralIndex > 0 !");
        }

        setNsplit(2); // always split in 2, calculate bins in energy for given spectrum:
        double dE = pow(1. / 2, 1. / (spectralIndex + 1));
        setEnergyBinsDSA(Emin, dE, nBins);
        setMinimalWeight(1. / pow(2, nBins));
}

void CandidateSplitting::process(Candidate *c) const {
        double currE = c->current.getEnergy();
        double prevE = c->previous.getEnergy();

        if (c->getWeight() <= minWeight){
                // minimal weight reached, no splitting
                return;
        }
        if (currE < Ebins[0] || nSplit == 0 ){
                // current energy is smaller than first bin -> no splitting
                // or, number of splits = 0
                return;
        }
        for (size_t i = 0; i < Ebins.size(); ++i){

                if( prevE < Ebins[i] ){
                        // previous energy is in energy bin [i-1, i]
                        if(currE < Ebins[i]){
                                //assuming that dE greater than 0, prevE and E in same energy bin -> no splitting
                                return;
                        }
                        // current energy is in energy bin [i,i+1] or higher -> particle splitting for each crossing
                        for (size_t j = i; j < Ebins.size(); ++j ){

                                // adapted from Acceleration Module:
                                c->updateWeight(1. / nSplit); // * 1/n_split

                                for (int i = 1; i < nSplit; i++) {

                                        ref_ptr<Candidate> new_candidate = c->clone(false);
                                        new_candidate->parent = c;
                                        new_candidate->previous.setEnergy(currE); // so that new candidate is not split again in next step!
                                        c->addSecondary(new_candidate);
                                }
                                if (j < Ebins.size()-1 && currE < Ebins[j+1]){
                                        // candidate is in energy bin [j, j+1] -> no further splitting
                                        return;
                                }
                        }
                        return;
                }
        }
}

void CandidateSplitting::setEnergyBins(double Emin, double Emax, double nBins, bool log) {
        Ebins.resize(0);
        if (Emin > Emax){
                throw std::runtime_error(
                                "CandidateSplitting: Emin > Emax!");
        }
        double dE = (Emax-Emin)/nBins;
        for (size_t i = 0; i < nBins; ++i) {
                if (log == true) {
                        Ebins.push_back(Emin * pow(Emax / Emin, i / (nBins - 1.0)));
                } else {
                        Ebins.push_back(Emin + i * dE);
                }
        }
}

void CandidateSplitting::setEnergyBinsDSA(double Emin, double dE, int n) {
        Ebins.resize(0);
        for (size_t i = 1; i < n + 1; ++i) {
                Ebins.push_back(Emin * pow(dE, i));
        }
}

const std::vector<double>& CandidateSplitting::getEnergyBins() const {
        return Ebins;
}

void CandidateSplitting::setNsplit(int n) {
        nSplit = n;
}

void CandidateSplitting::setMinimalWeight(double w) {
        minWeight = w;
}

int CandidateSplitting::getNsplit() const {
        return nSplit;
}

double CandidateSplitting::getMinimalWeight() const {
        return minWeight;
}

} // end namespace crpropa