Yet Another eXchange Tool  DO_NOT_EDIT_HERE
test_ut.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_ut
49  USE mpi
50  USE xt_ut, ONLY: ut_abort, ut_init, ut_init_decomposition, &
53  ut_init_transposition, &
54  comm_forward, ut_transpose, ut_destroy_decomposition, &
56  USE ftest_common, ONLY: finish_mpi, icmp, id_map, factorize, regular_deco
57  IMPLICIT NONE
58 
59  ! global extents including halos
60  INTEGER, PARAMETER :: g_ie = 8, g_je = 4
61  LOGICAL, PARAMETER :: verbose = .false.
62  INTEGER, PARAMETER :: nlev = 3
63  INTEGER, PARAMETER :: undef_int = g_ie * g_je * nlev + 1
64  INTEGER(xt_int_kind), PARAMETER :: undef_index = -1
65  INTEGER, PARAMETER :: nhalo = 1 ! 1dim. halo border size
66 
67  INTEGER :: ie, je ! local extents, including halos
68  INTEGER :: p_ioff, p_joff ! offsets within global domain
69  INTEGER :: nprocx, nprocy ! process space extents
70  INTEGER :: nprocs ! == nprocx*nprocy
71  ! process rank, process coords within (0:, 0:) process space
72  INTEGER :: mype, mypx, mypy
73  LOGICAL :: lroot ! true only for proc 0
74 
75  INTEGER(xt_int_kind) :: g_id(g_ie, g_je) ! global id
76 
77  ! global "tripolar-like" toy bounds exchange
78  INTEGER(xt_int_kind) :: g_tpex(g_ie, g_je)
79  INTEGER :: template_tpex, trans_tpex
80 
81  INTEGER(xt_int_kind), ALLOCATABLE :: loc_id(:,:), loc_tpex(:,:)
82  INTEGER, ALLOCATABLE :: fval(:,:), gval(:,:)
83  INTEGER, ALLOCATABLE :: gval3d(:,:,:)
84  INTEGER, ALLOCATABLE :: id_pos(:,:), pos3d_surf(:,:)
85  INTEGER :: surf_trans_tpex
86 
87  ! mpi & decomposition & allocate mem:
88  CALL init_all
89 
90  ! full global index space:
91  CALL id_map(g_id)
92 
93  ! local window of global index space:
94  CALL get_window(g_id, loc_id)
95 
96  ! define bounds exchange for full global index space
97  CALL def_exchange(g_id, g_tpex)
98 
99  ! local window of global bounds exchange:
100  CALL get_window(g_tpex, loc_tpex)
101 
102  ! template: loc_id -> loc_tpex
103  CALL gen_template(loc_id, loc_tpex, template_tpex)
104 
105  ! transposition: loc_id:data -> loc_tpex:data
106  CALL gen_trans(template_tpex, mpi_integer, mpi_integer, trans_tpex)
107 
108  ! test 2d-to-2d transposition:
109  fval = int(loc_id)
110  CALL exchange2d_2d(trans_tpex, fval, gval)
111  CALL icmp('2d to 2d check', gval, int(loc_tpex), mype)
112 
113  ! define positions of surface elements within (i,k,j) array
114  CALL gen_id_pos(id_pos)
115  CALL gen_id_pos(pos3d_surf)
116  CALL gen_pos3d_surf(pos3d_surf)
117 
118  ! generate surface transposition:
119  CALL gen_off_trans(template_tpex, mpi_integer, id_pos(:,:)-1, &
120  mpi_integer, pos3d_surf(:,:)-1, surf_trans_tpex)
121 
122  ! 2d to surface boundsexchange:
123  gval3d = -1
124  CALL exchange2d_3d(surf_trans_tpex, fval, gval3d)
125  CALL icmp('surface check', gval3d(:,1,:), int(loc_tpex), mype)
126 
127  ! check sub surface:
128  CALL icmp('sub surface check', gval3d(:,2,:), int(loc_tpex)*0-1, mype)
129 
130  ! cleanup:
131  CALL ut_destroy_transposition_template(template_tpex)
132  CALL ut_destroy_transposition(trans_tpex)
133  CALL ut_destroy_transposition(surf_trans_tpex)
134 
135  CALL ut_finalize()
136  CALL finish_mpi
137 
138 CONTAINS
139 
140  SUBROUTINE gen_pos3d_surf(pos)
141  INTEGER, INTENT(inout) :: pos(:,:)
142  ! positions for zero based arrays (ECHAM grid point dim order)
143  ! old pos = i + j*ie
144  ! new pos = i + k*ie + j*ie*nlev
145  INTEGER :: ii,jj, i,j,k, p,q
146 
147  k = 0 ! surface
148  DO jj=1,je
149  DO ii=1,ie
150  p = pos(ii,jj) - 1 ! shift to 0-based index
151  j = p/ie
152  i = mod(p,ie)
153  q = i + k*ie + j*ie*nlev
154  pos(ii,jj) = q + 1 ! shift to 1-based index
155  ENDDO
156  ENDDO
157 
158  END SUBROUTINE gen_pos3d_surf
159 
160  SUBROUTINE init_all
161  CHARACTER(len=*), PARAMETER :: context = 'init_all: '
162  INTEGER :: ierror
163 
164  CALL mpi_init(ierror)
165  IF (ierror /= mpi_success) CALL ut_abort(context//'MPI_INIT failed', &
166  __file__, &
167  __line__)
168 
169  CALL mpi_comm_size(mpi_comm_world, nprocs, ierror)
170  IF (ierror /= mpi_success) CALL ut_abort(context//'MPI_COMM_SIZE failed', &
171  __file__, &
172  __line__)
173 
174  CALL mpi_comm_rank(mpi_comm_world, mype, ierror)
175  IF (ierror /= mpi_success) CALL ut_abort(context//'MPI_COMM_RANK failed', &
176  __file__, &
177  __line__)
178  IF (mype==0) THEN
179  lroot = .true.
180  ELSE
181  lroot = .false.
182  ENDIF
183 
184  CALL factorize(nprocs, nprocx, nprocy)
185  IF (verbose .AND. lroot) WRITE(0,*) 'nprocx, nprocy=',nprocx, nprocy
186  mypy = mype / nprocx
187  mypx = mod(mype, nprocx)
188 
189  CALL ut_init(decomp_size=30, comm_tmpl_size=30, comm_size=30, &
190  & debug_lvl=0, mode=ut_mode_dt_p2p, debug_unit=0)
191 
192  CALL deco
193 
194  ALLOCATE(fval(ie,je), gval(ie,je))
195  ALLOCATE(loc_id(ie,je), loc_tpex(ie,je))
196  ALLOCATE(id_pos(ie,je), gval3d(ie,nlev,je), pos3d_surf(ie,je))
197 
198  fval = undef_int
199  gval = undef_int
200  loc_id = int(undef_int, xt_int_kind)
201  loc_tpex = int(undef_int, xt_int_kind)
202  id_pos = undef_int
203  gval3d = undef_int
204  pos3d_surf = undef_int
205 
206  END SUBROUTINE init_all
207 
208  SUBROUTINE gen_id_pos(pos)
209  INTEGER, INTENT(out) :: pos(:,:)
210 
211  INTEGER :: i,j
212  INTEGER :: p
213 
214  p = 0
215  DO j = 1, SIZE(pos,2)
216  DO i = 1, SIZE(pos,1)
217  p = p + 1
218  pos(i,j) = p
219  ENDDO
220  ENDDO
221 
222  END SUBROUTINE gen_id_pos
223 
224 
225  SUBROUTINE exchange2d_2d(itrans, f, g)
226  INTEGER, INTENT(in) :: itrans
227  INTEGER, TARGET, INTENT(in) :: f(:,:)
228  INTEGER, TARGET, INTENT(out) :: g(:,:)
229 
230  INTEGER, POINTER :: p_in, p_out
231 
232  p_in => f(1,1)
233  p_out=> g(1,1)
234 
235  CALL ut_transpose(p_in, itrans, comm_forward, p_out)
236 
237  END SUBROUTINE exchange2d_2d
238 
239  SUBROUTINE exchange2d_3d(itrans, f, g)
240  INTEGER, INTENT(in) :: itrans
241  INTEGER, TARGET, INTENT(in) :: f(:,:)
242  INTEGER, TARGET, INTENT(out) :: g(:,:,:)
243 
244  INTEGER, POINTER :: p_in, p_out
245 
246  p_in => f(1,1)
247  p_out=> g(1,1,1)
248 
249  CALL ut_transpose(p_in, itrans, comm_forward, p_out)
250 
251  END SUBROUTINE exchange2d_3d
252 
253  SUBROUTINE gen_trans(itemp, send_dt, recv_dt, itrans)
254  INTEGER,INTENT(in) :: itemp, send_dt, recv_dt
255  INTEGER,INTENT(out) :: itrans
256 
257  INTEGER :: dt
258 
259  IF (send_dt /= recv_dt) &
260  CALL ut_abort('gen_trans: (send_dt /= recv_dt) unsupported', &
261  __file__, &
262  __line__)
263  dt = send_dt
264  CALL ut_init_transposition(itemp, dt, itrans)
265 
266  END SUBROUTINE gen_trans
267 
268  SUBROUTINE gen_off_trans(itemp, send_dt, send_off, recv_dt, recv_off, itrans)
269  INTEGER,INTENT(in) :: itemp, send_dt, recv_dt
270  INTEGER,INTENT(in) :: send_off(:,:), recv_off(:,:)
271  INTEGER,INTENT(out) :: itrans
272 
273  INTEGER :: send_offsets(size(send_off)), recv_offsets(size(recv_off))
274 
275  send_offsets = reshape(send_off, (/SIZE(send_off)/) )
276  recv_offsets = reshape(recv_off, (/SIZE(recv_off)/) )
277 
278  CALL ut_init_transposition(itemp, send_offsets, recv_offsets, &
279  send_dt, recv_dt, itrans)
280 
281  END SUBROUTINE gen_off_trans
282 
283  SUBROUTINE get_window(gval, win)
284  INTEGER(xt_int_kind), INTENT(in) :: gval(:,:)
285  INTEGER(xt_int_kind), INTENT(out) :: win(:,:)
286 
287  INTEGER :: i, j, ig, jg
288 
289  DO j = 1, je
290  jg = p_joff + j
291  DO i = 1, ie
292  ig = p_ioff + i
293  win(i,j) = gval(ig,jg)
294  ENDDO
295  ENDDO
296 
297  END SUBROUTINE get_window
298 
299  SUBROUTINE gen_template(local_src_idx, local_dst_idx, ihandle)
300  INTEGER(xt_int_kind), INTENT(in) :: local_src_idx(:,:)
301  INTEGER(xt_int_kind), INTENT(in) :: local_dst_idx(:,:)
302  INTEGER, INTENT(out) :: ihandle
303 
304  INTEGER :: src(size(local_src_idx)), dst(size(local_dst_idx))
305 
306  INTEGER :: src_handle, dst_handle
307 
308  src = reshape( local_src_idx, (/SIZE(local_src_idx)/) )
309  dst = reshape( local_dst_idx, (/SIZE(local_dst_idx)/) )
310 
311  CALL ut_init_decomposition(src, g_ie * g_je, src_handle)
312  CALL ut_init_decomposition(dst, g_ie * g_je, dst_handle)
313 
314  CALL ut_init_oneway_transposition_template(src_handle, dst_handle, &
315  mpi_comm_world, ihandle)
316 
317  CALL ut_destroy_decomposition(dst_handle)
318  CALL ut_destroy_decomposition(src_handle)
319 
320  END SUBROUTINE gen_template
321 
322  SUBROUTINE def_exchange(id_in, id_out)
323  INTEGER(xt_int_kind), INTENT(in) :: id_in(:,:)
324  INTEGER(xt_int_kind), INTENT(out) :: id_out(:,:)
325 
326  LOGICAL, PARAMETER :: increased_north_halo = .false.
327  LOGICAL, PARAMETER :: with_north_halo = .true.
328  INTEGER :: i, j
329  INTEGER :: g_core_is, g_core_ie, g_core_js, g_core_je
330  INTEGER :: north_halo
331 
332  ! global core domain:
333  g_core_is = nhalo + 1
334  g_core_ie = g_ie-nhalo
335  g_core_js = nhalo + 1
336  g_core_je = g_je-nhalo
337 
338  ! global tripolar boundsexchange:
339  id_out = undef_index
340  id_out(g_core_is:g_core_ie, g_core_js:g_core_je) &
341  = id_in(g_core_is:g_core_ie, g_core_js:g_core_je)
342 
343  IF (with_north_halo) THEN
344 
345  ! north inversion, (maybe with increased north halo)
346  IF (increased_north_halo) THEN
347  north_halo = nhalo+1
348  ELSE
349  north_halo = nhalo
350  ENDIF
351 
352  IF (2*north_halo > g_core_je) &
353  CALL ut_abort('def_exchange: grid too small (or halo too large)&
354  & for tripolar north exchange', &
355  __file__, &
356  __line__)
357  DO j = 1, north_halo
358  DO i = g_core_is, g_core_ie
359  id_out(i,j) = id_out(g_core_ie + (g_core_is-i), 2*north_halo + (1-j))
360  ENDDO
361  ENDDO
362 
363  ELSE
364 
365  DO j = 1, nhalo
366  DO i = nhalo+1, g_ie-nhalo
367  id_out(i,j) = id_in(i,j)
368  ENDDO
369  ENDDO
370 
371  ENDIF
372 
373  ! south: no change
374  DO j = g_core_je+1, g_je
375  DO i = nhalo+1, g_ie-nhalo
376  id_out(i,j) = id_in(i,j)
377  ENDDO
378  ENDDO
379 
380  ! PBC
381  DO j = 1, g_je
382  DO i = 1, nhalo
383  id_out(g_core_is-i,j) = id_out(g_core_ie+(1-i),j)
384  ENDDO
385  DO i = 1, nhalo
386  id_out(g_core_ie+i,j) = id_out(nhalo+i,j)
387  ENDDO
388  ENDDO
389 
390  CALL check_g_idx(id_out)
391 
392  END SUBROUTINE def_exchange
393 
394  SUBROUTINE check_g_idx(gidx)
395  INTEGER(xt_int_kind), INTENT(in) :: gidx(:,:)
396 
397  IF (any(gidx == undef_index)) THEN
398  CALL ut_abort('check_g_idx: check failed', __file__, __line__)
399  ENDIF
400  END SUBROUTINE check_g_idx
401 
402  SUBROUTINE deco
403  INTEGER :: cx0(0:nprocx-1), cxn(0:nprocx-1)
404  INTEGER :: cy0(0:nprocy-1), cyn(0:nprocy-1)
405 
406  CALL regular_deco(g_ie-2*nhalo, cx0, cxn)
407  CALL regular_deco(g_je-2*nhalo, cy0, cyn)
408 
409  ! process local deco variables:
410  ie = cxn(mypx) + 2*nhalo
411  je = cyn(mypy) + 2*nhalo
412  p_ioff = cx0(mypx)
413  p_joff = cy0(mypy)
414 
415  END SUBROUTINE deco
416 
417 END PROGRAM test_ut
418 !
419 ! Local Variables:
420 ! f90-continuation-indent: 5
421 ! coding: utf-8
422 ! indent-tabs-mode: nil
423 ! show-trailing-whitespace: t
424 ! require-trailing-newline: t
425 ! End:
426 !