4 !***********************************************************************
5 !* GNU Lesser General Public License
7 !* This file is part of the GFDL Flexible Modeling System (FMS).
9 !* FMS is free software: you can redistribute it and/or modify it under
10 !* the terms of the GNU Lesser General Public License as published by
11 !* the Free Software Foundation, either version 3 of the License, or (at
12 !* your option) any later version.
14 !* FMS is distributed in the hope that it will be useful, but WITHOUT
15 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 !* You should have received a copy of the GNU Lesser General Public
20 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
21 !***********************************************************************
24 !> @ingroup mpp_domains_mod
25 !> @brief Various routines handling domains in @ref mpp_domains_mod
27 ! <SUBROUTINE NAME="mpp_define_layout2D" INTERFACE="mpp_define_layout">
28 ! <IN NAME="global_indices" TYPE="integer" DIM="(4)"></IN>
29 ! <IN NAME="ndivs" TYPE="integer"></IN>
30 ! <OUT NAME="layout" TYPE="integer" DIM="(2)"></OUT>
32 !> @brief Instantiates a layout with the given indices and divisions
33 subroutine mpp_define_layout2D( global_indices, ndivs, layout )
34 integer, intent(in) :: global_indices(:) !< (/ isg, ieg, jsg, jeg /); Defines the global domain.
35 integer, intent(in) :: ndivs !< number of divisions to divide global domain
36 integer, intent(out) :: layout(:)
38 integer :: isg, ieg, jsg, jeg, isz, jsz, idiv, jdiv
40 if(size(global_indices(:)) .NE. 4) call mpp_error(FATAL,"mpp_define_layout2D: size of global_indices should be 4")
41 if(size(layout(:)) .NE. 2) call mpp_error(FATAL,"mpp_define_layout2D: size of layout should be 2")
43 isg = global_indices(1)
44 ieg = global_indices(2)
45 jsg = global_indices(3)
46 jeg = global_indices(4)
50 !first try to divide ndivs in the domain aspect ratio: if imperfect aspect, reduce idiv till it divides ndivs
51 idiv = nint( sqrt(float(ndivs*isz)/jsz) )
52 idiv = max(idiv,1) !for isz=1 line above can give 0
53 do while( mod(ndivs,idiv).NE.0 )
55 end do !will terminate at idiv=1 if not before
58 layout = (/ idiv, jdiv /)
60 end subroutine mpp_define_layout2D
62 !############################################################################
63 ! <SUBROUTINE NAME="mpp_define_mosaic_pelist">
64 ! <IN NAME="global_indices" TYPE="integer" DIM="(4)"></IN>
65 ! <IN NAME="pelist" TYPE="integer" DIM="(0:)"> </IN>
67 ! NOTE: The following routine may need to revised to improve the capability.
68 ! It is very hard to make it balance for all the situation.
69 ! Hopefully some smart idea will come up someday.
70 subroutine mpp_define_mosaic_pelist( sizes, pe_start, pe_end, pelist, costpertile)
71 integer, dimension(:), intent(in) :: sizes
72 integer, dimension(:), intent(inout) :: pe_start, pe_end
73 integer, dimension(:), intent(in), optional :: pelist, costpertile
74 integer, dimension(size(sizes(:))) :: costs
75 integer, dimension(:), allocatable :: pes
76 integer :: ntiles, npes, totcosts, avgcost
77 integer :: ntiles_left, npes_left, pos, n, tile
78 integer :: cost_on_tile, cost_on_pe, npes_used, errunit
80 ntiles = size(sizes(:))
81 if(size(pe_start(:)) .NE. ntiles .OR. size(pe_end(:)) .NE. ntiles ) then
82 call mpp_error(FATAL, "mpp_define_mosaic_pelist: size mismatch between pe_start/pe_end and sizes")
85 if(present(costpertile)) then
86 if(size(costpertile(:)) .NE. ntiles ) then
87 call mpp_error(FATAL, "mpp_define_mosaic_pelist: size mismatch between costpertile and sizes")
89 costs = sizes*costpertile
94 if( PRESENT(pelist) )then
95 if( .NOT.any(pelist.EQ.mpp_pe()) )then
97 write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
98 call mpp_error( FATAL, 'mpp_define_mosaic_pelist: pe must be in pelist.' )
100 npes = size(pelist(:))
101 allocate( pes(0:npes-1) )
105 allocate( pes(0:npes-1) )
106 call mpp_get_current_pelist(pes)
113 do while( ntiles_left > 0 )
114 if( npes_left == 1 ) then ! all left tiles will on the last processor, imbalance possibly.
116 if(costs(n) > 0) then
125 totcosts = sum(costs)
126 avgcost = CEILING(real(totcosts)/npes_left )
127 tile = minval(maxloc(costs))
128 cost_on_tile = costs(tile)
130 ntiles_left = ntiles_left - 1
132 totcosts = totcosts - cost_on_tile
133 if(cost_on_tile .GE. avgcost ) then
134 npes_used = min(ceiling(real(cost_on_tile)/avgcost), npes_left)
135 if( ntiles_left > 0 .AND. npes_used == npes_left ) npes_used = npes_used - 1
136 pe_end(tile) = pos + npes_used - 1
137 npes_left = npes_left - npes_used
138 pos = pos + npes_used
140 !--- find other tiles to share the pe
142 cost_on_pe = cost_on_tile
143 do while(ntiles_left>npes_left) ! make sure all the pes are used.
144 tile = minval(minloc(costs, costs> 0 ))
145 cost_on_tile = costs(tile)
146 cost_on_pe = cost_on_pe + cost_on_tile
147 if(cost_on_pe > avgcost ) exit
150 ntiles_left = ntiles_left - 1
152 totcosts = totcosts - cost_on_tile
154 npes_left = npes_left - 1
160 if(npes_left .NE. 0 ) call mpp_error(FATAL, "mpp_define_mosaic_pelist: the left npes should be zero")
163 end subroutine mpp_define_mosaic_pelist
165 !-- The following implementation is different from mpp_compute_extents
166 !-- The last block might have most points
167 subroutine mpp_compute_block_extent(isg,ieg,ndivs,ibegin,iend)
168 integer, intent(in) :: isg, ieg, ndivs
169 integer, dimension(:), intent(out) :: ibegin, iend
176 !domain is sized by dividing remaining points by remaining domains
177 is = ie - CEILING( REAL(ie-isg+1)/ndiv ) + 1
181 if( ie.LT.is )call mpp_error( FATAL, &
182 'MPP_DEFINE_DOMAINS(mpp_compute_block_extent): domain extents must be positive definite.' )
183 if( ndiv.EQ.1 .AND. ibegin(ndiv) .NE. isg ) &
184 call mpp_error( FATAL, 'mpp_compute_block_extent: domain extents do not span space completely.' )
188 end subroutine mpp_compute_block_extent
191 !#####################################################################
192 subroutine mpp_compute_extent(isg,ieg,ndivs,ibegin,iend, extent )
193 integer, intent(in) :: isg, ieg, ndivs
194 integer, dimension(0:), intent(out) :: ibegin, iend
195 integer, dimension(0:), intent(in), optional :: extent
197 integer :: ndiv, imax, ndmax, ndmirror
199 logical :: symmetrize, use_extent
202 even(n) = (mod(n,2).EQ.0)
203 odd (n) = (mod(n,2).EQ.1)
206 if(PRESENT(extent)) then
207 if( size(extent(:)).NE.ndivs ) &
208 call mpp_error( FATAL, 'mpp_compute_extent: extent array size must equal number of domain divisions.' )
210 if(ALL(extent ==0)) use_extent = .false.
217 if(extent(ndiv) .LE. 0) call mpp_error( FATAL, &
218 & 'mpp_compute_extent: domain extents must be positive definite.' )
219 iend(ndiv) = ibegin(ndiv) + extent(ndiv) - 1
220 ibegin(ndiv+1) = iend(ndiv) + 1
222 iend(ndivs-1) = ibegin(ndivs-1) + extent(ndivs-1) - 1
223 if(iend(ndivs-1) .NE. ieg) call mpp_error(FATAL, &
224 & 'mpp_compute_extent: extent array limits do not match global domain.' )
227 !modified for mirror-symmetry
229 ! ie = is + CEILING( float(ieg-is+1)/(ndivs-ndiv) ) - 1
231 !problem of dividing nx points into n domains maintaining symmetry
232 !i.e nx=18 n=4 4554 and 5445 are solutions but 4455 is not.
233 !this will always work for nx even n even or odd
234 !this will always work for nx odd, n odd
235 !this will never work for nx odd, n even: for this case we supersede the mirror calculation
236 ! symmetrize = .NOT. ( mod(ndivs,2).EQ.0 .AND. mod(ieg-isg+1,2).EQ.1 )
237 !nx even n odd fails if n>nx/2
238 symmetrize = ( even(ndivs) .AND. even(ieg-isg+1) ) .OR. &
239 ( odd(ndivs) .AND. odd(ieg-isg+1) ) .OR. &
240 ( odd(ndivs) .AND. even(ieg-isg+1) .AND. ndivs.LT.(ieg-isg+1)/2 )
242 !mirror domains are stored in the list and retrieved if required.
244 !initialize max points and max domains
248 !do bottom half of decomposition, going over the midpoint for odd ndivs
249 if( ndiv.LT.(ndivs-1)/2+1 )then
250 !domain is sized by dividing remaining points by remaining domains
251 ie = is + CEILING( REAL(imax-is+1)/(ndmax-ndiv) ) - 1
252 ndmirror = (ndivs-1) - ndiv !mirror domain
253 if( ndmirror.GT.ndiv .AND. symmetrize )then !only for domains over the midpoint
254 !mirror extents, the max(,) is to eliminate overlaps
255 ibegin(ndmirror) = max( isg+ieg-ie, ie+1 )
256 iend(ndmirror) = max( isg+ieg-is, ie+1 )
257 imax = ibegin(ndmirror) - 1
262 !do top half of decomposition by retrieving saved values
266 ie = is + CEILING( REAL(imax-is+1)/(ndmax-ndiv) ) - 1
271 if( ie.LT.is )call mpp_error( FATAL, &
272 'MPP_DEFINE_DOMAINS(mpp_compute_extent): domain extents must be positive definite.' )
273 if( ndiv.EQ.ndivs-1 .AND. iend(ndiv).NE.ieg ) &
274 call mpp_error( FATAL, 'mpp_compute_extent: domain extents do not span space completely.' )
280 end subroutine mpp_compute_extent
282 !#####################################################################
284 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
286 !>@brief MPP_DEFINE_DOMAINS: define layout and decomposition !
288 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
290 !> @brief MPP_DEFINE_DOMAINS: define layout and decomposition !
292 !> Routine to divide global array indices among domains, and assign domains to PEs
293 subroutine mpp_define_domains1D( global_indices, ndivs, domain, pelist, flags, halo, extent, maskmap, &
294 memory_size, begin_halo, end_halo )
295 integer, intent(in) :: global_indices(:) !< (/ isg, ieg /) gives the extent of global domain
296 integer, intent(in) :: ndivs !< number of divisions of domain: even divisions unless extent is present.
297 type(domain1D), intent(inout) :: domain !< the returned domain1D; declared inout so that
298 !! existing links, if any, can be nullified
299 integer, intent(in), optional :: pelist(0:) !< list of PEs to which domains are to be assigned
300 !! (default 0...npes-1); size of pelist must
301 !! correspond to number of mask=.TRUE. divisions
302 integer, intent(in), optional :: flags, halo !< flags define whether compute and data domains
303 !! are global (undecomposed) and whether the global
304 !! domain has periodic boundaries.
305 !! halo defines halo width (currently the same on both sides)
306 integer, intent(in), optional :: extent(0:) !< array extent; defines width of each division
307 !! (used for non-uniform domain decomp, for e.g load-balancing)
308 logical, intent(in), optional :: maskmap(0:) !< a division whose maskmap=.FALSE. is not
309 !! assigned to any domain. By default we assume
310 !! decomposition of compute and data domains, non-periodic boundaries,
311 !! no halo, as close to uniform extents as the
312 !! input parameters permit
313 integer, intent(in), optional :: memory_size
314 integer, intent(in), optional :: begin_halo, end_halo
316 logical :: compute_domain_is_global, data_domain_is_global
317 integer :: ndiv, n, isg, ieg
318 integer, allocatable :: pes(:)
319 integer :: ibegin(0:ndivs-1), iend(0:ndivs-1)
320 logical :: mask(0:ndivs-1)
321 integer :: halosz, halobegin, haloend
324 if( .NOT.module_is_initialized )call mpp_error( FATAL, &
325 & 'MPP_DEFINE_DOMAINS1D: You must first call mpp_domains_init.' )
326 if(size(global_indices(:)) .NE. 2) call mpp_error(FATAL,"mpp_define_domains1D: size of global_indices should be 2")
328 isg = global_indices(1)
329 ieg = global_indices(2)
330 if( ndivs.GT.ieg-isg+1 )call mpp_error( FATAL, &
331 & 'MPP_DEFINE_DOMAINS1D: more divisions requested than rows available.' )
332 !get the list of PEs on which to assign domains; if pelist is absent use 0..npes-1
333 if( PRESENT(pelist) )then
334 if( .NOT.any(pelist.EQ.mpp_pe()) )then
336 write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
337 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS1D: pe must be in pelist.' )
339 allocate( pes(0:size(pelist(:))-1) )
342 allocate( pes(0:mpp_npes()-1) )
343 call mpp_get_current_pelist(pes)
344 ! pes(:) = (/ (i,i=0,mpp_npes()-1) /)
347 !get number of real domains: 1 mask domain per PE in pes
348 mask = .TRUE. !default mask
349 if( PRESENT(maskmap) )then
350 if( size(maskmap(:)).NE.ndivs ) &
351 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS1D: maskmap array size must equal number of domain divisions.' )
354 if( count(mask).NE.size(pes(:)) ) &
355 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS1D: number of TRUEs in maskmap array must match PE count.' )
359 if( PRESENT(halo) ) then
361 !--- if halo is present, begin_halo and end_halo should not present
362 if(present(begin_halo) .OR. present(end_halo) ) call mpp_error(FATAL, &
363 "mpp_domains_define.inc: when halo is present, begin_halo and end_halo should not present")
365 halobegin = halosz; haloend = halosz
366 if(present(begin_halo)) halobegin = begin_halo
367 if(present(end_halo)) haloend = end_halo
368 halosz = max(halobegin, haloend)
370 compute_domain_is_global = .FALSE.
371 data_domain_is_global = .FALSE.
372 domain%cyclic = .FALSE.
375 if( PRESENT(flags) )then
376 !NEW: obsolete flag global_compute_domain, since ndivs is non-optional and you cannot
377 !have global compute and ndivs.NE.1
378 compute_domain_is_global = ndivs.EQ.1
379 !if compute domain is global, data domain must also be
380 data_domain_is_global = BTEST(flags,GLOBAL) .OR. compute_domain_is_global
381 domain%cyclic = BTEST(flags,CYCLIC) .AND. halosz.NE.0
382 if(BTEST(flags,CYCLIC)) domain%goffset = 0
386 allocate( domain%list(0:ndivs-1) )
389 domain%list(:)%global%begin = isg
390 domain%list(:)%global%end = ieg
391 domain%list(:)%global%size = ieg-isg+1
392 domain%list(:)%global%max_size = ieg-isg+1
393 domain%list(:)%global%is_global = .TRUE. !always
396 if( compute_domain_is_global )then
397 domain%list(:)%compute%begin = isg
398 domain%list(:)%compute%end = ieg
399 domain%list(:)%compute%is_global = .TRUE.
400 domain%list(:)%pe = pes(:)
403 domain%list(:)%compute%is_global = .FALSE.
405 call mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
407 domain%list(ndiv)%compute%begin = ibegin(ndiv)
408 domain%list(ndiv)%compute%end = iend(ndiv)
410 domain%list(ndiv)%pe = pes(n)
411 if( mpp_pe().EQ.pes(n) )domain%pos = ndiv
414 domain%list(ndiv)%pe = NULL_PE
419 domain%list(:)%compute%size = domain%list(:)%compute%end - domain%list(:)%compute%begin + 1
422 !data domain is at least equal to compute domain
423 domain%list(:)%data%begin = domain%list(:)%compute%begin
424 domain%list(:)%data%end = domain%list(:)%compute%end
425 domain%list(:)%data%is_global = .FALSE.
427 if( data_domain_is_global )then
428 domain%list(:)%data%begin = isg
429 domain%list(:)%data%end = ieg
430 domain%list(:)%data%is_global = .TRUE.
433 domain%list(:)%data%begin = domain%list(:)%data%begin - halobegin
434 domain%list(:)%data%end = domain%list(:)%data%end + haloend
435 domain%list(:)%data%size = domain%list(:)%data%end - domain%list(:)%data%begin + 1
437 !--- define memory domain, if memory_size is not present or memory size is 0, memory domain size
438 !--- will be the same as data domain size. if momory_size is present, memory_size should greater than
439 !--- or equal to data size. The begin of memory domain will be always the same as data domain.
440 domain%list(:)%memory%begin = domain%list(:)%data%begin
441 domain%list(:)%memory%end = domain%list(:)%data%end
442 if( present(memory_size) ) then
443 if(memory_size > 0) then
444 if( domain%list(domain%pos)%data%size > memory_size ) call mpp_error(FATAL, &
445 "mpp_domains_define.inc: data domain size is larger than memory domain size on this pe")
446 domain%list(:)%memory%end = domain%list(:)%memory%begin + memory_size - 1
449 domain%list(:)%memory%size = domain%list(:)%memory%end - domain%list(:)%memory%begin + 1
450 domain%list(:)%memory%is_global = domain%list(:)%data%is_global
452 domain%compute = domain%list(domain%pos)%compute
453 domain%data = domain%list(domain%pos)%data
454 domain%global = domain%list(domain%pos)%global
455 domain%memory = domain%list(domain%pos)%memory
456 domain%compute%max_size = MAXVAL( domain%list(:)%compute%size )
457 domain%data%max_size = MAXVAL( domain%list(:)%data%size )
458 domain%global%max_size = domain%global%size
459 domain%memory%max_size = domain%memory%size
461 !PV786667: the deallocate stmts can be removed when fixed (7.3.1.3m)
465 end subroutine mpp_define_domains1D
467 !################################################################################
468 !> define the IO domain.
469 subroutine mpp_define_io_domain(domain, io_layout)
470 type(domain2D), intent(inout) :: domain
471 integer, intent(in ) :: io_layout(2)
473 integer :: npes_in_group
474 type(domain2D), pointer :: io_domain=>NULL()
475 integer :: i, j, n, m
476 integer :: ipos, jpos, igroup, jgroup
477 integer :: ipos_beg, ipos_end, jpos_beg, jpos_end
478 integer :: whalo, ehalo, shalo, nhalo
479 integer :: npes_x, npes_y, ndivx, ndivy
480 integer, allocatable :: posarray(:,:)
482 if(io_layout(1) * io_layout(2) .LE. 0) then
483 call mpp_error(NOTE, &
484 "mpp_domains_define.inc(mpp_define_io_domain): io domain will not be defined for "//trim(domain%name)// &
485 " when one or both entry of io_layout is not positive")
489 layout(1) = size(domain%x(1)%list(:))
490 layout(2) = size(domain%y(1)%list(:))
492 if(ASSOCIATED(domain%io_domain)) call mpp_error(FATAL, &
493 "mpp_domains_define.inc(mpp_define_io_domain): io_domain is already defined")
495 if(mod(layout(1), io_layout(1)) .NE. 0) call mpp_error(FATAL, &
496 "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
497 & " domain layout(1) must be divided by io_layout(1)")
498 if(mod(layout(2), io_layout(2)) .NE. 0) call mpp_error(FATAL, &
499 "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
500 & " domain layout(2) must be divided by io_layout(2)")
501 if(size(domain%x(:)) > 1) call mpp_error(FATAL, &
502 "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
503 ": multiple tile per pe is not supported yet for this routine")
505 allocate(domain%io_domain)
506 domain%io_layout = io_layout
507 io_domain => domain%io_domain
508 ! Find how many processors are in the group with the consideration that some of the region maybe masked out.
509 npes_x = layout(1)/io_layout(1)
510 npes_y = layout(2)/io_layout(2)
511 ipos = mod(domain%x(1)%pos, npes_x)
512 jpos = mod(domain%y(1)%pos, npes_y)
513 igroup = domain%x(1)%pos/npes_x
514 jgroup = domain%y(1)%pos/npes_y
515 ipos_beg = igroup*npes_x; ipos_end = ipos_beg + npes_x - 1
516 jpos_beg = jgroup*npes_y; jpos_end = jpos_beg + npes_y - 1
518 do j = jpos_beg, jpos_end
519 do i = ipos_beg, ipos_end
520 if(domain%pearray(i,j) .NE. NULL_PE) npes_in_group = npes_in_group+1
524 io_domain%whalo = domain%whalo
525 io_domain%ehalo = domain%ehalo
526 io_domain%shalo = domain%shalo
527 io_domain%nhalo = domain%nhalo
529 io_domain%pe = domain%pe
530 io_domain%symmetry = domain%symmetry
531 allocate(io_domain%list(0:npes_in_group-1))
532 do i = 0, npes_in_group-1
533 allocate( io_domain%list(i)%x(1), io_domain%list(i)%y(1), io_domain%list(i)%tile_id(1) )
536 ndivx = size(domain%pearray,1)
537 ndivy = size(domain%pearray,2)
538 allocate(posarray(0:ndivx-1, 0:ndivy-1))
539 n = domain%tile_root_pe - mpp_root_pe()
543 if( domain%pearray(i,j) == NULL_PE) cycle
550 do j = jpos_beg, jpos_end
551 do i = ipos_beg, ipos_end
552 if( domain%pearray(i,j) == NULL_PE) cycle
553 io_domain%list(n)%pe = domain%pearray(i,j)
555 io_domain%list(n)%x(1)%compute = domain%list(m)%x(1)%compute
556 io_domain%list(n)%y(1)%compute = domain%list(m)%y(1)%compute
557 igroup = domain%list(m)%x(1)%pos/npes_x
558 jgroup = domain%list(m)%y(1)%pos/npes_y
559 io_domain%list(n)%tile_id(1) = jgroup*io_layout(1) + igroup
565 allocate(io_domain%x(1), io_domain%y(1), io_domain%tile_id(1) )
566 allocate(io_domain%x(1)%list(0:npes_x-1), io_domain%y(1)%list(0:npes_y-1) )
568 do j = jpos_beg, jpos_beg+jpos
569 do i = ipos_beg, ipos_beg+ipos
570 if(domain%pearray(i,j) .NE. NULL_PE) n = n + 1
574 io_domain%x(1)%compute = domain%x(1)%compute
575 io_domain%x(1)%data = domain%x(1)%data
576 io_domain%x(1)%memory = domain%x(1)%memory
577 io_domain%y(1)%compute = domain%y(1)%compute
578 io_domain%y(1)%data = domain%y(1)%data
579 io_domain%y(1)%memory = domain%y(1)%memory
580 io_domain%x(1)%global%begin = domain%x(1)%list(ipos_beg)%compute%begin
581 io_domain%x(1)%global%end = domain%x(1)%list(ipos_end)%compute%end
582 io_domain%x(1)%global%size = io_domain%x(1)%global%end - io_domain%x(1)%global%begin + 1
583 io_domain%x(1)%global%max_size = io_domain%x(1)%global%size
584 io_domain%y(1)%global%begin = domain%y(1)%list(jpos_beg)%compute%begin
585 io_domain%y(1)%global%end = domain%y(1)%list(jpos_end)%compute%end
586 io_domain%y(1)%global%size = io_domain%y(1)%global%end - io_domain%y(1)%global%begin + 1
587 io_domain%y(1)%global%max_size = io_domain%y(1)%global%size
588 io_domain%x(1)%pos = ipos
589 io_domain%y(1)%pos = jpos
590 io_domain%tile_id(1) = io_domain%list(n)%tile_id(1)
591 io_domain%tile_root_pe = io_domain%list(0)%pe
594 !!$ do j = 0, npes_y - 1
595 !!$ n = j*npes_x + ipos
596 !!$ io_domain%y(1)%list(j) = io_domain%list(n)%y(1)
598 !!$ do i = 0, npes_x - 1
599 !!$ n = jpos*npes_x + i
600 !!$ io_domain%x(1)%list(i) = io_domain%list(n)%x(1)
611 end subroutine mpp_define_io_domain
613 ! <SUBROUTINE NAME="mpp_define_domains2D" INTERFACE="mpp_define_domains">
614 ! <IN NAME="global_indices" TYPE="integer" DIM="(4)"> </IN>
615 ! <IN NAME="layout" TYPE="integer" DIM="(2)"></IN>
616 ! <INOUT NAME="domain" TYPE="type(domain2D)"></INOUT>
617 ! <IN NAME="pelist" TYPE="integer" DIM="(0:)"></IN>
618 ! <IN NAME="xflags, yflags" TYPE="integer"></IN>
619 ! <IN NAME="xhalo, yhalo" TYPE="integer"></IN>
620 ! <IN NAME="xextent, yextent" TYPE="integer" DIM="(0:)"></IN>
621 ! <IN NAME="maskmap" TYPE="logical" DIM="(:,:)"></IN>
622 ! <IN NAME="name" TYPE="character(len=*)"></IN>
624 subroutine mpp_define_domains2D( global_indices, layout, domain, pelist, xflags, yflags, &
625 xhalo, yhalo, xextent, yextent, maskmap, name, symmetry, memory_size, &
626 whalo, ehalo, shalo, nhalo, is_mosaic, tile_count, tile_id, complete, x_cyclic_offset, y_cyclic_offset )
627 !define 2D data and computational domain on global rectilinear cartesian domain (isg:ieg,jsg:jeg)
628 !and assign them to PEs
629 integer, intent(in) :: global_indices(:) !<(/ isg, ieg, jsg, jeg /)
630 integer, intent(in) :: layout(:)
631 type(domain2D), intent(inout) :: domain
632 integer, intent(in), optional :: pelist(0:)
633 integer, intent(in), optional :: xflags, yflags, xhalo, yhalo
634 integer, intent(in), optional :: xextent(0:), yextent(0:)
635 logical, intent(in), optional :: maskmap(0:,0:)
636 character(len=*), intent(in), optional :: name
637 logical, intent(in), optional :: symmetry
638 logical, intent(in), optional :: is_mosaic !< indicate if calling mpp_define_domains
639 !! from mpp_define_mosaic.
640 integer, intent(in), optional :: memory_size(:)
641 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size for West, East,
642 !! South and North direction.
643 !! if whalo and ehalo is not present,
644 !! will take the value of xhalo
645 !! if shalo and nhalo is not present,
646 !! will take the value of yhalo
647 integer, intent(in), optional :: tile_count !< tile number on current pe,
648 !! default value is 1.
649 !! this is for the situation that
650 !! multiple tiles on one processor
651 integer, intent(in), optional :: tile_id !< tile id
652 logical, intent(in), optional :: complete !< true indicate mpp_define_domain
653 !! is completed for mosaic definition.
654 integer, intent(in), optional :: x_cyclic_offset !< offset for x-cyclic boundary condition,
655 !! (0,j) = (ni, mod(j+x_cyclic_offset,nj))
656 !! (ni+1, j)=(1 ,mod(j+nj-x_cyclic_offset,nj))
657 integer, intent(in), optional :: y_cyclic_offset !< offset for y-cyclic boundary condition
658 !!(i,0) = (mod(i+y_cyclic_offset,ni), nj))
659 !!(i,nj+1) =(mod(mod(i+ni-y_cyclic_offset,ni),
662 integer :: i, j, m, n, xhalosz, yhalosz, memory_xsize, memory_ysize
663 integer :: whalosz, ehalosz, shalosz, nhalosz
664 integer :: ipos, jpos, pos, tile, nlist, cur_tile_id
665 integer :: ndivx, ndivy, isg, ieg, jsg, jeg, ishift, jshift, errunit, logunit
666 integer :: x_offset, y_offset, start_pos, nfold
667 logical :: from_mosaic, is_complete
668 logical :: mask(0:layout(1)-1,0:layout(2)-1)
669 integer, allocatable :: pes(:), pesall(:)
670 integer :: pearray(0:layout(1)-1,0:layout(2)-1)
671 integer :: ibegin(0:layout(1)-1), iend(0:layout(1)-1)
672 integer :: jbegin(0:layout(2)-1), jend(0:layout(2)-1)
673 character(len=8) :: text
674 type(overlapSpec), pointer :: check_T => NULL()
676 logical :: send(8), recv(8)
679 if( .NOT.module_is_initialized )call mpp_error( FATAL, &
680 & 'MPP_DEFINE_DOMAINS2D: You must first call mpp_domains_init.' )
681 if(PRESENT(name)) then
682 if(len_trim(name) > NAME_LENGTH) call mpp_error(FATAL, &
683 "mpp_domains_define.inc(mpp_define_domains2D): the len_trim of optional argument name ="//trim(name)// &
684 " is greater than NAME_LENGTH, change the argument name or increase NAME_LENGTH")
687 if(size(global_indices(:)) .NE. 4) call mpp_error(FATAL, &
688 "mpp_define_domains2D: size of global_indices should be 4 for "//trim(domain%name) )
689 if(size(layout(:)) .NE. 2) call mpp_error(FATAL,"mpp_define_domains2D: size of layout should be 2 for "// &
690 & trim(domain%name) )
692 ndivx = layout(1); ndivy = layout(2)
693 isg = global_indices(1); ieg = global_indices(2); jsg = global_indices(3); jeg = global_indices(4)
695 from_mosaic = .false.
696 if(present(is_mosaic)) from_mosaic = is_mosaic
698 if(present(complete)) is_complete = complete
700 if(present(tile_count)) tile = tile_count
702 if(present(tile_id)) cur_tile_id = tile_id
704 if( PRESENT(pelist) )then
705 allocate( pes(0:size(pelist(:))-1) )
708 allocate( pesall(0:mpp_npes()-1) )
709 call mpp_get_current_pelist(pesall)
711 allocate( pesall(0:size(pes(:))-1) )
715 allocate( pes(0:mpp_npes()-1) )
716 allocate( pesall(0:mpp_npes()-1) )
717 call mpp_get_current_pelist(pes)
721 !--- at least of one of x_cyclic_offset and y_cyclic_offset must be zero
722 !--- folded boundary condition is not supported when either x_cyclic_offset or y_cyclic_offset is nonzero.
723 !--- Since we only implemented Folded-north boundary condition currently, we only consider y-flags.
724 x_offset = 0; y_offset = 0
725 if(PRESENT(x_cyclic_offset)) x_offset = x_cyclic_offset
726 if(PRESENT(y_cyclic_offset)) y_offset = y_cyclic_offset
727 if(x_offset*y_offset .NE. 0) call mpp_error(FATAL, &
728 'MPP_DEFINE_DOMAINS2D: At least one of x_cyclic_offset and y_cyclic_offset must be zero for '// &
731 !--- x_cyclic_offset and y_cyclic_offset should no larger than the global grid size.
732 if(abs(x_offset) > jeg-jsg+1) call mpp_error(FATAL, &
733 'MPP_DEFINE_DOMAINS2D: absolute value of x_cyclic_offset is greater than jeg-jsg+1 for '//trim(domain%name))
734 if(abs(y_offset) > ieg-isg+1) call mpp_error(FATAL, &
735 'MPP_DEFINE_DOMAINS2D: absolute value of y_cyclic_offset is greater than ieg-isg+1 for '//trim(domain%name))
737 !--- when there is more than one tile on one processor, all the tile will limited on this processor
738 if( tile > 1 .AND. size(pes(:)) > 1) call mpp_error(FATAL, &
739 'MPP_DEFINE_DOMAINS2D: there are more than one tile on this pe, '// &
740 'all the tile should be limited on this pe for '//trim(domain%name))
742 !--- the position of current pe is changed due to mosaic, because pes
743 !--- is only part of the pelist in mosaic (pesall). We assume the pe
744 !--- distribution are contious in mosaic.
746 do n = 0, size(pesall(:))-1
747 if(pesall(n) == mpp_pe() ) then
752 if(pos<0) call mpp_error(FATAL, 'MPP_DEFINE_DOMAINS2D: mpp_pe() is not in the pesall list')
754 domain%symmetry = .FALSE.
755 if(present(symmetry)) domain%symmetry = symmetry
756 if(domain%symmetry) then
757 ishift = 1; jshift = 1
759 ishift = 0; jshift = 0
762 !--- first compute domain decomposition.
763 call mpp_compute_extent(isg, ieg, ndivx, ibegin, iend, xextent)
764 call mpp_compute_extent(jsg, jeg, ndivy, jbegin, jend, yextent)
766 xhalosz = 0; yhalosz = 0
767 if(present(xhalo)) xhalosz = xhalo
768 if(present(yhalo)) yhalosz = yhalo
769 whalosz = xhalosz; ehalosz = xhalosz
770 shalosz = yhalosz; nhalosz = yhalosz
771 if(present(whalo)) whalosz = whalo
772 if(present(ehalo)) ehalosz = ehalo
773 if(present(shalo)) shalosz = shalo
774 if(present(nhalo)) nhalosz = nhalo
776 !--- configure maskmap
778 if( PRESENT(maskmap) )then
779 if( size(maskmap,1).NE.ndivx .OR. size(maskmap,2).NE.ndivy ) &
780 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS2D: maskmap array does not match layout for '// &
781 & trim(domain%name) )
782 mask(:,:) = maskmap(:,:)
784 !number of unmask domains in layout must equal number of PEs assigned
786 if( n.NE.size(pes(:)) )then
787 write( text,'(i8)' )n
788 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS2D: incorrect number of PEs assigned for ' // &
789 'this layout and maskmap. Use '//text//' PEs for this domain decomposition for '//trim(domain%name) )
792 memory_xsize = 0; memory_ysize = 0
793 if(present(memory_size)) then
794 if(size(memory_size(:)) .NE. 2) call mpp_error(FATAL, &
795 "mpp_define_domains2D: size of memory_size should be 2 for "//trim(domain%name))
796 memory_xsize = memory_size(1)
797 memory_ysize = memory_size(2)
800 !--- set up domain%list.
801 !--- set up 2-D domain decomposition for T, E, C, N and computing overlapping
802 !--- when current tile is the last tile in the mosaic.
803 nlist = size(pesall(:))
804 if( .NOT. Associated(domain%x) ) then
805 allocate(domain%tileList(1))
806 domain%tileList(1)%xbegin = global_indices(1)
807 domain%tileList(1)%xend = global_indices(2)
808 domain%tileList(1)%ybegin = global_indices(3)
809 domain%tileList(1)%yend = global_indices(4)
810 allocate(domain%x(1), domain%y(1) )
811 allocate(domain%tile_id(1))
812 allocate(domain%tile_id_all(1))
813 domain%tile_id = cur_tile_id
814 domain%tile_id_all = cur_tile_id
816 domain%max_ntile_pe = 1
818 domain%rotated_ninety = .FALSE.
819 allocate( domain%list(0:nlist-1) )
821 allocate( domain%list(i)%x(1), domain%list(i)%y(1), domain%list(i)%tile_id(1) )
825 domain%initialized = .true.
829 if(pesall(n) == pes(0)) then
835 !place on PE array; need flag to assign them to j first and then i
836 pearray(:,:) = NULL_PE
837 ipos = NULL_PE; jpos = NULL_PE
843 pearray(i,j) = pes(n)
844 domain%list(m)%x(tile)%compute%begin = ibegin(i)
845 domain%list(m)%x(tile)%compute%end = iend(i)
846 domain%list(m)%y(tile)%compute%begin = jbegin(j)
847 domain%list(m)%y(tile)%compute%end = jend(j)
848 domain%list(m)%x(tile)%compute%size = domain%list(m)%x(tile)%compute%end &
849 & - domain%list(m)%x(tile)%compute%begin + 1
850 domain%list(m)%y(tile)%compute%size = domain%list(m)%y(tile)%compute%end &
851 & - domain%list(m)%y(tile)%compute%begin + 1
852 domain%list(m)%tile_id(tile) = cur_tile_id
853 domain%list(m)%x(tile)%pos = i
854 domain%list(m)%y(tile)%pos = j
855 domain%list(m)%tile_root_pe = pes(0)
856 domain%list(m)%pe = pesall(m)
858 if( pes(n).EQ.mpp_pe() )then
868 !Considering mosaic, the following will only be done on the pe in the pelist
869 !when there is only one tile, all the current pe will be in the pelist.
870 if( ANY(pes == mpp_pe()) ) then
871 domain%io_layout = layout
872 domain%tile_root_pe = pes(0)
873 if( ipos.EQ.NULL_PE .OR. jpos.EQ.NULL_PE ) &
874 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS2D: pelist must include this PE for '//trim(domain%name) )
877 write( errunit, * )'pe, tile, ipos, jpos=', mpp_pe(), tile, ipos, jpos, ' pearray(:,jpos)=', &
878 pearray(:,jpos), ' pearray(ipos,:)=', pearray(ipos,:)
881 !--- when tile is not equal to 1, the layout for that tile always ( 1, 1), so no need for pearray in domain
883 allocate( domain%pearray(0:ndivx-1,0:ndivy-1) )
884 domain%pearray = pearray
889 domain_cnt = domain_cnt + INT(1,KIND=i8_kind)
890 domain%id = domain_cnt*DOMAIN_ID_BASE ! Must be i8_kind arithmetic
892 !do domain decomposition using 1D versions in X and Y,
893 call mpp_define_domains( global_indices(1:2), ndivx, domain%x(tile), &
894 pack(pearray(:,jpos),mask(:,jpos)), xflags, xhalo, xextent, mask(:,jpos), memory_xsize, whalo, ehalo )
895 call mpp_define_domains( global_indices(3:4), ndivy, domain%y(tile), &
896 pack(pearray(ipos,:),mask(ipos,:)), yflags, yhalo, yextent, mask(ipos,:), memory_ysize, shalo, nhalo )
897 if( domain%x(tile)%list(ipos)%pe.NE.domain%y(tile)%list(jpos)%pe ) &
898 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS2D: domain%x%list(ipos)%pe.NE.domain%y%list(jpos)%pe.' )
900 !--- when x_cyclic_offset or y_cyclic_offset is set, no cross domain is allowed
901 if(x_offset .NE. 0 .OR. y_offset .NE. 0) then
902 if(whalosz .GT. domain%x(tile)%compute%size .OR. ehalosz .GT. domain%x(tile)%compute%size ) &
903 call mpp_error(FATAL, "mpp_define_domains_2d: when x_cyclic_offset/y_cyclic_offset is set, "// &
904 "whalo and ehalo must be no larger than the x-direction computation domain size")
905 if(shalosz .GT. domain%y(tile)%compute%size .OR. nhalosz .GT. domain%y(tile)%compute%size ) &
906 call mpp_error(FATAL, "mpp_define_domains_2d: when x_cyclic_offset/y_cyclic_offset is set, "// &
907 "shalo and nhalo must be no larger than the y-direction computation domain size")
910 !--- restrict the halo size is no larger than global domain size.
911 if(whalosz .GT. domain%x(tile)%global%size) &
912 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: whalo is greather global domain size")
913 if(ehalosz .GT. domain%x(tile)%global%size) &
914 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: ehalo is greather global domain size")
915 if(shalosz .GT. domain%x(tile)%global%size) &
916 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: shalo is greather global domain size")
917 if(nhalosz .GT. domain%x(tile)%global%size) &
918 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: nhalo is greather global domain size")
920 !set up fold, when the boundary is folded, there is only one tile.
923 if( PRESENT(xflags) )then
924 if( BTEST(xflags,WEST) ) then
925 !--- make sure no cross-domain in y-direction
926 if(domain%x(tile)%data%begin .LE. domain%x(tile)%global%begin .AND. &
927 domain%x(tile)%compute%begin > domain%x(tile)%global%begin ) then
928 call mpp_error(FATAL, &
929 'MPP_DEFINE_DOMAINS: the domain could not be crossed when west is folded')
931 if( domain%x(tile)%cyclic )call mpp_error( FATAL, &
932 'MPP_DEFINE_DOMAINS: an axis cannot be both folded west and cyclic for '//trim(domain%name) )
933 domain%fold = domain%fold + FOLD_WEST_EDGE
936 if( BTEST(xflags,EAST) ) then
937 !--- make sure no cross-domain in y-direction
938 if(domain%x(tile)%data%end .GE. domain%x(tile)%global%end .AND. &
939 domain%x(tile)%compute%end < domain%x(tile)%global%end ) then
940 call mpp_error(FATAL, &
941 'MPP_DEFINE_DOMAINS: the domain could not be crossed when north is folded')
943 if( domain%x(tile)%cyclic )call mpp_error( FATAL, &
944 'MPP_DEFINE_DOMAINS: an axis cannot be both folded east and cyclic for '//trim(domain%name) )
945 domain%fold = domain%fold + FOLD_EAST_EDGE
949 if( PRESENT(yflags) )then
950 if( BTEST(yflags,SOUTH) ) then
951 !--- make sure no cross-domain in y-direction
952 if(domain%y(tile)%data%begin .LE. domain%y(tile)%global%begin .AND. &
953 domain%y(tile)%compute%begin > domain%y(tile)%global%begin ) then
954 call mpp_error(FATAL, &
955 'MPP_DEFINE_DOMAINS: the domain could not be crossed when south is folded')
957 if( domain%y(tile)%cyclic )call mpp_error( FATAL, &
958 'MPP_DEFINE_DOMAINS: an axis cannot be both folded north and cyclic for '//trim(domain%name))
959 domain%fold = domain%fold + FOLD_SOUTH_EDGE
962 if( BTEST(yflags,NORTH) ) then
963 !--- when the halo size is big and halo region is crossing neighbor domain, we
964 !--- restrict the halo size is less than half of the global size.
965 if(whalosz .GT. domain%x(tile)%compute%size .AND. whalosz .GE. domain%x(tile)%global%size/2 ) &
966 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: north is folded, whalo .GT. compute domain size "// &
967 "and whalo .GE. half of global domain size")
968 if(ehalosz .GT. domain%x(tile)%compute%size .AND. ehalosz .GE. domain%x(tile)%global%size/2 ) &
969 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: north is folded, ehalo is .GT. compute domain size "// &
970 "and ehalo .GE. half of global domain size")
971 if(shalosz .GT. domain%y(tile)%compute%size .AND. shalosz .GE. domain%x(tile)%global%size/2 ) &
972 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: north is folded, shalo .GT. compute domain size "// &
973 "and shalo .GE. half of global domain size")
974 if(nhalosz .GT. domain%y(tile)%compute%size .AND. nhalosz .GE. domain%x(tile)%global%size/2 ) &
975 call mpp_error(FATAL, "MPP_DEFINE_DOMAINS2D: north is folded, nhalo .GT. compute domain size "// &
976 "and nhalo .GE. half of global domain size")
979 if( domain%y(tile)%cyclic )call mpp_error( FATAL, &
980 'MPP_DEFINE_DOMAINS: an axis cannot be both folded south and cyclic for '//trim(domain%name) )
981 domain%fold = domain%fold + FOLD_NORTH_EDGE
985 if(nfold > 1) call mpp_error(FATAL, &
986 'MPP_DEFINE_DOMAINS2D: number of folded edge is greater than 1 for '//trim(domain%name) )
989 if( x_offset .NE. 0 .OR. y_offset .NE. 0) call mpp_error(FATAL, &
990 'MPP_DEFINE_DOMAINS2D: For the foled_north/folded_south/fold_east/folded_west boundary condition, '//&
991 'x_cyclic_offset and y_cyclic_offset must be zero for '//trim(domain%name))
993 if( BTEST(domain%fold,SOUTH) .OR. BTEST(domain%fold,NORTH) )then
994 if( domain%y(tile)%cyclic )call mpp_error( FATAL, &
995 'MPP_DEFINE_DOMAINS: an axis cannot be both folded and cyclic for '//trim(domain%name) )
996 if( modulo(domain%x(tile)%global%size,2).NE.0 ) &
997 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS: number of points in X must be even ' // &
998 'when there is a fold in Y for '//trim(domain%name) )
999 !check if folded domain boundaries line up in X: compute domains lining up is a sufficient
1000 !condition for symmetry
1003 if( domain%x(tile)%list(i)%compute%size.NE.domain%x(tile)%list(n-i)%compute%size ) &
1004 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS: Folded domain boundaries ' // &
1005 'must line up (mirror-symmetric extents) for '//trim(domain%name) )
1008 if( BTEST(domain%fold,WEST) .OR. BTEST(domain%fold,EAST) )then
1009 if( domain%x(tile)%cyclic )call mpp_error( FATAL, &
1010 'MPP_DEFINE_DOMAINS: an axis cannot be both folded and cyclic for '//trim(domain%name) )
1011 if( modulo(domain%y(tile)%global%size,2).NE.0 ) &
1012 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS: number of points in Y must be even '//&
1013 'when there is a fold in X for '//trim(domain%name) )
1014 !check if folded domain boundaries line up in Y: compute domains lining up is a sufficient
1015 !condition for symmetry
1018 if( domain%y(tile)%list(i)%compute%size.NE.domain%y(tile)%list(n-i)%compute%size ) &
1019 call mpp_error( FATAL, 'MPP_DEFINE_DOMAINS: Folded domain boundaries must '//&
1020 'line up (mirror-symmetric extents) for '//trim(domain%name) )
1025 if( mpp_pe().EQ.pes(0) .AND. PRESENT(name) )then
1027 write( logunit, '(/a,i5,a,i5)' )trim(name)//' domain decomposition: ', ndivx, ' X', ndivy
1028 write( logunit, '(3x,a)' )'pe, is, ie, js, je, isd, ied, jsd, jed'
1030 end if ! if( ANY(pes == mpp_pe()) )
1032 if(is_complete) then
1033 domain%whalo = whalosz; domain%ehalo = ehalosz
1034 domain%shalo = shalosz; domain%nhalo = nhalosz
1035 allocate(domain%update_T, domain%update_E, domain%update_C, domain%update_N)
1036 domain%update_T%next => NULL()
1037 domain%update_E%next => NULL()
1038 domain%update_C%next => NULL()
1039 domain%update_N%next => NULL()
1040 allocate(domain%check_E, domain%check_C, domain%check_N )
1041 domain%update_T%nsend = 0
1042 domain%update_T%nrecv = 0
1043 domain%update_C%nsend = 0
1044 domain%update_C%nrecv = 0
1045 domain%update_E%nsend = 0
1046 domain%update_E%nrecv = 0
1047 domain%update_N%nsend = 0
1048 domain%update_N%nrecv = 0
1050 if( BTEST(domain%fold,SOUTH) ) then
1051 call compute_overlaps_fold_south(domain, CENTER, 0, 0)
1052 call compute_overlaps_fold_south(domain, CORNER, ishift, jshift)
1053 call compute_overlaps_fold_south(domain, EAST, ishift, 0)
1054 call compute_overlaps_fold_south(domain, NORTH, 0, jshift)
1055 else if( BTEST(domain%fold,WEST) ) then
1056 call compute_overlaps_fold_west(domain, CENTER, 0, 0)
1057 call compute_overlaps_fold_west(domain, CORNER, ishift, jshift)
1058 call compute_overlaps_fold_west(domain, EAST, ishift, 0)
1059 call compute_overlaps_fold_west(domain, NORTH, 0, jshift)
1060 else if( BTEST(domain%fold,EAST) ) then
1061 call compute_overlaps_fold_east(domain, CENTER, 0, 0)
1062 call compute_overlaps_fold_east(domain, CORNER, ishift, jshift)
1063 call compute_overlaps_fold_east(domain, EAST, ishift, 0)
1064 call compute_overlaps_fold_east(domain, NORTH, 0, jshift)
1066 call compute_overlaps(domain, CENTER, domain%update_T, check_T, 0, 0, x_offset, y_offset, &
1067 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1068 call compute_overlaps(domain, CORNER, domain%update_C, domain%check_C, ishift, jshift, x_offset, y_offset, &
1069 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1070 call compute_overlaps(domain, EAST, domain%update_E, domain%check_E, ishift, 0, x_offset, y_offset, &
1071 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1072 call compute_overlaps(domain, NORTH, domain%update_N, domain%check_N, 0, jshift, x_offset, y_offset, &
1073 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1075 call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_domains")
1076 call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_domains")
1077 call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_domains")
1078 call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_domains")
1081 !--- when ncontacts is nonzero, set_check_overlap will be called in mpp_define
1082 if(domain%symmetry .AND. (domain%ncontacts == 0 .OR. domain%ntiles == 1) ) then
1083 call set_check_overlap( domain, CORNER )
1084 call set_check_overlap( domain, EAST )
1085 call set_check_overlap( domain, NORTH )
1086 allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1087 call set_bound_overlap( domain, CORNER )
1088 call set_bound_overlap( domain, EAST )
1089 call set_bound_overlap( domain, NORTH )
1091 call set_domain_comm_inf(domain%update_T)
1092 call set_domain_comm_inf(domain%update_E)
1093 call set_domain_comm_inf(domain%update_C)
1094 call set_domain_comm_inf(domain%update_N)
1097 !--- check the send and recv size are matching.
1098 !--- or ntiles>1 mosaic,
1099 !--- the check will be done in mpp_define_mosaic
1100 if(debug_message_passing .and. (domain%ncontacts == 0 .OR. domain%ntiles == 1) ) then
1103 call check_message_size(domain, domain%update_T, send, recv, 'T')
1104 call check_message_size(domain, domain%update_E, send, recv, 'E')
1105 call check_message_size(domain, domain%update_C, send, recv, 'C')
1106 call check_message_size(domain, domain%update_N, send, recv, 'N')
1110 !print out decomposition, this didn't consider maskmap.
1111 if( mpp_pe() .EQ. pes(0) .AND. PRESENT(name) )then
1112 write(*,*) trim(name)//' domain decomposition'
1113 write(*,'(a,i4,a,i4,a,i4,a,i4)')'whalo = ', whalosz, ", ehalo = ", ehalosz, ", shalo = ", shalosz, &
1114 & ", nhalo = ", nhalosz
1115 write (*,110) (domain%x(1)%list(i)%compute%size, i= 0, layout(1)-1)
1116 write (*,120) (domain%y(1)%list(i)%compute%size, i= 0, layout(2)-1)
1117 110 format (' X-AXIS = ',24i4,/,(11x,24i4))
1118 120 format (' Y-AXIS = ',24i4,/,(11x,24i4))
1121 deallocate( pes, pesall)
1125 end subroutine mpp_define_domains2D
1128 !#####################################################################
1129 subroutine check_message_size(domain, update, send, recv, position)
1130 type(domain2d), intent(in) :: domain
1131 type(overlapSpec), intent(in) :: update
1132 logical, intent(in) :: send(:)
1133 logical, intent(in) :: recv(:)
1134 character, intent(in) :: position
1136 integer, dimension(0:size(domain%list(:))-1) :: msg1, msg2, msg3
1137 integer :: m, n, l, dir, is, ie, js, je, from_pe, msgsize
1140 nlist = size(domain%list(:))
1145 do m = 1, update%nrecv
1147 do n = 1, update%recv(m)%count
1148 dir = update%recv(m)%dir(n)
1149 if( recv(dir) ) then
1150 is = update%recv(m)%is(n); ie = update%recv(m)%ie(n)
1151 js = update%recv(m)%js(n); je = update%recv(m)%je(n)
1152 msgsize = msgsize + (ie-is+1)*(je-js+1)
1155 from_pe = update%recv(m)%pe
1156 l = from_pe-mpp_root_pe()
1157 call mpp_recv( msg1(l), glen=1, from_pe=from_pe, block=.FALSE., tag=COMM_TAG_1)
1161 do m = 1, update%nsend
1163 do n = 1, update%send(m)%count
1164 dir = update%send(m)%dir(n)
1166 is = update%send(m)%is(n); ie = update%send(m)%ie(n)
1167 js = update%send(m)%js(n); je = update%send(m)%je(n)
1168 msgsize = msgsize + (ie-is+1)*(je-js+1)
1171 l = update%send(m)%pe-mpp_root_pe()
1173 call mpp_send( msg3(l), plen=1, to_pe=update%send(m)%pe, tag=COMM_TAG_1)
1175 call mpp_sync_self(check=EVENT_RECV)
1178 if(msg1(m) .NE. msg2(m)) then
1179 print*, "My pe = ", mpp_pe(), ",domain name =", trim(domain%name), ",at position=",position,",from pe=", &
1180 domain%list(m)%pe, ":send size = ", msg1(m), ", recv size = ", msg2(m)
1181 call mpp_error(FATAL, "mpp_define_domains2D: mismatch on send and recv size")
1184 call mpp_sync_self()
1187 end subroutine check_message_size
1189 !#####################################################################
1190 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1192 ! MPP_define_mosaic: define mosaic domain !
1193 ! NOTE: xflags and yflags is not in mpp_define_mosaic, because such relation !
1194 ! are already defined in the mosaic relation. !
1196 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1197 !??? do we need optional argument xextent and yextent
1198 !??? how to specify pelist, we may use two dimensional variable pelist to represent.
1199 !z1l: We assume the tilelist are in always limited to 1, 2, ... num_tile. If we want
1200 ! to remove this limitation, we need to add one more argument tilelist.
1201 subroutine mpp_define_mosaic( global_indices, layout, domain, num_tile, num_contact, tile1, tile2, &
1202 istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, pe_start, &
1203 pe_end, pelist, whalo, ehalo, shalo, nhalo, xextent, yextent, &
1204 maskmap, name, memory_size, symmetry, xflags, yflags, tile_id )
1205 integer, intent(in) :: global_indices(:,:) ! The size of first indice is 4,
1206 !! (/ isg, ieg, jsg, jeg /)
1207 ! The size of second indice
1208 ! is number of tiles in mosaic.
1209 integer, intent(in) :: layout(:,:)
1210 type(domain2D), intent(inout) :: domain
1211 integer, intent(in) :: num_tile ! number of tiles in the mosaic
1212 integer, intent(in) :: num_contact ! number of contact region between tiles.
1213 integer, intent(in) :: tile1(:), tile2(:) ! tile number
1214 integer, intent(in) :: istart1(:), iend1(:) ! i-index in tile_1 of contact region
1215 integer, intent(in) :: jstart1(:), jend1(:) ! j-index in tile_1 of contact region
1216 integer, intent(in) :: istart2(:), iend2(:) ! i-index in tile_2 of contact region
1217 integer, intent(in) :: jstart2(:), jend2(:) ! j-index in tile_2 of contact region
1218 integer, intent(in) :: pe_start(:) ! start pe of the pelist used in each tile
1219 integer, intent(in) :: pe_end(:) ! end pe of the pelist used in each tile
1220 integer, intent(in), optional :: pelist(:) ! list of processors used in mosaic
1221 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo
1222 integer, intent(in), optional :: xextent(:,:), yextent(:,:)
1223 logical, intent(in), optional :: maskmap(:,:,:)
1224 character(len=*), intent(in), optional :: name
1225 integer, intent(in), optional :: memory_size(2)
1226 logical, intent(in), optional :: symmetry
1227 integer, intent(in), optional :: xflags, yflags
1228 integer, intent(in), optional :: tile_id(:) ! tile_id of each tile in the mosaic
1230 integer :: n, m, ndivx, ndivy, nc, nlist, nt, pos, n1, n2
1231 integer :: whalosz, ehalosz, shalosz, nhalosz, xhalosz, yhalosz, t1, t2, tile
1232 integer :: flags_x, flags_y
1233 logical, allocatable :: mask(:,:)
1234 integer, allocatable :: pes(:), xext(:), yext(:), pelist_tile(:), ntile_per_pe(:), tile_count(:)
1235 integer, allocatable :: tile_id_local(:)
1236 logical :: is_symmetry
1237 integer, allocatable :: align1(:), align2(:), is1(:), ie1(:), js1(:), je1(:), is2(:), ie2(:), js2(:), je2(:)
1238 integer, allocatable :: isgList(:), iegList(:), jsgList(:), jegList(:)
1239 real, allocatable :: refine1(:), refine2(:)
1241 logical :: send(8), recv(8)
1244 mosaic_defined = .true.
1245 !--- the size of first indice of global_indices must be 4.
1246 if(size(global_indices, 1) .NE. 4) call mpp_error(FATAL, &
1247 'mpp_domains_define.inc: The size of first dimension of global_indices is not 4')
1248 !--- the size of second indice of global_indices must be num_tile
1249 if(size(global_indices, 2) .NE. num_tile) call mpp_error(FATAL, &
1250 'mpp_domains_define.inc: The size of second dimension of global_indices is not equal num_tile')
1251 !--- the size of first indice of layout must be 2. The second dimension size of layout must equal num_tile.
1252 if(size(layout, 1) .NE. 2) call mpp_error(FATAL, &
1253 'mpp_domains_define.inc: The size of first dimension of layout is not 2')
1254 if(size(layout,2) .NE. num_tile) call mpp_error(FATAL, &
1255 'mpp_domains_define.inc: The size of second dimension of layout is not equal num_tile')
1257 !--- setup pelist for the mosaic ---------------------
1259 allocate(pes(0:nlist-1))
1260 if(present(pelist)) then
1261 if( nlist .NE. size(pelist(:))) call mpp_error(FATAL, &
1262 'mpp_domains_define.inc: size of pelist is not equal mpp_npes')
1265 call mpp_get_current_pelist(pes)
1267 !--- pelist should be monotonic increasing by 1.
1269 if(pes(n) - pes(n-1) .NE. 1) call mpp_error(FATAL, &
1270 'mpp_domains_define.inc: pelist is not monotonic increasing by 1')
1273 is_symmetry = .FALSE.
1274 if(present(symmetry)) is_symmetry = symmetry
1276 if(size(pe_start(:)) .NE. num_tile .OR. size(pe_end(:)) .NE. num_tile ) call mpp_error(FATAL, &
1277 'mpp_domains_define.inc: size of pe_start and/or pe_end is not equal num_tile')
1278 !--- make sure pe_start and pe_end is in the pelist.
1279 if( ANY( pe_start < pes(0) ) ) call mpp_error(FATAL, &
1280 & 'mpp_domains_define.inc: not all the pe_start are in the pelist')
1281 if( ANY( pe_end > pes(nlist-1)) ) call mpp_error(FATAL, &
1282 & 'mpp_domains_define.inc: not all the pe_end are in the pelist')
1284 !--- calculate number of tiles on each pe.
1285 allocate( ntile_per_pe(0:nlist-1) )
1288 do m = pe_start(n) - mpp_root_pe(), pe_end(n) - mpp_root_pe()
1289 ntile_per_pe(m) = ntile_per_pe(m) + 1
1292 if(ANY(ntile_per_pe == 0)) call mpp_error(FATAL, &
1293 'mpp_domains_define.inc: At least one pe in pelist is not used by any tile in the mosaic')
1295 !--- check the size comformable of xextent and yextent
1296 if( PRESENT(xextent) ) then
1297 if(size(xextent,1) .GT. maxval(layout(1,:)) ) call mpp_error(FATAL, &
1298 'mpp_domains_define.inc: size mismatch between xextent and layout')
1299 if(size(xextent,2) .NE. num_tile) call mpp_error(FATAL, &
1300 'mpp_domains_define.inc: size of xextent is not eqaul num_tile')
1302 if( PRESENT(yextent) ) then
1303 if(size(yextent,1) .GT. maxval(layout(2,:)) ) call mpp_error(FATAL, &
1304 'mpp_domains_define.inc: size mismatch between yextent and layout')
1305 if(size(yextent,2) .NE. num_tile) call mpp_error(FATAL, &
1306 'mpp_domains_define.inc: size of yextent is not eqaul num_tile')
1309 !--- check the size comformable of maskmap
1310 !--- since the layout is different between tiles, so the actual size of maskmap for each tile is
1311 !--- not diffrent. When define maskmap for multiple tiles, user can choose the maximum value
1312 !--- of layout of all tiles to the first and second dimension of maskmap.
1313 if(present(maskmap)) then
1314 if(size(maskmap,1) .GT. maxval(layout(1,:)) .or. size(maskmap,2) .GT. maxval(layout(2,:))) &
1315 call mpp_error(FATAL, 'mpp_domains_define.inc: size mismatch between maskmap and layout')
1316 if(size(maskmap,3) .NE. num_tile) call mpp_error(FATAL, &
1317 'mpp_domains_define.inc: the third dimension of maskmap is not equal num_tile')
1320 allocate(domain%tileList(num_tile))
1322 domain%tileList(n)%xbegin = global_indices(1,n)
1323 domain%tileList(n)%xend = global_indices(2,n)
1324 domain%tileList(n)%ybegin = global_indices(3,n)
1325 domain%tileList(n)%yend = global_indices(4,n)
1327 !--- define some mosaic information in domain type
1328 nt = ntile_per_pe(mpp_pe()-mpp_root_pe())
1329 allocate(domain%tile_id(nt), domain%x(nt), domain%y(nt) )
1330 allocate(domain%list(0:nlist-1))
1333 nt = ntile_per_pe(n)
1334 allocate(domain%list(n)%x(nt), domain%list(n)%y(nt), domain%list(n)%tile_id(nt) )
1339 if( PRESENT(tile_id) ) then
1340 if(size(tile_id(:)) .NE. num_tile) then
1341 call mpp_error(FATAL, "mpp_domains_define.inc: size(tile_id) .NE. num_tile")
1344 allocate(tile_id_local(num_tile))
1346 !These directives are a work-around for a bug in the CCE compiler, which
1347 !causes a segmentation fault when the compiler attempts to vectorize a
1348 !loop containing an optional argument (when -g is included).
1352 if(PRESENT(tile_id)) then
1353 tile_id_local(n) = tile_id(n)
1355 tile_id_local(n) = n
1361 if( pe .GE. pe_start(n) .AND. pe .LE. pe_end(n)) then
1363 domain%tile_id(pos) = tile_id_local(n)
1367 allocate(domain%tile_id_all(num_tile))
1368 domain%tile_id_all(:) = tile_id_local(:)
1370 domain%initialized = .true.
1371 domain%rotated_ninety = .FALSE.
1372 domain%ntiles = num_tile
1373 domain%max_ntile_pe = maxval(ntile_per_pe)
1374 domain%ncontacts = num_contact
1376 deallocate(ntile_per_pe)
1377 !---call mpp_define_domain to define domain decomposition for each tile.
1378 allocate(tile_count(pes(0):pes(0)+nlist-1))
1379 tile_count = 0 ! tile number on current pe
1382 allocate(mask(layout(1,n), layout(2,n)))
1383 allocate(pelist_tile(pe_start(n):pe_end(n)) )
1384 tile_count(pe_start(n)) = tile_count(pe_start(n)) + 1
1385 do m = pe_start(n), pe_end(n)
1389 if(present(maskmap)) mask = maskmap(1:layout(1,n), 1:layout(2,n), n)
1390 ndivx = layout(1,n); ndivy = layout(2,n)
1391 allocate(xext(ndivx), yext(ndivy))
1393 if(present(xextent)) xext = xextent(1:ndivx,n)
1394 if(present(yextent)) yext = yextent(1:ndivy,n)
1395 ! when num_tile is one, we assume only folded_north and cyclic_x, cyclic_y boundary condition is the possible
1396 ! z1l: when we decide to support multiple-tile tripolar grid, we will redesign the following part.
1397 if(num_tile == 1) then
1400 if(PRESENT(xflags)) flags_x = xflags
1401 if(PRESENT(yflags)) flags_y = yflags
1402 do m = 1, num_contact
1403 if(istart1(m) == iend1(m) ) then ! x-direction contact, possible cyclic, folded-west or folded-east
1404 if(istart2(m) .NE. iend2(m) ) call mpp_error(FATAL, &
1405 "mpp_domains_define: for one tile mosaic, when istart1=iend1, istart2 must equal iend2")
1406 if(istart1(m) == istart2(m) ) then ! folded west or folded east
1407 if(istart1(m) == global_indices(1,n) ) then
1408 if(.NOT. BTEST(flags_x,WEST) ) flags_x = flags_x + FOLD_WEST_EDGE
1409 else if(istart1(m) == global_indices(2,n) ) then
1410 if(.NOT. BTEST(flags_x,EAST) ) flags_x = flags_x + FOLD_EAST_EDGE
1412 call mpp_error(FATAL, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1413 "istart1 should equal global_indices(1) or global_indices(2)")
1416 if(.NOT. BTEST(flags_x,CYCLIC)) flags_x = flags_x + CYCLIC_GLOBAL_DOMAIN
1418 else if( jstart1(m) == jend1(m) ) then ! y-direction contact, cyclic, folded-south or folded-north
1419 if(jstart2(m) .NE. jend2(m) ) call mpp_error(FATAL, &
1420 "mpp_domains_define: for one tile mosaic, when jstart1=jend1, jstart2 must equal jend2")
1421 if(jstart1(m) == jstart2(m) ) then ! folded south or folded north
1422 if(jstart1(m) == global_indices(3,n) ) then
1423 if(.NOT. BTEST(flags_y,SOUTH) ) flags_y = flags_y + FOLD_SOUTH_EDGE
1424 else if(jstart1(m) == global_indices(4,n) ) then
1425 if(.NOT. BTEST(flags_y,NORTH) ) flags_y = flags_y + FOLD_NORTH_EDGE
1427 call mpp_error(FATAL, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1428 "istart1 should equal global_indices(1) or global_indices(2)")
1431 if(.NOT. BTEST(flags_y,CYCLIC)) flags_y = flags_y + CYCLIC_GLOBAL_DOMAIN
1434 call mpp_error(FATAL, &
1435 "mpp_domains_define: for one tile mosaic, invalid boundary contact")
1438 call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, xflags = flags_x, &
1439 yflags = flags_y, whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, &
1440 xextent=xext, yextent=yext, maskmap=mask, name=name, symmetry=is_symmetry, &
1441 memory_size = memory_size, is_mosaic = .true., tile_id=tile_id_local(n))
1443 call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, &
1444 whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, xextent=xext, yextent=yext, &
1445 maskmap=mask, name=name, symmetry=is_symmetry, memory_size = memory_size, &
1446 is_mosaic = .true., tile_count = tile_count(pe_start(n)), tile_id=tile_id_local(n), &
1447 complete = n==num_tile)
1449 deallocate(mask, xext, yext, pelist_tile)
1452 deallocate(pes, tile_count)
1454 if(num_contact == 0 .OR. num_tile == 1) return
1456 !--- loop through each contact region and find the contact for each tile ( including alignment )
1457 !--- we assume the tiles list is continuous and starting from 1.
1458 allocate(is1(num_contact), ie1(num_contact), js1(num_contact), je1(num_contact) )
1459 allocate(is2(num_contact), ie2(num_contact), js2(num_contact), je2(num_contact) )
1460 allocate(isgList(num_tile), iegList(num_tile), jsgList(num_tile), jegList(num_tile) )
1461 allocate(align1(num_contact), align2(num_contact), refine1(num_contact), refine2(num_contact))
1462 !--- get the global domain for each tile
1464 isgList(n) = domain%tileList(n)%xbegin; iegList(n) = domain%tileList(n)%xend
1465 jsgList(n) = domain%tileList(n)%ybegin; jegList(n) = domain%tileList(n)%yend
1468 !--- transfer the contact index to domain index.
1470 do n = 1, num_contact
1473 is1(n) = istart1(n) + isgList(t1) - 1; ie1(n) = iend1(n) + isgList(t1) - 1
1474 js1(n) = jstart1(n) + jsgList(t1) - 1; je1(n) = jend1(n) + jsgList(t1) - 1
1475 is2(n) = istart2(n) + isgList(t2) - 1; ie2(n) = iend2(n) + isgList(t2) - 1
1476 js2(n) = jstart2(n) + jsgList(t2) - 1; je2(n) = jend2(n) + jsgList(t2) - 1
1477 call check_alignment( is1(n), ie1(n), js1(n), je1(n), isgList(t1), iegList(t1), jsgList(t1), &
1478 & jegList(t1), align1(n))
1479 call check_alignment( is2(n), ie2(n), js2(n), je2(n), isgList(t2), iegList(t2), jsgList(t2), &
1480 & jegList(t2), align2(n))
1481 if( (align1(n) == WEST .or. align1(n) == EAST ) .NEQV. (align2(n) == WEST .or. align2(n) == EAST ) )&
1482 domain%rotated_ninety=.true.
1485 !--- calculate the refinement ratio between tiles
1486 do n = 1, num_contact
1487 n1 = max(abs(iend1(n) - istart1(n)), abs(jend1(n) - jstart1(n)) ) + 1
1488 n2 = max(abs(iend2(n) - istart2(n)), abs(jend2(n) - jstart2(n)) ) + 1
1489 refine1(n) = real(n2)/n1
1490 refine2(n) = real(n1)/n2
1493 whalosz = 0; ehalosz = 0; shalosz = 0; nhalosz = 0
1494 if(present(whalo)) whalosz = whalo
1495 if(present(ehalo)) ehalosz = ehalo
1496 if(present(shalo)) shalosz = shalo
1497 if(present(nhalo)) nhalosz = nhalo
1498 xhalosz = max(whalosz, ehalosz)
1499 yhalosz = max(shalosz, nhalosz)
1501 !--- computing the overlap for the contact region with halo size xhalosz and yhalosz
1502 call define_contact_point( domain, CENTER, num_contact, tile1, tile2, align1, align2, refine1, refine2, &
1503 is1, ie1, js1, je1, is2, ie2, js2, je2, isgList, iegList, jsgList, jegList )
1505 call set_contact_point( domain, CORNER )
1506 call set_contact_point( domain, EAST )
1507 call set_contact_point( domain, NORTH )
1509 call set_domain_comm_inf(domain%update_T)
1510 call set_domain_comm_inf(domain%update_E)
1511 call set_domain_comm_inf(domain%update_C)
1512 call set_domain_comm_inf(domain%update_N)
1515 !--- goffset setting is needed for exact global sum
1516 do m = 1, size(domain%tile_id(:))
1517 tile = domain%tile_id(m)
1518 do n = 1, num_contact
1519 if( tile1(n) == tile ) then
1520 if(align1(n) == EAST ) domain%x(m)%goffset = 0
1521 if(align1(n) == NORTH) domain%y(m)%goffset = 0
1523 if( tile2(n) == tile ) then
1524 if(align2(n) == EAST ) domain%x(m)%goffset = 0
1525 if(align2(n) == NORTH) domain%y(m)%goffset = 0
1529 call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_mosaic")
1530 call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_mosaic")
1531 call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_mosaic")
1532 call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_mosaic")
1534 !--- set the overlapping for boundary check if domain is symmetry
1535 if(debug_update_level .NE. NO_CHECK) then
1536 call set_check_overlap( domain, CORNER )
1537 call set_check_overlap( domain, EAST )
1538 call set_check_overlap( domain, NORTH )
1540 if(domain%symmetry) then
1541 allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1542 call set_bound_overlap( domain, CORNER )
1543 call set_bound_overlap( domain, EAST )
1544 call set_bound_overlap( domain, NORTH )
1545 call check_overlap_pe_order(domain, domain%bound_C, trim(domain%name)//" bound_C")
1546 call check_overlap_pe_order(domain, domain%bound_E, trim(domain%name)//" bound_E")
1547 call check_overlap_pe_order(domain, domain%bound_N, trim(domain%name)//" bound_N")
1550 !--- check the send and recv size are matching.
1551 !--- currently only check T and C-cell. For ntiles>1 mosaic,
1552 !--- the check will be done in mpp_define_mosaic
1553 if(debug_message_passing) then
1556 call check_message_size(domain, domain%update_T, send, recv, 'T')
1557 call check_message_size(domain, domain%update_C, send, recv, 'C')
1558 call check_message_size(domain, domain%update_E, send, recv, 'E')
1559 call check_message_size(domain, domain%update_N, send, recv, 'N')
1564 deallocate(align1, align2, is1, ie1, js1, je1, is2, ie2, js2, je2 )
1565 deallocate(isgList, iegList, jsgList, jegList, refine1, refine2 )
1568 end subroutine mpp_define_mosaic
1570 !#####################################################################
1571 logical function mpp_mosaic_defined()
1572 ! Accessor function for value of mosaic_defined
1573 mpp_mosaic_defined = mosaic_defined
1574 end function mpp_mosaic_defined
1575 !#####################################################################
1577 subroutine compute_overlaps( domain, position, update, check, ishift, jshift, x_cyclic_offset, y_cyclic_offset, &
1578 whalo, ehalo, shalo, nhalo )
1579 !computes remote domain overlaps
1580 !assumes only one in each direction
1581 !will calculate the overlapping for T,E,C,N-cell seperately.
1582 type(domain2D), intent(inout) :: domain
1583 type(overlapSpec), intent(inout), pointer :: update
1584 type(overlapSpec), intent(inout), pointer :: check
1585 integer, intent(in) :: position, ishift, jshift
1586 integer, intent(in) :: x_cyclic_offset, y_cyclic_offset
1587 integer, intent(in) :: whalo, ehalo, shalo, nhalo
1589 integer :: i, m, n, nlist, tMe, tNbr, dir
1590 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
1591 integer :: isg, ieg, jsg, jeg, ioff, joff
1592 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
1593 integer :: ism, iem, jsm, jem
1594 integer :: is2, ie2, js2, je2
1595 integer :: is3, ie3, js3, je3
1596 integer :: isd3, ied3, jsd3, jed3
1597 integer :: isd2, ied2, jsd2, jed2
1598 logical :: folded, need_adjust_1, need_adjust_2, need_adjust_3, folded_north
1599 type(overlap_type) :: overlap
1600 type(overlap_type), pointer :: overlapList(:)=>NULL()
1601 type(overlap_type), pointer :: checkList(:)=>NULL()
1602 integer :: nsend, nrecv
1603 integer :: nsend_check, nrecv_check
1605 logical :: set_check
1607 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
1608 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
1609 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
1610 if(size(domain%x(:)) > 1) return
1612 !--- if there is no halo, no need to compute overlaps.
1613 if(whalo==0 .AND. ehalo==0 .AND. shalo==0 .AND. nhalo==0) return
1615 !--- when there is only one tile, n will equal to np
1616 nlist = size(domain%list(:))
1618 if(ASSOCIATED(check)) set_check = .true.
1619 allocate(overlapList(MAXLIST) )
1620 if(set_check) allocate(checkList(MAXLIST) )
1622 !--- overlap is used to store the overlapping temporarily.
1623 call allocate_update_overlap( overlap, MAXOVERLAP)
1625 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
1626 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
1627 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
1629 update%xbegin = ism; update%xend = iem
1630 update%ybegin = jsm; update%yend = jem
1632 check%xbegin = ism; check%xend = iem
1633 check%ybegin = jsm; check%yend = jem
1635 update%whalo = whalo; update%ehalo = ehalo
1636 update%shalo = shalo; update%nhalo = nhalo
1640 middle = (isg+ieg)/2+1
1642 folded_north = BTEST(domain%fold,NORTH)
1643 if( BTEST(domain%fold,SOUTH) .OR. BTEST(domain%fold,EAST) .OR. BTEST(domain%fold,WEST) ) then
1644 call mpp_error(FATAL,"mpp_domains_define.inc(compute_overlaps): folded south, east or west boundary condition "&
1645 &//"is not supported, please use other version of compute_overlaps for "//trim(domain%name))
1652 m = mod( domain%pos+list, nlist )
1653 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
1654 !to_pe's eastern halo
1656 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
1657 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
1658 !--- to make sure the consistence between pes
1659 if( domain%symmetry .AND. (position == NORTH .OR. position == CORNER ) &
1660 .AND. ( jsc == je .or. jec == js ) ) then
1661 !--- do nothing, this point will come from other pe
1663 !--- when the north face is folded, the east halo point at right side domain will be folded.
1664 !--- the position should be on CORNER or NORTH
1665 if( je == jeg .AND. folded_north .AND. (position == CORNER .OR. position == NORTH) ) then
1666 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1667 isg, ieg, dir, ishift, position, ioff, middle)
1669 if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1670 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1671 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, symmetry=domain%symmetry)
1673 if( ie.GT.ieg ) then
1674 if( domain%x(tMe)%cyclic .AND. iec.LT.is )then !try cyclic offset
1675 is = is-ioff; ie = ie-ioff
1676 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1679 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1680 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1687 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
1688 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
1689 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1690 !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
1691 !--- the other part is both are zero.
1692 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1693 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1694 if(je .LT. jsg) then ! js .LT. jsg
1695 if( domain%y(tMe)%cyclic ) then
1696 js = js + joff; je = je + joff
1698 else if(js .Lt. jsg) then ! split into two parts
1699 if( domain%y(tMe)%cyclic ) then
1700 js2 = js + joff; je2 = jsg-1+joff
1704 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1705 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
1706 if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1707 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
1710 if( domain%x(tMe)%cyclic .AND. iec.LT.is )then !try cyclic offset
1711 is = is-ioff; ie = ie-ioff
1712 need_adjust_1 = .false.
1713 if(jsg .GT. js) then
1714 if( domain%y(tMe)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1715 js = js+joff; je = je+joff
1716 need_adjust_2 = .false.
1717 if(x_cyclic_offset .NE. 0) then
1718 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1719 else if(y_cyclic_offset .NE. 0) then
1720 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1724 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1725 need_adjust_3 = .false.
1729 if( need_adjust_3 .AND. jsg.GT.js )then
1730 if( need_adjust_2 .AND. domain%y(tMe)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1731 js = js+joff; je = je+joff
1732 if(need_adjust_1 .AND. ie.LE.ieg) then
1733 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1737 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1740 !to_pe's southern halo
1742 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
1743 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
1745 if( jsg.GT.je )then ! jsg .GT. js
1746 if( domain%y(tMe)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1747 js = js+joff; je = je+joff
1748 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1750 else if (jsg .GT. js) then ! split into two parts
1751 if( domain%y(tMe)%cyclic) then
1752 js2 = js + joff; je2 = jsg-1+joff
1757 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1758 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1759 if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1760 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1764 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
1765 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
1766 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1767 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1768 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1769 if(je .LT. jsg) then ! js .LT. jsg
1770 if( domain%y(tMe)%cyclic ) then
1771 js = js + joff; je = je + joff
1773 else if(js .Lt. jsg) then ! split into two parts
1774 if( domain%y(tMe)%cyclic ) then
1775 js2 = js + joff; je2 = jsg-1+joff
1779 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1780 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
1781 if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1782 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
1785 if( domain%x(tMe)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1786 is = is+ioff; ie = ie+ioff
1787 need_adjust_1 = .false.
1788 if(jsg .GT. js) then
1789 if( domain%y(tMe)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1790 js = js+joff; je = je+joff
1791 need_adjust_2 = .false.
1792 if(x_cyclic_offset .NE. 0) then
1793 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1794 else if(y_cyclic_offset .NE. 0) then
1795 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1799 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1800 need_adjust_3 = .false.
1804 if( need_adjust_3 .AND. jsg.GT.js )then
1805 if( need_adjust_2 .AND. domain%y(tMe)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1806 js = js+joff; je = je+joff
1807 if(need_adjust_1 .AND. isg.LE.is )then
1808 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1812 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1815 !to_pe's western halo
1817 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
1818 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
1820 !--- when the north face is folded, some point at j=nj will be folded.
1821 !--- the position should be on CORNER or NORTH
1822 if( je == jeg .AND. folded_north .AND. (position == CORNER .OR. position == NORTH)) then
1823 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1824 isg, ieg, dir, ishift, position, ioff, middle)
1826 if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1827 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1828 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, symmetry=domain%symmetry)
1831 if( domain%x(tMe)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1832 is = is+ioff; ie = ie+ioff
1833 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1836 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1837 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1843 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
1844 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
1845 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1846 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
1848 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1849 if(js .GT. jeg) then ! je > jeg
1850 if( domain%y(tMe)%cyclic ) then
1851 js = js-joff; je = je-joff
1852 else if(folded_north )then
1854 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1856 else if(je .GT. jeg) then ! split into two parts
1857 if( domain%y(tMe)%cyclic ) then
1858 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1859 js = jeg+1-joff; je = je -joff
1860 else if(folded_north) then
1862 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1864 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1865 if( is .GT. ieg) then
1866 is = is - ioff; ie = ie - ioff
1867 else if( ie .GT. ieg ) then
1868 is3 = is; ie3 = ieg; js3 = js; je3 = je
1869 is = ieg+1-ioff; ie = ie - ioff
1874 if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == CORNER .OR. position == NORTH)) then
1875 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1876 isg, ieg, dir, ishift, position, ioff, middle)
1878 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1879 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
1881 if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
1882 isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
1883 if(ie2 .GE. is2) then
1884 if(je2 == jeg .AND. jec == jeg .AND. folded_north.AND.(position == CORNER .OR. position == NORTH))then
1885 call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1886 isg, ieg, dir, ishift, position, ioff, middle)
1888 call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1889 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
1893 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1895 if( domain%x(tMe)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1896 is = is+ioff; ie = ie+ioff
1897 need_adjust_1 = .false.
1898 if(je .GT. jeg) then
1899 if( domain%y(tMe)%cyclic .AND. jec.LT.js )then !try cyclic offset
1900 js = js-joff; je = je-joff
1901 need_adjust_2 = .false.
1902 if(x_cyclic_offset .NE. 0) then
1903 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1904 else if(y_cyclic_offset .NE. 0) then
1905 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1909 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1910 need_adjust_3 = .false.
1915 if( need_adjust_3 .AND. je.GT.jeg )then
1916 if( need_adjust_2 .AND. domain%y(tMe)%cyclic .AND. jec.LT.js )then !try cyclic offset
1917 js = js-joff; je = je-joff
1918 if( need_adjust_1 .AND. isg.LE.is)then
1919 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1921 else if( folded_north )then
1923 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1926 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1927 isg, ieg, jsg, jeg, dir)
1931 !to_pe's northern halo
1934 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
1935 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
1937 !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
1938 !--- no need to send, because the data on that point will come from other pe.
1939 !--- come from two pe ( there will be only one point on one pe. ).
1940 if( domain%symmetry .AND. (position == EAST .OR. position == CORNER ) &
1941 .AND. ( isc == ie .or. iec == is ) .AND. (.not. folded_north) ) then
1942 !--- do nothing, this point will come from other pe
1945 if( js .GT. jeg) then ! je .GT. jeg
1946 if( domain%y(tMe)%cyclic .AND. jec.LT.js )then !try cyclic offset
1947 js = js-joff; je = je-joff
1948 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1949 else if( folded_north )then
1951 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1953 else if( je.GT.jeg )then ! split into two parts
1954 if( domain%y(tMe)%cyclic)then !try cyclic offset
1955 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1956 js = jeg+1-joff; je = je - joff
1957 else if( folded_north )then
1959 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1961 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1964 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1965 if( je == jeg .AND. jec == jeg .AND. folded_north .AND.(position == CORNER .OR. position == NORTH))then
1966 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1967 isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1969 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1970 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded, domain%symmetry)
1973 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1974 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1977 if(ie2 .GE. is2) then
1978 if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == CORNER .OR. position == NORTH))then
1979 call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1980 isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1982 call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1983 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, symmetry=domain%symmetry)
1988 !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
1989 if(is .LT. isg .AND. domain%x(tMe)%cyclic) then
1991 ! call insert_update_overlap( overlap, domain%list(m)%pe, &
1992 ! is, is, js, je, isc, iec, jsc, jec, dir, folded)
1993 !??? if(je2 .GE. js2)call insert_update_overlap( overlap, domain%list(m)%pe, &
1994 ! is, is, js2, je2, isc, iec, jsc, jec, dir, folded)
1997 !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
1998 !--- for folded-north-edge, only need to consider to_pe's north(7) direction
1999 !--- only position at NORTH and CORNER need to be considered
2000 if( folded_north .AND. (position == NORTH .OR. position == CORNER) &
2001 .AND. domain%x(tMe)%pos .LT. (size(domain%x(tMe)%list(:))+1)/2 ) then
2002 if( domain%list(m)%y(tNbr)%compute%end+nhalo+jshift .GE. jeg .AND. isc .LE. middle)then
2004 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
2005 is = max(is, middle)
2006 select case (position)
2008 i=is; is = isg+ieg-ie; ie = isg+ieg-i
2010 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2012 call insert_update_overlap(overlap, domain%list(m)%pe, &
2013 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
2015 if(debug_update_level .NE. NO_CHECK .AND. set_check) then
2016 je = domain%list(m)%y(tNbr)%compute%end+jshift;
2018 is = max(is, isc); ie = min(ie, iec)
2019 js = max(js, jsc); je = min(je, jec)
2020 if(ie.GE.is .AND. je.GE.js )then
2021 nsend_check = nsend_check+1
2022 if(nsend_check > size(checkList(:)) ) then
2023 call expand_check_overlap_list(checkList, nlist)
2025 call allocate_check_overlap(checkList(nsend_check), 1)
2026 call insert_check_overlap(checkList(nsend_check), domain%list(m)%pe, &
2027 tMe, 4, ONE_HUNDRED_EIGHTY, is, ie, js, je)
2035 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
2036 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
2037 is2 = 0; ie2=-1; js2=0; je2=-1
2038 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2039 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2041 if(js .GT. jeg) then ! je > jeg
2042 if( domain%y(tMe)%cyclic ) then
2043 js = js-joff; je = je-joff
2044 else if(folded_north )then
2046 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2048 else if(je .GT. jeg) then ! split into two parts
2049 if( domain%y(tMe)%cyclic ) then
2050 is2 = is; ie2 = ie; js2 = js; je2 = jeg
2051 js = jeg+1-joff; je = je -joff
2052 else if(folded_north) then
2054 is2 = is; ie2 = ie; js2 = js; je2 = jeg
2056 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2058 if( ie .LT. isg )then
2059 is = is+ioff; ie = ie+ioff
2060 else if( is .LT. isg) then
2061 is3 = isg; ie3 = ie; js3 = js; je3 = je
2062 is = is+ioff; ie = isg-1+ioff;
2066 if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == CORNER .OR. position == NORTH)) then
2067 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2068 isg, ieg, dir, ishift, position, ioff, middle)
2070 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2071 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
2073 if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
2074 isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
2075 if(ie2 .GE. is2) then
2076 if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == CORNER .OR. position == NORTH))then
2077 call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2078 isg, ieg, dir, ishift, position, ioff, middle)
2080 call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2081 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
2085 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2087 if( domain%x(tMe)%cyclic .AND. iec.LT.is )then !try cyclic offset
2088 is = is-ioff; ie = ie-ioff
2089 need_adjust_1 = .false.
2090 if(je .GT. jeg) then
2091 if( domain%y(tMe)%cyclic .AND. jec.LT.js )then !try cyclic offset
2092 js = js-joff; je = je-joff
2093 need_adjust_2 = .false.
2094 if(x_cyclic_offset .NE. 0) then
2095 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2096 else if(y_cyclic_offset .NE. 0) then
2097 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2101 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2102 need_adjust_3 = .false.
2107 if( need_adjust_3 .AND. je.GT.jeg )then
2108 if( need_adjust_2 .AND. domain%y(tMe)%cyclic .AND. jec.LT.js )then !try cyclic offset
2109 js = js-joff; je = je-joff
2110 if( need_adjust_1 .AND. ie.LE.ieg)then
2111 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2113 else if( folded_north )then
2115 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2118 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2119 isg, ieg, jsg, jeg, dir)
2123 !--- copy the overlapping information
2124 if( overlap%count > 0) then
2126 if(nsend > size(overlapList(:)) ) then
2127 call mpp_error(NOTE, 'mpp_domains_define.inc(compute_overlaps): overlapList for send is expanded')
2128 call expand_update_overlap_list(overlapList, nlist)
2130 call add_update_overlap( overlapList(nsend), overlap)
2131 call init_overlap_type(overlap)
2133 end do ! end of send set up.
2135 if(debug_message_passing) then
2136 !--- write out send information
2137 unit = mpp_pe() + 1000
2139 write(unit, *) "********to_pe = " ,overlapList(m)%pe, " count = ",overlapList(m)%count
2140 do n = 1, overlapList(m)%count
2141 write(unit, *) overlapList(m)%is(n), overlapList(m)%ie(n), overlapList(m)%js(n), overlapList(m)%je(n), &
2142 overlapList(m)%dir(n), overlapList(m)%rotation(n)
2145 if(nsend >0) flush(unit)
2148 ! copy the overlapping information into domain data structure
2150 allocate(update%send(nsend))
2151 update%nsend = nsend
2153 call add_update_overlap( update%send(m), overlapList(m) )
2157 if(nsend_check>0) then
2158 check%nsend = nsend_check
2159 allocate(check%send(nsend_check))
2160 do m = 1, nsend_check
2161 call add_check_overlap( check%send(m), checkList(m) )
2165 do m = 1,size(overlapList(:))
2166 call deallocate_overlap_type(overlapList(m))
2169 if(debug_update_level .NE. NO_CHECK .AND. set_check) then
2170 do m = 1,size(checkList(:))
2171 call deallocate_overlap_type(checkList(m))
2175 isgd = isg - domain%whalo
2176 iegd = ieg + domain%ehalo
2177 jsgd = jsg - domain%shalo
2178 jegd = jeg + domain%nhalo
2180 ! begin setting up recv
2184 m = mod( domain%pos+nlist-list, nlist )
2185 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
2186 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
2187 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
2190 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%compute%end+ehalo+ishift
2191 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
2192 is=isc; ie=iec; js=jsc; je=jec
2193 if( domain%symmetry .AND. (position == NORTH .OR. position == CORNER ) &
2194 .AND. ( jsd == je .or. jed == js ) ) then
2195 ! --- do nothing, this point will come from other pe
2197 !--- when the north face is folded, the east halo point at right side domain will be folded.
2198 !--- the position should be on CORNER or NORTH
2199 if( jed == jeg .AND. folded_north .AND. (position == CORNER .OR. position == NORTH) ) then
2200 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2201 isg, ieg, dir, ishift, position, ioff, middle)
2203 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2204 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2205 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
2207 if( ied.GT.ieg )then
2208 if( domain%x(tMe)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2209 is = is+ioff; ie = ie+ioff
2210 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2213 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2214 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2221 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%compute%end+ehalo+ishift
2222 jsd = domain%y(tMe)%compute%begin-shalo; jed = domain%y(tMe)%compute%begin-1
2223 is=isc; ie=iec; js=jsc; je=jec
2224 !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
2225 !--- the other part is both are zero.
2226 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2227 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2228 if(jed .LT. jsg) then ! then jsd < jsg
2229 if( domain%y(tMe)%cyclic ) then
2230 js = js-joff; je = je-joff
2232 else if(jsd .LT. jsg) then !split into two parts
2233 if( domain%y(tMe)%cyclic ) then
2234 js2 = js-joff; je2 = je-joff
2237 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2238 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
2239 if(je2 .GE. js2) call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2240 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
2242 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2243 if( jsd.LT.jsg )then
2244 if( domain%y(tMe)%cyclic .AND. js.GT.jed )then !try cyclic offset
2245 js = js-joff; je = je-joff
2246 need_adjust_1 = .false.
2247 if( ied.GT.ieg )then
2248 if( domain%x(tMe)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2249 is = is+ioff; ie = ie+ioff
2250 need_adjust_2 = .false.
2251 if(x_cyclic_offset .NE. 0) then
2252 call apply_cyclic_offset(js, je, x_cyclic_offset, jsgd, jeg, nj)
2253 else if(y_cyclic_offset .NE. 0) then
2254 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, iegd, ni)
2258 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2259 need_adjust_3 = .false.
2263 if( need_adjust_3 .AND. ied.GT.ieg )then
2264 if( need_adjust_2 .AND. domain%x(tMe)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2265 is = is+ioff; ie = ie+ioff
2266 if( need_adjust_1 .AND. jsd.GE.jsg )then
2267 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2271 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2272 isg, ieg, jsg, jeg, dir)
2277 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
2278 jsd = domain%y(tMe)%compute%begin-shalo; jed = domain%y(tMe)%compute%begin-1
2279 is=isc; ie=iec; js=jsc; je=jec
2281 if( jed .LT. jsg) then ! jsd < jsg
2282 if( domain%y(tMe)%cyclic ) then
2283 js = js-joff; je = je-joff
2284 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2286 else if( jsd.LT.jsg )then ! split into two parts
2287 if( domain%y(tMe)%cyclic)then !try cyclic offset
2288 js2 = js-joff; je2 = je-joff
2291 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2292 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2293 if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2294 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2298 isd = domain%x(tMe)%compute%begin-whalo; ied = domain%x(tMe)%compute%begin-1
2299 jsd = domain%y(tMe)%compute%begin-shalo; jed = domain%y(tMe)%compute%begin-1
2300 is=isc; ie=iec; js=jsc; je=jec
2301 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2302 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2303 if( ied.LT.isg )then ! isd < isg
2304 if( domain%x(tMe)%cyclic ) then
2305 is = is-ioff; ie = ie-ioff
2307 else if (isd.LT.isg )then ! split into two parts
2308 if( domain%x(tMe)%cyclic ) then
2309 is2 = is-ioff; ie2 = ie-ioff
2312 if( jed.LT.jsg )then ! jsd < jsg
2313 if( domain%y(tMe)%cyclic ) then
2314 js = js-joff; je = je-joff
2316 else if( jsd.LT.jsg )then ! split into two parts
2317 if( domain%y(tMe)%cyclic ) then
2318 js2 = js-joff; je2 = je-joff
2322 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2323 if( jsd.LT.jsg )then
2324 if( domain%y(tMe)%cyclic .AND. js.GT.jed )then !try cyclic offset
2325 js = js-joff; je = je-joff
2326 need_adjust_1 = .false.
2327 if( isd.LT.isg )then
2328 if( domain%x(tMe)%cyclic .AND. is.GT.ied )then !try cyclic offset
2329 is = is-ioff; ie = ie-ioff
2330 need_adjust_2 = .false.
2331 if(x_cyclic_offset .NE. 0) then
2332 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsgd, jeg, nj)
2333 else if(y_cyclic_offset .NE. 0) then
2334 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isgd, ieg, ni)
2338 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2339 need_adjust_3 = .false.
2343 if( need_adjust_3 .AND. isd.LT.isg )then
2344 if( need_adjust_2 .AND. domain%x(tMe)%cyclic .AND. is.GT.ied )then !try cyclic offset
2345 is = is-ioff; ie = ie-ioff
2346 if(need_adjust_1 .AND. jsd.GE.jsg) then
2347 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2352 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2353 isg, ieg, jsg, jeg, dir)
2355 if(ie2 .GE. is2)call fill_overlap(overlap, domain, m, is2, ie2, js, je, isd, ied, jsd, jed, &
2356 isg, ieg, jsg, jeg, dir)
2357 if(je2 .GE. js2)call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2358 isg, ieg, jsg, jeg, dir)
2360 if(ie2 .GE. is2 .AND. je2 .GE. js2)call fill_overlap(overlap, domain, m, is2, ie2, js2, je2, isd, ied, jsd, &
2361 & jed, isg, ieg, jsg, jeg, dir)
2366 isd = domain%x(tMe)%compute%begin-whalo; ied = domain%x(tMe)%compute%begin-1
2367 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
2368 is=isc; ie=iec; js=jsc; je=jec
2370 !--- when the north face is folded, some point at j=nj will be folded.
2371 !--- the position should be on CORNER or NORTH
2372 if( jed == jeg .AND. folded_north .AND. (position == CORNER .OR. position == NORTH) ) then
2373 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2374 isg, ieg, dir, ishift, position, ioff, middle)
2376 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2377 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2378 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, symmetry=domain%symmetry)
2380 if( isd.LT.isg )then
2381 if( domain%x(tMe)%cyclic .AND. is.GT.ied )then !try cyclic offset
2382 is = is-ioff; ie = ie-ioff
2383 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2386 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2387 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2394 isd = domain%x(tMe)%compute%begin-whalo; ied = domain%x(tMe)%compute%begin-1
2395 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%compute%end+nhalo+jshift
2396 is=isc; ie=iec; js=jsc; je=jec
2397 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2398 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2399 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2401 if( jsd .GT. jeg ) then ! jed > jeg
2402 if( domain%y(tMe)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2403 js = js+joff; je = je+joff
2404 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2405 else if( folded_north )then
2407 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2409 else if( jed.GT.jeg )then ! split into two parts
2410 if( domain%y(tMe)%cyclic)then !try cyclic offset
2411 is2 = is; ie2 = ie; js2 = js; je2 = je
2412 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2413 js = js + joff; je = je + joff
2415 else if( folded_north )then
2417 is2 = is; ie2 = ie; js2 = js; je2 = je
2418 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2420 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2421 if(isd < isg .and. ied .GE. isg .and. domain%symmetry) then
2422 isd3 = isd; ied3 = isg-1
2423 jsd3 = jsd; jed3 = jed
2424 is3 = is-ioff; ie3=ie-ioff
2431 if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2432 .AND. (position == CORNER .OR. position == NORTH)) then
2433 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2434 isg, ieg, dir, ishift, position, ioff, middle)
2436 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2437 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
2440 if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2441 & jed3, isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
2443 if(ie2 .GE. is2) then
2444 if( jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2445 .AND. (position == CORNER .OR. position == NORTH)) then
2446 call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2447 isg, ieg, dir, ishift, position, ioff, middle)
2449 call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2450 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
2454 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2455 if( jed.GT.jeg )then
2456 if( domain%y(tMe)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2457 js = js+joff; je = je+joff
2458 need_adjust_1 = .false.
2459 if( isd.LT.isg )then
2460 if( domain%x(tMe)%cyclic .AND. is.GE.ied )then !try cyclic offset
2461 is = is-ioff; ie = ie-ioff
2462 need_adjust_2 = .false.
2463 if(x_cyclic_offset .NE. 0) then
2464 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jegd, nj)
2465 else if(y_cyclic_offset .NE. 0) then
2466 call apply_cyclic_offset(is, ie, y_cyclic_offset, isgd, ieg, ni)
2470 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2471 need_adjust_3 = .false.
2473 else if( folded_north )then
2475 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2478 if( need_adjust_3 .AND. isd.LT.isg )then
2479 if( need_adjust_2 .AND. domain%x(tMe)%cyclic .AND. is.GE.ied )then !try cyclic offset
2480 is = is-ioff; ie = ie-ioff
2481 if( need_adjust_1 .AND. jed.LE.jeg )then
2482 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2486 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2487 isg, ieg, jsg, jeg, dir)
2490 !--- when north edge is folded, is will be less than isg when position is EAST and CORNER
2491 if(is .LT. isg .AND. domain%x(tMe)%cyclic) then
2493 call insert_update_overlap(overlap, domain%list(m)%pe, &
2494 is, is, js, je, isd, ied, jsd, jed, dir, folded )
2500 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
2501 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%compute%end+nhalo+jshift
2502 is=isc; ie=iec; js=jsc; je=jec
2504 !--- when domain symmetry and position is EAST or CORNER, the point at i=isd will
2505 !--- come from two pe ( there will be only one point on one pe. ).
2506 if( domain%symmetry .AND. (position == EAST .OR. position == CORNER ) &
2507 .AND. (isd == ie .or. ied == is ) .AND. (.not. folded_north) ) then
2508 !--- do nothing, this point will come from other pe
2511 if( jsd .GT. jeg ) then ! jed > jeg
2512 if( domain%y(tMe)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2513 js = js+joff; je = je+joff
2514 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2515 else if( folded_north )then
2517 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2519 else if( jed.GT.jeg )then ! split into two parts
2520 if( domain%y(tMe)%cyclic)then !try cyclic offset
2521 is2 = is; ie2 = ie; js2 = js; je2 = je
2522 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2523 js = js + joff; je = je + joff
2525 else if( folded_north )then
2527 is2 = is; ie2 = ie; js2 = js; je2 = je
2528 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2530 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2533 if(x_cyclic_offset == 0 .and. y_cyclic_offset == 0) then
2534 if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2535 .AND. (position == CORNER .OR. position == NORTH)) then
2536 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2537 isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2539 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2540 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded, symmetry=domain%symmetry)
2543 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2544 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2546 if(ie2 .GE. is2) then
2547 if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2548 .AND. (position == CORNER .OR. position == NORTH)) then
2549 call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2550 isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2552 call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2553 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded, symmetry=domain%symmetry)
2558 !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2559 if(is .LT. isg .AND. domain%x(tMe)%cyclic) then
2561 ! call insert_update_overlap( overlap, domain%list(m)%pe, &
2562 ! is, is, js, je, isd, ied, jsd, jed, dir, folded)
2565 !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2566 !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2567 !--- only position at NORTH and CORNER need to be considered
2569 if( folded_north .AND. (position == NORTH .OR. position == CORNER) &
2570 .AND. domain%x(tMe)%pos .GE. size(domain%x(tMe)%list(:))/2) then
2571 if( jed .GE. jeg .AND. ied .GE. middle)then
2572 jsd = jeg; jed = jeg
2573 is=isc; ie=iec; js = jsc; je = jec
2574 isd = max(isd, middle)
2575 select case (position)
2577 i=is; is = isg+ieg-ie; ie = isg+ieg-i
2579 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2581 call insert_update_overlap(overlap, domain%list(m)%pe, &
2582 is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
2584 if(debug_update_level .NE. NO_CHECK .AND. set_check) then
2585 jsd = domain%y(tMe)%compute%end+jshift; jed = jsd
2587 is = max(is, isd); ie = min(ie, ied)
2588 js = max(js, jsd); je = min(je, jed)
2589 if(ie.GE.is .AND. je.GE.js )then
2590 nrecv_check = nrecv_check+1
2591 if(nrecv_check > size(checkList(:)) ) then
2592 call expand_check_overlap_list(checkList, nlist)
2594 call allocate_check_overlap(checkList(nrecv_check), 1)
2595 call insert_check_overlap(checkList(nrecv_check), domain%list(m)%pe, &
2596 tMe, 4, ONE_HUNDRED_EIGHTY, is, ie, js, je)
2606 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%compute%end+ehalo+ishift
2607 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%compute%end+nhalo+jshift
2608 is=isc; ie=iec; js=jsc; je=jec
2609 is2 = 0; ie2=-1; js2=0; je2=-1
2610 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2611 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2613 if( jsd .GT. jeg ) then ! jed > jeg
2614 if( domain%y(tMe)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2615 js = js+joff; je = je+joff
2616 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2617 else if( folded_north )then
2619 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2621 else if( jed.GT.jeg )then ! split into two parts
2622 if( domain%y(tMe)%cyclic)then !try cyclic offset
2623 is2 = is; ie2 = ie; js2 = js; je2 = je
2624 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2625 js = js + joff; je = je + joff
2627 else if( folded_north )then
2629 is2 = is; ie2 = ie; js2 = js; je2 = je
2630 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2632 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2633 if(ied > ieg .and. isd .LE. ieg .and. domain%symmetry) then
2634 isd3 = ieg+1; ied3 = ied
2635 jsd3 = jsd; jed3 = jed
2636 is3 = is+ioff; ie3=ie+ioff
2642 if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2643 .AND. (position == CORNER .OR. position == NORTH)) then
2644 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2645 isg, ieg, dir, ishift, position, ioff, middle)
2647 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2648 isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
2650 if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2651 & jed3, isg, ieg, dir, ioff, domain%x(tMe)%cyclic, folded)
2652 if(ie2 .GE. is2) then
2653 if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2654 .AND. (position == CORNER .OR. position == NORTH)) then
2655 call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2656 isg, ieg, dir, ishift, position, ioff, middle)
2658 call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2659 isg, ieg, dir, ioff, domain%x(tMe)%cyclic)
2663 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2664 if( jed.GT.jeg )then
2665 if( domain%y(tMe)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2666 js = js+joff; je = je+joff
2667 need_adjust_1 = .false.
2668 if( ied.GT.ieg )then
2669 if( domain%x(tMe)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2670 is = is+ioff; ie = ie+ioff
2671 need_adjust_2 = .false.
2672 if(x_cyclic_offset .NE. 0) then
2673 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jegd, nj)
2674 else if(y_cyclic_offset .NE. 0) then
2675 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, iegd, ni)
2679 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2680 need_adjust_3 = .false.
2682 else if( folded_north )then
2684 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2687 if( need_adjust_3 .AND. ied.GT.ieg )then
2688 if( need_adjust_2 .AND. domain%x(tMe)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2689 is = is+ioff; ie = ie+ioff
2690 if( need_adjust_1 .AND. jed.LE.jeg)then
2691 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2695 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2696 isg, ieg, jsg, jeg, dir)
2700 !--- copy the overlapping information
2701 if( overlap%count > 0) then
2703 if(nrecv > size(overlapList(:)) )then
2704 call mpp_error(NOTE, 'mpp_domains_define.inc(compute_overlaps): overlapList for recv is expanded')
2705 call expand_update_overlap_list(overlapList, nlist)
2707 call add_update_overlap( overlapList(nrecv), overlap)
2708 call init_overlap_type(overlap)
2710 enddo ! end of recv do loop
2712 if(debug_message_passing) then
2713 !--- write out send information
2714 unit = mpp_pe() + 1000
2716 write(unit, *) "********from_pe = " ,overlapList(m)%pe, " count = ",overlapList(m)%count
2717 do n = 1, overlapList(m)%count
2718 write(unit, *) overlapList(m)%is(n), overlapList(m)%ie(n), overlapList(m)%js(n), overlapList(m)%je(n), &
2719 overlapList(m)%dir(n), overlapList(m)%rotation(n)
2722 if(nrecv >0) flush(unit)
2725 ! copy the overlapping information into domain
2727 allocate(update%recv(nrecv))
2728 update%nrecv = nrecv
2730 call add_update_overlap( update%recv(m), overlapList(m) )
2731 do n = 1, update%recv(m)%count
2732 if(update%recv(m)%tileNbr(n) == domain%tile_id(tMe)) then
2733 if(update%recv(m)%dir(n) == 1) domain%x(tMe)%loffset = 0
2734 if(update%recv(m)%dir(n) == 7) domain%y(tMe)%loffset = 0
2740 if(nrecv_check>0) then
2741 check%nrecv = nrecv_check
2742 allocate(check%recv(nrecv_check))
2743 do m = 1, nrecv_check
2744 call add_check_overlap( check%recv(m), checkList(m) )
2748 call deallocate_overlap_type(overlap)
2749 do m = 1,size(overlapList(:))
2750 call deallocate_overlap_type(overlapList(m))
2753 if(debug_update_level .NE. NO_CHECK .AND. set_check) then
2754 do m = 1,size(checkList(:))
2755 call deallocate_overlap_type(checkList(m))
2759 deallocate(overlapList)
2760 if(set_check) deallocate(checkList)
2761 domain%initialized = .true.
2763 end subroutine compute_overlaps
2766 subroutine fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2767 isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2768 type(overlap_type), intent(inout) :: overlap
2769 type(domain2d), intent(inout) :: domain
2770 integer, intent(in ) :: m, is, ie, js, je
2771 integer, intent(in ) :: isc, iec, jsc, jec
2772 integer, intent(in ) :: isg, ieg, dir, ioff
2773 logical, intent(in ) :: is_cyclic
2774 logical, optional, intent(in ) :: folded, symmetry
2776 call insert_update_overlap( overlap, domain%list(m)%pe, &
2777 is, ie, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2779 if(ie .GT. ieg) then
2780 call insert_update_overlap( overlap, domain%list(m)%pe, &
2781 is-ioff, ie-ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2782 else if( is .LT. isg ) then
2783 call insert_update_overlap( overlap, domain%list(m)%pe, &
2784 is+ioff, ie+ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2788 end subroutine fill_overlap_send_nofold
2789 !##################################################################################
2790 subroutine fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2791 isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2792 type(overlap_type), intent(inout) :: overlap
2793 type(domain2d), intent(inout) :: domain
2794 integer, intent(in ) :: m, is, ie, js, je
2795 integer, intent(in ) :: isc, iec, jsc, jec
2796 integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2797 logical, optional, intent(in ) :: symmetry
2798 integer :: is1, ie1, is2, ie2, i
2800 !--- consider at j = jeg for west edge.
2801 !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2802 if(position == CORNER .AND. .NOT. domain%symmetry .AND. is .LE. isg-1 .AND. ie .GE. isg-1) then
2803 call insert_update_overlap(overlap, domain%list(m)%pe, &
2804 isg-1+ioff, isg-1+ioff, je, je, isc, iec, jsc, jec, dir, .true.)
2807 is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2810 is2 = is-ioff; ie2 = ie-ioff
2811 else if( ie > ieg ) then ! split into two parts
2813 is2 = ieg+1-ioff; ie2 = ie-ioff
2814 else if( is .GE. middle ) then
2816 else if( ie .GE. middle ) then ! split into two parts
2817 is1 = middle; ie1 = ie
2818 is2 = is; ie2 = middle-1
2819 else if( ie < isg ) then ! west boundary
2820 is1 = is+ieg-isg+1-ishift; ie1 = ie+ieg-isg+1-ishift
2821 else if( is < isg ) then ! split into two parts
2822 is1 = is+ieg-isg+1-ishift; ie1 = isg-1+ieg-isg+1-ishift
2828 if( ie1 .GE. is1) then
2829 call insert_update_overlap( overlap, domain%list(m)%pe, &
2830 is1, ie1, js, je-1, isc, iec, jsc, jec, dir, symmetry=symmetry)
2832 select case (position)
2834 i=is1; is1 = isg+ieg-ie1; ie1 = isg+ieg-i
2836 i=is1; is1 = isg+ieg-ie1-1+ishift; ie1 = isg+ieg-i-1+ishift
2838 call insert_update_overlap( overlap, domain%list(m)%pe, &
2839 is1, ie1, je, je, isc, iec, jsc, jec, dir, .true., symmetry=symmetry)
2842 if(ie2 .GE. is2) then
2843 call insert_update_overlap( overlap, domain%list(m)%pe, &
2844 is2, ie2, js, je, isc, iec, jsc, jec, dir)
2847 end subroutine fill_overlap_send_fold
2850 !#############################################################################
2851 subroutine fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2852 isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2853 type(overlap_type), intent(inout) :: overlap
2854 type(domain2d), intent(inout) :: domain
2855 integer, intent(in ) :: m, is, ie, js, je
2856 integer, intent(in ) :: isd, ied, jsd, jed
2857 integer, intent(in ) :: isg, ieg, dir, ioff
2858 logical, intent(in ) :: is_cyclic
2859 logical, optional, intent(in ) :: folded, symmetry
2860 integer :: is1, ie1, is2, ie2
2861 integer :: isd1, ied1, isd2, ied2
2863 is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2867 call insert_update_overlap( overlap, domain%list(m)%pe, &
2868 is, ie, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2870 if(ied .GT. ieg) then
2871 call insert_update_overlap( overlap, domain%list(m)%pe, &
2872 is+ioff, ie+ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2873 else if( isd .LT. isg ) then
2874 call insert_update_overlap( overlap, domain%list(m)%pe, &
2875 is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2876 else if ( is .LT. isg ) then
2877 call insert_update_overlap( overlap, domain%list(m)%pe, &
2878 is+ioff, ie+ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2879 else if ( ie .GT. ieg ) then
2880 call insert_update_overlap( overlap, domain%list(m)%pe, &
2881 is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2885 end subroutine fill_overlap_recv_nofold
2886 !#################################################################################
2887 subroutine fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2888 isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2889 type(overlap_type), intent(inout) :: overlap
2890 type(domain2d), intent(inout) :: domain
2891 integer, intent(in ) :: m, is, ie, js, je
2892 integer, intent(in ) :: isd, ied, jsd, jed
2893 integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2894 logical, optional, intent(in ) :: symmetry
2895 integer :: is1, ie1, is2, ie2, is3, ie3
2896 integer :: isd1, ied1, isd2, ied2
2898 !--- consider at j = jeg for west edge.
2899 !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2900 if( position == CORNER .AND. .NOT. domain%symmetry .AND. isd .LE. isg-1 .AND. ied .GE. isg-1 ) then
2901 call insert_update_overlap( overlap, domain%list(m)%pe, &
2902 is-ioff, ie-ioff, js, je, isg-1, isg-1, jed, jed, dir, .true.)
2905 is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2908 select case (position)
2910 is3 = isg+ieg-ie; ie3 = isg+ieg-is
2912 is3 = isg+ieg-ie-1+ishift; ie3 = isg+ieg-is-1+ishift
2915 if(isd .GT. ieg) then ! east
2916 is2 = is + ioff; ie2 = ie + ioff;
2917 else if(ied .GT. ieg) then ! split into two parts
2919 isd1 = isd; ied1 = ieg;
2920 is2 = is + ioff; ie2 = ie + ioff
2921 isd2 = ieg + 1; ied2 = ied
2922 else if(isd .GE. middle) then
2924 else if(ied .GE. middle) then ! split into two parts
2926 isd1 = middle; ied1 = ied
2928 isd2 = isd; ied2 = middle-1
2929 else if(ied .LT. isg) then
2930 is1 = is - ioff; ie1 = ie - ioff;
2931 is3 = is3 - ioff; ie3 = ie3 - ioff;
2932 else if(isd .LT. isg) then ! split into two parts
2933 is1 = is - ioff; ie1 = ie - ioff;
2934 is3 = is3 - ioff; ie3 = ie3 - ioff;
2935 isd1 = isd; ied1 = isg-1
2937 isd2 = isg; ied2 = ied
2940 isd2 = isd; ied2 = ied
2943 if( ie1 .GE. is1) then
2944 call insert_update_overlap( overlap, domain%list(m)%pe, &
2945 is1, ie1, js, je, isd1, ied1, jsd, jed-1, dir, symmetry=symmetry)
2947 call insert_update_overlap( overlap, domain%list(m)%pe, &
2948 is3, ie3, js, je, isd1, ied1, jed, jed, dir, .true., symmetry=symmetry)
2951 if(ie2 .GE. is2) then
2952 call insert_update_overlap( overlap, domain%list(m)%pe, &
2953 is2, ie2, js, je, isd2, ied2, jsd, jed, dir)
2956 end subroutine fill_overlap_recv_fold
2958 !#####################################################################################
2959 subroutine fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2960 isg, ieg, jsg, jeg, dir, reverse, symmetry)
2961 type(overlap_type), intent(inout) :: overlap
2962 type(domain2d), intent(inout) :: domain
2963 integer, intent(in ) :: m, is, ie, js, je
2964 integer, intent(in ) :: isc, iec, jsc, jec
2965 integer, intent(in ) :: isg, ieg, jsg, jeg
2966 integer, intent(in ) :: dir
2967 logical, optional, intent(in ) :: reverse, symmetry
2969 if(js > je) then ! seperate into two regions due to x_cyclic_offset is nonzero, the two region are
2970 ! (js, jeg) and (jsg, je).
2971 call insert_update_overlap( overlap, domain%list(m)%pe, &
2972 is, ie, jsg, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2973 call insert_update_overlap( overlap, domain%list(m)%pe, &
2974 is, ie, js, jeg, isc, iec, jsc, jec, dir, reverse, symmetry)
2975 else if(is > ie) then ! seperate into two regions due to y_cyclic_offset is nonzero, the two region are
2976 ! (is, ieg) and (isg, ie).
2977 call insert_update_overlap( overlap, domain%list(m)%pe, &
2978 is, ieg, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2979 call insert_update_overlap( overlap, domain%list(m)%pe, &
2980 isg, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2982 call insert_update_overlap( overlap, domain%list(m)%pe, &
2983 is, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2987 end subroutine fill_overlap
2989 !####################################################################################
2990 subroutine compute_overlaps_fold_south( domain, position, ishift, jshift)
2991 !computes remote domain overlaps
2992 !assumes only one in each direction
2993 !will calculate the overlapping for T,E,C,N-cell seperately.
2994 type(domain2D), intent(inout) :: domain
2995 integer, intent(in) :: position, ishift, jshift
2997 integer :: i, m, n, nlist, tMe, tNbr, dir
2998 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
2999 integer :: isg, ieg, jsg, jeg, ioff, joff
3000 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3001 integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3003 type(overlap_type) :: overlap
3004 type(overlapSpec), pointer :: update=>NULL()
3005 type(overlap_type), pointer :: overlapList(:)=>NULL()
3006 type(overlap_type), pointer :: checkList(:)=>NULL()
3007 type(overlapSpec), pointer :: check =>NULL()
3008 integer :: nsend, nrecv
3009 integer :: nsend_check, nrecv_check
3012 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3013 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3014 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3015 if(size(domain%x(:)) > 1) return
3017 !--- if there is no halo, no need to compute overlaps.
3018 if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3020 !--- when there is only one tile, n will equal to np
3021 nlist = size(domain%list(:))
3023 select case(position)
3025 update => domain%update_T
3028 update => domain%update_C
3029 check => domain%check_C
3031 update => domain%update_E
3032 check => domain%check_E
3034 update => domain%update_N
3035 check => domain%check_N
3037 call mpp_error(FATAL, &
3038 "mpp_domains_define.inc(compute_overlaps_fold_south): the value of position should be CENTER, EAST, &
3042 allocate(overlapList(MAXLIST) )
3043 allocate(checkList(MAXLIST) )
3045 !--- overlap is used to store the overlapping temporarily.
3046 call allocate_update_overlap( overlap, MAXOVERLAP)
3049 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3050 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3051 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3052 update%xbegin = ism; update%xend = iem
3053 update%ybegin = jsm; update%yend = jem
3054 if(ASSOCIATED(check)) then
3055 check%xbegin = ism; check%xend = iem
3056 check%ybegin = jsm; check%yend = jem
3058 update%whalo = domain%whalo; update%ehalo = domain%ehalo
3059 update%shalo = domain%shalo; update%nhalo = domain%nhalo
3060 whalo = domain%whalo; ehalo = domain%ehalo
3061 shalo = domain%shalo; nhalo = domain%nhalo
3066 middle = (isg+ieg)/2+1
3069 if(.NOT. BTEST(domain%fold,SOUTH)) then
3070 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3071 "boundary condition in y-direction should be folded-south for "//trim(domain%name))
3073 if(.NOT. domain%x(tMe)%cyclic) then
3074 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3075 "boundary condition in x-direction should be cyclic for "//trim(domain%name))
3078 if(.not. domain%symmetry) then
3079 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3080 "when south boundary is folded, the domain must be symmetry for "//trim(domain%name))
3086 m = mod( domain%pos+list, nlist )
3087 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
3088 !to_pe's eastern halo
3090 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3091 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
3092 !--- to make sure the consistence between pes
3093 if( (position == NORTH .OR. position == CORNER ) .AND. ( jsc == je .or. jec == js ) ) then
3094 !--- do nothing, this point will come from other pe
3096 if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3097 is = is-ioff; ie = ie-ioff
3099 !--- when the south face is folded, the east halo point at right side domain will be folded.
3100 !--- the position should be on CORNER or NORTH
3101 if( js == jsg .AND. (position == CORNER .OR. position == NORTH) &
3102 .AND. is .GE. middle .AND. domain%list(m)%x(tNbr)%compute%end+ehalo+jshift .LE. ieg ) then
3103 call insert_update_overlap( overlap, domain%list(m)%pe, &
3104 is, ie, js+1, je, isc, iec, jsc, jec, dir)
3105 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3107 select case (position)
3109 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3111 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3113 call insert_update_overlap( overlap, domain%list(m)%pe, &
3114 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3116 call insert_update_overlap( overlap, domain%list(m)%pe, &
3117 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3124 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3125 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3126 if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3127 is = is-ioff; ie = ie-ioff
3131 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3134 call insert_update_overlap( overlap, domain%list(m)%pe, &
3135 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3137 !to_pe's southern halo
3140 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
3141 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3145 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3147 !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3148 !--- no need to send, because the data on that point will come from other pe.
3149 !--- come from two pe ( there will be only one point on one pe. ).
3150 if( (position == EAST .OR. position == CORNER ) .AND. ( isc == ie .or. iec == is ) ) then
3151 !--- do nothing, this point will come from other pe
3153 call insert_update_overlap( overlap, domain%list(m)%pe, &
3154 is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3156 !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3157 if(is .LT. isg) then
3159 call insert_update_overlap( overlap, domain%list(m)%pe, &
3160 is, is, js, je, isc, iec, jsc, jec, dir, folded)
3166 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3167 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3168 if( isg.GT.is .AND. ie.LT.isc )then !cyclic offset
3169 is = is+ioff; ie = ie+ioff
3173 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3175 call insert_update_overlap( overlap, domain%list(m)%pe, &
3176 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3177 !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3178 if(is .LT. isg) then
3180 call insert_update_overlap( overlap, domain%list(m)%pe, &
3181 is, is, js, je, isc, iec, jsc, jec, dir, folded)
3184 !to_pe's western halo
3186 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3187 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
3189 !--- to make sure the consistence between pes
3190 if( (position == NORTH .OR. position == CORNER ) .AND. ( jsc == je .or. jec == js ) ) then
3191 !--- do nothing, this point will come from other pe
3193 if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3194 is = is+ioff; ie = ie+ioff
3196 !--- when the south face is folded, some point at j=nj will be folded.
3197 !--- the position should be on CORNER or NORTH
3198 if( js == jsg .AND. (position == CORNER .OR. position == NORTH) &
3199 .AND. ( domain%list(m)%x(tNbr)%compute%begin == isg .OR. &
3200 & domain%list(m)%x(tNbr)%compute%begin-1 .GE. middle)) then
3201 call insert_update_overlap( overlap, domain%list(m)%pe, &
3202 is, ie, js+1, je, isc, iec, jsc, jec, dir)
3203 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3204 js = domain%list(m)%y(tNbr)%compute%begin; je = js
3205 if ( domain%list(m)%x(tNbr)%compute%begin == isg ) then
3206 select case (position)
3208 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3210 i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3212 if(ie .GT. domain%x(tMe)%compute%end+ishift) call mpp_error( FATAL, &
3213 'mpp_domains_define.inc(compute_overlaps_fold_south): west edge ubound error send.' )
3215 select case (position)
3217 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3219 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3222 call insert_update_overlap( overlap, domain%list(m)%pe, &
3223 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3225 call insert_update_overlap( overlap, domain%list(m)%pe, &
3226 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3232 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3233 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3234 if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3235 is = is+ioff; ie = ie+ioff
3237 call insert_update_overlap( overlap, domain%list(m)%pe, &
3238 is, ie, js, je, isc, iec, jsc, jec, dir)
3240 !to_pe's northern halo
3242 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
3243 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3244 call insert_update_overlap( overlap, domain%list(m)%pe, &
3245 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3249 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3250 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3251 if( ie.GT.ieg .AND. iec.LT.is )then !cyclic offset
3252 is = is-ioff; ie = ie-ioff
3254 call insert_update_overlap( overlap, domain%list(m)%pe, &
3255 is, ie, js, je, isc, iec, jsc, jec, dir)
3257 !--- Now calculate the overlapping for fold-edge.
3258 !--- only position at NORTH and CORNER need to be considered
3259 if( ( position == NORTH .OR. position == CORNER) ) then
3260 if( domain%y(tMe)%data%begin .LE. jsg .AND. jsg .LE. domain%y(tMe)%data%end+jshift )then !fold
3263 !--- calculate the overlapping for sending
3264 if( domain%x(tMe)%pos .LT. (size(domain%x(tMe)%list(:))+1)/2 )then
3265 js = domain%list(m)%y(tNbr)%compute%begin; je = js
3266 if( js == jsg )then ! fold is within domain.
3267 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
3268 select case (position)
3270 is = max(is, middle)
3271 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3273 is = max(is, middle)
3274 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3276 call insert_update_overlap(overlap, domain%list(m)%pe, &
3277 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3278 is = max(is, isc); ie = min(ie, iec)
3279 js = max(js, jsc); je = min(je, jec)
3280 if(debug_update_level .NE. NO_CHECK .AND. ie.GE.is .AND. je.GE.js )then
3281 nsend_check = nsend_check+1
3282 call allocate_check_overlap(checkList(nsend_check), 1)
3283 call insert_check_overlap(checkList(nsend_check), domain%list(m)%pe, &
3284 tMe, 2, ONE_HUNDRED_EIGHTY, is, ie, js, je)
3291 !--- copy the overlapping information
3292 if( overlap%count > 0) then
3294 if(nsend > size(overlapList(:)) ) then
3295 call mpp_error(NOTE, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for send is expanded')
3296 call expand_update_overlap_list(overlapList, nlist)
3298 call add_update_overlap(overlapList(nsend), overlap)
3299 call init_overlap_type(overlap)
3301 end do ! end of send set up.
3303 if(debug_message_passing) then
3304 !--- write out send information
3305 unit = mpp_pe() + 1000
3307 write(unit, *) "********to_pe = " ,overlapList(m)%pe, " count = ",overlapList(m)%count
3308 do n = 1, overlapList(m)%count
3309 write(unit, *) overlapList(m)%is(n), overlapList(m)%ie(n), overlapList(m)%js(n), overlapList(m)%je(n), &
3310 overlapList(m)%dir(n), overlapList(m)%rotation(n)
3313 if( nsend > 0) flush(unit)
3316 ! copy the overlapping information into domain data structure
3318 allocate(update%send(nsend))
3319 update%nsend = nsend
3321 call add_update_overlap( update%send(m), overlapList(m) )
3325 if(nsend_check>0) then
3326 allocate(check%send(nsend_check))
3327 check%nsend = nsend_check
3328 do m = 1, nsend_check
3329 call add_check_overlap( check%send(m), checkList(m) )
3333 do m = 1,size(overlapList(:))
3334 call deallocate_overlap_type(overlapList(m))
3337 if(debug_update_level .NE. NO_CHECK) then
3338 do m = 1,size(checkList(:))
3339 call deallocate_overlap_type(checkList(m))
3343 isgd = isg - domain%whalo
3344 iegd = ieg + domain%ehalo
3345 jsgd = jsg - domain%shalo
3346 jegd = jeg + domain%nhalo
3348 ! begin setting up recv
3352 m = mod( domain%pos+nlist-list, nlist )
3353 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
3354 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
3355 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
3358 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
3359 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
3360 is=isc; ie=iec; js=jsc; je=jec
3361 if( (position == NORTH .OR. position == CORNER ) .AND. ( jsd == je .or. jed == js ) ) then
3362 ! --- do nothing, this point will come from other pe
3364 if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3365 is = is+ioff; ie = ie+ioff
3368 !--- when the south face is folded, the east halo point at right side domain will be folded.
3369 !--- the position should be on CORNER or NORTH
3370 if( jsd == jsg .AND. (position == CORNER .OR. position == NORTH) &
3371 .AND. isd .GE. middle .AND. ied .LE. ieg ) then
3372 call insert_update_overlap( overlap, domain%list(m)%pe, &
3373 is, ie, js, je, isd, ied, jsd+1, jed, dir)
3374 is=isc; ie=iec; js=jsc; je=jec
3376 select case (position)
3378 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3380 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3382 call insert_update_overlap( overlap, domain%list(m)%pe, &
3383 is, ie, js, je, isd, ied, jsd, jed, dir, .TRUE.)
3385 call insert_update_overlap( overlap, domain%list(m)%pe, &
3386 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3393 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
3394 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
3395 is=isc; ie=iec; js=jsc; je=jec
3396 if( jsd.LT.jsg )then
3398 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3400 if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3401 is = is+ioff; ie = ie+ioff
3403 call insert_update_overlap(overlap, domain%list(m)%pe, &
3404 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3409 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
3410 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
3411 is=isc; ie=iec; js=jsc; je=jec
3412 if( jsd.LT.jsg )then
3414 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3416 if( (position == EAST .OR. position == CORNER ) .AND. (isd == ie .or. ied == is ) ) then
3417 !--- do nothing, this point will come from other pe
3419 call insert_update_overlap(overlap, domain%list(m)%pe, &
3420 is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
3422 !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3423 if(is .LT. isg ) then
3425 call insert_update_overlap(overlap, domain%list(m)%pe, &
3426 is, is, js, je, isd, ied, jsd, jed, dir, folded)
3432 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
3433 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
3434 is=isc; ie=iec; js=jsc; je=jec
3435 if( jsd.LT.jsg )then
3437 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3439 if( isd.LT.isg .AND. is.GT.ied ) then ! cyclic offset
3440 is = is-ioff; ie = ie-ioff
3442 call insert_update_overlap(overlap, domain%list(m)%pe, &
3443 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3444 !--- when southth edge is folded, is will be less than isg when position is EAST and CORNER
3445 if(is .LT. isg ) then
3447 call insert_update_overlap(overlap, domain%list(m)%pe, &
3448 is, is, js, je, isd, ied, jsd, jed, dir, folded )
3453 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
3454 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
3455 is=isc; ie=iec; js=jsc; je=jec
3456 if( (position == NORTH .OR. position == CORNER ) .AND. ( jsd == je .or. jed == js ) ) then
3457 ! --- do nothing, this point will come from other pe
3459 if( isd.LT.isg .AND. is.GT.ied )then ! cyclic offset
3460 is = is-ioff; ie = ie-ioff
3462 !--- when the south face is folded, some point at j=nj will be folded.
3463 !--- the position should be on CORNER or NORTH
3464 if( jsd == jsg .AND. (position == CORNER .OR. position == NORTH) &
3465 .AND. ( isd < isg .OR. ied .GE. middle ) ) then
3466 call insert_update_overlap(overlap, domain%list(m)%pe, &
3467 is, ie, js, je, isd, ied, jsd+1, jed, dir)
3468 is=isc; ie=iec; js=jsc; je=jec
3470 select case (position)
3472 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3474 ied = ied -1 + ishift
3475 i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3477 if(ie .GT. domain%x(tMe)%compute%end+ishift) call mpp_error( FATAL, &
3478 'mpp_domains_define.inc(compute_overlaps): west edge ubound error recv.' )
3480 select case (position)
3482 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3484 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3487 call insert_update_overlap(overlap, domain%list(m)%pe, &
3488 is, ie, js, je, isd, ied, jsd, jsd, dir, .TRUE.)
3490 call insert_update_overlap(overlap, domain%list(m)%pe, &
3491 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3497 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
3498 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
3499 is=isc; ie=iec; js=jsc; je=jec
3500 if( isd.LT.isg .AND. is.GE.ied )then !cyclic offset
3501 is = is-ioff; ie = ie-ioff
3504 call insert_update_overlap( overlap, domain%list(m)%pe, &
3505 is, ie, js, je, isd, ied, jsd, jed, dir)
3509 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
3510 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
3511 is=isc; ie=iec; js=jsc; je=jec
3512 call insert_update_overlap( overlap, domain%list(m)%pe, &
3513 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3517 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
3518 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
3519 is=isc; ie=iec; js=jsc; je=jec
3520 if( ied.GT.ieg .AND. ie.LT.isd )then ! cyclic offset
3521 is = is+ioff; ie = ie+ioff
3523 call insert_update_overlap( overlap, domain%list(m)%pe, &
3524 is, ie, js, je, isd, ied, jsd, jed, dir)
3526 !--- Now calculate the overlapping for fold-edge.
3527 !--- for folded-south-edge, only need to consider to_pe's south(3) direction
3528 !--- only position at NORTH and CORNER need to be considered
3529 if( ( position == NORTH .OR. position == CORNER) ) then
3530 if( domain%y(tMe)%data%begin .LE. jsg .AND. jsg .LE. domain%y(tMe)%data%end+jshift )then !fold
3533 !--- calculating overlapping for receving on north
3534 if( domain%x(tMe)%pos .GE. size(domain%x(tMe)%list(:))/2 )then
3535 jsd = domain%y(tMe)%compute%begin; jed = jsd
3536 if( jsd == jsg )then ! fold is within domain.
3537 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
3538 is=isc; ie=iec; js = jsc; je = jec
3539 select case (position)
3541 isd = max(isd, middle)
3542 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3544 isd = max(isd, middle)
3545 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3547 call insert_update_overlap(overlap, domain%list(m)%pe, &
3548 is, ie, js, je, isd, ied, jsd, jed, dir, .TRUE.)
3549 is = max(is, isd); ie = min(ie, ied)
3550 js = max(js, jsd); je = min(je, jed)
3551 if(debug_update_level .NE. NO_CHECK .AND. ie.GE.is .AND. je.GE.js )then
3552 nrecv_check = nrecv_check+1
3553 call allocate_check_overlap(checkList(nrecv_check), 1)
3554 call insert_check_overlap(checkList(nrecv_check), domain%list(m)%pe, &
3555 tMe, 2, ONE_HUNDRED_EIGHTY, is, ie, js, je)
3562 !--- copy the overlapping information
3563 if( overlap%count > 0) then
3565 if(nrecv > size(overlapList(:)) )then
3566 call mpp_error(NOTE, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for recv is expanded')
3567 call expand_update_overlap_list(overlapList, nlist)
3569 call add_update_overlap( overlapList(nrecv), overlap)
3570 call init_overlap_type(overlap)
3572 enddo ! end of recv do loop
3574 if(debug_message_passing) then
3575 !--- write out send information
3576 unit = mpp_pe() + 1000
3578 write(unit, *) "********from_pe = " ,overlapList(m)%pe, " count = ",overlapList(m)%count
3579 do n = 1, overlapList(m)%count
3580 write(unit, *) overlapList(m)%is(n), overlapList(m)%ie(n), overlapList(m)%js(n), overlapList(m)%je(n), &
3581 overlapList(m)%dir(n), overlapList(m)%rotation(n)
3584 if(nrecv >0) flush(unit)
3587 ! copy the overlapping information into domain
3589 update%nrecv = nrecv
3590 allocate(update%recv(nrecv))
3592 call add_update_overlap( update%recv(m), overlapList(m) )
3593 do n = 1, update%recv(m)%count
3594 if(update%recv(m)%tileNbr(n) == domain%tile_id(tMe)) then
3595 if(update%recv(m)%dir(n) == 1) domain%x(tMe)%loffset = 0
3596 if(update%recv(m)%dir(n) == 7) domain%y(tMe)%loffset = 0
3602 if(nrecv_check>0) then
3603 check%nrecv = nrecv_check
3604 allocate(check%recv(nrecv_check))
3605 do m = 1, nrecv_check
3606 call add_check_overlap( check%recv(m), checkList(m) )
3610 call deallocate_overlap_type(overlap)
3612 do m = 1,size(overlapList(:))
3613 call deallocate_overlap_type(overlapList(m))
3616 if(debug_update_level .NE. NO_CHECK) then
3617 do m = 1,size(checkList(:))
3618 call deallocate_overlap_type(checkList(m))
3622 deallocate(overlapList)
3623 deallocate(checkList)
3626 domain%initialized = .true.
3628 end subroutine compute_overlaps_fold_south
3630 !####################################################################################
3631 subroutine compute_overlaps_fold_west( domain, position, ishift, jshift)
3632 !computes remote domain overlaps
3633 !assumes only one in each direction
3634 !will calculate the overlapping for T,E,C,N-cell seperately.
3635 type(domain2D), intent(inout) :: domain
3636 integer, intent(in) :: position, ishift, jshift
3638 integer :: j, m, n, nlist, tMe, tNbr, dir
3639 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3640 integer :: isg, ieg, jsg, jeg, ioff, joff
3641 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3642 integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3644 type(overlap_type) :: overlap
3645 type(overlapSpec), pointer :: update=>NULL()
3646 type(overlap_type) :: overlapList(MAXLIST)
3647 type(overlap_type) :: checkList(MAXLIST)
3648 type(overlapSpec), pointer :: check =>NULL()
3649 integer :: nsend, nrecv
3650 integer :: nsend_check, nrecv_check
3653 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3654 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3655 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3656 if(size(domain%x(:)) > 1) return
3658 !--- if there is no halo, no need to compute overlaps.
3659 if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3661 !--- when there is only one tile, n will equal to np
3662 nlist = size(domain%list(:))
3664 select case(position)
3666 update => domain%update_T
3669 update => domain%update_C
3670 check => domain%check_C
3672 update => domain%update_E
3673 check => domain%check_E
3675 update => domain%update_N
3676 check => domain%check_N
3678 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_west):"//&
3679 & " the value of position should be CENTER, EAST, CORNER or NORTH")
3682 !--- overlap is used to store the overlapping temporarily.
3683 call allocate_update_overlap( overlap, MAXOVERLAP)
3686 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3687 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3688 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3689 update%xbegin = ism; update%xend = iem
3690 update%ybegin = jsm; update%yend = jem
3691 if(ASSOCIATED(check)) then
3692 check%xbegin = ism; check%xend = iem
3693 check%ybegin = jsm; check%yend = jem
3695 update%whalo = domain%whalo; update%ehalo = domain%ehalo
3696 update%shalo = domain%shalo; update%nhalo = domain%nhalo
3697 whalo = domain%whalo; ehalo = domain%ehalo
3698 shalo = domain%shalo; nhalo = domain%nhalo
3702 middle = (jsg+jeg)/2+1
3705 if(.NOT. BTEST(domain%fold,WEST)) then
3706 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3707 "boundary condition in y-direction should be folded-west for "//trim(domain%name))
3709 if(.NOT. domain%y(tMe)%cyclic) then
3710 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3711 "boundary condition in y-direction should be cyclic for "//trim(domain%name))
3714 if(.not. domain%symmetry) then
3715 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3716 "when west boundary is folded, the domain must be symmetry for "//trim(domain%name))
3722 m = mod( domain%pos+list, nlist )
3723 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
3724 !to_pe's eastern halo
3726 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3727 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
3728 call insert_update_overlap( overlap, domain%list(m)%pe, &
3729 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3733 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3734 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3735 if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
3736 js = js+joff; je = je+joff
3739 call insert_update_overlap( overlap, domain%list(m)%pe, &
3740 is, ie, js, je, isc, iec, jsc, jec, dir)
3742 !to_pe's southern halo
3744 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
3745 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3746 !--- to make sure the consistence between pes
3747 if( (position == EAST .OR. position == CORNER ) .AND. ( isc == ie .or. iec == is ) ) then
3748 !--- do nothing, this point will come from other pe
3750 if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
3751 js = js+joff; je = je+joff
3754 !--- when the west face is folded, the south halo points at
3755 !--- the position should be on CORNER or EAST
3756 if( is == isg .AND. (position == CORNER .OR. position == EAST) &
3757 .AND. ( domain%list(m)%y(tNbr)%compute%begin == jsg .OR. &
3758 & domain%list(m)%y(tNbr)%compute%begin-1 .GE. middle)) then
3759 call insert_update_overlap( overlap, domain%list(m)%pe, &
3760 is+1, ie, js, je, isc, iec, jsc, jec, dir)
3761 is = domain%list(m)%x(tNbr)%compute%begin; ie = is
3762 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3763 if ( domain%list(m)%y(tNbr)%compute%begin == jsg ) then
3764 select case (position)
3766 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
3768 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
3770 if(je .GT. domain%y(tMe)%compute%end+jshift) call mpp_error( FATAL, &
3771 'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error send.' )
3773 select case (position)
3775 j=js; js = jsg+jeg-je; je = jsg+jeg-j
3777 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3780 call insert_update_overlap( overlap, domain%list(m)%pe, &
3781 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3783 call insert_update_overlap( overlap, domain%list(m)%pe, &
3784 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3791 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3792 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
3793 if( jsg.GT.js .AND. je.LT.jsc )then !cyclic offset
3794 js = js+joff; je = je+joff
3798 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3800 call insert_update_overlap( overlap, domain%list(m)%pe, &
3801 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3802 !--- when south edge is folded, js will be less than jsg when position is EAST and CORNER
3803 if(js .LT. jsg) then
3805 call insert_update_overlap( overlap, domain%list(m)%pe, &
3806 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3809 !to_pe's western halo
3812 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3813 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
3816 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3818 !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3819 !--- no need to send, because the data on that point will come from other pe.
3820 !--- come from two pe ( there will be only one point on one pe. ).
3821 if( (position == EAST .OR. position == CORNER ) .AND. ( jsc == je .or. jec == js ) ) then
3822 !--- do nothing, this point will come from other pe
3824 call insert_update_overlap( overlap, domain%list(m)%pe, &
3825 is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3827 !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3828 if(js .LT. jsg) then
3830 call insert_update_overlap( overlap, domain%list(m)%pe, &
3831 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3837 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
3838 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3839 if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
3840 js = js-joff; je = je-joff
3844 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3847 call insert_update_overlap( overlap, domain%list(m)%pe, &
3848 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3850 !to_pe's northern halo
3852 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
3853 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3854 !--- to make sure the consistence between pes
3855 if( (position == EAST .OR. position == CORNER ) .AND. ( isc == ie .or. iec == is ) ) then
3856 !--- do nothing, this point will come from other pe
3858 if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
3859 js = js-joff; je = je-joff
3861 !--- when the west face is folded, the south halo points at
3862 !--- the position should be on CORNER or EAST
3863 if( is == isg .AND. (position == CORNER .OR. position == EAST) &
3864 .AND. ( js .GE. middle .AND. domain%list(m)%y(tNbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
3865 call insert_update_overlap( overlap, domain%list(m)%pe, &
3866 is+1, ie, js, je, isc, iec, jsc, jec, dir)
3867 is = domain%list(m)%x(tNbr)%compute%begin; ie = is
3868 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3869 select case (position)
3871 j=js; js = jsg+jeg-je; je = jsg+jeg-j
3873 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3875 call insert_update_overlap( overlap, domain%list(m)%pe, &
3876 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3878 call insert_update_overlap( overlap, domain%list(m)%pe, &
3879 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3885 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
3886 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
3887 if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
3888 js = js-joff; je = je-joff
3890 call insert_update_overlap( overlap, domain%list(m)%pe, &
3891 is, ie, js, je, isc, iec, jsc, jec, dir)
3893 !--- Now calculate the overlapping for fold-edge.
3894 !--- only position at EAST and CORNER need to be considered
3895 if( ( position == EAST .OR. position == CORNER) ) then
3896 if( domain%x(tMe)%compute%begin-whalo .LE. isg .AND. isg .LE. domain%x(tMe)%data%end+ishift )then !fold
3899 !--- calculate the overlapping for sending
3900 if( domain%y(tMe)%pos .LT. (size(domain%y(tMe)%list(:))+1)/2 )then
3901 is = domain%list(m)%x(tNbr)%compute%begin; ie = is
3902 if( is == isg )then ! fold is within domain.
3903 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
3904 select case (position)
3906 js = max(js, middle)
3907 j=js; js = jsg+jeg-je; je = jsg+jeg-j
3909 js = max(js, middle)
3910 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3912 call insert_update_overlap(overlap, domain%list(m)%pe, &
3913 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3914 is = max(is, isc); ie = min(ie, iec)
3915 js = max(js, jsc); je = min(je, jec)
3916 if(debug_update_level .NE. NO_CHECK .AND. ie.GE.is .AND. je.GE.js )then
3917 nsend_check = nsend_check+1
3918 call allocate_check_overlap(checkList(nsend_check), 1)
3919 call insert_check_overlap(checkList(nsend_check), domain%list(m)%pe, &
3920 tMe, 3, ONE_HUNDRED_EIGHTY, is, ie, js, je)
3927 !--- copy the overlapping information
3928 if( overlap%count > 0) then
3930 if(nsend > MAXLIST) call mpp_error(FATAL, &
3931 "mpp_domains_define.inc(compute_overlaps_west): nsend is greater than MAXLIST, increase MAXLIST")
3932 call add_update_overlap(overlapList(nsend), overlap)
3933 call init_overlap_type(overlap)
3935 end do ! end of send set up.
3937 if(debug_message_passing) then
3938 !--- write out send information
3939 unit = mpp_pe() + 1000
3941 write(unit, *) "********to_pe = " ,overlapList(m)%pe, " count = ",overlapList(m)%count
3942 do n = 1, overlapList(m)%count
3943 write(unit, *) overlapList(m)%is(n), overlapList(m)%ie(n), overlapList(m)%js(n), overlapList(m)%je(n), &
3944 overlapList(m)%dir(n), overlapList(m)%rotation(n)
3947 if(nsend >0) flush(unit)
3950 ! copy the overlapping information into domain data structure
3952 update%nsend = nsend
3953 allocate(update%send(nsend))
3955 call add_update_overlap( update%send(m), overlapList(m) )
3959 if(nsend_check>0) then
3960 check%nsend = nsend_check
3961 allocate(check%send(nsend_check))
3962 do m = 1, nsend_check
3963 call add_check_overlap( check%send(m), checkList(m) )
3968 call deallocate_overlap_type(overlapList(m))
3969 if(debug_update_level .NE. NO_CHECK) call deallocate_overlap_type(checkList(m))
3972 isgd = isg - domain%whalo
3973 iegd = ieg + domain%ehalo
3974 jsgd = jsg - domain%shalo
3975 jegd = jeg + domain%nhalo
3977 ! begin setting up recv
3981 m = mod( domain%pos+nlist-list, nlist )
3982 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
3983 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
3984 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
3987 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
3988 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
3989 is=isc; ie=iec; js=jsc; je=jec
3990 call insert_update_overlap( overlap, domain%list(m)%pe, &
3991 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3995 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
3996 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
3997 is=isc; ie=iec; js=jsc; je=jec
3998 if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
3999 js = js-joff; je = je-joff
4001 call insert_update_overlap(overlap, domain%list(m)%pe, &
4002 is, ie, js, je, isd, ied, jsd, jed, dir)
4007 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
4008 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
4009 is=isc; ie=iec; js=jsc; je=jec
4011 if( (position == EAST .OR. position == CORNER ) .AND. ( isd == ie .or. ied == is ) ) then
4012 !--- do nothing, this point will come from other pe
4014 if( jsd.LT.jsg .AND. js .GT. jed)then
4015 js = js-joff; je = je-joff
4017 !--- when the west face is folded, the south halo points at
4018 !--- the position should be on CORNER or EAST
4019 if( isd == isg .AND. (position == CORNER .OR. position == EAST) &
4020 .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4021 call insert_update_overlap( overlap, domain%list(m)%pe, &
4022 is, ie, js, je, isd+1, ied, jsd, jed, dir)
4023 is=isc; ie=iec; js=jsc; je=jec
4025 select case (position)
4027 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4029 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4031 if(je .GT. domain%y(tMe)%compute%end+jshift) call mpp_error( FATAL, &
4032 'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4034 select case (position)
4036 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4038 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4041 call insert_update_overlap( overlap, domain%list(m)%pe, &
4042 is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4044 call insert_update_overlap( overlap, domain%list(m)%pe, &
4045 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4052 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
4053 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
4054 is=isc; ie=iec; js=jsc; je=jec
4055 if( isd.LT.isg )then
4057 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4059 if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4060 js = js-joff; je = je-joff
4062 call insert_update_overlap(overlap, domain%list(m)%pe, &
4063 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4064 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4065 if(js .LT. jsg ) then
4067 call insert_update_overlap(overlap, domain%list(m)%pe, &
4068 is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4074 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
4075 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
4076 is=isc; ie=iec; js=jsc; je=jec
4077 if( isd.LT.isg )then
4079 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4081 if( (position == EAST .OR. position == CORNER ) .AND. (jsd == je .or. jed == js ) ) then
4082 !--- do nothing, this point will come from other pe
4084 call insert_update_overlap(overlap, domain%list(m)%pe, &
4085 is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4087 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4088 if(js .LT. jsg ) then
4090 call insert_update_overlap(overlap, domain%list(m)%pe, &
4091 is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4097 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
4098 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
4099 is=isc; ie=iec; js=jsc; je=jec
4100 if( isd.LT.isg) then
4102 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4104 if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4105 js = js+joff; je = je+joff
4108 call insert_update_overlap( overlap, domain%list(m)%pe, &
4109 is, ie, js, je, isd, ied, jsd, jed, dir)
4114 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
4115 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
4116 is=isc; ie=iec; js=jsc; je=jec
4117 if( (position == EAST .OR. position == CORNER ) .AND. ( isd == ie .or. ied == is ) ) then
4118 !--- do nothing, this point will come from other pe
4120 if( jed.GT.jeg .AND. je.LT.jsd)then
4121 js = js+joff; je = je+joff
4123 !--- when the west face is folded, the south halo points at
4124 !--- the position should be on CORNER or EAST
4125 if( isd == isg .AND. (position == CORNER .OR. position == EAST) &
4126 .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4127 call insert_update_overlap( overlap, domain%list(m)%pe, &
4128 is, ie, js, je, isd+1, ied, jsd, jed, dir)
4129 is=isc; ie=iec; js=jsc; je=jec
4130 select case (position)
4132 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4134 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4136 call insert_update_overlap( overlap, domain%list(m)%pe, &
4137 is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4139 call insert_update_overlap( overlap, domain%list(m)%pe, &
4140 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4146 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
4147 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
4148 is=isc; ie=iec; js=jsc; je=jec
4149 if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4150 js = js+joff; je = je+joff
4152 call insert_update_overlap( overlap, domain%list(m)%pe, &
4153 is, ie, js, je, isd, ied, jsd, jed, dir)
4155 !--- Now calculate the overlapping for fold-edge.
4156 !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4157 !--- only position at EAST and CORNER need to be considered
4158 if( ( position == EAST .OR. position == CORNER) ) then
4159 if( domain%x(tMe)%data%begin .LE. isg .AND. isg .LE. domain%x(tMe)%data%end+ishift )then !fold
4162 !--- calculating overlapping for receving on north
4163 if( domain%y(tMe)%pos .GE. size(domain%y(tMe)%list(:))/2 )then
4164 isd = domain%x(tMe)%compute%begin; ied = isd
4165 if( isd == isg )then ! fold is within domain.
4166 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
4167 is=isc; ie=iec; js = jsc; je = jec
4168 select case (position)
4170 jsd = max(jsd, middle)
4171 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4173 jsd = max(jsd, middle)
4174 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4176 call insert_update_overlap(overlap, domain%list(m)%pe, &
4177 is, ie, js, je, isd, ied, jsd, jed, dir, .TRUE.)
4178 is = max(is, isd); ie = min(ie, ied)
4179 js = max(js, jsd); je = min(je, jed)
4180 if(debug_update_level .NE. NO_CHECK .AND. ie.GE.is .AND. je.GE.js )then
4181 nrecv_check = nrecv_check+1
4182 call allocate_check_overlap(checkList(nrecv_check), 1)
4183 call insert_check_overlap(checkList(nrecv_check), domain%list(m)%pe, &
4184 tMe, 3, ONE_HUNDRED_EIGHTY, is, ie, js, je)
4191 !--- copy the overlapping information
4192 if( overlap%count > 0) then
4194 if(nrecv > MAXLIST) call mpp_error(FATAL, &
4195 "mpp_domains_define.inc(compute_overlaps_west): nrecv is greater than MAXLIST, increase MAXLIST")
4196 call add_update_overlap( overlapList(nrecv), overlap)
4197 call init_overlap_type(overlap)
4199 enddo ! end of recv do loop
4201 if(debug_message_passing) then
4202 !--- write out send information
4203 unit = mpp_pe() + 1000
4205 write(unit, *) "********from_pe = " ,overlapList(m)%pe, " count = ",overlapList(m)%count
4206 do n = 1, overlapList(m)%count
4207 write(unit, *) overlapList(m)%is(n), overlapList(m)%ie(n), overlapList(m)%js(n), overlapList(m)%je(n), &
4208 overlapList(m)%dir(n), overlapList(m)%rotation(n)
4211 if(nrecv >0) flush(unit)
4214 ! copy the overlapping information into domain
4216 update%nrecv = nrecv
4217 allocate(update%recv(nrecv))
4219 call add_update_overlap( update%recv(m), overlapList(m) )
4220 do n = 1, update%recv(m)%count
4221 if(update%recv(m)%tileNbr(n) == domain%tile_id(tMe)) then
4222 if(update%recv(m)%dir(n) == 1) domain%x(tMe)%loffset = 0
4223 if(update%recv(m)%dir(n) == 7) domain%y(tMe)%loffset = 0
4229 if(nrecv_check>0) then
4230 check%nrecv = nrecv_check
4231 allocate(check%recv(nrecv_check))
4232 do m = 1, nrecv_check
4233 call add_check_overlap( check%recv(m), checkList(m) )
4237 call deallocate_overlap_type(overlap)
4239 call deallocate_overlap_type(overlapList(m))
4240 if(debug_update_level .NE. NO_CHECK) call deallocate_overlap_type(checkList(m))
4245 domain%initialized = .true.
4247 end subroutine compute_overlaps_fold_west
4249 !###############################################################################
4250 subroutine compute_overlaps_fold_east( domain, position, ishift, jshift )
4251 !computes remote domain overlaps
4252 !assumes only one in each direction
4253 !will calculate the overlapping for T,E,C,N-cell seperately.
4254 !here assume fold-east and y-cyclic boundary condition
4255 type(domain2D), intent(inout) :: domain
4256 integer, intent(in) :: position, ishift, jshift
4258 integer :: j, m, n, nlist, tMe, tNbr, dir
4259 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd
4260 integer :: jed, isg, ieg, jsg, jeg, ioff, joff
4261 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
4262 integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
4264 type(overlap_type) :: overlap
4265 type(overlapSpec), pointer :: update=>NULL()
4266 type(overlap_type) :: overlapList(MAXLIST)
4267 type(overlap_type) :: checkList(MAXLIST)
4268 type(overlapSpec), pointer :: check =>NULL()
4269 integer :: nsend, nrecv
4270 integer :: nsend_check, nrecv_check
4272 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
4273 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
4274 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
4275 if(size(domain%x(:)) > 1) return
4277 !--- if there is no halo, no need to compute overlaps.
4278 if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
4280 !--- when there is only one tile, n will equal to np
4281 nlist = size(domain%list(:))
4283 select case(position)
4285 update => domain%update_T
4287 update => domain%update_C
4288 check => domain%check_C
4290 update => domain%update_E
4291 check => domain%check_E
4293 update => domain%update_N
4294 check => domain%check_N
4296 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_east):"// &
4297 & " the value of position should be CENTER, EAST, CORNER or NORTH")
4300 !--- overlap is used to store the overlapping temporarily.
4301 call allocate_update_overlap( overlap, MAXOVERLAP)
4304 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
4305 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
4306 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
4307 update%xbegin = ism; update%xend = iem
4308 update%ybegin = jsm; update%yend = jem
4309 if(ASSOCIATED(check)) then
4310 check%xbegin = ism; check%xend = iem
4311 check%ybegin = jsm; check%yend = jem
4313 update%whalo = domain%whalo; update%ehalo = domain%ehalo
4314 update%shalo = domain%shalo; update%nhalo = domain%nhalo
4315 whalo = domain%whalo; ehalo = domain%ehalo
4316 shalo = domain%shalo; nhalo = domain%nhalo
4320 middle = (jsg+jeg)/2+1
4323 if(.NOT. BTEST(domain%fold,EAST)) then
4324 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4325 "boundary condition in y-direction should be folded-east for "//trim(domain%name))
4327 if(.NOT. domain%y(tMe)%cyclic) then
4328 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4329 "boundary condition in y-direction should be cyclic for "//trim(domain%name))
4331 if(.not. domain%symmetry) then
4332 call mpp_error(FATAL, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4333 "when east boundary is folded, the domain must be symmetry for "//trim(domain%name))
4339 m = mod( domain%pos+list, nlist )
4340 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
4341 !to_pe's eastern halo
4344 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
4345 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
4348 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4350 !--- when domain symmetry and position is EAST or CORNER, the point when jsc == je,
4351 !--- no need to send, because the data on that point will come from other pe.
4352 !--- come from two pe ( there will be only one point on one pe. ).
4353 if( (position == EAST .OR. position == CORNER ) .AND. ( jsc == je .or. jec == js ) ) then
4354 !--- do nothing, this point will come from other pe
4356 call insert_update_overlap( overlap, domain%list(m)%pe, &
4357 is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
4359 !--- when east edge is folded, js .LT. jsg
4360 if(js .LT. jsg) then
4362 call insert_update_overlap( overlap, domain%list(m)%pe, &
4363 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4369 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
4370 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
4371 if( jsg.GT.js .AND. je.LT.jsc )then !try cyclic offset
4372 js = js+joff; je = je+joff
4377 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4380 call insert_update_overlap( overlap, domain%list(m)%pe, &
4381 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4382 !--- when east edge is folded,
4383 if(js .LT. jsg) then
4385 call insert_update_overlap( overlap, domain%list(m)%pe, &
4386 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4389 !to_pe's southern halo
4391 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
4392 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
4393 !--- to make sure the consistence between pes
4394 if( (position == EAST .OR. position == CORNER ) .AND. ( isc == ie .or. iec == is ) ) then
4395 !--- do nothing, this point will come from other pe
4397 if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
4398 js = js+joff; je = je+joff
4400 !--- when the east face is folded, the south halo points at
4401 !--- the position should be on CORNER or EAST
4402 if( ie == ieg .AND. (position == CORNER .OR. position == EAST) &
4403 .AND. ( domain%list(m)%y(tNbr)%compute%begin == jsg .OR. &
4404 domain%list(m)%y(tNbr)%compute%begin-1 .GE. middle ) ) then
4405 call insert_update_overlap( overlap, domain%list(m)%pe, &
4406 is, ie-1, js, je, isc, iec, jsc, jec, dir)
4407 !--- consider at i = ieg for east edge.
4408 !--- when the data is at corner and not symmetry, j = jsg -1 will get from cyclic condition
4409 if(position == CORNER .AND. .NOT. domain%symmetry .AND. domain%list(m)%y(tNbr)%compute%begin==jsg)then
4410 call insert_update_overlap(overlap, domain%list(m)%pe, &
4411 ie, ie, je, je, isc, iec, jsc, jec, dir, .true.)
4414 ie = domain%list(m)%x(tNbr)%compute%end+ishift; is = ie
4415 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
4416 if ( domain%list(m)%y(tNbr)%compute%begin == jsg ) then
4417 select case (position)
4419 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4421 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4423 if(je .GT. domain%y(tMe)%compute%end+jshift) call mpp_error( FATAL, &
4424 'mpp_domains_define.inc(compute_overlaps_fold_east: south edge ubound error send.' )
4426 select case (position)
4428 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4430 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4433 call insert_update_overlap( overlap, domain%list(m)%pe, &
4434 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4436 call insert_update_overlap( overlap, domain%list(m)%pe, &
4437 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4443 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
4444 js = domain%list(m)%y(tNbr)%compute%begin-shalo; je = domain%list(m)%y(tNbr)%compute%begin-1
4445 if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
4446 js = js+joff; je = je+joff
4448 call insert_update_overlap( overlap, domain%list(m)%pe, &
4449 is, ie, js, je, isc, iec, jsc, jec, dir)
4451 !to_pe's western halo
4453 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
4454 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
4455 call insert_update_overlap( overlap, domain%list(m)%pe, &
4456 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4460 is = domain%list(m)%x(tNbr)%compute%begin-whalo; ie = domain%list(m)%x(tNbr)%compute%begin-1
4461 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
4462 if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
4463 js = js-joff; je = je-joff
4465 call insert_update_overlap( overlap, domain%list(m)%pe, &
4466 is, ie, js, je, isc, iec, jsc, jec, dir)
4468 !to_pe's northern halo
4471 is = domain%list(m)%x(tNbr)%compute%begin; ie = domain%list(m)%x(tNbr)%compute%end+ishift
4472 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
4473 !--- to make sure the consistence between pes
4474 if( (position == EAST .OR. position == CORNER ) .AND. ( isc == ie .or. iec == is ) ) then
4475 !--- do nothing, this point will come from other pe
4477 if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
4478 js = js-joff; je = je-joff
4480 !--- when the east face is folded, the north halo points at
4481 !--- the position should be on CORNER or EAST
4482 if( ie == ieg .AND. (position == CORNER .OR. position == EAST) &
4483 .AND. ( js .GE. middle .AND. domain%list(m)%y(tNbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
4484 call insert_update_overlap( overlap, domain%list(m)%pe, &
4485 is, ie-1, js, je, isc, iec, jsc, jec, dir)
4486 ie = domain%list(m)%x(tNbr)%compute%end+ishift; is = ie
4487 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
4488 select case (position)
4490 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4492 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4494 call insert_update_overlap( overlap, domain%list(m)%pe, &
4495 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4497 call insert_update_overlap( overlap, domain%list(m)%pe, &
4498 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4505 is = domain%list(m)%x(tNbr)%compute%end+1+ishift; ie = domain%list(m)%x(tNbr)%compute%end+ehalo+ishift
4506 js = domain%list(m)%y(tNbr)%compute%end+1+jshift; je = domain%list(m)%y(tNbr)%compute%end+nhalo+jshift
4507 if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
4508 js = js-joff; je = je-joff
4512 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4515 call insert_update_overlap( overlap, domain%list(m)%pe, &
4516 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4518 !--- Now calculate the overlapping for fold-edge.
4519 !--- only position at EAST and CORNER need to be considered
4520 if( ( position == EAST .OR. position == CORNER) ) then
4521 if( domain%x(tMe)%data%begin .LE. ieg .AND. ieg .LE. domain%x(tMe)%data%end+ishift )then !fold
4524 !--- calculate the overlapping for sending
4525 if( domain%y(tMe)%pos .LT. (size(domain%y(tMe)%list(:))+1)/2 )then
4526 ie = domain%list(m)%x(tNbr)%compute%end+ishift; is = ie
4527 if( ie == ieg )then ! fold is within domain.
4528 js = domain%list(m)%y(tNbr)%compute%begin; je = domain%list(m)%y(tNbr)%compute%end+jshift
4529 select case (position)
4531 js = max(js, middle)
4532 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4534 js = max(js, middle)
4535 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4537 call insert_update_overlap(overlap, domain%list(m)%pe, &
4538 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4539 is = max(is, isc); ie = min(ie, iec)
4540 js = max(js, jsc); je = min(je, jec)
4541 if(debug_update_level .NE. NO_CHECK .AND. ie.GE.is .AND. je.GE.js )then
4542 nsend_check = nsend_check+1
4543 call allocate_check_overlap(checkList(nsend_check), 1)
4544 call insert_check_overlap(checkList(nsend_check), domain%list(m)%pe, &
4545 tMe, 1, ONE_HUNDRED_EIGHTY, is, ie, js, je)
4552 !--- copy the overlapping information
4553 if( overlap%count > 0) then
4555 if(nsend > MAXLIST) call mpp_error(FATAL, &
4556 "mpp_domains_define.inc(compute_overlaps_east): nsend is greater than MAXLIST, increase MAXLIST")
4557 call add_update_overlap(overlapList(nsend), overlap)
4558 call init_overlap_type(overlap)
4560 end do ! end of send set up.
4562 ! copy the overlapping information into domain data structure
4564 update%nsend = nsend
4565 allocate(update%send(nsend))
4567 call add_update_overlap( update%send(m), overlapList(m) )
4571 if(nsend_check>0) then
4572 check%nsend = nsend_check
4573 allocate(check%send(nsend_check))
4574 do m = 1, nsend_check
4575 call add_check_overlap( check%send(m), checkList(m) )
4580 call deallocate_overlap_type(overlapList(m))
4581 if(debug_update_level .NE. NO_CHECK) call deallocate_overlap_type(checkList(m))
4584 isgd = isg - domain%whalo
4585 iegd = ieg + domain%ehalo
4586 jsgd = jsg - domain%shalo
4587 jegd = jeg + domain%nhalo
4589 ! begin setting up recv
4593 m = mod( domain%pos+nlist-list, nlist )
4594 if(domain%list(m)%tile_id(tNbr) == domain%tile_id(tMe) ) then ! only compute the overlapping within tile.
4595 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4596 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4600 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
4601 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
4602 is=isc; ie=iec; js=jsc; je=jec
4603 if( ied.GT.ieg )then
4605 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4607 if( (position == EAST .OR. position == CORNER ) .AND. (jsd == je .or. jed == js ) ) then
4608 !--- do nothing, this point will come from other pe
4610 call insert_update_overlap(overlap, domain%list(m)%pe, &
4611 is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4613 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4614 if(js .LT. jsg ) then
4616 call insert_update_overlap(overlap, domain%list(m)%pe, &
4617 is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4623 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
4624 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
4625 is=isc; ie=iec; js=jsc; je=jec
4626 if( ied.GT.ieg )then
4628 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4630 if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4631 js = js-joff; je = je-joff
4633 call insert_update_overlap(overlap, domain%list(m)%pe, &
4634 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4635 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4636 if(js .LT. jsg ) then
4638 call insert_update_overlap(overlap, domain%list(m)%pe, &
4639 is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4645 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
4646 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
4647 is=isc; ie=iec; js=jsc; je=jec
4649 if( (position == EAST .OR. position == CORNER ) .AND. ( isd == ie .or. ied == is ) ) then
4650 !--- do nothing, this point will come from other pe
4652 if( jsd.LT.jsg .AND. js .GT. jed)then
4653 js = js-joff; je = je-joff
4655 !--- when the east face is folded, the south halo points at
4656 !--- the position should be on CORNER or EAST
4657 if( ied == ieg .AND. (position == CORNER .OR. position == EAST) &
4658 .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4659 call insert_update_overlap( overlap, domain%list(m)%pe, &
4660 is, ie, js, je, isd, ied-1, jsd, jed, dir)
4661 is=isc; ie=iec; js=jsc; je=jec
4663 select case (position)
4665 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4667 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4669 if(je .GT. domain%y(tMe)%compute%end+jshift) call mpp_error( FATAL, &
4670 'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4672 select case (position)
4674 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4676 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4679 call insert_update_overlap( overlap, domain%list(m)%pe, &
4680 is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4682 call insert_update_overlap( overlap, domain%list(m)%pe, &
4683 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4689 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
4690 jsd = domain%y(tMe)%data%begin; jed = domain%y(tMe)%compute%begin-1
4691 is=isc; ie=iec; js=jsc; je=jec
4692 if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4693 js = js-joff; je = je-joff
4695 call insert_update_overlap(overlap, domain%list(m)%pe, &
4696 is, ie, js, je, isd, ied, jsd, jed, dir)
4700 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
4701 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
4702 is=isc; ie=iec; js=jsc; je=jec
4703 call insert_update_overlap( overlap, domain%list(m)%pe, &
4704 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4709 isd = domain%x(tMe)%data%begin; ied = domain%x(tMe)%compute%begin-1
4710 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
4711 is=isc; ie=iec; js=jsc; je=jec
4712 if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4713 js = js+joff; je = je+joff
4715 call insert_update_overlap( overlap, domain%list(m)%pe, &
4716 is, ie, js, je, isd, ied, jsd, jed, dir)
4721 isd = domain%x(tMe)%compute%begin; ied = domain%x(tMe)%compute%end+ishift
4722 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
4723 is=isc; ie=iec; js=jsc; je=jec
4724 if( (position == EAST .OR. position == CORNER ) .AND. ( isd == ie .or. ied == is ) ) then
4725 !--- do nothing, this point will come from other pe
4727 if( jed.GT.jeg .AND. je.LT.jsd)then
4728 js = js+joff; je = je+joff
4730 !--- when the east face is folded, the south halo points at
4731 !--- the position should be on CORNER or EAST
4732 if( ied == ieg .AND. (position == CORNER .OR. position == EAST) &
4733 .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4734 call insert_update_overlap( overlap, domain%list(m)%pe, &
4735 is, ie, js, je, isd, ied-1, jsd, jed, dir)
4736 is=isc; ie=iec; js=jsc; je=jec
4737 select case (position)
4739 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4741 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4743 call insert_update_overlap( overlap, domain%list(m)%pe, &
4744 is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4746 call insert_update_overlap( overlap, domain%list(m)%pe, &
4747 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4754 isd = domain%x(tMe)%compute%end+1+ishift; ied = domain%x(tMe)%data%end+ishift
4755 jsd = domain%y(tMe)%compute%end+1+jshift; jed = domain%y(tMe)%data%end+jshift
4756 is=isc; ie=iec; js=jsc; je=jec
4757 if( ied.GT.ieg) then
4759 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4761 if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4762 js = js+joff; je = je+joff
4765 call insert_update_overlap( overlap, domain%list(m)%pe, &
4766 is, ie, js, je, isd, ied, jsd, jed, dir)
4767 !--- Now calculate the overlapping for fold-edge.
4768 !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4769 !--- only position at EAST and CORNER need to be considered
4770 if( ( position == EAST .OR. position == CORNER) ) then
4771 if( domain%x(tMe)%data%begin .LE. ieg .AND. ieg .LE. domain%x(tMe)%data%end+ishift )then !fold
4774 !--- calculating overlapping for receving on north
4775 if( domain%y(tMe)%pos .GE. size(domain%y(tMe)%list(:))/2 )then
4776 ied = domain%x(tMe)%compute%end+ishift; isd = ied
4777 if( ied == ieg )then ! fold is within domain.
4778 jsd = domain%y(tMe)%compute%begin; jed = domain%y(tMe)%compute%end+jshift
4779 is=isc; ie=iec; js = jsc; je = jec
4780 select case (position)
4782 jsd = max(jsd, middle)
4783 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4785 jsd = max(jsd, middle)
4786 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4788 call insert_update_overlap(overlap, domain%list(m)%pe, &
4789 is, ie, js, je, isd, ied, jsd, jed, dir, .TRUE.)
4790 is = max(is, isd); ie = min(ie, ied)
4791 js = max(js, jsd); je = min(je, jed)
4792 if(debug_update_level .NE. NO_CHECK .AND. ie.GE.is .AND. je.GE.js )then
4793 nrecv_check = nrecv_check+1
4794 call allocate_check_overlap(checkList(nrecv_check), 1)
4795 call insert_check_overlap(checkList(nrecv_check), domain%list(m)%pe, &
4796 tMe, 3, ONE_HUNDRED_EIGHTY, is, ie, js, je)
4803 !--- copy the overlapping information
4804 if( overlap%count > 0) then
4806 if(nrecv > MAXLIST) call mpp_error(FATAL, &
4807 "mpp_domains_define.inc(compute_overlaps_east): nrecv is greater than MAXLIST, increase MAXLIST")
4808 call add_update_overlap( overlapList(nrecv), overlap)
4809 call init_overlap_type(overlap)
4811 enddo ! end of recv do loop
4813 ! copy the overlapping information into domain
4815 update%nrecv = nrecv
4816 allocate(update%recv(nrecv))
4818 call add_update_overlap( update%recv(m), overlapList(m) )
4819 do n = 1, update%recv(m)%count
4820 if(update%recv(m)%tileNbr(n) == domain%tile_id(tMe)) then
4821 if(update%recv(m)%dir(n) == 1) domain%x(tMe)%loffset = 0
4822 if(update%recv(m)%dir(n) == 7) domain%y(tMe)%loffset = 0
4828 if(nrecv_check>0) then
4829 check%nrecv = nrecv_check
4830 allocate(check%recv(nrecv_check))
4831 do m = 1, nrecv_check
4832 call add_check_overlap( check%recv(m), checkList(m) )
4836 call deallocate_overlap_type(overlap)
4838 call deallocate_overlap_type(overlapList(m))
4839 if(debug_update_level .NE. NO_CHECK) call deallocate_overlap_type(checkList(m))
4845 domain%initialized = .true.
4847 end subroutine compute_overlaps_fold_east
4849 !#####################################################################################
4850 subroutine get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4851 integer, intent(in) :: jsg, jeg, isg, jshift, position
4852 integer, intent(inout) :: is, ie, js, je
4855 select case(position)
4857 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4858 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4860 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4861 i=is; is = 2*isg-ie; ie = 2*isg-i
4863 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4864 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4866 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4867 i=is; is = 2*isg-ie; ie = 2*isg-i
4870 end subroutine get_fold_index_west
4872 !#####################################################################################
4873 subroutine get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4874 integer, intent(in) :: jsg, jeg, ieg, jshift, position
4875 integer, intent(inout) :: is, ie, js, je
4878 select case(position)
4880 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4881 i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4883 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4884 i=is; is = 2*ieg-ie; ie = 2*ieg-i
4886 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4887 i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4889 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4890 i=is; is = 2*ieg-ie; ie = 2*ieg-i
4893 end subroutine get_fold_index_east
4895 !#####################################################################################
4896 subroutine get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
4897 integer, intent(in) :: isg, ieg, jsg, ishift, position
4898 integer, intent(inout) :: is, ie, js, je
4901 select case(position)
4903 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4904 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4906 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4907 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4909 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4910 j=js; js = 2*jsg-je; je = 2*jsg-j
4912 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4913 j=js; js = 2*jsg-je; je = 2*jsg-j
4916 end subroutine get_fold_index_south
4917 !#####################################################################################
4918 subroutine get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
4919 integer, intent(in) :: isg, ieg, jeg, ishift, position
4920 integer, intent(inout) :: is, ie, js, je
4923 select case(position)
4925 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4926 j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4928 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4929 j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4931 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4932 j=js; js = 2*jeg-je; je = 2*jeg-j
4934 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4935 j=js; js = 2*jeg-je; je = 2*jeg-j
4938 end subroutine get_fold_index_north
4941 !#####################################################################################
4942 ! add offset to the index
4943 subroutine apply_cyclic_offset(lstart, lend, offset, gstart, gend, gsize)
4944 integer, intent(inout) :: lstart, lend
4945 integer, intent(in ) :: offset, gstart, gend, gsize
4947 lstart = lstart + offset
4948 if(lstart > gend) lstart = lstart - gsize
4949 if(lstart < gstart) lstart = lstart + gsize
4950 lend = lend + offset
4951 if(lend > gend) lend = lend - gsize
4952 if(lend < gstart) lend = lend + gsize
4956 end subroutine apply_cyclic_offset
4958 !###################################################################################
4959 ! this routine setup the overlapping for mpp_update_domains for arbitrary halo update.
4960 ! should be the halo size defined in mpp_define_domains.
4961 ! xhalo_out, yhalo_out should not be exactly the same as xhalo_in, yhalo_in
4962 ! currently we didn't consider about tripolar grid situation, because in the folded north
4963 ! region, the overlapping is specified through list of points, not through rectangular.
4964 ! But will return back to solve this problem in the future.
4965 subroutine set_overlaps(domain, overlap_in, overlap_out, whalo_out, ehalo_out, shalo_out, nhalo_out)
4966 type(domain2d), intent(in) :: domain
4967 type(overlapSpec), intent(in) :: overlap_in
4968 type(overlapSpec), intent(inout) :: overlap_out
4969 integer, intent(in) :: whalo_out, ehalo_out, shalo_out, nhalo_out
4970 integer :: nlist, m, n, isoff, ieoff, jsoff, jeoff, rotation
4971 integer :: whalo_in, ehalo_in, shalo_in, nhalo_in
4973 type(overlap_type) :: overlap
4974 type(overlap_type), allocatable :: send(:), recv(:)
4975 type(overlap_type), pointer :: ptrIn => NULL()
4976 integer :: nsend, nrecv, nsend_in, nrecv_in
4978 if( domain%fold .NE. 0) call mpp_error(FATAL, "mpp_domains_define.inc(set_overlaps):"// &
4979 & " folded domain is not implemented for arbitrary halo update, contact developer")
4981 whalo_in = domain%whalo
4982 ehalo_in = domain%ehalo
4983 shalo_in = domain%shalo
4984 nhalo_in = domain%nhalo
4986 if( .NOT. domain%initialized) call mpp_error(FATAL, &
4987 "mpp_domains_define.inc: domain is not defined yet")
4989 nlist = size(domain%list(:))
4990 isoff = whalo_in - abs(whalo_out)
4991 ieoff = ehalo_in - abs(ehalo_out)
4992 jsoff = shalo_in - abs(shalo_out)
4993 jeoff = nhalo_in - abs(nhalo_out)
4996 nsend_in = overlap_in%nsend
4997 nrecv_in = overlap_in%nrecv
4998 if(nsend_in>0) allocate(send(nsend_in))
4999 if(nrecv_in>0) allocate(recv(nrecv_in))
5000 call allocate_update_overlap(overlap, MAXOVERLAP)
5002 overlap_out%whalo = whalo_out
5003 overlap_out%ehalo = ehalo_out
5004 overlap_out%shalo = shalo_out
5005 overlap_out%nhalo = nhalo_out
5006 overlap_out%xbegin = overlap_in%xbegin
5007 overlap_out%xend = overlap_in%xend
5008 overlap_out%ybegin = overlap_in%ybegin
5009 overlap_out%yend = overlap_in%yend
5011 !--- setting up overlap.
5013 ptrIn => overlap_in%send(m)
5014 if(ptrIn%count .LE. 0) call mpp_error(FATAL, "mpp_domains_define.inc(set_overlaps):"// &
5015 " number of overlap for send should be a positive number for"//trim(domain%name) )
5016 do n = 1, ptrIn%count
5018 rotation = ptrIn%rotation(n)
5020 case(1) ! to_pe's eastern halo
5021 if(ehalo_out > 0) then
5022 call set_single_overlap(ptrIn, overlap, 0, -ieoff, 0, 0, n, dir, rotation)
5023 else if(ehalo_out<0) then
5024 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, 0, 0, n, dir, rotation)
5026 case(2) ! to_pe's southeast halo
5027 if(ehalo_out>0 .AND. shalo_out > 0) then
5028 call set_single_overlap(ptrIn, overlap, 0, -ieoff, jsoff, 0, n, dir, rotation)
5029 else if(ehalo_out<0 .AND. shalo_out < 0) then ! three parts: southeast, south and east.
5030 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, 0, shalo_out, n, dir, rotation)
5031 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1, rotation)
5032 call set_single_overlap(ptrIn, overlap, 0, -ieoff, 0, shalo_out, n, dir+1, rotation)
5034 case(3) ! to_pe's southern halo
5035 if(shalo_out > 0) then
5036 call set_single_overlap(ptrIn, overlap, 0, 0, jsoff, 0, n, dir, rotation)
5037 else if(shalo_out<0) then
5038 call set_single_overlap(ptrIn, overlap, 0, 0, 0, shalo_out, n, dir, rotation)
5040 case(4) ! to_pe's southwest halo
5041 if(whalo_out>0 .AND. shalo_out > 0) then
5042 call set_single_overlap(ptrIn, overlap, isoff, 0, jsoff, 0, n, dir, rotation)
5043 else if(whalo_out<0 .AND. shalo_out < 0) then
5044 call set_single_overlap(ptrIn, overlap, 0, whalo_out, 0, shalo_out, n, dir, rotation)
5045 call set_single_overlap(ptrIn, overlap, isoff, 0, 0, shalo_out, n, dir-1, rotation)
5046 call set_single_overlap(ptrIn, overlap, 0, whalo_out, jsoff, 0, n, dir+1, rotation)
5048 case(5) ! to_pe's western halo
5049 if(whalo_out > 0) then
5050 call set_single_overlap(ptrIn, overlap, isoff, 0, 0, 0, n, dir, rotation)
5051 else if(whalo_out<0) then
5052 call set_single_overlap(ptrIn, overlap, 0, whalo_out, 0, 0, n, dir, rotation)
5054 case(6) ! to_pe's northwest halo
5055 if(whalo_out>0 .AND. nhalo_out > 0) then
5056 call set_single_overlap(ptrIn, overlap, isoff, 0, 0, -jeoff, n, dir, rotation)
5057 else if(whalo_out<0 .AND. nhalo_out < 0) then
5058 call set_single_overlap(ptrIn, overlap, 0, whalo_out, -nhalo_out, 0, n, dir, rotation)
5059 call set_single_overlap(ptrIn, overlap, 0, whalo_out, 0, -jeoff, n, dir-1, rotation)
5060 call set_single_overlap(ptrIn, overlap, isoff, 0, -nhalo_out, 0, n, dir+1, rotation)
5062 case(7) ! to_pe's northern halo
5063 if(nhalo_out > 0) then
5064 call set_single_overlap(ptrIn, overlap, 0, 0, 0, -jeoff, n, dir, rotation)
5065 else if(nhalo_out<0) then
5066 call set_single_overlap(ptrIn, overlap, 0, 0, -nhalo_out, 0, n, dir, rotation)
5068 case(8) ! to_pe's northeast halo
5069 if(ehalo_out>0 .AND. nhalo_out > 0) then
5070 call set_single_overlap(ptrIn, overlap, 0, -ieoff, 0, -jeoff, n, dir, rotation)
5071 else if(ehalo_out<0 .AND. nhalo_out < 0) then
5072 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir, rotation)
5073 call set_single_overlap(ptrIn, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1, rotation)
5074 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, 0, -jeoff, n, 1, rotation)
5077 end do ! do n = 1, ptrIn%count
5078 if(overlap%count>0) then
5080 call add_update_overlap(send(nsend), overlap)
5081 call init_overlap_type(overlap)
5083 end do ! end do list = 0, nlist-1
5086 overlap_out%nsend = nsend
5087 allocate(overlap_out%send(nsend));
5089 call add_update_overlap(overlap_out%send(n), send(n) )
5092 overlap_out%nsend = 0
5095 !--------------------------------------------------
5097 !---------------------------------------------------
5101 ptrIn => overlap_in%recv(m)
5102 if(ptrIn%count .LE. 0) call mpp_error(FATAL, &
5103 "mpp_domains_define.inc(set_overlaps): number of overlap for recv should be a positive number")
5105 do n = 1, ptrIn%count
5107 rotation = ptrIn%rotation(n)
5109 case(1) ! eastern halo
5110 if(ehalo_out > 0) then
5111 call set_single_overlap(ptrIn, overlap, 0, -ieoff, 0, 0, n, dir)
5112 else if(ehalo_out<0) then
5113 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, 0, 0, n, dir)
5115 case(2) ! southeast halo
5116 if(ehalo_out>0 .AND. shalo_out > 0) then
5117 call set_single_overlap(ptrIn, overlap, 0, -ieoff, jsoff, 0, n, dir)
5118 else if(ehalo_out<0 .AND. shalo_out < 0) then
5119 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, 0, shalo_out, n, dir)
5120 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1)
5121 call set_single_overlap(ptrIn, overlap, 0, -ieoff, 0, shalo_out, n, dir+1)
5123 case(3) ! southern halo
5124 if(shalo_out > 0) then
5125 call set_single_overlap(ptrIn, overlap, 0, 0, jsoff, 0, n, dir)
5126 else if(shalo_out<0) then
5127 call set_single_overlap(ptrIn, overlap, 0, 0, 0, shalo_out, n, dir)
5129 case(4) ! southwest halo
5130 if(whalo_out>0 .AND. shalo_out > 0) then
5131 call set_single_overlap(ptrIn, overlap, isoff, 0, jsoff, 0, n, dir)
5132 else if(whalo_out<0 .AND. shalo_out < 0) then
5133 call set_single_overlap(ptrIn, overlap, 0, whalo_out, 0, shalo_out, n, dir)
5134 call set_single_overlap(ptrIn, overlap, isoff, 0, 0, shalo_out, n, dir-1)
5135 call set_single_overlap(ptrIn, overlap, 0, whalo_out, jsoff, 0, n, dir+1)
5137 case(5) ! western halo
5138 if(whalo_out > 0) then
5139 call set_single_overlap(ptrIn, overlap, isoff, 0, 0, 0, n, dir)
5140 else if(whalo_out<0) then
5141 call set_single_overlap(ptrIn, overlap, 0, whalo_out, 0, 0, n, dir)
5143 case(6) ! northwest halo
5144 if(whalo_out>0 .AND. nhalo_out > 0) then
5145 call set_single_overlap(ptrIn, overlap, isoff, 0, 0, -jeoff, n, dir)
5146 else if(whalo_out<0 .AND. nhalo_out < 0) then
5147 call set_single_overlap(ptrIn, overlap, 0, whalo_out, -nhalo_out, 0, n, dir)
5148 call set_single_overlap(ptrIn, overlap, 0, whalo_out, 0, -jeoff, n, dir-1)
5149 call set_single_overlap(ptrIn, overlap, isoff, 0, -nhalo_out, 0, n, dir+1)
5151 case(7) ! northern halo
5152 if(nhalo_out > 0) then
5153 call set_single_overlap(ptrIn, overlap, 0, 0, 0, -jeoff, n, dir)
5154 else if(nhalo_out<0) then
5155 call set_single_overlap(ptrIn, overlap, 0, 0, -nhalo_out, 0, n, dir)
5157 case(8) ! northeast halo
5158 if(ehalo_out>0 .AND. nhalo_out > 0) then
5159 call set_single_overlap(ptrIn, overlap, 0, -ieoff, 0, -jeoff, n, dir)
5160 else if(ehalo_out<0 .AND. nhalo_out < 0) then
5161 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir)
5162 call set_single_overlap(ptrIn, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1)
5163 call set_single_overlap(ptrIn, overlap, -ehalo_out, 0, 0, -jeoff, n, 1)
5166 end do ! do n = 1, ptrIn%count
5167 if(overlap%count>0) then
5169 call add_update_overlap(recv(nrecv), overlap)
5170 call init_overlap_type(overlap)
5172 end do ! end do list = 0, nlist-1
5175 overlap_out%nrecv = nrecv
5176 allocate(overlap_out%recv(nrecv));
5178 call add_update_overlap(overlap_out%recv(n), recv(n) )
5181 overlap_out%nrecv = 0
5184 call deallocate_overlap_type(overlap)
5186 call deallocate_overlap_type(send(n))
5189 call deallocate_overlap_type(recv(n))
5191 if(allocated(send)) deallocate(send)
5192 if(allocated(recv)) deallocate(recv)
5195 call set_domain_comm_inf(overlap_out)
5198 end subroutine set_overlaps
5200 !##############################################################################
5201 subroutine set_single_overlap(overlap_in, overlap_out, isoff, ieoff, jsoff, jeoff, index, dir, rotation)
5202 type(overlap_type), intent(in) :: overlap_in
5203 type(overlap_type), intent(inout) :: overlap_out
5204 integer, intent(in) :: isoff, jsoff, ieoff, jeoff
5205 integer, intent(in) :: index
5206 integer, intent(in) :: dir
5207 integer, optional, intent(in) :: rotation
5211 if( overlap_out%pe == NULL_PE ) then
5212 overlap_out%pe = overlap_in%pe
5214 if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(FATAL, &
5215 "mpp_domains_define.inc(set_single_overlap): mismatch of pe between overlap_in and overlap_out")
5218 if(isoff .NE. 0 .and. ieoff .NE. 0) call mpp_error(FATAL, &
5219 "mpp_domains_define.inc(set_single_overlap): both isoff and ieoff are non-zero")
5220 if(jsoff .NE. 0 .and. jeoff .NE. 0) call mpp_error(FATAL, &
5221 "mpp_domains_define.inc(set_single_overlap): both jsoff and jeoff are non-zero")
5224 overlap_out%count = overlap_out%count + 1
5225 count = overlap_out%count
5226 if(count > MAXOVERLAP) call mpp_error(FATAL, &
5227 "set_single_overlap: number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
5229 if(present(rotation)) rotate = rotation
5230 overlap_out%rotation (count) = overlap_in%rotation(index)
5231 overlap_out%dir (count) = dir
5232 overlap_out%tileMe (count) = overlap_in%tileMe(index)
5233 overlap_out%tileNbr (count) = overlap_in%tileNbr(index)
5237 overlap_out%is(count) = overlap_in%is(index) + isoff
5238 overlap_out%ie(count) = overlap_in%ie(index) + ieoff
5239 overlap_out%js(count) = overlap_in%js(index) + jsoff
5240 overlap_out%je(count) = overlap_in%je(index) + jeoff
5242 overlap_out%is(count) = overlap_in%is(index) - jeoff
5243 overlap_out%ie(count) = overlap_in%ie(index) - jsoff
5244 overlap_out%js(count) = overlap_in%js(index) + isoff
5245 overlap_out%je(count) = overlap_in%je(index) + ieoff
5247 overlap_out%is(count) = overlap_in%is(index) + jsoff
5248 overlap_out%ie(count) = overlap_in%ie(index) + jeoff
5249 overlap_out%js(count) = overlap_in%js(index) - ieoff
5250 overlap_out%je(count) = overlap_in%je(index) - isoff
5252 call mpp_error(FATAL, "mpp_domains_define.inc: the value of rotation should be ZERO, NINETY or MINUS_NINETY")
5255 end subroutine set_single_overlap
5257 !###################################################################################
5258 !--- compute the overlapping between tiles for the T-cell.
5259 subroutine define_contact_point( domain, position, num_contact, tile1, tile2, align1, align2, &
5260 refine1, refine2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, &
5261 isgList, iegList, jsgList, jegList )
5262 type(domain2D), intent(inout) :: domain
5263 integer, intent(in) :: position
5264 integer, intent(in) :: num_contact ! number of contact regions
5265 integer, dimension(:), intent(in) :: tile1, tile2 ! tile number
5266 integer, dimension(:), intent(in) :: align1, align2 ! align direction of contact region
5267 real, dimension(:), intent(in) :: refine1, refine2 ! refinement between tiles
5268 integer, dimension(:), intent(in) :: istart1, iend1 ! i-index in tile_1 of contact region
5269 integer, dimension(:), intent(in) :: jstart1, jend1 ! j-index in tile_1 of contact region
5270 integer, dimension(:), intent(in) :: istart2, iend2 ! i-index in tile_2 of contact region
5271 integer, dimension(:), intent(in) :: jstart2, jend2 ! j-index in tile_2 of contact region
5272 integer, dimension(:), intent(in) :: isgList, iegList ! i-global domain of each tile
5273 integer, dimension(:), intent(in) :: jsgList, jegList ! j-global domain of each tile
5275 integer :: isc, iec, jsc, jec, isd, ied, jsd, jed
5276 integer :: isc1, iec1, jsc1, jec1, isc2, iec2, jsc2, jec2
5277 integer :: isd1, ied1, jsd1, jed1, isd2, ied2, jsd2, jed2
5278 integer :: is, ie, js, je, ioff, joff
5279 integer :: ntiles, max_contact
5280 integer :: nlist, list, m, n, l, count, numS, numR
5281 integer :: whalo, ehalo, shalo, nhalo
5282 integer :: t1, t2, tt, pos
5283 integer :: ntileMe, ntileNbr, tMe, tNbr, tileMe, dir
5284 integer :: nxd, nyd, nxc, nyc, ism, iem, jsm, jem
5285 integer :: dirlist(8)
5286 !--- is2Send and is1Send will figure out the overlapping for sending from current pe.
5287 !--- is1Recv and iscREcv will figure out the overlapping for recving onto current pe.
5288 integer, dimension(4*num_contact) :: is1Send, ie1Send, js1Send, je1Send
5289 integer, dimension(4*num_contact) :: is2Send, ie2Send, js2Send, je2Send
5290 integer, dimension(4*num_contact) :: is2Recv, ie2Recv, js2Recv, je2Recv
5291 integer, dimension(4*num_contact) :: is1Recv, ie1Recv, js1Recv, je1Recv
5292 integer, dimension(4*num_contact) :: align1Recv, align2Recv, align1Send, align2Send
5293 real, dimension(4*num_contact) :: refineRecv, refineSend
5294 integer, dimension(4*num_contact) :: rotateSend, rotateRecv, tileSend, tileRecv
5295 integer :: nsend, nrecv, nsend2, nrecv2
5296 type(contact_type), dimension(domain%ntiles) :: eCont, wCont, sCont, nCont
5297 type(overlap_type), dimension(0:size(domain%list(:))-1) :: overlapSend, overlapRecv
5300 if( position .NE. CENTER ) call mpp_error(FATAL, "mpp_domains_define.inc: " //&
5301 "routine define_contact_point can only be used to calculate overlapping for cell center.")
5303 ntiles = domain%ntiles
5305 eCont(:)%ncontact = 0
5308 eCont(n)%ncontact = 0; sCont(n)%ncontact = 0; wCont(n)%ncontact = 0; nCont(n)%ncontact = 0;
5309 allocate(eCont(n)%tile(num_contact), wCont(n)%tile(num_contact) )
5310 allocate(nCont(n)%tile(num_contact), sCont(n)%tile(num_contact) )
5311 allocate(eCont(n)%align1(num_contact), eCont(n)%align2(num_contact) )
5312 allocate(wCont(n)%align1(num_contact), wCont(n)%align2(num_contact) )
5313 allocate(sCont(n)%align1(num_contact), sCont(n)%align2(num_contact) )
5314 allocate(nCont(n)%align1(num_contact), nCont(n)%align2(num_contact) )
5315 allocate(eCont(n)%refine1(num_contact), eCont(n)%refine2(num_contact) )
5316 allocate(wCont(n)%refine1(num_contact), wCont(n)%refine2(num_contact) )
5317 allocate(sCont(n)%refine1(num_contact), sCont(n)%refine2(num_contact) )
5318 allocate(nCont(n)%refine1(num_contact), nCont(n)%refine2(num_contact) )
5319 allocate(eCont(n)%is1(num_contact), eCont(n)%ie1(num_contact), eCont(n)%js1(num_contact), &
5320 & eCont(n)%je1(num_contact))
5321 allocate(eCont(n)%is2(num_contact), eCont(n)%ie2(num_contact), eCont(n)%js2(num_contact), &
5322 & eCont(n)%je2(num_contact))
5323 allocate(wCont(n)%is1(num_contact), wCont(n)%ie1(num_contact), wCont(n)%js1(num_contact), &
5324 & wCont(n)%je1(num_contact))
5325 allocate(wCont(n)%is2(num_contact), wCont(n)%ie2(num_contact), wCont(n)%js2(num_contact), &
5326 & wCont(n)%je2(num_contact))
5327 allocate(sCont(n)%is1(num_contact), sCont(n)%ie1(num_contact), sCont(n)%js1(num_contact), &
5328 & sCont(n)%je1(num_contact))
5329 allocate(sCont(n)%is2(num_contact), sCont(n)%ie2(num_contact), sCont(n)%js2(num_contact), &
5330 & sCont(n)%je2(num_contact))
5331 allocate(nCont(n)%is1(num_contact), nCont(n)%ie1(num_contact), nCont(n)%js1(num_contact), &
5332 & nCont(n)%je1(num_contact))
5333 allocate(nCont(n)%is2(num_contact), nCont(n)%ie2(num_contact), nCont(n)%js2(num_contact), &
5334 & nCont(n)%je2(num_contact))
5337 !--- set up the east, south, west and north contact for each tile.
5338 do n = 1, num_contact
5341 select case(align1(n))
5343 call fill_contact( eCont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5344 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5346 call fill_contact( wCont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5347 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5349 call fill_contact( sCont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5350 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5352 call fill_contact( nCont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5353 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5355 select case(align2(n))
5357 call fill_contact( eCont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5358 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5360 call fill_contact( wCont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5361 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5363 call fill_contact( sCont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5364 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5366 call fill_contact( nCont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5367 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5371 !--- the tile number of current pe, halo size
5372 whalo = domain%whalo
5373 ehalo = domain%ehalo
5374 shalo = domain%shalo
5375 nhalo = domain%nhalo
5377 !--- find if there is an extra point in x and y direction depending on position
5378 nlist = size(domain%list(:))
5380 max_contact = 4*num_contact ! should be enough
5382 ntileMe = size(domain%x(:))
5383 refineSend = 1; refineRecv = 1
5385 !--------------------------------------------------------------------------------------------------
5386 ! loop over each tile on current domain to set up the overlapping for each tile
5387 !--------------------------------------------------------------------------------------------------
5388 !--- first check the overlap within the tiles.
5389 do n = 1, domain%update_T%nsend
5390 pos = domain%update_T%send(n)%pe - mpp_root_pe()
5391 call add_update_overlap(overlapSend(pos), domain%update_T%send(n) )
5393 do n = 1, domain%update_T%nrecv
5394 pos = domain%update_T%recv(n)%pe - mpp_root_pe()
5395 call add_update_overlap(overlapRecv(pos), domain%update_T%recv(n) )
5398 call mpp_get_memory_domain(domain, ism, iem, jsm, jem)
5399 domain%update_T%xbegin = ism; domain%update_T%xend = iem
5400 domain%update_T%ybegin = jsm; domain%update_T%yend = jem
5401 domain%update_T%whalo = whalo; domain%update_T%ehalo = ehalo
5402 domain%update_T%shalo = shalo; domain%update_T%nhalo = nhalo
5405 tileMe = domain%tile_id(tMe)
5406 rotateSend = ZERO; rotateRecv = ZERO
5408 !--- loop over all the contact region to figure out the index for overlapping region.
5410 do n = 1, eCont(tileMe)%ncontact ! east contact
5412 tileRecv(count) = eCont(tileMe)%tile(n); tileSend(count) = eCont(tileMe)%tile(n)
5413 align1Recv(count) = eCont(tileMe)%align1(n); align2Recv(count) = eCont(tileMe)%align2(n)
5414 align1Send(count) = eCont(tileMe)%align1(n); align2Send(count) = eCont(tileMe)%align2(n)
5415 refineSend(count) = eCont(tileMe)%refine2(n); refineRecv(count) = eCont(tileMe)%refine1(n)
5416 is1Recv(count) = eCont(tileMe)%is1(n) + 1; ie1Recv(count) = is1Recv(count) + ehalo - 1
5417 js1Recv(count) = eCont(tileMe)%js1(n); je1Recv(count) = eCont(tileMe)%je1(n)
5418 select case(eCont(tileMe)%align2(n))
5419 case ( WEST ) ! w <-> e
5420 is2Recv(count) = eCont(tileMe)%is2(n); ie2Recv(count) = is2Recv(count) + ehalo - 1
5421 js2Recv(count) = eCont(tileMe)%js2(n); je2Recv(count) = eCont(tileMe)%je2(n)
5422 ie1Send(count) = eCont(tileMe)%is1(n); is1Send(count) = ie1Send(count) - whalo + 1
5423 js1Send(count) = eCont(tileMe)%js1(n); je1Send(count) = eCont(tileMe)%je1(n)
5424 ie2Send(count) = eCont(tileMe)%is2(n) - 1; is2Send(count) = ie2Send(count) - whalo + 1
5425 js2Send(count) = eCont(tileMe)%js2(n); je2Send(count) = eCont(tileMe)%je2(n)
5426 case ( SOUTH ) ! s <-> e
5427 rotateRecv(count) = NINETY; rotateSend(count) = MINUS_NINETY
5428 js2Recv(count) = eCont(tileMe)%js2(n); je2Recv(count) = js2Recv(count) + ehalo -1
5429 is2Recv(count) = eCont(tileMe)%is2(n); ie2Recv(count) = eCont(tileMe)%ie2(n)
5430 ie1Send(count) = eCont(tileMe)%is1(n); is1Send(count) = ie1Send(count) - shalo + 1
5431 js1Send(count) = eCont(tileMe)%js1(n); je1Send(count) = eCont(tileMe)%je1(n)
5432 is2Send(count) = eCont(tileMe)%is2(n); ie2Send(count) = eCont(tileMe)%ie2(n)
5433 je2Send(count) = eCont(tileMe)%js2(n) - 1; js2Send(count) = je2Send(count) - shalo + 1
5437 do n = 1, sCont(tileMe)%ncontact ! south contact
5439 tileRecv(count) = sCont(tileMe)%tile(n); tileSend(count) = sCont(tileMe)%tile(n)
5440 align1Recv(count) = sCont(tileMe)%align1(n); align2Recv(count) = sCont(tileMe)%align2(n);
5441 align1Send(count) = sCont(tileMe)%align1(n); align2Send(count) = sCont(tileMe)%align2(n);
5442 refineSend(count) = sCont(tileMe)%refine2(n); refineRecv(count) = sCont(tileMe)%refine1(n)
5443 is1Recv(count) = sCont(tileMe)%is1(n); ie1Recv(count) = sCont(tileMe)%ie1(n)
5444 je1Recv(count) = sCont(tileMe)%js1(n) - 1; js1Recv(count) = je1Recv(count) - shalo + 1
5445 select case(sCont(tileMe)%align2(n))
5446 case ( NORTH ) ! n <-> s
5447 is2Recv(count) = sCont(tileMe)%is2(n); ie2Recv(count) = sCont(tileMe)%ie2(n)
5448 je2Recv(count) = sCont(tileMe)%je2(n); js2Recv(count) = je2Recv(count) - shalo + 1
5449 is1Send(count) = sCont(tileMe)%is1(n); ie1Send(count) = sCont(tileMe)%ie1(n)
5450 js1Send(count) = sCont(tileMe)%js1(n); je1Send(count) = js1Send(count) + nhalo -1
5451 is2Send(count) = sCont(tileMe)%is2(n); ie2Send(count) = sCont(tileMe)%ie2(n)
5452 js2Send(count) = sCont(tileMe)%je2(n)+1; je2Send(count) = js2Send(count) + nhalo - 1
5453 case ( EAST ) ! e <-> s
5454 rotateRecv(count) = MINUS_NINETY; rotateSend(count) = NINETY
5455 ie2Recv(count) = sCont(tileMe)%ie2(n); is2Recv(count) = ie2Recv(count) - shalo + 1
5456 js2Recv(count) = sCont(tileMe)%js2(n); je2Recv(count) = sCont(tileMe)%je2(n)
5457 is1Send(count) = sCont(tileMe)%is1(n); ie1Send(count) = sCont(tileMe)%ie1(n)
5458 js1Send(count) = sCont(tileMe)%js1(n); je1Send(count) = js1Send(count) + ehalo - 1
5459 is2Send(count) = sCont(tileMe)%ie2(n)+1; ie2Send(count) = is2Send(count) + ehalo - 1
5460 js2Send(count) = sCont(tileMe)%js2(n); je2Send(count) = sCont(tileMe)%je2(n)
5464 do n = 1, wCont(tileMe)%ncontact ! west contact
5466 tileRecv(count) = wCont(tileMe)%tile(n); tileSend(count) = wCont(tileMe)%tile(n)
5467 align1Recv(count) = wCont(tileMe)%align1(n); align2Recv(count) = wCont(tileMe)%align2(n);
5468 align1Send(count) = wCont(tileMe)%align1(n); align2Send(count) = wCont(tileMe)%align2(n);
5469 refineSend(count) = wCont(tileMe)%refine2(n); refineRecv(count) = wCont(tileMe)%refine1(n)
5470 ie1Recv(count) = wCont(tileMe)%is1(n) - 1; is1Recv(count) = ie1Recv(count) - whalo + 1
5471 js1Recv(count) = wCont(tileMe)%js1(n); je1Recv(count) = wCont(tileMe)%je1(n)
5472 select case(wCont(tileMe)%align2(n))
5473 case ( EAST ) ! e <-> w
5474 ie2Recv(count) = wCont(tileMe)%ie2(n); is2Recv(count) = ie2Recv(count) - whalo + 1
5475 js2Recv(count) = wCont(tileMe)%js2(n); je2Recv(count) = wCont(tileMe)%je2(n)
5476 is1Send(count) = wCont(tileMe)%is1(n); ie1Send(count) = is1Send(count) + ehalo - 1
5477 js1Send(count) = wCont(tileMe)%js1(n); je1Send(count) = wCont(tileMe)%je1(n)
5478 is2Send(count) = wCont(tileMe)%ie2(n)+1; ie2Send(count) = is2Send(count) + ehalo - 1
5479 js2Send(count) = wCont(tileMe)%js2(n); je2Send(count) = wCont(tileMe)%je2(n)
5480 case ( NORTH ) ! n <-> w
5481 rotateRecv(count) = NINETY; rotateSend(count) = MINUS_NINETY
5482 je2Recv(count) = wCont(tileMe)%je2(n); js2Recv(count) = je2Recv(count) - whalo + 1
5483 is2Recv(count) = wCont(tileMe)%is2(n); ie2Recv(count) = wCont(tileMe)%ie2(n)
5484 is1Send(count) = wCont(tileMe)%is1(n); ie1Send(count) = is1Send(count) + nhalo - 1
5485 js1Send(count) = wCont(tileMe)%js1(n); je1Send(count) = wCont(tileMe)%je1(n)
5486 js2Send(count) = wCont(tileMe)%je2(n)+1; je2Send(count) = js2Send(count) + nhalo - 1
5487 is2Send(count) = wCont(tileMe)%is2(n); ie2Send(count) = wCont(tileMe)%ie2(n)
5491 do n = 1, nCont(tileMe)%ncontact ! north contact
5493 tileRecv(count) = nCont(tileMe)%tile(n); tileSend(count) = nCont(tileMe)%tile(n)
5494 align1Recv(count) = nCont(tileMe)%align1(n); align2Recv(count) = nCont(tileMe)%align2(n);
5495 align1Send(count) = nCont(tileMe)%align1(n); align2Send(count) = nCont(tileMe)%align2(n);
5496 refineSend(count) = nCont(tileMe)%refine2(n); refineRecv(count) = nCont(tileMe)%refine1(n)
5497 is1Recv(count) = nCont(tileMe)%is1(n); ie1Recv(count) = nCont(tileMe)%ie1(n)
5498 js1Recv(count) = nCont(tileMe)%je1(n)+1; je1Recv(count) = js1Recv(count) + nhalo - 1
5499 select case(nCont(tileMe)%align2(n))
5500 case ( SOUTH ) ! s <-> n
5501 is2Recv(count) = nCont(tileMe)%is2(n); ie2Recv(count) = nCont(tileMe)%ie2(n)
5502 js2Recv(count) = nCont(tileMe)%js2(n); je2Recv(count) = js2Recv(count) + nhalo - 1
5503 is1Send(count) = nCont(tileMe)%is1(n); ie1Send(count) = nCont(tileMe)%ie1(n)
5504 je1Send(count) = nCont(tileMe)%je1(n); js1Send(count) = je1Send(count) - shalo + 1
5505 is2Send(count) = nCont(tileMe)%is2(n); ie2Send(count) = nCont(tileMe)%ie2(n)
5506 je2Send(count) = nCont(tileMe)%js2(n)-1; js2Send(count) = je2Send(count) - shalo + 1
5507 case ( WEST ) ! w <-> n
5508 rotateRecv(count) = MINUS_NINETY; rotateSend(count) = NINETY
5509 is2Recv(count) = nCont(tileMe)%ie2(n); ie2Recv(count) = is2Recv(count) + nhalo - 1
5510 js2Recv(count) = nCont(tileMe)%js2(n); je2Recv(count) = nCont(tileMe)%je2(n)
5511 is1Send(count) = nCont(tileMe)%is1(n); ie1Send(count) = nCont(tileMe)%ie1(n)
5512 je1Send(count) = nCont(tileMe)%je1(n); js1Send(count) = je1Send(count) - whalo + 1
5513 ie2Send(count) = nCont(tileMe)%is2(n)-1; is2Send(count) = ie2Send(count) - whalo + 1
5514 js2Send(count) = nCont(tileMe)%js2(n); je2Send(count) = nCont(tileMe)%je2(n)
5520 !--- figure out the index for corner overlapping,
5521 !--- fill_corner_contact will be updated to deal with the situation that there are multiple tiles on
5522 !--- each side of six sides of cubic grid.
5523 if(.NOT. domain%rotated_ninety) then
5524 call fill_corner_contact(eCont, sCont, wCont, nCont, isgList, iegList, jsgList, jegList, numR, numS, &
5525 tileRecv, tileSend, is1Recv, ie1Recv, js1Recv, je1Recv, is2Recv, ie2Recv, &
5526 js2Recv, je2Recv, is1Send, ie1Send, js1Send, je1Send, is2Send, ie2Send, &
5527 js2Send, je2Send, align1Recv, align2Recv, align1Send, align2Send, &
5528 whalo, ehalo, shalo, nhalo, tileMe )
5531 isc = domain%x(tMe)%compute%begin; iec = domain%x(tMe)%compute%end
5532 jsc = domain%y(tMe)%compute%begin; jec = domain%y(tMe)%compute%end
5534 !--- compute the overlapping for send.
5536 do list = 0, nlist-1
5537 m = mod( domain%pos+list, nlist )
5538 ntileNbr = size(domain%list(m)%x(:))
5539 do tNbr = 1, ntileNbr
5540 if( domain%list(m)%tile_id(tNbr) .NE. tileSend(n) ) cycle
5541 isc1 = max(isc, is1Send(n)); iec1 = min(iec, ie1Send(n))
5542 jsc1 = max(jsc, js1Send(n)); jec1 = min(jec, je1Send(n))
5543 if( isc1 > iec1 .OR. jsc1 > jec1 ) cycle
5544 !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5546 !--- get the to_pe's data domain.
5548 case ( 1 ) ! eastern halo
5549 if( align2Send(n) .NE. EAST ) cycle
5550 isd = domain%list(m)%x(tNbr)%compute%end+1; ied = domain%list(m)%x(tNbr)%compute%end+ehalo
5551 jsd = domain%list(m)%y(tNbr)%compute%begin; jed = domain%list(m)%y(tNbr)%compute%end
5552 case ( 2 ) ! southeast halo
5553 isd = domain%list(m)%x(tNbr)%compute%end+1; ied = domain%list(m)%x(tNbr)%compute%end+ehalo
5554 jsd = domain%list(m)%y(tNbr)%compute%begin-shalo; jed = domain%list(m)%y(tNbr)%compute%begin-1
5555 case ( 3 ) ! southern halo
5556 if( align2Send(n) .NE. SOUTH ) cycle
5557 isd = domain%list(m)%x(tNbr)%compute%begin; ied = domain%list(m)%x(tNbr)%compute%end
5558 jsd = domain%list(m)%y(tNbr)%compute%begin-shalo; jed = domain%list(m)%y(tNbr)%compute%begin-1
5559 case ( 4 ) ! southwest halo
5560 isd = domain%list(m)%x(tNbr)%compute%begin-whalo; ied = domain%list(m)%x(tNbr)%compute%begin-1
5561 jsd = domain%list(m)%y(tNbr)%compute%begin-shalo; jed = domain%list(m)%y(tNbr)%compute%begin-1
5562 case ( 5 ) ! western halo
5563 if( align2Send(n) .NE. WEST ) cycle
5564 isd = domain%list(m)%x(tNbr)%compute%begin-whalo; ied = domain%list(m)%x(tNbr)%compute%begin-1
5565 jsd = domain%list(m)%y(tNbr)%compute%begin; jed = domain%list(m)%y(tNbr)%compute%end
5566 case ( 6 ) ! northwest halo
5567 isd = domain%list(m)%x(tNbr)%compute%begin-whalo; ied = domain%list(m)%x(tNbr)%compute%begin-1
5568 jsd = domain%list(m)%y(tNbr)%compute%end+1; jed = domain%list(m)%y(tNbr)%compute%end+nhalo
5569 case ( 7 ) ! northern halo
5570 if( align2Send(n) .NE. NORTH ) cycle
5571 isd = domain%list(m)%x(tNbr)%compute%begin; ied = domain%list(m)%x(tNbr)%compute%end
5572 jsd = domain%list(m)%y(tNbr)%compute%end+1; jed = domain%list(m)%y(tNbr)%compute%end+nhalo
5573 case ( 8 ) ! northeast halo
5574 isd = domain%list(m)%x(tNbr)%compute%end+1; ied = domain%list(m)%x(tNbr)%compute%end+ehalo
5575 jsd = domain%list(m)%y(tNbr)%compute%end+1; jed = domain%list(m)%y(tNbr)%compute%end+nhalo
5577 isd = max(isd, is2Send(n)); ied = min(ied, ie2Send(n))
5578 jsd = max(jsd, js2Send(n)); jed = min(jed, je2Send(n))
5579 if( isd > ied .OR. jsd > jed ) cycle
5583 select case ( align2Send(n) )
5585 ioff = isd - is2Send(n)
5586 joff = jsd - js2Send(n)
5587 case ( SOUTH, NORTH )
5588 ioff = isd - is2Send(n)
5589 joff = jsd - js2Send(n)
5592 !--- get the index in current pe.
5593 select case ( rotateSend(n) )
5595 isc2 = is1Send(n) + ioff; iec2 = isc2 + nxd - 1
5596 jsc2 = js1Send(n) + joff; jec2 = jsc2 + nyd - 1
5597 case ( NINETY ) ! N -> W or S -> E
5598 iec2 = ie1Send(n) - joff; isc2 = iec2 - nyd + 1
5599 jsc2 = js1Send(n) + ioff; jec2 = jsc2 + nxd - 1
5600 case ( MINUS_NINETY ) ! W -> N or E -> S
5601 isc2 = is1Send(n) + joff; iec2 = isc2 + nyd - 1
5602 jec2 = je1Send(n) - ioff; jsc2 = jec2 - nxd + 1
5604 is = max(isc1,isc2); ie = min(iec1,iec2)
5605 js = max(jsc1,jsc2); je = min(jec1,jec2)
5606 if(ie.GE.is .AND. je.GE.js )then
5607 if(.not. associated(overlapSend(m)%tileMe)) call allocate_update_overlap(overlapSend(m), &
5609 call insert_overlap_type(overlapSend(m), domain%list(m)%pe, tMe, tNbr, &
5610 is, ie, js, je, dir, rotateSend(n), .true. )
5612 end do ! end do dir = 1, 8
5613 end do ! end do tNbr = 1, ntileNbr
5614 end do ! end do list = 0, nlist-1
5615 end do ! end do n = 1, numS
5617 !--- compute the overlapping for recv.
5619 do list = 0, nlist-1
5620 m = mod( domain%pos+nlist-list, nlist )
5621 ntileNbr = size(domain%list(m)%x(:))
5622 do tNbr = 1, ntileNbr
5623 if( domain%list(m)%tile_id(tNbr) .NE. tileRecv(n) ) cycle
5624 isc = domain%list(m)%x(tNbr)%compute%begin; iec = domain%list(m)%x(tNbr)%compute%end
5625 jsc = domain%list(m)%y(tNbr)%compute%begin; jec = domain%list(m)%y(tNbr)%compute%end
5626 isc = max(isc, is2Recv(n)); iec = min(iec, ie2Recv(n))
5627 jsc = max(jsc, js2Recv(n)); jec = min(jec, je2Recv(n))
5628 if( isc > iec .OR. jsc > jec ) cycle
5629 !--- find the offset for this overlapping.
5631 nxc = iec - isc + 1; nyc = jec - jsc + 1
5632 select case ( align2Recv(n) )
5634 if(align2Recv(n) == WEST) then
5635 ioff = isc - is2Recv(n)
5637 ioff = ie2Recv(n) - iec
5639 joff = jsc - js2Recv(n)
5640 case ( NORTH, SOUTH )
5641 ioff = isc - is2Recv(n)
5642 if(align2Recv(n) == SOUTH) then
5643 joff = jsc - js2Recv(n)
5645 joff = je2Recv(n) - jec
5649 !--- get the index in current pe.
5650 select case ( rotateRecv(n) )
5652 isd1 = is1Recv(n) + ioff; ied1 = isd1 + nxc - 1
5653 jsd1 = js1Recv(n) + joff; jed1 = jsd1 + nyc - 1
5654 if( align1Recv(n) == WEST ) then
5655 ied1 = ie1Recv(n)-ioff; isd1 = ied1 - nxc + 1
5657 if( align1Recv(n) == SOUTH ) then
5658 jed1 = je1Recv(n)-joff; jsd1 = jed1 - nyc + 1
5660 case ( NINETY ) ! N -> W or S -> E
5661 if( align1Recv(n) == WEST ) then
5662 ied1 = ie1Recv(n)-joff; isd1 = ied1 - nyc + 1
5664 isd1 = is1Recv(n)+joff; ied1 = isd1 + nyc - 1
5666 jed1 = je1Recv(n) - ioff; jsd1 = jed1 - nxc + 1
5667 case ( MINUS_NINETY ) ! W -> N or E -> S
5668 ied1 = ie1Recv(n) - joff; isd1 = ied1 - nyc + 1
5669 if( align1Recv(n) == SOUTH ) then
5670 jed1 = je1Recv(n)-ioff; jsd1 = jed1 - nxc + 1
5672 jsd1 = js1Recv(n)+ioff; jed1 = jsd1 + nxc - 1
5676 !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5679 case ( 1 ) ! eastern halo
5680 if( align1Recv(n) .NE. EAST ) cycle
5681 isd2 = domain%x(tMe)%compute%end+1; ied2 = domain%x(tMe)%data%end
5682 jsd2 = domain%y(tMe)%compute%begin; jed2 = domain%y(tMe)%compute%end
5683 case ( 2 ) ! southeast halo
5684 isd2 = domain%x(tMe)%compute%end+1; ied2 = domain%x(tMe)%data%end
5685 jsd2 = domain%y(tMe)%data%begin; jed2 = domain%y(tMe)%compute%begin-1
5686 case ( 3 ) ! southern halo
5687 if( align1Recv(n) .NE. SOUTH ) cycle
5688 isd2 = domain%x(tMe)%compute%begin; ied2 = domain%x(tMe)%compute%end
5689 jsd2 = domain%y(tMe)%data%begin; jed2 = domain%y(tMe)%compute%begin-1
5690 case ( 4 ) ! southwest halo
5691 isd2 = domain%x(tMe)%data%begin; ied2 = domain%x(tMe)%compute%begin-1
5692 jsd2 = domain%y(tMe)%data%begin; jed2 = domain%y(tMe)%compute%begin-1
5693 case ( 5 ) ! western halo
5694 if( align1Recv(n) .NE. WEST ) cycle
5695 isd2 = domain%x(tMe)%data%begin; ied2 = domain%x(tMe)%compute%begin-1
5696 jsd2 = domain%y(tMe)%compute%begin; jed2 = domain%y(tMe)%compute%end
5697 case ( 6 ) ! northwest halo
5698 isd2 = domain%x(tMe)%data%begin; ied2 = domain%x(tMe)%compute%begin-1
5699 jsd2 = domain%y(tMe)%compute%end+1; jed2 = domain%y(tMe)%data%end
5700 case ( 7 ) ! northern halo
5701 if( align1Recv(n) .NE. NORTH ) cycle
5702 isd2 = domain%x(tMe)%compute%begin; ied2 = domain%x(tMe)%compute%end
5703 jsd2 = domain%y(tMe)%compute%end+1; jed2 = domain%y(tMe)%data%end
5704 case ( 8 ) ! northeast halo
5705 isd2 = domain%x(tMe)%compute%end+1; ied2 = domain%x(tMe)%data%end
5706 jsd2 = domain%y(tMe)%compute%end+1; jed2 = domain%y(tMe)%data%end
5708 is = max(isd1,isd2); ie = min(ied1,ied2)
5709 js = max(jsd1,jsd2); je = min(jed1,jed2)
5710 if(ie.GE.is .AND. je.GE.js )then
5711 if(.not. associated(overlapRecv(m)%tileMe)) call allocate_update_overlap(overlapRecv(m), &
5713 call insert_overlap_type(overlapRecv(m), domain%list(m)%pe, tMe, tNbr, &
5714 is, ie, js, je, dir, rotateRecv(n), .true.)
5715 count = overlapRecv(m)%count
5717 end do ! end do dir = 1, 8
5718 end do ! end do tNbr = 1, ntileNbr
5719 end do ! end do list = 0, nlist-1
5720 end do ! end do n = 1, numR
5721 end do ! end do tMe = 1, ntileMe
5723 !--- copy the overlapping information into domain data
5724 nsend = 0; nsend2 = 0
5725 do list = 0, nlist-1
5726 m = mod( domain%pos+list, nlist )
5727 if(overlapSend(m)%count>0) nsend = nsend + 1
5730 if(debug_message_passing) then
5731 !--- write out send information
5732 unit = mpp_pe() + 1000
5733 do list = 0, nlist-1
5734 m = mod( domain%pos+list, nlist )
5735 if(overlapSend(m)%count==0) cycle
5736 write(unit, *) "********to_pe = " ,overlapSend(m)%pe, " count = ",overlapSend(m)%count
5737 do n = 1, overlapSend(m)%count
5738 write(unit, *) overlapSend(m)%is(n), overlapSend(m)%ie(n), overlapSend(m)%js(n), overlapSend(m)%je(n), &
5739 overlapSend(m)%dir(n), overlapSend(m)%rotation(n)
5742 if(nsend >0) flush(unit)
5745 dirlist(1) = 1; dirlist(2) = 3; dirlist(3) = 5; dirlist(4) = 7
5746 dirlist(5) = 2; dirlist(6) = 4; dirlist(7) = 6; dirlist(8) = 8
5748 ! copy the overlap information into domain.
5750 if(associated(domain%update_T%send)) then
5751 do m = 1, domain%update_T%nsend
5752 call deallocate_overlap_type(domain%update_T%send(m))
5754 deallocate(domain%update_T%send)
5756 domain%update_T%nsend = nsend
5757 allocate(domain%update_T%send(nsend))
5758 do list = 0, nlist-1
5759 m = mod( domain%pos+list, nlist )
5760 ntileNbr = size(domain%list(m)%x(:))
5761 !--- for the send, the list should be in tileNbr order and dir order to be consistent with Recv
5762 if(overlapSend(m)%count > 0) then
5764 if(nsend2>nsend) call mpp_error(FATAL, &
5765 "mpp_domains_define.inc(define_contact_point): nsend2 is greater than nsend")
5766 call allocate_update_overlap(domain%update_T%send(nsend2), overlapSend(m)%count)
5768 do tNbr = 1, ntileNbr
5770 if(domain%list(m)%pe == domain%pe) then ! own processor
5772 if(tMe > ntileMe) tMe = tMe - ntileMe
5776 do n = 1, 8 ! loop over 8 direction
5777 do l = 1, overlapSend(m)%count
5778 if(overlapSend(m)%tileMe(l) .NE. tMe) cycle
5779 if(overlapSend(m)%tileNbr(l) .NE. tNbr) cycle
5780 if(overlapSend(m)%dir(l) .NE. dirlist(n) ) cycle
5781 call insert_overlap_type(domain%update_T%send(nsend2), overlapSend(m)%pe, &
5782 overlapSend(m)%tileMe(l), overlapSend(m)%tileNbr(l), overlapSend(m)%is(l), &
5783 overlapSend(m)%ie(l), overlapSend(m)%js(l), overlapSend(m)%je(l), overlapSend(m)%dir(l),&
5784 overlapSend(m)%rotation(l), overlapSend(m)%from_contact(l) )
5793 if(nsend2 .NE. nsend) call mpp_error(FATAL, &
5794 "mpp_domains_define.inc(define_contact_point): nsend2 does not equal to nsend")
5796 nrecv = 0; nrecv2 = 0
5797 do list = 0, nlist-1
5798 m = mod( domain%pos+list, nlist )
5799 if(overlapRecv(m)%count>0) nrecv = nrecv + 1
5802 if(debug_message_passing) then
5803 do list = 0, nlist-1
5804 m = mod( domain%pos+list, nlist )
5805 if(overlapRecv(m)%count==0) cycle
5806 write(unit, *) "********from_pe = " ,overlapRecv(m)%pe, " count = ",overlapRecv(m)%count
5807 do n = 1, overlapRecv(m)%count
5808 write(unit, *) overlapRecv(m)%is(n), overlapRecv(m)%ie(n), overlapRecv(m)%js(n), overlapRecv(m)%je(n), &
5809 overlapRecv(m)%dir(n), overlapRecv(m)%rotation(n)
5812 if(nrecv >0) flush(unit)
5816 if(associated(domain%update_T%recv)) then
5817 do m = 1, domain%update_T%nrecv
5818 call deallocate_overlap_type(domain%update_T%recv(m))
5820 deallocate(domain%update_T%recv)
5822 domain%update_T%nrecv = nrecv
5823 allocate(domain%update_T%recv(nrecv))
5825 do list = 0, nlist-1
5826 m = mod( domain%pos+nlist-list, nlist )
5827 ntileNbr = size(domain%list(m)%x(:))
5828 if(overlapRecv(m)%count > 0) then
5830 if(nrecv2>nrecv) call mpp_error(FATAL, &
5831 "mpp_domains_define.inc(define_contact_point): nrecv2 is greater than nrecv")
5832 call allocate_update_overlap(domain%update_T%recv(nrecv2), overlapRecv(m)%count)
5835 !--- make sure the same order tile for different pe count
5836 if(domain%list(m)%pe == domain%pe) then ! own processor
5838 if(tNbr>ntileNbr) tNbr = tNbr - ntileNbr
5842 do n = 1, 8 ! loop over 8 direction
5843 do l = 1, overlapRecv(m)%count
5844 if(overlapRecv(m)%tileMe(l) .NE. tMe) cycle
5845 if(overlapRecv(m)%tileNbr(l) .NE. tNbr) cycle
5846 if(overlapRecv(m)%dir(l) .NE. dirlist(n) ) cycle
5847 call insert_overlap_type(domain%update_T%recv(nrecv2), overlapRecv(m)%pe, &
5848 overlapRecv(m)%tileMe(l), overlapRecv(m)%tileNbr(l), overlapRecv(m)%is(l), &
5849 overlapRecv(m)%ie(l), overlapRecv(m)%js(l), overlapRecv(m)%je(l), overlapRecv(m)%dir(l),&
5850 overlapRecv(m)%rotation(l), overlapRecv(m)%from_contact(l))
5851 count = domain%update_T%recv(nrecv2)%count
5860 if(nrecv2 .NE. nrecv) call mpp_error(FATAL, &
5861 "mpp_domains_define.inc(define_contact_point): nrecv2 does not equal to nrecv")
5864 call deallocate_overlap_type(overlapSend(m))
5865 call deallocate_overlap_type(overlapRecv(m))
5869 deallocate(eCont(n)%tile, wCont(n)%tile, sCont(n)%tile, nCont(n)%tile )
5870 deallocate(eCont(n)%align1, wCont(n)%align1, sCont(n)%align1, nCont(n)%align1)
5871 deallocate(eCont(n)%align2, wCont(n)%align2, sCont(n)%align2, nCont(n)%align2)
5872 deallocate(eCont(n)%refine1, wCont(n)%refine1, sCont(n)%refine1, nCont(n)%refine1)
5873 deallocate(eCont(n)%refine2, wCont(n)%refine2, sCont(n)%refine2, nCont(n)%refine2)
5874 deallocate(eCont(n)%is1, eCont(n)%ie1, eCont(n)%js1, eCont(n)%je1 )
5875 deallocate(eCont(n)%is2, eCont(n)%ie2, eCont(n)%js2, eCont(n)%je2 )
5876 deallocate(wCont(n)%is1, wCont(n)%ie1, wCont(n)%js1, wCont(n)%je1 )
5877 deallocate(wCont(n)%is2, wCont(n)%ie2, wCont(n)%js2, wCont(n)%je2 )
5878 deallocate(sCont(n)%is1, sCont(n)%ie1, sCont(n)%js1, sCont(n)%je1 )
5879 deallocate(sCont(n)%is2, sCont(n)%ie2, sCont(n)%js2, sCont(n)%je2 )
5880 deallocate(nCont(n)%is1, nCont(n)%ie1, nCont(n)%js1, nCont(n)%je1 )
5881 deallocate(nCont(n)%is2, nCont(n)%ie2, nCont(n)%js2, nCont(n)%je2 )
5884 domain%initialized = .true.
5887 end subroutine define_contact_point
5889 !##############################################################################
5890 !--- always fill the contact according to index order.
5891 subroutine fill_contact(Contact, tile, is1, ie1, js1, je1, is2, ie2, js2, je2, align1, align2, refine1, refine2 )
5892 type(contact_type), intent(inout) :: Contact
5893 integer, intent(in) :: tile
5894 integer, intent(in) :: is1, ie1, js1, je1
5895 integer, intent(in) :: is2, ie2, js2, je2
5896 integer, intent(in) :: align1, align2
5897 real, intent(in) :: refine1, refine2
5900 do pos = 1, Contact%ncontact
5903 if( js1 < Contact%js1(pos) ) exit
5905 if( is1 < Contact%is1(pos) ) exit
5909 Contact%ncontact = Contact%ncontact + 1
5910 do n = Contact%ncontact, pos+1, -1 ! shift the data if needed.
5911 Contact%tile(n) = Contact%tile(n-1)
5912 Contact%align1(n) = Contact%align1(n-1)
5913 Contact%align2(n) = Contact%align2(n-1)
5914 Contact%is1(n) = Contact%is1(n-1); Contact%ie1(n) = Contact%ie1(n-1)
5915 Contact%js1(n) = Contact%js1(n-1); Contact%je1(n) = Contact%je1(n-1)
5916 Contact%is2(n) = Contact%is2(n-1); Contact%ie2(n) = Contact%ie2(n-1)
5917 Contact%js2(n) = Contact%js2(n-1); Contact%je2(n) = Contact%je2(n-1)
5920 Contact%tile(pos) = tile
5921 Contact%align1(pos) = align1
5922 Contact%align2(pos) = align2
5923 Contact%refine1(pos) = refine1
5924 Contact%refine2(pos) = refine2
5925 Contact%is1(pos) = is1; Contact%ie1(pos) = ie1
5926 Contact%js1(pos) = js1; Contact%je1(pos) = je1
5927 Contact%is2(pos) = is2; Contact%ie2(pos) = ie2
5928 Contact%js2(pos) = js2; Contact%je2(pos) = je2
5930 end subroutine fill_contact
5932 !############################################################################
5933 ! this routine sets the overlapping between tiles for E,C,N-cell based on T-cell overlapping
5934 subroutine set_contact_point(domain, position)
5935 type(domain2d), intent(inout) :: domain
5936 integer, intent(in) :: position
5938 integer :: ishift, jshift, nlist, list, m, n
5939 integer :: ntileMe, tMe, dir, count, pos, nsend, nrecv
5940 integer :: isoff1, ieoff1, jsoff1, jeoff1
5941 type(overlap_type), pointer :: ptrIn => NULL()
5942 type(overlapSpec), pointer :: update_in => NULL()
5943 type(overlapSpec), pointer :: update_out => NULL()
5944 type(overlap_type) :: overlapList(0:size(domain%list(:))-1)
5945 type(overlap_type) :: overlap
5947 call mpp_get_domain_shift(domain, ishift, jshift, position)
5948 update_in => domain%update_T
5949 select case(position)
5951 update_out => domain%update_C
5953 update_out => domain%update_E
5955 update_out => domain%update_N
5957 call mpp_error(FATAL, "mpp_domains_define.inc(set_contact_point): the position should be CORNER, EAST or NORTH")
5960 update_out%xbegin = update_in%xbegin; update_out%xend = update_in%xend + ishift
5961 update_out%ybegin = update_in%ybegin; update_out%yend = update_in%yend + jshift
5962 update_out%whalo = update_in%whalo; update_out%ehalo = update_in%ehalo
5963 update_out%shalo = update_in%shalo; update_out%nhalo = update_in%nhalo
5965 nlist = size(domain%list(:))
5966 ntileMe = size(domain%x(:))
5967 call allocate_update_overlap(overlap, MAXOVERLAP)
5969 call init_overlap_type(overlapList(m))
5972 !--- first copy the send information in update_out to send
5973 nsend = update_out%nsend
5975 pos = update_out%send(m)%pe - mpp_root_pe()
5976 call add_update_overlap(overlapList(pos), update_out%send(m))
5977 call deallocate_overlap_type(update_out%send(m))
5979 if(ASSOCIATED(update_out%send) )deallocate(update_out%send)
5981 !--- loop over the list of overlapping.
5982 nsend = update_in%nsend
5984 ptrIn => update_in%send(m)
5985 pos = PtrIn%pe - mpp_root_pe()
5986 do n = 1, ptrIn%count
5988 ! only set overlapping between tiles for send ( ptrOut%overlap(1) is false )
5989 if(ptrIn%from_contact(n)) then
5991 case ( 1 ) ! to_pe's eastern halo
5992 select case(ptrIn%rotation(n))
5993 case (ZERO) ! W -> E
5994 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
5995 case (NINETY) ! S -> E
5996 isoff1 = 0; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
5998 case ( 2 ) ! to_pe's south-eastearn halo
5999 select case(ptrIn%rotation(n))
6001 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6003 isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6005 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6007 case ( 3 ) ! to_pe's southern halo
6008 select case(ptrIn%rotation(n))
6009 case (ZERO) ! N -> S
6010 isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6011 case (MiNUS_NINETY) ! E -> S
6012 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = ishift
6014 case ( 4 ) ! to_pe's south-westearn halo
6015 select case(ptrIn%rotation(n))
6017 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6019 isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6021 isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6023 case ( 5 ) ! to_pe's western halo
6024 select case(ptrIn%rotation(n))
6025 case (ZERO) ! E -> W
6026 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6027 case (NINETY) ! N -> W
6028 isoff1 = 0; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6030 case ( 6 ) ! to_pe's north-westearn halo
6031 select case(ptrIn%rotation(n))
6033 isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6035 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6037 isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6039 case ( 7 ) ! to_pe's northern halo
6040 select case(ptrIn%rotation(n))
6041 case (ZERO) ! S -> N
6042 isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6043 case (MINUS_NINETY) ! W -> N
6044 isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = ishift
6046 case ( 8 ) ! to_pe's north-eastearn halo
6047 select case(ptrIn%rotation(n))
6049 isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6051 isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6053 isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6056 call insert_overlap_type(overlap, PtrIn%pe, PtrIn%tileMe(n), PtrIn%tileNbr(n), &
6057 Ptrin%is(n) + isoff1, Ptrin%ie(n) + ieoff1, Ptrin%js(n) + jsoff1, &
6058 Ptrin%je(n) + jeoff1, PtrIn%dir(n), PtrIn%rotation(n), PtrIn%from_contact(n))
6060 end do ! do n = 1, prtIn%count
6061 if(overlap%count > 0) then
6062 call add_update_overlap(overlapList(pos), overlap)
6063 call init_overlap_type(overlap)
6065 end do ! do list = 0, nlist-1
6068 do list = 0, nlist-1
6069 m = mod( domain%pos+list, nlist )
6070 if(overlapList(m)%count>0) nsend = nsend+1
6073 update_out%nsend = nsend
6075 allocate(update_out%send(nsend))
6077 do list = 0, nlist-1
6078 m = mod( domain%pos+list, nlist )
6079 if(overlapList(m)%count>0) then
6081 if(pos>nsend) call mpp_error(FATAL, &
6082 "mpp_domains_define.inc(set_contact_point): pos should be no larger than nsend")
6083 call add_update_overlap(update_out%send(pos), overlapList(m))
6084 call deallocate_overlap_type(overlapList(m))
6087 if(pos .NE. nsend) call mpp_error(FATAL, &
6088 "mpp_domains_define.inc(set_contact_point): pos should equal to nsend")
6093 !--- first copy the recv information in update_out to recv
6094 nrecv = update_out%nrecv
6096 pos = update_out%recv(m)%pe - mpp_root_pe()
6097 call add_update_overlap(overlapList(pos), update_out%recv(m))
6098 call deallocate_overlap_type(update_out%recv(m))
6100 if(ASSOCIATED(update_out%recv) )deallocate(update_out%recv)
6102 !--- loop over the list of overlapping.
6103 nrecv = update_in%nrecv
6105 ptrIn => update_in%recv(m)
6106 pos = PtrIn%pe - mpp_root_pe()
6107 do n = 1, ptrIn%count
6109 ! only set overlapping between tiles for recv ( ptrOut%overlap(1) is false )
6110 if(ptrIn%from_contact(n)) then
6113 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6115 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6117 isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6119 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6121 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6123 isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6125 isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6127 isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6129 call insert_overlap_type(overlap, PtrIn%pe, PtrIn%tileMe(n), PtrIn%tileNbr(n), &
6130 Ptrin%is(n) + isoff1, Ptrin%ie(n) + ieoff1, Ptrin%js(n) + jsoff1, &
6131 Ptrin%je(n) + jeoff1, PtrIn%dir(n), PtrIn%rotation(n), PtrIn%from_contact(n))
6132 count = overlap%count
6134 end do ! do n = 1, ptrIn%count
6135 if(overlap%count > 0) then
6136 call add_update_overlap(overlapList(pos), overlap)
6137 call init_overlap_type(overlap)
6139 do tMe = 1, size(domain%x(:))
6140 do n = 1, overlap%count
6141 if(overlap%tileMe(n) == tMe) then
6142 if(overlap%dir(n) == 1 ) domain%x(tMe)%loffset = 0
6143 if(overlap%dir(n) == 7 ) domain%y(tMe)%loffset = 0
6147 end do ! do list = 0, nlist-1
6150 do list = 0, nlist-1
6151 m = mod( domain%pos+nlist-list, nlist )
6152 if(overlapList(m)%count>0) nrecv = nrecv+1
6155 update_out%nrecv = nrecv
6157 allocate(update_out%recv(nrecv))
6159 do list = 0, nlist-1
6160 m = mod( domain%pos+nlist-list, nlist )
6161 if(overlapList(m)%count>0) then
6163 if(pos>nrecv) call mpp_error(FATAL, &
6164 "mpp_domains_define.inc(set_contact_point): pos should be no larger than nrecv")
6165 call add_update_overlap(update_out%recv(pos), overlapList(m))
6166 call deallocate_overlap_type(overlapList(m))
6169 if(pos .NE. nrecv) call mpp_error(FATAL, &
6170 "mpp_domains_define.inc(set_contact_point): pos should equal to nrecv")
6173 call deallocate_overlap_type(overlap)
6175 end subroutine set_contact_point
6177 !--- set up the overlapping for boundary check if the domain is symmetry. The check will be
6178 !--- done on current pe for east boundary for E-cell, north boundary for N-cell,
6179 !--- East and North boundary for C-cell
6180 subroutine set_check_overlap( domain, position )
6181 type(domain2d), intent(in) :: domain
6182 integer, intent(in) :: position
6183 integer :: nlist, m, n
6184 integer, parameter :: MAXCOUNT = 100
6185 integer :: is, ie, js, je
6186 integer :: nsend, nrecv, pos, maxsize, rotation
6187 type(overlap_type) :: overlap
6188 type(overlapSpec), pointer :: update => NULL()
6189 type(overlapSpec), pointer :: check => NULL()
6191 select case(position)
6193 update => domain%update_C
6194 check => domain%check_C
6196 update => domain%update_E
6197 check => domain%check_E
6199 update => domain%update_N
6200 check => domain%check_N
6202 call mpp_error(FATAL, "mpp_domains_define.inc(set_check_overlap): position should be CORNER, EAST or NORTH")
6205 check%xbegin = update%xbegin; check%xend = update%xend
6206 check%ybegin = update%ybegin; check%yend = update%yend
6209 if( .NOT. domain%symmetry ) return
6213 do m = 1, update%nsend
6214 do n = 1, update%send(m)%count
6215 if( update%send(m)%rotation(n) == ONE_HUNDRED_EIGHTY ) cycle
6216 if( ( (position == EAST .OR. position == CORNER) .AND. update%send(m)%dir(n) == 1 ) .OR. &
6217 ( (position == NORTH .OR. position == CORNER) .AND. update%send(m)%dir(n) == 7 ) ) then
6218 maxsize = max(maxsize, update%send(m)%count)
6226 allocate(check%send(nsend))
6227 call allocate_check_overlap(overlap, maxsize)
6231 nlist = size(domain%list(:))
6232 !--- loop over the list of domains to find the boundary overlap for send
6234 do m = 1, update%nsend
6235 do n = 1, update%send(m)%count
6236 if( update%send(m)%rotation(n) == ONE_HUNDRED_EIGHTY ) cycle
6237 ! comparing east direction on currently pe
6238 if( (position == EAST .OR. position == CORNER) .AND. update%send(m)%dir(n) == 1 ) then
6239 rotation = update%send(m)%rotation(n)
6240 select case( rotation )
6241 case( ZERO ) ! W -> E
6242 is = update%send(m)%is(n) - 1
6244 js = update%send(m)%js(n)
6245 je = update%send(m)%je(n)
6246 case( NINETY ) ! S -> E
6247 is = update%send(m)%is(n)
6248 ie = update%send(m)%ie(n)
6249 js = update%send(m)%js(n) - 1
6252 call insert_check_overlap(overlap, update%send(m)%pe, &
6253 update%send(m)%tileMe(n), 1, rotation, is, ie, js, je)
6256 ! comparing north direction on currently pe
6257 if( (position == NORTH .OR. position == CORNER) .AND. update%send(m)%dir(n) == 7 ) then
6258 rotation = update%send(m)%rotation(n)
6259 select case( rotation )
6261 is = update%send(m)%is(n)
6262 ie = update%send(m)%ie(n)
6263 js = update%send(m)%js(n) - 1
6265 case( MINUS_NINETY ) ! W->N
6266 is = update%send(m)%is(n) - 1
6268 js = update%send(m)%js(n)
6269 je = update%send(m)%je(n)
6271 call insert_check_overlap(overlap, update%send(m)%pe, &
6272 update%send(m)%tileMe(n), 4, rotation, is, ie, js, je)
6274 end do ! do n =1, update%send(m)%count
6275 if(overlap%count>0) then
6277 if(pos>nsend)call mpp_error(FATAL, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6278 call add_check_overlap(check%send(pos), overlap)
6279 call init_overlap_type(overlap)
6281 end do ! end do list = 0, nlist
6283 if(pos .NE. nsend)call mpp_error(FATAL, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6287 do m = 1, update%nrecv
6288 do n = 1, update%recv(m)%count
6289 if( update%recv(m)%rotation(n) == ONE_HUNDRED_EIGHTY ) cycle
6290 if( ( (position == EAST .OR. position == CORNER) .AND. update%recv(m)%dir(n) == 1 ) .OR. &
6291 ( (position == NORTH .OR. position == CORNER) .AND. update%recv(m)%dir(n) == 7 ) ) then
6292 maxsize = max(maxsize, update%recv(m)%count)
6299 if(nsend>0) call deallocate_overlap_type(overlap)
6302 allocate(check%recv(nrecv))
6303 call allocate_check_overlap(overlap, maxsize)
6307 do m = 1, update%nrecv
6308 do n = 1, update%recv(m)%count
6309 if( update%recv(m)%rotation(n) == ONE_HUNDRED_EIGHTY ) cycle
6310 if( (position == EAST .OR. position == CORNER) .AND. update%recv(m)%dir(n) == 1 ) then
6311 is = update%recv(m)%is(n) - 1
6313 js = update%recv(m)%js(n)
6314 je = update%recv(m)%je(n)
6315 call insert_check_overlap(overlap, update%recv(m)%pe, &
6316 update%recv(m)%tileMe(n), 1, update%recv(m)%rotation(n), is, ie, js, je)
6318 if( (position == NORTH .OR. position == CORNER) .AND. update%recv(m)%dir(n) == 7 ) then
6319 is = update%recv(m)%is(n)
6320 ie = update%recv(m)%ie(n)
6321 js = update%recv(m)%js(n) - 1
6323 call insert_check_overlap(overlap, update%recv(m)%pe, &
6324 update%recv(m)%tileMe(n), 3, update%recv(m)%rotation(n), is, ie, js, je)
6326 end do ! n = 1, overlap%count
6327 if(overlap%count>0) then
6329 if(pos>nrecv)call mpp_error(FATAL, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6330 call add_check_overlap(check%recv(pos), overlap)
6331 call init_overlap_type(overlap)
6333 end do ! end do list = 0, nlist
6335 if(pos .NE. nrecv)call mpp_error(FATAL, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6336 if(nrecv>0) call deallocate_overlap_type(overlap)
6338 end subroutine set_check_overlap
6340 !#############################################################################
6341 !--- set up the overlapping for boundary if the domain is symmetry.
6342 subroutine set_bound_overlap( domain, position )
6343 type(domain2d), intent(inout) :: domain
6344 integer, intent(in) :: position
6345 integer :: m, n, l, count, dr, tMe
6346 integer, parameter :: MAXCOUNT = 100
6347 integer, dimension(MAXCOUNT) :: dir, rotation, is, ie, js, je, tileMe, index
6348 integer, dimension(size(domain%x(:)), 4) :: nrecvl
6349 integer, dimension(size(domain%x(:)), 4, MAXCOUNT) :: isl, iel, jsl, jel
6350 type(overlap_type), pointer :: overlap => NULL()
6351 type(overlapSpec), pointer :: update => NULL()
6352 type(overlapSpec), pointer :: bound => NULL()
6353 integer :: nlist_send, nlist_recv, ishift, jshift
6354 integer :: ism, iem, jsm, jem, nsend, nrecv
6355 integer :: isg, ieg, jsg, jeg, nlist, list
6356 integer :: npes_x, npes_y, ipos, jpos, inbr, jnbr
6357 integer :: isc, iec, jsc, jec, my_pe
6358 integer :: pe_south1, pe_south2, pe_west0, pe_west1, pe_west2
6359 integer :: is_south1, ie_south1, js_south1, je_south1
6360 integer :: is_south2, ie_south2, js_south2, je_south2
6361 integer :: is_west0, ie_west0, js_west0, je_west0
6362 integer :: is_west1, ie_west1, js_west1, je_west1
6363 integer :: is_west2, ie_west2, js_west2, je_west2
6364 logical :: x_cyclic, y_cyclic, folded_north
6366 is_south1=0; ie_south1=0; js_south1=0; je_south1=0
6367 is_south2=0; ie_south2=0; js_south2=0; je_south2=0
6368 is_west0=0; ie_west0=0; js_west0=0; je_west0=0
6369 is_west1=0; ie_west1=0; js_west1=0; je_west1=0
6370 is_west2=0; ie_west2=0; js_west2=0; je_west2=0
6373 if( position == CENTER .OR. .NOT. domain%symmetry ) return
6374 call mpp_get_domain_shift(domain, ishift, jshift, position)
6375 call mpp_get_global_domain(domain, isg, ieg, jsg, jeg)
6376 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem )
6378 select case(position)
6380 update => domain%update_C
6381 bound => domain%bound_C
6383 update => domain%update_E
6384 bound => domain%bound_E
6386 update => domain%update_N
6387 bound => domain%bound_N
6389 call mpp_error( FATAL, "mpp_domains_mod(set_bound_overlap): invalid option of position")
6392 bound%xbegin = ism; bound%xend = iem + ishift
6393 bound%ybegin = jsm; bound%yend = jem + jshift
6395 nlist_send = max(update%nsend,4)
6396 nlist_recv = max(update%nrecv,4)
6397 bound%nsend = nlist_send
6398 bound%nrecv = nlist_recv
6399 if(nlist_send >0) then
6400 allocate(bound%send(nlist_send))
6401 bound%send(:)%count = 0
6403 if(nlist_recv >0) then
6404 allocate(bound%recv(nlist_recv))
6405 bound%recv(:)%count = 0
6407 !--- loop over the list of domains to find the boundary overlap for send
6408 nlist = size(domain%list(:))
6410 npes_x = size(domain%x(1)%list(:))
6411 npes_y = size(domain%y(1)%list(:))
6412 x_cyclic = domain%x(1)%cyclic
6413 y_cyclic = domain%y(1)%cyclic
6414 folded_north = BTEST(domain%fold,NORTH)
6415 ipos = domain%x(1)%pos
6416 jpos = domain%y(1)%pos
6417 isc = domain%x(1)%compute%begin; iec = domain%x(1)%compute%end
6418 jsc = domain%y(1)%compute%begin; jec = domain%y(1)%compute%end
6421 if(domain%ntiles == 1) then ! use neighbor processor to configure send and recv
6422 ! currently only set up for west and south boundary
6424 ! south boundary for send
6425 pe_south1 = NULL_PE; pe_south2 = NULL_PE
6426 if( position == NORTH .OR. position == CORNER ) then
6427 inbr = ipos; jnbr = jpos + 1
6428 if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6429 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6430 pe_south1 = domain%pearray(inbr,jnbr)
6431 is_south1 = isc + ishift; ie_south1 = iec+ishift
6432 js_south1 = jec + jshift; je_south1 = js_south1
6435 !--- send to the southwest processor when position is NORTH
6436 if( position == CORNER ) then
6437 inbr = ipos + 1; jnbr = jpos + 1
6438 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6439 if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6440 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6441 pe_south2 = domain%pearray(inbr,jnbr)
6442 is_south2 = iec + ishift; ie_south2 = is_south2
6443 js_south2 = jec + jshift; je_south2 = js_south2
6447 !---west boundary for send
6448 pe_west0 = NULL_PE; pe_west1 = NULL_PE; pe_west2 = NULL_PE
6449 if( position == EAST ) then
6450 inbr = ipos+1; jnbr = jpos
6451 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6452 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6453 pe_west1 = domain%pearray(inbr,jnbr)
6454 is_west1 = iec + ishift; ie_west1 = is_west1
6455 js_west1 = jsc + jshift; je_west1 = jec + jshift
6457 else if ( position == CORNER ) then ! possible split into two parts.
6459 if( folded_north .AND. jec == jeg .AND. ipos .LT. (npes_x-1)/2 ) then
6460 inbr = npes_x - ipos - 1; jnbr = jpos
6461 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6462 pe_west0 = domain%pearray(inbr,jnbr)
6463 is_west0 = iec+ishift; ie_west0 = is_west0
6464 js_west0 = jec+jshift; je_west0 = js_west0
6468 if( folded_north .AND. jec == jeg .AND. ipos .GE. npes_x/2 .AND. ipos .LT. (npes_x-1) ) then
6469 inbr = ipos+1; jnbr = jpos
6470 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6471 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6472 pe_west1 = domain%pearray(inbr,jnbr)
6473 is_west1 = iec + ishift; ie_west1 = is_west1
6474 js_west1 = jsc + jshift; je_west1 = jec
6477 inbr = ipos+1; jnbr = jpos
6478 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6479 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6480 pe_west1 = domain%pearray(inbr,jnbr)
6481 is_west1 = iec + ishift; ie_west1 = is_west1
6482 js_west1 = jsc + jshift; je_west1 = jec + jshift
6486 !--- send to the southwest processor when position is NORTH
6487 if( position == CORNER ) then
6488 inbr = ipos + 1; jnbr = jpos + 1
6489 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6490 if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6491 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6492 pe_west2 = domain%pearray(inbr,jnbr)
6493 is_west2 = iec + ishift; ie_west2 = is_west2
6494 js_west2 = jec + jshift; je_west2 = js_west2
6499 m = mod( domain%pos+list, nlist )
6501 my_pe = domain%list(m)%pe
6502 if(my_pe == pe_south1) then
6504 is(count) = is_south1; ie(count) = ie_south1
6505 js(count) = js_south1; je(count) = je_south1
6507 rotation(count) = ZERO
6509 if(my_pe == pe_south2) then
6511 is(count) = is_south2; ie(count) = ie_south2
6512 js(count) = js_south2; je(count) = je_south2
6514 rotation(count) = ZERO
6517 if(my_pe == pe_west0) then
6519 is(count) = is_west0; ie(count) = ie_west0
6520 js(count) = js_west0; je(count) = je_west0
6522 rotation(count) = ONE_HUNDRED_EIGHTY
6524 if(my_pe == pe_west1) then
6526 is(count) = is_west1; ie(count) = ie_west1
6527 js(count) = js_west1; je(count) = je_west1
6529 rotation(count) = ZERO
6531 if(my_pe == pe_west2) then
6533 is(count) = is_west2; ie(count) = ie_west2
6534 js(count) = js_west2; je(count) = je_west2
6536 rotation(count) = ZERO
6541 if(nsend > nlist_send) call mpp_error(FATAL, "set_bound_overlap: nsend > nlist_send")
6542 bound%send(nsend)%count = count
6543 bound%send(nsend)%pe = my_pe
6544 allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6545 allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6546 allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6547 allocate(bound%send(nsend)%tileMe(count))
6548 bound%send(nsend)%is(:) = is(1:count)
6549 bound%send(nsend)%ie(:) = ie(1:count)
6550 bound%send(nsend)%js(:) = js(1:count)
6551 bound%send(nsend)%je(:) = je(1:count)
6552 bound%send(nsend)%dir(:) = dir(1:count)
6553 bound%send(nsend)%tileMe(:) = 1
6554 bound%send(nsend)%rotation(:) = rotation(1:count)
6558 !--- The following did not consider wide halo case.
6559 do m = 1, update%nsend
6560 overlap => update%send(m)
6561 if( overlap%count == 0 ) cycle
6563 do n = 1, overlap%count
6564 !--- currently not support folded-north
6565 if( overlap%rotation(n) == ONE_HUNDRED_EIGHTY ) cycle
6566 if( (position == EAST .OR. position == CORNER) .AND. overlap%dir(n) == 1) then ! east
6569 rotation(count) = overlap%rotation(n)
6570 tileMe(count) = overlap%tileMe(n)
6571 select case( rotation(count) )
6572 case( ZERO ) ! W -> E
6573 is(count) = overlap%is(n) - 1
6574 ie(count) = is(count)
6575 js(count) = overlap%js(n)
6576 je(count) = overlap%je(n)
6577 case( NINETY ) ! S -> E
6578 is(count) = overlap%is(n)
6579 ie(count) = overlap%ie(n)
6580 js(count) = overlap%js(n) - 1
6581 je(count) = js(count)
6584 if( (position == NORTH .OR. position == CORNER) .AND. overlap%dir(n) == 3 ) then ! south
6587 rotation(count) = overlap%rotation(n)
6588 tileMe(count) = overlap%tileMe(n)
6589 select case( rotation(count) )
6591 is(count) = overlap%is(n)
6592 ie(count) = overlap%ie(n)
6593 js(count) = overlap%je(n) + 1
6594 je(count) = js(count)
6595 case( MINUS_NINETY ) ! E->S
6596 is(count) = overlap%ie(n) + 1
6597 ie(count) = is(count)
6598 js(count) = overlap%js(n)
6599 je(count) = overlap%je(n)
6602 if( (position == EAST .OR. position == CORNER) .AND. overlap%dir(n) == 5 ) then ! west
6605 rotation(count) = overlap%rotation(n)
6606 tileMe(count) = overlap%tileMe(n)
6607 select case( rotation(count) )
6609 is(count) = overlap%ie(n) + 1
6610 ie(count) = is(count)
6611 js(count) = overlap%js(n)
6612 je(count) = overlap%je(n)
6613 case( NINETY ) ! N->W
6614 is(count) = overlap%is(n)
6615 ie(count) = overlap%ie(n)
6616 js(count) = overlap%je(n) + 1
6617 je(count) = js(count)
6620 if( (position == NORTH .OR. position == CORNER) .AND. overlap%dir(n) == 7 ) then ! north
6623 rotation(count) = overlap%rotation(n)
6624 tileMe(count) = overlap%tileMe(n)
6625 select case( rotation(count) )
6627 is(count) = overlap%is(n)
6628 ie(count) = overlap%ie(n)
6629 js(count) = overlap%js(n) - 1
6630 je(count) = js(count)
6631 case( MINUS_NINETY ) ! W->N
6632 is(count) = overlap%is(n) - 1
6633 ie(count) = is(count)
6634 js(count) = overlap%js(n)
6635 je(count) = overlap%je(n)
6638 end do ! do n =1, overlap%count
6641 bound%send(nsend)%count = count
6642 bound%send(nsend)%pe = overlap%pe
6643 allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6644 allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6645 allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6646 allocate(bound%send(nsend)%tileMe(count))
6647 bound%send(nsend)%is(:) = is(1:count)
6648 bound%send(nsend)%ie(:) = ie(1:count)
6649 bound%send(nsend)%js(:) = js(1:count)
6650 bound%send(nsend)%je(:) = je(1:count)
6651 bound%send(nsend)%dir(:) = dir(1:count)
6652 bound%send(nsend)%tileMe(:) = tileMe(1:count)
6653 bound%send(nsend)%rotation(:) = rotation(1:count)
6655 end do ! end do list = 0, nlist
6658 !--- loop over the list of domains to find the boundary overlap for recv
6663 !--- will computing overlap for tripolar grid.
6664 if( domain%ntiles == 1 ) then
6665 ! currently only set up for west and south boundary
6667 ! south boundary for recv
6668 pe_south1 = NULL_PE; pe_south2 = NULL_PE
6669 if( position == NORTH .OR. position == CORNER ) then
6670 inbr = ipos; jnbr = jpos - 1
6671 if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6672 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6673 pe_south1 = domain%pearray(inbr,jnbr)
6674 is_south1 = isc + ishift; ie_south1 = iec+ishift
6675 js_south1 = jsc; je_south1 = js_south1
6679 !--- south boudary for recv: the southwest point when position is NORTH
6680 if( position == CORNER ) then
6681 inbr = ipos - 1; jnbr = jpos - 1
6682 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6683 if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6684 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6685 pe_south2 = domain%pearray(inbr,jnbr)
6686 is_south2 = isc; ie_south2 = is_south2
6687 js_south2 = jsc; je_south2 = js_south2
6692 !---west boundary for recv
6693 pe_west0 = NULL_PE; pe_west1 = NULL_PE; pe_west2 = NULL_PE
6694 if( position == EAST ) then
6695 inbr = ipos-1; jnbr = jpos
6696 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6697 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6698 pe_west1 = domain%pearray(inbr,jnbr)
6699 is_west1 = isc; ie_west1 = is_west1
6700 js_west1 = jsc + jshift; je_west1 = jec + jshift
6702 else if ( position == CORNER ) then ! possible split into two parts.
6704 if( folded_north .AND. jec == jeg .AND. ipos .GT. npes_x/2 ) then
6705 inbr = npes_x - ipos - 1; jnbr = jpos
6706 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6707 pe_west0 = domain%pearray(inbr,jnbr)
6708 is_west0 = isc; ie_west0 = is_west0
6709 js_west0 = jec+jshift; je_west0 = js_west0
6711 inbr = ipos-1; jnbr = jpos
6712 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6713 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6714 pe_west1 = domain%pearray(inbr,jnbr)
6715 is_west1 = isc; ie_west1 = is_west1
6716 js_west1 = jsc + jshift; je_west1 = jec
6719 inbr = ipos-1; jnbr = jpos
6720 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6721 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6722 pe_west1 = domain%pearray(inbr,jnbr)
6723 is_west1 = isc; ie_west1 = is_west1
6724 js_west1 = jsc + jshift; je_west1 = jec+jshift
6729 !--- west boundary for recv: the southwest point when position is CORNER
6730 if( position == CORNER ) then
6731 inbr = ipos - 1; jnbr = jpos - 1
6732 if( inbr == -1 .AND. x_cyclic) inbr = npes_x - 1
6733 if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y - 1
6734 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6735 pe_west2 = domain%pearray(inbr,jnbr)
6736 is_west2 = isc; ie_west2 = is_west2
6737 js_west2 = jsc; je_west2 = js_west2
6743 m = mod( domain%pos+nlist-list, nlist )
6745 my_pe = domain%list(m)%pe
6746 if(my_pe == pe_south1) then
6748 is(count) = is_south1; ie(count) = ie_south1
6749 js(count) = js_south1; je(count) = je_south1
6751 rotation(count) = ZERO
6752 index(count) = 1 + ishift
6754 if(my_pe == pe_south2) then
6756 is(count) = is_south2; ie(count) = ie_south2
6757 js(count) = js_south2; je(count) = je_south2
6759 rotation(count) = ZERO
6762 if(my_pe == pe_west0) then
6764 is(count) = is_west0; ie(count) = ie_west0
6765 js(count) = js_west0; je(count) = je_west0
6767 rotation(count) = ONE_HUNDRED_EIGHTY
6768 index(count) = jec-jsc+1+jshift
6770 if(my_pe == pe_west1) then
6772 is(count) = is_west1; ie(count) = ie_west1
6773 js(count) = js_west1; je(count) = je_west1
6775 rotation(count) = ZERO
6776 index(count) = 1 + jshift
6778 if(my_pe == pe_west2) then
6780 is(count) = is_west2; ie(count) = ie_west2
6781 js(count) = js_west2; je(count) = je_west2
6783 rotation(count) = ZERO
6789 if(nrecv > nlist_recv) call mpp_error(FATAL, "set_bound_overlap: nrecv > nlist_recv")
6790 bound%recv(nrecv)%count = count
6791 bound%recv(nrecv)%pe = my_pe
6792 allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6793 allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6794 allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6795 allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6797 bound%recv(nrecv)%is(:) = is(1:count)
6798 bound%recv(nrecv)%ie(:) = ie(1:count)
6799 bound%recv(nrecv)%js(:) = js(1:count)
6800 bound%recv(nrecv)%je(:) = je(1:count)
6801 bound%recv(nrecv)%dir(:) = dir(1:count)
6802 bound%recv(nrecv)%tileMe(:) = 1
6803 bound%recv(nrecv)%rotation(:) = rotation(1:count)
6804 bound%recv(nrecv)%index(:) = index(1:count)
6808 do m = 1, update%nrecv
6809 overlap => update%recv(m)
6810 if( overlap%count == 0 ) cycle
6812 do n = 1, overlap%count
6813 !--- currently not support folded-north
6814 if( overlap%rotation(n) == ONE_HUNDRED_EIGHTY ) cycle
6815 if( (position == EAST .OR. position == CORNER) .AND. overlap%dir(n) == 1) then ! east
6818 rotation(count) = overlap%rotation(n)
6819 tileMe(count) = overlap%tileMe(n)
6820 is(count) = overlap%is(n) - 1
6821 ie(count) = is(count)
6822 js(count) = overlap%js(n)
6823 je(count) = overlap%je(n)
6825 nrecvl(tMe, 1) = nrecvl(tMe,1) + 1
6826 isl (tMe,1,nrecvl(tMe, 1)) = is (count)
6827 iel (tMe,1,nrecvl(tMe, 1)) = ie (count)
6828 jsl (tMe,1,nrecvl(tMe, 1)) = js (count)
6829 jel (tMe,1,nrecvl(tMe, 1)) = je (count)
6832 if( (position == NORTH .OR. position == CORNER) .AND. overlap%dir(n) == 3) then ! south
6835 rotation(count) = overlap%rotation(n)
6836 tileMe(count) = overlap%tileMe(n)
6837 is(count) = overlap%is(n)
6838 ie(count) = overlap%ie(n)
6839 js(count) = overlap%je(n) + 1
6840 je(count) = js(count)
6842 nrecvl(tMe, 2) = nrecvl(tMe,2) + 1
6843 isl (tMe,2,nrecvl(tMe, 2)) = is (count)
6844 iel (tMe,2,nrecvl(tMe, 2)) = ie (count)
6845 jsl (tMe,2,nrecvl(tMe, 2)) = js (count)
6846 jel (tMe,2,nrecvl(tMe, 2)) = je (count)
6849 if( (position == EAST .OR. position == CORNER) .AND. overlap%dir(n) == 5) then ! west
6852 rotation(count) = overlap%rotation(n)
6853 tileMe(count) = overlap%tileMe(n)
6854 is(count) = overlap%ie(n) + 1
6855 ie(count) = is(count)
6856 js(count) = overlap%js(n)
6857 je(count) = overlap%je(n)
6859 nrecvl(tMe, 3) = nrecvl(tMe,3) + 1
6860 isl (tMe,3,nrecvl(tMe, 3)) = is (count)
6861 iel (tMe,3,nrecvl(tMe, 3)) = ie (count)
6862 jsl (tMe,3,nrecvl(tMe, 3)) = js (count)
6863 jel (tMe,3,nrecvl(tMe, 3)) = je (count)
6866 if( (position == NORTH .OR. position == CORNER) .AND. overlap%dir(n) == 7) then ! north
6869 rotation(count) = overlap%rotation(n)
6870 tileMe(count) = overlap%tileMe(n)
6871 is(count) = overlap%is(n)
6872 ie(count) = overlap%ie(n)
6873 js(count) = overlap%js(n) - 1
6874 je(count) = js(count)
6876 nrecvl(tMe, 4) = nrecvl(tMe,4) + 1
6877 isl (tMe,4,nrecvl(tMe, 4)) = is (count)
6878 iel (tMe,4,nrecvl(tMe, 4)) = ie (count)
6879 jsl (tMe,4,nrecvl(tMe, 4)) = js (count)
6880 jel (tMe,4,nrecvl(tMe, 4)) = je (count)
6882 end do ! do n = 1, overlap%count
6885 bound%recv(nrecv)%count = count
6886 bound%recv(nrecv)%pe = overlap%pe
6887 allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6888 allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6889 allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6890 allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6891 bound%recv(nrecv)%is(:) = is(1:count)
6892 bound%recv(nrecv)%ie(:) = ie(1:count)
6893 bound%recv(nrecv)%js(:) = js(1:count)
6894 bound%recv(nrecv)%je(:) = je(1:count)
6895 bound%recv(nrecv)%dir(:) = dir(1:count)
6896 bound%recv(nrecv)%tileMe(:) = tileMe(1:count)
6897 bound%recv(nrecv)%rotation(:) = rotation(1:count)
6899 end do ! end do list = 0, nlist
6900 !--- find the boundary index for each contact within the east boundary
6902 do n = 1, bound%recv(m)%count
6903 tMe = bound%recv(m)%tileMe(n)
6904 dr = bound%recv(m)%dir(n)
6905 bound%recv(m)%index(n) = 1
6906 do l = 1, nrecvl(tMe,dr)
6907 if(dr == 1 .OR. dr == 3) then ! EAST, WEST
6908 if( bound%recv(m)%js(n) > jsl(tMe, dr, l) ) then
6909 if( bound%recv(m)%rotation(n) == ONE_HUNDRED_EIGHTY ) then
6910 bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6911 max(abs(jel(tMe, dr, l)-jsl(tMe, dr, l))+1, &
6912 abs(iel(tMe, dr, l)-isl(tMe, dr, l))+1)
6914 bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6915 max(abs(jel(tMe, dr, l)-jsl(tMe, dr, l)), &
6916 abs(iel(tMe, dr, l)-isl(tMe, dr, l))) + 1 - jshift
6920 if( bound%recv(m)%is(n) > isl(tMe, dr, l) ) then
6921 bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6922 max(abs(jel(tMe, dr, l)-jsl(tMe, dr, l)), &
6923 abs(iel(tMe, dr, l)-isl(tMe, dr, l))) + 1 - ishift
6934 end subroutine set_bound_overlap
6937 !#############################################################################
6939 subroutine fill_corner_contact(eCont, sCont, wCont, nCont, isg, ieg, jsg, jeg, numR, numS, tileRecv, tileSend, &
6940 is1Recv, ie1Recv, js1Recv, je1Recv, is2Recv, ie2Recv, js2Recv, je2Recv, &
6941 is1Send, ie1Send, js1Send, je1Send, is2Send, ie2Send, js2Send, je2Send, &
6942 align1Recv, align2Recv, align1Send, align2Send, &
6943 whalo, ehalo, shalo, nhalo, tileMe)
6944 type(contact_type), dimension(:), intent(in) :: eCont, sCont, wCont, nCont
6945 integer, dimension(:), intent(in) :: isg, ieg, jsg, jeg
6946 integer, intent(inout) :: numR, numS
6947 integer, dimension(:), intent(inout) :: tileRecv, tileSend
6948 integer, dimension(:), intent(inout) :: is1Recv, ie1Recv, js1Recv, je1Recv
6949 integer, dimension(:), intent(inout) :: is2Recv, ie2Recv, js2Recv, je2Recv
6950 integer, dimension(:), intent(inout) :: is1Send, ie1Send, js1Send, je1Send
6951 integer, dimension(:), intent(inout) :: is2Send, ie2Send, js2Send, je2Send
6952 integer, dimension(:), intent(inout) :: align1Recv, align2Recv, align1Send, align2Send
6953 integer, intent(in) :: tileMe, whalo, ehalo, shalo, nhalo
6954 integer :: is1, ie1, js1, je1, is2, ie2, js2, je2
6955 integer :: tn, tc, n, m
6956 logical :: found_corner
6958 found_corner = .false.
6959 !--- southeast for recving
6960 if(eCont(tileMe)%ncontact > 0) then
6961 if(eCont(tileMe)%js1(1) == jsg(tileMe) ) then
6962 tn = eCont(tileMe)%tile(1)
6963 if(econt(tileMe)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
6964 if( econt(tileMe)%js2(1) - jsg(tn) < shalo ) call mpp_error(FATAL, &
6965 "mpp_domains_define.inc: southeast tile for recv 1 is not tiled properly")
6966 found_corner = .true.; tc = tn
6967 is1 = eCont(tileMe)%ie1(1) + 1; je1 = eCont(tileMe)%js1(1) - 1
6968 is2 = eCont(tileMe)%is2(1); je2 = eCont(tileMe)%js2(1) - 1
6969 else if(sCont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
6970 if(sCont(tn)%is1(1) == isg(tn)) then ! corner is nc.
6971 found_corner = .true.; tc = sCont(tn)%tile(1)
6972 is1 = eCont(tileMe)%ie1(1) + 1; je1 = eCont(tileMe)%js1(1) - 1
6973 is2 = sCont(tn)%is2(1); je2 = sCont(tn)%je2(1)
6978 if( .not. found_corner ) then ! not found,
6979 n = sCont(tileMe)%ncontact
6981 if( sCont(tileMe)%ie1(n) == ieg(tileMe)) then
6982 tn = sCont(tileMe)%tile(n)
6983 if(scont(tileMe)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
6984 if(ieg(tn) - scont(tileMe)%ie2(n) < ehalo ) call mpp_error(FATAL, &
6985 "mpp_domains_define.inc: southeast tile for recv 2 is not tiled properly")
6986 found_corner = .true.; tc = tn
6987 is1 = sCont(tileMe)%ie1(n) + 1; je1 = sCont(tileMe)%js1(n) - 1
6988 is2 = sCont(tileMe)%ie2(n) + 1; je2 = sCont(tileMe)%je2(n)
6989 else if(eCont(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
6990 m = eCont(tn)%ncontact
6991 if(eCont(tn)%je1(m) == jeg(tn)) then ! corner is nc.
6992 found_corner = .true.; tc = eCont(tn)%tile(m)
6993 is1 = sCont(tileMe)%ie1(n) + 1; je1 = sCont(tileMe)%js1(n) - 1
6994 is2 = eCont(tn)%is2(m); je2 = eCont(tn)%je2(m)
7000 if(found_corner) then
7002 tileRecv(numR) = tc; align1Recv(numR) = SOUTH_EAST; align2Recv(numR) = NORTH_WEST
7003 is1Recv(numR) = is1; ie1Recv(numR) = is1 + ehalo - 1
7004 js1Recv(numR) = je1 - shalo + 1; je1Recv(numR) = je1
7005 is2Recv(numR) = is2; ie2Recv(numR) = is2 + ehalo - 1
7006 js2Recv(numR) = je2 - shalo + 1; je2Recv(numR) = je2
7009 !--- southwest for recving
7010 found_corner = .false.
7011 if(wCont(tileMe)%ncontact > 0) then
7012 if(wCont(tileMe)%js1(1) == jsg(tileMe) ) then
7013 tn = wCont(tileMe)%tile(1)
7014 if(wcont(tileMe)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7015 if( wcont(tileMe)%js2(1) - jsg(tn) < shalo ) call mpp_error(FATAL, &
7016 "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7017 found_corner = .true.; tc = tn
7018 ie1 = wCont(tileMe)%is1(1) - 1; je1 = wCont(tileMe)%js1(1) - 1
7019 ie2 = wCont(tileMe)%is2(1); je2 = wCont(tileMe)%js2(1) - 1
7020 else if(sCont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7021 n = sCont(tn)%ncontact
7022 if(sCont(tn)%ie1(n) == ieg(tn)) then ! corner is nc.
7023 found_corner = .true.; tc = sCont(tn)%tile(n)
7024 ie1 = wCont(tileMe)%is1(1) - 1; je1 = wCont(tileMe)%js1(1) - 1
7025 ie2 = sCont(tn)%ie2(1); je2 = sCont(tn)%je2(1)
7030 if( .not. found_corner ) then ! not found,
7031 n = sCont(tileMe)%ncontact
7033 if( sCont(tileMe)%is1(1) == isg(tileMe)) then
7034 tn = sCont(tileMe)%tile(1)
7035 if(sCont(tileMe)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7036 if( scont(tileMe)%is2(1)-isg(tn) < whalo ) call mpp_error(FATAL, &
7037 "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7038 found_corner = .true.; tc = tn
7039 ie1 = sCont(tileMe)%is1(1) - 1; je1 = sCont(tileMe)%js1(1) - 1
7040 ie2 = sCont(tileMe)%is2(1) - 1; je2 = sCont(tileMe)%js2(1)
7041 else if(wCont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7042 m = wCont(tn)%ncontact
7043 if(wCont(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7044 found_corner = .true.; tc = wCont(tn)%tile(m)
7045 ie1 = sCont(tileMe)%is1(1) - 1; je1 = sCont(tileMe)%js1(1) - 1
7046 ie2 = wCont(tn)%ie2(m); je2 = wCont(tn)%je2(m)
7052 if(found_corner) then
7054 tileRecv(numR) = tc; align1Recv(numR) = SOUTH_WEST; align2Recv(numR) = NORTH_EAST
7055 is1Recv(numR) = ie1 - whalo + 1; ie1Recv(numR) = ie1
7056 js1Recv(numR) = je1 - shalo + 1; je1Recv(numR) = je1
7057 is2Recv(numR) = ie2 - whalo + 1; ie2Recv(numR) = ie2
7058 js2Recv(numR) = je2 - shalo + 1; je2Recv(numR) = je2
7061 !--- northwest for recving
7062 found_corner = .false.
7063 n = wCont(tileMe)%ncontact
7065 if(wCont(tileMe)%je1(n) == jeg(tileMe) ) then
7066 tn = wCont(tileMe)%tile(n)
7067 if(wcont(tileMe)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7068 if( jeg(tn) - wcont(tileMe)%je2(n) < nhalo ) call mpp_error(FATAL, &
7069 "mpp_domains_define.inc: northwest tile for recv 1 is not tiled properly")
7070 found_corner = .true.; tc = tn
7071 ie1 = wCont(tileMe)%is1(n) - 1; js1 = wCont(tileMe)%je1(n) + 1
7072 ie2 = wCont(tileMe)%is2(n); js2 = wCont(tileMe)%je2(n) + 1
7073 else if(nCont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7074 m = nCont(tn)%ncontact
7075 if(nCont(tn)%ie1(m) == ieg(tn)) then ! corner is nc.
7076 found_corner = .true.; tc = nCont(tn)%tile(m)
7077 ie1 = wCont(tileMe)%is1(n) - 1; js1 = wCont(tileMe)%je1(n) + 1
7078 ie2 = nCont(tn)%ie2(m); js2 = nCont(tn)%js2(m)
7083 if( .not. found_corner ) then ! not found,
7084 if( nCont(tileMe)%ncontact > 0) then
7085 if( nCont(tileMe)%is1(1) == isg(tileMe)) then
7086 tn = nCont(tileMe)%tile(1)
7087 if(nCont(tileMe)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7088 if( ncont(tileMe)%is2(1)-isg(tn) < whalo ) call mpp_error(FATAL, &
7089 "mpp_domains_define.inc: northwest tile for recv 2 is not tiled properly")
7090 found_corner = .true.; tc = tn
7091 ie1 = nCont(tileMe)%is1(1) - 1; js1 = nCont(tileMe)%je1(1) + 1
7092 ie2 = nCont(tileMe)%is2(1) - 1; js2 = nCont(tileMe)%js2(1)
7093 else if(wCont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7094 if(wCont(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7095 found_corner = .true.; tc = wCont(tn)%tile(1)
7096 ie1 = nCont(tileMe)%is1(1) - 1; js1 = nCont(tileMe)%je1(1) + 1
7097 ie2 = wCont(tn)%ie2(1); js2 = wCont(tn)%js2(1)
7103 if(found_corner) then
7105 tileRecv(numR) = tc; align1Recv(numR) =NORTH_WEST; align2Recv(numR) = SOUTH_EAST
7106 is1Recv(numR) = ie1 - whalo + 1; ie1Recv(numR) = ie1
7107 js1Recv(numR) = js1; je1Recv(numR) = js1 + nhalo - 1
7108 is2Recv(numR) = ie2 - whalo + 1; ie2Recv(numR) = ie2
7109 js2Recv(numR) = js2; je2Recv(numR) = js2 + nhalo - 1
7112 !--- northeast for recving
7113 found_corner = .false.
7114 n = eCont(tileMe)%ncontact
7116 if(eCont(tileMe)%je1(n) == jeg(tileMe) ) then
7117 tn = eCont(tileMe)%tile(n)
7118 if(econt(tileMe)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7119 if( jeg(tn) - econt(tileMe)%je2(n) < nhalo ) call mpp_error(FATAL, &
7120 "mpp_domains_define.inc: northeast tile for recv 1 is not tiled properly")
7121 found_corner = .true.; tc = tn
7122 is1 = eCont(tileMe)%ie1(n) + 1; js1 = eCont(tileMe)%je1(n) + 1
7123 is2 = eCont(tileMe)%is2(1); js2 = eCont(tileMe)%je2(1) + 1
7124 else if(nCont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7125 if(nCont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7126 found_corner = .true.; tc = nCont(tn)%tile(1)
7127 is1 = eCont(tileMe)%ie1(n) + 1; js1 = eCont(tileMe)%je1(n) + 1
7128 is2 = nCont(tn)%is2(1); js2 = nCont(tn)%js2(1)
7133 if( .not. found_corner ) then ! not found,
7134 n = nCont(tileMe)%ncontact
7136 if( nCont(tileMe)%ie1(n) == ieg(tileMe)) then
7137 tn = nCont(tileMe)%tile(n)
7138 if(nCont(tileMe)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7139 if(ieg(tn) - sCont(tileMe)%ie2(n) < ehalo ) call mpp_error(FATAL, &
7140 "mpp_domains_define.inc: northeast tile for recv 2 is not tiled properly")
7141 found_corner = .true.; tc = tn
7142 is1 = sCont(tileMe)%ie1(n) + 1; js1 = sCont(tileMe)%je1(n) + 1
7143 is2 = sCont(tileMe)%ie2(n) + 1; js2 = sCont(tileMe)%js2(n)
7144 else if(eCont(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7145 if(eCont(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7146 found_corner = .true.; tc = eCont(tn)%tile(1)
7147 is1 = sCont(tileMe)%ie1(n) + 1; js1 = sCont(tileMe)%je1(n) + 1
7148 is2 = eCont(tn)%is2(m); js2 = eCont(tn)%js2(m)
7154 if(found_corner) then
7156 tileRecv(numR) = tc; align1Recv(numR) =NORTH_EAST; align2Recv(numR) = SOUTH_WEST
7157 is1Recv(numR) = is1; ie1Recv(numR) = is1 + ehalo - 1
7158 js1Recv(numR) = js1; je1Recv(numR) = js1 + nhalo - 1
7159 is2Recv(numR) = is2; ie2Recv(numR) = is2 + ehalo - 1
7160 js2Recv(numR) = js2; je2Recv(numR) = js2 + nhalo - 1
7163 !--- to_pe's southeast for sending
7164 do n = 1, wCont(tileMe)%ncontact
7165 tn = wCont(tileMe)%tile(n)
7166 if(wCont(tileMe)%js2(n) == jsg(tn) ) then
7167 if(wcont(tileMe)%js1(n) > jsg(tileMe) ) then ! send to tile tn.
7168 if( wcont(tileMe)%js1(n) - jsg(tileMe) < shalo ) call mpp_error(FATAL, &
7169 "mpp_domains_define.inc: southeast tile for send 1 is not tiled properly")
7170 numS = numS+1; tileSend(numS) = tn
7171 align1Send(numS) = NORTH_WEST; align2Send(numS) = SOUTH_EAST
7172 is1Send(numS) = wCont(tileMe)%is1(n); ie1Send(numS) = is1Send(numS) + ehalo - 1
7173 je1Send(numS) = wCont(tileMe)%js1(n) - 1; js1Send(numS) = je1Send(numS) - shalo + 1
7174 is2Send(numS) = wCont(tileMe)%ie2(n) + 1; ie2Send(numS) = is2Send(numS) + ehalo - 1
7175 je2Send(numS) = wCont(tileMe)%js2(n) - 1; js2Send(numS) = je2Send(numS) - shalo + 1
7179 do n = 1, nCont(tileMe)%ncontact
7180 tn = nCont(tileMe)%tile(n)
7181 if(nCont(tileMe)%ie2(n) == ieg(tn) ) then
7182 if(nCont(tileMe)%ie1(n) < ieg(tileMe) ) then ! send to tile tn.
7183 if( ieg(tileMe) - nCont(tileMe)%ie1(n) < ehalo ) call mpp_error(FATAL, &
7184 "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7185 numS = numS+1; tileSend(numS) = tn
7186 align1Send(numS) = NORTH_WEST; align2Send(numS) = SOUTH_EAST
7187 is1Send(numS) = nCont(tileMe)%ie1(n) + 1; ie1Send(numS) = is1Send(numS) + ehalo - 1
7188 je1Send(numS) = nCont(tileMe)%je1(n) ; js1Send(numS) = je1Send(numS) - shalo + 1
7189 is2Send(numS) = nCont(tileMe)%ie2(n) + 1; ie2Send(numS) = is2Send(numS) + ehalo - 1
7190 je2Send(numS) = nCont(tileMe)%je2(n) - 1; js2Send(numS) = je2Send(numS) - shalo + 1
7195 !--- found the corner overlap that is not specified through contact line.
7196 n = wCont(tileMe)%ncontact
7197 found_corner = .false.
7199 tn = wCont(tileMe)%tile(n)
7200 if( wCont(tileMe)%je1(n) == jeg(tileMe) .AND. wCont(tileMe)%je2(n) == jeg(tn) ) then
7201 m = nCont(tn)%ncontact
7203 tc = nCont(tn)%tile(m)
7204 if( nCont(tn)%ie1(m) == ieg(tn) .AND. nCont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7208 if( .not. found_corner ) then ! not found, then starting from north contact
7209 if( nCont(tileMe)%ncontact > 0) then
7210 tn = nCont(tileMe)%tile(1)
7211 if( nCont(tileMe)%is1(1) == isg(tileMe) .AND. nCont(tileMe)%is2(1) == isg(tn) ) then
7212 if(wCont(tn)%ncontact >0) then
7213 tc = wCont(tn)%tile(1)
7214 if( wCont(tn)%js1(1) == jsg(tn) .AND. wCont(tn)%js2(1) == jsg(tc) ) found_corner = .true.
7220 if(found_corner) then
7221 numS = numS+1; tileSend(numS) = tc
7222 align1Send(numS) = NORTH_WEST; align2Send(numS) = SOUTH_EAST
7223 is1Send(numS) = isg(tileMe); ie1Send(numS) = is1Send(numS) + ehalo - 1
7224 je1Send(numS) = jeg(tileMe); js1Send(numS) = je1Send(numS) - shalo + 1
7225 is2Send(numS) = ieg(tc) + 1; ie2Send(numS) = is2Send(numS) + ehalo - 1
7226 je2Send(numS) = jsg(tc) - 1; js2Send(numS) = je2Send(numS) - shalo + 1
7229 !--- to_pe's southwest for sending
7230 do n = 1, eCont(tileMe)%ncontact
7231 tn = eCont(tileMe)%tile(n)
7232 if(eCont(tileMe)%js2(n) == jsg(tn) ) then
7233 if(econt(tileMe)%js1(n) > jsg(tileMe) ) then ! send to tile tn.
7234 if( econt(tileMe)%js1(n) - jsg(tileMe) < shalo ) call mpp_error(FATAL, &
7235 "mpp_domains_define.inc: southwest tile for send 1 is not tiled properly")
7236 numS = numS+1; tileSend(numS) = tn
7237 align1Send(numS) = NORTH_EAST; align2Send(numS) = SOUTH_WEST
7238 ie1Send(numS) = eCont(tileMe)%ie1(n); is1Send(numS) = ie1Send(numS) - whalo + 1
7239 je1Send(numS) = eCont(tileMe)%js1(n) - 1; js1Send(numS) = je1Send(numS) - shalo + 1
7240 ie2Send(numS) = eCont(tileMe)%is2(n) - 1; is2Send(numS) = ie2Send(numS) - whalo + 1
7241 je2Send(numS) = eCont(tileMe)%js2(n) - 1; js2Send(numS) = je2Send(numS) - shalo + 1
7245 do n = 1, nCont(tileMe)%ncontact
7246 tn = nCont(tileMe)%tile(n)
7247 if(nCont(tileMe)%is2(n) == isg(tn) ) then
7248 if(ncont(tileMe)%is1(n) > isg(tileMe) ) then ! send to tile tn.
7249 if( ncont(tileMe)%is1(n) - isg(tileMe) < whalo ) call mpp_error(FATAL, &
7250 "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7251 numS = numS+1; tileSend(numS) = tn
7252 align1Send(numS) = NORTH_EAST; align2Send(numS) = SOUTH_WEST
7253 ie1Send(numS) = nCont(tileMe)%is1(n) - 1; is1Send(numS) = ie1Send(numS) - whalo + 1
7254 ie1Send(numS) = nCont(tileMe)%je1(n) ; js1Send(numS) = je1Send(numS) - shalo + 1
7255 ie2Send(numS) = nCont(tileMe)%is2(n) - 1; is2Send(numS) = je2Send(numS) - whalo + 1
7256 je2Send(numS) = nCont(tileMe)%js2(n) - 1; js2Send(numS) = je2Send(numS) - shalo + 1
7261 !--- found the corner overlap that is not specified through contact line.
7262 n = eCont(tileMe)%ncontact
7263 found_corner = .false.
7265 tn = eCont(tileMe)%tile(n)
7266 if( eCont(tileMe)%je1(n) == jeg(tileMe) .AND. eCont(tileMe)%je2(n) == jeg(tn) ) then
7267 if(nCont(tn)%ncontact >0) then
7268 tc = nCont(tn)%tile(1)
7269 if( nCont(tn)%is1(1) == isg(tn) .AND. nCont(tn)%is2(n) == isg(tc) ) found_corner = .true.
7273 if( .not. found_corner ) then ! not found, then starting from north contact
7274 n = nCont(tileMe)%ncontact
7276 tn = nCont(tileMe)%tile(n)
7277 if( nCont(tileMe)%ie1(n) == ieg(tileMe) .AND. nCont(tileMe)%ie2(n) == ieg(tn) ) then
7278 if(eCont(tn)%ncontact >0) then
7279 tc = eCont(tn)%tile(1)
7280 if( eCont(tn)%js1(1) == jsg(tn) .AND. eCont(tn)%js2(n) == jsg(tc) ) found_corner = .true.
7286 if(found_corner) then
7287 numS = numS+1; tileSend(numS) = tc
7288 align1Send(numS) = NORTH_EAST; align2Send(numS) = SOUTH_WEST
7289 ie1Send(numS) = ieg(tileMe); is1Send(numS) = ie1Send(numS) - whalo + 1
7290 je1Send(numS) = jeg(tileMe); js1Send(numS) = je1Send(numS) - shalo + 1
7291 ie2Send(numS) = isg(tc) - 1; is2Send(numS) = ie2Send(numS) - whalo + 1
7292 je2Send(numS) = jsg(tc) - 1; js2Send(numS) = je2Send(numS) - shalo + 1
7295 !--- to_pe's northwest for sending
7296 do n = 1, eCont(tileMe)%ncontact
7297 tn = eCont(tileMe)%tile(n)
7298 if(eCont(tileMe)%je2(n) == jeg(tn) ) then
7299 if(econt(tileMe)%je1(n) < jeg(tileMe) ) then ! send to tile tn.
7300 if( jeg(tileMe) - econt(tileMe)%je1(n) < nhalo ) call mpp_error(FATAL, &
7301 "mpp_domains_define.inc: northwest tile for send 1 is not tiled properly")
7302 numS = numS+1; tileSend(numS) = tn
7303 align1Send(numS) = SOUTH_EAST; align2Send(numS) = NORTH_WEST
7304 ie1Send(numS) = eCont(tileMe)%ie1(n) ; is1Send(numS) = ie1Send(numS) - whalo + 1
7305 js1Send(numS) = eCont(tileMe)%je1(n) + 1; je1Send(numS) = js1Send(numS) + nhalo - 1
7306 ie2Send(numS) = eCont(tileMe)%is2(n) - 1; is2Send(numS) = ie2Send(numS) - whalo + 1
7307 js2Send(numS) = eCont(tileMe)%je2(n) + 1; je2Send(numS) = js2Send(numS) + nhalo - 1
7312 do n = 1, sCont(tileMe)%ncontact
7313 tn = sCont(tileMe)%tile(n)
7314 if(sCont(tileMe)%is2(n) == isg(tn) ) then
7315 if(scont(tileMe)%is1(n) > isg(tileMe) ) then ! send to tile tn.
7316 if( scont(tileMe)%is1(n) - isg(tileMe) < whalo ) call mpp_error(FATAL, &
7317 "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7318 numS = numS+1; tileSend(numS) = tn
7319 align1Send(numS) = SOUTH_EAST; align2Send(numS) = NORTH_WEST
7320 ie1Send(numS) = nCont(tileMe)%is1(n) - 1; is1Send(numS) = ie1Send(numS) - whalo + 1
7321 js1Send(numS) = nCont(tileMe)%je1(n) ; je1Send(numS) = js1Send(numS) + nhalo - 1
7322 ie2Send(numS) = nCont(tileMe)%is2(n) - 1; is2Send(numS) = ie2Send(numS) - whalo + 1
7323 js2Send(numS) = nCont(tileMe)%je2(n) + 1; je2Send(numS) = js2Send(numS) + nhalo - 1
7328 !--- found the corner overlap that is not specified through contact line.
7329 n = eCont(tileMe)%ncontact
7330 found_corner = .false.
7332 tn = eCont(tileMe)%tile(1)
7333 if( eCont(tileMe)%js1(1) == jsg(tileMe) .AND. eCont(tileMe)%js2(1) == jsg(tn) ) then
7334 if(sCont(tn)%ncontact >0) then
7335 tc = sCont(tn)%tile(1)
7336 if( sCont(tn)%is1(1) == isg(tn) .AND. sCont(tn)%is2(1) == isg(tc) ) found_corner = .true.
7340 if( .not. found_corner ) then ! not found, then starting from north contact
7341 n = sCont(tileMe)%ncontact
7342 found_corner = .false.
7344 tn = sCont(tileMe)%tile(n)
7345 if( sCont(tileMe)%ie1(n) == ieg(tileMe) .AND. sCont(tileMe)%ie2(n) == ieg(tn) ) then
7346 if(eCont(tn)%ncontact >0) then
7347 tc = eCont(tn)%tile(n)
7348 if( eCont(tn)%je1(n) == jeg(tn) .AND. eCont(tn)%je2(n) == jeg(tc) ) found_corner = .true.
7354 if(found_corner) then
7355 numS = numS+1; tileSend(numS) = tc
7356 align1Send(numS) = SOUTH_EAST; align2Send(numS) = NORTH_WEST
7357 ie1Send(numS) = ieg(tileMe); is1Send(numS) = ie1Send(numS) - whalo + 1
7358 js1Send(numS) = jsg(tileMe); je1Send(numS) = js1Send(numS) + nhalo - 1
7359 ie2Send(numS) = isg(tc) - 1; is2Send(numS) = ie2Send(numS) - whalo + 1
7360 js2Send(numS) = jeg(tc) + 1; je2Send(numS) = js2Send(numS) + nhalo - 1
7363 !--- to_pe's northeast for sending
7364 do n = 1, wCont(tileMe)%ncontact
7365 tn = wCont(tileMe)%tile(n)
7366 if(wCont(tileMe)%je2(n) == jeg(tn) ) then
7367 if(wcont(tileMe)%je1(n) < jeg(tileMe) ) then ! send to tile tn.
7368 if( jeg(tileMe) - wcont(tileMe)%je1(n) < nhalo ) call mpp_error(FATAL, &
7369 "mpp_domains_define.inc: northeast tile for send 1 is not tiled properly")
7370 numS = numS+1; tileSend(numS) = tn
7371 align1Send(numS) = SOUTH_WEST; align2Send(numS) = NORTH_EAST
7372 is1Send(numS) = wCont(tileMe)%is1(n) ; ie1Send(numS) = is1Send(numS) + ehalo - 1
7373 js1Send(numS) = wCont(tileMe)%je1(n) + 1; je1Send(numS) = js1Send(numS) + nhalo - 1
7374 is2Send(numS) = wCont(tileMe)%ie2(n) + 1; ie2Send(numS) = is2Send(numS) + ehalo - 1
7375 js2Send(numS) = wCont(tileMe)%je2(n) + 1; je2Send(numS) = js2Send(numS) + nhalo - 1
7380 do n = 1, sCont(tileMe)%ncontact
7381 tn = sCont(tileMe)%tile(n)
7382 if(sCont(tileMe)%ie2(n) == ieg(tn) ) then
7383 if(sCont(tileMe)%ie1(n) < ieg(tileMe) ) then ! send to tile tn.
7384 if( ieg(tileMe) - sCont(tileMe)%ie1(n) < ehalo ) call mpp_error(FATAL, &
7385 "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7386 numS = numS+1; tileSend(numS) = tn
7387 align1Send(numS) = SOUTH_WEST; align2Send(numS) = NORTH_EAST
7388 is1Send(numS) = sCont(tileMe)%ie1(n) + 1; ie1Send(numS) = is1Send(numS) + ehalo - 1
7389 js1Send(numS) = sCont(tileMe)%js1(n) ; je1Send(numS) = js1Send(numS) + nhalo - 1
7390 is2Send(numS) = sCont(tileMe)%ie2(n) + 1; ie2Send(numS) = is1Send(numS) + ehalo - 1
7391 js2Send(numS) = sCont(tileMe)%je2(n) + 1; je2Send(numS) = js2Send(numS) + nhalo - 1
7396 !--- found the corner overlap that is not specified through contact line.
7397 n = wCont(tileMe)%ncontact
7398 found_corner = .false.
7400 tn = wCont(tileMe)%tile(1)
7401 if( wCont(tileMe)%js1(n) == jsg(tileMe) .AND. wCont(tileMe)%js2(n) == jsg(tn) ) then
7402 m = sCont(tn)%ncontact
7404 tc = sCont(tn)%tile(m)
7405 if( sCont(tn)%ie1(m) == ieg(tn) .AND. sCont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7409 if( .not. found_corner ) then ! not found, then starting from north contact
7410 n = sCont(tileMe)%ncontact
7411 found_corner = .false.
7413 tn = sCont(tileMe)%tile(1)
7414 if( sCont(tileMe)%is1(1) == isg(tileMe) .AND. sCont(tileMe)%is2(1) == isg(tn) ) then
7415 m = wCont(tn)%ncontact
7417 tc = wCont(tn)%tile(m)
7418 if( wCont(tn)%je1(m) == jeg(tn) .AND. wCont(tn)%je2(m) == jeg(tc) ) found_corner = .true.
7423 if(found_corner) then
7424 numS = numS+1; tileSend(numS) = tc
7425 align1Send(numS) = SOUTH_WEST; align2Send(numS) = NORTH_EAST
7426 is1Send(numS) = isg(tileMe); ie1Send(numS) = is1Send(numS) + ehalo - 1
7427 js1Send(numS) = jsg(tileMe); je1Send(numS) = js1Send(numS) + nhalo - 1
7428 is2Send(numS) = ieg(tc) + 1; ie2Send(numS) = is2Send(numS) + ehalo - 1
7429 js2Send(numS) = jeg(tc) + 1; je2Send(numS) = js2Send(numS) + nhalo - 1
7432 end subroutine fill_corner_contact
7434 !--- find the alignment direction, check if index is reversed, if reversed, exchange index.
7435 subroutine check_alignment( is, ie, js, je, isg, ieg, jsg, jeg, alignment )
7436 integer, intent(inout) :: is, ie, js, je, isg, ieg, jsg, jeg
7437 integer, intent(out) :: alignment
7441 if ( is == ie ) then ! x-alignment
7442 if ( is == isg ) then
7444 else if ( is == ieg ) then
7447 call mpp_error(FATAL, 'mpp_domains_define.inc: The contact region is not on the x-boundary of the tile')
7450 j = js; js = je; je = j
7452 else if ( js == je ) then ! y-alignment
7453 if ( js == jsg ) then
7455 else if ( js == jeg ) then
7458 call mpp_error(FATAL, 'mpp_domains_define.inc: The contact region is not on the y-boundary of the tile')
7461 i = is; is = ie; ie = i
7464 call mpp_error(FATAL, 'mpp_domains_define.inc: The contact region should be line contact' )
7467 end subroutine check_alignment
7468 !#####################################################################
7470 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7472 ! MPP_MODIFY_DOMAIN: modify extent of domain !
7474 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7475 ! <SUBROUTINE NAME="mpp_modify_domain1D" INTERFACE="mpp_modify_domain">
7476 ! <IN NAME="domain_in" TYPE="type(domain1D)" > </IN>
7477 ! <IN NAME="hbegin,hend" TYPE="integer,optional" > </IN>
7478 ! <IN NAME="cbegin,cend" TYPE="integer,optional" > </IN>
7479 ! <IN NAME="gbegin,gend" TYPE="integer,optional" > </IN>
7480 ! <INOUT NAME="domain_out" TYPE="type(domain1D)" > </INOUT>
7483 subroutine mpp_modify_domain1D(domain_in,domain_out,cbegin,cend,gbegin,gend, hbegin, hend)
7485 type(domain1D), intent(in) :: domain_in !< The source domain.
7486 type(domain1D), intent(inout) :: domain_out !< The returned domain.
7487 integer, intent(in), optional :: hbegin, hend !< halo size
7488 integer, intent(in), optional :: cbegin, cend !< Axis specifications associated with the compute
7489 !! domain of the returned 1D domain.
7490 integer, intent(in), optional :: gbegin, gend !< Axis specifications associated with the global
7491 !! domain of the returned 1D domain.
7492 integer :: ndivs, global_indices(2) !(/ isg, ieg /)
7494 ! get the global indices of the input domain
7495 global_indices(1) = domain_in%global%begin; global_indices(2) = domain_in%global%end
7498 ndivs = size(domain_in%list(:))
7502 if(domain_in%cyclic) flag = flag + CYCLIC_GLOBAL_DOMAIN
7503 if(domain_in%data%is_global) flag = flag + GLOBAL_DATA_DOMAIN
7505 call mpp_define_domains( global_indices, ndivs, domain_out, pelist = domain_in%list(:)%pe, &
7506 flags = flag, begin_halo = hbegin, end_halo = hend, extent = domain_in%list(:)%compute%size )
7508 if(present(cbegin)) domain_out%compute%begin = cbegin
7509 if(present(cend)) domain_out%compute%end = cend
7510 domain_out%compute%size = domain_out%compute%end - domain_out%compute%begin + 1
7511 if(present(gbegin)) domain_out%global%begin = gbegin
7512 if(present(gend)) domain_out%global%end = gend
7513 domain_out%global%size = domain_out%global%end - domain_out%global%begin + 1
7515 end subroutine mpp_modify_domain1D
7518 !#######################################################################
7519 !----------------------------------------------------------------------------------
7520 ! <SUBROUTINE NAME="mpp_modify_domain2D" INTERFACE="mpp_modify_domain">
7521 ! <IN NAME="domain_in" TYPE="type(domain2D)" > </IN>
7522 ! <IN NAME="isc,iec" TYPE="integer,optional" > </IN>
7523 ! <IN NAME="jsc,jec" TYPE="integer,optional" > </IN>
7524 ! <IN NAME="isg,ieg" TYPE="integer,optional" > </IN>
7525 ! <IN NAME="jsg,jeg" TYPE="integer,optional" > </IN>
7526 ! <IN NAME="whalo,ehalo" TYPE="integer,optional" > </IN>
7527 ! <IN NAME="shalo,nhalo" TYPE="integer,optional" > </IN>
7528 ! <INOUT NAME="domain_out" TYPE="type(domain2D)" > </INOUT>
7531 subroutine mpp_modify_domain2D(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, &
7534 type(domain2D), intent(in) :: domain_in !< The source domain.
7535 type(domain2D), intent(inout) :: domain_out !< The returned domain.
7536 integer, intent(in), optional :: isc, iec, jsc, jec !< Zonal and meridional axis specifications
7537 !! associated with the global domain of the returned 2D domain.
7538 integer, intent(in), optional :: isg, ieg, jsg, jeg !< Zonal axis specifications associated with
7539 !! the global domain of the returned 2D domain.
7540 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size in x- and y- directions
7541 integer :: global_indices(4), layout(2)
7542 integer :: xflag, yflag, nlist, i
7544 if(present(whalo) .or. present(ehalo) .or. present(shalo) .or. present(nhalo) ) then
7545 ! get the global indices of the input domain
7546 global_indices(1) = domain_in%x(1)%global%begin; global_indices(2) = domain_in%x(1)%global%end
7547 global_indices(3) = domain_in%y(1)%global%begin; global_indices(4) = domain_in%y(1)%global%end
7550 layout(1) = size(domain_in%x(1)%list(:)); layout(2) = size(domain_in%y(1)%list(:))
7553 xflag = 0; yflag = 0
7554 if(domain_in%x(1)%cyclic) xflag = xflag + CYCLIC_GLOBAL_DOMAIN
7555 if(domain_in%x(1)%data%is_global) xflag = xflag + GLOBAL_DATA_DOMAIN
7556 if(domain_in%y(1)%cyclic) yflag = yflag + CYCLIC_GLOBAL_DOMAIN
7557 if(domain_in%y(1)%data%is_global) yflag = yflag + GLOBAL_DATA_DOMAIN
7559 call mpp_define_domains( global_indices, layout, domain_out, pelist = domain_in%list(:)%pe, &
7560 xflags = xflag, yflags = yflag, whalo = whalo, ehalo = ehalo, &
7561 shalo = shalo, nhalo = nhalo, &
7562 xextent = domain_in%x(1)%list(:)%compute%size, &
7563 yextent = domain_in%y(1)%list(:)%compute%size, &
7564 symmetry=domain_in%symmetry, &
7565 maskmap = domain_in%pearray .NE. NULL_PE )
7566 domain_out%ntiles = domain_in%ntiles
7567 domain_out%tile_id = domain_in%tile_id
7569 call mpp_define_null_domain(domain_out)
7570 nlist = size(domain_in%list(:))
7571 allocate(domain_out%list(0:nlist-1) )
7573 allocate(domain_out%list(i)%tile_id(1))
7574 domain_out%list(i)%tile_id(1) = 1
7576 call mpp_modify_domain(domain_in%x(1), domain_out%x(1), isc, iec, isg, ieg)
7577 call mpp_modify_domain(domain_in%y(1), domain_out%y(1), jsc, jec, jsg, jeg)
7578 domain_out%ntiles = domain_in%ntiles
7579 domain_out%tile_id = domain_in%tile_id
7582 end subroutine mpp_modify_domain2D
7585 !#####################################################################
7588 subroutine mpp_define_null_domain1D(domain)
7589 type(domain1D), intent(inout) :: domain
7591 domain%global%begin = -1; domain%global%end = -1; domain%global%size = 0
7592 domain%data%begin = -1; domain%data%end = -1; domain%data%size = 0
7593 domain%compute%begin = -1; domain%compute%end = -1; domain%compute%size = 0
7596 end subroutine mpp_define_null_domain1D
7598 !#####################################################################
7601 subroutine mpp_define_null_domain2D(domain)
7602 type(domain2D), intent(inout) :: domain
7604 allocate(domain%x(1), domain%y(1), domain%tile_id(1))
7605 call mpp_define_null_domain(domain%x(1))
7606 call mpp_define_null_domain(domain%y(1))
7608 domain%tile_id(1) = 1
7610 domain%max_ntile_pe = 1
7611 domain%ncontacts = 0
7613 end subroutine mpp_define_null_domain2D
7615 !####################################################################
7617 subroutine mpp_deallocate_domain1D(domain)
7618 type(domain1D), intent(inout) :: domain
7620 if(ASSOCIATED(domain%list)) deallocate(domain%list)
7622 end subroutine mpp_deallocate_domain1D
7624 !####################################################################
7626 subroutine mpp_deallocate_domain2D(domain)
7627 type(domain2D), intent(inout) :: domain
7629 call deallocate_domain2D_local(domain)
7630 if(ASSOCIATED(domain%io_domain) ) then
7631 call deallocate_domain2D_local(domain%io_domain)
7632 deallocate(domain%io_domain)
7635 end subroutine mpp_deallocate_domain2D
7637 !##################################################################
7639 subroutine deallocate_domain2D_local(domain)
7640 type(domain2D), intent(inout) :: domain
7641 integer :: i, ntileMe
7643 ntileMe = size(domain%x(:))
7645 if(ASSOCIATED(domain%pearray))deallocate(domain%pearray)
7647 call mpp_deallocate_domain1D(domain%x(i))
7648 call mpp_deallocate_domain1D(domain%y(i))
7650 deallocate(domain%x, domain%y, domain%tile_id)
7652 ! TODO: Check if these are always allocated
7653 if(ASSOCIATED(domain%tileList)) deallocate(domain%tileList)
7654 if(ASSOCIATED(domain%tile_id_all)) deallocate(domain%tile_id_all)
7656 if(ASSOCIATED(domain%list)) then
7657 do i = 0, size(domain%list(:))-1
7658 deallocate(domain%list(i)%x, domain%list(i)%y, domain%list(i)%tile_id)
7660 deallocate(domain%list)
7663 if(ASSOCIATED(domain%check_C)) then
7664 call deallocate_overlapSpec(domain%check_C)
7665 deallocate(domain%check_C)
7668 if(ASSOCIATED(domain%check_E)) then
7669 call deallocate_overlapSpec(domain%check_E)
7670 deallocate(domain%check_E)
7673 if(ASSOCIATED(domain%check_N)) then
7674 call deallocate_overlapSpec(domain%check_N)
7675 deallocate(domain%check_N)
7678 if(ASSOCIATED(domain%bound_C)) then
7679 call deallocate_overlapSpec(domain%bound_C)
7680 deallocate(domain%bound_C)
7683 if(ASSOCIATED(domain%bound_E)) then
7684 call deallocate_overlapSpec(domain%bound_E)
7685 deallocate(domain%bound_E)
7688 if(ASSOCIATED(domain%bound_N)) then
7689 call deallocate_overlapSpec(domain%bound_N)
7690 deallocate(domain%bound_N)
7693 if(ASSOCIATED(domain%update_T)) then
7694 call deallocate_overlapSpec(domain%update_T)
7695 deallocate(domain%update_T)
7698 if(ASSOCIATED(domain%update_E)) then
7699 call deallocate_overlapSpec(domain%update_E)
7700 deallocate(domain%update_E)
7703 if(ASSOCIATED(domain%update_C)) then
7704 call deallocate_overlapSpec(domain%update_C)
7705 deallocate(domain%update_C)
7708 if(ASSOCIATED(domain%update_N)) then
7709 call deallocate_overlapSpec(domain%update_N)
7710 deallocate(domain%update_N)
7713 end subroutine deallocate_domain2D_local
7715 !####################################################################
7717 subroutine allocate_check_overlap(overlap, count)
7718 type(overlap_type), intent(inout) :: overlap
7719 integer, intent(in ) :: count
7722 overlap%pe = NULL_PE
7723 if(associated(overlap%tileMe)) call mpp_error(FATAL, &
7724 "allocate_check_overlap(mpp_domains_define): overlap is already been allocated")
7725 if(count < 1) call mpp_error(FATAL, &
7726 "allocate_check_overlap(mpp_domains_define): count should be a positive integer")
7727 allocate(overlap%tileMe (count), overlap%dir(count) )
7728 allocate(overlap%is (count), overlap%ie (count) )
7729 allocate(overlap%js (count), overlap%je (count) )
7730 allocate(overlap%rotation(count) )
7731 overlap%rotation = ZERO
7733 end subroutine allocate_check_overlap
7735 !#######################################################################
7736 subroutine insert_check_overlap(overlap, pe, tileMe, dir, rotation, is, ie, js, je)
7737 type(overlap_type), intent(inout) :: overlap
7738 integer, intent(in ) :: pe
7739 integer, intent(in ) :: tileMe, dir, rotation
7740 integer, intent(in ) :: is, ie, js, je
7743 overlap%count = overlap%count + 1
7744 count = overlap%count
7745 if(.NOT. associated(overlap%tileMe)) call mpp_error(FATAL, &
7746 "mpp_domains_define.inc(insert_check_overlap): overlap is not assigned any memory")
7747 if(count > size(overlap%tileMe(:)) ) call mpp_error(FATAL, &
7748 "mpp_domains_define.inc(insert_check_overlap): overlap%count is greater than size(overlap%tileMe)")
7749 if( overlap%pe == NULL_PE ) then
7752 if(overlap%pe .NE. pe) call mpp_error(FATAL, &
7753 "mpp_domains_define.inc(insert_check_overlap): mismatch on pe")
7755 overlap%tileMe (count) = tileMe
7756 overlap%dir (count) = dir
7757 overlap%rotation(count) = rotation
7758 overlap%is (count) = is
7759 overlap%ie (count) = ie
7760 overlap%js (count) = js
7761 overlap%je (count) = je
7763 end subroutine insert_check_overlap
7765 !#######################################################################
7766 !--- this routine add the overlap_in into overlap_out
7767 subroutine add_check_overlap( overlap_out, overlap_in)
7768 type(overlap_type), intent(inout) :: overlap_out
7769 type(overlap_type), intent(in ) :: overlap_in
7770 type(overlap_type) :: overlap
7771 integer :: count, count_in, count_out
7773 ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
7774 count_in = overlap_in %count
7775 count_out = overlap_out%count
7776 count = count_in+count_out
7777 if(count_in == 0) call mpp_error(FATAL, &
7778 "add_check_overlap(mpp_domains_define): overlap_in%count is zero")
7780 if(count_out == 0) then
7781 if(associated(overlap_out%tileMe)) call mpp_error(FATAL, &
7782 "add_check_overlap(mpp_domains_define): overlap is already been allocated but count=0")
7783 call allocate_check_overlap(overlap_out, count_in)
7784 overlap_out%pe = overlap_in%pe
7785 else ! need to expand the dimension size of overlap
7786 call allocate_check_overlap(overlap, count_out)
7787 if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(FATAL, &
7788 "mpp_domains_define.inc(add_check_overlap): mismatch of pe between overlap_in and overlap_out")
7789 overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
7790 overlap%is (1:count_out) = overlap_out%is (1:count_out)
7791 overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
7792 overlap%js (1:count_out) = overlap_out%js (1:count_out)
7793 overlap%je (1:count_out) = overlap_out%je (1:count_out)
7794 overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
7795 overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
7796 call deallocate_overlap_type(overlap_out)
7797 call allocate_check_overlap(overlap_out, count)
7798 overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
7799 overlap_out%is (1:count_out) = overlap%is (1:count_out)
7800 overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
7801 overlap_out%js (1:count_out) = overlap%js (1:count_out)
7802 overlap_out%je (1:count_out) = overlap%je (1:count_out)
7803 overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
7804 overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
7805 call deallocate_overlap_type(overlap)
7807 overlap_out%count = count
7808 overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
7809 overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
7810 overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
7811 overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
7812 overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
7813 overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
7814 overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
7816 end subroutine add_check_overlap
7818 !####################################################################
7819 subroutine init_overlap_type(overlap)
7820 type(overlap_type), intent(inout) :: overlap
7823 overlap%pe = NULL_PE
7825 end subroutine init_overlap_type
7827 !####################################################################
7829 subroutine allocate_update_overlap( overlap, count)
7830 type(overlap_type), intent(inout) :: overlap
7831 integer, intent(in ) :: count
7834 overlap%pe = NULL_PE
7835 if(associated(overlap%tileMe)) call mpp_error(FATAL, &
7836 "allocate_update_overlap(mpp_domains_define): overlap is already been allocated")
7837 if(count < 1) call mpp_error(FATAL, &
7838 "allocate_update_overlap(mpp_domains_define): count should be a positive integer")
7839 allocate(overlap%tileMe (count), overlap%tileNbr (count) )
7840 allocate(overlap%is (count), overlap%ie (count) )
7841 allocate(overlap%js (count), overlap%je (count) )
7842 allocate(overlap%dir (count), overlap%rotation(count) )
7843 allocate(overlap%from_contact(count), overlap%msgsize (count) )
7844 overlap%rotation = ZERO
7845 overlap%from_contact = .FALSE.
7847 end subroutine allocate_update_overlap
7849 !#####################################################################################
7850 subroutine insert_update_overlap(overlap, pe, is1, ie1, js1, je1, is2, ie2, js2, je2, dir, reverse, symmetry)
7851 type(overlap_type), intent(inout) :: overlap
7852 integer, intent(in ) :: pe
7853 integer, intent(in ) :: is1, ie1, js1, je1, is2, ie2, js2, je2
7854 integer, intent(in ) :: dir
7855 logical, optional, intent(in ) :: reverse, symmetry
7857 logical :: is_reverse, is_symmetry, is_overlapped
7858 integer :: is, ie, js, je, count
7860 is_reverse = .FALSE.
7861 if(PRESENT(reverse)) is_reverse = reverse
7862 is_symmetry = .FALSE.
7863 if(PRESENT(symmetry)) is_symmetry = symmetry
7865 is = max(is1,is2); ie = min(ie1,ie2)
7866 js = max(js1,js2); je = min(je1,je2)
7867 is_overlapped = .false.
7868 !--- to avoid unnecessary ( duplicate overlap ) for symmetry domain
7869 if(is_symmetry .AND. (dir == 1 .OR. dir == 5)) then ! x-direction
7870 if( ie .GE. is .AND. je .GT. js ) is_overlapped = .true.
7871 else if(is_symmetry .AND. (dir == 3 .OR. dir == 7)) then ! y-direction
7872 if( ie .GT. is .AND. je .GE. js ) is_overlapped = .true.
7873 else if(ie.GE.is .AND. je.GE.js )then
7874 is_overlapped = .true.
7877 if(is_overlapped) then
7878 if( overlap%count == 0 ) then
7881 if(overlap%pe .NE. pe) call mpp_error(FATAL, &
7882 "mpp_domains_define.inc(insert_update_overlap): mismatch on pe")
7884 overlap%count = overlap%count+1
7885 count = overlap%count
7886 if(count > MAXOVERLAP) call mpp_error(FATAL, "mpp_domains_define.inc(insert_update_overlap):"//&
7887 & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7888 overlap%is(count) = is
7889 overlap%ie(count) = ie
7890 overlap%js(count) = js
7891 overlap%je(count) = je
7892 overlap%tileMe (count) = 1
7893 overlap%tileNbr(count) = 1
7894 overlap%dir(count) = dir
7896 overlap%rotation(count) = ONE_HUNDRED_EIGHTY
7898 overlap%rotation(count) = ZERO
7902 end subroutine insert_update_overlap
7904 !#####################################################################################
7905 subroutine insert_overlap_type(overlap, pe, tileMe, tileNbr, is, ie, js, je, dir, &
7906 rotation, from_contact)
7907 type(overlap_type), intent(inout) :: overlap
7908 integer, intent(in ) :: tileMe, tileNbr, pe
7909 integer, intent(in ) :: is, ie, js, je
7910 integer, intent(in ) :: dir, rotation
7911 logical, intent(in ) :: from_contact
7914 if( overlap%count == 0 ) then
7917 if(overlap%pe .NE. pe) call mpp_error(FATAL, &
7918 "mpp_domains_define.inc(insert_overlap_type): mismatch on pe")
7920 overlap%count = overlap%count+1
7921 count = overlap%count
7922 if(count > MAXOVERLAP) call mpp_error(FATAL, "mpp_domains_define.inc(insert_overlap_type):"//&
7923 & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7924 overlap%tileMe (count) = tileMe
7925 overlap%tileNbr (count) = tileNbr
7926 overlap%is (count) = is
7927 overlap%ie (count) = ie
7928 overlap%js (count) = js
7929 overlap%je (count) = je
7930 overlap%dir (count) = dir
7931 overlap%rotation (count) = rotation
7932 overlap%from_contact(count) = from_contact
7933 overlap%msgsize (count) = (ie-is+1)*(je-js+1)
7935 end subroutine insert_overlap_type
7938 !#######################################################################
7939 subroutine deallocate_overlap_type( overlap)
7940 type(overlap_type), intent(inout) :: overlap
7942 if(overlap%count == 0) then
7943 if( .NOT. associated(overlap%tileMe)) return
7945 if( .NOT. associated(overlap%tileMe)) call mpp_error(FATAL, &
7946 "deallocate_overlap_type(mpp_domains_define): overlap is not been allocated")
7948 if(ASSOCIATED(overlap%tileMe)) deallocate(overlap%tileMe)
7949 if(ASSOCIATED(overlap%tileNbr)) deallocate(overlap%tileNbr)
7950 if(ASSOCIATED(overlap%is)) deallocate(overlap%is)
7951 if(ASSOCIATED(overlap%ie)) deallocate(overlap%ie)
7952 if(ASSOCIATED(overlap%js)) deallocate(overlap%js)
7953 if(ASSOCIATED(overlap%je)) deallocate(overlap%je)
7954 if(ASSOCIATED(overlap%dir)) deallocate(overlap%dir)
7955 if(ASSOCIATED(overlap%index)) deallocate(overlap%index)
7956 if(ASSOCIATED(overlap%rotation)) deallocate(overlap%rotation)
7957 if(ASSOCIATED(overlap%from_contact)) deallocate(overlap%from_contact)
7958 if(ASSOCIATED(overlap%msgsize)) deallocate(overlap%msgsize)
7961 end subroutine deallocate_overlap_type
7963 !#######################################################################
7964 subroutine deallocate_overlapSpec(overlap)
7965 type(overlapSpec), intent(inout) :: overlap
7968 if(ASSOCIATED(overlap%send)) then
7969 do n = 1, size(overlap%send(:))
7970 call deallocate_overlap_type(overlap%send(n))
7972 deallocate(overlap%send)
7974 if(ASSOCIATED(overlap%recv)) then
7975 do n = 1, size(overlap%recv(:))
7976 call deallocate_overlap_type(overlap%recv(n))
7978 deallocate(overlap%recv)
7982 end subroutine deallocate_overlapSpec
7984 !#######################################################################
7985 !--- this routine add the overlap_in into overlap_out
7986 subroutine add_update_overlap( overlap_out, overlap_in)
7987 type(overlap_type), intent(inout) :: overlap_out
7988 type(overlap_type), intent(in ) :: overlap_in
7989 type(overlap_type) :: overlap
7990 integer :: count, count_in, count_out, n
7992 ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
7993 count_in = overlap_in %count
7994 count_out = overlap_out%count
7995 count = count_in+count_out
7996 if(count_in == 0) call mpp_error(FATAL, &
7997 "mpp_domains_define.inc(add_update_overlap): overlap_in%count is zero")
7999 if(count_out == 0) then
8000 if(associated(overlap_out%tileMe)) call mpp_error(FATAL, &
8001 "mpp_domains_define.inc(add_update_overlap): overlap is already been allocated but count=0")
8002 call allocate_update_overlap(overlap_out, count_in)
8003 overlap_out%pe = overlap_in%pe
8004 else ! need to expand the dimension size of overlap
8005 if(overlap_in%pe .NE. overlap_out%pe) call mpp_error(FATAL, &
8006 "mpp_domains_define.inc(add_update_overlap): mismatch of pe between overlap_in and overlap_out")
8008 call allocate_update_overlap(overlap, count_out)
8009 overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
8010 overlap%tileNbr (1:count_out) = overlap_out%tileNbr (1:count_out)
8011 overlap%is (1:count_out) = overlap_out%is (1:count_out)
8012 overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
8013 overlap%js (1:count_out) = overlap_out%js (1:count_out)
8014 overlap%je (1:count_out) = overlap_out%je (1:count_out)
8015 overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
8016 overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
8017 overlap%from_contact(1:count_out) = overlap_out%from_contact(1:count_out)
8018 call deallocate_overlap_type(overlap_out)
8019 call allocate_update_overlap(overlap_out, count)
8020 overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
8021 overlap_out%tileNbr (1:count_out) = overlap%tileNbr (1:count_out)
8022 overlap_out%is (1:count_out) = overlap%is (1:count_out)
8023 overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
8024 overlap_out%js (1:count_out) = overlap%js (1:count_out)
8025 overlap_out%je (1:count_out) = overlap%je (1:count_out)
8026 overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
8027 overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
8028 overlap_out%index (1:count_out) = overlap%index (1:count_out)
8029 overlap_out%from_contact(1:count_out) = overlap%from_contact(1:count_out)
8030 overlap_out%msgsize (1:count_out) = overlap%msgsize (1:count_out)
8031 call deallocate_overlap_type(overlap)
8033 overlap_out%count = count
8034 overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
8035 overlap_out%tileNbr (count_out+1:count) = overlap_in%tileNbr (1:count_in)
8036 overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
8037 overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
8038 overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
8039 overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
8040 overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
8041 overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
8042 overlap_out%from_contact(count_out+1:count) = overlap_in%from_contact(1:count_in)
8044 do n = count_out+1, count
8045 overlap_out%msgsize(n) = (overlap_out%ie(n)-overlap_out%is(n)+1)*(overlap_out%je(n)-overlap_out%js(n)+1)
8049 end subroutine add_update_overlap
8051 !##############################################################################
8052 subroutine expand_update_overlap_list(overlapList, npes)
8053 type(overlap_type), pointer :: overlapList(:)
8054 integer, intent(in ) :: npes
8055 type(overlap_type), pointer,save :: newlist(:) => NULL()
8056 integer :: nlist_old, nlist, m
8058 nlist_old = size(overlaplist(:))
8059 if(nlist_old .GE. npes) call mpp_error(FATAL, &
8060 'mpp_domains_define.inc(expand_update_overlap_list): size of overlaplist should be smaller than npes')
8061 nlist = min(npes, 2*nlist_old)
8062 allocate(newlist(nlist))
8064 call add_update_overlap(newlist(m), overlaplist(m))
8065 call deallocate_overlap_type(overlapList(m))
8068 deallocate(overlapList)
8069 overlaplist => newlist
8074 end subroutine expand_update_overlap_list
8076 !##################################################################################
8077 subroutine expand_check_overlap_list(overlaplist, npes)
8078 type(overlap_type), pointer :: overlaplist(:)
8079 integer, intent(in) :: npes
8080 type(overlap_type), pointer,save :: newlist(:) => NULL()
8081 integer :: nlist_old, nlist, m
8083 nlist_old = size(overlaplist(:))
8084 if(nlist_old .GE. npes) call mpp_error(FATAL, &
8085 'mpp_domains_define.inc(expand_check_overlap_list): size of overlaplist should be smaller than npes')
8086 nlist = min(npes, 2*nlist_old)
8087 allocate(newlist(nlist))
8088 do m = 1,size(overlaplist(:))
8089 call add_check_overlap(newlist(m), overlaplist(m))
8090 call deallocate_overlap_type(overlapList(m))
8092 deallocate(overlapList)
8093 overlaplist => newlist
8098 end subroutine expand_check_overlap_list
8101 !###############################################################################
8102 subroutine check_overlap_pe_order(domain, overlap, name)
8103 type(domain2d), intent(in) :: domain
8104 type(overlapSpec), intent(in) :: overlap
8105 character(len=*), intent(in) :: name
8109 !---make sure overlap%nsend and overlap%nrecv is no larger than MAXLIST
8110 if( overlap%nsend > MAXLIST) call mpp_error(FATAL, &
8111 "mpp_domains_define.inc(check_overlap_pe_order): overlap%nsend > MAXLIST, increase MAXLIST")
8112 if( overlap%nrecv > MAXLIST) call mpp_error(FATAL, &
8113 "mpp_domains_define.inc(check_overlap_pe_order): overlap%nrecv > MAXLIST, increase MAXLIST")
8115 do m = 2, overlap%nsend
8116 pe1 = overlap%send(m-1)%pe
8117 pe2 = overlap%send(m)%pe
8118 !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8119 if( pe2 == domain%pe ) then
8120 print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8121 call mpp_error(FATAL, &
8122 "mpp_domains_define.inc(check_overlap_pe_order): send pe2 can not equal to domain%pe")
8123 else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8124 if( pe2 < pe1 ) then
8125 print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8126 call mpp_error(FATAL, &
8127 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 1")
8129 else if ( pe2 > domain%pe .AND. pe1 < domain%pe ) then
8130 print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8131 call mpp_error(FATAL, &
8132 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 2")
8137 do m = 2, overlap%nrecv
8138 pe1 = overlap%recv(m-1)%pe
8139 pe2 = overlap%recv(m)%pe
8140 !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8141 if( pe2 == domain%pe ) then
8142 print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8143 call mpp_error(FATAL, &
8144 "mpp_domains_define.inc(check_overlap_pe_order): recv pe2 can not equal to domain%pe")
8145 else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8146 if( pe2 > pe1 ) then
8147 print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8148 call mpp_error(FATAL, &
8149 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 1")
8151 else if ( pe2 < domain%pe .AND. pe1 > domain%pe ) then
8152 print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8153 call mpp_error(FATAL, &
8154 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 2")
8159 end subroutine check_overlap_pe_order
8162 !###############################################################################
8163 subroutine set_domain_comm_inf(update)
8164 type(overlapSpec), intent(inout) :: update
8166 integer :: m, totsize, n
8169 ! first set the send and recv size
8172 do m = 1, update%nrecv
8174 do n = 1, update%recv(m)%count
8175 totsize = totsize + update%recv(m)%msgsize(n)
8177 update%recv(m)%totsize = totsize
8179 update%recv(m)%start_pos = 0
8181 update%recv(m)%start_pos = update%recv(m-1)%start_pos + update%recv(m-1)%totsize
8183 update%recvsize = update%recvsize + totsize
8186 do m = 1, update%nsend
8188 do n = 1, update%send(m)%count
8189 totsize = totsize + update%send(m)%msgsize(n)
8191 update%send(m)%totsize = totsize
8193 update%send(m)%start_pos = 0
8195 update%send(m)%start_pos = update%send(m-1)%start_pos + update%send(m-1)%totsize
8197 update%sendsize = update%sendsize + totsize
8203 end subroutine set_domain_comm_inf