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