1program midas_prepcma
2 !
3 !:Purpose: Read the observation files (usually after output by the background check)
4 ! and apply further quality control and thinning for use by the ``LETKF`` program
5 !
6 ! ---
7 !
8 !:Algorithm: After reading the observation files that have been processed by the background check,
9 ! the ``prepcma`` program rejects more observations based on the
10 ! various flags and conditions. It also performs further thinnings
11 ! on the data types of aircraft (AI), scatterometer (SC),
12 ! satellite winds (SW) and some radiance (TO). The rejection and thinning
13 ! are controlled by the options in the namelist of ``NAMPREPCMA``.
14 !
15 ! ---
16 !
17 !:File I/O: The required input files and produced output files are listed as follows.
18 !
19 ! --
20 !
21 !============================================== ==============================================================
22 ! Input and Output Files Description of file
23 !============================================== ==============================================================
24 ! ``flnml`` In - Main namelist file with parameters user may modify
25 ! ``flnml_static`` In - The "static" namelist that should not be modified
26 ! ``obserr`` In - Observation error statistics
27 ! ``obsfiles_$FAM/obs$FAM_$NNNN_$NNNN`` In - Observation file for each "family"
28 ! ``stats_tovs`` In - Satellite radiance observation errors
29 ! ``rtcoef_$PLATFORM_$SENSOR.dat`` In - RTTOV coefficient files
30 ! ``obsfiles_$FAM.updated/obs$FAM_$NNNN_$NNNN`` Out - final observation file for each family
31 !============================================== ==============================================================
32 !
33 ! ---
34 !
35 !:Synopsis: Below is a summary of the ``prepcma`` program calling sequence:
36 !
37 ! - **Initial setups:**
38 !
39 ! - Read the NAMPREPCMA namelist and check/modify some values.
40 !
41 ! - ``filt_setup``: set up list of elements to be assimilated and flags for rejection
42 !
43 ! - ``obsf_setup``: get observation file names and datestamp
44 !
45 ! - **Computation:**
46 !
47 ! - ``obsf_readFiles``: get the observations
48 !
49 ! - ``filt_suprep``: select the elements to assimilate and apply rejection flags
50 !
51 ! - ``oer_setObsErrors``: initialize obs error covariances and set flag
52 !
53 ! - ``oti_setup``: reject any observations outside the data assimilation window
54 !
55 ! - ``enkf_rejectHighLatIR``: reject all IR radiance observation in arctic and antarctic
56 !
57 ! - ``enkf_modifyAmsubObsError``: modify the obs error stddev for AMSUB in the tropics
58 !
59 ! - ``thinning_fam``: perform thinning for aircraft (AI), scatterometer (SC),
60 ! satellite winds (SW) and some radiance (TO)
61 !
62 ! - **Final steps:**
63 !
64 ! - ``obsf_writeFiles``: write to burp/sqlite files
65 !
66 ! - ``obsf_printFiles``: print to ascci file and to unformatted files
67 !
68 ! ---
69 !
70 !:Options: `List of namelist blocks <../namelists_in_each_program.html#prepcma>`_
71 ! that can affect the ``prepcma`` program.
72 !
73 ! * Some of the relevant namelist blocks used to configure the
74 ! prepcma are listed in the following table:
75 !
76 ! --
77 !
78 !=================== ====================== ===========================================
79 ! Program/Module Namelist Description of what is controlled
80 !=================== ====================== ===========================================
81 ! ``midas_prepcma`` ``NAMPREPCMA`` parameters for CMA format and others
82 ! to modify, reject and thinning some
83 ! observation data
84 ! ``timeCoord_mod`` ``NAMTIME`` assimilation time window length, temporal
85 ! resolution of the background state and the
86 ! analysis
87 ! ``tovs_nl_mod`` ``NAMTOV`` The list of satellite and instrument
88 !=================== ====================== ===========================================
89 !
90 !
91 use version_mod
92 use obsSpaceData_mod
93 use obsFiles_mod
94 use obsFilter_mod
95 use obsTimeInterp_mod
96 use obsErrors_mod
97 use tovsNL_mod
98 use timeCoord_mod
99 use enkf_mod
100 use utilities_mod
101 use midasMpi_mod
102 use ramDisk_mod
103 use regions_mod
104 use burpRead_mod
105
106 implicit none
107
108 integer :: fnom, fclos, nulnam, ierr, dateStampFromObs
109 type(struct_obs), target :: obsSpaceData
110 type(struct_oti), pointer :: oti => null()
111 real(kind=8) :: hx_dummy(1,1)
112 integer :: ncmahdr, ncmahx, ncmabdy, ncmadim, nobsout, nbrpform
113 logical :: qcvar, numHeader, numBody
114 character(len=7) :: resumeType
115
116 ! number of pressure ranges used for the thinning of aircraft (and other) data:
117 integer, parameter :: npres_ai = 5
118 integer, parameter :: npres_sw = 2
119 integer, parameter :: nai_target = 10
120 integer, parameter :: nsc_target = 10
121 integer, parameter :: nsw_target = 6
122 integer, parameter :: nto_target = 6
123 real(8) :: nai_pmax(npres_ai) = (/ 25000.0, 40000.0, 60000.0, 80000.0, 110000.0/)
124 real(8) :: nsw_pmax(npres_sw) = (/ 60000.0, 110000.0/)
125 ! For a scalar array, no layer selection will be done
126 real(8) :: nsc_pmax(1) = (/ 0.0 /)
127 real(8) :: nto_pmax(1) = (/ 0.0 /)
128
129 ! Namelist variables:
130 character(len=256) :: cmahdr ! should not be used anymore
131 character(len=256) :: cmabdy ! should not be used anymore
132 character(len=256) :: cmadim ! should not be used anymore
133 character(len=256) :: obsout ! file name for ascii output
134 character(len=256) :: brpform ! should not be used anymore
135 logical :: suprep ! choose to execute 'suprep' obs filtering
136 logical :: rejectOutsideTimeWindow ! choose to reject obs outside time window
137 logical :: thinning ! choose to apply 'extra' thinning of some obs types
138 logical :: applySatUtil ! choose to reject satellite obs based on 'util' column of stats_tovs
139 logical :: modifyAmsubObsError ! choose to modify the obs error stddev for AMSUB/MHS in the tropics
140 logical :: rejectHighLatIR ! choose to reject IR data in high latitudes
141 logical :: obsClean ! choose to remove rejected observations from files
142 logical :: writeObsFiles ! choose to update the (burp or sqlite) observation files
143 logical :: writeAsciiCmaFiles ! choose to write ascii output
144
145 NAMELIST /NAMPREPCMA/ cmahdr, cmabdy, cmadim, obsout, brpform, &
146 suprep, rejectOutsideTimeWindow, thinning, &
147 applySatUtil, modifyAmsubObsError, rejectHighLatIR, &
148 obsClean, writeObsFiles, writeAsciiCmaFiles
149
150 call ver_printNameAndVersion('prepcma','Prepare observations for LETKF')
151
152 !- 1.0 mpi
153 call mmpi_initialize
154
155 !- 1.1 timings
156 call tmg_init(mmpi_myid, 'TMG_INFO')
157 call utl_tmg_start(0,'Main')
158
159 if ( mmpi_myid == 0 ) call utl_writeStatus('PREPCMA_BEG')
160
161 !- Specify default values for namelist variables
162 cmahdr = 'NOT_DEFINED'
163 cmabdy = 'NOT_DEFINED'
164 cmadim = 'NOT_DEFINED'
165 obsout = 'NOT_DEFINED'
166 brpform = 'brpform'
167 suprep = .true.
168 rejectOutsideTimeWindow = .true.
169 thinning = .true.
170 applySatUtil = .true.
171 modifyAmsubObsError = .true.
172 rejectHighLatIR = .true.
173 obsClean = .true.
174 writeObsFiles = .false.
175 writeAsciiCmaFiles = .false.
176
177 nulnam = 0
178 ierr = fnom(nulnam,'./flnml','FTN+SEQ+R/O',0)
179 read(nulnam,nml=namprepcma,iostat=ierr)
180 if (ierr /= 0) call utl_abort('midas-prepcma: Error reading namelist')
181 if (mmpi_myid == 0) write(*,nml=namprepcma)
182 ierr = fclos(nulnam)
183
184 !- RAM disk usage
185 call ram_setup
186
187 call utl_tmg_start(10,'--Observations')
188
189 !- Set up list of elements to be assimilated and flags for rejection (from namelist)
190 call filt_setup('prepcma')
191
192 !- Observation file names and get datestamp
193 call obsf_setup(dateStampFromObs, 'prepcma')
194
195 !- Allocate obsSpaceData
196 call obs_class_initialize('ENKFMIDAS')
197 call obs_initialize( obsSpaceData, mpi_local_opt=obsf_filesSplit() )
198
199 !- Read observations
200 call utl_tmg_start(11,'----ReadObsFiles')
201 call obsf_readFiles( obsSpaceData )
202 call utl_tmg_stop(11)
203
204 numHeader = obs_numheader(obsSpaceData)
205 numBody = obs_numbody(obsSpaceData)
206 write(*,*) 'midas-prepcma: obs_numheader =', numheader
207 write(*,*) 'midas-prepcma: obs_numbody =', numbody
208
209 !- Determine if qcvar flag is expected to be present
210 resumeType = brpr_getTypeResume()
211 write(*,*) 'midas_prepcma: RESUME type =', resumeType
212 qcvar = (resumeType == 'POSTALT')
213 if (qcvar) then
214 write(*,*) 'midas_prepcma: The input file is a postalt file'
215 else
216 write(*,*) 'midas_prepcma: The input file is NOT a postalt file'
217 end if
218
219 !- Initialize TOVS processing
220 if (obs_famExist(obsSpaceData,'TO')) call tvs_setup
221
222 !- Select the elements to assimilate and apply rejection flags
223 if (suprep) call filt_suprep(obsSpaceData)
224
225 !- Allocation for TOVS
226 if (obs_famExist(obsSpaceData,'TO')) call tvs_setupAlloc(obsSpaceData)
227
228 !- Initialize obs error covariances and set flag using 'util' column of stats_tovs
229 call oer_setObsErrors(obsSpaceData, 'analysis', useTovsUtil_opt=applySatUtil) ! IN
230
231 !- Call suprep again to 'black list' channels according to 'util' column of stats_tovs
232 if (applySatUtil) call filt_suprep(obsSpaceData)
233
234 call utl_tmg_stop(10)
235
236 !- Setup timeCoord module and set dateStamp from env variable
237 call tim_setup()
238 if (tim_getDateStamp() == 0) then
239 if (dateStampFromObs > 0) then
240 ! use dateStamp from obs if not already set by env variable
241 call tim_setDateStamp(dateStampFromObs)
242 else
243 call utl_abort('midas-prepcma: DateStamp was not set')
244 end if
245 end if
246
247 !- Reject any observation outside the data assimilation window
248 if (rejectOutsideTimeWindow) then
249 call oti_setup( oti, obsSpaceData, numStep=1, &
250 headerIndexBeg=1, headerIndexEnd=obs_numheader(obsSpaceData), &
251 flagObsOutside_opt=.true. )
252 end if
253
254 !- Reject all IR radiance observation in arctic and antarctic (.i.e |lat|>60. )
255 if (rejectHighLatIR) call enkf_rejectHighLatIR(obsSpaceData)
256
257 !- Modify the obs error stddev for AMSUB in the tropics
258 if (modifyAmsubObsError) call enkf_modifyAmsubObsError(obsSpaceData)
259
260 !- Perform thinning for several observation types
261 if (thinning) then
262 ! perform thinning for aircraft observations
263 call thinning_fam(obsSpaceData, nai_pmax, nai_target, 'AI')
264 ! perform thinning for scatterometer observations
265 call thinning_fam(obsSpaceData, nsc_pmax, nsc_target, 'SC')
266 ! perform thinning for radiance observations
267 call thinning_fam(obsSpaceData, nto_pmax, nto_target, 'TO')
268 ! perform thinning for satwind observations
269 call thinning_fam(obsSpaceData, nsw_pmax, nsw_target, 'SW')
270 end if
271
272 !- Write the results
273 write(*,*)
274 write(*,*) '> midas-prepcma: writing to files'
275
276 !- Write to burp/sqlite files if requested
277 if (writeObsFiles) then
278 call obsf_writeFiles(obsSpaceData)
279 if ( obsClean ) call obsf_cleanObsFiles()
280 end if
281
282 if (writeAsciiCmaFiles) then
283
284 !- Remove all observations from obsSpaceData that will not be assimilated
285 !- But, unlike the EnKF program, do not check value of OBS_ZHA
286 if (obsClean) then
287 call obs_clean(obsSpaceData, hx_dummy, 0, -1, qcvar, checkZha_opt=.false.)
288 end if
289
290 if (mmpi_nprocs > 1) then
291 call obs_expandToMpiGlobal(obsSpaceData)
292 end if
293
294 if (mmpi_myid == 0) then
295 !- Open file for ascii output
296 nobsout = 0
297 ierr = fnom(nobsout, obsout, 'FMT+SEQ+R/W', 0)
298 call obs_print(obsSpaceData,nobsout)
299 close(nobsout)
300
301 !- Write the results in CMA format
302 ncmahdr = 0
303 ierr = fnom(ncmahdr, cmahdr, 'FTN+SEQ+UNF+R/W', 0)
304 ncmabdy = 0
305 ierr = fnom(ncmabdy, cmabdy, 'FTN+SEQ+UNF+R/W', 0)
306 ncmadim = 0
307 ierr = fnom(ncmadim, cmadim, 'FTN+SEQ+R/W', 0)
308 ncmahx = -1
309 call obs_write(obsSpaceData, hx_dummy, 0, ncmahdr, ncmabdy, ncmahx, ncmadim)
310 close(ncmahdr)
311 close(ncmabdy)
312 close(ncmadim)
313
314 !! This used to contain a .true. or .false. value indicating if observations passed the QCVar
315 !! Since, this is not the case, we can write .false.
316 nbrpform = 0
317 ierr = fnom(nbrpform, brpform, 'FTN+SEQ+R/W', 0)
318 write(nbrpform,*) .false.
319 close(nbrpform)
320
321 end if
322
323 end if
324
325 !
326 !- 3. Ending
327 !
328 write(*,*)
329 write(*,*) '> midas-prepcma: Ending'
330 call obs_finalize(obsSpaceData) ! deallocate obsSpaceData
331
332 call utl_tmg_stop(0)
333 call tmg_terminate(mmpi_myid, 'TMG_INFO')
334
335 call rpn_comm_finalize(ierr)
336
337 if ( mmpi_myid == 0 ) then
338 call utl_writeStatus('PREPCMA_END')
339 end if
340
341contains
342
343 subroutine thinning_fam(obsSpaceData, n_pmax, n_target, cfam)
344 !
345 ! :Purpose: thin the observations of the selected family
346 !
347 implicit none
348
349 ! Arguments:
350 type (struct_obs), intent(inout) :: obsSpaceData ! the data in observation space
351 real(8), intent(in) :: n_pmax(:) ! pressure levels that separate vertical layers for the thinning
352 integer, intent(in) :: n_target ! maximum desired amount of data per 3-D box
353 character(len=2), intent(in) :: cfam ! family type
354
355 ! Locals:
356 type(struct_reg) :: lsc
357 integer :: idist, n_count_thin, iai, iseed(4)
358 integer :: nobs_count, nobs_count_mpiGlobal, nobs_count_thin, nobs_count_thin_mpiGlobal
359 integer :: nrep_count, nrep_count_mpiGlobal, nrep_count_thin, nrep_count_thin_mpiGlobal
360 integer :: headerIndex, bodyIndex, bodyIndexBeg, bodyIndexEnd
361 integer :: iblock, codeType, ilat, incr, ipres, nblocksum, npres, nsize, num_stn
362 logical :: count_obs, allRejected
363 real(4) :: lat_r4, lon_r4
364 real(8) :: pressure, rannum
365 real(8), allocatable :: latcenter(:), latmin(:), latmax(:), ranvals(:)
366 integer, allocatable :: nblockoffset(:), nlonblock(:)
367 integer, allocatable :: ai_indices(:,:), nstation(:,:), nstationMpiGlobal(:,:)
368 real(8), allocatable :: keep_ai(:,:)
369
370 ! box size that is used for observation thinning
371 ! (the numerator is an approximate distance in km)
372 real(8), parameter :: r0_count_km = 200.0/(2**0.5)
373 ! next two parameters are not used in this program
374 real(8), parameter :: r1_dum = 1.0
375 real(8), parameter :: rz_dum = 1.0
376
377 num_stn = obs_numheader(obsSpaceData)
378 npres = size(n_pmax,1)
379 write(*,*) 'Start thinning for ', cfam, ' data'
380 ! at this stage we still have many radiance channels
381 ! that will be rejected at a later stage.
382 if (cfam == 'XX') then
383 ! never getting here
384 write(*,*) 'count individual observations'
385 count_obs = .true.
386 else
387 write(*,*) 'count the number of reports'
388 count_obs = .false.
389 end if
390
391 call reg_init_struct(lsc, r0_count_km, r1_dum, rz_dum)
392 if (mmpi_myid == 0) write(*,*) 'number of latitude bands: ', lsc%nlatband
393 nsize = lsc%nlatband
394 allocate(latmin(nsize))
395 allocate(latmax(nsize))
396 allocate(latcenter(nsize))
397 allocate(nlonblock(nsize))
398 allocate(nblockoffset(nsize))
399
400 call reg_getlatitude(lsc%r0_rad, lsc%nlatband, latmin, latcenter, latmax)
401 if (mmpi_myid == 0) write(*,*) 'number of latitude bands: ',lsc%nlatband
402 do ilat = 1, lsc%nlatband
403 if (mmpi_myid == 0) write(*,*) ' band: ', ilat, ' latitude between ', latmin(ilat), latmax(ilat)
404 end do
405 call reg_getblock(lsc%nlatband, lsc%r0_rad, latmin, latmax, nlonblock)
406 nblocksum = 0
407 do ilat = 1, lsc%nlatband
408 nblockoffset(ilat) = nblocksum
409 nblocksum = nblocksum + nlonblock(ilat)
410 if (mmpi_myid == 0) write(*,*) 'latband: ', ilat, ' no of blocks: ', nlonblock(ilat)
411 end do
412 if (mmpi_myid == 0) write(*,*) 'total number of blocks: ', nblocksum
413
414 nrep_count = 0
415 nobs_count = 0
416
417 allocate(nstation(nblocksum, npres))
418 allocate(keep_ai(nblocksum, npres))
419
420 nstation=0
421 ! keep_ai = 1 corresponds to no thinning
422 keep_ai(:,:) = 1.0
423
424 allocate(ai_indices(num_stn,3))
425
426 header_loop: do headerIndex = 1, num_stn
427 codeType= obs_headElem_i(obsSpaceData, obs_ity, headerIndex)
428 if ( (cfam=='AI' .and. (codeType==42 .or. codeType==128 .or. &
429 codeType==157 .or. codeType==177)) .or. &
430 (cfam=='SC' .and. codeType==254) .or. &
431 (cfam=='SW' .and. (codeType==88 .or. codeType==188)) .or. &
432 (cfam=='TO' .and. tvs_isIdBurpTovs(codeType)) ) then
433
434 ! skip this header if all observations already rejected
435 bodyIndexBeg = obs_headElem_i(obsSpaceData, obs_rln, headerIndex)
436 bodyIndexEnd = obs_headElem_i(obsSpaceData, obs_nlv, headerIndex) + bodyIndexBeg - 1
437 allRejected = .true.
438 body_loop: do bodyIndex = bodyIndexBeg, bodyIndexEnd
439 if (obs_bodyElem_i(obsSpaceData, obs_ass, bodyIndex) == obs_assimilated) then
440 allRejected = .false.
441 exit body_loop
442 end if
443 end do body_loop
444 if (allRejected) cycle header_loop
445
446 lat_r4 = obs_headElem_r(obsSpaceData, obs_lat, headerIndex)
447 lon_r4 = obs_headElem_r(obsSpaceData, obs_lon, headerIndex)
448 call reg_locatestn(lsc%r0_rad, lat_r4, lon_r4, &
449 lsc%nlatband, nlonblock, &
450 nblockoffset, iblock)
451 ! note that all data from the aircraft are at the same pressure
452 if (npres == 1) then
453 ipres = 1
454 else
455 pressure= obs_bodyElem_r(obsSpaceData, obs_ppp, bodyIndexBeg)
456 ipres = 1
457 do
458 if ((n_pmax(ipres) > pressure) .or. (ipres > npres)) exit
459 ipres = ipres + 1
460 end do
461 end if
462 if (ipres <= npres) then
463 if (count_obs) then
464 incr = obs_headElem_i(obsSpaceData, obs_nlv, headerIndex)
465 else
466 incr = 1
467 end if
468 nstation(iblock,ipres) = nstation(iblock,ipres) + incr
469 nobs_count = nobs_count + obs_headElem_i(obsSpaceData, obs_nlv, headerIndex)
470 nrep_count = nrep_count + 1
471 ai_indices(nrep_count, 1) = headerIndex
472 ai_indices(nrep_count, 2) = iblock
473 ai_indices(nrep_count, 3) = ipres
474 end if
475 end if
476 end do header_loop
477
478 ! do mpi communication of the accumulators
479 nsize = nblocksum * npres
480 allocate(nstationMpiGlobal(nblocksum, npres))
481 call rpn_comm_allreduce(nstation, nstationMpiGlobal, nsize, &
482 'mpi_integer','mpi_sum', 'GRID', ierr)
483 call rpn_comm_allreduce(nrep_count, nrep_count_mpiGlobal, 1, &
484 'mpi_integer','mpi_sum', 'GRID', ierr)
485 call rpn_comm_allreduce(nobs_count, nobs_count_mpiGlobal, 1, &
486 'mpi_integer','mpi_sum', 'GRID', ierr)
487
488 write(*,*) 'total number of ', cfam, ' reports (local and mpiglobal): ', &
489 nrep_count, nrep_count_mpiGlobal
490 allocate(ranvals(nrep_count))
491 write(*,*) 'total number of ', cfam, ' observations (local and mpiglobal): ', &
492 nobs_count, nobs_count_mpiGlobal
493
494 n_count_thin = 0
495 do iblock = 1, nblocksum
496 do ipres = 1, npres
497 if (nstationMpiGlobal(iblock,ipres) .ge. 1) then
498 if (mmpi_myid == 0) write(*,*) 'block ipres and count: ',iblock,ipres, &
499 nstationMpiGlobal(iblock,ipres)
500 if (nstationMpiGlobal(iblock,ipres) > n_target) then
501 keep_ai(iblock,ipres) = dble(n_target) / dble(nstationMpiGlobal(iblock,ipres))
502 n_count_thin = n_count_thin + n_target
503 else
504 n_count_thin = n_count_thin + nstationMpiGlobal(iblock,ipres)
505 end if
506 end if
507 end do
508 end do
509
510 if (count_obs) then
511 write(*,*) 'Estimated remaining number of ', cfam, ' observations (mpiGlobal): ', n_count_thin
512 else
513 write(*,*) 'Estimated remaining number of ', cfam, ' reports (mpiGlobal): ', n_count_thin
514 end if
515
516 nrep_count_thin = 0
517 nobs_count_thin = 0
518
519 idist = 1
520 iseed(1) = 1
521 iseed(2) = 5
522 iseed(3) = 9
523 iseed(4) = 11
524 call dlarnv(idist,iseed,nrep_count,ranvals)
525 do iai = 1, nrep_count
526 headerIndex = ai_indices(iai,1)
527 iblock = ai_indices(iai,2)
528 ipres = ai_indices(iai,3)
529 rannum = ranvals(iai)
530 if (rannum <= keep_ai(iblock,ipres)) then
531 nrep_count_thin = nrep_count_thin + 1
532 nobs_count_thin = nobs_count_thin + obs_headElem_i(obsSpaceData, obs_nlv, headerIndex)
533 else
534 ! reject the profile
535 bodyIndexBeg = obs_headElem_i(obsSpaceData, obs_rln, headerIndex)
536 bodyIndexEnd = obs_headElem_i(obsSpaceData, obs_nlv, headerIndex) + bodyIndexBeg - 1
537 do bodyIndex = bodyIndexBeg, bodyIndexEnd
538 call obs_bodySet_i(obsSpaceData, obs_ass, bodyIndex, obs_notAssimilated)
539 ! also set the 'rejected by selection process' flag (bit 11)
540 call obs_bodySet_i( obsSpaceData, obs_flg, bodyIndex, &
541 ibset( obs_bodyElem_i( obsSpaceData, obs_flg, bodyIndex ), 11) )
542 end do
543 end if
544 end do
545
546 ! mpi communication of accumulators
547 call rpn_comm_allreduce(nrep_count_thin, nrep_count_thin_mpiGlobal, 1, &
548 'mpi_integer','mpi_sum', 'GRID', ierr)
549 call rpn_comm_allreduce(nobs_count_thin, nobs_count_thin_mpiGlobal, 1, &
550 'mpi_integer','mpi_sum', 'GRID', ierr)
551
552 write(*,*) 'True remaining number of ', cfam, ' reports (local, mpiGlobal): ', &
553 nrep_count_thin, nrep_count_thin_mpiGlobal
554 write(*,*) 'True remaining number of ', cfam, ' observations (local, mpiGlobal): ', &
555 nobs_count_thin, nobs_count_thin_mpiGlobal
556
557 deallocate(ranvals)
558 deallocate(latmin)
559 deallocate(latmax)
560 deallocate(latcenter)
561 deallocate(nlonblock)
562 deallocate(nblockoffset)
563 deallocate(nstation)
564 deallocate(nstationMpiGlobal)
565 deallocate(keep_ai)
566 deallocate(ai_indices)
567
568 end subroutine thinning_fam
569
570end program