2 c From Craig Douglas, modified by Bill Gropp (based on code in Using
4 c This code tests some topology routines and sendrecv with some
5 c MPI_PROC_NULL source/destinations. It should be run with 4
12 double precision a(maxn,maxn)
14 integer myid, newid, numprocs, comm2d, ierr, stride
15 integer nbrleft, nbrright, nbrtop, nbrbottom
16 integer sx, ex, sy, ey
17 integer dims(2), coords(2)
18 integer nerrs, toterrs
21 data periods/2*.false./
25 call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )
26 call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )
27 c print *, "Process ", myid, " of ", numprocs, " is alive"
28 if (numprocs .ne. 4) then
29 print *, "This test requires exactly four processes"
30 call MPI_Abort( MPI_COMM_WORLD, 1, ierr )
36 call MPI_DIMS_CREATE( numprocs, 2, dims, ierr )
37 call MPI_CART_CREATE( MPI_COMM_WORLD, 2, dims, periods, .true.,
39 call MPI_COMM_RANK( comm2d, newid, ierr )
41 print *, "Process ", myid, " of ", numprocs, " is now ",
45 call MPI_Cart_shift( comm2d, 0, 1, nbrleft, nbrright, ierr )
46 call MPI_Cart_shift( comm2d, 1, 1, nbrbottom, nbrtop, ierr )
48 print *, "Process ", myid, " has nbrs", nbrleft, nbrright,
51 call MPI_Cart_get( comm2d, 2, dims, periods, coords, ierr )
52 call MPE_DECOMP1D( nx, dims(1), coords(1), sx, ex )
53 call MPE_DECOMP1D( ny, dims(2), coords(2), sy, ey )
55 c Fortran allows print to include * and , in the output!
56 c So, we use an explicit Format
58 & print 10, dims(1), dims(2)
59 10 format( " Dims: ", i4, i4 )
61 print *, "Process ", myid, " has coords of ", coords
62 print *, "Process ", myid, " has sx,ex/sy,ey ", sx,
65 call MPI_TYPE_VECTOR( ey-sy+3, 1, ex-sx+3,
66 $ MPI_DOUBLE_PRECISION, stride, ierr )
67 call MPI_TYPE_COMMIT( stride, ierr )
68 call setupv( myid, a, sx, ex, sy, ey )
69 call MPI_BARRIER( MPI_COMM_WORLD, ierr )
71 call exchng2( myid, a, sx, ex, sy, ey, comm2d, stride,
72 $ nbrleft, nbrright, nbrtop, nbrbottom )
76 call checkval( a, sx, ex, sy, ey, nx, ny, nerrs )
78 call mpi_allreduce( nerrs, toterrs, 1, MPI_INTEGER, MPI_SUM,
79 $ MPI_COMM_WORLD, ierr )
81 print *, " Total errors = ", toterrs
83 call MPI_TYPE_FREE( stride, ierr )
84 call MPI_COMM_FREE( comm2d, ierr )
85 c call prv( -1, -1, -1, a, sx, ex, sy, ey )
86 call MPI_FINALIZE(ierr)
88 subroutine MPE_DECOMP1D( n, numprocs, myid, s, e )
89 integer n, numprocs, myid, s, e
95 deficit = mod(n,numprocs)
96 s = s + min(myid,deficit)
97 if (myid .lt. deficit) then
101 if (e .gt. n .or. myid .eq. numprocs-1) e = n
104 subroutine exchng2( myid, v, sx, ex, sy, ey,
106 $ nbrleft, nbrright, nbrtop, nbrbottom )
108 integer myid, sx, ex, sy, ey, stride
109 double precision v(sx-1:ex+1,sy-1:ey+1)
110 integer nbrleft, nbrright, nbrtop, nbrbottom, comm2d
111 integer status(MPI_STATUS_SIZE), ierr, nx
114 c These are just like the 1-d versions, except for less data
115 c call prv( myid, -1, -1, v, sx, ex, sy, ey )
116 call MPI_SENDRECV( v(sx,ey), nx, MPI_DOUBLE_PRECISION,
118 $ v(sx,sy-1), nx, MPI_DOUBLE_PRECISION,
119 $ nbrbottom, 0, comm2d, status, ierr )
120 c call prv( myid, nbrtop, nbrbottom, v, sx, ex, sy, ey )
121 call MPI_SENDRECV( v(sx,sy), nx, MPI_DOUBLE_PRECISION,
123 $ v(sx,ey+1), nx, MPI_DOUBLE_PRECISION,
124 $ nbrtop, 1, comm2d, status, ierr )
125 c call prv( myid, nbrbottom, nbrtop, v, sx, ex, sy, ey )
126 c This uses the "strided" datatype
127 c v(ex,sy-1) = -100 - myid
128 call MPI_SENDRECV( v(ex,sy-1), 1, stride, nbrright, 2,
129 $ v(sx-1,sy-1), 1, stride, nbrleft, 2,
130 $ comm2d, status, ierr )
131 c call prv( myid, nbrright, nbrleft, v, sx, ex, sy, ey )
132 c v(sx,sy-1) = -200 - myid
133 call MPI_SENDRECV( v(sx,sy-1), 1, stride, nbrleft, 3,
134 $ v(ex+1,sy-1), 1, stride, nbrright, 3,
135 $ comm2d, status, ierr )
136 c call prv( myid, nbrleft, nbrright, v, sx, ex, sy, ey )
139 subroutine prv( myid, n1, n2, v, sx, ex, sy, ey )
140 c***********************************************************************
142 c Print a matrix of numbers.
144 c***********************************************************************
145 integer myid, n1, n2, sx, ex, sy, ey
146 double precision v(sx-1:ex+1,sy-1:ey+1)
151 if ( myid .lt. 0 ) then
155 write (fname,'(''foo.'',i1)') myid
157 & open( 11, file=fname, status='UNKNOWN' )
158 write (11,*) '----------------------------------------'
159 if ( count .eq. 0 ) then
160 write (11,*) 'sx ', sx
161 write (11,*) 'ex ', ex
162 write (11,*) 'sy ', sy
163 write (11,*) 'ey ', ey
164 write (11,*) '----------------------------------------'
167 write (11,*) 'count,n1,n2: ', count, n1, n2
169 write (11,1) j, (v(i,j), i = sx-1,ex+1)
172 1 Format( i3, 20f7.0 )
173 c1 Format( i3, 1p, 20d10.1 )
175 subroutine setupv( myid, v, sx, ex, sy, ey )
176 integer myid, sx, ex, sy, ey
177 double precision v(sx-1:ex+1,sy-1:ey+1)
179 c write (*,*) 'setupv: ', myid, sx, ex, sy, ey
192 c***********************************************************************
193 subroutine checkval( a, sx, ex, sy, ey, nx, ny, errs )
194 integer sx, ex, sy, ey, nx, ny
195 double precision a(sx-1:ex+1,sy-1:ey+1)
205 if (a(i,j) .ne. i + k ) then
207 print *, "error at (", i, ",", j, ") = ", a(i,j)
211 c Check the boundaries
216 if (a(i,j) .ne. 0.0) then
218 print *, "error at (", i, ",", j, ") = ", a(i,j)
223 if (a(i,j) .ne. i + j * 1000) then
225 print *, "error at (", i, ",", j, ") = ", a(i,j)
232 if (a(i,j) .ne. 0.0) then
234 print *, "error at (", i, ",", j, ") = ", a(i,j)
239 if (a(i,j) .ne. i + j * 1000) then
241 print *, "error at (", i, ",", j, ") = ", a(i,j)
248 if (a(i,j) .ne. 0.0) then
250 print *, "error at (", i, ",", j, ") = ", a(i,j)
255 if (a(i,j) .ne. i + j * 1000) then
257 print *, "error at (", i, ",", j, ") = ", a(i,j)
264 if (a(i,j) .ne. 0.0) then
266 print *, "error at (", i, ",", j, ") = ", a(i,j)
271 if (a(i,j) .ne. i + j * 1000) then
273 print *, "error at (", i, ",", j, ") = ", a(i,j)