FMS  2026.01.01-dev
Flexible Modeling System
ensemble_manager.F90
1 !***********************************************************************
2 !* Apache License 2.0
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* Licensed under the Apache License, Version 2.0 (the "License");
7 !* you may not use this file except in compliance with the License.
8 !* You may obtain a copy of the License at
9 !*
10 !* http://www.apache.org/licenses/LICENSE-2.0
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
14 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 !* PARTICULAR PURPOSE. See the License for the specific language
16 !* governing permissions and limitations under the License.
17 !***********************************************************************
18 !> @defgroup ensemble_manager_mod ensemble_manager_mod
19 !> @ingroup coupler
20 !> @brief Routines for setting up and managing ensembles and ensemble pe lists.
21 
22 !> @addtogroup ensemble_manager_mod
23 !> @{
24 module ensemble_manager_mod
25 
26 
27  use fms_mod, only : check_nml_error
28  use mpp_mod, only : mpp_npes, stdout, stdlog, mpp_error, fatal
29  use mpp_mod, only : mpp_pe, mpp_declare_pelist
30  use mpp_mod, only : input_nml_file
31  use fms2_io_mod, only : fms2_io_set_filename_appendix=>set_filename_appendix
32 
33  IMPLICIT NONE
34 
35  private
36 
37  integer, parameter :: MAX_ENSEMBLE_SIZE = 100
38 
39 
40  integer, allocatable, dimension(:,:) :: ensemble_pelist
41  integer, allocatable, dimension(:,:) :: ensemble_pelist_ocean
42  integer, allocatable, dimension(:,:) :: ensemble_pelist_atmos
43  integer, allocatable, dimension(:,:) :: ensemble_pelist_land
44  integer, allocatable, dimension(:,:) :: ensemble_pelist_ice
45  integer, allocatable, dimension(:) :: ensemble_pelist_ocean_filter
46  integer, allocatable, dimension(:) :: ensemble_pelist_atmos_filter
47  integer, allocatable, dimension(:) :: ensemble_pelist_land_filter
48  integer, allocatable, dimension(:) :: ensemble_pelist_ice_filter
49 
50  integer :: ensemble_size = 1
51  integer :: ensemble_id = 1
52 !> @brief Starting index for ensemble numbering in I/O filenames.
53 !!
54 !! Defines an offset applied to the local ensemble_id when constructing
55 !! filename appendices via fms2_io_set_filename_appendix.
56 !!
57 !! The effective ensemble index used in filenames is:
58 !! global_ens = starting_ensemble_id + ensemble_id - 1
59 !!
60 !! For example:
61 !! ensemble_size = 2
62 !! starting_ensemble_id = 10
63 !! results in filenames using ens_10 and ens_11.
64 !!
65 !! @note This parameter affects only I/O filename construction (e.g.,
66 !! restart and diagnostic files). It does not affect ensemble-specific
67 !! input selection such as data_override, which uses explicit filenames
68 !! or data_table.ens_XX.yaml.
69 !!
70 !! @default 1
71  integer :: starting_ensemble_id = 1
72  integer :: pe, total_npes_pm=0,ocean_npes_pm=0,atmos_npes_pm=0
73  integer :: land_npes_pm=0,ice_npes_pm=0
74 
76  public :: ensemble_pelist_setup
78 contains
79 
80 !> @brief Initializes @ref ensemble_manager_mod
81 !!
82 !> @throw FATAL, "ensemble_manager_mod: ensemble_nml variable ensemble_size must be a positive integer"
83 !! @throw FATAL, "ensemble_manager_mod: ensemble_nml variable ensemble_size should be no larger
84 !! than MAX_ENSEMBLE_SIZE, change ensemble_size or increase MAX_ENSEMBLE_SIZE"
85 !! @throw FATAL, "ensemble_size must be divis by npes"
86 !! @throw FATAL, "get_ensemble_pelist: size of pelist 1st index < ensemble_size"
87 !! @throw FATAL, "get_ensemble_pelist: size of pelist 2nd index < ocean_npes_pm"
88 !! @throw FATAL, "get_ensemble_pelist: size of pelist 2nd index < atmos_npes_pm"
89 !! @throw FATAL, "get_ensemble_pelist: size of pelist 2nd index < land_npes_pm"
90 !! @throw FATAL, "get_ensemble_pelist: size of pelist 2nd index < ice_npes_pm"
91 !! @throw FATAL, "get_ensemble_pelist: unknown argument name=[name]"
92 !! @throw FATAL, "get_ensemble_pelist: size of pelist 2nd index < total_npes_pm"
93  subroutine ensemble_manager_init()
94 
95 
96  integer :: i, io_status, npes, ierr
97 
98  !> @namelist ensemble_nml
99  !! @param ensemble_size Number of ensemble members.
100  !! @param starting_ensemble_id Offset applied to ensemble_id when
101  !! constructing I/O filename appendices.
102  namelist /ensemble_nml/ ensemble_size, starting_ensemble_id
103 
104  read (input_nml_file, ensemble_nml, iostat=io_status)
105  ierr = check_nml_error(io_status, 'ensemble_nml')
106 
107  if(ensemble_size < 1) call mpp_error(fatal, &
108  'ensemble_manager_mod: ensemble_nml variable ensemble_size must be a positive integer')
109  if(ensemble_size > max_ensemble_size) call mpp_error(fatal, &
110  'ensemble_manager_mod: ensemble_nml variable ensemble_size should be no larger than MAX_ENSEMBLE_SIZE, '// &
111  'change ensemble_size or increase MAX_ENSEMBLE_SIZE')
112  if(starting_ensemble_id < 1) call mpp_error(fatal, &
113  'ensemble_manager_mod: ensemble_nml variable starting_ensemble_id must be a positive integer')
114 
115  pe = mpp_pe()
116  npes = mpp_npes()
117  if (npes < ensemble_size) then
118  call mpp_error(fatal,'npes must be >= ensemble_size')
119  endif
120  total_npes_pm = npes/ensemble_size
121  if (mod(npes, total_npes_pm) /= 0) call mpp_error(fatal,'ensemble_size must be divis by npes')
122 
123  call mpp_declare_pelist((/(i,i=0,npes-1)/),'_ens0') ! for ensemble driver
124 
125  end subroutine ensemble_manager_init
126 
127  !> @brief Getter function for ensemble_id
128  !! @return integer of ensemble id
129  function get_ensemble_id()
130  integer :: get_ensemble_id
131  get_ensemble_id = ensemble_id
132  end function get_ensemble_id
133 
134  !> @brief Returns ensemble size integer array
135  !! @return integer array of sizes
136  function get_ensemble_size()
137 
138  integer, dimension(6) :: get_ensemble_size
139 
140  get_ensemble_size(1) = ensemble_size
141  get_ensemble_size(2) = total_npes_pm
142  get_ensemble_size(3) = ocean_npes_pm
143  get_ensemble_size(4) = atmos_npes_pm
144  get_ensemble_size(5) = land_npes_pm
145  get_ensemble_size(6) = ice_npes_pm
146 
147  end function get_ensemble_size
148 
149  !> @brief Gets pe list for current ensemble or a given ensemble component.
150  subroutine get_ensemble_pelist(pelist, name)
151 
152  integer, intent(inout) :: pelist(:,:) !< Ensemble pelist
153  character(len=*), intent(in), optional :: name !< Component name.
154 
155  if (size(pelist,1) < ensemble_size) &
156  call mpp_error(fatal,'get_ensemble_pelist: size of pelist 1st index < ensemble_size')
157 
158  if(present(name)) then
159  select case(name)
160  case('ocean')
161  if (size(pelist,2) < ocean_npes_pm)&
162  call mpp_error(fatal,'get_ensemble_pelist: size of pelist 2nd index < ocean_npes_pm')
163  pelist = 0
164  pelist(1:ensemble_size,1:ocean_npes_pm) = &
165  ensemble_pelist_ocean(1:ensemble_size,1:ocean_npes_pm)
166 
167  case('atmos')
168  if (size(pelist,2) < atmos_npes_pm)&
169  call mpp_error(fatal,'get_ensemble_pelist: size of pelist 2nd index < atmos_npes_pm')
170  pelist = 0
171  pelist(1:ensemble_size,1:atmos_npes_pm) = &
172  ensemble_pelist_atmos(1:ensemble_size,1:atmos_npes_pm)
173 
174  case('land')
175  if (size(pelist,2) < land_npes_pm)&
176  call mpp_error(fatal,'get_ensemble_pelist: size of pelist 2nd index < land_npes_pm')
177  pelist = 0
178  pelist(1:ensemble_size,1:land_npes_pm) = &
179  ensemble_pelist_land(1:ensemble_size,1:land_npes_pm)
180 
181  case('ice')
182  if (size(pelist,2) < ice_npes_pm)&
183  call mpp_error(fatal,'get_ensemble_pelist: size of pelist 2nd index < ice_npes_pm')
184  pelist = 0
185  pelist(1:ensemble_size,1:ice_npes_pm) = &
186  ensemble_pelist_ice(1:ensemble_size,1:ice_npes_pm)
187 
188  case default
189  call mpp_error(fatal,'get_ensemble_pelist: unknown argument name='//name)
190  end select
191  else
192  if (size(pelist,2) < total_npes_pm)&
193  call mpp_error(fatal,'get_ensemble_pelist: size of pelist 2nd index < total_npes_pm')
194  pelist = 0
195  pelist(1:ensemble_size,1:total_npes_pm) = &
196  ensemble_pelist(1:ensemble_size,1:total_npes_pm)
197  endif
198 
199  return
200  end subroutine get_ensemble_pelist
201 
202 !> @brief Gets filter pelist for a given ensemble component.
203 !!
204 !! @throw FATAL, "get_ensemble_filter_pelist: size of pelist argument < ensemble_size * ocean_npes_pm"
205 !! @throw FATAL, "get_ensemble_filter_pelist: size of pelist argument < ensemble_size * atmos_npes_pm"
206 !! @throw FATAL, "get_ensemble_filter_pelist: size of pelist argument < ensemble_size * land_npes_pm"
207 !! @throw FATAL, "get_ensemble_filter_pelist: size of pelist argument < ensemble_size * ice_npes_pm"
208 !! @throw FATAL, "get_ensemble_filter_pelist: unknown argument name=[name]"
209  subroutine get_ensemble_filter_pelist(pelist, name)
210 
211  integer, intent(inout) :: pelist(:) !< Returned filter pe list
212  character(len=*), intent(in) :: name !< Ensemble component name
213 
214  select case(name)
215  case('ocean')
216  if (size(pelist) < ensemble_size * ocean_npes_pm)&
217  call mpp_error(fatal,'get_ensemble_filter_pelist: size of pelist argument < ensemble_size * ocean_npes_pm')
218  pelist = 0
219  pelist(1:ensemble_size*ocean_npes_pm) = &
220  ensemble_pelist_ocean_filter(1:ensemble_size*ocean_npes_pm)
221 
222  case('atmos')
223  if (size(pelist) < ensemble_size * atmos_npes_pm)&
224  call mpp_error(fatal,'get_ensemble_filter_pelist: size of pelist argument < ensemble_size * atmos_npes_pm')
225  pelist = 0
226  pelist(1:ensemble_size*atmos_npes_pm) = &
227  ensemble_pelist_atmos_filter(1:ensemble_size*atmos_npes_pm)
228 
229  case('land')
230  if (size(pelist) < ensemble_size * land_npes_pm)&
231  call mpp_error(fatal,'get_ensemble_filter_pelist: size of pelist argument < ensemble_size * land_npes_pm')
232  pelist = 0
233  pelist(1:ensemble_size*land_npes_pm) = &
234  ensemble_pelist_land_filter(1:ensemble_size*land_npes_pm)
235 
236  case('ice')
237  if (size(pelist) < ensemble_size * ice_npes_pm)&
238  call mpp_error(fatal,'get_ensemble_filter_pelist: size of pelist argument < ensemble_size * ice_npes_pm')
239  pelist = 0
240  pelist(1:ensemble_size*ice_npes_pm) = &
241  ensemble_pelist_ice_filter(1:ensemble_size*ice_npes_pm)
242 
243  case default
244  call mpp_error(fatal,'get_ensemble_filter_pelist: unknown argument name='//name)
245  end select
246 
247 
248  return
249  end subroutine get_ensemble_filter_pelist
250 
251 !nnz: I think the following block of code should be contained in a subroutine
252 ! to consolidate and ensure the consistency of declaring the various pelists.
253 !> @brief Sets up pe list for an ensemble.
254 !!
255 !! @throw FATAL, "ensemble_manager_mod: land_npes > atmos_npes"
256 !! @throw FATAL, "ensemble_manager_mod: ice_npes > atmos_npes"
257  subroutine ensemble_pelist_setup(concurrent, atmos_npes, ocean_npes, land_npes, ice_npes, &
258  Atm_pelist, Ocean_pelist, Land_pelist, Ice_pelist)
259  logical, intent(in) :: concurrent
260  integer, intent(in) :: atmos_npes, ocean_npes
261  integer, intent(in) :: land_npes, ice_npes
262  integer, dimension(:), intent(inout) :: atm_pelist, ocean_pelist
263  integer, dimension(:), intent(inout) :: land_pelist, ice_pelist
264  integer :: atmos_pe_start, atmos_pe_end, ocean_pe_start, ocean_pe_end
265  integer :: land_pe_start, land_pe_end, ice_pe_start, ice_pe_end
266  character(len=10) :: pelist_name, text
267  integer :: npes, n, m ,i, global_ens
268 
269  npes = total_npes_pm
270 
271  ! make sure land_npes and ice_npes are not greater than atmos_npes
272  if(land_npes > atmos_npes) call mpp_error(fatal, 'ensemble_manager_mod: land_npes > atmos_npes')
273  if(ice_npes > atmos_npes) call mpp_error(fatal, 'ensemble_manager_mod: ice_npes > atmos_npes')
274 
275  allocate(ensemble_pelist(ensemble_size,total_npes_pm))
276  allocate(ensemble_pelist_ocean(1:ensemble_size, 1:ocean_npes) )
277  allocate(ensemble_pelist_atmos(1:ensemble_size, 1:atmos_npes) )
278  allocate(ensemble_pelist_land(1:ensemble_size, 1:land_npes) )
279  allocate(ensemble_pelist_ice(1:ensemble_size, 1:ice_npes) )
280 
281  atmos_pe_start = 0
282  ocean_pe_start = 0
283  land_pe_start = 0
284  ice_pe_start = 0
285  if( concurrent .OR. atmos_npes+ocean_npes == npes )then
286  ocean_pe_start = ensemble_size*atmos_npes
287  endif
288  do n=1,ensemble_size
289  atmos_pe_end = atmos_pe_start + atmos_npes - 1
290  ocean_pe_end = ocean_pe_start + ocean_npes - 1
291  land_pe_end = land_pe_start + land_npes - 1
292  ice_pe_end = ice_pe_start + ice_npes - 1
293  ensemble_pelist_atmos(n, 1:atmos_npes) = (/(i,i=atmos_pe_start,atmos_pe_end)/)
294  ensemble_pelist_ocean(n, 1:ocean_npes) = (/(i,i=ocean_pe_start,ocean_pe_end)/)
295  ensemble_pelist_land(n, 1:land_npes) = (/(i,i=land_pe_start, land_pe_end)/)
296  ensemble_pelist_ice(n, 1:ice_npes) = (/(i,i=ice_pe_start, ice_pe_end)/)
297  ensemble_pelist(n, 1:atmos_npes) = ensemble_pelist_atmos(n, 1:atmos_npes)
298  if( concurrent .OR. atmos_npes+ocean_npes == npes ) &
299  ensemble_pelist(n, atmos_npes+1:npes) = ensemble_pelist_ocean(n, 1:ocean_npes)
300  if(any(ensemble_pelist(n,:) == pe)) ensemble_id = n
301  write(pelist_name,'(a,i2.2)') '_ens',n
302  call mpp_declare_pelist(ensemble_pelist(n,:), trim(pelist_name))
303  atmos_pe_start = atmos_pe_end + 1
304  ocean_pe_start = ocean_pe_end + 1
305  land_pe_start = atmos_pe_start
306  ice_pe_start = atmos_pe_start
307  enddo
308 
309  atm_pelist(:) = ensemble_pelist_atmos(ensemble_id,:)
310  ocean_pelist(:) = ensemble_pelist_ocean(ensemble_id,:)
311  land_pelist(:) = ensemble_pelist_land(ensemble_id,:)
312  ice_pelist(:) = ensemble_pelist_ice(ensemble_id,:)
313 
314  ! write(pelist_name,'(a,i2.2)') '_ocn_ens',ensemble_id
315  ! call mpp_declare_pelist(Ocean%pelist , trim(pelist_name) )
316 
317  ! write(pelist_name,'(a,i2.2)') '_atm_ens',ensemble_id
318  ! call mpp_declare_pelist(Atm%pelist , trim(pelist_name) )
319  !
320  !nnz: The above is sufficient for non-concurrent mode.
321  ! BUT
322  ! For atmosphere_init to work in ensemble, concurrent mode
323  ! the following Atm_pelist should be declared (per ensemble member)
324  ! instead of the above Atm%pelist!
325  !
326  ! allocate( Atm_pelist(1:ensemble_size, 1:atmos_npes) )
327  ! do n=1,ensemble_size
328  ! do i=1, atmos_npes
329  ! Atm_pelist(n, i) = ensemble_pelist(n, i)
330  ! enddo
331  ! write(pelist_name,'(a,i2.2)') '_atm_ens',n
332  ! call mpp_declare_pelist(Atm_pelist(n,:) , trim(pelist_name) )
333  ! enddo
334  !
335  ! The way I understand this with the help of Totalview is:
336  ! With mpp_declare_pelist(Atm%pelist)
337  ! When we are in fv_arrays_init when mp_init(comID) is called
338  ! comID is the same for the atmospheric PE's for both ensemble members
339  ! since peset(5)%id is the same (7) for those PE's, so the PE count is double what it should be inside
340  ! mp_init().
341  ! It is also true that for Ocean PE's, peset(4)%id is the same (6) for Ocean PE's in both ensemble members
342  ! but for Ocean it is not a problem because Ocean is not trying to create new communicators
343  ! from this peset whereas ATM does (vis mp_init).
344  !
345  ! Who sets peset(i)%id ? Can it be modified to assign different %id for the two subsets.
346  ! peset(i)%id = 0 for Ocean PE's on ATM pesets and for ATM PE's on Ocean pesets.
347  !
348  ! With mpp_declare_pelist(Atm_pelist(n,:)) n=1,...,ensemble_size
349  ! we get separate pesets for each ATM ensemble member and each with a different %id and mp_init is cured.
350  !
351  ! There is also a matter of precedence. If we have both calls
352  ! call mpp_declare_pelist(Atm%pelist , trim(pelist_name) )
353  ! and
354  ! call mpp_declare_pelist(Atm_pelist(n,:) , trim(pelist_name) )
355  ! then concurrent run fails because with call mpp_set_current_pelist( Atm%pelist )
356  ! peset(i) is searched for i=1,2,... and the first pelist that matches argument, its peset is set as current.
357  !
358  ! To be consistent with ATM and OCEAN we can do the following
359  ! (eventhough mpp_declare_pelist(Ocean%pelist) is adequate right now.)
360 
361  if( concurrent )then
362  do n=1,ensemble_size
363  write(pelist_name,'(a,i2.2)') 'atm_ens',n
364  call mpp_declare_pelist(ensemble_pelist_atmos(n,:) , trim(pelist_name) )
365  write(pelist_name,'(a,i2.2)') 'ocn_ens',n
366  call mpp_declare_pelist(ensemble_pelist_ocean(n,:) , trim(pelist_name) )
367  write(pelist_name,'(a,i2.2)') 'lnd_ens',n
368  call mpp_declare_pelist(ensemble_pelist_land(n,:) , trim(pelist_name) )
369  write(pelist_name,'(a,i2.2)') 'ice_ens',n
370  call mpp_declare_pelist(ensemble_pelist_ice(n,:) , trim(pelist_name) )
371  enddo
372  else
373  write(pelist_name,'(a,i2.2)') 'atm_ens',ensemble_id
374  call mpp_declare_pelist(atm_pelist , trim(pelist_name) )
375  write(pelist_name,'(a,i2.2)') 'ocn_ens',ensemble_id
376  call mpp_declare_pelist(ocean_pelist , trim(pelist_name) )
377  write(pelist_name,'(a,i2.2)') 'lnd_ens',ensemble_id
378  call mpp_declare_pelist(land_pelist , trim(pelist_name) )
379  write(pelist_name,'(a,i2.2)') 'ice_ens',ensemble_id
380  call mpp_declare_pelist(ice_pelist , trim(pelist_name) )
381  endif
382 
383  ocean_npes_pm = ocean_npes
384  atmos_npes_pm = atmos_npes
385  land_npes_pm = land_npes
386  ice_npes_pm = ice_npes
387 
388  !Declare pelist of all Ocean, Atmos, Land and Ice pes across all ensembles ( filters )
389  allocate(ensemble_pelist_ocean_filter(ensemble_size * ocean_npes_pm))
390  allocate(ensemble_pelist_atmos_filter(ensemble_size * atmos_npes_pm))
391  allocate(ensemble_pelist_land_filter(ensemble_size * land_npes_pm))
392  allocate(ensemble_pelist_ice_filter(ensemble_size * ice_npes_pm))
393  do n=1,ensemble_size
394  do m=1,ocean_npes_pm
395  i=(n-1)*ocean_npes_pm + m
396  ensemble_pelist_ocean_filter(i) = ensemble_pelist_ocean(n,m)
397  enddo
398  do m=1,atmos_npes_pm
399  i=(n-1)*atmos_npes_pm + m
400  ensemble_pelist_atmos_filter(i) = ensemble_pelist_atmos(n,m)
401  enddo
402  do m=1,land_npes_pm
403  i=(n-1)*land_npes_pm + m
404  ensemble_pelist_land_filter(i) = ensemble_pelist_land(n,m)
405  enddo
406  do m=1,ice_npes_pm
407  i=(n-1)*ice_npes_pm + m
408  ensemble_pelist_ice_filter(i) = ensemble_pelist_ice(n,m)
409  enddo
410  enddo
411 
412  write(pelist_name,'(a)') 'ocn_filter'
413  call mpp_declare_pelist(ensemble_pelist_ocean_filter, trim(pelist_name) )
414 
415  write(pelist_name,'(a)') 'atm_filter'
416  call mpp_declare_pelist(ensemble_pelist_atmos_filter, trim(pelist_name) )
417 
418  write(pelist_name,'(a)') 'lnd_filter'
419  call mpp_declare_pelist(ensemble_pelist_land_filter, trim(pelist_name) )
420 
421  write(pelist_name,'(a)') 'ice_filter'
422  call mpp_declare_pelist(ensemble_pelist_ice_filter, trim(pelist_name) )
423 
424  !
425  !Rename output files to identify the ensemble
426  !If ensemble_size=1 do not rename files so that the same coupler
427  !can be used for non-ensemble experiments
428  !
429  if (ensemble_size > 1) then
430  global_ens = starting_ensemble_id + ensemble_id - 1
431  write( text,'(a,i2.2)' ) 'ens_', global_ens
432  !Append ensemble_id to the restart filenames
433  call fms2_io_set_filename_appendix(trim(text))
434  endif
435 
436  end subroutine ensemble_pelist_setup
437 
438 
439 end module ensemble_manager_mod
440 !> @}
441 ! close documentation grouping
integer function, public get_ensemble_id()
Getter function for ensemble_id.
integer function, dimension(6), public get_ensemble_size()
Returns ensemble size integer array.
integer starting_ensemble_id
Starting index for ensemble numbering in I/O filenames.
subroutine, public ensemble_pelist_setup(concurrent, atmos_npes, ocean_npes, land_npes, ice_npes, Atm_pelist, Ocean_pelist, Land_pelist, Ice_pelist)
Sets up pe list for an ensemble.
subroutine, public ensemble_manager_init()
Initializes ensemble_manager_mod.
subroutine, public get_ensemble_pelist(pelist, name)
Gets pe list for current ensemble or a given ensemble component.
subroutine, public get_ensemble_filter_pelist(pelist, name)
Gets filter pelist for a given ensemble component.
integer function, public check_nml_error(IOSTAT, NML_NAME)
Checks the iostat argument that is returned after reading a namelist and determines if the error code...
Definition: fms.F90:523
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:42
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:58
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:420
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
Error handler.
Definition: mpp.F90:385
Declare a pelist. The two flavors of this subroutine differ in the type of their comm/commID argument...
Definition: mpp.F90:424