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