27 #ifndef MAX_NUM_RESTART_VARS_
28 #define MAX_NUM_RESTART_VARS_ 250
39 integer,
parameter,
public :: default_deflate_level = 0
40 integer,
parameter :: variable_missing = -1
41 integer,
parameter :: dimension_missing = -1
42 integer,
parameter,
public :: no_unlimited_dimension = -1
43 character(len=1),
parameter :: missing_path =
""
44 integer,
parameter :: missing_ncid = -1
45 integer,
parameter :: missing_rank = -1
46 integer,
parameter,
public :: define_mode = 0
47 integer,
parameter,
public :: data_mode = 1
48 integer,
parameter,
public :: max_num_restart_vars = max_num_restart_vars_
49 integer,
parameter,
public :: unlimited = nf90_unlimited
50 integer,
parameter :: dimension_not_found = 0
51 integer,
parameter,
public :: max_num_compressed_dims = 10
67 integer,
dimension(:),
allocatable :: indices
69 integer,
dimension(:),
allocatable :: global_size
70 integer,
dimension(:),
allocatable :: pelist
76 real(kind=r4_kind),
dimension(:,:),
allocatable :: globaldata2d_r4
77 real(kind=r4_kind),
dimension(:,:,:),
allocatable :: globaldata3d_r4
78 real(kind=r8_kind),
dimension(:,:),
allocatable :: globaldata2d_r8
79 real(kind=r8_kind),
dimension(:,:,:),
allocatable :: globaldata3d_r8
80 character(len=32) :: chksum
81 logical :: data_on_file_root
88 character(len=256) :: varname
89 class(*),
pointer :: data0d => null()
90 class(*),
dimension(:),
pointer :: data1d => null()
91 class(*),
dimension(:,:),
pointer :: data2d => null()
92 class(*),
dimension(:,:,:),
pointer :: data3d => null()
93 class(*),
dimension(:,:,:,:),
pointer :: data4d => null()
94 class(*),
dimension(:,:,:,:,:),
pointer :: data5d => null()
97 logical :: is_bc_variable
104 character(len=256) :: dimname
105 integer,
dimension(:),
allocatable :: npes_corner
107 integer,
dimension(:),
allocatable :: npes_nelems
116 integer,
dimension(5) :: xlen
117 integer,
dimension(5) :: ylen
118 integer,
dimension(5) :: zlen
119 integer,
dimension(3) :: cur_dim_len
128 character(len=FMS_PATH_LEN) :: path
129 logical :: is_readonly
131 character(len=256) :: nc_format
132 logical :: is_netcdf4
133 integer,
dimension(:),
allocatable :: pelist
138 logical :: is_restart
140 logical :: mode_is_append
141 logical,
allocatable :: is_open
144 integer :: num_restart_vars
146 integer :: num_compressed_dims
147 logical :: is_diskless
148 character (len=20) :: time_name
151 logical :: use_collective = .false.
156 logical :: use_netcdf_mpi = .false.
172 logical :: has_missing
173 real(kind=r8_kind) :: fill_val
174 real(kind=r8_kind) :: min_val
175 real(kind=r8_kind) :: max_val
176 real(kind=r8_kind) :: missing_val
240 public :: get_variable_sense
241 public :: get_variable_missing
242 public :: get_variable_units
243 public :: get_time_calendar
248 public :: set_fileobj_time_name
350 subroutine netcdf_io_init (chksz, header_buffer_val, netcdf_default_format, deflate_level, shuffle)
351 integer,
intent(in) :: chksz
352 character (len = 10),
intent(in) :: netcdf_default_format
353 integer,
intent(in) :: header_buffer_val
354 integer,
intent(in) :: deflate_level
356 logical,
intent(in) :: shuffle
366 elseif (
string_compare(netcdf_default_format,
"classic", .true.))
then
369 elseif (
string_compare(netcdf_default_format,
"netcdf4", .true.))
then
374 call error(
"unrecognized netcdf file format "//trim(netcdf_default_format)// &
375 '. The acceptable values are "64bit", "classic", "netcdf4". Check fms2_io_nml: netcdf_default_format')
384 integer,
intent(in) :: err
385 character(len=*),
intent(in) :: msg
387 character(len=80) :: buf
389 if (err .ne. nf90_noerr)
then
390 buf = nf90_strerror(err)
391 call error(trim(buf)//
": "//trim(msg))
400 integer,
intent(in) :: ncid
401 integer,
intent(in) :: mode
405 if (mode .eq. define_mode)
then
406 err = nf90_redef(ncid)
407 if (err .eq. nf90_eindefine .or. err .eq. nf90_eperm)
then
410 elseif (mode .eq. data_mode)
then
411 if (
fms2_header_buffer_val == -1)
call error(
"set_netcdf_mode: fms2_header_buffer_val not set, call fms2_io_init")
413 if (err .eq. nf90_enotindefine .or. err .eq. nf90_eperm)
then
417 call error(
"mode must be either define_mode or data_mode.")
429 integer,
intent(in) :: ncid
430 character(len=*),
intent(in) :: dimension_name
431 character(len=*),
intent(in) :: msg
432 logical,
intent(in),
optional :: allow_failure
440 err = nf90_inq_dimid(ncid, trim(dimension_name), dimid)
441 if (
present(allow_failure))
then
442 if (allow_failure .and. err .eq. nf90_ebaddim)
then
443 dimid = dimension_missing
457 integer,
intent(in) :: ncid
458 character(len=*),
intent(in) :: variable_name
459 character(len=*),
intent(in) :: msg
460 logical,
intent(in),
optional :: allow_failure
468 err = nf90_inq_varid(ncid, trim(variable_name), varid)
469 if (
present(allow_failure))
then
470 if (allow_failure .and. err .eq. nf90_enotvar)
then
471 varid = variable_missing
485 integer,
intent(in) :: ncid
486 integer,
intent(in) :: varid
487 character(len=*),
intent(in) :: attribute_name
488 character(len=*),
intent(in),
optional :: msg
490 logical :: att_exists
494 err = nf90_inquire_attribute(ncid, varid, trim(attribute_name))
495 if (err .eq. nf90_enotatt)
then
510 integer,
intent(in) :: ncid
511 integer,
intent(in) :: varid
512 character(len=*),
intent(in) :: attname
513 character(len=*),
intent(in),
optional :: msg
519 err = nf90_inquire_attribute(ncid, varid, attname, xtype=xtype)
530 integer,
intent(in) :: ncid
531 integer,
intent(in) :: varid
532 character(len=*),
intent(in),
optional :: msg
538 err = nf90_inquire_variable(ncid, varid, xtype=xtype)
545 function netcdf_file_open(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename) &
549 character(len=*),
intent(in) :: path
550 character(len=*),
intent(in) :: mode
553 character(len=*),
intent(in),
optional :: nc_format
561 integer,
dimension(:),
intent(in),
optional :: pelist
566 logical,
intent(in),
optional :: is_restart
569 logical,
intent(in),
optional :: dont_add_res_to_filename
573 integer :: nc_format_param
577 character(len=FMS_PATH_LEN) :: buf
578 character(len=FMS_PATH_LEN) :: buf2
580 logical :: dont_add_res
582 if (
allocated(fileobj%is_open))
then
583 if (fileobj%is_open)
then
591 if (
present(is_restart))
then
594 dont_add_res = .false.
595 if (
present(dont_add_res_to_filename))
then
596 dont_add_res = dont_add_res_to_filename
599 if (is_res .and. .not. dont_add_res)
then
602 call string_copy(buf, trim(path))
609 call string_copy(buf2, trim(buf))
616 if (.not. success)
then
622 call string_copy(fileobj%path, trim(buf2))
623 if (
present(pelist))
then
624 allocate(fileobj%pelist(
size(pelist)))
625 fileobj%pelist(:) = pelist(:)
627 allocate(fileobj%pelist(1))
628 fileobj%pelist(1) =
mpp_pe()
630 fileobj%io_root = fileobj%pelist(1)
631 fileobj%is_root =
mpp_pe() .eq. fileobj%io_root
633 fileobj%is_netcdf4 = .false.
634 if (
fms2_ncchksz == -1)
call error(
"netcdf_file_open:: fms2_ncchksz not set, call fms2_io_init")
635 if (
fms2_nc_format_param == -1)
call error(
"netcdf_file_open:: fms2_nc_format_param not set, call fms2_io_init")
637 if (
present(nc_format))
then
639 nc_format_param = nf90_64bit_offset
641 nc_format_param = nf90_classic_model
643 fileobj%is_netcdf4 = .true.
644 nc_format_param = nf90_netcdf4
646 call error(
"unrecognized netcdf file format: '"//trim(nc_format)//
"' for file:"//trim(fileobj%path)//&
647 &
"Check your open_file call, the acceptable values are 64bit, classic, netcdf4")
649 call string_copy(fileobj%nc_format, nc_format)
657 if (fileobj%is_root .and. .not.(fileobj%use_collective))
then
659 err = nf90_open(trim(fileobj%path), nf90_nowrite, fileobj%ncid, chunksize=
fms2_ncchksz)
661 err = nf90_open(trim(fileobj%path), nf90_write, fileobj%ncid, chunksize=
fms2_ncchksz)
663 err = nf90_create(trim(fileobj%path), ior(nf90_noclobber, nc_format_param), fileobj%ncid, chunksize=
fms2_ncchksz)
665 err = nf90_create(trim(fileobj%path), ior(nf90_clobber, nc_format_param), fileobj%ncid, chunksize=
fms2_ncchksz)
667 call error(
"unrecognized file mode: '"//trim(mode)//
"' for file:"//trim(fileobj%path)//&
668 &
"Check your open_file call, the acceptable values are read, append, write, overwrite")
671 elseif(fileobj%use_collective .and. (fileobj%tile_comm /=
mpp_comm_null))
then
676 err = nf90_open(trim(fileobj%path), ior(nf90_nowrite, nf90_mpiio), fileobj%ncid, &
678 if(err /= nf90_noerr)
then
679 err = nf90_open(trim(fileobj%path), nf90_nowrite, fileobj%ncid)
680 err = nf90_get_att(fileobj%ncid, nf90_global,
"_IsNetcdf4", netcdf4)
681 err = nf90_close(fileobj%ncid)
682 if(netcdf4 /= 1)
then
683 call mpp_error(note,
"netcdf_file_open: Open for collective read failed because the file is not &
684 netCDF-4 format."// &
685 " Falling back to parallel independent for file "// trim(fileobj%path))
686 fileobj%use_collective = .false.
689 #ifdef NO_NC_PARALLEL4
690 call mpp_error(fatal,
"netCDF was not build with HDF5 parallel I/O features, "//&
691 "so collective netcdf io is not allowed. Please turn collective read off for file "//&
695 err = nf90_open(trim(fileobj%path), nf90_nowrite, fileobj%ncid, chunksize=
fms2_ncchksz)
698 call mpp_error(fatal,
"netcdf_file_open: Attempt to create a file for collective write"// &
699 " This feature is not implemented"// trim(fileobj%path))
703 call mpp_error(fatal,
"netcdf_file_open: Attempt to create a file for collective overwrite"// &
704 " This feature is not implemented"// trim(fileobj%path))
708 call error(
"unrecognized file mode: '"//trim(mode)//
"' for file:"//trim(fileobj%path)//&
709 &
"Check your open_file call, the acceptable values are read, append, write, overwrite")
713 fileobj%ncid = missing_ncid
716 fileobj%is_diskless = .false.
719 fileobj%is_restart = is_res
720 if (fileobj%is_restart)
then
721 allocate(fileobj%restart_vars(max_num_restart_vars))
722 fileobj%num_restart_vars = 0
726 allocate(fileobj%compressed_dims(max_num_compressed_dims))
727 fileobj%num_compressed_dims = 0
729 if (.not.
allocated(fileobj%is_open))
allocate(fileobj%is_open)
730 fileobj%is_open = .true.
732 fileobj%bc_dimensions%xlen = 0
733 fileobj%bc_dimensions%ylen = 0
734 fileobj%bc_dimensions%zlen = 0
735 fileobj%bc_dimensions%cur_dim_len = 0
748 if (fileobj%is_root)
then
749 err = nf90_close(fileobj%ncid)
752 if (
allocated(fileobj%is_open)) fileobj%is_open = .false.
753 fileobj%path = missing_path
754 fileobj%ncid = missing_ncid
755 if (
allocated(fileobj%pelist))
then
756 deallocate(fileobj%pelist)
758 fileobj%io_root = missing_rank
759 fileobj%is_root = .false.
760 if (
allocated(fileobj%restart_vars))
then
761 deallocate(fileobj%restart_vars)
763 fileobj%is_restart = .false.
764 fileobj%num_restart_vars = 0
765 do i = 1, fileobj%num_compressed_dims
766 if (
allocated(fileobj%compressed_dims(i)%npes_corner))
then
767 deallocate(fileobj%compressed_dims(i)%npes_corner)
769 if (
allocated(fileobj%compressed_dims(i)%npes_nelems))
then
770 deallocate(fileobj%compressed_dims(i)%npes_nelems)
773 if (
allocated(fileobj%compressed_dims))
then
774 deallocate(fileobj%compressed_dims)
786 character(len=*),
intent(in) :: dim_name
791 dindex = dimension_not_found
792 do i = 1, fileobj%num_compressed_dims
793 if (
string_compare(fileobj%compressed_dims(i)%dimname, dim_name))
then
807 character(len=*),
intent(in) :: dim_name
808 integer,
dimension(:),
intent(in) :: npes_corner
810 integer,
dimension(:),
intent(in) :: npes_nelems
817 call error(
"dimension "//trim(dim_name)//
" already registered" &
818 //
" to file "//trim(fileobj%path)//
".")
820 fileobj%num_compressed_dims = fileobj%num_compressed_dims + 1
821 n = fileobj%num_compressed_dims
822 if (n .gt. max_num_compressed_dims)
then
823 call error(
"number of compressed dimensions exceeds limit.")
825 call string_copy(fileobj%compressed_dims(n)%dimname, dim_name)
826 if (
size(npes_corner) .ne.
size(fileobj%pelist) .or. &
827 size(npes_nelems) .ne.
size(fileobj%pelist))
then
828 call error(
"incorrect size for input npes_corner or npes_nelems arrays.")
830 allocate(fileobj%compressed_dims(n)%npes_corner(
size(fileobj%pelist)))
831 fileobj%compressed_dims(n)%npes_corner(:) = npes_corner(:)
832 allocate(fileobj%compressed_dims(n)%npes_nelems(
size(fileobj%pelist)))
833 fileobj%compressed_dims(n)%npes_nelems(:) = npes_nelems(:)
834 fileobj%compressed_dims(n)%nelems = sum(fileobj%compressed_dims(n)%npes_nelems)
842 character(len=*),
intent(in) :: dimension_name
843 integer,
intent(in) :: dimension_length
845 integer,
dimension(:),
allocatable :: npes_start
846 integer,
dimension(:),
allocatable :: npes_count
852 allocate(npes_start(
size(fileobj%pelist)))
853 allocate(npes_count(
size(fileobj%pelist)))
855 call mpp_gather((/dimension_length/),npes_count,pelist=fileobj%pelist)
858 do i = 1,
size(fileobj%pelist)-1
859 npes_start(i+1) = npes_start(i) + npes_count(i)
864 if (fileobj%is_root .and. .not. fileobj%is_readonly)
then
866 err = nf90_def_dim(fileobj%ncid, trim(dimension_name), unlimited, dimid)
867 call check_netcdf_code(err,
"Netcdf_add_dimension: file:"//trim(fileobj%path)//
" dimension name:"// &
868 & trim(dimension_name))
877 character(len=*),
intent(in) :: dimension_name
878 integer,
intent(in) :: dimension_length
879 logical,
intent(in),
optional :: is_compressed
885 integer,
dimension(:),
allocatable :: npes_start
886 integer,
dimension(:),
allocatable :: npes_count
891 dim_len = dimension_length
892 if (
present(is_compressed))
then
893 if (is_compressed)
then
895 allocate(npes_start(
size(fileobj%pelist)))
896 allocate(npes_count(
size(fileobj%pelist)))
897 do i = 1,
size(fileobj%pelist)
898 if (fileobj%pelist(i) .eq.
mpp_pe())
then
899 npes_count(i) = dim_len
901 call mpp_recv(npes_count(i), fileobj%pelist(i), block=.false.)
902 call mpp_send(dim_len, fileobj%pelist(i))
908 do i = 1,
size(fileobj%pelist)-1
909 npes_start(i+1) = npes_start(i) + npes_count(i)
913 dim_len = sum(npes_count)
916 if ((fileobj%is_root) .and. .not. fileobj%is_readonly)
then
918 err = nf90_def_dim(fileobj%ncid, trim(dimension_name), dim_len, dimid)
919 call check_netcdf_code(err,
"Netcdf_add_dimension: file:"//trim(fileobj%path)//
" dimension name:"// &
920 & trim(dimension_name))
927 npes_corner, npes_nelems)
930 character(len=*),
intent(in) :: dimension_name
931 integer,
dimension(:),
intent(in) :: npes_corner
933 integer,
dimension(:),
intent(in) :: npes_nelems
941 dsize = sum(npes_nelems)
942 if (fileobj%is_readonly)
then
944 if (fdim_size .ne. dsize)
then
945 call error(
"dimension "//trim(dimension_name)//
" does not match" &
946 //
" the size of the associated compressed axis.")
958 character(len=*),
intent(in) :: variable_name
959 character(len=*),
intent(in) :: variable_type
962 character(len=*),
dimension(:),
intent(in),
optional :: dimensions
963 integer,
optional,
intent(in) :: chunksizes(:)
967 integer,
dimension(:),
allocatable :: dimids
971 character(len=200) :: append_error_msg
973 append_error_msg =
"netcdf_add_variable: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name)
975 if (fileobj%is_root)
then
980 if ( .not. fileobj%is_netcdf4)
call error(trim(fileobj%path)//&
981 &
": 64 bit integers are only supported with 'netcdf4' file format"//&
982 &
". Set netcdf_default_format='netcdf4' in the fms2_io namelist OR "//&
983 &
"add nc_format='netcdf4' to your open_file call")
991 if (.not.
present(dimensions))
then
992 call error(
"String variables require a string length dimension:"//trim(append_error_msg))
995 call error(
"Unsupported variable type:"//trim(append_error_msg))
997 if (
present(dimensions))
then
998 allocate(dimids(
size(dimensions)))
999 do i = 1,
size(dimids)
1000 dimids(i) =
get_dimension_id(fileobj%ncid, trim(dimensions(i)),msg=append_error_msg)
1002 if (fileobj%is_netcdf4)
then
1003 err = nf90_def_var(fileobj%ncid, trim(variable_name), vtype, dimids, varid, &
1007 &
call mpp_error(note,
"Not able to use deflate_level or chunksizes if not using netcdf4"// &
1009 err = nf90_def_var(fileobj%ncid, trim(variable_name), vtype, dimids, varid)
1013 err = nf90_def_var(fileobj%ncid, trim(variable_name), vtype, varid)
1018 if (fileobj%use_netcdf_mpi)
then
1019 err = nf90_var_par_access(fileobj%ncid, varid, nf90_collective)
1029 result(compressed_dimension_index)
1032 character(len=*),
intent(in) :: variable_name
1033 logical,
intent(in),
optional :: broadcast
1039 integer,
dimension(2) :: compressed_dimension_index
1042 character(len=nf90_max_name),
dimension(:),
allocatable :: dim_names
1046 compressed_dimension_index = dimension_not_found
1047 if (fileobj%is_root)
then
1049 if (ndims .gt. 0)
then
1050 allocate(dim_names(ndims))
1052 do i = 1,
size(dim_names)
1054 if (j .ne. dimension_not_found)
then
1055 compressed_dimension_index(1) = i
1056 compressed_dimension_index(2) = j
1060 deallocate(dim_names)
1063 if (
present(broadcast))
then
1064 if (.not. broadcast)
then
1068 call mpp_broadcast(compressed_dimension_index(1), fileobj%io_root, pelist=fileobj%pelist)
1069 call mpp_broadcast(compressed_dimension_index(2), fileobj%io_root, pelist=fileobj%pelist)
1078 character(len=*),
intent(in) :: variable_name
1082 if (.not. fileobj%is_restart)
then
1083 call error(
"file "//trim(fileobj%path)//
" is not a restart file.")
1085 do i = 1, fileobj%num_restart_vars
1086 if (
string_compare(fileobj%restart_vars(i)%varname, variable_name, .true.))
then
1087 call error(
"variable "//trim(variable_name)//
" has already" &
1088 //
" been added to restart file "//trim(fileobj%path)//
".")
1091 fileobj%num_restart_vars = fileobj%num_restart_vars + 1
1092 if (fileobj%num_restart_vars .gt. max_num_restart_vars)
then
1093 call error(
"Number of restart variables exceeds limit.")
1095 call string_copy(fileobj%restart_vars(fileobj%num_restart_vars)%varname, &
1105 integer,
intent(in),
optional :: unlim_dim_level
1110 if (.not. fileobj%is_restart)
then
1111 call error(
"write_restart:: file "//trim(fileobj%path)//
" is not a restart file. &
1112 &Be sure the file was opened with is_restart=.true.")
1114 do i = 1, fileobj%num_restart_vars
1115 if (
associated(fileobj%restart_vars(i)%data0d))
then
1117 fileobj%restart_vars(i)%data0d, &
1118 unlim_dim_level=unlim_dim_level)
1119 elseif (
associated(fileobj%restart_vars(i)%data1d))
then
1121 fileobj%restart_vars(i)%data1d, &
1122 unlim_dim_level=unlim_dim_level)
1123 elseif (
associated(fileobj%restart_vars(i)%data2d))
then
1125 fileobj%restart_vars(i)%data2d, &
1126 unlim_dim_level=unlim_dim_level)
1127 elseif (
associated(fileobj%restart_vars(i)%data3d))
then
1129 fileobj%restart_vars(i)%data3d, &
1130 unlim_dim_level=unlim_dim_level)
1131 elseif (
associated(fileobj%restart_vars(i)%data4d))
then
1133 fileobj%restart_vars(i)%data4d, &
1134 unlim_dim_level=unlim_dim_level)
1136 call error(
"this branch should not be reached.")
1147 integer,
intent(in),
optional :: unlim_dim_level
1152 if (.not. fileobj%is_restart)
then
1153 call error(
"read_restart:: file "//trim(fileobj%path)//
" is not a restart file. &
1154 &Be sure the file was opened with is_restart=.true.")
1156 do i = 1, fileobj%num_restart_vars
1157 if (
associated(fileobj%restart_vars(i)%data0d))
then
1159 fileobj%restart_vars(i)%data0d, &
1160 unlim_dim_level=unlim_dim_level, &
1162 elseif (
associated(fileobj%restart_vars(i)%data1d))
then
1164 fileobj%restart_vars(i)%data1d, &
1165 unlim_dim_level=unlim_dim_level, &
1167 elseif (
associated(fileobj%restart_vars(i)%data2d))
then
1169 fileobj%restart_vars(i)%data2d, &
1170 unlim_dim_level=unlim_dim_level, &
1172 elseif (
associated(fileobj%restart_vars(i)%data3d))
then
1174 fileobj%restart_vars(i)%data3d, &
1175 unlim_dim_level=unlim_dim_level, &
1177 elseif (
associated(fileobj%restart_vars(i)%data4d))
then
1179 fileobj%restart_vars(i)%data4d, &
1180 unlim_dim_level=unlim_dim_level, &
1183 call error(
"this branch should not be reached.")
1195 character(len=*),
intent(in) :: attribute_name
1196 logical,
intent(in),
optional :: broadcast
1202 logical :: att_exists
1204 if (fileobj%is_root)
then
1205 att_exists =
attribute_exists(fileobj%ncid, nf90_global, trim(attribute_name), &
1206 & msg=
"global_att_exists: file:"//trim(fileobj%path)//
" attribute name:"//trim(attribute_name))
1208 if (
present(broadcast))
then
1209 if (.not. broadcast)
then
1213 call mpp_broadcast(att_exists, fileobj%io_root, pelist=fileobj%pelist)
1224 character(len=*),
intent(in) :: variable_name
1225 character(len=*),
intent(in) :: attribute_name
1226 logical,
intent(in),
optional :: broadcast
1232 logical :: att_exists
1236 att_exists = .false.
1237 if (fileobj%is_root)
then
1239 & msg=
"variable_att_exists: file:"//trim(fileobj%path)//
"- variable:"//&
1240 &trim(variable_name))
1242 &msg=
"variable_att_exists: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name)//&
1243 &
" attribute name:"//trim(attribute_name))
1245 if (
present(broadcast))
then
1246 if (.not. broadcast)
then
1250 call mpp_broadcast(att_exists, fileobj%io_root, pelist=fileobj%pelist)
1260 logical,
intent(in),
optional :: broadcast
1270 if (fileobj%is_root)
then
1271 err = nf90_inquire(fileobj%ncid, ndimensions=ndims)
1274 if (
present(broadcast))
then
1275 if (.not. broadcast)
then
1279 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1287 character(len=*),
dimension(:),
intent(inout) :: names
1289 logical,
intent(in),
optional :: broadcast
1300 if (fileobj%is_root)
then
1302 if (ndims .gt. 0)
then
1303 if (
size(names) .ne. ndims)
then
1304 call error(
"'names' has to be the same size of the number of dimensions. &
1305 &Check your get_dimension_names call for file "//trim(fileobj%path))
1308 call error(
"get_dimension_names: the file "//trim(fileobj%path)//
" does not have any dimensions")
1312 err = nf90_inquire_dimension(fileobj%ncid, i, name=names(i))
1316 if (
present(broadcast))
then
1317 if (.not. broadcast)
then
1321 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1322 if (.not. fileobj%is_root)
then
1323 if (ndims .gt. 0)
then
1324 if (
size(names) .ne. ndims)
then
1325 call error(
"'names' has to be the same size of the number of dimensions. &
1326 &Check your get_dimension_names call for file "//trim(fileobj%path))
1329 call error(
"get_dimension_names: the file "//trim(fileobj%path)//
" does not have any dimensions")
1333 call mpp_broadcast(names, len(names(ndims)), fileobj%io_root, &
1334 pelist=fileobj%pelist)
1344 character(len=*),
intent(in) :: dimension_name
1345 logical,
intent(in),
optional :: broadcast
1351 logical :: dim_exists
1355 if (fileobj%is_root)
then
1357 msg=
"dimension_exists: file:"//trim(fileobj%path)//
" dimension:"//trim(dimension_name), &
1358 allow_failure=.true.)
1359 if (dimid .eq. dimension_missing)
then
1360 dim_exists = .false.
1365 if (
present(broadcast))
then
1366 if (.not. broadcast)
then
1370 call mpp_broadcast(dim_exists, fileobj%io_root, pelist=fileobj%pelist)
1377 result(is_unlimited)
1380 character(len=*),
intent(in) :: dimension_name
1381 logical,
intent(in),
optional :: broadcast
1387 logical :: is_unlimited
1389 character(len=200) :: append_error_msg
1392 integer :: ulim_dimid
1394 if (fileobj%is_root)
then
1395 append_error_msg=
"is_dimension_unlimited: file:"//trim(fileobj%path)//&
1396 &
" dimension_name:"//trim(dimension_name)
1397 dimid =
get_dimension_id(fileobj%ncid, trim(dimension_name), msg=append_error_msg)
1398 err = nf90_inquire(fileobj%ncid, unlimiteddimid=ulim_dimid)
1400 is_unlimited = dimid .eq. ulim_dimid
1402 if (
present(broadcast))
then
1403 if (.not. broadcast)
then
1407 call mpp_broadcast(is_unlimited, fileobj%io_root, pelist=fileobj%pelist)
1415 character(len=*),
intent(out) :: dimension_name
1416 logical,
intent(in),
optional :: broadcast
1425 character(len=nf90_max_name),
dimension(1) :: buffer
1428 if (fileobj%is_root)
then
1429 err = nf90_inquire(fileobj%ncid, unlimiteddimid=dimid)
1430 call check_netcdf_code(err,
"get_unlimited_dimension_name: file:"//trim(fileobj%path))
1431 err = nf90_inquire_dimension(fileobj%ncid, dimid, dimension_name)
1432 call check_netcdf_code(err,
"get_unlimited_dimension_name: file:"//trim(fileobj%path))
1433 call string_copy(buffer(1), dimension_name)
1435 if (
present(broadcast))
then
1436 if (.not. broadcast)
then
1440 call mpp_broadcast(buffer, nf90_max_name, fileobj%io_root, &
1441 pelist=fileobj%pelist)
1442 call string_copy(dimension_name, buffer(1))
1450 character(len=*),
intent(in) :: dimension_name
1451 integer,
intent(inout) :: dim_size
1452 logical,
intent(in),
optional :: broadcast
1461 character(len=200) :: append_error_msg
1463 if (fileobj%is_root)
then
1464 append_error_msg =
"get_dimension_size: file:"//trim(fileobj%path)//
" dimension_name: "//trim(dimension_name)
1465 dimid =
get_dimension_id(fileobj%ncid, trim(dimension_name), msg=append_error_msg)
1466 err = nf90_inquire_dimension(fileobj%ncid, dimid, len=dim_size)
1469 if (
present(broadcast))
then
1470 if (.not. broadcast)
then
1474 call mpp_broadcast(dim_size, fileobj%io_root, pelist=fileobj%pelist)
1484 logical,
intent(in),
optional :: broadcast
1494 if (fileobj%is_root)
then
1495 err = nf90_inquire(fileobj%ncid, nvariables=nvars)
1498 if (
present(broadcast))
then
1499 if (.not. broadcast)
then
1503 call mpp_broadcast(nvars, fileobj%io_root, pelist=fileobj%pelist)
1511 character(len=*),
dimension(:),
intent(inout) :: names
1513 logical,
intent(in),
optional :: broadcast
1524 if (fileobj%is_root)
then
1526 if (nvars .gt. 0)
then
1527 if (
size(names) .ne. nvars)
then
1528 call error(
"'names' has to be the same size of the number of variables. &
1529 &Check your get_variable_names call for file "//trim(fileobj%path))
1532 call error(
"get_variable_names: the file "//trim(fileobj%path)//
" does not have any variables")
1536 err = nf90_inquire_variable(fileobj%ncid, i, name=names(i))
1540 if (
present(broadcast))
then
1541 if (.not. broadcast)
then
1545 call mpp_broadcast(nvars, fileobj%io_root, pelist=fileobj%pelist)
1546 if (.not. fileobj%is_root)
then
1547 if (nvars .gt. 0)
then
1548 if (
size(names) .ne. nvars)
then
1549 call error(
"'names' has to be the same size of the number of variables. &
1550 &Check your get_variable_names call for file "//trim(fileobj%path))
1553 call error(
"get_variable_names: the file "//trim(fileobj%path)//
" does not have any variables")
1557 call mpp_broadcast(names, len(names(nvars)), fileobj%io_root, &
1558 pelist=fileobj%pelist)
1568 character(len=*),
intent(in) :: variable_name
1569 logical,
intent(in),
optional :: broadcast
1575 logical :: var_exists
1579 if (fileobj%is_root)
then
1581 msg=
"variable_exists: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name), &
1582 allow_failure=.true.)
1583 var_exists = varid .ne. variable_missing
1585 if (
present(broadcast))
then
1586 if (.not. broadcast)
then
1590 call mpp_broadcast(var_exists, fileobj%io_root, pelist=fileobj%pelist)
1600 character(len=*),
intent(in) :: variable_name
1601 logical,
intent(in),
optional :: broadcast
1611 character(len=200) :: append_error_msg
1614 if (fileobj%is_root)
then
1615 append_error_msg =
"get_variable_num_dimension: file:"//trim(fileobj%path)//
" variable: "//trim(variable_name)
1616 varid =
get_variable_id(fileobj%ncid, trim(variable_name), msg=append_error_msg)
1617 err = nf90_inquire_variable(fileobj%ncid, varid, ndims=ndims)
1620 if (
present(broadcast))
then
1621 if (.not. broadcast)
then
1625 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1634 character(len=*),
intent(in) :: variable_name
1635 character(len=*),
dimension(:),
intent(inout) :: dim_names
1638 logical,
intent(in),
optional :: broadcast
1648 integer,
dimension(nf90_max_var_dims) :: dimids
1650 character(len=200) :: append_error_msg
1653 if (fileobj%is_root)
then
1654 append_error_msg =
"get_variable_dimension_names: file:"//trim(fileobj%path)//
" variable: "//trim(variable_name)
1656 varid =
get_variable_id(fileobj%ncid, trim(variable_name), msg=append_error_msg)
1657 err = nf90_inquire_variable(fileobj%ncid, varid, ndims=ndims, &
1660 if (ndims .gt. 0)
then
1661 if (
size(dim_names) .ne. ndims)
then
1662 call error(
"'names' has to be the same size of the number of dimensions for the variable. &
1663 &Check your get_variable_dimension_names call for file "//trim(fileobj%path)// &
1664 " and variable:"//trim(variable_name))
1667 call error(
"get_variable_dimension_names: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)&
1668 & //
" does not any dimensions. ")
1672 err = nf90_inquire_dimension(fileobj%ncid, dimids(i), name=dim_names(i))
1676 if (
present(broadcast))
then
1677 if (.not. broadcast)
then
1681 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1682 if (.not. fileobj%is_root)
then
1683 if (ndims .gt. 0)
then
1684 if (
size(dim_names) .ne. ndims)
then
1685 call error(
"'names' has to be the same size of the number of dimensions for the variable. &
1686 & Check your get_variable_dimension_names call for file "//trim(fileobj%path)// &
1687 " and variable:"//trim(variable_name))
1690 call error(
"get_variable_dimension_names: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)&
1691 & //
" does not any dimensions. ")
1695 call mpp_broadcast(dim_names, len(dim_names(ndims)), fileobj%io_root, &
1696 pelist=fileobj%pelist)
1704 character(len=*),
intent(in) :: variable_name
1705 integer,
dimension(:),
intent(inout) :: dim_sizes
1707 logical,
intent(in),
optional :: broadcast
1717 integer,
dimension(nf90_max_var_dims) :: dimids
1719 character(len=200) :: append_error_msg
1721 if (fileobj%is_root)
then
1722 append_error_msg =
"get_variable_size: file:"//trim(fileobj%path)//
" variable:"//trim(variable_name)
1723 varid =
get_variable_id(fileobj%ncid, trim(variable_name), msg=append_error_msg)
1724 err = nf90_inquire_variable(fileobj%ncid, varid, ndims=ndims, dimids=dimids)
1726 if (ndims .gt. 0)
then
1727 if (
size(dim_sizes) .ne. ndims)
then
1728 call error(
"'dim_sizes' has to be the same size of the number of dimensions for the variable. &
1729 &Check your get_variable_size call for file "//trim(fileobj%path)// &
1730 " and variable:"//trim(variable_name))
1733 call error(
"get_variable_size: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)//&
1734 &
" does not any dimensions. ")
1737 err = nf90_inquire_dimension(fileobj%ncid, dimids(i), len=dim_sizes(i))
1741 if (
present(broadcast))
then
1742 if (.not. broadcast)
then
1746 call mpp_broadcast(ndims, fileobj%io_root, pelist=fileobj%pelist)
1747 if (.not. fileobj%is_root)
then
1748 if (ndims .gt. 0)
then
1749 if (
size(dim_sizes) .ne. ndims)
then
1750 call error(
"'dim_sizes' has to be the same size of the number of dimensions for the variable. &
1751 &Check your get_variable_size call for file "//trim(fileobj%path)// &
1752 " and variable:"//trim(variable_name))
1755 call error(
"get_variable_size: the variable: "//trim(variable_name)//
" in file: "//trim(fileobj%path)//&
1756 &
" does not any dimensions. ")
1759 call mpp_broadcast(dim_sizes, ndims, fileobj%io_root, pelist=fileobj%pelist)
1768 result(unlim_dim_index)
1771 character(len=*),
intent(in) :: variable_name
1772 logical,
intent(in),
optional :: broadcast
1778 integer :: unlim_dim_index
1781 character(len=nf90_max_name),
dimension(:),
allocatable :: dim_names
1784 unlim_dim_index = no_unlimited_dimension
1785 if (fileobj%is_root)
then
1787 allocate(dim_names(ndims))
1790 do i = 1,
size(dim_names)
1796 deallocate(dim_names)
1798 if (
present(broadcast))
then
1799 if (.not. broadcast)
then
1803 call mpp_broadcast(unlim_dim_index, fileobj%io_root, pelist=fileobj%pelist)
1814 character(len=*),
intent(in) :: variable_name
1818 real(kind=r8_kind) :: scale_factor
1819 real(kind=r8_kind) :: add_offset
1820 real(kind=r8_kind),
dimension(2) :: buffer
1822 character(len=200) :: append_error_msg
1824 append_error_msg =
"get_valid: file:"//trim(fileobj%path)
1825 if (fileobj%is_root)
then
1826 varid =
get_variable_id(fileobj%ncid, variable_name, msg=append_error_msg)
1827 valid%has_max = .false.
1828 valid%has_min = .false.
1829 valid%has_fill = .false.
1830 valid%has_missing = .false.
1831 valid%has_range = .false.
1835 if (
attribute_exists(fileobj%ncid, varid,
"scale_factor", msg=append_error_msg))
then
1839 scale_factor = 1._r8_kind
1841 if (
attribute_exists(fileobj%ncid, varid,
"add_offset", msg=append_error_msg))
then
1845 add_offset = 0._r8_kind
1852 if (
attribute_exists(fileobj%ncid, varid,
"valid_range", msg=append_error_msg))
then
1855 valid%max_val = buffer(2)*scale_factor + add_offset
1856 valid%has_max = .true.
1857 valid%min_val = buffer(1)*scale_factor + add_offset
1858 valid%has_min = .true.
1860 if (
attribute_exists(fileobj%ncid, varid,
"valid_max", msg=append_error_msg))
then
1863 valid%max_val = buffer(1)*scale_factor + add_offset
1864 valid%has_max = .true.
1866 if (
attribute_exists(fileobj%ncid, varid,
"valid_min", msg=append_error_msg))
then
1869 valid%min_val = buffer(1)*scale_factor + add_offset
1870 valid%has_min = .true.
1873 valid%has_range = valid%has_min .or. valid%has_max
1877 if (
attribute_exists(fileobj%ncid, varid,
"missing_value", msg=append_error_msg))
then
1880 valid%missing_val = buffer(1)*scale_factor + add_offset
1881 valid%has_missing = .true.
1892 if (
attribute_exists(fileobj%ncid, varid,
"_FillValue", msg=append_error_msg))
then
1895 valid%fill_val = buffer(1)*scale_factor + add_offset
1896 valid%has_fill = .true.
1899 if (.not. valid%has_range)
then
1900 if (xtype .eq. nf90_short .or. xtype .eq. nf90_int)
then
1901 if (buffer(1) .gt. 0)
then
1902 valid%max_val = (buffer(1) - 1._r8_kind)*scale_factor + add_offset
1903 valid%has_max = .true.
1905 valid%min_val = (buffer(1) + 1._r8_kind)*scale_factor + add_offset
1906 valid%has_min = .true.
1908 elseif (xtype .eq. nf90_float .or. xtype .eq. nf90_double)
then
1909 if (buffer(1) .gt. 0)
then
1910 valid%max_val = (nearest(nearest(buffer(1), -1._r8_kind), -1._r8_kind)) &
1911 *scale_factor + add_offset
1912 valid%has_max = .true.
1914 valid%min_val = (nearest(nearest(buffer(1), 1._r8_kind), 1._r8_kind)) &
1915 *scale_factor + add_offset
1916 valid%has_min = .true.
1919 call error(
"Unsupported variable type:"//trim(append_error_msg))
1921 valid%has_range = .true.
1927 call mpp_broadcast(valid%has_min, fileobj%io_root, pelist=fileobj%pelist)
1928 if (valid%has_min)
then
1929 call mpp_broadcast(valid%min_val, fileobj%io_root, pelist=fileobj%pelist)
1931 call mpp_broadcast(valid%has_max, fileobj%io_root, pelist=fileobj%pelist)
1932 if (valid%has_max)
then
1933 call mpp_broadcast(valid%max_val, fileobj%io_root, pelist=fileobj%pelist)
1935 call mpp_broadcast(valid%has_range, fileobj%io_root, pelist=fileobj%pelist)
1937 call mpp_broadcast(valid%has_fill, fileobj%io_root, pelist=fileobj%pelist)
1938 if (valid%has_fill)
then
1939 call mpp_broadcast(valid%fill_val, fileobj%io_root, pelist=fileobj%pelist)
1942 call mpp_broadcast(valid%has_missing, fileobj%io_root, pelist=fileobj%pelist)
1943 if (valid%has_missing)
then
1944 call mpp_broadcast(valid%missing_val, fileobj%io_root, pelist=fileobj%pelist)
1954 real(kind=r8_kind),
intent(in) :: datum
1955 type(
valid_t),
intent(in) :: validobj
1956 logical :: valid_data
1967 real(kind=r4_kind),
intent(in) :: datum
1968 type(
valid_t),
intent(in) :: validobj
1969 logical :: valid_data
1971 real(kind=r8_kind) :: rdatum
1974 rdatum = real(datum, kind=r8_kind)
1984 real(kind=r8_kind),
intent(in) :: rdatum
1985 type(
valid_t),
intent(in) :: validobj
1986 logical :: valid_data
1991 if (validobj%has_range)
then
1992 if (validobj%has_min .and. .not. validobj%has_max)
then
1993 valid_data = rdatum .ge. validobj%min_val
1994 elseif (validobj%has_max .and. .not. validobj%has_min)
then
1995 valid_data = rdatum .le. validobj%max_val
1997 valid_data = .not. (rdatum .lt. validobj%min_val .or. rdatum .gt. validobj%max_val)
2002 if (validobj%has_fill .or. validobj%has_missing)
then
2003 if (validobj%has_fill .and. .not. validobj%has_missing)
then
2004 valid_data = rdatum .ne. validobj%fill_val
2005 elseif (validobj%has_missing .and. .not. validobj%has_fill)
then
2006 valid_data = rdatum .ne. validobj%missing_val
2008 valid_data = .not. (rdatum .eq. validobj%missing_val .or. rdatum .eq. validobj%fill_val)
2018 integer,
intent(in) :: nelems
2019 integer,
dimension(:),
allocatable,
intent(out) :: npes_start
2020 integer,
dimension(:),
allocatable,
intent(out) :: npes_count
2025 allocate(npes_start(
size(fileobj%pelist)))
2026 allocate(npes_count(
size(fileobj%pelist)))
2027 do i = 1,
size(fileobj%pelist)
2028 if (fileobj%pelist(i) .eq.
mpp_pe())
then
2029 npes_count(i) = nelems
2031 call mpp_recv(npes_count(i), fileobj%pelist(i), block=.false.)
2032 call mpp_send(nelems, fileobj%pelist(i))
2038 do i = 1,
size(fileobj%pelist)-1
2039 npes_start(i+1) = npes_start(i) + npes_count(i)
2044 include
"netcdf_add_restart_variable.inc"
2045 include
"netcdf_read_data.inc"
2046 include
"netcdf_write_data.inc"
2047 include
"register_global_attribute.inc"
2048 include
"register_variable_attribute.inc"
2049 include
"get_global_attribute.inc"
2050 include
"get_variable_attribute.inc"
2051 include
"compressed_write.inc"
2052 include
"compressed_read.inc"
2053 include
"scatter_data_bc.inc"
2054 include
"gather_data_bc.inc"
2055 include
"unpack_data.inc"
2062 character(len=*),
intent(in) :: path
2063 character(len=*),
intent(in) :: mode
2066 character(len=*),
intent(in),
optional :: nc_format
2072 integer,
dimension(:),
intent(in),
optional :: pelist
2077 logical,
intent(in),
optional :: is_restart
2080 logical,
intent(in),
optional :: dont_add_res_to_filename
2084 success =
netcdf_file_open(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
2101 character(len=*),
intent(in) :: variable_name
2102 character(len=*),
intent(in) :: variable_type
2105 character(len=*),
dimension(:),
intent(in),
optional :: dimensions
2106 integer,
intent(in),
optional :: chunksizes(:)
2115 integer,
intent(in),
optional :: unlim_dim_level
2128 character(len=*),
intent(in) :: variable_name
2129 class(*),
intent(out) :: fill_value
2130 logical,
intent(in),
optional :: broadcast
2136 logical :: fill_exists
2138 character(len=32),
dimension(2) :: attribute_names
2142 fill_exists = .false.
2143 call string_copy(attribute_names(1),
"_FillValue")
2144 call string_copy(attribute_names(2),
"missing_value")
2145 if (
present(broadcast))
then
2150 do i = 1,
size(attribute_names)
2153 if (fill_exists)
then
2155 fill_value, broadcast=bcast)
2162 function get_variable_sense(fileobj, variable_name) &
2163 result(variable_sense)
2166 character(len=*),
intent(in) :: variable_name
2167 integer :: variable_sense
2169 character(len=256) :: buf
2180 end function get_variable_sense
2183 function get_variable_missing(fileobj, variable_name) &
2184 result(variable_missing)
2187 character(len=*),
intent(in) :: variable_name
2188 real(kind=r8_kind) :: variable_missing
2190 real(kind=r8_kind) :: variable_missing_1d(1)
2199 variable_missing_1d = mpp_fill_double
2202 variable_missing = variable_missing_1d(1)
2204 end function get_variable_missing
2207 subroutine get_variable_units(fileobj, variable_name, units)
2210 character(len=*),
intent(in) :: variable_name
2211 character(len=*),
intent(out) :: units
2218 end subroutine get_variable_units
2221 subroutine get_time_calendar(fileobj, time_name, calendar_type)
2224 character(len=*),
intent(in) :: time_name
2225 character(len=*),
intent(out) :: calendar_type
2232 calendar_type =
"unspecified"
2234 end subroutine get_time_calendar
2240 result(is_registered)
2243 character(len=*),
intent(in) :: variable_name
2244 logical :: is_registered
2248 if (.not. fileobj%is_restart)
then
2249 call error(
"file "//trim(fileobj%path)//
" is not a restart file. &
2250 &Add is_restart=.true. to your open_file call")
2252 is_registered = .false.
2253 do i = 1, fileobj%num_restart_vars
2254 if (
string_compare(fileobj%restart_vars(i)%varname, variable_name, .true.))
then
2255 is_registered = .true.
2265 character(len=*),
intent(in),
optional :: fname
2268 if (
allocated(fileobj%is_open))
then
2269 is_open = fileobj%is_open
2274 if (
present(fname))
then
2277 if (is_open .AND. trim(fname) .ne. trim(fileobj%path)) is_open = .false.
2281 subroutine set_fileobj_time_name (fileobj,time_name)
2283 character(*),
intent(in) :: time_name
2284 integer :: len_of_name
2285 len_of_name = len(trim(time_name))
2286 fileobj%time_name =
' '
2287 fileobj%time_name = time_name(1:len_of_name)
2294 end subroutine set_fileobj_time_name
2300 integer,
intent(in),
optional :: unlim_dim_level
2302 logical,
intent(in),
optional :: ignore_checksum
2306 if (.not. fileobj%is_restart)
then
2307 call error(
"file "//trim(fileobj%path)//
" is not a restart file.")
2310 do i = 1, fileobj%num_restart_vars
2312 if (.not.any(
mpp_pe().eq.fileobj%restart_vars(i)%bc_info%pelist(:))) cycle
2315 if (
associated(fileobj%restart_vars(i)%data2d))
then
2317 fileobj%restart_vars(i)%data2d, &
2318 fileobj%restart_vars(i)%bc_info, &
2319 unlim_dim_level = unlim_dim_level, &
2320 ignore_checksum=ignore_checksum)
2321 else if (
associated(fileobj%restart_vars(i)%data3d))
then
2323 fileobj%restart_vars(i)%data3d, &
2324 fileobj%restart_vars(i)%bc_info, &
2325 unlim_dim_level = unlim_dim_level, &
2326 ignore_checksum=ignore_checksum)
2337 integer,
intent(in),
optional :: unlim_dim_level
2341 if (.not. fileobj%is_restart)
then
2342 call error(
"file "//trim(fileobj%path)//
" is not a restart file. &
2343 &Add is_restart=.true. to your open_file call")
2351 do i = 1, fileobj%num_restart_vars
2353 if (.not.any(
mpp_pe().eq.fileobj%restart_vars(i)%bc_info%pelist(:))) cycle
2356 if (.not. fileobj%restart_vars(i)%is_bc_variable) cycle
2359 if (
associated(fileobj%restart_vars(i)%data2d))
then
2360 call gather_data_bc(fileobj, fileobj%restart_vars(i)%data2d, fileobj%restart_vars(i)%bc_info)
2362 fileobj%restart_vars(i)%bc_info%chksum(1:len(fileobj%restart_vars(i)%bc_info%chksum)),&
2363 str_len=len(fileobj%restart_vars(i)%bc_info%chksum))
2364 else if (
associated(fileobj%restart_vars(i)%data3d))
then
2365 call gather_data_bc(fileobj, fileobj%restart_vars(i)%data3d, fileobj%restart_vars(i)%bc_info)
2367 fileobj%restart_vars(i)%bc_info%chksum(1:len(fileobj%restart_vars(i)%bc_info%chksum)),&
2368 str_len=len(fileobj%restart_vars(i)%bc_info%chksum))
2373 do i = 1, fileobj%num_restart_vars
2374 if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata2d_r8 ))
then
2376 fileobj%restart_vars(i)%bc_info%globaldata2d_r8 , &
2377 unlim_dim_level=unlim_dim_level)
2378 deallocate(fileobj%restart_vars(i)%bc_info%globaldata2d_r8)
2379 else if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata2d_r4 ))
then
2381 fileobj%restart_vars(i)%bc_info%globaldata2d_r4 , &
2382 unlim_dim_level=unlim_dim_level)
2383 deallocate(fileobj%restart_vars(i)%bc_info%globaldata2d_r4)
2384 else if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata3d_r8 ))
then
2386 fileobj%restart_vars(i)%bc_info%globaldata3d_r8 , &
2387 unlim_dim_level=unlim_dim_level)
2388 deallocate(fileobj%restart_vars(i)%bc_info%globaldata3d_r8)
2389 else if (
allocated(fileobj%restart_vars(i)%bc_info%globaldata3d_r4 ))
then
2391 fileobj%restart_vars(i)%bc_info%globaldata3d_r4 , &
2392 unlim_dim_level=unlim_dim_level)
2393 deallocate(fileobj%restart_vars(i)%bc_info%globaldata3d_r4 )
2406 if (fileobj%is_root)
then
2407 err = nf90_sync(fileobj%ncid)
2419 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...
Receive 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 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.
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.
integer function, public get_variable_id(ncid, variable_name, msg, allow_failure)
Get the id of a variable from its name.
subroutine, public netcdf_add_variable_wrap(fileobj, variable_name, variable_type, dimensions, chunksizes)
Wrapper to distinguish interfaces.
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.
pure logical function is_file_using_netcdf_mpi(this)
Getter for use_netcdf_mpi.
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.