!> !> @file pex12.f90 !> !> @brief Create and write array with ghost cells, dynamic version !> !> @copyright !> Copyright (©) 2021 EPFL (Ecole Polytechnique Fédérale de Lausanne) !> SPC (Swiss Plasma Center) !> !> futils is free software: you can redistribute it and/or modify it under !> the terms of the GNU Lesser General Public License as published by the Free !> Software Foundation, either version 3 of the License, or (at your option) !> any later version. !> !> futils is distributed in the hope that it will be useful, but WITHOUT ANY !> WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS !> FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. !> !> You should have received a copy of the GNU Lesser General Public License !> along with this program. If not, see . !> !> @authors !> (in alphabetical order) !> @author Trach-Minh Tran !> PROGRAM main ! ! Create and write array with ghost cells, dynamic version ! USE futils USE mpi IMPLICIT NONE CHARACTER(len=32) :: file='para.h5', str INTEGER :: ierr, fid, me, npes, lstr INTEGER, PARAMETER :: ndims=2, comm=MPI_COMM_WORLD INTEGER, DIMENSION(ndims) :: dims, coords LOGICAL :: periods(ndims), reorder INTEGER :: cart, cartcol, cartrow ! INTEGER, DIMENSION(ndims) :: offsets, np INTEGER :: n1=7, n2=9, n3=3 INTEGER :: i, j, k, iglob, jglob DOUBLE PRECISION, ALLOCATABLE :: array2(:,:,:) !=========================================================================== ! 1. Prologue ! Init MPI CALL mpi_init(ierr) CALL mpi_comm_size(MPI_COMM_WORLD, npes, ierr) CALL mpi_comm_rank(MPI_COMM_WORLD, me, ierr) ! ! Read 2d processor grid P1xP2 from command line IF( command_argument_count() .EQ. 2 ) THEN CALL get_command_argument(1, str, lstr, ierr) READ(str(1:lstr),'(i3)') dims(1) CALL get_command_argument(2, str, lstr, ierr) READ(str(1:lstr),'(i3)') dims(2) ELSE IF( me.EQ.0 ) PRINT*, 'Requires 2 arguments: P1, P2!' CALL mpi_abort(MPI_COMM_WORLD, -1, ierr) END IF ! ! Create cartesian topololy IF( me .EQ. 0 ) WRITE(*,'(a,i3,i3)') '2d rocessor grid', dims periods = (/.FALSE., .FALSE./) reorder = .FALSE. CALL mpi_cart_create(comm, ndims, dims, periods, reorder, cart, ierr) CALL mpi_cart_coords(cart, me, ndims, coords, ierr) CALL mpi_cart_sub(cart, (/.TRUE., .FALSE. /), cartcol, ierr) CALL mpi_cart_sub(cart, (/.FALSE., .TRUE. /), cartrow, ierr) !=========================================================================== ! 2. Array parallel partition ! ! Local array offsets and sizes CALL dist1d(cartcol, 0, n1, offsets(1), np(1)) CALL dist1d(cartrow, 0, n2, offsets(2), np(2)) WRITE(*,'(a,i3.3,a,10i5)') 'PE', me, ': coords, offsets, np', & & coords, offsets, np ! ! Allocate local arrays including ghost cells ALLOCATE(array2(0:np(1)+1, 0:np(2)+1, n3)) ! ! Fill local arrays, with ghost cells containing value of "me" array2(:,:,:) = me DO i=1,np(1) iglob = offsets(1)+i DO j=1,np(2) jglob = offsets(2)+j DO k=1,n3 array2(i,j, k) = 100*iglob + 10*jglob + k END DO END DO END DO !=========================================================================== ! 3. Parallel write ! CALL creatf(file, fid, & & desc="A parallel file", & & real_prec='s', & & mpiposix=.FALSE., & & mpicomm=cart) ! CALL putarrnd(fid, "/parray2g", array2, (/1,2/), desc='With ghost cells') CALL putarrnd(fid, "/parray2", array2, (/1,2/), garea=(/1,1/), & & desc='Without ghost cells') CALL closef(fid) !=========================================================================== ! 9. Epilogue DEALLOCATE(array2) CALL mpi_finalize(ierr) END PROGRAM main SUBROUTINE dist1d(comm, s0, ntot, s, nloc) USE mpi IMPLICIT NONE INTEGER, INTENT(in) :: s0, ntot INTEGER, INTENT(out) :: s, nloc INTEGER :: comm, me, npes, ierr, naver, rem ! CALL MPI_COMM_SIZE(comm, npes, ierr) CALL MPI_COMM_RANK(comm, me, ierr) naver = ntot/npes rem = MODULO(ntot,npes) s = s0 + MIN(rem,me) + me*naver nloc = naver IF( me.LT.rem ) nloc = nloc+1 ! END SUBROUTINE dist1d