1 subroutine da_setup_obs_structures( grid, ob, iv, j_cost)
3 !---------------------------------------------------------------------------
4 ! Purpose: Allocate and read in components of observation structure.
5 !---------------------------------------------------------------------------
9 type (domain), intent(inout) :: grid ! Model data
10 type (y_type), intent(out) :: ob ! Observation structure.
11 type (iv_type), intent(out) :: iv ! O-B structure.
12 type (j_type), intent(inout) :: j_cost ! Cost function.
15 character (len=14) :: ob_name
18 integer :: istart,iend,jstart,jend
21 if (trace_use) call da_trace_entry("da_setup_obs_structures")
23 ! Default values for fmt_info, fmt_srfc, and fmt_each(YRG, 02/25/2009):
25 fmt_info = '(a12,1x,a19,1x,a40,1x,i6,3(f12.3,11x),6x,a40)'
26 fmt_srfc = '(7(:,f12.3,i4,f7.2))'
27 fmt_each = '(3(f12.3,i4,f7.2),11x,3(f12.3,i4,f7.2),11x,1(f12.3,i4,f7.2))'
29 call da_message((/'Set up observations (ob)'/))
32 if (use_pseudo_rad .or. num_pseudo > 0) then
33 call da_message((/"Single OBS Test:: Turn off all the OBS switches ***"/))
34 use_synopobs = .false.
35 use_shipsobs = .false.
36 use_metarobs = .false.
37 use_soundobs = .false.
38 use_mtgirsobs = .false.
39 use_tamdarobs = .false.
40 use_bogusobs = .false.
41 use_pilotobs = .false.
42 use_airepobs = .false.
43 use_geoamvobs = .false.
44 use_polaramvobs = .false.
46 use_profilerobs = .false.
47 use_satemobs = .false.
48 use_gpspwobs = .false.
49 use_gpsztdobs = .false.
50 use_gpsrefobs = .false.
51 use_gpsephobs = .false.
52 use_ssmiretrievalobs = .false.
53 use_ssmitbobs = .false.
54 use_ssmt1obs = .false.
55 use_ssmt2obs = .false.
56 use_qscatobs = .false.
57 use_hirs2obs = .false.
58 use_hirs3obs = .false.
59 use_hirs4obs = .false.
62 use_amsuaobs = .false.
63 use_amsubobs = .false.
68 use_eos_amsuaobs = .false.
71 use_mwhs2obs = .false.
73 use_goesabiobs = .false.
76 use_airsretobs = .false.
79 use_radarobs = .false.
80 use_radar_rv = .false.
81 use_radar_rf = .false.
82 use_lightningobs = .false.
83 use_lightning_w = .false.
84 use_lightning_div = .false.
85 use_lightning_qv = .false.
87 use_chemic_surfobs = .false.
89 ob_format = ob_format_ascii
92 if (use_synopobs .OR. use_shipsobs .OR. use_metarobs .OR. use_pilotobs .OR. &
93 use_profilerobs .OR. use_buoyobs .OR. use_soundobs .OR. use_mtgirsobs .OR. use_bogusobs .OR. &
94 use_satemobs .OR. use_geoamvobs .OR. use_polaramvobs .OR. use_airepobs .OR. use_tamdarobs .OR. &
95 use_gpspwobs .OR. use_gpsztdobs .OR. use_gpsrefobs .OR. use_ssmiretrievalobs .OR. &
96 use_ssmitbobs .OR. use_ssmt1obs .OR. use_ssmt2obs .OR. use_qscatobs .OR. &
97 use_airsretobs .OR. use_lsac .OR. use_gpsephobs) then
104 if (use_hirs2obs .OR. use_hirs3obs .OR. use_msuobs .OR. use_amsuaobs .OR. &
105 use_amsubobs .OR. use_airsobs .OR. use_eos_amsuaobs .OR. &
106 use_hsbobs .OR. use_kma1dvar .OR. use_filtered_rad .OR. &
107 use_ssmisobs .OR. use_hirs4obs .OR. use_mhsobs .OR. use_pseudo_rad .OR. &
108 use_mwtsobs .OR. use_mwhsobs .OR. use_atmsobs .OR. use_simulated_rad .OR. &
109 use_iasiobs .OR. use_seviriobs .OR. use_amsr2obs .OR. use_goesimgobs .OR. &
110 use_ahiobs .OR. use_mwhs2obs .OR. use_gmiobs .OR. use_goesabiobs) then
116 ! test_dm_exact can be set to .true. to force DM_PARALLEL runs
117 ! to produce results that are bitwise-identical regardless of the number of
118 ! MPI tasks used. This is useful for validating that multi-processor runs
119 ! are not a source of bugs. Runtime will be much longer. This option is
120 ! automatically overridden to .false. for serial or 1-MPI-task runs.
122 if (test_dm_exact) then
123 if (num_procs == 1) then
124 test_dm_exact = .false.
125 write(unit=stdout,fmt='(A)') &
126 ' test_dm_exact overridden to .false. for serial or 1-MPI-task run'
128 ! only implmenented for Sound and Synop, so switch other types off
129 use_shipsobs = .false.
130 use_metarobs = .false.
131 use_bogusobs = .false.
132 use_pilotobs = .false.
133 use_airepobs = .false.
134 use_geoamvobs = .false.
135 use_polaramvobs = .false.
136 use_buoyobs = .false.
137 use_profilerobs = .false.
138 use_satemobs = .false.
139 use_gpspwobs = .false.
140 use_gpsztdobs = .false.
141 use_gpsrefobs = .false.
142 use_gpsephobs = .false.
143 use_ssmiretrievalobs = .false.
144 use_ssmitbobs = .false.
145 use_ssmt1obs = .false.
146 use_ssmt2obs = .false.
147 use_qscatobs = .false.
148 use_hirs2obs = .false.
149 use_hirs3obs = .false.
150 use_hirs4obs = .false.
153 use_amsuaobs = .false.
154 use_amsubobs = .false.
155 use_mwtsobs = .false.
156 use_mwhsobs = .false.
157 use_atmsobs = .false.
158 use_airsobs = .false.
159 use_eos_amsuaobs = .false.
162 use_mwhs2obs = .false.
164 use_goesabiobs = .false.
167 use_airsretobs = .false.
168 use_rainobs = .false.
169 use_iasiobs = .false.
170 use_radarobs = .false.
171 use_radar_rv = .false.
172 use_radar_rf = .false.
173 use_lightningobs = .false.
174 use_lightning_w = .false.
175 use_lightning_div = .false.
176 use_lightning_qv = .false.
178 use_chemic_surfobs = .false.
182 if ( use_pseudo_rad ) then
187 rtminit_platform = pseudo_rad_platid
188 rtminit_satid = pseudo_rad_satid
189 rtminit_sensor = pseudo_rad_senid
192 obs_use(1:num_ob_indexes) = .false.
193 if ( use_airepobs ) obs_use(airep) = .true.
194 if ( use_bogusobs ) obs_use(bogus) = .true.
195 if ( use_buoyobs ) obs_use(buoy) = .true.
196 if ( use_geoamvobs ) obs_use(geoamv) = .true.
197 if ( use_gpsephobs ) obs_use(gpseph) = .true.
198 if ( use_gpsrefobs ) obs_use(gpsref) = .true.
199 if ( use_gpsztdobs .or. use_gpspwobs ) obs_use(gpspw) = .true.
200 if ( use_metarobs ) obs_use(metar) = .true.
201 if ( use_mtgirsobs ) obs_use(mtgirs) = .true.
202 if ( use_pilotobs ) obs_use(pilot) = .true.
203 if ( use_polaramvobs ) obs_use(polaramv) = .true.
204 if ( use_profilerobs ) obs_use(profiler) = .true.
205 if ( use_qscatobs ) obs_use(qscat) = .true.
206 if ( use_radarobs ) obs_use(radar) = .true.
207 if ( use_lightningobs ) obs_use(lightning) = .true.
208 if ( use_rainobs ) obs_use(rain) = .true.
209 if ( use_satemobs ) obs_use(satem) = .true.
210 if ( use_shipsobs ) obs_use(ships) = .true.
211 if ( use_soundobs ) then
212 obs_use(sound) = .true.
213 obs_use(sonde_sfc) = .true.
215 if ( use_ssmiretrievalobs ) obs_use(ssmi_rv) = .true.
216 if ( use_ssmitbobs ) obs_use(ssmi_tb) = .true.
217 if ( use_ssmt1obs ) obs_use(ssmt1) = .true.
218 if ( use_ssmt2obs ) obs_use(ssmt2) = .true.
219 if ( use_synopobs ) obs_use(synop) = .true.
220 if ( use_tamdarobs ) then
221 obs_use(tamdar) = .true.
222 obs_use(tamdar_sfc) = .true.
225 if (sfc_assi_options < 1 .OR. sfc_assi_options > 2) then
226 write(unit=message(1),fmt='(A,I3)') &
227 'Invalid sfc_assi_option = ', sfc_assi_options
228 call da_error(__FILE__,__LINE__,message(1:1))
231 if ( use_gpsrefobs ) then
232 if ( ob_format == ob_format_bufr ) then
233 ! when main conv input is from bufr, gpsro has to be from bufr too
234 ! overwrite the namelist setting
235 ob_format_gpsro = ob_format_bufr
237 if ( ob_format == ob_format_ascii .and. &
238 ob_format_gpsro == ob_format_bufr ) then
239 call da_message((/'ob_format=2 while ob_format_gpsro=1, will be reading GPSRO data from gpsro.bufr'/))
244 ! convert pseudo_var to be in lowercase
245 do i = 1, len_trim(pseudo_var)
246 icode = ichar(pseudo_var(i:i))
247 if (icode>=65 .and. icode<=90) then
248 pseudo_var(i:i)=char(icode + 97 - 65)
252 if ( num_pseudo > 0 .and. &
253 (trim(adjustl(pseudo_var))=='qcw' .or. &
254 trim(adjustl(pseudo_var))=='qrn' .or. &
255 trim(adjustl(pseudo_var))=='qci' .or. &
256 trim(adjustl(pseudo_var))=='qsn' .or. &
257 trim(adjustl(pseudo_var))=='qgr') ) then
258 if ( cloud_cv_options < 2 ) then
259 write(unit=message(1),fmt='(A,A)') &
260 'cloud_cv_options should be 2 or 3 for pseudo_var = ', trim(pseudo_var)
261 call da_error(__FILE__,__LINE__,message(1:1))
268 if ( num_pseudo > 0 .and. trim(adjustl(pseudo_var))=='tpw' ) then
270 use_gpspwobs = .true.
272 if ( num_pseudo > 0 .and. trim(adjustl(pseudo_var))=='ztd' ) then
274 use_gpsztdobs = .true.
276 if ( num_pseudo > 0 .and. trim(adjustl(pseudo_var))=='ref' ) then
278 use_gpsrefobs = .true.
280 ! if pseudo ob for conventional u, v, t, p, q
281 if ( num_pseudo > 0 ) then
282 pseudo_uvtpq = .true.
283 if ( pseudo_tpw .or. pseudo_ztd .or. pseudo_ref ) then
284 pseudo_uvtpq = .false.
287 if ( num_pseudo > 0 ) then
288 !to avoid errors when writing out filtered_obs for undefined variables
289 anal_type_qcobs = .false.
292 if ( thin_conv .or. thin_conv_ascii ) then
293 thin_conv_opt(gpseph) = no_thin
294 thin_conv_opt(radar) = no_thin
295 thin_conv_opt(radiance) = no_thin
296 thin_conv_opt(rain) = no_thin
297 thin_conv_opt(lightning) = no_thin
298 if ( thin_conv .and. ob_format==ob_format_bufr ) then
299 ! gpsref horizontal thinning is not implemented for bufr input
300 thin_conv_opt(gpsref) = no_thin
302 do i = 1, num_ob_indexes
303 ! resetting thin_conv_opt to no_thin for ob types that are not used
304 if ( thin_conv_opt(i) > no_thin .and. &
305 (.not. obs_use(i)) ) then
306 thin_conv_opt(i) = no_thin
309 if ( thin_conv .and. ob_format==ob_format_bufr .and. &
310 all(thin_conv_opt(:) <= no_thin) ) thin_conv = .false.
311 if ( thin_conv_ascii .and. ob_format==ob_format_ascii .and. &
312 all(thin_conv_opt(:) <= no_thin) ) thin_conv_ascii = .false.
314 if ( ((.not. thin_conv) .and. ob_format==ob_format_bufr) .or. &
315 ((.not. thin_conv_ascii) .and. ob_format==ob_format_ascii) ) then
316 thin_conv_opt(:) = no_thin
318 write(message(1),'(a,30i2)') 'thin_conv_opt = ', thin_conv_opt(:)
319 call da_message(message(1:1))
321 ! get lat/lon info (rlat_min,rlat_max,rlon_min,rlon_max,dlat_grid,dlon_grid)
322 ! to be used for making thinning grids for conv (ascii/bufr), radiance and rain ob types.
323 call init_constants_derived
328 istart=MINVAL( grid%i_start(1:grid%num_tiles) )
329 iend =MAXVAL( grid%i_end (1:grid%num_tiles) )
330 jstart=MINVAL( grid%j_start(1:grid%num_tiles) )
331 jend =MAXVAL( grid%j_end (1:grid%num_tiles) )
334 rlat_min=min(rlat_min, grid%xb%lat(i,j))
335 rlat_max=max(rlat_max, grid%xb%lat(i,j))
336 if( grid%xb%lon(i,j) < 0.0) then
337 rlon_min=min(rlon_min, (r360+grid%xb%lon(i,j)))
338 rlon_max=max(rlon_max, (r360+grid%xb%lon(i,j)))
340 rlon_min=min(rlon_min, grid%xb%lon(i,j))
341 rlon_max=max(rlon_max, grid%xb%lon(i,j))
346 call mpi_reduce(rlat_min, rlonlat(1), 1, true_mpi_real, mpi_min, root, comm, ierr)
347 call mpi_reduce(rlon_min, rlonlat(2), 1, true_mpi_real, mpi_min, root, comm, ierr)
348 call mpi_reduce(rlat_max, rlonlat(3), 1, true_mpi_real, mpi_max, root, comm, ierr)
349 call mpi_reduce(rlon_max, rlonlat(4), 1, true_mpi_real, mpi_max, root, comm, ierr)
350 CALL mpi_bcast( rlonlat, 4 , true_mpi_real , root , comm, ierr )
351 rlat_min = rlonlat(1)
352 rlon_min = rlonlat(2)
353 rlat_max = rlonlat(3)
354 rlon_max = rlonlat(4)
356 dlat_grid = rlat_max - rlat_min
357 dlon_grid = rlon_max - rlon_min
359 !---------------------------------------------------------------------------
360 ! [1.0] Setup and read in fields from first guess:
361 !----------------------------------------------------------------------------
364 ! iv%ptop = grid%xb%ptop
366 iv%total_rad_pixel = 0
367 iv%total_rad_channel = 0
369 iv%info(:)%nlocal = 0
370 iv%info(:)%ntotal = 0
371 iv%info(:)%thin_nlocal = 0
372 iv%info(:)%thin_ntotal = 0
373 do i=1,num_ob_indexes
374 iv%info(i)%plocal(:) = 0
375 iv%info(i)%ptotal(:) = 0
376 iv%info(i)%thin_plocal(:) = 0
377 iv%info(i)%thin_ptotal(:) = 0
385 iv%info(:)%max_lev = 1
387 ! get FGAT time slots
389 allocate ( time_slots(0:num_fgat_time) )
390 call da_get_time_slots(num_fgat_time,time_window_min,analysis_date, &
391 time_window_max, time_slots, ifgat_ana)
394 ! Conventional obs can be in BUFR or ascii format
395 if (ob_format == ob_format_bufr) then
396 call da_message((/'Using PREPBUFR format observation input'/))
397 call da_setup_obs_structures_bufr (grid, ob, iv)
398 else if (ob_format == ob_format_ascii) then
399 call da_message((/'Using ASCII format observation input'/))
400 call da_setup_obs_structures_ascii (ob, iv, grid)
402 write(unit=message(1),fmt='(A,I3)') 'Invalid ob_format = ', ob_format
403 call da_error(__FILE__,__LINE__,message(1:1))
407 if (use_radarobs) then
408 ! Radar obs are read from separate file(s)
409 call da_message((/'Using ASCII format radar observation input'/))
410 call da_setup_obs_structures_radar (grid, ob, iv)
413 if (use_lightningobs) then
414 ! Lightning obs are read from separate file(s)
415 call da_message((/'Using ASCII format lightning observation input'/))
416 call da_setup_obs_structures_lightning (grid, ob, iv)
419 if (use_rainobs .and. var4d) then
420 call da_message((/'Using ASCII format precipitation observation input'/))
421 call da_setup_obs_structures_rain (grid, ob, iv)
425 if ( (use_chemic_surfobs) ) then
426 call da_message((/'Using ASCII format chem IC observation input'/))
427 call da_setup_obs_structures_chem_sfc (ob, iv, grid)
432 #if defined(CRTM) || defined(RTTOV)
433 ! Radiance files can only be in BUFR
434 call da_message((/'Using NCEP BUFR radiance 1b input'/))
435 if ( use_amsr2obs ) then
436 call da_message((/'Using AMSR2 radiance input in HDF5 format'/))
438 if ( use_goesimgobs ) then
439 call da_message((/'Using GOES IMAGER radiance input in netcdf format'/))
441 if ( use_goesabiobs ) then
442 call da_message((/'Using GOES ABI radiance input in netcdf format'/))
444 if ( use_ahiobs ) then
445 call da_message((/'Using himawari AHI radiance input in netcdf format'/))
447 if ( use_gmiobs ) then
448 call da_message((/'Using GMI radiance input in HDF5 format'/))
450 call da_setup_radiance_structures(grid, ob, iv)
452 call da_error(__FILE__,__LINE__,(/"options to use radiance data are turned on in wrfvar4 namelist, the code needs to be compiled with CRTM or RTTOV library"/))
456 if ( num_pseudo > 0 ) then
457 call da_setup_pseudo_obs(grid, iv, ob)
460 ! Summarize observations
462 write(unit=stdout, fmt='(a)') 'Observation summary'
464 write(unit=stdout, fmt='(3x,2(a,i3))') 'ob time', i,' num_ob_indexes=',num_ob_indexes
465 do j=1,num_ob_indexes
466 if(j.eq.27) cycle ! skip tamdar_sfc (HA)
467 if (use_gpsztdobs .and.obs_names(j) == 'gpspw ' ) then
470 ob_name = obs_names(j)
472 if(iv%info(j)%ptotal(i) - iv%info(j)%ptotal(i-1) > 0) then
473 if ( thin_conv_ascii .and. ob_format == ob_format_ascii ) then
474 if ( j == radiance ) cycle !temporary fix to not print incorrect counts for radiance
475 write(unit=stdout, fmt='(2x,2(a,i10),a,i8,a)') &
476 ob_name, iv%info(j)%ptotal(i) - iv%info(j)%ptotal(i-1), ' global, ', &
477 iv%info(j)%thin_ptotal(i) - iv%info(j)%thin_ptotal(i-1), ' global (post-thinning), ', &
478 iv%info(j)%thin_plocal(i) - iv%info(j)%thin_plocal(i-1), ' local (post-thinning)'
481 write(unit=stdout, fmt='(i3,3x,a,i10,a,i8,a,i8,a,i8,a)') &
482 j,ob_name, iv%info(j)%ptotal(i) - iv%info(j)%ptotal(i-1), ' global,', &
483 iv%info(j)%plocal(i) - iv%info(j)%plocal(i-1), ' local', &
484 iv%info(chemic_surf)%ntotal, ' chem total', iv%info(chemic_surf)%nlocal, ' chem local'
486 write(unit=stdout, fmt='(6x,a,i10,a,i8,a)') &
487 ob_name, iv%info(j)%ptotal(i) - iv%info(j)%ptotal(i-1), ' global,', &
488 iv%info(j)%plocal(i) - iv%info(j)%plocal(i-1), ' local'
490 end if ! thin_conv_ascii
494 write(unit=stdout, fmt='(a)') ' '
496 ! Get horizontal interpolation weights.
498 call da_setup_obs_interp_wts (iv)
500 if (trace_use) call da_trace_exit("da_setup_obs_structures")
502 end subroutine da_setup_obs_structures