34 #include <fms_platform.h>
45 logical :: verbose=.false.
46 logical :: module_is_initialized=.false.
47 character(len=256) :: text
50 module procedure mpp_pset_broadcast_ptr_scalar
51 module procedure mpp_pset_broadcast_ptr_array
54 module procedure mpp_send_ptr_scalar
55 module procedure mpp_send_ptr_array
58 module procedure mpp_recv_ptr_scalar
59 module procedure mpp_recv_ptr_array
62 module procedure mpp_pset_print_chksum_1d
63 module procedure mpp_pset_print_chksum_2d
64 module procedure mpp_pset_print_chksum_3d
65 module procedure mpp_pset_print_chksum_4d
71 integer :: next_in_pset, prev_in_pset
72 integer :: root_in_pset
77 real,
allocatable :: stack(:)
78 integer,
allocatable :: pelist(:)
79 integer,
allocatable :: root_pelist(:)
80 integer,
allocatable :: pset(:)
81 integer(POINTER_KIND) :: p_stack
82 integer :: lstack, maxstack, hiWM
84 character(len=32) :: name
85 logical :: initialized=.false.
91 public :: mpp_pset_create, mpp_pset_sync, mpp_pset_broadcast, &
94 mpp_pset_delete, mpp_pset_root, mpp_pset_numroots, mpp_pset_init, &
95 mpp_pset_get_root_pelist, mpp_pset_print_stack_chksum
99 subroutine mpp_pset_init
100 module_is_initialized = .true.
101 end subroutine mpp_pset_init
103 subroutine mpp_pset_create(npset,pset,stacksize,pelist, commID)
107 integer,
intent(in) :: npset
108 type(mpp_pset_type),
intent(inout) :: pset
109 integer,
intent(in),
optional :: stacksize
110 integer,
intent(in),
optional :: pelist(:)
111 integer,
intent(in),
optional :: commID
113 integer :: npes, my_commID
114 integer :: i, j, k, out_unit, errunit
115 integer,
allocatable :: my_pelist(:), root_pelist(:)
126 if(
present(pelist))
then
127 npes =
size(pelist(:))
131 if( mod(npes,npset).NE.0 )
then
132 write( text,
'(a,2i6)' ) &
133 'MPP_PSET_CREATE: PSET size (npset) must divide npes exactly:'// &
134 ' npset, npes=', npset, npes
139 allocate(my_pelist(0:npes-1) )
140 allocate(root_pelist(0:npes/npset-1) )
141 if(
present(pelist))
then
142 if(.not.
present(commid))
call mpp_error(fatal, &
143 'MPP_PSET_CREATE: when pelist is present, commID should also be present')
147 call mpp_get_current_pelist(my_pelist, commid = my_commid)
149 do i = 0,npes/npset-1
150 root_pelist(i) = my_pelist(npset*i)
152 write( out_unit,
'(a,i6)' )
'MPP_PSET_CREATE creating PSETs... npset=', npset
153 if(any(my_pelist == pe) )
then
154 if( pset%initialized )
call mpp_error( fatal, &
155 'MPP_PSET_CREATE: PSET already initialized!' )
157 allocate( pset%pelist(0:npes-1) )
158 allocate( pset%root_pelist(0:npes/npset-1) )
159 pset%commID = my_commid
160 pset%pelist = my_pelist
162 pset%root_pelist = root_pelist
163 allocate( pset%pset(0:npset-1) )
164 do i = 0,npes/npset-1
168 if( pe.EQ.pset%pelist(k+j) )
then
169 pset%pset(:) = pset%pelist(k:k+npset-1)
171 pset%root_in_pset = pset%root_pelist(i)
173 pset%prev_in_pset = pset%pelist(k+npset-1)
175 pset%prev_in_pset = pset%pelist(k+j-1)
177 if( j.EQ.npset-1 )
then
178 pset%next_in_pset = pset%pelist(k)
180 pset%next_in_pset = pset%pelist(k+j+1)
186 pset%root = pe.EQ.pset%root_in_pset
190 pset%maxstack = 1000000
191 if(
PRESENT(stacksize) )pset%maxstack = stacksize
192 write( out_unit,
'(a,i8)' ) &
193 'MPP_PSET_CREATE: setting stacksize=', pset%maxstack
195 allocate( pset%stack(pset%maxstack) )
196 #ifdef use_CRI_pointers
197 pset%p_stack = loc(pset%stack)
200 pset%initialized = .true.
207 write( errunit,
'(a,4i6)' )
'MPP_PSET_CREATE: pe, root, next, prev=', &
208 pe, pset%root_in_pset, pset%next_in_pset, pset%prev_in_pset
209 write( errunit,* )
'PE ', pe,
' pset=', pset%pset(:)
210 write( out_unit,* )
'root pelist=', pset%root_pelist(:)
212 end subroutine mpp_pset_create
214 subroutine mpp_pset_delete(pset)
215 type(mpp_pset_type),
intent(inout) :: pset
219 if( .NOT.pset%initialized )
call mpp_error( fatal, &
220 'MPP_PSET_DELETE: called with uninitialized PSET.' )
222 deallocate( pset%pelist )
223 deallocate( pset%root_pelist )
224 deallocate( pset%pset )
225 if( pset%root )
deallocate( pset%stack )
226 write( out_unit,
'(a,i10)' ) &
227 'Deleting PSETs... stack high-water-mark=', pset%hiWM
229 pset%initialized = .false.
230 end subroutine mpp_pset_delete
232 subroutine mpp_send_ptr_scalar( ptr, pe )
233 integer(POINTER_KIND),
intent(in) :: ptr
234 integer,
intent(in) :: pe
238 call mpp_send( ptr, pe, tag=comm_tag_1 )
239 end subroutine mpp_send_ptr_scalar
241 subroutine mpp_send_ptr_array( ptr, pe )
242 integer(POINTER_KIND),
intent(in) :: ptr(:)
243 integer,
intent(in) :: pe
247 call mpp_send( ptr,
size(ptr), pe, tag=comm_tag_2 )
248 end subroutine mpp_send_ptr_array
250 subroutine mpp_recv_ptr_scalar( ptr, pe )
251 integer(POINTER_KIND),
intent(inout) :: ptr
252 integer,
intent(in) :: pe
254 call mpp_recv( ptr, pe, tag=comm_tag_1 )
255 call mpp_translate_remote_ptr( ptr, pe )
257 end subroutine mpp_recv_ptr_scalar
259 subroutine mpp_recv_ptr_array( ptr, pe )
260 integer(POINTER_KIND),
intent(inout) :: ptr(:)
261 integer,
intent(in) :: pe
264 call mpp_recv( ptr,
size(ptr), pe, tag=comm_tag_2 )
266 call mpp_translate_remote_ptr( ptr(i), pe )
269 end subroutine mpp_recv_ptr_array
271 subroutine mpp_translate_remote_ptr( ptr, pe )
273 integer(POINTER_KIND),
intent(inout) :: ptr
274 integer,
intent(in) :: pe
276 end subroutine mpp_translate_remote_ptr
278 subroutine mpp_pset_sync(pset)
281 type(mpp_pset_type),
intent(in) :: pset
283 if( .NOT.pset%initialized )
call mpp_error( fatal, &
284 'MPP_PSET_SYNC: called with uninitialized PSET.' )
288 end subroutine mpp_pset_sync
290 subroutine mpp_pset_broadcast(pset,a)
292 type(mpp_pset_type),
intent(in) :: pset
293 real,
intent(inout) :: a
296 if( .NOT.pset%initialized )
call mpp_error( fatal, &
297 'MPP_PSET_BROADCAST: called with uninitialized PSET.' )
299 do i = 1,pset%npset-1
300 call mpp_send( a, pset%pset(i), tag=comm_tag_3 )
303 call mpp_recv( a, pset%root_in_pset, tag=comm_tag_3 )
305 call mpp_pset_sync(pset)
306 end subroutine mpp_pset_broadcast
308 subroutine mpp_pset_broadcast_ptr_scalar(pset,ptr)
312 type(mpp_pset_type),
intent(in) :: pset
313 integer(POINTER_KIND),
intent(inout) :: ptr
316 if( .NOT.pset%initialized )
call mpp_error( fatal, &
317 'MPP_PSET_BROADCAST_PTR: called with uninitialized PSET.' )
320 do i = 1,pset%npset-1
327 end subroutine mpp_pset_broadcast_ptr_scalar
329 subroutine mpp_pset_broadcast_ptr_array(pset,ptr)
333 type(mpp_pset_type),
intent(in) :: pset
334 integer(POINTER_KIND),
intent(inout) :: ptr(:)
337 if( .NOT.pset%initialized )
call mpp_error( fatal, &
338 'MPP_PSET_BROADCAST_PTR: called with uninitialized PSET.' )
341 do i = 1,pset%npset-1
349 end subroutine mpp_pset_broadcast_ptr_array
351 subroutine mpp_pset_check_ptr(pset,ptr)
353 type(mpp_pset_type),
intent(in) :: pset
354 #ifdef use_CRI_pointers
356 pointer( ptr, dummy )
358 integer(POINTER_KIND),
intent(in) :: ptr
361 integer(POINTER_KIND) :: p
363 if( .NOT.pset%initialized )
call mpp_error( fatal, &
364 'MPP_PSET_CHECK_PTR: called with uninitialized PSET.' )
369 do i = 1,pset%npset-1
375 call mpp_pset_sync(pset)
377 'MPP_PSET_CHECK_PTR: pointers do not match!' )
381 end subroutine mpp_pset_check_ptr
383 subroutine mpp_pset_segment_array( pset, ls, le, lsp, lep )
388 type(mpp_pset_type),
intent(in) :: pset
389 integer,
intent(in) :: ls, le
390 integer,
intent(out) :: lsp, lep
393 if( .NOT.pset%initialized )
call mpp_error( fatal, &
394 'MPP_PSET_SEGMENT_ARRAY: called with uninitialized PSET.' )
396 if( le-ls+1.LT.pset%npset )
then
397 write( text,
'(3(a,i6))' ) &
398 'MPP_PSET_ARRAY_SEGMENT: parallel range (', ls,
',', le, &
399 ') is smaller than the number of threads:', pset%npset
406 lep = lsp + ceiling( real(le-lsp+1)/(pset%npset-i) ) - 1
408 end subroutine mpp_pset_segment_array
410 subroutine mpp_pset_stack_push( pset, ptr, len )
415 type(mpp_pset_type),
intent(inout) :: pset
416 integer,
intent(in) :: len
417 #ifdef use_CRI_pointers
419 pointer( ptr, dummy )
420 real :: stack(pset%maxstack)
423 if( .NOT.pset%initialized )
call mpp_error( fatal, &
424 'MPP_PSET_STACK_PUSH: called with uninitialized PSET.' )
425 if( pset%lstack+len.GT.pset%maxstack )
then
426 write( text,
'(a,3i12)' ) &
427 'MPP_PSET_STACK_PUSH: mpp_pset_stack overflow: '// &
428 .GT.
'len+lstackmaxstack. len, lstack, maxstack=', &
429 len, pset%lstack, pset%maxstack
433 ptr = loc( stack(pset%lstack+1) )
434 call mpp_pset_check_ptr(pset,ptr)
435 pset%lstack = pset%lstack + len
436 pset%hiWM = max( pset%hiWM, pset%lstack )
438 integer(POINTER_KIND),
intent(out) :: ptr
440 'MPP_PSET_STACK_PUSH only works with Cray pointers.' )
442 end subroutine mpp_pset_stack_push
444 subroutine mpp_pset_stack_reset(pset)
445 type(mpp_pset_type),
intent(inout) :: pset
455 if( .NOT.pset%initialized )
call mpp_error( fatal, &
456 'MPP_PSET_STACK_RESET: called with uninitialized PSET.' )
458 end subroutine mpp_pset_stack_reset
460 subroutine mpp_pset_print_chksum_1d(pset, caller, array)
464 type(mpp_pset_type),
intent(in) :: pset
465 character(len=*),
intent(in) :: caller
466 real,
intent(in) :: array(:)
471 integer(LONG_KIND) :: chksum
473 if( .NOT.pset%initialized )
call mpp_error( fatal, &
474 'MPP_PSET_PRINT_CHKSUM: called with uninitialized PSET.' )
478 do_print = pe.EQ.mpp_root_pe()
482 write( errunit,
'(a,z18)' )trim(caller)//
' chksum=', chksum
487 end subroutine mpp_pset_print_chksum_1d
489 subroutine mpp_pset_print_chksum_2d(pset, caller, array)
490 type(mpp_pset_type),
intent(in) :: pset
491 character(len=*),
intent(in) :: caller
492 real,
intent(in) :: array(:,:)
493 real :: array1D( size(array) )
494 #ifdef use_CRI_pointers
495 pointer( p, array1d )
498 array1d = transfer( array, array1d )
501 end subroutine mpp_pset_print_chksum_2d
503 subroutine mpp_pset_print_chksum_3d(pset, caller, array)
504 type(mpp_pset_type),
intent(in) :: pset
505 character(len=*),
intent(in) :: caller
506 real,
intent(in) :: array(:,:,:)
507 real :: array1D( size(array) )
508 #ifdef use_CRI_pointers
509 pointer( p, array1d )
512 array1d = transfer( array, array1d )
515 end subroutine mpp_pset_print_chksum_3d
517 subroutine mpp_pset_print_chksum_4d(pset, caller, array)
518 type(mpp_pset_type),
intent(in) :: pset
519 character(len=*),
intent(in) :: caller
520 real,
intent(in) :: array(:,:,:,:)
521 real :: array1D( size(array) )
522 #ifdef use_CRI_pointers
523 pointer( p, array1d )
526 array1d = transfer( array, array1d )
529 end subroutine mpp_pset_print_chksum_4d
531 subroutine mpp_pset_print_stack_chksum( pset, caller )
532 type(mpp_pset_type),
intent(in) :: pset
533 character(len=*),
intent(in) :: caller
535 if( .NOT.pset%initialized )
call mpp_error( fatal, &
536 'MPP_PSET_PRINT_STACK_CHKSUM: called with uninitialized PSET.' )
538 pset%stack(1:pset%lstack) )
539 end subroutine mpp_pset_print_stack_chksum
542 function mpp_pset_root(pset)
543 logical :: mpp_pset_root
544 type(mpp_pset_type),
intent(in) :: pset
546 if( .NOT.pset%initialized )
call mpp_error( fatal, &
547 'MPP_PSET_ROOT: called with uninitialized PSET.' )
548 mpp_pset_root = pset%root
549 end function mpp_pset_root
551 function mpp_pset_numroots(pset)
553 integer :: mpp_pset_numroots
554 type(mpp_pset_type),
intent(in) :: pset
556 if( .NOT.pset%initialized )
call mpp_error( fatal, &
557 'MPP_PSET_NUMROOTS: called with uninitialized PSET.' )
558 mpp_pset_numroots =
size(pset%root_pelist)
559 end function mpp_pset_numroots
561 subroutine mpp_pset_get_root_pelist(pset,pelist,commID)
562 type(mpp_pset_type),
intent(in) :: pset
563 integer,
intent(out) :: pelist(:)
564 integer,
intent(out),
optional :: commID
566 if( .NOT.pset%initialized )
call mpp_error( fatal, &
567 'MPP_PSET_GET_ROOT_PELIST: called with uninitialized PSET.' )
568 if(
size(pelist).NE.
size(pset%root_pelist) )
then
569 write( text,
'(a,2i6)' ) &
570 'pelist argument has wrong size: requested, actual=', &
571 size(pelist),
size(pset%root_pelist)
572 call mpp_error( fatal,
'MPP_PSET_GET_ROOT_PELIST: '//text )
574 pelist(:) = pset%root_pelist(:)
575 if(
PRESENT(commid) )
then
580 'MPP_PSET_GET_ROOT_PELIST: commID is only defined under -Duse_libMPI.' )
583 end subroutine mpp_pset_get_root_pelist
585 end module mpp_pset_mod
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function stdout()
This function returns the current standard fortran unit numbers for output.
subroutine mpp_set_current_pelist(pelist, no_sync)
Set context pelist.
subroutine mpp_init(flags, localcomm, test_level, alt_input_nml_path)
Initialize the mpp_mod module. Must be called before any usage.
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
subroutine mpp_declare_pelist(pelist, name, commID)
Declare a pelist.
integer function mpp_npes()
Returns processor count for current pelist.
integer function mpp_pe()
Returns processor ID.
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
Calculate parallel checksums.
Recieve data from another PE.
Send data to a receiving PE.