Program Listing for File CMZField.cpp
↰ Return to documentation for file (src/magneticField/CMZField.cpp
)
#include "crpropa/magneticField/CMZField.h"
#include "crpropa/Units.h"
namespace crpropa {
CMZField::CMZField() {
useMCField = false;
useICField = true;
useNTFField = false;
useRadioArc = false;
}
double CMZField::getA(double a1) const {
return 4*log(2)/a1/a1;
}
double CMZField::getL(double a2) const {
return a2/2*log(2);
}
Vector3d CMZField::BPol(const Vector3d& position,const Vector3d& mid, double B1, double a, double L) const{
// cylindircal coordinates
Vector3d pos = position - mid;
double r = sqrt(pos.x*pos.x + pos.y*pos.y);
double phi = std::atan2(pos.y, pos.x);
double r1 = 1/(1+a*pos.z*pos.z);
double Bs = B1*exp(-r1*r/L);
double Br = 2*a*pow_integer<3>(r1)*r*pos.z*Bs;
Vector3d b = Vector3d(0.);
b.z = r1*r1*Bs;
// transform to cartesian coordinates
b.x = Br*cos(phi);
b.y = Br*sin(phi);
return b;
}
Vector3d CMZField::BAz(const Vector3d& position, const Vector3d& mid, double B1, double eta, double R) const {
// cylindrical coordinates
Vector3d pos = position - mid;
double r = sqrt(pos.x*pos.x + pos.y*pos.y);
double phi = std::atan2(pos.y,pos.x);
Vector3d bVec(0.);
double Hc = R/sqrt(log(2));
double b = 1.;
double m = 1;
double r1 = R/10;
double v = m/eta*log((r+b)/(R+b));
double cosV = cos(v + m*phi);
double Br=0;
double Bphi=0;
if(r>r1){
double Pre = B1*cosV*exp(-pos.z*pos.z/Hc/Hc);
Br = Pre*R/r;
Bphi=-Pre/eta*R/(r+b);
}
else{
double Pre = B1*exp(-pos.z*pos.z/Hc/Hc)*R/r1*(3*r/r1 - 2*r*r/r1/r1)*cosV;
Br = Pre;
Bphi = 1 + 6*(r-r1)/(2*r-3*r1)*(sin(v+m*phi)-sin(v))/cosV;
Bphi *= -Pre*r/eta/(r+b);
}
bVec.x = Br*cos(phi) - Bphi*sin(phi);
bVec.y = Br*sin(phi) + Bphi*cos(phi);
return bVec;
}
bool CMZField::getUseMCField() const {
return useMCField;
}
bool CMZField::getUseICField() const {
return useICField;
}
bool CMZField::getUseNTFField() const {
return useNTFField;
}
bool CMZField::getUseRadioArc() const {
return useRadioArc;
}
void CMZField::setUseMCField(bool use) {
useMCField = use;
}
void CMZField::setUseICField(bool use) {
useICField = use;
}
void CMZField::setUseNTFField(bool use) {
useNTFField = use;
}
void CMZField::setUseRadioArc(bool use) {
useRadioArc = use;
}
Vector3d CMZField::getMCField(const Vector3d& pos) const {//Field in molecular clouds
Vector3d b(0.);
double eta=0.01;
double N=59; // normalization factor, depends on eta
// azimuthal component in dense clouds
//A=SgrC
Vector3d mid(0,-81.59*pc, -16.32*pc);
double R = 1.7*pc;
double B1=2.1e-3/N;
b += BAz(pos, mid, B1, eta, R);
// A=G0.253+0.016 Dust Ridge A
mid = Vector3d(0, 37.53*pc, -2.37*pc);
R=2.4*pc;
B1=2.5e-3/N;
b += BAz(pos, mid, B1, eta, R);
//A=Dust Ridge B
mid = Vector3d(0, 50.44, 8.16)*pc;
R=1.9*pc;
B1=0.9e-3/N;
b += BAz(pos, mid, B1, eta, R);
//A=Dust Ridge C
mid = Vector3d(0,56.37,7.71)*pc;
R=1.9*pc;
B1=1.2e-3/N;
b += BAz(pos, mid, B1, eta, R);
//A=Dust Ridge D
mid = Vector3d(0, 60.82, 7.42)*pc;
R=3.3*pc;
B1=1.7e-3/N;
b += BAz(pos, mid, B1, eta, R);
//A=Dust Ridge E
mid = Vector3d(0, 70.91, 0.74)*pc;
R=3.5*pc;
B1=4.1e-3/N;
b += BAz(pos, mid, B1, eta, R);
//A=Dust Ridge F
mid = Vector3d(0, 73.58, 2.97)*pc;
R=2.4*pc;
B1=3.9e-3/N;
b += BAz(pos, mid, B1, eta, R);
//Sgr D
mid = Vector3d(0, 166.14, -10.38)*pc;
R=1.8*pc;
B1=0.8e-3/N;
b += BAz(pos, mid, B1, eta, R);
//Sgr B2
mid = Vector3d(0, 97.01, -5.93)*pc;
R=14*pc;
B1=1.0e-3/N;
b += BAz(pos, mid, B1, eta, R);
//A=Inner R=5pc
mid = Vector3d(0, -8.3, -6.9)*pc;
R=5*pc;
B1=3.0e-3/0.91;
b += BAz(pos, mid, B1, 0.77, R); // different eta value!
//20 km s^-1
mid = Vector3d(0, -19.29,-11.87)*pc;
R=9.4*pc;
B1=2.7e-3/N;
b += BAz(pos, mid, B1, eta, R);
//50 km s^-1
mid = Vector3d(0, -2.97, -10.38)*pc;
R=9.4*pc;
B1=3.7e-3/N;
b += BAz(pos, mid, B1, eta, R);
//SgrA* is different orrientated!
//only phi component
double x = pos.x;
double y = pos.y + 8.3*pc;
double z = pos.z + 6.9*pc;
R=1.2e12;
B1=65./3.07;
double Hc = R/sqrt(log(2));
double r = sqrt(x*x + y*y);
double r1 = R/10;
double phi= std::atan2(y,x);
double Bphi;
if(r>r1){
Bphi = - B1*exp(-z*z/Hc/Hc)*R/r;
}
else{
- B1*exp(-z*z/Hc/Hc)*R/r1*(3*r/r1- 2*r*r/r1*r1);
}
b.x -= Bphi*sin(phi);
b.y += Bphi*cos(phi);
return b*gauss;
}
Vector3d CMZField::getICField(const Vector3d& pos) const {//Field in intercloud medium--> poloidal field
Vector3d mid(0.,-8.3*pc,-6.9*pc);
double eta = 0.85;
double B1 = 1e-5*gauss;
double B2 = B1/eta;
double a = 4*log(2)/pow(70*pc, 2);
double L = 158*pc/log(2);
return BPol(pos, mid, B2, a, L);
}
Vector3d CMZField::getNTFField(const Vector3d& pos) const {//Field in the non-thermal filaments--> predominantly poloidal field (except "pelical"-> azimuthal)
Vector3d b(0.);
Vector3d mid(0.);
//A=SgrC
mid = Vector3d(0., -81.59,-1.48)*pc;
double a1=27.44*pc;
double a2=1.73*pc;
double eta=0.48;
double B1=1.e-4;
b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
//A=G359.15-0.2 The Snake
mid = Vector3d(0, -126.1,-25.22)*pc;
a1=12.86*pc;
a2=2.22*pc;
B1=88.e-6;
b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
//A=G359.54+0.18 Nonthermal Filament
mid = Vector3d(0, -68.24,25.22)*pc;
a1=15.08*pc;
a2=2.72;
B1=1.e-3;
b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
//A=G359.79 +17 Nonthermal Filament
mid = Vector3d(0,-31.15,23.74)*pc;
a1=16.07*pc;
a2=3.46*pc;
B1=1.e-3;
b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
//A=G359.96 +0.09 Nonthermal Filament Southern Thread
mid = Vector3d(0, 5.93, 16.32)*pc;
a1=28.68*pc;
a2=1.73*pc;
B1=1.e-4;
b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
//A=G0.09 +0.17 Nonthermal Filament Northern thread
mid = Vector3d(0, 13.35, 25.22)*pc;
a1=29.42*pc;
a2=2.23*pc;
B1=140.e-6;
b += BPol(pos, mid, B1/eta, getA(a1), getL(a2));
//A=G359.85+0.47 Nonthermal Filament The Pelican is not poloidal but azimuthal
mid = Vector3d(0, -22.25, 69.73)*pc;
a1=11.37*pc;
a2=2.23*pc;
B1=70.e-6 /eta;
// by and bz switched because pelican is differently oriented
Vector3d bPelican = BPol(pos, mid, B1/eta, getA(a1), getL(a2));
b.x += bPelican.x;
b.y += bPelican.z;
b.z += bPelican.y;
return b*gauss;
}
Vector3d CMZField::getRadioArcField(const Vector3d& pos) const {//Field in the non-thermal filaments--> predominantly poloidal field
//poloidal field in the non-thermal filament region A=RadioArc
double eta=0.48;
Vector3d mid(0,26.7*pc,10.38*pc);
double a1=70.47*pc;// arcmin-> deg->cm
double a2=9.89*pc;// arcmin-> deg-> cm
double B1=1.e-3;
return BPol(pos, mid, B1/eta, getA(a1), getL(a2))*gauss;
}
Vector3d CMZField::getField(const Vector3d& pos) const{
Vector3d b(0.);
if(useMCField){
b += getMCField(pos);
}
if(useICField){
b += getICField(pos);
}
if(useNTFField){
b += getNTFField(pos);
}
if(useRadioArc){
b += getRadioArcField(pos);
}
return b;
}
} // namespace crpropa