Line data Source code
1 : #include "crpropa/magneticField/PT11Field.h" 2 : #include "crpropa/Units.h" 3 : 4 : #include <algorithm> 5 : 6 : namespace crpropa { 7 : 8 0 : PT11Field::PT11Field() : useASS(true), useBSS(false), useHalo(true) { 9 : // disk parameters 10 0 : d = - 0.6 * kpc; 11 0 : R_sun = 8.5 * kpc; 12 0 : R_c = 5.0 * kpc; 13 0 : z0_D = 1.0 * kpc; 14 0 : B0_D = 2.0 * muG; 15 : 16 : // halo parameters 17 0 : z0_H = 1.3 * kpc; 18 0 : R0_H = 8.0 * kpc; 19 0 : B0_Hn = 4.0 * muG; 20 0 : B0_Hs = 4.0 * muG; 21 0 : z11_H = 0.25 * kpc; 22 0 : z12_H = 0.4 * kpc; 23 : 24 : // set ASS specific parameters 25 0 : setUseASS(true); 26 0 : } 27 : 28 0 : void PT11Field::SetParams() { 29 0 : cos_pitch = cos(pitch); 30 0 : sin_pitch = sin(pitch); 31 0 : PHI = cos_pitch / sin_pitch * log1p(d / R_sun) - M_PI / 2; 32 0 : cos_PHI = cos(PHI); 33 0 : } 34 : 35 0 : void PT11Field::setUseASS(bool use) { 36 0 : useASS = use; 37 0 : if (not(use)) 38 : return; 39 : 40 0 : if (useBSS) { 41 : std::cout << "PT11Field: Disk field changed to ASS" << std::endl; 42 0 : useBSS = false; 43 : } 44 : 45 0 : pitch = -5.0 * M_PI / 180; 46 0 : B0_Hs = 2.0 * muG; 47 0 : SetParams(); 48 : } 49 : 50 0 : void PT11Field::setUseBSS(bool use) { 51 0 : useBSS = use; 52 0 : if (not(use)) 53 : return; 54 : 55 0 : if (useASS) { 56 : std::cout << "PT11Field: Disk field changed to BSS" << std::endl; 57 0 : useASS = false; 58 : } 59 : 60 0 : pitch = -6.0 * M_PI / 180; 61 0 : B0_Hs = 4.0 * muG; 62 0 : SetParams(); 63 : } 64 : 65 0 : void PT11Field::setUseHalo(bool use) { 66 0 : useHalo = use; 67 0 : } 68 : 69 0 : bool PT11Field::isUsingASS() { 70 0 : return useASS; 71 : } 72 : 73 0 : bool PT11Field::isUsingBSS() { 74 0 : return useBSS; 75 : } 76 : 77 0 : bool PT11Field::isUsingHalo() { 78 0 : return useHalo; 79 : } 80 : 81 0 : Vector3d PT11Field::getField(const Vector3d& pos) const { 82 0 : double r = sqrt(pos.x * pos.x + pos.y * pos.y); // in-plane radius 83 : 84 : Vector3d b(0.); 85 : 86 : // disk field 87 0 : if ((useASS) or (useBSS)) { 88 : // PT11 paper has B_theta = B * cos(p) but this seems because they define azimuth clockwise, while we have anticlockwise. 89 : // see Tinyakov 2002 APh 18,165: "local field points to l=90+p" so p=-5 deg gives l=85 and hence clockwise from above. 90 : // so to get local B clockwise in our system, need minus (like Sun etal). 91 : // Ps base their system on Han and Qiao 1994 A&A 288,759 which has a diagram with azimuth clockwise, hence confirmed. 92 : 93 : // PT11 paper define Earth position at (+8.5, 0, 0) kpc; but usual convention is (-8.5, 0, 0) 94 : // thus we have to rotate our position by 180 degree in azimuth 95 0 : double theta = M_PI - pos.getPhi(); // azimuth angle theta: PT11 paper uses opposite convention for azimuth 96 : // the following is equivalent to sin(pi - phi) and cos(pi - phi) which is computationally slower 97 0 : double cos_theta = - pos.x / r; 98 0 : double sin_theta = pos.y / r; 99 : 100 : // After some geometry calculations (on whiteboard) one finds: 101 : // Bx = +cos(theta) * B_r - sin(theta) * B_{theta} 102 : // By = -sin(theta) * B_r - cos(theta) * B_{theta} 103 : // Use from paper: B_theta = B * cos(pitch) and B_r = B * sin(pitch) 104 0 : b.x = sin_pitch * cos_theta - cos_pitch * sin_theta; 105 0 : b.y = - sin_pitch * sin_theta - cos_pitch * cos_theta; 106 : b *= -1; // flip magnetic field direction, as B_{theta} and B_{phi} refering to 180 degree rotated field 107 : 108 0 : double bMag = cos(theta - cos_pitch / sin_pitch * log(r / R_sun) + PHI); 109 0 : if (useASS) 110 0 : bMag = fabs(bMag); 111 0 : bMag *= B0_D * R_sun / std::max(r, R_c) / cos_PHI * exp(-fabs(pos.z) / z0_D); 112 : b *= bMag; 113 : } 114 : 115 : // halo field 116 0 : if (useHalo) { 117 0 : double bMag = (pos.z > 0 ? B0_Hn : - B0_Hs); 118 0 : double z1 = (fabs(pos.z) < z0_H ? z11_H : z12_H); 119 0 : bMag *= r / R0_H * exp(1 - r / R0_H) / (1 + pow((fabs(pos.z) - z0_H) / z1, 2.)); 120 : // equation (8) in paper: theta uses now the conventional azimuth definition in contrast to equation (3) 121 : // cos(phi) = pos.x / r (phi going counter-clockwise) 122 : // sin(phi) = pos.y / r 123 : // unitvector of phi in polar coordinates: (-sin(phi), cos(phi), 0) 124 0 : b += bMag * Vector3d(-pos.y / r, pos.x / r, 0); 125 : } 126 : 127 0 : return b; 128 : } 129 : 130 : } // namespace crpropa