| 
 
	积分1807贡献 精华在线时间 小时注册时间2013-3-19最后登录1970-1-1 
 | 
 
 
 楼主|
发表于 2017-5-1 20:06:48
|
显示全部楼层 
|  !!---------------------------------------------------------------------------!
!!输入的有:                                                                  !
!!    1.RH(nn,mm),需作旋转EOF的矩阵,注意nn代表时间,mm代表站点或格点;         !
!!    2.NP(整型):需要作旋转EOF的特征向量的个数;(一般对RH作EOF后由一定        !
!!               的规则来确定;                                               !
!!输出的有:                                                                  !
!!    1.对RH作EOF的特征值和方差贡献;                                         !
!!    2.对RH作EOF的特征向量和时间系数;                                       !
!!    3.选择前NP个特征向量作旋转EOF的特征向量和时间系数;                     !
!!    4.旋转前后主分量的相关矩阵;                                            !
!!---------------------------------------------------------------------------!
      PROGRAM reof
      parameter(nn=24,mm=98)
      parameter(np=13)
      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),MX(mm),XW(mm),RR(np,np),ST(np)          
      DIMENSION U(mm),VR(mm),WT(mm),WK(mm),WBT(nn),WBK(nn)
      DIMENSION VRLV(60)
      INTEGER T,K
!  数组Mx、rh、lat、lon都是实型数组
      REAL MX,rh
        real lat(mm),lon(mm)
        real zero(nn)
        real stid(mm,2)
        character*8 id(mm)
        data zero/nn*0.0/ 
       OPEN(12,FILE='result_of_reof.txt')  !旋转EOF的结果输出
       OPEN(11,file='nation.txt')
        OPEN(14,file='sta.grd',status='replace',form='binary')!REOF的结果sta.grd输出
    open(444,file='sjxs.grd',status='replace',form='binary')
    open(888,file='tzxl.txt',status='replace')
!  按站点读取原始资料
      do i=1,mm
        read(11,*)(rh(it,i),it=1,nn) 
         end do
        close(11)
        print*,rh
        OPEN(13,file='lat_lon.txt')!lat lon
        do i=1,mm
        read(13,*)(stid(i,j),j=1,2)
        enddo
        do i=1,mm
        write(*,*)(stid(i,j),j=1,2)
        enddo
!682   format(1x,'original data')                               !                           !
        CALL STANDARD(NN,MM,RH)
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!       原始资料                                                          c
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCccccccccccccccccccccccccccccccccccCCCCC
!ccc        !输出原始资料的标准化资料
        open(16,file='bzh.txt')  
        do   786 i=1,nn
!        write(12,683) j
   786  write(16,1686) (rh(i,j),j=1,mm)
1686    format(98f6.2)                            !按格点数目改动
!cccccccccccccccccccccccccccccccccccccccc
      rnn=real(nn)
      DO 12 J=1,mm
      DO 12 J1=1,mm
        A(J,J1)=0.0
        DO 13 I=1,nn
 13     A(J,J1)=A(J,J1)+RH(I,J)*RH(I,J1)/rnn
 12   continue
      write(12,101)
      write(12,102) ((A(i,j),j=1,mm),i=1,mm)
101   format(/1x,'原始资料的相关矩阵A')
102   format((1X,98f6.2))                       !按格点数目改动
      sum=0.0         
      do 80 k=1,mm
          sum=sum+A(k,k)
80        continue
      write(12,103) sum
 103  format(1x,' 相关矩阵A的维数 ==',f15.4)
      call jcb(mm,a,v,0.00001)
      call jcb1(mm,a,v)
      write(12,104)
      write(12,204)(a(i,i),i=1,mm)
 104  format(//1x,' Eigenvalue(lambad)特征值')
 204  format((1x,4f20.12))
      do 145 i=1,mm
 145  ramda(i)=a(i,i)
!      write(12,104) ramda
      sum2=0.0
      do 222 k=1,mm
 222  sum2=sum2+A(k,k)
      write(12,106) sum2
      write(12,909)
909   format(/3x,'特征值的总和必须等于相关矩阵A的维数!')
      err=abs(sum-sum2)
      if(err.lt.0.001) write(12,681) err
      if(err.ge.0.001) write(12,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(12,108)
      write(12,208) mx
 108  format(//1x,'The percentage of lambad 解释方差')
 208  format((1x,10f8.2))
      do 112 j=1,np
      write(12,110) j
!        write(*,'(10f8.3)')(v(i,j),i=1,mm)
 112  write(12,210) (v(i,j),i=1,mm)
 110  format(1x,'旋转前的特征向量或荷载.order:',I3)
 210  format((1x,10f8.3))
      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(12,125) j
400   write(12,805) (rh(i,j),i=1,nn)
    !  open(33,file='unrottzxl.grd',form='binary')
    !  open(44,file='unrotsjxs.grd',form='binary')
    !  open(55,file='unrottzxl.txt')
!! 下面是按GrADs站点资料的方式存取
!        tim=0.0
!        do 97, i=1,mm
!        id(i)=char(i)
!        lat(i)=stid(i,1)  !!!纬度 第一列
!        lon(i)=stid(i,2)  !!!经度 第二列
!        tim=0.0
!        nlev=1
!        nflag=1
!        write(33)id(i),lat(i),lon(i),tim,nlev,nflag,(v(i,j),j=1,np)
!97        continue        
!        nlev=0
!        write(33)id(i-1),lat(i-1),lon(i-1),tim,nlev,nflag
!        do i=1,mm
!        write(55,'(i8,28f8.3)')i,lat(i),lon(i),(v(i,j),j=1,np)
!        enddo
!        write(44)((rh(i,j),j=1,np),zero(i),i=1,nn)
!        close(13)
!        close(33)
!        close(44)
!        close(55)
!ccccccccccccccccccccccccccccccccccccccc
!      未旋转前时间系数                C
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
       open(18,file='unrot_time.txt')
       do   787 i=1,nn
 787   write(18,1688)i+1950,(rh(i,j),j=1,np)
1688   format(i4,10f8.3)
!cccccccccccccccccccccccccccccccccccccccc
125    format(/1x,'旋转前的时间系数(PC).order',i3)
       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(12,982)
!  按站输出重构的资料序列
       do   986 j=1,mm
       write(12,683) j
 986  write(12,686) (reco(i,j),i=1,nn)
982   format(/1x,'Reconstructed data(for inspect)   ')
683   format(1x,'Number station',i3)                          
686   format((1x,10f8.2))                          
      write(12,238)
 238  format(//3x,'To inspect perpendicularty and variance of PC')
      write(12,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(12,266) (rr(j1,j2),j2=1,np)
 266  format(3x,10f8.3)
      write(12,269)
      write(12,469)
      write(12,669)
      write(12,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.')
! 以下就是因子分析和旋转主成分分析部分
!
!cccccccccccccccccccccccccccccccc 
      DO 333 J=1,np
      DO 333 I=1,mm
      V(I,J)=V(I,J)*SQRT(RAMDA(J))
 333  CONTINUE
      write(12,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(12,801)
 801  format(/1x,'Sum of squared element of each colum of the loading martix(first NPcolum)')
      write(12,805) st
 805  format((1x,10f8.3))
      write(12,901)
 901  format(/1x,'Sum of squared element of first NP colum of loading matrix')
      write(12,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.52) goto 600
      goto 800
 600  continue
      write(12,538)
      write(12,549)
      write(12,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(12,701)
 701  format(/5x,'Sum of squared element of each of the first NP rotated loading vector')
      write(12,806) st
 806  format((1x,10f12.5))
      write(12,472)
 472  format(/1x,'Sum of squared element of rotated loading matrix')
      write(12,806) su
      do 971 j=1,np
      write(12,117) j
 971  write(12,805) (a(i,j),i=1,mm)
 117  format(1x,'旋转后的荷载(ROTATED LOADING VECTOR,简称RLV) ordre:',i3)
     
!ccccccccccccccccccccccccccccccccccccccccc
!      旋转后时间系数                    C                   
!CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
       open(2,file='rot_time.txt')
         do 401 i=1,nn
           write(2,809)(b(i,j),j=1,np)
401         continue
809    format(10f8.3)
       close(2)
         close(18)
       do 906 j=1,np
      write(12,127) j
 906  write(12,805) (b(i,j),i=1,nn)
 127  format(/1x,'旋转主分量(RPC).order:',i3)
      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(12,888)
888   format(//1X,'旋转前后主分量的相关距阵')
      do 977 i=1,np
 977  write(12,988) (rc(i,j),j=1,np)
!cccccccccc
 988  format((1X,10f6.2))
      close(12)
! 下面是按GrADs站点资料的方式存取
    tim=0.0
        do 100 i=1,mm
        id(i)=char(i)
        lat(i)=stid(i,1)  !!!纬度 第一列
        lon(i)=stid(i,2)  !!!经度 第二列
        tim=0.0
        nlev=1
        nflag=1
        write(14)id(i),lat(i),lon(i),tim,nlev,nflag,(a(i,j),j=1,np)
100        continue        
        nlev=0
        write(14)id(i-1),lat(i-1),lon(i-1),tim,nlev,nflag
        do i=1,mm
        write(888,'(i8,28f8.3)')i,lat(i),lon(i),(a(i,j),j=1,np)
        enddo
        write(444)((b(i,j),j=1,np),zero(i),i=1,nn)
        close(13)
        close(444)
        close(14)
        close(888)
    end
!cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
!****************************************************************************
      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)/(sqrt(sxx-fn*xmean**2)*sqrt(syy-fn*ymean**2))
      return
      end
!****************************************************************************
      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),WBT(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
!**************************************************************************
! m是站点数目
      subroutine jcb1(m,a,s)
      dimension a(m,m),s(m,m)
      do 20 i=1,m-1
      w=a(i,i)
      k=i
      do 30 j=i+1,m
      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,m
      W1=S(L,I)
      S(L,I)=S(L,K)
      S(L,K)=W1
 70   CONTINUE
 20   CONTINUE
      RETURN
      END
!***************************************************************************
      SUBROUTINE JCB(M,A,S,EPS)
      DIMENSION A(M,M),S(M,M)
      DO 30 I=1,M
      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,M
      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(M)*S1
      S3=S1
      L=0
 50   S3=S3/FLOAT(M)
 60   DO 130 IQ=2,M
      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,M
      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,M
      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
!*************************************************************************
        subroutine standard(n,m,x)   !m为格点数,n为时间长度
        dimension x(n,m)
        do j=1,m
          ave=0.0
          do i=1,n
            ave=ave+x(i,j)/float(n)
          enddo
          xigma=0.0
          do i=1,n
            xigma=xigma+(x(i,j)-ave)**2/float(n)
          enddo
          xigma=sqrt(xigma)
          do i=1,n
            x(i,j)=(x(i,j)-ave)/xigma
          enddo
        enddo
        end
 | 
 |