double JF12Field::getTurbulentStrength(const Vector3d& pos) const { if (pos.getR() > 20 * kpc) return 0; double r = sqrt(pos.x * pos.x + pos.y * pos.y); // in-plane radius double phi = pos.getPhi(); // azimuth // disk double bDisk = 0; if (r < 5 * kpc) { bDisk = bDiskTurb5; } else { // spiral region double r_negx = r * exp(-(phi - M_PI) / tan90MinusPitch); if (r_negx > rArms[7]) r_negx = r * exp(-(phi + M_PI) / tan90MinusPitch); if (r_negx > rArms[7]) r_negx = r * exp(-(phi + 3 * M_PI) / tan90MinusPitch); for (int i = 7; i >= 0; i--) if (r_negx < rArms[i]) bDisk = bDiskTurb[i]; bDisk *= (5 * kpc) / r; } bDisk *= exp(-0.5 * pow(pos.z / zDiskTurb, 2)); // halo double bHalo = bHaloTurb * exp(-r / rHaloTurb) * exp(-0.5 * pow(pos.z / zHaloTurb, 2)); // modulate turbulent field return sqrt(pow(bDisk, 2) + pow(bHalo, 2)); }
Vector3d JF12Field::getRegularField(const Vector3d& pos) const { Vector3d b(0.); double r = sqrt(pos.x * pos.x + pos.y * pos.y); // in-plane radius double d = pos.getR(); // distance to galactic center if ((d < 1 * kpc) or (d > 20 * kpc)) return b; // 0 field for d < 1 kpc or d > 20 kpc double phi = pos.getPhi(); // azimuth double sinPhi = sin(phi); double cosPhi = cos(phi); double lfDisk = logisticFunction(pos.z, hDisk, wDisk); // disk field if (r > 3 * kpc) { double bMag; if (r < 5 * kpc) { // molecular ring bMag = bRing * (5 * kpc / r) * (1 - lfDisk); b.x += -bMag * sinPhi; b.y += bMag * cosPhi; } else { // spiral region double r_negx = r * exp(-(phi - M_PI) / tan90MinusPitch); if (r_negx > rArms[7]) r_negx = r * exp(-(phi + M_PI) / tan90MinusPitch); if (r_negx > rArms[7]) r_negx = r * exp(-(phi + 3 * M_PI) / tan90MinusPitch); for (int i = 7; i >= 0; i--) if (r_negx < rArms[i]) bMag = bDisk[i]; bMag *= (5 * kpc / r) * (1 - lfDisk); b.x += bMag * (sinPitch * cosPhi - cosPitch * sinPhi); b.y += bMag * (sinPitch * sinPhi + cosPitch * cosPhi); } } // toroidal halo field double bMagH = exp(-fabs(pos.z) / z0) * lfDisk; if (pos.z >= 0) bMagH *= bNorth * (1 - logisticFunction(r, rNorth, wHalo)); else bMagH *= bSouth * (1 - logisticFunction(r, rSouth, wHalo)); b.x += -bMagH * sinPhi; b.y += bMagH * cosPhi; // poloidal halo field double bMagX; double sinThetaX, cosThetaX; double rp; double rc = rXc + fabs(pos.z) / tanThetaX0; if (r < rc) { // varying elevation region rp = r * rXc / rc; bMagX = bX * exp(-1 * rp / rX) * pow(rp / r, 2.); double thetaX = atan2(fabs(pos.z), (r - rp)); if (pos.z == 0) thetaX = M_PI / 2.; sinThetaX = sin(thetaX); cosThetaX = cos(thetaX); } else { // constant elevation region rp = r - fabs(pos.z) / tanThetaX0; bMagX = bX * exp(-rp / rX) * (rp / r); sinThetaX = sinThetaX0; cosThetaX = cosThetaX0; } double zsign = pos.z < 0 ? -1 : 1; b.x += zsign * bMagX * cosThetaX * cosPhi; b.y += zsign * bMagX * cosThetaX * sinPhi; b.z += bMagX * sinThetaX; return b; }
void ParticleState::setDirection(const Vector3d &dir) { direction = dir / dir.getR(); }