FMS  2025.04
Flexible Modeling System
fms_netcdf_unstructured_domain_io.F90
1 !***********************************************************************
2 !* Apache License 2.0
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* Licensed under the Apache License, Version 2.0 (the "License");
7 !* you may not use this file except in compliance with the License.
8 !* You may obtain a copy of the License at
9 !*
10 !* http://www.apache.org/licenses/LICENSE-2.0
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
14 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 !* PARTICULAR PURPOSE. See the License for the specific language
16 !* governing permissions and limitations under the License.
17 !***********************************************************************
18 !> @defgroup fms_netcdf_unstructured_domain_io_mod fms_netcdf_unstructured_domain_io_mod
19 !> @ingroup fms2_io
20 !> @brief Handles netcdf I/O for unstructured domains
21 !!
22 !> Mainly routines for use via interfaces in @ref fms2_io_mod
23 
24 module fms_netcdf_unstructured_domain_io_mod
25 use netcdf
26 use mpp_domains_mod
27 use fms_io_utils_mod
28 use netcdf_io_mod
29 use platform_mod
30 implicit none
31 private
32 
33 !> @brief netcdf unstructured domain file type.
34 !> @ingroup fms_netcdf_unstructured_domain_io_mod
36  type(domainug) :: domain !< Unstructured domain.
37  character(len=FMS_PATH_LEN) :: non_mangled_path !< Non-domain-mangled path.
39 
40 !> @addtogroup fms_netcdf_unstructured_domain_io_mod
41 !> @{
65 
66 
67 contains
68 
69 !> @brief Open a netcdf file that is associated with an unstructured domain.
70 !! @return Flag telling if the open completed successfully.
71 function open_unstructured_domain_file(fileobj, path, mode, domain, nc_format, &
72  is_restart, dont_add_res_to_filename) &
73  result(success)
74 
75  type(fmsnetcdfunstructureddomainfile_t), intent(inout) :: fileobj !< File object.
76  character(len=*), intent(in) :: path !< File path.
77  character(len=*), intent(in) :: mode !< File mode. Allowed values
78  !! are "read", "append", "write", or
79  !! "overwrite".
80  type(domainug), intent(in) :: domain !< Unstructured domain.
81  character(len=*), intent(in), optional :: nc_format !< Netcdf format that
82  !! new files are written
83  !! as. Allowed values
84  !! are: "64bit", "classic",
85  !! or "netcdf4". Defaults to
86  !! "64bit".
87  logical, intent(in), optional :: is_restart !< Flag telling if this file
88  !! is a restart file. Defaults
89  !! to false.
90  logical, intent(in), optional :: dont_add_res_to_filename !< Flag indicating not to add
91  !! ".res" to the filename
92  logical :: success
93 
94  type(domainug), pointer :: io_domain
95  integer :: pelist_size
96  integer, dimension(:), allocatable :: pelist
97  character(len=FMS_PATH_LEN) :: buf
98  character(len=FMS_PATH_LEN) :: buf2
99  integer :: tile_id
100 
101  !Get the input domain's I/O domain pelist.
102  io_domain => mpp_get_ug_io_domain(domain)
103  if (.not. associated(io_domain)) then
104  call error("The input domain associated with the file:"//trim(fileobj%path)//" does not have an io_domain.")
105  endif
106  pelist_size = mpp_get_ug_domain_npes(io_domain)
107  allocate(pelist(pelist_size))
108  call mpp_get_ug_domain_pelist(io_domain, pelist)
109 
110  !Add the domain tile id to the file name (if necessary).
111  call string_copy(buf, path)
112  if (mpp_get_ug_domain_ntiles(domain) .gt. 1) then
113  tile_id = mpp_get_ug_domain_tile_id(domain)
114  call domain_tile_filepath_mangle(buf, path, tile_id)
115  endif
116 
117  success = .false.
118  if (string_compare(mode, "read", .true.) .or. string_compare(mode, "append", .true.)) then
119  !Only for reading: attempt to open non-distributed files.
120  success = netcdf_file_open(fileobj, buf, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
121  endif
122  if (.not. success) then
123  !Add the domain tile id to the file name (if necessary).
124  if (mpp_get_io_domain_ug_layout(domain) .gt. 1) then
125  tile_id = mpp_get_ug_domain_tile_id(io_domain)
126  call string_copy(buf2, buf)
127  call io_domain_tile_filepath_mangle(buf, buf2, tile_id)
128  endif
129 
130  !Open distributed files.
131  success = netcdf_file_open(fileobj, buf, mode, nc_format, pelist, is_restart, dont_add_res_to_filename)
132  endif
133  deallocate(pelist)
134 
135  if (.not. success) then
136  !This branch should only be entered if the file attempting to be read
137  !does not exist.
138  return
139  endif
140 
141  !Store/initialize necessary properties.
142  fileobj%domain = domain
143  call string_copy(fileobj%non_mangled_path, path)
145 
146 
147 !> @brief Wrapper to distinguish interfaces.
149 
150  type(fmsnetcdfunstructureddomainfile_t), intent(inout) :: fileobj !< File object.
151 
152  call netcdf_file_close(fileobj)
153 end subroutine close_unstructured_domain_file
154 
155 
156 !> @brief Add an unstructured dimension.
157 subroutine register_unstructured_dimension(fileobj, dim_name)
158 
159  type(fmsnetcdfunstructureddomainfile_t), intent(inout) :: fileobj !< File object.
160  character(len=*), intent(in) :: dim_name !< Dimension name.
161 
162  type(domainug),pointer :: io_domain
163  integer, dimension(:), allocatable :: c
164  integer, dimension(:), allocatable :: e
165 
166  allocate(c(size(fileobj%pelist)))
167  allocate(e(size(fileobj%pelist)))
168  io_domain => mpp_get_ug_io_domain(fileobj%domain)
169  call mpp_get_ug_compute_domains(io_domain, begin=c, size=e)
170  if (c(1) .ne. 1) then
171  c(:) = c(:) - c(1) + 1
172  endif
173  call register_compressed_dimension(fileobj, dim_name, c, e)
174  deallocate(c)
175  deallocate(e)
176 end subroutine register_unstructured_dimension
177 
178 
179 !> @brief Wrapper to distinguish interfaces.
180 subroutine register_unstructured_domain_variable(fileobj, variable_name, &
181  variable_type, dimensions, chunksizes)
182 
183  type(fmsnetcdfunstructureddomainfile_t), intent(in) :: fileobj !< File object.
184  character(len=*), intent(in) :: variable_name !< Variable name.
185  character(len=*), intent(in) :: variable_type !< Variable type. Allowed
186  !! values are: "int", "int64",
187  !! "float", or "double".
188  character(len=*), dimension(:), intent(in), optional :: dimensions !< Dimension names.
189  integer, intent(in), optional :: chunksizes(:) !< netcdf chunksize to use for this variable (netcdf4 only)
190 
191  call netcdf_add_variable(fileobj, variable_name, variable_type, dimensions, chunksizes)
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, chunksizes)
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:742
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:547
subroutine, public register_compressed_dimension(fileobj, dimension_name, npes_corner, npes_nelems)
Add a compressed dimension.
Definition: netcdf_io.F90:928
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:1103
subroutine, public netcdf_add_variable(fileobj, variable_name, variable_type, dimensions, chunksizes)
Add a variable to a file.
Definition: netcdf_io.F90:956