8 use string_utils,
only: swap_name_member
11 use fckit_configuration_module,
only: fckit_configuration
14 use fms_io_mod,
only: restart_file_type, register_restart_field
15 use fms_io_mod,
only: free_restart_type, restore_state, save_restart
16 use mpp_domains_mod,
only: east, north, center
17 use mpp_mod,
only: mpp_pe, mpp_root_pe
36 character(len=128) :: datapath
39 integer :: index_core = 1
40 integer :: index_trcr = 2
41 integer :: index_sfcd = 3
42 integer :: index_sfcw = 4
43 integer :: index_cplr = 5
44 integer :: index_spec = 6
45 integer :: index_phys = 7
46 integer :: index_orog = 8
47 integer :: index_cold = 9
49 logical :: skip_coupler
50 logical :: prepend_date
69 type(fckit_configuration),
intent(in) :: f_conf
72 character(len=:),
allocatable :: str
73 character(len=13) :: fileconf(numfiles)
77 call f_conf%get_or_die(
"datapath",str)
79 call abor1_ftn(
'fv3jedi_io_gfs_mod.setup: datapath too long, max FMS char length= 128')
83 call swap_name_member(f_conf, str)
91 self%filenames_conf(self%index_core) =
'fv_core.res.nc'
92 self%filenames_conf(self%index_trcr) =
'fv_tracer.res.nc'
93 self%filenames_conf(self%index_sfcd) =
'sfc_data.nc'
94 self%filenames_conf(self%index_sfcw) =
'srf_wnd.nc'
95 self%filenames_conf(self%index_cplr) =
'coupler.res'
96 self%filenames_conf(self%index_spec) =
'null'
97 self%filenames_conf(self%index_phys) =
'phy_data.nc'
98 self%filenames_conf(self%index_orog) =
'oro_data.nc'
99 self%filenames_conf(self%index_cold) =
'gfs_data.nc'
103 fileconf(self%index_core) =
"filename_core"
104 fileconf(self%index_trcr) =
"filename_trcr"
105 fileconf(self%index_sfcd) =
"filename_sfcd"
106 fileconf(self%index_sfcw) =
"filename_sfcw"
107 fileconf(self%index_cplr) =
"filename_cplr"
108 fileconf(self%index_spec) =
"filename_spec"
109 fileconf(self%index_phys) =
"filename_phys"
110 fileconf(self%index_orog) =
"filename_orog"
111 fileconf(self%index_cold) =
"filename_cold"
119 if (f_conf%has(fileconf(n)))
then
120 call f_conf%get_or_die(fileconf(n),str)
121 if (len(str) > 128)
call abor1_ftn(
"fv3jedi_io_gfs_mod.setup: "//fileconf(n)//&
122 " too long, max FMS char length= 128")
123 self%filenames_conf(n) = str
128 self%filenames(n) = trim(self%filenames_conf(n))
134 self%ps_in_file = .false.
135 if (f_conf%has(
"psinfile"))
then
136 call f_conf%get_or_die(
"psinfile",self%ps_in_file)
141 self%skip_coupler = .false.
142 if (f_conf%has(
"skip coupler file"))
then
143 call f_conf%get_or_die(
"skip coupler file",self%skip_coupler)
148 if (.not.f_conf%get(
"prepend files with date", self%prepend_date))
then
149 self%prepend_date = .true.
159 type(datetime),
intent(in) :: vdate
162 character(len=4) :: yyyy
163 character(len=2) :: mm, dd, hh, min, ss
172 self%filenames(n) = trim(self%filenames_conf(n))
175 if (index(self%filenames(n),
"%yyyy") > 0) &
176 self%filenames(n) =
replace_text(self%filenames(n),
'%yyyy',yyyy)
177 if (index(self%filenames(n),
"%mm" ) > 0) &
178 self%filenames(n) =
replace_text(self%filenames(n),
'%mm' ,mm )
179 if (index(self%filenames(n),
"%dd" ) > 0) &
180 self%filenames(n) =
replace_text(self%filenames(n),
'%dd' ,dd )
181 if (index(self%filenames(n),
"%hh" ) > 0) &
182 self%filenames(n) =
replace_text(self%filenames(n),
'%hh' ,hh )
183 if (index(self%filenames(n),
"%MM" ) > 0) &
184 self%filenames(n) =
replace_text(self%filenames(n),
'%MM' ,min )
185 if (index(self%filenames(n),
"%ss" ) > 0) &
186 self%filenames(n) =
replace_text(self%filenames(n),
'%ss' ,ss )
194 subroutine read_meta(self, geom, vdate, calendar_type, date_init)
198 type(datetime),
intent(inout) :: vdate
199 integer,
intent(inout) :: calendar_type
200 integer,
intent(inout) :: date_init(6)
203 integer(kind=c_int) :: idate, isecs
205 type(restart_file_type) :: restart_spec
207 real(kind=
kind_real),
allocatable,
dimension(:,:) :: grid_lat, grid_lon
212 if (trim(self%filenames(self%index_spec)) .ne.
"null" .and. trim(self%datapath) .ne.
"null")
then
214 allocate(grid_lat(geom%isc:geom%iec,geom%jsc:geom%jec))
215 allocate(grid_lon(geom%isc:geom%iec,geom%jsc:geom%jec))
217 idrst = register_restart_field( restart_spec, trim(self%filenames(self%index_spec)), &
218 "grid_latt", grid_lat, domain=geom%domain )
219 idrst = register_restart_field( restart_spec, trim(self%filenames(self%index_spec)), &
220 "grid_lont", grid_lon, domain=geom%domain )
222 call restore_state(restart_spec, directory=trim(adjustl(self%datapath)))
223 call free_restart_type(restart_spec)
225 if ((maxval(abs(grid_lat-
rad2deg*geom%grid_lat(geom%isc:geom%iec,geom%jsc:geom%jec)))>1.0e-4) &
226 .or.(maxval(abs(grid_lon-
rad2deg*geom%grid_lon(geom%isc:geom%iec,geom%jsc:geom%jec)))>1.0e-4))
then
227 call abor1_ftn(
"Grid in gridspec file does not match that in the geometry")
235 if (.not. self%skip_coupler)
then
236 open(101, file=trim(adjustl(self%datapath))//
'/'//self%filenames(self%index_cplr), form=
'formatted')
237 read(101,
'(i6)') calendar_type
238 read(101,
'(6i6)') date_init
239 read(101,
'(6i6)') date
241 idate=date(1)*10000+date(2)*100+date(3)
242 isecs=date(4)*3600+date(5)*60+date(6)
249 call datetime_from_ifs(vdate, idate, isecs)
262 type(restart_file_type) :: restart(numfiles)
263 logical :: rstflag(numfiles)
264 integer :: n, indexrst, position, var, idrst
267 integer :: indexof_ps, indexof_delp
268 real(kind=
kind_real),
allocatable :: delp(:,:,:)
278 havedelp =
has_field(fields,
'delp', indexof_delp)
282 do var = 1,
size(fields)
285 if (trim(fields(var)%fv3jedi_name) ==
'ps' .and. .not.self%ps_in_file)
then
288 deallocate(fields(indexof_ps)%array)
289 allocate(fields(indexof_ps)%array(geom%isc:geom%iec,geom%jsc:geom%jec,1:geom%npz))
290 fields(indexof_ps)%short_name =
'DELP'
293 select case (trim(fields(var)%io_file))
295 indexrst = self%index_core
297 indexrst = self%index_trcr
299 indexrst = self%index_sfcd
301 indexrst = self%index_sfcw
303 indexrst = self%index_phys
305 indexrst = self%index_orog
307 indexrst = self%index_cold
309 call abor1_ftn(
"fv3jedi_io_gfs_mod: Abort, field "//trim(fields(var)%short_name)//&
310 " does not have IOFile specified in the FieldSets metadata or it"&
311 " does not match options in gfs IO module")
316 if (fields(var)%staggerloc ==
'northsouth')
then
318 elseif (fields(var)%staggerloc ==
'eastwest')
then
323 rstflag(indexrst) = .true.
326 idrst = register_restart_field( restart(indexrst), trim(self%filenames(indexrst)), &
327 trim(fields(var)%short_name), fields(var)%array, &
328 domain=geom%domain, position=position )
336 call restore_state(restart(n), directory=trim(adjustl(self%datapath)))
337 call free_restart_type(restart(n))
343 if (indexof_ps > 0)
then
344 allocate(delp(geom%isc:geom%iec,geom%jsc:geom%jec,1:geom%npz))
345 if (.not. havedelp)
then
346 delp = fields(indexof_ps)%array
347 deallocate(fields(indexof_ps)%array)
348 allocate(fields(indexof_ps)%array(geom%isc:geom%iec,geom%jsc:geom%jec,1))
350 delp = fields(indexof_delp)%array
352 fields(indexof_ps)%array(:,:,1) = sum(delp,3)
353 fields(indexof_ps)%short_name =
'ps'
360 subroutine write(self, geom, fields, vdate, calendar_type, date_init)
366 type(datetime),
intent(in) :: vdate
367 integer,
intent(in) :: calendar_type
368 integer,
intent(in) :: date_init(6)
370 logical :: rstflag(numfiles)
371 integer :: n, indexrst, position, var, idrst, date(6)
372 integer(kind=c_int) :: idate, isecs
373 type(restart_file_type) :: restart(numfiles)
374 character(len=64) :: datefile
378 call datetime_to_ifs(vdate, idate, isecs)
379 date(1) = idate/10000
380 date(2) = idate/100 - date(1)*100
381 date(3) = idate - (date(1)*10000 + date(2)*100)
383 date(5) = (isecs - date(4)*3600)/60
384 date(6) = isecs - (date(4)*3600 + date(5)*60)
388 write(datefile,
'(I4,I0.2,I0.2,A1,I0.2,I0.2,I0.2,A1)') date(1),date(2),date(3),
".",&
389 date(4),date(5),date(6),
"."
391 if (self%prepend_date)
then
393 self%filenames(n) = trim(datefile)//trim(self%filenames(n))
401 do var = 1,
size(fields)
403 select case (trim(fields(var)%io_file))
405 indexrst = self%index_core
407 indexrst = self%index_trcr
409 indexrst = self%index_sfcd
411 indexrst = self%index_sfcw
413 indexrst = self%index_phys
415 indexrst = self%index_orog
417 indexrst = self%index_cold
419 call abor1_ftn(
"fv3jedi_io_gfs_mod: Abort, field "//trim(fields(var)%short_name)//&
420 " does not have IOFile specified in the FieldSets metadata")
425 if (fields(var)%staggerloc ==
'northsouth')
then
427 elseif (fields(var)%staggerloc ==
'eastwest')
then
432 rstflag(indexrst) = .true.
435 idrst = register_restart_field( restart(indexrst), trim(self%filenames(indexrst)), &
436 fields(var)%short_name, fields(var)%array, domain=geom%domain, &
437 position=position, longname = trim(fields(var)%long_name), &
438 units = trim(fields(var)%units) )
447 call save_restart(restart(n), directory=trim(adjustl(self%datapath)))
448 call free_restart_type(restart(n))
455 if (mpp_pe() == mpp_root_pe() .and. .not. self%skip_coupler)
then
456 open(101, file = trim(adjustl(self%datapath))//
'/'// &
457 trim(adjustl(self%filenames(self%index_cplr))), form=
'formatted')
458 write( 101,
'(i6,8x,a)' ) calendar_type, &
459 '(Calendar: no_calendar=0, thirty_day_months=1, julian=2, gregorian=3, noleap=4)'
460 write( 101,
'(6i6,8x,a)') date_init,
'Model start time: year, month, day, hour, minute, second'
461 write( 101,
'(6i6,8x,a)') date,
'Current model time: year, month, day, hour, minute, second'