12 SUBROUTINE THIN_OB (max_number_of_obs, obs, number_of_obs, mix, mjx, &
13 missing_r, Ob_name, Ob_fm, Delta_P)
15 ! --------------------------------------------------------------------------
16 ! Purpose: To thin the sateliite (SATOB, SSMI Retrieval and Tb) data.
17 ! Method : To select only ONE data nearest to the center of the (I,J,K)
18 ! grid-box if there are more than one OBS within that gridbox.
20 ! The vertical P_thickness is defined by Delta_P.
21 ! Currently for SATOB the maximum of 100 level in vertical
22 ! and maximum of 20 data points within a grid box are allowed.
23 ! For the single level SSMI the maximum of 400 data points
24 ! within a gridbox is allowed.
26 ! Yong-Run Guo 05/01/2001
27 ! --------------------------------------------------------------------------
32 INTEGER, INTENT (in) :: max_number_of_obs
33 TYPE (report), DIMENSION (max_number_of_obs), INTENT (inout) :: obs
34 INTEGER, INTENT (in) :: number_of_obs
35 CHARACTER (LEN = *), INTENT (in) :: Ob_name
36 INTEGER, INTENT (in) :: Ob_fm
37 REAL, INTENT (in) :: missing_r
38 REAL , OPTIONAL, INTENT (in) :: Delta_P
40 INTEGER :: n, fm, i, j, k, kk, num_box, &
41 max_num, mix, mjx, num, nn, total, &
42 max_box, LV, N_selected, N1_selected
43 INTEGER, ALLOCATABLE :: Num_ob(:,:,:), Ob_index(:,:,:,:)
44 REAL :: X, Y, dx, dy, RR, Rmin, R1min
45 TYPE ( meas_data ) :: new
48 !------------------------------------------------------------------
50 ! 1.0 Allocate the working arrays
52 ! The default size: LV, max_box can be changed to meet the needs.
63 else if (Ob_fm == 125 .or. Ob_fm == 126 .or. Ob_fm == 281) then
68 WRITE(0,'(A,I3,A)') ' FM=',Ob_fm,' NOT SATELLITE OBS,', &
69 ' NO THINING APPLIED TO IT.'
73 allocate (Num_ob (mix,mjx,LV))
74 allocate (Ob_index(mix,mjx,LV,max_box))
76 WRITE(0,'(/"Thining OBS ==> ",A,1X,"FM=",I3,2X, &
77 & "mix, mjx, LV, max_box:",4I6)') &
78 & Ob_name, Ob_fm, mix, mjx, LV, max_box
80 ! 2.0 To count the number of OBS within the grid boxes
81 ! ------------------------------------------------
86 ! 2.1 Loop over stations
90 DO n = 1, number_of_obs
93 IF (obs (n)%info%discard ) THEN
99 READ (obs (n) % info % platform (4:6), '(I3)') fm
101 if (fm /= Ob_fm) CYCLE stations
103 nvalids_fm = nvalids_fm + 1
107 ! 2.2 count the number of SATOB within the grid box for thining
111 new = obs (n) % surface % meas
113 if (eps_equal (new%pressure%data, missing_r, 1.)) then
117 ! 2.2.1 Calculate the model horizonatl coordinates: I, J, and the
120 if (fg_format == 'MM5') then
121 call LLXY (obs (n) % location % latitude, &
122 obs (n) % location % longitude, X, Y)
123 else if (fg_format == 'WRF') then
124 call latlon_to_ij(map_info, obs(n)%location%latitude, &
125 obs (n)%location%longitude, X, Y)
131 K = INT(new % pressure % data / Delta_p)
133 ! 2.2.2 Grid-box counter
135 Num_ob (i,j,k) = Num_ob (i,j,k) + 1
137 ! 2.2.3 Keep the OBS indices for each of the grid-box
139 Ob_index(i,j,k, Num_ob(i,j,k)) = n
143 ! 2.3 count the number of SSMI within the grid box for thining
148 ! 2.3.1 Calculate the model horizonatl coordinates: I, J
150 if (fg_format == 'MM5') then
151 call LLXY (obs (n) % location % latitude, &
152 obs (n) % location % longitude, X, Y)
153 else if (fg_format == 'WRF') then
154 call latlon_to_ij(map_info, obs(n)%location%latitude, &
155 obs (n)%location%longitude, X, Y)
162 ! 2.3.2 Grid-box counter
164 Num_ob (i,j,k) = Num_ob (i,j,k) + 1
166 ! 2.3.3 Keep the OBS indices for each of the grid-box
168 Ob_index(i,j,k, Num_ob(i,j,k)) = n
170 ! 2.4 count the number of QSCAT within the grid box for thining
174 ! 2.4.1 Calculate the model horizonatl coordinates: I, J
176 if (fg_format == 'MM5') then
177 call LLXY (obs (n) % location % latitude, &
178 obs (n) % location % longitude, X, Y)
179 else if (fg_format == 'WRF') then
180 call latlon_to_ij(map_info, obs(n)%location%latitude, &
181 obs (n)%location%longitude, X, Y)
188 ! 2.4.2 Grid-box counter
190 Num_ob (i,j,k) = Num_ob (i,j,k) + 1
192 ! 2.4.3 Keep the OBS indices for each of the grid-box
194 Ob_index(i,j,k, Num_ob(i,j,k)) = n
200 ! Should never come here
207 ! 2.5 Print the total number of boxes and columns data available
208 ! ----------------------------------------------------------
210 WRITE(0,'("VALID NO.=",I6)') nvalids_fm
212 ! 2.5.1 Print the total number of boxes data available
220 IF (Num_ob (i,j,k) > 0) THEN
221 max_num = max(max_num, Num_ob (i,j,k))
223 num_box = num_box + 1
228 WRITE(0,'(A,I5,A,I5,A,I3)') "LEVEL ", K, " NUM=", KK, " Max=", max_num
231 write(0,'(10X,"Total Number of Boxes ",I6)') num_box
233 ! 2.5.2 Print the total number of columes data available
240 KK = KK + Num_ob (i,j,k)
242 if (kk > 0) num_box = num_box + 1
245 write(0,'(10X,"Number of columns =", I5)') num_box
247 ! 3.0 Select the ONE data within one grid box
248 ! ---------------------------------------
254 NEXT_box:DO J = 1,MJX
260 if (num <= 1) cycle NEXT_box
262 ! 3.1 The data nearest to the center of grid box (I,J) is selected
267 Select_ob:do nn = 1,num
268 n = Ob_index(i,j,k,nn)
272 ! 3.1.1 Select one SATOB within a grid-box
276 new = obs (n) % surface % meas
277 if (new % pressure % qc == 0 .and. &
278 new % speed % qc == 0 .and. &
279 new % direction % qc == 0) then
280 if (fg_format == 'MM5') then
281 call LLXY (obs (n) % location % latitude, &
282 obs (n) % location % longitude, X, Y)
283 else if (fg_format == 'WRF') then
284 call latlon_to_ij(map_info, obs(n)%location%latitude, &
285 obs (n)%location%longitude, X, Y)
301 ! 3.1.2 Select one good SSMI Retrieval Speed and one PW within a grid-box
302 ! This may be in same obs(n): N_selected = N1_selected = n
305 if (fg_format == 'MM5') then
306 call LLXY (obs (n) % location % latitude, &
307 obs (n) % location % longitude, X, Y)
308 else if (fg_format == 'WRF') then
309 call latlon_to_ij(map_info, obs(n)%location%latitude, &
310 obs (n)%location%longitude, X, Y)
322 IF (ASSOCIATED (obs (n) % surface)) then
323 new = obs (n) % surface % meas
324 if (new % speed % qc == 0) then
332 if (obs(n)%ground% pw % qc == 0) then
339 ! 3.1.3 Select one good SSMI Tb within a grid-box
340 ! Only keep the data when the data for all channels are good
344 if (obs (n) % ground % tb19v % qc == 0 .and. &
345 obs (n) % ground % tb19h % qc == 0 .and. &
346 obs (n) % ground % tb22v % qc == 0 .and. &
347 obs (n) % ground % tb37v % qc == 0 .and. &
348 obs (n) % ground % tb37h % qc == 0 .and. &
349 obs (n) % ground % tb85v % qc == 0 .and. &
350 obs (n) % ground % tb85h % qc == 0) then
351 if (fg_format == 'MM5') then
352 call LLXY (obs (n) % location % latitude, &
353 obs (n) % location % longitude, X, Y)
354 else if (fg_format == 'WRF') then
355 call latlon_to_ij(map_info, obs(n)%location%latitude, &
356 obs (n)%location%longitude, X, Y)
372 ! 3.1.2 Select one good QUIKSCAT within a grid-box
375 if (fg_format == 'MM5') then
376 call LLXY (obs (n) % location % latitude, &
377 obs (n) % location % longitude, X, Y)
378 else if (fg_format == 'WRF') then
379 call latlon_to_ij(map_info, obs(n)%location%latitude, &
380 obs (n)%location%longitude, X, Y)
391 ! if the speed is OK, keep this report.
393 IF (ASSOCIATED (obs (n) % surface)) then
394 new = obs (n) % surface % meas
395 if (new % speed % qc == 0) then
407 ! Should never come here
413 ! 3.2 Discard the unselected data
415 Discard:do nn = 1,num
416 n = Ob_index(i,j,k,nn)
420 ! 3.2.1 Thining SATOB data by setting discard = .TRUE.
424 if (n /= N_selected) obs(n) % info % discard = .TRUE.
426 ! 3.2.3 Thining SSMI Retrieval data by setting discard = .TRUE.
430 if (n /= N_selected .and. &
431 n /= N1_selected) obs(n) % info % discard = .TRUE.
434 ! 3.2.4 Thining SSMI Tb data by setting discard = .TRUE.
438 if (n /= N_selected) obs(n) % info % discard = .TRUE.
440 ! 3.2.5 Thining QUIKSCAT data by setting discard = .TRUE.
444 if (n /= N_selected) obs(n) % info % discard = .TRUE.
450 ! Should never come here
462 ! 4.0 deallocate the working arrays
465 deallocate (Ob_index)
467 END SUBROUTINE THIN_OB
469 END MODULE module_thin_ob