midas_ensPostProcess sourceΒΆ

  1program midas_ensPostProcess
  2  !
  3  !:Purpose: Post-processing program for the local ensemble transform Kalman filter (LETKF).
  4  !          Many aspects of this program are controlled throught the namelist block
  5  !          namEnsPostProc defined in epp_postProcess.
  6  !
  7  !          ---
  8  !
  9  !:Algorithm: The ``ensPostProcess`` program performs several post-processing tasks of
 10  !            LETK ensemble analyses and the ensemble trials. The following tasks are
 11  !            performed based on the namelist options.
 12  !
 13  !              - **Mean and std**: Ensemble mean and standard deviation are computed
 14  !                upon reading the ensemble members and after the processes which may
 15  !                alter the mean or the standard deviation.
 16  !
 17  !              - **RTPP**: Relaxation to the prior perturbation will relax the analysis
 18  !                perturbation to the trial perturbation with a given amount (:math:`\alpha`) in the namelist.
 19  !                It can be formulated as:
 20  !                :math:`x^a_i \leftarrow \overline{x^a} + (1-\alpha)(\overline{x^a}-x^a_i)+\alpha(\overline{x^b}-x^b_i)`
 21  !
 22  !                More details for the RTPP can be found in paper:
 23  !                `Impacts of Initial Estimate and Observation Availability on Convective-Scale
 24  !                Data Assimilation with an Ensemble Kalman Filter
 25  !                <https://journals.ametsoc.org/view/journals/mwre/132/5/1520-0493_2004_132_1238_ioieao_2.0.co_2.xml>`_
 26  !
 27  !              - **RTPS**: Relaxation to the prior spread will relax the analysis ensemble spread (i.e. standard
 28  !                deviation) to the trial ensemble spread with a given amount (:math:`\alpha`) in the namelist.
 29  !                With the ensemble spread of analysis (:math:`\sigma^a`)
 30  !                and trial (:math:`\sigma^b`), it can be formulated as:
 31  !                :math:`x^a_i \leftarrow \overline{x^a} + (\overline{x^a}-x^a_i)(1+\alpha(\sigma^b-\sigma^a)/\sigma^a)`
 32  !
 33  !                More details for the RTPS can be found in paper:
 34  !                `Evaluating Methods to Account for System Errors in Ensemble Data Assimilation
 35  !                <https://journals.ametsoc.org/view/journals/mwre/140/9/mwr-d-11-00276.1.xml>`_
 36  !
 37  !              - **Humidity limits**: Impose the saturation limits and RTTOV limits
 38  !                on the humidity for each member.
 39  !
 40  !              - **Recenter**: The ensemble analyses from the LETKF are recentered
 41  !                around the EnVar analysis based on the input coefficent.
 42  !                It is also called hybrid gain algorithm and more details can be found in
 43  !                paper:
 44  !                `Using the hybrid gain algorithm to sample data assimilation uncertainty
 45  !                <https://rmets.onlinelibrary.wiley.com/doi/10.1002/qj.3426>`_
 46  !
 47  !              - **Subsample**: Select 20 ensemble members for the medium range forecasts.
 48  !
 49  !              - **Random perturbation**: Generate homogeneous and isotropic random perturbations
 50  !                and add them to the ensemble analyses.
 51  !
 52  !              - **Analysis increments**: After all the processes above, the analysis incrememnts are
 53  !                computed at the central time for all the members including the control member and
 54  !                the subsampled 20 members.
 55  !
 56  !              - **Mask analysis increments**: For LAM grid, the analysis increments in the blending
 57  !                area are masked out.
 58  !
 59  !            --
 60  !
 61  !============================================= ==============================================================
 62  ! Input and Output Files                        Description of file
 63  !============================================= ==============================================================
 64  ! ``flnml``                                     In - Main namelist file with parameters user may modify
 65  ! ``ensemble_trial/$YYYYMMDDHH_006_$NNNN``      In - Background ensemble member files
 66  ! ``ensemble_anal/$YYYYMMDDHH_000_$NNNN``       In - Analysis ensemble member files
 67  ! ``bgcov``                                     In - Bnmc matrix for the random perturbations
 68  ! ``analysis_grid``                             In - Horizontal grid file on which the random perturbations
 69  !                                               are generated
 70  ! ``$YYYYMMDDHH_recentering_analysis``          In - Analysis from EnVar for recentering the ensemble analyses
 71  ! ``analinc_mask``                              In - Mask file for masking the analysis increments for LAM grid
 72  ! ``$YYYYMMDDHH_000_inc_$NNNN``                 Out - Ensemble analysis increments for trials
 73  ! ``$YYYYMMDDHH_000_$NNNN``                     Out - Ensemble analyses recentered and perturbed
 74  ! ``$YYYYMMDDHH_000_$NNNN_raw``                 Out - Ensemble analyses from LETKF
 75  ! ``$YYYYMMDDHH_000_analmean``                  Out - Mean ensemble analysis without perturbation
 76  ! ``$YYYYMMDDHH_000_analrms``                   Out - Analysis ensemble spread (i.e. standard deviation) without perturbation
 77  ! ``$YYYYMMDDHH_000_analrms_ascii``             Out - Global average of  ``$YYYYMMDDHH_000_analrms``
 78  ! ``$YYYYMMDDHH_000_analpertmean``              Out - Mean ensemble analysis with perturbation and recentering
 79  ! ``$YYYYMMDDHH_000_analpertrms``               Out - Analysis ensemble spread with perturbation and recentering
 80  ! ``$YYYYMMDDHH_000_analpertrms_ascii``         Out - Global average of  ``$YYYYMMDDHH_000_analpertrms``
 81  ! ``$YYYYMMDDHH_006_trialmean``                 Out - Mean ensemble trial for all time levels
 82  ! ``$YYYYMMDDHH_006_trialrms``                  Out - Trial ensemble spread at 6H
 83  ! ``$YYYYMMDDHH_006_trialrms_ascii``            Out - Global average of ``$YYYYMMDDHH_006_trialrms``
 84  ! ``subspace/$YYYYMMDDHH_000_inc_$NNNN``        Out - Subsampled ensemble analysis increments for progs
 85  ! ``subspace/$YYYYMMDDHH_000_$NNNN``            Out - Subsampled ensemble analyses recentered and perturbed
 86  ! ``subspace_unpert/$YYYYMMDDHH_000_$NNNN``     Out - Unperturbed subsampled ensemble analyses recentered
 87  !============================================= ==============================================================
 88  !
 89  !            --
 90  !
 91  !:Synopsis: Below is a summary of the ``ensPostProcess`` program calling sequence:
 92  !
 93  !             - **Initial setups:**
 94  !
 95  !               - Read the NAMLETKF namelist and check/modify some values.
 96  !
 97  !               - Various modules are setup: ``gridStateVector_mod``, ``timeCoord_mod`` (and set up dates
 98  !                 and ``dateStampList`` variables for both trials and increments/analyses).
 99  !
100  !               - Setup horizontal and vertical grid objects from first
101  !                 ensemble member file.
102  !
103  !               - Allocate varaibles and read ensemble analyses and trials
104  !
105  !             - **Ensemble postprocess:**
106  !
107  !               - Compute ensemble mean and spread (i.e. standard deviation) for analysis and trial
108  !
109  !               - Perform RTPP and RTPS and recompute analysis spread
110  !
111  !               - Recenter ensemble mean and recompute analysis mean and spread
112  !
113  !               - Apply humidity saturation limit and RTTOV HU limit and recompute analysis mean
114  !
115  !               - Subsample ensemble analysis
116  !
117  !               - Add random perturbation to the analyses and compute perturbed analysis spread
118  !
119  !               - Add random perturbation to the subsampled analyses and recenter subsampled mean to the
120  !                 global mean.
121  !
122  !               - Compute analysis increments for all analyses and subsampled analyses including the ensemble mean
123  !
124  !               - Mask LAM analysis increments are recompute the ensemble analyses by adding the increments
125  !                 to the trials
126  !
127  !               - Writing the outputs.
128  !
129  !:Options: `List of namelist blocks <../namelists_in_each_program.html#ensPostProcess>`_
130  !          that can affect the ``ensPostProcess`` program.
131  !
132  !========================== ========================== ==============================================================
133  ! Program/Module             Namelist                   Description of what is controlled
134  !========================== ========================== ==============================================================
135  ! ``midas_ensPostProcess``   ``NAMENSPOSTPROC``         Number of ensemble members and read, write control of trials
136  !                                                       and analyses and horizontal interpolation degree
137  ! ``enspostprocess_mod``     ``NAMENSPOSTPROCMODULE``   Control the postprocess algorithms
138  ! ``timeCoord_mod``          ``NAMTIME``                Temporal resolution of the background state and the analysis
139  !========================== ========================== ==============================================================
140  !
141
142  use version_mod
143  use midasMpi_mod
144  use fileNames_mod
145  use ensembleStateVector_mod
146  use gridStateVector_mod
147  use gridStateVectorFileIO_mod
148  use verticalCoord_mod
149  use horizontalCoord_mod
150  use timeCoord_mod
151  use utilities_mod
152  use ramDisk_mod
153  use ensPostProcess_mod
154  implicit none
155
156  type(struct_ens)          :: ensembleTrl
157  type(struct_ens)          :: ensembleAnl
158  type(struct_vco), pointer :: vco_ens => null()
159  type(struct_hco), pointer :: hco_ens => null()
160  type(struct_gsv)          :: stateVectorHeightSfc, stateVectorCtrlTrl
161
162  character(len=256) :: ensPathNameAnl = 'ensemble_anal'
163  character(len=256) :: ensPathNameTrl = 'ensemble_trial'
164  character(len=256) :: ensFileName, gridFileName, ctrlFileName
165  integer, allocatable :: dateStampList(:)
166  integer :: ierr, nulnam, stepIndex
167  logical :: targetGridFileExists
168  integer, external :: get_max_rss, fstopc, fnom, fclos
169
170  integer :: nEns             ! ensemble size
171  logical :: readTrlEnsemble  ! activate reading of trial ensemble
172  logical :: readAnlEnsemble  ! activate reading of analysis ensemble
173  logical :: writeTrlEnsemble ! activate writing of the trial ensemble (useful when it's interpolated)
174  character(len=12) :: hInterpolationDegree ! select degree of horizontal interpolation (if needed)
175  NAMELIST /namEnsPostProc/nEns, readTrlEnsemble, readAnlEnsemble, &
176                           writeTrlEnsemble, hInterpolationDegree
177
178  call ver_printNameAndVersion('ensPostProcess','Program for post-processing of LETKF analysis ensemble')
179
180  !
181  !- 0. MPI, TMG and misc. initialization
182  !
183  call mmpi_initialize
184  call tmg_init(mmpi_myid, 'TMG_INFO')
185
186  call utl_tmg_start(0,'Main')
187  write(*,*) 'Memory Used: ',get_max_rss()/1024,'Mb'
188
189  ! Avoid printing lots of stuff to listing for std file I/O
190  ierr = fstopc('MSGLVL','ERRORS',0)
191
192  ! Setup the ramdisk directory (if supplied)
193  call ram_setup
194
195  !- Setting default namelist variable values
196  nEns = 256
197  readTrlEnsemble  = .true.
198  readAnlEnsemble  = .true.
199  writeTrlEnsemble = .false.
200  hInterpolationDegree = 'LINEAR' ! or 'CUBIC' or 'NEAREST'
201
202  !- Read the namelist
203  nulnam = 0
204  ierr = fnom(nulnam, './flnml', 'FTN+SEQ+R/O', 0)
205  read(nulnam, nml=namEnsPostProc, iostat=ierr)
206  if ( ierr /= 0) call utl_abort('midas-ensPostProcess: Error reading namelist')
207  if ( mmpi_myid == 0 ) write(*,nml=namEnsPostProc)
208  ierr = fclos(nulnam)
209
210  if (.not.readTrlEnsemble .and. .not.readAnlEnsemble) then
211    call utl_abort('midas-ensPostProcess: must read either Trial or Analysis ensemble')
212  end if
213
214  if (writeTrlEnsemble .and. .not.readTrlEnsemble) then
215    call utl_abort('midas-ensPostProcess: cannot write Trial ensemble if it is not read')
216  end if
217
218  if (writeTrlEnsemble .and. readAnlEnsemble) then
219    call utl_abort('midas-ensPostProcess: cannot write Trial ensemble when Analysis ensemble is read')
220  end if
221
222  !- 1. Initialize date/time-related info
223
224  ! Setup timeCoord module, set dateStamp with value from trial or analysis ensemble member 1
225  if (readTrlEnsemble) then
226    call fln_ensFileName(ensFileName, ensPathNameTrl, memberIndex_opt=1, &
227                         copyToRamDisk_opt=.false.)
228  else
229    call fln_ensFileName(ensFileName, ensPathNameAnl, memberIndex_opt=1, &
230                         copyToRamDisk_opt=.false.)
231  end if
232  call tim_setup(fileNameForDate_opt=ensFileName)
233  allocate(dateStampList(tim_nstepobsinc))
234  call tim_getstamplist(dateStampList,tim_nstepobsinc,tim_getDatestamp())
235
236  write(*,*) 'midas-ensPostProcess: analysis dateStamp = ', tim_getDatestamp()
237
238  !- 2. Initialize variables and grids
239
240  !- Initialize variables of the model states
241  call gsv_setup
242
243  !- Initialize the grid from targetgrid file or from trial or analysis ensemble member 1
244  if (mmpi_myid == 0) write(*,*) ''
245  if (mmpi_myid == 0) write(*,*) 'midas-ensPostProcess: Set hco and vco parameters for ensemble grid'
246  inquire(file='targetgrid', exist=targetGridFileExists)
247  if (targetGridFileExists) then
248    gridFileName = 'targetgrid'
249  else if (readTrlEnsemble) then
250    call fln_ensFileName(gridFileName, ensPathNameTrl, memberIndex_opt=1, &
251                         copyToRamDisk_opt=.false.)
252  else
253    call fln_ensFileName(gridFileName, ensPathNameAnl, memberIndex_opt=1, &
254                         copyToRamDisk_opt=.false.)
255  end if
256  if (mmpi_myid == 0) then
257    write(*,*) 'midas-ensPostProcess: file use to define grid = ', trim(gridFileName)
258  end if
259  call hco_SetupFromFile(hco_ens, gridFileName, ' ', 'ENSFILEGRID')
260  call vco_setupFromFile(vco_ens, gridFileName)
261
262  !- Read the sfc height from trial ensemble member 1 - only if we are doing NWP!
263  if (vco_getNumLev(vco_ens,'TH') > 0 .or. vco_getNumLev(vco_ens,'MM') > 0) then
264    if (readTrlEnsemble) then
265      call fln_ensFileName(ensFileName, ensPathNameTrl, memberIndex_opt=1, &
266                           copyToRamDisk_opt=.false.)
267    else
268      call fln_ensFileName(ensFileName, ensPathNameAnl, memberIndex_opt=1, &
269                           copyToRamDisk_opt=.false.)
270    end if
271    call gsv_allocate(stateVectorHeightSfc, 1, hco_ens, vco_ens, dateStamp_opt=tim_getDateStamp(),  &
272                      mpi_local_opt=.true., mpi_distribution_opt='Tiles', &
273                      hInterpolateDegree_opt=hInterpolationDegree, &
274                      dataKind_opt=4, allocHeightSfc_opt=.true., varNames_opt=(/'P0','TT'/))
275    call gio_readFromFile(stateVectorHeightSfc, ensFileName, ' ', ' ',  &
276                          containsFullField_opt=.true., readHeightSfc_opt=.true.)
277  end if
278
279  !- 3. Allocate and read ensembles
280
281  call utl_tmg_start(2,'--ReadEnsemble')
282
283  !- Allocate ensembles, read the Anl ensemble
284  if (readAnlEnsemble) then
285    call fln_ensFileName(ensFileName, ensPathNameAnl, resetFileInfo_opt=.true.)
286    call ens_allocate(ensembleAnl, nEns, tim_nstepobsinc, hco_ens, vco_ens, &
287                      dateStampList, hInterpolateDegree_opt=hInterpolationDegree)
288    call ens_readEnsemble(ensembleAnl, ensPathNameAnl, biPeriodic=.false.)
289  end if
290
291  !- Allocate ensembles, read the Trl ensemble
292  if (readTrlEnsemble) then
293    call fln_ensFileName(ensFileName, ensPathNameAnl, resetFileInfo_opt=.true.)
294    call ens_allocate(ensembleTrl, nEns, tim_nstepobsinc, hco_ens, vco_ens, &
295                      dateStampList, hInterpolateDegree_opt=hInterpolationDegree)
296    call ens_readEnsemble(ensembleTrl, ensPathNameTrl, biPeriodic=.false.)
297
298  end if
299
300  call utl_tmg_stop(2)
301
302  !- Allocate and read the Trl control member
303  if (readTrlEnsemble .and. readAnlEnsemble) then
304    !- Allocate and read control member Trl
305    call gsv_allocate( stateVectorCtrlTrl, tim_nstepobsinc, hco_ens, vco_ens, &
306                       dateStamp_opt=tim_getDateStamp(),  &
307                       mpi_local_opt=.true., mpi_distribution_opt='Tiles', &
308                       dataKind_opt=4, allocHeightSfc_opt=.true., &
309                       hInterpolateDegree_opt=hInterpolationDegree, &
310                       allocHeight_opt=.false., allocPressure_opt=.false. )
311    call fln_ensFileName(ctrlFileName, ensPathNameTrl, memberIndex_opt=0, &
312                         copyToRamDisk_opt=.false.)
313    do stepIndex = 1, tim_nstepobsinc
314      call gio_readFromFile( stateVectorCtrlTrl, ctrlFileName, ' ', ' ',  &
315                             stepIndex_opt=stepIndex, containsFullField_opt=.true., &
316                             readHeightSfc_opt=.false. )
317    end do
318  end if
319
320  !- 4. Post processing of the analysis results (if desired) and write everything to files
321  call epp_postProcess(ensembleTrl, ensembleAnl, &
322                       stateVectorHeightSfc, stateVectorCtrlTrl, &
323                       writeTrlEnsemble)
324
325  !
326  !- 5. MPI, tmg finalize
327  !  
328  write(*,*) 'Memory Used: ', get_max_rss()/1024, 'Mb'
329  call utl_tmg_stop(0)
330
331  call tmg_terminate(mmpi_myid, 'TMG_INFO')
332  call rpn_comm_finalize(ierr) 
333
334  write(*,*) 'Memory Used: ', get_max_rss()/1024, 'Mb'
335
336  if ( mmpi_myid == 0 ) write(*,*) ' --------------------------------'
337  if ( mmpi_myid == 0 ) write(*,*) ' MIDAS-ensPostProcess ENDS'
338  if ( mmpi_myid == 0 ) write(*,*) ' --------------------------------'
339
340end program midas_ensPostProcess