Program Listing for File PT11Field.cpp

Return to documentation for file (src/magneticField/PT11Field.cpp)

#include "crpropa/magneticField/PT11Field.h"
#include "crpropa/Units.h"

#include <algorithm>

namespace crpropa {

PT11Field::PT11Field() : useASS(true), useBSS(false), useHalo(true) {
        // disk parameters
        d = - 0.6 * kpc;
        R_sun = 8.5 * kpc;
        R_c = 5.0 * kpc;
        z0_D = 1.0 * kpc;
        B0_D = 2.0 * muG;

        // halo parameters
        z0_H = 1.3 * kpc;
        R0_H = 8.0 * kpc;
        B0_Hn = 4.0 * muG;
        B0_Hs = 4.0 * muG;
        z11_H = 0.25 * kpc;
        z12_H = 0.4 * kpc;

        // set ASS specific parameters
        setUseASS(true);
}

void PT11Field::SetParams() {
        cos_pitch = cos(pitch);
        sin_pitch = sin(pitch);
        PHI = cos_pitch / sin_pitch * log1p(d / R_sun) - M_PI / 2;
        cos_PHI = cos(PHI);
}

void PT11Field::setUseASS(bool use) {
        useASS = use;
        if (not(use))
                return;

        if (useBSS) {
                std::cout << "PT11Field: Disk field changed to ASS" << std::endl;
                useBSS = false;
        }

        pitch = -5.0 * M_PI / 180;
        B0_Hs = 2.0 * muG;
        SetParams();
}

void PT11Field::setUseBSS(bool use) {
        useBSS = use;
        if (not(use))
                return;

        if (useASS) {
                std::cout << "PT11Field: Disk field changed to BSS" << std::endl;
                useASS = false;
        }

        pitch = -6.0 * M_PI / 180;
        B0_Hs = 4.0 * muG;
        SetParams();
}

void PT11Field::setUseHalo(bool use) {
        useHalo = use;
}

bool PT11Field::isUsingASS() {
        return useASS;
}

bool PT11Field::isUsingBSS() {
        return useBSS;
}

bool PT11Field::isUsingHalo() {
        return useHalo;
}

Vector3d PT11Field::getField(const Vector3d& pos) const {
        double r = sqrt(pos.x * pos.x + pos.y * pos.y);  // in-plane radius

        Vector3d b(0.);

        // disk field
        if ((useASS) or (useBSS)) {
                // PT11 paper has B_theta = B * cos(p) but this seems because they define azimuth clockwise, while we have anticlockwise.
                // 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.
                // so to get local B clockwise in our system, need minus (like Sun etal).
                // Ps base their system on Han and Qiao 1994 A&A 288,759 which has a diagram with azimuth clockwise, hence confirmed.

                // PT11 paper define Earth position at (+8.5, 0, 0) kpc; but usual convention is (-8.5, 0, 0)
                // thus we have to rotate our position by 180 degree in azimuth
                double theta = M_PI - pos.getPhi();  // azimuth angle theta: PT11 paper uses opposite convention for azimuth
                // the following is equivalent to sin(pi - phi) and cos(pi - phi) which is computationally slower
                double cos_theta = - pos.x / r;
                double sin_theta = pos.y / r;

                // After some geometry calculations (on whiteboard) one finds:
                // Bx = +cos(theta) * B_r - sin(theta) * B_{theta}
                // By = -sin(theta) * B_r - cos(theta) * B_{theta}
                // Use from paper: B_theta = B * cos(pitch)     and B_r = B * sin(pitch)
                b.x = sin_pitch * cos_theta - cos_pitch * sin_theta;
                b.y = - sin_pitch * sin_theta - cos_pitch * cos_theta;
                b *= -1;        // flip magnetic field direction, as B_{theta} and B_{phi} refering to 180 degree rotated field

                double bMag = cos(theta - cos_pitch / sin_pitch * log(r / R_sun) + PHI);
                if (useASS)
                        bMag = fabs(bMag);
                bMag *= B0_D * R_sun / std::max(r, R_c) / cos_PHI * exp(-fabs(pos.z) / z0_D);
                b *= bMag;
        }

        // halo field
        if (useHalo) {
                double bMag = (pos.z > 0 ? B0_Hn : - B0_Hs);
                double z1 = (fabs(pos.z) < z0_H ? z11_H : z12_H);
                bMag *= r / R0_H * exp(1 - r / R0_H) / (1 + pow((fabs(pos.z) - z0_H) / z1, 2.));
                // equation (8) in paper: theta uses now the conventional azimuth definition in contrast to equation (3)
                // cos(phi) = pos.x / r (phi going counter-clockwise)
                // sin(phi) = pos.y / r
                // unitvector of phi in polar coordinates: (-sin(phi), cos(phi), 0)
                b += bMag * Vector3d(-pos.y / r, pos.x / r, 0);
        }

        return b;
}

} // namespace crpropa