LCOV - code coverage report
Current view: top level - src/massDistribution - Ferriere.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 136 151 90.1 %
Date: 2024-04-29 14:43:01 Functions: 13 14 92.9 %

          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 1.14