1program midas_diagHBHt
2 !
3 !:Purpose: Main program for computing a single random realization of
4 ! background error in observation space, stored in ``obs_hbht``. This
5 ! can then be used by python or other scripts to compute the
6 ! background error variance (consistent with the specified B matrix)
7 ! in observation space for comparison with the innovation variance
8 ! and observation error variance.
9 !
10 ! --
11 !
12 !:Algorithm: The random realization of background error in observation space
13 ! is computed following these steps:
14 !
15 ! 1. Compute random values for the control vector with each element
16 ! drawn from independent Gaussian distribution with variance of one
17 ! and bias of zero.
18 !
19 ! 2. Multiply random vector by sqrt of B matrix.
20 !
21 ! 3. Apply observation operator to obtain random perturbation in
22 ! observation space.
23 !
24 ! --
25 !
26 !:File I/O: The required input files and produced output files can vary
27 ! according to the application. Below are tables of files for
28 ! typical NWP 4D-EnVar (e.g. GDPS) and sea ice or SST 3D-Var
29 ! applications.
30 !
31 ! --
32 !
33 !============================================== ==============================================================
34 ! Input and Output Files (for NWP application) Description of file
35 !============================================== ==============================================================
36 ! ``flnml`` In - Main namelist file with parameters user may modify
37 ! ``flnml_static`` In - The "static" namelist that should not be modified
38 ! ``trlm_$NN`` (e.g. ``trlm_01``) In - Background state (a.k.a. trial) files for each timestep
39 ! ``analysisgrid`` In - File defining grid for computing the random gridded perturbation
40 ! ``bgcov`` In - Static (i.e. NMC) B matrix file for NWP fields
41 ! ``bgchemcov`` In - Static B matrix file for chemistry fields
42 ! ``ensemble/$YYYYMMDDHH_006_$NNNN`` In - Ensemble member files defining ensemble B matrix
43 ! ``obsfiles_$FAM/obs$FAM_$NNNN_$NNNN`` In - Observation file for each "family" and MPI task
44 ! ``obserr`` In - Observation error statistics
45 ! ``obsinfo_chm`` In - Something needed for chemistry assimilation?
46 ! ``obsfiles_$FAM.updated/obs$FAM_$NNNN_$NNNN`` Out - Updated obs file for each "family" and MPI task
47 ! Remainder are files related to radiance obs:
48 ! ``stats_$SENSOR_assim`` In - Satellite radiance observation errors of different sensors
49 ! ``stats_tovs`` In - Satellite radiance observation errors
50 ! ``stats_tovs_symmetricObsErr`` In - User-defined symmetric TOVS errors for all sky
51 ! ``ceres_global.std`` In - High-res surface type and water fraction for radiance obs
52 ! ``rtcoef_$PLATFORM_$SENSOR.dat`` In - RTTOV coefficient files
53 ! ``ozoneclim98`` In - Ozone climatology
54 !============================================== ==============================================================
55 !
56 ! --
57 !
58 !:Synopsis: Below is a summary of the ``diagHBHt`` program calling sequence:
59 !
60 ! - **Initial setups:**
61 !
62 ! - Setup horizontal and vertical grid objects for "analysis
63 ! grid" from ``analysisgrid`` file and for "trial grid" from
64 ! first trial file: ``trlm_01``.
65 !
66 ! - Setup ``obsSpaceData`` object and read observations from
67 ! files: ``inn_setupObs``.
68 !
69 ! - Setup ``columnData`` and ``gridStateVector`` modules (read
70 ! list of analysis variables from namelist) and allocate column
71 ! object for storing trial on analysis levels.
72 !
73 ! - Setup the observation error statistics in ``obsSpaceData``
74 ! object: ``oer_setObsErrors``.
75 !
76 ! - Allocate a stateVector object on the trial grid and then
77 ! read the trials: ``gio_readTrials``.
78 !
79 ! - Setup the B matrices: ``bmat_setup``.
80 !
81 ! - Setup the ``gridVariableTransforms``.
82 !
83 ! - **Calculation**
84 !
85 ! - Compute ``columnTrlOnTrlLev`` and ``columnTrlOnAnlIncLev``
86 ! from trials: ``inn_setupColumnsOnTrlLev``,
87 ! ``inn_setupColumnsOnAnlIncLev``
88 !
89 ! - Compute innovation from updated state:
90 ! ``inn_computeInnovation``.
91 !
92 ! - Compute an MPI global random vector, then extract only
93 ! portion needed for this MPI task (to reduce sensitivity of
94 ! results to MPI topology).
95 !
96 ! - Multiply random vector by sqrt of B matrix with resulting
97 ! gridded state random perturbation in ``statevector``.
98 !
99 ! - Apply linearized observation operators to the random gridded
100 ! state: ``s2c_tl`` and ``oop_Htl`` with final result in
101 ! observation space: ``obs_work`` column of ``obsSpaceData``.
102 !
103 ! - Copy result from ``obs_work`` to ``obs_hbht`` column.
104 !
105 ! - **Final steps**, after the outer loop:
106 !
107 ! - Various final steps, including: update the observation files
108 ! (``obsf_writeFiles``).
109 !
110 ! --
111 !
112 !:Options: `List of namelist blocks <../namelists_in_each_program.html#diaghbht>`_
113 ! that can affect the ``diagHBHt`` program.
114 !
115 ! * The choice of what B matrix is used for the calculation is
116 ! controlled for each individual B matrix component through it's
117 ! own namelist block. The weights for all B matrix components are
118 ! zero be default and can be set to a nonzero value through the
119 ! namelist variable ``SCALEFACTOR`` in the namelist block for each
120 ! corresponding fortran module.
121 !
122 ! * All other namelist blocks related to observations are relevant
123 ! for the diagHBHt calculation, including ``NAMFILT`` and
124 ! ``NAMTOV``.
125 !
126 ! * Some of the other relevant namelist blocks used to configure the
127 ! diagHBHt calculation are listed in the following table:
128 !
129 !======================== ============ ==============================================================
130 ! Module Namelist Description of what is controlled
131 !======================== ============ ==============================================================
132 ! ``timeCoord_mod`` ``NAMTIME`` assimilation time window length, temporal resolution of
133 ! the background state and increment (i.e. perturbation)
134 ! ``bMatrixEnsemble_mod`` ``NAMBEN`` weight and other parameters for ensemble-based B matrix
135 ! component
136 ! ``bMatrixHI_mod`` ``NAMBHI`` weight and other parameters for the climatological B matrix
137 ! component based on homogeneous-isotropic covariances
138 ! represented in spectral space
139 ! Other B matrix modules various weight and other parameters for each type of B matrix
140 !======================== ============ ==============================================================
141 !
142 use version_mod
143 use codePrecision_mod
144 use ramDisk_mod
145 use utilities_mod
146 use midasMpi_mod
147 use MathPhysConstants_mod
148 use horizontalCoord_mod
149 use verticalCoord_mod
150 use timeCoord_mod
151 use obsSpaceData_mod
152 use columnData_mod
153 use gridStateVector_mod
154 use gridStateVectorFileIO_mod
155 use controlVector_mod
156 use obsFiles_mod
157 use randomNumber_mod
158 use obsTimeInterp_mod
159 use stateToColumn_mod
160 use innovation_mod
161 use bMatrix_mod
162 use obsErrors_mod
163 use gridVariableTransforms_mod
164 use obsOperators_mod
165 implicit none
166
167 integer :: istamp,exdb,exfin
168 integer :: ierr
169
170 type(struct_obs), target :: obsSpaceData
171 type(struct_columnData), target :: columnTrlOnAnlIncLev
172 type(struct_columnData), target :: columnTrlOnTrlLev
173 type(struct_gsv) :: stateVectorTrialHighRes
174 type(struct_hco), pointer :: hco_trl => null()
175 type(struct_vco), pointer :: vco_trl => null()
176
177 logical :: allocHeightSfc
178
179 character(len=48) :: obsMpiStrategy, varMode
180
181 type(struct_hco), pointer :: hco_anl => null()
182 type(struct_hco), pointer :: hco_core => null()
183
184 istamp = exdb('diagHBHt','DEBUT','NON')
185
186 call ver_printNameAndVersion('diagHBHt','RANDOMIZED DIAGNOSTIC of HBHt')
187
188 ! MPI initilization
189 call mmpi_initialize
190
191 call tmg_init(mmpi_myid, 'TMG_INFO')
192
193 call utl_tmg_start(0,'Main')
194
195 varMode='analysis'
196
197 call ram_setup
198
199 ! Do initial set up
200
201 obsMpiStrategy = 'LIKESPLITFILES'
202
203 call var_setup('VAR') ! obsColumnMode
204
205 ! Reading trials
206 call inn_getHcoVcoFromTrlmFile( hco_trl, vco_trl )
207 allocHeightSfc = ( vco_trl%Vcode /= 0 )
208
209 call gsv_allocate( stateVectorTrialHighRes, tim_nstepobs, hco_trl, vco_trl, &
210 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
211 mpi_distribution_opt='Tiles', dataKind_opt=4, &
212 allocHeightSfc_opt=allocHeightSfc, hInterpolateDegree_opt='LINEAR', &
213 beSilent_opt=.false. )
214 call gsv_zero( stateVectorTrialHighRes )
215 call gio_readTrials( stateVectorTrialHighRes )
216
217 ! Horizontally interpolate trials to trial columns
218 call inn_setupColumnsOnTrlLev( columnTrlOnTrlLev, obsSpaceData, hco_core, &
219 stateVectorTrialHighRes )
220
221 ! Interpolate trial columns to analysis levels and setup for linearized H
222 call inn_setupColumnsOnAnlIncLev(columnTrlOnTrlLev,columnTrlOnAnlIncLev)
223
224 ! Compute observation innovations and prepare obsSpaceData for minimization
225 call inn_computeInnovation(columnTrlOnTrlLev,obsSpaceData)
226
227 ! Compute perturbed
228 call diagHBHt(columnTrlOnAnlIncLev,obsSpaceData)
229
230 ! Deallocate memory related to B matrices
231 call bmat_finalize()
232
233 ! Now write out the observation data files
234 if ( .not. obsf_filesSplit() ) then
235 write(*,*) 'We read/write global observation files'
236 call obs_expandToMpiGlobal(obsSpaceData)
237 if (mmpi_myid == 0) call obsf_writeFiles(obsSpaceData)
238 else
239 ! redistribute obs data to how it was just after reading the files
240 call obs_MpiRedistribute(obsSpaceData,OBS_IPF)
241 call obsf_writeFiles(obsSpaceData)
242 end if
243
244
245 ! Deallocate copied obsSpaceData
246 call obs_finalize(obsSpaceData)
247
248 ! 3. Job termination
249
250 istamp = exfin('diagHBHt','FIN','NON')
251
252 call utl_tmg_stop(0)
253
254 call tmg_terminate(mmpi_myid, 'TMG_INFO')
255
256 call rpn_comm_finalize(ierr)
257
258contains
259
260 !--------------------------------------------------------------------------
261 ! var_setup
262 !--------------------------------------------------------------------------
263 subroutine var_setup(obsColumnMode)
264 !
265 !:Purpose: Control of the preprocessing of the variational assimilation
266 !
267 implicit none
268
269 ! Arguments:
270 character (len=*), intent(in) :: obsColumnMode
271
272 ! Locals:
273 integer :: dateStampFromObs
274 type(struct_vco),pointer :: vco_anl => null()
275 integer :: get_max_rss
276
277 write(*,*)
278 write(*,*) '-----------------------------------'
279 write(*,*) '-- Starting subroutine var_setup --'
280 write(*,*) '-----------------------------------'
281
282 !
283 !- Initialize the Temporal grid and set dateStamp from env variable
284 !
285 call tim_setup()
286
287 !
288 !- Initialize burp file names and set datestamp if not already
289 !
290 call obsf_setup(dateStampFromObs, 'analysis')
291 if (tim_getDateStamp() == 0) then
292 if (dateStampFromObs > 0) then
293 call tim_setDatestamp(dateStampFromObs)
294 else
295 call utl_abort('var_setup: dateStamp was not set')
296 end if
297 end if
298
299 !
300 !- Initialize constants
301 !
302 if ( mmpi_myid == 0 ) then
303 call mpc_printConstants(6)
304 call pre_printPrecisions
305 end if
306
307 !
308 !- Initialize variables of the model states
309 !
310 call gsv_setup
311 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
312
313 !
314 !- Initialize the Analysis grid
315 !
316 if(mmpi_myid.eq.0) write(*,*)''
317 if(mmpi_myid.eq.0) write(*,*)' preproc: Set hco parameters for analysis grid'
318 call hco_SetupFromFile(hco_anl, './analysisgrid', 'ANALYSIS', 'Analysis' ) ! IN
319
320 if ( hco_anl % global ) then
321 hco_core => hco_anl
322 else
323 !- Iniatilized the core (Non-Exteded) analysis grid
324 call hco_SetupFromFile( hco_core, './analysisgrid', 'COREGRID', 'AnalysisCore' ) ! IN
325 end if
326
327 !
328 !- Initialisation of the analysis grid vertical coordinate from analysisgrid file
329 !
330 call vco_SetupFromFile( vco_anl, & ! OUT
331 './analysisgrid') ! IN
332
333 call col_setVco(columnTrlOnAnlIncLev,vco_anl)
334 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
335
336 !
337 !- Setup and read observations
338 !
339 call inn_setupObs(obsSpaceData, hco_anl, obsColumnMode, obsMpiStrategy, varMode) ! IN
340 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
341
342 !
343 !- Basic setup of columnData module
344 !
345 call col_setup
346 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
347
348 !
349 !- Memory allocation for background column data
350 !
351 call col_allocate(columnTrlOnAnlIncLev,obs_numheader(obsSpaceData),mpiLocal_opt=.true.)
352
353 !
354 !- Initialize the observation error covariances
355 !
356 call oer_setObsErrors(obsSpaceData, varMode) ! IN
357 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
358
359 !
360 !- Initialize the background-error covariance, also sets up control vector module (cvm)
361 !
362 call bmat_setup(hco_anl,hco_core,vco_anl)
363 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
364
365 !
366 ! - Initialize the gridded variable transform module
367 !
368
369 call gvt_setup(hco_anl,hco_core,vco_anl)
370 call gvt_setupRefFromTrialFiles('HU')
371 call gvt_setupRefFromTrialFiles('height')
372
373 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
374
375 end subroutine var_setup
376
377 !--------------------------------------------------------------------------
378 ! diagHBHt
379 !--------------------------------------------------------------------------
380 subroutine diagHBHt(columnTrlOnAnlIncLev, obsSpaceData)
381 !
382 !:Purpose: Main calculations of HBHt
383 !
384 implicit none
385
386 ! Arguments:
387 type(struct_obs), intent(inout) :: obsSpaceData ! Observation-related data
388 type(struct_columnData), intent(inout) :: columnTrlOnAnlIncLev ! Background columns interpolated to anl levels and obs horiz locations
389
390 ! Locals:
391 type(struct_columnData) :: columnAnlInc
392 type(struct_gsv) :: statevector
393 type(struct_vco), pointer :: vco_anl
394 real(8) ,allocatable :: random_vector(:)
395 real(8) ,allocatable :: local_random_vector(:)
396 integer :: index_body, local_dimension, jj, ierr, dateprnt, timeprnt, nrandseed, istat
397 integer ,external :: newdate, get_max_rss
398 real(8) ,external :: gasdev
399
400 !
401 !- 1. Initialization
402
403 write(*,*)
404 write(*,*) 'Computing perturbations for randomized HBHT evaluation START'
405
406 vco_anl => col_getVco(columnTrlOnAnlIncLev)
407 !- 1.3 Create a gridstatevector to store the perturbations
408 call gsv_allocate(statevector,tim_nstepobsinc,hco_anl,vco_anl, &
409 dataKind_opt=pre_incrReal,mpi_local_opt=.true.)
410
411 !- 1.4 Create column vectors to store the perturbation interpolated to obs horizontal locations
412 call col_setVco(columnAnlInc,vco_anl)
413 call col_allocate(columnAnlInc,col_getNumCol(columnTrlOnAnlIncLev),mpiLocal_opt=.true.)
414
415 !- 1.6
416 call oti_timeBinning(obsSpaceData,tim_nstepobsinc)
417
418 !
419 !- 2. Compute the perturbations
420 !
421
422 !- 2.1 Random perturbations
423 write(*,*)
424 write(*,*) 'Generating random perturbation:'
425
426 !- Global vector (same for each processors)
427 allocate(random_vector(cvm_nvadim_mpiglobal),stat =istat )
428 allocate(local_random_vector(cvm_nvadim),stat =istat )
429
430 !- Initialize random number generator
431 ierr = newdate(tim_getDatestamp(), dateprnt, timeprnt, -3)
432 nrandseed=100*dateprnt + int(timeprnt/100.0)
433 write(*,*) 'diagHBHt: Random seed set to ',nrandseed
434 call rng_setup(nrandseed)
435 ! Generate a random vector from N(0,1)
436 do jj = 1, cvm_nvadim_mpiglobal
437 random_vector(jj) = rng_gaussian()
438 enddo
439 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
440 !- Extract only the subvector for this processor
441 call bmat_reduceToMPILocal(local_random_vector, & ! OUT
442 random_vector) ! IN
443 local_dimension = size(local_random_vector)
444 !- Transform to control variables in physical space
445 call bmat_sqrtB(local_random_vector,local_dimension,statevector)
446 !- 2.2 Interpolation to the observation horizontal locations
447
448 call s2c_tl( statevector, & ! IN
449 columnAnlInc, & ! OUT (H_horiz EnsPert)
450 columnTrlOnAnlIncLev, obsSpaceData ) ! IN
451 !- 2.3 Interpolation to observation space
452 call oop_Htl(columnAnlInc,columnTrlOnAnlIncLev,obsSpaceData,min_nsim=1)
453
454 !- Copy from OBS_WORK to OBS_HPHT
455
456 do index_body = 1, obs_numBody(obsSpaceData)
457 call obs_bodySet_r(obsSpaceData,OBS_HPHT,index_body, &
458 obs_bodyElem_r(obsSpaceData,OBS_WORK,index_body) )
459 end do
460 !
461 !- 3. Ending/Deallocation
462 !
463 deallocate(random_vector, stat=istat)
464 deallocate(local_random_vector, stat=istat)
465 call col_deallocate(columnAnlInc)
466 call gsv_deallocate(statevector)
467 write(*,*)
468 write(*,*) 'Computing perturbations for randomized HBHT evaluation END'
469
470 end subroutine diagHBHt
471
472end program midas_diagHBHt