49 USE iso_c_binding
, ONLY: c_int
58 USE ftest_common
, ONLY: test_abort, icmp, id_map, factorize, regular_deco, &
70 INTEGER,
PARAMETER :: g_ie = 8, g_je = 4
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
76 LOGICAL,
PARAMETER :: increased_north_halo = .false.
77 LOGICAL,
PARAMETER :: with_north_halo = .true.
80 INTEGER :: p_ioff, p_joff
81 INTEGER :: nprocx, nprocy
83 INTEGER :: mype, mypx, mypy
86 INTEGER(xt_int_kind) :: g_id(g_ie, g_je)
89 INTEGER(xt_int_kind) :: g_tpex(g_ie, g_je)
91 TYPE(xt_redist) :: redist_tpex
92 TYPE(xt_redist) :: redist_surf_tpex
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(:,:)
107 CALL get_window(g_id, loc_id)
110 CALL def_exchange(g_id, g_tpex)
113 CALL get_window(g_tpex, loc_tpex)
116 CALL general_fsection_test
122 CALL gen_template(loc_id, loc_tpex, xmap_tpex)
125 CALL gen_trans(xmap_tpex, mpi_integer, mpi_integer, redist_tpex)
131 CALL icmp(
'2d to 2d check', gval, int(loc_tpex), mype)
133 CALL check_redist_collection_static
136 CALL gen_id_pos(id_pos)
137 CALL gen_id_pos(pos3d_surf)
138 CALL gen_pos3d_surf(pos3d_surf)
141 CALL gen_off_trans(xmap_tpex, mpi_integer, int(id_pos(:,:)) - 1, &
142 mpi_integer, int(pos3d_surf(:,:)) - 1, redist_surf_tpex)
147 reshape(fval, (/ ie, je, 1 /)), gval3d)
149 CALL icmp(
'surface check', gval3d(:,1,:), int(loc_tpex), mype)
151 CALL icmp(
'sub surface check', gval3d(:,2,:), int(loc_tpex)*0-1, mype)
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)
172 INTEGER :: ir, ierror
173 rvec(:) = redist_tpex
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)
185 f(:,:,ir) = int(loc_id) + (ir-1) * ie*je
195 IF (any(g /= ref_g))
CALL my_abort(
'(g /= ref_g)', __line__)
198 END SUBROUTINE check_redist_collection_static
200 SUBROUTINE check_modifiers()
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
210 CALL def_tpex_mod_via_idxvec(m_tpex, m_tpex_num)
212 loc_tpex2_idxlist =
xt_idxmod_new(loc_id_idxlist, m_tpex, m_tpex_num, mstate)
215 IF (any(loc_tpex2 /= loc_tpex)) &
216 CALL my_abort(
'idx copy does not match', __line__)
220 loc_tpex2_idxlist =
xt_idxmod_new(loc_id_idxlist, m_tpex, m_tpex_num)
223 IF (any(loc_tpex2 /= loc_tpex)) &
224 CALL my_abort(
'idx copy does not match', __line__)
226 CALL delete_modifiers(m_tpex(1:m_tpex_num))
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)
234 IF (any(loc_tpex2 /= loc_tpex)) &
235 CALL my_abort(
'idx copy does not match', __line__)
237 CALL delete_modifiers(m_tpex(1:m_tpex_num))
241 END SUBROUTINE check_modifiers
243 SUBROUTINE delete_modifiers(m)
253 END SUBROUTINE delete_modifiers
255 SUBROUTINE my_abort(msg, line)
256 CHARACTER(*),
INTENT(in) :: msg
257 INTEGER,
VALUE,
INTENT(in) :: line
258 CALL test_abort(msg, &
261 END SUBROUTINE my_abort
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
282 lstart = (/ 1_xt_int_kind, 1_xt_int_kind /)
285 global_section = xt_idxfsection_new(gstart, gsize, int(gsize), lstart)
292 IF (egis(i,j) /= indices(p))
CALL my_abort(
'(1) bad indices', __line__)
298 local_section = xt_idxfsection_new(gstart, gsize, (/ ldx, ldy /), lstart)
305 IF (egis(i,j) /= indices(p))
CALL my_abort(
'(2) bad indices', __line__)
311 local_section = xt_idxfsection_new(gstart, gsize, &
312 (/ -ldx, ldy /), lstart)
319 IF (egis(i,j) /= indices(p))
CALL my_abort(
'(3) bad indices', __line__)
325 local_section = xt_idxfsection_new(gstart, gsize, (/ ldx, -ldy /), lstart)
332 IF (egis(i,j) /= indices(p))
CALL my_abort(
'(4) bad indices', __line__)
338 local_section = xt_idxfsection_new(gstart, gsize, &
339 (/ -ldx, -ldy /), lstart)
346 IF (egis(i,j) /= indices(p))
CALL my_abort(
'(5) bad indices', __line__)
350 END SUBROUTINE general_fsection_test
352 SUBROUTINE gen_pos3d_surf(pos)
353 INTEGER,
INTENT(inout) :: pos(:,:)
357 INTEGER :: ii,jj, i,j,k, p,q
365 q = i + k*ie + j*ie*nlev
370 END SUBROUTINE gen_pos3d_surf
373 CHARACTER(len=*),
PARAMETER :: context =
'init_all: ' 376 CALL mpi_init(ierror)
377 IF (ierror /= mpi_success) &
378 CALL my_abort(context//
'MPI_INIT failed', __line__)
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__)
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__)
395 CALL factorize(nprocs, nprocx, nprocy)
396 IF (verbose .AND. lroot)
WRITE(0,*)
'nprocx, nprocy=',nprocx, nprocy
398 mypx = mod(mype, nprocx)
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))
411 loc_id = int(undef_int, xt_int_kind)
412 loc_tpex = int(undef_int, xt_int_kind)
415 pos3d_surf = undef_int
417 END SUBROUTINE init_all
419 SUBROUTINE gen_id_pos(pos)
420 INTEGER,
INTENT(out) :: pos(:,:)
425 DO j = 1,
SIZE(pos,2)
426 DO i = 1,
SIZE(pos,1)
432 END SUBROUTINE gen_id_pos
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
441 IF (send_dt /= recv_dt) &
442 CALL my_abort(
'gen_trans: (send_dt /= recv_dt) unsupported', __line__)
447 END SUBROUTINE gen_trans
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
459 IF (recv_dt /= send_dt) &
460 CALL my_abort(
'(datatype_in /= datatype_out) not supported', &
466 END SUBROUTINE gen_off_trans
468 SUBROUTINE get_window(gval, win)
469 INTEGER(xt_int_kind),
INTENT(in) :: gval(:,:)
470 INTEGER(xt_int_kind),
INTENT(out) :: win(:,:)
472 INTEGER :: i, j, ig, jg
478 win(i,j) = gval(ig,jg)
482 END SUBROUTINE get_window
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
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)
496 IF (src_num /= g_ie*g_je)
CALL my_abort(
'unexpected src_num', __line__)
498 IF (any(cp_src_idx /= local_src_idx))
CALL my_abort(
'idx copy does not match', &
503 IF (dst_num /= g_ie*g_je)
CALL my_abort(
'unexpected dst_num', __line__)
505 IF (any(cp_dst_idx /= local_dst_idx))
CALL my_abort(
'idx copy does not match', &
512 END SUBROUTINE gen_template
514 SUBROUTINE def_tpex_mod_via_idxvec(mvec, mvec_num)
516 INTEGER,
INTENT(out) :: mvec_num
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
523 IF (
SIZE(mvec)<1)
CALL my_abort(
'def_tpex_mod_via_idxvec mvec too small', &
526 CALL id_map(g_start_indices)
527 g_start_idxlist =
xt_idxvec_new(g_start_indices,
SIZE(g_start_indices))
529 CALL def_exchange(g_start_indices, g_end_indices)
530 g_end_idxlist =
xt_idxvec_new(g_end_indices,
SIZE(g_end_indices))
532 mvec(1)%extract = g_start_idxlist
533 mvec(1)%subst = g_end_idxlist
537 END SUBROUTINE def_tpex_mod_via_idxvec
539 SUBROUTINE def_tpex_mod_via_sections(mvec, mvec_num)
541 INTEGER,
INTENT(out) :: mvec_num
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) /)
548 INTEGER(xt_int_kind) :: g_core_is, g_core_ie, g_core_je
549 INTEGER(xt_int_kind) :: north_halo, im
552 g_core_is = nhalo + 1
553 g_core_ie = g_ie-nhalo
554 g_core_je = g_je-nhalo
559 IF (with_north_halo)
THEN 562 IF (increased_north_halo)
THEN 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__)
572 im = im + 1_xt_int_kind
573 IF (
SIZE(mvec)<im)
CALL my_abort(
'(SIZE(mvec)<im)', __line__)
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/))
584 im = im + 1_xt_int_kind
585 IF (
SIZE(mvec)<im)
CALL my_abort(
'(SIZE(mvec)<im)', __line__)
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/))
594 im = im + 1_xt_int_kind
595 IF (
SIZE(mvec)<im)
CALL my_abort(
'(SIZE(mvec)<im)', __line__)
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, &
602 (/int(g_ie - 1, xt_int_kind), north_halo+1_xt_int_kind/))
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, &
620 (/ g_core_ie - int(ldx, xt_int_kind) + 1_xt_int_kind, &
621 north_halo + 1_xt_int_kind/))
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/))
635 END SUBROUTINE def_tpex_mod_via_sections
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(:,:)
642 INTEGER :: g_core_is, g_core_ie, g_core_js, g_core_je
643 INTEGER :: north_halo
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
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)
656 IF (with_north_halo)
THEN 659 IF (increased_north_halo)
THEN 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__)
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))
677 DO i = nhalo+1, g_ie-nhalo
678 id_out(i,j) = id_in(i,j)
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)
694 id_out(g_core_is-i,j) = id_out(g_core_ie+(1-i),j)
697 id_out(g_core_ie+i,j) = id_out(nhalo+i,j)
701 CALL check_g_idx(id_out)
703 END SUBROUTINE def_exchange
705 SUBROUTINE check_g_idx(gidx)
706 INTEGER(xt_int_kind),
INTENT(in) :: gidx(:,:)
708 IF (any(gidx == undef_index))
THEN 709 CALL my_abort(
'check_g_idx: check failed', __line__)
711 END SUBROUTINE check_g_idx
714 INTEGER :: cx0(0:nprocx-1), cxn(0:nprocx-1)
715 INTEGER :: cy0(0:nprocy-1), cyn(0:nprocy-1)
717 CALL regular_deco(g_ie-2*nhalo, cx0, cxn)
718 CALL regular_deco(g_je-2*nhalo, cy0, cyn)
721 ie = cxn(mypx) + 2*nhalo
722 je = cyn(mypy) + 2*nhalo
728 END PROGRAM test_yaxt