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