FMS  2024.03
Flexible Modeling System
domain_write.inc
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 !> @file
20 !> @brief Routines for writing domain decomposed variables for the @ref write_data interface
21 
22 !> @addtogroup fms2_io_mod
23 !> @{
24 
25 !> @brief Gather "compute" domain data on the I/O root rank and then have
26 !! the I/O root write out the data that spans the "global" domain.
27 !! This routine may only be used with variables that are "domain
28 !! decomposed".
29 subroutine domain_write_0d(fileobj, variable_name, vdata, unlim_dim_level, corner)
30 
31  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
32  character(len=*), intent(in) :: variable_name !< Variable name.
33  class(*), intent(in) :: vdata !< Data that will
34  !! be written out
35  !! to the netcdf file.
36  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
37  !! dimension.
38  integer, intent(in), optional :: corner !< Array of starting
39  !! indices describing
40  !! where the data
41  !! will be written to.
42 
43  call compressed_write(fileobj, variable_name, vdata, &
44  unlim_dim_level=unlim_dim_level, corner=corner)
45 
46 end subroutine domain_write_0d
47 
48 
49 !> @brief Gather "compute" domain data on the I/O root rank and then have
50 !! the I/O root write out the data that spans the "global" domain.
51 !! This routine may only be used with variables that are "domain
52 !! decomposed".
53 subroutine domain_write_1d(fileobj, variable_name, vdata, unlim_dim_level, &
54  corner, edge_lengths)
55 
56  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
57  character(len=*), intent(in) :: variable_name !< Variable name.
58  class(*), dimension(:), intent(in) :: vdata !< Data that will
59  !! be written out
60  !! to the netcdf file.
61  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
62  !! dimension.
63  integer, dimension(1), intent(in), optional :: corner !< Array of starting
64  !! indices describing
65  !! where the data
66  !! will be written to.
67  integer, dimension(1), intent(in), optional :: edge_lengths !< The number of
68  !! elements that
69  !! will be written
70  !! in each dimension.
71 
72  call compressed_write(fileobj, variable_name, vdata, &
73  unlim_dim_level=unlim_dim_level, corner=corner, &
74  edge_lengths=edge_lengths)
75 
76 end subroutine domain_write_1d
77 
78 
79 !> @brief Gather "compute" domain data on the I/O root rank and then have
80 !! the I/O root write out the data that spans the "global" domain.
81 !! This routine may only be used with variables that are "domain
82 !! decomposed".
83 subroutine domain_write_2d(fileobj, variable_name, vdata, unlim_dim_level, &
84  corner, edge_lengths)
85 
86  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
87  character(len=*), intent(in) :: variable_name !< Variable name.
88  class(*), dimension(:,:), intent(in) :: vdata !< Data that will
89  !! be written out
90  !! to the netcdf file.
91  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
92  !! dimension.
93  integer, dimension(2), intent(in), optional :: corner !< Array of starting
94  !! indices describing
95  !! where the data
96  !! will be written to.
97  integer, dimension(2), intent(in), optional :: edge_lengths !< The number of
98  !! elements that
99  !! will be written
100  !! in each dimension.
101 
102  integer(kind=i4_kind), dimension(:,:), allocatable :: buf_i4_kind
103  integer(kind=i8_kind), dimension(:,:), allocatable :: buf_i8_kind
104  real(kind=r4_kind), dimension(:,:), allocatable :: buf_r4_kind
105  real(kind=r8_kind), dimension(:,:), allocatable :: buf_r8_kind
106  logical :: buffer_includes_halos
107  integer, dimension(2) :: c
108  integer, dimension(2) :: e
109  integer(kind=i4_kind), dimension(:,:), allocatable :: global_buf_i4_kind
110  integer(kind=i8_kind), dimension(:,:), allocatable :: global_buf_i8_kind
111  real(kind=r4_kind), dimension(:,:), allocatable :: global_buf_r4_kind
112  real(kind=r8_kind), dimension(:,:), allocatable :: global_buf_r8_kind
113  integer :: i
114  type(domain2d), pointer :: io_domain
115  integer :: isc
116  integer :: isd
117  integer :: jsc
118  integer :: jsd
119  integer, dimension(:), allocatable :: pe_icsize
120  integer, dimension(:), allocatable :: pe_iec
121  integer, dimension(:), allocatable :: pe_isc
122  integer, dimension(:), allocatable :: pe_jcsize
123  integer, dimension(:), allocatable :: pe_jec
124  integer, dimension(:), allocatable :: pe_jsc
125  integer :: xc_size
126  integer :: xdim_index
127  integer :: xpos
128  integer :: ydim_index
129  integer :: ypos
130  integer :: yc_size
131  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
132  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
133  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
134  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
135  integer :: xgmax !< Ending x index of the global io domain
136  integer :: xgmin !< Starting x index of the global io domain
137  integer :: ygmax !< Ending y index of the global io domain
138  integer :: ygmin !< Ending y index of the global io domain
139 
140  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
141  xdim_index, ydim_index, xpos, ypos)) then
142  call compressed_write(fileobj, variable_name, vdata, &
143  unlim_dim_level=unlim_dim_level, corner=corner, &
144  edge_lengths=edge_lengths)
145  return
146  endif
147  io_domain => mpp_get_io_domain(fileobj%domain)
148  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
149  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
150  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
151  c(:) = 1
152  e(:) = shape(vdata)
153 
154  !I/O root gathers the data and writes it.
155  if (fileobj%is_root) then
156  allocate(pe_isc(size(fileobj%pelist)))
157  allocate(pe_iec(size(fileobj%pelist)))
158  allocate(pe_icsize(size(fileobj%pelist)))
159  call mpp_get_compute_domains(io_domain, xbegin=pe_isc, xend=pe_iec, xsize=pe_icsize, &
160  position=xpos)
161  allocate(pe_jsc(size(fileobj%pelist)))
162  allocate(pe_jec(size(fileobj%pelist)))
163  allocate(pe_jcsize(size(fileobj%pelist)))
164  call mpp_get_compute_domains(io_domain, ybegin=pe_jsc, yend=pe_jec, ysize=pe_jcsize, &
165  position=ypos)
166 
167  !< Determine the size of the global io domain
168  call mpp_get_global_domain(io_domain, ybegin=ygmin, yend=ygmax, position=ypos)
169  call mpp_get_global_domain(io_domain, xbegin=xgmin, xend=xgmax, position=xpos)
170 
171  !Write the out the data.
172  !< Set e to equal the size of the global io domain
173  e(xdim_index) = xgmax - xgmin + 1
174  e(ydim_index) = ygmax - ygmin + 1
175 
176  !< Allocate a global buffer, get the fill value if it exists in the file, and initialize
177  !! the buffer to the fill value
178  select type(vdata)
179  type is (integer(kind=i4_kind))
180  call allocate_array(global_buf_i4_kind, e)
181  global_buf_i4_kind = 0
182  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
183  global_buf_i4_kind = fill_i4_kind
184  endif
185  type is (integer(kind=i8_kind))
186  call allocate_array(global_buf_i8_kind, e)
187  global_buf_i8_kind = 0
188  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
189  global_buf_i8_kind = fill_i8_kind
190  endif
191  type is (real(kind=r4_kind))
192  call allocate_array(global_buf_r4_kind, e)
193  global_buf_r4_kind = 0.
194  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
195  global_buf_r4_kind = fill_r4_kind
196  endif
197  type is (real(kind=r8_kind))
198  call allocate_array(global_buf_r8_kind, e)
199  global_buf_r8_kind = 0.
200  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
201  global_buf_r8_kind = fill_r8_kind
202  endif
203  class default
204  call error("unsupported variable type: domain_write_2d: file: "//trim(fileobj%path)//" variable:"// &
205  & trim(variable_name))
206  end select
207 
208  do i = 1, size(fileobj%pelist)
209  !< Set c relative to the starting global io domain index
210  c(xdim_index) = pe_isc(i) - xgmin + 1
211  c(ydim_index) = pe_jsc(i) - ygmin + 1
212  e(xdim_index) = pe_icsize(i)
213  e(ydim_index) = pe_jcsize(i)
214  select type(vdata)
215  type is (integer(kind=i4_kind))
216  call allocate_array(buf_i4_kind, e)
217  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
218  if (i .eq. 1) then
219  !Root rank gets the data directly.
220  if (buffer_includes_halos) then
221  !Adjust if the input buffer has room for halos.
222  c(xdim_index) = isc - isd + 1
223  c(ydim_index) = jsc - jsd + 1
224  else
225  c(xdim_index) = 1
226  c(ydim_index) = 1
227  endif
228  call get_array_section(buf_i4_kind, vdata, c, e)
229  c(xdim_index) = pe_isc(i) - xgmin + 1
230  c(ydim_index) = pe_jsc(i) - ygmin + 1
231  else
232  !Receive data from non-root ranks.
233  call mpp_recv(buf_i4_kind, size(buf_i4_kind), fileobj%pelist(i), block=.true.)
234  endif
235  !Put local data into the global buffer.
236  call put_array_section(buf_i4_kind, global_buf_i4_kind, c, e)
237  deallocate(buf_i4_kind)
238  type is (integer(kind=i8_kind))
239  call allocate_array(buf_i8_kind, e)
240  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
241  if (i .eq. 1) then
242  !Root rank gets the data directly.
243  if (buffer_includes_halos) then
244  !Adjust if the input buffer has room for halos.
245  c(xdim_index) = isc - isd + 1
246  c(ydim_index) = jsc - jsd + 1
247  else
248  c(xdim_index) = 1
249  c(ydim_index) = 1
250  endif
251  call get_array_section(buf_i8_kind, vdata, c, e)
252  c(xdim_index) = pe_isc(i) - xgmin + 1
253  c(ydim_index) = pe_jsc(i) - ygmin + 1
254  else
255  !Receive data from non-root ranks.
256  call mpp_recv(buf_i8_kind, size(buf_i8_kind), fileobj%pelist(i), block=.true.)
257  endif
258  !Put local data into the global buffer.
259  call put_array_section(buf_i8_kind, global_buf_i8_kind, c, e)
260  deallocate(buf_i8_kind)
261  type is (real(kind=r4_kind))
262  call allocate_array(buf_r4_kind, e)
263  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
264  if (i .eq. 1) then
265  !Root rank gets the data directly.
266  if (buffer_includes_halos) then
267  !Adjust if the input buffer has room for halos.
268  c(xdim_index) = isc - isd + 1
269  c(ydim_index) = jsc - jsd + 1
270  else
271  c(xdim_index) = 1
272  c(ydim_index) = 1
273  endif
274  call get_array_section(buf_r4_kind, vdata, c, e)
275  c(xdim_index) = pe_isc(i) - xgmin + 1
276  c(ydim_index) = pe_jsc(i) - ygmin + 1
277  else
278  !Receive data from non-root ranks.
279  call mpp_recv(buf_r4_kind, size(buf_r4_kind), fileobj%pelist(i), block=.true.)
280  endif
281  !Put local data into the global buffer.
282  call put_array_section(buf_r4_kind, global_buf_r4_kind, c, e)
283  deallocate(buf_r4_kind)
284  type is (real(kind=r8_kind))
285  call allocate_array(buf_r8_kind, e)
286  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
287  if (i .eq. 1) then
288  !Root rank gets the data directly.
289  if (buffer_includes_halos) then
290  !Adjust if the input buffer has room for halos.
291  c(xdim_index) = isc - isd + 1
292  c(ydim_index) = jsc - jsd + 1
293  else
294  c(xdim_index) = 1
295  c(ydim_index) = 1
296  endif
297  call get_array_section(buf_r8_kind, vdata, c, e)
298  c(xdim_index) = pe_isc(i) - xgmin + 1
299  c(ydim_index) = pe_jsc(i) - ygmin + 1
300  else
301  !Receive data from non-root ranks.
302  call mpp_recv(buf_r8_kind, size(buf_r8_kind), fileobj%pelist(i), block=.true.)
303  endif
304  !Put local data into the global buffer.
305  call put_array_section(buf_r8_kind, global_buf_r8_kind, c, e)
306  deallocate(buf_r8_kind)
307  end select
308  enddo
309  deallocate(pe_isc)
310  deallocate(pe_iec)
311  deallocate(pe_icsize)
312  deallocate(pe_jsc)
313  deallocate(pe_jec)
314  deallocate(pe_jcsize)
315 
316  !Write the out the data.
317  select type(vdata)
318  type is (integer(kind=i4_kind))
319  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
320  unlim_dim_level=unlim_dim_level)
321  deallocate(global_buf_i4_kind)
322  type is (integer(kind=i8_kind))
323  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
324  unlim_dim_level=unlim_dim_level)
325  deallocate(global_buf_i8_kind)
326  type is (real(kind=r4_kind))
327  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
328  unlim_dim_level=unlim_dim_level)
329  deallocate(global_buf_r4_kind)
330  type is (real(kind=r8_kind))
331  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
332  unlim_dim_level=unlim_dim_level)
333  deallocate(global_buf_r8_kind)
334  end select
335  else
336  if (buffer_includes_halos) then
337  c(xdim_index) = isc - isd + 1
338  c(ydim_index) = jsc - jsd + 1
339  endif
340  e(xdim_index) = xc_size
341  e(ydim_index) = yc_size
342  select type(vdata)
343  type is (integer(kind=i4_kind))
344  call allocate_array(buf_i4_kind, e)
345  call get_array_section(buf_i4_kind, vdata, c, e)
346  call mpp_send(buf_i4_kind, size(buf_i4_kind), fileobj%io_root)
347  call mpp_sync_self(check=event_send)
348  deallocate(buf_i4_kind)
349  type is (integer(kind=i8_kind))
350  call allocate_array(buf_i8_kind, e)
351  call get_array_section(buf_i8_kind, vdata, c, e)
352  call mpp_send(buf_i8_kind, size(buf_i8_kind), fileobj%io_root)
353  call mpp_sync_self(check=event_send)
354  deallocate(buf_i8_kind)
355  type is (real(kind=r4_kind))
356  call allocate_array(buf_r4_kind, e)
357  call get_array_section(buf_r4_kind, vdata, c, e)
358  call mpp_send(buf_r4_kind, size(buf_r4_kind), fileobj%io_root)
359  call mpp_sync_self(check=event_send)
360  deallocate(buf_r4_kind)
361  type is (real(kind=r8_kind))
362  call allocate_array(buf_r8_kind, e)
363  call get_array_section(buf_r8_kind, vdata, c, e)
364  call mpp_send(buf_r8_kind, size(buf_r8_kind), fileobj%io_root)
365  call mpp_sync_self(check=event_send)
366  deallocate(buf_r8_kind)
367  class default
368  call error("unsupported variable type: domain_write_2d: file: "//trim(fileobj%path)//" variable:"// &
369  & trim(variable_name))
370  end select
371  endif
372 end subroutine domain_write_2d
373 
374 
375 !> @brief Gather "compute" domain data on the I/O root rank and then have
376 !! the I/O root write out the data that spans the "global" domain.
377 !! This routine may only be used with variables that are "domain
378 !! decomposed".
379 subroutine domain_write_3d(fileobj, variable_name, vdata, unlim_dim_level, &
380  corner, edge_lengths)
381 
382  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
383  character(len=*), intent(in) :: variable_name !< Variable name.
384  class(*), dimension(:,:,:), intent(in) :: vdata !< Data that will
385  !! be written out
386  !! to the netcdf file.
387  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
388  !! dimension.
389  integer, dimension(3), intent(in), optional :: corner !< Array of starting
390  !! indices describing
391  !! where the data
392  !! will be written to.
393  integer, dimension(3), intent(in), optional :: edge_lengths !< The number of
394  !! elements that
395  !! will be written
396  !! in each dimension.
397 
398  integer(kind=i4_kind), dimension(:,:,:), allocatable :: buf_i4_kind
399  integer(kind=i8_kind), dimension(:,:,:), allocatable :: buf_i8_kind
400  real(kind=r4_kind), dimension(:,:,:), allocatable :: buf_r4_kind
401  real(kind=r8_kind), dimension(:,:,:), allocatable :: buf_r8_kind
402  logical :: buffer_includes_halos
403  integer, dimension(3) :: c
404  integer, dimension(3) :: e
405  integer(kind=i4_kind), dimension(:,:,:), allocatable :: global_buf_i4_kind
406  integer(kind=i8_kind), dimension(:,:,:), allocatable :: global_buf_i8_kind
407  real(kind=r4_kind), dimension(:,:,:), allocatable :: global_buf_r4_kind
408  real(kind=r8_kind), dimension(:,:,:), allocatable :: global_buf_r8_kind
409  integer :: i
410  type(domain2d), pointer :: io_domain
411  integer :: isc
412  integer :: isd
413  integer :: jsc
414  integer :: jsd
415  integer, dimension(:), allocatable :: pe_icsize
416  integer, dimension(:), allocatable :: pe_iec
417  integer, dimension(:), allocatable :: pe_isc
418  integer, dimension(:), allocatable :: pe_jcsize
419  integer, dimension(:), allocatable :: pe_jec
420  integer, dimension(:), allocatable :: pe_jsc
421  integer :: xc_size
422  integer :: xdim_index
423  integer :: xpos
424  integer :: ydim_index
425  integer :: ypos
426  integer :: yc_size
427  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
428  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
429  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
430  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
431  integer :: xgmax !< Ending x index of the global io domain
432  integer :: xgmin !< Starting x index of the global io domain
433  integer :: ygmax !< Ending y index of the global io domain
434  integer :: ygmin !< Ending y index of the global io domain
435 
436  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
437  xdim_index, ydim_index, xpos, ypos)) then
438  call compressed_write(fileobj, variable_name, vdata, &
439  unlim_dim_level=unlim_dim_level, corner=corner, &
440  edge_lengths=edge_lengths)
441  return
442  endif
443  io_domain => mpp_get_io_domain(fileobj%domain)
444  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
445  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
446  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
447  c(:) = 1
448  e(:) = shape(vdata)
449 
450  !I/O root gathers the data and writes it.
451  if (fileobj%is_root) then
452  allocate(pe_isc(size(fileobj%pelist)))
453  allocate(pe_iec(size(fileobj%pelist)))
454  allocate(pe_icsize(size(fileobj%pelist)))
455  call mpp_get_compute_domains(io_domain, xbegin=pe_isc, xend=pe_iec, xsize=pe_icsize, &
456  position=xpos)
457  allocate(pe_jsc(size(fileobj%pelist)))
458  allocate(pe_jec(size(fileobj%pelist)))
459  allocate(pe_jcsize(size(fileobj%pelist)))
460  call mpp_get_compute_domains(io_domain, ybegin=pe_jsc, yend=pe_jec, ysize=pe_jcsize, &
461  position=ypos)
462 
463  !< Determine the size of the global io domain
464  call mpp_get_global_domain(io_domain, ybegin=ygmin, yend=ygmax, position=ypos)
465  call mpp_get_global_domain(io_domain, xbegin=xgmin, xend=xgmax, position=xpos)
466 
467  !Write the out the data.
468  !< Set e to equal the size of the global io domain
469  e(xdim_index) = xgmax - xgmin + 1
470  e(ydim_index) = ygmax - ygmin + 1
471 
472  !< Allocate a global buffer, get the fill value if it exists in the file, and initialize
473  !! the buffer to the fill value
474  select type(vdata)
475  type is (integer(kind=i4_kind))
476  call allocate_array(global_buf_i4_kind, e)
477  global_buf_i4_kind = 0
478  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
479  global_buf_i4_kind = fill_i4_kind
480  endif
481  type is (integer(kind=i8_kind))
482  call allocate_array(global_buf_i8_kind, e)
483  global_buf_i8_kind = 0
484  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
485  global_buf_i8_kind = fill_i8_kind
486  endif
487  type is (real(kind=r4_kind))
488  call allocate_array(global_buf_r4_kind, e)
489  global_buf_r4_kind = 0.
490  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
491  global_buf_r4_kind = fill_r4_kind
492  endif
493  type is (real(kind=r8_kind))
494  call allocate_array(global_buf_r8_kind, e)
495  global_buf_r8_kind = 0.
496  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
497  global_buf_r8_kind = fill_r8_kind
498  endif
499  class default
500  call error("unsupported variable type: domain_write_3d: file: "//trim(fileobj%path)//" variable:"// &
501  & trim(variable_name))
502  end select
503 
504  do i = 1, size(fileobj%pelist)
505  !< Set c relative to the starting global io domain index
506  c(xdim_index) = pe_isc(i) - xgmin + 1
507  c(ydim_index) = pe_jsc(i) - ygmin + 1
508  e(xdim_index) = pe_icsize(i)
509  e(ydim_index) = pe_jcsize(i)
510  select type(vdata)
511  type is (integer(kind=i4_kind))
512  call allocate_array(buf_i4_kind, e)
513  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
514  if (i .eq. 1) then
515  !Root rank gets the data directly.
516  if (buffer_includes_halos) then
517  !Adjust if the input buffer has room for halos.
518  c(xdim_index) = isc - isd + 1
519  c(ydim_index) = jsc - jsd + 1
520  else
521  c(xdim_index) = 1
522  c(ydim_index) = 1
523  endif
524  call get_array_section(buf_i4_kind, vdata, c, e)
525  c(xdim_index) = pe_isc(i) - xgmin + 1
526  c(ydim_index) = pe_jsc(i) - ygmin + 1
527  else
528  !Receive data from non-root ranks.
529  call mpp_recv(buf_i4_kind, size(buf_i4_kind), fileobj%pelist(i), block=.true.)
530  endif
531  !Put local data into the global buffer.
532  call put_array_section(buf_i4_kind, global_buf_i4_kind, c, e)
533  deallocate(buf_i4_kind)
534  type is (integer(kind=i8_kind))
535  call allocate_array(buf_i8_kind, e)
536  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
537  if (i .eq. 1) then
538  !Root rank gets the data directly.
539  if (buffer_includes_halos) then
540  !Adjust if the input buffer has room for halos.
541  c(xdim_index) = isc - isd + 1
542  c(ydim_index) = jsc - jsd + 1
543  else
544  c(xdim_index) = 1
545  c(ydim_index) = 1
546  endif
547  call get_array_section(buf_i8_kind, vdata, c, e)
548  c(xdim_index) = pe_isc(i) - xgmin + 1
549  c(ydim_index) = pe_jsc(i) - ygmin + 1
550  else
551  !Receive data from non-root ranks.
552  call mpp_recv(buf_i8_kind, size(buf_i8_kind), fileobj%pelist(i), block=.true.)
553  endif
554  !Put local data into the global buffer.
555  call put_array_section(buf_i8_kind, global_buf_i8_kind, c, e)
556  deallocate(buf_i8_kind)
557  type is (real(kind=r4_kind))
558  call allocate_array(buf_r4_kind, e)
559  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
560  if (i .eq. 1) then
561  !Root rank gets the data directly.
562  if (buffer_includes_halos) then
563  !Adjust if the input buffer has room for halos.
564  c(xdim_index) = isc - isd + 1
565  c(ydim_index) = jsc - jsd + 1
566  else
567  c(xdim_index) = 1
568  c(ydim_index) = 1
569  endif
570  call get_array_section(buf_r4_kind, vdata, c, e)
571  c(xdim_index) = pe_isc(i) - xgmin + 1
572  c(ydim_index) = pe_jsc(i) - ygmin + 1
573  else
574  !Receive data from non-root ranks.
575  call mpp_recv(buf_r4_kind, size(buf_r4_kind), fileobj%pelist(i), block=.true.)
576  endif
577  !Put local data into the global buffer.
578  call put_array_section(buf_r4_kind, global_buf_r4_kind, c, e)
579  deallocate(buf_r4_kind)
580  type is (real(kind=r8_kind))
581  call allocate_array(buf_r8_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_r8_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_r8_kind, size(buf_r8_kind), fileobj%pelist(i), block=.true.)
599  endif
600  !Put local data into the global buffer.
601  call put_array_section(buf_r8_kind, global_buf_r8_kind, c, e)
602  deallocate(buf_r8_kind)
603  end select
604  enddo
605  deallocate(pe_isc)
606  deallocate(pe_iec)
607  deallocate(pe_icsize)
608  deallocate(pe_jsc)
609  deallocate(pe_jec)
610  deallocate(pe_jcsize)
611 
612  !Write the out the data.
613  select type(vdata)
614  type is (integer(kind=i4_kind))
615  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
616  unlim_dim_level=unlim_dim_level)
617  deallocate(global_buf_i4_kind)
618  type is (integer(kind=i8_kind))
619  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
620  unlim_dim_level=unlim_dim_level)
621  deallocate(global_buf_i8_kind)
622  type is (real(kind=r4_kind))
623  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
624  unlim_dim_level=unlim_dim_level)
625  deallocate(global_buf_r4_kind)
626  type is (real(kind=r8_kind))
627  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
628  unlim_dim_level=unlim_dim_level)
629  deallocate(global_buf_r8_kind)
630  end select
631  else
632  if (buffer_includes_halos) then
633  c(xdim_index) = isc - isd + 1
634  c(ydim_index) = jsc - jsd + 1
635  endif
636  e(xdim_index) = xc_size
637  e(ydim_index) = yc_size
638  select type(vdata)
639  type is (integer(kind=i4_kind))
640  call allocate_array(buf_i4_kind, e)
641  call get_array_section(buf_i4_kind, vdata, c, e)
642  call mpp_send(buf_i4_kind, size(buf_i4_kind), fileobj%io_root)
643  call mpp_sync_self(check=event_send)
644  deallocate(buf_i4_kind)
645  type is (integer(kind=i8_kind))
646  call allocate_array(buf_i8_kind, e)
647  call get_array_section(buf_i8_kind, vdata, c, e)
648  call mpp_send(buf_i8_kind, size(buf_i8_kind), fileobj%io_root)
649  call mpp_sync_self(check=event_send)
650  deallocate(buf_i8_kind)
651  type is (real(kind=r4_kind))
652  call allocate_array(buf_r4_kind, e)
653  call get_array_section(buf_r4_kind, vdata, c, e)
654  call mpp_send(buf_r4_kind, size(buf_r4_kind), fileobj%io_root)
655  call mpp_sync_self(check=event_send)
656  deallocate(buf_r4_kind)
657  type is (real(kind=r8_kind))
658  call allocate_array(buf_r8_kind, e)
659  call get_array_section(buf_r8_kind, vdata, c, e)
660  call mpp_send(buf_r8_kind, size(buf_r8_kind), fileobj%io_root)
661  call mpp_sync_self(check=event_send)
662  deallocate(buf_r8_kind)
663  class default
664  call error("unsupported variable type: domain_write_3d: file: "//trim(fileobj%path)//" variable:"// &
665  & trim(variable_name))
666  end select
667  endif
668 end subroutine domain_write_3d
669 
670 
671 !> @brief Gather "compute" domain data on the I/O root rank and then have
672 !! the I/O root write out the data that spans the "global" domain.
673 !! This routine may only be used with variables that are "domain
674 !! decomposed".
675 subroutine domain_write_4d(fileobj, variable_name, vdata, unlim_dim_level, &
676  corner, edge_lengths)
677 
678  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
679  character(len=*), intent(in) :: variable_name !< Variable name.
680  class(*), dimension(:,:,:,:), intent(in) :: vdata !< Data that will
681  !! be written out
682  !! to the netcdf file.
683  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
684  !! dimension.
685  integer, dimension(4), intent(in), optional :: corner !< Array of starting
686  !! indices describing
687  !! where the data
688  !! will be written to.
689  integer, dimension(4), intent(in), optional :: edge_lengths !< The number of
690  !! elements that
691  !! will be written
692  !! in each dimension.
693 
694  integer(kind=i4_kind), dimension(:,:,:,:), allocatable :: buf_i4_kind
695  integer(kind=i8_kind), dimension(:,:,:,:), allocatable :: buf_i8_kind
696  real(kind=r4_kind), dimension(:,:,:,:), allocatable :: buf_r4_kind
697  real(kind=r8_kind), dimension(:,:,:,:), allocatable :: buf_r8_kind
698  logical :: buffer_includes_halos
699  integer, dimension(4) :: c
700  integer, dimension(4) :: e
701  integer(kind=i4_kind), dimension(:,:,:,:), allocatable :: global_buf_i4_kind
702  integer(kind=i8_kind), dimension(:,:,:,:), allocatable :: global_buf_i8_kind
703  real(kind=r4_kind), dimension(:,:,:,:), allocatable :: global_buf_r4_kind
704  real(kind=r8_kind), dimension(:,:,:,:), allocatable :: global_buf_r8_kind
705  integer :: i
706  type(domain2d), pointer :: io_domain
707  integer :: isc
708  integer :: isd
709  integer :: jsc
710  integer :: jsd
711  integer, dimension(:), allocatable :: pe_icsize
712  integer, dimension(:), allocatable :: pe_iec
713  integer, dimension(:), allocatable :: pe_isc
714  integer, dimension(:), allocatable :: pe_jcsize
715  integer, dimension(:), allocatable :: pe_jec
716  integer, dimension(:), allocatable :: pe_jsc
717  integer :: xc_size
718  integer :: xdim_index
719  integer :: xpos
720  integer :: ydim_index
721  integer :: ypos
722  integer :: yc_size
723  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
724  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
725  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
726  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
727  integer :: xgmax !< Ending x index of the global io domain
728  integer :: xgmin !< Starting x index of the global io domain
729  integer :: ygmax !< Ending y index of the global io domain
730  integer :: ygmin !< Ending y index of the global io domain
731 
732  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
733  xdim_index, ydim_index, xpos, ypos)) then
734  call compressed_write(fileobj, variable_name, vdata, &
735  unlim_dim_level=unlim_dim_level, corner=corner, &
736  edge_lengths=edge_lengths)
737  return
738  endif
739  io_domain => mpp_get_io_domain(fileobj%domain)
740  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
741  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
742  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
743  c(:) = 1
744  e(:) = shape(vdata)
745 
746  !I/O root gathers the data and writes it.
747  if (fileobj%is_root) then
748  allocate(pe_isc(size(fileobj%pelist)))
749  allocate(pe_iec(size(fileobj%pelist)))
750  allocate(pe_icsize(size(fileobj%pelist)))
751  call mpp_get_compute_domains(io_domain, xbegin=pe_isc, xend=pe_iec, xsize=pe_icsize, &
752  position=xpos)
753  allocate(pe_jsc(size(fileobj%pelist)))
754  allocate(pe_jec(size(fileobj%pelist)))
755  allocate(pe_jcsize(size(fileobj%pelist)))
756  call mpp_get_compute_domains(io_domain, ybegin=pe_jsc, yend=pe_jec, ysize=pe_jcsize, &
757  position=ypos)
758 
759  !< Determine the size of the global io domain
760  call mpp_get_global_domain(io_domain, ybegin=ygmin, yend=ygmax, position=ypos)
761  call mpp_get_global_domain(io_domain, xbegin=xgmin, xend=xgmax, position=xpos)
762 
763  !Write the out the data.
764  !< Set e to equal the size of the global io domain
765  e(xdim_index) = xgmax - xgmin + 1
766  e(ydim_index) = ygmax - ygmin + 1
767 
768  !< Allocate a global buffer, get the fill value if it exists in the file, and initialize
769  !! the buffer to the fill value
770  select type(vdata)
771  type is (integer(kind=i4_kind))
772  call allocate_array(global_buf_i4_kind, e)
773  global_buf_i4_kind = 0
774  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
775  global_buf_i4_kind = fill_i4_kind
776  endif
777  type is (integer(kind=i8_kind))
778  call allocate_array(global_buf_i8_kind, e)
779  global_buf_i8_kind = 0
780  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
781  global_buf_i8_kind = fill_i8_kind
782  endif
783  type is (real(kind=r4_kind))
784  call allocate_array(global_buf_r4_kind, e)
785  global_buf_r4_kind = 0.
786  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
787  global_buf_r4_kind = fill_r4_kind
788  endif
789  type is (real(kind=r8_kind))
790  call allocate_array(global_buf_r8_kind, e)
791  global_buf_r8_kind = 0.
792  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
793  global_buf_r8_kind = fill_r8_kind
794  endif
795  class default
796  call error("unsupported variable type: domain_write_4d: file: "//trim(fileobj%path)//" variable:"// &
797  & trim(variable_name))
798  end select
799 
800  do i = 1, size(fileobj%pelist)
801  !< Set c relative to the starting global io domain index
802  c(xdim_index) = pe_isc(i) - xgmin + 1
803  c(ydim_index) = pe_jsc(i) - ygmin + 1
804  e(xdim_index) = pe_icsize(i)
805  e(ydim_index) = pe_jcsize(i)
806  select type(vdata)
807  type is (integer(kind=i4_kind))
808  call allocate_array(buf_i4_kind, e)
809  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
810  if (i .eq. 1) then
811  !Root rank gets the data directly.
812  if (buffer_includes_halos) then
813  !Adjust if the input buffer has room for halos.
814  c(xdim_index) = isc - isd + 1
815  c(ydim_index) = jsc - jsd + 1
816  else
817  c(xdim_index) = 1
818  c(ydim_index) = 1
819  endif
820  call get_array_section(buf_i4_kind, vdata, c, e)
821  c(xdim_index) = pe_isc(i) - xgmin + 1
822  c(ydim_index) = pe_jsc(i) - ygmin + 1
823  else
824  !Receive data from non-root ranks.
825  call mpp_recv(buf_i4_kind, size(buf_i4_kind), fileobj%pelist(i), block=.true.)
826  endif
827  !Put local data into the global buffer.
828  call put_array_section(buf_i4_kind, global_buf_i4_kind, c, e)
829  deallocate(buf_i4_kind)
830  type is (integer(kind=i8_kind))
831  call allocate_array(buf_i8_kind, e)
832  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
833  if (i .eq. 1) then
834  !Root rank gets the data directly.
835  if (buffer_includes_halos) then
836  !Adjust if the input buffer has room for halos.
837  c(xdim_index) = isc - isd + 1
838  c(ydim_index) = jsc - jsd + 1
839  else
840  c(xdim_index) = 1
841  c(ydim_index) = 1
842  endif
843  call get_array_section(buf_i8_kind, vdata, c, e)
844  c(xdim_index) = pe_isc(i) - xgmin + 1
845  c(ydim_index) = pe_jsc(i) - ygmin + 1
846  else
847  !Receive data from non-root ranks.
848  call mpp_recv(buf_i8_kind, size(buf_i8_kind), fileobj%pelist(i), block=.true.)
849  endif
850  !Put local data into the global buffer.
851  call put_array_section(buf_i8_kind, global_buf_i8_kind, c, e)
852  deallocate(buf_i8_kind)
853  type is (real(kind=r4_kind))
854  call allocate_array(buf_r4_kind, e)
855  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
856  if (i .eq. 1) then
857  !Root rank gets the data directly.
858  if (buffer_includes_halos) then
859  !Adjust if the input buffer has room for halos.
860  c(xdim_index) = isc - isd + 1
861  c(ydim_index) = jsc - jsd + 1
862  else
863  c(xdim_index) = 1
864  c(ydim_index) = 1
865  endif
866  call get_array_section(buf_r4_kind, vdata, c, e)
867  c(xdim_index) = pe_isc(i) - xgmin + 1
868  c(ydim_index) = pe_jsc(i) - ygmin + 1
869  else
870  !Receive data from non-root ranks.
871  call mpp_recv(buf_r4_kind, size(buf_r4_kind), fileobj%pelist(i), block=.true.)
872  endif
873  !Put local data into the global buffer.
874  call put_array_section(buf_r4_kind, global_buf_r4_kind, c, e)
875  deallocate(buf_r4_kind)
876  type is (real(kind=r8_kind))
877  call allocate_array(buf_r8_kind, e)
878  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
879  if (i .eq. 1) then
880  !Root rank gets the data directly.
881  if (buffer_includes_halos) then
882  !Adjust if the input buffer has room for halos.
883  c(xdim_index) = isc - isd + 1
884  c(ydim_index) = jsc - jsd + 1
885  else
886  c(xdim_index) = 1
887  c(ydim_index) = 1
888  endif
889  call get_array_section(buf_r8_kind, vdata, c, e)
890  c(xdim_index) = pe_isc(i) - xgmin + 1
891  c(ydim_index) = pe_jsc(i) - ygmin + 1
892  else
893  !Receive data from non-root ranks.
894  call mpp_recv(buf_r8_kind, size(buf_r8_kind), fileobj%pelist(i), block=.true.)
895  endif
896  !Put local data into the global buffer.
897  call put_array_section(buf_r8_kind, global_buf_r8_kind, c, e)
898  deallocate(buf_r8_kind)
899  end select
900  enddo
901  deallocate(pe_isc)
902  deallocate(pe_iec)
903  deallocate(pe_icsize)
904  deallocate(pe_jsc)
905  deallocate(pe_jec)
906  deallocate(pe_jcsize)
907 
908  !Write the out the data.
909  select type(vdata)
910  type is (integer(kind=i4_kind))
911  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
912  unlim_dim_level=unlim_dim_level)
913  deallocate(global_buf_i4_kind)
914  type is (integer(kind=i8_kind))
915  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
916  unlim_dim_level=unlim_dim_level)
917  deallocate(global_buf_i8_kind)
918  type is (real(kind=r4_kind))
919  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
920  unlim_dim_level=unlim_dim_level)
921  deallocate(global_buf_r4_kind)
922  type is (real(kind=r8_kind))
923  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
924  unlim_dim_level=unlim_dim_level)
925  deallocate(global_buf_r8_kind)
926  end select
927  else
928  if (buffer_includes_halos) then
929  c(xdim_index) = isc - isd + 1
930  c(ydim_index) = jsc - jsd + 1
931  endif
932  e(xdim_index) = xc_size
933  e(ydim_index) = yc_size
934  select type(vdata)
935  type is (integer(kind=i4_kind))
936  call allocate_array(buf_i4_kind, e)
937  call get_array_section(buf_i4_kind, vdata, c, e)
938  call mpp_send(buf_i4_kind, size(buf_i4_kind), fileobj%io_root)
939  call mpp_sync_self(check=event_send)
940  deallocate(buf_i4_kind)
941  type is (integer(kind=i8_kind))
942  call allocate_array(buf_i8_kind, e)
943  call get_array_section(buf_i8_kind, vdata, c, e)
944  call mpp_send(buf_i8_kind, size(buf_i8_kind), fileobj%io_root)
945  call mpp_sync_self(check=event_send)
946  deallocate(buf_i8_kind)
947  type is (real(kind=r4_kind))
948  call allocate_array(buf_r4_kind, e)
949  call get_array_section(buf_r4_kind, vdata, c, e)
950  call mpp_send(buf_r4_kind, size(buf_r4_kind), fileobj%io_root)
951  call mpp_sync_self(check=event_send)
952  deallocate(buf_r4_kind)
953  type is (real(kind=r8_kind))
954  call allocate_array(buf_r8_kind, e)
955  call get_array_section(buf_r8_kind, vdata, c, e)
956  call mpp_send(buf_r8_kind, size(buf_r8_kind), fileobj%io_root)
957  call mpp_sync_self(check=event_send)
958  deallocate(buf_r8_kind)
959  class default
960  call error("unsupported variable type: domain_write_4d: file: "//trim(fileobj%path)//" variable:"// &
961  & trim(variable_name))
962  end select
963  endif
964 end subroutine domain_write_4d
965 
966 
967 !> @brief Gather "compute" domain data on the I/O root rank and then have
968 !! the I/O root write out the data that spans the "global" domain.
969 !! This routine may only be used with variables that are "domain
970 !! decomposed".
971 subroutine domain_write_5d(fileobj, variable_name, vdata, unlim_dim_level, &
972  corner, edge_lengths)
973 
974  type(fmsnetcdfdomainfile_t), intent(in) :: fileobj !< File object.
975  character(len=*), intent(in) :: variable_name !< Variable name.
976  class(*), dimension(:,:,:,:,:), intent(in) :: vdata !< Data that will
977  !! be written out
978  !! to the netcdf file.
979  integer, intent(in), optional :: unlim_dim_level !< Level for the unlimited
980  !! dimension.
981  integer, dimension(5), intent(in), optional :: corner !< Array of starting
982  !! indices describing
983  !! where the data
984  !! will be written to.
985  integer, dimension(5), intent(in), optional :: edge_lengths !< The number of
986  !! elements that
987  !! will be written
988  !! in each dimension.
989 
990  integer(kind=i4_kind), dimension(:,:,:,:,:), allocatable :: buf_i4_kind
991  integer(kind=i8_kind), dimension(:,:,:,:,:), allocatable :: buf_i8_kind
992  real(kind=r4_kind), dimension(:,:,:,:,:), allocatable :: buf_r4_kind
993  real(kind=r8_kind), dimension(:,:,:,:,:), allocatable :: buf_r8_kind
994  logical :: buffer_includes_halos
995  integer, dimension(5) :: c
996  integer, dimension(5) :: e
997  integer(kind=i4_kind), dimension(:,:,:,:,:), allocatable :: global_buf_i4_kind
998  integer(kind=i8_kind), dimension(:,:,:,:,:), allocatable :: global_buf_i8_kind
999  real(kind=r4_kind), dimension(:,:,:,:,:), allocatable :: global_buf_r4_kind
1000  real(kind=r8_kind), dimension(:,:,:,:,:), allocatable :: global_buf_r8_kind
1001  integer :: i
1002  type(domain2d), pointer :: io_domain
1003  integer :: isc
1004  integer :: isd
1005  integer :: jsc
1006  integer :: jsd
1007  integer, dimension(:), allocatable :: pe_icsize
1008  integer, dimension(:), allocatable :: pe_iec
1009  integer, dimension(:), allocatable :: pe_isc
1010  integer, dimension(:), allocatable :: pe_jcsize
1011  integer, dimension(:), allocatable :: pe_jec
1012  integer, dimension(:), allocatable :: pe_jsc
1013  integer :: xc_size
1014  integer :: xdim_index
1015  integer :: xpos
1016  integer :: ydim_index
1017  integer :: ypos
1018  integer :: yc_size
1019  integer(kind=i4_kind) :: fill_i4_kind !< Fill value of a i4_kind variable
1020  integer(kind=i8_kind) :: fill_i8_kind !< Fill value of a i8_kind variable
1021  real(kind=r4_kind) :: fill_r4_kind !< Fill value of a r4_kind variable
1022  real(kind=r8_kind) :: fill_r8_kind !< Fill value of a r8_kind variable
1023  integer :: xgmax !< Ending x index of the global io domain
1024  integer :: xgmin !< Starting x index of the global io domain
1025  integer :: ygmax !< Ending y index of the global io domain
1026  integer :: ygmin !< Ending y index of the global io domain
1027 
1028  if (.not. is_variable_domain_decomposed(fileobj, variable_name, .true., &
1029  xdim_index, ydim_index, xpos, ypos)) then
1030  call compressed_write(fileobj, variable_name, vdata, &
1031  unlim_dim_level=unlim_dim_level, corner=corner, &
1032  edge_lengths=edge_lengths)
1033  return
1034  endif
1035  io_domain => mpp_get_io_domain(fileobj%domain)
1036  call domain_offsets(size(vdata, xdim_index), size(vdata, ydim_index), fileobj%domain, &
1037  xpos, ypos, isd, isc, xc_size, jsd, jsc, yc_size, &
1038  buffer_includes_halos, msg="file:"//trim(fileobj%path)//" and variable:"//trim(variable_name))
1039  c(:) = 1
1040  e(:) = shape(vdata)
1041 
1042  !I/O root gathers the data and writes it.
1043  if (fileobj%is_root) then
1044  allocate(pe_isc(size(fileobj%pelist)))
1045  allocate(pe_iec(size(fileobj%pelist)))
1046  allocate(pe_icsize(size(fileobj%pelist)))
1047  call mpp_get_compute_domains(io_domain, xbegin=pe_isc, xend=pe_iec, xsize=pe_icsize, &
1048  position=xpos)
1049  allocate(pe_jsc(size(fileobj%pelist)))
1050  allocate(pe_jec(size(fileobj%pelist)))
1051  allocate(pe_jcsize(size(fileobj%pelist)))
1052  call mpp_get_compute_domains(io_domain, ybegin=pe_jsc, yend=pe_jec, ysize=pe_jcsize, &
1053  position=ypos)
1054 
1055  !< Determine the size of the global io domain
1056  call mpp_get_global_domain(io_domain, ybegin=ygmin, yend=ygmax, position=ypos)
1057  call mpp_get_global_domain(io_domain, xbegin=xgmin, xend=xgmax, position=xpos)
1058 
1059  !Write the out the data.
1060  !< Set e to equal the size of the global io domain
1061  e(xdim_index) = xgmax - xgmin + 1
1062  e(ydim_index) = ygmax - ygmin + 1
1063 
1064  !< Allocate a global buffer, get the fill value if it exists in the file, and initialize
1065  !! the buffer to the fill value
1066  select type(vdata)
1067  type is (integer(kind=i4_kind))
1068  call allocate_array(global_buf_i4_kind, e)
1069  global_buf_i4_kind = 0
1070  if (get_fill_value(fileobj, variable_name, fill_i4_kind, broadcast=.false.)) then
1071  global_buf_i4_kind = fill_i4_kind
1072  endif
1073  type is (integer(kind=i8_kind))
1074  call allocate_array(global_buf_i8_kind, e)
1075  global_buf_i8_kind = 0
1076  if (get_fill_value(fileobj, variable_name, fill_i8_kind, broadcast=.false.)) then
1077  global_buf_i8_kind = fill_i8_kind
1078  endif
1079  type is (real(kind=r4_kind))
1080  call allocate_array(global_buf_r4_kind, e)
1081  global_buf_r4_kind = 0.
1082  if (get_fill_value(fileobj, variable_name, fill_r4_kind, broadcast=.false.)) then
1083  global_buf_r4_kind = fill_r4_kind
1084  endif
1085  type is (real(kind=r8_kind))
1086  call allocate_array(global_buf_r8_kind, e)
1087  global_buf_r8_kind = 0.
1088  if (get_fill_value(fileobj, variable_name, fill_r8_kind, broadcast=.false.)) then
1089  global_buf_r8_kind = fill_r8_kind
1090  endif
1091  class default
1092  call error("unsupported variable type: domain_write_5d: file: "//trim(fileobj%path)//" variable:"// &
1093  & trim(variable_name))
1094  end select
1095 
1096  do i = 1, size(fileobj%pelist)
1097  !< Set c relative to the starting global io domain index
1098  c(xdim_index) = pe_isc(i) - xgmin + 1
1099  c(ydim_index) = pe_jsc(i) - ygmin + 1
1100  e(xdim_index) = pe_icsize(i)
1101  e(ydim_index) = pe_jcsize(i)
1102  select type(vdata)
1103  type is (integer(kind=i4_kind))
1104  call allocate_array(buf_i4_kind, e)
1105  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
1106  if (i .eq. 1) then
1107  !Root rank gets the data directly.
1108  if (buffer_includes_halos) then
1109  !Adjust if the input buffer has room for halos.
1110  c(xdim_index) = isc - isd + 1
1111  c(ydim_index) = jsc - jsd + 1
1112  else
1113  c(xdim_index) = 1
1114  c(ydim_index) = 1
1115  endif
1116  call get_array_section(buf_i4_kind, vdata, c, e)
1117  c(xdim_index) = pe_isc(i) - xgmin + 1
1118  c(ydim_index) = pe_jsc(i) - ygmin + 1
1119  else
1120  !Receive data from non-root ranks.
1121  call mpp_recv(buf_i4_kind, size(buf_i4_kind), fileobj%pelist(i), block=.true.)
1122  endif
1123  !Put local data into the global buffer.
1124  call put_array_section(buf_i4_kind, global_buf_i4_kind, c, e)
1125  deallocate(buf_i4_kind)
1126  type is (integer(kind=i8_kind))
1127  call allocate_array(buf_i8_kind, e)
1128  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
1129  if (i .eq. 1) then
1130  !Root rank gets the data directly.
1131  if (buffer_includes_halos) then
1132  !Adjust if the input buffer has room for halos.
1133  c(xdim_index) = isc - isd + 1
1134  c(ydim_index) = jsc - jsd + 1
1135  else
1136  c(xdim_index) = 1
1137  c(ydim_index) = 1
1138  endif
1139  call get_array_section(buf_i8_kind, vdata, c, e)
1140  c(xdim_index) = pe_isc(i) - xgmin + 1
1141  c(ydim_index) = pe_jsc(i) - ygmin + 1
1142  else
1143  !Receive data from non-root ranks.
1144  call mpp_recv(buf_i8_kind, size(buf_i8_kind), fileobj%pelist(i), block=.true.)
1145  endif
1146  !Put local data into the global buffer.
1147  call put_array_section(buf_i8_kind, global_buf_i8_kind, c, e)
1148  deallocate(buf_i8_kind)
1149  type is (real(kind=r4_kind))
1150  call allocate_array(buf_r4_kind, e)
1151  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
1152  if (i .eq. 1) then
1153  !Root rank gets the data directly.
1154  if (buffer_includes_halos) then
1155  !Adjust if the input buffer has room for halos.
1156  c(xdim_index) = isc - isd + 1
1157  c(ydim_index) = jsc - jsd + 1
1158  else
1159  c(xdim_index) = 1
1160  c(ydim_index) = 1
1161  endif
1162  call get_array_section(buf_r4_kind, vdata, c, e)
1163  c(xdim_index) = pe_isc(i) - xgmin + 1
1164  c(ydim_index) = pe_jsc(i) - ygmin + 1
1165  else
1166  !Receive data from non-root ranks.
1167  call mpp_recv(buf_r4_kind, size(buf_r4_kind), fileobj%pelist(i), block=.true.)
1168  endif
1169  !Put local data into the global buffer.
1170  call put_array_section(buf_r4_kind, global_buf_r4_kind, c, e)
1171  deallocate(buf_r4_kind)
1172  type is (real(kind=r8_kind))
1173  call allocate_array(buf_r8_kind, e)
1174  !Get the data for fileobj%pelist(i)'s portion of the compute domain.
1175  if (i .eq. 1) then
1176  !Root rank gets the data directly.
1177  if (buffer_includes_halos) then
1178  !Adjust if the input buffer has room for halos.
1179  c(xdim_index) = isc - isd + 1
1180  c(ydim_index) = jsc - jsd + 1
1181  else
1182  c(xdim_index) = 1
1183  c(ydim_index) = 1
1184  endif
1185  call get_array_section(buf_r8_kind, vdata, c, e)
1186  c(xdim_index) = pe_isc(i) - xgmin + 1
1187  c(ydim_index) = pe_jsc(i) - ygmin + 1
1188  else
1189  !Receive data from non-root ranks.
1190  call mpp_recv(buf_r8_kind, size(buf_r8_kind), fileobj%pelist(i), block=.true.)
1191  endif
1192  !Put local data into the global buffer.
1193  call put_array_section(buf_r8_kind, global_buf_r8_kind, c, e)
1194  deallocate(buf_r8_kind)
1195  end select
1196  enddo
1197  deallocate(pe_isc)
1198  deallocate(pe_iec)
1199  deallocate(pe_icsize)
1200  deallocate(pe_jsc)
1201  deallocate(pe_jec)
1202  deallocate(pe_jcsize)
1203 
1204  !Write the out the data.
1205  select type(vdata)
1206  type is (integer(kind=i4_kind))
1207  call netcdf_write_data(fileobj, variable_name, global_buf_i4_kind, &
1208  unlim_dim_level=unlim_dim_level)
1209  deallocate(global_buf_i4_kind)
1210  type is (integer(kind=i8_kind))
1211  call netcdf_write_data(fileobj, variable_name, global_buf_i8_kind, &
1212  unlim_dim_level=unlim_dim_level)
1213  deallocate(global_buf_i8_kind)
1214  type is (real(kind=r4_kind))
1215  call netcdf_write_data(fileobj, variable_name, global_buf_r4_kind, &
1216  unlim_dim_level=unlim_dim_level)
1217  deallocate(global_buf_r4_kind)
1218  type is (real(kind=r8_kind))
1219  call netcdf_write_data(fileobj, variable_name, global_buf_r8_kind, &
1220  unlim_dim_level=unlim_dim_level)
1221  deallocate(global_buf_r8_kind)
1222  end select
1223  else
1224  if (buffer_includes_halos) then
1225  c(xdim_index) = isc - isd + 1
1226  c(ydim_index) = jsc - jsd + 1
1227  endif
1228  e(xdim_index) = xc_size
1229  e(ydim_index) = yc_size
1230  select type(vdata)
1231  type is (integer(kind=i4_kind))
1232  call allocate_array(buf_i4_kind, e)
1233  call get_array_section(buf_i4_kind, vdata, c, e)
1234  call mpp_send(buf_i4_kind, size(buf_i4_kind), fileobj%io_root)
1235  call mpp_sync_self(check=event_send)
1236  deallocate(buf_i4_kind)
1237  type is (integer(kind=i8_kind))
1238  call allocate_array(buf_i8_kind, e)
1239  call get_array_section(buf_i8_kind, vdata, c, e)
1240  call mpp_send(buf_i8_kind, size(buf_i8_kind), fileobj%io_root)
1241  call mpp_sync_self(check=event_send)
1242  deallocate(buf_i8_kind)
1243  type is (real(kind=r4_kind))
1244  call allocate_array(buf_r4_kind, e)
1245  call get_array_section(buf_r4_kind, vdata, c, e)
1246  call mpp_send(buf_r4_kind, size(buf_r4_kind), fileobj%io_root)
1247  call mpp_sync_self(check=event_send)
1248  deallocate(buf_r4_kind)
1249  type is (real(kind=r8_kind))
1250  call allocate_array(buf_r8_kind, e)
1251  call get_array_section(buf_r8_kind, vdata, c, e)
1252  call mpp_send(buf_r8_kind, size(buf_r8_kind), fileobj%io_root)
1253  call mpp_sync_self(check=event_send)
1254  deallocate(buf_r8_kind)
1255  class default
1256  call error("unsupported variable type: domain_write_5d: file: "//trim(fileobj%path)//" variable:"// &
1257  & trim(variable_name))
1258  end select
1259  endif
1260 end subroutine domain_write_5d
1261 !> @}
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 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 ...
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...