Yet Another eXchange Tool  DO_NOT_EDIT_HERE
test_perf.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_perf
49  USE mpi
51  & ut_transpose, ut_init_decomposition, &
54  & ut_init_transposition, xt_int_kind
55  USE ftest_common, ONLY: finish_mpi, init_mpi, treset, tstart, tstop, &
56  treport, timer, id_map, factorize, regular_deco, set_verbose
57  USE yaxt, ONLY: xt_finalize
58 
59  IMPLICIT NONE
60  ! global extents including halos:
61 
62  INTEGER, PARAMETER :: nlev = 30
63  INTEGER, PARAMETER :: undef_int = huge(undef_int)/2 - 1
64  INTEGER(xt_int_kind), PARAMETER :: undef_index = -1
65  INTEGER, PARAMETER :: nhalo = 1 ! 1dim. halo border size
66 
67  INTEGER, PARAMETER :: grid_kind_test = 1
68  INTEGER, PARAMETER :: grid_kind_toy = 2
69  INTEGER, PARAMETER :: grid_kind_tp10 = 3
70  INTEGER, PARAMETER :: grid_kind_tp04 = 4
71  INTEGER, PARAMETER :: grid_kind_tp6m = 5
72  INTEGER :: grid_kind = grid_kind_test
73 
74  CHARACTER(len=10) :: grid_label
75  INTEGER :: g_ie, g_je ! global domain extents
76  INTEGER :: ie, je, ke ! local extents, including halos
77  INTEGER :: p_ioff, p_joff ! offsets within global domain
78  INTEGER :: nprocx, nprocy ! process space extents
79  INTEGER :: nprocs ! == nprocx*nprocy
80  ! process rank, process coords within (0:, 0:) process space
81  INTEGER :: mype, mypx, mypy
82  LOGICAL :: lroot ! true only for proc 0
83 
84  INTEGER, ALLOCATABLE :: g_id(:,:) ! global id
85  ! global "tripolar-like" toy bounds exchange
86  INTEGER, ALLOCATABLE :: g_tpex(:, :)
87  INTEGER :: template_tpex_2d, trans_tpex_2d
88  INTEGER :: template_tpex_3d, trans_tpex_3d
89 
90  INTEGER, ALLOCATABLE :: loc_id_2d(:,:), loc_tpex_2d(:,:)
91  INTEGER, ALLOCATABLE :: loc_id_3d(:,:,:), loc_tpex_3d(:,:,:)
92  INTEGER, ALLOCATABLE :: fval_2d(:,:), gval_2d(:,:)
93  INTEGER, ALLOCATABLE :: fval_3d(:,:,:), gval_3d(:,:,:)
94  INTEGER, ALLOCATABLE :: id_pos(:,:), pos3d_surf(:,:)
95  INTEGER :: surf_trans_tpex_2d
96  LOGICAL :: verbose
97 
98  TYPE(timer) :: t_all, t_surf_trans, t_exch_surf
99  TYPE(timer) :: t_template_2d, t_trans_2d, t_exch_2d
100  TYPE(timer) :: t_template_3d, t_trans_3d, t_exch_3d
101 
102  CALL treset(t_all, 'all')
103  CALL treset(t_surf_trans, 'surf_trans')
104  CALL treset(t_exch_surf, 'exch_surf')
105  CALL treset(t_template_2d, 'template_2d')
106  CALL treset(t_trans_2d, 'trans_2d')
107  CALL treset(t_exch_2d, 'exch_2d')
108  CALL treset(t_template_3d, 'template_3d')
109  CALL treset(t_trans_3d, 'trans_3d')
110  CALL treset(t_exch_3d, 'exch_3d')
111 
112  CALL init_mpi
113 
114  CALL tstart(t_all)
115 
116  ! mpi & decomposition & allocate mem:
117  CALL init_all
118 
119  ! full global index space:
120  CALL id_map(g_id)
121 
122  ! local window of global index space:
123  CALL get_window(g_id, loc_id_2d)
124 
125 
126  ! define bounds exchange for full global index space
127  CALL def_exchange()
128 
129  ! local window of global bounds exchange:
130  CALL get_window(g_tpex, loc_tpex_2d)
131 
132  ! template: loc_id_2d -> loc_tpex_2d
133  CALL tstart(t_template_2d)
134  CALL gen_template_2d(loc_id_2d, loc_tpex_2d, template_tpex_2d)
135  CALL tstop(t_template_2d)
136 
137  ! transposition: loc_id_2d:data -> loc_tpex_2d:data
138  CALL tstart(t_trans_2d)
139  CALL gen_trans(template_tpex_2d, mpi_integer, mpi_integer, trans_tpex_2d)
140  CALL tstop(t_trans_2d)
141 
142 
143  ! test 2d-to-2d transposition:
144  fval_2d = loc_id_2d
145  CALL tstart(t_exch_2d)
146  CALL exchange2d_2d(trans_tpex_2d, fval_2d, gval_2d)
147  CALL tstop(t_exch_2d)
148  CALL icmp_2d('2d to 2d check', gval_2d, loc_tpex_2d)
149 
150  ! define positions of surface elements within (i,k,j) array
151  CALL id_map(id_pos)
152  CALL id_map(pos3d_surf)
153  CALL gen_pos3d_surf(pos3d_surf)
154 
155  ! generate surface transposition:
156  CALL tstart(t_surf_trans)
157  CALL gen_off_trans(template_tpex_2d, mpi_integer, id_pos(:,:)-1, &
158  mpi_integer, pos3d_surf(:,:)-1, surf_trans_tpex_2d)
159  CALL tstop(t_surf_trans)
160 
161 
162  ! 2d to surface boundsexchange:
163  ALLOCATE(gval_3d(ie,nlev,je))
164  gval_3d = -1
165  CALL tstart(t_exch_surf)
166  CALL exchange2d_3d(surf_trans_tpex_2d, fval_2d, gval_3d)
167  CALL tstop(t_exch_surf)
168 
169  CALL icmp_2d('surface check', gval_3d(:,1,:), loc_tpex_2d)
170 
171  ! check sub surface:
172  CALL icmp_2d('sub surface check', gval_3d(:,2,:), loc_tpex_2d*0-1)
173 
174  ! cleanup 2d:
175  CALL ut_destroy_transposition_template(template_tpex_2d)
176  CALL ut_destroy_transposition(trans_tpex_2d)
177  CALL ut_destroy_transposition(surf_trans_tpex_2d)
178 
179  ! inflate 2d -> 3d
180  CALL inflate_idx(3, loc_id_2d, loc_id_3d)
181  CALL inflate_idx(3, loc_tpex_2d, loc_tpex_3d)
182 
183  ! template: loc_id_3d -> loc_tpex_3d
184  CALL tstart(t_template_3d)
185  CALL gen_template_3d(loc_id_3d, loc_tpex_3d, template_tpex_3d)
186  CALL tstop(t_template_3d)
187 
188  ! transposition: loc_id_3d:data -> loc_tpex_3d:data
189  CALL tstart(t_trans_3d)
190  CALL gen_trans(template_tpex_3d, mpi_integer, mpi_integer, trans_tpex_3d)
191  CALL tstop(t_trans_3d)
192 
193  ! test 3d-to-3d transposition:
194  DEALLOCATE(gval_3d)
195  ALLOCATE(fval_3d(ie,je,nlev), gval_3d(ie,je,nlev))
196  fval_3d = loc_id_3d
197  CALL tstart(t_exch_3d)
198  CALL exchange3d_3d(trans_tpex_3d, fval_3d, gval_3d)
199  CALL tstop(t_exch_3d)
200  CALL icmp_3d('3d to 3d check', gval_3d, loc_tpex_3d)
201 
202  ! cleanup 3d:
203  CALL ut_destroy_transposition_template(template_tpex_3d)
204  CALL ut_destroy_transposition(trans_tpex_3d)
205 
206  CALL tstop(t_all)
207 
208  IF (verbose) WRITE(0,*) 'timer report for nprocs=',nprocs
209 
210  CALL treport(t_all, trim(grid_label), mpi_comm_world)
211  CALL treport(t_surf_trans, trim(grid_label), mpi_comm_world)
212  CALL treport(t_exch_surf, trim(grid_label), mpi_comm_world)
213  CALL treport(t_template_2d, trim(grid_label), mpi_comm_world)
214  CALL treport(t_trans_2d, trim(grid_label), mpi_comm_world)
215  CALL treport(t_exch_2d, trim(grid_label), mpi_comm_world)
216  CALL treport(t_template_3d, trim(grid_label), mpi_comm_world)
217  CALL treport(t_trans_3d, trim(grid_label), mpi_comm_world)
218  CALL treport(t_exch_3d, trim(grid_label), mpi_comm_world)
219 
220  CALL xt_finalize
221  CALL finish_mpi
222 
223 CONTAINS
224 
225  SUBROUTINE msg(s)
226  CHARACTER(len=*), INTENT(in) :: s
227  IF (verbose) WRITE(0,*) s
228  END SUBROUTINE msg
229 
230  SUBROUTINE inflate_idx(inflate_pos, idx_2d, idx_3d)
231  CHARACTER(len=*), PARAMETER :: context = 'test_perf::inflate_idx: '
232  INTEGER, INTENT(in) :: inflate_pos
233  INTEGER, INTENT(in) :: idx_2d(:,:)
234  INTEGER, ALLOCATABLE, INTENT(out) :: idx_3d(:,:,:)
235 
236  INTEGER :: i, j, k
237 
238  IF (ALLOCATED(idx_3d)) DEALLOCATE(idx_3d)
239 
240  IF (inflate_pos == 3) THEN
241  ALLOCATE(idx_3d(ie, je, ke))
242  DO k=1,ke
243  DO j=1,je
244  DO i=1,ie
245  idx_3d(i,j,k) = idx_2d(i,j) + (k-1) * g_ie * g_je
246  ENDDO
247  ENDDO
248  ENDDO
249  ELSE
250  CALL ut_abort(context//' unsupported inflate position', &
251  __file__, &
252  __line__)
253  ENDIF
254 
255  END SUBROUTINE inflate_idx
256 
257  SUBROUTINE gen_pos3d_surf(pos)
258  INTEGER, INTENT(inout) :: pos(:,:)
259  ! positions for zero based arrays (ECHAM grid point dim order)
260  ! old pos = i + j*ie
261  ! new pos = i + k*ie + j*ie*nlev
262  INTEGER :: ii,jj, i,j,k, p,q
263 
264  k = 0 ! surface
265  DO jj=1,je
266  DO ii=1,ie
267  p = pos(ii,jj) - 1 ! shift to 0-based index
268  j = p/ie
269  i = mod(p,ie)
270  q = i + k*ie + j*ie*nlev
271  pos(ii,jj) = q + 1 ! shift to 1-based index
272  ENDDO
273  ENDDO
274 
275  END SUBROUTINE gen_pos3d_surf
276 
277  SUBROUTINE icmp_2d(label, f,g)
278  CHARACTER(len=*), PARAMETER :: context = 'test_perf::icmp_2d: '
279  CHARACTER(len=*), INTENT(in) :: label
280  INTEGER, INTENT(in) :: f(:,:)
281  INTEGER, INTENT(in) :: g(:,:)
282 
283  INTEGER :: i, j, n1, n2
284 
285  n1 = SIZE(f,1)
286  n2 = SIZE(f,2)
287  IF (SIZE(g,1) /= n1 .OR. SIZE(g,2) /= n2) &
288  CALL ut_abort(context//'internal error', &
289  __file__, &
290  __line__)
291 
292  DO j = 1, n2
293  DO i = 1, n1
294  IF (f(i,j) /= g(i,j)) THEN
295  WRITE(0,*) context,label,' test failed: i, j, f(i,j), g(i,j) =', &
296  i, j, f(i,j), g(i,j)
297  CALL ut_abort(context//label//' test failed', &
298  __file__, &
299  __line__)
300  ENDIF
301  ENDDO
302  ENDDO
303 
304  END SUBROUTINE icmp_2d
305 
306  SUBROUTINE icmp_3d(label, f,g)
307  CHARACTER(len=*), PARAMETER :: context = 'test_perf::icmp_3d: '
308  CHARACTER(len=*), INTENT(in) :: label
309  INTEGER, INTENT(in) :: f(:,:,:)
310  INTEGER, INTENT(in) :: g(:,:,:)
311 
312  INTEGER :: i, j, k, n1, n2, n3
313 
314  n1 = SIZE(f,1)
315  n2 = SIZE(f,2)
316  n3 = SIZE(f,3)
317  IF (SIZE(g,1) /= n1 .OR. SIZE(g,2) /= n2 .OR. SIZE(g,3) /= n3) &
318  CALL ut_abort(context//'internal error', &
319  __file__, &
320  __line__)
321 
322  DO k = 1, n3
323  DO j = 1, n2
324  DO i = 1, n1
325  IF (f(i,j,k) /= g(i,j,k)) THEN
326  WRITE(0,*) context,label, &
327  ' test failed: i, j, f(i,j,k), g(i,j,k) =', &
328  i, j, k, f(i,j,k), g(i,j,k)
329  CALL ut_abort(context//label//' test failed', &
330  __file__, &
331  __line__)
332  ENDIF
333  ENDDO
334  ENDDO
335  ENDDO
336 
337  END SUBROUTINE icmp_3d
338 
339  SUBROUTINE init_all
340  CHARACTER(len=*), PARAMETER :: context = 'init_all: '
341  INTEGER :: ierror
342  CHARACTER(len=20) :: grid_str
343 
344  CALL get_environment_variable('YAXT_TEST_PERF_GRID', grid_str)
345 
346  verbose = .true.
347 
348  SELECT CASE (trim(adjustl(grid_str)))
349  CASE('TOY')
350  grid_kind = grid_kind_toy
351  grid_label = 'TOY'
352  g_ie = 66
353  g_je = 36
354  CASE('TP10')
355  grid_kind = grid_kind_tp10
356  grid_label = 'TP10'
357  g_ie = 362
358  g_je = 192
359  CASE('TP04')
360  grid_kind = grid_kind_tp04
361  grid_label = 'TP04'
362  g_ie = 802
363  g_je = 404
364  CASE('TP6M')
365  grid_kind = grid_kind_tp6m
366  grid_label = 'TP6M'
367  g_ie = 3602
368  g_je = 2394
369  CASE default
370  grid_kind = grid_kind_test
371  grid_label = 'TEST'
372  g_ie = 32
373  g_je = 12
374  verbose = .false.
375  END SELECT
376 
377  CALL mpi_comm_size(mpi_comm_world, nprocs, ierror)
378  IF (ierror /= mpi_success) CALL ut_abort(context//'MPI_COMM_SIZE failed', &
379  __file__, &
380  __line__)
381 
382  CALL mpi_comm_rank(mpi_comm_world, mype, ierror)
383  IF (ierror /= mpi_success) CALL ut_abort(context//'MPI_COMM_RANK failed', &
384  __file__, &
385  __line__)
386  IF (mype==0) THEN
387  lroot = .true.
388  ELSE
389  lroot = .false.
390  verbose = .false.
391  ENDIF
392  CALL set_verbose(verbose)
393  CALL factorize(nprocs, nprocx, nprocy)
394  IF (lroot .AND. verbose) WRITE(0,*) 'nprocx, nprocy=',nprocx, nprocy
395  IF (lroot .AND. verbose) WRITE(0,*) 'g_ie, g_je=',g_ie, g_je
396  mypy = mype / nprocx
397  mypx = mod(mype, nprocx)
398 
399  CALL deco
400  ke = nlev
401 
402  ALLOCATE(g_id(g_ie, g_je), g_tpex(g_ie, g_je))
403 
404  ALLOCATE(fval_2d(ie,je), gval_2d(ie,je))
405  ALLOCATE(loc_id_2d(ie,je), loc_tpex_2d(ie,je))
406  ALLOCATE(id_pos(ie,je), pos3d_surf(ie,je))
407 
408  fval_2d = undef_int
409  gval_2d = undef_int
410  loc_id_2d = undef_int
411  loc_tpex_2d = undef_int
412  id_pos = undef_int
413  pos3d_surf = undef_int
414 
415  CALL ut_init(decomp_size=30, comm_tmpl_size=30, comm_size=30, &
416  & debug_lvl=0, mode=ut_mode_dt_p2p, debug_unit=0)
417 
418  END SUBROUTINE init_all
419 
420  SUBROUTINE exchange2d_2d(itrans, f, g)
421  INTEGER, INTENT(in) :: itrans
422  INTEGER, TARGET, INTENT(in) :: f(:,:)
423  INTEGER, TARGET, INTENT(out) :: g(:,:)
424 
425  INTEGER, POINTER :: p_in, p_out
426 
427  p_in => f(1,1)
428  p_out=> g(1,1)
429 
430  CALL ut_transpose(p_in, itrans, comm_forward, p_out)
431 
432  END SUBROUTINE exchange2d_2d
433 
434  SUBROUTINE exchange3d_3d(itrans, f, g)
435  INTEGER, INTENT(in) :: itrans
436  INTEGER, TARGET, INTENT(in) :: f(:,:,:)
437  INTEGER, TARGET, INTENT(out) :: g(:,:,:)
438 
439  INTEGER, POINTER :: p_in, p_out
440 
441  p_in => f(1,1,1)
442  p_out=> g(1,1,1)
443 
444  CALL ut_transpose(p_in, itrans, comm_forward, p_out)
445 
446  END SUBROUTINE exchange3d_3d
447 
448 
449  SUBROUTINE exchange2d_3d(itrans, f, g)
450  INTEGER, INTENT(in) :: itrans
451  INTEGER, TARGET, INTENT(in) :: f(:,:)
452  INTEGER, TARGET, INTENT(out) :: g(:,:,:)
453 
454  INTEGER, POINTER :: p_in, p_out
455 
456  p_in => f(1,1)
457  p_out=> g(1,1,1)
458 
459  CALL ut_transpose(p_in, itrans, comm_forward, p_out)
460 
461  END SUBROUTINE exchange2d_3d
462 
463  SUBROUTINE gen_trans(itemp, send_dt, recv_dt, itrans)
464  INTEGER,INTENT(in) :: itemp, send_dt, recv_dt
465  INTEGER,INTENT(out) :: itrans
466 
467  INTEGER :: dt
468 
469  IF (send_dt /= recv_dt) &
470  CALL ut_abort('gen_trans: (send_dt /= recv_dt) unsupported', &
471  __file__, &
472  __line__)
473  dt = send_dt
474  CALL ut_init_transposition(itemp, dt, itrans)
475 
476  END SUBROUTINE gen_trans
477 
478  SUBROUTINE gen_off_trans(itemp, send_dt, send_off, recv_dt, recv_off, itrans)
479  INTEGER,INTENT(in) :: itemp, send_dt, recv_dt
480  INTEGER,INTENT(in) :: send_off(:,:), recv_off(:,:)
481  INTEGER,INTENT(out) :: itrans
482 
483  INTEGER :: send_offsets(size(send_off)), recv_offsets(size(recv_off))
484 
485  send_offsets = reshape(send_off, (/SIZE(send_off)/) )
486  recv_offsets = reshape(recv_off, (/SIZE(recv_off)/) )
487 
488  CALL ut_init_transposition(itemp, send_offsets, recv_offsets, &
489  send_dt, recv_dt, itrans)
490 
491  END SUBROUTINE gen_off_trans
492 
493  SUBROUTINE get_window(gval, win)
494  INTEGER, INTENT(in) :: gval(:,:)
495  INTEGER, INTENT(out) :: win(:,:)
496 
497  INTEGER :: i, j, ig, jg
498 
499  DO j = 1, je
500  jg = p_joff + j
501  DO i = 1, ie
502  ig = p_ioff + i
503  win(i,j) = gval(ig,jg)
504  ENDDO
505  ENDDO
506 
507  END SUBROUTINE get_window
508 
509  SUBROUTINE gen_template_2d(local_src_idx, local_dst_idx, ihandle)
510  INTEGER, INTENT(in) :: local_src_idx(:,:)
511  INTEGER, INTENT(in) :: local_dst_idx(:,:)
512  INTEGER, INTENT(out) :: ihandle
513 
514  INTEGER :: src(size(local_src_idx)), dst(size(local_dst_idx))
515 
516  INTEGER :: src_handle, dst_handle
517 
518  src = reshape( local_src_idx, (/SIZE(local_src_idx)/) )
519  dst = reshape( local_dst_idx, (/SIZE(local_dst_idx)/) )
520 
521  CALL ut_init_decomposition(src, g_ie * g_je, src_handle)
522  CALL ut_init_decomposition(dst, g_ie * g_je, dst_handle)
523 
524  CALL ut_init_oneway_transposition_template(src_handle, dst_handle, &
525  mpi_comm_world, ihandle)
526 
527  CALL ut_destroy_decomposition(dst_handle)
528  CALL ut_destroy_decomposition(src_handle)
529 
530  END SUBROUTINE gen_template_2d
531 
532  SUBROUTINE gen_template_3d(local_src_idx, local_dst_idx, ihandle)
533  INTEGER, INTENT(in) :: local_src_idx(:,:,:)
534  INTEGER, INTENT(in) :: local_dst_idx(:,:,:)
535  INTEGER, INTENT(out) :: ihandle
536 
537  INTEGER, ALLOCATABLE :: src(:), dst(:)
538  INTEGER :: src_handle, dst_handle
539 
540  ALLOCATE(src(SIZE(local_src_idx)), dst(SIZE(local_dst_idx)))
541 
542  src = reshape( local_src_idx, (/SIZE(local_src_idx)/) )
543  dst = reshape( local_dst_idx, (/SIZE(local_dst_idx)/) )
544 
545  CALL ut_init_decomposition(src, g_ie * g_je, src_handle)
546  CALL ut_init_decomposition(dst, g_ie * g_je, dst_handle)
547 
548  CALL ut_init_oneway_transposition_template(src_handle, dst_handle, &
549  mpi_comm_world, ihandle)
550 
551  CALL ut_destroy_decomposition(dst_handle)
552  CALL ut_destroy_decomposition(src_handle)
553 
554  END SUBROUTINE gen_template_3d
555 
556 
557  SUBROUTINE def_exchange()
558 
559  LOGICAL, PARAMETER :: increased_north_halo = .false.
560  LOGICAL, PARAMETER :: with_north_halo = .true.
561  INTEGER :: i, j
562  INTEGER :: g_core_is, g_core_ie, g_core_js, g_core_je
563  INTEGER :: north_halo
564 
565  ! global core domain:
566  g_core_is = nhalo + 1
567  g_core_ie = g_ie-nhalo
568  g_core_js = nhalo + 1
569  g_core_je = g_je-nhalo
570 
571  ! global tripolar boundsexchange:
572  g_tpex = undef_index
573  g_tpex(g_core_is:g_core_ie, g_core_js:g_core_je) &
574  = g_id(g_core_is:g_core_ie, g_core_js:g_core_je)
575 
576  IF (with_north_halo) THEN
577 
578  ! north inversion, (maybe with increased north halo)
579  IF (increased_north_halo) THEN
580  north_halo = nhalo+1
581  ELSE
582  north_halo = nhalo
583  ENDIF
584 
585  IF (2*north_halo > g_core_je) &
586  CALL ut_abort('def_exchange: grid too small (or halo too large) &
587  &for tripolar north exchange', &
588  __file__, &
589  __line__)
590  DO j = 1, north_halo
591  DO i = g_core_is, g_core_ie
592  g_tpex(i,j) = g_tpex(g_core_ie + (g_core_is-i), 2*north_halo + (1-j))
593  ENDDO
594  ENDDO
595 
596  ELSE
597 
598  DO j = 1, nhalo
599  DO i = nhalo+1, g_ie-nhalo
600  g_tpex(i,j) = g_id(i,j)
601  ENDDO
602  ENDDO
603 
604  ENDIF
605 
606  ! south: no change
607  DO j = g_core_je+1, g_je
608  DO i = nhalo+1, g_ie-nhalo
609  g_tpex(i,j) = g_id(i,j)
610  ENDDO
611  ENDDO
612 
613  ! PBC
614  DO j = 1, g_je
615  DO i = 1, nhalo
616  g_tpex(g_core_is-i,j) = g_tpex(g_core_ie+(1-i),j)
617  ENDDO
618  DO i = 1, nhalo
619  g_tpex(g_core_ie+i,j) = g_tpex(nhalo+i,j)
620  ENDDO
621  ENDDO
622 
623  CALL check_g_idx (g_tpex)
624 
625  END SUBROUTINE def_exchange
626 
627  SUBROUTINE check_g_idx(gidx)
628  INTEGER,INTENT(in) :: gidx(:,:)
629 
630  IF (any(gidx == undef_index)) THEN
631  CALL ut_abort('check_g_idx: check failed', __file__, __line__)
632  ENDIF
633  END SUBROUTINE check_g_idx
634 
635  SUBROUTINE deco
636  INTEGER :: cx0(0:nprocx-1), cxn(0:nprocx-1)
637  INTEGER :: cy0(0:nprocy-1), cyn(0:nprocy-1)
638 
639  cx0 = 0
640  cxn = 0
641  CALL regular_deco(g_ie-2*nhalo, cx0, cxn)
642 
643  cy0 = 0
644  cyn = 0
645  CALL regular_deco(g_je-2*nhalo, cy0, cyn)
646 
647  ! process local deco variables:
648  ie = cxn(mypx) + 2*nhalo
649  je = cyn(mypy) + 2*nhalo
650  p_ioff = cx0(mypx)
651  p_joff = cy0(mypy)
652 
653  END SUBROUTINE deco
654 
655 END PROGRAM test_perf
656 !
657 ! Local Variables:
658 ! f90-continuation-indent: 5
659 ! coding: utf-8
660 ! indent-tabs-mode: nil
661 ! show-trailing-whitespace: t
662 ! require-trailing-newline: t
663 ! End:
664 !