00001 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00002 ! !
00003 ! MPP_TRANSMIT !
00004 ! !
00005 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00006
00007 subroutine MPP_TRANSMIT_( put_data, put_len, to_pe, get_data, get_len, from_pe )
00008 !a message-passing routine intended to be reminiscent equally of both MPI and SHMEM
00009
00010 !put_data and get_data are contiguous MPP_TYPE_ arrays
00011
00012 !at each call, your put_data array is put to to_pe's get_data
00013 ! your get_data array is got from from_pe's put_data
00014 !i.e we assume that typically (e.g updating halo regions) each PE performs a put _and_ a get
00015
00016 !special PE designations:
00017 ! NULL_PE: to disable a put or a get (e.g at boundaries)
00018 ! ANY_PE: if remote PE for the put or get is to be unspecific
00019 ! ALL_PES: broadcast and collect operations (collect not yet implemented)
00020
00021 !ideally we would not pass length, but this f77-style call performs better (arrays passed by address, not descriptor)
00022 !further, this permits <length> contiguous words from an array of any rank to be passed (avoiding f90 rank conformance check)
00023
00024 !caller is responsible for completion checks (mpp_sync_self) before and after
00025
00026 integer, intent(in) :: put_len, to_pe, get_len, from_pe
00027 MPP_TYPE_, intent(in) :: put_data(*)
00028 MPP_TYPE_, intent(out) :: get_data(*)
00029 integer :: i
00030 #ifdef use_libSMA
00031 integer :: np
00032 integer(LONG_KIND) :: data_loc
00033 !pointer to remote data
00034 MPP_TYPE_ :: remote_data(get_len)
00035 pointer( ptr_remote_data, remote_data )
00036 MPP_TYPE_ :: broadcast_data(get_len)
00037 pointer( ptr, broadcast_data )
00038 integer :: words
00039 character(len=8) :: text
00040 #endif
00041 MPP_TYPE_, allocatable, save :: local_data(:) !local copy used by non-parallel code (no SHMEM or MPI)
00042
00043 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_TRANSMIT: You must first call mpp_init.' )
00044 if( to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE )return
00045
00046 if( debug )then
00047 call SYSTEM_CLOCK(tick)
00048 write( stdout(),'(a,i18,a,i5,a,2i5,2i8)' )&
00049 'T=',tick, ' PE=',pe, ' MPP_TRANSMIT begin: to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len
00050 end if
00051
00052 !do put first and then get
00053 if( to_pe.GE.0 .AND. to_pe.LT.npes )then
00054 #ifdef use_libSMA
00055 !send data pointer to to_pe
00056 #ifdef _CRAYT90
00057 call SHMEM_UDCFLUSH !invalidate data cache
00058 #endif
00059 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00060 call SHMEM_INT8_WAIT( status(to_pe), MPP_WAIT )
00061 status(to_pe) = MPP_WAIT !prohibit puts to to_pe until it has retrieved this message
00062 if( current_clock.NE.0 )call increment_current_clock(EVENT_WAIT)
00063 data_loc = LOC(put_data)
00064 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00065 call SHMEM_INTEGER_PUT( mpp_from_pe, pe, 1, to_pe )
00066 call SHMEM_PUT8( remote_data_loc(pe), data_loc, 1, to_pe )
00067 if( current_clock.NE.0 )call increment_current_clock( EVENT_SEND, put_len*MPP_TYPE_BYTELEN_ )
00068 #elif use_libMPI
00069 !use non-blocking sends
00070 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00071 if( mpp_request(to_pe).NE.MPI_REQUEST_NULL )then !only one message from pe->to_pe in queue
00072 ! if( debug )write( stderr(),* )'PE waiting ', pe, to_pe
00073 call MPI_WAIT( mpp_request(to_pe), stat, error )
00074 end if
00075 call MPI_ISEND( put_data, put_len, MPI_TYPE_, to_pe, tag, peset(0)%id, mpp_request(to_pe), error )
00076 if( current_clock.NE.0 )call increment_current_clock( EVENT_SEND, put_len*MPP_TYPE_BYTELEN_ )
00077 #else !neither SHMEM nor MPI
00078 if( allocated(local_data) ) &
00079 call mpp_error( FATAL, 'MPP_TRANSMIT: local_data should have been deallocated by prior receive.' )
00080 allocate( local_data(put_len) )
00081 do i = 1,put_len
00082 local_data(i) = put_data(i)
00083 end do
00084 #endif
00085
00086 else if( to_pe.EQ.ALL_PES )then !this is a broadcast from from_pe
00087 if( from_pe.LT.0 .OR. from_pe.GE.npes )call mpp_error( FATAL, 'MPP_TRANSMIT: broadcasting from invalid PE.' )
00088 if( put_len.GT.get_len )call mpp_error( FATAL, 'MPP_TRANSMIT: size mismatch between put_data and get_data.' )
00089 if( pe.EQ.from_pe )then
00090 #ifdef use_CRI_pointers
00091 if( LOC(get_data).NE.LOC(put_data) )then
00092 !dir$ IVDEP
00093 #endif
00094 do i = 1,get_len
00095 get_data(i) = put_data(i)
00096 end do
00097 #ifdef use_CRI_pointers
00098 end if
00099 #endif
00100 end if
00101 call mpp_broadcast( get_data, get_len, from_pe )
00102 return
00103
00104 else if( to_pe.EQ.ANY_PE )then !we don't have a destination to do puts to, so only do gets
00105 #ifdef use_libSMA
00106 if( from_pe.LT.0 .OR. from_pe.GE.npes )call mpp_error( FATAL, 'MPP_TRANSMIT: invalid from_pe along with to_pe=ANY_PE.' )
00107 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00108 call SHMEM_GET_( get_data, put_data, get_len, from_pe )
00109 call SHMEM_PUT8( status(pe), MPP_READY, 1, from_pe ) !tell from_pe that you have retrieved this message
00110 if( current_clock.NE.0 )call increment_current_clock( EVENT_RECV, get_len*MPP_TYPE_BYTELEN_ )
00111 return
00112 #endif
00113 #ifdef use_libMPI
00114 !...but you cannot have a pure get with MPI
00115 call mpp_error( FATAL, 'MPP_TRANSMIT: you cannot transmit to ANY_PE using MPI.' )
00116 #endif
00117
00118 else if( to_pe.NE.NULL_PE )then !no other valid cases except NULL_PE
00119 call mpp_error( FATAL, 'MPP_TRANSMIT: invalid to_pe.' )
00120 end if
00121
00122 !do the get: for libSMA, a get means do a wait to ensure put on remote PE is complete
00123 if( from_pe.GE.0 .AND. from_pe.LT.npes )then
00124 #ifdef use_libSMA
00125 #ifdef _CRAYT90
00126 call SHMEM_UDCFLUSH !invalidate data cache
00127 #endif
00128 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00129 if( debug )write( stderr(),* )'pe, from_pe, remote_data_loc(from_pe)=', pe, from_pe, remote_data_loc(from_pe)
00130 call SHMEM_INT8_WAIT( remote_data_loc(from_pe), MPP_WAIT )
00131 if( current_clock.NE.0 )call increment_current_clock(EVENT_WAIT)
00132 ptr_remote_data = remote_data_loc(from_pe)
00133 remote_data_loc(from_pe) = MPP_WAIT !reset
00134 ! call SHMEM_PUT8( status(pe), MPP_READY, 1, from_pe ) !tell from_pe we have retrieved the location
00135 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00136 #if defined(CRAYPVP) || defined(sgi_mipspro)
00137 !since we have the pointer to remote data, just retrieve it with a simple copy
00138 if( LOC(get_data).NE.LOC(remote_data) )then
00139 !dir$ IVDEP
00140 do i = 1,get_len
00141 get_data(i) = remote_data(i)
00142 end do
00143 else
00144 call mpp_error(FATAL)
00145 end if
00146 #else
00147 call SHMEM_GET_( get_data, remote_data, get_len, from_pe )
00148 #endif
00149 call SHMEM_PUT8( status(pe), MPP_READY, 1, from_pe ) !tell from_pe we have retrieved the location
00150 if( current_clock.NE.0 )call increment_current_clock( EVENT_RECV, get_len*MPP_TYPE_BYTELEN_ )
00151 #elif use_libMPI
00152 !receive from from_pe
00153 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00154 call MPI_RECV( get_data, get_len, MPI_TYPE_, from_pe, MPI_ANY_TAG, peset(0)%id, stat, error )
00155 if( current_clock.NE.0 )call increment_current_clock( EVENT_RECV, get_len*MPP_TYPE_BYTELEN_ )
00156 #else !neither SHMEM nor MPI
00157 if( .NOT.allocated(local_data) ) &
00158 call mpp_error( FATAL, 'MPP_TRANSMIT: local_data should have been allocated by prior send.' )
00159 do i = 1,get_len
00160 get_data(i) = local_data(i)
00161 end do
00162 deallocate(local_data)
00163 !#else !neither use_libSMA nor use_libMPI
00164 ! if( pe.EQ.from_pe )then
00165 !#ifdef use_CRI_pointers
00166 !!dir$ IVDEP
00167 ! if( LOC(get_data).NE.LOC(put_data) ) &
00168 !#endif
00169 ! get_data(1:put_len) = put_data(1:put_len)
00170 ! end if
00171 #endif
00172
00173 else if( from_pe.EQ.ANY_PE )then
00174 #ifdef use_libSMA
00175 #ifdef _CRAYT90
00176 call SHMEM_UDCFLUSH !invalidate data cache
00177 #endif
00178 !since we don't know which PE is sending us data, we wait for remote PE to send us its ID
00179 !this is only required for !CRAYPVP && !sgi_mipspro, but is done there too, so that we can send put_is_done back.
00180 call shmem_integer_wait( mpp_from_pe, ANY_PE )
00181 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00182 call SHMEM_INT8_WAIT( remote_data_loc(mpp_from_pe), MPP_WAIT )
00183 if( current_clock.NE.0 )call increment_current_clock(EVENT_WAIT)
00184 ptr_remote_data = remote_data_loc(mpp_from_pe)
00185 remote_data_loc(mpp_from_pe) = MPP_WAIT !reset
00186 call SHMEM_PUT8( status(pe), MPP_READY, 1, mpp_from_pe ) !tell mpp_from_pe we have retrieved the location
00187 #if defined(CRAYPVP) || defined(sgi_mipspro)
00188 !since we have the pointer to remote data, just retrieve it with a simple copy
00189 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00190 if( LOC(get_data).NE.LOC(remote_data) )then
00191 !dir$ IVDEP
00192 do i = 1,get_len
00193 get_data(i) = remote_data(i)
00194 end do
00195 end if
00196 #else
00197 call SHMEM_GET_( get_data, remote_data, get_len, mpp_from_pe )
00198 #endif
00199 if( current_clock.NE.0 )call increment_current_clock( EVENT_RECV, get_len*MPP_TYPE_BYTELEN_ )
00200 mpp_from_pe = ANY_PE !reset
00201 #endif use_libSMA
00202 #ifdef use_libMPI
00203 !receive from MPI_ANY_SOURCE
00204 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00205 call MPI_RECV( get_data, get_len, MPI_TYPE_, MPI_ANY_SOURCE, MPI_ANY_TAG, peset(0)%id, stat, error )
00206 if( current_clock.NE.0 )call increment_current_clock( EVENT_RECV, get_len*MPP_TYPE_BYTELEN_ )
00207 #endif
00208
00209 else if( from_pe.EQ.ALL_PES )then
00210 call mpp_error( FATAL, 'MPP_TRANSMIT: from_pe=ALL_PES has ambiguous meaning, and hence is not implemented.' )
00211
00212 else if( from_pe.NE.NULL_PE )then !only remaining valid choice is NULL_PE
00213 call mpp_error( FATAL, 'MPP_TRANSMIT: invalid from_pe.' )
00214 end if
00215
00216 if( debug )then
00217 call SYSTEM_CLOCK(tick)
00218 write( stdout(),'(a,i18,a,i5,a,2i5,2i8)' )&
00219 'T=',tick, ' PE=',pe, ' MPP_TRANSMIT end: to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len
00220 end if
00221 return
00222 end subroutine MPP_TRANSMIT_
00223
00224 subroutine MPP_TRANSMIT_SCALAR_( put_data, to_pe, get_data, from_pe )
00225 integer, intent(in) :: to_pe, from_pe
00226 MPP_TYPE_, intent(in) :: put_data
00227 MPP_TYPE_, intent(out) :: get_data
00228 MPP_TYPE_ :: put_data1D(1), get_data1D(1)
00229 #ifdef use_CRI_pointers
00230 pointer( ptrp, put_data1D )
00231 pointer( ptrg, get_data1D )
00232
00233 ptrp = LOC(put_data)
00234 ptrg = LOC(get_data)
00235 call MPP_TRANSMIT_ ( put_data1D, 1, to_pe, get_data1D, 1, from_pe )
00236 #else
00237 put_data1D(1) = put_data
00238 call MPP_TRANSMIT_ ( put_data1D, 1, to_pe, get_data1D, 1, from_pe )
00239 get_data = get_data1D(1)
00240 #endif
00241 return
00242 end subroutine MPP_TRANSMIT_SCALAR_
00243
00244 subroutine MPP_TRANSMIT_2D_( put_data, put_len, to_pe, get_data, get_len, from_pe )
00245 integer, intent(in) :: put_len, to_pe, get_len, from_pe
00246 MPP_TYPE_, intent(in) :: put_data(:,:)
00247 MPP_TYPE_, intent(out) :: get_data(:,:)
00248 MPP_TYPE_ :: put_data1D(put_len), get_data1D(get_len)
00249 #ifdef use_CRI_pointers
00250 pointer( ptrp, put_data1D )
00251 pointer( ptrg, get_data1D )
00252 ptrp = LOC(put_data)
00253 ptrg = LOC(get_data)
00254 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00255 #else
00256 !faster than RESHAPE? length is probably redundant
00257 if( to_pe.NE.NULL_PE )put_data1D = TRANSFER( put_data, put_data1D, get_len )
00258 ! if( to_pe.NE.NULL_PE )put_data1D = RESHAPE( put_data, SHAPE(put_data1D) )
00259 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00260 if( from_pe.NE.NULL_PE )get_data = RESHAPE( get_data1D, SHAPE(get_data) )
00261 #endif
00262 return
00263 end subroutine MPP_TRANSMIT_2D_
00264
00265 subroutine MPP_TRANSMIT_3D_( put_data, put_len, to_pe, get_data, get_len, from_pe )
00266 integer, intent(in) :: put_len, to_pe, get_len, from_pe
00267 MPP_TYPE_, intent(in) :: put_data(:,:,:)
00268 MPP_TYPE_, intent(out) :: get_data(:,:,:)
00269 MPP_TYPE_ :: put_data1D(put_len), get_data1D(get_len)
00270 #ifdef use_CRI_pointers
00271 pointer( ptrp, put_data1D )
00272 pointer( ptrg, get_data1D )
00273 ptrp = LOC(put_data)
00274 ptrg = LOC(get_data)
00275 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00276 #else
00277 !faster than RESHAPE? length is probably redundant
00278 if( to_pe.NE.NULL_PE )put_data1D = TRANSFER( put_data, put_data1D, get_len )
00279 ! if( to_pe.NE.NULL_PE )put_data1D = RESHAPE( put_data, SHAPE(put_data1D) )
00280 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00281 if( from_pe.NE.NULL_PE )get_data = RESHAPE( get_data1D, SHAPE(get_data) )
00282 #endif
00283 return
00284 end subroutine MPP_TRANSMIT_3D_
00285
00286 subroutine MPP_TRANSMIT_4D_( put_data, put_len, to_pe, get_data, get_len, from_pe )
00287 integer, intent(in) :: put_len, to_pe, get_len, from_pe
00288 MPP_TYPE_, intent(in) :: put_data(:,:,:,:)
00289 MPP_TYPE_, intent(out) :: get_data(:,:,:,:)
00290 MPP_TYPE_ :: put_data1D(put_len), get_data1D(get_len)
00291 #ifdef use_CRI_pointers
00292 pointer( ptrp, put_data1D )
00293 pointer( ptrg, get_data1D )
00294 ptrp = LOC(put_data)
00295 ptrg = LOC(get_data)
00296 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00297 #else
00298 !faster than RESHAPE? length is probably redundant
00299 if( to_pe.NE.NULL_PE )put_data1D = TRANSFER( put_data, put_data1D, get_len )
00300 ! if( to_pe.NE.NULL_PE )put_data1D = RESHAPE( put_data, SHAPE(put_data1D) )
00301 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00302 if( from_pe.NE.NULL_PE )get_data = RESHAPE( get_data1D, SHAPE(get_data) )
00303 #endif
00304 return
00305 end subroutine MPP_TRANSMIT_4D_
00306
00307 subroutine MPP_TRANSMIT_5D_( put_data, put_len, to_pe, get_data, get_len, from_pe )
00308 integer, intent(in) :: put_len, to_pe, get_len, from_pe
00309 MPP_TYPE_, intent(in) :: put_data(:,:,:,:,:)
00310 MPP_TYPE_, intent(out) :: get_data(:,:,:,:,:)
00311 MPP_TYPE_ :: put_data1D(put_len), get_data1D(get_len)
00312 #ifdef use_CRI_pointers
00313 pointer( ptrp, put_data1D )
00314 pointer( ptrg, get_data1D )
00315 ptrp = LOC(put_data)
00316 ptrg = LOC(get_data)
00317 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00318 #else
00319 !faster than RESHAPE? length is probably redundant
00320 if( to_pe.NE.NULL_PE )put_data1D = TRANSFER( put_data, put_data1D, get_len )
00321 ! if( to_pe.NE.NULL_PE )put_data1D = RESHAPE( put_data, SHAPE(put_data1D) )
00322 call mpp_transmit( put_data1D, put_len, to_pe, get_data1D, get_len, from_pe )
00323 if( from_pe.NE.NULL_PE )get_data = RESHAPE( get_data1D, SHAPE(get_data) )
00324 #endif
00325 return
00326 end subroutine MPP_TRANSMIT_5D_
00327 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00328 ! !
00329 ! MPP_SEND and RECV !
00330 ! !
00331 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00332
00333 subroutine MPP_RECV_( get_data, get_len, from_pe )
00334 !a mpp_transmit with null arguments on the put side
00335 integer, intent(in) :: get_len, from_pe
00336 MPP_TYPE_, intent(out) :: get_data(*)
00337 MPP_TYPE_ :: dummy(1)
00338 call mpp_transmit( dummy, 1, NULL_PE, get_data, get_len, from_pe )
00339 end subroutine MPP_RECV_
00340
00341 subroutine MPP_SEND_( put_data, put_len, to_pe )
00342 !a mpp_transmit with null arguments on the get side
00343 integer, intent(in) :: put_len, to_pe
00344 MPP_TYPE_, intent(in) :: put_data(*)
00345 MPP_TYPE_ :: dummy(1)
00346 call mpp_transmit( put_data, put_len, to_pe, dummy, 1, NULL_PE )
00347 end subroutine MPP_SEND_
00348
00349 subroutine MPP_RECV_SCALAR_( get_data, from_pe )
00350 !a mpp_transmit with null arguments on the put side
00351 integer, intent(in) :: from_pe
00352 MPP_TYPE_, intent(out) :: get_data
00353 MPP_TYPE_ :: get_data1D(1)
00354 MPP_TYPE_ :: dummy(1)
00355 #ifdef use_CRI_pointers
00356 pointer( ptr, get_data1D )
00357 ptr = LOC(get_data)
00358 call mpp_transmit( dummy, 1, NULL_PE, get_data1D, 1, from_pe )
00359 #else
00360 call mpp_transmit( dummy, 1, NULL_PE, get_data1D, 1, from_pe )
00361 get_data = get_data1D(1)
00362 #endif
00363 end subroutine MPP_RECV_SCALAR_
00364
00365 subroutine MPP_SEND_SCALAR_( put_data, to_pe )
00366 !a mpp_transmit with null arguments on the get side
00367 integer, intent(in) :: to_pe
00368 MPP_TYPE_, intent(in) :: put_data
00369 MPP_TYPE_ :: put_data1D(1)
00370 MPP_TYPE_ :: dummy(1)
00371 #ifdef use_CRI_pointers
00372 pointer( ptr, put_data1D )
00373 ptr = LOC(put_data)
00374 call mpp_transmit( put_data1D, 1, to_pe, dummy, 1, NULL_PE )
00375 #else
00376 put_data1D(1) = put_data
00377 call mpp_transmit( put_data1D, 1, to_pe, dummy, 1, NULL_PE )
00378 #endif
00379 end subroutine MPP_SEND_SCALAR_
00380
00381 subroutine MPP_RECV_2D_( get_data, get_len, from_pe )
00382 !a mpp_transmit with null arguments on the put side
00383 integer, intent(in) :: get_len, from_pe
00384 MPP_TYPE_, intent(out) :: get_data(:,:)
00385 MPP_TYPE_ :: dummy(1,1)
00386 call mpp_transmit( dummy, 1, NULL_PE, get_data, get_len, from_pe )
00387 end subroutine MPP_RECV_2D_
00388
00389 subroutine MPP_SEND_2D_( put_data, put_len, to_pe )
00390 !a mpp_transmit with null arguments on the get side
00391 integer, intent(in) :: put_len, to_pe
00392 MPP_TYPE_, intent(in) :: put_data(:,:)
00393 MPP_TYPE_ :: dummy(1,1)
00394 call mpp_transmit( put_data, put_len, to_pe, dummy, 1, NULL_PE )
00395 end subroutine MPP_SEND_2D_
00396
00397 subroutine MPP_RECV_3D_( get_data, get_len, from_pe )
00398 !a mpp_transmit with null arguments on the put side
00399 integer, intent(in) :: get_len, from_pe
00400 MPP_TYPE_, intent(out) :: get_data(:,:,:)
00401 MPP_TYPE_ :: dummy(1,1,1)
00402 call mpp_transmit( dummy, 1, NULL_PE, get_data, get_len, from_pe )
00403 end subroutine MPP_RECV_3D_
00404
00405 subroutine MPP_SEND_3D_( put_data, put_len, to_pe )
00406 !a mpp_transmit with null arguments on the get side
00407 integer, intent(in) :: put_len, to_pe
00408 MPP_TYPE_, intent(in) :: put_data(:,:,:)
00409 MPP_TYPE_ :: dummy(1,1,1)
00410 call mpp_transmit( put_data, put_len, to_pe, dummy, 1, NULL_PE )
00411 end subroutine MPP_SEND_3D_
00412
00413 subroutine MPP_RECV_4D_( get_data, get_len, from_pe )
00414 !a mpp_transmit with null arguments on the put side
00415 integer, intent(in) :: get_len, from_pe
00416 MPP_TYPE_, intent(out) :: get_data(:,:,:,:)
00417 MPP_TYPE_ :: dummy(1,1,1,1)
00418 call mpp_transmit( dummy, 1, NULL_PE, get_data, get_len, from_pe )
00419 end subroutine MPP_RECV_4D_
00420
00421 subroutine MPP_SEND_4D_( put_data, put_len, to_pe )
00422 !a mpp_transmit with null arguments on the get side
00423 integer, intent(in) :: put_len, to_pe
00424 MPP_TYPE_, intent(in) :: put_data(:,:,:,:)
00425 MPP_TYPE_ :: dummy(1,1,1,1)
00426 call mpp_transmit( put_data, put_len, to_pe, dummy, 1, NULL_PE )
00427 end subroutine MPP_SEND_4D_
00428
00429 subroutine MPP_RECV_5D_( get_data, get_len, from_pe )
00430 !a mpp_transmit with null arguments on the put side
00431 integer, intent(in) :: get_len, from_pe
00432 MPP_TYPE_, intent(out) :: get_data(:,:,:,:,:)
00433 MPP_TYPE_ :: dummy(1,1,1,1,1)
00434 call mpp_transmit( dummy, 1, NULL_PE, get_data, get_len, from_pe )
00435 end subroutine MPP_RECV_5D_
00436
00437 subroutine MPP_SEND_5D_( put_data, put_len, to_pe )
00438 !a mpp_transmit with null arguments on the get side
00439 integer, intent(in) :: put_len, to_pe
00440 MPP_TYPE_, intent(in) :: put_data(:,:,:,:,:)
00441 MPP_TYPE_ :: dummy(1,1,1,1,1)
00442 call mpp_transmit( put_data, put_len, to_pe, dummy, 1, NULL_PE )
00443 end subroutine MPP_SEND_5D_
00444
00445 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00446 ! !
00447 ! MPP_BROADCAST !
00448 ! !
00449 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00450
00451 subroutine MPP_BROADCAST_( data, length, from_pe, pelist )
00452 !this call was originally bundled in with mpp_transmit, but that doesn't allow
00453 !broadcast to a subset of PEs. This version will, and mpp_transmit will remain
00454 !backward compatible.
00455 MPP_TYPE_, intent(inout) :: data(*)
00456 integer, intent(in) :: length, from_pe
00457 integer, intent(in), optional :: pelist(:)
00458 integer :: n
00459 #ifdef use_libSMA
00460 integer :: np, i
00461 integer(LONG_KIND) :: data_loc
00462 !pointer to remote data
00463 MPP_TYPE_ :: bdata(length)
00464 pointer( ptr, bdata )
00465 integer :: words
00466 character(len=8) :: text
00467 #endif
00468
00469 if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_BROADCAST: You must first call mpp_init.' )
00470 n = get_peset(pelist); if( peset(n)%count.EQ.1 )return
00471
00472 if( debug )then
00473 call SYSTEM_CLOCK(tick)
00474 write( stdout(),'(a,i18,a,i5,a,2i5,2i8)' )&
00475 'T=',tick, ' PE=',pe, ' MPP_BROADCAST begin: from_pe, length=', from_pe, length
00476 end if
00477
00478 if( .NOT.ANY(from_pe.EQ.peset(current_peset_num)%list) ) &
00479 call mpp_error( FATAL, 'MPP_BROADCAST: broadcasting from invalid PE.' )
00480
00481 if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
00482 #ifdef use_libSMA
00483 ptr = LOC(mpp_stack)
00484 words = size(bdata)*size(transfer(bdata(1),word))
00485 if( words.GT.mpp_stack_size )then
00486 write( text, '(i8)' )words
00487 call mpp_error( FATAL, 'MPP_BROADCAST user stack overflow: call mpp_set_stack_size('//text//') from all PEs.' )
00488 end if
00489 mpp_stack_hwm = max( words, mpp_stack_hwm )
00490 if( mpp_npes().GT.1 )then
00491 !dir$ IVDEP
00492 do i = 1,length
00493 bdata(i) = data(i)
00494 end do
00495 call mpp_sync(pelist) !eliminate?
00496 #ifdef _CRAYT90
00497 call SHMEM_UDCFLUSH !invalidate data cache
00498 #endif
00499 call SHMEM_BROADCAST_( bdata, bdata, length, from_pe, peset(n)%start, peset(n)%log2stride, peset(n)%count, sync )
00500 call mpp_sync(pelist) !eliminate?
00501 !dir$ IVDEP
00502 do i = 1,length
00503 data(i) = bdata(i)
00504 end do
00505 end if
00506 #endif
00507 #ifdef use_libMPI
00508 if( mpp_npes().GT.1 )call MPI_BCAST( data, length, MPI_TYPE_, from_pe, peset(n)%id, error )
00509 #endif
00510 if( current_clock.NE.0 )call increment_current_clock( EVENT_BROADCAST, length*MPP_TYPE_BYTELEN_ )
00511 return
00512 end subroutine MPP_BROADCAST_
00513
00514 subroutine MPP_BROADCAST_SCALAR_( data, from_pe, pelist )
00515 MPP_TYPE_, intent(inout) :: data
00516 integer, intent(in) :: from_pe
00517 integer, intent(in), optional :: pelist(:)
00518 MPP_TYPE_ :: data1D(1)
00519 #ifdef use_CRI_pointers
00520 pointer( ptr, data1D )
00521
00522 ptr = LOC(data)
00523 call MPP_BROADCAST_( data1D, 1, from_pe, pelist )
00524 #else
00525 data1D(1) = data
00526 call MPP_BROADCAST_( data1D, 1, from_pe, pelist )
00527 data = data1D(1)
00528 #endif
00529 return
00530 end subroutine MPP_BROADCAST_SCALAR_
00531
00532 subroutine MPP_BROADCAST_2D_( data, length, from_pe, pelist )
00533 !this call was originally bundled in with mpp_transmit, but that doesn't allow
00534 !broadcast to a subset of PEs. This version will, and mpp_transmit will remain
00535 !backward compatible.
00536 MPP_TYPE_, intent(inout) :: data(:,:)
00537 integer, intent(in) :: length, from_pe
00538 integer, intent(in), optional :: pelist(:)
00539 MPP_TYPE_ :: data1D(length)
00540 #ifdef use_CRI_pointers
00541 pointer( ptr, data1D )
00542 ptr = LOC(data)
00543 call mpp_broadcast( data1D, length, from_pe, pelist )
00544 #else
00545 !faster than RESHAPE? length is probably redundant
00546 data1D = TRANSFER( data, data1D, length )
00547 ! data1D = RESHAPE( data, SHAPE(data1D) )
00548 call mpp_broadcast( data1D, length, from_pe, pelist )
00549 data = RESHAPE( data1D, SHAPE(data) )
00550 #endif
00551 return
00552 end subroutine MPP_BROADCAST_2D_
00553
00554 subroutine MPP_BROADCAST_3D_( data, length, from_pe, pelist )
00555 !this call was originally bundled in with mpp_transmit, but that doesn't allow
00556 !broadcast to a subset of PEs. This version will, and mpp_transmit will remain
00557 !backward compatible.
00558 MPP_TYPE_, intent(inout) :: data(:,:,:)
00559 integer, intent(in) :: length, from_pe
00560 integer, intent(in), optional :: pelist(:)
00561 MPP_TYPE_ :: data1D(length)
00562 #ifdef use_CRI_pointers
00563 pointer( ptr, data1D )
00564 ptr = LOC(data)
00565 call mpp_broadcast( data1D, length, from_pe, pelist )
00566 #else
00567 !faster than RESHAPE? length is probably redundant
00568 data1D = TRANSFER( data, data1D, length )
00569 ! data1D = RESHAPE( data, SHAPE(data1D) )
00570 call mpp_broadcast( data1D, length, from_pe, pelist )
00571 data = RESHAPE( data1D, SHAPE(data) )
00572 #endif
00573 return
00574 end subroutine MPP_BROADCAST_3D_
00575
00576 subroutine MPP_BROADCAST_4D_( data, length, from_pe, pelist )
00577 !this call was originally bundled in with mpp_transmit, but that doesn't allow
00578 !broadcast to a subset of PEs. This version will, and mpp_transmit will remain
00579 !backward compatible.
00580 MPP_TYPE_, intent(inout) :: data(:,:,:,:)
00581 integer, intent(in) :: length, from_pe
00582 integer, intent(in), optional :: pelist(:)
00583 MPP_TYPE_ :: data1D(length)
00584 #ifdef use_CRI_pointers
00585 pointer( ptr, data1D )
00586 ptr = LOC(data)
00587 call mpp_broadcast( data1D, length, from_pe, pelist )
00588 #else
00589 !faster than RESHAPE? length is probably redundant
00590 data1D = TRANSFER( data, data1D, length )
00591 ! data1D = RESHAPE( data, SHAPE(data1D) )
00592 call mpp_broadcast( data1D, length, from_pe, pelist )
00593 data = RESHAPE( data1D, SHAPE(data) )
00594 #endif
00595 return
00596 end subroutine MPP_BROADCAST_4D_
00597
00598 subroutine MPP_BROADCAST_5D_( data, length, from_pe, pelist )
00599 !this call was originally bundled in with mpp_transmit, but that doesn't allow
00600 !broadcast to a subset of PEs. This version will, and mpp_transmit will remain
00601 !backward compatible.
00602 MPP_TYPE_, intent(inout) :: data(:,:,:,:,:)
00603 integer, intent(in) :: length, from_pe
00604 integer, intent(in), optional :: pelist(:)
00605 MPP_TYPE_ :: data1D(length)
00606 #ifdef use_CRI_pointers
00607 pointer( ptr, data1D )
00608 ptr = LOC(data)
00609 call mpp_broadcast( data1D, length, from_pe, pelist )
00610 #else
00611 !faster than RESHAPE? length is probably redundant
00612 data1D = TRANSFER( data, data1D, length )
00613 ! data1D = RESHAPE( data, SHAPE(data1D) )
00614 call mpp_broadcast( data1D, length, from_pe, pelist )
00615 data = RESHAPE( data1D, SHAPE(data) )
00616 #endif
00617 return
00618 end subroutine MPP_BROADCAST_5D_