- 积分
- 4609
- 贡献
-
- 精华
- 在线时间
- 小时
- 注册时间
- 2014-8-21
- 最后登录
- 1970-1-1
|
发表于 2015-6-25 23:10:20
|
显示全部楼层
本帖最后由 呼啦呼啦 于 2015-6-25 23:14 编辑
你好~~~我根据你修改之后的吴洪宝老师的程序做了一些修改,但是一直有问题
运行出错的图
我是对1982-2014年逐月的哈德来海温资料(HadISST)做的REOF,因为有缺测存在,我在程序里添加了处理缺测的东西,但不知道能不能完全处理好缺测值,我把我改动的地方用红色标记出来了,能麻烦你帮我看看是哪的问题吗? 非常感谢!
PROGRAM reof
!NY 为年份 IM为月份 NN为时间序列 IX和IY为经纬度格点数 M1为总格点数
PARAMETER(NY=33,IM=12,NN=NY*IM,IX=41,IY=42,MM=IX*IY)
PARAMETER (np=10,mon=396)
ccc mm=the sea grid number which should be identified first
ccc np=the tezhenxiangliang to be put out
DIMENSION RH(nn,mm),B(nn,np),reco(nn,mm)
DIMENSION A(mm,mm),V(mm,mm),RAMDA(mm),RC(np,np),X(nn),Y(nn),h(mm)
DIMENSION MX(mm),XW(mm),D(mm),RR(np,np),ST(np)
dimension U(mm),VR(mm),WT(mm),WK(mm),WBT(nn),WBK(nn)
dimension vrlv(50)
integer mask(MM)
INTEGER T,K
REAL MX
real tt(mm,mon),vs(mm,np),sst(IX,IY)
CCC 读取数据
open(30,file='D:\by\WPWP_Semiannual_Oscillation\process\REOF\
&1_data\HadISST_1982_2014.grd',form='binary')
do 994 it=1,mon
read(30,rec=it) ((sst(i,j),i=1,IX),j=1,IY)
no=0
ij=0
do 994 j=1,IY
do 994 i=1,IX
no=no+1
if(sst(i,j).ne.-1e+30) then
ij=ij+1
tt(ij,it)=sst(i,j)
mask(no)=1
else
mask(no)=0
endif
994 continue
write(*,*)'read data ok'
write(*,*) ij
num=0
do II=1,mon
num=num+1
do i=1,ij
rh(num,i)=tt(i,II)
enddo
! write(*,*) ij,no,num
enddo
IOUT1=6
IOUT2=12
IOUT3=13
NAME='heat'
c*******************************************************************
OPEN(IOUT1,FILE='D:\by\WPWP_Semiannual_Oscillation\process\REOF\
&2_REOF_Modes\wpssta.REOF')
OPEN(IOUT2,FILE='D:\by\WPWP_Semiannual_Oscillation\process\REOF\
&2_REOF_Modes\wpstVTOR.BIN',FORM='UNFORMATTED',ACCESS='DIRECT',
&RECL=IX*IY*4)
OPEN(IOUT3,FILE='D:\by\WPWP_Semiannual_Oscillation\process\REOF\
&2_REOF_Modes\wpstTIME.BIN',FORM='UNFORMATTED',ACCESS='DIRECT',
&RECL=NN*4)
c********求原始数据每个月的距平值*******
DO 60 J=1,mm
MX(J)=0.0
DO 62 IT=1,nn
62 MX(J)=MX(J)+RH(it,J)
mx(j)=mx(j)/real(nn)
60 CONTINUE
621 FORMAT(1X,'MEAN VALUE MONTH',I3,5(/1X,8F10.1))
C*********************标准化**********************************
DO J=1,mm
D(J)=0.0
DO IT=1,nn
if(RH(it,j).ne.-1e+30)then
D(J)=D(J)+(RH(it,j)-mx(j))*(RH(it,J)-mx(j))
else
D(J)=-1e+30
endif
enddo
if(D(J).ne.-1e+30)then
D(J)=SQRT(D(J)/real(nn))
else
D(J)=-1e+30
endif
enddo
DO J=1,mm
DO IT=1,nn
if(RH(it,j).ne.-1e+30.and.D(j).ne.-1e+30)then
RH(it,J)=(RH(it,J)-mx(j))/D(J)
else
RH(it,j)=-1e+30
endif
enddo
enddo
! 相关系数矩阵
rnn=real(nn)
DO J=1,mm
DO J1=1,mm
A(J,J1)=0.0
DO I=1,nn
A(J,J1)=A(J,J1)+RH(I,J)*RH(I,J1)/rnn
enddo
A(J,J1)=A(J,J1)/rnn
enddo
enddo
sum=0.0
do 80 k=1,mm
80 sum=sum+a(k,k)
write(6,103) sum
103 format(1x,'TRA of the matrix A =',f12.2)
! 求特征值
call jcb(mm,a,v,0.00001)
call jcb1(mm,a,v)
write(6,104)
write(6,204)(a(i,i),i=1,mm)
104 format(//1x,' Eigenvalue(lambad)')
204 format((1x,10f8.3))
do 145 i=1,mm
145 ramda(i)=a(i,i)
c write(6,104) ramda
sum2=0.0
do 222 k=1,mm
222 sum2=sum2+A(k,k)
write(6,106) sum2
write(6,909)
909 format(/3x,'Sum of eigenvalue must be equal to tra of martix A !')
err=abs(sum-sum2)
if(err.lt.0.001) write(6,681) err
if(err.ge.0.001) write(6,482) err
681 format(//1x,' ok 1 err= ',f9.4)
482 format(//1x,' in error err= ',f9.4)
106 format(1x,'THE SUM OF LAMBAD',f12.4)
do 25 k=1,mm
25 mx(k)=100.0*a(k,k)/sum
write(6,108)
write(6,208) mx
108 format(//1x,'The percentage of lambad')
208 format((1x,10f8.2))
call change(v,vs,mask,mm,m1,np)
cccccc未旋转的特征向量
do 112 j=1,np
write(IOUT1,110) j,(vs(I,j),i=1,M1)
112 write(IOUT2,rec=j) (vs(I,j),i=1,M1)
110 format(1x,'LOADING VECTOR (LV)',I3,4(/1x,21f6.2))
! 未旋转的时间系数
do 50 it=1,nn
do 47 jj=1,mm
47 xw(jj)=rh(it,jj)
do 50 j=1,mm
rh(it,j)=0.0
do 54 k=1,mm
54 rh(it,j)=rh(it,j)+xw(k)*v(k,j)
50 continue
do 400 j=1,np
write(IOUT1,125) j,(rh(i,j),i=1,NN)
400 write(IOUT3,rec=j) (rh(i,j),i=1,NN)
125 format(/1x,'The Coefficient (PC)',i3,10(/1x,18f7.2))
c do 400 j=1,np
c write(6,125) j
c 400 write(6,805) (rh(i,j),i=1,nn)
c 125 format(/1x,'The unrotated time coefficient(PC).order',i3)
ccc added by zzq
do 772 j=1,mm
do 772 it=1,nn
reco(it,j)=0.0
do 773 k=1,mm
773 reco(it,j)=reco(it,j)+v(j,k)*rh(it,k)
772 continue
write(6,982)
ccc added by zzq
c do 986 j=1,mm
c write(6,683) j
c 986 write(6,686) (reco(i,j),i=1,nn)
ccc added by zzq
982 format(/1x,'Reconstructed data(for inspect) ')
write(6,238)
238 format(//3x,'To inspect perpendicularty and variance of PC')
write(6,258)
258 format(/1X,'The covariance martix of first NP principal companent
*:')
! 时间系数之间的协方差
do 234 j1=1,np
do 234 j2=1,np
rr(j1,j2)=0.0
do 235 it=1,nn
rr(j1,j2)=rr(j1,j2)+rh(it,j1)*rh(it,j2)/rnn
235 continue
234 continue
do 366 j1=1,np
366 write(6,266) (rr(j1,j2),j2=1,np)
266 format(3x,10f8.3)
write(6,269)
write(6,469)
write(6,669)
write(6,869)
269 format(//4x,'Variance of each time coefficient(PC) must be equal')
469 format(/1x,'to corresponding eigenvalue.')
669 format(/4x,'The covariance between PC each other must be equal ')
869 format(/1x,' to zero.')
DO 333 J=1,np
DO 333 I=1,mm
V(I,J)=V(I,J)*SQRT(RAMDA(J))
333 CONTINUE
write(6,782)
782 format(//1x,' ok 2')
do 321 j=1,np
do 323 i=1,mm
323 a(i,j)=v(i,j)
do 325 it=1,nn
325 rh(it,j)=rh(it,j)/sqrt(ramda(j))
321 continue
do 20 i=1,mm
H(I)=0.0
do 21 j=1,np
21 H(i)=H(i)+A(i,j)**2
20 continue
do 23 i=1,mm
23 h(i)=sqrt(h(i))
do 702 j=1,np
st(j)=0.0
do 703 i=1,mm
703 st(j)=st(j)+a(i,j)**2
702 continue
su=0.0
do 704 j=1,np
704 su=su+st(j)
write(6,801)
801 format(/1x,'Sum of squared element of each colum of the loading
*martix(first NPcolum)')
write(6,805) st
805 format((1x,10f8.3))
write(6,901)
901 format(/1x,'Sum of squared element of first NP colum of loading
&matrix')
write(6,905) su
905 format((1x,f12.3))
! 旋转
do 346 j=1,np
do 346 it=1,nn
346 b(it,j)=rh(it,j)
lll=0
vrlv0=0.0
do 230 k=1,np
g1=0.0
g2=0.0
do 434 i=1,mm
g1=g1+(a(i,k)**2/h(i)**2)**2/real(mm)
434 g2=g2+(a(i,k)**2/h(i)**2)/real(mm)
g2=g2**2
vrlv0=vrlv0+g1-g2
230 continue
800 continue
do 505 t=1,np
do 505 k=1,np
if(t.ge.k) goto 505
call rot(a,b,h,t,k,mm,nn,np,u,vr,wt,wk,wbt,wbk)
505 continue
lll=lll+1
vrlv(lll)=0.0
do 530 k=1,np
g1=0.0
g2=0.0
do 534 i=1,mm
g1=g1+(a(i,k)**2/h(i)**2)**2/real(mm)
534 g2=g2+(a(i,k)**2/h(i)**2)/real(mm)
g2=g2**2
vrlv(lll)=vrlv(lll)+g1-g2
530 continue
if(lll.lt.2) goto 800
ci=(vrlv(lll)-vrlv(lll-1))/vrlv0
if(ci.lt.0.01) goto 600
if(lll.ge.40) goto 600
goto 800
600 continue
write(6,538)
write(6,549)
write(6,539) vrlv0,(vrlv(k),k=1,lll)
538 format(//1x,'Sum of variance of squared element of each colum of
& rotated loding martix ')
549 format(1x,'at each circulation')
539 format((1x,10f8.3))
do 802 j=1,np
st(j)=0.0
do 803 i=1,mm
803 st(j)=st(j)+a(i,j)**2
802 continue
su=0.0
do 804 j=1,np
804 su=su+st(j)
write(6,701)
701 format(/5x,'Sum of squared element of each of the first NP rotated
* loading vector')
write(6,805) st
write(6,472)
472 format(/1x,'Sum of squared element of rotated loading matrix')
write(6,905) su
call change(a,vs,mask,mm,m1,np)
! 旋转后的特征向量
do 961 j=1,np
write(IOUT1,117) j,(vs(i,j),i=1,M1)
irec=10+j
961 write(IOUT2,rec=irec) (vs(i,j),i=1,M1)
117 format(1x,'ROTATED LOADING VECTOR (RLV)',i3,4(/1x,21f6.2))
!旋转后主成分的时间系数
do 906 j=1,np
write(IOUT1,127) j,(b(i,j),i=1,NN)
irec=10+j
906 write(IOUT3,rec=irec) (b(i,j),i=1,NN)
127 format(/1x,'the rotated coefficient (RPC)',i3,10(/1x,18f7.2))
!!!未旋转和旋转后的主成分之间的相关系数矩阵
do 945 i=1,np
do 945 j=1,np
do 966 it=1,nn
x(it)=rh(it,i)
966 y(it)=b(it,j)
945 rc(i,j)=sokan(nn,x,y)
write(6,888)
888 format(//1X,'The correlation coefficients martix between unrotated
* PC and rotated PC')
do 977 i=1,np
977 write(6,988) (rc(i,j),j=1,np)
988 format((1X,12f6.2))
close(6)
stop
end
c****************************************************************************
c求两个序列之间的相关系数
function sokan(n,xx,yy)
dimension xx(n),yy(n)
sx=0.0
sy=0.0
sxy=0.0
sxx=0.0
syy=0.0
do 10 i=1,n
sx=sx+xx(i)
sy=sy+yy(i)
sxy=sxy+xx(i)*yy(i)
sxx=sxx+xx(i)**2
syy=syy+yy(i)**2
10 continue
fn=real(n)
xmean=sx/fn
ymean=sy/fn
sokan=(sxy-fn*xmean*ymean)/
1(sqrt(sxx-fn*xmean**2)*sqrt(syy-fn*ymean**2))
return
end
c****************************************************************************
subroutine rot(a,b,h,t,k,mm,nn,np,u,vr,wt,wk,wbt,wbk)
dimension A(mm,mm),B(nn,np),H(mm),U(mm),VR(mm),WT(mm),WK(mm),
1WBT(nn),WBK(nn)
integer t,k
do 25 i=1,mm
u(i)=(a(i,t)/h(i))**2-(a(i,k)/h(i))**2
25 vr(i)=2.0*(a(i,t)/h(i))*(a(i,k)/h(i))
c=0.0
d=0.0
s=0.0
g=0.0
do 30 i=1,mm
c=c+(u(i)**2-vr(I)**2)
d=d+2.0*u(i)*vr(i)
s=s+u(i)
30 g=g+vr(i)
tg1=d-2.0*s*g/mm
tg2=c-(s**2-g**2)/mm
fi=atan2(tg1,tg2)/4.0
do 75 i=1,mm
wt(i)=a(i,t)
75 wk(i)=a(i,k)
do 84 kk=1,nn
wbt(kk)=b(kk,t)
84 wbk(kk)=b(kk,k)
do 78 i=1,mm
a(i,t)=wt(i)*cos(fi)+wk(i)*sin(fi)
78 a(i,k)=wt(i)*(-sin(fi))+wk(i)*cos(fi)
do 89 it=1,nn
b(it,t)=wbt(it)*cos(fi)+wbk(it)*sin(fi)
89 b(it,k)=wbt(it)*(-sin(fi))+wbk(it)*cos(fi)
return
end
c**************************************************************************
subroutine jcb1(n,a,s)
dimension a(n,n),s(n,n)
do 20 i=1,n-1
w=a(i,i)
k=i
do 30 j=i+1,n
if(a(j,j).le.w) go to 30
W=A(J,J)
K=J
30 CONTINUE
A(K,K)=A(I,I)
A(I,I)=W
DO 70 L=1,N
W1=S(L,I)
S(L,I)=S(L,K)
S(L,K)=W1
70 CONTINUE
20 CONTINUE
RETURN
END
C***************************************************************************
SUBROUTINE JCB(N,A,S,EPS)
DIMENSION A(N,N),S(N,N)
DO 30 I=1,N
DO 30 J=1,I
IF(I-J)20,10,20
10 S(I,J)=1.0
GO TO 30
20 S(I,J)=0.0
S(J,I)=0.0
30 CONTINUE
G=0.0
DO 40 I=2,N
I1=I-1
DO 40 J=1,I1
40 G=G+2.0*A(I,J)*A(I,J)
S1=SQRT(G)
S2=EPS/FLOAT(N)*S1
S3=S1
L=0
50 S3=S3/FLOAT(N)
60 DO 130 IQ=2,N
IQ1=IQ-1
DO 130 IP=1,IQ1
IF(ABS(A(IP,IQ)).LT.S3) GO TO 130
L=1
V1=A(IP,IP)
V2=A(IP,IQ)
V3=A(IQ,IQ)
U=0.5*(V1-V3)
IF(U.EQ.0.0) G=1.
IF(ABS(U).GE.1E-10) G=-SIGN(1.,U)*V2/SQRT(V2*V2+U*U)
ST=G/SQRT(2.*(1.+SQRT(1.-G*G)))
CT=SQRT(1.-ST*ST)
DO 110 I=1,N
G=A(I,IP)*CT-A(I,IQ)*ST
A(I,IQ)=A(I,IP)*ST+A(I,IQ)*CT
A(I,IP)=G
G=S(I,IP)*CT-S(I,IQ)*ST
S(I,IQ)=S(I,IP)*ST+S(I,IQ)*CT
110 S(I,IP)=G
DO 120 I=1,N
A(IP,I)=A(I,IP)
120 A(IQ,I)=A(I,IQ)
G=2.*V2*ST*CT
A(IP,IP)=V1*CT*CT+V3*ST*ST-G
A(IQ,IQ)=V1*ST*ST+V3*CT*CT+G
A(IP,IQ)=(V1-V3)*ST*CT+V2*(CT*CT-ST*ST)
A(IQ,IP)=A(IP,IQ)
130 CONTINUE
IF(L-1)150,140,150
140 L=0
GOTO 60
150 IF(S3.GT.S2)GOTO 50
RETURN
END
C***************************************************************************
SUBROUTINE CHANGE(V,VS,MASK,I,I1,J)
REAL V(I,I),VS(I1,J)
integer MASK(I1)
DO 999 JJ=1,J
NO=0
DO 998 II=1,I1
IF(MASK(II).EQ.1) THEN
NO=NO+1
VS(II,JJ)=V(NO,JJ)
ELSE
VS(II,JJ)=99.9
ENDIF
998 CONTINUE
WRITE(*,*) 'NO=',NO,'I=',I
999 CONTINUE
RETURN
END
|
|