Yet Another eXchange Tool  DO_NOT_EDIT_HERE
test_yaxt.f90
1 
12 
13 !
14 ! Keywords:
15 ! Maintainer: Jörg Behrens <behrens@dkrz.de>
16 ! Moritz Hanke <hanke@dkrz.de>
17 ! Thomas Jahns <jahns@dkrz.de>
18 ! URL: https://doc.redmine.dkrz.de/yaxt/html/
19 !
20 ! Redistribution and use in source and binary forms, with or without
21 ! modification, are permitted provided that the following conditions are
22 ! met:
23 !
24 ! Redistributions of source code must retain the above copyright notice,
25 ! this list of conditions and the following disclaimer.
26 !
27 ! Redistributions in binary form must reproduce the above copyright
28 ! notice, this list of conditions and the following disclaimer in the
29 ! documentation and/or other materials provided with the distribution.
30 !
31 ! Neither the name of the DKRZ GmbH nor the names of its contributors
32 ! may be used to endorse or promote products derived from this software
33 ! without specific prior written permission.
34 !
35 ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
36 ! IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
37 ! TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
38 ! PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
39 ! OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40 ! EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41 ! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42 ! PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
43 ! LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44 ! NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45 ! SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 !
47 
48 PROGRAM test_yaxt
49  USE iso_c_binding, ONLY: c_int
50  USE mpi
51  USE yaxt, ONLY: xt_idxlist, xt_idxlist_delete, xt_idxvec_new, &
53  & xt_redist, xt_redist_p2p_new, xt_redist_delete, &
57  xt_idxfsection_new, xt_redist_collection_static_new
58  USE ftest_common, ONLY: test_abort, icmp, id_map, factorize, regular_deco, &
59  finish_mpi
60 
61  ! PGI compilers up to at least version 15 do not handle generic
62  ! interfaces correctly
63 #if defined __PGI
67 #endif
68  IMPLICIT NONE
69 
70  INTEGER, PARAMETER :: g_ie = 8, g_je = 4! global extents including halos
71  LOGICAL, PARAMETER :: verbose = .false.
72  INTEGER, PARAMETER :: nlev = 3
73  INTEGER, PARAMETER :: undef_int = -1
74  INTEGER(xt_int_kind), PARAMETER :: undef_index = -1
75  INTEGER, PARAMETER :: nhalo = 1 ! 1dim. halo border size
76  LOGICAL, PARAMETER :: increased_north_halo = .false.
77  LOGICAL, PARAMETER :: with_north_halo = .true.
78 
79  INTEGER :: ie, je ! local extents, including halos
80  INTEGER :: p_ioff, p_joff ! offsets within global domain
81  INTEGER :: nprocx, nprocy ! process space extents
82  INTEGER :: nprocs ! == nprocx*nprocy
83  INTEGER :: mype, mypx, mypy ! process rank, process coords within (0:, 0:) process space
84  LOGICAL :: lroot ! true only for proc 0
85 
86  INTEGER(xt_int_kind) :: g_id(g_ie, g_je) ! global id
87 
88  ! global "tripolar-like" toy bounds exchange
89  INTEGER(xt_int_kind) :: g_tpex(g_ie, g_je)
90  TYPE(xt_xmap) :: xmap_tpex
91  TYPE(xt_redist) :: redist_tpex
92  TYPE(xt_redist) :: redist_surf_tpex
93 
94  INTEGER(xt_int_kind), ALLOCATABLE :: loc_id(:,:), loc_tpex(:,:)
95  INTEGER(c_int), ALLOCATABLE :: mstate(:,:)
96  INTEGER, ALLOCATABLE :: fval(:,:), gval(:,:)
97  INTEGER, ALLOCATABLE :: gval3d(:,:,:)
98  INTEGER, ALLOCATABLE :: id_pos(:,:), pos3d_surf(:,:)
99 
100  ! mpi & decomposition & allocate mem:
101  CALL init_all
102 
103  ! full global index space:
104  CALL id_map(g_id)
105 
106  ! local window of global index space:
107  CALL get_window(g_id, loc_id)
108 
109  ! define bounds exchange for full global index space
110  CALL def_exchange(g_id, g_tpex)
111 
112  ! local window of global bounds exchange:
113  CALL get_window(g_tpex, loc_tpex)
114 
115  ! check interface to idxsection:
116  CALL general_fsection_test
117 
118  ! compare current index construction with modifier results
119  CALL check_modifiers
120 
121  ! template: loc_id -> loc_tpex
122  CALL gen_template(loc_id, loc_tpex, xmap_tpex) ! todo rename template to xmap
123 
124  ! transposition: loc_id:data -> loc_tpex:data
125  CALL gen_trans(xmap_tpex, mpi_integer, mpi_integer, redist_tpex)
126 
127  ! test 2d-to-2d transposition:
128  fval = int(loc_id)
129  CALL xt_redist_s_exchange(redist_tpex, fval, gval)
130 
131  CALL icmp('2d to 2d check', gval, int(loc_tpex), mype)
132 
133  CALL check_redist_collection_static
134 
135  ! define positions of surface elements within (i,k,j) array
136  CALL gen_id_pos(id_pos)
137  CALL gen_id_pos(pos3d_surf)
138  CALL gen_pos3d_surf(pos3d_surf)
139 
140  ! generate surface transposition:
141  CALL gen_off_trans(xmap_tpex, mpi_integer, int(id_pos(:,:)) - 1, &
142  mpi_integer, int(pos3d_surf(:,:)) - 1, redist_surf_tpex)
143 
144  ! 2d to surface boundsexchange:
145  gval3d = -1
146  CALL xt_redist_s_exchange(redist_surf_tpex, &
147  reshape(fval, (/ ie, je, 1 /)), gval3d)
148 
149  CALL icmp('surface check', gval3d(:,1,:), int(loc_tpex), mype)
150  ! check sub surface:
151  CALL icmp('sub surface check', gval3d(:,2,:), int(loc_tpex)*0-1, mype)
152 
153  ! cleanup:
154  CALL xt_xmap_delete(xmap_tpex)
155 
156  CALL xt_redist_delete(redist_tpex)
157 
158  CALL xt_redist_delete(redist_surf_tpex)
159 
160  CALL xt_finalize()
161  CALL finish_mpi
162 
163 CONTAINS
164 
165  SUBROUTINE check_redist_collection_static
166  INTEGER, PARAMETER :: nr = 2
167  TYPE(xt_redist) :: rvec(nr), rcol
168  INTEGER, TARGET :: f(ie,je,nr), g(ie,je,nr), ref_g(ie,je,nr)
169  INTEGER(mpi_address_kind) :: f_addr(nr), g_addr(nr)
170  INTEGER(mpi_address_kind) :: f_disp(nr), g_disp(nr)
171 
172  INTEGER :: ir, ierror
173  rvec(:) = redist_tpex
174  DO ir = 1, nr
175  CALL mpi_get_address(f(1,1,ir), f_addr(ir), ierror)
176  IF (ierror /= mpi_success) CALL my_abort('MPI_GET_ADDRESS failed', __line__)
177  CALL mpi_get_address(g(1,1,ir), g_addr(ir), ierror)
178  IF (ierror /= mpi_success) CALL my_abort('MPI_GET_ADDRESS failed', __line__)
179  f_disp(ir) = f_addr(ir) - f_addr(1)
180  g_disp(ir) = g_addr(ir) - g_addr(1)
181  ENDDO
182 
183  rcol = xt_redist_collection_static_new(rvec, nr, f_disp, g_disp, mpi_comm_world)
184  DO ir = 1, nr
185  f(:,:,ir) = int(loc_id) + (ir-1) * ie*je
186  ENDDO
187 
188  ref_g = 0
189  DO ir = 1, nr
190  CALL xt_redist_s_exchange(rvec(ir), f(:,:,ir), ref_g(:,:,ir))
191  ENDDO
192 
193  g = 0
194  CALL xt_redist_s_exchange(rcol, f, g)
195  IF (any(g /= ref_g)) CALL my_abort('(g /= ref_g)', __line__)
196  CALL xt_redist_delete(rcol)
197 
198  END SUBROUTINE check_redist_collection_static
199 
200  SUBROUTINE check_modifiers()
201  TYPE(xt_modifier) :: m_tpex(5)
202  INTEGER :: m_tpex_num
203  TYPE(xt_idxlist) :: loc_id_idxlist
204  INTEGER(xt_int_kind) :: loc_tpex2(ie,je)
205  TYPE(xt_idxlist) :: loc_tpex2_idxlist
206 
207  loc_id_idxlist = xt_idxvec_new(loc_id, SIZE(loc_id))
208 
209  ! use one simple modifier to define index transfer:
210  CALL def_tpex_mod_via_idxvec(m_tpex, m_tpex_num)
211 
212  loc_tpex2_idxlist = xt_idxmod_new(loc_id_idxlist, m_tpex, m_tpex_num, mstate)
213  loc_tpex2 = -1
214  CALL xt_idxlist_get_indices(loc_tpex2_idxlist, loc_tpex2)
215  IF (any(loc_tpex2 /= loc_tpex)) &
216  CALL my_abort('idx copy does not match', __line__)
217  CALL xt_idxlist_delete(loc_tpex2_idxlist)
218 
219  ! test call without mstate
220  loc_tpex2_idxlist = xt_idxmod_new(loc_id_idxlist, m_tpex, m_tpex_num)
221  loc_tpex2 = -1
222  CALL xt_idxlist_get_indices(loc_tpex2_idxlist, loc_tpex2)
223  IF (any(loc_tpex2 /= loc_tpex)) &
224  CALL my_abort('idx copy does not match', __line__)
225  CALL xt_idxlist_delete(loc_tpex2_idxlist)
226  CALL delete_modifiers(m_tpex(1:m_tpex_num))
227 
228  ! use compact modifiers to define index transfer:
229  CALL def_tpex_mod_via_sections(m_tpex, m_tpex_num)
230  loc_tpex2_idxlist = xt_idxmod_new(loc_id_idxlist, m_tpex, m_tpex_num, mstate)
231  loc_tpex2 = -1
232  CALL xt_idxlist_get_indices(loc_tpex2_idxlist, loc_tpex2)
233 
234  IF (any(loc_tpex2 /= loc_tpex)) &
235  CALL my_abort('idx copy does not match', __line__)
236  CALL xt_idxlist_delete(loc_tpex2_idxlist)
237  CALL delete_modifiers(m_tpex(1:m_tpex_num))
238 
239  ! cleanup:
240  CALL xt_idxlist_delete(loc_id_idxlist)
241  END SUBROUTINE check_modifiers
242 
243  SUBROUTINE delete_modifiers(m)
244  TYPE(xt_modifier), INTENT(inout) :: m(:)
245 
246  INTEGER :: i
247 
248  DO i = 1, SIZE(m)
249  CALL xt_idxlist_delete(m(i)%extract)
250  CALL xt_idxlist_delete(m(i)%subst)
251  ENDDO
252 
253  END SUBROUTINE delete_modifiers
254 
255  SUBROUTINE my_abort(msg, line)
256  CHARACTER(*), INTENT(in) :: msg
257  INTEGER, VALUE, INTENT(in) :: line
258  CALL test_abort(msg, &
259  __file__, &
260  line)
261  END SUBROUTINE my_abort
262 
263  SUBROUTINE general_fsection_test
264  INTEGER(xt_int_kind), PARAMETER :: gdx = 10_xt_int_kind, gdy=5_xt_int_kind
265  INTEGER, PARAMETER :: ldx = 4, ldy=2
266  INTEGER(xt_int_kind), PARAMETER :: gstart = 1
267  INTEGER(xt_int_kind), PARAMETER :: gsize(2) = (/ gdx, gdy /)
268  TYPE(xt_idxlist) :: global_section, local_section
269  INTEGER(xt_int_kind) :: indices(gdx*gdy), lstart(2)
270  INTEGER :: egis(gdx, gdy)
271  INTEGER :: i, j, idx, p
272 
273  ! prepare explicit global index space
274  idx = gstart - 1
275  DO j = 1, gdy
276  DO i = 1, gdx
277  idx = idx + 1
278  egis(i,j) = idx
279  ENDDO
280  ENDDO
281 
282  lstart = (/ 1_xt_int_kind, 1_xt_int_kind /)
283 
284  ! check case: local section == global section
285  global_section = xt_idxfsection_new(gstart, gsize, int(gsize), lstart)
286  indices = -1
287  CALL xt_idxlist_get_indices(global_section, indices)
288  p = 0
289  DO j = 1, gdy
290  DO i = 1, gdx
291  p = p + 1
292  IF (egis(i,j) /= indices(p)) CALL my_abort('(1) bad indices', __line__)
293  ENDDO
294  ENDDO
295  CALL xt_idxlist_delete(global_section)
296 
297  ! check case: simple subsection
298  local_section = xt_idxfsection_new(gstart, gsize, (/ ldx, ldy /), lstart)
299  indices = -1
300  CALL xt_idxlist_get_indices(local_section, indices)
301  p = 0
302  DO j = 1, ldy
303  DO i = 1, ldx
304  p = p + 1
305  IF (egis(i,j) /= indices(p)) CALL my_abort('(2) bad indices', __line__)
306  ENDDO
307  ENDDO
308  CALL xt_idxlist_delete(local_section)
309 
310  ! check case: i-reverse subsection
311  local_section = xt_idxfsection_new(gstart, gsize, &
312  (/ -ldx, ldy /), lstart)
313  indices = -1
314  CALL xt_idxlist_get_indices(local_section, indices)
315  p = 0
316  DO j = 1, ldy
317  DO i = ldx, 1, -1
318  p = p + 1
319  IF (egis(i,j) /= indices(p)) CALL my_abort('(3) bad indices', __line__)
320  ENDDO
321  ENDDO
322  CALL xt_idxlist_delete(local_section)
323 
324  ! check case: j-reverse subsection
325  local_section = xt_idxfsection_new(gstart, gsize, (/ ldx, -ldy /), lstart)
326  indices = -1
327  CALL xt_idxlist_get_indices(local_section, indices)
328  p = 0
329  DO j = ldy, 1, -1
330  DO i = 1, ldx
331  p = p + 1
332  IF (egis(i,j) /= indices(p)) CALL my_abort('(4) bad indices', __line__)
333  ENDDO
334  ENDDO
335  CALL xt_idxlist_delete(local_section)
336 
337  ! check case: ij-reverse subsection
338  local_section = xt_idxfsection_new(gstart, gsize, &
339  (/ -ldx, -ldy /), lstart)
340  indices = -1
341  CALL xt_idxlist_get_indices(local_section, indices)
342  p = 0
343  DO j = ldy, 1, -1
344  DO i = ldx, 1, -1
345  p = p + 1
346  IF (egis(i,j) /= indices(p)) CALL my_abort('(5) bad indices', __line__)
347  ENDDO
348  ENDDO
349  CALL xt_idxlist_delete(local_section)
350  END SUBROUTINE general_fsection_test
351 
352  SUBROUTINE gen_pos3d_surf(pos)
353  INTEGER, INTENT(inout) :: pos(:,:)
354  ! positions for zero based arrays (ECHAM grid point dim order)
355  ! old pos = i + j*ie
356  ! new pos = i + k*ie + j*ie*nlev
357  INTEGER :: ii,jj, i,j,k, p,q
358 
359  k = 0 ! surface
360  DO jj=1,je
361  DO ii=1,ie
362  p = pos(ii,jj) - 1 ! shift to 0-based index
363  j = p/ie
364  i = mod(p,ie)
365  q = i + k*ie + j*ie*nlev
366  pos(ii,jj) = q + 1 ! shift to 1-based index
367  ENDDO
368  ENDDO
369 
370  END SUBROUTINE gen_pos3d_surf
371 
372  SUBROUTINE init_all
373  CHARACTER(len=*), PARAMETER :: context = 'init_all: '
374  INTEGER :: ierror
375 
376  CALL mpi_init(ierror)
377  IF (ierror /= mpi_success) &
378  CALL my_abort(context//'MPI_INIT failed', __line__)
379 
380  CALL xt_initialize(mpi_comm_world)
381 
382  CALL mpi_comm_size(mpi_comm_world, nprocs, ierror)
383  IF (ierror /= mpi_success) &
384  CALL my_abort(context//'MPI_COMM_SIZE failed', __line__)
385 
386  CALL mpi_comm_rank(mpi_comm_world, mype, ierror)
387  IF (ierror /= mpi_success) &
388  CALL my_abort(context//'MPI_COMM_RANK failed', __line__)
389  IF (mype==0) THEN
390  lroot = .true.
391  ELSE
392  lroot = .false.
393  ENDIF
394 
395  CALL factorize(nprocs, nprocx, nprocy)
396  IF (verbose .AND. lroot) WRITE(0,*) 'nprocx, nprocy=',nprocx, nprocy
397  mypy = mype / nprocx
398  mypx = mod(mype, nprocx)
399 
400  !CALL ut_init(decomp_size=30, comm_tmpl_size=30, comm_size=30, &
401  ! & debug_lvl=0, mode=ut_mode_dt_p2p, debug_unit=0)
402 
403  CALL deco
404 
405  ALLOCATE(fval(ie,je), gval(ie,je))
406  ALLOCATE(loc_id(ie,je), loc_tpex(ie,je), mstate(ie,je))
407  ALLOCATE(id_pos(ie,je), gval3d(ie,nlev,je), pos3d_surf(ie,je))
408 
409  fval = undef_int
410  gval = undef_int
411  loc_id = int(undef_int, xt_int_kind)
412  loc_tpex = int(undef_int, xt_int_kind)
413  id_pos = undef_int
414  gval3d = undef_int
415  pos3d_surf = undef_int
416 
417  END SUBROUTINE init_all
418 
419  SUBROUTINE gen_id_pos(pos)
420  INTEGER, INTENT(out) :: pos(:,:)
421 
422  INTEGER :: i,j,p
423 
424  p = 0
425  DO j = 1, SIZE(pos,2)
426  DO i = 1, SIZE(pos,1)
427  p = p + 1
428  pos(i,j) = p
429  ENDDO
430  ENDDO
431 
432  END SUBROUTINE gen_id_pos
433 
434  SUBROUTINE gen_trans(xmap, send_dt, recv_dt, redist)
435  TYPE(xt_xmap), INTENT(in) :: xmap
436  INTEGER,INTENT(in) :: send_dt, recv_dt
437  TYPE(xt_redist),INTENT(out) :: redist
438 
439  INTEGER :: dt
440 
441  IF (send_dt /= recv_dt) &
442  CALL my_abort('gen_trans: (send_dt /= recv_dt) unsupported', __line__)
443  dt = send_dt
444  redist = xt_redist_p2p_new(xmap, dt)
445  !CALL ut_init_transposition(itemp, dt, itrans)
446 
447  END SUBROUTINE gen_trans
448 
449  SUBROUTINE gen_off_trans(xmap, send_dt, send_off, recv_dt, recv_off, redist)
450  TYPE(xt_xmap), INTENT(in) :: xmap
451  INTEGER,INTENT(in) :: send_dt, recv_dt
452  INTEGER(c_int),INTENT(in) :: send_off(:,:), recv_off(:,:)
453  TYPE(xt_redist),INTENT(out) :: redist
454 
455  !INTEGER :: send_offsets(SIZE(send_off)), recv_offsets(SIZE(recv_off))
456 
457  !send_offsets = RESHAPE(send_off, (/SIZE(send_off)/) )
458  !recv_offsets = RESHAPE(recv_off, (/SIZE(recv_off)/) )
459  IF (recv_dt /= send_dt) &
460  CALL my_abort('(datatype_in /= datatype_out) not supported', &
461  __line__)
462 
463  redist = xt_redist_p2p_off_new(xmap, send_off, recv_off, send_dt);
464  !CALL ut_init_transposition(itemp, send_offsets, recv_offsets, send_dt, recv_dt, itrans)
465 
466  END SUBROUTINE gen_off_trans
467 
468  SUBROUTINE get_window(gval, win)
469  INTEGER(xt_int_kind), INTENT(in) :: gval(:,:)
470  INTEGER(xt_int_kind), INTENT(out) :: win(:,:)
471 
472  INTEGER :: i, j, ig, jg
473 
474  DO j = 1, je
475  jg = p_joff + j
476  DO i = 1, ie
477  ig = p_ioff + i
478  win(i,j) = gval(ig,jg)
479  ENDDO
480  ENDDO
481 
482  END SUBROUTINE get_window
483 
484  SUBROUTINE gen_template(local_src_idx, local_dst_idx, xmap)
485  INTEGER(xt_int_kind), INTENT(in) :: local_src_idx(:,:)
486  INTEGER(xt_int_kind), INTENT(in) :: local_dst_idx(:,:)
487  TYPE(xt_xmap), INTENT(out) :: xmap
488 
489  TYPE(xt_idxlist) :: src_idxlist, dst_idxlist
490  INTEGER :: src_num, dst_num
491  INTEGER(xt_int_kind) :: cp_src_idx(g_ie, g_je)
492  INTEGER(xt_int_kind) :: cp_dst_idx(g_ie, g_je)
493 
494  src_idxlist = xt_idxvec_new(local_src_idx, g_ie * g_je)
495  src_num = int(xt_idxlist_get_num_indices(src_idxlist))
496  IF (src_num /= g_ie*g_je) CALL my_abort('unexpected src_num', __line__)
497  CALL xt_idxlist_get_indices(src_idxlist, cp_src_idx)
498  IF (any(cp_src_idx /= local_src_idx)) CALL my_abort('idx copy does not match', &
499  __line__)
500 
501  dst_idxlist = xt_idxvec_new(local_dst_idx, g_ie * g_je)
502  dst_num = int(xt_idxlist_get_num_indices(dst_idxlist))
503  IF (dst_num /= g_ie*g_je) CALL my_abort('unexpected dst_num', __line__)
504  CALL xt_idxlist_get_indices(dst_idxlist, cp_dst_idx)
505  IF (any(cp_dst_idx /= local_dst_idx)) CALL my_abort('idx copy does not match', &
506  __line__)
507 
508  xmap = xt_xmap_all2all_new(src_idxlist, dst_idxlist, mpi_comm_world)
509  CALL xt_idxlist_delete(src_idxlist)
510  CALL xt_idxlist_delete(dst_idxlist)
511 
512  END SUBROUTINE gen_template
513 
514  SUBROUTINE def_tpex_mod_via_idxvec(mvec, mvec_num)
515  TYPE(xt_modifier), INTENT(out) :: mvec(:)
516  INTEGER, INTENT(out) :: mvec_num
517 
518  INTEGER(xt_int_kind) :: g_start_indices(g_ie, g_je)
519  INTEGER(xt_int_kind) :: g_end_indices(g_ie, g_je)
520  TYPE(xt_idxlist) :: g_start_idxlist
521  TYPE(xt_idxlist) :: g_end_idxlist
522 
523  IF (SIZE(mvec)<1) CALL my_abort('def_tpex_mod_via_idxvec mvec too small', &
524  __line__)
525 
526  CALL id_map(g_start_indices)
527  g_start_idxlist = xt_idxvec_new(g_start_indices, SIZE(g_start_indices))
528 
529  CALL def_exchange(g_start_indices, g_end_indices)
530  g_end_idxlist = xt_idxvec_new(g_end_indices, SIZE(g_end_indices))
531 
532  mvec(1)%extract = g_start_idxlist
533  mvec(1)%subst = g_end_idxlist
534  mvec(1)%mask = 1
535  mvec_num = 1
536 
537  END SUBROUTINE def_tpex_mod_via_idxvec
538 
539  SUBROUTINE def_tpex_mod_via_sections(mvec, mvec_num)
540  TYPE(xt_modifier), INTENT(out) :: mvec(:)
541  INTEGER, INTENT(out) :: mvec_num
542 
543  INTEGER(xt_int_kind), PARAMETER :: gstart_idx = 1_xt_int_kind
544  INTEGER(xt_int_kind), PARAMETER :: gsize(2) &
545  = (/ int(g_ie, xt_int_kind), int(g_je, xt_int_kind) /)
546  INTEGER :: ldx, ldy
547 
548  INTEGER(xt_int_kind) :: g_core_is, g_core_ie, g_core_je
549  INTEGER(xt_int_kind) :: north_halo, im
550 
551  ! global core domain:
552  g_core_is = nhalo + 1
553  g_core_ie = g_ie-nhalo
554  g_core_je = g_je-nhalo
555 
556  im = 0
557 
558  ! global tripolar boundsexchange:
559  IF (with_north_halo) THEN
560 
561  ! north inversion, (maybe with increased north halo)
562  IF (increased_north_halo) THEN
563  north_halo = nhalo+1
564  ELSE
565  north_halo = nhalo
566  ENDIF
567 
568  IF (2*north_halo > g_core_je) &
569  CALL my_abort('def_tpex_mod_via_sections: grid too small (or halo too large)' // &
570  'for tripolar north exchange', __line__)
571 
572  im = im + 1_xt_int_kind
573  IF (SIZE(mvec)<im) CALL my_abort('(SIZE(mvec)<im)', __line__)
574  ! north border exchange without ew-halos
575  ldx = int(g_core_ie - g_core_is + 1)
576  ldy = int(north_halo)
577  mvec(im)%extract = xt_idxfsection_new(gstart_idx, gsize, &
578  (/ ldx, ldy /), (/g_core_is, 1_xt_int_kind/))
579  mvec(im)%subst = xt_idxfsection_new(gstart_idx, gsize, &
580  (/ -ldx, -ldy /), (/g_core_is, north_halo+1_xt_int_kind/))
581  mvec(im)%mask = 1
582 
583  ! 1. north edge:
584  im = im + 1_xt_int_kind
585  IF (SIZE(mvec)<im) CALL my_abort('(SIZE(mvec)<im)', __line__)
586  ldx = 1
587  ldy = int(north_halo)
588  mvec(im)%extract = xt_idxfsection_new(gstart_idx, gsize, &
589  (/ ldx, ldy /), (/1_xt_int_kind, 1_xt_int_kind/))
590  mvec(im)%subst = xt_idxfsection_new(gstart_idx, gsize, &
591  (/ -ldx, -ldy /), (/2_xt_int_kind, north_halo+1_xt_int_kind/))
592  mvec(im)%mask = 1
593  ! 2. north edge:
594  im = im + 1_xt_int_kind
595  IF (SIZE(mvec)<im) CALL my_abort('(SIZE(mvec)<im)', __line__)
596  ldx = 1
597  ldy = int(north_halo)
598  mvec(im)%extract = xt_idxfsection_new(gstart_idx, gsize, &
599  (/ ldx, ldy /), (/int(g_ie, xt_int_kind), 1_xt_int_kind/))
600  mvec(im)%subst = xt_idxfsection_new(gstart_idx, gsize, &
601  (/ -ldx, -ldy /), &
602  (/int(g_ie - 1, xt_int_kind), north_halo+1_xt_int_kind/))
603  mvec(im)%mask = 1
604 
605  ELSE
606 
607  ! nothing to do at the north border
608 
609  ENDIF
610 
611  ! PBC below north border
612  ldx = nhalo
613  ldy = int(int(g_je, xt_int_kind) - north_halo)
614  im = im + 1_xt_int_kind
615  IF (SIZE(mvec)<im) CALL my_abort('(SIZE(mvec)<im)', __line__)
616  mvec(im)%extract = xt_idxfsection_new(gstart_idx, gsize, &
617  (/ ldx, ldy /), (/1_xt_int_kind, north_halo+1_xt_int_kind/))
618  mvec(im)%subst = xt_idxfsection_new(gstart_idx, gsize, &
619  (/ ldx, ldy /), &
620  (/ g_core_ie - int(ldx, xt_int_kind) + 1_xt_int_kind, &
621  north_halo + 1_xt_int_kind/))
622  mvec(im)%mask = 1
623 
624  im = im + 1_xt_int_kind
625  IF (SIZE(mvec)<im) CALL my_abort('(SIZE(mvec)<im)', __line__)
626  mvec(im)%extract = xt_idxfsection_new(gstart_idx, gsize, &
627  (/ ldx, ldy /), (/g_core_ie+1_xt_int_kind, north_halo+1_xt_int_kind/))
628  mvec(im)%subst = xt_idxfsection_new(gstart_idx, gsize, &
629  (/ ldx, ldy /), (/ int(ldx, xt_int_kind) + 1_xt_int_kind, &
630  & north_halo+1_xt_int_kind/))
631  mvec(im)%mask = 1
632 
633  mvec_num = int(im)
634 
635  END SUBROUTINE def_tpex_mod_via_sections
636 
637  SUBROUTINE def_exchange(id_in, id_out)
638  INTEGER(xt_int_kind), INTENT(in) :: id_in(:,:)
639  INTEGER(xt_int_kind), INTENT(out) :: id_out(:,:)
640 
641  INTEGER :: i, j
642  INTEGER :: g_core_is, g_core_ie, g_core_js, g_core_je
643  INTEGER :: north_halo
644 
645  ! global core domain:
646  g_core_is = nhalo + 1
647  g_core_ie = g_ie-nhalo
648  g_core_js = nhalo + 1
649  g_core_je = g_je-nhalo
650 
651  ! global tripolar boundsexchange:
652  id_out = undef_index
653  id_out(g_core_is:g_core_ie, g_core_js:g_core_je) &
654  = id_in(g_core_is:g_core_ie, g_core_js:g_core_je)
655 
656  IF (with_north_halo) THEN
657 
658  ! north inversion, (maybe with increased north halo)
659  IF (increased_north_halo) THEN
660  north_halo = nhalo+1
661  ELSE
662  north_halo = nhalo
663  ENDIF
664 
665  IF (2*north_halo > g_core_je) &
666  CALL my_abort('def_exchange: grid too small (or halo too large)' // &
667  'for tripolar north exchange', __line__)
668  DO j = 1, north_halo
669  DO i = g_core_is, g_core_ie
670  id_out(i,j) = id_out(g_core_ie + (g_core_is-i), 2*north_halo + (1-j))
671  ENDDO
672  ENDDO
673 
674  ELSE
675 
676  DO j = 1, nhalo
677  DO i = nhalo+1, g_ie-nhalo
678  id_out(i,j) = id_in(i,j)
679  ENDDO
680  ENDDO
681 
682  ENDIF
683 
684  ! south: no change
685  DO j = g_core_je+1, g_je
686  DO i = nhalo+1, g_ie-nhalo
687  id_out(i,j) = id_in(i,j)
688  ENDDO
689  ENDDO
690 
691  ! PBC
692  DO j = 1, g_je
693  DO i = 1, nhalo
694  id_out(g_core_is-i,j) = id_out(g_core_ie+(1-i),j)
695  ENDDO
696  DO i = 1, nhalo
697  id_out(g_core_ie+i,j) = id_out(nhalo+i,j)
698  ENDDO
699  ENDDO
700 
701  CALL check_g_idx(id_out)
702 
703  END SUBROUTINE def_exchange
704 
705  SUBROUTINE check_g_idx(gidx)
706  INTEGER(xt_int_kind), INTENT(in) :: gidx(:,:)
707 
708  IF (any(gidx == undef_index)) THEN
709  CALL my_abort('check_g_idx: check failed', __line__)
710  ENDIF
711  END SUBROUTINE check_g_idx
712 
713  SUBROUTINE deco
714  INTEGER :: cx0(0:nprocx-1), cxn(0:nprocx-1)
715  INTEGER :: cy0(0:nprocy-1), cyn(0:nprocy-1)
716 
717  CALL regular_deco(g_ie-2*nhalo, cx0, cxn)
718  CALL regular_deco(g_je-2*nhalo, cy0, cyn)
719 
720  ! process local deco variables:
721  ie = cxn(mypx) + 2*nhalo
722  je = cyn(mypy) + 2*nhalo
723  p_ioff = cx0(mypx)
724  p_joff = cy0(mypy)
725 
726  END SUBROUTINE deco
727 
728 END PROGRAM test_yaxt
729 !
730 ! Local Variables:
731 ! f90-continuation-indent: 5
732 ! coding: utf-8
733 ! indent-tabs-mode: nil
734 ! show-trailing-whitespace: t
735 ! require-trailing-newline: t
736 ! End:
737 !