LCOV - code coverage report
Current view: top level - src/massDistribution - Ferriere.cpp (source / functions) Coverage Total Hit
Test: coverage.info.cleaned Lines: 90.1 % 151 136
Test Date: 2026-06-18 09:49:19 Functions: 92.9 % 14 13

            Line data    Source code
       1              : #include "crpropa/massDistribution/Ferriere.h"
       2              : #include "crpropa/Common.h"
       3              : 
       4              : #include "kiss/logger.h"
       5              : 
       6              : #include <sstream>
       7              : 
       8              : namespace crpropa {
       9              : 
      10           13 : Vector3d Ferriere::CMZTransformation(const Vector3d &position) const {
      11              :         // set galactocentric coordinate system with the Sun at (-8.5,0.,0.) instead of (8.5, 0, 0) to be consistand with JF12 implementation
      12           13 :         double x = -position.x;
      13           13 :         double y = -position.y;
      14              : 
      15              :         double xC = -50*pc;             //offset
      16              :         double yC = 50*pc;
      17              :         double sinTc = sin(70.*deg);
      18              :         double cosTc = cos(70.*deg);
      19              : 
      20              :         Vector3d pos;
      21           13 :         pos.x = (x - xC)*cosTc + (y - yC)*sinTc;
      22           13 :         pos.y = -(x - xC)*sinTc + (y - yC)*cosTc;
      23           13 :         pos.z = position.z;
      24              : 
      25           13 :         return pos;
      26              : }
      27              : 
      28           13 : Vector3d Ferriere::DiskTransformation(const Vector3d &position) const {
      29              :         // set galactocentric coordinate system with the Sun at (-8.5,0.,0.) instead of (8.5, 0, 0) to be consistand with JF12 implementation
      30           13 :         double x = -position.x;
      31           13 :         double y = - position.y;
      32           13 :         double z = position.z;
      33              : 
      34              :         double alphaD = 13.5*deg;  // rotation arround x-axis
      35              :         double sinAd = sin(alphaD);
      36              :         double cosAd = cos(alphaD);
      37              :         double betaD = 20.*deg;  // rotation arround y'-axis
      38              :         double sinBd = sin(betaD);
      39              :         double cosBd = cos(betaD);
      40              :         double TettaD = 48.5*deg;  // rotation arround x"-axis
      41              :         double sinTd = sin(TettaD);
      42              :         double cosTd = cos(TettaD);
      43              : 
      44              :         Vector3d pos;
      45              : 
      46           13 :         pos.x = x*cosBd*cosTd - y*(sinAd*sinBd*cosTd -cosAd*sinTd)-z*(cosAd*sinBd*cosTd +sinAd*sinTd);
      47              : 
      48           13 :         pos.y =  -x*cosBd*sinTd;
      49           13 :         pos.y += y*(sinAd*sinBd*sinTd +cosAd*cosTd);
      50           13 :         pos.y += z*(cosAd*sinBd*sinTd -sinAd*cosTd);
      51              : 
      52           13 :         pos.z = x*sinBd;
      53           13 :         pos.z += y*sinAd*cosBd;
      54           13 :         pos.z += z*cosAd*cosBd;
      55              : 
      56           13 :         return pos;
      57              : }
      58              : 
      59           12 : double Ferriere::getHIDensity(const Vector3d &position) const {
      60              :         double n = 0;
      61           12 :         double R = sqrt(position.x*position.x+position.y*position.y);
      62              : 
      63           12 :         if(R<3*kpc)
      64              :         {
      65              :                 // density at center
      66            6 :                 Vector3d pos = CMZTransformation(position);  // coordinate trafo
      67            6 :                 double x = pos.x/pc;  // all units in pc
      68            6 :                 double y = pos.y/pc;
      69            6 :                 double z = pos.z/pc;
      70              : 
      71            6 :                 double A = sqrt(x*x+2.5*2.5*y*y);
      72            6 :                 double nCMZ = 8.8/ccm*exp(-pow_integer<4>((A-125.)/137))*exp(-pow_integer<2>(z/54.));
      73              : 
      74              :                 // density in disk
      75            6 :                 pos = DiskTransformation(position);  // Corrdinate Trafo
      76            6 :                 x = pos.x/pc;  // all units in pc
      77            6 :                 y = pos.y/pc;
      78            6 :                 z = pos.z/pc;
      79              : 
      80            6 :                 A = sqrt(x*x+3.1*3.1*y*y);
      81            6 :                 double nDisk = 0.34/ccm*exp(-pow_integer<4>((A-1200.)/438.))*exp(-pow_integer<2>(z/120));
      82              : 
      83            6 :                 n = nCMZ + nDisk;
      84              :         }
      85              :         else{  // outer region
      86            6 :                 double z = position.z/pc;
      87              :                 double a;
      88            6 :                 if(R<=Rsun){
      89              :                         a = 1;
      90              :                 } else {
      91            3 :                         a = R/Rsun;
      92              :                 }
      93              : 
      94            6 :                 double nCold = 0.859*exp(-pow_integer<2>(z/(127*a))); // cold HI
      95            6 :                 nCold += 0.047*exp(-pow_integer<2>(z/(318*a)));
      96            6 :                 nCold += 0.094*exp(-fabs(z)/(403*a));
      97            6 :                 nCold *= 0.340/ccm/(a*a);
      98              : 
      99            6 :                 double nWarm = (1.745 - 1.289/a)*exp(-pow_integer<2>(z/(127*a)));  // warm HI
     100            6 :                 nWarm += (0.473 - 0.070/a)*exp(-pow_integer<2>(z/(318*a)));
     101            6 :                 nWarm += (0.283 - 0.142/a)*exp(-fabs(z)/(403*a));
     102            6 :                 nWarm *= 0.226/ccm/a;
     103              : 
     104            6 :                 n = nWarm + nCold;
     105              :         }
     106              : 
     107           12 :         return n;
     108              : }
     109              : 
     110           12 : double Ferriere::getHIIDensity(const Vector3d &position) const {
     111              :         double n = 0;
     112           12 :         double R = sqrt(position.x*position.x+position.y*position.y);
     113              : 
     114           12 :         if(R< 3*kpc){   // inner
     115            6 :                 double x = position.x/pc;
     116            6 :                 double y = position.y/pc;
     117            6 :                 double z = position.z/pc;
     118              : 
     119              :                 // warm interstellar matter
     120            6 :                 double H = (x*x + pow_integer<2>(y+10.))/(145*145);
     121            6 :                 double nWIM = exp(-H)* exp(-pow_integer<2>(z+20.)/(26*26));
     122            6 :                 nWIM += 0.009*exp(-pow_integer<2>((R/pc-3700)/(0.5*3700)))*1/pow_integer<2>(cosh(z/140.));
     123            6 :                 nWIM += 0.005*cos(M_PI*R/pc*0.5/17000)*1/pow_integer<2>(cosh(z/950.));
     124            6 :                 nWIM *= 8.0/ccm;  // rescaling with density at center
     125              : 
     126              :                 //very hot interstellar matter
     127              :                 double alphaVH = 21.*deg;  // angle for very hot IM in radiant
     128              :                 double cosA = cos(alphaVH);
     129              :                 double sinA = sin(alphaVH);
     130            6 :                 double etta = y*cosA+z*sinA;  // coordinate transformation for VHIM along major axis
     131            6 :                 double chi = -y*sinA+z*cosA;
     132              : 
     133            6 :                 double nVHIM = 0.29/ccm*exp(-((x*x+etta*etta)/(162.*162.)+chi*chi/(90*90)));
     134              : 
     135            6 :                 n = nWIM + nVHIM;
     136              :         } else {  // outer region
     137            6 :                 double z = position.z;
     138              : 
     139            6 :                 double nWarm = 0.0237/ccm*exp(-(R*R-Rsun*Rsun)/pow_integer<2>(37*kpc))*exp(-fabs(z)/(1*kpc));
     140            6 :                 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));
     141              : 
     142            6 :                 double nHot = 0.12*exp(-(R-Rsun)/(4.9*kpc));
     143            6 :                 nHot += 0.88*exp(-(pow_integer<2>(R-4.5*kpc)-pow_integer<2>(Rsun-4.5*kpc))/pow_integer<2>(2.9*kpc));
     144            6 :                 nHot *= pow(R/Rsun, -1.65);
     145            6 :                 nHot *= exp(-fabs(z)/((1500*pc)*pow(R/Rsun,1.65)));
     146            6 :                 nHot *= 4.8e-4/ccm;
     147              : 
     148            6 :                 n= nWarm + nHot;
     149              :         }
     150           12 :         return n;
     151              : }
     152              : 
     153           12 : double Ferriere::getH2Density(const Vector3d &position) const{
     154              :         double n=0;
     155           12 :         double R=sqrt(position.x*position.x+position.y*position.y);
     156              : 
     157           12 :         if(R<3*kpc) {
     158              :                 // density at center
     159            6 :                 Vector3d pos =CMZTransformation(position);  // coord trafo for CMZ
     160            6 :                 double x = pos.x/pc;  // all units in pc
     161            6 :                 double y = pos.y/pc;
     162            6 :                 double z = pos.z/pc;
     163              : 
     164            6 :                 double A = sqrt(x*x+pow(2.5*y,2));  // ellipticity
     165            6 :                 double nCMZ = exp(-pow((A-125.)/137.,4))*exp(-pow(z/18.,2));
     166            6 :                 nCMZ *= 150/ccm;  // rescaling
     167              : 
     168              :                 // density in disk
     169            6 :                 pos = DiskTransformation(position);  // coord trafo for disk
     170            6 :                 x=pos.x/pc;
     171            6 :                 y=pos.y/pc;
     172            6 :                 z=pos.z/pc;
     173              : 
     174            6 :                 A = sqrt(x*x+pow_integer<2>(3.1*y));
     175            6 :                 double nDISK = exp(-pow_integer<4>((A-1200)/438))*exp(-pow_integer<2>(z/42));
     176            6 :                 nDISK *= 4.8/ccm;  // rescaling
     177              : 
     178            6 :                 n = nCMZ + nDISK;
     179              :         } else {  // outer region
     180            6 :                 double z = position.z/pc;
     181            6 :                 n = pow(R/Rsun, -0.58);
     182            6 :                 n *= exp(-(pow_integer<2>(R-4.5*kpc)-pow_integer<2>(Rsun-4.5*kpc))/pow_integer<2>(2.9*kpc));
     183            6 :                 n *= exp(-pow_integer<2>(z/(81*pow(R/Rsun,0.58))));
     184            6 :                 n *= 0.58/ccm;  // rescaling
     185              :         }
     186              : 
     187           12 :         return n;
     188              : }
     189              : 
     190            5 : double Ferriere::getDensity(const Vector3d &position) const{
     191              :         double n=0;
     192            5 :         if(isforHI){
     193            4 :                 n += getHIDensity(position);
     194              :         }
     195            5 :         if(isforHII){
     196            4 :                 n+=getHIIDensity(position);
     197              :         }
     198            5 :         if(isforH2){
     199            4 :                 n+=getH2Density(position);
     200              :         }
     201              :         // check if all densities are deactivated and raise warning if so
     202            5 :         if((isforHI || isforHII || isforH2) == false){
     203            2 :                 KISS_LOG_WARNING
     204            1 :                         << "\nCalled getDensity on fully deactivated Ferriere \n"
     205            1 :                         << "gas density model. The total density is set to 0.";
     206              :         }
     207              : 
     208            5 :         return n;
     209              : }
     210              : 
     211            5 : double Ferriere::getNucleonDensity(const Vector3d &position) const{
     212              :         double n=0;
     213            5 :         if(isforHI){
     214            4 :                 n += getHIDensity(position);
     215              :         }
     216            5 :         if(isforHII){
     217            4 :                 n+=getHIIDensity(position);
     218              :         }
     219            5 :         if(isforH2){
     220            4 :                 n+= 2*getH2Density(position);
     221              :         }
     222              : 
     223              :         // check if all densities are deactivated and raise warning if so
     224            5 :         if((isforHI || isforHII || isforH2) == false){
     225            2 :                 KISS_LOG_WARNING
     226            1 :                         << "\nCalled getNucleonDensity on fully deactivated Ferriere \n"
     227            1 :                         << "gas density model. The total density is set to 0.";
     228              :         }
     229              : 
     230            5 :         return n;
     231              : }
     232              : 
     233            1 : void Ferriere::setIsForHI(bool HI){
     234            1 :         isforHI = HI;
     235            1 : }
     236              : 
     237            1 : void Ferriere::setIsForHII(bool HII){
     238            1 :         isforHII = HII;
     239            1 : }
     240              : 
     241            1 : void Ferriere::setIsForH2(bool H2){
     242            1 :         isforH2 = H2;
     243            1 : }
     244              : 
     245            4 : bool Ferriere::getIsForHI(){
     246            4 :         return isforHI;
     247              : }
     248              : 
     249            4 : bool Ferriere::getIsForHII(){
     250            4 :         return isforHII;
     251              : }
     252              : 
     253            4 : bool Ferriere::getIsForH2(){
     254            4 :         return isforH2;
     255              : }
     256              : 
     257            0 : std::string Ferriere::getDescription() {
     258            0 :         std::stringstream s;
     259            0 :         s << "Density model Ferriere 2007:\n";
     260            0 :         s<< "HI component is ";
     261            0 :         if(!isforHI)
     262            0 :                 s<< "not ";
     263            0 :         s<< "active.\nHII component is ";
     264            0 :         if(!isforHII)
     265            0 :                 s<< "not ";
     266            0 :         s<<"active.\nH2 component is ";
     267            0 :         if(!isforH2)
     268            0 :                 s<<"not ";
     269            0 :         s<<"active.";
     270            0 :         return s.str();
     271            0 : }
     272              : 
     273              : }  // namespace crpropa
        

Generated by: LCOV version 2.0-1