36 integer,
intent(in) :: n
37 character(len=8) :: text
39 if( n.LE.mpp_domains_stack_size )
return
40 if(
allocated(mpp_domains_stack) )
deallocate(mpp_domains_stack)
41 allocate( mpp_domains_stack(n) )
42 if(
allocated(mpp_domains_stack_nonblock) )
deallocate(mpp_domains_stack_nonblock)
43 allocate( mpp_domains_stack_nonblock(n) )
45 mpp_domains_stack_size = n
47 if(
mpp_pe().EQ.mpp_root_pe() )
call mpp_error( note,
'MPP_DOMAINS_SET_STACK_SIZE: stack size set to '//text//
'.' )
61 type(domain1d),
intent(in) :: a, b
64 a%compute%end .EQ.b%compute%end .AND. &
65 a%domain_data%begin .EQ.b%domain_data%begin .AND. &
66 a%domain_data%end .EQ.b%domain_data%end .AND. &
67 a%global%begin .EQ.b%global%begin .AND. &
68 a%global%end .EQ.b%global%end )
79 type(domain1d),
intent(in) :: a, b
87 type(domain2d),
intent(in) :: a, b
96 if(
mpp_domain2d_eq .AND. ((a%pe.EQ.null_pe).OR.(b%pe.EQ.null_pe)) )
return
111 type(domain2d),
intent(in) :: a, b
124 type(domain1d),
intent(in) :: domain
125 integer,
intent(out),
optional :: begin, end, size, max_size
126 logical,
intent(out),
optional :: is_global
128 if(
PRESENT(begin) )begin = domain%compute%begin
129 if(
PRESENT(
end) )end = domain%compute%end
130 if(
PRESENT(size) )
size = domain%compute%size
131 if(
PRESENT(max_size) )max_size = domain%compute%max_size
132 if(
PRESENT(is_global) )is_global = domain%compute%is_global
138 type(domain1d),
intent(in) :: domain
139 integer,
intent(out),
optional :: begin, end, size, max_size
140 logical,
intent(out),
optional :: is_global
142 if(
PRESENT(begin) )begin = domain%domain_data%begin
143 if(
PRESENT(
end) )end = domain%domain_data%end
144 if(
PRESENT(size) )
size = domain%domain_data%size
145 if(
PRESENT(max_size) )max_size = domain%domain_data%max_size
146 if(
PRESENT(is_global) )is_global = domain%domain_data%is_global
152 type(domain1d),
intent(in) :: domain
153 integer,
intent(out),
optional :: begin, end, size, max_size
155 if(
PRESENT(begin) )begin = domain%global%begin
156 if(
PRESENT(
end) )end = domain%global%end
157 if(
PRESENT(size) )
size = domain%global%size
158 if(
PRESENT(max_size) )max_size = domain%global%max_size
164 type(domain1d),
intent(in) :: domain
165 integer,
intent(out),
optional :: begin, end, size, max_size
166 logical,
intent(out),
optional :: is_global
168 if(
PRESENT(begin) )begin = domain%memory%begin
169 if(
PRESENT(
end) )end = domain%memory%end
170 if(
PRESENT(size) )
size = domain%memory%size
171 if(
PRESENT(max_size) )max_size = domain%memory%max_size
172 if(
PRESENT(is_global) )is_global = domain%memory%is_global
178 x_is_global, y_is_global, tile_count, position )
179 type(domain2d),
intent(in) :: domain
180 integer,
intent(out),
optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
181 logical,
intent(out),
optional :: x_is_global, y_is_global
182 integer,
intent(in),
optional :: tile_count, position
183 integer :: tile, ishift, jshift
186 if(
present(tile_count)) tile = tile_count
188 call mpp_get_compute_domain( domain%x(tile), xbegin, xend, xsize, xmax_size, x_is_global )
189 call mpp_get_compute_domain( domain%y(tile), ybegin, yend, ysize, ymax_size, y_is_global )
191 if(
PRESENT(xend) ) xend = xend + ishift
192 if(
PRESENT(yend) ) yend = yend + jshift
193 if(
PRESENT(xsize)) xsize = xsize + ishift
194 if(
PRESENT(ysize)) ysize = ysize + jshift
195 if(
PRESENT(xmax_size))xmax_size = xmax_size + ishift
196 if(
PRESENT(ymax_size))ymax_size = ymax_size + jshift
203 x_is_global, y_is_global, tile_count, position )
204 type(domain2d),
intent(in) :: domain
205 integer,
intent(out),
optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
206 logical,
intent(out),
optional :: x_is_global, y_is_global
207 integer,
intent(in),
optional :: tile_count, position
208 integer :: tile, ishift, jshift
211 if(
present(tile_count)) tile = tile_count
213 call mpp_get_data_domain( domain%x(tile), xbegin, xend, xsize, xmax_size, x_is_global )
214 call mpp_get_data_domain( domain%y(tile), ybegin, yend, ysize, ymax_size, y_is_global )
216 if(
PRESENT(xend) ) xend = xend + ishift
217 if(
PRESENT(yend) ) yend = yend + jshift
218 if(
PRESENT(xsize)) xsize = xsize + ishift
219 if(
PRESENT(ysize)) ysize = ysize + jshift
220 if(
PRESENT(xmax_size))xmax_size = xmax_size + ishift
221 if(
PRESENT(ymax_size))ymax_size = ymax_size + jshift
228 tile_count, position )
229 type(domain2d),
intent(in) :: domain
230 integer,
intent(out),
optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
231 integer,
intent(in),
optional :: tile_count, position
232 integer :: tile, ishift, jshift
235 if(
present(tile_count)) tile = tile_count
237 call mpp_get_global_domain( domain%x(tile), xbegin, xend, xsize, xmax_size )
238 call mpp_get_global_domain( domain%y(tile), ybegin, yend, ysize, ymax_size )
240 if(
PRESENT(xend) ) xend = xend + ishift
241 if(
PRESENT(yend) ) yend = yend + jshift
242 if(
PRESENT(xsize)) xsize = xsize + ishift
243 if(
PRESENT(ysize)) ysize = ysize + jshift
244 if(
PRESENT(xmax_size))xmax_size = xmax_size + ishift
245 if(
PRESENT(ymax_size))ymax_size = ymax_size + jshift
252 x_is_global, y_is_global, position)
253 type(domain2d),
intent(in) :: domain
254 integer,
intent(out),
optional :: xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size
255 logical,
intent(out),
optional :: x_is_global, y_is_global
256 integer,
intent(in),
optional :: position
257 integer :: tile, ishift, jshift
261 call mpp_get_memory_domain( domain%x(tile), xbegin, xend, xsize, xmax_size, x_is_global )
262 call mpp_get_memory_domain( domain%y(tile), ybegin, yend, ysize, ymax_size, y_is_global )
264 if(
PRESENT(xend) ) xend = xend + ishift
265 if(
PRESENT(yend) ) yend = yend + jshift
266 if(
PRESENT(xsize)) xsize = xsize + ishift
267 if(
PRESENT(ysize)) ysize = ysize + jshift
268 if(
PRESENT(xmax_size))xmax_size = xmax_size + ishift
269 if(
PRESENT(ymax_size))ymax_size = ymax_size + jshift
276 type(domain_axis_spec),
intent(inout) :: grid
278 grid%begin = 2*grid%begin-1
279 grid%end = 2*grid%end+1
280 grid%size = grid%end-grid%begin+1
293 type(domain2d),
intent(inout) :: domain
303 call mpp_get_global_domain(domain, xbegin=xbegin, xend=xend, ybegin=ybegin, yend=yend, xsize=xsize, ysize=ysize)
304 call mpp_set_global_domain (domain, 2*xbegin-1, 2*xend+1, 2*ybegin-1, 2*yend+1, 2*(xend-xbegin)+3, &
307 call mpp_get_compute_domain(domain, xbegin=xbegin, xend=xend, ybegin=ybegin, yend=yend, xsize=xsize, ysize=ysize)
308 call mpp_set_compute_domain (domain, 2*xbegin-1, 2*xend+1, 2*ybegin-1, 2*yend+1, 2*(xend-xbegin)+3, &
311 call mpp_get_data_domain(domain, xbegin=xbegin, xend=xend, ybegin=ybegin, yend=yend, xsize=xsize, ysize=ysize)
312 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 do i=1,
size(domain%list(:))
326 do i=1,
size(domain%x(1)%list)
330 do i=1,
size(domain%y(1)%list)
338 type(domain1d),
intent(inout) :: domain
339 integer,
intent(in),
optional :: begin, end, size
340 logical,
intent(in),
optional :: is_global
342 if(
present(begin)) domain%compute%begin = begin
343 if(
present(
end)) domain%compute%end = end
344 if(
present(size)) domain%compute%size =
size
345 if(
present(is_global)) domain%compute%is_global = is_global
351 x_is_global, y_is_global, tile_count )
352 type(domain2d),
intent(inout) :: domain
353 integer,
intent(in),
optional :: xbegin, xend, ybegin, yend, xsize, ysize
354 logical,
intent(in),
optional :: x_is_global, y_is_global
355 integer,
intent(in),
optional :: tile_count
359 if(
present(tile_count)) tile = tile_count
361 call mpp_set_compute_domain(domain%x(tile), xbegin, xend, xsize, x_is_global)
362 call mpp_set_compute_domain(domain%y(tile), ybegin, yend, ysize, y_is_global)
368 type(domain1d),
intent(inout) :: domain
369 integer,
intent(in),
optional :: begin, end, size
370 logical,
intent(in),
optional :: is_global
372 if(
present(begin)) domain%domain_data%begin = begin
373 if(
present(
end)) domain%domain_data%end = end
374 if(
present(size)) domain%domain_data%size =
size
375 if(
present(is_global)) domain%domain_data%is_global = is_global
381 x_is_global, y_is_global, tile_count )
382 type(domain2d),
intent(inout) :: domain
383 integer,
intent(in),
optional :: xbegin, xend, ybegin, yend, xsize, ysize
384 logical,
intent(in),
optional :: x_is_global, y_is_global
385 integer,
intent(in),
optional :: tile_count
389 if(
present(tile_count)) tile = tile_count
391 call mpp_set_data_domain(domain%x(tile), xbegin, xend, xsize, x_is_global)
392 call mpp_set_data_domain(domain%y(tile), ybegin, yend, ysize, y_is_global)
398 type(domain1d),
intent(inout) :: domain
399 integer,
intent(in),
optional :: begin, end, size
401 if(
present(begin)) domain%global%begin = begin
402 if(
present(
end)) domain%global%end = end
403 if(
present(size)) domain%global%size =
size
409 type(domain2d),
intent(inout) :: domain
410 integer,
intent(in),
optional :: xbegin, xend, ybegin, yend, xsize, ysize
411 integer,
intent(in),
optional :: tile_count
415 if(
present(tile_count)) tile = tile_count
416 call mpp_set_global_domain(domain%x(tile), xbegin, xend, xsize)
417 call mpp_set_global_domain(domain%y(tile), ybegin, yend, ysize)
431 type(domain2d),
intent(in) :: domain
432 type(domain1d),
intent(inout),
optional :: x, y
433 integer,
intent(in),
optional :: tile_count
437 if(
present(tile_count)) tile = tile_count
438 if(
PRESENT(x) )x = domain%x(tile)
439 if(
PRESENT(y) )y = domain%y(tile)
445 type(domain1d),
intent(in) :: domain
446 integer,
intent(out),
optional,
dimension(:) :: begin, end, size
448 if( .NOT.module_is_initialized ) &
449 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: must first call mpp_domains_init.' )
451 if(
PRESENT(begin) )
then
452 if( any(shape(begin).NE.shape(domain%list)) ) &
453 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: begin array size does not match domain.' )
454 begin(:) = domain%list(:)%compute%begin
456 if(
PRESENT(
end) )then
457 if( any(shape(
end).NE.shape(domain%list)) ) &
458 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: end array size does not match domain.' )
459 end(:) = domain%list(:)%compute%end
461 if(
PRESENT(size) )
then
462 if( any(shape(size).NE.shape(domain%list)) ) &
463 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: size array size does not match domain.' )
464 size(:) = domain%list(:)%compute%size
471 type(domain2d),
intent(in) :: domain
472 integer,
intent(out),
optional,
dimension(:) :: xbegin, xend, xsize, ybegin, yend, ysize
473 integer,
intent(in ),
optional :: position
475 integer :: i, ishift, jshift
480 if( .NOT.module_is_initialized ) &
481 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: must first call mpp_domains_init.' )
483 if(
PRESENT(xbegin) )
then
484 if(
size(xbegin(:)).NE.
size(domain%list(:)) ) &
485 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: xbegin array size does not match domain.' )
486 do i = 1,
size(xbegin(:))
487 xbegin(i) = domain%list(i-1)%x(1)%compute%begin
490 if(
PRESENT(xend) )
then
491 if(
size(xend(:)).NE.
size(domain%list(:)) ) &
492 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: xend array size does not match domain.' )
493 do i = 1,
size(xend(:))
494 xend(i) = domain%list(i-1)%x(1)%compute%end + ishift
497 if(
PRESENT(xsize) )
then
498 if(
size(xsize(:)).NE.
size(domain%list(:)) ) &
499 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: xsize array size does not match domain.' )
500 do i = 1,
size(xsize(:))
501 xsize(i) = domain%list(i-1)%x(1)%compute%size + ishift
504 if(
PRESENT(ybegin) )
then
505 if(
size(ybegin(:)).NE.
size(domain%list(:)) ) &
506 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: ybegin array size does not match domain.' )
507 do i = 1,
size(ybegin(:))
508 ybegin(i) = domain%list(i-1)%y(1)%compute%begin
511 if(
PRESENT(yend) )
then
512 if(
size(yend(:)).NE.
size(domain%list(:)) ) &
513 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: yend array size does not match domain.' )
514 do i = 1,
size(yend(:))
515 yend(i) = domain%list(i-1)%y(1)%compute%end + jshift
518 if(
PRESENT(ysize) )
then
519 if(
size(ysize(:)).NE.
size(domain%list(:)) ) &
520 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: ysize array size does not match domain.' )
521 do i = 1,
size(ysize(:))
522 ysize(i) = domain%list(i-1)%y(1)%compute%size + jshift
530 type(domain1d),
intent(in) :: domain
531 integer,
intent(out),
optional,
dimension(:) :: begin, end, size
533 if( .NOT.module_is_initialized ) &
534 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: must first call mpp_domains_init.' )
536 if(
PRESENT(begin) )
then
537 if( any(shape(begin).NE.shape(domain%list)) ) &
538 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: begin array size does not match domain.' )
539 begin(:) = domain%list(:)%global%begin
541 if(
PRESENT(
end) )then
542 if( any(shape(
end).NE.shape(domain%list)) ) &
543 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: end array size does not match domain.' )
544 end(:) = domain%list(:)%global%end
546 if(
PRESENT(size) )
then
547 if( any(shape(size).NE.shape(domain%list)) ) &
548 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: size array size does not match domain.' )
549 size(:) = domain%list(:)%global%size
557 type(domain2d),
intent(in) :: domain
558 integer,
intent(out),
optional,
dimension(:) :: xbegin, xend, xsize, ybegin, yend, ysize
559 integer,
intent(in ),
optional :: position
561 integer :: i, ishift, jshift
566 if( .NOT.module_is_initialized ) &
567 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: must first call mpp_domains_init.' )
569 if(
PRESENT(xbegin) )
then
570 if(
size(xbegin(:)).NE.
size(domain%list(:)) ) &
571 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: xbegin array size does not match domain.' )
572 do i = 1,
size(xbegin(:))
573 xbegin(i) = domain%list(i-1)%x(1)%global%begin
576 if(
PRESENT(xend) )
then
577 if(
size(xend(:)).NE.
size(domain%list(:)) ) &
578 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: xend array size does not match domain.' )
579 do i = 1,
size(xend(:))
580 xend(i) = domain%list(i-1)%x(1)%global%end + ishift
583 if(
PRESENT(xsize) )
then
584 if(
size(xsize(:)).NE.
size(domain%list(:)) ) &
585 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: xsize array size does not match domain.' )
586 do i = 1,
size(xsize(:))
587 xsize(i) = domain%list(i-1)%x(1)%global%size + ishift
590 if(
PRESENT(ybegin) )
then
591 if(
size(ybegin(:)).NE.
size(domain%list(:)) ) &
592 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: ybegin array size does not match domain.' )
593 do i = 1,
size(ybegin(:))
594 ybegin(i) = domain%list(i-1)%y(1)%global%begin
597 if(
PRESENT(yend) )
then
598 if(
size(yend(:)).NE.
size(domain%list(:)) ) &
599 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: yend array size does not match domain.' )
600 do i = 1,
size(yend(:))
601 yend(i) = domain%list(i-1)%y(1)%global%end + jshift
604 if(
PRESENT(ysize) )
then
605 if(
size(ysize(:)).NE.
size(domain%list(:)) ) &
606 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: ysize array size does not match domain.' )
607 do i = 1,
size(ysize(:))
608 ysize(i) = domain%list(i-1)%y(1)%global%size + jshift
617 type(domain2d),
intent(in) :: domain
618 integer,
dimension(0:),
intent(inout) :: xextent, yextent
621 if(domain%ntiles .NE. 1)
call mpp_error(fatal,
"mpp_domains_util.inc(mpp_get_domain_extents1D): "// &
622 "ntiles is more than 1, please use mpp_get_domain_extents2D")
623 if(
size(xextent) .NE.
size(domain%x(1)%list(:)))
call mpp_error(fatal, &
624 &
"mpp_domains_util.inc(mpp_get_domain_extents1D): "// &
625 &
"size(xextent) does not equal to size(domain%x(1)%list(:)))")
626 if(
size(yextent) .NE.
size(domain%y(1)%list(:)))
call mpp_error(fatal, &
627 &
"mpp_domains_util.inc(mpp_get_domain_extents1D): "// &
628 &
"size(yextent) does not equal to size(domain%y(1)%list(:)))")
629 do n = 0,
size(domain%x(1)%list(:))-1
630 xextent(n) = domain%x(1)%list(n)%compute%size
632 do n = 0,
size(domain%y(1)%list(:))-1
633 yextent(n) = domain%y(1)%list(n)%compute%size
641 type(domain2d),
intent(in) :: domain
642 integer,
dimension(:,:),
intent(inout) :: xextent, yextent
643 integer :: ntile, nlist, n, m, ndivx, ndivy, tile, pos
645 ntile = domain%ntiles
646 nlist =
size(domain%list(:))
647 if(
size(xextent,2) .ne. ntile .or.
size(yextent,2) .ne. ntile)
call mpp_error(fatal, &
648 "mpp_domains_utile.inc: the second dimension size of xextent/yextent is not correct")
649 ndivx =
size(xextent,1); ndivy =
size(yextent,1)
651 if(any(domain%list(n)%x(:)%pos>ndivx-1) )
call mpp_error(fatal, &
652 "mpp_domains_utile.inc: first dimension size of xextent is less than the x-layout in some tile")
653 if(any(domain%list(n)%y(:)%pos>ndivy-1) )
call mpp_error(fatal, &
654 "mpp_domains_utile.inc: first dimension size of yextent is less than the y-layout in some tile")
657 xextent = 0; yextent=0
660 do m = 1,
size(domain%list(n)%tile_id(:))
661 tile = domain%list(n)%tile_id(m)
662 pos = domain%list(n)%x(m)%pos+1
663 if(xextent(pos, tile) == 0) xextent(pos,tile) = domain%list(n)%x(m)%compute%size
664 pos = domain%list(n)%y(m)%pos+1
665 if(yextent(pos, tile) == 0) yextent(pos,tile) = domain%list(n)%y(m)%compute%size
674 type(domain2d),
intent(in) :: domain
684 type(domain2d),
intent(in) :: domain
693 type(domain2d),
intent(in) :: domain
702 type(domain2d),
intent(in) :: domain
705 call mpp_error(note,
"mpp_get_domain_tile_commid is deprecated: Please use mpp_get_domain_tile_comm instead")
712 type(domain2d),
intent(in) :: domain
721 type(domain2d),
intent(in) :: domain
724 call mpp_error(note,
"mpp_get_domain_commid is deprecated: Please use mpp_get_domain_comm instead")
731 type(domain2d),
intent(in) :: domain
734 if(
ASSOCIATED(domain%io_domain))
then
749 type(domain1d),
intent(in) :: domain
750 integer,
intent(out) :: pelist(:)
751 integer,
intent(out),
optional :: pos
754 if( .NOT.module_is_initialized ) &
755 call mpp_error( fatal,
'MPP_GET_PELIST: must first call mpp_domains_init.' )
756 ndivs =
size(domain%list(:))
758 if(
size(pelist(:)).NE.ndivs ) &
759 call mpp_error( fatal,
'MPP_GET_PELIST: pelist array size does not match domain.' )
761 pelist(:) = domain%list(0:ndivs-1)%pe
762 if(
PRESENT(pos) )pos = domain%pos
773 type(domain2d),
intent(in) :: domain
774 integer,
intent(out) :: pelist(:)
775 integer,
intent(out),
optional :: pos
777 if( .NOT.module_is_initialized ) &
778 call mpp_error( fatal,
'MPP_GET_PELIST: must first call mpp_domains_init.' )
779 if(
size(pelist(:)).NE.
size(domain%list(:)) ) &
780 call mpp_error( fatal,
'MPP_GET_PELIST: pelist array size does not match domain.' )
782 pelist(:) = domain%list(:)%pe
783 if(
PRESENT(pos) )pos = domain%pos
793 type(domain1d),
intent(in) :: domain
794 integer,
intent(out) :: layout
796 if( .NOT.module_is_initialized ) &
797 call mpp_error( fatal,
'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
799 layout =
size(domain%list(:))
809 type(domain2d),
intent(in) :: domain
810 integer,
intent(out) :: layout(2)
812 if( .NOT.module_is_initialized ) &
813 call mpp_error( fatal,
'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
815 layout(1) =
size(domain%x(1)%list(:))
816 layout(2) =
size(domain%y(1)%list(:))
831 type(domain2d),
intent(in) :: domain
832 integer,
intent(out) :: ishift, jshift
833 integer,
optional,
intent(in) :: position
836 ishift = 0 ; jshift = 0
838 if(
present(position)) pos = position
840 if(domain%symmetry)
then
843 ishift = 1; jshift = 1
857 type(domain1d),
intent(inout) :: domain
858 integer,
intent(in) :: direction
859 integer,
intent(out) :: pe
861 integer ipos, ipos2, npx
864 npx =
size(domain%list(:))
867 select case (direction)
873 if(domain%cyclic)
then
887 if(ipos2 > npx-1)
then
888 if(domain%cyclic)
then
897 if(ipos2 >= 0) pe = domain%list(ipos2)%pe
905 type(domain2d),
intent(inout) :: domain
906 integer,
intent(in) :: direction
907 integer,
intent(out) :: pe
909 integer ipos, jpos, npx, npy, ix, iy, ipos0, jpos0
912 npx =
size(domain%x(1)%list(:))
913 npy =
size(domain%y(1)%list(:))
914 ipos0 = domain%x(1)%pos
915 jpos0 = domain%y(1)%pos
917 select case (direction)
944 call mpp_error( fatal, &
945 &
'MPP_GET_NEIGHBOR_PE_2D: direction must be either NORTH, ' &
946 & //
'SOUTH, EAST, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST or NORTH_WEST')
953 if( (ipos < 0 .or. ipos > npx-1) .and. domain%x(1)%cyclic )
then
955 ipos = modulo(ipos, npx)
958 if( (ipos < 0 .and. btest(domain%fold,west)) .or. &
959 & (ipos > npx-1 .and. btest(domain%fold,east)) )
then
965 if( (jpos < 0 .or. jpos > npy-1) .and. domain%y(1)%cyclic )
then
967 jpos = modulo(jpos, npy)
970 if( (jpos < 0 .and. btest(domain%fold,south)) .or. &
971 & (jpos > npy-1 .and. btest(domain%fold,north)) )
then
979 if(ipos >= 0 .and. ipos <= npx-1 .and. jpos >= 0 .and. jpos <= npy-1)
then
980 pe = domain%pearray(ipos, jpos)
990 type(domain2d),
intent(inout) :: domain
998 type(domain2d),
intent(in) :: domain
1008 type(domain2d),
intent(in) :: domain
1022 type(domain2d),
intent(in) :: domain
1023 integer,
intent(in) :: whalo, ehalo, shalo, nhalo
1028 if(whalo == 0 .AND. ehalo==0 .AND. shalo == 0 .AND. nhalo==0 )
then
1030 if( debug )
call mpp_error(note, &
1031 'mpp_domains_util.inc: halo size to be updated are all zero, no update will be done')
1034 if( (whalo == -domain%whalo .AND. domain%whalo .NE. 0) .or. &
1035 (ehalo == -domain%ehalo .AND. domain%ehalo .NE. 0) .or. &
1036 (shalo == -domain%shalo .AND. domain%shalo .NE. 0) .or. &
1037 (nhalo == -domain%nhalo .AND. domain%nhalo .NE. 0) )
then
1039 call mpp_error(note,
'mpp_domains_util.inc: at least one of w/e/s/n halo size to be updated '// &
1040 'is the inverse of the original halo when defining domain, no update will be done')
1049 type(domain2d),
intent(inout) :: domain
1050 integer,
intent(in) :: whalo, ehalo, shalo, nhalo
1051 integer,
intent(in) :: position
1053 type(overlapspec),
pointer :: update_ref
1054 type(overlapspec),
pointer :: check => null()
1055 integer :: ishift, jshift, shift
1057 shift = 0;
if(domain%symmetry) shift = 1
1058 select case(position)
1060 update_ref => domain%update_T
1061 ishift = 0; jshift = 0
1063 update_ref => domain%update_C
1064 ishift = shift; jshift = shift
1066 update_ref => domain%update_N
1067 ishift = 0; jshift = shift
1069 update_ref => domain%update_E
1070 ishift = shift; jshift = 0
1072 call mpp_error(fatal,
"mpp_domains_util.inc(search_update_overlap): position should be CENTER|CORNER|EAST|NORTH")
1086 if(domain%fold .NE. 0)
then
1088 ishift, jshift, 0, 0, whalo, ehalo, shalo, nhalo)
1099 update_ref => null()
1106 type(domain2d),
intent(in) :: domain
1107 integer,
intent(in) :: position
1110 select case(position)
1120 call mpp_error(fatal,
"mpp_domains_util.inc(search_check_overlap): position should be CENTER|CORNER|EAST|NORTH")
1128 type(domain2d),
intent(in) :: domain
1129 integer,
intent(in) :: position
1132 select case(position)
1142 call mpp_error(fatal,
"mpp_domains_util.inc(search_bound_overlap): position should be CENTER|CORNER|EAST|NORTH")
1150 type(domain2d),
intent(in) :: domain
1161 type(domain2d),
intent(in) :: domain
1162 integer,
intent(inout) :: tiles(:)
1165 if(
size(tiles(:)).NE.
size(domain%list(:)) ) &
1166 call mpp_error( fatal,
'mpp_get_tile_list: tiles array size does not match domain.' )
1167 do i = 1,
size(tiles(:))
1168 if(
size(domain%list(i-1)%tile_id(:)) > 1)
call mpp_error( fatal, &
1169 'mpp_get_tile_list: only support one-tile-per-pe now, contact developer');
1170 tiles(i) = domain%list(i-1)%tile_id(1)
1178 type(domain2d),
intent(in) :: domain
1189 type(domain2d),
intent(in) :: domain
1202 type(domain2d),
intent(in) :: domain
1212 type(domain2d),
intent(in) :: domain
1218 if(
size(domain%tile_id(:)) > 1)
then
1222 tile = domain%tile_id(1)
1223 do i = 0,
size(domain%list(:))-1
1233 type(domain2d),
intent(in) :: domain
1234 integer,
intent(inout) :: pelist(:)
1235 integer :: npes_on_tile
1236 integer :: i, tile, pos
1239 if(
size(pelist(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1240 "mpp_domains_util.inc(mpp_get_tile_pelist): size(pelist) does not equal npes on current tile")
1241 tile = domain%tile_id(1)
1243 do i = 0,
size(domain%list(:))-1
1244 if(tile == domain%list(i)%tile_id(1))
then
1246 pelist(pos) = domain%list(i)%pe
1256 type(domain2d),
intent(in) :: domain
1257 integer,
intent(out),
dimension(:) :: xbegin, xend, ybegin, yend
1258 integer,
intent(in ),
optional :: position
1260 integer :: i, ishift, jshift
1261 integer :: npes_on_tile, pos, tile
1266 if( .NOT.module_is_initialized ) &
1267 call mpp_error( fatal,
'mpp_get_compute_domains2D: must first call mpp_domains_init.' )
1270 if(
size(xbegin(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1271 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(xbegin) does not equal npes on current tile")
1272 if(
size(xend(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1273 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(xend) does not equal npes on current tile")
1274 if(
size(ybegin(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1275 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(ybegin) does not equal npes on current tile")
1276 if(
size(yend(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1277 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(yend) does not equal npes on current tile")
1279 tile = domain%tile_id(1)
1281 do i = 0,
size(domain%list(:))-1
1282 if(tile == domain%list(i)%tile_id(1))
then
1284 xbegin(pos) = domain%list(i)%x(1)%compute%begin
1285 xend(pos) = domain%list(i)%x(1)%compute%end + ishift
1286 ybegin(pos) = domain%list(i)%y(1)%compute%begin
1287 yend(pos) = domain%list(i)%y(1)%compute%end + jshift
1299 type(domain2d),
intent(in) :: domain
1300 integer,
intent(in) :: action
1301 integer,
intent(in) :: p
1302 integer,
optional,
intent(in) :: position
1304 type(overlapspec),
pointer :: update => null()
1308 if(
present(position)) pos = position
1311 update => domain%update_T
1313 update => domain%update_C
1315 update => domain%update_E
1317 update => domain%update_N
1319 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_num_overlap): invalid option of position")
1322 if(action == event_send)
then
1323 if(p< 1 .OR. p > update%nsend)
call mpp_error( fatal, &
1324 "mpp_domains_mod(mpp_get_num_overlap): p should be between 1 and update%nsend")
1326 else if(action == event_recv)
then
1327 if(p< 1 .OR. p > update%nrecv)
call mpp_error( fatal, &
1328 "mpp_domains_mod(mpp_get_num_overlap): p should be between 1 and update%nrecv")
1331 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_num_overlap): invalid option of action")
1338 type(domain2d),
intent(in) :: domain
1339 integer,
intent(out) :: nsend, nrecv
1340 integer,
optional,
intent(in) :: position
1344 if(
present(position)) pos = position
1347 nsend = domain%update_T%nsend
1348 nrecv = domain%update_T%nrecv
1350 nsend = domain%update_C%nsend
1351 nrecv = domain%update_C%nrecv
1353 nsend = domain%update_E%nsend
1354 nrecv = domain%update_E%nrecv
1356 nsend = domain%update_N%nsend
1357 nrecv = domain%update_N%nrecv
1359 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_size): invalid option of position")
1366 type(domain2d),
intent(in) :: domain
1367 integer,
intent(in) :: action
1368 integer,
intent(inout) :: pelist(:)
1369 integer,
optional,
intent(in) :: position
1370 type(overlapspec),
pointer :: update => null()
1374 if(
present(position)) pos = position
1377 update => domain%update_T
1379 update => domain%update_C
1381 update => domain%update_E
1383 update => domain%update_N
1385 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_pelist): invalid option of position")
1388 if(action == event_send)
then
1389 if(
size(pelist) .NE. update%nsend)
call mpp_error( fatal, &
1390 "mpp_domains_mod(mpp_get_update_pelist): size of pelist does not match update%nsend")
1391 do p = 1, update%nsend
1392 pelist(p) = update%send(p)%pe
1394 else if(action == event_recv)
then
1395 if(
size(pelist) .NE. update%nrecv)
call mpp_error( fatal, &
1396 "mpp_domains_mod(mpp_get_update_pelist): size of pelist does not match update%nrecv")
1397 do p = 1, update%nrecv
1398 pelist(p) = update%recv(p)%pe
1401 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_pelist): invalid option of action")
1408 type(domain2d),
intent(in) :: domain
1409 integer,
intent(in) :: action
1410 integer,
intent(in) :: p
1411 integer,
dimension(:),
intent(out) :: is, ie, js, je
1412 integer,
dimension(:),
intent(out) :: dir, rot
1413 integer,
optional,
intent(in) :: position
1414 type(overlapspec),
pointer :: update => null()
1415 type(overlap_type),
pointer :: overlap => null()
1416 integer :: count, pos
1419 if(
present(position)) pos = position
1422 update => domain%update_T
1424 update => domain%update_C
1426 update => domain%update_E
1428 update => domain%update_N
1430 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_overlap): invalid option of position")
1433 if(action == event_send)
then
1434 overlap => update%send(p)
1435 else if(action == event_recv)
then
1436 overlap => update%recv(p)
1438 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_overlap): invalid option of action")
1441 count = overlap%count
1442 if(
size(is(:)) .NE. count .OR.
size(ie(:)) .NE. count .OR.
size(js(:)) .NE. count .OR. &
1443 size(je(:)) .NE. count .OR.
size(dir(:)) .NE. count .OR.
size(rot(:)) .NE. count ) &
1444 call mpp_error( fatal, &
1445 &
"mpp_domains_mod(mpp_get_overlap): size mismatch between number of overlap and array size")
1447 is = overlap%is (1:count)
1448 ie = overlap%ie (1:count)
1449 js = overlap%js (1:count)
1450 je = overlap%je (1:count)
1451 dir = overlap%dir (1:count)
1452 rot = overlap%rotation(1:count)
1461 type(domain2d),
intent(in) :: domain
1470 type(domain2d),
intent(in) :: domain
1478 type(domain2d),
intent(in) :: domain
1489 type(domain2d),
intent(in) :: domain
1490 integer,
intent(out) :: pelist(:)
1493 if(
size(pelist(:)) .NE.
size(domain%list(:)) )
then
1494 call mpp_error(fatal, .NE.
"mpp_get_domain_pelist: size(pelist(:)) size(domain%list(:)) ")
1497 do p = 0,
size(domain%list(:))-1
1498 pelist(p+1) = domain%list(p)%pe
1507 type(domain2d),
intent(in) :: domain
1515 function get_rank_send(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1516 type(domain2d),
intent(in) :: domain
1517 type(overlapspec),
intent(in) :: overlap_x, overlap_y
1518 integer,
intent(out) :: rank_x, rank_y, ind_x, ind_y
1520 integer :: nlist, nsend_x, nsend_y
1522 nlist =
size(domain%list(:))
1523 nsend_x = overlap_x%nsend
1524 nsend_y = overlap_y%nsend
1527 if(nsend_x>0) rank_x = overlap_x%send(1)%pe - domain%pe
1528 if(nsend_y>0) rank_y = overlap_y%send(1)%pe - domain%pe
1529 if(rank_x .LT. 0) rank_x = rank_x + nlist
1530 if(rank_y .LT. 0) rank_y = rank_y + nlist
1535 if(nsend_x>0) ind_x = 1
1536 if(nsend_y>0) ind_y = 1
1542 function get_rank_recv(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1543 type(domain2d),
intent(in) :: domain
1544 type(overlapspec),
intent(in) :: overlap_x, overlap_y
1545 integer,
intent(out) :: rank_x, rank_y, ind_x, ind_y
1547 integer :: nlist, nrecv_x, nrecv_y
1549 nlist =
size(domain%list(:))
1550 nrecv_x = overlap_x%nrecv
1551 nrecv_y = overlap_y%nrecv
1555 rank_x = overlap_x%recv(1)%pe - domain%pe
1556 if(rank_x .LE. 0) rank_x = rank_x + nlist
1559 rank_y = overlap_y%recv(1)%pe - domain%pe
1560 if(rank_y .LE. 0) rank_y = rank_y + nlist
1566 if(nrecv_x>0) ind_x = 1
1567 if(nrecv_y>0) ind_y = 1
1573 type(domain2d),
intent(in) :: domain
1574 type(overlapspec),
intent(in) :: update_x, update_y
1575 integer,
intent(out) :: ind_x(:), ind_y(:)
1576 integer,
intent(out) :: start_pos(:)
1577 integer,
intent(out) :: pelist(:)
1578 integer :: nlist, nrecv_x, nrecv_y, ntot, n
1579 integer :: ix, iy, rank_x, rank_y, cur_pos
1582 nlist =
size(domain%list(:))
1583 nrecv_x = update_x%nrecv
1584 nrecv_y = update_y%nrecv
1586 ntot = nrecv_x + nrecv_y
1596 if(ix <= nrecv_x )
then
1597 rank_x = update_x%recv(ix)%pe-domain%pe
1598 if(rank_x .LE. 0) rank_x = rank_x + nlist
1602 if(iy <= nrecv_y )
then
1603 rank_y = update_y%recv(iy)%pe-domain%pe
1604 if(rank_y .LE. 0) rank_y = rank_y + nlist
1610 if( rank_x == rank_y )
then
1614 cur_pos = cur_pos + update_x%recv(ix)%totsize + update_y%recv(iy)%totsize
1618 else if ( rank_x > rank_y )
then
1622 cur_pos = cur_pos + update_x%recv(ix)%totsize
1625 else if ( rank_y > rank_x )
then
1629 cur_pos = cur_pos + update_y%recv(iy)%totsize
1639 type(domain2d),
intent(in) :: domain
1640 type(overlapspec),
intent(in) :: update_x, update_y
1641 integer,
intent(out) :: ind_x(:), ind_y(:)
1642 integer,
intent(out) :: start_pos(:)
1643 integer,
intent(out) :: pelist(:)
1644 integer :: nlist, nsend_x, nsend_y, ntot, n
1645 integer :: ix, iy, rank_x, rank_y, cur_pos
1648 nlist =
size(domain%list(:))
1649 nsend_x = update_x%nsend
1650 nsend_y = update_y%nsend
1652 ntot = nsend_x + nsend_y
1661 if(ix <= nsend_x )
then
1662 rank_x = update_x%send(ix)%pe-domain%pe
1663 if(rank_x .LT. 0) rank_x = rank_x + nlist
1667 if(iy <= nsend_y )
then
1668 rank_y = update_y%send(iy)%pe-domain%pe
1669 if(rank_y .LT. 0) rank_y = rank_y + nlist
1676 if( rank_x == rank_y )
then
1680 cur_pos = cur_pos + update_x%send(ix)%totsize + update_y%send(iy)%totsize
1684 else if ( rank_x < rank_y )
then
1688 cur_pos = cur_pos + update_x%send(ix)%totsize
1691 else if ( rank_y < rank_x )
then
1695 cur_pos = cur_pos + update_y%send(iy)%totsize
1707 type(domain2d),
intent(in) :: domain
1708 type(overlapspec),
intent(in) :: overlap_x, overlap_y
1709 integer,
intent(out) :: rank_x, rank_y, ind_x, ind_y
1711 integer :: nlist, nrecv_x, nrecv_y
1713 nlist =
size(domain%list(:))
1714 nrecv_x = overlap_x%nrecv
1715 nrecv_y = overlap_y%nrecv
1719 if(nrecv_x>0) rank_x = overlap_x%recv(nrecv_x)%pe - domain%pe
1720 if(nrecv_y>0) rank_y = overlap_y%recv(nrecv_y)%pe - domain%pe
1721 if(rank_x .LE.0) rank_x = rank_x + nlist
1722 if(rank_y .LE.0) rank_y = rank_y + nlist
1728 if(nrecv_x >0) ind_x = nrecv_x
1729 if(nrecv_y >0) ind_y = nrecv_y
1735 type(overlap_type),
intent(in) :: overlap
1736 logical,
intent(in) :: do_dir(:)
1741 do n = 1, overlap%count
1742 dir = overlap%dir(n)
1743 if(do_dir(dir))
then
1752 type(domain2d),
intent(inout) :: domain
1753 logical,
intent(in ) :: symmetry
1755 domain%symmetry = symmetry
1761 type(domain1d),
intent(in) :: domain_in
1762 type(domain1d),
intent(inout) :: domain_out
1768 domain_out%compute = domain_in%compute
1769 domain_out%domain_data = domain_in%domain_data
1770 domain_out%global = domain_in%global
1771 domain_out%memory = domain_in%memory
1772 domain_out%cyclic = domain_in%cyclic
1773 domain_out%pe = domain_in%pe
1774 domain_out%pos = domain_in%pos
1776 if (
associated(domain_in%list))
then
1777 starting = lbound(domain_in%list, 1)
1778 ending = ubound(domain_in%list, 1)
1779 if (
associated(domain_out%list))
deallocate(domain_out%list)
1780 allocate(domain_out%list(starting:ending))
1782 do i = starting, ending
1793 type(domain2d),
intent(in) :: domain_in
1794 type(domain2d),
intent(inout) :: domain_out
1798 integer :: starting(2)
1799 integer :: ending(2)
1801 if (
associated(domain_out%x))
then
1802 call mpp_error(fatal,
"mpp_copy_domain: domain_out is already set")
1805 domain_out%id = domain_in%id
1806 domain_out%pe = domain_in%pe
1807 domain_out%fold = domain_in%fold
1808 domain_out%pos = domain_in%pos
1809 domain_out%symmetry = domain_in%symmetry
1810 domain_out%whalo = domain_in%whalo
1811 domain_out%ehalo = domain_in%ehalo
1812 domain_out%shalo = domain_in%shalo
1813 domain_out%nhalo = domain_in%nhalo
1814 domain_out%ntiles = domain_in%ntiles
1815 domain_out%max_ntile_pe = domain_in%max_ntile_pe
1816 domain_out%ncontacts = domain_in%ncontacts
1817 domain_out%rotated_ninety = domain_in%rotated_ninety
1818 domain_out%initialized = domain_in%initialized
1819 domain_out%tile_root_pe = domain_in%tile_root_pe
1820 domain_out%io_layout = domain_in%io_layout
1821 domain_out%name = domain_in%name
1823 ntiles =
size(domain_in%x(:))
1824 allocate(domain_out%x(ntiles), domain_out%y(ntiles), domain_out%tile_id(ntiles) )
1830 if (
associated(domain_in%pearray))
then
1831 starting = lbound(domain_in%pearray)
1832 ending = ubound(domain_in%pearray)
1834 allocate(domain_out%pearray(starting(1):ending(1), starting(2):ending(2)))
1835 domain_out%pearray=domain_in%pearray
1838 if (
associated(domain_in%tile_id))
then
1839 starting(1) = lbound(domain_in%tile_id,1)
1840 ending(1) = ubound(domain_in%tile_id,1)
1842 allocate(domain_out%tile_id(starting(1):ending(1)))
1843 domain_out%tile_id = domain_in%tile_id
1846 if (
associated(domain_in%tile_id_all))
then
1847 starting(1) = lbound(domain_in%tile_id_all,1)
1848 ending(1) = ubound(domain_in%tile_id_all,1)
1850 allocate(domain_out%tile_id_all(starting(1):ending(1)))
1851 domain_out%tile_id_all = domain_in%tile_id_all
1854 if (
associated(domain_in%list))
then
1855 starting(1) = lbound(domain_in%list,1)
1856 ending(1) = ubound(domain_in%list,1)
1858 allocate(domain_out%list(starting(1):ending(1)))
1859 do i = starting(1), ending(1)
1870 type(domain2d_spec),
intent(in) :: domain2D_spec_in
1871 type(domain2d_spec),
intent(out) :: domain2D_spec_out
1877 domain2d_spec_out%pe = domain2d_spec_in%pe
1878 domain2d_spec_out%pos = domain2d_spec_in%pos
1879 domain2d_spec_out%tile_root_pe = domain2d_spec_in%tile_root_pe
1881 if (
associated(domain2d_spec_in%tile_id))
then
1882 starting = lbound(domain2d_spec_in%tile_id,1)
1883 ending = ubound(domain2d_spec_in%tile_id,1)
1885 if (
associated(domain2d_spec_out%tile_id))
deallocate(domain2d_spec_out%tile_id)
1886 allocate(domain2d_spec_out%tile_id(starting:ending))
1887 domain2d_spec_out%tile_id = domain2d_spec_in%tile_id
1890 if (
associated(domain2d_spec_in%x))
then
1891 starting = lbound(domain2d_spec_in%x,1)
1892 ending = ubound(domain2d_spec_in%x,1)
1894 if (
associated(domain2d_spec_out%x))
deallocate(domain2d_spec_out%x)
1895 allocate(domain2d_spec_out%x(starting:ending))
1896 do i = starting, ending
1901 if (
associated(domain2d_spec_in%y))
then
1902 starting = lbound(domain2d_spec_in%y,1)
1903 ending = ubound(domain2d_spec_in%y,1)
1905 if (
associated(domain2d_spec_out%y))
deallocate(domain2d_spec_out%y)
1906 allocate(domain2d_spec_out%y(starting:ending))
1907 do i = starting, ending
1916 type(domain1d_spec),
intent(in) :: domain1D_spec_in
1917 type(domain1d_spec),
intent(out) :: domain1D_spec_out
1919 domain1d_spec_out%pos = domain1d_spec_in%pos
1927 type(domain_axis_spec),
intent(in) :: domain_axis_spec_in
1928 type(domain_axis_spec),
intent(out) :: domain_axis_spec_out
1930 domain_axis_spec_out%begin = domain_axis_spec_in%begin
1931 domain_axis_spec_out%end = domain_axis_spec_in%end
1932 domain_axis_spec_out%size = domain_axis_spec_in%size
1933 domain_axis_spec_out%max_size = domain_axis_spec_in%max_size
1934 domain_axis_spec_out%is_global = domain_axis_spec_in%is_global
1939 type(mpp_group_update_type),
intent(inout) :: group
1940 type(domain2d),
intent(inout) :: domain
1941 integer :: nscalar, nvector, nlist
1942 integer :: nsend, nrecv, nsend_old, nrecv_old
1943 integer :: nsend_s, nsend_x, nsend_y
1944 integer :: nrecv_s, nrecv_x, nrecv_y
1945 integer :: update_buffer_pos, tot_recv_size, tot_send_size
1946 integer :: msgsize_s, msgsize_x, msgsize_y, msgsize
1947 logical :: recv_s(8), send_s(8)
1948 logical :: recv_x(8), send_x(8), recv_y(8), send_y(8)
1949 integer :: ntot, n, l, m, ksize
1950 integer :: i_s, i_x, i_y, rank_s, rank_x, rank_y, rank
1951 integer :: ind_s(3*MAXOVERLAP)
1952 integer :: ind_x(3*MAXOVERLAP)
1953 integer :: ind_y(3*MAXOVERLAP)
1954 integer :: pelist(3*MAXOVERLAP)
1955 integer :: send_size(3*MAXOVERLAP)
1956 integer :: position_x, position_y, npack, nunpack, dir
1957 integer :: pack_buffer_pos, unpack_buffer_pos
1958 integer :: omp_get_num_threads, nthreads
1959 character(len=8) :: text
1960 type(overlap_type),
pointer :: overPtr => null()
1961 type(overlapspec),
pointer :: update_s => null()
1962 type(overlapspec),
pointer :: update_x => null()
1963 type(overlapspec),
pointer :: update_y => null()
1965 nscalar = group%nscalar
1966 nvector = group%nvector
1969 select case(group%gridtype)
1973 case (bgrid_ne, bgrid_sw)
1976 case (cgrid_ne, cgrid_sw)
1979 case (dgrid_ne, dgrid_sw)
1983 call mpp_error(fatal,
"set_group_update: invalid value of gridtype")
1987 group%shalo_s, group%nhalo_s, group%position)
1991 group%shalo_v, group%nhalo_v, position_x)
1993 group%shalo_v, group%nhalo_v, position_y)
1996 if(nscalar > 0)
then
1997 recv_s = group%recv_s
2000 if(nvector > 0)
then
2001 recv_x = group%recv_x
2003 recv_y = group%recv_y
2006 nlist =
size(domain%list(:))
2007 group%initialized = .true.
2008 nsend_s = 0; nsend_x = 0; nsend_y = 0
2009 nrecv_s = 0; nrecv_x = 0; nrecv_y = 0
2012 if(nscalar > 0)
then
2016 nsend_s = update_s%nsend
2017 nrecv_s = update_s%nrecv
2020 if(nvector.eq.0 .and. nscalar.eq.0)
then
2021 call mpp_error(fatal,
"set_group_update: nscalar and nvector are both 0")
2028 if( nthreads > nthread_control_loop )
then
2029 group%k_loop_inside = .false.
2031 group%k_loop_inside = .true.
2034 if(nvector > 0)
then
2040 nsend_x = update_x%nsend
2041 nrecv_x = update_x%nrecv
2042 nsend_y = update_y%nsend
2043 nrecv_y = update_y%nrecv
2047 ntot = nrecv_s + nrecv_x + nrecv_y
2048 if(ntot > 3*maxoverlap)
call mpp_error(fatal,
"set_group_update: ntot is greater than 3*MAXOVERLAP")
2058 if( i_s <= nrecv_s )
then
2059 rank_s = update_s%recv(i_s)%pe-domain%pe
2060 if(rank_s .LE. 0) rank_s = rank_s + nlist
2064 if( i_x <= nrecv_x )
then
2065 rank_x = update_x%recv(i_x)%pe-domain%pe
2066 if(rank_x .LE. 0) rank_x = rank_x + nlist
2070 if( i_y <= nrecv_y )
then
2071 rank_y = update_y%recv(i_y)%pe-domain%pe
2072 if(rank_y .LE. 0) rank_y = rank_y + nlist
2077 rank = maxval((/rank_s, rank_x, rank_y/))
2078 if(rank == rank_s)
then
2081 pelist(nrecv) = update_s%recv(i_s)%pe
2084 if(rank == rank_x)
then
2087 pelist(nrecv) = update_x%recv(i_x)%pe
2090 if(rank == rank_y)
then
2093 pelist(nrecv) = update_y%recv(i_y)%pe
2100 update_buffer_pos = 0
2109 if(m>0) msgsize_s =
get_mesgsize(update_s%recv(m), recv_s)*ksize*nscalar
2111 if(m>0) msgsize_x =
get_mesgsize(update_x%recv(m), recv_x)*ksize*nvector
2113 if(m>0) msgsize_y =
get_mesgsize(update_y%recv(m), recv_y)*ksize*nvector
2114 msgsize = msgsize_s + msgsize_x + msgsize_y
2115 if( msgsize.GT.0 )
then
2116 tot_recv_size = tot_recv_size + msgsize
2118 if(nrecv > maxoverlap)
then
2119 call mpp_error(fatal,
"set_group_update: nrecv is greater than MAXOVERLAP, increase MAXOVERLAP")
2121 group%from_pe(nrecv) = pelist(l)
2122 group%recv_size(nrecv) = msgsize
2123 group%buffer_pos_recv(nrecv) = update_buffer_pos
2124 update_buffer_pos = update_buffer_pos + msgsize
2131 unpack_buffer_pos = 0
2135 overptr => update_s%recv(m)
2136 do n = 1, overptr%count
2137 dir = overptr%dir(n)
2138 if(recv_s(dir))
then
2139 nunpack = nunpack + 1
2140 if(nunpack > maxoverlap)
call mpp_error(fatal, &
2141 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 1")
2142 group%unpack_type(nunpack) = field_s
2143 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2144 group%unpack_rotation(nunpack) = overptr%rotation(n)
2145 group%unpack_is(nunpack) = overptr%is(n)
2146 group%unpack_ie(nunpack) = overptr%ie(n)
2147 group%unpack_js(nunpack) = overptr%js(n)
2148 group%unpack_je(nunpack) = overptr%je(n)
2149 group%unpack_size(nunpack) = overptr%msgsize(n)*nscalar
2150 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2157 overptr => update_x%recv(m)
2158 do n = 1, overptr%count
2159 dir = overptr%dir(n)
2160 if(recv_x(dir))
then
2161 nunpack = nunpack + 1
2162 if(nunpack > maxoverlap)
call mpp_error(fatal, &
2163 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 2")
2164 group%unpack_type(nunpack) = field_x
2165 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2166 group%unpack_rotation(nunpack) = overptr%rotation(n)
2167 group%unpack_is(nunpack) = overptr%is(n)
2168 group%unpack_ie(nunpack) = overptr%ie(n)
2169 group%unpack_js(nunpack) = overptr%js(n)
2170 group%unpack_je(nunpack) = overptr%je(n)
2171 group%unpack_size(nunpack) = overptr%msgsize(n)*nvector
2172 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2179 overptr => update_y%recv(m)
2180 do n = 1, overptr%count
2181 dir = overptr%dir(n)
2182 if(recv_y(dir))
then
2183 nunpack = nunpack + 1
2184 if(nunpack > maxoverlap)
call mpp_error(fatal, &
2185 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 3")
2186 group%unpack_type(nunpack) = field_y
2187 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2188 group%unpack_rotation(nunpack) = overptr%rotation(n)
2189 group%unpack_is(nunpack) = overptr%is(n)
2190 group%unpack_ie(nunpack) = overptr%ie(n)
2191 group%unpack_js(nunpack) = overptr%js(n)
2192 group%unpack_je(nunpack) = overptr%je(n)
2193 group%unpack_size(nunpack) = overptr%msgsize(n)*nvector
2194 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2199 group%nunpack = nunpack
2201 if(update_buffer_pos .NE. unpack_buffer_pos )
call mpp_error(fatal, &
2202 .NE.
"set_group_update: update_buffer_pos unpack_buffer_pos")
2205 ntot = nsend_s + nsend_x + nsend_y
2215 if( i_s <= nsend_s )
then
2216 rank_s = update_s%send(i_s)%pe-domain%pe
2217 if(rank_s .LT. 0) rank_s = rank_s + nlist
2221 if( i_x <= nsend_x )
then
2222 rank_x = update_x%send(i_x)%pe-domain%pe
2223 if(rank_x .LT. 0) rank_x = rank_x + nlist
2227 if( i_y <= nsend_y )
then
2228 rank_y = update_y%send(i_y)%pe-domain%pe
2229 if(rank_y .LT. 0) rank_y = rank_y + nlist
2234 rank = minval((/rank_s, rank_x, rank_y/))
2235 if(rank == rank_s)
then
2238 pelist(nsend) = update_s%send(i_s)%pe
2241 if(rank == rank_x)
then
2244 pelist(nsend) = update_x%send(i_x)%pe
2247 if(rank == rank_y)
then
2250 pelist(nsend) = update_y%send(i_y)%pe
2263 if(m>0) msgsize_s =
get_mesgsize(update_s%send(m), send_s)*ksize*nscalar
2265 if(m>0) msgsize_x =
get_mesgsize(update_x%send(m), send_x)*ksize*nvector
2267 if(m>0) msgsize_y =
get_mesgsize(update_y%send(m), send_y)*ksize*nvector
2268 msgsize = msgsize_s + msgsize_x + msgsize_y
2269 if( msgsize.GT.0 )
then
2270 tot_send_size = tot_send_size + msgsize
2272 if(nsend > maxoverlap)
then
2273 call mpp_error(fatal,
"set_group_update: nsend is greater than MAXOVERLAP, increase MAXOVERLAP")
2275 send_size(nsend) = msgsize
2276 group%to_pe(nsend) = pelist(l)
2277 group%buffer_pos_send(nsend) = update_buffer_pos
2278 group%send_size(nsend) = msgsize
2279 update_buffer_pos = update_buffer_pos + msgsize
2286 pack_buffer_pos = unpack_buffer_pos
2290 overptr => update_s%send(m)
2291 do n = 1, overptr%count
2292 dir = overptr%dir(n)
2293 if(send_s(dir))
then
2295 if(npack > maxoverlap)
call mpp_error(fatal, &
2296 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 1")
2297 group%pack_type(npack) = field_s
2298 group%pack_buffer_pos(npack) = pack_buffer_pos
2299 group%pack_rotation(npack) = overptr%rotation(n)
2300 group%pack_is(npack) = overptr%is(n)
2301 group%pack_ie(npack) = overptr%ie(n)
2302 group%pack_js(npack) = overptr%js(n)
2303 group%pack_je(npack) = overptr%je(n)
2304 group%pack_size(npack) = overptr%msgsize(n)*nscalar
2305 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2312 overptr => update_x%send(m)
2313 do n = 1, overptr%count
2314 dir = overptr%dir(n)
2316 if( group%nonsym_edge .and. (overptr%rotation(n)==ninety .or. &
2317 overptr%rotation(n)==minus_ninety) )
then
2318 call mpp_error(fatal,
'set_group_update: flags=NONSYMEDGEUPDATE is not compatible '// &
2319 'with 90 or -90 degree rotation (normally cubic sphere grid' )
2321 if(send_x(dir))
then
2323 if(npack > maxoverlap)
call mpp_error(fatal, &
2324 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 2")
2325 group%pack_type(npack) = field_x
2326 group%pack_buffer_pos(npack) = pack_buffer_pos
2327 group%pack_rotation(npack) = overptr%rotation(n)
2328 group%pack_is(npack) = overptr%is(n)
2329 group%pack_ie(npack) = overptr%ie(n)
2330 group%pack_js(npack) = overptr%js(n)
2331 group%pack_je(npack) = overptr%je(n)
2332 group%pack_size(npack) = overptr%msgsize(n)*nvector
2333 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2340 overptr => update_y%send(m)
2341 do n = 1, overptr%count
2342 dir = overptr%dir(n)
2343 if( group%nonsym_edge .and. (overptr%rotation(n)==ninety .or. &
2344 overptr%rotation(n)==minus_ninety) )
then
2345 call mpp_error(fatal,
'set_group_update: flags=NONSYMEDGEUPDATE is not compatible '// &
2346 'with 90 or -90 degree rotation (normally cubic sphere grid' )
2348 if(send_y(dir))
then
2350 if(npack > maxoverlap)
call mpp_error(fatal, &
2351 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 3")
2352 group%pack_type(npack) = field_y
2353 group%pack_buffer_pos(npack) = pack_buffer_pos
2354 group%pack_rotation(npack) = overptr%rotation(n)
2355 group%pack_is(npack) = overptr%is(n)
2356 group%pack_ie(npack) = overptr%ie(n)
2357 group%pack_js(npack) = overptr%js(n)
2358 group%pack_je(npack) = overptr%je(n)
2359 group%pack_size(npack) = overptr%msgsize(n)*nvector
2360 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2366 if(update_buffer_pos .NE. pack_buffer_pos )
call mpp_error(fatal, &
2367 .NE.
"set_group_update: update_buffer_pos pack_buffer_pos")
2370 mpp_domains_stack_hwm = max( mpp_domains_stack_hwm, tot_recv_size+tot_send_size )
2372 if( mpp_domains_stack_hwm.GT.mpp_domains_stack_size )
then
2373 write( text,
'(i8)' )mpp_domains_stack_hwm
2374 call mpp_error( fatal,
'set_group_update: mpp_domains_stack overflow, '// &
2375 'call mpp_domains_set_stack_size('//trim(text)//
') from all PEs.' )
2378 group%tot_msgsize = tot_recv_size+tot_send_size
2385 type(mpp_group_update_type),
intent(inout) :: group
2393 group%initialized = .false.
2395 if (
allocated(group%shape_s))
deallocate(group%shape_s)
2396 if (
allocated(group%shape_x))
deallocate(group%shape_x)
2397 if (
allocated(group%shape_y))
deallocate(group%shape_y)
2403 type(mpp_group_update_type),
intent(in) :: group
2412 type(mpp_group_update_type),
intent(in) :: group
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_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.
subroutine mpp_copy_domain1d_spec(domain1D_spec_in, domain1D_spec_out)
Copies input 1d domain spec to the output 1d domain spec.
logical function mpp_domain1d_ne(a, b)
Set user stack size.
subroutine mpp_get_layout1d(domain, layout)
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_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_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.
type(mpi_comm) function mpp_get_domain_tile_comm(domain)
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.
type(mpi_comm) function mpp_get_domain_comm(domain)
Set user stack size.
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.
integer function mpp_pe()
Returns processor ID.