FMS  2024.03
Flexible Modeling System
mpp_domains_define.inc
1 ! -*-f90-*-
2 !***********************************************************************
3 !* GNU Lesser General Public License
4 !*
5 !* This file is part of the GFDL Flexible Modeling System (FMS).
6 !*
7 !* FMS is free software: you can redistribute it and/or modify it under
8 !* the terms of the GNU Lesser General Public License as published by
9 !* the Free Software Foundation, either version 3 of the License, or (at
10 !* your option) any later version.
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 !* for more details.
16 !*
17 !* You should have received a copy of the GNU Lesser General Public
18 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
19 !***********************************************************************
20 
21 !> @file
22 !> @brief Various routines handling domains in @ref mpp_domains_mod
23 
24 !> @addtogroup mpp_domains_mod
25 !> @{
26  !> @brief Instantiates a layout with the given indices and divisions
27  subroutine mpp_define_layout2d( global_indices, ndivs, layout )
28  integer, intent(in) :: global_indices(:) !< (/ isg, ieg, jsg, jeg /); Defines the global domain.
29  integer, intent(in) :: ndivs !< number of divisions to divide global domain
30  integer, intent(out) :: layout(:)
31 
32  integer :: isg, ieg, jsg, jeg, isz, jsz, idiv, jdiv
33 
34  if(size(global_indices(:)) .NE. 4) call mpp_error(fatal,"mpp_define_layout2D: size of global_indices should be 4")
35  if(size(layout(:)) .NE. 2) call mpp_error(fatal,"mpp_define_layout2D: size of layout should be 2")
36 
37  isg = global_indices(1)
38  ieg = global_indices(2)
39  jsg = global_indices(3)
40  jeg = global_indices(4)
41 
42  isz = ieg - isg + 1
43  jsz = jeg - jsg + 1
44  !first try to divide ndivs in the domain aspect ratio: if imperfect aspect, reduce idiv till it divides ndivs
45  idiv = nint( sqrt(float(ndivs*isz)/jsz) )
46  idiv = max(idiv,1) !for isz=1 line above can give 0
47  do while( mod(ndivs,idiv).NE.0 )
48  idiv = idiv - 1
49  end do !will terminate at idiv=1 if not before
50  jdiv = ndivs/idiv
51 
52  layout = (/ idiv, jdiv /)
53  return
54  end subroutine mpp_define_layout2d
55 
56  !############################################################################
57 
58  !> Defines a pelist for use with mosaic tiles
59  !! @note The following routine may need to revised to improve the capability.
60  !! It is very hard to make it balance for all the situation.
61  !! Hopefully some smart idea will come up someday.
62  subroutine mpp_define_mosaic_pelist( sizes, pe_start, pe_end, pelist, costpertile)
63  integer, dimension(:), intent(in) :: sizes
64  integer, dimension(:), intent(inout) :: pe_start, pe_end
65  integer, dimension(:), intent(in), optional :: pelist, costpertile
66  integer, dimension(size(sizes(:))) :: costs
67  integer, dimension(:), allocatable :: pes
68  integer :: ntiles, npes, totcosts, avgcost
69  integer :: ntiles_left, npes_left, pos, n, tile
70  integer :: cost_on_tile, cost_on_pe, npes_used, errunit
71 
72  ntiles = size(sizes(:))
73  if(size(pe_start(:)) .NE. ntiles .OR. size(pe_end(:)) .NE. ntiles ) then
74  call mpp_error(fatal, "mpp_define_mosaic_pelist: size mismatch between pe_start/pe_end and sizes")
75  end if
76 
77  if(present(costpertile)) then
78  if(size(costpertile(:)) .NE. ntiles ) then
79  call mpp_error(fatal, "mpp_define_mosaic_pelist: size mismatch between costpertile and sizes")
80  end if
81  costs = sizes*costpertile
82  else
83  costs = sizes
84  end if
85 
86  if( PRESENT(pelist) )then
87  if( .NOT.any(pelist.EQ.mpp_pe()) )then
88  errunit = stderr()
89  write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
90  call mpp_error( fatal, 'mpp_define_mosaic_pelist: pe must be in pelist.' )
91  end if
92  npes = size(pelist(:))
93  allocate( pes(0:npes-1) )
94  pes(:) = pelist(:)
95  else
96  npes = mpp_npes()
97  allocate( pes(0:npes-1) )
98  call mpp_get_current_pelist(pes)
99  end if
100 
101  ntiles_left = ntiles
102  npes_left = npes
103  pos = pes(0)
104 
105  do while( ntiles_left > 0 )
106  if( npes_left == 1 ) then ! all left tiles will on the last processor, imbalance possibly.
107  do n = 1, ntiles
108  if(costs(n) > 0) then
109  pe_start(n) = pos
110  pe_end(n) = pos
111  costs(n) = 0
112  end if
113  end do
114  ntiles_left = 0
115  npes_left = 0
116  else
117  totcosts = sum(costs)
118  avgcost = ceiling(real(totcosts)/npes_left )
119  tile = minval(maxloc(costs))
120  cost_on_tile = costs(tile)
121  pe_start(tile) = pos
122  ntiles_left = ntiles_left - 1
123  costs(tile) = 0
124  totcosts = totcosts - cost_on_tile
125  if(cost_on_tile .GE. avgcost ) then
126  npes_used = min(ceiling(real(cost_on_tile)/avgcost), npes_left)
127  if( ntiles_left > 0 .AND. npes_used == npes_left ) npes_used = npes_used - 1
128  pe_end(tile) = pos + npes_used - 1
129  npes_left = npes_left - npes_used
130  pos = pos + npes_used
131  else
132  !--- find other tiles to share the pe
133  pe_end(tile) = pos
134  cost_on_pe = cost_on_tile
135  do while(ntiles_left>npes_left) ! make sure all the pes are used.
136  tile = minval(minloc(costs, costs> 0 ))
137  cost_on_tile = costs(tile)
138  cost_on_pe = cost_on_pe + cost_on_tile
139  if(cost_on_pe > avgcost ) exit
140  pe_start(tile) = pos
141  pe_end(tile) = pos
142  ntiles_left = ntiles_left - 1
143  costs(tile) = 0
144  totcosts = totcosts - cost_on_tile
145  end do
146  npes_left = npes_left - 1
147  pos = pos + 1
148  end if
149  end if
150  end do
151 
152  if(npes_left .NE. 0 ) call mpp_error(fatal, "mpp_define_mosaic_pelist: the left npes should be zero")
153  deallocate(pes)
154 
155  end subroutine mpp_define_mosaic_pelist
156 
157  !> Computes the extents of a grid block
158  !!
159  !> Tis implementation is different from mpp_compute_extents
160  !! The last block might have most points
161  subroutine mpp_compute_block_extent(isg,ieg,ndivs,ibegin,iend)
162  integer, intent(in) :: isg, ieg, ndivs
163  integer, dimension(:), intent(out) :: ibegin, iend
164 
165  integer :: ndiv
166  integer :: is, ie
167 
168  ie = ieg
169  do ndiv=ndivs,1,-1
170  !domain is sized by dividing remaining points by remaining domains
171  is = ie - ceiling( real(ie-isg+1)/ndiv ) + 1
172  ibegin(ndiv) = is
173  iend(ndiv) = ie
174 
175  if( ie.LT.is )call mpp_error( fatal, &
176  'MPP_DEFINE_DOMAINS(mpp_compute_block_extent): domain extents must be positive definite.' )
177  if( ndiv.EQ.1 .AND. ibegin(ndiv) .NE. isg ) &
178  call mpp_error( fatal, 'mpp_compute_block_extent: domain extents do not span space completely.' )
179  ie = is - 1
180  end do
181 
182  end subroutine mpp_compute_block_extent
183 
184 
185  !#####################################################################
186  !> Computes extents for a grid decomposition with the given indices and divisions
187  subroutine mpp_compute_extent(isg,ieg,ndivs,ibegin,iend, extent )
188  integer, intent(in) :: isg, ieg, ndivs
189  integer, dimension(0:), intent(out) :: ibegin, iend
190  integer, dimension(0:), intent(in), optional :: extent
191 
192  integer :: ndiv, imax, ndmax, ndmirror
193  integer :: is, ie, n
194  logical :: symmetrize, use_extent
195  !statement functions
196  logical :: even, odd
197  even(n) = (mod(n,2).EQ.0)
198  odd(n) = (mod(n,2).EQ.1)
199 
200  use_extent = .false.
201  if(PRESENT(extent)) then
202  if( size(extent(:)).NE.ndivs ) &
203  call mpp_error( fatal, 'mpp_compute_extent: extent array size must equal number of domain divisions.' )
204  use_extent = .true.
205  if(all(extent ==0)) use_extent = .false.
206  endif
207 
208  is = isg
209  if(use_extent) then
210  ibegin(0) = isg
211  do ndiv = 0, ndivs-2
212  if(extent(ndiv) .LE. 0) call mpp_error( fatal, &
213  & 'mpp_compute_extent: domain extents must be positive definite.' )
214  iend(ndiv) = ibegin(ndiv) + extent(ndiv) - 1
215  ibegin(ndiv+1) = iend(ndiv) + 1
216  enddo
217  iend(ndivs-1) = ibegin(ndivs-1) + extent(ndivs-1) - 1
218  if(iend(ndivs-1) .NE. ieg) call mpp_error(fatal, &
219  & 'mpp_compute_extent: extent array limits do not match global domain.' )
220  else
221  do ndiv=0,ndivs-1
222  !modified for mirror-symmetry
223  !original line
224  ! ie = is + CEILING( float(ieg-is+1)/(ndivs-ndiv) ) - 1
225 
226  !problem of dividing nx points into n domains maintaining symmetry
227  !i.e nx=18 n=4 4554 and 5445 are solutions but 4455 is not.
228  !this will always work for nx even n even or odd
229  !this will always work for nx odd, n odd
230  !this will never work for nx odd, n even: for this case we supersede the mirror calculation
231  ! symmetrize = .NOT. ( mod(ndivs,2).EQ.0 .AND. mod(ieg-isg+1,2).EQ.1 )
232  !nx even n odd fails if n>nx/2
233  symmetrize = ( even(ndivs) .AND. even(ieg-isg+1) ) .OR. &
234  ( odd(ndivs) .AND. odd(ieg-isg+1) ) .OR. &
235  ( odd(ndivs) .AND. even(ieg-isg+1) .AND. ndivs.LT.(ieg-isg+1)/2 )
236 
237  !mirror domains are stored in the list and retrieved if required.
238  if( ndiv.EQ.0 )then
239  !initialize max points and max domains
240  imax = ieg
241  ndmax = ndivs
242  end if
243  !do bottom half of decomposition, going over the midpoint for odd ndivs
244  if( ndiv.LT.(ndivs-1)/2+1 )then
245  !domain is sized by dividing remaining points by remaining domains
246  ie = is + ceiling( real(imax-is+1)/(ndmax-ndiv) ) - 1
247  ndmirror = (ndivs-1) - ndiv !mirror domain
248  if( ndmirror.GT.ndiv .AND. symmetrize )then !only for domains over the midpoint
249  !mirror extents, the max(,) is to eliminate overlaps
250  ibegin(ndmirror) = max( isg+ieg-ie, ie+1 )
251  iend(ndmirror) = max( isg+ieg-is, ie+1 )
252  imax = ibegin(ndmirror) - 1
253  ndmax = ndmax - 1
254  end if
255  else
256  if( symmetrize )then
257  !do top half of decomposition by retrieving saved values
258  is = ibegin(ndiv)
259  ie = iend(ndiv)
260  else
261  ie = is + ceiling( real(imax-is+1)/(ndmax-ndiv) ) - 1
262  end if
263  end if
264  ibegin(ndiv) = is
265  iend(ndiv) = ie
266  if( ie.LT.is )call mpp_error( fatal, &
267  'MPP_DEFINE_DOMAINS(mpp_compute_extent): domain extents must be positive definite.' )
268  if( ndiv.EQ.ndivs-1 .AND. iend(ndiv).NE.ieg ) &
269  call mpp_error( fatal, 'mpp_compute_extent: domain extents do not span space completely.' )
270  is = ie + 1
271  end do
272  endif
273 
274 
275  end subroutine mpp_compute_extent
276 
277  !#####################################################################
278 
279 
280  !> Define data and computational domains on a 1D set of data (isg:ieg) and assign them to PEs
281  subroutine mpp_define_domains1d( global_indices, ndivs, domain, pelist, flags, halo, extent, maskmap, &
282  memory_size, begin_halo, end_halo )
283  integer, intent(in) :: global_indices(:) !< (/ isg, ieg /) gives the extent of global domain
284  integer, intent(in) :: ndivs !< number of divisions of domain: even divisions unless extent is present.
285  type(domain1d), intent(inout) :: domain !< the returned domain1D; declared inout so that
286  !! existing links, if any, can be nullified
287  integer, intent(in), optional :: pelist(0:) !< list of PEs to which domains are to be assigned
288  !! (default 0...npes-1); size of pelist must
289  !! correspond to number of mask=.TRUE. divisions
290  integer, intent(in), optional :: flags, halo !< flags define whether compute and data domains
291  !! are global (undecomposed) and whether the global
292  !! domain has periodic boundaries.
293  !! halo defines halo width (currently the same on both sides)
294  integer, intent(in), optional :: extent(0:) !< array extent; defines width of each division
295  !! (used for non-uniform domain decomp, for e.g load-balancing)
296  logical, intent(in), optional :: maskmap(0:) !< a division whose maskmap=.FALSE. is not
297  !! assigned to any domain. By default we assume
298  !! decomposition of compute and data domains, non-periodic boundaries,
299  !! no halo, as close to uniform extents as the
300  !! input parameters permit
301  integer, intent(in), optional :: memory_size
302  integer, intent(in), optional :: begin_halo, end_halo
303 
304  logical :: compute_domain_is_global, data_domain_is_global
305  integer :: ndiv, n, isg, ieg
306  integer, allocatable :: pes(:)
307  integer :: ibegin(0:ndivs-1), iend(0:ndivs-1)
308  logical :: mask(0:ndivs-1)
309  integer :: halosz, halobegin, haloend
310  integer :: errunit
311 
312  if( .NOT.module_is_initialized )call mpp_error( fatal, &
313  & 'MPP_DEFINE_DOMAINS1D: You must first call mpp_domains_init.' )
314  if(size(global_indices(:)) .NE. 2) call mpp_error(fatal,"mpp_define_domains1D: size of global_indices should be 2")
315  !get global indices
316  isg = global_indices(1)
317  ieg = global_indices(2)
318  if( ndivs.GT.ieg-isg+1 )call mpp_error( fatal, &
319  & 'MPP_DEFINE_DOMAINS1D: more divisions requested than rows available.' )
320  !get the list of PEs on which to assign domains; if pelist is absent use 0..npes-1
321  if( PRESENT(pelist) )then
322  if( .NOT.any(pelist.EQ.mpp_pe()) )then
323  errunit = stderr()
324  write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
325  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: pe must be in pelist.' )
326  end if
327  allocate( pes(0:size(pelist(:))-1) )
328  pes(:) = pelist(:)
329  else
330  allocate( pes(0:mpp_npes()-1) )
331  call mpp_get_current_pelist(pes)
332 ! pes(:) = (/ (i,i=0,mpp_npes()-1) /)
333  end if
334 
335  !get number of real domains: 1 mask domain per PE in pes
336  mask = .true. !default mask
337  if( PRESENT(maskmap) )then
338  if( size(maskmap(:)).NE.ndivs ) &
339  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: maskmap array size must equal number of domain divisions.' )
340  mask(:) = maskmap(:)
341  end if
342  if( count(mask).NE.size(pes(:)) ) &
343  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: number of TRUEs in maskmap array must match PE count.' )
344 
345  !get halosize
346  halosz = 0
347  if( PRESENT(halo) ) then
348  halosz = halo
349  !--- if halo is present, begin_halo and end_halo should not present
350  if(present(begin_halo) .OR. present(end_halo) ) call mpp_error(fatal, &
351  "mpp_domains_define.inc: when halo is present, begin_halo and end_halo should not present")
352  end if
353  halobegin = halosz; haloend = halosz
354  if(present(begin_halo)) halobegin = begin_halo
355  if(present(end_halo)) haloend = end_halo
356  halosz = max(halobegin, haloend)
357  !get flags
358  compute_domain_is_global = .false.
359  data_domain_is_global = .false.
360  domain%cyclic = .false.
361  domain%goffset = 1
362  domain%loffset = 1
363  if( PRESENT(flags) )then
364  !NEW: obsolete flag global_compute_domain, since ndivs is non-optional and you cannot
365  !have global compute and ndivs.NE.1
366  compute_domain_is_global = ndivs.EQ.1
367  !if compute domain is global, data domain must also be
368  data_domain_is_global = btest(flags,global) .OR. compute_domain_is_global
369  domain%cyclic = btest(flags,cyclic) .AND. halosz.NE.0
370  if(btest(flags,cyclic)) domain%goffset = 0
371  end if
372 
373  !set up links list
374  allocate( domain%list(0:ndivs-1) )
375 
376  !set global domain
377  domain%list(:)%global%begin = isg
378  domain%list(:)%global%end = ieg
379  domain%list(:)%global%size = ieg-isg+1
380  domain%list(:)%global%max_size = ieg-isg+1
381  domain%list(:)%global%is_global = .true. !always
382 
383  !get compute domain
384  if( compute_domain_is_global )then
385  domain%list(:)%compute%begin = isg
386  domain%list(:)%compute%end = ieg
387  domain%list(:)%compute%is_global = .true.
388  domain%list(:)%pe = pes(:)
389  domain%pos = 0
390  else
391  domain%list(:)%compute%is_global = .false.
392  n = 0
393  call mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
394  do ndiv=0,ndivs-1
395  domain%list(ndiv)%compute%begin = ibegin(ndiv)
396  domain%list(ndiv)%compute%end = iend(ndiv)
397  if( mask(ndiv) )then
398  domain%list(ndiv)%pe = pes(n)
399  if( mpp_pe().EQ.pes(n) )domain%pos = ndiv
400  n = n + 1
401  else
402  domain%list(ndiv)%pe = null_pe
403  end if
404  end do
405  end if
406 
407  domain%list(:)%compute%size = domain%list(:)%compute%end - domain%list(:)%compute%begin + 1
408 
409  !get data domain
410  !data domain is at least equal to compute domain
411  domain%list(:)%domain_data%begin = domain%list(:)%compute%begin
412  domain%list(:)%domain_data%end = domain%list(:)%compute%end
413  domain%list(:)%domain_data%is_global = .false.
414  !apply global flags
415  if( data_domain_is_global )then
416  domain%list(:)%domain_data%begin = isg
417  domain%list(:)%domain_data%end = ieg
418  domain%list(:)%domain_data%is_global = .true.
419  end if
420  !apply margins
421  domain%list(:)%domain_data%begin = domain%list(:)%domain_data%begin - halobegin
422  domain%list(:)%domain_data%end = domain%list(:)%domain_data%end + haloend
423  domain%list(:)%domain_data%size = domain%list(:)%domain_data%end - domain%list(:)%domain_data%begin + 1
424 
425  !--- define memory domain, if memory_size is not present or memory size is 0, memory domain size
426  !--- will be the same as data domain size. if momory_size is present, memory_size should greater than
427  !--- or equal to data size. The begin of memory domain will be always the same as data domain.
428  domain%list(:)%memory%begin = domain%list(:)%domain_data%begin
429  domain%list(:)%memory%end = domain%list(:)%domain_data%end
430  if( present(memory_size) ) then
431  if(memory_size > 0) then
432  if( domain%list(domain%pos)%domain_data%size > memory_size ) call mpp_error(fatal, &
433  "mpp_domains_define.inc: data domain size is larger than memory domain size on this pe")
434  domain%list(:)%memory%end = domain%list(:)%memory%begin + memory_size - 1
435  end if
436  end if
437  domain%list(:)%memory%size = domain%list(:)%memory%end - domain%list(:)%memory%begin + 1
438  domain%list(:)%memory%is_global = domain%list(:)%domain_data%is_global
439 
440  domain%compute = domain%list(domain%pos)%compute
441  domain%domain_data = domain%list(domain%pos)%domain_data
442  domain%global = domain%list(domain%pos)%global
443  domain%memory = domain%list(domain%pos)%memory
444  domain%compute%max_size = maxval( domain%list(:)%compute%size )
445  domain%domain_data%max_size = maxval( domain%list(:)%domain_data%size )
446  domain%global%max_size = domain%global%size
447  domain%memory%max_size = domain%memory%size
448 
449  !PV786667: the deallocate stmts can be removed when fixed (7.3.1.3m)
450  deallocate( pes )
451  return
452 
453  end subroutine mpp_define_domains1d
454 
455  !################################################################################
456  !> Define the layout for IO pe's for the given domain
457  subroutine mpp_define_io_domain(domain, io_layout)
458  type(domain2d), intent(inout) :: domain !< Input 2D domain
459  integer, intent(in ) :: io_layout(2) !< 2 value io pe layout to define
460  integer :: layout(2)
461  integer :: npes_in_group
462  type(domain2d), pointer :: io_domain=>null()
463  integer :: i, j, n, m
464  integer :: ipos, jpos, igroup, jgroup
465  integer :: ipos_beg, ipos_end, jpos_beg, jpos_end
466  integer :: whalo, ehalo, shalo, nhalo
467  integer :: npes_x, npes_y, ndivx, ndivy
468  integer, allocatable :: posarray(:,:)
469 
470  if(io_layout(1) * io_layout(2) .LE. 0) then
471  call mpp_error(note, &
472  "mpp_domains_define.inc(mpp_define_io_domain): io domain will not be defined for "//trim(domain%name)// &
473  " when one or both entry of io_layout is not positive")
474  return
475  endif
476 
477  layout(1) = size(domain%x(1)%list(:))
478  layout(2) = size(domain%y(1)%list(:))
479 
480  if(ASSOCIATED(domain%io_domain)) call mpp_error(fatal, &
481  "mpp_domains_define.inc(mpp_define_io_domain): io_domain is already defined")
482 
483  if(mod(layout(1), io_layout(1)) .NE. 0) call mpp_error(fatal, &
484  "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
485  & " domain layout(1) must be divided by io_layout(1)")
486  if(mod(layout(2), io_layout(2)) .NE. 0) call mpp_error(fatal, &
487  "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
488  & " domain layout(2) must be divided by io_layout(2)")
489  if(size(domain%x(:)) > 1) call mpp_error(fatal, &
490  "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
491  ": multiple tile per pe is not supported yet for this routine")
492 
493  if (associated(domain%io_domain)) deallocate(domain%io_domain) !< Check if associated
494  allocate(domain%io_domain)
495  domain%io_layout = io_layout
496  io_domain => domain%io_domain
497  ! Find how many processors are in the group with the consideration that some of the region maybe masked out.
498  npes_x = layout(1)/io_layout(1)
499  npes_y = layout(2)/io_layout(2)
500  ipos = mod(domain%x(1)%pos, npes_x)
501  jpos = mod(domain%y(1)%pos, npes_y)
502  igroup = domain%x(1)%pos/npes_x
503  jgroup = domain%y(1)%pos/npes_y
504  ipos_beg = igroup*npes_x; ipos_end = ipos_beg + npes_x - 1
505  jpos_beg = jgroup*npes_y; jpos_end = jpos_beg + npes_y - 1
506  npes_in_group = 0
507  do j = jpos_beg, jpos_end
508  do i = ipos_beg, ipos_end
509  if(domain%pearray(i,j) .NE. null_pe) npes_in_group = npes_in_group+1
510  enddo
511  enddo
512 
513  io_domain%whalo = domain%whalo
514  io_domain%ehalo = domain%ehalo
515  io_domain%shalo = domain%shalo
516  io_domain%nhalo = domain%nhalo
517  io_domain%ntiles = 1
518  io_domain%pe = domain%pe
519  io_domain%symmetry = domain%symmetry
520  if (associated(io_domain%list)) deallocate(io_domain%list) !< Check if associated
521  allocate(io_domain%list(0:npes_in_group-1))
522  do i = 0, npes_in_group-1
523  allocate( io_domain%list(i)%x(1), io_domain%list(i)%y(1), io_domain%list(i)%tile_id(1) )
524  enddo
525 
526  ndivx = size(domain%pearray,1)
527  ndivy = size(domain%pearray,2)
528  allocate(posarray(0:ndivx-1, 0:ndivy-1))
529  n = domain%tile_root_pe - mpp_root_pe()
530  posarray = -1
531  do j = 0,ndivy-1
532  do i = 0,ndivx-1
533  if( domain%pearray(i,j) == null_pe) cycle
534  posarray(i,j) = n
535  n = n + 1
536  enddo
537  enddo
538 
539  n = 0
540  do j = jpos_beg, jpos_end
541  do i = ipos_beg, ipos_end
542  if( domain%pearray(i,j) == null_pe) cycle
543  io_domain%list(n)%pe = domain%pearray(i,j)
544  m = posarray(i,j)
545  io_domain%list(n)%x(1)%compute = domain%list(m)%x(1)%compute
546  io_domain%list(n)%y(1)%compute = domain%list(m)%y(1)%compute
547  igroup = domain%list(m)%x(1)%pos/npes_x
548  jgroup = domain%list(m)%y(1)%pos/npes_y
549  io_domain%list(n)%tile_id(1) = jgroup*io_layout(1) + igroup
550  n = n + 1
551  enddo
552  enddo
553  deallocate(posarray)
554 
555  if (associated(io_domain%x)) deallocate(io_domain%x) !< Check if associated
556  if (associated(io_domain%y)) deallocate(io_domain%y) !< Check if associated
557  if (associated(io_domain%tile_id)) deallocate(io_domain%tile_id) !< Check if associated
558  allocate(io_domain%x(1), io_domain%y(1), io_domain%tile_id(1) )
559  allocate(io_domain%x(1)%list(0:npes_x-1), io_domain%y(1)%list(0:npes_y-1) )
560  n = -1
561  do j = jpos_beg, jpos_beg+jpos
562  do i = ipos_beg, ipos_beg+ipos
563  if(domain%pearray(i,j) .NE. null_pe) n = n + 1
564  enddo
565  enddo
566  io_domain%pos = n
567  io_domain%x(1)%compute = domain%x(1)%compute
568  io_domain%x(1)%domain_data = domain%x(1)%domain_data
569  io_domain%x(1)%memory = domain%x(1)%memory
570  io_domain%y(1)%compute = domain%y(1)%compute
571  io_domain%y(1)%domain_data = domain%y(1)%domain_data
572  io_domain%y(1)%memory = domain%y(1)%memory
573  io_domain%x(1)%global%begin = domain%x(1)%list(ipos_beg)%compute%begin
574  io_domain%x(1)%global%end = domain%x(1)%list(ipos_end)%compute%end
575  io_domain%x(1)%global%size = io_domain%x(1)%global%end - io_domain%x(1)%global%begin + 1
576  io_domain%x(1)%global%max_size = io_domain%x(1)%global%size
577  io_domain%y(1)%global%begin = domain%y(1)%list(jpos_beg)%compute%begin
578  io_domain%y(1)%global%end = domain%y(1)%list(jpos_end)%compute%end
579  io_domain%y(1)%global%size = io_domain%y(1)%global%end - io_domain%y(1)%global%begin + 1
580  io_domain%y(1)%global%max_size = io_domain%y(1)%global%size
581  io_domain%x(1)%pos = ipos
582  io_domain%y(1)%pos = jpos
583  io_domain%tile_id(1) = io_domain%list(n)%tile_id(1)
584  io_domain%tile_root_pe = io_domain%list(0)%pe
585 
586  !z1l
587 !!$ do j = 0, npes_y - 1
588 !!$ n = j*npes_x + ipos
589 !!$ io_domain%y(1)%list(j) = io_domain%list(n)%y(1)
590 !!$ enddo
591 !!$ do i = 0, npes_x - 1
592 !!$ n = jpos*npes_x + i
593 !!$ io_domain%x(1)%list(i) = io_domain%list(n)%x(1)
594 !!$ enddo
595 
596  whalo = domain%whalo
597  ehalo = domain%ehalo
598  shalo = domain%shalo
599  nhalo = domain%nhalo
600 
601  io_domain=>null()
602 
603 
604  end subroutine mpp_define_io_domain
605 
606  !> Define 2D data and computational domain on global rectilinear cartesian domain
607  !! (isg:ieg,jsg:jeg) and assign them to PEs
608  subroutine mpp_define_domains2d( global_indices, layout, domain, pelist, xflags, yflags, &
609  xhalo, yhalo, xextent, yextent, maskmap, name, symmetry, memory_size, &
610  whalo, ehalo, shalo, nhalo, is_mosaic, tile_count, tile_id, complete, x_cyclic_offset, y_cyclic_offset )
611  integer, intent(in) :: global_indices(:) !<(/ isg, ieg, jsg, jeg /)
612  integer, intent(in) :: layout(:) !< pe layout
613  type(domain2d), intent(inout) :: domain !< 2D domain decomposition to define
614  integer, intent(in), optional :: pelist(0:) !< current pelist to run on
615  integer, intent(in), optional :: xflags, yflags !< directional flag
616  integer, intent(in), optional :: xhalo, yhalo !< halo sizes for x and y indices
617  integer, intent(in), optional :: xextent(0:), yextent(0:)
618  logical, intent(in), optional :: maskmap(0:,0:)
619  character(len=*), intent(in), optional :: name
620  logical, intent(in), optional :: symmetry
621  logical, intent(in), optional :: is_mosaic !< indicate if calling mpp_define_domains
622  !! from mpp_define_mosaic.
623  integer, intent(in), optional :: memory_size(:)
624  integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size for West, East,
625  !! South and North direction.
626  !! if whalo and ehalo is not present,
627  !! will take the value of xhalo
628  !! if shalo and nhalo is not present,
629  !! will take the value of yhalo
630  integer, intent(in), optional :: tile_count !< tile number on current pe,
631  !! default value is 1.
632  !! this is for the situation that
633  !! multiple tiles on one processor
634  integer, intent(in), optional :: tile_id !< tile id
635  logical, intent(in), optional :: complete !< true indicate mpp_define_domain
636  !! is completed for mosaic definition.
637  integer, intent(in), optional :: x_cyclic_offset !< offset for x-cyclic boundary condition,
638  !! (0,j) = (ni, mod(j+x_cyclic_offset,nj))
639  !! (ni+1, j)=(1 ,mod(j+nj-x_cyclic_offset,nj))
640  integer, intent(in), optional :: y_cyclic_offset !< offset for y-cyclic boundary condition
641  !!(i,0) = (mod(i+y_cyclic_offset,ni), nj))
642  !!(i,nj+1) =(mod(mod(i+ni-y_cyclic_offset,ni),
643  !! 1) )
644 
645  integer :: i, j, m, n, xhalosz, yhalosz, memory_xsize, memory_ysize
646  integer :: whalosz, ehalosz, shalosz, nhalosz
647  integer :: ipos, jpos, pos, tile, nlist, cur_tile_id, cur_comm_id
648  integer :: ndivx, ndivy, isg, ieg, jsg, jeg, ishift, jshift, errunit, logunit
649  integer :: x_offset, y_offset, start_pos, nfold
650  logical :: from_mosaic, is_complete
651  logical :: mask(0:layout(1)-1,0:layout(2)-1)
652  integer, allocatable :: pes(:), pesall(:)
653  integer :: pearray(0:layout(1)-1,0:layout(2)-1)
654  integer :: ibegin(0:layout(1)-1), iend(0:layout(1)-1)
655  integer :: jbegin(0:layout(2)-1), jend(0:layout(2)-1)
656  character(len=8) :: text
657  type(overlapspec), pointer :: check_T => null()
658  integer :: outunit
659  logical :: send(8), recv(8)
660 
661  outunit = stdout()
662  if( .NOT.module_is_initialized )call mpp_error( fatal, &
663  & 'MPP_DEFINE_DOMAINS2D: You must first call mpp_domains_init.' )
664  if(PRESENT(name)) then
665  if(len_trim(name) > name_length) call mpp_error(fatal, &
666  "mpp_domains_define.inc(mpp_define_domains2D): the len_trim of optional argument name ="//trim(name)// &
667  " is greater than NAME_LENGTH, change the argument name or increase NAME_LENGTH")
668  domain%name = name
669  endif
670  if(size(global_indices(:)) .NE. 4) call mpp_error(fatal, &
671  "mpp_define_domains2D: size of global_indices should be 4 for "//trim(domain%name) )
672  if(size(layout(:)) .NE. 2) call mpp_error(fatal,"mpp_define_domains2D: size of layout should be 2 for "// &
673  & trim(domain%name) )
674 
675  ndivx = layout(1); ndivy = layout(2)
676  isg = global_indices(1); ieg = global_indices(2); jsg = global_indices(3); jeg = global_indices(4)
677 
678  from_mosaic = .false.
679  if(present(is_mosaic)) from_mosaic = is_mosaic
680  is_complete = .true.
681  if(present(complete)) is_complete = complete
682  tile = 1
683  if(present(tile_count)) tile = tile_count
684  cur_tile_id = 1
685  if(present(tile_id)) cur_tile_id = tile_id
686 
687  cur_comm_id=0
688  if( PRESENT(pelist) )then
689  allocate( pes(0:size(pelist(:))-1) )
690  pes = pelist
691  if(from_mosaic) then
692  allocate( pesall(0:mpp_npes()-1) )
693  call mpp_get_current_pelist(pesall, commid=cur_comm_id)
694  else
695  allocate( pesall(0:size(pes(:))-1) )
696  pesall = pes
697  call mpp_get_current_pelist(pesall, commid=cur_comm_id)
698  end if
699  else
700  allocate( pes(0:mpp_npes()-1) )
701  allocate( pesall(0:mpp_npes()-1) )
702  call mpp_get_current_pelist(pes, commid=cur_comm_id)
703  pesall = pes
704  end if
705 
706  !--- at least of one of x_cyclic_offset and y_cyclic_offset must be zero
707  !--- folded boundary condition is not supported when either x_cyclic_offset or y_cyclic_offset is nonzero.
708  !--- Since we only implemented Folded-north boundary condition currently, we only consider y-flags.
709  x_offset = 0; y_offset = 0
710  if(PRESENT(x_cyclic_offset)) x_offset = x_cyclic_offset
711  if(PRESENT(y_cyclic_offset)) y_offset = y_cyclic_offset
712  if(x_offset*y_offset .NE. 0) call mpp_error(fatal, &
713  'MPP_DEFINE_DOMAINS2D: At least one of x_cyclic_offset and y_cyclic_offset must be zero for '// &
714  & trim(domain%name))
715 
716  !--- x_cyclic_offset and y_cyclic_offset should no larger than the global grid size.
717  if(abs(x_offset) > jeg-jsg+1) call mpp_error(fatal, &
718  'MPP_DEFINE_DOMAINS2D: absolute value of x_cyclic_offset is greater than jeg-jsg+1 for '//trim(domain%name))
719  if(abs(y_offset) > ieg-isg+1) call mpp_error(fatal, &
720  'MPP_DEFINE_DOMAINS2D: absolute value of y_cyclic_offset is greater than ieg-isg+1 for '//trim(domain%name))
721 
722  !--- when there is more than one tile on one processor, all the tile will limited on this processor
723  if( tile > 1 .AND. size(pes(:)) > 1) call mpp_error(fatal, &
724  'MPP_DEFINE_DOMAINS2D: there are more than one tile on this pe, '// &
725  'all the tile should be limited on this pe for '//trim(domain%name))
726 
727  !--- the position of current pe is changed due to mosaic, because pes
728  !--- is only part of the pelist in mosaic (pesall). We assume the pe
729  !--- distribution are contious in mosaic.
730  pos = -1
731  do n = 0, size(pesall(:))-1
732  if(pesall(n) == mpp_pe() ) then
733  pos = n
734  exit
735  endif
736  enddo
737  if(pos<0) call mpp_error(fatal, 'MPP_DEFINE_DOMAINS2D: mpp_pe() is not in the pesall list')
738 
739  domain%symmetry = .false.
740  if(present(symmetry)) domain%symmetry = symmetry
741  if(domain%symmetry) then
742  ishift = 1; jshift = 1
743  else
744  ishift = 0; jshift = 0
745  end if
746 
747  !--- first compute domain decomposition.
748  call mpp_compute_extent(isg, ieg, ndivx, ibegin, iend, xextent)
749  call mpp_compute_extent(jsg, jeg, ndivy, jbegin, jend, yextent)
750 
751  xhalosz = 0; yhalosz = 0
752  if(present(xhalo)) xhalosz = xhalo
753  if(present(yhalo)) yhalosz = yhalo
754  whalosz = xhalosz; ehalosz = xhalosz
755  shalosz = yhalosz; nhalosz = yhalosz
756  if(present(whalo)) whalosz = whalo
757  if(present(ehalo)) ehalosz = ehalo
758  if(present(shalo)) shalosz = shalo
759  if(present(nhalo)) nhalosz = nhalo
760 
761  !--- configure maskmap
762  mask = .true.
763  if( PRESENT(maskmap) )then
764  if( size(maskmap,1).NE.ndivx .OR. size(maskmap,2).NE.ndivy ) &
765  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS2D: maskmap array does not match layout for '// &
766  & trim(domain%name) )
767  mask(:,:) = maskmap(:,:)
768  end if
769  !number of unmask domains in layout must equal number of PEs assigned
770  n = count(mask)
771  if( n.NE.size(pes(:)) )then
772  write( text,'(i8)' )n
773  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS2D: incorrect number of PEs assigned for ' // &
774  'this layout and maskmap. Use '//text//' PEs for this domain decomposition for '//trim(domain%name) )
775  end if
776 
777  memory_xsize = 0; memory_ysize = 0
778  if(present(memory_size)) then
779  if(size(memory_size(:)) .NE. 2) call mpp_error(fatal, &
780  "mpp_define_domains2D: size of memory_size should be 2 for "//trim(domain%name))
781  memory_xsize = memory_size(1)
782  memory_ysize = memory_size(2)
783  end if
784 
785  !--- set up domain%list.
786  !--- set up 2-D domain decomposition for T, E, C, N and computing overlapping
787  !--- when current tile is the last tile in the mosaic.
788  nlist = size(pesall(:))
789  if( .NOT. Associated(domain%x) ) then
790  allocate(domain%tileList(1))
791  domain%tileList(1)%xbegin = global_indices(1)
792  domain%tileList(1)%xend = global_indices(2)
793  domain%tileList(1)%ybegin = global_indices(3)
794  domain%tileList(1)%yend = global_indices(4)
795  allocate(domain%x(1), domain%y(1) )
796  allocate(domain%tile_id(1))
797  allocate(domain%tile_id_all(1))
798  domain%tile_id = cur_tile_id
799  domain%tile_id_all = cur_tile_id
800  domain%tile_comm_id = cur_comm_id
801  domain%ntiles = 1
802  domain%max_ntile_pe = 1
803  domain%ncontacts = 0
804  domain%rotated_ninety = .false.
805  allocate( domain%list(0:nlist-1) )
806  do i = 0, nlist-1
807  allocate( domain%list(i)%x(1), domain%list(i)%y(1), domain%list(i)%tile_id(1))
808  end do
809  end if
810 
811  domain%initialized = .true.
812 
813  start_pos = 0
814  do n = 0, nlist-1
815  if(pesall(n) == pes(0)) then
816  start_pos = n
817  exit
818  endif
819  enddo
820 
821  !place on PE array; need flag to assign them to j first and then i
822  pearray(:,:) = null_pe
823  ipos = null_pe; jpos = null_pe
824  n = 0
825  m = start_pos
826  do j = 0,ndivy-1
827  do i = 0,ndivx-1
828  if( mask(i,j) )then
829  pearray(i,j) = pes(n)
830  domain%list(m)%x(tile)%compute%begin = ibegin(i)
831  domain%list(m)%x(tile)%compute%end = iend(i)
832  domain%list(m)%y(tile)%compute%begin = jbegin(j)
833  domain%list(m)%y(tile)%compute%end = jend(j)
834  domain%list(m)%x(tile)%compute%size = domain%list(m)%x(tile)%compute%end &
835  & - domain%list(m)%x(tile)%compute%begin + 1
836  domain%list(m)%y(tile)%compute%size = domain%list(m)%y(tile)%compute%end &
837  & - domain%list(m)%y(tile)%compute%begin + 1
838  domain%list(m)%tile_id(tile) = cur_tile_id
839  domain%list(m)%x(tile)%pos = i
840  domain%list(m)%y(tile)%pos = j
841  domain%list(m)%tile_root_pe = pes(0)
842  domain%list(m)%pe = pesall(m)
843 
844  if( pes(n).EQ.mpp_pe() )then
845  ipos = i
846  jpos = j
847  end if
848  n = n + 1
849  m = m + 1
850  end if
851  end do
852  end do
853 
854  !Considering mosaic, the following will only be done on the pe in the pelist
855  !when there is only one tile, all the current pe will be in the pelist.
856  if( any(pes == mpp_pe()) ) then
857  domain%io_layout = layout
858  domain%tile_root_pe = pes(0)
859  domain%comm_id = cur_comm_id
860  if( ipos.EQ.null_pe .OR. jpos.EQ.null_pe ) &
861  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS2D: pelist must include this PE for '//trim(domain%name) )
862  if( debug ) then
863  errunit = stderr()
864  write( errunit, * )'pe, tile, ipos, jpos=', mpp_pe(), tile, ipos, jpos, ' pearray(:,jpos)=', &
865  pearray(:,jpos), ' pearray(ipos,:)=', pearray(ipos,:)
866  endif
867 
868  !--- when tile is not equal to 1, the layout for that tile always ( 1, 1), so no need for pearray in domain
869  if( tile == 1 ) then
870  if (associated(domain%pearray)) deallocate(domain%pearray) !< Check if allocated
871  allocate( domain%pearray(0:ndivx-1,0:ndivy-1) )
872  domain%pearray = pearray
873  end if
874 
875  domain%pe = mpp_pe()
876  domain%pos = pos
877  domain_cnt = domain_cnt + int(1,kind=i8_kind)
878  domain%id = domain_cnt*domain_id_base ! Must be i8_kind arithmetic
879 
880  !do domain decomposition using 1D versions in X and Y,
881  call mpp_define_domains( global_indices(1:2), ndivx, domain%x(tile), &
882  pack(pearray(:,jpos),mask(:,jpos)), xflags, xhalo, xextent, mask(:,jpos), memory_xsize, whalo, ehalo )
883  call mpp_define_domains( global_indices(3:4), ndivy, domain%y(tile), &
884  pack(pearray(ipos,:),mask(ipos,:)), yflags, yhalo, yextent, mask(ipos,:), memory_ysize, shalo, nhalo )
885  if( domain%x(tile)%list(ipos)%pe.NE.domain%y(tile)%list(jpos)%pe ) &
886  call mpp_error( fatal, .NE.'MPP_DEFINE_DOMAINS2D: domain%x%list(ipos)%pedomain%y%list(jpos)%pe.' )
887 
888  !--- when x_cyclic_offset or y_cyclic_offset is set, no cross domain is allowed
889  if(x_offset .NE. 0 .OR. y_offset .NE. 0) then
890  if(whalosz .GT. domain%x(tile)%compute%size .OR. ehalosz .GT. domain%x(tile)%compute%size ) &
891  call mpp_error(fatal, "mpp_define_domains_2d: when x_cyclic_offset/y_cyclic_offset is set, "// &
892  "whalo and ehalo must be no larger than the x-direction computation domain size")
893  if(shalosz .GT. domain%y(tile)%compute%size .OR. nhalosz .GT. domain%y(tile)%compute%size ) &
894  call mpp_error(fatal, "mpp_define_domains_2d: when x_cyclic_offset/y_cyclic_offset is set, "// &
895  "shalo and nhalo must be no larger than the y-direction computation domain size")
896  endif
897 
898  !--- restrict the halo size is no larger than global domain size.
899  if(whalosz .GT. domain%x(tile)%global%size) &
900  call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: whalo is greather global domain size")
901  if(ehalosz .GT. domain%x(tile)%global%size) &
902  call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: ehalo is greather global domain size")
903  if(shalosz .GT. domain%x(tile)%global%size) &
904  call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: shalo is greather global domain size")
905  if(nhalosz .GT. domain%x(tile)%global%size) &
906  call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: nhalo is greather global domain size")
907 
908  !set up fold, when the boundary is folded, there is only one tile.
909  domain%fold = 0
910  nfold = 0
911  if( PRESENT(xflags) )then
912  if( btest(xflags,west) ) then
913  !--- make sure no cross-domain in y-direction
914  if(domain%x(tile)%domain_data%begin .LE. domain%x(tile)%global%begin .AND. &
915  domain%x(tile)%compute%begin > domain%x(tile)%global%begin ) then
916  call mpp_error(fatal, &
917  'MPP_DEFINE_DOMAINS: the domain could not be crossed when west is folded')
918  endif
919  if( domain%x(tile)%cyclic )call mpp_error( fatal, &
920  'MPP_DEFINE_DOMAINS: an axis cannot be both folded west and cyclic for '//trim(domain%name) )
921  domain%fold = domain%fold + fold_west_edge
922  nfold = nfold+1
923  endif
924  if( btest(xflags,east) ) then
925  !--- make sure no cross-domain in y-direction
926  if(domain%x(tile)%domain_data%end .GE. domain%x(tile)%global%end .AND. &
927  domain%x(tile)%compute%end < domain%x(tile)%global%end ) then
928  call mpp_error(fatal, &
929  'MPP_DEFINE_DOMAINS: the domain could not be crossed when north is folded')
930  endif
931  if( domain%x(tile)%cyclic )call mpp_error( fatal, &
932  'MPP_DEFINE_DOMAINS: an axis cannot be both folded east and cyclic for '//trim(domain%name) )
933  domain%fold = domain%fold + fold_east_edge
934  nfold = nfold+1
935  endif
936  endif
937  if( PRESENT(yflags) )then
938  if( btest(yflags,south) ) then
939  !--- make sure no cross-domain in y-direction
940  if(domain%y(tile)%domain_data%begin .LE. domain%y(tile)%global%begin .AND. &
941  domain%y(tile)%compute%begin > domain%y(tile)%global%begin ) then
942  call mpp_error(fatal, &
943  'MPP_DEFINE_DOMAINS: the domain could not be crossed when south is folded')
944  endif
945  if( domain%y(tile)%cyclic )call mpp_error( fatal, &
946  'MPP_DEFINE_DOMAINS: an axis cannot be both folded north and cyclic for '//trim(domain%name))
947  domain%fold = domain%fold + fold_south_edge
948  nfold = nfold+1
949  endif
950  if( btest(yflags,north) ) then
951  !--- when the halo size is big and halo region is crossing neighbor domain, we
952  !--- restrict the halo size is less than half of the global size.
953  if(whalosz .GT. domain%x(tile)%compute%size .AND. whalosz .GE. domain%x(tile)%global%size/2 ) &
954  call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, whalo compute domain size "// &
955  .GE."and whalo half of global domain size")
956  if(ehalosz .GT. domain%x(tile)%compute%size .AND. ehalosz .GE. domain%x(tile)%global%size/2 ) &
957  call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, ehalo is compute domain size "// &
958  .GE."and ehalo half of global domain size")
959  if(shalosz .GT. domain%y(tile)%compute%size .AND. shalosz .GE. domain%x(tile)%global%size/2 ) &
960  call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, shalo compute domain size "// &
961  .GE."and shalo half of global domain size")
962  if(nhalosz .GT. domain%y(tile)%compute%size .AND. nhalosz .GE. domain%x(tile)%global%size/2 ) &
963  call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, nhalo compute domain size "// &
964  .GE."and nhalo half of global domain size")
965 
966 
967  if( domain%y(tile)%cyclic )call mpp_error( fatal, &
968  'MPP_DEFINE_DOMAINS: an axis cannot be both folded south and cyclic for '//trim(domain%name) )
969  domain%fold = domain%fold + fold_north_edge
970  nfold = nfold+1
971  endif
972  endif
973  if(nfold > 1) call mpp_error(fatal, &
974  'MPP_DEFINE_DOMAINS2D: number of folded edge is greater than 1 for '//trim(domain%name) )
975 
976  if(nfold == 1) then
977  if( x_offset .NE. 0 .OR. y_offset .NE. 0) call mpp_error(fatal, &
978  'MPP_DEFINE_DOMAINS2D: For the foled_north/folded_south/fold_east/folded_west boundary condition, '//&
979  'x_cyclic_offset and y_cyclic_offset must be zero for '//trim(domain%name))
980  endif
981  if( btest(domain%fold,south) .OR. btest(domain%fold,north) )then
982  if( domain%y(tile)%cyclic )call mpp_error( fatal, &
983  'MPP_DEFINE_DOMAINS: an axis cannot be both folded and cyclic for '//trim(domain%name) )
984  if( modulo(domain%x(tile)%global%size,2).NE.0 ) &
985  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: number of points in X must be even ' // &
986  'when there is a fold in Y for '//trim(domain%name) )
987  !check if folded domain boundaries line up in X: compute domains lining up is a sufficient
988  !condition for symmetry
989  n = ndivx - 1
990  do i = 0,n/2
991  if( domain%x(tile)%list(i)%compute%size.NE.domain%x(tile)%list(n-i)%compute%size ) &
992  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: Folded domain boundaries ' // &
993  'must line up (mirror-symmetric extents) for '//trim(domain%name) )
994  end do
995  end if
996  if( btest(domain%fold,west) .OR. btest(domain%fold,east) )then
997  if( domain%x(tile)%cyclic )call mpp_error( fatal, &
998  'MPP_DEFINE_DOMAINS: an axis cannot be both folded and cyclic for '//trim(domain%name) )
999  if( modulo(domain%y(tile)%global%size,2).NE.0 ) &
1000  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: number of points in Y must be even '//&
1001  'when there is a fold in X for '//trim(domain%name) )
1002  !check if folded domain boundaries line up in Y: compute domains lining up is a sufficient
1003  !condition for symmetry
1004  n = ndivy - 1
1005  do i = 0,n/2
1006  if( domain%y(tile)%list(i)%compute%size.NE.domain%y(tile)%list(n-i)%compute%size ) &
1007  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: Folded domain boundaries must '//&
1008  'line up (mirror-symmetric extents) for '//trim(domain%name) )
1009  end do
1010  end if
1011 
1012  !set up domain%list
1013  if( mpp_pe().EQ.pes(0) .AND. PRESENT(name) )then
1014  logunit = stdlog()
1015  write( logunit, '(/a,i5,a,i5)' )trim(name)//' domain decomposition: ', ndivx, ' X', ndivy
1016  write( logunit, '(3x,a)' )'pe, is, ie, js, je, isd, ied, jsd, jed'
1017  end if
1018  end if ! if( ANY(pes == mpp_pe()) )
1019 
1020  if(is_complete) then
1021  domain%whalo = whalosz; domain%ehalo = ehalosz
1022  domain%shalo = shalosz; domain%nhalo = nhalosz
1023  if (associated(domain%update_T)) deallocate(domain%update_T) !< Check if associated
1024  if (associated(domain%update_E)) deallocate(domain%update_E) !< Check if associated
1025  if (associated(domain%update_C)) deallocate(domain%update_C) !< Check if associated
1026  if (associated(domain%update_N)) deallocate(domain%update_N) !< Check if associated
1027  allocate(domain%update_T, domain%update_E, domain%update_C, domain%update_N)
1028  domain%update_T%next => null()
1029  domain%update_E%next => null()
1030  domain%update_C%next => null()
1031  domain%update_N%next => null()
1032  if (associated(domain%check_E)) deallocate(domain%check_E) !< Check if associated
1033  if (associated(domain%check_C)) deallocate(domain%check_C) !< Check if associated
1034  if (associated(domain%check_N)) deallocate(domain%check_N) !< Check if associated
1035  allocate(domain%check_E, domain%check_C, domain%check_N )
1036  domain%update_T%nsend = 0
1037  domain%update_T%nrecv = 0
1038  domain%update_C%nsend = 0
1039  domain%update_C%nrecv = 0
1040  domain%update_E%nsend = 0
1041  domain%update_E%nrecv = 0
1042  domain%update_N%nsend = 0
1043  domain%update_N%nrecv = 0
1044 
1045  if( btest(domain%fold,south) ) then
1046  call compute_overlaps_fold_south(domain, center, 0, 0)
1047  call compute_overlaps_fold_south(domain, corner, ishift, jshift)
1048  call compute_overlaps_fold_south(domain, east, ishift, 0)
1049  call compute_overlaps_fold_south(domain, north, 0, jshift)
1050  else if( btest(domain%fold,west) ) then
1051  call compute_overlaps_fold_west(domain, center, 0, 0)
1052  call compute_overlaps_fold_west(domain, corner, ishift, jshift)
1053  call compute_overlaps_fold_west(domain, east, ishift, 0)
1054  call compute_overlaps_fold_west(domain, north, 0, jshift)
1055  else if( btest(domain%fold,east) ) then
1056  call compute_overlaps_fold_east(domain, center, 0, 0)
1057  call compute_overlaps_fold_east(domain, corner, ishift, jshift)
1058  call compute_overlaps_fold_east(domain, east, ishift, 0)
1059  call compute_overlaps_fold_east(domain, north, 0, jshift)
1060  else
1061  call compute_overlaps(domain, center, domain%update_T, check_t, 0, 0, x_offset, y_offset, &
1062  domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1063  call compute_overlaps(domain, corner, domain%update_C, domain%check_C, ishift, jshift, x_offset, y_offset, &
1064  domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1065  call compute_overlaps(domain, east, domain%update_E, domain%check_E, ishift, 0, x_offset, y_offset, &
1066  domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1067  call compute_overlaps(domain, north, domain%update_N, domain%check_N, 0, jshift, x_offset, y_offset, &
1068  domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1069  endif
1070  call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_domains")
1071  call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_domains")
1072  call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_domains")
1073  call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_domains")
1074 
1075 
1076  !--- when ncontacts is nonzero, set_check_overlap will be called in mpp_define
1077  if(domain%symmetry .AND. (domain%ncontacts == 0 .OR. domain%ntiles == 1) ) then
1078  call set_check_overlap( domain, corner )
1079  call set_check_overlap( domain, east )
1080  call set_check_overlap( domain, north )
1081  if (associated(domain%bound_E)) deallocate(domain%bound_E) !< Check if associated
1082  if (associated(domain%bound_C)) deallocate(domain%bound_C) !< Check if associated
1083  if (associated(domain%bound_N)) deallocate(domain%bound_N) !< Check if associated
1084  allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1085  call set_bound_overlap( domain, corner )
1086  call set_bound_overlap( domain, east )
1087  call set_bound_overlap( domain, north )
1088  end if
1089  call set_domain_comm_inf(domain%update_T)
1090  call set_domain_comm_inf(domain%update_E)
1091  call set_domain_comm_inf(domain%update_C)
1092  call set_domain_comm_inf(domain%update_N)
1093  end if
1094 
1095  !--- check the send and recv size are matching.
1096  !--- or ntiles>1 mosaic,
1097  !--- the check will be done in mpp_define_mosaic
1098  if(debug_message_passing .and. (domain%ncontacts == 0 .OR. domain%ntiles == 1) ) then
1099  send = .true.
1100  recv = .true.
1101  call check_message_size(domain, domain%update_T, send, recv, 'T')
1102  call check_message_size(domain, domain%update_E, send, recv, 'E')
1103  call check_message_size(domain, domain%update_C, send, recv, 'C')
1104  call check_message_size(domain, domain%update_N, send, recv, 'N')
1105  endif
1106 
1107 
1108  !print out decomposition, this didn't consider maskmap.
1109  if( mpp_pe() .EQ. pes(0) .AND. PRESENT(name) )then
1110  write(*,*) trim(name)//' domain decomposition'
1111  write(*,'(a,i4,a,i4,a,i4,a,i4)')'whalo = ', whalosz, ", ehalo = ", ehalosz, ", shalo = ", shalosz, &
1112  & ", nhalo = ", nhalosz
1113  write (*,110) (domain%x(1)%list(i)%compute%size, i= 0, layout(1)-1)
1114  write (*,120) (domain%y(1)%list(i)%compute%size, i= 0, layout(2)-1)
1115 110 format (' X-AXIS = ',24i4,/,(11x,24i4))
1116 120 format (' Y-AXIS = ',24i4,/,(11x,24i4))
1117  endif
1118 
1119  deallocate( pes, pesall)
1120 
1121 
1122  return
1123 end subroutine mpp_define_domains2d
1124 
1125 
1126 !#####################################################################
1127 subroutine check_message_size(domain, update, send, recv, position)
1128  type(domain2d), intent(in) :: domain
1129  type(overlapspec), intent(in) :: update
1130  logical, intent(in) :: send(:)
1131  logical, intent(in) :: recv(:)
1132  character, intent(in) :: position
1133 
1134  integer, dimension(0:size(domain%list(:))-1) :: msg1, msg2, msg3
1135  integer :: m, n, l, dir, is, ie, js, je, from_pe, msgsize
1136  integer :: nlist
1137 
1138  nlist = size(domain%list(:))
1139 
1140 
1141  msg1 = 0
1142  msg2 = 0
1143  do m = 1, update%nrecv
1144  msgsize = 0
1145  do n = 1, update%recv(m)%count
1146  dir = update%recv(m)%dir(n)
1147  if( recv(dir) ) then
1148  is = update%recv(m)%is(n); ie = update%recv(m)%ie(n)
1149  js = update%recv(m)%js(n); je = update%recv(m)%je(n)
1150  msgsize = msgsize + (ie-is+1)*(je-js+1)
1151  endif
1152  end do
1153  from_pe = update%recv(m)%pe
1154  l = from_pe-mpp_root_pe()
1155  call mpp_recv( msg1(l), glen=1, from_pe=from_pe, block=.false., tag=comm_tag_1)
1156  msg2(l) = msgsize
1157  enddo
1158 
1159  do m = 1, update%nsend
1160  msgsize = 0
1161  do n = 1, update%send(m)%count
1162  dir = update%send(m)%dir(n)
1163  if(send(dir))then
1164  is = update%send(m)%is(n); ie = update%send(m)%ie(n)
1165  js = update%send(m)%js(n); je = update%send(m)%je(n)
1166  msgsize = msgsize + (ie-is+1)*(je-js+1)
1167  endif
1168  end do
1169  l = update%send(m)%pe-mpp_root_pe()
1170  msg3(l) = msgsize
1171  call mpp_send( msg3(l), plen=1, to_pe=update%send(m)%pe, tag=comm_tag_1)
1172  enddo
1173  call mpp_sync_self(check=event_recv)
1174 
1175  do m = 0, nlist-1
1176  if(msg1(m) .NE. msg2(m)) then
1177  print*, "My pe = ", mpp_pe(), ",domain name =", trim(domain%name), ",at position=",position,",from pe=", &
1178  domain%list(m)%pe, ":send size = ", msg1(m), ", recv size = ", msg2(m)
1179  call mpp_error(fatal, "mpp_define_domains2D: mismatch on send and recv size")
1180  endif
1181  enddo
1182  call mpp_sync_self()
1183 
1184 
1185 end subroutine check_message_size
1186 
1187  !#####################################################################
1188 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1189 ! !
1190 ! MPP_define_mosaic: define mosaic domain !
1191 ! NOTE: xflags and yflags is not in mpp_define_mosaic, because such relation !
1192 ! are already defined in the mosaic relation. !
1193 ! !
1194 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1195 !??? do we need optional argument xextent and yextent
1196 !??? how to specify pelist, we may use two dimensional variable pelist to represent.
1197 !z1l: We assume the tilelist are in always limited to 1, 2, ... num_tile. If we want
1198 ! to remove this limitation, we need to add one more argument tilelist.
1199 
1200  !> Defines a domain for mosaic tile grids
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
1229 
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(:)
1240  integer :: outunit
1241  logical :: send(8), recv(8)
1242 
1243  outunit = stdout()
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')
1256 
1257  !--- setup pelist for the mosaic ---------------------
1258  nlist = mpp_npes()
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')
1263  pes = pelist
1264  end if
1265  call mpp_get_current_pelist(pes, commid=domain%comm_id)
1266  !--- pelist should be monotonic increasing by 1.
1267  do n = 1, nlist-1
1268  if(pes(n) - pes(n-1) .NE. 1) call mpp_error(fatal, &
1269  'mpp_domains_define.inc: pelist is not monotonic increasing by 1')
1270  end do
1271 
1272  is_symmetry = .false.
1273  if(present(symmetry)) is_symmetry = symmetry
1274 
1275  if(size(pe_start(:)) .NE. num_tile .OR. size(pe_end(:)) .NE. num_tile ) call mpp_error(fatal, &
1276  'mpp_domains_define.inc: size of pe_start and/or pe_end is not equal num_tile')
1277  !--- make sure pe_start and pe_end is in the pelist.
1278  if( any( pe_start < pes(0) ) ) call mpp_error(fatal, &
1279  & 'mpp_domains_define.inc: not all the pe_start are in the pelist')
1280  if( any( pe_end > pes(nlist-1)) ) call mpp_error(fatal, &
1281  & 'mpp_domains_define.inc: not all the pe_end are in the pelist')
1282 
1283  !--- calculate number of tiles on each pe.
1284  allocate( ntile_per_pe(0:nlist-1) )
1285  ntile_per_pe = 0
1286  do n = 1, num_tile
1287  do m = pe_start(n) - mpp_root_pe(), pe_end(n) - mpp_root_pe()
1288  ntile_per_pe(m) = ntile_per_pe(m) + 1
1289  end do
1290  end do
1291  if(any(ntile_per_pe == 0)) call mpp_error(fatal, &
1292  'mpp_domains_define.inc: At least one pe in pelist is not used by any tile in the mosaic')
1293 
1294  !--- check the size comformable of xextent and yextent
1295  if( PRESENT(xextent) ) then
1296  if(size(xextent,1) .GT. maxval(layout(1,:)) ) call mpp_error(fatal, &
1297  'mpp_domains_define.inc: size mismatch between xextent and layout')
1298  if(size(xextent,2) .NE. num_tile) call mpp_error(fatal, &
1299  'mpp_domains_define.inc: size of xextent is not eqaul num_tile')
1300  end if
1301  if( PRESENT(yextent) ) then
1302  if(size(yextent,1) .GT. maxval(layout(2,:)) ) call mpp_error(fatal, &
1303  'mpp_domains_define.inc: size mismatch between yextent and layout')
1304  if(size(yextent,2) .NE. num_tile) call mpp_error(fatal, &
1305  'mpp_domains_define.inc: size of yextent is not eqaul num_tile')
1306  end if
1307 
1308  !--- check the size comformable of maskmap
1309  !--- since the layout is different between tiles, so the actual size of maskmap for each tile is
1310  !--- not diffrent. When define maskmap for multiple tiles, user can choose the maximum value
1311  !--- of layout of all tiles to the first and second dimension of maskmap.
1312  if(present(maskmap)) then
1313  if(size(maskmap,1) .GT. maxval(layout(1,:)) .or. size(maskmap,2) .GT. maxval(layout(2,:))) &
1314  call mpp_error(fatal, 'mpp_domains_define.inc: size mismatch between maskmap and layout')
1315  if(size(maskmap,3) .NE. num_tile) call mpp_error(fatal, &
1316  'mpp_domains_define.inc: the third dimension of maskmap is not equal num_tile')
1317  end if
1318 
1319  if (associated(domain%tileList)) deallocate(domain%tileList) !< Check if associated
1320  allocate(domain%tileList(num_tile))
1321  do n = 1, 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)
1326  enddo
1327  !--- define some mosaic information in domain type
1328  nt = ntile_per_pe(mpp_pe()-mpp_root_pe())
1329  if (associated(domain%tile_id)) deallocate(domain%tile_id) !< Check if associated
1330  if (associated(domain%x)) deallocate(domain%x) !< Check if associated
1331  if (associated(domain%y)) deallocate(domain%y) !< Check if associated
1332  if (associated(domain%list)) deallocate(domain%list) !< Check if associated
1333  allocate(domain%tile_id(nt), domain%x(nt), domain%y(nt) )
1334  allocate(domain%list(0:nlist-1))
1335 
1336  do n = 0, nlist-1
1337  nt = ntile_per_pe(n)
1338  allocate(domain%list(n)%x(nt), domain%list(n)%y(nt), domain%list(n)%tile_id(nt))
1339  end do
1340 
1341  pos = 0
1342  pe = mpp_pe()
1343  if( PRESENT(tile_id) ) then
1344  if(size(tile_id(:)) .NE. num_tile) then
1345  call mpp_error(fatal, .NE."mpp_domains_define.inc: size(tile_id) num_tile")
1346  endif
1347  endif
1348  allocate(tile_id_local(num_tile))
1349 
1350 !These directives are a work-around for a bug in the CCE compiler, which
1351 !causes a segmentation fault when the compiler attempts to vectorize a
1352 !loop containing an optional argument (when -g is included).
1353 
1354 !DIR$ NOVECTOR
1355  do n = 1, num_tile
1356  if(PRESENT(tile_id)) then
1357  tile_id_local(n) = tile_id(n)
1358  else
1359  tile_id_local(n) = n
1360  endif
1361  enddo
1362 !DIR$ VECTOR
1363 
1364  do n = 1, num_tile
1365  if( pe .GE. pe_start(n) .AND. pe .LE. pe_end(n)) then
1366  pos = pos + 1
1367  domain%tile_id(pos) = tile_id_local(n)
1368  end if
1369  end do
1370 
1371  if (associated(domain%tile_id_all)) deallocate(domain%tile_id_all) !< Check if associated
1372  allocate(domain%tile_id_all(num_tile))
1373  domain%tile_id_all(:) = tile_id_local(:)
1374 
1375  domain%initialized = .true.
1376  domain%rotated_ninety = .false.
1377  domain%ntiles = num_tile
1378  domain%max_ntile_pe = maxval(ntile_per_pe)
1379  domain%ncontacts = num_contact
1380 
1381  deallocate(ntile_per_pe)
1382  !---call mpp_define_domain to define domain decomposition for each tile.
1383  allocate(tile_count(pes(0):pes(0)+nlist-1))
1384  tile_count = 0 ! tile number on current pe
1385 
1386  domain%tile_comm_id=0
1387  do n = 1, num_tile
1388  allocate(mask(layout(1,n), layout(2,n)))
1389  allocate(pelist_tile(pe_start(n):pe_end(n)) )
1390  tile_count(pe_start(n)) = tile_count(pe_start(n)) + 1
1391  do m = pe_start(n), pe_end(n)
1392  pelist_tile(m) = m
1393  end do
1394  !--- set the tile communicator
1395  if (any(pelist_tile == pe)) then
1396  call mpp_declare_pelist(pelist_tile, commid=domain%tile_comm_id)
1397  endif
1398  mask = .true.
1399  if(present(maskmap)) mask = maskmap(1:layout(1,n), 1:layout(2,n), n)
1400  ndivx = layout(1,n); ndivy = layout(2,n)
1401  allocate(xext(ndivx), yext(ndivy))
1402  xext = 0; yext = 0
1403  if(present(xextent)) xext = xextent(1:ndivx,n)
1404  if(present(yextent)) yext = yextent(1:ndivy,n)
1405  ! when num_tile is one, we assume only folded_north and cyclic_x, cyclic_y boundary condition is the possible
1406  ! z1l: when we decide to support multiple-tile tripolar grid, we will redesign the following part.
1407  if(num_tile == 1) then
1408  flags_x = 0
1409  flags_y = 0
1410  if(PRESENT(xflags)) flags_x = xflags
1411  if(PRESENT(yflags)) flags_y = yflags
1412  do m = 1, num_contact
1413  if(istart1(m) == iend1(m) ) then ! x-direction contact, possible cyclic, folded-west or folded-east
1414  if(istart2(m) .NE. iend2(m) ) call mpp_error(fatal, &
1415  "mpp_domains_define: for one tile mosaic, when istart1=iend1, istart2 must equal iend2")
1416  if(istart1(m) == istart2(m) ) then ! folded west or folded east
1417  if(istart1(m) == global_indices(1,n) ) then
1418  if(.NOT. btest(flags_x,west) ) flags_x = flags_x + fold_west_edge
1419  else if(istart1(m) == global_indices(2,n) ) then
1420  if(.NOT. btest(flags_x,east) ) flags_x = flags_x + fold_east_edge
1421  else
1422  call mpp_error(fatal, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1423  "istart1 should equal global_indices(1) or global_indices(2)")
1424  endif
1425  else
1426  if(.NOT. btest(flags_x,cyclic)) flags_x = flags_x + cyclic_global_domain
1427  endif
1428  else if( jstart1(m) == jend1(m) ) then ! y-direction contact, cyclic, folded-south or folded-north
1429  if(jstart2(m) .NE. jend2(m) ) call mpp_error(fatal, &
1430  "mpp_domains_define: for one tile mosaic, when jstart1=jend1, jstart2 must equal jend2")
1431  if(jstart1(m) == jstart2(m) ) then ! folded south or folded north
1432  if(jstart1(m) == global_indices(3,n) ) then
1433  if(.NOT. btest(flags_y,south) ) flags_y = flags_y + fold_south_edge
1434  else if(jstart1(m) == global_indices(4,n) ) then
1435  if(.NOT. btest(flags_y,north) ) flags_y = flags_y + fold_north_edge
1436  else
1437  call mpp_error(fatal, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1438  "istart1 should equal global_indices(1) or global_indices(2)")
1439  endif
1440  else
1441  if(.NOT. btest(flags_y,cyclic)) flags_y = flags_y + cyclic_global_domain
1442  end if
1443  else
1444  call mpp_error(fatal, &
1445  "mpp_domains_define: for one tile mosaic, invalid boundary contact")
1446  end if
1447  end do
1448  call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, xflags = flags_x, &
1449  yflags = flags_y, whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, &
1450  xextent=xext, yextent=yext, maskmap=mask, name=name, symmetry=is_symmetry, &
1451  memory_size = memory_size, is_mosaic = .true., tile_id=tile_id_local(n))
1452  else
1453  call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, &
1454  whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, xextent=xext, yextent=yext, &
1455  maskmap=mask, name=name, symmetry=is_symmetry, memory_size = memory_size, &
1456  is_mosaic = .true., tile_count = tile_count(pe_start(n)), tile_id=tile_id_local(n), &
1457  complete = n==num_tile)
1458  end if
1459  deallocate(mask, xext, yext, pelist_tile)
1460  end do
1461 
1462  deallocate(pes, tile_count, tile_id_local)
1463 
1464  if(num_contact == 0 .OR. num_tile == 1) return
1465 
1466  !--- loop through each contact region and find the contact for each tile ( including alignment )
1467  !--- we assume the tiles list is continuous and starting from 1.
1468  allocate(is1(num_contact), ie1(num_contact), js1(num_contact), je1(num_contact) )
1469  allocate(is2(num_contact), ie2(num_contact), js2(num_contact), je2(num_contact) )
1470  allocate(isglist(num_tile), ieglist(num_tile), jsglist(num_tile), jeglist(num_tile) )
1471  allocate(align1(num_contact), align2(num_contact), refine1(num_contact), refine2(num_contact))
1472  !--- get the global domain for each tile
1473  do n = 1, num_tile
1474  isglist(n) = domain%tileList(n)%xbegin; ieglist(n) = domain%tileList(n)%xend
1475  jsglist(n) = domain%tileList(n)%ybegin; jeglist(n) = domain%tileList(n)%yend
1476  end do
1477 
1478  !--- transfer the contact index to domain index.
1479  nc = 0
1480  do n = 1, num_contact
1481  t1 = tile1(n)
1482  t2 = tile2(n)
1483  is1(n) = istart1(n) + isglist(t1) - 1; ie1(n) = iend1(n) + isglist(t1) - 1
1484  js1(n) = jstart1(n) + jsglist(t1) - 1; je1(n) = jend1(n) + jsglist(t1) - 1
1485  is2(n) = istart2(n) + isglist(t2) - 1; ie2(n) = iend2(n) + isglist(t2) - 1
1486  js2(n) = jstart2(n) + jsglist(t2) - 1; je2(n) = jend2(n) + jsglist(t2) - 1
1487  call check_alignment( is1(n), ie1(n), js1(n), je1(n), isglist(t1), ieglist(t1), jsglist(t1), &
1488  & jeglist(t1), align1(n))
1489  call check_alignment( is2(n), ie2(n), js2(n), je2(n), isglist(t2), ieglist(t2), jsglist(t2), &
1490  & jeglist(t2), align2(n))
1491  if( (align1(n) == west .or. align1(n) == east ) .NEQV. (align2(n) == west .or. align2(n) == east ) )&
1492  domain%rotated_ninety=.true.
1493  end do
1494 
1495  !--- calculate the refinement ratio between tiles
1496  do n = 1, num_contact
1497  n1 = max(abs(iend1(n) - istart1(n)), abs(jend1(n) - jstart1(n)) ) + 1
1498  n2 = max(abs(iend2(n) - istart2(n)), abs(jend2(n) - jstart2(n)) ) + 1
1499  refine1(n) = real(n2)/n1
1500  refine2(n) = real(n1)/n2
1501  end do
1502 
1503  whalosz = 0; ehalosz = 0; shalosz = 0; nhalosz = 0
1504  if(present(whalo)) whalosz = whalo
1505  if(present(ehalo)) ehalosz = ehalo
1506  if(present(shalo)) shalosz = shalo
1507  if(present(nhalo)) nhalosz = nhalo
1508  xhalosz = max(whalosz, ehalosz)
1509  yhalosz = max(shalosz, nhalosz)
1510 
1511  !--- computing the overlap for the contact region with halo size xhalosz and yhalosz
1512  call define_contact_point( domain, center, num_contact, tile1, tile2, align1, align2, refine1, refine2, &
1513  is1, ie1, js1, je1, is2, ie2, js2, je2, isglist, ieglist, jsglist, jeglist )
1514 
1515  call set_contact_point( domain, corner )
1516  call set_contact_point( domain, east )
1517  call set_contact_point( domain, north )
1518 
1519  call set_domain_comm_inf(domain%update_T)
1520  call set_domain_comm_inf(domain%update_E)
1521  call set_domain_comm_inf(domain%update_C)
1522  call set_domain_comm_inf(domain%update_N)
1523 
1524 
1525  !--- goffset setting is needed for exact global sum
1526  do m = 1, size(domain%tile_id(:))
1527  tile = domain%tile_id(m)
1528  do n = 1, num_contact
1529  if( tile1(n) == tile ) then
1530  if(align1(n) == east ) domain%x(m)%goffset = 0
1531  if(align1(n) == north) domain%y(m)%goffset = 0
1532  end if
1533  if( tile2(n) == tile ) then
1534  if(align2(n) == east ) domain%x(m)%goffset = 0
1535  if(align2(n) == north) domain%y(m)%goffset = 0
1536  end if
1537  end do
1538  end do
1539  call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_mosaic")
1540  call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_mosaic")
1541  call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_mosaic")
1542  call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_mosaic")
1543 
1544  !--- set the overlapping for boundary check if domain is symmetry
1545  if(debug_update_level .NE. no_check) then
1546  call set_check_overlap( domain, corner )
1547  call set_check_overlap( domain, east )
1548  call set_check_overlap( domain, north )
1549  endif
1550  if(domain%symmetry) then
1551  if (associated(domain%bound_E)) deallocate(domain%bound_E) !< Check if associated
1552  if (associated(domain%bound_C)) deallocate(domain%bound_C) !< Check if associated
1553  if (associated(domain%bound_N)) deallocate(domain%bound_N) !< Check if associated
1554  allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1555  call set_bound_overlap( domain, corner )
1556  call set_bound_overlap( domain, east )
1557  call set_bound_overlap( domain, north )
1558  call check_overlap_pe_order(domain, domain%bound_C, trim(domain%name)//" bound_C")
1559  call check_overlap_pe_order(domain, domain%bound_E, trim(domain%name)//" bound_E")
1560  call check_overlap_pe_order(domain, domain%bound_N, trim(domain%name)//" bound_N")
1561  end if
1562 
1563  !--- check the send and recv size are matching.
1564  !--- currently only check T and C-cell. For ntiles>1 mosaic,
1565  !--- the check will be done in mpp_define_mosaic
1566  if(debug_message_passing) then
1567  send = .true.
1568  recv = .true.
1569  call check_message_size(domain, domain%update_T, send, recv, 'T')
1570  call check_message_size(domain, domain%update_C, send, recv, 'C')
1571  call check_message_size(domain, domain%update_E, send, recv, 'E')
1572  call check_message_size(domain, domain%update_N, send, recv, 'N')
1573  endif
1574 
1575 
1576  !--- release memory
1577  deallocate(align1, align2, is1, ie1, js1, je1, is2, ie2, js2, je2 )
1578  deallocate(isglist, ieglist, jsglist, jeglist, refine1, refine2 )
1579 
1580 
1581  end subroutine mpp_define_mosaic
1582 
1583 !#####################################################################
1584  !> Accessor function for value of mosaic_defined
1585  logical function mpp_mosaic_defined()
1586  mpp_mosaic_defined = mosaic_defined
1587  end function mpp_mosaic_defined
1588 !#####################################################################
1589 
1590  !> @brief Computes remote domain overlaps
1591  !!
1592  !> Assumes only one in each direction
1593  !! will calculate the overlapping for T,E,C,N-cell seperately.
1594  subroutine compute_overlaps( domain, position, update, check, ishift, jshift, x_cyclic_offset, y_cyclic_offset, &
1595  whalo, ehalo, shalo, nhalo )
1596  type(domain2d), intent(inout) :: domain
1597  type(overlapspec), intent(inout), pointer :: update
1598  type(overlapspec), intent(inout), pointer :: check
1599  integer, intent(in) :: position, ishift, jshift
1600  integer, intent(in) :: x_cyclic_offset, y_cyclic_offset
1601  integer, intent(in) :: whalo, ehalo, shalo, nhalo
1602 
1603  integer :: i, m, n, nlist, tMe, tNbr, dir
1604  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
1605  integer :: isg, ieg, jsg, jeg, ioff, joff
1606  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
1607  integer :: ism, iem, jsm, jem
1608  integer :: is2, ie2, js2, je2
1609  integer :: is3, ie3, js3, je3
1610  integer :: isd3, ied3, jsd3, jed3
1611  integer :: isd2, ied2, jsd2, jed2
1612  logical :: folded, need_adjust_1, need_adjust_2, need_adjust_3, folded_north
1613  type(overlap_type) :: overlap
1614  type(overlap_type), pointer :: overlapList(:)=>null()
1615  type(overlap_type), pointer :: checkList(:)=>null()
1616  integer :: nsend, nrecv
1617  integer :: nsend_check, nrecv_check
1618  integer :: iunit
1619  logical :: set_check
1620 
1621  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
1622  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
1623  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
1624  if(size(domain%x(:)) > 1) return
1625 
1626  !--- if there is no halo, no need to compute overlaps.
1627  if(whalo==0 .AND. ehalo==0 .AND. shalo==0 .AND. nhalo==0) return
1628 
1629  !--- when there is only one tile, n will equal to np
1630  nlist = size(domain%list(:))
1631  set_check = .false.
1632  if(ASSOCIATED(check)) set_check = .true.
1633  allocate(overlaplist(maxlist) )
1634  if(set_check) allocate(checklist(maxlist) )
1635 
1636  !--- overlap is used to store the overlapping temporarily.
1637  call allocate_update_overlap( overlap, maxoverlap)
1638  !send
1639  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
1640  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
1641  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
1642 
1643  update%xbegin = ism; update%xend = iem
1644  update%ybegin = jsm; update%yend = jem
1645  if(set_check) then
1646  check%xbegin = ism; check%xend = iem
1647  check%ybegin = jsm; check%yend = jem
1648  endif
1649  update%whalo = whalo; update%ehalo = ehalo
1650  update%shalo = shalo; update%nhalo = nhalo
1651 
1652  ioff = ni - ishift
1653  joff = nj - jshift
1654  middle = (isg+ieg)/2+1
1655  tme = 1; tnbr = 1
1656  folded_north = btest(domain%fold,north)
1657  if( btest(domain%fold,south) .OR. btest(domain%fold,east) .OR. btest(domain%fold,west) ) then
1658  call mpp_error(fatal,"mpp_domains_define.inc(compute_overlaps): folded south, east or west boundary condition "&
1659  &//"is not supported, please use other version of compute_overlaps for "//trim(domain%name))
1660  endif
1661 
1662  nsend = 0
1663  nsend_check = 0
1664 
1665  do list = 0,nlist-1
1666  m = mod( domain%pos+list, nlist )
1667  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
1668  !to_pe's eastern halo
1669  dir = 1
1670  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
1671  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
1672  !--- to make sure the consistence between pes
1673  if( domain%symmetry .AND. (position == north .OR. position == corner ) &
1674  .AND. ( jsc == je .or. jec == js ) ) then
1675  !--- do nothing, this point will come from other pe
1676  else
1677  !--- when the north face is folded, the east halo point at right side domain will be folded.
1678  !--- the position should be on CORNER or NORTH
1679  if( je == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
1680  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1681  isg, ieg, dir, ishift, position, ioff, middle)
1682  else
1683  if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1684  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1685  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1686  else
1687  if( ie.GT.ieg ) then
1688  if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
1689  is = is-ioff; ie = ie-ioff
1690  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1691  end if
1692  end if
1693  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1694  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1695  endif
1696  endif
1697  end if
1698 
1699  !to_pe's SE halo
1700  dir = 2
1701  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
1702  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1703  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1704  !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
1705  !--- the other part is both are zero.
1706  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1707  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1708  if(je .LT. jsg) then ! js .LT. jsg
1709  if( domain%y(tme)%cyclic ) then
1710  js = js + joff; je = je + joff
1711  endif
1712  else if(js .Lt. jsg) then ! split into two parts
1713  if( domain%y(tme)%cyclic ) then
1714  js2 = js + joff; je2 = jsg-1+joff
1715  js = jsg;
1716  endif
1717  endif
1718  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1719  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1720  if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1721  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1722  else
1723  if( ie.GT.ieg )then
1724  if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
1725  is = is-ioff; ie = ie-ioff
1726  need_adjust_1 = .false.
1727  if(jsg .GT. js) then
1728  if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1729  js = js+joff; je = je+joff
1730  need_adjust_2 = .false.
1731  if(x_cyclic_offset .NE. 0) then
1732  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1733  else if(y_cyclic_offset .NE. 0) then
1734  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1735  end if
1736  end if
1737  else
1738  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1739  need_adjust_3 = .false.
1740  end if
1741  end if
1742  end if
1743  if( need_adjust_3 .AND. jsg.GT.js )then
1744  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1745  js = js+joff; je = je+joff
1746  if(need_adjust_1 .AND. ie.LE.ieg) then
1747  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1748  end if
1749  end if
1750  end if
1751  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1752  endif
1753 
1754  !to_pe's southern halo
1755  dir = 3
1756  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
1757  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1758  js2 = 0; je2 = -1
1759  if( jsg.GT.je )then ! jsg .GT. js
1760  if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1761  js = js+joff; je = je+joff
1762  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1763  end if
1764  else if (jsg .GT. js) then ! split into two parts
1765  if( domain%y(tme)%cyclic) then
1766  js2 = js + joff; je2 = jsg-1+joff
1767  js = jsg
1768  endif
1769  end if
1770 
1771  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1772  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1773  if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1774  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1775 
1776  !to_pe's SW halo
1777  dir = 4
1778  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1779  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1780  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1781  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1782  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1783  if(je .LT. jsg) then ! js .LT. jsg
1784  if( domain%y(tme)%cyclic ) then
1785  js = js + joff; je = je + joff
1786  endif
1787  else if(js .Lt. jsg) then ! split into two parts
1788  if( domain%y(tme)%cyclic ) then
1789  js2 = js + joff; je2 = jsg-1+joff
1790  js = jsg;
1791  endif
1792  endif
1793  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1794  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1795  if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1796  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1797  else
1798  if( isg.GT.is )then
1799  if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1800  is = is+ioff; ie = ie+ioff
1801  need_adjust_1 = .false.
1802  if(jsg .GT. js) then
1803  if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1804  js = js+joff; je = je+joff
1805  need_adjust_2 = .false.
1806  if(x_cyclic_offset .NE. 0) then
1807  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1808  else if(y_cyclic_offset .NE. 0) then
1809  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1810  end if
1811  end if
1812  else
1813  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1814  need_adjust_3 = .false.
1815  end if
1816  end if
1817  end if
1818  if( need_adjust_3 .AND. jsg.GT.js )then
1819  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1820  js = js+joff; je = je+joff
1821  if(need_adjust_1 .AND. isg.LE.is )then
1822  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1823  end if
1824  end if
1825  end if
1826  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1827  endif
1828 
1829  !to_pe's western halo
1830  dir = 5
1831  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1832  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
1833 
1834  !--- when the north face is folded, some point at j=nj will be folded.
1835  !--- the position should be on CORNER or NORTH
1836  if( je == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
1837  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1838  isg, ieg, dir, ishift, position, ioff, middle)
1839  else
1840  if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1841  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1842  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1843  else
1844  if( isg.GT.is )then
1845  if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1846  is = is+ioff; ie = ie+ioff
1847  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1848  endif
1849  end if
1850  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1851  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1852  end if
1853  end if
1854 
1855  !to_pe's NW halo
1856  dir = 6
1857  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1858  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
1859  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1860  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
1861  folded = .false.
1862  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1863  if(js .GT. jeg) then ! je > jeg
1864  if( domain%y(tme)%cyclic ) then
1865  js = js-joff; je = je-joff
1866  else if(folded_north )then
1867  folded = .true.
1868  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1869  endif
1870  else if(je .GT. jeg) then ! split into two parts
1871  if( domain%y(tme)%cyclic ) then
1872  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1873  js = jeg+1-joff; je = je -joff
1874  else if(folded_north) then
1875  folded = .true.
1876  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1877  js = jeg+1
1878  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1879  if( is .GT. ieg) then
1880  is = is - ioff; ie = ie - ioff
1881  else if( ie .GT. ieg ) then
1882  is3 = is; ie3 = ieg; js3 = js; je3 = je
1883  is = ieg+1-ioff; ie = ie - ioff
1884  endif
1885  endif
1886  endif
1887 
1888  if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
1889  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1890  isg, ieg, dir, ishift, position, ioff, middle)
1891  else
1892  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1893  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
1894  endif
1895  if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
1896  isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
1897  if(ie2 .GE. is2) then
1898  if(je2 == jeg .AND. jec == jeg .AND. folded_north.AND.(position == corner .OR. position == north))then
1899  call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1900  isg, ieg, dir, ishift, position, ioff, middle)
1901  else
1902  call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1903  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1904  endif
1905  endif
1906  else
1907  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1908  if( isg.GT.is )then
1909  if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1910  is = is+ioff; ie = ie+ioff
1911  need_adjust_1 = .false.
1912  if(je .GT. jeg) then
1913  if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1914  js = js-joff; je = je-joff
1915  need_adjust_2 = .false.
1916  if(x_cyclic_offset .NE. 0) then
1917  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1918  else if(y_cyclic_offset .NE. 0) then
1919  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1920  end if
1921  end if
1922  else
1923  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1924  need_adjust_3 = .false.
1925  end if
1926  end if
1927  end if
1928  folded = .false.
1929  if( need_adjust_3 .AND. je.GT.jeg )then
1930  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1931  js = js-joff; je = je-joff
1932  if( need_adjust_1 .AND. isg.LE.is)then
1933  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1934  end if
1935  else if( folded_north )then
1936  folded = .true.
1937  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1938  end if
1939  end if
1940  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1941  isg, ieg, jsg, jeg, dir)
1942  endif
1943 
1944 
1945  !to_pe's northern halo
1946  dir = 7
1947  folded = .false.
1948  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
1949  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
1950 
1951  !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
1952  !--- no need to send, because the data on that point will come from other pe.
1953  !--- come from two pe ( there will be only one point on one pe. ).
1954  if( domain%symmetry .AND. (position == east .OR. position == corner ) &
1955  .AND. ( isc == ie .or. iec == is ) .AND. (.not. folded_north) ) then
1956  !--- do nothing, this point will come from other pe
1957  else
1958  js2 = -1; je2 = 0
1959  if( js .GT. jeg) then ! je .GT. jeg
1960  if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1961  js = js-joff; je = je-joff
1962  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1963  else if( folded_north )then
1964  folded = .true.
1965  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1966  end if
1967  else if( je.GT.jeg )then ! split into two parts
1968  if( domain%y(tme)%cyclic)then !try cyclic offset
1969  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1970  js = jeg+1-joff; je = je - joff
1971  else if( folded_north )then
1972  folded = .true.
1973  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1974  js = jeg+1;
1975  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1976  end if
1977  end if
1978  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1979  if( je == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
1980  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1981  isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1982  else
1983  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1984  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, domain%symmetry)
1985  endif
1986  else
1987  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1988  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1989  endif
1990 
1991  if(ie2 .GE. is2) then
1992  if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
1993  call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1994  isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1995  else
1996  call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1997  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1998  endif
1999  endif
2000  end if
2001 
2002  !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2003  if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2004 ! is = is + ioff
2005 ! call insert_update_overlap( overlap, domain%list(m)%pe, &
2006 ! is, is, js, je, isc, iec, jsc, jec, dir, folded)
2007 !??? if(je2 .GE. js2)call insert_update_overlap( overlap, domain%list(m)%pe, &
2008 ! is, is, js2, je2, isc, iec, jsc, jec, dir, folded)
2009  endif
2010 
2011  !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2012  !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2013  !--- only position at NORTH and CORNER need to be considered
2014  if( folded_north .AND. (position == north .OR. position == corner) &
2015  .AND. domain%x(tme)%pos .LT. (size(domain%x(tme)%list(:))+1)/2 ) then
2016  if( domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .GE. jeg .AND. isc .LE. middle)then
2017  js = jeg; je = jeg
2018  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
2019  is = max(is, middle)
2020  select case (position)
2021  case(north)
2022  i=is; is = isg+ieg-ie; ie = isg+ieg-i
2023  case(corner)
2024  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2025  end select
2026  call insert_update_overlap(overlap, domain%list(m)%pe, &
2027  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
2028  endif
2029  if(debug_update_level .NE. no_check .AND. set_check) then
2030  je = domain%list(m)%y(tnbr)%compute%end+jshift;
2031  if(je == jeg) then
2032  is = max(is, isc); ie = min(ie, iec)
2033  js = max(js, jsc); je = min(je, jec)
2034  if(ie.GE.is .AND. je.GE.js )then
2035  nsend_check = nsend_check+1
2036  if(nsend_check > size(checklist(:)) ) then
2037  call expand_check_overlap_list(checklist, nlist)
2038  endif
2039  call allocate_check_overlap(checklist(nsend_check), 1)
2040  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
2041  tme, 4, one_hundred_eighty, is, ie, js, je)
2042  end if
2043  end if
2044  endif
2045  endif
2046 
2047  !to_pe's NE halo
2048  dir = 8
2049  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
2050  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
2051  is2 = 0; ie2=-1; js2=0; je2=-1
2052  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2053  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2054  folded = .false.
2055  if(js .GT. jeg) then ! je > jeg
2056  if( domain%y(tme)%cyclic ) then
2057  js = js-joff; je = je-joff
2058  else if(folded_north )then
2059  folded = .true.
2060  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2061  endif
2062  else if(je .GT. jeg) then ! split into two parts
2063  if( domain%y(tme)%cyclic ) then
2064  is2 = is; ie2 = ie; js2 = js; je2 = jeg
2065  js = jeg+1-joff; je = je -joff
2066  else if(folded_north) then
2067  folded = .true.
2068  is2 = is; ie2 = ie; js2 = js; je2 = jeg
2069  js = jeg+1
2070  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2071 
2072  if( ie .LT. isg )then
2073  is = is+ioff; ie = ie+ioff
2074  else if( is .LT. isg) then
2075  is3 = isg; ie3 = ie; js3 = js; je3 = je
2076  is = is+ioff; ie = isg-1+ioff;
2077  endif
2078  endif
2079  endif
2080  if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
2081  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2082  isg, ieg, dir, ishift, position, ioff, middle)
2083  else
2084  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2085  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2086  endif
2087  if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
2088  isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2089  if(ie2 .GE. is2) then
2090  if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
2091  call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2092  isg, ieg, dir, ishift, position, ioff, middle)
2093  else
2094  call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2095  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2096  endif
2097  endif
2098  else
2099  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2100  if( ie.GT.ieg )then
2101  if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
2102  is = is-ioff; ie = ie-ioff
2103  need_adjust_1 = .false.
2104  if(je .GT. jeg) then
2105  if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
2106  js = js-joff; je = je-joff
2107  need_adjust_2 = .false.
2108  if(x_cyclic_offset .NE. 0) then
2109  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2110  else if(y_cyclic_offset .NE. 0) then
2111  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2112  end if
2113  end if
2114  else
2115  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2116  need_adjust_3 = .false.
2117  end if
2118  end if
2119  end if
2120  folded = .false.
2121  if( need_adjust_3 .AND. je.GT.jeg )then
2122  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
2123  js = js-joff; je = je-joff
2124  if( need_adjust_1 .AND. ie.LE.ieg)then
2125  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2126  end if
2127  else if( folded_north )then
2128  folded = .true.
2129  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2130  end if
2131  end if
2132  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2133  isg, ieg, jsg, jeg, dir)
2134  endif
2135  endif
2136 
2137  !--- copy the overlapping information
2138  if( overlap%count > 0) then
2139  nsend = nsend + 1
2140  if(nsend > size(overlaplist(:)) ) then
2141  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps): overlapList for send is expanded')
2142  call expand_update_overlap_list(overlaplist, nlist)
2143  endif
2144  call add_update_overlap( overlaplist(nsend), overlap)
2145  call init_overlap_type(overlap)
2146  endif
2147  end do ! end of send set up.
2148 
2149  if(debug_message_passing) then
2150  !--- write out send information
2151  iunit = mpp_pe() + 1000
2152  do m =1,nsend
2153  write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
2154  do n = 1, overlaplist(m)%count
2155  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
2156  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
2157  enddo
2158  enddo
2159  if(nsend >0) flush(iunit)
2160  endif
2161 
2162  ! copy the overlapping information into domain data structure
2163  if(nsend>0) then
2164  if (associated(update%send)) deallocate(update%send) !< Check if associated
2165  allocate(update%send(nsend))
2166  update%nsend = nsend
2167  do m = 1, nsend
2168  call add_update_overlap( update%send(m), overlaplist(m) )
2169  enddo
2170  endif
2171 
2172  if(nsend_check>0) then
2173  check%nsend = nsend_check
2174  if (associated(check%send)) deallocate(check%send) !< Check if associated
2175  allocate(check%send(nsend_check))
2176  do m = 1, nsend_check
2177  call add_check_overlap( check%send(m), checklist(m) )
2178  enddo
2179  endif
2180 
2181  do m = 1,size(overlaplist(:))
2182  call deallocate_overlap_type(overlaplist(m))
2183  enddo
2184 
2185  if(debug_update_level .NE. no_check .AND. set_check) then
2186  do m = 1,size(checklist(:))
2187  call deallocate_overlap_type(checklist(m))
2188  enddo
2189  endif
2190 
2191  isgd = isg - domain%whalo
2192  iegd = ieg + domain%ehalo
2193  jsgd = jsg - domain%shalo
2194  jegd = jeg + domain%nhalo
2195 
2196  ! begin setting up recv
2197  nrecv = 0
2198  nrecv_check = 0
2199  do list = 0,nlist-1
2200  m = mod( domain%pos+nlist-list, nlist )
2201  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
2202  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
2203  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
2204  !recv_e
2205  dir = 1
2206  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2207  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
2208  is=isc; ie=iec; js=jsc; je=jec
2209  if( domain%symmetry .AND. (position == north .OR. position == corner ) &
2210  .AND. ( jsd == je .or. jed == js ) ) then
2211  ! --- do nothing, this point will come from other pe
2212  else
2213  !--- when the north face is folded, the east halo point at right side domain will be folded.
2214  !--- the position should be on CORNER or NORTH
2215  if( jed == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
2216  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2217  isg, ieg, dir, ishift, position, ioff, middle)
2218  else
2219  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2220  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2221  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2222  else
2223  if( ied.GT.ieg )then
2224  if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2225  is = is+ioff; ie = ie+ioff
2226  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2227  end if
2228  end if
2229  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2230  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2231  endif
2232  endif
2233  endif
2234 
2235  !recv_se
2236  dir = 2
2237  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2238  jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2239  is=isc; ie=iec; js=jsc; je=jec
2240  !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
2241  !--- the other part is both are zero.
2242  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2243  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2244  if(jed .LT. jsg) then ! then jsd < jsg
2245  if( domain%y(tme)%cyclic ) then
2246  js = js-joff; je = je-joff
2247  endif
2248  else if(jsd .LT. jsg) then !split into two parts
2249  if( domain%y(tme)%cyclic ) then
2250  js2 = js-joff; je2 = je-joff
2251  endif
2252  endif
2253  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2254  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2255  if(je2 .GE. js2) call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2256  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2257  else
2258  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2259  if( jsd.LT.jsg )then
2260  if( domain%y(tme)%cyclic .AND. js.GT.jed )then !try cyclic offset
2261  js = js-joff; je = je-joff
2262  need_adjust_1 = .false.
2263  if( ied.GT.ieg )then
2264  if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2265  is = is+ioff; ie = ie+ioff
2266  need_adjust_2 = .false.
2267  if(x_cyclic_offset .NE. 0) then
2268  call apply_cyclic_offset(js, je, x_cyclic_offset, jsgd, jeg, nj)
2269  else if(y_cyclic_offset .NE. 0) then
2270  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, iegd, ni)
2271  end if
2272  end if
2273  else
2274  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2275  need_adjust_3 = .false.
2276  end if
2277  end if
2278  end if
2279  if( need_adjust_3 .AND. ied.GT.ieg )then
2280  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2281  is = is+ioff; ie = ie+ioff
2282  if( need_adjust_1 .AND. jsd.GE.jsg )then
2283  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2284  end if
2285  end if
2286  end if
2287  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2288  isg, ieg, jsg, jeg, dir)
2289  endif
2290 
2291  !recv_s
2292  dir = 3
2293  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
2294  jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2295  is=isc; ie=iec; js=jsc; je=jec
2296  js2 = 0; je2 = -1
2297  if( jed .LT. jsg) then ! jsd < jsg
2298  if( domain%y(tme)%cyclic ) then
2299  js = js-joff; je = je-joff
2300  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2301  endif
2302  else if( jsd.LT.jsg )then ! split into two parts
2303  if( domain%y(tme)%cyclic)then !try cyclic offset
2304  js2 = js-joff; je2 = je-joff
2305  end if
2306  end if
2307  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2308  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2309  if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2310  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2311 
2312  !recv_sw
2313  dir = 4
2314  isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2315  jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2316  is=isc; ie=iec; js=jsc; je=jec
2317  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2318  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2319  if( ied.LT.isg )then ! isd < isg
2320  if( domain%x(tme)%cyclic ) then
2321  is = is-ioff; ie = ie-ioff
2322  endif
2323  else if (isd.LT.isg )then ! split into two parts
2324  if( domain%x(tme)%cyclic ) then
2325  is2 = is-ioff; ie2 = ie-ioff
2326  endif
2327  endif
2328  if( jed.LT.jsg )then ! jsd < jsg
2329  if( domain%y(tme)%cyclic ) then
2330  js = js-joff; je = je-joff
2331  endif
2332  else if( jsd.LT.jsg )then ! split into two parts
2333  if( domain%y(tme)%cyclic ) then
2334  js2 = js-joff; je2 = je-joff
2335  endif
2336  endif
2337  else
2338  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2339  if( jsd.LT.jsg )then
2340  if( domain%y(tme)%cyclic .AND. js.GT.jed )then !try cyclic offset
2341  js = js-joff; je = je-joff
2342  need_adjust_1 = .false.
2343  if( isd.LT.isg )then
2344  if( domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2345  is = is-ioff; ie = ie-ioff
2346  need_adjust_2 = .false.
2347  if(x_cyclic_offset .NE. 0) then
2348  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsgd, jeg, nj)
2349  else if(y_cyclic_offset .NE. 0) then
2350  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isgd, ieg, ni)
2351  end if
2352  end if
2353  else
2354  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2355  need_adjust_3 = .false.
2356  end if
2357  end if
2358  end if
2359  if( need_adjust_3 .AND. isd.LT.isg )then
2360  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2361  is = is-ioff; ie = ie-ioff
2362  if(need_adjust_1 .AND. jsd.GE.jsg) then
2363  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2364  end if
2365  end if
2366  end if
2367  endif
2368  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2369  isg, ieg, jsg, jeg, dir)
2370 
2371  if(ie2 .GE. is2)call fill_overlap(overlap, domain, m, is2, ie2, js, je, isd, ied, jsd, jed, &
2372  isg, ieg, jsg, jeg, dir)
2373  if(je2 .GE. js2)call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2374  isg, ieg, jsg, jeg, dir)
2375 
2376  if(ie2 .GE. is2 .AND. je2 .GE. js2)call fill_overlap(overlap, domain, m, is2, ie2, js2, je2, isd, ied, jsd, &
2377  & jed, isg, ieg, jsg, jeg, dir)
2378 
2379 
2380  !recv_w
2381  dir = 5
2382  isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2383  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
2384  is=isc; ie=iec; js=jsc; je=jec
2385 
2386  !--- when the north face is folded, some point at j=nj will be folded.
2387  !--- the position should be on CORNER or NORTH
2388  if( jed == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
2389  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2390  isg, ieg, dir, ishift, position, ioff, middle)
2391  else
2392  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2393  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2394  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
2395  else
2396  if( isd.LT.isg )then
2397  if( domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2398  is = is-ioff; ie = ie-ioff
2399  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2400  end if
2401  end if
2402  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2403  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2404  endif
2405  endif
2406 
2407  !recv_nw
2408  dir = 6
2409  folded = .false.
2410  isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2411  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2412  is=isc; ie=iec; js=jsc; je=jec
2413  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2414  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2415  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2416  js2 = -1; je2 = 0
2417  if( jsd .GT. jeg ) then ! jed > jeg
2418  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2419  js = js+joff; je = je+joff
2420  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2421  else if( folded_north )then
2422  folded = .true.
2423  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2424  end if
2425  else if( jed.GT.jeg )then ! split into two parts
2426  if( domain%y(tme)%cyclic)then !try cyclic offset
2427  is2 = is; ie2 = ie; js2 = js; je2 = je
2428  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2429  js = js + joff; je = je + joff
2430  jsd = jeg+1
2431  else if( folded_north )then
2432  folded = .true.
2433  is2 = is; ie2 = ie; js2 = js; je2 = je
2434  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2435  jsd = jeg+1
2436  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2437  if(isd < isg .and. ied .GE. isg .and. domain%symmetry) then
2438  isd3 = isd; ied3 = isg-1
2439  jsd3 = jsd; jed3 = jed
2440  is3 = is-ioff; ie3=ie-ioff
2441  js3 = js; je3 = je
2442  isd = isg;
2443  endif
2444  end if
2445  endif
2446 
2447  if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2448  .AND. (position == corner .OR. position == north)) then
2449  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2450  isg, ieg, dir, ishift, position, ioff, middle)
2451  else
2452  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2453  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2454  endif
2455 
2456  if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2457  & jed3, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2458 
2459  if(ie2 .GE. is2) then
2460  if( jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2461  .AND. (position == corner .OR. position == north)) then
2462  call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2463  isg, ieg, dir, ishift, position, ioff, middle)
2464  else
2465  call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2466  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2467  endif
2468  endif
2469  else
2470  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2471  if( jed.GT.jeg )then
2472  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2473  js = js+joff; je = je+joff
2474  need_adjust_1 = .false.
2475  if( isd.LT.isg )then
2476  if( domain%x(tme)%cyclic .AND. is.GE.ied )then !try cyclic offset
2477  is = is-ioff; ie = ie-ioff
2478  need_adjust_2 = .false.
2479  if(x_cyclic_offset .NE. 0) then
2480  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jegd, nj)
2481  else if(y_cyclic_offset .NE. 0) then
2482  call apply_cyclic_offset(is, ie, y_cyclic_offset, isgd, ieg, ni)
2483  end if
2484  end if
2485  else
2486  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2487  need_adjust_3 = .false.
2488  end if
2489  else if( folded_north )then
2490  folded = .true.
2491  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2492  end if
2493  end if
2494  if( need_adjust_3 .AND. isd.LT.isg )then
2495  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. is.GE.ied )then !try cyclic offset
2496  is = is-ioff; ie = ie-ioff
2497  if( need_adjust_1 .AND. jed.LE.jeg )then
2498  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2499  end if
2500  end if
2501  end if
2502  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2503  isg, ieg, jsg, jeg, dir)
2504  endif
2505 
2506  !--- when north edge is folded, is will be less than isg when position is EAST and CORNER
2507  if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2508  is = is + ioff
2509  call insert_update_overlap(overlap, domain%list(m)%pe, &
2510  is, is, js, je, isd, ied, jsd, jed, dir, folded )
2511  endif
2512 
2513  !recv_n
2514  dir = 7
2515  folded = .false.
2516  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
2517  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2518  is=isc; ie=iec; js=jsc; je=jec
2519 
2520  !--- when domain symmetry and position is EAST or CORNER, the point at i=isd will
2521  !--- come from two pe ( there will be only one point on one pe. ).
2522  if( domain%symmetry .AND. (position == east .OR. position == corner ) &
2523  .AND. (isd == ie .or. ied == is ) .AND. (.not. folded_north) ) then
2524  !--- do nothing, this point will come from other pe
2525  else
2526  js2 = -1; je2 = 0
2527  if( jsd .GT. jeg ) then ! jed > jeg
2528  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2529  js = js+joff; je = je+joff
2530  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2531  else if( folded_north )then
2532  folded = .true.
2533  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2534  end if
2535  else if( jed.GT.jeg )then ! split into two parts
2536  if( domain%y(tme)%cyclic)then !try cyclic offset
2537  is2 = is; ie2 = ie; js2 = js; je2 = je
2538  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2539  js = js + joff; je = je + joff
2540  jsd = jeg+1
2541  else if( folded_north )then
2542  folded = .true.
2543  is2 = is; ie2 = ie; js2 = js; je2 = je
2544  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2545  jsd = jeg+1
2546  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2547  end if
2548  end if
2549  if(x_cyclic_offset == 0 .and. y_cyclic_offset == 0) then
2550  if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2551  .AND. (position == corner .OR. position == north)) then
2552  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2553  isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2554  else
2555  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2556  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, symmetry=domain%symmetry)
2557  endif
2558  else
2559  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2560  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2561  endif
2562  if(ie2 .GE. is2) then
2563  if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2564  .AND. (position == corner .OR. position == north)) then
2565  call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2566  isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2567  else
2568  call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2569  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, symmetry=domain%symmetry)
2570  endif
2571  endif
2572  endif
2573 
2574  !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2575  if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2576 ! is = is + ioff
2577 ! call insert_update_overlap( overlap, domain%list(m)%pe, &
2578 ! is, is, js, je, isd, ied, jsd, jed, dir, folded)
2579  endif
2580 
2581  !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2582  !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2583  !--- only position at NORTH and CORNER need to be considered
2584 
2585  if( folded_north .AND. (position == north .OR. position == corner) &
2586  .AND. domain%x(tme)%pos .GE. size(domain%x(tme)%list(:))/2) then
2587  if( jed .GE. jeg .AND. ied .GE. middle)then
2588  jsd = jeg; jed = jeg
2589  is=isc; ie=iec; js = jsc; je = jec
2590  isd = max(isd, middle)
2591  select case (position)
2592  case(north)
2593  i=is; is = isg+ieg-ie; ie = isg+ieg-i
2594  case(corner)
2595  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2596  end select
2597  call insert_update_overlap(overlap, domain%list(m)%pe, &
2598  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
2599  endif
2600  if(debug_update_level .NE. no_check .AND. set_check) then
2601  jsd = domain%y(tme)%compute%end+jshift; jed = jsd
2602  if(jed == jeg) then
2603  is = max(is, isd); ie = min(ie, ied)
2604  js = max(js, jsd); je = min(je, jed)
2605  if(ie.GE.is .AND. je.GE.js )then
2606  nrecv_check = nrecv_check+1
2607  if(nrecv_check > size(checklist(:)) ) then
2608  call expand_check_overlap_list(checklist, nlist)
2609  endif
2610  call allocate_check_overlap(checklist(nrecv_check), 1)
2611  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
2612  tme, 4, one_hundred_eighty, is, ie, js, je)
2613  end if
2614  end if
2615  endif
2616 
2617  endif
2618 
2619  !recv_ne
2620  dir = 8
2621  folded = .false.
2622  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2623  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2624  is=isc; ie=iec; js=jsc; je=jec
2625  is2 = 0; ie2=-1; js2=0; je2=-1
2626  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2627  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2628  js2 = -1; je2 = 0
2629  if( jsd .GT. jeg ) then ! jed > jeg
2630  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2631  js = js+joff; je = je+joff
2632  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2633  else if( folded_north )then
2634  folded = .true.
2635  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2636  end if
2637  else if( jed.GT.jeg )then ! split into two parts
2638  if( domain%y(tme)%cyclic)then !try cyclic offset
2639  is2 = is; ie2 = ie; js2 = js; je2 = je
2640  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2641  js = js + joff; je = je + joff
2642  jsd = jeg+1
2643  else if( folded_north )then
2644  folded = .true.
2645  is2 = is; ie2 = ie; js2 = js; je2 = je
2646  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2647  jsd = jeg+1
2648  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2649  if(ied > ieg .and. isd .LE. ieg .and. domain%symmetry) then
2650  isd3 = ieg+1; ied3 = ied
2651  jsd3 = jsd; jed3 = jed
2652  is3 = is+ioff; ie3=ie+ioff
2653  js3 = js; je3 = je
2654  ied = ieg;
2655  endif
2656  end if
2657  endif
2658  if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2659  .AND. (position == corner .OR. position == north)) then
2660  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2661  isg, ieg, dir, ishift, position, ioff, middle)
2662  else
2663  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2664  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2665  endif
2666  if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2667  & jed3, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2668  if(ie2 .GE. is2) then
2669  if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2670  .AND. (position == corner .OR. position == north)) then
2671  call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2672  isg, ieg, dir, ishift, position, ioff, middle)
2673  else
2674  call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2675  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2676  endif
2677  endif
2678  else
2679  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2680  if( jed.GT.jeg )then
2681  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2682  js = js+joff; je = je+joff
2683  need_adjust_1 = .false.
2684  if( ied.GT.ieg )then
2685  if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2686  is = is+ioff; ie = ie+ioff
2687  need_adjust_2 = .false.
2688  if(x_cyclic_offset .NE. 0) then
2689  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jegd, nj)
2690  else if(y_cyclic_offset .NE. 0) then
2691  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, iegd, ni)
2692  end if
2693  end if
2694  else
2695  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2696  need_adjust_3 = .false.
2697  end if
2698  else if( folded_north )then
2699  folded = .true.
2700  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2701  end if
2702  end if
2703  if( need_adjust_3 .AND. ied.GT.ieg )then
2704  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2705  is = is+ioff; ie = ie+ioff
2706  if( need_adjust_1 .AND. jed.LE.jeg)then
2707  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2708  end if
2709  end if
2710  end if
2711  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2712  isg, ieg, jsg, jeg, dir)
2713  endif
2714  endif
2715 
2716  !--- copy the overlapping information
2717  if( overlap%count > 0) then
2718  nrecv = nrecv + 1
2719  if(nrecv > size(overlaplist(:)) )then
2720  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps): overlapList for recv is expanded')
2721  call expand_update_overlap_list(overlaplist, nlist)
2722  endif
2723  call add_update_overlap( overlaplist(nrecv), overlap)
2724  call init_overlap_type(overlap)
2725  endif
2726  enddo ! end of recv do loop
2727 
2728  if(debug_message_passing) then
2729  !--- write out send information
2730  iunit = mpp_pe() + 1000
2731  do m =1,nrecv
2732  write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
2733  do n = 1, overlaplist(m)%count
2734  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
2735  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
2736  enddo
2737  enddo
2738  if(nrecv >0) flush(iunit)
2739  endif
2740 
2741  ! copy the overlapping information into domain
2742  if(nrecv>0) then
2743  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
2744  allocate(update%recv(nrecv))
2745  update%nrecv = nrecv
2746  do m = 1, nrecv
2747  call add_update_overlap( update%recv(m), overlaplist(m) )
2748  do n = 1, update%recv(m)%count
2749  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
2750  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
2751  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
2752  endif
2753  enddo
2754  enddo
2755  endif
2756 
2757  if(nrecv_check>0) then
2758  check%nrecv = nrecv_check
2759  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
2760  allocate(check%recv(nrecv_check))
2761  do m = 1, nrecv_check
2762  call add_check_overlap( check%recv(m), checklist(m) )
2763  enddo
2764  endif
2765 
2766  call deallocate_overlap_type(overlap)
2767  do m = 1,size(overlaplist(:))
2768  call deallocate_overlap_type(overlaplist(m))
2769  enddo
2770 
2771  if(debug_update_level .NE. no_check .AND. set_check) then
2772  do m = 1,size(checklist(:))
2773  call deallocate_overlap_type(checklist(m))
2774  enddo
2775  endif
2776 
2777  deallocate(overlaplist)
2778  if(set_check) deallocate(checklist)
2779  domain%initialized = .true.
2780 
2781  end subroutine compute_overlaps
2782 
2783 
2784  subroutine fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2785  isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2786  type(overlap_type), intent(inout) :: overlap
2787  type(domain2d), intent(inout) :: domain
2788  integer, intent(in ) :: m, is, ie, js, je
2789  integer, intent(in ) :: isc, iec, jsc, jec
2790  integer, intent(in ) :: isg, ieg, dir, ioff
2791  logical, intent(in ) :: is_cyclic
2792  logical, optional, intent(in ) :: folded, symmetry
2793 
2794  call insert_update_overlap( overlap, domain%list(m)%pe, &
2795  is, ie, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2796  if(is_cyclic) then
2797  if(ie .GT. ieg) then
2798  call insert_update_overlap( overlap, domain%list(m)%pe, &
2799  is-ioff, ie-ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2800  else if( is .LT. isg ) then
2801  call insert_update_overlap( overlap, domain%list(m)%pe, &
2802  is+ioff, ie+ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2803  endif
2804  endif
2805 
2806  end subroutine fill_overlap_send_nofold
2807  !##################################################################################
2808  subroutine fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2809  isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2810  type(overlap_type), intent(inout) :: overlap
2811  type(domain2d), intent(inout) :: domain
2812  integer, intent(in ) :: m, is, ie, js, je
2813  integer, intent(in ) :: isc, iec, jsc, jec
2814  integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2815  logical, optional, intent(in ) :: symmetry
2816  integer :: is1, ie1, is2, ie2, i
2817 
2818  !--- consider at j = jeg for west edge.
2819  !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2820  if(position == corner .AND. .NOT. domain%symmetry .AND. is .LE. isg-1 .AND. ie .GE. isg-1) then
2821  call insert_update_overlap(overlap, domain%list(m)%pe, &
2822  isg-1+ioff, isg-1+ioff, je, je, isc, iec, jsc, jec, dir, .true.)
2823  end if
2824 
2825  is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2826  !--- east edge
2827  if( is > ieg ) then
2828  is2 = is-ioff; ie2 = ie-ioff
2829  else if( ie > ieg ) then ! split into two parts
2830  is1 = is; ie1 = ieg
2831  is2 = ieg+1-ioff; ie2 = ie-ioff
2832  else if( is .GE. middle ) then
2833  is1 = is; ie1 = ie
2834  else if( ie .GE. middle ) then ! split into two parts
2835  is1 = middle; ie1 = ie
2836  is2 = is; ie2 = middle-1
2837  else if( ie < isg ) then ! west boundary
2838  is1 = is+ieg-isg+1-ishift; ie1 = ie+ieg-isg+1-ishift
2839  else if( is < isg ) then ! split into two parts
2840  is1 = is+ieg-isg+1-ishift; ie1 = isg-1+ieg-isg+1-ishift
2841  is2 = isg; ie2 = ie
2842  else
2843  is2 = is; ie2 = ie
2844  endif
2845 
2846  if( ie1 .GE. is1) then
2847  call insert_update_overlap( overlap, domain%list(m)%pe, &
2848  is1, ie1, js, je-1, isc, iec, jsc, jec, dir, symmetry=symmetry)
2849 
2850  select case (position)
2851  case(north)
2852  i=is1; is1 = isg+ieg-ie1; ie1 = isg+ieg-i
2853  case(corner)
2854  i=is1; is1 = isg+ieg-ie1-1+ishift; ie1 = isg+ieg-i-1+ishift
2855  end select
2856  call insert_update_overlap( overlap, domain%list(m)%pe, &
2857  is1, ie1, je, je, isc, iec, jsc, jec, dir, .true., symmetry=symmetry)
2858  endif
2859 
2860  if(ie2 .GE. is2) then
2861  call insert_update_overlap( overlap, domain%list(m)%pe, &
2862  is2, ie2, js, je, isc, iec, jsc, jec, dir)
2863  endif
2864 
2865  end subroutine fill_overlap_send_fold
2866 
2867 
2868  !#############################################################################
2869  subroutine fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2870  isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2871  type(overlap_type), intent(inout) :: overlap
2872  type(domain2d), intent(inout) :: domain
2873  integer, intent(in ) :: m, is, ie, js, je
2874  integer, intent(in ) :: isd, ied, jsd, jed
2875  integer, intent(in ) :: isg, ieg, dir, ioff
2876  logical, intent(in ) :: is_cyclic
2877  logical, optional, intent(in ) :: folded, symmetry
2878  integer :: is1, ie1, is2, ie2
2879  integer :: isd1, ied1, isd2, ied2
2880 
2881  is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2882  isd1=isd; ied1=ied
2883  isd2=isd; ied2=ied
2884 
2885  call insert_update_overlap( overlap, domain%list(m)%pe, &
2886  is, ie, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2887  if(is_cyclic) then
2888  if(ied .GT. ieg) then
2889  call insert_update_overlap( overlap, domain%list(m)%pe, &
2890  is+ioff, ie+ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2891  else if( isd .LT. isg ) then
2892  call insert_update_overlap( overlap, domain%list(m)%pe, &
2893  is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2894  else if ( is .LT. isg ) then
2895  call insert_update_overlap( overlap, domain%list(m)%pe, &
2896  is+ioff, ie+ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2897  else if ( ie .GT. ieg ) then
2898  call insert_update_overlap( overlap, domain%list(m)%pe, &
2899  is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2900  endif
2901  endif
2902 
2903  end subroutine fill_overlap_recv_nofold
2904  !#################################################################################
2905  subroutine fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2906  isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2907  type(overlap_type), intent(inout) :: overlap
2908  type(domain2d), intent(inout) :: domain
2909  integer, intent(in ) :: m, is, ie, js, je
2910  integer, intent(in ) :: isd, ied, jsd, jed
2911  integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2912  logical, optional, intent(in ) :: symmetry
2913  integer :: is1, ie1, is2, ie2, is3, ie3
2914  integer :: isd1, ied1, isd2, ied2
2915 
2916  !--- consider at j = jeg for west edge.
2917  !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2918  if( position == corner .AND. .NOT. domain%symmetry .AND. isd .LE. isg-1 .AND. ied .GE. isg-1 ) then
2919  call insert_update_overlap( overlap, domain%list(m)%pe, &
2920  is-ioff, ie-ioff, js, je, isg-1, isg-1, jed, jed, dir, .true.)
2921  end if
2922 
2923  is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2924  isd1=isd; ied1=ied
2925  isd2=isd; ied2=ied
2926  select case (position)
2927  case(north)
2928  is3 = isg+ieg-ie; ie3 = isg+ieg-is
2929  case(corner)
2930  is3 = isg+ieg-ie-1+ishift; ie3 = isg+ieg-is-1+ishift
2931  end select
2932 
2933  if(isd .GT. ieg) then ! east
2934  is2 = is + ioff; ie2 = ie + ioff;
2935  else if(ied .GT. ieg) then ! split into two parts
2936  is1 = is; ie1 = ie;
2937  isd1 = isd; ied1 = ieg;
2938  is2 = is + ioff; ie2 = ie + ioff
2939  isd2 = ieg + 1; ied2 = ied
2940  else if(isd .GE. middle) then
2941  is1 = is; ie1 = ie
2942  else if(ied .GE. middle) then ! split into two parts
2943  is1 = is; ie1 = ie
2944  isd1 = middle; ied1 = ied
2945  is2 = is; ie2 = ie
2946  isd2 = isd; ied2 = middle-1
2947  else if(ied .LT. isg) then
2948  is1 = is - ioff; ie1 = ie - ioff;
2949  is3 = is3 - ioff; ie3 = ie3 - ioff;
2950  else if(isd .LT. isg) then ! split into two parts
2951  is1 = is - ioff; ie1 = ie - ioff;
2952  is3 = is3 - ioff; ie3 = ie3 - ioff;
2953  isd1 = isd; ied1 = isg-1
2954  is2 = is; ie2 = ie
2955  isd2 = isg; ied2 = ied
2956  else
2957  is2 = is ; ie2 =ie
2958  isd2 = isd; ied2 = ied
2959  endif
2960 
2961  if( ie1 .GE. is1) then
2962  call insert_update_overlap( overlap, domain%list(m)%pe, &
2963  is1, ie1, js, je, isd1, ied1, jsd, jed-1, dir, symmetry=symmetry)
2964 
2965  call insert_update_overlap( overlap, domain%list(m)%pe, &
2966  is3, ie3, js, je, isd1, ied1, jed, jed, dir, .true., symmetry=symmetry)
2967  endif
2968 
2969  if(ie2 .GE. is2) then
2970  call insert_update_overlap( overlap, domain%list(m)%pe, &
2971  is2, ie2, js, je, isd2, ied2, jsd, jed, dir)
2972  endif
2973 
2974  end subroutine fill_overlap_recv_fold
2975 
2976 !#####################################################################################
2977  subroutine fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2978  isg, ieg, jsg, jeg, dir, reverse, symmetry)
2979  type(overlap_type), intent(inout) :: overlap
2980  type(domain2d), intent(inout) :: domain
2981  integer, intent(in ) :: m, is, ie, js, je
2982  integer, intent(in ) :: isc, iec, jsc, jec
2983  integer, intent(in ) :: isg, ieg, jsg, jeg
2984  integer, intent(in ) :: dir
2985  logical, optional, intent(in ) :: reverse, symmetry
2986 
2987  if(js > je) then ! seperate into two regions due to x_cyclic_offset is nonzero, the two region are
2988  ! (js, jeg) and (jsg, je).
2989  call insert_update_overlap( overlap, domain%list(m)%pe, &
2990  is, ie, jsg, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2991  call insert_update_overlap( overlap, domain%list(m)%pe, &
2992  is, ie, js, jeg, isc, iec, jsc, jec, dir, reverse, symmetry)
2993  else if(is > ie) then ! seperate into two regions due to y_cyclic_offset is nonzero, the two region are
2994  ! (is, ieg) and (isg, ie).
2995  call insert_update_overlap( overlap, domain%list(m)%pe, &
2996  is, ieg, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2997  call insert_update_overlap( overlap, domain%list(m)%pe, &
2998  isg, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2999  else
3000  call insert_update_overlap( overlap, domain%list(m)%pe, &
3001  is, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
3002  end if
3003 
3004 
3005  end subroutine fill_overlap
3006 
3007  !####################################################################################
3008  !> Computes remote domain overlaps
3009  !! assumes only one in each direction
3010  !! will calculate the overlapping for T,E,C,N-cell seperately.
3011  subroutine compute_overlaps_fold_south( domain, position, ishift, jshift)
3012  type(domain2d), intent(inout) :: domain
3013  integer, intent(in) :: position, ishift, jshift
3014 
3015  integer :: i, m, n, nlist, tMe, tNbr, dir
3016  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3017  integer :: isg, ieg, jsg, jeg, ioff, joff
3018  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3019  integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3020  logical :: folded
3021  type(overlap_type) :: overlap
3022  type(overlapspec), pointer :: update=>null()
3023  type(overlap_type), pointer :: overlapList(:)=>null()
3024  type(overlap_type), pointer :: checkList(:)=>null()
3025  type(overlapspec), pointer :: check =>null()
3026  integer :: nsend, nrecv
3027  integer :: nsend_check, nrecv_check
3028  integer :: iunit
3029 
3030  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3031  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3032  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3033  if(size(domain%x(:)) > 1) return
3034 
3035  !--- if there is no halo, no need to compute overlaps.
3036  if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3037 
3038  !--- when there is only one tile, n will equal to np
3039  nlist = size(domain%list(:))
3040 
3041  select case(position)
3042  case (center)
3043  update => domain%update_T
3044  check => null()
3045  case (corner)
3046  update => domain%update_C
3047  check => domain%check_C
3048  case (east)
3049  update => domain%update_E
3050  check => domain%check_E
3051  case (north)
3052  update => domain%update_N
3053  check => domain%check_N
3054  case default
3055  call mpp_error(fatal, &
3056  "mpp_domains_define.inc(compute_overlaps_fold_south): the value of position should be CENTER, EAST, &
3057  & CORNER or NORTH")
3058  end select
3059 
3060  allocate(overlaplist(maxlist) )
3061  allocate(checklist(maxlist) )
3062 
3063  !--- overlap is used to store the overlapping temporarily.
3064  call allocate_update_overlap( overlap, maxoverlap)
3065 
3066  !send
3067  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3068  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3069  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3070  update%xbegin = ism; update%xend = iem
3071  update%ybegin = jsm; update%yend = jem
3072  if(ASSOCIATED(check)) then
3073  check%xbegin = ism; check%xend = iem
3074  check%ybegin = jsm; check%yend = jem
3075  endif
3076  update%whalo = domain%whalo; update%ehalo = domain%ehalo
3077  update%shalo = domain%shalo; update%nhalo = domain%nhalo
3078  whalo = domain%whalo; ehalo = domain%ehalo
3079  shalo = domain%shalo; nhalo = domain%nhalo
3080 
3081 
3082  ioff = ni - ishift
3083  joff = nj - jshift
3084  middle = (isg+ieg)/2+1
3085  tme = 1; tnbr = 1
3086 
3087  if(.NOT. btest(domain%fold,south)) then
3088  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3089  "boundary condition in y-direction should be folded-south for "//trim(domain%name))
3090  endif
3091  if(.NOT. domain%x(tme)%cyclic) then
3092  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3093  "boundary condition in x-direction should be cyclic for "//trim(domain%name))
3094  endif
3095 
3096  if(.not. domain%symmetry) then
3097  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3098  "when south boundary is folded, the domain must be symmetry for "//trim(domain%name))
3099  endif
3100 
3101  nsend = 0
3102  nsend_check = 0
3103  do list = 0,nlist-1
3104  m = mod( domain%pos+list, nlist )
3105  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3106  !to_pe's eastern halo
3107  dir = 1
3108  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3109  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3110  !--- to make sure the consistence between pes
3111  if( (position == north .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3112  !--- do nothing, this point will come from other pe
3113  else
3114  if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3115  is = is-ioff; ie = ie-ioff
3116  end if
3117  !--- when the south face is folded, the east halo point at right side domain will be folded.
3118  !--- the position should be on CORNER or NORTH
3119  if( js == jsg .AND. (position == corner .OR. position == north) &
3120  .AND. is .GE. middle .AND. domain%list(m)%x(tnbr)%compute%end+ehalo+jshift .LE. ieg ) then
3121  call insert_update_overlap( overlap, domain%list(m)%pe, &
3122  is, ie, js+1, je, isc, iec, jsc, jec, dir)
3123  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3124  je = js
3125  select case (position)
3126  case(north)
3127  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3128  case(corner)
3129  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3130  end select
3131  call insert_update_overlap( overlap, domain%list(m)%pe, &
3132  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3133  else
3134  call insert_update_overlap( overlap, domain%list(m)%pe, &
3135  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3136  end if
3137  end if
3138 
3139  !to_pe's SE halo
3140  dir = 2
3141  folded = .false.
3142  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3143  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3144  if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3145  is = is-ioff; ie = ie-ioff
3146  end if
3147  if( js.LT.jsg )then
3148  folded = .true.
3149  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3150  end if
3151 
3152  call insert_update_overlap( overlap, domain%list(m)%pe, &
3153  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3154 
3155  !to_pe's southern halo
3156  dir = 3
3157  folded = .false.
3158  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3159  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3160  folded = .false.
3161  if( js.LT.jsg )then
3162  folded = .true.
3163  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3164  end if
3165  !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3166  !--- no need to send, because the data on that point will come from other pe.
3167  !--- come from two pe ( there will be only one point on one pe. ).
3168  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3169  !--- do nothing, this point will come from other pe
3170  else
3171  call insert_update_overlap( overlap, domain%list(m)%pe, &
3172  is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3173  endif
3174  !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3175  if(is .LT. isg) then
3176  is = is + ioff
3177  call insert_update_overlap( overlap, domain%list(m)%pe, &
3178  is, is, js, je, isc, iec, jsc, jec, dir, folded)
3179  endif
3180 
3181  !to_pe's SW halo
3182  dir = 4
3183  folded = .false.
3184  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3185  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3186  if( isg.GT.is .AND. ie.LT.isc )then !cyclic offset
3187  is = is+ioff; ie = ie+ioff
3188  end if
3189  if( js.LT.jsg )then
3190  folded = .true.
3191  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3192  end if
3193  call insert_update_overlap( overlap, domain%list(m)%pe, &
3194  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3195  !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3196  if(is .LT. isg) then
3197  is = is + ioff
3198  call insert_update_overlap( overlap, domain%list(m)%pe, &
3199  is, is, js, je, isc, iec, jsc, jec, dir, folded)
3200  endif
3201 
3202  !to_pe's western halo
3203  dir = 5
3204  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3205  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3206 
3207  !--- to make sure the consistence between pes
3208  if( (position == north .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3209  !--- do nothing, this point will come from other pe
3210  else
3211  if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3212  is = is+ioff; ie = ie+ioff
3213  end if
3214  !--- when the south face is folded, some point at j=nj will be folded.
3215  !--- the position should be on CORNER or NORTH
3216  if( js == jsg .AND. (position == corner .OR. position == north) &
3217  .AND. ( domain%list(m)%x(tnbr)%compute%begin == isg .OR. &
3218  & domain%list(m)%x(tnbr)%compute%begin-1 .GE. middle)) then
3219  call insert_update_overlap( overlap, domain%list(m)%pe, &
3220  is, ie, js+1, je, isc, iec, jsc, jec, dir)
3221  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3222  js = domain%list(m)%y(tnbr)%compute%begin; je = js
3223  if ( domain%list(m)%x(tnbr)%compute%begin == isg ) then
3224  select case (position)
3225  case(north)
3226  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3227  case(corner)
3228  i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3229  end select
3230  if(ie .GT. domain%x(tme)%compute%end+ishift) call mpp_error( fatal, &
3231  'mpp_domains_define.inc(compute_overlaps_fold_south): west edge ubound error send.' )
3232  else
3233  select case (position)
3234  case(north)
3235  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3236  case(corner)
3237  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3238  end select
3239  end if
3240  call insert_update_overlap( overlap, domain%list(m)%pe, &
3241  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3242  else
3243  call insert_update_overlap( overlap, domain%list(m)%pe, &
3244  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3245  end if
3246  endif
3247 
3248  !to_pe's NW halo
3249  dir = 6
3250  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3251  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3252  if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3253  is = is+ioff; ie = ie+ioff
3254  end if
3255  call insert_update_overlap( overlap, domain%list(m)%pe, &
3256  is, ie, js, je, isc, iec, jsc, jec, dir)
3257 
3258  !to_pe's northern halo
3259  dir = 7
3260  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3261  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3262  call insert_update_overlap( overlap, domain%list(m)%pe, &
3263  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3264 
3265  !to_pe's NE halo
3266  dir = 8
3267  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3268  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3269  if( ie.GT.ieg .AND. iec.LT.is )then !cyclic offset
3270  is = is-ioff; ie = ie-ioff
3271  end if
3272  call insert_update_overlap( overlap, domain%list(m)%pe, &
3273  is, ie, js, je, isc, iec, jsc, jec, dir)
3274 
3275  !--- Now calculate the overlapping for fold-edge.
3276  !--- only position at NORTH and CORNER need to be considered
3277  if( ( position == north .OR. position == corner) ) then
3278  !fold is within domain
3279  if( domain%y(tme)%domain_data%begin .LE. jsg .AND. jsg .LE. domain%y(tme)%domain_data%end+jshift )then
3280  dir = 3
3281  !--- calculate the overlapping for sending
3282  if( domain%x(tme)%pos .LT. (size(domain%x(tme)%list(:))+1)/2 )then
3283  js = domain%list(m)%y(tnbr)%compute%begin; je = js
3284  if( js == jsg )then ! fold is within domain.
3285  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3286  select case (position)
3287  case(north)
3288  is = max(is, middle)
3289  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3290  case(corner)
3291  is = max(is, middle)
3292  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3293  end select
3294  call insert_update_overlap(overlap, domain%list(m)%pe, &
3295  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3296  is = max(is, isc); ie = min(ie, iec)
3297  js = max(js, jsc); je = min(je, jec)
3298  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3299  nsend_check = nsend_check+1
3300  call allocate_check_overlap(checklist(nsend_check), 1)
3301  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
3302  tme, 2, one_hundred_eighty, is, ie, js, je)
3303  end if
3304  end if
3305  end if
3306  end if
3307  end if
3308  end if
3309  !--- copy the overlapping information
3310  if( overlap%count > 0) then
3311  nsend = nsend + 1
3312  if(nsend > size(overlaplist(:)) ) then
3313  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for send is expanded')
3314  call expand_update_overlap_list(overlaplist, nlist)
3315  endif
3316  call add_update_overlap(overlaplist(nsend), overlap)
3317  call init_overlap_type(overlap)
3318  endif
3319  end do ! end of send set up.
3320 
3321  if(debug_message_passing) then
3322  !--- write out send information
3323  iunit = mpp_pe() + 1000
3324  do m =1,nsend
3325  write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3326  do n = 1, overlaplist(m)%count
3327  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3328  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3329  enddo
3330  enddo
3331  if( nsend > 0) flush(iunit)
3332  endif
3333 
3334  ! copy the overlapping information into domain data structure
3335  if(nsend>0) then
3336  if (associated(update%send)) deallocate(update%send) !< Check if associated
3337  allocate(update%send(nsend))
3338  update%nsend = nsend
3339  do m = 1, nsend
3340  call add_update_overlap( update%send(m), overlaplist(m) )
3341  enddo
3342  endif
3343 
3344  if(nsend_check>0) then
3345  if (associated(check%send)) deallocate(check%send) !< Check if associated
3346  allocate(check%send(nsend_check))
3347  check%nsend = nsend_check
3348  do m = 1, nsend_check
3349  call add_check_overlap( check%send(m), checklist(m) )
3350  enddo
3351  endif
3352 
3353  do m = 1,size(overlaplist(:))
3354  call deallocate_overlap_type(overlaplist(m))
3355  enddo
3356 
3357  if(debug_update_level .NE. no_check) then
3358  do m = 1,size(checklist(:))
3359  call deallocate_overlap_type(checklist(m))
3360  enddo
3361  endif
3362 
3363  isgd = isg - domain%whalo
3364  iegd = ieg + domain%ehalo
3365  jsgd = jsg - domain%shalo
3366  jegd = jeg + domain%nhalo
3367 
3368  ! begin setting up recv
3369  nrecv = 0
3370  nrecv_check = 0
3371  do list = 0,nlist-1
3372  m = mod( domain%pos+nlist-list, nlist )
3373  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3374  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
3375  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
3376  !recv_e
3377  dir = 1
3378  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3379  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
3380  is=isc; ie=iec; js=jsc; je=jec
3381  if( (position == north .OR. position == corner ) .AND. ( jsd == je .or. jed == js ) ) then
3382  ! --- do nothing, this point will come from other pe
3383  else
3384  if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3385  is = is+ioff; ie = ie+ioff
3386  end if
3387 
3388  !--- when the south face is folded, the east halo point at right side domain will be folded.
3389  !--- the position should be on CORNER or NORTH
3390  if( jsd == jsg .AND. (position == corner .OR. position == north) &
3391  .AND. isd .GE. middle .AND. ied .LE. ieg ) then
3392  call insert_update_overlap( overlap, domain%list(m)%pe, &
3393  is, ie, js, je, isd, ied, jsd+1, jed, dir)
3394  is=isc; ie=iec; js=jsc; je=jec
3395  jed = jsd
3396  select case (position)
3397  case(north)
3398  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3399  case(corner)
3400  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3401  end select
3402  call insert_update_overlap( overlap, domain%list(m)%pe, &
3403  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
3404  else
3405  call insert_update_overlap( overlap, domain%list(m)%pe, &
3406  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3407  end if
3408  end if
3409 
3410  !recv_se
3411  dir = 2
3412  folded = .false.
3413  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3414  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3415  is=isc; ie=iec; js=jsc; je=jec
3416  if( jsd.LT.jsg )then
3417  folded = .true.
3418  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3419  end if
3420  if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3421  is = is+ioff; ie = ie+ioff
3422  endif
3423  call insert_update_overlap(overlap, domain%list(m)%pe, &
3424  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3425 
3426  !recv_s
3427  dir = 3
3428  folded = .false.
3429  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3430  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3431  is=isc; ie=iec; js=jsc; je=jec
3432  if( jsd.LT.jsg )then
3433  folded = .true.
3434  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3435  end if
3436  if( (position == east .OR. position == corner ) .AND. (isd == ie .or. ied == is ) ) then
3437  !--- do nothing, this point will come from other pe
3438  else
3439  call insert_update_overlap(overlap, domain%list(m)%pe, &
3440  is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
3441  end if
3442  !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3443  if(is .LT. isg ) then
3444  is = is + ioff
3445  call insert_update_overlap(overlap, domain%list(m)%pe, &
3446  is, is, js, je, isd, ied, jsd, jed, dir, folded)
3447  endif
3448 
3449  !recv_sw
3450  dir = 4
3451  folded = .false.
3452  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3453  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3454  is=isc; ie=iec; js=jsc; je=jec
3455  if( jsd.LT.jsg )then
3456  folded = .true.
3457  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3458  end if
3459  if( isd.LT.isg .AND. is.GT.ied ) then ! cyclic offset
3460  is = is-ioff; ie = ie-ioff
3461  end if
3462  call insert_update_overlap(overlap, domain%list(m)%pe, &
3463  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3464  !--- when southth edge is folded, is will be less than isg when position is EAST and CORNER
3465  if(is .LT. isg ) then
3466  is = is + ioff
3467  call insert_update_overlap(overlap, domain%list(m)%pe, &
3468  is, is, js, je, isd, ied, jsd, jed, dir, folded )
3469  endif
3470 
3471  !recv_w
3472  dir = 5
3473  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3474  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
3475  is=isc; ie=iec; js=jsc; je=jec
3476  if( (position == north .OR. position == corner ) .AND. ( jsd == je .or. jed == js ) ) then
3477  ! --- do nothing, this point will come from other pe
3478  else
3479  if( isd.LT.isg .AND. is.GT.ied )then ! cyclic offset
3480  is = is-ioff; ie = ie-ioff
3481  end if
3482  !--- when the south face is folded, some point at j=nj will be folded.
3483  !--- the position should be on CORNER or NORTH
3484  if( jsd == jsg .AND. (position == corner .OR. position == north) &
3485  .AND. ( isd < isg .OR. ied .GE. middle ) ) then
3486  call insert_update_overlap(overlap, domain%list(m)%pe, &
3487  is, ie, js, je, isd, ied, jsd+1, jed, dir)
3488  is=isc; ie=iec; js=jsc; je=jec
3489  if(isd < isg) then
3490  select case (position)
3491  case(north)
3492  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3493  case(corner)
3494  ied = ied -1 + ishift
3495  i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3496  end select
3497  if(ie .GT. domain%x(tme)%compute%end+ishift) call mpp_error( fatal, &
3498  'mpp_domains_define.inc(compute_overlaps): west edge ubound error recv.' )
3499  else
3500  select case (position)
3501  case(north)
3502  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3503  case(corner)
3504  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3505  end select
3506  end if
3507  call insert_update_overlap(overlap, domain%list(m)%pe, &
3508  is, ie, js, je, isd, ied, jsd, jsd, dir, .true.)
3509  else
3510  call insert_update_overlap(overlap, domain%list(m)%pe, &
3511  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3512  end if
3513  endif
3514 
3515  !recv_nw
3516  dir = 6
3517  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3518  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3519  is=isc; ie=iec; js=jsc; je=jec
3520  if( isd.LT.isg .AND. is.GE.ied )then !cyclic offset
3521  is = is-ioff; ie = ie-ioff
3522  endif
3523 
3524  call insert_update_overlap( overlap, domain%list(m)%pe, &
3525  is, ie, js, je, isd, ied, jsd, jed, dir)
3526 
3527  !recv_n
3528  dir = 7
3529  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3530  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3531  is=isc; ie=iec; js=jsc; je=jec
3532  call insert_update_overlap( overlap, domain%list(m)%pe, &
3533  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3534 
3535  !recv_ne
3536  dir = 8
3537  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3538  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3539  is=isc; ie=iec; js=jsc; je=jec
3540  if( ied.GT.ieg .AND. ie.LT.isd )then ! cyclic offset
3541  is = is+ioff; ie = ie+ioff
3542  end if
3543  call insert_update_overlap( overlap, domain%list(m)%pe, &
3544  is, ie, js, je, isd, ied, jsd, jed, dir)
3545 
3546  !--- Now calculate the overlapping for fold-edge.
3547  !--- for folded-south-edge, only need to consider to_pe's south(3) direction
3548  !--- only position at NORTH and CORNER need to be considered
3549  if( ( position == north .OR. position == corner) ) then
3550  !fold is within domain
3551  if( domain%y(tme)%domain_data%begin .LE. jsg .AND. jsg .LE. domain%y(tme)%domain_data%end+jshift )then
3552  dir = 3
3553  !--- calculating overlapping for receving on north
3554  if( domain%x(tme)%pos .GE. size(domain%x(tme)%list(:))/2 )then
3555  jsd = domain%y(tme)%compute%begin; jed = jsd
3556  if( jsd == jsg )then ! fold is within domain.
3557  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3558  is=isc; ie=iec; js = jsc; je = jec
3559  select case (position)
3560  case(north)
3561  isd = max(isd, middle)
3562  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3563  case(corner)
3564  isd = max(isd, middle)
3565  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3566  end select
3567  call insert_update_overlap(overlap, domain%list(m)%pe, &
3568  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
3569  is = max(is, isd); ie = min(ie, ied)
3570  js = max(js, jsd); je = min(je, jed)
3571  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3572  nrecv_check = nrecv_check+1
3573  call allocate_check_overlap(checklist(nrecv_check), 1)
3574  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
3575  tme, 2, one_hundred_eighty, is, ie, js, je)
3576  endif
3577  endif
3578  endif
3579  endif
3580  endif
3581  endif
3582  !--- copy the overlapping information
3583  if( overlap%count > 0) then
3584  nrecv = nrecv + 1
3585  if(nrecv > size(overlaplist(:)) )then
3586  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for recv is expanded')
3587  call expand_update_overlap_list(overlaplist, nlist)
3588  endif
3589  call add_update_overlap( overlaplist(nrecv), overlap)
3590  call init_overlap_type(overlap)
3591  endif
3592  enddo ! end of recv do loop
3593 
3594  if(debug_message_passing) then
3595  !--- write out send information
3596  iunit = mpp_pe() + 1000
3597  do m =1,nrecv
3598  write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3599  do n = 1, overlaplist(m)%count
3600  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3601  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3602  enddo
3603  enddo
3604  if(nrecv >0) flush(iunit)
3605  endif
3606 
3607  ! copy the overlapping information into domain
3608  if(nrecv>0) then
3609  update%nrecv = nrecv
3610  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
3611  allocate(update%recv(nrecv))
3612  do m = 1, nrecv
3613  call add_update_overlap( update%recv(m), overlaplist(m) )
3614  do n = 1, update%recv(m)%count
3615  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
3616  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
3617  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
3618  endif
3619  enddo
3620  enddo
3621  endif
3622 
3623  if(nrecv_check>0) then
3624  check%nrecv = nrecv_check
3625  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
3626  allocate(check%recv(nrecv_check))
3627  do m = 1, nrecv_check
3628  call add_check_overlap( check%recv(m), checklist(m) )
3629  enddo
3630  endif
3631 
3632  call deallocate_overlap_type(overlap)
3633 
3634  do m = 1,size(overlaplist(:))
3635  call deallocate_overlap_type(overlaplist(m))
3636  enddo
3637 
3638  if(debug_update_level .NE. no_check) then
3639  do m = 1,size(checklist(:))
3640  call deallocate_overlap_type(checklist(m))
3641  enddo
3642  endif
3643 
3644  deallocate(overlaplist)
3645  deallocate(checklist)
3646  update => null()
3647  check=>null()
3648  domain%initialized = .true.
3649 
3650  end subroutine compute_overlaps_fold_south
3651 
3652  !####################################################################################
3653  !> Computes remote domain overlaps
3654  !! assumes only one in each direction
3655  !! will calculate the overlapping for T,E,C,N-cell seperately.
3656  subroutine compute_overlaps_fold_west( domain, position, ishift, jshift)
3657  type(domain2d), intent(inout) :: domain
3658  integer, intent(in) :: position, ishift, jshift
3659 
3660  integer :: j, m, n, nlist, tMe, tNbr, dir
3661  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3662  integer :: isg, ieg, jsg, jeg, ioff, joff
3663  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3664  integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3665  logical :: folded
3666  type(overlap_type) :: overlap
3667  type(overlapspec), pointer :: update=>null()
3668  type(overlap_type) :: overlapList(MAXLIST)
3669  type(overlap_type) :: checkList(MAXLIST)
3670  type(overlapspec), pointer :: check =>null()
3671  integer :: nsend, nrecv
3672  integer :: nsend_check, nrecv_check
3673  integer :: iunit
3674 
3675  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3676  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3677  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3678  if(size(domain%x(:)) > 1) return
3679 
3680  !--- if there is no halo, no need to compute overlaps.
3681  if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3682 
3683  !--- when there is only one tile, n will equal to np
3684  nlist = size(domain%list(:))
3685 
3686  select case(position)
3687  case (center)
3688  update => domain%update_T
3689  check => null()
3690  case (corner)
3691  update => domain%update_C
3692  check => domain%check_C
3693  case (east)
3694  update => domain%update_E
3695  check => domain%check_E
3696  case (north)
3697  update => domain%update_N
3698  check => domain%check_N
3699  case default
3700  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west):"//&
3701  & " the value of position should be CENTER, EAST, CORNER or NORTH")
3702  end select
3703 
3704  !--- overlap is used to store the overlapping temporarily.
3705  call allocate_update_overlap( overlap, maxoverlap)
3706 
3707  !send
3708  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3709  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3710  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3711  update%xbegin = ism; update%xend = iem
3712  update%ybegin = jsm; update%yend = jem
3713  if(ASSOCIATED(check)) then
3714  check%xbegin = ism; check%xend = iem
3715  check%ybegin = jsm; check%yend = jem
3716  endif
3717  update%whalo = domain%whalo; update%ehalo = domain%ehalo
3718  update%shalo = domain%shalo; update%nhalo = domain%nhalo
3719  whalo = domain%whalo; ehalo = domain%ehalo
3720  shalo = domain%shalo; nhalo = domain%nhalo
3721 
3722  ioff = ni - ishift
3723  joff = nj - jshift
3724  middle = (jsg+jeg)/2+1
3725  tme = 1; tnbr = 1
3726 
3727  if(.NOT. btest(domain%fold,west)) then
3728  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3729  "boundary condition in y-direction should be folded-west for "//trim(domain%name))
3730  endif
3731  if(.NOT. domain%y(tme)%cyclic) then
3732  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3733  "boundary condition in y-direction should be cyclic for "//trim(domain%name))
3734  endif
3735 
3736  if(.not. domain%symmetry) then
3737  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3738  "when west boundary is folded, the domain must be symmetry for "//trim(domain%name))
3739  endif
3740 
3741  nsend = 0
3742  nsend_check = 0
3743  do list = 0,nlist-1
3744  m = mod( domain%pos+list, nlist )
3745  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3746  !to_pe's eastern halo
3747  dir = 1
3748  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3749  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3750  call insert_update_overlap( overlap, domain%list(m)%pe, &
3751  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3752 
3753  !to_pe's SE halo
3754  dir = 2
3755  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3756  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3757  if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
3758  js = js+joff; je = je+joff
3759  end if
3760 
3761  call insert_update_overlap( overlap, domain%list(m)%pe, &
3762  is, ie, js, je, isc, iec, jsc, jec, dir)
3763 
3764  !to_pe's southern halo
3765  dir = 3
3766  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3767  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3768  !--- to make sure the consistence between pes
3769  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3770  !--- do nothing, this point will come from other pe
3771  else
3772  if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
3773  js = js+joff; je = je+joff
3774  endif
3775 
3776  !--- when the west face is folded, the south halo points at
3777  !--- the position should be on CORNER or EAST
3778  if( is == isg .AND. (position == corner .OR. position == east) &
3779  .AND. ( domain%list(m)%y(tnbr)%compute%begin == jsg .OR. &
3780  & domain%list(m)%y(tnbr)%compute%begin-1 .GE. middle)) then
3781  call insert_update_overlap( overlap, domain%list(m)%pe, &
3782  is+1, ie, js, je, isc, iec, jsc, jec, dir)
3783  is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3784  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3785  if ( domain%list(m)%y(tnbr)%compute%begin == jsg ) then
3786  select case (position)
3787  case(east)
3788  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
3789  case(corner)
3790  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
3791  end select
3792  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
3793  'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error send.' )
3794  else
3795  select case (position)
3796  case(east)
3797  j=js; js = jsg+jeg-je; je = jsg+jeg-j
3798  case(corner)
3799  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3800  end select
3801  end if
3802  call insert_update_overlap( overlap, domain%list(m)%pe, &
3803  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3804  else
3805  call insert_update_overlap( overlap, domain%list(m)%pe, &
3806  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3807  end if
3808  endif
3809 
3810  !to_pe's SW halo
3811  dir = 4
3812  folded = .false.
3813  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3814  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3815  if( jsg.GT.js .AND. je.LT.jsc )then !cyclic offset
3816  js = js+joff; je = je+joff
3817  end if
3818  if( is.LT.isg )then
3819  folded = .true.
3820  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3821  end if
3822  call insert_update_overlap( overlap, domain%list(m)%pe, &
3823  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3824  !--- when south edge is folded, js will be less than jsg when position is EAST and CORNER
3825  if(js .LT. jsg) then
3826  js = js + joff
3827  call insert_update_overlap( overlap, domain%list(m)%pe, &
3828  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3829  endif
3830 
3831  !to_pe's western halo
3832  dir = 5
3833  folded = .false.
3834  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3835  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3836  if( isg.GT.is )then
3837  folded = .true.
3838  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3839  end if
3840  !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3841  !--- no need to send, because the data on that point will come from other pe.
3842  !--- come from two pe ( there will be only one point on one pe. ).
3843  if( (position == east .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3844  !--- do nothing, this point will come from other pe
3845  else
3846  call insert_update_overlap( overlap, domain%list(m)%pe, &
3847  is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3848  endif
3849  !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3850  if(js .LT. jsg) then
3851  js = js + ioff
3852  call insert_update_overlap( overlap, domain%list(m)%pe, &
3853  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3854  endif
3855 
3856  !to_pe's NW halo
3857  dir = 6
3858  folded = .false.
3859  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3860  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3861  if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
3862  js = js-joff; je = je-joff
3863  end if
3864  if( is.LT.isg )then
3865  folded = .true.
3866  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3867  end if
3868 
3869  call insert_update_overlap( overlap, domain%list(m)%pe, &
3870  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3871 
3872  !to_pe's northern halo
3873  dir = 7
3874  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3875  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3876  !--- to make sure the consistence between pes
3877  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3878  !--- do nothing, this point will come from other pe
3879  else
3880  if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
3881  js = js-joff; je = je-joff
3882  endif
3883  !--- when the west face is folded, the south halo points at
3884  !--- the position should be on CORNER or EAST
3885  if( is == isg .AND. (position == corner .OR. position == east) &
3886  .AND. ( js .GE. middle .AND. domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
3887  call insert_update_overlap( overlap, domain%list(m)%pe, &
3888  is+1, ie, js, je, isc, iec, jsc, jec, dir)
3889  is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3890  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3891  select case (position)
3892  case(east)
3893  j=js; js = jsg+jeg-je; je = jsg+jeg-j
3894  case(corner)
3895  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3896  end select
3897  call insert_update_overlap( overlap, domain%list(m)%pe, &
3898  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3899  else
3900  call insert_update_overlap( overlap, domain%list(m)%pe, &
3901  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3902  end if
3903  endif
3904 
3905  !to_pe's NE halo
3906  dir = 8
3907  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3908  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3909  if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
3910  js = js-joff; je = je-joff
3911  end if
3912  call insert_update_overlap( overlap, domain%list(m)%pe, &
3913  is, ie, js, je, isc, iec, jsc, jec, dir)
3914 
3915  !--- Now calculate the overlapping for fold-edge.
3916  !--- only position at EAST and CORNER need to be considered
3917  if( ( position == east .OR. position == corner) ) then
3918  !fold is within domain
3919  if( domain%x(tme)%compute%begin-whalo .LE. isg .AND. isg .LE. domain%x(tme)%domain_data%end+ishift )then
3920  dir = 5
3921  !--- calculate the overlapping for sending
3922  if( domain%y(tme)%pos .LT. (size(domain%y(tme)%list(:))+1)/2 )then
3923  is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3924  if( is == isg )then ! fold is within domain.
3925  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3926  select case (position)
3927  case(east)
3928  js = max(js, middle)
3929  j=js; js = jsg+jeg-je; je = jsg+jeg-j
3930  case(corner)
3931  js = max(js, middle)
3932  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3933  end select
3934  call insert_update_overlap(overlap, domain%list(m)%pe, &
3935  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3936  is = max(is, isc); ie = min(ie, iec)
3937  js = max(js, jsc); je = min(je, jec)
3938  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3939  nsend_check = nsend_check+1
3940  call allocate_check_overlap(checklist(nsend_check), 1)
3941  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
3942  tme, 3, one_hundred_eighty, is, ie, js, je)
3943  end if
3944  end if
3945  end if
3946  end if
3947  end if
3948  end if
3949  !--- copy the overlapping information
3950  if( overlap%count > 0) then
3951  nsend = nsend + 1
3952  if(nsend > maxlist) call mpp_error(fatal, &
3953  "mpp_domains_define.inc(compute_overlaps_west): nsend is greater than MAXLIST, increase MAXLIST")
3954  call add_update_overlap(overlaplist(nsend), overlap)
3955  call init_overlap_type(overlap)
3956  endif
3957  end do ! end of send set up.
3958 
3959  if(debug_message_passing) then
3960  !--- write out send information
3961  iunit = mpp_pe() + 1000
3962  do m =1,nsend
3963  write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3964  do n = 1, overlaplist(m)%count
3965  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3966  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3967  enddo
3968  enddo
3969  if(nsend >0) flush(iunit)
3970  endif
3971 
3972  ! copy the overlapping information into domain data structure
3973  if(nsend>0) then
3974  update%nsend = nsend
3975  if (associated(update%send)) deallocate(update%send) !< Check if associated
3976  allocate(update%send(nsend))
3977  do m = 1, nsend
3978  call add_update_overlap( update%send(m), overlaplist(m) )
3979  enddo
3980  endif
3981 
3982  if(nsend_check>0) then
3983  check%nsend = nsend_check
3984  if (associated(check%send)) deallocate(check%send) !< Check if associated
3985  allocate(check%send(nsend_check))
3986  do m = 1, nsend_check
3987  call add_check_overlap( check%send(m), checklist(m) )
3988  enddo
3989  endif
3990 
3991  do m = 1, maxlist
3992  call deallocate_overlap_type(overlaplist(m))
3993  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
3994  enddo
3995 
3996  isgd = isg - domain%whalo
3997  iegd = ieg + domain%ehalo
3998  jsgd = jsg - domain%shalo
3999  jegd = jeg + domain%nhalo
4000 
4001  ! begin setting up recv
4002  nrecv = 0
4003  nrecv_check = 0
4004  do list = 0,nlist-1
4005  m = mod( domain%pos+nlist-list, nlist )
4006  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4007  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4008  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4009  !recv_e
4010  dir = 1
4011  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4012  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4013  is=isc; ie=iec; js=jsc; je=jec
4014  call insert_update_overlap( overlap, domain%list(m)%pe, &
4015  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4016 
4017  !recv_se
4018  dir = 2
4019  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4020  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4021  is=isc; ie=iec; js=jsc; je=jec
4022  if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4023  js = js-joff; je = je-joff
4024  end if
4025  call insert_update_overlap(overlap, domain%list(m)%pe, &
4026  is, ie, js, je, isd, ied, jsd, jed, dir)
4027 
4028  !recv_s
4029  dir = 3
4030  folded = .false.
4031  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4032  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4033  is=isc; ie=iec; js=jsc; je=jec
4034 
4035  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4036  !--- do nothing, this point will come from other pe
4037  else
4038  if( jsd.LT.jsg .AND. js .GT. jed)then
4039  js = js-joff; je = je-joff
4040  end if
4041  !--- when the west face is folded, the south halo points at
4042  !--- the position should be on CORNER or EAST
4043  if( isd == isg .AND. (position == corner .OR. position == east) &
4044  .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4045  call insert_update_overlap( overlap, domain%list(m)%pe, &
4046  is, ie, js, je, isd+1, ied, jsd, jed, dir)
4047  is=isc; ie=iec; js=jsc; je=jec
4048  if(jsd<jsg) then
4049  select case (position)
4050  case(east)
4051  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4052  case(corner)
4053  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4054  end select
4055  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4056  'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4057  else
4058  select case (position)
4059  case(east)
4060  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4061  case(corner)
4062  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4063  end select
4064  end if
4065  call insert_update_overlap( overlap, domain%list(m)%pe, &
4066  is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4067  else
4068  call insert_update_overlap( overlap, domain%list(m)%pe, &
4069  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4070  end if
4071  endif
4072 
4073  !recv_sw
4074  dir = 4
4075  folded = .false.
4076  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4077  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4078  is=isc; ie=iec; js=jsc; je=jec
4079  if( isd.LT.isg )then
4080  folded = .true.
4081  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4082  end if
4083  if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4084  js = js-joff; je = je-joff
4085  end if
4086  call insert_update_overlap(overlap, domain%list(m)%pe, &
4087  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4088  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4089  if(js .LT. jsg ) then
4090  js = js + joff
4091  call insert_update_overlap(overlap, domain%list(m)%pe, &
4092  is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4093  endif
4094 
4095  !recv_w
4096  dir = 5
4097  folded = .false.
4098  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4099  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4100  is=isc; ie=iec; js=jsc; je=jec
4101  if( isd.LT.isg )then
4102  folded = .true.
4103  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4104  end if
4105  if( (position == east .OR. position == corner ) .AND. (jsd == je .or. jed == js ) ) then
4106  !--- do nothing, this point will come from other pe
4107  else
4108  call insert_update_overlap(overlap, domain%list(m)%pe, &
4109  is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4110  end if
4111  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4112  if(js .LT. jsg ) then
4113  js = js + joff
4114  call insert_update_overlap(overlap, domain%list(m)%pe, &
4115  is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4116  endif
4117 
4118  !recv_nw
4119  dir = 6
4120  folded = .false.
4121  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4122  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4123  is=isc; ie=iec; js=jsc; je=jec
4124  if( isd.LT.isg) then
4125  folded = .true.
4126  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4127  end if
4128  if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4129  js = js+joff; je = je+joff
4130  endif
4131 
4132  call insert_update_overlap( overlap, domain%list(m)%pe, &
4133  is, ie, js, je, isd, ied, jsd, jed, dir)
4134 
4135  !recv_n
4136  dir = 7
4137  folded = .false.
4138  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4139  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4140  is=isc; ie=iec; js=jsc; je=jec
4141  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4142  !--- do nothing, this point will come from other pe
4143  else
4144  if( jed.GT.jeg .AND. je.LT.jsd)then
4145  js = js+joff; je = je+joff
4146  end if
4147  !--- when the west face is folded, the south halo points at
4148  !--- the position should be on CORNER or EAST
4149  if( isd == isg .AND. (position == corner .OR. position == east) &
4150  .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4151  call insert_update_overlap( overlap, domain%list(m)%pe, &
4152  is, ie, js, je, isd+1, ied, jsd, jed, dir)
4153  is=isc; ie=iec; js=jsc; je=jec
4154  select case (position)
4155  case(east)
4156  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4157  case(corner)
4158  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4159  end select
4160  call insert_update_overlap( overlap, domain%list(m)%pe, &
4161  is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4162  else
4163  call insert_update_overlap( overlap, domain%list(m)%pe, &
4164  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4165  end if
4166  endif
4167 
4168  !recv_ne
4169  dir = 8
4170  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4171  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4172  is=isc; ie=iec; js=jsc; je=jec
4173  if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4174  js = js+joff; je = je+joff
4175  end if
4176  call insert_update_overlap( overlap, domain%list(m)%pe, &
4177  is, ie, js, je, isd, ied, jsd, jed, dir)
4178 
4179  !--- Now calculate the overlapping for fold-edge.
4180  !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4181  !--- only position at EAST and CORNER need to be considered
4182  if( ( position == east .OR. position == corner) ) then
4183  !fold is within domain
4184  if( domain%x(tme)%domain_data%begin .LE. isg .AND. isg .LE. domain%x(tme)%domain_data%end+ishift )then
4185  dir = 5
4186  !--- calculating overlapping for receving on north
4187  if( domain%y(tme)%pos .GE. size(domain%y(tme)%list(:))/2 )then
4188  isd = domain%x(tme)%compute%begin; ied = isd
4189  if( isd == isg )then ! fold is within domain.
4190  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4191  is=isc; ie=iec; js = jsc; je = jec
4192  select case (position)
4193  case(east)
4194  jsd = max(jsd, middle)
4195  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4196  case(corner)
4197  jsd = max(jsd, middle)
4198  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4199  end select
4200  call insert_update_overlap(overlap, domain%list(m)%pe, &
4201  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
4202  is = max(is, isd); ie = min(ie, ied)
4203  js = max(js, jsd); je = min(je, jed)
4204  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4205  nrecv_check = nrecv_check+1
4206  call allocate_check_overlap(checklist(nrecv_check), 1)
4207  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
4208  tme, 3, one_hundred_eighty, is, ie, js, je)
4209  endif
4210  endif
4211  endif
4212  endif
4213  endif
4214  endif
4215  !--- copy the overlapping information
4216  if( overlap%count > 0) then
4217  nrecv = nrecv + 1
4218  if(nrecv > maxlist) call mpp_error(fatal, &
4219  "mpp_domains_define.inc(compute_overlaps_west): nrecv is greater than MAXLIST, increase MAXLIST")
4220  call add_update_overlap( overlaplist(nrecv), overlap)
4221  call init_overlap_type(overlap)
4222  endif
4223  enddo ! end of recv do loop
4224 
4225  if(debug_message_passing) then
4226  !--- write out send information
4227  iunit = mpp_pe() + 1000
4228  do m =1,nrecv
4229  write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
4230  do n = 1, overlaplist(m)%count
4231  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
4232  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
4233  enddo
4234  enddo
4235  if(nrecv >0) flush(iunit)
4236  endif
4237 
4238  ! copy the overlapping information into domain
4239  if(nrecv>0) then
4240  update%nrecv = nrecv
4241  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
4242  allocate(update%recv(nrecv))
4243  do m = 1, nrecv
4244  call add_update_overlap( update%recv(m), overlaplist(m) )
4245  do n = 1, update%recv(m)%count
4246  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
4247  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
4248  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
4249  endif
4250  enddo
4251  enddo
4252  endif
4253 
4254  if(nrecv_check>0) then
4255  check%nrecv = nrecv_check
4256  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
4257  allocate(check%recv(nrecv_check))
4258  do m = 1, nrecv_check
4259  call add_check_overlap( check%recv(m), checklist(m) )
4260  enddo
4261  endif
4262 
4263  call deallocate_overlap_type(overlap)
4264  do m = 1, maxlist
4265  call deallocate_overlap_type(overlaplist(m))
4266  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4267  enddo
4268 
4269  update=>null()
4270  check=>null()
4271  domain%initialized = .true.
4272 
4273  end subroutine compute_overlaps_fold_west
4274 
4275  !###############################################################################
4276  !> computes remote domain overlaps
4277  !! assumes only one in each direction
4278  !! will calculate the overlapping for T,E,C,N-cell seperately.
4279  !! here assume fold-east and y-cyclic boundary condition
4280  subroutine compute_overlaps_fold_east( domain, position, ishift, jshift )
4281  type(domain2d), intent(inout) :: domain
4282  integer, intent(in) :: position, ishift, jshift
4283 
4284  integer :: j, m, n, nlist, tMe, tNbr, dir
4285  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd
4286  integer :: jed, isg, ieg, jsg, jeg, ioff, joff
4287  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
4288  integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
4289  logical :: folded
4290  type(overlap_type) :: overlap
4291  type(overlapspec), pointer :: update=>null()
4292  type(overlap_type) :: overlapList(MAXLIST)
4293  type(overlap_type) :: checkList(MAXLIST)
4294  type(overlapspec), pointer :: check =>null()
4295  integer :: nsend, nrecv
4296  integer :: nsend_check, nrecv_check
4297 
4298  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
4299  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
4300  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
4301  if(size(domain%x(:)) > 1) return
4302 
4303  !--- if there is no halo, no need to compute overlaps.
4304  if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
4305 
4306  !--- when there is only one tile, n will equal to np
4307  nlist = size(domain%list(:))
4308 
4309  select case(position)
4310  case (center)
4311  update => domain%update_T
4312  case (corner)
4313  update => domain%update_C
4314  check => domain%check_C
4315  case (east)
4316  update => domain%update_E
4317  check => domain%check_E
4318  case (north)
4319  update => domain%update_N
4320  check => domain%check_N
4321  case default
4322  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east):"// &
4323  & " the value of position should be CENTER, EAST, CORNER or NORTH")
4324  end select
4325 
4326  !--- overlap is used to store the overlapping temporarily.
4327  call allocate_update_overlap( overlap, maxoverlap)
4328 
4329  !send
4330  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
4331  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
4332  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
4333  update%xbegin = ism; update%xend = iem
4334  update%ybegin = jsm; update%yend = jem
4335  if(ASSOCIATED(check)) then
4336  check%xbegin = ism; check%xend = iem
4337  check%ybegin = jsm; check%yend = jem
4338  endif
4339  update%whalo = domain%whalo; update%ehalo = domain%ehalo
4340  update%shalo = domain%shalo; update%nhalo = domain%nhalo
4341  whalo = domain%whalo; ehalo = domain%ehalo
4342  shalo = domain%shalo; nhalo = domain%nhalo
4343 
4344  ioff = ni - ishift
4345  joff = nj - jshift
4346  middle = (jsg+jeg)/2+1
4347  tme = 1; tnbr = 1
4348 
4349  if(.NOT. btest(domain%fold,east)) then
4350  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4351  "boundary condition in y-direction should be folded-east for "//trim(domain%name))
4352  endif
4353  if(.NOT. domain%y(tme)%cyclic) then
4354  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4355  "boundary condition in y-direction should be cyclic for "//trim(domain%name))
4356  endif
4357  if(.not. domain%symmetry) then
4358  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4359  "when east boundary is folded, the domain must be symmetry for "//trim(domain%name))
4360  endif
4361 
4362  nsend = 0
4363  nsend_check = 0
4364  do list = 0,nlist-1
4365  m = mod( domain%pos+list, nlist )
4366  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4367  !to_pe's eastern halo
4368  dir = 1
4369  folded = .false.
4370  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4371  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4372  if( ie.GT.ieg )then
4373  folded = .true.
4374  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4375  end if
4376  !--- when domain symmetry and position is EAST or CORNER, the point when jsc == je,
4377  !--- no need to send, because the data on that point will come from other pe.
4378  !--- come from two pe ( there will be only one point on one pe. ).
4379  if( (position == east .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
4380  !--- do nothing, this point will come from other pe
4381  else
4382  call insert_update_overlap( overlap, domain%list(m)%pe, &
4383  is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
4384  endif
4385  !--- when east edge is folded, js .LT. jsg
4386  if(js .LT. jsg) then
4387  js = js + ioff
4388  call insert_update_overlap( overlap, domain%list(m)%pe, &
4389  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4390  endif
4391 
4392  !to_pe's SE halo
4393  dir = 2
4394  folded = .false.
4395  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4396  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4397  if( jsg.GT.js .AND. je.LT.jsc )then !try cyclic offset
4398  js = js+joff; je = je+joff
4399  end if
4400 
4401  if( ie.GT.ieg )then
4402  folded = .true.
4403  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4404  end if
4405 
4406  call insert_update_overlap( overlap, domain%list(m)%pe, &
4407  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4408  !--- when east edge is folded,
4409  if(js .LT. jsg) then
4410  js = js + joff
4411  call insert_update_overlap( overlap, domain%list(m)%pe, &
4412  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4413  endif
4414 
4415  !to_pe's southern halo
4416  dir = 3
4417  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
4418  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4419  !--- to make sure the consistence between pes
4420  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
4421  !--- do nothing, this point will come from other pe
4422  else
4423  if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
4424  js = js+joff; je = je+joff
4425  endif
4426  !--- when the east face is folded, the south halo points at
4427  !--- the position should be on CORNER or EAST
4428  if( ie == ieg .AND. (position == corner .OR. position == east) &
4429  .AND. ( domain%list(m)%y(tnbr)%compute%begin == jsg .OR. &
4430  domain%list(m)%y(tnbr)%compute%begin-1 .GE. middle ) ) then
4431  call insert_update_overlap( overlap, domain%list(m)%pe, &
4432  is, ie-1, js, je, isc, iec, jsc, jec, dir)
4433  !--- consider at i = ieg for east edge.
4434  !--- when the data is at corner and not symmetry, j = jsg -1 will get from cyclic condition
4435  if(position == corner .AND. .NOT. domain%symmetry .AND. domain%list(m)%y(tnbr)%compute%begin==jsg)then
4436  call insert_update_overlap(overlap, domain%list(m)%pe, &
4437  ie, ie, je, je, isc, iec, jsc, jec, dir, .true.)
4438  end if
4439 
4440  ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4441  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4442  if ( domain%list(m)%y(tnbr)%compute%begin == jsg ) then
4443  select case (position)
4444  case(east)
4445  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4446  case(corner)
4447  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4448  end select
4449  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4450  'mpp_domains_define.inc(compute_overlaps_fold_east: south edge ubound error send.' )
4451  else
4452  select case (position)
4453  case(east)
4454  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4455  case(corner)
4456  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4457  end select
4458  end if
4459  call insert_update_overlap( overlap, domain%list(m)%pe, &
4460  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4461  else
4462  call insert_update_overlap( overlap, domain%list(m)%pe, &
4463  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4464  end if
4465  endif
4466 
4467  !to_pe's SW halo
4468  dir = 4
4469  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4470  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4471  if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
4472  js = js+joff; je = je+joff
4473  end if
4474  call insert_update_overlap( overlap, domain%list(m)%pe, &
4475  is, ie, js, je, isc, iec, jsc, jec, dir)
4476 
4477  !to_pe's western halo
4478  dir = 5
4479  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4480  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4481  call insert_update_overlap( overlap, domain%list(m)%pe, &
4482  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4483 
4484  !to_pe's NW halo
4485  dir = 6
4486  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4487  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4488  if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
4489  js = js-joff; je = je-joff
4490  end if
4491  call insert_update_overlap( overlap, domain%list(m)%pe, &
4492  is, ie, js, je, isc, iec, jsc, jec, dir)
4493 
4494  !to_pe's northern halo
4495  dir = 7
4496  folded = .false.
4497  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
4498  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4499  !--- to make sure the consistence between pes
4500  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
4501  !--- do nothing, this point will come from other pe
4502  else
4503  if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
4504  js = js-joff; je = je-joff
4505  endif
4506  !--- when the east face is folded, the north halo points at
4507  !--- the position should be on CORNER or EAST
4508  if( ie == ieg .AND. (position == corner .OR. position == east) &
4509  .AND. ( js .GE. middle .AND. domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
4510  call insert_update_overlap( overlap, domain%list(m)%pe, &
4511  is, ie-1, js, je, isc, iec, jsc, jec, dir)
4512  ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4513  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4514  select case (position)
4515  case(east)
4516  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4517  case(corner)
4518  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4519  end select
4520  call insert_update_overlap( overlap, domain%list(m)%pe, &
4521  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4522  else
4523  call insert_update_overlap( overlap, domain%list(m)%pe, &
4524  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4525  end if
4526  endif
4527 
4528  !to_pe's NE halo
4529  dir = 8
4530  folded = .false.
4531  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4532  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4533  if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
4534  js = js-joff; je = je-joff
4535  end if
4536  if( ie.GT.ieg )then
4537  folded = .true.
4538  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4539  end if
4540 
4541  call insert_update_overlap( overlap, domain%list(m)%pe, &
4542  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4543 
4544  !--- Now calculate the overlapping for fold-edge.
4545  !--- only position at EAST and CORNER need to be considered
4546  if( ( position == east .OR. position == corner) ) then
4547  !fold is within domain
4548  if( domain%x(tme)%domain_data%begin .LE. ieg .AND. ieg .LE. domain%x(tme)%domain_data%end+ishift )then
4549  dir = 1
4550  !--- calculate the overlapping for sending
4551  if( domain%y(tme)%pos .LT. (size(domain%y(tme)%list(:))+1)/2 )then
4552  ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4553  if( ie == ieg )then ! fold is within domain.
4554  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4555  select case (position)
4556  case(east)
4557  js = max(js, middle)
4558  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4559  case(corner)
4560  js = max(js, middle)
4561  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4562  end select
4563  call insert_update_overlap(overlap, domain%list(m)%pe, &
4564  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4565  is = max(is, isc); ie = min(ie, iec)
4566  js = max(js, jsc); je = min(je, jec)
4567  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4568  nsend_check = nsend_check+1
4569  call allocate_check_overlap(checklist(nsend_check), 1)
4570  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
4571  tme, 1, one_hundred_eighty, is, ie, js, je)
4572  end if
4573  end if
4574  end if
4575  end if
4576  end if
4577  end if
4578  !--- copy the overlapping information
4579  if( overlap%count > 0) then
4580  nsend = nsend + 1
4581  if(nsend > maxlist) call mpp_error(fatal, &
4582  "mpp_domains_define.inc(compute_overlaps_east): nsend is greater than MAXLIST, increase MAXLIST")
4583  call add_update_overlap(overlaplist(nsend), overlap)
4584  call init_overlap_type(overlap)
4585  endif
4586  end do ! end of send set up.
4587 
4588  ! copy the overlapping information into domain data structure
4589  if(nsend>0) then
4590  update%nsend = nsend
4591  if (associated(update%send)) deallocate(update%send) !< Check if associated
4592  allocate(update%send(nsend))
4593  do m = 1, nsend
4594  call add_update_overlap( update%send(m), overlaplist(m) )
4595  enddo
4596  endif
4597 
4598  if(nsend_check>0) then
4599  check%nsend = nsend_check
4600  if (associated(check%send)) deallocate(check%send) !< Check if associated
4601  allocate(check%send(nsend_check))
4602  do m = 1, nsend_check
4603  call add_check_overlap( check%send(m), checklist(m) )
4604  enddo
4605  endif
4606 
4607  do m = 1, maxlist
4608  call deallocate_overlap_type(overlaplist(m))
4609  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4610  enddo
4611 
4612  isgd = isg - domain%whalo
4613  iegd = ieg + domain%ehalo
4614  jsgd = jsg - domain%shalo
4615  jegd = jeg + domain%nhalo
4616 
4617  ! begin setting up recv
4618  nrecv = 0
4619  nrecv_check = 0
4620  do list = 0,nlist-1
4621  m = mod( domain%pos+nlist-list, nlist )
4622  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4623  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4624  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4625  !recv_e
4626  dir = 1
4627  folded = .false.
4628  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4629  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4630  is=isc; ie=iec; js=jsc; je=jec
4631  if( ied.GT.ieg )then
4632  folded = .true.
4633  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4634  end if
4635  if( (position == east .OR. position == corner ) .AND. (jsd == je .or. jed == js ) ) then
4636  !--- do nothing, this point will come from other pe
4637  else
4638  call insert_update_overlap(overlap, domain%list(m)%pe, &
4639  is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4640  end if
4641  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4642  if(js .LT. jsg ) then
4643  js = js + joff
4644  call insert_update_overlap(overlap, domain%list(m)%pe, &
4645  is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4646  endif
4647 
4648  !recv_se
4649  dir = 2
4650  folded = .false.
4651  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4652  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4653  is=isc; ie=iec; js=jsc; je=jec
4654  if( ied.GT.ieg )then
4655  folded = .true.
4656  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4657  end if
4658  if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4659  js = js-joff; je = je-joff
4660  end if
4661  call insert_update_overlap(overlap, domain%list(m)%pe, &
4662  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4663  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4664  if(js .LT. jsg ) then
4665  js = js + joff
4666  call insert_update_overlap(overlap, domain%list(m)%pe, &
4667  is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4668  endif
4669 
4670  !recv_s
4671  dir = 3
4672  folded = .false.
4673  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4674  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4675  is=isc; ie=iec; js=jsc; je=jec
4676 
4677  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4678  !--- do nothing, this point will come from other pe
4679  else
4680  if( jsd.LT.jsg .AND. js .GT. jed)then
4681  js = js-joff; je = je-joff
4682  end if
4683  !--- when the east face is folded, the south halo points at
4684  !--- the position should be on CORNER or EAST
4685  if( ied == ieg .AND. (position == corner .OR. position == east) &
4686  .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4687  call insert_update_overlap( overlap, domain%list(m)%pe, &
4688  is, ie, js, je, isd, ied-1, jsd, jed, dir)
4689  is=isc; ie=iec; js=jsc; je=jec
4690  if(jsd<jsg) then
4691  select case (position)
4692  case(east)
4693  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4694  case(corner)
4695  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4696  end select
4697  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4698  'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4699  else
4700  select case (position)
4701  case(east)
4702  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4703  case(corner)
4704  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4705  end select
4706  end if
4707  call insert_update_overlap( overlap, domain%list(m)%pe, &
4708  is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4709  else
4710  call insert_update_overlap( overlap, domain%list(m)%pe, &
4711  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4712  end if
4713  endif
4714 
4715  !recv_sw
4716  dir = 4
4717  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4718  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4719  is=isc; ie=iec; js=jsc; je=jec
4720  if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4721  js = js-joff; je = je-joff
4722  end if
4723  call insert_update_overlap(overlap, domain%list(m)%pe, &
4724  is, ie, js, je, isd, ied, jsd, jed, dir)
4725 
4726  !recv_w
4727  dir = 5
4728  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4729  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4730  is=isc; ie=iec; js=jsc; je=jec
4731  call insert_update_overlap( overlap, domain%list(m)%pe, &
4732  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4733 
4734  !recv_nw
4735  dir = 6
4736  folded = .false.
4737  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4738  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4739  is=isc; ie=iec; js=jsc; je=jec
4740  if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4741  js = js+joff; je = je+joff
4742  end if
4743  call insert_update_overlap( overlap, domain%list(m)%pe, &
4744  is, ie, js, je, isd, ied, jsd, jed, dir)
4745 
4746  !recv_n
4747  dir = 7
4748  folded = .false.
4749  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4750  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4751  is=isc; ie=iec; js=jsc; je=jec
4752  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4753  !--- do nothing, this point will come from other pe
4754  else
4755  if( jed.GT.jeg .AND. je.LT.jsd)then
4756  js = js+joff; je = je+joff
4757  end if
4758  !--- when the east face is folded, the south halo points at
4759  !--- the position should be on CORNER or EAST
4760  if( ied == ieg .AND. (position == corner .OR. position == east) &
4761  .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4762  call insert_update_overlap( overlap, domain%list(m)%pe, &
4763  is, ie, js, je, isd, ied-1, jsd, jed, dir)
4764  is=isc; ie=iec; js=jsc; je=jec
4765  select case (position)
4766  case(east)
4767  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4768  case(corner)
4769  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4770  end select
4771  call insert_update_overlap( overlap, domain%list(m)%pe, &
4772  is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4773  else
4774  call insert_update_overlap( overlap, domain%list(m)%pe, &
4775  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4776  end if
4777  endif
4778 
4779  !recv_ne
4780  dir = 8
4781  folded = .false.
4782  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4783  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4784  is=isc; ie=iec; js=jsc; je=jec
4785  if( ied.GT.ieg) then
4786  folded = .true.
4787  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4788  end if
4789  if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4790  js = js+joff; je = je+joff
4791  endif
4792 
4793  call insert_update_overlap( overlap, domain%list(m)%pe, &
4794  is, ie, js, je, isd, ied, jsd, jed, dir)
4795  !--- Now calculate the overlapping for fold-edge.
4796  !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4797  !--- only position at EAST and CORNER need to be considered
4798  if( ( position == east .OR. position == corner) ) then
4799  !fold is within domain
4800  if( domain%x(tme)%domain_data%begin .LE. ieg .AND. ieg .LE. domain%x(tme)%domain_data%end+ishift )then
4801  dir = 1
4802  !--- calculating overlapping for receving on north
4803  if( domain%y(tme)%pos .GE. size(domain%y(tme)%list(:))/2 )then
4804  ied = domain%x(tme)%compute%end+ishift; isd = ied
4805  if( ied == ieg )then ! fold is within domain.
4806  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4807  is=isc; ie=iec; js = jsc; je = jec
4808  select case (position)
4809  case(east)
4810  jsd = max(jsd, middle)
4811  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4812  case(corner)
4813  jsd = max(jsd, middle)
4814  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4815  end select
4816  call insert_update_overlap(overlap, domain%list(m)%pe, &
4817  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
4818  is = max(is, isd); ie = min(ie, ied)
4819  js = max(js, jsd); je = min(je, jed)
4820  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4821  nrecv_check = nrecv_check+1
4822  call allocate_check_overlap(checklist(nrecv_check), 1)
4823  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
4824  tme, 3, one_hundred_eighty, is, ie, js, je)
4825  endif
4826  endif
4827  endif
4828  endif
4829  endif
4830  endif
4831  !--- copy the overlapping information
4832  if( overlap%count > 0) then
4833  nrecv = nrecv + 1
4834  if(nrecv > maxlist) call mpp_error(fatal, &
4835  "mpp_domains_define.inc(compute_overlaps_east): nrecv is greater than MAXLIST, increase MAXLIST")
4836  call add_update_overlap( overlaplist(nrecv), overlap)
4837  call init_overlap_type(overlap)
4838  endif
4839  enddo ! end of recv do loop
4840 
4841  ! copy the overlapping information into domain
4842  if(nrecv>0) then
4843  update%nrecv = nrecv
4844  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
4845  allocate(update%recv(nrecv))
4846  do m = 1, nrecv
4847  call add_update_overlap( update%recv(m), overlaplist(m) )
4848  do n = 1, update%recv(m)%count
4849  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
4850  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
4851  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
4852  endif
4853  enddo
4854  enddo
4855  endif
4856 
4857  if(nrecv_check>0) then
4858  check%nrecv = nrecv_check
4859  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
4860  allocate(check%recv(nrecv_check))
4861  do m = 1, nrecv_check
4862  call add_check_overlap( check%recv(m), checklist(m) )
4863  enddo
4864  endif
4865 
4866  call deallocate_overlap_type(overlap)
4867  do m = 1, maxlist
4868  call deallocate_overlap_type(overlaplist(m))
4869  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4870  enddo
4871 
4872  update=>null()
4873  check=>null()
4874 
4875  domain%initialized = .true.
4876 
4877  end subroutine compute_overlaps_fold_east
4878 
4879  !#####################################################################################
4880  subroutine get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4881  integer, intent(in) :: jsg, jeg, isg, jshift, position
4882  integer, intent(inout) :: is, ie, js, je
4883  integer :: i, j
4884 
4885  select case(position)
4886  case(center)
4887  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4888  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4889  case(east)
4890  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4891  i=is; is = 2*isg-ie; ie = 2*isg-i
4892  case(north)
4893  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4894  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4895  case(corner)
4896  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4897  i=is; is = 2*isg-ie; ie = 2*isg-i
4898  end select
4899 
4900  end subroutine get_fold_index_west
4901 
4902  !#####################################################################################
4903  subroutine get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4904  integer, intent(in) :: jsg, jeg, ieg, jshift, position
4905  integer, intent(inout) :: is, ie, js, je
4906  integer :: i, j
4907 
4908  select case(position)
4909  case(center)
4910  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4911  i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4912  case(east)
4913  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4914  i=is; is = 2*ieg-ie; ie = 2*ieg-i
4915  case(north)
4916  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4917  i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4918  case(corner)
4919  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4920  i=is; is = 2*ieg-ie; ie = 2*ieg-i
4921  end select
4922 
4923  end subroutine get_fold_index_east
4924 
4925  !#####################################################################################
4926  subroutine get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
4927  integer, intent(in) :: isg, ieg, jsg, ishift, position
4928  integer, intent(inout) :: is, ie, js, je
4929  integer :: i, j
4930 
4931  select case(position)
4932  case(center)
4933  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4934  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4935  case(east)
4936  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4937  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4938  case(north)
4939  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4940  j=js; js = 2*jsg-je; je = 2*jsg-j
4941  case(corner)
4942  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4943  j=js; js = 2*jsg-je; je = 2*jsg-j
4944  end select
4945 
4946  end subroutine get_fold_index_south
4947  !#####################################################################################
4948  subroutine get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
4949  integer, intent(in) :: isg, ieg, jeg, ishift, position
4950  integer, intent(inout) :: is, ie, js, je
4951  integer :: i, j
4952 
4953  select case(position)
4954  case(center)
4955  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4956  j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4957  case(east)
4958  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4959  j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4960  case(north)
4961  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4962  j=js; js = 2*jeg-je; je = 2*jeg-j
4963  case(corner)
4964  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4965  j=js; js = 2*jeg-je; je = 2*jeg-j
4966  end select
4967 
4968  end subroutine get_fold_index_north
4969 
4970 
4971  !#####################################################################################
4972  !> add offset to the index
4973  subroutine apply_cyclic_offset(lstart, lend, offset, gstart, gend, gsize)
4974  integer, intent(inout) :: lstart, lend
4975  integer, intent(in ) :: offset, gstart, gend, gsize
4976 
4977  lstart = lstart + offset
4978  if(lstart > gend) lstart = lstart - gsize
4979  if(lstart < gstart) lstart = lstart + gsize
4980  lend = lend + offset
4981  if(lend > gend) lend = lend - gsize
4982  if(lend < gstart) lend = lend + gsize
4983 
4984  return
4985 
4986  end subroutine apply_cyclic_offset
4987 
4988  !###################################################################################
4989  !> this routine sets up the overlapping for mpp_update_domains for arbitrary halo update.
4990  !! should be the halo size defined in mpp_define_domains.
4991  !! xhalo_out, yhalo_out should not be exactly the same as xhalo_in, yhalo_in
4992  !! currently we didn't consider about tripolar grid situation, because in the folded north
4993  !! region, the overlapping is specified through list of points, not through rectangular.
4994  !! But will return back to solve this problem in the future.
4995  subroutine set_overlaps(domain, overlap_in, overlap_out, whalo_out, ehalo_out, shalo_out, nhalo_out)
4996  type(domain2d), intent(in) :: domain
4997  type(overlapspec), intent(in) :: overlap_in
4998  type(overlapspec), intent(inout) :: overlap_out
4999  integer, intent(in) :: whalo_out, ehalo_out, shalo_out, nhalo_out
5000  integer :: nlist, m, n, isoff, ieoff, jsoff, jeoff, rotation
5001  integer :: whalo_in, ehalo_in, shalo_in, nhalo_in
5002  integer :: dir
5003  type(overlap_type) :: overlap
5004  type(overlap_type), allocatable :: send(:), recv(:)
5005  type(overlap_type), pointer :: ptrIn => null()
5006  integer :: nsend, nrecv, nsend_in, nrecv_in
5007 
5008  if( domain%fold .NE. 0) call mpp_error(fatal, "mpp_domains_define.inc(set_overlaps):"// &
5009  & " folded domain is not implemented for arbitrary halo update, contact developer")
5010 
5011  whalo_in = domain%whalo
5012  ehalo_in = domain%ehalo
5013  shalo_in = domain%shalo
5014  nhalo_in = domain%nhalo
5015 
5016  if( .NOT. domain%initialized) call mpp_error(fatal, &
5017  "mpp_domains_define.inc: domain is not defined yet")
5018 
5019  nlist = size(domain%list(:))
5020  isoff = whalo_in - abs(whalo_out)
5021  ieoff = ehalo_in - abs(ehalo_out)
5022  jsoff = shalo_in - abs(shalo_out)
5023  jeoff = nhalo_in - abs(nhalo_out)
5024 
5025  nsend = 0
5026  nsend_in = overlap_in%nsend
5027  nrecv_in = overlap_in%nrecv
5028  if(nsend_in>0) allocate(send(nsend_in))
5029  if(nrecv_in>0) allocate(recv(nrecv_in))
5030  call allocate_update_overlap(overlap, maxoverlap)
5031 
5032  overlap_out%whalo = whalo_out
5033  overlap_out%ehalo = ehalo_out
5034  overlap_out%shalo = shalo_out
5035  overlap_out%nhalo = nhalo_out
5036  overlap_out%xbegin = overlap_in%xbegin
5037  overlap_out%xend = overlap_in%xend
5038  overlap_out%ybegin = overlap_in%ybegin
5039  overlap_out%yend = overlap_in%yend
5040 
5041  !--- setting up overlap.
5042  do m = 1, nsend_in
5043  ptrin => overlap_in%send(m)
5044  if(ptrin%count .LE. 0) call mpp_error(fatal, "mpp_domains_define.inc(set_overlaps):"// &
5045  " number of overlap for send should be a positive number for"//trim(domain%name) )
5046  do n = 1, ptrin%count
5047  dir = ptrin%dir(n)
5048  rotation = ptrin%rotation(n)
5049  select case(dir)
5050  case(1) ! to_pe's eastern halo
5051  if(ehalo_out > 0) then
5052  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, 0, n, dir, rotation)
5053  else if(ehalo_out<0) then
5054  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, 0, n, dir, rotation)
5055  end if
5056  case(2) ! to_pe's southeast halo
5057  if(ehalo_out>0 .AND. shalo_out > 0) then
5058  call set_single_overlap(ptrin, overlap, 0, -ieoff, jsoff, 0, n, dir, rotation)
5059  else if(ehalo_out<0 .AND. shalo_out < 0) then ! three parts: southeast, south and east.
5060  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, shalo_out, n, dir, rotation)
5061  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1, rotation)
5062  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, shalo_out, n, dir+1, rotation)
5063  end if
5064  case(3) ! to_pe's southern halo
5065  if(shalo_out > 0) then
5066  call set_single_overlap(ptrin, overlap, 0, 0, jsoff, 0, n, dir, rotation)
5067  else if(shalo_out<0) then
5068  call set_single_overlap(ptrin, overlap, 0, 0, 0, shalo_out, n, dir, rotation)
5069  end if
5070  case(4) ! to_pe's southwest halo
5071  if(whalo_out>0 .AND. shalo_out > 0) then
5072  call set_single_overlap(ptrin, overlap, isoff, 0, jsoff, 0, n, dir, rotation)
5073  else if(whalo_out<0 .AND. shalo_out < 0) then
5074  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, shalo_out, n, dir, rotation)
5075  call set_single_overlap(ptrin, overlap, isoff, 0, 0, shalo_out, n, dir-1, rotation)
5076  call set_single_overlap(ptrin, overlap, 0, whalo_out, jsoff, 0, n, dir+1, rotation)
5077  end if
5078  case(5) ! to_pe's western halo
5079  if(whalo_out > 0) then
5080  call set_single_overlap(ptrin, overlap, isoff, 0, 0, 0, n, dir, rotation)
5081  else if(whalo_out<0) then
5082  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, 0, n, dir, rotation)
5083  end if
5084  case(6) ! to_pe's northwest halo
5085  if(whalo_out>0 .AND. nhalo_out > 0) then
5086  call set_single_overlap(ptrin, overlap, isoff, 0, 0, -jeoff, n, dir, rotation)
5087  else if(whalo_out<0 .AND. nhalo_out < 0) then
5088  call set_single_overlap(ptrin, overlap, 0, whalo_out, -nhalo_out, 0, n, dir, rotation)
5089  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, -jeoff, n, dir-1, rotation)
5090  call set_single_overlap(ptrin, overlap, isoff, 0, -nhalo_out, 0, n, dir+1, rotation)
5091  end if
5092  case(7) ! to_pe's northern halo
5093  if(nhalo_out > 0) then
5094  call set_single_overlap(ptrin, overlap, 0, 0, 0, -jeoff, n, dir, rotation)
5095  else if(nhalo_out<0) then
5096  call set_single_overlap(ptrin, overlap, 0, 0, -nhalo_out, 0, n, dir, rotation)
5097  end if
5098  case(8) ! to_pe's northeast halo
5099  if(ehalo_out>0 .AND. nhalo_out > 0) then
5100  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, -jeoff, n, dir, rotation)
5101  else if(ehalo_out<0 .AND. nhalo_out < 0) then
5102  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir, rotation)
5103  call set_single_overlap(ptrin, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1, rotation)
5104  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, -jeoff, n, 1, rotation)
5105  end if
5106  end select
5107  end do ! do n = 1, ptrIn%count
5108  if(overlap%count>0) then
5109  nsend = nsend+1
5110  call add_update_overlap(send(nsend), overlap)
5111  call init_overlap_type(overlap)
5112  endif
5113  end do ! end do list = 0, nlist-1
5114 
5115  if(nsend>0) then
5116  overlap_out%nsend = nsend
5117  if (associated(overlap_out%send)) deallocate(overlap_out%send) !< Check if associated
5118  allocate(overlap_out%send(nsend));
5119  do n = 1, nsend
5120  call add_update_overlap(overlap_out%send(n), send(n) )
5121  enddo
5122  else
5123  overlap_out%nsend = 0
5124  endif
5125 
5126  !--------------------------------------------------
5127  ! recving
5128  !---------------------------------------------------
5129  overlap%count = 0
5130  nrecv = 0
5131  do m = 1, nrecv_in
5132  ptrin => overlap_in%recv(m)
5133  if(ptrin%count .LE. 0) call mpp_error(fatal, &
5134  "mpp_domains_define.inc(set_overlaps): number of overlap for recv should be a positive number")
5135  overlap%count = 0
5136  do n = 1, ptrin%count
5137  dir = ptrin%dir(n)
5138  rotation = ptrin%rotation(n)
5139  select case(dir)
5140  case(1) ! eastern halo
5141  if(ehalo_out > 0) then
5142  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, 0, n, dir)
5143  else if(ehalo_out<0) then
5144  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, 0, n, dir)
5145  end if
5146  case(2) ! southeast halo
5147  if(ehalo_out>0 .AND. shalo_out > 0) then
5148  call set_single_overlap(ptrin, overlap, 0, -ieoff, jsoff, 0, n, dir)
5149  else if(ehalo_out<0 .AND. shalo_out < 0) then
5150  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, shalo_out, n, dir)
5151  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1)
5152  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, shalo_out, n, dir+1)
5153  end if
5154  case(3) ! southern halo
5155  if(shalo_out > 0) then
5156  call set_single_overlap(ptrin, overlap, 0, 0, jsoff, 0, n, dir)
5157  else if(shalo_out<0) then
5158  call set_single_overlap(ptrin, overlap, 0, 0, 0, shalo_out, n, dir)
5159  end if
5160  case(4) ! southwest halo
5161  if(whalo_out>0 .AND. shalo_out > 0) then
5162  call set_single_overlap(ptrin, overlap, isoff, 0, jsoff, 0, n, dir)
5163  else if(whalo_out<0 .AND. shalo_out < 0) then
5164  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, shalo_out, n, dir)
5165  call set_single_overlap(ptrin, overlap, isoff, 0, 0, shalo_out, n, dir-1)
5166  call set_single_overlap(ptrin, overlap, 0, whalo_out, jsoff, 0, n, dir+1)
5167  end if
5168  case(5) ! western halo
5169  if(whalo_out > 0) then
5170  call set_single_overlap(ptrin, overlap, isoff, 0, 0, 0, n, dir)
5171  else if(whalo_out<0) then
5172  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, 0, n, dir)
5173  end if
5174  case(6) ! northwest halo
5175  if(whalo_out>0 .AND. nhalo_out > 0) then
5176  call set_single_overlap(ptrin, overlap, isoff, 0, 0, -jeoff, n, dir)
5177  else if(whalo_out<0 .AND. nhalo_out < 0) then
5178  call set_single_overlap(ptrin, overlap, 0, whalo_out, -nhalo_out, 0, n, dir)
5179  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, -jeoff, n, dir-1)
5180  call set_single_overlap(ptrin, overlap, isoff, 0, -nhalo_out, 0, n, dir+1)
5181  end if
5182  case(7) ! northern halo
5183  if(nhalo_out > 0) then
5184  call set_single_overlap(ptrin, overlap, 0, 0, 0, -jeoff, n, dir)
5185  else if(nhalo_out<0) then
5186  call set_single_overlap(ptrin, overlap, 0, 0, -nhalo_out, 0, n, dir)
5187  end if
5188  case(8) ! northeast halo
5189  if(ehalo_out>0 .AND. nhalo_out > 0) then
5190  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, -jeoff, n, dir)
5191  else if(ehalo_out<0 .AND. nhalo_out < 0) then
5192  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir)
5193  call set_single_overlap(ptrin, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1)
5194  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, -jeoff, n, 1)
5195  end if
5196  end select
5197  end do ! do n = 1, ptrIn%count
5198  if(overlap%count>0) then
5199  nrecv = nrecv+1
5200  call add_update_overlap(recv(nrecv), overlap)
5201  call init_overlap_type(overlap)
5202  endif
5203  end do ! end do list = 0, nlist-1
5204 
5205  if(nrecv>0) then
5206  overlap_out%nrecv = nrecv
5207  if (associated(overlap_out%recv)) deallocate(overlap_out%recv) !< Check if associated
5208  allocate(overlap_out%recv(nrecv));
5209  do n = 1, nrecv
5210  call add_update_overlap(overlap_out%recv(n), recv(n) )
5211  enddo
5212  else
5213  overlap_out%nrecv = 0
5214  endif
5215 
5216  call deallocate_overlap_type(overlap)
5217  do n = 1, nsend_in
5218  call deallocate_overlap_type(send(n))
5219  enddo
5220  do n = 1, nrecv_in
5221  call deallocate_overlap_type(recv(n))
5222  enddo
5223  if(allocated(send)) deallocate(send)
5224  if(allocated(recv)) deallocate(recv)
5225  ptrin => null()
5226 
5227  call set_domain_comm_inf(overlap_out)
5228 
5229 
5230  end subroutine set_overlaps
5231 
5232  !##############################################################################
5233  subroutine set_single_overlap(overlap_in, overlap_out, isoff, ieoff, jsoff, jeoff, index, dir, rotation)
5234  type(overlap_type), intent(in) :: overlap_in
5235  type(overlap_type), intent(inout) :: overlap_out
5236  integer, intent(in) :: isoff, jsoff, ieoff, jeoff
5237  integer, intent(in) :: index
5238  integer, intent(in) :: dir
5239  integer, optional, intent(in) :: rotation
5240  integer :: rotate
5241  integer :: count
5242 
5243  if( overlap_out%pe == null_pe ) then
5244  overlap_out%pe = overlap_in%pe
5245  else
5246  if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(fatal, &
5247  "mpp_domains_define.inc(set_single_overlap): mismatch of pe between overlap_in and overlap_out")
5248  endif
5249 
5250  if(isoff .NE. 0 .and. ieoff .NE. 0) call mpp_error(fatal, &
5251  "mpp_domains_define.inc(set_single_overlap): both isoff and ieoff are non-zero")
5252  if(jsoff .NE. 0 .and. jeoff .NE. 0) call mpp_error(fatal, &
5253  "mpp_domains_define.inc(set_single_overlap): both jsoff and jeoff are non-zero")
5254 
5255 
5256  overlap_out%count = overlap_out%count + 1
5257  count = overlap_out%count
5258  if(count > maxoverlap) call mpp_error(fatal, &
5259  "set_single_overlap: number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
5260  rotate = zero
5261  if(present(rotation)) rotate = rotation
5262  overlap_out%rotation (count) = overlap_in%rotation(index)
5263  overlap_out%dir (count) = dir
5264  overlap_out%tileMe (count) = overlap_in%tileMe(index)
5265  overlap_out%tileNbr (count) = overlap_in%tileNbr(index)
5266 
5267  select case(rotate)
5268  case(zero)
5269  overlap_out%is(count) = overlap_in%is(index) + isoff
5270  overlap_out%ie(count) = overlap_in%ie(index) + ieoff
5271  overlap_out%js(count) = overlap_in%js(index) + jsoff
5272  overlap_out%je(count) = overlap_in%je(index) + jeoff
5273  case(ninety)
5274  overlap_out%is(count) = overlap_in%is(index) - jeoff
5275  overlap_out%ie(count) = overlap_in%ie(index) - jsoff
5276  overlap_out%js(count) = overlap_in%js(index) + isoff
5277  overlap_out%je(count) = overlap_in%je(index) + ieoff
5278  case(minus_ninety)
5279  overlap_out%is(count) = overlap_in%is(index) + jsoff
5280  overlap_out%ie(count) = overlap_in%ie(index) + jeoff
5281  overlap_out%js(count) = overlap_in%js(index) - ieoff
5282  overlap_out%je(count) = overlap_in%je(index) - isoff
5283  case default
5284  call mpp_error(fatal, "mpp_domains_define.inc: the value of rotation should be ZERO, NINETY or MINUS_NINETY")
5285  end select
5286 
5287  end subroutine set_single_overlap
5288 
5289  !###################################################################################
5290  !> compute the overlapping between tiles for the T-cell.
5291  subroutine define_contact_point( domain, position, num_contact, tile1, tile2, align1, align2, &
5292  refine1, refine2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, &
5293  isgList, iegList, jsgList, jegList )
5294  type(domain2d), intent(inout) :: domain
5295  integer, intent(in) :: position
5296  integer, intent(in) :: num_contact !< number of contact regions
5297  integer, dimension(:), intent(in) :: tile1, tile2 !< tile number
5298  integer, dimension(:), intent(in) :: align1, align2 !< align direction of contact region
5299  real, dimension(:), intent(in) :: refine1, refine2 !< refinement between tiles
5300  integer, dimension(:), intent(in) :: istart1, iend1 !< i-index in tile_1 of contact region
5301  integer, dimension(:), intent(in) :: jstart1, jend1 !< j-index in tile_1 of contact region
5302  integer, dimension(:), intent(in) :: istart2, iend2 !< i-index in tile_2 of contact region
5303  integer, dimension(:), intent(in) :: jstart2, jend2 !< j-index in tile_2 of contact region
5304  integer, dimension(:), intent(in) :: isgList, iegList !< i-global domain of each tile
5305  integer, dimension(:), intent(in) :: jsgList, jegList !< j-global domain of each tile
5306 
5307  integer :: isc, iec, jsc, jec, isd, ied, jsd, jed
5308  integer :: isc1, iec1, jsc1, jec1, isc2, iec2, jsc2, jec2
5309  integer :: isd1, ied1, jsd1, jed1, isd2, ied2, jsd2, jed2
5310  integer :: is, ie, js, je, ioff, joff
5311  integer :: ntiles, max_contact
5312  integer :: nlist, list, m, n, l, count, numS, numR
5313  integer :: whalo, ehalo, shalo, nhalo
5314  integer :: t1, t2, tt, pos
5315  integer :: ntileMe, ntileNbr, tMe, tNbr, tileMe, dir
5316  integer :: nxd, nyd, nxc, nyc, ism, iem, jsm, jem
5317  integer :: dirlist(8)
5318  !--- is2Send and is1Send will figure out the overlapping for sending from current pe.
5319  !--- is1Recv and iscREcv will figure out the overlapping for recving onto current pe.
5320  integer, dimension(4*num_contact) :: is1Send, ie1Send, js1Send, je1Send
5321  integer, dimension(4*num_contact) :: is2Send, ie2Send, js2Send, je2Send
5322  integer, dimension(4*num_contact) :: is2Recv, ie2Recv, js2Recv, je2Recv
5323  integer, dimension(4*num_contact) :: is1Recv, ie1Recv, js1Recv, je1Recv
5324  integer, dimension(4*num_contact) :: align1Recv, align2Recv, align1Send, align2Send
5325  real, dimension(4*num_contact) :: refineRecv, refineSend
5326  integer, dimension(4*num_contact) :: rotateSend, rotateRecv, tileSend, tileRecv
5327  integer :: nsend, nrecv, nsend2, nrecv2
5328  type(contact_type), dimension(domain%ntiles) :: eCont, wCont, sCont, nCont
5329  type(overlap_type), dimension(0:size(domain%list(:))-1) :: overlapSend, overlapRecv
5330  integer :: iunit
5331 
5332  if( position .NE. center ) call mpp_error(fatal, "mpp_domains_define.inc: " //&
5333  "routine define_contact_point can only be used to calculate overlapping for cell center.")
5334 
5335  ntiles = domain%ntiles
5336 
5337  econt(:)%ncontact = 0
5338 
5339  do n = 1, ntiles
5340  econt(n)%ncontact = 0; scont(n)%ncontact = 0; wcont(n)%ncontact = 0; ncont(n)%ncontact = 0;
5341  allocate(econt(n)%tile(num_contact), wcont(n)%tile(num_contact) )
5342  allocate(ncont(n)%tile(num_contact), scont(n)%tile(num_contact) )
5343  allocate(econt(n)%align1(num_contact), econt(n)%align2(num_contact) )
5344  allocate(wcont(n)%align1(num_contact), wcont(n)%align2(num_contact) )
5345  allocate(scont(n)%align1(num_contact), scont(n)%align2(num_contact) )
5346  allocate(ncont(n)%align1(num_contact), ncont(n)%align2(num_contact) )
5347  allocate(econt(n)%refine1(num_contact), econt(n)%refine2(num_contact) )
5348  allocate(wcont(n)%refine1(num_contact), wcont(n)%refine2(num_contact) )
5349  allocate(scont(n)%refine1(num_contact), scont(n)%refine2(num_contact) )
5350  allocate(ncont(n)%refine1(num_contact), ncont(n)%refine2(num_contact) )
5351  allocate(econt(n)%is1(num_contact), econt(n)%ie1(num_contact), econt(n)%js1(num_contact), &
5352  & econt(n)%je1(num_contact))
5353  allocate(econt(n)%is2(num_contact), econt(n)%ie2(num_contact), econt(n)%js2(num_contact), &
5354  & econt(n)%je2(num_contact))
5355  allocate(wcont(n)%is1(num_contact), wcont(n)%ie1(num_contact), wcont(n)%js1(num_contact), &
5356  & wcont(n)%je1(num_contact))
5357  allocate(wcont(n)%is2(num_contact), wcont(n)%ie2(num_contact), wcont(n)%js2(num_contact), &
5358  & wcont(n)%je2(num_contact))
5359  allocate(scont(n)%is1(num_contact), scont(n)%ie1(num_contact), scont(n)%js1(num_contact), &
5360  & scont(n)%je1(num_contact))
5361  allocate(scont(n)%is2(num_contact), scont(n)%ie2(num_contact), scont(n)%js2(num_contact), &
5362  & scont(n)%je2(num_contact))
5363  allocate(ncont(n)%is1(num_contact), ncont(n)%ie1(num_contact), ncont(n)%js1(num_contact), &
5364  & ncont(n)%je1(num_contact))
5365  allocate(ncont(n)%is2(num_contact), ncont(n)%ie2(num_contact), ncont(n)%js2(num_contact), &
5366  & ncont(n)%je2(num_contact))
5367  end do
5368 
5369  !--- set up the east, south, west and north contact for each tile.
5370  do n = 1, num_contact
5371  t1 = tile1(n)
5372  t2 = tile2(n)
5373  select case(align1(n))
5374  case (east)
5375  call fill_contact( econt(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5376  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5377  case (west)
5378  call fill_contact( wcont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5379  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5380  case (south)
5381  call fill_contact( scont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5382  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5383  case (north)
5384  call fill_contact( ncont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5385  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5386  end select
5387  select case(align2(n))
5388  case (east)
5389  call fill_contact( econt(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5390  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5391  case (west)
5392  call fill_contact( wcont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5393  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5394  case (south)
5395  call fill_contact( scont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5396  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5397  case (north)
5398  call fill_contact( ncont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5399  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5400  end select
5401  end do
5402 
5403  !--- the tile number of current pe, halo size
5404  whalo = domain%whalo
5405  ehalo = domain%ehalo
5406  shalo = domain%shalo
5407  nhalo = domain%nhalo
5408 
5409  !--- find if there is an extra point in x and y direction depending on position
5410  nlist = size(domain%list(:))
5411 
5412  max_contact = 4*num_contact ! should be enough
5413 
5414  ntileme = size(domain%x(:))
5415  refinesend = 1; refinerecv = 1
5416 
5417  !--------------------------------------------------------------------------------------------------
5418  ! loop over each tile on current domain to set up the overlapping for each tile
5419  !--------------------------------------------------------------------------------------------------
5420  !--- first check the overlap within the tiles.
5421  do n = 1, domain%update_T%nsend
5422  pos = domain%update_T%send(n)%pe - mpp_root_pe()
5423  call add_update_overlap(overlapsend(pos), domain%update_T%send(n) )
5424  enddo
5425  do n = 1, domain%update_T%nrecv
5426  pos = domain%update_T%recv(n)%pe - mpp_root_pe()
5427  call add_update_overlap(overlaprecv(pos), domain%update_T%recv(n) )
5428  enddo
5429 
5430  call mpp_get_memory_domain(domain, ism, iem, jsm, jem)
5431  domain%update_T%xbegin = ism; domain%update_T%xend = iem
5432  domain%update_T%ybegin = jsm; domain%update_T%yend = jem
5433  domain%update_T%whalo = whalo; domain%update_T%ehalo = ehalo
5434  domain%update_T%shalo = shalo; domain%update_T%nhalo = nhalo
5435 
5436  do tme = 1, ntileme
5437  tileme = domain%tile_id(tme)
5438  rotatesend = zero; rotaterecv = zero
5439 
5440  !--- loop over all the contact region to figure out the index for overlapping region.
5441  count = 0
5442  do n = 1, econt(tileme)%ncontact ! east contact
5443  count = count+1
5444  tilerecv(count) = econt(tileme)%tile(n); tilesend(count) = econt(tileme)%tile(n)
5445  align1recv(count) = econt(tileme)%align1(n); align2recv(count) = econt(tileme)%align2(n)
5446  align1send(count) = econt(tileme)%align1(n); align2send(count) = econt(tileme)%align2(n)
5447  refinesend(count) = econt(tileme)%refine2(n); refinerecv(count) = econt(tileme)%refine1(n)
5448  is1recv(count) = econt(tileme)%is1(n) + 1; ie1recv(count) = is1recv(count) + ehalo - 1
5449  js1recv(count) = econt(tileme)%js1(n); je1recv(count) = econt(tileme)%je1(n)
5450  select case(econt(tileme)%align2(n))
5451  case ( west ) ! w <-> e
5452  is2recv(count) = econt(tileme)%is2(n); ie2recv(count) = is2recv(count) + ehalo - 1
5453  js2recv(count) = econt(tileme)%js2(n); je2recv(count) = econt(tileme)%je2(n)
5454  ie1send(count) = econt(tileme)%is1(n); is1send(count) = ie1send(count) - whalo + 1
5455  js1send(count) = econt(tileme)%js1(n); je1send(count) = econt(tileme)%je1(n)
5456  ie2send(count) = econt(tileme)%is2(n) - 1; is2send(count) = ie2send(count) - whalo + 1
5457  js2send(count) = econt(tileme)%js2(n); je2send(count) = econt(tileme)%je2(n)
5458  case ( south ) ! s <-> e
5459  rotaterecv(count) = ninety; rotatesend(count) = minus_ninety
5460  js2recv(count) = econt(tileme)%js2(n); je2recv(count) = js2recv(count) + ehalo -1
5461  is2recv(count) = econt(tileme)%is2(n); ie2recv(count) = econt(tileme)%ie2(n)
5462  ie1send(count) = econt(tileme)%is1(n); is1send(count) = ie1send(count) - shalo + 1
5463  js1send(count) = econt(tileme)%js1(n); je1send(count) = econt(tileme)%je1(n)
5464  is2send(count) = econt(tileme)%is2(n); ie2send(count) = econt(tileme)%ie2(n)
5465  je2send(count) = econt(tileme)%js2(n) - 1; js2send(count) = je2send(count) - shalo + 1
5466  end select
5467  end do
5468 
5469  do n = 1, scont(tileme)%ncontact ! south contact
5470  count = count+1
5471  tilerecv(count) = scont(tileme)%tile(n); tilesend(count) = scont(tileme)%tile(n)
5472  align1recv(count) = scont(tileme)%align1(n); align2recv(count) = scont(tileme)%align2(n);
5473  align1send(count) = scont(tileme)%align1(n); align2send(count) = scont(tileme)%align2(n);
5474  refinesend(count) = scont(tileme)%refine2(n); refinerecv(count) = scont(tileme)%refine1(n)
5475  is1recv(count) = scont(tileme)%is1(n); ie1recv(count) = scont(tileme)%ie1(n)
5476  je1recv(count) = scont(tileme)%js1(n) - 1; js1recv(count) = je1recv(count) - shalo + 1
5477  select case(scont(tileme)%align2(n))
5478  case ( north ) ! n <-> s
5479  is2recv(count) = scont(tileme)%is2(n); ie2recv(count) = scont(tileme)%ie2(n)
5480  je2recv(count) = scont(tileme)%je2(n); js2recv(count) = je2recv(count) - shalo + 1
5481  is1send(count) = scont(tileme)%is1(n); ie1send(count) = scont(tileme)%ie1(n)
5482  js1send(count) = scont(tileme)%js1(n); je1send(count) = js1send(count) + nhalo -1
5483  is2send(count) = scont(tileme)%is2(n); ie2send(count) = scont(tileme)%ie2(n)
5484  js2send(count) = scont(tileme)%je2(n)+1; je2send(count) = js2send(count) + nhalo - 1
5485  case ( east ) ! e <-> s
5486  rotaterecv(count) = minus_ninety; rotatesend(count) = ninety
5487  ie2recv(count) = scont(tileme)%ie2(n); is2recv(count) = ie2recv(count) - shalo + 1
5488  js2recv(count) = scont(tileme)%js2(n); je2recv(count) = scont(tileme)%je2(n)
5489  is1send(count) = scont(tileme)%is1(n); ie1send(count) = scont(tileme)%ie1(n)
5490  js1send(count) = scont(tileme)%js1(n); je1send(count) = js1send(count) + ehalo - 1
5491  is2send(count) = scont(tileme)%ie2(n)+1; ie2send(count) = is2send(count) + ehalo - 1
5492  js2send(count) = scont(tileme)%js2(n); je2send(count) = scont(tileme)%je2(n)
5493  end select
5494  end do
5495 
5496  do n = 1, wcont(tileme)%ncontact ! west contact
5497  count = count+1
5498  tilerecv(count) = wcont(tileme)%tile(n); tilesend(count) = wcont(tileme)%tile(n)
5499  align1recv(count) = wcont(tileme)%align1(n); align2recv(count) = wcont(tileme)%align2(n);
5500  align1send(count) = wcont(tileme)%align1(n); align2send(count) = wcont(tileme)%align2(n);
5501  refinesend(count) = wcont(tileme)%refine2(n); refinerecv(count) = wcont(tileme)%refine1(n)
5502  ie1recv(count) = wcont(tileme)%is1(n) - 1; is1recv(count) = ie1recv(count) - whalo + 1
5503  js1recv(count) = wcont(tileme)%js1(n); je1recv(count) = wcont(tileme)%je1(n)
5504  select case(wcont(tileme)%align2(n))
5505  case ( east ) ! e <-> w
5506  ie2recv(count) = wcont(tileme)%ie2(n); is2recv(count) = ie2recv(count) - whalo + 1
5507  js2recv(count) = wcont(tileme)%js2(n); je2recv(count) = wcont(tileme)%je2(n)
5508  is1send(count) = wcont(tileme)%is1(n); ie1send(count) = is1send(count) + ehalo - 1
5509  js1send(count) = wcont(tileme)%js1(n); je1send(count) = wcont(tileme)%je1(n)
5510  is2send(count) = wcont(tileme)%ie2(n)+1; ie2send(count) = is2send(count) + ehalo - 1
5511  js2send(count) = wcont(tileme)%js2(n); je2send(count) = wcont(tileme)%je2(n)
5512  case ( north ) ! n <-> w
5513  rotaterecv(count) = ninety; rotatesend(count) = minus_ninety
5514  je2recv(count) = wcont(tileme)%je2(n); js2recv(count) = je2recv(count) - whalo + 1
5515  is2recv(count) = wcont(tileme)%is2(n); ie2recv(count) = wcont(tileme)%ie2(n)
5516  is1send(count) = wcont(tileme)%is1(n); ie1send(count) = is1send(count) + nhalo - 1
5517  js1send(count) = wcont(tileme)%js1(n); je1send(count) = wcont(tileme)%je1(n)
5518  js2send(count) = wcont(tileme)%je2(n)+1; je2send(count) = js2send(count) + nhalo - 1
5519  is2send(count) = wcont(tileme)%is2(n); ie2send(count) = wcont(tileme)%ie2(n)
5520  end select
5521  end do
5522 
5523  do n = 1, ncont(tileme)%ncontact ! north contact
5524  count = count+1
5525  tilerecv(count) = ncont(tileme)%tile(n); tilesend(count) = ncont(tileme)%tile(n)
5526  align1recv(count) = ncont(tileme)%align1(n); align2recv(count) = ncont(tileme)%align2(n);
5527  align1send(count) = ncont(tileme)%align1(n); align2send(count) = ncont(tileme)%align2(n);
5528  refinesend(count) = ncont(tileme)%refine2(n); refinerecv(count) = ncont(tileme)%refine1(n)
5529  is1recv(count) = ncont(tileme)%is1(n); ie1recv(count) = ncont(tileme)%ie1(n)
5530  js1recv(count) = ncont(tileme)%je1(n)+1; je1recv(count) = js1recv(count) + nhalo - 1
5531  select case(ncont(tileme)%align2(n))
5532  case ( south ) ! s <-> n
5533  is2recv(count) = ncont(tileme)%is2(n); ie2recv(count) = ncont(tileme)%ie2(n)
5534  js2recv(count) = ncont(tileme)%js2(n); je2recv(count) = js2recv(count) + nhalo - 1
5535  is1send(count) = ncont(tileme)%is1(n); ie1send(count) = ncont(tileme)%ie1(n)
5536  je1send(count) = ncont(tileme)%je1(n); js1send(count) = je1send(count) - shalo + 1
5537  is2send(count) = ncont(tileme)%is2(n); ie2send(count) = ncont(tileme)%ie2(n)
5538  je2send(count) = ncont(tileme)%js2(n)-1; js2send(count) = je2send(count) - shalo + 1
5539  case ( west ) ! w <-> n
5540  rotaterecv(count) = minus_ninety; rotatesend(count) = ninety
5541  is2recv(count) = ncont(tileme)%ie2(n); ie2recv(count) = is2recv(count) + nhalo - 1
5542  js2recv(count) = ncont(tileme)%js2(n); je2recv(count) = ncont(tileme)%je2(n)
5543  is1send(count) = ncont(tileme)%is1(n); ie1send(count) = ncont(tileme)%ie1(n)
5544  je1send(count) = ncont(tileme)%je1(n); js1send(count) = je1send(count) - whalo + 1
5545  ie2send(count) = ncont(tileme)%is2(n)-1; is2send(count) = ie2send(count) - whalo + 1
5546  js2send(count) = ncont(tileme)%js2(n); je2send(count) = ncont(tileme)%je2(n)
5547  end select
5548  end do
5549 
5550  nums = count
5551  numr = count
5552  !--- figure out the index for corner overlapping,
5553  !--- fill_corner_contact will be updated to deal with the situation that there are multiple tiles on
5554  !--- each side of six sides of cubic grid.
5555  if(.NOT. domain%rotated_ninety) then
5556  call fill_corner_contact(econt, scont, wcont, ncont, isglist, ieglist, jsglist, jeglist, numr, nums, &
5557  tilerecv, tilesend, is1recv, ie1recv, js1recv, je1recv, is2recv, ie2recv, &
5558  js2recv, je2recv, is1send, ie1send, js1send, je1send, is2send, ie2send, &
5559  js2send, je2send, align1recv, align2recv, align1send, align2send, &
5560  whalo, ehalo, shalo, nhalo, tileme )
5561  end if
5562 
5563  isc = domain%x(tme)%compute%begin; iec = domain%x(tme)%compute%end
5564  jsc = domain%y(tme)%compute%begin; jec = domain%y(tme)%compute%end
5565 
5566  !--- compute the overlapping for send.
5567  do n = 1, nums
5568  do list = 0, nlist-1
5569  m = mod( domain%pos+list, nlist )
5570  ntilenbr = size(domain%list(m)%x(:))
5571  do tnbr = 1, ntilenbr
5572  if( domain%list(m)%tile_id(tnbr) .NE. tilesend(n) ) cycle
5573  isc1 = max(isc, is1send(n)); iec1 = min(iec, ie1send(n))
5574  jsc1 = max(jsc, js1send(n)); jec1 = min(jec, je1send(n))
5575  if( isc1 > iec1 .OR. jsc1 > jec1 ) cycle
5576  !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5577  do dir = 1, 8
5578  !--- get the to_pe's data domain.
5579  select case ( dir )
5580  case ( 1 ) ! eastern halo
5581  if( align2send(n) .NE. east ) cycle
5582  isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5583  jsd = domain%list(m)%y(tnbr)%compute%begin; jed = domain%list(m)%y(tnbr)%compute%end
5584  case ( 2 ) ! southeast halo
5585  isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5586  jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5587  case ( 3 ) ! southern halo
5588  if( align2send(n) .NE. south ) cycle
5589  isd = domain%list(m)%x(tnbr)%compute%begin; ied = domain%list(m)%x(tnbr)%compute%end
5590  jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5591  case ( 4 ) ! southwest halo
5592  isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5593  jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5594  case ( 5 ) ! western halo
5595  if( align2send(n) .NE. west ) cycle
5596  isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5597  jsd = domain%list(m)%y(tnbr)%compute%begin; jed = domain%list(m)%y(tnbr)%compute%end
5598  case ( 6 ) ! northwest halo
5599  isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5600  jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5601  case ( 7 ) ! northern halo
5602  if( align2send(n) .NE. north ) cycle
5603  isd = domain%list(m)%x(tnbr)%compute%begin; ied = domain%list(m)%x(tnbr)%compute%end
5604  jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5605  case ( 8 ) ! northeast halo
5606  isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5607  jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5608  end select
5609  isd = max(isd, is2send(n)); ied = min(ied, ie2send(n))
5610  jsd = max(jsd, js2send(n)); jed = min(jed, je2send(n))
5611  if( isd > ied .OR. jsd > jed ) cycle
5612  ioff = 0; joff = 0
5613  nxd = ied - isd + 1
5614  nyd = jed - jsd + 1
5615  select case ( align2send(n) )
5616  case ( west, east )
5617  ioff = isd - is2send(n)
5618  joff = jsd - js2send(n)
5619  case ( south, north )
5620  ioff = isd - is2send(n)
5621  joff = jsd - js2send(n)
5622  end select
5623 
5624  !--- get the index in current pe.
5625  select case ( rotatesend(n) )
5626  case ( zero )
5627  isc2 = is1send(n) + ioff; iec2 = isc2 + nxd - 1
5628  jsc2 = js1send(n) + joff; jec2 = jsc2 + nyd - 1
5629  case ( ninety ) ! N -> W or S -> E
5630  iec2 = ie1send(n) - joff; isc2 = iec2 - nyd + 1
5631  jsc2 = js1send(n) + ioff; jec2 = jsc2 + nxd - 1
5632  case ( minus_ninety ) ! W -> N or E -> S
5633  isc2 = is1send(n) + joff; iec2 = isc2 + nyd - 1
5634  jec2 = je1send(n) - ioff; jsc2 = jec2 - nxd + 1
5635  end select
5636  is = max(isc1,isc2); ie = min(iec1,iec2)
5637  js = max(jsc1,jsc2); je = min(jec1,jec2)
5638  if(ie.GE.is .AND. je.GE.js )then
5639  if(.not. associated(overlapsend(m)%tileMe)) call allocate_update_overlap(overlapsend(m), &
5640  & maxoverlap)
5641  call insert_overlap_type(overlapsend(m), domain%list(m)%pe, tme, tnbr, &
5642  is, ie, js, je, dir, rotatesend(n), .true. )
5643  endif
5644  end do ! end do dir = 1, 8
5645  end do ! end do tNbr = 1, ntileNbr
5646  end do ! end do list = 0, nlist-1
5647  end do ! end do n = 1, numS
5648 
5649  !--- compute the overlapping for recv.
5650  do n = 1, numr
5651  do list = 0, nlist-1
5652  m = mod( domain%pos+nlist-list, nlist )
5653  ntilenbr = size(domain%list(m)%x(:))
5654  do tnbr = 1, ntilenbr
5655  if( domain%list(m)%tile_id(tnbr) .NE. tilerecv(n) ) cycle
5656  isc = domain%list(m)%x(tnbr)%compute%begin; iec = domain%list(m)%x(tnbr)%compute%end
5657  jsc = domain%list(m)%y(tnbr)%compute%begin; jec = domain%list(m)%y(tnbr)%compute%end
5658  isc = max(isc, is2recv(n)); iec = min(iec, ie2recv(n))
5659  jsc = max(jsc, js2recv(n)); jec = min(jec, je2recv(n))
5660  if( isc > iec .OR. jsc > jec ) cycle
5661  !--- find the offset for this overlapping.
5662  ioff = 0; joff = 0
5663  nxc = iec - isc + 1; nyc = jec - jsc + 1
5664  select case ( align2recv(n) )
5665  case ( west, east )
5666  if(align2recv(n) == west) then
5667  ioff = isc - is2recv(n)
5668  else
5669  ioff = ie2recv(n) - iec
5670  endif
5671  joff = jsc - js2recv(n)
5672  case ( north, south )
5673  ioff = isc - is2recv(n)
5674  if(align2recv(n) == south) then
5675  joff = jsc - js2recv(n)
5676  else
5677  joff = je2recv(n) - jec
5678  endif
5679  end select
5680 
5681  !--- get the index in current pe.
5682  select case ( rotaterecv(n) )
5683  case ( zero )
5684  isd1 = is1recv(n) + ioff; ied1 = isd1 + nxc - 1
5685  jsd1 = js1recv(n) + joff; jed1 = jsd1 + nyc - 1
5686  if( align1recv(n) == west ) then
5687  ied1 = ie1recv(n)-ioff; isd1 = ied1 - nxc + 1
5688  endif
5689  if( align1recv(n) == south ) then
5690  jed1 = je1recv(n)-joff; jsd1 = jed1 - nyc + 1
5691  endif
5692  case ( ninety ) ! N -> W or S -> E
5693  if( align1recv(n) == west ) then
5694  ied1 = ie1recv(n)-joff; isd1 = ied1 - nyc + 1
5695  else
5696  isd1 = is1recv(n)+joff; ied1 = isd1 + nyc - 1
5697  endif
5698  jed1 = je1recv(n) - ioff; jsd1 = jed1 - nxc + 1
5699  case ( minus_ninety ) ! W -> N or E -> S
5700  ied1 = ie1recv(n) - joff; isd1 = ied1 - nyc + 1
5701  if( align1recv(n) == south ) then
5702  jed1 = je1recv(n)-ioff; jsd1 = jed1 - nxc + 1
5703  else
5704  jsd1 = js1recv(n)+ioff; jed1 = jsd1 + nxc - 1
5705  endif
5706  end select
5707 
5708  !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5709  do dir = 1, 8
5710  select case ( dir )
5711  case ( 1 ) ! eastern halo
5712  if( align1recv(n) .NE. east ) cycle
5713  isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5714  jsd2 = domain%y(tme)%compute%begin; jed2 = domain%y(tme)%compute%end
5715  case ( 2 ) ! southeast halo
5716  isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5717  jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5718  case ( 3 ) ! southern halo
5719  if( align1recv(n) .NE. south ) cycle
5720  isd2 = domain%x(tme)%compute%begin; ied2 = domain%x(tme)%compute%end
5721  jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5722  case ( 4 ) ! southwest halo
5723  isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5724  jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5725  case ( 5 ) ! western halo
5726  if( align1recv(n) .NE. west ) cycle
5727  isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5728  jsd2 = domain%y(tme)%compute%begin; jed2 = domain%y(tme)%compute%end
5729  case ( 6 ) ! northwest halo
5730  isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5731  jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5732  case ( 7 ) ! northern halo
5733  if( align1recv(n) .NE. north ) cycle
5734  isd2 = domain%x(tme)%compute%begin; ied2 = domain%x(tme)%compute%end
5735  jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5736  case ( 8 ) ! northeast halo
5737  isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5738  jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5739  end select
5740  is = max(isd1,isd2); ie = min(ied1,ied2)
5741  js = max(jsd1,jsd2); je = min(jed1,jed2)
5742  if(ie.GE.is .AND. je.GE.js )then
5743  if(.not. associated(overlaprecv(m)%tileMe)) call allocate_update_overlap(overlaprecv(m), &
5744  & maxoverlap)
5745  call insert_overlap_type(overlaprecv(m), domain%list(m)%pe, tme, tnbr, &
5746  is, ie, js, je, dir, rotaterecv(n), .true.)
5747  count = overlaprecv(m)%count
5748  endif
5749  end do ! end do dir = 1, 8
5750  end do ! end do tNbr = 1, ntileNbr
5751  end do ! end do list = 0, nlist-1
5752  end do ! end do n = 1, numR
5753  end do ! end do tMe = 1, ntileMe
5754 
5755  !--- copy the overlapping information into domain data
5756  nsend = 0; nsend2 = 0
5757  do list = 0, nlist-1
5758  m = mod( domain%pos+list, nlist )
5759  if(overlapsend(m)%count>0) nsend = nsend + 1
5760  enddo
5761 
5762  if(debug_message_passing) then
5763  !--- write out send information
5764  iunit = mpp_pe() + 1000
5765  do list = 0, nlist-1
5766  m = mod( domain%pos+list, nlist )
5767  if(overlapsend(m)%count==0) cycle
5768  write(iunit, *) "********to_pe = " ,overlapsend(m)%pe, " count = ",overlapsend(m)%count
5769  do n = 1, overlapsend(m)%count
5770  write(iunit, *) overlapsend(m)%is(n), overlapsend(m)%ie(n), overlapsend(m)%js(n), overlapsend(m)%je(n), &
5771  overlapsend(m)%dir(n), overlapsend(m)%rotation(n)
5772  enddo
5773  enddo
5774  if(nsend >0) flush(iunit)
5775  endif
5776 
5777  dirlist(1) = 1; dirlist(2) = 3; dirlist(3) = 5; dirlist(4) = 7
5778  dirlist(5) = 2; dirlist(6) = 4; dirlist(7) = 6; dirlist(8) = 8
5779 
5780  ! copy the overlap information into domain.
5781  if(nsend >0) then
5782  if(associated(domain%update_T%send)) then
5783  do m = 1, domain%update_T%nsend
5784  call deallocate_overlap_type(domain%update_T%send(m))
5785  enddo
5786  deallocate(domain%update_T%send)
5787  endif
5788  domain%update_T%nsend = nsend
5789  allocate(domain%update_T%send(nsend))
5790  do list = 0, nlist-1
5791  m = mod( domain%pos+list, nlist )
5792  ntilenbr = size(domain%list(m)%x(:))
5793  !--- for the send, the list should be in tileNbr order and dir order to be consistent with Recv
5794  if(overlapsend(m)%count > 0) then
5795  nsend2 = nsend2+1
5796  if(nsend2>nsend) call mpp_error(fatal, &
5797  "mpp_domains_define.inc(define_contact_point): nsend2 is greater than nsend")
5798  call allocate_update_overlap(domain%update_T%send(nsend2), overlapsend(m)%count)
5799 
5800  do tnbr = 1, ntilenbr
5801  do tt = 1, ntileme
5802  if(domain%list(m)%pe == domain%pe) then ! own processor
5803  tme = tnbr+tt-1
5804  if(tme > ntileme) tme = tme - ntileme
5805  else
5806  tme = tt
5807  end if
5808  do n = 1, 8 ! loop over 8 direction
5809  do l = 1, overlapsend(m)%count
5810  if(overlapsend(m)%tileMe(l) .NE. tme) cycle
5811  if(overlapsend(m)%tileNbr(l) .NE. tnbr) cycle
5812  if(overlapsend(m)%dir(l) .NE. dirlist(n) ) cycle
5813  call insert_overlap_type(domain%update_T%send(nsend2), overlapsend(m)%pe, &
5814  overlapsend(m)%tileMe(l), overlapsend(m)%tileNbr(l), overlapsend(m)%is(l), &
5815  overlapsend(m)%ie(l), overlapsend(m)%js(l), overlapsend(m)%je(l), overlapsend(m)%dir(l),&
5816  overlapsend(m)%rotation(l), overlapsend(m)%from_contact(l) )
5817  end do
5818  end do
5819  end do
5820  end do
5821  end if
5822  enddo
5823  endif
5824 
5825  if(nsend2 .NE. nsend) call mpp_error(fatal, &
5826  "mpp_domains_define.inc(define_contact_point): nsend2 does not equal to nsend")
5827 
5828  nrecv = 0; nrecv2 = 0
5829  do list = 0, nlist-1
5830  m = mod( domain%pos+list, nlist )
5831  if(overlaprecv(m)%count>0) nrecv = nrecv + 1
5832  enddo
5833 
5834  if(debug_message_passing) then
5835  do list = 0, nlist-1
5836  m = mod( domain%pos+list, nlist )
5837  if(overlaprecv(m)%count==0) cycle
5838  write(iunit, *) "********from_pe = " ,overlaprecv(m)%pe, " count = ",overlaprecv(m)%count
5839  do n = 1, overlaprecv(m)%count
5840  write(iunit, *) overlaprecv(m)%is(n), overlaprecv(m)%ie(n), overlaprecv(m)%js(n), overlaprecv(m)%je(n), &
5841  overlaprecv(m)%dir(n), overlaprecv(m)%rotation(n)
5842  enddo
5843  enddo
5844  if(nrecv >0) flush(iunit)
5845  endif
5846 
5847  if(nrecv >0) then
5848  if(associated(domain%update_T%recv)) then
5849  do m = 1, domain%update_T%nrecv
5850  call deallocate_overlap_type(domain%update_T%recv(m))
5851  enddo
5852  deallocate(domain%update_T%recv)
5853  endif
5854  domain%update_T%nrecv = nrecv
5855  allocate(domain%update_T%recv(nrecv))
5856 
5857  do list = 0, nlist-1
5858  m = mod( domain%pos+nlist-list, nlist )
5859  ntilenbr = size(domain%list(m)%x(:))
5860  if(overlaprecv(m)%count > 0) then
5861  nrecv2 = nrecv2 + 1
5862  if(nrecv2>nrecv) call mpp_error(fatal, &
5863  "mpp_domains_define.inc(define_contact_point): nrecv2 is greater than nrecv")
5864  call allocate_update_overlap(domain%update_T%recv(nrecv2), overlaprecv(m)%count)
5865  do tme = 1, ntileme
5866  do tt = 1, ntilenbr
5867  !--- make sure the same order tile for different pe count
5868  if(domain%list(m)%pe == domain%pe) then ! own processor
5869  tnbr = tme+tt-1
5870  if(tnbr>ntilenbr) tnbr = tnbr - ntilenbr
5871  else
5872  tnbr = tt
5873  end if
5874  do n = 1, 8 ! loop over 8 direction
5875  do l = 1, overlaprecv(m)%count
5876  if(overlaprecv(m)%tileMe(l) .NE. tme) cycle
5877  if(overlaprecv(m)%tileNbr(l) .NE. tnbr) cycle
5878  if(overlaprecv(m)%dir(l) .NE. dirlist(n) ) cycle
5879  call insert_overlap_type(domain%update_T%recv(nrecv2), overlaprecv(m)%pe, &
5880  overlaprecv(m)%tileMe(l), overlaprecv(m)%tileNbr(l), overlaprecv(m)%is(l), &
5881  overlaprecv(m)%ie(l), overlaprecv(m)%js(l), overlaprecv(m)%je(l), overlaprecv(m)%dir(l),&
5882  overlaprecv(m)%rotation(l), overlaprecv(m)%from_contact(l))
5883  count = domain%update_T%recv(nrecv2)%count
5884  end do
5885  end do
5886  end do
5887  end do
5888  end if
5889  end do
5890  endif
5891 
5892  if(nrecv2 .NE. nrecv) call mpp_error(fatal, &
5893  "mpp_domains_define.inc(define_contact_point): nrecv2 does not equal to nrecv")
5894 
5895  do m = 0,nlist-1
5896  call deallocate_overlap_type(overlapsend(m))
5897  call deallocate_overlap_type(overlaprecv(m))
5898  enddo
5899  !--- release memory
5900  do n = 1, ntiles
5901  deallocate(econt(n)%tile, wcont(n)%tile, scont(n)%tile, ncont(n)%tile )
5902  deallocate(econt(n)%align1, wcont(n)%align1, scont(n)%align1, ncont(n)%align1)
5903  deallocate(econt(n)%align2, wcont(n)%align2, scont(n)%align2, ncont(n)%align2)
5904  deallocate(econt(n)%refine1, wcont(n)%refine1, scont(n)%refine1, ncont(n)%refine1)
5905  deallocate(econt(n)%refine2, wcont(n)%refine2, scont(n)%refine2, ncont(n)%refine2)
5906  deallocate(econt(n)%is1, econt(n)%ie1, econt(n)%js1, econt(n)%je1 )
5907  deallocate(econt(n)%is2, econt(n)%ie2, econt(n)%js2, econt(n)%je2 )
5908  deallocate(wcont(n)%is1, wcont(n)%ie1, wcont(n)%js1, wcont(n)%je1 )
5909  deallocate(wcont(n)%is2, wcont(n)%ie2, wcont(n)%js2, wcont(n)%je2 )
5910  deallocate(scont(n)%is1, scont(n)%ie1, scont(n)%js1, scont(n)%je1 )
5911  deallocate(scont(n)%is2, scont(n)%ie2, scont(n)%js2, scont(n)%je2 )
5912  deallocate(ncont(n)%is1, ncont(n)%ie1, ncont(n)%js1, ncont(n)%je1 )
5913  deallocate(ncont(n)%is2, ncont(n)%ie2, ncont(n)%js2, ncont(n)%je2 )
5914  end do
5915 
5916  domain%initialized = .true.
5917 
5918 
5919  end subroutine define_contact_point
5920 
5921 !##############################################################################
5922 !> always fill the contact according to index order.
5923 subroutine fill_contact(Contact, tile, is1, ie1, js1, je1, is2, ie2, js2, je2, align1, align2, refine1, refine2 )
5924  type(contact_type), intent(inout) :: Contact
5925  integer, intent(in) :: tile
5926  integer, intent(in) :: is1, ie1, js1, je1
5927  integer, intent(in) :: is2, ie2, js2, je2
5928  integer, intent(in) :: align1, align2
5929  real, intent(in) :: refine1, refine2
5930  integer :: pos, n
5931 
5932  do pos = 1, contact%ncontact
5933  select case(align1)
5934  case(west, east)
5935  if( js1 < contact%js1(pos) ) exit
5936  case(south, north)
5937  if( is1 < contact%is1(pos) ) exit
5938  end select
5939  end do
5940 
5941  contact%ncontact = contact%ncontact + 1
5942  do n = contact%ncontact, pos+1, -1 ! shift the data if needed.
5943  contact%tile(n) = contact%tile(n-1)
5944  contact%align1(n) = contact%align1(n-1)
5945  contact%align2(n) = contact%align2(n-1)
5946  contact%is1(n) = contact%is1(n-1); contact%ie1(n) = contact%ie1(n-1)
5947  contact%js1(n) = contact%js1(n-1); contact%je1(n) = contact%je1(n-1)
5948  contact%is2(n) = contact%is2(n-1); contact%ie2(n) = contact%ie2(n-1)
5949  contact%js2(n) = contact%js2(n-1); contact%je2(n) = contact%je2(n-1)
5950  end do
5951 
5952  contact%tile(pos) = tile
5953  contact%align1(pos) = align1
5954  contact%align2(pos) = align2
5955  contact%refine1(pos) = refine1
5956  contact%refine2(pos) = refine2
5957  contact%is1(pos) = is1; contact%ie1(pos) = ie1
5958  contact%js1(pos) = js1; contact%je1(pos) = je1
5959  contact%is2(pos) = is2; contact%ie2(pos) = ie2
5960  contact%js2(pos) = js2; contact%je2(pos) = je2
5961 
5962 end subroutine fill_contact
5963 
5964 !############################################################################
5965 !> this routine sets the overlapping between tiles for E,C,N-cell based on T-cell overlapping
5966 subroutine set_contact_point(domain, position)
5967  type(domain2d), intent(inout) :: domain
5968  integer, intent(in) :: position
5969 
5970  integer :: ishift, jshift, nlist, list, m, n
5971  integer :: ntileMe, tMe, dir, count, pos, nsend, nrecv
5972  integer :: isoff1, ieoff1, jsoff1, jeoff1
5973  type(overlap_type), pointer :: ptrIn => null()
5974  type(overlapspec), pointer :: update_in => null()
5975  type(overlapspec), pointer :: update_out => null()
5976  type(overlap_type) :: overlapList(0:size(domain%list(:))-1)
5977  type(overlap_type) :: overlap
5978 
5979  call mpp_get_domain_shift(domain, ishift, jshift, position)
5980  update_in => domain%update_T
5981  select case(position)
5982  case (corner)
5983  update_out => domain%update_C
5984  case (east)
5985  update_out => domain%update_E
5986  case (north)
5987  update_out => domain%update_N
5988  case default
5989  call mpp_error(fatal, "mpp_domains_define.inc(set_contact_point): the position should be CORNER, EAST or NORTH")
5990  end select
5991 
5992  update_out%xbegin = update_in%xbegin; update_out%xend = update_in%xend + ishift
5993  update_out%ybegin = update_in%ybegin; update_out%yend = update_in%yend + jshift
5994  update_out%whalo = update_in%whalo; update_out%ehalo = update_in%ehalo
5995  update_out%shalo = update_in%shalo; update_out%nhalo = update_in%nhalo
5996 
5997  nlist = size(domain%list(:))
5998  ntileme = size(domain%x(:))
5999  call allocate_update_overlap(overlap, maxoverlap)
6000  do m = 0, nlist-1
6001  call init_overlap_type(overlaplist(m))
6002  enddo
6003 
6004  !--- first copy the send information in update_out to send
6005  nsend = update_out%nsend
6006  do m = 1, nsend
6007  pos = update_out%send(m)%pe - mpp_root_pe()
6008  call add_update_overlap(overlaplist(pos), update_out%send(m))
6009  call deallocate_overlap_type(update_out%send(m))
6010  enddo
6011  if(ASSOCIATED(update_out%send) )deallocate(update_out%send)
6012 
6013  !--- loop over the list of overlapping.
6014  nsend = update_in%nsend
6015  do m = 1, nsend
6016  ptrin => update_in%send(m)
6017  pos = ptrin%pe - mpp_root_pe()
6018  do n = 1, ptrin%count
6019  dir = ptrin%dir(n)
6020  ! only set overlapping between tiles for send ( ptrOut%overlap(1) is false )
6021  if(ptrin%from_contact(n)) then
6022  select case ( dir )
6023  case ( 1 ) ! to_pe's eastern halo
6024  select case(ptrin%rotation(n))
6025  case (zero) ! W -> E
6026  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6027  case (ninety) ! S -> E
6028  isoff1 = 0; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6029  end select
6030  case ( 2 ) ! to_pe's south-eastearn halo
6031  select case(ptrin%rotation(n))
6032  case (zero)
6033  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6034  case (ninety)
6035  isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6036  case (minus_ninety)
6037  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6038  end select
6039  case ( 3 ) ! to_pe's southern halo
6040  select case(ptrin%rotation(n))
6041  case (zero) ! N -> S
6042  isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6043  case (minus_ninety) ! E -> S
6044  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = ishift
6045  end select
6046  case ( 4 ) ! to_pe's south-westearn halo
6047  select case(ptrin%rotation(n))
6048  case (zero)
6049  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6050  case (ninety)
6051  isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6052  case (minus_ninety)
6053  isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6054  end select
6055  case ( 5 ) ! to_pe's western halo
6056  select case(ptrin%rotation(n))
6057  case (zero) ! E -> W
6058  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6059  case (ninety) ! N -> W
6060  isoff1 = 0; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6061  end select
6062  case ( 6 ) ! to_pe's north-westearn halo
6063  select case(ptrin%rotation(n))
6064  case (zero)
6065  isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6066  case (ninety)
6067  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6068  case (minus_ninety)
6069  isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6070  end select
6071  case ( 7 ) ! to_pe's northern halo
6072  select case(ptrin%rotation(n))
6073  case (zero) ! S -> N
6074  isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6075  case (minus_ninety) ! W -> N
6076  isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = ishift
6077  end select
6078  case ( 8 ) ! to_pe's north-eastearn halo
6079  select case(ptrin%rotation(n))
6080  case (zero)
6081  isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6082  case (ninety)
6083  isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6084  case (minus_ninety)
6085  isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6086  end select
6087  end select
6088  call insert_overlap_type(overlap, ptrin%pe, ptrin%tileMe(n), ptrin%tileNbr(n), &
6089  ptrin%is(n) + isoff1, ptrin%ie(n) + ieoff1, ptrin%js(n) + jsoff1, &
6090  ptrin%je(n) + jeoff1, ptrin%dir(n), ptrin%rotation(n), ptrin%from_contact(n))
6091  end if
6092  end do ! do n = 1, prtIn%count
6093  if(overlap%count > 0) then
6094  call add_update_overlap(overlaplist(pos), overlap)
6095  call init_overlap_type(overlap)
6096  endif
6097  end do ! do list = 0, nlist-1
6098 
6099  nsend = 0
6100  do list = 0, nlist-1
6101  m = mod( domain%pos+list, nlist )
6102  if(overlaplist(m)%count>0) nsend = nsend+1
6103  enddo
6104 
6105  update_out%nsend = nsend
6106  if(nsend>0) then
6107  if (associated(update_out%send)) deallocate(update_out%send) !< Check if associated
6108  allocate(update_out%send(nsend))
6109  pos = 0
6110  do list = 0, nlist-1
6111  m = mod( domain%pos+list, nlist )
6112  if(overlaplist(m)%count>0) then
6113  pos = pos+1
6114  if(pos>nsend) call mpp_error(fatal, &
6115  "mpp_domains_define.inc(set_contact_point): pos should be no larger than nsend")
6116  call add_update_overlap(update_out%send(pos), overlaplist(m))
6117  call deallocate_overlap_type(overlaplist(m))
6118  endif
6119  enddo
6120  if(pos .NE. nsend) call mpp_error(fatal, &
6121  "mpp_domains_define.inc(set_contact_point): pos should equal to nsend")
6122  endif
6123 
6124 
6125 
6126  !--- first copy the recv information in update_out to recv
6127  nrecv = update_out%nrecv
6128  do m = 1, nrecv
6129  pos = update_out%recv(m)%pe - mpp_root_pe()
6130  call add_update_overlap(overlaplist(pos), update_out%recv(m))
6131  call deallocate_overlap_type(update_out%recv(m))
6132  enddo
6133  if(ASSOCIATED(update_out%recv) )deallocate(update_out%recv)
6134 
6135  !--- loop over the list of overlapping.
6136  nrecv = update_in%nrecv
6137  do m=1,nrecv
6138  ptrin => update_in%recv(m)
6139  pos = ptrin%pe - mpp_root_pe()
6140  do n = 1, ptrin%count
6141  dir = ptrin%dir(n)
6142  ! only set overlapping between tiles for recv ( ptrOut%overlap(1) is false )
6143  if(ptrin%from_contact(n)) then
6144  select case ( dir )
6145  case ( 1 ) ! E
6146  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6147  case ( 2 ) ! SE
6148  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6149  case ( 3 ) ! S
6150  isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6151  case ( 4 ) ! SW
6152  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6153  case ( 5 ) ! W
6154  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6155  case ( 6 ) ! NW
6156  isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6157  case ( 7 ) ! N
6158  isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6159  case ( 8 ) ! NE
6160  isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6161  end select
6162  call insert_overlap_type(overlap, ptrin%pe, ptrin%tileMe(n), ptrin%tileNbr(n), &
6163  ptrin%is(n) + isoff1, ptrin%ie(n) + ieoff1, ptrin%js(n) + jsoff1, &
6164  ptrin%je(n) + jeoff1, ptrin%dir(n), ptrin%rotation(n), ptrin%from_contact(n))
6165  count = overlap%count
6166  end if
6167  end do ! do n = 1, ptrIn%count
6168  if(overlap%count > 0) then
6169  call add_update_overlap(overlaplist(pos), overlap)
6170  call init_overlap_type(overlap)
6171  endif
6172  do tme = 1, size(domain%x(:))
6173  do n = 1, overlap%count
6174  if(overlap%tileMe(n) == tme) then
6175  if(overlap%dir(n) == 1 ) domain%x(tme)%loffset = 0
6176  if(overlap%dir(n) == 7 ) domain%y(tme)%loffset = 0
6177  end if
6178  end do
6179  end do
6180  end do ! do list = 0, nlist-1
6181 
6182  nrecv = 0
6183  do list = 0, nlist-1
6184  m = mod( domain%pos+nlist-list, nlist )
6185  if(overlaplist(m)%count>0) nrecv = nrecv+1
6186  enddo
6187 
6188  update_out%nrecv = nrecv
6189  if(nrecv>0) then
6190  if (associated(update_out%recv)) deallocate(update_out%recv) !< Check if associated
6191  allocate(update_out%recv(nrecv))
6192  pos = 0
6193  do list = 0, nlist-1
6194  m = mod( domain%pos+nlist-list, nlist )
6195  if(overlaplist(m)%count>0) then
6196  pos = pos+1
6197  if(pos>nrecv) call mpp_error(fatal, &
6198  "mpp_domains_define.inc(set_contact_point): pos should be no larger than nrecv")
6199  call add_update_overlap(update_out%recv(pos), overlaplist(m))
6200  call deallocate_overlap_type(overlaplist(m))
6201  endif
6202  enddo
6203  if(pos .NE. nrecv) call mpp_error(fatal, &
6204  "mpp_domains_define.inc(set_contact_point): pos should equal to nrecv")
6205  endif
6206 
6207  call deallocate_overlap_type(overlap)
6208 
6209 end subroutine set_contact_point
6210 
6211 !> set up the overlapping for boundary check if the domain is symmetry. The check will be
6212 !! done on current pe for east boundary for E-cell, north boundary for N-cell,
6213 !! East and North boundary for C-cell
6214 subroutine set_check_overlap( domain, position )
6215 type(domain2d), intent(in) :: domain
6216 integer, intent(in) :: position
6217 integer :: nlist, m, n
6218 integer, parameter :: MAXCOUNT = 100
6219 integer :: is, ie, js, je
6220 integer :: nsend, nrecv, pos, maxsize, rotation
6221 type(overlap_type) :: overlap
6222 type(overlapspec), pointer :: update => null()
6223 type(overlapspec), pointer :: check => null()
6224 
6225 select case(position)
6226 case (corner)
6227  update => domain%update_C
6228  check => domain%check_C
6229 case (east)
6230  update => domain%update_E
6231  check => domain%check_E
6232 case (north)
6233  update => domain%update_N
6234  check => domain%check_N
6235 case default
6236  call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): position should be CORNER, EAST or NORTH")
6237 end select
6238 
6239 check%xbegin = update%xbegin; check%xend = update%xend
6240 check%ybegin = update%ybegin; check%yend = update%yend
6241 check%nsend = 0
6242 check%nrecv = 0
6243 if( .NOT. domain%symmetry ) return
6244 
6245 nsend = 0
6246 maxsize = 0
6247 do m = 1, update%nsend
6248  do n = 1, update%send(m)%count
6249  if( update%send(m)%rotation(n) == one_hundred_eighty ) cycle
6250  if( ( (position == east .OR. position == corner) .AND. update%send(m)%dir(n) == 1 ) .OR. &
6251  ( (position == north .OR. position == corner) .AND. update%send(m)%dir(n) == 7 ) ) then
6252  maxsize = max(maxsize, update%send(m)%count)
6253  nsend = nsend + 1
6254  exit
6255  endif
6256  enddo
6257 enddo
6258 
6259 if(nsend>0) then
6260  if (associated(check%send)) deallocate(check%send) !< Check if associated
6261  allocate(check%send(nsend))
6262  call allocate_check_overlap(overlap, maxsize)
6263 endif
6264 
6265 
6266 nlist = size(domain%list(:))
6267 !--- loop over the list of domains to find the boundary overlap for send
6268 pos = 0
6269 do m = 1, update%nsend
6270  do n = 1, update%send(m)%count
6271  if( update%send(m)%rotation(n) == one_hundred_eighty ) cycle
6272  ! comparing east direction on currently pe
6273  if( (position == east .OR. position == corner) .AND. update%send(m)%dir(n) == 1 ) then
6274  rotation = update%send(m)%rotation(n)
6275  select case( rotation )
6276  case( zero ) ! W -> E
6277  is = update%send(m)%is(n) - 1
6278  ie = is
6279  js = update%send(m)%js(n)
6280  je = update%send(m)%je(n)
6281  case( ninety ) ! S -> E
6282  is = update%send(m)%is(n)
6283  ie = update%send(m)%ie(n)
6284  js = update%send(m)%js(n) - 1
6285  je = js
6286  end select
6287  call insert_check_overlap(overlap, update%send(m)%pe, &
6288  update%send(m)%tileMe(n), 1, rotation, is, ie, js, je)
6289  end if
6290 
6291  ! comparing north direction on currently pe
6292  if( (position == north .OR. position == corner) .AND. update%send(m)%dir(n) == 7 ) then
6293  rotation = update%send(m)%rotation(n)
6294  select case( rotation )
6295  case( zero ) ! S->N
6296  is = update%send(m)%is(n)
6297  ie = update%send(m)%ie(n)
6298  js = update%send(m)%js(n) - 1
6299  je = js
6300  case( minus_ninety ) ! W->N
6301  is = update%send(m)%is(n) - 1
6302  ie = is
6303  js = update%send(m)%js(n)
6304  je = update%send(m)%je(n)
6305  end select
6306  call insert_check_overlap(overlap, update%send(m)%pe, &
6307  update%send(m)%tileMe(n), 4, rotation, is, ie, js, je)
6308  end if
6309  end do ! do n =1, update%send(m)%count
6310  if(overlap%count>0) then
6311  pos = pos+1
6312  if(pos>nsend)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6313  call add_check_overlap(check%send(pos), overlap)
6314  call init_overlap_type(overlap)
6315  endif
6316 end do ! end do list = 0, nlist
6317 
6318 if(pos .NE. nsend)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6319 
6320 nrecv = 0
6321 maxsize = 0
6322 do m = 1, update%nrecv
6323  do n = 1, update%recv(m)%count
6324  if( update%recv(m)%rotation(n) == one_hundred_eighty ) cycle
6325  if( ( (position == east .OR. position == corner) .AND. update%recv(m)%dir(n) == 1 ) .OR. &
6326  ( (position == north .OR. position == corner) .AND. update%recv(m)%dir(n) == 7 ) ) then
6327  maxsize = max(maxsize, update%recv(m)%count)
6328  nrecv = nrecv + 1
6329  exit
6330  endif
6331  enddo
6332 enddo
6333 
6334 if(nsend>0) call deallocate_overlap_type(overlap)
6335 
6336 if(nrecv>0) then
6337  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
6338  allocate(check%recv(nrecv))
6339  call allocate_check_overlap(overlap, maxsize)
6340 endif
6341 
6342 pos = 0
6343 do m = 1, update%nrecv
6344  do n = 1, update%recv(m)%count
6345  if( update%recv(m)%rotation(n) == one_hundred_eighty ) cycle
6346  if( (position == east .OR. position == corner) .AND. update%recv(m)%dir(n) == 1 ) then
6347  is = update%recv(m)%is(n) - 1
6348  ie = is
6349  js = update%recv(m)%js(n)
6350  je = update%recv(m)%je(n)
6351  call insert_check_overlap(overlap, update%recv(m)%pe, &
6352  update%recv(m)%tileMe(n), 1, update%recv(m)%rotation(n), is, ie, js, je)
6353  end if
6354  if( (position == north .OR. position == corner) .AND. update%recv(m)%dir(n) == 7 ) then
6355  is = update%recv(m)%is(n)
6356  ie = update%recv(m)%ie(n)
6357  js = update%recv(m)%js(n) - 1
6358  je = js
6359  call insert_check_overlap(overlap, update%recv(m)%pe, &
6360  update%recv(m)%tileMe(n), 3, update%recv(m)%rotation(n), is, ie, js, je)
6361  end if
6362  end do ! n = 1, overlap%count
6363  if(overlap%count>0) then
6364  pos = pos+1
6365  if(pos>nrecv)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6366  call add_check_overlap(check%recv(pos), overlap)
6367  call init_overlap_type(overlap)
6368  endif
6369 end do ! end do list = 0, nlist
6370 
6371 if(pos .NE. nrecv)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6372 if(nrecv>0) call deallocate_overlap_type(overlap)
6373 
6374 end subroutine set_check_overlap
6375 
6376 !#############################################################################
6377 !> set up the overlapping for boundary if the domain is symmetry.
6378 subroutine set_bound_overlap( domain, position )
6379  type(domain2d), intent(inout) :: domain
6380  integer, intent(in) :: position
6381  integer :: m, n, l, count, dr, tMe
6382  integer, parameter :: MAXCOUNT = 100
6383  integer, dimension(MAXCOUNT) :: dir, rotation, is, ie, js, je, tileMe, index
6384  integer, dimension(size(domain%x(:)), 4) :: nrecvl
6385  integer, dimension(size(domain%x(:)), 4, MAXCOUNT) :: isl, iel, jsl, jel
6386  type(overlap_type), pointer :: overlap => null()
6387  type(overlapspec), pointer :: update => null()
6388  type(overlapspec), pointer :: bound => null()
6389  integer :: nlist_send, nlist_recv, ishift, jshift
6390  integer :: ism, iem, jsm, jem, nsend, nrecv
6391  integer :: isg, ieg, jsg, jeg, nlist, list
6392  integer :: npes_x, npes_y, ipos, jpos, inbr, jnbr
6393  integer :: isc, iec, jsc, jec, my_pe
6394  integer :: pe_south1, pe_south2, pe_west0, pe_west1, pe_west2
6395  integer :: is_south1, ie_south1, js_south1, je_south1
6396  integer :: is_south2, ie_south2, js_south2, je_south2
6397  integer :: is_west0, ie_west0, js_west0, je_west0
6398  integer :: is_west1, ie_west1, js_west1, je_west1
6399  integer :: is_west2, ie_west2, js_west2, je_west2
6400  logical :: x_cyclic, y_cyclic, folded_north
6401 
6402  is_south1=0; ie_south1=0; js_south1=0; je_south1=0
6403  is_south2=0; ie_south2=0; js_south2=0; je_south2=0
6404  is_west0=0; ie_west0=0; js_west0=0; je_west0=0
6405  is_west1=0; ie_west1=0; js_west1=0; je_west1=0
6406  is_west2=0; ie_west2=0; js_west2=0; je_west2=0
6407 
6408 
6409  if( position == center .OR. .NOT. domain%symmetry ) return
6410  call mpp_get_domain_shift(domain, ishift, jshift, position)
6411  call mpp_get_global_domain(domain, isg, ieg, jsg, jeg)
6412  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem )
6413 
6414  select case(position)
6415  case (corner)
6416  update => domain%update_C
6417  bound => domain%bound_C
6418  case (east)
6419  update => domain%update_E
6420  bound => domain%bound_E
6421  case (north)
6422  update => domain%update_N
6423  bound => domain%bound_N
6424  case default
6425  call mpp_error( fatal, "mpp_domains_mod(set_bound_overlap): invalid option of position")
6426  end select
6427 
6428  bound%xbegin = ism; bound%xend = iem + ishift
6429  bound%ybegin = jsm; bound%yend = jem + jshift
6430 
6431  nlist_send = max(update%nsend,4)
6432  nlist_recv = max(update%nrecv,4)
6433  bound%nsend = nlist_send
6434  bound%nrecv = nlist_recv
6435  if(nlist_send >0) then
6436  if (associated(bound%send)) deallocate(bound%send) !< Check if associated
6437  allocate(bound%send(nlist_send))
6438  bound%send(:)%count = 0
6439  endif
6440  if(nlist_recv >0) then
6441  if (associated(bound%recv)) deallocate(bound%recv) !< Check if associated
6442  allocate(bound%recv(nlist_recv))
6443  bound%recv(:)%count = 0
6444  endif
6445  !--- loop over the list of domains to find the boundary overlap for send
6446  nlist = size(domain%list(:))
6447 
6448  npes_x = size(domain%x(1)%list(:))
6449  npes_y = size(domain%y(1)%list(:))
6450  x_cyclic = domain%x(1)%cyclic
6451  y_cyclic = domain%y(1)%cyclic
6452  folded_north = btest(domain%fold,north)
6453  ipos = domain%x(1)%pos
6454  jpos = domain%y(1)%pos
6455  isc = domain%x(1)%compute%begin; iec = domain%x(1)%compute%end
6456  jsc = domain%y(1)%compute%begin; jec = domain%y(1)%compute%end
6457 
6458  nsend = 0
6459  if(domain%ntiles == 1) then ! use neighbor processor to configure send and recv
6460  ! currently only set up for west and south boundary
6461 
6462  ! south boundary for send
6463  pe_south1 = null_pe; pe_south2 = null_pe
6464  if( position == north .OR. position == corner ) then
6465  inbr = ipos; jnbr = jpos + 1
6466  if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6467  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6468  pe_south1 = domain%pearray(inbr,jnbr)
6469  is_south1 = isc + ishift; ie_south1 = iec+ishift
6470  js_south1 = jec + jshift; je_south1 = js_south1
6471  endif
6472  endif
6473  !--- send to the southwest processor when position is NORTH
6474  if( position == corner ) then
6475  inbr = ipos + 1; jnbr = jpos + 1
6476  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6477  if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6478  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6479  pe_south2 = domain%pearray(inbr,jnbr)
6480  is_south2 = iec + ishift; ie_south2 = is_south2
6481  js_south2 = jec + jshift; je_south2 = js_south2
6482  endif
6483  endif
6484 
6485  !---west boundary for send
6486  pe_west0 = null_pe; pe_west1 = null_pe; pe_west2 = null_pe
6487  if( position == east ) then
6488  inbr = ipos+1; jnbr = jpos
6489  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6490  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6491  pe_west1 = domain%pearray(inbr,jnbr)
6492  is_west1 = iec + ishift; ie_west1 = is_west1
6493  js_west1 = jsc + jshift; je_west1 = jec + jshift
6494  endif
6495  else if ( position == corner ) then ! possible split into two parts.
6496  !--- on the fold.
6497  if( folded_north .AND. jec == jeg .AND. ipos .LT. (npes_x-1)/2 ) then
6498  inbr = npes_x - ipos - 1; jnbr = jpos
6499  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6500  pe_west0 = domain%pearray(inbr,jnbr)
6501  is_west0 = iec+ishift; ie_west0 = is_west0
6502  js_west0 = jec+jshift; je_west0 = js_west0
6503  endif
6504  endif
6505 
6506  if( folded_north .AND. jec == jeg .AND. ipos .GE. npes_x/2 .AND. ipos .LT. (npes_x-1) ) then
6507  inbr = ipos+1; jnbr = jpos
6508  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6509  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6510  pe_west1 = domain%pearray(inbr,jnbr)
6511  is_west1 = iec + ishift; ie_west1 = is_west1
6512  js_west1 = jsc + jshift; je_west1 = jec
6513  endif
6514  else
6515  inbr = ipos+1; jnbr = jpos
6516  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6517  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6518  pe_west1 = domain%pearray(inbr,jnbr)
6519  is_west1 = iec + ishift; ie_west1 = is_west1
6520  js_west1 = jsc + jshift; je_west1 = jec + jshift
6521  endif
6522  endif
6523  endif
6524  !--- send to the southwest processor when position is NORTH
6525  if( position == corner ) then
6526  inbr = ipos + 1; jnbr = jpos + 1
6527  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6528  if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6529  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6530  pe_west2 = domain%pearray(inbr,jnbr)
6531  is_west2 = iec + ishift; ie_west2 = is_west2
6532  js_west2 = jec + jshift; je_west2 = js_west2
6533  endif
6534  endif
6535 
6536  do list = 0,nlist-1
6537  m = mod( domain%pos+list, nlist )
6538  count = 0
6539  my_pe = domain%list(m)%pe
6540  if(my_pe == pe_south1) then
6541  count = count + 1
6542  is(count) = is_south1; ie(count) = ie_south1
6543  js(count) = js_south1; je(count) = je_south1
6544  dir(count) = 2
6545  rotation(count) = zero
6546  endif
6547  if(my_pe == pe_south2) then
6548  count = count + 1
6549  is(count) = is_south2; ie(count) = ie_south2
6550  js(count) = js_south2; je(count) = je_south2
6551  dir(count) = 2
6552  rotation(count) = zero
6553  endif
6554 
6555  if(my_pe == pe_west0) then
6556  count = count + 1
6557  is(count) = is_west0; ie(count) = ie_west0
6558  js(count) = js_west0; je(count) = je_west0
6559  dir(count) = 3
6560  rotation(count) = one_hundred_eighty
6561  endif
6562  if(my_pe == pe_west1) then
6563  count = count + 1
6564  is(count) = is_west1; ie(count) = ie_west1
6565  js(count) = js_west1; je(count) = je_west1
6566  dir(count) = 3
6567  rotation(count) = zero
6568  endif
6569  if(my_pe == pe_west2) then
6570  count = count + 1
6571  is(count) = is_west2; ie(count) = ie_west2
6572  js(count) = js_west2; je(count) = je_west2
6573  dir(count) = 3
6574  rotation(count) = zero
6575  endif
6576 
6577  if(count >0) then
6578  nsend = nsend + 1
6579  if(nsend > nlist_send) call mpp_error(fatal, "set_bound_overlap: nsend > nlist_send")
6580  bound%send(nsend)%count = count
6581  bound%send(nsend)%pe = my_pe
6582  if (associated(bound%send(nsend)%is)) deallocate(bound%send(nsend)%is) !< Check if allocated
6583  if (associated(bound%send(nsend)%ie)) deallocate(bound%send(nsend)%ie) !< Check if allocated
6584  if (associated(bound%send(nsend)%js)) deallocate(bound%send(nsend)%js) !< Check if allocated
6585  if (associated(bound%send(nsend)%je)) deallocate(bound%send(nsend)%je) !< Check if allocated
6586  if (associated(bound%send(nsend)%dir)) deallocate(bound%send(nsend)%dir) !< Check if allocated
6587  if (associated(bound%send(nsend)%rotation)) deallocate(bound%send(nsend)%rotation) !< Check if allocated
6588  if (associated(bound%send(nsend)%tileMe)) deallocate(bound%send(nsend)%tileMe) !< Check if allocated
6589  allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6590  allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6591  allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6592  allocate(bound%send(nsend)%tileMe(count))
6593  bound%send(nsend)%is(:) = is(1:count)
6594  bound%send(nsend)%ie(:) = ie(1:count)
6595  bound%send(nsend)%js(:) = js(1:count)
6596  bound%send(nsend)%je(:) = je(1:count)
6597  bound%send(nsend)%dir(:) = dir(1:count)
6598  bound%send(nsend)%tileMe(:) = 1
6599  bound%send(nsend)%rotation(:) = rotation(1:count)
6600  endif
6601  enddo
6602  else
6603  !--- The following did not consider wide halo case.
6604  do m = 1, update%nsend
6605  overlap => update%send(m)
6606  if( overlap%count == 0 ) cycle
6607  count = 0
6608  do n = 1, overlap%count
6609  !--- currently not support folded-north
6610  if( overlap%rotation(n) == one_hundred_eighty ) cycle
6611  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 1) then ! east
6612  count=count+1
6613  dir(count) = 1
6614  rotation(count) = overlap%rotation(n)
6615  tileme(count) = overlap%tileMe(n)
6616  select case( rotation(count) )
6617  case( zero ) ! W -> E
6618  is(count) = overlap%is(n) - 1
6619  ie(count) = is(count)
6620  js(count) = overlap%js(n)
6621  je(count) = overlap%je(n)
6622  case( ninety ) ! S -> E
6623  is(count) = overlap%is(n)
6624  ie(count) = overlap%ie(n)
6625  js(count) = overlap%js(n) - 1
6626  je(count) = js(count)
6627  end select
6628  end if
6629  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 3 ) then ! south
6630  count=count+1
6631  dir(count) = 2
6632  rotation(count) = overlap%rotation(n)
6633  tileme(count) = overlap%tileMe(n)
6634  select case( rotation(count) )
6635  case( zero ) ! N->S
6636  is(count) = overlap%is(n)
6637  ie(count) = overlap%ie(n)
6638  js(count) = overlap%je(n) + 1
6639  je(count) = js(count)
6640  case( minus_ninety ) ! E->S
6641  is(count) = overlap%ie(n) + 1
6642  ie(count) = is(count)
6643  js(count) = overlap%js(n)
6644  je(count) = overlap%je(n)
6645  end select
6646  end if
6647  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 5 ) then ! west
6648  count=count+1
6649  dir(count) = 3
6650  rotation(count) = overlap%rotation(n)
6651  tileme(count) = overlap%tileMe(n)
6652  select case( rotation(count) )
6653  case( zero ) ! E->W
6654  is(count) = overlap%ie(n) + 1
6655  ie(count) = is(count)
6656  js(count) = overlap%js(n)
6657  je(count) = overlap%je(n)
6658  case( ninety ) ! N->W
6659  is(count) = overlap%is(n)
6660  ie(count) = overlap%ie(n)
6661  js(count) = overlap%je(n) + 1
6662  je(count) = js(count)
6663  end select
6664  end if
6665  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 7 ) then ! north
6666  count=count+1
6667  dir(count) = 4
6668  rotation(count) = overlap%rotation(n)
6669  tileme(count) = overlap%tileMe(n)
6670  select case( rotation(count) )
6671  case( zero ) ! S->N
6672  is(count) = overlap%is(n)
6673  ie(count) = overlap%ie(n)
6674  js(count) = overlap%js(n) - 1
6675  je(count) = js(count)
6676  case( minus_ninety ) ! W->N
6677  is(count) = overlap%is(n) - 1
6678  ie(count) = is(count)
6679  js(count) = overlap%js(n)
6680  je(count) = overlap%je(n)
6681  end select
6682  end if
6683  end do ! do n =1, overlap%count
6684  if(count>0) then
6685  nsend = nsend + 1
6686  bound%send(nsend)%count = count
6687  bound%send(nsend)%pe = overlap%pe
6688  if (associated(bound%send(nsend)%is)) deallocate(bound%send(nsend)%is) !< Check if allocated
6689  if (associated(bound%send(nsend)%ie)) deallocate(bound%send(nsend)%ie) !< Check if allocated
6690  if (associated(bound%send(nsend)%js)) deallocate(bound%send(nsend)%js) !< Check if allocated
6691  if (associated(bound%send(nsend)%je)) deallocate(bound%send(nsend)%je) !< Check if allocated
6692  if (associated(bound%send(nsend)%dir)) deallocate(bound%send(nsend)%dir) !< Check if allocated
6693  if (associated(bound%send(nsend)%rotation)) deallocate(bound%send(nsend)%rotation) !< Check if allocated
6694  if (associated(bound%send(nsend)%tileMe)) deallocate(bound%send(nsend)%tileMe) !< Check if allocated
6695  allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6696  allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6697  allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6698  allocate(bound%send(nsend)%tileMe(count))
6699  bound%send(nsend)%is(:) = is(1:count)
6700  bound%send(nsend)%ie(:) = ie(1:count)
6701  bound%send(nsend)%js(:) = js(1:count)
6702  bound%send(nsend)%je(:) = je(1:count)
6703  bound%send(nsend)%dir(:) = dir(1:count)
6704  bound%send(nsend)%tileMe(:) = tileme(1:count)
6705  bound%send(nsend)%rotation(:) = rotation(1:count)
6706  end if
6707  end do ! end do list = 0, nlist
6708  endif
6709 
6710  !--- loop over the list of domains to find the boundary overlap for recv
6711  bound%nsend = nsend
6712  nrecvl(:,:) = 0
6713  nrecv = 0
6714 
6715  !--- will computing overlap for tripolar grid.
6716  if( domain%ntiles == 1 ) then
6717  ! currently only set up for west and south boundary
6718 
6719  ! south boundary for recv
6720  pe_south1 = null_pe; pe_south2 = null_pe
6721  if( position == north .OR. position == corner ) then
6722  inbr = ipos; jnbr = jpos - 1
6723  if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6724  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6725  pe_south1 = domain%pearray(inbr,jnbr)
6726  is_south1 = isc + ishift; ie_south1 = iec+ishift
6727  js_south1 = jsc; je_south1 = js_south1
6728  endif
6729  endif
6730 
6731  !--- south boudary for recv: the southwest point when position is NORTH
6732  if( position == corner ) then
6733  inbr = ipos - 1; jnbr = jpos - 1
6734  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6735  if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6736  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6737  pe_south2 = domain%pearray(inbr,jnbr)
6738  is_south2 = isc; ie_south2 = is_south2
6739  js_south2 = jsc; je_south2 = js_south2
6740  endif
6741  endif
6742 
6743 
6744  !---west boundary for recv
6745  pe_west0 = null_pe; pe_west1 = null_pe; pe_west2 = null_pe
6746  if( position == east ) then
6747  inbr = ipos-1; jnbr = jpos
6748  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6749  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6750  pe_west1 = domain%pearray(inbr,jnbr)
6751  is_west1 = isc; ie_west1 = is_west1
6752  js_west1 = jsc + jshift; je_west1 = jec + jshift
6753  endif
6754  else if ( position == corner ) then ! possible split into two parts.
6755  !--- on the fold.
6756  if( folded_north .AND. jec == jeg .AND. ipos .GT. npes_x/2 ) then
6757  inbr = npes_x - ipos - 1; jnbr = jpos
6758  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6759  pe_west0 = domain%pearray(inbr,jnbr)
6760  is_west0 = isc; ie_west0 = is_west0
6761  js_west0 = jec+jshift; je_west0 = js_west0
6762  endif
6763  inbr = ipos-1; jnbr = jpos
6764  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6765  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6766  pe_west1 = domain%pearray(inbr,jnbr)
6767  is_west1 = isc; ie_west1 = is_west1
6768  js_west1 = jsc + jshift; je_west1 = jec
6769  endif
6770  else
6771  inbr = ipos-1; jnbr = jpos
6772  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6773  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6774  pe_west1 = domain%pearray(inbr,jnbr)
6775  is_west1 = isc; ie_west1 = is_west1
6776  js_west1 = jsc + jshift; je_west1 = jec+jshift
6777  endif
6778  endif
6779  endif
6780 
6781  !--- west boundary for recv: the southwest point when position is CORNER
6782  if( position == corner ) then
6783  inbr = ipos - 1; jnbr = jpos - 1
6784  if( inbr == -1 .AND. x_cyclic) inbr = npes_x - 1
6785  if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y - 1
6786  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6787  pe_west2 = domain%pearray(inbr,jnbr)
6788  is_west2 = isc; ie_west2 = is_west2
6789  js_west2 = jsc; je_west2 = js_west2
6790  endif
6791  endif
6792 
6793  tme = 1
6794  do list = 0,nlist-1
6795  m = mod( domain%pos+nlist-list, nlist )
6796  count = 0
6797  my_pe = domain%list(m)%pe
6798  if(my_pe == pe_south1) then
6799  count = count + 1
6800  is(count) = is_south1; ie(count) = ie_south1
6801  js(count) = js_south1; je(count) = je_south1
6802  dir(count) = 2
6803  rotation(count) = zero
6804  index(count) = 1 + ishift
6805  endif
6806  if(my_pe == pe_south2) then
6807  count = count + 1
6808  is(count) = is_south2; ie(count) = ie_south2
6809  js(count) = js_south2; je(count) = je_south2
6810  dir(count) = 2
6811  rotation(count) = zero
6812  index(count) = 1
6813  endif
6814  if(my_pe == pe_west0) then
6815  count = count + 1
6816  is(count) = is_west0; ie(count) = ie_west0
6817  js(count) = js_west0; je(count) = je_west0
6818  dir(count) = 3
6819  rotation(count) = one_hundred_eighty
6820  index(count) = jec-jsc+1+jshift
6821  endif
6822  if(my_pe == pe_west1) then
6823  count = count + 1
6824  is(count) = is_west1; ie(count) = ie_west1
6825  js(count) = js_west1; je(count) = je_west1
6826  dir(count) = 3
6827  rotation(count) = zero
6828  index(count) = 1 + jshift
6829  endif
6830  if(my_pe == pe_west2) then
6831  count = count + 1
6832  is(count) = is_west2; ie(count) = ie_west2
6833  js(count) = js_west2; je(count) = je_west2
6834  dir(count) = 3
6835  rotation(count) = zero
6836  index(count) = 1
6837  endif
6838 
6839  if(count >0) then
6840  nrecv = nrecv + 1
6841  if(nrecv > nlist_recv) call mpp_error(fatal, "set_bound_overlap: nrecv > nlist_recv")
6842  bound%recv(nrecv)%count = count
6843  bound%recv(nrecv)%pe = my_pe
6844  if (associated(bound%recv(nrecv)%is)) deallocate(bound%recv(nrecv)%is) !< Check if allocated
6845  if (associated(bound%recv(nrecv)%ie)) deallocate(bound%recv(nrecv)%ie) !< Check if allocated
6846  if (associated(bound%recv(nrecv)%js)) deallocate(bound%recv(nrecv)%js) !< Check if allocated
6847  if (associated(bound%recv(nrecv)%je)) deallocate(bound%recv(nrecv)%je) !< Check if allocated
6848  if (associated(bound%recv(nrecv)%dir)) deallocate(bound%recv(nrecv)%dir) !< Check if allocated
6849  if (associated(bound%recv(nrecv)%index)) deallocate(bound%recv(nrecv)%index) !< Check if allocated
6850  if (associated(bound%recv(nrecv)%tileMe)) deallocate(bound%recv(nrecv)%tileMe) !< Check if allocated
6851  if (associated(bound%recv(nrecv)%rotation)) deallocate(bound%recv(nrecv)%rotation) !< Check if allocated
6852  allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6853  allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6854  allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6855  allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6856 
6857  bound%recv(nrecv)%is(:) = is(1:count)
6858  bound%recv(nrecv)%ie(:) = ie(1:count)
6859  bound%recv(nrecv)%js(:) = js(1:count)
6860  bound%recv(nrecv)%je(:) = je(1:count)
6861  bound%recv(nrecv)%dir(:) = dir(1:count)
6862  bound%recv(nrecv)%tileMe(:) = 1
6863  bound%recv(nrecv)%rotation(:) = rotation(1:count)
6864  bound%recv(nrecv)%index(:) = index(1:count)
6865  endif
6866  enddo
6867  else
6868  do m = 1, update%nrecv
6869  overlap => update%recv(m)
6870  if( overlap%count == 0 ) cycle
6871  count = 0
6872  do n = 1, overlap%count
6873  !--- currently not support folded-north
6874  if( overlap%rotation(n) == one_hundred_eighty ) cycle
6875  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 1) then ! east
6876  count=count+1
6877  dir(count) = 1
6878  rotation(count) = overlap%rotation(n)
6879  tileme(count) = overlap%tileMe(n)
6880  is(count) = overlap%is(n) - 1
6881  ie(count) = is(count)
6882  js(count) = overlap%js(n)
6883  je(count) = overlap%je(n)
6884  tme = tileme(count)
6885  nrecvl(tme, 1) = nrecvl(tme,1) + 1
6886  isl(tme,1,nrecvl(tme, 1)) = is(count)
6887  iel(tme,1,nrecvl(tme, 1)) = ie(count)
6888  jsl(tme,1,nrecvl(tme, 1)) = js(count)
6889  jel(tme,1,nrecvl(tme, 1)) = je(count)
6890  end if
6891 
6892  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 3) then ! south
6893  count=count+1
6894  dir(count) = 2
6895  rotation(count) = overlap%rotation(n)
6896  tileme(count) = overlap%tileMe(n)
6897  is(count) = overlap%is(n)
6898  ie(count) = overlap%ie(n)
6899  js(count) = overlap%je(n) + 1
6900  je(count) = js(count)
6901  tme = tileme(count)
6902  nrecvl(tme, 2) = nrecvl(tme,2) + 1
6903  isl(tme,2,nrecvl(tme, 2)) = is(count)
6904  iel(tme,2,nrecvl(tme, 2)) = ie(count)
6905  jsl(tme,2,nrecvl(tme, 2)) = js(count)
6906  jel(tme,2,nrecvl(tme, 2)) = je(count)
6907  end if
6908 
6909  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 5) then ! west
6910  count=count+1
6911  dir(count) = 3
6912  rotation(count) = overlap%rotation(n)
6913  tileme(count) = overlap%tileMe(n)
6914  is(count) = overlap%ie(n) + 1
6915  ie(count) = is(count)
6916  js(count) = overlap%js(n)
6917  je(count) = overlap%je(n)
6918  tme = tileme(count)
6919  nrecvl(tme, 3) = nrecvl(tme,3) + 1
6920  isl(tme,3,nrecvl(tme, 3)) = is(count)
6921  iel(tme,3,nrecvl(tme, 3)) = ie(count)
6922  jsl(tme,3,nrecvl(tme, 3)) = js(count)
6923  jel(tme,3,nrecvl(tme, 3)) = je(count)
6924  end if
6925 
6926  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 7) then ! north
6927  count=count+1
6928  dir(count) = 4
6929  rotation(count) = overlap%rotation(n)
6930  tileme(count) = overlap%tileMe(n)
6931  is(count) = overlap%is(n)
6932  ie(count) = overlap%ie(n)
6933  js(count) = overlap%js(n) - 1
6934  je(count) = js(count)
6935  tme = tileme(count)
6936  nrecvl(tme, 4) = nrecvl(tme,4) + 1
6937  isl(tme,4,nrecvl(tme, 4)) = is(count)
6938  iel(tme,4,nrecvl(tme, 4)) = ie(count)
6939  jsl(tme,4,nrecvl(tme, 4)) = js(count)
6940  jel(tme,4,nrecvl(tme, 4)) = je(count)
6941  end if
6942  end do ! do n = 1, overlap%count
6943  if(count>0) then
6944  nrecv = nrecv + 1
6945  bound%recv(nrecv)%count = count
6946  bound%recv(nrecv)%pe = overlap%pe
6947  if (associated(bound%recv(nrecv)%is)) deallocate(bound%recv(nrecv)%is) !< Check if allocated
6948  if (associated(bound%recv(nrecv)%ie)) deallocate(bound%recv(nrecv)%ie) !< Check if allocated
6949  if (associated(bound%recv(nrecv)%js)) deallocate(bound%recv(nrecv)%js) !< Check if allocated
6950  if (associated(bound%recv(nrecv)%je)) deallocate(bound%recv(nrecv)%je) !< Check if allocated
6951  if (associated(bound%recv(nrecv)%dir)) deallocate(bound%recv(nrecv)%dir) !< Check if allocated
6952  if (associated(bound%recv(nrecv)%index)) deallocate(bound%recv(nrecv)%index) !< Check if allocated
6953  if (associated(bound%recv(nrecv)%tileMe)) deallocate(bound%recv(nrecv)%tileMe) !< Check if allocated
6954  if (associated(bound%recv(nrecv)%rotation)) deallocate(bound%recv(nrecv)%rotation) !< Check if allocated
6955  allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6956  allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6957  allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6958  allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6959  bound%recv(nrecv)%is(:) = is(1:count)
6960  bound%recv(nrecv)%ie(:) = ie(1:count)
6961  bound%recv(nrecv)%js(:) = js(1:count)
6962  bound%recv(nrecv)%je(:) = je(1:count)
6963  bound%recv(nrecv)%dir(:) = dir(1:count)
6964  bound%recv(nrecv)%tileMe(:) = tileme(1:count)
6965  bound%recv(nrecv)%rotation(:) = rotation(1:count)
6966  end if
6967  end do ! end do list = 0, nlist
6968  !--- find the boundary index for each contact within the east boundary
6969  do m = 1, nrecv
6970  do n = 1, bound%recv(m)%count
6971  tme = bound%recv(m)%tileMe(n)
6972  dr = bound%recv(m)%dir(n)
6973  bound%recv(m)%index(n) = 1
6974  do l = 1, nrecvl(tme,dr)
6975  if(dr == 1 .OR. dr == 3) then ! EAST, WEST
6976  if( bound%recv(m)%js(n) > jsl(tme, dr, l) ) then
6977  if( bound%recv(m)%rotation(n) == one_hundred_eighty ) then
6978  bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6979  max(abs(jel(tme, dr, l)-jsl(tme, dr, l))+1, &
6980  abs(iel(tme, dr, l)-isl(tme, dr, l))+1)
6981  else
6982  bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6983  max(abs(jel(tme, dr, l)-jsl(tme, dr, l)), &
6984  abs(iel(tme, dr, l)-isl(tme, dr, l))) + 1 - jshift
6985  endif
6986  end if
6987  else ! South, North
6988  if( bound%recv(m)%is(n) > isl(tme, dr, l) ) then
6989  bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6990  max(abs(jel(tme, dr, l)-jsl(tme, dr, l)), &
6991  abs(iel(tme, dr, l)-isl(tme, dr, l))) + 1 - ishift
6992  end if
6993  end if
6994  end do
6995  end do
6996  end do
6997 
6998  endif
6999  bound%nrecv = nrecv
7000 
7001 
7002 end subroutine set_bound_overlap
7003 
7004 
7005 !#############################################################################
7006 
7007 subroutine fill_corner_contact(eCont, sCont, wCont, nCont, isg, ieg, jsg, jeg, numR, numS, tileRecv, tileSend, &
7008  is1Recv, ie1Recv, js1Recv, je1Recv, is2Recv, ie2Recv, js2Recv, je2Recv, &
7009  is1Send, ie1Send, js1Send, je1Send, is2Send, ie2Send, js2Send, je2Send, &
7010  align1Recv, align2Recv, align1Send, align2Send, &
7011  whalo, ehalo, shalo, nhalo, tileMe)
7012 type(contact_type), dimension(:), intent(in) :: eCont, sCont, wCont, nCont
7013 integer, dimension(:), intent(in) :: isg, ieg, jsg, jeg
7014 integer, intent(inout) :: numR, numS
7015 integer, dimension(:), intent(inout) :: tileRecv, tileSend
7016 integer, dimension(:), intent(inout) :: is1Recv, ie1Recv, js1Recv, je1Recv
7017 integer, dimension(:), intent(inout) :: is2Recv, ie2Recv, js2Recv, je2Recv
7018 integer, dimension(:), intent(inout) :: is1Send, ie1Send, js1Send, je1Send
7019 integer, dimension(:), intent(inout) :: is2Send, ie2Send, js2Send, je2Send
7020 integer, dimension(:), intent(inout) :: align1Recv, align2Recv, align1Send, align2Send
7021 integer, intent(in) :: tileMe, whalo, ehalo, shalo, nhalo
7022 integer :: is1, ie1, js1, je1, is2, ie2, js2, je2
7023 integer :: tn, tc, n, m
7024 logical :: found_corner
7025 
7026 found_corner = .false.
7027 !--- southeast for recving
7028 if(econt(tileme)%ncontact > 0) then
7029  if(econt(tileme)%js1(1) == jsg(tileme) ) then
7030  tn = econt(tileme)%tile(1)
7031  if(econt(tileme)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7032  if( econt(tileme)%js2(1) - jsg(tn) < shalo ) call mpp_error(fatal, &
7033  "mpp_domains_define.inc: southeast tile for recv 1 is not tiled properly")
7034  found_corner = .true.; tc = tn
7035  is1 = econt(tileme)%ie1(1) + 1; je1 = econt(tileme)%js1(1) - 1
7036  is2 = econt(tileme)%is2(1); je2 = econt(tileme)%js2(1) - 1
7037  else if(scont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7038  if(scont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7039  found_corner = .true.; tc = scont(tn)%tile(1)
7040  is1 = econt(tileme)%ie1(1) + 1; je1 = econt(tileme)%js1(1) - 1
7041  is2 = scont(tn)%is2(1); je2 = scont(tn)%je2(1)
7042  end if
7043  end if
7044  end if
7045 end if
7046 if( .not. found_corner ) then ! not found,
7047  n = scont(tileme)%ncontact
7048  if( n > 0) then
7049  if( scont(tileme)%ie1(n) == ieg(tileme)) then
7050  tn = scont(tileme)%tile(n)
7051  if(scont(tileme)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7052  if(ieg(tn) - scont(tileme)%ie2(n) < ehalo ) call mpp_error(fatal, &
7053  "mpp_domains_define.inc: southeast tile for recv 2 is not tiled properly")
7054  found_corner = .true.; tc = tn
7055  is1 = scont(tileme)%ie1(n) + 1; je1 = scont(tileme)%js1(n) - 1
7056  is2 = scont(tileme)%ie2(n) + 1; je2 = scont(tileme)%je2(n)
7057  else if(econt(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7058  m = econt(tn)%ncontact
7059  if(econt(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7060  found_corner = .true.; tc = econt(tn)%tile(m)
7061  is1 = scont(tileme)%ie1(n) + 1; je1 = scont(tileme)%js1(n) - 1
7062  is2 = econt(tn)%is2(m); je2 = econt(tn)%je2(m)
7063  end if
7064  end if
7065  end if
7066  end if
7067 end if
7068 if(found_corner) then
7069  numr = numr + 1
7070  tilerecv(numr) = tc; align1recv(numr) = south_east; align2recv(numr) = north_west
7071  is1recv(numr) = is1; ie1recv(numr) = is1 + ehalo - 1
7072  js1recv(numr) = je1 - shalo + 1; je1recv(numr) = je1
7073  is2recv(numr) = is2; ie2recv(numr) = is2 + ehalo - 1
7074  js2recv(numr) = je2 - shalo + 1; je2recv(numr) = je2
7075 end if
7076 
7077 !--- southwest for recving
7078 found_corner = .false.
7079 if(wcont(tileme)%ncontact > 0) then
7080  if(wcont(tileme)%js1(1) == jsg(tileme) ) then
7081  tn = wcont(tileme)%tile(1)
7082  if(wcont(tileme)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7083  if( wcont(tileme)%js2(1) - jsg(tn) < shalo ) call mpp_error(fatal, &
7084  "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7085  found_corner = .true.; tc = tn
7086  ie1 = wcont(tileme)%is1(1) - 1; je1 = wcont(tileme)%js1(1) - 1
7087  ie2 = wcont(tileme)%is2(1); je2 = wcont(tileme)%js2(1) - 1
7088  else if(scont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7089  n = scont(tn)%ncontact
7090  if(scont(tn)%ie1(n) == ieg(tn)) then ! corner is nc.
7091  found_corner = .true.; tc = scont(tn)%tile(n)
7092  ie1 = wcont(tileme)%is1(1) - 1; je1 = wcont(tileme)%js1(1) - 1
7093  ie2 = scont(tn)%ie2(1); je2 = scont(tn)%je2(1)
7094  end if
7095  end if
7096  end if
7097 end if
7098 if( .not. found_corner ) then ! not found,
7099  n = scont(tileme)%ncontact
7100  if( n > 0) then
7101  if( scont(tileme)%is1(1) == isg(tileme)) then
7102  tn = scont(tileme)%tile(1)
7103  if(scont(tileme)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7104  if( scont(tileme)%is2(1)-isg(tn) < whalo ) call mpp_error(fatal, &
7105  "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7106  found_corner = .true.; tc = tn
7107  ie1 = scont(tileme)%is1(1) - 1; je1 = scont(tileme)%js1(1) - 1
7108  ie2 = scont(tileme)%is2(1) - 1; je2 = scont(tileme)%js2(1)
7109  else if(wcont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7110  m = wcont(tn)%ncontact
7111  if(wcont(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7112  found_corner = .true.; tc = wcont(tn)%tile(m)
7113  ie1 = scont(tileme)%is1(1) - 1; je1 = scont(tileme)%js1(1) - 1
7114  ie2 = wcont(tn)%ie2(m); je2 = wcont(tn)%je2(m)
7115  end if
7116  end if
7117  end if
7118  end if
7119 end if
7120 if(found_corner) then
7121  numr = numr + 1
7122  tilerecv(numr) = tc; align1recv(numr) = south_west; align2recv(numr) = north_east
7123  is1recv(numr) = ie1 - whalo + 1; ie1recv(numr) = ie1
7124  js1recv(numr) = je1 - shalo + 1; je1recv(numr) = je1
7125  is2recv(numr) = ie2 - whalo + 1; ie2recv(numr) = ie2
7126  js2recv(numr) = je2 - shalo + 1; je2recv(numr) = je2
7127 end if
7128 
7129 !--- northwest for recving
7130 found_corner = .false.
7131 n = wcont(tileme)%ncontact
7132 if( n > 0) then
7133  if(wcont(tileme)%je1(n) == jeg(tileme) ) then
7134  tn = wcont(tileme)%tile(n)
7135  if(wcont(tileme)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7136  if( jeg(tn) - wcont(tileme)%je2(n) < nhalo ) call mpp_error(fatal, &
7137  "mpp_domains_define.inc: northwest tile for recv 1 is not tiled properly")
7138  found_corner = .true.; tc = tn
7139  ie1 = wcont(tileme)%is1(n) - 1; js1 = wcont(tileme)%je1(n) + 1
7140  ie2 = wcont(tileme)%is2(n); js2 = wcont(tileme)%je2(n) + 1
7141  else if(ncont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7142  m = ncont(tn)%ncontact
7143  if(ncont(tn)%ie1(m) == ieg(tn)) then ! corner is nc.
7144  found_corner = .true.; tc = ncont(tn)%tile(m)
7145  ie1 = wcont(tileme)%is1(n) - 1; js1 = wcont(tileme)%je1(n) + 1
7146  ie2 = ncont(tn)%ie2(m); js2 = ncont(tn)%js2(m)
7147  end if
7148  endif
7149  endif
7150 end if
7151 if( .not. found_corner ) then ! not found,
7152  if( ncont(tileme)%ncontact > 0) then
7153  if( ncont(tileme)%is1(1) == isg(tileme)) then
7154  tn = ncont(tileme)%tile(1)
7155  if(ncont(tileme)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7156  if( ncont(tileme)%is2(1)-isg(tn) < whalo ) call mpp_error(fatal, &
7157  "mpp_domains_define.inc: northwest tile for recv 2 is not tiled properly")
7158  found_corner = .true.; tc = tn
7159  ie1 = ncont(tileme)%is1(1) - 1; js1 = ncont(tileme)%je1(1) + 1
7160  ie2 = ncont(tileme)%is2(1) - 1; js2 = ncont(tileme)%js2(1)
7161  else if(wcont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7162  if(wcont(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7163  found_corner = .true.; tc = wcont(tn)%tile(1)
7164  ie1 = ncont(tileme)%is1(1) - 1; js1 = ncont(tileme)%je1(1) + 1
7165  ie2 = wcont(tn)%ie2(1); js2 = wcont(tn)%js2(1)
7166  end if
7167  end if
7168  end if
7169  end if
7170 end if
7171 if(found_corner) then
7172  numr = numr + 1
7173  tilerecv(numr) = tc; align1recv(numr) =north_west; align2recv(numr) = south_east
7174  is1recv(numr) = ie1 - whalo + 1; ie1recv(numr) = ie1
7175  js1recv(numr) = js1; je1recv(numr) = js1 + nhalo - 1
7176  is2recv(numr) = ie2 - whalo + 1; ie2recv(numr) = ie2
7177  js2recv(numr) = js2; je2recv(numr) = js2 + nhalo - 1
7178 end if
7179 
7180 !--- northeast for recving
7181 found_corner = .false.
7182 n = econt(tileme)%ncontact
7183 if( n > 0) then
7184  if(econt(tileme)%je1(n) == jeg(tileme) ) then
7185  tn = econt(tileme)%tile(n)
7186  if(econt(tileme)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7187  if( jeg(tn) - econt(tileme)%je2(n) < nhalo ) call mpp_error(fatal, &
7188  "mpp_domains_define.inc: northeast tile for recv 1 is not tiled properly")
7189  found_corner = .true.; tc = tn
7190  is1 = econt(tileme)%ie1(n) + 1; js1 = econt(tileme)%je1(n) + 1
7191  is2 = econt(tileme)%is2(1); js2 = econt(tileme)%je2(1) + 1
7192  else if(ncont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7193  if(ncont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7194  found_corner = .true.; tc = ncont(tn)%tile(1)
7195  is1 = econt(tileme)%ie1(n) + 1; js1 = econt(tileme)%je1(n) + 1
7196  is2 = ncont(tn)%is2(1); js2 = ncont(tn)%js2(1)
7197  end if
7198  end if
7199  end if
7200 end if
7201 if( .not. found_corner ) then ! not found,
7202  n = ncont(tileme)%ncontact
7203  if( n > 0) then
7204  if( ncont(tileme)%ie1(n) == ieg(tileme)) then
7205  tn = ncont(tileme)%tile(n)
7206  if(ncont(tileme)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7207  if(ieg(tn) - scont(tileme)%ie2(n) < ehalo ) call mpp_error(fatal, &
7208  "mpp_domains_define.inc: northeast tile for recv 2 is not tiled properly")
7209  found_corner = .true.; tc = tn
7210  is1 = scont(tileme)%ie1(n) + 1; js1 = scont(tileme)%je1(n) + 1
7211  is2 = scont(tileme)%ie2(n) + 1; js2 = scont(tileme)%js2(n)
7212  else if(econt(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7213  if(econt(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7214  found_corner = .true.; tc = econt(tn)%tile(1)
7215  is1 = scont(tileme)%ie1(n) + 1; js1 = scont(tileme)%je1(n) + 1
7216  is2 = econt(tn)%is2(m); js2 = econt(tn)%js2(m)
7217  end if
7218  end if
7219  end if
7220  end if
7221 end if
7222 if(found_corner) then
7223  numr = numr + 1
7224  tilerecv(numr) = tc; align1recv(numr) =north_east; align2recv(numr) = south_west
7225  is1recv(numr) = is1; ie1recv(numr) = is1 + ehalo - 1
7226  js1recv(numr) = js1; je1recv(numr) = js1 + nhalo - 1
7227  is2recv(numr) = is2; ie2recv(numr) = is2 + ehalo - 1
7228  js2recv(numr) = js2; je2recv(numr) = js2 + nhalo - 1
7229 end if
7230 
7231 !--- to_pe's southeast for sending
7232 do n = 1, wcont(tileme)%ncontact
7233  tn = wcont(tileme)%tile(n)
7234  if(wcont(tileme)%js2(n) == jsg(tn) ) then
7235  if(wcont(tileme)%js1(n) > jsg(tileme) ) then ! send to tile tn.
7236  if( wcont(tileme)%js1(n) - jsg(tileme) < shalo ) call mpp_error(fatal, &
7237  "mpp_domains_define.inc: southeast tile for send 1 is not tiled properly")
7238  nums = nums+1; tilesend(nums) = tn
7239  align1send(nums) = north_west; align2send(nums) = south_east
7240  is1send(nums) = wcont(tileme)%is1(n); ie1send(nums) = is1send(nums) + ehalo - 1
7241  je1send(nums) = wcont(tileme)%js1(n) - 1; js1send(nums) = je1send(nums) - shalo + 1
7242  is2send(nums) = wcont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7243  je2send(nums) = wcont(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7244  end if
7245  end if
7246 end do
7247 do n = 1, ncont(tileme)%ncontact
7248  tn = ncont(tileme)%tile(n)
7249  if(ncont(tileme)%ie2(n) == ieg(tn) ) then
7250  if(ncont(tileme)%ie1(n) < ieg(tileme) ) then ! send to tile tn.
7251  if( ieg(tileme) - ncont(tileme)%ie1(n) < ehalo ) call mpp_error(fatal, &
7252  "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7253  nums = nums+1; tilesend(nums) = tn
7254  align1send(nums) = north_west; align2send(nums) = south_east
7255  is1send(nums) = ncont(tileme)%ie1(n) + 1; ie1send(nums) = is1send(nums) + ehalo - 1
7256  je1send(nums) = ncont(tileme)%je1(n) ; js1send(nums) = je1send(nums) - shalo + 1
7257  is2send(nums) = ncont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7258  je2send(nums) = ncont(tileme)%je2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7259  end if
7260  end if
7261 end do
7262 
7263 !--- found the corner overlap that is not specified through contact line.
7264 n = wcont(tileme)%ncontact
7265 found_corner = .false.
7266 if( n > 0) then
7267  tn = wcont(tileme)%tile(n)
7268  if( wcont(tileme)%je1(n) == jeg(tileme) .AND. wcont(tileme)%je2(n) == jeg(tn) ) then
7269  m = ncont(tn)%ncontact
7270  if(m >0) then
7271  tc = ncont(tn)%tile(m)
7272  if( ncont(tn)%ie1(m) == ieg(tn) .AND. ncont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7273  end if
7274  end if
7275 end if
7276 if( .not. found_corner ) then ! not found, then starting from north contact
7277  if( ncont(tileme)%ncontact > 0) then
7278  tn = ncont(tileme)%tile(1)
7279  if( ncont(tileme)%is1(1) == isg(tileme) .AND. ncont(tileme)%is2(1) == isg(tn) ) then
7280  if(wcont(tn)%ncontact >0) then
7281  tc = wcont(tn)%tile(1)
7282  if( wcont(tn)%js1(1) == jsg(tn) .AND. wcont(tn)%js2(1) == jsg(tc) ) found_corner = .true.
7283  end if
7284  end if
7285  end if
7286 end if
7287 
7288 if(found_corner) then
7289  nums = nums+1; tilesend(nums) = tc
7290  align1send(nums) = north_west; align2send(nums) = south_east
7291  is1send(nums) = isg(tileme); ie1send(nums) = is1send(nums) + ehalo - 1
7292  je1send(nums) = jeg(tileme); js1send(nums) = je1send(nums) - shalo + 1
7293  is2send(nums) = ieg(tc) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7294  je2send(nums) = jsg(tc) - 1; js2send(nums) = je2send(nums) - shalo + 1
7295 end if
7296 
7297 !--- to_pe's southwest for sending
7298 do n = 1, econt(tileme)%ncontact
7299  tn = econt(tileme)%tile(n)
7300  if(econt(tileme)%js2(n) == jsg(tn) ) then
7301  if(econt(tileme)%js1(n) > jsg(tileme) ) then ! send to tile tn.
7302  if( econt(tileme)%js1(n) - jsg(tileme) < shalo ) call mpp_error(fatal, &
7303  "mpp_domains_define.inc: southwest tile for send 1 is not tiled properly")
7304  nums = nums+1; tilesend(nums) = tn
7305  align1send(nums) = north_east; align2send(nums) = south_west
7306  ie1send(nums) = econt(tileme)%ie1(n); is1send(nums) = ie1send(nums) - whalo + 1
7307  je1send(nums) = econt(tileme)%js1(n) - 1; js1send(nums) = je1send(nums) - shalo + 1
7308  ie2send(nums) = econt(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7309  je2send(nums) = econt(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7310  end if
7311  end if
7312 end do
7313 do n = 1, ncont(tileme)%ncontact
7314  tn = ncont(tileme)%tile(n)
7315  if(ncont(tileme)%is2(n) == isg(tn) ) then
7316  if(ncont(tileme)%is1(n) > isg(tileme) ) then ! send to tile tn.
7317  if( ncont(tileme)%is1(n) - isg(tileme) < whalo ) call mpp_error(fatal, &
7318  "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7319  nums = nums+1; tilesend(nums) = tn
7320  align1send(nums) = north_east; align2send(nums) = south_west
7321  ie1send(nums) = ncont(tileme)%is1(n) - 1; is1send(nums) = ie1send(nums) - whalo + 1
7322  ie1send(nums) = ncont(tileme)%je1(n) ; js1send(nums) = je1send(nums) - shalo + 1
7323  ie2send(nums) = ncont(tileme)%is2(n) - 1; is2send(nums) = je2send(nums) - whalo + 1
7324  je2send(nums) = ncont(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7325  end if
7326  end if
7327 end do
7328 
7329 !--- found the corner overlap that is not specified through contact line.
7330 n = econt(tileme)%ncontact
7331 found_corner = .false.
7332 if( n > 0) then
7333  tn = econt(tileme)%tile(n)
7334  if( econt(tileme)%je1(n) == jeg(tileme) .AND. econt(tileme)%je2(n) == jeg(tn) ) then
7335  if(ncont(tn)%ncontact >0) then
7336  tc = ncont(tn)%tile(1)
7337  if( ncont(tn)%is1(1) == isg(tn) .AND. ncont(tn)%is2(n) == isg(tc) ) found_corner = .true.
7338  end if
7339  end if
7340 end if
7341 if( .not. found_corner ) then ! not found, then starting from north contact
7342  n = ncont(tileme)%ncontact
7343  if( n > 0) then
7344  tn = ncont(tileme)%tile(n)
7345  if( ncont(tileme)%ie1(n) == ieg(tileme) .AND. ncont(tileme)%ie2(n) == ieg(tn) ) then
7346  if(econt(tn)%ncontact >0) then
7347  tc = econt(tn)%tile(1)
7348  if( econt(tn)%js1(1) == jsg(tn) .AND. econt(tn)%js2(n) == jsg(tc) ) found_corner = .true.
7349  end if
7350  end if
7351  end if
7352 end if
7353 
7354 if(found_corner) then
7355  nums = nums+1; tilesend(nums) = tc
7356  align1send(nums) = north_east; align2send(nums) = south_west
7357  ie1send(nums) = ieg(tileme); is1send(nums) = ie1send(nums) - whalo + 1
7358  je1send(nums) = jeg(tileme); js1send(nums) = je1send(nums) - shalo + 1
7359  ie2send(nums) = isg(tc) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7360  je2send(nums) = jsg(tc) - 1; js2send(nums) = je2send(nums) - shalo + 1
7361 end if
7362 
7363 !--- to_pe's northwest for sending
7364 do n = 1, econt(tileme)%ncontact
7365  tn = econt(tileme)%tile(n)
7366  if(econt(tileme)%je2(n) == jeg(tn) ) then
7367  if(econt(tileme)%je1(n) < jeg(tileme) ) then ! send to tile tn.
7368  if( jeg(tileme) - econt(tileme)%je1(n) < nhalo ) call mpp_error(fatal, &
7369  "mpp_domains_define.inc: northwest tile for send 1 is not tiled properly")
7370  nums = nums+1; tilesend(nums) = tn
7371  align1send(nums) = south_east; align2send(nums) = north_west
7372  ie1send(nums) = econt(tileme)%ie1(n) ; is1send(nums) = ie1send(nums) - whalo + 1
7373  js1send(nums) = econt(tileme)%je1(n) + 1; je1send(nums) = js1send(nums) + nhalo - 1
7374  ie2send(nums) = econt(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7375  js2send(nums) = econt(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7376  end if
7377  end if
7378 end do
7379 
7380 do n = 1, scont(tileme)%ncontact
7381  tn = scont(tileme)%tile(n)
7382  if(scont(tileme)%is2(n) == isg(tn) ) then
7383  if(scont(tileme)%is1(n) > isg(tileme) ) then ! send to tile tn.
7384  if( scont(tileme)%is1(n) - isg(tileme) < whalo ) call mpp_error(fatal, &
7385  "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7386  nums = nums+1; tilesend(nums) = tn
7387  align1send(nums) = south_east; align2send(nums) = north_west
7388  ie1send(nums) = ncont(tileme)%is1(n) - 1; is1send(nums) = ie1send(nums) - whalo + 1
7389  js1send(nums) = ncont(tileme)%je1(n) ; je1send(nums) = js1send(nums) + nhalo - 1
7390  ie2send(nums) = ncont(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7391  js2send(nums) = ncont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7392  end if
7393  end if
7394 end do
7395 
7396 !--- found the corner overlap that is not specified through contact line.
7397 n = econt(tileme)%ncontact
7398 found_corner = .false.
7399 if( n > 0) then
7400  tn = econt(tileme)%tile(1)
7401  if( econt(tileme)%js1(1) == jsg(tileme) .AND. econt(tileme)%js2(1) == jsg(tn) ) then
7402  if(scont(tn)%ncontact >0) then
7403  tc = scont(tn)%tile(1)
7404  if( scont(tn)%is1(1) == isg(tn) .AND. scont(tn)%is2(1) == isg(tc) ) found_corner = .true.
7405  end if
7406  end if
7407 end if
7408 if( .not. found_corner ) then ! not found, then starting from north contact
7409  n = scont(tileme)%ncontact
7410  found_corner = .false.
7411  if( n > 0) then
7412  tn = scont(tileme)%tile(n)
7413  if( scont(tileme)%ie1(n) == ieg(tileme) .AND. scont(tileme)%ie2(n) == ieg(tn) ) then
7414  if(econt(tn)%ncontact >0) then
7415  tc = econt(tn)%tile(n)
7416  if( econt(tn)%je1(n) == jeg(tn) .AND. econt(tn)%je2(n) == jeg(tc) ) found_corner = .true.
7417  end if
7418  end if
7419  end if
7420 end if
7421 
7422 if(found_corner) then
7423  nums = nums+1; tilesend(nums) = tc
7424  align1send(nums) = south_east; align2send(nums) = north_west
7425  ie1send(nums) = ieg(tileme); is1send(nums) = ie1send(nums) - whalo + 1
7426  js1send(nums) = jsg(tileme); je1send(nums) = js1send(nums) + nhalo - 1
7427  ie2send(nums) = isg(tc) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7428  js2send(nums) = jeg(tc) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7429 end if
7430 
7431 !--- to_pe's northeast for sending
7432 do n = 1, wcont(tileme)%ncontact
7433  tn = wcont(tileme)%tile(n)
7434  if(wcont(tileme)%je2(n) == jeg(tn) ) then
7435  if(wcont(tileme)%je1(n) < jeg(tileme) ) then ! send to tile tn.
7436  if( jeg(tileme) - wcont(tileme)%je1(n) < nhalo ) call mpp_error(fatal, &
7437  "mpp_domains_define.inc: northeast tile for send 1 is not tiled properly")
7438  nums = nums+1; tilesend(nums) = tn
7439  align1send(nums) = south_west; align2send(nums) = north_east
7440  is1send(nums) = wcont(tileme)%is1(n) ; ie1send(nums) = is1send(nums) + ehalo - 1
7441  js1send(nums) = wcont(tileme)%je1(n) + 1; je1send(nums) = js1send(nums) + nhalo - 1
7442  is2send(nums) = wcont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7443  js2send(nums) = wcont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7444  end if
7445  end if
7446 end do
7447 
7448 do n = 1, scont(tileme)%ncontact
7449  tn = scont(tileme)%tile(n)
7450  if(scont(tileme)%ie2(n) == ieg(tn) ) then
7451  if(scont(tileme)%ie1(n) < ieg(tileme) ) then ! send to tile tn.
7452  if( ieg(tileme) - scont(tileme)%ie1(n) < ehalo ) call mpp_error(fatal, &
7453  "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7454  nums = nums+1; tilesend(nums) = tn
7455  align1send(nums) = south_west; align2send(nums) = north_east
7456  is1send(nums) = scont(tileme)%ie1(n) + 1; ie1send(nums) = is1send(nums) + ehalo - 1
7457  js1send(nums) = scont(tileme)%js1(n) ; je1send(nums) = js1send(nums) + nhalo - 1
7458  is2send(nums) = scont(tileme)%ie2(n) + 1; ie2send(nums) = is1send(nums) + ehalo - 1
7459  js2send(nums) = scont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7460  end if
7461  end if
7462 end do
7463 
7464 !--- found the corner overlap that is not specified through contact line.
7465 n = wcont(tileme)%ncontact
7466 found_corner = .false.
7467 if( n > 0) then
7468  tn = wcont(tileme)%tile(1)
7469  if( wcont(tileme)%js1(n) == jsg(tileme) .AND. wcont(tileme)%js2(n) == jsg(tn) ) then
7470  m = scont(tn)%ncontact
7471  if(m >0) then
7472  tc = scont(tn)%tile(m)
7473  if( scont(tn)%ie1(m) == ieg(tn) .AND. scont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7474  end if
7475  end if
7476 end if
7477 if( .not. found_corner ) then ! not found, then starting from north contact
7478  n = scont(tileme)%ncontact
7479  found_corner = .false.
7480  if( n > 0) then
7481  tn = scont(tileme)%tile(1)
7482  if( scont(tileme)%is1(1) == isg(tileme) .AND. scont(tileme)%is2(1) == isg(tn) ) then
7483  m = wcont(tn)%ncontact
7484  if( m > 0 ) then
7485  tc = wcont(tn)%tile(m)
7486  if( wcont(tn)%je1(m) == jeg(tn) .AND. wcont(tn)%je2(m) == jeg(tc) ) found_corner = .true.
7487  end if
7488  end if
7489  end if
7490 end if
7491 if(found_corner) then
7492  nums = nums+1; tilesend(nums) = tc
7493  align1send(nums) = south_west; align2send(nums) = north_east
7494  is1send(nums) = isg(tileme); ie1send(nums) = is1send(nums) + ehalo - 1
7495  js1send(nums) = jsg(tileme); je1send(nums) = js1send(nums) + nhalo - 1
7496  is2send(nums) = ieg(tc) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7497  js2send(nums) = jeg(tc) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7498 end if
7499 
7500 end subroutine fill_corner_contact
7501 
7502 !--- find the alignment direction, check if index is reversed, if reversed, exchange index.
7503 subroutine check_alignment( is, ie, js, je, isg, ieg, jsg, jeg, alignment )
7504 integer, intent(inout) :: is, ie, js, je, isg, ieg, jsg, jeg
7505 integer, intent(out) :: alignment
7506 
7507 integer :: i, j
7508 
7509 if ( is == ie ) then ! x-alignment
7510  if ( is == isg ) then
7511  alignment = west
7512  else if ( is == ieg ) then
7513  alignment = east
7514  else
7515  call mpp_error(fatal, 'mpp_domains_define.inc: The contact region is not on the x-boundary of the tile')
7516  end if
7517  if ( js > je ) then
7518  j = js; js = je; je = j
7519  end if
7520 else if ( js == je ) then ! y-alignment
7521  if ( js == jsg ) then
7522  alignment = south
7523  else if ( js == jeg ) then
7524  alignment = north
7525  else
7526  call mpp_error(fatal, 'mpp_domains_define.inc: The contact region is not on the y-boundary of the tile')
7527  end if
7528  if ( is > ie ) then
7529  i = is; is = ie; ie = i
7530  end if
7531 else
7532  call mpp_error(fatal, 'mpp_domains_define.inc: The contact region should be line contact' )
7533 end if
7534 
7535 end subroutine check_alignment
7536 !#####################################################################
7537 
7538 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7539 ! !
7540 ! MPP_MODIFY_DOMAIN: modify extent of domain !
7541 ! !
7542 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7543 
7544 !> @brief Modifies the exents of a domain
7545 subroutine mpp_modify_domain1d(domain_in,domain_out,cbegin,cend,gbegin,gend, hbegin, hend)
7546  ! </PUBLICROUTINE>
7547 type(domain1d), intent(in) :: domain_in !< The source domain.
7548 type(domain1d), intent(inout) :: domain_out !< The returned domain.
7549 integer, intent(in), optional :: hbegin, hend !< halo size
7550 integer, intent(in), optional :: cbegin, cend !< Axis specifications associated with the compute
7551  !! domain of the returned 1D domain.
7552 integer, intent(in), optional :: gbegin, gend !< Axis specifications associated with the global
7553  !! domain of the returned 1D domain.
7554 integer :: ndivs, global_indices(2) !(/ isg, ieg /)
7555 integer :: flag
7556 ! get the global indices of the input domain
7557 global_indices(1) = domain_in%global%begin; global_indices(2) = domain_in%global%end
7558 
7559 ! get the layout
7560 ndivs = size(domain_in%list(:))
7561 
7562 ! get the flag
7563 flag = 0
7564 if(domain_in%cyclic) flag = flag + cyclic_global_domain
7565 if(domain_in%domain_data%is_global) flag = flag + global_data_domain
7566 
7567 call mpp_define_domains( global_indices, ndivs, domain_out, pelist = domain_in%list(:)%pe, &
7568  flags = flag, begin_halo = hbegin, end_halo = hend, extent = domain_in%list(:)%compute%size )
7569 
7570 if(present(cbegin)) domain_out%compute%begin = cbegin
7571 if(present(cend)) domain_out%compute%end = cend
7572 domain_out%compute%size = domain_out%compute%end - domain_out%compute%begin + 1
7573 if(present(gbegin)) domain_out%global%begin = gbegin
7574 if(present(gend)) domain_out%global%end = gend
7575 domain_out%global%size = domain_out%global%end - domain_out%global%begin + 1
7576 
7577 end subroutine mpp_modify_domain1d
7578 
7579 !#######################################################################
7580 
7581 subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, &
7582  & shalo, nhalo)
7583  ! </PUBLICROUTINE>
7584 type(domain2d), intent(in) :: domain_in !< The source domain.
7585 type(domain2d), intent(inout) :: domain_out !< The returned domain.
7586 integer, intent(in), optional :: isc, iec, jsc, jec !< Zonal and meridional axis specifications
7587  !! associated with the global domain of the returned 2D domain.
7588 integer, intent(in), optional :: isg, ieg, jsg, jeg !< Zonal axis specifications associated with
7589  !! the global domain of the returned 2D domain.
7590 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size in x- and y- directions
7591 integer :: global_indices(4), layout(2)
7592 integer :: xflag, yflag, nlist, i
7593 
7594 if(present(whalo) .or. present(ehalo) .or. present(shalo) .or. present(nhalo) ) then
7595  ! get the global indices of the input domain
7596  global_indices(1) = domain_in%x(1)%global%begin; global_indices(2) = domain_in%x(1)%global%end
7597  global_indices(3) = domain_in%y(1)%global%begin; global_indices(4) = domain_in%y(1)%global%end
7598 
7599  ! get the layout
7600  layout(1) = size(domain_in%x(1)%list(:)); layout(2) = size(domain_in%y(1)%list(:))
7601 
7602  ! get the flag
7603  xflag = 0; yflag = 0
7604  if(domain_in%x(1)%cyclic) xflag = xflag + cyclic_global_domain
7605  if(domain_in%x(1)%domain_data%is_global) xflag = xflag + global_data_domain
7606  if(domain_in%y(1)%cyclic) yflag = yflag + cyclic_global_domain
7607  if(domain_in%y(1)%domain_data%is_global) yflag = yflag + global_data_domain
7608 
7609  call mpp_define_domains( global_indices, layout, domain_out, pelist = domain_in%list(:)%pe, &
7610  xflags = xflag, yflags = yflag, whalo = whalo, ehalo = ehalo, &
7611  shalo = shalo, nhalo = nhalo, &
7612  xextent = domain_in%x(1)%list(:)%compute%size, &
7613  yextent = domain_in%y(1)%list(:)%compute%size, &
7614  symmetry=domain_in%symmetry, &
7615  maskmap = domain_in%pearray .NE. null_pe )
7616  domain_out%ntiles = domain_in%ntiles
7617  domain_out%tile_id = domain_in%tile_id
7618 else
7619  call mpp_define_null_domain(domain_out)
7620  nlist = size(domain_in%list(:))
7621  if (associated(domain_out%list)) deallocate(domain_out%list) !< Check if allocated
7622  allocate(domain_out%list(0:nlist-1) )
7623  do i = 0, nlist-1
7624  allocate(domain_out%list(i)%tile_id(1))
7625  domain_out%list(i)%tile_id(1) = 1
7626  enddo
7627  call mpp_modify_domain(domain_in%x(1), domain_out%x(1), isc, iec, isg, ieg)
7628  call mpp_modify_domain(domain_in%y(1), domain_out%y(1), jsc, jec, jsg, jeg)
7629  domain_out%ntiles = domain_in%ntiles
7630  domain_out%tile_id = domain_in%tile_id
7631 endif
7632 
7633 end subroutine mpp_modify_domain2d
7634 ! </SUBROUTINE>
7635 
7636 !#####################################################################
7637 
7638 
7639 subroutine mpp_define_null_domain1d(domain)
7640 type(domain1d), intent(inout) :: domain
7641 
7642 domain%global%begin = -1; domain%global%end = -1; domain%global%size = 0
7643 domain%domain_data%begin = -1; domain%domain_data%end = -1; domain%domain_data%size = 0
7644 domain%compute%begin = -1; domain%compute%end = -1; domain%compute%size = 0
7645 domain%pe = null_pe
7646 
7647 end subroutine mpp_define_null_domain1d
7648 
7649 !#####################################################################
7650 
7651 
7652 subroutine mpp_define_null_domain2d(domain)
7653 type(domain2d), intent(inout) :: domain
7654 
7655 allocate(domain%x(1), domain%y(1), domain%tile_id(1))
7656 call mpp_define_null_domain(domain%x(1))
7657 call mpp_define_null_domain(domain%y(1))
7658 domain%pe = null_pe
7659 domain%tile_id(1) = 1
7660 domain%ntiles = 1
7661 domain%max_ntile_pe = 1
7662 domain%ncontacts = 0
7663 
7664 end subroutine mpp_define_null_domain2d
7665 
7666 !####################################################################
7667 
7668 subroutine mpp_deallocate_domain1d(domain)
7669  type(domain1d), intent(inout) :: domain
7670 
7671  if(ASSOCIATED(domain%list)) deallocate(domain%list)
7672 
7673 end subroutine mpp_deallocate_domain1d
7674 
7675 !####################################################################
7676 
7677 subroutine mpp_deallocate_domain2d(domain)
7678  type(domain2d), intent(inout) :: domain
7679 
7680  call deallocate_domain2d_local(domain)
7681  if(ASSOCIATED(domain%io_domain) ) then
7682  call deallocate_domain2d_local(domain%io_domain)
7683  deallocate(domain%io_domain)
7684  endif
7685 
7686 end subroutine mpp_deallocate_domain2d
7687 
7688 !##################################################################
7689 
7690 subroutine deallocate_domain2d_local(domain)
7691 type(domain2d), intent(inout) :: domain
7692 integer :: i, ntileMe
7693 
7694 ntileme = size(domain%x(:))
7695 
7696 if(ASSOCIATED(domain%pearray))deallocate(domain%pearray)
7697 do i = 1, ntileme
7698  call mpp_deallocate_domain1d(domain%x(i))
7699  call mpp_deallocate_domain1d(domain%y(i))
7700 enddo
7701 deallocate(domain%x, domain%y, domain%tile_id)
7702 
7703 ! TODO: Check if these are always allocated
7704 if(ASSOCIATED(domain%tileList)) deallocate(domain%tileList)
7705 if(ASSOCIATED(domain%tile_id_all)) deallocate(domain%tile_id_all)
7706 
7707 if(ASSOCIATED(domain%list)) then
7708  do i = 0, size(domain%list(:))-1
7709  deallocate(domain%list(i)%x, domain%list(i)%y, domain%list(i)%tile_id)
7710  enddo
7711  deallocate(domain%list)
7712 endif
7713 
7714 if(ASSOCIATED(domain%check_C)) then
7715  call deallocate_overlapspec(domain%check_C)
7716  deallocate(domain%check_C)
7717 endif
7718 
7719 if(ASSOCIATED(domain%check_E)) then
7720  call deallocate_overlapspec(domain%check_E)
7721  deallocate(domain%check_E)
7722 endif
7723 
7724 if(ASSOCIATED(domain%check_N)) then
7725  call deallocate_overlapspec(domain%check_N)
7726  deallocate(domain%check_N)
7727 endif
7728 
7729 if(ASSOCIATED(domain%bound_C)) then
7730  call deallocate_overlapspec(domain%bound_C)
7731  deallocate(domain%bound_C)
7732 endif
7733 
7734 if(ASSOCIATED(domain%bound_E)) then
7735  call deallocate_overlapspec(domain%bound_E)
7736  deallocate(domain%bound_E)
7737 endif
7738 
7739 if(ASSOCIATED(domain%bound_N)) then
7740  call deallocate_overlapspec(domain%bound_N)
7741  deallocate(domain%bound_N)
7742 endif
7743 
7744 if(ASSOCIATED(domain%update_T)) then
7745  call deallocate_overlapspec(domain%update_T)
7746  deallocate(domain%update_T)
7747 endif
7748 
7749 if(ASSOCIATED(domain%update_E)) then
7750  call deallocate_overlapspec(domain%update_E)
7751  deallocate(domain%update_E)
7752 endif
7753 
7754 if(ASSOCIATED(domain%update_C)) then
7755  call deallocate_overlapspec(domain%update_C)
7756  deallocate(domain%update_C)
7757 endif
7758 
7759 if(ASSOCIATED(domain%update_N)) then
7760  call deallocate_overlapspec(domain%update_N)
7761  deallocate(domain%update_N)
7762 endif
7763 
7764 end subroutine deallocate_domain2d_local
7765 
7766 !####################################################################
7767 
7768 subroutine allocate_check_overlap(overlap, count)
7769  type(overlap_type), intent(inout) :: overlap
7770  integer, intent(in ) :: count
7771 
7772  overlap%count = 0
7773  overlap%pe = null_pe
7774  if(associated(overlap%tileMe)) call mpp_error(fatal, &
7775  "allocate_check_overlap(mpp_domains_define): overlap is already been allocated")
7776  if(count < 1) call mpp_error(fatal, &
7777  "allocate_check_overlap(mpp_domains_define): count should be a positive integer")
7778  allocate(overlap%tileMe (count), overlap%dir(count) )
7779  allocate(overlap%is (count), overlap%ie (count) )
7780  allocate(overlap%js (count), overlap%je (count) )
7781  allocate(overlap%rotation(count) )
7782  overlap%rotation = zero
7783 
7784 end subroutine allocate_check_overlap
7785 
7786 !#######################################################################
7787 subroutine insert_check_overlap(overlap, pe, tileMe, dir, rotation, is, ie, js, je)
7788  type(overlap_type), intent(inout) :: overlap
7789  integer, intent(in ) :: pe
7790  integer, intent(in ) :: tileMe, dir, rotation
7791  integer, intent(in ) :: is, ie, js, je
7792  integer :: count
7793 
7794  overlap%count = overlap%count + 1
7795  count = overlap%count
7796  if(.NOT. associated(overlap%tileMe)) call mpp_error(fatal, &
7797  "mpp_domains_define.inc(insert_check_overlap): overlap is not assigned any memory")
7798  if(count > size(overlap%tileMe(:)) ) call mpp_error(fatal, &
7799  "mpp_domains_define.inc(insert_check_overlap): overlap%count is greater than size(overlap%tileMe)")
7800  if( overlap%pe == null_pe ) then
7801  overlap%pe = pe
7802  else
7803  if(overlap%pe .NE. pe) call mpp_error(fatal, &
7804  "mpp_domains_define.inc(insert_check_overlap): mismatch on pe")
7805  endif
7806  overlap%tileMe (count) = tileme
7807  overlap%dir (count) = dir
7808  overlap%rotation(count) = rotation
7809  overlap%is (count) = is
7810  overlap%ie (count) = ie
7811  overlap%js (count) = js
7812  overlap%je (count) = je
7813 
7814 end subroutine insert_check_overlap
7815 
7816 !#######################################################################
7817 !> this routine adds the overlap_in into overlap_out
7818 subroutine add_check_overlap( overlap_out, overlap_in)
7819  type(overlap_type), intent(inout) :: overlap_out
7820  type(overlap_type), intent(in ) :: overlap_in
7821  type(overlap_type) :: overlap
7822  integer :: count, count_in, count_out
7823 
7824  ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
7825  count_in = overlap_in %count
7826  count_out = overlap_out%count
7827  count = count_in+count_out
7828  if(count_in == 0) call mpp_error(fatal, &
7829  "add_check_overlap(mpp_domains_define): overlap_in%count is zero")
7830 
7831  if(count_out == 0) then
7832  if(associated(overlap_out%tileMe)) call mpp_error(fatal, &
7833  "add_check_overlap(mpp_domains_define): overlap is already been allocated but count=0")
7834  call allocate_check_overlap(overlap_out, count_in)
7835  overlap_out%pe = overlap_in%pe
7836  else ! need to expand the dimension size of overlap
7837  call allocate_check_overlap(overlap, count_out)
7838  if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(fatal, &
7839  "mpp_domains_define.inc(add_check_overlap): mismatch of pe between overlap_in and overlap_out")
7840  overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
7841  overlap%is (1:count_out) = overlap_out%is (1:count_out)
7842  overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
7843  overlap%js (1:count_out) = overlap_out%js (1:count_out)
7844  overlap%je (1:count_out) = overlap_out%je (1:count_out)
7845  overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
7846  overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
7847  call deallocate_overlap_type(overlap_out)
7848  call allocate_check_overlap(overlap_out, count)
7849  overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
7850  overlap_out%is (1:count_out) = overlap%is (1:count_out)
7851  overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
7852  overlap_out%js (1:count_out) = overlap%js (1:count_out)
7853  overlap_out%je (1:count_out) = overlap%je (1:count_out)
7854  overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
7855  overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
7856  call deallocate_overlap_type(overlap)
7857  end if
7858  overlap_out%count = count
7859  overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
7860  overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
7861  overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
7862  overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
7863  overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
7864  overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
7865  overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
7866 
7867 end subroutine add_check_overlap
7868 
7869 !####################################################################
7870 subroutine init_overlap_type(overlap)
7871  type(overlap_type), intent(inout) :: overlap
7872 
7873  overlap%count = 0
7874  overlap%pe = null_pe
7875 
7876 end subroutine init_overlap_type
7877 
7878 !####################################################################
7879 
7880 subroutine allocate_update_overlap( overlap, count)
7881  type(overlap_type), intent(inout) :: overlap
7882  integer, intent(in ) :: count
7883 
7884  overlap%count = 0
7885  overlap%pe = null_pe
7886  if(associated(overlap%tileMe)) call mpp_error(fatal, &
7887  "allocate_update_overlap(mpp_domains_define): overlap is already been allocated")
7888  if(count < 1) call mpp_error(fatal, &
7889  "allocate_update_overlap(mpp_domains_define): count should be a positive integer")
7890  allocate(overlap%tileMe (count), overlap%tileNbr (count) )
7891  allocate(overlap%is (count), overlap%ie (count) )
7892  allocate(overlap%js (count), overlap%je (count) )
7893  allocate(overlap%dir (count), overlap%rotation(count) )
7894  allocate(overlap%from_contact(count), overlap%msgsize (count) )
7895  overlap%rotation = zero
7896  overlap%from_contact = .false.
7897 
7898 end subroutine allocate_update_overlap
7899 
7900  !#####################################################################################
7901  subroutine insert_update_overlap(overlap, pe, is1, ie1, js1, je1, is2, ie2, js2, je2, dir, reverse, symmetry)
7902  type(overlap_type), intent(inout) :: overlap
7903  integer, intent(in ) :: pe
7904  integer, intent(in ) :: is1, ie1, js1, je1, is2, ie2, js2, je2
7905  integer, intent(in ) :: dir
7906  logical, optional, intent(in ) :: reverse, symmetry
7907 
7908  logical :: is_reverse, is_symmetry, is_overlapped
7909  integer :: is, ie, js, je, count
7910 
7911  is_reverse = .false.
7912  if(PRESENT(reverse)) is_reverse = reverse
7913  is_symmetry = .false.
7914  if(PRESENT(symmetry)) is_symmetry = symmetry
7915 
7916  is = max(is1,is2); ie = min(ie1,ie2)
7917  js = max(js1,js2); je = min(je1,je2)
7918  is_overlapped = .false.
7919  !--- to avoid unnecessary ( duplicate overlap ) for symmetry domain
7920  if(is_symmetry .AND. (dir == 1 .OR. dir == 5)) then ! x-direction
7921  if( ie .GE. is .AND. je .GT. js ) is_overlapped = .true.
7922  else if(is_symmetry .AND. (dir == 3 .OR. dir == 7)) then ! y-direction
7923  if( ie .GT. is .AND. je .GE. js ) is_overlapped = .true.
7924  else if(ie.GE.is .AND. je.GE.js )then
7925  is_overlapped = .true.
7926  endif
7927 
7928  if(is_overlapped) then
7929  if( overlap%count == 0 ) then
7930  overlap%pe = pe
7931  else
7932  if(overlap%pe .NE. pe) call mpp_error(fatal, &
7933  "mpp_domains_define.inc(insert_update_overlap): mismatch on pe")
7934  endif
7935  overlap%count = overlap%count+1
7936  count = overlap%count
7937  if(count > maxoverlap) call mpp_error(fatal, "mpp_domains_define.inc(insert_update_overlap):"//&
7938  & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7939  overlap%is(count) = is
7940  overlap%ie(count) = ie
7941  overlap%js(count) = js
7942  overlap%je(count) = je
7943  overlap%tileMe (count) = 1
7944  overlap%tileNbr(count) = 1
7945  overlap%dir(count) = dir
7946  if(is_reverse) then
7947  overlap%rotation(count) = one_hundred_eighty
7948  else
7949  overlap%rotation(count) = zero
7950  end if
7951  end if
7952 
7953  end subroutine insert_update_overlap
7954 
7955  !#####################################################################################
7956 subroutine insert_overlap_type(overlap, pe, tileMe, tileNbr, is, ie, js, je, dir, &
7957  rotation, from_contact)
7958  type(overlap_type), intent(inout) :: overlap
7959  integer, intent(in ) :: tileMe, tileNbr, pe
7960  integer, intent(in ) :: is, ie, js, je
7961  integer, intent(in ) :: dir, rotation
7962  logical, intent(in ) :: from_contact
7963  integer :: count
7964 
7965  if( overlap%count == 0 ) then
7966  overlap%pe = pe
7967  else
7968  if(overlap%pe .NE. pe) call mpp_error(fatal, &
7969  "mpp_domains_define.inc(insert_overlap_type): mismatch on pe")
7970  endif
7971  overlap%count = overlap%count+1
7972  count = overlap%count
7973  if(count > maxoverlap) call mpp_error(fatal, "mpp_domains_define.inc(insert_overlap_type):"//&
7974  & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7975  overlap%tileMe (count) = tileme
7976  overlap%tileNbr (count) = tilenbr
7977  overlap%is (count) = is
7978  overlap%ie (count) = ie
7979  overlap%js (count) = js
7980  overlap%je (count) = je
7981  overlap%dir (count) = dir
7982  overlap%rotation (count) = rotation
7983  overlap%from_contact(count) = from_contact
7984  overlap%msgsize (count) = (ie-is+1)*(je-js+1)
7985 
7986 end subroutine insert_overlap_type
7987 
7988 
7989 !#######################################################################
7990 subroutine deallocate_overlap_type( overlap)
7991  type(overlap_type), intent(inout) :: overlap
7992 
7993  if(overlap%count == 0) then
7994  if( .NOT. associated(overlap%tileMe)) return
7995  else
7996  if( .NOT. associated(overlap%tileMe)) call mpp_error(fatal, &
7997  "deallocate_overlap_type(mpp_domains_define): overlap is not been allocated")
7998  endif
7999  if(ASSOCIATED(overlap%tileMe)) deallocate(overlap%tileMe)
8000  if(ASSOCIATED(overlap%tileNbr)) deallocate(overlap%tileNbr)
8001  if(ASSOCIATED(overlap%is)) deallocate(overlap%is)
8002  if(ASSOCIATED(overlap%ie)) deallocate(overlap%ie)
8003  if(ASSOCIATED(overlap%js)) deallocate(overlap%js)
8004  if(ASSOCIATED(overlap%je)) deallocate(overlap%je)
8005  if(ASSOCIATED(overlap%dir)) deallocate(overlap%dir)
8006  if(ASSOCIATED(overlap%index)) deallocate(overlap%index)
8007  if(ASSOCIATED(overlap%rotation)) deallocate(overlap%rotation)
8008  if(ASSOCIATED(overlap%from_contact)) deallocate(overlap%from_contact)
8009  if(ASSOCIATED(overlap%msgsize)) deallocate(overlap%msgsize)
8010  overlap%count = 0
8011 
8012 end subroutine deallocate_overlap_type
8013 
8014 !#######################################################################
8015 subroutine deallocate_overlapspec(overlap)
8016 type(overlapspec), intent(inout) :: overlap
8017 integer :: n
8018 
8019  if(ASSOCIATED(overlap%send)) then
8020  do n = 1, size(overlap%send(:))
8021  call deallocate_overlap_type(overlap%send(n))
8022  enddo
8023  deallocate(overlap%send)
8024  endif
8025  if(ASSOCIATED(overlap%recv)) then
8026  do n = 1, size(overlap%recv(:))
8027  call deallocate_overlap_type(overlap%recv(n))
8028  enddo
8029  deallocate(overlap%recv)
8030  endif
8031 
8032 
8033 end subroutine deallocate_overlapspec
8034 
8035 !#######################################################################
8036 !--- this routine add the overlap_in into overlap_out
8037 subroutine add_update_overlap( overlap_out, overlap_in)
8038  type(overlap_type), intent(inout) :: overlap_out
8039  type(overlap_type), intent(in ) :: overlap_in
8040  type(overlap_type) :: overlap
8041  integer :: count, count_in, count_out, n
8042 
8043  ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
8044  count_in = overlap_in %count
8045  count_out = overlap_out%count
8046  count = count_in+count_out
8047  if(count_in == 0) call mpp_error(fatal, &
8048  "mpp_domains_define.inc(add_update_overlap): overlap_in%count is zero")
8049 
8050  if(count_out == 0) then
8051  if(associated(overlap_out%tileMe)) call mpp_error(fatal, &
8052  "mpp_domains_define.inc(add_update_overlap): overlap is already been allocated but count=0")
8053  call allocate_update_overlap(overlap_out, count_in)
8054  overlap_out%pe = overlap_in%pe
8055  else ! need to expand the dimension size of overlap
8056  if(overlap_in%pe .NE. overlap_out%pe) call mpp_error(fatal, &
8057  "mpp_domains_define.inc(add_update_overlap): mismatch of pe between overlap_in and overlap_out")
8058 
8059  call allocate_update_overlap(overlap, count_out)
8060  overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
8061  overlap%tileNbr (1:count_out) = overlap_out%tileNbr (1:count_out)
8062  overlap%is (1:count_out) = overlap_out%is (1:count_out)
8063  overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
8064  overlap%js (1:count_out) = overlap_out%js (1:count_out)
8065  overlap%je (1:count_out) = overlap_out%je (1:count_out)
8066  overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
8067  overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
8068  overlap%from_contact(1:count_out) = overlap_out%from_contact(1:count_out)
8069  call deallocate_overlap_type(overlap_out)
8070  call allocate_update_overlap(overlap_out, count)
8071  overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
8072  overlap_out%tileNbr (1:count_out) = overlap%tileNbr (1:count_out)
8073  overlap_out%is (1:count_out) = overlap%is (1:count_out)
8074  overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
8075  overlap_out%js (1:count_out) = overlap%js (1:count_out)
8076  overlap_out%je (1:count_out) = overlap%je (1:count_out)
8077  overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
8078  overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
8079  overlap_out%index (1:count_out) = overlap%index (1:count_out)
8080  overlap_out%from_contact(1:count_out) = overlap%from_contact(1:count_out)
8081  overlap_out%msgsize (1:count_out) = overlap%msgsize (1:count_out)
8082  call deallocate_overlap_type(overlap)
8083  end if
8084  overlap_out%count = count
8085  overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
8086  overlap_out%tileNbr (count_out+1:count) = overlap_in%tileNbr (1:count_in)
8087  overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
8088  overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
8089  overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
8090  overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
8091  overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
8092  overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
8093  overlap_out%from_contact(count_out+1:count) = overlap_in%from_contact(1:count_in)
8094 
8095  do n = count_out+1, count
8096  overlap_out%msgsize(n) = (overlap_out%ie(n)-overlap_out%is(n)+1)*(overlap_out%je(n)-overlap_out%js(n)+1)
8097  enddo
8098 
8099 
8100 end subroutine add_update_overlap
8101 
8102 !##############################################################################
8103 subroutine expand_update_overlap_list(overlapList, npes)
8104  type(overlap_type), pointer :: overlapList(:)
8105  integer, intent(in ) :: npes
8106  type(overlap_type), pointer,save :: newlist(:) => null()
8107  integer :: nlist_old, nlist, m
8108 
8109  nlist_old = size(overlaplist(:))
8110  if(nlist_old .GE. npes) call mpp_error(fatal, &
8111  'mpp_domains_define.inc(expand_update_overlap_list): size of overlaplist should be smaller than npes')
8112  nlist = min(npes, 2*nlist_old)
8113  allocate(newlist(nlist))
8114  do m = 1, nlist_old
8115  call add_update_overlap(newlist(m), overlaplist(m))
8116  call deallocate_overlap_type(overlaplist(m))
8117  enddo
8118 
8119  deallocate(overlaplist)
8120  overlaplist => newlist
8121  newlist => null()
8122 
8123  return
8124 
8125 end subroutine expand_update_overlap_list
8126 
8127 !##################################################################################
8128 subroutine expand_check_overlap_list(overlaplist, npes)
8129  type(overlap_type), pointer :: overlaplist(:)
8130  integer, intent(in) :: npes
8131  type(overlap_type), pointer,save :: newlist(:) => null()
8132  integer :: nlist_old, nlist, m
8133 
8134  nlist_old = size(overlaplist(:))
8135  if(nlist_old .GE. npes) call mpp_error(fatal, &
8136  'mpp_domains_define.inc(expand_check_overlap_list): size of overlaplist should be smaller than npes')
8137  nlist = min(npes, 2*nlist_old)
8138  allocate(newlist(nlist))
8139  do m = 1,size(overlaplist(:))
8140  call add_check_overlap(newlist(m), overlaplist(m))
8141  call deallocate_overlap_type(overlaplist(m))
8142  enddo
8143  deallocate(overlaplist)
8144  overlaplist => newlist
8145 
8146 
8147  return
8148 
8149 end subroutine expand_check_overlap_list
8150 
8151 
8152 !###############################################################################
8153 subroutine check_overlap_pe_order(domain, overlap, name)
8154  type(domain2d), intent(in) :: domain
8155  type(overlapspec), intent(in) :: overlap
8156  character(len=*), intent(in) :: name
8157  integer :: m
8158  integer :: pe1, pe2
8159 
8160  !---make sure overlap%nsend and overlap%nrecv is no larger than MAXLIST
8161  if( overlap%nsend > maxlist) call mpp_error(fatal, &
8162  "mpp_domains_define.inc(check_overlap_pe_order): overlap%nsend > MAXLIST, increase MAXLIST")
8163  if( overlap%nrecv > maxlist) call mpp_error(fatal, &
8164  "mpp_domains_define.inc(check_overlap_pe_order): overlap%nrecv > MAXLIST, increase MAXLIST")
8165 
8166  do m = 2, overlap%nsend
8167  pe1 = overlap%send(m-1)%pe
8168  pe2 = overlap%send(m)%pe
8169  !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8170  if( pe2 == domain%pe ) then
8171  print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8172  call mpp_error(fatal, &
8173  "mpp_domains_define.inc(check_overlap_pe_order): send pe2 can not equal to domain%pe")
8174  else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8175  if( pe2 < pe1 ) then
8176  print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8177  call mpp_error(fatal, &
8178  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 1")
8179  endif
8180  else if ( pe2 > domain%pe .AND. pe1 < domain%pe ) then
8181  print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8182  call mpp_error(fatal, &
8183  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 2")
8184  endif
8185  enddo
8186 
8187 
8188  do m = 2, overlap%nrecv
8189  pe1 = overlap%recv(m-1)%pe
8190  pe2 = overlap%recv(m)%pe
8191  !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8192  if( pe2 == domain%pe ) then
8193  print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8194  call mpp_error(fatal, &
8195  "mpp_domains_define.inc(check_overlap_pe_order): recv pe2 can not equal to domain%pe")
8196  else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8197  if( pe2 > pe1 ) then
8198  print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8199  call mpp_error(fatal, &
8200  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 1")
8201  endif
8202  else if ( pe2 < domain%pe .AND. pe1 > domain%pe ) then
8203  print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8204  call mpp_error(fatal, &
8205  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 2")
8206  endif
8207  enddo
8208 
8209 
8210 end subroutine check_overlap_pe_order
8211 
8212 
8213 !###############################################################################
8214 subroutine set_domain_comm_inf(update)
8215  type(overlapspec), intent(inout) :: update
8216 
8217  integer :: m, totsize, n
8218 
8219 
8220  ! first set the send and recv size
8221  update%sendsize = 0
8222  update%recvsize = 0
8223  do m = 1, update%nrecv
8224  totsize = 0
8225  do n = 1, update%recv(m)%count
8226  totsize = totsize + update%recv(m)%msgsize(n)
8227  enddo
8228  update%recv(m)%totsize = totsize
8229  if(m==1) then
8230  update%recv(m)%start_pos = 0
8231  else
8232  update%recv(m)%start_pos = update%recv(m-1)%start_pos + update%recv(m-1)%totsize
8233  endif
8234  update%recvsize = update%recvsize + totsize
8235  enddo
8236 
8237  do m = 1, update%nsend
8238  totsize = 0
8239  do n = 1, update%send(m)%count
8240  totsize = totsize + update%send(m)%msgsize(n)
8241  enddo
8242  update%send(m)%totsize = totsize
8243  if(m==1) then
8244  update%send(m)%start_pos = 0
8245  else
8246  update%send(m)%start_pos = update%send(m-1)%start_pos + update%send(m-1)%totsize
8247  endif
8248  update%sendsize = update%sendsize + totsize
8249  enddo
8250 
8251  return
8252 
8253 
8254 end subroutine set_domain_comm_inf
8255 !> @}
subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, shalo, nhalo)
subroutine set_check_overlap(domain, position)
set up the overlapping for boundary check if the domain is symmetry. The check will be done on curren...
subroutine apply_cyclic_offset(lstart, lend, offset, gstart, gend, gsize)
add offset to the index
logical function mpp_mosaic_defined()
Accessor function for value of mosaic_defined.
subroutine set_contact_point(domain, position)
this routine sets the overlapping between tiles for E,C,N-cell based on T-cell overlapping
subroutine mpp_define_domains1d(global_indices, ndivs, domain, pelist, flags, halo, extent, maskmap, memory_size, begin_halo, end_halo)
Define data and computational domains on a 1D set of data (isg:ieg) and assign them to PEs.
subroutine set_bound_overlap(domain, position)
set up the overlapping for boundary if the domain is symmetry.
subroutine define_contact_point(domain, position, num_contact, tile1, tile2, align1, align2, refine1, refine2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, isgList, iegList, jsgList, jegList)
compute the overlapping between tiles for the T-cell.
subroutine mpp_define_mosaic_pelist(sizes, pe_start, pe_end, pelist, costpertile)
Defines a pelist for use with mosaic tiles.
subroutine mpp_define_io_domain(domain, io_layout)
Define the layout for IO pe's for the given domain.
subroutine mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
Computes extents for a grid decomposition with the given indices and divisions.
subroutine mpp_modify_domain1d(domain_in, domain_out, cbegin, cend, gbegin, gend, hbegin, hend)
Modifies the exents of a domain.
subroutine compute_overlaps_fold_west(domain, position, ishift, jshift)
Computes remote domain overlaps assumes only one in each direction will calculate the overlapping for...
subroutine mpp_define_mosaic(global_indices, layout, domain, num_tile, num_contact, tile1, tile2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, pe_start, pe_end, pelist, whalo, ehalo, shalo, nhalo, xextent, yextent, maskmap, name, memory_size, symmetry, xflags, yflags, tile_id)
Defines a domain for mosaic tile grids.
subroutine fill_contact(Contact, tile, is1, ie1, js1, je1, is2, ie2, js2, je2, align1, align2, refine1, refine2)
always fill the contact according to index order.
subroutine mpp_define_layout2d(global_indices, ndivs, layout)
subroutine add_check_overlap(overlap_out, overlap_in)
this routine adds the overlap_in into overlap_out
subroutine mpp_compute_block_extent(isg, ieg, ndivs, ibegin, iend)
Computes the extents of a grid block.
subroutine compute_overlaps(domain, position, update, check, ishift, jshift, x_cyclic_offset, y_cyclic_offset, whalo, ehalo, shalo, nhalo)
Computes remote domain overlaps.
subroutine mpp_get_domain_shift(domain, ishift, jshift, position)
Returns the shift value in x and y-direction according to domain position..
subroutine compute_overlaps_fold_east(domain, position, ishift, jshift)
computes remote domain overlaps assumes only one in each direction will calculate the overlapping for...
subroutine compute_overlaps_fold_south(domain, position, ishift, jshift)
Computes remote domain overlaps assumes only one in each direction will calculate the overlapping for...
subroutine set_overlaps(domain, overlap_in, overlap_out, whalo_out, ehalo_out, shalo_out, nhalo_out)
this routine sets up the overlapping for mpp_update_domains for arbitrary halo update....
subroutine mpp_define_domains2d(global_indices, layout, domain, pelist, xflags, yflags, xhalo, yhalo, xextent, yextent, maskmap, name, symmetry, memory_size, whalo, ehalo, shalo, nhalo, is_mosaic, tile_count, tile_id, complete, x_cyclic_offset, y_cyclic_offset)
Define 2D data and computational domain on global rectilinear cartesian domain (isg:ieg,...
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:43
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
Definition: mpp_util.inc:51
subroutine mpp_declare_pelist(pelist, name, commID)
Declare a pelist.
Definition: mpp_util.inc:461
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:59
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:421
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:407