#coding:sjis
'''
Created on 2011/03/18
@author: uchiyama
'''
"""
importの使い方・考え方は以下が分かりやすい。
http://1-byte.jp/2010/09/29/learning_python5/
そもそもこのシリーズは図解が多くて良さげなので後で読む。
"""
from math import cos,sin,pi, atan, exp, sqrt
from scipy import integrate
"""
普遍であるべき観測量
ここにグローバルな変数として書くのは正しいのだろうか。
"""
#postion of Sgr A* in the Galactic coordinate (degree)
L_GC=-0.056
B_GC=-0.046
# 1 pc in the unit of cm
#CM_PER_PC=3.09e18
#Position of the Earth from the plane (pc)
Z0=16.0
#Distance to Sgr A* (pc)
R0=8.5e3
#The rotation angle
BD1=15.0
BD2=1.0
"""
座標変換に必要な関数。
本当はscipyの座標変換使えばもっと賢くできる気がする。
"""
def sin_d(degree):
return sin(2*pi*degree/360.0);
def cos_d(degree):
return cos(2*pi*degree/360.0);
def dl(l):
return l-L_GC
def db_bulge(b):
return b-B_GC-atan(Z0/R0)
def db(b):
return b-B_GC
def r_f(s,l,b):
l0=dl(l)
b0=db(b)
(R0**2+(s*cos_d(b0))**2-2*R0*s*cos_d(l0)*cos_d(b0))**0.5
def z_f(s, l, b):
b0=db(b)
return s*sin_d(b0)
def x_f_bulge(s, l, b):
l0=dl(l)
b0=db(b)
return R0-s*cos_d(b0)*cos_d(l0)
def y_f_bulge(s, l, b):
l0=dl(l)
b0=db_bulge(b)
s*cos_d(b0)*sin_d(l0)
def z_f_bulge(s, l, b):
b0=db_bulge(b)
return s*sin_d(b0)+Z0
def X_f(x, y, z):
return x*cos_d(BD1)+y*sin_d(BD1)
def Y_f(x, y, z):
return -1*x*sin_d(BD1)*cos_d(BD2)+y*cos_d(BD1)*cos_d(BD2)+z*sin_d(BD2);
def Z_f(x, y, z):
return -1*x*sin_d(BD1)*sin_d(BD2)+y*cos_d(BD1)*sin_d(BD2)+z*cos_d(BD2);
"""
以下星質量モデル。
基本的にMuno+06に基づく…が数式に誤りたくさん+説明不足。
http://adsabs.harvard.edu/abs/2006ApJS..165..173M
Kent+91, Launhardt+02を元に情報を補足、整理。
http://adsabs.harvard.edu/abs/1991ApJ...378..131K
http://adsabs.harvard.edu/abs/2002A%26A...384..112L
更に詳しくは
http://www-utheal.phys.s.u-tokyo.ac.jp/~uchiyama/wordpress/wp-content/uploads/2011/05/SMM.pdf
"""
def NSC(x,l,b):
norm1=3.3e6 # M_solar pc^{-3}
norm2=norm1*8.98e7/3.3e6
n1=2.0
n2=3.0
R_c=0.22 # pc
R_lim=6.0
R_cutoff=200.0
r=r_f(x,l,b)
z=z_f(x,l,b)
"""
powや**は(defaultで)使えるのにsqrtはmathをimportしないと使えない。
意味がよく分からないが、そもそもsqrt不要と言われるとそれが正しい気もする。
"""
R=sqrt(pow(r,2)+pow(z,2))
"""
元々は3項演算子を使っていたがpythonの3項演算子に慣れずネストの仕方が分からないのでif文で書く。
"""
if R < R_lim :
return norm1/(1+pow((R/R_c),n1))
elif R < R_cutoff :
return norm2/(1+pow((R/R_c),n2))
else:
return 0
def NSD(x,l,b):
n1=-0.1
n2=-3.5
n3=-10.0
r_1=120.0
r_2=220.0
r_3=2000.0
r_d=1.0
z_d=45.0
norm1=300.0
norm2=norm1*(r_1/r_d)**(-n2+n1)
norm3=norm2*(r_2/r_d)**(-n3+n2)
r=r_f(x,l,b)+1e-30
z=z_f(x,l,b)
if r <=0 :
return 0.0
elif r < r_1 :
return norm1*(abs(r/r_d)**n1)*exp(-1.0*z/z_d)
elif r < r_2 :
return norm2*(abs(r/r_d)**n2)*exp(-1.0*z/z_d)
elif r < r_3 :
return norm3*(abs(r/r_d)**n3)*exp(-1.0*z/z_d)
else:
return 0.0
def GB(x,l,b):
"""
Unit of value returned by this function
M_solar pc^{-3}
"""
#norm Unit: M_solar pc^{-3}
norm=8.0
#a_x,a_y,a_z : pc
a_x=1100.0
a_y=360.0
a_z=220.0
c_para=3.2
c_perp=1.6
x_b=x_f_bulge(x, l, b);
y=y_f_bulge(x, l, b);
z=z_f_bulge(x, l, b);
"""
Pythonはべき乘を表す演算子**もあるけどpowもある。
そして小数乘もできるし、負の数を小数乗して複素数を
返すこともできる。
"""
R_perp=((abs(X_f(x_b,y,z))/a_x)**c_perp+(abs(Y_f(x_b,y,z))/a_y)**c_perp)**(1/c_perp)
Rs=(pow(abs(Z_f(x_b,y,z))/a_z,c_para)+pow(R_perp,c_para))**(1/c_para);
return norm*exp(-1*Rs);
def GD(x,l,b):
"""
Unit of this function
M_solar pc^{-3}
"""
#norm Unit: M_solar pc^{-3}
norm=5.0
#r_d, z_d : pc
r_d=2700.0;
z_d=200.0;
r=r_f(x, l, b)
z=z_f(x, l, b)
return norm*exp(-1.0*r/r_d)*exp(-1.0*(z/z_d))
def Stellar_density_f(x, l, b):
"""
Unit of this function
M_solar pc^{-3}
"""
return NSC(x,l,b)+NSD(x,l,b)+GB(x,l,b)+GD(x,l,b)
def SMM(l, b, s=16e3 , region='SMM'):
"""
Pythonで関数はオブジェクトなので下記の様なことができてしまう。
正直キモイ。ポインタを渡したくなる…。以下を参照。
http://python.g.hatena.ne.jp/muscovyduck/20080707/p2
"""
if region=='NSC':
func=NSC
elif region=='NSD':
func=NSD
elif region=='GD':
func=GD
elif region=='GB':
func=GB
elif region=='SMM':
func=SMM
else :
exit("3rd argument must be one of NSC/NSD/GD/GB/SMM.")
"""
SciPy(さいぱい。すしぱいと読んでいた…)を使った積分。
http://docs.scipy.org/doc/scipy/scipy-ref.pdf
の1.4.1を見る。
lambda式の意図は
http://atkonn.blogspot.com/2008/02/python-python27-lambda.html
をみるとなんとなく分かる。
"""
res=integrate.quad(lambda x: func(x,l,b), 0.0, s)[0]
"""
The unit of returned value is M_solar/pc^2/str
"""
return res/(4.0*pi);