FMS  2025.04
Flexible Modeling System
domain_write.inc
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 !> @file
19 !> @brief Routines for writing domain decomposed variables for the @ref write_data interface
20 
21 !> @addtogroup fms2_io_mod
22 !> @{
23 
24 !> @brief Gather "compute" domain data on the I/O root rank and then have
25 !! the I/O root write out the data that spans the "global" domain.
26 !! This routine may only be used with variables that are "domain
27 !! decomposed".
28 subroutine domain_write_0d(fileobj, variable_name, vdata, unlim_dim_level, corner)
29 
30  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
31  character(len=*), intent(in) :: variable_name !< Variable name.
32  class(*), intent(in) :: vdata !< Data that will
33  !! be written out
34  !! to the netcdf file.
35  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
36  !! dimension.
37  integer, intent(in), optional :: corner !< Array of starting
38  !! indices describing
39  !! where the data
40  !! will be written to.
41 
42  call compressed_write(fileobj, variable_name, vdata, &
43  unlim_dim_level=unlim_dim_level, corner=corner)
44 
45 end subroutine domain_write_0d
46 
47 
48 !> @brief Gather "compute" domain data on the I/O root rank and then have
49 !! the I/O root write out the data that spans the "global" domain.
50 !! This routine may only be used with variables that are "domain
51 !! decomposed".
52 subroutine domain_write_1d(fileobj, variable_name, vdata, unlim_dim_level, &
53  corner, edge_lengths)
54 
55  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
56  character(len=*), intent(in) :: variable_name !< Variable name.
57  class(*), dimension(:), intent(in) :: vdata !< Data that will
58  !! be written out
59  !! to the netcdf file.
60  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
61  !! dimension.
62  integer, dimension(1), intent(in), optional :: corner !< Array of starting
63  !! indices describing
64  !! where the data
65  !! will be written to.
66  integer, dimension(1), intent(in), optional :: edge_lengths !< The number of
67  !! elements that
68  !! will be written
69  !! in each dimension.
70 
71  call compressed_write(fileobj, variable_name, vdata, &
72  unlim_dim_level=unlim_dim_level, corner=corner, &
73  edge_lengths=edge_lengths)
74 
75 end subroutine domain_write_1d
76 
77 
78 !> @brief Gather "compute" domain data on the I/O root rank and then have
79 !! the I/O root write out the data that spans the "global" domain.
80 !! This routine may only be used with variables that are "domain
81 !! decomposed" using mpp_gather.
82 subroutine domain_write_2d(fileobj, variable_name, vdata, unlim_dim_level, &
83  corner, edge_lengths)
84 
85  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
86  character(len=*), intent(in) :: variable_name !< Variable name.
87  class(*), contiguous, dimension(:,:), target, intent(in) :: vdata !< Data that will
88  !! be written out
89  !! to the netcdf file.
90  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
91  !! dimension.
92  integer, dimension(2), intent(in), optional :: corner !< Array of starting
93  !! indices describing
94  !! where the data
95  !! will be written to.
96  integer, dimension(2), intent(in), optional :: edge_lengths !< The number of
97  !! elements that
98  !! will be written
99  !! in each dimension.
100 
101  integer(kind=i4_kind), dimension(:,:), allocatable :: global_buf_i4_kind
102  integer(kind=i8_kind), dimension(:,:), allocatable :: global_buf_i8_kind
103  real(kind=r4_kind), dimension(:,:), allocatable :: global_buf_r4_kind
104  real(kind=r8_kind), dimension(:,:), allocatable :: global_buf_r8_kind
105  logical :: buffer_includes_halos
106  type(domain2d), pointer :: io_domain
107  integer :: isc
108  integer :: isd
109  integer :: jsc
110  integer :: jsd
111  integer :: xc_size
112  integer :: xdim_index
113  integer :: xpos
114  integer :: ydim_index
115  integer :: ypos
116  integer :: yc_size
117  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
118  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
119  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
120  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
121  class(*), dimension(:,:,:,:), pointer :: vdata_dummy !< Vdata remapped as 4D
122  integer :: xgmin !< Starting x index of the global io domain
123  integer :: ygmin !< Ending y index of the global io domain
124  integer :: xgsize, ygsize
125  integer :: istart, jstart, iend, jend
126  integer :: ioff, joff
127 
128  if (fileobj%use_netcdf_mpi) then
129  call netcdf_mpi_write_2d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
130  return
131  endif
132 
133  ! If the file is not domain decomposed, do not do anything in this routine
134  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
135  xdim_index, ydim_index, xpos, ypos)) then
136  call compressed_write(fileobj, variable_name, vdata, &
137  unlim_dim_level=unlim_dim_level, corner=corner, &
138  edge_lengths=edge_lengths)
139  return
140  endif
141 
142  if (xdim_index .ne. 1 .or. ydim_index .ne. 2) then
143  ! This is a KLUDGE
144  ! mpp_scatter assumes that the variable is (x,y), if that is not the case it remaps the data
145  ! to a 4D array and calls domain_read_4d which does not use mpp_scatter yet
146  vdata_dummy(1:size(vdata,1),1:size(vdata,2), 1:1, 1:1) => vdata(:,:)
147  call domain_write_4d(fileobj, variable_name, vdata_dummy, unlim_dim_level)
148  return
149  endif
150 
151  ! Get the io domain from the fileobj
152  io_domain => mpp_get_io_domain(fileobj%domain)
153 
154  ! Get some info about the domain:
155  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
156  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, buffer_includes_halos, &
157  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
158 
159  ! Get the global io domain:
160  call mpp_get_global_domain(io_domain, xbegin=xgmin, xsize=xgsize, position=xpos)
161  call mpp_get_global_domain(io_domain, ybegin=ygmin, ysize=ygsize, position=ypos)
162 
163  ! Root pe allocates room to gather the data and computes offsets for data placement
164  if (fileobj%is_root) then
165  ! Offsets used to place data in recv buffer
166  ioff = 1-xgmin
167  joff = 1-ygmin
168 
169  ! Allocate recv buffer for gather
170  select type(vdata)
171  type is (integer(kind=i4_kind))
172  allocate(global_buf_i4_kind(xgsize, ygsize))
173  global_buf_i4_kind = 0
174  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
175  global_buf_i4_kind = fill_i4_kind
176  endif
177  type is (integer(kind=i8_kind))
178  allocate(global_buf_i8_kind(xgsize, ygsize))
179  global_buf_i8_kind = 0
180  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
181  global_buf_i8_kind = fill_i8_kind
182  endif
183  type is (real(kind=r4_kind))
184  allocate(global_buf_r4_kind(xgsize, ygsize))
185  global_buf_r4_kind = 0.
186  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
187  global_buf_r4_kind = fill_r4_kind
188  endif
189  type is (real(kind=r8_kind))
190  allocate(global_buf_r8_kind(xgsize, ygsize))
191  global_buf_r8_kind = 0.
192  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
193  global_buf_r8_kind = fill_r8_kind
194  endif
195  class default
196  call error("unsupported variable type: domain_write_2d_mpp_gather: file: " &
197  & //trim(fileobj%path)//" variable:"//trim(variable_name))
198  end select
199  endif
200 
201  ! Get the starting and indices of the compute domain relative to vdata (note that vdata start indices at 1 #Fortran)
202  istart = 1
203  jstart = 1
204 
205  ! If the buffer contains halos, get the portion of vdata with only the compute domain
206  if (buffer_includes_halos) then
207  istart = isc - isd + 1
208  jstart = jsc - jsd + 1
209  endif
210 
211  iend = istart + xc_size - 1
212  jend = jstart + yc_size - 1
213 
214  ! Gather the data
215  select type(vdata)
216  type is (integer(kind=i4_kind))
217  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, fileobj%pelist, vdata(istart:iend, jstart:jend), &
218  & global_buf_i4_kind, fileobj%is_root, ishift=ioff, jshift=joff)
219  type is (integer(kind=i8_kind))
220  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, fileobj%pelist, vdata(istart:iend, jstart:jend), &
221  & global_buf_i8_kind, fileobj%is_root, ishift=ioff, jshift=joff)
222  type is (real(kind=r4_kind))
223  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, fileobj%pelist, vdata(istart:iend, jstart:jend), &
224  & global_buf_r4_kind, fileobj%is_root, ishift=ioff, jshift=joff)
225  type is (real(kind=r8_kind))
226  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, fileobj%pelist, vdata(istart:iend, jstart:jend), &
227  & global_buf_r8_kind, fileobj%is_root, ishift=ioff, jshift=joff)
228  class default
229  call error("unsupported variable type: domain_write_2d_mpp_gather: file: " &
230  & //trim(fileobj%path)//" variable:"// trim(variable_name))
231  end select
232 
233  ! Root pe writes out the data
234  if (fileobj%is_root) then
235  select type(vdata)
236  type is (integer(kind=i4_kind))
237  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
238  & unlim_dim_level=unlim_dim_level)
239  type is (integer(kind=i8_kind))
240  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
241  & unlim_dim_level=unlim_dim_level)
242  type is (real(kind=r4_kind))
243  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
244  & unlim_dim_level=unlim_dim_level)
245  type is (real(kind=r8_kind))
246  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
247  & unlim_dim_level=unlim_dim_level)
248  class default
249  call error("unsupported variable type: domain_write_2d_mpp_gather: file: " &
250  & //trim(fileobj%path)//" variable:"// trim(variable_name))
251  end select
252  endif
253 
254 end subroutine domain_write_2d
255 
256 
257 !> @brief Gather "compute" domain data on the I/O root rank and then have
258 !! the I/O root write out the data that spans the "global" domain.
259 !! This routine may only be used with variables that are "domain
260 !! decomposed" using mpp_gather.
261 subroutine domain_write_3d(fileobj, variable_name, vdata, unlim_dim_level, &
262  corner, edge_lengths)
263 
264  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
265  character(len=*), intent(in) :: variable_name !< Variable name.
266  class(*), contiguous, dimension(:,:,:), target, intent(in) :: vdata !< Data that will
267  !! be written out
268  !! to the netcdf file.
269  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
270  !! dimension.
271  integer, dimension(3), intent(in), optional :: corner !< Array of starting
272  !! indices describing
273  !! where the data
274  !! will be written to.
275  integer, dimension(3), intent(in), optional :: edge_lengths !< The number of
276  !! elements that
277  !! will be written
278  !! in each dimension.
279 
280  integer(kind=i4_kind), dimension(:,:,:), allocatable :: global_buf_i4_kind
281  integer(kind=i8_kind), dimension(:,:,:), allocatable :: global_buf_i8_kind
282  real(kind=r4_kind), dimension(:,:,:), allocatable :: global_buf_r4_kind
283  real(kind=r8_kind), dimension(:,:,:), allocatable :: global_buf_r8_kind
284  logical :: buffer_includes_halos
285  type(domain2d), pointer :: io_domain
286  integer :: isc
287  integer :: isd
288  integer :: jsc
289  integer :: jsd
290  integer :: xc_size
291  integer :: xdim_index
292  integer :: xpos
293  integer :: ydim_index
294  integer :: ypos
295  integer :: yc_size
296  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
297  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
298  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
299  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
300  class(*), dimension(:,:,:,:), pointer :: vdata_dummy !< Vdata remapped as 4D
301  integer :: xgmin !< Starting x index of the global io domain
302  integer :: ygmin !< Ending y index of the global io domain
303  integer :: xgsize, ygsize
304  integer :: istart, jstart, iend, jend
305  integer :: ioff, joff
306 
307  if (fileobj%use_netcdf_mpi) then
308  call netcdf_mpi_write_3d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
309  return
310  endif
311 
312  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
313  xdim_index, ydim_index, xpos, ypos)) then
314  call compressed_write(fileobj, variable_name, vdata, &
315  unlim_dim_level=unlim_dim_level, corner=corner, &
316  edge_lengths=edge_lengths)
317  return
318  endif
319 
320  if (xdim_index .ne. 1 .or. ydim_index .ne. 2) then
321  ! This is a KLUDGE
322  ! mpp_scatter assumes that the variable is (x,y), if that is not the case it remaps the data
323  ! to a 4D array and calls domain_read_4d which does not use mpp_scatter yet
324  vdata_dummy(1:size(vdata,1),1:size(vdata,2), 1:size(vdata,3), 1:1) => vdata(:,:,:)
325  call domain_write_4d(fileobj, variable_name, vdata_dummy, unlim_dim_level)
326  return
327  endif
328 
329  ! Get the io domain from the fileobj
330  io_domain => mpp_get_io_domain(fileobj%domain)
331 
332  ! Get some info about the domain:
333  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
334  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, buffer_includes_halos, &
335  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
336 
337  ! Get the global io domain:
338  call mpp_get_global_domain(io_domain, xbegin=xgmin, xsize=xgsize, position=xpos)
339  call mpp_get_global_domain(io_domain, ybegin=ygmin, ysize=ygsize, position=ypos)
340 
341  ! Root pe allocates room to gather the data and computes offsets for data placement
342  if (fileobj%is_root) then
343  ! Offsets used to place data in recv buffer
344  ioff = 1-xgmin
345  joff = 1-ygmin
346 
347  ! Allocate recv buffer for gather
348  select type(vdata)
349  type is (integer(kind=i4_kind))
350  allocate(global_buf_i4_kind(xgsize, ygsize, size(vdata,3)))
351  global_buf_i4_kind = 0
352  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
353  global_buf_i4_kind = fill_i4_kind
354  endif
355  type is (integer(kind=i8_kind))
356  allocate(global_buf_i8_kind(xgsize, ygsize, size(vdata,3)))
357  global_buf_i8_kind = 0
358  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
359  global_buf_i8_kind = fill_i8_kind
360  endif
361  type is (real(kind=r4_kind))
362  allocate(global_buf_r4_kind(xgsize, ygsize, size(vdata,3)))
363  global_buf_r4_kind = 0.
364  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
365  global_buf_r4_kind = fill_r4_kind
366  endif
367  type is (real(kind=r8_kind))
368  allocate(global_buf_r8_kind(xgsize, ygsize, size(vdata,3)))
369  global_buf_r8_kind = 0.
370  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
371  global_buf_r8_kind = fill_r8_kind
372  endif
373  class default
374  call error("unsupported variable type: domain_write_3d_mpp_gather: file: " &
375  & //trim(fileobj%path)//" variable:"//trim(variable_name))
376  end select
377  endif
378 
379  ! Get the starting and indices of the compute domain relative to vdata(note that vdata start indices at 1 #Fortran)
380  istart = 1
381  jstart = 1
382 
383  ! If the buffer contains halos, get the portion of vdata with only the compute domain
384  if (buffer_includes_halos) then
385  istart = isc - isd + 1
386  jstart = jsc - jsd + 1
387  endif
388 
389  iend = istart + xc_size - 1
390  jend = jstart + yc_size - 1
391 
392  ! Get offsets for buffer
393  ioff = 1-xgmin
394  joff = 1-ygmin
395 
396  ! Gather the data
397  select type(vdata)
398  type is (integer(kind=i4_kind))
399  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, size(vdata,3), fileobj%pelist, &
400  & vdata(istart:iend, jstart:jend,:), global_buf_i4_kind, fileobj%is_root, ishift=ioff, jshift=joff)
401  type is (integer(kind=i8_kind))
402  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, size(vdata,3), fileobj%pelist, &
403  & vdata(istart:iend, jstart:jend,:), global_buf_i8_kind, fileobj%is_root, ishift=ioff, jshift=joff)
404  type is (real(kind=r4_kind))
405  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, size(vdata,3), fileobj%pelist, &
406  & vdata(istart:iend, jstart:jend,:), global_buf_r4_kind, fileobj%is_root, ishift=ioff, jshift=joff)
407  type is (real(kind=r8_kind))
408  call mpp_gather(isc, isc+xc_size-1, jsc, jsc+yc_size-1, size(vdata,3), fileobj%pelist, &
409  & vdata(istart:iend, jstart:jend,:), global_buf_r8_kind, fileobj%is_root, ishift=ioff, jshift=joff)
410  class default
411  call error("unsupported variable type: domain_write_3d_mpp_gather: file: " &
412  & //trim(fileobj%path)//" variable:"//trim(variable_name))
413  end select
414 
415  ! Root pe writes out the data
416  if (fileobj%is_root) then
417  select type(vdata)
418  type is (integer(kind=i4_kind))
419  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
420  unlim_dim_level=unlim_dim_level)
421  type is (integer(kind=i8_kind))
422  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
423  unlim_dim_level=unlim_dim_level)
424  type is (real(kind=r4_kind))
425  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
426  unlim_dim_level=unlim_dim_level)
427  type is (real(kind=r8_kind))
428  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
429  unlim_dim_level=unlim_dim_level)
430  class default
431  call error("unsupported variable type: domain_write_3d_mpp_gather: file: " &
432  & //trim(fileobj%path)//" variable:"//trim(variable_name))
433  end select
434  endif
435 
436 end subroutine domain_write_3d
437 
438 
439 !> @brief Gather "compute" domain data on the I/O root rank and then have
440 !! the I/O root write out the data that spans the "global" domain.
441 !! This routine may only be used with variables that are "domain
442 !! decomposed".
443 subroutine domain_write_4d(fileobj, variable_name, vdata, unlim_dim_level, &
444  corner, edge_lengths)
445 
446  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
447  character(len=*), intent(in) :: variable_name !< Variable name.
448  class(*), dimension(:,:,:,:), intent(in) :: vdata !< Data that will
449  !! be written out
450  !! to the netcdf file.
451  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
452  !! dimension.
453  integer, dimension(4), intent(in), optional :: corner !< Array of starting
454  !! indices describing
455  !! where the data
456  !! will be written to.
457  integer, dimension(4), intent(in), optional :: edge_lengths !< The number of
458  !! elements that
459  !! will be written
460  !! in each dimension.
461 
462  integer(kind=i4_kind), dimension(:,:,:,:), allocatable :: buf_i4_kind
463  integer(kind=i8_kind), dimension(:,:,:,:), allocatable :: buf_i8_kind
464  real(kind=r4_kind), dimension(:,:,:,:), allocatable :: buf_r4_kind
465  real(kind=r8_kind), dimension(:,:,:,:), allocatable :: buf_r8_kind
466  logical :: buffer_includes_halos
467  integer, dimension(4) :: c
468  integer, dimension(4) :: e
469  integer(kind=i4_kind), dimension(:,:,:,:), allocatable :: global_buf_i4_kind
470  integer(kind=i8_kind), dimension(:,:,:,:), allocatable :: global_buf_i8_kind
471  real(kind=r4_kind), dimension(:,:,:,:), allocatable :: global_buf_r4_kind
472  real(kind=r8_kind), dimension(:,:,:,:), allocatable :: global_buf_r8_kind
473  integer :: i
474  type(domain2d), pointer :: io_domain
475  integer :: isc
476  integer :: isd
477  integer :: jsc
478  integer :: jsd
479  integer, dimension(:), allocatable :: pe_icsize
480  integer, dimension(:), allocatable :: pe_iec
481  integer, dimension(:), allocatable :: pe_isc
482  integer, dimension(:), allocatable :: pe_jcsize
483  integer, dimension(:), allocatable :: pe_jec
484  integer, dimension(:), allocatable :: pe_jsc
485  integer :: xc_size
486  integer :: xdim_index
487  integer :: xpos
488  integer :: ydim_index
489  integer :: ypos
490  integer :: yc_size
491  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
492  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
493  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
494  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
495  integer :: xgmax !< Ending x index of the global io domain
496  integer :: xgmin !< Starting x index of the global io domain
497  integer :: ygmax !< Ending y index of the global io domain
498  integer :: ygmin !< Ending y index of the global io domain
499 
500  if (fileobj%use_netcdf_mpi) then
501  call netcdf_mpi_write_4d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
502  return
503  endif
504 
505  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
506  xdim_index, ydim_index, xpos, ypos)) then
507  call compressed_write(fileobj, variable_name, vdata, &
508  unlim_dim_level=unlim_dim_level, corner=corner, &
509  edge_lengths=edge_lengths)
510  return
511  endif
512  io_domain => mpp_get_io_domain(fileobj%domain)
513  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
514  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
515  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
516  c(:) = 1
517  e(:) = shape(vdata)
518 
519  !I/O root gathers the data and writes it.
520  if (fileobj%is_root) then
521  allocate(pe_isc(size(fileobj%pelist)))
522  allocate(pe_iec(size(fileobj%pelist)))
523  allocate(pe_icsize(size(fileobj%pelist)))
524  call mpp_get_compute_domains(io_domain, xbegin=pe_isc, xend=pe_iec, xsize=pe_icsize, &
525  position=xpos)
526  allocate(pe_jsc(size(fileobj%pelist)))
527  allocate(pe_jec(size(fileobj%pelist)))
528  allocate(pe_jcsize(size(fileobj%pelist)))
529  call mpp_get_compute_domains(io_domain, ybegin=pe_jsc, yend=pe_jec, ysize=pe_jcsize, &
530  position=ypos)
531 
532  !< Determine the size of the global io domain
533  call mpp_get_global_domain(io_domain, ybegin=ygmin, yend=ygmax, position=ypos)
534  call mpp_get_global_domain(io_domain, xbegin=xgmin, xend=xgmax, position=xpos)
535 
536  !Write the out the data.
537  !< Set e to equal the size of the global io domain
538  e(xdim_index) = xgmax - xgmin + 1
539  e(ydim_index) = ygmax - ygmin + 1
540 
541  !< Allocate a global buffer, get the fill value if it exists in the file, and initialize
542  !! the buffer to the fill value
543  select type(vdata)
544  type is (integer(kind=i4_kind))
545  call allocate_array(global_buf_i4_kind, e)
546  global_buf_i4_kind = 0
547  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
548  global_buf_i4_kind = fill_i4_kind
549  endif
550  type is (integer(kind=i8_kind))
551  call allocate_array(global_buf_i8_kind, e)
552  global_buf_i8_kind = 0
553  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
554  global_buf_i8_kind = fill_i8_kind
555  endif
556  type is (real(kind=r4_kind))
557  call allocate_array(global_buf_r4_kind, e)
558  global_buf_r4_kind = 0.
559  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
560  global_buf_r4_kind = fill_r4_kind
561  endif
562  type is (real(kind=r8_kind))
563  call allocate_array(global_buf_r8_kind, e)
564  global_buf_r8_kind = 0.
565  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
566  global_buf_r8_kind = fill_r8_kind
567  endif
568  class default
569  call error("unsupported variable type: domain_write_4d: file: "//trim(fileobj%path)//" variable:"// &
570  & trim(variable_name))
571  end select
572 
573  do i = 1, size(fileobj%pelist)
574  !< Set c relative to the starting global io domain index
575  c(xdim_index) = pe_isc(i) - xgmin + 1
576  c(ydim_index) = pe_jsc(i) - ygmin + 1
577  e(xdim_index) = pe_icsize(i)
578  e(ydim_index) = pe_jcsize(i)
579  select type(vdata)
580  type is (integer(kind=i4_kind))
581  call allocate_array(buf_i4_kind, e)
582  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
583  if (i .eq. 1) then
584  !Root rank gets the data directly.
585  if (buffer_includes_halos) then
586  !Adjust if the input buffer has room for halos.
587  c(xdim_index) = isc - isd + 1
588  c(ydim_index) = jsc - jsd + 1
589  else
590  c(xdim_index) = 1
591  c(ydim_index) = 1
592  endif
593  call get_array_section(buf_i4_kind, vdata, c, e)
594  c(xdim_index) = pe_isc(i) - xgmin + 1
595  c(ydim_index) = pe_jsc(i) - ygmin + 1
596  else
597  !Receive data from non-root ranks.
598  call mpp_recv(buf_i4_kind, size(buf_i4_kind), fileobj%pelist(i), block=.true.)
599  endif
600  !Put local data into the global buffer.
601  call put_array_section(buf_i4_kind, global_buf_i4_kind, c, e)
602  deallocate(buf_i4_kind)
603  type is (integer(kind=i8_kind))
604  call allocate_array(buf_i8_kind, e)
605  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
606  if (i .eq. 1) then
607  !Root rank gets the data directly.
608  if (buffer_includes_halos) then
609  !Adjust if the input buffer has room for halos.
610  c(xdim_index) = isc - isd + 1
611  c(ydim_index) = jsc - jsd + 1
612  else
613  c(xdim_index) = 1
614  c(ydim_index) = 1
615  endif
616  call get_array_section(buf_i8_kind, vdata, c, e)
617  c(xdim_index) = pe_isc(i) - xgmin + 1
618  c(ydim_index) = pe_jsc(i) - ygmin + 1
619  else
620  !Receive data from non-root ranks.
621  call mpp_recv(buf_i8_kind, size(buf_i8_kind), fileobj%pelist(i), block=.true.)
622  endif
623  !Put local data into the global buffer.
624  call put_array_section(buf_i8_kind, global_buf_i8_kind, c, e)
625  deallocate(buf_i8_kind)
626  type is (real(kind=r4_kind))
627  call allocate_array(buf_r4_kind, e)
628  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
629  if (i .eq. 1) then
630  !Root rank gets the data directly.
631  if (buffer_includes_halos) then
632  !Adjust if the input buffer has room for halos.
633  c(xdim_index) = isc - isd + 1
634  c(ydim_index) = jsc - jsd + 1
635  else
636  c(xdim_index) = 1
637  c(ydim_index) = 1
638  endif
639  call get_array_section(buf_r4_kind, vdata, c, e)
640  c(xdim_index) = pe_isc(i) - xgmin + 1
641  c(ydim_index) = pe_jsc(i) - ygmin + 1
642  else
643  !Receive data from non-root ranks.
644  call mpp_recv(buf_r4_kind, size(buf_r4_kind), fileobj%pelist(i), block=.true.)
645  endif
646  !Put local data into the global buffer.
647  call put_array_section(buf_r4_kind, global_buf_r4_kind, c, e)
648  deallocate(buf_r4_kind)
649  type is (real(kind=r8_kind))
650  call allocate_array(buf_r8_kind, e)
651  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
652  if (i .eq. 1) then
653  !Root rank gets the data directly.
654  if (buffer_includes_halos) then
655  !Adjust if the input buffer has room for halos.
656  c(xdim_index) = isc - isd + 1
657  c(ydim_index) = jsc - jsd + 1
658  else
659  c(xdim_index) = 1
660  c(ydim_index) = 1
661  endif
662  call get_array_section(buf_r8_kind, vdata, c, e)
663  c(xdim_index) = pe_isc(i) - xgmin + 1
664  c(ydim_index) = pe_jsc(i) - ygmin + 1
665  else
666  !Receive data from non-root ranks.
667  call mpp_recv(buf_r8_kind, size(buf_r8_kind), fileobj%pelist(i), block=.true.)
668  endif
669  !Put local data into the global buffer.
670  call put_array_section(buf_r8_kind, global_buf_r8_kind, c, e)
671  deallocate(buf_r8_kind)
672  end select
673  enddo
674  deallocate(pe_isc)
675  deallocate(pe_iec)
676  deallocate(pe_icsize)
677  deallocate(pe_jsc)
678  deallocate(pe_jec)
679  deallocate(pe_jcsize)
680 
681  !Write the out the data.
682  select type(vdata)
683  type is (integer(kind=i4_kind))
684  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
685  unlim_dim_level=unlim_dim_level)
686  deallocate(global_buf_i4_kind)
687  type is (integer(kind=i8_kind))
688  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
689  unlim_dim_level=unlim_dim_level)
690  deallocate(global_buf_i8_kind)
691  type is (real(kind=r4_kind))
692  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
693  unlim_dim_level=unlim_dim_level)
694  deallocate(global_buf_r4_kind)
695  type is (real(kind=r8_kind))
696  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
697  unlim_dim_level=unlim_dim_level)
698  deallocate(global_buf_r8_kind)
699  end select
700  else
701  if (buffer_includes_halos) then
702  c(xdim_index) = isc - isd + 1
703  c(ydim_index) = jsc - jsd + 1
704  endif
705  e(xdim_index) = xc_size
706  e(ydim_index) = yc_size
707  select type(vdata)
708  type is (integer(kind=i4_kind))
709  call allocate_array(buf_i4_kind, e)
710  call get_array_section(buf_i4_kind, vdata, c, e)
711  call mpp_send(buf_i4_kind, size(buf_i4_kind), fileobj%io_root)
712  call mpp_sync_self(check=event_send)
713  deallocate(buf_i4_kind)
714  type is (integer(kind=i8_kind))
715  call allocate_array(buf_i8_kind, e)
716  call get_array_section(buf_i8_kind, vdata, c, e)
717  call mpp_send(buf_i8_kind, size(buf_i8_kind), fileobj%io_root)
718  call mpp_sync_self(check=event_send)
719  deallocate(buf_i8_kind)
720  type is (real(kind=r4_kind))
721  call allocate_array(buf_r4_kind, e)
722  call get_array_section(buf_r4_kind, vdata, c, e)
723  call mpp_send(buf_r4_kind, size(buf_r4_kind), fileobj%io_root)
724  call mpp_sync_self(check=event_send)
725  deallocate(buf_r4_kind)
726  type is (real(kind=r8_kind))
727  call allocate_array(buf_r8_kind, e)
728  call get_array_section(buf_r8_kind, vdata, c, e)
729  call mpp_send(buf_r8_kind, size(buf_r8_kind), fileobj%io_root)
730  call mpp_sync_self(check=event_send)
731  deallocate(buf_r8_kind)
732  class default
733  call error("unsupported variable type: domain_write_4d: file: "//trim(fileobj%path)//" variable:"// &
734  & trim(variable_name))
735  end select
736  endif
737 end subroutine domain_write_4d
738 
739 
740 !> @brief Gather "compute" domain data on the I/O root rank and then have
741 !! the I/O root write out the data that spans the "global" domain.
742 !! This routine may only be used with variables that are "domain
743 !! decomposed".
744 subroutine domain_write_5d(fileobj, variable_name, vdata, unlim_dim_level, &
745  corner, edge_lengths)
746 
747  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
748  character(len=*), intent(in) :: variable_name !< Variable name.
749  class(*), dimension(:,:,:,:,:), intent(in) :: vdata !< Data that will
750  !! be written out
751  !! to the netcdf file.
752  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
753  !! dimension.
754  integer, dimension(5), intent(in), optional :: corner !< Array of starting
755  !! indices describing
756  !! where the data
757  !! will be written to.
758  integer, dimension(5), intent(in), optional :: edge_lengths !< The number of
759  !! elements that
760  !! will be written
761  !! in each dimension.
762 
763  integer(kind=i4_kind), dimension(:,:,:,:,:), allocatable :: buf_i4_kind
764  integer(kind=i8_kind), dimension(:,:,:,:,:), allocatable :: buf_i8_kind
765  real(kind=r4_kind), dimension(:,:,:,:,:), allocatable :: buf_r4_kind
766  real(kind=r8_kind), dimension(:,:,:,:,:), allocatable :: buf_r8_kind
767  logical :: buffer_includes_halos
768  integer, dimension(5) :: c
769  integer, dimension(5) :: e
770  integer(kind=i4_kind), dimension(:,:,:,:,:), allocatable :: global_buf_i4_kind
771  integer(kind=i8_kind), dimension(:,:,:,:,:), allocatable :: global_buf_i8_kind
772  real(kind=r4_kind), dimension(:,:,:,:,:), allocatable :: global_buf_r4_kind
773  real(kind=r8_kind), dimension(:,:,:,:,:), allocatable :: global_buf_r8_kind
774  integer :: i
775  type(domain2d), pointer :: io_domain
776  integer :: isc
777  integer :: isd
778  integer :: jsc
779  integer :: jsd
780  integer, dimension(:), allocatable :: pe_icsize
781  integer, dimension(:), allocatable :: pe_iec
782  integer, dimension(:), allocatable :: pe_isc
783  integer, dimension(:), allocatable :: pe_jcsize
784  integer, dimension(:), allocatable :: pe_jec
785  integer, dimension(:), allocatable :: pe_jsc
786  integer :: xc_size
787  integer :: xdim_index
788  integer :: xpos
789  integer :: ydim_index
790  integer :: ypos
791  integer :: yc_size
792  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
793  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
794  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
795  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
796  integer :: xgmax !< Ending x index of the global io domain
797  integer :: xgmin !< Starting x index of the global io domain
798  integer :: ygmax !< Ending y index of the global io domain
799  integer :: ygmin !< Ending y index of the global io domain
800 
801  if (fileobj%use_netcdf_mpi) then
802  call netcdf_mpi_write_5d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
803  return
804  endif
805 
806  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
807  xdim_index, ydim_index, xpos, ypos)) then
808  call compressed_write(fileobj, variable_name, vdata, &
809  unlim_dim_level=unlim_dim_level, corner=corner, &
810  edge_lengths=edge_lengths)
811  return
812  endif
813  io_domain => mpp_get_io_domain(fileobj%domain)
814  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
815  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
816  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
817  c(:) = 1
818  e(:) = shape(vdata)
819 
820  !I/O root gathers the data and writes it.
821  if (fileobj%is_root) then
822  allocate(pe_isc(size(fileobj%pelist)))
823  allocate(pe_iec(size(fileobj%pelist)))
824  allocate(pe_icsize(size(fileobj%pelist)))
825  call mpp_get_compute_domains(io_domain, xbegin=pe_isc, xend=pe_iec, xsize=pe_icsize, &
826  position=xpos)
827  allocate(pe_jsc(size(fileobj%pelist)))
828  allocate(pe_jec(size(fileobj%pelist)))
829  allocate(pe_jcsize(size(fileobj%pelist)))
830  call mpp_get_compute_domains(io_domain, ybegin=pe_jsc, yend=pe_jec, ysize=pe_jcsize, &
831  position=ypos)
832 
833  !< Determine the size of the global io domain
834  call mpp_get_global_domain(io_domain, ybegin=ygmin, yend=ygmax, position=ypos)
835  call mpp_get_global_domain(io_domain, xbegin=xgmin, xend=xgmax, position=xpos)
836 
837  !Write the out the data.
838  !< Set e to equal the size of the global io domain
839  e(xdim_index) = xgmax - xgmin + 1
840  e(ydim_index) = ygmax - ygmin + 1
841 
842  !< Allocate a global buffer, get the fill value if it exists in the file, and initialize
843  !! the buffer to the fill value
844  select type(vdata)
845  type is (integer(kind=i4_kind))
846  call allocate_array(global_buf_i4_kind, e)
847  global_buf_i4_kind = 0
848  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
849  global_buf_i4_kind = fill_i4_kind
850  endif
851  type is (integer(kind=i8_kind))
852  call allocate_array(global_buf_i8_kind, e)
853  global_buf_i8_kind = 0
854  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
855  global_buf_i8_kind = fill_i8_kind
856  endif
857  type is (real(kind=r4_kind))
858  call allocate_array(global_buf_r4_kind, e)
859  global_buf_r4_kind = 0.
860  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
861  global_buf_r4_kind = fill_r4_kind
862  endif
863  type is (real(kind=r8_kind))
864  call allocate_array(global_buf_r8_kind, e)
865  global_buf_r8_kind = 0.
866  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
867  global_buf_r8_kind = fill_r8_kind
868  endif
869  class default
870  call error("unsupported variable type: domain_write_5d: file: "//trim(fileobj%path)//" variable:"// &
871  & trim(variable_name))
872  end select
873 
874  do i = 1, size(fileobj%pelist)
875  !< Set c relative to the starting global io domain index
876  c(xdim_index) = pe_isc(i) - xgmin + 1
877  c(ydim_index) = pe_jsc(i) - ygmin + 1
878  e(xdim_index) = pe_icsize(i)
879  e(ydim_index) = pe_jcsize(i)
880  select type(vdata)
881  type is (integer(kind=i4_kind))
882  call allocate_array(buf_i4_kind, e)
883  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
884  if (i .eq. 1) then
885  !Root rank gets the data directly.
886  if (buffer_includes_halos) then
887  !Adjust if the input buffer has room for halos.
888  c(xdim_index) = isc - isd + 1
889  c(ydim_index) = jsc - jsd + 1
890  else
891  c(xdim_index) = 1
892  c(ydim_index) = 1
893  endif
894  call get_array_section(buf_i4_kind, vdata, c, e)
895  c(xdim_index) = pe_isc(i) - xgmin + 1
896  c(ydim_index) = pe_jsc(i) - ygmin + 1
897  else
898  !Receive data from non-root ranks.
899  call mpp_recv(buf_i4_kind, size(buf_i4_kind), fileobj%pelist(i), block=.true.)
900  endif
901  !Put local data into the global buffer.
902  call put_array_section(buf_i4_kind, global_buf_i4_kind, c, e)
903  deallocate(buf_i4_kind)
904  type is (integer(kind=i8_kind))
905  call allocate_array(buf_i8_kind, e)
906  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
907  if (i .eq. 1) then
908  !Root rank gets the data directly.
909  if (buffer_includes_halos) then
910  !Adjust if the input buffer has room for halos.
911  c(xdim_index) = isc - isd + 1
912  c(ydim_index) = jsc - jsd + 1
913  else
914  c(xdim_index) = 1
915  c(ydim_index) = 1
916  endif
917  call get_array_section(buf_i8_kind, vdata, c, e)
918  c(xdim_index) = pe_isc(i) - xgmin + 1
919  c(ydim_index) = pe_jsc(i) - ygmin + 1
920  else
921  !Receive data from non-root ranks.
922  call mpp_recv(buf_i8_kind, size(buf_i8_kind), fileobj%pelist(i), block=.true.)
923  endif
924  !Put local data into the global buffer.
925  call put_array_section(buf_i8_kind, global_buf_i8_kind, c, e)
926  deallocate(buf_i8_kind)
927  type is (real(kind=r4_kind))
928  call allocate_array(buf_r4_kind, e)
929  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
930  if (i .eq. 1) then
931  !Root rank gets the data directly.
932  if (buffer_includes_halos) then
933  !Adjust if the input buffer has room for halos.
934  c(xdim_index) = isc - isd + 1
935  c(ydim_index) = jsc - jsd + 1
936  else
937  c(xdim_index) = 1
938  c(ydim_index) = 1
939  endif
940  call get_array_section(buf_r4_kind, vdata, c, e)
941  c(xdim_index) = pe_isc(i) - xgmin + 1
942  c(ydim_index) = pe_jsc(i) - ygmin + 1
943  else
944  !Receive data from non-root ranks.
945  call mpp_recv(buf_r4_kind, size(buf_r4_kind), fileobj%pelist(i), block=.true.)
946  endif
947  !Put local data into the global buffer.
948  call put_array_section(buf_r4_kind, global_buf_r4_kind, c, e)
949  deallocate(buf_r4_kind)
950  type is (real(kind=r8_kind))
951  call allocate_array(buf_r8_kind, e)
952  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
953  if (i .eq. 1) then
954  !Root rank gets the data directly.
955  if (buffer_includes_halos) then
956  !Adjust if the input buffer has room for halos.
957  c(xdim_index) = isc - isd + 1
958  c(ydim_index) = jsc - jsd + 1
959  else
960  c(xdim_index) = 1
961  c(ydim_index) = 1
962  endif
963  call get_array_section(buf_r8_kind, vdata, c, e)
964  c(xdim_index) = pe_isc(i) - xgmin + 1
965  c(ydim_index) = pe_jsc(i) - ygmin + 1
966  else
967  !Receive data from non-root ranks.
968  call mpp_recv(buf_r8_kind, size(buf_r8_kind), fileobj%pelist(i), block=.true.)
969  endif
970  !Put local data into the global buffer.
971  call put_array_section(buf_r8_kind, global_buf_r8_kind, c, e)
972  deallocate(buf_r8_kind)
973  end select
974  enddo
975  deallocate(pe_isc)
976  deallocate(pe_iec)
977  deallocate(pe_icsize)
978  deallocate(pe_jsc)
979  deallocate(pe_jec)
980  deallocate(pe_jcsize)
981 
982  !Write the out the data.
983  select type(vdata)
984  type is (integer(kind=i4_kind))
985  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
986  unlim_dim_level=unlim_dim_level)
987  deallocate(global_buf_i4_kind)
988  type is (integer(kind=i8_kind))
989  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
990  unlim_dim_level=unlim_dim_level)
991  deallocate(global_buf_i8_kind)
992  type is (real(kind=r4_kind))
993  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
994  unlim_dim_level=unlim_dim_level)
995  deallocate(global_buf_r4_kind)
996  type is (real(kind=r8_kind))
997  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
998  unlim_dim_level=unlim_dim_level)
999  deallocate(global_buf_r8_kind)
1000  end select
1001  else
1002  if (buffer_includes_halos) then
1003  c(xdim_index) = isc - isd + 1
1004  c(ydim_index) = jsc - jsd + 1
1005  endif
1006  e(xdim_index) = xc_size
1007  e(ydim_index) = yc_size
1008  select type(vdata)
1009  type is (integer(kind=i4_kind))
1010  call allocate_array(buf_i4_kind, e)
1011  call get_array_section(buf_i4_kind, vdata, c, e)
1012  call mpp_send(buf_i4_kind, size(buf_i4_kind), fileobj%io_root)
1013  call mpp_sync_self(check=event_send)
1014  deallocate(buf_i4_kind)
1015  type is (integer(kind=i8_kind))
1016  call allocate_array(buf_i8_kind, e)
1017  call get_array_section(buf_i8_kind, vdata, c, e)
1018  call mpp_send(buf_i8_kind, size(buf_i8_kind), fileobj%io_root)
1019  call mpp_sync_self(check=event_send)
1020  deallocate(buf_i8_kind)
1021  type is (real(kind=r4_kind))
1022  call allocate_array(buf_r4_kind, e)
1023  call get_array_section(buf_r4_kind, vdata, c, e)
1024  call mpp_send(buf_r4_kind, size(buf_r4_kind), fileobj%io_root)
1025  call mpp_sync_self(check=event_send)
1026  deallocate(buf_r4_kind)
1027  type is (real(kind=r8_kind))
1028  call allocate_array(buf_r8_kind, e)
1029  call get_array_section(buf_r8_kind, vdata, c, e)
1030  call mpp_send(buf_r8_kind, size(buf_r8_kind), fileobj%io_root)
1031  call mpp_sync_self(check=event_send)
1032  deallocate(buf_r8_kind)
1033  class default
1034  call error("unsupported variable type: domain_write_5d: file: "//trim(fileobj%path)//" variable:"// &
1035  & trim(variable_name))
1036  end select
1037  endif
1038 end subroutine domain_write_5d
1039 
1040 !> @brief Write 2D data using NetCDF MPI
1041 subroutine netcdf_mpi_write_2d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
1042  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
1043  character(len=*), intent(in) :: variable_name !< Variable name.
1044  class(*), dimension(:,:), intent(in) :: vdata !< Data that will be written out to the netcdf file.
1045  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited dimension.
1046  integer, dimension(2), intent(in), optional :: corner !< Array of starting indices describing where the data
1047  !! will be written to.
1048  integer, dimension(2), intent(in), optional :: edge_lengths !< The number of elements that will be written
1049  !! in each dimension.
1050 
1051  integer :: xdim_index
1052  integer :: ydim_index
1053  integer :: xpos
1054  integer :: ypos
1055 
1056  integer :: isd !< Starting "x" index of the data domain
1057  integer :: isc !< Starting "x" index of the compute domain
1058  integer :: jsd !< Starting "y" index of the data domain
1059  integer :: jsc !< Starting "y" index of the compute domain
1060  integer :: xc_size !< Size of the compute domain
1061  integer :: yc_size !< Size of the compute domain
1062  logical :: buffer_includes_halos !< True if "vdata" is the size of the data domain
1063  !! (i.e it includes halos (which are not written))
1064 
1065  integer, dimension(3) :: c !< Indices of the corners for each dimension
1066  integer, dimension(3) :: e !< Size of the data for each dimension
1067  integer :: varid
1068  integer :: unlim_dim_index
1069 
1070  integer :: i0, i1
1071  integer :: j0, j1
1072  integer :: err
1073 
1074  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., xdim_index, ydim_index, xpos, ypos)) then
1075  call compressed_write(fileobj, variable_name, vdata, unlim_dim_level=unlim_dim_level, corner=corner, &
1076  edge_lengths=edge_lengths)
1077  return
1078  endif
1079 
1080  !! Get some more info about the variable
1081  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
1082  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
1083  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1084 
1085  c = 1
1086  e = [shape(vdata), 1]
1087 
1088  c(xdim_index) = isc
1089  c(ydim_index) = jsc
1090  e(xdim_index) = xc_size
1091  e(ydim_index) = yc_size
1092 
1093  if (present(unlim_dim_level)) then
1094  unlim_dim_index = get_variable_unlimited_dimension_index(fileobj, variable_name, broadcast=.false.)
1095  if (unlim_dim_index .ne. 3) then
1096  call error("unlimited dimension must be the slowest varying dimension in variable: "//trim(variable_name))
1097  endif
1098  c(unlim_dim_index) = unlim_dim_level
1099  endif
1100 
1101  i0 = 1
1102  j0 = 1
1103  select case (xdim_index)
1104  case (1)
1105  ! X is the first dimension
1106  if (buffer_includes_halos) then
1107  i0 = isc - isd + 1
1108  j0 = jsc - jsd + 1
1109  endif
1110  i1 = i0 + xc_size - 1
1111  j1 = j0 + yc_size - 1
1112  case (2)
1113  ! X is the second dimension
1114  if (buffer_includes_halos) then
1115  i0 = jsc - jsd + 1
1116  j0 = isc - isd + 1
1117  endif
1118  i1 = i0 + yc_size - 1
1119  j1 = j0 + xc_size - 1
1120  end select
1121 
1122  varid = get_variable_id(fileobj%ncid, trim(variable_name), &
1123  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1124 
1125  select type(vdata)
1126  type is (integer(kind=i4_kind))
1127  err = nf90_put_var(fileobj%ncid, varid, &
1128  vdata(i0:i1, j0:j1), &
1129  start=c, count=e)
1130  type is (integer(kind=i8_kind))
1131  err = nf90_put_var(fileobj%ncid, varid, &
1132  vdata(i0:i1, j0:j1), &
1133  start=c, count=e)
1134  type is (real(kind=r4_kind))
1135  err = nf90_put_var(fileobj%ncid, varid, &
1136  vdata(i0:i1, j0:j1), &
1137  start=c, count=e)
1138  type is (real(kind=r8_kind))
1139  err = nf90_put_var(fileobj%ncid, varid, &
1140  vdata(i0:i1, j0:j1), &
1141  start=c, count=e)
1142  end select
1143 
1144  call check_netcdf_code(err, "Failed to write variable: "//trim(variable_name))
1145 end subroutine netcdf_mpi_write_2d
1146 
1147 !> @brief Write 3D data using NetCDF MPI
1148 subroutine netcdf_mpi_write_3d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
1149  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
1150  character(len=*), intent(in) :: variable_name !< Variable name.
1151  class(*), dimension(:,:,:), intent(in) :: vdata !< Data that will be written out to the netcdf file.
1152  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited dimension.
1153  integer, dimension(3), intent(in), optional :: corner !< Array of starting indices describing where the data
1154  !! will be written to.
1155  integer, dimension(3), intent(in), optional :: edge_lengths !< The number of elements that will be written
1156  !! in each dimension.
1157 
1158  integer :: xdim_index
1159  integer :: ydim_index
1160  integer :: xpos
1161  integer :: ypos
1162 
1163  integer :: isd !< Starting "x" index of the data domain
1164  integer :: isc !< Starting "x" index of the compute domain
1165  integer :: jsd !< Starting "y" index of the data domain
1166  integer :: jsc !< Starting "y" index of the compute domain
1167  integer :: xc_size !< Size of the compute domain
1168  integer :: yc_size !< Size of the compute domain
1169  logical :: buffer_includes_halos !< True if "vdata" is the size of the data domain
1170  !! (i.e it includes halos (which are not written))
1171 
1172  integer, dimension(4) :: c !< Indices of the corners for each dimension
1173  integer, dimension(4) :: e !< Size of the data for each dimension
1174  integer :: varid
1175  integer :: unlim_dim_index
1176 
1177  integer :: i0, i1
1178  integer :: j0, j1
1179  integer :: k0, k1
1180  integer :: err
1181 
1182  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., xdim_index, ydim_index, xpos, ypos)) then
1183  call compressed_write(fileobj, variable_name, vdata, unlim_dim_level=unlim_dim_level, corner=corner, &
1184  edge_lengths=edge_lengths)
1185  return
1186  endif
1187 
1188  !! Get some more info about the variable
1189  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
1190  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
1191  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1192 
1193  c = 1
1194  e = [shape(vdata), 1]
1195 
1196  c(xdim_index) = isc
1197  c(ydim_index) = jsc
1198  e(xdim_index) = xc_size
1199  e(ydim_index) = yc_size
1200 
1201  if (present(unlim_dim_level)) then
1202  unlim_dim_index = get_variable_unlimited_dimension_index(fileobj, variable_name, broadcast=.false.)
1203  if (unlim_dim_index .ne. 4) then
1204  call error("unlimited dimension must be the slowest varying dimension in variable: "//trim(variable_name))
1205  endif
1206  c(unlim_dim_index) = unlim_dim_level
1207  endif
1208 
1209  i0 = 1
1210  j0 = 1
1211  k0 = 1
1212 
1213  i1 = size(vdata, 1)
1214  j1 = size(vdata, 2)
1215  k1 = size(vdata, 3)
1216 
1217  select case (xdim_index)
1218  case (1)
1219  ! X is the first dimension
1220  if (buffer_includes_halos) then
1221  i0 = isc - isd + 1
1222  endif
1223  i1 = i0 + xc_size - 1
1224  case (2)
1225  ! X is the second dimension
1226  if (buffer_includes_halos) then
1227  j0 = isc - isd + 1
1228  endif
1229  j1 = j0 + xc_size - 1
1230  case (3)
1231  ! X is the third dimension
1232  if (buffer_includes_halos) then
1233  k0 = isc - isd + 1
1234  endif
1235  k1 = k0 + xc_size - 1
1236  end select
1237 
1238  select case (ydim_index)
1239  case (1)
1240  ! y is the first dimension
1241  if (buffer_includes_halos) then
1242  i0 = jsc - jsd + 1
1243  endif
1244  i1 = i0 + yc_size - 1
1245  case (2)
1246  ! y is the second dimension
1247  if (buffer_includes_halos) then
1248  j0 = jsc - jsd + 1
1249  endif
1250  j1 = j0 + yc_size - 1
1251  case (3)
1252  ! y is the third dimension
1253  if (buffer_includes_halos) then
1254  k0 = jsc - jsd + 1
1255  endif
1256  k1 = k0 + yc_size - 1
1257  end select
1258 
1259  varid = get_variable_id(fileobj%ncid, trim(variable_name), &
1260  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1261 
1262  select type(vdata)
1263  type is (integer(kind=i4_kind))
1264  err = nf90_put_var(fileobj%ncid, varid, &
1265  vdata(i0:i1, j0:j1, k0:k1), &
1266  start=c, count=e)
1267  type is (integer(kind=i8_kind))
1268  err = nf90_put_var(fileobj%ncid, varid, &
1269  vdata(i0:i1, j0:j1, k0:k1), &
1270  start=c, count=e)
1271  type is (real(kind=r4_kind))
1272  err = nf90_put_var(fileobj%ncid, varid, &
1273  vdata(i0:i1, j0:j1, k0:k1), &
1274  start=c, count=e)
1275  type is (real(kind=r8_kind))
1276  err = nf90_put_var(fileobj%ncid, varid, &
1277  vdata(i0:i1, j0:j1, k0:k1), &
1278  start=c, count=e)
1279  end select
1280 
1281  call check_netcdf_code(err, "Failed to write variable: "//trim(variable_name))
1282 end subroutine netcdf_mpi_write_3d
1283 
1284 !> @brief Write 4D data using NetCDF MPI
1285 subroutine netcdf_mpi_write_4d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
1286  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
1287  character(len=*), intent(in) :: variable_name !< Variable name.
1288  class(*), dimension(:,:,:,:), intent(in) :: vdata !< Data that will be written out to the netcdf file.
1289  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited dimension.
1290  integer, dimension(4), intent(in), optional :: corner !< Array of starting indices describing where the data
1291  !! will be written to.
1292  integer, dimension(4), intent(in), optional :: edge_lengths !< The number of elements that will be written
1293  !! in each dimension.
1294 
1295  integer :: xdim_index
1296  integer :: ydim_index
1297  integer :: xpos
1298  integer :: ypos
1299 
1300  integer :: isd !< Starting "x" index of the data domain
1301  integer :: isc !< Starting "x" index of the compute domain
1302  integer :: jsd !< Starting "y" index of the data domain
1303  integer :: jsc !< Starting "y" index of the compute domain
1304  integer :: xc_size !< Size of the compute domain
1305  integer :: yc_size !< Size of the compute domain
1306  logical :: buffer_includes_halos !< True if "vdata" is the size of the data domain
1307  !! (i.e it includes halos (which are not written))
1308 
1309  integer, dimension(5) :: c !< Indices of the corners for each dimension
1310  integer, dimension(5) :: e !< Size of the data for each dimension
1311  integer :: varid
1312  integer :: unlim_dim_index
1313 
1314  integer :: i0, i1
1315  integer :: j0, j1
1316  integer :: k0, k1
1317  integer :: l0, l1
1318  integer :: err
1319 
1320  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., xdim_index, ydim_index, xpos, ypos)) then
1321  call compressed_write(fileobj, variable_name, vdata, unlim_dim_level=unlim_dim_level, corner=corner, &
1322  edge_lengths=edge_lengths)
1323  return
1324  endif
1325 
1326  !! Get some more info about the variable
1327  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
1328  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
1329  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1330 
1331  c = 1
1332  e = [shape(vdata), 1]
1333 
1334  c(xdim_index) = isc
1335  c(ydim_index) = jsc
1336  e(xdim_index) = xc_size
1337  e(ydim_index) = yc_size
1338 
1339  if (present(unlim_dim_level)) then
1340  unlim_dim_index = get_variable_unlimited_dimension_index(fileobj, variable_name, broadcast=.false.)
1341  if (unlim_dim_index .ne. 5) then
1342  call error("unlimited dimension must be the slowest varying dimension in variable: "//trim(variable_name))
1343  endif
1344  c(unlim_dim_index) = unlim_dim_level
1345  endif
1346 
1347  i0 = 1
1348  j0 = 1
1349  k0 = 1
1350  l0 = 1
1351 
1352  i1 = size(vdata, 1)
1353  j1 = size(vdata, 2)
1354  k1 = size(vdata, 3)
1355  l1 = size(vdata, 4)
1356 
1357  select case (xdim_index)
1358  case (1)
1359  ! X is the first dimension
1360  if (buffer_includes_halos) then
1361  i0 = isc - isd + 1
1362  endif
1363  i1 = i0 + xc_size - 1
1364  case (2)
1365  ! X is the second dimension
1366  if (buffer_includes_halos) then
1367  j0 = isc - isd + 1
1368  endif
1369  j1 = j0 + xc_size - 1
1370  case (3)
1371  ! X is the third dimension
1372  if (buffer_includes_halos) then
1373  k0 = isc - isd + 1
1374  endif
1375  k1 = k0 + xc_size - 1
1376  case (4)
1377  ! X is the fourth dimension
1378  if (buffer_includes_halos) then
1379  l0 = isc - isd + 1
1380  endif
1381  l1 = l0 + xc_size - 1
1382  end select
1383 
1384  select case (ydim_index)
1385  case (1)
1386  ! y is the first dimension
1387  if (buffer_includes_halos) then
1388  i0 = jsc - jsd + 1
1389  endif
1390  i1 = i0 + yc_size - 1
1391  case (2)
1392  ! y is the second dimension
1393  if (buffer_includes_halos) then
1394  j0 = jsc - jsd + 1
1395  endif
1396  j1 = j0 + yc_size - 1
1397  case (3)
1398  ! y is the third dimension
1399  if (buffer_includes_halos) then
1400  k0 = jsc - jsd + 1
1401  endif
1402  k1 = k0 + yc_size - 1
1403  case (4)
1404  ! y is the fourth dimension
1405  if (buffer_includes_halos) then
1406  l0 = jsc - jsd + 1
1407  endif
1408  l1 = l0 + yc_size - 1
1409  end select
1410 
1411  varid = get_variable_id(fileobj%ncid, trim(variable_name), &
1412  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1413 
1414  select type(vdata)
1415  type is (integer(kind=i4_kind))
1416  err = nf90_put_var(fileobj%ncid, varid, &
1417  vdata(i0:i1, j0:j1, k0:k1, l0:l1), &
1418  start=c, count=e)
1419  type is (integer(kind=i8_kind))
1420  err = nf90_put_var(fileobj%ncid, varid, &
1421  vdata(i0:i1, j0:j1, k0:k1, l0:l1), &
1422  start=c, count=e)
1423  type is (real(kind=r4_kind))
1424  err = nf90_put_var(fileobj%ncid, varid, &
1425  vdata(i0:i1, j0:j1, k0:k1, l0:l1), &
1426  start=c, count=e)
1427  type is (real(kind=r8_kind))
1428  err = nf90_put_var(fileobj%ncid, varid, &
1429  vdata(i0:i1, j0:j1, k0:k1, l0:l1), &
1430  start=c, count=e)
1431  end select
1432 
1433  call check_netcdf_code(err, "Failed to write variable: "//trim(variable_name))
1434 end subroutine netcdf_mpi_write_4d
1435 
1436 !> @brief Write 5D data using NetCDF MPI
1437 subroutine netcdf_mpi_write_5d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
1438  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
1439  character(len=*), intent(in) :: variable_name !< Variable name.
1440  class(*), dimension(:,:,:,:,:), intent(in) :: vdata !< Data that will be written out to the netcdf file.
1441  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited dimension.
1442  integer, dimension(5), intent(in), optional :: corner !< Array of starting indices describing where the data
1443  !! will be written to.
1444  integer, dimension(5), intent(in), optional :: edge_lengths !< The number of elements that will be written
1445  !! in each dimension.
1446 
1447  integer :: xdim_index
1448  integer :: ydim_index
1449  integer :: xpos
1450  integer :: ypos
1451 
1452  integer :: isd !< Starting "x" index of the data domain
1453  integer :: isc !< Starting "x" index of the compute domain
1454  integer :: jsd !< Starting "y" index of the data domain
1455  integer :: jsc !< Starting "y" index of the compute domain
1456  integer :: xc_size !< Size of the compute domain
1457  integer :: yc_size !< Size of the compute domain
1458  logical :: buffer_includes_halos !< True if "vdata" is the size of the data domain
1459  !! (i.e it includes halos (which are not written))
1460 
1461  integer, dimension(6) :: c !< Indices of the corners for each dimension
1462  integer, dimension(6) :: e !< Size of the data for each dimension
1463  integer :: varid
1464  integer :: unlim_dim_index
1465 
1466  integer :: i0, i1
1467  integer :: j0, j1
1468  integer :: k0, k1
1469  integer :: l0, l1
1470  integer :: m0, m1
1471  integer :: err
1472 
1473  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., xdim_index, ydim_index, xpos, ypos)) then
1474  call compressed_write(fileobj, variable_name, vdata, unlim_dim_level=unlim_dim_level, corner=corner, &
1475  edge_lengths=edge_lengths)
1476  return
1477  endif
1478 
1479  !! Get some more info about the variable
1480  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
1481  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
1482  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1483 
1484  c = 1
1485  e = [shape(vdata), 1]
1486 
1487  c(xdim_index) = isc
1488  c(ydim_index) = jsc
1489  e(xdim_index) = xc_size
1490  e(ydim_index) = yc_size
1491 
1492  if (present(unlim_dim_level)) then
1493  unlim_dim_index = get_variable_unlimited_dimension_index(fileobj, variable_name, broadcast=.false.)
1494  if (unlim_dim_index .ne. 6) then
1495  call error("unlimited dimension must be the slowest varying dimension in variable: "//trim(variable_name))
1496  endif
1497  c(unlim_dim_index) = unlim_dim_level
1498  endif
1499 
1500  i0 = 1
1501  j0 = 1
1502  k0 = 1
1503  l0 = 1
1504  m0 = 1
1505 
1506  i1 = size(vdata, 1)
1507  j1 = size(vdata, 2)
1508  k1 = size(vdata, 3)
1509  l1 = size(vdata, 4)
1510  m1 = size(vdata, 5)
1511 
1512  select case (xdim_index)
1513  case (1)
1514  ! X is the first dimension
1515  if (buffer_includes_halos) then
1516  i0 = isc - isd + 1
1517  endif
1518  i1 = i0 + xc_size - 1
1519  case (2)
1520  ! X is the second dimension
1521  if (buffer_includes_halos) then
1522  j0 = isc - isd + 1
1523  endif
1524  j1 = j0 + xc_size - 1
1525  case (3)
1526  ! X is the third dimension
1527  if (buffer_includes_halos) then
1528  k0 = isc - isd + 1
1529  endif
1530  k1 = k0 + xc_size - 1
1531  case (4)
1532  ! X is the fourth dimension
1533  if (buffer_includes_halos) then
1534  l0 = isc - isd + 1
1535  endif
1536  l1 = l0 + xc_size - 1
1537  case (5)
1538  ! X is the fifth dimension
1539  if (buffer_includes_halos) then
1540  m0 = isc - isd + 1
1541  endif
1542  m1 = m0 + xc_size - 1
1543  end select
1544 
1545  select case (ydim_index)
1546  case (1)
1547  ! y is the first dimension
1548  if (buffer_includes_halos) then
1549  i0 = jsc - jsd + 1
1550  endif
1551  i1 = i0 + yc_size - 1
1552  case (2)
1553  ! y is the second dimension
1554  if (buffer_includes_halos) then
1555  j0 = jsc - jsd + 1
1556  endif
1557  j1 = j0 + yc_size - 1
1558  case (3)
1559  ! y is the third dimension
1560  if (buffer_includes_halos) then
1561  k0 = jsc - jsd + 1
1562  endif
1563  k1 = k0 + yc_size - 1
1564  case (4)
1565  ! y is the fourth dimension
1566  if (buffer_includes_halos) then
1567  l0 = jsc - jsd + 1
1568  endif
1569  l1 = l0 + yc_size - 1
1570  case (5)
1571  ! y is the fifth dimension
1572  if (buffer_includes_halos) then
1573  m0 = jsc - jsd + 1
1574  endif
1575  m1 = m0 + yc_size - 1
1576  end select
1577 
1578  varid = get_variable_id(fileobj%ncid, trim(variable_name), &
1579  msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1580 
1581  select type(vdata)
1582  type is (integer(kind=i4_kind))
1583  err = nf90_put_var(fileobj%ncid, varid, &
1584  vdata(i0:i1, j0:j1, k0:k1, l0:l1, m0:m1), &
1585  start=c, count=e)
1586  type is (integer(kind=i8_kind))
1587  err = nf90_put_var(fileobj%ncid, varid, &
1588  vdata(i0:i1, j0:j1, k0:k1, l0:l1, m0:m1), &
1589  start=c, count=e)
1590  type is (real(kind=r4_kind))
1591  err = nf90_put_var(fileobj%ncid, varid, &
1592  vdata(i0:i1, j0:j1, k0:k1, l0:l1, m0:m1), &
1593  start=c, count=e)
1594  type is (real(kind=r8_kind))
1595  err = nf90_put_var(fileobj%ncid, varid, &
1596  vdata(i0:i1, j0:j1, k0:k1, l0:l1, m0:m1), &
1597  start=c, count=e)
1598  end select
1599 
1600  call check_netcdf_code(err, "Failed to write variable: "//trim(variable_name))
1601 end subroutine netcdf_mpi_write_5d
1602 !> @}
subroutine netcdf_mpi_write_5d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Write 5D data using NetCDF MPI.
subroutine domain_write_3d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Gather "compute" domain data on the I/O root rank and then have the I/O root write out the data that ...
subroutine domain_write_4d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Gather "compute" domain data on the I/O root rank and then have the I/O root write out the data that ...
subroutine domain_write_1d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Gather "compute" domain data on the I/O root rank and then have the I/O root write out the data that ...
subroutine netcdf_mpi_write_2d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Write 2D data using NetCDF MPI.
subroutine domain_write_5d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Gather "compute" domain data on the I/O root rank and then have the I/O root write out the data that ...
subroutine domain_write_0d(fileobj, variable_name, vdata, unlim_dim_level, corner)
Gather "compute" domain data on the I/O root rank and then have the I/O root write out the data that ...
subroutine domain_write_2d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Gather "compute" domain data on the I/O root rank and then have the I/O root write out the data that ...
subroutine netcdf_mpi_write_3d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Write 3D data using NetCDF MPI.
subroutine netcdf_mpi_write_4d(fileobj, variable_name, vdata, unlim_dim_level, corner, edge_lengths)
Write 4D data using NetCDF MPI.
type(domain2d) function, pointer mpp_get_io_domain(domain)
Set user stack size.
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...