song.yz@foxmail.com wechat: math-box

blog



美国广域增强系统的电离层算法



WAAS(Wide Area Augmentation System)是由美国联邦航空局开发建立的用于空中导航的一个系统, 该系统主要是通过解决广域差分GPS的数据通信问题从而提高全球定位系统的精度和可用性。

美国联邦航空主管机关(FAA)及交通部是WAAS程序的发展者, 并应用于精准的航空器入场之用。 一般的GPS并不具有接收FAA的系统能力,WAAS是分析电离层的干扰所导致的讯号时差,及计算卫星轨道误差值来校正GPS讯号的, 并提供每一个卫星状况的重要数据,虽然WAAS还没有被航空界认证,这个系统还是可供给一般民众使用,如船舶及平常的GPS用户。

WAAS(图片来自网络)



WAAS由约25个地面参考站台所组成,位置横跨整个美国。它们监看着卫星的数据。 其中两个主要的站台,位于两岸,从各参考站台收集校正讯号并建立校正信息。 这些信息根据卫星的轨道误差,卫星上的电子钟误差,以及由于大气及电离层所造成的讯号延迟。 这些数据经计算校正之后再经由一个或两个地球同步卫星传播,或是轨道固定在赤道上空的卫星。 这些信息的结构是完全兼容于基本的GPS讯号,这意味着任何其有WAAS启始的GPS接收机将能解读这种讯号。

其中电离层改正是WAAS系统的一项重要内容,这里编写了WAAS系统电离层算法,仅供参考。

定义模块

  
module  iono_grid
!----------------------------------------module coment
!  Version     :  V1.0    
!  Coded by    :  song.yz
!  Date        :  2014-03-04 16:20:31          *星期二*
!-----------------------------------------------------
!  Description :    
!                  data structureof Grid point
!-----------------------------------------------------

implicit real*8(a-h,o-z)
save

!-----------data structure of Grid piont
type gridpoint      !structure of one point
  real*8::xlong     !geographic longitude  (unit: degree)
  real*8::xlat      !geographic latitude  (unit: degree)
end type gridpoint

type (gridpoint):: grid(202,0:10)
!------------------------------------


!-------------------------------------interference for outside

type bandgrid
   type (gridpoint):: apoint(202)
end type bandgrid

type bandsgrid
  type (bandgrid) ::bandpoint(0:10)
end type bandsgrid

!-------------------------------------

end module iono_grid
设置网格
  
subroutine set_grid (grid_out)
!---------------------------------subroutine  comment
!  Purpose   :  set the Grid structure matrix
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-04 16:26:47 
!                
!-----------------------------------------------------
!  Input Parameters    :
!       
!
!  Output Parameters   :
!         
!
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use iono_grid

implicit real*8(a-h,o-z)

type (bandsgrid) :: grid_out

character*20::ckey

open(unit=1001,file='./data/grid.dat',status='old',iostat=ierror)

!write(*,*) 'open grid.data correct ?' ,ierror


do 

   read(1001,*,iostat=ioend) ckey
   if (ioend /= 0)   exit
   ! exit the loop if reach the end of the file

   if (ckey(1:5)=='begin') exit
   ! exit if get the key word of  'begin'

end do

! get the longitude and latitude by reading the file
 
do 
   read(1001,*,iostat=ioend) iband,iindex,xlong,xlat
   if (ioend /= 0)   exit
   !exit  if reach to the end of the file
   !grid(0:10,202)
   grid(iindex,iband)%xlong=xlong
   grid(iindex,iband)%xlat=xlat
   
!   write(*,*) grid(iindex,iband)%xlong
!   write(*,*) grid(iindex,iband)%xlat
!  
end do


!rewind(1001)
close(1001)


!-------------------------output the Grid info.
  do i=0,10
  
     do j=1,202
     
        grid_out%bandpoint(i)%apoint(j)%xlong=grid(j,i)%xlong
        grid_out%bandpoint(i)%apoint(j)%xlat =grid(j,i)%xlat
     end do 
  
  end do 
!-----------------------------------------------

end subroutine set_grid

定义结构体
  
module def_fi
!----------------------------------------module coment
!  Version     :  V1.0    
!  Coded by    :  song.yz
!  Date        :  2014-04-01 09:40:40          *星期二*
!-----------------------------------------------------
!  Description :  
!                  data structure of iono_grid
!  Post Script :
!      1.
!      2. 
!
!-----------------------------------------------------
!  Contains    :
!      *.     
!      *.     
!-----------------------------------------------------

implicit real*8(a-h,o-z)
save
      integer,parameter:: MAX_PIERCE_NO=50000
    
      type ipptype
       sequence
        integer*1:: iflagAB
        integer*1 :: ierr
        integer*1 :: SysType    
        integer*2 :: week
        integer*4 :: sow
        real*8 :: phi
        real*8 :: lam
        real*8 :: IncVtec
        real*8 :: RcIono
        real*8 :: Elevation
        real*8 :: Azimuth
        integer*1 :: stationNo
        integer*1 :: rcvNo
        integer*1 :: satelliteNo
        integer*1 :: choseWN
        integer*1 :: choseB
        real*8::cVtec                
      end type ipptype

      type ipplist
        sequence
         integer*1   :: FlagAB
         integer*4   :: n_pierce  !实际穿刺点个数
         type(ipptype)::pierce(MAX_PIERCE_NO)
      end type ipplist



      type (ipplist) :: ipp
      !所有穿刺点数据结构
!input ---------

! out put-----------

!----------
! the following Data struct are defined by song.yezhi
       type GridData
          integer*4::GridID
          real*8::Delay
          integer*4::GiveI
!          real*8::Give  !defined by song.yz
       end type GridData
      
       type BandData
          integer*1::BandID
          integer*1::Mask(210)   !一个带中的掩码,当Mask(i)=1表示算出了格网点延迟,
                                !等于0表示未算出格网点延迟
          type(GridData)::Grid(210)
       end type BandData

       type IGPlist
         integer*2::Week
         integer*4::Sow
         integer*1::BandNum
         integer*1::SysType
         type(BandData)::GridBand(0:10)
       end type IGPlist

       type (IGPlist) :: iGP
       ! 所有格网点数据结构

end module def_fi
由穿刺点计算延迟
  
subroutine ionogrid(iGP_p,ipp_p,week,sow,Grid_p)
!---------------------------------subroutine  comment
!  Purpose   :  由穿刺点计算格网点延迟及GIVEI
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-04-12 15:26:21 
!           周和秒由外部传入
!             
!       ***   说明:需要配置文件 gird.dat 不能删除 
!            该函数为计算主函数      
!-----------------------------------------------------
!  Input Parameters    :
!       ipp-----------------穿刺点结构体
!       week----------------格网点周
!       sow-----------------格网点秒
!                week 和 sow 由外部传入
!       Grid_p-----------------格网结构
!  Output Parameters   :
!        IGP-----------------格网点结构体
!
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use iono_grid
use def_fi

implicit real*8(a-h,o-z)


real*8,parameter:: Factor = 0.1651d0  
!基于B1频点 TECU 到 长度单位(米) 转换系数

 
 integer *2  week
 integer *4  sow 
 type (Ipplist) :: iPP_p
 type (IGPlist) :: iGP_p
! type (gridpoint) :: Grid_p
! type (bandsgrid) :: grid_p(0:10)
 
 type (bandsgrid) :: grid_p 
   
  
 !type (gridpoint):: grid_song(202,0:10)  
   
  ! Grid=Grid_p 
!该部分由FORTRAN读入,并放在公共内存,这里传回给Grid  
!----------------------------------------------------
   do i=0,10
      do j=1,202
      
        Grid(j,i)%xlong=Grid_p%bandpoint(i)%apoint(j)%xlong
        Grid(j,i)%xlat =Grid_p%bandpoint(i)%apoint(j)%xlat
              
      end do  
   end do
!-----------------------------------------------------   

   
   !------------------
   ipp=ipp_p
    
   ipp%pierce(:)%IncVtec=ipp%pierce(:)%IncVtec*Factor 
   
   !单位化为米 
   !在整个ionoGrid数据处理内部,VTEC都化为等效的长度单位
        
   !------------------

!   call test
   !输出中间结果


   IGP%BandNum=11
   !总带数
   IGP%SysType=2
   !1为1期,2为试验,3为全球
   IGP%week=week
   IGP%sow=sow

   

  ! call IGP_delay_give
   
   call IGP_delay_givei
 

   do i=0,10

     IGP%GridBand(i)%BandID=i
     !带号
     do j=1,210
       
       iGP%GridBand(i)%Grid(j)%GridID=j
       !格网点编号
     end do

   end do 

   !-------
     
     iGP_P=iGP
     ipp_p=ipp
   !-------



   return


end subroutine ionoGrid
  
subroutine ionogrid(iGP_p,ipp_p,week,sow,Grid_p)
!---------------------------------subroutine  comment
!  Purpose   :  由穿刺点计算格网点延迟及GIVEI
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-04-12 15:26:21 
!           周和秒由外部传入
!             
!       ***   说明:需要配置文件 gird.dat 不能删除 
!            该函数为计算主函数      
!-----------------------------------------------------
!  Input Parameters    :
!       ipp-----------------穿刺点结构体
!       week----------------格网点周
!       sow-----------------格网点秒
!                week 和 sow 由外部传入
!       Grid_p-----------------格网结构
!  Output Parameters   :
!        IGP-----------------格网点结构体
!
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use iono_grid
use def_fi

implicit real*8(a-h,o-z)


real*8,parameter:: Factor = 0.1651d0  
!基于B1频点 TECU 到 长度单位(米) 转换系数

 
 integer *2  week
 integer *4  sow 
 type (Ipplist) :: iPP_p
 type (IGPlist) :: iGP_p
! type (gridpoint) :: Grid_p
! type (bandsgrid) :: grid_p(0:10)
 
 type (bandsgrid) :: grid_p 
   
  
 !type (gridpoint):: grid_song(202,0:10)  
   
  ! Grid=Grid_p 
!该部分由FORTRAN读入,并放在公共内存,这里传回给Grid  
!----------------------------------------------------
   do i=0,10
      do j=1,202
      
        Grid(j,i)%xlong=Grid_p%bandpoint(i)%apoint(j)%xlong
        Grid(j,i)%xlat =Grid_p%bandpoint(i)%apoint(j)%xlat
              
      end do  
   end do
!-----------------------------------------------------   

   
   !------------------
   ipp=ipp_p
    
   ipp%pierce(:)%IncVtec=ipp%pierce(:)%IncVtec*Factor 
   
   !单位化为米 
   !在整个ionoGrid数据处理内部,VTEC都化为等效的长度单位
        
   !------------------

!   call test
   !输出中间结果


   IGP%BandNum=11
   !总带数
   IGP%SysType=2
   !1为1期,2为试验,3为全球
   IGP%week=week
   IGP%sow=sow

   

  ! call IGP_delay_give
   
   call IGP_delay_givei
 

   do i=0,10

     IGP%GridBand(i)%BandID=i
     !带号
     do j=1,210
       
       iGP%GridBand(i)%Grid(j)%GridID=j
       !格网点编号
     end do

   end do 

   !-------
     
     iGP_P=iGP
     ipp_p=ipp
   !-------



   return


end subroutine ionoGrid
计算格网点延迟
  
subroutine  IGP_delay_givei
!---------------------------------subroutine  comment
!  Purpose   :  计算格网点的delay及giveI
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-04-14 02:10:42 
!                  
!-----------------------------------------------------
use def_fi
implicit real*8(a-h,o-z)

integer::ippband(ipp%n_pierce+1,0:10)


 call ipp2band(ippband,ipp%n_pierce)

!把穿刺点分到各个带中
!ippband记录各个带中穿刺点序号


 call IGP_delay(ippband) 
!由穿刺点计算格网点延迟

!call IPP_cVtec(ippband)
 call IPP_cVTEC
!由格网点反算穿刺点延迟


 call  IGP_delay1(ippband)
!第二次计算,已经剔除了穿刺点VTEC与CVTEC误差大于 TOL的数据 


 call IGP_givei(ippband)
!计算GIVEI值


!do i=1,ipp%n_pierce
!  
! write(*,*) 'routine from test1',ipp%n_pierce
! write(*,101)  ipp%n_pierce, ipp%pierce(i)%sow,ipp%pierce(i)%phi, ipp%pierce(i)%lam ,&
!            ipp%pierce(i)%IncVtec,ipp%pierce(i)%cVtec 
!           
!end do
!
!101 format(2I8,4F16.6)

end subroutine IGP_delay_givei

由格网点反算穿刺点理论值
  
subroutine IPP_cVTEC
!---------------------------------subroutine  comment
!  Purpose   :  由格网点反算穿刺点理论值(方法2)
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-04-03 17:30:20 
!          本版本为方法2,基本思路是对每一个穿刺点
!          搜索其周围的格网点,并判断格网点delay是否已经解算出
!          当超过三个格网点解算出后,则解算其VTEC理论值  
!          该方法比方法1简便    
!-----------------------------------------------------
!  Input Parameters    :
!       
!
!  Output Parameters   :
!         
!
!  Subroutines used    :
!       *.   由经纬度搜索格网点函数
!  x1=Dmod(-42d0,5d0)   !-2
!  x2=MODULO(-42d0,5d0) ! 3

!  x3=Dmod(42d0,5d0)    !2
!  x4=modulo(42d0,5d0)  !2 
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------
use def_fi

implicit real*8(a-h,o-z)

integer::ippband(ipp%n_pierce+1,0:10)



ipp%pierce(:)%cVtec = 0d0
!设置所有穿刺点理论值初值为0


do  i=1,ipp%n_pierce

       xlongP=ipp%pierce(i)%lam
       xlatP=ipp%pierce(i)%phi
          
         
       !正负55度以内跨度5度,高纬度跨度10度 
       if(xlatP<=55.AND.xlatP>=-55) then
          span=5d0
       else if (xlatP>55.or.xlatP<-55) then
          span=10d0
       end if

       remLong=MODULO(xlongP,span)
       remLat=MODULO(xlatP,span)
       !MODULO范例见程序开头注释部分

       GridLong1=xlongP-remLong
       GridLong2=GridLong1+span

       GridLat1=xlatP-remlat
       GridLat2=GridLat1+span

       !化到正负180度之间
       Glong1= anpm (Gridlong1)
       Glong2= anpm(Gridlong2)
       GLat1= anpm(Gridlat1)
       Glat2= anpm(Gridlat2)


!       grid_search(iflag,iband,iindex,iband2,iindex2,Glong1,Glat1,ierr)
        
       isum=0
       vtectmp=0d0
       wtmp=0d0

       !下面开始搜索格网点编号
         call grid_search(iflag,ib1,ig1,iband2,iindex2,Glong1,Glat1,ierr)
         
         if(iflag/=0) then
            
            if (IGP%GridBand(ib1)%mask(ig1)==1) then   
            
              call weight(w,Glong1,Glat1,xlongP,xlatP)
             !计算格网点与穿刺点之间的权重
             !vtectmp=vtectmp+w*ipp%pierce(itmp2)%IncVtec
             vtectmp=vtectmp+w*iGP%GridBand(ib1)%Grid(ig1)%delay
             !可以再加模型改正部分
             wtmp=wtmp+w
              isum=isum+1
            end if

         end if
         

         call  grid_search(iflag,ib2,ig2,iband2,iindex2,Glong1,Glat2,ierr)
         if(iflag/=0) then
            
            if (IGP%GridBand(ib2)%mask(ig2)==1) then    
            
             call weight(w,Glong1,Glat2,xlongP,xlatP)
             !计算格网点与穿刺点之间的权重
             !vtectmp=vtectmp+w*ipp%pierce(itmp2)%IncVtec
             vtectmp=vtectmp+w*iGP%GridBand(ib2)%Grid(ig2)%delay
             !可以再加模型改正部分
             wtmp=wtmp+w

              isum=isum+1
            end if

         end if


         
         call  grid_search(iflag,ib3,ig3,iband2,iindex2,Glong2,Glat1,ierr)

         if(iflag/=0) then
            
            if (IGP%GridBand(ib3)%mask(ig3)==1) then          
             call weight(w,Glong2,Glat1,xlongP,xlatP)
             !计算格网点与穿刺点之间的权重
             !vtectmp=vtectmp+w*ipp%pierce(itmp2)%IncVtec
             vtectmp=vtectmp+w*iGP%GridBand(ib3)%Grid(ig3)%delay
             !可以再加模型改正部分
             wtmp=wtmp+w
             isum=isum+1
            end if

         end if


         call  grid_search(iflag,ib4,ig4,iband2,iindex2,Glong2,Glat2,ierr)

         if(iflag/=0) then
            
            if (IGP%GridBand(ib4)%mask(ig4)==1) then          
             call weight(w,Glong2,Glat2,xlongP,xlatP)
             !计算格网点与穿刺点之间的权重
             !vtectmp=vtectmp+w*ipp%pierce(itmp2)%IncVtec
             vtectmp=vtectmp+w*iGP%GridBand(ib4)%Grid(ig4)%delay
             !可以再加模型改正部分
             wtmp=wtmp+w

              isum=isum+1
            end if

         end if

      if (isum>=3) then
        ipp%pierce(i)%cVtec=vtectmp/wtmp
      else if (isum<3) then
        ipp%pierce(i)%cVtec=0d0
      end if

end do

end subroutine  IPP_cVTEC
计算givei
  
subroutine IGP_givei(ippband)
!---------------------------------subroutine  comment
!  Purpose   :  calculate the GIVEI of the Grid point
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-04-02 09:26:35 
!         calculate the GIVEI
!         IT SHOULD BE CALLED AFTHER THE DELAY HAD BEEN CALCULATED
!       V1.1------2014-05-05 16:52:03
!         修复未满足反算条件情况下穿刺点统计的BUG
!         并在统计结果上加上中位数统计信息
!       V2.0------2014-05-14 15:35:12
!         统计垂直格网点点离散方法 
!         Ref :  Ionospheric Time Delay  Estimation using
!                IDW  Grid Model for GAGAN
!                Niranjan  Parasad  
!-----------------------------------------------------
!  Input Parameters    :
!       ippband--------------
!                     pierce point's in each band's index
!  Output Parameters   :
!       UPDATE THE GIVEI OF THE GRID POINT WHICH WAS SAVED IN THE MODULE 
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use def_fi

implicit real*8(a-h,o-z)

integer::ippband(ipp%n_pierce+1,0:10)

!---------------
!real*8:: Vec(ipp%n_pierce+2)
           !最大可能性为所有穿刺点
           !一个格网点附近所有穿刺点垂直序列
           !增加时间 2014-05-14 15:38:48    宋叶志
           !随着版本 V2.0 新引入变量

!integer*8:: indexVec(ipp%n_pierce+2,3)
           !垂直误差指标
           !第一个指标为   站号
           !第二个指标为   卫星号
           !第三个指标为   时间序列次数
!---------------


!real*8,parameter:: Factor = 0.1651d0         
!基于B1频点 TECU 到 长度单位(米) 转换系数  

real*8,parameter::kappa=3.2905d0
!99.9%置信概率分位数

do i=0,10
  IGP%GridBand(i)%Grid(:)%GIVEI=15
  !设置所有格网点初值为未监测状态
end do



do iband=0,10

    itmp=sum(IGP%GridBand(iband)%mask)
    !这个带总共解算出多少格网点

    if (itmp<5) cycle
!    如果设置 itmp<3 则退出当次循环 ,解释如下
!    !如果一个带总解算出的格网点少于3个
!    !则这个带不可能由格网点解算出穿刺点延迟
!    !那么就退出本带循环
!
!    这里更进一步的这里设置 itmp<5 退出当次循环
!    因为如果解算出的格网点低于5个,则不可能由
!    格网点算出超过3个穿刺点的理论延迟值
!    而少于3个穿刺点的理论延迟,则无法对一个格网点
!    计算其 GIVE值
!    这样的话,计算这个带中穿刺点理论值已经没有必要
!    故而退出本带内穿刺点理论值的计算
    

    do k=1,210

      if (IGP%GridBand(iband)%mask(k)==0) cycle
      !MASK记录了是否成功解算出delay
      !如果格网点未算出 delay则退出 当次循环
       
       !格网点如果已经算出来的话,则其周围至少三个象限内
       !都有穿刺点,所以这里不需要再进行是否满足三个象限的判断
     
      
      !存储 give有关数值
      sumtmp1=0d0
      sumtmp2=0d0
      sumtmp3=0d0

      M=0
      !记录计算GIVE时用到穿刺点的个数


      call grid_index(iband,k,xlongGrid,xlatGrid,ierr)



      sum_err=0d0

!本次循环仅仅用于统计误差均值
    do k1=1,ipp%n_pierce
       
					if(ipp%pierce(k1)%cVtec==0) cycle
!					!如果穿刺点处反算VTEC为0,则不参加解算 deq 2014-05-05 08:41
										
          xlongP=ipp%pierce(k1)%lam
          xlatP=ipp%pierce(k1)%phi
          !穿刺点经纬度
!----------------------
 
           call quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
           ! 判断穿刺点是否落在格网点5度范围内的象限
           !及其落在第几个象限
           if(iq/=0) then
             
             call weight(wei,xlongGrid,xlatGrid,xlongP,xlatP)
             !计算权重
             
             err=ipp%pierce(k1)%cVtec-ipp%pierce(k1)%IncVtec
             !计算穿刺点理论值与观测值的误差
 
!            sumerr=sumerr+err
             !统计误差和
             
             
             sumtmp1=sumtmp1+err*wei
             sumtmp2=sumtmp2+wei
             !统计 GIVE 第一项
             sumtmp3=sumtmp3+dabs(err)*wei
             
!             M=M+1

           end if

      end do
      !对所有穿刺点k1循环结束

      ave_err=sumtmp1/sumtmp2
      !实际为M个点满足统计条件
      abs_err=sumtmp3/sumtmp2

!统计置信区间  2014-05-13 14:07:31  syz
!================================================================== 

      !存储 give有关数值
      sumtmp1=0d0
      sumtmp2=0d0


     do k1=1,ipp%n_pierce
       
					if(ipp%pierce(k1)%cVtec==0) cycle
!					!如果穿刺点处反算VTEC为0,则不参加解算 deq 2014-05-05 08:41
										
          xlongP=ipp%pierce(k1)%lam
          xlatP=ipp%pierce(k1)%phi
          !穿刺点经纬度
!----------------------
 
           call quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
           ! 判断穿刺点是否落在格网点5度范围内的象限
           !及其落在第几个象限
           if(iq/=0) then
            
           call weight(wei,xlongGrid,xlatGrid,xlongP,xlatP)
             !计算权重
             
           err=ipp%pierce(k1)%cVtec-ipp%pierce(k1)%IncVtec
             !计算穿刺点理论值与观测值的误差

					 sumtmp1 = sumtmp1 +  (err - ave_err)*(err - ave_err)
					 sumtmp2 = sumtmp2 + 1d0; 
					 
           end if

      end do   ! k1, 对所有穿刺点k1循环结束

!=============================================================
     
          !GIVE=dabs(ave_err)+kappa*dsqrt(sumtmp1/sumtmp2)
          GIVE=abs_err+kappa*dsqrt(sumtmp1/sumtmp2)  
          !GIVE值

          call  Give2GiveI(iGiveI,Give)

          IGP%GridBand(iband)%Grid(k)%GIVEI=iGiveI
       

    end do  !k ,对所有格网点循环结束

end do !iband ,对所有带循环结束

end subroutine IGP_givei

计算所有格网点延迟
  
subroutine IGP_delay(ippband)
!subroutine IGP_delay(ipp,iGP)
!---------------------------------subroutine  comment
!  Purpose   :  
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-06 19:16:33 
!             计算所有格网点延迟   
!-----------------------------------------------------
!  Input Parameters    :
!       ipp--------穿刺点结构体数组
!       
!  Output Parameters   :
!       igp-------格网点数组,其中包含格网点延迟  
!    
!       ippband----穿刺点分布在不同带中的索引
!
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use def_fi


implicit real*8(a-h,o-z)


integer::ippband(ipp%n_pierce+1,0:10)

!real*8,parameter:: Factor = 0.1651d0  
!基于B1频点 TECU 到 长度单位(米) 转换系数


do iband=0,10   !------带循环
!对所有的带循环 
 
   !---------------------------------------------
!    if (ippband(1,iband)==0) cycle
!    !如果该带中第一个指标为0,表示该带就没有穿刺点
!    !则退出本次带的所有格网点循环
   !---------------------------------------------

      !---------------------------------------------
    if (ippband(3,iband)==0) cycle
!    !如果该带中第3个指标为0,表示该带即便有1个或2个穿刺点也不足以
!    解算出一个格网点
!    这样避免了一些带只有一两个穿刺点,而造成本带进行循环
   !---------------------------------------------

   inumber=201
    !每个带格网点个数                
   if(iband==8) inumber=200
   if(iband==9) inumber=192
   if(iband==10) inumber=192

   
   igp%GridBand(iband)%Mask(:)=0
    !一个带的格网点掩码初值设置为0


   do k1=1,inumber !-----对每一个格网点
           
      call grid_index(iband,k1,xlonggrid,xlatgrid,ierr)
      ! gridlong ---格网点经度
      ! gridlat ----格网点纬度
      ! 根据带号和格网编号,给出格网点的经纬度
    
         it1=0
         it2=0
         it3=0
         it4=0
      ! 4个象限的循环指标


      do k2=1,ipp%n_pierce+1
                  !------------对所有穿刺点循环
                  !------------目的是判断每个格网点四个象限内穿刺点的个数
                  ! 虽然表面上N很大,但是每次循环到每个带中无穿刺点时,自动结束
                  ! 所以循环量较小         
          
          
          itmp=ippband(k2,iband)
          !该带中实际的穿刺点指标
          !索引这个带(第iband带)中的第k2个穿刺点的序号
          !从该带中第一个穿刺点索引,索引到为0表示这个带中已经没有穿刺点

          if(itmp==0) exit
          !碰到第一个为0时候,表示该带中已经没有穿刺点,退出循环
                          
          xlongP=ipp%pierce(itmp)%lam
          xlatP=ipp%pierce(itmp)%phi
          !穿刺点经纬度


          call quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
         ! 判断穿刺点是否落在格网点5度范围内的象限
         !及其落在第几个象限
         !同一个象限的穿刺点个数不累计,这里仅仅是为了判断
         !是否满足格网点多于3个象限


          select case (iq)

          case (1)
            it1=1
          case (2)
            it2=1
          case (3)
            it3=1
          case (4)
            it4=1
          end select 

           

      end do       !-k2 循环结束,一个格网点对带内所有穿刺点循环结束
       
       
       ittmp=it1+it2+it3+it4


      if (ittmp>=3) then
      !大于等于3个象限时解算

             vtectmp=0d0  !vtec
             wtmp=0d0     !权重
        
         
         do k3=1,ipp%n_pierce+1

           itmp2=ippband(k3,iband)
           !该带中实际的穿刺点指标
           if(itmp2==0) exit
          !碰到第一个为0时候,表示该带中已经没有穿刺点,退出循环


          xlongP=ipp%pierce(itmp2)%lam
          xlatP=ipp%pierce(itmp2)%phi
          !穿刺点经纬度

           call quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
           ! 判断穿刺点是否落在格网点5度范围内的象限
           !及其落在第几个象限
           if(iq/=0) then
             call weight(w,xlongGrid,xlatGrid,xlongP,xlatP)
             !计算格网点与穿刺点之间的权重
             vtectmp=vtectmp+w*ipp%pierce(itmp2)%IncVtec
             !可以再加模型改正部分
             wtmp=wtmp+w
           end if

            !X36B_d%GridBand(iband)%IPG(k1)%GridDelayCrt= vtectmp/wtmp

            tmp_delay=vtectmp/wtmp
          
            
            iGP%Gridband(iband)%Grid(k1)%delay=tmp_delay
            !延迟值
            
            
            !iGP%Gridband(iband)%Mask(k1)=1 
            !如果可以算出delay值,则掩码为1

         end do
         
         
            iGP%Gridband(iband)%Mask(k1)=1 
            !如果可以算出delay值,则掩码为1
            !改到循环体外  2014-06-12
         
          
      end if      !如果象限大于3个的条件及条件内处理结束 

   end do ! k1 带内格网点循环结束

end do  ! iband 所有带循环结束


end subroutine IGP_delay
第二次计算延迟
  
subroutine IGP_delay1(ippband)
!---------------------------------subroutine  comment
!  Purpose   : 计算格网点延迟,第二次计算 
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-06 19:16:33 
!             计算所有格网点延迟   
!       V2.0-----2014-05-29 15:34:06
!             如果 穿刺点 |VTEC-CVTEC|> TOL 则这一类穿刺点
!             第二次计算时候不参与 格网点计算
!-----------------------------------------------------
!  Input Parameters    :
!       ipp--------穿刺点结构体数组
!       
!  Output Parameters   :
!       igp-------格网点数组,其中包含格网点延迟  
!    
!       ippband----穿刺点分布在不同带中的索引
!
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use def_fi


implicit real*8(a-h,o-z)


integer::ippband(ipp%n_pierce+1,0:10)

real*8,parameter :: TOL =5D0
   !用于判断穿刺点理论值与观测值误差容限




!real*8,parameter:: Factor = 0.1651d0  
!基于B1频点 TECU 到 长度单位(米) 转换系数


do iband=0,10   !------带循环
!对所有的带循环 
 
   !---------------------------------------------
!    if (ippband(1,iband)==0) cycle
!    !如果该带中第一个指标为0,表示该带就没有穿刺点
!    !则退出本次带的所有格网点循环
   !---------------------------------------------

      !---------------------------------------------
    if (ippband(3,iband)==0) cycle
!    !如果该带中第3个指标为0,表示该带即便有1个或2个穿刺点也不足以
!    解算出一个格网点
!    这样避免了一些带只有一两个穿刺点,而造成本带进行循环
   !---------------------------------------------

   inumber=201
    !每个带格网点个数                
   if(iband==8) inumber=200
   if(iband==9) inumber=192
   if(iband==10) inumber=192

   
   igp%GridBand(iband)%Mask(:)=0
    !一个带的格网点掩码初值设置为0


   do k1=1,inumber !-----对每一个格网点
           
      call grid_index(iband,k1,xlonggrid,xlatgrid,ierr)
      ! gridlong ---格网点经度
      ! gridlat ----格网点纬度
      ! 根据带号和格网编号,给出格网点的经纬度
    
         it1=0
         it2=0
         it3=0
         it4=0
      ! 4个象限的循环指标


      do k2=1,ipp%n_pierce+1
                  !------------对所有穿刺点循环
                  !------------目的是判断每个格网点四个象限内穿刺点的个数
                  ! 虽然表面上N很大,但是每次循环到每个带中无穿刺点时,自动结束
                  ! 所以循环量较小         
       
          !======================================  
           if (dabs(ipp%pierce(k2)%cVtec-ipp%pierce(k2)%IncVtec)> TOL)  cycle
           !如果穿刺点理论值与测量值误差绝对值大于误差剔除标准
           !则剔除这一类穿刺点不参与计算
           !2014-05-29 15:06:33    song.yz
          !======================================
          
          
          itmp=ippband(k2,iband)
          !该带中实际的穿刺点指标
          !索引这个带(第iband带)中的第k2个穿刺点的序号
          !从该带中第一个穿刺点索引,索引到为0表示这个带中已经没有穿刺点

          if(itmp==0) exit
          !碰到第一个为0时候,表示该带中已经没有穿刺点,退出循环
                          
          xlongP=ipp%pierce(itmp)%lam
          xlatP=ipp%pierce(itmp)%phi
          !穿刺点经纬度


          call quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
         ! 判断穿刺点是否落在格网点5度范围内的象限
         !及其落在第几个象限
         !同一个象限的穿刺点个数不累计,这里仅仅是为了判断
         !是否满足格网点多于3个象限


          select case (iq)

          case (1)
            it1=1
          case (2)
            it2=1
          case (3)
            it3=1
          case (4)
            it4=1
          end select 
 
      end do       !-k2 循环结束,一个格网点对带内所有穿刺点循环结束
       
       
       ittmp=it1+it2+it3+it4


      if (ittmp>=3) then
      !大于等于3个象限时解算

             vtectmp=0d0  !vtec
             wtmp=0d0     !权重


         do k3=1,ipp%n_pierce+1

           itmp2=ippband(k3,iband)
           !该带中实际的穿刺点指标
           if(itmp2==0) exit
          !碰到第一个为0时候,表示该带中已经没有穿刺点,退出循环


          xlongP=ipp%pierce(itmp2)%lam
          xlatP=ipp%pierce(itmp2)%phi
          !穿刺点经纬度

           call quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
           ! 判断穿刺点是否落在格网点5度范围内的象限
           !及其落在第几个象限
           if(iq/=0) then
             call weight(w,xlongGrid,xlatGrid,xlongP,xlatP)
             !计算格网点与穿刺点之间的权重
             vtectmp=vtectmp+w*ipp%pierce(itmp2)%IncVtec
             !可以再加模型改正部分
             wtmp=wtmp+w
           end if

            !X36B_d%GridBand(iband)%IPG(k1)%GridDelayCrt= vtectmp/wtmp

            tmp_delay=vtectmp/wtmp
          
            
            iGP%Gridband(iband)%Grid(k1)%delay=tmp_delay
            !延迟值
            
            
            !iGP%Gridband(iband)%Mask(k1)=1 
            !如果可以算出delay值,则掩码为1

         end do
         
            iGP%Gridband(iband)%Mask(k1)=1 
            !如果可以算出delay值,则掩码为1
            !改到循环体外  ,2014-06-12          
      end if      !如果象限大于3个的条件及条件内处理结束 

   end do ! k1 带内格网点循环结束

end do  ! iband 所有带循环结束


end subroutine IGP_delay1
判断象限
  
subroutine quadrant(iq,xlongGrid,xlatgrid,xlongP,xlatP)
!---------------------------------subroutine  comment
!  Purpose   :  根据格网点经纬度和穿刺点经纬度,判断穿刺点位于格网点的
!               的哪各象限
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-06 23:14:58 
!            根据格网点经纬度和穿刺点经纬度
!            判断穿刺点位于格网点的哪个象限
!            特别需要注意的是在格网点经度是+/180时的特殊边界情况      
!         
!            一种看似可行的方法,其实不可行,即对格网点和穿刺点的经度
!             同时加 360的倍数  如720
!            这样同样要面临,起始点的问题 
!           应该按照本程序中的方法进行处理 
!      V2.0 ----2014-06-12
!            对于落在象限的经纬度范围由原先的5度改为可设置
!            这里设置为2.5度
!-----------------------------------------------------
!  Input Parameters    :
!         xlonggrid-----格网点经度
!         xlatgrid ------格网点纬度
!         xlongP-------穿刺点经度
!         xlongP-------穿刺点纬度
!  Output Parameters   :
!         iq  --   0----穿刺点不在格网点5度附近
!                 1--- 穿刺点位于格网点第一象限 [0,90]
!                 2----穿刺点位于格网点第二象限 [90,180]
!                 3----穿刺点位于格网点第三象限 [180,270]
!                 4----穿刺点位于格网点第四象限 [270,360]
!                
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------
implicit real*8(a-h,o-z)

real*8,parameter:: xp =  5d0   !正数 
real*8,parameter:: xm = -5d0   !负数   

   !-----------非常重要
   if (xlongGrid==-180.and.(xlongP>175.and.xlongP<180)) then
       xlongP=xlongp-360
   end if
   !处理经度在 -180度边界线上的交叉问题

   if (xlongGrid==180.and.(xlongP>-180.and.xlongP<-175)) then
       xlongP=xlongP+360
   end if
   !处理经度在 180度边界线上的交叉问题


   tmp1=xlongP-xlongGrid

   tmp2=xlatP-xlatGrid

   iq=0
   !设置初状态


   if ((tmp10d0).and.(tmp20d0)) then
     iq=1
   !第一象限
   else if ((tmp10d0).and.(tmp2<0d0.and.tmp2>xm)) then
     iq=4
   else if ((tmp1>=xm.and.tmp1<=0d0) .and. (tmp2<=xp.and.tmp2>=0d0)) then
      iq=2
   else if ((tmp1>=xm.and.tmp1<=0d0) .and. (tmp2<=0d0.and.tmp2>=xm)) then
      iq=3
   end if


end subroutine quadrant
根据穿刺点经纬度判断象限
  
 subroutine quadrant1(iq,xlongGrid,xlatgrid,xlongP,xlatP)
!---------------------------------subroutine  comment
!  Purpose   :  根据格网点经纬度和穿刺点经纬度,判断穿刺点位于格网点的
!               的哪各象限
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-06 23:14:58 
!            根据格网点经纬度和穿刺点经纬度
!            判断穿刺点位于格网点的哪个象限
!            特别需要注意的是在格网点经度是+/180时的特殊边界情况      
!         
!            一种看似可行的方法,其实不可行,即对格网点和穿刺点的经度
!             同时加 360的倍数  如720
!            这样同样要面临,起始点的问题 
!           应该按照本程序中的方法进行处理 
!-----------------------------------------------------
!  Input Parameters    :
!         xlonggrid-----格网点经度
!         xlatgrid ------格网点纬度
!         xlongP-------穿刺点经度
!         xlongP-------穿刺点纬度
!  Output Parameters   :
!         iq  --   0----穿刺点不在格网点5度附近
!                 1--- 穿刺点位于格网点第一象限 [0,90]
!                 2----穿刺点位于格网点第二象限 [90,180]
!                 3----穿刺点位于格网点第三象限 [180,270]
!                 4----穿刺点位于格网点第四象限 [270,360]
!                
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------
implicit real*8(a-h,o-z)
   

   !-----------非常重要
   if (xlongGrid==-180.and.(xlongP>175.and.xlongP<180)) then
       xlongP=xlongp-360
   end if
   !处理经度在 -180度边界线上的交叉问题

   if (xlongGrid==180.and.(xlongP>-180.and.xlongP<-175)) then
       xlongP=xlongP+360
   end if
   !处理经度在 180度边界线上的交叉问题


   tmp1=xlongP-xlongGrid

   tmp2=xlatP-xlatGrid

   iq=0
   !设置初状态


   if ((tmp1<5d0.and.tmp1>0d0).and.(tmp2<5d0.and.tmp2>0d0)) then
     iq=1
     !第一象限
   else if ((tmp1<5d0.and.tmp1>0d0).and.(tmp2<0d0.and.tmp2>-5d0)) then
     iq=4
   else if ((tmp1>=-5d0.and.tmp1<=0d0) .and. (tmp2<=5d0.and.tmp2>=0d0)) then
      iq=2
   else if ((tmp1>=-5d0.and.tmp1<=0d0) .and. (tmp2<=0d0.and.tmp2>=-5d0)) then
      iq=3
   end if


end subroutine quadrant1

权函数
  
subroutine weight(w,xlongGrid,xlatGrid,xlongP,xlatP)
!---------------------------------subroutine  comment
!  Purpose   :  计算格网点与穿刺点的权重
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-07 00:00:08 
!             根据球面距离计算权重     
!             注意输入参数均为角度(算权重时要化为弧度) 
!       V2.0----2014-06-12 18:49:12
!             去掉球半径 6378.1改用单位1, 半径作为常数,用在不同的权上,最终消去了。
!-----------------------------------------------------
!  Input Parameters    :
!       xlongGrid------格网点经度(角度)
!       xlatGrid-------格网点纬度(角度)
!       xlongP--------穿刺点经度(角度)
!       xlatP---------穿刺点纬度(角度)
!  Output Parameters   :
!        w------------权重 
! 
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------
implicit real*8(a-h,o-z)

!tmp = dsin(xlatGrid)*dsin(xlatP)+dcos(xlatGrid)*dcos(xlatP)*dcos(xlongGrid-xlongP)
 arc=0.01745329251994d0
 !degree two arc   ,arc = pi/180
tmp = dsin(xlatGrid*arc)*dsin(xlatP*arc)+dcos(xlatGrid*arc)*dcos(xlatP*arc)*dcos(xlongGrid*arc-xlongP*arc)

!d = 6378.1*dacos(tmp)
!w = 1d0/d

eps=3d-4  
!加一小常数,防止奇异
d= dacos(tmp)+eps

w=1d0/d

end subroutine weight
记录各带穿刺点序列
  
subroutine ipp2band(ippband,N)
!---------------------------------subroutine  comment
!  Purpose   : set the piece points to different bands
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-31 16:20:04  (had been tested)
!          set the piece points to different bands
!          用ippband记录各个带中穿刺点的序列    
!          如第0个带穿刺点序列为  7,15,24,...
!             ...
!            第10带穿刺点序列为   8,12,36 ...
!        
!          经过如此存储后,允许同一个穿刺点在不同的带中被记录
!          如被经度交叉的带中同时记录  
!-----------------------------------------------------
!  Input Parameters    :
!        ipp --------piece points
!        N-----------the number of iono piece points
!  Output Parameters   :
!        ippband-------piece points in different bands
!          
!             0   1   2   3   4  .... 10
!             .   .   .   .   .        .
!             .   .   .   .   .        .
!
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use def_fi

implicit real*8(a-h,o-z)

!include 'def.fi'
!!引入数据结构
!type (ipplist) :: ipp

integer::ippband(N+1,0:10)

integer::k(0:10)
! the index of every band

! do i=1,5
!  
! write(*,*) 'routine from ipp2band',ipp%n_pierce
! write(*,101)  ipp%n_pierce, ipp%pierce(i)%sow,ipp%pierce(i)%phi, ipp%pierce(i)%lam ,&
!            ipp%pierce(i)%IncVtec,ipp%pierce(i)%cVtec 
!           
!end do
!
!101 format(2I8,4F16.6)


ippband=0


k(0:10)=1

do i=1,ipp%n_pierce
   
    xlong=ipp%pierce(i)%lam
    xlat=ipp%pierce(i)%phi
    !longitude and latitude of pierce point

    xlong=anpm(xlong)
    !transfer the longitude to 0 - 180(degree)
    !-----------------------------------------

    do iband=0,8
  
    ! !cross 5 degree in  both plus and minus direction   **** important
      tmp1=-180+40*iband-5
      tmp2=tmp1+40+10

      if (xlong>=tmp1.and.xlong175) then
     
     ippband(k(0),0)=i
     k(0)=k(0)+1
    end if
    !  175-----180 也化到第0带

    if (xlong>-180.and.xlong<-175) then
      
     ippband(k,8)=i
     k(8)=k(8)+1

    end if
    !  -180 ---- -175 也化到第8带
!-----------------------------------------

    if(xlat>55) then
    !向下交叉5度
      
     ippband(k,9)=i
     k(9)=k(9)+1

    end if

    if(xlat<-55) then
    !向上交叉5度
      
     ippband(k,10)=i
     k(10)=k(10)+1

    end if

end do

end subroutine ipp2band
格网索引
  
subroutine grid_index(iband,iindex,xlong,xlat,ierr)
!---------------------------------subroutine  comment
!  Purpose   :  Output the longitude and latitude by the band ID and the point ID
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-01 16:51:06
!              Output the longitude and latitude by the band ID and the point ID
!       V2.0-----2014-03-04 18:01:22
!               get the longitude and latitude directly by new data structure  
!-----------------------------------------------------
!  Input Parameters    :
!         iband-----------band ID
!         iindex----------point ID (in the band)   
!  Output Parameters   : 
!         xlong-----------longitude
!         xlat------------latitude
!         ierr------------flag for record whether it is wrong
!                         it means the wrong ID  if ierr equals  minus one
!  Subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use iono_grid

implicit real*8(a-h,o-z)

if(iindex<1.OR.iindex>201) ierr=-1
if(iband>10.OR.iband<0) ierr=-1

if(iband==8.AND.iindex>200) ierr=-1
!there are 200 Grid points in band 8

xlong=grid(iindex,iband)%xlong
xlat=grid(iindex,iband)%xlat


!output the information of the Grid
!   do i=0,2
!      do j=1,202                      
!        write(*,*) Grid(j,i)%xlong, Grid(j,i)%xlat,'Grid point'             
!      end do  
!   end do
!-----------------------------------------------------
   

end subroutine grid_index  

格网搜索
  
 subroutine grid_search(iflag,iband,iindex,iband2,iindex2,xlong0,xlat0,ierr)
!---------------------------------subroutine  comment
!  Purpose   :  seach the Grid ID by longitude and latitude
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-03-01 10:46:21 
!               根据经纬度搜索格网点
!               是否搜索到以 is,is2作为判断标准
!       V2.0 ---合并 is与  is2 ,以 iflag作为输出指标
!               iflag    意义见 output parameters
!       V3.0 ---2014-03-04 17:23:20
!               采用格网点结构体二维矩阵索引,这样就不需要计算每个格网点在所有矩阵中的绝对指标
!               相应的模块也作升级为 iono_grid   
!       V3.1 ---2014-03-05 17:19:59  
!               判断两个角度是否相等,不以 绝对相等为依据
!               而是当两者之差绝对值小于 一个很小的数 eps(设置为1D-15)时,认为两者相等
!               这样避免了,角度和弧度相互转化之后,带来的精度影响最终的匹配 
!       V3.2 ---2014-03-06 11:29:32
!        Normalize angle into the range -180 <= A < +180
!                不再度输入角度检查是否在 +/-180之间
!                而是把输入的经纬度化到 +/-180
!                如果纬度 在  +/- 90之外,则 令 ierr为 -1  
!-----------------------------------------------------
!  Input Parameters    :
!       xlong---------经度(单位:角度)  范围  -180---180
!       xlat----------纬度(单位:角度)  范围  -90----90
!       
!  Output Parameters   :
!               iflag    0       未匹配到格网点
!                        1       匹配到 1-8带中某格网点,但未匹配到9或10带
!                                带号及带内号见 iband, iindex
!                        2       匹配到 9 或 10带,但未匹配到1-8带
!                                带号及带内号见 iband2,iindex2
!                        3       同时匹配到1-8和9(或10)
!                                带号和带内号分别见
!                                iband,iindex,iband2,iindex2

!          ==================================================
!       iband--------如果落在1-8某带中,则输出带编号
!                    无论是否匹配到穿刺点,iband一定会输出
!                    而是否匹配成功,则以 is 为依据
!                    因为角度总在-180--180之间,所以一定iband一定有值
!       iindex-------输出该iband带内号 
!                    如果匹配到穿刺点,则输出该编号
!                    如果未匹配到穿刺点,则输出该带的最后一个编号
!                    未匹配到,则输出-1
!       iband2-------如果既落在1-8某带中,也落在9-10某带中,则输出该带号
!                    (9或10)
!                    如果未落在 9 或者 10带中
!                    iband2=-1
!       iindex2------该带 iband2(9或10) 的带内编号    
!                    未匹配到输出-1
!      ierr---------ierr为-1,则输入数据范围不在区间内,不予计算
!  Subroutines used    :
!       *. band_interval(iband,ibegin,iend,ierr)  输出各带的始末指标
!       *.    
!-----------------------------------------------------
!  Notes :    
!       1.无论是否匹配到穿刺点
!         任何一个点的经纬度范围必然落在1-8带中,所以1-8带 iband一定会输出
!         如果一个点经纬度范围也落在9或10带中,则iband2会输出9或10
!      
!       2. 如果为落到9或10区域,则 iband2=-1, iindex2=202
!          这里  iband2默认不取0,是因为有第0带,防止引起歧义
!   
!       3. 对于1-8区域,如果未匹配上,则 index=-1
!      
!       4. 对于输出结果首先要看  iflag 来判断匹配结果,然后再看其他量
!
!  Ref.  :
!       MOPS for GPS WAAS DO-229D 2006      P252
!
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------

use iono_grid  !gridMAT

implicit real*8(a-h,o-z)


real*8,parameter::eps=1d-15


!--------------------------
iband=-1
iindex=-1
iband2=-1
iindex2=-1
!--------------------------
!      
iflag=0
is=0
is2=0
!-----------------------
 
 ! 先把经纬度化为 +/- 180之间
 ! 如果纬度 在  +/- 90之外  则不计算,并返回 ierr=-1 作为警告信息
xlong=anpm(xlong0)
xlat=anpm(xlat0)

 if (xlat>90.or.xlat<-90) then
   ierr=-1
   return
 end if
!=======================================================================


!=======================================================================
! check the point in which band (1-8) by longitude
do i=0,8
  
   tmp1=-180+40*i
   tmp2=tmp1+40

   if (xlong>=tmp1.and.xlong=60) then
   
   iband2=9
   !第二个带指标为9

 ! iindex2=0
   do i=1,192
 
   	!    if (xlong==grid(i,9)%xlong.and.xlat==grid(i,9)%xlat) then
    !   V 3.0
      if (dabs(xlong-grid(i,9)%xlong) < eps .and. dabs(xlat-grid(i,9)%xlat) < eps) then

           is2=1    	!如果和9带中某穿刺点匹配上  is2为1
           iindex2=i    !
           exit         !1个带中没有重复,如果搜到格网点则退出该带搜索 
   	    end if	

  end do

end if


if (xlat<=-60) then

   iband2=10
   !第二个带指标为10

 ! iindex2=0
   do i=1,192
 
   	     
         if (dabs( xlong-grid(i,10)%xlong ) < eps .and. dabs(xlat-grid(i,10)%xlat) < eps) then
           is2=1    	!如果和9带中某穿刺点匹配上  is2为1
           iindex2=i    !
           exit         !1个带中没有重复,如果搜到格网点则退出该带搜索 
   	    end if	

  end do

 
end if  ! seach in band 10


!               iflag    0       have not get the grid point 
!                        1       get the grid point in band 1 to 8, but not in 
!                                band 9 or 10.  the band ID and the point id
!                                were recorded by iband and iindex
!                        2       the point was seached in band 9 or band 10,but 
!                                not in band 1 to 8.
!                                the band ID and the point ID were recorded by
!                                iband2 and iindex2.
!                        3       the point was in band 1 to 8 and 9(or 10)
!                                the band ID and the point ID were recorded by
!                                iband,iindex,iband2,iindex2

  if (is==0.and.is2==0) then
    iflag=0
    return
  else if (is==1.and.is2==0) then
    iflag=1
    return
  else if (is==0.and.is2==1) then
    iflag=2
    return
  else if (is==1.and.is2==1) then
    iflag=3
  end if


end subroutine grid_search
  
 
角度归一化
  
double precision function anpm ( a )
!---------------------------------subroutine  comment
!  purpose   :  Normalize angle into the range -180 <= A < +180
!  author    :  song yezhi         
!  versions and changes   :
!       v1.0 ----2014-03-04 18:17:59 
!             if need to normalize the angle to -pi ---pi   
!             could set 
!             dpi  = 3.1415926535897932384626d0 
!             d2pi = 6.283185307179586476925287d0
!            Ref .  sofa   iau_anpm
!       v2.0 ---
!               if the angle equals 180 after it 
!               had been normalized to +/-180, set it to -180
!-----------------------------------------------------
!  input parameters    :
!       a-----input angle (unit: degree) 
!  output parameters   :
!       anpm-----
!              angle in range +/-180
!  subroutines used    :
!       *.
!       *.    
!-----------------------------------------------------
!  copyrigt (c)  :              (all rights reserved.)
!        center for astro-geodynamics
!        shanghai astronomical observatory
!        chinese academy of sciences , 2014  
!----------------------------------------------------

      implicit none

      double precision a

 
      double precision dpi
      parameter ( dpi = 180 )
 
      double precision d2pi
      parameter ( d2pi = 360 )

      double precision w

! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

      w = mod(a,d2pi)
      if ( abs(w) .ge. dpi ) w = w - sign(d2pi,a)
      anpm = w

!
      if (anpm==180)   anpm=-180

!
 end  function anpm 
    
 
计算GIVEI
  
subroutine Give2GiveI(iGiveI,Give)
!---------------------------------subroutine  comment
!  Purpose   :   Give to GiveI    EVALUATION OF GIVEI
!  Author    :  Song Yezhi         
!  Versions and Changes   :
!       V1.0 ----2014-04-02 13:41:59 
!          GIVE to GiveI
!          Ref :  MOPS for GPS Wass DO-229D 2006
!              Appendix A  Page A-33       
!-----------------------------------------------------
!  Input Parameters    :
!       GIVE  : Meters
!
!  Output Parameters   :
!       GIVEI :  0--15 ranks
!                
!                              sigma^2              
!  GIVEI   GIVE Meters      GIVE Meters^2                 
!    0        0.3              0.0084 
!    1        0.6              0.0333 
!    2        0.9              0.0749 
!    3        1.20             0.1331 
!    4        1.5              0.2079 
!    5        1.8              0.2994 
!    6        2.1              0.4075 
!    7        2.4              0.5322 
!    8        2.7              0.6735 
!    9        3.0              0.8315 
!    10       3.6              1.1974 
!    11       4.5              1.8709 
!    12       6.0              3.3260 
!    13       15.0             20.7870 
!    14       45.0             187.0826 
!    15       Not Monitored    Not Monitored
!-----------------------------------------------------
!  Copyrigt (C)  :              (All rights reserved.)
!        Center for Astro-geodynamics
!        Shanghai Astronomical Observatory
!        Chinese Academy of Sciences , 2014  
!----------------------------------------------------
implicit real*8(a-h,o-z)

real*8::rank(0:14)

rank=(/0.3d0,0.6d0,0.9d0,1.2d0,1.5d0,1.8d0,   &
    2.1d0,2.4d0,2.7d0,3.0d0,3.6d0,4.5d0,   &
    6.0d0,15.d0,45.d0   /)

 if (Give<=rank(0))    iGiveI=0

do i=1,14  
  if( give<=rank(i).and.give>rank(i-1))  iGiveI=i
end do

if (Give>=45)   IGiveI=15

end subroutine Give2GiveI