mpp_mod_oa.F90

Go to the documentation of this file.
00001 #ifndef key_noIO
00002 !-----------------------------------------------------------------------
00003 !                 Communication for message-passing codes
00004 !
00005 ! AUTHOR: V. Balaji (vbalaji@noaa.gov)
00006 !         Princeton University/GFDL
00007 !
00008 ! MODIFICATIONS: Reiner Vogelsang (reiner@sgi.com)
00009 !                Sophie Valcke: renamed the routine with _oa suffix
00010 !
00011 ! This program is free software; The author agrees that you can
00012 ! redistribute and/or modify this version of the program under the
00013 ! terms of the Lesser GNU General Public License as published
00014 ! by the Free Software Foundation.
00015 !
00016 ! This program is distributed in the hope that it will be useful,
00017 ! but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 ! Lesser GNU General Public License for more details
00020 ! (http://www.gnu.org/copyleft/lesser.html).
00021 !-----------------------------------------------------------------------
00022 
00023 !these are used to determine hardware/OS/compiler
00024 !#include <os.h>
00025 
00026 !onlysgi_mipspro one of SMA or MPI can be used
00027 !(though mixing calls is allowed, this module will not)
00028 #ifdef use_libSMA
00029 #undef use_libMPI
00030 #endif
00031 !
00032 #if defined(_CRAYT3E) || defined(_CRAYT3D) || defined(sgi_mipspro)
00033 #define SGICRAY_MPP
00034 #endif
00035 !
00036 !shmalloc is used on MPP SGI/Cray systems for shmem
00037 #if defined(use_libSMA) && defined(SGICRAY_MPP)
00038 #define use_shmalloc
00039 #endif
00040 
00041 module mpp_mod_oa
00042 use mod_kinds_mpp
00043 #include <os.h>
00044 !string BWA is used to tag lines that are bug workarounds and will disappear
00045 !when offending compiler bug is fixed
00046 !a generalized communication package for use with shmem and MPI
00047 !will add: co_array_fortran, MPI2
00048 !Balaji (vb@gfdl.gov) 11 May 1998
00049 #ifdef sgi_mipspro
00050 #ifdef use_libSMA
00051 !  use shmem_interface
00052 #endif
00053 !#ifdef use_libMPI
00054 !  use mpi
00055 !#endif
00056 #endif
00057 #ifdef NAG_COMPILER
00058     use mpi
00059 #endif
00060   implicit none
00061   private
00062   character(len=128), private :: version= 
00063        '$Id: mpp_mod_oa.F90 2303 2010-04-09 15:46:00Z valcke $'
00064   character(len=128), private :: tagname= 
00065        '$Name$'
00066 
00067 !various lengths (see shpalloc) are estimated in "words" which are 32bit on SGI, 64bit on Cray
00068 !these are also the expected sizeof of args to MPI/shmem libraries
00069 #ifdef _CRAY
00070   integer(LONG_KIND), private :: word(1)
00071 #endif
00072 #ifdef sgi_mipspro
00073   integer(INT_KIND), private :: word(1)
00074 #endif
00075 
00076 #ifdef SGICRAY
00077 !see intro_io(3F): to see why these values are used rather than 5,6,0
00078   integer, private :: in_unit=100, out_unit=101, err_unit=102
00079 #else
00080   integer, private :: in_unit=5, out_unit=6, err_unit=0
00081 #endif
00082   integer :: log_unit, etc_unit
00083   logical, private :: module_is_initialized=.FALSE.
00084   integer, private :: pe=0, node=0, npes=1, root_pe=0
00085   integer, private :: error
00086   integer, parameter, private :: MAXPES=2048 !used for dimensioning stuff that might be indexed by pe
00087   character(len=32) :: configfile='logfile.out'
00088   character(len=32) :: etcfile='._mpp.nonrootpe.stdout'
00089   logical,save::logfile_defined=.false.,opened
00090   integer::io_num
00091 
00092 !initialization flags
00093   integer, parameter, public :: MPP_VERBOSE=1, MPP_DEBUG=2
00094   logical, private :: verbose=.FALSE., debug=.FALSE.
00095 
00096 !flags to transmit routines
00097   integer, parameter, public :: ALL_PES=-1, ANY_PE=-2, NULL_PE=-3
00098 
00099 !errortype flags
00100   integer, parameter, public :: NOTE=0, WARNING=1, FATAL=2
00101   logical, private :: warnings_are_fatal = .FALSE.
00102   integer, private :: error_state=0
00103 
00104   integer(LONG_KIND), parameter, private :: MPP_WAIT=-1, MPP_READY=-2
00105 #ifdef use_libSMA
00106 #include <mpp/shmem.fh>
00107   integer :: sync(SHMEM_REDUCE_SYNC_SIZE+SHMEM_BCAST_SYNC_SIZE+SHMEM_BARRIER_SYNC_SIZE)
00108 !status and remote_data_loc are used to synchronize communication is MPP_TRANSMIT
00109 #ifdef use_shmalloc
00110   integer(LONG_KIND), private, dimension(0:MAXPES) :: status, remote_data_loc
00111 #else
00112   integer(LONG_KIND), private, allocatable, dimension(:) :: status, remote_data_loc
00113 #endif
00114   integer, private :: mpp_from_pe !used to announce from where data is coming from
00115 #ifdef use_shmalloc
00116 !we call shpalloc in mpp_init() to ensure all these are remotely accessible
00117 !on PVP where shpalloc doesn't exist, module variables are automatically
00118 !guaranteed to be remotely accessible
00119   pointer( ptr_sync, sync )
00120   pointer( ptr_status, status )
00121   pointer( ptr_from, mpp_from_pe )
00122   pointer( ptr_remote, remote_data_loc )
00123 #endif
00124 #endif /* use_libSMA */
00125 #ifdef use_libMPI
00126 !#ifndef sgi_mipspro
00127 !sgi_mipspro gets this from 'use mpi'
00128 #ifndef NAG_COMPILER
00129 #include <mpif.h>
00130 #endif
00131 !!include 'mpif.h'
00132 !#endif
00133 !tag is never used, but must be initialized to non-negative integer
00134   integer, private :: tag=1, stat(MPI_STATUS_SIZE)
00135 !  integer, private, allocatable :: request(:)
00136   integer, public, allocatable :: mpp_request(:)
00137 #ifdef _CRAYT3E
00138 !BWA: mpif.h on t3e currently does not contain MPI_INTEGER8 datatype
00139 !(O2k and t90 do)
00140 !(t3e: fixed on 3.3 I believe)
00141   integer, parameter :: MPI_INTEGER8=MPI_INTEGER
00142 #endif
00143 #endif /* use_libMPI */
00144 
00145 !mpp_stack is used by SHMEM collective ops
00146 !must be SHPALLOC'd on SGICRAY_MPP, but is allocatable on PVP
00147 #ifdef use_shmalloc
00148   real(DOUBLE_KIND), private :: mpp_stack(1)
00149   pointer( ptr_stack, mpp_stack )
00150 #else
00151   real(DOUBLE_KIND), private, allocatable :: mpp_stack(:)
00152 #endif
00153   integer, private :: mpp_stack_size=0, mpp_stack_hwm=0
00154 
00155 !peset hold communicators as SHMEM-compatible triads (start, log2(stride), num)
00156   type, private :: communicator
00157      character(len=32) :: name
00158      integer, pointer :: list(:)
00159      integer :: count
00160 #ifdef use_libSMA
00161      integer :: start, log2stride
00162 #elif use_libMPI
00163      integer :: id, group    !MPI communicator and group id for this PE set
00164 #endif
00165   end type
00166   integer, parameter :: PESET_MAX=32 !should be .LE. max num of MPI communicators
00167   type(communicator) :: peset(0:PESET_MAX) !0 is a dummy used to hold single-PE "self" communicator
00168   integer :: peset_num=0, current_peset_num=0
00169   integer :: world_peset_num !the world communicator
00170 
00171 !performance profiling
00172 !  This profiles every type of MPI/SHMEM call within
00173 !    a specified region of high-level code
00174 !  Initialize or retrieve a clock with
00175 !  id = mpp_clock_id( 'Region identifier name' )
00176 !  Then set caliper points around the region using:
00177 !  call mpp_clock_begin(id)
00178 !  ...
00179 !  call mpp_clock_end(id)
00180 !  mpp_exit will print out the results.
00181 #ifdef __sgi
00182 #define SYSTEM_CLOCK system_clock_sgi
00183 #endif
00184 
00185 #ifdef use_libMPI
00186 #define SYSTEM_CLOCK system_clock_mpi
00187 #endif
00188 
00189 #if defined(__sgi) || defined(use_libMPI)
00190   integer(LONG_KIND), private :: tick, ticks_per_sec, max_ticks, start_tick, end_tick, tick0=0
00191 #else
00192   integer, private :: tick, ticks_per_sec, max_ticks, start_tick, end_tick, tick0=0
00193 #endif
00194   real, private :: tick_rate
00195   integer, private, parameter :: MAX_CLOCKS=100, MAX_EVENT_TYPES=5, MAX_EVENTS=40000
00196 !event types
00197   integer, private, parameter :: EVENT_ALLREDUCE=1, EVENT_BROADCAST=2, EVENT_RECV=3, EVENT_SEND=4, EVENT_WAIT=5
00198   integer, private :: clock_num=0, current_clock=0
00199   integer, private :: clock0    !measures total runtime from mpp_init to mpp_exit
00200   integer, private :: clock_grain=HUGE(1)
00201 !the event contains information for each type of event (e.g SHMEM_PUT)
00202   type, private :: event
00203      character(len=16)  :: name
00204      integer(LONG_KIND) :: ticks(MAX_EVENTS), bytes(MAX_EVENTS)
00205      integer            :: calls
00206   end type event
00207 !a clock contains an array of event profiles for a region
00208   integer, parameter, public :: MPP_CLOCK_SYNC=1, MPP_CLOCK_DETAILED=2
00209   type, private :: clock
00210      character(len=32) :: name
00211 #if defined(__sgi) || defined(use_libMPI)
00212      integer(LONG_KIND) :: tick
00213 #else
00214      integer :: tick
00215 #endif
00216      integer(LONG_KIND) :: total_ticks
00217      integer :: peset_num
00218      logical :: sync_on_begin, detailed
00219      type(event), pointer :: events(:) !if needed, allocate to MAX_EVENT_TYPES
00220   end type
00221   type(clock) :: clocks(MAX_CLOCKS)
00222 
00223   integer,parameter :: MAX_BINS=20
00224   TYPE :: Clock_Data_Summary
00225     character(len=16) :: name
00226     real(DOUBLE_KIND) :: msg_size_sums(MAX_BINS)
00227     real(DOUBLE_KIND) :: msg_time_sums(MAX_BINS)
00228     real(DOUBLE_KIND) :: total_data
00229     real(DOUBLE_KIND) :: total_time
00230     integer(LONG_KIND) :: msg_size_cnts(MAX_BINS)
00231     integer(LONG_KIND) :: total_cnts
00232   END TYPE Clock_Data_Summary
00233 
00234   TYPE :: Summary_Struct
00235     character(len=16)         :: name
00236     type (Clock_Data_Summary) :: event(MAX_EVENT_TYPES)
00237   END TYPE Summary_Struct
00238   type(Summary_Struct) :: clock_summary(MAX_CLOCKS)
00239   
00240 !public interfaces
00241   interface mpp_max
00242      module procedure mpp_max_real8
00243 #ifndef no_8byte_integers
00244      module procedure mpp_max_int8
00245 #endif
00246 #ifndef no_4byte_reals
00247      module procedure mpp_max_real4
00248 #endif
00249      module procedure mpp_max_int4
00250   end interface
00251   interface mpp_min
00252      module procedure mpp_min_real8
00253 #ifndef no_8byte_integers
00254      module procedure mpp_min_int8
00255 #endif
00256 #ifndef no_4byte_reals
00257      module procedure mpp_min_real4
00258 #endif
00259      module procedure mpp_min_int4
00260   end interface
00261   interface mpp_sum
00262 #ifndef no_8byte_integers
00263      module procedure mpp_sum_int8
00264      module procedure mpp_sum_int8_scalar
00265      module procedure mpp_sum_int8_2d
00266      module procedure mpp_sum_int8_3d
00267      module procedure mpp_sum_int8_4d
00268      module procedure mpp_sum_int8_5d
00269 #endif
00270      module procedure mpp_sum_real8
00271      module procedure mpp_sum_real8_scalar
00272      module procedure mpp_sum_real8_2d
00273      module procedure mpp_sum_real8_3d
00274      module procedure mpp_sum_real8_4d
00275      module procedure mpp_sum_real8_5d
00276      module procedure mpp_sum_cmplx8
00277      module procedure mpp_sum_cmplx8_scalar
00278      module procedure mpp_sum_cmplx8_2d
00279      module procedure mpp_sum_cmplx8_3d
00280      module procedure mpp_sum_cmplx8_4d
00281      module procedure mpp_sum_cmplx8_5d
00282      module procedure mpp_sum_int4
00283      module procedure mpp_sum_int4_scalar
00284      module procedure mpp_sum_int4_2d
00285      module procedure mpp_sum_int4_3d
00286      module procedure mpp_sum_int4_4d
00287      module procedure mpp_sum_int4_5d
00288 #ifndef no_4byte_reals
00289      module procedure mpp_sum_real4
00290      module procedure mpp_sum_real4_scalar
00291      module procedure mpp_sum_real4_2d
00292      module procedure mpp_sum_real4_3d
00293      module procedure mpp_sum_real4_4d
00294      module procedure mpp_sum_real4_5d
00295 #endif
00296 #ifndef no_4byte_cmplx
00297      module procedure mpp_sum_cmplx4
00298      module procedure mpp_sum_cmplx4_scalar
00299      module procedure mpp_sum_cmplx4_2d
00300      module procedure mpp_sum_cmplx4_3d
00301      module procedure mpp_sum_cmplx4_4d
00302      module procedure mpp_sum_cmplx4_5d
00303 #endif
00304   end interface
00305   interface mpp_transmit
00306      module procedure mpp_transmit_real8
00307      module procedure mpp_transmit_real8_scalar
00308      module procedure mpp_transmit_real8_2d
00309      module procedure mpp_transmit_real8_3d
00310      module procedure mpp_transmit_real8_4d
00311      module procedure mpp_transmit_real8_5d
00312      module procedure mpp_transmit_cmplx8
00313      module procedure mpp_transmit_cmplx8_scalar
00314      module procedure mpp_transmit_cmplx8_2d
00315      module procedure mpp_transmit_cmplx8_3d
00316      module procedure mpp_transmit_cmplx8_4d
00317      module procedure mpp_transmit_cmplx8_5d
00318 #ifndef no_8byte_integers
00319      module procedure mpp_transmit_int8
00320      module procedure mpp_transmit_int8_scalar
00321      module procedure mpp_transmit_int8_2d
00322      module procedure mpp_transmit_int8_3d
00323      module procedure mpp_transmit_int8_4d
00324      module procedure mpp_transmit_int8_5d
00325      module procedure mpp_transmit_logical8
00326      module procedure mpp_transmit_logical8_scalar
00327      module procedure mpp_transmit_logical8_2d
00328      module procedure mpp_transmit_logical8_3d
00329      module procedure mpp_transmit_logical8_4d
00330      module procedure mpp_transmit_logical8_5d
00331 #endif
00332 #ifndef no_4byte_reals
00333      module procedure mpp_transmit_real4
00334      module procedure mpp_transmit_real4_scalar
00335      module procedure mpp_transmit_real4_2d
00336      module procedure mpp_transmit_real4_3d
00337      module procedure mpp_transmit_real4_4d
00338      module procedure mpp_transmit_real4_5d
00339 #endif
00340 #ifndef no_4byte_cmplx
00341      module procedure mpp_transmit_cmplx4
00342      module procedure mpp_transmit_cmplx4_scalar
00343      module procedure mpp_transmit_cmplx4_2d
00344      module procedure mpp_transmit_cmplx4_3d
00345      module procedure mpp_transmit_cmplx4_4d
00346      module procedure mpp_transmit_cmplx4_5d
00347 #endif
00348      module procedure mpp_transmit_int4
00349      module procedure mpp_transmit_int4_scalar
00350      module procedure mpp_transmit_int4_2d
00351      module procedure mpp_transmit_int4_3d
00352      module procedure mpp_transmit_int4_4d
00353      module procedure mpp_transmit_int4_5d
00354      module procedure mpp_transmit_logical4
00355      module procedure mpp_transmit_logical4_scalar
00356      module procedure mpp_transmit_logical4_2d
00357      module procedure mpp_transmit_logical4_3d
00358      module procedure mpp_transmit_logical4_4d
00359      module procedure mpp_transmit_logical4_5d
00360   end interface
00361   interface mpp_recv
00362      module procedure mpp_recv_real8
00363      module procedure mpp_recv_real8_scalar
00364      module procedure mpp_recv_real8_2d
00365      module procedure mpp_recv_real8_3d
00366      module procedure mpp_recv_real8_4d
00367      module procedure mpp_recv_real8_5d
00368      module procedure mpp_recv_cmplx8
00369      module procedure mpp_recv_cmplx8_scalar
00370      module procedure mpp_recv_cmplx8_2d
00371      module procedure mpp_recv_cmplx8_3d
00372      module procedure mpp_recv_cmplx8_4d
00373      module procedure mpp_recv_cmplx8_5d
00374 #ifndef no_8byte_integers
00375      module procedure mpp_recv_int8
00376      module procedure mpp_recv_int8_scalar
00377      module procedure mpp_recv_int8_2d
00378      module procedure mpp_recv_int8_3d
00379      module procedure mpp_recv_int8_4d
00380      module procedure mpp_recv_int8_5d
00381      module procedure mpp_recv_logical8
00382      module procedure mpp_recv_logical8_scalar
00383      module procedure mpp_recv_logical8_2d
00384      module procedure mpp_recv_logical8_3d
00385      module procedure mpp_recv_logical8_4d
00386      module procedure mpp_recv_logical8_5d
00387 #endif
00388 #ifndef no_4byte_reals
00389      module procedure mpp_recv_real4
00390      module procedure mpp_recv_real4_scalar
00391      module procedure mpp_recv_real4_2d
00392      module procedure mpp_recv_real4_3d
00393      module procedure mpp_recv_real4_4d
00394      module procedure mpp_recv_real4_5d
00395 #endif
00396 #ifndef no_4byte_cmplx
00397      module procedure mpp_recv_cmplx4
00398      module procedure mpp_recv_cmplx4_scalar
00399      module procedure mpp_recv_cmplx4_2d
00400      module procedure mpp_recv_cmplx4_3d
00401      module procedure mpp_recv_cmplx4_4d
00402      module procedure mpp_recv_cmplx4_5d
00403 #endif
00404      module procedure mpp_recv_int4
00405      module procedure mpp_recv_int4_scalar
00406      module procedure mpp_recv_int4_2d
00407      module procedure mpp_recv_int4_3d
00408      module procedure mpp_recv_int4_4d
00409      module procedure mpp_recv_int4_5d
00410      module procedure mpp_recv_logical4
00411      module procedure mpp_recv_logical4_scalar
00412      module procedure mpp_recv_logical4_2d
00413      module procedure mpp_recv_logical4_3d
00414      module procedure mpp_recv_logical4_4d
00415      module procedure mpp_recv_logical4_5d
00416   end interface
00417   interface mpp_send
00418      module procedure mpp_send_real8
00419      module procedure mpp_send_real8_scalar
00420      module procedure mpp_send_real8_2d
00421      module procedure mpp_send_real8_3d
00422      module procedure mpp_send_real8_4d
00423      module procedure mpp_send_real8_5d
00424      module procedure mpp_send_cmplx8
00425      module procedure mpp_send_cmplx8_scalar
00426      module procedure mpp_send_cmplx8_2d
00427      module procedure mpp_send_cmplx8_3d
00428      module procedure mpp_send_cmplx8_4d
00429      module procedure mpp_send_cmplx8_5d
00430 #ifndef no_8byte_integers
00431      module procedure mpp_send_int8
00432      module procedure mpp_send_int8_scalar
00433      module procedure mpp_send_int8_2d
00434      module procedure mpp_send_int8_3d
00435      module procedure mpp_send_int8_4d
00436      module procedure mpp_send_int8_5d
00437      module procedure mpp_send_logical8
00438      module procedure mpp_send_logical8_scalar
00439      module procedure mpp_send_logical8_2d
00440      module procedure mpp_send_logical8_3d
00441      module procedure mpp_send_logical8_4d
00442      module procedure mpp_send_logical8_5d
00443 #endif
00444 #ifndef no_4byte_reals
00445      module procedure mpp_send_real4
00446      module procedure mpp_send_real4_scalar
00447      module procedure mpp_send_real4_2d
00448      module procedure mpp_send_real4_3d
00449      module procedure mpp_send_real4_4d
00450      module procedure mpp_send_real4_5d
00451 #endif
00452 #ifndef no_4byte_cmplx
00453      module procedure mpp_send_cmplx4
00454      module procedure mpp_send_cmplx4_scalar
00455      module procedure mpp_send_cmplx4_2d
00456      module procedure mpp_send_cmplx4_3d
00457      module procedure mpp_send_cmplx4_4d
00458      module procedure mpp_send_cmplx4_5d
00459 #endif
00460      module procedure mpp_send_int4
00461      module procedure mpp_send_int4_scalar
00462      module procedure mpp_send_int4_2d
00463      module procedure mpp_send_int4_3d
00464      module procedure mpp_send_int4_4d
00465      module procedure mpp_send_int4_5d
00466      module procedure mpp_send_logical4
00467      module procedure mpp_send_logical4_scalar
00468      module procedure mpp_send_logical4_2d
00469      module procedure mpp_send_logical4_3d
00470      module procedure mpp_send_logical4_4d
00471      module procedure mpp_send_logical4_5d
00472   end interface
00473 
00474   interface mpp_broadcast
00475      module procedure mpp_broadcast_real8
00476      module procedure mpp_broadcast_real8_scalar
00477      module procedure mpp_broadcast_real8_2d
00478      module procedure mpp_broadcast_real8_3d
00479      module procedure mpp_broadcast_real8_4d
00480      module procedure mpp_broadcast_real8_5d
00481      module procedure mpp_broadcast_cmplx8
00482      module procedure mpp_broadcast_cmplx8_scalar
00483      module procedure mpp_broadcast_cmplx8_2d
00484      module procedure mpp_broadcast_cmplx8_3d
00485      module procedure mpp_broadcast_cmplx8_4d
00486      module procedure mpp_broadcast_cmplx8_5d
00487 #ifndef no_8byte_integers
00488      module procedure mpp_broadcast_int8
00489      module procedure mpp_broadcast_int8_scalar
00490      module procedure mpp_broadcast_int8_2d
00491      module procedure mpp_broadcast_int8_3d
00492      module procedure mpp_broadcast_int8_4d
00493      module procedure mpp_broadcast_int8_5d
00494      module procedure mpp_broadcast_logical8
00495      module procedure mpp_broadcast_logical8_scalar
00496      module procedure mpp_broadcast_logical8_2d
00497      module procedure mpp_broadcast_logical8_3d
00498      module procedure mpp_broadcast_logical8_4d
00499      module procedure mpp_broadcast_logical8_5d
00500 #endif
00501 #ifndef no_4byte_reals
00502      module procedure mpp_broadcast_real4
00503      module procedure mpp_broadcast_real4_scalar
00504      module procedure mpp_broadcast_real4_2d
00505      module procedure mpp_broadcast_real4_3d
00506      module procedure mpp_broadcast_real4_4d
00507      module procedure mpp_broadcast_real4_5d
00508 #endif
00509 #ifndef no_4byte_cmplx
00510      module procedure mpp_broadcast_cmplx4
00511      module procedure mpp_broadcast_cmplx4_scalar
00512      module procedure mpp_broadcast_cmplx4_2d
00513      module procedure mpp_broadcast_cmplx4_3d
00514      module procedure mpp_broadcast_cmplx4_4d
00515      module procedure mpp_broadcast_cmplx4_5d
00516 #endif
00517      module procedure mpp_broadcast_int4
00518      module procedure mpp_broadcast_int4_scalar
00519      module procedure mpp_broadcast_int4_2d
00520      module procedure mpp_broadcast_int4_3d
00521      module procedure mpp_broadcast_int4_4d
00522      module procedure mpp_broadcast_int4_5d
00523      module procedure mpp_broadcast_logical4
00524      module procedure mpp_broadcast_logical4_scalar
00525      module procedure mpp_broadcast_logical4_2d
00526      module procedure mpp_broadcast_logical4_3d
00527      module procedure mpp_broadcast_logical4_4d
00528      module procedure mpp_broadcast_logical4_5d
00529   end interface
00530 
00531   interface mpp_chksum
00532 #ifndef no_8byte_integers
00533      module procedure mpp_chksum_i8_1d
00534      module procedure mpp_chksum_i8_2d
00535      module procedure mpp_chksum_i8_3d
00536      module procedure mpp_chksum_i8_4d
00537 #endif
00538      module procedure mpp_chksum_i4_1d
00539      module procedure mpp_chksum_i4_2d
00540      module procedure mpp_chksum_i4_3d
00541      module procedure mpp_chksum_i4_4d
00542      module procedure mpp_chksum_r8_0d
00543      module procedure mpp_chksum_r8_1d
00544      module procedure mpp_chksum_r8_2d
00545      module procedure mpp_chksum_r8_3d
00546      module procedure mpp_chksum_r8_4d
00547      module procedure mpp_chksum_r8_5d
00548      module procedure mpp_chksum_c8_0d
00549      module procedure mpp_chksum_c8_1d
00550      module procedure mpp_chksum_c8_2d
00551      module procedure mpp_chksum_c8_3d
00552      module procedure mpp_chksum_c8_4d
00553      module procedure mpp_chksum_c8_5d
00554 #ifndef no_4byte_reals
00555      module procedure mpp_chksum_r4_0d
00556      module procedure mpp_chksum_r4_1d
00557      module procedure mpp_chksum_r4_2d
00558      module procedure mpp_chksum_r4_3d
00559      module procedure mpp_chksum_r4_4d
00560      module procedure mpp_chksum_r4_5d
00561 #endif
00562 #ifndef no_4byte_cmplx
00563      module procedure mpp_chksum_c4_0d
00564      module procedure mpp_chksum_c4_1d
00565      module procedure mpp_chksum_c4_2d
00566      module procedure mpp_chksum_c4_3d
00567      module procedure mpp_chksum_c4_4d
00568      module procedure mpp_chksum_c4_5d
00569 #endif
00570   end interface
00571 
00572   interface mpp_error
00573      module procedure mpp_error_basic
00574      module procedure mpp_error_mesg
00575      module procedure mpp_error_noargs
00576   end interface
00577 
00578 #ifdef use_libSMA
00579 !currently SMA contains no generic shmem_wait for different integer kinds:
00580 !I have inserted one here
00581   interface shmem_integer_wait
00582      module procedure shmem_int4_wait_local
00583      module procedure shmem_int8_wait_local
00584   end interface
00585 #endif
00586   public :: mpp_chksum, mpp_max, mpp_min, mpp_sum
00587   public :: mpp_exit, mpp_init
00588   public :: mpp_pe, mpp_node, mpp_npes, mpp_root_pe, mpp_set_root_pe, mpp_set_stack_size
00589   public :: mpp_clock_begin, mpp_clock_end, mpp_clock_id, mpp_clock_set_grain
00590   public :: mpp_error, mpp_error_state, mpp_set_warn_level
00591   public :: mpp_sync, mpp_sync_self
00592   public :: mpp_transmit, mpp_send, mpp_recv, mpp_broadcast
00593   public :: stdin, stdout, stderr, stdlog
00594   public :: mpp_declare_pelist, mpp_get_current_pelist, mpp_set_current_pelist
00595 #ifdef use_shmalloc
00596   public :: mpp_malloc
00597 #endif
00598 
00599   contains
00600 
00601 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00602 !                                                                             !
00603 !       ROUTINES TO INITIALIZE/FINALIZE MPP MODULE: mpp_init, mpp_exit        !
00604 !                                                                             !
00605 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
00606 
00607     subroutine mpp_init( flags,mpp_comm ,logfile)
00608       integer, optional, intent(in) :: flags,mpp_comm
00609       character(len=*), optional, intent(in) :: logfile
00610 !    subroutine mpp_init( flags, in, out, err, log )
00611 !      integer, optional, intent(in) :: flags, in, out, err, log
00612       integer :: my_pe, num_pes, len
00613       integer :: i
00614       integer :: comm_intern
00615       logical :: opened
00616 #ifdef _CRAYT3E
00617       intrinsic my_pe
00618 #endif
00619 
00620       if( module_is_initialized )return
00621 
00622 #ifdef use_libSMA
00623       call START_PES(0)         !the argument 0 means extract from environment variable NPES on PVP/SGI, from mpprun -n on t3e
00624       pe = my_pe()
00625       node = pe                 !on an SMP this should return node ID rather than PE number.
00626       npes = num_pes()
00627 #elif use_libMPI
00628       call MPI_INITIALIZED( opened, error ) !in case called from another MPI package
00629       if(PRESENT(mpp_comm)) then
00630         comm_intern=mpp_comm
00631       else
00632         comm_intern=MPI_COMM_WORLD
00633       endif
00634 !
00635       if(present(logfile)) then
00636         etcfile=trim(logfile)
00637         configfile=trim(logfile)
00638         logfile_defined=.true.
00639       endif
00640 !
00641       if( .NOT.opened )then
00642       call MPI_INIT(error)
00643         comm_intern=MPI_COMM_WORLD
00644       endif
00645       call MPI_COMM_RANK(  comm_intern, pe,   error )
00646       call MPI_COMM_SIZE(  comm_intern, npes, error )
00647       allocate( mpp_request(0:npes-1) )
00648       mpp_request(:) = MPI_REQUEST_NULL
00649 #endif
00650       module_is_initialized = .TRUE.
00651 
00652 !PEsets: make defaults illegal
00653       peset(:)%count = -1
00654 #ifdef use_libSMA
00655       peset(:)%start = -1
00656       peset(:)%log2stride = -1
00657 #elif use_libMPI
00658       peset(:)%id = -1
00659       peset(:)%group = -1
00660 #endif
00661 !0=single-PE, initialized so that count returns 1
00662       peset(0)%count = 1
00663       allocate( peset(0)%list(1) )
00664       peset(0)%list = pe
00665 #ifdef use_libMPI
00666       current_peset_num = 0
00667       peset(0)%id = comm_intern
00668       call MPI_COMM_GROUP(  peset(0)%id, peset(0)%group, error )
00669 #endif
00670       world_peset_num = get_peset( (/(i,i=0,npes-1)/) )
00671       current_peset_num = world_peset_num !initialize current PEset to world
00672 
00673 !initialize clocks
00674       call SYSTEM_CLOCK( count=tick0, count_rate=ticks_per_sec, count_max=max_ticks )
00675       tick_rate = 1./ticks_per_sec
00676       clock0 = mpp_clock_id( 'Total runtime', flags=MPP_CLOCK_SYNC )
00677 
00678       if( PRESENT(flags) )then
00679           debug   = flags.EQ.MPP_DEBUG
00680           verbose = flags.EQ.MPP_VERBOSE .OR. debug
00681       end if
00682 
00683 #ifdef use_libSMA
00684 #ifdef use_shmalloc
00685 !we use shpalloc to ensure all these are remotely accessible
00686       len=0; ptr_sync = LOC(pe)   !null initialization
00687       call mpp_malloc( ptr_sync,        size(TRANSFER(sync,word)),            len )
00688       len=0; ptr_status = LOC(pe)  !null initialization
00689       call mpp_malloc( ptr_status, npes*size(TRANSFER(status(0),word)),   len )
00690       len=0; ptr_remote = LOC(pe) !null initialization
00691       call mpp_malloc( ptr_remote, npes*size(TRANSFER(remote_data_loc(0),word)), len )
00692       len=0; ptr_from = LOC(pe)   !null initialization
00693       call mpp_malloc( ptr_from,        size(TRANSFER(mpp_from_pe,word)),     len )
00694 #else
00695       allocate( status(0:npes-1) )
00696       allocate( remote_data_loc(0:npes-1) )
00697 #endif
00698       sync(:) = SHMEM_SYNC_VALUE
00699       status(0:npes-1) = MPP_READY
00700       remote_data_loc(0:npes-1) = MPP_WAIT
00701       call mpp_set_stack_size(32768) !default initial value
00702 #endif
00703 
00704 !logunit: log messages are written to configfile.out by default
00705       etc_unit=get_unit()
00706 !      write( etcfile,'(a,i4.4)' )trim(etcfile)//'.', pe
00707 !rv
00708 !rv Status 'REPLACE' eads to an unpredictable behaviour on SX-6
00709 !rv      if( pe.EQ.root_pe )open( unit=etc_unit, file=trim(etcfile), status='REPLACE' )
00710 !rv
00711       if( pe.EQ.root_pe )then
00712           if(logfile_defined) then
00713             inquire( file=trim(etcfile), opened=opened,number=io_num)
00714             if(opened) then
00715               etc_unit=io_num
00716             else
00717               open( unit=etc_unit, file=trim(etcfile), status='UNKNOWN' )
00718               close(etc_unit)
00719             endif
00720           else
00721             open( unit=etc_unit, file=trim(etcfile), status='UNKNOWN' )
00722             close(etc_unit)
00723           endif
00724       endif
00725 
00726       call mpp_sync()                         
00727 !rv
00728       if(present(logfile)) then
00729         inquire( file=trim(etcfile), opened=opened,number=io_num)
00730         if(opened) then
00731           if( pe.NE.root_pe ) then
00732             etc_unit=io_num
00733           endif
00734         else
00735           if( pe.NE.root_pe ) then
00736             open( unit=etc_unit, file=trim(etcfile), status='UNKNOWN' )
00737             close(etc_unit)
00738           endif
00739         endif
00740       else
00741         if( pe.NE.root_pe ) then
00742           open( unit=etc_unit, file=trim(etcfile), status='OLD' )
00743           close(etc_unit)
00744         endif
00745       endif
00746 !            write(0,*)'etc_unit=',etc_unit
00747 !rv
00748 
00749 !if optional argument logunit=stdout, write messages to stdout instead.
00750 !if specifying non-defaults, you must specify units not yet in use.
00751 !      if( PRESENT(in) )then
00752 !          inquire( unit=in, opened=opened )
00753 !          if( opened )call mpp_error( FATAL, 'MPP_INIT: unable to open stdin.' )
00754 !          in_unit=in
00755 !      end if
00756 !      if( PRESENT(out) )then
00757 !          inquire( unit=out, opened=opened )
00758 !          if( opened )call mpp_error( FATAL, 'MPP_INIT: unable to open stdout.' )
00759 !          out_unit=out
00760 !      end if
00761 !      if( PRESENT(err) )then
00762 !          inquire( unit=err, opened=opened )
00763 !          if( opened )call mpp_error( FATAL, 'MPP_INIT: unable to open stderr.' )
00764 !          err_unit=err
00765 !      end if
00766 !      log_unit=get_unit()
00767 !      if( PRESENT(log) )then
00768 !          inquire( unit=log, opened=opened )
00769 !          if( opened .AND. log.NE.out_unit )call mpp_error( FATAL, 'MPP_INIT: unable to open stdlog.' )
00770 !          log_unit=log
00771 !      end if
00772 !!log_unit can be written to only from root_pe, all others write to stdout
00773 !      if( log_unit.NE.out_unit )then
00774 !          inquire( unit=log_unit, opened=opened )
00775 !          if( opened )call mpp_error( FATAL, 'MPP_INIT: specified unit for stdlog already in use.' )
00776 !          if( pe.EQ.root_pe )open( unit=log_unit, file=trim(configfile), status='REPLACE' )
00777 !          call mpp_sync()
00778 !          if( pe.NE.root_pe )open( unit=log_unit, file=trim(configfile), status='OLD' )
00779 !      end if
00780       if( pe.EQ.root_pe )then
00781           log_unit = get_unit()
00782 !rv Status 'REPLACE' leads to an unpredictable  behaviour on the SX-6.
00783 !rv          open( unit=log_unit, file=trim(configfile), status='REPLACE' )
00784         if(logfile_defined) then
00785           inquire( file=trim(configfile), opened=opened,number=io_num)
00786           if(opened)then
00787             log_unit=io_num
00788           else
00789             open( unit=log_unit, file=trim(configfile), status='UNKNOWN' )
00790             close(log_unit)
00791           endif
00792         else
00793           open( unit=log_unit, file=trim(configfile), status='UNKNOWN' )
00794           close(log_unit)
00795         endif
00796       end if
00797 !messages
00798       if( verbose )call mpp_error( NOTE, 'MPP_INIT: initializing MPP module...' )
00799       if( pe.EQ.root_pe )then
00800           write( stdout(),'(/a)' )'MPP module '//trim(version)//trim(tagname)
00801           write( stdout(),'(a,i4)' )'MPP started with NPES=', npes
00802 #ifdef use_libSMA
00803           write( stdout(),'(a)' )'Using SMA (shmem) library for message passing...'
00804 #endif
00805 #ifdef use_libMPI
00806           write( stdout(),'(a)' )'Using MPI library for message passing...'
00807 #endif
00808           write( stdout(), '(a,es12.4,a,i20,a)' ) &
00809                'Realtime clock resolution=', tick_rate, ' sec (', ticks_per_sec, ' ticks/sec)'
00810           write( stdout(), '(a,es12.4,a,i20,a)' ) &
00811                'Clock rolls over after ', max_ticks*tick_rate, ' sec (', max_ticks, ' ticks)'
00812       end if
00813       call mpp_clock_begin(clock0)
00814 
00815       return
00816     end subroutine mpp_init
00817 
00818     function stdin()
00819       integer :: stdin
00820       stdin = in_unit
00821       return
00822     end function stdin
00823 
00824     function stdout()
00825       integer :: stdout
00826       integer::tmp_unit
00827       logical::opened
00828       stdout = out_unit
00829       if( pe.NE.root_pe ) then
00830         stdout = etc_unit
00831         inquire( file=trim(etcfile), opened=opened ,number=tmp_unit)
00832         if(.not.opened) open(file=etcfile,unit=etc_unit,status='UNKNOWN')
00833       endif
00834       if(logfile_defined)then
00835 
00836         if( pe.EQ.root_pe )then
00837             inquire( file=trim(etcfile), opened=opened ,number=tmp_unit)
00838             if( opened )then
00839 
00840                 out_unit=tmp_unit
00841                 stdout=out_unit
00842 !              write(0,*) 'stdout:',tmp_unit,etcfile
00843                call mpp_flushstd(out_unit)
00844 
00845             else
00846                 tmp_unit=get_unit()
00847 !              write(0,*) 'stdout(not):',tmp_unit,etcfile
00848 !ac
00849                 open( unit=tmp_unit, status='UNKNOWN', file=trim(etcfile), err=10 )
00850 !ac
00851               out_unit=tmp_unit
00852             end if
00853 
00854             stdout = out_unit
00855 
00856         endif
00857         
00858       endif
00859       return
00860  10 logfile_defined=.false.
00861     call mpp_error( FATAL, 'STDOUT: unable to open '//trim(etcfile))
00862     end function stdout
00863 
00864     function stderr()
00865       integer :: stderr
00866       integer :: tmp_unit
00867       logical :: opened
00868 
00869       stderr = err_unit
00870 
00871       if(logfile_defined)then
00872 
00873         if( pe.EQ.root_pe )then
00874             inquire( file=trim(configfile), opened=opened ,number=tmp_unit)
00875             if( opened )then
00876                 err_unit=tmp_unit
00877                 stderr=err_unit
00878                 call mpp_flushstd(err_unit)
00879 !              write(0,*) 'stderr:',tmp_unit
00880             else
00881 !              write(0,*) 'stderr(not):',tmp_unit
00882                 tmp_unit=get_unit()
00883 !ac
00884                 open( unit=tmp_unit, status='UNKNOWN', file=trim(configfile), err=10 )
00885 !ac
00886               err_unit=tmp_unit
00887             end if
00888 
00889             stderr = err_unit
00890 
00891         endif
00892         
00893       endif
00894       return
00895 
00896  10 logfile_defined=.false.
00897     call mpp_error( FATAL, 'STDERR: unable to open '//trim(configfile))
00898 
00899     end function stderr
00900 
00901     function stdlog()
00902       integer :: stdlog
00903       logical :: opened
00904       if( pe.EQ.root_pe )then
00905           inquire( file=trim(configfile), opened=opened )
00906           if( opened )then
00907           call mpp_flushstd(log_unit)
00908           else
00909               log_unit=get_unit()
00910 !ac
00911               open( unit=log_unit, status='UNKNOWN', file=trim(configfile), err=10 )
00912 !ac
00913           end if
00914           stdlog = log_unit
00915       else
00916           stdlog = etc_unit
00917       end if
00918       return
00919    10 call mpp_error( FATAL, 'STDLOG: unable to open '//trim(configfile)//'.' )
00920     end function stdlog
00921 
00922     subroutine mpp_exit()
00923 !to be called at the end of a run
00924       integer :: i, j, k, n, nmax
00925       real :: t, tmin, tmax, tavg, tstd
00926       real :: m, mmin, mmax, mavg, mstd
00927       real :: t_total
00928 
00929       if( .NOT.module_is_initialized )return
00930       call mpp_clock_end(clock0)
00931       t_total = clocks(clock0)%total_ticks*tick_rate
00932       if( clock_num.GT.0 )then
00933           if( ANY(clocks(1:clock_num)%detailed) )then
00934               call sum_clock_data; call dump_clock_summary
00935           end if
00936           if( pe.EQ.root_pe )then
00937               write( stdout(),'(/a,i4,a)' ) 'Tabulating mpp_clock statistics across ', npes, ' PEs...'
00938               if( ANY(clocks(1:clock_num)%detailed) ) &
00939                    write( stdout(),'(a)' )'   ... see mpp_clock.out.#### for details on individual PEs.'
00940               write( stdout(),'(/32x,a)' ) '          tmin          tmax          tavg          tstd  tfrac'
00941           end if
00942           do i = 1,clock_num
00943              call mpp_set_current_pelist() !implied global barrier
00944              current_peset_num = clocks(i)%peset_num
00945              if( .NOT.ANY(peset(current_peset_num)%list(:).EQ.pe) )cycle
00946 !times between mpp_clock ticks
00947              t = clocks(i)%total_ticks*tick_rate
00948              tmin = t; call mpp_min(tmin)
00949              tmax = t; call mpp_max(tmax)
00950              tavg = t; call mpp_sum(tavg); tavg = tavg/mpp_npes()
00951              tstd = (t-tavg)**2; call mpp_sum(tstd); tstd = sqrt( tstd/mpp_npes() )
00952              if( pe.EQ.root_pe )write( stdout(),'(a32,4f14.6,f7.3)' ) &
00953                   clocks(i)%name, tmin, tmax, tavg, tstd, tavg/t_total
00954           end do
00955           if( ANY(clocks(1:clock_num)%detailed) .AND. pe.EQ.root_pe )write( stdout(),'(/32x,a)' ) &
00956                '       tmin       tmax       tavg       tstd       mmin       mmax       mavg       mstd  mavg/tavg'
00957           do i = 1,clock_num
00958 !messages: bytelengths and times
00959          if( .NOT.clocks(i)%detailed )cycle
00960              do j = 1,MAX_EVENT_TYPES
00961                 n = clocks(i)%events(j)%calls; nmax = n
00962                 call mpp_max(nmax)
00963                 if( nmax.NE.0 )then
00964 !don't divide by n because n might be 0
00965                     m = 0
00966                     if( n.GT.0 )m = sum(clocks(i)%events(j)%bytes(1:n))
00967                     mmin = m; call mpp_min(mmin)
00968                     mmax = m; call mpp_max(mmax)
00969                     mavg = m; call mpp_sum(mavg); mavg = mavg/mpp_npes()
00970                     mstd = (m-mavg)**2; call mpp_sum(mstd); mstd = sqrt( mstd/mpp_npes() )
00971                     t = 0
00972                     if( n.GT.0 )t = sum(clocks(i)%events(j)%ticks(1:n))*tick_rate
00973                     tmin = t; call mpp_min(tmin)
00974                     tmax = t; call mpp_max(tmax)
00975                     tavg = t; call mpp_sum(tavg); tavg = tavg/mpp_npes()
00976                     tstd = (t-tavg)**2; call mpp_sum(tstd); tstd = sqrt( tstd/mpp_npes() )
00977                     if( pe.EQ.root_pe )write( stdout(),'(a32,4f11.3,5es11.3)' ) &
00978                          trim(clocks(i)%name)//' '//trim(clocks(i)%events(j)%name), &
00979                          tmin, tmax, tavg, tstd, mmin, mmax, mavg, mstd, mavg/tavg
00980                 end if
00981              end do
00982           end do
00983       end if
00984       call mpp_set_current_pelist()
00985       call mpp_sync()
00986       call mpp_max(mpp_stack_hwm)
00987       if( pe.EQ.root_pe )write( stdout(),* )'MPP_STACK high water mark=', mpp_stack_hwm
00988 #ifdef use_libMPI
00989 !reiner Let's do the MPI_finalize outside the mpp environment
00990 !reiner      call MPI_FINALIZE(error)
00991 #endif
00992 
00993       return
00994     end subroutine mpp_exit
00995 
00996     function mpp_pe()
00997       integer :: mpp_pe
00998 
00999       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_PE: You must first call mpp_init.' )
01000       mpp_pe = pe
01001       return
01002     end function mpp_pe
01003 
01004     function mpp_node()
01005       integer :: mpp_node
01006 
01007       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_NODE: You must first call mpp_init.' )
01008       mpp_node = node
01009       return
01010     end function mpp_node
01011 
01012     function mpp_npes()
01013       integer :: mpp_npes
01014 
01015       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_NPES: You must first call mpp_init.' )
01016 !      mpp_npes = npes
01017       mpp_npes = size(peset(current_peset_num)%list)
01018       return
01019     end function mpp_npes
01020 
01021     function mpp_root_pe()
01022       integer :: mpp_root_pe
01023 
01024       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_ROOT_PE: You must first call mpp_init.' )
01025       mpp_root_pe = root_pe
01026       return
01027     end function mpp_root_pe
01028 
01029     subroutine mpp_set_root_pe(num)
01030       integer, intent(in) :: num
01031       logical :: opened
01032 
01033       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_SET_ROOT_PE: You must first call mpp_init.' )
01034       if( .NOT.(ANY(num.EQ.peset(current_peset_num)%list)) ) &
01035            call mpp_error( FATAL, 'MPP_SET_ROOT_PE: you cannot set a root PE outside the current pelist.' )
01036 !actions to take if root_pe has changed:
01037 ! open log_unit on new root_pe, close it on old root_pe and point its log_unit to stdout.
01038 !      if( num.NE.root_pe )then  !root_pe has changed
01039 !          if( pe.EQ.num )then
01040 !!on the new root_pe
01041 !              if( log_unit.NE.out_unit )then
01042 !                  inquire( unit=log_unit, opened=opened )
01043 !                  if( .NOT.opened )open( unit=log_unit, status='OLD', file=trim(configfile), position='APPEND' )
01044 !              end if
01045 !          else if( pe.EQ.root_pe )then
01046 !!on the old root_pe
01047 !              if( log_unit.NE.out_unit )then
01048 !                  inquire( unit=log_unit, opened=opened )
01049 !                  if( opened )close(log_unit)
01050 !                  log_unit = out_unit
01051 !              end if
01052 !          end if
01053 !      end if
01054       root_pe = num
01055       return
01056     end subroutine mpp_set_root_pe
01057 
01058     subroutine mpp_declare_pelist( pelist, name )
01059 !this call is written specifically to accommodate a brain-dead MPI restriction
01060 !that requires a parent communicator to create a child communicator:
01061 !in other words: a pelist cannot go off and declare a communicator, but every PE
01062 !in the parent, including those not in pelist(:), must get together for the
01063 !MPI_COMM_CREATE call. The parent is typically  peset(0)%id, though it could also
01064 !be a subset that includes all PEs in pelist.
01065 !This restriction does not apply to SMA but to have uniform code,
01066 !you may as well call it. It must be placed in a context where all PEs call it.
01067 !Subsequent calls that use the pelist should be called PEs in the pelist only.
01068       integer, intent(in) :: pelist(:)
01069       character(len=*), optional :: name
01070       integer :: i
01071 
01072       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_DECLARE_PELIST: You must first call mpp_init.' )
01073       i = get_peset(pelist)
01074       write( peset(i)%name,'(a,i2.2)' ) 'PElist', i !default name
01075       if( PRESENT(name) )peset(i)%name = name
01076       return
01077     end subroutine mpp_declare_pelist
01078 
01079     subroutine mpp_set_current_pelist( pelist )
01080 !Once we branch off into a PE subset, we want subsequent "global" calls to
01081 !sync only across this subset. This is declared as the current pelist (peset(current_peset_num)%list)
01082 !when current_peset all pelist ops with no pelist should apply the current pelist.
01083 !also, we set the start PE in this pelist to be the root_pe.
01084 !unlike mpp_declare_pelist, this is called by the PEs in the pelist only
01085 !so if the PEset has not been previously declared, this will hang in MPI.
01086 !if pelist is omitted, we reset pelist to the world pelist.
01087       integer, intent(in), optional :: pelist(:)
01088       integer :: i
01089 
01090       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_SET_CURRENT_PELIST: You must first call mpp_init.' )
01091       if( PRESENT(pelist) )then
01092           if( .NOT.ANY(pe.EQ.pelist) )call mpp_error( FATAL, 'MPP_SET_CURRENT_PELIST: pe must be in pelist.' )
01093           current_peset_num = get_peset(pelist)
01094       else
01095           current_peset_num = world_peset_num
01096       end if
01097       call mpp_set_root_pe( MINVAL(peset(current_peset_num)%list) )
01098       call mpp_sync()           !this is called to make sure everyone in the current pelist is here.
01099 !      npes = mpp_npes()
01100       return
01101     end subroutine mpp_set_current_pelist
01102 
01103     subroutine mpp_get_current_pelist( pelist, name )
01104 !this is created for use by mpp_define_domains within a pelist
01105 !will be published but not publicized
01106       integer, intent(out) :: pelist(:)
01107       character(len=*), intent(out), optional :: name
01108 
01109       if( size(pelist).NE.size(peset(current_peset_num)%list) ) &
01110            call mpp_error( FATAL, 'MPP_GET_CURRENT_PELIST: size(pelist) is wrong.' )
01111       pelist(:) = peset(current_peset_num)%list(:)
01112       if( PRESENT(name) )name = peset(current_peset_num)%name
01113 
01114       return
01115     end subroutine mpp_get_current_pelist
01116 
01117     function get_peset(pelist)
01118       integer :: get_peset
01119 !makes a PE set out of a PE list
01120 !a PE list is an ordered list of PEs
01121 !a PE set is a triad (start,log2stride,size) for SHMEM, an a communicator for MPI
01122 !if stride is non-uniform or not a power of 2, will return error (not required for MPI but enforced for uniformity)
01123       integer, intent(in), optional :: pelist(:)
01124       integer :: group
01125       integer :: i, n, stride
01126       integer, allocatable :: sorted(:)
01127 
01128       if( .NOT.PRESENT(pelist) )then !set it to current_peset_num
01129           get_peset = current_peset_num; return
01130       end if
01131       if( size(pelist).EQ.1 .AND. npes.GT.1 )then    !collective ops on single PEs should return
01132           get_peset = 0; return
01133       end if
01134 !make a sorted list
01135       n = 1
01136       if( ascend_sort(pelist).NE.1 )call mpp_error( FATAL, 'GET_PESET: sort error.' )   !result is the array sorted(:)
01137       if( debug )write( stderr(),* )'pelist=', pelist, ' sorted=', sorted
01138 !find if this array matches any existing peset
01139       do i = 1,peset_num
01140          if( debug )write( stderr(),'(a,3i4)' )'pe, i, peset_num=', pe, i, peset_num
01141          if( size(sorted).EQ.size(peset(i)%list) )then
01142              if( ALL(sorted.EQ.peset(i)%list) )then
01143                  deallocate(sorted)
01144                  get_peset = i; return
01145              end if
01146          end if
01147       end do
01148 !not found, so create new peset
01149       peset_num = peset_num + 1
01150       if( peset_num.GE.PESET_MAX )call mpp_error( FATAL, 'GET_PESET: number of PE sets exceeds PESET_MAX.' )
01151       i = peset_num             !shorthand
01152 !create list
01153       allocate( peset(i)%list(size(sorted)) )
01154       peset(i)%list(:) = sorted(:)
01155       peset(i)%count = size(sorted)
01156 #ifdef use_libSMA
01157       peset(i)%start = sorted(1)
01158       if( size(sorted).GT.1 )then
01159           stride = sorted(2)-sorted(1)
01160           if( ANY(sorted(2:n)-sorted(1:n-1).NE.stride) ) &
01161                call mpp_error( WARNING, 'GET_PESET: pelist must have constant stride.' )
01162           peset(i)%log2stride = nint( log(real(stride))/log(2.) )
01163           if( 2**peset(i)%log2stride.NE.stride )call mpp_error( WARNING, 'GET_PESET: pelist must have power-of-2 stride.' )
01164       else
01165           peset(i)%log2stride = 0
01166       end if
01167 #elif use_libMPI
01168       call MPI_GROUP_INCL( peset(current_peset_num)%group, size(sorted), sorted, peset(i)%group, error )
01169       call MPI_COMM_CREATE( peset(current_peset_num)%id, peset(i)%group, peset(i)%id, error )
01170 #endif
01171       deallocate(sorted)
01172       get_peset = i
01173 
01174       return
01175 
01176       contains
01177         
01178         recursive function ascend_sort(a) result(a_sort)
01179           integer :: a_sort
01180           integer, intent(in) :: a(:)
01181           integer :: b, i
01182           if( size(a).EQ.1 .OR. ALL(a.EQ.a(1)) )then
01183               allocate( sorted(n) )
01184               sorted(n) = a(1)
01185               a_sort = n
01186               return
01187           end if
01188           b = minval(a)
01189           n = n + 1
01190           i = ascend_sort( pack(a,mask=a.NE.b) )
01191           a_sort = i - 1
01192           sorted(i-1) = b
01193           return
01194         end function ascend_sort
01195 
01196     end function get_peset
01197 
01198 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01199 !                                                                             !
01200 !                        PERFORMANCE PROFILING CALLS                          !
01201 !                                                                             !
01202 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01203     subroutine mpp_clock_set_grain( grain )
01204       integer, intent(in) :: grain
01205 !set the granularity of times: only clocks whose grain is lower than
01206 !clock_grain are triggered, finer-grained clocks are dormant.
01207 !clock_grain is initialized to HUGE(1), so all clocks are triggered if
01208 !this is never called.   
01209       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_CLOCK_SET_GRAIN: You must first call mpp_init.' )
01210 
01211       clock_grain = grain
01212       return
01213     end subroutine mpp_clock_set_grain
01214 
01215     function mpp_clock_id( name, flags, grain )
01216 !return an ID for a new or existing clock
01217       integer :: mpp_clock_id
01218       character(len=*), intent(in) :: name
01219       integer, intent(in), optional :: flags, grain
01220       integer :: i
01221 
01222       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_CLOCK_ID: You must first call mpp_init.' )
01223 !if grain is present, the clock is only triggered if it
01224 !is low ("coarse") enough: compared to clock_grain
01225 !finer-grained clocks are dormant.
01226 !if grain is absent, clock is triggered.
01227       if( PRESENT(grain) )then
01228           if( grain.GT.clock_grain )then
01229               mpp_clock_id = 0
01230               return
01231           end if
01232       end if
01233       mpp_clock_id = 1
01234       if( clock_num.EQ.0 )then  !first
01235 !         allocate( clocks(MAX_CLOCKS) )
01236           clock_num = mpp_clock_id
01237           call clock_init(mpp_clock_id,name,flags)
01238       else
01239           FIND_CLOCK: do while( trim(name).NE.trim(clocks(mpp_clock_id)%name) )
01240              mpp_clock_id = mpp_clock_id + 1
01241              if( mpp_clock_id.GT.clock_num )then
01242                  if( mpp_clock_id.GT.MAX_CLOCKS )then
01243                      call mpp_error( WARNING, 'MPP_CLOCK_ID: too many clock requests, this one is ignored.' )
01244                  else               !new clock: initialize
01245                      clock_num = mpp_clock_id
01246                      call clock_init(mpp_clock_id,name,flags)
01247                      exit FIND_CLOCK
01248                  end if
01249              end if
01250           end do FIND_CLOCK
01251       endif
01252       return
01253     end function mpp_clock_id
01254 
01255     subroutine mpp_clock_begin(id)
01256       integer, intent(in) :: id
01257 
01258       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_CLOCK_BEGIN: You must first call mpp_init.' )
01259       if( id.EQ.0 )return
01260       if( id.LT.0 .OR. id.GT.clock_num )call mpp_error( FATAL, 'MPP_CLOCK_BEGIN: invalid id.' )
01261 
01262       if( clocks(id)%peset_num.EQ.0 )clocks(id)%peset_num = current_peset_num
01263       if( clocks(id)%peset_num.NE.current_peset_num ) &
01264            call mpp_error( FATAL, 'MPP_CLOCK_BEGIN: cannot change pelist context of a clock.' )
01265       if( clocks(id)%sync_on_begin )then
01266 !do an untimed sync at the beginning of the clock
01267 !this puts all PEs in the current pelist on par, so that measurements begin together
01268 !ending time will be different, thus measuring load imbalance for this clock.
01269           current_clock = 0; call mpp_sync()
01270       end if
01271       current_clock = id
01272       call SYSTEM_CLOCK( clocks(id)%tick )
01273       return
01274     end subroutine mpp_clock_begin
01275 
01276     subroutine mpp_clock_end(id)
01277 !the id argument is not used for anything at present
01278       integer, intent(in), optional :: id
01279       integer(LONG_KIND) :: delta
01280 
01281       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_CLOCK_END: You must first call mpp_init.' )
01282       if( id.EQ.0 )return
01283       if( id.LT.0 .OR. id.GT.clock_num )call mpp_error( FATAL, 'MPP_CLOCK_BEGIN: invalid id.' )
01284       call SYSTEM_CLOCK(end_tick)
01285       if( clocks(id)%peset_num.NE.current_peset_num ) &
01286            call mpp_error( FATAL, 'MPP_CLOCK_END: cannot change pelist context of a clock.' )
01287       delta = end_tick - clocks(id)%tick
01288       if( delta.LT.0 )then
01289           write( stderr(),* )'pe, id, start_tick, end_tick, delta, max_ticks=', pe, id, clocks(id)%tick, end_tick, delta, max_ticks
01290           delta = delta + max_ticks + 1
01291           call mpp_error( WARNING, 'MPP_CLOCK_END: Clock rollover, assumed single roll.' )
01292       end if
01293       clocks(id)%total_ticks = clocks(id)%total_ticks + delta
01294       current_clock = 0
01295       return
01296     end subroutine mpp_clock_end
01297 
01298     subroutine increment_current_clock( event_id, bytes )
01299       integer, intent(in) :: event_id
01300       integer, intent(in), optional :: bytes
01301       integer :: n
01302       integer(LONG_KIND) :: delta
01303 
01304       if( current_clock.EQ.0 )return
01305       if( current_clock.LT.0 .OR. current_clock.GT.clock_num )call mpp_error( FATAL, 'MPP_CLOCK_BEGIN: invalid current_clock.' )
01306       if( .NOT.clocks(current_clock)%detailed )return
01307       call SYSTEM_CLOCK(end_tick)
01308       n = clocks(current_clock)%events(event_id)%calls + 1
01309 
01310       if( n.EQ.MAX_EVENTS )call mpp_error( WARNING, &
01311            'MPP_CLOCK: events exceed MAX_EVENTS, ignore detailed profiling data for clock '//trim(clocks(current_clock)%name) )
01312       if( n.GT.MAX_EVENTS )return
01313 
01314       clocks(current_clock)%events(event_id)%calls = n
01315       delta = end_tick - start_tick
01316       if( delta.LT.0 )then
01317           delta = delta + max_ticks + 1
01318           call mpp_error( WARNING, 'MPP_CLOCK_END: Clock rollover, assumed single roll.' )
01319       end if
01320       clocks(current_clock)%events(event_id)%ticks(n) = delta
01321       if( PRESENT(bytes) )clocks(current_clock)%events(event_id)%bytes(n) = bytes
01322       return
01323     end subroutine increment_current_clock
01324 
01325   subroutine dump_clock_summary()
01326     implicit none
01327 
01328     real :: total_time,total_time_all,total_data
01329     real :: msg_size,eff_BW,s
01330     integer :: SD_UNIT
01331     integer :: total_calls
01332     integer :: i,j,k,ct
01333     integer :: msg_cnt
01334     character(len=2)  :: u
01335     character(len=18) :: filename
01336     character(len=20),dimension(MAX_BINS),save :: bin
01337 
01338     data bin( 1)  /'  0   -    8    B:  '/
01339     data bin( 2)  /'  8   -   16    B:  '/
01340     data bin( 3)  /' 16   -   32    B:  '/
01341     data bin( 4)  /' 32   -   64    B:  '/
01342     data bin( 5)  /' 64   -  128    B:  '/
01343     data bin( 6)  /'128   -  256    B:  '/
01344     data bin( 7)  /'256   -  512    B:  '/
01345     data bin( 8)  /'512   - 1024    B:  '/
01346     data bin( 9)  /'  1.0 -    2.1 KB:  '/
01347     data bin(10)  /'  2.1 -    4.1 KB:  '/
01348     data bin(11)  /'  4.1 -    8.2 KB:  '/
01349     data bin(12)  /'  8.2 -   16.4 KB:  '/
01350     data bin(13)  /' 16.4 -   32.8 KB:  '/
01351     data bin(14)  /' 32.8 -   65.5 KB:  '/
01352     data bin(15)  /' 65.5 -  131.1 KB:  '/
01353     data bin(16)  /'131.1 -  262.1 KB:  '/
01354     data bin(17)  /'262.1 -  524.3 KB:  '/
01355     data bin(18)  /'524.3 - 1048.6 KB:  '/
01356     data bin(19)  /'  1.0 -    2.1 MB:  '/
01357     data bin(20)  /' >2.1          MB:  '/
01358 
01359     if( .NOT.ANY(clocks(1:clock_num)%detailed) )return
01360     write( filename,'(a,i4.4)' )'mpp_clock.out.', pe
01361 
01362     SD_UNIT = get_unit()
01363     open(SD_UNIT,file=trim(filename),form='formatted')
01364 
01365     COMM_TYPE: do ct = 1,clock_num
01366 
01367       if( .NOT.clocks(ct)%detailed )cycle
01368       write(SD_UNIT,*) &
01369           clock_summary(ct)%name(1:15),' Communication Data for PE ',pe
01370 
01371       write(SD_UNIT,*) ' '
01372       write(SD_UNIT,*) ' '
01373 
01374       total_time_all = 0.0
01375       EVENT_TYPE: do k = 1,MAX_EVENT_TYPES-1
01376 
01377         if(clock_summary(ct)%event(k)%total_time == 0.0)cycle
01378 
01379         total_time = clock_summary(ct)%event(k)%total_time
01380         total_time_all = total_time_all + total_time
01381         total_data = clock_summary(ct)%event(k)%total_data
01382         total_calls = clock_summary(ct)%event(k)%total_cnts
01383 
01384         write(SD_UNIT,1000) clock_summary(ct)%event(k)%name(1:9) // ':'
01385 
01386         write(SD_UNIT,1001) 'Total Data: ',total_data*1.0e-6, &
01387                             'MB; Total Time: ', total_time, &
01388                             'secs; Total Calls: ',total_calls
01389 
01390         write(SD_UNIT,*) ' '
01391         write(SD_UNIT,1002) '     Bin            Counts      Avg Size        Eff B/W'
01392         write(SD_UNIT,*) ' '
01393 
01394         BIN_LOOP: do j=1,MAX_BINS
01395 
01396           if(clock_summary(ct)%event(k)%msg_size_cnts(j)==0)cycle
01397 
01398           if(j<=8)then
01399             s = 1.0
01400             u = ' B'
01401           elseif(j<=18)then
01402             s = 1.0e-3
01403             u = 'KB'
01404           else
01405             s = 1.0e-6
01406             u = 'MB'
01407           endif
01408 
01409           msg_cnt = clock_summary(ct)%event(k)%msg_size_cnts(j)
01410           msg_size = &
01411             s*(clock_summary(ct)%event(k)%msg_size_sums(j)/real(msg_cnt))
01412           eff_BW = (1.0e-6)*( clock_summary(ct)%event(k)%msg_size_sums(j) / &
01413                                   clock_summary(ct)%event(k)%msg_time_sums(j) )
01414 
01415           write(SD_UNIT,1003) bin(j),msg_cnt,msg_size,u,eff_BW
01416 
01417         end do BIN_LOOP
01418 
01419         write(SD_UNIT,*) ' '
01420         write(SD_UNIT,*) ' '
01421       end do EVENT_TYPE
01422 
01423    ! "Data-less" WAIT
01424 
01425       if(clock_summary(ct)%event(MAX_EVENT_TYPES)%total_time>0.0)then
01426 
01427         total_time = clock_summary(ct)%event(MAX_EVENT_TYPES)%total_time
01428         total_time_all = total_time_all + total_time
01429         total_calls = clock_summary(ct)%event(MAX_EVENT_TYPES)%total_cnts
01430 
01431         write(SD_UNIT,1000) clock_summary(ct)%event(MAX_EVENT_TYPES)%name(1:9) // ':'
01432 
01433         write(SD_UNIT,1004) 'Total Calls: ',total_calls,'; Total Time: ', &
01434                              total_time,'secs'
01435 
01436       endif
01437 
01438       write(SD_UNIT,*) ' '
01439       write(SD_UNIT,1005) 'Total communication time spent for ' // &
01440                       clock_summary(ct)%name(1:9) // ': ',total_time_all,'secs'
01441       write(SD_UNIT,*) ' '
01442       write(SD_UNIT,*) ' '
01443       write(SD_UNIT,*) ' '
01444 
01445     end do COMM_TYPE
01446 
01447     close(SD_UNIT)
01448 
01449 1000  format(a)
01450 1001  format(a,f8.2,a,f8.2,a,i6)
01451 1002  format(a)
01452 1003  format(a,i6,'    ','  ',f6.1,a,'    ',f7.3,'MB/sec')
01453 1004  format(a,i8,a,f9.2,a)
01454 1005  format(a,f9.2,a)
01455     return
01456   end subroutine dump_clock_summary
01457 
01458       integer function get_unit()
01459         implicit none
01460 
01461         integer,save :: i
01462         logical :: l_open
01463 
01464         i = 10
01465         do i=10,99
01466            inquire(unit=i,opened=l_open)
01467            if(.not.l_open)exit
01468         end do
01469 
01470         if(i==100)then
01471             call mpp_error(FATAL,'Unable to get I/O unit')
01472         else
01473             get_unit = i
01474         endif
01475 
01476         return
01477       end function get_unit
01478 
01479   subroutine sum_clock_data()
01480     implicit none
01481 
01482     integer :: i,j,k,ct,event_size,event_cnt
01483     real    :: msg_time
01484 
01485     CLOCK_TYPE: do ct=1,clock_num
01486       if( .NOT.clocks(ct)%detailed )cycle
01487       EVENT_TYPE: do j=1,MAX_EVENT_TYPES-1
01488         event_cnt = clocks(ct)%events(j)%calls
01489         EVENT_SUMMARY: do i=1,event_cnt
01490 
01491         clock_summary(ct)%event(j)%total_cnts = &
01492               clock_summary(ct)%event(j)%total_cnts + 1
01493 
01494         event_size = clocks(ct)%events(j)%bytes(i)
01495 
01496         k = find_bin(event_size)
01497 
01498         clock_summary(ct)%event(j)%msg_size_cnts(k) = &
01499               clock_summary(ct)%event(j)%msg_size_cnts(k) + 1
01500 
01501         clock_summary(ct)%event(j)%msg_size_sums(k) = &
01502               clock_summary(ct)%event(j)%msg_size_sums(k) &
01503             + clocks(ct)%events(j)%bytes(i)
01504 
01505         clock_summary(ct)%event(j)%total_data = &
01506               clock_summary(ct)%event(j)%total_data &
01507             + clocks(ct)%events(j)%bytes(i)
01508 
01509         msg_time = clocks(ct)%events(j)%ticks(i)
01510         msg_time = tick_rate * real( clocks(ct)%events(j)%ticks(i) )
01511 
01512         clock_summary(ct)%event(j)%msg_time_sums(k) = &
01513               clock_summary(ct)%event(j)%msg_time_sums(k) + msg_time
01514 
01515         clock_summary(ct)%event(j)%total_time = &
01516               clock_summary(ct)%event(j)%total_time + msg_time
01517 
01518         end do EVENT_SUMMARY
01519       end do EVENT_TYPE
01520 
01521       j = MAX_EVENT_TYPES ! WAITs
01522            ! "msg_size_cnts" doesn't really mean anything for WAIT
01523            ! but position will be used to store number of counts for now.
01524 
01525       event_cnt = clocks(ct)%events(j)%calls
01526       clock_summary(ct)%event(j)%msg_size_cnts(1) = event_cnt
01527       clock_summary(ct)%event(j)%total_cnts       = event_cnt
01528 
01529       msg_time = tick_rate * real( sum ( clocks(ct)%events(j)%ticks(1:event_cnt) ) )
01530       clock_summary(ct)%event(j)%msg_time_sums(1) = &
01531               clock_summary(ct)%event(j)%msg_time_sums(1) + msg_time
01532 
01533       clock_summary(ct)%event(j)%total_time = clock_summary(ct)%event(j)%msg_time_sums(1)
01534 
01535     end do CLOCK_TYPE
01536 
01537     return
01538     contains
01539       integer function find_bin(event_size)
01540         implicit none
01541 
01542         integer,intent(in) :: event_size
01543         integer :: k,msg_size
01544 
01545         msg_size = 8
01546         k = 1
01547         do while(event_size>msg_size .and. k<MAX_BINS)
01548            k = k+1
01549            msg_size = msg_size*2
01550         end do
01551         find_bin = k
01552         return
01553       end function find_bin
01554 
01555   end subroutine sum_clock_data
01556 
01557   subroutine clock_init(id,name,flags)
01558     integer, intent(in) :: id
01559     character(len=*), intent(in) :: name
01560     integer, intent(in), optional :: flags
01561     integer :: i
01562 
01563     clocks(id)%name = name
01564     clocks(id)%tick = 0
01565     clocks(id)%total_ticks = 0
01566     clocks(id)%sync_on_begin = .FALSE.
01567     clocks(id)%detailed      = .FALSE.
01568     clocks(id)%peset_num = 0
01569     if( PRESENT(flags) )then
01570         if( BTEST(flags,0) )clocks(id)%sync_on_begin = .TRUE.
01571         if( BTEST(flags,1) )clocks(id)%detailed      = .TRUE.
01572     end if
01573     if( clocks(id)%detailed )then
01574         allocate( clocks(id)%events(MAX_EVENT_TYPES) )
01575         clocks(id)%events(EVENT_ALLREDUCE)%name = 'ALLREDUCE'
01576         clocks(id)%events(EVENT_BROADCAST)%name = 'BROADCAST'
01577         clocks(id)%events(EVENT_RECV)%name = 'RECV'
01578         clocks(id)%events(EVENT_SEND)%name = 'SEND'
01579         clocks(id)%events(EVENT_WAIT)%name = 'WAIT'
01580         do i=1,MAX_EVENT_TYPES
01581            clocks(id)%events(i)%ticks(:) = 0
01582            clocks(id)%events(i)%bytes(:) = 0
01583            clocks(id)%events(i)%calls = 0
01584         end do
01585         clock_summary(id)%name = name
01586         clock_summary(id)%event(EVENT_ALLREDUCE)%name = 'ALLREDUCE'
01587         clock_summary(id)%event(EVENT_BROADCAST)%name = 'BROADCAST'
01588         clock_summary(id)%event(EVENT_RECV)%name = 'RECV'
01589         clock_summary(id)%event(EVENT_SEND)%name = 'SEND'
01590         clock_summary(id)%event(EVENT_WAIT)%name = 'WAIT'
01591         do i=1,MAX_EVENT_TYPES
01592            clock_summary(id)%event(i)%msg_size_sums(:) = 0.0
01593            clock_summary(id)%event(i)%msg_time_sums(:) = 0.0
01594            clock_summary(id)%event(i)%total_data = 0.0
01595            clock_summary(id)%event(i)%total_time = 0.0
01596            clock_summary(id)%event(i)%msg_size_cnts(:) = 0
01597            clock_summary(id)%event(i)%total_cnts = 0
01598         end do
01599     end if
01600     return
01601   end subroutine clock_init
01602 
01603 #ifdef __sgi
01604     subroutine system_clock_sgi( count, count_rate, count_max )
01605 !mimics F90 SYSTEM_CLOCK intrinsic
01606       integer(LONG_KIND), intent(out), optional :: count, count_rate, count_max
01607       integer(LONG_KIND) :: sgi_tick, sgi_ticks_per_sec, sgi_max_tick
01608 !sgi_max_tick currently returns 64
01609 !count must return a number between 0 and count_max
01610       integer(LONG_KIND), save :: maxtick=0
01611       if( maxtick.EQ.0 )then
01612           maxtick = sgi_max_tick() !actually reports #bits in maxtick
01613           if( maxtick.LT.BIT_SIZE(maxtick) )then
01614               maxtick = 2**maxtick
01615           else
01616               maxtick = huge(maxtick)
01617           end if
01618       end if
01619       if( PRESENT(count) )then
01620           count = modulo( sgi_tick()-tick0, maxtick )
01621 !          count = sgi_tick()
01622       end if
01623       if( PRESENT(count_rate) )then
01624           count_rate = sgi_ticks_per_sec()
01625       end if
01626       if( PRESENT(count_max) )then
01627           count_max = maxtick-1
01628       end if
01629       return
01630     end subroutine system_clock_sgi
01631 #endif
01632 
01633 
01634 #ifdef use_libMPI
01635     subroutine system_clock_mpi( count, count_rate, count_max )
01636 !mimics F90 SYSTEM_CLOCK intrinsic
01637       integer(LONG_KIND), intent(out), optional :: count, count_rate, count_max
01638 !count must return a number between 0 and count_max
01639       integer(LONG_KIND), parameter :: maxtick=HUGE(count_max)
01640       logical,           save       :: first_call = .true.
01641       real(DOUBLE_KIND), save       :: count0  ! use to prevent integer overflow
01642       if ( first_call ) count0 = MPI_WTime(); first_call = .false.
01643       if( PRESENT(count) )then
01644           count = (MPI_WTime()-count0)/MPI_WTick()
01645       end if
01646       if( PRESENT(count_rate) )then
01647           count_rate = MPI_Wtick()**(-1)
01648       end if
01649       if( PRESENT(count_max) )then
01650           count_max = maxtick-1
01651       end if
01652       return
01653     end subroutine system_clock_mpi
01654 #endif
01655 
01656 
01657 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01658 !                                                                             !
01659 !                BASIC MESSAGE PASSING ROUTINE: mpp_transmit                  !
01660 !                                                                             !
01661 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01662 
01663 #define MPP_TRANSMIT_ mpp_transmit_real8
01664 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_real8_scalar
01665 #define MPP_TRANSMIT_2D_ mpp_transmit_real8_2d
01666 #define MPP_TRANSMIT_3D_ mpp_transmit_real8_3d
01667 #define MPP_TRANSMIT_4D_ mpp_transmit_real8_4d
01668 #define MPP_TRANSMIT_5D_ mpp_transmit_real8_5d
01669 #define MPP_RECV_ mpp_recv_real8
01670 #define MPP_RECV_SCALAR_ mpp_recv_real8_scalar
01671 #define MPP_RECV_2D_ mpp_recv_real8_2d
01672 #define MPP_RECV_3D_ mpp_recv_real8_3d
01673 #define MPP_RECV_4D_ mpp_recv_real8_4d
01674 #define MPP_RECV_5D_ mpp_recv_real8_5d
01675 #define MPP_SEND_ mpp_send_real8
01676 #define MPP_SEND_SCALAR_ mpp_send_real8_scalar
01677 #define MPP_SEND_2D_ mpp_send_real8_2d
01678 #define MPP_SEND_3D_ mpp_send_real8_3d
01679 #define MPP_SEND_4D_ mpp_send_real8_4d
01680 #define MPP_SEND_5D_ mpp_send_real8_5d
01681 #define MPP_BROADCAST_ mpp_broadcast_real8
01682 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_real8_scalar
01683 #define MPP_BROADCAST_2D_ mpp_broadcast_real8_2d
01684 #define MPP_BROADCAST_3D_ mpp_broadcast_real8_3d
01685 #define MPP_BROADCAST_4D_ mpp_broadcast_real8_4d
01686 #define MPP_BROADCAST_5D_ mpp_broadcast_real8_5d
01687 #define MPP_TYPE_ real(DOUBLE_KIND)
01688 #define MPP_TYPE_BYTELEN_ 8
01689 #ifdef use_LAM_MPI
01690 #define MPI_TYPE_ MPI_DOUBLE_PRECISION
01691 #else 
01692 #define MPI_TYPE_ MPI_REAL8
01693 #endif
01694 #define SHMEM_BROADCAST_ SHMEM_BROADCAST8
01695 #define SHMEM_GET_ SHMEM_GET8
01696 #include <mpp_transmit.h>
01697 
01698 #ifndef no_4byte_reals
01699 #define MPP_TRANSMIT_ mpp_transmit_real4
01700 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_real4_scalar
01701 #define MPP_TRANSMIT_2D_ mpp_transmit_real4_2d
01702 #define MPP_TRANSMIT_3D_ mpp_transmit_real4_3d
01703 #define MPP_TRANSMIT_4D_ mpp_transmit_real4_4d
01704 #define MPP_TRANSMIT_5D_ mpp_transmit_real4_5d
01705 #define MPP_RECV_ mpp_recv_real4
01706 #define MPP_RECV_SCALAR_ mpp_recv_real4_scalar
01707 #define MPP_RECV_2D_ mpp_recv_real4_2d
01708 #define MPP_RECV_3D_ mpp_recv_real4_3d
01709 #define MPP_RECV_4D_ mpp_recv_real4_4d
01710 #define MPP_RECV_5D_ mpp_recv_real4_5d
01711 #define MPP_SEND_ mpp_send_real4
01712 #define MPP_SEND_SCALAR_ mpp_send_real4_scalar
01713 #define MPP_SEND_2D_ mpp_send_real4_2d
01714 #define MPP_SEND_3D_ mpp_send_real4_3d
01715 #define MPP_SEND_4D_ mpp_send_real4_4d
01716 #define MPP_SEND_5D_ mpp_send_real4_5d
01717 #define MPP_BROADCAST_ mpp_broadcast_real4
01718 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_real4_scalar
01719 #define MPP_BROADCAST_2D_ mpp_broadcast_real4_2d
01720 #define MPP_BROADCAST_3D_ mpp_broadcast_real4_3d
01721 #define MPP_BROADCAST_4D_ mpp_broadcast_real4_4d
01722 #define MPP_BROADCAST_5D_ mpp_broadcast_real4_5d
01723 #define MPP_TYPE_ real(FLOAT_KIND)
01724 #define MPP_TYPE_BYTELEN_ 4
01725 #ifdef use_LAM_MPI
01726 #define MPI_TYPE_ MPI_REAL
01727 #else
01728 #define MPI_TYPE_ MPI_REAL4
01729 #endif
01730 #define SHMEM_BROADCAST_ SHMEM_BROADCAST4
01731 #define SHMEM_GET_ SHMEM_GET4
01732 #include <mpp_transmit.h>
01733 #endif
01734 
01735 #define MPP_TRANSMIT_ mpp_transmit_cmplx8
01736 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_cmplx8_scalar
01737 #define MPP_TRANSMIT_2D_ mpp_transmit_cmplx8_2d
01738 #define MPP_TRANSMIT_3D_ mpp_transmit_cmplx8_3d
01739 #define MPP_TRANSMIT_4D_ mpp_transmit_cmplx8_4d
01740 #define MPP_TRANSMIT_5D_ mpp_transmit_cmplx8_5d
01741 #define MPP_RECV_ mpp_recv_cmplx8
01742 #define MPP_RECV_SCALAR_ mpp_recv_cmplx8_scalar
01743 #define MPP_RECV_2D_ mpp_recv_cmplx8_2d
01744 #define MPP_RECV_3D_ mpp_recv_cmplx8_3d
01745 #define MPP_RECV_4D_ mpp_recv_cmplx8_4d
01746 #define MPP_RECV_5D_ mpp_recv_cmplx8_5d
01747 #define MPP_SEND_ mpp_send_cmplx8
01748 #define MPP_SEND_SCALAR_ mpp_send_cmplx8_scalar
01749 #define MPP_SEND_2D_ mpp_send_cmplx8_2d
01750 #define MPP_SEND_3D_ mpp_send_cmplx8_3d
01751 #define MPP_SEND_4D_ mpp_send_cmplx8_4d
01752 #define MPP_SEND_5D_ mpp_send_cmplx8_5d
01753 #define MPP_BROADCAST_ mpp_broadcast_cmplx8
01754 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_cmplx8_scalar
01755 #define MPP_BROADCAST_2D_ mpp_broadcast_cmplx8_2d
01756 #define MPP_BROADCAST_3D_ mpp_broadcast_cmplx8_3d
01757 #define MPP_BROADCAST_4D_ mpp_broadcast_cmplx8_4d
01758 #define MPP_BROADCAST_5D_ mpp_broadcast_cmplx8_5d
01759 #define MPP_TYPE_ complex(DOUBLE_KIND)
01760 #define MPP_TYPE_BYTELEN_ 16
01761 #define MPI_TYPE_ MPI_DOUBLE_COMPLEX
01762 #define SHMEM_BROADCAST_ SHMEM_BROADCAST8
01763 #define SHMEM_GET_ SHMEM_GET128
01764 #include <mpp_transmit.h>
01765 
01766 #ifndef no_4byte_cmplx
01767 #define MPP_TRANSMIT_ mpp_transmit_cmplx4
01768 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_cmplx4_scalar
01769 #define MPP_TRANSMIT_2D_ mpp_transmit_cmplx4_2d
01770 #define MPP_TRANSMIT_3D_ mpp_transmit_cmplx4_3d
01771 #define MPP_TRANSMIT_4D_ mpp_transmit_cmplx4_4d
01772 #define MPP_TRANSMIT_5D_ mpp_transmit_cmplx4_5d
01773 #define MPP_RECV_ mpp_recv_cmplx4
01774 #define MPP_RECV_SCALAR_ mpp_recv_cmplx4_scalar
01775 #define MPP_RECV_2D_ mpp_recv_cmplx4_2d
01776 #define MPP_RECV_3D_ mpp_recv_cmplx4_3d
01777 #define MPP_RECV_4D_ mpp_recv_cmplx4_4d
01778 #define MPP_RECV_5D_ mpp_recv_cmplx4_5d
01779 #define MPP_SEND_ mpp_send_cmplx4
01780 #define MPP_SEND_SCALAR_ mpp_send_cmplx4_scalar
01781 #define MPP_SEND_2D_ mpp_send_cmplx4_2d
01782 #define MPP_SEND_3D_ mpp_send_cmplx4_3d
01783 #define MPP_SEND_4D_ mpp_send_cmplx4_4d
01784 #define MPP_SEND_5D_ mpp_send_cmplx4_5d
01785 #define MPP_BROADCAST_ mpp_broadcast_cmplx4
01786 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_cmplx4_scalar
01787 #define MPP_BROADCAST_2D_ mpp_broadcast_cmplx4_2d
01788 #define MPP_BROADCAST_3D_ mpp_broadcast_cmplx4_3d
01789 #define MPP_BROADCAST_4D_ mpp_broadcast_cmplx4_4d
01790 #define MPP_BROADCAST_5D_ mpp_broadcast_cmplx4_5d
01791 #define MPP_TYPE_ complex(FLOAT_KIND)
01792 #define MPP_TYPE_BYTELEN_ 8
01793 #define MPI_TYPE_ MPI_COMPLEX
01794 #define SHMEM_BROADCAST_ SHMEM_BROADCAST4
01795 #define SHMEM_GET_ SHMEM_GET64
01796 #include <mpp_transmit.h>
01797 #endif
01798 
01799 #ifndef no_8byte_integers
01800 #define MPP_TRANSMIT_ mpp_transmit_int8
01801 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_int8_scalar
01802 #define MPP_TRANSMIT_2D_ mpp_transmit_int8_2d
01803 #define MPP_TRANSMIT_3D_ mpp_transmit_int8_3d
01804 #define MPP_TRANSMIT_4D_ mpp_transmit_int8_4d
01805 #define MPP_TRANSMIT_5D_ mpp_transmit_int8_5d
01806 #define MPP_RECV_ mpp_recv_int8
01807 #define MPP_RECV_SCALAR_ mpp_recv_int8_scalar
01808 #define MPP_RECV_2D_ mpp_recv_int8_2d
01809 #define MPP_RECV_3D_ mpp_recv_int8_3d
01810 #define MPP_RECV_4D_ mpp_recv_int8_4d
01811 #define MPP_RECV_5D_ mpp_recv_int8_5d
01812 #define MPP_SEND_ mpp_send_int8
01813 #define MPP_SEND_SCALAR_ mpp_send_int8_scalar
01814 #define MPP_SEND_2D_ mpp_send_int8_2d
01815 #define MPP_SEND_3D_ mpp_send_int8_3d
01816 #define MPP_SEND_4D_ mpp_send_int8_4d
01817 #define MPP_SEND_5D_ mpp_send_int8_5d
01818 #define MPP_BROADCAST_ mpp_broadcast_int8
01819 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_int8_scalar
01820 #define MPP_BROADCAST_2D_ mpp_broadcast_int8_2d
01821 #define MPP_BROADCAST_3D_ mpp_broadcast_int8_3d
01822 #define MPP_BROADCAST_4D_ mpp_broadcast_int8_4d
01823 #define MPP_BROADCAST_5D_ mpp_broadcast_int8_5d
01824 #define MPP_TYPE_ integer(LONG_KIND)
01825 #define MPP_TYPE_BYTELEN_ 8
01826 #ifdef use_LAM_MPI
01827 #define MPI_TYPE_ MPI_INTEGER
01828 #else
01829 #define MPI_TYPE_ MPI_INTEGER8
01830 #endif
01831 #define SHMEM_BROADCAST_ SHMEM_BROADCAST8
01832 #define SHMEM_GET_ SHMEM_GET8
01833 #include <mpp_transmit.h>
01834 #endif
01835 
01836 #define MPP_TRANSMIT_ mpp_transmit_int4
01837 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_int4_scalar
01838 #define MPP_TRANSMIT_2D_ mpp_transmit_int4_2d
01839 #define MPP_TRANSMIT_3D_ mpp_transmit_int4_3d
01840 #define MPP_TRANSMIT_4D_ mpp_transmit_int4_4d
01841 #define MPP_TRANSMIT_5D_ mpp_transmit_int4_5d
01842 #define MPP_RECV_ mpp_recv_int4
01843 #define MPP_RECV_SCALAR_ mpp_recv_int4_scalar
01844 #define MPP_RECV_2D_ mpp_recv_int4_2d
01845 #define MPP_RECV_3D_ mpp_recv_int4_3d
01846 #define MPP_RECV_4D_ mpp_recv_int4_4d
01847 #define MPP_RECV_5D_ mpp_recv_int4_5d
01848 #define MPP_SEND_ mpp_send_int4
01849 #define MPP_SEND_SCALAR_ mpp_send_int4_scalar
01850 #define MPP_SEND_2D_ mpp_send_int4_2d
01851 #define MPP_SEND_3D_ mpp_send_int4_3d
01852 #define MPP_SEND_4D_ mpp_send_int4_4d
01853 #define MPP_SEND_5D_ mpp_send_int4_5d
01854 #define MPP_BROADCAST_ mpp_broadcast_int4
01855 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_int4_scalar
01856 #define MPP_BROADCAST_2D_ mpp_broadcast_int4_2d
01857 #define MPP_BROADCAST_3D_ mpp_broadcast_int4_3d
01858 #define MPP_BROADCAST_4D_ mpp_broadcast_int4_4d
01859 #define MPP_BROADCAST_5D_ mpp_broadcast_int4_5d
01860 #define MPP_TYPE_ integer(INT_KIND)
01861 #define MPP_TYPE_BYTELEN_ 4
01862 #ifdef use_LAM_MPI
01863 #define MPI_TYPE_ MPI_INTEGER
01864 #else
01865 #define MPI_TYPE_ MPI_INTEGER4
01866 #endif
01867 #define SHMEM_BROADCAST_ SHMEM_BROADCAST4
01868 #define SHMEM_GET_ SHMEM_GET4
01869 #include <mpp_transmit.h>
01870 
01871 #ifndef no_8byte_integers
01872 #define MPP_TRANSMIT_ mpp_transmit_logical8
01873 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_logical8_scalar
01874 #define MPP_TRANSMIT_2D_ mpp_transmit_logical8_2d
01875 #define MPP_TRANSMIT_3D_ mpp_transmit_logical8_3d
01876 #define MPP_TRANSMIT_4D_ mpp_transmit_logical8_4d
01877 #define MPP_TRANSMIT_5D_ mpp_transmit_logical8_5d
01878 #define MPP_RECV_ mpp_recv_logical8
01879 #define MPP_RECV_SCALAR_ mpp_recv_logical8_scalar
01880 #define MPP_RECV_2D_ mpp_recv_logical8_2d
01881 #define MPP_RECV_3D_ mpp_recv_logical8_3d
01882 #define MPP_RECV_4D_ mpp_recv_logical8_4d
01883 #define MPP_RECV_5D_ mpp_recv_logical8_5d
01884 #define MPP_SEND_ mpp_send_logical8
01885 #define MPP_SEND_SCALAR_ mpp_send_logical8_scalar
01886 #define MPP_SEND_2D_ mpp_send_logical8_2d
01887 #define MPP_SEND_3D_ mpp_send_logical8_3d
01888 #define MPP_SEND_4D_ mpp_send_logical8_4d
01889 #define MPP_SEND_5D_ mpp_send_logical8_5d
01890 #define MPP_BROADCAST_ mpp_broadcast_logical8
01891 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_logical8_scalar
01892 #define MPP_BROADCAST_2D_ mpp_broadcast_logical8_2d
01893 #define MPP_BROADCAST_3D_ mpp_broadcast_logical8_3d
01894 #define MPP_BROADCAST_4D_ mpp_broadcast_logical8_4d
01895 #define MPP_BROADCAST_5D_ mpp_broadcast_logical8_5d
01896 #define MPP_TYPE_ logical(LONG_KIND)
01897 #define MPP_TYPE_BYTELEN_ 8
01898 #ifdef use_LAM_MPI
01899 #define MPI_TYPE_ MPI_INTEGER
01900 #else
01901 #define MPI_TYPE_ MPI_INTEGER8
01902 #endif
01903 #define SHMEM_BROADCAST_ SHMEM_BROADCAST8
01904 #define SHMEM_GET_ SHMEM_GET8
01905 #include <mpp_transmit.h>
01906 #endif
01907 
01908 #define MPP_TRANSMIT_ mpp_transmit_logical4
01909 #define MPP_TRANSMIT_SCALAR_ mpp_transmit_logical4_scalar
01910 #define MPP_TRANSMIT_2D_ mpp_transmit_logical4_2d
01911 #define MPP_TRANSMIT_3D_ mpp_transmit_logical4_3d
01912 #define MPP_TRANSMIT_4D_ mpp_transmit_logical4_4d
01913 #define MPP_TRANSMIT_5D_ mpp_transmit_logical4_5d
01914 #define MPP_RECV_ mpp_recv_logical4
01915 #define MPP_RECV_SCALAR_ mpp_recv_logical4_scalar
01916 #define MPP_RECV_2D_ mpp_recv_logical4_2d
01917 #define MPP_RECV_3D_ mpp_recv_logical4_3d
01918 #define MPP_RECV_4D_ mpp_recv_logical4_4d
01919 #define MPP_RECV_5D_ mpp_recv_logical4_5d
01920 #define MPP_SEND_ mpp_send_logical4
01921 #define MPP_SEND_SCALAR_ mpp_send_logical4_scalar
01922 #define MPP_SEND_2D_ mpp_send_logical4_2d
01923 #define MPP_SEND_3D_ mpp_send_logical4_3d
01924 #define MPP_SEND_4D_ mpp_send_logical4_4d
01925 #define MPP_SEND_5D_ mpp_send_logical4_5d
01926 #define MPP_BROADCAST_ mpp_broadcast_logical4
01927 #define MPP_BROADCAST_SCALAR_ mpp_broadcast_logical4_scalar
01928 #define MPP_BROADCAST_2D_ mpp_broadcast_logical4_2d
01929 #define MPP_BROADCAST_3D_ mpp_broadcast_logical4_3d
01930 #define MPP_BROADCAST_4D_ mpp_broadcast_logical4_4d
01931 #define MPP_BROADCAST_5D_ mpp_broadcast_logical4_5d
01932 #define MPP_TYPE_ logical(INT_KIND)
01933 #define MPP_TYPE_BYTELEN_ 4
01934 #ifdef use_LAM_MPI
01935 #define MPI_TYPE_ MPI_INTEGER
01936 #else
01937 #define MPI_TYPE_ MPI_INTEGER4
01938 #endif
01939 #define SHMEM_BROADCAST_ SHMEM_BROADCAST4
01940 #define SHMEM_GET_ SHMEM_GET4
01941 #include <mpp_transmit.h>
01942 
01943 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01944 !                                                                             !
01945 !            GLOBAL REDUCTION ROUTINES: mpp_max, mpp_sum, mpp_min             !
01946 !                                                                             !
01947 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
01948 
01949 #define MPP_REDUCE_ mpp_max_real8
01950 #define MPP_TYPE_ real(DOUBLE_KIND)
01951 #define SHMEM_REDUCE_ SHMEM_REAL8_MAX_TO_ALL
01952 #ifdef use_LAM_MPI
01953 #define MPI_TYPE_ MPI_DOUBLE_PRECISION
01954 #else
01955 #define MPI_TYPE_ MPI_REAL8
01956 #endif
01957 #define MPI_REDUCE_ MPI_MAX
01958 #include <mpp_reduce.h>
01959 
01960 #define MPP_REDUCE_ mpp_max_real4
01961 #define MPP_TYPE_ real(FLOAT_KIND)
01962 #define SHMEM_REDUCE_ SHMEM_REAL4_MAX_TO_ALL
01963 #ifdef use_LAM_MPI
01964 #define MPI_TYPE_ MPI_REAL
01965 #else
01966 #define MPI_TYPE_ MPI_REAL4
01967 #endif
01968 #define MPI_REDUCE_ MPI_MAX
01969 #include <mpp_reduce.h>
01970 
01971 #ifndef no_8byte_integers   
01972 #define MPP_REDUCE_ mpp_max_int8
01973 #define MPP_TYPE_ integer(LONG_KIND)
01974 #define SHMEM_REDUCE_ SHMEM_INT8_MAX_TO_ALL
01975 #ifdef use_LAM_MPI
01976 #define MPI_TYPE_ MPI_INTEGER
01977 #else
01978 #define MPI_TYPE_ MPI_INTEGER8
01979 #endif
01980 #define MPI_REDUCE_ MPI_MAX
01981 #include <mpp_reduce.h>
01982 #endif
01983 
01984 #define MPP_REDUCE_ mpp_max_int4
01985 #define MPP_TYPE_ integer(INT_KIND)
01986 #define SHMEM_REDUCE_ SHMEM_INT4_MAX_TO_ALL
01987 #ifdef use_LAM_MPI
01988 #define MPI_TYPE_ MPI_INTEGER
01989 #else
01990 #define MPI_TYPE_ MPI_INTEGER4
01991 #endif
01992 #define MPI_REDUCE_ MPI_MAX
01993 #include <mpp_reduce.h>
01994 
01995 #define MPP_REDUCE_ mpp_min_real8
01996 #define MPP_TYPE_ real(DOUBLE_KIND)
01997 #define SHMEM_REDUCE_ SHMEM_REAL8_MIN_TO_ALL
01998 #ifdef use_LAM_MPI
01999 #define MPI_TYPE_ MPI_DOUBLE_PRECISION
02000 #else
02001 #define MPI_TYPE_ MPI_REAL8
02002 #endif
02003 #define MPI_REDUCE_ MPI_MIN
02004 #include <mpp_reduce.h>
02005 
02006 #ifndef no_4byte_reals
02007 #define MPP_REDUCE_ mpp_min_real4
02008 #define MPP_TYPE_ real(FLOAT_KIND)
02009 #define SHMEM_REDUCE_ SHMEM_REAL4_MIN_TO_ALL
02010 #ifdef use_LAM_MPI
02011 #define MPI_TYPE_ MPI_REAL
02012 #else
02013 #define MPI_TYPE_ MPI_REAL4
02014 #endif
02015 #define MPI_REDUCE_ MPI_MIN
02016 #include <mpp_reduce.h>
02017 #endif
02018 
02019 #ifndef no_8byte_integers   
02020 #define MPP_REDUCE_ mpp_min_int8
02021 #define MPP_TYPE_ integer(LONG_KIND)
02022 #define SHMEM_REDUCE_ SHMEM_INT8_MIN_TO_ALL
02023 #ifdef use_LAM_MPI
02024 #define MPI_TYPE_ MPI_INTEGER
02025 #else
02026 #define MPI_TYPE_ MPI_INTEGER8
02027 #endif
02028 #define MPI_REDUCE_ MPI_MIN
02029 #include <mpp_reduce.h>
02030 #endif
02031 
02032 #define MPP_REDUCE_ mpp_min_int4
02033 #define MPP_TYPE_ integer(INT_KIND)
02034 #define SHMEM_REDUCE_ SHMEM_INT4_MIN_TO_ALL
02035 #ifdef use_LAM_MPI
02036 #define MPI_TYPE_ MPI_INTEGER
02037 #else
02038 #define MPI_TYPE_ MPI_INTEGER4
02039 #endif
02040 #define MPI_REDUCE_ MPI_MIN
02041 #include <mpp_reduce.h>
02042 
02043 #define MPP_SUM_ mpp_sum_real8
02044 #define MPP_SUM_SCALAR_ mpp_sum_real8_scalar
02045 #define MPP_SUM_2D_ mpp_sum_real8_2d
02046 #define MPP_SUM_3D_ mpp_sum_real8_3d
02047 #define MPP_SUM_4D_ mpp_sum_real8_4d
02048 #define MPP_SUM_5D_ mpp_sum_real8_5d
02049 #define MPP_TYPE_ real(DOUBLE_KIND)
02050 #define SHMEM_SUM_ SHMEM_REAL8_SUM_TO_ALL
02051 #ifdef use_LAM_MPI
02052 #define MPI_TYPE_ MPI_DOUBLE_PRECISION
02053 #else
02054 #define MPI_TYPE_ MPI_REAL8
02055 #endif
02056 #define MPP_TYPE_BYTELEN_ 8
02057 #include <mpp_sum.h>
02058 
02059 #ifndef no_4byte_reals
02060 #define MPP_SUM_ mpp_sum_real4
02061 #define MPP_SUM_SCALAR_ mpp_sum_real4_scalar
02062 #define MPP_SUM_2D_ mpp_sum_real4_2d
02063 #define MPP_SUM_3D_ mpp_sum_real4_3d
02064 #define MPP_SUM_4D_ mpp_sum_real4_4d
02065 #define MPP_SUM_5D_ mpp_sum_real4_5d
02066 #define MPP_TYPE_ real(FLOAT_KIND)
02067 #define SHMEM_SUM_ SHMEM_REAL4_SUM_TO_ALL
02068 #ifdef use_LAM_MPI
02069 #define MPI_TYPE_ MPI_REAL
02070 #else
02071 #define MPI_TYPE_ MPI_REAL4
02072 #endif
02073 #define MPP_TYPE_BYTELEN_ 4
02074 #include <mpp_sum.h>
02075 #endif
02076 
02077 #define MPP_SUM_ mpp_sum_cmplx8
02078 #define MPP_SUM_SCALAR_ mpp_sum_cmplx8_scalar
02079 #define MPP_SUM_2D_ mpp_sum_cmplx8_2d
02080 #define MPP_SUM_3D_ mpp_sum_cmplx8_3d
02081 #define MPP_SUM_4D_ mpp_sum_cmplx8_4d
02082 #define MPP_SUM_5D_ mpp_sum_cmplx8_5d
02083 #define MPP_TYPE_ complex(DOUBLE_KIND)
02084 #define SHMEM_SUM_ SHMEM_COMP8_SUM_TO_ALL
02085 #define MPI_TYPE_ MPI_DOUBLE_COMPLEX
02086 #define MPP_TYPE_BYTELEN_ 16
02087 #include <mpp_sum.h>
02088 
02089 #ifndef no_4byte_cmplx
02090 #define MPP_SUM_ mpp_sum_cmplx4
02091 #define MPP_SUM_SCALAR_ mpp_sum_cmplx4_scalar
02092 #define MPP_SUM_2D_ mpp_sum_cmplx4_2d
02093 #define MPP_SUM_3D_ mpp_sum_cmplx4_3d
02094 #define MPP_SUM_4D_ mpp_sum_cmplx4_4d
02095 #define MPP_SUM_5D_ mpp_sum_cmplx4_5d
02096 #define MPP_TYPE_ complex(FLOAT_KIND)
02097 #define SHMEM_SUM_ SHMEM_COMP4_SUM_TO_ALL
02098 #define MPI_TYPE_ MPI_COMPLEX
02099 #define MPP_TYPE_BYTELEN_ 8
02100 #include <mpp_sum.h>
02101 #endif
02102 
02103 #ifndef no_8byte_integers
02104 #define MPP_SUM_ mpp_sum_int8
02105 #define MPP_SUM_SCALAR_ mpp_sum_int8_scalar
02106 #define MPP_SUM_2D_ mpp_sum_int8_2d
02107 #define MPP_SUM_3D_ mpp_sum_int8_3d
02108 #define MPP_SUM_4D_ mpp_sum_int8_4d
02109 #define MPP_SUM_5D_ mpp_sum_int8_5d
02110 #define MPP_TYPE_ integer(LONG_KIND)
02111 #define SHMEM_SUM_ SHMEM_INT8_SUM_TO_ALL
02112 #ifdef use_LAM_MPI
02113 #define MPI_TYPE_ MPI_INTEGER
02114 #else
02115 #define MPI_TYPE_ MPI_INTEGER8
02116 #endif
02117 #define MPP_TYPE_BYTELEN_ 8
02118 #include <mpp_sum.h>
02119 #endif
02120 
02121 #define MPP_SUM_ mpp_sum_int4
02122 #define MPP_SUM_SCALAR_ mpp_sum_int4_scalar
02123 #define MPP_SUM_2D_ mpp_sum_int4_2d
02124 #define MPP_SUM_3D_ mpp_sum_int4_3d
02125 #define MPP_SUM_4D_ mpp_sum_int4_4d
02126 #define MPP_SUM_5D_ mpp_sum_int4_5d
02127 #define MPP_TYPE_ integer(INT_KIND)
02128 #define SHMEM_SUM_ SHMEM_INT4_SUM_TO_ALL
02129 #ifdef use_LAM_MPI
02130 #define MPI_TYPE_ MPI_INTEGER
02131 #else
02132 #define MPI_TYPE_ MPI_INTEGER4
02133 #endif
02134 #define MPP_TYPE_BYTELEN_ 4
02135 #include <mpp_sum.h>
02136 
02137 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
02138 !                                                                             !
02139 !           SYNCHRONIZATION ROUTINES: mpp_sync, mpp_sync_self                 !
02140 !                                                                             !
02141 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
02142 
02143     subroutine mpp_sync( pelist )
02144 !synchronize PEs in list
02145       integer, intent(in), optional :: pelist(:)
02146       integer :: n
02147 
02148       call mpp_sync_self(pelist)
02149 
02150       n = get_peset(pelist); if( peset(n)%count.EQ.1 )return
02151 
02152       if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
02153 #ifdef use_libSMA
02154       if( n.EQ.world_peset_num )then
02155           call SHMEM_BARRIER_ALL() !special call is faster
02156       else
02157           call SHMEM_BARRIER( peset(n)%start, peset(n)%log2stride, peset(n)%count, sync )
02158       end if
02159 #endif
02160 #ifdef use_libMPI
02161       call MPI_BARRIER( peset(n)%id, error )
02162 #endif
02163       if( current_clock.NE.0 )call increment_current_clock(EVENT_WAIT)
02164 
02165       return
02166     end subroutine mpp_sync
02167 
02168     subroutine mpp_sync_self( pelist )
02169 !this is to check if current PE's outstanding puts are complete
02170 !but we can't use shmem_fence because we are actually waiting for
02171 !a remote PE to complete its get
02172       integer, intent(in), optional :: pelist(:)
02173       integer :: i, m, n, stride
02174 
02175       n = get_peset(pelist); if( peset(n)%count.EQ.1 )return
02176 
02177       if( current_clock.NE.0 )call SYSTEM_CLOCK(start_tick)
02178 #ifdef use_libSMA
02179 #ifdef _CRAYT90
02180       call SHMEM_UDCFLUSH !invalidate data cache
02181 #endif
02182 #endif
02183       do m = 1,peset(n)%count
02184          i = peset(n)%list(m)
02185 #ifdef use_libSMA
02186          call SHMEM_INT8_WAIT( status(i), MPP_WAIT ) !wait for status.NE.MPP_WAIT
02187 #endif
02188 #ifdef use_libMPI
02189          if( mpp_request(i).NE.MPI_REQUEST_NULL )call MPI_WAIT( mpp_request(i), stat, error )
02190 #endif
02191       end do
02192       if( current_clock.NE.0 )call increment_current_clock(EVENT_WAIT)
02193       return
02194     end subroutine mpp_sync_self
02195 
02196 #ifdef use_libSMA
02197 !these local versions are written for grouping into shmem_integer_wait
02198     subroutine shmem_int4_wait_local( ivar, cmp_value )
02199 !dir$ INLINEALWAYS shmem_int4_wait_local
02200       integer(INT_KIND), intent(in) :: cmp_value
02201       integer(INT_KIND), intent(inout) :: ivar
02202       call SHMEM_INT4_WAIT( ivar, cmp_value )
02203       return
02204     end subroutine shmem_int4_wait_local
02205     subroutine shmem_int8_wait_local( ivar, cmp_value )
02206 !dir$ INLINEALWAYS shmem_int8_wait_local
02207       integer(LONG_KIND), intent(in) :: cmp_value
02208       integer(LONG_KIND), intent(inout) :: ivar
02209       call SHMEM_INT8_WAIT( ivar, cmp_value )
02210       return
02211     end subroutine shmem_int8_wait_local
02212 #endif
02213       
02214 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
02215 !                                                                             !
02216 !         MISCELLANEOUS UTILITIES: mpp_error, mpp_chksum, mpp_malloc          !
02217 !                                                                             !
02218 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
02219 
02220     subroutine mpp_error_basic( errortype, errormsg )
02221 !a very basic error handler
02222 !uses ABORT and FLUSH calls, may need to use cpp to rename
02223       integer, intent(in) :: errortype
02224       character(len=*), intent(in), optional :: errormsg
02225       character(len=128) :: text
02226       logical :: opened
02227 
02228 #ifdef use_libMPI
02229 
02230       if( .NOT.module_is_initialized )call MPI_ABORT(  peset(0)%id, 1, error ) 
02231 #else
02232       if( .NOT.module_is_initialized )call ABORT()
02233 
02234 #endif
02235 
02236       select case( errortype )
02237       case(NOTE)
02238           text = 'NOTE'         !just FYI
02239       case(WARNING)
02240           text = 'WARNING'      !probable error
02241       case(FATAL)
02242           text = 'FATAL'        !fatal error
02243       case default
02244           text = 'WARNING: non-existent errortype (must be NOTE|WARNING|FATAL)'
02245       end select
02246 
02247       if( npes.GT.1 )write( text,'(a,i5)' )trim(text)//' from PE', pe !this is the mpp part
02248       if( PRESENT(errormsg) )text = trim(text)//': '//trim(errormsg)
02249 
02250       select case( errortype )
02251       case(NOTE)
02252           write( stdout(),'(a)' )trim(text)
02253       case default
02254           write( stderr(),'(/a/)' )trim(text)
02255           if( errortype.EQ.FATAL .OR. warnings_are_fatal )then
02256               call mpp_flushstd(stdout())
02257 #ifdef sgi_mipspro
02258 !              call TRACE_BACK_STACK_AND_PRINT()
02259 #endif
02260 #ifdef use_libMPI
02261 #ifndef sgi_mipspro
02262 !the call to MPI_ABORT is not trapped by TotalView on sgi
02263               call MPI_ABORT(  peset(0)%id, 1, error )
02264 #else
02265               call ABORT()
02266 #endif
02267 #else
02268               call ABORT()
02269 #endif
02270           end if
02271       end select
02272 
02273       error_state = errortype
02274       return
02275     end subroutine mpp_error_basic
02276 !overloads to mpp_error_basic
02277     subroutine mpp_error_mesg( routine, errormsg, errortype )
02278 !support for error_mesg routine in FMS
02279       character(len=*), intent(in) :: routine, errormsg
02280       integer, intent(in) :: errortype
02281       call mpp_error( errortype, trim(routine)//': '//trim(errormsg) )
02282       return
02283     end subroutine mpp_error_mesg
02284     subroutine mpp_error_noargs()
02285       call mpp_error(FATAL)
02286     end subroutine mpp_error_noargs
02287       
02288     subroutine mpp_set_warn_level(flag)
02289       integer, intent(in) :: flag
02290 
02291       if( flag.EQ.WARNING )then
02292           warnings_are_fatal = .FALSE.
02293       else if( flag.EQ.FATAL )then
02294           warnings_are_fatal = .TRUE.
02295       else
02296           call mpp_error( FATAL, 'MPP_SET_WARN_LEVEL: warning flag must be set to WARNING or FATAL.' )
02297       end if
02298       return
02299     end subroutine mpp_set_warn_level
02300 
02301     function mpp_error_state()
02302       integer :: mpp_error_state
02303       mpp_error_state = error_state
02304       return
02305     end function mpp_error_state
02306 
02307 #ifdef use_shmalloc
02308     subroutine mpp_malloc( ptr, newlen, len )
02309 !routine to perform symmetric allocation:
02310 !this is required on the t3e/O2k for variables that will be non-local arguments
02311 !to a shmem call (see man intro_shmem(3F)).
02312 !newlen is the required allocation length for the pointer ptr
02313 !   len is the current allocation (0 if unallocated)
02314       integer, intent(in) :: newlen
02315       integer, intent(inout) :: len
02316       real :: dummy
02317       integer :: words_per_long
02318       integer(LONG_KIND) :: long
02319 !argument ptr is a cray pointer, points to a dummy argument in this routine
02320       pointer( ptr, dummy )
02321 !      integer(LONG_KIND) :: error_8
02322 
02323       if( .NOT.module_is_initialized )call mpp_error( FATAL, 'MPP_MALLOC: You must first call mpp_init.' )
02324 !use existing allocation if it is enough
02325       if( newlen.LE.len )return
02326 
02327       call SHMEM_BARRIER_ALL()
02328 !if the pointer is already allocated, deallocate
02329 !      if( len.NE.0 )call SHPDEALLC( ptr, error_8, -1 ) !BWA: error_8 instead of error, see PV 682618 (fixed in mpt.1.3.0.1)
02330       if( len.NE.0 )call SHPDEALLC( ptr, error, -1 )
02331 !allocate new length: assume that the array is KIND=8
02332       words_per_long = size(transfer(long,word))
02333       call SHPALLOC( ptr, newlen*words_per_long, error, -1 )
02334       len = newlen
02335       call SHMEM_BARRIER_ALL()
02336 
02337       if( debug )then
02338           call SYSTEM_CLOCK(tick)
02339           write( stdout(),'(a,i18,a,i5,a,2i8,i16)' )'T=', tick, ' PE=', pe, ' MPP_MALLOC: len, newlen, ptr=', len, newlen, ptr
02340       end if
02341       return
02342     end subroutine mpp_malloc
02343 #endif use_shmalloc
02344 
02345     subroutine mpp_set_stack_size(n)
02346 !set the mpp_stack variable to be at least n LONG words long
02347       integer, intent(in) :: n
02348       character(len=8) :: text
02349 #ifdef use_shmalloc
02350       call mpp_malloc( ptr_stack, n, mpp_stack_size )
02351 #else
02352       if( n.GT.mpp_stack_size .AND. allocated(mpp_stack) )deallocate(mpp_stack)
02353       if( .NOT.allocated(mpp_stack) )then
02354           allocate( mpp_stack(n) )
02355           mpp_stack_size = n
02356       end if
02357 #endif
02358       write( text,'(i8)' )n
02359       if( pe.EQ.root_pe )call mpp_error( NOTE, 'MPP_SET_STACK_SIZE: stack size set to '//text//'.' )
02360 
02361       return
02362     end subroutine mpp_set_stack_size
02363 
02364 #ifndef no_8byte_integers
02365 #define MPP_CHKSUM_INT_ mpp_chksum_i8_1d
02366 #define MPP_TYPE_ integer(LONG_KIND)
02367 #define MPP_RANK_  (:)
02368 #include <mpp_chksum_int.h>
02369 
02370 #define MPP_CHKSUM_INT_ mpp_chksum_i8_2d
02371 #define MPP_TYPE_ integer(LONG_KIND)
02372 #define MPP_RANK_  (:,:)
02373 #include <mpp_chksum_int.h>
02374 
02375 #define MPP_CHKSUM_INT_ mpp_chksum_i8_3d
02376 #define MPP_TYPE_ integer(LONG_KIND)
02377 #define MPP_RANK_  (:,:,:)
02378 #include <mpp_chksum_int.h>
02379 
02380 #define MPP_CHKSUM_INT_ mpp_chksum_i8_4d
02381 #define MPP_TYPE_ integer(LONG_KIND)
02382 #define MPP_RANK_  (:,:,:,:)
02383 #include <mpp_chksum_int.h>
02384 
02385 #define MPP_CHKSUM_INT_ mpp_chksum_i8_5d
02386 #define MPP_TYPE_ integer(LONG_KIND)
02387 #define MPP_RANK_  (:,:,:,:,:)
02388 #include <mpp_chksum_int.h>
02389 #endif
02390 
02391 #define MPP_CHKSUM_INT_ mpp_chksum_i4_1d
02392 #define MPP_TYPE_ integer(INT_KIND)
02393 #define MPP_RANK_  (:)
02394 #include <mpp_chksum_int.h>
02395 
02396 #define MPP_CHKSUM_INT_ mpp_chksum_i4_2d
02397 #define MPP_TYPE_ integer(INT_KIND)
02398 #define MPP_RANK_  (:,:)
02399 #include <mpp_chksum_int.h>
02400 
02401 #define MPP_CHKSUM_INT_ mpp_chksum_i4_3d
02402 #define MPP_TYPE_ integer(INT_KIND)
02403 #define MPP_RANK_  (:,:,:)
02404 #include <mpp_chksum_int.h>
02405 
02406 #define MPP_CHKSUM_INT_ mpp_chksum_i4_4d
02407 #define MPP_TYPE_ integer(INT_KIND)
02408 #define MPP_RANK_  (:,:,:,:)
02409 #include <mpp_chksum_int.h>
02410 
02411 #define MPP_CHKSUM_INT_ mpp_chksum_i4_5d
02412 #define MPP_TYPE_ integer(INT_KIND)
02413 #define MPP_RANK_  (:,:,:,:,:)
02414 #include <mpp_chksum_int.h>
02415 
02416 #define MPP_CHKSUM_ mpp_chksum_r8_0d
02417 #define MPP_TYPE_ real(DOUBLE_KIND)
02418 #define MPP_RANK_ !
02419 #include <mpp_chksum.h>
02420 
02421 #define MPP_CHKSUM_ mpp_chksum_r8_1d
02422 #define MPP_TYPE_ real(DOUBLE_KIND)
02423 #define MPP_RANK_ (:)
02424 #include <mpp_chksum.h>
02425 
02426 #define MPP_CHKSUM_ mpp_chksum_r8_2d
02427 #define MPP_TYPE_ real(DOUBLE_KIND)
02428 #define MPP_RANK_ (:,:)
02429 #include <mpp_chksum.h>
02430 
02431 #define MPP_CHKSUM_ mpp_chksum_r8_3d
02432 #define MPP_TYPE_ real(DOUBLE_KIND)
02433 #define MPP_RANK_ (:,:,:)
02434 #include <mpp_chksum.h>
02435 
02436 #define MPP_CHKSUM_ mpp_chksum_r8_4d
02437 #define MPP_TYPE_ real(DOUBLE_KIND)
02438 #define MPP_RANK_ (:,:,:,:)
02439 #include <mpp_chksum.h>
02440 
02441 #define MPP_CHKSUM_ mpp_chksum_r8_5d
02442 #define MPP_TYPE_ real(DOUBLE_KIND)
02443 #define MPP_RANK_ (:,:,:,:,:)
02444 #include <mpp_chksum.h>
02445 
02446 #define MPP_CHKSUM_ mpp_chksum_c8_0d
02447 #define MPP_TYPE_ complex(DOUBLE_KIND)
02448 #define MPP_RANK_ !
02449 #include <mpp_chksum.h>
02450 
02451 #define MPP_CHKSUM_ mpp_chksum_c8_1d
02452 #define MPP_TYPE_ complex(DOUBLE_KIND)
02453 #define MPP_RANK_ (:)
02454 #include <mpp_chksum.h>
02455 
02456 #define MPP_CHKSUM_ mpp_chksum_c8_2d
02457 #define MPP_TYPE_ complex(DOUBLE_KIND)
02458 #define MPP_RANK_ (:,:)
02459 #include <mpp_chksum.h>
02460 
02461 #define MPP_CHKSUM_ mpp_chksum_c8_3d
02462 #define MPP_TYPE_ complex(DOUBLE_KIND)
02463 #define MPP_RANK_ (:,:,:)
02464 #include <mpp_chksum.h>
02465 
02466 #define MPP_CHKSUM_ mpp_chksum_c8_4d
02467 #define MPP_TYPE_ complex(DOUBLE_KIND)
02468 #define MPP_RANK_ (:,:,:,:)
02469 #include <mpp_chksum.h>
02470 
02471 #define MPP_CHKSUM_ mpp_chksum_c8_5d
02472 #define MPP_TYPE_ complex(DOUBLE_KIND)
02473 #define MPP_RANK_ (:,:,:,:,:)
02474 #include <mpp_chksum.h>
02475 
02476 #ifndef no_4byte_reals
02477 !CAUTION: the r4 versions of these may produce
02478 !unpredictable results: I'm not sure what the result
02479 !of the TRANSFER() to integer(8) is from an odd number of real(4)s?
02480 !However the complex(4) will work, since it is guaranteed even.
02481 #define MPP_CHKSUM_ mpp_chksum_r4_0d
02482 #define MPP_TYPE_ real(FLOAT_KIND)
02483 #define MPP_RANK_ !
02484 #include <mpp_chksum.h>
02485 
02486 #define MPP_CHKSUM_ mpp_chksum_r4_1d
02487 #define MPP_TYPE_ real(FLOAT_KIND)
02488 #define MPP_RANK_ (:)
02489 #include <mpp_chksum.h>
02490 
02491 #define MPP_CHKSUM_ mpp_chksum_r4_2d
02492 #define MPP_TYPE_ real(FLOAT_KIND)
02493 #define MPP_RANK_ (:,:)
02494 #include <mpp_chksum.h>
02495 
02496 #define MPP_CHKSUM_ mpp_chksum_r4_3d
02497 #define MPP_TYPE_ real(FLOAT_KIND)
02498 #define MPP_RANK_ (:,:,:)
02499 #include <mpp_chksum.h>
02500 
02501 #define MPP_CHKSUM_ mpp_chksum_r4_4d
02502 #define MPP_TYPE_ real(FLOAT_KIND)
02503 #define MPP_RANK_ (:,:,:,:)
02504 #include <mpp_chksum.h>
02505 
02506 #define MPP_CHKSUM_ mpp_chksum_r4_5d
02507 #define MPP_TYPE_ real(FLOAT_KIND)
02508 #define MPP_RANK_ (:,:,:,:,:)
02509 #include <mpp_chksum.h>
02510 #endif
02511 
02512 #ifndef no_4byte_cmplx
02513 #define MPP_CHKSUM_ mpp_chksum_c4_0d
02514 #define MPP_TYPE_ complex(FLOAT_KIND)
02515 #define MPP_RANK_ !
02516 #include <mpp_chksum.h>
02517 
02518 #define MPP_CHKSUM_ mpp_chksum_c4_1d
02519 #define MPP_TYPE_ complex(FLOAT_KIND)
02520 #define MPP_RANK_ (:)
02521 #include <mpp_chksum.h>
02522 
02523 #define MPP_CHKSUM_ mpp_chksum_c4_2d
02524 #define MPP_TYPE_ complex(FLOAT_KIND)
02525 #define MPP_RANK_ (:,:)
02526 #include <mpp_chksum.h>
02527 
02528 #define MPP_CHKSUM_ mpp_chksum_c4_3d
02529 #define MPP_TYPE_ complex(FLOAT_KIND)
02530 #define MPP_RANK_ (:,:,:)
02531 #include <mpp_chksum.h>
02532 
02533 #define MPP_CHKSUM_ mpp_chksum_c4_4d
02534 #define MPP_TYPE_ complex(FLOAT_KIND)
02535 #define MPP_RANK_ (:,:,:,:)
02536 #include <mpp_chksum.h>
02537 
02538 #define MPP_CHKSUM_ mpp_chksum_c4_5d
02539 #define MPP_TYPE_ complex(FLOAT_KIND)
02540 #define MPP_RANK_ (:,:,:,:,:)
02541 #include <mpp_chksum.h>
02542 #endif
02543 
02544   end module mpp_mod_oa
02545 
02546 #endif

Generated on 18 Mar 2011 for Oasis4 by  doxygen 1.6.1