FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
mpp_domains_util.inc
1! -*-f90-*-
2
3!***********************************************************************
4!* GNU Lesser General Public License
5!*
6!* This file is part of the GFDL Flexible Modeling System (FMS).
7!*
8!* FMS is free software: you can redistribute it and/or modify it under
9!* the terms of the GNU Lesser General Public License as published by
10!* the Free Software Foundation, either version 3 of the License, or (at
11!* your option) any later version.
12!*
13!* FMS is distributed in the hope that it will be useful, but WITHOUT
14!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16!* for more details.
17!*
18!* You should have received a copy of the GNU Lesser General Public
19!* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
20!***********************************************************************
21
22!> @file
23!> @brief Utility routines for getting and setting values in @ref mpp_domains_mod
24
25!> @ingroup mpp_domains_mod
26!> @{
27
28 !> @brief Set user stack size.
29 !!
30 !> This sets the size of an array that is used for internal storage by
31 !! <TT>mpp_domains</TT>. This array is used, for instance, to buffer the
32 !! data sent and received in halo updates.<br>
33 !! This call has implied global synchronization. It should be
34 !! placed somewhere where all PEs can call it.
36 !set the mpp_domains_stack variable to be at least n LONG words long
37 integer, intent(in) :: n
38 character(len=8) :: text
39
40 if( n.LE.mpp_domains_stack_size )return
41 if( allocated(mpp_domains_stack) )deallocate(mpp_domains_stack)
42 allocate( mpp_domains_stack(n) )
43 if( allocated(mpp_domains_stack_nonblock) )deallocate(mpp_domains_stack_nonblock)
44 allocate( mpp_domains_stack_nonblock(n) )
45
46 mpp_domains_stack_size = n
47 write( text,'(i8)' )n
48 if( mpp_pe().EQ.mpp_root_pe() )call mpp_error( note, 'MPP_DOMAINS_SET_STACK_SIZE: stack size set to '//text//'.' )
49
50 return
51 end subroutine mpp_domains_set_stack_size
52
53
54!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
55 ! !
56 ! MPP_DOMAINS: overloaded operators (==, /=) !
57 ! !
58!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
59
60 function mpp_domain1d_eq( a, b )
61 logical :: mpp_domain1d_eq
62 type(domain1d), intent(in) :: a, b
63
64 mpp_domain1d_eq = ( a%compute%begin.EQ.b%compute%begin .AND. &
65 a%compute%end .EQ.b%compute%end .AND. &
66 a%domain_data%begin .EQ.b%domain_data%begin .AND. &
67 a%domain_data%end .EQ.b%domain_data%end .AND. &
68 a%global%begin .EQ.b%global%begin .AND. &
69 a%global%end .EQ.b%global%end )
70 !compare pelists
71 ! if( mpp_domain1D_eq )mpp_domain1D_eq = ASSOCIATED(a%list) .AND. ASSOCIATED(b%list)
72 ! if( mpp_domain1D_eq )mpp_domain1D_eq = size(a%list(:)).EQ.size(b%list(:))
73 ! if( mpp_domain1D_eq )mpp_domain1D_eq = ALL(a%list%pe.EQ.b%list%pe)
74
75 return
76 end function mpp_domain1d_eq
77
78 function mpp_domain1d_ne( a, b )
79 logical :: mpp_domain1d_ne
80 type(domain1d), intent(in) :: a, b
81
82 mpp_domain1d_ne = .NOT. ( a.EQ.b )
83 return
84 end function mpp_domain1d_ne
85
86 function mpp_domain2d_eq( a, b )
87 logical :: mpp_domain2d_eq
88 type(domain2d), intent(in) :: a, b
89 integer :: nt, n
90
91 mpp_domain2d_eq = size(a%x(:)) .EQ. size(b%x(:))
92 nt = size(a%x(:))
93 do n = 1, nt
94 if(mpp_domain2d_eq) mpp_domain2d_eq = a%x(n).EQ.b%x(n) .AND. a%y(n).EQ.b%y(n)
95 end do
96
97 if( mpp_domain2d_eq .AND. ((a%pe.EQ.null_pe).OR.(b%pe.EQ.null_pe)) )return !NULL_DOMAIN2D
98 !compare pelists
99 if( mpp_domain2d_eq )mpp_domain2d_eq = ASSOCIATED(a%list) .AND. ASSOCIATED(b%list)
100 if( mpp_domain2d_eq )mpp_domain2d_eq = size(a%list(:)).EQ.size(b%list(:))
101 if( mpp_domain2d_eq )mpp_domain2d_eq = all(a%list%pe.EQ.b%list%pe)
102 if( mpp_domain2d_eq )mpp_domain2d_eq = all(a%io_layout .EQ. b%io_layout)
103 if( mpp_domain2d_eq )mpp_domain2d_eq = a%symmetry .eqv. b%symmetry
104
105 return
106 end function mpp_domain2d_eq
107
108 !#####################################################################
109
110 function mpp_domain2d_ne( a, b )
111 logical :: mpp_domain2d_ne
112 type(domain2d), intent(in) :: a, b
113
114 mpp_domain2d_ne = .NOT. ( a.EQ.b )
115 return
116 end function mpp_domain2d_ne
117
118!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
119 ! !
120 ! MPP_GET and SET routiness: retrieve various components of domains !
121 ! !
122!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
123
124 subroutine mpp_get_compute_domain1d( domain, begin, end, size, max_size, is_global )
125 type(domain1d), intent(in) :: domain
126 integer, intent(out), optional :: begin, end, size, max_size
127 logical, intent(out), optional :: is_global
128
129 if( PRESENT(begin) )begin = domain%compute%begin
130 if( PRESENT(end) )end = domain%compute%end
131 if( PRESENT(size) )size = domain%compute%size
132 if( PRESENT(max_size) )max_size = domain%compute%max_size
133 if( PRESENT(is_global) )is_global = domain%compute%is_global
134 return
135 end subroutine mpp_get_compute_domain1d
136
137 !#####################################################################
138 subroutine mpp_get_data_domain1d( domain, begin, end, size, max_size, is_global )
139 type(domain1d), intent(in) :: domain
140 integer, intent(out), optional :: begin, end, size, max_size
141 logical, intent(out), optional :: is_global
142
143 if( PRESENT(begin) )begin = domain%domain_data%begin
144 if( PRESENT(end) )end = domain%domain_data%end
145 if( PRESENT(size) )size = domain%domain_data%size
146 if( PRESENT(max_size) )max_size = domain%domain_data%max_size
147 if( PRESENT(is_global) )is_global = domain%domain_data%is_global
148 return
149 end subroutine mpp_get_data_domain1d
150
151 !#####################################################################
152 subroutine mpp_get_global_domain1d( domain, begin, end, size, max_size )
153 type(domain1d), intent(in) :: domain
154 integer, intent(out), optional :: begin, end, size, max_size
155
156 if( PRESENT(begin) )begin = domain%global%begin
157 if( PRESENT(end) )end = domain%global%end
158 if( PRESENT(size) )size = domain%global%size
159 if( PRESENT(max_size) )max_size = domain%global%max_size
160 return
161 end subroutine mpp_get_global_domain1d
162
163 !#####################################################################
164 subroutine mpp_get_memory_domain1d( domain, begin, end, size, max_size, is_global )
165 type(domain1d), intent(in) :: domain
166 integer, intent(out), optional :: begin, end, size, max_size
167 logical, intent(out), optional :: is_global
168
169 if( PRESENT(begin) )begin = domain%memory%begin
170 if( PRESENT(end) )end = domain%memory%end
171 if( PRESENT(size) )size = domain%memory%size
172 if( PRESENT(max_size) )max_size = domain%memory%max_size
173 if( PRESENT(is_global) )is_global = domain%memory%is_global
174 return
175 end subroutine mpp_get_memory_domain1d
176
177 !#####################################################################
178 subroutine mpp_get_compute_domain2d( domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, &
179 x_is_global, y_is_global, tile_count, position )
180 type(domain2d), intent(in) :: domain
181 integer, intent(out), optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
182 logical, intent(out), optional :: x_is_global, y_is_global
183 integer, intent(in), optional :: tile_count, position
184 integer :: tile, ishift, jshift
185
186 tile = 1
187 if(present(tile_count)) tile = tile_count
188
189 call mpp_get_compute_domain( domain%x(tile), xbegin, xend, xsize, xmax_size, x_is_global )
190 call mpp_get_compute_domain( domain%y(tile), ybegin, yend, ysize, ymax_size, y_is_global )
191 call mpp_get_domain_shift( domain, ishift, jshift, position )
192 if( PRESENT(xend) ) xend = xend + ishift
193 if( PRESENT(yend) ) yend = yend + jshift
194 if( PRESENT(xsize)) xsize = xsize + ishift
195 if( PRESENT(ysize)) ysize = ysize + jshift
196 if(PRESENT(xmax_size))xmax_size = xmax_size + ishift
197 if(PRESENT(ymax_size))ymax_size = ymax_size + jshift
198
199 return
200 end subroutine mpp_get_compute_domain2d
201
202 !#####################################################################
203 subroutine mpp_get_data_domain2d( domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, &
204 x_is_global, y_is_global, tile_count, position )
205 type(domain2d), intent(in) :: domain
206 integer, intent(out), optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
207 logical, intent(out), optional :: x_is_global, y_is_global
208 integer, intent(in), optional :: tile_count, position
209 integer :: tile, ishift, jshift
210
211 tile = 1
212 if(present(tile_count)) tile = tile_count
213
214 call mpp_get_data_domain( domain%x(tile), xbegin, xend, xsize, xmax_size, x_is_global )
215 call mpp_get_data_domain( domain%y(tile), ybegin, yend, ysize, ymax_size, y_is_global )
216 call mpp_get_domain_shift( domain, ishift, jshift, position )
217 if( PRESENT(xend) ) xend = xend + ishift
218 if( PRESENT(yend) ) yend = yend + jshift
219 if( PRESENT(xsize)) xsize = xsize + ishift
220 if( PRESENT(ysize)) ysize = ysize + jshift
221 if(PRESENT(xmax_size))xmax_size = xmax_size + ishift
222 if(PRESENT(ymax_size))ymax_size = ymax_size + jshift
223
224 return
225 end subroutine mpp_get_data_domain2d
226
227 !#####################################################################
228 subroutine mpp_get_global_domain2d( domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, &
229 tile_count, position )
230 type(domain2d), intent(in) :: domain
231 integer, intent(out), optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
232 integer, intent(in), optional :: tile_count, position
233 integer :: tile, ishift, jshift
234
235 tile = 1
236 if(present(tile_count)) tile = tile_count
237
238 call mpp_get_global_domain( domain%x(tile), xbegin, xend, xsize, xmax_size )
239 call mpp_get_global_domain( domain%y(tile), ybegin, yend, ysize, ymax_size )
240 call mpp_get_domain_shift( domain, ishift, jshift, position )
241 if( PRESENT(xend) ) xend = xend + ishift
242 if( PRESENT(yend) ) yend = yend + jshift
243 if( PRESENT(xsize)) xsize = xsize + ishift
244 if( PRESENT(ysize)) ysize = ysize + jshift
245 if(PRESENT(xmax_size))xmax_size = xmax_size + ishift
246 if(PRESENT(ymax_size))ymax_size = ymax_size + jshift
247
248 return
249 end subroutine mpp_get_global_domain2d
250
251 !#####################################################################
252 subroutine mpp_get_memory_domain2d( domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, &
253 x_is_global, y_is_global, position)
254 type(domain2d), intent(in) :: domain
255 integer, intent(out), optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
256 logical, intent(out), optional :: x_is_global, y_is_global
257 integer, intent(in), optional :: position
258 integer :: tile, ishift, jshift
259
260 tile = 1
261
262 call mpp_get_memory_domain( domain%x(tile), xbegin, xend, xsize, xmax_size, x_is_global )
263 call mpp_get_memory_domain( domain%y(tile), ybegin, yend, ysize, ymax_size, y_is_global )
264 call mpp_get_domain_shift( domain, ishift, jshift, position )
265 if( PRESENT(xend) ) xend = xend + ishift
266 if( PRESENT(yend) ) yend = yend + jshift
267 if( PRESENT(xsize)) xsize = xsize + ishift
268 if( PRESENT(ysize)) ysize = ysize + jshift
269 if(PRESENT(xmax_size))xmax_size = xmax_size + ishift
270 if(PRESENT(ymax_size))ymax_size = ymax_size + jshift
271
272 return
273 end subroutine mpp_get_memory_domain2d
274
275 !> @brief Modifies the indices in the domain_axis_spec type to those of the supergrid
277 type(domain_axis_spec), intent(inout) :: grid !< domain_axis_spec type
278
279 grid%begin = 2*grid%begin-1
280 grid%end = 2*grid%end+1
281 grid%size = grid%end-grid%begin+1
282
283 end subroutine mpp_set_super_grid_indices
284
285 !> @brief Modifies the indices of the input domain to create the supergrid domain
286 !!
287 !> This is an example of how to use mpp_create_super_grid_domain
288 !! @code{.F90}
289 !! call mpp_copy_domain(domain_in, domain_out)
290 !! call super_grid_domain(domain_out)
291 !! @endcode
292 !! domain_in is the original domain, domain_out is the domain with the supergrid indices.
294 type(domain2d), intent(inout) :: domain !< Input domain
295
296 integer :: xbegin !< Begining x indices
297 integer :: ybegin !< Begining y indices
298 integer :: xend !< Ending x indices
299 integer :: yend !< Ending y indices
300 integer :: xsize !< Size of the x domain
301 integer :: ysize !< Size of the y domain
302 integer :: i !< For loops
303
304 call mpp_get_global_domain(domain, xbegin=xbegin, xend=xend, ybegin=ybegin, yend=yend, xsize=xsize, ysize=ysize)
305 call mpp_set_global_domain (domain, 2*xbegin-1, 2*xend+1, 2*ybegin-1, 2*yend+1, 2*(xend-xbegin)+3, &
306 & 2*(yend-ybegin)+3)
307
308 call mpp_get_compute_domain(domain, xbegin=xbegin, xend=xend, ybegin=ybegin, yend=yend, xsize=xsize, ysize=ysize)
309 call mpp_set_compute_domain (domain, 2*xbegin-1, 2*xend+1, 2*ybegin-1, 2*yend+1, 2*(xend-xbegin)+3, &
310 & 2*(yend-ybegin)+3)
311
312 call mpp_get_data_domain(domain, xbegin=xbegin, xend=xend, ybegin=ybegin, yend=yend, xsize=xsize, ysize=ysize)
313 call mpp_set_data_domain (domain, 2*xbegin-1, 2*xend+1, 2*ybegin-1, 2*yend+1, 2*(xend-xbegin)+3, 2*(yend-ybegin)+3)
314
315 do i=1, size(domain%list(:))
316 call mpp_set_super_grid_indices(domain%list(i-1)%x(1)%global)
317 call mpp_set_super_grid_indices(domain%list(i-1)%y(1)%global)
318
319 call mpp_set_super_grid_indices(domain%list(i-1)%x(1)%compute)
320 call mpp_set_super_grid_indices(domain%list(i-1)%y(1)%compute)
321
322 !< There is no data domain in domain%list
323 !call mpp_set_super_grid_indices(domain%list(i-1)%x(1)%domain_data)
324 !call mpp_set_super_grid_indices(domain%list(i-1)%y(1)%domain_data)
325 enddo
326
327 do i=1, size(domain%x(1)%list)
328 call mpp_set_super_grid_indices(domain%x(1)%list(i-1)%compute)
329 enddo
330
331 do i=1, size(domain%y(1)%list)
332 call mpp_set_super_grid_indices(domain%y(1)%list(i-1)%compute)
333 enddo
334
335 end subroutine mpp_create_super_grid_domain
336
337 !#####################################################################
338 subroutine mpp_set_compute_domain1d( domain, begin, end, size, is_global )
339 type(domain1d), intent(inout) :: domain
340 integer, intent(in), optional :: begin, end, size
341 logical, intent(in), optional :: is_global
342
343 if(present(begin)) domain%compute%begin = begin
344 if(present(end)) domain%compute%end = end
345 if(present(size)) domain%compute%size = size
346 if(present(is_global)) domain%compute%is_global = is_global
347
348 end subroutine mpp_set_compute_domain1d
349
350 !#####################################################################
351 subroutine mpp_set_compute_domain2d( domain, xbegin, xend, ybegin, yend, xsize, ysize, &
352 x_is_global, y_is_global, tile_count )
353 type(domain2d), intent(inout) :: domain
354 integer, intent(in), optional :: xbegin, xend, ybegin, yend, xsize, ysize
355 logical, intent(in), optional :: x_is_global, y_is_global
356 integer, intent(in), optional :: tile_count
357 integer :: tile
358
359 tile = 1
360 if(present(tile_count)) tile = tile_count
361
362 call mpp_set_compute_domain(domain%x(tile), xbegin, xend, xsize, x_is_global)
363 call mpp_set_compute_domain(domain%y(tile), ybegin, yend, ysize, y_is_global)
364
365 end subroutine mpp_set_compute_domain2d
366
367 !#####################################################################
368 subroutine mpp_set_data_domain1d( domain, begin, end, size, is_global )
369 type(domain1d), intent(inout) :: domain
370 integer, intent(in), optional :: begin, end, size
371 logical, intent(in), optional :: is_global
372
373 if(present(begin)) domain%domain_data%begin = begin
374 if(present(end)) domain%domain_data%end = end
375 if(present(size)) domain%domain_data%size = size
376 if(present(is_global)) domain%domain_data%is_global = is_global
377
378 end subroutine mpp_set_data_domain1d
379
380 !#####################################################################
381 subroutine mpp_set_data_domain2d( domain, xbegin, xend, ybegin, yend, xsize, ysize, &
382 x_is_global, y_is_global, tile_count )
383 type(domain2d), intent(inout) :: domain
384 integer, intent(in), optional :: xbegin, xend, ybegin, yend, xsize, ysize
385 logical, intent(in), optional :: x_is_global, y_is_global
386 integer, intent(in), optional :: tile_count
387 integer :: tile
388
389 tile = 1
390 if(present(tile_count)) tile = tile_count
391
392 call mpp_set_data_domain(domain%x(tile), xbegin, xend, xsize, x_is_global)
393 call mpp_set_data_domain(domain%y(tile), ybegin, yend, ysize, y_is_global)
394
395 end subroutine mpp_set_data_domain2d
396
397 !#####################################################################
398 subroutine mpp_set_global_domain1d( domain, begin, end, size)
399 type(domain1d), intent(inout) :: domain
400 integer, intent(in), optional :: begin, end, size
401
402 if(present(begin)) domain%global%begin = begin
403 if(present(end)) domain%global%end = end
404 if(present(size)) domain%global%size = size
405
406 end subroutine mpp_set_global_domain1d
407
408 !#####################################################################
409 subroutine mpp_set_global_domain2d( domain, xbegin, xend, ybegin, yend, xsize, ysize, tile_count )
410 type(domain2d), intent(inout) :: domain
411 integer, intent(in), optional :: xbegin, xend, ybegin, yend, xsize, ysize
412 integer, intent(in), optional :: tile_count
413 integer :: tile
414
415 tile = 1
416 if(present(tile_count)) tile = tile_count
417 call mpp_set_global_domain(domain%x(tile), xbegin, xend, xsize)
418 call mpp_set_global_domain(domain%y(tile), ybegin, yend, ysize)
419
420 end subroutine mpp_set_global_domain2d
421
422 !#####################################################################
423
424 !> @brief Retrieve 1D components of 2D decomposition.
425 !!
426 !! It is sometime necessary to have direct recourse to the domain1D types
427 !! that compose a domain2D object. This call retrieves them.
428 !! @code{.F90}
429 !! call mpp_get_domain_components( domain, x, y )
430 !! @endcode
431 subroutine mpp_get_domain_components( domain, x, y, tile_count )
432 type(domain2d), intent(in) :: domain
433 type(domain1d), intent(inout), optional :: x, y
434 integer, intent(in), optional :: tile_count
435 integer :: tile
436
437 tile = 1
438 if(present(tile_count)) tile = tile_count
439 if( PRESENT(x) )x = domain%x(tile)
440 if( PRESENT(y) )y = domain%y(tile)
441 return
442 end subroutine mpp_get_domain_components
443
444 !#####################################################################
445 subroutine mpp_get_compute_domains1d( domain, begin, end, size )
446 type(domain1d), intent(in) :: domain
447 integer, intent(out), optional, dimension(:) :: begin, end, size
448
449 if( .NOT.module_is_initialized ) &
450 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: must first call mpp_domains_init.' )
451 !we use shape instead of size for error checks because size is used as an argument
452 if( PRESENT(begin) )then
453 if( any(shape(begin).NE.shape(domain%list)) ) &
454 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: begin array size does not match domain.' )
455 begin(:) = domain%list(:)%compute%begin
456 end if
457 if( PRESENT(end) )then
458 if( any(shape(end).NE.shape(domain%list)) ) &
459 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: end array size does not match domain.' )
460 end(:) = domain%list(:)%compute%end
461 end if
462 if( PRESENT(size) )then
463 if( any(shape(size).NE.shape(domain%list)) ) &
464 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: size array size does not match domain.' )
465 size(:) = domain%list(:)%compute%size
466 end if
467 return
468end subroutine mpp_get_compute_domains1d
469
470!#####################################################################
471subroutine mpp_get_compute_domains2d( domain, xbegin, xend, xsize, ybegin, yend, ysize, position )
472 type(domain2d), intent(in) :: domain
473 integer, intent(out), optional, dimension(:) :: xbegin, xend, xsize, ybegin, yend, ysize
474 integer, intent(in ), optional :: position
475
476 integer :: i, ishift, jshift
477
478 call mpp_get_domain_shift( domain, ishift, jshift, position )
479
480
481 if( .NOT.module_is_initialized ) &
482 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: must first call mpp_domains_init.' )
483
484 if( PRESENT(xbegin) )then
485 if( size(xbegin(:)).NE.size(domain%list(:)) ) &
486 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: xbegin array size does not match domain.' )
487 do i = 1, size(xbegin(:))
488 xbegin(i) = domain%list(i-1)%x(1)%compute%begin
489 end do
490 end if
491 if( PRESENT(xend) )then
492 if( size(xend(:)).NE.size(domain%list(:)) ) &
493 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: xend array size does not match domain.' )
494 do i = 1, size(xend(:))
495 xend(i) = domain%list(i-1)%x(1)%compute%end + ishift
496 end do
497 end if
498 if( PRESENT(xsize) )then
499 if( size(xsize(:)).NE.size(domain%list(:)) ) &
500 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: xsize array size does not match domain.' )
501 do i = 1, size(xsize(:))
502 xsize(i) = domain%list(i-1)%x(1)%compute%size + ishift
503 end do
504 end if
505 if( PRESENT(ybegin) )then
506 if( size(ybegin(:)).NE.size(domain%list(:)) ) &
507 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: ybegin array size does not match domain.' )
508 do i = 1, size(ybegin(:))
509 ybegin(i) = domain%list(i-1)%y(1)%compute%begin
510 end do
511 end if
512 if( PRESENT(yend) )then
513 if( size(yend(:)).NE.size(domain%list(:)) ) &
514 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: yend array size does not match domain.' )
515 do i = 1, size(yend(:))
516 yend(i) = domain%list(i-1)%y(1)%compute%end + jshift
517 end do
518 end if
519 if( PRESENT(ysize) )then
520 if( size(ysize(:)).NE.size(domain%list(:)) ) &
521 call mpp_error( fatal, 'MPP_GET_COMPUTE_DOMAINS: ysize array size does not match domain.' )
522 do i = 1, size(ysize(:))
523 ysize(i) = domain%list(i-1)%y(1)%compute%size + jshift
524 end do
525 end if
526 return
527end subroutine mpp_get_compute_domains2d
528
529 !#####################################################################
530 subroutine mpp_get_global_domains1d( domain, begin, end, size )
531 type(domain1d), intent(in) :: domain
532 integer, intent(out), optional, dimension(:) :: begin, end, size
533
534 if( .NOT.module_is_initialized ) &
535 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: must first call mpp_domains_init.' )
536 !we use shape instead of size for error checks because size is used as an argument
537 if( PRESENT(begin) )then
538 if( any(shape(begin).NE.shape(domain%list)) ) &
539 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: begin array size does not match domain.' )
540 begin(:) = domain%list(:)%global%begin
541 end if
542 if( PRESENT(end) )then
543 if( any(shape(end).NE.shape(domain%list)) ) &
544 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: end array size does not match domain.' )
545 end(:) = domain%list(:)%global%end
546 end if
547 if( PRESENT(size) )then
548 if( any(shape(size).NE.shape(domain%list)) ) &
549 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: size array size does not match domain.' )
550 size(:) = domain%list(:)%global%size
551 end if
552 return
553 end subroutine mpp_get_global_domains1d
554
555
556!#####################################################################
557subroutine mpp_get_global_domains2d( domain, xbegin, xend, xsize, ybegin, yend, ysize, position )
558 type(domain2d), intent(in) :: domain
559 integer, intent(out), optional, dimension(:) :: xbegin, xend, xsize, ybegin, yend, ysize
560 integer, intent(in ), optional :: position
561
562 integer :: i, ishift, jshift
563
564 call mpp_get_domain_shift( domain, ishift, jshift, position )
565
566
567 if( .NOT.module_is_initialized ) &
568 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: must first call mpp_domains_init.' )
569
570 if( PRESENT(xbegin) )then
571 if( size(xbegin(:)).NE.size(domain%list(:)) ) &
572 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: xbegin array size does not match domain.' )
573 do i = 1, size(xbegin(:))
574 xbegin(i) = domain%list(i-1)%x(1)%global%begin
575 end do
576 end if
577 if( PRESENT(xend) )then
578 if( size(xend(:)).NE.size(domain%list(:)) ) &
579 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: xend array size does not match domain.' )
580 do i = 1, size(xend(:))
581 xend(i) = domain%list(i-1)%x(1)%global%end + ishift
582 end do
583 end if
584 if( PRESENT(xsize) )then
585 if( size(xsize(:)).NE.size(domain%list(:)) ) &
586 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: xsize array size does not match domain.' )
587 do i = 1, size(xsize(:))
588 xsize(i) = domain%list(i-1)%x(1)%global%size + ishift
589 end do
590 end if
591 if( PRESENT(ybegin) )then
592 if( size(ybegin(:)).NE.size(domain%list(:)) ) &
593 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: ybegin array size does not match domain.' )
594 do i = 1, size(ybegin(:))
595 ybegin(i) = domain%list(i-1)%y(1)%global%begin
596 end do
597 end if
598 if( PRESENT(yend) )then
599 if( size(yend(:)).NE.size(domain%list(:)) ) &
600 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: yend array size does not match domain.' )
601 do i = 1, size(yend(:))
602 yend(i) = domain%list(i-1)%y(1)%global%end + jshift
603 end do
604 end if
605 if( PRESENT(ysize) )then
606 if( size(ysize(:)).NE.size(domain%list(:)) ) &
607 call mpp_error( fatal, 'MPP_GET_GLOBAL_DOMAINS: ysize array size does not match domain.' )
608 do i = 1, size(ysize(:))
609 ysize(i) = domain%list(i-1)%y(1)%global%size + jshift
610 end do
611 end if
612 return
613end subroutine mpp_get_global_domains2d
614
615
616!#####################################################################
617subroutine mpp_get_domain_extents1d(domain, xextent, yextent)
618 type(domain2d), intent(in) :: domain
619 integer, dimension(0:), intent(inout) :: xextent, yextent
620 integer :: n
621
622 if(domain%ntiles .NE. 1) call mpp_error(fatal,"mpp_domains_util.inc(mpp_get_domain_extents1D): "// &
623 "ntiles is more than 1, please use mpp_get_domain_extents2D")
624 if(size(xextent) .NE. size(domain%x(1)%list(:))) call mpp_error(fatal, &
625 & "mpp_domains_util.inc(mpp_get_domain_extents1D): "// &
626 & "size(xextent) does not equal to size(domain%x(1)%list(:)))")
627 if(size(yextent) .NE. size(domain%y(1)%list(:))) call mpp_error(fatal, &
628 & "mpp_domains_util.inc(mpp_get_domain_extents1D): "// &
629 & "size(yextent) does not equal to size(domain%y(1)%list(:)))")
630 do n = 0, size(domain%x(1)%list(:))-1
631 xextent(n) = domain%x(1)%list(n)%compute%size
632 enddo
633 do n = 0, size(domain%y(1)%list(:))-1
634 yextent(n) = domain%y(1)%list(n)%compute%size
635 enddo
636
637end subroutine mpp_get_domain_extents1d
638
639!#####################################################################
640!> This will return xextent and yextent for each tile
641subroutine mpp_get_domain_extents2d(domain, xextent, yextent)
642 type(domain2d), intent(in) :: domain
643 integer, dimension(:,:), intent(inout) :: xextent, yextent
644 integer :: ntile, nlist, n, m, ndivx, ndivy, tile, pos
645
646 ntile = domain%ntiles
647 nlist = size(domain%list(:))
648 if(size(xextent,2) .ne. ntile .or. size(yextent,2) .ne. ntile) call mpp_error(fatal, &
649 "mpp_domains_utile.inc: the second dimension size of xextent/yextent is not correct")
650 ndivx = size(xextent,1); ndivy = size(yextent,1)
651 do n = 0, nlist-1
652 if(any(domain%list(n)%x(:)%pos>ndivx-1) ) call mpp_error(fatal, &
653 "mpp_domains_utile.inc: first dimension size of xextent is less than the x-layout in some tile")
654 if(any(domain%list(n)%y(:)%pos>ndivy-1) ) call mpp_error(fatal, &
655 "mpp_domains_utile.inc: first dimension size of yextent is less than the y-layout in some tile")
656 end do
657
658 xextent = 0; yextent=0
659
660 do n = 0, nlist-1
661 do m = 1, size(domain%list(n)%tile_id(:))
662 tile = domain%list(n)%tile_id(m)
663 pos = domain%list(n)%x(m)%pos+1
664 if(xextent(pos, tile) == 0) xextent(pos,tile) = domain%list(n)%x(m)%compute%size
665 pos = domain%list(n)%y(m)%pos+1
666 if(yextent(pos, tile) == 0) yextent(pos,tile) = domain%list(n)%y(m)%compute%size
667 end do
668 end do
669
670
671end subroutine mpp_get_domain_extents2d
672
673!#####################################################################
674function mpp_get_domain_pe(domain)
675 type(domain2d), intent(in) :: domain
676 integer :: mpp_get_domain_pe
677
678 mpp_get_domain_pe = domain%pe
679
680
681end function mpp_get_domain_pe
682
683
685 type(domain2d), intent(in) :: domain
687
688 mpp_get_domain_tile_root_pe = domain%tile_root_pe
689
691
692
694 type(domain2d), intent(in) :: domain !> domain you are querying for information
695 integer :: mpp_get_domain_tile_commid !> declaration of the return tile communicator
696
697 mpp_get_domain_tile_commid = domain%tile_comm_id
698
700
701
702function mpp_get_domain_commid(domain)
703 type(domain2d), intent(in) :: domain !> domain you are querying for information
704 integer :: mpp_get_domain_commid !> declaration of the return domain communicator
705
706 mpp_get_domain_commid = domain%comm_id
707
708end function mpp_get_domain_commid
709
710
711function mpp_get_io_domain(domain)
712 type(domain2d), intent(in) :: domain
713 type(domain2d), pointer :: mpp_get_io_domain
714
715 if(ASSOCIATED(domain%io_domain)) then
716 mpp_get_io_domain => domain%io_domain
717 else
718 mpp_get_io_domain => null()
719 endif
720
721end function mpp_get_io_domain
722
723!#####################################################################
724! <SUBROUTINE NAME="mpp_get_pelist1D" INTERFACE="mpp_get_pelist">
725! <IN NAME="domain" TYPE="type(domain1D)"></IN>
726! <OUT NAME="pelist" TYPE="integer" DIM="(:)"></OUT>
727! <OUT NAME="pos" TYPE="integer"></OUT>
728! </SUBROUTINE>
729subroutine mpp_get_pelist1d( domain, pelist, pos )
730 type(domain1d), intent(in) :: domain
731 integer, intent(out) :: pelist(:)
732 integer, intent(out), optional :: pos
733 integer :: ndivs
734
735 if( .NOT.module_is_initialized ) &
736 call mpp_error( fatal, 'MPP_GET_PELIST: must first call mpp_domains_init.' )
737 ndivs = size(domain%list(:))
738
739 if( size(pelist(:)).NE.ndivs ) &
740 call mpp_error( fatal, 'MPP_GET_PELIST: pelist array size does not match domain.' )
741
742 pelist(:) = domain%list(0:ndivs-1)%pe
743 if( PRESENT(pos) )pos = domain%pos
744 return
745end subroutine mpp_get_pelist1d
746
747!#####################################################################
748! <SUBROUTINE NAME="mpp_get_pelist2D" INTERFACE="mpp_get_pelist">
749! <IN NAME="domain" TYPE="type(domain2D)"></IN>
750! <OUT NAME="pelist" TYPE="integer" DIM="(:)"></OUT>
751! <OUT NAME="pos" TYPE="integer"></OUT>
752! </SUBROUTINE>
753subroutine mpp_get_pelist2d( domain, pelist, pos )
754 type(domain2d), intent(in) :: domain
755 integer, intent(out) :: pelist(:)
756 integer, intent(out), optional :: pos
757
758 if( .NOT.module_is_initialized ) &
759 call mpp_error( fatal, 'MPP_GET_PELIST: must first call mpp_domains_init.' )
760 if( size(pelist(:)).NE.size(domain%list(:)) ) &
761 call mpp_error( fatal, 'MPP_GET_PELIST: pelist array size does not match domain.' )
762
763 pelist(:) = domain%list(:)%pe
764 if( PRESENT(pos) )pos = domain%pos
765 return
766end subroutine mpp_get_pelist2d
767
768!#####################################################################
769! <SUBROUTINE NAME="mpp_get_layout1D" INTERFACE="mpp_get_layout">
770! <IN NAME="domain" TYPE="type(domain1D)"></IN>
771! <OUT NAME="layout" TYPE="integer"></OUT>
772! </SUBROUTINE>
773subroutine mpp_get_layout1d( domain, layout )
774 type(domain1d), intent(in) :: domain
775 integer, intent(out) :: layout
776
777 if( .NOT.module_is_initialized ) &
778 call mpp_error( fatal, 'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
779
780 layout = size(domain%list(:))
781 return
782end subroutine mpp_get_layout1d
783
784!#####################################################################
785! <SUBROUTINE NAME="mpp_get_layout2D" INTERFACE="mpp_get_layout">
786! <IN NAME="domain" TYPE="type(domain2D)"></IN>
787! <OUT NAME="layout" TYPE="integer" DIM="(2)"></OUT>
788! </SUBROUTINE>
789subroutine mpp_get_layout2d( domain, layout )
790 type(domain2d), intent(in) :: domain
791 integer, intent(out) :: layout(2)
792
793 if( .NOT.module_is_initialized ) &
794 call mpp_error( fatal, 'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
795
796 layout(1) = size(domain%x(1)%list(:))
797 layout(2) = size(domain%y(1)%list(:))
798 return
799end subroutine mpp_get_layout2d
800
801!#####################################################################
802
803 !> @brief Returns the shift value in x and y-direction according to domain position..
804 !!
805 !> When domain is symmetry, one extra point maybe needed in
806 !! x- and/or y-direction. This routine will return the shift value based
807 !! on the position
808 !! @code{.F90}
809 !! call mpp_get_domain_shift( domain, ishift, jshift, position )
810 !! @endcode
811subroutine mpp_get_domain_shift(domain, ishift, jshift, position)
812 type(domain2d), intent(in) :: domain!> predefined data contains 2-d domain decomposition.
813 integer, intent(out) :: ishift, jshift!< return value will be 0 or 1.
814 integer, optional, intent(in) :: position!< position of data. Its value can be CENTER, EAST, NORTH or CORNER.
815 integer :: pos
816
817 ishift = 0 ; jshift = 0
818 pos = center
819 if(present(position)) pos = position
820
821 if(domain%symmetry) then ! shift is non-zero only when the domain is symmetry.
822 select case(pos)
823 case(corner)
824 ishift = 1; jshift = 1
825 case(east)
826 ishift = 1
827 case(north)
828 jshift = 1
829 end select
830 end if
831
832end subroutine mpp_get_domain_shift
833
834!#####################################################################
835
836 !> Return PE to the righ/left of this PE-domain.
837 subroutine mpp_get_neighbor_pe_1d(domain, direction, pe)
838 type(domain1d), intent(inout) :: domain
839 integer, intent(in) :: direction
840 integer, intent(out) :: pe
841
842 integer ipos, ipos2, npx
843
844 pe = null_pe
845 npx = size(domain%list(:)) ! 0..npx-1
846 ipos = domain%pos
847
848 select case (direction)
849
850 case (:-1)
851 ! neighbor on the left
852 ipos2 = ipos - 1
853 if(ipos2 < 0) then
854 if(domain%cyclic) then
855 ipos2 = npx-1
856 else
857 ipos2 = -999
858 endif
859 endif
860
861 case (0)
862 ! identity
863 ipos2 = ipos
864
865 case (1:)
866 ! neighbor on the right
867 ipos2 = ipos + 1
868 if(ipos2 > npx-1) then
869 if(domain%cyclic) then
870 ipos2 = 0
871 else
872 ipos2 = -999
873 endif
874 endif
875
876 end select
877
878 if(ipos2 >= 0) pe = domain%list(ipos2)%pe
879
880 end subroutine mpp_get_neighbor_pe_1d
881!#####################################################################
882
883 !> Return PE North/South/East/West of this PE-domain.
884 !! direction must be NORTH, SOUTH, EAST or WEST.
885 subroutine mpp_get_neighbor_pe_2d(domain, direction, pe)
886 type(domain2d), intent(inout) :: domain
887 integer, intent(in) :: direction
888 integer, intent(out) :: pe
889
890 integer ipos, jpos, npx, npy, ix, iy, ipos0, jpos0
891
892 pe = null_pe
893 npx = size(domain%x(1)%list(:)) ! 0..npx-1
894 npy = size(domain%y(1)%list(:)) ! 0..npy-1
895 ipos0 = domain%x(1)%pos
896 jpos0 = domain%y(1)%pos
897
898 select case (direction)
899 case (north)
900 ix = 0
901 iy = 1
902 case (north_east)
903 ix = 1
904 iy = 1
905 case (east)
906 ix = 1
907 iy = 0
908 case (south_east)
909 ix = 1
910 iy =-1
911 case (south)
912 ix = 0
913 iy =-1
914 case (south_west)
915 ix =-1
916 iy =-1
917 case (west)
918 ix =-1
919 iy = 0
920 case (north_west)
921 ix =-1
922 iy = 1
923
924 case default
925 call mpp_error( fatal, &
926 & 'MPP_GET_NEIGHBOR_PE_2D: direction must be either NORTH, ' &
927 & // 'SOUTH, EAST, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST or NORTH_WEST')
928 end select
929
930 ipos = ipos0 + ix
931 jpos = jpos0 + iy
932
933
934 if( (ipos < 0 .or. ipos > npx-1) .and. domain%x(1)%cyclic ) then
935 ! E/W cyclic domain
936 ipos = modulo(ipos, npx)
937 endif
938
939 if( (ipos < 0 .and. btest(domain%fold,west)) .or. &
940 & (ipos > npx-1 .and. btest(domain%fold,east)) ) then
941 ! E or W folded domain
942 ipos = ipos0
943 jpos = npy-jpos-1
944 endif
945
946 if( (jpos < 0 .or. jpos > npy-1) .and. domain%y(1)%cyclic ) then
947 ! N/S cyclic
948 jpos = modulo(jpos, npy)
949 endif
950
951 if( (jpos < 0 .and. btest(domain%fold,south)) .or. &
952 & (jpos > npy-1 .and. btest(domain%fold,north)) ) then
953 ! N or S folded
954 ipos = npx-ipos-1
955 jpos = jpos0
956 endif
957
958 ! get the PE number
959 pe = null_pe
960 if(ipos >= 0 .and. ipos <= npx-1 .and. jpos >= 0 .and. jpos <= npy-1) then
961 pe = domain%pearray(ipos, jpos)
962 endif
963
964
965 end subroutine mpp_get_neighbor_pe_2d
966
967
968!#######################################################################
969
970 subroutine nullify_domain2d_list(domain)
971 type(domain2d), intent(inout) :: domain
972
973 domain%list =>null()
974
975 end subroutine nullify_domain2d_list
976
977!#######################################################################
978 function mpp_domain_is_symmetry(domain)
979 type(domain2d), intent(in) :: domain
980 logical :: mpp_domain_is_symmetry
981
982 mpp_domain_is_symmetry = domain%symmetry
983 return
984
985 end function mpp_domain_is_symmetry
986
987!#######################################################################
989 type(domain2d), intent(in) :: domain
991
992 mpp_domain_is_initialized = domain%initialized
993
994 return
995
996 end function mpp_domain_is_initialized
997
998!#######################################################################
999 !--- private routine used only for mpp_update_domains. This routine will
1000 !--- compare whalo, ehalo, shalo, nhalo with the halo size when defining "domain"
1001 !--- to decide if update is needed. Also it check the sign of whalo, ehalo, shalo and nhalo.
1002 function domain_update_is_needed(domain, whalo, ehalo, shalo, nhalo)
1003 type(domain2d), intent(in) :: domain
1004 integer, intent(in) :: whalo, ehalo, shalo, nhalo
1005 logical :: domain_update_is_needed
1006
1008
1009 if(whalo == 0 .AND. ehalo==0 .AND. shalo == 0 .AND. nhalo==0 ) then
1010 domain_update_is_needed = .false.
1011 if( debug )call mpp_error(note, &
1012 'mpp_domains_util.inc: halo size to be updated are all zero, no update will be done')
1013 return
1014 end if
1015 if( (whalo == -domain%whalo .AND. domain%whalo .NE. 0) .or. &
1016 (ehalo == -domain%ehalo .AND. domain%ehalo .NE. 0) .or. &
1017 (shalo == -domain%shalo .AND. domain%shalo .NE. 0) .or. &
1018 (nhalo == -domain%nhalo .AND. domain%nhalo .NE. 0) ) then
1019 domain_update_is_needed = .false.
1020 call mpp_error(note, 'mpp_domains_util.inc: at least one of w/e/s/n halo size to be updated '// &
1021 'is the inverse of the original halo when defining domain, no update will be done')
1022 return
1023 end if
1024
1025 end function domain_update_is_needed
1026!#######################################################################
1027 !> this routine found the domain has the same halo size with the input
1028 !! whalo, ehalo,
1029 function search_update_overlap(domain, whalo, ehalo, shalo, nhalo, position)
1030 type(domain2d), intent(inout) :: domain
1031 integer, intent(in) :: whalo, ehalo, shalo, nhalo
1032 integer, intent(in) :: position
1033 type(overlapspec), pointer :: search_update_overlap
1034 type(overlapspec), pointer :: update_ref
1035 type(overlapspec), pointer :: check => null()
1036 integer :: ishift, jshift, shift
1037
1038 shift = 0; if(domain%symmetry) shift = 1
1039 select case(position)
1040 case (center)
1041 update_ref => domain%update_T
1042 ishift = 0; jshift = 0
1043 case (corner)
1044 update_ref => domain%update_C
1045 ishift = shift; jshift = shift
1046 case (north)
1047 update_ref => domain%update_N
1048 ishift = 0; jshift = shift
1049 case (east)
1050 update_ref => domain%update_E
1051 ishift = shift; jshift = 0
1052 case default
1053 call mpp_error(fatal,"mpp_domains_util.inc(search_update_overlap): position should be CENTER|CORNER|EAST|NORTH")
1054 end select
1055
1056 search_update_overlap => update_ref
1057
1058 do
1059 if(whalo == search_update_overlap%whalo .AND. ehalo == search_update_overlap%ehalo .AND. &
1060 shalo == search_update_overlap%shalo .AND. nhalo == search_update_overlap%nhalo ) then
1061 exit ! found domain
1062 endif
1063 !--- if not found, switch to next
1064 if(.NOT. ASSOCIATED(search_update_overlap%next)) then
1065 allocate(search_update_overlap%next)
1067 if(domain%fold .NE. 0) then
1068 call compute_overlaps(domain, position, search_update_overlap, check, &
1069 ishift, jshift, 0, 0, whalo, ehalo, shalo, nhalo)
1070 else
1071 call set_overlaps(domain, update_ref, search_update_overlap, whalo, ehalo, shalo, nhalo )
1072 endif
1073 exit
1074 else
1076 end if
1077
1078 end do
1079
1080 update_ref => null()
1081
1082 end function search_update_overlap
1083
1084!#######################################################################
1085 !> this routine finds the check at certain position
1086 function search_check_overlap(domain, position)
1087 type(domain2d), intent(in) :: domain
1088 integer, intent(in) :: position
1089 type(overlapspec), pointer :: search_check_overlap
1090
1091 select case(position)
1092 case (center)
1093 search_check_overlap => null()
1094 case (corner)
1095 search_check_overlap => domain%check_C
1096 case (north)
1097 search_check_overlap => domain%check_N
1098 case (east)
1099 search_check_overlap => domain%check_E
1100 case default
1101 call mpp_error(fatal,"mpp_domains_util.inc(search_check_overlap): position should be CENTER|CORNER|EAST|NORTH")
1102 end select
1103
1104 end function search_check_overlap
1105
1106!#######################################################################
1107 !> This routine finds the bound at certain position
1108 function search_bound_overlap(domain, position)
1109 type(domain2d), intent(in) :: domain
1110 integer, intent(in) :: position
1111 type(overlapspec), pointer :: search_bound_overlap
1112
1113 select case(position)
1114 case (center)
1115 search_bound_overlap => null()
1116 case (corner)
1117 search_bound_overlap => domain%bound_C
1118 case (north)
1119 search_bound_overlap => domain%bound_N
1120 case (east)
1121 search_bound_overlap => domain%bound_E
1122 case default
1123 call mpp_error(fatal,"mpp_domains_util.inc(search_bound_overlap): position should be CENTER|CORNER|EAST|NORTH")
1124 end select
1125
1126 end function search_bound_overlap
1127
1128 !########################################################################
1129 !> Returns the tile_id on current pe
1130 function mpp_get_tile_id(domain)
1131 type(domain2d), intent(in) :: domain
1132 integer, dimension(size(domain%tile_id(:))) :: mpp_get_tile_id
1133
1134 mpp_get_tile_id = domain%tile_id
1135 return
1136
1137 end function mpp_get_tile_id
1138
1139 !#######################################################################
1140 !> Return the tile_id on current pelist. one-tile-per-pe is assumed.
1141 subroutine mpp_get_tile_list(domain, tiles)
1142 type(domain2d), intent(in) :: domain
1143 integer, intent(inout) :: tiles(:)
1144 integer :: i
1145
1146 if( size(tiles(:)).NE.size(domain%list(:)) ) &
1147 call mpp_error( fatal, 'mpp_get_tile_list: tiles array size does not match domain.' )
1148 do i = 1, size(tiles(:))
1149 if(size(domain%list(i-1)%tile_id(:)) > 1) call mpp_error( fatal, &
1150 'mpp_get_tile_list: only support one-tile-per-pe now, contact developer');
1151 tiles(i) = domain%list(i-1)%tile_id(1)
1152 end do
1153
1154 end subroutine mpp_get_tile_list
1155
1156 !########################################################################
1157 !> Returns number of tiles in mosaic
1158 function mpp_get_ntile_count(domain)
1159 type(domain2d), intent(in) :: domain
1160 integer :: mpp_get_ntile_count
1161
1162 mpp_get_ntile_count = domain%ntiles
1163 return
1164
1165 end function mpp_get_ntile_count
1166
1167 !########################################################################
1168 !> Returns number of tile on current pe
1169 function mpp_get_current_ntile(domain)
1170 type(domain2d), intent(in) :: domain
1171 integer :: mpp_get_current_ntile
1172
1173 mpp_get_current_ntile = size(domain%tile_id(:))
1174 return
1175
1176 end function mpp_get_current_ntile
1177
1178 !#######################################################################
1179 !> Returns if current pe is the root pe of the tile, if number of tiles on current pe
1180 !! is greater than 1, will return true, if isc==isg and jsc==jsg also will return true,
1181 !! otherwise false will be returned.
1183 type(domain2d), intent(in) :: domain
1185
1186 mpp_domain_is_tile_root_pe = domain%pe == domain%tile_root_pe;
1187
1188 end function mpp_domain_is_tile_root_pe
1189
1190 !#########################################################################
1191 !> Returns number of processors used on current tile.
1192 function mpp_get_tile_npes(domain)
1193 type(domain2d), intent(in) :: domain
1194 integer :: mpp_get_tile_npes
1195 integer :: i, tile
1196
1197 !--- When there is more than one tile on this pe, we assume each tile will be
1198 !--- limited to this pe.
1199 if(size(domain%tile_id(:)) > 1) then
1201 else
1203 tile = domain%tile_id(1)
1204 do i = 0, size(domain%list(:))-1
1205 if(tile == domain%list(i)%tile_id(1) ) mpp_get_tile_npes = mpp_get_tile_npes + 1
1206 end do
1207 endif
1208
1209 end function mpp_get_tile_npes
1210
1211 !########################################################################
1212 !> Get the processors list used on current tile.
1213 subroutine mpp_get_tile_pelist(domain, pelist)
1214 type(domain2d), intent(in) :: domain
1215 integer, intent(inout) :: pelist(:)
1216 integer :: npes_on_tile
1217 integer :: i, tile, pos
1218
1219 npes_on_tile = mpp_get_tile_npes(domain)
1220 if(size(pelist(:)) .NE. npes_on_tile) call mpp_error(fatal, &
1221 "mpp_domains_util.inc(mpp_get_tile_pelist): size(pelist) does not equal npes on current tile")
1222 tile = domain%tile_id(1)
1223 pos = 0
1224 do i = 0, size(domain%list(:))-1
1225 if(tile == domain%list(i)%tile_id(1)) then
1226 pos = pos+1
1227 pelist(pos) = domain%list(i)%pe
1228 endif
1229 enddo
1230
1231 return
1232
1233 end subroutine mpp_get_tile_pelist
1234
1235!#####################################################################
1236subroutine mpp_get_tile_compute_domains( domain, xbegin, xend, ybegin, yend, position )
1237 type(domain2d), intent(in) :: domain
1238 integer, intent(out), dimension(:) :: xbegin, xend, ybegin, yend
1239 integer, intent(in ), optional :: position
1240
1241 integer :: i, ishift, jshift
1242 integer :: npes_on_tile, pos, tile
1243
1244 call mpp_get_domain_shift( domain, ishift, jshift, position )
1245
1246
1247 if( .NOT.module_is_initialized ) &
1248 call mpp_error( fatal, 'mpp_get_compute_domains2D: must first call mpp_domains_init.' )
1249
1250 npes_on_tile = mpp_get_tile_npes(domain)
1251 if(size(xbegin(:)) .NE. npes_on_tile) call mpp_error(fatal, &
1252 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(xbegin) does not equal npes on current tile")
1253 if(size(xend(:)) .NE. npes_on_tile) call mpp_error(fatal, &
1254 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(xend) does not equal npes on current tile")
1255 if(size(ybegin(:)) .NE. npes_on_tile) call mpp_error(fatal, &
1256 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(ybegin) does not equal npes on current tile")
1257 if(size(yend(:)) .NE. npes_on_tile) call mpp_error(fatal, &
1258 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(yend) does not equal npes on current tile")
1259
1260 tile = domain%tile_id(1)
1261 pos = 0
1262 do i = 0, size(domain%list(:))-1
1263 if(tile == domain%list(i)%tile_id(1)) then
1264 pos = pos+1
1265 xbegin(pos) = domain%list(i)%x(1)%compute%begin
1266 xend(pos) = domain%list(i)%x(1)%compute%end + ishift
1267 ybegin(pos) = domain%list(i)%y(1)%compute%begin
1268 yend(pos) = domain%list(i)%y(1)%compute%end + jshift
1269 endif
1270 enddo
1271
1272 return
1273
1274end subroutine mpp_get_tile_compute_domains
1275
1276
1277
1278 !#############################################################################
1279 function mpp_get_num_overlap(domain, action, p, position)
1280 type(domain2d), intent(in) :: domain
1281 integer, intent(in) :: action
1282 integer, intent(in) :: p
1283 integer, optional, intent(in) :: position
1284 integer :: mpp_get_num_overlap
1285 type(overlapspec), pointer :: update => null()
1286 integer :: pos
1287
1288 pos = center
1289 if(present(position)) pos = position
1290 select case(pos)
1291 case (center)
1292 update => domain%update_T
1293 case (corner)
1294 update => domain%update_C
1295 case (east)
1296 update => domain%update_E
1297 case (north)
1298 update => domain%update_N
1299 case default
1300 call mpp_error( fatal, "mpp_domains_mod(mpp_get_num_overlap): invalid option of position")
1301 end select
1302
1303 if(action == event_send) then
1304 if(p< 1 .OR. p > update%nsend) call mpp_error( fatal, &
1305 "mpp_domains_mod(mpp_get_num_overlap): p should be between 1 and update%nsend")
1306 mpp_get_num_overlap = update%send(p)%count
1307 else if(action == event_recv) then
1308 if(p< 1 .OR. p > update%nrecv) call mpp_error( fatal, &
1309 "mpp_domains_mod(mpp_get_num_overlap): p should be between 1 and update%nrecv")
1310 mpp_get_num_overlap = update%recv(p)%count
1311 else
1312 call mpp_error( fatal, "mpp_domains_mod(mpp_get_num_overlap): invalid option of action")
1313 end if
1314
1315 end function mpp_get_num_overlap
1316
1317 !#############################################################################
1318 subroutine mpp_get_update_size(domain, nsend, nrecv, position)
1319 type(domain2d), intent(in) :: domain
1320 integer, intent(out) :: nsend, nrecv
1321 integer, optional, intent(in) :: position
1322 integer :: pos
1323
1324 pos = center
1325 if(present(position)) pos = position
1326 select case(pos)
1327 case (center)
1328 nsend = domain%update_T%nsend
1329 nrecv = domain%update_T%nrecv
1330 case (corner)
1331 nsend = domain%update_C%nsend
1332 nrecv = domain%update_C%nrecv
1333 case (east)
1334 nsend = domain%update_E%nsend
1335 nrecv = domain%update_E%nrecv
1336 case (north)
1337 nsend = domain%update_N%nsend
1338 nrecv = domain%update_N%nrecv
1339 case default
1340 call mpp_error( fatal, "mpp_domains_mod(mpp_get_update_size): invalid option of position")
1341 end select
1342
1343 end subroutine mpp_get_update_size
1344
1345 !#############################################################################
1346 subroutine mpp_get_update_pelist(domain, action, pelist, position)
1347 type(domain2d), intent(in) :: domain
1348 integer, intent(in) :: action
1349 integer, intent(inout) :: pelist(:)
1350 integer, optional, intent(in) :: position
1351 type(overlapspec), pointer :: update => null()
1352 integer :: pos, p
1353
1354 pos = center
1355 if(present(position)) pos = position
1356 select case(pos)
1357 case (center)
1358 update => domain%update_T
1359 case (corner)
1360 update => domain%update_C
1361 case (east)
1362 update => domain%update_E
1363 case (north)
1364 update => domain%update_N
1365 case default
1366 call mpp_error( fatal, "mpp_domains_mod(mpp_get_update_pelist): invalid option of position")
1367 end select
1368
1369 if(action == event_send) then
1370 if(size(pelist) .NE. update%nsend) call mpp_error( fatal, &
1371 "mpp_domains_mod(mpp_get_update_pelist): size of pelist does not match update%nsend")
1372 do p = 1, update%nsend
1373 pelist(p) = update%send(p)%pe
1374 enddo
1375 else if(action == event_recv) then
1376 if(size(pelist) .NE. update%nrecv) call mpp_error( fatal, &
1377 "mpp_domains_mod(mpp_get_update_pelist): size of pelist does not match update%nrecv")
1378 do p = 1, update%nrecv
1379 pelist(p) = update%recv(p)%pe
1380 enddo
1381 else
1382 call mpp_error( fatal, "mpp_domains_mod(mpp_get_update_pelist): invalid option of action")
1383 end if
1384
1385 end subroutine mpp_get_update_pelist
1386
1387 !#############################################################################
1388 subroutine mpp_get_overlap(domain, action, p, is, ie, js, je, dir, rot, position)
1389 type(domain2d), intent(in) :: domain
1390 integer, intent(in) :: action
1391 integer, intent(in) :: p
1392 integer, dimension(:), intent(out) :: is, ie, js, je
1393 integer, dimension(:), intent(out) :: dir, rot
1394 integer, optional, intent(in) :: position
1395 type(overlapspec), pointer :: update => null()
1396 type(overlap_type), pointer :: overlap => null()
1397 integer :: count, pos
1398
1399 pos = center
1400 if(present(position)) pos = position
1401 select case(pos)
1402 case (center)
1403 update => domain%update_T
1404 case (corner)
1405 update => domain%update_C
1406 case (east)
1407 update => domain%update_E
1408 case (north)
1409 update => domain%update_N
1410 case default
1411 call mpp_error( fatal, "mpp_domains_mod(mpp_get_overlap): invalid option of position")
1412 end select
1413
1414 if(action == event_send) then
1415 overlap => update%send(p)
1416 else if(action == event_recv) then
1417 overlap => update%recv(p)
1418 else
1419 call mpp_error( fatal, "mpp_domains_mod(mpp_get_overlap): invalid option of action")
1420 end if
1421
1422 count = overlap%count
1423 if(size(is(:)) .NE. count .OR. size(ie(:)) .NE. count .OR. size(js(:)) .NE. count .OR. &
1424 size(je(:)) .NE. count .OR. size(dir(:)) .NE. count .OR. size(rot(:)) .NE. count ) &
1425 call mpp_error( fatal, &
1426 & "mpp_domains_mod(mpp_get_overlap): size mismatch between number of overlap and array size")
1427
1428 is = overlap%is (1:count)
1429 ie = overlap%ie (1:count)
1430 js = overlap%js (1:count)
1431 je = overlap%je (1:count)
1432 dir = overlap%dir (1:count)
1433 rot = overlap%rotation(1:count)
1434
1435 update => null()
1436 overlap => null()
1437
1438 end subroutine mpp_get_overlap
1439
1440 !##################################################################
1441 function mpp_get_domain_name(domain)
1442 type(domain2d), intent(in) :: domain
1443 character(len=NAME_LENGTH) :: mpp_get_domain_name
1444
1445 mpp_get_domain_name = domain%name
1446
1447 end function mpp_get_domain_name
1448
1449 !#################################################################
1450 function mpp_get_domain_root_pe(domain)
1451 type(domain2d), intent(in) :: domain
1452 integer :: mpp_get_domain_root_pe
1453
1454 mpp_get_domain_root_pe = domain%list(0)%pe
1455
1456 end function mpp_get_domain_root_pe
1457 !#################################################################
1458 function mpp_get_domain_npes(domain)
1459 type(domain2d), intent(in) :: domain
1460 integer :: mpp_get_domain_npes
1461
1462 mpp_get_domain_npes = size(domain%list(:))
1463
1464 return
1465
1466 end function mpp_get_domain_npes
1467
1468 !################################################################
1469 subroutine mpp_get_domain_pelist(domain, pelist)
1470 type(domain2d), intent(in) :: domain
1471 integer, intent(out) :: pelist(:)
1472 integer :: p
1473
1474 if(size(pelist(:)) .NE. size(domain%list(:)) ) then
1475 call mpp_error(fatal, .NE."mpp_get_domain_pelist: size(pelist(:)) size(domain%list(:)) ")
1476 endif
1477
1478 do p = 0, size(domain%list(:))-1
1479 pelist(p+1) = domain%list(p)%pe
1480 enddo
1481
1482 return
1483
1484 end subroutine mpp_get_domain_pelist
1485
1486 !#################################################################
1488 type(domain2d), intent(in) :: domain
1489 integer, dimension(2) :: mpp_get_io_domain_layout
1490
1491 mpp_get_io_domain_layout = domain%io_layout
1492
1493 end function mpp_get_io_domain_layout
1494
1495 !################################################################
1496 function get_rank_send(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1497 type(domain2d), intent(in) :: domain
1498 type(overlapspec), intent(in) :: overlap_x, overlap_y
1499 integer, intent(out) :: rank_x, rank_y, ind_x, ind_y
1500 integer :: get_rank_send
1501 integer :: nlist, nsend_x, nsend_y
1502
1503 nlist = size(domain%list(:))
1504 nsend_x = overlap_x%nsend
1505 nsend_y = overlap_y%nsend
1506 rank_x = nlist+1
1507 rank_y = nlist+1
1508 if(nsend_x>0) rank_x = overlap_x%send(1)%pe - domain%pe
1509 if(nsend_y>0) rank_y = overlap_y%send(1)%pe - domain%pe
1510 if(rank_x .LT. 0) rank_x = rank_x + nlist
1511 if(rank_y .LT. 0) rank_y = rank_y + nlist
1512 get_rank_send = min(rank_x, rank_y)
1513 ind_x = nsend_x + 1
1514 ind_y = nsend_y + 1
1515 if(get_rank_send < nlist+1) then
1516 if(nsend_x>0) ind_x = 1
1517 if(nsend_y>0) ind_y = 1
1518 endif
1519
1520 end function get_rank_send
1521
1522 !############################################################################
1523 function get_rank_recv(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1524 type(domain2d), intent(in) :: domain
1525 type(overlapspec), intent(in) :: overlap_x, overlap_y
1526 integer, intent(out) :: rank_x, rank_y, ind_x, ind_y
1527 integer :: get_rank_recv
1528 integer :: nlist, nrecv_x, nrecv_y
1529
1530 nlist = size(domain%list(:))
1531 nrecv_x = overlap_x%nrecv
1532 nrecv_y = overlap_y%nrecv
1533 rank_x = -1
1534 rank_y = -1
1535 if(nrecv_x>0) then
1536 rank_x = overlap_x%recv(1)%pe - domain%pe
1537 if(rank_x .LE. 0) rank_x = rank_x + nlist
1538 endif
1539 if(nrecv_y>0) then
1540 rank_y = overlap_y%recv(1)%pe - domain%pe
1541 if(rank_y .LE. 0) rank_y = rank_y + nlist
1542 endif
1543 get_rank_recv = max(rank_x, rank_y)
1544 ind_x = nrecv_x + 1
1545 ind_y = nrecv_y + 1
1546 if(get_rank_recv < nlist+1) then
1547 if(nrecv_x>0) ind_x = 1
1548 if(nrecv_y>0) ind_y = 1
1549 endif
1550
1551 end function get_rank_recv
1552
1553 function get_vector_recv(domain, update_x, update_y, ind_x, ind_y, start_pos, pelist)
1554 type(domain2d), intent(in) :: domain
1555 type(overlapspec), intent(in) :: update_x, update_y
1556 integer, intent(out) :: ind_x(:), ind_y(:)
1557 integer, intent(out) :: start_pos(:)
1558 integer, intent(out) :: pelist(:)
1559 integer :: nlist, nrecv_x, nrecv_y, ntot, n
1560 integer :: ix, iy, rank_x, rank_y, cur_pos
1561 integer :: get_vector_recv
1562
1563 nlist = size(domain%list(:))
1564 nrecv_x = update_x%nrecv
1565 nrecv_y = update_y%nrecv
1566
1567 ntot = nrecv_x + nrecv_y
1568
1569 n = 1
1570 ix = 1
1571 iy = 1
1572 ind_x = -1
1573 ind_y = -1
1574 get_vector_recv = 0
1575 cur_pos = 0
1576 do while (n<=ntot)
1577 if(ix <= nrecv_x ) then
1578 rank_x = update_x%recv(ix)%pe-domain%pe
1579 if(rank_x .LE. 0) rank_x = rank_x + nlist
1580 else
1581 rank_x = -1
1582 endif
1583 if(iy <= nrecv_y ) then
1584 rank_y = update_y%recv(iy)%pe-domain%pe
1585 if(rank_y .LE. 0) rank_y = rank_y + nlist
1586 else
1587 rank_y = -1
1588 endif
1590 start_pos(get_vector_recv) = cur_pos
1591 if( rank_x == rank_y ) then
1592 n = n+2
1593 ind_x(get_vector_recv) = ix
1594 ind_y(get_vector_recv) = iy
1595 cur_pos = cur_pos + update_x%recv(ix)%totsize + update_y%recv(iy)%totsize
1596 pelist(get_vector_recv) = update_x%recv(ix)%pe
1597 ix = ix + 1
1598 iy = iy + 1
1599 else if ( rank_x > rank_y ) then
1600 n = n+1
1601 ind_x(get_vector_recv) = ix
1602 ind_y(get_vector_recv) = -1
1603 cur_pos = cur_pos + update_x%recv(ix)%totsize
1604 pelist(get_vector_recv) = update_x%recv(ix)%pe
1605 ix = ix + 1
1606 else if ( rank_y > rank_x ) then
1607 n = n+1
1608 ind_x(get_vector_recv) = -1
1609 ind_y(get_vector_recv) = iy
1610 cur_pos = cur_pos + update_y%recv(iy)%totsize
1611 pelist(get_vector_recv) = update_y%recv(iy)%pe
1612 iy = iy+1
1613 endif
1614 end do
1615
1616
1617 end function get_vector_recv
1618
1619 function get_vector_send(domain, update_x, update_y, ind_x, ind_y, start_pos, pelist)
1620 type(domain2d), intent(in) :: domain
1621 type(overlapspec), intent(in) :: update_x, update_y
1622 integer, intent(out) :: ind_x(:), ind_y(:)
1623 integer, intent(out) :: start_pos(:)
1624 integer, intent(out) :: pelist(:)
1625 integer :: nlist, nsend_x, nsend_y, ntot, n
1626 integer :: ix, iy, rank_x, rank_y, cur_pos
1627 integer :: get_vector_send
1628
1629 nlist = size(domain%list(:))
1630 nsend_x = update_x%nsend
1631 nsend_y = update_y%nsend
1632
1633 ntot = nsend_x + nsend_y
1634 n = 1
1635 ix = 1
1636 iy = 1
1637 ind_x = -1
1638 ind_y = -1
1639 get_vector_send = 0
1640 cur_pos = 0
1641 do while (n<=ntot)
1642 if(ix <= nsend_x ) then
1643 rank_x = update_x%send(ix)%pe-domain%pe
1644 if(rank_x .LT. 0) rank_x = rank_x + nlist
1645 else
1646 rank_x = nlist+1
1647 endif
1648 if(iy <= nsend_y ) then
1649 rank_y = update_y%send(iy)%pe-domain%pe
1650 if(rank_y .LT. 0) rank_y = rank_y + nlist
1651 else
1652 rank_y = nlist+1
1653 endif
1655 start_pos(get_vector_send) = cur_pos
1656
1657 if( rank_x == rank_y ) then
1658 n = n+2
1659 ind_x(get_vector_send) = ix
1660 ind_y(get_vector_send) = iy
1661 cur_pos = cur_pos + update_x%send(ix)%totsize + update_y%send(iy)%totsize
1662 pelist(get_vector_send) = update_x%send(ix)%pe
1663 ix = ix + 1
1664 iy = iy + 1
1665 else if ( rank_x < rank_y ) then
1666 n = n+1
1667 ind_x(get_vector_send) = ix
1668 ind_y(get_vector_send) = -1
1669 cur_pos = cur_pos + update_x%send(ix)%totsize
1670 pelist(get_vector_send) = update_x%send(ix)%pe
1671 ix = ix + 1
1672 else if ( rank_y < rank_x ) then
1673 n = n+1
1674 ind_x(get_vector_send) = -1
1675 ind_y(get_vector_send) = iy
1676 cur_pos = cur_pos + update_y%send(iy)%totsize
1677 pelist(get_vector_send) = update_y%send(iy)%pe
1678 iy = iy+1
1679 endif
1680 end do
1681
1682
1683 end function get_vector_send
1684
1685
1686 !############################################################################
1687 function get_rank_unpack(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1688 type(domain2d), intent(in) :: domain
1689 type(overlapspec), intent(in) :: overlap_x, overlap_y
1690 integer, intent(out) :: rank_x, rank_y, ind_x, ind_y
1691 integer :: get_rank_unpack
1692 integer :: nlist, nrecv_x, nrecv_y
1693
1694 nlist = size(domain%list(:))
1695 nrecv_x = overlap_x%nrecv
1696 nrecv_y = overlap_y%nrecv
1697
1698 rank_x = nlist+1
1699 rank_y = nlist+1
1700 if(nrecv_x>0) rank_x = overlap_x%recv(nrecv_x)%pe - domain%pe
1701 if(nrecv_y>0) rank_y = overlap_y%recv(nrecv_y)%pe - domain%pe
1702 if(rank_x .LE.0) rank_x = rank_x + nlist
1703 if(rank_y .LE.0) rank_y = rank_y + nlist
1704
1705 get_rank_unpack = min(rank_x, rank_y)
1706 ind_x = 0
1707 ind_y = 0
1708 if(get_rank_unpack < nlist+1) then
1709 if(nrecv_x >0) ind_x = nrecv_x
1710 if(nrecv_y >0) ind_y = nrecv_y
1711 endif
1712
1713 end function get_rank_unpack
1714
1715 function get_mesgsize(overlap, do_dir)
1716 type(overlap_type), intent(in) :: overlap
1717 logical, intent(in) :: do_dir(:)
1718 integer :: get_mesgsize
1719 integer :: n, dir
1720
1721 get_mesgsize = 0
1722 do n = 1, overlap%count
1723 dir = overlap%dir(n)
1724 if(do_dir(dir)) then
1725 get_mesgsize = get_mesgsize + overlap%msgsize(n)
1726 end if
1727 end do
1728
1729 end function get_mesgsize
1730
1731 !#############################################################################
1732 subroutine mpp_set_domain_symmetry(domain, symmetry)
1733 type(domain2d), intent(inout) :: domain
1734 logical, intent(in ) :: symmetry
1735
1736 domain%symmetry = symmetry
1737
1738 end subroutine mpp_set_domain_symmetry
1739
1740 !> @brief Copies input 1d domain to the output 1d domain
1741 recursive subroutine mpp_copy_domain1d(domain_in, domain_out)
1742 type(domain1d), intent(in) :: domain_in !< Input domain
1743 type(domain1d), intent(inout) :: domain_out !< Output domain
1744
1745 integer :: i !< For loop
1746 integer :: starting !< Starting bounds
1747 integer :: ending !< Ending bounds
1748
1749 domain_out%compute = domain_in%compute
1750 domain_out%domain_data = domain_in%domain_data
1751 domain_out%global = domain_in%global
1752 domain_out%memory = domain_in%memory
1753 domain_out%cyclic = domain_in%cyclic
1754 domain_out%pe = domain_in%pe
1755 domain_out%pos = domain_in%pos
1756
1757 if (associated(domain_in%list)) then
1758 starting = lbound(domain_in%list, 1)
1759 ending = ubound(domain_in%list, 1)
1760 if (associated(domain_out%list)) deallocate(domain_out%list) !< Check if allocated
1761 allocate(domain_out%list(starting:ending))
1762
1763 do i = starting, ending
1764 call mpp_copy_domain1d(domain_in%list(i), domain_out%list(i))
1765 enddo
1766
1767 endif
1768
1769 end subroutine mpp_copy_domain1d
1770
1771 !#################################################################
1772 !> @brief Copies input 2d domain to the output 2d domain
1773 subroutine mpp_copy_domain2d(domain_in, domain_out)
1774 type(domain2d), intent(in) :: domain_in !< Input domain
1775 type(domain2d), intent(inout) :: domain_out !< Output domain
1776
1777 integer :: n,i !< For loops
1778 integer :: ntiles !< Number of tiles
1779 integer :: starting(2) !< Starting bounds
1780 integer :: ending(2) !< Ending bounds
1781
1782 if (associated(domain_out%x)) then
1783 call mpp_error(fatal, "mpp_copy_domain: domain_out is already set")
1784 endif
1785
1786 domain_out%id = domain_in%id
1787 domain_out%pe = domain_in%pe
1788 domain_out%fold = domain_in%fold
1789 domain_out%pos = domain_in%pos
1790 domain_out%symmetry = domain_in%symmetry
1791 domain_out%whalo = domain_in%whalo
1792 domain_out%ehalo = domain_in%ehalo
1793 domain_out%shalo = domain_in%shalo
1794 domain_out%nhalo = domain_in%nhalo
1795 domain_out%ntiles = domain_in%ntiles
1796 domain_out%max_ntile_pe = domain_in%max_ntile_pe
1797 domain_out%ncontacts = domain_in%ncontacts
1798 domain_out%rotated_ninety = domain_in%rotated_ninety
1799 domain_out%initialized = domain_in%initialized
1800 domain_out%tile_root_pe = domain_in%tile_root_pe
1801 domain_out%io_layout = domain_in%io_layout
1802 domain_out%name = domain_in%name
1803
1804 ntiles = size(domain_in%x(:))
1805 allocate(domain_out%x(ntiles), domain_out%y(ntiles), domain_out%tile_id(ntiles) )
1806 do n = 1, ntiles
1807 call mpp_copy_domain1d(domain_in%x(n), domain_out%x(n))
1808 call mpp_copy_domain1d(domain_in%y(n), domain_out%y(n))
1809 enddo
1810
1811 if (associated(domain_in%pearray)) then
1812 starting = lbound(domain_in%pearray)
1813 ending = ubound(domain_in%pearray)
1814
1815 allocate(domain_out%pearray(starting(1):ending(1), starting(2):ending(2)))
1816 domain_out%pearray=domain_in%pearray
1817 endif
1818
1819 if (associated(domain_in%tile_id)) then
1820 starting(1) = lbound(domain_in%tile_id,1)
1821 ending(1) = ubound(domain_in%tile_id,1)
1822
1823 allocate(domain_out%tile_id(starting(1):ending(1)))
1824 domain_out%tile_id = domain_in%tile_id
1825 endif
1826
1827 if (associated(domain_in%tile_id_all)) then
1828 starting(1) = lbound(domain_in%tile_id_all,1)
1829 ending(1) = ubound(domain_in%tile_id_all,1)
1830
1831 allocate(domain_out%tile_id_all(starting(1):ending(1)))
1832 domain_out%tile_id_all = domain_in%tile_id_all
1833 endif
1834
1835 if (associated(domain_in%list)) then
1836 starting(1) = lbound(domain_in%list,1)
1837 ending(1) = ubound(domain_in%list,1)
1838
1839 allocate(domain_out%list(starting(1):ending(1)))
1840 do i = starting(1), ending(1)
1841 call mpp_copy_domain2d_spec(domain_in%list(i),domain_out%list(i))
1842 enddo
1843 endif
1844
1845 return
1846
1847 end subroutine mpp_copy_domain2d
1848
1849 !> @brief Copies input 2d domain spec to the output 2d domain spec
1850 subroutine mpp_copy_domain2d_spec(domain2D_spec_in, domain2d_spec_out)
1851 type(domain2d_spec), intent(in) :: domain2D_spec_in !< Input
1852 type(domain2d_spec), intent(out) :: domain2D_spec_out !< Output
1853
1854 integer :: starting !< Starting bounds
1855 integer :: ending !< Ending bounds
1856 integer :: i !< For loop
1857
1858 domain2d_spec_out%pe = domain2d_spec_in%pe
1859 domain2d_spec_out%pos = domain2d_spec_in%pos
1860 domain2d_spec_out%tile_root_pe = domain2d_spec_in%tile_root_pe
1861
1862 if (associated(domain2d_spec_in%tile_id)) then
1863 starting = lbound(domain2d_spec_in%tile_id,1)
1864 ending = ubound(domain2d_spec_in%tile_id,1)
1865
1866 if (associated(domain2d_spec_out%tile_id)) deallocate(domain2d_spec_out%tile_id) !< Check if allocated
1867 allocate(domain2d_spec_out%tile_id(starting:ending))
1868 domain2d_spec_out%tile_id = domain2d_spec_in%tile_id
1869 endif
1870
1871 if (associated(domain2d_spec_in%x)) then
1872 starting = lbound(domain2d_spec_in%x,1)
1873 ending = ubound(domain2d_spec_in%x,1)
1874
1875 if (associated(domain2d_spec_out%x)) deallocate(domain2d_spec_out%x) !< Check if allocated
1876 allocate(domain2d_spec_out%x(starting:ending))
1877 do i = starting, ending
1878 call mpp_copy_domain1d_spec(domain2d_spec_in%x(i), domain2d_spec_out%x(i))
1879 enddo
1880 endif
1881
1882 if (associated(domain2d_spec_in%y)) then
1883 starting = lbound(domain2d_spec_in%y,1)
1884 ending = ubound(domain2d_spec_in%y,1)
1885
1886 if (associated(domain2d_spec_out%y)) deallocate(domain2d_spec_out%y) !< Check if allocated
1887 allocate(domain2d_spec_out%y(starting:ending))
1888 do i = starting, ending
1889 call mpp_copy_domain1d_spec(domain2d_spec_in%y(i), domain2d_spec_out%y(i))
1890 enddo
1891 endif
1892
1893 end subroutine mpp_copy_domain2d_spec
1894
1895 !> @brief Copies input 1d domain spec to the output 1d domain spec
1896 subroutine mpp_copy_domain1d_spec(domain1D_spec_in, domain1D_spec_out)
1897 type(domain1d_spec), intent(in) :: domain1D_spec_in !< Input
1898 type(domain1d_spec), intent(out) :: domain1D_spec_out !< Output
1899
1900 domain1d_spec_out%pos = domain1d_spec_in%pos
1901
1902 call mpp_copy_domain_axis_spec(domain1d_spec_in%compute, domain1d_spec_out%compute)
1903 call mpp_copy_domain_axis_spec(domain1d_spec_in%global, domain1d_spec_out%global)
1904 end subroutine mpp_copy_domain1d_spec
1905
1906 !> @brief Copies input domain_axis_spec to the output domain_axis_spec
1907 subroutine mpp_copy_domain_axis_spec(domain_axis_spec_in, domain_axis_spec_out)
1908 type(domain_axis_spec), intent(in) :: domain_axis_spec_in !< Input
1909 type(domain_axis_spec), intent(out) :: domain_axis_spec_out !< Output
1910
1911 domain_axis_spec_out%begin = domain_axis_spec_in%begin
1912 domain_axis_spec_out%end = domain_axis_spec_in%end
1913 domain_axis_spec_out%size = domain_axis_spec_in%size
1914 domain_axis_spec_out%max_size = domain_axis_spec_in%max_size
1915 domain_axis_spec_out%is_global = domain_axis_spec_in%is_global
1916 end subroutine mpp_copy_domain_axis_spec
1917
1918 !######################################################################
1919 subroutine set_group_update(group, domain)
1920 type(mpp_group_update_type), intent(inout) :: group
1921 type(domain2d), intent(inout) :: domain
1922 integer :: nscalar, nvector, nlist
1923 integer :: nsend, nrecv, nsend_old, nrecv_old
1924 integer :: nsend_s, nsend_x, nsend_y
1925 integer :: nrecv_s, nrecv_x, nrecv_y
1926 integer :: update_buffer_pos, tot_recv_size, tot_send_size
1927 integer :: msgsize_s, msgsize_x, msgsize_y, msgsize
1928 logical :: recv_s(8), send_s(8)
1929 logical :: recv_x(8), send_x(8), recv_y(8), send_y(8)
1930 integer :: ntot, n, l, m, ksize
1931 integer :: i_s, i_x, i_y, rank_s, rank_x, rank_y, rank
1932 integer :: ind_s(3*MAXOVERLAP)
1933 integer :: ind_x(3*MAXOVERLAP)
1934 integer :: ind_y(3*MAXOVERLAP)
1935 integer :: pelist(3*MAXOVERLAP)
1936 integer :: send_size(3*MAXOVERLAP)
1937 integer :: position_x, position_y, npack, nunpack, dir
1938 integer :: pack_buffer_pos, unpack_buffer_pos
1939 integer :: omp_get_num_threads, nthreads
1940 character(len=8) :: text
1941 type(overlap_type), pointer :: overPtr => null()
1942 type(overlapspec), pointer :: update_s => null()
1943 type(overlapspec), pointer :: update_x => null()
1944 type(overlapspec), pointer :: update_y => null()
1945
1946 nscalar = group%nscalar
1947 nvector = group%nvector
1948
1949 !--- get the overlap data type
1950 select case(group%gridtype)
1951 case (agrid)
1952 position_x = center
1953 position_y = center
1954 case (bgrid_ne, bgrid_sw)
1955 position_x = corner
1956 position_y = corner
1957 case (cgrid_ne, cgrid_sw)
1958 position_x = east
1959 position_y = north
1960 case (dgrid_ne, dgrid_sw)
1961 position_x = north
1962 position_y = east
1963 case default
1964 call mpp_error(fatal, "set_group_update: invalid value of gridtype")
1965 end select
1966 if(nscalar>0) then
1967 update_s => search_update_overlap(domain, group%whalo_s, group%ehalo_s, &
1968 group%shalo_s, group%nhalo_s, group%position)
1969 endif
1970 if(nvector>0) then
1971 update_x => search_update_overlap(domain, group%whalo_v, group%ehalo_v, &
1972 group%shalo_v, group%nhalo_v, position_x)
1973 update_y => search_update_overlap(domain, group%whalo_v, group%ehalo_v, &
1974 group%shalo_v, group%nhalo_v, position_y)
1975 endif
1976
1977 if(nscalar > 0) then
1978 recv_s = group%recv_s
1979 send_s = recv_s
1980 endif
1981 if(nvector > 0) then
1982 recv_x = group%recv_x
1983 send_x = recv_x
1984 recv_y = group%recv_y
1985 send_y = recv_y
1986 end if
1987 nlist = size(domain%list(:))
1988 group%initialized = .true.
1989 nsend_s = 0; nsend_x = 0; nsend_y = 0
1990 nrecv_s = 0; nrecv_x = 0; nrecv_y = 0
1991
1992 if(nscalar > 0) then
1993 !--- This check could not be done because of memory domain
1994! if( group%isize_s .NE. (group%ie_s-group%is_s+1) .OR. group%jsize_s .NE. (group%je_s-group%js_s+1)) &
1995! call mpp_error(FATAL, "set_group_update: mismatch of size of the field and domain memory domain")
1996 nsend_s = update_s%nsend
1997 nrecv_s = update_s%nrecv
1998 endif
1999
2000 !--- ksize_s must equal ksize_v
2001 if(nvector > 0 .AND. nscalar > 0) then
2002 if(group%ksize_s .NE. group%ksize_v) then
2003 call mpp_error(fatal, "set_group_update: ksize_s and ksize_v are not equal")
2004 endif
2005 ksize = group%ksize_s
2006 else if (nscalar > 0) then
2007 ksize = group%ksize_s
2008 else if (nvector > 0) then
2009 ksize = group%ksize_v
2010 else
2011 call mpp_error(fatal, "set_group_update: nscalar and nvector are all 0")
2012 endif
2013
2014 nthreads = 1
2015!$OMP PARALLEL
2016!$ nthreads = omp_get_num_threads()
2017!$OMP END PARALLEL
2018 if( nthreads > nthread_control_loop ) then
2019 group%k_loop_inside = .false.
2020 else
2021 group%k_loop_inside = .true.
2022 endif
2023
2024 if(nvector > 0) then
2025 !--- This check could not be done because of memory domain
2026! if( group%isize_x .NE. (group%ie_x-group%is_x+1) .OR. group%jsize_x .NE. (group%je_x-group%js_x+1)) &
2027! call mpp_error(FATAL, "set_group_update: mismatch of size of the fieldx and domain memory domain")
2028! if( group%isize_y .NE. (group%ie_y-group%is_y+1) .OR. group%jsize_y .NE. (group%je_y-group%js_y+1)) &
2029! call mpp_error(FATAL, "set_group_update: mismatch of size of the fieldy and domain memory domain")
2030 nsend_x = update_x%nsend
2031 nrecv_x = update_x%nrecv
2032 nsend_y = update_y%nsend
2033 nrecv_y = update_y%nrecv
2034 endif
2035
2036 !figure out message size for each processor.
2037 ntot = nrecv_s + nrecv_x + nrecv_y
2038 if(ntot > 3*maxoverlap) call mpp_error(fatal, "set_group_update: ntot is greater than 3*MAXOVERLAP")
2039 n = 1
2040 i_s = 1
2041 i_x = 1
2042 i_y = 1
2043 ind_s = -1
2044 ind_x = -1
2045 ind_y = -1
2046 nrecv = 0
2047 do while(n<=ntot)
2048 if( i_s <= nrecv_s ) then
2049 rank_s = update_s%recv(i_s)%pe-domain%pe
2050 if(rank_s .LE. 0) rank_s = rank_s + nlist
2051 else
2052 rank_s = -1
2053 endif
2054 if( i_x <= nrecv_x ) then
2055 rank_x = update_x%recv(i_x)%pe-domain%pe
2056 if(rank_x .LE. 0) rank_x = rank_x + nlist
2057 else
2058 rank_x = -1
2059 endif
2060 if( i_y <= nrecv_y ) then
2061 rank_y = update_y%recv(i_y)%pe-domain%pe
2062 if(rank_y .LE. 0) rank_y = rank_y + nlist
2063 else
2064 rank_y = -1
2065 endif
2066 nrecv = nrecv + 1
2067 rank = maxval((/rank_s, rank_x, rank_y/))
2068 if(rank == rank_s) then
2069 n = n + 1
2070 ind_s(nrecv) = i_s
2071 pelist(nrecv) = update_s%recv(i_s)%pe
2072 i_s = i_s + 1
2073 endif
2074 if(rank == rank_x) then
2075 n = n + 1
2076 ind_x(nrecv) = i_x
2077 pelist(nrecv) = update_x%recv(i_x)%pe
2078 i_x = i_x + 1
2079 endif
2080 if(rank == rank_y) then
2081 n = n + 1
2082 ind_y(nrecv) = i_y
2083 pelist(nrecv) = update_y%recv(i_y)%pe
2084 i_y = i_y + 1
2085 endif
2086 enddo
2087
2088 nrecv_old = nrecv
2089 nrecv = 0
2090 update_buffer_pos = 0
2091 tot_recv_size = 0
2092
2093 !--- setup for recv
2094 do l = 1, nrecv_old
2095 msgsize_s = 0
2096 msgsize_x = 0
2097 msgsize_y = 0
2098 m = ind_s(l)
2099 if(m>0) msgsize_s = get_mesgsize(update_s%recv(m), recv_s)*ksize*nscalar
2100 m = ind_x(l)
2101 if(m>0) msgsize_x = get_mesgsize(update_x%recv(m), recv_x)*ksize*nvector
2102 m = ind_y(l)
2103 if(m>0) msgsize_y = get_mesgsize(update_y%recv(m), recv_y)*ksize*nvector
2104 msgsize = msgsize_s + msgsize_x + msgsize_y
2105 if( msgsize.GT.0 )then
2106 tot_recv_size = tot_recv_size + msgsize
2107 nrecv = nrecv + 1
2108 if(nrecv > maxoverlap) then
2109 call mpp_error(fatal, "set_group_update: nrecv is greater than MAXOVERLAP, increase MAXOVERLAP")
2110 endif
2111 group%from_pe(nrecv) = pelist(l)
2112 group%recv_size(nrecv) = msgsize
2113 group%buffer_pos_recv(nrecv) = update_buffer_pos
2114 update_buffer_pos = update_buffer_pos + msgsize
2115 end if
2116 end do
2117 group%nrecv = nrecv
2118
2119 !--- setup for unpack
2120 nunpack = 0
2121 unpack_buffer_pos = 0
2122 do l = 1, nrecv_old
2123 m = ind_s(l)
2124 if(m>0) then
2125 overptr => update_s%recv(m)
2126 do n = 1, overptr%count
2127 dir = overptr%dir(n)
2128 if(recv_s(dir)) then
2129 nunpack = nunpack + 1
2130 if(nunpack > maxoverlap) call mpp_error(fatal, &
2131 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 1")
2132 group%unpack_type(nunpack) = field_s
2133 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2134 group%unpack_rotation(nunpack) = overptr%rotation(n)
2135 group%unpack_is(nunpack) = overptr%is(n)
2136 group%unpack_ie(nunpack) = overptr%ie(n)
2137 group%unpack_js(nunpack) = overptr%js(n)
2138 group%unpack_je(nunpack) = overptr%je(n)
2139 group%unpack_size(nunpack) = overptr%msgsize(n)*nscalar
2140 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2141 end if
2142 end do
2143 end if
2144
2145 m = ind_x(l)
2146 if(m>0) then
2147 overptr => update_x%recv(m)
2148 do n = 1, overptr%count
2149 dir = overptr%dir(n)
2150 if(recv_x(dir)) then
2151 nunpack = nunpack + 1
2152 if(nunpack > maxoverlap) call mpp_error(fatal, &
2153 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 2")
2154 group%unpack_type(nunpack) = field_x
2155 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2156 group%unpack_rotation(nunpack) = overptr%rotation(n)
2157 group%unpack_is(nunpack) = overptr%is(n)
2158 group%unpack_ie(nunpack) = overptr%ie(n)
2159 group%unpack_js(nunpack) = overptr%js(n)
2160 group%unpack_je(nunpack) = overptr%je(n)
2161 group%unpack_size(nunpack) = overptr%msgsize(n)*nvector
2162 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2163 end if
2164 end do
2165 end if
2166
2167 m = ind_y(l)
2168 if(m>0) then
2169 overptr => update_y%recv(m)
2170 do n = 1, overptr%count
2171 dir = overptr%dir(n)
2172 if(recv_y(dir)) then
2173 nunpack = nunpack + 1
2174 if(nunpack > maxoverlap) call mpp_error(fatal, &
2175 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 3")
2176 group%unpack_type(nunpack) = field_y
2177 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2178 group%unpack_rotation(nunpack) = overptr%rotation(n)
2179 group%unpack_is(nunpack) = overptr%is(n)
2180 group%unpack_ie(nunpack) = overptr%ie(n)
2181 group%unpack_js(nunpack) = overptr%js(n)
2182 group%unpack_je(nunpack) = overptr%je(n)
2183 group%unpack_size(nunpack) = overptr%msgsize(n)*nvector
2184 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2185 end if
2186 end do
2187 end if
2188 end do
2189 group%nunpack = nunpack
2190
2191 if(update_buffer_pos .NE. unpack_buffer_pos ) call mpp_error(fatal, &
2192 .NE."set_group_update: update_buffer_pos unpack_buffer_pos")
2193
2194 !figure out message size for each processor.
2195 ntot = nsend_s + nsend_x + nsend_y
2196 n = 1
2197 i_s = 1
2198 i_x = 1
2199 i_y = 1
2200 ind_s = -1
2201 ind_x = -1
2202 ind_y = -1
2203 nsend = 0
2204 do while(n<=ntot)
2205 if( i_s <= nsend_s ) then
2206 rank_s = update_s%send(i_s)%pe-domain%pe
2207 if(rank_s .LT. 0) rank_s = rank_s + nlist
2208 else
2209 rank_s = nlist+1
2210 endif
2211 if( i_x <= nsend_x ) then
2212 rank_x = update_x%send(i_x)%pe-domain%pe
2213 if(rank_x .LT. 0) rank_x = rank_x + nlist
2214 else
2215 rank_x = nlist+1
2216 endif
2217 if( i_y <= nsend_y ) then
2218 rank_y = update_y%send(i_y)%pe-domain%pe
2219 if(rank_y .LT. 0) rank_y = rank_y + nlist
2220 else
2221 rank_y = nlist+1
2222 endif
2223 nsend = nsend + 1
2224 rank = minval((/rank_s, rank_x, rank_y/))
2225 if(rank == rank_s) then
2226 n = n + 1
2227 ind_s(nsend) = i_s
2228 pelist(nsend) = update_s%send(i_s)%pe
2229 i_s = i_s + 1
2230 endif
2231 if(rank == rank_x) then
2232 n = n + 1
2233 ind_x(nsend) = i_x
2234 pelist(nsend) = update_x%send(i_x)%pe
2235 i_x = i_x + 1
2236 endif
2237 if(rank == rank_y) then
2238 n = n + 1
2239 ind_y(nsend) = i_y
2240 pelist(nsend) = update_y%send(i_y)%pe
2241 i_y = i_y + 1
2242 endif
2243 enddo
2244
2245 nsend_old = nsend
2246 nsend = 0
2247 tot_send_size = 0
2248 do l = 1, nsend_old
2249 msgsize_s = 0
2250 msgsize_x = 0
2251 msgsize_y = 0
2252 m = ind_s(l)
2253 if(m>0) msgsize_s = get_mesgsize(update_s%send(m), send_s)*ksize*nscalar
2254 m = ind_x(l)
2255 if(m>0) msgsize_x = get_mesgsize(update_x%send(m), send_x)*ksize*nvector
2256 m = ind_y(l)
2257 if(m>0) msgsize_y = get_mesgsize(update_y%send(m), send_y)*ksize*nvector
2258 msgsize = msgsize_s + msgsize_x + msgsize_y
2259 if( msgsize.GT.0 )then
2260 tot_send_size = tot_send_size + msgsize
2261 nsend = nsend + 1
2262 if(nsend > maxoverlap) then
2263 call mpp_error(fatal, "set_group_update: nsend is greater than MAXOVERLAP, increase MAXOVERLAP")
2264 endif
2265 send_size(nsend) = msgsize
2266 group%to_pe(nsend) = pelist(l)
2267 group%buffer_pos_send(nsend) = update_buffer_pos
2268 group%send_size(nsend) = msgsize
2269 update_buffer_pos = update_buffer_pos + msgsize
2270 end if
2271 end do
2272 group%nsend = nsend
2273
2274 !--- setup for pack
2275 npack = 0
2276 pack_buffer_pos = unpack_buffer_pos
2277 do l = 1, nsend_old
2278 m = ind_s(l)
2279 if(m>0) then
2280 overptr => update_s%send(m)
2281 do n = 1, overptr%count
2282 dir = overptr%dir(n)
2283 if(send_s(dir)) then
2284 npack = npack + 1
2285 if(npack > maxoverlap) call mpp_error(fatal, &
2286 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 1")
2287 group%pack_type(npack) = field_s
2288 group%pack_buffer_pos(npack) = pack_buffer_pos
2289 group%pack_rotation(npack) = overptr%rotation(n)
2290 group%pack_is(npack) = overptr%is(n)
2291 group%pack_ie(npack) = overptr%ie(n)
2292 group%pack_js(npack) = overptr%js(n)
2293 group%pack_je(npack) = overptr%je(n)
2294 group%pack_size(npack) = overptr%msgsize(n)*nscalar
2295 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2296 end if
2297 end do
2298 end if
2299
2300 m = ind_x(l)
2301 if(m>0) then
2302 overptr => update_x%send(m)
2303 do n = 1, overptr%count
2304 dir = overptr%dir(n)
2305 !--- nonsym_edge update is not for rotation of 90 or -90 degree ( cubic sphere grid )
2306 if( group%nonsym_edge .and. (overptr%rotation(n)==ninety .or. &
2307 overptr%rotation(n)==minus_ninety) ) then
2308 call mpp_error(fatal, 'set_group_update: flags=NONSYMEDGEUPDATE is not compatible '// &
2309 'with 90 or -90 degree rotation (normally cubic sphere grid' )
2310 endif
2311 if(send_x(dir)) then
2312 npack = npack + 1
2313 if(npack > maxoverlap) call mpp_error(fatal, &
2314 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 2")
2315 group%pack_type(npack) = field_x
2316 group%pack_buffer_pos(npack) = pack_buffer_pos
2317 group%pack_rotation(npack) = overptr%rotation(n)
2318 group%pack_is(npack) = overptr%is(n)
2319 group%pack_ie(npack) = overptr%ie(n)
2320 group%pack_js(npack) = overptr%js(n)
2321 group%pack_je(npack) = overptr%je(n)
2322 group%pack_size(npack) = overptr%msgsize(n)*nvector
2323 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2324 end if
2325 end do
2326 end if
2327
2328 m = ind_y(l)
2329 if(m>0) then
2330 overptr => update_y%send(m)
2331 do n = 1, overptr%count
2332 dir = overptr%dir(n)
2333 if( group%nonsym_edge .and. (overptr%rotation(n)==ninety .or. &
2334 overptr%rotation(n)==minus_ninety) ) then
2335 call mpp_error(fatal, 'set_group_update: flags=NONSYMEDGEUPDATE is not compatible '// &
2336 'with 90 or -90 degree rotation (normally cubic sphere grid' )
2337 endif
2338 if(send_y(dir)) then
2339 npack = npack + 1
2340 if(npack > maxoverlap) call mpp_error(fatal, &
2341 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 3")
2342 group%pack_type(npack) = field_y
2343 group%pack_buffer_pos(npack) = pack_buffer_pos
2344 group%pack_rotation(npack) = overptr%rotation(n)
2345 group%pack_is(npack) = overptr%is(n)
2346 group%pack_ie(npack) = overptr%ie(n)
2347 group%pack_js(npack) = overptr%js(n)
2348 group%pack_je(npack) = overptr%je(n)
2349 group%pack_size(npack) = overptr%msgsize(n)*nvector
2350 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2351 end if
2352 end do
2353 end if
2354 end do
2355 group%npack = npack
2356 if(update_buffer_pos .NE. pack_buffer_pos ) call mpp_error(fatal, &
2357 .NE."set_group_update: update_buffer_pos pack_buffer_pos")
2358
2359 !--- make sure the buffer is large enough
2360 mpp_domains_stack_hwm = max( mpp_domains_stack_hwm, tot_recv_size+tot_send_size )
2361
2362 if( mpp_domains_stack_hwm.GT.mpp_domains_stack_size )then
2363 write( text,'(i8)' )mpp_domains_stack_hwm
2364 call mpp_error( fatal, 'set_group_update: mpp_domains_stack overflow, '// &
2365 'call mpp_domains_set_stack_size('//trim(text)//') from all PEs.' )
2366 end if
2367
2368 group%tot_msgsize = tot_recv_size+tot_send_size
2369
2370end subroutine set_group_update
2371
2372
2373!######################################################################
2374 subroutine mpp_clear_group_update(group)
2375 type(mpp_group_update_type), intent(inout) :: group
2376
2377 group%nscalar = 0
2378 group%nvector = 0
2379 group%nsend = 0
2380 group%nrecv = 0
2381 group%npack = 0
2382 group%nunpack = 0
2383 group%initialized = .false.
2384
2385 end subroutine mpp_clear_group_update
2386
2387!#####################################################################
2389 type(mpp_group_update_type), intent(in) :: group
2391
2392 mpp_group_update_initialized = group%initialized
2393
2394 end function mpp_group_update_initialized
2395
2396!#####################################################################
2398 type(mpp_group_update_type), intent(in) :: group
2399 logical :: mpp_group_update_is_set
2400
2401 mpp_group_update_is_set = (group%nscalar > 0 .OR. group%nvector > 0)
2402
2403 end function mpp_group_update_is_set
2404!> @}
subroutine mpp_get_overlap(domain, action, p, is, ie, js, je, dir, rot, position)
Set user stack size.
subroutine mpp_get_neighbor_pe_2d(domain, direction, pe)
Return PE North/South/East/West of this PE-domain. direction must be NORTH, SOUTH,...
subroutine mpp_get_global_domains1d(domain, begin, end, size)
Set user stack size.
type(overlapspec) function, pointer search_bound_overlap(domain, position)
This routine finds the bound at certain position.
subroutine mpp_set_super_grid_indices(grid)
Modifies the indices in the domain_axis_spec type to those of the supergrid.
integer function mpp_get_domain_npes(domain)
Set user stack size.
logical function mpp_domain2d_eq(a, b)
Set user stack size.
integer function mpp_get_tile_npes(domain)
Returns number of processors used on current tile.
integer function get_rank_send(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
Set user stack size.
subroutine set_group_update(group, domain)
Set user stack size.
subroutine mpp_get_global_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, tile_count, position)
Set user stack size.
subroutine mpp_get_pelist1d(domain, pelist, pos)
Set user stack size.
subroutine mpp_set_global_domain1d(domain, begin, end, size)
Set user stack size.
subroutine mpp_get_layout2d(domain, layout)
Set user stack size.
subroutine mpp_get_tile_pelist(domain, pelist)
Get the processors list used on current tile.
subroutine mpp_get_domain_components(domain, x, y, tile_count)
Retrieve 1D components of 2D decomposition.
subroutine mpp_get_domain_extents1d(domain, xextent, yextent)
Set user stack size.
logical function mpp_group_update_is_set(group)
Set user stack size.
integer function get_vector_send(domain, update_x, update_y, ind_x, ind_y, start_pos, pelist)
Set user stack size.
subroutine mpp_copy_domain_axis_spec(domain_axis_spec_in, domain_axis_spec_out)
Copies input domain_axis_spec to the output domain_axis_spec.
integer function mpp_get_domain_tile_commid(domain)
Set user stack size.
subroutine mpp_set_global_domain2d(domain, xbegin, xend, ybegin, yend, xsize, ysize, tile_count)
Set user stack size.
logical function mpp_domain1d_eq(a, b)
Set user stack size.
integer function get_rank_recv(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
Set user stack size.
integer function, dimension(size(domain%tile_id(:))) mpp_get_tile_id(domain)
Returns the tile_id on current pe.
logical function mpp_domain_is_symmetry(domain)
Set user stack size.
subroutine mpp_create_super_grid_domain(domain)
Modifies the indices of the input domain to create the supergrid domain.
integer function mpp_get_num_overlap(domain, action, p, position)
Set user stack size.
type(overlapspec) function, pointer search_check_overlap(domain, position)
this routine finds the check at certain position
integer function mpp_get_current_ntile(domain)
Returns number of tile on current pe.
subroutine mpp_set_domain_symmetry(domain, symmetry)
Set user stack size.
integer function mpp_get_ntile_count(domain)
Returns number of tiles in mosaic.
subroutine mpp_get_domain_extents2d(domain, xextent, yextent)
This will return xextent and yextent for each tile.
subroutine mpp_get_global_domain1d(domain, begin, end, size, max_size)
Set user stack size.
logical function domain_update_is_needed(domain, whalo, ehalo, shalo, nhalo)
Set user stack size.
integer function, dimension(2) mpp_get_io_domain_layout(domain)
Set user stack size.
subroutine mpp_get_neighbor_pe_1d(domain, direction, pe)
Return PE to the righ/left of this PE-domain.
subroutine mpp_copy_domain1d_spec(domain1d_spec_in, domain1d_spec_out)
Copies input 1d domain spec to the output 1d domain spec.
subroutine mpp_get_tile_compute_domains(domain, xbegin, xend, ybegin, yend, position)
Set user stack size.
subroutine mpp_get_compute_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, x_is_global, y_is_global, tile_count, position)
Set user stack size.
subroutine mpp_get_compute_domain1d(domain, begin, end, size, max_size, is_global)
Set user stack size.
logical function mpp_domain1d_ne(a, b)
Set user stack size.
subroutine mpp_get_layout1d(domain, layout)
Set user stack size.
subroutine mpp_get_update_pelist(domain, action, pelist, position)
Set user stack size.
subroutine mpp_set_data_domain2d(domain, xbegin, xend, ybegin, yend, xsize, ysize, x_is_global, y_is_global, tile_count)
Set user stack size.
type(overlapspec) function, pointer search_update_overlap(domain, whalo, ehalo, shalo, nhalo, position)
this routine found the domain has the same halo size with the input whalo, ehalo,
subroutine mpp_get_compute_domains1d(domain, begin, end, size)
Set user stack size.
integer function mpp_get_domain_tile_root_pe(domain)
Set user stack size.
subroutine mpp_get_pelist2d(domain, pelist, pos)
Set user stack size.
subroutine mpp_copy_domain2d_spec(domain2d_spec_in, domain2d_spec_out)
Copies input 2d domain spec to the output 2d domain spec.
subroutine mpp_get_memory_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, x_is_global, y_is_global, position)
Set user stack size.
integer function get_mesgsize(overlap, do_dir)
Set user stack size.
subroutine mpp_set_compute_domain1d(domain, begin, end, size, is_global)
Set user stack size.
integer function mpp_get_domain_pe(domain)
Set user stack size.
integer function get_vector_recv(domain, update_x, update_y, ind_x, ind_y, start_pos, pelist)
Set user stack size.
subroutine mpp_get_tile_list(domain, tiles)
Return the tile_id on current pelist. one-tile-per-pe is assumed.
logical function mpp_group_update_initialized(group)
Set user stack size.
subroutine mpp_set_compute_domain2d(domain, xbegin, xend, ybegin, yend, xsize, ysize, x_is_global, y_is_global, tile_count)
Set user stack size.
type(domain2d) function, pointer mpp_get_io_domain(domain)
Set user stack size.
subroutine mpp_get_compute_domains2d(domain, xbegin, xend, xsize, ybegin, yend, ysize, position)
Set user stack size.
subroutine compute_overlaps(domain, position, update, check, ishift, jshift, x_cyclic_offset, y_cyclic_offset, whalo, ehalo, shalo, nhalo)
Computes remote domain overlaps.
subroutine mpp_copy_domain2d(domain_in, domain_out)
Copies input 2d domain to the output 2d domain.
subroutine mpp_get_memory_domain1d(domain, begin, end, size, max_size, is_global)
Set user stack size.
subroutine mpp_get_domain_shift(domain, ishift, jshift, position)
Returns the shift value in x and y-direction according to domain position..
logical function mpp_domain2d_ne(a, b)
Set user stack size.
logical function mpp_domain_is_initialized(domain)
Set user stack size.
subroutine nullify_domain2d_list(domain)
Set user stack size.
logical function mpp_domain_is_tile_root_pe(domain)
Returns if current pe is the root pe of the tile, if number of tiles on current pe is greater than 1,...
character(len=name_length) function mpp_get_domain_name(domain)
Set user stack size.
subroutine mpp_get_global_domains2d(domain, xbegin, xend, xsize, ybegin, yend, ysize, position)
Set user stack size.
integer function mpp_get_domain_commid(domain)
Set user stack size.
subroutine mpp_get_data_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, x_is_global, y_is_global, tile_count, position)
Set user stack size.
subroutine mpp_get_domain_pelist(domain, pelist)
Set user stack size.
subroutine mpp_domains_set_stack_size(n)
Set user stack size.
subroutine mpp_clear_group_update(group)
Set user stack size.
subroutine mpp_get_update_size(domain, nsend, nrecv, position)
Set user stack size.
integer function get_rank_unpack(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
Set user stack size.
integer function mpp_get_domain_root_pe(domain)
Set user stack size.
subroutine mpp_set_data_domain1d(domain, begin, end, size, is_global)
Set user stack size.
recursive subroutine mpp_copy_domain1d(domain_in, domain_out)
Copies input 1d domain to the output 1d domain.
subroutine set_overlaps(domain, overlap_in, overlap_out, whalo_out, ehalo_out, shalo_out, nhalo_out)
this routine sets up the overlapping for mpp_update_domains for arbitrary halo update....
subroutine mpp_get_data_domain1d(domain, begin, end, size, max_size, is_global)
Set user stack size.