28 #ifndef MAX_NUM_RESTART_VARS_
29 #define MAX_NUM_RESTART_VARS_ 250
40 integer,
parameter,
public :: default_deflate_level = 0
41 integer,
parameter :: variable_missing = -1
42 integer,
parameter :: dimension_missing = -1
43 integer,
parameter,
public :: no_unlimited_dimension = -1
44 character(len=1),
parameter :: missing_path =
""
45 integer,
parameter :: missing_ncid = -1
46 integer,
parameter :: missing_rank = -1
47 integer,
parameter,
public :: define_mode = 0
48 integer,
parameter,
public :: data_mode = 1
49 integer,
parameter,
public :: max_num_restart_vars = max_num_restart_vars_
50 integer,
parameter,
public :: unlimited = nf90_unlimited
51 integer,
parameter :: dimension_not_found = 0
52 integer,
parameter,
public :: max_num_compressed_dims = 10
68 integer,
dimension(:),
allocatable :: indices
70 integer,
dimension(:),
allocatable :: global_size
71 integer,
dimension(:),
allocatable :: pelist
77 real(kind=r4_kind),
dimension(:,:),
allocatable :: globaldata2d_r4
78 real(kind=r4_kind),
dimension(:,:,:),
allocatable :: globaldata3d_r4
79 real(kind=r8_kind),
dimension(:,:),
allocatable :: globaldata2d_r8
80 real(kind=r8_kind),
dimension(:,:,:),
allocatable :: globaldata3d_r8
81 character(len=32) :: chksum
82 logical :: data_on_file_root
89 character(len=256) :: varname
90 class(*),
pointer :: data0d => null()
91 class(*),
dimension(:),
pointer :: data1d => null()
92 class(*),
dimension(:,:),
pointer :: data2d => null()
93 class(*),
dimension(:,:,:),
pointer :: data3d => null()
94 class(*),
dimension(:,:,:,:),
pointer :: data4d => null()
95 class(*),
dimension(:,:,:,:,:),
pointer :: data5d => null()
98 logical :: is_bc_variable
105 character(len=256) :: dimname
106 integer,
dimension(:),
allocatable :: npes_corner
108 integer,
dimension(:),
allocatable :: npes_nelems
117 integer,
dimension(5) :: xlen
118 integer,
dimension(5) :: ylen
119 integer,
dimension(5) :: zlen
120 integer,
dimension(3) :: cur_dim_len
129 character(len=FMS_PATH_LEN) :: path
130 logical :: is_readonly
132 character(len=256) :: nc_format
133 logical :: is_netcdf4
134 integer,
dimension(:),
allocatable :: pelist
139 logical :: is_restart
141 logical :: mode_is_append
142 logical,
allocatable :: is_open
145 integer :: num_restart_vars
147 integer :: num_compressed_dims
148 logical :: is_diskless
149 character (len=20) :: time_name
152 logical :: use_collective = .false.
168 logical :: has_missing
169 real(kind=r8_kind) :: fill_val
170 real(kind=r8_kind) :: min_val
171 real(kind=r8_kind) :: max_val
172 real(kind=r8_kind) :: missing_val
236 public :: get_variable_sense
237 public :: get_variable_missing
238 public :: get_variable_units
239 public :: get_time_calendar
244 public :: set_fileobj_time_name
345 subroutine netcdf_io_init (chksz, header_buffer_val, netcdf_default_format, deflate_level, shuffle)
346 integer,
intent(in) :: chksz
347 character (len = 10),
intent(in) :: netcdf_default_format
348 integer,
intent(in) :: header_buffer_val
349 integer,
intent(in) :: deflate_level
351 logical,
intent(in) :: shuffle
361 elseif (
string_compare(netcdf_default_format,
"classic", .true.))
then
364 elseif (
string_compare(netcdf_default_format,
"netcdf4", .true.))
then
369 call error(
"unrecognized netcdf file format "//trim(netcdf_default_format)// &
370 '. The acceptable values are "64bit", "classic", "netcdf4". Check fms2_io_nml: netcdf_default_format')
379 integer,
intent(in) :: err
380 character(len=*),
intent(in) :: msg
382 character(len=80) :: buf
384 if (err .ne. nf90_noerr)
then
385 buf = nf90_strerror(err)
386 call error(trim(buf)//
": "//trim(msg))
395 integer,
intent(in) :: ncid
396 integer,
intent(in) :: mode
400 if (mode .eq. define_mode)
then
401 err = nf90_redef(ncid)
402 if (err .eq. nf90_eindefine .or. err .eq. nf90_eperm)
then
405 elseif (mode .eq. data_mode)
then
406 if (
fms2_header_buffer_val == -1)
call error(
"set_netcdf_mode: fms2_header_buffer_val not set, call fms2_io_init")
408 if (err .eq. nf90_enotindefine .or. err .eq. nf90_eperm)
then
412 call error(
"mode must be either define_mode or data_mode.")
424 integer,
intent(in) :: ncid
425 character(len=*),
intent(in) :: dimension_name
426 character(len=*),
intent(in) :: msg
427 logical,
intent(in),
optional :: allow_failure
435 err = nf90_inq_dimid(ncid, trim(dimension_name), dimid)
436 if (
present(allow_failure))
then
437 if (allow_failure .and. err .eq. nf90_ebaddim)
then
438 dimid = dimension_missing
452 integer,
intent(in) :: ncid
453 character(len=*),
intent(in) :: variable_name
454 character(len=*),
intent(in) :: msg
455 logical,
intent(in),
optional :: allow_failure
463 err = nf90_inq_varid(ncid, trim(variable_name), varid)
464 if (
present(allow_failure))
then
465 if (allow_failure .and. err .eq. nf90_enotvar)
then
466 varid = variable_missing
480 integer,
intent(in) :: ncid
481 integer,
intent(in) :: varid
482 character(len=*),
intent(in) :: attribute_name
483 character(len=*),
intent(in),
optional :: msg
485 logical :: att_exists
489 err = nf90_inquire_attribute(ncid, varid, trim(attribute_name))
490 if (err .eq. nf90_enotatt)
then
505 integer,
intent(in) :: ncid
506 integer,
intent(in) :: varid
507 character(len=*),
intent(in) :: attname
508 character(len=*),
intent(in),
optional :: msg
514 err = nf90_inquire_attribute(ncid, varid, attname, xtype=xtype)
525 integer,
intent(in) :: ncid
526 integer,
intent(in) :: varid
527 character(len=*),
intent(in),
optional :: msg
533 err = nf90_inquire_variable(ncid, varid, xtype=xtype)
540 function netcdf_file_open(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename) &
544 character(len=*),
intent(in) :: path
545 character(len=*),
intent(in) :: mode
548 character(len=*),
intent(in),
optional :: nc_format
556 integer,
dimension(:),
intent(in),
optional :: pelist
561 logical,
intent(in),
optional :: is_restart
564 logical,
intent(in),
optional :: dont_add_res_to_filename
568 integer :: nc_format_param
572 character(len=FMS_PATH_LEN) :: buf
573 character(len=FMS_PATH_LEN) :: buf2
575 logical :: dont_add_res
577 if (
allocated(fileobj%is_open))
then
578 if (fileobj%is_open)
then
586 if (
present(is_restart))
then
589 dont_add_res = .false.
590 if (
present(dont_add_res_to_filename))
then
591 dont_add_res = dont_add_res_to_filename
594 if (is_res .and. .not. dont_add_res)
then
597 call string_copy(buf, trim(path))
604 call string_copy(buf2, trim(buf))
611 if (.not. success)
then
617 call string_copy(fileobj%path, trim(buf2))
618 if (
present(pelist))
then
619 allocate(fileobj%pelist(
size(pelist)))
620 fileobj%pelist(:) = pelist(:)
622 allocate(fileobj%pelist(1))
623 fileobj%pelist(1) =
mpp_pe()
625 fileobj%io_root = fileobj%pelist(1)
626 fileobj%is_root =
mpp_pe() .eq. fileobj%io_root
628 fileobj%is_netcdf4 = .false.
629 if (
fms2_ncchksz == -1)
call error(
"netcdf_file_open:: fms2_ncchksz not set, call fms2_io_init")
630 if (
fms2_nc_format_param == -1)
call error(
"netcdf_file_open:: fms2_nc_format_param not set, call fms2_io_init")
632 if (
present(nc_format))
then
634 nc_format_param = nf90_64bit_offset
636 nc_format_param = nf90_classic_model
638 fileobj%is_netcdf4 = .true.
639 nc_format_param = nf90_netcdf4
641 call error(
"unrecognized netcdf file format: '"//trim(nc_format)//
"' for file:"//trim(fileobj%path)//&
642 &
"Check your open_file call, the acceptable values are 64bit, classic, netcdf4")
644 call string_copy(fileobj%nc_format, nc_format)
652 if (fileobj%is_root .and. .not.(fileobj%use_collective))
then
654 err = nf90_open(trim(fileobj%path), nf90_nowrite, fileobj%ncid, chunksize=
fms2_ncchksz)
656 err = nf90_open(trim(fileobj%path), nf90_write, fileobj%ncid, chunksize=
fms2_ncchksz)
658 err = nf90_create(trim(fileobj%path), ior(nf90_noclobber, nc_format_param), fileobj%ncid, chunksize=
fms2_ncchksz)
660 err = nf90_create(trim(fileobj%path), ior(nf90_clobber, nc_format_param), fileobj%ncid, chunksize=
fms2_ncchksz)
662 call error(
"unrecognized file mode: '"//trim(mode)//
"' for file:"//trim(fileobj%path)//&
663 &
"Check your open_file call, the acceptable values are read, append, write, overwrite")
666 elseif(fileobj%use_collective .and. (fileobj%tile_comm /=
mpp_comm_null))
then
671 err = nf90_open(trim(fileobj%path), ior(nf90_nowrite, nf90_mpiio), fileobj%ncid, &
673 if(err /= nf90_noerr)
then
674 err = nf90_open(trim(fileobj%path), nf90_nowrite, fileobj%ncid)
675 err = nf90_get_att(fileobj%ncid, nf90_global,
"_IsNetcdf4", netcdf4)
676 err = nf90_close(fileobj%ncid)
677 if(netcdf4 /= 1)
then
678 call mpp_error(note,
"netcdf_file_open: Open for collective read failed because the file is not &
679 netCDF-4 format."// &
680 " Falling back to parallel independent for file "// trim(fileobj%path))
682 err = nf90_open(trim(fileobj%path), nf90_nowrite, fileobj%ncid, chunksize=
fms2_ncchksz)
685 call mpp_error(fatal,
"netcdf_file_open: Attempt to create a file for collective write"// &
686 " This feature is not implemented"// trim(fileobj%path))
690 call mpp_error(fatal,
"netcdf_file_open: Attempt to create a file for collective overwrite"// &
691 " This feature is not implemented"// trim(fileobj%path))
695 call error(
"unrecognized file mode: '"//trim(mode)//
"' for file:"//trim(fileobj%path)//&
696 &
"Check your open_file call, the acceptable values are read, append, write, overwrite")
700 fileobj%ncid = missing_ncid
703 fileobj%is_diskless = .false.
706 fileobj%is_restart = is_res
707 if (fileobj%is_restart)
then
708 allocate(fileobj%restart_vars(max_num_restart_vars))
709 fileobj%num_restart_vars = 0
713 allocate(fileobj%compressed_dims(max_num_compressed_dims))
714 fileobj%num_compressed_dims = 0
716 if (.not.
allocated(fileobj%is_open))
allocate(fileobj%is_open)
717 fileobj%is_open = .true.
719 fileobj%bc_dimensions%xlen = 0
720 fileobj%bc_dimensions%ylen = 0
721 fileobj%bc_dimensions%zlen = 0
722 fileobj%bc_dimensions%cur_dim_len = 0
735 if (fileobj%is_root)
then
736 err = nf90_close(fileobj%ncid)
739 if (
allocated(fileobj%is_open)) fileobj%is_open = .false.
740 fileobj%path = missing_path
741 fileobj%ncid = missing_ncid
742 if (
allocated(fileobj%pelist))
then
743 deallocate(fileobj%pelist)
745 fileobj%io_root = missing_rank
746 fileobj%is_root = .false.
747 if (
allocated(fileobj%restart_vars))
then
748 deallocate(fileobj%restart_vars)
750 fileobj%is_restart = .false.
751 fileobj%num_restart_vars = 0
752 do i = 1, fileobj%num_compressed_dims
753 if (
allocated(fileobj%compressed_dims(i)%npes_corner))
then
754 deallocate(fileobj%compressed_dims(i)%npes_corner)
756 if (
allocated(fileobj%compressed_dims(i)%npes_nelems))
then
757 deallocate(fileobj%compressed_dims(i)%npes_nelems)
760 if (
allocated(fileobj%compressed_dims))
then
761 deallocate(fileobj%compressed_dims)
773 character(len=*),
intent(in) :: dim_name
778 dindex = dimension_not_found
779 do i = 1, fileobj%num_compressed_dims
780 if (
string_compare(fileobj%compressed_dims(i)%dimname, dim_name))
then
794 character(len=*),
intent(in) :: dim_name
795 integer,
dimension(:),
intent(in) :: npes_corner
797 integer,
dimension(:),
intent(in) :: npes_nelems
804 call error(
"dimension "//trim(dim_name)//
" already registered" &
805 //
" to file "//trim(fileobj%path)//
".")
807 fileobj%num_compressed_dims = fileobj%num_compressed_dims + 1
808 n = fileobj%num_compressed_dims
809 if (n .gt. max_num_compressed_dims)
then
810 call error(
"number of compressed dimensions exceeds limit.")
812 call string_copy(fileobj%compressed_dims(n)%dimname, dim_name)
813 if (
size(npes_corner) .ne.
size(fileobj%pelist) .or. &
814 size(npes_nelems) .ne.
size(fileobj%pelist))
then
815 call error(
"incorrect size for input npes_corner or npes_nelems arrays.")
817 allocate(fileobj%compressed_dims(n)%npes_corner(
size(fileobj%pelist)))
818 fileobj%compressed_dims(n)%npes_corner(:) = npes_corner(:)
819 allocate(fileobj%compressed_dims(n)%npes_nelems(
size(fileobj%pelist)))
820 fileobj%compressed_dims(n)%npes_nelems(:) = npes_nelems(:)
821 fileobj%compressed_dims(n)%nelems = sum(fileobj%compressed_dims(n)%npes_nelems)
829 character(len=*),
intent(in) :: dimension_name
830 integer,
intent(in) :: dimension_length
832 integer,
dimension(:),
allocatable :: npes_start
833 integer,
dimension(:),
allocatable :: npes_count
839 allocate(npes_start(
size(fileobj%pelist)))
840 allocate(npes_count(
size(fileobj%pelist)))
842 call mpp_gather((/dimension_length/),npes_count,pelist=fileobj%pelist)
845 do i = 1,
size(fileobj%pelist)-1
846 npes_start(i+1) = npes_start(i) + npes_count(i)
851 if (fileobj%is_root .and. .not. fileobj%is_readonly)
then
853 err = nf90_def_dim(fileobj%ncid, trim(dimension_name), unlimited, dimid)
854 call check_netcdf_code(err,
"Netcdf_add_dimension: file:"//trim(fileobj%path)//
" dimension name:"// &
855 & trim(dimension_name))
864 character(len=*),
intent(in) :: dimension_name
865 integer,
intent(in) :: dimension_length
866 logical,
intent(in),
optional :: is_compressed
872 integer,
dimension(:),
allocatable :: npes_start
873 integer,
dimension(:),
allocatable :: npes_count
878 dim_len = dimension_length
879 if (
present(is_compressed))
then
880 if (is_compressed)
then
882 allocate(npes_start(
size(fileobj%pelist)))
883 allocate(npes_count(
size(fileobj%pelist)))
884 do i = 1,
size(fileobj%pelist)
885 if (fileobj%pelist(i) .eq.
mpp_pe())
then
886 npes_count(i) = dim_len
888 call mpp_recv(npes_count(i), fileobj%pelist(i), block=.false.)
889 call mpp_send(dim_len, fileobj%pelist(i))
895 do i = 1,
size(fileobj%pelist)-1
896 npes_start(i+1) = npes_start(i) + npes_count(i)
900 dim_len = sum(npes_count)
903 if (fileobj%is_root .and. .not. fileobj%is_readonly)
then
905 err = nf90_def_dim(fileobj%ncid, trim(dimension_name), dim_len, dimid)
906 call check_netcdf_code(err,
"Netcdf_add_dimension: file:"//trim(fileobj%path)//
" dimension name:"// &
907 & trim(dimension_name))
914 npes_corner, npes_nelems)
917 character(len=*),
intent(in) :: dimension_name
918 integer,
dimension(:),
intent(in) :: npes_corner
920 integer,
dimension(:),
intent(in) :: npes_nelems
928 dsize = sum(npes_nelems)
929 if (fileobj%is_readonly)
then
931 if (fdim_size .ne. dsize)
then
932 call error(
"dimension "//trim(dimension_name)//
" does not match" &
933 //
" the size of the associated compressed axis.")
945 character(len=*),
intent(in) :: variable_name
946 character(len=*),
intent(in) :: variable_type
949 character(len=*),
dimension(:),
intent(in),
optional :: dimensions
950 integer,
optional,
intent(in) :: chunksizes(:)
954 integer,
dimension(:),
allocatable :: dimids
958 character(len=200) :: append_error_msg
960 append_error_msg =
"netcdf_add_variable: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name)
962 if (fileobj%is_root)
then
967 if ( .not. fileobj%is_netcdf4)
call error(trim(fileobj%path)//&
968 &
": 64 bit integers are only supported with 'netcdf4' file format"//&
969 &
". Set netcdf_default_format='netcdf4' in the fms2_io namelist OR "//&
970 &
"add nc_format='netcdf4' to your open_file call")
978 if (.not.
present(dimensions))
then
979 call error(
"String variables require a string length dimension:"//trim(append_error_msg))
982 call error(
"Unsupported variable type:"//trim(append_error_msg))
984 if (
present(dimensions))
then
985 allocate(dimids(
size(dimensions)))
986 do i = 1,
size(dimids)
987 dimids(i) =
get_dimension_id(fileobj%ncid, trim(dimensions(i)),msg=append_error_msg)
989 if (fileobj%is_netcdf4)
then
990 err = nf90_def_var(fileobj%ncid, trim(variable_name), vtype, dimids, varid, &
994 &
call mpp_error(note,
"Not able to use deflate_level or chunksizes if not using netcdf4"// &
996 err = nf90_def_var(fileobj%ncid, trim(variable_name), vtype, dimids, varid)
1000 err = nf90_def_var(fileobj%ncid, trim(variable_name), vtype, varid)
1011 result(compressed_dimension_index)
1014 character(len=*),
intent(in) :: variable_name
1015 logical,
intent(in),
optional :: broadcast
1021 integer,
dimension(2) :: compressed_dimension_index
1024 character(len=nf90_max_name),
dimension(:),
allocatable :: dim_names
1028 compressed_dimension_index = dimension_not_found
1029 if (fileobj%is_root)
then
1031 if (ndims .gt. 0)
then
1032 allocate(dim_names(ndims))
1034 do i = 1,
size(dim_names)
1036 if (j .ne. dimension_not_found)
then
1037 compressed_dimension_index(1) = i
1038 compressed_dimension_index(2) = j
1042 deallocate(dim_names)
1045 if (
present(broadcast))
then
1046 if (.not. broadcast)
then
1050 call mpp_broadcast(compressed_dimension_index(1), fileobj%io_root, pelist=fileobj%pelist)
1051 call mpp_broadcast(compressed_dimension_index(2), fileobj%io_root, pelist=fileobj%pelist)
1060 character(len=*),
intent(in) :: variable_name
1064 if (.not. fileobj%is_restart)
then
1065 call error(
"file "//trim(fileobj%path)//
" is not a restart file.")
1067 do i = 1, fileobj%num_restart_vars
1068 if (
string_compare(fileobj%restart_vars(i)%varname, variable_name, .true.))
then
1069 call error(
"variable "//trim(variable_name)//
" has already" &
1070 //
" been added to restart file "//trim(fileobj%path)//
".")
1073 fileobj%num_restart_vars = fileobj%num_restart_vars + 1
1074 if (fileobj%num_restart_vars .gt. max_num_restart_vars)
then
1075 call error(
"Number of restart variables exceeds limit.")
1077 call string_copy(fileobj%restart_vars(fileobj%num_restart_vars)%varname, &
1087 integer,
intent(in),
optional :: unlim_dim_level
1092 if (.not. fileobj%is_restart)
then
1093 call error(
"write_restart:: file "//trim(fileobj%path)//
" is not a restart file. &
1094 &Be sure the file was opened with is_restart=.true.")
1096 do i = 1, fileobj%num_restart_vars
1097 if (
associated(fileobj%restart_vars(i)%data0d))
then
1099 fileobj%restart_vars(i)%data0d, &
1100 unlim_dim_level=unlim_dim_level)
1101 elseif (
associated(fileobj%restart_vars(i)%data1d))
then
1103 fileobj%restart_vars(i)%data1d, &
1104 unlim_dim_level=unlim_dim_level)
1105 elseif (
associated(fileobj%restart_vars(i)%data2d))
then
1107 fileobj%restart_vars(i)%data2d, &
1108 unlim_dim_level=unlim_dim_level)
1109 elseif (
associated(fileobj%restart_vars(i)%data3d))
then
1111 fileobj%restart_vars(i)%data3d, &
1112 unlim_dim_level=unlim_dim_level)
1113 elseif (
associated(fileobj%restart_vars(i)%data4d))
then
1115 fileobj%restart_vars(i)%data4d, &
1116 unlim_dim_level=unlim_dim_level)
1118 call error(
"this branch should not be reached.")
1129 integer,
intent(in),
optional :: unlim_dim_level
1134 if (.not. fileobj%is_restart)
then
1135 call error(
"read_restart:: file "//trim(fileobj%path)//
" is not a restart file. &
1136 &Be sure the file was opened with is_restart=.true.")
1138 do i = 1, fileobj%num_restart_vars
1139 if (
associated(fileobj%restart_vars(i)%data0d))
then
1141 fileobj%restart_vars(i)%data0d, &
1142 unlim_dim_level=unlim_dim_level, &
1144 elseif (
associated(fileobj%restart_vars(i)%data1d))
then
1146 fileobj%restart_vars(i)%data1d, &
1147 unlim_dim_level=unlim_dim_level, &
1149 elseif (
associated(fileobj%restart_vars(i)%data2d))
then
1151 fileobj%restart_vars(i)%data2d, &
1152 unlim_dim_level=unlim_dim_level, &
1154 elseif (
associated(fileobj%restart_vars(i)%data3d))
then
1156 fileobj%restart_vars(i)%data3d, &
1157 unlim_dim_level=unlim_dim_level, &
1159 elseif (
associated(fileobj%restart_vars(i)%data4d))
then
1161 fileobj%restart_vars(i)%data4d, &
1162 unlim_dim_level=unlim_dim_level, &
1165 call error(
"this branch should not be reached.")
1177 character(len=*),
intent(in) :: attribute_name
1178 logical,
intent(in),
optional :: broadcast
1184 logical :: att_exists
1186 if (fileobj%is_root)
then
1187 att_exists =
attribute_exists(fileobj%ncid, nf90_global, trim(attribute_name), &
1188 & msg=
"global_att_exists: file:"//trim(fileobj%path)//
" attribute name:"//trim(attribute_name))
1190 if (
present(broadcast))
then
1191 if (.not. broadcast)
then
1195 call mpp_broadcast(att_exists, fileobj%io_root, pelist=fileobj%pelist)
1206 character(len=*),
intent(in) :: variable_name
1207 character(len=*),
intent(in) :: attribute_name
1208 logical,
intent(in),
optional :: broadcast
1214 logical :: att_exists
1218 att_exists = .false.
1219 if (fileobj%is_root)
then
1221 & msg=
"variable_att_exists: file:"//trim(fileobj%path)//
"- variable:"//&
1222 &trim(variable_name))
1224 &msg=
"variable_att_exists: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name)//&
1225 &
" attribute name:"//trim(attribute_name))
1227 if (
present(broadcast))
then
1228 if (.not. broadcast)
then
1232 call mpp_broadcast(att_exists, fileobj%io_root, pelist=fileobj%pelist)
1242 logical,
intent(in),
optional :: broadcast
1252 if (fileobj%is_root)
then
1253 err = nf90_inquire(fileobj%ncid, ndimensions=ndims)
1256 if (
present(broadcast))
then
1257 if (.not. broadcast)
then
1261 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1269 character(len=*),
dimension(:),
intent(inout) :: names
1271 logical,
intent(in),
optional :: broadcast
1282 if (fileobj%is_root)
then
1284 if (ndims .gt. 0)
then
1285 if (
size(names) .ne. ndims)
then
1286 call error(
"'names' has to be the same size of the number of dimensions. &
1287 &Check your get_dimension_names call for file "//trim(fileobj%path))
1290 call error(
"get_dimension_names: the file "//trim(fileobj%path)//
" does not have any dimensions")
1294 err = nf90_inquire_dimension(fileobj%ncid, i, name=names(i))
1298 if (
present(broadcast))
then
1299 if (.not. broadcast)
then
1303 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1304 if (.not. fileobj%is_root)
then
1305 if (ndims .gt. 0)
then
1306 if (
size(names) .ne. ndims)
then
1307 call error(
"'names' has to be the same size of the number of dimensions. &
1308 &Check your get_dimension_names call for file "//trim(fileobj%path))
1311 call error(
"get_dimension_names: the file "//trim(fileobj%path)//
" does not have any dimensions")
1315 call mpp_broadcast(names, len(names(ndims)), fileobj%io_root, &
1316 pelist=fileobj%pelist)
1326 character(len=*),
intent(in) :: dimension_name
1327 logical,
intent(in),
optional :: broadcast
1333 logical :: dim_exists
1337 if (fileobj%is_root)
then
1339 msg=
"dimension_exists: file:"//trim(fileobj%path)//
" dimension:"//trim(dimension_name), &
1340 allow_failure=.true.)
1341 if (dimid .eq. dimension_missing)
then
1342 dim_exists = .false.
1347 if (
present(broadcast))
then
1348 if (.not. broadcast)
then
1352 call mpp_broadcast(dim_exists, fileobj%io_root, pelist=fileobj%pelist)
1359 result(is_unlimited)
1362 character(len=*),
intent(in) :: dimension_name
1363 logical,
intent(in),
optional :: broadcast
1369 logical :: is_unlimited
1371 character(len=200) :: append_error_msg
1374 integer :: ulim_dimid
1376 if (fileobj%is_root)
then
1377 append_error_msg=
"is_dimension_unlimited: file:"//trim(fileobj%path)//&
1378 &
" dimension_name:"//trim(dimension_name)
1379 dimid =
get_dimension_id(fileobj%ncid, trim(dimension_name), msg=append_error_msg)
1380 err = nf90_inquire(fileobj%ncid, unlimiteddimid=ulim_dimid)
1382 is_unlimited = dimid .eq. ulim_dimid
1384 if (
present(broadcast))
then
1385 if (.not. broadcast)
then
1389 call mpp_broadcast(is_unlimited, fileobj%io_root, pelist=fileobj%pelist)
1397 character(len=*),
intent(out) :: dimension_name
1398 logical,
intent(in),
optional :: broadcast
1407 character(len=nf90_max_name),
dimension(1) :: buffer
1410 if (fileobj%is_root)
then
1411 err = nf90_inquire(fileobj%ncid, unlimiteddimid=dimid)
1412 call check_netcdf_code(err,
"get_unlimited_dimension_name: file:"//trim(fileobj%path))
1413 err = nf90_inquire_dimension(fileobj%ncid, dimid, dimension_name)
1414 call check_netcdf_code(err,
"get_unlimited_dimension_name: file:"//trim(fileobj%path))
1415 call string_copy(buffer(1), dimension_name)
1417 if (
present(broadcast))
then
1418 if (.not. broadcast)
then
1422 call mpp_broadcast(buffer, nf90_max_name, fileobj%io_root, &
1423 pelist=fileobj%pelist)
1424 call string_copy(dimension_name, buffer(1))
1432 character(len=*),
intent(in) :: dimension_name
1433 integer,
intent(inout) :: dim_size
1434 logical,
intent(in),
optional :: broadcast
1443 character(len=200) :: append_error_msg
1445 if (fileobj%is_root)
then
1446 append_error_msg =
"get_dimension_size: file:"//trim(fileobj%path)//
" dimension_name: "//trim(dimension_name)
1447 dimid =
get_dimension_id(fileobj%ncid, trim(dimension_name), msg=append_error_msg)
1448 err = nf90_inquire_dimension(fileobj%ncid, dimid, len=dim_size)
1451 if (
present(broadcast))
then
1452 if (.not. broadcast)
then
1456 call mpp_broadcast(dim_size, fileobj%io_root, pelist=fileobj%pelist)
1466 logical,
intent(in),
optional :: broadcast
1476 if (fileobj%is_root)
then
1477 err = nf90_inquire(fileobj%ncid, nvariables=nvars)
1480 if (
present(broadcast))
then
1481 if (.not. broadcast)
then
1485 call mpp_broadcast(nvars, fileobj%io_root, pelist=fileobj%pelist)
1493 character(len=*),
dimension(:),
intent(inout) :: names
1495 logical,
intent(in),
optional :: broadcast
1506 if (fileobj%is_root)
then
1508 if (nvars .gt. 0)
then
1509 if (
size(names) .ne. nvars)
then
1510 call error(
"'names' has to be the same size of the number of variables. &
1511 &Check your get_variable_names call for file "//trim(fileobj%path))
1514 call error(
"get_variable_names: the file "//trim(fileobj%path)//
" does not have any variables")
1518 err = nf90_inquire_variable(fileobj%ncid, i, name=names(i))
1522 if (
present(broadcast))
then
1523 if (.not. broadcast)
then
1527 call mpp_broadcast(nvars, fileobj%io_root, pelist=fileobj%pelist)
1528 if (.not. fileobj%is_root)
then
1529 if (nvars .gt. 0)
then
1530 if (
size(names) .ne. nvars)
then
1531 call error(
"'names' has to be the same size of the number of variables. &
1532 &Check your get_variable_names call for file "//trim(fileobj%path))
1535 call error(
"get_variable_names: the file "//trim(fileobj%path)//
" does not have any variables")
1539 call mpp_broadcast(names, len(names(nvars)), fileobj%io_root, &
1540 pelist=fileobj%pelist)
1550 character(len=*),
intent(in) :: variable_name
1551 logical,
intent(in),
optional :: broadcast
1557 logical :: var_exists
1561 if (fileobj%is_root)
then
1563 msg=
"variable_exists: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name), &
1564 allow_failure=.true.)
1565 var_exists = varid .ne. variable_missing
1567 if (
present(broadcast))
then
1568 if (.not. broadcast)
then
1572 call mpp_broadcast(var_exists, fileobj%io_root, pelist=fileobj%pelist)
1582 character(len=*),
intent(in) :: variable_name
1583 logical,
intent(in),
optional :: broadcast
1593 character(len=200) :: append_error_msg
1596 if (fileobj%is_root)
then
1597 append_error_msg =
"get_variable_num_dimension: file:"//trim(fileobj%path)//
" variable: "//trim(variable_name)
1598 varid =
get_variable_id(fileobj%ncid, trim(variable_name), msg=append_error_msg)
1599 err = nf90_inquire_variable(fileobj%ncid, varid, ndims=ndims)
1602 if (
present(broadcast))
then
1603 if (.not. broadcast)
then
1607 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1616 character(len=*),
intent(in) :: variable_name
1617 character(len=*),
dimension(:),
intent(inout) :: dim_names
1620 logical,
intent(in),
optional :: broadcast
1630 integer,
dimension(nf90_max_var_dims) :: dimids
1632 character(len=200) :: append_error_msg
1635 if (fileobj%is_root)
then
1636 append_error_msg =
"get_variable_dimension_names: file:"//trim(fileobj%path)//
" variable: "//trim(variable_name)
1638 varid =
get_variable_id(fileobj%ncid, trim(variable_name), msg=append_error_msg)
1639 err = nf90_inquire_variable(fileobj%ncid, varid, ndims=ndims, &
1642 if (ndims .gt. 0)
then
1643 if (
size(dim_names) .ne. ndims)
then
1644 call error(
"'names' has to be the same size of the number of dimensions for the variable. &
1645 &Check your get_variable_dimension_names call for file "//trim(fileobj%path)// &
1646 " and variable:"//trim(variable_name))
1649 call error(
"get_variable_dimension_names: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)&
1650 & //
" does not any dimensions. ")
1654 err = nf90_inquire_dimension(fileobj%ncid, dimids(i), name=dim_names(i))
1658 if (
present(broadcast))
then
1659 if (.not. broadcast)
then
1663 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1664 if (.not. fileobj%is_root)
then
1665 if (ndims .gt. 0)
then
1666 if (
size(dim_names) .ne. ndims)
then
1667 call error(
"'names' has to be the same size of the number of dimensions for the variable. &
1668 & Check your get_variable_dimension_names call for file "//trim(fileobj%path)// &
1669 " and variable:"//trim(variable_name))
1672 call error(
"get_variable_dimension_names: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)&
1673 & //
" does not any dimensions. ")
1677 call mpp_broadcast(dim_names, len(dim_names(ndims)), fileobj%io_root, &
1678 pelist=fileobj%pelist)
1686 character(len=*),
intent(in) :: variable_name
1687 integer,
dimension(:),
intent(inout) :: dim_sizes
1689 logical,
intent(in),
optional :: broadcast
1699 integer,
dimension(nf90_max_var_dims) :: dimids
1701 character(len=200) :: append_error_msg
1703 if (fileobj%is_root)
then
1704 append_error_msg =
"get_variable_size: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name)
1705 varid =
get_variable_id(fileobj%ncid, trim(variable_name), msg=append_error_msg)
1706 err = nf90_inquire_variable(fileobj%ncid, varid, ndims=ndims, dimids=dimids)
1708 if (ndims .gt. 0)
then
1709 if (
size(dim_sizes) .ne. ndims)
then
1710 call error(
"'dim_sizes' has to be the same size of the number of dimensions for the variable. &
1711 &Check your get_variable_size call for file "//trim(fileobj%path)// &
1712 " and variable:"//trim(variable_name))
1715 call error(
"get_variable_size: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)//&
1716 &
" does not any dimensions. ")
1719 err = nf90_inquire_dimension(fileobj%ncid, dimids(i), len=dim_sizes(i))
1723 if (
present(broadcast))
then
1724 if (.not. broadcast)
then
1728 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1729 if (.not. fileobj%is_root)
then
1730 if (ndims .gt. 0)
then
1731 if (
size(dim_sizes) .ne. ndims)
then
1732 call error(
"'dim_sizes' has to be the same size of the number of dimensions for the variable. &
1733 &Check your get_variable_size call for file "//trim(fileobj%path)// &
1734 " and variable:"//trim(variable_name))
1737 call error(
"get_variable_size: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)//&
1738 &
" does not any dimensions. ")
1741 call mpp_broadcast(dim_sizes, ndims, fileobj%io_root, pelist=fileobj%pelist)
1750 result(unlim_dim_index)
1753 character(len=*),
intent(in) :: variable_name
1754 logical,
intent(in),
optional :: broadcast
1760 integer :: unlim_dim_index
1763 character(len=nf90_max_name),
dimension(:),
allocatable :: dim_names
1766 unlim_dim_index = no_unlimited_dimension
1767 if (fileobj%is_root)
then
1769 allocate(dim_names(ndims))
1772 do i = 1,
size(dim_names)
1778 deallocate(dim_names)
1780 if (
present(broadcast))
then
1781 if (.not. broadcast)
then
1785 call mpp_broadcast(unlim_dim_index, fileobj%io_root, pelist=fileobj%pelist)
1796 character(len=*),
intent(in) :: variable_name
1800 real(kind=r8_kind) :: scale_factor
1801 real(kind=r8_kind) :: add_offset
1802 real(kind=r8_kind),
dimension(2) :: buffer
1804 character(len=200) :: append_error_msg
1806 append_error_msg =
"get_valid: file:"//trim(fileobj%path)
1807 if (fileobj%is_root)
then
1808 varid =
get_variable_id(fileobj%ncid, variable_name, msg=append_error_msg)
1809 valid%has_max = .false.
1810 valid%has_min = .false.
1811 valid%has_fill = .false.
1812 valid%has_missing = .false.
1813 valid%has_range = .false.
1817 if (
attribute_exists(fileobj%ncid, varid,
"scale_factor", msg=append_error_msg))
then
1821 scale_factor = 1._r8_kind
1823 if (
attribute_exists(fileobj%ncid, varid,
"add_offset", msg=append_error_msg))
then
1827 add_offset = 0._r8_kind
1834 if (
attribute_exists(fileobj%ncid, varid,
"valid_range", msg=append_error_msg))
then
1837 valid%max_val = buffer(2)*scale_factor + add_offset
1838 valid%has_max = .true.
1839 valid%min_val = buffer(1)*scale_factor + add_offset
1840 valid%has_min = .true.
1842 if (
attribute_exists(fileobj%ncid, varid,
"valid_max", msg=append_error_msg))
then
1845 valid%max_val = buffer(1)*scale_factor + add_offset
1846 valid%has_max = .true.
1848 if (
attribute_exists(fileobj%ncid, varid,
"valid_min", msg=append_error_msg))
then
1851 valid%min_val = buffer(1)*scale_factor + add_offset
1852 valid%has_min = .true.
1855 valid%has_range = valid%has_min .or. valid%has_max
1859 if (
attribute_exists(fileobj%ncid, varid,
"missing_value", msg=append_error_msg))
then
1862 valid%missing_val = buffer(1)*scale_factor + add_offset
1863 valid%has_missing = .true.
1874 if (
attribute_exists(fileobj%ncid, varid,
"_FillValue", msg=append_error_msg))
then
1877 valid%fill_val = buffer(1)*scale_factor + add_offset
1878 valid%has_fill = .true.
1881 if (.not. valid%has_range)
then
1882 if (xtype .eq. nf90_short .or. xtype .eq. nf90_int)
then
1883 if (buffer(1) .gt. 0)
then
1884 valid%max_val = (buffer(1) - 1._r8_kind)*scale_factor + add_offset
1885 valid%has_max = .true.
1887 valid%min_val = (buffer(1) + 1._r8_kind)*scale_factor + add_offset
1888 valid%has_min = .true.
1890 elseif (xtype .eq. nf90_float .or. xtype .eq. nf90_double)
then
1891 if (buffer(1) .gt. 0)
then
1892 valid%max_val = (nearest(nearest(buffer(1), -1._r8_kind), -1._r8_kind)) &
1893 *scale_factor + add_offset
1894 valid%has_max = .true.
1896 valid%min_val = (nearest(nearest(buffer(1), 1._r8_kind), 1._r8_kind)) &
1897 *scale_factor + add_offset
1898 valid%has_min = .true.
1901 call error(
"Unsupported variable type:"//trim(append_error_msg))
1903 valid%has_range = .true.
1909 call mpp_broadcast(valid%has_min, fileobj%io_root, pelist=fileobj%pelist)
1910 if (valid%has_min)
then
1911 call mpp_broadcast(valid%min_val, fileobj%io_root, pelist=fileobj%pelist)
1913 call mpp_broadcast(valid%has_max, fileobj%io_root, pelist=fileobj%pelist)
1914 if (valid%has_max)
then
1915 call mpp_broadcast(valid%max_val, fileobj%io_root, pelist=fileobj%pelist)
1917 call mpp_broadcast(valid%has_range, fileobj%io_root, pelist=fileobj%pelist)
1919 call mpp_broadcast(valid%has_fill, fileobj%io_root, pelist=fileobj%pelist)
1920 if (valid%has_fill)
then
1921 call mpp_broadcast(valid%fill_val, fileobj%io_root, pelist=fileobj%pelist)
1924 call mpp_broadcast(valid%has_missing, fileobj%io_root, pelist=fileobj%pelist)
1925 if (valid%has_missing)
then
1926 call mpp_broadcast(valid%missing_val, fileobj%io_root, pelist=fileobj%pelist)
1936 real(kind=r8_kind),
intent(in) :: datum
1937 type(
valid_t),
intent(in) :: validobj
1938 logical :: valid_data
1949 real(kind=r4_kind),
intent(in) :: datum
1950 type(
valid_t),
intent(in) :: validobj
1951 logical :: valid_data
1953 real(kind=r8_kind) :: rdatum
1956 rdatum = real(datum, kind=r8_kind)
1966 real(kind=r8_kind),
intent(in) :: rdatum
1967 type(
valid_t),
intent(in) :: validobj
1968 logical :: valid_data
1973 if (validobj%has_range)
then
1974 if (validobj%has_min .and. .not. validobj%has_max)
then
1975 valid_data = rdatum .ge. validobj%min_val
1976 elseif (validobj%has_max .and. .not. validobj%has_min)
then
1977 valid_data = rdatum .le. validobj%max_val
1979 valid_data = .not. (rdatum .lt. validobj%min_val .or. rdatum .gt. validobj%max_val)
1984 if (validobj%has_fill .or. validobj%has_missing)
then
1985 if (validobj%has_fill .and. .not. validobj%has_missing)
then
1986 valid_data = rdatum .ne. validobj%fill_val
1987 elseif (validobj%has_missing .and. .not. validobj%has_fill)
then
1988 valid_data = rdatum .ne. validobj%missing_val
1990 valid_data = .not. (rdatum .eq. validobj%missing_val .or. rdatum .eq. validobj%fill_val)
2000 integer,
intent(in) :: nelems
2001 integer,
dimension(:),
allocatable,
intent(out) :: npes_start
2002 integer,
dimension(:),
allocatable,
intent(out) :: npes_count
2007 allocate(npes_start(
size(fileobj%pelist)))
2008 allocate(npes_count(
size(fileobj%pelist)))
2009 do i = 1,
size(fileobj%pelist)
2010 if (fileobj%pelist(i) .eq.
mpp_pe())
then
2011 npes_count(i) = nelems
2013 call mpp_recv(npes_count(i), fileobj%pelist(i), block=.false.)
2014 call mpp_send(nelems, fileobj%pelist(i))
2020 do i = 1,
size(fileobj%pelist)-1
2021 npes_start(i+1) = npes_start(i) + npes_count(i)
2026 include
"netcdf_add_restart_variable.inc"
2027 include
"netcdf_read_data.inc"
2028 include
"netcdf_write_data.inc"
2029 include
"register_global_attribute.inc"
2030 include
"register_variable_attribute.inc"
2031 include
"get_global_attribute.inc"
2032 include
"get_variable_attribute.inc"
2033 include
"compressed_write.inc"
2034 include
"compressed_read.inc"
2035 include
"scatter_data_bc.inc"
2036 include
"gather_data_bc.inc"
2037 include
"unpack_data.inc"
2044 character(len=*),
intent(in) :: path
2045 character(len=*),
intent(in) :: mode
2048 character(len=*),
intent(in),
optional :: nc_format
2054 integer,
dimension(:),
intent(in),
optional :: pelist
2059 logical,
intent(in),
optional :: is_restart
2062 logical,
intent(in),
optional :: dont_add_res_to_filename
2066 success =
netcdf_file_open(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
2083 character(len=*),
intent(in) :: variable_name
2084 character(len=*),
intent(in) :: variable_type
2087 character(len=*),
dimension(:),
intent(in),
optional :: dimensions
2096 integer,
intent(in),
optional :: unlim_dim_level
2109 character(len=*),
intent(in) :: variable_name
2110 class(*),
intent(out) :: fill_value
2111 logical,
intent(in),
optional :: broadcast
2117 logical :: fill_exists
2119 character(len=32),
dimension(2) :: attribute_names
2123 fill_exists = .false.
2124 call string_copy(attribute_names(1),
"_FillValue")
2125 call string_copy(attribute_names(2),
"missing_value")
2126 if (
present(broadcast))
then
2131 do i = 1,
size(attribute_names)
2134 if (fill_exists)
then
2136 fill_value, broadcast=bcast)
2143 function get_variable_sense(fileobj, variable_name) &
2144 result(variable_sense)
2147 character(len=*),
intent(in) :: variable_name
2148 integer :: variable_sense
2150 character(len=256) :: buf
2161 end function get_variable_sense
2164 function get_variable_missing(fileobj, variable_name) &
2165 result(variable_missing)
2168 character(len=*),
intent(in) :: variable_name
2169 real(kind=r8_kind) :: variable_missing
2171 real(kind=r8_kind) :: variable_missing_1d(1)
2180 variable_missing_1d = mpp_fill_double
2183 variable_missing = variable_missing_1d(1)
2185 end function get_variable_missing
2188 subroutine get_variable_units(fileobj, variable_name, units)
2191 character(len=*),
intent(in) :: variable_name
2192 character(len=*),
intent(out) :: units
2199 end subroutine get_variable_units
2202 subroutine get_time_calendar(fileobj, time_name, calendar_type)
2205 character(len=*),
intent(in) :: time_name
2206 character(len=*),
intent(out) :: calendar_type
2213 calendar_type =
"unspecified"
2215 end subroutine get_time_calendar
2221 result(is_registered)
2224 character(len=*),
intent(in) :: variable_name
2225 logical :: is_registered
2229 if (.not. fileobj%is_restart)
then
2230 call error(
"file "//trim(fileobj%path)//
" is not a restart file. &
2231 &Add is_restart=.true. to your open_file call")
2233 is_registered = .false.
2234 do i = 1, fileobj%num_restart_vars
2235 if (
string_compare(fileobj%restart_vars(i)%varname, variable_name, .true.))
then
2236 is_registered = .true.
2246 character(len=*),
intent(in),
optional :: fname
2249 if (
allocated(fileobj%is_open))
then
2250 is_open = fileobj%is_open
2255 if (
present(fname))
then
2258 if (is_open .AND. trim(fname) .ne. trim(fileobj%path)) is_open = .false.
2262 subroutine set_fileobj_time_name (fileobj,time_name)
2264 character(*),
intent(in) :: time_name
2265 integer :: len_of_name
2266 len_of_name = len(trim(time_name))
2267 fileobj%time_name =
' '
2268 fileobj%time_name = time_name(1:len_of_name)
2275 end subroutine set_fileobj_time_name
2281 integer,
intent(in),
optional :: unlim_dim_level
2283 logical,
intent(in),
optional :: ignore_checksum
2287 if (.not. fileobj%is_restart)
then
2288 call error(
"file "//trim(fileobj%path)//
" is not a restart file.")
2291 do i = 1, fileobj%num_restart_vars
2293 if (.not.any(
mpp_pe().eq.fileobj%restart_vars(i)%bc_info%pelist(:))) cycle
2296 if (
associated(fileobj%restart_vars(i)%data2d))
then
2298 fileobj%restart_vars(i)%data2d, &
2299 fileobj%restart_vars(i)%bc_info, &
2300 unlim_dim_level = unlim_dim_level, &
2301 ignore_checksum=ignore_checksum)
2302 else if (
associated(fileobj%restart_vars(i)%data3d))
then
2304 fileobj%restart_vars(i)%data3d, &
2305 fileobj%restart_vars(i)%bc_info, &
2306 unlim_dim_level = unlim_dim_level, &
2307 ignore_checksum=ignore_checksum)
2318 integer,
intent(in),
optional :: unlim_dim_level
2322 if (.not. fileobj%is_restart)
then
2323 call error(
"file "//trim(fileobj%path)//
" is not a restart file. &
2324 &Add is_restart=.true. to your open_file call")
2332 do i = 1, fileobj%num_restart_vars
2334 if (.not.any(
mpp_pe().eq.fileobj%restart_vars(i)%bc_info%pelist(:))) cycle
2337 if (.not. fileobj%restart_vars(i)%is_bc_variable) cycle
2340 if (
associated(fileobj%restart_vars(i)%data2d))
then
2341 call gather_data_bc(fileobj, fileobj%restart_vars(i)%data2d, fileobj%restart_vars(i)%bc_info)
2343 fileobj%restart_vars(i)%bc_info%chksum(1:len(fileobj%restart_vars(i)%bc_info%chksum)),&
2344 str_len=len(fileobj%restart_vars(i)%bc_info%chksum))
2345 else if (
associated(fileobj%restart_vars(i)%data3d))
then
2346 call gather_data_bc(fileobj, fileobj%restart_vars(i)%data3d, fileobj%restart_vars(i)%bc_info)
2348 fileobj%restart_vars(i)%bc_info%chksum(1:len(fileobj%restart_vars(i)%bc_info%chksum)),&
2349 str_len=len(fileobj%restart_vars(i)%bc_info%chksum))
2354 do i = 1, fileobj%num_restart_vars
2355 if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata2d_r8 ))
then
2357 fileobj%restart_vars(i)%bc_info%globaldata2d_r8 , &
2358 unlim_dim_level=unlim_dim_level)
2359 deallocate(fileobj%restart_vars(i)%bc_info%globaldata2d_r8)
2360 else if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata2d_r4 ))
then
2362 fileobj%restart_vars(i)%bc_info%globaldata2d_r4 , &
2363 unlim_dim_level=unlim_dim_level)
2364 deallocate(fileobj%restart_vars(i)%bc_info%globaldata2d_r4)
2365 else if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata3d_r8 ))
then
2367 fileobj%restart_vars(i)%bc_info%globaldata3d_r8 , &
2368 unlim_dim_level=unlim_dim_level)
2369 deallocate(fileobj%restart_vars(i)%bc_info%globaldata3d_r8)
2370 else if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata3d_r4 ))
then
2372 fileobj%restart_vars(i)%bc_info%globaldata3d_r4 , &
2373 unlim_dim_level=unlim_dim_level)
2374 deallocate(fileobj%restart_vars(i)%bc_info%globaldata3d_r4 )
2387 if (fileobj%is_root)
then
2388 err = nf90_sync(fileobj%ncid)
2393 end module netcdf_io_mod
subroutine compressed_write_1d_wrap(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine register_variable_attribute_1d(fileobj, variable_name, attribute_name, attribute_value, str_len)
Add an attribute to a variable.
subroutine compressed_write_3d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
For variables without a compressed dimension, this routine simply wraps netcdf_write data....
subroutine compressed_write_5d_wrap(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine compressed_write_0d(fileobj, variable_name, cdata, unlim_dim_level, corner)
For variables without a compressed dimension, this routine simply wraps netcdf_write data....
subroutine compressed_read_0d(fileobj, variable_name, cdata, unlim_dim_level, corner)
I/O domain reads in data from the netcdf file and broadcasts the data to the rest of the ranks....
subroutine compressed_write_5d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
For variables without a compressed dimension, this routine simply wraps netcdf_write data....
subroutine compressed_read_5d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
I/O domain reads in data from the netcdf file and broadcasts the data to the rest of the ranks....
subroutine compressed_read_3d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
I/O domain reads in data from the netcdf file and broadcasts the data to the rest of the ranks....
subroutine compressed_write_0d_wrap(fileobj, variable_name, cdata, unlim_dim_level, corner)
Wrapper to distinguish interfaces.
subroutine compressed_read_1d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
I/O domain reads in data from the netcdf file and broadcasts the data to the rest of the ranks....
subroutine compressed_read_2d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
I/O domain reads in data from the netcdf file and broadcasts the data to the rest of the ranks....
subroutine compressed_write_4d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
For variables without a compressed dimension, this routine simply wraps netcdf_write data....
subroutine compressed_write_2d_wrap(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine compressed_write_1d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
For variables without a compressed dimension, this routine simply wraps netcdf_write data....
subroutine compressed_write_4d_wrap(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine compressed_read_4d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
I/O domain reads in data from the netcdf file and broadcasts the data to the rest of the ranks....
subroutine compressed_write_2d(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
For variables without a compressed dimension, this routine simply wraps netcdf_write data....
subroutine register_variable_attribute_0d(fileobj, variable_name, attribute_name, attribute_value, str_len)
Add an attribute to a variable.
subroutine compressed_write_3d_wrap(fileobj, variable_name, cdata, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine, public get_instance_filename(name_in, name_out)
Adds the filename_appendix to name_in and sets it as name_out.
subroutine, public restart_filepath_mangle(dest, source)
Add ".res" to an input file path.
logical function, public file_exists(path)
Determine if a file exists.
logical function, public string_compare(string1, string2, ignore_case)
Compare strings.
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer, parameter, public mpp_comm_null
MPP_COMM_NULL acts as an analagous mpp-macro for MPI_COMM_NULL to share with fms2_io NetCDF4 mpi-io....
integer, parameter, public mpp_info_null
MPP_INFO_NULL acts as an analagous mpp-macro for MPI_INFO_NULL to share with fms2_io NetCDF4 mpi-io....
integer function mpp_pe()
Returns processor ID.
Perform parallel broadcasts.
Gather data sent from pelist onto the root pe Wrapper for MPI_gather, can be used with and without in...
Recieve data from another PE.
Send data to a receiving PE.
integer, private fms2_ncchksz
Chunksize (bytes) used in nc_open and nc_create.
subroutine, public netcdf_restore_state(fileobj, unlim_dim_level)
Loop through registered restart variables and read them from a netcdf file.
subroutine append_compressed_dimension(fileobj, dim_name, npes_corner, npes_nelems)
Add a compressed dimension to a file object.
subroutine, public netcdf_file_close(fileobj)
Close a netcdf file.
subroutine netcdf_add_restart_variable_4d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
integer function, dimension(2) get_variable_compressed_dimension_index(fileobj, variable_name, broadcast)
Given a compressed variable, get the index of the compressed dimension.
logical function, public netcdf_file_open(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
Open a netcdf file.
elemental logical function is_valid_r8(datum, validobj)
Determine if a piece of (r4) data is "valid" (in the correct range.)
logical function attribute_exists(ncid, varid, attribute_name, msg)
Determine if an attribute exists.
subroutine, public get_variable_size(fileobj, variable_name, dim_sizes, broadcast)
Get the size of a variable's dimensions.
subroutine, public netcdf_add_dimension(fileobj, dimension_name, dimension_length, is_compressed)
Add a dimension to a file.
subroutine netcdf_add_restart_variable_0d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
type(valid_t) function, public get_valid(fileobj, variable_name)
Store the valid range for a variable.
subroutine, public read_restart_bc(fileobj, unlim_dim_level, ignore_checksum)
Loop through the registered restart variables (including regional variables) and read them from the n...
logical function, public is_dimension_unlimited(fileobj, dimension_name, broadcast)
Determine where or not the dimension is unlimited.
character(len=10), private fms2_nc_format
Netcdf format type used in netcdf_file_open.
integer function, public get_variable_unlimited_dimension_index(fileobj, variable_name, broadcast)
Get the index of a variable's unlimited dimensions.
logical function, public netcdf_file_open_wrap(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
Wrapper to distinguish interfaces.
integer function get_compressed_dimension_index(fileobj, dim_name)
Get the index of a compressed dimension in a file object.
subroutine, public compressed_start_and_count(fileobj, nelems, npes_start, npes_count)
Gathers a compressed arrays size and offset for each pe.
subroutine scatter_data_bc_2d(fileobj, varname, vdata, bc_info, unlim_dim_level, ignore_checksum)
integer, private fms2_header_buffer_val
value used in NF__ENDDEF
integer, private fms2_nc_format_param
Netcdf format type param used in nc_create.
elemental logical function is_valid_r4(datum, validobj)
Determine if a piece of (r8) data is "valid" (in the correct range.)
integer function, public get_variable_num_dimensions(fileobj, variable_name, broadcast)
Get the number of dimensions a variable depends on.
subroutine, public get_dimension_size(fileobj, dimension_name, dim_size, broadcast)
Get the length of a dimension.
subroutine, public netcdf_add_variable_wrap(fileobj, variable_name, variable_type, dimensions)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_3d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine netcdf_write_data_4d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Write data to a variable in a netcdf file.
subroutine netcdf_read_data_1d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Read in data from a variable in a netcdf file.
subroutine netcdf_add_restart_variable_5d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
elemental logical function check_if_valid(rdatum, validobj)
Determine if a piece of data is "valid" (in the correct range.)
subroutine netcdf_add_restart_variable_1d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
logical function, public global_att_exists(fileobj, attribute_name, broadcast)
Determine if a global attribute exists.
subroutine, public set_netcdf_mode(ncid, mode)
Switch to the correct netcdf mode.
subroutine netcdf_write_data_0d(fileobj, variable_name, variable_data, unlim_dim_level, corner)
Write data to a variable in a netcdf file.
subroutine register_global_attribute_0d(fileobj, attribute_name, attribute_value, str_len)
Add a global attribute.
subroutine get_variable_attribute_1d(fileobj, variable_name, attribute_name, attribute_value, broadcast)
Get the value of a variable's attribute.
subroutine netcdf_add_restart_variable_0d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
logical, private fms2_shuffle
Flag indicating whether to use the netcdf shuffle filter.
subroutine get_global_attribute_1d(fileobj, attribute_name, attribute_value, broadcast)
Get the value of a global attribute.
subroutine netcdf_add_restart_variable_3d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine netcdf_add_restart_variable_1d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine get_variable_attribute_0d(fileobj, variable_name, attribute_name, attribute_value, broadcast, reproduce_null_char_bug_flag)
Get the value of a variable's attribute.
integer function get_variable_id(ncid, variable_name, msg, allow_failure)
Get the id of a variable from its name.
subroutine register_restart_region_3d(fileobj, variable_name, vdata, indices, global_size, pelist, is_root_pe, x_halo, y_halo, jshift, ishift, is_optional)
Registers a regional 3D variable and stores the information needed.
subroutine register_global_attribute_1d(fileobj, attribute_name, attribute_value, str_len)
Add a global attribute.
logical function, public dimension_exists(fileobj, dimension_name, broadcast)
Determine if a dimension exists.
logical function, public is_registered_to_restart(fileobj, variable_name)
Determine if a variable has been registered to a restart file..
integer function get_dimension_id(ncid, dimension_name, msg, allow_failure)
Get the id of a dimension from its name.
subroutine, public register_compressed_dimension(fileobj, dimension_name, npes_corner, npes_nelems)
Add a compressed dimension.
logical function, public variable_att_exists(fileobj, variable_name, attribute_name, broadcast)
Determine if a variable's attribute exists.
integer, private fms2_deflate_level
Netcdf deflate level to use in nf90_def_var (integer between 1 to 9)
subroutine netcdf_read_data_5d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Read in data from a variable in a netcdf file.
subroutine netcdf_add_restart_variable_2d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine netcdf_write_data_3d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Write data to a variable in a netcdf file.
logical function, public get_fill_value(fileobj, variable_name, fill_value, broadcast)
Returns a variable's fill value if it exists in the file.
subroutine gather_data_bc_3d(fileobj, vdata, bc_info)
gathers the 2d vdata from all of the relevant pes into the root_pe and saves it to a buffer.
subroutine, public get_variable_dimension_names(fileobj, variable_name, dim_names, broadcast)
Get the name of a variable's dimensions.
subroutine, public check_netcdf_code(err, msg)
Check for errors returned by netcdf.
subroutine netcdf_write_data_1d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Write data to a variable in a netcdf file.
subroutine, public flush_file(fileobj)
flushes the netcdf file into disk
subroutine netcdf_add_restart_variable_4d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine get_global_attribute_0d(fileobj, attribute_name, attribute_value, broadcast)
Get the value of a global attribute.
subroutine netcdf_add_restart_variable_5d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a restart variable to a netcdf file.
subroutine, public register_unlimited_compressed_axis(fileobj, dimension_name, dimension_length)
Add a "compressed" unlimited dimension to a netcdf file.
subroutine, public netcdf_save_restart(fileobj, unlim_dim_level)
Loop through registered restart variables and write them to a netcdf file.
subroutine netcdf_read_data_3d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Read in data from a variable in a netcdf file.
subroutine netcdf_write_data_2d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Write data to a variable in a netcdf file.
subroutine, public write_restart_bc(fileobj, unlim_dim_level)
Loop through the registered restart variables (including regional variables) and write them to the ne...
integer function get_variable_type(ncid, varid, msg)
Get the type of a netcdf variable.
logical, private fms2_is_netcdf4
Flag indicating whether the default netcdf file format is netcdf4.
subroutine, public netcdf_save_restart_wrap(fileobj, unlim_dim_level)
Wrapper to distinguish interfaces.
subroutine, public get_variable_names(fileobj, names, broadcast)
Get the names of the variables in a file.
subroutine netcdf_read_data_2d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Read in data from a variable in a netcdf file.
subroutine netcdf_add_restart_variable_2d_wrap(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Wrapper to distinguish interfaces.
subroutine, public get_dimension_names(fileobj, names, broadcast)
Get the names of the dimensions in a file.
subroutine gather_data_bc_2d(fileobj, vdata, bc_info)
gathers the 2d vdata from all of the relevant pes into the root_pe and saves it to a buffer.
logical function, public check_if_open(fileobj, fname)
subroutine, public netcdf_io_init(chksz, header_buffer_val, netcdf_default_format, deflate_level, shuffle)
Accepts the namelist fms2_io_nml variables relevant to netcdf_io_mod.
integer function, public get_num_variables(fileobj, broadcast)
Determine the number of variables in a file.
subroutine, public get_unlimited_dimension_name(fileobj, dimension_name, broadcast)
Get the name of the unlimited dimension.
integer function get_attribute_type(ncid, varid, attname, msg)
Get the type of a netcdf attribute.
subroutine, public netcdf_add_variable(fileobj, variable_name, variable_type, dimensions, chunksizes)
Add a variable to a file.
subroutine scatter_data_bc_3d(fileobj, varname, vdata, bc_info, unlim_dim_level, ignore_checksum)
subroutine netcdf_write_data_5d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Write data to a variable in a netcdf file.
subroutine register_restart_region_2d(fileobj, variable_name, vdata, indices, global_size, pelist, is_root_pe, x_halo, y_halo, jshift, ishift, is_optional)
Registers a regional 2D variable and stores the information needed.
subroutine, public netcdf_file_close_wrap(fileobj)
Wrapper to distinguish interfaces.
subroutine netcdf_read_data_0d(fileobj, variable_name, buf, unlim_dim_level, corner, broadcast)
Read in data from a variable in a netcdf file.
logical function, public variable_exists(fileobj, variable_name, broadcast)
Determine if a variable exists.
subroutine add_restart_var_to_array(fileobj, variable_name)
Add a restart variable to a FmsNetcdfFile_t type.
integer function, public get_num_dimensions(fileobj, broadcast)
Determine the number of dimensions in a file.
subroutine netcdf_read_data_4d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Read in data from a variable in a netcdf file.
The interface is needed to accomodate pgi because it can't handle class * and there was no other way ...
Range type for a netcdf variable.