37 integer,
intent(in) :: n
38 character(len=8) :: text
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) )
46 mpp_domains_stack_size = n
48 if(
mpp_pe().EQ.mpp_root_pe() )
call mpp_error( note,
'MPP_DOMAINS_SET_STACK_SIZE: stack size set to '//text//
'.' )
62 type(domain1d),
intent(in) :: a, b
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 )
80 type(domain1d),
intent(in) :: a, b
88 type(domain2d),
intent(in) :: a, b
97 if(
mpp_domain2d_eq .AND. ((a%pe.EQ.null_pe).OR.(b%pe.EQ.null_pe)) )
return
112 type(domain2d),
intent(in) :: a, b
125 type(domain1d),
intent(in) :: domain
126 integer,
intent(out),
optional :: begin, end, size, max_size
127 logical,
intent(out),
optional :: is_global
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
139 type(domain1d),
intent(in) :: domain
140 integer,
intent(out),
optional :: begin, end, size, max_size
141 logical,
intent(out),
optional :: is_global
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
153 type(domain1d),
intent(in) :: domain
154 integer,
intent(out),
optional :: begin, end, size, max_size
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
165 type(domain1d),
intent(in) :: domain
166 integer,
intent(out),
optional :: begin, end, size, max_size
167 logical,
intent(out),
optional :: is_global
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
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
187 if(
present(tile_count)) tile = tile_count
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 )
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
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
212 if(
present(tile_count)) tile = tile_count
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 )
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
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
236 if(
present(tile_count)) tile = tile_count
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 )
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
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
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 )
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
277 type(domain_axis_spec),
intent(inout) :: grid
279 grid%begin = 2*grid%begin-1
280 grid%end = 2*grid%end+1
281 grid%size = grid%end-grid%begin+1
294 type(domain2d),
intent(inout) :: domain
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, &
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, &
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)
315 do i=1,
size(domain%list(:))
327 do i=1,
size(domain%x(1)%list)
331 do i=1,
size(domain%y(1)%list)
339 type(domain1d),
intent(inout) :: domain
340 integer,
intent(in),
optional :: begin, end, size
341 logical,
intent(in),
optional :: is_global
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
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
360 if(
present(tile_count)) tile = tile_count
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)
369 type(domain1d),
intent(inout) :: domain
370 integer,
intent(in),
optional :: begin, end, size
371 logical,
intent(in),
optional :: is_global
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
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
390 if(
present(tile_count)) tile = tile_count
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)
399 type(domain1d),
intent(inout) :: domain
400 integer,
intent(in),
optional :: begin, end, size
402 if(
present(begin)) domain%global%begin = begin
403 if(
present(
end)) domain%global%end = end
404 if(
present(size)) domain%global%size =
size
410 type(domain2d),
intent(inout) :: domain
411 integer,
intent(in),
optional :: xbegin, xend, ybegin, yend, xsize, ysize
412 integer,
intent(in),
optional :: tile_count
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)
432 type(domain2d),
intent(in) :: domain
433 type(domain1d),
intent(inout),
optional :: x, y
434 integer,
intent(in),
optional :: tile_count
438 if(
present(tile_count)) tile = tile_count
439 if(
PRESENT(x) )x = domain%x(tile)
440 if(
PRESENT(y) )y = domain%y(tile)
446 type(domain1d),
intent(in) :: domain
447 integer,
intent(out),
optional,
dimension(:) :: begin, end, size
449 if( .NOT.module_is_initialized ) &
450 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: must first call mpp_domains_init.' )
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
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
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
472 type(domain2d),
intent(in) :: domain
473 integer,
intent(out),
optional,
dimension(:) :: xbegin, xend, xsize, ybegin, yend, ysize
474 integer,
intent(in ),
optional :: position
476 integer :: i, ishift, jshift
481 if( .NOT.module_is_initialized ) &
482 call mpp_error( fatal,
'MPP_GET_COMPUTE_DOMAINS: must first call mpp_domains_init.' )
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
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
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
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
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
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
531 type(domain1d),
intent(in) :: domain
532 integer,
intent(out),
optional,
dimension(:) :: begin, end, size
534 if( .NOT.module_is_initialized ) &
535 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: must first call mpp_domains_init.' )
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
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
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
558 type(domain2d),
intent(in) :: domain
559 integer,
intent(out),
optional,
dimension(:) :: xbegin, xend, xsize, ybegin, yend, ysize
560 integer,
intent(in ),
optional :: position
562 integer :: i, ishift, jshift
567 if( .NOT.module_is_initialized ) &
568 call mpp_error( fatal,
'MPP_GET_GLOBAL_DOMAINS: must first call mpp_domains_init.' )
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
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
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
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
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
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
618 type(domain2d),
intent(in) :: domain
619 integer,
dimension(0:),
intent(inout) :: xextent, yextent
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
633 do n = 0,
size(domain%y(1)%list(:))-1
634 yextent(n) = domain%y(1)%list(n)%compute%size
642 type(domain2d),
intent(in) :: domain
643 integer,
dimension(:,:),
intent(inout) :: xextent, yextent
644 integer :: ntile, nlist, n, m, ndivx, ndivy, tile, pos
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)
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")
658 xextent = 0; yextent=0
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
675 type(domain2d),
intent(in) :: domain
685 type(domain2d),
intent(in) :: domain
694 type(domain2d),
intent(in) :: domain
703 type(domain2d),
intent(in) :: domain
712 type(domain2d),
intent(in) :: domain
715 if(
ASSOCIATED(domain%io_domain))
then
730 type(domain1d),
intent(in) :: domain
731 integer,
intent(out) :: pelist(:)
732 integer,
intent(out),
optional :: pos
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(:))
739 if(
size(pelist(:)).NE.ndivs ) &
740 call mpp_error( fatal,
'MPP_GET_PELIST: pelist array size does not match domain.' )
742 pelist(:) = domain%list(0:ndivs-1)%pe
743 if(
PRESENT(pos) )pos = domain%pos
754 type(domain2d),
intent(in) :: domain
755 integer,
intent(out) :: pelist(:)
756 integer,
intent(out),
optional :: pos
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.' )
763 pelist(:) = domain%list(:)%pe
764 if(
PRESENT(pos) )pos = domain%pos
774 type(domain1d),
intent(in) :: domain
775 integer,
intent(out) :: layout
777 if( .NOT.module_is_initialized ) &
778 call mpp_error( fatal,
'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
780 layout =
size(domain%list(:))
790 type(domain2d),
intent(in) :: domain
791 integer,
intent(out) :: layout(2)
793 if( .NOT.module_is_initialized ) &
794 call mpp_error( fatal,
'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
796 layout(1) =
size(domain%x(1)%list(:))
797 layout(2) =
size(domain%y(1)%list(:))
812 type(domain2d),
intent(in) :: domain
813 integer,
intent(out) :: ishift, jshift
814 integer,
optional,
intent(in) :: position
817 ishift = 0 ; jshift = 0
819 if(
present(position)) pos = position
821 if(domain%symmetry)
then
824 ishift = 1; jshift = 1
838 type(domain1d),
intent(inout) :: domain
839 integer,
intent(in) :: direction
840 integer,
intent(out) :: pe
842 integer ipos, ipos2, npx
845 npx =
size(domain%list(:))
848 select case (direction)
854 if(domain%cyclic)
then
868 if(ipos2 > npx-1)
then
869 if(domain%cyclic)
then
878 if(ipos2 >= 0) pe = domain%list(ipos2)%pe
886 type(domain2d),
intent(inout) :: domain
887 integer,
intent(in) :: direction
888 integer,
intent(out) :: pe
890 integer ipos, jpos, npx, npy, ix, iy, ipos0, jpos0
893 npx =
size(domain%x(1)%list(:))
894 npy =
size(domain%y(1)%list(:))
895 ipos0 = domain%x(1)%pos
896 jpos0 = domain%y(1)%pos
898 select case (direction)
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')
934 if( (ipos < 0 .or. ipos > npx-1) .and. domain%x(1)%cyclic )
then
936 ipos = modulo(ipos, npx)
939 if( (ipos < 0 .and. btest(domain%fold,west)) .or. &
940 & (ipos > npx-1 .and. btest(domain%fold,east)) )
then
946 if( (jpos < 0 .or. jpos > npy-1) .and. domain%y(1)%cyclic )
then
948 jpos = modulo(jpos, npy)
951 if( (jpos < 0 .and. btest(domain%fold,south)) .or. &
952 & (jpos > npy-1 .and. btest(domain%fold,north)) )
then
960 if(ipos >= 0 .and. ipos <= npx-1 .and. jpos >= 0 .and. jpos <= npy-1)
then
961 pe = domain%pearray(ipos, jpos)
971 type(domain2d),
intent(inout) :: domain
979 type(domain2d),
intent(in) :: domain
989 type(domain2d),
intent(in) :: domain
1003 type(domain2d),
intent(in) :: domain
1004 integer,
intent(in) :: whalo, ehalo, shalo, nhalo
1009 if(whalo == 0 .AND. ehalo==0 .AND. shalo == 0 .AND. nhalo==0 )
then
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')
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
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')
1030 type(domain2d),
intent(inout) :: domain
1031 integer,
intent(in) :: whalo, ehalo, shalo, nhalo
1032 integer,
intent(in) :: position
1034 type(overlapspec),
pointer :: update_ref
1035 type(overlapspec),
pointer :: check => null()
1036 integer :: ishift, jshift, shift
1038 shift = 0;
if(domain%symmetry) shift = 1
1039 select case(position)
1041 update_ref => domain%update_T
1042 ishift = 0; jshift = 0
1044 update_ref => domain%update_C
1045 ishift = shift; jshift = shift
1047 update_ref => domain%update_N
1048 ishift = 0; jshift = shift
1050 update_ref => domain%update_E
1051 ishift = shift; jshift = 0
1053 call mpp_error(fatal,
"mpp_domains_util.inc(search_update_overlap): position should be CENTER|CORNER|EAST|NORTH")
1067 if(domain%fold .NE. 0)
then
1069 ishift, jshift, 0, 0, whalo, ehalo, shalo, nhalo)
1080 update_ref => null()
1087 type(domain2d),
intent(in) :: domain
1088 integer,
intent(in) :: position
1091 select case(position)
1101 call mpp_error(fatal,
"mpp_domains_util.inc(search_check_overlap): position should be CENTER|CORNER|EAST|NORTH")
1109 type(domain2d),
intent(in) :: domain
1110 integer,
intent(in) :: position
1113 select case(position)
1123 call mpp_error(fatal,
"mpp_domains_util.inc(search_bound_overlap): position should be CENTER|CORNER|EAST|NORTH")
1131 type(domain2d),
intent(in) :: domain
1142 type(domain2d),
intent(in) :: domain
1143 integer,
intent(inout) :: tiles(:)
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)
1159 type(domain2d),
intent(in) :: domain
1170 type(domain2d),
intent(in) :: domain
1183 type(domain2d),
intent(in) :: domain
1193 type(domain2d),
intent(in) :: domain
1199 if(
size(domain%tile_id(:)) > 1)
then
1203 tile = domain%tile_id(1)
1204 do i = 0,
size(domain%list(:))-1
1214 type(domain2d),
intent(in) :: domain
1215 integer,
intent(inout) :: pelist(:)
1216 integer :: npes_on_tile
1217 integer :: i, tile, pos
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)
1224 do i = 0,
size(domain%list(:))-1
1225 if(tile == domain%list(i)%tile_id(1))
then
1227 pelist(pos) = domain%list(i)%pe
1237 type(domain2d),
intent(in) :: domain
1238 integer,
intent(out),
dimension(:) :: xbegin, xend, ybegin, yend
1239 integer,
intent(in ),
optional :: position
1241 integer :: i, ishift, jshift
1242 integer :: npes_on_tile, pos, tile
1247 if( .NOT.module_is_initialized ) &
1248 call mpp_error( fatal,
'mpp_get_compute_domains2D: must first call mpp_domains_init.' )
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")
1260 tile = domain%tile_id(1)
1262 do i = 0,
size(domain%list(:))-1
1263 if(tile == domain%list(i)%tile_id(1))
then
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
1280 type(domain2d),
intent(in) :: domain
1281 integer,
intent(in) :: action
1282 integer,
intent(in) :: p
1283 integer,
optional,
intent(in) :: position
1285 type(overlapspec),
pointer :: update => null()
1289 if(
present(position)) pos = position
1292 update => domain%update_T
1294 update => domain%update_C
1296 update => domain%update_E
1298 update => domain%update_N
1300 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_num_overlap): invalid option of position")
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")
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")
1312 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_num_overlap): invalid option of action")
1319 type(domain2d),
intent(in) :: domain
1320 integer,
intent(out) :: nsend, nrecv
1321 integer,
optional,
intent(in) :: position
1325 if(
present(position)) pos = position
1328 nsend = domain%update_T%nsend
1329 nrecv = domain%update_T%nrecv
1331 nsend = domain%update_C%nsend
1332 nrecv = domain%update_C%nrecv
1334 nsend = domain%update_E%nsend
1335 nrecv = domain%update_E%nrecv
1337 nsend = domain%update_N%nsend
1338 nrecv = domain%update_N%nrecv
1340 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_size): invalid option of 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()
1355 if(
present(position)) pos = position
1358 update => domain%update_T
1360 update => domain%update_C
1362 update => domain%update_E
1364 update => domain%update_N
1366 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_pelist): invalid option of position")
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
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
1382 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_pelist): invalid option of action")
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
1400 if(
present(position)) pos = position
1403 update => domain%update_T
1405 update => domain%update_C
1407 update => domain%update_E
1409 update => domain%update_N
1411 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_overlap): invalid option of position")
1414 if(action == event_send)
then
1415 overlap => update%send(p)
1416 else if(action == event_recv)
then
1417 overlap => update%recv(p)
1419 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_overlap): invalid option of action")
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")
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)
1442 type(domain2d),
intent(in) :: domain
1451 type(domain2d),
intent(in) :: domain
1459 type(domain2d),
intent(in) :: domain
1470 type(domain2d),
intent(in) :: domain
1471 integer,
intent(out) :: pelist(:)
1474 if(
size(pelist(:)) .NE.
size(domain%list(:)) )
then
1475 call mpp_error(fatal, .NE.
"mpp_get_domain_pelist: size(pelist(:)) size(domain%list(:)) ")
1478 do p = 0,
size(domain%list(:))-1
1479 pelist(p+1) = domain%list(p)%pe
1488 type(domain2d),
intent(in) :: domain
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
1501 integer :: nlist, nsend_x, nsend_y
1503 nlist =
size(domain%list(:))
1504 nsend_x = overlap_x%nsend
1505 nsend_y = overlap_y%nsend
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
1516 if(nsend_x>0) ind_x = 1
1517 if(nsend_y>0) ind_y = 1
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
1528 integer :: nlist, nrecv_x, nrecv_y
1530 nlist =
size(domain%list(:))
1531 nrecv_x = overlap_x%nrecv
1532 nrecv_y = overlap_y%nrecv
1536 rank_x = overlap_x%recv(1)%pe - domain%pe
1537 if(rank_x .LE. 0) rank_x = rank_x + nlist
1540 rank_y = overlap_y%recv(1)%pe - domain%pe
1541 if(rank_y .LE. 0) rank_y = rank_y + nlist
1547 if(nrecv_x>0) ind_x = 1
1548 if(nrecv_y>0) ind_y = 1
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
1563 nlist =
size(domain%list(:))
1564 nrecv_x = update_x%nrecv
1565 nrecv_y = update_y%nrecv
1567 ntot = nrecv_x + nrecv_y
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
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
1591 if( rank_x == rank_y )
then
1595 cur_pos = cur_pos + update_x%recv(ix)%totsize + update_y%recv(iy)%totsize
1599 else if ( rank_x > rank_y )
then
1603 cur_pos = cur_pos + update_x%recv(ix)%totsize
1606 else if ( rank_y > rank_x )
then
1610 cur_pos = cur_pos + update_y%recv(iy)%totsize
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
1629 nlist =
size(domain%list(:))
1630 nsend_x = update_x%nsend
1631 nsend_y = update_y%nsend
1633 ntot = nsend_x + nsend_y
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
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
1657 if( rank_x == rank_y )
then
1661 cur_pos = cur_pos + update_x%send(ix)%totsize + update_y%send(iy)%totsize
1665 else if ( rank_x < rank_y )
then
1669 cur_pos = cur_pos + update_x%send(ix)%totsize
1672 else if ( rank_y < rank_x )
then
1676 cur_pos = cur_pos + update_y%send(iy)%totsize
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
1692 integer :: nlist, nrecv_x, nrecv_y
1694 nlist =
size(domain%list(:))
1695 nrecv_x = overlap_x%nrecv
1696 nrecv_y = overlap_y%nrecv
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
1709 if(nrecv_x >0) ind_x = nrecv_x
1710 if(nrecv_y >0) ind_y = nrecv_y
1716 type(overlap_type),
intent(in) :: overlap
1717 logical,
intent(in) :: do_dir(:)
1722 do n = 1, overlap%count
1723 dir = overlap%dir(n)
1724 if(do_dir(dir))
then
1733 type(domain2d),
intent(inout) :: domain
1734 logical,
intent(in ) :: symmetry
1736 domain%symmetry = symmetry
1742 type(domain1d),
intent(in) :: domain_in
1743 type(domain1d),
intent(inout) :: domain_out
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
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)
1761 allocate(domain_out%list(starting:ending))
1763 do i = starting, ending
1774 type(domain2d),
intent(in) :: domain_in
1775 type(domain2d),
intent(inout) :: domain_out
1779 integer :: starting(2)
1780 integer :: ending(2)
1782 if (
associated(domain_out%x))
then
1783 call mpp_error(fatal,
"mpp_copy_domain: domain_out is already set")
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
1804 ntiles =
size(domain_in%x(:))
1805 allocate(domain_out%x(ntiles), domain_out%y(ntiles), domain_out%tile_id(ntiles) )
1811 if (
associated(domain_in%pearray))
then
1812 starting = lbound(domain_in%pearray)
1813 ending = ubound(domain_in%pearray)
1815 allocate(domain_out%pearray(starting(1):ending(1), starting(2):ending(2)))
1816 domain_out%pearray=domain_in%pearray
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)
1823 allocate(domain_out%tile_id(starting(1):ending(1)))
1824 domain_out%tile_id = domain_in%tile_id
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)
1831 allocate(domain_out%tile_id_all(starting(1):ending(1)))
1832 domain_out%tile_id_all = domain_in%tile_id_all
1835 if (
associated(domain_in%list))
then
1836 starting(1) = lbound(domain_in%list,1)
1837 ending(1) = ubound(domain_in%list,1)
1839 allocate(domain_out%list(starting(1):ending(1)))
1840 do i = starting(1), ending(1)
1851 type(domain2d_spec),
intent(in) :: domain2D_spec_in
1852 type(domain2d_spec),
intent(out) :: domain2D_spec_out
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
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)
1866 if (
associated(domain2d_spec_out%tile_id))
deallocate(domain2d_spec_out%tile_id)
1867 allocate(domain2d_spec_out%tile_id(starting:ending))
1868 domain2d_spec_out%tile_id = domain2d_spec_in%tile_id
1871 if (
associated(domain2d_spec_in%x))
then
1872 starting = lbound(domain2d_spec_in%x,1)
1873 ending = ubound(domain2d_spec_in%x,1)
1875 if (
associated(domain2d_spec_out%x))
deallocate(domain2d_spec_out%x)
1876 allocate(domain2d_spec_out%x(starting:ending))
1877 do i = starting, ending
1882 if (
associated(domain2d_spec_in%y))
then
1883 starting = lbound(domain2d_spec_in%y,1)
1884 ending = ubound(domain2d_spec_in%y,1)
1886 if (
associated(domain2d_spec_out%y))
deallocate(domain2d_spec_out%y)
1887 allocate(domain2d_spec_out%y(starting:ending))
1888 do i = starting, ending
1897 type(domain1d_spec),
intent(in) :: domain1D_spec_in
1898 type(domain1d_spec),
intent(out) :: domain1D_spec_out
1900 domain1d_spec_out%pos = domain1d_spec_in%pos
1908 type(domain_axis_spec),
intent(in) :: domain_axis_spec_in
1909 type(domain_axis_spec),
intent(out) :: domain_axis_spec_out
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
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()
1946 nscalar = group%nscalar
1947 nvector = group%nvector
1950 select case(group%gridtype)
1954 case (bgrid_ne, bgrid_sw)
1957 case (cgrid_ne, cgrid_sw)
1960 case (dgrid_ne, dgrid_sw)
1964 call mpp_error(fatal,
"set_group_update: invalid value of gridtype")
1968 group%shalo_s, group%nhalo_s, group%position)
1972 group%shalo_v, group%nhalo_v, position_x)
1974 group%shalo_v, group%nhalo_v, position_y)
1977 if(nscalar > 0)
then
1978 recv_s = group%recv_s
1981 if(nvector > 0)
then
1982 recv_x = group%recv_x
1984 recv_y = group%recv_y
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
1992 if(nscalar > 0)
then
1996 nsend_s = update_s%nsend
1997 nrecv_s = update_s%nrecv
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")
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
2011 call mpp_error(fatal,
"set_group_update: nscalar and nvector are all 0")
2018 if( nthreads > nthread_control_loop )
then
2019 group%k_loop_inside = .false.
2021 group%k_loop_inside = .true.
2024 if(nvector > 0)
then
2030 nsend_x = update_x%nsend
2031 nrecv_x = update_x%nrecv
2032 nsend_y = update_y%nsend
2033 nrecv_y = update_y%nrecv
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")
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
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
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
2067 rank = maxval((/rank_s, rank_x, rank_y/))
2068 if(rank == rank_s)
then
2071 pelist(nrecv) = update_s%recv(i_s)%pe
2074 if(rank == rank_x)
then
2077 pelist(nrecv) = update_x%recv(i_x)%pe
2080 if(rank == rank_y)
then
2083 pelist(nrecv) = update_y%recv(i_y)%pe
2090 update_buffer_pos = 0
2099 if(m>0) msgsize_s =
get_mesgsize(update_s%recv(m), recv_s)*ksize*nscalar
2101 if(m>0) msgsize_x =
get_mesgsize(update_x%recv(m), recv_x)*ksize*nvector
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
2108 if(nrecv > maxoverlap)
then
2109 call mpp_error(fatal,
"set_group_update: nrecv is greater than MAXOVERLAP, increase MAXOVERLAP")
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
2121 unpack_buffer_pos = 0
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
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
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
2189 group%nunpack = nunpack
2191 if(update_buffer_pos .NE. unpack_buffer_pos )
call mpp_error(fatal, &
2192 .NE.
"set_group_update: update_buffer_pos unpack_buffer_pos")
2195 ntot = nsend_s + nsend_x + nsend_y
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
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
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
2224 rank = minval((/rank_s, rank_x, rank_y/))
2225 if(rank == rank_s)
then
2228 pelist(nsend) = update_s%send(i_s)%pe
2231 if(rank == rank_x)
then
2234 pelist(nsend) = update_x%send(i_x)%pe
2237 if(rank == rank_y)
then
2240 pelist(nsend) = update_y%send(i_y)%pe
2253 if(m>0) msgsize_s =
get_mesgsize(update_s%send(m), send_s)*ksize*nscalar
2255 if(m>0) msgsize_x =
get_mesgsize(update_x%send(m), send_x)*ksize*nvector
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
2262 if(nsend > maxoverlap)
then
2263 call mpp_error(fatal,
"set_group_update: nsend is greater than MAXOVERLAP, increase MAXOVERLAP")
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
2276 pack_buffer_pos = unpack_buffer_pos
2280 overptr => update_s%send(m)
2281 do n = 1, overptr%count
2282 dir = overptr%dir(n)
2283 if(send_s(dir))
then
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
2302 overptr => update_x%send(m)
2303 do n = 1, overptr%count
2304 dir = overptr%dir(n)
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' )
2311 if(send_x(dir))
then
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
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' )
2338 if(send_y(dir))
then
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
2356 if(update_buffer_pos .NE. pack_buffer_pos )
call mpp_error(fatal, &
2357 .NE.
"set_group_update: update_buffer_pos pack_buffer_pos")
2360 mpp_domains_stack_hwm = max( mpp_domains_stack_hwm, tot_recv_size+tot_send_size )
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.' )
2368 group%tot_msgsize = tot_recv_size+tot_send_size
2375 type(mpp_group_update_type),
intent(inout) :: group
2383 group%initialized = .false.
2389 type(mpp_group_update_type),
intent(in) :: group
2398 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.
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.
integer function mpp_pe()
Returns processor ID.