51 & ut_transpose, ut_init_decomposition, &
55 USE ftest_common
, ONLY: finish_mpi, init_mpi, treset, tstart, tstop, &
56 treport, timer, id_map, factorize, regular_deco, set_verbose
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
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
74 CHARACTER(len=10) :: grid_label
77 INTEGER :: p_ioff, p_joff
78 INTEGER :: nprocx, nprocy
81 INTEGER :: mype, mypx, mypy
84 INTEGER,
ALLOCATABLE :: g_id(:,:)
86 INTEGER,
ALLOCATABLE :: g_tpex(:, :)
87 INTEGER :: template_tpex_2d, trans_tpex_2d
88 INTEGER :: template_tpex_3d, trans_tpex_3d
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
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
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')
123 CALL get_window(g_id, loc_id_2d)
130 CALL get_window(g_tpex, 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)
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)
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)
152 CALL id_map(pos3d_surf)
153 CALL gen_pos3d_surf(pos3d_surf)
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)
163 ALLOCATE(gval_3d(ie,nlev,je))
165 CALL tstart(t_exch_surf)
166 CALL exchange2d_3d(surf_trans_tpex_2d, fval_2d, gval_3d)
167 CALL tstop(t_exch_surf)
169 CALL icmp_2d(
'surface check', gval_3d(:,1,:), loc_tpex_2d)
172 CALL icmp_2d(
'sub surface check', gval_3d(:,2,:), loc_tpex_2d*0-1)
180 CALL inflate_idx(3, loc_id_2d, loc_id_3d)
181 CALL inflate_idx(3, loc_tpex_2d, 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)
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)
195 ALLOCATE(fval_3d(ie,je,nlev), gval_3d(ie,je,nlev))
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)
208 IF (verbose)
WRITE(0,*)
'timer report for nprocs=',nprocs
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)
226 CHARACTER(len=*),
INTENT(in) :: s
227 IF (verbose)
WRITE(0,*) s
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(:,:,:)
238 IF (
ALLOCATED(idx_3d))
DEALLOCATE(idx_3d)
240 IF (inflate_pos == 3)
THEN 241 ALLOCATE(idx_3d(ie, je, ke))
245 idx_3d(i,j,k) = idx_2d(i,j) + (k-1) * g_ie * g_je
250 CALL ut_abort(context//
' unsupported inflate position', &
255 END SUBROUTINE inflate_idx
257 SUBROUTINE gen_pos3d_surf(pos)
258 INTEGER,
INTENT(inout) :: pos(:,:)
262 INTEGER :: ii,jj, i,j,k, p,q
270 q = i + k*ie + j*ie*nlev
275 END SUBROUTINE gen_pos3d_surf
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(:,:)
283 INTEGER :: i, j, n1, n2
287 IF (
SIZE(g,1) /= n1 .OR.
SIZE(g,2) /= n2) &
288 CALL ut_abort(context//
'internal error', &
294 IF (f(i,j) /= g(i,j))
THEN 295 WRITE(0,*) context,label,
' test failed: i, j, f(i,j), g(i,j) =', &
297 CALL ut_abort(context//label//
' test failed', &
304 END SUBROUTINE icmp_2d
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(:,:,:)
312 INTEGER :: i, j, k, n1, n2, n3
317 IF (
SIZE(g,1) /= n1 .OR.
SIZE(g,2) /= n2 .OR.
SIZE(g,3) /= n3) &
318 CALL ut_abort(context//
'internal error', &
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', &
337 END SUBROUTINE icmp_3d
340 CHARACTER(len=*),
PARAMETER :: context =
'init_all: ' 342 CHARACTER(len=20) :: grid_str
344 CALL get_environment_variable(
'YAXT_TEST_PERF_GRID', grid_str)
348 SELECT CASE (trim(adjustl(grid_str)))
350 grid_kind = grid_kind_toy
355 grid_kind = grid_kind_tp10
360 grid_kind = grid_kind_tp04
365 grid_kind = grid_kind_tp6m
370 grid_kind = grid_kind_test
377 CALL mpi_comm_size(mpi_comm_world, nprocs, ierror)
378 IF (ierror /= mpi_success)
CALL ut_abort(context//
'MPI_COMM_SIZE failed', &
382 CALL mpi_comm_rank(mpi_comm_world, mype, ierror)
383 IF (ierror /= mpi_success)
CALL ut_abort(context//
'MPI_COMM_RANK failed', &
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
397 mypx = mod(mype, nprocx)
402 ALLOCATE(g_id(g_ie, g_je), g_tpex(g_ie, g_je))
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))
410 loc_id_2d = undef_int
411 loc_tpex_2d = undef_int
413 pos3d_surf = undef_int
415 CALL ut_init(decomp_size=30, comm_tmpl_size=30, comm_size=30, &
418 END SUBROUTINE init_all
420 SUBROUTINE exchange2d_2d(itrans, f, g)
421 INTEGER,
INTENT(in) :: itrans
422 INTEGER,
TARGET,
INTENT(in) :: f(:,:)
423 INTEGER,
TARGET,
INTENT(out) :: g(:,:)
425 INTEGER,
POINTER :: p_in, p_out
432 END SUBROUTINE exchange2d_2d
434 SUBROUTINE exchange3d_3d(itrans, f, g)
435 INTEGER,
INTENT(in) :: itrans
436 INTEGER,
TARGET,
INTENT(in) :: f(:,:,:)
437 INTEGER,
TARGET,
INTENT(out) :: g(:,:,:)
439 INTEGER,
POINTER :: p_in, p_out
446 END SUBROUTINE exchange3d_3d
449 SUBROUTINE exchange2d_3d(itrans, f, g)
450 INTEGER,
INTENT(in) :: itrans
451 INTEGER,
TARGET,
INTENT(in) :: f(:,:)
452 INTEGER,
TARGET,
INTENT(out) :: g(:,:,:)
454 INTEGER,
POINTER :: p_in, p_out
461 END SUBROUTINE exchange2d_3d
463 SUBROUTINE gen_trans(itemp, send_dt, recv_dt, itrans)
464 INTEGER,
INTENT(in) :: itemp, send_dt, recv_dt
465 INTEGER,
INTENT(out) :: itrans
469 IF (send_dt /= recv_dt) &
470 CALL ut_abort(
'gen_trans: (send_dt /= recv_dt) unsupported', &
474 CALL ut_init_transposition(itemp, dt, itrans)
476 END SUBROUTINE gen_trans
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
483 INTEGER :: send_offsets(size(send_off)), recv_offsets(size(recv_off))
485 send_offsets = reshape(send_off, (/
SIZE(send_off)/) )
486 recv_offsets = reshape(recv_off, (/
SIZE(recv_off)/) )
488 CALL ut_init_transposition(itemp, send_offsets, recv_offsets, &
489 send_dt, recv_dt, itrans)
491 END SUBROUTINE gen_off_trans
493 SUBROUTINE get_window(gval, win)
494 INTEGER,
INTENT(in) :: gval(:,:)
495 INTEGER,
INTENT(out) :: win(:,:)
497 INTEGER :: i, j, ig, jg
503 win(i,j) = gval(ig,jg)
507 END SUBROUTINE get_window
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
514 INTEGER :: src(size(local_src_idx)), dst(size(local_dst_idx))
516 INTEGER :: src_handle, dst_handle
518 src = reshape( local_src_idx, (/
SIZE(local_src_idx)/) )
519 dst = reshape( local_dst_idx, (/
SIZE(local_dst_idx)/) )
521 CALL ut_init_decomposition(src, g_ie * g_je, src_handle)
522 CALL ut_init_decomposition(dst, g_ie * g_je, dst_handle)
525 mpi_comm_world, ihandle)
530 END SUBROUTINE gen_template_2d
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
537 INTEGER,
ALLOCATABLE :: src(:), dst(:)
538 INTEGER :: src_handle, dst_handle
540 ALLOCATE(src(
SIZE(local_src_idx)), dst(
SIZE(local_dst_idx)))
542 src = reshape( local_src_idx, (/
SIZE(local_src_idx)/) )
543 dst = reshape( local_dst_idx, (/
SIZE(local_dst_idx)/) )
545 CALL ut_init_decomposition(src, g_ie * g_je, src_handle)
546 CALL ut_init_decomposition(dst, g_ie * g_je, dst_handle)
549 mpi_comm_world, ihandle)
554 END SUBROUTINE gen_template_3d
557 SUBROUTINE def_exchange()
559 LOGICAL,
PARAMETER :: increased_north_halo = .false.
560 LOGICAL,
PARAMETER :: with_north_halo = .true.
562 INTEGER :: g_core_is, g_core_ie, g_core_js, g_core_je
563 INTEGER :: north_halo
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
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)
576 IF (with_north_halo)
THEN 579 IF (increased_north_halo)
THEN 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', &
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))
599 DO i = nhalo+1, g_ie-nhalo
600 g_tpex(i,j) = g_id(i,j)
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)
616 g_tpex(g_core_is-i,j) = g_tpex(g_core_ie+(1-i),j)
619 g_tpex(g_core_ie+i,j) = g_tpex(nhalo+i,j)
623 CALL check_g_idx (g_tpex)
625 END SUBROUTINE def_exchange
627 SUBROUTINE check_g_idx(gidx)
628 INTEGER,
INTENT(in) :: gidx(:,:)
630 IF (any(gidx == undef_index))
THEN 631 CALL ut_abort(
'check_g_idx: check failed', __file__, __line__)
633 END SUBROUTINE check_g_idx
636 INTEGER :: cx0(0:nprocx-1), cxn(0:nprocx-1)
637 INTEGER :: cy0(0:nprocy-1), cyn(0:nprocy-1)
641 CALL regular_deco(g_ie-2*nhalo, cx0, cxn)
645 CALL regular_deco(g_je-2*nhalo, cy0, cyn)
648 ie = cxn(mypx) + 2*nhalo
649 je = cyn(mypy) + 2*nhalo
655 END PROGRAM test_perf