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