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
711 type(domain2d),
intent(in) :: domain
714 if(
ASSOCIATED(domain%io_domain))
then
729 type(domain1d),
intent(in) :: domain
730 integer,
intent(out) :: pelist(:)
731 integer,
intent(out),
optional :: pos
734 if( .NOT.module_is_initialized ) &
735 call mpp_error( fatal,
'MPP_GET_PELIST: must first call mpp_domains_init.' )
736 ndivs =
size(domain%list(:))
738 if(
size(pelist(:)).NE.ndivs ) &
739 call mpp_error( fatal,
'MPP_GET_PELIST: pelist array size does not match domain.' )
741 pelist(:) = domain%list(0:ndivs-1)%pe
742 if(
PRESENT(pos) )pos = domain%pos
753 type(domain2d),
intent(in) :: domain
754 integer,
intent(out) :: pelist(:)
755 integer,
intent(out),
optional :: pos
757 if( .NOT.module_is_initialized ) &
758 call mpp_error( fatal,
'MPP_GET_PELIST: must first call mpp_domains_init.' )
759 if(
size(pelist(:)).NE.
size(domain%list(:)) ) &
760 call mpp_error( fatal,
'MPP_GET_PELIST: pelist array size does not match domain.' )
762 pelist(:) = domain%list(:)%pe
763 if(
PRESENT(pos) )pos = domain%pos
773 type(domain1d),
intent(in) :: domain
774 integer,
intent(out) :: layout
776 if( .NOT.module_is_initialized ) &
777 call mpp_error( fatal,
'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
779 layout =
size(domain%list(:))
789 type(domain2d),
intent(in) :: domain
790 integer,
intent(out) :: layout(2)
792 if( .NOT.module_is_initialized ) &
793 call mpp_error( fatal,
'MPP_GET_LAYOUT: must first call mpp_domains_init.' )
795 layout(1) =
size(domain%x(1)%list(:))
796 layout(2) =
size(domain%y(1)%list(:))
811 type(domain2d),
intent(in) :: domain
812 integer,
intent(out) :: ishift, jshift
813 integer,
optional,
intent(in) :: position
816 ishift = 0 ; jshift = 0
818 if(
present(position)) pos = position
820 if(domain%symmetry)
then
823 ishift = 1; jshift = 1
837 type(domain1d),
intent(inout) :: domain
838 integer,
intent(in) :: direction
839 integer,
intent(out) :: pe
841 integer ipos, ipos2, npx
844 npx =
size(domain%list(:))
847 select case (direction)
853 if(domain%cyclic)
then
867 if(ipos2 > npx-1)
then
868 if(domain%cyclic)
then
877 if(ipos2 >= 0) pe = domain%list(ipos2)%pe
885 type(domain2d),
intent(inout) :: domain
886 integer,
intent(in) :: direction
887 integer,
intent(out) :: pe
889 integer ipos, jpos, npx, npy, ix, iy, ipos0, jpos0
892 npx =
size(domain%x(1)%list(:))
893 npy =
size(domain%y(1)%list(:))
894 ipos0 = domain%x(1)%pos
895 jpos0 = domain%y(1)%pos
897 select case (direction)
924 call mpp_error( fatal, &
925 &
'MPP_GET_NEIGHBOR_PE_2D: direction must be either NORTH, ' &
926 & //
'SOUTH, EAST, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST or NORTH_WEST')
933 if( (ipos < 0 .or. ipos > npx-1) .and. domain%x(1)%cyclic )
then
935 ipos = modulo(ipos, npx)
938 if( (ipos < 0 .and. btest(domain%fold,west)) .or. &
939 & (ipos > npx-1 .and. btest(domain%fold,east)) )
then
945 if( (jpos < 0 .or. jpos > npy-1) .and. domain%y(1)%cyclic )
then
947 jpos = modulo(jpos, npy)
950 if( (jpos < 0 .and. btest(domain%fold,south)) .or. &
951 & (jpos > npy-1 .and. btest(domain%fold,north)) )
then
959 if(ipos >= 0 .and. ipos <= npx-1 .and. jpos >= 0 .and. jpos <= npy-1)
then
960 pe = domain%pearray(ipos, jpos)
970 type(domain2d),
intent(inout) :: domain
978 type(domain2d),
intent(in) :: domain
988 type(domain2d),
intent(in) :: domain
1002 type(domain2d),
intent(in) :: domain
1003 integer,
intent(in) :: whalo, ehalo, shalo, nhalo
1008 if(whalo == 0 .AND. ehalo==0 .AND. shalo == 0 .AND. nhalo==0 )
then
1010 if( debug )
call mpp_error(note, &
1011 'mpp_domains_util.inc: halo size to be updated are all zero, no update will be done')
1014 if( (whalo == -domain%whalo .AND. domain%whalo .NE. 0) .or. &
1015 (ehalo == -domain%ehalo .AND. domain%ehalo .NE. 0) .or. &
1016 (shalo == -domain%shalo .AND. domain%shalo .NE. 0) .or. &
1017 (nhalo == -domain%nhalo .AND. domain%nhalo .NE. 0) )
then
1019 call mpp_error(note,
'mpp_domains_util.inc: at least one of w/e/s/n halo size to be updated '// &
1020 'is the inverse of the original halo when defining domain, no update will be done')
1029 type(domain2d),
intent(inout) :: domain
1030 integer,
intent(in) :: whalo, ehalo, shalo, nhalo
1031 integer,
intent(in) :: position
1033 type(overlapspec),
pointer :: update_ref
1034 type(overlapspec),
pointer :: check => null()
1035 integer :: ishift, jshift, shift
1037 shift = 0;
if(domain%symmetry) shift = 1
1038 select case(position)
1040 update_ref => domain%update_T
1041 ishift = 0; jshift = 0
1043 update_ref => domain%update_C
1044 ishift = shift; jshift = shift
1046 update_ref => domain%update_N
1047 ishift = 0; jshift = shift
1049 update_ref => domain%update_E
1050 ishift = shift; jshift = 0
1052 call mpp_error(fatal,
"mpp_domains_util.inc(search_update_overlap): position should be CENTER|CORNER|EAST|NORTH")
1066 if(domain%fold .NE. 0)
then
1068 ishift, jshift, 0, 0, whalo, ehalo, shalo, nhalo)
1079 update_ref => null()
1086 type(domain2d),
intent(in) :: domain
1087 integer,
intent(in) :: position
1090 select case(position)
1100 call mpp_error(fatal,
"mpp_domains_util.inc(search_check_overlap): position should be CENTER|CORNER|EAST|NORTH")
1108 type(domain2d),
intent(in) :: domain
1109 integer,
intent(in) :: position
1112 select case(position)
1122 call mpp_error(fatal,
"mpp_domains_util.inc(search_bound_overlap): position should be CENTER|CORNER|EAST|NORTH")
1130 type(domain2d),
intent(in) :: domain
1141 type(domain2d),
intent(in) :: domain
1142 integer,
intent(inout) :: tiles(:)
1145 if(
size(tiles(:)).NE.
size(domain%list(:)) ) &
1146 call mpp_error( fatal,
'mpp_get_tile_list: tiles array size does not match domain.' )
1147 do i = 1,
size(tiles(:))
1148 if(
size(domain%list(i-1)%tile_id(:)) > 1)
call mpp_error( fatal, &
1149 'mpp_get_tile_list: only support one-tile-per-pe now, contact developer');
1150 tiles(i) = domain%list(i-1)%tile_id(1)
1158 type(domain2d),
intent(in) :: domain
1169 type(domain2d),
intent(in) :: domain
1182 type(domain2d),
intent(in) :: domain
1192 type(domain2d),
intent(in) :: domain
1198 if(
size(domain%tile_id(:)) > 1)
then
1202 tile = domain%tile_id(1)
1203 do i = 0,
size(domain%list(:))-1
1213 type(domain2d),
intent(in) :: domain
1214 integer,
intent(inout) :: pelist(:)
1215 integer :: npes_on_tile
1216 integer :: i, tile, pos
1219 if(
size(pelist(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1220 "mpp_domains_util.inc(mpp_get_tile_pelist): size(pelist) does not equal npes on current tile")
1221 tile = domain%tile_id(1)
1223 do i = 0,
size(domain%list(:))-1
1224 if(tile == domain%list(i)%tile_id(1))
then
1226 pelist(pos) = domain%list(i)%pe
1236 type(domain2d),
intent(in) :: domain
1237 integer,
intent(out),
dimension(:) :: xbegin, xend, ybegin, yend
1238 integer,
intent(in ),
optional :: position
1240 integer :: i, ishift, jshift
1241 integer :: npes_on_tile, pos, tile
1246 if( .NOT.module_is_initialized ) &
1247 call mpp_error( fatal,
'mpp_get_compute_domains2D: must first call mpp_domains_init.' )
1250 if(
size(xbegin(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1251 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(xbegin) does not equal npes on current tile")
1252 if(
size(xend(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1253 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(xend) does not equal npes on current tile")
1254 if(
size(ybegin(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1255 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(ybegin) does not equal npes on current tile")
1256 if(
size(yend(:)) .NE. npes_on_tile)
call mpp_error(fatal, &
1257 "mpp_domains_util.inc(mpp_get_compute_domains2D): size(yend) does not equal npes on current tile")
1259 tile = domain%tile_id(1)
1261 do i = 0,
size(domain%list(:))-1
1262 if(tile == domain%list(i)%tile_id(1))
then
1264 xbegin(pos) = domain%list(i)%x(1)%compute%begin
1265 xend(pos) = domain%list(i)%x(1)%compute%end + ishift
1266 ybegin(pos) = domain%list(i)%y(1)%compute%begin
1267 yend(pos) = domain%list(i)%y(1)%compute%end + jshift
1279 type(domain2d),
intent(in) :: domain
1280 integer,
intent(in) :: action
1281 integer,
intent(in) :: p
1282 integer,
optional,
intent(in) :: position
1284 type(overlapspec),
pointer :: update => null()
1288 if(
present(position)) pos = position
1291 update => domain%update_T
1293 update => domain%update_C
1295 update => domain%update_E
1297 update => domain%update_N
1299 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_num_overlap): invalid option of position")
1302 if(action == event_send)
then
1303 if(p< 1 .OR. p > update%nsend)
call mpp_error( fatal, &
1304 "mpp_domains_mod(mpp_get_num_overlap): p should be between 1 and update%nsend")
1306 else if(action == event_recv)
then
1307 if(p< 1 .OR. p > update%nrecv)
call mpp_error( fatal, &
1308 "mpp_domains_mod(mpp_get_num_overlap): p should be between 1 and update%nrecv")
1311 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_num_overlap): invalid option of action")
1318 type(domain2d),
intent(in) :: domain
1319 integer,
intent(out) :: nsend, nrecv
1320 integer,
optional,
intent(in) :: position
1324 if(
present(position)) pos = position
1327 nsend = domain%update_T%nsend
1328 nrecv = domain%update_T%nrecv
1330 nsend = domain%update_C%nsend
1331 nrecv = domain%update_C%nrecv
1333 nsend = domain%update_E%nsend
1334 nrecv = domain%update_E%nrecv
1336 nsend = domain%update_N%nsend
1337 nrecv = domain%update_N%nrecv
1339 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_size): invalid option of position")
1346 type(domain2d),
intent(in) :: domain
1347 integer,
intent(in) :: action
1348 integer,
intent(inout) :: pelist(:)
1349 integer,
optional,
intent(in) :: position
1350 type(overlapspec),
pointer :: update => null()
1354 if(
present(position)) pos = position
1357 update => domain%update_T
1359 update => domain%update_C
1361 update => domain%update_E
1363 update => domain%update_N
1365 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_pelist): invalid option of position")
1368 if(action == event_send)
then
1369 if(
size(pelist) .NE. update%nsend)
call mpp_error( fatal, &
1370 "mpp_domains_mod(mpp_get_update_pelist): size of pelist does not match update%nsend")
1371 do p = 1, update%nsend
1372 pelist(p) = update%send(p)%pe
1374 else if(action == event_recv)
then
1375 if(
size(pelist) .NE. update%nrecv)
call mpp_error( fatal, &
1376 "mpp_domains_mod(mpp_get_update_pelist): size of pelist does not match update%nrecv")
1377 do p = 1, update%nrecv
1378 pelist(p) = update%recv(p)%pe
1381 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_update_pelist): invalid option of action")
1388 type(domain2d),
intent(in) :: domain
1389 integer,
intent(in) :: action
1390 integer,
intent(in) :: p
1391 integer,
dimension(:),
intent(out) :: is, ie, js, je
1392 integer,
dimension(:),
intent(out) :: dir, rot
1393 integer,
optional,
intent(in) :: position
1394 type(overlapspec),
pointer :: update => null()
1395 type(overlap_type),
pointer :: overlap => null()
1396 integer :: count, pos
1399 if(
present(position)) pos = position
1402 update => domain%update_T
1404 update => domain%update_C
1406 update => domain%update_E
1408 update => domain%update_N
1410 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_overlap): invalid option of position")
1413 if(action == event_send)
then
1414 overlap => update%send(p)
1415 else if(action == event_recv)
then
1416 overlap => update%recv(p)
1418 call mpp_error( fatal,
"mpp_domains_mod(mpp_get_overlap): invalid option of action")
1421 count = overlap%count
1422 if(
size(is(:)) .NE. count .OR.
size(ie(:)) .NE. count .OR.
size(js(:)) .NE. count .OR. &
1423 size(je(:)) .NE. count .OR.
size(dir(:)) .NE. count .OR.
size(rot(:)) .NE. count ) &
1424 call mpp_error( fatal, &
1425 &
"mpp_domains_mod(mpp_get_overlap): size mismatch between number of overlap and array size")
1427 is = overlap%is (1:count)
1428 ie = overlap%ie (1:count)
1429 js = overlap%js (1:count)
1430 je = overlap%je (1:count)
1431 dir = overlap%dir (1:count)
1432 rot = overlap%rotation(1:count)
1441 type(domain2d),
intent(in) :: domain
1450 type(domain2d),
intent(in) :: domain
1458 type(domain2d),
intent(in) :: domain
1469 type(domain2d),
intent(in) :: domain
1470 integer,
intent(out) :: pelist(:)
1473 if(
size(pelist(:)) .NE.
size(domain%list(:)) )
then
1474 call mpp_error(fatal, .NE.
"mpp_get_domain_pelist: size(pelist(:)) size(domain%list(:)) ")
1477 do p = 0,
size(domain%list(:))-1
1478 pelist(p+1) = domain%list(p)%pe
1487 type(domain2d),
intent(in) :: domain
1495 function get_rank_send(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1496 type(domain2d),
intent(in) :: domain
1497 type(overlapspec),
intent(in) :: overlap_x, overlap_y
1498 integer,
intent(out) :: rank_x, rank_y, ind_x, ind_y
1500 integer :: nlist, nsend_x, nsend_y
1502 nlist =
size(domain%list(:))
1503 nsend_x = overlap_x%nsend
1504 nsend_y = overlap_y%nsend
1507 if(nsend_x>0) rank_x = overlap_x%send(1)%pe - domain%pe
1508 if(nsend_y>0) rank_y = overlap_y%send(1)%pe - domain%pe
1509 if(rank_x .LT. 0) rank_x = rank_x + nlist
1510 if(rank_y .LT. 0) rank_y = rank_y + nlist
1515 if(nsend_x>0) ind_x = 1
1516 if(nsend_y>0) ind_y = 1
1522 function get_rank_recv(domain, overlap_x, overlap_y, rank_x, rank_y, ind_x, ind_y)
1523 type(domain2d),
intent(in) :: domain
1524 type(overlapspec),
intent(in) :: overlap_x, overlap_y
1525 integer,
intent(out) :: rank_x, rank_y, ind_x, ind_y
1527 integer :: nlist, nrecv_x, nrecv_y
1529 nlist =
size(domain%list(:))
1530 nrecv_x = overlap_x%nrecv
1531 nrecv_y = overlap_y%nrecv
1535 rank_x = overlap_x%recv(1)%pe - domain%pe
1536 if(rank_x .LE. 0) rank_x = rank_x + nlist
1539 rank_y = overlap_y%recv(1)%pe - domain%pe
1540 if(rank_y .LE. 0) rank_y = rank_y + nlist
1546 if(nrecv_x>0) ind_x = 1
1547 if(nrecv_y>0) ind_y = 1
1553 type(domain2d),
intent(in) :: domain
1554 type(overlapspec),
intent(in) :: update_x, update_y
1555 integer,
intent(out) :: ind_x(:), ind_y(:)
1556 integer,
intent(out) :: start_pos(:)
1557 integer,
intent(out) :: pelist(:)
1558 integer :: nlist, nrecv_x, nrecv_y, ntot, n
1559 integer :: ix, iy, rank_x, rank_y, cur_pos
1562 nlist =
size(domain%list(:))
1563 nrecv_x = update_x%nrecv
1564 nrecv_y = update_y%nrecv
1566 ntot = nrecv_x + nrecv_y
1576 if(ix <= nrecv_x )
then
1577 rank_x = update_x%recv(ix)%pe-domain%pe
1578 if(rank_x .LE. 0) rank_x = rank_x + nlist
1582 if(iy <= nrecv_y )
then
1583 rank_y = update_y%recv(iy)%pe-domain%pe
1584 if(rank_y .LE. 0) rank_y = rank_y + nlist
1590 if( rank_x == rank_y )
then
1594 cur_pos = cur_pos + update_x%recv(ix)%totsize + update_y%recv(iy)%totsize
1598 else if ( rank_x > rank_y )
then
1602 cur_pos = cur_pos + update_x%recv(ix)%totsize
1605 else if ( rank_y > rank_x )
then
1609 cur_pos = cur_pos + update_y%recv(iy)%totsize
1619 type(domain2d),
intent(in) :: domain
1620 type(overlapspec),
intent(in) :: update_x, update_y
1621 integer,
intent(out) :: ind_x(:), ind_y(:)
1622 integer,
intent(out) :: start_pos(:)
1623 integer,
intent(out) :: pelist(:)
1624 integer :: nlist, nsend_x, nsend_y, ntot, n
1625 integer :: ix, iy, rank_x, rank_y, cur_pos
1628 nlist =
size(domain%list(:))
1629 nsend_x = update_x%nsend
1630 nsend_y = update_y%nsend
1632 ntot = nsend_x + nsend_y
1641 if(ix <= nsend_x )
then
1642 rank_x = update_x%send(ix)%pe-domain%pe
1643 if(rank_x .LT. 0) rank_x = rank_x + nlist
1647 if(iy <= nsend_y )
then
1648 rank_y = update_y%send(iy)%pe-domain%pe
1649 if(rank_y .LT. 0) rank_y = rank_y + nlist
1656 if( rank_x == rank_y )
then
1660 cur_pos = cur_pos + update_x%send(ix)%totsize + update_y%send(iy)%totsize
1664 else if ( rank_x < rank_y )
then
1668 cur_pos = cur_pos + update_x%send(ix)%totsize
1671 else if ( rank_y < rank_x )
then
1675 cur_pos = cur_pos + update_y%send(iy)%totsize
1687 type(domain2d),
intent(in) :: domain
1688 type(overlapspec),
intent(in) :: overlap_x, overlap_y
1689 integer,
intent(out) :: rank_x, rank_y, ind_x, ind_y
1691 integer :: nlist, nrecv_x, nrecv_y
1693 nlist =
size(domain%list(:))
1694 nrecv_x = overlap_x%nrecv
1695 nrecv_y = overlap_y%nrecv
1699 if(nrecv_x>0) rank_x = overlap_x%recv(nrecv_x)%pe - domain%pe
1700 if(nrecv_y>0) rank_y = overlap_y%recv(nrecv_y)%pe - domain%pe
1701 if(rank_x .LE.0) rank_x = rank_x + nlist
1702 if(rank_y .LE.0) rank_y = rank_y + nlist
1708 if(nrecv_x >0) ind_x = nrecv_x
1709 if(nrecv_y >0) ind_y = nrecv_y
1715 type(overlap_type),
intent(in) :: overlap
1716 logical,
intent(in) :: do_dir(:)
1721 do n = 1, overlap%count
1722 dir = overlap%dir(n)
1723 if(do_dir(dir))
then
1732 type(domain2d),
intent(inout) :: domain
1733 logical,
intent(in ) :: symmetry
1735 domain%symmetry = symmetry
1741 type(domain1d),
intent(in) :: domain_in
1742 type(domain1d),
intent(inout) :: domain_out
1748 domain_out%compute = domain_in%compute
1749 domain_out%domain_data = domain_in%domain_data
1750 domain_out%global = domain_in%global
1751 domain_out%memory = domain_in%memory
1752 domain_out%cyclic = domain_in%cyclic
1753 domain_out%pe = domain_in%pe
1754 domain_out%pos = domain_in%pos
1756 if (
associated(domain_in%list))
then
1757 starting = lbound(domain_in%list, 1)
1758 ending = ubound(domain_in%list, 1)
1759 if (
associated(domain_out%list))
deallocate(domain_out%list)
1760 allocate(domain_out%list(starting:ending))
1762 do i = starting, ending
1773 type(domain2d),
intent(in) :: domain_in
1774 type(domain2d),
intent(inout) :: domain_out
1778 integer :: starting(2)
1779 integer :: ending(2)
1781 if (
associated(domain_out%x))
then
1782 call mpp_error(fatal,
"mpp_copy_domain: domain_out is already set")
1785 domain_out%id = domain_in%id
1786 domain_out%pe = domain_in%pe
1787 domain_out%fold = domain_in%fold
1788 domain_out%pos = domain_in%pos
1789 domain_out%symmetry = domain_in%symmetry
1790 domain_out%whalo = domain_in%whalo
1791 domain_out%ehalo = domain_in%ehalo
1792 domain_out%shalo = domain_in%shalo
1793 domain_out%nhalo = domain_in%nhalo
1794 domain_out%ntiles = domain_in%ntiles
1795 domain_out%max_ntile_pe = domain_in%max_ntile_pe
1796 domain_out%ncontacts = domain_in%ncontacts
1797 domain_out%rotated_ninety = domain_in%rotated_ninety
1798 domain_out%initialized = domain_in%initialized
1799 domain_out%tile_root_pe = domain_in%tile_root_pe
1800 domain_out%io_layout = domain_in%io_layout
1801 domain_out%name = domain_in%name
1803 ntiles =
size(domain_in%x(:))
1804 allocate(domain_out%x(ntiles), domain_out%y(ntiles), domain_out%tile_id(ntiles) )
1810 if (
associated(domain_in%pearray))
then
1811 starting = lbound(domain_in%pearray)
1812 ending = ubound(domain_in%pearray)
1814 allocate(domain_out%pearray(starting(1):ending(1), starting(2):ending(2)))
1815 domain_out%pearray=domain_in%pearray
1818 if (
associated(domain_in%tile_id))
then
1819 starting(1) = lbound(domain_in%tile_id,1)
1820 ending(1) = ubound(domain_in%tile_id,1)
1822 allocate(domain_out%tile_id(starting(1):ending(1)))
1823 domain_out%tile_id = domain_in%tile_id
1826 if (
associated(domain_in%tile_id_all))
then
1827 starting(1) = lbound(domain_in%tile_id_all,1)
1828 ending(1) = ubound(domain_in%tile_id_all,1)
1830 allocate(domain_out%tile_id_all(starting(1):ending(1)))
1831 domain_out%tile_id_all = domain_in%tile_id_all
1834 if (
associated(domain_in%list))
then
1835 starting(1) = lbound(domain_in%list,1)
1836 ending(1) = ubound(domain_in%list,1)
1838 allocate(domain_out%list(starting(1):ending(1)))
1839 do i = starting(1), ending(1)
1850 type(domain2d_spec),
intent(in) :: domain2D_spec_in
1851 type(domain2d_spec),
intent(out) :: domain2D_spec_out
1857 domain2d_spec_out%pe = domain2d_spec_in%pe
1858 domain2d_spec_out%pos = domain2d_spec_in%pos
1859 domain2d_spec_out%tile_root_pe = domain2d_spec_in%tile_root_pe
1861 if (
associated(domain2d_spec_in%tile_id))
then
1862 starting = lbound(domain2d_spec_in%tile_id,1)
1863 ending = ubound(domain2d_spec_in%tile_id,1)
1865 if (
associated(domain2d_spec_out%tile_id))
deallocate(domain2d_spec_out%tile_id)
1866 allocate(domain2d_spec_out%tile_id(starting:ending))
1867 domain2d_spec_out%tile_id = domain2d_spec_in%tile_id
1870 if (
associated(domain2d_spec_in%x))
then
1871 starting = lbound(domain2d_spec_in%x,1)
1872 ending = ubound(domain2d_spec_in%x,1)
1874 if (
associated(domain2d_spec_out%x))
deallocate(domain2d_spec_out%x)
1875 allocate(domain2d_spec_out%x(starting:ending))
1876 do i = starting, ending
1881 if (
associated(domain2d_spec_in%y))
then
1882 starting = lbound(domain2d_spec_in%y,1)
1883 ending = ubound(domain2d_spec_in%y,1)
1885 if (
associated(domain2d_spec_out%y))
deallocate(domain2d_spec_out%y)
1886 allocate(domain2d_spec_out%y(starting:ending))
1887 do i = starting, ending
1896 type(domain1d_spec),
intent(in) :: domain1D_spec_in
1897 type(domain1d_spec),
intent(out) :: domain1D_spec_out
1899 domain1d_spec_out%pos = domain1d_spec_in%pos
1907 type(domain_axis_spec),
intent(in) :: domain_axis_spec_in
1908 type(domain_axis_spec),
intent(out) :: domain_axis_spec_out
1910 domain_axis_spec_out%begin = domain_axis_spec_in%begin
1911 domain_axis_spec_out%end = domain_axis_spec_in%end
1912 domain_axis_spec_out%size = domain_axis_spec_in%size
1913 domain_axis_spec_out%max_size = domain_axis_spec_in%max_size
1914 domain_axis_spec_out%is_global = domain_axis_spec_in%is_global
1919 type(mpp_group_update_type),
intent(inout) :: group
1920 type(domain2d),
intent(inout) :: domain
1921 integer :: nscalar, nvector, nlist
1922 integer :: nsend, nrecv, nsend_old, nrecv_old
1923 integer :: nsend_s, nsend_x, nsend_y
1924 integer :: nrecv_s, nrecv_x, nrecv_y
1925 integer :: update_buffer_pos, tot_recv_size, tot_send_size
1926 integer :: msgsize_s, msgsize_x, msgsize_y, msgsize
1927 logical :: recv_s(8), send_s(8)
1928 logical :: recv_x(8), send_x(8), recv_y(8), send_y(8)
1929 integer :: ntot, n, l, m, ksize
1930 integer :: i_s, i_x, i_y, rank_s, rank_x, rank_y, rank
1931 integer :: ind_s(3*MAXOVERLAP)
1932 integer :: ind_x(3*MAXOVERLAP)
1933 integer :: ind_y(3*MAXOVERLAP)
1934 integer :: pelist(3*MAXOVERLAP)
1935 integer :: send_size(3*MAXOVERLAP)
1936 integer :: position_x, position_y, npack, nunpack, dir
1937 integer :: pack_buffer_pos, unpack_buffer_pos
1938 integer :: omp_get_num_threads, nthreads
1939 character(len=8) :: text
1940 type(overlap_type),
pointer :: overPtr => null()
1941 type(overlapspec),
pointer :: update_s => null()
1942 type(overlapspec),
pointer :: update_x => null()
1943 type(overlapspec),
pointer :: update_y => null()
1945 nscalar = group%nscalar
1946 nvector = group%nvector
1949 select case(group%gridtype)
1953 case (bgrid_ne, bgrid_sw)
1956 case (cgrid_ne, cgrid_sw)
1959 case (dgrid_ne, dgrid_sw)
1963 call mpp_error(fatal,
"set_group_update: invalid value of gridtype")
1967 group%shalo_s, group%nhalo_s, group%position)
1971 group%shalo_v, group%nhalo_v, position_x)
1973 group%shalo_v, group%nhalo_v, position_y)
1976 if(nscalar > 0)
then
1977 recv_s = group%recv_s
1980 if(nvector > 0)
then
1981 recv_x = group%recv_x
1983 recv_y = group%recv_y
1986 nlist =
size(domain%list(:))
1987 group%initialized = .true.
1988 nsend_s = 0; nsend_x = 0; nsend_y = 0
1989 nrecv_s = 0; nrecv_x = 0; nrecv_y = 0
1991 if(nscalar > 0)
then
1995 nsend_s = update_s%nsend
1996 nrecv_s = update_s%nrecv
2000 if(nvector > 0 .AND. nscalar > 0)
then
2001 if(group%ksize_s .NE. group%ksize_v)
then
2002 call mpp_error(fatal,
"set_group_update: ksize_s and ksize_v are not equal")
2004 ksize = group%ksize_s
2005 else if (nscalar > 0)
then
2006 ksize = group%ksize_s
2007 else if (nvector > 0)
then
2008 ksize = group%ksize_v
2010 call mpp_error(fatal,
"set_group_update: nscalar and nvector are all 0")
2017 if( nthreads > nthread_control_loop )
then
2018 group%k_loop_inside = .false.
2020 group%k_loop_inside = .true.
2023 if(nvector > 0)
then
2029 nsend_x = update_x%nsend
2030 nrecv_x = update_x%nrecv
2031 nsend_y = update_y%nsend
2032 nrecv_y = update_y%nrecv
2036 ntot = nrecv_s + nrecv_x + nrecv_y
2037 if(ntot > 3*maxoverlap)
call mpp_error(fatal,
"set_group_update: ntot is greater than 3*MAXOVERLAP")
2047 if( i_s <= nrecv_s )
then
2048 rank_s = update_s%recv(i_s)%pe-domain%pe
2049 if(rank_s .LE. 0) rank_s = rank_s + nlist
2053 if( i_x <= nrecv_x )
then
2054 rank_x = update_x%recv(i_x)%pe-domain%pe
2055 if(rank_x .LE. 0) rank_x = rank_x + nlist
2059 if( i_y <= nrecv_y )
then
2060 rank_y = update_y%recv(i_y)%pe-domain%pe
2061 if(rank_y .LE. 0) rank_y = rank_y + nlist
2066 rank = maxval((/rank_s, rank_x, rank_y/))
2067 if(rank == rank_s)
then
2070 pelist(nrecv) = update_s%recv(i_s)%pe
2073 if(rank == rank_x)
then
2076 pelist(nrecv) = update_x%recv(i_x)%pe
2079 if(rank == rank_y)
then
2082 pelist(nrecv) = update_y%recv(i_y)%pe
2089 update_buffer_pos = 0
2098 if(m>0) msgsize_s =
get_mesgsize(update_s%recv(m), recv_s)*ksize*nscalar
2100 if(m>0) msgsize_x =
get_mesgsize(update_x%recv(m), recv_x)*ksize*nvector
2102 if(m>0) msgsize_y =
get_mesgsize(update_y%recv(m), recv_y)*ksize*nvector
2103 msgsize = msgsize_s + msgsize_x + msgsize_y
2104 if( msgsize.GT.0 )
then
2105 tot_recv_size = tot_recv_size + msgsize
2107 if(nrecv > maxoverlap)
then
2108 call mpp_error(fatal,
"set_group_update: nrecv is greater than MAXOVERLAP, increase MAXOVERLAP")
2110 group%from_pe(nrecv) = pelist(l)
2111 group%recv_size(nrecv) = msgsize
2112 group%buffer_pos_recv(nrecv) = update_buffer_pos
2113 update_buffer_pos = update_buffer_pos + msgsize
2120 unpack_buffer_pos = 0
2124 overptr => update_s%recv(m)
2125 do n = 1, overptr%count
2126 dir = overptr%dir(n)
2127 if(recv_s(dir))
then
2128 nunpack = nunpack + 1
2129 if(nunpack > maxoverlap)
call mpp_error(fatal, &
2130 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 1")
2131 group%unpack_type(nunpack) = field_s
2132 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2133 group%unpack_rotation(nunpack) = overptr%rotation(n)
2134 group%unpack_is(nunpack) = overptr%is(n)
2135 group%unpack_ie(nunpack) = overptr%ie(n)
2136 group%unpack_js(nunpack) = overptr%js(n)
2137 group%unpack_je(nunpack) = overptr%je(n)
2138 group%unpack_size(nunpack) = overptr%msgsize(n)*nscalar
2139 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2146 overptr => update_x%recv(m)
2147 do n = 1, overptr%count
2148 dir = overptr%dir(n)
2149 if(recv_x(dir))
then
2150 nunpack = nunpack + 1
2151 if(nunpack > maxoverlap)
call mpp_error(fatal, &
2152 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 2")
2153 group%unpack_type(nunpack) = field_x
2154 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2155 group%unpack_rotation(nunpack) = overptr%rotation(n)
2156 group%unpack_is(nunpack) = overptr%is(n)
2157 group%unpack_ie(nunpack) = overptr%ie(n)
2158 group%unpack_js(nunpack) = overptr%js(n)
2159 group%unpack_je(nunpack) = overptr%je(n)
2160 group%unpack_size(nunpack) = overptr%msgsize(n)*nvector
2161 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2168 overptr => update_y%recv(m)
2169 do n = 1, overptr%count
2170 dir = overptr%dir(n)
2171 if(recv_y(dir))
then
2172 nunpack = nunpack + 1
2173 if(nunpack > maxoverlap)
call mpp_error(fatal, &
2174 "set_group_update: nunpack is greater than MAXOVERLAP, increase MAXOVERLAP 3")
2175 group%unpack_type(nunpack) = field_y
2176 group%unpack_buffer_pos(nunpack) = unpack_buffer_pos
2177 group%unpack_rotation(nunpack) = overptr%rotation(n)
2178 group%unpack_is(nunpack) = overptr%is(n)
2179 group%unpack_ie(nunpack) = overptr%ie(n)
2180 group%unpack_js(nunpack) = overptr%js(n)
2181 group%unpack_je(nunpack) = overptr%je(n)
2182 group%unpack_size(nunpack) = overptr%msgsize(n)*nvector
2183 unpack_buffer_pos = unpack_buffer_pos + group%unpack_size(nunpack)*ksize
2188 group%nunpack = nunpack
2190 if(update_buffer_pos .NE. unpack_buffer_pos )
call mpp_error(fatal, &
2191 .NE.
"set_group_update: update_buffer_pos unpack_buffer_pos")
2194 ntot = nsend_s + nsend_x + nsend_y
2204 if( i_s <= nsend_s )
then
2205 rank_s = update_s%send(i_s)%pe-domain%pe
2206 if(rank_s .LT. 0) rank_s = rank_s + nlist
2210 if( i_x <= nsend_x )
then
2211 rank_x = update_x%send(i_x)%pe-domain%pe
2212 if(rank_x .LT. 0) rank_x = rank_x + nlist
2216 if( i_y <= nsend_y )
then
2217 rank_y = update_y%send(i_y)%pe-domain%pe
2218 if(rank_y .LT. 0) rank_y = rank_y + nlist
2223 rank = minval((/rank_s, rank_x, rank_y/))
2224 if(rank == rank_s)
then
2227 pelist(nsend) = update_s%send(i_s)%pe
2230 if(rank == rank_x)
then
2233 pelist(nsend) = update_x%send(i_x)%pe
2236 if(rank == rank_y)
then
2239 pelist(nsend) = update_y%send(i_y)%pe
2252 if(m>0) msgsize_s =
get_mesgsize(update_s%send(m), send_s)*ksize*nscalar
2254 if(m>0) msgsize_x =
get_mesgsize(update_x%send(m), send_x)*ksize*nvector
2256 if(m>0) msgsize_y =
get_mesgsize(update_y%send(m), send_y)*ksize*nvector
2257 msgsize = msgsize_s + msgsize_x + msgsize_y
2258 if( msgsize.GT.0 )
then
2259 tot_send_size = tot_send_size + msgsize
2261 if(nsend > maxoverlap)
then
2262 call mpp_error(fatal,
"set_group_update: nsend is greater than MAXOVERLAP, increase MAXOVERLAP")
2264 send_size(nsend) = msgsize
2265 group%to_pe(nsend) = pelist(l)
2266 group%buffer_pos_send(nsend) = update_buffer_pos
2267 group%send_size(nsend) = msgsize
2268 update_buffer_pos = update_buffer_pos + msgsize
2275 pack_buffer_pos = unpack_buffer_pos
2279 overptr => update_s%send(m)
2280 do n = 1, overptr%count
2281 dir = overptr%dir(n)
2282 if(send_s(dir))
then
2284 if(npack > maxoverlap)
call mpp_error(fatal, &
2285 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 1")
2286 group%pack_type(npack) = field_s
2287 group%pack_buffer_pos(npack) = pack_buffer_pos
2288 group%pack_rotation(npack) = overptr%rotation(n)
2289 group%pack_is(npack) = overptr%is(n)
2290 group%pack_ie(npack) = overptr%ie(n)
2291 group%pack_js(npack) = overptr%js(n)
2292 group%pack_je(npack) = overptr%je(n)
2293 group%pack_size(npack) = overptr%msgsize(n)*nscalar
2294 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2301 overptr => update_x%send(m)
2302 do n = 1, overptr%count
2303 dir = overptr%dir(n)
2305 if( group%nonsym_edge .and. (overptr%rotation(n)==ninety .or. &
2306 overptr%rotation(n)==minus_ninety) )
then
2307 call mpp_error(fatal,
'set_group_update: flags=NONSYMEDGEUPDATE is not compatible '// &
2308 'with 90 or -90 degree rotation (normally cubic sphere grid' )
2310 if(send_x(dir))
then
2312 if(npack > maxoverlap)
call mpp_error(fatal, &
2313 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 2")
2314 group%pack_type(npack) = field_x
2315 group%pack_buffer_pos(npack) = pack_buffer_pos
2316 group%pack_rotation(npack) = overptr%rotation(n)
2317 group%pack_is(npack) = overptr%is(n)
2318 group%pack_ie(npack) = overptr%ie(n)
2319 group%pack_js(npack) = overptr%js(n)
2320 group%pack_je(npack) = overptr%je(n)
2321 group%pack_size(npack) = overptr%msgsize(n)*nvector
2322 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2329 overptr => update_y%send(m)
2330 do n = 1, overptr%count
2331 dir = overptr%dir(n)
2332 if( group%nonsym_edge .and. (overptr%rotation(n)==ninety .or. &
2333 overptr%rotation(n)==minus_ninety) )
then
2334 call mpp_error(fatal,
'set_group_update: flags=NONSYMEDGEUPDATE is not compatible '// &
2335 'with 90 or -90 degree rotation (normally cubic sphere grid' )
2337 if(send_y(dir))
then
2339 if(npack > maxoverlap)
call mpp_error(fatal, &
2340 "set_group_update: npack is greater than MAXOVERLAP, increase MAXOVERLAP 3")
2341 group%pack_type(npack) = field_y
2342 group%pack_buffer_pos(npack) = pack_buffer_pos
2343 group%pack_rotation(npack) = overptr%rotation(n)
2344 group%pack_is(npack) = overptr%is(n)
2345 group%pack_ie(npack) = overptr%ie(n)
2346 group%pack_js(npack) = overptr%js(n)
2347 group%pack_je(npack) = overptr%je(n)
2348 group%pack_size(npack) = overptr%msgsize(n)*nvector
2349 pack_buffer_pos = pack_buffer_pos + group%pack_size(npack)*ksize
2355 if(update_buffer_pos .NE. pack_buffer_pos )
call mpp_error(fatal, &
2356 .NE.
"set_group_update: update_buffer_pos pack_buffer_pos")
2359 mpp_domains_stack_hwm = max( mpp_domains_stack_hwm, tot_recv_size+tot_send_size )
2361 if( mpp_domains_stack_hwm.GT.mpp_domains_stack_size )
then
2362 write( text,
'(i8)' )mpp_domains_stack_hwm
2363 call mpp_error( fatal,
'set_group_update: mpp_domains_stack overflow, '// &
2364 'call mpp_domains_set_stack_size('//trim(text)//
') from all PEs.' )
2367 group%tot_msgsize = tot_recv_size+tot_send_size
2374 type(mpp_group_update_type),
intent(inout) :: group
2382 group%initialized = .false.
2388 type(mpp_group_update_type),
intent(in) :: group
2397 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.