FMS  2026.01.01-dev
Flexible Modeling System
mpp.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 !-----------------------------------------------------------------------
19 ! Communication for message-passing codes
20 !
21 ! AUTHOR: V. Balaji (V.Balaji@noaa.gov)
22 ! SGI/GFDL Princeton University
23 !
24 !-----------------------------------------------------------------------
25 
26 !> @defgroup mpp_mod mpp_mod
27 !> @ingroup mpp
28 !> @brief This module defines interfaces for common operations using message-passing libraries.
29 !! Any type-less arguments in the documentation are MPP_TYPE_ which is defined by the pre-processor
30 !! to create multiple subroutines out of one implementation for use in an interface. See the note
31 !! below for more information
32 !!
33 !> @author V. Balaji <"V.Balaji@noaa.gov">
34 !!
35 !! A set of simple calls to provide a uniform interface
36 !! to different message-passing libraries. It currently can be
37 !! implemented either in the SGI/Cray native SHMEM library or in the MPI
38 !! standard. Other libraries (e.g MPI-2, Co-Array Fortran) can be
39 !! incorporated as the need arises.
40 !!
41 !! The data transfer between a processor and its own memory is based
42 !! on <TT>load</TT> and <TT>store</TT> operations upon
43 !! memory. Shared-memory systems (including distributed shared memory
44 !! systems) have a single address space and any processor can acquire any
45 !! data within the memory by <TT>load</TT> and
46 !! <TT>store</TT>. The situation is different for distributed
47 !! parallel systems. Specialized MPP systems such as the T3E can simulate
48 !! shared-memory by direct data acquisition from remote memory. But if
49 !! the parallel code is distributed across a cluster, or across the Net,
50 !! messages must be sent and received using the protocols for
51 !! long-distance communication, such as TCP/IP. This requires a
52 !! ``handshaking'' between nodes of the distributed system. One can think
53 !! of the two different methods as involving <TT>put</TT>s or
54 !! <TT>get</TT>s (e.g the SHMEM library), or in the case of
55 !! negotiated communication (e.g MPI), <TT>send</TT>s and
56 !! <TT>recv</TT>s.
57 !!
58 !! The difference between SHMEM and MPI is that SHMEM uses one-sided
59 !! communication, which can have very low-latency high-bandwidth
60 !! implementations on tightly coupled systems. MPI is a standard
61 !! developed for distributed computing across loosely-coupled systems,
62 !! and therefore incurs a software penalty for negotiating the
63 !! communication. It is however an open industry standard whereas SHMEM
64 !! is a proprietary interface. Besides, the <TT>put</TT>s or
65 !! <TT>get</TT>s on which it is based cannot currently be implemented in
66 !! a cluster environment (there are recent announcements from Compaq that
67 !! occasion hope).
68 !!
69 !! The message-passing requirements of climate and weather codes can be
70 !! reduced to a fairly simple minimal set, which is easily implemented in
71 !! any message-passing API. <TT>mpp_mod</TT> provides this API.
72 !!
73 !! Features of <TT>mpp_mod</TT> include:
74 !! <ol>
75 !! <li> Simple, minimal API, with free access to underlying API for </li>
76 !! more complicated stuff.<BR/>
77 !! <li> Design toward typical use in climate/weather CFD codes. </li>
78 !! <li> Performance to be not significantly lower than any native API. </li>
79 !! </ol>
80 !!
81 !! This module is used to develop higher-level calls for
82 !! domain decomposition (@ref mpp_domains) and parallel I/O (@ref fms2_io)
83 !! <br/>
84 !! Parallel computing is initially daunting, but it soon becomes
85 !! second nature, much the way many of us can now write vector code
86 !! without much effort. The key insight required while reading and
87 !! writing parallel code is in arriving at a mental grasp of several
88 !! independent parallel execution streams through the same code (the SPMD
89 !! model). Each variable you examine may have different values for each
90 !! stream, the processor ID being an obvious example. Subroutines and
91 !! function calls are particularly subtle, since it is not always obvious
92 !! from looking at a call what synchronization between execution streams
93 !! it implies. An example of erroneous code would be a global barrier
94 !! call (see @ref mpp_sync below) placed
95 !! within a code block that not all PEs will execute, e.g:
96 !!
97 !! <PRE>
98 !! if( pe.EQ.0 )call mpp_sync()
99 !! </PRE>
100 !!
101 !! Here only PE 0 reaches the barrier, where it will wait
102 !! indefinitely. While this is a particularly egregious example to
103 !! illustrate the coding flaw, more subtle versions of the same are
104 !! among the most common errors in parallel code.
105 !! <br/>
106 !! It is therefore important to be conscious of the context of a
107 !! subroutine or function call, and the implied synchronization. There
108 !! are certain calls here (e.g <TT>mpp_declare_pelist, mpp_init,
109 !! mpp_set_stack_size</TT>) which must be called by all
110 !! PEs. There are others which must be called by a subset of PEs (here
111 !! called a <TT>pelist</TT>) which must be called by all the PEs in the
112 !! <TT>pelist</TT> (e.g <TT>mpp_max, mpp_sum, mpp_sync</TT>). Still
113 !! others imply no synchronization at all. I will make every effort to
114 !! highlight the context of each call in the MPP modules, so that the
115 !! implicit synchronization is spelt out.
116 !! <br/>
117 !! For performance it is necessary to keep synchronization as limited
118 !! as the algorithm being implemented will allow. For instance, a single
119 !! message between two PEs should only imply synchronization across the
120 !! PEs in question. A <I>global</I> synchronization (or <I>barrier</I>)
121 !! is likely to be slow, and is best avoided. But codes first
122 !! parallelized on a Cray T3E tend to have many global syncs, as very
123 !! fast barriers were implemented there in hardware.
124 !! <br/>
125 !! Another reason to use pelists is to run a single program in MPMD
126 !! mode, where different PE subsets work on different portions of the
127 !! code. A typical example is to assign an ocean model and atmosphere
128 !! model to different PE subsets, and couple them concurrently instead of
129 !! running them serially. The MPP module provides the notion of a
130 !! <I>current pelist</I>, which is set when a group of PEs branch off
131 !! into a subset. Subsequent calls that omit the <TT>pelist</TT> optional
132 !! argument (seen below in many of the individual calls) assume that the
133 !! implied synchronization is across the current pelist. The calls
134 !! <TT>mpp_root_pe</TT> and <TT>mpp_npes</TT> also return the values
135 !! appropriate to the current pelist. The <TT>mpp_set_current_pelist</TT>
136 !! call is provided to set the current pelist.
137 !! </DESCRIPTION>
138 !! <br/>
139 !!
140 !! @note F90 is a strictly-typed language, and the syntax pass of the
141 !! compiler requires matching of type, kind and rank (TKR). Most calls
142 !! listed here use a generic type, shown here as <TT>MPP_TYPE_</TT>. This
143 !! is resolved in the pre-processor stage to any of a variety of
144 !! types. In general the MPP operations work on 4-byte and 8-byte
145 !! variants of <TT>integer, real, complex, logical</TT> variables, of
146 !! rank 0 to 5, leading to 48 specific module procedures under the same
147 !! generic interface. Any of the variables below shown as
148 !! <TT>MPP_TYPE_</TT> is treated in this way.
149 
150 module mpp_mod
151 
152 ! Define rank(X) for PGI compiler
153 #if defined( __PGI) || defined (__FLANG)
154 #define rank(X) size(shape(X))
155 #endif
156 
157 
158 #ifdef use_libMPI
159  use mpi_f08
160 #else
161  use gfdl_nompi_f08
162 #endif
163 
164  use iso_fortran_env, only : input_unit, output_unit, error_unit
165  use mpp_parameter_mod, only : mpp_verbose, mpp_debug, all_pes, any_pe, null_pe
166  use mpp_parameter_mod, only : note, warning, fatal, mpp_clock_detailed,mpp_clock_sync
167  use mpp_parameter_mod, only : clock_component, clock_subcomponent, clock_module_driver
168  use mpp_parameter_mod, only : clock_module, clock_routine, clock_loop, clock_infra
169  use mpp_parameter_mod, only : max_events, max_bins, max_event_types, max_clocks
170  use mpp_parameter_mod, only : maxpes, event_wait, event_allreduce, event_broadcast
171  use mpp_parameter_mod, only : event_alltoall
172  use mpp_parameter_mod, only : event_type_create, event_type_free
173  use mpp_parameter_mod, only : event_recv, event_send, mpp_ready, mpp_wait
174  use mpp_parameter_mod, only : mpp_parameter_version=>version
175  use mpp_parameter_mod, only : default_tag
176  use mpp_parameter_mod, only : comm_tag_1, comm_tag_2, comm_tag_3, comm_tag_4
177  use mpp_parameter_mod, only : comm_tag_5, comm_tag_6, comm_tag_7, comm_tag_8
178  use mpp_parameter_mod, only : comm_tag_9, comm_tag_10, comm_tag_11, comm_tag_12
179  use mpp_parameter_mod, only : comm_tag_13, comm_tag_14, comm_tag_15, comm_tag_16
180  use mpp_parameter_mod, only : comm_tag_17, comm_tag_18, comm_tag_19, comm_tag_20
181  use mpp_parameter_mod, only : mpp_fill_int,mpp_fill_double
182  use mpp_data_mod, only : stat, mpp_stack, ptr_stack, status, ptr_status, sync, ptr_sync
183  use mpp_data_mod, only : mpp_from_pe, ptr_from, remote_data_loc, ptr_remote
184  use mpp_data_mod, only : mpp_data_version=>version
185  use platform_mod
186 
187 implicit none
188 private
189 
190  !--- public parameters -----------------------------------------------
191  public :: mpp_verbose, mpp_debug, all_pes, any_pe, null_pe, note, warning, fatal
192  public :: mpp_clock_sync, mpp_clock_detailed, clock_component, clock_subcomponent
193  public :: clock_module_driver, clock_module, clock_routine, clock_loop, clock_infra
194  public :: maxpes, event_recv, event_send
195  public :: comm_tag_1, comm_tag_2, comm_tag_3, comm_tag_4
196  public :: comm_tag_5, comm_tag_6, comm_tag_7, comm_tag_8
197  public :: comm_tag_9, comm_tag_10, comm_tag_11, comm_tag_12
198  public :: comm_tag_13, comm_tag_14, comm_tag_15, comm_tag_16
199  public :: comm_tag_17, comm_tag_18, comm_tag_19, comm_tag_20
200  public :: mpp_fill_int, mpp_fill_double, mpp_info_null, mpp_comm_null
201  public :: mpp_init_test_full_init, mpp_init_test_init_true_only, mpp_init_test_peset_allocated
202  public :: mpp_init_test_clocks_init, mpp_init_test_datatype_list_init, mpp_init_test_logfile_init
203  public :: mpp_init_test_read_namelist, mpp_init_test_etc_unit, mpp_init_test_requests_allocated
204 
205  !--- public interface from mpp_util.h ------------------------------
206  public :: stdin, stdout, stderr, stdlog, warnlog, lowercase, uppercase, mpp_error, mpp_error_state
207  public :: mpp_set_warn_level, mpp_sync, mpp_sync_self, mpp_pe
208  public :: mpp_npes, mpp_root_pe, mpp_set_root_pe, mpp_declare_pelist
209  public :: mpp_get_current_pelist, mpp_set_current_pelist, mpp_get_current_pelist_name
210  public :: mpp_clock_id, mpp_clock_set_grain, mpp_record_timing_data, get_unit
211  public :: read_ascii_file, read_input_nml, mpp_clock_begin, mpp_clock_end
212  public :: get_ascii_file_num_lines, get_ascii_file_num_lines_and_length
213  public :: mpp_record_time_start, mpp_record_time_end
214  public :: mpp_commid, mpp_comm, inverse_permutation
215 
216  !--- public interface from mpp_comm.h ------------------------------
218  public :: mpp_sum_ad
219  public :: mpp_broadcast, mpp_init, mpp_exit
221  public :: mpp_type, mpp_byte, mpp_type_create, mpp_type_free
222 
223  !*********************************************************************
224  !
225  ! public data type
226  !
227  !*********************************************************************
228  !> Communication information for message passing libraries
229  !!
230  !> peset hold communicators as SHMEM-compatible triads (start, log2(stride), num)
231  !> @ingroup mpp_mod
232  type :: communicator
233  private
234  character(len=32) :: name
235  integer, pointer :: list(:) =>null()
236  integer :: count
237  integer :: start, log2stride !< dummy variables when libMPI is defined.
238  type(mpi_comm) :: comm !< MPI communicator for this PE set
239  type(mpi_group) :: group !< MPI group for this PE set
240  end type communicator
241 
242  !> Communication event profile
243  !> @ingroup mpp_mod
244  type :: event
245  private
246  character(len=16) :: name
247  integer(i8_kind), dimension(MAX_EVENTS) :: ticks, bytes
248  integer :: calls
249  end type event
250 
251  !> a clock contains an array of event profiles for a region
252  !> @ingroup mpp_mod
253  type :: clock
254  private
255  character(len=32) :: name
256  integer(i8_kind) :: hits
257  integer(i8_kind) :: tick
258  integer(i8_kind) :: total_ticks
259  integer :: peset_num
260  logical :: sync_on_begin, detailed
261  integer :: grain
262  type(event), pointer :: events(:) =>null() !> if needed, allocate to MAX_EVENT_TYPES
263  logical :: is_on !> initialize to false. set true when calling mpp_clock_begin
264  !! set false when calling mpp_clock_end
265  end type clock
266 
267  !> Summary of information from a clock run
268  !> @ingroup mpp_mod
270  private
271  character(len=16) :: name
272  real(r8_kind) :: msg_size_sums(MAX_BINS)
273  real(r8_kind) :: msg_time_sums(MAX_BINS)
274  real(r8_kind) :: total_data
275  real(r8_kind) :: total_time
276  integer(i8_kind) :: msg_size_cnts(MAX_BINS)
277  integer(i8_kind) :: total_cnts
278  end type clock_data_summary
279 
280  !> holds name and clock data for use in @ref mpp_util.h
281  !> @ingroup mpp_mod
283  private
284  character(len=16) :: name
285  type (Clock_Data_Summary) :: event(MAX_EVENT_TYPES)
286  end type summary_struct
287 
288  !> Data types for generalized data transfer (e.g. MPI_Type)
289  !> @ingroup mpp_mod
290  type :: mpp_type
291  private
292  integer :: counter !> Number of instances of this type
293  integer :: ndims
294  integer, allocatable :: sizes(:)
295  integer, allocatable :: subsizes(:)
296  integer, allocatable :: starts(:)
297  type(mpi_datatype) :: etype !> Elementary data type (e.g. MPI_BYTE)
298  type(mpi_datatype) :: id !> Identifier within message passing library (e.g. MPI)
299 
300  type(mpp_type), pointer :: prev => null()
301  type(mpp_type), pointer :: next => null()
302  end type mpp_type
303 
304  !> Persisent elements for linked list interaction
305  !> @ingroup mpp_mod
307  private
308  type(mpp_type), pointer :: head => null()
309  type(mpp_type), pointer :: tail => null()
310  integer :: length
311  end type mpp_type_list
312 
313 !***********************************************************************
314 !
315 ! public interface from mpp_util.h
316 !
317 !***********************************************************************
318  !> @brief Error handler.
319  !!
320  !> It is strongly recommended that all error exits pass through
321  !! <TT>mpp_error</TT> to assure the program fails cleanly. An individual
322  !! PE encountering a <TT>STOP</TT> statement, for instance, can cause the
323  !! program to hang. The use of the <TT>STOP</TT> statement is strongly
324  !! discouraged.
325  !!
326  !! Calling mpp_error with no arguments produces an immediate error
327  !! exit, i.e:
328  !! <PRE>
329  !! call mpp_error
330  !! call mpp_error()
331  !! </PRE>
332  !! are equivalent.
333  !!
334  !! The argument order
335  !! <PRE>
336  !! call mpp_error( routine, errormsg, errortype )
337  !! </PRE>
338  !! is also provided to support legacy code. In this version of the
339  !! call, none of the arguments may be omitted.
340  !!
341  !! The behaviour of <TT>mpp_error</TT> for a <TT>WARNING</TT> can be
342  !! controlled with an additional call <TT>mpp_set_warn_level</TT>.
343  !! <PRE>
344  !! call mpp_set_warn_level(ERROR)
345  !! </PRE>
346  !! causes <TT>mpp_error</TT> to treat <TT>WARNING</TT>
347  !! exactly like <TT>FATAL</TT>.
348  !! <PRE>
349  !! call mpp_set_warn_level(WARNING)
350  !! </PRE>
351  !! resets to the default behaviour described above.
352  !!
353  !! <TT>mpp_error</TT> also has an internal error state which
354  !! maintains knowledge of whether a warning has been issued. This can be
355  !! used at startup in a subroutine that checks if the model has been
356  !! properly configured. You can generate a series of warnings using
357  !! <TT>mpp_error</TT>, and then check at the end if any warnings has been
358  !! issued using the function <TT>mpp_error_state()</TT>. If the value of
359  !! this is <TT>WARNING</TT>, at least one warning has been issued, and
360  !! the user can take appropriate action:
361  !!
362  !! <PRE>
363  !! if( ... )call mpp_error( WARNING, '...' )
364  !! if( ... )call mpp_error( WARNING, '...' )
365  !! if( ... )call mpp_error( WARNING, '...' )
366  !! ...
367  !! if( mpp_error_state().EQ.WARNING )call mpp_error( FATAL, '...' )
368  !! </PRE>
369  !! </DESCRIPTION>
370  !! <br> Example usage:
371  !! @code{.F90}
372  !! call mpp_error( errortype, routine, errormsg )
373  !! @endcode
374  !! @param errortype
375  !! One of <TT>NOTE</TT>, <TT>WARNING</TT> or <TT>FATAL</TT>
376  !! (these definitions are acquired by use association).
377  !! <TT>NOTE</TT> writes <TT>errormsg</TT> to <TT>STDOUT</TT>.
378  !! <TT>WARNING</TT> writes <TT>errormsg</TT> to <TT>STDERR</TT>.
379  !! <TT>FATAL</TT> writes <TT>errormsg</TT> to <TT>STDERR</TT>,
380  !! and induces a clean error exit with a call stack traceback.
381  !! @param routine Calling routine name
382  !! @param errmsg Message to output
383  !! </IN>
384  !> @ingroup mpp_mod
385  interface mpp_error
386  module procedure mpp_error_basic
387  module procedure mpp_error_mesg
388  module procedure mpp_error_noargs
389  module procedure mpp_error_is
390  module procedure mpp_error_rs
391  module procedure mpp_error_ia
392  module procedure mpp_error_ra
393  module procedure mpp_error_ia_ia
394  module procedure mpp_error_ia_ra
395  module procedure mpp_error_ra_ia
396  module procedure mpp_error_ra_ra
397  module procedure mpp_error_ia_is
398  module procedure mpp_error_ia_rs
399  module procedure mpp_error_ra_is
400  module procedure mpp_error_ra_rs
401  module procedure mpp_error_is_ia
402  module procedure mpp_error_is_ra
403  module procedure mpp_error_rs_ia
404  module procedure mpp_error_rs_ra
405  module procedure mpp_error_is_is
406  module procedure mpp_error_is_rs
407  module procedure mpp_error_rs_is
408  module procedure mpp_error_rs_rs
409  end interface
410 
411  !> Takes a given integer or real array and returns it as a string
412  !> @param[in] array An array of integers or reals
413  !> @returns string equivalent of given array
414  !> @ingroup mpp_mod
415  interface array_to_char
416  module procedure iarray_to_char
417  module procedure rarray_to_char
418  end interface
419 
420  !> Declare a pelist. The two flavors of this subroutine differ in the type
421  !! of their comm/commID argument: mpp_declare_pelist_f08 expects a type(mpi_comm)
422  !! as its comm argument, whereas mpp_declare_pelist_legacy expects an integer
423  !! as its commID argument.
425  module procedure mpp_declare_pelist_f08
426  module procedure mpp_declare_pelist_legacy
427  end interface
428 
429  !> Get the current pelist. The two flavors of this subroutine differ in the type
430  !! of their comm/commID argument: mpp_get_current_pelist_f08 expects a type(mpi_comm)
431  !! as its comm argument, whereas mpp_get_current_pelist_legacy expects an integer
432  !! as its commID argument.
434  module procedure mpp_get_current_pelist_f08
435  module procedure mpp_get_current_pelist_legacy
436  end interface
437 
438 !***********************************************************************
439 !
440 ! public interface from mpp_comm.h
441 !
442 !***********************************************************************
443 
444 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
445  ! !
446  ! ROUTINES TO INITIALIZE/FINALIZE MPP MODULE: mpp_init, mpp_exit !
447  ! !
448 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
449 
450 !> @fn mpp_mod::mpp_init::mpp_init( flags, localcomm, test_level)
451 !> @ingroup mpp_mod
452 !> @brief Initialize @ref mpp_mod
453 !!
454 !> Called to initialize the <TT>mpp_mod</TT> package. It is recommended
455 !! that this call be the first executed line in your program. It sets the
456 !! number of PEs assigned to this run (acquired from the command line, or
457 !! through the environment variable <TT>NPES</TT>), and associates an ID
458 !! number to each PE. These can be accessed by calling @ref mpp_npes and
459 !! @ref mpp_pe.
460 !! <br> Example usage:
461 !!
462 !! call mpp_init( flags )
463 !!
464 !! @param flags
465 !! <TT>flags</TT> can be set to <TT>MPP_VERBOSE</TT> to
466 !! have <TT>mpp_mod</TT> keep you informed of what it's up to.
467 !! @param localcomm
468 !! This is a type(mpi_comm) in mpp_init_f08, and an integer in mpp_init_legacy.
469 !! This argument should only be used if MPI has previously been initialized by
470 !! an external call to MPI_Init.
471 !! @param test_level
472 !! Debugging flag to set amount of initialization tasks performed
473  interface mpp_init
474  module procedure mpp_init_f08
475  module procedure mpp_init_legacy
476  end interface
477 
478 !> @fn mpp_mod::mpp_exit()
479 !> @brief Exit <TT>@ref mpp_mod</TT>.
480 !!
481 !> Called at the end of the run, or to re-initialize <TT>mpp_mod</TT>,
482 !! should you require that for some odd reason.
483 !!
484 !! This call implies synchronization across all PEs.
485 !!
486 !! <br>Example usage:
487 !!
488 !! call mpp_exit()
489 !> @ingroup mpp_mod
490 
491  !#####################################################################
492 
493  !> @fn subroutine mpp_set_stack_size(n)
494  !> @brief Allocate module internal workspace.
495  !> @param Integer to set stack size to(in words)
496  !> <TT>mpp_mod</TT> maintains a private internal array called
497  !! <TT>mpp_stack</TT> for private workspace. This call sets the length,
498  !! in words, of this array.
499  !!
500  !! The <TT>mpp_init</TT> call sets this
501  !! workspace length to a default of 32768, and this call may be used if a
502  !! longer workspace is needed.
503  !!
504  !! This call implies synchronization across all PEs.
505  !!
506  !! This workspace is symmetrically allocated, as required for
507  !! efficient communication on SGI and Cray MPP systems. Since symmetric
508  !! allocation must be performed by <I>all</I> PEs in a job, this call
509  !! must also be called by all PEs, using the same value of
510  !! <TT>n</TT>. Calling <TT>mpp_set_stack_size</TT> from a subset of PEs,
511  !! or with unequal argument <TT>n</TT>, may cause the program to hang.
512  !!
513  !! If any MPP call using <TT>mpp_stack</TT> overflows the declared
514  !! stack array, the program will abort with a message specifying the
515  !! stack length that is required. Many users wonder why, if the required
516  !! stack length can be computed, it cannot also be specified at that
517  !! point. This cannot be automated because there is no way for the
518  !! program to know if all PEs are present at that call, and with equal
519  !! values of <TT>n</TT>. The program must be rerun by the user with the
520  !! correct argument to <TT>mpp_set_stack_size</TT>, called at an
521  !! appropriate point in the code where all PEs are known to be present.
522  !! @verbose call mpp_set_stack_size(n)
523  !!
524  !> @ingroup mpp_mod
525  public :: mpp_set_stack_size
526  ! from mpp_util.h
527 
528 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
529 ! !
530 ! DATA TRANSFER TYPES: mpp_type_create !
531 ! !
532 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
533 
534  !> @brief Create a mpp_type variable
535  !> @param[in] field A field of any numerical or logical type
536  !> @param[in] array_of_subsizes Integer array of subsizes
537  !> @param[in] array_of_starts Integer array of starts
538  !> @param[out] dtype_out Output variable for created @ref mpp_type
539  !> @ingroup mpp_mod
540  interface mpp_type_create
541  module procedure mpp_type_create_int4
542  module procedure mpp_type_create_int8
543  module procedure mpp_type_create_real4
544  module procedure mpp_type_create_real8
545  module procedure mpp_type_create_cmplx4
546  module procedure mpp_type_create_cmplx8
547  module procedure mpp_type_create_logical4
548  module procedure mpp_type_create_logical8
549  end interface mpp_type_create
550 
551 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
552  ! !
553  ! GLOBAL REDUCTION ROUTINES: mpp_max, mpp_sum, mpp_min !
554  ! !
555 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
556 
557  !> @brief Reduction operations.
558  !> Find the max of scalar a from the PEs in pelist
559  !! result is also automatically broadcast to all PEs
560  !! @code{.F90}
561  !! call mpp_max( a, pelist )
562  !! @endcode
563  !> @param a <TT>real</TT> or <TT>integer</TT>, of 4-byte of 8-byte kind.
564  !> @param pelist If <TT>pelist</TT> is omitted, the context is assumed to be the
565  !! current pelist. This call implies synchronization across the PEs in
566  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
567  !> @ingroup mpp_mod
568  interface mpp_max
569  module procedure mpp_max_real8_0d
570  module procedure mpp_max_real8_1d
571  module procedure mpp_max_int8_0d
572  module procedure mpp_max_int8_1d
573  module procedure mpp_max_real4_0d
574  module procedure mpp_max_real4_1d
575  module procedure mpp_max_int4_0d
576  module procedure mpp_max_int4_1d
577  end interface
578 
579  !> @brief Reduction operations.
580  !> Find the min of scalar a from the PEs in pelist
581  !! result is also automatically broadcast to all PEs
582  !! @code{.F90}
583  !! call mpp_min( a, pelist )
584  !! @endcode
585  !> @param a <TT>real</TT> or <TT>integer</TT>, of 4-byte of 8-byte kind.
586  !> @param pelist If <TT>pelist</TT> is omitted, the context is assumed to be the
587  !! current pelist. This call implies synchronization across the PEs in
588  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
589  !> @ingroup mpp_mod
590  interface mpp_min
591  module procedure mpp_min_real8_0d
592  module procedure mpp_min_real8_1d
593  module procedure mpp_min_int8_0d
594  module procedure mpp_min_int8_1d
595  module procedure mpp_min_real4_0d
596  module procedure mpp_min_real4_1d
597  module procedure mpp_min_int4_0d
598  module procedure mpp_min_int4_1d
599  end interface
600 
601 
602  !> @brief Reduction operation.
603  !!
604  !> <TT>MPP_TYPE_</TT> corresponds to any 4-byte and 8-byte variant of
605  !! <TT>integer, real, complex</TT> variables, of rank 0 or 1. A
606  !! contiguous block from a multi-dimensional array may be passed by its
607  !! starting address and its length, as in <TT>f77</TT>.
608  !!
609  !! Library reduction operators are not required or guaranteed to be
610  !! bit-reproducible. In any case, changing the processor count changes
611  !! the data layout, and thus very likely the order of operations. For
612  !! bit-reproducible sums of distributed arrays, consider using the
613  !! <TT>mpp_global_sum</TT> routine provided by the
614  !! @ref mpp_domains module.
615  !!
616  !! The <TT>bit_reproducible</TT> flag provided in earlier versions of
617  !! this routine has been removed.
618  !!
619  !!
620  !! If <TT>pelist</TT> is omitted, the context is assumed to be the
621  !! current pelist. This call implies synchronization across the PEs in
622  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
623  !! Example usage:
624  !! call mpp_sum( a, length, pelist )
625  !!
626  !> @ingroup mpp_mod
627  interface mpp_sum
628  module procedure mpp_sum_int8
629  module procedure mpp_sum_int8_scalar
630  module procedure mpp_sum_int8_2d
631  module procedure mpp_sum_int8_3d
632  module procedure mpp_sum_int8_4d
633  module procedure mpp_sum_int8_5d
634  module procedure mpp_sum_real8
635  module procedure mpp_sum_real8_scalar
636  module procedure mpp_sum_real8_2d
637  module procedure mpp_sum_real8_3d
638  module procedure mpp_sum_real8_4d
639  module procedure mpp_sum_real8_5d
640 #ifdef OVERLOAD_C8
641  module procedure mpp_sum_cmplx8
642  module procedure mpp_sum_cmplx8_scalar
643  module procedure mpp_sum_cmplx8_2d
644  module procedure mpp_sum_cmplx8_3d
645  module procedure mpp_sum_cmplx8_4d
646  module procedure mpp_sum_cmplx8_5d
647 #endif
648  module procedure mpp_sum_int4
649  module procedure mpp_sum_int4_scalar
650  module procedure mpp_sum_int4_2d
651  module procedure mpp_sum_int4_3d
652  module procedure mpp_sum_int4_4d
653  module procedure mpp_sum_int4_5d
654  module procedure mpp_sum_real4
655  module procedure mpp_sum_real4_scalar
656  module procedure mpp_sum_real4_2d
657  module procedure mpp_sum_real4_3d
658  module procedure mpp_sum_real4_4d
659  module procedure mpp_sum_real4_5d
660 #ifdef OVERLOAD_C4
661  module procedure mpp_sum_cmplx4
662  module procedure mpp_sum_cmplx4_scalar
663  module procedure mpp_sum_cmplx4_2d
664  module procedure mpp_sum_cmplx4_3d
665  module procedure mpp_sum_cmplx4_4d
666  module procedure mpp_sum_cmplx4_5d
667 #endif
668  end interface
669 
670  !> Calculates sum of a given numerical array across pe's for adjoint domains
671  !> @ingroup mpp_mod
672  interface mpp_sum_ad
673  module procedure mpp_sum_int8_ad
674  module procedure mpp_sum_int8_scalar_ad
675  module procedure mpp_sum_int8_2d_ad
676  module procedure mpp_sum_int8_3d_ad
677  module procedure mpp_sum_int8_4d_ad
678  module procedure mpp_sum_int8_5d_ad
679  module procedure mpp_sum_real8_ad
680  module procedure mpp_sum_real8_scalar_ad
681  module procedure mpp_sum_real8_2d_ad
682  module procedure mpp_sum_real8_3d_ad
683  module procedure mpp_sum_real8_4d_ad
684  module procedure mpp_sum_real8_5d_ad
685 #ifdef OVERLOAD_C8
686  module procedure mpp_sum_cmplx8_ad
687  module procedure mpp_sum_cmplx8_scalar_ad
688  module procedure mpp_sum_cmplx8_2d_ad
689  module procedure mpp_sum_cmplx8_3d_ad
690  module procedure mpp_sum_cmplx8_4d_ad
691  module procedure mpp_sum_cmplx8_5d_ad
692 #endif
693  module procedure mpp_sum_int4_ad
694  module procedure mpp_sum_int4_scalar_ad
695  module procedure mpp_sum_int4_2d_ad
696  module procedure mpp_sum_int4_3d_ad
697  module procedure mpp_sum_int4_4d_ad
698  module procedure mpp_sum_int4_5d_ad
699  module procedure mpp_sum_real4_ad
700  module procedure mpp_sum_real4_scalar_ad
701  module procedure mpp_sum_real4_2d_ad
702  module procedure mpp_sum_real4_3d_ad
703  module procedure mpp_sum_real4_4d_ad
704  module procedure mpp_sum_real4_5d_ad
705 #ifdef OVERLOAD_C4
706  module procedure mpp_sum_cmplx4_ad
707  module procedure mpp_sum_cmplx4_scalar_ad
708  module procedure mpp_sum_cmplx4_2d_ad
709  module procedure mpp_sum_cmplx4_3d_ad
710  module procedure mpp_sum_cmplx4_4d_ad
711  module procedure mpp_sum_cmplx4_5d_ad
712 #endif
713  end interface
714 
715  !> @brief Gather data sent from pelist onto the root pe
716  !! Wrapper for MPI_gather, can be used with and without indices
717  !> @ingroup mpp_mod
718  !!
719  !> @param sbuf MPP_TYPE_ data buffer to send
720  !> @param rbuf MPP_TYPE_ data buffer to receive
721  !> @param pelist integer(:) optional pelist to gather from, defaults to current
722  !>
723  !> <BR> Example usage:
724  !!
725  !! call mpp_gather(send_buffer,recv_buffer, pelist)
726  !! call mpp_gather(is, ie, js, je, pelist, array_seg, data, is_root_pe)
727  !!
728  interface mpp_gather
729  module procedure mpp_gather_logical4
730  module procedure mpp_gatherv_logical4
731  module procedure mpp_gather_logical_1d
732  module procedure mpp_gather_int4
733  module procedure mpp_gather_int8
734  module procedure mpp_gatherv_int4
735  module procedure mpp_gatherv_int8
736  module procedure mpp_gather_int4_1d
737  module procedure mpp_gather_int8_1d
738  module procedure mpp_gather_real4
739  module procedure mpp_gather_real8
740  module procedure mpp_gatherv_real4
741  module procedure mpp_gatherv_real8
742  module procedure mpp_gather_real4_1d
743  module procedure mpp_gather_real8_1d
744  module procedure mpp_gather_logical_1dv
745  module procedure mpp_gather_int4_1dv
746  module procedure mpp_gather_int8_1dv
747  module procedure mpp_gather_real4_1dv
748  module procedure mpp_gather_real8_1dv
749  module procedure mpp_gather_pelist_logical_2d
750  module procedure mpp_gather_pelist_logical_gen_2d
751  module procedure mpp_gather_pelist_logical_3d
752  module procedure mpp_gather_pelist_logical_gen_3d
753  module procedure mpp_gather_pelist_int4_2d
754  module procedure mpp_gather_pelist_int4_gen_2d
755  module procedure mpp_gather_pelist_int4_3d
756  module procedure mpp_gather_pelist_int4_gen_3d
757  module procedure mpp_gather_pelist_int8_2d
758  module procedure mpp_gather_pelist_int8_gen_2d
759  module procedure mpp_gather_pelist_int8_3d
760  module procedure mpp_gather_pelist_int8_gen_3d
761  module procedure mpp_gather_pelist_real4_2d
762  module procedure mpp_gather_pelist_real4_gen_2d
763  module procedure mpp_gather_pelist_real4_3d
764  module procedure mpp_gather_pelist_real4_gen_3d
765  module procedure mpp_gather_pelist_real8_2d
766  module procedure mpp_gather_pelist_real8_gen_2d
767  module procedure mpp_gather_pelist_real8_3d
768  module procedure mpp_gather_pelist_real8_gen_3d
769  end interface
770 
771  !> @brief Scatter (ie - is) * (je - js) contiguous elements of array data from the designated root pe
772  !! into contigous members of array segment in each pe that is included in the pelist argument.
773  !> @ingroup mpp_mod
774  !!
775  !> @param is, ie integer start and end index of the first dimension of the segment array
776  !> @param je, js integer start and end index of the second dimension of the segment array
777  !> @param pelist integer(:) the PE list of target pes, needs to be monotonically increasing
778  !> @param array_seg MPP_TYPE_ 2D array that the data is to be copied into
779  !> @param data MPP_TYPE_ the source array
780  !> @param is_root_pe logical true if calling from root pe
781  !> @param ishift integer offsets specifying the first elelement in the data array
782  !> @param nk integer size of third dimension for 3D calls
783  !!
784  !> <BR> Example usage:
785  !!
786  !! call mpp_scatter(is, ie, js, je, pelist, segment, data, .true.)
787  !!
788  interface mpp_scatter
789  module procedure mpp_scatterv_int4
790  module procedure mpp_scatter_pelist_int4_2d
791  module procedure mpp_scatter_pelist_int4_gen_2d
792  module procedure mpp_scatter_pelist_int4_3d
793  module procedure mpp_scatter_pelist_int4_gen_3d
794  module procedure mpp_scatterv_int8
795  module procedure mpp_scatter_pelist_int8_2d
796  module procedure mpp_scatter_pelist_int8_gen_2d
797  module procedure mpp_scatter_pelist_int8_3d
798  module procedure mpp_scatter_pelist_int8_gen_3d
799  module procedure mpp_scatterv_real4
800  module procedure mpp_scatter_pelist_real4_2d
801  module procedure mpp_scatter_pelist_real4_gen_2d
802  module procedure mpp_scatter_pelist_real4_3d
803  module procedure mpp_scatter_pelist_real4_gen_3d
804  module procedure mpp_scatterv_real8
805  module procedure mpp_scatter_pelist_real8_2d
806  module procedure mpp_scatter_pelist_real8_gen_2d
807  module procedure mpp_scatter_pelist_real8_3d
808  module procedure mpp_scatter_pelist_real8_gen_3d
809  end interface
810 
811  !#####################################################################
812  !> @brief Scatter a vector across all PEs
813  !!
814  !> Transpose the vector and PE index
815  !! Wrapper for the MPI_alltoall function, includes more generic _V and _W
816  !! versions if given displacements/data types
817  !!
818  !! Generic MPP_TYPE_ implentations:
819  !! <li> @ref mpp_alltoall_ </li>
820  !! <li> @ref mpp_alltoallv_ </li>
821  !! <li> @ref mpp_alltoallw_ </li>
822  !!
823  !> @ingroup mpp_mod
824  interface mpp_alltoall
825  module procedure mpp_alltoall_int4
826  module procedure mpp_alltoall_int8
827  module procedure mpp_alltoall_real4
828  module procedure mpp_alltoall_real8
829 #ifdef OVERLOAD_C4
830  module procedure mpp_alltoall_cmplx4
831 #endif
832 #ifdef OVERLOAD_C8
833  module procedure mpp_alltoall_cmplx8
834 #endif
835  module procedure mpp_alltoall_logical4
836  module procedure mpp_alltoall_logical8
837  module procedure mpp_alltoall_int4_v
838  module procedure mpp_alltoall_int8_v
839  module procedure mpp_alltoall_real4_v
840  module procedure mpp_alltoall_real8_v
841 #ifdef OVERLOAD_C4
842  module procedure mpp_alltoall_cmplx4_v
843 #endif
844 #ifdef OVERLOAD_C8
845  module procedure mpp_alltoall_cmplx8_v
846 #endif
847  module procedure mpp_alltoall_logical4_v
848  module procedure mpp_alltoall_logical8_v
849  module procedure mpp_alltoall_int4_w
850  module procedure mpp_alltoall_int8_w
851  module procedure mpp_alltoall_real4_w
852  module procedure mpp_alltoall_real8_w
853 #ifdef OVERLOAD_C4
854  module procedure mpp_alltoall_cmplx4_w
855 #endif
856 #ifdef OVERLOAD_C8
857  module procedure mpp_alltoall_cmplx8_w
858 #endif
859  module procedure mpp_alltoall_logical4_w
860  module procedure mpp_alltoall_logical8_w
861  end interface
862 
863 
864  !#####################################################################
865  !> @brief Basic message-passing call.
866  !!
867  !> <TT>MPP_TYPE_</TT> corresponds to any 4-byte and 8-byte variant of
868  !! <TT>integer, real, complex, logical</TT> variables, of rank 0 or 1. A
869  !! contiguous block from a multi-dimensional array may be passed by its
870  !! starting address and its length, as in <TT>f77</TT>.
871  !!
872  !! <TT>mpp_transmit</TT> is currently implemented as asynchronous
873  !! outward transmission and synchronous inward transmission. This follows
874  !! the behaviour of <TT>shmem_put</TT> and <TT>shmem_get</TT>. In MPI, it
875  !! is implemented as <TT>mpi_isend</TT> and <TT>mpi_recv</TT>. For most
876  !! applications, transmissions occur in pairs, and are here accomplished
877  !! in a single call.
878  !!
879  !! The special PE designations <TT>NULL_PE</TT>,
880  !! <TT>ANY_PE</TT> and <TT>ALL_PES</TT> are provided by use
881  !! association.
882  !!
883  !! <TT>NULL_PE</TT>: is used to disable one of the pair of
884  !! transmissions.<BR/>
885  !! <TT>ANY_PE</TT>: is used for unspecific remote
886  !! destination. (Please note that <TT>put_pe=ANY_PE</TT> has no meaning
887  !! in the MPI context, though it is available in the SHMEM invocation. If
888  !! portability is a concern, it is best avoided).<BR/>
889  !! <TT>ALL_PES</TT>: is used for broadcast operations.
890  !!
891  !! It is recommended that
892  !! @ref mpp_broadcast be used for
893  !! broadcasts.
894  !!
895  !! The following example illustrates the use of
896  !! <TT>NULL_PE</TT> and <TT>ALL_PES</TT>:
897  !!
898  !! <PRE>
899  !! real, dimension(n) :: a
900  !! if( pe.EQ.0 )then
901  !! do p = 1,npes-1
902  !! call mpp_transmit( a, n, p, a, n, NULL_PE )
903  !! end do
904  !! else
905  !! call mpp_transmit( a, n, NULL_PE, a, n, 0 )
906  !! end if
907  !!
908  !! call mpp_transmit( a, n, ALL_PES, a, n, 0 )
909  !! </PRE>
910  !!
911  !! The do loop and the broadcast operation above are equivalent.
912  !!
913  !! Two overloaded calls <TT>mpp_send</TT> and
914  !! <TT>mpp_recv</TT> have also been
915  !! provided. <TT>mpp_send</TT> calls <TT>mpp_transmit</TT>
916  !! with <TT>get_pe=NULL_PE</TT>. <TT>mpp_recv</TT> calls
917  !! <TT>mpp_transmit</TT> with <TT>put_pe=NULL_PE</TT>. Thus
918  !! the do loop above could be written more succinctly:
919  !!
920  !! <PRE>
921  !! if( pe.EQ.0 )then
922  !! do p = 1,npes-1
923  !! call mpp_send( a, n, p )
924  !! end do
925  !! else
926  !! call mpp_recv( a, n, 0 )
927  !! end if
928  !! </PRE>
929  !! <br>Example call:
930  !! @code{.F90}
931  !! call mpp_transmit( put_data, put_len, put_pe, get_data, get_len, get_pe )
932  !! @endcode
933  !> @ingroup mpp_mod
934  interface mpp_transmit
935  module procedure mpp_transmit_real8
936  module procedure mpp_transmit_real8_scalar
937  module procedure mpp_transmit_real8_2d
938  module procedure mpp_transmit_real8_3d
939  module procedure mpp_transmit_real8_4d
940  module procedure mpp_transmit_real8_5d
941 #ifdef OVERLOAD_C8
942  module procedure mpp_transmit_cmplx8
943  module procedure mpp_transmit_cmplx8_scalar
944  module procedure mpp_transmit_cmplx8_2d
945  module procedure mpp_transmit_cmplx8_3d
946  module procedure mpp_transmit_cmplx8_4d
947  module procedure mpp_transmit_cmplx8_5d
948 #endif
949  module procedure mpp_transmit_int8
950  module procedure mpp_transmit_int8_scalar
951  module procedure mpp_transmit_int8_2d
952  module procedure mpp_transmit_int8_3d
953  module procedure mpp_transmit_int8_4d
954  module procedure mpp_transmit_int8_5d
955  module procedure mpp_transmit_logical8
956  module procedure mpp_transmit_logical8_scalar
957  module procedure mpp_transmit_logical8_2d
958  module procedure mpp_transmit_logical8_3d
959  module procedure mpp_transmit_logical8_4d
960  module procedure mpp_transmit_logical8_5d
961 
962  module procedure mpp_transmit_real4
963  module procedure mpp_transmit_real4_scalar
964  module procedure mpp_transmit_real4_2d
965  module procedure mpp_transmit_real4_3d
966  module procedure mpp_transmit_real4_4d
967  module procedure mpp_transmit_real4_5d
968 
969 #ifdef OVERLOAD_C4
970  module procedure mpp_transmit_cmplx4
971  module procedure mpp_transmit_cmplx4_scalar
972  module procedure mpp_transmit_cmplx4_2d
973  module procedure mpp_transmit_cmplx4_3d
974  module procedure mpp_transmit_cmplx4_4d
975  module procedure mpp_transmit_cmplx4_5d
976 #endif
977  module procedure mpp_transmit_int4
978  module procedure mpp_transmit_int4_scalar
979  module procedure mpp_transmit_int4_2d
980  module procedure mpp_transmit_int4_3d
981  module procedure mpp_transmit_int4_4d
982  module procedure mpp_transmit_int4_5d
983  module procedure mpp_transmit_logical4
984  module procedure mpp_transmit_logical4_scalar
985  module procedure mpp_transmit_logical4_2d
986  module procedure mpp_transmit_logical4_3d
987  module procedure mpp_transmit_logical4_4d
988  module procedure mpp_transmit_logical4_5d
989  end interface
990  !> @brief Receive data from another PE
991  !!
992  !> @param[out] get_data scalar or array to get written with received data
993  !> @param get_len size of array to recv from get_data
994  !> @param from_pe PE number to receive from
995  !> @param block true for blocking, false for non-blocking. Defaults to true
996  !> @param tag communication tag
997  !> @param[out] request MPI request handle
998  !> @ingroup mpp_mod
999  interface mpp_recv
1000  module procedure mpp_recv_real8
1001  module procedure mpp_recv_real8_scalar
1002  module procedure mpp_recv_real8_2d
1003  module procedure mpp_recv_real8_3d
1004  module procedure mpp_recv_real8_4d
1005  module procedure mpp_recv_real8_5d
1006 #ifdef OVERLOAD_C8
1007  module procedure mpp_recv_cmplx8
1008  module procedure mpp_recv_cmplx8_scalar
1009  module procedure mpp_recv_cmplx8_2d
1010  module procedure mpp_recv_cmplx8_3d
1011  module procedure mpp_recv_cmplx8_4d
1012  module procedure mpp_recv_cmplx8_5d
1013 #endif
1014  module procedure mpp_recv_int8
1015  module procedure mpp_recv_int8_scalar
1016  module procedure mpp_recv_int8_2d
1017  module procedure mpp_recv_int8_3d
1018  module procedure mpp_recv_int8_4d
1019  module procedure mpp_recv_int8_5d
1020  module procedure mpp_recv_logical8
1021  module procedure mpp_recv_logical8_scalar
1022  module procedure mpp_recv_logical8_2d
1023  module procedure mpp_recv_logical8_3d
1024  module procedure mpp_recv_logical8_4d
1025  module procedure mpp_recv_logical8_5d
1026 
1027  module procedure mpp_recv_real4
1028  module procedure mpp_recv_real4_scalar
1029  module procedure mpp_recv_real4_2d
1030  module procedure mpp_recv_real4_3d
1031  module procedure mpp_recv_real4_4d
1032  module procedure mpp_recv_real4_5d
1033 
1034 #ifdef OVERLOAD_C4
1035  module procedure mpp_recv_cmplx4
1036  module procedure mpp_recv_cmplx4_scalar
1037  module procedure mpp_recv_cmplx4_2d
1038  module procedure mpp_recv_cmplx4_3d
1039  module procedure mpp_recv_cmplx4_4d
1040  module procedure mpp_recv_cmplx4_5d
1041 #endif
1042  module procedure mpp_recv_int4
1043  module procedure mpp_recv_int4_scalar
1044  module procedure mpp_recv_int4_2d
1045  module procedure mpp_recv_int4_3d
1046  module procedure mpp_recv_int4_4d
1047  module procedure mpp_recv_int4_5d
1048  module procedure mpp_recv_logical4
1049  module procedure mpp_recv_logical4_scalar
1050  module procedure mpp_recv_logical4_2d
1051  module procedure mpp_recv_logical4_3d
1052  module procedure mpp_recv_logical4_4d
1053  module procedure mpp_recv_logical4_5d
1054  end interface
1055  !> Send data to a receiving PE.
1056  !!
1057  !> @param put_data scalar or array to get sent to a receiving PE
1058  !> @param put_len size of data to send from put_data
1059  !> @param to_pe PE number to send to
1060  !> @param block true for blocking, false for non-blocking. Defaults to true
1061  !> @param tag communication tag
1062  !> @param[out] request MPI request handle
1063  !! <br> Example usage:
1064  !! @code{.F90} call mpp_send(data, ie, pe) @endcode
1065  !> @ingroup mpp_mod
1066  interface mpp_send
1067  module procedure mpp_send_real8
1068  module procedure mpp_send_real8_scalar
1069  module procedure mpp_send_real8_2d
1070  module procedure mpp_send_real8_3d
1071  module procedure mpp_send_real8_4d
1072  module procedure mpp_send_real8_5d
1073 #ifdef OVERLOAD_C8
1074  module procedure mpp_send_cmplx8
1075  module procedure mpp_send_cmplx8_scalar
1076  module procedure mpp_send_cmplx8_2d
1077  module procedure mpp_send_cmplx8_3d
1078  module procedure mpp_send_cmplx8_4d
1079  module procedure mpp_send_cmplx8_5d
1080 #endif
1081  module procedure mpp_send_int8
1082  module procedure mpp_send_int8_scalar
1083  module procedure mpp_send_int8_2d
1084  module procedure mpp_send_int8_3d
1085  module procedure mpp_send_int8_4d
1086  module procedure mpp_send_int8_5d
1087  module procedure mpp_send_logical8
1088  module procedure mpp_send_logical8_scalar
1089  module procedure mpp_send_logical8_2d
1090  module procedure mpp_send_logical8_3d
1091  module procedure mpp_send_logical8_4d
1092  module procedure mpp_send_logical8_5d
1093 
1094  module procedure mpp_send_real4
1095  module procedure mpp_send_real4_scalar
1096  module procedure mpp_send_real4_2d
1097  module procedure mpp_send_real4_3d
1098  module procedure mpp_send_real4_4d
1099  module procedure mpp_send_real4_5d
1100 
1101 #ifdef OVERLOAD_C4
1102  module procedure mpp_send_cmplx4
1103  module procedure mpp_send_cmplx4_scalar
1104  module procedure mpp_send_cmplx4_2d
1105  module procedure mpp_send_cmplx4_3d
1106  module procedure mpp_send_cmplx4_4d
1107  module procedure mpp_send_cmplx4_5d
1108 #endif
1109  module procedure mpp_send_int4
1110  module procedure mpp_send_int4_scalar
1111  module procedure mpp_send_int4_2d
1112  module procedure mpp_send_int4_3d
1113  module procedure mpp_send_int4_4d
1114  module procedure mpp_send_int4_5d
1115  module procedure mpp_send_logical4
1116  module procedure mpp_send_logical4_scalar
1117  module procedure mpp_send_logical4_2d
1118  module procedure mpp_send_logical4_3d
1119  module procedure mpp_send_logical4_4d
1120  module procedure mpp_send_logical4_5d
1121  end interface
1122 
1123 
1124  !> @brief Perform parallel broadcasts
1125  !!
1126  !> The <TT>mpp_broadcast</TT> call has been added because the original
1127  !! syntax (using <TT>ALL_PES</TT> in <TT>mpp_transmit</TT>) did not
1128  !! support a broadcast across a pelist.
1129  !!
1130  !! <TT>MPP_TYPE_</TT> corresponds to any 4-byte and 8-byte variant of
1131  !! <TT>integer, real, complex, logical</TT> variables, of rank 0 or 1. A
1132  !! contiguous block from a multi-dimensional array may be passed by its
1133  !! starting address and its length, as in <TT>f77</TT>.
1134  !!
1135  !! Global broadcasts through the <TT>ALL_PES</TT> argument to
1136  !! @ref mpp_transmit are still provided for
1137  !! backward-compatibility.
1138  !!
1139  !! If <TT>pelist</TT> is omitted, the context is assumed to be the
1140  !! current pelist. <TT>from_pe</TT> must belong to the current
1141  !! pelist. This call implies synchronization across the PEs in
1142  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
1143  !!
1144  !! <br>Example usage:
1145  !!
1146  !! call mpp_broadcast( data, length, from_pe, pelist )
1147  !!
1148  !> @param[inout] data Data to broadcast
1149  !> @param length Length of data to broadcast
1150  !> @param from_pe PE to send the data from
1151  !> @param pelist List of PE's to broadcast across, if not provided uses current list
1152  !> @ingroup mpp_mod
1153  interface mpp_broadcast
1154  module procedure mpp_broadcast_char
1155  module procedure mpp_broadcast_real8
1156  module procedure mpp_broadcast_real8_scalar
1157  module procedure mpp_broadcast_real8_2d
1158  module procedure mpp_broadcast_real8_3d
1159  module procedure mpp_broadcast_real8_4d
1160  module procedure mpp_broadcast_real8_5d
1161 #ifdef OVERLOAD_C8
1162  module procedure mpp_broadcast_cmplx8
1163  module procedure mpp_broadcast_cmplx8_scalar
1164  module procedure mpp_broadcast_cmplx8_2d
1165  module procedure mpp_broadcast_cmplx8_3d
1166  module procedure mpp_broadcast_cmplx8_4d
1167  module procedure mpp_broadcast_cmplx8_5d
1168 #endif
1169  module procedure mpp_broadcast_int8
1170  module procedure mpp_broadcast_int8_scalar
1171  module procedure mpp_broadcast_int8_2d
1172  module procedure mpp_broadcast_int8_3d
1173  module procedure mpp_broadcast_int8_4d
1174  module procedure mpp_broadcast_int8_5d
1175  module procedure mpp_broadcast_logical8
1176  module procedure mpp_broadcast_logical8_scalar
1177  module procedure mpp_broadcast_logical8_2d
1178  module procedure mpp_broadcast_logical8_3d
1179  module procedure mpp_broadcast_logical8_4d
1180  module procedure mpp_broadcast_logical8_5d
1181 
1182  module procedure mpp_broadcast_real4
1183  module procedure mpp_broadcast_real4_scalar
1184  module procedure mpp_broadcast_real4_2d
1185  module procedure mpp_broadcast_real4_3d
1186  module procedure mpp_broadcast_real4_4d
1187  module procedure mpp_broadcast_real4_5d
1188 
1189 #ifdef OVERLOAD_C4
1190  module procedure mpp_broadcast_cmplx4
1191  module procedure mpp_broadcast_cmplx4_scalar
1192  module procedure mpp_broadcast_cmplx4_2d
1193  module procedure mpp_broadcast_cmplx4_3d
1194  module procedure mpp_broadcast_cmplx4_4d
1195  module procedure mpp_broadcast_cmplx4_5d
1196 #endif
1197  module procedure mpp_broadcast_int4
1198  module procedure mpp_broadcast_int4_scalar
1199  module procedure mpp_broadcast_int4_2d
1200  module procedure mpp_broadcast_int4_3d
1201  module procedure mpp_broadcast_int4_4d
1202  module procedure mpp_broadcast_int4_5d
1203  module procedure mpp_broadcast_logical4
1204  module procedure mpp_broadcast_logical4_scalar
1205  module procedure mpp_broadcast_logical4_2d
1206  module procedure mpp_broadcast_logical4_3d
1207  module procedure mpp_broadcast_logical4_4d
1208  module procedure mpp_broadcast_logical4_5d
1209  end interface
1210 
1211  !#####################################################################
1212 
1213  !> @brief Calculate parallel checksums
1214  !!
1215  !> \e mpp_chksum is a parallel checksum routine that returns an
1216  !! identical answer for the same array irrespective of how it has been
1217  !! partitioned across processors. \e int_kind is the KIND
1218  !! parameter corresponding to long integers (see discussion on
1219  !! OS-dependent preprocessor directives) defined in
1220  !! the file platform.F90. \e MPP_TYPE_ corresponds to any
1221  !! 4-byte and 8-byte variant of \e integer, \e real, \e complex, \e logical
1222  !! variables, of rank 0 to 5.
1223  !!
1224  !! Integer checksums on FP data use the F90 <TT>TRANSFER()</TT>
1225  !! intrinsic.
1226  !!
1227  !! This provides identical results on a single-processor job, and to perform
1228  !! serial checksums on a single processor of a parallel job, you only
1229  !! need to use the optional <TT>pelist</TT> argument.
1230  !! <PRE>
1231  !! use mpp_mod
1232  !! integer :: pe, chksum
1233  !! real :: a(:)
1234  !! pe = mpp_pe()
1235  !! chksum = mpp_chksum( a, (/pe/) )
1236  !! </PRE>
1237  !!
1238  !! The additional functionality of <TT>mpp_chksum</TT> over
1239  !! serial checksums is to compute the checksum across the PEs in
1240  !! <TT>pelist</TT>. The answer is guaranteed to be the same for
1241  !! the same distributed array irrespective of how it has been
1242  !! partitioned.
1243  !!
1244  !! If <TT>pelist</TT> is omitted, the context is assumed to be the
1245  !! current pelist. This call implies synchronization across the PEs in
1246  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
1247  !! <br> Example usage:
1248  !!
1249  !! mpp_chksum( var, pelist )
1250  !!
1251  !! @param var Data to calculate checksum of
1252  !! @param pelist Optional list of PE's to include in checksum calculation if not using
1253  !! current pelist
1254  !! @return Parallel checksum of var across given or implicit pelist
1255  !!
1256  !! Generic MPP_TYPE_ implentations:
1257  !! <li> @ref mpp_chksum_</li>
1258  !! <li> @ref mpp_chksum_int_</li>
1259  !! <li> @ref mpp_chksum_int_rmask_</li>
1260  !!
1261  !> @ingroup mpp_mod
1262  interface mpp_chksum
1263  module procedure mpp_chksum_i8_1d
1264  module procedure mpp_chksum_i8_2d
1265  module procedure mpp_chksum_i8_3d
1266  module procedure mpp_chksum_i8_4d
1267  module procedure mpp_chksum_i8_5d
1268  module procedure mpp_chksum_i8_1d_rmask
1269  module procedure mpp_chksum_i8_2d_rmask
1270  module procedure mpp_chksum_i8_3d_rmask
1271  module procedure mpp_chksum_i8_4d_rmask
1272  module procedure mpp_chksum_i8_5d_rmask
1273 
1274  module procedure mpp_chksum_i4_1d
1275  module procedure mpp_chksum_i4_2d
1276  module procedure mpp_chksum_i4_3d
1277  module procedure mpp_chksum_i4_4d
1278  module procedure mpp_chksum_i4_5d
1279  module procedure mpp_chksum_i4_1d_rmask
1280  module procedure mpp_chksum_i4_2d_rmask
1281  module procedure mpp_chksum_i4_3d_rmask
1282  module procedure mpp_chksum_i4_4d_rmask
1283  module procedure mpp_chksum_i4_5d_rmask
1284 
1285  module procedure mpp_chksum_r8_0d
1286  module procedure mpp_chksum_r8_1d
1287  module procedure mpp_chksum_r8_2d
1288  module procedure mpp_chksum_r8_3d
1289  module procedure mpp_chksum_r8_4d
1290  module procedure mpp_chksum_r8_5d
1291 
1292  module procedure mpp_chksum_r4_0d
1293  module procedure mpp_chksum_r4_1d
1294  module procedure mpp_chksum_r4_2d
1295  module procedure mpp_chksum_r4_3d
1296  module procedure mpp_chksum_r4_4d
1297  module procedure mpp_chksum_r4_5d
1298 #ifdef OVERLOAD_C8
1299  module procedure mpp_chksum_c8_0d
1300  module procedure mpp_chksum_c8_1d
1301  module procedure mpp_chksum_c8_2d
1302  module procedure mpp_chksum_c8_3d
1303  module procedure mpp_chksum_c8_4d
1304  module procedure mpp_chksum_c8_5d
1305 #endif
1306 #ifdef OVERLOAD_C4
1307  module procedure mpp_chksum_c4_0d
1308  module procedure mpp_chksum_c4_1d
1309  module procedure mpp_chksum_c4_2d
1310  module procedure mpp_chksum_c4_3d
1311  module procedure mpp_chksum_c4_4d
1312  module procedure mpp_chksum_c4_5d
1313 #endif
1314  end interface
1315 
1316 !> @addtogroup mpp_mod
1317 !> @{
1318 !***********************************************************************
1319 !
1320 ! module variables
1321 !
1322 !***********************************************************************
1323  integer, parameter :: PESET_MAX = 10000
1324  integer :: current_peset_max = 32
1325  type(communicator), allocatable :: peset(:) !< Will be allocated starting from 0, 0 is a dummy used
1326  !! to hold single-PE "self" communicator
1327  logical :: module_is_initialized = .false.
1328  logical :: debug = .false.
1329  integer :: npes=1, root_pe=0, pe=0
1330  integer(i8_kind) :: tick, ticks_per_sec, max_ticks, start_tick, end_tick, tick0=0
1331  type(mpi_comm) :: mpp_comm_private
1332  logical :: first_call_system_clock_mpi=.true.
1333  real(r8_kind) :: mpi_count0=0 !< use to prevent integer overflow
1334  real(r8_kind) :: mpi_tick_rate=0.d0 !< clock rate for mpi_wtick()
1335  logical :: mpp_record_timing_data=.true.
1336  type(clock),save :: clocks(max_clocks)
1337  integer :: log_unit, etc_unit
1338  integer :: warn_unit !< unit number of the warning log
1339  character(len=32), parameter :: configfile='logfile'
1340  character(len=32), parameter :: warnfile='warnfile' !< base name for warninglog (appends ".<PE>.out")
1341  integer :: peset_num=0, current_peset_num=0
1342  integer :: world_peset_num !<the world communicator
1343  integer :: error
1344  integer :: clock_num=0, num_clock_ids=0,current_clock=0, previous_clock(max_clocks)=0
1345  real :: tick_rate
1346 
1347  type(mpp_type_list) :: datatypes
1348  type(mpp_type), target :: mpp_byte
1349 
1350  integer :: cur_send_request = 0
1351  integer :: cur_recv_request = 0
1352  type(mpi_request), allocatable :: request_send(:)
1353  type(mpi_request), allocatable :: request_recv(:)
1354  type(mpi_datatype), allocatable :: type_recv(:)
1355  integer, allocatable :: size_recv(:)
1356 ! if you want to save the non-root PE information uncomment out the following line
1357 ! and comment out the assigment of etcfile to '/dev/null'
1358 #ifdef NO_DEV_NULL
1359  character(len=32) :: etcfile='._mpp.nonrootpe.msgs'
1360 #else
1361  character(len=32) :: etcfile='/dev/null'
1362 #endif
1363 
1364 !> Use the intrinsics in iso_fortran_env
1365  integer :: in_unit=input_unit, out_unit=output_unit, err_unit=error_unit
1366  integer :: stdout_unit
1367 
1368  !--- variables used in mpp_util.h
1369  type(summary_struct) :: clock_summary(max_clocks)
1370  logical :: warnings_are_fatal = .false.
1371  integer :: error_state=0
1372  integer :: clock_grain=clock_loop-1
1373 
1374  !--- variables used in mpp_comm.h
1375  integer :: clock0 !<measures total runtime from mpp_init to mpp_exit
1376  integer :: mpp_stack_size=0, mpp_stack_hwm=0
1377  logical :: verbose=.false.
1378 
1379  integer :: get_len_nocomm = 0 !< needed for mpp_transmit_nocomm.h
1380 
1381  !--- variables used in mpp_comm_mpi.inc
1382  integer, parameter :: mpp_init_test_full_init = -1
1383  integer, parameter :: mpp_init_test_init_true_only = 0
1384  integer, parameter :: mpp_init_test_peset_allocated = 1
1385  integer, parameter :: mpp_init_test_clocks_init = 2
1386  integer, parameter :: mpp_init_test_datatype_list_init = 3
1387  integer, parameter :: mpp_init_test_logfile_init = 4
1388  integer, parameter :: mpp_init_test_read_namelist = 5
1389  integer, parameter :: mpp_init_test_etc_unit = 6
1390  integer, parameter :: mpp_init_test_requests_allocated = 7
1391 
1392  !> MPP_INFO_NULL acts as an analagous mpp-macro for MPI_INFO_NULL to share with fms2_io NetCDF4
1393  !! mpi-io. Intel MPI and MPICH provide a value of 469762048. OpenMPI provides a value of 0.
1394  integer, parameter :: mpp_info_null = mpi_info_null%mpi_val
1395 
1396  !> MPP_COMM_NULL acts as an analagous mpp-macro for MPI_COMM_NULL to share with fms2_io NetCDF4
1397  !! mpi-io. Intel MPI and MPICH provide a value of 67108864. OpenMPI provides a value of 0.
1398  integer, parameter :: mpp_comm_null = mpi_comm_null%mpi_val
1399 
1400 !***********************************************************************
1401 ! variables needed for subroutine read_input_nml (include/mpp_util.inc)
1402 !
1403 ! public variable needed for reading input nml file from an internal file
1404  character(len=:), dimension(:), allocatable, target, public :: input_nml_file
1405  logical :: read_ascii_file_on = .false.
1406 !***********************************************************************
1407 
1408 ! Include variable "version" to be written to log file.
1409 #include<file_version.h>
1410  public version
1411 
1412  integer, parameter :: max_request_min = 10000
1413  integer :: request_multiply = 20
1414 
1415  logical :: etc_unit_is_stderr = .false.
1416  integer :: max_request = 0
1417  logical :: sync_all_clocks = .false.
1418  namelist /mpp_nml/ etc_unit_is_stderr, request_multiply, mpp_record_timing_data, sync_all_clocks
1419 
1420  contains
1421 #include <system_clock.fh>
1422 #include <mpp_util.inc>
1423 #include <mpp_comm.inc>
1424 
1425  end module mpp_mod
1426 !> @}
1427 ! close documentation grouping
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 warn_unit
unit number of the warning log
Definition: mpp.F90:1338
subroutine mpp_error_basic(errortype, errormsg)
A very basic error handler uses ABORT and FLUSH calls, may need to use cpp to rename.
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:42
subroutine read_ascii_file(FILENAME, LENGTH, Content, PELIST)
Reads any ascii file into a character array and broadcasts it to the non-root mpi-tasks....
Definition: mpp_util.inc:1469
subroutine mpp_init_legacy(flags, localcomm, test_level, alt_input_nml_path)
Definition: mpp_comm.inc:28
subroutine mpp_error_mesg(routine, errormsg, errortype)
overloads to mpp_error_basic, support for error_mesg routine in FMS
Definition: mpp_util.inc:174
subroutine mpp_set_current_pelist(pelist, no_sync)
Set context pelist.
Definition: mpp_util.inc:514
integer, parameter, public mpp_comm_null
MPP_COMM_NULL acts as an analagous mpp-macro for MPI_COMM_NULL to share with fms2_io NetCDF4 mpi-io....
Definition: mpp.F90:1398
integer get_len_nocomm
needed for mpp_transmit_nocomm.h
Definition: mpp.F90:1379
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
Definition: mpp_util.inc:50
subroutine read_input_nml(pelist_name_in, alt_input_nml_path)
Reads an existing input nml file into a character array and broadcasts it to the non-root mpi-tasks....
Definition: mpp_util.inc:1250
character(len=32), parameter warnfile
base name for warninglog (appends ".<PE>.out")
Definition: mpp.F90:1340
subroutine inverse_permutation(x, y)
Produce an inverse permutation. For example, transform [2, 3, 1, 4] to [3, 1, 2, 4].
Definition: mpp_util.inc:1574
type(communicator), dimension(:), allocatable peset
Will be allocated starting from 0, 0 is a dummy used to hold single-PE "self" communicator.
Definition: mpp.F90:1325
subroutine mpp_type_free(dtype)
Deallocates memory for mpp_type objects @TODO This should probably not take a pointer,...
integer, parameter, public mpp_info_null
MPP_INFO_NULL acts as an analagous mpp-macro for MPI_INFO_NULL to share with fms2_io NetCDF4 mpi-io....
Definition: mpp.F90:1394
integer clock0
measures total runtime from mpp_init to mpp_exit
Definition: mpp.F90:1375
subroutine mpp_clock_set_grain(grain)
Set the level of granularity of timing measurements.
Definition: mpp_util.inc:672
real(r8_kind) mpi_tick_rate
clock rate for mpi_wtick()
Definition: mpp.F90:1334
integer world_peset_num
the world communicator
Definition: mpp.F90:1342
subroutine mpp_exit()
Finalizes process termination. To be called at the end of a run. Certain mpi implementations(openmpi)...
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:58
subroutine mpp_init_f08(flags, localcomm, test_level, alt_input_nml_path)
Initialize the mpp_mod module. Must be called before any usage.
integer in_unit
Use the intrinsics in iso_fortran_env.
Definition: mpp.F90:1365
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:420
subroutine mpp_set_stack_size(n)
Set the mpp_stack variable to be at least n LONG words long.
integer function, dimension(2) get_ascii_file_num_lines_and_length(FILENAME, PELIST)
Function to determine the maximum line length and number of lines from an ascii file.
Definition: mpp_util.inc:1376
real(r8_kind) mpi_count0
use to prevent integer overflow
Definition: mpp.F90:1333
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
integer function mpp_clock_id(name, flags, grain)
Return an ID for a new or existing clock.
Definition: mpp_util.inc:736
integer function warnlog()
This function returns unit number for the warning log if on the root pe, otherwise returns the etc_un...
Definition: mpp_util.inc:140
subroutine mpp_broadcast_char(char_data, length, from_pe, pelist)
Broadcasts a character string from the given pe to it's pelist.
integer function stdin()
This function returns the current standard fortran unit numbers for input.
Definition: mpp_util.inc:35
subroutine mpp_declare_pelist_f08(pelist, name, comm)
Declare a pelist.
Definition: mpp_util.inc:475
Takes a given integer or real array and returns it as a string.
Definition: mpp.F90:415
Scatter a vector across all PEs.
Definition: mpp.F90:824
Perform parallel broadcasts.
Definition: mpp.F90:1153
Calculate parallel checksums.
Definition: mpp.F90:1262
Error handler.
Definition: mpp.F90:385
Gather data sent from pelist onto the root pe Wrapper for MPI_gather, can be used with and without in...
Definition: mpp.F90:728
Reduction operations. Find the max of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:568
Reduction operations. Find the min of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:590
Receive data from another PE.
Definition: mpp.F90:999
Scatter (ie - is) * (je - js) contiguous elements of array data from the designated root pe into cont...
Definition: mpp.F90:788
Send data to a receiving PE.
Definition: mpp.F90:1066
Reduction operation.
Definition: mpp.F90:627
Calculates sum of a given numerical array across pe's for adjoint domains.
Definition: mpp.F90:672
Basic message-passing call.
Definition: mpp.F90:934
Create a mpp_type variable.
Definition: mpp.F90:540
a clock contains an array of event profiles for a region
Definition: mpp.F90:253
Summary of information from a clock run.
Definition: mpp.F90:269
Communication information for message passing libraries.
Definition: mpp.F90:232
Communication event profile.
Definition: mpp.F90:244
Data types for generalized data transfer (e.g. MPI_Type)
Definition: mpp.F90:290
Persisent elements for linked list interaction.
Definition: mpp.F90:306
holds name and clock data for use in mpp_util.h
Definition: mpp.F90:282
Declare a pelist. The two flavors of this subroutine differ in the type of their comm/commID argument...
Definition: mpp.F90:424
Get the current pelist. The two flavors of this subroutine differ in the type of their comm/commID ar...
Definition: mpp.F90:433