FMS  2024.03
Flexible Modeling System
fms_netcdf_unstructured_domain_io.F90
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 !> @defgroup fms_netcdf_unstructured_domain_io_mod fms_netcdf_unstructured_domain_io_mod
20 !> @ingroup fms2_io
21 !> @brief Handles netcdf I/O for unstructured domains
22 !!
23 !> Mainly routines for use via interfaces in @ref fms2_io_mod
24 
25 module fms_netcdf_unstructured_domain_io_mod
26 use netcdf
27 use mpp_domains_mod
28 use fms_io_utils_mod
29 use netcdf_io_mod
30 use platform_mod
31 implicit none
32 private
33 
34 !> @brief netcdf unstructured domain file type.
35 !> @ingroup fms_netcdf_unstructured_domain_io_mod
37  type(domainug) :: domain !< Unstructured domain.
38  character(len=FMS_PATH_LEN) :: non_mangled_path !< Non-domain-mangled path.
40 
41 !> @addtogroup fms_netcdf_unstructured_domain_io_mod
42 !> @{
66 
67 
68 contains
69 
70 !> @brief Open a netcdf file that is associated with an unstructured domain.
71 !! @return Flag telling if the open completed successfully.
72 function open_unstructured_domain_file(fileobj, path, mode, domain, nc_format, &
73  is_restart, dont_add_res_to_filename) &
74  result(success)
75 
76  type(fmsnetcdfunstructureddomainfile_t), intent(inout) :: fileobj !< File object.
77  character(len=*), intent(in) :: path !< File path.
78  character(len=*), intent(in) :: mode !< File mode. Allowed values
79  !! are "read", "append", "write", or
80  !! "overwrite".
81  type(domainug), intent(in) :: domain !< Unstructured domain.
82  character(len=*), intent(in), optional :: nc_format !< Netcdf format that
83  !! new files are written
84  !! as. Allowed values
85  !! are: "64bit", "classic",
86  !! or "netcdf4". Defaults to
87  !! "64bit".
88  logical, intent(in), optional :: is_restart !< Flag telling if this file
89  !! is a restart file. Defaults
90  !! to false.
91  logical, intent(in), optional :: dont_add_res_to_filename !< Flag indicating not to add
92  !! ".res" to the filename
93  logical :: success
94 
95  type(domainug), pointer :: io_domain
96  integer :: pelist_size
97  integer, dimension(:), allocatable :: pelist
98  character(len=FMS_PATH_LEN) :: buf
99  character(len=FMS_PATH_LEN) :: buf2
100  integer :: tile_id
101 
102  !Get the input domain's I/O domain pelist.
103  io_domain => mpp_get_ug_io_domain(domain)
104  if (.not. associated(io_domain)) then
105  call error("The input domain associated with the file:"//trim(fileobj%path)//" does not have an io_domain.")
106  endif
107  pelist_size = mpp_get_ug_domain_npes(io_domain)
108  allocate(pelist(pelist_size))
109  call mpp_get_ug_domain_pelist(io_domain, pelist)
110 
111  !Add the domain tile id to the file name (if necessary).
112  call string_copy(buf, path)
113  if (mpp_get_ug_domain_ntiles(domain) .gt. 1) then
114  tile_id = mpp_get_ug_domain_tile_id(domain)
115  call domain_tile_filepath_mangle(buf, path, tile_id)
116  endif
117 
118  success = .false.
119  if (string_compare(mode, "read", .true.) .or. string_compare(mode, "append", .true.)) then
120  !Only for reading: attempt to open non-distributed files.
121  success = netcdf_file_open(fileobj, buf, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
122  endif
123  if (.not. success) then
124  !Add the domain tile id to the file name (if necessary).
125  if (mpp_get_io_domain_ug_layout(domain) .gt. 1) then
126  tile_id = mpp_get_ug_domain_tile_id(io_domain)
127  call string_copy(buf2, buf)
128  call io_domain_tile_filepath_mangle(buf, buf2, tile_id)
129  endif
130 
131  !Open distributed files.
132  success = netcdf_file_open(fileobj, buf, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
133  endif
134  deallocate(pelist)
135 
136  if (.not. success) then
137  !This branch should only be entered if the file attempting to be read
138  !does not exist.
139  return
140  endif
141 
142  !Store/initialize necessary properties.
143  fileobj%domain = domain
144  call string_copy(fileobj%non_mangled_path, path)
146 
147 
148 !> @brief Wrapper to distinguish interfaces.
150 
151  type(fmsnetcdfunstructureddomainfile_t), intent(inout) :: fileobj !< File object.
152 
153  call netcdf_file_close(fileobj)
154 end subroutine close_unstructured_domain_file
155 
156 
157 !> @brief Add an unstructured dimension.
158 subroutine register_unstructured_dimension(fileobj, dim_name)
159 
160  type(fmsnetcdfunstructureddomainfile_t), intent(inout) :: fileobj !< File object.
161  character(len=*), intent(in) :: dim_name !< Dimension name.
162 
163  type(domainug),pointer :: io_domain
164  integer, dimension(:), allocatable :: c
165  integer, dimension(:), allocatable :: e
166 
167  allocate(c(size(fileobj%pelist)))
168  allocate(e(size(fileobj%pelist)))
169  io_domain => mpp_get_ug_io_domain(fileobj%domain)
170  call mpp_get_ug_compute_domains(io_domain, begin=c, size=e)
171  if (c(1) .ne. 1) then
172  c(:) = c(:) - c(1) + 1
173  endif
174  call register_compressed_dimension(fileobj, dim_name, c, e)
175  deallocate(c)
176  deallocate(e)
177 end subroutine register_unstructured_dimension
178 
179 
180 !> @brief Wrapper to distinguish interfaces.
181 subroutine register_unstructured_domain_variable(fileobj, variable_name, &
182  variable_type, dimensions)
183 
184  type(fmsnetcdfunstructureddomainfile_t), intent(in) :: fileobj !< File object.
185  character(len=*), intent(in) :: variable_name !< Variable name.
186  character(len=*), intent(in) :: variable_type !< Variable type. Allowed
187  !! values are: "int", "int64",
188  !! "float", or "double".
189  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
190 
191  call netcdf_add_variable(fileobj, variable_name, variable_type, dimensions)
193 
194 
195 !> @brief Wrapper to distinguish interfaces.
196 subroutine unstructured_write_restart(fileobj, unlim_dim_level)
197 
198  type(fmsnetcdfunstructureddomainfile_t), intent(in) :: fileobj !< File object.
199  integer, intent(in), optional :: unlim_dim_level !< Unlimited dimension level.
200 
201  call netcdf_save_restart(fileobj, unlim_dim_level)
202 end subroutine unstructured_write_restart
203 
204 
205 include "register_unstructured_domain_restart_variable.inc"
206 include "unstructured_domain_read.inc"
207 include "unstructured_domain_write.inc"
208 
209 
210 end module fms_netcdf_unstructured_domain_io_mod
subroutine unstructured_domain_read_4d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Wrapper to distinguish interfaces.
subroutine unstructured_domain_write_2d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine register_unstructured_domain_restart_variable_4d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a domain decomposed variable.
subroutine unstructured_domain_read_3d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Wrapper to distinguish interfaces.
subroutine unstructured_domain_write_3d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine register_unstructured_domain_restart_variable_2d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a domain decomposed variable.
subroutine unstructured_domain_write_0d(fileobj, variable_name, variable_data, unlim_dim_level, corner)
Wrapper to distinguish interfaces.
subroutine unstructured_domain_read_0d(fileobj, variable_name, buf, unlim_dim_level, corner, broadcast)
Wrapper to distinguish interfaces.
subroutine unstructured_domain_write_4d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine register_unstructured_domain_restart_variable_3d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a domain decomposed variable.
subroutine unstructured_domain_read_5d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Wrapper to distinguish interfaces.
subroutine unstructured_domain_read_2d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Wrapper to distinguish interfaces.
subroutine register_unstructured_domain_restart_variable_1d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a domain decomposed variable.
subroutine register_unstructured_domain_restart_variable_5d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a domain decomposed variable.
subroutine unstructured_domain_write_1d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine unstructured_domain_write_5d(fileobj, variable_name, variable_data, unlim_dim_level, corner, edge_lengths)
Wrapper to distinguish interfaces.
subroutine register_unstructured_domain_restart_variable_0d(fileobj, variable_name, vdata, dimensions, is_optional, chunksizes)
Add a domain decomposed variable.
subroutine unstructured_domain_read_1d(fileobj, variable_name, buf, unlim_dim_level, corner, edge_lengths, broadcast)
Wrapper to distinguish interfaces.
subroutine, public error(mesg)
Print a message to stderr, then stop the program.
subroutine, public io_domain_tile_filepath_mangle(dest, source, io_domain_tile_id)
Add the I/O domain tile id to an input filepath.
logical function, public string_compare(string1, string2, ignore_case)
Compare strings.
subroutine, public domain_tile_filepath_mangle(dest, source, domain_tile_id)
Add the domain tile id to an input filepath.
subroutine, public register_unstructured_dimension(fileobj, dim_name)
Add an unstructured dimension.
logical function, public open_unstructured_domain_file(fileobj, path, mode, domain, nc_format, is_restart, dont_add_res_to_filename)
Open a netcdf file that is associated with an unstructured domain.
subroutine, public close_unstructured_domain_file(fileobj)
Wrapper to distinguish interfaces.
subroutine, public register_unstructured_domain_variable(fileobj, variable_name, variable_type, dimensions)
Wrapper to distinguish interfaces.
subroutine, public unstructured_write_restart(fileobj, unlim_dim_level)
Wrapper to distinguish interfaces.
Domain information for managing data on unstructured grids.
subroutine, public netcdf_file_close(fileobj)
Close a netcdf file.
Definition: netcdf_io.F90:729
logical function, public netcdf_file_open(fileobj, path, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
Open a netcdf file.
Definition: netcdf_io.F90:542
subroutine, public register_compressed_dimension(fileobj, dimension_name, npes_corner, npes_nelems)
Add a compressed dimension.
Definition: netcdf_io.F90:915
subroutine, public netcdf_save_restart(fileobj, unlim_dim_level)
Loop through registered restart variables and write them to a netcdf file.
Definition: netcdf_io.F90:1085
subroutine, public netcdf_add_variable(fileobj, variable_name, variable_type, dimensions, chunksizes)
Add a variable to a file.
Definition: netcdf_io.F90:943