fileNames_mod sourceΒΆ

  1module fileNames_mod
  2  ! MODULE fileNames_mod (prefix='fln' category='7. Low-level data objects')
  3  !
  4  !:Purpose: Routines related to file names.
  5  !
  6  use utilities_mod
  7  use clibInterfaces_mod
  8  use ramDisk_mod
  9  use timeCoord_mod
 10  implicit none
 11  save
 12  private
 13
 14  ! public procedures
 15  public :: fln_ensFileName, fln_ensAnlFileName, fln_ensTrlFileName
 16
 17contains
 18
 19  !--------------------------------------------------------------------------
 20  ! fln_ensFileName
 21  !--------------------------------------------------------------------------
 22  subroutine fln_ensFileName(ensFileName, ensPathName, memberIndex_opt, ensFileNamePrefix_opt,  &
 23                             ensFileBaseName_opt, shouldExist_opt, ensembleFileExtLength_opt, &
 24                             copyToRamDisk_opt, resetFileInfo_opt, fileMemberIndex1_opt)
 25    !:Purpose: Return the filename of an ensemble member. Will also call routine in 
 26    !           ramdisk_mod module that will copy the file (if shouldExist_opt is true)
 27    !           to the ram disk. If the memberIndex_opt is not specified, the filename
 28    !           is returned without the member index extension (used to read deterministic
 29    !           background state that is stored in the ensemble directory for LETKF).
 30    !
 31    implicit none
 32
 33    ! Arguments:
 34    character(len=*),           intent(out) :: ensFileName
 35    character(len=*),           intent(in)  :: ensPathName
 36    integer,          optional, intent(in)  :: memberIndex_opt
 37    character(len=*), optional, intent(out) :: ensFileBaseName_opt
 38    character(len=*), optional, intent(in)  :: ensFileNamePrefix_opt
 39    logical,          optional, intent(in)  :: shouldExist_opt
 40    integer,          optional, intent(out) :: ensembleFileExtLength_opt
 41    logical,          optional, intent(in)  :: copyToRamDisk_opt
 42    logical,          optional, intent(in)  :: resetFileInfo_opt
 43    integer,          optional, intent(in)  :: fileMemberIndex1_opt
 44
 45    ! Locals:
 46    integer          :: numFiles, returnCode, totalLength, ensembleBaseFileNameLength
 47    character(len=10):: ensNumber  !! this is sufficient until we reach 10^10 members
 48    logical          :: shouldExist
 49    character(len=2000) :: fileList(10), fileNamePattern
 50    character        :: ensembleFileExtLengthStr
 51    logical, save    :: firstTime = .true.
 52    integer, save    :: ensembleFileExtLength = 4
 53    integer, save    :: fileMemberIndex1 = 1
 54    character(len=4),   save :: fileMemberIndex1Str
 55    character(len=200), save :: ensFileBaseName
 56
 57    if ( present(resetFileInfo_opt) ) then
 58      if (resetFileInfo_opt) firstTime = .true.
 59      return
 60    end if
 61
 62    if ( present(shouldExist_opt) ) then
 63      shouldExist = shouldExist_opt
 64    else
 65      shouldExist = .true.
 66    end if
 67
 68    ! Do this step only once in the program since this should not change during the program is running.
 69    if (firstTime) then
 70      if (present(fileMemberIndex1_opt)) fileMemberIndex1 = fileMemberIndex1_opt
 71      if (fileMemberIndex1 > 999) then
 72        write(fileMemberIndex1Str,'(i4.4)') fileMemberIndex1
 73      else
 74        write(fileMemberIndex1Str,'(i3.3)') fileMemberIndex1
 75      end if
 76
 77      write(*,*) 'fln_ensFileName: looking for ./' // trim(enspathname) // '/' // '*_*' // trim(fileMemberIndex1Str)
 78      fileNamePattern = './' // trim(enspathname) // '/' // '*_*' // trim(fileMemberIndex1Str)
 79      returnCode = clib_glob(fileList,numFiles,trim(fileNamePattern),10)
 80      if (returnCode /= 1) then
 81        if (shouldExist) then
 82          call utl_abort('fln_ensFileName: reached maximum number of files or no file is available')
 83        else
 84          write(*,*) 'fln_ensFileName: reached maximum number of files or no file is available'
 85          ensFileName='missing'
 86          return
 87        end if
 88      end if
 89
 90      ensFileName = trim(fileList(1))
 91      totalLength = len_trim(ensFileName)
 92      if ( totalLength == 0 ) then
 93        call utl_abort('fln_ensFileName: ensFileName seems empty: ''ensFileName=' // trim(ensFileName) // '''')
 94      end if
 95
 96      ! find number of digits used to identify ensemble member index
 97      ensembleFileExtLength = 0
 98      do
 99        if ( ensFileName((totalLength-ensembleFileExtLength):(totalLength-ensembleFileExtLength)) == '_' ) exit
100        ensembleFileExtLength = ensembleFileExtLength + 1
101      end do
102
103      if (ensembleFileExtLength == 0) then
104        call utl_abort('fln_ensFileName: Cannot determine the ensemble file extention length with ' // trim(ensFileName))
105      end if
106
107      ! find the last '/' in the file name to get the basename of the file
108      ensembleBaseFileNameLength = 0
109      do
110        if ( totalLength == ensembleBaseFileNameLength ) exit
111        if ( ensFileName((totalLength-ensembleBaseFileNameLength):(totalLength-ensembleBaseFileNameLength)) == '/' ) exit
112        ensembleBaseFileNameLength = ensembleBaseFileNameLength + 1
113      end do
114
115      ! if 'ensFileName = ./abc/def/ghi/123_456_001' then
116      !    totalLength = 25
117      !    ensembleFileExtLength = 3
118      !    ensembleBaseFileNameLength = 11
119      !    ensFileBaseName = '123_456'
120      ! if 'ensFileName = 123_456_001' then
121      !    totalLength = 11
122      !    ensembleFileExtLength = 3
123      !    ensembleBaseFileNameLength = 11
124      !    ensFileBaseName = '123_456'
125      ensFileBasename = ensFileName((totalLength-ensembleBaseFileNameLength+1):(totalLength-ensembleFileExtLength-1))
126
127      firstTime = .false.
128    end if
129
130    if (present(memberIndex_opt)) then
131      write(ensembleFileExtLengthStr,'(i1.1)') ensembleFileExtLength
132      write(ensNumber,'(i' // ensembleFileExtLengthStr // '.' // ensembleFileExtLengthStr // ')') &
133          memberIndex_opt + fileMemberIndex1 - 1
134    end if
135
136    if (present(memberIndex_opt)) then
137      if (present(ensFileNamePrefix_opt)) then
138        ensFileName = trim(enspathname) // '/' // trim(ensFileNamePrefix_opt) //  &
139                      trim(ensFileBaseName) // '_' // trim(ensNumber)
140      else
141        ensFileName = trim(enspathname) // '/' // trim(ensFileBaseName) // '_' // trim(ensNumber)
142      end if
143    else
144      if (present(ensFileNamePrefix_opt)) then
145        ensFileName = trim(enspathname) // '/' // trim(ensFileNamePrefix_opt) // trim(ensFileBaseName)
146      else
147        ensFileName = trim(enspathname) // '/' // trim(ensFileBaseName)
148      end if
149    end if
150
151    write(*,*) 'fln_ensFileName: ensFileName = ', trim(ensFileName)
152
153    if ( shouldExist ) ensFileName = ram_fullWorkingPath(ensFileName, copyToRamDisk_opt=copyToRamDisk_opt)
154
155    if (present(ensFileBaseName_opt)) ensFileBaseName_opt = trim(ensFileBaseName)
156    if (present(ensembleFileExtLength_opt)) ensembleFileExtLength_opt = ensembleFileExtLength
157
158  end subroutine fln_ensFileName
159
160  !--------------------------------------------------------------------------
161  ! fln_ensAnlFileName
162  !--------------------------------------------------------------------------
163  subroutine fln_ensAnlFileName( ensFileName, ensPathName, dateStamp,  &
164                                 memberIndex_opt, ensFileNamePrefix_opt, ensFileNameSuffix_opt )
165    !:Purpose: Return the filename for an analysis state, including for
166    !           ensemble members (by specifying memberIndex_opt). The member
167    !           index extension is assumed to be 4 digits.
168    !
169    implicit none
170
171    ! Arguments:
172    character(len=*),           intent(out) :: ensFileName
173    character(len=*)  ,         intent(in)  :: ensPathName
174    integer           ,         intent(in)  :: dateStamp
175    integer,          optional, intent(in)  :: memberIndex_opt
176    character(len=*), optional, intent(in)  :: ensFileNamePrefix_opt
177    character(len=*), optional, intent(in)  :: ensFileNameSuffix_opt
178
179    ! Locals:
180    integer :: imode, ierr, hours, prntdate, prnttime, newdate
181    character(len=4)  :: ensNumber
182    character(len=10) :: dateStrAnl
183
184    ! Set the printable date for analysis related file names
185    imode = -3 ! stamp to printable date and time: YYYYMMDD, HHMMSShh
186    ierr = newdate(dateStamp, prntdate, prnttime, imode)
187    hours = prnttime/1000000
188    write(dateStrAnl,'(i10.10)') prntdate*100 + hours
189
190    if (present(memberIndex_opt)) then
191      write(ensNumber,'(i4.4)') memberIndex_opt
192    end if
193
194    if (present(memberIndex_opt)) then
195      if (present(ensFileNamePrefix_opt)) then
196        if (present(ensFileNameSuffix_opt)) then
197          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
198                        dateStrAnl // '_000_' // trim(ensFileNameSuffix_opt) // '_' // trim(ensNumber)
199        else
200          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
201                        dateStrAnl // '_000_' // trim(ensNumber)
202        end if
203      else
204        if (present(ensFileNameSuffix_opt)) then
205          ensFileName = trim(ensPathName) // '/' // dateStrAnl // '_000_' //  &
206                        trim(ensFileNameSuffix_opt) // '_' // trim(ensNumber)
207        else
208          ensFileName = trim(ensPathName) // '/' // dateStrAnl // '_000_' // trim(ensNumber)
209        end if
210      end if
211    else
212      if (present(ensFileNamePrefix_opt)) then
213        if (present(ensFileNameSuffix_opt)) then
214          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
215                        dateStrAnl // '_000_' // trim(ensFileNameSuffix_opt)
216        else
217          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
218                        dateStrAnl // '_000'
219        end if
220      else
221        if (present(ensFileNameSuffix_opt)) then
222          ensFileName = trim(ensPathName) // '/' // dateStrAnl // '_000_' //  &
223                        trim(ensFileNameSuffix_opt)
224        else
225          ensFileName = trim(ensPathName) // '/' // dateStrAnl // '_000'
226        end if
227      end if
228    end if
229
230    write(*,*) 'fln_ensAnlFileName: ensFileName = ', trim(ensFileName)
231
232  end subroutine fln_ensAnlFileName
233
234  !--------------------------------------------------------------------------
235  ! fln_ensTrlFileName
236  !--------------------------------------------------------------------------
237  subroutine fln_ensTrlFileName( ensFileName, ensPathName, dateStamp,  &
238                                 memberIndex_opt, ensFileNamePrefix_opt, ensFileNameSuffix_opt )
239    !:Purpose: Return the filename for a trial state, including for
240    !           ensemble members (by specifying memberIndex_opt). The member
241    !           index extension is assumed to be 4 digits.
242    !
243    implicit none
244
245    ! Arguments:
246    character(len=*),           intent(out) :: ensFileName
247    character(len=*),           intent(in)  :: ensPathName
248    integer         ,           intent(in)  :: dateStamp
249    integer,          optional, intent(in)  :: memberIndex_opt
250    character(len=*), optional, intent(in)  :: ensFileNamePrefix_opt
251    character(len=*), optional, intent(in)  :: ensFileNameSuffix_opt
252
253    ! Locals:
254    integer :: imode, ierr, hours, prntdate, prnttime, newdate, dateStampTrl
255    character(len=4)  :: ensNumber
256    character(len=3)  :: leadTimeStr
257    character(len=10) :: dateStrTrl
258
259    ! Compute the datestamp for the origin time of the trial forecasts
260    call incdatr(dateStampTrl, dateStamp, -tim_windowsize)
261    
262    ! Set the printable date for trial related file names
263    imode = -3 ! stamp to printable date and time: YYYYMMDD, HHMMSShh
264    ierr = newdate(dateStampTrl, prntdate, prnttime, imode)
265    hours = prnttime/1000000
266    write(dateStrTrl,'(i10.10)') prntdate*100 + hours
267
268    if (present(memberIndex_opt)) then
269      write(ensNumber,'(i4.4)') memberIndex_opt
270    end if
271    write(leadTimeStr,'(i3.3)') nint(tim_windowsize)
272
273    if (present(memberIndex_opt)) then
274      if (present(ensFileNamePrefix_opt)) then
275        if (present(ensFileNameSuffix_opt)) then
276          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
277                        dateStrTrl // '_' // leadTimeStr // '_' // trim(ensFileNameSuffix_opt) // '_' // trim(ensNumber)
278        else
279          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
280                        dateStrTrl // '_' // leadTimeStr // '_' // trim(ensNumber)
281        end if
282      else
283        if (present(ensFileNameSuffix_opt)) then
284          ensFileName = trim(ensPathName) // '/' // dateStrTrl // '_' // leadTimeStr // '_' //  &
285                        trim(ensFileNameSuffix_opt) // '_' // trim(ensNumber)
286        else
287          ensFileName = trim(ensPathName) // '/' // dateStrTrl // '_' // leadTimeStr // '_' // trim(ensNumber)
288        end if
289      end if
290    else
291      if (present(ensFileNamePrefix_opt)) then
292        if (present(ensFileNameSuffix_opt)) then
293          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
294                        dateStrTrl // '_' // leadTimeStr // '_' // trim(ensFileNameSuffix_opt)
295        else
296          ensFileName = trim(ensPathName) // '/' // trim(ensFileNamePrefix_opt) //  &
297                        dateStrTrl // '_' // leadTimeStr
298        end if
299      else
300        if (present(ensFileNameSuffix_opt)) then
301          ensFileName = trim(ensPathName) // '/' // dateStrTrl // '_' // leadTimeStr // '_' //  &
302                        trim(ensFileNameSuffix_opt)
303        else
304          ensFileName = trim(ensPathName) // '/' // dateStrTrl // '_' // leadTimeStr
305        end if
306      end if
307    end if
308
309    write(*,*) 'fln_ensTrlFileName: ensFileName = ', trim(ensFileName)
310
311  end subroutine fln_ensTrlFileName
312
313end module fileNames_mod