FMS  2026.01.01-dev
Flexible Modeling System
mpp_domains_define.inc
1 ! -*-f90-*-
2 !***********************************************************************
3 !* Apache License 2.0
4 !*
5 !* This file is part of the GFDL Flexible Modeling System (FMS).
6 !*
7 !* Licensed under the Apache License, Version 2.0 (the "License");
8 !* you may not use this file except in compliance with the License.
9 !* You may obtain a copy of the License at
10 !*
11 !* http://www.apache.org/licenses/LICENSE-2.0
12 !*
13 !* FMS is distributed in the hope that it will be useful, but WITHOUT
14 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
15 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
16 !* PARTICULAR PURPOSE. See the License for the specific language
17 !* governing permissions and limitations under the License.
18 !***********************************************************************
19 
20 !> @file
21 !> @brief Various routines handling domains in @ref mpp_domains_mod
22 
23 !> @addtogroup mpp_domains_mod
24 !> @{
25  !> @brief Instantiates a layout with the given indices and divisions
26  subroutine mpp_define_layout2d( global_indices, ndivs, layout )
27  integer, intent(in) :: global_indices(:) !< (/ isg, ieg, jsg, jeg /); Defines the global domain.
28  integer, intent(in) :: ndivs !< number of divisions to divide global domain
29  integer, intent(out) :: layout(:)
30 
31  integer :: isg, ieg, jsg, jeg, isz, jsz, idiv, jdiv
32 
33  if(size(global_indices(:)) .NE. 4) call mpp_error(fatal,"mpp_define_layout2D: size of global_indices should be 4")
34  if(size(layout(:)) .NE. 2) call mpp_error(fatal,"mpp_define_layout2D: size of layout should be 2")
35 
36  isg = global_indices(1)
37  ieg = global_indices(2)
38  jsg = global_indices(3)
39  jeg = global_indices(4)
40 
41  isz = ieg - isg + 1
42  jsz = jeg - jsg + 1
43  !first try to divide ndivs in the domain aspect ratio: if imperfect aspect, reduce idiv till it divides ndivs
44  idiv = nint( sqrt(float(ndivs*isz)/jsz) )
45  idiv = max(idiv,1) !for isz=1 line above can give 0
46  do while( mod(ndivs,idiv).NE.0 )
47  idiv = idiv - 1
48  end do !will terminate at idiv=1 if not before
49  jdiv = ndivs/idiv
50 
51  layout = (/ idiv, jdiv /)
52  return
53  end subroutine mpp_define_layout2d
54 
55  !############################################################################
56 
57  !> Defines a pelist for use with mosaic tiles
58  !! @note The following routine may need to revised to improve the capability.
59  !! It is very hard to make it balance for all the situation.
60  !! Hopefully some smart idea will come up someday.
61  subroutine mpp_define_mosaic_pelist( sizes, pe_start, pe_end, pelist, costpertile)
62  integer, dimension(:), intent(in) :: sizes
63  integer, dimension(:), intent(inout) :: pe_start, pe_end
64  integer, dimension(:), intent(in), optional :: pelist, costpertile
65  integer, dimension(size(sizes(:))) :: costs
66  integer, dimension(:), allocatable :: pes
67  integer :: ntiles, npes, totcosts, avgcost
68  integer :: ntiles_left, npes_left, pos, n, tile
69  integer :: cost_on_tile, cost_on_pe, npes_used, errunit
70 
71  ntiles = size(sizes(:))
72  if(size(pe_start(:)) .NE. ntiles .OR. size(pe_end(:)) .NE. ntiles ) then
73  call mpp_error(fatal, "mpp_define_mosaic_pelist: size mismatch between pe_start/pe_end and sizes")
74  end if
75 
76  if(present(costpertile)) then
77  if(size(costpertile(:)) .NE. ntiles ) then
78  call mpp_error(fatal, "mpp_define_mosaic_pelist: size mismatch between costpertile and sizes")
79  end if
80  costs = sizes*costpertile
81  else
82  costs = sizes
83  end if
84 
85  if( PRESENT(pelist) )then
86  if( .NOT.any(pelist.EQ.mpp_pe()) )then
87  errunit = stderr()
88  write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
89  call mpp_error( fatal, 'mpp_define_mosaic_pelist: pe must be in pelist.' )
90  end if
91  npes = size(pelist(:))
92  allocate( pes(0:npes-1) )
93  pes(:) = pelist(:)
94  else
95  npes = mpp_npes()
96  allocate( pes(0:npes-1) )
97  call mpp_get_current_pelist(pes)
98  end if
99 
100  ntiles_left = ntiles
101  npes_left = npes
102  pos = pes(0)
103 
104  do while( ntiles_left > 0 )
105  if( npes_left == 1 ) then ! all left tiles will on the last processor, imbalance possibly.
106  do n = 1, ntiles
107  if(costs(n) > 0) then
108  pe_start(n) = pos
109  pe_end(n) = pos
110  costs(n) = 0
111  end if
112  end do
113  ntiles_left = 0
114  npes_left = 0
115  else
116  totcosts = sum(costs)
117  avgcost = ceiling(real(totcosts)/npes_left )
118  tile = minval(maxloc(costs))
119  cost_on_tile = costs(tile)
120  pe_start(tile) = pos
121  ntiles_left = ntiles_left - 1
122  costs(tile) = 0
123  totcosts = totcosts - cost_on_tile
124  if(cost_on_tile .GE. avgcost ) then
125  npes_used = min(ceiling(real(cost_on_tile)/avgcost), npes_left)
126  if( ntiles_left > 0 .AND. npes_used == npes_left ) npes_used = npes_used - 1
127  pe_end(tile) = pos + npes_used - 1
128  npes_left = npes_left - npes_used
129  pos = pos + npes_used
130  else
131  !--- find other tiles to share the pe
132  pe_end(tile) = pos
133  cost_on_pe = cost_on_tile
134  do while(ntiles_left>npes_left) ! make sure all the pes are used.
135  tile = minval(minloc(costs, costs> 0 ))
136  cost_on_tile = costs(tile)
137  cost_on_pe = cost_on_pe + cost_on_tile
138  if(cost_on_pe > avgcost ) exit
139  pe_start(tile) = pos
140  pe_end(tile) = pos
141  ntiles_left = ntiles_left - 1
142  costs(tile) = 0
143  totcosts = totcosts - cost_on_tile
144  end do
145  npes_left = npes_left - 1
146  pos = pos + 1
147  end if
148  end if
149  end do
150 
151  if(npes_left .NE. 0 ) call mpp_error(fatal, "mpp_define_mosaic_pelist: the left npes should be zero")
152  deallocate(pes)
153 
154  end subroutine mpp_define_mosaic_pelist
155 
156  !> Computes the extents of a grid block
157  !!
158  !> Tis implementation is different from mpp_compute_extents
159  !! The last block might have most points
160  subroutine mpp_compute_block_extent(isg,ieg,ndivs,ibegin,iend)
161  integer, intent(in) :: isg, ieg, ndivs
162  integer, dimension(:), intent(out) :: ibegin, iend
163 
164  integer :: ndiv
165  integer :: is, ie
166 
167  ie = ieg
168  do ndiv=ndivs,1,-1
169  !domain is sized by dividing remaining points by remaining domains
170  is = ie - ceiling( real(ie-isg+1)/ndiv ) + 1
171  ibegin(ndiv) = is
172  iend(ndiv) = ie
173 
174  if( ie.LT.is )call mpp_error( fatal, &
175  'MPP_DEFINE_DOMAINS(mpp_compute_block_extent): domain extents must be positive definite.' )
176  if( ndiv.EQ.1 .AND. ibegin(ndiv) .NE. isg ) &
177  call mpp_error( fatal, 'mpp_compute_block_extent: domain extents do not span space completely.' )
178  ie = is - 1
179  end do
180 
181  end subroutine mpp_compute_block_extent
182 
183 
184  !#####################################################################
185  !> Computes extents for a grid decomposition with the given indices and divisions
186  subroutine mpp_compute_extent(isg,ieg,ndivs,ibegin,iend, extent )
187  integer, intent(in) :: isg, ieg, ndivs
188  integer, dimension(0:), intent(out) :: ibegin, iend
189  integer, dimension(0:), intent(in), optional :: extent
190 
191  integer :: ndiv, imax, ndmax, ndmirror
192  integer :: is, ie, n
193  logical :: symmetrize, use_extent
194  !statement functions
195  logical :: even, odd
196  even(n) = (mod(n,2).EQ.0)
197  odd(n) = (mod(n,2).EQ.1)
198 
199  use_extent = .false.
200  if(PRESENT(extent)) then
201  if( size(extent(:)).NE.ndivs ) &
202  call mpp_error( fatal, 'mpp_compute_extent: extent array size must equal number of domain divisions.' )
203  use_extent = .true.
204  if(all(extent ==0)) use_extent = .false.
205  endif
206 
207  is = isg
208  if(use_extent) then
209  ibegin(0) = isg
210  do ndiv = 0, ndivs-2
211  if(extent(ndiv) .LE. 0) call mpp_error( fatal, &
212  & 'mpp_compute_extent: domain extents must be positive definite.' )
213  iend(ndiv) = ibegin(ndiv) + extent(ndiv) - 1
214  ibegin(ndiv+1) = iend(ndiv) + 1
215  enddo
216  iend(ndivs-1) = ibegin(ndivs-1) + extent(ndivs-1) - 1
217  if(iend(ndivs-1) .NE. ieg) call mpp_error(fatal, &
218  & 'mpp_compute_extent: extent array limits do not match global domain.' )
219  else
220  do ndiv=0,ndivs-1
221  !modified for mirror-symmetry
222  !original line
223  ! ie = is + CEILING( float(ieg-is+1)/(ndivs-ndiv) ) - 1
224 
225  !problem of dividing nx points into n domains maintaining symmetry
226  !i.e nx=18 n=4 4554 and 5445 are solutions but 4455 is not.
227  !this will always work for nx even n even or odd
228  !this will always work for nx odd, n odd
229  !this will never work for nx odd, n even: for this case we supersede the mirror calculation
230  ! symmetrize = .NOT. ( mod(ndivs,2).EQ.0 .AND. mod(ieg-isg+1,2).EQ.1 )
231  !nx even n odd fails if n>nx/2
232  symmetrize = ( even(ndivs) .AND. even(ieg-isg+1) ) .OR. &
233  ( odd(ndivs) .AND. odd(ieg-isg+1) ) .OR. &
234  ( odd(ndivs) .AND. even(ieg-isg+1) .AND. ndivs.LT.(ieg-isg+1)/2 )
235 
236  !mirror domains are stored in the list and retrieved if required.
237  if( ndiv.EQ.0 )then
238  !initialize max points and max domains
239  imax = ieg
240  ndmax = ndivs
241  end if
242  !do bottom half of decomposition, going over the midpoint for odd ndivs
243  if( ndiv.LT.(ndivs-1)/2+1 )then
244  !domain is sized by dividing remaining points by remaining domains
245  ie = is + ceiling( real(imax-is+1)/(ndmax-ndiv) ) - 1
246  ndmirror = (ndivs-1) - ndiv !mirror domain
247  if( ndmirror.GT.ndiv .AND. symmetrize )then !only for domains over the midpoint
248  !mirror extents, the max(,) is to eliminate overlaps
249  ibegin(ndmirror) = max( isg+ieg-ie, ie+1 )
250  iend(ndmirror) = max( isg+ieg-is, ie+1 )
251  imax = ibegin(ndmirror) - 1
252  ndmax = ndmax - 1
253  end if
254  else
255  if( symmetrize )then
256  !do top half of decomposition by retrieving saved values
257  is = ibegin(ndiv)
258  ie = iend(ndiv)
259  else
260  ie = is + ceiling( real(imax-is+1)/(ndmax-ndiv) ) - 1
261  end if
262  end if
263  ibegin(ndiv) = is
264  iend(ndiv) = ie
265  if( ie.LT.is )call mpp_error( fatal, &
266  'MPP_DEFINE_DOMAINS(mpp_compute_extent): domain extents must be positive definite.' )
267  if( ndiv.EQ.ndivs-1 .AND. iend(ndiv).NE.ieg ) &
268  call mpp_error( fatal, 'mpp_compute_extent: domain extents do not span space completely.' )
269  is = ie + 1
270  end do
271  endif
272 
273 
274  end subroutine mpp_compute_extent
275 
276  !#####################################################################
277 
278 
279  !> Define data and computational domains on a 1D set of data (isg:ieg) and assign them to PEs
280  subroutine mpp_define_domains1d( global_indices, ndivs, domain, pelist, flags, halo, extent, maskmap, &
281  memory_size, begin_halo, end_halo )
282  integer, intent(in) :: global_indices(:) !< (/ isg, ieg /) gives the extent of global domain
283  integer, intent(in) :: ndivs !< number of divisions of domain: even divisions unless extent is present.
284  type(domain1d), intent(inout) :: domain !< the returned domain1D; declared inout so that
285  !! existing links, if any, can be nullified
286  integer, intent(in), optional :: pelist(0:) !< list of PEs to which domains are to be assigned
287  !! (default 0...npes-1); size of pelist must
288  !! correspond to number of mask=.TRUE. divisions
289  integer, intent(in), optional :: flags, halo !< flags define whether compute and data domains
290  !! are global (undecomposed) and whether the global
291  !! domain has periodic boundaries.
292  !! halo defines halo width (currently the same on both sides)
293  integer, intent(in), optional :: extent(0:) !< array extent; defines width of each division
294  !! (used for non-uniform domain decomp, for e.g load-balancing)
295  logical, intent(in), optional :: maskmap(0:) !< a division whose maskmap=.FALSE. is not
296  !! assigned to any domain. By default we assume
297  !! decomposition of compute and data domains, non-periodic boundaries,
298  !! no halo, as close to uniform extents as the
299  !! input parameters permit
300  integer, intent(in), optional :: memory_size
301  integer, intent(in), optional :: begin_halo, end_halo
302 
303  logical :: compute_domain_is_global, data_domain_is_global
304  integer :: ndiv, n, isg, ieg
305  integer, allocatable :: pes(:)
306  integer :: ibegin(0:ndivs-1), iend(0:ndivs-1)
307  logical :: mask(0:ndivs-1)
308  integer :: halosz, halobegin, haloend
309  integer :: errunit
310 
311  if( .NOT.module_is_initialized )call mpp_error( fatal, &
312  & 'MPP_DEFINE_DOMAINS1D: You must first call mpp_domains_init.' )
313  if(size(global_indices(:)) .NE. 2) call mpp_error(fatal,"mpp_define_domains1D: size of global_indices should be 2")
314  !get global indices
315  isg = global_indices(1)
316  ieg = global_indices(2)
317  if( ndivs.GT.ieg-isg+1 )call mpp_error( fatal, &
318  & 'MPP_DEFINE_DOMAINS1D: more divisions requested than rows available.' )
319  !get the list of PEs on which to assign domains; if pelist is absent use 0..npes-1
320  if( PRESENT(pelist) )then
321  if( .NOT.any(pelist.EQ.mpp_pe()) )then
322  errunit = stderr()
323  write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
324  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: pe must be in pelist.' )
325  end if
326  allocate( pes(0:size(pelist(:))-1) )
327  pes(:) = pelist(:)
328  else
329  allocate( pes(0:mpp_npes()-1) )
330  call mpp_get_current_pelist(pes)
331 ! pes(:) = (/ (i,i=0,mpp_npes()-1) /)
332  end if
333 
334  !get number of real domains: 1 mask domain per PE in pes
335  mask = .true. !default mask
336  if( PRESENT(maskmap) )then
337  if( size(maskmap(:)).NE.ndivs ) &
338  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: maskmap array size must equal number of domain divisions.' )
339  mask(:) = maskmap(:)
340  end if
341  if( count(mask).NE.size(pes(:)) ) &
342  call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: number of TRUEs in maskmap array must match PE count.' )
343 
344  !get halosize
345  halosz = 0
346  if( PRESENT(halo) ) then
347  halosz = halo
348  !--- if halo is present, begin_halo and end_halo should not present
349  if(present(begin_halo) .OR. present(end_halo) ) call mpp_error(fatal, &
350  "mpp_domains_define.inc: when halo is present, begin_halo and end_halo should not present")
351  end if
352  halobegin = halosz; haloend = halosz
353  if(present(begin_halo)) halobegin = begin_halo
354  if(present(end_halo)) haloend = end_halo
355  halosz = max(halobegin, haloend)
356  !get flags
357  compute_domain_is_global = .false.
358  data_domain_is_global = .false.
359  domain%cyclic = .false.
360  domain%goffset = 1
361  domain%loffset = 1
362  if( PRESENT(flags) )then
363  !NEW: obsolete flag global_compute_domain, since ndivs is non-optional and you cannot
364  !have global compute and ndivs.NE.1
365  compute_domain_is_global = ndivs.EQ.1
366  !if compute domain is global, data domain must also be
367  data_domain_is_global = btest(flags,global) .OR. compute_domain_is_global
368  domain%cyclic = btest(flags,cyclic) .AND. halosz.NE.0
369  if(btest(flags,cyclic)) domain%goffset = 0
370  end if
371 
372  !set up links list
373  allocate( domain%list(0:ndivs-1) )
374 
375  !set global domain
376  domain%list(:)%global%begin = isg
377  domain%list(:)%global%end = ieg
378  domain%list(:)%global%size = ieg-isg+1
379  domain%list(:)%global%max_size = ieg-isg+1
380  domain%list(:)%global%is_global = .true. !always
381 
382  !get compute domain
383  if( compute_domain_is_global )then
384  domain%list(:)%compute%begin = isg
385  domain%list(:)%compute%end = ieg
386  domain%list(:)%compute%is_global = .true.
387  domain%list(:)%pe = pes(:)
388  domain%pos = 0
389  else
390  domain%list(:)%compute%is_global = .false.
391  n = 0
392  call mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
393  do ndiv=0,ndivs-1
394  domain%list(ndiv)%compute%begin = ibegin(ndiv)
395  domain%list(ndiv)%compute%end = iend(ndiv)
396  if( mask(ndiv) )then
397  domain%list(ndiv)%pe = pes(n)
398  if( mpp_pe().EQ.pes(n) )domain%pos = ndiv
399  n = n + 1
400  else
401  domain%list(ndiv)%pe = null_pe
402  end if
403  end do
404  end if
405 
406  domain%list(:)%compute%size = domain%list(:)%compute%end - domain%list(:)%compute%begin + 1
407 
408  !get data domain
409  !data domain is at least equal to compute domain
410  domain%list(:)%domain_data%begin = domain%list(:)%compute%begin
411  domain%list(:)%domain_data%end = domain%list(:)%compute%end
412  domain%list(:)%domain_data%is_global = .false.
413  !apply global flags
414  if( data_domain_is_global )then
415  domain%list(:)%domain_data%begin = isg
416  domain%list(:)%domain_data%end = ieg
417  domain%list(:)%domain_data%is_global = .true.
418  end if
419  !apply margins
420  domain%list(:)%domain_data%begin = domain%list(:)%domain_data%begin - halobegin
421  domain%list(:)%domain_data%end = domain%list(:)%domain_data%end + haloend
422  domain%list(:)%domain_data%size = domain%list(:)%domain_data%end - domain%list(:)%domain_data%begin + 1
423 
424  !--- define memory domain, if memory_size is not present or memory size is 0, memory domain size
425  !--- will be the same as data domain size. if momory_size is present, memory_size should greater than
426  !--- or equal to data size. The begin of memory domain will be always the same as data domain.
427  domain%list(:)%memory%begin = domain%list(:)%domain_data%begin
428  domain%list(:)%memory%end = domain%list(:)%domain_data%end
429  if( present(memory_size) ) then
430  if(memory_size > 0) then
431  if( domain%list(domain%pos)%domain_data%size > memory_size ) call mpp_error(fatal, &
432  "mpp_domains_define.inc: data domain size is larger than memory domain size on this pe")
433  domain%list(:)%memory%end = domain%list(:)%memory%begin + memory_size - 1
434  end if
435  end if
436  domain%list(:)%memory%size = domain%list(:)%memory%end - domain%list(:)%memory%begin + 1
437  domain%list(:)%memory%is_global = domain%list(:)%domain_data%is_global
438 
439  domain%compute = domain%list(domain%pos)%compute
440  domain%domain_data = domain%list(domain%pos)%domain_data
441  domain%global = domain%list(domain%pos)%global
442  domain%memory = domain%list(domain%pos)%memory
443  domain%compute%max_size = maxval( domain%list(:)%compute%size )
444  domain%domain_data%max_size = maxval( domain%list(:)%domain_data%size )
445  domain%global%max_size = domain%global%size
446  domain%memory%max_size = domain%memory%size
447 
448  !PV786667: the deallocate stmts can be removed when fixed (7.3.1.3m)
449  deallocate( pes )
450  return
451 
452  end subroutine mpp_define_domains1d
453 
454  !################################################################################
455  !> Define the layout for IO pe's for the given domain
456  subroutine mpp_define_io_domain(domain, io_layout)
457  type(domain2d), intent(inout) :: domain !< Input 2D domain
458  integer, intent(in ) :: io_layout(2) !< 2 value io pe layout to define
459  integer :: layout(2)
460  integer :: npes_in_group
461  type(domain2d), pointer :: io_domain=>null()
462  integer :: i, j, n, m
463  integer :: ipos, jpos, igroup, jgroup
464  integer :: ipos_beg, ipos_end, jpos_beg, jpos_end
465  integer :: whalo, ehalo, shalo, nhalo
466  integer :: npes_x, npes_y, ndivx, ndivy
467  integer, allocatable :: posarray(:,:)
468 
469  if(io_layout(1) * io_layout(2) .LE. 0) then
470  call mpp_error(note, &
471  "mpp_domains_define.inc(mpp_define_io_domain): io domain will not be defined for "//trim(domain%name)// &
472  " when one or both entry of io_layout is not positive")
473  return
474  endif
475 
476  layout(1) = size(domain%x(1)%list(:))
477  layout(2) = size(domain%y(1)%list(:))
478 
479  if(ASSOCIATED(domain%io_domain)) call mpp_error(fatal, &
480  "mpp_domains_define.inc(mpp_define_io_domain): io_domain is already defined")
481 
482  if(mod(layout(1), io_layout(1)) .NE. 0) call mpp_error(fatal, &
483  "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
484  & " domain layout(1) must be divided by io_layout(1)")
485  if(mod(layout(2), io_layout(2)) .NE. 0) call mpp_error(fatal, &
486  "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
487  & " domain layout(2) must be divided by io_layout(2)")
488  if(size(domain%x(:)) > 1) call mpp_error(fatal, &
489  "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
490  ": multiple tile per pe is not supported yet for this routine")
491 
492  if (associated(domain%io_domain)) deallocate(domain%io_domain) !< Check if associated
493  allocate(domain%io_domain)
494  domain%io_layout = io_layout
495  io_domain => domain%io_domain
496  ! Find how many processors are in the group with the consideration that some of the region maybe masked out.
497  npes_x = layout(1)/io_layout(1)
498  npes_y = layout(2)/io_layout(2)
499  ipos = mod(domain%x(1)%pos, npes_x)
500  jpos = mod(domain%y(1)%pos, npes_y)
501  igroup = domain%x(1)%pos/npes_x
502  jgroup = domain%y(1)%pos/npes_y
503  ipos_beg = igroup*npes_x; ipos_end = ipos_beg + npes_x - 1
504  jpos_beg = jgroup*npes_y; jpos_end = jpos_beg + npes_y - 1
505  npes_in_group = 0
506  do j = jpos_beg, jpos_end
507  do i = ipos_beg, ipos_end
508  if(domain%pearray(i,j) .NE. null_pe) npes_in_group = npes_in_group+1
509  enddo
510  enddo
511 
512  io_domain%whalo = domain%whalo
513  io_domain%ehalo = domain%ehalo
514  io_domain%shalo = domain%shalo
515  io_domain%nhalo = domain%nhalo
516  io_domain%ntiles = 1
517  io_domain%pe = domain%pe
518  io_domain%symmetry = domain%symmetry
519  if (associated(io_domain%list)) deallocate(io_domain%list) !< Check if associated
520  allocate(io_domain%list(0:npes_in_group-1))
521  do i = 0, npes_in_group-1
522  allocate( io_domain%list(i)%x(1), io_domain%list(i)%y(1), io_domain%list(i)%tile_id(1) )
523  enddo
524 
525  ndivx = size(domain%pearray,1)
526  ndivy = size(domain%pearray,2)
527  allocate(posarray(0:ndivx-1, 0:ndivy-1))
528  n = domain%tile_root_pe - mpp_root_pe()
529  posarray = -1
530  do j = 0,ndivy-1
531  do i = 0,ndivx-1
532  if( domain%pearray(i,j) == null_pe) cycle
533  posarray(i,j) = n
534  n = n + 1
535  enddo
536  enddo
537 
538  n = 0
539  do j = jpos_beg, jpos_end
540  do i = ipos_beg, ipos_end
541  if( domain%pearray(i,j) == null_pe) cycle
542  io_domain%list(n)%pe = domain%pearray(i,j)
543  m = posarray(i,j)
544  io_domain%list(n)%x(1)%compute = domain%list(m)%x(1)%compute
545  io_domain%list(n)%y(1)%compute = domain%list(m)%y(1)%compute
546  igroup = domain%list(m)%x(1)%pos/npes_x
547  jgroup = domain%list(m)%y(1)%pos/npes_y
548  io_domain%list(n)%tile_id(1) = jgroup*io_layout(1) + igroup
549  n = n + 1
550  enddo
551  enddo
552  deallocate(posarray)
553 
554  if (associated(io_domain%x)) deallocate(io_domain%x) !< Check if associated
555  if (associated(io_domain%y)) deallocate(io_domain%y) !< Check if associated
556  if (associated(io_domain%tile_id)) deallocate(io_domain%tile_id) !< Check if associated
557  allocate(io_domain%x(1), io_domain%y(1), io_domain%tile_id(1) )
558  allocate(io_domain%x(1)%list(0:npes_x-1), io_domain%y(1)%list(0:npes_y-1) )
559  n = -1
560  do j = jpos_beg, jpos_beg+jpos
561  do i = ipos_beg, ipos_beg+ipos
562  if(domain%pearray(i,j) .NE. null_pe) n = n + 1
563  enddo
564  enddo
565  io_domain%pos = n
566  io_domain%x(1)%compute = domain%x(1)%compute
567  io_domain%x(1)%domain_data = domain%x(1)%domain_data
568  io_domain%x(1)%memory = domain%x(1)%memory
569  io_domain%y(1)%compute = domain%y(1)%compute
570  io_domain%y(1)%domain_data = domain%y(1)%domain_data
571  io_domain%y(1)%memory = domain%y(1)%memory
572  io_domain%x(1)%global%begin = domain%x(1)%list(ipos_beg)%compute%begin
573  io_domain%x(1)%global%end = domain%x(1)%list(ipos_end)%compute%end
574  io_domain%x(1)%global%size = io_domain%x(1)%global%end - io_domain%x(1)%global%begin + 1
575  io_domain%x(1)%global%max_size = io_domain%x(1)%global%size
576  io_domain%y(1)%global%begin = domain%y(1)%list(jpos_beg)%compute%begin
577  io_domain%y(1)%global%end = domain%y(1)%list(jpos_end)%compute%end
578  io_domain%y(1)%global%size = io_domain%y(1)%global%end - io_domain%y(1)%global%begin + 1
579  io_domain%y(1)%global%max_size = io_domain%y(1)%global%size
580  io_domain%x(1)%pos = ipos
581  io_domain%y(1)%pos = jpos
582  io_domain%tile_id(1) = io_domain%list(n)%tile_id(1)
583  io_domain%tile_root_pe = io_domain%list(0)%pe
584 
585  !z1l
586 !!$ do j = 0, npes_y - 1
587 !!$ n = j*npes_x + ipos
588 !!$ io_domain%y(1)%list(j) = io_domain%list(n)%y(1)
589 !!$ enddo
590 !!$ do i = 0, npes_x - 1
591 !!$ n = jpos*npes_x + i
592 !!$ io_domain%x(1)%list(i) = io_domain%list(n)%x(1)
593 !!$ enddo
594 
595  whalo = domain%whalo
596  ehalo = domain%ehalo
597  shalo = domain%shalo
598  nhalo = domain%nhalo
599 
600  io_domain=>null()
601 
602 
603  end subroutine mpp_define_io_domain
604 
605  !> Define 2D data and computational domain on global rectilinear cartesian domain
606  !! (isg:ieg,jsg:jeg) and assign them to PEs
607  subroutine mpp_define_domains2d( global_indices, layout, domain, pelist, xflags, yflags, &
608  xhalo, yhalo, xextent, yextent, maskmap, name, symmetry, memory_size, &
609  whalo, ehalo, shalo, nhalo, is_mosaic, tile_count, tile_id, complete, x_cyclic_offset, y_cyclic_offset )
610  integer, intent(in) :: global_indices(:) !<(/ isg, ieg, jsg, jeg /)
611  integer, intent(in) :: layout(:) !< pe layout
612  type(domain2d), intent(inout) :: domain !< 2D domain decomposition to define
613  integer, intent(in), optional :: pelist(0:) !< current pelist to run on
614  integer, intent(in), optional :: xflags, yflags !< directional flag
615  integer, intent(in), optional :: xhalo, yhalo !< halo sizes for x and y indices
616  integer, intent(in), optional :: xextent(0:), yextent(0:)
617  logical, intent(in), optional :: maskmap(0:,0:)
618  character(len=*), intent(in), optional :: name
619  logical, intent(in), optional :: symmetry
620  logical, intent(in), optional :: is_mosaic !< indicate if calling mpp_define_domains
621  !! from mpp_define_mosaic.
622  integer, intent(in), optional :: memory_size(:)
623  integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size for West, East,
624  !! South and North direction.
625  !! if whalo and ehalo is not present,
626  !! will take the value of xhalo
627  !! if shalo and nhalo is not present,
628  !! will take the value of yhalo
629  integer, intent(in), optional :: tile_count !< tile number on current pe,
630  !! default value is 1.
631  !! this is for the situation that
632  !! multiple tiles on one processor
633  integer, intent(in), optional :: tile_id !< tile id
634  logical, intent(in), optional :: complete !< true indicate mpp_define_domain
635  !! is completed for mosaic definition.
636  integer, intent(in), optional :: x_cyclic_offset !< offset for x-cyclic boundary condition,
637  !! (0,j) = (ni, mod(j+x_cyclic_offset,nj))
638  !! (ni+1, j)=(1 ,mod(j+nj-x_cyclic_offset,nj))
639  integer, intent(in), optional :: y_cyclic_offset !< offset for y-cyclic boundary condition
640  !!(i,0) = (mod(i+y_cyclic_offset,ni), nj))
641  !!(i,nj+1) =(mod(mod(i+ni-y_cyclic_offset,ni),
642  !! 1) )
643 
644  integer :: i, j, m, n, xhalosz, yhalosz, memory_xsize, memory_ysize
645  integer :: whalosz, ehalosz, shalosz, nhalosz
646  integer :: ipos, jpos, pos, tile, nlist, cur_tile_id
647  type(mpi_comm) :: cur_comm
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 = mpi_comm_null
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, comm=cur_comm)
694  else
695  allocate( pesall(0:size(pes(:))-1) )
696  pesall = pes
697  call mpp_get_current_pelist(pesall, comm=cur_comm)
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, comm=cur_comm)
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 = cur_comm
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 = cur_comm
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  integer :: tile_base !< Minimum tile ID minus 1. Used to transform tile IDs to array indices.
1237  logical :: is_symmetry
1238  integer, allocatable :: align1(:), align2(:), is1(:), ie1(:), js1(:), je1(:), is2(:), ie2(:), js2(:), je2(:)
1239  integer, allocatable :: isgList(:), iegList(:), jsgList(:), jegList(:)
1240  real, allocatable :: refine1(:), refine2(:)
1241  integer :: outunit
1242  logical :: send(8), recv(8)
1243 
1244  outunit = stdout()
1245  mosaic_defined = .true.
1246  !--- the size of first indice of global_indices must be 4.
1247  if(size(global_indices, 1) .NE. 4) call mpp_error(fatal, &
1248  'mpp_domains_define.inc: The size of first dimension of global_indices is not 4')
1249  !--- the size of second indice of global_indices must be num_tile
1250  if(size(global_indices, 2) .NE. num_tile) call mpp_error(fatal, &
1251  'mpp_domains_define.inc: The size of second dimension of global_indices is not equal num_tile')
1252  !--- the size of first indice of layout must be 2. The second dimension size of layout must equal num_tile.
1253  if(size(layout, 1) .NE. 2) call mpp_error(fatal, &
1254  'mpp_domains_define.inc: The size of first dimension of layout is not 2')
1255  if(size(layout,2) .NE. num_tile) call mpp_error(fatal, &
1256  'mpp_domains_define.inc: The size of second dimension of layout is not equal num_tile')
1257 
1258  !--- setup pelist for the mosaic ---------------------
1259  nlist = mpp_npes()
1260  allocate(pes(0:nlist-1))
1261  if(present(pelist)) then
1262  if( nlist .NE. size(pelist(:))) call mpp_error(fatal, &
1263  'mpp_domains_define.inc: size of pelist is not equal mpp_npes')
1264  pes = pelist
1265  end if
1266  call mpp_get_current_pelist(pes, comm=domain%comm)
1267  !--- pelist should be monotonic increasing by 1.
1268  do n = 1, nlist-1
1269  if(pes(n) - pes(n-1) .NE. 1) call mpp_error(fatal, &
1270  'mpp_domains_define.inc: pelist is not monotonic increasing by 1')
1271  end do
1272 
1273  is_symmetry = .false.
1274  if(present(symmetry)) is_symmetry = symmetry
1275 
1276  if(size(pe_start(:)) .NE. num_tile .OR. size(pe_end(:)) .NE. num_tile ) call mpp_error(fatal, &
1277  'mpp_domains_define.inc: size of pe_start and/or pe_end is not equal num_tile')
1278  !--- make sure pe_start and pe_end is in the pelist.
1279  if( any( pe_start < pes(0) ) ) call mpp_error(fatal, &
1280  & 'mpp_domains_define.inc: not all the pe_start are in the pelist')
1281  if( any( pe_end > pes(nlist-1)) ) call mpp_error(fatal, &
1282  & 'mpp_domains_define.inc: not all the pe_end are in the pelist')
1283 
1284  !--- calculate number of tiles on each pe.
1285  allocate( ntile_per_pe(0:nlist-1) )
1286  ntile_per_pe = 0
1287  do n = 1, num_tile
1288  do m = pe_start(n) - mpp_root_pe(), pe_end(n) - mpp_root_pe()
1289  ntile_per_pe(m) = ntile_per_pe(m) + 1
1290  end do
1291  end do
1292  if(any(ntile_per_pe == 0)) call mpp_error(fatal, &
1293  'mpp_domains_define.inc: At least one pe in pelist is not used by any tile in the mosaic')
1294 
1295  !--- check the size comformable of xextent and yextent
1296  if( PRESENT(xextent) ) then
1297  if(size(xextent,1) .GT. maxval(layout(1,:)) ) call mpp_error(fatal, &
1298  'mpp_domains_define.inc: size mismatch between xextent and layout')
1299  if(size(xextent,2) .NE. num_tile) call mpp_error(fatal, &
1300  'mpp_domains_define.inc: size of xextent is not eqaul num_tile')
1301  end if
1302  if( PRESENT(yextent) ) then
1303  if(size(yextent,1) .GT. maxval(layout(2,:)) ) call mpp_error(fatal, &
1304  'mpp_domains_define.inc: size mismatch between yextent and layout')
1305  if(size(yextent,2) .NE. num_tile) call mpp_error(fatal, &
1306  'mpp_domains_define.inc: size of yextent is not eqaul num_tile')
1307  end if
1308 
1309  !--- check the size comformable of maskmap
1310  !--- since the layout is different between tiles, so the actual size of maskmap for each tile is
1311  !--- not diffrent. When define maskmap for multiple tiles, user can choose the maximum value
1312  !--- of layout of all tiles to the first and second dimension of maskmap.
1313  if(present(maskmap)) then
1314  if(size(maskmap,1) .GT. maxval(layout(1,:)) .or. size(maskmap,2) .GT. maxval(layout(2,:))) &
1315  call mpp_error(fatal, 'mpp_domains_define.inc: size mismatch between maskmap and layout')
1316  if(size(maskmap,3) .NE. num_tile) call mpp_error(fatal, &
1317  'mpp_domains_define.inc: the third dimension of maskmap is not equal num_tile')
1318  end if
1319 
1320  if (associated(domain%tileList)) deallocate(domain%tileList) !< Check if associated
1321  allocate(domain%tileList(num_tile))
1322  do n = 1, num_tile
1323  domain%tileList(n)%xbegin = global_indices(1,n)
1324  domain%tileList(n)%xend = global_indices(2,n)
1325  domain%tileList(n)%ybegin = global_indices(3,n)
1326  domain%tileList(n)%yend = global_indices(4,n)
1327  enddo
1328  !--- define some mosaic information in domain type
1329  nt = ntile_per_pe(mpp_pe()-mpp_root_pe())
1330  if (associated(domain%tile_id)) deallocate(domain%tile_id) !< Check if associated
1331  if (associated(domain%x)) deallocate(domain%x) !< Check if associated
1332  if (associated(domain%y)) deallocate(domain%y) !< Check if associated
1333  if (associated(domain%list)) deallocate(domain%list) !< Check if associated
1334  allocate(domain%tile_id(nt), domain%x(nt), domain%y(nt) )
1335  allocate(domain%list(0:nlist-1))
1336 
1337  do n = 0, nlist-1
1338  nt = ntile_per_pe(n)
1339  allocate(domain%list(n)%x(nt), domain%list(n)%y(nt), domain%list(n)%tile_id(nt))
1340  end do
1341 
1342  pos = 0
1343  pe = mpp_pe()
1344  if( PRESENT(tile_id) ) then
1345  if(size(tile_id(:)) .NE. num_tile) then
1346  call mpp_error(fatal, .NE."mpp_domains_define.inc: size(tile_id) num_tile")
1347  endif
1348  endif
1349  allocate(tile_id_local(num_tile))
1350 
1351 !These directives are a work-around for a bug in the CCE compiler, which
1352 !causes a segmentation fault when the compiler attempts to vectorize a
1353 !loop containing an optional argument (when -g is included).
1354 
1355 !DIR$ NOVECTOR
1356  do n = 1, num_tile
1357  if(PRESENT(tile_id)) then
1358  tile_id_local(n) = tile_id(n)
1359  else
1360  tile_id_local(n) = n
1361  endif
1362  enddo
1363 !DIR$ VECTOR
1364 
1365  tile_base = minval(tile_id_local) - 1
1366 
1367  do n = 1, num_tile
1368  if( pe .GE. pe_start(n) .AND. pe .LE. pe_end(n)) then
1369  pos = pos + 1
1370  domain%tile_id(pos) = tile_id_local(n)
1371  end if
1372  end do
1373 
1374  if (associated(domain%tile_id_all)) deallocate(domain%tile_id_all) !< Check if associated
1375  allocate(domain%tile_id_all(num_tile))
1376  domain%tile_id_all(:) = tile_id_local(:)
1377 
1378  domain%initialized = .true.
1379  domain%rotated_ninety = .false.
1380  domain%ntiles = num_tile
1381  domain%max_ntile_pe = maxval(ntile_per_pe)
1382  domain%ncontacts = num_contact
1383 
1384  deallocate(ntile_per_pe)
1385  !---call mpp_define_domain to define domain decomposition for each tile.
1386  allocate(tile_count(pes(0):pes(0)+nlist-1))
1387  tile_count = 0 ! tile number on current pe
1388 
1389  domain%tile_comm = mpi_comm_null
1390  do n = 1, num_tile
1391  allocate(mask(layout(1,n), layout(2,n)))
1392  allocate(pelist_tile(pe_start(n):pe_end(n)) )
1393  tile_count(pe_start(n)) = tile_count(pe_start(n)) + 1
1394  do m = pe_start(n), pe_end(n)
1395  pelist_tile(m) = m
1396  end do
1397  !--- set the tile communicator
1398  if (any(pelist_tile == pe)) then
1399  call mpp_declare_pelist(pelist_tile, comm=domain%tile_comm)
1400  endif
1401  mask = .true.
1402  if(present(maskmap)) mask = maskmap(1:layout(1,n), 1:layout(2,n), n)
1403  ndivx = layout(1,n); ndivy = layout(2,n)
1404  allocate(xext(ndivx), yext(ndivy))
1405  xext = 0; yext = 0
1406  if(present(xextent)) xext = xextent(1:ndivx,n)
1407  if(present(yextent)) yext = yextent(1:ndivy,n)
1408  ! when num_tile is one, we assume only folded_north and cyclic_x, cyclic_y boundary condition is the possible
1409  ! z1l: when we decide to support multiple-tile tripolar grid, we will redesign the following part.
1410  if(num_tile == 1) then
1411  flags_x = 0
1412  flags_y = 0
1413  if(PRESENT(xflags)) flags_x = xflags
1414  if(PRESENT(yflags)) flags_y = yflags
1415  do m = 1, num_contact
1416  if(istart1(m) == iend1(m) ) then ! x-direction contact, possible cyclic, folded-west or folded-east
1417  if(istart2(m) .NE. iend2(m) ) call mpp_error(fatal, &
1418  "mpp_domains_define: for one tile mosaic, when istart1=iend1, istart2 must equal iend2")
1419  if(istart1(m) == istart2(m) ) then ! folded west or folded east
1420  if(istart1(m) == global_indices(1,n) ) then
1421  if(.NOT. btest(flags_x,west) ) flags_x = flags_x + fold_west_edge
1422  else if(istart1(m) == global_indices(2,n) ) then
1423  if(.NOT. btest(flags_x,east) ) flags_x = flags_x + fold_east_edge
1424  else
1425  call mpp_error(fatal, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1426  "istart1 should equal global_indices(1) or global_indices(2)")
1427  endif
1428  else
1429  if(.NOT. btest(flags_x,cyclic)) flags_x = flags_x + cyclic_global_domain
1430  endif
1431  else if( jstart1(m) == jend1(m) ) then ! y-direction contact, cyclic, folded-south or folded-north
1432  if(jstart2(m) .NE. jend2(m) ) call mpp_error(fatal, &
1433  "mpp_domains_define: for one tile mosaic, when jstart1=jend1, jstart2 must equal jend2")
1434  if(jstart1(m) == jstart2(m) ) then ! folded south or folded north
1435  if(jstart1(m) == global_indices(3,n) ) then
1436  if(.NOT. btest(flags_y,south) ) flags_y = flags_y + fold_south_edge
1437  else if(jstart1(m) == global_indices(4,n) ) then
1438  if(.NOT. btest(flags_y,north) ) flags_y = flags_y + fold_north_edge
1439  else
1440  call mpp_error(fatal, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1441  "istart1 should equal global_indices(1) or global_indices(2)")
1442  endif
1443  else
1444  if(.NOT. btest(flags_y,cyclic)) flags_y = flags_y + cyclic_global_domain
1445  end if
1446  else
1447  call mpp_error(fatal, &
1448  "mpp_domains_define: for one tile mosaic, invalid boundary contact")
1449  end if
1450  end do
1451  call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, xflags = flags_x, &
1452  yflags = flags_y, whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, &
1453  xextent=xext, yextent=yext, maskmap=mask, name=name, symmetry=is_symmetry, &
1454  memory_size = memory_size, is_mosaic = .true., tile_id=tile_id_local(n))
1455  else
1456  call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, &
1457  whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, xextent=xext, yextent=yext, &
1458  maskmap=mask, name=name, symmetry=is_symmetry, memory_size = memory_size, &
1459  is_mosaic = .true., tile_count = tile_count(pe_start(n)), tile_id=tile_id_local(n), &
1460  complete = n==num_tile)
1461  end if
1462  deallocate(mask, xext, yext, pelist_tile)
1463  end do
1464 
1465  deallocate(pes, tile_count, tile_id_local)
1466 
1467  if(num_contact == 0 .OR. num_tile == 1) return
1468 
1469  !--- loop through each contact region and find the contact for each tile ( including alignment )
1470  !--- we assume the tiles list is continuous and starting from 1.
1471  allocate(is1(num_contact), ie1(num_contact), js1(num_contact), je1(num_contact) )
1472  allocate(is2(num_contact), ie2(num_contact), js2(num_contact), je2(num_contact) )
1473  allocate(isglist(num_tile), ieglist(num_tile), jsglist(num_tile), jeglist(num_tile) )
1474  allocate(align1(num_contact), align2(num_contact), refine1(num_contact), refine2(num_contact))
1475  !--- get the global domain for each tile
1476  do n = 1, num_tile
1477  isglist(n) = domain%tileList(n)%xbegin; ieglist(n) = domain%tileList(n)%xend
1478  jsglist(n) = domain%tileList(n)%ybegin; jeglist(n) = domain%tileList(n)%yend
1479  end do
1480 
1481  !--- transfer the contact index to domain index.
1482  nc = 0
1483  do n = 1, num_contact
1484  t1 = tile1(n) - tile_base
1485  t2 = tile2(n) - tile_base
1486  is1(n) = istart1(n) + isglist(t1) - 1; ie1(n) = iend1(n) + isglist(t1) - 1
1487  js1(n) = jstart1(n) + jsglist(t1) - 1; je1(n) = jend1(n) + jsglist(t1) - 1
1488  is2(n) = istart2(n) + isglist(t2) - 1; ie2(n) = iend2(n) + isglist(t2) - 1
1489  js2(n) = jstart2(n) + jsglist(t2) - 1; je2(n) = jend2(n) + jsglist(t2) - 1
1490  call check_alignment( is1(n), ie1(n), js1(n), je1(n), isglist(t1), ieglist(t1), jsglist(t1), &
1491  & jeglist(t1), align1(n))
1492  call check_alignment( is2(n), ie2(n), js2(n), je2(n), isglist(t2), ieglist(t2), jsglist(t2), &
1493  & jeglist(t2), align2(n))
1494  if( (align1(n) == west .or. align1(n) == east ) .NEQV. (align2(n) == west .or. align2(n) == east ) )&
1495  domain%rotated_ninety=.true.
1496  end do
1497 
1498  !--- calculate the refinement ratio between tiles
1499  do n = 1, num_contact
1500  n1 = max(abs(iend1(n) - istart1(n)), abs(jend1(n) - jstart1(n)) ) + 1
1501  n2 = max(abs(iend2(n) - istart2(n)), abs(jend2(n) - jstart2(n)) ) + 1
1502  refine1(n) = real(n2)/n1
1503  refine2(n) = real(n1)/n2
1504  end do
1505 
1506  whalosz = 0; ehalosz = 0; shalosz = 0; nhalosz = 0
1507  if(present(whalo)) whalosz = whalo
1508  if(present(ehalo)) ehalosz = ehalo
1509  if(present(shalo)) shalosz = shalo
1510  if(present(nhalo)) nhalosz = nhalo
1511  xhalosz = max(whalosz, ehalosz)
1512  yhalosz = max(shalosz, nhalosz)
1513 
1514  !--- computing the overlap for the contact region with halo size xhalosz and yhalosz
1515  call define_contact_point( domain, center, num_contact, tile1, tile2, align1, align2, refine1, refine2, &
1516  is1, ie1, js1, je1, is2, ie2, js2, je2, isglist, ieglist, jsglist, jeglist, tile_base )
1517 
1518  call set_contact_point( domain, corner )
1519  call set_contact_point( domain, east )
1520  call set_contact_point( domain, north )
1521 
1522  call set_domain_comm_inf(domain%update_T)
1523  call set_domain_comm_inf(domain%update_E)
1524  call set_domain_comm_inf(domain%update_C)
1525  call set_domain_comm_inf(domain%update_N)
1526 
1527 
1528  !--- goffset setting is needed for exact global sum
1529  do m = 1, size(domain%tile_id(:))
1530  tile = domain%tile_id(m)
1531  do n = 1, num_contact
1532  if( tile1(n) == tile ) then
1533  if(align1(n) == east ) domain%x(m)%goffset = 0
1534  if(align1(n) == north) domain%y(m)%goffset = 0
1535  end if
1536  if( tile2(n) == tile ) then
1537  if(align2(n) == east ) domain%x(m)%goffset = 0
1538  if(align2(n) == north) domain%y(m)%goffset = 0
1539  end if
1540  end do
1541  end do
1542  call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_mosaic")
1543  call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_mosaic")
1544  call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_mosaic")
1545  call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_mosaic")
1546 
1547  !--- set the overlapping for boundary check if domain is symmetry
1548  if(debug_update_level .NE. no_check) then
1549  call set_check_overlap( domain, corner )
1550  call set_check_overlap( domain, east )
1551  call set_check_overlap( domain, north )
1552  endif
1553  if(domain%symmetry) then
1554  if (associated(domain%bound_E)) deallocate(domain%bound_E) !< Check if associated
1555  if (associated(domain%bound_C)) deallocate(domain%bound_C) !< Check if associated
1556  if (associated(domain%bound_N)) deallocate(domain%bound_N) !< Check if associated
1557  allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1558  call set_bound_overlap( domain, corner )
1559  call set_bound_overlap( domain, east )
1560  call set_bound_overlap( domain, north )
1561  call check_overlap_pe_order(domain, domain%bound_C, trim(domain%name)//" bound_C")
1562  call check_overlap_pe_order(domain, domain%bound_E, trim(domain%name)//" bound_E")
1563  call check_overlap_pe_order(domain, domain%bound_N, trim(domain%name)//" bound_N")
1564  end if
1565 
1566  !--- check the send and recv size are matching.
1567  !--- currently only check T and C-cell. For ntiles>1 mosaic,
1568  !--- the check will be done in mpp_define_mosaic
1569  if(debug_message_passing) then
1570  send = .true.
1571  recv = .true.
1572  call check_message_size(domain, domain%update_T, send, recv, 'T')
1573  call check_message_size(domain, domain%update_C, send, recv, 'C')
1574  call check_message_size(domain, domain%update_E, send, recv, 'E')
1575  call check_message_size(domain, domain%update_N, send, recv, 'N')
1576  endif
1577 
1578 
1579  !--- release memory
1580  deallocate(align1, align2, is1, ie1, js1, je1, is2, ie2, js2, je2 )
1581  deallocate(isglist, ieglist, jsglist, jeglist, refine1, refine2 )
1582 
1583 
1584  end subroutine mpp_define_mosaic
1585 
1586 !#####################################################################
1587  !> Accessor function for value of mosaic_defined
1588  logical function mpp_mosaic_defined()
1589  mpp_mosaic_defined = mosaic_defined
1590  end function mpp_mosaic_defined
1591 !#####################################################################
1592 
1593  !> @brief Computes remote domain overlaps
1594  !!
1595  !> Assumes only one in each direction
1596  !! will calculate the overlapping for T,E,C,N-cell separately.
1597  subroutine compute_overlaps( domain, position, update, check, ishift, jshift, x_cyclic_offset, y_cyclic_offset, &
1598  whalo, ehalo, shalo, nhalo )
1599  type(domain2d), intent(inout) :: domain
1600  type(overlapspec), intent(inout), pointer :: update
1601  type(overlapspec), intent(inout), pointer :: check
1602  integer, intent(in) :: position, ishift, jshift
1603  integer, intent(in) :: x_cyclic_offset, y_cyclic_offset
1604  integer, intent(in) :: whalo, ehalo, shalo, nhalo
1605 
1606  integer :: i, m, n, nlist, tMe, tNbr, dir
1607  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
1608  integer :: isg, ieg, jsg, jeg, ioff, joff
1609  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
1610  integer :: ism, iem, jsm, jem
1611  integer :: is2, ie2, js2, je2
1612  integer :: is3, ie3, js3, je3
1613  integer :: isd3, ied3, jsd3, jed3
1614  integer :: isd2, ied2, jsd2, jed2
1615  logical :: folded, need_adjust_1, need_adjust_2, need_adjust_3, folded_north
1616  type(overlap_type) :: overlap
1617  type(overlap_type), pointer :: overlapList(:)=>null()
1618  type(overlap_type), pointer :: checkList(:)=>null()
1619  integer :: nsend, nrecv
1620  integer :: nsend_check, nrecv_check
1621  integer :: iunit
1622  logical :: set_check
1623 
1624  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
1625  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
1626  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
1627  if(size(domain%x(:)) > 1) return
1628 
1629  !--- if there is no halo, no need to compute overlaps.
1630  if(whalo==0 .AND. ehalo==0 .AND. shalo==0 .AND. nhalo==0) return
1631 
1632  !--- when there is only one tile, n will equal to np
1633  nlist = size(domain%list(:))
1634  set_check = .false.
1635  if(ASSOCIATED(check)) set_check = .true.
1636  allocate(overlaplist(maxlist) )
1637  if(set_check) allocate(checklist(maxlist) )
1638 
1639  !--- overlap is used to store the overlapping temporarily.
1640  call allocate_update_overlap( overlap, maxoverlap)
1641  !send
1642  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
1643  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
1644  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
1645 
1646  update%xbegin = ism; update%xend = iem
1647  update%ybegin = jsm; update%yend = jem
1648  if(set_check) then
1649  check%xbegin = ism; check%xend = iem
1650  check%ybegin = jsm; check%yend = jem
1651  endif
1652  update%whalo = whalo; update%ehalo = ehalo
1653  update%shalo = shalo; update%nhalo = nhalo
1654 
1655  ioff = ni - ishift
1656  joff = nj - jshift
1657  middle = (isg+ieg)/2+1
1658  tme = 1; tnbr = 1
1659  folded_north = btest(domain%fold,north)
1660  if( btest(domain%fold,south) .OR. btest(domain%fold,east) .OR. btest(domain%fold,west) ) then
1661  call mpp_error(fatal,"mpp_domains_define.inc(compute_overlaps): folded south, east or west boundary condition "&
1662  &//"is not supported, please use other version of compute_overlaps for "//trim(domain%name))
1663  endif
1664 
1665  nsend = 0
1666  nsend_check = 0
1667 
1668  do list = 0,nlist-1
1669  m = mod( domain%pos+list, nlist )
1670  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
1671  !to_pe's eastern halo
1672  dir = 1
1673  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
1674  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
1675  !--- to make sure the consistence between pes
1676  if( domain%symmetry .AND. (position == north .OR. position == corner ) &
1677  .AND. ( jsc == je .or. jec == js ) ) then
1678  !--- do nothing, this point will come from other pe
1679  else
1680  !--- when the north face is folded, the east halo point at right side domain will be folded.
1681  !--- the position should be on CORNER or NORTH
1682  if( je == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
1683  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1684  isg, ieg, dir, ishift, position, ioff, middle)
1685  else
1686  if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1687  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1688  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1689  else
1690  if( ie.GT.ieg ) then
1691  if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
1692  is = is-ioff; ie = ie-ioff
1693  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1694  end if
1695  end if
1696  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1697  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1698  endif
1699  endif
1700  end if
1701 
1702  !to_pe's SE halo
1703  dir = 2
1704  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
1705  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1706  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1707  !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
1708  !--- the other part is both are zero.
1709  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1710  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1711  if(je .LT. jsg) then ! js .LT. jsg
1712  if( domain%y(tme)%cyclic ) then
1713  js = js + joff; je = je + joff
1714  endif
1715  else if(js .Lt. jsg) then ! split into two parts
1716  if( domain%y(tme)%cyclic ) then
1717  js2 = js + joff; je2 = jsg-1+joff
1718  js = jsg;
1719  endif
1720  endif
1721  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1722  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1723  if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1724  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1725  else
1726  if( ie.GT.ieg )then
1727  if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
1728  is = is-ioff; ie = ie-ioff
1729  need_adjust_1 = .false.
1730  if(jsg .GT. js) then
1731  if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1732  js = js+joff; je = je+joff
1733  need_adjust_2 = .false.
1734  if(x_cyclic_offset .NE. 0) then
1735  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1736  else if(y_cyclic_offset .NE. 0) then
1737  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1738  end if
1739  end if
1740  else
1741  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1742  need_adjust_3 = .false.
1743  end if
1744  end if
1745  end if
1746  if( need_adjust_3 .AND. jsg.GT.js )then
1747  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1748  js = js+joff; je = je+joff
1749  if(need_adjust_1 .AND. ie.LE.ieg) then
1750  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1751  end if
1752  end if
1753  end if
1754  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1755  endif
1756 
1757  !to_pe's southern halo
1758  dir = 3
1759  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
1760  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1761  js2 = 0; je2 = -1
1762  if( jsg.GT.je )then ! jsg .GT. js
1763  if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1764  js = js+joff; je = je+joff
1765  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1766  end if
1767  else if (jsg .GT. js) then ! split into two parts
1768  if( domain%y(tme)%cyclic) then
1769  js2 = js + joff; je2 = jsg-1+joff
1770  js = jsg
1771  endif
1772  end if
1773 
1774  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1775  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1776  if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1777  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1778 
1779  !to_pe's SW halo
1780  dir = 4
1781  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1782  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1783  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1784  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1785  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1786  if(je .LT. jsg) then ! js .LT. jsg
1787  if( domain%y(tme)%cyclic ) then
1788  js = js + joff; je = je + joff
1789  endif
1790  else if(js .Lt. jsg) then ! split into two parts
1791  if( domain%y(tme)%cyclic ) then
1792  js2 = js + joff; je2 = jsg-1+joff
1793  js = jsg;
1794  endif
1795  endif
1796  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1797  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1798  if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1799  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1800  else
1801  if( isg.GT.is )then
1802  if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1803  is = is+ioff; ie = ie+ioff
1804  need_adjust_1 = .false.
1805  if(jsg .GT. js) then
1806  if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1807  js = js+joff; je = je+joff
1808  need_adjust_2 = .false.
1809  if(x_cyclic_offset .NE. 0) then
1810  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1811  else if(y_cyclic_offset .NE. 0) then
1812  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1813  end if
1814  end if
1815  else
1816  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1817  need_adjust_3 = .false.
1818  end if
1819  end if
1820  end if
1821  if( need_adjust_3 .AND. jsg.GT.js )then
1822  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1823  js = js+joff; je = je+joff
1824  if(need_adjust_1 .AND. isg.LE.is )then
1825  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1826  end if
1827  end if
1828  end if
1829  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1830  endif
1831 
1832  !to_pe's western halo
1833  dir = 5
1834  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1835  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
1836 
1837  !--- when the north face is folded, some point at j=nj will be folded.
1838  !--- the position should be on CORNER or NORTH
1839  if( je == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
1840  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1841  isg, ieg, dir, ishift, position, ioff, middle)
1842  else
1843  if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1844  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1845  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1846  else
1847  if( isg.GT.is )then
1848  if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1849  is = is+ioff; ie = ie+ioff
1850  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1851  endif
1852  end if
1853  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1854  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1855  end if
1856  end if
1857 
1858  !to_pe's NW halo
1859  dir = 6
1860  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1861  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
1862  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1863  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
1864  folded = .false.
1865  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1866  if(js .GT. jeg) then ! je > jeg
1867  if( domain%y(tme)%cyclic ) then
1868  js = js-joff; je = je-joff
1869  else if(folded_north )then
1870  folded = .true.
1871  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1872  endif
1873  else if(je .GT. jeg) then ! split into two parts
1874  if( domain%y(tme)%cyclic ) then
1875  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1876  js = jeg+1-joff; je = je -joff
1877  else if(folded_north) then
1878  folded = .true.
1879  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1880  js = jeg+1
1881  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1882  if( is .GT. ieg) then
1883  is = is - ioff; ie = ie - ioff
1884  else if( ie .GT. ieg ) then
1885  is3 = is; ie3 = ieg; js3 = js; je3 = je
1886  is = ieg+1-ioff; ie = ie - ioff
1887  endif
1888  endif
1889  endif
1890 
1891  if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
1892  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1893  isg, ieg, dir, ishift, position, ioff, middle)
1894  else
1895  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1896  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
1897  endif
1898  if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
1899  isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
1900  if(ie2 .GE. is2) then
1901  if(je2 == jeg .AND. jec == jeg .AND. folded_north.AND.(position == corner .OR. position == north))then
1902  call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1903  isg, ieg, dir, ishift, position, ioff, middle)
1904  else
1905  call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1906  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1907  endif
1908  endif
1909  else
1910  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1911  if( isg.GT.is )then
1912  if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1913  is = is+ioff; ie = ie+ioff
1914  need_adjust_1 = .false.
1915  if(je .GT. jeg) then
1916  if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1917  js = js-joff; je = je-joff
1918  need_adjust_2 = .false.
1919  if(x_cyclic_offset .NE. 0) then
1920  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1921  else if(y_cyclic_offset .NE. 0) then
1922  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1923  end if
1924  end if
1925  else
1926  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1927  need_adjust_3 = .false.
1928  end if
1929  end if
1930  end if
1931  folded = .false.
1932  if( need_adjust_3 .AND. je.GT.jeg )then
1933  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1934  js = js-joff; je = je-joff
1935  if( need_adjust_1 .AND. isg.LE.is)then
1936  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1937  end if
1938  else if( folded_north )then
1939  folded = .true.
1940  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1941  end if
1942  end if
1943  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1944  isg, ieg, jsg, jeg, dir)
1945  endif
1946 
1947 
1948  !to_pe's northern halo
1949  dir = 7
1950  folded = .false.
1951  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
1952  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
1953 
1954  !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
1955  !--- no need to send, because the data on that point will come from other pe.
1956  !--- come from two pe ( there will be only one point on one pe. ).
1957  if( domain%symmetry .AND. (position == east .OR. position == corner ) &
1958  .AND. ( isc == ie .or. iec == is ) .AND. (.not. folded_north) ) then
1959  !--- do nothing, this point will come from other pe
1960  else
1961  js2 = -1; je2 = 0
1962  if( js .GT. jeg) then ! je .GT. jeg
1963  if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1964  js = js-joff; je = je-joff
1965  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1966  else if( folded_north )then
1967  folded = .true.
1968  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1969  end if
1970  else if( je.GT.jeg )then ! split into two parts
1971  if( domain%y(tme)%cyclic)then !try cyclic offset
1972  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1973  js = jeg+1-joff; je = je - joff
1974  else if( folded_north )then
1975  folded = .true.
1976  is2 = is; ie2 = ie; js2 = js; je2 = jeg
1977  js = jeg+1;
1978  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1979  end if
1980  end if
1981  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1982  if( je == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
1983  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1984  isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1985  else
1986  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1987  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, domain%symmetry)
1988  endif
1989  else
1990  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1991  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1992  endif
1993 
1994  if(ie2 .GE. is2) then
1995  if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
1996  call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1997  isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1998  else
1999  call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2000  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
2001  endif
2002  endif
2003  end if
2004 
2005  !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2006  if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2007 ! is = is + ioff
2008 ! call insert_update_overlap( overlap, domain%list(m)%pe, &
2009 ! is, is, js, je, isc, iec, jsc, jec, dir, folded)
2010 !??? if(je2 .GE. js2)call insert_update_overlap( overlap, domain%list(m)%pe, &
2011 ! is, is, js2, je2, isc, iec, jsc, jec, dir, folded)
2012  endif
2013 
2014  !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2015  !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2016  !--- only position at NORTH and CORNER need to be considered
2017  if( folded_north .AND. (position == north .OR. position == corner) &
2018  .AND. domain%x(tme)%pos .LT. (size(domain%x(tme)%list(:))+1)/2 ) then
2019  if( domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .GE. jeg .AND. isc .LE. middle)then
2020  js = jeg; je = jeg
2021  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
2022  is = max(is, middle)
2023  select case (position)
2024  case(north)
2025  i=is; is = isg+ieg-ie; ie = isg+ieg-i
2026  case(corner)
2027  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2028  end select
2029  call insert_update_overlap(overlap, domain%list(m)%pe, &
2030  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
2031  endif
2032  if(debug_update_level .NE. no_check .AND. set_check) then
2033  je = domain%list(m)%y(tnbr)%compute%end+jshift;
2034  if(je == jeg) then
2035  is = max(is, isc); ie = min(ie, iec)
2036  js = max(js, jsc); je = min(je, jec)
2037  if(ie.GE.is .AND. je.GE.js )then
2038  nsend_check = nsend_check+1
2039  if(nsend_check > size(checklist(:)) ) then
2040  call expand_check_overlap_list(checklist, nlist)
2041  endif
2042  call allocate_check_overlap(checklist(nsend_check), 1)
2043  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
2044  tme, 4, one_hundred_eighty, is, ie, js, je)
2045  end if
2046  end if
2047  endif
2048  endif
2049 
2050  !to_pe's NE halo
2051  dir = 8
2052  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
2053  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
2054  is2 = 0; ie2=-1; js2=0; je2=-1
2055  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2056  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2057  folded = .false.
2058  if(js .GT. jeg) then ! je > jeg
2059  if( domain%y(tme)%cyclic ) then
2060  js = js-joff; je = je-joff
2061  else if(folded_north )then
2062  folded = .true.
2063  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2064  endif
2065  else if(je .GT. jeg) then ! split into two parts
2066  if( domain%y(tme)%cyclic ) then
2067  is2 = is; ie2 = ie; js2 = js; je2 = jeg
2068  js = jeg+1-joff; je = je -joff
2069  else if(folded_north) then
2070  folded = .true.
2071  is2 = is; ie2 = ie; js2 = js; je2 = jeg
2072  js = jeg+1
2073  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2074 
2075  if( ie .LT. isg )then
2076  is = is+ioff; ie = ie+ioff
2077  else if( is .LT. isg) then
2078  is3 = isg; ie3 = ie; js3 = js; je3 = je
2079  is = is+ioff; ie = isg-1+ioff;
2080  endif
2081  endif
2082  endif
2083  if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
2084  call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2085  isg, ieg, dir, ishift, position, ioff, middle)
2086  else
2087  call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2088  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2089  endif
2090  if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
2091  isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2092  if(ie2 .GE. is2) then
2093  if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
2094  call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2095  isg, ieg, dir, ishift, position, ioff, middle)
2096  else
2097  call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2098  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2099  endif
2100  endif
2101  else
2102  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2103  if( ie.GT.ieg )then
2104  if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
2105  is = is-ioff; ie = ie-ioff
2106  need_adjust_1 = .false.
2107  if(je .GT. jeg) then
2108  if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
2109  js = js-joff; je = je-joff
2110  need_adjust_2 = .false.
2111  if(x_cyclic_offset .NE. 0) then
2112  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2113  else if(y_cyclic_offset .NE. 0) then
2114  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2115  end if
2116  end if
2117  else
2118  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2119  need_adjust_3 = .false.
2120  end if
2121  end if
2122  end if
2123  folded = .false.
2124  if( need_adjust_3 .AND. je.GT.jeg )then
2125  if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
2126  js = js-joff; je = je-joff
2127  if( need_adjust_1 .AND. ie.LE.ieg)then
2128  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2129  end if
2130  else if( folded_north )then
2131  folded = .true.
2132  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2133  end if
2134  end if
2135  call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2136  isg, ieg, jsg, jeg, dir)
2137  endif
2138  endif
2139 
2140  !--- copy the overlapping information
2141  if( overlap%count > 0) then
2142  nsend = nsend + 1
2143  if(nsend > size(overlaplist(:)) ) then
2144  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps): overlapList for send is expanded')
2145  call expand_update_overlap_list(overlaplist, nlist)
2146  endif
2147  call add_update_overlap( overlaplist(nsend), overlap)
2148  call init_overlap_type(overlap)
2149  endif
2150  end do ! end of send set up.
2151 
2152  if(debug_message_passing) then
2153  !--- write out send information
2154  iunit = mpp_pe() + 1000
2155  do m =1,nsend
2156  write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
2157  do n = 1, overlaplist(m)%count
2158  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
2159  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
2160  enddo
2161  enddo
2162  if(nsend >0) flush(iunit)
2163  endif
2164 
2165  ! copy the overlapping information into domain data structure
2166  if(nsend>0) then
2167  if (associated(update%send)) deallocate(update%send) !< Check if associated
2168  allocate(update%send(nsend))
2169  update%nsend = nsend
2170  do m = 1, nsend
2171  call add_update_overlap( update%send(m), overlaplist(m) )
2172  enddo
2173  endif
2174 
2175  if(nsend_check>0) then
2176  check%nsend = nsend_check
2177  if (associated(check%send)) deallocate(check%send) !< Check if associated
2178  allocate(check%send(nsend_check))
2179  do m = 1, nsend_check
2180  call add_check_overlap( check%send(m), checklist(m) )
2181  enddo
2182  endif
2183 
2184  do m = 1,size(overlaplist(:))
2185  call deallocate_overlap_type(overlaplist(m))
2186  enddo
2187 
2188  if(debug_update_level .NE. no_check .AND. set_check) then
2189  do m = 1,size(checklist(:))
2190  call deallocate_overlap_type(checklist(m))
2191  enddo
2192  endif
2193 
2194  isgd = isg - domain%whalo
2195  iegd = ieg + domain%ehalo
2196  jsgd = jsg - domain%shalo
2197  jegd = jeg + domain%nhalo
2198 
2199  ! begin setting up recv
2200  nrecv = 0
2201  nrecv_check = 0
2202  do list = 0,nlist-1
2203  m = mod( domain%pos+nlist-list, nlist )
2204  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
2205  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
2206  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
2207  !recv_e
2208  dir = 1
2209  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2210  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
2211  is=isc; ie=iec; js=jsc; je=jec
2212  if( domain%symmetry .AND. (position == north .OR. position == corner ) &
2213  .AND. ( jsd == je .or. jed == js ) ) then
2214  ! --- do nothing, this point will come from other pe
2215  else
2216  !--- when the north face is folded, the east halo point at right side domain will be folded.
2217  !--- the position should be on CORNER or NORTH
2218  if( jed == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
2219  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2220  isg, ieg, dir, ishift, position, ioff, middle)
2221  else
2222  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2223  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2224  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2225  else
2226  if( ied.GT.ieg )then
2227  if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2228  is = is+ioff; ie = ie+ioff
2229  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2230  end if
2231  end if
2232  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2233  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2234  endif
2235  endif
2236  endif
2237 
2238  !recv_se
2239  dir = 2
2240  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2241  jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2242  is=isc; ie=iec; js=jsc; je=jec
2243  !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
2244  !--- the other part is both are zero.
2245  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2246  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2247  if(jed .LT. jsg) then ! then jsd < jsg
2248  if( domain%y(tme)%cyclic ) then
2249  js = js-joff; je = je-joff
2250  endif
2251  else if(jsd .LT. jsg) then !split into two parts
2252  if( domain%y(tme)%cyclic ) then
2253  js2 = js-joff; je2 = je-joff
2254  endif
2255  endif
2256  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2257  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2258  if(je2 .GE. js2) call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2259  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2260  else
2261  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2262  if( jsd.LT.jsg )then
2263  if( domain%y(tme)%cyclic .AND. js.GT.jed )then !try cyclic offset
2264  js = js-joff; je = je-joff
2265  need_adjust_1 = .false.
2266  if( ied.GT.ieg )then
2267  if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2268  is = is+ioff; ie = ie+ioff
2269  need_adjust_2 = .false.
2270  if(x_cyclic_offset .NE. 0) then
2271  call apply_cyclic_offset(js, je, x_cyclic_offset, jsgd, jeg, nj)
2272  else if(y_cyclic_offset .NE. 0) then
2273  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, iegd, ni)
2274  end if
2275  end if
2276  else
2277  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2278  need_adjust_3 = .false.
2279  end if
2280  end if
2281  end if
2282  if( need_adjust_3 .AND. ied.GT.ieg )then
2283  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2284  is = is+ioff; ie = ie+ioff
2285  if( need_adjust_1 .AND. jsd.GE.jsg )then
2286  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2287  end if
2288  end if
2289  end if
2290  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2291  isg, ieg, jsg, jeg, dir)
2292  endif
2293 
2294  !recv_s
2295  dir = 3
2296  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
2297  jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2298  is=isc; ie=iec; js=jsc; je=jec
2299  js2 = 0; je2 = -1
2300  if( jed .LT. jsg) then ! jsd < jsg
2301  if( domain%y(tme)%cyclic ) then
2302  js = js-joff; je = je-joff
2303  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2304  endif
2305  else if( jsd.LT.jsg )then ! split into two parts
2306  if( domain%y(tme)%cyclic)then !try cyclic offset
2307  js2 = js-joff; je2 = je-joff
2308  end if
2309  end if
2310  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2311  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2312  if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2313  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2314 
2315  !recv_sw
2316  dir = 4
2317  isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2318  jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2319  is=isc; ie=iec; js=jsc; je=jec
2320  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2321  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2322  if( ied.LT.isg )then ! isd < isg
2323  if( domain%x(tme)%cyclic ) then
2324  is = is-ioff; ie = ie-ioff
2325  endif
2326  else if (isd.LT.isg )then ! split into two parts
2327  if( domain%x(tme)%cyclic ) then
2328  is2 = is-ioff; ie2 = ie-ioff
2329  endif
2330  endif
2331  if( jed.LT.jsg )then ! jsd < jsg
2332  if( domain%y(tme)%cyclic ) then
2333  js = js-joff; je = je-joff
2334  endif
2335  else if( jsd.LT.jsg )then ! split into two parts
2336  if( domain%y(tme)%cyclic ) then
2337  js2 = js-joff; je2 = je-joff
2338  endif
2339  endif
2340  else
2341  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2342  if( jsd.LT.jsg )then
2343  if( domain%y(tme)%cyclic .AND. js.GT.jed )then !try cyclic offset
2344  js = js-joff; je = je-joff
2345  need_adjust_1 = .false.
2346  if( isd.LT.isg )then
2347  if( domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2348  is = is-ioff; ie = ie-ioff
2349  need_adjust_2 = .false.
2350  if(x_cyclic_offset .NE. 0) then
2351  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsgd, jeg, nj)
2352  else if(y_cyclic_offset .NE. 0) then
2353  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isgd, ieg, ni)
2354  end if
2355  end if
2356  else
2357  call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2358  need_adjust_3 = .false.
2359  end if
2360  end if
2361  end if
2362  if( need_adjust_3 .AND. isd.LT.isg )then
2363  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2364  is = is-ioff; ie = ie-ioff
2365  if(need_adjust_1 .AND. jsd.GE.jsg) then
2366  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2367  end if
2368  end if
2369  end if
2370  endif
2371  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2372  isg, ieg, jsg, jeg, dir)
2373 
2374  if(ie2 .GE. is2)call fill_overlap(overlap, domain, m, is2, ie2, js, je, isd, ied, jsd, jed, &
2375  isg, ieg, jsg, jeg, dir)
2376  if(je2 .GE. js2)call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2377  isg, ieg, jsg, jeg, dir)
2378 
2379  if(ie2 .GE. is2 .AND. je2 .GE. js2)call fill_overlap(overlap, domain, m, is2, ie2, js2, je2, isd, ied, jsd, &
2380  & jed, isg, ieg, jsg, jeg, dir)
2381 
2382 
2383  !recv_w
2384  dir = 5
2385  isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2386  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
2387  is=isc; ie=iec; js=jsc; je=jec
2388 
2389  !--- when the north face is folded, some point at j=nj will be folded.
2390  !--- the position should be on CORNER or NORTH
2391  if( jed == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
2392  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2393  isg, ieg, dir, ishift, position, ioff, middle)
2394  else
2395  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2396  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2397  isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
2398  else
2399  if( isd.LT.isg )then
2400  if( domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2401  is = is-ioff; ie = ie-ioff
2402  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2403  end if
2404  end if
2405  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2406  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2407  endif
2408  endif
2409 
2410  !recv_nw
2411  dir = 6
2412  folded = .false.
2413  isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2414  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2415  is=isc; ie=iec; js=jsc; je=jec
2416  is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2417  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2418  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2419  js2 = -1; je2 = 0
2420  if( jsd .GT. jeg ) then ! jed > jeg
2421  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2422  js = js+joff; je = je+joff
2423  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2424  else if( folded_north )then
2425  folded = .true.
2426  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2427  end if
2428  else if( jed.GT.jeg )then ! split into two parts
2429  if( domain%y(tme)%cyclic)then !try cyclic offset
2430  is2 = is; ie2 = ie; js2 = js; je2 = je
2431  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2432  js = js + joff; je = je + joff
2433  jsd = jeg+1
2434  else if( folded_north )then
2435  folded = .true.
2436  is2 = is; ie2 = ie; js2 = js; je2 = je
2437  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2438  jsd = jeg+1
2439  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2440  if(isd < isg .and. ied .GE. isg .and. domain%symmetry) then
2441  isd3 = isd; ied3 = isg-1
2442  jsd3 = jsd; jed3 = jed
2443  is3 = is-ioff; ie3=ie-ioff
2444  js3 = js; je3 = je
2445  isd = isg;
2446  endif
2447  end if
2448  endif
2449 
2450  if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2451  .AND. (position == corner .OR. position == north)) then
2452  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2453  isg, ieg, dir, ishift, position, ioff, middle)
2454  else
2455  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2456  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2457  endif
2458 
2459  if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2460  & jed3, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2461 
2462  if(ie2 .GE. is2) then
2463  if( jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2464  .AND. (position == corner .OR. position == north)) then
2465  call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2466  isg, ieg, dir, ishift, position, ioff, middle)
2467  else
2468  call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2469  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2470  endif
2471  endif
2472  else
2473  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2474  if( jed.GT.jeg )then
2475  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2476  js = js+joff; je = je+joff
2477  need_adjust_1 = .false.
2478  if( isd.LT.isg )then
2479  if( domain%x(tme)%cyclic .AND. is.GE.ied )then !try cyclic offset
2480  is = is-ioff; ie = ie-ioff
2481  need_adjust_2 = .false.
2482  if(x_cyclic_offset .NE. 0) then
2483  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jegd, nj)
2484  else if(y_cyclic_offset .NE. 0) then
2485  call apply_cyclic_offset(is, ie, y_cyclic_offset, isgd, ieg, ni)
2486  end if
2487  end if
2488  else
2489  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2490  need_adjust_3 = .false.
2491  end if
2492  else if( folded_north )then
2493  folded = .true.
2494  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2495  end if
2496  end if
2497  if( need_adjust_3 .AND. isd.LT.isg )then
2498  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. is.GE.ied )then !try cyclic offset
2499  is = is-ioff; ie = ie-ioff
2500  if( need_adjust_1 .AND. jed.LE.jeg )then
2501  call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2502  end if
2503  end if
2504  end if
2505  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2506  isg, ieg, jsg, jeg, dir)
2507  endif
2508 
2509  !--- when north edge is folded, is will be less than isg when position is EAST and CORNER
2510  if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2511  is = is + ioff
2512  call insert_update_overlap(overlap, domain%list(m)%pe, &
2513  is, is, js, je, isd, ied, jsd, jed, dir, folded )
2514  endif
2515 
2516  !recv_n
2517  dir = 7
2518  folded = .false.
2519  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
2520  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2521  is=isc; ie=iec; js=jsc; je=jec
2522 
2523  !--- when domain symmetry and position is EAST or CORNER, the point at i=isd will
2524  !--- come from two pe ( there will be only one point on one pe. ).
2525  if( domain%symmetry .AND. (position == east .OR. position == corner ) &
2526  .AND. (isd == ie .or. ied == is ) .AND. (.not. folded_north) ) then
2527  !--- do nothing, this point will come from other pe
2528  else
2529  js2 = -1; je2 = 0
2530  if( jsd .GT. jeg ) then ! jed > jeg
2531  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2532  js = js+joff; je = je+joff
2533  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2534  else if( folded_north )then
2535  folded = .true.
2536  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2537  end if
2538  else if( jed.GT.jeg )then ! split into two parts
2539  if( domain%y(tme)%cyclic)then !try cyclic offset
2540  is2 = is; ie2 = ie; js2 = js; je2 = je
2541  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2542  js = js + joff; je = je + joff
2543  jsd = jeg+1
2544  else if( folded_north )then
2545  folded = .true.
2546  is2 = is; ie2 = ie; js2 = js; je2 = je
2547  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2548  jsd = jeg+1
2549  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2550  end if
2551  end if
2552  if(x_cyclic_offset == 0 .and. y_cyclic_offset == 0) then
2553  if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2554  .AND. (position == corner .OR. position == north)) then
2555  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2556  isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2557  else
2558  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2559  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, symmetry=domain%symmetry)
2560  endif
2561  else
2562  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2563  isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2564  endif
2565  if(ie2 .GE. is2) then
2566  if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2567  .AND. (position == corner .OR. position == north)) then
2568  call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2569  isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2570  else
2571  call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2572  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, symmetry=domain%symmetry)
2573  endif
2574  endif
2575  endif
2576 
2577  !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2578  if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2579 ! is = is + ioff
2580 ! call insert_update_overlap( overlap, domain%list(m)%pe, &
2581 ! is, is, js, je, isd, ied, jsd, jed, dir, folded)
2582  endif
2583 
2584  !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2585  !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2586  !--- only position at NORTH and CORNER need to be considered
2587 
2588  if( folded_north .AND. (position == north .OR. position == corner) &
2589  .AND. domain%x(tme)%pos .GE. size(domain%x(tme)%list(:))/2) then
2590  if( jed .GE. jeg .AND. ied .GE. middle)then
2591  jsd = jeg; jed = jeg
2592  is=isc; ie=iec; js = jsc; je = jec
2593  isd = max(isd, middle)
2594  select case (position)
2595  case(north)
2596  i=is; is = isg+ieg-ie; ie = isg+ieg-i
2597  case(corner)
2598  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2599  end select
2600  call insert_update_overlap(overlap, domain%list(m)%pe, &
2601  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
2602  endif
2603  if(debug_update_level .NE. no_check .AND. set_check) then
2604  jsd = domain%y(tme)%compute%end+jshift; jed = jsd
2605  if(jed == jeg) then
2606  is = max(is, isd); ie = min(ie, ied)
2607  js = max(js, jsd); je = min(je, jed)
2608  if(ie.GE.is .AND. je.GE.js )then
2609  nrecv_check = nrecv_check+1
2610  if(nrecv_check > size(checklist(:)) ) then
2611  call expand_check_overlap_list(checklist, nlist)
2612  endif
2613  call allocate_check_overlap(checklist(nrecv_check), 1)
2614  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
2615  tme, 4, one_hundred_eighty, is, ie, js, je)
2616  end if
2617  end if
2618  endif
2619 
2620  endif
2621 
2622  !recv_ne
2623  dir = 8
2624  folded = .false.
2625  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2626  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2627  is=isc; ie=iec; js=jsc; je=jec
2628  is2 = 0; ie2=-1; js2=0; je2=-1
2629  is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2630  if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2631  js2 = -1; je2 = 0
2632  if( jsd .GT. jeg ) then ! jed > jeg
2633  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2634  js = js+joff; je = je+joff
2635  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2636  else if( folded_north )then
2637  folded = .true.
2638  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2639  end if
2640  else if( jed.GT.jeg )then ! split into two parts
2641  if( domain%y(tme)%cyclic)then !try cyclic offset
2642  is2 = is; ie2 = ie; js2 = js; je2 = je
2643  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2644  js = js + joff; je = je + joff
2645  jsd = jeg+1
2646  else if( folded_north )then
2647  folded = .true.
2648  is2 = is; ie2 = ie; js2 = js; je2 = je
2649  isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2650  jsd = jeg+1
2651  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2652  if(ied > ieg .and. isd .LE. ieg .and. domain%symmetry) then
2653  isd3 = ieg+1; ied3 = ied
2654  jsd3 = jsd; jed3 = jed
2655  is3 = is+ioff; ie3=ie+ioff
2656  js3 = js; je3 = je
2657  ied = ieg;
2658  endif
2659  end if
2660  endif
2661  if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2662  .AND. (position == corner .OR. position == north)) then
2663  call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2664  isg, ieg, dir, ishift, position, ioff, middle)
2665  else
2666  call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2667  isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2668  endif
2669  if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2670  & jed3, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2671  if(ie2 .GE. is2) then
2672  if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2673  .AND. (position == corner .OR. position == north)) then
2674  call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2675  isg, ieg, dir, ishift, position, ioff, middle)
2676  else
2677  call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2678  isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2679  endif
2680  endif
2681  else
2682  need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2683  if( jed.GT.jeg )then
2684  if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2685  js = js+joff; je = je+joff
2686  need_adjust_1 = .false.
2687  if( ied.GT.ieg )then
2688  if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2689  is = is+ioff; ie = ie+ioff
2690  need_adjust_2 = .false.
2691  if(x_cyclic_offset .NE. 0) then
2692  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jegd, nj)
2693  else if(y_cyclic_offset .NE. 0) then
2694  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, iegd, ni)
2695  end if
2696  end if
2697  else
2698  call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2699  need_adjust_3 = .false.
2700  end if
2701  else if( folded_north )then
2702  folded = .true.
2703  call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2704  end if
2705  end if
2706  if( need_adjust_3 .AND. ied.GT.ieg )then
2707  if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2708  is = is+ioff; ie = ie+ioff
2709  if( need_adjust_1 .AND. jed.LE.jeg)then
2710  call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2711  end if
2712  end if
2713  end if
2714  call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2715  isg, ieg, jsg, jeg, dir)
2716  endif
2717  endif
2718 
2719  !--- copy the overlapping information
2720  if( overlap%count > 0) then
2721  nrecv = nrecv + 1
2722  if(nrecv > size(overlaplist(:)) )then
2723  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps): overlapList for recv is expanded')
2724  call expand_update_overlap_list(overlaplist, nlist)
2725  endif
2726  call add_update_overlap( overlaplist(nrecv), overlap)
2727  call init_overlap_type(overlap)
2728  endif
2729  enddo ! end of recv do loop
2730 
2731  if(debug_message_passing) then
2732  !--- write out send information
2733  iunit = mpp_pe() + 1000
2734  do m =1,nrecv
2735  write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
2736  do n = 1, overlaplist(m)%count
2737  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
2738  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
2739  enddo
2740  enddo
2741  if(nrecv >0) flush(iunit)
2742  endif
2743 
2744  ! copy the overlapping information into domain
2745  if(nrecv>0) then
2746  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
2747  allocate(update%recv(nrecv))
2748  update%nrecv = nrecv
2749  do m = 1, nrecv
2750  call add_update_overlap( update%recv(m), overlaplist(m) )
2751  do n = 1, update%recv(m)%count
2752  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
2753  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
2754  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
2755  endif
2756  enddo
2757  enddo
2758  endif
2759 
2760  if(nrecv_check>0) then
2761  check%nrecv = nrecv_check
2762  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
2763  allocate(check%recv(nrecv_check))
2764  do m = 1, nrecv_check
2765  call add_check_overlap( check%recv(m), checklist(m) )
2766  enddo
2767  endif
2768 
2769  call deallocate_overlap_type(overlap)
2770  do m = 1,size(overlaplist(:))
2771  call deallocate_overlap_type(overlaplist(m))
2772  enddo
2773 
2774  if(debug_update_level .NE. no_check .AND. set_check) then
2775  do m = 1,size(checklist(:))
2776  call deallocate_overlap_type(checklist(m))
2777  enddo
2778  endif
2779 
2780  deallocate(overlaplist)
2781  if(set_check) deallocate(checklist)
2782  domain%initialized = .true.
2783 
2784  end subroutine compute_overlaps
2785 
2786 
2787  subroutine fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2788  isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2789  type(overlap_type), intent(inout) :: overlap
2790  type(domain2d), intent(inout) :: domain
2791  integer, intent(in ) :: m, is, ie, js, je
2792  integer, intent(in ) :: isc, iec, jsc, jec
2793  integer, intent(in ) :: isg, ieg, dir, ioff
2794  logical, intent(in ) :: is_cyclic
2795  logical, optional, intent(in ) :: folded, symmetry
2796 
2797  call insert_update_overlap( overlap, domain%list(m)%pe, &
2798  is, ie, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2799  if(is_cyclic) then
2800  if(ie .GT. ieg) 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  else if( is .LT. isg ) then
2804  call insert_update_overlap( overlap, domain%list(m)%pe, &
2805  is+ioff, ie+ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2806  endif
2807  endif
2808 
2809  end subroutine fill_overlap_send_nofold
2810  !##################################################################################
2811  subroutine fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2812  isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2813  type(overlap_type), intent(inout) :: overlap
2814  type(domain2d), intent(inout) :: domain
2815  integer, intent(in ) :: m, is, ie, js, je
2816  integer, intent(in ) :: isc, iec, jsc, jec
2817  integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2818  logical, optional, intent(in ) :: symmetry
2819  integer :: is1, ie1, is2, ie2, i
2820 
2821  !--- consider at j = jeg for west edge.
2822  !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2823  if(position == corner .AND. .NOT. domain%symmetry .AND. is .LE. isg-1 .AND. ie .GE. isg-1) then
2824  call insert_update_overlap(overlap, domain%list(m)%pe, &
2825  isg-1+ioff, isg-1+ioff, je, je, isc, iec, jsc, jec, dir, .true.)
2826  end if
2827 
2828  is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2829  !--- east edge
2830  if( is > ieg ) then
2831  is2 = is-ioff; ie2 = ie-ioff
2832  else if( ie > ieg ) then ! split into two parts
2833  is1 = is; ie1 = ieg
2834  is2 = ieg+1-ioff; ie2 = ie-ioff
2835  else if( is .GE. middle ) then
2836  is1 = is; ie1 = ie
2837  else if( ie .GE. middle ) then ! split into two parts
2838  is1 = middle; ie1 = ie
2839  is2 = is; ie2 = middle-1
2840  else if( ie < isg ) then ! west boundary
2841  is1 = is+ieg-isg+1-ishift; ie1 = ie+ieg-isg+1-ishift
2842  else if( is < isg ) then ! split into two parts
2843  is1 = is+ieg-isg+1-ishift; ie1 = isg-1+ieg-isg+1-ishift
2844  is2 = isg; ie2 = ie
2845  else
2846  is2 = is; ie2 = ie
2847  endif
2848 
2849  if( ie1 .GE. is1) then
2850  call insert_update_overlap( overlap, domain%list(m)%pe, &
2851  is1, ie1, js, je-1, isc, iec, jsc, jec, dir, symmetry=symmetry)
2852 
2853  select case (position)
2854  case(north)
2855  i=is1; is1 = isg+ieg-ie1; ie1 = isg+ieg-i
2856  case(corner)
2857  i=is1; is1 = isg+ieg-ie1-1+ishift; ie1 = isg+ieg-i-1+ishift
2858  end select
2859  call insert_update_overlap( overlap, domain%list(m)%pe, &
2860  is1, ie1, je, je, isc, iec, jsc, jec, dir, .true., symmetry=symmetry)
2861  endif
2862 
2863  if(ie2 .GE. is2) then
2864  call insert_update_overlap( overlap, domain%list(m)%pe, &
2865  is2, ie2, js, je, isc, iec, jsc, jec, dir)
2866  endif
2867 
2868  end subroutine fill_overlap_send_fold
2869 
2870 
2871  !#############################################################################
2872  subroutine fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2873  isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2874  type(overlap_type), intent(inout) :: overlap
2875  type(domain2d), intent(inout) :: domain
2876  integer, intent(in ) :: m, is, ie, js, je
2877  integer, intent(in ) :: isd, ied, jsd, jed
2878  integer, intent(in ) :: isg, ieg, dir, ioff
2879  logical, intent(in ) :: is_cyclic
2880  logical, optional, intent(in ) :: folded, symmetry
2881  integer :: is1, ie1, is2, ie2
2882  integer :: isd1, ied1, isd2, ied2
2883 
2884  is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2885  isd1=isd; ied1=ied
2886  isd2=isd; ied2=ied
2887 
2888  call insert_update_overlap( overlap, domain%list(m)%pe, &
2889  is, ie, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2890  if(is_cyclic) then
2891  if(ied .GT. ieg) 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( isd .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 ( is .LT. isg ) 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  else if ( ie .GT. ieg ) then
2901  call insert_update_overlap( overlap, domain%list(m)%pe, &
2902  is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2903  endif
2904  endif
2905 
2906  end subroutine fill_overlap_recv_nofold
2907  !#################################################################################
2908  subroutine fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2909  isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2910  type(overlap_type), intent(inout) :: overlap
2911  type(domain2d), intent(inout) :: domain
2912  integer, intent(in ) :: m, is, ie, js, je
2913  integer, intent(in ) :: isd, ied, jsd, jed
2914  integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2915  logical, optional, intent(in ) :: symmetry
2916  integer :: is1, ie1, is2, ie2, is3, ie3
2917  integer :: isd1, ied1, isd2, ied2
2918 
2919  !--- consider at j = jeg for west edge.
2920  !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2921  if( position == corner .AND. .NOT. domain%symmetry .AND. isd .LE. isg-1 .AND. ied .GE. isg-1 ) then
2922  call insert_update_overlap( overlap, domain%list(m)%pe, &
2923  is-ioff, ie-ioff, js, je, isg-1, isg-1, jed, jed, dir, .true.)
2924  end if
2925 
2926  is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2927  isd1=isd; ied1=ied
2928  isd2=isd; ied2=ied
2929  select case (position)
2930  case(north)
2931  is3 = isg+ieg-ie; ie3 = isg+ieg-is
2932  case(corner)
2933  is3 = isg+ieg-ie-1+ishift; ie3 = isg+ieg-is-1+ishift
2934  end select
2935 
2936  if(isd .GT. ieg) then ! east
2937  is2 = is + ioff; ie2 = ie + ioff;
2938  else if(ied .GT. ieg) then ! split into two parts
2939  is1 = is; ie1 = ie;
2940  isd1 = isd; ied1 = ieg;
2941  is2 = is + ioff; ie2 = ie + ioff
2942  isd2 = ieg + 1; ied2 = ied
2943  else if(isd .GE. middle) then
2944  is1 = is; ie1 = ie
2945  else if(ied .GE. middle) then ! split into two parts
2946  is1 = is; ie1 = ie
2947  isd1 = middle; ied1 = ied
2948  is2 = is; ie2 = ie
2949  isd2 = isd; ied2 = middle-1
2950  else if(ied .LT. isg) then
2951  is1 = is - ioff; ie1 = ie - ioff;
2952  is3 = is3 - ioff; ie3 = ie3 - ioff;
2953  else if(isd .LT. isg) then ! split into two parts
2954  is1 = is - ioff; ie1 = ie - ioff;
2955  is3 = is3 - ioff; ie3 = ie3 - ioff;
2956  isd1 = isd; ied1 = isg-1
2957  is2 = is; ie2 = ie
2958  isd2 = isg; ied2 = ied
2959  else
2960  is2 = is ; ie2 =ie
2961  isd2 = isd; ied2 = ied
2962  endif
2963 
2964  if( ie1 .GE. is1) then
2965  call insert_update_overlap( overlap, domain%list(m)%pe, &
2966  is1, ie1, js, je, isd1, ied1, jsd, jed-1, dir, symmetry=symmetry)
2967 
2968  call insert_update_overlap( overlap, domain%list(m)%pe, &
2969  is3, ie3, js, je, isd1, ied1, jed, jed, dir, .true., symmetry=symmetry)
2970  endif
2971 
2972  if(ie2 .GE. is2) then
2973  call insert_update_overlap( overlap, domain%list(m)%pe, &
2974  is2, ie2, js, je, isd2, ied2, jsd, jed, dir)
2975  endif
2976 
2977  end subroutine fill_overlap_recv_fold
2978 
2979 !#####################################################################################
2980  subroutine fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2981  isg, ieg, jsg, jeg, dir, reverse, symmetry)
2982  type(overlap_type), intent(inout) :: overlap
2983  type(domain2d), intent(inout) :: domain
2984  integer, intent(in ) :: m, is, ie, js, je
2985  integer, intent(in ) :: isc, iec, jsc, jec
2986  integer, intent(in ) :: isg, ieg, jsg, jeg
2987  integer, intent(in ) :: dir
2988  logical, optional, intent(in ) :: reverse, symmetry
2989 
2990  if(js > je) then ! separate into two regions due to x_cyclic_offset is nonzero, the two region are
2991  ! (js, jeg) and (jsg, je).
2992  call insert_update_overlap( overlap, domain%list(m)%pe, &
2993  is, ie, jsg, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2994  call insert_update_overlap( overlap, domain%list(m)%pe, &
2995  is, ie, js, jeg, isc, iec, jsc, jec, dir, reverse, symmetry)
2996  else if(is > ie) then ! separate into two regions due to y_cyclic_offset is nonzero, the two region are
2997  ! (is, ieg) and (isg, ie).
2998  call insert_update_overlap( overlap, domain%list(m)%pe, &
2999  is, ieg, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
3000  call insert_update_overlap( overlap, domain%list(m)%pe, &
3001  isg, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
3002  else
3003  call insert_update_overlap( overlap, domain%list(m)%pe, &
3004  is, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
3005  end if
3006 
3007 
3008  end subroutine fill_overlap
3009 
3010  !####################################################################################
3011  !> Computes remote domain overlaps
3012  !! assumes only one in each direction
3013  !! will calculate the overlapping for T,E,C,N-cell separately.
3014  subroutine compute_overlaps_fold_south( domain, position, ishift, jshift)
3015  type(domain2d), intent(inout) :: domain
3016  integer, intent(in) :: position, ishift, jshift
3017 
3018  integer :: i, m, n, nlist, tMe, tNbr, dir
3019  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3020  integer :: isg, ieg, jsg, jeg, ioff, joff
3021  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3022  integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3023  logical :: folded
3024  type(overlap_type) :: overlap
3025  type(overlapspec), pointer :: update=>null()
3026  type(overlap_type), pointer :: overlapList(:)=>null()
3027  type(overlap_type), pointer :: checkList(:)=>null()
3028  type(overlapspec), pointer :: check =>null()
3029  integer :: nsend, nrecv
3030  integer :: nsend_check, nrecv_check
3031  integer :: iunit
3032 
3033  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3034  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3035  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3036  if(size(domain%x(:)) > 1) return
3037 
3038  !--- if there is no halo, no need to compute overlaps.
3039  if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3040 
3041  !--- when there is only one tile, n will equal to np
3042  nlist = size(domain%list(:))
3043 
3044  select case(position)
3045  case (center)
3046  update => domain%update_T
3047  check => null()
3048  case (corner)
3049  update => domain%update_C
3050  check => domain%check_C
3051  case (east)
3052  update => domain%update_E
3053  check => domain%check_E
3054  case (north)
3055  update => domain%update_N
3056  check => domain%check_N
3057  case default
3058  call mpp_error(fatal, &
3059  "mpp_domains_define.inc(compute_overlaps_fold_south): the value of position should be CENTER, EAST, &
3060  & CORNER or NORTH")
3061  end select
3062 
3063  allocate(overlaplist(maxlist) )
3064  allocate(checklist(maxlist) )
3065 
3066  !--- overlap is used to store the overlapping temporarily.
3067  call allocate_update_overlap( overlap, maxoverlap)
3068 
3069  !send
3070  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3071  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3072  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3073  update%xbegin = ism; update%xend = iem
3074  update%ybegin = jsm; update%yend = jem
3075  if(ASSOCIATED(check)) then
3076  check%xbegin = ism; check%xend = iem
3077  check%ybegin = jsm; check%yend = jem
3078  endif
3079  update%whalo = domain%whalo; update%ehalo = domain%ehalo
3080  update%shalo = domain%shalo; update%nhalo = domain%nhalo
3081  whalo = domain%whalo; ehalo = domain%ehalo
3082  shalo = domain%shalo; nhalo = domain%nhalo
3083 
3084 
3085  ioff = ni - ishift
3086  joff = nj - jshift
3087  middle = (isg+ieg)/2+1
3088  tme = 1; tnbr = 1
3089 
3090  if(.NOT. btest(domain%fold,south)) then
3091  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3092  "boundary condition in y-direction should be folded-south for "//trim(domain%name))
3093  endif
3094  if(.NOT. domain%x(tme)%cyclic) then
3095  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3096  "boundary condition in x-direction should be cyclic for "//trim(domain%name))
3097  endif
3098 
3099  if(.not. domain%symmetry) then
3100  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3101  "when south boundary is folded, the domain must be symmetry for "//trim(domain%name))
3102  endif
3103 
3104  nsend = 0
3105  nsend_check = 0
3106  do list = 0,nlist-1
3107  m = mod( domain%pos+list, nlist )
3108  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3109  !to_pe's eastern halo
3110  dir = 1
3111  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3112  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3113  !--- to make sure the consistence between pes
3114  if( (position == north .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3115  !--- do nothing, this point will come from other pe
3116  else
3117  if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3118  is = is-ioff; ie = ie-ioff
3119  end if
3120  !--- when the south face is folded, the east halo point at right side domain will be folded.
3121  !--- the position should be on CORNER or NORTH
3122  if( js == jsg .AND. (position == corner .OR. position == north) &
3123  .AND. is .GE. middle .AND. domain%list(m)%x(tnbr)%compute%end+ehalo+jshift .LE. ieg ) then
3124  call insert_update_overlap( overlap, domain%list(m)%pe, &
3125  is, ie, js+1, je, isc, iec, jsc, jec, dir)
3126  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3127  je = js
3128  select case (position)
3129  case(north)
3130  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3131  case(corner)
3132  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3133  end select
3134  call insert_update_overlap( overlap, domain%list(m)%pe, &
3135  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3136  else
3137  call insert_update_overlap( overlap, domain%list(m)%pe, &
3138  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3139  end if
3140  end if
3141 
3142  !to_pe's SE halo
3143  dir = 2
3144  folded = .false.
3145  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3146  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3147  if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3148  is = is-ioff; ie = ie-ioff
3149  end if
3150  if( js.LT.jsg )then
3151  folded = .true.
3152  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3153  end if
3154 
3155  call insert_update_overlap( overlap, domain%list(m)%pe, &
3156  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3157 
3158  !to_pe's southern halo
3159  dir = 3
3160  folded = .false.
3161  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3162  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3163  folded = .false.
3164  if( js.LT.jsg )then
3165  folded = .true.
3166  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3167  end if
3168  !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3169  !--- no need to send, because the data on that point will come from other pe.
3170  !--- come from two pe ( there will be only one point on one pe. ).
3171  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3172  !--- do nothing, this point will come from other pe
3173  else
3174  call insert_update_overlap( overlap, domain%list(m)%pe, &
3175  is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3176  endif
3177  !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3178  if(is .LT. isg) then
3179  is = is + ioff
3180  call insert_update_overlap( overlap, domain%list(m)%pe, &
3181  is, is, js, je, isc, iec, jsc, jec, dir, folded)
3182  endif
3183 
3184  !to_pe's SW halo
3185  dir = 4
3186  folded = .false.
3187  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3188  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3189  if( isg.GT.is .AND. ie.LT.isc )then !cyclic offset
3190  is = is+ioff; ie = ie+ioff
3191  end if
3192  if( js.LT.jsg )then
3193  folded = .true.
3194  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3195  end if
3196  call insert_update_overlap( overlap, domain%list(m)%pe, &
3197  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3198  !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3199  if(is .LT. isg) then
3200  is = is + ioff
3201  call insert_update_overlap( overlap, domain%list(m)%pe, &
3202  is, is, js, je, isc, iec, jsc, jec, dir, folded)
3203  endif
3204 
3205  !to_pe's western halo
3206  dir = 5
3207  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3208  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3209 
3210  !--- to make sure the consistence between pes
3211  if( (position == north .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3212  !--- do nothing, this point will come from other pe
3213  else
3214  if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3215  is = is+ioff; ie = ie+ioff
3216  end if
3217  !--- when the south face is folded, some point at j=nj will be folded.
3218  !--- the position should be on CORNER or NORTH
3219  if( js == jsg .AND. (position == corner .OR. position == north) &
3220  .AND. ( domain%list(m)%x(tnbr)%compute%begin == isg .OR. &
3221  & domain%list(m)%x(tnbr)%compute%begin-1 .GE. middle)) then
3222  call insert_update_overlap( overlap, domain%list(m)%pe, &
3223  is, ie, js+1, je, isc, iec, jsc, jec, dir)
3224  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3225  js = domain%list(m)%y(tnbr)%compute%begin; je = js
3226  if ( domain%list(m)%x(tnbr)%compute%begin == isg ) then
3227  select case (position)
3228  case(north)
3229  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3230  case(corner)
3231  i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3232  end select
3233  if(ie .GT. domain%x(tme)%compute%end+ishift) call mpp_error( fatal, &
3234  'mpp_domains_define.inc(compute_overlaps_fold_south): west edge ubound error send.' )
3235  else
3236  select case (position)
3237  case(north)
3238  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3239  case(corner)
3240  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3241  end select
3242  end if
3243  call insert_update_overlap( overlap, domain%list(m)%pe, &
3244  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3245  else
3246  call insert_update_overlap( overlap, domain%list(m)%pe, &
3247  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3248  end if
3249  endif
3250 
3251  !to_pe's NW halo
3252  dir = 6
3253  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3254  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3255  if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3256  is = is+ioff; ie = ie+ioff
3257  end if
3258  call insert_update_overlap( overlap, domain%list(m)%pe, &
3259  is, ie, js, je, isc, iec, jsc, jec, dir)
3260 
3261  !to_pe's northern halo
3262  dir = 7
3263  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3264  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3265  call insert_update_overlap( overlap, domain%list(m)%pe, &
3266  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3267 
3268  !to_pe's NE halo
3269  dir = 8
3270  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3271  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3272  if( ie.GT.ieg .AND. iec.LT.is )then !cyclic offset
3273  is = is-ioff; ie = ie-ioff
3274  end if
3275  call insert_update_overlap( overlap, domain%list(m)%pe, &
3276  is, ie, js, je, isc, iec, jsc, jec, dir)
3277 
3278  !--- Now calculate the overlapping for fold-edge.
3279  !--- only position at NORTH and CORNER need to be considered
3280  if( ( position == north .OR. position == corner) ) then
3281  !fold is within domain
3282  if( domain%y(tme)%domain_data%begin .LE. jsg .AND. jsg .LE. domain%y(tme)%domain_data%end+jshift )then
3283  dir = 3
3284  !--- calculate the overlapping for sending
3285  if( domain%x(tme)%pos .LT. (size(domain%x(tme)%list(:))+1)/2 )then
3286  js = domain%list(m)%y(tnbr)%compute%begin; je = js
3287  if( js == jsg )then ! fold is within domain.
3288  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3289  select case (position)
3290  case(north)
3291  is = max(is, middle)
3292  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3293  case(corner)
3294  is = max(is, middle)
3295  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3296  end select
3297  call insert_update_overlap(overlap, domain%list(m)%pe, &
3298  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3299  is = max(is, isc); ie = min(ie, iec)
3300  js = max(js, jsc); je = min(je, jec)
3301  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3302  nsend_check = nsend_check+1
3303  call allocate_check_overlap(checklist(nsend_check), 1)
3304  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
3305  tme, 2, one_hundred_eighty, is, ie, js, je)
3306  end if
3307  end if
3308  end if
3309  end if
3310  end if
3311  end if
3312  !--- copy the overlapping information
3313  if( overlap%count > 0) then
3314  nsend = nsend + 1
3315  if(nsend > size(overlaplist(:)) ) then
3316  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for send is expanded')
3317  call expand_update_overlap_list(overlaplist, nlist)
3318  endif
3319  call add_update_overlap(overlaplist(nsend), overlap)
3320  call init_overlap_type(overlap)
3321  endif
3322  end do ! end of send set up.
3323 
3324  if(debug_message_passing) then
3325  !--- write out send information
3326  iunit = mpp_pe() + 1000
3327  do m =1,nsend
3328  write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3329  do n = 1, overlaplist(m)%count
3330  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3331  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3332  enddo
3333  enddo
3334  if( nsend > 0) flush(iunit)
3335  endif
3336 
3337  ! copy the overlapping information into domain data structure
3338  if(nsend>0) then
3339  if (associated(update%send)) deallocate(update%send) !< Check if associated
3340  allocate(update%send(nsend))
3341  update%nsend = nsend
3342  do m = 1, nsend
3343  call add_update_overlap( update%send(m), overlaplist(m) )
3344  enddo
3345  endif
3346 
3347  if(nsend_check>0) then
3348  if (associated(check%send)) deallocate(check%send) !< Check if associated
3349  allocate(check%send(nsend_check))
3350  check%nsend = nsend_check
3351  do m = 1, nsend_check
3352  call add_check_overlap( check%send(m), checklist(m) )
3353  enddo
3354  endif
3355 
3356  do m = 1,size(overlaplist(:))
3357  call deallocate_overlap_type(overlaplist(m))
3358  enddo
3359 
3360  if(debug_update_level .NE. no_check) then
3361  do m = 1,size(checklist(:))
3362  call deallocate_overlap_type(checklist(m))
3363  enddo
3364  endif
3365 
3366  isgd = isg - domain%whalo
3367  iegd = ieg + domain%ehalo
3368  jsgd = jsg - domain%shalo
3369  jegd = jeg + domain%nhalo
3370 
3371  ! begin setting up recv
3372  nrecv = 0
3373  nrecv_check = 0
3374  do list = 0,nlist-1
3375  m = mod( domain%pos+nlist-list, nlist )
3376  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3377  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
3378  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
3379  !recv_e
3380  dir = 1
3381  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3382  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
3383  is=isc; ie=iec; js=jsc; je=jec
3384  if( (position == north .OR. position == corner ) .AND. ( jsd == je .or. jed == js ) ) then
3385  ! --- do nothing, this point will come from other pe
3386  else
3387  if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3388  is = is+ioff; ie = ie+ioff
3389  end if
3390 
3391  !--- when the south face is folded, the east halo point at right side domain will be folded.
3392  !--- the position should be on CORNER or NORTH
3393  if( jsd == jsg .AND. (position == corner .OR. position == north) &
3394  .AND. isd .GE. middle .AND. ied .LE. ieg ) then
3395  call insert_update_overlap( overlap, domain%list(m)%pe, &
3396  is, ie, js, je, isd, ied, jsd+1, jed, dir)
3397  is=isc; ie=iec; js=jsc; je=jec
3398  jed = jsd
3399  select case (position)
3400  case(north)
3401  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3402  case(corner)
3403  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3404  end select
3405  call insert_update_overlap( overlap, domain%list(m)%pe, &
3406  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
3407  else
3408  call insert_update_overlap( overlap, domain%list(m)%pe, &
3409  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3410  end if
3411  end if
3412 
3413  !recv_se
3414  dir = 2
3415  folded = .false.
3416  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3417  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3418  is=isc; ie=iec; js=jsc; je=jec
3419  if( jsd.LT.jsg )then
3420  folded = .true.
3421  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3422  end if
3423  if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3424  is = is+ioff; ie = ie+ioff
3425  endif
3426  call insert_update_overlap(overlap, domain%list(m)%pe, &
3427  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3428 
3429  !recv_s
3430  dir = 3
3431  folded = .false.
3432  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3433  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3434  is=isc; ie=iec; js=jsc; je=jec
3435  if( jsd.LT.jsg )then
3436  folded = .true.
3437  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3438  end if
3439  if( (position == east .OR. position == corner ) .AND. (isd == ie .or. ied == is ) ) then
3440  !--- do nothing, this point will come from other pe
3441  else
3442  call insert_update_overlap(overlap, domain%list(m)%pe, &
3443  is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
3444  end if
3445  !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3446  if(is .LT. isg ) then
3447  is = is + ioff
3448  call insert_update_overlap(overlap, domain%list(m)%pe, &
3449  is, is, js, je, isd, ied, jsd, jed, dir, folded)
3450  endif
3451 
3452  !recv_sw
3453  dir = 4
3454  folded = .false.
3455  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3456  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3457  is=isc; ie=iec; js=jsc; je=jec
3458  if( jsd.LT.jsg )then
3459  folded = .true.
3460  call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3461  end if
3462  if( isd.LT.isg .AND. is.GT.ied ) then ! cyclic offset
3463  is = is-ioff; ie = ie-ioff
3464  end if
3465  call insert_update_overlap(overlap, domain%list(m)%pe, &
3466  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3467  !--- when southth edge is folded, is will be less than isg when position is EAST and CORNER
3468  if(is .LT. isg ) then
3469  is = is + ioff
3470  call insert_update_overlap(overlap, domain%list(m)%pe, &
3471  is, is, js, je, isd, ied, jsd, jed, dir, folded )
3472  endif
3473 
3474  !recv_w
3475  dir = 5
3476  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3477  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
3478  is=isc; ie=iec; js=jsc; je=jec
3479  if( (position == north .OR. position == corner ) .AND. ( jsd == je .or. jed == js ) ) then
3480  ! --- do nothing, this point will come from other pe
3481  else
3482  if( isd.LT.isg .AND. is.GT.ied )then ! cyclic offset
3483  is = is-ioff; ie = ie-ioff
3484  end if
3485  !--- when the south face is folded, some point at j=nj will be folded.
3486  !--- the position should be on CORNER or NORTH
3487  if( jsd == jsg .AND. (position == corner .OR. position == north) &
3488  .AND. ( isd < isg .OR. ied .GE. middle ) ) then
3489  call insert_update_overlap(overlap, domain%list(m)%pe, &
3490  is, ie, js, je, isd, ied, jsd+1, jed, dir)
3491  is=isc; ie=iec; js=jsc; je=jec
3492  if(isd < isg) then
3493  select case (position)
3494  case(north)
3495  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3496  case(corner)
3497  ied = ied -1 + ishift
3498  i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3499  end select
3500  if(ie .GT. domain%x(tme)%compute%end+ishift) call mpp_error( fatal, &
3501  'mpp_domains_define.inc(compute_overlaps): west edge ubound error recv.' )
3502  else
3503  select case (position)
3504  case(north)
3505  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3506  case(corner)
3507  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3508  end select
3509  end if
3510  call insert_update_overlap(overlap, domain%list(m)%pe, &
3511  is, ie, js, je, isd, ied, jsd, jsd, dir, .true.)
3512  else
3513  call insert_update_overlap(overlap, domain%list(m)%pe, &
3514  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3515  end if
3516  endif
3517 
3518  !recv_nw
3519  dir = 6
3520  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3521  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3522  is=isc; ie=iec; js=jsc; je=jec
3523  if( isd.LT.isg .AND. is.GE.ied )then !cyclic offset
3524  is = is-ioff; ie = ie-ioff
3525  endif
3526 
3527  call insert_update_overlap( overlap, domain%list(m)%pe, &
3528  is, ie, js, je, isd, ied, jsd, jed, dir)
3529 
3530  !recv_n
3531  dir = 7
3532  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3533  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3534  is=isc; ie=iec; js=jsc; je=jec
3535  call insert_update_overlap( overlap, domain%list(m)%pe, &
3536  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3537 
3538  !recv_ne
3539  dir = 8
3540  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3541  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3542  is=isc; ie=iec; js=jsc; je=jec
3543  if( ied.GT.ieg .AND. ie.LT.isd )then ! cyclic offset
3544  is = is+ioff; ie = ie+ioff
3545  end if
3546  call insert_update_overlap( overlap, domain%list(m)%pe, &
3547  is, ie, js, je, isd, ied, jsd, jed, dir)
3548 
3549  !--- Now calculate the overlapping for fold-edge.
3550  !--- for folded-south-edge, only need to consider to_pe's south(3) direction
3551  !--- only position at NORTH and CORNER need to be considered
3552  if( ( position == north .OR. position == corner) ) then
3553  !fold is within domain
3554  if( domain%y(tme)%domain_data%begin .LE. jsg .AND. jsg .LE. domain%y(tme)%domain_data%end+jshift )then
3555  dir = 3
3556  !--- calculating overlapping for receving on north
3557  if( domain%x(tme)%pos .GE. size(domain%x(tme)%list(:))/2 )then
3558  jsd = domain%y(tme)%compute%begin; jed = jsd
3559  if( jsd == jsg )then ! fold is within domain.
3560  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3561  is=isc; ie=iec; js = jsc; je = jec
3562  select case (position)
3563  case(north)
3564  isd = max(isd, middle)
3565  i=is; is = isg+ieg-ie; ie = isg+ieg-i
3566  case(corner)
3567  isd = max(isd, middle)
3568  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3569  end select
3570  call insert_update_overlap(overlap, domain%list(m)%pe, &
3571  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
3572  is = max(is, isd); ie = min(ie, ied)
3573  js = max(js, jsd); je = min(je, jed)
3574  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3575  nrecv_check = nrecv_check+1
3576  call allocate_check_overlap(checklist(nrecv_check), 1)
3577  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
3578  tme, 2, one_hundred_eighty, is, ie, js, je)
3579  endif
3580  endif
3581  endif
3582  endif
3583  endif
3584  endif
3585  !--- copy the overlapping information
3586  if( overlap%count > 0) then
3587  nrecv = nrecv + 1
3588  if(nrecv > size(overlaplist(:)) )then
3589  call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for recv is expanded')
3590  call expand_update_overlap_list(overlaplist, nlist)
3591  endif
3592  call add_update_overlap( overlaplist(nrecv), overlap)
3593  call init_overlap_type(overlap)
3594  endif
3595  enddo ! end of recv do loop
3596 
3597  if(debug_message_passing) then
3598  !--- write out send information
3599  iunit = mpp_pe() + 1000
3600  do m =1,nrecv
3601  write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3602  do n = 1, overlaplist(m)%count
3603  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3604  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3605  enddo
3606  enddo
3607  if(nrecv >0) flush(iunit)
3608  endif
3609 
3610  ! copy the overlapping information into domain
3611  if(nrecv>0) then
3612  update%nrecv = nrecv
3613  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
3614  allocate(update%recv(nrecv))
3615  do m = 1, nrecv
3616  call add_update_overlap( update%recv(m), overlaplist(m) )
3617  do n = 1, update%recv(m)%count
3618  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
3619  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
3620  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
3621  endif
3622  enddo
3623  enddo
3624  endif
3625 
3626  if(nrecv_check>0) then
3627  check%nrecv = nrecv_check
3628  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
3629  allocate(check%recv(nrecv_check))
3630  do m = 1, nrecv_check
3631  call add_check_overlap( check%recv(m), checklist(m) )
3632  enddo
3633  endif
3634 
3635  call deallocate_overlap_type(overlap)
3636 
3637  do m = 1,size(overlaplist(:))
3638  call deallocate_overlap_type(overlaplist(m))
3639  enddo
3640 
3641  if(debug_update_level .NE. no_check) then
3642  do m = 1,size(checklist(:))
3643  call deallocate_overlap_type(checklist(m))
3644  enddo
3645  endif
3646 
3647  deallocate(overlaplist)
3648  deallocate(checklist)
3649  update => null()
3650  check=>null()
3651  domain%initialized = .true.
3652 
3653  end subroutine compute_overlaps_fold_south
3654 
3655  !####################################################################################
3656  !> Computes remote domain overlaps
3657  !! assumes only one in each direction
3658  !! will calculate the overlapping for T,E,C,N-cell separately.
3659  subroutine compute_overlaps_fold_west( domain, position, ishift, jshift)
3660  type(domain2d), intent(inout) :: domain
3661  integer, intent(in) :: position, ishift, jshift
3662 
3663  integer :: j, m, n, nlist, tMe, tNbr, dir
3664  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3665  integer :: isg, ieg, jsg, jeg, ioff, joff
3666  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3667  integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3668  logical :: folded
3669  type(overlap_type) :: overlap
3670  type(overlapspec), pointer :: update=>null()
3671  type(overlap_type) :: overlapList(MAXLIST)
3672  type(overlap_type) :: checkList(MAXLIST)
3673  type(overlapspec), pointer :: check =>null()
3674  integer :: nsend, nrecv
3675  integer :: nsend_check, nrecv_check
3676  integer :: iunit
3677 
3678  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3679  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3680  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3681  if(size(domain%x(:)) > 1) return
3682 
3683  !--- if there is no halo, no need to compute overlaps.
3684  if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3685 
3686  !--- when there is only one tile, n will equal to np
3687  nlist = size(domain%list(:))
3688 
3689  select case(position)
3690  case (center)
3691  update => domain%update_T
3692  check => null()
3693  case (corner)
3694  update => domain%update_C
3695  check => domain%check_C
3696  case (east)
3697  update => domain%update_E
3698  check => domain%check_E
3699  case (north)
3700  update => domain%update_N
3701  check => domain%check_N
3702  case default
3703  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west):"//&
3704  & " the value of position should be CENTER, EAST, CORNER or NORTH")
3705  end select
3706 
3707  !--- overlap is used to store the overlapping temporarily.
3708  call allocate_update_overlap( overlap, maxoverlap)
3709 
3710  !send
3711  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3712  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3713  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3714  update%xbegin = ism; update%xend = iem
3715  update%ybegin = jsm; update%yend = jem
3716  if(ASSOCIATED(check)) then
3717  check%xbegin = ism; check%xend = iem
3718  check%ybegin = jsm; check%yend = jem
3719  endif
3720  update%whalo = domain%whalo; update%ehalo = domain%ehalo
3721  update%shalo = domain%shalo; update%nhalo = domain%nhalo
3722  whalo = domain%whalo; ehalo = domain%ehalo
3723  shalo = domain%shalo; nhalo = domain%nhalo
3724 
3725  ioff = ni - ishift
3726  joff = nj - jshift
3727  middle = (jsg+jeg)/2+1
3728  tme = 1; tnbr = 1
3729 
3730  if(.NOT. btest(domain%fold,west)) then
3731  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3732  "boundary condition in y-direction should be folded-west for "//trim(domain%name))
3733  endif
3734  if(.NOT. domain%y(tme)%cyclic) then
3735  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3736  "boundary condition in y-direction should be cyclic for "//trim(domain%name))
3737  endif
3738 
3739  if(.not. domain%symmetry) then
3740  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3741  "when west boundary is folded, the domain must be symmetry for "//trim(domain%name))
3742  endif
3743 
3744  nsend = 0
3745  nsend_check = 0
3746  do list = 0,nlist-1
3747  m = mod( domain%pos+list, nlist )
3748  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3749  !to_pe's eastern halo
3750  dir = 1
3751  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3752  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3753  call insert_update_overlap( overlap, domain%list(m)%pe, &
3754  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3755 
3756  !to_pe's SE halo
3757  dir = 2
3758  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3759  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3760  if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
3761  js = js+joff; je = je+joff
3762  end if
3763 
3764  call insert_update_overlap( overlap, domain%list(m)%pe, &
3765  is, ie, js, je, isc, iec, jsc, jec, dir)
3766 
3767  !to_pe's southern halo
3768  dir = 3
3769  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3770  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3771  !--- to make sure the consistence between pes
3772  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3773  !--- do nothing, this point will come from other pe
3774  else
3775  if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
3776  js = js+joff; je = je+joff
3777  endif
3778 
3779  !--- when the west face is folded, the south halo points at
3780  !--- the position should be on CORNER or EAST
3781  if( is == isg .AND. (position == corner .OR. position == east) &
3782  .AND. ( domain%list(m)%y(tnbr)%compute%begin == jsg .OR. &
3783  & domain%list(m)%y(tnbr)%compute%begin-1 .GE. middle)) then
3784  call insert_update_overlap( overlap, domain%list(m)%pe, &
3785  is+1, ie, js, je, isc, iec, jsc, jec, dir)
3786  is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3787  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3788  if ( domain%list(m)%y(tnbr)%compute%begin == jsg ) then
3789  select case (position)
3790  case(east)
3791  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
3792  case(corner)
3793  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
3794  end select
3795  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
3796  'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error send.' )
3797  else
3798  select case (position)
3799  case(east)
3800  j=js; js = jsg+jeg-je; je = jsg+jeg-j
3801  case(corner)
3802  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3803  end select
3804  end if
3805  call insert_update_overlap( overlap, domain%list(m)%pe, &
3806  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3807  else
3808  call insert_update_overlap( overlap, domain%list(m)%pe, &
3809  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3810  end if
3811  endif
3812 
3813  !to_pe's SW halo
3814  dir = 4
3815  folded = .false.
3816  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3817  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3818  if( jsg.GT.js .AND. je.LT.jsc )then !cyclic offset
3819  js = js+joff; je = je+joff
3820  end if
3821  if( is.LT.isg )then
3822  folded = .true.
3823  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3824  end if
3825  call insert_update_overlap( overlap, domain%list(m)%pe, &
3826  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3827  !--- when south edge is folded, js will be less than jsg when position is EAST and CORNER
3828  if(js .LT. jsg) then
3829  js = js + joff
3830  call insert_update_overlap( overlap, domain%list(m)%pe, &
3831  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3832  endif
3833 
3834  !to_pe's western halo
3835  dir = 5
3836  folded = .false.
3837  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3838  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3839  if( isg.GT.is )then
3840  folded = .true.
3841  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3842  end if
3843  !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3844  !--- no need to send, because the data on that point will come from other pe.
3845  !--- come from two pe ( there will be only one point on one pe. ).
3846  if( (position == east .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3847  !--- do nothing, this point will come from other pe
3848  else
3849  call insert_update_overlap( overlap, domain%list(m)%pe, &
3850  is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3851  endif
3852  !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3853  if(js .LT. jsg) then
3854  js = js + ioff
3855  call insert_update_overlap( overlap, domain%list(m)%pe, &
3856  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3857  endif
3858 
3859  !to_pe's NW halo
3860  dir = 6
3861  folded = .false.
3862  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3863  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3864  if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
3865  js = js-joff; je = je-joff
3866  end if
3867  if( is.LT.isg )then
3868  folded = .true.
3869  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3870  end if
3871 
3872  call insert_update_overlap( overlap, domain%list(m)%pe, &
3873  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3874 
3875  !to_pe's northern halo
3876  dir = 7
3877  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3878  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3879  !--- to make sure the consistence between pes
3880  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3881  !--- do nothing, this point will come from other pe
3882  else
3883  if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
3884  js = js-joff; je = je-joff
3885  endif
3886  !--- when the west face is folded, the south halo points at
3887  !--- the position should be on CORNER or EAST
3888  if( is == isg .AND. (position == corner .OR. position == east) &
3889  .AND. ( js .GE. middle .AND. domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
3890  call insert_update_overlap( overlap, domain%list(m)%pe, &
3891  is+1, ie, js, je, isc, iec, jsc, jec, dir)
3892  is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3893  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3894  select case (position)
3895  case(east)
3896  j=js; js = jsg+jeg-je; je = jsg+jeg-j
3897  case(corner)
3898  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3899  end select
3900  call insert_update_overlap( overlap, domain%list(m)%pe, &
3901  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3902  else
3903  call insert_update_overlap( overlap, domain%list(m)%pe, &
3904  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3905  end if
3906  endif
3907 
3908  !to_pe's NE halo
3909  dir = 8
3910  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3911  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3912  if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
3913  js = js-joff; je = je-joff
3914  end if
3915  call insert_update_overlap( overlap, domain%list(m)%pe, &
3916  is, ie, js, je, isc, iec, jsc, jec, dir)
3917 
3918  !--- Now calculate the overlapping for fold-edge.
3919  !--- only position at EAST and CORNER need to be considered
3920  if( ( position == east .OR. position == corner) ) then
3921  !fold is within domain
3922  if( domain%x(tme)%compute%begin-whalo .LE. isg .AND. isg .LE. domain%x(tme)%domain_data%end+ishift )then
3923  dir = 5
3924  !--- calculate the overlapping for sending
3925  if( domain%y(tme)%pos .LT. (size(domain%y(tme)%list(:))+1)/2 )then
3926  is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3927  if( is == isg )then ! fold is within domain.
3928  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3929  select case (position)
3930  case(east)
3931  js = max(js, middle)
3932  j=js; js = jsg+jeg-je; je = jsg+jeg-j
3933  case(corner)
3934  js = max(js, middle)
3935  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3936  end select
3937  call insert_update_overlap(overlap, domain%list(m)%pe, &
3938  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3939  is = max(is, isc); ie = min(ie, iec)
3940  js = max(js, jsc); je = min(je, jec)
3941  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3942  nsend_check = nsend_check+1
3943  call allocate_check_overlap(checklist(nsend_check), 1)
3944  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
3945  tme, 3, one_hundred_eighty, is, ie, js, je)
3946  end if
3947  end if
3948  end if
3949  end if
3950  end if
3951  end if
3952  !--- copy the overlapping information
3953  if( overlap%count > 0) then
3954  nsend = nsend + 1
3955  if(nsend > maxlist) call mpp_error(fatal, &
3956  "mpp_domains_define.inc(compute_overlaps_west): nsend is greater than MAXLIST, increase MAXLIST")
3957  call add_update_overlap(overlaplist(nsend), overlap)
3958  call init_overlap_type(overlap)
3959  endif
3960  end do ! end of send set up.
3961 
3962  if(debug_message_passing) then
3963  !--- write out send information
3964  iunit = mpp_pe() + 1000
3965  do m =1,nsend
3966  write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3967  do n = 1, overlaplist(m)%count
3968  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3969  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3970  enddo
3971  enddo
3972  if(nsend >0) flush(iunit)
3973  endif
3974 
3975  ! copy the overlapping information into domain data structure
3976  if(nsend>0) then
3977  update%nsend = nsend
3978  if (associated(update%send)) deallocate(update%send) !< Check if associated
3979  allocate(update%send(nsend))
3980  do m = 1, nsend
3981  call add_update_overlap( update%send(m), overlaplist(m) )
3982  enddo
3983  endif
3984 
3985  if(nsend_check>0) then
3986  check%nsend = nsend_check
3987  if (associated(check%send)) deallocate(check%send) !< Check if associated
3988  allocate(check%send(nsend_check))
3989  do m = 1, nsend_check
3990  call add_check_overlap( check%send(m), checklist(m) )
3991  enddo
3992  endif
3993 
3994  do m = 1, maxlist
3995  call deallocate_overlap_type(overlaplist(m))
3996  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
3997  enddo
3998 
3999  isgd = isg - domain%whalo
4000  iegd = ieg + domain%ehalo
4001  jsgd = jsg - domain%shalo
4002  jegd = jeg + domain%nhalo
4003 
4004  ! begin setting up recv
4005  nrecv = 0
4006  nrecv_check = 0
4007  do list = 0,nlist-1
4008  m = mod( domain%pos+nlist-list, nlist )
4009  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4010  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4011  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4012  !recv_e
4013  dir = 1
4014  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4015  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4016  is=isc; ie=iec; js=jsc; je=jec
4017  call insert_update_overlap( overlap, domain%list(m)%pe, &
4018  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4019 
4020  !recv_se
4021  dir = 2
4022  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4023  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4024  is=isc; ie=iec; js=jsc; je=jec
4025  if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4026  js = js-joff; je = je-joff
4027  end if
4028  call insert_update_overlap(overlap, domain%list(m)%pe, &
4029  is, ie, js, je, isd, ied, jsd, jed, dir)
4030 
4031  !recv_s
4032  dir = 3
4033  folded = .false.
4034  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4035  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4036  is=isc; ie=iec; js=jsc; je=jec
4037 
4038  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4039  !--- do nothing, this point will come from other pe
4040  else
4041  if( jsd.LT.jsg .AND. js .GT. jed)then
4042  js = js-joff; je = je-joff
4043  end if
4044  !--- when the west face is folded, the south halo points at
4045  !--- the position should be on CORNER or EAST
4046  if( isd == isg .AND. (position == corner .OR. position == east) &
4047  .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4048  call insert_update_overlap( overlap, domain%list(m)%pe, &
4049  is, ie, js, je, isd+1, ied, jsd, jed, dir)
4050  is=isc; ie=iec; js=jsc; je=jec
4051  if(jsd<jsg) then
4052  select case (position)
4053  case(east)
4054  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4055  case(corner)
4056  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4057  end select
4058  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4059  'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4060  else
4061  select case (position)
4062  case(east)
4063  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4064  case(corner)
4065  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4066  end select
4067  end if
4068  call insert_update_overlap( overlap, domain%list(m)%pe, &
4069  is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4070  else
4071  call insert_update_overlap( overlap, domain%list(m)%pe, &
4072  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4073  end if
4074  endif
4075 
4076  !recv_sw
4077  dir = 4
4078  folded = .false.
4079  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4080  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4081  is=isc; ie=iec; js=jsc; je=jec
4082  if( isd.LT.isg )then
4083  folded = .true.
4084  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4085  end if
4086  if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4087  js = js-joff; je = je-joff
4088  end if
4089  call insert_update_overlap(overlap, domain%list(m)%pe, &
4090  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4091  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4092  if(js .LT. jsg ) then
4093  js = js + joff
4094  call insert_update_overlap(overlap, domain%list(m)%pe, &
4095  is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4096  endif
4097 
4098  !recv_w
4099  dir = 5
4100  folded = .false.
4101  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4102  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4103  is=isc; ie=iec; js=jsc; je=jec
4104  if( isd.LT.isg )then
4105  folded = .true.
4106  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4107  end if
4108  if( (position == east .OR. position == corner ) .AND. (jsd == je .or. jed == js ) ) then
4109  !--- do nothing, this point will come from other pe
4110  else
4111  call insert_update_overlap(overlap, domain%list(m)%pe, &
4112  is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4113  end if
4114  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4115  if(js .LT. jsg ) then
4116  js = js + joff
4117  call insert_update_overlap(overlap, domain%list(m)%pe, &
4118  is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4119  endif
4120 
4121  !recv_nw
4122  dir = 6
4123  folded = .false.
4124  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4125  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4126  is=isc; ie=iec; js=jsc; je=jec
4127  if( isd.LT.isg) then
4128  folded = .true.
4129  call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4130  end if
4131  if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4132  js = js+joff; je = je+joff
4133  endif
4134 
4135  call insert_update_overlap( overlap, domain%list(m)%pe, &
4136  is, ie, js, je, isd, ied, jsd, jed, dir)
4137 
4138  !recv_n
4139  dir = 7
4140  folded = .false.
4141  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4142  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4143  is=isc; ie=iec; js=jsc; je=jec
4144  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4145  !--- do nothing, this point will come from other pe
4146  else
4147  if( jed.GT.jeg .AND. je.LT.jsd)then
4148  js = js+joff; je = je+joff
4149  end if
4150  !--- when the west face is folded, the south halo points at
4151  !--- the position should be on CORNER or EAST
4152  if( isd == isg .AND. (position == corner .OR. position == east) &
4153  .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4154  call insert_update_overlap( overlap, domain%list(m)%pe, &
4155  is, ie, js, je, isd+1, ied, jsd, jed, dir)
4156  is=isc; ie=iec; js=jsc; je=jec
4157  select case (position)
4158  case(east)
4159  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4160  case(corner)
4161  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4162  end select
4163  call insert_update_overlap( overlap, domain%list(m)%pe, &
4164  is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4165  else
4166  call insert_update_overlap( overlap, domain%list(m)%pe, &
4167  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4168  end if
4169  endif
4170 
4171  !recv_ne
4172  dir = 8
4173  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4174  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4175  is=isc; ie=iec; js=jsc; je=jec
4176  if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4177  js = js+joff; je = je+joff
4178  end if
4179  call insert_update_overlap( overlap, domain%list(m)%pe, &
4180  is, ie, js, je, isd, ied, jsd, jed, dir)
4181 
4182  !--- Now calculate the overlapping for fold-edge.
4183  !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4184  !--- only position at EAST and CORNER need to be considered
4185  if( ( position == east .OR. position == corner) ) then
4186  !fold is within domain
4187  if( domain%x(tme)%domain_data%begin .LE. isg .AND. isg .LE. domain%x(tme)%domain_data%end+ishift )then
4188  dir = 5
4189  !--- calculating overlapping for receving on north
4190  if( domain%y(tme)%pos .GE. size(domain%y(tme)%list(:))/2 )then
4191  isd = domain%x(tme)%compute%begin; ied = isd
4192  if( isd == isg )then ! fold is within domain.
4193  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4194  is=isc; ie=iec; js = jsc; je = jec
4195  select case (position)
4196  case(east)
4197  jsd = max(jsd, middle)
4198  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4199  case(corner)
4200  jsd = max(jsd, middle)
4201  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4202  end select
4203  call insert_update_overlap(overlap, domain%list(m)%pe, &
4204  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
4205  is = max(is, isd); ie = min(ie, ied)
4206  js = max(js, jsd); je = min(je, jed)
4207  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4208  nrecv_check = nrecv_check+1
4209  call allocate_check_overlap(checklist(nrecv_check), 1)
4210  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
4211  tme, 3, one_hundred_eighty, is, ie, js, je)
4212  endif
4213  endif
4214  endif
4215  endif
4216  endif
4217  endif
4218  !--- copy the overlapping information
4219  if( overlap%count > 0) then
4220  nrecv = nrecv + 1
4221  if(nrecv > maxlist) call mpp_error(fatal, &
4222  "mpp_domains_define.inc(compute_overlaps_west): nrecv is greater than MAXLIST, increase MAXLIST")
4223  call add_update_overlap( overlaplist(nrecv), overlap)
4224  call init_overlap_type(overlap)
4225  endif
4226  enddo ! end of recv do loop
4227 
4228  if(debug_message_passing) then
4229  !--- write out send information
4230  iunit = mpp_pe() + 1000
4231  do m =1,nrecv
4232  write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
4233  do n = 1, overlaplist(m)%count
4234  write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
4235  overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
4236  enddo
4237  enddo
4238  if(nrecv >0) flush(iunit)
4239  endif
4240 
4241  ! copy the overlapping information into domain
4242  if(nrecv>0) then
4243  update%nrecv = nrecv
4244  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
4245  allocate(update%recv(nrecv))
4246  do m = 1, nrecv
4247  call add_update_overlap( update%recv(m), overlaplist(m) )
4248  do n = 1, update%recv(m)%count
4249  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
4250  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
4251  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
4252  endif
4253  enddo
4254  enddo
4255  endif
4256 
4257  if(nrecv_check>0) then
4258  check%nrecv = nrecv_check
4259  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
4260  allocate(check%recv(nrecv_check))
4261  do m = 1, nrecv_check
4262  call add_check_overlap( check%recv(m), checklist(m) )
4263  enddo
4264  endif
4265 
4266  call deallocate_overlap_type(overlap)
4267  do m = 1, maxlist
4268  call deallocate_overlap_type(overlaplist(m))
4269  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4270  enddo
4271 
4272  update=>null()
4273  check=>null()
4274  domain%initialized = .true.
4275 
4276  end subroutine compute_overlaps_fold_west
4277 
4278  !###############################################################################
4279  !> computes remote domain overlaps
4280  !! assumes only one in each direction
4281  !! will calculate the overlapping for T,E,C,N-cell separately.
4282  !! here assume fold-east and y-cyclic boundary condition
4283  subroutine compute_overlaps_fold_east( domain, position, ishift, jshift )
4284  type(domain2d), intent(inout) :: domain
4285  integer, intent(in) :: position, ishift, jshift
4286 
4287  integer :: j, m, n, nlist, tMe, tNbr, dir
4288  integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd
4289  integer :: jed, isg, ieg, jsg, jeg, ioff, joff
4290  integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
4291  integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
4292  logical :: folded
4293  type(overlap_type) :: overlap
4294  type(overlapspec), pointer :: update=>null()
4295  type(overlap_type) :: overlapList(MAXLIST)
4296  type(overlap_type) :: checkList(MAXLIST)
4297  type(overlapspec), pointer :: check =>null()
4298  integer :: nsend, nrecv
4299  integer :: nsend_check, nrecv_check
4300 
4301  !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
4302  !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
4303  !--- In this case the overlapping exist only for tMe=1 and tNbr=1
4304  if(size(domain%x(:)) > 1) return
4305 
4306  !--- if there is no halo, no need to compute overlaps.
4307  if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
4308 
4309  !--- when there is only one tile, n will equal to np
4310  nlist = size(domain%list(:))
4311 
4312  select case(position)
4313  case (center)
4314  update => domain%update_T
4315  case (corner)
4316  update => domain%update_C
4317  check => domain%check_C
4318  case (east)
4319  update => domain%update_E
4320  check => domain%check_E
4321  case (north)
4322  update => domain%update_N
4323  check => domain%check_N
4324  case default
4325  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east):"// &
4326  & " the value of position should be CENTER, EAST, CORNER or NORTH")
4327  end select
4328 
4329  !--- overlap is used to store the overlapping temporarily.
4330  call allocate_update_overlap( overlap, maxoverlap)
4331 
4332  !send
4333  call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
4334  call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
4335  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
4336  update%xbegin = ism; update%xend = iem
4337  update%ybegin = jsm; update%yend = jem
4338  if(ASSOCIATED(check)) then
4339  check%xbegin = ism; check%xend = iem
4340  check%ybegin = jsm; check%yend = jem
4341  endif
4342  update%whalo = domain%whalo; update%ehalo = domain%ehalo
4343  update%shalo = domain%shalo; update%nhalo = domain%nhalo
4344  whalo = domain%whalo; ehalo = domain%ehalo
4345  shalo = domain%shalo; nhalo = domain%nhalo
4346 
4347  ioff = ni - ishift
4348  joff = nj - jshift
4349  middle = (jsg+jeg)/2+1
4350  tme = 1; tnbr = 1
4351 
4352  if(.NOT. btest(domain%fold,east)) then
4353  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4354  "boundary condition in y-direction should be folded-east for "//trim(domain%name))
4355  endif
4356  if(.NOT. domain%y(tme)%cyclic) then
4357  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4358  "boundary condition in y-direction should be cyclic for "//trim(domain%name))
4359  endif
4360  if(.not. domain%symmetry) then
4361  call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4362  "when east boundary is folded, the domain must be symmetry for "//trim(domain%name))
4363  endif
4364 
4365  nsend = 0
4366  nsend_check = 0
4367  do list = 0,nlist-1
4368  m = mod( domain%pos+list, nlist )
4369  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4370  !to_pe's eastern halo
4371  dir = 1
4372  folded = .false.
4373  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4374  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4375  if( ie.GT.ieg )then
4376  folded = .true.
4377  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4378  end if
4379  !--- when domain symmetry and position is EAST or CORNER, the point when jsc == je,
4380  !--- no need to send, because the data on that point will come from other pe.
4381  !--- come from two pe ( there will be only one point on one pe. ).
4382  if( (position == east .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
4383  !--- do nothing, this point will come from other pe
4384  else
4385  call insert_update_overlap( overlap, domain%list(m)%pe, &
4386  is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
4387  endif
4388  !--- when east edge is folded, js .LT. jsg
4389  if(js .LT. jsg) then
4390  js = js + ioff
4391  call insert_update_overlap( overlap, domain%list(m)%pe, &
4392  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4393  endif
4394 
4395  !to_pe's SE halo
4396  dir = 2
4397  folded = .false.
4398  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4399  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4400  if( jsg.GT.js .AND. je.LT.jsc )then !try cyclic offset
4401  js = js+joff; je = je+joff
4402  end if
4403 
4404  if( ie.GT.ieg )then
4405  folded = .true.
4406  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4407  end if
4408 
4409  call insert_update_overlap( overlap, domain%list(m)%pe, &
4410  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4411  !--- when east edge is folded,
4412  if(js .LT. jsg) then
4413  js = js + joff
4414  call insert_update_overlap( overlap, domain%list(m)%pe, &
4415  is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4416  endif
4417 
4418  !to_pe's southern halo
4419  dir = 3
4420  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
4421  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4422  !--- to make sure the consistence between pes
4423  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
4424  !--- do nothing, this point will come from other pe
4425  else
4426  if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
4427  js = js+joff; je = je+joff
4428  endif
4429  !--- when the east face is folded, the south halo points at
4430  !--- the position should be on CORNER or EAST
4431  if( ie == ieg .AND. (position == corner .OR. position == east) &
4432  .AND. ( domain%list(m)%y(tnbr)%compute%begin == jsg .OR. &
4433  domain%list(m)%y(tnbr)%compute%begin-1 .GE. middle ) ) then
4434  call insert_update_overlap( overlap, domain%list(m)%pe, &
4435  is, ie-1, js, je, isc, iec, jsc, jec, dir)
4436  !--- consider at i = ieg for east edge.
4437  !--- when the data is at corner and not symmetry, j = jsg -1 will get from cyclic condition
4438  if(position == corner .AND. .NOT. domain%symmetry .AND. domain%list(m)%y(tnbr)%compute%begin==jsg)then
4439  call insert_update_overlap(overlap, domain%list(m)%pe, &
4440  ie, ie, je, je, isc, iec, jsc, jec, dir, .true.)
4441  end if
4442 
4443  ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4444  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4445  if ( domain%list(m)%y(tnbr)%compute%begin == jsg ) then
4446  select case (position)
4447  case(east)
4448  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4449  case(corner)
4450  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4451  end select
4452  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4453  'mpp_domains_define.inc(compute_overlaps_fold_east: south edge ubound error send.' )
4454  else
4455  select case (position)
4456  case(east)
4457  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4458  case(corner)
4459  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4460  end select
4461  end if
4462  call insert_update_overlap( overlap, domain%list(m)%pe, &
4463  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4464  else
4465  call insert_update_overlap( overlap, domain%list(m)%pe, &
4466  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4467  end if
4468  endif
4469 
4470  !to_pe's SW halo
4471  dir = 4
4472  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4473  js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4474  if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
4475  js = js+joff; je = je+joff
4476  end if
4477  call insert_update_overlap( overlap, domain%list(m)%pe, &
4478  is, ie, js, je, isc, iec, jsc, jec, dir)
4479 
4480  !to_pe's western halo
4481  dir = 5
4482  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4483  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4484  call insert_update_overlap( overlap, domain%list(m)%pe, &
4485  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4486 
4487  !to_pe's NW halo
4488  dir = 6
4489  is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4490  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4491  if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
4492  js = js-joff; je = je-joff
4493  end if
4494  call insert_update_overlap( overlap, domain%list(m)%pe, &
4495  is, ie, js, je, isc, iec, jsc, jec, dir)
4496 
4497  !to_pe's northern halo
4498  dir = 7
4499  folded = .false.
4500  is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
4501  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4502  !--- to make sure the consistence between pes
4503  if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
4504  !--- do nothing, this point will come from other pe
4505  else
4506  if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
4507  js = js-joff; je = je-joff
4508  endif
4509  !--- when the east face is folded, the north halo points at
4510  !--- the position should be on CORNER or EAST
4511  if( ie == ieg .AND. (position == corner .OR. position == east) &
4512  .AND. ( js .GE. middle .AND. domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
4513  call insert_update_overlap( overlap, domain%list(m)%pe, &
4514  is, ie-1, js, je, isc, iec, jsc, jec, dir)
4515  ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4516  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4517  select case (position)
4518  case(east)
4519  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4520  case(corner)
4521  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4522  end select
4523  call insert_update_overlap( overlap, domain%list(m)%pe, &
4524  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4525  else
4526  call insert_update_overlap( overlap, domain%list(m)%pe, &
4527  is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4528  end if
4529  endif
4530 
4531  !to_pe's NE halo
4532  dir = 8
4533  folded = .false.
4534  is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4535  js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4536  if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
4537  js = js-joff; je = je-joff
4538  end if
4539  if( ie.GT.ieg )then
4540  folded = .true.
4541  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4542  end if
4543 
4544  call insert_update_overlap( overlap, domain%list(m)%pe, &
4545  is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4546 
4547  !--- Now calculate the overlapping for fold-edge.
4548  !--- only position at EAST and CORNER need to be considered
4549  if( ( position == east .OR. position == corner) ) then
4550  !fold is within domain
4551  if( domain%x(tme)%domain_data%begin .LE. ieg .AND. ieg .LE. domain%x(tme)%domain_data%end+ishift )then
4552  dir = 1
4553  !--- calculate the overlapping for sending
4554  if( domain%y(tme)%pos .LT. (size(domain%y(tme)%list(:))+1)/2 )then
4555  ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4556  if( ie == ieg )then ! fold is within domain.
4557  js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4558  select case (position)
4559  case(east)
4560  js = max(js, middle)
4561  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4562  case(corner)
4563  js = max(js, middle)
4564  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4565  end select
4566  call insert_update_overlap(overlap, domain%list(m)%pe, &
4567  is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4568  is = max(is, isc); ie = min(ie, iec)
4569  js = max(js, jsc); je = min(je, jec)
4570  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4571  nsend_check = nsend_check+1
4572  call allocate_check_overlap(checklist(nsend_check), 1)
4573  call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
4574  tme, 1, one_hundred_eighty, is, ie, js, je)
4575  end if
4576  end if
4577  end if
4578  end if
4579  end if
4580  end if
4581  !--- copy the overlapping information
4582  if( overlap%count > 0) then
4583  nsend = nsend + 1
4584  if(nsend > maxlist) call mpp_error(fatal, &
4585  "mpp_domains_define.inc(compute_overlaps_east): nsend is greater than MAXLIST, increase MAXLIST")
4586  call add_update_overlap(overlaplist(nsend), overlap)
4587  call init_overlap_type(overlap)
4588  endif
4589  end do ! end of send set up.
4590 
4591  ! copy the overlapping information into domain data structure
4592  if(nsend>0) then
4593  update%nsend = nsend
4594  if (associated(update%send)) deallocate(update%send) !< Check if associated
4595  allocate(update%send(nsend))
4596  do m = 1, nsend
4597  call add_update_overlap( update%send(m), overlaplist(m) )
4598  enddo
4599  endif
4600 
4601  if(nsend_check>0) then
4602  check%nsend = nsend_check
4603  if (associated(check%send)) deallocate(check%send) !< Check if associated
4604  allocate(check%send(nsend_check))
4605  do m = 1, nsend_check
4606  call add_check_overlap( check%send(m), checklist(m) )
4607  enddo
4608  endif
4609 
4610  do m = 1, maxlist
4611  call deallocate_overlap_type(overlaplist(m))
4612  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4613  enddo
4614 
4615  isgd = isg - domain%whalo
4616  iegd = ieg + domain%ehalo
4617  jsgd = jsg - domain%shalo
4618  jegd = jeg + domain%nhalo
4619 
4620  ! begin setting up recv
4621  nrecv = 0
4622  nrecv_check = 0
4623  do list = 0,nlist-1
4624  m = mod( domain%pos+nlist-list, nlist )
4625  if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4626  isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4627  jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4628  !recv_e
4629  dir = 1
4630  folded = .false.
4631  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4632  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4633  is=isc; ie=iec; js=jsc; je=jec
4634  if( ied.GT.ieg )then
4635  folded = .true.
4636  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4637  end if
4638  if( (position == east .OR. position == corner ) .AND. (jsd == je .or. jed == js ) ) then
4639  !--- do nothing, this point will come from other pe
4640  else
4641  call insert_update_overlap(overlap, domain%list(m)%pe, &
4642  is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4643  end if
4644  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4645  if(js .LT. jsg ) then
4646  js = js + joff
4647  call insert_update_overlap(overlap, domain%list(m)%pe, &
4648  is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4649  endif
4650 
4651  !recv_se
4652  dir = 2
4653  folded = .false.
4654  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4655  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4656  is=isc; ie=iec; js=jsc; je=jec
4657  if( ied.GT.ieg )then
4658  folded = .true.
4659  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4660  end if
4661  if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4662  js = js-joff; je = je-joff
4663  end if
4664  call insert_update_overlap(overlap, domain%list(m)%pe, &
4665  is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4666  !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4667  if(js .LT. jsg ) then
4668  js = js + joff
4669  call insert_update_overlap(overlap, domain%list(m)%pe, &
4670  is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4671  endif
4672 
4673  !recv_s
4674  dir = 3
4675  folded = .false.
4676  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4677  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4678  is=isc; ie=iec; js=jsc; je=jec
4679 
4680  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4681  !--- do nothing, this point will come from other pe
4682  else
4683  if( jsd.LT.jsg .AND. js .GT. jed)then
4684  js = js-joff; je = je-joff
4685  end if
4686  !--- when the east face is folded, the south halo points at
4687  !--- the position should be on CORNER or EAST
4688  if( ied == ieg .AND. (position == corner .OR. position == east) &
4689  .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4690  call insert_update_overlap( overlap, domain%list(m)%pe, &
4691  is, ie, js, je, isd, ied-1, jsd, jed, dir)
4692  is=isc; ie=iec; js=jsc; je=jec
4693  if(jsd<jsg) then
4694  select case (position)
4695  case(east)
4696  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4697  case(corner)
4698  j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4699  end select
4700  if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4701  'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4702  else
4703  select case (position)
4704  case(east)
4705  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4706  case(corner)
4707  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4708  end select
4709  end if
4710  call insert_update_overlap( overlap, domain%list(m)%pe, &
4711  is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4712  else
4713  call insert_update_overlap( overlap, domain%list(m)%pe, &
4714  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4715  end if
4716  endif
4717 
4718  !recv_sw
4719  dir = 4
4720  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4721  jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4722  is=isc; ie=iec; js=jsc; je=jec
4723  if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4724  js = js-joff; je = je-joff
4725  end if
4726  call insert_update_overlap(overlap, domain%list(m)%pe, &
4727  is, ie, js, je, isd, ied, jsd, jed, dir)
4728 
4729  !recv_w
4730  dir = 5
4731  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4732  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4733  is=isc; ie=iec; js=jsc; je=jec
4734  call insert_update_overlap( overlap, domain%list(m)%pe, &
4735  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4736 
4737  !recv_nw
4738  dir = 6
4739  folded = .false.
4740  isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4741  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4742  is=isc; ie=iec; js=jsc; je=jec
4743  if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4744  js = js+joff; je = je+joff
4745  end if
4746  call insert_update_overlap( overlap, domain%list(m)%pe, &
4747  is, ie, js, je, isd, ied, jsd, jed, dir)
4748 
4749  !recv_n
4750  dir = 7
4751  folded = .false.
4752  isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4753  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4754  is=isc; ie=iec; js=jsc; je=jec
4755  if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4756  !--- do nothing, this point will come from other pe
4757  else
4758  if( jed.GT.jeg .AND. je.LT.jsd)then
4759  js = js+joff; je = je+joff
4760  end if
4761  !--- when the east face is folded, the south halo points at
4762  !--- the position should be on CORNER or EAST
4763  if( ied == ieg .AND. (position == corner .OR. position == east) &
4764  .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4765  call insert_update_overlap( overlap, domain%list(m)%pe, &
4766  is, ie, js, je, isd, ied-1, jsd, jed, dir)
4767  is=isc; ie=iec; js=jsc; je=jec
4768  select case (position)
4769  case(east)
4770  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4771  case(corner)
4772  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4773  end select
4774  call insert_update_overlap( overlap, domain%list(m)%pe, &
4775  is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4776  else
4777  call insert_update_overlap( overlap, domain%list(m)%pe, &
4778  is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4779  end if
4780  endif
4781 
4782  !recv_ne
4783  dir = 8
4784  folded = .false.
4785  isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4786  jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4787  is=isc; ie=iec; js=jsc; je=jec
4788  if( ied.GT.ieg) then
4789  folded = .true.
4790  call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4791  end if
4792  if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4793  js = js+joff; je = je+joff
4794  endif
4795 
4796  call insert_update_overlap( overlap, domain%list(m)%pe, &
4797  is, ie, js, je, isd, ied, jsd, jed, dir)
4798  !--- Now calculate the overlapping for fold-edge.
4799  !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4800  !--- only position at EAST and CORNER need to be considered
4801  if( ( position == east .OR. position == corner) ) then
4802  !fold is within domain
4803  if( domain%x(tme)%domain_data%begin .LE. ieg .AND. ieg .LE. domain%x(tme)%domain_data%end+ishift )then
4804  dir = 1
4805  !--- calculating overlapping for receving on north
4806  if( domain%y(tme)%pos .GE. size(domain%y(tme)%list(:))/2 )then
4807  ied = domain%x(tme)%compute%end+ishift; isd = ied
4808  if( ied == ieg )then ! fold is within domain.
4809  jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4810  is=isc; ie=iec; js = jsc; je = jec
4811  select case (position)
4812  case(east)
4813  jsd = max(jsd, middle)
4814  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4815  case(corner)
4816  jsd = max(jsd, middle)
4817  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4818  end select
4819  call insert_update_overlap(overlap, domain%list(m)%pe, &
4820  is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
4821  is = max(is, isd); ie = min(ie, ied)
4822  js = max(js, jsd); je = min(je, jed)
4823  if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4824  nrecv_check = nrecv_check+1
4825  call allocate_check_overlap(checklist(nrecv_check), 1)
4826  call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
4827  tme, 3, one_hundred_eighty, is, ie, js, je)
4828  endif
4829  endif
4830  endif
4831  endif
4832  endif
4833  endif
4834  !--- copy the overlapping information
4835  if( overlap%count > 0) then
4836  nrecv = nrecv + 1
4837  if(nrecv > maxlist) call mpp_error(fatal, &
4838  "mpp_domains_define.inc(compute_overlaps_east): nrecv is greater than MAXLIST, increase MAXLIST")
4839  call add_update_overlap( overlaplist(nrecv), overlap)
4840  call init_overlap_type(overlap)
4841  endif
4842  enddo ! end of recv do loop
4843 
4844  ! copy the overlapping information into domain
4845  if(nrecv>0) then
4846  update%nrecv = nrecv
4847  if (associated(update%recv)) deallocate(update%recv) !< Check if associated
4848  allocate(update%recv(nrecv))
4849  do m = 1, nrecv
4850  call add_update_overlap( update%recv(m), overlaplist(m) )
4851  do n = 1, update%recv(m)%count
4852  if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
4853  if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
4854  if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
4855  endif
4856  enddo
4857  enddo
4858  endif
4859 
4860  if(nrecv_check>0) then
4861  check%nrecv = nrecv_check
4862  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
4863  allocate(check%recv(nrecv_check))
4864  do m = 1, nrecv_check
4865  call add_check_overlap( check%recv(m), checklist(m) )
4866  enddo
4867  endif
4868 
4869  call deallocate_overlap_type(overlap)
4870  do m = 1, maxlist
4871  call deallocate_overlap_type(overlaplist(m))
4872  if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4873  enddo
4874 
4875  update=>null()
4876  check=>null()
4877 
4878  domain%initialized = .true.
4879 
4880  end subroutine compute_overlaps_fold_east
4881 
4882  !#####################################################################################
4883  subroutine get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4884  integer, intent(in) :: jsg, jeg, isg, jshift, position
4885  integer, intent(inout) :: is, ie, js, je
4886  integer :: i, j
4887 
4888  select case(position)
4889  case(center)
4890  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4891  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4892  case(east)
4893  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4894  i=is; is = 2*isg-ie; ie = 2*isg-i
4895  case(north)
4896  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4897  i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4898  case(corner)
4899  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4900  i=is; is = 2*isg-ie; ie = 2*isg-i
4901  end select
4902 
4903  end subroutine get_fold_index_west
4904 
4905  !#####################################################################################
4906  subroutine get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4907  integer, intent(in) :: jsg, jeg, ieg, jshift, position
4908  integer, intent(inout) :: is, ie, js, je
4909  integer :: i, j
4910 
4911  select case(position)
4912  case(center)
4913  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4914  i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4915  case(east)
4916  j=js; js = jsg+jeg-je; je = jsg+jeg-j
4917  i=is; is = 2*ieg-ie; ie = 2*ieg-i
4918  case(north)
4919  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4920  i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4921  case(corner)
4922  j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4923  i=is; is = 2*ieg-ie; ie = 2*ieg-i
4924  end select
4925 
4926  end subroutine get_fold_index_east
4927 
4928  !#####################################################################################
4929  subroutine get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
4930  integer, intent(in) :: isg, ieg, jsg, ishift, position
4931  integer, intent(inout) :: is, ie, js, je
4932  integer :: i, j
4933 
4934  select case(position)
4935  case(center)
4936  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4937  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4938  case(east)
4939  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4940  j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4941  case(north)
4942  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4943  j=js; js = 2*jsg-je; je = 2*jsg-j
4944  case(corner)
4945  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4946  j=js; js = 2*jsg-je; je = 2*jsg-j
4947  end select
4948 
4949  end subroutine get_fold_index_south
4950  !#####################################################################################
4951  subroutine get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
4952  integer, intent(in) :: isg, ieg, jeg, ishift, position
4953  integer, intent(inout) :: is, ie, js, je
4954  integer :: i, j
4955 
4956  select case(position)
4957  case(center)
4958  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4959  j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4960  case(east)
4961  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4962  j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4963  case(north)
4964  i=is; is = isg+ieg-ie; ie = isg+ieg-i
4965  j=js; js = 2*jeg-je; je = 2*jeg-j
4966  case(corner)
4967  i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4968  j=js; js = 2*jeg-je; je = 2*jeg-j
4969  end select
4970 
4971  end subroutine get_fold_index_north
4972 
4973 
4974  !#####################################################################################
4975  !> add offset to the index
4976  subroutine apply_cyclic_offset(lstart, lend, offset, gstart, gend, gsize)
4977  integer, intent(inout) :: lstart, lend
4978  integer, intent(in ) :: offset, gstart, gend, gsize
4979 
4980  lstart = lstart + offset
4981  if(lstart > gend) lstart = lstart - gsize
4982  if(lstart < gstart) lstart = lstart + gsize
4983  lend = lend + offset
4984  if(lend > gend) lend = lend - gsize
4985  if(lend < gstart) lend = lend + gsize
4986 
4987  return
4988 
4989  end subroutine apply_cyclic_offset
4990 
4991  !###################################################################################
4992  !> this routine sets up the overlapping for mpp_update_domains for arbitrary halo update.
4993  !! should be the halo size defined in mpp_define_domains.
4994  !! xhalo_out, yhalo_out should not be exactly the same as xhalo_in, yhalo_in
4995  !! currently we didn't consider about tripolar grid situation, because in the folded north
4996  !! region, the overlapping is specified through list of points, not through rectangular.
4997  !! But will return back to solve this problem in the future.
4998  subroutine set_overlaps(domain, overlap_in, overlap_out, whalo_out, ehalo_out, shalo_out, nhalo_out)
4999  type(domain2d), intent(in) :: domain
5000  type(overlapspec), intent(in) :: overlap_in
5001  type(overlapspec), intent(inout) :: overlap_out
5002  integer, intent(in) :: whalo_out, ehalo_out, shalo_out, nhalo_out
5003  integer :: nlist, m, n, isoff, ieoff, jsoff, jeoff, rotation
5004  integer :: whalo_in, ehalo_in, shalo_in, nhalo_in
5005  integer :: dir
5006  type(overlap_type) :: overlap
5007  type(overlap_type), allocatable :: send(:), recv(:)
5008  type(overlap_type), pointer :: ptrIn => null()
5009  integer :: nsend, nrecv, nsend_in, nrecv_in
5010 
5011  if( domain%fold .NE. 0) call mpp_error(fatal, "mpp_domains_define.inc(set_overlaps):"// &
5012  & " folded domain is not implemented for arbitrary halo update, contact developer")
5013 
5014  whalo_in = domain%whalo
5015  ehalo_in = domain%ehalo
5016  shalo_in = domain%shalo
5017  nhalo_in = domain%nhalo
5018 
5019  if( .NOT. domain%initialized) call mpp_error(fatal, &
5020  "mpp_domains_define.inc: domain is not defined yet")
5021 
5022  nlist = size(domain%list(:))
5023  isoff = whalo_in - abs(whalo_out)
5024  ieoff = ehalo_in - abs(ehalo_out)
5025  jsoff = shalo_in - abs(shalo_out)
5026  jeoff = nhalo_in - abs(nhalo_out)
5027 
5028  nsend = 0
5029  nsend_in = overlap_in%nsend
5030  nrecv_in = overlap_in%nrecv
5031  if(nsend_in>0) allocate(send(nsend_in))
5032  if(nrecv_in>0) allocate(recv(nrecv_in))
5033  call allocate_update_overlap(overlap, maxoverlap)
5034 
5035  overlap_out%whalo = whalo_out
5036  overlap_out%ehalo = ehalo_out
5037  overlap_out%shalo = shalo_out
5038  overlap_out%nhalo = nhalo_out
5039  overlap_out%xbegin = overlap_in%xbegin
5040  overlap_out%xend = overlap_in%xend
5041  overlap_out%ybegin = overlap_in%ybegin
5042  overlap_out%yend = overlap_in%yend
5043 
5044  !--- setting up overlap.
5045  do m = 1, nsend_in
5046  ptrin => overlap_in%send(m)
5047  if(ptrin%count .LE. 0) call mpp_error(fatal, "mpp_domains_define.inc(set_overlaps):"// &
5048  " number of overlap for send should be a positive number for"//trim(domain%name) )
5049  do n = 1, ptrin%count
5050  dir = ptrin%dir(n)
5051  rotation = ptrin%rotation(n)
5052  select case(dir)
5053  case(1) ! to_pe's eastern halo
5054  if(ehalo_out > 0) then
5055  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, 0, n, dir, rotation)
5056  else if(ehalo_out<0) then
5057  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, 0, n, dir, rotation)
5058  end if
5059  case(2) ! to_pe's southeast halo
5060  if(ehalo_out>0 .AND. shalo_out > 0) then
5061  call set_single_overlap(ptrin, overlap, 0, -ieoff, jsoff, 0, n, dir, rotation)
5062  else if(ehalo_out<0 .AND. shalo_out < 0) then ! three parts: southeast, south and east.
5063  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, shalo_out, n, dir, rotation)
5064  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1, rotation)
5065  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, shalo_out, n, dir+1, rotation)
5066  end if
5067  case(3) ! to_pe's southern halo
5068  if(shalo_out > 0) then
5069  call set_single_overlap(ptrin, overlap, 0, 0, jsoff, 0, n, dir, rotation)
5070  else if(shalo_out<0) then
5071  call set_single_overlap(ptrin, overlap, 0, 0, 0, shalo_out, n, dir, rotation)
5072  end if
5073  case(4) ! to_pe's southwest halo
5074  if(whalo_out>0 .AND. shalo_out > 0) then
5075  call set_single_overlap(ptrin, overlap, isoff, 0, jsoff, 0, n, dir, rotation)
5076  else if(whalo_out<0 .AND. shalo_out < 0) then
5077  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, shalo_out, n, dir, rotation)
5078  call set_single_overlap(ptrin, overlap, isoff, 0, 0, shalo_out, n, dir-1, rotation)
5079  call set_single_overlap(ptrin, overlap, 0, whalo_out, jsoff, 0, n, dir+1, rotation)
5080  end if
5081  case(5) ! to_pe's western halo
5082  if(whalo_out > 0) then
5083  call set_single_overlap(ptrin, overlap, isoff, 0, 0, 0, n, dir, rotation)
5084  else if(whalo_out<0) then
5085  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, 0, n, dir, rotation)
5086  end if
5087  case(6) ! to_pe's northwest halo
5088  if(whalo_out>0 .AND. nhalo_out > 0) then
5089  call set_single_overlap(ptrin, overlap, isoff, 0, 0, -jeoff, n, dir, rotation)
5090  else if(whalo_out<0 .AND. nhalo_out < 0) then
5091  call set_single_overlap(ptrin, overlap, 0, whalo_out, -nhalo_out, 0, n, dir, rotation)
5092  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, -jeoff, n, dir-1, rotation)
5093  call set_single_overlap(ptrin, overlap, isoff, 0, -nhalo_out, 0, n, dir+1, rotation)
5094  end if
5095  case(7) ! to_pe's northern halo
5096  if(nhalo_out > 0) then
5097  call set_single_overlap(ptrin, overlap, 0, 0, 0, -jeoff, n, dir, rotation)
5098  else if(nhalo_out<0) then
5099  call set_single_overlap(ptrin, overlap, 0, 0, -nhalo_out, 0, n, dir, rotation)
5100  end if
5101  case(8) ! to_pe's northeast halo
5102  if(ehalo_out>0 .AND. nhalo_out > 0) then
5103  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, -jeoff, n, dir, rotation)
5104  else if(ehalo_out<0 .AND. nhalo_out < 0) then
5105  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir, rotation)
5106  call set_single_overlap(ptrin, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1, rotation)
5107  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, -jeoff, n, 1, rotation)
5108  end if
5109  end select
5110  end do ! do n = 1, ptrIn%count
5111  if(overlap%count>0) then
5112  nsend = nsend+1
5113  call add_update_overlap(send(nsend), overlap)
5114  call init_overlap_type(overlap)
5115  endif
5116  end do ! end do list = 0, nlist-1
5117 
5118  if(nsend>0) then
5119  overlap_out%nsend = nsend
5120  if (associated(overlap_out%send)) deallocate(overlap_out%send) !< Check if associated
5121  allocate(overlap_out%send(nsend));
5122  do n = 1, nsend
5123  call add_update_overlap(overlap_out%send(n), send(n) )
5124  enddo
5125  else
5126  overlap_out%nsend = 0
5127  endif
5128 
5129  !--------------------------------------------------
5130  ! recving
5131  !---------------------------------------------------
5132  overlap%count = 0
5133  nrecv = 0
5134  do m = 1, nrecv_in
5135  ptrin => overlap_in%recv(m)
5136  if(ptrin%count .LE. 0) call mpp_error(fatal, &
5137  "mpp_domains_define.inc(set_overlaps): number of overlap for recv should be a positive number")
5138  overlap%count = 0
5139  do n = 1, ptrin%count
5140  dir = ptrin%dir(n)
5141  rotation = ptrin%rotation(n)
5142  select case(dir)
5143  case(1) ! eastern halo
5144  if(ehalo_out > 0) then
5145  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, 0, n, dir)
5146  else if(ehalo_out<0) then
5147  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, 0, n, dir)
5148  end if
5149  case(2) ! southeast halo
5150  if(ehalo_out>0 .AND. shalo_out > 0) then
5151  call set_single_overlap(ptrin, overlap, 0, -ieoff, jsoff, 0, n, dir)
5152  else if(ehalo_out<0 .AND. shalo_out < 0) then
5153  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, shalo_out, n, dir)
5154  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1)
5155  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, shalo_out, n, dir+1)
5156  end if
5157  case(3) ! southern halo
5158  if(shalo_out > 0) then
5159  call set_single_overlap(ptrin, overlap, 0, 0, jsoff, 0, n, dir)
5160  else if(shalo_out<0) then
5161  call set_single_overlap(ptrin, overlap, 0, 0, 0, shalo_out, n, dir)
5162  end if
5163  case(4) ! southwest halo
5164  if(whalo_out>0 .AND. shalo_out > 0) then
5165  call set_single_overlap(ptrin, overlap, isoff, 0, jsoff, 0, n, dir)
5166  else if(whalo_out<0 .AND. shalo_out < 0) then
5167  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, shalo_out, n, dir)
5168  call set_single_overlap(ptrin, overlap, isoff, 0, 0, shalo_out, n, dir-1)
5169  call set_single_overlap(ptrin, overlap, 0, whalo_out, jsoff, 0, n, dir+1)
5170  end if
5171  case(5) ! western halo
5172  if(whalo_out > 0) then
5173  call set_single_overlap(ptrin, overlap, isoff, 0, 0, 0, n, dir)
5174  else if(whalo_out<0) then
5175  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, 0, n, dir)
5176  end if
5177  case(6) ! northwest halo
5178  if(whalo_out>0 .AND. nhalo_out > 0) then
5179  call set_single_overlap(ptrin, overlap, isoff, 0, 0, -jeoff, n, dir)
5180  else if(whalo_out<0 .AND. nhalo_out < 0) then
5181  call set_single_overlap(ptrin, overlap, 0, whalo_out, -nhalo_out, 0, n, dir)
5182  call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, -jeoff, n, dir-1)
5183  call set_single_overlap(ptrin, overlap, isoff, 0, -nhalo_out, 0, n, dir+1)
5184  end if
5185  case(7) ! northern halo
5186  if(nhalo_out > 0) then
5187  call set_single_overlap(ptrin, overlap, 0, 0, 0, -jeoff, n, dir)
5188  else if(nhalo_out<0) then
5189  call set_single_overlap(ptrin, overlap, 0, 0, -nhalo_out, 0, n, dir)
5190  end if
5191  case(8) ! northeast halo
5192  if(ehalo_out>0 .AND. nhalo_out > 0) then
5193  call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, -jeoff, n, dir)
5194  else if(ehalo_out<0 .AND. nhalo_out < 0) then
5195  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir)
5196  call set_single_overlap(ptrin, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1)
5197  call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, -jeoff, n, 1)
5198  end if
5199  end select
5200  end do ! do n = 1, ptrIn%count
5201  if(overlap%count>0) then
5202  nrecv = nrecv+1
5203  call add_update_overlap(recv(nrecv), overlap)
5204  call init_overlap_type(overlap)
5205  endif
5206  end do ! end do list = 0, nlist-1
5207 
5208  if(nrecv>0) then
5209  overlap_out%nrecv = nrecv
5210  if (associated(overlap_out%recv)) deallocate(overlap_out%recv) !< Check if associated
5211  allocate(overlap_out%recv(nrecv));
5212  do n = 1, nrecv
5213  call add_update_overlap(overlap_out%recv(n), recv(n) )
5214  enddo
5215  else
5216  overlap_out%nrecv = 0
5217  endif
5218 
5219  call deallocate_overlap_type(overlap)
5220  do n = 1, nsend_in
5221  call deallocate_overlap_type(send(n))
5222  enddo
5223  do n = 1, nrecv_in
5224  call deallocate_overlap_type(recv(n))
5225  enddo
5226  if(allocated(send)) deallocate(send)
5227  if(allocated(recv)) deallocate(recv)
5228  ptrin => null()
5229 
5230  call set_domain_comm_inf(overlap_out)
5231 
5232 
5233  end subroutine set_overlaps
5234 
5235  !##############################################################################
5236  subroutine set_single_overlap(overlap_in, overlap_out, isoff, ieoff, jsoff, jeoff, index, dir, rotation)
5237  type(overlap_type), intent(in) :: overlap_in
5238  type(overlap_type), intent(inout) :: overlap_out
5239  integer, intent(in) :: isoff, jsoff, ieoff, jeoff
5240  integer, intent(in) :: index
5241  integer, intent(in) :: dir
5242  integer, optional, intent(in) :: rotation
5243  integer :: rotate
5244  integer :: count
5245 
5246  if( overlap_out%pe == null_pe ) then
5247  overlap_out%pe = overlap_in%pe
5248  else
5249  if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(fatal, &
5250  "mpp_domains_define.inc(set_single_overlap): mismatch of pe between overlap_in and overlap_out")
5251  endif
5252 
5253  if(isoff .NE. 0 .and. ieoff .NE. 0) call mpp_error(fatal, &
5254  "mpp_domains_define.inc(set_single_overlap): both isoff and ieoff are non-zero")
5255  if(jsoff .NE. 0 .and. jeoff .NE. 0) call mpp_error(fatal, &
5256  "mpp_domains_define.inc(set_single_overlap): both jsoff and jeoff are non-zero")
5257 
5258 
5259  overlap_out%count = overlap_out%count + 1
5260  count = overlap_out%count
5261  if(count > maxoverlap) call mpp_error(fatal, &
5262  "set_single_overlap: number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
5263  rotate = zero
5264  if(present(rotation)) rotate = rotation
5265  overlap_out%rotation (count) = overlap_in%rotation(index)
5266  overlap_out%dir (count) = dir
5267  overlap_out%tileMe (count) = overlap_in%tileMe(index)
5268  overlap_out%tileNbr (count) = overlap_in%tileNbr(index)
5269 
5270  select case(rotate)
5271  case(zero)
5272  overlap_out%is(count) = overlap_in%is(index) + isoff
5273  overlap_out%ie(count) = overlap_in%ie(index) + ieoff
5274  overlap_out%js(count) = overlap_in%js(index) + jsoff
5275  overlap_out%je(count) = overlap_in%je(index) + jeoff
5276  case(ninety)
5277  overlap_out%is(count) = overlap_in%is(index) - jeoff
5278  overlap_out%ie(count) = overlap_in%ie(index) - jsoff
5279  overlap_out%js(count) = overlap_in%js(index) + isoff
5280  overlap_out%je(count) = overlap_in%je(index) + ieoff
5281  case(minus_ninety)
5282  overlap_out%is(count) = overlap_in%is(index) + jsoff
5283  overlap_out%ie(count) = overlap_in%ie(index) + jeoff
5284  overlap_out%js(count) = overlap_in%js(index) - ieoff
5285  overlap_out%je(count) = overlap_in%je(index) - isoff
5286  case default
5287  call mpp_error(fatal, "mpp_domains_define.inc: the value of rotation should be ZERO, NINETY or MINUS_NINETY")
5288  end select
5289 
5290  end subroutine set_single_overlap
5291 
5292  !###################################################################################
5293  !> compute the overlapping between tiles for the T-cell.
5294  subroutine define_contact_point( domain, position, num_contact, tile1, tile2, align1, align2, &
5295  refine1, refine2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, &
5296  isgList, iegList, jsgList, jegList, tile_base )
5297  type(domain2d), intent(inout) :: domain
5298  integer, intent(in) :: position
5299  integer, intent(in) :: num_contact !< number of contact regions
5300  integer, dimension(:), intent(in) :: tile1, tile2 !< tile number
5301  integer, dimension(:), intent(in) :: align1, align2 !< align direction of contact region
5302  real, dimension(:), intent(in) :: refine1, refine2 !< refinement between tiles
5303  integer, dimension(:), intent(in) :: istart1, iend1 !< i-index in tile_1 of contact region
5304  integer, dimension(:), intent(in) :: jstart1, jend1 !< j-index in tile_1 of contact region
5305  integer, dimension(:), intent(in) :: istart2, iend2 !< i-index in tile_2 of contact region
5306  integer, dimension(:), intent(in) :: jstart2, jend2 !< j-index in tile_2 of contact region
5307  integer, dimension(:), intent(in) :: isgList, iegList !< i-global domain of each tile
5308  integer, dimension(:), intent(in) :: jsgList, jegList !< j-global domain of each tile
5309  integer, intent(in) :: tile_base !< Minimum tile ID minus 1
5310 
5311  integer :: isc, iec, jsc, jec, isd, ied, jsd, jed
5312  integer :: isc1, iec1, jsc1, jec1, isc2, iec2, jsc2, jec2
5313  integer :: isd1, ied1, jsd1, jed1, isd2, ied2, jsd2, jed2
5314  integer :: is, ie, js, je, ioff, joff
5315  integer :: ntiles, max_contact
5316  integer :: nlist, list, m, n, l, count, numS, numR
5317  integer :: whalo, ehalo, shalo, nhalo
5318  integer :: t1, t2, tt, pos
5319  integer :: ntileMe, ntileNbr, tMe, tNbr, tileMe, dir
5320  integer :: nxd, nyd, nxc, nyc, ism, iem, jsm, jem
5321  integer :: dirlist(8)
5322  !--- is2Send and is1Send will figure out the overlapping for sending from current pe.
5323  !--- is1Recv and iscREcv will figure out the overlapping for recving onto current pe.
5324  integer, dimension(4*num_contact) :: is1Send, ie1Send, js1Send, je1Send
5325  integer, dimension(4*num_contact) :: is2Send, ie2Send, js2Send, je2Send
5326  integer, dimension(4*num_contact) :: is2Recv, ie2Recv, js2Recv, je2Recv
5327  integer, dimension(4*num_contact) :: is1Recv, ie1Recv, js1Recv, je1Recv
5328  integer, dimension(4*num_contact) :: align1Recv, align2Recv, align1Send, align2Send
5329  real, dimension(4*num_contact) :: refineRecv, refineSend
5330  integer, dimension(4*num_contact) :: rotateSend, rotateRecv, tileSend, tileRecv
5331  integer :: nsend, nrecv, nsend2, nrecv2
5332  type(contact_type), dimension(domain%ntiles) :: eCont, wCont, sCont, nCont
5333  type(overlap_type), dimension(0:size(domain%list(:))-1) :: overlapSend, overlapRecv
5334  integer :: iunit
5335 
5336  if( position .NE. center ) call mpp_error(fatal, "mpp_domains_define.inc: " //&
5337  "routine define_contact_point can only be used to calculate overlapping for cell center.")
5338 
5339  ntiles = domain%ntiles
5340 
5341  econt(:)%ncontact = 0
5342 
5343  do n = 1, ntiles
5344  econt(n)%ncontact = 0; scont(n)%ncontact = 0; wcont(n)%ncontact = 0; ncont(n)%ncontact = 0;
5345  allocate(econt(n)%tile(num_contact), wcont(n)%tile(num_contact) )
5346  allocate(ncont(n)%tile(num_contact), scont(n)%tile(num_contact) )
5347  allocate(econt(n)%align1(num_contact), econt(n)%align2(num_contact) )
5348  allocate(wcont(n)%align1(num_contact), wcont(n)%align2(num_contact) )
5349  allocate(scont(n)%align1(num_contact), scont(n)%align2(num_contact) )
5350  allocate(ncont(n)%align1(num_contact), ncont(n)%align2(num_contact) )
5351  allocate(econt(n)%refine1(num_contact), econt(n)%refine2(num_contact) )
5352  allocate(wcont(n)%refine1(num_contact), wcont(n)%refine2(num_contact) )
5353  allocate(scont(n)%refine1(num_contact), scont(n)%refine2(num_contact) )
5354  allocate(ncont(n)%refine1(num_contact), ncont(n)%refine2(num_contact) )
5355  allocate(econt(n)%is1(num_contact), econt(n)%ie1(num_contact), econt(n)%js1(num_contact), &
5356  & econt(n)%je1(num_contact))
5357  allocate(econt(n)%is2(num_contact), econt(n)%ie2(num_contact), econt(n)%js2(num_contact), &
5358  & econt(n)%je2(num_contact))
5359  allocate(wcont(n)%is1(num_contact), wcont(n)%ie1(num_contact), wcont(n)%js1(num_contact), &
5360  & wcont(n)%je1(num_contact))
5361  allocate(wcont(n)%is2(num_contact), wcont(n)%ie2(num_contact), wcont(n)%js2(num_contact), &
5362  & wcont(n)%je2(num_contact))
5363  allocate(scont(n)%is1(num_contact), scont(n)%ie1(num_contact), scont(n)%js1(num_contact), &
5364  & scont(n)%je1(num_contact))
5365  allocate(scont(n)%is2(num_contact), scont(n)%ie2(num_contact), scont(n)%js2(num_contact), &
5366  & scont(n)%je2(num_contact))
5367  allocate(ncont(n)%is1(num_contact), ncont(n)%ie1(num_contact), ncont(n)%js1(num_contact), &
5368  & ncont(n)%je1(num_contact))
5369  allocate(ncont(n)%is2(num_contact), ncont(n)%ie2(num_contact), ncont(n)%js2(num_contact), &
5370  & ncont(n)%je2(num_contact))
5371  end do
5372 
5373  !--- set up the east, south, west and north contact for each tile.
5374  do n = 1, num_contact
5375  t1 = tile1(n) - tile_base
5376  t2 = tile2(n) - tile_base
5377  select case(align1(n))
5378  case (east)
5379  call fill_contact( econt(t1), tile2(n), istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5380  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5381  case (west)
5382  call fill_contact( wcont(t1), tile2(n), istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5383  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5384  case (south)
5385  call fill_contact( scont(t1), tile2(n), istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5386  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5387  case (north)
5388  call fill_contact( ncont(t1), tile2(n), istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5389  jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5390  end select
5391  select case(align2(n))
5392  case (east)
5393  call fill_contact( econt(t2), tile1(n), istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5394  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5395  case (west)
5396  call fill_contact( wcont(t2), tile1(n), istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5397  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5398  case (south)
5399  call fill_contact( scont(t2), tile1(n), istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5400  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5401  case (north)
5402  call fill_contact( ncont(t2), tile1(n), istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5403  jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5404  end select
5405  end do
5406 
5407  !--- the tile number of current pe, halo size
5408  whalo = domain%whalo
5409  ehalo = domain%ehalo
5410  shalo = domain%shalo
5411  nhalo = domain%nhalo
5412 
5413  !--- find if there is an extra point in x and y direction depending on position
5414  nlist = size(domain%list(:))
5415 
5416  max_contact = 4*num_contact ! should be enough
5417 
5418  ntileme = size(domain%x(:))
5419  refinesend = 1; refinerecv = 1
5420 
5421  !--------------------------------------------------------------------------------------------------
5422  ! loop over each tile on current domain to set up the overlapping for each tile
5423  !--------------------------------------------------------------------------------------------------
5424  !--- first check the overlap within the tiles.
5425  do n = 1, domain%update_T%nsend
5426  pos = domain%update_T%send(n)%pe - mpp_root_pe()
5427  call add_update_overlap(overlapsend(pos), domain%update_T%send(n) )
5428  enddo
5429  do n = 1, domain%update_T%nrecv
5430  pos = domain%update_T%recv(n)%pe - mpp_root_pe()
5431  call add_update_overlap(overlaprecv(pos), domain%update_T%recv(n) )
5432  enddo
5433 
5434  call mpp_get_memory_domain(domain, ism, iem, jsm, jem)
5435  domain%update_T%xbegin = ism; domain%update_T%xend = iem
5436  domain%update_T%ybegin = jsm; domain%update_T%yend = jem
5437  domain%update_T%whalo = whalo; domain%update_T%ehalo = ehalo
5438  domain%update_T%shalo = shalo; domain%update_T%nhalo = nhalo
5439 
5440  do tme = 1, ntileme
5441  tileme = domain%tile_id(tme) - tile_base
5442  rotatesend = zero; rotaterecv = zero
5443 
5444  !--- loop over all the contact region to figure out the index for overlapping region.
5445  count = 0
5446  do n = 1, econt(tileme)%ncontact ! east contact
5447  count = count+1
5448  tilerecv(count) = econt(tileme)%tile(n); tilesend(count) = econt(tileme)%tile(n)
5449  align1recv(count) = econt(tileme)%align1(n); align2recv(count) = econt(tileme)%align2(n)
5450  align1send(count) = econt(tileme)%align1(n); align2send(count) = econt(tileme)%align2(n)
5451  refinesend(count) = econt(tileme)%refine2(n); refinerecv(count) = econt(tileme)%refine1(n)
5452  is1recv(count) = econt(tileme)%is1(n) + 1; ie1recv(count) = is1recv(count) + ehalo - 1
5453  js1recv(count) = econt(tileme)%js1(n); je1recv(count) = econt(tileme)%je1(n)
5454  select case(econt(tileme)%align2(n))
5455  case ( west ) ! w <-> e
5456  is2recv(count) = econt(tileme)%is2(n); ie2recv(count) = is2recv(count) + ehalo - 1
5457  js2recv(count) = econt(tileme)%js2(n); je2recv(count) = econt(tileme)%je2(n)
5458  ie1send(count) = econt(tileme)%is1(n); is1send(count) = ie1send(count) - whalo + 1
5459  js1send(count) = econt(tileme)%js1(n); je1send(count) = econt(tileme)%je1(n)
5460  ie2send(count) = econt(tileme)%is2(n) - 1; is2send(count) = ie2send(count) - whalo + 1
5461  js2send(count) = econt(tileme)%js2(n); je2send(count) = econt(tileme)%je2(n)
5462  case ( south ) ! s <-> e
5463  rotaterecv(count) = ninety; rotatesend(count) = minus_ninety
5464  js2recv(count) = econt(tileme)%js2(n); je2recv(count) = js2recv(count) + ehalo -1
5465  is2recv(count) = econt(tileme)%is2(n); ie2recv(count) = econt(tileme)%ie2(n)
5466  ie1send(count) = econt(tileme)%is1(n); is1send(count) = ie1send(count) - shalo + 1
5467  js1send(count) = econt(tileme)%js1(n); je1send(count) = econt(tileme)%je1(n)
5468  is2send(count) = econt(tileme)%is2(n); ie2send(count) = econt(tileme)%ie2(n)
5469  je2send(count) = econt(tileme)%js2(n) - 1; js2send(count) = je2send(count) - shalo + 1
5470  end select
5471  end do
5472 
5473  do n = 1, scont(tileme)%ncontact ! south contact
5474  count = count+1
5475  tilerecv(count) = scont(tileme)%tile(n); tilesend(count) = scont(tileme)%tile(n)
5476  align1recv(count) = scont(tileme)%align1(n); align2recv(count) = scont(tileme)%align2(n);
5477  align1send(count) = scont(tileme)%align1(n); align2send(count) = scont(tileme)%align2(n);
5478  refinesend(count) = scont(tileme)%refine2(n); refinerecv(count) = scont(tileme)%refine1(n)
5479  is1recv(count) = scont(tileme)%is1(n); ie1recv(count) = scont(tileme)%ie1(n)
5480  je1recv(count) = scont(tileme)%js1(n) - 1; js1recv(count) = je1recv(count) - shalo + 1
5481  select case(scont(tileme)%align2(n))
5482  case ( north ) ! n <-> s
5483  is2recv(count) = scont(tileme)%is2(n); ie2recv(count) = scont(tileme)%ie2(n)
5484  je2recv(count) = scont(tileme)%je2(n); js2recv(count) = je2recv(count) - shalo + 1
5485  is1send(count) = scont(tileme)%is1(n); ie1send(count) = scont(tileme)%ie1(n)
5486  js1send(count) = scont(tileme)%js1(n); je1send(count) = js1send(count) + nhalo -1
5487  is2send(count) = scont(tileme)%is2(n); ie2send(count) = scont(tileme)%ie2(n)
5488  js2send(count) = scont(tileme)%je2(n)+1; je2send(count) = js2send(count) + nhalo - 1
5489  case ( east ) ! e <-> s
5490  rotaterecv(count) = minus_ninety; rotatesend(count) = ninety
5491  ie2recv(count) = scont(tileme)%ie2(n); is2recv(count) = ie2recv(count) - shalo + 1
5492  js2recv(count) = scont(tileme)%js2(n); je2recv(count) = scont(tileme)%je2(n)
5493  is1send(count) = scont(tileme)%is1(n); ie1send(count) = scont(tileme)%ie1(n)
5494  js1send(count) = scont(tileme)%js1(n); je1send(count) = js1send(count) + ehalo - 1
5495  is2send(count) = scont(tileme)%ie2(n)+1; ie2send(count) = is2send(count) + ehalo - 1
5496  js2send(count) = scont(tileme)%js2(n); je2send(count) = scont(tileme)%je2(n)
5497  end select
5498  end do
5499 
5500  do n = 1, wcont(tileme)%ncontact ! west contact
5501  count = count+1
5502  tilerecv(count) = wcont(tileme)%tile(n); tilesend(count) = wcont(tileme)%tile(n)
5503  align1recv(count) = wcont(tileme)%align1(n); align2recv(count) = wcont(tileme)%align2(n);
5504  align1send(count) = wcont(tileme)%align1(n); align2send(count) = wcont(tileme)%align2(n);
5505  refinesend(count) = wcont(tileme)%refine2(n); refinerecv(count) = wcont(tileme)%refine1(n)
5506  ie1recv(count) = wcont(tileme)%is1(n) - 1; is1recv(count) = ie1recv(count) - whalo + 1
5507  js1recv(count) = wcont(tileme)%js1(n); je1recv(count) = wcont(tileme)%je1(n)
5508  select case(wcont(tileme)%align2(n))
5509  case ( east ) ! e <-> w
5510  ie2recv(count) = wcont(tileme)%ie2(n); is2recv(count) = ie2recv(count) - whalo + 1
5511  js2recv(count) = wcont(tileme)%js2(n); je2recv(count) = wcont(tileme)%je2(n)
5512  is1send(count) = wcont(tileme)%is1(n); ie1send(count) = is1send(count) + ehalo - 1
5513  js1send(count) = wcont(tileme)%js1(n); je1send(count) = wcont(tileme)%je1(n)
5514  is2send(count) = wcont(tileme)%ie2(n)+1; ie2send(count) = is2send(count) + ehalo - 1
5515  js2send(count) = wcont(tileme)%js2(n); je2send(count) = wcont(tileme)%je2(n)
5516  case ( north ) ! n <-> w
5517  rotaterecv(count) = ninety; rotatesend(count) = minus_ninety
5518  je2recv(count) = wcont(tileme)%je2(n); js2recv(count) = je2recv(count) - whalo + 1
5519  is2recv(count) = wcont(tileme)%is2(n); ie2recv(count) = wcont(tileme)%ie2(n)
5520  is1send(count) = wcont(tileme)%is1(n); ie1send(count) = is1send(count) + nhalo - 1
5521  js1send(count) = wcont(tileme)%js1(n); je1send(count) = wcont(tileme)%je1(n)
5522  js2send(count) = wcont(tileme)%je2(n)+1; je2send(count) = js2send(count) + nhalo - 1
5523  is2send(count) = wcont(tileme)%is2(n); ie2send(count) = wcont(tileme)%ie2(n)
5524  end select
5525  end do
5526 
5527  do n = 1, ncont(tileme)%ncontact ! north contact
5528  count = count+1
5529  tilerecv(count) = ncont(tileme)%tile(n); tilesend(count) = ncont(tileme)%tile(n)
5530  align1recv(count) = ncont(tileme)%align1(n); align2recv(count) = ncont(tileme)%align2(n);
5531  align1send(count) = ncont(tileme)%align1(n); align2send(count) = ncont(tileme)%align2(n);
5532  refinesend(count) = ncont(tileme)%refine2(n); refinerecv(count) = ncont(tileme)%refine1(n)
5533  is1recv(count) = ncont(tileme)%is1(n); ie1recv(count) = ncont(tileme)%ie1(n)
5534  js1recv(count) = ncont(tileme)%je1(n)+1; je1recv(count) = js1recv(count) + nhalo - 1
5535  select case(ncont(tileme)%align2(n))
5536  case ( south ) ! s <-> n
5537  is2recv(count) = ncont(tileme)%is2(n); ie2recv(count) = ncont(tileme)%ie2(n)
5538  js2recv(count) = ncont(tileme)%js2(n); je2recv(count) = js2recv(count) + nhalo - 1
5539  is1send(count) = ncont(tileme)%is1(n); ie1send(count) = ncont(tileme)%ie1(n)
5540  je1send(count) = ncont(tileme)%je1(n); js1send(count) = je1send(count) - shalo + 1
5541  is2send(count) = ncont(tileme)%is2(n); ie2send(count) = ncont(tileme)%ie2(n)
5542  je2send(count) = ncont(tileme)%js2(n)-1; js2send(count) = je2send(count) - shalo + 1
5543  case ( west ) ! w <-> n
5544  rotaterecv(count) = minus_ninety; rotatesend(count) = ninety
5545  is2recv(count) = ncont(tileme)%ie2(n); ie2recv(count) = is2recv(count) + nhalo - 1
5546  js2recv(count) = ncont(tileme)%js2(n); je2recv(count) = ncont(tileme)%je2(n)
5547  is1send(count) = ncont(tileme)%is1(n); ie1send(count) = ncont(tileme)%ie1(n)
5548  je1send(count) = ncont(tileme)%je1(n); js1send(count) = je1send(count) - whalo + 1
5549  ie2send(count) = ncont(tileme)%is2(n)-1; is2send(count) = ie2send(count) - whalo + 1
5550  js2send(count) = ncont(tileme)%js2(n); je2send(count) = ncont(tileme)%je2(n)
5551  end select
5552  end do
5553 
5554  nums = count
5555  numr = count
5556  !--- figure out the index for corner overlapping,
5557  !--- fill_corner_contact will be updated to deal with the situation that there are multiple tiles on
5558  !--- each side of six sides of cubic grid.
5559  if(.NOT. domain%rotated_ninety) then
5560  call fill_corner_contact(econt, scont, wcont, ncont, isglist, ieglist, jsglist, jeglist, numr, nums, &
5561  tilerecv, tilesend, is1recv, ie1recv, js1recv, je1recv, is2recv, ie2recv, &
5562  js2recv, je2recv, is1send, ie1send, js1send, je1send, is2send, ie2send, &
5563  js2send, je2send, align1recv, align2recv, align1send, align2send, &
5564  whalo, ehalo, shalo, nhalo, tileme )
5565  end if
5566 
5567  isc = domain%x(tme)%compute%begin; iec = domain%x(tme)%compute%end
5568  jsc = domain%y(tme)%compute%begin; jec = domain%y(tme)%compute%end
5569 
5570  !--- compute the overlapping for send.
5571  do n = 1, nums
5572  do list = 0, nlist-1
5573  m = mod( domain%pos+list, nlist )
5574  ntilenbr = size(domain%list(m)%x(:))
5575  do tnbr = 1, ntilenbr
5576  if( domain%list(m)%tile_id(tnbr) .NE. tilesend(n) ) cycle
5577  isc1 = max(isc, is1send(n)); iec1 = min(iec, ie1send(n))
5578  jsc1 = max(jsc, js1send(n)); jec1 = min(jec, je1send(n))
5579  if( isc1 > iec1 .OR. jsc1 > jec1 ) cycle
5580  !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5581  do dir = 1, 8
5582  !--- get the to_pe's data domain.
5583  select case ( dir )
5584  case ( 1 ) ! eastern halo
5585  if( align2send(n) .NE. east ) cycle
5586  isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5587  jsd = domain%list(m)%y(tnbr)%compute%begin; jed = domain%list(m)%y(tnbr)%compute%end
5588  case ( 2 ) ! southeast halo
5589  isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5590  jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5591  case ( 3 ) ! southern halo
5592  if( align2send(n) .NE. south ) cycle
5593  isd = domain%list(m)%x(tnbr)%compute%begin; ied = domain%list(m)%x(tnbr)%compute%end
5594  jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5595  case ( 4 ) ! southwest halo
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-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5598  case ( 5 ) ! western halo
5599  if( align2send(n) .NE. west ) cycle
5600  isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5601  jsd = domain%list(m)%y(tnbr)%compute%begin; jed = domain%list(m)%y(tnbr)%compute%end
5602  case ( 6 ) ! northwest halo
5603  isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5604  jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5605  case ( 7 ) ! northern halo
5606  if( align2send(n) .NE. north ) cycle
5607  isd = domain%list(m)%x(tnbr)%compute%begin; ied = domain%list(m)%x(tnbr)%compute%end
5608  jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5609  case ( 8 ) ! northeast halo
5610  isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5611  jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5612  end select
5613  isd = max(isd, is2send(n)); ied = min(ied, ie2send(n))
5614  jsd = max(jsd, js2send(n)); jed = min(jed, je2send(n))
5615  if( isd > ied .OR. jsd > jed ) cycle
5616  ioff = 0; joff = 0
5617  nxd = ied - isd + 1
5618  nyd = jed - jsd + 1
5619  select case ( align2send(n) )
5620  case ( west, east )
5621  ioff = isd - is2send(n)
5622  joff = jsd - js2send(n)
5623  case ( south, north )
5624  ioff = isd - is2send(n)
5625  joff = jsd - js2send(n)
5626  end select
5627 
5628  !--- get the index in current pe.
5629  select case ( rotatesend(n) )
5630  case ( zero )
5631  isc2 = is1send(n) + ioff; iec2 = isc2 + nxd - 1
5632  jsc2 = js1send(n) + joff; jec2 = jsc2 + nyd - 1
5633  case ( ninety ) ! N -> W or S -> E
5634  iec2 = ie1send(n) - joff; isc2 = iec2 - nyd + 1
5635  jsc2 = js1send(n) + ioff; jec2 = jsc2 + nxd - 1
5636  case ( minus_ninety ) ! W -> N or E -> S
5637  isc2 = is1send(n) + joff; iec2 = isc2 + nyd - 1
5638  jec2 = je1send(n) - ioff; jsc2 = jec2 - nxd + 1
5639  end select
5640  is = max(isc1,isc2); ie = min(iec1,iec2)
5641  js = max(jsc1,jsc2); je = min(jec1,jec2)
5642  if(ie.GE.is .AND. je.GE.js )then
5643  if(.not. associated(overlapsend(m)%tileMe)) call allocate_update_overlap(overlapsend(m), &
5644  & maxoverlap)
5645  call insert_overlap_type(overlapsend(m), domain%list(m)%pe, tme, tnbr, &
5646  is, ie, js, je, dir, rotatesend(n), .true. )
5647  endif
5648  end do ! end do dir = 1, 8
5649  end do ! end do tNbr = 1, ntileNbr
5650  end do ! end do list = 0, nlist-1
5651  end do ! end do n = 1, numS
5652 
5653  !--- compute the overlapping for recv.
5654  do n = 1, numr
5655  do list = 0, nlist-1
5656  m = mod( domain%pos+nlist-list, nlist )
5657  ntilenbr = size(domain%list(m)%x(:))
5658  do tnbr = 1, ntilenbr
5659  if( domain%list(m)%tile_id(tnbr) .NE. tilerecv(n) ) cycle
5660  isc = domain%list(m)%x(tnbr)%compute%begin; iec = domain%list(m)%x(tnbr)%compute%end
5661  jsc = domain%list(m)%y(tnbr)%compute%begin; jec = domain%list(m)%y(tnbr)%compute%end
5662  isc = max(isc, is2recv(n)); iec = min(iec, ie2recv(n))
5663  jsc = max(jsc, js2recv(n)); jec = min(jec, je2recv(n))
5664  if( isc > iec .OR. jsc > jec ) cycle
5665  !--- find the offset for this overlapping.
5666  ioff = 0; joff = 0
5667  nxc = iec - isc + 1; nyc = jec - jsc + 1
5668  select case ( align2recv(n) )
5669  case ( west, east )
5670  if(align2recv(n) == west) then
5671  ioff = isc - is2recv(n)
5672  else
5673  ioff = ie2recv(n) - iec
5674  endif
5675  joff = jsc - js2recv(n)
5676  case ( north, south )
5677  ioff = isc - is2recv(n)
5678  if(align2recv(n) == south) then
5679  joff = jsc - js2recv(n)
5680  else
5681  joff = je2recv(n) - jec
5682  endif
5683  end select
5684 
5685  !--- get the index in current pe.
5686  select case ( rotaterecv(n) )
5687  case ( zero )
5688  isd1 = is1recv(n) + ioff; ied1 = isd1 + nxc - 1
5689  jsd1 = js1recv(n) + joff; jed1 = jsd1 + nyc - 1
5690  if( align1recv(n) == west ) then
5691  ied1 = ie1recv(n)-ioff; isd1 = ied1 - nxc + 1
5692  endif
5693  if( align1recv(n) == south ) then
5694  jed1 = je1recv(n)-joff; jsd1 = jed1 - nyc + 1
5695  endif
5696  case ( ninety ) ! N -> W or S -> E
5697  if( align1recv(n) == west ) then
5698  ied1 = ie1recv(n)-joff; isd1 = ied1 - nyc + 1
5699  else
5700  isd1 = is1recv(n)+joff; ied1 = isd1 + nyc - 1
5701  endif
5702  jed1 = je1recv(n) - ioff; jsd1 = jed1 - nxc + 1
5703  case ( minus_ninety ) ! W -> N or E -> S
5704  ied1 = ie1recv(n) - joff; isd1 = ied1 - nyc + 1
5705  if( align1recv(n) == south ) then
5706  jed1 = je1recv(n)-ioff; jsd1 = jed1 - nxc + 1
5707  else
5708  jsd1 = js1recv(n)+ioff; jed1 = jsd1 + nxc - 1
5709  endif
5710  end select
5711 
5712  !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5713  do dir = 1, 8
5714  select case ( dir )
5715  case ( 1 ) ! eastern halo
5716  if( align1recv(n) .NE. east ) cycle
5717  isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5718  jsd2 = domain%y(tme)%compute%begin; jed2 = domain%y(tme)%compute%end
5719  case ( 2 ) ! southeast halo
5720  isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5721  jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5722  case ( 3 ) ! southern halo
5723  if( align1recv(n) .NE. south ) cycle
5724  isd2 = domain%x(tme)%compute%begin; ied2 = domain%x(tme)%compute%end
5725  jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5726  case ( 4 ) ! southwest halo
5727  isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5728  jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5729  case ( 5 ) ! western halo
5730  if( align1recv(n) .NE. west ) cycle
5731  isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5732  jsd2 = domain%y(tme)%compute%begin; jed2 = domain%y(tme)%compute%end
5733  case ( 6 ) ! northwest halo
5734  isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5735  jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5736  case ( 7 ) ! northern halo
5737  if( align1recv(n) .NE. north ) cycle
5738  isd2 = domain%x(tme)%compute%begin; ied2 = domain%x(tme)%compute%end
5739  jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5740  case ( 8 ) ! northeast halo
5741  isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5742  jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5743  end select
5744  is = max(isd1,isd2); ie = min(ied1,ied2)
5745  js = max(jsd1,jsd2); je = min(jed1,jed2)
5746  if(ie.GE.is .AND. je.GE.js )then
5747  if(.not. associated(overlaprecv(m)%tileMe)) call allocate_update_overlap(overlaprecv(m), &
5748  & maxoverlap)
5749  call insert_overlap_type(overlaprecv(m), domain%list(m)%pe, tme, tnbr, &
5750  is, ie, js, je, dir, rotaterecv(n), .true.)
5751  count = overlaprecv(m)%count
5752  endif
5753  end do ! end do dir = 1, 8
5754  end do ! end do tNbr = 1, ntileNbr
5755  end do ! end do list = 0, nlist-1
5756  end do ! end do n = 1, numR
5757  end do ! end do tMe = 1, ntileMe
5758 
5759  !--- copy the overlapping information into domain data
5760  nsend = 0; nsend2 = 0
5761  do list = 0, nlist-1
5762  m = mod( domain%pos+list, nlist )
5763  if(overlapsend(m)%count>0) nsend = nsend + 1
5764  enddo
5765 
5766  if(debug_message_passing) then
5767  !--- write out send information
5768  iunit = mpp_pe() + 1000
5769  do list = 0, nlist-1
5770  m = mod( domain%pos+list, nlist )
5771  if(overlapsend(m)%count==0) cycle
5772  write(iunit, *) "********to_pe = " ,overlapsend(m)%pe, " count = ",overlapsend(m)%count
5773  do n = 1, overlapsend(m)%count
5774  write(iunit, *) overlapsend(m)%is(n), overlapsend(m)%ie(n), overlapsend(m)%js(n), overlapsend(m)%je(n), &
5775  overlapsend(m)%dir(n), overlapsend(m)%rotation(n)
5776  enddo
5777  enddo
5778  if(nsend >0) flush(iunit)
5779  endif
5780 
5781  dirlist(1) = 1; dirlist(2) = 3; dirlist(3) = 5; dirlist(4) = 7
5782  dirlist(5) = 2; dirlist(6) = 4; dirlist(7) = 6; dirlist(8) = 8
5783 
5784  ! copy the overlap information into domain.
5785  if(nsend >0) then
5786  if(associated(domain%update_T%send)) then
5787  do m = 1, domain%update_T%nsend
5788  call deallocate_overlap_type(domain%update_T%send(m))
5789  enddo
5790  deallocate(domain%update_T%send)
5791  endif
5792  domain%update_T%nsend = nsend
5793  allocate(domain%update_T%send(nsend))
5794  do list = 0, nlist-1
5795  m = mod( domain%pos+list, nlist )
5796  ntilenbr = size(domain%list(m)%x(:))
5797  !--- for the send, the list should be in tileNbr order and dir order to be consistent with Recv
5798  if(overlapsend(m)%count > 0) then
5799  nsend2 = nsend2+1
5800  if(nsend2>nsend) call mpp_error(fatal, &
5801  "mpp_domains_define.inc(define_contact_point): nsend2 is greater than nsend")
5802  call allocate_update_overlap(domain%update_T%send(nsend2), overlapsend(m)%count)
5803 
5804  do tnbr = 1, ntilenbr
5805  do tt = 1, ntileme
5806  if(domain%list(m)%pe == domain%pe) then ! own processor
5807  tme = tnbr+tt-1
5808  if(tme > ntileme) tme = tme - ntileme
5809  else
5810  tme = tt
5811  end if
5812  do n = 1, 8 ! loop over 8 direction
5813  do l = 1, overlapsend(m)%count
5814  if(overlapsend(m)%tileMe(l) .NE. tme) cycle
5815  if(overlapsend(m)%tileNbr(l) .NE. tnbr) cycle
5816  if(overlapsend(m)%dir(l) .NE. dirlist(n) ) cycle
5817  call insert_overlap_type(domain%update_T%send(nsend2), overlapsend(m)%pe, &
5818  overlapsend(m)%tileMe(l), overlapsend(m)%tileNbr(l), overlapsend(m)%is(l), &
5819  overlapsend(m)%ie(l), overlapsend(m)%js(l), overlapsend(m)%je(l), overlapsend(m)%dir(l),&
5820  overlapsend(m)%rotation(l), overlapsend(m)%from_contact(l) )
5821  end do
5822  end do
5823  end do
5824  end do
5825  end if
5826  enddo
5827  endif
5828 
5829  if(nsend2 .NE. nsend) call mpp_error(fatal, &
5830  "mpp_domains_define.inc(define_contact_point): nsend2 does not equal to nsend")
5831 
5832  nrecv = 0; nrecv2 = 0
5833  do list = 0, nlist-1
5834  m = mod( domain%pos+list, nlist )
5835  if(overlaprecv(m)%count>0) nrecv = nrecv + 1
5836  enddo
5837 
5838  if(debug_message_passing) then
5839  do list = 0, nlist-1
5840  m = mod( domain%pos+list, nlist )
5841  if(overlaprecv(m)%count==0) cycle
5842  write(iunit, *) "********from_pe = " ,overlaprecv(m)%pe, " count = ",overlaprecv(m)%count
5843  do n = 1, overlaprecv(m)%count
5844  write(iunit, *) overlaprecv(m)%is(n), overlaprecv(m)%ie(n), overlaprecv(m)%js(n), overlaprecv(m)%je(n), &
5845  overlaprecv(m)%dir(n), overlaprecv(m)%rotation(n)
5846  enddo
5847  enddo
5848  if(nrecv >0) flush(iunit)
5849  endif
5850 
5851  if(nrecv >0) then
5852  if(associated(domain%update_T%recv)) then
5853  do m = 1, domain%update_T%nrecv
5854  call deallocate_overlap_type(domain%update_T%recv(m))
5855  enddo
5856  deallocate(domain%update_T%recv)
5857  endif
5858  domain%update_T%nrecv = nrecv
5859  allocate(domain%update_T%recv(nrecv))
5860 
5861  do list = 0, nlist-1
5862  m = mod( domain%pos+nlist-list, nlist )
5863  ntilenbr = size(domain%list(m)%x(:))
5864  if(overlaprecv(m)%count > 0) then
5865  nrecv2 = nrecv2 + 1
5866  if(nrecv2>nrecv) call mpp_error(fatal, &
5867  "mpp_domains_define.inc(define_contact_point): nrecv2 is greater than nrecv")
5868  call allocate_update_overlap(domain%update_T%recv(nrecv2), overlaprecv(m)%count)
5869  do tme = 1, ntileme
5870  do tt = 1, ntilenbr
5871  !--- make sure the same order tile for different pe count
5872  if(domain%list(m)%pe == domain%pe) then ! own processor
5873  tnbr = tme+tt-1
5874  if(tnbr>ntilenbr) tnbr = tnbr - ntilenbr
5875  else
5876  tnbr = tt
5877  end if
5878  do n = 1, 8 ! loop over 8 direction
5879  do l = 1, overlaprecv(m)%count
5880  if(overlaprecv(m)%tileMe(l) .NE. tme) cycle
5881  if(overlaprecv(m)%tileNbr(l) .NE. tnbr) cycle
5882  if(overlaprecv(m)%dir(l) .NE. dirlist(n) ) cycle
5883  call insert_overlap_type(domain%update_T%recv(nrecv2), overlaprecv(m)%pe, &
5884  overlaprecv(m)%tileMe(l), overlaprecv(m)%tileNbr(l), overlaprecv(m)%is(l), &
5885  overlaprecv(m)%ie(l), overlaprecv(m)%js(l), overlaprecv(m)%je(l), overlaprecv(m)%dir(l),&
5886  overlaprecv(m)%rotation(l), overlaprecv(m)%from_contact(l))
5887  count = domain%update_T%recv(nrecv2)%count
5888  end do
5889  end do
5890  end do
5891  end do
5892  end if
5893  end do
5894  endif
5895 
5896  if(nrecv2 .NE. nrecv) call mpp_error(fatal, &
5897  "mpp_domains_define.inc(define_contact_point): nrecv2 does not equal to nrecv")
5898 
5899  do m = 0,nlist-1
5900  call deallocate_overlap_type(overlapsend(m))
5901  call deallocate_overlap_type(overlaprecv(m))
5902  enddo
5903  !--- release memory
5904  do n = 1, ntiles
5905  deallocate(econt(n)%tile, wcont(n)%tile, scont(n)%tile, ncont(n)%tile )
5906  deallocate(econt(n)%align1, wcont(n)%align1, scont(n)%align1, ncont(n)%align1)
5907  deallocate(econt(n)%align2, wcont(n)%align2, scont(n)%align2, ncont(n)%align2)
5908  deallocate(econt(n)%refine1, wcont(n)%refine1, scont(n)%refine1, ncont(n)%refine1)
5909  deallocate(econt(n)%refine2, wcont(n)%refine2, scont(n)%refine2, ncont(n)%refine2)
5910  deallocate(econt(n)%is1, econt(n)%ie1, econt(n)%js1, econt(n)%je1 )
5911  deallocate(econt(n)%is2, econt(n)%ie2, econt(n)%js2, econt(n)%je2 )
5912  deallocate(wcont(n)%is1, wcont(n)%ie1, wcont(n)%js1, wcont(n)%je1 )
5913  deallocate(wcont(n)%is2, wcont(n)%ie2, wcont(n)%js2, wcont(n)%je2 )
5914  deallocate(scont(n)%is1, scont(n)%ie1, scont(n)%js1, scont(n)%je1 )
5915  deallocate(scont(n)%is2, scont(n)%ie2, scont(n)%js2, scont(n)%je2 )
5916  deallocate(ncont(n)%is1, ncont(n)%ie1, ncont(n)%js1, ncont(n)%je1 )
5917  deallocate(ncont(n)%is2, ncont(n)%ie2, ncont(n)%js2, ncont(n)%je2 )
5918  end do
5919 
5920  domain%initialized = .true.
5921 
5922 
5923  end subroutine define_contact_point
5924 
5925 !##############################################################################
5926 !> always fill the contact according to index order.
5927 subroutine fill_contact(Contact, tile, is1, ie1, js1, je1, is2, ie2, js2, je2, align1, align2, refine1, refine2 )
5928  type(contact_type), intent(inout) :: Contact
5929  integer, intent(in) :: tile
5930  integer, intent(in) :: is1, ie1, js1, je1
5931  integer, intent(in) :: is2, ie2, js2, je2
5932  integer, intent(in) :: align1, align2
5933  real, intent(in) :: refine1, refine2
5934  integer :: pos, n
5935 
5936  do pos = 1, contact%ncontact
5937  select case(align1)
5938  case(west, east)
5939  if( js1 < contact%js1(pos) ) exit
5940  case(south, north)
5941  if( is1 < contact%is1(pos) ) exit
5942  end select
5943  end do
5944 
5945  contact%ncontact = contact%ncontact + 1
5946  do n = contact%ncontact, pos+1, -1 ! shift the data if needed.
5947  contact%tile(n) = contact%tile(n-1)
5948  contact%align1(n) = contact%align1(n-1)
5949  contact%align2(n) = contact%align2(n-1)
5950  contact%is1(n) = contact%is1(n-1); contact%ie1(n) = contact%ie1(n-1)
5951  contact%js1(n) = contact%js1(n-1); contact%je1(n) = contact%je1(n-1)
5952  contact%is2(n) = contact%is2(n-1); contact%ie2(n) = contact%ie2(n-1)
5953  contact%js2(n) = contact%js2(n-1); contact%je2(n) = contact%je2(n-1)
5954  end do
5955 
5956  contact%tile(pos) = tile
5957  contact%align1(pos) = align1
5958  contact%align2(pos) = align2
5959  contact%refine1(pos) = refine1
5960  contact%refine2(pos) = refine2
5961  contact%is1(pos) = is1; contact%ie1(pos) = ie1
5962  contact%js1(pos) = js1; contact%je1(pos) = je1
5963  contact%is2(pos) = is2; contact%ie2(pos) = ie2
5964  contact%js2(pos) = js2; contact%je2(pos) = je2
5965 
5966 end subroutine fill_contact
5967 
5968 !############################################################################
5969 !> this routine sets the overlapping between tiles for E,C,N-cell based on T-cell overlapping
5970 subroutine set_contact_point(domain, position)
5971  type(domain2d), intent(inout) :: domain
5972  integer, intent(in) :: position
5973 
5974  integer :: ishift, jshift, nlist, list, m, n
5975  integer :: ntileMe, tMe, dir, count, pos, nsend, nrecv
5976  integer :: isoff1, ieoff1, jsoff1, jeoff1
5977  type(overlap_type), pointer :: ptrIn => null()
5978  type(overlapspec), pointer :: update_in => null()
5979  type(overlapspec), pointer :: update_out => null()
5980  type(overlap_type) :: overlapList(0:size(domain%list(:))-1)
5981  type(overlap_type) :: overlap
5982 
5983  call mpp_get_domain_shift(domain, ishift, jshift, position)
5984  update_in => domain%update_T
5985  select case(position)
5986  case (corner)
5987  update_out => domain%update_C
5988  case (east)
5989  update_out => domain%update_E
5990  case (north)
5991  update_out => domain%update_N
5992  case default
5993  call mpp_error(fatal, "mpp_domains_define.inc(set_contact_point): the position should be CORNER, EAST or NORTH")
5994  end select
5995 
5996  update_out%xbegin = update_in%xbegin; update_out%xend = update_in%xend + ishift
5997  update_out%ybegin = update_in%ybegin; update_out%yend = update_in%yend + jshift
5998  update_out%whalo = update_in%whalo; update_out%ehalo = update_in%ehalo
5999  update_out%shalo = update_in%shalo; update_out%nhalo = update_in%nhalo
6000 
6001  nlist = size(domain%list(:))
6002  ntileme = size(domain%x(:))
6003  call allocate_update_overlap(overlap, maxoverlap)
6004  do m = 0, nlist-1
6005  call init_overlap_type(overlaplist(m))
6006  enddo
6007 
6008  !--- first copy the send information in update_out to send
6009  nsend = update_out%nsend
6010  do m = 1, nsend
6011  pos = update_out%send(m)%pe - mpp_root_pe()
6012  call add_update_overlap(overlaplist(pos), update_out%send(m))
6013  call deallocate_overlap_type(update_out%send(m))
6014  enddo
6015  if(ASSOCIATED(update_out%send) )deallocate(update_out%send)
6016 
6017  !--- loop over the list of overlapping.
6018  nsend = update_in%nsend
6019  do m = 1, nsend
6020  ptrin => update_in%send(m)
6021  pos = ptrin%pe - mpp_root_pe()
6022  do n = 1, ptrin%count
6023  dir = ptrin%dir(n)
6024  ! only set overlapping between tiles for send ( ptrOut%overlap(1) is false )
6025  if(ptrin%from_contact(n)) then
6026  select case ( dir )
6027  case ( 1 ) ! to_pe's eastern halo
6028  select case(ptrin%rotation(n))
6029  case (zero) ! W -> E
6030  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6031  case (ninety) ! S -> E
6032  isoff1 = 0; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6033  end select
6034  case ( 2 ) ! to_pe's south-eastearn halo
6035  select case(ptrin%rotation(n))
6036  case (zero)
6037  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6038  case (ninety)
6039  isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6040  case (minus_ninety)
6041  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6042  end select
6043  case ( 3 ) ! to_pe's southern halo
6044  select case(ptrin%rotation(n))
6045  case (zero) ! N -> S
6046  isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6047  case (minus_ninety) ! E -> S
6048  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = ishift
6049  end select
6050  case ( 4 ) ! to_pe's south-westearn halo
6051  select case(ptrin%rotation(n))
6052  case (zero)
6053  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6054  case (ninety)
6055  isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6056  case (minus_ninety)
6057  isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6058  end select
6059  case ( 5 ) ! to_pe's western halo
6060  select case(ptrin%rotation(n))
6061  case (zero) ! E -> W
6062  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6063  case (ninety) ! N -> W
6064  isoff1 = 0; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6065  end select
6066  case ( 6 ) ! to_pe's north-westearn halo
6067  select case(ptrin%rotation(n))
6068  case (zero)
6069  isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6070  case (ninety)
6071  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6072  case (minus_ninety)
6073  isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6074  end select
6075  case ( 7 ) ! to_pe's northern halo
6076  select case(ptrin%rotation(n))
6077  case (zero) ! S -> N
6078  isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6079  case (minus_ninety) ! W -> N
6080  isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = ishift
6081  end select
6082  case ( 8 ) ! to_pe's north-eastearn halo
6083  select case(ptrin%rotation(n))
6084  case (zero)
6085  isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6086  case (ninety)
6087  isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6088  case (minus_ninety)
6089  isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6090  end select
6091  end select
6092  call insert_overlap_type(overlap, ptrin%pe, ptrin%tileMe(n), ptrin%tileNbr(n), &
6093  ptrin%is(n) + isoff1, ptrin%ie(n) + ieoff1, ptrin%js(n) + jsoff1, &
6094  ptrin%je(n) + jeoff1, ptrin%dir(n), ptrin%rotation(n), ptrin%from_contact(n))
6095  end if
6096  end do ! do n = 1, prtIn%count
6097  if(overlap%count > 0) then
6098  call add_update_overlap(overlaplist(pos), overlap)
6099  call init_overlap_type(overlap)
6100  endif
6101  end do ! do list = 0, nlist-1
6102 
6103  nsend = 0
6104  do list = 0, nlist-1
6105  m = mod( domain%pos+list, nlist )
6106  if(overlaplist(m)%count>0) nsend = nsend+1
6107  enddo
6108 
6109  update_out%nsend = nsend
6110  if(nsend>0) then
6111  if (associated(update_out%send)) deallocate(update_out%send) !< Check if associated
6112  allocate(update_out%send(nsend))
6113  pos = 0
6114  do list = 0, nlist-1
6115  m = mod( domain%pos+list, nlist )
6116  if(overlaplist(m)%count>0) then
6117  pos = pos+1
6118  if(pos>nsend) call mpp_error(fatal, &
6119  "mpp_domains_define.inc(set_contact_point): pos should be no larger than nsend")
6120  call add_update_overlap(update_out%send(pos), overlaplist(m))
6121  call deallocate_overlap_type(overlaplist(m))
6122  endif
6123  enddo
6124  if(pos .NE. nsend) call mpp_error(fatal, &
6125  "mpp_domains_define.inc(set_contact_point): pos should equal to nsend")
6126  endif
6127 
6128 
6129 
6130  !--- first copy the recv information in update_out to recv
6131  nrecv = update_out%nrecv
6132  do m = 1, nrecv
6133  pos = update_out%recv(m)%pe - mpp_root_pe()
6134  call add_update_overlap(overlaplist(pos), update_out%recv(m))
6135  call deallocate_overlap_type(update_out%recv(m))
6136  enddo
6137  if(ASSOCIATED(update_out%recv) )deallocate(update_out%recv)
6138 
6139  !--- loop over the list of overlapping.
6140  nrecv = update_in%nrecv
6141  do m=1,nrecv
6142  ptrin => update_in%recv(m)
6143  pos = ptrin%pe - mpp_root_pe()
6144  do n = 1, ptrin%count
6145  dir = ptrin%dir(n)
6146  ! only set overlapping between tiles for recv ( ptrOut%overlap(1) is false )
6147  if(ptrin%from_contact(n)) then
6148  select case ( dir )
6149  case ( 1 ) ! E
6150  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6151  case ( 2 ) ! SE
6152  isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6153  case ( 3 ) ! S
6154  isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6155  case ( 4 ) ! SW
6156  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6157  case ( 5 ) ! W
6158  isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6159  case ( 6 ) ! NW
6160  isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6161  case ( 7 ) ! N
6162  isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6163  case ( 8 ) ! NE
6164  isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6165  end select
6166  call insert_overlap_type(overlap, ptrin%pe, ptrin%tileMe(n), ptrin%tileNbr(n), &
6167  ptrin%is(n) + isoff1, ptrin%ie(n) + ieoff1, ptrin%js(n) + jsoff1, &
6168  ptrin%je(n) + jeoff1, ptrin%dir(n), ptrin%rotation(n), ptrin%from_contact(n))
6169  count = overlap%count
6170  end if
6171  end do ! do n = 1, ptrIn%count
6172  if(overlap%count > 0) then
6173  call add_update_overlap(overlaplist(pos), overlap)
6174  call init_overlap_type(overlap)
6175  endif
6176  do tme = 1, size(domain%x(:))
6177  do n = 1, overlap%count
6178  if(overlap%tileMe(n) == tme) then
6179  if(overlap%dir(n) == 1 ) domain%x(tme)%loffset = 0
6180  if(overlap%dir(n) == 7 ) domain%y(tme)%loffset = 0
6181  end if
6182  end do
6183  end do
6184  end do ! do list = 0, nlist-1
6185 
6186  nrecv = 0
6187  do list = 0, nlist-1
6188  m = mod( domain%pos+nlist-list, nlist )
6189  if(overlaplist(m)%count>0) nrecv = nrecv+1
6190  enddo
6191 
6192  update_out%nrecv = nrecv
6193  if(nrecv>0) then
6194  if (associated(update_out%recv)) deallocate(update_out%recv) !< Check if associated
6195  allocate(update_out%recv(nrecv))
6196  pos = 0
6197  do list = 0, nlist-1
6198  m = mod( domain%pos+nlist-list, nlist )
6199  if(overlaplist(m)%count>0) then
6200  pos = pos+1
6201  if(pos>nrecv) call mpp_error(fatal, &
6202  "mpp_domains_define.inc(set_contact_point): pos should be no larger than nrecv")
6203  call add_update_overlap(update_out%recv(pos), overlaplist(m))
6204  call deallocate_overlap_type(overlaplist(m))
6205  endif
6206  enddo
6207  if(pos .NE. nrecv) call mpp_error(fatal, &
6208  "mpp_domains_define.inc(set_contact_point): pos should equal to nrecv")
6209  endif
6210 
6211  call deallocate_overlap_type(overlap)
6212 
6213 end subroutine set_contact_point
6214 
6215 !> set up the overlapping for boundary check if the domain is symmetry. The check will be
6216 !! done on current pe for east boundary for E-cell, north boundary for N-cell,
6217 !! East and North boundary for C-cell
6218 subroutine set_check_overlap( domain, position )
6219 type(domain2d), intent(in) :: domain
6220 integer, intent(in) :: position
6221 integer :: nlist, m, n
6222 integer, parameter :: MAXCOUNT = 100
6223 integer :: is, ie, js, je
6224 integer :: nsend, nrecv, pos, maxsize, rotation
6225 type(overlap_type) :: overlap
6226 type(overlapspec), pointer :: update => null()
6227 type(overlapspec), pointer :: check => null()
6228 
6229 select case(position)
6230 case (corner)
6231  update => domain%update_C
6232  check => domain%check_C
6233 case (east)
6234  update => domain%update_E
6235  check => domain%check_E
6236 case (north)
6237  update => domain%update_N
6238  check => domain%check_N
6239 case default
6240  call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): position should be CORNER, EAST or NORTH")
6241 end select
6242 
6243 check%xbegin = update%xbegin; check%xend = update%xend
6244 check%ybegin = update%ybegin; check%yend = update%yend
6245 check%nsend = 0
6246 check%nrecv = 0
6247 if( .NOT. domain%symmetry ) return
6248 
6249 nsend = 0
6250 maxsize = 0
6251 do m = 1, update%nsend
6252  do n = 1, update%send(m)%count
6253  if( update%send(m)%rotation(n) == one_hundred_eighty ) cycle
6254  if( ( (position == east .OR. position == corner) .AND. update%send(m)%dir(n) == 1 ) .OR. &
6255  ( (position == north .OR. position == corner) .AND. update%send(m)%dir(n) == 7 ) ) then
6256  maxsize = max(maxsize, update%send(m)%count)
6257  nsend = nsend + 1
6258  exit
6259  endif
6260  enddo
6261 enddo
6262 
6263 if(nsend>0) then
6264  if (associated(check%send)) deallocate(check%send) !< Check if associated
6265  allocate(check%send(nsend))
6266  call allocate_check_overlap(overlap, maxsize)
6267 endif
6268 
6269 
6270 nlist = size(domain%list(:))
6271 !--- loop over the list of domains to find the boundary overlap for send
6272 pos = 0
6273 do m = 1, update%nsend
6274  do n = 1, update%send(m)%count
6275  if( update%send(m)%rotation(n) == one_hundred_eighty ) cycle
6276  ! comparing east direction on currently pe
6277  if( (position == east .OR. position == corner) .AND. update%send(m)%dir(n) == 1 ) then
6278  rotation = update%send(m)%rotation(n)
6279  select case( rotation )
6280  case( zero ) ! W -> E
6281  is = update%send(m)%is(n) - 1
6282  ie = is
6283  js = update%send(m)%js(n)
6284  je = update%send(m)%je(n)
6285  case( ninety ) ! S -> E
6286  is = update%send(m)%is(n)
6287  ie = update%send(m)%ie(n)
6288  js = update%send(m)%js(n) - 1
6289  je = js
6290  end select
6291  call insert_check_overlap(overlap, update%send(m)%pe, &
6292  update%send(m)%tileMe(n), 1, rotation, is, ie, js, je)
6293  end if
6294 
6295  ! comparing north direction on currently pe
6296  if( (position == north .OR. position == corner) .AND. update%send(m)%dir(n) == 7 ) then
6297  rotation = update%send(m)%rotation(n)
6298  select case( rotation )
6299  case( zero ) ! S->N
6300  is = update%send(m)%is(n)
6301  ie = update%send(m)%ie(n)
6302  js = update%send(m)%js(n) - 1
6303  je = js
6304  case( minus_ninety ) ! W->N
6305  is = update%send(m)%is(n) - 1
6306  ie = is
6307  js = update%send(m)%js(n)
6308  je = update%send(m)%je(n)
6309  end select
6310  call insert_check_overlap(overlap, update%send(m)%pe, &
6311  update%send(m)%tileMe(n), 4, rotation, is, ie, js, je)
6312  end if
6313  end do ! do n =1, update%send(m)%count
6314  if(overlap%count>0) then
6315  pos = pos+1
6316  if(pos>nsend)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6317  call add_check_overlap(check%send(pos), overlap)
6318  call init_overlap_type(overlap)
6319  endif
6320 end do ! end do list = 0, nlist
6321 
6322 if(pos .NE. nsend)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6323 
6324 nrecv = 0
6325 maxsize = 0
6326 do m = 1, update%nrecv
6327  do n = 1, update%recv(m)%count
6328  if( update%recv(m)%rotation(n) == one_hundred_eighty ) cycle
6329  if( ( (position == east .OR. position == corner) .AND. update%recv(m)%dir(n) == 1 ) .OR. &
6330  ( (position == north .OR. position == corner) .AND. update%recv(m)%dir(n) == 7 ) ) then
6331  maxsize = max(maxsize, update%recv(m)%count)
6332  nrecv = nrecv + 1
6333  exit
6334  endif
6335  enddo
6336 enddo
6337 
6338 if(nsend>0) call deallocate_overlap_type(overlap)
6339 
6340 if(nrecv>0) then
6341  if (associated(check%recv)) deallocate(check%recv) !< Check if associated
6342  allocate(check%recv(nrecv))
6343  call allocate_check_overlap(overlap, maxsize)
6344 endif
6345 
6346 pos = 0
6347 do m = 1, update%nrecv
6348  do n = 1, update%recv(m)%count
6349  if( update%recv(m)%rotation(n) == one_hundred_eighty ) cycle
6350  if( (position == east .OR. position == corner) .AND. update%recv(m)%dir(n) == 1 ) then
6351  is = update%recv(m)%is(n) - 1
6352  ie = is
6353  js = update%recv(m)%js(n)
6354  je = update%recv(m)%je(n)
6355  call insert_check_overlap(overlap, update%recv(m)%pe, &
6356  update%recv(m)%tileMe(n), 1, update%recv(m)%rotation(n), is, ie, js, je)
6357  end if
6358  if( (position == north .OR. position == corner) .AND. update%recv(m)%dir(n) == 7 ) then
6359  is = update%recv(m)%is(n)
6360  ie = update%recv(m)%ie(n)
6361  js = update%recv(m)%js(n) - 1
6362  je = js
6363  call insert_check_overlap(overlap, update%recv(m)%pe, &
6364  update%recv(m)%tileMe(n), 3, update%recv(m)%rotation(n), is, ie, js, je)
6365  end if
6366  end do ! n = 1, overlap%count
6367  if(overlap%count>0) then
6368  pos = pos+1
6369  if(pos>nrecv)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6370  call add_check_overlap(check%recv(pos), overlap)
6371  call init_overlap_type(overlap)
6372  endif
6373 end do ! end do list = 0, nlist
6374 
6375 if(pos .NE. nrecv)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6376 if(nrecv>0) call deallocate_overlap_type(overlap)
6377 
6378 end subroutine set_check_overlap
6379 
6380 !#############################################################################
6381 !> set up the overlapping for boundary if the domain is symmetry.
6382 subroutine set_bound_overlap( domain, position )
6383  type(domain2d), intent(inout) :: domain
6384  integer, intent(in) :: position
6385  integer :: m, n, l, count, dr, tMe
6386  integer, parameter :: MAXCOUNT = 100
6387  integer, dimension(MAXCOUNT) :: dir, rotation, is, ie, js, je, tileMe, index
6388  integer, dimension(size(domain%x(:)), 4) :: nrecvl
6389  integer, dimension(size(domain%x(:)), 4, MAXCOUNT) :: isl, iel, jsl, jel
6390  type(overlap_type), pointer :: overlap => null()
6391  type(overlapspec), pointer :: update => null()
6392  type(overlapspec), pointer :: bound => null()
6393  integer :: nlist_send, nlist_recv, ishift, jshift
6394  integer :: ism, iem, jsm, jem, nsend, nrecv
6395  integer :: isg, ieg, jsg, jeg, nlist, list
6396  integer :: npes_x, npes_y, ipos, jpos, inbr, jnbr
6397  integer :: isc, iec, jsc, jec, my_pe
6398  integer :: pe_south1, pe_south2, pe_west0, pe_west1, pe_west2
6399  integer :: is_south1, ie_south1, js_south1, je_south1
6400  integer :: is_south2, ie_south2, js_south2, je_south2
6401  integer :: is_west0, ie_west0, js_west0, je_west0
6402  integer :: is_west1, ie_west1, js_west1, je_west1
6403  integer :: is_west2, ie_west2, js_west2, je_west2
6404  logical :: x_cyclic, y_cyclic, folded_north
6405 
6406  is_south1=0; ie_south1=0; js_south1=0; je_south1=0
6407  is_south2=0; ie_south2=0; js_south2=0; je_south2=0
6408  is_west0=0; ie_west0=0; js_west0=0; je_west0=0
6409  is_west1=0; ie_west1=0; js_west1=0; je_west1=0
6410  is_west2=0; ie_west2=0; js_west2=0; je_west2=0
6411 
6412 
6413  if( position == center .OR. .NOT. domain%symmetry ) return
6414  call mpp_get_domain_shift(domain, ishift, jshift, position)
6415  call mpp_get_global_domain(domain, isg, ieg, jsg, jeg)
6416  call mpp_get_memory_domain ( domain, ism, iem, jsm, jem )
6417 
6418  select case(position)
6419  case (corner)
6420  update => domain%update_C
6421  bound => domain%bound_C
6422  case (east)
6423  update => domain%update_E
6424  bound => domain%bound_E
6425  case (north)
6426  update => domain%update_N
6427  bound => domain%bound_N
6428  case default
6429  call mpp_error( fatal, "mpp_domains_mod(set_bound_overlap): invalid option of position")
6430  end select
6431 
6432  bound%xbegin = ism; bound%xend = iem + ishift
6433  bound%ybegin = jsm; bound%yend = jem + jshift
6434 
6435  nlist_send = max(update%nsend,4)
6436  nlist_recv = max(update%nrecv,4)
6437  bound%nsend = nlist_send
6438  bound%nrecv = nlist_recv
6439  if(nlist_send >0) then
6440  if (associated(bound%send)) deallocate(bound%send) !< Check if associated
6441  allocate(bound%send(nlist_send))
6442  bound%send(:)%count = 0
6443  endif
6444  if(nlist_recv >0) then
6445  if (associated(bound%recv)) deallocate(bound%recv) !< Check if associated
6446  allocate(bound%recv(nlist_recv))
6447  bound%recv(:)%count = 0
6448  endif
6449  !--- loop over the list of domains to find the boundary overlap for send
6450  nlist = size(domain%list(:))
6451 
6452  npes_x = size(domain%x(1)%list(:))
6453  npes_y = size(domain%y(1)%list(:))
6454  x_cyclic = domain%x(1)%cyclic
6455  y_cyclic = domain%y(1)%cyclic
6456  folded_north = btest(domain%fold,north)
6457  ipos = domain%x(1)%pos
6458  jpos = domain%y(1)%pos
6459  isc = domain%x(1)%compute%begin; iec = domain%x(1)%compute%end
6460  jsc = domain%y(1)%compute%begin; jec = domain%y(1)%compute%end
6461 
6462  nsend = 0
6463  if(domain%ntiles == 1) then ! use neighbor processor to configure send and recv
6464  ! currently only set up for west and south boundary
6465 
6466  ! south boundary for send
6467  pe_south1 = null_pe; pe_south2 = null_pe
6468  if( position == north .OR. position == corner ) then
6469  inbr = ipos; jnbr = jpos + 1
6470  if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6471  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6472  pe_south1 = domain%pearray(inbr,jnbr)
6473  is_south1 = isc + ishift; ie_south1 = iec+ishift
6474  js_south1 = jec + jshift; je_south1 = js_south1
6475  endif
6476  endif
6477  !--- send to the southwest processor when position is NORTH
6478  if( position == corner ) then
6479  inbr = ipos + 1; jnbr = jpos + 1
6480  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6481  if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6482  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6483  pe_south2 = domain%pearray(inbr,jnbr)
6484  is_south2 = iec + ishift; ie_south2 = is_south2
6485  js_south2 = jec + jshift; je_south2 = js_south2
6486  endif
6487  endif
6488 
6489  !---west boundary for send
6490  pe_west0 = null_pe; pe_west1 = null_pe; pe_west2 = null_pe
6491  if( position == east ) then
6492  inbr = ipos+1; jnbr = jpos
6493  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6494  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6495  pe_west1 = domain%pearray(inbr,jnbr)
6496  is_west1 = iec + ishift; ie_west1 = is_west1
6497  js_west1 = jsc + jshift; je_west1 = jec + jshift
6498  endif
6499  else if ( position == corner ) then ! possible split into two parts.
6500  !--- on the fold.
6501  if( folded_north .AND. jec == jeg .AND. ipos .LT. (npes_x-1)/2 ) then
6502  inbr = npes_x - ipos - 1; jnbr = jpos
6503  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6504  pe_west0 = domain%pearray(inbr,jnbr)
6505  is_west0 = iec+ishift; ie_west0 = is_west0
6506  js_west0 = jec+jshift; je_west0 = js_west0
6507  endif
6508  endif
6509 
6510  if( folded_north .AND. jec == jeg .AND. ipos .GE. npes_x/2 .AND. ipos .LT. (npes_x-1) ) then
6511  inbr = ipos+1; jnbr = jpos
6512  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6513  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6514  pe_west1 = domain%pearray(inbr,jnbr)
6515  is_west1 = iec + ishift; ie_west1 = is_west1
6516  js_west1 = jsc + jshift; je_west1 = jec
6517  endif
6518  else
6519  inbr = ipos+1; jnbr = jpos
6520  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6521  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6522  pe_west1 = domain%pearray(inbr,jnbr)
6523  is_west1 = iec + ishift; ie_west1 = is_west1
6524  js_west1 = jsc + jshift; je_west1 = jec + jshift
6525  endif
6526  endif
6527  endif
6528  !--- send to the southwest processor when position is NORTH
6529  if( position == corner ) then
6530  inbr = ipos + 1; jnbr = jpos + 1
6531  if( inbr == npes_x .AND. x_cyclic) inbr = 0
6532  if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6533  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6534  pe_west2 = domain%pearray(inbr,jnbr)
6535  is_west2 = iec + ishift; ie_west2 = is_west2
6536  js_west2 = jec + jshift; je_west2 = js_west2
6537  endif
6538  endif
6539 
6540  do list = 0,nlist-1
6541  m = mod( domain%pos+list, nlist )
6542  count = 0
6543  my_pe = domain%list(m)%pe
6544  if(my_pe == pe_south1) then
6545  count = count + 1
6546  is(count) = is_south1; ie(count) = ie_south1
6547  js(count) = js_south1; je(count) = je_south1
6548  dir(count) = 2
6549  rotation(count) = zero
6550  endif
6551  if(my_pe == pe_south2) then
6552  count = count + 1
6553  is(count) = is_south2; ie(count) = ie_south2
6554  js(count) = js_south2; je(count) = je_south2
6555  dir(count) = 2
6556  rotation(count) = zero
6557  endif
6558 
6559  if(my_pe == pe_west0) then
6560  count = count + 1
6561  is(count) = is_west0; ie(count) = ie_west0
6562  js(count) = js_west0; je(count) = je_west0
6563  dir(count) = 3
6564  rotation(count) = one_hundred_eighty
6565  endif
6566  if(my_pe == pe_west1) then
6567  count = count + 1
6568  is(count) = is_west1; ie(count) = ie_west1
6569  js(count) = js_west1; je(count) = je_west1
6570  dir(count) = 3
6571  rotation(count) = zero
6572  endif
6573  if(my_pe == pe_west2) then
6574  count = count + 1
6575  is(count) = is_west2; ie(count) = ie_west2
6576  js(count) = js_west2; je(count) = je_west2
6577  dir(count) = 3
6578  rotation(count) = zero
6579  endif
6580 
6581  if(count >0) then
6582  nsend = nsend + 1
6583  if(nsend > nlist_send) call mpp_error(fatal, "set_bound_overlap: nsend > nlist_send")
6584  bound%send(nsend)%count = count
6585  bound%send(nsend)%pe = my_pe
6586  if (associated(bound%send(nsend)%is)) deallocate(bound%send(nsend)%is) !< Check if allocated
6587  if (associated(bound%send(nsend)%ie)) deallocate(bound%send(nsend)%ie) !< Check if allocated
6588  if (associated(bound%send(nsend)%js)) deallocate(bound%send(nsend)%js) !< Check if allocated
6589  if (associated(bound%send(nsend)%je)) deallocate(bound%send(nsend)%je) !< Check if allocated
6590  if (associated(bound%send(nsend)%dir)) deallocate(bound%send(nsend)%dir) !< Check if allocated
6591  if (associated(bound%send(nsend)%rotation)) deallocate(bound%send(nsend)%rotation) !< Check if allocated
6592  if (associated(bound%send(nsend)%tileMe)) deallocate(bound%send(nsend)%tileMe) !< Check if allocated
6593  allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6594  allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6595  allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6596  allocate(bound%send(nsend)%tileMe(count))
6597  bound%send(nsend)%is(:) = is(1:count)
6598  bound%send(nsend)%ie(:) = ie(1:count)
6599  bound%send(nsend)%js(:) = js(1:count)
6600  bound%send(nsend)%je(:) = je(1:count)
6601  bound%send(nsend)%dir(:) = dir(1:count)
6602  bound%send(nsend)%tileMe(:) = 1
6603  bound%send(nsend)%rotation(:) = rotation(1:count)
6604  endif
6605  enddo
6606  else
6607  !--- The following did not consider wide halo case.
6608  do m = 1, update%nsend
6609  overlap => update%send(m)
6610  if( overlap%count == 0 ) cycle
6611  count = 0
6612  do n = 1, overlap%count
6613  !--- currently not support folded-north
6614  if( overlap%rotation(n) == one_hundred_eighty ) cycle
6615  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 1) then ! east
6616  count=count+1
6617  dir(count) = 1
6618  rotation(count) = overlap%rotation(n)
6619  tileme(count) = overlap%tileMe(n)
6620  select case( rotation(count) )
6621  case( zero ) ! W -> E
6622  is(count) = overlap%is(n) - 1
6623  ie(count) = is(count)
6624  js(count) = overlap%js(n)
6625  je(count) = overlap%je(n)
6626  case( ninety ) ! S -> E
6627  is(count) = overlap%is(n)
6628  ie(count) = overlap%ie(n)
6629  js(count) = overlap%js(n) - 1
6630  je(count) = js(count)
6631  end select
6632  end if
6633  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 3 ) then ! south
6634  count=count+1
6635  dir(count) = 2
6636  rotation(count) = overlap%rotation(n)
6637  tileme(count) = overlap%tileMe(n)
6638  select case( rotation(count) )
6639  case( zero ) ! N->S
6640  is(count) = overlap%is(n)
6641  ie(count) = overlap%ie(n)
6642  js(count) = overlap%je(n) + 1
6643  je(count) = js(count)
6644  case( minus_ninety ) ! E->S
6645  is(count) = overlap%ie(n) + 1
6646  ie(count) = is(count)
6647  js(count) = overlap%js(n)
6648  je(count) = overlap%je(n)
6649  end select
6650  end if
6651  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 5 ) then ! west
6652  count=count+1
6653  dir(count) = 3
6654  rotation(count) = overlap%rotation(n)
6655  tileme(count) = overlap%tileMe(n)
6656  select case( rotation(count) )
6657  case( zero ) ! E->W
6658  is(count) = overlap%ie(n) + 1
6659  ie(count) = is(count)
6660  js(count) = overlap%js(n)
6661  je(count) = overlap%je(n)
6662  case( ninety ) ! N->W
6663  is(count) = overlap%is(n)
6664  ie(count) = overlap%ie(n)
6665  js(count) = overlap%je(n) + 1
6666  je(count) = js(count)
6667  end select
6668  end if
6669  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 7 ) then ! north
6670  count=count+1
6671  dir(count) = 4
6672  rotation(count) = overlap%rotation(n)
6673  tileme(count) = overlap%tileMe(n)
6674  select case( rotation(count) )
6675  case( zero ) ! S->N
6676  is(count) = overlap%is(n)
6677  ie(count) = overlap%ie(n)
6678  js(count) = overlap%js(n) - 1
6679  je(count) = js(count)
6680  case( minus_ninety ) ! W->N
6681  is(count) = overlap%is(n) - 1
6682  ie(count) = is(count)
6683  js(count) = overlap%js(n)
6684  je(count) = overlap%je(n)
6685  end select
6686  end if
6687  end do ! do n =1, overlap%count
6688  if(count>0) then
6689  nsend = nsend + 1
6690  bound%send(nsend)%count = count
6691  bound%send(nsend)%pe = overlap%pe
6692  if (associated(bound%send(nsend)%is)) deallocate(bound%send(nsend)%is) !< Check if allocated
6693  if (associated(bound%send(nsend)%ie)) deallocate(bound%send(nsend)%ie) !< Check if allocated
6694  if (associated(bound%send(nsend)%js)) deallocate(bound%send(nsend)%js) !< Check if allocated
6695  if (associated(bound%send(nsend)%je)) deallocate(bound%send(nsend)%je) !< Check if allocated
6696  if (associated(bound%send(nsend)%dir)) deallocate(bound%send(nsend)%dir) !< Check if allocated
6697  if (associated(bound%send(nsend)%rotation)) deallocate(bound%send(nsend)%rotation) !< Check if allocated
6698  if (associated(bound%send(nsend)%tileMe)) deallocate(bound%send(nsend)%tileMe) !< Check if allocated
6699  allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6700  allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6701  allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6702  allocate(bound%send(nsend)%tileMe(count))
6703  bound%send(nsend)%is(:) = is(1:count)
6704  bound%send(nsend)%ie(:) = ie(1:count)
6705  bound%send(nsend)%js(:) = js(1:count)
6706  bound%send(nsend)%je(:) = je(1:count)
6707  bound%send(nsend)%dir(:) = dir(1:count)
6708  bound%send(nsend)%tileMe(:) = tileme(1:count)
6709  bound%send(nsend)%rotation(:) = rotation(1:count)
6710  end if
6711  end do ! end do list = 0, nlist
6712  endif
6713 
6714  !--- loop over the list of domains to find the boundary overlap for recv
6715  bound%nsend = nsend
6716  nrecvl(:,:) = 0
6717  nrecv = 0
6718 
6719  !--- will computing overlap for tripolar grid.
6720  if( domain%ntiles == 1 ) then
6721  ! currently only set up for west and south boundary
6722 
6723  ! south boundary for recv
6724  pe_south1 = null_pe; pe_south2 = null_pe
6725  if( position == north .OR. position == corner ) then
6726  inbr = ipos; jnbr = jpos - 1
6727  if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6728  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6729  pe_south1 = domain%pearray(inbr,jnbr)
6730  is_south1 = isc + ishift; ie_south1 = iec+ishift
6731  js_south1 = jsc; je_south1 = js_south1
6732  endif
6733  endif
6734 
6735  !--- south boudary for recv: the southwest point when position is NORTH
6736  if( position == corner ) then
6737  inbr = ipos - 1; jnbr = jpos - 1
6738  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6739  if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6740  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6741  pe_south2 = domain%pearray(inbr,jnbr)
6742  is_south2 = isc; ie_south2 = is_south2
6743  js_south2 = jsc; je_south2 = js_south2
6744  endif
6745  endif
6746 
6747 
6748  !---west boundary for recv
6749  pe_west0 = null_pe; pe_west1 = null_pe; pe_west2 = null_pe
6750  if( position == east ) then
6751  inbr = ipos-1; jnbr = jpos
6752  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6753  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6754  pe_west1 = domain%pearray(inbr,jnbr)
6755  is_west1 = isc; ie_west1 = is_west1
6756  js_west1 = jsc + jshift; je_west1 = jec + jshift
6757  endif
6758  else if ( position == corner ) then ! possible split into two parts.
6759  !--- on the fold.
6760  if( folded_north .AND. jec == jeg .AND. ipos .GT. npes_x/2 ) then
6761  inbr = npes_x - ipos - 1; jnbr = jpos
6762  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6763  pe_west0 = domain%pearray(inbr,jnbr)
6764  is_west0 = isc; ie_west0 = is_west0
6765  js_west0 = jec+jshift; je_west0 = js_west0
6766  endif
6767  inbr = ipos-1; jnbr = jpos
6768  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6769  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6770  pe_west1 = domain%pearray(inbr,jnbr)
6771  is_west1 = isc; ie_west1 = is_west1
6772  js_west1 = jsc + jshift; je_west1 = jec
6773  endif
6774  else
6775  inbr = ipos-1; jnbr = jpos
6776  if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6777  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6778  pe_west1 = domain%pearray(inbr,jnbr)
6779  is_west1 = isc; ie_west1 = is_west1
6780  js_west1 = jsc + jshift; je_west1 = jec+jshift
6781  endif
6782  endif
6783  endif
6784 
6785  !--- west boundary for recv: the southwest point when position is CORNER
6786  if( position == corner ) then
6787  inbr = ipos - 1; jnbr = jpos - 1
6788  if( inbr == -1 .AND. x_cyclic) inbr = npes_x - 1
6789  if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y - 1
6790  if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6791  pe_west2 = domain%pearray(inbr,jnbr)
6792  is_west2 = isc; ie_west2 = is_west2
6793  js_west2 = jsc; je_west2 = js_west2
6794  endif
6795  endif
6796 
6797  tme = 1
6798  do list = 0,nlist-1
6799  m = mod( domain%pos+nlist-list, nlist )
6800  count = 0
6801  my_pe = domain%list(m)%pe
6802  if(my_pe == pe_south1) then
6803  count = count + 1
6804  is(count) = is_south1; ie(count) = ie_south1
6805  js(count) = js_south1; je(count) = je_south1
6806  dir(count) = 2
6807  rotation(count) = zero
6808  index(count) = 1 + ishift
6809  endif
6810  if(my_pe == pe_south2) then
6811  count = count + 1
6812  is(count) = is_south2; ie(count) = ie_south2
6813  js(count) = js_south2; je(count) = je_south2
6814  dir(count) = 2
6815  rotation(count) = zero
6816  index(count) = 1
6817  endif
6818  if(my_pe == pe_west0) then
6819  count = count + 1
6820  is(count) = is_west0; ie(count) = ie_west0
6821  js(count) = js_west0; je(count) = je_west0
6822  dir(count) = 3
6823  rotation(count) = one_hundred_eighty
6824  index(count) = jec-jsc+1+jshift
6825  endif
6826  if(my_pe == pe_west1) then
6827  count = count + 1
6828  is(count) = is_west1; ie(count) = ie_west1
6829  js(count) = js_west1; je(count) = je_west1
6830  dir(count) = 3
6831  rotation(count) = zero
6832  index(count) = 1 + jshift
6833  endif
6834  if(my_pe == pe_west2) then
6835  count = count + 1
6836  is(count) = is_west2; ie(count) = ie_west2
6837  js(count) = js_west2; je(count) = je_west2
6838  dir(count) = 3
6839  rotation(count) = zero
6840  index(count) = 1
6841  endif
6842 
6843  if(count >0) then
6844  nrecv = nrecv + 1
6845  if(nrecv > nlist_recv) call mpp_error(fatal, "set_bound_overlap: nrecv > nlist_recv")
6846  bound%recv(nrecv)%count = count
6847  bound%recv(nrecv)%pe = my_pe
6848  if (associated(bound%recv(nrecv)%is)) deallocate(bound%recv(nrecv)%is) !< Check if allocated
6849  if (associated(bound%recv(nrecv)%ie)) deallocate(bound%recv(nrecv)%ie) !< Check if allocated
6850  if (associated(bound%recv(nrecv)%js)) deallocate(bound%recv(nrecv)%js) !< Check if allocated
6851  if (associated(bound%recv(nrecv)%je)) deallocate(bound%recv(nrecv)%je) !< Check if allocated
6852  if (associated(bound%recv(nrecv)%dir)) deallocate(bound%recv(nrecv)%dir) !< Check if allocated
6853  if (associated(bound%recv(nrecv)%index)) deallocate(bound%recv(nrecv)%index) !< Check if allocated
6854  if (associated(bound%recv(nrecv)%tileMe)) deallocate(bound%recv(nrecv)%tileMe) !< Check if allocated
6855  if (associated(bound%recv(nrecv)%rotation)) deallocate(bound%recv(nrecv)%rotation) !< Check if allocated
6856  allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6857  allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6858  allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6859  allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6860 
6861  bound%recv(nrecv)%is(:) = is(1:count)
6862  bound%recv(nrecv)%ie(:) = ie(1:count)
6863  bound%recv(nrecv)%js(:) = js(1:count)
6864  bound%recv(nrecv)%je(:) = je(1:count)
6865  bound%recv(nrecv)%dir(:) = dir(1:count)
6866  bound%recv(nrecv)%tileMe(:) = 1
6867  bound%recv(nrecv)%rotation(:) = rotation(1:count)
6868  bound%recv(nrecv)%index(:) = index(1:count)
6869  endif
6870  enddo
6871  else
6872  do m = 1, update%nrecv
6873  overlap => update%recv(m)
6874  if( overlap%count == 0 ) cycle
6875  count = 0
6876  do n = 1, overlap%count
6877  !--- currently not support folded-north
6878  if( overlap%rotation(n) == one_hundred_eighty ) cycle
6879  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 1) then ! east
6880  count=count+1
6881  dir(count) = 1
6882  rotation(count) = overlap%rotation(n)
6883  tileme(count) = overlap%tileMe(n)
6884  is(count) = overlap%is(n) - 1
6885  ie(count) = is(count)
6886  js(count) = overlap%js(n)
6887  je(count) = overlap%je(n)
6888  tme = tileme(count)
6889  nrecvl(tme, 1) = nrecvl(tme,1) + 1
6890  isl(tme,1,nrecvl(tme, 1)) = is(count)
6891  iel(tme,1,nrecvl(tme, 1)) = ie(count)
6892  jsl(tme,1,nrecvl(tme, 1)) = js(count)
6893  jel(tme,1,nrecvl(tme, 1)) = je(count)
6894  end if
6895 
6896  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 3) then ! south
6897  count=count+1
6898  dir(count) = 2
6899  rotation(count) = overlap%rotation(n)
6900  tileme(count) = overlap%tileMe(n)
6901  is(count) = overlap%is(n)
6902  ie(count) = overlap%ie(n)
6903  js(count) = overlap%je(n) + 1
6904  je(count) = js(count)
6905  tme = tileme(count)
6906  nrecvl(tme, 2) = nrecvl(tme,2) + 1
6907  isl(tme,2,nrecvl(tme, 2)) = is(count)
6908  iel(tme,2,nrecvl(tme, 2)) = ie(count)
6909  jsl(tme,2,nrecvl(tme, 2)) = js(count)
6910  jel(tme,2,nrecvl(tme, 2)) = je(count)
6911  end if
6912 
6913  if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 5) then ! west
6914  count=count+1
6915  dir(count) = 3
6916  rotation(count) = overlap%rotation(n)
6917  tileme(count) = overlap%tileMe(n)
6918  is(count) = overlap%ie(n) + 1
6919  ie(count) = is(count)
6920  js(count) = overlap%js(n)
6921  je(count) = overlap%je(n)
6922  tme = tileme(count)
6923  nrecvl(tme, 3) = nrecvl(tme,3) + 1
6924  isl(tme,3,nrecvl(tme, 3)) = is(count)
6925  iel(tme,3,nrecvl(tme, 3)) = ie(count)
6926  jsl(tme,3,nrecvl(tme, 3)) = js(count)
6927  jel(tme,3,nrecvl(tme, 3)) = je(count)
6928  end if
6929 
6930  if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 7) then ! north
6931  count=count+1
6932  dir(count) = 4
6933  rotation(count) = overlap%rotation(n)
6934  tileme(count) = overlap%tileMe(n)
6935  is(count) = overlap%is(n)
6936  ie(count) = overlap%ie(n)
6937  js(count) = overlap%js(n) - 1
6938  je(count) = js(count)
6939  tme = tileme(count)
6940  nrecvl(tme, 4) = nrecvl(tme,4) + 1
6941  isl(tme,4,nrecvl(tme, 4)) = is(count)
6942  iel(tme,4,nrecvl(tme, 4)) = ie(count)
6943  jsl(tme,4,nrecvl(tme, 4)) = js(count)
6944  jel(tme,4,nrecvl(tme, 4)) = je(count)
6945  end if
6946  end do ! do n = 1, overlap%count
6947  if(count>0) then
6948  nrecv = nrecv + 1
6949  bound%recv(nrecv)%count = count
6950  bound%recv(nrecv)%pe = overlap%pe
6951  if (associated(bound%recv(nrecv)%is)) deallocate(bound%recv(nrecv)%is) !< Check if allocated
6952  if (associated(bound%recv(nrecv)%ie)) deallocate(bound%recv(nrecv)%ie) !< Check if allocated
6953  if (associated(bound%recv(nrecv)%js)) deallocate(bound%recv(nrecv)%js) !< Check if allocated
6954  if (associated(bound%recv(nrecv)%je)) deallocate(bound%recv(nrecv)%je) !< Check if allocated
6955  if (associated(bound%recv(nrecv)%dir)) deallocate(bound%recv(nrecv)%dir) !< Check if allocated
6956  if (associated(bound%recv(nrecv)%index)) deallocate(bound%recv(nrecv)%index) !< Check if allocated
6957  if (associated(bound%recv(nrecv)%tileMe)) deallocate(bound%recv(nrecv)%tileMe) !< Check if allocated
6958  if (associated(bound%recv(nrecv)%rotation)) deallocate(bound%recv(nrecv)%rotation) !< Check if allocated
6959  allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6960  allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6961  allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6962  allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6963  bound%recv(nrecv)%is(:) = is(1:count)
6964  bound%recv(nrecv)%ie(:) = ie(1:count)
6965  bound%recv(nrecv)%js(:) = js(1:count)
6966  bound%recv(nrecv)%je(:) = je(1:count)
6967  bound%recv(nrecv)%dir(:) = dir(1:count)
6968  bound%recv(nrecv)%tileMe(:) = tileme(1:count)
6969  bound%recv(nrecv)%rotation(:) = rotation(1:count)
6970  end if
6971  end do ! end do list = 0, nlist
6972  !--- find the boundary index for each contact within the east boundary
6973  do m = 1, nrecv
6974  do n = 1, bound%recv(m)%count
6975  tme = bound%recv(m)%tileMe(n)
6976  dr = bound%recv(m)%dir(n)
6977  bound%recv(m)%index(n) = 1
6978  do l = 1, nrecvl(tme,dr)
6979  if(dr == 1 .OR. dr == 3) then ! EAST, WEST
6980  if( bound%recv(m)%js(n) > jsl(tme, dr, l) ) then
6981  if( bound%recv(m)%rotation(n) == one_hundred_eighty ) then
6982  bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6983  max(abs(jel(tme, dr, l)-jsl(tme, dr, l))+1, &
6984  abs(iel(tme, dr, l)-isl(tme, dr, l))+1)
6985  else
6986  bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6987  max(abs(jel(tme, dr, l)-jsl(tme, dr, l)), &
6988  abs(iel(tme, dr, l)-isl(tme, dr, l))) + 1 - jshift
6989  endif
6990  end if
6991  else ! South, North
6992  if( bound%recv(m)%is(n) > isl(tme, dr, l) ) then
6993  bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6994  max(abs(jel(tme, dr, l)-jsl(tme, dr, l)), &
6995  abs(iel(tme, dr, l)-isl(tme, dr, l))) + 1 - ishift
6996  end if
6997  end if
6998  end do
6999  end do
7000  end do
7001 
7002  endif
7003  bound%nrecv = nrecv
7004 
7005 
7006 end subroutine set_bound_overlap
7007 
7008 
7009 !#############################################################################
7010 
7011 subroutine fill_corner_contact(eCont, sCont, wCont, nCont, isg, ieg, jsg, jeg, numR, numS, tileRecv, tileSend, &
7012  is1Recv, ie1Recv, js1Recv, je1Recv, is2Recv, ie2Recv, js2Recv, je2Recv, &
7013  is1Send, ie1Send, js1Send, je1Send, is2Send, ie2Send, js2Send, je2Send, &
7014  align1Recv, align2Recv, align1Send, align2Send, &
7015  whalo, ehalo, shalo, nhalo, tileMe)
7016 type(contact_type), dimension(:), intent(in) :: eCont, sCont, wCont, nCont
7017 integer, dimension(:), intent(in) :: isg, ieg, jsg, jeg
7018 integer, intent(inout) :: numR, numS
7019 integer, dimension(:), intent(inout) :: tileRecv, tileSend
7020 integer, dimension(:), intent(inout) :: is1Recv, ie1Recv, js1Recv, je1Recv
7021 integer, dimension(:), intent(inout) :: is2Recv, ie2Recv, js2Recv, je2Recv
7022 integer, dimension(:), intent(inout) :: is1Send, ie1Send, js1Send, je1Send
7023 integer, dimension(:), intent(inout) :: is2Send, ie2Send, js2Send, je2Send
7024 integer, dimension(:), intent(inout) :: align1Recv, align2Recv, align1Send, align2Send
7025 integer, intent(in) :: tileMe, whalo, ehalo, shalo, nhalo
7026 integer :: is1, ie1, js1, je1, is2, ie2, js2, je2
7027 integer :: tn, tc, n, m
7028 logical :: found_corner
7029 
7030 found_corner = .false.
7031 !--- southeast for recving
7032 if(econt(tileme)%ncontact > 0) then
7033  if(econt(tileme)%js1(1) == jsg(tileme) ) then
7034  tn = econt(tileme)%tile(1)
7035  if(econt(tileme)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7036  if( econt(tileme)%js2(1) - jsg(tn) < shalo ) call mpp_error(fatal, &
7037  "mpp_domains_define.inc: southeast tile for recv 1 is not tiled properly")
7038  found_corner = .true.; tc = tn
7039  is1 = econt(tileme)%ie1(1) + 1; je1 = econt(tileme)%js1(1) - 1
7040  is2 = econt(tileme)%is2(1); je2 = econt(tileme)%js2(1) - 1
7041  else if(scont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7042  if(scont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7043  found_corner = .true.; tc = scont(tn)%tile(1)
7044  is1 = econt(tileme)%ie1(1) + 1; je1 = econt(tileme)%js1(1) - 1
7045  is2 = scont(tn)%is2(1); je2 = scont(tn)%je2(1)
7046  end if
7047  end if
7048  end if
7049 end if
7050 if( .not. found_corner ) then ! not found,
7051  n = scont(tileme)%ncontact
7052  if( n > 0) then
7053  if( scont(tileme)%ie1(n) == ieg(tileme)) then
7054  tn = scont(tileme)%tile(n)
7055  if(scont(tileme)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7056  if(ieg(tn) - scont(tileme)%ie2(n) < ehalo ) call mpp_error(fatal, &
7057  "mpp_domains_define.inc: southeast tile for recv 2 is not tiled properly")
7058  found_corner = .true.; tc = tn
7059  is1 = scont(tileme)%ie1(n) + 1; je1 = scont(tileme)%js1(n) - 1
7060  is2 = scont(tileme)%ie2(n) + 1; je2 = scont(tileme)%je2(n)
7061  else if(econt(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7062  m = econt(tn)%ncontact
7063  if(econt(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7064  found_corner = .true.; tc = econt(tn)%tile(m)
7065  is1 = scont(tileme)%ie1(n) + 1; je1 = scont(tileme)%js1(n) - 1
7066  is2 = econt(tn)%is2(m); je2 = econt(tn)%je2(m)
7067  end if
7068  end if
7069  end if
7070  end if
7071 end if
7072 if(found_corner) then
7073  numr = numr + 1
7074  tilerecv(numr) = tc; align1recv(numr) = south_east; align2recv(numr) = north_west
7075  is1recv(numr) = is1; ie1recv(numr) = is1 + ehalo - 1
7076  js1recv(numr) = je1 - shalo + 1; je1recv(numr) = je1
7077  is2recv(numr) = is2; ie2recv(numr) = is2 + ehalo - 1
7078  js2recv(numr) = je2 - shalo + 1; je2recv(numr) = je2
7079 end if
7080 
7081 !--- southwest for recving
7082 found_corner = .false.
7083 if(wcont(tileme)%ncontact > 0) then
7084  if(wcont(tileme)%js1(1) == jsg(tileme) ) then
7085  tn = wcont(tileme)%tile(1)
7086  if(wcont(tileme)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7087  if( wcont(tileme)%js2(1) - jsg(tn) < shalo ) call mpp_error(fatal, &
7088  "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7089  found_corner = .true.; tc = tn
7090  ie1 = wcont(tileme)%is1(1) - 1; je1 = wcont(tileme)%js1(1) - 1
7091  ie2 = wcont(tileme)%is2(1); je2 = wcont(tileme)%js2(1) - 1
7092  else if(scont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7093  n = scont(tn)%ncontact
7094  if(scont(tn)%ie1(n) == ieg(tn)) then ! corner is nc.
7095  found_corner = .true.; tc = scont(tn)%tile(n)
7096  ie1 = wcont(tileme)%is1(1) - 1; je1 = wcont(tileme)%js1(1) - 1
7097  ie2 = scont(tn)%ie2(1); je2 = scont(tn)%je2(1)
7098  end if
7099  end if
7100  end if
7101 end if
7102 if( .not. found_corner ) then ! not found,
7103  n = scont(tileme)%ncontact
7104  if( n > 0) then
7105  if( scont(tileme)%is1(1) == isg(tileme)) then
7106  tn = scont(tileme)%tile(1)
7107  if(scont(tileme)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7108  if( scont(tileme)%is2(1)-isg(tn) < whalo ) call mpp_error(fatal, &
7109  "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7110  found_corner = .true.; tc = tn
7111  ie1 = scont(tileme)%is1(1) - 1; je1 = scont(tileme)%js1(1) - 1
7112  ie2 = scont(tileme)%is2(1) - 1; je2 = scont(tileme)%js2(1)
7113  else if(wcont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7114  m = wcont(tn)%ncontact
7115  if(wcont(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7116  found_corner = .true.; tc = wcont(tn)%tile(m)
7117  ie1 = scont(tileme)%is1(1) - 1; je1 = scont(tileme)%js1(1) - 1
7118  ie2 = wcont(tn)%ie2(m); je2 = wcont(tn)%je2(m)
7119  end if
7120  end if
7121  end if
7122  end if
7123 end if
7124 if(found_corner) then
7125  numr = numr + 1
7126  tilerecv(numr) = tc; align1recv(numr) = south_west; align2recv(numr) = north_east
7127  is1recv(numr) = ie1 - whalo + 1; ie1recv(numr) = ie1
7128  js1recv(numr) = je1 - shalo + 1; je1recv(numr) = je1
7129  is2recv(numr) = ie2 - whalo + 1; ie2recv(numr) = ie2
7130  js2recv(numr) = je2 - shalo + 1; je2recv(numr) = je2
7131 end if
7132 
7133 !--- northwest for recving
7134 found_corner = .false.
7135 n = wcont(tileme)%ncontact
7136 if( n > 0) then
7137  if(wcont(tileme)%je1(n) == jeg(tileme) ) then
7138  tn = wcont(tileme)%tile(n)
7139  if(wcont(tileme)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7140  if( jeg(tn) - wcont(tileme)%je2(n) < nhalo ) call mpp_error(fatal, &
7141  "mpp_domains_define.inc: northwest tile for recv 1 is not tiled properly")
7142  found_corner = .true.; tc = tn
7143  ie1 = wcont(tileme)%is1(n) - 1; js1 = wcont(tileme)%je1(n) + 1
7144  ie2 = wcont(tileme)%is2(n); js2 = wcont(tileme)%je2(n) + 1
7145  else if(ncont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7146  m = ncont(tn)%ncontact
7147  if(ncont(tn)%ie1(m) == ieg(tn)) then ! corner is nc.
7148  found_corner = .true.; tc = ncont(tn)%tile(m)
7149  ie1 = wcont(tileme)%is1(n) - 1; js1 = wcont(tileme)%je1(n) + 1
7150  ie2 = ncont(tn)%ie2(m); js2 = ncont(tn)%js2(m)
7151  end if
7152  endif
7153  endif
7154 end if
7155 if( .not. found_corner ) then ! not found,
7156  if( ncont(tileme)%ncontact > 0) then
7157  if( ncont(tileme)%is1(1) == isg(tileme)) then
7158  tn = ncont(tileme)%tile(1)
7159  if(ncont(tileme)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7160  if( ncont(tileme)%is2(1)-isg(tn) < whalo ) call mpp_error(fatal, &
7161  "mpp_domains_define.inc: northwest tile for recv 2 is not tiled properly")
7162  found_corner = .true.; tc = tn
7163  ie1 = ncont(tileme)%is1(1) - 1; js1 = ncont(tileme)%je1(1) + 1
7164  ie2 = ncont(tileme)%is2(1) - 1; js2 = ncont(tileme)%js2(1)
7165  else if(wcont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7166  if(wcont(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7167  found_corner = .true.; tc = wcont(tn)%tile(1)
7168  ie1 = ncont(tileme)%is1(1) - 1; js1 = ncont(tileme)%je1(1) + 1
7169  ie2 = wcont(tn)%ie2(1); js2 = wcont(tn)%js2(1)
7170  end if
7171  end if
7172  end if
7173  end if
7174 end if
7175 if(found_corner) then
7176  numr = numr + 1
7177  tilerecv(numr) = tc; align1recv(numr) =north_west; align2recv(numr) = south_east
7178  is1recv(numr) = ie1 - whalo + 1; ie1recv(numr) = ie1
7179  js1recv(numr) = js1; je1recv(numr) = js1 + nhalo - 1
7180  is2recv(numr) = ie2 - whalo + 1; ie2recv(numr) = ie2
7181  js2recv(numr) = js2; je2recv(numr) = js2 + nhalo - 1
7182 end if
7183 
7184 !--- northeast for recving
7185 found_corner = .false.
7186 n = econt(tileme)%ncontact
7187 if( n > 0) then
7188  if(econt(tileme)%je1(n) == jeg(tileme) ) then
7189  tn = econt(tileme)%tile(n)
7190  if(econt(tileme)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7191  if( jeg(tn) - econt(tileme)%je2(n) < nhalo ) call mpp_error(fatal, &
7192  "mpp_domains_define.inc: northeast tile for recv 1 is not tiled properly")
7193  found_corner = .true.; tc = tn
7194  is1 = econt(tileme)%ie1(n) + 1; js1 = econt(tileme)%je1(n) + 1
7195  is2 = econt(tileme)%is2(1); js2 = econt(tileme)%je2(1) + 1
7196  else if(ncont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7197  if(ncont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7198  found_corner = .true.; tc = ncont(tn)%tile(1)
7199  is1 = econt(tileme)%ie1(n) + 1; js1 = econt(tileme)%je1(n) + 1
7200  is2 = ncont(tn)%is2(1); js2 = ncont(tn)%js2(1)
7201  end if
7202  end if
7203  end if
7204 end if
7205 if( .not. found_corner ) then ! not found,
7206  n = ncont(tileme)%ncontact
7207  if( n > 0) then
7208  if( ncont(tileme)%ie1(n) == ieg(tileme)) then
7209  tn = ncont(tileme)%tile(n)
7210  if(ncont(tileme)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7211  if(ieg(tn) - scont(tileme)%ie2(n) < ehalo ) call mpp_error(fatal, &
7212  "mpp_domains_define.inc: northeast tile for recv 2 is not tiled properly")
7213  found_corner = .true.; tc = tn
7214  is1 = scont(tileme)%ie1(n) + 1; js1 = scont(tileme)%je1(n) + 1
7215  is2 = scont(tileme)%ie2(n) + 1; js2 = scont(tileme)%js2(n)
7216  else if(econt(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7217  if(econt(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7218  found_corner = .true.; tc = econt(tn)%tile(1)
7219  is1 = scont(tileme)%ie1(n) + 1; js1 = scont(tileme)%je1(n) + 1
7220  is2 = econt(tn)%is2(m); js2 = econt(tn)%js2(m)
7221  end if
7222  end if
7223  end if
7224  end if
7225 end if
7226 if(found_corner) then
7227  numr = numr + 1
7228  tilerecv(numr) = tc; align1recv(numr) =north_east; align2recv(numr) = south_west
7229  is1recv(numr) = is1; ie1recv(numr) = is1 + ehalo - 1
7230  js1recv(numr) = js1; je1recv(numr) = js1 + nhalo - 1
7231  is2recv(numr) = is2; ie2recv(numr) = is2 + ehalo - 1
7232  js2recv(numr) = js2; je2recv(numr) = js2 + nhalo - 1
7233 end if
7234 
7235 !--- to_pe's southeast for sending
7236 do n = 1, wcont(tileme)%ncontact
7237  tn = wcont(tileme)%tile(n)
7238  if(wcont(tileme)%js2(n) == jsg(tn) ) then
7239  if(wcont(tileme)%js1(n) > jsg(tileme) ) then ! send to tile tn.
7240  if( wcont(tileme)%js1(n) - jsg(tileme) < shalo ) call mpp_error(fatal, &
7241  "mpp_domains_define.inc: southeast tile for send 1 is not tiled properly")
7242  nums = nums+1; tilesend(nums) = tn
7243  align1send(nums) = north_west; align2send(nums) = south_east
7244  is1send(nums) = wcont(tileme)%is1(n); ie1send(nums) = is1send(nums) + ehalo - 1
7245  je1send(nums) = wcont(tileme)%js1(n) - 1; js1send(nums) = je1send(nums) - shalo + 1
7246  is2send(nums) = wcont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7247  je2send(nums) = wcont(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7248  end if
7249  end if
7250 end do
7251 do n = 1, ncont(tileme)%ncontact
7252  tn = ncont(tileme)%tile(n)
7253  if(ncont(tileme)%ie2(n) == ieg(tn) ) then
7254  if(ncont(tileme)%ie1(n) < ieg(tileme) ) then ! send to tile tn.
7255  if( ieg(tileme) - ncont(tileme)%ie1(n) < ehalo ) call mpp_error(fatal, &
7256  "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7257  nums = nums+1; tilesend(nums) = tn
7258  align1send(nums) = north_west; align2send(nums) = south_east
7259  is1send(nums) = ncont(tileme)%ie1(n) + 1; ie1send(nums) = is1send(nums) + ehalo - 1
7260  je1send(nums) = ncont(tileme)%je1(n) ; js1send(nums) = je1send(nums) - shalo + 1
7261  is2send(nums) = ncont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7262  je2send(nums) = ncont(tileme)%je2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7263  end if
7264  end if
7265 end do
7266 
7267 !--- found the corner overlap that is not specified through contact line.
7268 n = wcont(tileme)%ncontact
7269 found_corner = .false.
7270 if( n > 0) then
7271  tn = wcont(tileme)%tile(n)
7272  if( wcont(tileme)%je1(n) == jeg(tileme) .AND. wcont(tileme)%je2(n) == jeg(tn) ) then
7273  m = ncont(tn)%ncontact
7274  if(m >0) then
7275  tc = ncont(tn)%tile(m)
7276  if( ncont(tn)%ie1(m) == ieg(tn) .AND. ncont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7277  end if
7278  end if
7279 end if
7280 if( .not. found_corner ) then ! not found, then starting from north contact
7281  if( ncont(tileme)%ncontact > 0) then
7282  tn = ncont(tileme)%tile(1)
7283  if( ncont(tileme)%is1(1) == isg(tileme) .AND. ncont(tileme)%is2(1) == isg(tn) ) then
7284  if(wcont(tn)%ncontact >0) then
7285  tc = wcont(tn)%tile(1)
7286  if( wcont(tn)%js1(1) == jsg(tn) .AND. wcont(tn)%js2(1) == jsg(tc) ) found_corner = .true.
7287  end if
7288  end if
7289  end if
7290 end if
7291 
7292 if(found_corner) then
7293  nums = nums+1; tilesend(nums) = tc
7294  align1send(nums) = north_west; align2send(nums) = south_east
7295  is1send(nums) = isg(tileme); ie1send(nums) = is1send(nums) + ehalo - 1
7296  je1send(nums) = jeg(tileme); js1send(nums) = je1send(nums) - shalo + 1
7297  is2send(nums) = ieg(tc) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7298  je2send(nums) = jsg(tc) - 1; js2send(nums) = je2send(nums) - shalo + 1
7299 end if
7300 
7301 !--- to_pe's southwest for sending
7302 do n = 1, econt(tileme)%ncontact
7303  tn = econt(tileme)%tile(n)
7304  if(econt(tileme)%js2(n) == jsg(tn) ) then
7305  if(econt(tileme)%js1(n) > jsg(tileme) ) then ! send to tile tn.
7306  if( econt(tileme)%js1(n) - jsg(tileme) < shalo ) call mpp_error(fatal, &
7307  "mpp_domains_define.inc: southwest tile for send 1 is not tiled properly")
7308  nums = nums+1; tilesend(nums) = tn
7309  align1send(nums) = north_east; align2send(nums) = south_west
7310  ie1send(nums) = econt(tileme)%ie1(n); is1send(nums) = ie1send(nums) - whalo + 1
7311  je1send(nums) = econt(tileme)%js1(n) - 1; js1send(nums) = je1send(nums) - shalo + 1
7312  ie2send(nums) = econt(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7313  je2send(nums) = econt(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7314  end if
7315  end if
7316 end do
7317 do n = 1, ncont(tileme)%ncontact
7318  tn = ncont(tileme)%tile(n)
7319  if(ncont(tileme)%is2(n) == isg(tn) ) then
7320  if(ncont(tileme)%is1(n) > isg(tileme) ) then ! send to tile tn.
7321  if( ncont(tileme)%is1(n) - isg(tileme) < whalo ) call mpp_error(fatal, &
7322  "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7323  nums = nums+1; tilesend(nums) = tn
7324  align1send(nums) = north_east; align2send(nums) = south_west
7325  ie1send(nums) = ncont(tileme)%is1(n) - 1; is1send(nums) = ie1send(nums) - whalo + 1
7326  ie1send(nums) = ncont(tileme)%je1(n) ; js1send(nums) = je1send(nums) - shalo + 1
7327  ie2send(nums) = ncont(tileme)%is2(n) - 1; is2send(nums) = je2send(nums) - whalo + 1
7328  je2send(nums) = ncont(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7329  end if
7330  end if
7331 end do
7332 
7333 !--- found the corner overlap that is not specified through contact line.
7334 n = econt(tileme)%ncontact
7335 found_corner = .false.
7336 if( n > 0) then
7337  tn = econt(tileme)%tile(n)
7338  if( econt(tileme)%je1(n) == jeg(tileme) .AND. econt(tileme)%je2(n) == jeg(tn) ) then
7339  if(ncont(tn)%ncontact >0) then
7340  tc = ncont(tn)%tile(1)
7341  if( ncont(tn)%is1(1) == isg(tn) .AND. ncont(tn)%is2(n) == isg(tc) ) found_corner = .true.
7342  end if
7343  end if
7344 end if
7345 if( .not. found_corner ) then ! not found, then starting from north contact
7346  n = ncont(tileme)%ncontact
7347  if( n > 0) then
7348  tn = ncont(tileme)%tile(n)
7349  if( ncont(tileme)%ie1(n) == ieg(tileme) .AND. ncont(tileme)%ie2(n) == ieg(tn) ) then
7350  if(econt(tn)%ncontact >0) then
7351  tc = econt(tn)%tile(1)
7352  if( econt(tn)%js1(1) == jsg(tn) .AND. econt(tn)%js2(n) == jsg(tc) ) found_corner = .true.
7353  end if
7354  end if
7355  end if
7356 end if
7357 
7358 if(found_corner) then
7359  nums = nums+1; tilesend(nums) = tc
7360  align1send(nums) = north_east; align2send(nums) = south_west
7361  ie1send(nums) = ieg(tileme); is1send(nums) = ie1send(nums) - whalo + 1
7362  je1send(nums) = jeg(tileme); js1send(nums) = je1send(nums) - shalo + 1
7363  ie2send(nums) = isg(tc) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7364  je2send(nums) = jsg(tc) - 1; js2send(nums) = je2send(nums) - shalo + 1
7365 end if
7366 
7367 !--- to_pe's northwest for sending
7368 do n = 1, econt(tileme)%ncontact
7369  tn = econt(tileme)%tile(n)
7370  if(econt(tileme)%je2(n) == jeg(tn) ) then
7371  if(econt(tileme)%je1(n) < jeg(tileme) ) then ! send to tile tn.
7372  if( jeg(tileme) - econt(tileme)%je1(n) < nhalo ) call mpp_error(fatal, &
7373  "mpp_domains_define.inc: northwest tile for send 1 is not tiled properly")
7374  nums = nums+1; tilesend(nums) = tn
7375  align1send(nums) = south_east; align2send(nums) = north_west
7376  ie1send(nums) = econt(tileme)%ie1(n) ; is1send(nums) = ie1send(nums) - whalo + 1
7377  js1send(nums) = econt(tileme)%je1(n) + 1; je1send(nums) = js1send(nums) + nhalo - 1
7378  ie2send(nums) = econt(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7379  js2send(nums) = econt(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7380  end if
7381  end if
7382 end do
7383 
7384 do n = 1, scont(tileme)%ncontact
7385  tn = scont(tileme)%tile(n)
7386  if(scont(tileme)%is2(n) == isg(tn) ) then
7387  if(scont(tileme)%is1(n) > isg(tileme) ) then ! send to tile tn.
7388  if( scont(tileme)%is1(n) - isg(tileme) < whalo ) call mpp_error(fatal, &
7389  "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7390  nums = nums+1; tilesend(nums) = tn
7391  align1send(nums) = south_east; align2send(nums) = north_west
7392  ie1send(nums) = ncont(tileme)%is1(n) - 1; is1send(nums) = ie1send(nums) - whalo + 1
7393  js1send(nums) = ncont(tileme)%je1(n) ; je1send(nums) = js1send(nums) + nhalo - 1
7394  ie2send(nums) = ncont(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7395  js2send(nums) = ncont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7396  end if
7397  end if
7398 end do
7399 
7400 !--- found the corner overlap that is not specified through contact line.
7401 n = econt(tileme)%ncontact
7402 found_corner = .false.
7403 if( n > 0) then
7404  tn = econt(tileme)%tile(1)
7405  if( econt(tileme)%js1(1) == jsg(tileme) .AND. econt(tileme)%js2(1) == jsg(tn) ) then
7406  if(scont(tn)%ncontact >0) then
7407  tc = scont(tn)%tile(1)
7408  if( scont(tn)%is1(1) == isg(tn) .AND. scont(tn)%is2(1) == isg(tc) ) found_corner = .true.
7409  end if
7410  end if
7411 end if
7412 if( .not. found_corner ) then ! not found, then starting from north contact
7413  n = scont(tileme)%ncontact
7414  found_corner = .false.
7415  if( n > 0) then
7416  tn = scont(tileme)%tile(n)
7417  if( scont(tileme)%ie1(n) == ieg(tileme) .AND. scont(tileme)%ie2(n) == ieg(tn) ) then
7418  if(econt(tn)%ncontact >0) then
7419  tc = econt(tn)%tile(n)
7420  if( econt(tn)%je1(n) == jeg(tn) .AND. econt(tn)%je2(n) == jeg(tc) ) found_corner = .true.
7421  end if
7422  end if
7423  end if
7424 end if
7425 
7426 if(found_corner) then
7427  nums = nums+1; tilesend(nums) = tc
7428  align1send(nums) = south_east; align2send(nums) = north_west
7429  ie1send(nums) = ieg(tileme); is1send(nums) = ie1send(nums) - whalo + 1
7430  js1send(nums) = jsg(tileme); je1send(nums) = js1send(nums) + nhalo - 1
7431  ie2send(nums) = isg(tc) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7432  js2send(nums) = jeg(tc) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7433 end if
7434 
7435 !--- to_pe's northeast for sending
7436 do n = 1, wcont(tileme)%ncontact
7437  tn = wcont(tileme)%tile(n)
7438  if(wcont(tileme)%je2(n) == jeg(tn) ) then
7439  if(wcont(tileme)%je1(n) < jeg(tileme) ) then ! send to tile tn.
7440  if( jeg(tileme) - wcont(tileme)%je1(n) < nhalo ) call mpp_error(fatal, &
7441  "mpp_domains_define.inc: northeast tile for send 1 is not tiled properly")
7442  nums = nums+1; tilesend(nums) = tn
7443  align1send(nums) = south_west; align2send(nums) = north_east
7444  is1send(nums) = wcont(tileme)%is1(n) ; ie1send(nums) = is1send(nums) + ehalo - 1
7445  js1send(nums) = wcont(tileme)%je1(n) + 1; je1send(nums) = js1send(nums) + nhalo - 1
7446  is2send(nums) = wcont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7447  js2send(nums) = wcont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7448  end if
7449  end if
7450 end do
7451 
7452 do n = 1, scont(tileme)%ncontact
7453  tn = scont(tileme)%tile(n)
7454  if(scont(tileme)%ie2(n) == ieg(tn) ) then
7455  if(scont(tileme)%ie1(n) < ieg(tileme) ) then ! send to tile tn.
7456  if( ieg(tileme) - scont(tileme)%ie1(n) < ehalo ) call mpp_error(fatal, &
7457  "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7458  nums = nums+1; tilesend(nums) = tn
7459  align1send(nums) = south_west; align2send(nums) = north_east
7460  is1send(nums) = scont(tileme)%ie1(n) + 1; ie1send(nums) = is1send(nums) + ehalo - 1
7461  js1send(nums) = scont(tileme)%js1(n) ; je1send(nums) = js1send(nums) + nhalo - 1
7462  is2send(nums) = scont(tileme)%ie2(n) + 1; ie2send(nums) = is1send(nums) + ehalo - 1
7463  js2send(nums) = scont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7464  end if
7465  end if
7466 end do
7467 
7468 !--- found the corner overlap that is not specified through contact line.
7469 n = wcont(tileme)%ncontact
7470 found_corner = .false.
7471 if( n > 0) then
7472  tn = wcont(tileme)%tile(1)
7473  if( wcont(tileme)%js1(n) == jsg(tileme) .AND. wcont(tileme)%js2(n) == jsg(tn) ) then
7474  m = scont(tn)%ncontact
7475  if(m >0) then
7476  tc = scont(tn)%tile(m)
7477  if( scont(tn)%ie1(m) == ieg(tn) .AND. scont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7478  end if
7479  end if
7480 end if
7481 if( .not. found_corner ) then ! not found, then starting from north contact
7482  n = scont(tileme)%ncontact
7483  found_corner = .false.
7484  if( n > 0) then
7485  tn = scont(tileme)%tile(1)
7486  if( scont(tileme)%is1(1) == isg(tileme) .AND. scont(tileme)%is2(1) == isg(tn) ) then
7487  m = wcont(tn)%ncontact
7488  if( m > 0 ) then
7489  tc = wcont(tn)%tile(m)
7490  if( wcont(tn)%je1(m) == jeg(tn) .AND. wcont(tn)%je2(m) == jeg(tc) ) found_corner = .true.
7491  end if
7492  end if
7493  end if
7494 end if
7495 if(found_corner) then
7496  nums = nums+1; tilesend(nums) = tc
7497  align1send(nums) = south_west; align2send(nums) = north_east
7498  is1send(nums) = isg(tileme); ie1send(nums) = is1send(nums) + ehalo - 1
7499  js1send(nums) = jsg(tileme); je1send(nums) = js1send(nums) + nhalo - 1
7500  is2send(nums) = ieg(tc) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7501  js2send(nums) = jeg(tc) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7502 end if
7503 
7504 end subroutine fill_corner_contact
7505 
7506 !--- find the alignment direction, check if index is reversed, if reversed, exchange index.
7507 subroutine check_alignment( is, ie, js, je, isg, ieg, jsg, jeg, alignment )
7508 integer, intent(inout) :: is, ie, js, je, isg, ieg, jsg, jeg
7509 integer, intent(out) :: alignment
7510 
7511 integer :: i, j
7512 
7513 if ( is == ie ) then ! x-alignment
7514  if ( is == isg ) then
7515  alignment = west
7516  else if ( is == ieg ) then
7517  alignment = east
7518  else
7519  call mpp_error(fatal, 'mpp_domains_define.inc: The contact region is not on the x-boundary of the tile')
7520  end if
7521  if ( js > je ) then
7522  j = js; js = je; je = j
7523  end if
7524 else if ( js == je ) then ! y-alignment
7525  if ( js == jsg ) then
7526  alignment = south
7527  else if ( js == jeg ) then
7528  alignment = north
7529  else
7530  call mpp_error(fatal, 'mpp_domains_define.inc: The contact region is not on the y-boundary of the tile')
7531  end if
7532  if ( is > ie ) then
7533  i = is; is = ie; ie = i
7534  end if
7535 else
7536  call mpp_error(fatal, 'mpp_domains_define.inc: The contact region should be line contact' )
7537 end if
7538 
7539 end subroutine check_alignment
7540 !#####################################################################
7541 
7542 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7543 ! !
7544 ! MPP_MODIFY_DOMAIN: modify extent of domain !
7545 ! !
7546 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7547 
7548 !> @brief Modifies the exents of a domain
7549 subroutine mpp_modify_domain1d(domain_in,domain_out,cbegin,cend,gbegin,gend, hbegin, hend)
7550  ! </PUBLICROUTINE>
7551 type(domain1d), intent(in) :: domain_in !< The source domain.
7552 type(domain1d), intent(inout) :: domain_out !< The returned domain.
7553 integer, intent(in), optional :: hbegin, hend !< halo size
7554 integer, intent(in), optional :: cbegin, cend !< Axis specifications associated with the compute
7555  !! domain of the returned 1D domain.
7556 integer, intent(in), optional :: gbegin, gend !< Axis specifications associated with the global
7557  !! domain of the returned 1D domain.
7558 integer :: ndivs, global_indices(2) !(/ isg, ieg /)
7559 integer :: flag
7560 ! get the global indices of the input domain
7561 global_indices(1) = domain_in%global%begin; global_indices(2) = domain_in%global%end
7562 
7563 ! get the layout
7564 ndivs = size(domain_in%list(:))
7565 
7566 ! get the flag
7567 flag = 0
7568 if(domain_in%cyclic) flag = flag + cyclic_global_domain
7569 if(domain_in%domain_data%is_global) flag = flag + global_data_domain
7570 
7571 call mpp_define_domains( global_indices, ndivs, domain_out, pelist = domain_in%list(:)%pe, &
7572  flags = flag, begin_halo = hbegin, end_halo = hend, extent = domain_in%list(:)%compute%size )
7573 
7574 if(present(cbegin)) domain_out%compute%begin = cbegin
7575 if(present(cend)) domain_out%compute%end = cend
7576 domain_out%compute%size = domain_out%compute%end - domain_out%compute%begin + 1
7577 if(present(gbegin)) domain_out%global%begin = gbegin
7578 if(present(gend)) domain_out%global%end = gend
7579 domain_out%global%size = domain_out%global%end - domain_out%global%begin + 1
7580 
7581 end subroutine mpp_modify_domain1d
7582 
7583 !#######################################################################
7584 
7585 subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, &
7586  & shalo, nhalo)
7587  ! </PUBLICROUTINE>
7588 type(domain2d), intent(in) :: domain_in !< The source domain.
7589 type(domain2d), intent(inout) :: domain_out !< The returned domain.
7590 integer, intent(in), optional :: isc, iec, jsc, jec !< Zonal and meridional axis specifications
7591  !! associated with the global domain of the returned 2D domain.
7592 integer, intent(in), optional :: isg, ieg, jsg, jeg !< Zonal axis specifications associated with
7593  !! the global domain of the returned 2D domain.
7594 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size in x- and y- directions
7595 integer :: global_indices(4), layout(2)
7596 integer :: xflag, yflag, nlist, i
7597 
7598 if(present(whalo) .or. present(ehalo) .or. present(shalo) .or. present(nhalo) ) then
7599  ! get the global indices of the input domain
7600  global_indices(1) = domain_in%x(1)%global%begin; global_indices(2) = domain_in%x(1)%global%end
7601  global_indices(3) = domain_in%y(1)%global%begin; global_indices(4) = domain_in%y(1)%global%end
7602 
7603  ! get the layout
7604  layout(1) = size(domain_in%x(1)%list(:)); layout(2) = size(domain_in%y(1)%list(:))
7605 
7606  ! get the flag
7607  xflag = 0; yflag = 0
7608  if(domain_in%x(1)%cyclic) xflag = xflag + cyclic_global_domain
7609  if(domain_in%x(1)%domain_data%is_global) xflag = xflag + global_data_domain
7610  if(domain_in%y(1)%cyclic) yflag = yflag + cyclic_global_domain
7611  if(domain_in%y(1)%domain_data%is_global) yflag = yflag + global_data_domain
7612 
7613  call mpp_define_domains( global_indices, layout, domain_out, pelist = domain_in%list(:)%pe, &
7614  xflags = xflag, yflags = yflag, whalo = whalo, ehalo = ehalo, &
7615  shalo = shalo, nhalo = nhalo, &
7616  xextent = domain_in%x(1)%list(:)%compute%size, &
7617  yextent = domain_in%y(1)%list(:)%compute%size, &
7618  symmetry=domain_in%symmetry, &
7619  maskmap = domain_in%pearray .NE. null_pe )
7620  domain_out%ntiles = domain_in%ntiles
7621  domain_out%tile_id = domain_in%tile_id
7622 else
7623  call mpp_define_null_domain(domain_out)
7624  nlist = size(domain_in%list(:))
7625  if (associated(domain_out%list)) deallocate(domain_out%list) !< Check if allocated
7626  allocate(domain_out%list(0:nlist-1) )
7627  do i = 0, nlist-1
7628  allocate(domain_out%list(i)%tile_id(1))
7629  domain_out%list(i)%tile_id(1) = 1
7630  enddo
7631  call mpp_modify_domain(domain_in%x(1), domain_out%x(1), isc, iec, isg, ieg)
7632  call mpp_modify_domain(domain_in%y(1), domain_out%y(1), jsc, jec, jsg, jeg)
7633  domain_out%ntiles = domain_in%ntiles
7634  domain_out%tile_id = domain_in%tile_id
7635 endif
7636 
7637 end subroutine mpp_modify_domain2d
7638 ! </SUBROUTINE>
7639 
7640 !#####################################################################
7641 
7642 
7643 subroutine mpp_define_null_domain1d(domain)
7644 type(domain1d), intent(inout) :: domain
7645 
7646 domain%global%begin = -1; domain%global%end = -1; domain%global%size = 0
7647 domain%domain_data%begin = -1; domain%domain_data%end = -1; domain%domain_data%size = 0
7648 domain%compute%begin = -1; domain%compute%end = -1; domain%compute%size = 0
7649 domain%pe = null_pe
7650 
7651 end subroutine mpp_define_null_domain1d
7652 
7653 !#####################################################################
7654 
7655 
7656 subroutine mpp_define_null_domain2d(domain)
7657 type(domain2d), intent(inout) :: domain
7658 
7659 allocate(domain%x(1), domain%y(1), domain%tile_id(1))
7660 call mpp_define_null_domain(domain%x(1))
7661 call mpp_define_null_domain(domain%y(1))
7662 domain%pe = null_pe
7663 domain%tile_id(1) = 1
7664 domain%ntiles = 1
7665 domain%max_ntile_pe = 1
7666 domain%ncontacts = 0
7667 
7668 end subroutine mpp_define_null_domain2d
7669 
7670 !####################################################################
7671 
7672 subroutine mpp_deallocate_domain1d(domain)
7673  type(domain1d), intent(inout) :: domain
7674 
7675  if(ASSOCIATED(domain%list)) deallocate(domain%list)
7676 
7677 end subroutine mpp_deallocate_domain1d
7678 
7679 !####################################################################
7680 
7681 subroutine mpp_deallocate_domain2d(domain)
7682  type(domain2d), intent(inout) :: domain
7683 
7684  call deallocate_domain2d_local(domain)
7685  if(ASSOCIATED(domain%io_domain) ) then
7686  call deallocate_domain2d_local(domain%io_domain)
7687  deallocate(domain%io_domain)
7688  endif
7689 
7690 end subroutine mpp_deallocate_domain2d
7691 
7692 !##################################################################
7693 
7694 subroutine deallocate_domain2d_local(domain)
7695 type(domain2d), intent(inout) :: domain
7696 integer :: i, ntileMe
7697 
7698 ntileme = size(domain%x(:))
7699 
7700 if(ASSOCIATED(domain%pearray))deallocate(domain%pearray)
7701 do i = 1, ntileme
7702  call mpp_deallocate_domain1d(domain%x(i))
7703  call mpp_deallocate_domain1d(domain%y(i))
7704 enddo
7705 deallocate(domain%x, domain%y, domain%tile_id)
7706 
7707 ! TODO: Check if these are always allocated
7708 if(ASSOCIATED(domain%tileList)) deallocate(domain%tileList)
7709 if(ASSOCIATED(domain%tile_id_all)) deallocate(domain%tile_id_all)
7710 
7711 if(ASSOCIATED(domain%list)) then
7712  do i = 0, size(domain%list(:))-1
7713  deallocate(domain%list(i)%x, domain%list(i)%y, domain%list(i)%tile_id)
7714  enddo
7715  deallocate(domain%list)
7716 endif
7717 
7718 if(ASSOCIATED(domain%check_C)) then
7719  call deallocate_overlapspec(domain%check_C)
7720  deallocate(domain%check_C)
7721 endif
7722 
7723 if(ASSOCIATED(domain%check_E)) then
7724  call deallocate_overlapspec(domain%check_E)
7725  deallocate(domain%check_E)
7726 endif
7727 
7728 if(ASSOCIATED(domain%check_N)) then
7729  call deallocate_overlapspec(domain%check_N)
7730  deallocate(domain%check_N)
7731 endif
7732 
7733 if(ASSOCIATED(domain%bound_C)) then
7734  call deallocate_overlapspec(domain%bound_C)
7735  deallocate(domain%bound_C)
7736 endif
7737 
7738 if(ASSOCIATED(domain%bound_E)) then
7739  call deallocate_overlapspec(domain%bound_E)
7740  deallocate(domain%bound_E)
7741 endif
7742 
7743 if(ASSOCIATED(domain%bound_N)) then
7744  call deallocate_overlapspec(domain%bound_N)
7745  deallocate(domain%bound_N)
7746 endif
7747 
7748 if(ASSOCIATED(domain%update_T)) then
7749  call deallocate_overlapspec(domain%update_T)
7750  deallocate(domain%update_T)
7751 endif
7752 
7753 if(ASSOCIATED(domain%update_E)) then
7754  call deallocate_overlapspec(domain%update_E)
7755  deallocate(domain%update_E)
7756 endif
7757 
7758 if(ASSOCIATED(domain%update_C)) then
7759  call deallocate_overlapspec(domain%update_C)
7760  deallocate(domain%update_C)
7761 endif
7762 
7763 if(ASSOCIATED(domain%update_N)) then
7764  call deallocate_overlapspec(domain%update_N)
7765  deallocate(domain%update_N)
7766 endif
7767 
7768 end subroutine deallocate_domain2d_local
7769 
7770 !####################################################################
7771 
7772 subroutine allocate_check_overlap(overlap, count)
7773  type(overlap_type), intent(inout) :: overlap
7774  integer, intent(in ) :: count
7775 
7776  overlap%count = 0
7777  overlap%pe = null_pe
7778  if(associated(overlap%tileMe)) call mpp_error(fatal, &
7779  "allocate_check_overlap(mpp_domains_define): overlap is already been allocated")
7780  if(count < 1) call mpp_error(fatal, &
7781  "allocate_check_overlap(mpp_domains_define): count should be a positive integer")
7782  allocate(overlap%tileMe (count), overlap%dir(count) )
7783  allocate(overlap%is (count), overlap%ie (count) )
7784  allocate(overlap%js (count), overlap%je (count) )
7785  allocate(overlap%rotation(count) )
7786  overlap%rotation = zero
7787 
7788 end subroutine allocate_check_overlap
7789 
7790 !#######################################################################
7791 subroutine insert_check_overlap(overlap, pe, tileMe, dir, rotation, is, ie, js, je)
7792  type(overlap_type), intent(inout) :: overlap
7793  integer, intent(in ) :: pe
7794  integer, intent(in ) :: tileMe, dir, rotation
7795  integer, intent(in ) :: is, ie, js, je
7796  integer :: count
7797 
7798  overlap%count = overlap%count + 1
7799  count = overlap%count
7800  if(.NOT. associated(overlap%tileMe)) call mpp_error(fatal, &
7801  "mpp_domains_define.inc(insert_check_overlap): overlap is not assigned any memory")
7802  if(count > size(overlap%tileMe(:)) ) call mpp_error(fatal, &
7803  "mpp_domains_define.inc(insert_check_overlap): overlap%count is greater than size(overlap%tileMe)")
7804  if( overlap%pe == null_pe ) then
7805  overlap%pe = pe
7806  else
7807  if(overlap%pe .NE. pe) call mpp_error(fatal, &
7808  "mpp_domains_define.inc(insert_check_overlap): mismatch on pe")
7809  endif
7810  overlap%tileMe (count) = tileme
7811  overlap%dir (count) = dir
7812  overlap%rotation(count) = rotation
7813  overlap%is (count) = is
7814  overlap%ie (count) = ie
7815  overlap%js (count) = js
7816  overlap%je (count) = je
7817 
7818 end subroutine insert_check_overlap
7819 
7820 !#######################################################################
7821 !> this routine adds the overlap_in into overlap_out
7822 subroutine add_check_overlap( overlap_out, overlap_in)
7823  type(overlap_type), intent(inout) :: overlap_out
7824  type(overlap_type), intent(in ) :: overlap_in
7825  type(overlap_type) :: overlap
7826  integer :: count, count_in, count_out
7827 
7828  ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
7829  count_in = overlap_in %count
7830  count_out = overlap_out%count
7831  count = count_in+count_out
7832  if(count_in == 0) call mpp_error(fatal, &
7833  "add_check_overlap(mpp_domains_define): overlap_in%count is zero")
7834 
7835  if(count_out == 0) then
7836  if(associated(overlap_out%tileMe)) call mpp_error(fatal, &
7837  "add_check_overlap(mpp_domains_define): overlap is already been allocated but count=0")
7838  call allocate_check_overlap(overlap_out, count_in)
7839  overlap_out%pe = overlap_in%pe
7840  else ! need to expand the dimension size of overlap
7841  call allocate_check_overlap(overlap, count_out)
7842  if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(fatal, &
7843  "mpp_domains_define.inc(add_check_overlap): mismatch of pe between overlap_in and overlap_out")
7844  overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
7845  overlap%is (1:count_out) = overlap_out%is (1:count_out)
7846  overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
7847  overlap%js (1:count_out) = overlap_out%js (1:count_out)
7848  overlap%je (1:count_out) = overlap_out%je (1:count_out)
7849  overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
7850  overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
7851  call deallocate_overlap_type(overlap_out)
7852  call allocate_check_overlap(overlap_out, count)
7853  overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
7854  overlap_out%is (1:count_out) = overlap%is (1:count_out)
7855  overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
7856  overlap_out%js (1:count_out) = overlap%js (1:count_out)
7857  overlap_out%je (1:count_out) = overlap%je (1:count_out)
7858  overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
7859  overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
7860  call deallocate_overlap_type(overlap)
7861  end if
7862  overlap_out%count = count
7863  overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
7864  overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
7865  overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
7866  overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
7867  overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
7868  overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
7869  overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
7870 
7871 end subroutine add_check_overlap
7872 
7873 !####################################################################
7874 subroutine init_overlap_type(overlap)
7875  type(overlap_type), intent(inout) :: overlap
7876 
7877  overlap%count = 0
7878  overlap%pe = null_pe
7879 
7880 end subroutine init_overlap_type
7881 
7882 !####################################################################
7883 
7884 subroutine allocate_update_overlap( overlap, count)
7885  type(overlap_type), intent(inout) :: overlap
7886  integer, intent(in ) :: count
7887 
7888  overlap%count = 0
7889  overlap%pe = null_pe
7890  if(associated(overlap%tileMe)) call mpp_error(fatal, &
7891  "allocate_update_overlap(mpp_domains_define): overlap is already been allocated")
7892  if(count < 1) call mpp_error(fatal, &
7893  "allocate_update_overlap(mpp_domains_define): count should be a positive integer")
7894  allocate(overlap%tileMe (count), overlap%tileNbr (count) )
7895  allocate(overlap%is (count), overlap%ie (count) )
7896  allocate(overlap%js (count), overlap%je (count) )
7897  allocate(overlap%dir (count), overlap%rotation(count) )
7898  allocate(overlap%from_contact(count), overlap%msgsize (count) )
7899  overlap%rotation = zero
7900  overlap%from_contact = .false.
7901 
7902 end subroutine allocate_update_overlap
7903 
7904  !#####################################################################################
7905  subroutine insert_update_overlap(overlap, pe, is1, ie1, js1, je1, is2, ie2, js2, je2, dir, reverse, symmetry)
7906  type(overlap_type), intent(inout) :: overlap
7907  integer, intent(in ) :: pe
7908  integer, intent(in ) :: is1, ie1, js1, je1, is2, ie2, js2, je2
7909  integer, intent(in ) :: dir
7910  logical, optional, intent(in ) :: reverse, symmetry
7911 
7912  logical :: is_reverse, is_symmetry, is_overlapped
7913  integer :: is, ie, js, je, count
7914 
7915  is_reverse = .false.
7916  if(PRESENT(reverse)) is_reverse = reverse
7917  is_symmetry = .false.
7918  if(PRESENT(symmetry)) is_symmetry = symmetry
7919 
7920  is = max(is1,is2); ie = min(ie1,ie2)
7921  js = max(js1,js2); je = min(je1,je2)
7922  is_overlapped = .false.
7923  !--- to avoid unnecessary ( duplicate overlap ) for symmetry domain
7924  if(is_symmetry .AND. (dir == 1 .OR. dir == 5)) then ! x-direction
7925  if( ie .GE. is .AND. je .GT. js ) is_overlapped = .true.
7926  else if(is_symmetry .AND. (dir == 3 .OR. dir == 7)) then ! y-direction
7927  if( ie .GT. is .AND. je .GE. js ) is_overlapped = .true.
7928  else if(ie.GE.is .AND. je.GE.js )then
7929  is_overlapped = .true.
7930  endif
7931 
7932  if(is_overlapped) then
7933  if( overlap%count == 0 ) then
7934  overlap%pe = pe
7935  else
7936  if(overlap%pe .NE. pe) call mpp_error(fatal, &
7937  "mpp_domains_define.inc(insert_update_overlap): mismatch on pe")
7938  endif
7939  overlap%count = overlap%count+1
7940  count = overlap%count
7941  if(count > maxoverlap) call mpp_error(fatal, "mpp_domains_define.inc(insert_update_overlap):"//&
7942  & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7943  overlap%is(count) = is
7944  overlap%ie(count) = ie
7945  overlap%js(count) = js
7946  overlap%je(count) = je
7947  overlap%tileMe (count) = 1
7948  overlap%tileNbr(count) = 1
7949  overlap%dir(count) = dir
7950  if(is_reverse) then
7951  overlap%rotation(count) = one_hundred_eighty
7952  else
7953  overlap%rotation(count) = zero
7954  end if
7955  end if
7956 
7957  end subroutine insert_update_overlap
7958 
7959  !#####################################################################################
7960 subroutine insert_overlap_type(overlap, pe, tileMe, tileNbr, is, ie, js, je, dir, &
7961  rotation, from_contact)
7962  type(overlap_type), intent(inout) :: overlap
7963  integer, intent(in ) :: tileMe, tileNbr, pe
7964  integer, intent(in ) :: is, ie, js, je
7965  integer, intent(in ) :: dir, rotation
7966  logical, intent(in ) :: from_contact
7967  integer :: count
7968 
7969  if( overlap%count == 0 ) then
7970  overlap%pe = pe
7971  else
7972  if(overlap%pe .NE. pe) call mpp_error(fatal, &
7973  "mpp_domains_define.inc(insert_overlap_type): mismatch on pe")
7974  endif
7975  overlap%count = overlap%count+1
7976  count = overlap%count
7977  if(count > maxoverlap) call mpp_error(fatal, "mpp_domains_define.inc(insert_overlap_type):"//&
7978  & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7979  overlap%tileMe (count) = tileme
7980  overlap%tileNbr (count) = tilenbr
7981  overlap%is (count) = is
7982  overlap%ie (count) = ie
7983  overlap%js (count) = js
7984  overlap%je (count) = je
7985  overlap%dir (count) = dir
7986  overlap%rotation (count) = rotation
7987  overlap%from_contact(count) = from_contact
7988  overlap%msgsize (count) = (ie-is+1)*(je-js+1)
7989 
7990 end subroutine insert_overlap_type
7991 
7992 
7993 !#######################################################################
7994 subroutine deallocate_overlap_type( overlap)
7995  type(overlap_type), intent(inout) :: overlap
7996 
7997  if(overlap%count == 0) then
7998  if( .NOT. associated(overlap%tileMe)) return
7999  else
8000  if( .NOT. associated(overlap%tileMe)) call mpp_error(fatal, &
8001  "deallocate_overlap_type(mpp_domains_define): overlap is not been allocated")
8002  endif
8003  if(ASSOCIATED(overlap%tileMe)) deallocate(overlap%tileMe)
8004  if(ASSOCIATED(overlap%tileNbr)) deallocate(overlap%tileNbr)
8005  if(ASSOCIATED(overlap%is)) deallocate(overlap%is)
8006  if(ASSOCIATED(overlap%ie)) deallocate(overlap%ie)
8007  if(ASSOCIATED(overlap%js)) deallocate(overlap%js)
8008  if(ASSOCIATED(overlap%je)) deallocate(overlap%je)
8009  if(ASSOCIATED(overlap%dir)) deallocate(overlap%dir)
8010  if(ASSOCIATED(overlap%index)) deallocate(overlap%index)
8011  if(ASSOCIATED(overlap%rotation)) deallocate(overlap%rotation)
8012  if(ASSOCIATED(overlap%from_contact)) deallocate(overlap%from_contact)
8013  if(ASSOCIATED(overlap%msgsize)) deallocate(overlap%msgsize)
8014  overlap%count = 0
8015 
8016 end subroutine deallocate_overlap_type
8017 
8018 !#######################################################################
8019 subroutine deallocate_overlapspec(overlap)
8020 type(overlapspec), intent(inout) :: overlap
8021 integer :: n
8022 
8023  if(ASSOCIATED(overlap%send)) then
8024  do n = 1, size(overlap%send(:))
8025  call deallocate_overlap_type(overlap%send(n))
8026  enddo
8027  deallocate(overlap%send)
8028  endif
8029  if(ASSOCIATED(overlap%recv)) then
8030  do n = 1, size(overlap%recv(:))
8031  call deallocate_overlap_type(overlap%recv(n))
8032  enddo
8033  deallocate(overlap%recv)
8034  endif
8035 
8036 
8037 end subroutine deallocate_overlapspec
8038 
8039 !#######################################################################
8040 !--- this routine add the overlap_in into overlap_out
8041 subroutine add_update_overlap( overlap_out, overlap_in)
8042  type(overlap_type), intent(inout) :: overlap_out
8043  type(overlap_type), intent(in ) :: overlap_in
8044  type(overlap_type) :: overlap
8045  integer :: count, count_in, count_out, n
8046 
8047  ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
8048  count_in = overlap_in %count
8049  count_out = overlap_out%count
8050  count = count_in+count_out
8051  if(count_in == 0) call mpp_error(fatal, &
8052  "mpp_domains_define.inc(add_update_overlap): overlap_in%count is zero")
8053 
8054  if(count_out == 0) then
8055  if(associated(overlap_out%tileMe)) call mpp_error(fatal, &
8056  "mpp_domains_define.inc(add_update_overlap): overlap is already been allocated but count=0")
8057  call allocate_update_overlap(overlap_out, count_in)
8058  overlap_out%pe = overlap_in%pe
8059  else ! need to expand the dimension size of overlap
8060  if(overlap_in%pe .NE. overlap_out%pe) call mpp_error(fatal, &
8061  "mpp_domains_define.inc(add_update_overlap): mismatch of pe between overlap_in and overlap_out")
8062 
8063  call allocate_update_overlap(overlap, count_out)
8064  overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
8065  overlap%tileNbr (1:count_out) = overlap_out%tileNbr (1:count_out)
8066  overlap%is (1:count_out) = overlap_out%is (1:count_out)
8067  overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
8068  overlap%js (1:count_out) = overlap_out%js (1:count_out)
8069  overlap%je (1:count_out) = overlap_out%je (1:count_out)
8070  overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
8071  overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
8072  overlap%from_contact(1:count_out) = overlap_out%from_contact(1:count_out)
8073  call deallocate_overlap_type(overlap_out)
8074  call allocate_update_overlap(overlap_out, count)
8075  overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
8076  overlap_out%tileNbr (1:count_out) = overlap%tileNbr (1:count_out)
8077  overlap_out%is (1:count_out) = overlap%is (1:count_out)
8078  overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
8079  overlap_out%js (1:count_out) = overlap%js (1:count_out)
8080  overlap_out%je (1:count_out) = overlap%je (1:count_out)
8081  overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
8082  overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
8083  overlap_out%index (1:count_out) = overlap%index (1:count_out)
8084  overlap_out%from_contact(1:count_out) = overlap%from_contact(1:count_out)
8085  overlap_out%msgsize (1:count_out) = overlap%msgsize (1:count_out)
8086  call deallocate_overlap_type(overlap)
8087  end if
8088  overlap_out%count = count
8089  overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
8090  overlap_out%tileNbr (count_out+1:count) = overlap_in%tileNbr (1:count_in)
8091  overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
8092  overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
8093  overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
8094  overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
8095  overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
8096  overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
8097  overlap_out%from_contact(count_out+1:count) = overlap_in%from_contact(1:count_in)
8098 
8099  do n = count_out+1, count
8100  overlap_out%msgsize(n) = (overlap_out%ie(n)-overlap_out%is(n)+1)*(overlap_out%je(n)-overlap_out%js(n)+1)
8101  enddo
8102 
8103 
8104 end subroutine add_update_overlap
8105 
8106 !##############################################################################
8107 subroutine expand_update_overlap_list(overlapList, npes)
8108  type(overlap_type), pointer :: overlapList(:)
8109  integer, intent(in ) :: npes
8110  type(overlap_type), pointer,save :: newlist(:) => null()
8111  integer :: nlist_old, nlist, m
8112 
8113  nlist_old = size(overlaplist(:))
8114  if(nlist_old .GE. npes) call mpp_error(fatal, &
8115  'mpp_domains_define.inc(expand_update_overlap_list): size of overlaplist should be smaller than npes')
8116  nlist = min(npes, 2*nlist_old)
8117  allocate(newlist(nlist))
8118  do m = 1, nlist_old
8119  call add_update_overlap(newlist(m), overlaplist(m))
8120  call deallocate_overlap_type(overlaplist(m))
8121  enddo
8122 
8123  deallocate(overlaplist)
8124  overlaplist => newlist
8125  newlist => null()
8126 
8127  return
8128 
8129 end subroutine expand_update_overlap_list
8130 
8131 !##################################################################################
8132 subroutine expand_check_overlap_list(overlaplist, npes)
8133  type(overlap_type), pointer :: overlaplist(:)
8134  integer, intent(in) :: npes
8135  type(overlap_type), pointer,save :: newlist(:) => null()
8136  integer :: nlist_old, nlist, m
8137 
8138  nlist_old = size(overlaplist(:))
8139  if(nlist_old .GE. npes) call mpp_error(fatal, &
8140  'mpp_domains_define.inc(expand_check_overlap_list): size of overlaplist should be smaller than npes')
8141  nlist = min(npes, 2*nlist_old)
8142  allocate(newlist(nlist))
8143  do m = 1,size(overlaplist(:))
8144  call add_check_overlap(newlist(m), overlaplist(m))
8145  call deallocate_overlap_type(overlaplist(m))
8146  enddo
8147  deallocate(overlaplist)
8148  overlaplist => newlist
8149 
8150 
8151  return
8152 
8153 end subroutine expand_check_overlap_list
8154 
8155 
8156 !###############################################################################
8157 subroutine check_overlap_pe_order(domain, overlap, name)
8158  type(domain2d), intent(in) :: domain
8159  type(overlapspec), intent(in) :: overlap
8160  character(len=*), intent(in) :: name
8161  integer :: m
8162  integer :: pe1, pe2
8163 
8164  !---make sure overlap%nsend and overlap%nrecv is no larger than MAXLIST
8165  if( overlap%nsend > maxlist) call mpp_error(fatal, &
8166  "mpp_domains_define.inc(check_overlap_pe_order): overlap%nsend > MAXLIST, increase MAXLIST")
8167  if( overlap%nrecv > maxlist) call mpp_error(fatal, &
8168  "mpp_domains_define.inc(check_overlap_pe_order): overlap%nrecv > MAXLIST, increase MAXLIST")
8169 
8170  do m = 2, overlap%nsend
8171  pe1 = overlap%send(m-1)%pe
8172  pe2 = overlap%send(m)%pe
8173  !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8174  if( pe2 == domain%pe ) then
8175  print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8176  call mpp_error(fatal, &
8177  "mpp_domains_define.inc(check_overlap_pe_order): send pe2 can not equal to domain%pe")
8178  else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8179  if( pe2 < pe1 ) then
8180  print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8181  call mpp_error(fatal, &
8182  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 1")
8183  endif
8184  else if ( pe2 > domain%pe .AND. pe1 < domain%pe ) then
8185  print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8186  call mpp_error(fatal, &
8187  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 2")
8188  endif
8189  enddo
8190 
8191 
8192  do m = 2, overlap%nrecv
8193  pe1 = overlap%recv(m-1)%pe
8194  pe2 = overlap%recv(m)%pe
8195  !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8196  if( pe2 == domain%pe ) then
8197  print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8198  call mpp_error(fatal, &
8199  "mpp_domains_define.inc(check_overlap_pe_order): recv pe2 can not equal to domain%pe")
8200  else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8201  if( pe2 > pe1 ) then
8202  print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8203  call mpp_error(fatal, &
8204  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 1")
8205  endif
8206  else if ( pe2 < domain%pe .AND. pe1 > domain%pe ) then
8207  print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8208  call mpp_error(fatal, &
8209  "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 2")
8210  endif
8211  enddo
8212 
8213 
8214 end subroutine check_overlap_pe_order
8215 
8216 
8217 !###############################################################################
8218 subroutine set_domain_comm_inf(update)
8219  type(overlapspec), intent(inout) :: update
8220 
8221  integer :: m, totsize, n
8222 
8223 
8224  ! first set the send and recv size
8225  update%sendsize = 0
8226  update%recvsize = 0
8227  do m = 1, update%nrecv
8228  totsize = 0
8229  do n = 1, update%recv(m)%count
8230  totsize = totsize + update%recv(m)%msgsize(n)
8231  enddo
8232  update%recv(m)%totsize = totsize
8233  if(m==1) then
8234  update%recv(m)%start_pos = 0
8235  else
8236  update%recv(m)%start_pos = update%recv(m-1)%start_pos + update%recv(m-1)%totsize
8237  endif
8238  update%recvsize = update%recvsize + totsize
8239  enddo
8240 
8241  do m = 1, update%nsend
8242  totsize = 0
8243  do n = 1, update%send(m)%count
8244  totsize = totsize + update%send(m)%msgsize(n)
8245  enddo
8246  update%send(m)%totsize = totsize
8247  if(m==1) then
8248  update%send(m)%start_pos = 0
8249  else
8250  update%send(m)%start_pos = update%send(m-1)%start_pos + update%send(m-1)%totsize
8251  endif
8252  update%sendsize = update%sendsize + totsize
8253  enddo
8254 
8255  return
8256 
8257 
8258 end subroutine set_domain_comm_inf
8259 !> @}
subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, shalo, nhalo)
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, tile_base)
compute the overlapping between tiles for the T-cell.
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 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:42
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
Definition: mpp_util.inc:50
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:58
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:420
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406