加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[转载]常用气象数据插值(1)

(2012-03-09 17:13:17)
标签:

转载

分类: 气象
 首先感谢武大毕业的尹雄锐博士提供的程序.

ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
  本程序用于2001年气象数据空间插值
           2006-9-28
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
 
  parameter(n_sta=35,n=365,nn=1,n_pix=584915)
n---一年的总天数  nn---需要插值的天数
  dimension elev_sta(n_sta),temp_sta(n,n_sta)
  real mxtemp_sta(n,n_sta),mntemp_sta(n,n_sta)
  dimension vpre_sta(n,n_sta),suntime_sta(n,n_sta)
  dimension wind_sta(n,n_sta),p_sta(n,n_sta)
   character*50  No_sta(n_sta),Name_sta(n_sta),Name_prov,temps

n_sta----------------------气象站站点数
NO_sta---------------------气象站号
elev_sta-------------------气象站高程
temp_sta-------------------气象站气温
mxtemp_sta,mntemp_sta------气象站最高、最低气温
vpre_sta-------------------气象站水气压
suntime_sta----------------气象站日照时数
wind_sta-------------------气象站风速
     P_sta----------------------气象站降雨
Name_sta,Name_prov---------气象站站名和所在省名

  dimension cor_x(n_sta),cor_y(n_sta)
  integer year(n,n_sta),month(n,n_sta),day(n,n_sta)
cor_x,cor_y ---------气象站经纬度坐标
    
  dimension x(n_pix),y(n_pix),dem(n_pix)
x,y---------网格投影坐标(单位:米)
dem----------网格高程
  integer ye(nn),mo(nn),da(nn)
插值日期
  dimension x0(n_sta),y0(n_sta)
x0,y0---------气象站投影坐标(Alberes,WGS84)

  real temperature(n_sta),mxtemp(n_sta),mntemp(n_sta)
  dimension vpre(n_sta),suntime(n_sta),wind(n_sta),p(n_sta)
  dimension Vpre_out(n_pix),wind_out(n_pix),suntime_out(n_pix)
  dimension  temperature_out(n_pix),P_out(n_pix)
  real lanbuda,Ning

读入气象站点各项数据
       open(1,file='2001.txt',status='old')
       read(1,*)
  do i=1,n_sta
    do j=1,n
       read(1,*)NO_sta(i),cor_x(i),cor_y(i),Name_sta(i),Name_prov,temp1,
     $ elev_sta(i),temp2,temps,temp3,temp4,temp5,temp6,temp7,temp8,
     $ year(j,i),month(j,i),day(j,i),temp9,temp_sta(j,i),
     $ mxtemp_sta(j,i),mntemp_sta(j,i),
     $ vpre_sta(j,i),temp10,temp11,wind_sta(j,i),p_sta(j,i),
     $ temp12,suntime_sta(j,i)
    enddo
  enddo
  close(1)
do i=1,n_sta
write(*,*)cor_x(i),cor_y(i)
enddo

     读入栅格坐标
  open(2,file='coordinate.txt',status='old')
  do i=1,n_pix
   read(2,*) x(i),y(i),dem(i)
  enddo
  close(2)

输入日期
  open(3,file='input_data.txt',status='old')
  do i=1,nn
  read(3,*)ye(i),mo(i),da(i)
  enddo
  close(3)
 
open(211,file='wind.txt')
open(333,file='relation.txt')
找出该天的所有气象站点的数据并进行插值
  do ii=1,1  !nn
   
    !挑出当天各站的气象数据
    do i=1,n_sta
      do j=1,n
    if(year(j,i).eq.ye(ii).and.month(j,i).eq.mo(ii).
      and.day(j,i).eq.da(ii))then
       temperature(i)=temp_sta(j,i)*0.1      !0.1--scale factor
       mxtemp(i)=mxtemp_sta(j,i)*0.1
    mntemp(i)=mntemp_sta(j,i)*0.1
       vpre(i)=vpre_sta(j,i)*0.1
    suntime(i)=suntime_sta(j,i)*0.1
    wind(i)=wind_sta(j,i)*0.1
      降雨对前五天累计进行插值,要保证j>5,否则不行
    p(i)=0.0
    do kk=1,5
     if(P_sta(j-kk,i).gt.3000) P_sta(j-kk,i)=0.0
     p(i)=p(i)+P_sta(j-kk,i)*0.1
    enddo
         
       endif
      enddo

 write(*,*)temperature(i),vpre(i),suntime(i),P(i)

write(333,*)elev_sta(i),suntime(i)*0.1

  ! 找出各气象站点的风速,不插值
      lanbuda=cor_x(i)
    fi=cor_y(i)
 write(*,*)lanbuda,fi,wind(i)
   call proj(lanbuda,fi,Eing,Ning)
      x0(i)=Eing
   y0(i)=Ning
 
    write(211,212)lanbuda*180/3.141593,fi*180/3.141593,x0(i)
    $,y0(i),wind(i),name_sta(i)
c212 format(2(1x,f10.4),2(1x,f10.1),3x,f4.1,2x,a20)
  enddo
close(211)

 do i=1,n_pix
   wind_out(i)=-10.0
   do j=1,n_sta
  if(abs(x(i)-x0(j)).le.500.and.abs(y(i)-y0(j)).le.500) then
    wind_out(i)=wind(j)
   write(*,*) 'find',j,wind_out(i)
  endif
   enddo
 enddo


  !------------------------------------------------------------------
  ! 对网格点插值
     ! 水汽压插值,对高程有明显的趋势,随高程指数下降
  do i=1,n_sta
       vpre(i)=vpre(i)*10**(elev_sta(i)/5000.0)
  enddo

  call DDWA(x0,y0,vpre,n_sta,x,y,n_pix,vpre_out)

  do i=1,n_pix
    if(dem(i).eq.-32768)then
   vpre_out(i)=-999
       else 
      vpre_out(i)=vpre_out(i)*10**(-dem(i)/5000.0)
    endif
  enddo

  !------------------------------------------------------------------
  ! 风速插值,对比高程和风速没有明显的趋势
 call DDWA(x0,y0,wind,n_sta,x,y,n_pix,wind_out)

 

  !-------------------------------------------------------------------
  ! 太阳日照时数插值, 对高程没有趋势
  call DDWA(x0,y0,suntime,n_sta,x,y,n_pix,suntime_out)


  !-------------------------------------------------------------------
  ! 气温插值,需要将气象站高度订正到同一平面再插值,然后网格再算回去
     do i=1,n_sta
       offset=elev_sta(i)/100.0*0.6   !海拔每上升100米,气温平均下降0.6度
    temperature(i)=temperature(i)+offset
     enddo

  call DDWA(x0,y0,temperature,n_sta,x,y,n_pix,temperature_out)
  
  do i=1,n_pix
    if(dem(i).eq.-32768)then
   temperature_out(i)=-999
       else 
   offset=dem(i)/100*0.6
      temperature_out(i)=temperature_out(i)-offset
    endif
  enddo
c
  !------------------------------------------------------------------------
   ! 降雨插值
  call DDWA(x0,y0,P,n_sta,x,y,n_pix,P_out)

  do i=1,n_pix
    if(dem(i).eq.-32768)then
   p_out(i)=-999
       else 
      p_out(i)=p_out(i)
    endif
  enddo
  !------------------------------------------------------------------------

     open(4,file='Vpre.txt')
     do i=1,n_pix
          write(4,111)x(i),y(i),Vpre_out(i)
111  format(1x,f10.1,1x,f10.1,1x,f10.3)
     enddo
     close(4)

     open(5,file='Wind.txt')
     do i=1,n_pix
          write(5,112)x(i),y(i),wind_out(i)
112  format(1x,f10.1,1x,f10.1,1x,f10.3)
     enddo
     close(5)

  open(6,file='suntime.txt')
     do i=1,n_pix
      if(dem(i).eq.-32768) then
    suntime_out(i)=-999
   else
    suntime_out(i)=suntime_out(i)
   endif
          write(6,113)x(i),y(i),suntime_out(i)
113  format(1x,f10.1,1x,f10.1,1x,f10.3)
     enddo
     close(6)

  open(7,file='Temperature.txt')
     do i=1,n_pix
          write(7,114)x(i),y(i),Temperature_out(i)
114  format(1x,f10.1,1x,f10.1,1x,f10.3)
     enddo
     close(7)

  open(8,file='precipitation.txt')
     do i=1,n_pix
          write(8,115)x(i),y(i),P_out(i)
115  format(1x,f10.1,1x,f10.1,1x,f10.3)
     enddo
     close(8)


  enddo

 end

 


ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
该子程序用于将点的经纬度坐标转化为Albers的投影坐标,用于将气象站的经纬度转化为米
     经纬度为度的形式,非度分秒形式
取中国区的参数为:fi1-------第一标准纬度25
                   fi2-------第二标准纬度47
                   lanbuda0--中央经线105
                       fi0-------中央纬线0
                   EF--------东偏0,单位:米
                       NF--------北偏0,单位:米
     WGS84椭球体参数       长半轴a=6378137
                           短半轴b=6356752.3142
     Karasovsky椭球体参数  长半轴a=6378245
                           短半轴b=6356863.0188
偏心率e=SQRT(2f-f^2),1/f=a/(a-b)                    
cc     这里采用WGS84

  subroutine proj(lanbuda,fi,Eing,Ning)
  输入(地理经纬度)lanbuda------精度
                        fi-----------纬度
      输出(投影坐标m) Eing---------东的坐标
                        Ning---------北的坐标
  real lanbuda,lanbuda0,NF,m1,m2,n,Ning 
  pi=4*atan(1.0)
       fi0=0*pi/180
  lanbuda0=105*pi/180
  fi1=25*pi/180
  fi2=47*pi/180
  EF=0
  NF=0

  fi=fi*pi/180
  lanbuda=lanbuda*pi/180
 
  a=6378137
  b=6356752.3142
       e1=SQRT(1-b/a*b/a)
  e2=1-e1*e1

  alfa=e2*(sin(fi)/(1-e1*e1*sin(fi)*sin(fi))-0.5/e1
        *log((1-e1*sin(fi))/(1+e1*sin(fi))))
       alfa0=e2*(sin(fi0)/(1-e1*e1*sin(fi0)*sin(fi0))-0.5/e1
         *log((1-e1*sin(fi0))/(1+e1*sin(fi0))))
       alfa1=e2*(sin(fi1)/(1-e1*e1*sin(fi1)*sin(fi1))
         -0.5/e1*log((1-e1*sin(fi1))/(1+e1*sin(fi1))))
       alfa2=e2*(sin(fi2)/(1-e1*e1*sin(fi2)*sin(fi2))
         -0.5/e1*log((1-e1*sin(fi2))/(1+e1*sin(fi2))))
       m1=cos(fi1)/sqrt(1-e1*e1*sin(fi1)*sin(fi1))
       m2=cos(fi2)/sqrt(1-e1*e1*sin(fi2)*sin(fi2))
       n=(m1*m1-m2*m2)/(alfa2-alfa1)
       C=m1*m1+n*alfa1
       rou0=a*sqrt(C-n*alfa0)/n
       rou=a*sqrt(C-n*alfa)/n
       sita=n*(lanbuda-lanbuda0)

  Eing=EF+rou*sin(sita)
       Ning=NF+rou0-rou*cos(sita)
  return
       end
 
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
该子程序采用距离方向加权平均法进行空间插值
x0,y0---------气象站点坐标,n0-----站数(站号)
     x1,y1---------待求点坐标
P-------------气象站实测值
     P-out---------点插值结果
dis(j)--------与第j个站的距离
cc
  subroutine DDWA(x0,y0,p,n0,x1,y1,n1,P_out)
  dimension x0(n0),y0(n0),x1(n1),y1(n1)
  dimension P(n0),P_out(n1)
  dimension dis(n0),num(n0),w(n0),alf(n0)

通过最近8个站计算每个目标点的值
  do i=1,n1
      do j=1,n0
        dis(j)=sqrt((x1(i)-x0(j))*(x1(i)-x0(j))
        +(y1(i)-y0(j))*(y1(i)-y0(j)))
   if(dis(j).eq.0) then
     P_out(i)=p(j)
     goto 33
   endif
      enddo

     
    !找出最近的8个站及其与待求点的距离
       do j=1,n0
        num(j)=j
       enddo

   do ii=1,8
         s=1000000000
        do j=ii+1,n0 
         if(dis(j).lt.s) then
    s=dis(j)
          k=j
         endif
        enddo
    if(s.lt.dis(ii))then
        dis(k)=dis(ii)
     dis(ii)=s
   tempk=num(ii)
   num(ii)=num(k)
   num(k)=tempk
     endif  
      enddo
    
       !计算权重距离
       dis0=dis(8)             !取8个最远的点的距离(经验衰减距离)
       do j=1,8
   w(j)=(exp(-dis(j)/dis0))**4.0
    enddo

    !计算方向修正系数
   do j=1,8
   s1=0
   s2=0
     do l=1,8
   s1=s1+w(l)
   d=SQRT((x0(num(j))-x0(num(l)))**2
     +(y0(num(j))-y0(num(l)))**2)
   cos=(dis(j)*dis(j)+dis(l)*dis(l)-d*d)/(2*dis(j)*dis(l))
   s2=s2+w(l)-w(l)*cos
        enddo
   alf(j)=s2/s1
   enddo

   !计算总修正权重
   do j=1,8
    w(j)=w(j)*(1+alf(j))
   enddo

   !计算目标点值
   s1=0
   s2=0
   do j=1,8
      s1=s1+w(j)*P(num(j))
    s2=s2+w(j)
   enddo
   P_out(i)=s1/s2
33  enddo
  return
  end

ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
      该子程序采用修正距离倒数平方法
x0,y0---------气象站点坐标,n0-----站数(站号)
     x1,y1---------待求点坐标
dem-----------待求点高程 
P-------------气象站实测值
     P-out---------点插值结果
dis(j)--------与第j个站的距离
cc
  subroutine MIDW(x0,y0,elev_sta,p,n0,x1,y1,dem,n1,P_out)
  dimension x0(n0),y0(n0),elev_sta(n0),x1(n1),y1(n1),dem(n1)
  dimension P(n0),P_out(n1)
  dimension dis(n0),alf(n0)

  b=-2                   ! b是权重指数,一般情况下取负值
  do i=1,n1
 
  ss=0.0
     do j=1,n0
    de=abs(dem(i)-elev_sta(j))
    if(de.eq.0) de=1
   de=1       !如果de=1,则变为距离倒数平方法
       dis(j)=SQRT((x1(i)-x0(j))**2+(y1(i)-y0(j))**2)
       if(dis(j).eq.0)then
         P_out(i)=p(j)
   goto 440
     endif
    dis(j)=(dis(j)/de)**b
    ss=ss+dis(j)
   enddo
 
  do j=1,n0
      alf(j)=dis(j)/ss
 write(*,*)alf(j)
   p_out(i)=p_out(i)+alf(j)*p(j)
  enddo
440 enddo
 return
 end

0

  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有