LCOV - code coverage report
Current view: top level - src/magneticField - CMZField.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 103 107 96.3 %
Date: 2024-04-29 14:43:01 Functions: 18 18 100.0 %

          Line data    Source code
       1             : #include "crpropa/magneticField/CMZField.h"
       2             : #include "crpropa/Units.h"
       3             : 
       4             : namespace crpropa {
       5             : 
       6           5 : CMZField::CMZField() {
       7           5 :     useMCField = false;
       8           5 :     useICField = true;
       9           5 :     useNTFField = false;
      10           5 :     useRadioArc = false;
      11           5 : }
      12             : 
      13           8 : double CMZField::getA(double a1) const {
      14           8 :     return 4*log(2)/a1/a1;  
      15             : }
      16             : 
      17           8 : double CMZField::getL(double a2) const {
      18           8 :     return a2/2*log(2);
      19             : }
      20             : 
      21           9 : Vector3d CMZField::BPol(const Vector3d& position,const Vector3d& mid, double B1, double a, double L) const{
      22             :     // cylindircal coordinates
      23             :     Vector3d pos = position - mid;
      24           9 :     double r = sqrt(pos.x*pos.x + pos.y*pos.y);
      25           9 :     double phi = std::atan2(pos.y, pos.x);
      26             : 
      27           9 :     double r1 = 1/(1+a*pos.z*pos.z);
      28           9 :     double Bs = B1*exp(-r1*r/L);
      29           9 :     double Br = 2*a*pow_integer<3>(r1)*r*pos.z*Bs;
      30             :     
      31             :     Vector3d b = Vector3d(0.);
      32           9 :     b.z = r1*r1*Bs;
      33             :     // transform to cartesian coordinates
      34           9 :     b.x = Br*cos(phi);
      35           9 :     b.y = Br*sin(phi);
      36           9 :     return b;
      37             : }
      38             : 
      39          14 : Vector3d CMZField::BAz(const Vector3d& position, const Vector3d& mid, double B1, double eta, double R) const {
      40             :     // cylindrical coordinates
      41             :     Vector3d pos = position - mid;
      42          14 :     double r = sqrt(pos.x*pos.x + pos.y*pos.y);
      43          14 :     double phi = std::atan2(pos.y,pos.x);
      44             : 
      45             :     Vector3d bVec(0.);
      46          14 :     double Hc = R/sqrt(log(2));
      47             :     double b = 1.;
      48             :     double m = 1;
      49          14 :     double r1 = R/10;
      50          14 :     double v = m/eta*log((r+b)/(R+b));
      51          14 :     double cosV = cos(v + m*phi);
      52             : 
      53             :     double Br=0;
      54             :     double Bphi=0;
      55             :     
      56          14 :     if(r>r1){
      57          13 :         double Pre = B1*cosV*exp(-pos.z*pos.z/Hc/Hc);
      58          13 :         Br = Pre*R/r;
      59          13 :         Bphi=-Pre/eta*R/(r+b);
      60             :     }
      61             :     else{
      62           1 :         double Pre = B1*exp(-pos.z*pos.z/Hc/Hc)*R/r1*(3*r/r1 - 2*r*r/r1/r1)*cosV;
      63             :         Br = Pre;
      64           1 :         Bphi = 1 + 6*(r-r1)/(2*r-3*r1)*(sin(v+m*phi)-sin(v))/cosV;
      65           1 :         Bphi *= -Pre*r/eta/(r+b);
      66             :     }
      67             : 
      68          14 :     bVec.x = Br*cos(phi) - Bphi*sin(phi);
      69          14 :     bVec.y = Br*sin(phi) + Bphi*cos(phi);
      70             : 
      71          14 :     return bVec;
      72             : }
      73             : 
      74           2 : bool CMZField::getUseMCField() const {
      75           2 :     return useMCField;
      76             : }
      77           2 : bool CMZField::getUseICField() const {
      78           2 :     return useICField;
      79             : }
      80           2 : bool CMZField::getUseNTFField() const {
      81           2 :     return useNTFField;
      82             : }
      83           2 : bool CMZField::getUseRadioArc() const {
      84           2 :     return useRadioArc;
      85             : }
      86             : 
      87           1 : void CMZField::setUseMCField(bool use) {
      88           1 :     useMCField = use;
      89           1 : }
      90           1 : void CMZField::setUseICField(bool use) {
      91           1 :     useICField = use;
      92           1 : }
      93           1 : void CMZField::setUseNTFField(bool use) {
      94           1 :     useNTFField = use;
      95           1 : }
      96           1 : void CMZField::setUseRadioArc(bool use) {
      97           1 :     useRadioArc = use;
      98           1 : }
      99             : 
     100           1 : Vector3d CMZField::getMCField(const Vector3d& pos) const {//Field in molecular clouds
     101             :     Vector3d b(0.);
     102             :     double eta=0.01;
     103             :     double N=59; // normalization factor, depends on eta
     104             : 
     105             :         // azimuthal component in dense clouds
     106             :     //A=SgrC 
     107             :     Vector3d mid(0,-81.59*pc, -16.32*pc);
     108             :     double R = 1.7*pc; 
     109             :     double B1=2.1e-3/N;
     110           1 :     b += BAz(pos, mid, B1, eta, R);
     111             : 
     112             :     // A=G0.253+0.016 Dust Ridge A
     113             :     mid = Vector3d(0, 37.53*pc, -2.37*pc);
     114             :     R=2.4*pc; 
     115             :     B1=2.5e-3/N;
     116           1 :     b += BAz(pos, mid, B1, eta, R);
     117             : 
     118             :     //A=Dust Ridge B
     119             :     mid = Vector3d(0, 50.44, 8.16)*pc;
     120             :     R=1.9*pc; 
     121             :     B1=0.9e-3/N;
     122           1 :     b += BAz(pos, mid, B1, eta, R);
     123             :     
     124             :     //A=Dust Ridge C
     125             :     mid = Vector3d(0,56.37,7.71)*pc;
     126             :     R=1.9*pc; 
     127             :     B1=1.2e-3/N;
     128           1 :     b += BAz(pos, mid, B1, eta, R);
     129             : 
     130             :     //A=Dust Ridge D
     131             :     mid = Vector3d(0, 60.82, 7.42)*pc;
     132             :     R=3.3*pc; 
     133             :     B1=1.7e-3/N;
     134           1 :     b += BAz(pos, mid, B1, eta, R);
     135             :     
     136             :     //A=Dust Ridge E
     137             :     mid = Vector3d(0, 70.91, 0.74)*pc;
     138             :     R=3.5*pc; 
     139             :     B1=4.1e-3/N;
     140           1 :     b += BAz(pos, mid, B1, eta, R);
     141             :         
     142             :     //A=Dust Ridge F
     143             :     mid = Vector3d(0, 73.58, 2.97)*pc;
     144             :     R=2.4*pc; 
     145             :     B1=3.9e-3/N;
     146           1 :     b += BAz(pos, mid, B1, eta, R);
     147             : 
     148             :     //Sgr D
     149             :     mid = Vector3d(0, 166.14, -10.38)*pc;
     150             :     R=1.8*pc;
     151             :     B1=0.8e-3/N;
     152           1 :     b += BAz(pos, mid, B1, eta, R);
     153             : 
     154             :     //Sgr B2
     155             :     mid = Vector3d(0, 97.01, -5.93)*pc;
     156             :     R=14*pc; 
     157             :     B1=1.0e-3/N;
     158           1 :     b += BAz(pos, mid, B1, eta, R);
     159             :         
     160             :     //A=Inner R=5pc
     161             :     mid = Vector3d(0, -8.3, -6.9)*pc;
     162             :     R=5*pc; 
     163             :     B1=3.0e-3/0.91;    
     164           1 :     b += BAz(pos, mid, B1, 0.77, R); // different eta value!
     165             : 
     166             :     //20 km s^-1
     167             :     mid = Vector3d(0, -19.29,-11.87)*pc;
     168             :     R=9.4*pc; 
     169             :     B1=2.7e-3/N;
     170           1 :     b += BAz(pos, mid, B1, eta, R);    
     171             :     
     172             :     //50 km s^-1
     173             :     mid = Vector3d(0, -2.97, -10.38)*pc;
     174             :     R=9.4*pc; 
     175             :     B1=3.7e-3/N;
     176           1 :     b += BAz(pos, mid, B1, eta, R);    
     177             :     
     178             :     //SgrA* is different orrientated! 
     179             :     //only phi component
     180           1 :     double x = pos.x;
     181           1 :     double y = pos.y + 8.3*pc;
     182           1 :     double z = pos.z + 6.9*pc;
     183             :     R=1.2e12; 
     184             :     B1=65./3.07;
     185             :     double Hc = R/sqrt(log(2));
     186           1 :     double r = sqrt(x*x + y*y);
     187             :     double r1 = R/10;
     188           1 :     double phi= std::atan2(y,x);
     189             :     double Bphi;
     190             : 
     191           1 :     if(r>r1){
     192           1 :         Bphi = - B1*exp(-z*z/Hc/Hc)*R/r;
     193             :     }
     194             :     else{
     195           0 :         - B1*exp(-z*z/Hc/Hc)*R/r1*(3*r/r1- 2*r*r/r1*r1);
     196             :     }
     197             : 
     198           1 :     b.x -= Bphi*sin(phi);
     199           1 :     b.y += Bphi*cos(phi);
     200             : 
     201           1 :     return b*gauss;
     202             : } 
     203             : 
     204           1 : Vector3d CMZField::getICField(const Vector3d& pos) const {//Field in intercloud medium--> poloidal field
     205             :     Vector3d mid(0.,-8.3*pc,-6.9*pc);
     206             : 
     207             :     double eta = 0.85;
     208             :     double B1 = 1e-5*gauss;
     209             :     double B2 = B1/eta;
     210             :     double a = 4*log(2)/pow(70*pc, 2); 
     211             :     double L = 158*pc/log(2);
     212             : 
     213           1 :     return BPol(pos, mid, B2, a, L);
     214             : }                                                         
     215             :   
     216           1 : Vector3d CMZField::getNTFField(const Vector3d& pos) const {//Field in the non-thermal filaments--> predominantly poloidal field (except "pelical"-> azimuthal)
     217             :     Vector3d b(0.); 
     218             :     Vector3d mid(0.);
     219             : 
     220             :     //A=SgrC
     221             :     mid = Vector3d(0., -81.59,-1.48)*pc;
     222             :     double a1=27.44*pc;
     223             :     double a2=1.73*pc;
     224             :     double eta=0.48;
     225             :     double B1=1.e-4;
     226           1 :     b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     227             : 
     228             :     //A=G359.15-0.2 The Snake
     229             :     mid = Vector3d(0, -126.1,-25.22)*pc;
     230             :     a1=12.86*pc;
     231             :     a2=2.22*pc;
     232             :     B1=88.e-6;
     233           1 :     b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     234             : 
     235             :     //A=G359.54+0.18 Nonthermal Filament
     236             :     mid = Vector3d(0, -68.24,25.22)*pc;
     237             :     a1=15.08*pc;
     238             :     a2=2.72;
     239             :     B1=1.e-3;
     240           1 :     b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     241             : 
     242             :     //A=G359.79 +17 Nonthermal Filament
     243             :     mid = Vector3d(0,-31.15,23.74)*pc;
     244             :     a1=16.07*pc;
     245             :     a2=3.46*pc;
     246             :     B1=1.e-3;
     247           1 :     b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     248             : 
     249             :     //A=G359.96 +0.09  Nonthermal Filament Southern Thread
     250             :     mid = Vector3d(0, 5.93, 16.32)*pc;
     251             :     a1=28.68*pc;
     252             :     a2=1.73*pc;
     253             :     B1=1.e-4;
     254           1 :     b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     255             : 
     256             :     //A=G0.09 +0.17  Nonthermal Filament Northern thread
     257             :     mid = Vector3d(0, 13.35, 25.22)*pc;
     258             :     a1=29.42*pc;
     259             :     a2=2.23*pc;
     260             :     B1=140.e-6;
     261           1 :     b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     262             : 
     263             :     //A=G359.85+0.47  Nonthermal Filament The Pelican  is not poloidal but azimuthal
     264             :     mid = Vector3d(0, -22.25, 69.73)*pc;
     265             :     a1=11.37*pc;
     266             :     a2=2.23*pc;
     267             :     B1=70.e-6 /eta;
     268             :     // by and bz switched because pelican is differently oriented
     269           1 :     Vector3d bPelican = BPol(pos, mid, B1/eta, getA(a1), getL(a2));
     270           1 :     b.x += bPelican.x;
     271           1 :     b.y += bPelican.z;
     272           1 :     b.z += bPelican.y;
     273             :     
     274           1 :         return b*gauss;
     275             : }
     276             :   
     277           1 : Vector3d CMZField::getRadioArcField(const Vector3d& pos) const {//Field in the non-thermal filaments--> predominantly poloidal field
     278             :     //poloidal field in the non-thermal filament region A=RadioArc
     279             :     double eta=0.48;
     280             :     Vector3d mid(0,26.7*pc,10.38*pc);
     281             :     double a1=70.47*pc;// arcmin-> deg->cm
     282             :     double a2=9.89*pc;// arcmin-> deg-> cm
     283             :     double B1=1.e-3;
     284           1 :     return BPol(pos, mid, B1/eta, getA(a1), getL(a2))*gauss;
     285             : }
     286             : 
     287           1 : Vector3d CMZField::getField(const Vector3d& pos) const{
     288             :     Vector3d b(0.);
     289             : 
     290           1 :     if(useMCField){
     291           0 :         b += getMCField(pos);
     292             :     }
     293           1 :     if(useICField){
     294           1 :         b += getICField(pos);
     295             :     }
     296           1 :     if(useNTFField){
     297           0 :         b += getNTFField(pos);
     298             :     }
     299           1 :     if(useRadioArc){
     300           0 :         b += getRadioArcField(pos);
     301             :     }
     302             : 
     303           1 :     return b;
     304             : }
     305             : 
     306             : } // namespace crpropa

Generated by: LCOV version 1.14