|||
日食的原理在小学课本中就有介绍,也就是月亮的影子遮挡住了太阳。日食每次必定发生在农历初一,因为农历初一是朔,此时从地心看起来月亮距离太阳最近。为什么要强调地心呢? 因为在地球表面的不同位置,有视差的存在。天文学家在计算天象的时候,很多时候会先计算地心坐标。具体到某一个地点,再归算到地平坐标。
日食的原理说来简单,但是计算起来并不容易。在我国古代,对日食的时间和类型的计算,是检验历法是否准确的重要标准。很多部历法由于不能准确的预测日月食,而不得不被新的历法所替代。如《新唐书.历志一》记载:“唐终始二百九十馀年,而历八改。初曰戊寅元历,曰麟德甲子元历,曰开元大衍历。”《新唐书.历志三上》又记载:"开元九年,麟德历署日蚀不效,诏僧一行作新历,推大衍数立术以应之..."。被誉为唐代历法首屈一指的《大衍历》,最后也难免被更为精确的历法所代替。
这里采用的算法,是基于比利时天文学家Jean Meeus提出的现代天文算法。详情请参见许剑伟老师翻译的《天文算法》第52章。
全部R程序改变自剑伟老师的《寿星万年历》javascript源代码。
### 快速日食搜索,jd为朔时间
### 改编自许剑伟老师的《寿星万年历》javascript源代码
### 输入儒略日2000,计算最近的朔的时间,并判断该次朔是否会发生日食。
DateSolarEclipse <-
function (jd){
rad = 180*3600/pi; #每弧度的角秒数
radd = 180/pi; #每弧度的度数
pi2 = pi*2;
pi_2 = pi/2;
J2000 = 2451545;
re=list();
W = floor((jd+8)/29.5306)*pi*2; #合朔时的日月黄经差
#合朔时间计算,2000前+-4000年误差1小时以内,+-2000年小于10分钟
t = ( W + 1.08472 )/7771.37714500204; #平朔时间
re$jd = re$jdNewMoon = t*36525;
t2=t*t
t3=t2*t
t4=t3*t;
L = ( 93.2720993+483202.0175273*t-0.0034029*t2-t3/3526000+t4/863310000 )/180*pi;
re$ac=1
re$type='N';
if(abs(sin(L))>0.4) return(re); #一般大于21度已不可能
t = t - ( -0.0000331*t*t + 0.10976 *cos( 0.785 + 8328.6914*t) )/7771;
t2= t*t;
L = (-1.084719 +7771.377145013*t -0.0000331*t2 +
(22640 * cos(0.785+ 8328.6914*t +0.000152*t2)
+4586 * cos(0.19 + 7214.063*t -0.000218*t2)
+2370 * cos(2.54 + 15542.754*t -0.000070*t2)
+ 769 * cos(3.1 + 16657.383*t)
+ 666 * cos(1.5 + 628.302*t)
+ 412 * cos(4.8 + 16866.93*t)
+ 212 * cos(4.1 -1114.63*t)
+ 205 * cos(0.2 + 6585.76*t)
+ 192 * cos(4.9 + 23871.45*t)
+ 165 * cos(2.6 + 14914.45*t)
+ 147 * cos(5.5 -7700.39*t)
+ 125 * cos(0.5 + 7771.38*t)
+ 109 * cos(3.9 + 8956.99*t)
+ 55 * cos(5.6 -1324.18*t)
+ 45 * cos(0.9 + 25195.62*t)
+ 40 * cos(3.8 -8538.24*t)
+ 38 * cos(4.3 + 22756.82*t)
+ 36 * cos(5.5 + 24986.07*t)
-6893 * cos(4.669257+628.3076*t)
- 72 * cos(4.6261 +1256.62*t)
- 43 * cos(2.67823 +628.31*t)*t
+ 21) / rad);
t = t + ( W - L ) / ( 7771.38
- 914 * sin( 0.7848 + 8328.691425*t + 0.0001523*t2 )
- 179 * sin( 2.543 +15542.7543*t )
- 160 * sin( 0.1874 + 7214.0629*t ) );
re$jd = re$jdNewMoon = jd = t*36525; #朔时刻
#纬 52,15 (角秒)
t2=t*t/10000;
t3=t2*t/10000;
mB= ( 18461*cos(0.0571+ 8433.46616*t -0.640*t2 -1*t3)
+ 1010*cos(2.413 + 16762.1576 *t + 0.88 *t2 + 25*t3)
+ 1000*cos(5.440 -104.7747 *t + 2.16 *t2 + 26*t3)
+ 624*cos(0.915 + 7109.2881 *t + 0 *t2 + 7*t3)
+ 199*cos(1.82 + 15647.529 *t -2.8 *t2 -19*t3)
+ 167*cos(4.84 -1219.403 *t -1.5 *t2 -18*t3)
+ 117*cos(4.17 + 23976.220 *t -1.3 *t2 + 6*t3)
+ 62*cos(4.8 + 25090.849 *t + 2 *t2 + 50*t3)
+ 33*cos(3.3 + 15437.980 *t + 2 *t2 + 32*t3)
+ 32*cos(1.5 + 8223.917 *t + 4 *t2 + 51*t3)
+ 30*cos(1.0 + 6480.986 *t + 0 *t2 + 7*t3)
+ 16*cos(2.5 -9548.095 *t -3 *t2 -43*t3)
+ 15*cos(0.2 + 32304.912 *t + 0 *t2 + 31*t3)
+ 12*cos(4.0 + 7737.590 *t)
+ 9*cos(1.9 + 15019.227 *t)
+ 8*cos(5.4 + 8399.709 *t)
+ 8*cos(4.2 + 23347.918 *t)
+ 7*cos(4.9 -1847.705 *t)
+ 7*cos(3.8 -16133.856 *t)
+ 7*cos(2.7 + 14323.351 *t));
mB = mB / rad;
#月地距离 106, 23 (千米)
mR = (385001
+20905*cos(5.4971+ 8328.691425*t+ 1.52 *t2 + 25*t3)
+ 3699*cos(4.900 + 7214.06287*t -2.18 *t2 -19*t3)
+ 2956*cos(0.972 + 15542.75429*t -0.66 *t2 + 6*t3)
+ 570*cos(1.57 + 16657.3828 *t + 3.0 *t2 + 50*t3)
+ 246*cos(5.69 -1114.6286 *t -3.7 *t2 -44*t3)
+ 205*cos(1.02 + 14914.4523 *t -1 *t2 + 6*t3)
+ 171*cos(3.33 + 23871.4457 *t + 1 *t2 + 31*t3)
+ 152*cos(4.94 + 6585.761 *t -2 *t2 -19*t3)
+ 130*cos(0.74 -7700.389 *t -2 *t2 -25*t3)
+ 109*cos(5.20 + 7771.377 *t)
+ 105*cos(2.31 + 8956.993 *t + 1 *t2 + 25*t3)
+ 80*cos(5.38 -8538.241 *t + 2.8 *t2 + 26*t3)
+ 49*cos(6.24 + 628.302 *t)
+ 35*cos(2.7 + 22756.817 *t -3 *t2 -13*t3)
+ 31*cos(4.1 + 16171.056 *t -1 *t2 + 6*t3)
+ 24*cos(1.7 + 7842.365 *t -2 *t2 -19*t3)
+ 23*cos(3.9 + 24986.074 *t + 5 *t2 + 75*t3)
+ 22*cos(0.4 + 14428.126 *t -4 *t2 -38*t3)
+ 17*cos(2.0 + 8399.679 *t));
mR = mR/ 6378.1366;
t=jd/365250;
t2=t*t;
t3=t2*t;
#误0.0002AU
sR = (10001399 #日地距离
+167070*cos(3.098464 + 6283.07585*t)
+ 1396*cos(3.0552 + 12566.1517 *t)
+ 10302*cos(1.10749 + 6283.07585*t)*t
+ 172*cos(1.064 + 12566.152 *t)*t
+ 436*cos(5.785 + 6283.076 *t)*t2
+ 14*cos(4.27 + 6283.08 *t)*t3)
sR = sR * 1.49597870691/6378.1366*10;
#经纬速度
t=jd/36525;
vL = (7771 #月日黄经差速度
-914*sin(0.785 + 8328.6914*t)
-179*sin(2.543 +15542.7543*t)
-160*sin(0.187 + 7214.0629*t));
vB = (-755*sin(0.057 + 8433.4662*t) #月亮黄纬速度
- 82*sin(2.413 +16762.1576*t));
vR =(-27299*sin(5.497 + 8328.691425*t)
- 4184*sin(4.900 + 7214.06287*t)
- 7204*sin(0.972 +15542.75429*t));
vL = vL/36525
vB = vB/36525
vR = vR/36525; #每日速度
gm = mR*sin(mB)*vL/sqrt(vB*vB+vL*vL);
smR= sR-mR; #gm伽马值,smR日月距
mk = 0.2725076;
sk = 109.1222;
f1 = (sk+mk)/smR; r1 = mk+f1*mR; #tanf1半影锥角, r1半影半径
f2 = (sk-mk)/smR; r2 = mk-f2*mR; #tanf2本影锥角, r2本影半径
b = 0.9972;
Agm = abs(gm);
Ar2 = abs(r2);
fh2 = mR-mk/f2;
if(Agm < 1){
h = sqrt(1-gm*gm)
}else{
h = 0
}
## h = Agm<1 ? sqrt(1-gm*gm) : 0; #fh2本影顶点的z坐标
## ls1,ls2,ls3,ls4;
if(fh2<h) {
re$type = 'T'; #全食
}else{
re$type = 'A'; #环食
}
ls1 = Agm-(b+r1 );
if(abs(ls1)<0.016) re$ac=0; #无食分界
ls2 = Agm-(b+Ar2);
if(abs(ls2)<0.016) re$ac=0; #偏食分界
ls3 = Agm-(b );
if(abs(ls3)<0.016) re$ac=0; #无中心食分界
ls4 = Agm-(b-Ar2);
if(abs(ls4)<0.016) re$ac=0; #有中心食分界(但本影未全部进入)
if (ls1>0) {
re$type = 'N'; #无日食
} else {
if(ls2>0) {
re$type = 'P'; #偏食
} else {
if(ls3>0) {
re$type = paste(re$type, '0', sep = ""); #无中心
} else {
if(ls4>0) {
re$type = paste(re$type, '1', sep = ""); #有中心(本影未全部进入)
} else { #本影全进入
if(abs(fh2-h)<0.019) re$ac=0;
if( abs(fh2)<h ){
dr = vR*h/vL/mR;
H1 = mR-dr-mk/f2; #入点影锥z坐标
H2 = mR+dr-mk/f2; #出点影锥z坐标
if(H1>0) re$type='H3'; #环全全
if(H2>0) re$type='H2'; #全全环
if(H1>0&H2>0) re$type='H'; #环全环
if(abs(H1)<0.019) re$ac=0;
if(abs(H2)<0.019) re$ac=0;
}
}
}
}
}
return (re);
}
#取整数部分
int2 <-
function (v) {
return (floor(v));
}
### 公历转儒略日
JD <-
function(y,m,d){
n=0;G=0;
if(y*372+m*31+int2(d)>=588829)
G = 1; #判断是否为格里高利历日1582*372+10*31+15
if(m<=2) {
m = m +12;
y = y - 1;
}
if(G > 0) {
n=int2(y/100);
n=2-n+int2(n/4); #加百年闰
}
res <- int2(365.25*(y+4716)) + int2(30.6001*(m+1))+d+n - 1524.5;
class(res) <- "JD"
return(res)
}
### 将儒略日转换为儒略日2000
JD2000 <-
function(jd){
res <- jd - JD(2000,1,1)
return(res)
}
### 将日期转换为儒略日2000
date2JD2000 <-
function(y,m,d){
juliand <- JD(y,m,d)
res <- JD2000(juliand)
return(res)
}
### 打印JD类型对象的方法
print.JD <-
function(JD){
print(sprintf("%f",JD))
}
##儒略日转为公历
Julian2Date <-
function(jd){
r = list();
D = int2(jd+0.5);
F= jd+0.5-D #取得日数的整数部份A及小数部分F
if(D >= 2299161) {
c = int2((D-1867216.25)/36524.25);
D = D + 1 + c - int2(c/4);
}
D = D + 1524;
r$Y = int2((D - 122.1)/365.25);#年数
D = D - int2(365.25*r$Y);
r$M = int2(D/30.601); #月数
D = D - int2(30.601*r$M);
r$D = D; #日数
if(r$M>13) {
r$M = r$M - 13;
r$Y = r$Y - 4715;
} else {
r$M = r$M - 1;
r$Y = r$Y - 4716;
}
#日的小数转为时分秒
F = F * 24;
r$h=int2(F);
F = F - r$h;
F = F * 60;
r$m=int2(F);
F = F -r$m;
F = F * 60;
r$s=F;
return(r);
}
#日期转为字符串
DD2str <-
function(r){
Y = r$Y
M = r$M
D = r$D;
h = r$h;
m = r$m;
s = int2(r$s+0.5);
if(s >= 60) {
s = s - 60;
m = m + 1;
}
if(m >= 60) {
m = m - 60
h = h + 1;
}
h = paste("0", h, sep = "");
m = paste("0", m, sep = "");
s = paste("0", s, sep = "");
Y = substr(Y, nchar(Y)- 4, nchar(Y) );
M = substr(M, nchar(M)- 1, nchar(M) );
D = substr(D, nchar(D)- 1, nchar(D) );
h = substr(h, nchar(h)- 1, nchar(h) );
m = substr(m, nchar(m)- 1, nchar(m) );
s = substr(s, nchar(s)- 1, nchar(s) );
res <- paste(Y,"-",M,"-",D," ",h,":",m,":",s, sep = "");
return(res)
}
JD2str <-
function(jd){ #JD转为串
r = DD( jd );
res <- DD2str( r );
return(res)
}
### 判断距离输入日期最近的朔,有没有日食发生。
## "P"为偏食
## "T"为全食
## "A"为日环食
## "N"没有日食发生
find.solar.eclipse <-
function(y,m,d){
res <- list()
dd <- DateSolarEclipse(date2JD2000(y,m,d))
date.solar.eclipse <- DD2str(Julian2Date(dd$jdNewMoon + JD(2000,1,1) + 0.5))
type <- dd$type
res$NewMoonTime <- date.solar.eclipse
res$EclipseType <- type
return(res)
}
##距离1987年9月23日最近的朔,以及日食类型
find.solar.eclipse(1987,9,23)
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-10-20 02:20
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社