midas_extractBmatrixFor1Dvar sourceΒΆ

  1program midas_extractBmatrixFor1Dvar
  2  !
  3  !:Purpose: Main program to extract B matrix to binary file Bmatrix.bin suitable for 1Dvar applications
  4  !          The B matrix is defined at a set of locations specified by the variable lonlatExtract and date 
  5  !          extractDate
  6  !
  7  !          ---
  8  !
  9  !:Algorithm:  The B matrix is computed column by column by application of operators bmat_sqrtBT and bmat_sqrtB 
 10  !
 11  !            --
 12  !
 13  !:File I/O: The required input files and produced output files are listed as follows.
 14  !
 15  !============================================== ==============================================================
 16  ! Input and Output Files                          Description of file
 17  !============================================== ==============================================================
 18  ! ``flnml``                                      In - Main namelist file with parameters user may modify
 19  ! ``flnml_static``                               In - The "static" namelist that should not be modified
 20  ! ``bgcov``                                      In - The B NMC matrix file
 21  ! ``analysisgrid``                               In - analysis grid 
 22  ! ``Bmatrix.bin``                                Out - The Bmatrix binary file for 1DVar
 23  !============================================== ==============================================================
 24  !
 25  !           --
 26  !
 27  !:Synopsis: Below is a summary of the ``extractBmatrixFor1Dvar`` program calling sequence:
 28  !    
 29  !             - **Initial setups:**
 30  !
 31  !               - Read parameters from the program namelist section NAMEXTRACT
 32  !
 33  !               - Setup temporal grid
 34  !
 35  !               - Get vertical and horizontal grid information from analysisgrid file
 36  !
 37  !               - Allocate a gridStatevector object
 38  !
 39  !               - Initialize the B matrix
 40  !
 41  !               - Initialize the gridded variable transform module 
 42  !
 43  !             - **Computation:**
 44  !
 45  !               - For each location specified in the namelist: 
 46  !
 47  !                   - for each element of the stateVector
 48  !
 49  !                      - set this elemnt to one and the other to zero
 50  !
 51  !                      - apply bmat_sqrtBT
 52  !
 53  !                      - apply bmat_sqrtB
 54  !
 55  !                      - get the corresponding column of the B matrix
 56  !
 57  !                   - write the resulting B matrix to file
 58  !           --
 59  !:Options: `List of namelist blocks <../namelists_in_each_program.html#extractbmatrixfor1dvar>`_
 60  !          that can affect the ``extractBmatrixFor1Dvar`` program.
 61  !
 62  !          - The use of ``extractBmatrixFor1Dvar`` program is controlled by the namelist block
 63  !            ``&namextract`` read by the ``extractBmatrixFor1Dvar`` program.
 64  !              *  ``extractdate`` date (YYYYMMDDHH format) for the B matrix extracted
 65  !              *  ``lonlatExtract`` (longitudes, latitudes) pairs definining the locations where the B matrix is to be extracted
 66  !              *  ``varNameExtract`` name of the variable to extract or ``all`` to extract everything in namstate
 67  !              *  ``stepBinExtract`` should be one of ``first``, ``middle`` or ``last`` to define when in the assimilation window the B matrix is valid
 68  !
 69  use version_mod
 70  use midasMpi_mod
 71  use mathPhysConstants_mod
 72  use controlVector_mod
 73  use gridVariableTransforms_mod
 74  use varNameList_mod
 75  use gridStateVector_mod
 76  use bMatrix_mod
 77  use horizontalCoord_mod
 78  use verticalCoord_mod
 79  use timeCoord_mod
 80  use utilities_mod
 81  use ramDisk_mod
 82  implicit none
 83
 84  type(struct_gsv) :: statevector
 85  type(struct_hco), pointer :: hco_anl  => null()
 86  type(struct_hco), pointer :: hco_core => null()
 87  type(struct_vco), pointer :: vco_anl  => null()
 88  real(4) :: factor1, factor2
 89  real(8), pointer :: field4d(:,:,:,:)
 90  real(8), allocatable :: controlVector(:)
 91  integer, parameter :: nmaxLevs = 100
 92  real(4) :: latitude, longitude
 93  integer, external :: fclos, fnom, fstopc, newdate, get_max_rss
 94  integer :: ierr
 95  integer :: varIndex, nkgdim, levIndex1, lonIndex, latIndex, levIndex2
 96  integer :: kIndex1, kIndex2, columnProcIdLocal, columnProcIdGlobal, nulmat, varCount
 97  integer :: idate, itime, nulnam, dateStamp
 98  integer :: stepBinExtractIndex
 99  integer :: nLonLatPos, lonLatPosIndex
100
101  integer, parameter :: lonColumn = 1
102  integer, parameter :: latColumn = 2
103
104  character(len=10)  :: datestr
105  character(len=4)   :: varName1, varName2
106  character(len=4),allocatable :: varList(:)
107  real(8), allocatable :: Bmatrix(:,:)
108
109  ! namelist variables
110  integer :: extractdate               ! date for the B matrix extracted
111  integer :: lonlatExtract(nmaxLevs,2) ! lon lat pairs definining the locations where the B matrix is to be extracted
112  character(len=128) :: stepBinExtract ! number of step bins to extract (1 typically for B NMC)
113  character(len=4)   :: varNameExtract ! variable to extract (all to extract everything in namstate)
114  namelist /namextract/ extractdate, lonlatExtract, &
115                    varNameExtract, stepBinExtract
116
117  call ver_printNameAndVersion('extractBmatrix', 'Extract 1Dvar B matrix')
118
119  ! MPI, tmg initialization
120  call mmpi_initialize
121  call tmg_init(mmpi_myid, 'TMG_INFO')
122  call utl_tmg_start(0, 'Main')
123  ierr = fstopc('MSGLVL', 'ERRORS', 0)
124
125  ! Set default values for namelist NAMEXTRACT parameters
126  extractdate        =  2011020100
127  varNameExtract     = 'all'
128  stepBinExtract     = 'middle'
129  lonlatExtract(:,:) = -1
130
131  ! Read the parameters from NAMEXTRACT
132  nulnam = 0
133  ierr = fnom(nulnam, './flnml', 'FTN+SEQ+R/O', 0)
134  read(nulnam, nml=namextract, iostat=ierr)
135  if (ierr /= 0) call utl_abort('midas-extractBmatrix: Error reading namelist')
136  write(*, nml=namextract)
137  ierr = fclos(nulnam)
138
139  nLonLatPos = 0
140  do lonlatPosIndex = 1, size(lonlatExtract(:,lonColumn))
141    if (lonlatExtract(lonlatPosIndex,lonColumn) >= 1 .and. lonlatExtract(lonlatPosIndex,latColumn) >= 1) nLonLatPos = nLonLatPos + 1  
142  end do
143
144  if ( nLonLatPos == 0 ) then
145    call utl_abort('midas-extractBmatrix: You should specify at least one lonlat position !')
146  end if
147
148  ! Decompose extractdate(yyyymmddhh) into idate(YYYYMMDD) itime(HHMMSShh)
149  ! and calculate date-time stamp
150  idate = extractdate/100
151  itime = (extractdate-idate*100)*1000000
152  ierr = newdate(dateStamp, idate, itime, 3)
153  write(datestr,'(i10.10)') extractdate
154  write(*,*)' idate= ',idate,' time= ',itime
155  write(*,*)' date= ',extractdate,' stamp= ',dateStamp
156
157  ! Top Level Control setup
158  call ram_setup
159  !- Initialize the Temporal grid
160  call tim_setup
161  if (tim_getDateStamp() == 0) then
162    call tim_setDatestamp(dateStamp)
163  else
164    call utl_abort('midas-extractBmatrix: Code changes needed to use dateStamp from env variable')
165  end if
166  ! Initialize variables of the model states
167  call gsv_setup
168  ! Initialize the Analysis horizontal grid
169  call hco_SetupFromFile( hco_anl, './analysisgrid', 'ANALYSIS', 'Analysis' ) ! IN
170  if ( hco_anl % global ) then
171    hco_core => hco_anl
172  else
173    !- Iniatilized the core (Non-Extended) analysis grid
174    call hco_SetupFromFile( hco_core, './analysisgrid', 'COREGRID', 'AnalysisCore' ) ! IN
175  end if
176  write(*,*) 'Memory Used: ', get_max_rss()/1024, 'Mb'
177
178  ! Initialize the vertical coordinate from the statistics file
179  call vco_SetupFromFile( vco_anl,        & ! OUT
180                          './analysisgrid') ! IN
181  ! Allocate the statevector
182  call gsv_allocate(statevector, tim_nstepobsinc, hco_anl, vco_anl, &
183                    datestamp_opt=tim_getDatestamp(), mpi_local_opt=.true., &
184                    allocHeight_opt=.false., allocPressure_opt=.false.)
185  call gsv_zero(statevector)
186  nkgdim = statevector%nk
187  allocate( Bmatrix(nkgdim, nkgdim) )
188  ! Setup the B matrix
189  call bmat_setup(hco_anl, hco_core, vco_anl)
190  !- Initialize the gridded variable transform module
191  call gvt_setup(hco_anl, hco_core, vco_anl)
192  call gvt_setupRefFromTrialFiles('HU')
193  write(*,*) 'Memory Used: ', get_max_rss()/1024, 'Mb'
194
195  !
196  !==============================================
197  !- Compute columns of B matrix
198  !==============================================
199  !
200  select case(trim(stepBinExtract))
201  case ('first')
202   stepBinExtractIndex = 1
203  case ('middle')
204    if (mod(tim_nstepobsinc,2) == 0) then
205      write(*,*)
206      write(*,*) 'odd number of nstepobsinc a required for obs place in the middle of the analysis window '
207      write(*,*) 'tim_nstepobsinc = ', tim_nstepobsinc
208      call utl_abort('midas-extractBmatrix')
209    end if
210   stepBinExtractIndex = (tim_nstepobsinc+1)/2
211  case ('last')
212   stepBinExtractIndex = tim_nstepobsinc
213  case default
214    write(*,*)
215    write(*,*) 'Unsupported stepBinExtract : ', trim(stepBinExtract)
216    call utl_abort('midas-extractBmatrix')
217  end select
218  
219  allocate(controlVector(cvm_nvadim))
220
221  write(*,*) '************************************************************'
222  write(*,*) 'midas-extractBmatrix: Compute columns of B matrix for 1Dvar'
223  write(*,*) '************************************************************'
224  write(*,*)
225  write(*,*) ' temporal location           = ', trim(stepBinExtract), stepBinExtractIndex
226  write(*,*) ' number of lon-lat positions = ', nLonLatPos
227  
228  if (mmpi_myId == 0) then
229    varCount = 0
230    do varIndex=1, vnl_numvarmax
231      if ( .not. gsv_varExist(varName=vnl_varNameList(varIndex)) ) cycle
232      if ( trim(varNameExtract)  /= 'all' .and. (trim(varNameExtract) /= trim(vnl_varNameList(varIndex))) ) cycle
233      varCount = varCount + 1
234    end do
235    allocate(varList(varCount))
236    varCount = 0
237    do varIndex=1, vnl_numvarmax
238      if ( .not. gsv_varExist(varName=vnl_varNameList(varIndex)) ) cycle
239      if ( trim(varNameExtract) /= 'all' .and. (trim(varNameExtract) /= trim(vnl_varNameList(varIndex))) ) cycle
240      varCount = varCount + 1
241      varList(varCount) = vnl_varNameList(varIndex)
242    end do
243    nulmat = 0
244    ierr = fnom(nulmat, './Bmatrix.bin', 'FTN+SEQ+UNF', 0)
245    write(nulmat) extractDate, vco_anl % nlev_T, vco_anl % nlev_M, vco_anl % Vcode, &
246         vco_anl % ip1_sfc, vco_anl % ip1_T_2m, vco_anl % ip1_M_10m, varCount, nkgdim, nLonLatPos
247    write(nulmat) vco_anl % ip1_T(:), vco_anl % ip1_M(:), varList(:)
248  end if
249  
250  locationLoop:do lonLatPosIndex = 1, nLonLatPos
251
252    Bmatrix(:,:) = MPC_missingValue_R8
253
254    latIndex = lonlatExtract(lonLatPosIndex,latColumn)
255    lonIndex = lonlatExtract(lonLatPosIndex,lonColumn)
256    
257    latitude = hco_anl%lat2d_4(lonIndex, latIndex)
258    longitude = hco_anl%lon2d_4(lonIndex, latIndex)
259
260    variableLoop1:do kIndex1 = 1, nkgdim
261      varName1 = gsv_getVarNameFromK(statevector, kIndex1)
262      if ( .not. gsv_varExist(varName=varName1) ) cycle
263      if ( trim(varNameExtract) /= 'all' .and. trim(varNameExtract) /= trim(varName1) ) cycle
264      
265      write(*,*)
266      write(*,*) 'midas-extractBmatrix: simulating a pseudo-observation of ', trim(varName1)
267      
268      factor1 = getConversionFactor( varName1 )
269      levIndex1 = gsv_getLevFromK(statevector, kIndex1)
270      call gsv_zero(statevector)
271      call gsv_getField(statevector,field4d, varName1)
272      if ( latIndex >= statevector%myLatBeg .and. latIndex <= statevector%myLatEnd .and. &
273           lonIndex >= statevector%myLonBeg .and. lonIndex <= statevector%myLonEnd ) then
274        if (vnl_varLevelFromVarname(varName1) == 'SF') then
275          field4d(lonIndex, latIndex, 1, stepBinExtractIndex) = 1.0D0
276        else
277          field4d(lonIndex, latIndex, levIndex1, stepBinExtractIndex) = 1.0D0
278        end if
279      end if
280      !ici field4d est initialise a zero sauf au point qui nous interesse ou on a 1
281      !et donc aussi statevector (puisque field4V est un pointeur vers la partie correspondante de statevector)
282      controlVector(:) = 0.0d0
283      call bmat_sqrtBT(controlVector, cvm_nvadim, statevector)
284      call bmat_sqrtB (controlVector, cvm_nvadim, statevector)
285      ! ici statevector contient la colonne correspondante de la matrice B
286      write(*,*) 'midas-extractBmatrix: writing out the column of B. levIndex1,lonIndex,latIndex=', &
287                 levIndex1,lonIndex,latIndex
288      
289      variableLoop2:do kIndex2 = 1, nkgdim
290        varName2 = gsv_getVarNameFromK(statevector, kIndex2)
291        if ( .not. gsv_varExist(varName= varName2) ) cycle
292        if ( trim(varNameExtract) /= 'all' .and. trim(varNameExtract) /= trim(varName2) ) cycle
293        columnProcIdLocal = -1
294        if ( latIndex >= statevector % myLatBeg .and. latIndex <= statevector % myLatEnd .and. &
295             lonIndex >= statevector % myLonBeg .and. lonIndex <= statevector % myLonEnd ) then
296          columnProcIdLocal = mmpi_myId
297          call gsv_getField(statevector, field4d, varName2)
298          factor2 = getConversionFactor( varName2 )
299          levIndex2 = gsv_getLevFromK(statevector, kIndex2)
300          bmatrix(kIndex2, kIndex1) = factor1 * factor2 * field4d(lonIndex, latIndex, levIndex2, stepBinExtractIndex)
301        end if
302        call rpn_comm_allreduce(columnProcIdLocal, columnProcIdGlobal, 1, "mpi_integer", "mpi_max", "GRID", ierr)
303      end do variableLoop2
304
305    end do variableLoop1
306
307    call RPN_COMM_bcast(Bmatrix, nkgdim * nkgdim, 'MPI_REAL8', columnProcIdGlobal, 'GRID', ierr )
308    if (mmpi_myId ==0) then
309      write(nulmat) latitude, longitude,  Bmatrix(:,:)
310    end if
311
312  end do locationLoop
313    
314  ierr = fclos(nulmat)
315
316  deallocate(Bmatrix)
317  deallocate(controlVector)
318
319  write(*,*) 'Memory Used: ', get_max_rss()/1024, 'Mb'
320
321  call gsv_deallocate(statevector)
322
323  write(*,*) 'Memory Used: ', get_max_rss()/1024, 'Mb'
324  
325  ! MPI, tmg finalize
326  call utl_tmg_stop(0)
327  call tmg_terminate(mmpi_myid, 'TMG_INFO')
328  call rpn_comm_finalize(ierr) 
329
330  write(*,*) ' --------------------------------'
331  write(*,*) ' midas-extractBmatrix ENDS'
332  write(*,*) ' --------------------------------'
333
334contains
335
336  real(4) function getConversionFactor(varName)
337    character(len=*), intent(in) :: varName
338    if ( trim(varName) == 'UU' .or. trim(varName) == 'VV') then
339      getConversionFactor = mpc_knots_per_m_per_s_r4 ! m/s -> knots
340    else if ( trim(varName) == 'P0' ) then
341      getConversionFactor = 0.01 ! Pa -> hPa
342    else 
343      getConversionFactor = 1.0 ! no conversion
344    end if
345  end function getConversionFactor
346
347end program midas_extractBmatrixFor1Dvar