IODA Bundle
gnssro_mod.f90
Go to the documentation of this file.
1 !!!-------- README --------------------------------------------------------------------
2 ! this is a temporary routine to generate netcdf file
3 ! for jedi/ufo/gnssro/ operator test
4 ! Copyright UCAR 2019
5 ! Authors: Hailing Zhang
6 ! Mark Olah
7 
9 use netcdf
10 implicit none
11 
12 integer, parameter :: i_short = selected_int_kind(4) !2
13 integer, parameter :: i_kind = selected_int_kind(8)
14 integer, parameter :: r_double = selected_real_kind(15) !8
15 integer, parameter :: r_kind = selected_real_kind(15) !8
16 
17 integer(i_kind) :: said
18 logical :: verbose = .false.
19 
20 contains
21 
22 subroutine read_write_gnssro(infile, outdir)
23 
24 ! output obs data stucture
25 integer :: ncid
26 integer :: nobs_dimid,nlocs_dimid,nvars_dimid,nrecs_dimid,ndatetime_dimid
27 integer :: varid_lat,varid_lon,varid_time,varid_datetime,varid_said,varid_ptid,varid_sclf,varid_asce
28 integer :: varid_recn
29 integer :: varid_geoid, varid_rfict
30 integer :: varid_ref,varid_msl,varid_refoe
31 integer :: varid_bnd,varid_bndoe,varid_impp, varid_imph,varid_azim
32 integer :: nlev_dimid
33 integer :: varid_geo_temp,varid_geo_pres,varid_geo_shum,varid_geo_geop, varid_geo_geop_sfc
34 
35 character(len=*), intent(in) :: infile
36 character(len=*), intent(in) :: outdir
37 character(len=256) :: outfile
38 character,dimension(8) :: subset
39 character(len=10) :: anatime
40 integer(i_kind) :: ndatetime = 20
41 character(len=20) :: datetime
42 integer(i_kind) :: i,k,m,ireadmg,ireadsb,ptid,sclf,asce
43 integer(i_kind) :: lnbufr = 10
44 integer(i_kind) :: nread,ndata,nvars,nrec, ndata0
45 integer(i_kind) :: anatime_i
46 integer(i_kind) :: idate5(6), idate,iadate5(6)
47 integer(i_kind) :: mincy,minobs
48 logical :: good,outside
49 integer :: refflag, bendflag
50 integer(i_kind),parameter :: mxib=31
51 integer(i_kind) :: ibit(mxib),nib
52 integer(i_kind),parameter :: maxlevs=500
53 integer(i_kind),parameter :: n1ahdr=11
54 integer(i_kind) :: maxobs
55 real(r_kind) :: timeo
56 type gpsro_type
57  integer(i_kind), allocatable, dimension(:) :: said
58  integer(i_kind), allocatable, dimension(:) :: sclf
59  integer(i_kind), allocatable, dimension(:) :: ptid
60  integer(i_kind), allocatable, dimension(:) :: recn
61  integer(i_kind), allocatable, dimension(:) :: asce
62  real(r_double), allocatable, dimension(:) :: time
63  character(len=20), allocatable, dimension(:) :: datetime
64  real(r_double), allocatable, dimension(:) :: lat
65  real(r_double), allocatable, dimension(:) :: lon
66  real(r_double), allocatable, dimension(:) :: rfict
67  real(r_double), allocatable, dimension(:) :: azim
68  real(r_double), allocatable, dimension(:) :: geoid
69  real(r_double), allocatable, dimension(:) :: msl_alt
70  real(r_double), allocatable, dimension(:) :: ref
71  real(r_double), allocatable, dimension(:) :: refoe_gsi
72  real(r_double), allocatable, dimension(:) :: bend_ang
73  real(r_double), allocatable, dimension(:) :: impact_para
74  real(r_double), allocatable, dimension(:) :: bndoe_gsi
75 end type gpsro_type
76 
77 type(gpsro_type) :: gpsro_data
78 
79 real(r_double),dimension(n1ahdr) :: bfr1ahdr
80 real(r_double),dimension(50,maxlevs) :: data1b
81 real(r_double),dimension(50,maxlevs) :: data2a
82 real(r_double),dimension(maxlevs) :: nreps_this_ROSEQ2
83 integer(i_kind) :: iret,levs,levsr,nreps_ROSEQ1,nreps_ROSEQ2_int
84 real(r_double) :: pcc,qfro,usage,dlat,dlat_earth,dlon,dlon_earth,freq_chk,freq,azim
85 real(r_double) :: height,rlat,rlon,ref,bend,impact,roc,geoid, bend_error,ref_error,bend_pccf,ref_pccf
86 real(r_double) :: obsErr
87 real(r_double), parameter :: missingvalue=-9.9e10
88 logical, parameter :: GlobalModel = .true. ! temporary
89 
90 character(10) nemo
91 character(80) hdr1a
92 
93 data hdr1a / 'YEAR MNTH DAYS HOUR MINU PCCF ELRC SAID PTID GEODU SCLF' /
94 data nemo /'QFRO'/
95 nrec =0
96 ndata=0
97 nvars=2
98 maxobs=0
99 
100 open(lnbufr,file=trim(infile),form='unformatted')
101 call openbf(lnbufr,'IN',lnbufr)
102 call datelen(10)
103 call readmg(lnbufr,subset,idate,iret)
104 if (iret/=0) then
105  write(6,*)'READ_GNSSRO: can not open gnssro file!'
106  stop
107 end if
108 
109 write(unit=*,fmt='(a,i10)') trim(infile)//' file date is: ', idate
110 iadate5(1) = idate/1000000
111 iadate5(2) = (idate-iadate5(1)*1000000)/10000
112 iadate5(3) = (idate-iadate5(1)*1000000-iadate5(2)*10000)/100
113 iadate5(4) = idate-iadate5(1)*1000000-iadate5(2)*10000-iadate5(3)*100
114 iadate5(5) = 0
115 call w3fs21(iadate5,mincy)
116 anatime_i = idate
117 
118 write(outfile,'(a,i10.10,a)') trim(outdir)//'gnssro_obs_',idate,'.nc4'
119 
120 ! loop over all message to estimate maxobs
121 do while(ireadmg(lnbufr,subset,idate)==0)
122  read_loop_countmaxobs: do while(ireadsb(lnbufr)==0)
123  call ufbint(lnbufr,bfr1ahdr,n1ahdr,1,iret,hdr1a)
124  call ufbseq(lnbufr,data1b,50,maxlevs,levs,'ROSEQ1')
125  maxobs= maxobs + levs
126  enddo read_loop_countmaxobs
127 end do
128 
129 allocate(gpsro_data%said(maxobs))
130 allocate(gpsro_data%sclf(maxobs))
131 allocate(gpsro_data%ptid(maxobs))
132 allocate(gpsro_data%recn(maxobs))
133 allocate(gpsro_data%asce(maxobs))
134 allocate(gpsro_data%time(maxobs))
135 allocate(gpsro_data%datetime(maxobs))
136 allocate(gpsro_data%lat(maxobs))
137 allocate(gpsro_data%lon(maxobs))
138 allocate(gpsro_data%rfict(maxobs))
139 allocate(gpsro_data%azim(maxobs))
140 allocate(gpsro_data%geoid(maxobs))
141 allocate(gpsro_data%msl_alt(maxobs))
142 allocate(gpsro_data%ref(maxobs))
143 allocate(gpsro_data%refoe_gsi(maxobs))
144 allocate(gpsro_data%bend_ang(maxobs))
145 allocate(gpsro_data%impact_para(maxobs))
146 allocate(gpsro_data%bndoe_gsi(maxobs))
147 
148 !rewind lnbufr
149 call closbf(lnbufr)
150 open(lnbufr,file=trim(infile),form='unformatted')
151 call openbf(lnbufr,'IN',lnbufr)
152 call datelen(10)
153 call readmg(lnbufr,subset,idate,iret)
154 
155 do while(ireadmg(lnbufr,subset,idate)==0)
156  read_loop: do while(ireadsb(lnbufr)==0)
157 ! Read/decode data in subset (profile)
158  call ufbint(lnbufr,bfr1ahdr,n1ahdr,1,iret,hdr1a)
159  call ufbint(lnbufr,qfro,1,1,iret,nemo)
160 ! observation time in minutes
161  idate5(1) = bfr1ahdr(1) ! year
162  idate5(2) = bfr1ahdr(2) ! month
163  idate5(3) = bfr1ahdr(3) ! day
164  idate5(4) = bfr1ahdr(4) ! hour
165  idate5(5) = bfr1ahdr(5) ! minute
166  idate5(6) = 0 ! seconds
167  pcc = bfr1ahdr(6) ! profile per cent confidence
168  roc = bfr1ahdr(7) ! Earth local radius of curvature
169  said = bfr1ahdr(8) ! Satellite identifier
170  ptid = bfr1ahdr(9) ! Platform transmitter ID number
171  geoid= bfr1ahdr(10) ! Geoid undulation
172  sclf = bfr1ahdr(11)
173 
174  call w3fs21(idate5,minobs)
175  write(datetime,'(I4,"-",I2.2,"-",I2.2,"T",I2.2,":",I2.2,":",I2.2,"Z")') &
176  idate5(1),idate5(2),idate5(3),idate5(4),idate5(5),idate5(6)
177  timeo=real(minobs-mincy,r_kind)/60.0
178 
179  if( roc>6450000.0_r_kind .or. roc<6250000.0_r_kind .or. &
180  geoid>200_r_kind .or. geoid<-200._r_kind ) then
181  if (verbose) write(6,*)'READ_GNSSRO: profile fails georeality check, skip this report'
182  cycle read_loop
183  endif
184 
185 ! profile check: (1) CDAAC processing - cosmic-1, cosmic-2, sacc, cnofs, kompsat5
186  if ( ((said >= 740).and.(said <=745)) .or. &
187  ((said >= 750).and.(said <= 755)).or. &
188  (said == 820).or.(said == 786).or.(said == 825)) then !CDAAC processing
189  if(pcc == 0.0) then
190  if (verbose) write(6,*)'READ_GNSSRO: bad profile 0.0% confidence said=', &
191  said,'ptid=',ptid, ' SKIP this report'
192  cycle read_loop
193  endif
194  endif
195 
196  bendflag = 0
197  refflag = 0
198 ! profile check: (2) GRAS SAF processing - metopa-c, oceansat2, megha-tropiques, sacd
199  if ( (said >= 3 .and.said <= 5).or.(said == 421).or.(said == 440).or. (said == 821) ) then
200  call upftbv(lnbufr,nemo,qfro,mxib,ibit,nib)
201  if(nib > 0) then
202  do i = 1, nib
203  if(ibit(i)== 5) then ! bending angle
204  bendflag = 1
205  if (verbose) write(6,*)'READ_GNSSRO: bad profile said=',said,'ptid=',&
206  ptid, ' SKIP this report'
207  cycle read_loop
208  endif
209  if(ibit(i)== 6) then ! refractivity
210  refflag = 1
211  exit
212  endif
213  enddo
214  endif
215  endif
216 
217  asce = 0
218  call upftbv(lnbufr,nemo,qfro,mxib,ibit,nib)
219  if ( nib > 0) then
220  do i = 1, nib
221  if(ibit(i)== 3) then
222  asce = 1
223  exit
224  endif
225  enddo
226  end if
227 
228  call ufbint(lnbufr,nreps_this_roseq2,1,maxlevs,nreps_roseq1,'{ROSEQ2}')
229  call ufbseq(lnbufr,data1b,50,maxlevs,levs,'ROSEQ1')
230  call ufbseq(lnbufr,data2a,50,maxlevs,levsr,'ROSEQ3') ! refractivity
231 
232  nrec=nrec+1
233  ndata0 = ndata
234 
235  do k = 1, levs
236  rlat = data1b(1,k) ! earth relative latitude (degrees)
237  rlon = data1b(2,k) ! earth relative longitude (degrees)
238  azim = data1b(3,k)
239  height = data2a(1,k)
240  ref = data2a(2,k)
241  ref_error= data2a(4,k)
242  ref_pccf = data2a(6,k)
243 
244 ! Loop over number of replications of ROSEQ2 nested inside this particular replication of ROSEQ1
245  nreps_roseq2_int = nreps_this_roseq2(k)
246  do i = 1,nreps_roseq2_int
247  m = (6*i)-2
248  freq_chk=data1b(m,k) ! frequency (hertz)
249  if(nint(freq_chk).ne.0) cycle ! do not want non-zero freq., go on to next replication of ROSEQ2
250  freq = data1b(m,k)
251  impact = data1b(m+1,k) ! impact parameter (m)
252  bend = data1b(m+2,k) ! bending angle (rad)
253  bend_error = data1b(m+4,k) ! RMSE in bending angle (rad)
254  enddo
255 
256  bend_pccf=data1b((6*nreps_roseq2_int)+4,k) ! percent confidence for this ROSEQ1 replication
257  good=.true.
258 
259  if ( height<0._r_kind .or. height>60000._r_kind .or. &
260  abs(rlat)>90._r_kind .or. abs(rlon)>360._r_kind ) then
261  good=.false.
262  if (verbose) write(6,*)'READ_GNSSRO: obs fails georeality check, said=',said,'ptid=',ptid
263  endif
264  if ( bend>=1.e+9_r_kind .or. bend<=0._r_kind .or. impact>=1.e+9_r_kind .or. impact<roc .or. bendflag == 1 ) then
265  good=.false.
266  if (verbose) write(6,*)'READ_GNSSRO: obs bend/impact is invalid, said=',said,'ptid=',ptid
267  endif
268 
269  if ( ref>=1.e+9_r_kind .or. ref<=0._r_kind .or. refflag == 1 ) then
270  ref = missingvalue
271  endif
272 
273  if ( abs(azim)>360._r_kind .or. azim<0._r_kind ) then
274  azim = missingvalue
275  endif
276 
277  if(good) then
278  ndata = ndata +1
279  gpsro_data%recn(ndata) = nrec
280  gpsro_data%lat(ndata) = rlat
281  gpsro_data%lon(ndata) = rlon
282  gpsro_data%time(ndata) = timeo
283  gpsro_data%datetime(ndata) = datetime
284  gpsro_data%said(ndata) = said
285  gpsro_data%sclf(ndata) = sclf
286  gpsro_data%asce(ndata) = asce
287  gpsro_data%ptid(ndata) = ptid
288  gpsro_data%ref(ndata) = ref
289  gpsro_data%msl_alt(ndata) = height
290  gpsro_data%bend_ang(ndata) = bend
291  gpsro_data%bndoe_gsi(ndata) = bend_error
292  gpsro_data%impact_para(ndata) = impact!
293  gpsro_data%rfict(ndata) = roc
294  gpsro_data%geoid(ndata) = geoid
295  gpsro_data%azim(ndata) = azim
296  CALL bendingangle_err_gsi(rlat,impact-roc, obserr)
297  gpsro_data%bndoe_gsi(ndata) = obserr
298  if ( ref > missingvalue) then
299  CALL refractivity_err_gsi(rlat,height, globalmodel, obserr)
300  gpsro_data%refoe_gsi(ndata) = obserr
301  else
302  gpsro_data%refoe_gsi(ndata) = missingvalue
303  end if
304  end if
305 
306  end do ! end of k loop
307 
308  if (ndata == ndata0) nrec = nrec -1
309 
310  enddo read_loop
311 end do
312 
313 call closbf(lnbufr)
314 if (nrec==0) then
315  write(6,*) "Error. No valid observations found. Cannot create NetCDF ouput."
316  stop 2
317 endif
318 
319 call check( nf90_create(trim(outfile), nf90_netcdf4, ncid))
320 call check( nf90_def_dim(ncid, 'nlocs', ndata, nlocs_dimid) )
321 call check( nf90_def_dim(ncid, 'nrecs', nrec, nrecs_dimid) )
322 call check( nf90_def_dim(ncid, 'nobs', ndata*nvars, nobs_dimid) )
323 call check( nf90_def_dim(ncid, 'nvars', nvars, nvars_dimid) )
324 call check( nf90_def_dim(ncid, 'ndatetime', ndatetime, ndatetime_dimid) )
325 call check( nf90_put_att(ncid, nf90_global, 'date_time', anatime_i) )
326 call check( nf90_def_var(ncid, "latitude@MetaData", nf90_float, nlocs_dimid, varid_lat) )
327 call check( nf90_def_var(ncid, "longitude@MetaData", nf90_float, nlocs_dimid, varid_lon) )
328 call check( nf90_def_var(ncid, "time@MetaData", nf90_float, nlocs_dimid, varid_time) )
329 call check( nf90_put_att(ncid, varid_time, "longname", "time offset to analysis time" ))
330 call check( nf90_put_att(ncid, varid_time, "units", "hour" ))
331 call check( nf90_def_var(ncid, "datetime@MetaData", nf90_char, (/ ndatetime_dimid, nlocs_dimid /), varid_datetime) )
332 call check( nf90_def_var(ncid, "record_number@MetaData", nf90_int, nlocs_dimid, varid_recn))
333 call check( nf90_put_att(ncid, varid_recn, "longname", "GNSS RO profile identifier" ))
334 call check( nf90_def_var(ncid, "gnss_sat_class@MetaData", nf90_int, nlocs_dimid, varid_sclf))
335 call check( nf90_put_att(ncid, varid_sclf, "longname", "GNSS satellite classification, e.g, 401=GPS, 402=GLONASS" ))
336 call check( nf90_def_var(ncid, "reference_sat_id@MetaData", nf90_int, nlocs_dimid, varid_ptid))
337 call check( nf90_put_att(ncid, varid_ptid, "longname", "GNSS satellite transmitter identifier (1-32)" ))
338 call check( nf90_def_var(ncid, "occulting_sat_id@MetaData", nf90_int, nlocs_dimid, varid_said))
339 call check( nf90_put_att(ncid, varid_said, "longname", "Low Earth Orbit satellite identifier, e.g., COSMIC2=750-755" ))
340 call check( nf90_def_var(ncid, "ascending_flag@MetaData", nf90_int, nlocs_dimid, varid_asce))
341 call check( nf90_put_att(ncid, varid_asce, "longname", "the original occultation ascending/descending flag" ))
342 call check( nf90_put_att(ncid, varid_asce, "valid_range", "0/descending or 1/ascending" ))
343 call check( nf90_def_var(ncid, "refractivity@ObsValue", nf90_float, nlocs_dimid, varid_ref) )
344 call check( nf90_put_att(ncid, varid_ref, "longname", "Atmospheric refractivity" ))
345 call check( nf90_put_att(ncid, varid_ref, "_FillValue", real(missingvalue) ))
346 call check( nf90_put_att(ncid, varid_ref, "units", "N" ))
347 call check( nf90_put_att(ncid, varid_ref, "valid_range", "0 - 500 N" ))
348 call check( nf90_def_var(ncid, "refractivity@ObsError", nf90_float, nlocs_dimid, varid_refoe))
349 call check( nf90_put_att(ncid, varid_refoe, "longname", "Input error in atmospheric refractivity" ))
350 call check( nf90_put_att(ncid, varid_refoe, "_FillValue", real(missingvalue) ))
351 call check( nf90_put_att(ncid, varid_refoe, "units", "N" ))
352 call check( nf90_put_att(ncid, varid_refoe, "valid_range", "0 - 10 N" ))
353 call check( nf90_def_var(ncid, "altitude@MetaData", nf90_float, nlocs_dimid, varid_msl) )
354 call check( nf90_put_att(ncid, varid_msl, "longname", "Geometric altitude" ))
355 call check( nf90_put_att(ncid, varid_msl, "units", "Meters" ))
356 call check( nf90_def_var(ncid, "bending_angle@ObsValue", nf90_float, nlocs_dimid, varid_bnd) )
357 call check( nf90_put_att(ncid, varid_bnd, "longname", "Bending Angle" ))
358 call check( nf90_put_att(ncid, varid_bnd, "units", "Radians" ))
359 call check( nf90_put_att(ncid, varid_bnd, "valid_range", "-0.001 - 0.08 Radians" ))
360 call check( nf90_def_var(ncid, "bending_angle@ObsError", nf90_float, nlocs_dimid, varid_bndoe) )
361 call check( nf90_put_att(ncid, varid_bndoe, "longname", "Input error in Bending Angle" ))
362 call check( nf90_put_att(ncid, varid_bndoe, "units", "Radians" ))
363 call check( nf90_put_att(ncid, varid_bndoe, "valid_range", "0 - 0.008 Radians" ))
364 call check( nf90_def_var(ncid, "impact_parameter@MetaData", nf90_float, nlocs_dimid, varid_impp))
365 call check( nf90_put_att(ncid, varid_impp, "longname", "distance from centre of curvature" ))
366 call check( nf90_put_att(ncid, varid_impp, "units", "Meters" ))
367 call check( nf90_put_att(ncid, varid_impp, "valid_range", "6200 - 6600 km" ))
368 call check( nf90_def_var(ncid, "impact_height@MetaData", nf90_float, nlocs_dimid, varid_imph))
369 call check( nf90_put_att(ncid, varid_imph, "longname", "distance from mean sea level" ))
370 call check( nf90_put_att(ncid, varid_imph, "units", "Meters" ))
371 call check( nf90_put_att(ncid, varid_imph, "valid_range", "0 - 200 km" ))
372 call check( nf90_def_var(ncid, "sensor_azimuth_angle@MetaData", nf90_float, nlocs_dimid, varid_azim))
373 call check( nf90_put_att(ncid, varid_azim, "longname", "GNSS->LEO line of sight" ))
374 call check( nf90_put_att(ncid, varid_azim, "_FillValue", real(missingvalue) ))
375 call check( nf90_put_att(ncid, varid_azim, "units", "Degree" ))
376 call check( nf90_put_att(ncid, varid_azim, "valid_range", "0 - 360 degree" ))
377 call check( nf90_def_var(ncid, "geoid_height_above_reference_ellipsoid@MetaData",nf90_float, nlocs_dimid, varid_geoid))
378 call check( nf90_put_att(ncid, varid_geoid, "longname", "Geoid height above WGS-84 ellipsoid" ))
379 call check( nf90_put_att(ncid, varid_geoid, "units", "Meters" ))
380 call check( nf90_put_att(ncid, varid_geoid, "valid_range", "-200 - 200 m" ))
381 call check( nf90_def_var(ncid, "earth_radius_of_curvature@MetaData",nf90_float, nlocs_dimid, varid_rfict))
382 call check( nf90_put_att(ncid, varid_rfict, "longname", ’"Earths local radius of curvature" ))
383 call check( nf90_put_att(ncid, varid_rfict, "units", "Meters" ))
384 call check( nf90_put_att(ncid, varid_rfict, "valid_range", "6200 - 6600 km" ))
385 call check( nf90_enddef(ncid) )
386 
387 call check( nf90_put_var(ncid, varid_lat, gpsro_data%lat(1:ndata)) )
388 call check( nf90_put_var(ncid, varid_lon, gpsro_data%lon(1:ndata)) )
389 call check( nf90_put_var(ncid, varid_time, gpsro_data%time(1:ndata)) )
390 call check( nf90_put_var(ncid, varid_datetime, gpsro_data%datetime(1:ndata)) )
391 call check( nf90_put_var(ncid, varid_recn, gpsro_data%recn(1:ndata)) )
392 call check( nf90_put_var(ncid, varid_said, gpsro_data%said(1:ndata)) )
393 call check( nf90_put_var(ncid, varid_ptid, gpsro_data%ptid(1:ndata)) )
394 call check( nf90_put_var(ncid, varid_sclf, gpsro_data%sclf(1:ndata)) )
395 call check( nf90_put_var(ncid, varid_asce, gpsro_data%asce(1:ndata)) )
396 call check( nf90_put_var(ncid, varid_ref, gpsro_data%ref(1:ndata)) )
397 call check( nf90_put_var(ncid, varid_refoe, gpsro_data%refoe_gsi(1:ndata)) )
398 call check( nf90_put_var(ncid, varid_msl, gpsro_data%msl_alt(1:ndata)) )
399 call check( nf90_put_var(ncid, varid_bnd, gpsro_data%bend_ang(1:ndata)) )
400 call check( nf90_put_var(ncid, varid_bndoe, gpsro_data%bndoe_gsi(1:ndata)) )
401 call check( nf90_put_var(ncid, varid_impp, gpsro_data%impact_para(1:ndata)) )
402 call check( nf90_put_var(ncid, varid_imph, gpsro_data%impact_para(1:ndata)-gpsro_data%rfict(1:ndata)-gpsro_data%geoid(1:ndata) ) )
403 call check( nf90_put_var(ncid, varid_azim, gpsro_data%azim(1:ndata)) )
404 call check( nf90_put_var(ncid, varid_geoid, gpsro_data%geoid(1:ndata)) )
405 call check( nf90_put_var(ncid, varid_rfict, gpsro_data%rfict(1:ndata)) )
406 call check( nf90_close(ncid) )
407 
408 deallocate(gpsro_data%said)
409 deallocate(gpsro_data%sclf)
410 deallocate(gpsro_data%ptid)
411 deallocate(gpsro_data%recn)
412 deallocate(gpsro_data%asce)
413 deallocate(gpsro_data%time)
414 deallocate(gpsro_data%datetime)
415 deallocate(gpsro_data%lat)
416 deallocate(gpsro_data%lon)
417 deallocate(gpsro_data%rfict)
418 deallocate(gpsro_data%azim)
419 deallocate(gpsro_data%geoid)
420 deallocate(gpsro_data%msl_alt)
421 deallocate(gpsro_data%ref)
422 deallocate(gpsro_data%refoe_gsi)
423 deallocate(gpsro_data%bend_ang)
424 deallocate(gpsro_data%impact_para)
425 deallocate(gpsro_data%bndoe_gsi)
426 
427 end subroutine read_write_gnssro
428 
429 !contains
430  subroutine check(status)
431  integer, intent ( in) :: status
432 
433  if(status /= nf90_noerr) then
434  print *, trim(nf90_strerror(status))
435  stop "Stopped"
436  end if
437 
438  end subroutine check
439 
440 
441 subroutine refractivity_err_gsi(obsLat, obsZ, GlobalModel, obsErr)
442 real(r_double), intent(in) :: obsLat, obsZ
443 real(r_double), intent(out) :: obsErr
444 logical, intent(in) :: GlobalModel
445 real(r_double) :: obsZ_km
446 
447 obsz_km = obsz / 1000.0
448 
449 if( globalmodel ) then ! for global
450 
451  if( obslat>= 20.0 .or.obslat<= -20.0 ) then
452  obserr=-1.321_r_kind+0.341_r_kind*obsz_km-0.005_r_kind*obsz_km**2
453  else
454  if(obsz_km > 10.0) then
455  obserr=2.013_r_kind-0.060_r_kind*obsz_km+0.0045_r_kind*obsz_km**2
456  else
457  obserr=-1.18_r_kind+0.058_r_kind*obsz_km+0.025_r_kind*obsz_km**2
458  endif
459  endif
460  obserr = 1.0_r_kind/abs(exp(obserr))
461 
462 else ! for regional
463  if( obslat >= 20.0 .or.obslat <= -20.0 ) then
464  if (obsz_km > 10.00) then
465  obserr =-1.321_r_kind+0.341_r_kind*obsz_km-0.005_r_kind*obsz_km**2
466  else
467  obserr =-1.2_r_kind+0.065_r_kind*obsz_km+0.021_r_kind*obsz_km**2
468  endif
469  else
470  if(obsz_km > 10.00) then
471  obserr =2.013_r_kind-0.120_r_kind*obsz_km+0.0065_r_kind*obsz_km**2
472  else
473  obserr =-1.19_r_kind+0.03_r_kind*obsz_km+0.023_r_kind*obsz_km**2
474  endif
475  endif
476  obserr = 1.0_r_kind/abs(exp(obserr))
477 endif
478 
479 end subroutine refractivity_err_gsi
480 
481 subroutine bendingangle_err_gsi(obsLat, obsZ, obsErr)
482 real(r_double), intent(in) :: obsLat, obsZ
483 real(r_double), intent(out) :: obsErr
484 real(r_double) :: obsZ_km
485 
486 obsz_km = obsz / 1000.0
487 if((said==41).or.(said==722).or.(said==723).or.(said==4).or.(said==42).or.&
488  (said==3).or.(said==821.or.(said==421)).or.(said==440).or.(said==43)) then
489  if( abs(obslat)>= 40.00 ) then
490 
491  if(obsz_km>12.) then
492  obserr=0.19032_r_kind+0.287535_r_kind*obsz_km-0.00260813_r_kind*obsz_km**2
493  else
494  obserr=-3.20978_r_kind+1.26964_r_kind*obsz_km-0.0622538_r_kind*obsz_km**2
495  endif
496  else
497  if(obsz_km>18.) then
498  obserr=-1.87788_r_kind+0.354718_r_kind*obsz_km-0.00313189_r_kind*obsz_km**2
499  else
500  obserr=-2.41024_r_kind+0.806594_r_kind*obsz_km-0.027257_r_kind*obsz_km**2
501  endif
502  endif
503  obserr = 0.001_r_kind/abs(exp(obserr))
504 
505  else !!!! CDAAC processing
506  if( abs(obslat)>= 40.00 ) then
507  if (obsz_km > 12.00) then
508  obserr=-0.685627_r_kind+0.377174_r_kind*obsz_km-0.00421934_r_kind*obsz_km**2
509  else
510  obserr=-3.27737_r_kind+1.20003_r_kind*obsz_km-0.0558024_r_kind*obsz_km**2
511  endif
512  else
513  if(obsz_km >18.00) then
514  obserr=-2.73867_r_kind+0.447663_r_kind*obsz_km-0.00475603_r_kind*obsz_km**2
515  else
516  obserr=-3.45303_r_kind+0.908216_r_kind*obsz_km-0.0293331_r_kind*obsz_km**2
517  endif
518  endif
519  obserr = 0.001_r_kind/abs(exp(obserr))
520 
521 endif
522 
523 end subroutine bendingangle_err_gsi
524 !!!!!!________________________________________________________
525 
526 !!!!!! SUBROUTINE W3FS21 was copied from GSI/src/libs/w3nco_v2.0.6/w3fs21.f and iw3jdn.f
527 SUBROUTINE w3fs21(IDATE, NMIN)
528  INTEGER IDATE(5)
529  INTEGER NMIN
530  INTEGER IYEAR, NDAYS, IJDN
531  INTEGER JDN78
532  DATA jdn78 / 2443510 /
533  nmin = 0
534 
535  iyear = idate(1)
536 
537  IF (iyear.LE.99) THEN
538  IF (iyear.LT.78) THEN
539  iyear = iyear + 2000
540  ELSE
541  iyear = iyear + 1900
542  ENDIF
543  ENDIF
544 
545 ! COMPUTE JULIAN DAY NUMBER FROM YEAR, MONTH, DAY
546  ijdn = idate(3) - 32075 &
547  + 1461 * (iyear + 4800 + (idate(2) - 14) / 12) / 4 &
548  + 367 * (idate(2)- 2 - (idate(2) -14) / 12 * 12) / 12 &
549  - 3 * ((iyear + 4900 + (idate(2) - 14) / 12) / 100) / 4
550 
551 ! SUBTRACT JULIAN DAY NUMBER OF JAN 1,1978 TO GET THE
552 ! NUMBER OF DAYS BETWEEN DATES
553  ndays = ijdn - jdn78
554  nmin = ndays * 1440 + idate(4) * 60 + idate(5)
555  RETURN
556 END SUBROUTINE w3fs21
557 
558 !end program
559 end module gnssro_bufr2ioda
subroutine bendingangle_err_gsi(obsLat, obsZ, obsErr)
subroutine refractivity_err_gsi(obsLat, obsZ, GlobalModel, obsErr)
subroutine check(status)
subroutine w3fs21(IDATE, NMIN)
integer(i_kind) said
Definition: gnssro_mod.f90:17
integer, parameter i_short
Definition: gnssro_mod.f90:12
integer, parameter r_kind
Definition: gnssro_mod.f90:15
integer, parameter r_double
Definition: gnssro_mod.f90:14
subroutine read_write_gnssro(infile, outdir)
Definition: gnssro_mod.f90:23
integer, parameter i_kind
Definition: gnssro_mod.f90:13