FMS  2026.03
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 !***********************************************************************
421 !
422 ! public interface from mpp_comm.h
423 !
424 !***********************************************************************
425 
426 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
427  ! !
428  ! ROUTINES TO INITIALIZE/FINALIZE MPP MODULE: mpp_init, mpp_exit !
429  ! !
430 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
431 
432 !> @fn mpp_mod::mpp_init::mpp_init( flags, localcomm, test_level)
433 !> @ingroup mpp_mod
434 !> @brief Initialize @ref mpp_mod
435 !!
436 !> Called to initialize the <TT>mpp_mod</TT> package. It is recommended
437 !! that this call be the first executed line in your program. It sets the
438 !! number of PEs assigned to this run (acquired from the command line, or
439 !! through the environment variable <TT>NPES</TT>), and associates an ID
440 !! number to each PE. These can be accessed by calling @ref mpp_npes and
441 !! @ref mpp_pe.
442 !! <br> Example usage:
443 !!
444 !! call mpp_init( flags )
445 !!
446 !! @param flags
447 !! <TT>flags</TT> can be set to <TT>MPP_VERBOSE</TT> to
448 !! have <TT>mpp_mod</TT> keep you informed of what it's up to.
449 !! @param localcomm
450 !! This is a type(mpi_comm) in mpp_init_f08, and an integer in mpp_init_legacy.
451 !! This argument should only be used if MPI has previously been initialized by
452 !! an external call to MPI_Init.
453 !! @param test_level
454 !! Debugging flag to set amount of initialization tasks performed
455  interface mpp_init
456  module procedure mpp_init_f08
457  module procedure mpp_init_legacy
458  end interface
459 
460 !> @fn mpp_mod::mpp_exit()
461 !> @brief Exit <TT>@ref mpp_mod</TT>.
462 !!
463 !> Called at the end of the run, or to re-initialize <TT>mpp_mod</TT>,
464 !! should you require that for some odd reason.
465 !!
466 !! This call implies synchronization across all PEs.
467 !!
468 !! <br>Example usage:
469 !!
470 !! call mpp_exit()
471 !> @ingroup mpp_mod
472 
473  !#####################################################################
474 
475  !> @fn subroutine mpp_set_stack_size(n)
476  !> @brief Allocate module internal workspace.
477  !> @param Integer to set stack size to(in words)
478  !> <TT>mpp_mod</TT> maintains a private internal array called
479  !! <TT>mpp_stack</TT> for private workspace. This call sets the length,
480  !! in words, of this array.
481  !!
482  !! The <TT>mpp_init</TT> call sets this
483  !! workspace length to a default of 32768, and this call may be used if a
484  !! longer workspace is needed.
485  !!
486  !! This call implies synchronization across all PEs.
487  !!
488  !! This workspace is symmetrically allocated, as required for
489  !! efficient communication on SGI and Cray MPP systems. Since symmetric
490  !! allocation must be performed by <I>all</I> PEs in a job, this call
491  !! must also be called by all PEs, using the same value of
492  !! <TT>n</TT>. Calling <TT>mpp_set_stack_size</TT> from a subset of PEs,
493  !! or with unequal argument <TT>n</TT>, may cause the program to hang.
494  !!
495  !! If any MPP call using <TT>mpp_stack</TT> overflows the declared
496  !! stack array, the program will abort with a message specifying the
497  !! stack length that is required. Many users wonder why, if the required
498  !! stack length can be computed, it cannot also be specified at that
499  !! point. This cannot be automated because there is no way for the
500  !! program to know if all PEs are present at that call, and with equal
501  !! values of <TT>n</TT>. The program must be rerun by the user with the
502  !! correct argument to <TT>mpp_set_stack_size</TT>, called at an
503  !! appropriate point in the code where all PEs are known to be present.
504  !! @verbose call mpp_set_stack_size(n)
505  !!
506  !> @ingroup mpp_mod
507  public :: mpp_set_stack_size
508  ! from mpp_util.h
509 
510 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
511 ! !
512 ! DATA TRANSFER TYPES: mpp_type_create !
513 ! !
514 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
515 
516  !> @brief Create a mpp_type variable
517  !> @param[in] field A field of any numerical or logical type
518  !> @param[in] array_of_subsizes Integer array of subsizes
519  !> @param[in] array_of_starts Integer array of starts
520  !> @param[out] dtype_out Output variable for created @ref mpp_type
521  !> @ingroup mpp_mod
522  interface mpp_type_create
523  module procedure mpp_type_create_int4
524  module procedure mpp_type_create_int8
525  module procedure mpp_type_create_real4
526  module procedure mpp_type_create_real8
527  module procedure mpp_type_create_cmplx4
528  module procedure mpp_type_create_cmplx8
529  module procedure mpp_type_create_logical4
530  module procedure mpp_type_create_logical8
531  end interface mpp_type_create
532 
533 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
534  ! !
535  ! GLOBAL REDUCTION ROUTINES: mpp_max, mpp_sum, mpp_min !
536  ! !
537 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
538 
539  !> @brief Reduction operations.
540  !> Find the max of scalar a from the PEs in pelist
541  !! result is also automatically broadcast to all PEs
542  !! @code{.F90}
543  !! call mpp_max( a, pelist )
544  !! @endcode
545  !> @param a <TT>real</TT> or <TT>integer</TT>, of 4-byte of 8-byte kind.
546  !> @param pelist If <TT>pelist</TT> is omitted, the context is assumed to be the
547  !! current pelist. This call implies synchronization across the PEs in
548  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
549  !> @ingroup mpp_mod
550  interface mpp_max
551  module procedure mpp_max_real8_0d
552  module procedure mpp_max_real8_1d
553  module procedure mpp_max_int8_0d
554  module procedure mpp_max_int8_1d
555  module procedure mpp_max_real4_0d
556  module procedure mpp_max_real4_1d
557  module procedure mpp_max_int4_0d
558  module procedure mpp_max_int4_1d
559  end interface
560 
561  !> @brief Reduction operations.
562  !> Find the min of scalar a from the PEs in pelist
563  !! result is also automatically broadcast to all PEs
564  !! @code{.F90}
565  !! call mpp_min( a, pelist )
566  !! @endcode
567  !> @param a <TT>real</TT> or <TT>integer</TT>, of 4-byte of 8-byte kind.
568  !> @param pelist If <TT>pelist</TT> is omitted, the context is assumed to be the
569  !! current pelist. This call implies synchronization across the PEs in
570  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
571  !> @ingroup mpp_mod
572  interface mpp_min
573  module procedure mpp_min_real8_0d
574  module procedure mpp_min_real8_1d
575  module procedure mpp_min_int8_0d
576  module procedure mpp_min_int8_1d
577  module procedure mpp_min_real4_0d
578  module procedure mpp_min_real4_1d
579  module procedure mpp_min_int4_0d
580  module procedure mpp_min_int4_1d
581  end interface
582 
583 
584  !> @brief Reduction operation.
585  !!
586  !> <TT>MPP_TYPE_</TT> corresponds to any 4-byte and 8-byte variant of
587  !! <TT>integer, real, complex</TT> variables, of rank 0 or 1. A
588  !! contiguous block from a multi-dimensional array may be passed by its
589  !! starting address and its length, as in <TT>f77</TT>.
590  !!
591  !! Library reduction operators are not required or guaranteed to be
592  !! bit-reproducible. In any case, changing the processor count changes
593  !! the data layout, and thus very likely the order of operations. For
594  !! bit-reproducible sums of distributed arrays, consider using the
595  !! <TT>mpp_global_sum</TT> routine provided by the
596  !! @ref mpp_domains module.
597  !!
598  !! The <TT>bit_reproducible</TT> flag provided in earlier versions of
599  !! this routine has been removed.
600  !!
601  !!
602  !! If <TT>pelist</TT> is omitted, the context is assumed to be the
603  !! current pelist. This call implies synchronization across the PEs in
604  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
605  !! Example usage:
606  !! call mpp_sum( a, length, pelist )
607  !!
608  !> @ingroup mpp_mod
609  interface mpp_sum
610  module procedure mpp_sum_int8
611  module procedure mpp_sum_int8_scalar
612  module procedure mpp_sum_int8_2d
613  module procedure mpp_sum_int8_3d
614  module procedure mpp_sum_int8_4d
615  module procedure mpp_sum_int8_5d
616  module procedure mpp_sum_real8
617  module procedure mpp_sum_real8_scalar
618  module procedure mpp_sum_real8_2d
619  module procedure mpp_sum_real8_3d
620  module procedure mpp_sum_real8_4d
621  module procedure mpp_sum_real8_5d
622 #ifdef OVERLOAD_C8
623  module procedure mpp_sum_cmplx8
624  module procedure mpp_sum_cmplx8_scalar
625  module procedure mpp_sum_cmplx8_2d
626  module procedure mpp_sum_cmplx8_3d
627  module procedure mpp_sum_cmplx8_4d
628  module procedure mpp_sum_cmplx8_5d
629 #endif
630  module procedure mpp_sum_int4
631  module procedure mpp_sum_int4_scalar
632  module procedure mpp_sum_int4_2d
633  module procedure mpp_sum_int4_3d
634  module procedure mpp_sum_int4_4d
635  module procedure mpp_sum_int4_5d
636  module procedure mpp_sum_real4
637  module procedure mpp_sum_real4_scalar
638  module procedure mpp_sum_real4_2d
639  module procedure mpp_sum_real4_3d
640  module procedure mpp_sum_real4_4d
641  module procedure mpp_sum_real4_5d
642 #ifdef OVERLOAD_C4
643  module procedure mpp_sum_cmplx4
644  module procedure mpp_sum_cmplx4_scalar
645  module procedure mpp_sum_cmplx4_2d
646  module procedure mpp_sum_cmplx4_3d
647  module procedure mpp_sum_cmplx4_4d
648  module procedure mpp_sum_cmplx4_5d
649 #endif
650  end interface
651 
652  !> Calculates sum of a given numerical array across pe's for adjoint domains
653  !> @ingroup mpp_mod
654  interface mpp_sum_ad
655  module procedure mpp_sum_int8_ad
656  module procedure mpp_sum_int8_scalar_ad
657  module procedure mpp_sum_int8_2d_ad
658  module procedure mpp_sum_int8_3d_ad
659  module procedure mpp_sum_int8_4d_ad
660  module procedure mpp_sum_int8_5d_ad
661  module procedure mpp_sum_real8_ad
662  module procedure mpp_sum_real8_scalar_ad
663  module procedure mpp_sum_real8_2d_ad
664  module procedure mpp_sum_real8_3d_ad
665  module procedure mpp_sum_real8_4d_ad
666  module procedure mpp_sum_real8_5d_ad
667 #ifdef OVERLOAD_C8
668  module procedure mpp_sum_cmplx8_ad
669  module procedure mpp_sum_cmplx8_scalar_ad
670  module procedure mpp_sum_cmplx8_2d_ad
671  module procedure mpp_sum_cmplx8_3d_ad
672  module procedure mpp_sum_cmplx8_4d_ad
673  module procedure mpp_sum_cmplx8_5d_ad
674 #endif
675  module procedure mpp_sum_int4_ad
676  module procedure mpp_sum_int4_scalar_ad
677  module procedure mpp_sum_int4_2d_ad
678  module procedure mpp_sum_int4_3d_ad
679  module procedure mpp_sum_int4_4d_ad
680  module procedure mpp_sum_int4_5d_ad
681  module procedure mpp_sum_real4_ad
682  module procedure mpp_sum_real4_scalar_ad
683  module procedure mpp_sum_real4_2d_ad
684  module procedure mpp_sum_real4_3d_ad
685  module procedure mpp_sum_real4_4d_ad
686  module procedure mpp_sum_real4_5d_ad
687 #ifdef OVERLOAD_C4
688  module procedure mpp_sum_cmplx4_ad
689  module procedure mpp_sum_cmplx4_scalar_ad
690  module procedure mpp_sum_cmplx4_2d_ad
691  module procedure mpp_sum_cmplx4_3d_ad
692  module procedure mpp_sum_cmplx4_4d_ad
693  module procedure mpp_sum_cmplx4_5d_ad
694 #endif
695  end interface
696 
697  !> @brief Gather data sent from pelist onto the root pe
698  !! Wrapper for MPI_gather, can be used with and without indices
699  !> @ingroup mpp_mod
700  !!
701  !> @param sbuf MPP_TYPE_ data buffer to send
702  !> @param rbuf MPP_TYPE_ data buffer to receive
703  !> @param pelist integer(:) optional pelist to gather from, defaults to current
704  !>
705  !> <BR> Example usage:
706  !!
707  !! call mpp_gather(send_buffer,recv_buffer, pelist)
708  !! call mpp_gather(is, ie, js, je, pelist, array_seg, data, is_root_pe)
709  !!
710  interface mpp_gather
711  module procedure mpp_gather_logical4
712  module procedure mpp_gatherv_logical4
713  module procedure mpp_gather_logical_1d
714  module procedure mpp_gather_int4
715  module procedure mpp_gather_int8
716  module procedure mpp_gatherv_int4
717  module procedure mpp_gatherv_int8
718  module procedure mpp_gather_int4_1d
719  module procedure mpp_gather_int8_1d
720  module procedure mpp_gather_real4
721  module procedure mpp_gather_real8
722  module procedure mpp_gatherv_real4
723  module procedure mpp_gatherv_real8
724  module procedure mpp_gather_real4_1d
725  module procedure mpp_gather_real8_1d
726  module procedure mpp_gather_logical_1dv
727  module procedure mpp_gather_int4_1dv
728  module procedure mpp_gather_int8_1dv
729  module procedure mpp_gather_real4_1dv
730  module procedure mpp_gather_real8_1dv
731  module procedure mpp_gather_pelist_logical_2d
732  module procedure mpp_gather_pelist_logical_gen_2d
733  module procedure mpp_gather_pelist_logical_3d
734  module procedure mpp_gather_pelist_logical_gen_3d
735  module procedure mpp_gather_pelist_int4_2d
736  module procedure mpp_gather_pelist_int4_gen_2d
737  module procedure mpp_gather_pelist_int4_3d
738  module procedure mpp_gather_pelist_int4_gen_3d
739  module procedure mpp_gather_pelist_int8_2d
740  module procedure mpp_gather_pelist_int8_gen_2d
741  module procedure mpp_gather_pelist_int8_3d
742  module procedure mpp_gather_pelist_int8_gen_3d
743  module procedure mpp_gather_pelist_real4_2d
744  module procedure mpp_gather_pelist_real4_gen_2d
745  module procedure mpp_gather_pelist_real4_3d
746  module procedure mpp_gather_pelist_real4_gen_3d
747  module procedure mpp_gather_pelist_real8_2d
748  module procedure mpp_gather_pelist_real8_gen_2d
749  module procedure mpp_gather_pelist_real8_3d
750  module procedure mpp_gather_pelist_real8_gen_3d
751  end interface
752 
753  !> @brief Scatter (ie - is) * (je - js) contiguous elements of array data from the designated root pe
754  !! into contigous members of array segment in each pe that is included in the pelist argument.
755  !> @ingroup mpp_mod
756  !!
757  !> @param is, ie integer start and end index of the first dimension of the segment array
758  !> @param je, js integer start and end index of the second dimension of the segment array
759  !> @param pelist integer(:) the PE list of target pes, needs to be monotonically increasing
760  !> @param array_seg MPP_TYPE_ 2D array that the data is to be copied into
761  !> @param data MPP_TYPE_ the source array
762  !> @param is_root_pe logical true if calling from root pe
763  !> @param ishift integer offsets specifying the first elelement in the data array
764  !> @param nk integer size of third dimension for 3D calls
765  !!
766  !> <BR> Example usage:
767  !!
768  !! call mpp_scatter(is, ie, js, je, pelist, segment, data, .true.)
769  !!
770  interface mpp_scatter
771  module procedure mpp_scatterv_int4
772  module procedure mpp_scatter_pelist_int4_2d
773  module procedure mpp_scatter_pelist_int4_gen_2d
774  module procedure mpp_scatter_pelist_int4_3d
775  module procedure mpp_scatter_pelist_int4_gen_3d
776  module procedure mpp_scatterv_int8
777  module procedure mpp_scatter_pelist_int8_2d
778  module procedure mpp_scatter_pelist_int8_gen_2d
779  module procedure mpp_scatter_pelist_int8_3d
780  module procedure mpp_scatter_pelist_int8_gen_3d
781  module procedure mpp_scatterv_real4
782  module procedure mpp_scatter_pelist_real4_2d
783  module procedure mpp_scatter_pelist_real4_gen_2d
784  module procedure mpp_scatter_pelist_real4_3d
785  module procedure mpp_scatter_pelist_real4_gen_3d
786  module procedure mpp_scatterv_real8
787  module procedure mpp_scatter_pelist_real8_2d
788  module procedure mpp_scatter_pelist_real8_gen_2d
789  module procedure mpp_scatter_pelist_real8_3d
790  module procedure mpp_scatter_pelist_real8_gen_3d
791  end interface
792 
793  !#####################################################################
794  !> @brief Scatter a vector across all PEs
795  !!
796  !> Transpose the vector and PE index
797  !! Wrapper for the MPI_alltoall function, includes more generic _V and _W
798  !! versions if given displacements/data types
799  !!
800  !! Generic MPP_TYPE_ implentations:
801  !! <li> @ref mpp_alltoall_ </li>
802  !! <li> @ref mpp_alltoallv_ </li>
803  !! <li> @ref mpp_alltoallw_ </li>
804  !!
805  !> @ingroup mpp_mod
806  interface mpp_alltoall
807  module procedure mpp_alltoall_int4
808  module procedure mpp_alltoall_int8
809  module procedure mpp_alltoall_real4
810  module procedure mpp_alltoall_real8
811 #ifdef OVERLOAD_C4
812  module procedure mpp_alltoall_cmplx4
813 #endif
814 #ifdef OVERLOAD_C8
815  module procedure mpp_alltoall_cmplx8
816 #endif
817  module procedure mpp_alltoall_logical4
818  module procedure mpp_alltoall_logical8
819  module procedure mpp_alltoall_int4_v
820  module procedure mpp_alltoall_int8_v
821  module procedure mpp_alltoall_real4_v
822  module procedure mpp_alltoall_real8_v
823 #ifdef OVERLOAD_C4
824  module procedure mpp_alltoall_cmplx4_v
825 #endif
826 #ifdef OVERLOAD_C8
827  module procedure mpp_alltoall_cmplx8_v
828 #endif
829  module procedure mpp_alltoall_logical4_v
830  module procedure mpp_alltoall_logical8_v
831  module procedure mpp_alltoall_int4_w
832  module procedure mpp_alltoall_int8_w
833  module procedure mpp_alltoall_real4_w
834  module procedure mpp_alltoall_real8_w
835 #ifdef OVERLOAD_C4
836  module procedure mpp_alltoall_cmplx4_w
837 #endif
838 #ifdef OVERLOAD_C8
839  module procedure mpp_alltoall_cmplx8_w
840 #endif
841  module procedure mpp_alltoall_logical4_w
842  module procedure mpp_alltoall_logical8_w
843  end interface
844 
845 
846  !#####################################################################
847  !> @brief Basic message-passing call.
848  !!
849  !> <TT>MPP_TYPE_</TT> corresponds to any 4-byte and 8-byte variant of
850  !! <TT>integer, real, complex, logical</TT> variables, of rank 0 or 1. A
851  !! contiguous block from a multi-dimensional array may be passed by its
852  !! starting address and its length, as in <TT>f77</TT>.
853  !!
854  !! <TT>mpp_transmit</TT> is currently implemented as asynchronous
855  !! outward transmission and synchronous inward transmission. This follows
856  !! the behaviour of <TT>shmem_put</TT> and <TT>shmem_get</TT>. In MPI, it
857  !! is implemented as <TT>mpi_isend</TT> and <TT>mpi_recv</TT>. For most
858  !! applications, transmissions occur in pairs, and are here accomplished
859  !! in a single call.
860  !!
861  !! The special PE designations <TT>NULL_PE</TT>,
862  !! <TT>ANY_PE</TT> and <TT>ALL_PES</TT> are provided by use
863  !! association.
864  !!
865  !! <TT>NULL_PE</TT>: is used to disable one of the pair of
866  !! transmissions.<BR/>
867  !! <TT>ANY_PE</TT>: is used for unspecific remote
868  !! destination. (Please note that <TT>put_pe=ANY_PE</TT> has no meaning
869  !! in the MPI context, though it is available in the SHMEM invocation. If
870  !! portability is a concern, it is best avoided).<BR/>
871  !! <TT>ALL_PES</TT>: is used for broadcast operations.
872  !!
873  !! It is recommended that
874  !! @ref mpp_broadcast be used for
875  !! broadcasts.
876  !!
877  !! The following example illustrates the use of
878  !! <TT>NULL_PE</TT> and <TT>ALL_PES</TT>:
879  !!
880  !! <PRE>
881  !! real, dimension(n) :: a
882  !! if( pe.EQ.0 )then
883  !! do p = 1,npes-1
884  !! call mpp_transmit( a, n, p, a, n, NULL_PE )
885  !! end do
886  !! else
887  !! call mpp_transmit( a, n, NULL_PE, a, n, 0 )
888  !! end if
889  !!
890  !! call mpp_transmit( a, n, ALL_PES, a, n, 0 )
891  !! </PRE>
892  !!
893  !! The do loop and the broadcast operation above are equivalent.
894  !!
895  !! Two overloaded calls <TT>mpp_send</TT> and
896  !! <TT>mpp_recv</TT> have also been
897  !! provided. <TT>mpp_send</TT> calls <TT>mpp_transmit</TT>
898  !! with <TT>get_pe=NULL_PE</TT>. <TT>mpp_recv</TT> calls
899  !! <TT>mpp_transmit</TT> with <TT>put_pe=NULL_PE</TT>. Thus
900  !! the do loop above could be written more succinctly:
901  !!
902  !! <PRE>
903  !! if( pe.EQ.0 )then
904  !! do p = 1,npes-1
905  !! call mpp_send( a, n, p )
906  !! end do
907  !! else
908  !! call mpp_recv( a, n, 0 )
909  !! end if
910  !! </PRE>
911  !! <br>Example call:
912  !! @code{.F90}
913  !! call mpp_transmit( put_data, put_len, put_pe, get_data, get_len, get_pe )
914  !! @endcode
915  !> @ingroup mpp_mod
916  interface mpp_transmit
917  module procedure mpp_transmit_real8
918  module procedure mpp_transmit_real8_scalar
919  module procedure mpp_transmit_real8_2d
920  module procedure mpp_transmit_real8_3d
921  module procedure mpp_transmit_real8_4d
922  module procedure mpp_transmit_real8_5d
923 #ifdef OVERLOAD_C8
924  module procedure mpp_transmit_cmplx8
925  module procedure mpp_transmit_cmplx8_scalar
926  module procedure mpp_transmit_cmplx8_2d
927  module procedure mpp_transmit_cmplx8_3d
928  module procedure mpp_transmit_cmplx8_4d
929  module procedure mpp_transmit_cmplx8_5d
930 #endif
931  module procedure mpp_transmit_int8
932  module procedure mpp_transmit_int8_scalar
933  module procedure mpp_transmit_int8_2d
934  module procedure mpp_transmit_int8_3d
935  module procedure mpp_transmit_int8_4d
936  module procedure mpp_transmit_int8_5d
937  module procedure mpp_transmit_logical8
938  module procedure mpp_transmit_logical8_scalar
939  module procedure mpp_transmit_logical8_2d
940  module procedure mpp_transmit_logical8_3d
941  module procedure mpp_transmit_logical8_4d
942  module procedure mpp_transmit_logical8_5d
943 
944  module procedure mpp_transmit_real4
945  module procedure mpp_transmit_real4_scalar
946  module procedure mpp_transmit_real4_2d
947  module procedure mpp_transmit_real4_3d
948  module procedure mpp_transmit_real4_4d
949  module procedure mpp_transmit_real4_5d
950 
951 #ifdef OVERLOAD_C4
952  module procedure mpp_transmit_cmplx4
953  module procedure mpp_transmit_cmplx4_scalar
954  module procedure mpp_transmit_cmplx4_2d
955  module procedure mpp_transmit_cmplx4_3d
956  module procedure mpp_transmit_cmplx4_4d
957  module procedure mpp_transmit_cmplx4_5d
958 #endif
959  module procedure mpp_transmit_int4
960  module procedure mpp_transmit_int4_scalar
961  module procedure mpp_transmit_int4_2d
962  module procedure mpp_transmit_int4_3d
963  module procedure mpp_transmit_int4_4d
964  module procedure mpp_transmit_int4_5d
965  module procedure mpp_transmit_logical4
966  module procedure mpp_transmit_logical4_scalar
967  module procedure mpp_transmit_logical4_2d
968  module procedure mpp_transmit_logical4_3d
969  module procedure mpp_transmit_logical4_4d
970  module procedure mpp_transmit_logical4_5d
971  end interface
972  !> @brief Receive data from another PE
973  !!
974  !> @param[out] get_data scalar or array to get written with received data
975  !> @param get_len size of array to recv from get_data
976  !> @param from_pe PE number to receive from
977  !> @param block true for blocking, false for non-blocking. Defaults to true
978  !> @param tag communication tag
979  !> @param[out] request MPI request handle
980  !> @ingroup mpp_mod
981  interface mpp_recv
982  module procedure mpp_recv_real8
983  module procedure mpp_recv_real8_scalar
984  module procedure mpp_recv_real8_2d
985  module procedure mpp_recv_real8_3d
986  module procedure mpp_recv_real8_4d
987  module procedure mpp_recv_real8_5d
988 #ifdef OVERLOAD_C8
989  module procedure mpp_recv_cmplx8
990  module procedure mpp_recv_cmplx8_scalar
991  module procedure mpp_recv_cmplx8_2d
992  module procedure mpp_recv_cmplx8_3d
993  module procedure mpp_recv_cmplx8_4d
994  module procedure mpp_recv_cmplx8_5d
995 #endif
996  module procedure mpp_recv_int8
997  module procedure mpp_recv_int8_scalar
998  module procedure mpp_recv_int8_2d
999  module procedure mpp_recv_int8_3d
1000  module procedure mpp_recv_int8_4d
1001  module procedure mpp_recv_int8_5d
1002  module procedure mpp_recv_logical8
1003  module procedure mpp_recv_logical8_scalar
1004  module procedure mpp_recv_logical8_2d
1005  module procedure mpp_recv_logical8_3d
1006  module procedure mpp_recv_logical8_4d
1007  module procedure mpp_recv_logical8_5d
1008 
1009  module procedure mpp_recv_real4
1010  module procedure mpp_recv_real4_scalar
1011  module procedure mpp_recv_real4_2d
1012  module procedure mpp_recv_real4_3d
1013  module procedure mpp_recv_real4_4d
1014  module procedure mpp_recv_real4_5d
1015 
1016 #ifdef OVERLOAD_C4
1017  module procedure mpp_recv_cmplx4
1018  module procedure mpp_recv_cmplx4_scalar
1019  module procedure mpp_recv_cmplx4_2d
1020  module procedure mpp_recv_cmplx4_3d
1021  module procedure mpp_recv_cmplx4_4d
1022  module procedure mpp_recv_cmplx4_5d
1023 #endif
1024  module procedure mpp_recv_int4
1025  module procedure mpp_recv_int4_scalar
1026  module procedure mpp_recv_int4_2d
1027  module procedure mpp_recv_int4_3d
1028  module procedure mpp_recv_int4_4d
1029  module procedure mpp_recv_int4_5d
1030  module procedure mpp_recv_logical4
1031  module procedure mpp_recv_logical4_scalar
1032  module procedure mpp_recv_logical4_2d
1033  module procedure mpp_recv_logical4_3d
1034  module procedure mpp_recv_logical4_4d
1035  module procedure mpp_recv_logical4_5d
1036  end interface
1037  !> Send data to a receiving PE.
1038  !!
1039  !> @param put_data scalar or array to get sent to a receiving PE
1040  !> @param put_len size of data to send from put_data
1041  !> @param to_pe PE number to send to
1042  !> @param block true for blocking, false for non-blocking. Defaults to true
1043  !> @param tag communication tag
1044  !> @param[out] request MPI request handle
1045  !! <br> Example usage:
1046  !! @code{.F90} call mpp_send(data, ie, pe) @endcode
1047  !> @ingroup mpp_mod
1048  interface mpp_send
1049  module procedure mpp_send_real8
1050  module procedure mpp_send_real8_scalar
1051  module procedure mpp_send_real8_2d
1052  module procedure mpp_send_real8_3d
1053  module procedure mpp_send_real8_4d
1054  module procedure mpp_send_real8_5d
1055 #ifdef OVERLOAD_C8
1056  module procedure mpp_send_cmplx8
1057  module procedure mpp_send_cmplx8_scalar
1058  module procedure mpp_send_cmplx8_2d
1059  module procedure mpp_send_cmplx8_3d
1060  module procedure mpp_send_cmplx8_4d
1061  module procedure mpp_send_cmplx8_5d
1062 #endif
1063  module procedure mpp_send_int8
1064  module procedure mpp_send_int8_scalar
1065  module procedure mpp_send_int8_2d
1066  module procedure mpp_send_int8_3d
1067  module procedure mpp_send_int8_4d
1068  module procedure mpp_send_int8_5d
1069  module procedure mpp_send_logical8
1070  module procedure mpp_send_logical8_scalar
1071  module procedure mpp_send_logical8_2d
1072  module procedure mpp_send_logical8_3d
1073  module procedure mpp_send_logical8_4d
1074  module procedure mpp_send_logical8_5d
1075 
1076  module procedure mpp_send_real4
1077  module procedure mpp_send_real4_scalar
1078  module procedure mpp_send_real4_2d
1079  module procedure mpp_send_real4_3d
1080  module procedure mpp_send_real4_4d
1081  module procedure mpp_send_real4_5d
1082 
1083 #ifdef OVERLOAD_C4
1084  module procedure mpp_send_cmplx4
1085  module procedure mpp_send_cmplx4_scalar
1086  module procedure mpp_send_cmplx4_2d
1087  module procedure mpp_send_cmplx4_3d
1088  module procedure mpp_send_cmplx4_4d
1089  module procedure mpp_send_cmplx4_5d
1090 #endif
1091  module procedure mpp_send_int4
1092  module procedure mpp_send_int4_scalar
1093  module procedure mpp_send_int4_2d
1094  module procedure mpp_send_int4_3d
1095  module procedure mpp_send_int4_4d
1096  module procedure mpp_send_int4_5d
1097  module procedure mpp_send_logical4
1098  module procedure mpp_send_logical4_scalar
1099  module procedure mpp_send_logical4_2d
1100  module procedure mpp_send_logical4_3d
1101  module procedure mpp_send_logical4_4d
1102  module procedure mpp_send_logical4_5d
1103  end interface
1104 
1105 
1106  !> @brief Perform parallel broadcasts
1107  !!
1108  !> The <TT>mpp_broadcast</TT> call has been added because the original
1109  !! syntax (using <TT>ALL_PES</TT> in <TT>mpp_transmit</TT>) did not
1110  !! support a broadcast across a pelist.
1111  !!
1112  !! <TT>MPP_TYPE_</TT> corresponds to any 4-byte and 8-byte variant of
1113  !! <TT>integer, real, complex, logical</TT> variables, of rank 0 or 1. A
1114  !! contiguous block from a multi-dimensional array may be passed by its
1115  !! starting address and its length, as in <TT>f77</TT>.
1116  !!
1117  !! Global broadcasts through the <TT>ALL_PES</TT> argument to
1118  !! @ref mpp_transmit are still provided for
1119  !! backward-compatibility.
1120  !!
1121  !! If <TT>pelist</TT> is omitted, the context is assumed to be the
1122  !! current pelist. <TT>from_pe</TT> must belong to the current
1123  !! pelist. This call implies synchronization across the PEs in
1124  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
1125  !!
1126  !! <br>Example usage:
1127  !!
1128  !! call mpp_broadcast( data, length, from_pe, pelist )
1129  !!
1130  !> @param[inout] data Data to broadcast
1131  !> @param length Length of data to broadcast
1132  !> @param from_pe PE to send the data from
1133  !> @param pelist List of PE's to broadcast across, if not provided uses current list
1134  !> @ingroup mpp_mod
1135  interface mpp_broadcast
1136  module procedure mpp_broadcast_char
1137  module procedure mpp_broadcast_real8
1138  module procedure mpp_broadcast_real8_scalar
1139  module procedure mpp_broadcast_real8_2d
1140  module procedure mpp_broadcast_real8_3d
1141  module procedure mpp_broadcast_real8_4d
1142  module procedure mpp_broadcast_real8_5d
1143 #ifdef OVERLOAD_C8
1144  module procedure mpp_broadcast_cmplx8
1145  module procedure mpp_broadcast_cmplx8_scalar
1146  module procedure mpp_broadcast_cmplx8_2d
1147  module procedure mpp_broadcast_cmplx8_3d
1148  module procedure mpp_broadcast_cmplx8_4d
1149  module procedure mpp_broadcast_cmplx8_5d
1150 #endif
1151  module procedure mpp_broadcast_int8
1152  module procedure mpp_broadcast_int8_scalar
1153  module procedure mpp_broadcast_int8_2d
1154  module procedure mpp_broadcast_int8_3d
1155  module procedure mpp_broadcast_int8_4d
1156  module procedure mpp_broadcast_int8_5d
1157  module procedure mpp_broadcast_logical8
1158  module procedure mpp_broadcast_logical8_scalar
1159  module procedure mpp_broadcast_logical8_2d
1160  module procedure mpp_broadcast_logical8_3d
1161  module procedure mpp_broadcast_logical8_4d
1162  module procedure mpp_broadcast_logical8_5d
1163 
1164  module procedure mpp_broadcast_real4
1165  module procedure mpp_broadcast_real4_scalar
1166  module procedure mpp_broadcast_real4_2d
1167  module procedure mpp_broadcast_real4_3d
1168  module procedure mpp_broadcast_real4_4d
1169  module procedure mpp_broadcast_real4_5d
1170 
1171 #ifdef OVERLOAD_C4
1172  module procedure mpp_broadcast_cmplx4
1173  module procedure mpp_broadcast_cmplx4_scalar
1174  module procedure mpp_broadcast_cmplx4_2d
1175  module procedure mpp_broadcast_cmplx4_3d
1176  module procedure mpp_broadcast_cmplx4_4d
1177  module procedure mpp_broadcast_cmplx4_5d
1178 #endif
1179  module procedure mpp_broadcast_int4
1180  module procedure mpp_broadcast_int4_scalar
1181  module procedure mpp_broadcast_int4_2d
1182  module procedure mpp_broadcast_int4_3d
1183  module procedure mpp_broadcast_int4_4d
1184  module procedure mpp_broadcast_int4_5d
1185  module procedure mpp_broadcast_logical4
1186  module procedure mpp_broadcast_logical4_scalar
1187  module procedure mpp_broadcast_logical4_2d
1188  module procedure mpp_broadcast_logical4_3d
1189  module procedure mpp_broadcast_logical4_4d
1190  module procedure mpp_broadcast_logical4_5d
1191  end interface
1192 
1193  !#####################################################################
1194 
1195  !> @brief Calculate parallel checksums
1196  !!
1197  !> \e mpp_chksum is a parallel checksum routine that returns an
1198  !! identical answer for the same array irrespective of how it has been
1199  !! partitioned across processors. \e int_kind is the KIND
1200  !! parameter corresponding to long integers (see discussion on
1201  !! OS-dependent preprocessor directives) defined in
1202  !! the file platform.F90. \e MPP_TYPE_ corresponds to any
1203  !! 4-byte and 8-byte variant of \e integer, \e real, \e complex, \e logical
1204  !! variables, of rank 0 to 5.
1205  !!
1206  !! Integer checksums on FP data use the F90 <TT>TRANSFER()</TT>
1207  !! intrinsic.
1208  !!
1209  !! This provides identical results on a single-processor job, and to perform
1210  !! serial checksums on a single processor of a parallel job, you only
1211  !! need to use the optional <TT>pelist</TT> argument.
1212  !! <PRE>
1213  !! use mpp_mod
1214  !! integer :: pe, chksum
1215  !! real :: a(:)
1216  !! pe = mpp_pe()
1217  !! chksum = mpp_chksum( a, (/pe/) )
1218  !! </PRE>
1219  !!
1220  !! The additional functionality of <TT>mpp_chksum</TT> over
1221  !! serial checksums is to compute the checksum across the PEs in
1222  !! <TT>pelist</TT>. The answer is guaranteed to be the same for
1223  !! the same distributed array irrespective of how it has been
1224  !! partitioned.
1225  !!
1226  !! If <TT>pelist</TT> is omitted, the context is assumed to be the
1227  !! current pelist. This call implies synchronization across the PEs in
1228  !! <TT>pelist</TT>, or the current pelist if <TT>pelist</TT> is absent.
1229  !! <br> Example usage:
1230  !!
1231  !! mpp_chksum( var, pelist )
1232  !!
1233  !! @param var Data to calculate checksum of
1234  !! @param pelist Optional list of PE's to include in checksum calculation if not using
1235  !! current pelist
1236  !! @return Parallel checksum of var across given or implicit pelist
1237  !!
1238  !! Generic MPP_TYPE_ implentations:
1239  !! <li> @ref mpp_chksum_</li>
1240  !! <li> @ref mpp_chksum_int_</li>
1241  !! <li> @ref mpp_chksum_int_rmask_</li>
1242  !!
1243  !> @ingroup mpp_mod
1244  interface mpp_chksum
1245  module procedure mpp_chksum_i8_1d
1246  module procedure mpp_chksum_i8_2d
1247  module procedure mpp_chksum_i8_3d
1248  module procedure mpp_chksum_i8_4d
1249  module procedure mpp_chksum_i8_5d
1250  module procedure mpp_chksum_i8_1d_rmask
1251  module procedure mpp_chksum_i8_2d_rmask
1252  module procedure mpp_chksum_i8_3d_rmask
1253  module procedure mpp_chksum_i8_4d_rmask
1254  module procedure mpp_chksum_i8_5d_rmask
1255 
1256  module procedure mpp_chksum_i4_1d
1257  module procedure mpp_chksum_i4_2d
1258  module procedure mpp_chksum_i4_3d
1259  module procedure mpp_chksum_i4_4d
1260  module procedure mpp_chksum_i4_5d
1261  module procedure mpp_chksum_i4_1d_rmask
1262  module procedure mpp_chksum_i4_2d_rmask
1263  module procedure mpp_chksum_i4_3d_rmask
1264  module procedure mpp_chksum_i4_4d_rmask
1265  module procedure mpp_chksum_i4_5d_rmask
1266 
1267  module procedure mpp_chksum_r8_0d
1268  module procedure mpp_chksum_r8_1d
1269  module procedure mpp_chksum_r8_2d
1270  module procedure mpp_chksum_r8_3d
1271  module procedure mpp_chksum_r8_4d
1272  module procedure mpp_chksum_r8_5d
1273 
1274  module procedure mpp_chksum_r4_0d
1275  module procedure mpp_chksum_r4_1d
1276  module procedure mpp_chksum_r4_2d
1277  module procedure mpp_chksum_r4_3d
1278  module procedure mpp_chksum_r4_4d
1279  module procedure mpp_chksum_r4_5d
1280 #ifdef OVERLOAD_C8
1281  module procedure mpp_chksum_c8_0d
1282  module procedure mpp_chksum_c8_1d
1283  module procedure mpp_chksum_c8_2d
1284  module procedure mpp_chksum_c8_3d
1285  module procedure mpp_chksum_c8_4d
1286  module procedure mpp_chksum_c8_5d
1287 #endif
1288 #ifdef OVERLOAD_C4
1289  module procedure mpp_chksum_c4_0d
1290  module procedure mpp_chksum_c4_1d
1291  module procedure mpp_chksum_c4_2d
1292  module procedure mpp_chksum_c4_3d
1293  module procedure mpp_chksum_c4_4d
1294  module procedure mpp_chksum_c4_5d
1295 #endif
1296  end interface
1297 
1298 !> @addtogroup mpp_mod
1299 !> @{
1300 !***********************************************************************
1301 !
1302 ! module variables
1303 !
1304 !***********************************************************************
1305  integer, parameter :: PESET_MAX = 10000
1306  integer :: current_peset_max = 32
1307  type(communicator), allocatable :: peset(:) !< Will be allocated starting from 0, 0 is a dummy used
1308  !! to hold single-PE "self" communicator
1309  logical :: module_is_initialized = .false.
1310  logical :: debug = .false.
1311  integer :: npes=1, root_pe=0, pe=0
1312  integer(i8_kind) :: tick, ticks_per_sec, max_ticks, start_tick, end_tick, tick0=0
1313  type(mpi_comm) :: mpp_comm_private
1314  logical :: first_call_system_clock_mpi=.true.
1315  real(r8_kind) :: mpi_count0=0 !< use to prevent integer overflow
1316  real(r8_kind) :: mpi_tick_rate=0.d0 !< clock rate for mpi_wtick()
1317  logical :: mpp_record_timing_data=.true.
1318  type(clock),save :: clocks(max_clocks)
1319  integer :: log_unit, etc_unit
1320  integer :: warn_unit !< unit number of the warning log
1321  character(len=32), parameter :: configfile='logfile'
1322  character(len=32), parameter :: warnfile='warnfile' !< base name for warninglog (appends ".<PE>.out")
1323  integer :: peset_num=0, current_peset_num=0
1324  integer :: world_peset_num !<the world communicator
1325  integer :: error
1326  integer :: clock_num=0, num_clock_ids=0,current_clock=0, previous_clock(max_clocks)=0
1327  real :: tick_rate
1328 
1329  type(mpp_type_list) :: datatypes
1330  type(mpp_type), target :: mpp_byte
1331 
1332  integer :: cur_send_request = 0
1333  integer :: cur_recv_request = 0
1334  type(mpi_request), allocatable :: request_send(:)
1335  type(mpi_request), allocatable :: request_recv(:)
1336  type(mpi_datatype), allocatable :: type_recv(:)
1337  integer, allocatable :: size_recv(:)
1338 ! if you want to save the non-root PE information uncomment out the following line
1339 ! and comment out the assigment of etcfile to '/dev/null'
1340 #ifdef NO_DEV_NULL
1341  character(len=32) :: etcfile='._mpp.nonrootpe.msgs'
1342 #else
1343  character(len=32) :: etcfile='/dev/null'
1344 #endif
1345 
1346 !> Use the intrinsics in iso_fortran_env
1347  integer :: in_unit=input_unit, out_unit=output_unit, err_unit=error_unit
1348  integer :: stdout_unit
1349 
1350  !--- variables used in mpp_util.h
1351  type(summary_struct) :: clock_summary(max_clocks)
1352  logical :: warnings_are_fatal = .false.
1353  integer :: error_state=0
1354  integer :: clock_grain=clock_loop-1
1355 
1356  !--- variables used in mpp_comm.h
1357  integer :: clock0 !<measures total runtime from mpp_init to mpp_exit
1358  integer :: mpp_stack_size=0, mpp_stack_hwm=0
1359  logical :: verbose=.false.
1360 
1361  integer :: get_len_nocomm = 0 !< needed for mpp_transmit_nocomm.h
1362 
1363  !--- variables used in mpp_comm_mpi.inc
1364  integer, parameter :: mpp_init_test_full_init = -1
1365  integer, parameter :: mpp_init_test_init_true_only = 0
1366  integer, parameter :: mpp_init_test_peset_allocated = 1
1367  integer, parameter :: mpp_init_test_clocks_init = 2
1368  integer, parameter :: mpp_init_test_datatype_list_init = 3
1369  integer, parameter :: mpp_init_test_logfile_init = 4
1370  integer, parameter :: mpp_init_test_read_namelist = 5
1371  integer, parameter :: mpp_init_test_etc_unit = 6
1372  integer, parameter :: mpp_init_test_requests_allocated = 7
1373 
1374  !> MPP_INFO_NULL acts as an analagous mpp-macro for MPI_INFO_NULL to share with fms2_io NetCDF4
1375  !! mpi-io. Intel MPI and MPICH provide a value of 469762048. OpenMPI provides a value of 0.
1376  integer, parameter :: mpp_info_null = mpi_info_null%mpi_val
1377 
1378  !> MPP_COMM_NULL acts as an analagous mpp-macro for MPI_COMM_NULL to share with fms2_io NetCDF4
1379  !! mpi-io. Intel MPI and MPICH provide a value of 67108864. OpenMPI provides a value of 0.
1380  integer, parameter :: mpp_comm_null = mpi_comm_null%mpi_val
1381 
1382 !***********************************************************************
1383 ! variables needed for subroutine read_input_nml (include/mpp_util.inc)
1384 !
1385 ! public variable needed for reading input nml file from an internal file
1386  character(len=:), dimension(:), allocatable, target, public :: input_nml_file
1387  logical :: read_ascii_file_on = .false.
1388 !***********************************************************************
1389 
1390 ! Include variable "version" to be written to log file.
1391 #include<file_version.h>
1392  public version
1393 
1394  integer, parameter :: max_request_min = 10000
1395  integer :: request_multiply = 20
1396 
1397  logical :: etc_unit_is_stderr = .false.
1398  integer :: max_request = 0
1399  logical :: sync_all_clocks = .false.
1400  namelist /mpp_nml/ etc_unit_is_stderr, request_multiply, mpp_record_timing_data, sync_all_clocks
1401 
1402  contains
1403 #include <system_clock.fh>
1404 #include <mpp_util.inc>
1405 #include <mpp_comm.inc>
1406 
1407  end module mpp_mod
1408 !> @}
1409 ! 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:1320
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:1449
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:504
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:1380
integer get_len_nocomm
needed for mpp_transmit_nocomm.h
Definition: mpp.F90:1361
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:1230
character(len=32), parameter warnfile
base name for warninglog (appends ".<PE>.out")
Definition: mpp.F90:1322
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:1554
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:1307
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:1376
integer clock0
measures total runtime from mpp_init to mpp_exit
Definition: mpp.F90:1357
subroutine mpp_clock_set_grain(grain)
Set the level of granularity of timing measurements.
Definition: mpp_util.inc:652
real(r8_kind) mpi_tick_rate
clock rate for mpi_wtick()
Definition: mpp.F90:1316
subroutine mpp_declare_pelist(pelist, name, commID)
Declare a pelist.
Definition: mpp_util.inc:475
integer world_peset_num
the world communicator
Definition: mpp.F90:1324
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:1347
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:1356
real(r8_kind) mpi_count0
use to prevent integer overflow
Definition: mpp.F90:1315
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:716
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
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:806
Perform parallel broadcasts.
Definition: mpp.F90:1135
Calculate parallel checksums.
Definition: mpp.F90:1244
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:710
Reduction operations. Find the max of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:550
Reduction operations. Find the min of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:572
Receive data from another PE.
Definition: mpp.F90:981
Scatter (ie - is) * (je - js) contiguous elements of array data from the designated root pe into cont...
Definition: mpp.F90:770
Send data to a receiving PE.
Definition: mpp.F90:1048
Reduction operation.
Definition: mpp.F90:609
Calculates sum of a given numerical array across pe's for adjoint domains.
Definition: mpp.F90:654
Basic message-passing call.
Definition: mpp.F90:916
Create a mpp_type variable.
Definition: mpp.F90:522
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