15 use ensemble_manager_mod
, only : get_ensemble_id
16 use fms_mod
, only : write_version_number, open_namelist_file, check_nml_error
17 use fms_io_mod
, only : file_exist, field_size, read_data
18 use fms_io_mod
, only : field_exists => field_exist, io_infra_end=>fms_io_exit
19 use fms_io_mod
, only : get_filename_appendix => get_filename_appendix
20 use mpp_domains_mod
, only : domain1d, mpp_get_domain_components
21 use mpp_domains_mod
, only : center, corner, north_face=>north, east_face=>east
22 use mpp_io_mod
, only : open_file => mpp_open, close_file => mpp_close
23 use mpp_io_mod
, only : mpp_write_meta, write_field => mpp_write, mpp_get_info
24 use mpp_io_mod
, only : mpp_get_atts, mpp_get_axes, mpp_get_axis_data, axistype
25 use mpp_io_mod
, only : mpp_get_fields, fieldtype, axistype, flush_file => mpp_flush
26 use mpp_io_mod
, only : append_file=>mpp_append, ascii_file=>mpp_ascii
27 use mpp_io_mod
, only : multiple=>mpp_multi, netcdf_file=>mpp_netcdf
28 use mpp_io_mod
, only : overwrite_file=>mpp_overwr, readonly_file=>mpp_rdonly
29 use mpp_io_mod
, only : single_file=>mpp_single, writeonly_file=>mpp_wronly
30 use mpp_io_mod
, only : mpp_append, mpp_multi, mpp_overwr, mpp_netcdf, mpp_rdonly
31 use mpp_io_mod
, only : get_file_info=>mpp_get_info, get_file_atts=>mpp_get_atts
32 use mpp_io_mod
, only : get_file_fields=>mpp_get_fields, get_file_times=>mpp_get_times
33 use mpp_io_mod
, only : read_field=>mpp_read, io_infra_init=>mpp_io_init
37 implicit none ;
private 39 public :: close_file,
create_file, field_exists, field_size, fieldtype, get_filename_appendix
40 public ::
file_exists, flush_file, get_file_info, get_file_atts, get_file_fields
41 public :: get_file_times, open_file,
read_axis_data, read_data, read_field
44 public :: open_namelist_file, check_nml_error, io_infra_init, io_infra_end
45 public :: append_file, ascii_file, multiple, netcdf_file, overwrite_file
46 public :: readonly_file, single_file, writeonly_file
47 public :: center, corner, north_face, east_face
52 character(len=64) :: name
53 character(len=48) :: units
54 character(len=240) :: longname
55 character(len=8) :: hor_grid
56 character(len=8) :: z_grid
57 character(len=8) :: t_grid
58 character(len=64) :: cmor_field_name
59 character(len=64) :: cmor_units
65 module procedure file_exist
81 subroutine create_file(unit, filename, vars, novars, fields, threading, timeunit, G, dG, GV)
82 integer,
intent(out) :: unit
84 character(len=*),
intent(in) :: filename
85 type(
vardesc),
intent(in) :: vars(:)
86 integer,
intent(in) :: novars
87 type(fieldtype),
intent(inout) :: fields(:)
88 integer,
optional,
intent(in) :: threading
89 real,
optional,
intent(in) :: timeunit
101 logical :: use_lath, use_lonh, use_latq, use_lonq, use_time
102 logical :: use_layer, use_int, use_periodic
103 logical :: one_file, domain_set
104 type(axistype) :: axis_lath, axis_latq, axis_lonh, axis_lonq
105 type(axistype) :: axis_layer, axis_int, axis_time, axis_periodic
106 type(axistype) :: axes(4)
108 type(domain1d) :: x_domain, y_domain
109 integer :: numaxes, pack, thread, k
110 integer :: isg, ieg, jsg, jeg, IsgB, IegB, JsgB, JegB
111 integer :: var_periods, num_periods=0
112 real,
dimension(:),
allocatable :: period_val
113 real,
pointer,
dimension(:) :: &
114 gridLatT => null(), &
115 gridlatb => null(), &
116 gridlont => null(), gridlonb => null()
117 character(len=40) :: time_units, x_axis_units, y_axis_units
118 character(len=8) :: t_grid, t_grid_read
120 use_lath = .false. ; use_lonh = .false.
121 use_latq = .false. ; use_lonq = .false.
122 use_time = .false. ; use_periodic = .false.
123 use_layer = .false. ; use_int = .false.
126 if (
PRESENT(threading)) thread = threading
130 domain_set = .true. ; domain => g%Domain
131 gridlatt => g%gridLatT ; gridlatb => g%gridLatB
132 gridlont => g%gridLonT ; gridlonb => g%gridLonB
133 x_axis_units = g%x_axis_units ; y_axis_units = g%y_axis_units
134 isg = g%isg ; ieg = g%ieg ; jsg = g%jsg ; jeg = g%jeg
135 isgb = g%IsgB ; iegb = g%IegB ; jsgb = g%JsgB ; jegb = g%JegB
136 elseif (
present(dg))
then 137 domain_set = .true. ; domain => dg%Domain
138 gridlatt => dg%gridLatT ; gridlatb => dg%gridLatB
139 gridlont => dg%gridLonT ; gridlonb => dg%gridLonB
140 x_axis_units = dg%x_axis_units ; y_axis_units = dg%y_axis_units
141 isg = dg%isg ; ieg = dg%ieg ; jsg = dg%jsg ; jeg = dg%jeg
142 isgb = dg%IsgB ; iegb = dg%IegB ; jsgb = dg%JsgB ; jegb = dg%JegB
147 one_file = ((thread == single_file) .or. .not.domain%use_io_layout)
151 call open_file(unit, filename, mpp_overwr, mpp_netcdf, threading=thread)
153 call open_file(unit, filename, mpp_overwr, mpp_netcdf, domain=domain%mpp_domain)
158 select case (vars(k)%hor_grid)
159 case (
'h') ; use_lath = .true. ; use_lonh = .true.
160 case (
'q') ; use_latq = .true. ; use_lonq = .true.
161 case (
'u') ; use_lath = .true. ; use_lonq = .true.
162 case (
'v') ; use_latq = .true. ; use_lonh = .true.
163 case (
'T') ; use_lath = .true. ; use_lonh = .true.
164 case (
'Bu') ; use_latq = .true. ; use_lonq = .true.
165 case (
'Cu') ; use_lath = .true. ; use_lonq = .true.
166 case (
'Cv') ; use_latq = .true. ; use_lonh = .true.
169 call mom_error(warning,
"MOM_io create_file: "//trim(vars(k)%name)//&
170 " has unrecognized hor_grid "//trim(vars(k)%hor_grid))
172 select case (vars(k)%z_grid)
173 case (
'L') ; use_layer = .true.
174 case (
'i') ; use_int = .true.
177 call mom_error(fatal,
"MOM_io create_file: "//trim(vars(k)%name)//&
178 " has unrecognized z_grid "//trim(vars(k)%z_grid))
180 t_grid = adjustl(vars(k)%t_grid)
181 select case (t_grid(1:1))
182 case (
's',
'a',
'm') ; use_time = .true.
183 case (
'p') ; use_periodic = .true.
184 if (len_trim(t_grid(2:8)) <= 0)
call mom_error(fatal, &
185 "MOM_io create_file: No periodic axis length was specified in "//&
186 trim(vars(k)%t_grid) //
" in the periodic axes of variable "//&
187 trim(vars(k)%name)//
" in file "//trim(filename))
188 var_periods = -9999999
189 t_grid_read = adjustl(t_grid(2:8))
190 read(t_grid_read,*) var_periods
191 if (var_periods == -9999999)
call mom_error(fatal, &
192 "MOM_io create_file: Failed to read the number of periods from "//&
193 trim(vars(k)%t_grid) //
" in the periodic axes of variable "//&
194 trim(vars(k)%name)//
" in file "//trim(filename))
195 if (var_periods < 1)
call mom_error(fatal,
"MOM_io create_file: "//&
196 "variable "//trim(vars(k)%name)//
" in file "//trim(filename)//&
197 " uses a periodic time axis, and must have a positive "//&
198 "value for the number of periods in "//vars(k)%t_grid )
199 if ((num_periods > 0) .and. (var_periods /= num_periods)) &
200 call mom_error(fatal,
"MOM_io create_file: "//&
201 "Only one value of the number of periods can be used in the "//&
202 "create_file call for file "//trim(filename)//
". The second is "//&
203 "variable "//trim(vars(k)%name)//
" with t_grid "//vars(k)%t_grid )
205 num_periods = var_periods
208 call mom_error(warning,
"MOM_io create_file: "//trim(vars(k)%name)//&
209 " has unrecognized t_grid "//trim(vars(k)%t_grid))
213 if ((use_lath .or. use_lonh .or. use_latq .or. use_lonq))
then 214 if (.not.domain_set)
call mom_error(fatal,
"create_file: "//&
215 "An ocean_grid_type or dyn_horgrid_type is required to create a file with a horizontal coordinate.")
217 call mpp_get_domain_components(domain%mpp_domain, x_domain, y_domain)
219 if ((use_layer .or. use_int) .and. .not.
present(gv))
call mom_error(fatal, &
220 "create_file: A vertical grid type is required to create a file with a vertical coordinate.")
225 call mpp_write_meta(unit, axis_lath, name=
"lath", units=y_axis_units, longname=
"Latitude", &
226 cartesian=
'Y', domain = y_domain, data=gridlatt(jsg:jeg))
229 call mpp_write_meta(unit, axis_lonh, name=
"lonh", units=x_axis_units, longname=
"Longitude", &
230 cartesian=
'X', domain = x_domain, data=gridlont(isg:ieg))
233 call mpp_write_meta(unit, axis_latq, name=
"latq", units=y_axis_units, longname=
"Latitude", &
234 cartesian=
'Y', domain = y_domain, data=gridlatb(jsgb:jegb))
237 call mpp_write_meta(unit, axis_lonq, name=
"lonq", units=x_axis_units, longname=
"Longitude", &
238 cartesian=
'X', domain = x_domain, data=gridlonb(isgb:iegb))
241 call mpp_write_meta(unit, axis_layer, name=
"Layer", units=trim(gv%zAxisUnits), &
242 longname=
"Layer "//trim(gv%zAxisLongName), cartesian=
'Z', &
243 sense=1, data=gv%sLayer(1:gv%ke))
246 call mpp_write_meta(unit, axis_int, name=
"Interface", units=trim(gv%zAxisUnits), &
247 longname=
"Interface "//trim(gv%zAxisLongName), cartesian=
'Z', &
248 sense=1, data=gv%sInterface(1:gv%ke+1))
250 if (use_time)
then ;
if (
present(timeunit))
then 252 if (timeunit < 0.0)
then 254 else if ((timeunit >= 0.99) .and. (timeunit < 1.01))
then 255 time_units =
"seconds" 256 else if ((timeunit >= 3599.0) .and. (timeunit < 3601.0))
then 258 else if ((timeunit >= 86399.0) .and. (timeunit < 86401.0))
then 260 else if ((timeunit >= 3.0e7) .and. (timeunit < 3.2e7))
then 263 write(time_units,
'(es8.2," s")') timeunit
266 call mpp_write_meta(unit, axis_time, name=
"Time", units=time_units, longname=
"Time", cartesian=
'T')
268 call mpp_write_meta(unit, axis_time, name=
"Time", units=
"days", longname=
"Time",cartesian=
'T')
271 if (use_periodic)
then 272 if (num_periods <= 1)
call mom_error(fatal,
"MOM_io create_file: "//&
273 "num_periods for file "//trim(filename)//
" must be at least 1.")
275 allocate(period_val(num_periods))
276 do k=1,num_periods ; period_val(k) =
real(k) ; enddo
277 call mpp_write_meta(unit, axis_periodic, name=
"Period", units=
"nondimensional", &
278 longname=
"Periods for cyclical varaiables", cartesian=
't', data=period_val)
279 deallocate(period_val)
284 select case (vars(k)%hor_grid)
285 case (
'h') ; numaxes = 2 ; axes(1) = axis_lonh ; axes(2) = axis_lath
286 case (
'q') ; numaxes = 2 ; axes(1) = axis_lonq ; axes(2) = axis_latq
287 case (
'u') ; numaxes = 2 ; axes(1) = axis_lonq ; axes(2) = axis_lath
288 case (
'v') ; numaxes = 2 ; axes(1) = axis_lonh ; axes(2) = axis_latq
289 case (
'T') ; numaxes = 2 ; axes(1) = axis_lonh ; axes(2) = axis_lath
290 case (
'Bu') ; numaxes = 2 ; axes(1) = axis_lonq ; axes(2) = axis_latq
291 case (
'Cu') ; numaxes = 2 ; axes(1) = axis_lonq ; axes(2) = axis_lath
292 case (
'Cv') ; numaxes = 2 ; axes(1) = axis_lonh ; axes(2) = axis_latq
295 call mom_error(warning,
"MOM_io create_file: "//trim(vars(k)%name)//&
296 " has unrecognized hor_grid "//trim(vars(k)%hor_grid))
298 select case (vars(k)%z_grid)
299 case (
'L') ; numaxes = numaxes+1 ; axes(numaxes) = axis_layer
300 case (
'i') ; numaxes = numaxes+1 ; axes(numaxes) = axis_int
303 call mom_error(fatal,
"MOM_io create_file: "//trim(vars(k)%name)//&
304 " has unrecognized z_grid "//trim(vars(k)%z_grid))
306 t_grid = adjustl(vars(k)%t_grid)
307 select case (t_grid(1:1))
308 case (
's',
'a',
'm') ; numaxes = numaxes+1 ; axes(numaxes) = axis_time
309 case (
'p') ; numaxes = numaxes+1 ; axes(numaxes) = axis_periodic
312 call mom_error(warning,
"MOM_io create_file: "//trim(vars(k)%name)//&
313 " has unrecognized t_grid "//trim(vars(k)%t_grid))
317 call mpp_write_meta(unit, fields(k), axes(1:numaxes), vars(k)%name, vars(k)%units, &
318 vars(k)%longname, pack = pack)
321 if (use_lath)
call write_field(unit, axis_lath)
322 if (use_latq)
call write_field(unit, axis_latq)
323 if (use_lonh)
call write_field(unit, axis_lonh)
324 if (use_lonq)
call write_field(unit, axis_lonq)
325 if (use_layer)
call write_field(unit, axis_layer)
326 if (use_int)
call write_field(unit, axis_int)
327 if (use_periodic)
call write_field(unit, axis_periodic)
336 subroutine reopen_file(unit, filename, vars, novars, fields, threading, timeunit, G, dG, GV)
337 integer,
intent(out) :: unit
339 character(len=*),
intent(in) :: filename
340 type(
vardesc),
intent(in) :: vars(:)
341 integer,
intent(in) :: novars
342 type(fieldtype),
intent(inout) :: fields(:)
343 integer,
optional,
intent(in) :: threading
344 real,
optional,
intent(in) :: timeunit
357 character(len=200) :: check_name, mesg
358 integer :: length, ndim, nvar, natt, ntime, thread
359 logical :: exists, one_file, domain_set
362 if (
PRESENT(threading)) thread = threading
364 check_name = filename
365 length = len(trim(check_name))
366 if (check_name(length-2:length) /=
".nc") check_name = trim(check_name)//
".nc" 367 if (thread /= single_file) check_name = trim(check_name)//
".0000" 369 inquire(file=check_name,exist=exists)
371 if (.not.exists)
then 372 call create_file(unit, filename, vars, novars, fields, threading, timeunit, &
378 domain_set = .true. ; domain => g%Domain
379 elseif (
present(dg))
then 380 domain_set = .true. ; domain => dg%Domain
385 one_file = ((thread == single_file) .or. .not.domain%use_io_layout)
389 call open_file(unit, filename, mpp_append, mpp_netcdf, threading=thread)
391 call open_file(unit, filename, mpp_append, mpp_netcdf, domain=domain%mpp_domain)
395 call mpp_get_info(unit, ndim, nvar, natt, ntime)
398 write (mesg,*)
"Reopening file ",trim(filename),
" apparently had ",nvar,&
399 " variables. Clobbering and creating file with ",novars,
" instead." 401 call create_file(unit, filename, vars, novars, fields, threading, timeunit, g=g, gv=gv)
402 elseif (nvar /= novars)
then 403 write (mesg,*)
"Reopening file ",trim(filename),
" with ",novars,&
404 " variables instead of ",nvar,
"." 408 if (nvar>0)
call mpp_get_fields(unit,fields(1:nvar))
424 character(len=*),
intent(in) :: filename, axis_name
425 real,
dimension(:),
intent(out) :: var
427 integer :: i,len,unit, ndim, nvar, natt, ntime
428 logical :: axis_found
429 type(axistype),
allocatable :: axes(:)
430 type(axistype) :: time_axis
431 character(len=32) :: name, units
433 call open_file(unit, trim(filename), action=mpp_rdonly, form=mpp_netcdf, &
434 threading=mpp_multi, fileset=single_file)
437 call mpp_get_info(unit, ndim, nvar, natt, ntime)
442 call mpp_get_axes(unit, axes, time_axis)
446 call mpp_get_atts(axes(i), name=name,len=len,units=units)
447 if (name == axis_name)
then 449 call mpp_get_axis_data(axes(i),var)
454 if (.not.axis_found)
call mom_error(fatal,
"MOM_io read_axis_data: "//&
455 "Unable to find axis "//trim(axis_name)//
" in file "//trim(filename))
462 function num_timelevels(filename, varname, min_dims)
result(n_time)
463 character(len=*),
intent(in) :: filename
464 character(len=*),
intent(in) :: varname
466 integer,
optional,
intent(in) :: min_dims
472 character(len=200) :: msg
473 character(len=nf90_max_name) :: name
474 integer :: ncid, nvars, status, varid, ndims, n
475 integer,
allocatable :: varids(:)
476 integer,
dimension(nf90_max_var_dims) :: dimids
481 status = nf90_open(filename, nf90_nowrite, ncid)
482 if (status /= nf90_noerr)
then 483 call mom_error(warning,
"num_timelevels: "//&
484 " Difficulties opening "//trim(filename)//
" - "//&
485 trim(nf90_strerror(status)))
489 status = nf90_inquire(ncid, nvariables=nvars)
490 if (status /= nf90_noerr)
then 491 call mom_error(warning,
"num_timelevels: "//&
492 " Difficulties getting the number of variables in file "//&
493 trim(filename)//
" - "//trim(nf90_strerror(status)))
498 call mom_error(warning,
"num_timelevels: "//&
499 " There appear not to be any variables in "//trim(filename))
504 allocate(varids(nvars))
506 status = nf90_inq_varids(ncid, nvars, varids)
507 if (status /= nf90_noerr)
then 508 call mom_error(warning,
"num_timelevels: "//&
509 " Difficulties getting the variable IDs in file "//&
510 trim(filename)//
" - "//trim(nf90_strerror(status)))
511 deallocate(varids) ;
return 515 status = nf90_inquire_variable(ncid, varids(n), name=name)
516 if (status /= nf90_noerr)
then 517 call mom_error(warning,
"num_timelevels: "//&
518 " Difficulties getting a variable name in file "//&
519 trim(filename)//
" - "//trim(nf90_strerror(status)))
524 call mom_error(warning,
"num_timelevels: "//&
525 " Two variables match the case-insensitive name "//trim(varname)//&
526 " in file "//trim(filename)//
" - "//trim(nf90_strerror(status)))
528 varid = varids(n) ; found = .true.
536 call mom_error(warning,
"num_timelevels: "//&
537 " variable "//trim(varname)//
" was not found in file "//&
542 status = nf90_inquire_variable(ncid, varid, ndims = ndims)
543 if (status /= nf90_noerr)
then 544 call mom_error(warning,
"num_timelevels: "//&
545 trim(nf90_strerror(status))//
" Getting number of dimensions of "//&
546 trim(varname)//
" in "//trim(filename))
550 if (
present(min_dims))
then 551 if (ndims < min_dims-1)
then 552 write(msg,
'(I3)') min_dims
553 call mom_error(warning,
"num_timelevels: variable "//trim(varname)//&
554 " in file "//trim(filename)//
" has fewer than min_dims = "//trim(msg)//&
556 elseif (ndims == min_dims - 1)
then 561 status = nf90_inquire_variable(ncid, varid, dimids = dimids(1:ndims))
562 if (status /= nf90_noerr)
then 563 call mom_error(warning,
"num_timelevels: "//&
564 trim(nf90_strerror(status))//
" Getting last dimension ID for "//&
565 trim(varname)//
" in "//trim(filename))
569 status = nf90_inquire_dimension(ncid, dimids(ndims), len=n_time)
570 if (status /= nf90_noerr)
call mom_error(warning,
"num_timelevels: "//&
571 trim(nf90_strerror(status))//
" Getting number of time levels of "//&
572 trim(varname)//
" in "//trim(filename))
583 function var_desc(name, units, longname, hor_grid, z_grid, t_grid, &
584 cmor_field_name, cmor_units, conversion, caller)
result(vd)
585 character(len=*),
intent(in) :: name
586 character(len=*),
optional,
intent(in) :: units
587 character(len=*),
optional,
intent(in) :: longname
588 character(len=*),
optional,
intent(in) :: hor_grid
589 character(len=*),
optional,
intent(in) :: z_grid
590 character(len=*),
optional,
intent(in) :: t_grid
591 character(len=*),
optional,
intent(in) :: cmor_field_name
592 character(len=*),
optional,
intent(in) :: cmor_units
593 real ,
optional,
intent(in) :: conversion
595 character(len=*),
optional,
intent(in) :: caller
598 character(len=120) :: cllr
600 if (
present(caller)) cllr = trim(caller)
604 vd%longname =
"" ; vd%units =
"" 605 vd%hor_grid =
'h' ; vd%z_grid =
'L' ; vd%t_grid =
's' 607 vd%cmor_field_name =
"" 611 call modify_vardesc(vd, units=units, longname=longname, hor_grid=hor_grid, &
612 z_grid=z_grid, t_grid=t_grid, &
613 cmor_field_name=cmor_field_name,cmor_units=cmor_units, &
614 conversion=conversion, caller=cllr)
621 subroutine modify_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid,&
622 cmor_field_name, cmor_units, conversion, caller)
624 character(len=*),
optional,
intent(in) :: name
625 character(len=*),
optional,
intent(in) :: units
626 character(len=*),
optional,
intent(in) :: longname
627 character(len=*),
optional,
intent(in) :: hor_grid
628 character(len=*),
optional,
intent(in) :: z_grid
629 character(len=*),
optional,
intent(in) :: t_grid
630 character(len=*),
optional,
intent(in) :: cmor_field_name
631 character(len=*),
optional,
intent(in) :: cmor_units
632 real ,
optional,
intent(in) :: conversion
634 character(len=*),
optional,
intent(in) :: caller
636 character(len=120) :: cllr
638 if (
present(caller)) cllr = trim(caller)
643 "vd%longname of "//trim(vd%name), cllr)
645 "vd%units of "//trim(vd%name), cllr)
647 "vd%hor_grid of "//trim(vd%name), cllr)
649 "vd%z_grid of "//trim(vd%name), cllr)
651 "vd%t_grid of "//trim(vd%name), cllr)
653 if (
present(cmor_field_name))
call safe_string_copy(cmor_field_name, vd%cmor_field_name, &
654 "vd%cmor_field_name of "//trim(vd%name), cllr)
656 "vd%cmor_units of "//trim(vd%name), cllr)
662 subroutine query_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, &
663 cmor_field_name, cmor_units, conversion, caller)
665 character(len=*),
optional,
intent(out) :: name
666 character(len=*),
optional,
intent(out) :: units
667 character(len=*),
optional,
intent(out) :: longname
668 character(len=*),
optional,
intent(out) :: hor_grid
669 character(len=*),
optional,
intent(out) :: z_grid
670 character(len=*),
optional,
intent(out) :: t_grid
671 character(len=*),
optional,
intent(out) :: cmor_field_name
672 character(len=*),
optional,
intent(out) :: cmor_units
673 real ,
optional,
intent(out) :: conversion
675 character(len=*),
optional,
intent(in) :: caller
678 character(len=120) :: cllr
680 if (
present(caller)) cllr = trim(caller)
683 "vd%name of "//trim(vd%name), cllr)
685 "vd%longname of "//trim(vd%name), cllr)
687 "vd%units of "//trim(vd%name), cllr)
689 "vd%hor_grid of "//trim(vd%name), cllr)
691 "vd%z_grid of "//trim(vd%name), cllr)
693 "vd%t_grid of "//trim(vd%name), cllr)
695 if (
present(cmor_field_name))
call safe_string_copy(vd%cmor_field_name, cmor_field_name, &
696 "vd%cmor_field_name of "//trim(vd%name), cllr)
698 "vd%cmor_units of "//trim(vd%name), cllr)
705 character(len=*),
intent(in) :: str1
706 character(len=*),
intent(out) :: str2
707 character(len=*),
optional,
intent(in) :: fieldnm, caller
709 if (len(trim(str1)) > len(str2))
then 710 if (
present(fieldnm) .and.
present(caller))
then 711 call mom_error(fatal, trim(caller)//
" attempted to copy the overly long"//&
712 " string "//trim(str1)//
" into "//trim(fieldnm))
714 call mom_error(fatal,
"safe_string_copy: The string "//trim(str1)//&
715 " is longer than its intended target.")
723 function ensembler(name, ens_no_in)
result(en_nm)
724 character(len=*),
intent(in) :: name
725 integer,
optional,
intent(in) :: ens_no_in
726 character(len=len(name)) :: en_nm
732 character(len=len(name)) :: tmp
733 character(10) :: ens_num_char
734 character(3) :: code_str
739 if (index(name,
"%") == 0)
return 741 if (
present(ens_no_in))
then 744 ens_no = get_ensemble_id()
747 write(ens_num_char,
'(I10)') ens_no ; ens_num_char = adjustl(ens_num_char)
749 is = index(en_nm,
"%E")
751 if (len(en_nm) < len(trim(en_nm)) + len(trim(ens_num_char)) - 2) &
752 call mom_error(fatal,
"MOM_io ensembler: name "//trim(name)// &
753 " is not long enough for %E expansion for ens_no "//trim(ens_num_char))
754 tmp = en_nm(1:is-1)//trim(ens_num_char)//trim(en_nm(is+2:))
758 if (index(name,
"%") == 0)
return 760 write(ens_num_char,
'(I10.10)') ens_no
762 write(code_str,
'("%",I1,"E")') n
764 is = index(en_nm,code_str)
766 if (ens_no < 10**n)
then 767 if (len(en_nm) < len(trim(en_nm)) + n-3)
call mom_error(fatal, &
768 "MOM_io ensembler: name "//trim(name)//
" is not long enough for %E expansion.")
769 tmp = en_nm(1:is-1)//trim(ens_num_char(11-n:10))//trim(en_nm(is+3:))
771 call mom_error(fatal,
"MOM_io ensembler: Ensemble number is too large "//&
772 "to be encoded with "//code_str//
" in "//trim(name))
782 character(len=*),
intent(in) :: file_name
788 logical :: MOM_file_exists
790 mom_file_exists = file_exist(file_name, mom_domain%mpp_domain)
798 character(len=*),
intent(in) :: filename, fieldname
799 real,
dimension(:),
intent(inout) :: data
801 call read_data(filename, fieldname, data)
811 character(len=*),
intent(in) :: filename, fieldname
812 real,
dimension(:,:),
intent(inout) :: data
814 integer,
optional,
intent(in) :: timelevel, position
816 call read_data(filename, fieldname,
data, mom_domain%mpp_domain, &
817 timelevel=timelevel, position=position)
827 character(len=*),
intent(in) :: filename, fieldname
828 real,
dimension(:,:,:),
intent(inout) :: data
830 integer,
optional,
intent(in) :: timelevel, position
832 call read_data(filename, fieldname,
data, mom_domain%mpp_domain, &
833 timelevel=timelevel, position=position)
844 #include "version_variable.h" 845 character(len=40) :: mdl =
"MOM_io" subroutine, public mom_io_init(param_file)
Initialize the MOM_io module.
subroutine, public read_axis_data(filename, axis_name, var)
character(len=len(name)) function, public ensembler(name, ens_no_in)
Returns a name with "%#E" or "%E" replaced with the ensemble member number.
type(vardesc) function, public var_desc(name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
Returns a vardesc type whose elements have been filled with the provided fields. The argument name is...
Ocean grid type. See mom_grid for details.
Provides the ocean grid type.
subroutine safe_string_copy(str1, str2, fieldnm, caller)
Copies a string.
subroutine mom_read_data_3d(filename, fieldname, data, MOM_Domain, timelevel, position)
This function uses the fms_io function read_data to read a distributed 2-D data field named "fieldnam...
This module contains I/O framework code.
subroutine mom_read_data_1d(filename, fieldname, data)
This function uses the fms_io function read_data to read 1-D data field named "fieldname" from file "...
character(len=len(input_string)) function, public lowercase(input_string)
character(len=len(dir)+2) function, public slasher(dir)
Returns a directory name that is terminated with a "/" or "./" if the argument is an empty string...
subroutine mom_read_data_2d(filename, fieldname, data, MOM_Domain, timelevel, position)
This function uses the fms_io function read_data to read a distributed 2-D data field named "fieldnam...
logical function mom_file_exists(file_name, MOM_Domain)
Returns true if the named file or its domain-decomposed variant exists.
Type for describing a variable, typically a tracer.
The MOM_domain_type contains information about the domain decompositoin.
subroutine, public query_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
This routine queries vardesc.
subroutine, public reopen_file(unit, filename, vars, novars, fields, threading, timeunit, G, dG, GV)
This routine opens an existing NetCDF file for output. If it does not find the file, a new file is created. It also sets up structures that describe this file and the variables that will later be written to this file.
subroutine, public create_file(unit, filename, vars, novars, fields, threading, timeunit, G, dG, GV)
Routine creates a new NetCDF file. It also sets up structures that describe this file and variables t...
subroutine, public mom_error(level, message, all_print)
subroutine, public modify_vardesc(vd, name, units, longname, hor_grid, z_grid, t_grid, cmor_field_name, cmor_units, conversion, caller)
This routine modifies the named elements of a vardesc type. All arguments are optional, except the vardesc type to be modified.
integer function, public num_timelevels(filename, varname, min_dims)
This function determines how many time levels a variable has.