1 subroutine da_read_obs_bufrgpsro_eph (iv)
3 !---------------------------------------------------------------------------
4 ! Purpose: Read NCEP GPSRO BUFR observation file for input to wrfvar
5 !---------------------------------------------------------------------------
6 ! METHOD: use F90 sequantial data structure to avoid reading the file twice
7 ! 1. read gpsro data in sequential data structure
9 ! 3. assign sequential data structure to innovation structure
10 ! and deallocate sequential data structure
12 ! HISTORY: 2009/12/17 - F90 sequantial structure Peng Xiu
13 ! Nov. 2015 - added the option for the assimilation of
14 ! gps excess phase which requires the input data
17 !----------------------------------------------------------------------------
23 type (iv_type), intent(inout) :: iv
27 real, parameter :: r8bfms = 9.0D08 ! BUFR missing value threshold
28 integer, parameter :: maxlevs = 500
29 integer :: iunit, iost, idate, iret, nlev1, nlev2,k,i, nlev_bad
30 integer :: num_report, num_outside_all, num_outside_time
31 integer :: iyear,imonth,iday,ihour,imin
32 integer :: ntotal, nlocal, nlev, ref_qc, iobs
35 real :: ntotal_ifgat(0:num_fgat_time)
36 real*8 :: rdata1(25,maxlevs), rdata2(25,maxlevs)
37 real :: height, ref_data, ref_error
39 character(len=8) :: subset
40 character(len=80) :: hdstr
41 logical :: outside, outside_all
42 type(info_type) :: info !for input to llxy
43 type(model_loc_type) :: loc !for output from llxy
44 character(len=5) :: id
45 character(len=19) :: date_char
46 character(len=12) :: platform_name
48 integer :: err_opt ! 1: WRF-Var/obsproc, 2: GSI
49 real :: erh90, erh0, err90, err0
50 integer(i_kind) :: ireadns
51 type datalink_gpsro !for gpsro data reading
52 type (info_type) :: info
53 type (model_loc_type) :: loc
54 type (gpsref_type) :: gpsref
56 real :: rfict !to be used for gpseph
57 real, allocatable :: azim(:) !to be used for gpseph
58 real, allocatable :: lat(:) !to be used for gpseph
59 real, allocatable :: lon(:) !to be used for gpseph
60 integer :: obs_global_index
61 type(datalink_gpsro), pointer :: next
62 end type datalink_gpsro
63 type(datalink_gpsro),pointer :: head=>null(), plink=>null()
64 type(ob_in_mean_h) :: pseudo_ob
67 integer :: lowest_level
68 integer,parameter :: nfile_max = 8
69 integer :: nfile, ifile, max_lev
70 character(80) :: fname(nfile_max)
71 character(80) :: infile_prefix, fname_tmp
73 logical :: treat_as_profile
75 if (trace_use) call da_trace_entry("da_read_obs_bufrgpsro_eph")
77 treat_as_profile = .false.
78 platform_name = 'FM-116 GPSRF'
79 if ( use_gpsephobs ) then
80 treat_as_profile = .true.
81 platform_name = 'FM-118 GPSEP'
85 infile_prefix = 'gpsro'
92 ntotal_ifgat(0:num_fgat_time)=0
94 ! checking for input files
96 fname(:) = '' !initialize
97 ! first check if gpsro.bufr is available
98 fname_tmp = trim(infile_prefix)//'.bufr'
99 inquire (file=fname_tmp, exist=fexist)
102 fname(nfile) = fname_tmp
104 ! check if gpsro-0x.bufr is available for multiple input files
105 ! here 0x is the input file sequence number
106 ! do not confuse it with fgat time slot index
108 write(fname_tmp,fmt='(A,A,I2.2,A)') trim(infile_prefix),'-',i,'.bufr'
109 inquire (file=fname_tmp, exist=fexist)
112 fname(nfile) = fname_tmp
119 if ( nfile == 0 ) then
120 call da_warning(__FILE__,__LINE__, &
121 (/"No valid NCEP BUFR gpsro.bufr or gpsro-01.bufr file found."/))
122 if (trace_use) call da_trace_exit("da_read_obs_bufrgpsro_eph")
126 bufrfile: do ifile = 1, nfile
128 ! Use specified unit number, so we can control its endian format in environment.
131 open(unit=iunit, file=trim(fname(ifile)), &
132 iostat=iost, form='unformatted', status='OLD')
134 write(unit=message(1),fmt='(A,I5,A)') &
135 "Error",iost," opening PREPBUFR obs file "//trim(fname(ifile))
136 call da_warning(__FILE__,__LINE__,message(1:1))
137 if (trace_use) call da_trace_exit("da_read_obs_bufrgpsro_eph")
141 !--------------------------------
142 ! open bufr file then check date
143 !--------------------------------
144 call openbf(iunit,'IN',iunit)
146 call readmg(iunit,subset,idate,iret)
147 if ( iret /= 0 ) then
148 write(unit=message(1),fmt='(A,I5,A)') &
149 "Error",iret," reading GPSRO BUFR obs file "//trim(fname(ifile))
150 call da_warning(__FILE__,__LINE__,message(1:1))
153 if (trace_use) call da_trace_exit("da_read_obs_bufrgpsro_eph")
156 write(unit=message(1),fmt='(a,i10)') 'GPSRO BUFR file date is: ', idate
157 call da_message(message(1:1))
160 hdstr = 'YEAR MNTH DAYS HOUR MINU PCCF ELRC SAID PTID GEODU CLATH CLONH'
162 reports: do while ( ireadns(iunit,subset,idate) == 0 )
164 num_report = num_report + 1
166 call ufbint(iunit,hdr,12,1,iret,hdstr)
174 write(id, '(i3.3,i2.2)') int(hdr(8)), int(hdr(9)) ! construct id using SAID and PTID
175 write(date_char, fmt='(i4,a,i2.2,a,i2.2,a,i2.2,a,i2.2,a,i2.2)') &
176 iyear, '-', imonth, '-', iday, '_', ihour, ':', imin, ':', 0
179 call da_get_julian_time (iyear,imonth,iday,ihour,imin,obs_time)
180 if (obs_time < time_slots(0) .or. &
181 obs_time >= time_slots(num_fgat_time)) then
182 num_outside_time = num_outside_time + 1
183 if ( print_detail_obs ) then
184 write(unit=stderr,fmt='(a,1x,i4.4,4i2.2,a)') &
185 info%id(1:5),iyear,imonth,iday,ihour,imin, ' -> outside_time'
190 ! determine FGAT index ifgat
191 do ifgat=1,num_fgat_time
192 if (obs_time >= time_slots(ifgat-1) .and. &
193 obs_time < time_slots(ifgat)) exit
196 if ( hdr(6) < 100.0 ) then ! check percentage of confidence PCCF
200 call ufbseq(iunit,rdata1,25,maxlevs,nlev1,'ROSEQ1') ! RAOC PROFILE LOCATIONS SEQUENCE
201 call ufbseq(iunit,rdata2,25,maxlevs,nlev2,'ROSEQ3') ! RAOC HEIGHT/REFRACTIVITY SEQUENCE
203 if ( nlev1 /= nlev2 ) then
207 if ( treat_as_profile ) then
208 !only one lat/lon (perigee point at occultation point)
209 !for each report that contains multiple levels of data
212 ! gpsro.bufr contains missing longitude, occasionally
213 if ( info%lat > r8bfms .or. info%lon > r8bfms ) then
217 info%lat = max(info%lat, -89.95)
218 info%lat = min(info%lat, 89.95)
219 call da_llxy(info, loc, outside, outside_all)
220 if ( outside_all ) then
221 num_outside_all = num_outside_all + 1
222 if ( print_detail_obs ) then
223 write(unit=stderr,fmt='(a,2(1x,f8.3),a)') &
224 id(1:5), info%lat, info%lon, ' -> outside_domain'
232 !info%lat = rdata1(1,k)
233 !info%lon = rdata1(2,k)
235 !height = rdata2(1,k)
236 !ref_data = rdata2(2,k)
237 if ( abs(rdata1(1,k)) > 90.0 .or. abs(rdata1(2,k)) > 180.0 .or. &
238 abs(rdata1(3,k)) > 180.0 .or. rdata2(1,k) > r8bfms .or. &
239 rdata2(2,k) > r8bfms ) then
240 nlev_bad = nlev_bad + 1
243 if ( nlev_bad == nlev1 ) cycle reports
246 ntotal_ifgat(ifgat)=ntotal_ifgat(ifgat)+1
247 if ( use_gpsephobs .and. gpseph_loadbalance ) then
248 if ( myproc /= MOD((ntotal-1), num_procs) ) cycle reports
250 if ( outside ) cycle reports
255 if (.not. associated(head)) then
258 nullify ( head%next )
261 allocate ( plink%next )
263 nullify ( plink%next )
266 write(info%name, '(a,i6.6,a,a)') 'NCEP_GPSRO_', nlocal, '_', date_char
269 max_lev = max(max_lev, nlev)
271 plink%info%name = info%name
272 plink%info%platform = platform_name
274 plink%info%date_char = date_char
275 plink%info%levels = nlev
276 plink%info%elv = 0.0 ! not used
277 plink%info%lat = info%lat
278 plink%info%lon = info%lon
283 plink%loc%dx = loc%dx
284 plink%loc%dxm = loc%dxm
285 plink%loc%dy = loc%dy
286 plink%loc%dym = loc%dym
288 plink%obs_global_index = ntotal
291 plink%rfict = hdr(7)*0.001 !ELRC: EARTH LOC RADIUS OF CURVATURE
293 allocate (plink%gpsref%h (1:nlev))
294 allocate (plink%gpsref%ref(1:nlev))
295 if ( use_gpsephobs ) then
296 allocate (plink%azim(1:nlev))
297 allocate (plink%lat(1:nlev))
298 allocate (plink%lon(1:nlev))
300 end if !treat_as_profile
304 lev_loop: do k = 1, nlev1
306 info%lat = rdata1(1,k)
307 info%lon = rdata1(2,k)
310 ref_data = rdata2(2,k)
311 ref_qc = 0 ! initialized to be good
313 if ( .not. treat_as_profile ) then
315 ! gpsro.bufr contains missing longitude, occasionally
316 if ( info%lat > r8bfms .or. info%lon > r8bfms ) then
320 ! check for missing data
321 if ( height > r8bfms .or. ref_data > r8bfms ) then
326 info%lat = max(info%lat, -89.95)
327 info%lat = min(info%lat, 89.95)
328 call da_llxy(info, loc, outside, outside_all)
329 if ( outside_all ) then
330 num_outside_all = num_outside_all + 1
331 if ( print_detail_obs ) then
332 write(unit=stderr,fmt='(a,2(1x,f8.3),a)') &
333 id(1:5), info%lat, info%lon, ' -> outside_domain'
338 ntotal_ifgat(ifgat)=ntotal_ifgat(ifgat)+1
345 if ( treat_as_profile ) then
347 plink%lat(k) = missing_r
348 plink%lon(k) = missing_r
349 plink%gpsref%h(k) = missing_r
350 plink%gpsref%ref(k)%inv = missing_r
351 plink%gpsref%ref(k)%qc = missing_data
352 plink%gpsref%ref(k)%error = xmiss
353 if ( use_gpsephobs ) then
354 if ( info%lat < r8bfms .and. info%lon < r8bfms .and. &
357 if ( gpsro_drift == 0 ) then
358 plink%lat(k) = plink%info%lat
359 plink%lon(k) = plink%info%lon
361 plink%lat(k) = info%lat
362 plink%lon(k) = info%lon
366 if ( height < r8bfms .and. ref_data < r8bfms ) then
367 plink%gpsref%h(k) = height
368 plink%gpsref%ref(k)%inv = ref_data
369 plink%gpsref%ref(k)%qc = ref_qc
370 plink%gpsref%ref(k)%error = ref_error
372 end if !treat_as_profile
374 if ( ref_data < r8bfms ) then ! non-missing data
375 ref_error = ref_data * 0.01
378 if ( height < r8bfms .and. info%lat < r8bfms ) then ! non-missing height
380 ! check height, only keep data below certain height (default is 30km)
381 if ( height > top_km_gpsro*1000.0 .or. &
382 height < bot_km_gpsro*1000.0 ) then
387 ! observation errors WRF-Var/obsproc
388 if ( err_opt == 1 ) then
389 if ( height >= 12000.0 ) then
390 ref_error = ref_error * 0.3
392 erh90 = (0.3-1.5)*(height-12000.0)/(12000.0-0.0) + 0.3
393 if ( height >= 5500.0 ) then
394 erh0 = (0.3-1.3)*(height-12000.0)/(12000.0-5500.0) + 0.3
395 else if ( height >= 2500.0) then
396 erh0 = (1.3-2.5)*(height-5500.0)/(5500.0-2500.0) + 1.3
400 err90 = ref_error * erh90
401 err0 = ref_error * erh0
402 ref_error = err90 - (1.0-abs(info%lat)/90.0)*(err90-err0)
406 ! observation errors GSI_Q1FY09, Kuo et al. 2003
407 if ( err_opt == 2 ) then
408 if ( (info%lat >= -30.0) .and. (info%lat <= 30.0) ) then ! tropics
409 if ( (height >= 7000.0) .and. (height <= 31000.0) ) then
410 ref_error = ref_error*(0.1125+(1.25e-5*height))
411 else if ( height > 31000.0 ) then
412 ref_error = ref_error*0.5
413 else if ( height < 7000.0 ) then
414 ref_error = ref_error*(3.0-(4.0e-4*height))
416 write(unit=message(1),fmt='(a,f8.1,a,f8.2)') 'unable to process with height = ', &
417 height, ' at lat = ', info%lat
418 call da_error(__FILE__,__LINE__,message(1:1))
421 if ( (height >= 5000.0) .and. (height <= 25000.0) ) then
422 ref_error = ref_error*0.3
423 else if ( (height >= 25000.0) .and. (height <= 31000.0) ) then
424 ref_error = ref_error*(-3.45+(1.5e-4*height))
425 else if ( height > 31000.0 ) then
426 ref_error = ref_error*1.2
427 else if ( height < 5000.0 ) then
428 ref_error = ref_error*(0.75-(9.0e-5*height))
430 write(unit=message(1),fmt='(a,f8.1,a,f8.2)') 'unable to process with height = ', &
431 height, ' at lat = ', info%lat
432 call da_error(__FILE__,__LINE__,message(1:1))
437 end if ! non-missing height
439 !write(info%name, '(a,i6.6,a,a)') 'NCEP_GPSRO_', nlocal, '_', date_char
440 write(info%name, '(a,i6.6,a,a)') 'NCEP_GPSRO_', iprof, '_', date_char
442 if ( print_detail_obs ) then
443 write(unit=stdout,fmt='(a,1x,a,1x,i4.4,4i2.2,2f8.2,f8.1,f8.2,i3,f9.5)') &
444 info%name,id(1:5),iyear,imonth,iday,ihour,imin, &
445 info%lat,info%lon,height,ref_data,ref_qc,ref_error
448 if ( .not. treat_as_profile ) then
449 if (.not. associated(head)) then
452 nullify ( head%next )
455 allocate ( plink%next )
457 nullify ( plink%next )
460 plink%info%name = info%name
461 plink%info%platform = platform_name
463 plink%info%date_char = date_char
464 plink%info%levels = 1 ! each level is treated as separate obs
465 plink%info%elv = 0.0 ! not used
466 plink%info%lat = info%lat
467 plink%info%lon = info%lon
472 plink%loc%dx = loc%dx
473 plink%loc%dxm = loc%dxm
474 plink%loc%dy = loc%dy
475 plink%loc%dym = loc%dym
477 plink%obs_global_index = ntotal
480 allocate (plink%gpsref%h (1:1))
481 allocate (plink%gpsref%ref(1:1))
482 plink%gpsref%h(1) = height
483 plink%gpsref%ref(1)%inv = ref_data
484 plink%gpsref%ref(1)%qc = ref_qc
485 plink%gpsref%ref(1)%error = ref_error
487 end if !not treat_as_profile
497 ! assign data in either iv%gpsref or iv%gpseph
498 if ( use_gpsephobs ) then
500 !re-set mex_lev for pseudo_ob on model mean height levels
502 allocate (pseudo_ob%ref(kds:kde))
503 allocate (pseudo_ob%lat(kds:kde))
504 allocate (pseudo_ob%lon(kds:kde))
505 allocate (pseudo_ob%azim(kds:kde))
510 iv%info(obs_index)%max_lev = max_lev
511 iv%info(obs_index)%ntotal = ntotal
512 iv%info(obs_index)%nlocal = nlocal
516 if (iv%info(obs_index)%nlocal > 0) then
517 allocate (iv%info(obs_index)%name(iv%info(obs_index)%nlocal))
518 allocate (iv%info(obs_index)%platform(iv%info(obs_index)%nlocal))
519 allocate (iv%info(obs_index)%id(iv%info(obs_index)%nlocal))
520 allocate (iv%info(obs_index)%date_char(iv%info(obs_index)%nlocal))
521 allocate (iv%info(obs_index)%levels(iv%info(obs_index)%nlocal))
522 allocate (iv%info(obs_index)%lat(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
523 allocate (iv%info(obs_index)%lon(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
524 allocate (iv%info(obs_index)%elv(iv%info(obs_index)%nlocal))
525 allocate (iv%info(obs_index)%pstar(iv%info(obs_index)%nlocal))
526 allocate (iv%info(obs_index)%slp(iv%info(obs_index)%nlocal))
527 allocate (iv%info(obs_index)%pw(iv%info(obs_index)%nlocal))
528 allocate (iv%info(obs_index)%x (kms:kme,iv%info(obs_index)%nlocal))
529 allocate (iv%info(obs_index)%y (kms:kme,iv%info(obs_index)%nlocal))
530 allocate (iv%info(obs_index)%i (kms:kme,iv%info(obs_index)%nlocal))
531 allocate (iv%info(obs_index)%j (kms:kme,iv%info(obs_index)%nlocal))
532 allocate (iv%info(obs_index)%dx (kms:kme,iv%info(obs_index)%nlocal))
533 allocate (iv%info(obs_index)%dxm(kms:kme,iv%info(obs_index)%nlocal))
534 allocate (iv%info(obs_index)%dy (kms:kme,iv%info(obs_index)%nlocal))
535 allocate (iv%info(obs_index)%dym(kms:kme,iv%info(obs_index)%nlocal))
536 allocate (iv%info(obs_index)%k (iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
537 allocate (iv%info(obs_index)%dz (iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
538 allocate (iv%info(obs_index)%dzm(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
539 allocate (iv%info(obs_index)%zk (iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
540 allocate (iv%info(obs_index)%proc_domain(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
541 allocate (iv%info(obs_index)%thinned(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
542 allocate (iv%info(obs_index)%obs_global_index(iv%info(obs_index)%nlocal))
543 iv%info(obs_index)%proc_domain(:,:) = .false.
544 iv%info(obs_index)%thinned(:,:) = .false.
545 iv%info(obs_index)%zk(:,:) = missing_r
548 if ( use_gpsephobs ) then
549 if (iv%info(gpseph)%nlocal > 0) allocate(iv%gpseph(1:iv%info(gpseph)%nlocal))
551 if (iv%info(gpsref)%nlocal > 0) allocate(iv%gpsref(1:iv%info(gpsref)%nlocal))
554 ! sort obs and assign to iv structure
557 do kk = 1, num_fgat_time
559 iv%info(obs_index)%ptotal(kk)=0
561 reports2: do i = 1, iv%info(obs_index)%nlocal
563 if ( plink%ifgat /= kk ) then ! not in current time slot
570 iv%info(obs_index)%name(iobs) = plink%info%name
571 iv%info(obs_index)%platform(iobs) = plink%info%platform
572 iv%info(obs_index)%id(iobs) = plink%info%id
573 iv%info(obs_index)%date_char(iobs) = plink%info%date_char
574 iv%info(obs_index)%levels(iobs) = plink%info%levels
575 iv%info(obs_index)%elv(iobs) = plink%info%elv ! not used
577 iv%info(obs_index)%lat(:,iobs) = plink%info%lat
578 iv%info(obs_index)%lon(:,iobs) = plink%info%lon
579 iv%info(obs_index)%x(:,iobs) = plink%loc%x
580 iv%info(obs_index)%y(:,iobs) = plink%loc%y
581 iv%info(obs_index)%i(:,iobs) = plink%loc%i
582 iv%info(obs_index)%j(:,iobs) = plink%loc%j
583 iv%info(obs_index)%dx(:,iobs) = plink%loc%dx
584 iv%info(obs_index)%dxm(:,iobs) = plink%loc%dxm
585 iv%info(obs_index)%dy(:,iobs) = plink%loc%dy
586 iv%info(obs_index)%dym(:,iobs) = plink%loc%dym
588 iv%info(obs_index)%slp(iobs)%inv = missing_r
589 iv%info(obs_index)%slp(iobs)%qc = missing_data
590 iv%info(obs_index)%slp(iobs)%error = xmiss
591 iv%info(obs_index)%pw(iobs)%inv = missing_r
592 iv%info(obs_index)%pw(iobs)%qc = missing_data
593 iv%info(obs_index)%pw(iobs)%error = xmiss
595 iv%info(obs_index)%obs_global_index(iobs) = plink%obs_global_index
597 if ( use_gpsephobs ) then
598 nlev = plink%info%levels
599 !create pseudo_ob on grid mean altitude for gpseph
600 call da_gpseph_create_ob(nlev, plink%gpsref%h(1:nlev), &
601 plink%gpsref%ref(1:nlev)%inv, &
604 plink%azim(1:nlev), &
605 pseudo_ob, lowest_level)
606 if ( lowest_level < 0 ) then
607 ! no valid levels found for creating ob
608 iv%info(gpseph)%levels(iobs) = 1
609 iv%gpseph(iobs)%level1 = 0
610 iv%gpseph(iobs)%level2 = 0
611 iv%gpseph(iobs)%rfict = plink%rfict
612 !hcl tmp hack: still allocate for 1 level
613 allocate (iv%gpseph(iobs)%h (1))
614 allocate (iv%gpseph(iobs)%ref(1))
615 allocate (iv%gpseph(iobs)%eph(1))
616 allocate (iv%gpseph(iobs)%lat(1))
617 allocate (iv%gpseph(iobs)%lon(1))
618 allocate (iv%gpseph(iobs)%azim(1))
619 iv%gpseph(iobs)%h(1) = global_h_mean(1)*1000.0 !km to m
620 iv%gpseph(iobs)%lat(1) = missing_r
621 iv%gpseph(iobs)%lon(1) = missing_r
622 iv%gpseph(iobs)%azim(1) = missing_r
623 iv%gpseph(iobs)%ref(1)%inv = missing_r
624 iv%gpseph(iobs)%ref(1)%qc = missing_data
625 iv%gpseph(iobs)%ref(1)%error = xmiss
626 iv%gpseph(iobs)%eph(1)%inv = missing_r
627 iv%gpseph(iobs)%eph(1)%qc = missing_data
628 iv%gpseph(iobs)%eph(1)%error = xmiss
630 iv%gpseph(iobs)%level1 = lowest_level+1
631 iv%gpseph(iobs)%level2 = kde-1
632 iv%info(gpseph)%levels(iobs) = max_lev !it is kde-kds+1 for gpseph
633 iv%gpseph(iobs)%rfict = plink%rfict
635 allocate (iv%gpseph(iobs)%h (kds:kde))
636 allocate (iv%gpseph(iobs)%ref(kds:kde))
637 allocate (iv%gpseph(iobs)%eph(kds:kde))
638 ! iv%gpseph includes additional azim/lat/lon info of each level
639 allocate (iv%gpseph(iobs)%lat(kds:kde))
640 allocate (iv%gpseph(iobs)%lon(kds:kde))
641 allocate (iv%gpseph(iobs)%azim(kds:kde))
643 iv%gpseph(iobs)%h(k) = global_h_mean(k)*1000.0 !km to m
644 iv%gpseph(iobs)%lat(k) = pseudo_ob%lat(k)
645 iv%gpseph(iobs)%lon(k) = pseudo_ob%lon(k)
646 iv%gpseph(iobs)%azim(k) = pseudo_ob%azim(k)
647 iv%gpseph(iobs)%ref(k)%inv = pseudo_ob%ref(k)
648 iv%gpseph(iobs)%ref(k)%qc = missing_data !plink%gpsref%ref(i)%qc
649 iv%gpseph(iobs)%ref(k)%error = xmiss !plink%gpsref%ref(i)%error
650 iv%gpseph(iobs)%eph(k)%inv = missing_r
651 iv%gpseph(iobs)%eph(k)%qc = missing_data
652 iv%gpseph(iobs)%eph(k)%error = xmiss
656 else !not use_gpsephobs
658 nlev = plink%info%levels
659 allocate (iv%gpsref(iobs)%h (1:nlev))
660 allocate (iv%gpsref(iobs)%ref(1:nlev))
661 allocate (iv%gpsref(iobs)%p (1:nlev))
662 allocate (iv%gpsref(iobs)%t (1:nlev))
663 allocate (iv%gpsref(iobs)%q (1:nlev))
665 iv%gpsref(iobs)%h(k) = plink%gpsref%h(k)
666 iv%gpsref(iobs)%ref(k)%inv = plink%gpsref%ref(k)%inv
667 iv%gpsref(iobs)%ref(k)%qc = plink%gpsref%ref(k)%qc
668 iv%gpsref(iobs)%ref(k)%error = plink%gpsref%ref(k)%error
670 iv%gpsref(iobs)%p(k)%inv = missing_r
671 iv%gpsref(iobs)%p(k)%qc = missing_data
672 iv%gpsref(iobs)%p(k)%error = xmiss
673 iv%gpsref(iobs)%t(k)%inv = missing_r
674 iv%gpsref(iobs)%t(k)%qc = missing_data
675 iv%gpsref(iobs)%t(k)%error = xmiss
676 iv%gpsref(iobs)%q(k)%inv = missing_r
677 iv%gpsref(iobs)%q(k)%qc = missing_data
678 iv%gpsref(iobs)%q(k)%error = xmiss
681 end if !use_gpsephobs
682 end if ! if current time slot
686 ntotal_ifgat(kk)=ntotal_ifgat(kk)+ntotal_ifgat(kk-1)
687 iv%info(obs_index)%ptotal(kk)=ntotal_ifgat(kk)
688 iv%info(obs_index)%plocal(kk)=iobs
689 ! thinning is not applied to GPSRO BUFR, simply make a copy from total number
690 iv%info(obs_index)%thin_ptotal(kk)=ntotal_ifgat(kk)
691 iv%info(obs_index)%thin_plocal(kk)=iobs
694 write(unit=message(1),fmt='(A,3(1x,i7))') &
695 'da_read_obs_bufrgpsro_eph: num_report, num_outside_all, num_outside_time: ', &
696 num_report, num_outside_all, num_outside_time
697 call da_message(message(1:1))
699 if ( iobs /= iv%info(obs_index)%nlocal ) then
700 call da_error(__FILE__,__LINE__,(/"numbers mismatch between scanning and reading NCEP GSPRO BUFR file"/))
703 if ( use_gpsephobs ) then
704 deallocate (pseudo_ob%ref)
705 deallocate (pseudo_ob%lat)
706 deallocate (pseudo_ob%lon)
707 deallocate (pseudo_ob%azim)
710 ! Release the linked list
713 DO WHILE ( ASSOCIATED (plink) )
715 deallocate (plink%gpsref%h)
716 deallocate (plink%gpsref%ref)
717 if ( use_gpsephobs ) then
718 deallocate (plink%azim)
719 deallocate (plink%lat)
720 deallocate (plink%lon)
728 if (trace_use) call da_trace_exit("da_read_obs_bufrgpsro_eph")
730 call da_error(__FILE__,__LINE__,(/"must compile with BUFR library"/))
733 end subroutine da_read_obs_bufrgpsro_eph