1 subroutine da_setup_obs_structures_madis( ob, iv)
3 !------------------------------------------------------------------------------
4 ! PURPOSE: Define, allocate and read of observation structure.
6 ! METHOD: Define, allocate and read of observation structure.
8 ! HISTORY: 05-21-03 M. Barth The setup_obs routine to ingest data from
9 ! the FSL MADIS netCDF files.
10 ! 10-20-03 M. Barth - Changed calls to get SATOB data for the
11 ! changes made in the MADIS API when the
12 ! true SATWND dataset was added. (This code
13 ! originally accessed a dummy SATW dataset.)
14 ! - Changed max_map from 150 to 2000 to
15 ! accommodate full time window options.
16 ! 04-01-04 M. Barth Added MADIS COOP surface dataset.
17 ! 08-27-04 M. Barth - Added sonde_sfc stuff.
18 ! - Initialize new count_obs entries that we
19 ! don't use (radar, profiler, buoy). Note
20 ! that, as with the BUFR interface, we
21 ! continue to lump profiler in with "sound"
22 ! and buoy with "ships" -- as the downstream
23 ! processing is identical regardless of
24 ! the designation, and we offer MADIS-level
25 ! control of these datasets, this is simpler
26 ! than restructuring this code.
27 ! 02-06-06 M. Barth Changes for WRFVAR version 2.1.
28 ! - Renamed all "fsl" references to "madis".
29 ! (Exception: "FSL" is still used as an
32 ! - Removed xbx arg, so analysis time is
33 ! now determined by the NAMELIST ANALYSIS_DATE
35 ! - Changed satob to geoamv.
36 ! - Changed max_sfc from 50K to 200K.
37 ! - Changed max_raoblev from 256 to 405.
38 ! - Miscellaneous other minor changes to
39 ! conform to current paradigm.
40 ! - Added protection against invalid lat/lons,
41 ! as well as protection against latitude
42 ! at the poles -- some projections can't
43 ! handle this, and the WRFVAR routines
44 ! that do the coordinate conversions aren't
45 ! smart enough to trap this case. [Are you
47 ! 08-07-07 M. Barth - Fixed problem introduced in 2005 version
48 ! of WRFVAR by filling in the ob_num
49 ! and current_ob_time data structures in iv.
50 ! 02-06-06 M. Barth Changes for WRFVAR version 3:
51 ! - Removed xp argument.
52 ! - Changed DA_ll_to_xy call to da_llxy.
53 ! - Added trace usage.
54 ! - Changed ob_type structure to iv_type.
55 ! - Changes in iv structure:
56 ! - current_ob_time -> time
57 ! - New info structure
58 ! - Fill in global vs. local obs counts
59 ! into iv%info. This is *presumably* the
60 ! replacement for iv%ob_num.
61 ! - Fill in iv%info with stuff that used
62 ! to go into iv%<dataset>%info.
63 ! - Since DA_Constants and DA_Read_Namelist no
64 ! longer exist, the declaration of, and
65 ! input of, the MADIS namelist variables
66 ! have been moved to this routine.
67 ! - Changed print_detail to print_detail_obs.
68 ! - Added duplication logic (see explanation
69 ! in PROCESS_DATASET).
70 ! 11-28-08 M. Barth Since I finally got the darn thing to
71 ! compile, I debugged the massive changes
74 ! PARENT_MODULE: da_setup_structures
75 !------------------------------------------------------------------------------
77 use da_tools, only : da_llxy
82 TYPE ( y_type), INTENT(OUT) :: ob ! Observation structure.
83 TYPE (iv_type), INTENT(INOUT) :: iv ! O-B structure.
89 ! Primarily used by DA routines:
91 TYPE (multi_level_type) :: platform
95 LOGICAL :: outside, outside_all
97 ! Primarily used by MADIS ingest:
101 ! Max number of input reports:
102 INTEGER*4, PARAMETER :: max_sfc = 200000, & ! Surface
103 max_raob = 1000, & ! Radiosonde
104 max_npn = 160, & ! NOAA Profiler Network (NPN) winds
105 max_acars = 60000, & ! ACARS
106 max_map = 2000, & ! Multi-Agency profilers (MAP)
107 max_satw = 60000, & ! Satellite winds
109 max_sta = max(max_sfc,max_raob,max_npn, &
110 max_acars,max_map,max_satw), &
112 ! Max number of input levels:
113 max_raoblev = 405, & ! Radiosonde
114 max_npnlev_madis = 64, & ! NPN MADIS database
115 max_npnlev_awips = 43, &!NPN AWIPS database
116 max_maplev = 202, & ! MAP
118 success_p = 0, & ! Successful status return
119 qcall = 99, & ! Only return data passing all QC
120 max_provider = 100 ! Maximum number of data providers
121 REAL*4, PARAMETER :: miss_p = 999999.0 ! Missing data flag
125 CHARACTER*10, ALLOCATABLE :: stanam(:),provdr(:)
126 CHARACTER*9, ALLOCATABLE :: timeob(:)
127 CHARACTER*1, ALLOCATABLE :: qcd(:)
128 INTEGER*4, ALLOCATABLE :: wmoid(:),qca(:),qcr(:),nlevels(:),keep(:)
129 REAL*4, ALLOCATABLE :: lat(:),lon(:),elev(:),p(:),q(:),t(:),z(:), &
130 dd(:),ff(:),pw(:),slp(:),levtype(:)
134 INTEGER*4 :: nsta,nobs,istatus,i,j,ntmp,nlev,ntmp_r, &
135 ntmp_n,ntmp_m,keep_r(max_raob), recwin, &
136 keep_n(max_npn),keep_m(max_map),minbck,minfwd, &
137 nsatw_vartype,satw_var_len(5),pvdriostat,n,iost, &
138 nlocal(num_ob_indexes),ntotal(num_ob_indexes), &
139 nl_raob,nt_raob,nl_npn,nt_npn,nl_map,nt_map, &
140 nlocal_out,ntotal_out
143 CHARACTER*10 :: dpname
144 CHARACTER*255 :: pvdrfile
145 INTEGER*4, PARAMETER :: lun = 19 ! LUN for namelist and data provider files
146 CHARACTER*5 :: satw_var(2,5)
147 CHARACTER*4 :: pvdriotype
148 LOGICAL :: map_init,npn_init
149 CHARACTER*20 :: namelist_file
150 CHARACTER*29 :: errmsg(0:8)
151 INTEGER*4 :: mfbdebug
152 INTEGER*4 :: sfclev(max_map)
154 !------------------------------------------------------------------------------
155 ! Namelist options for ingest of MADIS/AWIPS datasets into 3DVAR
156 !------------------------------------------------------------------------------
157 ! The user can select either the MADIS or AWIPS database for each dataset that's
158 ! ingest by the WRFVAR. Each dataset's time window can be independently set as
159 ! well, which allows the user to select the number of minutes before and after
160 ! the nominal time to be used for the window, and how duplicates should be
161 ! handled. For the METAR, PROFILER and GEOAMV datasets, the user can also
162 ! choose to ingest data from all providers of the METAR and PROFILER datasets
163 ! (e.g., ASOS) as well as mesonets for METAR, and from operational GOES
164 ! products from both satellites for GEOAMV), or the user can specify which
165 ! providers should be used. For more details on how and why to select
166 ! different settings, see the README.MADIS_WRFVAR file in the
169 ! The meaning of each variable is the same for all of the datasets, so full
170 ! comments are only included for the METAR dataset below, and where the variables
171 ! are specific to only one or two datasets.
172 !------------------------------------------------------------------------------
176 INTEGER*4 :: madis_debug ! 0 - no debug
178 ! 2 - print all obs, stop after obs ingest
182 CHARACTER*6 :: madis_metar_db ! Database: 'FSL' or 'AWIPS'
183 INTEGER*4 :: madis_metar_minbck ! Number of minutes relative to nominal
184 ! time at which to start time window
185 INTEGER*4 :: madis_metar_minfwd ! Number of minutes relative to nominal
186 ! time at which to end time window
187 ! (max(minfwd-minbck) is 180)
188 INTEGER*4 :: madis_metar_recwin ! 1 - return one record per fixed station,
189 ! closest to nominal time
190 ! 2 - return one record per fixed station,
191 ! closest to start of window
192 ! 3 - return one record per fixed station,
193 ! closest to end of window
194 ! 4 - return all records within *window*
195 LOGICAL :: madis_metar_all_providers ! .TRUE./.FALSE. - use all providers
196 CHARACTER*255 :: madis_metar_provider_list ! Full path to file with list of providers,
197 ! one per line; must be specified if
198 ! all_providers is false
202 CHARACTER*6 :: madis_ships_db ! Database: 'FSL' or 'AWIPS'
203 INTEGER*4 :: madis_ships_minbck ! Time window start
204 INTEGER*4 :: madis_ships_minfwd ! Time window end
205 INTEGER*4 :: madis_ships_recwin ! How to handle duplicate records
209 CHARACTER*6 :: madis_gpspw_db ! Database: 'FSL' or 'AWIPS'
210 INTEGER*4 :: madis_gpspw_minbck ! Time window start
211 INTEGER*4 :: madis_gpspw_minfwd ! Time window end
212 INTEGER*4 :: madis_gpspw_recwin ! How to handle duplicate records
216 CHARACTER*6 :: madis_sound_db ! Database: 'FSL' or 'AWIPS'
217 INTEGER*4 :: madis_sound_minbck ! Time window start
218 INTEGER*4 :: madis_sound_minfwd ! Time window end
219 INTEGER*4 :: madis_sound_recwin ! How to handle duplicate records
223 CHARACTER*6 :: madis_profiler_db ! Database: 'FSL' or 'AWIPS'
224 INTEGER*4 :: madis_profiler_minbck ! Time window start
225 INTEGER*4 :: madis_profiler_minfwd ! Time window end
226 INTEGER*4 :: madis_profiler_recwin ! How to handle duplicate records
227 LOGICAL :: madis_profiler_all_providers ! .TRUE./.FALSE. - use all providers
228 CHARACTER*255 :: madis_profiler_provider_list ! Full path to file with list of providers
232 CHARACTER*6 :: madis_airep_db ! Database: 'FSL' or 'AWIPS'
233 INTEGER*4 :: madis_airep_minbck ! Time window start
234 INTEGER*4 :: madis_airep_minfwd ! Time window end
235 INTEGER*4 :: madis_airep_recwin ! How to handle duplicate records
239 CHARACTER*6 :: madis_geoamv_db ! Database: 'FSL' or 'AWIPS'
240 INTEGER*4 :: madis_geoamv_minbck ! Time window start
241 INTEGER*4 :: madis_geoamv_minfwd ! Time window end
242 INTEGER*4 :: madis_geoamv_recwin ! How to handle duplicate records
243 LOGICAL :: madis_geoamv_all_providers ! .TRUE./.FALSE. - use default providers
244 CHARACTER*255 :: madis_geoamv_provider_list ! Full path to file with list of providers
245 LOGICAL :: madis_geoamv_wv ! .TRUE./.FALSE. - use water vapor winds
246 LOGICAL :: madis_geoamv_ir ! .TRUE./.FALSE. - use infrared winds
247 LOGICAL :: madis_geoamv_vis ! .TRUE./.FALSE. - use visible winds
248 LOGICAL :: madis_geoamv_s10 ! .TRUE./.FALSE. - use sounder channel 10 winds
249 LOGICAL :: madis_geoamv_s11 ! .TRUE./.FALSE. - use sounder channel 11 winds
251 ! Note that the meaning of "madis_geoamv_all_providers" is different for GEOAMV than
252 ! for the other datasets. If the variable is .TRUE., the *default* providers will be
253 ! selected, i.e., operational products from both GOES satellites.
254 !------------------------------------------------------------------------------
255 ! End of MADIS/AWIPS WRFVAR options
256 !------------------------------------------------------------------------------
257 ! Namelist contents :
259 NAMELIST/MADIS_GENERAL/madis_debug
260 NAMELIST/MADIS_METAR/madis_metar_db,madis_metar_minbck,madis_metar_minfwd,madis_metar_recwin, &
261 madis_metar_all_providers,madis_metar_provider_list
262 NAMELIST/MADIS_SHIPS/madis_ships_db,madis_ships_minbck,madis_ships_minfwd,madis_ships_recwin
263 NAMELIST/MADIS_GPSPW/madis_gpspw_db,madis_gpspw_minbck,madis_gpspw_minfwd,madis_gpspw_recwin
264 NAMELIST/MADIS_SOUND/madis_sound_db,madis_sound_minbck,madis_sound_minfwd,madis_sound_recwin
265 NAMELIST/MADIS_PROFILER/madis_profiler_db,madis_profiler_minbck,madis_profiler_minfwd,&
266 madis_profiler_recwin,madis_profiler_all_providers,&
267 madis_profiler_provider_list
268 NAMELIST/MADIS_AIREP/madis_airep_db,madis_airep_minbck,madis_airep_minfwd,madis_airep_recwin
269 NAMELIST/MADIS_GEOAMV/madis_geoamv_db,madis_geoamv_minbck,madis_geoamv_minfwd,&
270 madis_geoamv_recwin,madis_geoamv_all_providers,&
271 madis_geoamv_provider_list,madis_geoamv_wv,madis_geoamv_ir,&
272 madis_geoamv_vis,madis_geoamv_s10,madis_geoamv_s11
274 DATA ERRMSG/'Opening namelist.3dvar_madis',&
275 'Reading madis_general namelist',&
276 'Reading madis_metar namelist',&
277 'Reading madis_ships namelist',&
278 'Reading madis_gpspw namelist',&
279 'Reading madis_sound namelist',&
280 'Reading madis_profiler namelist',&
281 'Reading madis_airep namelist',&
282 'Reading madis_geoamv namelist'/
284 ! Note that all of the variables sent into MADIS routines are explicitly
285 ! declared INTEGER*4 and REAL*4, rather than letting the generic kind be
286 ! established based on the choices used in the WRF options. On at least
287 ! one machine, the WRF-default for REAL is REAL*8, but the MADIS library
288 ! uses REAL*4. To stay on the safe side, we'll declare all the int/real
289 ! MADIS variables to what we want.
291 if (trace_use) CALL da_trace_entry("da_setup_obs_structures_madis")
293 !------------------------------------------------------------------------------
294 ! MADIS-related initialization
295 !------------------------------------------------------------------------------
296 ! Note that any variables prefixed with "madis_" are namelist variables read in
297 ! from namelist.3dvar_madis. These are used to give the user the ability to
298 ! set all relevant MADIS options for the various datasets.
300 write(6,*)' -----------------------------------------------------'
301 write(6,*)' Read WRFVAR namelist options for MADIS datasets'
302 write(6,*)' -----------------------------------------------------'
305 !----------------------------------------------------------------------------
306 ! Set default values. These represent reasonable choices for an hourly data
307 ! assimilation cycle, using all datasets, for MADIS database, without
309 !----------------------------------------------------------------------------
312 madis_metar_db = 'FSL'
313 madis_metar_minbck = -30
314 madis_metar_minfwd = 29
315 madis_metar_recwin = 4
316 madis_metar_all_providers = .TRUE.
318 madis_ships_db = 'FSL'
319 madis_ships_minbck = -30
320 madis_ships_minfwd = 29
321 madis_ships_recwin = 4
323 madis_gpspw_db = 'FSL'
324 madis_gpspw_minbck = -30
325 madis_gpspw_minfwd = 29
326 madis_gpspw_recwin = 4
328 madis_sound_db = 'FSL'
329 madis_sound_minbck = -60
330 madis_sound_minfwd = 60
331 madis_sound_recwin = 3
333 madis_profiler_db = 'FSL'
334 madis_profiler_minbck = -30
335 madis_profiler_minfwd = 29
336 madis_profiler_recwin = 4
337 madis_profiler_all_providers = .TRUE.
339 madis_airep_db = 'FSL'
340 madis_airep_minbck = -30
341 madis_airep_minfwd = 29
342 madis_airep_recwin = 4
344 madis_geoamv_db = 'FSL'
345 madis_geoamv_minbck = -150
346 madis_geoamv_minfwd = 30
347 madis_geoamv_recwin = 4
348 madis_geoamv_all_providers = .TRUE.
349 madis_geoamv_wv = .TRUE.
350 madis_geoamv_ir = .TRUE.
351 madis_geoamv_vis = .FALSE.
352 madis_geoamv_s10 = .FALSE.
353 madis_geoamv_s11 = .FALSE.
355 !----------------------------------------------------------------------------
356 ! Open namelist file.
357 !----------------------------------------------------------------------------
358 namelist_file = 'namelist.3dvar_madis'
359 write(6,*)' WRFVAR MADIS datasets namelist options used are in: ', &
364 write(6,*) ' Opening WRFVAR MADIS namelist input file...'
366 open(file=namelist_file,unit=lun,status='old', &
367 access='sequential',form='formatted',action='read', &
368 err=8500,iostat=iost)
370 !----------------------------------------------------------------------------
371 ! Read namelist and close.
372 !----------------------------------------------------------------------------
375 read(unit=lun,nml=madis_general,err=8500,iostat=iost)
377 read(unit=lun,nml=madis_metar,err=8500,iostat=iost)
379 read(unit=lun,nml=madis_ships,err=8500,iostat=iost)
381 read(unit=lun,nml=madis_gpspw,err=8500,iostat=iost)
383 read(unit=lun,nml=madis_sound,err=8500,iostat=iost)
385 read(unit=lun,nml=madis_profiler,err=8500,iostat=iost)
387 read(unit=lun,nml=madis_airep,err=8500,iostat=iost)
389 read(unit=lun,nml=madis_geoamv,err=8500,iostat=iost)
392 write(6,*) ' WRFVAR MADIS namelist input file successfully read.'
394 !------------------------------------------------------------------------------
395 ! The input will be validated when the user's choices are employed in the
396 ! da_setup_obs_structures_madis routine, and the MADIS library routines that
397 ! it calls. Therefore, don't duplicate the validation here.
398 !------------------------------------------------------------------------------
400 !----------------------------------------------------------------------------
402 !----------------------------------------------------------------------------
404 if (print_detail_obs) then
406 write(6,*) ' Printing contents of WRFVAR MADIS namelist input file...'
409 write(6,*)'madis_debug = ',madis_debug
411 write(6,*)'madis_metar_db = ',madis_metar_db
412 write(6,*)'madis_metar_minbck = ',madis_metar_minbck
413 write(6,*)'madis_metar_minfwd = ',madis_metar_minfwd
414 write(6,*)'madis_metar_recwin = ',madis_metar_recwin
415 write(6,*)'madis_metar_all_providers = ',madis_metar_all_providers
416 write(6,*)'madis_metar_provider_list = ',trim(madis_metar_provider_list)
418 write(6,*)'madis_sound_db = ',madis_sound_db
419 write(6,*)'madis_sound_minbck = ',madis_sound_minbck
420 write(6,*)'madis_sound_minfwd = ',madis_sound_minfwd
421 write(6,*)'madis_sound_recwin = ',madis_sound_recwin
423 write(6,*)'madis_profiler_db = ',madis_profiler_db
424 write(6,*)'madis_profiler_minbck = ',madis_profiler_minbck
425 write(6,*)'madis_profiler_minfwd = ',madis_profiler_minfwd
426 write(6,*)'madis_profiler_recwin = ',madis_profiler_recwin
427 write(6,*)'madis_profiler_all_providers = ',madis_profiler_all_providers
428 write(6,*)'madis_profiler_provider_list = ',trim(madis_profiler_provider_list)
430 write(6,*)'madis_airep_db = ',madis_airep_db
431 write(6,*)'madis_airep_minbck = ',madis_airep_minbck
432 write(6,*)'madis_airep_minfwd = ',madis_airep_minfwd
433 write(6,*)'madis_airep_recwin = ',madis_airep_recwin
435 write(6,*)'madis_geoamv_db = ',madis_geoamv_db
436 write(6,*)'madis_geoamv_minbck = ',madis_geoamv_minbck
437 write(6,*)'madis_geoamv_minfwd = ',madis_geoamv_minfwd
438 write(6,*)'madis_geoamv_recwin = ',madis_geoamv_recwin
439 write(6,*)'madis_geoamv_all_providers = ',madis_geoamv_all_providers
440 write(6,*)'madis_geoamv_provider_list = ',trim(madis_geoamv_provider_list)
441 write(6,*)'madis_geoamv_wv = ',madis_geoamv_wv
442 write(6,*)'madis_geoamv_ir = ',madis_geoamv_ir
443 write(6,*)'madis_geoamv_vis = ',madis_geoamv_vis
444 write(6,*)'madis_geoamv_s10 = ',madis_geoamv_s10
445 write(6,*)'madis_geoamv_s11 = ',madis_geoamv_s11
451 ! Allocate the local memory needed to read in the MADIS arrays that are
452 ! dimensioned by station.
454 write(6,*) ' Allocating memory for MADIS arrays...'
456 allocate (stanam(max_sta))
457 allocate (provdr(max_sta))
458 allocate (timeob(max_sta))
459 allocate (wmoid(max_sta))
460 allocate (lat(max_sta))
461 allocate (lon(max_sta))
462 allocate (elev(max_sta))
463 allocate (pw(max_sta))
464 allocate (slp(max_sta))
465 allocate (keep(max_sta))
466 allocate (nlevels(max_sta))
468 ! Initialize the dataset ob counts.
470 do i = 1, num_ob_indexes
475 write(6,*) ' Memory allocated, obcounts set to zero'
477 ! Initialize the MADIS subsystems to be used, using the database
478 ! selected for each subsystem by the user, and with error messages
479 ! echoed to standard output. For subsystems that have optional
480 ! data provider selection files, read those in as required, and
481 ! set the subset of data providers to be used.
483 pvdriostat = 0 ! Indicates I/O errors on provider files.
485 if(use_metarobs .or. use_shipsobs .or. use_gpspwobs)then
487 ! Because these three WRF datasets map into only one MADIS subsystem, and
488 ! the user has database & time window control over each of them independently,
489 ! we can only initialize one of them here. We'll initialize the first one
490 ! that will be used below when we read in the data. (This is because something
491 ! has to be initialized so we can get proper error message handling inside
492 ! the MADIS routines.)
496 CALL MINIT('SFC',madis_metar_db,.true.,istatus)
497 if(istatus /= success_p)stop
498 CALL MSETSFCPVDR('ALL-SFC',.false.,istatus)
499 if(istatus /= success_p)stop
501 if(.not. madis_metar_all_providers)then
503 if(print_detail_obs)then
505 write(6,*)'Selecting individual METAR providers from ',&
506 trim(madis_metar_provider_list)
508 if(istatus /= success_p)stop
511 pvdrfile = madis_metar_provider_list
512 open(unit=lun,file=trim(pvdrfile),status='OLD', &
513 iostat=pvdriostat,err=8000)
517 do i = 1, max_provider
518 read(lun,1,err=8000,iostat=pvdriostat,end=2)dpname
520 if(.not. (dpname(1:1) == '#' .or. len(trim(dpname)) == 0 .or. &
521 dpname(1:8) == 'MARITIME'))then
522 if(print_detail_obs)write(6,*)' Selecting: ',trim(dpname)
523 CALL MSETSFCPVDR(trim(dpname),.true.,istatus)
524 if(istatus /= success_p)stop
533 ! Select all of the surface datasets other than maritime.
535 CALL MSETSFCPVDR('ALL-MTR',.true.,istatus)
536 if(istatus /= success_p)stop
537 CALL MSETSFCPVDR('SAO',.true.,istatus)
538 if(istatus /= success_p)stop
539 CALL MSETSFCPVDR('ALL-MESO',.true.,istatus)
540 if(istatus /= success_p)stop
541 CALL MSETSFCPVDR('COOP',.true.,istatus)
542 if(istatus /= success_p)stop
546 else if(use_shipsobs)then
548 CALL MINIT('SFC',madis_ships_db,.true.,istatus)
549 if(istatus /= success_p)stop
551 else if(use_gpspwobs)then
553 CALL MINIT('SFC',madis_gpspw_db,.true.,istatus)
554 if(istatus /= success_p)stop
562 CALL MINIT('RAOB',madis_sound_db,.true.,istatus)
563 if(istatus /= success_p)stop
567 ! ***** Remember to add use_xxxobs logic for profilers once that's added.
569 if(use_soundobs)then ! ***** change to use_profilerobs...
574 if(.not. madis_profiler_all_providers)then
576 if(print_detail_obs)then
578 write(6,*)'Selecting individual PROFILER providers from ',&
579 trim(madis_profiler_provider_list)
583 pvdrfile = madis_profiler_provider_list
584 open(unit=lun,file=trim(pvdrfile),status='OLD', &
585 iostat=pvdriostat,err=8000)
589 do i = 1, max_provider
591 ! Because the WRF profiler dataset maps into two MADIS subsystems (NPN and MAP)
592 ! we need to make sure that we initialize each subsystem as it's encountered
593 ! in the user's list.
595 read(lun,1,err=8000,iostat=pvdriostat,end=3)dpname
596 if(.not. (dpname(1:1) == '#' .or. len(trim(dpname)) == 0))then
598 if(print_detail_obs)write(6,*)' Selecting: ',trim(dpname)
600 if(trim(dpname) == 'NOAA')then
602 CALL MINIT('NPN',madis_profiler_db,.true.,istatus)
603 if(istatus /= success_p)stop
606 else if(trim(dpname) == 'ALL-PROF')then
608 CALL MINIT('NPN',madis_profiler_db,.true.,istatus)
609 if(istatus /= success_p)stop
611 CALL MINIT('MAP','FSL',.true.,istatus) ! No AWIPS database for MAP.
612 if(istatus /= success_p)then
614 ! We'll be forgiving if the AWIPS profiler database has been selected, and just
615 ! set things so no MAP data will be read. If MADIS (FSL) has been selected,
616 ! however, this is obviously an error on the user's part, and he/she should fix it.
618 if(madis_profiler_db(1:3).eq.'FSL')stop
624 else if(trim(dpname) == 'ALL-MAP')then
626 CALL MINIT('MAP','FSL',.true.,istatus)
627 if(istatus /= success_p)then
628 if(madis_profiler_db(1:3).eq.'FSL')stop
634 ! ***** Get rid of the NO-PROF else once profiler data structures have
637 else if(trim(dpname) == 'NO-PROF')then
643 ! An individual MAP provider is being selected. Make sure we're initialized
644 ! for MAP, then add in the provider.
646 if(.not. map_init)then
647 CALL MINIT('MAP','FSL',.true.,istatus)
648 if(istatus /= success_p)then
649 if(madis_profiler_db(1:3).eq.'FSL')stop
653 CALL MSETMAPPVDR('ALL-MAP',.false.,istatus)
654 if(istatus /= success_p)stop
659 CALL MSETMAPPVDR(trim(dpname),.true.,istatus)
660 if(istatus /= success_p)stop
674 ! "All profilers" consists of both the NPN and the MAP subsystems. We'll be
675 ! forgiving if an AWIPS database user naively included MAP (by not specifically
676 ! setting the providers). A user of the MADIS database, however, should know
677 ! better -- we'll stop with a fatal exit.
679 CALL MINIT('NPN',madis_profiler_db,.true.,istatus)
680 if(istatus /= success_p)stop
682 CALL MINIT('MAP','FSL',.true.,istatus) ! No AWIPS database for MAP.
683 if(istatus /= success_p)then
684 if(madis_profiler_db(1:3).eq.'FSL')stop
696 CALL MINIT('ACARS',madis_airep_db,.true.,istatus)
697 if(istatus /= success_p)stop
701 if(use_geoamvobs)then
703 CALL MINIT('SATWND',madis_geoamv_db,.true.,istatus)
704 if(istatus /= success_p)stop
706 if(.not. madis_geoamv_all_providers)then
708 if(print_detail_obs)then
710 write(6,*)'Selecting individual SATOB providers from ',&
711 trim(madis_geoamv_provider_list)
713 CALL MSETSATWNDPVDR('ALL-GOES-O',.false.,istatus)
714 if(istatus /= success_p)stop
717 pvdrfile = madis_geoamv_provider_list
718 open(unit=lun,file=trim(pvdrfile),status='OLD', &
719 iostat=pvdriostat,err=8000)
723 do i = 1, max_provider
724 read(lun,1,err=8000,iostat=pvdriostat,end=4)dpname
725 if(.not. (dpname(1:1) == '#' .or. len(trim(dpname)) == 0))then
726 if(print_detail_obs)write(6,*)' Selecting: ',trim(dpname)
727 CALL MSETSATWNDPVDR(trim(dpname),.true.,istatus)
728 if(istatus /= success_p)stop
737 ! Set the number and types of SATW variables to read.
741 if(madis_geoamv_ir.and.madis_geoamv_wv.and.madis_geoamv_vis.and. &
742 madis_geoamv_s10.and.madis_geoamv_s11)then
751 if(madis_geoamv_ir)then
752 nsatw_vartype = nsatw_vartype + 1
753 satw_var_len(nsatw_vartype) = 4
754 satw_var(1,nsatw_vartype) = 'DDIR'
755 satw_var(2,nsatw_vartype) = 'FFIR'
758 if(madis_geoamv_wv)then
759 nsatw_vartype = nsatw_vartype + 1
760 satw_var_len(nsatw_vartype) = 4
761 satw_var(1,nsatw_vartype) = 'DDWV'
762 satw_var(2,nsatw_vartype) = 'FFWV'
765 if(madis_geoamv_vis)then
766 nsatw_vartype = nsatw_vartype + 1
767 satw_var_len(nsatw_vartype) = 5
768 satw_var(1,nsatw_vartype) = 'DDVIS'
769 satw_var(2,nsatw_vartype) = 'FFVIS'
772 if(madis_geoamv_s10)then
773 nsatw_vartype = nsatw_vartype + 1
774 satw_var_len(nsatw_vartype) = 5
775 satw_var(1,nsatw_vartype) = 'DDS10'
776 satw_var(2,nsatw_vartype) = 'FFS10'
779 if(madis_geoamv_s11)then
780 nsatw_vartype = nsatw_vartype + 1
781 satw_var_len(nsatw_vartype) = 5
782 satw_var(1,nsatw_vartype) = 'DDS11'
783 satw_var(2,nsatw_vartype) = 'FFS11'
790 ! Select the QC level to be returned to "max possible QC level for each
793 CALL MSETQC(qcall,istatus)
794 if(istatus /= success_p)stop
796 ! Convert the user's desired time to the format used by MADIS
799 tstr = analysis_date(1:4)//analysis_date(6:7)//analysis_date(9:10)// &
800 '_'//analysis_date(12:13)//analysis_date(15:16)
802 ! ***** This commented-out section is used only by MADIS developers to
803 ! hardwire the desired time when doing stand-alone testing.
805 ! open(unit=19,file='mfb_time.txt',status='old')
809 ! ***** End of test code section.
811 ! Now convert 'YYYYMMDD_HH00' to 'YYJJJHH00' (JJJ = Julian date).
813 CALL MTRNTIM(tstr,1,atime,istatus)
814 if(istatus /= success_p)stop
816 !------------------------------------------------------------------------------
817 ! MADIS surface datasets --> WRF datasets METAR, GPSPW, SHIPS
818 !------------------------------------------------------------------------------
819 ! If we're not processing any of these WRF datasets, skip to the next dataset.
821 if(.not. use_metarobs .and. .not. use_shipsobs .and. .not. use_gpspwobs)go to 150
823 ! Allocate the local memory for the MADIS arrays that have a level dimension
824 ! (only 1 level in this case).
826 allocate (p(max_sfc))
827 allocate (q(max_sfc))
828 allocate (t(max_sfc))
829 allocate (z(max_sfc))
830 allocate (dd(max_sfc))
831 allocate (ff(max_sfc))
832 allocate (qca(max_sfc))
833 allocate (qcr(max_sfc))
834 allocate (qcd(max_sfc))
838 ! Set the time window for this dataset with the user's choices.
840 CALL MSETWIN(madis_metar_minbck,madis_metar_minfwd,madis_metar_recwin,istatus)
841 if(istatus /= success_p)stop
843 ! Load in the stations that have data in this time window. If we have any
844 ! problems reading in the stations we'll skip this dataset. When we're done
845 ! with all the datasets, if nothing's been read in there's a problem
846 ! and we'll stop with an error. If a particular dataset isn't there, but
847 ! the others aren't, that's not as fundamental of a problem.
849 CALL MSFCSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,provdr,istatus)
850 if(istatus /= success_p)go to 50
852 ! Read in the observations, with QC filtering as specified in MSETQC --
853 ! this will put MADIS missing flags in all obs that didn't pass the QC.
854 ! Note that we don't check the status on each variable read. It's simpler
855 ! to fill in missing flags into each variable before reading them, then
856 ! we can sort this all out below.
859 CALL MGETSFC(atime,'P',ntmp,nobs,p,qcd,qca,qcr,istatus)
861 CALL MGETSFC(atime,'Q',ntmp,nobs,q,qcd,qca,qcr,istatus)
863 CALL MGETSFC(atime,'T',ntmp,nobs,t,qcd,qca,qcr,istatus)
865 CALL MGETSFC(atime,'DD',ntmp,nobs,dd,qcd,qca,qcr,istatus)
867 CALL MGETSFC(atime,'FF',ntmp,nobs,ff,qcd,qca,qcr,istatus)
869 CALL MGETSFC(atime,'SLP',ntmp,nobs,slp,qcd,qca,qcr,istatus)
871 ! Fill in missing flags for the PW variable, copy ELEV to Z
872 ! and fill in 1 level for each station for use by the PROCESS_DATASET
873 ! routine. Also, any stations at sea level that have SLP but not P,
874 ! put SLP into P -- while a useful idea in general, this particularly
875 ! makes a difference with maritime obs -- usually at sea level, with
876 ! a lot of stations measuring SLP but not P.
882 if(p(i) == miss_p)then
883 if(elev(i) == 0.0 .and. slp(i) /= miss_p)p(i) = slp(i)
887 ! Determine which ones are inside the user's domain, and then allocate
888 ! memory for the IV data for this dataset. Also note that we toss surface obs
891 ntmp = 0 ! Count of records inside domain.
895 ! Put LAT/LON into PLATFORM and call a DA subroutine to determine if
896 ! the station is in the domain. Also check for bad (mesonet) station
897 ! locations -- we have at least one provider who puts these into his
898 ! station table when he doesn't have valid coordinates.
900 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
901 platform % info % lat = lat(i)
902 platform % info % lon = lon(i)
904 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
906 if (outside_all .or. p(i) == miss_p)then
908 keep(i) = 0 ! 0 = Not in domain or no P.
912 ntotal(metar) = ntotal(metar) + 1
919 keep(i) = 1 ! 1 = Process.
922 if (global .and. (platform%loc%i < ids.or.platform%loc%i >= ide)) then
923 nlocal(metar) = nlocal(metar) + 2
925 nlocal(metar) = nlocal(metar) + 1
940 if(nlocal(metar) > 0)then
942 allocate (iv % metar(1:nlocal(metar)))
944 ! Call all land surface data METAR, and tell the sub that there's one level.
948 iv%info(metar)%max_lev = 1
950 ! Move the data out of the ingest arrays into the IV structure,
951 ! including attendant processing that fills in the location within
952 ! the user's domain, etc.
954 CALL PROCESS_DATASET(nsta,nlev,fm,keep,lat,lon,elev,timeob, &
955 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
956 0,0,nlevels,iv,nlocal_out,ntotal_out,sfclev)
958 ! Note that if PROCESS_DATASET detects that there's no useful data for
959 ! a station, it won't put it into IV. Therefore we'll adjust NLOCAL
960 ! accordingly (FILL_IV_INFO adjusts NTOTAL in the structure where it's
961 ! sent back to the data assimilation code).
963 iv%info(metar)%nlocal = nlocal_out
969 50 if(use_shipsobs)then
971 ! Because this WRF dataset is a subset of the MADIS surface subsystem,
972 ! we have to re-initialize the MADIS subsystem here, with provider selection,
973 ! QC level selection, etc.
975 CALL MINIT('SFC',madis_ships_db,.true.,istatus)
976 if(istatus /= success_p)stop
977 CALL MSETSFCPVDR('ALL-SFC',.false.,istatus)
978 if(istatus /= success_p)stop
979 CALL MSETSFCPVDR('MARITIME',.true.,istatus)
980 if(istatus /= success_p)stop
981 CALL MSETQC(qcall,istatus)
982 if(istatus /= success_p)stop
984 ! Set the time window for this dataset with the user's choices.
986 CALL MSETWIN(madis_ships_minbck,madis_ships_minfwd,madis_ships_recwin,istatus)
987 if(istatus /= success_p)stop
989 ! Load in the stations that have data in this time window.
991 CALL MSFCSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,provdr,istatus)
992 if(istatus /= success_p)go to 75
994 ! Read in the observations.
997 CALL MGETSFC(atime,'P',ntmp,nobs,p,qcd,qca,qcr,istatus)
999 CALL MGETSFC(atime,'Q',ntmp,nobs,q,qcd,qca,qcr,istatus)
1001 CALL MGETSFC(atime,'T',ntmp,nobs,t,qcd,qca,qcr,istatus)
1003 CALL MGETSFC(atime,'DD',ntmp,nobs,dd,qcd,qca,qcr,istatus)
1005 CALL MGETSFC(atime,'FF',ntmp,nobs,ff,qcd,qca,qcr,istatus)
1006 slp(1:nsta) = miss_p
1007 CALL MGETSFC(atime,'SLP',ntmp,nobs,slp,qcd,qca,qcr,istatus)
1009 ! Fill in missing flags for the PW variable, copy ELEV to Z
1010 ! and fill in 1 level for each station for use by the PROCESS_DATASET
1011 ! routine. Also, any stations at sea level that have SLP but not P,
1012 ! put SLP into P -- while a useful idea in general, this particularly
1013 ! makes a difference with maritime obs -- usually at sea level, with
1014 ! a lot of stations measuring SLP but not P.
1020 if(p(i) == miss_p)then
1021 if(elev(i) == 0.0 .and. slp(i) /= miss_p)p(i) = slp(i)
1025 ! Determine which ones are inside the user's domain, and then allocate
1026 ! memory for the IV data for this dataset. Also note that we toss ships obs
1027 ! that don't have P.
1029 ntmp = 0 ! Count of records inside domain.
1033 ! Put LAT/LON into PLATFORM and call a DA subroutine to determine if
1034 ! the station is in the domain.
1036 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
1037 platform % info % lat = lat(i)
1038 platform % info % lon = lon(i)
1039 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1041 if (outside_all .or. p(i) == miss_p)then
1044 ntotal(ships) = ntotal(ships) + 1
1050 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1051 nlocal(ships) = nlocal(ships) + 2
1053 nlocal(ships) = nlocal(ships) + 1
1063 if(nlocal(ships) > 0)then
1065 allocate (iv % ships(1:nlocal(ships)))
1067 iv%info(ships)%max_lev = 1
1068 CALL PROCESS_DATASET(nsta,nlev,fm,keep,lat,lon,elev,timeob, &
1069 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
1070 0,0,nlevels,iv,nlocal_out,ntotal_out,sfclev)
1071 iv%info(ships)%nlocal = nlocal_out
1076 75 if(use_gpspwobs)then
1078 ! Reinitialize the MADIS surface subsystem for GPSPW.
1080 CALL MINIT('SFC',madis_gpspw_db,.true.,istatus)
1081 if(istatus /= success_p)stop
1082 CALL MSETSFCPVDR('ALL-SFC',.false.,istatus)
1083 if(istatus /= success_p)stop
1084 CALL MSETSFCPVDR('GPSMET',.true.,istatus)
1085 if(istatus /= success_p)stop
1086 CALL MSETQC(qcall,istatus)
1087 if(istatus /= success_p)stop
1089 ! Set the time window for this dataset with the user's choices.
1091 CALL MSETWIN(madis_gpspw_minbck,madis_gpspw_minfwd,madis_gpspw_recwin,istatus)
1092 if(istatus /= success_p)stop
1094 ! Load in the stations that have data in this time window.
1096 CALL MSFCSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,provdr,istatus)
1097 if(istatus /= success_p)go to 100
1099 ! Read in the observations. Note that we put missing flags into DD/FF so
1100 ! that the DD/FF->U/V conversion won't be attempted in PROCESS_DATASETS.
1106 CALL MGETSFC(atime,'PWV',ntmp,nobs,pw,qcd,qca,qcr,istatus)
1107 slp(1:nsta) = miss_p
1108 CALL MGETSFC(atime,'SLP',ntmp,nobs,slp,qcd,qca,qcr,istatus)
1110 ! Copy ELEV to Z and fill in 1 level for each station for use by the
1111 ! PROCESS_DATASET routine.
1118 ! Determine which ones are inside the user's domain and have PW, and then
1119 ! allocate memory for the IV data for this dataset.
1125 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
1126 platform % info % lat = lat(i)
1127 platform % info % lon = lon(i)
1128 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1130 if (outside_all .or. pw(i) == miss_p)then
1133 ntotal(gpspw) = ntotal(gpspw) + 1
1138 pw(i) = pw(i) * 100.0 ! Convert from m to cm.
1140 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1141 nlocal(gpspw) = nlocal(gpspw) + 2
1143 nlocal(gpspw) = nlocal(gpspw) + 1
1153 if(nlocal(gpspw) > 0)then
1155 allocate (iv % gpspw(1:nlocal(gpspw)))
1157 iv%info(gpspw)%max_lev = 1
1158 CALL PROCESS_DATASET(nsta,nlev,fm,keep,lat,lon,elev,timeob, &
1159 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
1160 0,0,nlevels,iv,nlocal_out,ntotal_out,sfclev)
1161 iv%info(gpspw)%nlocal = nlocal_out
1166 ! Finish up with the MADIS surface datasets by deallocating the
1167 ! levels-dimensioned arrays.
1179 !------------------------------------------------------------------------------
1180 ! MADIS ACARS dataset --> WRF AIREP dataset
1181 !------------------------------------------------------------------------------
1182 ! If we're not using this WRF dataset, skip to the next one.
1184 150 if(.not. use_airepobs)go to 250
1186 ! Set the time window for this dataset with the user's choices.
1188 CALL MSETWIN(madis_airep_minbck,madis_airep_minfwd,madis_airep_recwin,istatus)
1189 if(istatus /= success_p)stop
1191 ! Load in the stations with data for this time window.
1193 CALL MACARSSTA(atime,nsta,stanam,timeob,istatus)
1194 if(istatus /= success_p)go to 200
1196 ! Allocate the local memory for the MADIS arrays that have a level dimension.
1204 allocate (qca(nsta))
1205 allocate (qcr(nsta))
1206 allocate (qcd(nsta))
1208 ! Read in the observations. Note that unlike the other MADIS datasets,
1209 ! the lat/lon are read in as obs, not station info.
1212 CALL MGETACARS(atime,'P',ntmp,nobs,p,qcd,qca,qcr,istatus)
1214 CALL MGETACARS(atime,'T',ntmp,nobs,t,qcd,qca,qcr,istatus)
1216 CALL MGETACARS(atime,'DD',ntmp,nobs,dd,qcd,qca,qcr,istatus)
1218 CALL MGETACARS(atime,'FF',ntmp,nobs,ff,qcd,qca,qcr,istatus)
1219 lat(1:nsta) = miss_p
1220 CALL MGETACARS(atime,'LAT',ntmp,nobs,lat,qcd,qca,qcr,istatus)
1221 lon(1:nsta) = miss_p
1222 CALL MGETACARS(atime,'LON',ntmp,nobs,lon,qcd,qca,qcr,istatus)
1224 CALL MGETACARS(atime,'HT',ntmp,nobs,z,qcd,qca,qcr,istatus)
1226 ! Fill in missing flags for the PW, SLP and ELEV variables, and fill in
1227 ! 1 level for each station for use by the PROCESS_DATASET routine.
1236 ! Determine which ones are inside the user's domain, and then allocate
1237 ! memory for the IV data for this dataset.
1239 ntmp = 0 ! Count of records inside domain.
1243 if (abs(lat(i)).lt.90.and.abs(lon(i)).le.180) then
1244 platform % info % lat = lat(i)
1245 platform % info % lon = lon(i)
1246 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1248 if (outside_all) then
1250 keep(i) = 0 ! 0 = Not in domain.
1254 ntotal(airep) = ntotal(airep) + 1
1258 keep(i) = 1 ! 1 = Process.
1260 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1261 nlocal(airep) = nlocal(airep) + 2
1263 nlocal(airep) = nlocal(airep) + 1
1277 if(nlocal(airep) > 0)then
1278 allocate (iv % airep(1:nlocal(airep)))
1283 iv%info(airep)%max_lev = 1
1285 ! Move the data out of the ingest arrays into the IV structure.
1287 CALL PROCESS_DATASET(nsta,nlev,fm,keep,lat,lon,elev,timeob, &
1288 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
1289 0,0,nlevels,iv,nlocal_out,ntotal_out,sfclev)
1291 iv%info(airep)%nlocal = nlocal_out
1292 iv%info(airep)%plocal(1) = nlocal_out
1293 iv%info(airep)%ptotal(1) = ntotal(airep)
1294 iv%info(airep)%ntotal = ntotal(airep)
1297 ! Finish up with the MADIS ACARS datasets by deallocating the
1298 ! levels-dimensioned arrays.
1310 !------------------------------------------------------------------------------
1311 ! MADIS RAOB/NPN/MAP datasets --> WRF SOUND dataset
1312 !------------------------------------------------------------------------------
1314 250 if(.not. use_soundobs)go to 300
1316 ! ***** Split off the RAOB dataset from this section once profiler data
1317 ! structures have been added.
1319 ! ***** Remember to add the use_xxxobs logic for profilers.
1321 ! This MADIS-->WRF dataset transition is more complicated than the other
1322 ! ones we've done above, because we need to map multiple MADIS datasets
1323 ! into one WRF dataset, and we need to know how many reports we're going
1324 ! to have in the domain in order to allocate the IV memory. Therefore,
1325 ! we'll set the time window for each MADIS dataset, read its station info,
1326 ! and count up the reports inside the domain over all the MADIS datasets.
1327 ! Once that's been done, then the same tasks will be done as for the
1328 ! simpler datasets above.
1332 ! Set the time window for this dataset with the user's choices.
1334 CALL MSETWIN(madis_sound_minbck,madis_sound_minfwd,madis_sound_recwin,istatus)
1335 if(istatus /= success_p)stop
1337 CALL MRAOBSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,istatus)
1338 if(istatus == success_p)then
1340 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
1341 platform % info % lat = lat(i)
1342 platform % info % lon = lon(i)
1343 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1344 if (outside_all) then
1345 keep_r(i) = 0 ! 0 = Not in domain.
1347 ntotal(sound) = ntotal(sound) + 1
1351 keep_r(i) = 1 ! 1 = Process.
1353 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1354 nlocal(sound) = nlocal(sound) + 2
1356 nlocal(sound) = nlocal(sound) + 1
1367 ! Keep track of nlocal and notal for use by PROCESS_DATASET when it needs to
1368 ! know these values over several calls.
1370 nl_raob = nlocal(sound)
1371 nt_raob = ntotal(sound)
1375 write(unit=message(1),fmt='(A,I10)')'ntotal_raob=',ntotal(sound)
1376 call da_message(message(1:1))
1381 ! Set the time window for this dataset with the user's choices.
1383 CALL MSETWIN(madis_profiler_minbck,madis_profiler_minfwd,madis_profiler_recwin,istatus)
1384 if(istatus /= success_p)stop
1385 CALL MNPNSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,istatus)
1386 if(istatus == success_p)then
1388 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
1389 platform % info % lat = lat(i)
1390 platform % info % lon = lon(i)
1391 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1392 if (outside_all)then
1393 keep_n(i) = 0 ! 0 = Not in domain.
1395 ntotal(sound) = ntotal(sound) + 1
1399 keep_n(i) = 1 ! 1 = Process.
1401 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1402 nlocal(sound) = nlocal(sound) + 2
1404 nlocal(sound) = nlocal(sound) + 1
1416 ! Keep track of nlocal and notal for use by PROCESS_DATASET when it needs to
1417 ! know these values over several calls.
1419 nl_npn = nlocal(sound) - nl_raob
1420 nt_npn = ntotal(sound) - nt_raob
1422 write(unit=message(1),fmt='(A,I10)')'ntotal_npn=',ntotal(sound)
1423 call da_message(message(1:1))
1430 ! Set the time window for this dataset with the user's choices.
1432 CALL MSETWIN(madis_profiler_minbck,madis_profiler_minfwd,madis_profiler_recwin,istatus)
1433 if(istatus /= success_p)stop
1434 CALL MMAPSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,provdr, &
1436 if(istatus == success_p)then
1438 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
1439 platform % info % lat = lat(i)
1440 platform % info % lon = lon(i)
1441 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1442 if (outside_all)then
1443 keep_m(i) = 0 ! 0 = Not in domain.
1445 ntotal(sound) = ntotal(sound) + 1
1449 keep_m(i) = 1 ! 1 = Process.
1451 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1452 nlocal(sound) = nlocal(sound) + 2
1454 nlocal(sound) = nlocal(sound) + 1
1466 ! Keep track of nlocal and notal for use by PROCESS_DATASET when it needs to
1467 ! know these values over several calls.
1469 nl_map = nlocal(sound) - nl_raob - nl_npn
1470 nt_map = ntotal(sound) - nt_raob - nt_npn
1472 write(unit=message(1),fmt='(A,I10)')'ntotal_map=',ntotal(sound)
1473 call da_message(message(1:1))
1474 ! If we didn't find anything, we're done with this WRF dataset.
1476 if (nlocal(sound) > 0) then
1477 allocate (iv % sound(1:nlocal(sound)))
1478 allocate (iv % sonde_sfc(1:nlocal(sound)))
1482 iv%info(sound)%max_lev = max_raoblev
1483 iv%info(sonde_sfc)%max_lev=1
1485 ! Since we have the MAP station info, start with that dataset.
1489 ! Allocate the local memory for the MADIS arrays that have a level dimension.
1491 allocate (p(max_maplev*nsta))
1492 allocate (q(max_maplev*nsta))
1493 allocate (t(max_maplev*nsta))
1494 allocate (z(max_maplev*nsta))
1495 allocate (dd(max_maplev*nsta))
1496 allocate (ff(max_maplev*nsta))
1497 allocate (qca(max_maplev*nsta))
1498 allocate (qcr(max_maplev*nsta))
1499 allocate (qcd(max_maplev*nsta))
1503 ! Read in the observations.
1505 p(1:nsta*nlev) = miss_p
1506 CALL MGETMAP(atime,'P',ntmp,nobs,nlevels,p,qcd,qca,qcr,istatus)
1507 dd(1:nsta*nlev) = miss_p
1508 CALL MGETMAP(atime,'DD',ntmp,nobs,nlevels,dd,qcd,qca,qcr,istatus)
1509 ff(1:nsta*nlev) = miss_p
1510 CALL MGETMAP(atime,'FF',ntmp,nobs,nlevels,ff,qcd,qca,qcr,istatus)
1511 z(1:nsta*nlev) = miss_p
1512 CALL MGETMAP(atime,'HT',ntmp,nobs,nlevels,z,qcd,qca,qcr,istatus)
1514 ! Fill in missing flags for the variables that aren't in this dataset,
1515 ! process it, deallocate the memory.
1517 slp(1:nsta) = miss_p
1519 q(1:nsta*nlev) = miss_p
1520 t(1:nsta*nlev) = miss_p
1523 CALL PROCESS_DATASET(nsta,nlev,fm,keep_m,lat,lon,elev,timeob, &
1524 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
1525 0,0,nlevels,iv,nlocal_out,ntotal_out,sfclev)
1543 ! Now do the NPN dataset.
1547 ! Allocate the local memory for the MADIS arrays that have a level dimension.
1549 if(madis_profiler_db(1:3) == 'FSL')then
1550 nlev = max_npnlev_madis
1552 nlev = max_npnlev_awips
1555 ! Set the time window and load in the station info.
1557 CALL MSETWIN(madis_profiler_minbck,madis_profiler_minfwd,madis_profiler_recwin,istatus)
1558 if(istatus /= success_p)stop
1559 CALL MNPNSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,istatus)
1560 if(istatus /= success_p)stop ! Can't possibly happen, so stop if it does.
1562 allocate (p(nlev*nsta))
1563 allocate (q(nlev*nsta))
1564 allocate (t(nlev*nsta))
1565 allocate (z(nlev*nsta))
1566 allocate (dd(nlev*nsta))
1567 allocate (ff(nlev*nsta))
1568 allocate (qca(nlev*nsta))
1569 allocate (qcr(nlev*nsta))
1570 allocate (qcd(nlev*nsta))
1572 ! Read in the observations.
1574 p(1:nsta*nlev) = miss_p
1575 CALL MGETNPN(atime,'P',ntmp,nobs,nlevels,p,qcd,qca,qcr,istatus)
1576 dd(1:nsta*nlev) = miss_p
1577 CALL MGETNPN(atime,'DD',ntmp,nobs,nlevels,dd,qcd,qca,qcr,istatus)
1578 ff(1:nsta*nlev) = miss_p
1579 CALL MGETNPN(atime,'FF',ntmp,nobs,nlevels,ff,qcd,qca,qcr,istatus)
1580 z(1:nsta*nlev) = miss_p
1581 CALL MGETNPN(atime,'HT',ntmp,nobs,nlevels,z,qcd,qca,qcr,istatus)
1583 ! Fill in missing flags for the variables that aren't in this dataset,
1584 ! process it, deallocate the memory.
1586 slp(1:nsta) = miss_p
1588 q(1:nsta*nlev) = miss_p
1589 t(1:nsta*nlev) = miss_p
1592 CALL PROCESS_DATASET(nsta,nlev,fm,keep_n,lat,lon,elev,timeob, &
1593 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
1594 nlocal_out,ntotal_out,nlevels,iv,nlocal_out, &
1609 ! Do the RAOB dataset.
1615 ! Set the time window and load in the station info.
1617 CALL MSETWIN(madis_sound_minbck,madis_sound_minfwd,madis_sound_recwin,istatus)
1618 if(istatus /= success_p)stop
1619 CALL MRAOBSTA(atime,nsta,stanam,wmoid,lat,lon,elev,timeob,istatus)
1620 if(istatus /= success_p)stop ! Can't possibly happen, so stop if it does.
1622 ! Allocate the local memory for the MADIS arrays that have a level dimension.
1624 allocate (p(max_raoblev*nsta))
1625 allocate (q(max_raoblev*nsta))
1626 allocate (t(max_raoblev*nsta))
1627 allocate (z(max_raoblev*nsta))
1628 allocate (dd(max_raoblev*nsta))
1629 allocate (ff(max_raoblev*nsta))
1630 allocate (qca(max_raoblev*nsta))
1631 allocate (qcr(max_raoblev*nsta))
1632 allocate (qcd(max_raoblev*nsta))
1633 allocate (levtype(max_raoblev*nsta))
1635 ! Read in the observations.
1637 p(1:nsta*nlev) = miss_p
1638 CALL MGETRAOB(atime,'P',ntmp,nobs,nlevels,p,qcd,qca,qcr,istatus)
1639 q(1:nsta*nlev) = miss_p
1640 CALL MGETRAOB(atime,'Q',ntmp,nobs,nlevels,q,qcd,qca,qcr,istatus)
1641 t(1:nsta*nlev) = miss_p
1642 CALL MGETRAOB(atime,'T',ntmp,nobs,nlevels,t,qcd,qca,qcr,istatus)
1643 dd(1:nsta*nlev) = miss_p
1644 CALL MGETRAOB(atime,'DD',ntmp,nobs,nlevels,dd,qcd,qca,qcr,istatus)
1645 ff(1:nsta*nlev) = miss_p
1646 CALL MGETRAOB(atime,'FF',ntmp,nobs,nlevels,ff,qcd,qca,qcr,istatus)
1647 z(1:nsta*nlev) = miss_p
1648 CALL MGETRAOB(atime,'HT',ntmp,nobs,nlevels,z,qcd,qca,qcr,istatus)
1649 levtype(1:nsta*nlev) = miss_p
1650 CALL MGETRAOB(atime,'LEVTYPE',ntmp,nobs,nlevels,levtype,qcd,qca,qcr,istatus)
1652 ! Knock out any stations with zero levels of actual data. Also find the
1653 ! surface level for each station and fill in its P into SLP.
1659 if(nlevels(i) == 0)then
1665 CALL FIND_SFC_LEVEL(i,nlev,nsta,nlevels(i),levtype,p,slp(i),sfclev(i))
1671 ! Fill in missing flags for the variables that aren't in this dataset,
1672 ! process the data, deallocate the memory.
1674 260 pw(1:nsta) = miss_p
1676 CALL PROCESS_DATASET(nsta,nlev,fm,keep_r,lat,lon,elev,timeob, &
1677 slp,pw,stanam,p,q,t,dd,ff,z,nlocal,ntotal, &
1678 nlocal_out,ntotal_out,nlevels,iv,nlocal_out, &
1680 iv%info(sound)%nlocal = nlocal_out
1691 deallocate (levtype)
1695 iv%info(sound)%plocal(1) = nlocal_out
1696 iv%info(sound)%ptotal(1) = ntotal(sound)
1697 iv%info(sound)%ntotal = ntotal(sound)
1698 iv%info(sonde_sfc)%plocal(1) = nlocal_out
1699 iv%info(sonde_sfc)%ptotal(1) = ntotal(sound)
1700 iv%info(sonde_sfc)%ntotal = ntotal(sound)
1701 iv%info(sonde_sfc)%nlocal = nlocal_out
1705 !***** Put the profiler or raob dataset here (at statement 300) when these
1708 !------------------------------------------------------------------------------
1709 ! MADIS SATWND dataset --> WRF GeoAMV dataset
1710 !------------------------------------------------------------------------------
1711 ! If we're not using this WRF dataset, skip to the next one.
1713 450 if(.not. use_geoamvobs)go to 550
1715 ! Allocate the local memory for the MADIS arrays that have a level dimension.
1717 allocate (p(max_satw))
1718 allocate (q(max_satw))
1719 allocate (t(max_satw))
1720 allocate (z(max_satw))
1721 allocate (dd(max_satw))
1722 allocate (ff(max_satw))
1723 allocate (qca(max_satw))
1724 allocate (qcr(max_satw))
1725 allocate (qcd(max_satw))
1727 ! Set the time window for this dataset with the user's choices.
1729 CALL MSETWIN(madis_geoamv_minbck,madis_geoamv_minfwd,madis_geoamv_recwin,istatus)
1730 if(istatus /= success_p)stop
1732 ! Load in the stations with data for this hour. Note that the station call
1733 ! covers all variable types. Therefore, when we read each variable type's
1734 ! data separately, we'll have to overlay that into the dd/ff arrays so
1735 ! we don't wipe out data read for an earlier variable type. We'll use the
1736 ! not-applicable pw/slp arrays for temporary storage.
1738 CALL MSATWNDSTA(atime,nsta,provdr,lat,lon,p,timeob,istatus)
1739 if(istatus /= success_p)go to 500
1741 ! Read in the observations, appending each variable type as we go along.
1746 do i = 1, nsatw_vartype
1748 CALL MGETSATWND(atime,satw_var(1,i)(1:satw_var_len(i)),ntmp,nobs, &
1749 pw,qcd,qca,qcr,istatus)
1750 CALL MGETSATWND(atime,satw_var(2,i)(1:satw_var_len(i)),ntmp,nobs, &
1751 slp,qcd,qca,qcr,istatus)
1753 if(istatus == success_p)then
1757 if(pw(j) /= miss_p)then
1770 ! Fill in missing flags for the variables that aren't in this dataset,
1771 ! and fill in 1 level for each station for use by the PROCESS_DATASET routine.
1774 slp(1:nsta) = miss_p
1775 elev(1:nsta) = miss_p
1779 ! Determine which ones are inside the user's domain, and then allocate
1780 ! memory for the IV data for this dataset. Also toss those that don't
1781 ! have any data -- we only have to check one of the wind variables,
1782 ! if it exists, then all variables will exist.
1784 ntmp = 0 ! Count of records inside domain.
1788 if(abs(lat(i)).lt.90.and.abs(lon(i)).le.180)then
1789 platform % info % lat = lat(i)
1790 platform % info % lon = lon(i)
1791 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
1792 if (outside_all .or. dd(i) == miss_p)then
1793 keep(i) = 0 ! 0 = Not in domain or no data.
1795 ntotal(geoamv) = ntotal(geoamv) + 1
1799 keep(i) = 1 ! 1 = Process.
1801 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
1802 nlocal(geoamv) = nlocal(geoamv) + 2
1804 nlocal(geoamv) = nlocal(geoamv) + 1
1814 if(nlocal(geoamv) > 0)then
1816 allocate (iv % geoamv(1:nlocal(geoamv)))
1820 iv%info(geoamv)%max_lev = 1
1822 ! Move the data out of the ingest arrays into the IV structure.
1824 CALL PROCESS_DATASET(nsta,nlev,fm,keep,lat,lon,elev,timeob, &
1825 slp,pw,provdr,p,q,t,dd,ff,z,nlocal,ntotal, &
1826 0,0,nlevels,iv,nlocal_out,ntotal_out,sfclev)
1827 iv%info(geoamv)%nlocal = nlocal_out
1831 ! Finish up with the MADIS SATWND datasets by deallocating the
1832 ! levels-dimensioned arrays.
1844 550 continue ! Placeholder for the next dataset that's added.
1848 !----------------------------------------------------------------------------
1849 ! Report error reading namelist.
1850 !----------------------------------------------------------------------------
1851 8500 write(0,*)' ERROR: ', errmsg(i), ' IOSTAT = ', IOST, &
1852 ' while reading MADIS namelist'
1855 !------------------------------------------------------------------------------
1856 ! Endgame processing
1857 !------------------------------------------------------------------------------
1859 8000 if(pvdriostat /= 0)then
1861 ! I/O error on opening or reading a provider-selection file.
1863 write(0,*)'ERROR: ',pvdriotype,' failure on ',trim(pvdrfile), &
1864 ' IOSTAT = ',pvdriostat
1867 ! If we didn't get *anything*, output a suitable message and stop.
1869 else if(iv%info(sound)%nlocal+iv%info(geoamv)%nlocal+iv%info(airep)%nlocal+ &
1870 iv%info(gpspw)%nlocal+iv%info(metar)%nlocal+iv%info(ships)%nlocal &
1872 write(0,*)'ERROR: No MADIS observations were found.'
1876 ! Close the MADIS files and deallocate the memory used for the
1877 ! MADIS arrays that are dimensioned only by station.
1890 deallocate (nlevels)
1892 ! Output the same summary info as the MM5 ingest routine, but just
1893 ! for those datasets we handle.
1895 if ( print_detail_obs ) then
1897 write(6, fmt='(5x,a,i6,a)') &
1898 'Read: ', iv%info(sound)%nlocal, ' SOUND reports,', &
1899 'Read: ', iv%info(geoamv)%nlocal, ' Geo AMV reports,', &
1900 'Read: ', iv%info(airep)%nlocal, ' AIREP reports,', &
1901 'Read: ', iv%info(gpspw)%nlocal, ' GPSPW/GPSZD reports,', &
1902 'Read: ', iv%info(metar)%nlocal, ' METAR reports,', &
1903 'Read: ', iv%info(ships)%nlocal, ' SHIP reports,'
1907 ! Output a dump of all the obs, when desired, for testing purposes.
1909 if(madis_debug > 0)then
1912 write(6,*)'METAR: ',iv%info(metar)%nlocal
1915 do i = 1, iv%info(metar)%nlocal
1916 write(6,1000)iv%info(metar)%name(i)(1:8), &
1917 iv%info(metar)%date_char(i)(1:16), &
1918 iv%info(metar)%platform(i), &
1919 iv%info(metar)%lat(1,i),iv%info(metar)%lon(1,i), &
1920 iv%info(metar)%elv(i),iv%info(metar)%pstar(i), &
1921 iv%info(metar)%levels(i), &
1922 iv%info(metar)%slp(i)%inv,iv%info(metar)%slp(i)%qc, &
1923 iv%info(metar)%slp(i)%error,iv%info(metar)%pw(i)%inv, &
1924 iv%info(metar)%pw(i)%qc,iv%info(metar)%pw(i)%error
1925 1000 format(a,1x,a,1x,a,f6.2,1x,f7.2,1x,f10.2,1x,f8.2,1x,i3,1x, &
1926 f10.2,1x,i3,1x,f10.2,1x,f12.4,1x,i3,1x,f10.2)
1927 write(6,1001)1,' H/Z/U/V',iv%metar(i)%h,missing_data, &
1928 iv%info(metar)%zk(1,i), &
1929 iv%metar(i)%u%inv,iv%metar(i)%u%qc,iv%metar(i)%u%error, &
1930 iv%metar(i)%v%inv,iv%metar(i)%v%qc,iv%metar(i)%v%error
1931 1001 format(i3,a,3(1x,f11.3,1x,i3,1x,f11.3))
1932 write(6,1001)1,' P/T/Q ',iv%metar(i)%p%inv,iv%metar(i)%p%qc, &
1933 iv%metar(i)%p%error,iv%metar(i)%t%inv,iv%metar(i)%t%qc, &
1934 iv%metar(i)%t%error,iv%metar(i)%q%inv,iv%metar(i)%q%qc, &
1939 write(6,*)'SHIPS: ',iv%info(ships)%nlocal
1942 do i = 1, iv%info(ships)%nlocal
1943 write(6,1000)iv%info(ships)%name(i)(1:8), &
1944 iv%info(ships)%date_char(i)(1:16), &
1945 iv%info(ships)%platform(i), &
1946 iv%info(ships)%lat(1,i),iv%info(ships)%lon(1,i), &
1947 iv%info(ships)%elv(i),iv%info(ships)%pstar(i), &
1948 iv%info(ships)%levels(i), &
1949 iv%info(ships)%slp(i)%inv,iv%info(ships)%slp(i)%qc, &
1950 iv%info(ships)%slp(i)%error,iv%info(ships)%pw(i)%inv, &
1951 iv%info(ships)%pw(i)%qc,iv%info(ships)%pw(i)%error
1952 write(6,1001)1,' H/Z/U/V',iv%ships(i)%h,missing_data, &
1953 iv%info(ships)%zk(1,i), &
1954 iv%ships(i)%u%inv,iv%ships(i)%u%qc,iv%ships(i)%u%error, &
1955 iv%ships(i)%v%inv,iv%ships(i)%v%qc,iv%ships(i)%v%error
1956 write(6,1001)1,' P/T/Q ',iv%ships(i)%p%inv,iv%ships(i)%p%qc, &
1957 iv%ships(i)%p%error,iv%ships(i)%t%inv,iv%ships(i)%t%qc, &
1958 iv%ships(i)%t%error,iv%ships(i)%q%inv,iv%ships(i)%q%qc, &
1963 write(6,*)'GPSPW: ',iv%info(gpspw)%nlocal
1966 do i = 1, iv%info(gpspw)%nlocal
1967 write(6,1002)iv%info(gpspw)%name(i)(1:8), &
1968 iv%info(gpspw)%date_char(i)(1:16), &
1969 iv%info(gpspw)%platform(i), &
1970 iv%info(gpspw)%lat(1,i),iv%info(gpspw)%lon(1,i), &
1971 iv%info(gpspw)%elv(i),iv%info(gpspw)%pstar(i), &
1972 iv%info(gpspw)%levels(i), &
1973 iv%info(gpspw)%slp(i)%inv,iv%info(gpspw)%slp(i)%qc, &
1974 iv%info(gpspw)%slp(i)%error,iv%info(gpspw)%pw(i)%inv, &
1975 iv%info(gpspw)%pw(i)%qc,iv%info(gpspw)%pw(i)%error, &
1976 iv%gpspw(i)%tpw%inv,iv%gpspw(i)%tpw%qc, &
1977 iv%gpspw(i)%tpw%error
1978 1002 format(a,1x,a,1x,a,f6.2,1x,f7.2,1x,f7.2,1x,f8.2,1x,i3,1x, &
1979 f10.2,1x,i3,1x,f10.2,1x,f12.4,1x,i3,1x,f10.2,1x, &
1980 f12.4,1x,i3,1x,f10.2)
1984 write(6,*)'SOUND: ',iv%info(sound)%nlocal
1987 do i = 1, iv%info(sound)%nlocal
1988 write(6,1000)iv%info(sound)%name(i)(1:8), &
1989 iv%info(sound)%date_char(i)(1:16), &
1990 iv%info(sound)%platform(i), &
1991 iv%info(sound)%lat(1,i),iv%info(sound)%lon(1,i), &
1992 iv%info(sound)%elv(i),iv%info(sound)%pstar(i), &
1993 iv%info(sound)%levels(i), &
1994 iv%info(sound)%slp(i)%inv,iv%info(sound)%slp(i)%qc, &
1995 iv%info(sound)%slp(i)%error,iv%info(sound)%pw(i)%inv, &
1996 iv%info(sound)%pw(i)%qc,iv%info(sound)%pw(i)%error
1997 do j = 1, iv%info(sound)%levels(i)
1998 write(6,1001)j,' H/Z/U/V',iv%sound(i)%h(j),missing_data, &
1999 iv%info(sound)%zk(j,i), &
2000 iv%sound(i)%u(j)%inv,iv%sound(i)%u(j)%qc, &
2001 iv%sound(i)%u(j)%error,iv%sound(i)%v(j)%inv, &
2002 iv%sound(i)%v(j)%qc,iv%sound(i)%v(j)%error
2003 write(6,1001)j,' P/T/Q ',iv%sound(i)%p(j),missing_data,missing_r, &
2004 iv%sound(i)%t(j)%inv, &
2005 iv%sound(i)%t(j)%qc,iv%sound(i)%t(j)%error, &
2006 iv%sound(i)%q(j)%inv,iv%sound(i)%q(j)%qc, &
2007 iv%sound(i)%q(j)%error
2012 write(6,*)'SONDE_SFC: ',iv%info(sonde_sfc)%nlocal
2015 do i = 1, iv%info(sonde_sfc)%nlocal
2016 write(6,1000)iv%info(sonde_sfc)%name(i)(1:8), &
2017 iv%info(sonde_sfc)%date_char(i)(1:16), &
2018 iv%info(sonde_sfc)%platform(i), &
2019 iv%info(sonde_sfc)%lat(1,i),iv%info(sonde_sfc)%lon(1,i), &
2020 iv%info(sonde_sfc)%elv(i),iv%info(sonde_sfc)%pstar(i), &
2021 iv%info(sonde_sfc)%levels(i), &
2022 iv%info(sonde_sfc)%slp(i)%inv,iv%info(sonde_sfc)%slp(i)%qc, &
2023 iv%info(sonde_sfc)%slp(i)%error,iv%info(sonde_sfc)%pw(i)%inv, &
2024 iv%info(sonde_sfc)%pw(i)%qc,iv%info(sonde_sfc)%pw(i)%error
2025 write(6,1001)1,' H/Z/U/V',iv%sonde_sfc(i)%h,missing_data, &
2026 iv%info(sonde_sfc)%zk(1,i), &
2027 iv%sonde_sfc(i)%u%inv,iv%sonde_sfc(i)%u%qc,iv%sonde_sfc(i)%u%error, &
2028 iv%sonde_sfc(i)%v%inv,iv%sonde_sfc(i)%v%qc,iv%sonde_sfc(i)%v%error
2029 write(6,1001)1,' P/T/Q ',iv%sonde_sfc(i)%p%inv,iv%sonde_sfc(i)%p%qc, &
2030 iv%sonde_sfc(i)%p%error,iv%sonde_sfc(i)%t%inv,iv%sonde_sfc(i)%t%qc, &
2031 iv%sonde_sfc(i)%t%error,iv%sonde_sfc(i)%q%inv,iv%sonde_sfc(i)%q%qc, &
2032 iv%sonde_sfc(i)%q%error
2036 write(6,*)'AIREP: ',iv%info(airep)%nlocal
2039 do i = 1, iv%info(airep)%nlocal
2040 write(6,1000)iv%info(airep)%name(i)(1:8), &
2041 iv%info(airep)%date_char(i)(1:16), &
2042 iv%info(airep)%platform(i), &
2043 iv%info(airep)%lat(1,i),iv%info(airep)%lon(1,i), &
2044 iv%info(airep)%elv(i),iv%info(airep)%pstar(i), &
2045 iv%info(airep)%levels(i), &
2046 iv%info(airep)%slp(i)%inv,iv%info(airep)%slp(i)%qc, &
2047 iv%info(airep)%slp(i)%error,iv%info(airep)%pw(i)%inv, &
2048 iv%info(airep)%pw(i)%qc,iv%info(airep)%pw(i)%error
2049 write(6,1001)1,' H/Z/U/V',iv%airep(i)%h(1),missing_data, &
2050 iv%info(airep)%zk(1,i), &
2051 iv%airep(i)%u(1)%inv,iv%airep(i)%u(1)%qc, &
2052 iv%airep(i)%u(1)%error,iv%airep(i)%v(1)%inv, &
2053 iv%airep(i)%v(1)%qc,iv%airep(i)%v(1)%error
2054 write(6,1001)1,' P/T ',iv%airep(i)%p(1),missing_data, &
2055 missing_r,iv%airep(i)%t(1)%inv, &
2056 iv%airep(i)%t(1)%qc,iv%airep(i)%t(1)%error
2060 write(6,*)'GEOAMV: ',iv%info(geoamv)%nlocal
2063 do i = 1, iv%info(geoamv)%nlocal
2064 write(6,1000)iv%info(geoamv)%name(i)(1:8), &
2065 iv%info(geoamv)%date_char(i)(1:16), &
2066 iv%info(geoamv)%platform(i), &
2067 iv%info(geoamv)%lat(1,i),iv%info(geoamv)%lon(1,i), &
2068 iv%info(geoamv)%elv(i),iv%info(geoamv)%pstar(i), &
2069 iv%info(geoamv)%levels(i), &
2070 iv%info(geoamv)%slp(i)%inv,iv%info(geoamv)%slp(i)%qc, &
2071 iv%info(geoamv)%slp(i)%error,iv%info(geoamv)%pw(i)%inv, &
2072 iv%info(geoamv)%pw(i)%qc,iv%info(geoamv)%pw(i)%error
2073 write(6,1001)1,' P/Z/U/V',iv%geoamv(i)%p(1),missing_data, &
2074 iv%info(geoamv)%zk(1,i), &
2075 iv%geoamv(i)%u(1)%inv,iv%geoamv(i)%u(1)%qc, &
2076 iv%geoamv(i)%u(1)%error,iv%geoamv(i)%v(1)%inv, &
2077 iv%geoamv(i)%v(1)%qc,iv%geoamv(i)%v(1)%error
2080 endif ! if(madis_debug > 0)
2082 ! Fill in the IV time.
2087 ! Copy data out of the IV structure into the OB structure.
2089 CALL da_fill_obs_structures(iv,ob)
2091 if(madis_debug > 0)then
2093 ! If we're in debugging mode, indicate that we made it to the bottom of
2094 ! the routine OK. Also, if requested, just stop after the obs ingest.
2097 write(6,*)'Successful MADIS ingest.'
2099 if(madis_debug == 2)stop
2106 call da_error(__FILE__,__LINE__,(/"Needs to be compiled with a MADIS library"/))
2109 if (trace_use) CALL da_trace_exit("da_setup_obs_structures_madis")
2111 END SUBROUTINE da_setup_obs_structures_madis
2115 SUBROUTINE PROCESS_DATASET(nsta,nlev,fm,keep,lat,lon,elev,timeob, &
2116 slp,pw,stanam,p,q,t,dd,ff,z, &
2117 nlocal,ntotal,nloc_init,ntot_init,nlevels,iv, &
2118 nlocal_out,ntotal_out,sfclev)
2120 !------------------------------------------------------------------------------
2121 ! PURPOSE: Move obs out of MADIS ingest arrays into the WRF innovation
2122 ! vector structure, including attendant processing that fills in the
2123 ! location within the user's domain, etc., for one MADIS dataset.
2125 ! METHOD: Move obs & metadata from MADIS ingest arrays to MM5-like
2126 ! PLATFORM structure, manipulate PLATFORM with DA_Obs routines,
2127 ! then move the resulting stuff into IV.
2129 ! HISTORY: 05-21-03 M. Barth Original version.
2130 ! 08-27-04 M. Barth Removed psfc and added sonde_sfc.
2131 ! 02-06-06 M. Barth Removed arguments no longer in use,
2132 ! changed xb to xp, removed DA_Obs_Count.
2133 ! 05-30-08 M. Barth Removed xp, changed DA_ll_to_xy to da_llxy,
2134 ! used the new iv%info structures,
2135 ! changed ob_type structure to iv_type,
2136 ! added nlocal and ntotal arrays and
2137 ! nloc_init, ntot_init. Added
2138 ! use of FILL_IV_INFO subroutine.
2139 ! 11-28-08 M. Barth Since I finally got the darn thing to
2140 ! compile, I debugged the massive changes
2144 ! PARENT_MODULE: da_setup_structures
2145 !------------------------------------------------------------------------------
2147 use da_grid_definitions, only : da_ffdduv
2148 use da_tools, only : da_llxy
2149 use da_obs, only : da_obs_proc_station
2154 INTEGER*4, INTENT(IN) :: nsta ! Number of stations
2155 INTEGER*4, INTENT(IN) :: nlev ! Number of levels
2156 INTEGER, INTENT(IN) :: fm ! GTS FM number for this dataset
2157 INTEGER*4, INTENT(IN) :: keep(nsta) ! 1 = process this station
2158 REAL*4, INTENT(IN) :: lat(nsta) ! Latitude (deg N)
2159 REAL*4, INTENT(IN) :: lon(nsta) ! Longitude (deg E)
2160 REAL*4, INTENT(IN) :: elev(nsta) ! Elevation (m)
2161 CHARACTER*9, INTENT(IN) :: timeob(nsta) ! Time (YYJJJHHMM)
2162 REAL*4, INTENT(IN) :: slp(nsta) ! Sea level pressure (Pa)
2163 REAL*4, INTENT(IN) :: pw(nsta) ! Precipitable water vapor (cm)
2164 CHARACTER*10, INTENT(IN) :: stanam(nsta) ! Station ID
2165 REAL*4, INTENT(IN) :: p(nlev,nsta) ! Pressure (Pa)
2166 REAL*4, INTENT(IN) :: q(nlev,nsta) ! Mixing ratio (kg/kg)
2167 REAL*4, INTENT(IN) :: t(nlev,nsta) ! Temperature (K)
2168 REAL*4, INTENT(INOUT) :: dd(nlev,nsta) ! Wind speed (m/s)
2169 REAL*4, INTENT(INOUT) :: ff(nlev,nsta) ! Wind direction (0-360 N)
2170 REAL*4, INTENT(IN) :: z(nlev,nsta) ! Height (m)
2171 INTEGER*4, INTENT(IN) :: nlocal(*) ! Obs counts per dataset, in domain
2172 INTEGER*4, INTENT(IN) :: ntotal(*) ! Obs counts per dataset, in or out
2173 INTEGER*4, INTENT(IN) :: nloc_init ! Initial value for nlocal index
2174 INTEGER*4, INTENT(IN) :: ntot_init ! Initial value for ntotal index
2175 INTEGER*4, INTENT(IN) :: nlevels(nsta) ! Num levels per station
2176 TYPE (iv_type), INTENT(INOUT) :: iv ! Innovation vector
2177 INTEGER*4, INTENT(OUT) :: nlocal_out ! Obs count in domain, and with useful data
2178 INTEGER*4, INTENT(OUT) :: ntotal_out ! Obs count, and with useful data
2179 INTEGER*4, INTENT(IN) :: sfclev(nsta) ! Index to raob sfc level per station
2183 TYPE (multi_level_type) :: platform
2184 INTEGER :: i,j,k,n,istatus,obs_index,ntot,ndup,l
2185 REAL*4, PARAMETER :: miss_p = 999999.0 ! Missing data flag
2186 CHARACTER*13 :: tstr
2187 LOGICAL :: outside,cycle_report,anyvar,outside_all
2188 REAL :: xff,xdd,xlon
2189 INTEGER*4 :: sfclev_j,m
2191 !------------------------------------------------------------------------------
2192 ! The MM5-like PLATFORM structure is used to move data out of the MADIS
2193 ! ingest arrays into a structure that can then be manipulated by the DA_Obs
2194 ! routines. Then, the single-station data in PLATFORM is moved to where
2195 ! it belongs in the output innovation vector, IV.
2196 !------------------------------------------------------------------------------
2197 ! Fill in dataset-specific info.
2201 platform % info % platform = 'FM-015 METAR'
2204 platform % info % platform = 'FM-013 SHIP '
2207 platform % info % platform = 'FM-096 AIREP'
2210 platform % info % platform = 'FM-035 SOUND'
2213 platform % info % platform = 'FM-111 GPSPW'
2216 platform % info % platform = 'FM-088 SATOB'
2220 ! Only allocate stuff the first time we're here for a WRF dataset, since multiple
2221 ! MADIS datasets may comprise a single WRF dataset (e.g., MAP, NPN, raob).
2223 if(nloc_init.eq.0)then
2225 iv%info(obs_index)%nlocal = nlocal(obs_index)
2226 iv%info(obs_index)%ntotal = ntotal(obs_index)
2227 if (iv%info(obs_index)%nlocal > 0) then
2228 allocate (iv%info(obs_index)%name(iv%info(obs_index)%nlocal))
2229 allocate (iv%info(obs_index)%platform(iv%info(obs_index)%nlocal))
2230 allocate (iv%info(obs_index)%id(iv%info(obs_index)%nlocal))
2231 allocate (iv%info(obs_index)%date_char(iv%info(obs_index)%nlocal))
2232 allocate (iv%info(obs_index)%levels(iv%info(obs_index)%nlocal))
2233 allocate (iv%info(obs_index)%lat(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2234 allocate (iv%info(obs_index)%lon(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2235 allocate (iv%info(obs_index)%elv(iv%info(obs_index)%nlocal))
2236 allocate (iv%info(obs_index)%pstar(iv%info(obs_index)%nlocal))
2237 allocate (iv%info(obs_index)%slp(iv%info(obs_index)%nlocal))
2238 allocate (iv%info(obs_index)%pw(iv%info(obs_index)%nlocal))
2239 allocate (iv%info(obs_index)%x (kms:kme,iv%info(obs_index)%nlocal))
2240 allocate (iv%info(obs_index)%y (kms:kme,iv%info(obs_index)%nlocal))
2241 allocate (iv%info(obs_index)%i (kms:kme,iv%info(obs_index)%nlocal))
2242 allocate (iv%info(obs_index)%j (kms:kme,iv%info(obs_index)%nlocal))
2243 allocate (iv%info(obs_index)%dx (kms:kme,iv%info(obs_index)%nlocal))
2244 allocate (iv%info(obs_index)%dxm(kms:kme,iv%info(obs_index)%nlocal))
2245 allocate (iv%info(obs_index)%dy (kms:kme,iv%info(obs_index)%nlocal))
2246 allocate (iv%info(obs_index)%dym(kms:kme,iv%info(obs_index)%nlocal))
2247 allocate (iv%info(obs_index)%k (iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2248 allocate (iv%info(obs_index)%dz (iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2249 allocate (iv%info(obs_index)%dzm(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2250 allocate (iv%info(obs_index)%zk (iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2251 allocate (iv%info(obs_index)%proc_domain(iv%info(obs_index)%max_lev,iv%info(obs_index)%nlocal))
2252 allocate (iv%info(obs_index)%obs_global_index(iv%info(obs_index)%nlocal))
2253 iv%info(obs_index)%proc_domain(:,:) = .false.
2254 iv%info(obs_index)%zk(:,:) = missing_r
2258 ! Now allocate the sonde_sfc iv%info arrays.
2260 allocate (iv%info(sonde_sfc)%name(iv%info(obs_index)%nlocal))
2261 allocate (iv%info(sonde_sfc)%platform(iv%info(obs_index)%nlocal))
2262 allocate (iv%info(sonde_sfc)%id(iv%info(obs_index)%nlocal))
2263 allocate (iv%info(sonde_sfc)%date_char(iv%info(obs_index)%nlocal))
2264 allocate (iv%info(sonde_sfc)%levels(iv%info(obs_index)%nlocal))
2265 allocate (iv%info(sonde_sfc)%lat(iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2266 allocate (iv%info(sonde_sfc)%lon(iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2267 allocate (iv%info(sonde_sfc)%elv(iv%info(obs_index)%nlocal))
2268 allocate (iv%info(sonde_sfc)%pstar(iv%info(obs_index)%nlocal))
2269 allocate (iv%info(sonde_sfc)%slp(iv%info(obs_index)%nlocal))
2270 allocate (iv%info(sonde_sfc)%pw(iv%info(obs_index)%nlocal))
2271 allocate (iv%info(sonde_sfc)%x (kms:kme,iv%info(obs_index)%nlocal))
2272 allocate (iv%info(sonde_sfc)%y (kms:kme,iv%info(obs_index)%nlocal))
2273 allocate (iv%info(sonde_sfc)%i (kms:kme,iv%info(obs_index)%nlocal))
2274 allocate (iv%info(sonde_sfc)%j (kms:kme,iv%info(obs_index)%nlocal))
2275 allocate (iv%info(sonde_sfc)%dx (kms:kme,iv%info(obs_index)%nlocal))
2276 allocate (iv%info(sonde_sfc)%dxm(kms:kme,iv%info(obs_index)%nlocal))
2277 allocate (iv%info(sonde_sfc)%dy (kms:kme,iv%info(obs_index)%nlocal))
2278 allocate (iv%info(sonde_sfc)%dym(kms:kme,iv%info(obs_index)%nlocal))
2279 allocate (iv%info(sonde_sfc)%k (iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2280 allocate (iv%info(sonde_sfc)%dz (iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2281 allocate (iv%info(sonde_sfc)%dzm(iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2282 allocate (iv%info(sonde_sfc)%zk (iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2283 allocate (iv%info(sonde_sfc)%proc_domain(iv%info(sonde_sfc)%max_lev,iv%info(obs_index)%nlocal))
2284 allocate (iv%info(sonde_sfc)%obs_global_index(iv%info(obs_index)%nlocal))
2285 iv%info(sonde_sfc)%proc_domain(:,:) = .false.
2286 iv%info(sonde_sfc)%zk(:,:) = missing_r
2294 ! Process each record that's in the user's domain.
2296 ! Note that the PLATFORM structure includes some variables that
2297 ! aren't needed, so we don't deal with them: RH, TD, SPEED.
2299 n = nloc_init ! Index into iv.
2300 ntot = ntot_init ! Value to use for current ntotal within iv-filling
2301 ! loop. See explanation of duplication logic.
2305 if(keep(i) == 1)then
2307 ! Fill in the header-type info for this record.
2309 platform % info % lat = lat(i)
2310 platform % info % lon = lon(i)
2311 platform % info % elv = elev(i)
2312 platform % info % name = stanam(i)
2313 platform % info % id = stanam(i)(1:5)
2314 platform % info % levels = nlevels(i)
2316 ! Convert time from YYJJJHHMM to YYYYMMDD_HHMM, then put it into
2317 ! the info % date_char format of YYYY-MM-DD_HH:MM:SS.
2319 CALL MTRNTIM(timeob(i),2,tstr,istatus)
2320 platform % info % date_char = tstr(1:4)//'-'//tstr(5:6)//'-'// &
2321 tstr(7:11)//':'//tstr(12:13)//':00'
2323 ! Fill in PW and SLP.
2325 ! ***** Note that I'm not sure if good QC is indicated by qc_good (1) or
2326 ! good_quality (0), or both... I'm guessing qc_good should work
2327 ! since da_read_obs_bufr accepts any value < 4.
2329 if(pw(i) /= miss_p)then
2330 platform % loc % pw % inv = pw(i)
2331 platform % loc % pw % qc = qc_good
2333 platform % loc % pw % inv = missing_r
2334 platform % loc % pw % qc = missing_data
2336 platform % loc % pw % error = .2 ! Same reference as in GET_OB_ERRORS.
2340 if(slp(i) /= miss_p)then
2341 platform % loc % slp % inv = slp(i)
2342 platform % loc % slp % qc = qc_good
2344 platform % loc % slp % inv = missing_r
2345 platform % loc % slp % qc = missing_data
2347 platform % loc % slp % error = 200. ! Same reference as in GET_OB_ERRORS.
2349 ! Fill in the data variables that are a function of level.
2351 j = 1 ! J = level index for what's gonna get used
2354 do k = 1, nlevels(i)
2356 if(z(k,i) /= miss_p)then
2357 platform % each(j) % height = z(k,i)
2359 platform % each(j) % height = missing_r
2362 if(p(k,i) /= miss_p)then
2363 platform % each(j) % p % inv = p(k,i)
2364 platform % each(j) % p % qc = qc_good
2366 platform % each(j) % p % inv = missing_r
2367 platform % each(j) % p % qc = missing_data
2370 ! If there isn't any P or Z, this level isn't going to make the cut, so
2371 ! skip the rest of its processing.
2373 if(.not.(p(k,i) == miss_p .and. z(k,i) == miss_p))then
2377 ! If DD and FF exist, convert to U,V with rotation to the user's grid.
2379 if(dd(k,i) /= miss_p .and. ff(k,i) /= miss_p)then
2383 CALL DA_FFDDUV(xff,xdd,platform%each(j)%u%inv, &
2384 platform%each(j)%v%inv,xlon,1)
2385 platform % each(j) % u % qc = qc_good
2386 platform % each(j) % v % qc = qc_good
2389 platform % each(j) % u % inv = missing_r
2390 platform % each(j) % u % qc = missing_data
2391 platform % each(j) % v % inv = missing_r
2392 platform % each(j) % v % qc = missing_data
2395 if(t(k,i) /= miss_p)then
2396 platform % each(j) % t % inv = t(k,i)
2397 platform % each(j) % t % qc = qc_good
2400 platform % each(j) % t % inv = missing_r
2401 platform % each(j) % t % qc = missing_data
2404 if(q(k,i) /= miss_p)then
2405 platform % each(j) % q % inv = q(k,i)
2406 platform % each(j) % q % qc = qc_good
2409 platform % each(j) % q % inv = missing_r
2410 platform % each(j) % q % qc = missing_data
2413 ! If we don't have any variables for profilers, punt. (For the
2414 ! other datasets, we can't be here without having at least P or Z,
2415 ! which for the non-profiler datasets, must be actual observations.
2416 ! For profilers, the P/Z variables are only coordinates of the
2417 ! observations, and aren't really observations.)
2419 if(anyvar .or. fm /= 35)then !***** change 35 when profilers defined
2421 ! Fill in the observation errors for this level.
2423 CALL GET_OB_ERRORS(platform%each(j))
2425 ! Compute the (x,y,z) and increment the counter of levels that are used.
2427 CALL da_llxy(platform%info,platform%loc,outside,outside_all)
2429 if(fm == 35 .and. k == sfclev(i))sfclev_j = j
2434 ! Subtract this level from the total count for this station.
2436 platform % info % levels = platform % info % levels - 1
2438 endif ! If any observed variables exist
2442 platform % info % levels = platform % info % levels - 1
2444 endif ! If P/Z exist
2448 ! It's possible that there will be no data at this point. One example of this
2449 ! is a RASS (temperature) only Multi-Agency Profiler report.
2451 if(platform % info % levels == 0) go to 5
2453 ! Handle surface corrections, and other end-of-station processing.
2455 CALL da_obs_proc_station(platform, fm)
2457 ! Move the data for this station from PLATFORM to IV.
2459 if (global .and. (platform%loc%i < ids .or. platform%loc%i >= ide)) then
2465 !------------------------------------------------------------------------
2466 ! Duplication explanation:
2468 ! - Assume two reports (1 and 2)
2470 ! - What this does is that if you have N obs available what goes into
2471 ! iv is 1,1,...,N,N.
2473 ! Also note that the ntotal that's put into iv%info%obs_global_index
2474 ! is the "incremented of first pass only" local value, so:
2478 ! index orig ob index iv%info%obs_global_index
2484 ! It's a bit more complicated than that, because of the test on
2485 ! platform%loc%i. This means we're only duplicating obs that are in
2486 ! a particular subset of the domain.
2487 !------------------------------------------------------------------------
2496 if(l.eq.1)ntot = ntot + 1
2498 iv % metar(j) % h = platform % each(1) % height
2499 iv % info(metar) % zk(1,j) = platform % each(1) % zk
2500 iv % metar(j) % u = platform % each(1) % u
2501 iv % metar(j) % v = platform % each(1) % v
2502 iv % metar(j) % t = platform % each(1) % t
2503 iv % metar(j) % p = platform % each(1) % p
2504 iv % metar(j) % q = platform % each(1) % q
2509 if(l.eq.1)ntot = ntot + 1
2511 iv % ships(j) % h = platform % each(1) % height
2512 iv % info(ships) % zk(1,j) = platform % each(1) % zk
2513 iv % ships(j) % u = platform % each(1) % u
2514 iv % ships(j) % v = platform % each(1) % v
2515 iv % ships(j) % t = platform % each(1) % t
2516 iv % ships(j) % p = platform % each(1) % p
2517 iv % ships(j) % q = platform % each(1) % q
2522 if(l.eq.1)ntot = ntot + 1
2525 ! With the datasets that have levels, we have to allocate the memory.
2526 ! Note that this is needed for GEOAMV and AIREP even though the MADIS data
2527 ! will produce a single-level report for each "station" (as contrasted
2528 ! with multiple-level reports for a single satellite or aircraft). For example,
2529 ! if you have 10 aircraft reporting 5 levels of info each, this
2530 ! will produce 50 distinct reports.
2532 allocate (iv % geoamv(j) % u(1:1))
2533 allocate (iv % geoamv(j) % v(1:1))
2534 allocate (iv % geoamv(j) % p(1:1))
2536 iv % info(geoamv) % zk(1,j) = platform % each(1) % zk
2537 iv % geoamv(j) % u(1) = platform % each(1) % u
2538 iv % geoamv(j) % v(1) = platform % each(1) % v
2539 iv % geoamv(j) % p(1) = platform % each(1) % p % inv
2544 if(l.eq.1)ntot = ntot + 1
2547 allocate (iv % airep(j) % h(1:1))
2548 allocate (iv % airep(j) % u(1:1))
2549 allocate (iv % airep(j) % v(1:1))
2550 allocate (iv % airep(j) % t(1:1))
2551 allocate (iv % airep(j) % p(1:1))
2553 iv % airep(j) % h(1) = platform % each(1) % height
2554 iv % info(airep) % zk(1,j) = platform % each(1) % zk
2555 iv % airep(j) % u(1) = platform % each(1) % u
2556 iv % airep(j) % v(1) = platform % each(1) % v
2557 iv % airep(j) % t(1) = platform % each(1) % t
2558 iv % airep(j) % p(1) = platform % each(1) % p % inv
2562 ! If this is a raob sfc level, put it into sonde_sfc and not into sound.
2565 if(l.eq.1)ntot = ntot + 1
2568 m = platform%info%levels
2570 if(sfclev_j /= 0)then
2572 iv%sonde_sfc(j)%h = platform%each(sfclev_j)%height
2573 iv%sonde_sfc(j)%u = platform%each(sfclev_j)%u
2574 iv%sonde_sfc(j)%v = platform%each(sfclev_j)%v
2575 iv%sonde_sfc(j)%t = platform%each(sfclev_j)%t
2576 iv%sonde_sfc(j)%q = platform%each(sfclev_j)%q
2577 iv%sonde_sfc(j)%p = platform%each(sfclev_j)%p
2578 iv%info(sonde_sfc)%zk(1,j) = platform%each(sfclev_j)%zk
2580 platform%info%levels = platform%info%levels - 1
2584 iv % sonde_sfc(j) % h = missing_r
2585 iv % sonde_sfc(j) % u % inv = missing_r
2586 iv % sonde_sfc(j) % u % qc = missing_data
2587 iv % sonde_sfc(j) % u % error = missing_r
2588 iv % sonde_sfc(j) % v = iv % sonde_sfc(j) % u
2589 iv % sonde_sfc(j) % t = iv % sonde_sfc(j) % u
2590 iv % sonde_sfc(j) % p = iv % sonde_sfc(j) % u
2591 iv % sonde_sfc(j) % q = iv % sonde_sfc(j) % u
2595 allocate (iv % sound(j) % h (1:platform % info % levels))
2596 allocate (iv % sound(j) % u (1:platform % info % levels))
2597 allocate (iv % sound(j) % v (1:platform % info % levels))
2598 allocate (iv % sound(j) % t (1:platform % info % levels))
2599 allocate (iv % sound(j) % p (1:platform % info % levels))
2600 allocate (iv % sound(j) % q (1:platform % info % levels))
2604 ! Note: I don't have a testcase that involves the duplication logic,
2605 ! and I'm not sure if the "j-1" logic below will work correctly under
2606 ! those circumstances.
2608 if(sfclev_j.eq.0)then
2609 iv % sound(j) % h(k) = platform % each(k) % height
2610 iv % info(sound) % zk(k,j) = platform % each(k) % zk
2611 iv % sound(j) % u(k) = platform % each(k) % u
2612 iv % sound(j) % v(k) = platform % each(k) % v
2613 iv % sound(j) % t(k) = platform % each(k) % t
2614 iv % sound(j) % p(k) = platform % each(k) % p % inv
2615 iv % sound(j) % q(k) = platform % each(k) % q
2616 else if(k.lt.sfclev_j)then
2617 iv % sound(j) % h(k) = platform % each(k) % height
2618 iv % info(sound) % zk(k,j) = platform % each(k) % zk
2619 iv % sound(j) % u(k) = platform % each(k) % u
2620 iv % sound(j) % v(k) = platform % each(k) % v
2621 iv % sound(j) % t(k) = platform % each(k) % t
2622 iv % sound(j) % p(k) = platform % each(k) % p % inv
2623 iv % sound(j) % q(k) = platform % each(k) % q
2624 else if(k.ne.sfclev_j)then
2625 iv % sound(j) % h(k-1) = platform % each(k) % height
2626 iv % info(sound) % zk(k-1,j) = platform % each(k) % zk
2627 iv % sound(j) % u(k-1) = platform % each(k) % u
2628 iv % sound(j) % v(k-1) = platform % each(k) % v
2629 iv % sound(j) % t(k-1) = platform % each(k) % t
2630 iv % sound(j) % p(k-1) = platform % each(k) % p % inv
2631 iv % sound(j) % q(k-1) = platform % each(k) % q
2639 if(l.eq.1)ntot = ntot + 1
2641 iv % gpspw(j) % tpw = platform % loc % pw
2645 CALL FILL_IV_INFO(obs_index,n,platform,ntot,platform % info % levels,iv)
2647 enddo ! duplication loop
2649 endif ! if(keep(i) == 1)
2651 5 enddo ! station loop
2656 !zx iv%info(obs_index)%plocal(1) = nlocal_out
2657 !zx iv%info(obs_index)%ptotal(1) = ntotal(obs_index)
2658 !zx iv%info(obs_index)%ntotal = ntotal(obs_index)
2659 !zx if(fm == 35)then
2660 !zx iv%info(sonde_sfc)%obs_global_index(obs_index) = ntotal_out
2661 !zx iv%info(sonde_sfc)%plocal(1) = nlocal_out
2662 !zx iv%info(sonde_sfc)%ptotal(1) = ntotal(sonde_sfc)
2663 !zx iv%info(sonde_sfc)%ntotal = ntotal(sonde_sfc)
2664 !zx iv%info(sonde_sfc)%nlocal = nlocal_out
2669 END SUBROUTINE PROCESS_DATASET
2672 SUBROUTINE GET_OB_ERRORS(each)
2674 !------------------------------------------------------------------------------
2675 ! PURPOSE: Fill in the observational errors,
2677 ! METHOD: The method was adapted from the MM5 3DVAR obs preprocessor
2678 ! obs_err_ncep subroutine. The observational error is defined at
2679 ! 1000, 700, 500, 300, 100, 50mb for U, V, T, RH and P. Values at
2680 ! actual obs position are obtained by interpolation between
2681 ! these levels (logarithmic for U and V) and linear for (T and RH).
2682 ! Errors are extrapolated below 1000mb and above 50mb.
2684 ! Also note that the RH error is put into the Q error -- the
2685 ! WRF 3DVAR moisture variable is Q, but the error table is
2686 ! specified in RH. The da_fill_obs_structures routine (called
2687 ! after this on) will take the RH error in the Q slot, and
2688 ! use that in calculating the actual error to be used for Q.
2692 ! Parrish S. and J. Derber 1992: The National Meteorological Centers
2693 ! Spectral Statistical Analysis-Interpolation System.
2694 ! Month. Wea. Rev., 120,1747-1763.
2696 ! HISTORY: 07-22-02 M. Barth Original version.
2698 ! PARENT_MODULE: da_setup_structures
2699 !------------------------------------------------------------------------------
2705 TYPE (each_level_type), INTENT(INOUT) :: each ! Data for this level.
2709 real err_k(6),err_u(6),err_v(6),err_t(6),err_rh(6),err_p(6)
2711 !...NCEP errors (U in m/s, V in m/s, T in k, P in Pa)
2712 !...pressure is obtained from surface value linearly decreasing
2713 !...to 10% of its value at 10hPa
2714 !...RH has been divided by 2
2716 data err_k/100000.,70000.,50000.,30000.,10000.,5000./
2717 data err_u/1.4, 2.4, 2.8, 3.4, 2.5, 2.7/
2718 data err_v/1.4, 2.4, 2.8, 3.4, 2.5, 2.7/
2719 data err_t/1.8, 1.3, 1.3, 2.0, 3.1, 4.0/
2720 data err_rh/10.0, 10.0, 10.0, 10.0, 10.0, 10.0/
2721 data err_p/100.0, 72.7, 54.5, 36.4, 18.2, 13.6/
2723 !------------------------------------------------------------------------------!
2724 ! At this point, I don't think we can have missing P. To stay on the safe side,
2725 ! if P is missing --> set all errors to missing.
2727 if(each % p % inv == missing_r)then
2729 each % u % error = missing_r
2730 each % v % error = missing_r
2731 each % p % error = missing_r
2732 each % t % error = missing_r
2733 each % q % error = missing_r
2737 ! Vertical interpolation of NCEP observational error.
2739 each % u % error = INTPLIN(each%p%inv,err_k,err_u)
2740 each % v % error = INTPLIN(each%p%inv,err_k,err_v)
2741 each % p % error = INTPLIN(each%p%inv,err_k,err_p)
2742 each % t % error = INTPLOG(each%p%inv,err_k,err_t)
2743 each % q % error = INTPLOG(each%p%inv,err_k,err_rh)
2749 END SUBROUTINE GET_OB_ERRORS
2751 FUNCTION INTPLIN (x,xx,yy) RESULT (val)
2752 !------------------------------------------------------------------------------!
2755 real, dimension (:) :: xx, yy
2760 !------------------------------------------------------------------------------!
2768 else if (jl .ge. n) then
2771 val = (xx (jl+1) - x) * yy (jl) + (x - xx (jl)) * yy (jl+1)
2772 val = val / (xx (jl+1) - xx (jl))
2775 END FUNCTION INTPLIN
2777 FUNCTION INTPLOG (x,xx,yy) result (val)
2778 !------------------------------------------------------------------------------!
2781 real, dimension (:) :: xx, yy
2786 !------------------------------------------------------------------------------!
2794 else if (jl .ge. n) then
2797 val = log (xx (jl+1) / x) * yy (jl) + log (x / xx (jl)) * yy (jl+1)
2798 val = val / log (xx (jl+1) / xx (jl))
2801 END FUNCTION INTPLOG
2803 FUNCTION LOCATE (x,xx) result (index)
2804 !------------------------------------------------------------------------------!
2807 real, dimension (:) :: xx
2811 integer :: n,jl,jm,ju
2813 !------------------------------------------------------------------------------!
2815 ascnd = (xx (n) >= xx (1)) ! true if ascending order, false otherwise
2816 jl = 0 ! initialize lower limit
2817 ju = n+1 ! initialize upper limit
2821 if (ju-jl <= 1) exit ! repeat until this condition is satisfied
2823 jm = (ju+jl) / 2. ! compute a mid point
2825 if (ascnd .eqv. (x >= xx (jm))) then
2826 jl = jm ! replace mid point by lower limit
2828 ju = jm ! replace mid point by upper limit
2833 if (x .eq. xx (1)) then ! set the output, being careful with endpoints
2835 else if (x .eq. xx (n)) then
2843 SUBROUTINE FIND_SFC_LEVEL(ista,nlev,nsta,nlevels,levtype,p,slp,lev)
2844 !------------------------------------------------------------------------------!
2849 INTEGER*4, INTENT(IN) :: ista ! Index of current station
2850 INTEGER*4, INTENT(IN) :: nlev ! Number of levels dimension
2851 INTEGER*4, INTENT(IN) :: nsta ! Number of stations dimension
2852 INTEGER*4, INTENT(IN) :: nlevels ! Number of levels for this station
2853 INTEGER*4 :: lev ! Index to sfc level
2854 REAL*4, INTENT(IN) :: levtype(nlev,nsta) ! Level type (1 is sfc)
2855 REAL*4, INTENT(IN) :: p(nlev,nsta) ! Pressure (Pa)
2856 REAL*4, INTENT(OUT) :: slp ! Surface pressure (Pa)
2858 ! Note that lev is not dimensioned with INTENT(IN) due to some picky compilers...
2862 if(levtype(lev,ista).eq.1)then
2873 END SUBROUTINE FIND_SFC_LEVEL
2875 SUBROUTINE FILL_IV_INFO(obs_index,iv_index,platform,ntotal,nlevels,iv)
2877 !------------------------------------------------------------------------------
2878 ! PURPOSE: Fill in the iv%info structures used for each station's reports.
2880 ! METHOD: Take it out of platform and put it into iv%info.
2882 ! HISTORY: 06-05-08 M. Barth Original version.
2886 ! PARENT_MODULE: da_setup_structures
2887 !------------------------------------------------------------------------------
2893 INTEGER*4, INTENT(IN) :: obs_index ! iv%info() index
2894 INTEGER*4, INTENT(IN) :: iv_index ! iv%info()%<item>() index
2895 TYPE (multi_level_type), INTENT(IN) :: platform ! Structure with the data
2896 INTEGER*4, INTENT(IN) :: ntotal ! NTOTAL at this point
2897 INTEGER*4, INTENT(IN) :: nlevels ! Num levels for the station
2898 TYPE (iv_type), INTENT(INOUT) :: iv ! Innovation vector
2900 iv%info(obs_index)%name(iv_index) = platform%info%name
2901 iv%info(obs_index)%platform(iv_index) = platform%info%platform
2902 iv%info(obs_index)%id(iv_index) = platform%info%id
2903 iv%info(obs_index)%date_char(iv_index) = platform%info%date_char
2905 iv%info(obs_index)%levels(iv_index) = nlevels
2906 iv%info(obs_index)%lat(:,iv_index) = platform%info%lat
2907 iv%info(obs_index)%lon(:,iv_index) = platform%info%lon
2908 iv%info(obs_index)%elv(iv_index) = platform%info%elv
2909 iv%info(obs_index)%pstar(iv_index) = platform%info%pstar
2911 iv%info(obs_index)%slp(iv_index) = platform%loc%slp
2912 iv%info(obs_index)%pw(iv_index) = platform%loc%pw
2913 iv%info(obs_index)%x(:,iv_index) = platform%loc%x
2914 iv%info(obs_index)%y(:,iv_index) = platform%loc%y
2915 iv%info(obs_index)%i(:,iv_index) = platform%loc%i
2916 iv%info(obs_index)%j(:,iv_index) = platform%loc%j
2917 iv%info(obs_index)%dx(:,iv_index) = platform%loc%dx
2918 iv%info(obs_index)%dxm(:,iv_index) = platform%loc%dxm
2919 iv%info(obs_index)%dy(:,iv_index) = platform%loc%dy
2920 iv%info(obs_index)%dym(:,iv_index) = platform%loc%dym
2921 iv%info(obs_index)%proc_domain(:,iv_index) = platform%loc%proc_domain
2923 iv%info(obs_index)%obs_global_index(iv_index) = ntotal
2926 ! special case for sonde_sfc, duplicate sound info
2928 if (obs_index == sound) then
2930 iv%info(sonde_sfc)%name(iv_index) = platform%info%name
2931 iv%info(sonde_sfc)%platform(iv_index) = platform%info%platform
2932 iv%info(sonde_sfc)%id(iv_index) = platform%info%id
2933 iv%info(sonde_sfc)%date_char(iv_index) = platform%info%date_char
2934 iv%info(sonde_sfc)%levels(iv_index) = 1
2935 iv%info(sonde_sfc)%lat(:,iv_index) = platform%info%lat
2936 iv%info(sonde_sfc)%lon(:,iv_index) = platform%info%lon
2937 iv%info(sonde_sfc)%elv(iv_index) = platform%info%elv
2938 iv%info(sonde_sfc)%pstar(iv_index) = platform%info%pstar
2940 iv%info(sonde_sfc)%slp(iv_index) = platform%loc%slp
2941 iv%info(sonde_sfc)%pw(iv_index) = platform%loc%pw
2942 iv%info(sonde_sfc)%x(:,iv_index) = platform%loc%x
2943 iv%info(sonde_sfc)%y(:,iv_index) = platform%loc%y
2944 iv%info(sonde_sfc)%i(:,iv_index) = platform%loc%i
2945 iv%info(sonde_sfc)%j(:,iv_index) = platform%loc%j
2946 iv%info(sonde_sfc)%dx(:,iv_index) = platform%loc%dx
2947 iv%info(sonde_sfc)%dxm(:,iv_index) = platform%loc%dxm
2948 iv%info(sonde_sfc)%dy(:,iv_index) = platform%loc%dy
2949 iv%info(sonde_sfc)%dym(:,iv_index) = platform%loc%dym
2950 iv%info(sonde_sfc)%proc_domain(:,iv_index) = platform%loc%proc_domain
2952 iv%info(sonde_sfc)%obs_global_index(iv_index) = ntotal
2958 END SUBROUTINE FILL_IV_INFO