FMS  2024.03
Flexible Modeling System
mpp_pset.F90
1 !***********************************************************************
2 !* GNU Lesser General Public License
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* FMS is free software: you can redistribute it and/or modify it under
7 !* the terms of the GNU Lesser General Public License as published by
8 !* the Free Software Foundation, either version 3 of the License, or (at
9 !* your option) any later version.
10 !*
11 !* FMS is distributed in the hope that it will be useful, but WITHOUT
12 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 !* for more details.
15 !*
16 !* You should have received a copy of the GNU Lesser General Public
17 !* License along with FMS. If not, see <http://www.gnu.org/licenses/>.
18 !***********************************************************************
19 #ifdef test_mpp_pset
20 !PSET_DEBUG is always turned on in the test program
21 #define PSET_DEBUG
22 #endif
23 
24 !> @defgroup mpp_pset_mod mpp_pset_mod
25 !> @ingroup mpp
26 !> @brief Handles PSETs(Persistent Shared-memory Execution Threads) for mpp modules
27 !!
28 !! @author V. Balaji (v.balaji@noaa.gov)
29 !! @date 2006-01-15
30 
31 !> @addtogroup mpp_pset_mod mpp_pset_mod
32 !> @{
33 module mpp_pset_mod
34 #include <fms_platform.h>
35  use mpp_mod, only: mpp_pe, mpp_npes, mpp_root_pe, mpp_send, mpp_recv, &
36  mpp_sync, mpp_error, fatal, warning, stdout, stderr, mpp_chksum, &
37  mpp_declare_pelist, mpp_get_current_pelist, mpp_set_current_pelist, &
38  mpp_init, comm_tag_1, comm_tag_2, comm_tag_3, mpp_sync_self
39  implicit none
40  private
41 
42 !private variables
43  integer :: pe
44  integer :: commID !MPI communicator, copy here from pset
45  logical :: verbose=.false.
46  logical :: module_is_initialized=.false.
47  character(len=256) :: text
48 !generic interfaces
50  module procedure mpp_pset_broadcast_ptr_scalar
51  module procedure mpp_pset_broadcast_ptr_array
52  end interface
53  interface mpp_send_ptr
54  module procedure mpp_send_ptr_scalar
55  module procedure mpp_send_ptr_array
56  end interface
57  interface mpp_recv_ptr
58  module procedure mpp_recv_ptr_scalar
59  module procedure mpp_recv_ptr_array
60  end interface
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
66  end interface
67 !public type
68  type :: mpp_pset_type
69  private
70  integer :: npset !number of PSETs
71  integer :: next_in_pset, prev_in_pset !next and prev PE in PSET (cyclic)
72  integer :: root_in_pset !PE designated to be the root within PSET
73  logical :: root !true if you are the root PSET
74  integer :: pos !position of current PE within pset
75 !stack is allocated by root
76 !it is then mapped to mpp_pset_stack by mpp_pset_broadcast_ptr
77  real, allocatable :: stack(:)
78  integer, allocatable :: pelist(:) !base PElist
79  integer, allocatable :: root_pelist(:) !a PElist of all the roots
80  integer, allocatable :: pset(:) !PSET IDs
81  integer(POINTER_KIND) :: p_stack
82  integer :: lstack, maxstack, hiWM !current stack length, max, hiWM
83  integer :: commID
84  character(len=32) :: name
85  logical :: initialized=.false.
86  end type mpp_pset_type
87 !public types
88  public :: mpp_pset_type
89 !public variables
90 !public member functions
91  public :: mpp_pset_create, mpp_pset_sync, mpp_pset_broadcast, &
92  mpp_pset_broadcast_ptr, mpp_pset_check_ptr, mpp_pset_segment_array, &
93  mpp_pset_stack_push, mpp_pset_stack_reset, mpp_pset_print_chksum, &
94  mpp_pset_delete, mpp_pset_root, mpp_pset_numroots, mpp_pset_init, &
95  mpp_pset_get_root_pelist, mpp_pset_print_stack_chksum
96 
97 
98 contains
99  subroutine mpp_pset_init
100  module_is_initialized = .true.
101  end subroutine mpp_pset_init
102 
103  subroutine mpp_pset_create(npset,pset,stacksize,pelist, commID)
104 !create PSETs
105 ! called by all PEs in parent pelist
106 ! mpset must be exact divisor of npes
107  integer, intent(in) :: npset !number of PSETs per set
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
112 
113  integer :: npes, my_commID
114  integer :: i, j, k, out_unit, errunit
115  integer, allocatable :: my_pelist(:), root_pelist(:)
116 
117  call mpp_init()
118  call mpp_pset_init()
119 
120 #ifdef PSET_DEBUG
121  verbose=.true.
122 #endif
123  out_unit = stdout()
124  errunit = stderr()
125  pe = mpp_pe()
126  if(present(pelist)) then
127  npes = size(pelist(:))
128  else
129  npes = mpp_npes()
130  endif
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
135  call mpp_error( fatal, text )
136  end if
137 
138  !configure out root_pelist
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')
144  my_pelist = pelist
145  my_commid = commid
146  else
147  call mpp_get_current_pelist(my_pelist, commid = my_commid)
148  endif
149  do i = 0,npes/npset-1
150  root_pelist(i) = my_pelist(npset*i)
151  enddo
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!' )
156  pset%npset = npset
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
161 !create the root PElist
162  pset%root_pelist = root_pelist
163  allocate( pset%pset(0:npset-1) )
164  do i = 0,npes/npset-1
165  k = npset*i
166 !designate the root PE, next PE, prev PE
167  do j = 0,npset-1
168  if( pe.EQ.pset%pelist(k+j) )then
169  pset%pset(:) = pset%pelist(k:k+npset-1)
170  pset%pos = j
171  pset%root_in_pset = pset%root_pelist(i)
172  if( j.EQ.0 )then
173  pset%prev_in_pset = pset%pelist(k+npset-1)
174  else
175  pset%prev_in_pset = pset%pelist(k+j-1)
176  end if
177  if( j.EQ.npset-1 )then
178  pset%next_in_pset = pset%pelist(k)
179  else
180  pset%next_in_pset = pset%pelist(k+j+1)
181  end if
182  end if
183  end do
184  end do
185 
186  pset%root = pe.EQ.pset%root_in_pset
187 
188 !stack
189  pset%hiWM = 0 !initialize hi-water-mark
190  pset%maxstack = 1000000 !default
191  if( PRESENT(stacksize) )pset%maxstack = stacksize
192  write( out_unit,'(a,i8)' ) &
193  'MPP_PSET_CREATE: setting stacksize=', pset%maxstack
194  if( pset%root )then
195  allocate( pset%stack(pset%maxstack) )
196 #ifdef use_CRI_pointers
197  pset%p_stack = loc(pset%stack)
198 #endif
199  end if
200  pset%initialized = .true. !must be called before using pset
201  call mpp_pset_broadcast_ptr(pset,pset%p_stack)
202  endif
203 
204  call mpp_declare_pelist(root_pelist)
205 
206  if( verbose )then
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(:)
211  end if
212  end subroutine mpp_pset_create
213 
214  subroutine mpp_pset_delete(pset)
215  type(mpp_pset_type), intent(inout) :: pset
216  integer :: out_unit
217 
218  out_unit = stdout()
219  if( .NOT.pset%initialized )call mpp_error( fatal, &
220  'MPP_PSET_DELETE: called with uninitialized PSET.' )
221 !deallocate arrays...
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
228 !... and set status flag
229  pset%initialized = .false.
230  end subroutine mpp_pset_delete
231 
232  subroutine mpp_send_ptr_scalar( ptr, pe )
233  integer(POINTER_KIND), intent(in) :: ptr
234  integer, intent(in) :: pe
235 
236 !currently only wraps mpp_send
237 !on some architectures, mangling might occur
238  call mpp_send( ptr, pe, tag=comm_tag_1 )
239  end subroutine mpp_send_ptr_scalar
240 
241  subroutine mpp_send_ptr_array( ptr, pe )
242  integer(POINTER_KIND), intent(in) :: ptr(:)
243  integer, intent(in) :: pe
244 
245 !currently only wraps mpp_send
246 !on some architectures, mangling might occur
247  call mpp_send( ptr, size(ptr), pe, tag=comm_tag_2 )
248  end subroutine mpp_send_ptr_array
249 
250  subroutine mpp_recv_ptr_scalar( ptr, pe )
251  integer(POINTER_KIND), intent(inout) :: ptr
252  integer, intent(in) :: pe
253 
254  call mpp_recv( ptr, pe, tag=comm_tag_1 )
255  call mpp_translate_remote_ptr( ptr, pe )
256  return
257  end subroutine mpp_recv_ptr_scalar
258 
259  subroutine mpp_recv_ptr_array( ptr, pe )
260  integer(POINTER_KIND), intent(inout) :: ptr(:)
261  integer, intent(in) :: pe
262  integer :: i
263 
264  call mpp_recv( ptr, size(ptr), pe, tag=comm_tag_2 )
265  do i = 1, size(ptr)
266  call mpp_translate_remote_ptr( ptr(i), pe )
267  end do
268  return
269  end subroutine mpp_recv_ptr_array
270 
271  subroutine mpp_translate_remote_ptr( ptr, pe )
272 !modifies the received pointer to correct numerical address
273  integer(POINTER_KIND), intent(inout) :: ptr
274  integer, intent(in) :: pe
275  return
276  end subroutine mpp_translate_remote_ptr
277 
278  subroutine mpp_pset_sync(pset)
279 !this is a replacement for mpp_sync, doing syncs across
280 !shared arrays without calling mpp_sync
281  type(mpp_pset_type), intent(in) :: pset
282 
283  if( .NOT.pset%initialized )call mpp_error( fatal, &
284  'MPP_PSET_SYNC: called with uninitialized PSET.' )
285 !currently does mpp_sync!!! slow!!!
286 !try and make a lightweight pset sync
287  call mpp_sync
288  end subroutine mpp_pset_sync
289 
290  subroutine mpp_pset_broadcast(pset,a)
291 !broadcast value on the root to its sub-threads
292  type(mpp_pset_type), intent(in) :: pset
293  real, intent(inout) :: a
294  integer :: i
295 
296  if( .NOT.pset%initialized )call mpp_error( fatal, &
297  'MPP_PSET_BROADCAST: called with uninitialized PSET.' )
298  if( pset%root )then
299  do i = 1,pset%npset-1
300  call mpp_send( a, pset%pset(i), tag=comm_tag_3 )
301  end do
302  else
303  call mpp_recv( a, pset%root_in_pset, tag=comm_tag_3 )
304  end if
305  call mpp_pset_sync(pset)
306  end subroutine mpp_pset_broadcast
307 
308  subroutine mpp_pset_broadcast_ptr_scalar(pset,ptr)
309 !create a shared array by broadcasting pointer
310 !root allocates memory and passes pointer in
311 !on return all other PSETs will have the pointer to a shared object
312  type(mpp_pset_type), intent(in) :: pset
313  integer(POINTER_KIND), intent(inout) :: ptr
314  integer :: i
315 
316  if( .NOT.pset%initialized )call mpp_error( fatal, &
317  'MPP_PSET_BROADCAST_PTR: called with uninitialized PSET.' )
318  commid = pset%commID !pass to mpp_translate_remote_ptr
319  if( pset%root )then
320  do i = 1,pset%npset-1
321  call mpp_send_ptr( ptr, pset%pset(i) )
322  end do
323  else
324  call mpp_recv_ptr( ptr, pset%root_in_pset )
325  end if
326  call mpp_sync_self()
327  end subroutine mpp_pset_broadcast_ptr_scalar
328 
329  subroutine mpp_pset_broadcast_ptr_array(pset,ptr)
330 !create a shared array by broadcasting pointer
331 !root allocates memory and passes pointer in
332 !on return all other PSETs will have the pointer to a shared object
333  type(mpp_pset_type), intent(in) :: pset
334  integer(POINTER_KIND), intent(inout) :: ptr(:)
335  integer :: i
336 
337  if( .NOT.pset%initialized )call mpp_error( fatal, &
338  'MPP_PSET_BROADCAST_PTR: called with uninitialized PSET.' )
339  commid = pset%commID !pass to mpp_translate_remote_ptr
340  if( pset%root )then
341  do i = 1,pset%npset-1
342  call mpp_send_ptr( ptr, pset%pset(i) )
343  end do
344  else
345  call mpp_recv_ptr( ptr, pset%root_in_pset )
346  end if
347  call mpp_sync_self()
348 
349  end subroutine mpp_pset_broadcast_ptr_array
350 
351  subroutine mpp_pset_check_ptr(pset,ptr)
352 !checks if the supplied pointer is indeed shared
353  type(mpp_pset_type), intent(in) :: pset
354 #ifdef use_CRI_pointers
355  real :: dummy
356  pointer( ptr, dummy )
357 #else
358  integer(POINTER_KIND), intent(in) :: ptr
359 #endif
360 #ifdef PSET_DEBUG
361  integer(POINTER_KIND) :: p
362  integer :: i
363  if( .NOT.pset%initialized )call mpp_error( fatal, &
364  'MPP_PSET_CHECK_PTR: called with uninitialized PSET.' )
365  commid = pset%commID !pass to mpp_translate_remote_ptr
366 !check if this is a shared pointer
367  p = ptr
368  if( pset%root )then
369  do i = 1,pset%npset-1
370  call mpp_send_ptr( p, pset%pset(i) )
371  end do
372  else
373  call mpp_recv_ptr( p, pset%root_in_pset )
374  end if
375  call mpp_pset_sync(pset)
376  if( p.NE.ptr )call mpp_error( fatal, &
377  'MPP_PSET_CHECK_PTR: pointers do not match!' )
378 #else
379 !do nothing if the debug CPP flag isn't on
380 #endif
381  end subroutine mpp_pset_check_ptr
382 
383  subroutine mpp_pset_segment_array( pset, ls, le, lsp, lep )
384 !given input indices ls, le, returns indices lsp, lep
385 !so that segments span the range ls:le with no overlaps.
386 !attempts load balance: also some PSETs might get lsp>lep
387 !so that do-loops will be null
388  type(mpp_pset_type), intent(in) :: pset
389  integer, intent(in) :: ls, le
390  integer, intent(out) :: lsp, lep
391  integer :: i
392 
393  if( .NOT.pset%initialized )call mpp_error( fatal, &
394  'MPP_PSET_SEGMENT_ARRAY: called with uninitialized PSET.' )
395 #ifdef PSET_DEBUG
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
400  call mpp_error( warning, text )
401  end if
402 #endif
403  lep = ls-1 !initialize so that lsp is correct on first pass
404  do i = 0,pset%pos
405  lsp = lep + 1
406  lep = lsp + ceiling( real(le-lsp+1)/(pset%npset-i) ) - 1
407  end do
408  end subroutine mpp_pset_segment_array
409 
410  subroutine mpp_pset_stack_push( pset, ptr, len )
411 !mpp_malloc specialized for shared arrays
412 !len is the length of the required array
413 !lstack is the stack already in play
414 !user should zero lstack (call mpp_pset_stack_reset) when the stack is to be cleared
415  type(mpp_pset_type), intent(inout) :: pset
416  integer, intent(in) :: len
417 #ifdef use_CRI_pointers
418  real :: dummy
419  pointer( ptr, dummy )
420  real :: stack(pset%maxstack)
421  pointer( p, stack )
422 
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
430  call mpp_error( fatal, text )
431  end if
432  p = pset%p_stack !point stack to shared stack pointer
433  ptr = loc( stack(pset%lstack+1) )
434  call mpp_pset_check_ptr(pset,ptr) !make sure ptr is the same across PSETs
435  pset%lstack = pset%lstack + len
436  pset%hiWM = max( pset%hiWM, pset%lstack )
437 #else
438  integer(POINTER_KIND), intent(out) :: ptr
439  call mpp_error( fatal, &
440  'MPP_PSET_STACK_PUSH only works with Cray pointers.' )
441 #endif
442  end subroutine mpp_pset_stack_push
443 
444  subroutine mpp_pset_stack_reset(pset)
445  type(mpp_pset_type), intent(inout) :: pset
446 !reset stack... will reuse any temporary arrays! USE WITH CARE
447 !next few lines are to zero stack contents...
448 !but it's better noone tries to use uninitialized stack variables!
449 ! integer :: l1, l2
450 ! real :: mpp_pset_stack(maxstack)
451 ! pointer( p_mpp_pset_stack, mpp_pset_stack )
452 ! p_mpp_pset_stack = ptr_mpp_pset_stack
453 ! call mpp_pset_array_segment( 1, lstack, l1, l2 )
454 ! mpp_pset_stack(l1:l2) = 0.
455  if( .NOT.pset%initialized )call mpp_error( fatal, &
456  'MPP_PSET_STACK_RESET: called with uninitialized PSET.' )
457  pset%lstack = 0
458  end subroutine mpp_pset_stack_reset
459 
460  subroutine mpp_pset_print_chksum_1d(pset, caller, array)
461 !print a checksum of an array
462 !pass the whole domain seen by root PSET
463 !add lines to check on shared array?
464  type(mpp_pset_type), intent(in) :: pset
465  character(len=*), intent(in) :: caller
466  real, intent(in) :: array(:)
467 
468 #ifdef PSET_DEBUG
469  integer :: errunit
470  logical :: do_print
471  integer(LONG_KIND) :: chksum
472 
473  if( .NOT.pset%initialized )call mpp_error( fatal, &
474  'MPP_PSET_PRINT_CHKSUM: called with uninitialized PSET.' )
475  errunit = stderr()
476 
477  if( pset%root )then
478  do_print = pe.EQ.mpp_root_pe() !set to T to print from all PEs
479  call mpp_set_current_pelist(pset%root_pelist)
480  chksum = mpp_chksum( array )
481  if( do_print ) &
482  write( errunit, '(a,z18)' )trim(caller)//' chksum=', chksum
483  end if
484  call mpp_set_current_pelist(pset%pelist)
485 #endif
486  return
487  end subroutine mpp_pset_print_chksum_1d
488 
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 )
496  p = loc(array)
497 #else
498  array1d = transfer( array, array1d )
499 #endif
500  call mpp_pset_print_chksum(pset, caller, array1d)
501  end subroutine mpp_pset_print_chksum_2d
502 
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(:,:,:) !overload for other ranks
507  real :: array1D( size(array) )
508 #ifdef use_CRI_pointers
509  pointer( p, array1d )
510  p = loc(array)
511 #else
512  array1d = transfer( array, array1d )
513 #endif
514  call mpp_pset_print_chksum(pset, caller, array1d)
515  end subroutine mpp_pset_print_chksum_3d
516 
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 )
524  p = loc(array)
525 #else
526  array1d = transfer( array, array1d )
527 #endif
528  call mpp_pset_print_chksum(pset, caller, array1d)
529  end subroutine mpp_pset_print_chksum_4d
530 
531  subroutine mpp_pset_print_stack_chksum( pset, caller )
532  type(mpp_pset_type), intent(in) :: pset
533  character(len=*), intent(in) :: caller
534 
535  if( .NOT.pset%initialized )call mpp_error( fatal, &
536  'MPP_PSET_PRINT_STACK_CHKSUM: called with uninitialized PSET.' )
537  call mpp_pset_print_chksum( pset, trim(caller)//' stack', &
538  pset%stack(1:pset%lstack) )
539  end subroutine mpp_pset_print_stack_chksum
540 
541 !accessor functions
542  function mpp_pset_root(pset)
543  logical :: mpp_pset_root
544  type(mpp_pset_type), intent(in) :: pset
545 
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
550 
551  function mpp_pset_numroots(pset)
552 !necessary to export root_pelist: caller needs to pre-allocate
553  integer :: mpp_pset_numroots
554  type(mpp_pset_type), intent(in) :: pset
555 
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
560 
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
565 
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 )
573  end if
574  pelist(:) = pset%root_pelist(:)
575  if( PRESENT(commid) )then
576 #ifdef use_libMPI
577  commid = pset%commID
578 #else
579  call mpp_error( warning, &
580  'MPP_PSET_GET_ROOT_PELIST: commID is only defined under -Duse_libMPI.' )
581 #endif
582  end if
583  end subroutine mpp_pset_get_root_pelist
584 
585 end module mpp_pset_mod
586 !> @}
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.
Definition: mpp_util.inc:43
subroutine mpp_set_current_pelist(pelist, no_sync)
Set context pelist.
Definition: mpp_util.inc:490
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.
Definition: mpp_util.inc:51
subroutine mpp_declare_pelist(pelist, name, commID)
Declare a pelist.
Definition: mpp_util.inc:461
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:421
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:407
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
Calculate parallel checksums.
Definition: mpp.F90:1200
Error handler.
Definition: mpp.F90:382
Recieve data from another PE.
Definition: mpp.F90:937
Send data to a receiving PE.
Definition: mpp.F90:1004