1program midas_obsImpact
2 !
3 !:Purpose: Main program for computing the Forecast Sensitivity to Observation Impact (FSOI)
4 !
5 ! ---
6 !
7 !:Algorithm: FSOI partitions the forecast error reduction within the current system from
8 ! assimilating the observations. The total forecast error reduction defined as:
9 !
10 ! :math:`(e_{t}^{fa})^{T}*C*(e_{t}^{fa})-(e_{t}^{fb})^{T}*C*(e_{t}^{fb})`
11 !
12 ! where :math:`e_{t}^{fa}=M(x_{0}^{a})-x_{t}^{a}`
13 !
14 ! and :math:`e_{t}^{fb}=M(x_{0}^{b})-x_{t}^{a}`
15 !
16 ! and C is the energy norm.
17 !
18 ! --
19 !
20 ! In this program, there are the hybrid FSOI approach (HFSOI) and the ensemble FSOI (EFSOI) approaches.
21 ! The hybrid approach is appropriate for computing the impact of observations assimilated with 4D-EnVar.
22 ! It combines the ensemble approach for propagating the sensitivities from forecast to analysis time and
23 ! the variational approach for the adjoint of the assimilation procedure. The ensemble approach is
24 ! appropriate for computing the impact of observations assimilated with the LETKF. It relies purely on
25 ! analysis and forecast ensemble for the calculation.
26 !
27 !
28 ! More details on HFSOI can be found in the paper: `HFSOI approach <https://doi.org/10.1175/MWR-D-17-0252.1>`_
29 !
30 !
31 ! More details on EFSOI can be found in the paper:`EFSOI approach <http://doi.org/10.3402/tellusa.v65i0.20038>`_
32 !
33 ! --
34 !
35 !:File I/O: The required input files and produced output files are listed as follows.
36 !
37 ! --
38 !
39 !============================================== ====================================================================
40 ! Input and Output Files Description of file
41 !============================================== ====================================================================
42 ! ``flnml`` In - Main namelist file with parameters user may modify
43 ! ``trlm_$NN`` (e.g. ``trlm_01``) In - Background state (a.k.a. trial) files for each timestep
44 ! ``analysisgrid`` In - File defining grid for computing the analysis increment
45 ! ``bgcov`` In - Static (i.e. NMC) B matrix file for NWP fields
46 ! ``ensemble/$YYYYMMDDHH_006_$NNNN`` In - Ensemble member files defining ensemble B matrix
47 ! ``ensemble/$YYYYMMDDHH_foradv`` In - advection files
48 ! ``obsfiles_$FAM/obs$FAM_$NNNN_$NNNN`` In - Observation file for each "family" and MPI task
49 ! ``obserr`` In - Observation error statistics
50 ! ``forecasts/forecast_*`` In - Global deterministic forecast from backgroud and analysis
51 ! ``forecasts/analysis`` In - Verifying analysis
52 ! ``diafiles_$FAM.updated/obs$FAM_$NNNN_$NNNN`` Out - Updated obs file for each "family" and MPI task in SQLite
53 ! Remainder are files related to radiance obs:
54 ! ``stats_$SENSOR_assim`` In - Satellite radiance observation errors of difference sensors
55 ! ``stats_tovs`` In - Satellite radiance observation errors
56 ! ``rtcoef_$PLATFORM_$SENSOR.**`` In - RTTOV coefficient files
57 ! ``rttov_h2o_limits.dat`` In - Min/Max humidity limits
58 ! ``stats_tovs_symmetricObsErr`` In - user-defined symmetric TOVS errors for all sky
59 ! ``Cmat_$PLATFORM_$SENSOR.dat`` In - Inter-channel observation-error correlations
60 !============================================== ====================================================================
61 !
62 ! --
63 !
64 !:Synopsis: Below is a summary of the ``obsImpact`` program calling sequence:
65 !
66 ! - **Initial setups:**
67 !
68 ! - Initialize FSOI module, read the namelist from ``fso_setup``
69 !
70 ! - Setup horizontal and vertical grid objects for "analysis
71 ! grid" from ``analysisgrid`` file and for "trial grid" from
72 ! first trial file: ``trlm_01``.
73 !
74 ! - Setup ``obsSpaceData`` object and read observations from
75 ! files: ``inn_setupObs``.
76 !
77 ! - Setup ``columnData`` and ``gridStateVector`` modules (read
78 ! list of analysis variables from namelist) and allocate column
79 ! object for storing trial on analysis levels.
80 !
81 ! - Setup the observation error statistics in ``obsSpaceData``
82 ! object: ``oer_setObsErrors``.
83 !
84 ! - Allocate a stateVector object on the trial grid and then
85 ! read the trials: ``gio_readTrials``.
86 !
87 ! - Setup the B matrices: ``bmat_setup``.
88 !
89 ! - Setup the ``gridVariableTransforms``.
90 !
91 ! - **Computation:**
92 !
93 ! - ``incdatr``: Setup dateStamp(one extra timestamp: leadTime) for FSOI.
94 !
95 ! - ``inn_computeInnovation``: Compute innovation
96 !
97 ! - ``calcFcstError``: Read the forcasts from background and analysis, and
98 ! the verifying analysis as well, calculate the forecast
99 ! error norm defined as:
100 ! :math:`(C*(e_{t}^{fa}+e_{t}^{fb}))`.
101 !
102 ! - ``bmat_sqrtBT``: Compute the variable :math:`\hat{v}` for minimization in HFSO mode.
103 ! :math:`\hat{v}=B_{t}^{T/2}*C*(e_{t}^{fa}+e_{t}^{fb})`
104 !
105 ! - ``minimize``: Do the minimization to apply the adjoint of the 4D-EnVar assimilation
106 ! to :math:`\hat{v}` with the result being :math:`\hat{a}`.
107 !
108 ! - ``bmat_sqrt``: Compute :math:`B^{1/2}*\hat{a}` .
109 !
110 ! - ``s2c_tl``, ``oop_Htl``: Apply the observation operators :math:`H*B^{1/2}*\hat{a}` .
111 !
112 ! - ``rmat_RsqrtInverseAllObs``: Multiply by the inverse of the observation error variances
113 ! :math:`R^{-1}*H*B^{1/2}*\hat{a}`
114 !
115 ! - ``obs_bodySet_r``: Multiply the resulting sensitivity value by the innovation and put
116 ! the result in the ``obsSpaceDate`` column ``OBS_FSO`` so it can be stored in
117 ! the observation files
118 !
119 ! - ``sumFSO``: Print out the FSOI value, including total and the one from each obs family.
120 !
121 ! - **Final steps:**
122 !
123 ! - ``obsf_writeFiles``: Write the final FSOI value in SQLite file.
124 !
125 ! --
126 !
127 !:Options: `List of namelist blocks <../namelists_in_each_program.html#obsimpact>`_
128 ! that can affect the ``obsImpact`` program.
129 !
130 ! * The use of ``obsImpact`` program is controlled mainly by the namelist block
131 ! ``&NAMFSO`` read by the ``fso_mod`` module.
132 !
133 ! * Some of the other relevant namelist blocks used to configure FSOI
134 ! are listed in the following table:
135 !
136 !
137 !========================= ====================== =============================================================
138 ! Module Namelist Description of what is controlled
139 !========================= ====================== =============================================================
140 ! ``timeCoord_mod`` ``NAMTIME`` assimilation time window length, temporal resolution of
141 ! the background state and increment
142 ! ``bMatrixEnsemble_mod`` ``NAMBEN`` weight and other parameters for ensemble-based B matrix
143 ! component
144 !========================= ====================== =============================================================
145 !
146 !
147 use version_mod
148 use codePrecision_mod
149 use ramDisk_mod
150 use utilities_mod
151 use midasMpi_mod
152 use mathPhysConstants_mod
153 use horizontalCoord_mod
154 use verticalCoord_mod
155 use timeCoord_mod
156 use columnData_mod
157 use obsSpaceData_mod
158 use gridStateVector_mod
159 use gridStateVectorFileIO_mod
160 use bMatrix_mod
161 use innovation_mod
162 use obsFiles_mod
163 use obsErrors_mod
164 use gridVariableTransforms_mod
165 use fsoi_mod
166
167 implicit none
168
169 integer :: istamp,exdb,exfin,ierr, dateStampFromObs
170
171 type(struct_obs), target :: obsSpaceData
172 type(struct_columnData),target :: columnTrlOnAnlIncLev
173 type(struct_columnData),target :: columnTrlOnTrlLev
174 type(struct_gsv) :: stateVectorTrialHighRes
175
176 character(len=48) :: obsMpiStrategy
177 character(len=3) :: obsColumnMode
178
179 type(struct_vco), pointer :: vco_anl => null()
180 type(struct_hco), pointer :: hco_anl => null()
181 type(struct_hco), pointer :: hco_trl => null()
182 type(struct_vco), pointer :: vco_trl => null()
183 type(struct_hco), pointer :: hco_core => null()
184 integer,external :: get_max_rss
185 logical :: allocHeightSfc
186
187 istamp = exdb('OBSIMPACT','DEBUT','NON')
188
189 call ver_printNameAndVersion('obsImpact','Calculation of observation impact')
190
191 ! MPI initilization
192 call mmpi_initialize
193
194 call tmg_init(mmpi_myid, 'TMG_INFO')
195
196 call utl_tmg_start(0,'Main')
197
198 if (mmpi_myid == 0) then
199 call utl_writeStatus('VAR3D_BEG')
200 end if
201
202 call ram_setup
203
204 !
205 !- 1. Settings
206 !
207 obsColumnMode = 'VAR'
208 obsMpiStrategy = 'LIKESPLITFILES'
209
210 !
211 !- Initialize the Temporal grid and set dateStamp from env variable
212 !
213 call tim_setup()
214 !
215 !- Initialize burp file names and set datestamp if not already
216 !
217 call obsf_setup(dateStampFromObs, 'FSO')
218 if (tim_getDateStamp() == 0) then
219 if (dateStampFromObs > 0) then
220 call tim_setDatestamp(dateStampFromObs)
221 else
222 call utl_abort('obsImpact: DateStamp was not set')
223 end if
224 end if
225 !
226 !- Initialize constants
227 !
228 if ( mmpi_myid == 0 ) then
229 call mpc_printConstants(6)
230 call pre_printPrecisions
231 end if
232
233 !
234 !- Initialize variables of the model states
235 !
236 call gsv_setup
237 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
238 !
239 !- Initialize the Analysis grid
240 !
241 if (mmpi_myid.eq.0) write(*,*)''
242 if (mmpi_myid.eq.0) write(*,*)'obsImpact: Set hco parameters for analysis grid'
243 call hco_SetupFromFile(hco_anl, './analysisgrid', 'ANALYSIS', 'Analysis' ) ! IN
244
245 !- Do FSO module set up
246 call fso_setup(hco_anl)
247
248 if ( hco_anl % global ) then
249 hco_core => hco_anl
250 else
251 !- Iniatilized the core (Non-Exteded) analysis grid
252 call hco_SetupFromFile( hco_core, './analysisgrid', 'COREGRID', 'AnalysisCore' ) ! IN
253 end if
254
255 !
256 !- Initialisation of the analysis grid vertical coordinate from analysisgrid file !
257 call vco_SetupFromFile( vco_anl, & ! OUT
258 './analysisgrid') ! IN
259
260 call col_setVco(columnTrlOnAnlIncLev,vco_anl)
261 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
262
263 !
264 !- Setup and read observations
265 !
266 call inn_setupObs(obsSpaceData, hco_anl, obsColumnMode, obsMpiStrategy, 'FSO') ! IN
267 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
268
269 !
270 !- Basic setup of columnData module
271 !
272 call col_setup
273 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
274
275 !
276 !- Memory allocation for background column data
277 !
278 call col_allocate(columnTrlOnAnlIncLev,obs_numheader(obsSpaceData),mpiLocal_opt=.true.)
279
280 !
281 !- Initialize the observation error covariances
282 !
283 call oer_setObsErrors(obsSpaceData, 'FSO') ! IN
284 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
285
286 ! Reading trials
287 call inn_getHcoVcoFromTrlmFile( hco_trl, vco_trl )
288 allocHeightSfc = ( vco_trl%Vcode /= 0 )
289
290 call gsv_allocate( stateVectorTrialHighRes, tim_nstepobs, hco_trl, vco_trl, &
291 dateStamp_opt=tim_getDateStamp(), mpi_local_opt=.true., &
292 mpi_distribution_opt='Tiles', dataKind_opt=4, &
293 allocHeightSfc_opt=allocHeightSfc, hInterpolateDegree_opt='LINEAR', &
294 beSilent_opt=.false. )
295 call gsv_zero( stateVectorTrialHighRes )
296 call gio_readTrials( stateVectorTrialHighRes )
297 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
298
299 ! Horizontally interpolate trials to trial columns
300 call inn_setupColumnsOnTrlLev( columnTrlOnTrlLev, obsSpaceData, hco_core, &
301 stateVectorTrialHighRes )
302 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
303
304 !
305 !- Initialize the background-error covariance, also sets up control vector module (cvm)
306 !
307 call bmat_setup(hco_anl,hco_core,vco_anl)
308 write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
309
310 !
311 ! - Initialize the gridded variable transform module
312 !
313 call gvt_setup(hco_anl,hco_core,vco_anl)
314 call gvt_setupRefFromTrialFiles('HU')
315 call gvt_setupRefFromTrialFiles('height')
316
317 !
318 !- 2. Do the actual job
319 !
320
321 ! Interpolate trial columns to analysis levels and setup for linearized H
322 call inn_setupColumnsOnAnlIncLev(columnTrlOnTrlLev,columnTrlOnAnlIncLev)
323
324 ! Compute observation innovations and prepare obsSpaceData for minimization
325 call inn_computeInnovation(columnTrlOnTrlLev,obsSpaceData)
326
327 ! Perform forecast sensitivity to observation calculation using ensemble approach
328 call fso_ensemble(columnTrlOnAnlIncLev,obsSpaceData)
329
330 ! Deallocate memory related to B matrices
331 call bmat_finalize()
332
333 ! Now write out the observation data files
334 if ( .not. obsf_filesSplit() ) then
335 write(*,*) 'We read/write global observation files'
336 call obs_expandToMpiGlobal(obsSpaceData)
337 if (mmpi_myid == 0) call obsf_writeFiles(obsSpaceData)
338 else
339 ! redistribute obs data to how it was just after reading the files
340 call obs_MpiRedistribute(obsSpaceData,OBS_IPF)
341 call obsf_writeFiles(obsSpaceData)
342 end if
343
344 ! Deallocate copied obsSpaceData
345 call obs_finalize(obsSpaceData)
346
347 !
348 !- 3. Job termination
349 !
350 istamp = exfin('OBSIMPACT','FIN','NON')
351
352 if (mmpi_myid == 0) then
353 call utl_writeStatus('VAR3D_END')
354 endif
355
356 call utl_tmg_stop(0)
357
358 call tmg_terminate(mmpi_myid, 'TMG_INFO')
359
360 call rpn_comm_finalize(ierr)
361
362end program midas_obsImpact