FMS 2025.01-dev
Flexible Modeling System
Loading...
Searching...
No Matches
mpp_domains_define.inc
1! -*-f90-*-
2!***********************************************************************
3!* GNU Lesser General Public License
4!*
5!* This file is part of the GFDL Flexible Modeling System (FMS).
6!*
7!* FMS is free software: you can redistribute it and/or modify it under
8!* the terms of the GNU Lesser General Public License as published by
9!* the Free Software Foundation, either version 3 of the License, or (at
10!* your option) any later version.
11!*
12!* FMS is distributed in the hope that it will be useful, but WITHOUT
13!* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14!* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15!* for more details.
16!*
17!* You should have received a copy of the GNU Lesser General Public
18!* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
19!***********************************************************************
20
21!> @file
22!> @brief Various routines handling domains in @ref mpp_domains_mod
23
24!> @addtogroup mpp_domains_mod
25!> @{
26 !> @brief Instantiates a layout with the given indices and divisions
27 subroutine mpp_define_layout2d( global_indices, ndivs, layout )
28 integer, intent(in) :: global_indices(:) !< (/ isg, ieg, jsg, jeg /); Defines the global domain.
29 integer, intent(in) :: ndivs !< number of divisions to divide global domain
30 integer, intent(out) :: layout(:)
31
32 integer :: isg, ieg, jsg, jeg, isz, jsz, idiv, jdiv
33
34 if(size(global_indices(:)) .NE. 4) call mpp_error(fatal,"mpp_define_layout2D: size of global_indices should be 4")
35 if(size(layout(:)) .NE. 2) call mpp_error(fatal,"mpp_define_layout2D: size of layout should be 2")
36
37 isg = global_indices(1)
38 ieg = global_indices(2)
39 jsg = global_indices(3)
40 jeg = global_indices(4)
41
42 isz = ieg - isg + 1
43 jsz = jeg - jsg + 1
44 !first try to divide ndivs in the domain aspect ratio: if imperfect aspect, reduce idiv till it divides ndivs
45 idiv = nint( sqrt(float(ndivs*isz)/jsz) )
46 idiv = max(idiv,1) !for isz=1 line above can give 0
47 do while( mod(ndivs,idiv).NE.0 )
48 idiv = idiv - 1
49 end do !will terminate at idiv=1 if not before
50 jdiv = ndivs/idiv
51
52 layout = (/ idiv, jdiv /)
53 return
54 end subroutine mpp_define_layout2d
55
56 !############################################################################
57
58 !> Defines a pelist for use with mosaic tiles
59 !! @note The following routine may need to revised to improve the capability.
60 !! It is very hard to make it balance for all the situation.
61 !! Hopefully some smart idea will come up someday.
62 subroutine mpp_define_mosaic_pelist( sizes, pe_start, pe_end, pelist, costpertile)
63 integer, dimension(:), intent(in) :: sizes
64 integer, dimension(:), intent(inout) :: pe_start, pe_end
65 integer, dimension(:), intent(in), optional :: pelist, costpertile
66 integer, dimension(size(sizes(:))) :: costs
67 integer, dimension(:), allocatable :: pes
68 integer :: ntiles, npes, totcosts, avgcost
69 integer :: ntiles_left, npes_left, pos, n, tile
70 integer :: cost_on_tile, cost_on_pe, npes_used, errunit
71
72 ntiles = size(sizes(:))
73 if(size(pe_start(:)) .NE. ntiles .OR. size(pe_end(:)) .NE. ntiles ) then
74 call mpp_error(fatal, "mpp_define_mosaic_pelist: size mismatch between pe_start/pe_end and sizes")
75 end if
76
77 if(present(costpertile)) then
78 if(size(costpertile(:)) .NE. ntiles ) then
79 call mpp_error(fatal, "mpp_define_mosaic_pelist: size mismatch between costpertile and sizes")
80 end if
81 costs = sizes*costpertile
82 else
83 costs = sizes
84 end if
85
86 if( PRESENT(pelist) )then
87 if( .NOT.any(pelist.EQ.mpp_pe()) )then
88 errunit = stderr()
89 write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
90 call mpp_error( fatal, 'mpp_define_mosaic_pelist: pe must be in pelist.' )
91 end if
92 npes = size(pelist(:))
93 allocate( pes(0:npes-1) )
94 pes(:) = pelist(:)
95 else
96 npes = mpp_npes()
97 allocate( pes(0:npes-1) )
98 call mpp_get_current_pelist(pes)
99 end if
100
101 ntiles_left = ntiles
102 npes_left = npes
103 pos = pes(0)
104
105 do while( ntiles_left > 0 )
106 if( npes_left == 1 ) then ! all left tiles will on the last processor, imbalance possibly.
107 do n = 1, ntiles
108 if(costs(n) > 0) then
109 pe_start(n) = pos
110 pe_end(n) = pos
111 costs(n) = 0
112 end if
113 end do
114 ntiles_left = 0
115 npes_left = 0
116 else
117 totcosts = sum(costs)
118 avgcost = ceiling(real(totcosts)/npes_left )
119 tile = minval(maxloc(costs))
120 cost_on_tile = costs(tile)
121 pe_start(tile) = pos
122 ntiles_left = ntiles_left - 1
123 costs(tile) = 0
124 totcosts = totcosts - cost_on_tile
125 if(cost_on_tile .GE. avgcost ) then
126 npes_used = min(ceiling(real(cost_on_tile)/avgcost), npes_left)
127 if( ntiles_left > 0 .AND. npes_used == npes_left ) npes_used = npes_used - 1
128 pe_end(tile) = pos + npes_used - 1
129 npes_left = npes_left - npes_used
130 pos = pos + npes_used
131 else
132 !--- find other tiles to share the pe
133 pe_end(tile) = pos
134 cost_on_pe = cost_on_tile
135 do while(ntiles_left>npes_left) ! make sure all the pes are used.
136 tile = minval(minloc(costs, costs> 0 ))
137 cost_on_tile = costs(tile)
138 cost_on_pe = cost_on_pe + cost_on_tile
139 if(cost_on_pe > avgcost ) exit
140 pe_start(tile) = pos
141 pe_end(tile) = pos
142 ntiles_left = ntiles_left - 1
143 costs(tile) = 0
144 totcosts = totcosts - cost_on_tile
145 end do
146 npes_left = npes_left - 1
147 pos = pos + 1
148 end if
149 end if
150 end do
151
152 if(npes_left .NE. 0 ) call mpp_error(fatal, "mpp_define_mosaic_pelist: the left npes should be zero")
153 deallocate(pes)
154
155 end subroutine mpp_define_mosaic_pelist
156
157 !> Computes the extents of a grid block
158 !!
159 !> Tis implementation is different from mpp_compute_extents
160 !! The last block might have most points
161 subroutine mpp_compute_block_extent(isg,ieg,ndivs,ibegin,iend)
162 integer, intent(in) :: isg, ieg, ndivs
163 integer, dimension(:), intent(out) :: ibegin, iend
164
165 integer :: ndiv
166 integer :: is, ie
167
168 ie = ieg
169 do ndiv=ndivs,1,-1
170 !domain is sized by dividing remaining points by remaining domains
171 is = ie - ceiling( real(ie-isg+1)/ndiv ) + 1
172 ibegin(ndiv) = is
173 iend(ndiv) = ie
174
175 if( ie.LT.is )call mpp_error( fatal, &
176 'MPP_DEFINE_DOMAINS(mpp_compute_block_extent): domain extents must be positive definite.' )
177 if( ndiv.EQ.1 .AND. ibegin(ndiv) .NE. isg ) &
178 call mpp_error( fatal, 'mpp_compute_block_extent: domain extents do not span space completely.' )
179 ie = is - 1
180 end do
181
182 end subroutine mpp_compute_block_extent
183
184
185 !#####################################################################
186 !> Computes extents for a grid decomposition with the given indices and divisions
187 subroutine mpp_compute_extent(isg,ieg,ndivs,ibegin,iend, extent )
188 integer, intent(in) :: isg, ieg, ndivs
189 integer, dimension(0:), intent(out) :: ibegin, iend
190 integer, dimension(0:), intent(in), optional :: extent
191
192 integer :: ndiv, imax, ndmax, ndmirror
193 integer :: is, ie, n
194 logical :: symmetrize, use_extent
195 !statement functions
196 logical :: even, odd
197 even(n) = (mod(n,2).EQ.0)
198 odd(n) = (mod(n,2).EQ.1)
199
200 use_extent = .false.
201 if(PRESENT(extent)) then
202 if( size(extent(:)).NE.ndivs ) &
203 call mpp_error( fatal, 'mpp_compute_extent: extent array size must equal number of domain divisions.' )
204 use_extent = .true.
205 if(all(extent ==0)) use_extent = .false.
206 endif
207
208 is = isg
209 if(use_extent) then
210 ibegin(0) = isg
211 do ndiv = 0, ndivs-2
212 if(extent(ndiv) .LE. 0) call mpp_error( fatal, &
213 & 'mpp_compute_extent: domain extents must be positive definite.' )
214 iend(ndiv) = ibegin(ndiv) + extent(ndiv) - 1
215 ibegin(ndiv+1) = iend(ndiv) + 1
216 enddo
217 iend(ndivs-1) = ibegin(ndivs-1) + extent(ndivs-1) - 1
218 if(iend(ndivs-1) .NE. ieg) call mpp_error(fatal, &
219 & 'mpp_compute_extent: extent array limits do not match global domain.' )
220 else
221 do ndiv=0,ndivs-1
222 !modified for mirror-symmetry
223 !original line
224 ! ie = is + CEILING( float(ieg-is+1)/(ndivs-ndiv) ) - 1
225
226 !problem of dividing nx points into n domains maintaining symmetry
227 !i.e nx=18 n=4 4554 and 5445 are solutions but 4455 is not.
228 !this will always work for nx even n even or odd
229 !this will always work for nx odd, n odd
230 !this will never work for nx odd, n even: for this case we supersede the mirror calculation
231 ! symmetrize = .NOT. ( mod(ndivs,2).EQ.0 .AND. mod(ieg-isg+1,2).EQ.1 )
232 !nx even n odd fails if n>nx/2
233 symmetrize = ( even(ndivs) .AND. even(ieg-isg+1) ) .OR. &
234 ( odd(ndivs) .AND. odd(ieg-isg+1) ) .OR. &
235 ( odd(ndivs) .AND. even(ieg-isg+1) .AND. ndivs.LT.(ieg-isg+1)/2 )
236
237 !mirror domains are stored in the list and retrieved if required.
238 if( ndiv.EQ.0 )then
239 !initialize max points and max domains
240 imax = ieg
241 ndmax = ndivs
242 end if
243 !do bottom half of decomposition, going over the midpoint for odd ndivs
244 if( ndiv.LT.(ndivs-1)/2+1 )then
245 !domain is sized by dividing remaining points by remaining domains
246 ie = is + ceiling( real(imax-is+1)/(ndmax-ndiv) ) - 1
247 ndmirror = (ndivs-1) - ndiv !mirror domain
248 if( ndmirror.GT.ndiv .AND. symmetrize )then !only for domains over the midpoint
249 !mirror extents, the max(,) is to eliminate overlaps
250 ibegin(ndmirror) = max( isg+ieg-ie, ie+1 )
251 iend(ndmirror) = max( isg+ieg-is, ie+1 )
252 imax = ibegin(ndmirror) - 1
253 ndmax = ndmax - 1
254 end if
255 else
256 if( symmetrize )then
257 !do top half of decomposition by retrieving saved values
258 is = ibegin(ndiv)
259 ie = iend(ndiv)
260 else
261 ie = is + ceiling( real(imax-is+1)/(ndmax-ndiv) ) - 1
262 end if
263 end if
264 ibegin(ndiv) = is
265 iend(ndiv) = ie
266 if( ie.LT.is )call mpp_error( fatal, &
267 'MPP_DEFINE_DOMAINS(mpp_compute_extent): domain extents must be positive definite.' )
268 if( ndiv.EQ.ndivs-1 .AND. iend(ndiv).NE.ieg ) &
269 call mpp_error( fatal, 'mpp_compute_extent: domain extents do not span space completely.' )
270 is = ie + 1
271 end do
272 endif
273
274
275 end subroutine mpp_compute_extent
276
277 !#####################################################################
278
279
280 !> Define data and computational domains on a 1D set of data (isg:ieg) and assign them to PEs
281 subroutine mpp_define_domains1d( global_indices, ndivs, domain, pelist, flags, halo, extent, maskmap, &
282 memory_size, begin_halo, end_halo )
283 integer, intent(in) :: global_indices(:) !< (/ isg, ieg /) gives the extent of global domain
284 integer, intent(in) :: ndivs !< number of divisions of domain: even divisions unless extent is present.
285 type(domain1d), intent(inout) :: domain !< the returned domain1D; declared inout so that
286 !! existing links, if any, can be nullified
287 integer, intent(in), optional :: pelist(0:) !< list of PEs to which domains are to be assigned
288 !! (default 0...npes-1); size of pelist must
289 !! correspond to number of mask=.TRUE. divisions
290 integer, intent(in), optional :: flags, halo !< flags define whether compute and data domains
291 !! are global (undecomposed) and whether the global
292 !! domain has periodic boundaries.
293 !! halo defines halo width (currently the same on both sides)
294 integer, intent(in), optional :: extent(0:) !< array extent; defines width of each division
295 !! (used for non-uniform domain decomp, for e.g load-balancing)
296 logical, intent(in), optional :: maskmap(0:) !< a division whose maskmap=.FALSE. is not
297 !! assigned to any domain. By default we assume
298 !! decomposition of compute and data domains, non-periodic boundaries,
299 !! no halo, as close to uniform extents as the
300 !! input parameters permit
301 integer, intent(in), optional :: memory_size
302 integer, intent(in), optional :: begin_halo, end_halo
303
304 logical :: compute_domain_is_global, data_domain_is_global
305 integer :: ndiv, n, isg, ieg
306 integer, allocatable :: pes(:)
307 integer :: ibegin(0:ndivs-1), iend(0:ndivs-1)
308 logical :: mask(0:ndivs-1)
309 integer :: halosz, halobegin, haloend
310 integer :: errunit
311
312 if( .NOT.module_is_initialized )call mpp_error( fatal, &
313 & 'MPP_DEFINE_DOMAINS1D: You must first call mpp_domains_init.' )
314 if(size(global_indices(:)) .NE. 2) call mpp_error(fatal,"mpp_define_domains1D: size of global_indices should be 2")
315 !get global indices
316 isg = global_indices(1)
317 ieg = global_indices(2)
318 if( ndivs.GT.ieg-isg+1 )call mpp_error( fatal, &
319 & 'MPP_DEFINE_DOMAINS1D: more divisions requested than rows available.' )
320 !get the list of PEs on which to assign domains; if pelist is absent use 0..npes-1
321 if( PRESENT(pelist) )then
322 if( .NOT.any(pelist.EQ.mpp_pe()) )then
323 errunit = stderr()
324 write( errunit,* )'pe=', mpp_pe(), ' pelist=', pelist
325 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: pe must be in pelist.' )
326 end if
327 allocate( pes(0:size(pelist(:))-1) )
328 pes(:) = pelist(:)
329 else
330 allocate( pes(0:mpp_npes()-1) )
331 call mpp_get_current_pelist(pes)
332! pes(:) = (/ (i,i=0,mpp_npes()-1) /)
333 end if
334
335 !get number of real domains: 1 mask domain per PE in pes
336 mask = .true. !default mask
337 if( PRESENT(maskmap) )then
338 if( size(maskmap(:)).NE.ndivs ) &
339 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: maskmap array size must equal number of domain divisions.' )
340 mask(:) = maskmap(:)
341 end if
342 if( count(mask).NE.size(pes(:)) ) &
343 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS1D: number of TRUEs in maskmap array must match PE count.' )
344
345 !get halosize
346 halosz = 0
347 if( PRESENT(halo) ) then
348 halosz = halo
349 !--- if halo is present, begin_halo and end_halo should not present
350 if(present(begin_halo) .OR. present(end_halo) ) call mpp_error(fatal, &
351 "mpp_domains_define.inc: when halo is present, begin_halo and end_halo should not present")
352 end if
353 halobegin = halosz; haloend = halosz
354 if(present(begin_halo)) halobegin = begin_halo
355 if(present(end_halo)) haloend = end_halo
356 halosz = max(halobegin, haloend)
357 !get flags
358 compute_domain_is_global = .false.
359 data_domain_is_global = .false.
360 domain%cyclic = .false.
361 domain%goffset = 1
362 domain%loffset = 1
363 if( PRESENT(flags) )then
364 !NEW: obsolete flag global_compute_domain, since ndivs is non-optional and you cannot
365 !have global compute and ndivs.NE.1
366 compute_domain_is_global = ndivs.EQ.1
367 !if compute domain is global, data domain must also be
368 data_domain_is_global = btest(flags,global) .OR. compute_domain_is_global
369 domain%cyclic = btest(flags,cyclic) .AND. halosz.NE.0
370 if(btest(flags,cyclic)) domain%goffset = 0
371 end if
372
373 !set up links list
374 allocate( domain%list(0:ndivs-1) )
375
376 !set global domain
377 domain%list(:)%global%begin = isg
378 domain%list(:)%global%end = ieg
379 domain%list(:)%global%size = ieg-isg+1
380 domain%list(:)%global%max_size = ieg-isg+1
381 domain%list(:)%global%is_global = .true. !always
382
383 !get compute domain
384 if( compute_domain_is_global )then
385 domain%list(:)%compute%begin = isg
386 domain%list(:)%compute%end = ieg
387 domain%list(:)%compute%is_global = .true.
388 domain%list(:)%pe = pes(:)
389 domain%pos = 0
390 else
391 domain%list(:)%compute%is_global = .false.
392 n = 0
393 call mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
394 do ndiv=0,ndivs-1
395 domain%list(ndiv)%compute%begin = ibegin(ndiv)
396 domain%list(ndiv)%compute%end = iend(ndiv)
397 if( mask(ndiv) )then
398 domain%list(ndiv)%pe = pes(n)
399 if( mpp_pe().EQ.pes(n) )domain%pos = ndiv
400 n = n + 1
401 else
402 domain%list(ndiv)%pe = null_pe
403 end if
404 end do
405 end if
406
407 domain%list(:)%compute%size = domain%list(:)%compute%end - domain%list(:)%compute%begin + 1
408
409 !get data domain
410 !data domain is at least equal to compute domain
411 domain%list(:)%domain_data%begin = domain%list(:)%compute%begin
412 domain%list(:)%domain_data%end = domain%list(:)%compute%end
413 domain%list(:)%domain_data%is_global = .false.
414 !apply global flags
415 if( data_domain_is_global )then
416 domain%list(:)%domain_data%begin = isg
417 domain%list(:)%domain_data%end = ieg
418 domain%list(:)%domain_data%is_global = .true.
419 end if
420 !apply margins
421 domain%list(:)%domain_data%begin = domain%list(:)%domain_data%begin - halobegin
422 domain%list(:)%domain_data%end = domain%list(:)%domain_data%end + haloend
423 domain%list(:)%domain_data%size = domain%list(:)%domain_data%end - domain%list(:)%domain_data%begin + 1
424
425 !--- define memory domain, if memory_size is not present or memory size is 0, memory domain size
426 !--- will be the same as data domain size. if momory_size is present, memory_size should greater than
427 !--- or equal to data size. The begin of memory domain will be always the same as data domain.
428 domain%list(:)%memory%begin = domain%list(:)%domain_data%begin
429 domain%list(:)%memory%end = domain%list(:)%domain_data%end
430 if( present(memory_size) ) then
431 if(memory_size > 0) then
432 if( domain%list(domain%pos)%domain_data%size > memory_size ) call mpp_error(fatal, &
433 "mpp_domains_define.inc: data domain size is larger than memory domain size on this pe")
434 domain%list(:)%memory%end = domain%list(:)%memory%begin + memory_size - 1
435 end if
436 end if
437 domain%list(:)%memory%size = domain%list(:)%memory%end - domain%list(:)%memory%begin + 1
438 domain%list(:)%memory%is_global = domain%list(:)%domain_data%is_global
439
440 domain%compute = domain%list(domain%pos)%compute
441 domain%domain_data = domain%list(domain%pos)%domain_data
442 domain%global = domain%list(domain%pos)%global
443 domain%memory = domain%list(domain%pos)%memory
444 domain%compute%max_size = maxval( domain%list(:)%compute%size )
445 domain%domain_data%max_size = maxval( domain%list(:)%domain_data%size )
446 domain%global%max_size = domain%global%size
447 domain%memory%max_size = domain%memory%size
448
449 !PV786667: the deallocate stmts can be removed when fixed (7.3.1.3m)
450 deallocate( pes )
451 return
452
453 end subroutine mpp_define_domains1d
454
455 !################################################################################
456 !> Define the layout for IO pe's for the given domain
457 subroutine mpp_define_io_domain(domain, io_layout)
458 type(domain2d), intent(inout) :: domain !< Input 2D domain
459 integer, intent(in ) :: io_layout(2) !< 2 value io pe layout to define
460 integer :: layout(2)
461 integer :: npes_in_group
462 type(domain2d), pointer :: io_domain=>null()
463 integer :: i, j, n, m
464 integer :: ipos, jpos, igroup, jgroup
465 integer :: ipos_beg, ipos_end, jpos_beg, jpos_end
466 integer :: whalo, ehalo, shalo, nhalo
467 integer :: npes_x, npes_y, ndivx, ndivy
468 integer, allocatable :: posarray(:,:)
469
470 if(io_layout(1) * io_layout(2) .LE. 0) then
471 call mpp_error(note, &
472 "mpp_domains_define.inc(mpp_define_io_domain): io domain will not be defined for "//trim(domain%name)// &
473 " when one or both entry of io_layout is not positive")
474 return
475 endif
476
477 layout(1) = size(domain%x(1)%list(:))
478 layout(2) = size(domain%y(1)%list(:))
479
480 if(ASSOCIATED(domain%io_domain)) call mpp_error(fatal, &
481 "mpp_domains_define.inc(mpp_define_io_domain): io_domain is already defined")
482
483 if(mod(layout(1), io_layout(1)) .NE. 0) call mpp_error(fatal, &
484 "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
485 & " domain layout(1) must be divided by io_layout(1)")
486 if(mod(layout(2), io_layout(2)) .NE. 0) call mpp_error(fatal, &
487 "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
488 & " domain layout(2) must be divided by io_layout(2)")
489 if(size(domain%x(:)) > 1) call mpp_error(fatal, &
490 "mpp_domains_define.inc(mpp_define_io_domain): "//trim(domain%name)// &
491 ": multiple tile per pe is not supported yet for this routine")
492
493 if (associated(domain%io_domain)) deallocate(domain%io_domain) !< Check if associated
494 allocate(domain%io_domain)
495 domain%io_layout = io_layout
496 io_domain => domain%io_domain
497 ! Find how many processors are in the group with the consideration that some of the region maybe masked out.
498 npes_x = layout(1)/io_layout(1)
499 npes_y = layout(2)/io_layout(2)
500 ipos = mod(domain%x(1)%pos, npes_x)
501 jpos = mod(domain%y(1)%pos, npes_y)
502 igroup = domain%x(1)%pos/npes_x
503 jgroup = domain%y(1)%pos/npes_y
504 ipos_beg = igroup*npes_x; ipos_end = ipos_beg + npes_x - 1
505 jpos_beg = jgroup*npes_y; jpos_end = jpos_beg + npes_y - 1
506 npes_in_group = 0
507 do j = jpos_beg, jpos_end
508 do i = ipos_beg, ipos_end
509 if(domain%pearray(i,j) .NE. null_pe) npes_in_group = npes_in_group+1
510 enddo
511 enddo
512
513 io_domain%whalo = domain%whalo
514 io_domain%ehalo = domain%ehalo
515 io_domain%shalo = domain%shalo
516 io_domain%nhalo = domain%nhalo
517 io_domain%ntiles = 1
518 io_domain%pe = domain%pe
519 io_domain%symmetry = domain%symmetry
520 if (associated(io_domain%list)) deallocate(io_domain%list) !< Check if associated
521 allocate(io_domain%list(0:npes_in_group-1))
522 do i = 0, npes_in_group-1
523 allocate( io_domain%list(i)%x(1), io_domain%list(i)%y(1), io_domain%list(i)%tile_id(1) )
524 enddo
525
526 ndivx = size(domain%pearray,1)
527 ndivy = size(domain%pearray,2)
528 allocate(posarray(0:ndivx-1, 0:ndivy-1))
529 n = domain%tile_root_pe - mpp_root_pe()
530 posarray = -1
531 do j = 0,ndivy-1
532 do i = 0,ndivx-1
533 if( domain%pearray(i,j) == null_pe) cycle
534 posarray(i,j) = n
535 n = n + 1
536 enddo
537 enddo
538
539 n = 0
540 do j = jpos_beg, jpos_end
541 do i = ipos_beg, ipos_end
542 if( domain%pearray(i,j) == null_pe) cycle
543 io_domain%list(n)%pe = domain%pearray(i,j)
544 m = posarray(i,j)
545 io_domain%list(n)%x(1)%compute = domain%list(m)%x(1)%compute
546 io_domain%list(n)%y(1)%compute = domain%list(m)%y(1)%compute
547 igroup = domain%list(m)%x(1)%pos/npes_x
548 jgroup = domain%list(m)%y(1)%pos/npes_y
549 io_domain%list(n)%tile_id(1) = jgroup*io_layout(1) + igroup
550 n = n + 1
551 enddo
552 enddo
553 deallocate(posarray)
554
555 if (associated(io_domain%x)) deallocate(io_domain%x) !< Check if associated
556 if (associated(io_domain%y)) deallocate(io_domain%y) !< Check if associated
557 if (associated(io_domain%tile_id)) deallocate(io_domain%tile_id) !< Check if associated
558 allocate(io_domain%x(1), io_domain%y(1), io_domain%tile_id(1) )
559 allocate(io_domain%x(1)%list(0:npes_x-1), io_domain%y(1)%list(0:npes_y-1) )
560 n = -1
561 do j = jpos_beg, jpos_beg+jpos
562 do i = ipos_beg, ipos_beg+ipos
563 if(domain%pearray(i,j) .NE. null_pe) n = n + 1
564 enddo
565 enddo
566 io_domain%pos = n
567 io_domain%x(1)%compute = domain%x(1)%compute
568 io_domain%x(1)%domain_data = domain%x(1)%domain_data
569 io_domain%x(1)%memory = domain%x(1)%memory
570 io_domain%y(1)%compute = domain%y(1)%compute
571 io_domain%y(1)%domain_data = domain%y(1)%domain_data
572 io_domain%y(1)%memory = domain%y(1)%memory
573 io_domain%x(1)%global%begin = domain%x(1)%list(ipos_beg)%compute%begin
574 io_domain%x(1)%global%end = domain%x(1)%list(ipos_end)%compute%end
575 io_domain%x(1)%global%size = io_domain%x(1)%global%end - io_domain%x(1)%global%begin + 1
576 io_domain%x(1)%global%max_size = io_domain%x(1)%global%size
577 io_domain%y(1)%global%begin = domain%y(1)%list(jpos_beg)%compute%begin
578 io_domain%y(1)%global%end = domain%y(1)%list(jpos_end)%compute%end
579 io_domain%y(1)%global%size = io_domain%y(1)%global%end - io_domain%y(1)%global%begin + 1
580 io_domain%y(1)%global%max_size = io_domain%y(1)%global%size
581 io_domain%x(1)%pos = ipos
582 io_domain%y(1)%pos = jpos
583 io_domain%tile_id(1) = io_domain%list(n)%tile_id(1)
584 io_domain%tile_root_pe = io_domain%list(0)%pe
585
586 !z1l
587!!$ do j = 0, npes_y - 1
588!!$ n = j*npes_x + ipos
589!!$ io_domain%y(1)%list(j) = io_domain%list(n)%y(1)
590!!$ enddo
591!!$ do i = 0, npes_x - 1
592!!$ n = jpos*npes_x + i
593!!$ io_domain%x(1)%list(i) = io_domain%list(n)%x(1)
594!!$ enddo
595
596 whalo = domain%whalo
597 ehalo = domain%ehalo
598 shalo = domain%shalo
599 nhalo = domain%nhalo
600
601 io_domain=>null()
602
603
604 end subroutine mpp_define_io_domain
605
606 !> Define 2D data and computational domain on global rectilinear cartesian domain
607 !! (isg:ieg,jsg:jeg) and assign them to PEs
608 subroutine mpp_define_domains2d( global_indices, layout, domain, pelist, xflags, yflags, &
609 xhalo, yhalo, xextent, yextent, maskmap, name, symmetry, memory_size, &
610 whalo, ehalo, shalo, nhalo, is_mosaic, tile_count, tile_id, complete, x_cyclic_offset, y_cyclic_offset )
611 integer, intent(in) :: global_indices(:) !<(/ isg, ieg, jsg, jeg /)
612 integer, intent(in) :: layout(:) !< pe layout
613 type(domain2d), intent(inout) :: domain !< 2D domain decomposition to define
614 integer, intent(in), optional :: pelist(0:) !< current pelist to run on
615 integer, intent(in), optional :: xflags, yflags !< directional flag
616 integer, intent(in), optional :: xhalo, yhalo !< halo sizes for x and y indices
617 integer, intent(in), optional :: xextent(0:), yextent(0:)
618 logical, intent(in), optional :: maskmap(0:,0:)
619 character(len=*), intent(in), optional :: name
620 logical, intent(in), optional :: symmetry
621 logical, intent(in), optional :: is_mosaic !< indicate if calling mpp_define_domains
622 !! from mpp_define_mosaic.
623 integer, intent(in), optional :: memory_size(:)
624 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size for West, East,
625 !! South and North direction.
626 !! if whalo and ehalo is not present,
627 !! will take the value of xhalo
628 !! if shalo and nhalo is not present,
629 !! will take the value of yhalo
630 integer, intent(in), optional :: tile_count !< tile number on current pe,
631 !! default value is 1.
632 !! this is for the situation that
633 !! multiple tiles on one processor
634 integer, intent(in), optional :: tile_id !< tile id
635 logical, intent(in), optional :: complete !< true indicate mpp_define_domain
636 !! is completed for mosaic definition.
637 integer, intent(in), optional :: x_cyclic_offset !< offset for x-cyclic boundary condition,
638 !! (0,j) = (ni, mod(j+x_cyclic_offset,nj))
639 !! (ni+1, j)=(1 ,mod(j+nj-x_cyclic_offset,nj))
640 integer, intent(in), optional :: y_cyclic_offset !< offset for y-cyclic boundary condition
641 !!(i,0) = (mod(i+y_cyclic_offset,ni), nj))
642 !!(i,nj+1) =(mod(mod(i+ni-y_cyclic_offset,ni),
643 !! 1) )
644
645 integer :: i, j, m, n, xhalosz, yhalosz, memory_xsize, memory_ysize
646 integer :: whalosz, ehalosz, shalosz, nhalosz
647 integer :: ipos, jpos, pos, tile, nlist, cur_tile_id, cur_comm_id
648 integer :: ndivx, ndivy, isg, ieg, jsg, jeg, ishift, jshift, errunit, logunit
649 integer :: x_offset, y_offset, start_pos, nfold
650 logical :: from_mosaic, is_complete
651 logical :: mask(0:layout(1)-1,0:layout(2)-1)
652 integer, allocatable :: pes(:), pesall(:)
653 integer :: pearray(0:layout(1)-1,0:layout(2)-1)
654 integer :: ibegin(0:layout(1)-1), iend(0:layout(1)-1)
655 integer :: jbegin(0:layout(2)-1), jend(0:layout(2)-1)
656 character(len=8) :: text
657 type(overlapspec), pointer :: check_T => null()
658 integer :: outunit
659 logical :: send(8), recv(8)
660
661 outunit = stdout()
662 if( .NOT.module_is_initialized )call mpp_error( fatal, &
663 & 'MPP_DEFINE_DOMAINS2D: You must first call mpp_domains_init.' )
664 if(PRESENT(name)) then
665 if(len_trim(name) > name_length) call mpp_error(fatal, &
666 "mpp_domains_define.inc(mpp_define_domains2D): the len_trim of optional argument name ="//trim(name)// &
667 " is greater than NAME_LENGTH, change the argument name or increase NAME_LENGTH")
668 domain%name = name
669 endif
670 if(size(global_indices(:)) .NE. 4) call mpp_error(fatal, &
671 "mpp_define_domains2D: size of global_indices should be 4 for "//trim(domain%name) )
672 if(size(layout(:)) .NE. 2) call mpp_error(fatal,"mpp_define_domains2D: size of layout should be 2 for "// &
673 & trim(domain%name) )
674
675 ndivx = layout(1); ndivy = layout(2)
676 isg = global_indices(1); ieg = global_indices(2); jsg = global_indices(3); jeg = global_indices(4)
677
678 from_mosaic = .false.
679 if(present(is_mosaic)) from_mosaic = is_mosaic
680 is_complete = .true.
681 if(present(complete)) is_complete = complete
682 tile = 1
683 if(present(tile_count)) tile = tile_count
684 cur_tile_id = 1
685 if(present(tile_id)) cur_tile_id = tile_id
686
687 cur_comm_id=0
688 if( PRESENT(pelist) )then
689 allocate( pes(0:size(pelist(:))-1) )
690 pes = pelist
691 if(from_mosaic) then
692 allocate( pesall(0:mpp_npes()-1) )
693 call mpp_get_current_pelist(pesall, commid=cur_comm_id)
694 else
695 allocate( pesall(0:size(pes(:))-1) )
696 pesall = pes
697 call mpp_get_current_pelist(pesall, commid=cur_comm_id)
698 end if
699 else
700 allocate( pes(0:mpp_npes()-1) )
701 allocate( pesall(0:mpp_npes()-1) )
702 call mpp_get_current_pelist(pes, commid=cur_comm_id)
703 pesall = pes
704 end if
705
706 !--- at least of one of x_cyclic_offset and y_cyclic_offset must be zero
707 !--- folded boundary condition is not supported when either x_cyclic_offset or y_cyclic_offset is nonzero.
708 !--- Since we only implemented Folded-north boundary condition currently, we only consider y-flags.
709 x_offset = 0; y_offset = 0
710 if(PRESENT(x_cyclic_offset)) x_offset = x_cyclic_offset
711 if(PRESENT(y_cyclic_offset)) y_offset = y_cyclic_offset
712 if(x_offset*y_offset .NE. 0) call mpp_error(fatal, &
713 'MPP_DEFINE_DOMAINS2D: At least one of x_cyclic_offset and y_cyclic_offset must be zero for '// &
714 & trim(domain%name))
715
716 !--- x_cyclic_offset and y_cyclic_offset should no larger than the global grid size.
717 if(abs(x_offset) > jeg-jsg+1) call mpp_error(fatal, &
718 'MPP_DEFINE_DOMAINS2D: absolute value of x_cyclic_offset is greater than jeg-jsg+1 for '//trim(domain%name))
719 if(abs(y_offset) > ieg-isg+1) call mpp_error(fatal, &
720 'MPP_DEFINE_DOMAINS2D: absolute value of y_cyclic_offset is greater than ieg-isg+1 for '//trim(domain%name))
721
722 !--- when there is more than one tile on one processor, all the tile will limited on this processor
723 if( tile > 1 .AND. size(pes(:)) > 1) call mpp_error(fatal, &
724 'MPP_DEFINE_DOMAINS2D: there are more than one tile on this pe, '// &
725 'all the tile should be limited on this pe for '//trim(domain%name))
726
727 !--- the position of current pe is changed due to mosaic, because pes
728 !--- is only part of the pelist in mosaic (pesall). We assume the pe
729 !--- distribution are contious in mosaic.
730 pos = -1
731 do n = 0, size(pesall(:))-1
732 if(pesall(n) == mpp_pe() ) then
733 pos = n
734 exit
735 endif
736 enddo
737 if(pos<0) call mpp_error(fatal, 'MPP_DEFINE_DOMAINS2D: mpp_pe() is not in the pesall list')
738
739 domain%symmetry = .false.
740 if(present(symmetry)) domain%symmetry = symmetry
741 if(domain%symmetry) then
742 ishift = 1; jshift = 1
743 else
744 ishift = 0; jshift = 0
745 end if
746
747 !--- first compute domain decomposition.
748 call mpp_compute_extent(isg, ieg, ndivx, ibegin, iend, xextent)
749 call mpp_compute_extent(jsg, jeg, ndivy, jbegin, jend, yextent)
750
751 xhalosz = 0; yhalosz = 0
752 if(present(xhalo)) xhalosz = xhalo
753 if(present(yhalo)) yhalosz = yhalo
754 whalosz = xhalosz; ehalosz = xhalosz
755 shalosz = yhalosz; nhalosz = yhalosz
756 if(present(whalo)) whalosz = whalo
757 if(present(ehalo)) ehalosz = ehalo
758 if(present(shalo)) shalosz = shalo
759 if(present(nhalo)) nhalosz = nhalo
760
761 !--- configure maskmap
762 mask = .true.
763 if( PRESENT(maskmap) )then
764 if( size(maskmap,1).NE.ndivx .OR. size(maskmap,2).NE.ndivy ) &
765 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS2D: maskmap array does not match layout for '// &
766 & trim(domain%name) )
767 mask(:,:) = maskmap(:,:)
768 end if
769 !number of unmask domains in layout must equal number of PEs assigned
770 n = count(mask)
771 if( n.NE.size(pes(:)) )then
772 write( text,'(i8)' )n
773 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS2D: incorrect number of PEs assigned for ' // &
774 'this layout and maskmap. Use '//text//' PEs for this domain decomposition for '//trim(domain%name) )
775 end if
776
777 memory_xsize = 0; memory_ysize = 0
778 if(present(memory_size)) then
779 if(size(memory_size(:)) .NE. 2) call mpp_error(fatal, &
780 "mpp_define_domains2D: size of memory_size should be 2 for "//trim(domain%name))
781 memory_xsize = memory_size(1)
782 memory_ysize = memory_size(2)
783 end if
784
785 !--- set up domain%list.
786 !--- set up 2-D domain decomposition for T, E, C, N and computing overlapping
787 !--- when current tile is the last tile in the mosaic.
788 nlist = size(pesall(:))
789 if( .NOT. Associated(domain%x) ) then
790 allocate(domain%tileList(1))
791 domain%tileList(1)%xbegin = global_indices(1)
792 domain%tileList(1)%xend = global_indices(2)
793 domain%tileList(1)%ybegin = global_indices(3)
794 domain%tileList(1)%yend = global_indices(4)
795 allocate(domain%x(1), domain%y(1) )
796 allocate(domain%tile_id(1))
797 allocate(domain%tile_id_all(1))
798 domain%tile_id = cur_tile_id
799 domain%tile_id_all = cur_tile_id
800 domain%tile_comm_id = cur_comm_id
801 domain%ntiles = 1
802 domain%max_ntile_pe = 1
803 domain%ncontacts = 0
804 domain%rotated_ninety = .false.
805 allocate( domain%list(0:nlist-1) )
806 do i = 0, nlist-1
807 allocate( domain%list(i)%x(1), domain%list(i)%y(1), domain%list(i)%tile_id(1))
808 end do
809 end if
810
811 domain%initialized = .true.
812
813 start_pos = 0
814 do n = 0, nlist-1
815 if(pesall(n) == pes(0)) then
816 start_pos = n
817 exit
818 endif
819 enddo
820
821 !place on PE array; need flag to assign them to j first and then i
822 pearray(:,:) = null_pe
823 ipos = null_pe; jpos = null_pe
824 n = 0
825 m = start_pos
826 do j = 0,ndivy-1
827 do i = 0,ndivx-1
828 if( mask(i,j) )then
829 pearray(i,j) = pes(n)
830 domain%list(m)%x(tile)%compute%begin = ibegin(i)
831 domain%list(m)%x(tile)%compute%end = iend(i)
832 domain%list(m)%y(tile)%compute%begin = jbegin(j)
833 domain%list(m)%y(tile)%compute%end = jend(j)
834 domain%list(m)%x(tile)%compute%size = domain%list(m)%x(tile)%compute%end &
835 & - domain%list(m)%x(tile)%compute%begin + 1
836 domain%list(m)%y(tile)%compute%size = domain%list(m)%y(tile)%compute%end &
837 & - domain%list(m)%y(tile)%compute%begin + 1
838 domain%list(m)%tile_id(tile) = cur_tile_id
839 domain%list(m)%x(tile)%pos = i
840 domain%list(m)%y(tile)%pos = j
841 domain%list(m)%tile_root_pe = pes(0)
842 domain%list(m)%pe = pesall(m)
843
844 if( pes(n).EQ.mpp_pe() )then
845 ipos = i
846 jpos = j
847 end if
848 n = n + 1
849 m = m + 1
850 end if
851 end do
852 end do
853
854 !Considering mosaic, the following will only be done on the pe in the pelist
855 !when there is only one tile, all the current pe will be in the pelist.
856 if( any(pes == mpp_pe()) ) then
857 domain%io_layout = layout
858 domain%tile_root_pe = pes(0)
859 domain%comm_id = cur_comm_id
860 if( ipos.EQ.null_pe .OR. jpos.EQ.null_pe ) &
861 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS2D: pelist must include this PE for '//trim(domain%name) )
862 if( debug ) then
863 errunit = stderr()
864 write( errunit, * )'pe, tile, ipos, jpos=', mpp_pe(), tile, ipos, jpos, ' pearray(:,jpos)=', &
865 pearray(:,jpos), ' pearray(ipos,:)=', pearray(ipos,:)
866 endif
867
868 !--- when tile is not equal to 1, the layout for that tile always ( 1, 1), so no need for pearray in domain
869 if( tile == 1 ) then
870 if (associated(domain%pearray)) deallocate(domain%pearray) !< Check if allocated
871 allocate( domain%pearray(0:ndivx-1,0:ndivy-1) )
872 domain%pearray = pearray
873 end if
874
875 domain%pe = mpp_pe()
876 domain%pos = pos
877 domain_cnt = domain_cnt + int(1,kind=i8_kind)
878 domain%id = domain_cnt*domain_id_base ! Must be i8_kind arithmetic
879
880 !do domain decomposition using 1D versions in X and Y,
881 call mpp_define_domains( global_indices(1:2), ndivx, domain%x(tile), &
882 pack(pearray(:,jpos),mask(:,jpos)), xflags, xhalo, xextent, mask(:,jpos), memory_xsize, whalo, ehalo )
883 call mpp_define_domains( global_indices(3:4), ndivy, domain%y(tile), &
884 pack(pearray(ipos,:),mask(ipos,:)), yflags, yhalo, yextent, mask(ipos,:), memory_ysize, shalo, nhalo )
885 if( domain%x(tile)%list(ipos)%pe.NE.domain%y(tile)%list(jpos)%pe ) &
886 call mpp_error( fatal, .NE.'MPP_DEFINE_DOMAINS2D: domain%x%list(ipos)%pedomain%y%list(jpos)%pe.' )
887
888 !--- when x_cyclic_offset or y_cyclic_offset is set, no cross domain is allowed
889 if(x_offset .NE. 0 .OR. y_offset .NE. 0) then
890 if(whalosz .GT. domain%x(tile)%compute%size .OR. ehalosz .GT. domain%x(tile)%compute%size ) &
891 call mpp_error(fatal, "mpp_define_domains_2d: when x_cyclic_offset/y_cyclic_offset is set, "// &
892 "whalo and ehalo must be no larger than the x-direction computation domain size")
893 if(shalosz .GT. domain%y(tile)%compute%size .OR. nhalosz .GT. domain%y(tile)%compute%size ) &
894 call mpp_error(fatal, "mpp_define_domains_2d: when x_cyclic_offset/y_cyclic_offset is set, "// &
895 "shalo and nhalo must be no larger than the y-direction computation domain size")
896 endif
897
898 !--- restrict the halo size is no larger than global domain size.
899 if(whalosz .GT. domain%x(tile)%global%size) &
900 call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: whalo is greather global domain size")
901 if(ehalosz .GT. domain%x(tile)%global%size) &
902 call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: ehalo is greather global domain size")
903 if(shalosz .GT. domain%x(tile)%global%size) &
904 call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: shalo is greather global domain size")
905 if(nhalosz .GT. domain%x(tile)%global%size) &
906 call mpp_error(fatal, "MPP_DEFINE_DOMAINS2D: nhalo is greather global domain size")
907
908 !set up fold, when the boundary is folded, there is only one tile.
909 domain%fold = 0
910 nfold = 0
911 if( PRESENT(xflags) )then
912 if( btest(xflags,west) ) then
913 !--- make sure no cross-domain in y-direction
914 if(domain%x(tile)%domain_data%begin .LE. domain%x(tile)%global%begin .AND. &
915 domain%x(tile)%compute%begin > domain%x(tile)%global%begin ) then
916 call mpp_error(fatal, &
917 'MPP_DEFINE_DOMAINS: the domain could not be crossed when west is folded')
918 endif
919 if( domain%x(tile)%cyclic )call mpp_error( fatal, &
920 'MPP_DEFINE_DOMAINS: an axis cannot be both folded west and cyclic for '//trim(domain%name) )
921 domain%fold = domain%fold + fold_west_edge
922 nfold = nfold+1
923 endif
924 if( btest(xflags,east) ) then
925 !--- make sure no cross-domain in y-direction
926 if(domain%x(tile)%domain_data%end .GE. domain%x(tile)%global%end .AND. &
927 domain%x(tile)%compute%end < domain%x(tile)%global%end ) then
928 call mpp_error(fatal, &
929 'MPP_DEFINE_DOMAINS: the domain could not be crossed when north is folded')
930 endif
931 if( domain%x(tile)%cyclic )call mpp_error( fatal, &
932 'MPP_DEFINE_DOMAINS: an axis cannot be both folded east and cyclic for '//trim(domain%name) )
933 domain%fold = domain%fold + fold_east_edge
934 nfold = nfold+1
935 endif
936 endif
937 if( PRESENT(yflags) )then
938 if( btest(yflags,south) ) then
939 !--- make sure no cross-domain in y-direction
940 if(domain%y(tile)%domain_data%begin .LE. domain%y(tile)%global%begin .AND. &
941 domain%y(tile)%compute%begin > domain%y(tile)%global%begin ) then
942 call mpp_error(fatal, &
943 'MPP_DEFINE_DOMAINS: the domain could not be crossed when south is folded')
944 endif
945 if( domain%y(tile)%cyclic )call mpp_error( fatal, &
946 'MPP_DEFINE_DOMAINS: an axis cannot be both folded north and cyclic for '//trim(domain%name))
947 domain%fold = domain%fold + fold_south_edge
948 nfold = nfold+1
949 endif
950 if( btest(yflags,north) ) then
951 !--- when the halo size is big and halo region is crossing neighbor domain, we
952 !--- restrict the halo size is less than half of the global size.
953 if(whalosz .GT. domain%x(tile)%compute%size .AND. whalosz .GE. domain%x(tile)%global%size/2 ) &
954 call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, whalo compute domain size "// &
955 .GE."and whalo half of global domain size")
956 if(ehalosz .GT. domain%x(tile)%compute%size .AND. ehalosz .GE. domain%x(tile)%global%size/2 ) &
957 call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, ehalo is compute domain size "// &
958 .GE."and ehalo half of global domain size")
959 if(shalosz .GT. domain%y(tile)%compute%size .AND. shalosz .GE. domain%x(tile)%global%size/2 ) &
960 call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, shalo compute domain size "// &
961 .GE."and shalo half of global domain size")
962 if(nhalosz .GT. domain%y(tile)%compute%size .AND. nhalosz .GE. domain%x(tile)%global%size/2 ) &
963 call mpp_error(fatal, .GT."MPP_DEFINE_DOMAINS2D: north is folded, nhalo compute domain size "// &
964 .GE."and nhalo half of global domain size")
965
966
967 if( domain%y(tile)%cyclic )call mpp_error( fatal, &
968 'MPP_DEFINE_DOMAINS: an axis cannot be both folded south and cyclic for '//trim(domain%name) )
969 domain%fold = domain%fold + fold_north_edge
970 nfold = nfold+1
971 endif
972 endif
973 if(nfold > 1) call mpp_error(fatal, &
974 'MPP_DEFINE_DOMAINS2D: number of folded edge is greater than 1 for '//trim(domain%name) )
975
976 if(nfold == 1) then
977 if( x_offset .NE. 0 .OR. y_offset .NE. 0) call mpp_error(fatal, &
978 'MPP_DEFINE_DOMAINS2D: For the foled_north/folded_south/fold_east/folded_west boundary condition, '//&
979 'x_cyclic_offset and y_cyclic_offset must be zero for '//trim(domain%name))
980 endif
981 if( btest(domain%fold,south) .OR. btest(domain%fold,north) )then
982 if( domain%y(tile)%cyclic )call mpp_error( fatal, &
983 'MPP_DEFINE_DOMAINS: an axis cannot be both folded and cyclic for '//trim(domain%name) )
984 if( modulo(domain%x(tile)%global%size,2).NE.0 ) &
985 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: number of points in X must be even ' // &
986 'when there is a fold in Y for '//trim(domain%name) )
987 !check if folded domain boundaries line up in X: compute domains lining up is a sufficient
988 !condition for symmetry
989 n = ndivx - 1
990 do i = 0,n/2
991 if( domain%x(tile)%list(i)%compute%size.NE.domain%x(tile)%list(n-i)%compute%size ) &
992 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: Folded domain boundaries ' // &
993 'must line up (mirror-symmetric extents) for '//trim(domain%name) )
994 end do
995 end if
996 if( btest(domain%fold,west) .OR. btest(domain%fold,east) )then
997 if( domain%x(tile)%cyclic )call mpp_error( fatal, &
998 'MPP_DEFINE_DOMAINS: an axis cannot be both folded and cyclic for '//trim(domain%name) )
999 if( modulo(domain%y(tile)%global%size,2).NE.0 ) &
1000 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: number of points in Y must be even '//&
1001 'when there is a fold in X for '//trim(domain%name) )
1002 !check if folded domain boundaries line up in Y: compute domains lining up is a sufficient
1003 !condition for symmetry
1004 n = ndivy - 1
1005 do i = 0,n/2
1006 if( domain%y(tile)%list(i)%compute%size.NE.domain%y(tile)%list(n-i)%compute%size ) &
1007 call mpp_error( fatal, 'MPP_DEFINE_DOMAINS: Folded domain boundaries must '//&
1008 'line up (mirror-symmetric extents) for '//trim(domain%name) )
1009 end do
1010 end if
1011
1012 !set up domain%list
1013 if( mpp_pe().EQ.pes(0) .AND. PRESENT(name) )then
1014 logunit = stdlog()
1015 write( logunit, '(/a,i5,a,i5)' )trim(name)//' domain decomposition: ', ndivx, ' X', ndivy
1016 write( logunit, '(3x,a)' )'pe, is, ie, js, je, isd, ied, jsd, jed'
1017 end if
1018 end if ! if( ANY(pes == mpp_pe()) )
1019
1020 if(is_complete) then
1021 domain%whalo = whalosz; domain%ehalo = ehalosz
1022 domain%shalo = shalosz; domain%nhalo = nhalosz
1023 if (associated(domain%update_T)) deallocate(domain%update_T) !< Check if associated
1024 if (associated(domain%update_E)) deallocate(domain%update_E) !< Check if associated
1025 if (associated(domain%update_C)) deallocate(domain%update_C) !< Check if associated
1026 if (associated(domain%update_N)) deallocate(domain%update_N) !< Check if associated
1027 allocate(domain%update_T, domain%update_E, domain%update_C, domain%update_N)
1028 domain%update_T%next => null()
1029 domain%update_E%next => null()
1030 domain%update_C%next => null()
1031 domain%update_N%next => null()
1032 if (associated(domain%check_E)) deallocate(domain%check_E) !< Check if associated
1033 if (associated(domain%check_C)) deallocate(domain%check_C) !< Check if associated
1034 if (associated(domain%check_N)) deallocate(domain%check_N) !< Check if associated
1035 allocate(domain%check_E, domain%check_C, domain%check_N )
1036 domain%update_T%nsend = 0
1037 domain%update_T%nrecv = 0
1038 domain%update_C%nsend = 0
1039 domain%update_C%nrecv = 0
1040 domain%update_E%nsend = 0
1041 domain%update_E%nrecv = 0
1042 domain%update_N%nsend = 0
1043 domain%update_N%nrecv = 0
1044
1045 if( btest(domain%fold,south) ) then
1046 call compute_overlaps_fold_south(domain, center, 0, 0)
1047 call compute_overlaps_fold_south(domain, corner, ishift, jshift)
1048 call compute_overlaps_fold_south(domain, east, ishift, 0)
1049 call compute_overlaps_fold_south(domain, north, 0, jshift)
1050 else if( btest(domain%fold,west) ) then
1051 call compute_overlaps_fold_west(domain, center, 0, 0)
1052 call compute_overlaps_fold_west(domain, corner, ishift, jshift)
1053 call compute_overlaps_fold_west(domain, east, ishift, 0)
1054 call compute_overlaps_fold_west(domain, north, 0, jshift)
1055 else if( btest(domain%fold,east) ) then
1056 call compute_overlaps_fold_east(domain, center, 0, 0)
1057 call compute_overlaps_fold_east(domain, corner, ishift, jshift)
1058 call compute_overlaps_fold_east(domain, east, ishift, 0)
1059 call compute_overlaps_fold_east(domain, north, 0, jshift)
1060 else
1061 call compute_overlaps(domain, center, domain%update_T, check_t, 0, 0, x_offset, y_offset, &
1062 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1063 call compute_overlaps(domain, corner, domain%update_C, domain%check_C, ishift, jshift, x_offset, y_offset, &
1064 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1065 call compute_overlaps(domain, east, domain%update_E, domain%check_E, ishift, 0, x_offset, y_offset, &
1066 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1067 call compute_overlaps(domain, north, domain%update_N, domain%check_N, 0, jshift, x_offset, y_offset, &
1068 domain%whalo, domain%ehalo, domain%shalo, domain%nhalo)
1069 endif
1070 call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_domains")
1071 call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_domains")
1072 call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_domains")
1073 call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_domains")
1074
1075
1076 !--- when ncontacts is nonzero, set_check_overlap will be called in mpp_define
1077 if(domain%symmetry .AND. (domain%ncontacts == 0 .OR. domain%ntiles == 1) ) then
1078 call set_check_overlap( domain, corner )
1079 call set_check_overlap( domain, east )
1080 call set_check_overlap( domain, north )
1081 if (associated(domain%bound_E)) deallocate(domain%bound_E) !< Check if associated
1082 if (associated(domain%bound_C)) deallocate(domain%bound_C) !< Check if associated
1083 if (associated(domain%bound_N)) deallocate(domain%bound_N) !< Check if associated
1084 allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1085 call set_bound_overlap( domain, corner )
1086 call set_bound_overlap( domain, east )
1087 call set_bound_overlap( domain, north )
1088 end if
1089 call set_domain_comm_inf(domain%update_T)
1090 call set_domain_comm_inf(domain%update_E)
1091 call set_domain_comm_inf(domain%update_C)
1092 call set_domain_comm_inf(domain%update_N)
1093 end if
1094
1095 !--- check the send and recv size are matching.
1096 !--- or ntiles>1 mosaic,
1097 !--- the check will be done in mpp_define_mosaic
1098 if(debug_message_passing .and. (domain%ncontacts == 0 .OR. domain%ntiles == 1) ) then
1099 send = .true.
1100 recv = .true.
1101 call check_message_size(domain, domain%update_T, send, recv, 'T')
1102 call check_message_size(domain, domain%update_E, send, recv, 'E')
1103 call check_message_size(domain, domain%update_C, send, recv, 'C')
1104 call check_message_size(domain, domain%update_N, send, recv, 'N')
1105 endif
1106
1107
1108 !print out decomposition, this didn't consider maskmap.
1109 if( mpp_pe() .EQ. pes(0) .AND. PRESENT(name) )then
1110 write(*,*) trim(name)//' domain decomposition'
1111 write(*,'(a,i4,a,i4,a,i4,a,i4)')'whalo = ', whalosz, ", ehalo = ", ehalosz, ", shalo = ", shalosz, &
1112 & ", nhalo = ", nhalosz
1113 write (*,110) (domain%x(1)%list(i)%compute%size, i= 0, layout(1)-1)
1114 write (*,120) (domain%y(1)%list(i)%compute%size, i= 0, layout(2)-1)
1115110 format (' X-AXIS = ',24i4,/,(11x,24i4))
1116120 format (' Y-AXIS = ',24i4,/,(11x,24i4))
1117 endif
1118
1119 deallocate( pes, pesall)
1120
1121
1122 return
1123end subroutine mpp_define_domains2d
1124
1125
1126!#####################################################################
1127subroutine 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
1185end subroutine check_message_size
1186
1187 !#####################################################################
1188!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1189! !
1190! MPP_define_mosaic: define mosaic domain !
1191! NOTE: xflags and yflags is not in mpp_define_mosaic, because such relation !
1192! are already defined in the mosaic relation. !
1193! !
1194!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1195!??? do we need optional argument xextent and yextent
1196!??? how to specify pelist, we may use two dimensional variable pelist to represent.
1197!z1l: We assume the tilelist are in always limited to 1, 2, ... num_tile. If we want
1198! to remove this limitation, we need to add one more argument tilelist.
1199
1200 !> Defines a domain for mosaic tile grids
1201 subroutine mpp_define_mosaic( global_indices, layout, domain, num_tile, num_contact, tile1, tile2, &
1202 istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, pe_start, &
1203 pe_end, pelist, whalo, ehalo, shalo, nhalo, xextent, yextent, &
1204 maskmap, name, memory_size, symmetry, xflags, yflags, tile_id )
1205 integer, intent(in) :: global_indices(:,:) !>The size of first indice is 4,
1206 !! (/ isg, ieg, jsg, jeg /)
1207 !!The size of second indice
1208 !!is number of tiles in mosaic.
1209 integer, intent(in) :: layout(:,:)
1210 type(domain2d), intent(inout) :: domain
1211 integer, intent(in) :: num_tile !< number of tiles in the mosaic
1212 integer, intent(in) :: num_contact !< number of contact region between tiles.
1213 integer, intent(in) :: tile1(:), tile2(:) !< tile number
1214 integer, intent(in) :: istart1(:), iend1(:) !< i-index in tile_1 of contact region
1215 integer, intent(in) :: jstart1(:), jend1(:) !< j-index in tile_1 of contact region
1216 integer, intent(in) :: istart2(:), iend2(:) !< i-index in tile_2 of contact region
1217 integer, intent(in) :: jstart2(:), jend2(:) !< j-index in tile_2 of contact region
1218 integer, intent(in) :: pe_start(:) !< start pe of the pelist used in each tile
1219 integer, intent(in) :: pe_end(:) !< end pe of the pelist used in each tile
1220 integer, intent(in), optional :: pelist(:) !< list of processors used in mosaic
1221 integer, intent(in), optional :: whalo, ehalo, shalo, nhalo
1222 integer, intent(in), optional :: xextent(:,:), yextent(:,:)
1223 logical, intent(in), optional :: maskmap(:,:,:)
1224 character(len=*), intent(in), optional :: name
1225 integer, intent(in), optional :: memory_size(2)
1226 logical, intent(in), optional :: symmetry
1227 integer, intent(in), optional :: xflags, yflags
1228 integer, intent(in), optional :: tile_id(:) !< tile_id of each tile in the mosaic
1229
1230 integer :: n, m, ndivx, ndivy, nc, nlist, nt, pos, n1, n2
1231 integer :: whalosz, ehalosz, shalosz, nhalosz, xhalosz, yhalosz, t1, t2, tile
1232 integer :: flags_x, flags_y
1233 logical, allocatable :: mask(:,:)
1234 integer, allocatable :: pes(:), xext(:), yext(:), pelist_tile(:), ntile_per_pe(:), tile_count(:)
1235 integer, allocatable :: tile_id_local(:)
1236 logical :: is_symmetry
1237 integer, allocatable :: align1(:), align2(:), is1(:), ie1(:), js1(:), je1(:), is2(:), ie2(:), js2(:), je2(:)
1238 integer, allocatable :: isgList(:), iegList(:), jsgList(:), jegList(:)
1239 real, allocatable :: refine1(:), refine2(:)
1240 integer :: outunit
1241 logical :: send(8), recv(8)
1242
1243 outunit = stdout()
1244 mosaic_defined = .true.
1245 !--- the size of first indice of global_indices must be 4.
1246 if(size(global_indices, 1) .NE. 4) call mpp_error(fatal, &
1247 'mpp_domains_define.inc: The size of first dimension of global_indices is not 4')
1248 !--- the size of second indice of global_indices must be num_tile
1249 if(size(global_indices, 2) .NE. num_tile) call mpp_error(fatal, &
1250 'mpp_domains_define.inc: The size of second dimension of global_indices is not equal num_tile')
1251 !--- the size of first indice of layout must be 2. The second dimension size of layout must equal num_tile.
1252 if(size(layout, 1) .NE. 2) call mpp_error(fatal, &
1253 'mpp_domains_define.inc: The size of first dimension of layout is not 2')
1254 if(size(layout,2) .NE. num_tile) call mpp_error(fatal, &
1255 'mpp_domains_define.inc: The size of second dimension of layout is not equal num_tile')
1256
1257 !--- setup pelist for the mosaic ---------------------
1258 nlist = mpp_npes()
1259 allocate(pes(0:nlist-1))
1260 if(present(pelist)) then
1261 if( nlist .NE. size(pelist(:))) call mpp_error(fatal, &
1262 'mpp_domains_define.inc: size of pelist is not equal mpp_npes')
1263 pes = pelist
1264 end if
1265 call mpp_get_current_pelist(pes, commid=domain%comm_id)
1266 !--- pelist should be monotonic increasing by 1.
1267 do n = 1, nlist-1
1268 if(pes(n) - pes(n-1) .NE. 1) call mpp_error(fatal, &
1269 'mpp_domains_define.inc: pelist is not monotonic increasing by 1')
1270 end do
1271
1272 is_symmetry = .false.
1273 if(present(symmetry)) is_symmetry = symmetry
1274
1275 if(size(pe_start(:)) .NE. num_tile .OR. size(pe_end(:)) .NE. num_tile ) call mpp_error(fatal, &
1276 'mpp_domains_define.inc: size of pe_start and/or pe_end is not equal num_tile')
1277 !--- make sure pe_start and pe_end is in the pelist.
1278 if( any( pe_start < pes(0) ) ) call mpp_error(fatal, &
1279 & 'mpp_domains_define.inc: not all the pe_start are in the pelist')
1280 if( any( pe_end > pes(nlist-1)) ) call mpp_error(fatal, &
1281 & 'mpp_domains_define.inc: not all the pe_end are in the pelist')
1282
1283 !--- calculate number of tiles on each pe.
1284 allocate( ntile_per_pe(0:nlist-1) )
1285 ntile_per_pe = 0
1286 do n = 1, num_tile
1287 do m = pe_start(n) - mpp_root_pe(), pe_end(n) - mpp_root_pe()
1288 ntile_per_pe(m) = ntile_per_pe(m) + 1
1289 end do
1290 end do
1291 if(any(ntile_per_pe == 0)) call mpp_error(fatal, &
1292 'mpp_domains_define.inc: At least one pe in pelist is not used by any tile in the mosaic')
1293
1294 !--- check the size comformable of xextent and yextent
1295 if( PRESENT(xextent) ) then
1296 if(size(xextent,1) .GT. maxval(layout(1,:)) ) call mpp_error(fatal, &
1297 'mpp_domains_define.inc: size mismatch between xextent and layout')
1298 if(size(xextent,2) .NE. num_tile) call mpp_error(fatal, &
1299 'mpp_domains_define.inc: size of xextent is not eqaul num_tile')
1300 end if
1301 if( PRESENT(yextent) ) then
1302 if(size(yextent,1) .GT. maxval(layout(2,:)) ) call mpp_error(fatal, &
1303 'mpp_domains_define.inc: size mismatch between yextent and layout')
1304 if(size(yextent,2) .NE. num_tile) call mpp_error(fatal, &
1305 'mpp_domains_define.inc: size of yextent is not eqaul num_tile')
1306 end if
1307
1308 !--- check the size comformable of maskmap
1309 !--- since the layout is different between tiles, so the actual size of maskmap for each tile is
1310 !--- not diffrent. When define maskmap for multiple tiles, user can choose the maximum value
1311 !--- of layout of all tiles to the first and second dimension of maskmap.
1312 if(present(maskmap)) then
1313 if(size(maskmap,1) .GT. maxval(layout(1,:)) .or. size(maskmap,2) .GT. maxval(layout(2,:))) &
1314 call mpp_error(fatal, 'mpp_domains_define.inc: size mismatch between maskmap and layout')
1315 if(size(maskmap,3) .NE. num_tile) call mpp_error(fatal, &
1316 'mpp_domains_define.inc: the third dimension of maskmap is not equal num_tile')
1317 end if
1318
1319 if (associated(domain%tileList)) deallocate(domain%tileList) !< Check if associated
1320 allocate(domain%tileList(num_tile))
1321 do n = 1, num_tile
1322 domain%tileList(n)%xbegin = global_indices(1,n)
1323 domain%tileList(n)%xend = global_indices(2,n)
1324 domain%tileList(n)%ybegin = global_indices(3,n)
1325 domain%tileList(n)%yend = global_indices(4,n)
1326 enddo
1327 !--- define some mosaic information in domain type
1328 nt = ntile_per_pe(mpp_pe()-mpp_root_pe())
1329 if (associated(domain%tile_id)) deallocate(domain%tile_id) !< Check if associated
1330 if (associated(domain%x)) deallocate(domain%x) !< Check if associated
1331 if (associated(domain%y)) deallocate(domain%y) !< Check if associated
1332 if (associated(domain%list)) deallocate(domain%list) !< Check if associated
1333 allocate(domain%tile_id(nt), domain%x(nt), domain%y(nt) )
1334 allocate(domain%list(0:nlist-1))
1335
1336 do n = 0, nlist-1
1337 nt = ntile_per_pe(n)
1338 allocate(domain%list(n)%x(nt), domain%list(n)%y(nt), domain%list(n)%tile_id(nt))
1339 end do
1340
1341 pos = 0
1342 pe = mpp_pe()
1343 if( PRESENT(tile_id) ) then
1344 if(size(tile_id(:)) .NE. num_tile) then
1345 call mpp_error(fatal, .NE."mpp_domains_define.inc: size(tile_id) num_tile")
1346 endif
1347 endif
1348 allocate(tile_id_local(num_tile))
1349
1350!These directives are a work-around for a bug in the CCE compiler, which
1351!causes a segmentation fault when the compiler attempts to vectorize a
1352!loop containing an optional argument (when -g is included).
1353
1354!DIR$ NOVECTOR
1355 do n = 1, num_tile
1356 if(PRESENT(tile_id)) then
1357 tile_id_local(n) = tile_id(n)
1358 else
1359 tile_id_local(n) = n
1360 endif
1361 enddo
1362!DIR$ VECTOR
1363
1364 do n = 1, num_tile
1365 if( pe .GE. pe_start(n) .AND. pe .LE. pe_end(n)) then
1366 pos = pos + 1
1367 domain%tile_id(pos) = tile_id_local(n)
1368 end if
1369 end do
1370
1371 if (associated(domain%tile_id_all)) deallocate(domain%tile_id_all) !< Check if associated
1372 allocate(domain%tile_id_all(num_tile))
1373 domain%tile_id_all(:) = tile_id_local(:)
1374
1375 domain%initialized = .true.
1376 domain%rotated_ninety = .false.
1377 domain%ntiles = num_tile
1378 domain%max_ntile_pe = maxval(ntile_per_pe)
1379 domain%ncontacts = num_contact
1380
1381 deallocate(ntile_per_pe)
1382 !---call mpp_define_domain to define domain decomposition for each tile.
1383 allocate(tile_count(pes(0):pes(0)+nlist-1))
1384 tile_count = 0 ! tile number on current pe
1385
1386 domain%tile_comm_id=0
1387 do n = 1, num_tile
1388 allocate(mask(layout(1,n), layout(2,n)))
1389 allocate(pelist_tile(pe_start(n):pe_end(n)) )
1390 tile_count(pe_start(n)) = tile_count(pe_start(n)) + 1
1391 do m = pe_start(n), pe_end(n)
1392 pelist_tile(m) = m
1393 end do
1394 !--- set the tile communicator
1395 if (any(pelist_tile == pe)) then
1396 call mpp_declare_pelist(pelist_tile, commid=domain%tile_comm_id)
1397 endif
1398 mask = .true.
1399 if(present(maskmap)) mask = maskmap(1:layout(1,n), 1:layout(2,n), n)
1400 ndivx = layout(1,n); ndivy = layout(2,n)
1401 allocate(xext(ndivx), yext(ndivy))
1402 xext = 0; yext = 0
1403 if(present(xextent)) xext = xextent(1:ndivx,n)
1404 if(present(yextent)) yext = yextent(1:ndivy,n)
1405 ! when num_tile is one, we assume only folded_north and cyclic_x, cyclic_y boundary condition is the possible
1406 ! z1l: when we decide to support multiple-tile tripolar grid, we will redesign the following part.
1407 if(num_tile == 1) then
1408 flags_x = 0
1409 flags_y = 0
1410 if(PRESENT(xflags)) flags_x = xflags
1411 if(PRESENT(yflags)) flags_y = yflags
1412 do m = 1, num_contact
1413 if(istart1(m) == iend1(m) ) then ! x-direction contact, possible cyclic, folded-west or folded-east
1414 if(istart2(m) .NE. iend2(m) ) call mpp_error(fatal, &
1415 "mpp_domains_define: for one tile mosaic, when istart1=iend1, istart2 must equal iend2")
1416 if(istart1(m) == istart2(m) ) then ! folded west or folded east
1417 if(istart1(m) == global_indices(1,n) ) then
1418 if(.NOT. btest(flags_x,west) ) flags_x = flags_x + fold_west_edge
1419 else if(istart1(m) == global_indices(2,n) ) then
1420 if(.NOT. btest(flags_x,east) ) flags_x = flags_x + fold_east_edge
1421 else
1422 call mpp_error(fatal, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1423 "istart1 should equal global_indices(1) or global_indices(2)")
1424 endif
1425 else
1426 if(.NOT. btest(flags_x,cyclic)) flags_x = flags_x + cyclic_global_domain
1427 endif
1428 else if( jstart1(m) == jend1(m) ) then ! y-direction contact, cyclic, folded-south or folded-north
1429 if(jstart2(m) .NE. jend2(m) ) call mpp_error(fatal, &
1430 "mpp_domains_define: for one tile mosaic, when jstart1=jend1, jstart2 must equal jend2")
1431 if(jstart1(m) == jstart2(m) ) then ! folded south or folded north
1432 if(jstart1(m) == global_indices(3,n) ) then
1433 if(.NOT. btest(flags_y,south) ) flags_y = flags_y + fold_south_edge
1434 else if(jstart1(m) == global_indices(4,n) ) then
1435 if(.NOT. btest(flags_y,north) ) flags_y = flags_y + fold_north_edge
1436 else
1437 call mpp_error(fatal, "mpp_domains_define: when istart1=iend1,jstart1=jend1, "//&
1438 "istart1 should equal global_indices(1) or global_indices(2)")
1439 endif
1440 else
1441 if(.NOT. btest(flags_y,cyclic)) flags_y = flags_y + cyclic_global_domain
1442 end if
1443 else
1444 call mpp_error(fatal, &
1445 "mpp_domains_define: for one tile mosaic, invalid boundary contact")
1446 end if
1447 end do
1448 call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, xflags = flags_x, &
1449 yflags = flags_y, whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, &
1450 xextent=xext, yextent=yext, maskmap=mask, name=name, symmetry=is_symmetry, &
1451 memory_size = memory_size, is_mosaic = .true., tile_id=tile_id_local(n))
1452 else
1453 call mpp_define_domains(global_indices(:,n), layout(:,n), domain, pelist=pelist_tile, &
1454 whalo=whalo, ehalo=ehalo, shalo=shalo, nhalo=nhalo, xextent=xext, yextent=yext, &
1455 maskmap=mask, name=name, symmetry=is_symmetry, memory_size = memory_size, &
1456 is_mosaic = .true., tile_count = tile_count(pe_start(n)), tile_id=tile_id_local(n), &
1457 complete = n==num_tile)
1458 end if
1459 deallocate(mask, xext, yext, pelist_tile)
1460 end do
1461
1462 deallocate(pes, tile_count, tile_id_local)
1463
1464 if(num_contact == 0 .OR. num_tile == 1) return
1465
1466 !--- loop through each contact region and find the contact for each tile ( including alignment )
1467 !--- we assume the tiles list is continuous and starting from 1.
1468 allocate(is1(num_contact), ie1(num_contact), js1(num_contact), je1(num_contact) )
1469 allocate(is2(num_contact), ie2(num_contact), js2(num_contact), je2(num_contact) )
1470 allocate(isglist(num_tile), ieglist(num_tile), jsglist(num_tile), jeglist(num_tile) )
1471 allocate(align1(num_contact), align2(num_contact), refine1(num_contact), refine2(num_contact))
1472 !--- get the global domain for each tile
1473 do n = 1, num_tile
1474 isglist(n) = domain%tileList(n)%xbegin; ieglist(n) = domain%tileList(n)%xend
1475 jsglist(n) = domain%tileList(n)%ybegin; jeglist(n) = domain%tileList(n)%yend
1476 end do
1477
1478 !--- transfer the contact index to domain index.
1479 nc = 0
1480 do n = 1, num_contact
1481 t1 = tile1(n)
1482 t2 = tile2(n)
1483 is1(n) = istart1(n) + isglist(t1) - 1; ie1(n) = iend1(n) + isglist(t1) - 1
1484 js1(n) = jstart1(n) + jsglist(t1) - 1; je1(n) = jend1(n) + jsglist(t1) - 1
1485 is2(n) = istart2(n) + isglist(t2) - 1; ie2(n) = iend2(n) + isglist(t2) - 1
1486 js2(n) = jstart2(n) + jsglist(t2) - 1; je2(n) = jend2(n) + jsglist(t2) - 1
1487 call check_alignment( is1(n), ie1(n), js1(n), je1(n), isglist(t1), ieglist(t1), jsglist(t1), &
1488 & jeglist(t1), align1(n))
1489 call check_alignment( is2(n), ie2(n), js2(n), je2(n), isglist(t2), ieglist(t2), jsglist(t2), &
1490 & jeglist(t2), align2(n))
1491 if( (align1(n) == west .or. align1(n) == east ) .NEQV. (align2(n) == west .or. align2(n) == east ) )&
1492 domain%rotated_ninety=.true.
1493 end do
1494
1495 !--- calculate the refinement ratio between tiles
1496 do n = 1, num_contact
1497 n1 = max(abs(iend1(n) - istart1(n)), abs(jend1(n) - jstart1(n)) ) + 1
1498 n2 = max(abs(iend2(n) - istart2(n)), abs(jend2(n) - jstart2(n)) ) + 1
1499 refine1(n) = real(n2)/n1
1500 refine2(n) = real(n1)/n2
1501 end do
1502
1503 whalosz = 0; ehalosz = 0; shalosz = 0; nhalosz = 0
1504 if(present(whalo)) whalosz = whalo
1505 if(present(ehalo)) ehalosz = ehalo
1506 if(present(shalo)) shalosz = shalo
1507 if(present(nhalo)) nhalosz = nhalo
1508 xhalosz = max(whalosz, ehalosz)
1509 yhalosz = max(shalosz, nhalosz)
1510
1511 !--- computing the overlap for the contact region with halo size xhalosz and yhalosz
1512 call define_contact_point( domain, center, num_contact, tile1, tile2, align1, align2, refine1, refine2, &
1513 is1, ie1, js1, je1, is2, ie2, js2, je2, isglist, ieglist, jsglist, jeglist )
1514
1515 call set_contact_point( domain, corner )
1516 call set_contact_point( domain, east )
1517 call set_contact_point( domain, north )
1518
1519 call set_domain_comm_inf(domain%update_T)
1520 call set_domain_comm_inf(domain%update_E)
1521 call set_domain_comm_inf(domain%update_C)
1522 call set_domain_comm_inf(domain%update_N)
1523
1524
1525 !--- goffset setting is needed for exact global sum
1526 do m = 1, size(domain%tile_id(:))
1527 tile = domain%tile_id(m)
1528 do n = 1, num_contact
1529 if( tile1(n) == tile ) then
1530 if(align1(n) == east ) domain%x(m)%goffset = 0
1531 if(align1(n) == north) domain%y(m)%goffset = 0
1532 end if
1533 if( tile2(n) == tile ) then
1534 if(align2(n) == east ) domain%x(m)%goffset = 0
1535 if(align2(n) == north) domain%y(m)%goffset = 0
1536 end if
1537 end do
1538 end do
1539 call check_overlap_pe_order(domain, domain%update_T, trim(domain%name)//" update_T in mpp_define_mosaic")
1540 call check_overlap_pe_order(domain, domain%update_C, trim(domain%name)//" update_C in mpp_define_mosaic")
1541 call check_overlap_pe_order(domain, domain%update_E, trim(domain%name)//" update_E in mpp_define_mosaic")
1542 call check_overlap_pe_order(domain, domain%update_N, trim(domain%name)//" update_N in mpp_define_mosaic")
1543
1544 !--- set the overlapping for boundary check if domain is symmetry
1545 if(debug_update_level .NE. no_check) then
1546 call set_check_overlap( domain, corner )
1547 call set_check_overlap( domain, east )
1548 call set_check_overlap( domain, north )
1549 endif
1550 if(domain%symmetry) then
1551 if (associated(domain%bound_E)) deallocate(domain%bound_E) !< Check if associated
1552 if (associated(domain%bound_C)) deallocate(domain%bound_C) !< Check if associated
1553 if (associated(domain%bound_N)) deallocate(domain%bound_N) !< Check if associated
1554 allocate(domain%bound_E, domain%bound_C, domain%bound_N )
1555 call set_bound_overlap( domain, corner )
1556 call set_bound_overlap( domain, east )
1557 call set_bound_overlap( domain, north )
1558 call check_overlap_pe_order(domain, domain%bound_C, trim(domain%name)//" bound_C")
1559 call check_overlap_pe_order(domain, domain%bound_E, trim(domain%name)//" bound_E")
1560 call check_overlap_pe_order(domain, domain%bound_N, trim(domain%name)//" bound_N")
1561 end if
1562
1563 !--- check the send and recv size are matching.
1564 !--- currently only check T and C-cell. For ntiles>1 mosaic,
1565 !--- the check will be done in mpp_define_mosaic
1566 if(debug_message_passing) then
1567 send = .true.
1568 recv = .true.
1569 call check_message_size(domain, domain%update_T, send, recv, 'T')
1570 call check_message_size(domain, domain%update_C, send, recv, 'C')
1571 call check_message_size(domain, domain%update_E, send, recv, 'E')
1572 call check_message_size(domain, domain%update_N, send, recv, 'N')
1573 endif
1574
1575
1576 !--- release memory
1577 deallocate(align1, align2, is1, ie1, js1, je1, is2, ie2, js2, je2 )
1578 deallocate(isglist, ieglist, jsglist, jeglist, refine1, refine2 )
1579
1580
1581 end subroutine mpp_define_mosaic
1582
1583!#####################################################################
1584 !> Accessor function for value of mosaic_defined
1585 logical function mpp_mosaic_defined()
1586 mpp_mosaic_defined = mosaic_defined
1587 end function mpp_mosaic_defined
1588!#####################################################################
1589
1590 !> @brief Computes remote domain overlaps
1591 !!
1592 !> Assumes only one in each direction
1593 !! will calculate the overlapping for T,E,C,N-cell seperately.
1594 subroutine compute_overlaps( domain, position, update, check, ishift, jshift, x_cyclic_offset, y_cyclic_offset, &
1595 whalo, ehalo, shalo, nhalo )
1596 type(domain2d), intent(inout) :: domain
1597 type(overlapspec), intent(inout), pointer :: update
1598 type(overlapspec), intent(inout), pointer :: check
1599 integer, intent(in) :: position, ishift, jshift
1600 integer, intent(in) :: x_cyclic_offset, y_cyclic_offset
1601 integer, intent(in) :: whalo, ehalo, shalo, nhalo
1602
1603 integer :: i, m, n, nlist, tMe, tNbr, dir
1604 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
1605 integer :: isg, ieg, jsg, jeg, ioff, joff
1606 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
1607 integer :: ism, iem, jsm, jem
1608 integer :: is2, ie2, js2, je2
1609 integer :: is3, ie3, js3, je3
1610 integer :: isd3, ied3, jsd3, jed3
1611 integer :: isd2, ied2, jsd2, jed2
1612 logical :: folded, need_adjust_1, need_adjust_2, need_adjust_3, folded_north
1613 type(overlap_type) :: overlap
1614 type(overlap_type), pointer :: overlapList(:)=>null()
1615 type(overlap_type), pointer :: checkList(:)=>null()
1616 integer :: nsend, nrecv
1617 integer :: nsend_check, nrecv_check
1618 integer :: iunit
1619 logical :: set_check
1620
1621 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
1622 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
1623 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
1624 if(size(domain%x(:)) > 1) return
1625
1626 !--- if there is no halo, no need to compute overlaps.
1627 if(whalo==0 .AND. ehalo==0 .AND. shalo==0 .AND. nhalo==0) return
1628
1629 !--- when there is only one tile, n will equal to np
1630 nlist = size(domain%list(:))
1631 set_check = .false.
1632 if(ASSOCIATED(check)) set_check = .true.
1633 allocate(overlaplist(maxlist) )
1634 if(set_check) allocate(checklist(maxlist) )
1635
1636 !--- overlap is used to store the overlapping temporarily.
1637 call allocate_update_overlap( overlap, maxoverlap)
1638 !send
1639 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
1640 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
1641 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
1642
1643 update%xbegin = ism; update%xend = iem
1644 update%ybegin = jsm; update%yend = jem
1645 if(set_check) then
1646 check%xbegin = ism; check%xend = iem
1647 check%ybegin = jsm; check%yend = jem
1648 endif
1649 update%whalo = whalo; update%ehalo = ehalo
1650 update%shalo = shalo; update%nhalo = nhalo
1651
1652 ioff = ni - ishift
1653 joff = nj - jshift
1654 middle = (isg+ieg)/2+1
1655 tme = 1; tnbr = 1
1656 folded_north = btest(domain%fold,north)
1657 if( btest(domain%fold,south) .OR. btest(domain%fold,east) .OR. btest(domain%fold,west) ) then
1658 call mpp_error(fatal,"mpp_domains_define.inc(compute_overlaps): folded south, east or west boundary condition "&
1659 &//"is not supported, please use other version of compute_overlaps for "//trim(domain%name))
1660 endif
1661
1662 nsend = 0
1663 nsend_check = 0
1664
1665 do list = 0,nlist-1
1666 m = mod( domain%pos+list, nlist )
1667 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
1668 !to_pe's eastern halo
1669 dir = 1
1670 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
1671 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
1672 !--- to make sure the consistence between pes
1673 if( domain%symmetry .AND. (position == north .OR. position == corner ) &
1674 .AND. ( jsc == je .or. jec == js ) ) then
1675 !--- do nothing, this point will come from other pe
1676 else
1677 !--- when the north face is folded, the east halo point at right side domain will be folded.
1678 !--- the position should be on CORNER or NORTH
1679 if( je == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
1680 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1681 isg, ieg, dir, ishift, position, ioff, middle)
1682 else
1683 if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1684 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1685 isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1686 else
1687 if( ie.GT.ieg ) then
1688 if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
1689 is = is-ioff; ie = ie-ioff
1690 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1691 end if
1692 end if
1693 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1694 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1695 endif
1696 endif
1697 end if
1698
1699 !to_pe's SE halo
1700 dir = 2
1701 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
1702 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1703 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1704 !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
1705 !--- the other part is both are zero.
1706 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1707 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1708 if(je .LT. jsg) then ! js .LT. jsg
1709 if( domain%y(tme)%cyclic ) then
1710 js = js + joff; je = je + joff
1711 endif
1712 else if(js .Lt. jsg) then ! split into two parts
1713 if( domain%y(tme)%cyclic ) then
1714 js2 = js + joff; je2 = jsg-1+joff
1715 js = jsg;
1716 endif
1717 endif
1718 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1719 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1720 if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1721 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1722 else
1723 if( ie.GT.ieg )then
1724 if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
1725 is = is-ioff; ie = ie-ioff
1726 need_adjust_1 = .false.
1727 if(jsg .GT. js) then
1728 if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1729 js = js+joff; je = je+joff
1730 need_adjust_2 = .false.
1731 if(x_cyclic_offset .NE. 0) then
1732 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1733 else if(y_cyclic_offset .NE. 0) then
1734 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1735 end if
1736 end if
1737 else
1738 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
1739 need_adjust_3 = .false.
1740 end if
1741 end if
1742 end if
1743 if( need_adjust_3 .AND. jsg.GT.js )then
1744 if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1745 js = js+joff; je = je+joff
1746 if(need_adjust_1 .AND. ie.LE.ieg) then
1747 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1748 end if
1749 end if
1750 end if
1751 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1752 endif
1753
1754 !to_pe's southern halo
1755 dir = 3
1756 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
1757 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1758 js2 = 0; je2 = -1
1759 if( jsg.GT.je )then ! jsg .GT. js
1760 if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1761 js = js+joff; je = je+joff
1762 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1763 end if
1764 else if (jsg .GT. js) then ! split into two parts
1765 if( domain%y(tme)%cyclic) then
1766 js2 = js + joff; je2 = jsg-1+joff
1767 js = jsg
1768 endif
1769 end if
1770
1771 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1772 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1773 if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1774 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1775
1776 !to_pe's SW halo
1777 dir = 4
1778 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1779 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
1780 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1781 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1782 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1783 if(je .LT. jsg) then ! js .LT. jsg
1784 if( domain%y(tme)%cyclic ) then
1785 js = js + joff; je = je + joff
1786 endif
1787 else if(js .Lt. jsg) then ! split into two parts
1788 if( domain%y(tme)%cyclic ) then
1789 js2 = js + joff; je2 = jsg-1+joff
1790 js = jsg;
1791 endif
1792 endif
1793 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1794 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1795 if(je2 .GE. js2) call fill_overlap_send_nofold(overlap, domain, m, is, ie, js2, je2, isc, iec, jsc, jec, &
1796 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1797 else
1798 if( isg.GT.is )then
1799 if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1800 is = is+ioff; ie = ie+ioff
1801 need_adjust_1 = .false.
1802 if(jsg .GT. js) then
1803 if( domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1804 js = js+joff; je = je+joff
1805 need_adjust_2 = .false.
1806 if(x_cyclic_offset .NE. 0) then
1807 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1808 else if(y_cyclic_offset .NE. 0) then
1809 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1810 end if
1811 end if
1812 else
1813 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1814 need_adjust_3 = .false.
1815 end if
1816 end if
1817 end if
1818 if( need_adjust_3 .AND. jsg.GT.js )then
1819 if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. je.LT.jsc )then !try cyclic offset
1820 js = js+joff; je = je+joff
1821 if(need_adjust_1 .AND. isg.LE.is )then
1822 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
1823 end if
1824 end if
1825 end if
1826 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, isg, ieg, jsg, jeg, dir)
1827 endif
1828
1829 !to_pe's western halo
1830 dir = 5
1831 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1832 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
1833
1834 !--- when the north face is folded, some point at j=nj will be folded.
1835 !--- the position should be on CORNER or NORTH
1836 if( je == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
1837 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1838 isg, ieg, dir, ishift, position, ioff, middle)
1839 else
1840 if(x_cyclic_offset ==0 .AND. y_cyclic_offset == 0) then
1841 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1842 isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1843 else
1844 if( isg.GT.is )then
1845 if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1846 is = is+ioff; ie = ie+ioff
1847 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1848 endif
1849 end if
1850 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1851 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1852 end if
1853 end if
1854
1855 !to_pe's NW halo
1856 dir = 6
1857 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
1858 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
1859 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
1860 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
1861 folded = .false.
1862 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1863 if(js .GT. jeg) then ! je > jeg
1864 if( domain%y(tme)%cyclic ) then
1865 js = js-joff; je = je-joff
1866 else if(folded_north )then
1867 folded = .true.
1868 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1869 endif
1870 else if(je .GT. jeg) then ! split into two parts
1871 if( domain%y(tme)%cyclic ) then
1872 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1873 js = jeg+1-joff; je = je -joff
1874 else if(folded_north) then
1875 folded = .true.
1876 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1877 js = jeg+1
1878 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1879 if( is .GT. ieg) then
1880 is = is - ioff; ie = ie - ioff
1881 else if( ie .GT. ieg ) then
1882 is3 = is; ie3 = ieg; js3 = js; je3 = je
1883 is = ieg+1-ioff; ie = ie - ioff
1884 endif
1885 endif
1886 endif
1887
1888 if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
1889 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1890 isg, ieg, dir, ishift, position, ioff, middle)
1891 else
1892 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1893 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
1894 endif
1895 if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
1896 isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
1897 if(ie2 .GE. is2) then
1898 if(je2 == jeg .AND. jec == jeg .AND. folded_north.AND.(position == corner .OR. position == north))then
1899 call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1900 isg, ieg, dir, ishift, position, ioff, middle)
1901 else
1902 call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1903 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
1904 endif
1905 endif
1906 else
1907 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
1908 if( isg.GT.is )then
1909 if( domain%x(tme)%cyclic .AND. ie.LT.isc )then !try cyclic offset
1910 is = is+ioff; ie = ie+ioff
1911 need_adjust_1 = .false.
1912 if(je .GT. jeg) then
1913 if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1914 js = js-joff; je = je-joff
1915 need_adjust_2 = .false.
1916 if(x_cyclic_offset .NE. 0) then
1917 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1918 else if(y_cyclic_offset .NE. 0) then
1919 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1920 end if
1921 end if
1922 else
1923 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
1924 need_adjust_3 = .false.
1925 end if
1926 end if
1927 end if
1928 folded = .false.
1929 if( need_adjust_3 .AND. je.GT.jeg )then
1930 if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1931 js = js-joff; je = je-joff
1932 if( need_adjust_1 .AND. isg.LE.is)then
1933 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1934 end if
1935 else if( folded_north )then
1936 folded = .true.
1937 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1938 end if
1939 end if
1940 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1941 isg, ieg, jsg, jeg, dir)
1942 endif
1943
1944
1945 !to_pe's northern halo
1946 dir = 7
1947 folded = .false.
1948 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
1949 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
1950
1951 !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
1952 !--- no need to send, because the data on that point will come from other pe.
1953 !--- come from two pe ( there will be only one point on one pe. ).
1954 if( domain%symmetry .AND. (position == east .OR. position == corner ) &
1955 .AND. ( isc == ie .or. iec == is ) .AND. (.not. folded_north) ) then
1956 !--- do nothing, this point will come from other pe
1957 else
1958 js2 = -1; je2 = 0
1959 if( js .GT. jeg) then ! je .GT. jeg
1960 if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
1961 js = js-joff; je = je-joff
1962 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
1963 else if( folded_north )then
1964 folded = .true.
1965 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1966 end if
1967 else if( je.GT.jeg )then ! split into two parts
1968 if( domain%y(tme)%cyclic)then !try cyclic offset
1969 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1970 js = jeg+1-joff; je = je - joff
1971 else if( folded_north )then
1972 folded = .true.
1973 is2 = is; ie2 = ie; js2 = js; je2 = jeg
1974 js = jeg+1;
1975 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
1976 end if
1977 end if
1978 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
1979 if( je == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
1980 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1981 isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1982 else
1983 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1984 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, domain%symmetry)
1985 endif
1986 else
1987 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
1988 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
1989 endif
1990
1991 if(ie2 .GE. is2) then
1992 if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
1993 call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1994 isg, ieg, dir, ishift, position, ioff, middle, domain%symmetry)
1995 else
1996 call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
1997 isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
1998 endif
1999 endif
2000 end if
2001
2002 !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2003 if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2004! is = is + ioff
2005! call insert_update_overlap( overlap, domain%list(m)%pe, &
2006! is, is, js, je, isc, iec, jsc, jec, dir, folded)
2007!??? if(je2 .GE. js2)call insert_update_overlap( overlap, domain%list(m)%pe, &
2008! is, is, js2, je2, isc, iec, jsc, jec, dir, folded)
2009 endif
2010
2011 !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2012 !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2013 !--- only position at NORTH and CORNER need to be considered
2014 if( folded_north .AND. (position == north .OR. position == corner) &
2015 .AND. domain%x(tme)%pos .LT. (size(domain%x(tme)%list(:))+1)/2 ) then
2016 if( domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .GE. jeg .AND. isc .LE. middle)then
2017 js = jeg; je = jeg
2018 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
2019 is = max(is, middle)
2020 select case (position)
2021 case(north)
2022 i=is; is = isg+ieg-ie; ie = isg+ieg-i
2023 case(corner)
2024 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2025 end select
2026 call insert_update_overlap(overlap, domain%list(m)%pe, &
2027 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
2028 endif
2029 if(debug_update_level .NE. no_check .AND. set_check) then
2030 je = domain%list(m)%y(tnbr)%compute%end+jshift;
2031 if(je == jeg) then
2032 is = max(is, isc); ie = min(ie, iec)
2033 js = max(js, jsc); je = min(je, jec)
2034 if(ie.GE.is .AND. je.GE.js )then
2035 nsend_check = nsend_check+1
2036 if(nsend_check > size(checklist(:)) ) then
2037 call expand_check_overlap_list(checklist, nlist)
2038 endif
2039 call allocate_check_overlap(checklist(nsend_check), 1)
2040 call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
2041 tme, 4, one_hundred_eighty, is, ie, js, je)
2042 end if
2043 end if
2044 endif
2045 endif
2046
2047 !to_pe's NE halo
2048 dir = 8
2049 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
2050 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
2051 is2 = 0; ie2=-1; js2=0; je2=-1
2052 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2053 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2054 folded = .false.
2055 if(js .GT. jeg) then ! je > jeg
2056 if( domain%y(tme)%cyclic ) then
2057 js = js-joff; je = je-joff
2058 else if(folded_north )then
2059 folded = .true.
2060 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2061 endif
2062 else if(je .GT. jeg) then ! split into two parts
2063 if( domain%y(tme)%cyclic ) then
2064 is2 = is; ie2 = ie; js2 = js; je2 = jeg
2065 js = jeg+1-joff; je = je -joff
2066 else if(folded_north) then
2067 folded = .true.
2068 is2 = is; ie2 = ie; js2 = js; je2 = jeg
2069 js = jeg+1
2070 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2071
2072 if( ie .LT. isg )then
2073 is = is+ioff; ie = ie+ioff
2074 else if( is .LT. isg) then
2075 is3 = isg; ie3 = ie; js3 = js; je3 = je
2076 is = is+ioff; ie = isg-1+ioff;
2077 endif
2078 endif
2079 endif
2080 if( je == jeg .AND. jec == jeg .AND. folded_north .AND. (position == corner .OR. position == north)) then
2081 call fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2082 isg, ieg, dir, ishift, position, ioff, middle)
2083 else
2084 call fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2085 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2086 endif
2087 if(ie3 .GE. is3) call fill_overlap_send_nofold(overlap, domain, m, is3, ie3, js3, je3, &
2088 isc, iec, jsc, jec, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2089 if(ie2 .GE. is2) then
2090 if(je2 == jeg .AND. jec == jeg .AND. folded_north .AND.(position == corner .OR. position == north))then
2091 call fill_overlap_send_fold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2092 isg, ieg, dir, ishift, position, ioff, middle)
2093 else
2094 call fill_overlap_send_nofold(overlap, domain, m, is2, ie2, js2, je2, isc, iec, jsc, jec, &
2095 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2096 endif
2097 endif
2098 else
2099 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2100 if( ie.GT.ieg )then
2101 if( domain%x(tme)%cyclic .AND. iec.LT.is )then !try cyclic offset
2102 is = is-ioff; ie = ie-ioff
2103 need_adjust_1 = .false.
2104 if(je .GT. jeg) then
2105 if( domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
2106 js = js-joff; je = je-joff
2107 need_adjust_2 = .false.
2108 if(x_cyclic_offset .NE. 0) then
2109 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2110 else if(y_cyclic_offset .NE. 0) then
2111 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2112 end if
2113 end if
2114 else
2115 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2116 need_adjust_3 = .false.
2117 end if
2118 end if
2119 end if
2120 folded = .false.
2121 if( need_adjust_3 .AND. je.GT.jeg )then
2122 if( need_adjust_2 .AND. domain%y(tme)%cyclic .AND. jec.LT.js )then !try cyclic offset
2123 js = js-joff; je = je-joff
2124 if( need_adjust_1 .AND. ie.LE.ieg)then
2125 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2126 end if
2127 else if( folded_north )then
2128 folded = .true.
2129 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2130 end if
2131 end if
2132 call fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2133 isg, ieg, jsg, jeg, dir)
2134 endif
2135 endif
2136
2137 !--- copy the overlapping information
2138 if( overlap%count > 0) then
2139 nsend = nsend + 1
2140 if(nsend > size(overlaplist(:)) ) then
2141 call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps): overlapList for send is expanded')
2142 call expand_update_overlap_list(overlaplist, nlist)
2143 endif
2144 call add_update_overlap( overlaplist(nsend), overlap)
2145 call init_overlap_type(overlap)
2146 endif
2147 end do ! end of send set up.
2148
2149 if(debug_message_passing) then
2150 !--- write out send information
2151 iunit = mpp_pe() + 1000
2152 do m =1,nsend
2153 write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
2154 do n = 1, overlaplist(m)%count
2155 write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
2156 overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
2157 enddo
2158 enddo
2159 if(nsend >0) flush(iunit)
2160 endif
2161
2162 ! copy the overlapping information into domain data structure
2163 if(nsend>0) then
2164 if (associated(update%send)) deallocate(update%send) !< Check if associated
2165 allocate(update%send(nsend))
2166 update%nsend = nsend
2167 do m = 1, nsend
2168 call add_update_overlap( update%send(m), overlaplist(m) )
2169 enddo
2170 endif
2171
2172 if(nsend_check>0) then
2173 check%nsend = nsend_check
2174 if (associated(check%send)) deallocate(check%send) !< Check if associated
2175 allocate(check%send(nsend_check))
2176 do m = 1, nsend_check
2177 call add_check_overlap( check%send(m), checklist(m) )
2178 enddo
2179 endif
2180
2181 do m = 1,size(overlaplist(:))
2182 call deallocate_overlap_type(overlaplist(m))
2183 enddo
2184
2185 if(debug_update_level .NE. no_check .AND. set_check) then
2186 do m = 1,size(checklist(:))
2187 call deallocate_overlap_type(checklist(m))
2188 enddo
2189 endif
2190
2191 isgd = isg - domain%whalo
2192 iegd = ieg + domain%ehalo
2193 jsgd = jsg - domain%shalo
2194 jegd = jeg + domain%nhalo
2195
2196 ! begin setting up recv
2197 nrecv = 0
2198 nrecv_check = 0
2199 do list = 0,nlist-1
2200 m = mod( domain%pos+nlist-list, nlist )
2201 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
2202 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
2203 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
2204 !recv_e
2205 dir = 1
2206 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2207 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
2208 is=isc; ie=iec; js=jsc; je=jec
2209 if( domain%symmetry .AND. (position == north .OR. position == corner ) &
2210 .AND. ( jsd == je .or. jed == js ) ) then
2211 ! --- do nothing, this point will come from other pe
2212 else
2213 !--- when the north face is folded, the east halo point at right side domain will be folded.
2214 !--- the position should be on CORNER or NORTH
2215 if( jed == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
2216 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2217 isg, ieg, dir, ishift, position, ioff, middle)
2218 else
2219 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2220 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2221 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2222 else
2223 if( ied.GT.ieg )then
2224 if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2225 is = is+ioff; ie = ie+ioff
2226 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2227 end if
2228 end if
2229 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2230 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2231 endif
2232 endif
2233 endif
2234
2235 !recv_se
2236 dir = 2
2237 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2238 jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2239 is=isc; ie=iec; js=jsc; je=jec
2240 !--- divide into two parts, one part is x_cyclic_offset/y_cyclic_offset is non-zeor,
2241 !--- the other part is both are zero.
2242 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2243 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2244 if(jed .LT. jsg) then ! then jsd < jsg
2245 if( domain%y(tme)%cyclic ) then
2246 js = js-joff; je = je-joff
2247 endif
2248 else if(jsd .LT. jsg) then !split into two parts
2249 if( domain%y(tme)%cyclic ) then
2250 js2 = js-joff; je2 = je-joff
2251 endif
2252 endif
2253 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2254 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2255 if(je2 .GE. js2) call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2256 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2257 else
2258 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2259 if( jsd.LT.jsg )then
2260 if( domain%y(tme)%cyclic .AND. js.GT.jed )then !try cyclic offset
2261 js = js-joff; je = je-joff
2262 need_adjust_1 = .false.
2263 if( ied.GT.ieg )then
2264 if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2265 is = is+ioff; ie = ie+ioff
2266 need_adjust_2 = .false.
2267 if(x_cyclic_offset .NE. 0) then
2268 call apply_cyclic_offset(js, je, x_cyclic_offset, jsgd, jeg, nj)
2269 else if(y_cyclic_offset .NE. 0) then
2270 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, iegd, ni)
2271 end if
2272 end if
2273 else
2274 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2275 need_adjust_3 = .false.
2276 end if
2277 end if
2278 end if
2279 if( need_adjust_3 .AND. ied.GT.ieg )then
2280 if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2281 is = is+ioff; ie = ie+ioff
2282 if( need_adjust_1 .AND. jsd.GE.jsg )then
2283 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2284 end if
2285 end if
2286 end if
2287 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2288 isg, ieg, jsg, jeg, dir)
2289 endif
2290
2291 !recv_s
2292 dir = 3
2293 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
2294 jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2295 is=isc; ie=iec; js=jsc; je=jec
2296 js2 = 0; je2 = -1
2297 if( jed .LT. jsg) then ! jsd < jsg
2298 if( domain%y(tme)%cyclic ) then
2299 js = js-joff; je = je-joff
2300 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2301 endif
2302 else if( jsd.LT.jsg )then ! split into two parts
2303 if( domain%y(tme)%cyclic)then !try cyclic offset
2304 js2 = js-joff; je2 = je-joff
2305 end if
2306 end if
2307 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2308 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2309 if(je2 .GE. js2) call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2310 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2311
2312 !recv_sw
2313 dir = 4
2314 isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2315 jsd = domain%y(tme)%compute%begin-shalo; jed = domain%y(tme)%compute%begin-1
2316 is=isc; ie=iec; js=jsc; je=jec
2317 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2318 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2319 if( ied.LT.isg )then ! isd < isg
2320 if( domain%x(tme)%cyclic ) then
2321 is = is-ioff; ie = ie-ioff
2322 endif
2323 else if (isd.LT.isg )then ! split into two parts
2324 if( domain%x(tme)%cyclic ) then
2325 is2 = is-ioff; ie2 = ie-ioff
2326 endif
2327 endif
2328 if( jed.LT.jsg )then ! jsd < jsg
2329 if( domain%y(tme)%cyclic ) then
2330 js = js-joff; je = je-joff
2331 endif
2332 else if( jsd.LT.jsg )then ! split into two parts
2333 if( domain%y(tme)%cyclic ) then
2334 js2 = js-joff; je2 = je-joff
2335 endif
2336 endif
2337 else
2338 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2339 if( jsd.LT.jsg )then
2340 if( domain%y(tme)%cyclic .AND. js.GT.jed )then !try cyclic offset
2341 js = js-joff; je = je-joff
2342 need_adjust_1 = .false.
2343 if( isd.LT.isg )then
2344 if( domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2345 is = is-ioff; ie = ie-ioff
2346 need_adjust_2 = .false.
2347 if(x_cyclic_offset .NE. 0) then
2348 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsgd, jeg, nj)
2349 else if(y_cyclic_offset .NE. 0) then
2350 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isgd, ieg, ni)
2351 end if
2352 end if
2353 else
2354 call apply_cyclic_offset(is, ie, -y_cyclic_offset, isg, ieg, ni)
2355 need_adjust_3 = .false.
2356 end if
2357 end if
2358 end if
2359 if( need_adjust_3 .AND. isd.LT.isg )then
2360 if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2361 is = is-ioff; ie = ie-ioff
2362 if(need_adjust_1 .AND. jsd.GE.jsg) then
2363 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2364 end if
2365 end if
2366 end if
2367 endif
2368 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2369 isg, ieg, jsg, jeg, dir)
2370
2371 if(ie2 .GE. is2)call fill_overlap(overlap, domain, m, is2, ie2, js, je, isd, ied, jsd, jed, &
2372 isg, ieg, jsg, jeg, dir)
2373 if(je2 .GE. js2)call fill_overlap(overlap, domain, m, is, ie, js2, je2, isd, ied, jsd, jed, &
2374 isg, ieg, jsg, jeg, dir)
2375
2376 if(ie2 .GE. is2 .AND. je2 .GE. js2)call fill_overlap(overlap, domain, m, is2, ie2, js2, je2, isd, ied, jsd, &
2377 & jed, isg, ieg, jsg, jeg, dir)
2378
2379
2380 !recv_w
2381 dir = 5
2382 isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2383 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
2384 is=isc; ie=iec; js=jsc; je=jec
2385
2386 !--- when the north face is folded, some point at j=nj will be folded.
2387 !--- the position should be on CORNER or NORTH
2388 if( jed == jeg .AND. folded_north .AND. (position == corner .OR. position == north) ) then
2389 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2390 isg, ieg, dir, ishift, position, ioff, middle)
2391 else
2392 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2393 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2394 isg, ieg, dir, ioff, domain%x(tme)%cyclic, symmetry=domain%symmetry)
2395 else
2396 if( isd.LT.isg )then
2397 if( domain%x(tme)%cyclic .AND. is.GT.ied )then !try cyclic offset
2398 is = is-ioff; ie = ie-ioff
2399 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2400 end if
2401 end if
2402 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2403 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2404 endif
2405 endif
2406
2407 !recv_nw
2408 dir = 6
2409 folded = .false.
2410 isd = domain%x(tme)%compute%begin-whalo; ied = domain%x(tme)%compute%begin-1
2411 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2412 is=isc; ie=iec; js=jsc; je=jec
2413 is2 = 0; ie2 = -1; js2 = 0; je2 = -1
2414 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2415 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2416 js2 = -1; je2 = 0
2417 if( jsd .GT. jeg ) then ! jed > jeg
2418 if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2419 js = js+joff; je = je+joff
2420 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2421 else if( folded_north )then
2422 folded = .true.
2423 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2424 end if
2425 else if( jed.GT.jeg )then ! split into two parts
2426 if( domain%y(tme)%cyclic)then !try cyclic offset
2427 is2 = is; ie2 = ie; js2 = js; je2 = je
2428 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2429 js = js + joff; je = je + joff
2430 jsd = jeg+1
2431 else if( folded_north )then
2432 folded = .true.
2433 is2 = is; ie2 = ie; js2 = js; je2 = je
2434 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2435 jsd = jeg+1
2436 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2437 if(isd < isg .and. ied .GE. isg .and. domain%symmetry) then
2438 isd3 = isd; ied3 = isg-1
2439 jsd3 = jsd; jed3 = jed
2440 is3 = is-ioff; ie3=ie-ioff
2441 js3 = js; je3 = je
2442 isd = isg;
2443 endif
2444 end if
2445 endif
2446
2447 if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2448 .AND. (position == corner .OR. position == north)) then
2449 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2450 isg, ieg, dir, ishift, position, ioff, middle)
2451 else
2452 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2453 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2454 endif
2455
2456 if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2457 & jed3, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2458
2459 if(ie2 .GE. is2) then
2460 if( jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2461 .AND. (position == corner .OR. position == north)) then
2462 call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2463 isg, ieg, dir, ishift, position, ioff, middle)
2464 else
2465 call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2466 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2467 endif
2468 endif
2469 else
2470 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2471 if( jed.GT.jeg )then
2472 if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2473 js = js+joff; je = je+joff
2474 need_adjust_1 = .false.
2475 if( isd.LT.isg )then
2476 if( domain%x(tme)%cyclic .AND. is.GE.ied )then !try cyclic offset
2477 is = is-ioff; ie = ie-ioff
2478 need_adjust_2 = .false.
2479 if(x_cyclic_offset .NE. 0) then
2480 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jegd, nj)
2481 else if(y_cyclic_offset .NE. 0) then
2482 call apply_cyclic_offset(is, ie, y_cyclic_offset, isgd, ieg, ni)
2483 end if
2484 end if
2485 else
2486 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2487 need_adjust_3 = .false.
2488 end if
2489 else if( folded_north )then
2490 folded = .true.
2491 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2492 end if
2493 end if
2494 if( need_adjust_3 .AND. isd.LT.isg )then
2495 if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. is.GE.ied )then !try cyclic offset
2496 is = is-ioff; ie = ie-ioff
2497 if( need_adjust_1 .AND. jed.LE.jeg )then
2498 call apply_cyclic_offset(js, je, -x_cyclic_offset, jsg, jeg, nj)
2499 end if
2500 end if
2501 end if
2502 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2503 isg, ieg, jsg, jeg, dir)
2504 endif
2505
2506 !--- when north edge is folded, is will be less than isg when position is EAST and CORNER
2507 if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2508 is = is + ioff
2509 call insert_update_overlap(overlap, domain%list(m)%pe, &
2510 is, is, js, je, isd, ied, jsd, jed, dir, folded )
2511 endif
2512
2513 !recv_n
2514 dir = 7
2515 folded = .false.
2516 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
2517 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2518 is=isc; ie=iec; js=jsc; je=jec
2519
2520 !--- when domain symmetry and position is EAST or CORNER, the point at i=isd will
2521 !--- come from two pe ( there will be only one point on one pe. ).
2522 if( domain%symmetry .AND. (position == east .OR. position == corner ) &
2523 .AND. (isd == ie .or. ied == is ) .AND. (.not. folded_north) ) then
2524 !--- do nothing, this point will come from other pe
2525 else
2526 js2 = -1; je2 = 0
2527 if( jsd .GT. jeg ) then ! jed > jeg
2528 if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2529 js = js+joff; je = je+joff
2530 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2531 else if( folded_north )then
2532 folded = .true.
2533 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2534 end if
2535 else if( jed.GT.jeg )then ! split into two parts
2536 if( domain%y(tme)%cyclic)then !try cyclic offset
2537 is2 = is; ie2 = ie; js2 = js; je2 = je
2538 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2539 js = js + joff; je = je + joff
2540 jsd = jeg+1
2541 else if( folded_north )then
2542 folded = .true.
2543 is2 = is; ie2 = ie; js2 = js; je2 = je
2544 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2545 jsd = jeg+1
2546 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2547 end if
2548 end if
2549 if(x_cyclic_offset == 0 .and. y_cyclic_offset == 0) then
2550 if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2551 .AND. (position == corner .OR. position == north)) then
2552 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2553 isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2554 else
2555 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2556 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, symmetry=domain%symmetry)
2557 endif
2558 else
2559 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2560 isg, ieg, jsg, jeg, dir, symmetry=domain%symmetry)
2561 endif
2562 if(ie2 .GE. is2) then
2563 if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2564 .AND. (position == corner .OR. position == north)) then
2565 call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2566 isg, ieg, dir, ishift, position, ioff, middle, symmetry=domain%symmetry)
2567 else
2568 call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2569 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded, symmetry=domain%symmetry)
2570 endif
2571 endif
2572 endif
2573
2574 !--- when north edge is folded, ie will be less than isg when position is EAST and CORNER
2575 if(is .LT. isg .AND. domain%x(tme)%cyclic) then
2576! is = is + ioff
2577! call insert_update_overlap( overlap, domain%list(m)%pe, &
2578! is, is, js, je, isd, ied, jsd, jed, dir, folded)
2579 endif
2580
2581 !--- Now calculate the overlapping for fold-edge. Currently we only consider about folded-north
2582 !--- for folded-north-edge, only need to consider to_pe's north(7) direction
2583 !--- only position at NORTH and CORNER need to be considered
2584
2585 if( folded_north .AND. (position == north .OR. position == corner) &
2586 .AND. domain%x(tme)%pos .GE. size(domain%x(tme)%list(:))/2) then
2587 if( jed .GE. jeg .AND. ied .GE. middle)then
2588 jsd = jeg; jed = jeg
2589 is=isc; ie=iec; js = jsc; je = jec
2590 isd = max(isd, middle)
2591 select case (position)
2592 case(north)
2593 i=is; is = isg+ieg-ie; ie = isg+ieg-i
2594 case(corner)
2595 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
2596 end select
2597 call insert_update_overlap(overlap, domain%list(m)%pe, &
2598 is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
2599 endif
2600 if(debug_update_level .NE. no_check .AND. set_check) then
2601 jsd = domain%y(tme)%compute%end+jshift; jed = jsd
2602 if(jed == jeg) then
2603 is = max(is, isd); ie = min(ie, ied)
2604 js = max(js, jsd); je = min(je, jed)
2605 if(ie.GE.is .AND. je.GE.js )then
2606 nrecv_check = nrecv_check+1
2607 if(nrecv_check > size(checklist(:)) ) then
2608 call expand_check_overlap_list(checklist, nlist)
2609 endif
2610 call allocate_check_overlap(checklist(nrecv_check), 1)
2611 call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
2612 tme, 4, one_hundred_eighty, is, ie, js, je)
2613 end if
2614 end if
2615 endif
2616
2617 endif
2618
2619 !recv_ne
2620 dir = 8
2621 folded = .false.
2622 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%compute%end+ehalo+ishift
2623 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%compute%end+nhalo+jshift
2624 is=isc; ie=iec; js=jsc; je=jec
2625 is2 = 0; ie2=-1; js2=0; je2=-1
2626 is3 = 0; ie3 = -1; js3 = 0; je3 = -1
2627 if(x_cyclic_offset == 0 .AND. y_cyclic_offset == 0) then
2628 js2 = -1; je2 = 0
2629 if( jsd .GT. jeg ) then ! jed > jeg
2630 if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2631 js = js+joff; je = je+joff
2632 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2633 else if( folded_north )then
2634 folded = .true.
2635 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2636 end if
2637 else if( jed.GT.jeg )then ! split into two parts
2638 if( domain%y(tme)%cyclic)then !try cyclic offset
2639 is2 = is; ie2 = ie; js2 = js; je2 = je
2640 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2641 js = js + joff; je = je + joff
2642 jsd = jeg+1
2643 else if( folded_north )then
2644 folded = .true.
2645 is2 = is; ie2 = ie; js2 = js; je2 = je
2646 isd2 = isd; ied2 = ied; jsd2 = jsd; jed2 = jeg
2647 jsd = jeg+1
2648 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2649 if(ied > ieg .and. isd .LE. ieg .and. domain%symmetry) then
2650 isd3 = ieg+1; ied3 = ied
2651 jsd3 = jsd; jed3 = jed
2652 is3 = is+ioff; ie3=ie+ioff
2653 js3 = js; je3 = je
2654 ied = ieg;
2655 endif
2656 end if
2657 endif
2658 if( jeg .GE. js .AND. jeg .LE. je .AND. jed == jeg .AND. folded_north &
2659 .AND. (position == corner .OR. position == north)) then
2660 call fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2661 isg, ieg, dir, ishift, position, ioff, middle)
2662 else
2663 call fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2664 isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2665 endif
2666 if(ie3 .GE. is3) call fill_overlap_recv_nofold(overlap, domain, m, is3, ie3, js3, je3, isd3, ied3, jsd3, &
2667 & jed3, isg, ieg, dir, ioff, domain%x(tme)%cyclic, folded)
2668 if(ie2 .GE. is2) then
2669 if(jeg .GE. js2 .AND. jeg .LE. je2 .AND. jed2 == jeg .AND. folded_north &
2670 .AND. (position == corner .OR. position == north)) then
2671 call fill_overlap_recv_fold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2672 isg, ieg, dir, ishift, position, ioff, middle)
2673 else
2674 call fill_overlap_recv_nofold(overlap, domain, m, is2, ie2, js2, je2, isd2, ied2, jsd2, jed2, &
2675 isg, ieg, dir, ioff, domain%x(tme)%cyclic)
2676 endif
2677 endif
2678 else
2679 need_adjust_1 = .true.; need_adjust_2 = .true.; need_adjust_3 = .true.
2680 if( jed.GT.jeg )then
2681 if( domain%y(tme)%cyclic .AND. je.LT.jsd )then !try cyclic offset
2682 js = js+joff; je = je+joff
2683 need_adjust_1 = .false.
2684 if( ied.GT.ieg )then
2685 if( domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2686 is = is+ioff; ie = ie+ioff
2687 need_adjust_2 = .false.
2688 if(x_cyclic_offset .NE. 0) then
2689 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jegd, nj)
2690 else if(y_cyclic_offset .NE. 0) then
2691 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, iegd, ni)
2692 end if
2693 end if
2694 else
2695 call apply_cyclic_offset(is, ie, y_cyclic_offset, isg, ieg, ni)
2696 need_adjust_3 = .false.
2697 end if
2698 else if( folded_north )then
2699 folded = .true.
2700 call get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
2701 end if
2702 end if
2703 if( need_adjust_3 .AND. ied.GT.ieg )then
2704 if( need_adjust_2 .AND. domain%x(tme)%cyclic .AND. ie.LT.isd )then !try cyclic offset
2705 is = is+ioff; ie = ie+ioff
2706 if( need_adjust_1 .AND. jed.LE.jeg)then
2707 call apply_cyclic_offset(js, je, x_cyclic_offset, jsg, jeg, nj)
2708 end if
2709 end if
2710 end if
2711 call fill_overlap(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2712 isg, ieg, jsg, jeg, dir)
2713 endif
2714 endif
2715
2716 !--- copy the overlapping information
2717 if( overlap%count > 0) then
2718 nrecv = nrecv + 1
2719 if(nrecv > size(overlaplist(:)) )then
2720 call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps): overlapList for recv is expanded')
2721 call expand_update_overlap_list(overlaplist, nlist)
2722 endif
2723 call add_update_overlap( overlaplist(nrecv), overlap)
2724 call init_overlap_type(overlap)
2725 endif
2726 enddo ! end of recv do loop
2727
2728 if(debug_message_passing) then
2729 !--- write out send information
2730 iunit = mpp_pe() + 1000
2731 do m =1,nrecv
2732 write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
2733 do n = 1, overlaplist(m)%count
2734 write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
2735 overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
2736 enddo
2737 enddo
2738 if(nrecv >0) flush(iunit)
2739 endif
2740
2741 ! copy the overlapping information into domain
2742 if(nrecv>0) then
2743 if (associated(update%recv)) deallocate(update%recv) !< Check if associated
2744 allocate(update%recv(nrecv))
2745 update%nrecv = nrecv
2746 do m = 1, nrecv
2747 call add_update_overlap( update%recv(m), overlaplist(m) )
2748 do n = 1, update%recv(m)%count
2749 if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
2750 if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
2751 if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
2752 endif
2753 enddo
2754 enddo
2755 endif
2756
2757 if(nrecv_check>0) then
2758 check%nrecv = nrecv_check
2759 if (associated(check%recv)) deallocate(check%recv) !< Check if associated
2760 allocate(check%recv(nrecv_check))
2761 do m = 1, nrecv_check
2762 call add_check_overlap( check%recv(m), checklist(m) )
2763 enddo
2764 endif
2765
2766 call deallocate_overlap_type(overlap)
2767 do m = 1,size(overlaplist(:))
2768 call deallocate_overlap_type(overlaplist(m))
2769 enddo
2770
2771 if(debug_update_level .NE. no_check .AND. set_check) then
2772 do m = 1,size(checklist(:))
2773 call deallocate_overlap_type(checklist(m))
2774 enddo
2775 endif
2776
2777 deallocate(overlaplist)
2778 if(set_check) deallocate(checklist)
2779 domain%initialized = .true.
2780
2781 end subroutine compute_overlaps
2782
2783
2784 subroutine fill_overlap_send_nofold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2785 isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2786 type(overlap_type), intent(inout) :: overlap
2787 type(domain2d), intent(inout) :: domain
2788 integer, intent(in ) :: m, is, ie, js, je
2789 integer, intent(in ) :: isc, iec, jsc, jec
2790 integer, intent(in ) :: isg, ieg, dir, ioff
2791 logical, intent(in ) :: is_cyclic
2792 logical, optional, intent(in ) :: folded, symmetry
2793
2794 call insert_update_overlap( overlap, domain%list(m)%pe, &
2795 is, ie, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2796 if(is_cyclic) then
2797 if(ie .GT. ieg) then
2798 call insert_update_overlap( overlap, domain%list(m)%pe, &
2799 is-ioff, ie-ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2800 else if( is .LT. isg ) then
2801 call insert_update_overlap( overlap, domain%list(m)%pe, &
2802 is+ioff, ie+ioff, js, je, isc, iec, jsc, jec, dir, reverse=folded, symmetry=symmetry)
2803 endif
2804 endif
2805
2806 end subroutine fill_overlap_send_nofold
2807 !##################################################################################
2808 subroutine fill_overlap_send_fold(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2809 isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2810 type(overlap_type), intent(inout) :: overlap
2811 type(domain2d), intent(inout) :: domain
2812 integer, intent(in ) :: m, is, ie, js, je
2813 integer, intent(in ) :: isc, iec, jsc, jec
2814 integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2815 logical, optional, intent(in ) :: symmetry
2816 integer :: is1, ie1, is2, ie2, i
2817
2818 !--- consider at j = jeg for west edge.
2819 !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2820 if(position == corner .AND. .NOT. domain%symmetry .AND. is .LE. isg-1 .AND. ie .GE. isg-1) then
2821 call insert_update_overlap(overlap, domain%list(m)%pe, &
2822 isg-1+ioff, isg-1+ioff, je, je, isc, iec, jsc, jec, dir, .true.)
2823 end if
2824
2825 is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2826 !--- east edge
2827 if( is > ieg ) then
2828 is2 = is-ioff; ie2 = ie-ioff
2829 else if( ie > ieg ) then ! split into two parts
2830 is1 = is; ie1 = ieg
2831 is2 = ieg+1-ioff; ie2 = ie-ioff
2832 else if( is .GE. middle ) then
2833 is1 = is; ie1 = ie
2834 else if( ie .GE. middle ) then ! split into two parts
2835 is1 = middle; ie1 = ie
2836 is2 = is; ie2 = middle-1
2837 else if( ie < isg ) then ! west boundary
2838 is1 = is+ieg-isg+1-ishift; ie1 = ie+ieg-isg+1-ishift
2839 else if( is < isg ) then ! split into two parts
2840 is1 = is+ieg-isg+1-ishift; ie1 = isg-1+ieg-isg+1-ishift
2841 is2 = isg; ie2 = ie
2842 else
2843 is2 = is; ie2 = ie
2844 endif
2845
2846 if( ie1 .GE. is1) then
2847 call insert_update_overlap( overlap, domain%list(m)%pe, &
2848 is1, ie1, js, je-1, isc, iec, jsc, jec, dir, symmetry=symmetry)
2849
2850 select case (position)
2851 case(north)
2852 i=is1; is1 = isg+ieg-ie1; ie1 = isg+ieg-i
2853 case(corner)
2854 i=is1; is1 = isg+ieg-ie1-1+ishift; ie1 = isg+ieg-i-1+ishift
2855 end select
2856 call insert_update_overlap( overlap, domain%list(m)%pe, &
2857 is1, ie1, je, je, isc, iec, jsc, jec, dir, .true., symmetry=symmetry)
2858 endif
2859
2860 if(ie2 .GE. is2) then
2861 call insert_update_overlap( overlap, domain%list(m)%pe, &
2862 is2, ie2, js, je, isc, iec, jsc, jec, dir)
2863 endif
2864
2865 end subroutine fill_overlap_send_fold
2866
2867
2868 !#############################################################################
2869 subroutine fill_overlap_recv_nofold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2870 isg, ieg, dir, ioff, is_cyclic, folded, symmetry)
2871 type(overlap_type), intent(inout) :: overlap
2872 type(domain2d), intent(inout) :: domain
2873 integer, intent(in ) :: m, is, ie, js, je
2874 integer, intent(in ) :: isd, ied, jsd, jed
2875 integer, intent(in ) :: isg, ieg, dir, ioff
2876 logical, intent(in ) :: is_cyclic
2877 logical, optional, intent(in ) :: folded, symmetry
2878 integer :: is1, ie1, is2, ie2
2879 integer :: isd1, ied1, isd2, ied2
2880
2881 is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2882 isd1=isd; ied1=ied
2883 isd2=isd; ied2=ied
2884
2885 call insert_update_overlap( overlap, domain%list(m)%pe, &
2886 is, ie, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2887 if(is_cyclic) then
2888 if(ied .GT. ieg) then
2889 call insert_update_overlap( overlap, domain%list(m)%pe, &
2890 is+ioff, ie+ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2891 else if( isd .LT. isg ) then
2892 call insert_update_overlap( overlap, domain%list(m)%pe, &
2893 is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2894 else if ( is .LT. isg ) then
2895 call insert_update_overlap( overlap, domain%list(m)%pe, &
2896 is+ioff, ie+ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2897 else if ( ie .GT. ieg ) then
2898 call insert_update_overlap( overlap, domain%list(m)%pe, &
2899 is-ioff, ie-ioff, js, je, isd, ied, jsd, jed, dir, reverse=folded, symmetry=symmetry)
2900 endif
2901 endif
2902
2903 end subroutine fill_overlap_recv_nofold
2904 !#################################################################################
2905 subroutine fill_overlap_recv_fold(overlap, domain, m, is, ie, js, je, isd, ied, jsd, jed, &
2906 isg, ieg, dir, ishift, position, ioff, middle, symmetry)
2907 type(overlap_type), intent(inout) :: overlap
2908 type(domain2d), intent(inout) :: domain
2909 integer, intent(in ) :: m, is, ie, js, je
2910 integer, intent(in ) :: isd, ied, jsd, jed
2911 integer, intent(in ) :: isg, ieg, dir, ishift, position, ioff, middle
2912 logical, optional, intent(in ) :: symmetry
2913 integer :: is1, ie1, is2, ie2, is3, ie3
2914 integer :: isd1, ied1, isd2, ied2
2915
2916 !--- consider at j = jeg for west edge.
2917 !--- when the data is at corner and not symmetry, i = isg -1 will get from cyclic condition
2918 if( position == corner .AND. .NOT. domain%symmetry .AND. isd .LE. isg-1 .AND. ied .GE. isg-1 ) then
2919 call insert_update_overlap( overlap, domain%list(m)%pe, &
2920 is-ioff, ie-ioff, js, je, isg-1, isg-1, jed, jed, dir, .true.)
2921 end if
2922
2923 is1 = 0; ie1 = -1; is2 = 0; ie2 = -1
2924 isd1=isd; ied1=ied
2925 isd2=isd; ied2=ied
2926 select case (position)
2927 case(north)
2928 is3 = isg+ieg-ie; ie3 = isg+ieg-is
2929 case(corner)
2930 is3 = isg+ieg-ie-1+ishift; ie3 = isg+ieg-is-1+ishift
2931 end select
2932
2933 if(isd .GT. ieg) then ! east
2934 is2 = is + ioff; ie2 = ie + ioff;
2935 else if(ied .GT. ieg) then ! split into two parts
2936 is1 = is; ie1 = ie;
2937 isd1 = isd; ied1 = ieg;
2938 is2 = is + ioff; ie2 = ie + ioff
2939 isd2 = ieg + 1; ied2 = ied
2940 else if(isd .GE. middle) then
2941 is1 = is; ie1 = ie
2942 else if(ied .GE. middle) then ! split into two parts
2943 is1 = is; ie1 = ie
2944 isd1 = middle; ied1 = ied
2945 is2 = is; ie2 = ie
2946 isd2 = isd; ied2 = middle-1
2947 else if(ied .LT. isg) then
2948 is1 = is - ioff; ie1 = ie - ioff;
2949 is3 = is3 - ioff; ie3 = ie3 - ioff;
2950 else if(isd .LT. isg) then ! split into two parts
2951 is1 = is - ioff; ie1 = ie - ioff;
2952 is3 = is3 - ioff; ie3 = ie3 - ioff;
2953 isd1 = isd; ied1 = isg-1
2954 is2 = is; ie2 = ie
2955 isd2 = isg; ied2 = ied
2956 else
2957 is2 = is ; ie2 =ie
2958 isd2 = isd; ied2 = ied
2959 endif
2960
2961 if( ie1 .GE. is1) then
2962 call insert_update_overlap( overlap, domain%list(m)%pe, &
2963 is1, ie1, js, je, isd1, ied1, jsd, jed-1, dir, symmetry=symmetry)
2964
2965 call insert_update_overlap( overlap, domain%list(m)%pe, &
2966 is3, ie3, js, je, isd1, ied1, jed, jed, dir, .true., symmetry=symmetry)
2967 endif
2968
2969 if(ie2 .GE. is2) then
2970 call insert_update_overlap( overlap, domain%list(m)%pe, &
2971 is2, ie2, js, je, isd2, ied2, jsd, jed, dir)
2972 endif
2973
2974 end subroutine fill_overlap_recv_fold
2975
2976!#####################################################################################
2977 subroutine fill_overlap(overlap, domain, m, is, ie, js, je, isc, iec, jsc, jec, &
2978 isg, ieg, jsg, jeg, dir, reverse, symmetry)
2979 type(overlap_type), intent(inout) :: overlap
2980 type(domain2d), intent(inout) :: domain
2981 integer, intent(in ) :: m, is, ie, js, je
2982 integer, intent(in ) :: isc, iec, jsc, jec
2983 integer, intent(in ) :: isg, ieg, jsg, jeg
2984 integer, intent(in ) :: dir
2985 logical, optional, intent(in ) :: reverse, symmetry
2986
2987 if(js > je) then ! seperate into two regions due to x_cyclic_offset is nonzero, the two region are
2988 ! (js, jeg) and (jsg, je).
2989 call insert_update_overlap( overlap, domain%list(m)%pe, &
2990 is, ie, jsg, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2991 call insert_update_overlap( overlap, domain%list(m)%pe, &
2992 is, ie, js, jeg, isc, iec, jsc, jec, dir, reverse, symmetry)
2993 else if(is > ie) then ! seperate into two regions due to y_cyclic_offset is nonzero, the two region are
2994 ! (is, ieg) and (isg, ie).
2995 call insert_update_overlap( overlap, domain%list(m)%pe, &
2996 is, ieg, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2997 call insert_update_overlap( overlap, domain%list(m)%pe, &
2998 isg, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
2999 else
3000 call insert_update_overlap( overlap, domain%list(m)%pe, &
3001 is, ie, js, je, isc, iec, jsc, jec, dir, reverse, symmetry)
3002 end if
3003
3004
3005 end subroutine fill_overlap
3006
3007 !####################################################################################
3008 !> Computes remote domain overlaps
3009 !! assumes only one in each direction
3010 !! will calculate the overlapping for T,E,C,N-cell seperately.
3011 subroutine compute_overlaps_fold_south( domain, position, ishift, jshift)
3012 type(domain2d), intent(inout) :: domain
3013 integer, intent(in) :: position, ishift, jshift
3014
3015 integer :: i, m, n, nlist, tMe, tNbr, dir
3016 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3017 integer :: isg, ieg, jsg, jeg, ioff, joff
3018 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3019 integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3020 logical :: folded
3021 type(overlap_type) :: overlap
3022 type(overlapspec), pointer :: update=>null()
3023 type(overlap_type), pointer :: overlapList(:)=>null()
3024 type(overlap_type), pointer :: checkList(:)=>null()
3025 type(overlapspec), pointer :: check =>null()
3026 integer :: nsend, nrecv
3027 integer :: nsend_check, nrecv_check
3028 integer :: iunit
3029
3030 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3031 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3032 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3033 if(size(domain%x(:)) > 1) return
3034
3035 !--- if there is no halo, no need to compute overlaps.
3036 if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3037
3038 !--- when there is only one tile, n will equal to np
3039 nlist = size(domain%list(:))
3040
3041 select case(position)
3042 case (center)
3043 update => domain%update_T
3044 check => null()
3045 case (corner)
3046 update => domain%update_C
3047 check => domain%check_C
3048 case (east)
3049 update => domain%update_E
3050 check => domain%check_E
3051 case (north)
3052 update => domain%update_N
3053 check => domain%check_N
3054 case default
3055 call mpp_error(fatal, &
3056 "mpp_domains_define.inc(compute_overlaps_fold_south): the value of position should be CENTER, EAST, &
3057 & CORNER or NORTH")
3058 end select
3059
3060 allocate(overlaplist(maxlist) )
3061 allocate(checklist(maxlist) )
3062
3063 !--- overlap is used to store the overlapping temporarily.
3064 call allocate_update_overlap( overlap, maxoverlap)
3065
3066 !send
3067 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3068 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3069 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3070 update%xbegin = ism; update%xend = iem
3071 update%ybegin = jsm; update%yend = jem
3072 if(ASSOCIATED(check)) then
3073 check%xbegin = ism; check%xend = iem
3074 check%ybegin = jsm; check%yend = jem
3075 endif
3076 update%whalo = domain%whalo; update%ehalo = domain%ehalo
3077 update%shalo = domain%shalo; update%nhalo = domain%nhalo
3078 whalo = domain%whalo; ehalo = domain%ehalo
3079 shalo = domain%shalo; nhalo = domain%nhalo
3080
3081
3082 ioff = ni - ishift
3083 joff = nj - jshift
3084 middle = (isg+ieg)/2+1
3085 tme = 1; tnbr = 1
3086
3087 if(.NOT. btest(domain%fold,south)) then
3088 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3089 "boundary condition in y-direction should be folded-south for "//trim(domain%name))
3090 endif
3091 if(.NOT. domain%x(tme)%cyclic) then
3092 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3093 "boundary condition in x-direction should be cyclic for "//trim(domain%name))
3094 endif
3095
3096 if(.not. domain%symmetry) then
3097 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_south): "//&
3098 "when south boundary is folded, the domain must be symmetry for "//trim(domain%name))
3099 endif
3100
3101 nsend = 0
3102 nsend_check = 0
3103 do list = 0,nlist-1
3104 m = mod( domain%pos+list, nlist )
3105 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3106 !to_pe's eastern halo
3107 dir = 1
3108 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3109 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3110 !--- to make sure the consistence between pes
3111 if( (position == north .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3112 !--- do nothing, this point will come from other pe
3113 else
3114 if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3115 is = is-ioff; ie = ie-ioff
3116 end if
3117 !--- when the south face is folded, the east halo point at right side domain will be folded.
3118 !--- the position should be on CORNER or NORTH
3119 if( js == jsg .AND. (position == corner .OR. position == north) &
3120 .AND. is .GE. middle .AND. domain%list(m)%x(tnbr)%compute%end+ehalo+jshift .LE. ieg ) then
3121 call insert_update_overlap( overlap, domain%list(m)%pe, &
3122 is, ie, js+1, je, isc, iec, jsc, jec, dir)
3123 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3124 je = js
3125 select case (position)
3126 case(north)
3127 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3128 case(corner)
3129 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3130 end select
3131 call insert_update_overlap( overlap, domain%list(m)%pe, &
3132 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3133 else
3134 call insert_update_overlap( overlap, domain%list(m)%pe, &
3135 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3136 end if
3137 end if
3138
3139 !to_pe's SE halo
3140 dir = 2
3141 folded = .false.
3142 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3143 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3144 if( ie.GT.ieg .AND. iec.LT.is )then ! cyclic is assumed
3145 is = is-ioff; ie = ie-ioff
3146 end if
3147 if( js.LT.jsg )then
3148 folded = .true.
3149 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3150 end if
3151
3152 call insert_update_overlap( overlap, domain%list(m)%pe, &
3153 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3154
3155 !to_pe's southern halo
3156 dir = 3
3157 folded = .false.
3158 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3159 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3160 folded = .false.
3161 if( js.LT.jsg )then
3162 folded = .true.
3163 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3164 end if
3165 !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3166 !--- no need to send, because the data on that point will come from other pe.
3167 !--- come from two pe ( there will be only one point on one pe. ).
3168 if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3169 !--- do nothing, this point will come from other pe
3170 else
3171 call insert_update_overlap( overlap, domain%list(m)%pe, &
3172 is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3173 endif
3174 !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3175 if(is .LT. isg) then
3176 is = is + ioff
3177 call insert_update_overlap( overlap, domain%list(m)%pe, &
3178 is, is, js, je, isc, iec, jsc, jec, dir, folded)
3179 endif
3180
3181 !to_pe's SW halo
3182 dir = 4
3183 folded = .false.
3184 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3185 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3186 if( isg.GT.is .AND. ie.LT.isc )then !cyclic offset
3187 is = is+ioff; ie = ie+ioff
3188 end if
3189 if( js.LT.jsg )then
3190 folded = .true.
3191 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3192 end if
3193 call insert_update_overlap( overlap, domain%list(m)%pe, &
3194 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3195 !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3196 if(is .LT. isg) then
3197 is = is + ioff
3198 call insert_update_overlap( overlap, domain%list(m)%pe, &
3199 is, is, js, je, isc, iec, jsc, jec, dir, folded)
3200 endif
3201
3202 !to_pe's western halo
3203 dir = 5
3204 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3205 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3206
3207 !--- to make sure the consistence between pes
3208 if( (position == north .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3209 !--- do nothing, this point will come from other pe
3210 else
3211 if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3212 is = is+ioff; ie = ie+ioff
3213 end if
3214 !--- when the south face is folded, some point at j=nj will be folded.
3215 !--- the position should be on CORNER or NORTH
3216 if( js == jsg .AND. (position == corner .OR. position == north) &
3217 .AND. ( domain%list(m)%x(tnbr)%compute%begin == isg .OR. &
3218 & domain%list(m)%x(tnbr)%compute%begin-1 .GE. middle)) then
3219 call insert_update_overlap( overlap, domain%list(m)%pe, &
3220 is, ie, js+1, je, isc, iec, jsc, jec, dir)
3221 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3222 js = domain%list(m)%y(tnbr)%compute%begin; je = js
3223 if ( domain%list(m)%x(tnbr)%compute%begin == isg ) then
3224 select case (position)
3225 case(north)
3226 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3227 case(corner)
3228 i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3229 end select
3230 if(ie .GT. domain%x(tme)%compute%end+ishift) call mpp_error( fatal, &
3231 'mpp_domains_define.inc(compute_overlaps_fold_south): west edge ubound error send.' )
3232 else
3233 select case (position)
3234 case(north)
3235 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3236 case(corner)
3237 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3238 end select
3239 end if
3240 call insert_update_overlap( overlap, domain%list(m)%pe, &
3241 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3242 else
3243 call insert_update_overlap( overlap, domain%list(m)%pe, &
3244 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3245 end if
3246 endif
3247
3248 !to_pe's NW halo
3249 dir = 6
3250 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3251 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3252 if( isg.GT.is .AND. ie.LT.isc )then ! cyclic offset
3253 is = is+ioff; ie = ie+ioff
3254 end if
3255 call insert_update_overlap( overlap, domain%list(m)%pe, &
3256 is, ie, js, je, isc, iec, jsc, jec, dir)
3257
3258 !to_pe's northern halo
3259 dir = 7
3260 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3261 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3262 call insert_update_overlap( overlap, domain%list(m)%pe, &
3263 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3264
3265 !to_pe's NE halo
3266 dir = 8
3267 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3268 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3269 if( ie.GT.ieg .AND. iec.LT.is )then !cyclic offset
3270 is = is-ioff; ie = ie-ioff
3271 end if
3272 call insert_update_overlap( overlap, domain%list(m)%pe, &
3273 is, ie, js, je, isc, iec, jsc, jec, dir)
3274
3275 !--- Now calculate the overlapping for fold-edge.
3276 !--- only position at NORTH and CORNER need to be considered
3277 if( ( position == north .OR. position == corner) ) then
3278 !fold is within domain
3279 if( domain%y(tme)%domain_data%begin .LE. jsg .AND. jsg .LE. domain%y(tme)%domain_data%end+jshift )then
3280 dir = 3
3281 !--- calculate the overlapping for sending
3282 if( domain%x(tme)%pos .LT. (size(domain%x(tme)%list(:))+1)/2 )then
3283 js = domain%list(m)%y(tnbr)%compute%begin; je = js
3284 if( js == jsg )then ! fold is within domain.
3285 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3286 select case (position)
3287 case(north)
3288 is = max(is, middle)
3289 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3290 case(corner)
3291 is = max(is, middle)
3292 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3293 end select
3294 call insert_update_overlap(overlap, domain%list(m)%pe, &
3295 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3296 is = max(is, isc); ie = min(ie, iec)
3297 js = max(js, jsc); je = min(je, jec)
3298 if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3299 nsend_check = nsend_check+1
3300 call allocate_check_overlap(checklist(nsend_check), 1)
3301 call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
3302 tme, 2, one_hundred_eighty, is, ie, js, je)
3303 end if
3304 end if
3305 end if
3306 end if
3307 end if
3308 end if
3309 !--- copy the overlapping information
3310 if( overlap%count > 0) then
3311 nsend = nsend + 1
3312 if(nsend > size(overlaplist(:)) ) then
3313 call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for send is expanded')
3314 call expand_update_overlap_list(overlaplist, nlist)
3315 endif
3316 call add_update_overlap(overlaplist(nsend), overlap)
3317 call init_overlap_type(overlap)
3318 endif
3319 end do ! end of send set up.
3320
3321 if(debug_message_passing) then
3322 !--- write out send information
3323 iunit = mpp_pe() + 1000
3324 do m =1,nsend
3325 write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3326 do n = 1, overlaplist(m)%count
3327 write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3328 overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3329 enddo
3330 enddo
3331 if( nsend > 0) flush(iunit)
3332 endif
3333
3334 ! copy the overlapping information into domain data structure
3335 if(nsend>0) then
3336 if (associated(update%send)) deallocate(update%send) !< Check if associated
3337 allocate(update%send(nsend))
3338 update%nsend = nsend
3339 do m = 1, nsend
3340 call add_update_overlap( update%send(m), overlaplist(m) )
3341 enddo
3342 endif
3343
3344 if(nsend_check>0) then
3345 if (associated(check%send)) deallocate(check%send) !< Check if associated
3346 allocate(check%send(nsend_check))
3347 check%nsend = nsend_check
3348 do m = 1, nsend_check
3349 call add_check_overlap( check%send(m), checklist(m) )
3350 enddo
3351 endif
3352
3353 do m = 1,size(overlaplist(:))
3354 call deallocate_overlap_type(overlaplist(m))
3355 enddo
3356
3357 if(debug_update_level .NE. no_check) then
3358 do m = 1,size(checklist(:))
3359 call deallocate_overlap_type(checklist(m))
3360 enddo
3361 endif
3362
3363 isgd = isg - domain%whalo
3364 iegd = ieg + domain%ehalo
3365 jsgd = jsg - domain%shalo
3366 jegd = jeg + domain%nhalo
3367
3368 ! begin setting up recv
3369 nrecv = 0
3370 nrecv_check = 0
3371 do list = 0,nlist-1
3372 m = mod( domain%pos+nlist-list, nlist )
3373 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3374 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
3375 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
3376 !recv_e
3377 dir = 1
3378 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3379 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
3380 is=isc; ie=iec; js=jsc; je=jec
3381 if( (position == north .OR. position == corner ) .AND. ( jsd == je .or. jed == js ) ) then
3382 ! --- do nothing, this point will come from other pe
3383 else
3384 if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3385 is = is+ioff; ie = ie+ioff
3386 end if
3387
3388 !--- when the south face is folded, the east halo point at right side domain will be folded.
3389 !--- the position should be on CORNER or NORTH
3390 if( jsd == jsg .AND. (position == corner .OR. position == north) &
3391 .AND. isd .GE. middle .AND. ied .LE. ieg ) then
3392 call insert_update_overlap( overlap, domain%list(m)%pe, &
3393 is, ie, js, je, isd, ied, jsd+1, jed, dir)
3394 is=isc; ie=iec; js=jsc; je=jec
3395 jed = jsd
3396 select case (position)
3397 case(north)
3398 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3399 case(corner)
3400 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3401 end select
3402 call insert_update_overlap( overlap, domain%list(m)%pe, &
3403 is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
3404 else
3405 call insert_update_overlap( overlap, domain%list(m)%pe, &
3406 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3407 end if
3408 end if
3409
3410 !recv_se
3411 dir = 2
3412 folded = .false.
3413 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3414 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3415 is=isc; ie=iec; js=jsc; je=jec
3416 if( jsd.LT.jsg )then
3417 folded = .true.
3418 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3419 end if
3420 if( ied.GT.ieg .AND. ie.LT.isd )then !cyclic offset
3421 is = is+ioff; ie = ie+ioff
3422 endif
3423 call insert_update_overlap(overlap, domain%list(m)%pe, &
3424 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3425
3426 !recv_s
3427 dir = 3
3428 folded = .false.
3429 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3430 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3431 is=isc; ie=iec; js=jsc; je=jec
3432 if( jsd.LT.jsg )then
3433 folded = .true.
3434 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3435 end if
3436 if( (position == east .OR. position == corner ) .AND. (isd == ie .or. ied == is ) ) then
3437 !--- do nothing, this point will come from other pe
3438 else
3439 call insert_update_overlap(overlap, domain%list(m)%pe, &
3440 is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
3441 end if
3442 !--- when south edge is folded, is will be less than isg when position is EAST and CORNER
3443 if(is .LT. isg ) then
3444 is = is + ioff
3445 call insert_update_overlap(overlap, domain%list(m)%pe, &
3446 is, is, js, je, isd, ied, jsd, jed, dir, folded)
3447 endif
3448
3449 !recv_sw
3450 dir = 4
3451 folded = .false.
3452 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3453 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
3454 is=isc; ie=iec; js=jsc; je=jec
3455 if( jsd.LT.jsg )then
3456 folded = .true.
3457 call get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
3458 end if
3459 if( isd.LT.isg .AND. is.GT.ied ) then ! cyclic offset
3460 is = is-ioff; ie = ie-ioff
3461 end if
3462 call insert_update_overlap(overlap, domain%list(m)%pe, &
3463 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
3464 !--- when southth edge is folded, is will be less than isg when position is EAST and CORNER
3465 if(is .LT. isg ) then
3466 is = is + ioff
3467 call insert_update_overlap(overlap, domain%list(m)%pe, &
3468 is, is, js, je, isd, ied, jsd, jed, dir, folded )
3469 endif
3470
3471 !recv_w
3472 dir = 5
3473 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3474 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
3475 is=isc; ie=iec; js=jsc; je=jec
3476 if( (position == north .OR. position == corner ) .AND. ( jsd == je .or. jed == js ) ) then
3477 ! --- do nothing, this point will come from other pe
3478 else
3479 if( isd.LT.isg .AND. is.GT.ied )then ! cyclic offset
3480 is = is-ioff; ie = ie-ioff
3481 end if
3482 !--- when the south face is folded, some point at j=nj will be folded.
3483 !--- the position should be on CORNER or NORTH
3484 if( jsd == jsg .AND. (position == corner .OR. position == north) &
3485 .AND. ( isd < isg .OR. ied .GE. middle ) ) then
3486 call insert_update_overlap(overlap, domain%list(m)%pe, &
3487 is, ie, js, je, isd, ied, jsd+1, jed, dir)
3488 is=isc; ie=iec; js=jsc; je=jec
3489 if(isd < isg) then
3490 select case (position)
3491 case(north)
3492 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
3493 case(corner)
3494 ied = ied -1 + ishift
3495 i=is; is = 2*isg-ie-2+2*ishift; ie = 2*isg-i-2+2*ishift
3496 end select
3497 if(ie .GT. domain%x(tme)%compute%end+ishift) call mpp_error( fatal, &
3498 'mpp_domains_define.inc(compute_overlaps): west edge ubound error recv.' )
3499 else
3500 select case (position)
3501 case(north)
3502 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3503 case(corner)
3504 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3505 end select
3506 end if
3507 call insert_update_overlap(overlap, domain%list(m)%pe, &
3508 is, ie, js, je, isd, ied, jsd, jsd, dir, .true.)
3509 else
3510 call insert_update_overlap(overlap, domain%list(m)%pe, &
3511 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3512 end if
3513 endif
3514
3515 !recv_nw
3516 dir = 6
3517 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
3518 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3519 is=isc; ie=iec; js=jsc; je=jec
3520 if( isd.LT.isg .AND. is.GE.ied )then !cyclic offset
3521 is = is-ioff; ie = ie-ioff
3522 endif
3523
3524 call insert_update_overlap( overlap, domain%list(m)%pe, &
3525 is, ie, js, je, isd, ied, jsd, jed, dir)
3526
3527 !recv_n
3528 dir = 7
3529 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3530 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3531 is=isc; ie=iec; js=jsc; je=jec
3532 call insert_update_overlap( overlap, domain%list(m)%pe, &
3533 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
3534
3535 !recv_ne
3536 dir = 8
3537 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
3538 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
3539 is=isc; ie=iec; js=jsc; je=jec
3540 if( ied.GT.ieg .AND. ie.LT.isd )then ! cyclic offset
3541 is = is+ioff; ie = ie+ioff
3542 end if
3543 call insert_update_overlap( overlap, domain%list(m)%pe, &
3544 is, ie, js, je, isd, ied, jsd, jed, dir)
3545
3546 !--- Now calculate the overlapping for fold-edge.
3547 !--- for folded-south-edge, only need to consider to_pe's south(3) direction
3548 !--- only position at NORTH and CORNER need to be considered
3549 if( ( position == north .OR. position == corner) ) then
3550 !fold is within domain
3551 if( domain%y(tme)%domain_data%begin .LE. jsg .AND. jsg .LE. domain%y(tme)%domain_data%end+jshift )then
3552 dir = 3
3553 !--- calculating overlapping for receving on north
3554 if( domain%x(tme)%pos .GE. size(domain%x(tme)%list(:))/2 )then
3555 jsd = domain%y(tme)%compute%begin; jed = jsd
3556 if( jsd == jsg )then ! fold is within domain.
3557 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
3558 is=isc; ie=iec; js = jsc; je = jec
3559 select case (position)
3560 case(north)
3561 isd = max(isd, middle)
3562 i=is; is = isg+ieg-ie; ie = isg+ieg-i
3563 case(corner)
3564 isd = max(isd, middle)
3565 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
3566 end select
3567 call insert_update_overlap(overlap, domain%list(m)%pe, &
3568 is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
3569 is = max(is, isd); ie = min(ie, ied)
3570 js = max(js, jsd); je = min(je, jed)
3571 if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3572 nrecv_check = nrecv_check+1
3573 call allocate_check_overlap(checklist(nrecv_check), 1)
3574 call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
3575 tme, 2, one_hundred_eighty, is, ie, js, je)
3576 endif
3577 endif
3578 endif
3579 endif
3580 endif
3581 endif
3582 !--- copy the overlapping information
3583 if( overlap%count > 0) then
3584 nrecv = nrecv + 1
3585 if(nrecv > size(overlaplist(:)) )then
3586 call mpp_error(note, 'mpp_domains_define.inc(compute_overlaps_south): overlapList for recv is expanded')
3587 call expand_update_overlap_list(overlaplist, nlist)
3588 endif
3589 call add_update_overlap( overlaplist(nrecv), overlap)
3590 call init_overlap_type(overlap)
3591 endif
3592 enddo ! end of recv do loop
3593
3594 if(debug_message_passing) then
3595 !--- write out send information
3596 iunit = mpp_pe() + 1000
3597 do m =1,nrecv
3598 write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3599 do n = 1, overlaplist(m)%count
3600 write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3601 overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3602 enddo
3603 enddo
3604 if(nrecv >0) flush(iunit)
3605 endif
3606
3607 ! copy the overlapping information into domain
3608 if(nrecv>0) then
3609 update%nrecv = nrecv
3610 if (associated(update%recv)) deallocate(update%recv) !< Check if associated
3611 allocate(update%recv(nrecv))
3612 do m = 1, nrecv
3613 call add_update_overlap( update%recv(m), overlaplist(m) )
3614 do n = 1, update%recv(m)%count
3615 if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
3616 if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
3617 if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
3618 endif
3619 enddo
3620 enddo
3621 endif
3622
3623 if(nrecv_check>0) then
3624 check%nrecv = nrecv_check
3625 if (associated(check%recv)) deallocate(check%recv) !< Check if associated
3626 allocate(check%recv(nrecv_check))
3627 do m = 1, nrecv_check
3628 call add_check_overlap( check%recv(m), checklist(m) )
3629 enddo
3630 endif
3631
3632 call deallocate_overlap_type(overlap)
3633
3634 do m = 1,size(overlaplist(:))
3635 call deallocate_overlap_type(overlaplist(m))
3636 enddo
3637
3638 if(debug_update_level .NE. no_check) then
3639 do m = 1,size(checklist(:))
3640 call deallocate_overlap_type(checklist(m))
3641 enddo
3642 endif
3643
3644 deallocate(overlaplist)
3645 deallocate(checklist)
3646 update => null()
3647 check=>null()
3648 domain%initialized = .true.
3649
3650 end subroutine compute_overlaps_fold_south
3651
3652 !####################################################################################
3653 !> Computes remote domain overlaps
3654 !! assumes only one in each direction
3655 !! will calculate the overlapping for T,E,C,N-cell seperately.
3656 subroutine compute_overlaps_fold_west( domain, position, ishift, jshift)
3657 type(domain2d), intent(inout) :: domain
3658 integer, intent(in) :: position, ishift, jshift
3659
3660 integer :: j, m, n, nlist, tMe, tNbr, dir
3661 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd, jed
3662 integer :: isg, ieg, jsg, jeg, ioff, joff
3663 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
3664 integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
3665 logical :: folded
3666 type(overlap_type) :: overlap
3667 type(overlapspec), pointer :: update=>null()
3668 type(overlap_type) :: overlapList(MAXLIST)
3669 type(overlap_type) :: checkList(MAXLIST)
3670 type(overlapspec), pointer :: check =>null()
3671 integer :: nsend, nrecv
3672 integer :: nsend_check, nrecv_check
3673 integer :: iunit
3674
3675 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
3676 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
3677 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
3678 if(size(domain%x(:)) > 1) return
3679
3680 !--- if there is no halo, no need to compute overlaps.
3681 if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
3682
3683 !--- when there is only one tile, n will equal to np
3684 nlist = size(domain%list(:))
3685
3686 select case(position)
3687 case (center)
3688 update => domain%update_T
3689 check => null()
3690 case (corner)
3691 update => domain%update_C
3692 check => domain%check_C
3693 case (east)
3694 update => domain%update_E
3695 check => domain%check_E
3696 case (north)
3697 update => domain%update_N
3698 check => domain%check_N
3699 case default
3700 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west):"//&
3701 & " the value of position should be CENTER, EAST, CORNER or NORTH")
3702 end select
3703
3704 !--- overlap is used to store the overlapping temporarily.
3705 call allocate_update_overlap( overlap, maxoverlap)
3706
3707 !send
3708 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
3709 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
3710 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
3711 update%xbegin = ism; update%xend = iem
3712 update%ybegin = jsm; update%yend = jem
3713 if(ASSOCIATED(check)) then
3714 check%xbegin = ism; check%xend = iem
3715 check%ybegin = jsm; check%yend = jem
3716 endif
3717 update%whalo = domain%whalo; update%ehalo = domain%ehalo
3718 update%shalo = domain%shalo; update%nhalo = domain%nhalo
3719 whalo = domain%whalo; ehalo = domain%ehalo
3720 shalo = domain%shalo; nhalo = domain%nhalo
3721
3722 ioff = ni - ishift
3723 joff = nj - jshift
3724 middle = (jsg+jeg)/2+1
3725 tme = 1; tnbr = 1
3726
3727 if(.NOT. btest(domain%fold,west)) then
3728 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3729 "boundary condition in y-direction should be folded-west for "//trim(domain%name))
3730 endif
3731 if(.NOT. domain%y(tme)%cyclic) then
3732 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3733 "boundary condition in y-direction should be cyclic for "//trim(domain%name))
3734 endif
3735
3736 if(.not. domain%symmetry) then
3737 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_west): "//&
3738 "when west boundary is folded, the domain must be symmetry for "//trim(domain%name))
3739 endif
3740
3741 nsend = 0
3742 nsend_check = 0
3743 do list = 0,nlist-1
3744 m = mod( domain%pos+list, nlist )
3745 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
3746 !to_pe's eastern halo
3747 dir = 1
3748 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3749 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3750 call insert_update_overlap( overlap, domain%list(m)%pe, &
3751 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3752
3753 !to_pe's SE halo
3754 dir = 2
3755 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3756 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3757 if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
3758 js = js+joff; je = je+joff
3759 end if
3760
3761 call insert_update_overlap( overlap, domain%list(m)%pe, &
3762 is, ie, js, je, isc, iec, jsc, jec, dir)
3763
3764 !to_pe's southern halo
3765 dir = 3
3766 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3767 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3768 !--- to make sure the consistence between pes
3769 if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3770 !--- do nothing, this point will come from other pe
3771 else
3772 if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
3773 js = js+joff; je = je+joff
3774 endif
3775
3776 !--- when the west face is folded, the south halo points at
3777 !--- the position should be on CORNER or EAST
3778 if( is == isg .AND. (position == corner .OR. position == east) &
3779 .AND. ( domain%list(m)%y(tnbr)%compute%begin == jsg .OR. &
3780 & domain%list(m)%y(tnbr)%compute%begin-1 .GE. middle)) then
3781 call insert_update_overlap( overlap, domain%list(m)%pe, &
3782 is+1, ie, js, je, isc, iec, jsc, jec, dir)
3783 is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3784 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3785 if ( domain%list(m)%y(tnbr)%compute%begin == jsg ) then
3786 select case (position)
3787 case(east)
3788 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
3789 case(corner)
3790 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
3791 end select
3792 if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
3793 'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error send.' )
3794 else
3795 select case (position)
3796 case(east)
3797 j=js; js = jsg+jeg-je; je = jsg+jeg-j
3798 case(corner)
3799 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3800 end select
3801 end if
3802 call insert_update_overlap( overlap, domain%list(m)%pe, &
3803 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3804 else
3805 call insert_update_overlap( overlap, domain%list(m)%pe, &
3806 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3807 end if
3808 endif
3809
3810 !to_pe's SW halo
3811 dir = 4
3812 folded = .false.
3813 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3814 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
3815 if( jsg.GT.js .AND. je.LT.jsc )then !cyclic offset
3816 js = js+joff; je = je+joff
3817 end if
3818 if( is.LT.isg )then
3819 folded = .true.
3820 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3821 end if
3822 call insert_update_overlap( overlap, domain%list(m)%pe, &
3823 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3824 !--- when south edge is folded, js will be less than jsg when position is EAST and CORNER
3825 if(js .LT. jsg) then
3826 js = js + joff
3827 call insert_update_overlap( overlap, domain%list(m)%pe, &
3828 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3829 endif
3830
3831 !to_pe's western halo
3832 dir = 5
3833 folded = .false.
3834 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3835 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3836 if( isg.GT.is )then
3837 folded = .true.
3838 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3839 end if
3840 !--- when domain symmetry and position is EAST or CORNER, the point when isc == ie,
3841 !--- no need to send, because the data on that point will come from other pe.
3842 !--- come from two pe ( there will be only one point on one pe. ).
3843 if( (position == east .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
3844 !--- do nothing, this point will come from other pe
3845 else
3846 call insert_update_overlap( overlap, domain%list(m)%pe, &
3847 is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
3848 endif
3849 !--- when south edge is folded, ie will be less than isg when position is EAST and CORNER
3850 if(js .LT. jsg) then
3851 js = js + ioff
3852 call insert_update_overlap( overlap, domain%list(m)%pe, &
3853 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
3854 endif
3855
3856 !to_pe's NW halo
3857 dir = 6
3858 folded = .false.
3859 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
3860 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3861 if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
3862 js = js-joff; je = je-joff
3863 end if
3864 if( is.LT.isg )then
3865 folded = .true.
3866 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
3867 end if
3868
3869 call insert_update_overlap( overlap, domain%list(m)%pe, &
3870 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
3871
3872 !to_pe's northern halo
3873 dir = 7
3874 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
3875 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3876 !--- to make sure the consistence between pes
3877 if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
3878 !--- do nothing, this point will come from other pe
3879 else
3880 if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
3881 js = js-joff; je = je-joff
3882 endif
3883 !--- when the west face is folded, the south halo points at
3884 !--- the position should be on CORNER or EAST
3885 if( is == isg .AND. (position == corner .OR. position == east) &
3886 .AND. ( js .GE. middle .AND. domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
3887 call insert_update_overlap( overlap, domain%list(m)%pe, &
3888 is+1, ie, js, je, isc, iec, jsc, jec, dir)
3889 is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3890 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3891 select case (position)
3892 case(east)
3893 j=js; js = jsg+jeg-je; je = jsg+jeg-j
3894 case(corner)
3895 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3896 end select
3897 call insert_update_overlap( overlap, domain%list(m)%pe, &
3898 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3899 else
3900 call insert_update_overlap( overlap, domain%list(m)%pe, &
3901 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
3902 end if
3903 endif
3904
3905 !to_pe's NE halo
3906 dir = 8
3907 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
3908 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
3909 if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
3910 js = js-joff; je = je-joff
3911 end if
3912 call insert_update_overlap( overlap, domain%list(m)%pe, &
3913 is, ie, js, je, isc, iec, jsc, jec, dir)
3914
3915 !--- Now calculate the overlapping for fold-edge.
3916 !--- only position at EAST and CORNER need to be considered
3917 if( ( position == east .OR. position == corner) ) then
3918 !fold is within domain
3919 if( domain%x(tme)%compute%begin-whalo .LE. isg .AND. isg .LE. domain%x(tme)%domain_data%end+ishift )then
3920 dir = 5
3921 !--- calculate the overlapping for sending
3922 if( domain%y(tme)%pos .LT. (size(domain%y(tme)%list(:))+1)/2 )then
3923 is = domain%list(m)%x(tnbr)%compute%begin; ie = is
3924 if( is == isg )then ! fold is within domain.
3925 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
3926 select case (position)
3927 case(east)
3928 js = max(js, middle)
3929 j=js; js = jsg+jeg-je; je = jsg+jeg-j
3930 case(corner)
3931 js = max(js, middle)
3932 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
3933 end select
3934 call insert_update_overlap(overlap, domain%list(m)%pe, &
3935 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
3936 is = max(is, isc); ie = min(ie, iec)
3937 js = max(js, jsc); je = min(je, jec)
3938 if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
3939 nsend_check = nsend_check+1
3940 call allocate_check_overlap(checklist(nsend_check), 1)
3941 call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
3942 tme, 3, one_hundred_eighty, is, ie, js, je)
3943 end if
3944 end if
3945 end if
3946 end if
3947 end if
3948 end if
3949 !--- copy the overlapping information
3950 if( overlap%count > 0) then
3951 nsend = nsend + 1
3952 if(nsend > maxlist) call mpp_error(fatal, &
3953 "mpp_domains_define.inc(compute_overlaps_west): nsend is greater than MAXLIST, increase MAXLIST")
3954 call add_update_overlap(overlaplist(nsend), overlap)
3955 call init_overlap_type(overlap)
3956 endif
3957 end do ! end of send set up.
3958
3959 if(debug_message_passing) then
3960 !--- write out send information
3961 iunit = mpp_pe() + 1000
3962 do m =1,nsend
3963 write(iunit, *) "********to_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
3964 do n = 1, overlaplist(m)%count
3965 write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
3966 overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
3967 enddo
3968 enddo
3969 if(nsend >0) flush(iunit)
3970 endif
3971
3972 ! copy the overlapping information into domain data structure
3973 if(nsend>0) then
3974 update%nsend = nsend
3975 if (associated(update%send)) deallocate(update%send) !< Check if associated
3976 allocate(update%send(nsend))
3977 do m = 1, nsend
3978 call add_update_overlap( update%send(m), overlaplist(m) )
3979 enddo
3980 endif
3981
3982 if(nsend_check>0) then
3983 check%nsend = nsend_check
3984 if (associated(check%send)) deallocate(check%send) !< Check if associated
3985 allocate(check%send(nsend_check))
3986 do m = 1, nsend_check
3987 call add_check_overlap( check%send(m), checklist(m) )
3988 enddo
3989 endif
3990
3991 do m = 1, maxlist
3992 call deallocate_overlap_type(overlaplist(m))
3993 if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
3994 enddo
3995
3996 isgd = isg - domain%whalo
3997 iegd = ieg + domain%ehalo
3998 jsgd = jsg - domain%shalo
3999 jegd = jeg + domain%nhalo
4000
4001 ! begin setting up recv
4002 nrecv = 0
4003 nrecv_check = 0
4004 do list = 0,nlist-1
4005 m = mod( domain%pos+nlist-list, nlist )
4006 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4007 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4008 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4009 !recv_e
4010 dir = 1
4011 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4012 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4013 is=isc; ie=iec; js=jsc; je=jec
4014 call insert_update_overlap( overlap, domain%list(m)%pe, &
4015 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4016
4017 !recv_se
4018 dir = 2
4019 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4020 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4021 is=isc; ie=iec; js=jsc; je=jec
4022 if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4023 js = js-joff; je = je-joff
4024 end if
4025 call insert_update_overlap(overlap, domain%list(m)%pe, &
4026 is, ie, js, je, isd, ied, jsd, jed, dir)
4027
4028 !recv_s
4029 dir = 3
4030 folded = .false.
4031 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4032 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4033 is=isc; ie=iec; js=jsc; je=jec
4034
4035 if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4036 !--- do nothing, this point will come from other pe
4037 else
4038 if( jsd.LT.jsg .AND. js .GT. jed)then
4039 js = js-joff; je = je-joff
4040 end if
4041 !--- when the west face is folded, the south halo points at
4042 !--- the position should be on CORNER or EAST
4043 if( isd == isg .AND. (position == corner .OR. position == east) &
4044 .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4045 call insert_update_overlap( overlap, domain%list(m)%pe, &
4046 is, ie, js, je, isd+1, ied, jsd, jed, dir)
4047 is=isc; ie=iec; js=jsc; je=jec
4048 if(jsd<jsg) then
4049 select case (position)
4050 case(east)
4051 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4052 case(corner)
4053 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4054 end select
4055 if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4056 'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4057 else
4058 select case (position)
4059 case(east)
4060 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4061 case(corner)
4062 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4063 end select
4064 end if
4065 call insert_update_overlap( overlap, domain%list(m)%pe, &
4066 is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4067 else
4068 call insert_update_overlap( overlap, domain%list(m)%pe, &
4069 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4070 end if
4071 endif
4072
4073 !recv_sw
4074 dir = 4
4075 folded = .false.
4076 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4077 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4078 is=isc; ie=iec; js=jsc; je=jec
4079 if( isd.LT.isg )then
4080 folded = .true.
4081 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4082 end if
4083 if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4084 js = js-joff; je = je-joff
4085 end if
4086 call insert_update_overlap(overlap, domain%list(m)%pe, &
4087 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4088 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4089 if(js .LT. jsg ) then
4090 js = js + joff
4091 call insert_update_overlap(overlap, domain%list(m)%pe, &
4092 is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4093 endif
4094
4095 !recv_w
4096 dir = 5
4097 folded = .false.
4098 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4099 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4100 is=isc; ie=iec; js=jsc; je=jec
4101 if( isd.LT.isg )then
4102 folded = .true.
4103 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4104 end if
4105 if( (position == east .OR. position == corner ) .AND. (jsd == je .or. jed == js ) ) then
4106 !--- do nothing, this point will come from other pe
4107 else
4108 call insert_update_overlap(overlap, domain%list(m)%pe, &
4109 is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4110 end if
4111 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4112 if(js .LT. jsg ) then
4113 js = js + joff
4114 call insert_update_overlap(overlap, domain%list(m)%pe, &
4115 is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4116 endif
4117
4118 !recv_nw
4119 dir = 6
4120 folded = .false.
4121 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4122 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4123 is=isc; ie=iec; js=jsc; je=jec
4124 if( isd.LT.isg) then
4125 folded = .true.
4126 call get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4127 end if
4128 if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4129 js = js+joff; je = je+joff
4130 endif
4131
4132 call insert_update_overlap( overlap, domain%list(m)%pe, &
4133 is, ie, js, je, isd, ied, jsd, jed, dir)
4134
4135 !recv_n
4136 dir = 7
4137 folded = .false.
4138 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4139 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4140 is=isc; ie=iec; js=jsc; je=jec
4141 if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4142 !--- do nothing, this point will come from other pe
4143 else
4144 if( jed.GT.jeg .AND. je.LT.jsd)then
4145 js = js+joff; je = je+joff
4146 end if
4147 !--- when the west face is folded, the south halo points at
4148 !--- the position should be on CORNER or EAST
4149 if( isd == isg .AND. (position == corner .OR. position == east) &
4150 .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4151 call insert_update_overlap( overlap, domain%list(m)%pe, &
4152 is, ie, js, je, isd+1, ied, jsd, jed, dir)
4153 is=isc; ie=iec; js=jsc; je=jec
4154 select case (position)
4155 case(east)
4156 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4157 case(corner)
4158 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4159 end select
4160 call insert_update_overlap( overlap, domain%list(m)%pe, &
4161 is, ie, js, je, isd, isd, jsd, jed, dir, .true.)
4162 else
4163 call insert_update_overlap( overlap, domain%list(m)%pe, &
4164 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4165 end if
4166 endif
4167
4168 !recv_ne
4169 dir = 8
4170 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4171 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4172 is=isc; ie=iec; js=jsc; je=jec
4173 if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4174 js = js+joff; je = je+joff
4175 end if
4176 call insert_update_overlap( overlap, domain%list(m)%pe, &
4177 is, ie, js, je, isd, ied, jsd, jed, dir)
4178
4179 !--- Now calculate the overlapping for fold-edge.
4180 !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4181 !--- only position at EAST and CORNER need to be considered
4182 if( ( position == east .OR. position == corner) ) then
4183 !fold is within domain
4184 if( domain%x(tme)%domain_data%begin .LE. isg .AND. isg .LE. domain%x(tme)%domain_data%end+ishift )then
4185 dir = 5
4186 !--- calculating overlapping for receving on north
4187 if( domain%y(tme)%pos .GE. size(domain%y(tme)%list(:))/2 )then
4188 isd = domain%x(tme)%compute%begin; ied = isd
4189 if( isd == isg )then ! fold is within domain.
4190 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4191 is=isc; ie=iec; js = jsc; je = jec
4192 select case (position)
4193 case(east)
4194 jsd = max(jsd, middle)
4195 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4196 case(corner)
4197 jsd = max(jsd, middle)
4198 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4199 end select
4200 call insert_update_overlap(overlap, domain%list(m)%pe, &
4201 is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
4202 is = max(is, isd); ie = min(ie, ied)
4203 js = max(js, jsd); je = min(je, jed)
4204 if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4205 nrecv_check = nrecv_check+1
4206 call allocate_check_overlap(checklist(nrecv_check), 1)
4207 call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
4208 tme, 3, one_hundred_eighty, is, ie, js, je)
4209 endif
4210 endif
4211 endif
4212 endif
4213 endif
4214 endif
4215 !--- copy the overlapping information
4216 if( overlap%count > 0) then
4217 nrecv = nrecv + 1
4218 if(nrecv > maxlist) call mpp_error(fatal, &
4219 "mpp_domains_define.inc(compute_overlaps_west): nrecv is greater than MAXLIST, increase MAXLIST")
4220 call add_update_overlap( overlaplist(nrecv), overlap)
4221 call init_overlap_type(overlap)
4222 endif
4223 enddo ! end of recv do loop
4224
4225 if(debug_message_passing) then
4226 !--- write out send information
4227 iunit = mpp_pe() + 1000
4228 do m =1,nrecv
4229 write(iunit, *) "********from_pe = " ,overlaplist(m)%pe, " count = ",overlaplist(m)%count
4230 do n = 1, overlaplist(m)%count
4231 write(iunit, *) overlaplist(m)%is(n), overlaplist(m)%ie(n), overlaplist(m)%js(n), overlaplist(m)%je(n), &
4232 overlaplist(m)%dir(n), overlaplist(m)%rotation(n)
4233 enddo
4234 enddo
4235 if(nrecv >0) flush(iunit)
4236 endif
4237
4238 ! copy the overlapping information into domain
4239 if(nrecv>0) then
4240 update%nrecv = nrecv
4241 if (associated(update%recv)) deallocate(update%recv) !< Check if associated
4242 allocate(update%recv(nrecv))
4243 do m = 1, nrecv
4244 call add_update_overlap( update%recv(m), overlaplist(m) )
4245 do n = 1, update%recv(m)%count
4246 if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
4247 if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
4248 if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
4249 endif
4250 enddo
4251 enddo
4252 endif
4253
4254 if(nrecv_check>0) then
4255 check%nrecv = nrecv_check
4256 if (associated(check%recv)) deallocate(check%recv) !< Check if associated
4257 allocate(check%recv(nrecv_check))
4258 do m = 1, nrecv_check
4259 call add_check_overlap( check%recv(m), checklist(m) )
4260 enddo
4261 endif
4262
4263 call deallocate_overlap_type(overlap)
4264 do m = 1, maxlist
4265 call deallocate_overlap_type(overlaplist(m))
4266 if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4267 enddo
4268
4269 update=>null()
4270 check=>null()
4271 domain%initialized = .true.
4272
4273 end subroutine compute_overlaps_fold_west
4274
4275 !###############################################################################
4276 !> computes remote domain overlaps
4277 !! assumes only one in each direction
4278 !! will calculate the overlapping for T,E,C,N-cell seperately.
4279 !! here assume fold-east and y-cyclic boundary condition
4280 subroutine compute_overlaps_fold_east( domain, position, ishift, jshift )
4281 type(domain2d), intent(inout) :: domain
4282 integer, intent(in) :: position, ishift, jshift
4283
4284 integer :: j, m, n, nlist, tMe, tNbr, dir
4285 integer :: is, ie, js, je, isc, iec, jsc, jec, isd, ied, jsd
4286 integer :: jed, isg, ieg, jsg, jeg, ioff, joff
4287 integer :: list, middle, ni, nj, isgd, iegd, jsgd, jegd
4288 integer :: ism, iem, jsm, jem, whalo, ehalo, shalo, nhalo
4289 logical :: folded
4290 type(overlap_type) :: overlap
4291 type(overlapspec), pointer :: update=>null()
4292 type(overlap_type) :: overlapList(MAXLIST)
4293 type(overlap_type) :: checkList(MAXLIST)
4294 type(overlapspec), pointer :: check =>null()
4295 integer :: nsend, nrecv
4296 integer :: nsend_check, nrecv_check
4297
4298 !--- since we restrict that if multiple tiles on one pe, all the tiles are limited to this pe.
4299 !--- In this case, if ntiles on this pe is greater than 1, no overlapping between processor within each tile
4300 !--- In this case the overlapping exist only for tMe=1 and tNbr=1
4301 if(size(domain%x(:)) > 1) return
4302
4303 !--- if there is no halo, no need to compute overlaps.
4304 if(domain%whalo==0 .AND. domain%ehalo==0 .AND. domain%shalo==0 .AND. domain%nhalo==0) return
4305
4306 !--- when there is only one tile, n will equal to np
4307 nlist = size(domain%list(:))
4308
4309 select case(position)
4310 case (center)
4311 update => domain%update_T
4312 case (corner)
4313 update => domain%update_C
4314 check => domain%check_C
4315 case (east)
4316 update => domain%update_E
4317 check => domain%check_E
4318 case (north)
4319 update => domain%update_N
4320 check => domain%check_N
4321 case default
4322 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east):"// &
4323 & " the value of position should be CENTER, EAST, CORNER or NORTH")
4324 end select
4325
4326 !--- overlap is used to store the overlapping temporarily.
4327 call allocate_update_overlap( overlap, maxoverlap)
4328
4329 !send
4330 call mpp_get_compute_domain( domain, isc, iec, jsc, jec, position=position )
4331 call mpp_get_global_domain ( domain, isg, ieg, jsg, jeg, xsize=ni, ysize=nj, position=position ) !cyclic offsets
4332 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem, position=position )
4333 update%xbegin = ism; update%xend = iem
4334 update%ybegin = jsm; update%yend = jem
4335 if(ASSOCIATED(check)) then
4336 check%xbegin = ism; check%xend = iem
4337 check%ybegin = jsm; check%yend = jem
4338 endif
4339 update%whalo = domain%whalo; update%ehalo = domain%ehalo
4340 update%shalo = domain%shalo; update%nhalo = domain%nhalo
4341 whalo = domain%whalo; ehalo = domain%ehalo
4342 shalo = domain%shalo; nhalo = domain%nhalo
4343
4344 ioff = ni - ishift
4345 joff = nj - jshift
4346 middle = (jsg+jeg)/2+1
4347 tme = 1; tnbr = 1
4348
4349 if(.NOT. btest(domain%fold,east)) then
4350 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4351 "boundary condition in y-direction should be folded-east for "//trim(domain%name))
4352 endif
4353 if(.NOT. domain%y(tme)%cyclic) then
4354 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4355 "boundary condition in y-direction should be cyclic for "//trim(domain%name))
4356 endif
4357 if(.not. domain%symmetry) then
4358 call mpp_error(fatal, "mpp_domains_define.inc(compute_overlaps_fold_east): "//&
4359 "when east boundary is folded, the domain must be symmetry for "//trim(domain%name))
4360 endif
4361
4362 nsend = 0
4363 nsend_check = 0
4364 do list = 0,nlist-1
4365 m = mod( domain%pos+list, nlist )
4366 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4367 !to_pe's eastern halo
4368 dir = 1
4369 folded = .false.
4370 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4371 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4372 if( ie.GT.ieg )then
4373 folded = .true.
4374 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4375 end if
4376 !--- when domain symmetry and position is EAST or CORNER, the point when jsc == je,
4377 !--- no need to send, because the data on that point will come from other pe.
4378 !--- come from two pe ( there will be only one point on one pe. ).
4379 if( (position == east .OR. position == corner ) .AND. ( jsc == je .or. jec == js ) ) then
4380 !--- do nothing, this point will come from other pe
4381 else
4382 call insert_update_overlap( overlap, domain%list(m)%pe, &
4383 is, ie, js, je, isc, iec, jsc, jec, dir, folded, symmetry=domain%symmetry)
4384 endif
4385 !--- when east edge is folded, js .LT. jsg
4386 if(js .LT. jsg) then
4387 js = js + ioff
4388 call insert_update_overlap( overlap, domain%list(m)%pe, &
4389 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4390 endif
4391
4392 !to_pe's SE halo
4393 dir = 2
4394 folded = .false.
4395 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4396 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4397 if( jsg.GT.js .AND. je.LT.jsc )then !try cyclic offset
4398 js = js+joff; je = je+joff
4399 end if
4400
4401 if( ie.GT.ieg )then
4402 folded = .true.
4403 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4404 end if
4405
4406 call insert_update_overlap( overlap, domain%list(m)%pe, &
4407 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4408 !--- when east edge is folded,
4409 if(js .LT. jsg) then
4410 js = js + joff
4411 call insert_update_overlap( overlap, domain%list(m)%pe, &
4412 is, ie, js, js, isc, iec, jsc, jec, dir, folded)
4413 endif
4414
4415 !to_pe's southern halo
4416 dir = 3
4417 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
4418 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4419 !--- to make sure the consistence between pes
4420 if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
4421 !--- do nothing, this point will come from other pe
4422 else
4423 if( js.LT.jsg .AND. jsc.GT.je) then ! cyclic offset
4424 js = js+joff; je = je+joff
4425 endif
4426 !--- when the east face is folded, the south halo points at
4427 !--- the position should be on CORNER or EAST
4428 if( ie == ieg .AND. (position == corner .OR. position == east) &
4429 .AND. ( domain%list(m)%y(tnbr)%compute%begin == jsg .OR. &
4430 domain%list(m)%y(tnbr)%compute%begin-1 .GE. middle ) ) then
4431 call insert_update_overlap( overlap, domain%list(m)%pe, &
4432 is, ie-1, js, je, isc, iec, jsc, jec, dir)
4433 !--- consider at i = ieg for east edge.
4434 !--- when the data is at corner and not symmetry, j = jsg -1 will get from cyclic condition
4435 if(position == corner .AND. .NOT. domain%symmetry .AND. domain%list(m)%y(tnbr)%compute%begin==jsg)then
4436 call insert_update_overlap(overlap, domain%list(m)%pe, &
4437 ie, ie, je, je, isc, iec, jsc, jec, dir, .true.)
4438 end if
4439
4440 ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4441 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4442 if ( domain%list(m)%y(tnbr)%compute%begin == jsg ) then
4443 select case (position)
4444 case(east)
4445 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4446 case(corner)
4447 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4448 end select
4449 if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4450 'mpp_domains_define.inc(compute_overlaps_fold_east: south edge ubound error send.' )
4451 else
4452 select case (position)
4453 case(east)
4454 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4455 case(corner)
4456 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4457 end select
4458 end if
4459 call insert_update_overlap( overlap, domain%list(m)%pe, &
4460 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4461 else
4462 call insert_update_overlap( overlap, domain%list(m)%pe, &
4463 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4464 end if
4465 endif
4466
4467 !to_pe's SW halo
4468 dir = 4
4469 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4470 js = domain%list(m)%y(tnbr)%compute%begin-shalo; je = domain%list(m)%y(tnbr)%compute%begin-1
4471 if( js.LT.jsg .AND. jsc.GT.je )then ! cyclic is assumed
4472 js = js+joff; je = je+joff
4473 end if
4474 call insert_update_overlap( overlap, domain%list(m)%pe, &
4475 is, ie, js, je, isc, iec, jsc, jec, dir)
4476
4477 !to_pe's western halo
4478 dir = 5
4479 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4480 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4481 call insert_update_overlap( overlap, domain%list(m)%pe, &
4482 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4483
4484 !to_pe's NW halo
4485 dir = 6
4486 is = domain%list(m)%x(tnbr)%compute%begin-whalo; ie = domain%list(m)%x(tnbr)%compute%begin-1
4487 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4488 if( je.GT.jeg .AND. jec.LT.js )then !cyclic offset
4489 js = js-joff; je = je-joff
4490 end if
4491 call insert_update_overlap( overlap, domain%list(m)%pe, &
4492 is, ie, js, je, isc, iec, jsc, jec, dir)
4493
4494 !to_pe's northern halo
4495 dir = 7
4496 folded = .false.
4497 is = domain%list(m)%x(tnbr)%compute%begin; ie = domain%list(m)%x(tnbr)%compute%end+ishift
4498 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4499 !--- to make sure the consistence between pes
4500 if( (position == east .OR. position == corner ) .AND. ( isc == ie .or. iec == is ) ) then
4501 !--- do nothing, this point will come from other pe
4502 else
4503 if( je.GT.jeg .AND. jec.LT.js) then ! cyclic offset
4504 js = js-joff; je = je-joff
4505 endif
4506 !--- when the east face is folded, the north halo points at
4507 !--- the position should be on CORNER or EAST
4508 if( ie == ieg .AND. (position == corner .OR. position == east) &
4509 .AND. ( js .GE. middle .AND. domain%list(m)%y(tnbr)%compute%end+nhalo+jshift .LE. jeg ) ) then
4510 call insert_update_overlap( overlap, domain%list(m)%pe, &
4511 is, ie-1, js, je, isc, iec, jsc, jec, dir)
4512 ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4513 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4514 select case (position)
4515 case(east)
4516 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4517 case(corner)
4518 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4519 end select
4520 call insert_update_overlap( overlap, domain%list(m)%pe, &
4521 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4522 else
4523 call insert_update_overlap( overlap, domain%list(m)%pe, &
4524 is, ie, js, je, isc, iec, jsc, jec, dir, symmetry=domain%symmetry)
4525 end if
4526 endif
4527
4528 !to_pe's NE halo
4529 dir = 8
4530 folded = .false.
4531 is = domain%list(m)%x(tnbr)%compute%end+1+ishift; ie = domain%list(m)%x(tnbr)%compute%end+ehalo+ishift
4532 js = domain%list(m)%y(tnbr)%compute%end+1+jshift; je = domain%list(m)%y(tnbr)%compute%end+nhalo+jshift
4533 if( je.GT.jeg .AND. jec.LT.js )then ! cyclic offset
4534 js = js-joff; je = je-joff
4535 end if
4536 if( ie.GT.ieg )then
4537 folded = .true.
4538 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4539 end if
4540
4541 call insert_update_overlap( overlap, domain%list(m)%pe, &
4542 is, ie, js, je, isc, iec, jsc, jec, dir, folded)
4543
4544 !--- Now calculate the overlapping for fold-edge.
4545 !--- only position at EAST and CORNER need to be considered
4546 if( ( position == east .OR. position == corner) ) then
4547 !fold is within domain
4548 if( domain%x(tme)%domain_data%begin .LE. ieg .AND. ieg .LE. domain%x(tme)%domain_data%end+ishift )then
4549 dir = 1
4550 !--- calculate the overlapping for sending
4551 if( domain%y(tme)%pos .LT. (size(domain%y(tme)%list(:))+1)/2 )then
4552 ie = domain%list(m)%x(tnbr)%compute%end+ishift; is = ie
4553 if( ie == ieg )then ! fold is within domain.
4554 js = domain%list(m)%y(tnbr)%compute%begin; je = domain%list(m)%y(tnbr)%compute%end+jshift
4555 select case (position)
4556 case(east)
4557 js = max(js, middle)
4558 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4559 case(corner)
4560 js = max(js, middle)
4561 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4562 end select
4563 call insert_update_overlap(overlap, domain%list(m)%pe, &
4564 is, ie, js, je, isc, iec, jsc, jec, dir, .true.)
4565 is = max(is, isc); ie = min(ie, iec)
4566 js = max(js, jsc); je = min(je, jec)
4567 if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4568 nsend_check = nsend_check+1
4569 call allocate_check_overlap(checklist(nsend_check), 1)
4570 call insert_check_overlap(checklist(nsend_check), domain%list(m)%pe, &
4571 tme, 1, one_hundred_eighty, is, ie, js, je)
4572 end if
4573 end if
4574 end if
4575 end if
4576 end if
4577 end if
4578 !--- copy the overlapping information
4579 if( overlap%count > 0) then
4580 nsend = nsend + 1
4581 if(nsend > maxlist) call mpp_error(fatal, &
4582 "mpp_domains_define.inc(compute_overlaps_east): nsend is greater than MAXLIST, increase MAXLIST")
4583 call add_update_overlap(overlaplist(nsend), overlap)
4584 call init_overlap_type(overlap)
4585 endif
4586 end do ! end of send set up.
4587
4588 ! copy the overlapping information into domain data structure
4589 if(nsend>0) then
4590 update%nsend = nsend
4591 if (associated(update%send)) deallocate(update%send) !< Check if associated
4592 allocate(update%send(nsend))
4593 do m = 1, nsend
4594 call add_update_overlap( update%send(m), overlaplist(m) )
4595 enddo
4596 endif
4597
4598 if(nsend_check>0) then
4599 check%nsend = nsend_check
4600 if (associated(check%send)) deallocate(check%send) !< Check if associated
4601 allocate(check%send(nsend_check))
4602 do m = 1, nsend_check
4603 call add_check_overlap( check%send(m), checklist(m) )
4604 enddo
4605 endif
4606
4607 do m = 1, maxlist
4608 call deallocate_overlap_type(overlaplist(m))
4609 if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4610 enddo
4611
4612 isgd = isg - domain%whalo
4613 iegd = ieg + domain%ehalo
4614 jsgd = jsg - domain%shalo
4615 jegd = jeg + domain%nhalo
4616
4617 ! begin setting up recv
4618 nrecv = 0
4619 nrecv_check = 0
4620 do list = 0,nlist-1
4621 m = mod( domain%pos+nlist-list, nlist )
4622 if(domain%list(m)%tile_id(tnbr) == domain%tile_id(tme) ) then ! only compute the overlapping within tile.
4623 isc = domain%list(m)%x(1)%compute%begin; iec = domain%list(m)%x(1)%compute%end+ishift
4624 jsc = domain%list(m)%y(1)%compute%begin; jec = domain%list(m)%y(1)%compute%end+jshift
4625 !recv_e
4626 dir = 1
4627 folded = .false.
4628 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4629 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4630 is=isc; ie=iec; js=jsc; je=jec
4631 if( ied.GT.ieg )then
4632 folded = .true.
4633 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4634 end if
4635 if( (position == east .OR. position == corner ) .AND. (jsd == je .or. jed == js ) ) then
4636 !--- do nothing, this point will come from other pe
4637 else
4638 call insert_update_overlap(overlap, domain%list(m)%pe, &
4639 is, ie, js, je, isd, ied, jsd, jed, dir, folded, symmetry=domain%symmetry)
4640 end if
4641 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4642 if(js .LT. jsg ) then
4643 js = js + joff
4644 call insert_update_overlap(overlap, domain%list(m)%pe, &
4645 is, ie, js, js, isd, ied, jsd, jed, dir, folded)
4646 endif
4647
4648 !recv_se
4649 dir = 2
4650 folded = .false.
4651 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4652 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4653 is=isc; ie=iec; js=jsc; je=jec
4654 if( ied.GT.ieg )then
4655 folded = .true.
4656 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4657 end if
4658 if( jsd.LT.jsg .AND. js.GT.jed ) then ! cyclic offset
4659 js = js-joff; je = je-joff
4660 end if
4661 call insert_update_overlap(overlap, domain%list(m)%pe, &
4662 is, ie, js, je, isd, ied, jsd, jed, dir, folded)
4663 !--- when west edge is folded, js will be less than jsg when position is EAST and CORNER
4664 if(js .LT. jsg ) then
4665 js = js + joff
4666 call insert_update_overlap(overlap, domain%list(m)%pe, &
4667 is, ie, js, js, isd, ied, jsd, jed, dir, folded )
4668 endif
4669
4670 !recv_s
4671 dir = 3
4672 folded = .false.
4673 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4674 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4675 is=isc; ie=iec; js=jsc; je=jec
4676
4677 if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4678 !--- do nothing, this point will come from other pe
4679 else
4680 if( jsd.LT.jsg .AND. js .GT. jed)then
4681 js = js-joff; je = je-joff
4682 end if
4683 !--- when the east face is folded, the south halo points at
4684 !--- the position should be on CORNER or EAST
4685 if( ied == ieg .AND. (position == corner .OR. position == east) &
4686 .AND. ( jsd < jsg .OR. jed .GE. middle ) ) then
4687 call insert_update_overlap( overlap, domain%list(m)%pe, &
4688 is, ie, js, je, isd, ied-1, jsd, jed, dir)
4689 is=isc; ie=iec; js=jsc; je=jec
4690 if(jsd<jsg) then
4691 select case (position)
4692 case(east)
4693 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4694 case(corner)
4695 j=js; js = 2*jsg-je-2+2*jshift; je = 2*jsg-j-2+2*jshift
4696 end select
4697 if(je .GT. domain%y(tme)%compute%end+jshift) call mpp_error( fatal, &
4698 'mpp_domains_define.inc(compute_overlaps_fold_west: south edge ubound error recv.' )
4699 else
4700 select case (position)
4701 case(east)
4702 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4703 case(corner)
4704 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4705 end select
4706 end if
4707 call insert_update_overlap( overlap, domain%list(m)%pe, &
4708 is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4709 else
4710 call insert_update_overlap( overlap, domain%list(m)%pe, &
4711 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4712 end if
4713 endif
4714
4715 !recv_sw
4716 dir = 4
4717 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4718 jsd = domain%y(tme)%domain_data%begin; jed = domain%y(tme)%compute%begin-1
4719 is=isc; ie=iec; js=jsc; je=jec
4720 if( jsd.LT.jsg .AND. js.GE.jed )then ! cyclic is assumed
4721 js = js-joff; je = je-joff
4722 end if
4723 call insert_update_overlap(overlap, domain%list(m)%pe, &
4724 is, ie, js, je, isd, ied, jsd, jed, dir)
4725
4726 !recv_w
4727 dir = 5
4728 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4729 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4730 is=isc; ie=iec; js=jsc; je=jec
4731 call insert_update_overlap( overlap, domain%list(m)%pe, &
4732 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4733
4734 !recv_nw
4735 dir = 6
4736 folded = .false.
4737 isd = domain%x(tme)%domain_data%begin; ied = domain%x(tme)%compute%begin-1
4738 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4739 is=isc; ie=iec; js=jsc; je=jec
4740 if( jed.GT.jeg .AND. je.LT.jsd )then ! cyclic offset
4741 js = js+joff; je = je+joff
4742 end if
4743 call insert_update_overlap( overlap, domain%list(m)%pe, &
4744 is, ie, js, je, isd, ied, jsd, jed, dir)
4745
4746 !recv_n
4747 dir = 7
4748 folded = .false.
4749 isd = domain%x(tme)%compute%begin; ied = domain%x(tme)%compute%end+ishift
4750 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4751 is=isc; ie=iec; js=jsc; je=jec
4752 if( (position == east .OR. position == corner ) .AND. ( isd == ie .or. ied == is ) ) then
4753 !--- do nothing, this point will come from other pe
4754 else
4755 if( jed.GT.jeg .AND. je.LT.jsd)then
4756 js = js+joff; je = je+joff
4757 end if
4758 !--- when the east face is folded, the south halo points at
4759 !--- the position should be on CORNER or EAST
4760 if( ied == ieg .AND. (position == corner .OR. position == east) &
4761 .AND. jsd .GE. middle .AND. jed .LE. jeg ) then
4762 call insert_update_overlap( overlap, domain%list(m)%pe, &
4763 is, ie, js, je, isd, ied-1, jsd, jed, dir)
4764 is=isc; ie=iec; js=jsc; je=jec
4765 select case (position)
4766 case(east)
4767 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4768 case(corner)
4769 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4770 end select
4771 call insert_update_overlap( overlap, domain%list(m)%pe, &
4772 is, ie, js, je, ied, ied, jsd, jed, dir, .true.)
4773 else
4774 call insert_update_overlap( overlap, domain%list(m)%pe, &
4775 is, ie, js, je, isd, ied, jsd, jed, dir, symmetry=domain%symmetry)
4776 end if
4777 endif
4778
4779 !recv_ne
4780 dir = 8
4781 folded = .false.
4782 isd = domain%x(tme)%compute%end+1+ishift; ied = domain%x(tme)%domain_data%end+ishift
4783 jsd = domain%y(tme)%compute%end+1+jshift; jed = domain%y(tme)%domain_data%end+jshift
4784 is=isc; ie=iec; js=jsc; je=jec
4785 if( ied.GT.ieg) then
4786 folded = .true.
4787 call get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4788 end if
4789 if( jed.GT.jeg .AND. je.LT.jsd )then !cyclic offset
4790 js = js+joff; je = je+joff
4791 endif
4792
4793 call insert_update_overlap( overlap, domain%list(m)%pe, &
4794 is, ie, js, je, isd, ied, jsd, jed, dir)
4795 !--- Now calculate the overlapping for fold-edge.
4796 !--- for folded-south-edge, only need to consider to_pe's south(3) direction
4797 !--- only position at EAST and CORNER need to be considered
4798 if( ( position == east .OR. position == corner) ) then
4799 !fold is within domain
4800 if( domain%x(tme)%domain_data%begin .LE. ieg .AND. ieg .LE. domain%x(tme)%domain_data%end+ishift )then
4801 dir = 1
4802 !--- calculating overlapping for receving on north
4803 if( domain%y(tme)%pos .GE. size(domain%y(tme)%list(:))/2 )then
4804 ied = domain%x(tme)%compute%end+ishift; isd = ied
4805 if( ied == ieg )then ! fold is within domain.
4806 jsd = domain%y(tme)%compute%begin; jed = domain%y(tme)%compute%end+jshift
4807 is=isc; ie=iec; js = jsc; je = jec
4808 select case (position)
4809 case(east)
4810 jsd = max(jsd, middle)
4811 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4812 case(corner)
4813 jsd = max(jsd, middle)
4814 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4815 end select
4816 call insert_update_overlap(overlap, domain%list(m)%pe, &
4817 is, ie, js, je, isd, ied, jsd, jed, dir, .true.)
4818 is = max(is, isd); ie = min(ie, ied)
4819 js = max(js, jsd); je = min(je, jed)
4820 if(debug_update_level .NE. no_check .AND. ie.GE.is .AND. je.GE.js )then
4821 nrecv_check = nrecv_check+1
4822 call allocate_check_overlap(checklist(nrecv_check), 1)
4823 call insert_check_overlap(checklist(nrecv_check), domain%list(m)%pe, &
4824 tme, 3, one_hundred_eighty, is, ie, js, je)
4825 endif
4826 endif
4827 endif
4828 endif
4829 endif
4830 endif
4831 !--- copy the overlapping information
4832 if( overlap%count > 0) then
4833 nrecv = nrecv + 1
4834 if(nrecv > maxlist) call mpp_error(fatal, &
4835 "mpp_domains_define.inc(compute_overlaps_east): nrecv is greater than MAXLIST, increase MAXLIST")
4836 call add_update_overlap( overlaplist(nrecv), overlap)
4837 call init_overlap_type(overlap)
4838 endif
4839 enddo ! end of recv do loop
4840
4841 ! copy the overlapping information into domain
4842 if(nrecv>0) then
4843 update%nrecv = nrecv
4844 if (associated(update%recv)) deallocate(update%recv) !< Check if associated
4845 allocate(update%recv(nrecv))
4846 do m = 1, nrecv
4847 call add_update_overlap( update%recv(m), overlaplist(m) )
4848 do n = 1, update%recv(m)%count
4849 if(update%recv(m)%tileNbr(n) == domain%tile_id(tme)) then
4850 if(update%recv(m)%dir(n) == 1) domain%x(tme)%loffset = 0
4851 if(update%recv(m)%dir(n) == 7) domain%y(tme)%loffset = 0
4852 endif
4853 enddo
4854 enddo
4855 endif
4856
4857 if(nrecv_check>0) then
4858 check%nrecv = nrecv_check
4859 if (associated(check%recv)) deallocate(check%recv) !< Check if associated
4860 allocate(check%recv(nrecv_check))
4861 do m = 1, nrecv_check
4862 call add_check_overlap( check%recv(m), checklist(m) )
4863 enddo
4864 endif
4865
4866 call deallocate_overlap_type(overlap)
4867 do m = 1, maxlist
4868 call deallocate_overlap_type(overlaplist(m))
4869 if(debug_update_level .NE. no_check) call deallocate_overlap_type(checklist(m))
4870 enddo
4871
4872 update=>null()
4873 check=>null()
4874
4875 domain%initialized = .true.
4876
4877 end subroutine compute_overlaps_fold_east
4878
4879 !#####################################################################################
4880 subroutine get_fold_index_west(jsg, jeg, isg, jshift, position, is, ie, js, je)
4881 integer, intent(in) :: jsg, jeg, isg, jshift, position
4882 integer, intent(inout) :: is, ie, js, je
4883 integer :: i, j
4884
4885 select case(position)
4886 case(center)
4887 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4888 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4889 case(east)
4890 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4891 i=is; is = 2*isg-ie; ie = 2*isg-i
4892 case(north)
4893 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4894 i=is; is = 2*isg-ie-1; ie = 2*isg-i-1
4895 case(corner)
4896 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4897 i=is; is = 2*isg-ie; ie = 2*isg-i
4898 end select
4899
4900 end subroutine get_fold_index_west
4901
4902 !#####################################################################################
4903 subroutine get_fold_index_east(jsg, jeg, ieg, jshift, position, is, ie, js, je)
4904 integer, intent(in) :: jsg, jeg, ieg, jshift, position
4905 integer, intent(inout) :: is, ie, js, je
4906 integer :: i, j
4907
4908 select case(position)
4909 case(center)
4910 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4911 i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4912 case(east)
4913 j=js; js = jsg+jeg-je; je = jsg+jeg-j
4914 i=is; is = 2*ieg-ie; ie = 2*ieg-i
4915 case(north)
4916 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4917 i=is; is = 2*ieg-ie+1; ie = 2*ieg-i+1
4918 case(corner)
4919 j=js; js = jsg+jeg-je-1+jshift; je = jsg+jeg-j-1+jshift
4920 i=is; is = 2*ieg-ie; ie = 2*ieg-i
4921 end select
4922
4923 end subroutine get_fold_index_east
4924
4925 !#####################################################################################
4926 subroutine get_fold_index_south(isg, ieg, jsg, ishift, position, is, ie, js, je)
4927 integer, intent(in) :: isg, ieg, jsg, ishift, position
4928 integer, intent(inout) :: is, ie, js, je
4929 integer :: i, j
4930
4931 select case(position)
4932 case(center)
4933 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4934 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4935 case(east)
4936 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4937 j=js; js = 2*jsg-je-1; je = 2*jsg-j-1
4938 case(north)
4939 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4940 j=js; js = 2*jsg-je; je = 2*jsg-j
4941 case(corner)
4942 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4943 j=js; js = 2*jsg-je; je = 2*jsg-j
4944 end select
4945
4946 end subroutine get_fold_index_south
4947 !#####################################################################################
4948 subroutine get_fold_index_north(isg, ieg, jeg, ishift, position, is, ie, js, je)
4949 integer, intent(in) :: isg, ieg, jeg, ishift, position
4950 integer, intent(inout) :: is, ie, js, je
4951 integer :: i, j
4952
4953 select case(position)
4954 case(center)
4955 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4956 j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4957 case(east)
4958 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4959 j=js; js = 2*jeg-je+1; je = 2*jeg-j+1
4960 case(north)
4961 i=is; is = isg+ieg-ie; ie = isg+ieg-i
4962 j=js; js = 2*jeg-je; je = 2*jeg-j
4963 case(corner)
4964 i=is; is = isg+ieg-ie-1+ishift; ie = isg+ieg-i-1+ishift
4965 j=js; js = 2*jeg-je; je = 2*jeg-j
4966 end select
4967
4968 end subroutine get_fold_index_north
4969
4970
4971 !#####################################################################################
4972 !> add offset to the index
4973 subroutine apply_cyclic_offset(lstart, lend, offset, gstart, gend, gsize)
4974 integer, intent(inout) :: lstart, lend
4975 integer, intent(in ) :: offset, gstart, gend, gsize
4976
4977 lstart = lstart + offset
4978 if(lstart > gend) lstart = lstart - gsize
4979 if(lstart < gstart) lstart = lstart + gsize
4980 lend = lend + offset
4981 if(lend > gend) lend = lend - gsize
4982 if(lend < gstart) lend = lend + gsize
4983
4984 return
4985
4986 end subroutine apply_cyclic_offset
4987
4988 !###################################################################################
4989 !> this routine sets up the overlapping for mpp_update_domains for arbitrary halo update.
4990 !! should be the halo size defined in mpp_define_domains.
4991 !! xhalo_out, yhalo_out should not be exactly the same as xhalo_in, yhalo_in
4992 !! currently we didn't consider about tripolar grid situation, because in the folded north
4993 !! region, the overlapping is specified through list of points, not through rectangular.
4994 !! But will return back to solve this problem in the future.
4995 subroutine set_overlaps(domain, overlap_in, overlap_out, whalo_out, ehalo_out, shalo_out, nhalo_out)
4996 type(domain2d), intent(in) :: domain
4997 type(overlapspec), intent(in) :: overlap_in
4998 type(overlapspec), intent(inout) :: overlap_out
4999 integer, intent(in) :: whalo_out, ehalo_out, shalo_out, nhalo_out
5000 integer :: nlist, m, n, isoff, ieoff, jsoff, jeoff, rotation
5001 integer :: whalo_in, ehalo_in, shalo_in, nhalo_in
5002 integer :: dir
5003 type(overlap_type) :: overlap
5004 type(overlap_type), allocatable :: send(:), recv(:)
5005 type(overlap_type), pointer :: ptrIn => null()
5006 integer :: nsend, nrecv, nsend_in, nrecv_in
5007
5008 if( domain%fold .NE. 0) call mpp_error(fatal, "mpp_domains_define.inc(set_overlaps):"// &
5009 & " folded domain is not implemented for arbitrary halo update, contact developer")
5010
5011 whalo_in = domain%whalo
5012 ehalo_in = domain%ehalo
5013 shalo_in = domain%shalo
5014 nhalo_in = domain%nhalo
5015
5016 if( .NOT. domain%initialized) call mpp_error(fatal, &
5017 "mpp_domains_define.inc: domain is not defined yet")
5018
5019 nlist = size(domain%list(:))
5020 isoff = whalo_in - abs(whalo_out)
5021 ieoff = ehalo_in - abs(ehalo_out)
5022 jsoff = shalo_in - abs(shalo_out)
5023 jeoff = nhalo_in - abs(nhalo_out)
5024
5025 nsend = 0
5026 nsend_in = overlap_in%nsend
5027 nrecv_in = overlap_in%nrecv
5028 if(nsend_in>0) allocate(send(nsend_in))
5029 if(nrecv_in>0) allocate(recv(nrecv_in))
5030 call allocate_update_overlap(overlap, maxoverlap)
5031
5032 overlap_out%whalo = whalo_out
5033 overlap_out%ehalo = ehalo_out
5034 overlap_out%shalo = shalo_out
5035 overlap_out%nhalo = nhalo_out
5036 overlap_out%xbegin = overlap_in%xbegin
5037 overlap_out%xend = overlap_in%xend
5038 overlap_out%ybegin = overlap_in%ybegin
5039 overlap_out%yend = overlap_in%yend
5040
5041 !--- setting up overlap.
5042 do m = 1, nsend_in
5043 ptrin => overlap_in%send(m)
5044 if(ptrin%count .LE. 0) call mpp_error(fatal, "mpp_domains_define.inc(set_overlaps):"// &
5045 " number of overlap for send should be a positive number for"//trim(domain%name) )
5046 do n = 1, ptrin%count
5047 dir = ptrin%dir(n)
5048 rotation = ptrin%rotation(n)
5049 select case(dir)
5050 case(1) ! to_pe's eastern halo
5051 if(ehalo_out > 0) then
5052 call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, 0, n, dir, rotation)
5053 else if(ehalo_out<0) then
5054 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, 0, n, dir, rotation)
5055 end if
5056 case(2) ! to_pe's southeast halo
5057 if(ehalo_out>0 .AND. shalo_out > 0) then
5058 call set_single_overlap(ptrin, overlap, 0, -ieoff, jsoff, 0, n, dir, rotation)
5059 else if(ehalo_out<0 .AND. shalo_out < 0) then ! three parts: southeast, south and east.
5060 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, shalo_out, n, dir, rotation)
5061 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1, rotation)
5062 call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, shalo_out, n, dir+1, rotation)
5063 end if
5064 case(3) ! to_pe's southern halo
5065 if(shalo_out > 0) then
5066 call set_single_overlap(ptrin, overlap, 0, 0, jsoff, 0, n, dir, rotation)
5067 else if(shalo_out<0) then
5068 call set_single_overlap(ptrin, overlap, 0, 0, 0, shalo_out, n, dir, rotation)
5069 end if
5070 case(4) ! to_pe's southwest halo
5071 if(whalo_out>0 .AND. shalo_out > 0) then
5072 call set_single_overlap(ptrin, overlap, isoff, 0, jsoff, 0, n, dir, rotation)
5073 else if(whalo_out<0 .AND. shalo_out < 0) then
5074 call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, shalo_out, n, dir, rotation)
5075 call set_single_overlap(ptrin, overlap, isoff, 0, 0, shalo_out, n, dir-1, rotation)
5076 call set_single_overlap(ptrin, overlap, 0, whalo_out, jsoff, 0, n, dir+1, rotation)
5077 end if
5078 case(5) ! to_pe's western halo
5079 if(whalo_out > 0) then
5080 call set_single_overlap(ptrin, overlap, isoff, 0, 0, 0, n, dir, rotation)
5081 else if(whalo_out<0) then
5082 call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, 0, n, dir, rotation)
5083 end if
5084 case(6) ! to_pe's northwest halo
5085 if(whalo_out>0 .AND. nhalo_out > 0) then
5086 call set_single_overlap(ptrin, overlap, isoff, 0, 0, -jeoff, n, dir, rotation)
5087 else if(whalo_out<0 .AND. nhalo_out < 0) then
5088 call set_single_overlap(ptrin, overlap, 0, whalo_out, -nhalo_out, 0, n, dir, rotation)
5089 call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, -jeoff, n, dir-1, rotation)
5090 call set_single_overlap(ptrin, overlap, isoff, 0, -nhalo_out, 0, n, dir+1, rotation)
5091 end if
5092 case(7) ! to_pe's northern halo
5093 if(nhalo_out > 0) then
5094 call set_single_overlap(ptrin, overlap, 0, 0, 0, -jeoff, n, dir, rotation)
5095 else if(nhalo_out<0) then
5096 call set_single_overlap(ptrin, overlap, 0, 0, -nhalo_out, 0, n, dir, rotation)
5097 end if
5098 case(8) ! to_pe's northeast halo
5099 if(ehalo_out>0 .AND. nhalo_out > 0) then
5100 call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, -jeoff, n, dir, rotation)
5101 else if(ehalo_out<0 .AND. nhalo_out < 0) then
5102 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir, rotation)
5103 call set_single_overlap(ptrin, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1, rotation)
5104 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, -jeoff, n, 1, rotation)
5105 end if
5106 end select
5107 end do ! do n = 1, ptrIn%count
5108 if(overlap%count>0) then
5109 nsend = nsend+1
5110 call add_update_overlap(send(nsend), overlap)
5111 call init_overlap_type(overlap)
5112 endif
5113 end do ! end do list = 0, nlist-1
5114
5115 if(nsend>0) then
5116 overlap_out%nsend = nsend
5117 if (associated(overlap_out%send)) deallocate(overlap_out%send) !< Check if associated
5118 allocate(overlap_out%send(nsend));
5119 do n = 1, nsend
5120 call add_update_overlap(overlap_out%send(n), send(n) )
5121 enddo
5122 else
5123 overlap_out%nsend = 0
5124 endif
5125
5126 !--------------------------------------------------
5127 ! recving
5128 !---------------------------------------------------
5129 overlap%count = 0
5130 nrecv = 0
5131 do m = 1, nrecv_in
5132 ptrin => overlap_in%recv(m)
5133 if(ptrin%count .LE. 0) call mpp_error(fatal, &
5134 "mpp_domains_define.inc(set_overlaps): number of overlap for recv should be a positive number")
5135 overlap%count = 0
5136 do n = 1, ptrin%count
5137 dir = ptrin%dir(n)
5138 rotation = ptrin%rotation(n)
5139 select case(dir)
5140 case(1) ! eastern halo
5141 if(ehalo_out > 0) then
5142 call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, 0, n, dir)
5143 else if(ehalo_out<0) then
5144 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, 0, n, dir)
5145 end if
5146 case(2) ! southeast halo
5147 if(ehalo_out>0 .AND. shalo_out > 0) then
5148 call set_single_overlap(ptrin, overlap, 0, -ieoff, jsoff, 0, n, dir)
5149 else if(ehalo_out<0 .AND. shalo_out < 0) then
5150 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, shalo_out, n, dir)
5151 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, jsoff, 0, n, dir-1)
5152 call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, shalo_out, n, dir+1)
5153 end if
5154 case(3) ! southern halo
5155 if(shalo_out > 0) then
5156 call set_single_overlap(ptrin, overlap, 0, 0, jsoff, 0, n, dir)
5157 else if(shalo_out<0) then
5158 call set_single_overlap(ptrin, overlap, 0, 0, 0, shalo_out, n, dir)
5159 end if
5160 case(4) ! southwest halo
5161 if(whalo_out>0 .AND. shalo_out > 0) then
5162 call set_single_overlap(ptrin, overlap, isoff, 0, jsoff, 0, n, dir)
5163 else if(whalo_out<0 .AND. shalo_out < 0) then
5164 call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, shalo_out, n, dir)
5165 call set_single_overlap(ptrin, overlap, isoff, 0, 0, shalo_out, n, dir-1)
5166 call set_single_overlap(ptrin, overlap, 0, whalo_out, jsoff, 0, n, dir+1)
5167 end if
5168 case(5) ! western halo
5169 if(whalo_out > 0) then
5170 call set_single_overlap(ptrin, overlap, isoff, 0, 0, 0, n, dir)
5171 else if(whalo_out<0) then
5172 call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, 0, n, dir)
5173 end if
5174 case(6) ! northwest halo
5175 if(whalo_out>0 .AND. nhalo_out > 0) then
5176 call set_single_overlap(ptrin, overlap, isoff, 0, 0, -jeoff, n, dir)
5177 else if(whalo_out<0 .AND. nhalo_out < 0) then
5178 call set_single_overlap(ptrin, overlap, 0, whalo_out, -nhalo_out, 0, n, dir)
5179 call set_single_overlap(ptrin, overlap, 0, whalo_out, 0, -jeoff, n, dir-1)
5180 call set_single_overlap(ptrin, overlap, isoff, 0, -nhalo_out, 0, n, dir+1)
5181 end if
5182 case(7) ! northern halo
5183 if(nhalo_out > 0) then
5184 call set_single_overlap(ptrin, overlap, 0, 0, 0, -jeoff, n, dir)
5185 else if(nhalo_out<0) then
5186 call set_single_overlap(ptrin, overlap, 0, 0, -nhalo_out, 0, n, dir)
5187 end if
5188 case(8) ! northeast halo
5189 if(ehalo_out>0 .AND. nhalo_out > 0) then
5190 call set_single_overlap(ptrin, overlap, 0, -ieoff, 0, -jeoff, n, dir)
5191 else if(ehalo_out<0 .AND. nhalo_out < 0) then
5192 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, -nhalo_out, 0, n, dir)
5193 call set_single_overlap(ptrin, overlap, 0, -ieoff, -nhalo_out, 0, n, dir-1)
5194 call set_single_overlap(ptrin, overlap, -ehalo_out, 0, 0, -jeoff, n, 1)
5195 end if
5196 end select
5197 end do ! do n = 1, ptrIn%count
5198 if(overlap%count>0) then
5199 nrecv = nrecv+1
5200 call add_update_overlap(recv(nrecv), overlap)
5201 call init_overlap_type(overlap)
5202 endif
5203 end do ! end do list = 0, nlist-1
5204
5205 if(nrecv>0) then
5206 overlap_out%nrecv = nrecv
5207 if (associated(overlap_out%recv)) deallocate(overlap_out%recv) !< Check if associated
5208 allocate(overlap_out%recv(nrecv));
5209 do n = 1, nrecv
5210 call add_update_overlap(overlap_out%recv(n), recv(n) )
5211 enddo
5212 else
5213 overlap_out%nrecv = 0
5214 endif
5215
5216 call deallocate_overlap_type(overlap)
5217 do n = 1, nsend_in
5218 call deallocate_overlap_type(send(n))
5219 enddo
5220 do n = 1, nrecv_in
5221 call deallocate_overlap_type(recv(n))
5222 enddo
5223 if(allocated(send)) deallocate(send)
5224 if(allocated(recv)) deallocate(recv)
5225 ptrin => null()
5226
5227 call set_domain_comm_inf(overlap_out)
5228
5229
5230 end subroutine set_overlaps
5231
5232 !##############################################################################
5233 subroutine set_single_overlap(overlap_in, overlap_out, isoff, ieoff, jsoff, jeoff, index, dir, rotation)
5234 type(overlap_type), intent(in) :: overlap_in
5235 type(overlap_type), intent(inout) :: overlap_out
5236 integer, intent(in) :: isoff, jsoff, ieoff, jeoff
5237 integer, intent(in) :: index
5238 integer, intent(in) :: dir
5239 integer, optional, intent(in) :: rotation
5240 integer :: rotate
5241 integer :: count
5242
5243 if( overlap_out%pe == null_pe ) then
5244 overlap_out%pe = overlap_in%pe
5245 else
5246 if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(fatal, &
5247 "mpp_domains_define.inc(set_single_overlap): mismatch of pe between overlap_in and overlap_out")
5248 endif
5249
5250 if(isoff .NE. 0 .and. ieoff .NE. 0) call mpp_error(fatal, &
5251 "mpp_domains_define.inc(set_single_overlap): both isoff and ieoff are non-zero")
5252 if(jsoff .NE. 0 .and. jeoff .NE. 0) call mpp_error(fatal, &
5253 "mpp_domains_define.inc(set_single_overlap): both jsoff and jeoff are non-zero")
5254
5255
5256 overlap_out%count = overlap_out%count + 1
5257 count = overlap_out%count
5258 if(count > maxoverlap) call mpp_error(fatal, &
5259 "set_single_overlap: number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
5260 rotate = zero
5261 if(present(rotation)) rotate = rotation
5262 overlap_out%rotation (count) = overlap_in%rotation(index)
5263 overlap_out%dir (count) = dir
5264 overlap_out%tileMe (count) = overlap_in%tileMe(index)
5265 overlap_out%tileNbr (count) = overlap_in%tileNbr(index)
5266
5267 select case(rotate)
5268 case(zero)
5269 overlap_out%is(count) = overlap_in%is(index) + isoff
5270 overlap_out%ie(count) = overlap_in%ie(index) + ieoff
5271 overlap_out%js(count) = overlap_in%js(index) + jsoff
5272 overlap_out%je(count) = overlap_in%je(index) + jeoff
5273 case(ninety)
5274 overlap_out%is(count) = overlap_in%is(index) - jeoff
5275 overlap_out%ie(count) = overlap_in%ie(index) - jsoff
5276 overlap_out%js(count) = overlap_in%js(index) + isoff
5277 overlap_out%je(count) = overlap_in%je(index) + ieoff
5278 case(minus_ninety)
5279 overlap_out%is(count) = overlap_in%is(index) + jsoff
5280 overlap_out%ie(count) = overlap_in%ie(index) + jeoff
5281 overlap_out%js(count) = overlap_in%js(index) - ieoff
5282 overlap_out%je(count) = overlap_in%je(index) - isoff
5283 case default
5284 call mpp_error(fatal, "mpp_domains_define.inc: the value of rotation should be ZERO, NINETY or MINUS_NINETY")
5285 end select
5286
5287 end subroutine set_single_overlap
5288
5289 !###################################################################################
5290 !> compute the overlapping between tiles for the T-cell.
5291 subroutine define_contact_point( domain, position, num_contact, tile1, tile2, align1, align2, &
5292 refine1, refine2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, &
5293 isgList, iegList, jsgList, jegList )
5294 type(domain2d), intent(inout) :: domain
5295 integer, intent(in) :: position
5296 integer, intent(in) :: num_contact !< number of contact regions
5297 integer, dimension(:), intent(in) :: tile1, tile2 !< tile number
5298 integer, dimension(:), intent(in) :: align1, align2 !< align direction of contact region
5299 real, dimension(:), intent(in) :: refine1, refine2 !< refinement between tiles
5300 integer, dimension(:), intent(in) :: istart1, iend1 !< i-index in tile_1 of contact region
5301 integer, dimension(:), intent(in) :: jstart1, jend1 !< j-index in tile_1 of contact region
5302 integer, dimension(:), intent(in) :: istart2, iend2 !< i-index in tile_2 of contact region
5303 integer, dimension(:), intent(in) :: jstart2, jend2 !< j-index in tile_2 of contact region
5304 integer, dimension(:), intent(in) :: isgList, iegList !< i-global domain of each tile
5305 integer, dimension(:), intent(in) :: jsgList, jegList !< j-global domain of each tile
5306
5307 integer :: isc, iec, jsc, jec, isd, ied, jsd, jed
5308 integer :: isc1, iec1, jsc1, jec1, isc2, iec2, jsc2, jec2
5309 integer :: isd1, ied1, jsd1, jed1, isd2, ied2, jsd2, jed2
5310 integer :: is, ie, js, je, ioff, joff
5311 integer :: ntiles, max_contact
5312 integer :: nlist, list, m, n, l, count, numS, numR
5313 integer :: whalo, ehalo, shalo, nhalo
5314 integer :: t1, t2, tt, pos
5315 integer :: ntileMe, ntileNbr, tMe, tNbr, tileMe, dir
5316 integer :: nxd, nyd, nxc, nyc, ism, iem, jsm, jem
5317 integer :: dirlist(8)
5318 !--- is2Send and is1Send will figure out the overlapping for sending from current pe.
5319 !--- is1Recv and iscREcv will figure out the overlapping for recving onto current pe.
5320 integer, dimension(4*num_contact) :: is1Send, ie1Send, js1Send, je1Send
5321 integer, dimension(4*num_contact) :: is2Send, ie2Send, js2Send, je2Send
5322 integer, dimension(4*num_contact) :: is2Recv, ie2Recv, js2Recv, je2Recv
5323 integer, dimension(4*num_contact) :: is1Recv, ie1Recv, js1Recv, je1Recv
5324 integer, dimension(4*num_contact) :: align1Recv, align2Recv, align1Send, align2Send
5325 real, dimension(4*num_contact) :: refineRecv, refineSend
5326 integer, dimension(4*num_contact) :: rotateSend, rotateRecv, tileSend, tileRecv
5327 integer :: nsend, nrecv, nsend2, nrecv2
5328 type(contact_type), dimension(domain%ntiles) :: eCont, wCont, sCont, nCont
5329 type(overlap_type), dimension(0:size(domain%list(:))-1) :: overlapSend, overlapRecv
5330 integer :: iunit
5331
5332 if( position .NE. center ) call mpp_error(fatal, "mpp_domains_define.inc: " //&
5333 "routine define_contact_point can only be used to calculate overlapping for cell center.")
5334
5335 ntiles = domain%ntiles
5336
5337 econt(:)%ncontact = 0
5338
5339 do n = 1, ntiles
5340 econt(n)%ncontact = 0; scont(n)%ncontact = 0; wcont(n)%ncontact = 0; ncont(n)%ncontact = 0;
5341 allocate(econt(n)%tile(num_contact), wcont(n)%tile(num_contact) )
5342 allocate(ncont(n)%tile(num_contact), scont(n)%tile(num_contact) )
5343 allocate(econt(n)%align1(num_contact), econt(n)%align2(num_contact) )
5344 allocate(wcont(n)%align1(num_contact), wcont(n)%align2(num_contact) )
5345 allocate(scont(n)%align1(num_contact), scont(n)%align2(num_contact) )
5346 allocate(ncont(n)%align1(num_contact), ncont(n)%align2(num_contact) )
5347 allocate(econt(n)%refine1(num_contact), econt(n)%refine2(num_contact) )
5348 allocate(wcont(n)%refine1(num_contact), wcont(n)%refine2(num_contact) )
5349 allocate(scont(n)%refine1(num_contact), scont(n)%refine2(num_contact) )
5350 allocate(ncont(n)%refine1(num_contact), ncont(n)%refine2(num_contact) )
5351 allocate(econt(n)%is1(num_contact), econt(n)%ie1(num_contact), econt(n)%js1(num_contact), &
5352 & econt(n)%je1(num_contact))
5353 allocate(econt(n)%is2(num_contact), econt(n)%ie2(num_contact), econt(n)%js2(num_contact), &
5354 & econt(n)%je2(num_contact))
5355 allocate(wcont(n)%is1(num_contact), wcont(n)%ie1(num_contact), wcont(n)%js1(num_contact), &
5356 & wcont(n)%je1(num_contact))
5357 allocate(wcont(n)%is2(num_contact), wcont(n)%ie2(num_contact), wcont(n)%js2(num_contact), &
5358 & wcont(n)%je2(num_contact))
5359 allocate(scont(n)%is1(num_contact), scont(n)%ie1(num_contact), scont(n)%js1(num_contact), &
5360 & scont(n)%je1(num_contact))
5361 allocate(scont(n)%is2(num_contact), scont(n)%ie2(num_contact), scont(n)%js2(num_contact), &
5362 & scont(n)%je2(num_contact))
5363 allocate(ncont(n)%is1(num_contact), ncont(n)%ie1(num_contact), ncont(n)%js1(num_contact), &
5364 & ncont(n)%je1(num_contact))
5365 allocate(ncont(n)%is2(num_contact), ncont(n)%ie2(num_contact), ncont(n)%js2(num_contact), &
5366 & ncont(n)%je2(num_contact))
5367 end do
5368
5369 !--- set up the east, south, west and north contact for each tile.
5370 do n = 1, num_contact
5371 t1 = tile1(n)
5372 t2 = tile2(n)
5373 select case(align1(n))
5374 case (east)
5375 call fill_contact( econt(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5376 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5377 case (west)
5378 call fill_contact( wcont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5379 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5380 case (south)
5381 call fill_contact( scont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5382 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5383 case (north)
5384 call fill_contact( ncont(t1), t2, istart1(n), iend1(n), jstart1(n), jend1(n), istart2(n), iend2(n), &
5385 jstart2(n), jend2(n), align1(n), align2(n), refine1(n), refine2(n))
5386 end select
5387 select case(align2(n))
5388 case (east)
5389 call fill_contact( econt(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5390 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5391 case (west)
5392 call fill_contact( wcont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5393 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5394 case (south)
5395 call fill_contact( scont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5396 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5397 case (north)
5398 call fill_contact( ncont(t2), t1, istart2(n), iend2(n), jstart2(n), jend2(n), istart1(n), iend1(n), &
5399 jstart1(n), jend1(n), align2(n), align1(n), refine2(n), refine1(n))
5400 end select
5401 end do
5402
5403 !--- the tile number of current pe, halo size
5404 whalo = domain%whalo
5405 ehalo = domain%ehalo
5406 shalo = domain%shalo
5407 nhalo = domain%nhalo
5408
5409 !--- find if there is an extra point in x and y direction depending on position
5410 nlist = size(domain%list(:))
5411
5412 max_contact = 4*num_contact ! should be enough
5413
5414 ntileme = size(domain%x(:))
5415 refinesend = 1; refinerecv = 1
5416
5417 !--------------------------------------------------------------------------------------------------
5418 ! loop over each tile on current domain to set up the overlapping for each tile
5419 !--------------------------------------------------------------------------------------------------
5420 !--- first check the overlap within the tiles.
5421 do n = 1, domain%update_T%nsend
5422 pos = domain%update_T%send(n)%pe - mpp_root_pe()
5423 call add_update_overlap(overlapsend(pos), domain%update_T%send(n) )
5424 enddo
5425 do n = 1, domain%update_T%nrecv
5426 pos = domain%update_T%recv(n)%pe - mpp_root_pe()
5427 call add_update_overlap(overlaprecv(pos), domain%update_T%recv(n) )
5428 enddo
5429
5430 call mpp_get_memory_domain(domain, ism, iem, jsm, jem)
5431 domain%update_T%xbegin = ism; domain%update_T%xend = iem
5432 domain%update_T%ybegin = jsm; domain%update_T%yend = jem
5433 domain%update_T%whalo = whalo; domain%update_T%ehalo = ehalo
5434 domain%update_T%shalo = shalo; domain%update_T%nhalo = nhalo
5435
5436 do tme = 1, ntileme
5437 tileme = domain%tile_id(tme)
5438 rotatesend = zero; rotaterecv = zero
5439
5440 !--- loop over all the contact region to figure out the index for overlapping region.
5441 count = 0
5442 do n = 1, econt(tileme)%ncontact ! east contact
5443 count = count+1
5444 tilerecv(count) = econt(tileme)%tile(n); tilesend(count) = econt(tileme)%tile(n)
5445 align1recv(count) = econt(tileme)%align1(n); align2recv(count) = econt(tileme)%align2(n)
5446 align1send(count) = econt(tileme)%align1(n); align2send(count) = econt(tileme)%align2(n)
5447 refinesend(count) = econt(tileme)%refine2(n); refinerecv(count) = econt(tileme)%refine1(n)
5448 is1recv(count) = econt(tileme)%is1(n) + 1; ie1recv(count) = is1recv(count) + ehalo - 1
5449 js1recv(count) = econt(tileme)%js1(n); je1recv(count) = econt(tileme)%je1(n)
5450 select case(econt(tileme)%align2(n))
5451 case ( west ) ! w <-> e
5452 is2recv(count) = econt(tileme)%is2(n); ie2recv(count) = is2recv(count) + ehalo - 1
5453 js2recv(count) = econt(tileme)%js2(n); je2recv(count) = econt(tileme)%je2(n)
5454 ie1send(count) = econt(tileme)%is1(n); is1send(count) = ie1send(count) - whalo + 1
5455 js1send(count) = econt(tileme)%js1(n); je1send(count) = econt(tileme)%je1(n)
5456 ie2send(count) = econt(tileme)%is2(n) - 1; is2send(count) = ie2send(count) - whalo + 1
5457 js2send(count) = econt(tileme)%js2(n); je2send(count) = econt(tileme)%je2(n)
5458 case ( south ) ! s <-> e
5459 rotaterecv(count) = ninety; rotatesend(count) = minus_ninety
5460 js2recv(count) = econt(tileme)%js2(n); je2recv(count) = js2recv(count) + ehalo -1
5461 is2recv(count) = econt(tileme)%is2(n); ie2recv(count) = econt(tileme)%ie2(n)
5462 ie1send(count) = econt(tileme)%is1(n); is1send(count) = ie1send(count) - shalo + 1
5463 js1send(count) = econt(tileme)%js1(n); je1send(count) = econt(tileme)%je1(n)
5464 is2send(count) = econt(tileme)%is2(n); ie2send(count) = econt(tileme)%ie2(n)
5465 je2send(count) = econt(tileme)%js2(n) - 1; js2send(count) = je2send(count) - shalo + 1
5466 end select
5467 end do
5468
5469 do n = 1, scont(tileme)%ncontact ! south contact
5470 count = count+1
5471 tilerecv(count) = scont(tileme)%tile(n); tilesend(count) = scont(tileme)%tile(n)
5472 align1recv(count) = scont(tileme)%align1(n); align2recv(count) = scont(tileme)%align2(n);
5473 align1send(count) = scont(tileme)%align1(n); align2send(count) = scont(tileme)%align2(n);
5474 refinesend(count) = scont(tileme)%refine2(n); refinerecv(count) = scont(tileme)%refine1(n)
5475 is1recv(count) = scont(tileme)%is1(n); ie1recv(count) = scont(tileme)%ie1(n)
5476 je1recv(count) = scont(tileme)%js1(n) - 1; js1recv(count) = je1recv(count) - shalo + 1
5477 select case(scont(tileme)%align2(n))
5478 case ( north ) ! n <-> s
5479 is2recv(count) = scont(tileme)%is2(n); ie2recv(count) = scont(tileme)%ie2(n)
5480 je2recv(count) = scont(tileme)%je2(n); js2recv(count) = je2recv(count) - shalo + 1
5481 is1send(count) = scont(tileme)%is1(n); ie1send(count) = scont(tileme)%ie1(n)
5482 js1send(count) = scont(tileme)%js1(n); je1send(count) = js1send(count) + nhalo -1
5483 is2send(count) = scont(tileme)%is2(n); ie2send(count) = scont(tileme)%ie2(n)
5484 js2send(count) = scont(tileme)%je2(n)+1; je2send(count) = js2send(count) + nhalo - 1
5485 case ( east ) ! e <-> s
5486 rotaterecv(count) = minus_ninety; rotatesend(count) = ninety
5487 ie2recv(count) = scont(tileme)%ie2(n); is2recv(count) = ie2recv(count) - shalo + 1
5488 js2recv(count) = scont(tileme)%js2(n); je2recv(count) = scont(tileme)%je2(n)
5489 is1send(count) = scont(tileme)%is1(n); ie1send(count) = scont(tileme)%ie1(n)
5490 js1send(count) = scont(tileme)%js1(n); je1send(count) = js1send(count) + ehalo - 1
5491 is2send(count) = scont(tileme)%ie2(n)+1; ie2send(count) = is2send(count) + ehalo - 1
5492 js2send(count) = scont(tileme)%js2(n); je2send(count) = scont(tileme)%je2(n)
5493 end select
5494 end do
5495
5496 do n = 1, wcont(tileme)%ncontact ! west contact
5497 count = count+1
5498 tilerecv(count) = wcont(tileme)%tile(n); tilesend(count) = wcont(tileme)%tile(n)
5499 align1recv(count) = wcont(tileme)%align1(n); align2recv(count) = wcont(tileme)%align2(n);
5500 align1send(count) = wcont(tileme)%align1(n); align2send(count) = wcont(tileme)%align2(n);
5501 refinesend(count) = wcont(tileme)%refine2(n); refinerecv(count) = wcont(tileme)%refine1(n)
5502 ie1recv(count) = wcont(tileme)%is1(n) - 1; is1recv(count) = ie1recv(count) - whalo + 1
5503 js1recv(count) = wcont(tileme)%js1(n); je1recv(count) = wcont(tileme)%je1(n)
5504 select case(wcont(tileme)%align2(n))
5505 case ( east ) ! e <-> w
5506 ie2recv(count) = wcont(tileme)%ie2(n); is2recv(count) = ie2recv(count) - whalo + 1
5507 js2recv(count) = wcont(tileme)%js2(n); je2recv(count) = wcont(tileme)%je2(n)
5508 is1send(count) = wcont(tileme)%is1(n); ie1send(count) = is1send(count) + ehalo - 1
5509 js1send(count) = wcont(tileme)%js1(n); je1send(count) = wcont(tileme)%je1(n)
5510 is2send(count) = wcont(tileme)%ie2(n)+1; ie2send(count) = is2send(count) + ehalo - 1
5511 js2send(count) = wcont(tileme)%js2(n); je2send(count) = wcont(tileme)%je2(n)
5512 case ( north ) ! n <-> w
5513 rotaterecv(count) = ninety; rotatesend(count) = minus_ninety
5514 je2recv(count) = wcont(tileme)%je2(n); js2recv(count) = je2recv(count) - whalo + 1
5515 is2recv(count) = wcont(tileme)%is2(n); ie2recv(count) = wcont(tileme)%ie2(n)
5516 is1send(count) = wcont(tileme)%is1(n); ie1send(count) = is1send(count) + nhalo - 1
5517 js1send(count) = wcont(tileme)%js1(n); je1send(count) = wcont(tileme)%je1(n)
5518 js2send(count) = wcont(tileme)%je2(n)+1; je2send(count) = js2send(count) + nhalo - 1
5519 is2send(count) = wcont(tileme)%is2(n); ie2send(count) = wcont(tileme)%ie2(n)
5520 end select
5521 end do
5522
5523 do n = 1, ncont(tileme)%ncontact ! north contact
5524 count = count+1
5525 tilerecv(count) = ncont(tileme)%tile(n); tilesend(count) = ncont(tileme)%tile(n)
5526 align1recv(count) = ncont(tileme)%align1(n); align2recv(count) = ncont(tileme)%align2(n);
5527 align1send(count) = ncont(tileme)%align1(n); align2send(count) = ncont(tileme)%align2(n);
5528 refinesend(count) = ncont(tileme)%refine2(n); refinerecv(count) = ncont(tileme)%refine1(n)
5529 is1recv(count) = ncont(tileme)%is1(n); ie1recv(count) = ncont(tileme)%ie1(n)
5530 js1recv(count) = ncont(tileme)%je1(n)+1; je1recv(count) = js1recv(count) + nhalo - 1
5531 select case(ncont(tileme)%align2(n))
5532 case ( south ) ! s <-> n
5533 is2recv(count) = ncont(tileme)%is2(n); ie2recv(count) = ncont(tileme)%ie2(n)
5534 js2recv(count) = ncont(tileme)%js2(n); je2recv(count) = js2recv(count) + nhalo - 1
5535 is1send(count) = ncont(tileme)%is1(n); ie1send(count) = ncont(tileme)%ie1(n)
5536 je1send(count) = ncont(tileme)%je1(n); js1send(count) = je1send(count) - shalo + 1
5537 is2send(count) = ncont(tileme)%is2(n); ie2send(count) = ncont(tileme)%ie2(n)
5538 je2send(count) = ncont(tileme)%js2(n)-1; js2send(count) = je2send(count) - shalo + 1
5539 case ( west ) ! w <-> n
5540 rotaterecv(count) = minus_ninety; rotatesend(count) = ninety
5541 is2recv(count) = ncont(tileme)%ie2(n); ie2recv(count) = is2recv(count) + nhalo - 1
5542 js2recv(count) = ncont(tileme)%js2(n); je2recv(count) = ncont(tileme)%je2(n)
5543 is1send(count) = ncont(tileme)%is1(n); ie1send(count) = ncont(tileme)%ie1(n)
5544 je1send(count) = ncont(tileme)%je1(n); js1send(count) = je1send(count) - whalo + 1
5545 ie2send(count) = ncont(tileme)%is2(n)-1; is2send(count) = ie2send(count) - whalo + 1
5546 js2send(count) = ncont(tileme)%js2(n); je2send(count) = ncont(tileme)%je2(n)
5547 end select
5548 end do
5549
5550 nums = count
5551 numr = count
5552 !--- figure out the index for corner overlapping,
5553 !--- fill_corner_contact will be updated to deal with the situation that there are multiple tiles on
5554 !--- each side of six sides of cubic grid.
5555 if(.NOT. domain%rotated_ninety) then
5556 call fill_corner_contact(econt, scont, wcont, ncont, isglist, ieglist, jsglist, jeglist, numr, nums, &
5557 tilerecv, tilesend, is1recv, ie1recv, js1recv, je1recv, is2recv, ie2recv, &
5558 js2recv, je2recv, is1send, ie1send, js1send, je1send, is2send, ie2send, &
5559 js2send, je2send, align1recv, align2recv, align1send, align2send, &
5560 whalo, ehalo, shalo, nhalo, tileme )
5561 end if
5562
5563 isc = domain%x(tme)%compute%begin; iec = domain%x(tme)%compute%end
5564 jsc = domain%y(tme)%compute%begin; jec = domain%y(tme)%compute%end
5565
5566 !--- compute the overlapping for send.
5567 do n = 1, nums
5568 do list = 0, nlist-1
5569 m = mod( domain%pos+list, nlist )
5570 ntilenbr = size(domain%list(m)%x(:))
5571 do tnbr = 1, ntilenbr
5572 if( domain%list(m)%tile_id(tnbr) .NE. tilesend(n) ) cycle
5573 isc1 = max(isc, is1send(n)); iec1 = min(iec, ie1send(n))
5574 jsc1 = max(jsc, js1send(n)); jec1 = min(jec, je1send(n))
5575 if( isc1 > iec1 .OR. jsc1 > jec1 ) cycle
5576 !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5577 do dir = 1, 8
5578 !--- get the to_pe's data domain.
5579 select case ( dir )
5580 case ( 1 ) ! eastern halo
5581 if( align2send(n) .NE. east ) cycle
5582 isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5583 jsd = domain%list(m)%y(tnbr)%compute%begin; jed = domain%list(m)%y(tnbr)%compute%end
5584 case ( 2 ) ! southeast halo
5585 isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5586 jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5587 case ( 3 ) ! southern halo
5588 if( align2send(n) .NE. south ) cycle
5589 isd = domain%list(m)%x(tnbr)%compute%begin; ied = domain%list(m)%x(tnbr)%compute%end
5590 jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5591 case ( 4 ) ! southwest halo
5592 isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5593 jsd = domain%list(m)%y(tnbr)%compute%begin-shalo; jed = domain%list(m)%y(tnbr)%compute%begin-1
5594 case ( 5 ) ! western halo
5595 if( align2send(n) .NE. west ) cycle
5596 isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5597 jsd = domain%list(m)%y(tnbr)%compute%begin; jed = domain%list(m)%y(tnbr)%compute%end
5598 case ( 6 ) ! northwest halo
5599 isd = domain%list(m)%x(tnbr)%compute%begin-whalo; ied = domain%list(m)%x(tnbr)%compute%begin-1
5600 jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5601 case ( 7 ) ! northern halo
5602 if( align2send(n) .NE. north ) cycle
5603 isd = domain%list(m)%x(tnbr)%compute%begin; ied = domain%list(m)%x(tnbr)%compute%end
5604 jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5605 case ( 8 ) ! northeast halo
5606 isd = domain%list(m)%x(tnbr)%compute%end+1; ied = domain%list(m)%x(tnbr)%compute%end+ehalo
5607 jsd = domain%list(m)%y(tnbr)%compute%end+1; jed = domain%list(m)%y(tnbr)%compute%end+nhalo
5608 end select
5609 isd = max(isd, is2send(n)); ied = min(ied, ie2send(n))
5610 jsd = max(jsd, js2send(n)); jed = min(jed, je2send(n))
5611 if( isd > ied .OR. jsd > jed ) cycle
5612 ioff = 0; joff = 0
5613 nxd = ied - isd + 1
5614 nyd = jed - jsd + 1
5615 select case ( align2send(n) )
5616 case ( west, east )
5617 ioff = isd - is2send(n)
5618 joff = jsd - js2send(n)
5619 case ( south, north )
5620 ioff = isd - is2send(n)
5621 joff = jsd - js2send(n)
5622 end select
5623
5624 !--- get the index in current pe.
5625 select case ( rotatesend(n) )
5626 case ( zero )
5627 isc2 = is1send(n) + ioff; iec2 = isc2 + nxd - 1
5628 jsc2 = js1send(n) + joff; jec2 = jsc2 + nyd - 1
5629 case ( ninety ) ! N -> W or S -> E
5630 iec2 = ie1send(n) - joff; isc2 = iec2 - nyd + 1
5631 jsc2 = js1send(n) + ioff; jec2 = jsc2 + nxd - 1
5632 case ( minus_ninety ) ! W -> N or E -> S
5633 isc2 = is1send(n) + joff; iec2 = isc2 + nyd - 1
5634 jec2 = je1send(n) - ioff; jsc2 = jec2 - nxd + 1
5635 end select
5636 is = max(isc1,isc2); ie = min(iec1,iec2)
5637 js = max(jsc1,jsc2); je = min(jec1,jec2)
5638 if(ie.GE.is .AND. je.GE.js )then
5639 if(.not. associated(overlapsend(m)%tileMe)) call allocate_update_overlap(overlapsend(m), &
5640 & maxoverlap)
5641 call insert_overlap_type(overlapsend(m), domain%list(m)%pe, tme, tnbr, &
5642 is, ie, js, je, dir, rotatesend(n), .true. )
5643 endif
5644 end do ! end do dir = 1, 8
5645 end do ! end do tNbr = 1, ntileNbr
5646 end do ! end do list = 0, nlist-1
5647 end do ! end do n = 1, numS
5648
5649 !--- compute the overlapping for recv.
5650 do n = 1, numr
5651 do list = 0, nlist-1
5652 m = mod( domain%pos+nlist-list, nlist )
5653 ntilenbr = size(domain%list(m)%x(:))
5654 do tnbr = 1, ntilenbr
5655 if( domain%list(m)%tile_id(tnbr) .NE. tilerecv(n) ) cycle
5656 isc = domain%list(m)%x(tnbr)%compute%begin; iec = domain%list(m)%x(tnbr)%compute%end
5657 jsc = domain%list(m)%y(tnbr)%compute%begin; jec = domain%list(m)%y(tnbr)%compute%end
5658 isc = max(isc, is2recv(n)); iec = min(iec, ie2recv(n))
5659 jsc = max(jsc, js2recv(n)); jec = min(jec, je2recv(n))
5660 if( isc > iec .OR. jsc > jec ) cycle
5661 !--- find the offset for this overlapping.
5662 ioff = 0; joff = 0
5663 nxc = iec - isc + 1; nyc = jec - jsc + 1
5664 select case ( align2recv(n) )
5665 case ( west, east )
5666 if(align2recv(n) == west) then
5667 ioff = isc - is2recv(n)
5668 else
5669 ioff = ie2recv(n) - iec
5670 endif
5671 joff = jsc - js2recv(n)
5672 case ( north, south )
5673 ioff = isc - is2recv(n)
5674 if(align2recv(n) == south) then
5675 joff = jsc - js2recv(n)
5676 else
5677 joff = je2recv(n) - jec
5678 endif
5679 end select
5680
5681 !--- get the index in current pe.
5682 select case ( rotaterecv(n) )
5683 case ( zero )
5684 isd1 = is1recv(n) + ioff; ied1 = isd1 + nxc - 1
5685 jsd1 = js1recv(n) + joff; jed1 = jsd1 + nyc - 1
5686 if( align1recv(n) == west ) then
5687 ied1 = ie1recv(n)-ioff; isd1 = ied1 - nxc + 1
5688 endif
5689 if( align1recv(n) == south ) then
5690 jed1 = je1recv(n)-joff; jsd1 = jed1 - nyc + 1
5691 endif
5692 case ( ninety ) ! N -> W or S -> E
5693 if( align1recv(n) == west ) then
5694 ied1 = ie1recv(n)-joff; isd1 = ied1 - nyc + 1
5695 else
5696 isd1 = is1recv(n)+joff; ied1 = isd1 + nyc - 1
5697 endif
5698 jed1 = je1recv(n) - ioff; jsd1 = jed1 - nxc + 1
5699 case ( minus_ninety ) ! W -> N or E -> S
5700 ied1 = ie1recv(n) - joff; isd1 = ied1 - nyc + 1
5701 if( align1recv(n) == south ) then
5702 jed1 = je1recv(n)-ioff; jsd1 = jed1 - nxc + 1
5703 else
5704 jsd1 = js1recv(n)+ioff; jed1 = jsd1 + nxc - 1
5705 endif
5706 end select
5707
5708 !--- loop over 8 direction to get the overlapping starting from east with clockwise.
5709 do dir = 1, 8
5710 select case ( dir )
5711 case ( 1 ) ! eastern halo
5712 if( align1recv(n) .NE. east ) cycle
5713 isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5714 jsd2 = domain%y(tme)%compute%begin; jed2 = domain%y(tme)%compute%end
5715 case ( 2 ) ! southeast halo
5716 isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5717 jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5718 case ( 3 ) ! southern halo
5719 if( align1recv(n) .NE. south ) cycle
5720 isd2 = domain%x(tme)%compute%begin; ied2 = domain%x(tme)%compute%end
5721 jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5722 case ( 4 ) ! southwest halo
5723 isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5724 jsd2 = domain%y(tme)%domain_data%begin; jed2 = domain%y(tme)%compute%begin-1
5725 case ( 5 ) ! western halo
5726 if( align1recv(n) .NE. west ) cycle
5727 isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5728 jsd2 = domain%y(tme)%compute%begin; jed2 = domain%y(tme)%compute%end
5729 case ( 6 ) ! northwest halo
5730 isd2 = domain%x(tme)%domain_data%begin; ied2 = domain%x(tme)%compute%begin-1
5731 jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5732 case ( 7 ) ! northern halo
5733 if( align1recv(n) .NE. north ) cycle
5734 isd2 = domain%x(tme)%compute%begin; ied2 = domain%x(tme)%compute%end
5735 jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5736 case ( 8 ) ! northeast halo
5737 isd2 = domain%x(tme)%compute%end+1; ied2 = domain%x(tme)%domain_data%end
5738 jsd2 = domain%y(tme)%compute%end+1; jed2 = domain%y(tme)%domain_data%end
5739 end select
5740 is = max(isd1,isd2); ie = min(ied1,ied2)
5741 js = max(jsd1,jsd2); je = min(jed1,jed2)
5742 if(ie.GE.is .AND. je.GE.js )then
5743 if(.not. associated(overlaprecv(m)%tileMe)) call allocate_update_overlap(overlaprecv(m), &
5744 & maxoverlap)
5745 call insert_overlap_type(overlaprecv(m), domain%list(m)%pe, tme, tnbr, &
5746 is, ie, js, je, dir, rotaterecv(n), .true.)
5747 count = overlaprecv(m)%count
5748 endif
5749 end do ! end do dir = 1, 8
5750 end do ! end do tNbr = 1, ntileNbr
5751 end do ! end do list = 0, nlist-1
5752 end do ! end do n = 1, numR
5753 end do ! end do tMe = 1, ntileMe
5754
5755 !--- copy the overlapping information into domain data
5756 nsend = 0; nsend2 = 0
5757 do list = 0, nlist-1
5758 m = mod( domain%pos+list, nlist )
5759 if(overlapsend(m)%count>0) nsend = nsend + 1
5760 enddo
5761
5762 if(debug_message_passing) then
5763 !--- write out send information
5764 iunit = mpp_pe() + 1000
5765 do list = 0, nlist-1
5766 m = mod( domain%pos+list, nlist )
5767 if(overlapsend(m)%count==0) cycle
5768 write(iunit, *) "********to_pe = " ,overlapsend(m)%pe, " count = ",overlapsend(m)%count
5769 do n = 1, overlapsend(m)%count
5770 write(iunit, *) overlapsend(m)%is(n), overlapsend(m)%ie(n), overlapsend(m)%js(n), overlapsend(m)%je(n), &
5771 overlapsend(m)%dir(n), overlapsend(m)%rotation(n)
5772 enddo
5773 enddo
5774 if(nsend >0) flush(iunit)
5775 endif
5776
5777 dirlist(1) = 1; dirlist(2) = 3; dirlist(3) = 5; dirlist(4) = 7
5778 dirlist(5) = 2; dirlist(6) = 4; dirlist(7) = 6; dirlist(8) = 8
5779
5780 ! copy the overlap information into domain.
5781 if(nsend >0) then
5782 if(associated(domain%update_T%send)) then
5783 do m = 1, domain%update_T%nsend
5784 call deallocate_overlap_type(domain%update_T%send(m))
5785 enddo
5786 deallocate(domain%update_T%send)
5787 endif
5788 domain%update_T%nsend = nsend
5789 allocate(domain%update_T%send(nsend))
5790 do list = 0, nlist-1
5791 m = mod( domain%pos+list, nlist )
5792 ntilenbr = size(domain%list(m)%x(:))
5793 !--- for the send, the list should be in tileNbr order and dir order to be consistent with Recv
5794 if(overlapsend(m)%count > 0) then
5795 nsend2 = nsend2+1
5796 if(nsend2>nsend) call mpp_error(fatal, &
5797 "mpp_domains_define.inc(define_contact_point): nsend2 is greater than nsend")
5798 call allocate_update_overlap(domain%update_T%send(nsend2), overlapsend(m)%count)
5799
5800 do tnbr = 1, ntilenbr
5801 do tt = 1, ntileme
5802 if(domain%list(m)%pe == domain%pe) then ! own processor
5803 tme = tnbr+tt-1
5804 if(tme > ntileme) tme = tme - ntileme
5805 else
5806 tme = tt
5807 end if
5808 do n = 1, 8 ! loop over 8 direction
5809 do l = 1, overlapsend(m)%count
5810 if(overlapsend(m)%tileMe(l) .NE. tme) cycle
5811 if(overlapsend(m)%tileNbr(l) .NE. tnbr) cycle
5812 if(overlapsend(m)%dir(l) .NE. dirlist(n) ) cycle
5813 call insert_overlap_type(domain%update_T%send(nsend2), overlapsend(m)%pe, &
5814 overlapsend(m)%tileMe(l), overlapsend(m)%tileNbr(l), overlapsend(m)%is(l), &
5815 overlapsend(m)%ie(l), overlapsend(m)%js(l), overlapsend(m)%je(l), overlapsend(m)%dir(l),&
5816 overlapsend(m)%rotation(l), overlapsend(m)%from_contact(l) )
5817 end do
5818 end do
5819 end do
5820 end do
5821 end if
5822 enddo
5823 endif
5824
5825 if(nsend2 .NE. nsend) call mpp_error(fatal, &
5826 "mpp_domains_define.inc(define_contact_point): nsend2 does not equal to nsend")
5827
5828 nrecv = 0; nrecv2 = 0
5829 do list = 0, nlist-1
5830 m = mod( domain%pos+list, nlist )
5831 if(overlaprecv(m)%count>0) nrecv = nrecv + 1
5832 enddo
5833
5834 if(debug_message_passing) then
5835 do list = 0, nlist-1
5836 m = mod( domain%pos+list, nlist )
5837 if(overlaprecv(m)%count==0) cycle
5838 write(iunit, *) "********from_pe = " ,overlaprecv(m)%pe, " count = ",overlaprecv(m)%count
5839 do n = 1, overlaprecv(m)%count
5840 write(iunit, *) overlaprecv(m)%is(n), overlaprecv(m)%ie(n), overlaprecv(m)%js(n), overlaprecv(m)%je(n), &
5841 overlaprecv(m)%dir(n), overlaprecv(m)%rotation(n)
5842 enddo
5843 enddo
5844 if(nrecv >0) flush(iunit)
5845 endif
5846
5847 if(nrecv >0) then
5848 if(associated(domain%update_T%recv)) then
5849 do m = 1, domain%update_T%nrecv
5850 call deallocate_overlap_type(domain%update_T%recv(m))
5851 enddo
5852 deallocate(domain%update_T%recv)
5853 endif
5854 domain%update_T%nrecv = nrecv
5855 allocate(domain%update_T%recv(nrecv))
5856
5857 do list = 0, nlist-1
5858 m = mod( domain%pos+nlist-list, nlist )
5859 ntilenbr = size(domain%list(m)%x(:))
5860 if(overlaprecv(m)%count > 0) then
5861 nrecv2 = nrecv2 + 1
5862 if(nrecv2>nrecv) call mpp_error(fatal, &
5863 "mpp_domains_define.inc(define_contact_point): nrecv2 is greater than nrecv")
5864 call allocate_update_overlap(domain%update_T%recv(nrecv2), overlaprecv(m)%count)
5865 do tme = 1, ntileme
5866 do tt = 1, ntilenbr
5867 !--- make sure the same order tile for different pe count
5868 if(domain%list(m)%pe == domain%pe) then ! own processor
5869 tnbr = tme+tt-1
5870 if(tnbr>ntilenbr) tnbr = tnbr - ntilenbr
5871 else
5872 tnbr = tt
5873 end if
5874 do n = 1, 8 ! loop over 8 direction
5875 do l = 1, overlaprecv(m)%count
5876 if(overlaprecv(m)%tileMe(l) .NE. tme) cycle
5877 if(overlaprecv(m)%tileNbr(l) .NE. tnbr) cycle
5878 if(overlaprecv(m)%dir(l) .NE. dirlist(n) ) cycle
5879 call insert_overlap_type(domain%update_T%recv(nrecv2), overlaprecv(m)%pe, &
5880 overlaprecv(m)%tileMe(l), overlaprecv(m)%tileNbr(l), overlaprecv(m)%is(l), &
5881 overlaprecv(m)%ie(l), overlaprecv(m)%js(l), overlaprecv(m)%je(l), overlaprecv(m)%dir(l),&
5882 overlaprecv(m)%rotation(l), overlaprecv(m)%from_contact(l))
5883 count = domain%update_T%recv(nrecv2)%count
5884 end do
5885 end do
5886 end do
5887 end do
5888 end if
5889 end do
5890 endif
5891
5892 if(nrecv2 .NE. nrecv) call mpp_error(fatal, &
5893 "mpp_domains_define.inc(define_contact_point): nrecv2 does not equal to nrecv")
5894
5895 do m = 0,nlist-1
5896 call deallocate_overlap_type(overlapsend(m))
5897 call deallocate_overlap_type(overlaprecv(m))
5898 enddo
5899 !--- release memory
5900 do n = 1, ntiles
5901 deallocate(econt(n)%tile, wcont(n)%tile, scont(n)%tile, ncont(n)%tile )
5902 deallocate(econt(n)%align1, wcont(n)%align1, scont(n)%align1, ncont(n)%align1)
5903 deallocate(econt(n)%align2, wcont(n)%align2, scont(n)%align2, ncont(n)%align2)
5904 deallocate(econt(n)%refine1, wcont(n)%refine1, scont(n)%refine1, ncont(n)%refine1)
5905 deallocate(econt(n)%refine2, wcont(n)%refine2, scont(n)%refine2, ncont(n)%refine2)
5906 deallocate(econt(n)%is1, econt(n)%ie1, econt(n)%js1, econt(n)%je1 )
5907 deallocate(econt(n)%is2, econt(n)%ie2, econt(n)%js2, econt(n)%je2 )
5908 deallocate(wcont(n)%is1, wcont(n)%ie1, wcont(n)%js1, wcont(n)%je1 )
5909 deallocate(wcont(n)%is2, wcont(n)%ie2, wcont(n)%js2, wcont(n)%je2 )
5910 deallocate(scont(n)%is1, scont(n)%ie1, scont(n)%js1, scont(n)%je1 )
5911 deallocate(scont(n)%is2, scont(n)%ie2, scont(n)%js2, scont(n)%je2 )
5912 deallocate(ncont(n)%is1, ncont(n)%ie1, ncont(n)%js1, ncont(n)%je1 )
5913 deallocate(ncont(n)%is2, ncont(n)%ie2, ncont(n)%js2, ncont(n)%je2 )
5914 end do
5915
5916 domain%initialized = .true.
5917
5918
5919 end subroutine define_contact_point
5920
5921!##############################################################################
5922!> always fill the contact according to index order.
5923subroutine fill_contact(Contact, tile, is1, ie1, js1, je1, is2, ie2, js2, je2, align1, align2, refine1, refine2 )
5924 type(contact_type), intent(inout) :: Contact
5925 integer, intent(in) :: tile
5926 integer, intent(in) :: is1, ie1, js1, je1
5927 integer, intent(in) :: is2, ie2, js2, je2
5928 integer, intent(in) :: align1, align2
5929 real, intent(in) :: refine1, refine2
5930 integer :: pos, n
5931
5932 do pos = 1, contact%ncontact
5933 select case(align1)
5934 case(west, east)
5935 if( js1 < contact%js1(pos) ) exit
5936 case(south, north)
5937 if( is1 < contact%is1(pos) ) exit
5938 end select
5939 end do
5940
5941 contact%ncontact = contact%ncontact + 1
5942 do n = contact%ncontact, pos+1, -1 ! shift the data if needed.
5943 contact%tile(n) = contact%tile(n-1)
5944 contact%align1(n) = contact%align1(n-1)
5945 contact%align2(n) = contact%align2(n-1)
5946 contact%is1(n) = contact%is1(n-1); contact%ie1(n) = contact%ie1(n-1)
5947 contact%js1(n) = contact%js1(n-1); contact%je1(n) = contact%je1(n-1)
5948 contact%is2(n) = contact%is2(n-1); contact%ie2(n) = contact%ie2(n-1)
5949 contact%js2(n) = contact%js2(n-1); contact%je2(n) = contact%je2(n-1)
5950 end do
5951
5952 contact%tile(pos) = tile
5953 contact%align1(pos) = align1
5954 contact%align2(pos) = align2
5955 contact%refine1(pos) = refine1
5956 contact%refine2(pos) = refine2
5957 contact%is1(pos) = is1; contact%ie1(pos) = ie1
5958 contact%js1(pos) = js1; contact%je1(pos) = je1
5959 contact%is2(pos) = is2; contact%ie2(pos) = ie2
5960 contact%js2(pos) = js2; contact%je2(pos) = je2
5961
5962end subroutine fill_contact
5963
5964!############################################################################
5965!> this routine sets the overlapping between tiles for E,C,N-cell based on T-cell overlapping
5966subroutine set_contact_point(domain, position)
5967 type(domain2d), intent(inout) :: domain
5968 integer, intent(in) :: position
5969
5970 integer :: ishift, jshift, nlist, list, m, n
5971 integer :: ntileMe, tMe, dir, count, pos, nsend, nrecv
5972 integer :: isoff1, ieoff1, jsoff1, jeoff1
5973 type(overlap_type), pointer :: ptrIn => null()
5974 type(overlapspec), pointer :: update_in => null()
5975 type(overlapspec), pointer :: update_out => null()
5976 type(overlap_type) :: overlapList(0:size(domain%list(:))-1)
5977 type(overlap_type) :: overlap
5978
5979 call mpp_get_domain_shift(domain, ishift, jshift, position)
5980 update_in => domain%update_T
5981 select case(position)
5982 case (corner)
5983 update_out => domain%update_C
5984 case (east)
5985 update_out => domain%update_E
5986 case (north)
5987 update_out => domain%update_N
5988 case default
5989 call mpp_error(fatal, "mpp_domains_define.inc(set_contact_point): the position should be CORNER, EAST or NORTH")
5990 end select
5991
5992 update_out%xbegin = update_in%xbegin; update_out%xend = update_in%xend + ishift
5993 update_out%ybegin = update_in%ybegin; update_out%yend = update_in%yend + jshift
5994 update_out%whalo = update_in%whalo; update_out%ehalo = update_in%ehalo
5995 update_out%shalo = update_in%shalo; update_out%nhalo = update_in%nhalo
5996
5997 nlist = size(domain%list(:))
5998 ntileme = size(domain%x(:))
5999 call allocate_update_overlap(overlap, maxoverlap)
6000 do m = 0, nlist-1
6001 call init_overlap_type(overlaplist(m))
6002 enddo
6003
6004 !--- first copy the send information in update_out to send
6005 nsend = update_out%nsend
6006 do m = 1, nsend
6007 pos = update_out%send(m)%pe - mpp_root_pe()
6008 call add_update_overlap(overlaplist(pos), update_out%send(m))
6009 call deallocate_overlap_type(update_out%send(m))
6010 enddo
6011 if(ASSOCIATED(update_out%send) )deallocate(update_out%send)
6012
6013 !--- loop over the list of overlapping.
6014 nsend = update_in%nsend
6015 do m = 1, nsend
6016 ptrin => update_in%send(m)
6017 pos = ptrin%pe - mpp_root_pe()
6018 do n = 1, ptrin%count
6019 dir = ptrin%dir(n)
6020 ! only set overlapping between tiles for send ( ptrOut%overlap(1) is false )
6021 if(ptrin%from_contact(n)) then
6022 select case ( dir )
6023 case ( 1 ) ! to_pe's eastern halo
6024 select case(ptrin%rotation(n))
6025 case (zero) ! W -> E
6026 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6027 case (ninety) ! S -> E
6028 isoff1 = 0; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6029 end select
6030 case ( 2 ) ! to_pe's south-eastearn halo
6031 select case(ptrin%rotation(n))
6032 case (zero)
6033 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6034 case (ninety)
6035 isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6036 case (minus_ninety)
6037 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6038 end select
6039 case ( 3 ) ! to_pe's southern halo
6040 select case(ptrin%rotation(n))
6041 case (zero) ! N -> S
6042 isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6043 case (minus_ninety) ! E -> S
6044 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = ishift
6045 end select
6046 case ( 4 ) ! to_pe's south-westearn halo
6047 select case(ptrin%rotation(n))
6048 case (zero)
6049 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6050 case (ninety)
6051 isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6052 case (minus_ninety)
6053 isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6054 end select
6055 case ( 5 ) ! to_pe's western halo
6056 select case(ptrin%rotation(n))
6057 case (zero) ! E -> W
6058 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6059 case (ninety) ! N -> W
6060 isoff1 = 0; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6061 end select
6062 case ( 6 ) ! to_pe's north-westearn halo
6063 select case(ptrin%rotation(n))
6064 case (zero)
6065 isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6066 case (ninety)
6067 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6068 case (minus_ninety)
6069 isoff1 = jshift; ieoff1 = jshift; jsoff1 = ishift; jeoff1 = ishift
6070 end select
6071 case ( 7 ) ! to_pe's northern halo
6072 select case(ptrin%rotation(n))
6073 case (zero) ! S -> N
6074 isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6075 case (minus_ninety) ! W -> N
6076 isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = ishift
6077 end select
6078 case ( 8 ) ! to_pe's north-eastearn halo
6079 select case(ptrin%rotation(n))
6080 case (zero)
6081 isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6082 case (ninety)
6083 isoff1 = 0; ieoff1 = 0; jsoff1 = ishift; jeoff1 = ishift
6084 case (minus_ninety)
6085 isoff1 = jshift; ieoff1 = jshift; jsoff1 = 0; jeoff1 = 0
6086 end select
6087 end select
6088 call insert_overlap_type(overlap, ptrin%pe, ptrin%tileMe(n), ptrin%tileNbr(n), &
6089 ptrin%is(n) + isoff1, ptrin%ie(n) + ieoff1, ptrin%js(n) + jsoff1, &
6090 ptrin%je(n) + jeoff1, ptrin%dir(n), ptrin%rotation(n), ptrin%from_contact(n))
6091 end if
6092 end do ! do n = 1, prtIn%count
6093 if(overlap%count > 0) then
6094 call add_update_overlap(overlaplist(pos), overlap)
6095 call init_overlap_type(overlap)
6096 endif
6097 end do ! do list = 0, nlist-1
6098
6099 nsend = 0
6100 do list = 0, nlist-1
6101 m = mod( domain%pos+list, nlist )
6102 if(overlaplist(m)%count>0) nsend = nsend+1
6103 enddo
6104
6105 update_out%nsend = nsend
6106 if(nsend>0) then
6107 if (associated(update_out%send)) deallocate(update_out%send) !< Check if associated
6108 allocate(update_out%send(nsend))
6109 pos = 0
6110 do list = 0, nlist-1
6111 m = mod( domain%pos+list, nlist )
6112 if(overlaplist(m)%count>0) then
6113 pos = pos+1
6114 if(pos>nsend) call mpp_error(fatal, &
6115 "mpp_domains_define.inc(set_contact_point): pos should be no larger than nsend")
6116 call add_update_overlap(update_out%send(pos), overlaplist(m))
6117 call deallocate_overlap_type(overlaplist(m))
6118 endif
6119 enddo
6120 if(pos .NE. nsend) call mpp_error(fatal, &
6121 "mpp_domains_define.inc(set_contact_point): pos should equal to nsend")
6122 endif
6123
6124
6125
6126 !--- first copy the recv information in update_out to recv
6127 nrecv = update_out%nrecv
6128 do m = 1, nrecv
6129 pos = update_out%recv(m)%pe - mpp_root_pe()
6130 call add_update_overlap(overlaplist(pos), update_out%recv(m))
6131 call deallocate_overlap_type(update_out%recv(m))
6132 enddo
6133 if(ASSOCIATED(update_out%recv) )deallocate(update_out%recv)
6134
6135 !--- loop over the list of overlapping.
6136 nrecv = update_in%nrecv
6137 do m=1,nrecv
6138 ptrin => update_in%recv(m)
6139 pos = ptrin%pe - mpp_root_pe()
6140 do n = 1, ptrin%count
6141 dir = ptrin%dir(n)
6142 ! only set overlapping between tiles for recv ( ptrOut%overlap(1) is false )
6143 if(ptrin%from_contact(n)) then
6144 select case ( dir )
6145 case ( 1 ) ! E
6146 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = jshift
6147 case ( 2 ) ! SE
6148 isoff1 = ishift; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6149 case ( 3 ) ! S
6150 isoff1 = 0; ieoff1 = ishift; jsoff1 = 0; jeoff1 = 0
6151 case ( 4 ) ! SW
6152 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = 0
6153 case ( 5 ) ! W
6154 isoff1 = 0; ieoff1 = 0; jsoff1 = 0; jeoff1 = jshift
6155 case ( 6 ) ! NW
6156 isoff1 = 0; ieoff1 = 0; jsoff1 = jshift; jeoff1 = jshift
6157 case ( 7 ) ! N
6158 isoff1 = 0; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6159 case ( 8 ) ! NE
6160 isoff1 = ishift; ieoff1 = ishift; jsoff1 = jshift; jeoff1 = jshift
6161 end select
6162 call insert_overlap_type(overlap, ptrin%pe, ptrin%tileMe(n), ptrin%tileNbr(n), &
6163 ptrin%is(n) + isoff1, ptrin%ie(n) + ieoff1, ptrin%js(n) + jsoff1, &
6164 ptrin%je(n) + jeoff1, ptrin%dir(n), ptrin%rotation(n), ptrin%from_contact(n))
6165 count = overlap%count
6166 end if
6167 end do ! do n = 1, ptrIn%count
6168 if(overlap%count > 0) then
6169 call add_update_overlap(overlaplist(pos), overlap)
6170 call init_overlap_type(overlap)
6171 endif
6172 do tme = 1, size(domain%x(:))
6173 do n = 1, overlap%count
6174 if(overlap%tileMe(n) == tme) then
6175 if(overlap%dir(n) == 1 ) domain%x(tme)%loffset = 0
6176 if(overlap%dir(n) == 7 ) domain%y(tme)%loffset = 0
6177 end if
6178 end do
6179 end do
6180 end do ! do list = 0, nlist-1
6181
6182 nrecv = 0
6183 do list = 0, nlist-1
6184 m = mod( domain%pos+nlist-list, nlist )
6185 if(overlaplist(m)%count>0) nrecv = nrecv+1
6186 enddo
6187
6188 update_out%nrecv = nrecv
6189 if(nrecv>0) then
6190 if (associated(update_out%recv)) deallocate(update_out%recv) !< Check if associated
6191 allocate(update_out%recv(nrecv))
6192 pos = 0
6193 do list = 0, nlist-1
6194 m = mod( domain%pos+nlist-list, nlist )
6195 if(overlaplist(m)%count>0) then
6196 pos = pos+1
6197 if(pos>nrecv) call mpp_error(fatal, &
6198 "mpp_domains_define.inc(set_contact_point): pos should be no larger than nrecv")
6199 call add_update_overlap(update_out%recv(pos), overlaplist(m))
6200 call deallocate_overlap_type(overlaplist(m))
6201 endif
6202 enddo
6203 if(pos .NE. nrecv) call mpp_error(fatal, &
6204 "mpp_domains_define.inc(set_contact_point): pos should equal to nrecv")
6205 endif
6206
6207 call deallocate_overlap_type(overlap)
6208
6209end subroutine set_contact_point
6210
6211!> set up the overlapping for boundary check if the domain is symmetry. The check will be
6212!! done on current pe for east boundary for E-cell, north boundary for N-cell,
6213!! East and North boundary for C-cell
6214subroutine set_check_overlap( domain, position )
6215type(domain2d), intent(in) :: domain
6216integer, intent(in) :: position
6217integer :: nlist, m, n
6218integer, parameter :: MAXCOUNT = 100
6219integer :: is, ie, js, je
6220integer :: nsend, nrecv, pos, maxsize, rotation
6221type(overlap_type) :: overlap
6222type(overlapspec), pointer :: update => null()
6223type(overlapspec), pointer :: check => null()
6224
6225select case(position)
6226case (corner)
6227 update => domain%update_C
6228 check => domain%check_C
6229case (east)
6230 update => domain%update_E
6231 check => domain%check_E
6232case (north)
6233 update => domain%update_N
6234 check => domain%check_N
6235case default
6236 call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): position should be CORNER, EAST or NORTH")
6237end select
6238
6239check%xbegin = update%xbegin; check%xend = update%xend
6240check%ybegin = update%ybegin; check%yend = update%yend
6241check%nsend = 0
6242check%nrecv = 0
6243if( .NOT. domain%symmetry ) return
6244
6245nsend = 0
6246maxsize = 0
6247do m = 1, update%nsend
6248 do n = 1, update%send(m)%count
6249 if( update%send(m)%rotation(n) == one_hundred_eighty ) cycle
6250 if( ( (position == east .OR. position == corner) .AND. update%send(m)%dir(n) == 1 ) .OR. &
6251 ( (position == north .OR. position == corner) .AND. update%send(m)%dir(n) == 7 ) ) then
6252 maxsize = max(maxsize, update%send(m)%count)
6253 nsend = nsend + 1
6254 exit
6255 endif
6256 enddo
6257enddo
6258
6259if(nsend>0) then
6260 if (associated(check%send)) deallocate(check%send) !< Check if associated
6261 allocate(check%send(nsend))
6262 call allocate_check_overlap(overlap, maxsize)
6263endif
6264
6265
6266nlist = size(domain%list(:))
6267!--- loop over the list of domains to find the boundary overlap for send
6268pos = 0
6269do m = 1, update%nsend
6270 do n = 1, update%send(m)%count
6271 if( update%send(m)%rotation(n) == one_hundred_eighty ) cycle
6272 ! comparing east direction on currently pe
6273 if( (position == east .OR. position == corner) .AND. update%send(m)%dir(n) == 1 ) then
6274 rotation = update%send(m)%rotation(n)
6275 select case( rotation )
6276 case( zero ) ! W -> E
6277 is = update%send(m)%is(n) - 1
6278 ie = is
6279 js = update%send(m)%js(n)
6280 je = update%send(m)%je(n)
6281 case( ninety ) ! S -> E
6282 is = update%send(m)%is(n)
6283 ie = update%send(m)%ie(n)
6284 js = update%send(m)%js(n) - 1
6285 je = js
6286 end select
6287 call insert_check_overlap(overlap, update%send(m)%pe, &
6288 update%send(m)%tileMe(n), 1, rotation, is, ie, js, je)
6289 end if
6290
6291 ! comparing north direction on currently pe
6292 if( (position == north .OR. position == corner) .AND. update%send(m)%dir(n) == 7 ) then
6293 rotation = update%send(m)%rotation(n)
6294 select case( rotation )
6295 case( zero ) ! S->N
6296 is = update%send(m)%is(n)
6297 ie = update%send(m)%ie(n)
6298 js = update%send(m)%js(n) - 1
6299 je = js
6300 case( minus_ninety ) ! W->N
6301 is = update%send(m)%is(n) - 1
6302 ie = is
6303 js = update%send(m)%js(n)
6304 je = update%send(m)%je(n)
6305 end select
6306 call insert_check_overlap(overlap, update%send(m)%pe, &
6307 update%send(m)%tileMe(n), 4, rotation, is, ie, js, je)
6308 end if
6309 end do ! do n =1, update%send(m)%count
6310 if(overlap%count>0) then
6311 pos = pos+1
6312 if(pos>nsend)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6313 call add_check_overlap(check%send(pos), overlap)
6314 call init_overlap_type(overlap)
6315 endif
6316end do ! end do list = 0, nlist
6317
6318if(pos .NE. nsend)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nsend")
6319
6320nrecv = 0
6321maxsize = 0
6322do m = 1, update%nrecv
6323 do n = 1, update%recv(m)%count
6324 if( update%recv(m)%rotation(n) == one_hundred_eighty ) cycle
6325 if( ( (position == east .OR. position == corner) .AND. update%recv(m)%dir(n) == 1 ) .OR. &
6326 ( (position == north .OR. position == corner) .AND. update%recv(m)%dir(n) == 7 ) ) then
6327 maxsize = max(maxsize, update%recv(m)%count)
6328 nrecv = nrecv + 1
6329 exit
6330 endif
6331 enddo
6332enddo
6333
6334if(nsend>0) call deallocate_overlap_type(overlap)
6335
6336if(nrecv>0) then
6337 if (associated(check%recv)) deallocate(check%recv) !< Check if associated
6338 allocate(check%recv(nrecv))
6339 call allocate_check_overlap(overlap, maxsize)
6340endif
6341
6342pos = 0
6343do m = 1, update%nrecv
6344 do n = 1, update%recv(m)%count
6345 if( update%recv(m)%rotation(n) == one_hundred_eighty ) cycle
6346 if( (position == east .OR. position == corner) .AND. update%recv(m)%dir(n) == 1 ) then
6347 is = update%recv(m)%is(n) - 1
6348 ie = is
6349 js = update%recv(m)%js(n)
6350 je = update%recv(m)%je(n)
6351 call insert_check_overlap(overlap, update%recv(m)%pe, &
6352 update%recv(m)%tileMe(n), 1, update%recv(m)%rotation(n), is, ie, js, je)
6353 end if
6354 if( (position == north .OR. position == corner) .AND. update%recv(m)%dir(n) == 7 ) then
6355 is = update%recv(m)%is(n)
6356 ie = update%recv(m)%ie(n)
6357 js = update%recv(m)%js(n) - 1
6358 je = js
6359 call insert_check_overlap(overlap, update%recv(m)%pe, &
6360 update%recv(m)%tileMe(n), 3, update%recv(m)%rotation(n), is, ie, js, je)
6361 end if
6362 end do ! n = 1, overlap%count
6363 if(overlap%count>0) then
6364 pos = pos+1
6365 if(pos>nrecv)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6366 call add_check_overlap(check%recv(pos), overlap)
6367 call init_overlap_type(overlap)
6368 endif
6369end do ! end do list = 0, nlist
6370
6371if(pos .NE. nrecv)call mpp_error(fatal, "mpp_domains_define.inc(set_check_overlap): pos is greater than nrecv")
6372if(nrecv>0) call deallocate_overlap_type(overlap)
6373
6374end subroutine set_check_overlap
6375
6376!#############################################################################
6377!> set up the overlapping for boundary if the domain is symmetry.
6378subroutine set_bound_overlap( domain, position )
6379 type(domain2d), intent(inout) :: domain
6380 integer, intent(in) :: position
6381 integer :: m, n, l, count, dr, tMe
6382 integer, parameter :: MAXCOUNT = 100
6383 integer, dimension(MAXCOUNT) :: dir, rotation, is, ie, js, je, tileMe, index
6384 integer, dimension(size(domain%x(:)), 4) :: nrecvl
6385 integer, dimension(size(domain%x(:)), 4, MAXCOUNT) :: isl, iel, jsl, jel
6386 type(overlap_type), pointer :: overlap => null()
6387 type(overlapspec), pointer :: update => null()
6388 type(overlapspec), pointer :: bound => null()
6389 integer :: nlist_send, nlist_recv, ishift, jshift
6390 integer :: ism, iem, jsm, jem, nsend, nrecv
6391 integer :: isg, ieg, jsg, jeg, nlist, list
6392 integer :: npes_x, npes_y, ipos, jpos, inbr, jnbr
6393 integer :: isc, iec, jsc, jec, my_pe
6394 integer :: pe_south1, pe_south2, pe_west0, pe_west1, pe_west2
6395 integer :: is_south1, ie_south1, js_south1, je_south1
6396 integer :: is_south2, ie_south2, js_south2, je_south2
6397 integer :: is_west0, ie_west0, js_west0, je_west0
6398 integer :: is_west1, ie_west1, js_west1, je_west1
6399 integer :: is_west2, ie_west2, js_west2, je_west2
6400 logical :: x_cyclic, y_cyclic, folded_north
6401
6402 is_south1=0; ie_south1=0; js_south1=0; je_south1=0
6403 is_south2=0; ie_south2=0; js_south2=0; je_south2=0
6404 is_west0=0; ie_west0=0; js_west0=0; je_west0=0
6405 is_west1=0; ie_west1=0; js_west1=0; je_west1=0
6406 is_west2=0; ie_west2=0; js_west2=0; je_west2=0
6407
6408
6409 if( position == center .OR. .NOT. domain%symmetry ) return
6410 call mpp_get_domain_shift(domain, ishift, jshift, position)
6411 call mpp_get_global_domain(domain, isg, ieg, jsg, jeg)
6412 call mpp_get_memory_domain ( domain, ism, iem, jsm, jem )
6413
6414 select case(position)
6415 case (corner)
6416 update => domain%update_C
6417 bound => domain%bound_C
6418 case (east)
6419 update => domain%update_E
6420 bound => domain%bound_E
6421 case (north)
6422 update => domain%update_N
6423 bound => domain%bound_N
6424 case default
6425 call mpp_error( fatal, "mpp_domains_mod(set_bound_overlap): invalid option of position")
6426 end select
6427
6428 bound%xbegin = ism; bound%xend = iem + ishift
6429 bound%ybegin = jsm; bound%yend = jem + jshift
6430
6431 nlist_send = max(update%nsend,4)
6432 nlist_recv = max(update%nrecv,4)
6433 bound%nsend = nlist_send
6434 bound%nrecv = nlist_recv
6435 if(nlist_send >0) then
6436 if (associated(bound%send)) deallocate(bound%send) !< Check if associated
6437 allocate(bound%send(nlist_send))
6438 bound%send(:)%count = 0
6439 endif
6440 if(nlist_recv >0) then
6441 if (associated(bound%recv)) deallocate(bound%recv) !< Check if associated
6442 allocate(bound%recv(nlist_recv))
6443 bound%recv(:)%count = 0
6444 endif
6445 !--- loop over the list of domains to find the boundary overlap for send
6446 nlist = size(domain%list(:))
6447
6448 npes_x = size(domain%x(1)%list(:))
6449 npes_y = size(domain%y(1)%list(:))
6450 x_cyclic = domain%x(1)%cyclic
6451 y_cyclic = domain%y(1)%cyclic
6452 folded_north = btest(domain%fold,north)
6453 ipos = domain%x(1)%pos
6454 jpos = domain%y(1)%pos
6455 isc = domain%x(1)%compute%begin; iec = domain%x(1)%compute%end
6456 jsc = domain%y(1)%compute%begin; jec = domain%y(1)%compute%end
6457
6458 nsend = 0
6459 if(domain%ntiles == 1) then ! use neighbor processor to configure send and recv
6460 ! currently only set up for west and south boundary
6461
6462 ! south boundary for send
6463 pe_south1 = null_pe; pe_south2 = null_pe
6464 if( position == north .OR. position == corner ) then
6465 inbr = ipos; jnbr = jpos + 1
6466 if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6467 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6468 pe_south1 = domain%pearray(inbr,jnbr)
6469 is_south1 = isc + ishift; ie_south1 = iec+ishift
6470 js_south1 = jec + jshift; je_south1 = js_south1
6471 endif
6472 endif
6473 !--- send to the southwest processor when position is NORTH
6474 if( position == corner ) then
6475 inbr = ipos + 1; jnbr = jpos + 1
6476 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6477 if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6478 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6479 pe_south2 = domain%pearray(inbr,jnbr)
6480 is_south2 = iec + ishift; ie_south2 = is_south2
6481 js_south2 = jec + jshift; je_south2 = js_south2
6482 endif
6483 endif
6484
6485 !---west boundary for send
6486 pe_west0 = null_pe; pe_west1 = null_pe; pe_west2 = null_pe
6487 if( position == east ) then
6488 inbr = ipos+1; jnbr = jpos
6489 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6490 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6491 pe_west1 = domain%pearray(inbr,jnbr)
6492 is_west1 = iec + ishift; ie_west1 = is_west1
6493 js_west1 = jsc + jshift; je_west1 = jec + jshift
6494 endif
6495 else if ( position == corner ) then ! possible split into two parts.
6496 !--- on the fold.
6497 if( folded_north .AND. jec == jeg .AND. ipos .LT. (npes_x-1)/2 ) then
6498 inbr = npes_x - ipos - 1; jnbr = jpos
6499 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6500 pe_west0 = domain%pearray(inbr,jnbr)
6501 is_west0 = iec+ishift; ie_west0 = is_west0
6502 js_west0 = jec+jshift; je_west0 = js_west0
6503 endif
6504 endif
6505
6506 if( folded_north .AND. jec == jeg .AND. ipos .GE. npes_x/2 .AND. ipos .LT. (npes_x-1) ) then
6507 inbr = ipos+1; jnbr = jpos
6508 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6509 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6510 pe_west1 = domain%pearray(inbr,jnbr)
6511 is_west1 = iec + ishift; ie_west1 = is_west1
6512 js_west1 = jsc + jshift; je_west1 = jec
6513 endif
6514 else
6515 inbr = ipos+1; jnbr = jpos
6516 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6517 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6518 pe_west1 = domain%pearray(inbr,jnbr)
6519 is_west1 = iec + ishift; ie_west1 = is_west1
6520 js_west1 = jsc + jshift; je_west1 = jec + jshift
6521 endif
6522 endif
6523 endif
6524 !--- send to the southwest processor when position is NORTH
6525 if( position == corner ) then
6526 inbr = ipos + 1; jnbr = jpos + 1
6527 if( inbr == npes_x .AND. x_cyclic) inbr = 0
6528 if( jnbr == npes_y .AND. y_cyclic) jnbr = 0
6529 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6530 pe_west2 = domain%pearray(inbr,jnbr)
6531 is_west2 = iec + ishift; ie_west2 = is_west2
6532 js_west2 = jec + jshift; je_west2 = js_west2
6533 endif
6534 endif
6535
6536 do list = 0,nlist-1
6537 m = mod( domain%pos+list, nlist )
6538 count = 0
6539 my_pe = domain%list(m)%pe
6540 if(my_pe == pe_south1) then
6541 count = count + 1
6542 is(count) = is_south1; ie(count) = ie_south1
6543 js(count) = js_south1; je(count) = je_south1
6544 dir(count) = 2
6545 rotation(count) = zero
6546 endif
6547 if(my_pe == pe_south2) then
6548 count = count + 1
6549 is(count) = is_south2; ie(count) = ie_south2
6550 js(count) = js_south2; je(count) = je_south2
6551 dir(count) = 2
6552 rotation(count) = zero
6553 endif
6554
6555 if(my_pe == pe_west0) then
6556 count = count + 1
6557 is(count) = is_west0; ie(count) = ie_west0
6558 js(count) = js_west0; je(count) = je_west0
6559 dir(count) = 3
6560 rotation(count) = one_hundred_eighty
6561 endif
6562 if(my_pe == pe_west1) then
6563 count = count + 1
6564 is(count) = is_west1; ie(count) = ie_west1
6565 js(count) = js_west1; je(count) = je_west1
6566 dir(count) = 3
6567 rotation(count) = zero
6568 endif
6569 if(my_pe == pe_west2) then
6570 count = count + 1
6571 is(count) = is_west2; ie(count) = ie_west2
6572 js(count) = js_west2; je(count) = je_west2
6573 dir(count) = 3
6574 rotation(count) = zero
6575 endif
6576
6577 if(count >0) then
6578 nsend = nsend + 1
6579 if(nsend > nlist_send) call mpp_error(fatal, "set_bound_overlap: nsend > nlist_send")
6580 bound%send(nsend)%count = count
6581 bound%send(nsend)%pe = my_pe
6582 if (associated(bound%send(nsend)%is)) deallocate(bound%send(nsend)%is) !< Check if allocated
6583 if (associated(bound%send(nsend)%ie)) deallocate(bound%send(nsend)%ie) !< Check if allocated
6584 if (associated(bound%send(nsend)%js)) deallocate(bound%send(nsend)%js) !< Check if allocated
6585 if (associated(bound%send(nsend)%je)) deallocate(bound%send(nsend)%je) !< Check if allocated
6586 if (associated(bound%send(nsend)%dir)) deallocate(bound%send(nsend)%dir) !< Check if allocated
6587 if (associated(bound%send(nsend)%rotation)) deallocate(bound%send(nsend)%rotation) !< Check if allocated
6588 if (associated(bound%send(nsend)%tileMe)) deallocate(bound%send(nsend)%tileMe) !< Check if allocated
6589 allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6590 allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6591 allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6592 allocate(bound%send(nsend)%tileMe(count))
6593 bound%send(nsend)%is(:) = is(1:count)
6594 bound%send(nsend)%ie(:) = ie(1:count)
6595 bound%send(nsend)%js(:) = js(1:count)
6596 bound%send(nsend)%je(:) = je(1:count)
6597 bound%send(nsend)%dir(:) = dir(1:count)
6598 bound%send(nsend)%tileMe(:) = 1
6599 bound%send(nsend)%rotation(:) = rotation(1:count)
6600 endif
6601 enddo
6602 else
6603 !--- The following did not consider wide halo case.
6604 do m = 1, update%nsend
6605 overlap => update%send(m)
6606 if( overlap%count == 0 ) cycle
6607 count = 0
6608 do n = 1, overlap%count
6609 !--- currently not support folded-north
6610 if( overlap%rotation(n) == one_hundred_eighty ) cycle
6611 if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 1) then ! east
6612 count=count+1
6613 dir(count) = 1
6614 rotation(count) = overlap%rotation(n)
6615 tileme(count) = overlap%tileMe(n)
6616 select case( rotation(count) )
6617 case( zero ) ! W -> E
6618 is(count) = overlap%is(n) - 1
6619 ie(count) = is(count)
6620 js(count) = overlap%js(n)
6621 je(count) = overlap%je(n)
6622 case( ninety ) ! S -> E
6623 is(count) = overlap%is(n)
6624 ie(count) = overlap%ie(n)
6625 js(count) = overlap%js(n) - 1
6626 je(count) = js(count)
6627 end select
6628 end if
6629 if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 3 ) then ! south
6630 count=count+1
6631 dir(count) = 2
6632 rotation(count) = overlap%rotation(n)
6633 tileme(count) = overlap%tileMe(n)
6634 select case( rotation(count) )
6635 case( zero ) ! N->S
6636 is(count) = overlap%is(n)
6637 ie(count) = overlap%ie(n)
6638 js(count) = overlap%je(n) + 1
6639 je(count) = js(count)
6640 case( minus_ninety ) ! E->S
6641 is(count) = overlap%ie(n) + 1
6642 ie(count) = is(count)
6643 js(count) = overlap%js(n)
6644 je(count) = overlap%je(n)
6645 end select
6646 end if
6647 if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 5 ) then ! west
6648 count=count+1
6649 dir(count) = 3
6650 rotation(count) = overlap%rotation(n)
6651 tileme(count) = overlap%tileMe(n)
6652 select case( rotation(count) )
6653 case( zero ) ! E->W
6654 is(count) = overlap%ie(n) + 1
6655 ie(count) = is(count)
6656 js(count) = overlap%js(n)
6657 je(count) = overlap%je(n)
6658 case( ninety ) ! N->W
6659 is(count) = overlap%is(n)
6660 ie(count) = overlap%ie(n)
6661 js(count) = overlap%je(n) + 1
6662 je(count) = js(count)
6663 end select
6664 end if
6665 if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 7 ) then ! north
6666 count=count+1
6667 dir(count) = 4
6668 rotation(count) = overlap%rotation(n)
6669 tileme(count) = overlap%tileMe(n)
6670 select case( rotation(count) )
6671 case( zero ) ! S->N
6672 is(count) = overlap%is(n)
6673 ie(count) = overlap%ie(n)
6674 js(count) = overlap%js(n) - 1
6675 je(count) = js(count)
6676 case( minus_ninety ) ! W->N
6677 is(count) = overlap%is(n) - 1
6678 ie(count) = is(count)
6679 js(count) = overlap%js(n)
6680 je(count) = overlap%je(n)
6681 end select
6682 end if
6683 end do ! do n =1, overlap%count
6684 if(count>0) then
6685 nsend = nsend + 1
6686 bound%send(nsend)%count = count
6687 bound%send(nsend)%pe = overlap%pe
6688 if (associated(bound%send(nsend)%is)) deallocate(bound%send(nsend)%is) !< Check if allocated
6689 if (associated(bound%send(nsend)%ie)) deallocate(bound%send(nsend)%ie) !< Check if allocated
6690 if (associated(bound%send(nsend)%js)) deallocate(bound%send(nsend)%js) !< Check if allocated
6691 if (associated(bound%send(nsend)%je)) deallocate(bound%send(nsend)%je) !< Check if allocated
6692 if (associated(bound%send(nsend)%dir)) deallocate(bound%send(nsend)%dir) !< Check if allocated
6693 if (associated(bound%send(nsend)%rotation)) deallocate(bound%send(nsend)%rotation) !< Check if allocated
6694 if (associated(bound%send(nsend)%tileMe)) deallocate(bound%send(nsend)%tileMe) !< Check if allocated
6695 allocate(bound%send(nsend)%is(count), bound%send(nsend)%ie(count) )
6696 allocate(bound%send(nsend)%js(count), bound%send(nsend)%je(count) )
6697 allocate(bound%send(nsend)%dir(count), bound%send(nsend)%rotation(count) )
6698 allocate(bound%send(nsend)%tileMe(count))
6699 bound%send(nsend)%is(:) = is(1:count)
6700 bound%send(nsend)%ie(:) = ie(1:count)
6701 bound%send(nsend)%js(:) = js(1:count)
6702 bound%send(nsend)%je(:) = je(1:count)
6703 bound%send(nsend)%dir(:) = dir(1:count)
6704 bound%send(nsend)%tileMe(:) = tileme(1:count)
6705 bound%send(nsend)%rotation(:) = rotation(1:count)
6706 end if
6707 end do ! end do list = 0, nlist
6708 endif
6709
6710 !--- loop over the list of domains to find the boundary overlap for recv
6711 bound%nsend = nsend
6712 nrecvl(:,:) = 0
6713 nrecv = 0
6714
6715 !--- will computing overlap for tripolar grid.
6716 if( domain%ntiles == 1 ) then
6717 ! currently only set up for west and south boundary
6718
6719 ! south boundary for recv
6720 pe_south1 = null_pe; pe_south2 = null_pe
6721 if( position == north .OR. position == corner ) then
6722 inbr = ipos; jnbr = jpos - 1
6723 if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6724 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6725 pe_south1 = domain%pearray(inbr,jnbr)
6726 is_south1 = isc + ishift; ie_south1 = iec+ishift
6727 js_south1 = jsc; je_south1 = js_south1
6728 endif
6729 endif
6730
6731 !--- south boudary for recv: the southwest point when position is NORTH
6732 if( position == corner ) then
6733 inbr = ipos - 1; jnbr = jpos - 1
6734 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6735 if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y-1
6736 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6737 pe_south2 = domain%pearray(inbr,jnbr)
6738 is_south2 = isc; ie_south2 = is_south2
6739 js_south2 = jsc; je_south2 = js_south2
6740 endif
6741 endif
6742
6743
6744 !---west boundary for recv
6745 pe_west0 = null_pe; pe_west1 = null_pe; pe_west2 = null_pe
6746 if( position == east ) then
6747 inbr = ipos-1; jnbr = jpos
6748 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6749 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6750 pe_west1 = domain%pearray(inbr,jnbr)
6751 is_west1 = isc; ie_west1 = is_west1
6752 js_west1 = jsc + jshift; je_west1 = jec + jshift
6753 endif
6754 else if ( position == corner ) then ! possible split into two parts.
6755 !--- on the fold.
6756 if( folded_north .AND. jec == jeg .AND. ipos .GT. npes_x/2 ) then
6757 inbr = npes_x - ipos - 1; jnbr = jpos
6758 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6759 pe_west0 = domain%pearray(inbr,jnbr)
6760 is_west0 = isc; ie_west0 = is_west0
6761 js_west0 = jec+jshift; je_west0 = js_west0
6762 endif
6763 inbr = ipos-1; jnbr = jpos
6764 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6765 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6766 pe_west1 = domain%pearray(inbr,jnbr)
6767 is_west1 = isc; ie_west1 = is_west1
6768 js_west1 = jsc + jshift; je_west1 = jec
6769 endif
6770 else
6771 inbr = ipos-1; jnbr = jpos
6772 if( inbr == -1 .AND. x_cyclic) inbr = npes_x-1
6773 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6774 pe_west1 = domain%pearray(inbr,jnbr)
6775 is_west1 = isc; ie_west1 = is_west1
6776 js_west1 = jsc + jshift; je_west1 = jec+jshift
6777 endif
6778 endif
6779 endif
6780
6781 !--- west boundary for recv: the southwest point when position is CORNER
6782 if( position == corner ) then
6783 inbr = ipos - 1; jnbr = jpos - 1
6784 if( inbr == -1 .AND. x_cyclic) inbr = npes_x - 1
6785 if( jnbr == -1 .AND. y_cyclic) jnbr = npes_y - 1
6786 if( inbr .GE. 0 .AND. inbr .LT. npes_x .AND. jnbr .GE. 0 .AND. jnbr .LT. npes_y ) then
6787 pe_west2 = domain%pearray(inbr,jnbr)
6788 is_west2 = isc; ie_west2 = is_west2
6789 js_west2 = jsc; je_west2 = js_west2
6790 endif
6791 endif
6792
6793 tme = 1
6794 do list = 0,nlist-1
6795 m = mod( domain%pos+nlist-list, nlist )
6796 count = 0
6797 my_pe = domain%list(m)%pe
6798 if(my_pe == pe_south1) then
6799 count = count + 1
6800 is(count) = is_south1; ie(count) = ie_south1
6801 js(count) = js_south1; je(count) = je_south1
6802 dir(count) = 2
6803 rotation(count) = zero
6804 index(count) = 1 + ishift
6805 endif
6806 if(my_pe == pe_south2) then
6807 count = count + 1
6808 is(count) = is_south2; ie(count) = ie_south2
6809 js(count) = js_south2; je(count) = je_south2
6810 dir(count) = 2
6811 rotation(count) = zero
6812 index(count) = 1
6813 endif
6814 if(my_pe == pe_west0) then
6815 count = count + 1
6816 is(count) = is_west0; ie(count) = ie_west0
6817 js(count) = js_west0; je(count) = je_west0
6818 dir(count) = 3
6819 rotation(count) = one_hundred_eighty
6820 index(count) = jec-jsc+1+jshift
6821 endif
6822 if(my_pe == pe_west1) then
6823 count = count + 1
6824 is(count) = is_west1; ie(count) = ie_west1
6825 js(count) = js_west1; je(count) = je_west1
6826 dir(count) = 3
6827 rotation(count) = zero
6828 index(count) = 1 + jshift
6829 endif
6830 if(my_pe == pe_west2) then
6831 count = count + 1
6832 is(count) = is_west2; ie(count) = ie_west2
6833 js(count) = js_west2; je(count) = je_west2
6834 dir(count) = 3
6835 rotation(count) = zero
6836 index(count) = 1
6837 endif
6838
6839 if(count >0) then
6840 nrecv = nrecv + 1
6841 if(nrecv > nlist_recv) call mpp_error(fatal, "set_bound_overlap: nrecv > nlist_recv")
6842 bound%recv(nrecv)%count = count
6843 bound%recv(nrecv)%pe = my_pe
6844 if (associated(bound%recv(nrecv)%is)) deallocate(bound%recv(nrecv)%is) !< Check if allocated
6845 if (associated(bound%recv(nrecv)%ie)) deallocate(bound%recv(nrecv)%ie) !< Check if allocated
6846 if (associated(bound%recv(nrecv)%js)) deallocate(bound%recv(nrecv)%js) !< Check if allocated
6847 if (associated(bound%recv(nrecv)%je)) deallocate(bound%recv(nrecv)%je) !< Check if allocated
6848 if (associated(bound%recv(nrecv)%dir)) deallocate(bound%recv(nrecv)%dir) !< Check if allocated
6849 if (associated(bound%recv(nrecv)%index)) deallocate(bound%recv(nrecv)%index) !< Check if allocated
6850 if (associated(bound%recv(nrecv)%tileMe)) deallocate(bound%recv(nrecv)%tileMe) !< Check if allocated
6851 if (associated(bound%recv(nrecv)%rotation)) deallocate(bound%recv(nrecv)%rotation) !< Check if allocated
6852 allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6853 allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6854 allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6855 allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6856
6857 bound%recv(nrecv)%is(:) = is(1:count)
6858 bound%recv(nrecv)%ie(:) = ie(1:count)
6859 bound%recv(nrecv)%js(:) = js(1:count)
6860 bound%recv(nrecv)%je(:) = je(1:count)
6861 bound%recv(nrecv)%dir(:) = dir(1:count)
6862 bound%recv(nrecv)%tileMe(:) = 1
6863 bound%recv(nrecv)%rotation(:) = rotation(1:count)
6864 bound%recv(nrecv)%index(:) = index(1:count)
6865 endif
6866 enddo
6867 else
6868 do m = 1, update%nrecv
6869 overlap => update%recv(m)
6870 if( overlap%count == 0 ) cycle
6871 count = 0
6872 do n = 1, overlap%count
6873 !--- currently not support folded-north
6874 if( overlap%rotation(n) == one_hundred_eighty ) cycle
6875 if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 1) then ! east
6876 count=count+1
6877 dir(count) = 1
6878 rotation(count) = overlap%rotation(n)
6879 tileme(count) = overlap%tileMe(n)
6880 is(count) = overlap%is(n) - 1
6881 ie(count) = is(count)
6882 js(count) = overlap%js(n)
6883 je(count) = overlap%je(n)
6884 tme = tileme(count)
6885 nrecvl(tme, 1) = nrecvl(tme,1) + 1
6886 isl(tme,1,nrecvl(tme, 1)) = is(count)
6887 iel(tme,1,nrecvl(tme, 1)) = ie(count)
6888 jsl(tme,1,nrecvl(tme, 1)) = js(count)
6889 jel(tme,1,nrecvl(tme, 1)) = je(count)
6890 end if
6891
6892 if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 3) then ! south
6893 count=count+1
6894 dir(count) = 2
6895 rotation(count) = overlap%rotation(n)
6896 tileme(count) = overlap%tileMe(n)
6897 is(count) = overlap%is(n)
6898 ie(count) = overlap%ie(n)
6899 js(count) = overlap%je(n) + 1
6900 je(count) = js(count)
6901 tme = tileme(count)
6902 nrecvl(tme, 2) = nrecvl(tme,2) + 1
6903 isl(tme,2,nrecvl(tme, 2)) = is(count)
6904 iel(tme,2,nrecvl(tme, 2)) = ie(count)
6905 jsl(tme,2,nrecvl(tme, 2)) = js(count)
6906 jel(tme,2,nrecvl(tme, 2)) = je(count)
6907 end if
6908
6909 if( (position == east .OR. position == corner) .AND. overlap%dir(n) == 5) then ! west
6910 count=count+1
6911 dir(count) = 3
6912 rotation(count) = overlap%rotation(n)
6913 tileme(count) = overlap%tileMe(n)
6914 is(count) = overlap%ie(n) + 1
6915 ie(count) = is(count)
6916 js(count) = overlap%js(n)
6917 je(count) = overlap%je(n)
6918 tme = tileme(count)
6919 nrecvl(tme, 3) = nrecvl(tme,3) + 1
6920 isl(tme,3,nrecvl(tme, 3)) = is(count)
6921 iel(tme,3,nrecvl(tme, 3)) = ie(count)
6922 jsl(tme,3,nrecvl(tme, 3)) = js(count)
6923 jel(tme,3,nrecvl(tme, 3)) = je(count)
6924 end if
6925
6926 if( (position == north .OR. position == corner) .AND. overlap%dir(n) == 7) then ! north
6927 count=count+1
6928 dir(count) = 4
6929 rotation(count) = overlap%rotation(n)
6930 tileme(count) = overlap%tileMe(n)
6931 is(count) = overlap%is(n)
6932 ie(count) = overlap%ie(n)
6933 js(count) = overlap%js(n) - 1
6934 je(count) = js(count)
6935 tme = tileme(count)
6936 nrecvl(tme, 4) = nrecvl(tme,4) + 1
6937 isl(tme,4,nrecvl(tme, 4)) = is(count)
6938 iel(tme,4,nrecvl(tme, 4)) = ie(count)
6939 jsl(tme,4,nrecvl(tme, 4)) = js(count)
6940 jel(tme,4,nrecvl(tme, 4)) = je(count)
6941 end if
6942 end do ! do n = 1, overlap%count
6943 if(count>0) then
6944 nrecv = nrecv + 1
6945 bound%recv(nrecv)%count = count
6946 bound%recv(nrecv)%pe = overlap%pe
6947 if (associated(bound%recv(nrecv)%is)) deallocate(bound%recv(nrecv)%is) !< Check if allocated
6948 if (associated(bound%recv(nrecv)%ie)) deallocate(bound%recv(nrecv)%ie) !< Check if allocated
6949 if (associated(bound%recv(nrecv)%js)) deallocate(bound%recv(nrecv)%js) !< Check if allocated
6950 if (associated(bound%recv(nrecv)%je)) deallocate(bound%recv(nrecv)%je) !< Check if allocated
6951 if (associated(bound%recv(nrecv)%dir)) deallocate(bound%recv(nrecv)%dir) !< Check if allocated
6952 if (associated(bound%recv(nrecv)%index)) deallocate(bound%recv(nrecv)%index) !< Check if allocated
6953 if (associated(bound%recv(nrecv)%tileMe)) deallocate(bound%recv(nrecv)%tileMe) !< Check if allocated
6954 if (associated(bound%recv(nrecv)%rotation)) deallocate(bound%recv(nrecv)%rotation) !< Check if allocated
6955 allocate(bound%recv(nrecv)%is(count), bound%recv(nrecv)%ie(count) )
6956 allocate(bound%recv(nrecv)%js(count), bound%recv(nrecv)%je(count) )
6957 allocate(bound%recv(nrecv)%dir(count), bound%recv(nrecv)%index(count) )
6958 allocate(bound%recv(nrecv)%tileMe(count), bound%recv(nrecv)%rotation(count) )
6959 bound%recv(nrecv)%is(:) = is(1:count)
6960 bound%recv(nrecv)%ie(:) = ie(1:count)
6961 bound%recv(nrecv)%js(:) = js(1:count)
6962 bound%recv(nrecv)%je(:) = je(1:count)
6963 bound%recv(nrecv)%dir(:) = dir(1:count)
6964 bound%recv(nrecv)%tileMe(:) = tileme(1:count)
6965 bound%recv(nrecv)%rotation(:) = rotation(1:count)
6966 end if
6967 end do ! end do list = 0, nlist
6968 !--- find the boundary index for each contact within the east boundary
6969 do m = 1, nrecv
6970 do n = 1, bound%recv(m)%count
6971 tme = bound%recv(m)%tileMe(n)
6972 dr = bound%recv(m)%dir(n)
6973 bound%recv(m)%index(n) = 1
6974 do l = 1, nrecvl(tme,dr)
6975 if(dr == 1 .OR. dr == 3) then ! EAST, WEST
6976 if( bound%recv(m)%js(n) > jsl(tme, dr, l) ) then
6977 if( bound%recv(m)%rotation(n) == one_hundred_eighty ) then
6978 bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6979 max(abs(jel(tme, dr, l)-jsl(tme, dr, l))+1, &
6980 abs(iel(tme, dr, l)-isl(tme, dr, l))+1)
6981 else
6982 bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6983 max(abs(jel(tme, dr, l)-jsl(tme, dr, l)), &
6984 abs(iel(tme, dr, l)-isl(tme, dr, l))) + 1 - jshift
6985 endif
6986 end if
6987 else ! South, North
6988 if( bound%recv(m)%is(n) > isl(tme, dr, l) ) then
6989 bound%recv(m)%index(n) = bound%recv(m)%index(n) + &
6990 max(abs(jel(tme, dr, l)-jsl(tme, dr, l)), &
6991 abs(iel(tme, dr, l)-isl(tme, dr, l))) + 1 - ishift
6992 end if
6993 end if
6994 end do
6995 end do
6996 end do
6997
6998 endif
6999 bound%nrecv = nrecv
7000
7001
7002end subroutine set_bound_overlap
7003
7004
7005!#############################################################################
7006
7007subroutine fill_corner_contact(eCont, sCont, wCont, nCont, isg, ieg, jsg, jeg, numR, numS, tileRecv, tileSend, &
7008 is1Recv, ie1Recv, js1Recv, je1Recv, is2Recv, ie2Recv, js2Recv, je2Recv, &
7009 is1Send, ie1Send, js1Send, je1Send, is2Send, ie2Send, js2Send, je2Send, &
7010 align1Recv, align2Recv, align1Send, align2Send, &
7011 whalo, ehalo, shalo, nhalo, tileMe)
7012type(contact_type), dimension(:), intent(in) :: eCont, sCont, wCont, nCont
7013integer, dimension(:), intent(in) :: isg, ieg, jsg, jeg
7014integer, intent(inout) :: numR, numS
7015integer, dimension(:), intent(inout) :: tileRecv, tileSend
7016integer, dimension(:), intent(inout) :: is1Recv, ie1Recv, js1Recv, je1Recv
7017integer, dimension(:), intent(inout) :: is2Recv, ie2Recv, js2Recv, je2Recv
7018integer, dimension(:), intent(inout) :: is1Send, ie1Send, js1Send, je1Send
7019integer, dimension(:), intent(inout) :: is2Send, ie2Send, js2Send, je2Send
7020integer, dimension(:), intent(inout) :: align1Recv, align2Recv, align1Send, align2Send
7021integer, intent(in) :: tileMe, whalo, ehalo, shalo, nhalo
7022integer :: is1, ie1, js1, je1, is2, ie2, js2, je2
7023integer :: tn, tc, n, m
7024logical :: found_corner
7025
7026found_corner = .false.
7027!--- southeast for recving
7028if(econt(tileme)%ncontact > 0) then
7029 if(econt(tileme)%js1(1) == jsg(tileme) ) then
7030 tn = econt(tileme)%tile(1)
7031 if(econt(tileme)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7032 if( econt(tileme)%js2(1) - jsg(tn) < shalo ) call mpp_error(fatal, &
7033 "mpp_domains_define.inc: southeast tile for recv 1 is not tiled properly")
7034 found_corner = .true.; tc = tn
7035 is1 = econt(tileme)%ie1(1) + 1; je1 = econt(tileme)%js1(1) - 1
7036 is2 = econt(tileme)%is2(1); je2 = econt(tileme)%js2(1) - 1
7037 else if(scont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7038 if(scont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7039 found_corner = .true.; tc = scont(tn)%tile(1)
7040 is1 = econt(tileme)%ie1(1) + 1; je1 = econt(tileme)%js1(1) - 1
7041 is2 = scont(tn)%is2(1); je2 = scont(tn)%je2(1)
7042 end if
7043 end if
7044 end if
7045end if
7046if( .not. found_corner ) then ! not found,
7047 n = scont(tileme)%ncontact
7048 if( n > 0) then
7049 if( scont(tileme)%ie1(n) == ieg(tileme)) then
7050 tn = scont(tileme)%tile(n)
7051 if(scont(tileme)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7052 if(ieg(tn) - scont(tileme)%ie2(n) < ehalo ) call mpp_error(fatal, &
7053 "mpp_domains_define.inc: southeast tile for recv 2 is not tiled properly")
7054 found_corner = .true.; tc = tn
7055 is1 = scont(tileme)%ie1(n) + 1; je1 = scont(tileme)%js1(n) - 1
7056 is2 = scont(tileme)%ie2(n) + 1; je2 = scont(tileme)%je2(n)
7057 else if(econt(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7058 m = econt(tn)%ncontact
7059 if(econt(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7060 found_corner = .true.; tc = econt(tn)%tile(m)
7061 is1 = scont(tileme)%ie1(n) + 1; je1 = scont(tileme)%js1(n) - 1
7062 is2 = econt(tn)%is2(m); je2 = econt(tn)%je2(m)
7063 end if
7064 end if
7065 end if
7066 end if
7067end if
7068if(found_corner) then
7069 numr = numr + 1
7070 tilerecv(numr) = tc; align1recv(numr) = south_east; align2recv(numr) = north_west
7071 is1recv(numr) = is1; ie1recv(numr) = is1 + ehalo - 1
7072 js1recv(numr) = je1 - shalo + 1; je1recv(numr) = je1
7073 is2recv(numr) = is2; ie2recv(numr) = is2 + ehalo - 1
7074 js2recv(numr) = je2 - shalo + 1; je2recv(numr) = je2
7075end if
7076
7077!--- southwest for recving
7078found_corner = .false.
7079if(wcont(tileme)%ncontact > 0) then
7080 if(wcont(tileme)%js1(1) == jsg(tileme) ) then
7081 tn = wcont(tileme)%tile(1)
7082 if(wcont(tileme)%js2(1) > jsg(tn) ) then ! the corner tile is tn.
7083 if( wcont(tileme)%js2(1) - jsg(tn) < shalo ) call mpp_error(fatal, &
7084 "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7085 found_corner = .true.; tc = tn
7086 ie1 = wcont(tileme)%is1(1) - 1; je1 = wcont(tileme)%js1(1) - 1
7087 ie2 = wcont(tileme)%is2(1); je2 = wcont(tileme)%js2(1) - 1
7088 else if(scont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7089 n = scont(tn)%ncontact
7090 if(scont(tn)%ie1(n) == ieg(tn)) then ! corner is nc.
7091 found_corner = .true.; tc = scont(tn)%tile(n)
7092 ie1 = wcont(tileme)%is1(1) - 1; je1 = wcont(tileme)%js1(1) - 1
7093 ie2 = scont(tn)%ie2(1); je2 = scont(tn)%je2(1)
7094 end if
7095 end if
7096 end if
7097end if
7098if( .not. found_corner ) then ! not found,
7099 n = scont(tileme)%ncontact
7100 if( n > 0) then
7101 if( scont(tileme)%is1(1) == isg(tileme)) then
7102 tn = scont(tileme)%tile(1)
7103 if(scont(tileme)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7104 if( scont(tileme)%is2(1)-isg(tn) < whalo ) call mpp_error(fatal, &
7105 "mpp_domains_define.inc: southwest tile for recv 1 is not tiled properly")
7106 found_corner = .true.; tc = tn
7107 ie1 = scont(tileme)%is1(1) - 1; je1 = scont(tileme)%js1(1) - 1
7108 ie2 = scont(tileme)%is2(1) - 1; je2 = scont(tileme)%js2(1)
7109 else if(wcont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7110 m = wcont(tn)%ncontact
7111 if(wcont(tn)%je1(m) == jeg(tn)) then ! corner is nc.
7112 found_corner = .true.; tc = wcont(tn)%tile(m)
7113 ie1 = scont(tileme)%is1(1) - 1; je1 = scont(tileme)%js1(1) - 1
7114 ie2 = wcont(tn)%ie2(m); je2 = wcont(tn)%je2(m)
7115 end if
7116 end if
7117 end if
7118 end if
7119end if
7120if(found_corner) then
7121 numr = numr + 1
7122 tilerecv(numr) = tc; align1recv(numr) = south_west; align2recv(numr) = north_east
7123 is1recv(numr) = ie1 - whalo + 1; ie1recv(numr) = ie1
7124 js1recv(numr) = je1 - shalo + 1; je1recv(numr) = je1
7125 is2recv(numr) = ie2 - whalo + 1; ie2recv(numr) = ie2
7126 js2recv(numr) = je2 - shalo + 1; je2recv(numr) = je2
7127end if
7128
7129!--- northwest for recving
7130found_corner = .false.
7131n = wcont(tileme)%ncontact
7132if( n > 0) then
7133 if(wcont(tileme)%je1(n) == jeg(tileme) ) then
7134 tn = wcont(tileme)%tile(n)
7135 if(wcont(tileme)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7136 if( jeg(tn) - wcont(tileme)%je2(n) < nhalo ) call mpp_error(fatal, &
7137 "mpp_domains_define.inc: northwest tile for recv 1 is not tiled properly")
7138 found_corner = .true.; tc = tn
7139 ie1 = wcont(tileme)%is1(n) - 1; js1 = wcont(tileme)%je1(n) + 1
7140 ie2 = wcont(tileme)%is2(n); js2 = wcont(tileme)%je2(n) + 1
7141 else if(ncont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7142 m = ncont(tn)%ncontact
7143 if(ncont(tn)%ie1(m) == ieg(tn)) then ! corner is nc.
7144 found_corner = .true.; tc = ncont(tn)%tile(m)
7145 ie1 = wcont(tileme)%is1(n) - 1; js1 = wcont(tileme)%je1(n) + 1
7146 ie2 = ncont(tn)%ie2(m); js2 = ncont(tn)%js2(m)
7147 end if
7148 endif
7149 endif
7150end if
7151if( .not. found_corner ) then ! not found,
7152 if( ncont(tileme)%ncontact > 0) then
7153 if( ncont(tileme)%is1(1) == isg(tileme)) then
7154 tn = ncont(tileme)%tile(1)
7155 if(ncont(tileme)%is2(1) > isg(tn) ) then ! the corner tile is tn.
7156 if( ncont(tileme)%is2(1)-isg(tn) < whalo ) call mpp_error(fatal, &
7157 "mpp_domains_define.inc: northwest tile for recv 2 is not tiled properly")
7158 found_corner = .true.; tc = tn
7159 ie1 = ncont(tileme)%is1(1) - 1; js1 = ncont(tileme)%je1(1) + 1
7160 ie2 = ncont(tileme)%is2(1) - 1; js2 = ncont(tileme)%js2(1)
7161 else if(wcont(tn)%ncontact >0) then ! the corner tile may be west tile of tn.
7162 if(wcont(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7163 found_corner = .true.; tc = wcont(tn)%tile(1)
7164 ie1 = ncont(tileme)%is1(1) - 1; js1 = ncont(tileme)%je1(1) + 1
7165 ie2 = wcont(tn)%ie2(1); js2 = wcont(tn)%js2(1)
7166 end if
7167 end if
7168 end if
7169 end if
7170end if
7171if(found_corner) then
7172 numr = numr + 1
7173 tilerecv(numr) = tc; align1recv(numr) =north_west; align2recv(numr) = south_east
7174 is1recv(numr) = ie1 - whalo + 1; ie1recv(numr) = ie1
7175 js1recv(numr) = js1; je1recv(numr) = js1 + nhalo - 1
7176 is2recv(numr) = ie2 - whalo + 1; ie2recv(numr) = ie2
7177 js2recv(numr) = js2; je2recv(numr) = js2 + nhalo - 1
7178end if
7179
7180!--- northeast for recving
7181found_corner = .false.
7182n = econt(tileme)%ncontact
7183if( n > 0) then
7184 if(econt(tileme)%je1(n) == jeg(tileme) ) then
7185 tn = econt(tileme)%tile(n)
7186 if(econt(tileme)%je2(n) < jeg(tn) ) then ! the corner tile is tn.
7187 if( jeg(tn) - econt(tileme)%je2(n) < nhalo ) call mpp_error(fatal, &
7188 "mpp_domains_define.inc: northeast tile for recv 1 is not tiled properly")
7189 found_corner = .true.; tc = tn
7190 is1 = econt(tileme)%ie1(n) + 1; js1 = econt(tileme)%je1(n) + 1
7191 is2 = econt(tileme)%is2(1); js2 = econt(tileme)%je2(1) + 1
7192 else if(ncont(tn)%ncontact >0) then ! the corner tile may be south tile of tn.
7193 if(ncont(tn)%is1(1) == isg(tn)) then ! corner is nc.
7194 found_corner = .true.; tc = ncont(tn)%tile(1)
7195 is1 = econt(tileme)%ie1(n) + 1; js1 = econt(tileme)%je1(n) + 1
7196 is2 = ncont(tn)%is2(1); js2 = ncont(tn)%js2(1)
7197 end if
7198 end if
7199 end if
7200end if
7201if( .not. found_corner ) then ! not found,
7202 n = ncont(tileme)%ncontact
7203 if( n > 0) then
7204 if( ncont(tileme)%ie1(n) == ieg(tileme)) then
7205 tn = ncont(tileme)%tile(n)
7206 if(ncont(tileme)%ie2(n) < ieg(tn) ) then ! the corner tile is tn.
7207 if(ieg(tn) - scont(tileme)%ie2(n) < ehalo ) call mpp_error(fatal, &
7208 "mpp_domains_define.inc: northeast tile for recv 2 is not tiled properly")
7209 found_corner = .true.; tc = tn
7210 is1 = scont(tileme)%ie1(n) + 1; js1 = scont(tileme)%je1(n) + 1
7211 is2 = scont(tileme)%ie2(n) + 1; js2 = scont(tileme)%js2(n)
7212 else if(econt(tn)%ncontact >0) then ! the corner tile may be east tile of tn.
7213 if(econt(tn)%js1(1) == jsg(tn)) then ! corner is nc.
7214 found_corner = .true.; tc = econt(tn)%tile(1)
7215 is1 = scont(tileme)%ie1(n) + 1; js1 = scont(tileme)%je1(n) + 1
7216 is2 = econt(tn)%is2(m); js2 = econt(tn)%js2(m)
7217 end if
7218 end if
7219 end if
7220 end if
7221end if
7222if(found_corner) then
7223 numr = numr + 1
7224 tilerecv(numr) = tc; align1recv(numr) =north_east; align2recv(numr) = south_west
7225 is1recv(numr) = is1; ie1recv(numr) = is1 + ehalo - 1
7226 js1recv(numr) = js1; je1recv(numr) = js1 + nhalo - 1
7227 is2recv(numr) = is2; ie2recv(numr) = is2 + ehalo - 1
7228 js2recv(numr) = js2; je2recv(numr) = js2 + nhalo - 1
7229end if
7230
7231!--- to_pe's southeast for sending
7232do n = 1, wcont(tileme)%ncontact
7233 tn = wcont(tileme)%tile(n)
7234 if(wcont(tileme)%js2(n) == jsg(tn) ) then
7235 if(wcont(tileme)%js1(n) > jsg(tileme) ) then ! send to tile tn.
7236 if( wcont(tileme)%js1(n) - jsg(tileme) < shalo ) call mpp_error(fatal, &
7237 "mpp_domains_define.inc: southeast tile for send 1 is not tiled properly")
7238 nums = nums+1; tilesend(nums) = tn
7239 align1send(nums) = north_west; align2send(nums) = south_east
7240 is1send(nums) = wcont(tileme)%is1(n); ie1send(nums) = is1send(nums) + ehalo - 1
7241 je1send(nums) = wcont(tileme)%js1(n) - 1; js1send(nums) = je1send(nums) - shalo + 1
7242 is2send(nums) = wcont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7243 je2send(nums) = wcont(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7244 end if
7245 end if
7246end do
7247do n = 1, ncont(tileme)%ncontact
7248 tn = ncont(tileme)%tile(n)
7249 if(ncont(tileme)%ie2(n) == ieg(tn) ) then
7250 if(ncont(tileme)%ie1(n) < ieg(tileme) ) then ! send to tile tn.
7251 if( ieg(tileme) - ncont(tileme)%ie1(n) < ehalo ) call mpp_error(fatal, &
7252 "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7253 nums = nums+1; tilesend(nums) = tn
7254 align1send(nums) = north_west; align2send(nums) = south_east
7255 is1send(nums) = ncont(tileme)%ie1(n) + 1; ie1send(nums) = is1send(nums) + ehalo - 1
7256 je1send(nums) = ncont(tileme)%je1(n) ; js1send(nums) = je1send(nums) - shalo + 1
7257 is2send(nums) = ncont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7258 je2send(nums) = ncont(tileme)%je2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7259 end if
7260 end if
7261end do
7262
7263!--- found the corner overlap that is not specified through contact line.
7264n = wcont(tileme)%ncontact
7265found_corner = .false.
7266if( n > 0) then
7267 tn = wcont(tileme)%tile(n)
7268 if( wcont(tileme)%je1(n) == jeg(tileme) .AND. wcont(tileme)%je2(n) == jeg(tn) ) then
7269 m = ncont(tn)%ncontact
7270 if(m >0) then
7271 tc = ncont(tn)%tile(m)
7272 if( ncont(tn)%ie1(m) == ieg(tn) .AND. ncont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7273 end if
7274 end if
7275end if
7276if( .not. found_corner ) then ! not found, then starting from north contact
7277 if( ncont(tileme)%ncontact > 0) then
7278 tn = ncont(tileme)%tile(1)
7279 if( ncont(tileme)%is1(1) == isg(tileme) .AND. ncont(tileme)%is2(1) == isg(tn) ) then
7280 if(wcont(tn)%ncontact >0) then
7281 tc = wcont(tn)%tile(1)
7282 if( wcont(tn)%js1(1) == jsg(tn) .AND. wcont(tn)%js2(1) == jsg(tc) ) found_corner = .true.
7283 end if
7284 end if
7285 end if
7286end if
7287
7288if(found_corner) then
7289 nums = nums+1; tilesend(nums) = tc
7290 align1send(nums) = north_west; align2send(nums) = south_east
7291 is1send(nums) = isg(tileme); ie1send(nums) = is1send(nums) + ehalo - 1
7292 je1send(nums) = jeg(tileme); js1send(nums) = je1send(nums) - shalo + 1
7293 is2send(nums) = ieg(tc) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7294 je2send(nums) = jsg(tc) - 1; js2send(nums) = je2send(nums) - shalo + 1
7295end if
7296
7297!--- to_pe's southwest for sending
7298do n = 1, econt(tileme)%ncontact
7299 tn = econt(tileme)%tile(n)
7300 if(econt(tileme)%js2(n) == jsg(tn) ) then
7301 if(econt(tileme)%js1(n) > jsg(tileme) ) then ! send to tile tn.
7302 if( econt(tileme)%js1(n) - jsg(tileme) < shalo ) call mpp_error(fatal, &
7303 "mpp_domains_define.inc: southwest tile for send 1 is not tiled properly")
7304 nums = nums+1; tilesend(nums) = tn
7305 align1send(nums) = north_east; align2send(nums) = south_west
7306 ie1send(nums) = econt(tileme)%ie1(n); is1send(nums) = ie1send(nums) - whalo + 1
7307 je1send(nums) = econt(tileme)%js1(n) - 1; js1send(nums) = je1send(nums) - shalo + 1
7308 ie2send(nums) = econt(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7309 je2send(nums) = econt(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7310 end if
7311 end if
7312end do
7313do n = 1, ncont(tileme)%ncontact
7314 tn = ncont(tileme)%tile(n)
7315 if(ncont(tileme)%is2(n) == isg(tn) ) then
7316 if(ncont(tileme)%is1(n) > isg(tileme) ) then ! send to tile tn.
7317 if( ncont(tileme)%is1(n) - isg(tileme) < whalo ) call mpp_error(fatal, &
7318 "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7319 nums = nums+1; tilesend(nums) = tn
7320 align1send(nums) = north_east; align2send(nums) = south_west
7321 ie1send(nums) = ncont(tileme)%is1(n) - 1; is1send(nums) = ie1send(nums) - whalo + 1
7322 ie1send(nums) = ncont(tileme)%je1(n) ; js1send(nums) = je1send(nums) - shalo + 1
7323 ie2send(nums) = ncont(tileme)%is2(n) - 1; is2send(nums) = je2send(nums) - whalo + 1
7324 je2send(nums) = ncont(tileme)%js2(n) - 1; js2send(nums) = je2send(nums) - shalo + 1
7325 end if
7326 end if
7327end do
7328
7329!--- found the corner overlap that is not specified through contact line.
7330n = econt(tileme)%ncontact
7331found_corner = .false.
7332if( n > 0) then
7333 tn = econt(tileme)%tile(n)
7334 if( econt(tileme)%je1(n) == jeg(tileme) .AND. econt(tileme)%je2(n) == jeg(tn) ) then
7335 if(ncont(tn)%ncontact >0) then
7336 tc = ncont(tn)%tile(1)
7337 if( ncont(tn)%is1(1) == isg(tn) .AND. ncont(tn)%is2(n) == isg(tc) ) found_corner = .true.
7338 end if
7339 end if
7340end if
7341if( .not. found_corner ) then ! not found, then starting from north contact
7342 n = ncont(tileme)%ncontact
7343 if( n > 0) then
7344 tn = ncont(tileme)%tile(n)
7345 if( ncont(tileme)%ie1(n) == ieg(tileme) .AND. ncont(tileme)%ie2(n) == ieg(tn) ) then
7346 if(econt(tn)%ncontact >0) then
7347 tc = econt(tn)%tile(1)
7348 if( econt(tn)%js1(1) == jsg(tn) .AND. econt(tn)%js2(n) == jsg(tc) ) found_corner = .true.
7349 end if
7350 end if
7351 end if
7352end if
7353
7354if(found_corner) then
7355 nums = nums+1; tilesend(nums) = tc
7356 align1send(nums) = north_east; align2send(nums) = south_west
7357 ie1send(nums) = ieg(tileme); is1send(nums) = ie1send(nums) - whalo + 1
7358 je1send(nums) = jeg(tileme); js1send(nums) = je1send(nums) - shalo + 1
7359 ie2send(nums) = isg(tc) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7360 je2send(nums) = jsg(tc) - 1; js2send(nums) = je2send(nums) - shalo + 1
7361end if
7362
7363!--- to_pe's northwest for sending
7364do n = 1, econt(tileme)%ncontact
7365 tn = econt(tileme)%tile(n)
7366 if(econt(tileme)%je2(n) == jeg(tn) ) then
7367 if(econt(tileme)%je1(n) < jeg(tileme) ) then ! send to tile tn.
7368 if( jeg(tileme) - econt(tileme)%je1(n) < nhalo ) call mpp_error(fatal, &
7369 "mpp_domains_define.inc: northwest tile for send 1 is not tiled properly")
7370 nums = nums+1; tilesend(nums) = tn
7371 align1send(nums) = south_east; align2send(nums) = north_west
7372 ie1send(nums) = econt(tileme)%ie1(n) ; is1send(nums) = ie1send(nums) - whalo + 1
7373 js1send(nums) = econt(tileme)%je1(n) + 1; je1send(nums) = js1send(nums) + nhalo - 1
7374 ie2send(nums) = econt(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7375 js2send(nums) = econt(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7376 end if
7377 end if
7378end do
7379
7380do n = 1, scont(tileme)%ncontact
7381 tn = scont(tileme)%tile(n)
7382 if(scont(tileme)%is2(n) == isg(tn) ) then
7383 if(scont(tileme)%is1(n) > isg(tileme) ) then ! send to tile tn.
7384 if( scont(tileme)%is1(n) - isg(tileme) < whalo ) call mpp_error(fatal, &
7385 "mpp_domains_define.inc: southwest tile for send 2 is not tiled properly")
7386 nums = nums+1; tilesend(nums) = tn
7387 align1send(nums) = south_east; align2send(nums) = north_west
7388 ie1send(nums) = ncont(tileme)%is1(n) - 1; is1send(nums) = ie1send(nums) - whalo + 1
7389 js1send(nums) = ncont(tileme)%je1(n) ; je1send(nums) = js1send(nums) + nhalo - 1
7390 ie2send(nums) = ncont(tileme)%is2(n) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7391 js2send(nums) = ncont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7392 end if
7393 end if
7394end do
7395
7396!--- found the corner overlap that is not specified through contact line.
7397n = econt(tileme)%ncontact
7398found_corner = .false.
7399if( n > 0) then
7400 tn = econt(tileme)%tile(1)
7401 if( econt(tileme)%js1(1) == jsg(tileme) .AND. econt(tileme)%js2(1) == jsg(tn) ) then
7402 if(scont(tn)%ncontact >0) then
7403 tc = scont(tn)%tile(1)
7404 if( scont(tn)%is1(1) == isg(tn) .AND. scont(tn)%is2(1) == isg(tc) ) found_corner = .true.
7405 end if
7406 end if
7407end if
7408if( .not. found_corner ) then ! not found, then starting from north contact
7409 n = scont(tileme)%ncontact
7410 found_corner = .false.
7411 if( n > 0) then
7412 tn = scont(tileme)%tile(n)
7413 if( scont(tileme)%ie1(n) == ieg(tileme) .AND. scont(tileme)%ie2(n) == ieg(tn) ) then
7414 if(econt(tn)%ncontact >0) then
7415 tc = econt(tn)%tile(n)
7416 if( econt(tn)%je1(n) == jeg(tn) .AND. econt(tn)%je2(n) == jeg(tc) ) found_corner = .true.
7417 end if
7418 end if
7419 end if
7420end if
7421
7422if(found_corner) then
7423 nums = nums+1; tilesend(nums) = tc
7424 align1send(nums) = south_east; align2send(nums) = north_west
7425 ie1send(nums) = ieg(tileme); is1send(nums) = ie1send(nums) - whalo + 1
7426 js1send(nums) = jsg(tileme); je1send(nums) = js1send(nums) + nhalo - 1
7427 ie2send(nums) = isg(tc) - 1; is2send(nums) = ie2send(nums) - whalo + 1
7428 js2send(nums) = jeg(tc) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7429end if
7430
7431!--- to_pe's northeast for sending
7432do n = 1, wcont(tileme)%ncontact
7433 tn = wcont(tileme)%tile(n)
7434 if(wcont(tileme)%je2(n) == jeg(tn) ) then
7435 if(wcont(tileme)%je1(n) < jeg(tileme) ) then ! send to tile tn.
7436 if( jeg(tileme) - wcont(tileme)%je1(n) < nhalo ) call mpp_error(fatal, &
7437 "mpp_domains_define.inc: northeast tile for send 1 is not tiled properly")
7438 nums = nums+1; tilesend(nums) = tn
7439 align1send(nums) = south_west; align2send(nums) = north_east
7440 is1send(nums) = wcont(tileme)%is1(n) ; ie1send(nums) = is1send(nums) + ehalo - 1
7441 js1send(nums) = wcont(tileme)%je1(n) + 1; je1send(nums) = js1send(nums) + nhalo - 1
7442 is2send(nums) = wcont(tileme)%ie2(n) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7443 js2send(nums) = wcont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7444 end if
7445 end if
7446end do
7447
7448do n = 1, scont(tileme)%ncontact
7449 tn = scont(tileme)%tile(n)
7450 if(scont(tileme)%ie2(n) == ieg(tn) ) then
7451 if(scont(tileme)%ie1(n) < ieg(tileme) ) then ! send to tile tn.
7452 if( ieg(tileme) - scont(tileme)%ie1(n) < ehalo ) call mpp_error(fatal, &
7453 "mpp_domains_define.inc: southeast tile for send 2 is not tiled properly")
7454 nums = nums+1; tilesend(nums) = tn
7455 align1send(nums) = south_west; align2send(nums) = north_east
7456 is1send(nums) = scont(tileme)%ie1(n) + 1; ie1send(nums) = is1send(nums) + ehalo - 1
7457 js1send(nums) = scont(tileme)%js1(n) ; je1send(nums) = js1send(nums) + nhalo - 1
7458 is2send(nums) = scont(tileme)%ie2(n) + 1; ie2send(nums) = is1send(nums) + ehalo - 1
7459 js2send(nums) = scont(tileme)%je2(n) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7460 end if
7461 end if
7462end do
7463
7464!--- found the corner overlap that is not specified through contact line.
7465n = wcont(tileme)%ncontact
7466found_corner = .false.
7467if( n > 0) then
7468 tn = wcont(tileme)%tile(1)
7469 if( wcont(tileme)%js1(n) == jsg(tileme) .AND. wcont(tileme)%js2(n) == jsg(tn) ) then
7470 m = scont(tn)%ncontact
7471 if(m >0) then
7472 tc = scont(tn)%tile(m)
7473 if( scont(tn)%ie1(m) == ieg(tn) .AND. scont(tn)%ie2(m) == ieg(tc) ) found_corner = .true.
7474 end if
7475 end if
7476end if
7477if( .not. found_corner ) then ! not found, then starting from north contact
7478 n = scont(tileme)%ncontact
7479 found_corner = .false.
7480 if( n > 0) then
7481 tn = scont(tileme)%tile(1)
7482 if( scont(tileme)%is1(1) == isg(tileme) .AND. scont(tileme)%is2(1) == isg(tn) ) then
7483 m = wcont(tn)%ncontact
7484 if( m > 0 ) then
7485 tc = wcont(tn)%tile(m)
7486 if( wcont(tn)%je1(m) == jeg(tn) .AND. wcont(tn)%je2(m) == jeg(tc) ) found_corner = .true.
7487 end if
7488 end if
7489 end if
7490end if
7491if(found_corner) then
7492 nums = nums+1; tilesend(nums) = tc
7493 align1send(nums) = south_west; align2send(nums) = north_east
7494 is1send(nums) = isg(tileme); ie1send(nums) = is1send(nums) + ehalo - 1
7495 js1send(nums) = jsg(tileme); je1send(nums) = js1send(nums) + nhalo - 1
7496 is2send(nums) = ieg(tc) + 1; ie2send(nums) = is2send(nums) + ehalo - 1
7497 js2send(nums) = jeg(tc) + 1; je2send(nums) = js2send(nums) + nhalo - 1
7498end if
7499
7500end subroutine fill_corner_contact
7501
7502!--- find the alignment direction, check if index is reversed, if reversed, exchange index.
7503subroutine check_alignment( is, ie, js, je, isg, ieg, jsg, jeg, alignment )
7504integer, intent(inout) :: is, ie, js, je, isg, ieg, jsg, jeg
7505integer, intent(out) :: alignment
7506
7507integer :: i, j
7508
7509if ( is == ie ) then ! x-alignment
7510 if ( is == isg ) then
7511 alignment = west
7512 else if ( is == ieg ) then
7513 alignment = east
7514 else
7515 call mpp_error(fatal, 'mpp_domains_define.inc: The contact region is not on the x-boundary of the tile')
7516 end if
7517 if ( js > je ) then
7518 j = js; js = je; je = j
7519 end if
7520else if ( js == je ) then ! y-alignment
7521 if ( js == jsg ) then
7522 alignment = south
7523 else if ( js == jeg ) then
7524 alignment = north
7525 else
7526 call mpp_error(fatal, 'mpp_domains_define.inc: The contact region is not on the y-boundary of the tile')
7527 end if
7528 if ( is > ie ) then
7529 i = is; is = ie; ie = i
7530 end if
7531else
7532 call mpp_error(fatal, 'mpp_domains_define.inc: The contact region should be line contact' )
7533end if
7534
7535end subroutine check_alignment
7536!#####################################################################
7537
7538!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7539! !
7540! MPP_MODIFY_DOMAIN: modify extent of domain !
7541! !
7542!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7543
7544!> @brief Modifies the exents of a domain
7545subroutine mpp_modify_domain1d(domain_in,domain_out,cbegin,cend,gbegin,gend, hbegin, hend)
7546 ! </PUBLICROUTINE>
7547type(domain1d), intent(in) :: domain_in !< The source domain.
7548type(domain1d), intent(inout) :: domain_out !< The returned domain.
7549integer, intent(in), optional :: hbegin, hend !< halo size
7550integer, intent(in), optional :: cbegin, cend !< Axis specifications associated with the compute
7551 !! domain of the returned 1D domain.
7552integer, intent(in), optional :: gbegin, gend !< Axis specifications associated with the global
7553 !! domain of the returned 1D domain.
7554integer :: ndivs, global_indices(2) !(/ isg, ieg /)
7555integer :: flag
7556! get the global indices of the input domain
7557global_indices(1) = domain_in%global%begin; global_indices(2) = domain_in%global%end
7558
7559! get the layout
7560ndivs = size(domain_in%list(:))
7561
7562! get the flag
7563flag = 0
7564if(domain_in%cyclic) flag = flag + cyclic_global_domain
7565if(domain_in%domain_data%is_global) flag = flag + global_data_domain
7566
7567call mpp_define_domains( global_indices, ndivs, domain_out, pelist = domain_in%list(:)%pe, &
7568 flags = flag, begin_halo = hbegin, end_halo = hend, extent = domain_in%list(:)%compute%size )
7569
7570if(present(cbegin)) domain_out%compute%begin = cbegin
7571if(present(cend)) domain_out%compute%end = cend
7572domain_out%compute%size = domain_out%compute%end - domain_out%compute%begin + 1
7573if(present(gbegin)) domain_out%global%begin = gbegin
7574if(present(gend)) domain_out%global%end = gend
7575domain_out%global%size = domain_out%global%end - domain_out%global%begin + 1
7576
7577end subroutine mpp_modify_domain1d
7578
7579!#######################################################################
7580
7581subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, &
7582 & shalo, nhalo)
7583 ! </PUBLICROUTINE>
7584type(domain2d), intent(in) :: domain_in !< The source domain.
7585type(domain2d), intent(inout) :: domain_out !< The returned domain.
7586integer, intent(in), optional :: isc, iec, jsc, jec !< Zonal and meridional axis specifications
7587 !! associated with the global domain of the returned 2D domain.
7588integer, intent(in), optional :: isg, ieg, jsg, jeg !< Zonal axis specifications associated with
7589 !! the global domain of the returned 2D domain.
7590integer, intent(in), optional :: whalo, ehalo, shalo, nhalo !< halo size in x- and y- directions
7591integer :: global_indices(4), layout(2)
7592integer :: xflag, yflag, nlist, i
7593
7594if(present(whalo) .or. present(ehalo) .or. present(shalo) .or. present(nhalo) ) then
7595 ! get the global indices of the input domain
7596 global_indices(1) = domain_in%x(1)%global%begin; global_indices(2) = domain_in%x(1)%global%end
7597 global_indices(3) = domain_in%y(1)%global%begin; global_indices(4) = domain_in%y(1)%global%end
7598
7599 ! get the layout
7600 layout(1) = size(domain_in%x(1)%list(:)); layout(2) = size(domain_in%y(1)%list(:))
7601
7602 ! get the flag
7603 xflag = 0; yflag = 0
7604 if(domain_in%x(1)%cyclic) xflag = xflag + cyclic_global_domain
7605 if(domain_in%x(1)%domain_data%is_global) xflag = xflag + global_data_domain
7606 if(domain_in%y(1)%cyclic) yflag = yflag + cyclic_global_domain
7607 if(domain_in%y(1)%domain_data%is_global) yflag = yflag + global_data_domain
7608
7609 call mpp_define_domains( global_indices, layout, domain_out, pelist = domain_in%list(:)%pe, &
7610 xflags = xflag, yflags = yflag, whalo = whalo, ehalo = ehalo, &
7611 shalo = shalo, nhalo = nhalo, &
7612 xextent = domain_in%x(1)%list(:)%compute%size, &
7613 yextent = domain_in%y(1)%list(:)%compute%size, &
7614 symmetry=domain_in%symmetry, &
7615 maskmap = domain_in%pearray .NE. null_pe )
7616 domain_out%ntiles = domain_in%ntiles
7617 domain_out%tile_id = domain_in%tile_id
7618else
7619 call mpp_define_null_domain(domain_out)
7620 nlist = size(domain_in%list(:))
7621 if (associated(domain_out%list)) deallocate(domain_out%list) !< Check if allocated
7622 allocate(domain_out%list(0:nlist-1) )
7623 do i = 0, nlist-1
7624 allocate(domain_out%list(i)%tile_id(1))
7625 domain_out%list(i)%tile_id(1) = 1
7626 enddo
7627 call mpp_modify_domain(domain_in%x(1), domain_out%x(1), isc, iec, isg, ieg)
7628 call mpp_modify_domain(domain_in%y(1), domain_out%y(1), jsc, jec, jsg, jeg)
7629 domain_out%ntiles = domain_in%ntiles
7630 domain_out%tile_id = domain_in%tile_id
7631endif
7632
7633end subroutine mpp_modify_domain2d
7634! </SUBROUTINE>
7635
7636!#####################################################################
7637
7638
7639subroutine mpp_define_null_domain1d(domain)
7640type(domain1d), intent(inout) :: domain
7641
7642domain%global%begin = -1; domain%global%end = -1; domain%global%size = 0
7643domain%domain_data%begin = -1; domain%domain_data%end = -1; domain%domain_data%size = 0
7644domain%compute%begin = -1; domain%compute%end = -1; domain%compute%size = 0
7645domain%pe = null_pe
7646
7647end subroutine mpp_define_null_domain1d
7648
7649!#####################################################################
7650
7651
7652subroutine mpp_define_null_domain2d(domain)
7653type(domain2d), intent(inout) :: domain
7654
7655allocate(domain%x(1), domain%y(1), domain%tile_id(1))
7656call mpp_define_null_domain(domain%x(1))
7657call mpp_define_null_domain(domain%y(1))
7658domain%pe = null_pe
7659domain%tile_id(1) = 1
7660domain%ntiles = 1
7661domain%max_ntile_pe = 1
7662domain%ncontacts = 0
7663
7664end subroutine mpp_define_null_domain2d
7665
7666!####################################################################
7667
7668subroutine mpp_deallocate_domain1d(domain)
7669 type(domain1d), intent(inout) :: domain
7670
7671 if(ASSOCIATED(domain%list)) deallocate(domain%list)
7672
7673end subroutine mpp_deallocate_domain1d
7674
7675!####################################################################
7676
7677subroutine mpp_deallocate_domain2d(domain)
7678 type(domain2d), intent(inout) :: domain
7679
7680 call deallocate_domain2d_local(domain)
7681 if(ASSOCIATED(domain%io_domain) ) then
7682 call deallocate_domain2d_local(domain%io_domain)
7683 deallocate(domain%io_domain)
7684 endif
7685
7686end subroutine mpp_deallocate_domain2d
7687
7688!##################################################################
7689
7690subroutine deallocate_domain2d_local(domain)
7691type(domain2d), intent(inout) :: domain
7692integer :: i, ntileMe
7693
7694ntileme = size(domain%x(:))
7695
7696if(ASSOCIATED(domain%pearray))deallocate(domain%pearray)
7697do i = 1, ntileme
7698 call mpp_deallocate_domain1d(domain%x(i))
7699 call mpp_deallocate_domain1d(domain%y(i))
7700enddo
7701deallocate(domain%x, domain%y, domain%tile_id)
7702
7703! TODO: Check if these are always allocated
7704if(ASSOCIATED(domain%tileList)) deallocate(domain%tileList)
7705if(ASSOCIATED(domain%tile_id_all)) deallocate(domain%tile_id_all)
7706
7707if(ASSOCIATED(domain%list)) then
7708 do i = 0, size(domain%list(:))-1
7709 deallocate(domain%list(i)%x, domain%list(i)%y, domain%list(i)%tile_id)
7710 enddo
7711 deallocate(domain%list)
7712endif
7713
7714if(ASSOCIATED(domain%check_C)) then
7715 call deallocate_overlapspec(domain%check_C)
7716 deallocate(domain%check_C)
7717endif
7718
7719if(ASSOCIATED(domain%check_E)) then
7720 call deallocate_overlapspec(domain%check_E)
7721 deallocate(domain%check_E)
7722endif
7723
7724if(ASSOCIATED(domain%check_N)) then
7725 call deallocate_overlapspec(domain%check_N)
7726 deallocate(domain%check_N)
7727endif
7728
7729if(ASSOCIATED(domain%bound_C)) then
7730 call deallocate_overlapspec(domain%bound_C)
7731 deallocate(domain%bound_C)
7732endif
7733
7734if(ASSOCIATED(domain%bound_E)) then
7735 call deallocate_overlapspec(domain%bound_E)
7736 deallocate(domain%bound_E)
7737endif
7738
7739if(ASSOCIATED(domain%bound_N)) then
7740 call deallocate_overlapspec(domain%bound_N)
7741 deallocate(domain%bound_N)
7742endif
7743
7744if(ASSOCIATED(domain%update_T)) then
7745 call deallocate_overlapspec(domain%update_T)
7746 deallocate(domain%update_T)
7747endif
7748
7749if(ASSOCIATED(domain%update_E)) then
7750 call deallocate_overlapspec(domain%update_E)
7751 deallocate(domain%update_E)
7752endif
7753
7754if(ASSOCIATED(domain%update_C)) then
7755 call deallocate_overlapspec(domain%update_C)
7756 deallocate(domain%update_C)
7757endif
7758
7759if(ASSOCIATED(domain%update_N)) then
7760 call deallocate_overlapspec(domain%update_N)
7761 deallocate(domain%update_N)
7762endif
7763
7764end subroutine deallocate_domain2d_local
7765
7766!####################################################################
7767
7768subroutine allocate_check_overlap(overlap, count)
7769 type(overlap_type), intent(inout) :: overlap
7770 integer, intent(in ) :: count
7771
7772 overlap%count = 0
7773 overlap%pe = null_pe
7774 if(associated(overlap%tileMe)) call mpp_error(fatal, &
7775 "allocate_check_overlap(mpp_domains_define): overlap is already been allocated")
7776 if(count < 1) call mpp_error(fatal, &
7777 "allocate_check_overlap(mpp_domains_define): count should be a positive integer")
7778 allocate(overlap%tileMe (count), overlap%dir(count) )
7779 allocate(overlap%is (count), overlap%ie (count) )
7780 allocate(overlap%js (count), overlap%je (count) )
7781 allocate(overlap%rotation(count) )
7782 overlap%rotation = zero
7783
7784end subroutine allocate_check_overlap
7785
7786!#######################################################################
7787subroutine insert_check_overlap(overlap, pe, tileMe, dir, rotation, is, ie, js, je)
7788 type(overlap_type), intent(inout) :: overlap
7789 integer, intent(in ) :: pe
7790 integer, intent(in ) :: tileMe, dir, rotation
7791 integer, intent(in ) :: is, ie, js, je
7792 integer :: count
7793
7794 overlap%count = overlap%count + 1
7795 count = overlap%count
7796 if(.NOT. associated(overlap%tileMe)) call mpp_error(fatal, &
7797 "mpp_domains_define.inc(insert_check_overlap): overlap is not assigned any memory")
7798 if(count > size(overlap%tileMe(:)) ) call mpp_error(fatal, &
7799 "mpp_domains_define.inc(insert_check_overlap): overlap%count is greater than size(overlap%tileMe)")
7800 if( overlap%pe == null_pe ) then
7801 overlap%pe = pe
7802 else
7803 if(overlap%pe .NE. pe) call mpp_error(fatal, &
7804 "mpp_domains_define.inc(insert_check_overlap): mismatch on pe")
7805 endif
7806 overlap%tileMe (count) = tileme
7807 overlap%dir (count) = dir
7808 overlap%rotation(count) = rotation
7809 overlap%is (count) = is
7810 overlap%ie (count) = ie
7811 overlap%js (count) = js
7812 overlap%je (count) = je
7813
7814end subroutine insert_check_overlap
7815
7816!#######################################################################
7817!> this routine adds the overlap_in into overlap_out
7818subroutine add_check_overlap( overlap_out, overlap_in)
7819 type(overlap_type), intent(inout) :: overlap_out
7820 type(overlap_type), intent(in ) :: overlap_in
7821 type(overlap_type) :: overlap
7822 integer :: count, count_in, count_out
7823
7824 ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
7825 count_in = overlap_in %count
7826 count_out = overlap_out%count
7827 count = count_in+count_out
7828 if(count_in == 0) call mpp_error(fatal, &
7829 "add_check_overlap(mpp_domains_define): overlap_in%count is zero")
7830
7831 if(count_out == 0) then
7832 if(associated(overlap_out%tileMe)) call mpp_error(fatal, &
7833 "add_check_overlap(mpp_domains_define): overlap is already been allocated but count=0")
7834 call allocate_check_overlap(overlap_out, count_in)
7835 overlap_out%pe = overlap_in%pe
7836 else ! need to expand the dimension size of overlap
7837 call allocate_check_overlap(overlap, count_out)
7838 if(overlap_out%pe .NE. overlap_in%pe) call mpp_error(fatal, &
7839 "mpp_domains_define.inc(add_check_overlap): mismatch of pe between overlap_in and overlap_out")
7840 overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
7841 overlap%is (1:count_out) = overlap_out%is (1:count_out)
7842 overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
7843 overlap%js (1:count_out) = overlap_out%js (1:count_out)
7844 overlap%je (1:count_out) = overlap_out%je (1:count_out)
7845 overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
7846 overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
7847 call deallocate_overlap_type(overlap_out)
7848 call allocate_check_overlap(overlap_out, count)
7849 overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
7850 overlap_out%is (1:count_out) = overlap%is (1:count_out)
7851 overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
7852 overlap_out%js (1:count_out) = overlap%js (1:count_out)
7853 overlap_out%je (1:count_out) = overlap%je (1:count_out)
7854 overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
7855 overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
7856 call deallocate_overlap_type(overlap)
7857 end if
7858 overlap_out%count = count
7859 overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
7860 overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
7861 overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
7862 overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
7863 overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
7864 overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
7865 overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
7866
7867end subroutine add_check_overlap
7868
7869!####################################################################
7870subroutine init_overlap_type(overlap)
7871 type(overlap_type), intent(inout) :: overlap
7872
7873 overlap%count = 0
7874 overlap%pe = null_pe
7875
7876end subroutine init_overlap_type
7877
7878!####################################################################
7879
7880subroutine allocate_update_overlap( overlap, count)
7881 type(overlap_type), intent(inout) :: overlap
7882 integer, intent(in ) :: count
7883
7884 overlap%count = 0
7885 overlap%pe = null_pe
7886 if(associated(overlap%tileMe)) call mpp_error(fatal, &
7887 "allocate_update_overlap(mpp_domains_define): overlap is already been allocated")
7888 if(count < 1) call mpp_error(fatal, &
7889 "allocate_update_overlap(mpp_domains_define): count should be a positive integer")
7890 allocate(overlap%tileMe (count), overlap%tileNbr (count) )
7891 allocate(overlap%is (count), overlap%ie (count) )
7892 allocate(overlap%js (count), overlap%je (count) )
7893 allocate(overlap%dir (count), overlap%rotation(count) )
7894 allocate(overlap%from_contact(count), overlap%msgsize (count) )
7895 overlap%rotation = zero
7896 overlap%from_contact = .false.
7897
7898end subroutine allocate_update_overlap
7899
7900 !#####################################################################################
7901 subroutine insert_update_overlap(overlap, pe, is1, ie1, js1, je1, is2, ie2, js2, je2, dir, reverse, symmetry)
7902 type(overlap_type), intent(inout) :: overlap
7903 integer, intent(in ) :: pe
7904 integer, intent(in ) :: is1, ie1, js1, je1, is2, ie2, js2, je2
7905 integer, intent(in ) :: dir
7906 logical, optional, intent(in ) :: reverse, symmetry
7907
7908 logical :: is_reverse, is_symmetry, is_overlapped
7909 integer :: is, ie, js, je, count
7910
7911 is_reverse = .false.
7912 if(PRESENT(reverse)) is_reverse = reverse
7913 is_symmetry = .false.
7914 if(PRESENT(symmetry)) is_symmetry = symmetry
7915
7916 is = max(is1,is2); ie = min(ie1,ie2)
7917 js = max(js1,js2); je = min(je1,je2)
7918 is_overlapped = .false.
7919 !--- to avoid unnecessary ( duplicate overlap ) for symmetry domain
7920 if(is_symmetry .AND. (dir == 1 .OR. dir == 5)) then ! x-direction
7921 if( ie .GE. is .AND. je .GT. js ) is_overlapped = .true.
7922 else if(is_symmetry .AND. (dir == 3 .OR. dir == 7)) then ! y-direction
7923 if( ie .GT. is .AND. je .GE. js ) is_overlapped = .true.
7924 else if(ie.GE.is .AND. je.GE.js )then
7925 is_overlapped = .true.
7926 endif
7927
7928 if(is_overlapped) then
7929 if( overlap%count == 0 ) then
7930 overlap%pe = pe
7931 else
7932 if(overlap%pe .NE. pe) call mpp_error(fatal, &
7933 "mpp_domains_define.inc(insert_update_overlap): mismatch on pe")
7934 endif
7935 overlap%count = overlap%count+1
7936 count = overlap%count
7937 if(count > maxoverlap) call mpp_error(fatal, "mpp_domains_define.inc(insert_update_overlap):"//&
7938 & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7939 overlap%is(count) = is
7940 overlap%ie(count) = ie
7941 overlap%js(count) = js
7942 overlap%je(count) = je
7943 overlap%tileMe (count) = 1
7944 overlap%tileNbr(count) = 1
7945 overlap%dir(count) = dir
7946 if(is_reverse) then
7947 overlap%rotation(count) = one_hundred_eighty
7948 else
7949 overlap%rotation(count) = zero
7950 end if
7951 end if
7952
7953 end subroutine insert_update_overlap
7954
7955 !#####################################################################################
7956subroutine insert_overlap_type(overlap, pe, tileMe, tileNbr, is, ie, js, je, dir, &
7957 rotation, from_contact)
7958 type(overlap_type), intent(inout) :: overlap
7959 integer, intent(in ) :: tileMe, tileNbr, pe
7960 integer, intent(in ) :: is, ie, js, je
7961 integer, intent(in ) :: dir, rotation
7962 logical, intent(in ) :: from_contact
7963 integer :: count
7964
7965 if( overlap%count == 0 ) then
7966 overlap%pe = pe
7967 else
7968 if(overlap%pe .NE. pe) call mpp_error(fatal, &
7969 "mpp_domains_define.inc(insert_overlap_type): mismatch on pe")
7970 endif
7971 overlap%count = overlap%count+1
7972 count = overlap%count
7973 if(count > maxoverlap) call mpp_error(fatal, "mpp_domains_define.inc(insert_overlap_type):"//&
7974 & " number of overlap is greater than MAXOVERLAP, increase MAXOVERLAP")
7975 overlap%tileMe (count) = tileme
7976 overlap%tileNbr (count) = tilenbr
7977 overlap%is (count) = is
7978 overlap%ie (count) = ie
7979 overlap%js (count) = js
7980 overlap%je (count) = je
7981 overlap%dir (count) = dir
7982 overlap%rotation (count) = rotation
7983 overlap%from_contact(count) = from_contact
7984 overlap%msgsize (count) = (ie-is+1)*(je-js+1)
7985
7986end subroutine insert_overlap_type
7987
7988
7989!#######################################################################
7990subroutine deallocate_overlap_type( overlap)
7991 type(overlap_type), intent(inout) :: overlap
7992
7993 if(overlap%count == 0) then
7994 if( .NOT. associated(overlap%tileMe)) return
7995 else
7996 if( .NOT. associated(overlap%tileMe)) call mpp_error(fatal, &
7997 "deallocate_overlap_type(mpp_domains_define): overlap is not been allocated")
7998 endif
7999 if(ASSOCIATED(overlap%tileMe)) deallocate(overlap%tileMe)
8000 if(ASSOCIATED(overlap%tileNbr)) deallocate(overlap%tileNbr)
8001 if(ASSOCIATED(overlap%is)) deallocate(overlap%is)
8002 if(ASSOCIATED(overlap%ie)) deallocate(overlap%ie)
8003 if(ASSOCIATED(overlap%js)) deallocate(overlap%js)
8004 if(ASSOCIATED(overlap%je)) deallocate(overlap%je)
8005 if(ASSOCIATED(overlap%dir)) deallocate(overlap%dir)
8006 if(ASSOCIATED(overlap%index)) deallocate(overlap%index)
8007 if(ASSOCIATED(overlap%rotation)) deallocate(overlap%rotation)
8008 if(ASSOCIATED(overlap%from_contact)) deallocate(overlap%from_contact)
8009 if(ASSOCIATED(overlap%msgsize)) deallocate(overlap%msgsize)
8010 overlap%count = 0
8011
8012end subroutine deallocate_overlap_type
8013
8014!#######################################################################
8015subroutine deallocate_overlapspec(overlap)
8016type(overlapspec), intent(inout) :: overlap
8017integer :: n
8018
8019 if(ASSOCIATED(overlap%send)) then
8020 do n = 1, size(overlap%send(:))
8021 call deallocate_overlap_type(overlap%send(n))
8022 enddo
8023 deallocate(overlap%send)
8024 endif
8025 if(ASSOCIATED(overlap%recv)) then
8026 do n = 1, size(overlap%recv(:))
8027 call deallocate_overlap_type(overlap%recv(n))
8028 enddo
8029 deallocate(overlap%recv)
8030 endif
8031
8032
8033end subroutine deallocate_overlapspec
8034
8035!#######################################################################
8036!--- this routine add the overlap_in into overlap_out
8037subroutine add_update_overlap( overlap_out, overlap_in)
8038 type(overlap_type), intent(inout) :: overlap_out
8039 type(overlap_type), intent(in ) :: overlap_in
8040 type(overlap_type) :: overlap
8041 integer :: count, count_in, count_out, n
8042
8043 ! if overlap_out%count == 0, then just copy overlap_in to overlap_out
8044 count_in = overlap_in %count
8045 count_out = overlap_out%count
8046 count = count_in+count_out
8047 if(count_in == 0) call mpp_error(fatal, &
8048 "mpp_domains_define.inc(add_update_overlap): overlap_in%count is zero")
8049
8050 if(count_out == 0) then
8051 if(associated(overlap_out%tileMe)) call mpp_error(fatal, &
8052 "mpp_domains_define.inc(add_update_overlap): overlap is already been allocated but count=0")
8053 call allocate_update_overlap(overlap_out, count_in)
8054 overlap_out%pe = overlap_in%pe
8055 else ! need to expand the dimension size of overlap
8056 if(overlap_in%pe .NE. overlap_out%pe) call mpp_error(fatal, &
8057 "mpp_domains_define.inc(add_update_overlap): mismatch of pe between overlap_in and overlap_out")
8058
8059 call allocate_update_overlap(overlap, count_out)
8060 overlap%tileMe (1:count_out) = overlap_out%tileMe (1:count_out)
8061 overlap%tileNbr (1:count_out) = overlap_out%tileNbr (1:count_out)
8062 overlap%is (1:count_out) = overlap_out%is (1:count_out)
8063 overlap%ie (1:count_out) = overlap_out%ie (1:count_out)
8064 overlap%js (1:count_out) = overlap_out%js (1:count_out)
8065 overlap%je (1:count_out) = overlap_out%je (1:count_out)
8066 overlap%dir (1:count_out) = overlap_out%dir (1:count_out)
8067 overlap%rotation (1:count_out) = overlap_out%rotation (1:count_out)
8068 overlap%from_contact(1:count_out) = overlap_out%from_contact(1:count_out)
8069 call deallocate_overlap_type(overlap_out)
8070 call allocate_update_overlap(overlap_out, count)
8071 overlap_out%tileMe (1:count_out) = overlap%tileMe (1:count_out)
8072 overlap_out%tileNbr (1:count_out) = overlap%tileNbr (1:count_out)
8073 overlap_out%is (1:count_out) = overlap%is (1:count_out)
8074 overlap_out%ie (1:count_out) = overlap%ie (1:count_out)
8075 overlap_out%js (1:count_out) = overlap%js (1:count_out)
8076 overlap_out%je (1:count_out) = overlap%je (1:count_out)
8077 overlap_out%dir (1:count_out) = overlap%dir (1:count_out)
8078 overlap_out%rotation (1:count_out) = overlap%rotation (1:count_out)
8079 overlap_out%index (1:count_out) = overlap%index (1:count_out)
8080 overlap_out%from_contact(1:count_out) = overlap%from_contact(1:count_out)
8081 overlap_out%msgsize (1:count_out) = overlap%msgsize (1:count_out)
8082 call deallocate_overlap_type(overlap)
8083 end if
8084 overlap_out%count = count
8085 overlap_out%tileMe (count_out+1:count) = overlap_in%tileMe (1:count_in)
8086 overlap_out%tileNbr (count_out+1:count) = overlap_in%tileNbr (1:count_in)
8087 overlap_out%is (count_out+1:count) = overlap_in%is (1:count_in)
8088 overlap_out%ie (count_out+1:count) = overlap_in%ie (1:count_in)
8089 overlap_out%js (count_out+1:count) = overlap_in%js (1:count_in)
8090 overlap_out%je (count_out+1:count) = overlap_in%je (1:count_in)
8091 overlap_out%dir (count_out+1:count) = overlap_in%dir (1:count_in)
8092 overlap_out%rotation (count_out+1:count) = overlap_in%rotation (1:count_in)
8093 overlap_out%from_contact(count_out+1:count) = overlap_in%from_contact(1:count_in)
8094
8095 do n = count_out+1, count
8096 overlap_out%msgsize(n) = (overlap_out%ie(n)-overlap_out%is(n)+1)*(overlap_out%je(n)-overlap_out%js(n)+1)
8097 enddo
8098
8099
8100end subroutine add_update_overlap
8101
8102!##############################################################################
8103subroutine expand_update_overlap_list(overlapList, npes)
8104 type(overlap_type), pointer :: overlapList(:)
8105 integer, intent(in ) :: npes
8106 type(overlap_type), pointer,save :: newlist(:) => null()
8107 integer :: nlist_old, nlist, m
8108
8109 nlist_old = size(overlaplist(:))
8110 if(nlist_old .GE. npes) call mpp_error(fatal, &
8111 'mpp_domains_define.inc(expand_update_overlap_list): size of overlaplist should be smaller than npes')
8112 nlist = min(npes, 2*nlist_old)
8113 allocate(newlist(nlist))
8114 do m = 1, nlist_old
8115 call add_update_overlap(newlist(m), overlaplist(m))
8116 call deallocate_overlap_type(overlaplist(m))
8117 enddo
8118
8119 deallocate(overlaplist)
8120 overlaplist => newlist
8121 newlist => null()
8122
8123 return
8124
8125end subroutine expand_update_overlap_list
8126
8127!##################################################################################
8128subroutine expand_check_overlap_list(overlaplist, npes)
8129 type(overlap_type), pointer :: overlaplist(:)
8130 integer, intent(in) :: npes
8131 type(overlap_type), pointer,save :: newlist(:) => null()
8132 integer :: nlist_old, nlist, m
8133
8134 nlist_old = size(overlaplist(:))
8135 if(nlist_old .GE. npes) call mpp_error(fatal, &
8136 'mpp_domains_define.inc(expand_check_overlap_list): size of overlaplist should be smaller than npes')
8137 nlist = min(npes, 2*nlist_old)
8138 allocate(newlist(nlist))
8139 do m = 1,size(overlaplist(:))
8140 call add_check_overlap(newlist(m), overlaplist(m))
8141 call deallocate_overlap_type(overlaplist(m))
8142 enddo
8143 deallocate(overlaplist)
8144 overlaplist => newlist
8145
8146
8147 return
8148
8149end subroutine expand_check_overlap_list
8150
8151
8152!###############################################################################
8153subroutine check_overlap_pe_order(domain, overlap, name)
8154 type(domain2d), intent(in) :: domain
8155 type(overlapspec), intent(in) :: overlap
8156 character(len=*), intent(in) :: name
8157 integer :: m
8158 integer :: pe1, pe2
8159
8160 !---make sure overlap%nsend and overlap%nrecv is no larger than MAXLIST
8161 if( overlap%nsend > maxlist) call mpp_error(fatal, &
8162 "mpp_domains_define.inc(check_overlap_pe_order): overlap%nsend > MAXLIST, increase MAXLIST")
8163 if( overlap%nrecv > maxlist) call mpp_error(fatal, &
8164 "mpp_domains_define.inc(check_overlap_pe_order): overlap%nrecv > MAXLIST, increase MAXLIST")
8165
8166 do m = 2, overlap%nsend
8167 pe1 = overlap%send(m-1)%pe
8168 pe2 = overlap%send(m)%pe
8169 !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8170 if( pe2 == domain%pe ) then
8171 print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8172 call mpp_error(fatal, &
8173 "mpp_domains_define.inc(check_overlap_pe_order): send pe2 can not equal to domain%pe")
8174 else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8175 if( pe2 < pe1 ) then
8176 print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8177 call mpp_error(fatal, &
8178 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 1")
8179 endif
8180 else if ( pe2 > domain%pe .AND. pe1 < domain%pe ) then
8181 print*, trim(name)//" at pe = ", domain%pe, ": send pe is ", pe1, pe2
8182 call mpp_error(fatal, &
8183 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for send 2")
8184 endif
8185 enddo
8186
8187
8188 do m = 2, overlap%nrecv
8189 pe1 = overlap%recv(m-1)%pe
8190 pe2 = overlap%recv(m)%pe
8191 !-- when p1 == domain%pe, pe2 could be any value except domain%pe
8192 if( pe2 == domain%pe ) then
8193 print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8194 call mpp_error(fatal, &
8195 "mpp_domains_define.inc(check_overlap_pe_order): recv pe2 can not equal to domain%pe")
8196 else if( (pe1 > domain%pe .AND. pe2 > domain%pe) .OR. (pe1 < domain%pe .AND. pe2 < domain%pe)) then
8197 if( pe2 > pe1 ) then
8198 print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8199 call mpp_error(fatal, &
8200 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 1")
8201 endif
8202 else if ( pe2 < domain%pe .AND. pe1 > domain%pe ) then
8203 print*, trim(name)//" at pe = ", domain%pe, ": recv pe is ", pe1, pe2
8204 call mpp_error(fatal, &
8205 "mpp_domains_define.inc(check_overlap_pe_order): pe is not in right order for recv 2")
8206 endif
8207 enddo
8208
8209
8210end subroutine check_overlap_pe_order
8211
8212
8213!###############################################################################
8214subroutine set_domain_comm_inf(update)
8215 type(overlapspec), intent(inout) :: update
8216
8217 integer :: m, totsize, n
8218
8219
8220 ! first set the send and recv size
8221 update%sendsize = 0
8222 update%recvsize = 0
8223 do m = 1, update%nrecv
8224 totsize = 0
8225 do n = 1, update%recv(m)%count
8226 totsize = totsize + update%recv(m)%msgsize(n)
8227 enddo
8228 update%recv(m)%totsize = totsize
8229 if(m==1) then
8230 update%recv(m)%start_pos = 0
8231 else
8232 update%recv(m)%start_pos = update%recv(m-1)%start_pos + update%recv(m-1)%totsize
8233 endif
8234 update%recvsize = update%recvsize + totsize
8235 enddo
8236
8237 do m = 1, update%nsend
8238 totsize = 0
8239 do n = 1, update%send(m)%count
8240 totsize = totsize + update%send(m)%msgsize(n)
8241 enddo
8242 update%send(m)%totsize = totsize
8243 if(m==1) then
8244 update%send(m)%start_pos = 0
8245 else
8246 update%send(m)%start_pos = update%send(m-1)%start_pos + update%send(m-1)%totsize
8247 endif
8248 update%sendsize = update%sendsize + totsize
8249 enddo
8250
8251 return
8252
8253
8254end subroutine set_domain_comm_inf
8255!> @}
subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, shalo, nhalo)
subroutine define_contact_point(domain, position, num_contact, tile1, tile2, align1, align2, refine1, refine2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, isglist, ieglist, jsglist, jeglist)
compute the overlapping between tiles for the T-cell.
subroutine 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 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_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 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...