Program Listing for File Ferriere.cpp

Return to documentation for file (src/massDistribution/Ferriere.cpp)

#include "crpropa/massDistribution/Ferriere.h"
#include "crpropa/Common.h"

#include "kiss/logger.h"

#include <sstream>

namespace crpropa {

Vector3d Ferriere::CMZTransformation(const Vector3d &position) const {
        // set galactocentric coordinate system with the Sun at (-8.5,0.,0.) instead of (8.5, 0, 0) to be consistand with JF12 implementation
        double x = -position.x;
        double y = -position.y;

        double xC = -50*pc;             //offset
        double yC = 50*pc;
        double sinTc = sin(70.*deg);
        double cosTc = cos(70.*deg);

        Vector3d pos;
        pos.x = (x - xC)*cosTc + (y - yC)*sinTc;
        pos.y = -(x - xC)*sinTc + (y - yC)*cosTc;
        pos.z = position.z;

        return pos;
}

Vector3d Ferriere::DiskTransformation(const Vector3d &position) const {
        // set galactocentric coordinate system with the Sun at (-8.5,0.,0.) instead of (8.5, 0, 0) to be consistand with JF12 implementation
        double x = -position.x;
        double y = - position.y;
        double z = position.z;

        double alphaD = 13.5*deg;  // rotation arround x-axis
        double sinAd = sin(alphaD);
        double cosAd = cos(alphaD);
        double betaD = 20.*deg;  // rotation arround y'-axis
        double sinBd = sin(betaD);
        double cosBd = cos(betaD);
        double TettaD = 48.5*deg;  // rotation arround x"-axis
        double sinTd = sin(TettaD);
        double cosTd = cos(TettaD);

        Vector3d pos;

        pos.x = x*cosBd*cosTd - y*(sinAd*sinBd*cosTd -cosAd*sinTd)-z*(cosAd*sinBd*cosTd +sinAd*sinTd);

        pos.y =  -x*cosBd*sinTd;
        pos.y += y*(sinAd*sinBd*sinTd +cosAd*cosTd);
        pos.y += z*(cosAd*sinBd*sinTd -sinAd*cosTd);

        pos.z = x*sinBd;
        pos.z += y*sinAd*cosBd;
        pos.z += z*cosAd*cosBd;

        return pos;
}

double Ferriere::getHIDensity(const Vector3d &position) const {
        double n = 0;
        double R = sqrt(position.x*position.x+position.y*position.y);

        if(R<3*kpc)
        {
                // density at center
                Vector3d pos = CMZTransformation(position);  // coordinate trafo
                double x = pos.x/pc;  // all units in pc
                double y = pos.y/pc;
                double z = pos.z/pc;

                double A = sqrt(x*x+2.5*2.5*y*y);
                double nCMZ = 8.8/ccm*exp(-pow_integer<4>((A-125.)/137))*exp(-pow_integer<2>(z/54.));

                // density in disk
                pos = DiskTransformation(position);  // Corrdinate Trafo
                x = pos.x/pc;  // all units in pc
                y = pos.y/pc;
                z = pos.z/pc;

                A = sqrt(x*x+3.1*3.1*y*y);
                double nDisk = 0.34/ccm*exp(-pow_integer<4>((A-1200.)/438.))*exp(-pow_integer<2>(z/120));

                n = nCMZ + nDisk;
        }
        else{  // outer region
                double z = position.z/pc;
                double a;
                if(R<=Rsun){
                        a = 1;
                } else {
                        a = R/Rsun;
                }

                double nCold = 0.859*exp(-pow_integer<2>(z/(127*a))); // cold HI
                nCold += 0.047*exp(-pow_integer<2>(z/(318*a)));
                nCold += 0.094*exp(-fabs(z)/(403*a));
                nCold *= 0.340/ccm/(a*a);

                double nWarm = (1.745 - 1.289/a)*exp(-pow_integer<2>(z/(127*a)));  // warm HI
                nWarm += (0.473 - 0.070/a)*exp(-pow_integer<2>(z/(318*a)));
                nWarm += (0.283 - 0.142/a)*exp(-fabs(z)/(403*a));
                nWarm *= 0.226/ccm/a;

                n = nWarm + nCold;
        }

        return n;
}

double Ferriere::getHIIDensity(const Vector3d &position) const {
        double n = 0;
        double R = sqrt(position.x*position.x+position.y*position.y);

        if(R< 3*kpc){   // inner
                double x = position.x/pc;
                double y = position.y/pc;
                double z = position.z/pc;

                // warm interstellar matter
                double H = (x*x + pow_integer<2>(y+10.))/(145*145);
                double nWIM = exp(-H)* exp(-pow_integer<2>(z+20.)/(26*26));
                nWIM += 0.009*exp(-pow_integer<2>((R/pc-3700)/(0.5*3700)))*1/pow_integer<2>(cosh(z/140.));
                nWIM += 0.005*cos(M_PI*R/pc*0.5/17000)*1/pow_integer<2>(cosh(z/950.));
                nWIM *= 8.0/ccm;  // rescaling with density at center

                //very hot interstellar matter
                double alphaVH = 21.*deg;  // angle for very hot IM in radiant
                double cosA = cos(alphaVH);
                double sinA = sin(alphaVH);
                double etta = y*cosA+z*sinA;  // coordinate transformation for VHIM along major axis
                double chi = -y*sinA+z*cosA;

                double nVHIM = 0.29/ccm*exp(-((x*x+etta*etta)/(162.*162.)+chi*chi/(90*90)));

                n = nWIM + nVHIM;
        } else {  // outer region
                double z = position.z;

                double nWarm = 0.0237/ccm*exp(-(R*R-Rsun*Rsun)/pow_integer<2>(37*kpc))*exp(-fabs(z)/(1*kpc));
                nWarm += 0.0013/ccm*exp(-(pow_integer<2>(R-4*kpc)-pow_integer<2>(Rsun-4*kpc))/pow_integer<2>(2*kpc))*exp(-fabs(z)/(150*pc));

                double nHot = 0.12*exp(-(R-Rsun)/(4.9*kpc));
                nHot += 0.88*exp(-(pow_integer<2>(R-4.5*kpc)-pow_integer<2>(Rsun-4.5*kpc))/pow_integer<2>(2.9*kpc));
                nHot *= pow(R/Rsun, -1.65);
                nHot *= exp(-fabs(z)/((1500*pc)*pow(R/Rsun,1.65)));
                nHot *= 4.8e-4/ccm;

                n= nWarm + nHot;
        }
        return n;
}

double Ferriere::getH2Density(const Vector3d &position) const{
        double n=0;
        double R=sqrt(position.x*position.x+position.y*position.y);

        if(R<3*kpc) {
                // density at center
                Vector3d pos =CMZTransformation(position);  // coord trafo for CMZ
                double x = pos.x/pc;  // all units in pc
                double y = pos.y/pc;
                double z = pos.z/pc;

                double A = sqrt(x*x+pow(2.5*y,2));  // ellipticity
                double nCMZ = exp(-pow((A-125.)/137.,4))*exp(-pow(z/18.,2));
                nCMZ *= 150/ccm;  // rescaling

                // density in disk
                pos = DiskTransformation(position);  // coord trafo for disk
                x=pos.x/pc;
                y=pos.y/pc;
                z=pos.z/pc;

                A = sqrt(x*x+pow_integer<2>(3.1*y));
                double nDISK = exp(-pow_integer<4>((A-1200)/438))*exp(-pow_integer<2>(z/42));
                nDISK *= 4.8/ccm;  // rescaling

                n = nCMZ + nDISK;
        } else {  // outer region
                double z = position.z/pc;
                n = pow(R/Rsun, -0.58);
                n *= exp(-(pow_integer<2>(R-4.5*kpc)-pow_integer<2>(Rsun-4.5*kpc))/pow_integer<2>(2.9*kpc));
                n *= exp(-pow_integer<2>(z/(81*pow(R/Rsun,0.58))));
                n *= 0.58/ccm;  // rescaling
        }

        return n;
}

double Ferriere::getDensity(const Vector3d &position) const{
        double n=0;
        if(isforHI){
                n += getHIDensity(position);
        }
        if(isforHII){
                n+=getHIIDensity(position);
        }
        if(isforH2){
                n+=getH2Density(position);
        }
        // check if all densities are deactivated and raise warning if so
        if((isforHI || isforHII || isforH2) == false){
                KISS_LOG_WARNING
                        << "\nCalled getDensity on fully deactivated Ferriere \n"
                        << "gas density model. The total density is set to 0.";
        }

        return n;
}

double Ferriere::getNucleonDensity(const Vector3d &position) const{
        double n=0;
        if(isforHI){
                n += getHIDensity(position);
        }
        if(isforHII){
                n+=getHIIDensity(position);
        }
        if(isforH2){
                n+= 2*getH2Density(position);
        }

        // check if all densities are deactivated and raise warning if so
        if((isforHI || isforHII || isforH2) == false){
                KISS_LOG_WARNING
                        << "\nCalled getNucleonDensity on fully deactivated Ferriere \n"
                        << "gas density model. The total density is set to 0.";
        }

        return n;
}

void Ferriere::setIsForHI(bool HI){
        isforHI = HI;
}

void Ferriere::setIsForHII(bool HII){
        isforHII = HII;
}

void Ferriere::setIsForH2(bool H2){
        isforH2 = H2;
}

bool Ferriere::getIsForHI(){
        return isforHI;
}

bool Ferriere::getIsForHII(){
        return isforHII;
}

bool Ferriere::getIsForH2(){
        return isforH2;
}

std::string Ferriere::getDescription() {
        std::stringstream s;
        s << "Density model Ferriere 2007:\n";
        s<< "HI component is ";
        if(!isforHI)
                s<< "not ";
        s<< "active.\nHII component is ";
        if(!isforHII)
                s<< "not ";
        s<<"active.\nH2 component is ";
        if(!isforH2)
                s<<"not ";
        s<<"active.";
        return s.str();
}

}  // namespace crpropa