FMS 2025.01.02-dev
Flexible Modeling System
Loading...
Searching...
No Matches
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".
29subroutine 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
46end 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".
53subroutine 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
76end 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".
83subroutine 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
372end 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".
379subroutine 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
668end 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".
675subroutine 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
964end 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".
971subroutine 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
1260end 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...