FMS  2026.01.01-dev
Flexible Modeling System
mpp_domains.F90
1 !***********************************************************************
2 !* Apache License 2.0
3 !*
4 !* This file is part of the GFDL Flexible Modeling System (FMS).
5 !*
6 !* Licensed under the Apache License, Version 2.0 (the "License");
7 !* you may not use this file except in compliance with the License.
8 !* You may obtain a copy of the License at
9 !*
10 !* http://www.apache.org/licenses/LICENSE-2.0
11 !*
12 !* FMS is distributed in the hope that it will be useful, but WITHOUT
13 !* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied;
14 !* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15 !* PARTICULAR PURPOSE. See the License for the specific language
16 !* governing permissions and limitations under the License.
17 !***********************************************************************
18 !-----------------------------------------------------------------------
19 !> @defgroup mpp_domains_mod mpp_domains_mod
20 !> @ingroup mpp
21 !> @brief Domain decomposition and domain update for message-passing codes
22 !> @author V. Balaji SGI/GFDL Princeton University
23 !!
24 !> A set of simple calls for domain
25 !! decomposition and domain updates on rectilinear grids. It requires the
26 !! module mpp.F90, upon which it is built.\n
27 !! Scalable implementations of finite-difference codes are generally
28 !! based on decomposing the model domain into subdomains that are
29 !! distributed among processors. These domains will then be obliged to
30 !! exchange data at their boundaries if data dependencies are merely
31 !! nearest-neighbour, or may need to acquire information from the global
32 !! domain if there are extended data dependencies, as in the spectral
33 !! transform. The domain decomposition is a key operation in the
34 !! development of parallel codes.\n
35 !!\n
36 !! mpp_domains_mod provides a domain decomposition and domain
37 !! update API for rectilinear grids, built on top of the mpp_mod API for message passing.
38 !! Features of mpp_domains_mod include:\n
39 !!\n
40 !! Simple, minimal API, with free access to underlying API for more complicated stuff.\n
41 !!\n
42 !! Design toward typical use in climate/weather CFD codes.\n
43 !!
44 !> @par[Domains]
45 !! It is assumed that domain decomposition will mainly be in 2
46 !! horizontal dimensions, which will in general be the two
47 !! fastest-varying indices. There is a separate implementation of 1D
48 !! decomposition on the fastest-varying index, and 1D decomposition on
49 !! the second index, treated as a special case of 2D decomposition, is
50 !! also possible. We define domain as the grid associated with a <I>task</I>.
51 !! We define the compute domain as the set of gridpoints that are
52 !! computed by a task, and the data domain as the set of points
53 !! that are required by the task for the calculation. There can in
54 !! general be more than 1 task per PE, though often
55 !! the number of domains is the same as the processor count. We define
56 !! the global domain as the global computational domain of the
57 !! entire model (i.e, the same as the computational domain if run on a
58 !! single processor). 2D domains are defined using a derived type domain2D,
59 !! constructed as follows (see comments in code for more details).
60 !!
61 !! type, public :: domain_axis_spec
62 !! private
63 !! integer :: begin, end, size, max_size
64 !! logical :: is_global
65 !! end type domain_axis_spec
66 !!
67 !! type, public :: domain1D
68 !! private
69 !! type(domain_axis_spec) :: compute, data, global, active
70 !! logical :: mustputb, mustgetb, mustputf, mustgetf, folded
71 !! type(domain1D), pointer, dimension(:) :: list
72 !! integer :: pe ! pe to which the domain is assigned
73 !! integer :: pos
74 !! end type domain1D
75 !!
76 !! type, public :: domain2D
77 !! private
78 !! type(domain1D) :: x
79 !! type(domain1D) :: y
80 !! type(domain2D), pointer, dimension(:) :: list
81 !! integer :: pe ! PE to which this domain is assigned
82 !! integer :: pos
83 !! end type domain2D
84 !!
85 !! type(domain1D), public :: NULL_DOMAIN1D
86 !! type(domain2D), public :: NULL_DOMAIN2D
87 
88 !> @addtogroup mpp_domains_mod
89 !> @{
90 
91 module mpp_domains_mod
92 
93 #ifdef use_libMPI
94  use mpi_f08
95 #else
96  use gfdl_nompi_f08
97 #endif
98 
99  use iso_c_binding, only : c_f_pointer, c_loc, c_ptr
100  use mpp_parameter_mod, only : mpp_debug, mpp_verbose, mpp_domain_time
101  use mpp_parameter_mod, only : global_data_domain, cyclic_global_domain, global,cyclic
102  use mpp_parameter_mod, only : agrid, bgrid_sw, bgrid_ne, cgrid_ne, cgrid_sw, dgrid_ne, dgrid_sw
103  use mpp_parameter_mod, only : fold_west_edge, fold_east_edge, fold_south_edge, fold_north_edge
104  use mpp_parameter_mod, only : wupdate, eupdate, supdate, nupdate, xupdate, yupdate
105  use mpp_parameter_mod, only : non_bitwise_exact_sum, bitwise_exact_sum, mpp_domain_time
106  use mpp_parameter_mod, only : center, corner, scalar_pair, scalar_bit, bitwise_efp_sum
107  use mpp_parameter_mod, only : north, north_east, east, south_east
108  use mpp_parameter_mod, only : south, south_west, west, north_west
109  use mpp_parameter_mod, only : max_domain_fields, null_pe, domain_id_base
110  use mpp_parameter_mod, only : zero, ninety, minus_ninety, one_hundred_eighty, max_tiles
111  use mpp_parameter_mod, only : event_send, event_recv, root_global
112  use mpp_parameter_mod, only : nonblock_update_tag, edgeonly, edgeupdate
113  use mpp_parameter_mod, only : nonsymedge, nonsymedgeupdate
114  use mpp_data_mod, only : mpp_domains_stack, ptr_domains_stack
115  use mpp_data_mod, only : mpp_domains_stack_nonblock, ptr_domains_stack_nonblock
116  use mpp_mod, only : mpp_pe, mpp_root_pe, mpp_npes, mpp_error, fatal, warning, note
118  use mpp_mod, only : mpp_clock_id, mpp_clock_begin, mpp_clock_end
120  use mpp_mod, only : mpp_sum_ad
121  use mpp_mod, only : mpp_sync, mpp_init, lowercase
122  use mpp_mod, only : input_nml_file, mpp_alltoall
123  use mpp_mod, only : mpp_type, mpp_byte
124  use mpp_mod, only : mpp_type_create, mpp_type_free
125  use mpp_mod, only : comm_tag_1, comm_tag_2, comm_tag_3, comm_tag_4
126  use mpp_mod, only : mpp_declare_pelist, mpp_set_current_pelist
127  use mpp_memutils_mod, only : mpp_memuse_begin, mpp_memuse_end
128  use mpp_efp_mod, only : mpp_reproducing_sum
129  use platform_mod
130  implicit none
131  private
132 
133  !--- public parameters imported from mpp_domains_parameter_mod
134  public :: global_data_domain, cyclic_global_domain, bgrid_ne, bgrid_sw, cgrid_ne, cgrid_sw, agrid
135  public :: dgrid_ne, dgrid_sw, fold_west_edge, fold_east_edge, fold_south_edge, fold_north_edge
136  public :: wupdate, eupdate, supdate, nupdate, xupdate, yupdate
137  public :: non_bitwise_exact_sum, bitwise_exact_sum, mpp_domain_time, bitwise_efp_sum
138  public :: center, corner, scalar_pair
139  public :: north, north_east, east, south_east
140  public :: south, south_west, west, north_west
141  public :: zero, ninety, minus_ninety, one_hundred_eighty
142  public :: edgeupdate, nonsymedgeupdate
143 
144  !--- public data imported from mpp_data_mod
145  public :: null_domain1d, null_domain2d
146 
149 
150  !--- public interface from mpp_domains_util.h
153  public :: mpp_get_layout, mpp_get_pelist, operator(.EQ.), operator(.NE.)
159  public :: mpp_get_tile_list
169  public :: mpp_clear_group_update
171  public :: mpp_get_global_domains
173 
174  !--- public interface from mpp_domains_reduce.h
177  !--- public interface from mpp_domains_misc.h
185  public :: mpp_get_boundary
186  public :: mpp_update_domains_ad
187  public :: mpp_get_boundary_ad
189  !--- public interface from mpp_domains_define.h
194 
195  !--- public interface for unstruct domain
196  public :: mpp_define_unstruct_domain, domainug, mpp_get_ug_io_domain
197  public :: mpp_get_ug_domain_npes, mpp_get_ug_compute_domain, mpp_get_ug_domain_tile_id
198  public :: mpp_get_ug_domain_pelist, mpp_get_ug_domain_grid_index
199  public :: mpp_get_ug_domain_ntiles, mpp_get_ug_global_domain
200  public :: mpp_global_field_ug, mpp_get_ug_domain_tile_list, mpp_get_ug_compute_domains
201  public :: mpp_define_null_ug_domain, null_domainug, mpp_get_ug_domains_index
202  public :: mpp_get_ug_sg_domain, mpp_get_ug_domain_tile_pe_inf
203 
204  !--- public interface from mpp_define_domains.inc
206  public :: mpp_shift_nest_domains
207  public :: mpp_get_nest_coarse_domain, mpp_get_nest_fine_domain
208  public :: mpp_is_nest_coarse, mpp_is_nest_fine
209  public :: mpp_get_nest_pelist, mpp_get_nest_npes
210  public :: mpp_get_nest_fine_pelist, mpp_get_nest_fine_npes
211 
212 !----------
213 !ug support
214  public :: mpp_domain_ug_is_tile_root_pe
215  public :: mpp_deallocate_domainug
216  public :: mpp_get_io_domain_ug_layout
217 !----------
218 
219  integer, parameter :: NAME_LENGTH = 64
220  integer, parameter :: MAXLIST = 100
221  integer, parameter :: MAXOVERLAP = 200
222  integer, parameter :: FIELD_S = 0
223  integer, parameter :: FIELD_X = 1
224  integer, parameter :: FIELD_Y = 2
225 
226  !> @}
227 
228  ! data types used by mpp_domains_mod
229 
230  !> @brief Private type for axis specification data for an unstructured grid
231  !> @ingroup mpp_domains_mod
233  private
234  integer :: begin, end, size, max_size
235  integer :: begin_index, end_index
236  end type unstruct_axis_spec
237 
238  !> Private type for axis specification data for an unstructured domain
239  !> @ingroup mpp_domains_mod
241  private
242  type(unstruct_axis_spec) :: compute
243  integer :: pe
244  integer :: pos
245  integer :: tile_id
246  end type unstruct_domain_spec
247 
248  !> Private type
249  !> @ingroup mpp_domains_mod
251  private
252  integer :: count = 0
253  integer :: pe
254  integer, pointer :: i(:)=>null()
255  integer, pointer :: j(:)=>null()
256  end type unstruct_overlap_type
257 
258  !> Private type
259  !> @ingroup mpp_domains_mod
261  private
262  integer :: nsend, nrecv
263  type(unstruct_overlap_type), pointer :: recv(:)=>null()
264  type(unstruct_overlap_type), pointer :: send(:)=>null()
265  end type unstruct_pass_type
266 
267  !> Domain information for managing data on unstructured grids
268  !> @ingroup mpp_domains_mod
269  type :: domainug
270  private
271  type(unstruct_axis_spec) :: compute, global !< axis specifications
272  type(unstruct_domain_spec), pointer :: list(:)=>null() !<
273  type(domainug), pointer :: io_domain=>null() !<
274  type(unstruct_pass_type) :: sg2ug
275  type(unstruct_pass_type) :: ug2sg
276  integer, pointer :: grid_index(:) => null() !< index of grid on current pe
277  type(domain2d), pointer :: sg_domain => null()
278  integer :: pe
279  integer :: pos
280  integer :: ntiles
281  integer :: tile_id
282  integer :: tile_root_pe
283  integer :: tile_npes
284  integer :: npes_io_group
285  integer(i4_kind) :: io_layout
286  end type domainug
287 
288  !> Used to specify index limits along an axis of a domain
289  !> @ingroup mpp_domains_mod
291  private
292  integer :: begin !< start of domain axis
293  integer :: end !< end of domain axis
294  integer :: size !< size of domain axis
295  integer :: max_size !< max size in set
296  logical :: is_global !< .true. if domain axis extent covers global domain
297  end type domain_axis_spec
298 
299  !> A private type used to specify index limits for a domain decomposition
300  !> @ingroup mpp_domains_mod
302  private
303  type(domain_axis_spec) :: compute
304  type(domain_axis_spec) :: global
305  integer :: pos
306  end type domain1d_spec
307 
308  !> @brief Private type to specify multiple index limits and pe information for a 2D domain
309  !> @ingroup mpp_domains_mod
311  private
312  type(domain1d_spec), pointer :: x(:) => null() !< x-direction domain decomposition
313  type(domain1d_spec), pointer :: y(:) => null() !< y-direction domain decomposition
314  integer, pointer :: tile_id(:) => null() !< tile id of each tile
315  integer :: pe !< PE to which this domain is assigned
316  integer :: pos !< position of this PE within link list
317  integer :: tile_root_pe !< root pe of tile.
318  end type domain2d_spec
319 
320  !> Type for overlapping data
321  !> @ingroup mpp_domains_mod
322  type :: overlap_type
323  private
324  integer :: count = 0 !< number of overlapping
325  integer :: pe
326  integer :: start_pos !< start position in the buffer
327  integer :: totsize !< all message size
328  integer , pointer :: msgsize(:) => null() !< overlapping msgsize to be sent or received
329  integer, pointer :: tileme(:) => null() !< my tile id for this overlap
330  integer, pointer :: tilenbr(:) => null() !< neighbor tile id for this overlap
331  integer, pointer :: is(:) => null() !< starting i-index
332  integer, pointer :: ie(:) => null() !< ending i-index
333  integer, pointer :: js(:) => null() !< starting j-index
334  integer, pointer :: je(:) => null() !< ending j-index
335  integer, pointer :: dir(:) => null() !< direction ( value 1,2,3,4 = E,S,W,N)
336  integer, pointer :: rotation(:) => null() !< rotation angle.
337  integer, pointer :: index(:) => null() !< for refinement
338  logical, pointer :: from_contact(:) => null() !< indicate if the overlap is computed from
339  !! define_contact_overlap
340  end type overlap_type
341 
342  !> Private type for overlap specifications
343  !> @ingroup mpp_domains_mod
344  type :: overlapspec
345  private
346  integer :: whalo, ehalo, shalo, nhalo !< halo size
347  integer :: xbegin, xend, ybegin, yend
348  integer :: nsend, nrecv
349  integer :: sendsize, recvsize
350  type(overlap_type), pointer :: send(:) => null()
351  type(overlap_type), pointer :: recv(:) => null()
352  type(overlapspec), pointer :: next => null()
353  end type overlapspec
354 
355  !> @brief Upper and lower x and y bounds for a tile
356  !> @ingroup mpp_domains_mod
357  type :: tile_type
358  integer :: xbegin, xend, ybegin, yend
359  end type tile_type
360 
361  !> The domain2D type contains all the necessary information to
362  !! define the global, compute and data domains of each task, as well as the PE
363  !! associated with the task. The PEs from which remote data may be
364  !! acquired to update the data domain are also contained in a linked list of neighbours.
365  !!
366  !! Domain types of higher rank can be constructed from type domain1D
367  !! typically we only need 1 and 2D, but could need higher (e.g 3D LES)
368  !! some elements are repeated below if they are needed once per domain, not once per axis
369  !> @ingroup mpp_domains_mod
370  TYPE :: domain2d
371  private
372  character(len=NAME_LENGTH) :: name='unnamed' !< name of the domain, default is "unspecified"
373  integer(i8_kind) :: id
374  integer :: pe !< PE to which this domain is assigned
375  integer :: fold
376  integer :: pos !< position of this PE within link list
377  logical :: symmetry !< indicate the domain is symmetric or non-symmetric.
378  integer :: whalo, ehalo !< halo size in x-direction
379  integer :: shalo, nhalo !< halo size in y-direction
380  integer :: ntiles !< number of tiles within mosaic
381  type(mpi_comm) :: comm !< MPI communicator for the mosaic
382  type(mpi_comm) :: tile_comm !< MPI communicator for this tile of domain
383  integer :: max_ntile_pe !< maximum value in the pelist of number of tiles on each pe.
384  integer :: ncontacts !< number of contact region within mosaic.
385  logical :: rotated_ninety !< indicate if any contact rotate NINETY or MINUS_NINETY
386  logical :: initialized=.false. !< indicate if the overlapping is computed or not.
387  integer :: tile_root_pe !< root pe of current tile.
388  integer :: io_layout(2) !< io_layout, will be set through mpp_define_io_domain
389  !! default = domain layout
390  integer, pointer :: pearray(:,:) => null() !< pe of each layout position
391  integer, pointer :: tile_id(:) => null() !< tile id of each tile on current processor
392  integer, pointer :: tile_id_all(:)=> null() !< tile id of all the tiles of domain
393  type(domain1d), pointer :: x(:) => null() !< x-direction domain decomposition
394  type(domain1d), pointer :: y(:) => null() !< y-direction domain decomposition
395  type(domain2d_spec),pointer :: list(:) => null() !< domain decomposition on pe list
396  type(tile_type), pointer :: tilelist(:) => null() !< store tile information
397  type(overlapspec), pointer :: check_c => null() !< send and recv information for boundary
398  !! consistency check of C-cell
399  type(overlapspec), pointer :: check_e => null() !< send and recv information for boundary
400  !! consistency check of E-cell
401  type(overlapspec), pointer :: check_n => null() !< send and recv information for boundary
402  !! consistency check of N-cell
403  type(overlapspec), pointer :: bound_c => null() !< send information for getting boundary
404  !! value for symmetry domain.
405  type(overlapspec), pointer :: bound_e => null() !< send information for getting boundary
406  !! value for symmetry domain.
407  type(overlapspec), pointer :: bound_n => null() !< send information for getting boundary
408  !! value for symmetry domain.
409  type(overlapspec), pointer :: update_t => null() !< send and recv information for halo update of T-cell.
410  type(overlapspec), pointer :: update_e => null() !< send and recv information for halo update of E-cell.
411  type(overlapspec), pointer :: update_c => null() !< send and recv information for halo update of C-cell.
412  type(overlapspec), pointer :: update_n => null() !< send and recv information for halo update of N-cell.
413  type(domain2d), pointer :: io_domain => null() !< domain for IO, will be set through calling
414  !! mpp_set_io_domain ( this will be changed).
415  END TYPE domain2d
416 
417  !> Type used to represent the contact between tiles.
418  !> @note This type will only be used in mpp_domains_define.inc
419  !> @ingroup mpp_domains_mod
420  type, private :: contact_type
421  private
422  integer :: ncontact !< number of neighbor tile.
423  integer, pointer :: tile(:) =>null() !< neighbor tile
424  integer, pointer :: align1(:)=>null(), align2(:)=>null() !< alignment of me and neighbor
425  real, pointer :: refine1(:)=>null(), refine2(:)=>null() !
426  integer, pointer :: is1(:)=>null(), ie1(:)=>null() !< i-index of current tile repsenting contact
427  integer, pointer :: js1(:)=>null(), je1(:)=>null() !< j-index of current tile repsenting contact
428  integer, pointer :: is2(:)=>null(), ie2(:)=>null() !< i-index of neighbor tile repsenting contact
429  integer, pointer :: js2(:)=>null(), je2(:)=>null() !< j-index of neighbor tile repsenting contact
430  end type contact_type
431 
432  !> index bounds for use in @ref nestSpec
433  !> @ingroup mpp_domains_mod
434  type :: index_type
435  integer :: is_me, ie_me, js_me, je_me
436  integer :: is_you, ie_you, js_you, je_you
437  end type index_type
438 
439  !> Used to specify bounds and index information for nested tiles as a linked list
440  !> @ingroup mpp_domains_mod
441  type :: nestspec
442  private
443  integer :: xbegin, xend, ybegin, yend
444  integer :: xbegin_c, xend_c, ybegin_c, yend_c
445  integer :: xbegin_f, xend_f, ybegin_f, yend_f
446  integer :: xsize_c, ysize_c
447  type(index_type) :: west, east, south, north, center
448  integer :: nsend, nrecv
449  integer :: extra_halo
450  type(overlap_type), pointer :: send(:) => null()
451  type(overlap_type), pointer :: recv(:) => null()
452  type(nestSpec), pointer :: next => null()
453 
454  end type nestspec
455 
456  !> @brief domain with nested fine and course tiles
457  !> @ingroup mpp_domains_mod
459  character(len=NAME_LENGTH) :: name
460  integer :: num_level
461  integer, pointer :: nest_level(:) => null() !< Added for moving nest functionality
462  type(nest_level_type), pointer :: nest(:) => null()
463  integer :: num_nest
464  integer, pointer :: tile_fine(:), tile_coarse(:)
465  integer, pointer :: istart_fine(:), iend_fine(:), jstart_fine(:), jend_fine(:)
466  integer, pointer :: istart_coarse(:), iend_coarse(:), jstart_coarse(:), jend_coarse(:)
467  end type nest_domain_type
468 
469  !> Private type to hold data for each level of nesting
470  !> @ingroup mpp_domains_mod
472  private
473  logical :: on_level
474  logical :: is_fine, is_coarse
475  integer :: num_nest
476  integer :: my_num_nest
477  integer, pointer :: my_nest_id(:)
478  integer, pointer :: tile_fine(:), tile_coarse(:)
479  integer, pointer :: istart_fine(:), iend_fine(:), jstart_fine(:), jend_fine(:)
480  integer, pointer :: istart_coarse(:), iend_coarse(:), jstart_coarse(:), jend_coarse(:)
481  integer :: x_refine, y_refine
482  logical :: is_fine_pe, is_coarse_pe
483  integer, pointer :: pelist(:) => null()
484  integer, pointer :: pelist_fine(:) => null()
485  integer, pointer :: pelist_coarse(:) => null()
486  type(nestSpec), pointer :: C2F_T => null()
487  type(nestSpec), pointer :: C2F_C => null()
488  type(nestSpec), pointer :: C2F_E => null()
489  type(nestSpec), pointer :: C2F_N => null()
490  type(nestSpec), pointer :: F2C_T => null()
491  type(nestSpec), pointer :: F2C_C => null()
492  type(nestSpec), pointer :: F2C_E => null()
493  type(nestSpec), pointer :: F2C_N => null()
494  type(domain2d), pointer :: domain_fine => null()
495  type(domain2d), pointer :: domain_coarse => null()
496  end type nest_level_type
497 
498 
499  !> Used for sending domain data between pe's
500  !> @ingroup mpp_domains_mod
502  private
503  logical :: initialized=.false.
504  integer(i8_kind) :: id=-9999
505  integer(i8_kind) :: l_addr =-9999
506  integer(i8_kind) :: l_addrx =-9999
507  integer(i8_kind) :: l_addry =-9999
508  type(domain2D), pointer :: domain =>null()
509  type(domain2D), pointer :: domain_in =>null()
510  type(domain2D), pointer :: domain_out =>null()
511  type(overlapSpec), pointer :: send(:,:,:,:) => null()
512  type(overlapSpec), pointer :: recv(:,:,:,:) => null()
513  integer, dimension(:,:), allocatable :: sendis
514  integer, dimension(:,:), allocatable :: sendie
515  integer, dimension(:,:), allocatable :: sendjs
516  integer, dimension(:,:), allocatable :: sendje
517  integer, dimension(:,:), allocatable :: recvis
518  integer, dimension(:,:), allocatable :: recvie
519  integer, dimension(:,:), allocatable :: recvjs
520  integer, dimension(:,:), allocatable :: recvje
521  logical, dimension(:), allocatable :: S_do_buf
522  logical, dimension(:), allocatable :: R_do_buf
523  integer, dimension(:), allocatable :: cto_pe
524  integer, dimension(:), allocatable :: cfrom_pe
525  integer, dimension(:), allocatable :: S_msize
526  integer, dimension(:), allocatable :: R_msize
527  integer :: Slist_size=0, rlist_size=0
528  integer :: isize=0, jsize=0, ke=0
529  integer :: isize_in=0, jsize_in=0
530  integer :: isize_out=0, jsize_out=0
531  integer :: isize_max=0, jsize_max=0
532  integer :: gf_ioff=0, gf_joff=0
533  ! Remote data
534  integer, dimension(:) , allocatable :: isizeR
535  integer, dimension(:) , allocatable :: jsizeR
536  integer, dimension(:,:), allocatable :: sendisR
537  integer, dimension(:,:), allocatable :: sendjsR
538  integer(i8_kind), dimension(:), allocatable :: rem_addr
539  integer(i8_kind), dimension(:), allocatable :: rem_addrx
540  integer(i8_kind), dimension(:), allocatable :: rem_addry
541  integer(i8_kind), dimension(:,:), allocatable :: rem_addrl
542  integer(i8_kind), dimension(:,:), allocatable :: rem_addrlx
543  integer(i8_kind), dimension(:,:), allocatable :: rem_addrly
544  integer :: position !< data location. T, E, C, or N.
545  end type domaincommunicator2d
546 
547  integer, parameter :: max_request = 100
548 
549  !> Used for nonblocking data transfer
550  !> @ingroup mpp_domains_mod
552  integer :: recv_pos
553  integer :: send_pos
554  integer :: recv_msgsize
555  integer :: send_msgsize
556  integer :: update_flags
557  integer :: update_position
558  integer :: update_gridtype
559  integer :: update_whalo
560  integer :: update_ehalo
561  integer :: update_shalo
562  integer :: update_nhalo
563  integer :: request_send_count
564  integer :: request_recv_count
565  type(mpi_request) :: request_send(MAX_REQUEST)
566  type(mpi_request) :: request_recv(MAX_REQUEST)
567  type(mpi_datatype) :: type_recv(MAX_REQUEST)
568  integer, dimension(MAX_REQUEST) :: size_recv
569  integer, dimension(MAX_REQUEST) :: buffer_pos_send
570  integer, dimension(MAX_REQUEST) :: buffer_pos_recv
571  integer(i8_kind) :: field_addrs(MAX_DOMAIN_FIELDS)
572  integer(i8_kind) :: field_addrs2(MAX_DOMAIN_FIELDS)
573  integer :: nfields
574  end type nonblock_type
575 
576  !> used for updates on a group
577  !> @ingroup mpp_domains_mod
579  private
580  logical :: initialized = .false.
581  logical :: k_loop_inside = .true.
582  logical :: nonsym_edge = .false.
583  integer :: nscalar = 0
584  integer :: nvector = 0
585  integer :: flags_s=0, flags_v=0
586  integer :: whalo_s=0, ehalo_s=0, shalo_s=0, nhalo_s=0
587  integer :: isize_s=0, jsize_s=0
588  integer :: whalo_v=0, ehalo_v=0, shalo_v=0, nhalo_v=0
589  integer :: isize_x=0, jsize_x=0
590  integer :: isize_y=0, jsize_y=0
591  integer :: ksize=1
592  integer :: position=0, gridtype=0
593  logical :: recv_s(8), recv_x(8), recv_y(8)
594  integer :: is_s=0, ie_s=0, js_s=0, je_s=0
595  integer :: is_x=0, ie_x=0, js_x=0, je_x=0
596  integer :: is_y=0, ie_y=0, js_y=0, je_y=0
597  integer :: ix_s=1, iy_s=2 !< Domain-decomposed dimensions of scalar arrays
598  integer :: ix_v=1, iy_v=2 !< Domain-decomposed dimensions of vector arrays
599  integer, allocatable, dimension(:) :: shape_s !< Shapes of scalar arrays
600  integer, allocatable, dimension(:) :: shape_x !< Shapes of vector arrays (x-component)
601  integer, allocatable, dimension(:) :: shape_y !< Shapes of vector arrays (y-component)
602  integer :: nrecv=0, nsend=0
603  integer :: npack=0, nunpack=0
604  integer :: reset_index_s = 0
605  integer :: reset_index_v = 0
606  integer :: tot_msgsize = 0
607  integer :: from_pe(maxoverlap)
608  integer :: to_pe(maxoverlap)
609  integer :: recv_size(maxoverlap)
610  integer :: send_size(maxoverlap)
611  integer :: buffer_pos_recv(maxoverlap)
612  integer :: buffer_pos_send(maxoverlap)
613  integer :: pack_type(maxoverlap)
614  integer :: pack_buffer_pos(maxoverlap)
615  integer :: pack_rotation(maxoverlap)
616  integer :: pack_size(maxoverlap)
617  integer :: pack_is(maxoverlap)
618  integer :: pack_ie(maxoverlap)
619  integer :: pack_js(maxoverlap)
620  integer :: pack_je(maxoverlap)
621  integer :: unpack_type(maxoverlap)
622  integer :: unpack_buffer_pos(maxoverlap)
623  integer :: unpack_rotation(maxoverlap)
624  integer :: unpack_size(maxoverlap)
625  integer :: unpack_is(maxoverlap)
626  integer :: unpack_ie(maxoverlap)
627  integer :: unpack_js(maxoverlap)
628  integer :: unpack_je(maxoverlap)
629  type(c_ptr) :: addrs_s(max_domain_fields)
630  type(c_ptr) :: addrs_x(max_domain_fields)
631  type(c_ptr) :: addrs_y(max_domain_fields)
632  integer :: buffer_start_pos = -1
633  type(mpi_request) :: request_send(max_request)
634  type(mpi_request) :: request_recv(max_request)
635  type(mpi_datatype) :: type_recv(max_request)
636  end type mpp_group_update_type
637 
638  !> One dimensional domain used to manage shared data access between pes
639  !> @ingroup mpp_domains_mod
640  type :: domain1d
641  private
642  type(domain_axis_spec) :: compute !< index limits for compute domain
643  type(domain_axis_spec) :: domain_data !< index limits for data domain
644  type(domain_axis_spec) :: global !< index limits for global domain
645  type(domain_axis_spec) :: memory !< index limits for memory domain
646  logical :: cyclic !< true if domain is cyclic
647  type(domain1d), pointer :: list(:) =>null() !< list of each pe's domains
648  integer :: pe !<PE to which this domain is assigned
649  integer :: pos !< position of this PE within link list, i.e domain%list(pos)%pe = pe
650  integer :: goffset !< needed for global sum
651  integer :: loffset !< needed for global sum
652  end type domain1d
653 
654 !#######################################################################
655 
656 !> @addtogroup mpp_domains_mod
657 !> @{
658 !***********************************************************************
659 !
660 ! module variables
661 !
662 !***********************************************************************
663  integer :: pe
664  logical :: module_is_initialized = .false.
665  logical :: debug = .false.
666  logical :: verbose=.false.
667  logical :: mosaic_defined = .false.
668  integer :: mpp_domains_stack_size=0
669  integer :: mpp_domains_stack_hwm=0
670  type(domain1d),save :: null_domain1d
671  type(domain2d),save :: null_domain2d
672  type(domainug),save :: null_domainug
673  integer :: current_id_update = 0
674  integer :: num_update = 0
675  integer :: num_nonblock_group_update = 0
676  integer :: nonblock_buffer_pos = 0
677  integer :: nonblock_group_buffer_pos = 0
678  logical :: start_update = .true.
679  logical :: complete_update = .false.
680  type(nonblock_type), allocatable :: nonblock_data(:)
681  integer, parameter :: max_nonblock_update = 100
682 
683  integer :: group_update_buffer_pos = 0
684  logical :: complete_group_update_on = .false.
685  !-------- The following variables are used in mpp_domains_comm.h
686 
687  integer, parameter :: max_addrs=512
688  integer(i8_kind),dimension(MAX_ADDRS),save :: addrs_sorted=-9999 !< list of sorted local addresses
689  integer, dimension(-1:MAX_ADDRS),save :: addrs_idx=-9999 !< index of address associated with d_comm
690  integer, save :: a_sort_len=0 !< length sorted memory list
691  integer, save :: n_addrs=0 !< number of memory addresses used
692 
693  integer(i8_kind), parameter :: addr2_base = 65536_i8_kind !< = 0x0000000000010000
694  integer, parameter :: max_addrs2=128
695  integer(i8_kind),dimension(MAX_ADDRS2),save :: addrs2_sorted=-9999 !< list of sorted local addresses
696  integer, dimension(-1:MAX_ADDRS2),save :: addrs2_idx=-9999 !< index of addr2 associated with d_comm
697  integer, save :: a2_sort_len=0 !< length sorted memory list
698  integer, save :: n_addrs2=0 !< number of memory addresses used
699 
700  integer, parameter :: max_dom_ids=128
701  integer(i8_kind),dimension(MAX_DOM_IDS),save :: ids_sorted=-9999 !< list of sorted domain identifiers
702  integer, dimension(-1:MAX_DOM_IDS),save :: ids_idx=-9999 !< index of d_comm associated with sorted addesses
703  integer, save :: i_sort_len=0 !< length sorted domain ids list
704  integer, save :: n_ids=0 !< number of domain ids used
705  !!(=i_sort_len; domain ids are never removed)
706 
707  integer, parameter :: max_fields=1024
708  integer(i8_kind), dimension(MAX_FIELDS),save :: dckey_sorted=-9999 !< list of sorted local addresses
709  ! Not sure why static d_comm fails during deallocation of derived type members; allocatable works
710  ! type(DomainCommunicator2D),dimension(MAX_FIELDS),save,target :: d_comm !< domain communicators
711  type(domaincommunicator2d),dimension(:),allocatable,save,target :: d_comm !< domain communicators
712  integer, dimension(-1:MAX_FIELDS),save :: d_comm_idx=-9999 !< index of
713  !! d_comm associated with sorted addresses
714  integer, save :: dc_sort_len=0 !< length sorted comm keys
715 !! (=num active communicators)
716  integer, save :: n_comm=0 !< number of communicators used
717 
718  ! integer(i8_kind), parameter :: GT_BASE=2**8
719  integer(i8_kind), parameter :: gt_base = 256_i8_kind !0x0000000000000100
720 
721  ! integer(i8_kind), parameter :: KE_BASE=2**48
722  integer(i8_kind), parameter :: ke_base = 281474976710656_i8_kind !0x0001000000000000
723 
724  integer(i8_kind) :: domain_cnt=0
725 
726  !--- the following variables are used in mpp_domains_misc.h
727  logical :: domain_clocks_on=.false.
728  integer :: send_clock=0, recv_clock=0, unpk_clock=0
729  integer :: wait_clock=0, pack_clock=0
730  integer :: send_pack_clock_nonblock=0, recv_clock_nonblock=0, unpk_clock_nonblock=0
731  integer :: wait_clock_nonblock=0
732  integer :: nest_send_clock=0, nest_recv_clock=0, nest_unpk_clock=0
733  integer :: nest_wait_clock=0, nest_pack_clock=0
734  integer :: group_recv_clock=0, group_send_clock=0, group_pack_clock=0, group_unpk_clock=0, group_wait_clock=0
735  integer :: nonblock_group_recv_clock=0, nonblock_group_send_clock=0, nonblock_group_pack_clock=0
736  integer :: nonblock_group_unpk_clock=0, nonblock_group_wait_clock=0
737 
738 !> namelist interface
739  character(len=32) :: debug_update_domain = "none" !< when debug_update_domain = none, no debug will be done.
740  !! When debug_update_domain is set to fatal,
741  !! the run will be exited with fatal error message
742  !! When debug_update_domain is set to warning,
743  !! the run will output warning message.
744  !! When debug update_domain is set to note,
745  !! the run will output some note message.
746  logical :: debug_message_passing = .false. !< Will check the consistency on the boundary between
747  !! processor/tile when updating domain for symmetric domain and
748  !! check the consistency on the north folded edge.
749  integer :: nthread_control_loop = 8 !< Determine the loop order for packing and unpacking.
750  !! When number of threads is greater than nthread_control_loop,
751  !! the k-loop will be moved outside and combined with number
752  !! of pack and unpack. When the number of threads is
753  !! less than or equal to nthread_control_loop, the k-loop
754  !! is moved inside, but still outside, of j,i loop.
755  logical :: efp_sum_overflow_check = .false. !< If .true., always do overflow_check
756  !! when doing EFP bitwise mpp_global_sum.
757  logical :: use_alltoallw = .false.
758  namelist /mpp_domains_nml/ debug_update_domain, domain_clocks_on, debug_message_passing, nthread_control_loop, &
759  efp_sum_overflow_check, use_alltoallw
760 
761  !***********************************************************************
762 
763  integer, parameter :: no_check = -1
764  integer :: debug_update_level = no_check
765 !> @}
766 !***********************************************************************
767 !
768 ! public interface from mpp_domains_define.h
769 !
770 !***********************************************************************
771  !> @brief Retrieve layout associated with a domain decomposition.
772  !> Given a global 2D domain and the number of divisions in the
773  !! decomposition ndivs (usually the PE count unless some
774  !! domains are \e masked) this calls returns a 2D domain layout.
775  !! By default, mpp_define_layout will attempt to divide the
776  !! 2D index space into domains that maintain the aspect ratio of the
777  !! global domain. If this cannot be done, the algorithm favours domains
778  !! that are longer in \e x than \e y, a preference that could improve vector performance.
779  !! <br>Example usage:
780  !! @code{.F90}call mpp_define_layout( global_indices, ndivs, layout )@endcode
781  !> @ingroup mpp_domains_mod
783  module procedure mpp_define_layout2d
784  end interface
785 
786  !> @brief Set up a domain decomposition.
787  !!
788  !> There are two forms for the \e mpp_define_domains call. The 2D version is generally
789  !! to be used but is built by repeated calls to the 1D version, also provided.
790  !!
791  !! <br>Example usage:
792  !!
793  !! call mpp_define_domains( global_indices, ndivs, domain, &
794  !! pelist, flags, halo, extent, maskmap )
795  !! call mpp_define_domains( global_indices, layout, domain, pelist, &
796  !! xflags, yflags, xhalo, yhalo, &
797  !! xextent, yextent, maskmap, name )
798  !!
799  !! @param global_indices Defines the global domain.
800  !! @param ndivs The number of domain divisions required.
801  !! @param [inout] domain Holds the resulting domain decomposition.
802  !! @param pelist List of PEs to which the domains are to be assigned.
803  !! @param flags An optional flag to pass additional information
804  !! about the desired domain topology. Useful flags in a 1D decomposition
805  !! include <TT>GLOBAL_DATA_DOMAIN</TT> and
806  !! <TT>CYCLIC_GLOBAL_DOMAIN</TT>. Flags are integers: multiple flags may
807  !! be added together. The flag values are public parameters available by
808  !! use association.
809  !! @param halo Width of the halo.
810  !! @param extent Normally <TT>mpp_define_domains</TT> attempts
811  !! an even division of the global domain across <TT>ndivs</TT>
812  !! domains. The <TT>extent</TT> array can be used by the user to pass a
813  !! custom domain division. The <TT>extent</TT> array has <TT>ndivs</TT>
814  !! elements and holds the compute domain widths, which should add up to
815  !! cover the global domain exactly.
816  !! @param maskmap Some divisions may be masked
817  !! (<TT>maskmap=.FALSE.</TT>) to exclude them from the computation (e.g
818  !! for ocean model domains that are all land). The <TT>maskmap</TT> array
819  !! is dimensioned <TT>ndivs</TT> and contains <TT>.TRUE.</TT> values for
820  !! any domain that must be <I>included</I> in the computation (default
821  !! all). The <TT>pelist</TT> array length should match the number of
822  !! domains included in the computation.
823  !!
824  !! <br>Example usage:
825  !! @code{.F90}
826  !! call mpp_define_domains( (/1,100/), 10, domain, &
827  !! flags=GLOBAL_DATA_DOMAIN+CYCLIC_GLOBAL_DOMAIN, halo=2 )
828  !! @endcode
829  !!
830  !! defines 10 compute domains spanning the range [1,100] of the global
831  !! domain. The compute domains are non-overlapping blocks of 10. All the data
832  !! domains are global, and with a halo of 2 span the range [-1:102]. And
833  !! since the global domain has been declared to be cyclic,
834  !! domain(9)%next => domain(0) and domain(0)%prev =>
835  !! domain(9). A field is allocated on the data domain, and computations proceed on
836  !! the compute domain. A call to mpp_update_domains would fill in the values
837  !! in the halo region:<br>
838  !!<br>
839  !! @code{.F90}
840  !! call mpp_get_data_domain( domain, isd, ied ) !returns -1 and 102
841  !! call mpp_get_compute_domain( domain, is, ie ) !returns (1,10) on PE 0 ...
842  !! allocate( a(isd:ied) )
843  !! do i = is,ie
844  !! a(i) = &lt;perform computations&gt;
845  !! end do
846  !! call mpp_update_domains( a, domain )
847  !! @endcode
848  !!<br>
849  !! The call to mpp_update_domainsfills in the regions outside
850  !! the compute domain. Since the global domain is cyclic, the values at
851  !! \e i=(-1,0) are the same as at \e i=(99,100); and \e i=(101,102)
852  !! are the same as \e i=(1,2).
853  !!
854  !! The 2D version is just an extension of this syntax to two dimensions.
855  !!
856  !! The 2D version of the above should generally be used in
857  !! codes, including 1D-decomposed ones, if there is a possibility of
858  !! future evolution toward 2D decomposition. The arguments are similar to
859  !! the 1D case, except that now we have optional arguments
860  !! flags, halo, extent and maskmap along two axes.
861  !!
862  !! flags can now take an additional possible value to fold one or more edges.
863  !! This is done by using flags \e FOLD_WEST_EDGE, \e FOLD_EAST_EDGE, \e FOLD_SOUTH_EDGE or
864  !! \e FOLD_NORTH_EDGE. When a fold exists (e.g cylindrical domain),
865  !! vector fields reverse sign upon
866  !! crossing the fold. This parity reversal is performed only in the vector version of
867  !! mpp_update_domains. In addition, shift operations may need to be applied to vector fields on
868  !! staggered grids, also described in the vector interface to mpp_update_domains.
869  !!
870  !! <TT>name</TT> is the name associated with the decomposition,
871  !! e.g <TT>'Ocean model'</TT>. If this argument is present,
872  !! <TT>mpp_define_domains</TT> will print the domain decomposition
873  !! generated to <TT>stdlog</TT>.
874  !!
875  !! <br>Examples:
876  !! call mpp_define_domains( (/1,100,1,100/), (/2,2/), domain, xhalo=1 )
877  !! will create the following domain layout:<br>
878  !!<br>
879  !! | domain |domain(1)|domain(2) |domain(3) |domain(4) |
880  !! |--------------|---------|-----------|-----------|-------------|
881  !! |Compute domain|1,50,1,50|51,100,1,50|1,50,51,100|51,100,51,100|
882  !! |Data domain |0,51,1,50|50,101,1,50|0,51,51,100|50,101,51,100|
883  !!
884  !!
885  !! Again, we allocate arrays on the data domain, perform computations
886  !! on the compute domain, and call mpp_update_domains to update the halo region.
887  !!
888  !! If we wished to perfom a 1D decomposition along Y on the same global domain,
889  !! we could use:
890  !!
891  !! call mpp_define_domains( (/1,100,1,100/), layout=(/4,1/), domain, xhalo=1 )
892  !!
893  !! This will create the following domain layout:<br>
894  !!<br>
895  !! | domain |domain(1) |domain(2) |domain(3) |domain(4) |
896  !! |--------------|----------|-----------|-----------|------------|
897  !! |Compute domain|1,100,1,25|1,100,26,50|1,100,51,75|1,100,76,100|
898  !! |Data domain |0,101,1,25|0,101,26,50|0,101,51,75|1,101,76,100|
899  !> @ingroup mpp_domains_mod
901  module procedure mpp_define_domains1d
902  module procedure mpp_define_domains2d
903  end interface
904 
905  !> Defines a nullified 1D or 2D domain
906  !!
907  !> <br> Example usage:
908  !! @code{.F90}
909  !! call mpp_define_null_domain(domain)
910  !! @endcode
911  !> @ingroup mpp_domains_mod
913  module procedure mpp_define_null_domain1d
914  module procedure mpp_define_null_domain2d
915  end interface
916 
917  !> Copy 1D or 2D domain
918  !> @param domain_in Input domain to get read
919  !> @param domain_out Output domain to get written to
920  !> @ingroup mpp_domains_mod
921  interface mpp_copy_domain
922  module procedure mpp_copy_domain1d
923  module procedure mpp_copy_domain2d
924  end interface mpp_copy_domain
925  !> Deallocate given 1D or 2D domain
926  !> @param domain an allocated @ref domain1D or @ref domain2D
927  !> @ingroup mpp_domains_mod
929  module procedure mpp_deallocate_domain1d
930  module procedure mpp_deallocate_domain2d
931  end interface
932 
933  !> Modifies the extents (compute, data and global) of a given domain
934  !> @ingroup mpp_domains_mod
936  module procedure mpp_modify_domain1d
937  module procedure mpp_modify_domain2d
938  end interface
939 
940 
941 !***********************************************************************
942 !
943 ! public interface from mpp_domains_misc.h
944 !
945 !***********************************************************************
946 
947 !> Performs halo updates for a given domain.<br>
948 !!
949 !! Used to perform a halo update of a
950 !! domain-decomposed array on each PE. \e MPP_TYPE can be of type
951 !! complex, integer, logical or real of 4-byte or 8-byte kind; of rank up to 5.
952 !! The vector version (with two input data fields) is only present for real types.
953 !! For 2D domain updates, if there are halos present along both
954 !! x and y, we can choose to update one only, by specifying \e flags=XUPDATE or \e flags=YUPDATE.
955 !! In addition, one-sided updates can be performed by setting flags
956 !! to any combination of WUPDATE, EUPDATE, SUPDATE and NUPDATE
957 !! to update the west, east, north and south halos respectively.
958 !! Any combination of halos may be used by adding the requisite flags, e.g:
959 !! \e flags=XUPDATE+SUPDATE or \e flags=EUPDATE+WUPDATE+SUPDATE will update the east,
960 !! west and south halos.<br>
961 !!<br>
962 !! If a call to \e mpp_update_domains involves at least one E-W
963 !! halo and one N-S halo, the corners involved will also be updated, i.e,
964 !! in the example above, the SE and SW corners will be updated.<br>
965 !! If \e flags is not supplied, that is equivalent to \e flags=XUPDATE+YUPDATE.<br>
966 !!<br>
967 !! The vector version is passed the \e x and \e y components of a vector field in tandem,
968 !! and both are updated upon return. They are passed together to treat parity issues on various
969 !! grids. For example, on a cubic sphere projection, the \e x \e y components may be
970 !! interchanged when passing from an equatorial cube face to a polar face.
971 !! For grids with folds, vector components change sign on crossing the fold. Paired scalar
972 !! quantities can also be passed with the vector version if \e flags=SCALAR_PAIR, in which
973 !! case components are appropriately interchanged, but signs are not.<br>
974 !!<br>
975 !! Special treatment at boundaries such as folds is also required for
976 !! staggered grids. The following types of staggered grids are
977 !! recognized:<br>
978 !!<br>
979 !! 1) AGRID: values are at grid centers.<br>
980 !! 2) BGRID_NE: vector fields are at the NE vertex of a grid
981 !! cell, i.e: the array elements \e u(i,j)and \e v(i,j)are
982 !! actually at (i,j;) with respect to the grid centers.<br>
983 !! 3) BGRID_SW: vector fields are at the SW vertex of a grid
984 !! cell, i.e: the array elements \e u(i,j) and \e v(i,j) are
985 !! actually at (i;,j;) with respect to the grid centers<br>
986 !! 4) CGRID_NE: vector fields are at the N and E faces of a
987 !! grid cell, i.e: the array elements \e u(i,j) and \e v(i,j)
988 !! are actually at (i;,j) and (i,j+&#189;) with respect to the
989 !! grid centers.<br>
990 !! 5) CGRID_SW: vector fields are at the S and W faces of a
991 !! grid cell, i.e: the array elements \e u(i,j)and \e v(i,j)
992 !! are actually at (i;,j) and (i,j;) with respect to the
993 !! grid centers.<br>
994 !!<br>
995 !! The gridtypes listed above are all available by use association as
996 !! integer parameters. The scalar version of \e mpp_update_domains
997 !! assumes that the values of a scalar field are always at \e AGRID
998 !! locations, and no special boundary treatment is required. If vector
999 !! fields are at staggered locations, the optional argument
1000 !! \e gridtype must be appropriately set for correct treatment at
1001 !! boundaries.
1002 !!<br>
1003 !! It is safe to apply vector field updates to the appropriate arrays
1004 !! irrespective of the domain topology: if the topology requires no
1005 !! special treatment of vector fields, specifying \e gridtype will
1006 !! do no harm.<br>
1007 !!<br>
1008 !! \e mpp_update_domains internally buffers the date being sent
1009 !! and received into single messages for efficiency. A turnable internal
1010 !! buffer area in memory is provided for this purpose by
1011 !! \e mpp_domains_mod. The size of this buffer area can be set by
1012 !! the user by calling mpp_domains
1013 !! \e mpp_domains_set_stack_size.
1014 !!
1015 !! Example usage:
1016 !! call mpp_update_domains( field, domain, flags )
1017 !! Update a 1D domain for the given field.
1018 !! call mpp_update_domains( fieldx, fieldy, domain, flags, gridtype )
1019 !! Update a 2D domain for the given fields.
1020 !> @ingroup mpp_domains_mod
1022  module procedure mpp_update_domain2d_r8_2d
1023  module procedure mpp_update_domain2d_r8_3d
1024  module procedure mpp_update_domain2d_r8_4d
1025  module procedure mpp_update_domain2d_r8_5d
1026  module procedure mpp_update_domain2d_r8_2dv
1027  module procedure mpp_update_domain2d_r8_3dv
1028  module procedure mpp_update_domain2d_r8_4dv
1029  module procedure mpp_update_domain2d_r8_5dv
1030 #ifdef OVERLOAD_C8
1031  module procedure mpp_update_domain2d_c8_2d
1032  module procedure mpp_update_domain2d_c8_3d
1033  module procedure mpp_update_domain2d_c8_4d
1034  module procedure mpp_update_domain2d_c8_5d
1035 #endif
1036  module procedure mpp_update_domain2d_i8_2d
1037  module procedure mpp_update_domain2d_i8_3d
1038  module procedure mpp_update_domain2d_i8_4d
1039  module procedure mpp_update_domain2d_i8_5d
1040  module procedure mpp_update_domain2d_r4_2d
1041  module procedure mpp_update_domain2d_r4_3d
1042  module procedure mpp_update_domain2d_r4_4d
1043  module procedure mpp_update_domain2d_r4_5d
1044  module procedure mpp_update_domain2d_r4_2dv
1045  module procedure mpp_update_domain2d_r4_3dv
1046  module procedure mpp_update_domain2d_r4_4dv
1047  module procedure mpp_update_domain2d_r4_5dv
1048 #ifdef OVERLOAD_C4
1049  module procedure mpp_update_domain2d_c4_2d
1050  module procedure mpp_update_domain2d_c4_3d
1051  module procedure mpp_update_domain2d_c4_4d
1052  module procedure mpp_update_domain2d_c4_5d
1053 #endif
1054  module procedure mpp_update_domain2d_i4_2d
1055  module procedure mpp_update_domain2d_i4_3d
1056  module procedure mpp_update_domain2d_i4_4d
1057  module procedure mpp_update_domain2d_i4_5d
1058  end interface
1059 
1060 !> Interface to start halo updates
1061 !! \e mpp_start_update_domains is used to start a halo update of a
1062 !! domain-decomposed array on each PE. \e MPP_TYPE_ can be of type
1063 !! \e complex, \e integer, \e logical or \e real;
1064 !! of 4-byte or 8-byte kind; of rank up to 5. The vector version (with
1065 !! two input data fields) is only present for \ereal types.<br>
1066 !!<br>
1067 !! \empp_start_update_domains must be paired together with
1068 !! \empp_complete_update_domains. In \e mpp_start_update_domains,
1069 !! a buffer will be pre-post to receive (non-blocking) the
1070 !! data and data on computational domain will be packed and sent (non-blocking send)
1071 !! to other processor. In \e mpp_complete_update_domains, buffer will
1072 !! be unpacked to fill the halo and mpp_sync_self will be called to
1073 !! to ensure communication safe at the last call of mpp_complete_update_domains.<br>
1074 !!<br>
1075 !! Each mpp_update_domains can be replaced by the combination of mpp_start_update_domains
1076 !! and mpp_complete_update_domains. The arguments in mpp_start_update_domains
1077 !! and mpp_complete_update_domains should be the exact the same as in
1078 !! mpp_update_domains to be replaced except no optional argument "complete".
1079 !! The following are examples on how to replace mpp_update_domains with
1080 !! mpp_start_update_domains/mpp_complete_update_domains
1081 !!
1082 !> @par Example 1: Replace one scalar mpp_update_domains.<br>
1083 !!<br>
1084 !! Replace<br>
1085 !!<br>
1086 !! call mpp_update_domains(data, domain, flags=update_flags)<br>
1087 !!
1088 !! with<br>
1089 !!<br>
1090 !! id_update = mpp_start_update_domains(data, domain, flags=update_flags)<br>
1091 !! ...( doing some computation )<br>
1092 !! call mpp_complete_update_domains(id_update, data, domain, flags=update_flags)<br>
1093 !!
1094 !> @par Example 2: Replace group scalar mpp_update_domains<br>
1095 !!<br>
1096 !! Replace<br>
1097 !!<br>
1098 !! call mpp_update_domains(data_1, domain, flags=update_flags, complete=.false.)<br>
1099 !! .... ( other n-2 call mpp_update_domains with complete = .false. )<br>
1100 !! call mpp_update_domains(data_n, domain, flags=update_flags, complete=.true. )<br>
1101 !!<br>
1102 !! With<br>
1103 !!<br>
1104 !! id_up_1 = mpp_start_update_domains(data_1, domain, flags=update_flags)<br>
1105 !! .... ( other n-2 call mpp_start_update_domains )<br>
1106 !! id_up_n = mpp_start_update_domains(data_n, domain, flags=update_flags)<br>
1107 !!<br>
1108 !! ..... ( doing some computation )<br>
1109 !!<br>
1110 !! call mpp_complete_update_domains(id_up_1, data_1, domain, flags=update_flags)<br>
1111 !! .... ( other n-2 call mpp_complete_update_domains )<br>
1112 !! call mpp_complete_update_domains(id_up_n, data_n, domain, flags=update_flags)<br>
1113 !!
1114 !> @par Example 3: Replace group CGRID_NE vector, mpp_update_domains<br>
1115 !!<br>
1116 !! Replace<br>
1117 !!<br>
1118 !! call mpp_update_domains(u_1, v_1, domain, flags=update_flgs, gridtype=CGRID_NE, complete=.false.)<br>
1119 !! .... ( other n-2 call mpp_update_domains with complete = .false. )<br>
1120 !! call mpp_update_domains(u_1, v_1, domain, flags=update_flags, gridtype=CGRID_NE, complete=.true. )<br>
1121 !!<br>
1122 !! with<br>
1123 !!<br>
1124 !! id_up_1 = mpp_start_update_domains(u_1, v_1, domain, flags=update_flags, gridtype=CGRID_NE)<br>
1125 !! .... ( other n-2 call mpp_start_update_domains )<br>
1126 !! id_up_n = mpp_start_update_domains(u_n, v_n, domain, flags=update_flags, gridtype=CGRID_NE)<br>
1127 !!<br>
1128 !! ..... ( doing some computation )<br>
1129 !!<br>
1130 !! call mpp_complete_update_domains(id_up_1, u_1, v_1, domain, flags=update_flags, gridtype=CGRID_NE)<br>
1131 !! .... ( other n-2 call mpp_complete_update_domains )<br>
1132 !! call mpp_complete_update_domains(id_up_n, u_n, v_n, domain, flags=update_flags, gridtype=CGRID_NE)<br>
1133 !!<br>
1134 !! For 2D domain updates, if there are halos present along both
1135 !! \e x and \e y, we can choose to update one only, by
1136 !! specifying \e flags=XUPDATE or \e flags=YUPDATE. In
1137 !! addition, one-sided updates can be performed by setting \e flags
1138 !! to any combination of \e WUPDATE, \e EUPDATE,
1139 !! \e SUPDATE and \e NUPDATE, to update the west, east, north
1140 !! and south halos respectively. Any combination of halos may be used by
1141 !! adding the requisite flags, e.g: \e flags=XUPDATE+SUPDATE or
1142 !! \e flags=EUPDATE+WUPDATE+SUPDATE will update the east, west and
1143 !! south halos.<br>
1144 !!<br>
1145 !! If a call to \e mpp_start_update_domains/mpp_complete_update_domains involves at least one E-W
1146 !! halo and one N-S halo, the corners involved will also be updated, i.e,
1147 !! in the example above, the SE and SW corners will be updated.<br>
1148 !!<br>
1149 !! If \e flags is not supplied, that is
1150 !! equivalent to \e flags=XUPDATE+YUPDATE.<br>
1151 !!<br>
1152 !! The vector version is passed the \e x and \e y
1153 !! components of a vector field in tandem, and both are updated upon
1154 !! return. They are passed together to treat parity issues on various
1155 !! grids. For example, on a cubic sphere projection, the \e x and
1156 !! \e y components may be interchanged when passing from an
1157 !! equatorial cube face to a polar face. For grids with folds, vector
1158 !! components change sign on crossing the fold. Paired scalar quantities
1159 !! can also be passed with the vector version if flags=SCALAR_PAIR, in which
1160 !! case components are appropriately interchanged, but signs are not.<br>
1161 !!<br>
1162 !! Special treatment at boundaries such as folds is also required for
1163 !! staggered grids. The following types of staggered grids are
1164 !! recognized:
1165 !!<br>
1166 !! 1) \e AGRID: values are at grid centers.<br>
1167 !! 2) \e BGRID_NE: vector fields are at the NE vertex of a grid
1168 !! cell, i.e: the array elements \e u(i,j) and \e v(i,j) are
1169 !! actually at (i+&#189;,j+&#189;) with respect to the grid centers.<br>
1170 !! 3) \e BGRID_SW: vector fields are at the SW vertex of a grid
1171 !! cell, i.e., the array elements \e u(i,j) and \e v(i,j) are
1172 !! actually at (i-&#189;,j-&#189;) with respect to the grid centers.<br>
1173 !! 4) \e CGRID_NE: vector fields are at the N and E faces of a
1174 !! grid cell, i.e: the array elements \e u(i,j) and \e v(i,j)
1175 !! are actually at (i+&#189;,j) and (i,j+&#189;) with respect to the
1176 !! grid centers.<br>
1177 !! 5) \e CGRID_SW: vector fields are at the S and W faces of a
1178 !! grid cell, i.e: the array elements \e u(i,j) and \e v(i,j)
1179 !! are actually at (i-&#189;,j) and (i,j-&#189;) with respect to the
1180 !! grid centers.<br>
1181 !!<br>
1182 !! The gridtypes listed above are all available by use association as
1183 !! integer parameters. If vector fields are at staggered locations, the
1184 !! optional argument \e gridtype must be appropriately set for
1185 !! correct treatment at boundaries.
1186 !!<br>
1187 !! It is safe to apply vector field updates to the appropriate arrays
1188 !! irrespective of the domain topology: if the topology requires no
1189 !! special treatment of vector fields, specifying \e gridtype will
1190 !! do no harm.<br>
1191 !!<br>
1192 !! \e mpp_start_update_domains/mpp_complete_update_domains internally
1193 !! buffers the data being sent and received into single messages for efficiency.
1194 !! A turnable internal buffer area in memory is provided for this purpose by
1195 !! \e mpp_domains_mod. The size of this buffer area can be set by
1196 !! the user by calling \e mpp_domains_set_stack_size.<br>
1197 !! Example usage:
1198 !!
1199 !! call mpp_start_update_domains( field, domain, flags )
1200 !! call mpp_complete_update_domains( field, domain, flags )
1201 !> @ingroup mpp_domains_mod
1203  module procedure mpp_start_update_domain2d_r8_2d
1204  module procedure mpp_start_update_domain2d_r8_3d
1205  module procedure mpp_start_update_domain2d_r8_4d
1206  module procedure mpp_start_update_domain2d_r8_5d
1207  module procedure mpp_start_update_domain2d_r8_2dv
1208  module procedure mpp_start_update_domain2d_r8_3dv
1209  module procedure mpp_start_update_domain2d_r8_4dv
1210  module procedure mpp_start_update_domain2d_r8_5dv
1211 #ifdef OVERLOAD_C8
1212  module procedure mpp_start_update_domain2d_c8_2d
1213  module procedure mpp_start_update_domain2d_c8_3d
1214  module procedure mpp_start_update_domain2d_c8_4d
1215  module procedure mpp_start_update_domain2d_c8_5d
1216 #endif
1217  module procedure mpp_start_update_domain2d_i8_2d
1218  module procedure mpp_start_update_domain2d_i8_3d
1219  module procedure mpp_start_update_domain2d_i8_4d
1220  module procedure mpp_start_update_domain2d_i8_5d
1221  module procedure mpp_start_update_domain2d_r4_2d
1222  module procedure mpp_start_update_domain2d_r4_3d
1223  module procedure mpp_start_update_domain2d_r4_4d
1224  module procedure mpp_start_update_domain2d_r4_5d
1225  module procedure mpp_start_update_domain2d_r4_2dv
1226  module procedure mpp_start_update_domain2d_r4_3dv
1227  module procedure mpp_start_update_domain2d_r4_4dv
1228  module procedure mpp_start_update_domain2d_r4_5dv
1229 #ifdef OVERLOAD_C4
1230  module procedure mpp_start_update_domain2d_c4_2d
1231  module procedure mpp_start_update_domain2d_c4_3d
1232  module procedure mpp_start_update_domain2d_c4_4d
1233  module procedure mpp_start_update_domain2d_c4_5d
1234 #endif
1235  module procedure mpp_start_update_domain2d_i4_2d
1236  module procedure mpp_start_update_domain2d_i4_3d
1237  module procedure mpp_start_update_domain2d_i4_4d
1238  module procedure mpp_start_update_domain2d_i4_5d
1239  end interface
1240 
1241  !> Must be used after a call to @ref mpp_start_update_domains
1242  !! in order to complete a nonblocking domain update. See @ref mpp_start_update_domains
1243  !! for more info.
1244  !> @ingroup mpp_domains_mod
1246  module procedure mpp_complete_update_domain2d_r8_2d
1247  module procedure mpp_complete_update_domain2d_r8_3d
1248  module procedure mpp_complete_update_domain2d_r8_4d
1249  module procedure mpp_complete_update_domain2d_r8_5d
1250  module procedure mpp_complete_update_domain2d_r8_2dv
1251  module procedure mpp_complete_update_domain2d_r8_3dv
1252  module procedure mpp_complete_update_domain2d_r8_4dv
1253  module procedure mpp_complete_update_domain2d_r8_5dv
1254 #ifdef OVERLOAD_C8
1255  module procedure mpp_complete_update_domain2d_c8_2d
1256  module procedure mpp_complete_update_domain2d_c8_3d
1257  module procedure mpp_complete_update_domain2d_c8_4d
1258  module procedure mpp_complete_update_domain2d_c8_5d
1259 #endif
1260  module procedure mpp_complete_update_domain2d_i8_2d
1261  module procedure mpp_complete_update_domain2d_i8_3d
1262  module procedure mpp_complete_update_domain2d_i8_4d
1263  module procedure mpp_complete_update_domain2d_i8_5d
1264  module procedure mpp_complete_update_domain2d_r4_2d
1265  module procedure mpp_complete_update_domain2d_r4_3d
1266  module procedure mpp_complete_update_domain2d_r4_4d
1267  module procedure mpp_complete_update_domain2d_r4_5d
1268  module procedure mpp_complete_update_domain2d_r4_2dv
1269  module procedure mpp_complete_update_domain2d_r4_3dv
1270  module procedure mpp_complete_update_domain2d_r4_4dv
1271  module procedure mpp_complete_update_domain2d_r4_5dv
1272 #ifdef OVERLOAD_C4
1273  module procedure mpp_complete_update_domain2d_c4_2d
1274  module procedure mpp_complete_update_domain2d_c4_3d
1275  module procedure mpp_complete_update_domain2d_c4_4d
1276  module procedure mpp_complete_update_domain2d_c4_5d
1277 #endif
1278  module procedure mpp_complete_update_domain2d_i4_2d
1279  module procedure mpp_complete_update_domain2d_i4_3d
1280  module procedure mpp_complete_update_domain2d_i4_4d
1281  module procedure mpp_complete_update_domain2d_i4_5d
1282  end interface
1283 
1284  !> Private interface used for non blocking updates
1285  !> @ingroup mpp_domains_mod
1287  module procedure mpp_start_do_update_r8_3d
1288  module procedure mpp_start_do_update_r8_3dv
1289 #ifdef OVERLOAD_C8
1290  module procedure mpp_start_do_update_c8_3d
1291 #endif
1292  module procedure mpp_start_do_update_i8_3d
1293  module procedure mpp_start_do_update_r4_3d
1294  module procedure mpp_start_do_update_r4_3dv
1295 #ifdef OVERLOAD_C4
1296  module procedure mpp_start_do_update_c4_3d
1297 #endif
1298  module procedure mpp_start_do_update_i4_3d
1299  end interface
1300 
1301  !> Private interface used for non blocking updates
1302  !> @ingroup mpp_domains_mod
1304  module procedure mpp_complete_do_update_r8_3d
1305  module procedure mpp_complete_do_update_r8_3dv
1306 #ifdef OVERLOAD_C8
1307  module procedure mpp_complete_do_update_c8_3d
1308 #endif
1309  module procedure mpp_complete_do_update_i8_3d
1310  module procedure mpp_complete_do_update_r4_3d
1311  module procedure mpp_complete_do_update_r4_3dv
1312 #ifdef OVERLOAD_C4
1313  module procedure mpp_complete_do_update_c4_3d
1314 #endif
1315  module procedure mpp_complete_do_update_i4_3d
1316  end interface
1317 
1318  !> Constructor for the @ref mpp_group_update_type which is
1319  !! then used with @ref mpp_start_group_update
1320  !!
1321  !> @param
1322  !> @ingroup mpp_domains_mod
1324  module procedure mpp_create_group_update_r4
1325  module procedure mpp_create_group_update_r4_v
1326  module procedure mpp_create_group_update_r8
1327  module procedure mpp_create_group_update_r8_v
1328  end interface mpp_create_group_update
1329 
1330  !> @ingroup mpp_domains_mod
1332  module procedure mpp_do_group_update_r4
1333  module procedure mpp_do_group_update_r8
1334  end interface mpp_do_group_update
1335 
1336  !> Starts non-blocking group update
1337  !! Must be followed up with a call to @ref mpp_complete_group_update
1338  !! @ref mpp_group_update_type can be created with @ref mpp_create_group_update
1339  !!
1340  !> @param[inout] type(mpp_group_update_type) group type created for group update
1341  !> @param[inout] type(domain2D) domain to update
1342  !> @ingroup mpp_domains_mod
1344  module procedure mpp_start_group_update_r4
1345  module procedure mpp_start_group_update_r8
1346  end interface mpp_start_group_update
1347 
1348  !> Completes a pending non-blocking group update
1349  !! Must follow a call to @ref mpp_start_group_update
1350  !!
1351  !> @param[inout] type(mpp_group_update_type) group
1352  !> @param[inout] type(domain2D) domain
1353  !> @param[in] d_type data type
1354  !> @ingroup mpp_domains_mod
1356  module procedure mpp_complete_group_update_r4
1357  module procedure mpp_complete_group_update_r8
1358  end interface mpp_complete_group_update
1359 
1360  !> @ingroup mpp_domains_mod
1362  module procedure mpp_reset_group_update_field_r4
1363  module procedure mpp_reset_group_update_field_r4_v
1364  module procedure mpp_reset_group_update_field_r8
1365  module procedure mpp_reset_group_update_field_r8_v
1366  end interface mpp_reset_group_update_field
1367 
1368  !> Pass the data from coarse grid to fill the buffer to be ready to be interpolated
1369  !! onto fine grid.
1370  !! <br>Example usage:
1371  !!
1372  !! call mpp_update_nest_fine(field, nest_domain, wbuffer, ebuffer, sbuffer,
1373  !! nbuffer, nest_level, flags, complete, position, extra_halo, name,
1374  !! tile_count)
1375  !> @ingroup mpp_domains_mod
1377  module procedure mpp_update_nest_fine_r8_2d
1378  module procedure mpp_update_nest_fine_r8_3d
1379  module procedure mpp_update_nest_fine_r8_4d
1380  module procedure mpp_update_nest_fine_r8_2dv
1381  module procedure mpp_update_nest_fine_r8_3dv
1382  module procedure mpp_update_nest_fine_r8_4dv
1383 #ifdef OVERLOAD_C8
1384  module procedure mpp_update_nest_fine_c8_2d
1385  module procedure mpp_update_nest_fine_c8_3d
1386  module procedure mpp_update_nest_fine_c8_4d
1387 #endif
1388  module procedure mpp_update_nest_fine_i8_2d
1389  module procedure mpp_update_nest_fine_i8_3d
1390  module procedure mpp_update_nest_fine_i8_4d
1391  module procedure mpp_update_nest_fine_r4_2d
1392  module procedure mpp_update_nest_fine_r4_3d
1393  module procedure mpp_update_nest_fine_r4_4d
1394  module procedure mpp_update_nest_fine_r4_2dv
1395  module procedure mpp_update_nest_fine_r4_3dv
1396  module procedure mpp_update_nest_fine_r4_4dv
1397 #ifdef OVERLOAD_C4
1398  module procedure mpp_update_nest_fine_c4_2d
1399  module procedure mpp_update_nest_fine_c4_3d
1400  module procedure mpp_update_nest_fine_c4_4d
1401 #endif
1402  module procedure mpp_update_nest_fine_i4_2d
1403  module procedure mpp_update_nest_fine_i4_3d
1404  module procedure mpp_update_nest_fine_i4_4d
1405  end interface
1406 
1407  !> @ingroup mpp_domains_mod
1409  module procedure mpp_do_update_nest_fine_r8_3d
1410  module procedure mpp_do_update_nest_fine_r8_3dv
1411 #ifdef OVERLOAD_C8
1412  module procedure mpp_do_update_nest_fine_c8_3d
1413 #endif
1414  module procedure mpp_do_update_nest_fine_i8_3d
1415  module procedure mpp_do_update_nest_fine_r4_3d
1416  module procedure mpp_do_update_nest_fine_r4_3dv
1417 #ifdef OVERLOAD_C4
1418  module procedure mpp_do_update_nest_fine_c4_3d
1419 #endif
1420  module procedure mpp_do_update_nest_fine_i4_3d
1421  end interface
1422 
1423  !> Pass the data from fine grid to fill the buffer to be ready to be interpolated
1424  !! onto coarse grid.
1425  !! <br>Example usage:
1426  !!
1427  !! call mpp_update_nest_coarse(field, nest_domain, field_out, nest_level, complete,
1428  !! position, name, tile_count)
1429  !> @ingroup mpp_domains_mod
1431  module procedure mpp_update_nest_coarse_r8_2d
1432  module procedure mpp_update_nest_coarse_r8_3d
1433  module procedure mpp_update_nest_coarse_r8_4d
1434  module procedure mpp_update_nest_coarse_r8_2dv
1435  module procedure mpp_update_nest_coarse_r8_3dv
1436  module procedure mpp_update_nest_coarse_r8_4dv
1437 #ifdef OVERLOAD_C8
1438  module procedure mpp_update_nest_coarse_c8_2d
1439  module procedure mpp_update_nest_coarse_c8_3d
1440  module procedure mpp_update_nest_coarse_c8_4d
1441 #endif
1442  module procedure mpp_update_nest_coarse_i8_2d
1443  module procedure mpp_update_nest_coarse_i8_3d
1444  module procedure mpp_update_nest_coarse_i8_4d
1445  module procedure mpp_update_nest_coarse_r4_2d
1446  module procedure mpp_update_nest_coarse_r4_3d
1447  module procedure mpp_update_nest_coarse_r4_4d
1448  module procedure mpp_update_nest_coarse_r4_2dv
1449  module procedure mpp_update_nest_coarse_r4_3dv
1450  module procedure mpp_update_nest_coarse_r4_4dv
1451 #ifdef OVERLOAD_C4
1452  module procedure mpp_update_nest_coarse_c4_2d
1453  module procedure mpp_update_nest_coarse_c4_3d
1454  module procedure mpp_update_nest_coarse_c4_4d
1455 #endif
1456  module procedure mpp_update_nest_coarse_i4_2d
1457  module procedure mpp_update_nest_coarse_i4_3d
1458  module procedure mpp_update_nest_coarse_i4_4d
1459  end interface
1460 
1461  !> @brief Used by @ref mpp_update_nest_coarse to perform domain updates
1462  !!
1463  !> @ingroup mpp_domains_mod
1465  module procedure mpp_do_update_nest_coarse_r8_3d
1466  module procedure mpp_do_update_nest_coarse_r8_3dv
1467 #ifdef OVERLOAD_C8
1468  module procedure mpp_do_update_nest_coarse_c8_3d
1469 #endif
1470  module procedure mpp_do_update_nest_coarse_i8_3d
1471  module procedure mpp_do_update_nest_coarse_r4_3d
1472  module procedure mpp_do_update_nest_coarse_r4_3dv
1473 #ifdef OVERLOAD_C4
1474  module procedure mpp_do_update_nest_coarse_c4_3d
1475 #endif
1476  module procedure mpp_do_update_nest_coarse_i4_3d
1477  end interface
1478 
1479  !> Get the index of the data passed from fine grid to coarse grid.
1480  !! <br>Example usage:
1481  !!
1482  !! call mpp_get_F2C_index(nest_domain, is_coarse, ie_coarse, js_coarse, je_coarse,
1483  !! is_fine, ie_fine, js_fine, je_fine, nest_level, position)
1484  !> @ingroup mpp_domains_mod
1486  module procedure mpp_get_f2c_index_fine
1487  module procedure mpp_get_f2c_index_coarse
1488  end interface
1489 
1490  !> Broadcasts domain to every pe. Only useful outside the context of it's own pelist
1491  !!
1492  !> <br>Example usage:
1493  !! call mpp_broadcast_domain(domain)
1494  !! call mpp_broadcast_domain(domain_in, domain_out)
1495  !! call mpp_broadcast_domain(domain, tile_coarse) ! nested domains
1496  !!
1497  !> @ingroup mpp_domains_mod
1499  module procedure mpp_broadcast_domain_1
1500  module procedure mpp_broadcast_domain_2
1501  module procedure mpp_broadcast_domain_ug
1502  module procedure mpp_broadcast_domain_nest_fine
1503  module procedure mpp_broadcast_domain_nest_coarse
1504  end interface
1505 
1506 !--------------------------------------------------------------
1507 ! for adjoint update
1508 !--------------------------------------------------------------
1509  !> Similar to @ref mpp_update_domains , updates adjoint domains
1510  !> @ingroup mpp_domains_mod
1512  module procedure mpp_update_domains_ad_2d_r8_2d
1513  module procedure mpp_update_domains_ad_2d_r8_3d
1514  module procedure mpp_update_domains_ad_2d_r8_4d
1515  module procedure mpp_update_domains_ad_2d_r8_5d
1516  module procedure mpp_update_domains_ad_2d_r8_2dv
1517  module procedure mpp_update_domains_ad_2d_r8_3dv
1518  module procedure mpp_update_domains_ad_2d_r8_4dv
1519  module procedure mpp_update_domains_ad_2d_r8_5dv
1520  module procedure mpp_update_domains_ad_2d_r4_2d
1521  module procedure mpp_update_domains_ad_2d_r4_3d
1522  module procedure mpp_update_domains_ad_2d_r4_4d
1523  module procedure mpp_update_domains_ad_2d_r4_5d
1524  module procedure mpp_update_domains_ad_2d_r4_2dv
1525  module procedure mpp_update_domains_ad_2d_r4_3dv
1526  module procedure mpp_update_domains_ad_2d_r4_4dv
1527  module procedure mpp_update_domains_ad_2d_r4_5dv
1528  end interface
1529 !
1530  !> Private interface used for @ref mpp_update_domains
1531  !> @ingroup mpp_domains_mod
1532  interface mpp_do_update
1533  module procedure mpp_do_update_r8_3d
1534  module procedure mpp_do_update_r8_3dv
1535 #ifdef OVERLOAD_C8
1536  module procedure mpp_do_update_c8_3d
1537 #endif
1538  module procedure mpp_do_update_i8_3d
1539  module procedure mpp_do_update_r4_3d
1540  module procedure mpp_do_update_r4_3dv
1541 #ifdef OVERLOAD_C4
1542  module procedure mpp_do_update_c4_3d
1543 #endif
1544  module procedure mpp_do_update_i4_3d
1545  end interface
1546  !> Private interface to updates data domain of 3D field whose computational domains have been computed
1547  !> @ingroup mpp_domains_mod
1548  interface mpp_do_check
1549  module procedure mpp_do_check_r8_3d
1550  module procedure mpp_do_check_r8_3dv
1551 #ifdef OVERLOAD_C8
1552  module procedure mpp_do_check_c8_3d
1553 #endif
1554  module procedure mpp_do_check_i8_3d
1555  module procedure mpp_do_check_r4_3d
1556  module procedure mpp_do_check_r4_3dv
1557 #ifdef OVERLOAD_C4
1558  module procedure mpp_do_check_c4_3d
1559 #endif
1560  module procedure mpp_do_check_i4_3d
1561  end interface
1562 
1563  !> Passes data from a structured grid to an unstructured grid
1564  !! <br>Example usage:
1565  !!
1566  !! call mpp_pass_SG_to_UG(domain, sg_data, ug_data)
1567  !> @ingroup mpp_domains_mod
1569  module procedure mpp_pass_sg_to_ug_r8_2d
1570  module procedure mpp_pass_sg_to_ug_r8_3d
1571  module procedure mpp_pass_sg_to_ug_r4_2d
1572  module procedure mpp_pass_sg_to_ug_r4_3d
1573  module procedure mpp_pass_sg_to_ug_i4_2d
1574  module procedure mpp_pass_sg_to_ug_i4_3d
1575  module procedure mpp_pass_sg_to_ug_l4_2d
1576  module procedure mpp_pass_sg_to_ug_l4_3d
1577  end interface
1578 
1579  !> Passes a data field from a structured grid to an unstructured grid
1580  !! <br>Example usage:
1581  !!
1582  !! call mpp_pass_SG_to_UG(SG_domain, field_SG, field_UG)
1583  !> @ingroup mpp_domains_mod
1585  module procedure mpp_pass_ug_to_sg_r8_2d
1586  module procedure mpp_pass_ug_to_sg_r8_3d
1587  module procedure mpp_pass_ug_to_sg_r4_2d
1588  module procedure mpp_pass_ug_to_sg_r4_3d
1589  module procedure mpp_pass_ug_to_sg_i4_2d
1590  module procedure mpp_pass_ug_to_sg_i4_3d
1591  module procedure mpp_pass_ug_to_sg_l4_2d
1592  module procedure mpp_pass_ug_to_sg_l4_3d
1593  end interface
1594 
1595  !> Passes a data field from a unstructured grid to an structured grid
1596  !! <br>Example usage:
1597  !!
1598  !! call mpp_pass_UG_to_SG(UG_domain, field_UG, field_SG)
1599  !!
1600  !> @ingroup mpp_domains_mod
1602  module procedure mpp_do_update_ad_r8_3d
1603  module procedure mpp_do_update_ad_r8_3dv
1604  module procedure mpp_do_update_ad_r4_3d
1605  module procedure mpp_do_update_ad_r4_3dv
1606  end interface
1607 
1608 !> Get the boundary data for symmetric domain when the data is at C, E, or N-cell center.<br>
1609 !! @ref mpp_get_boundary is used to get the boundary data for symmetric domain
1610 !! when the data is at C, E, or N-cell center. For cubic grid, the data should always
1611 !! at C-cell center.
1612 !! <br>Example usage:
1613 !!
1614 !! call mpp_get_boundary(domain, field, ebuffer, sbuffer, wbuffer, nbuffer)
1615 !! Get boundary information from domain and field and store in buffers
1616 !> @ingroup mpp_domains_mod
1618  module procedure mpp_get_boundary_r8_2d
1619  module procedure mpp_get_boundary_r8_3d
1620 ! module procedure mpp_get_boundary_r8_4d
1621 ! module procedure mpp_get_boundary_r8_5d
1622  module procedure mpp_get_boundary_r8_2dv
1623  module procedure mpp_get_boundary_r8_3dv
1624 ! module procedure mpp_get_boundary_r8_4dv
1625 ! module procedure mpp_get_boundary_r8_5dv
1626  module procedure mpp_get_boundary_r4_2d
1627  module procedure mpp_get_boundary_r4_3d
1628 ! module procedure mpp_get_boundary_r4_4d
1629 ! module procedure mpp_get_boundary_r4_5d
1630  module procedure mpp_get_boundary_r4_2dv
1631  module procedure mpp_get_boundary_r4_3dv
1632 ! module procedure mpp_get_boundary_r4_4dv
1633 ! module procedure mpp_get_boundary_r4_5dv
1634  end interface
1635 
1636  !> @ingroup mpp_domains_mod
1638  module procedure mpp_get_boundary_ad_r8_2d
1639  module procedure mpp_get_boundary_ad_r8_3d
1640  module procedure mpp_get_boundary_ad_r8_2dv
1641  module procedure mpp_get_boundary_ad_r8_3dv
1642  module procedure mpp_get_boundary_ad_r4_2d
1643  module procedure mpp_get_boundary_ad_r4_3d
1644  module procedure mpp_get_boundary_ad_r4_2dv
1645  module procedure mpp_get_boundary_ad_r4_3dv
1646  end interface
1647 
1648  !> @ingroup mpp_domains_mod
1650  module procedure mpp_do_get_boundary_r8_3d
1651  module procedure mpp_do_get_boundary_r8_3dv
1652  module procedure mpp_do_get_boundary_r4_3d
1653  module procedure mpp_do_get_boundary_r4_3dv
1654  end interface
1655 
1656  !> @ingroup mpp_domains_mod
1658  module procedure mpp_do_get_boundary_ad_r8_3d
1659  module procedure mpp_do_get_boundary_ad_r8_3dv
1660  module procedure mpp_do_get_boundary_ad_r4_3d
1661  module procedure mpp_do_get_boundary_ad_r4_3dv
1662  end interface
1663 
1664 !> Reorganization of distributed global arrays.<br>
1665 !! \e mpp_redistribute is used to reorganize a distributed array.
1666 !! \e MPP_TYPE_can be of type \e integer, \e complex, or \e real;
1667 !! of 4-byte or 8-byte kind; of rank up to 5.
1668 !! <br>Example usage:
1669 !! call mpp_redistribute( domain_in, field_in, domain_out, field_out )
1670 !> @ingroup mpp_domains_mod
1672  module procedure mpp_redistribute_r8_2d
1673  module procedure mpp_redistribute_r8_3d
1674  module procedure mpp_redistribute_r8_4d
1675  module procedure mpp_redistribute_r8_5d
1676 #ifdef OVERLOAD_C8
1677  module procedure mpp_redistribute_c8_2d
1678  module procedure mpp_redistribute_c8_3d
1679  module procedure mpp_redistribute_c8_4d
1680  module procedure mpp_redistribute_c8_5d
1681 #endif
1682  module procedure mpp_redistribute_i8_2d
1683  module procedure mpp_redistribute_i8_3d
1684  module procedure mpp_redistribute_i8_4d
1685  module procedure mpp_redistribute_i8_5d
1686 !!$ module procedure mpp_redistribute_l8_2D
1687 !!$ module procedure mpp_redistribute_l8_3D
1688 !!$ module procedure mpp_redistribute_l8_4D
1689 !!$ module procedure mpp_redistribute_l8_5D
1690  module procedure mpp_redistribute_r4_2d
1691  module procedure mpp_redistribute_r4_3d
1692  module procedure mpp_redistribute_r4_4d
1693  module procedure mpp_redistribute_r4_5d
1694 #ifdef OVERLOAD_C4
1695  module procedure mpp_redistribute_c4_2d
1696  module procedure mpp_redistribute_c4_3d
1697  module procedure mpp_redistribute_c4_4d
1698  module procedure mpp_redistribute_c4_5d
1699 #endif
1700  module procedure mpp_redistribute_i4_2d
1701  module procedure mpp_redistribute_i4_3d
1702  module procedure mpp_redistribute_i4_4d
1703  module procedure mpp_redistribute_i4_5d
1704 !!$ module procedure mpp_redistribute_l4_2D
1705 !!$ module procedure mpp_redistribute_l4_3D
1706 !!$ module procedure mpp_redistribute_l4_4D
1707 !!$ module procedure mpp_redistribute_l4_5D
1708  end interface
1709 
1710  !> @ingroup mpp_domains_mod
1712  module procedure mpp_do_redistribute_r8_3d
1713 #ifdef OVERLOAD_C8
1714  module procedure mpp_do_redistribute_c8_3d
1715 #endif
1716  module procedure mpp_do_redistribute_i8_3d
1717  module procedure mpp_do_redistribute_l8_3d
1718  module procedure mpp_do_redistribute_r4_3d
1719 #ifdef OVERLOAD_C4
1720  module procedure mpp_do_redistribute_c4_3d
1721 #endif
1722  module procedure mpp_do_redistribute_i4_3d
1723  module procedure mpp_do_redistribute_l4_3d
1724  end interface
1725 
1726 !> Parallel checking between two ensembles which run on different set pes at the same time<br>
1727 !! There are two forms for the <TT>mpp_check_field</TT> call. The 2D
1728 !! version is generally to be used and 3D version is built by repeated calls to the
1729 !! 2D version.<br>
1730 !! <br>Example usage:
1731 !! @code{.F90}
1732 !! call mpp_check_field(field_in, pelist1, pelist2, domain, mesg, &
1733 !! w_halo, s_halo, e_halo, n_halo, force_abort )
1734 !! @endcode
1735 !! @param field_in Field to be checked
1736 !! @param domain Domain of current pe
1737 !! @param mesg Message to be printed out
1738 !! @param w_halo Halo size to be checked, default is 0
1739 !! @param s_halo Halo size to be checked, default is 0
1740 !! @param e_halo Halo size to be checked, default is 0
1741 !! @param n_halo Halo size to be checked, default is 0
1742 !! @param force_abort When true, abort program when any difference found. Default is false.
1743 !> @ingroup mpp_domains_mod
1745  module procedure mpp_check_field_2d
1746  module procedure mpp_check_field_3d
1747  end interface
1748 
1749 !***********************************************************************
1750 !
1751 ! public interface from mpp_domains_reduce.h
1752 !
1753 !***********************************************************************
1754 
1755 !> Fill in a global array from domain-decomposed arrays.<br>
1756 !!
1757 !> <TT>mpp_global_field</TT> is used to get an entire
1758 !! domain-decomposed array on each PE. <TT>MPP_TYPE_</TT> can be of type
1759 !! <TT>complex</TT>, <TT>integer</TT>, <TT>logical</TT> or <TT>real</TT>;
1760 !! of 4-byte or 8-byte kind; of rank up to 5.<br>
1761 !!
1762 !! All PEs in a domain decomposition must call
1763 !! <TT>mpp_global_field</TT>, and each will have a complete global field
1764 !! at the end. Please note that a global array of rank 3 or higher could
1765 !! occupy a lot of memory.
1766 !!
1767 !! @param domain 2D domain
1768 !! @param local Data dimensioned on either the compute or data domains of 'domain'
1769 !! @param[out] global output data dimensioned on the corresponding global domain
1770 !! @param flags can be either XONLY or YONLY parameters to specify a globalization on one axis only
1771 !!
1772 !! <br> Example usage:
1773 !! @code{.F90}
1774 !! call mpp_global_field( domain, local, global, flags )
1775 !! @endcode
1776 !> @ingroup mpp_domains_mod
1778 
1779 #ifndef __NVCOMPILER
1780  module procedure mpp_global_field_r8
1781 #ifdef OVERLOAD_C8
1782  module procedure mpp_global_field_c8
1783 #endif
1784  module procedure mpp_global_field_i8
1785  module procedure mpp_global_field_l8
1786  module procedure mpp_global_field_r4
1787 #ifdef OVERLOAD_C4
1788  module procedure mpp_global_field_c4
1789 #endif
1790  module procedure mpp_global_field_i4
1791  module procedure mpp_global_field_l4
1792 !! rank specific interfaces are needed for NVHPC because it does not support deferred-rank arrays
1793 #else
1794  module procedure mpp_global_field_r8_2d
1795  module procedure mpp_global_field_r8_3d
1796  module procedure mpp_global_field_r8_4d
1797  module procedure mpp_global_field_r8_5d
1798 #ifdef OVERLOAD_C8
1799  module procedure mpp_global_field_c8_2d
1800  module procedure mpp_global_field_c8_3d
1801  module procedure mpp_global_field_c8_4d
1802  module procedure mpp_global_field_c8_5d
1803 #endif
1804  module procedure mpp_global_field_i8_2d
1805  module procedure mpp_global_field_i8_3d
1806  module procedure mpp_global_field_i8_4d
1807  module procedure mpp_global_field_i8_5d
1808  module procedure mpp_global_field_l8_2d
1809  module procedure mpp_global_field_l8_3d
1810  module procedure mpp_global_field_l8_4d
1811  module procedure mpp_global_field_l8_5d
1812  module procedure mpp_global_field_r4_2d
1813  module procedure mpp_global_field_r4_3d
1814  module procedure mpp_global_field_r4_4d
1815  module procedure mpp_global_field_r4_5d
1816 #ifdef OVERLOAD_C4
1817  module procedure mpp_global_field_c4_2d
1818  module procedure mpp_global_field_c4_3d
1819  module procedure mpp_global_field_c4_4d
1820  module procedure mpp_global_field_c4_5d
1821 #endif
1822  module procedure mpp_global_field_i4_2d
1823  module procedure mpp_global_field_i4_3d
1824  module procedure mpp_global_field_i4_4d
1825  module procedure mpp_global_field_i4_5d
1826  module procedure mpp_global_field_l4_2d
1827  module procedure mpp_global_field_l4_3d
1828  module procedure mpp_global_field_l4_4d
1829  module procedure mpp_global_field_l4_5d
1830 #endif
1831  end interface
1832 
1833 !> @ingroup mpp_domains_mod
1835  module procedure mpp_global_field2d_r8_2d_ad
1836  module procedure mpp_global_field2d_r8_3d_ad
1837  module procedure mpp_global_field2d_r8_4d_ad
1838  module procedure mpp_global_field2d_r8_5d_ad
1839 #ifdef OVERLOAD_C8
1840  module procedure mpp_global_field2d_c8_2d_ad
1841  module procedure mpp_global_field2d_c8_3d_ad
1842  module procedure mpp_global_field2d_c8_4d_ad
1843  module procedure mpp_global_field2d_c8_5d_ad
1844 #endif
1845  module procedure mpp_global_field2d_i8_2d_ad
1846  module procedure mpp_global_field2d_i8_3d_ad
1847  module procedure mpp_global_field2d_i8_4d_ad
1848  module procedure mpp_global_field2d_i8_5d_ad
1849  module procedure mpp_global_field2d_l8_2d_ad
1850  module procedure mpp_global_field2d_l8_3d_ad
1851  module procedure mpp_global_field2d_l8_4d_ad
1852  module procedure mpp_global_field2d_l8_5d_ad
1853  module procedure mpp_global_field2d_r4_2d_ad
1854  module procedure mpp_global_field2d_r4_3d_ad
1855  module procedure mpp_global_field2d_r4_4d_ad
1856  module procedure mpp_global_field2d_r4_5d_ad
1857 #ifdef OVERLOAD_C4
1858  module procedure mpp_global_field2d_c4_2d_ad
1859  module procedure mpp_global_field2d_c4_3d_ad
1860  module procedure mpp_global_field2d_c4_4d_ad
1861  module procedure mpp_global_field2d_c4_5d_ad
1862 #endif
1863  module procedure mpp_global_field2d_i4_2d_ad
1864  module procedure mpp_global_field2d_i4_3d_ad
1865  module procedure mpp_global_field2d_i4_4d_ad
1866  module procedure mpp_global_field2d_i4_5d_ad
1867  module procedure mpp_global_field2d_l4_2d_ad
1868  module procedure mpp_global_field2d_l4_3d_ad
1869  module procedure mpp_global_field2d_l4_4d_ad
1870  module procedure mpp_global_field2d_l4_5d_ad
1871  end interface
1872 
1873 !> Same functionality as @ref mpp_global_field but for unstructured domains
1874 !> @ingroup mpp_domains_mod
1876  module procedure mpp_global_field2d_ug_r8_2d
1877  module procedure mpp_global_field2d_ug_r8_3d
1878  module procedure mpp_global_field2d_ug_r8_4d
1879  module procedure mpp_global_field2d_ug_r8_5d
1880  module procedure mpp_global_field2d_ug_i8_2d
1881  module procedure mpp_global_field2d_ug_i8_3d
1882  module procedure mpp_global_field2d_ug_i8_4d
1883  module procedure mpp_global_field2d_ug_i8_5d
1884  module procedure mpp_global_field2d_ug_r4_2d
1885  module procedure mpp_global_field2d_ug_r4_3d
1886  module procedure mpp_global_field2d_ug_r4_4d
1887  module procedure mpp_global_field2d_ug_r4_5d
1888  module procedure mpp_global_field2d_ug_i4_2d
1889  module procedure mpp_global_field2d_ug_i4_3d
1890  module procedure mpp_global_field2d_ug_i4_4d
1891  module procedure mpp_global_field2d_ug_i4_5d
1892  end interface
1893 
1894 !> @ingroup mpp_domains_mod
1896  module procedure mpp_do_global_field2d_r8_3d_ad
1897 #ifdef OVERLOAD_C8
1898  module procedure mpp_do_global_field2d_c8_3d_ad
1899 #endif
1900  module procedure mpp_do_global_field2d_i8_3d_ad
1901  module procedure mpp_do_global_field2d_l8_3d_ad
1902  module procedure mpp_do_global_field2d_r4_3d_ad
1903 #ifdef OVERLOAD_C4
1904  module procedure mpp_do_global_field2d_c4_3d_ad
1905 #endif
1906  module procedure mpp_do_global_field2d_i4_3d_ad
1907  module procedure mpp_do_global_field2d_l4_3d_ad
1908  end interface
1909 
1910 !> Global max of domain-decomposed arrays.<br>
1911 !! \e mpp_global_max is used to get the maximum value of a
1912 !! domain-decomposed array on each PE. \e MPP_TYPE_can be of type
1913 !! \e integer or \e real; of 4-byte or 8-byte kind; of rank
1914 !! up to 5. The dimension of \e locus must equal the rank of \e field.<br>
1915 !!<br>
1916 !! All PEs in a domain decomposition must call \e mpp_global_max,
1917 !! and each will have the result upon exit.
1918 !! The function \e mpp_global_min, with an identical syntax. is also available.
1919 !!
1920 !! @param domain 2D domain
1921 !! @param field field data dimensioned on either the compute or data domains of 'domain'
1922 !! @param locus If present, van be used to retrieve the location of the maximum
1923 !!
1924 !! <br>Example usage:
1925 !! mpp_global_max( domain, field, locus )
1926 !> @ingroup mpp_domains_mod
1927  interface mpp_global_max
1928  module procedure mpp_global_max_r8_2d
1929  module procedure mpp_global_max_r8_3d
1930  module procedure mpp_global_max_r8_4d
1931  module procedure mpp_global_max_r8_5d
1932  module procedure mpp_global_max_r4_2d
1933  module procedure mpp_global_max_r4_3d
1934  module procedure mpp_global_max_r4_4d
1935  module procedure mpp_global_max_r4_5d
1936  module procedure mpp_global_max_i8_2d
1937  module procedure mpp_global_max_i8_3d
1938  module procedure mpp_global_max_i8_4d
1939  module procedure mpp_global_max_i8_5d
1940  module procedure mpp_global_max_i4_2d
1941  module procedure mpp_global_max_i4_3d
1942  module procedure mpp_global_max_i4_4d
1943  module procedure mpp_global_max_i4_5d
1944  end interface
1945 
1946 !> Global min of domain-decomposed arrays.<br>
1947 !! \e mpp_global_min is used to get the minimum value of a
1948 !! domain-decomposed array on each PE. \e MPP_TYPE_can be of type
1949 !! \e integer or \e real; of 4-byte or 8-byte kind; of rank
1950 !! up to 5. The dimension of \e locus must equal the rank of \e field.<br>
1951 !!<br>
1952 !! All PEs in a domain decomposition must call \e mpp_global_min,
1953 !! and each will have the result upon exit.
1954 !! The function \e mpp_global_max, with an identical syntax. is also available.
1955 !!
1956 !! @param domain 2D domain
1957 !! @param field field data dimensioned on either the compute or data domains of 'domain'
1958 !! @param locus If present, van be used to retrieve the location of the minimum
1959 !!
1960 !! <br>Example usage:
1961 !! mpp_global_min( domain, field, locus )
1962 !> @ingroup mpp_domains_mod
1963  interface mpp_global_min
1964  module procedure mpp_global_min_r8_2d
1965  module procedure mpp_global_min_r8_3d
1966  module procedure mpp_global_min_r8_4d
1967  module procedure mpp_global_min_r8_5d
1968  module procedure mpp_global_min_r4_2d
1969  module procedure mpp_global_min_r4_3d
1970  module procedure mpp_global_min_r4_4d
1971  module procedure mpp_global_min_r4_5d
1972  module procedure mpp_global_min_i8_2d
1973  module procedure mpp_global_min_i8_3d
1974  module procedure mpp_global_min_i8_4d
1975  module procedure mpp_global_min_i8_5d
1976  module procedure mpp_global_min_i4_2d
1977  module procedure mpp_global_min_i4_3d
1978  module procedure mpp_global_min_i4_4d
1979  module procedure mpp_global_min_i4_5d
1980  end interface
1981 
1982 !> Global sum of domain-decomposed arrays.<br>
1983 !! \e mpp_global_sum is used to get the sum of a domain-decomposed array
1984 !! on each PE. \e MPP_TYPE_ can be of type \e integer, \e complex, or \e real; of 4-byte or
1985 !! 8-byte kind; of rank up to 5.
1986 !!
1987 !! @param domain 2D domain
1988 !! @param field field data dimensioned on either the compute or data domain of 'domain'
1989 !! @param flags If present must have the value BITWISE_EXACT_SUM. This produces a sum that
1990 !! is guaranteed to produce the identical result irrespective of how the domain is decomposed.
1991 !! This method does the sum first along the ranks beyond 2, and then calls mpp_global_field
1992 !! to produce a global 2D array which is then summed. The default method, which is
1993 !! considerably faster, does a local sum followed by mpp_sum across the domain
1994 !! decomposition.
1995 !!
1996 !! <br>Example usage:
1997 !! call mpp_global_sum( domain, field, flags )
1998 !! @note All PEs in a domain decomposition must call \e mpp_global_sum,
1999 !! and each will have the result upon exit.
2000 !> @ingroup mpp_domains_mod
2001  interface mpp_global_sum
2002  module procedure mpp_global_sum_r8_2d
2003  module procedure mpp_global_sum_r8_3d
2004  module procedure mpp_global_sum_r8_4d
2005  module procedure mpp_global_sum_r8_5d
2006 #ifdef OVERLOAD_C8
2007  module procedure mpp_global_sum_c8_2d
2008  module procedure mpp_global_sum_c8_3d
2009  module procedure mpp_global_sum_c8_4d
2010  module procedure mpp_global_sum_c8_5d
2011 #endif
2012  module procedure mpp_global_sum_r4_2d
2013  module procedure mpp_global_sum_r4_3d
2014  module procedure mpp_global_sum_r4_4d
2015  module procedure mpp_global_sum_r4_5d
2016 #ifdef OVERLOAD_C4
2017  module procedure mpp_global_sum_c4_2d
2018  module procedure mpp_global_sum_c4_3d
2019  module procedure mpp_global_sum_c4_4d
2020  module procedure mpp_global_sum_c4_5d
2021 #endif
2022  module procedure mpp_global_sum_i8_2d
2023  module procedure mpp_global_sum_i8_3d
2024  module procedure mpp_global_sum_i8_4d
2025  module procedure mpp_global_sum_i8_5d
2026  module procedure mpp_global_sum_i4_2d
2027  module procedure mpp_global_sum_i4_3d
2028  module procedure mpp_global_sum_i4_4d
2029  module procedure mpp_global_sum_i4_5d
2030  end interface
2031 
2032 !gag
2033 !> @ingroup mpp_domains_mod
2035  module procedure mpp_global_sum_tl_r8_2d
2036  module procedure mpp_global_sum_tl_r8_3d
2037  module procedure mpp_global_sum_tl_r8_4d
2038  module procedure mpp_global_sum_tl_r8_5d
2039 #ifdef OVERLOAD_C8
2040  module procedure mpp_global_sum_tl_c8_2d
2041  module procedure mpp_global_sum_tl_c8_3d
2042  module procedure mpp_global_sum_tl_c8_4d
2043  module procedure mpp_global_sum_tl_c8_5d
2044 #endif
2045  module procedure mpp_global_sum_tl_r4_2d
2046  module procedure mpp_global_sum_tl_r4_3d
2047  module procedure mpp_global_sum_tl_r4_4d
2048  module procedure mpp_global_sum_tl_r4_5d
2049 #ifdef OVERLOAD_C4
2050  module procedure mpp_global_sum_tl_c4_2d
2051  module procedure mpp_global_sum_tl_c4_3d
2052  module procedure mpp_global_sum_tl_c4_4d
2053  module procedure mpp_global_sum_tl_c4_5d
2054 #endif
2055  module procedure mpp_global_sum_tl_i8_2d
2056  module procedure mpp_global_sum_tl_i8_3d
2057  module procedure mpp_global_sum_tl_i8_4d
2058  module procedure mpp_global_sum_tl_i8_5d
2059  module procedure mpp_global_sum_tl_i4_2d
2060  module procedure mpp_global_sum_tl_i4_3d
2061  module procedure mpp_global_sum_tl_i4_4d
2062  module procedure mpp_global_sum_tl_i4_5d
2063  end interface
2064 !gag
2065 
2066 !bnc
2067 !> @ingroup mpp_domains_mod
2069  module procedure mpp_global_sum_ad_r8_2d
2070  module procedure mpp_global_sum_ad_r8_3d
2071  module procedure mpp_global_sum_ad_r8_4d
2072  module procedure mpp_global_sum_ad_r8_5d
2073 #ifdef OVERLOAD_C8
2074  module procedure mpp_global_sum_ad_c8_2d
2075  module procedure mpp_global_sum_ad_c8_3d
2076  module procedure mpp_global_sum_ad_c8_4d
2077  module procedure mpp_global_sum_ad_c8_5d
2078 #endif
2079  module procedure mpp_global_sum_ad_r4_2d
2080  module procedure mpp_global_sum_ad_r4_3d
2081  module procedure mpp_global_sum_ad_r4_4d
2082  module procedure mpp_global_sum_ad_r4_5d
2083 #ifdef OVERLOAD_C4
2084  module procedure mpp_global_sum_ad_c4_2d
2085  module procedure mpp_global_sum_ad_c4_3d
2086  module procedure mpp_global_sum_ad_c4_4d
2087  module procedure mpp_global_sum_ad_c4_5d
2088 #endif
2089  module procedure mpp_global_sum_ad_i8_2d
2090  module procedure mpp_global_sum_ad_i8_3d
2091  module procedure mpp_global_sum_ad_i8_4d
2092  module procedure mpp_global_sum_ad_i8_5d
2093  module procedure mpp_global_sum_ad_i4_2d
2094  module procedure mpp_global_sum_ad_i4_3d
2095  module procedure mpp_global_sum_ad_i4_4d
2096  module procedure mpp_global_sum_ad_i4_5d
2097  end interface
2098 !bnc
2099 
2100 !***********************************************************************
2101 !
2102 ! public interface from mpp_domain_util.h
2103 !
2104 !***********************************************************************
2105  !> @brief Retrieve PE number of a neighboring domain.
2106  !!
2107  !> Given a 1-D or 2-D domain decomposition, this call allows users to retrieve
2108  !! the PE number of an adjacent PE-domain while taking into account that the
2109  !! domain may have holes (masked) and/or have cyclic boundary conditions and/or a
2110  !! folded edge. Which PE-domain will be retrived will depend on "direction":
2111  !! +1 (right) or -1 (left) for a 1-D domain decomposition and either NORTH, SOUTH,
2112  !! EAST, WEST, NORTH_EAST, SOUTH_EAST, SOUTH_WEST, or NORTH_WEST for a 2-D
2113  !! decomposition. If no neighboring domain exists (masked domain), then the
2114  !! returned "pe" value will be set to NULL_PE.<br>
2115  !! <br>Example usage:
2116  !!
2117  !! call mpp_get_neighbor_pe( domain1d, direction=+1 , pe)
2118  !!
2119  !! Set pe to the neighbor pe number that is to the right of the current pe
2120  !!
2121  !! call mpp_get_neighbor_pe( domain2d, direction=NORTH, pe)
2122  !!
2123  !! Get neighbor pe number that's above/north of the current pe
2124  !> @ingroup mpp_domains_mod
2126  module procedure mpp_get_neighbor_pe_1d
2127  module procedure mpp_get_neighbor_pe_2d
2128  end interface
2129 
2130  !> Equality/inequality operators for domaintypes. <br>
2131  !!
2132  !! <br>The module provides public operators to check for
2133  !! equality/inequality of domaintypes, e.g:<br>
2134  !!
2135  !! type(domain1D) :: a, b
2136  !! type(domain2D) :: c, d
2137  !! ...
2138  !! if( a.NE.b )then
2139  !! ...
2140  !! end if
2141  !! if( c==d )then
2142  !! ...
2143  !! end if
2144  !!<br>
2145  !! Domains are considered equal if and only if the start and end
2146  !! indices of each of their component global, data and compute domains are equal.
2147  !> @ingroup mpp_domains_mod
2148  interface operator(.EQ.)
2149  module procedure mpp_domain1d_eq
2150  module procedure mpp_domain2d_eq
2151  module procedure mpp_domainug_eq
2152  end interface
2153 
2154  !> @ingroup mpp_domains_mod
2155  interface operator(.NE.)
2156  module procedure mpp_domain1d_ne
2157  module procedure mpp_domain2d_ne
2158  module procedure mpp_domainug_ne
2159  end interface
2160 
2161  !> These routines retrieve the axis specifications associated with the compute domains.
2162  !! The domain is a derived type with private elements. These routines
2163  !! retrieve the axis specifications associated with the compute domains
2164  !! The 2D version of these is a simple extension of 1D.
2165  !! <br>Example usage:
2166  !!
2167  !! call mpp_get_compute_domain(domain_1D, is, ie)
2168  !! call mpp_get_compute_domain(domain_2D, is, ie, js, je)
2169  !> @ingroup mpp_domains_mod
2171  module procedure mpp_get_compute_domain1d
2172  module procedure mpp_get_compute_domain2d
2173  end interface
2174 
2175  !> Retrieve the entire array of compute domain extents associated with a decomposition.
2176  !!
2177  !> @param domain 2D domain
2178  !> @param[out] xbegin,ybegin x and y domain starting indices
2179  !> @param[out] xsize,ysize x and y domain sizes
2180  !! <br>Example usage:
2181  !!
2182  !! call mpp_get_compute_domains( domain, xbegin, xend, xsize, &
2183  !! ybegin, yend, ysize )
2184  !> @ingroup mpp_domains_mod
2186  module procedure mpp_get_compute_domains1d
2187  module procedure mpp_get_compute_domains2d
2188  end interface
2189 
2190  !> @ingroup mpp_domains_mod
2192  module procedure mpp_get_global_domains1d
2193  module procedure mpp_get_global_domains2d
2194  end interface
2195 
2196  !> These routines retrieve the axis specifications associated with the data domains.
2197  !! The domain is a derived type with private elements. These routines
2198  !! retrieve the axis specifications associated with the data domains.
2199  !! The 2D version of these is a simple extension of 1D.
2200  !! <br>Example usage:
2201  !!
2202  !! call mpp_get_data_domain(domain_1d, isd, ied)
2203  !! call mpp_get_data_domain(domain_2d, isd, ied, jsd, jed)
2204  !> @ingroup mpp_domains_mod
2206  module procedure mpp_get_data_domain1d
2207  module procedure mpp_get_data_domain2d
2208  end interface
2209 
2210  !> These routines retrieve the axis specifications associated with the global domains.
2211  !! The domain is a derived type with private elements. These routines
2212  !! retrieve the axis specifications associated with the global domains.
2213  !! The 2D version of these is a simple extension of 1D.
2214  !! <br>Example usage:
2215  !!
2216  !! call mpp_get_global_domain(domain_1d, isg, ieg)
2217  !! call mpp_get_global_domain(domain_2d, isg, ieg, jsg, jeg)
2218  !> @ingroup mpp_domains_mod
2220  module procedure mpp_get_global_domain1d
2221  module procedure mpp_get_global_domain2d
2222  end interface
2223 
2224  !> These routines retrieve the axis specifications associated with the memory domains.
2225  !! The domain is a derived type with private elements. These routines
2226  !! retrieve the axis specifications associated with the memory domains.
2227  !! The 2D version of these is a simple extension of 1D.
2228  !! <br>Example usage:
2229  !!
2230  !! call mpp_get_memory_domain(domain_1d, ism, iem)
2231  !! call mpp_get_memory_domain(domain_2d, ism, iem, jsm, jem)
2232  !> @ingroup mpp_domains_mod
2234  module procedure mpp_get_memory_domain1d
2235  module procedure mpp_get_memory_domain2d
2236  end interface
2237 
2238  !> @ingroup mpp_domains_mod
2240  module procedure mpp_get_domain_extents1d
2241  module procedure mpp_get_domain_extents2d
2242  end interface
2243 
2244  !> These routines set the axis specifications associated with the compute domains.
2245  !! The domain is a derived type with private elements. These routines
2246  !! set the axis specifications associated with the compute domains
2247  !! The 2D version of these is a simple extension of 1D.
2248  !! <br>Example usage:
2249  !!
2250  !! call mpp_get_data_domain(domain_1d, isd, ied)
2251  !! call mpp_get_data_domain(domain_2d, isd, ied, jsd, jed)
2252  !> @ingroup mpp_domains_mod
2254  module procedure mpp_set_compute_domain1d
2255  module procedure mpp_set_compute_domain2d
2256  end interface
2257 
2258  !> These routines set the axis specifications associated with the data domains.
2259  !! The domain is a derived type with private elements. These routines
2260  !! set the axis specifications associated with the data domains.
2261  !! The 2D version of these is a simple extension of 1D.
2262  !! <br>Example usage:
2263  !!
2264  !! call mpp_set_data_domain(domain_1d, isd, ied)
2265  !! call mpp_set_data_domain(domain_2d, isd, ied, jsd, jed)
2266  !> @ingroup mpp_domains_mod
2268  module procedure mpp_set_data_domain1d
2269  module procedure mpp_set_data_domain2d
2270  end interface
2271 
2272  !> These routines set the axis specifications associated with the global domains.
2273  !! The domain is a derived type with private elements. These routines
2274  !! set the axis specifications associated with the global domains.
2275  !! The 2D version of these is a simple extension of 1D.
2276  !! <br>Example usage:
2277  !!
2278  !! call mpp_set_global_domain(domain_1d, isg, ieg)
2279  !! call mpp_set_global_domain(domain_2d, isg, ieg, jsg, jeg)
2280  !> @ingroup mpp_domains_mod
2282  module procedure mpp_set_global_domain1d
2283  module procedure mpp_set_global_domain2d
2284  end interface
2285 
2286  !> Retrieve list of PEs associated with a domain decomposition.
2287  !! The 1D version of this call returns an array of the PEs assigned to
2288  !! this 1D domain decomposition. In addition the optional argument pos may be
2289  !! used to retrieve the 0-based position of the domain local to the
2290  !! calling PE, i.e., <TT> domain\%list(pos)\%pe</TT> is the local PE,
2291  !! as returned by @ref mpp_pe().
2292  !! The 2D version of this call is identical to 1D version.
2293  !> @ingroup mpp_domains_mod
2294  interface mpp_get_pelist
2295  module procedure mpp_get_pelist1d
2296  module procedure mpp_get_pelist2d
2297  end interface
2298 
2299  !> Retrieve layout associated with a domain decomposition
2300  !! The 1D version of this call returns the number of divisions that was assigned to this
2301  !! decomposition axis. The 2D version of this call returns an array of dimension 2 holding the
2302  !! results on two axes.
2303  !! <br>Example usage:
2304  !!
2305  !! call mpp_get_layout( domain, layout )
2306  !> @ingroup mpp_domains_mod
2307  interface mpp_get_layout
2308  module procedure mpp_get_layout1d
2309  module procedure mpp_get_layout2d
2310  end interface
2311  !> Private interface for internal usage, compares two sizes
2312  !> @ingroup mpp_domains_mod
2314  module procedure check_data_size_1d
2315  module procedure check_data_size_2d
2316  end interface
2317 
2318  !> Nullify domain list. This interface is needed in mpp_domains_test.
2319  !! 1-D case can be added in if needed.
2320  !! <br>Example usage:
2321  !!
2322  !! call mpp_nullify_domain_list(domain)
2323  !> @ingroup mpp_domains_mod
2325  module procedure nullify_domain2d_list
2326  end interface
2327 
2328  !> Private interface to pack an array into a vector
2329  !> @ingroup mpp_domains_mod
2330  interface arr2vec
2331 #ifndef __NVCOMPILER
2332  module procedure arr2vec_r8
2333 #ifdef OVERLOAD_C8
2334  module procedure arr2vec_c8
2335 #endif
2336  module procedure arr2vec_i8
2337  module procedure arr2vec_l8
2338  module procedure arr2vec_r4
2339 #ifdef OVERLOAD_C4
2340  module procedure arr2vec_c4
2341 #endif
2342  module procedure arr2vec_i4
2343  module procedure arr2vec_l4
2344 #else
2345  module procedure arr2vec_r8_2d
2346  module procedure arr2vec_r8_3d
2347  module procedure arr2vec_r8_4d
2348  module procedure arr2vec_r8_5d
2349  module procedure arr2vec_i8_2d
2350  module procedure arr2vec_i8_3d
2351  module procedure arr2vec_i8_4d
2352  module procedure arr2vec_i8_5d
2353  module procedure arr2vec_l8_2d
2354  module procedure arr2vec_l8_3d
2355  module procedure arr2vec_l8_4d
2356  module procedure arr2vec_l8_5d
2357  module procedure arr2vec_r4_2d
2358  module procedure arr2vec_r4_3d
2359  module procedure arr2vec_r4_4d
2360  module procedure arr2vec_r4_5d
2361  module procedure arr2vec_i4_2d
2362  module procedure arr2vec_i4_3d
2363  module procedure arr2vec_i4_4d
2364  module procedure arr2vec_i4_5d
2365  module procedure arr2vec_l4_2d
2366  module procedure arr2vec_l4_3d
2367  module procedure arr2vec_l4_4d
2368  module procedure arr2vec_l4_5d
2369 #endif
2370  end interface
2371 
2372  !> Private interface to unpack a vector into an array
2373  !> @ingroup mpp_domains_mod
2374  interface vec2arr
2375 #ifndef __NVCOMPILER
2376  module procedure vec2arr_r8
2377 #ifdef OVERLOAD_C8
2378  module procedure vec2arr_c8
2379 #endif
2380  module procedure vec2arr_i8
2381  module procedure vec2arr_l8
2382  module procedure vec2arr_r4
2383 #ifdef OVERLOAD_C4
2384  module procedure vec2arr_c4
2385 #endif
2386  module procedure vec2arr_i4
2387  module procedure vec2arr_l4
2388 #else
2389  module procedure vec2arr_r8_2d
2390  module procedure vec2arr_r8_3d
2391  module procedure vec2arr_r8_4d
2392  module procedure vec2arr_r8_5d
2393  module procedure vec2arr_i8_2d
2394  module procedure vec2arr_i8_3d
2395  module procedure vec2arr_i8_4d
2396  module procedure vec2arr_i8_5d
2397  module procedure vec2arr_l8_2d
2398  module procedure vec2arr_l8_3d
2399  module procedure vec2arr_l8_4d
2400  module procedure vec2arr_l8_5d
2401  module procedure vec2arr_r4_2d
2402  module procedure vec2arr_r4_3d
2403  module procedure vec2arr_r4_4d
2404  module procedure vec2arr_r4_5d
2405  module procedure vec2arr_i4_2d
2406  module procedure vec2arr_i4_3d
2407  module procedure vec2arr_i4_4d
2408  module procedure vec2arr_i4_5d
2409  module procedure vec2arr_l4_2d
2410  module procedure vec2arr_l4_3d
2411  module procedure vec2arr_l4_4d
2412  module procedure vec2arr_l4_5d
2413 #endif
2414  end interface
2415 
2416  !> Private interface to initialize an assumed-rank array
2417  !> @ingroup mpp_domains_mod
2418  interface arr_init
2419 #ifndef __NVCOMPILER
2420  module procedure arr_init_r8
2421 #ifdef OVERLOAD_C8
2422  module procedure arr_init_c8
2423 #endif
2424  module procedure arr_init_i8
2425  module procedure arr_init_l8
2426  module procedure arr_init_r4
2427 #ifdef OVERLOAD_C4
2428  module procedure arr_init_c4
2429 #endif
2430  module procedure arr_init_i4
2431  module procedure arr_init_l4
2432 #else
2433  module procedure arr_init_r8_2d
2434  module procedure arr_init_r8_3d
2435  module procedure arr_init_r8_4d
2436  module procedure arr_init_r8_5d
2437  module procedure arr_init_i8_2d
2438  module procedure arr_init_i8_3d
2439  module procedure arr_init_i8_4d
2440  module procedure arr_init_i8_5d
2441  module procedure arr_init_l8_2d
2442  module procedure arr_init_l8_3d
2443  module procedure arr_init_l8_4d
2444  module procedure arr_init_l8_5d
2445  module procedure arr_init_r4_2d
2446  module procedure arr_init_r4_3d
2447  module procedure arr_init_r4_4d
2448  module procedure arr_init_r4_5d
2449  module procedure arr_init_i4_2d
2450  module procedure arr_init_i4_3d
2451  module procedure arr_init_i4_4d
2452  module procedure arr_init_i4_5d
2453  module procedure arr_init_l4_2d
2454  module procedure arr_init_l4_3d
2455  module procedure arr_init_l4_4d
2456  module procedure arr_init_l4_5d
2457 #endif
2458  end interface
2459 
2460  ! Include variable "version" to be written to log file.
2461 #include<file_version.h>
2462  public version
2463 
2464 
2465 contains
2466 
2467 #include <mpp_define_nest_domains.inc>
2468 #include <mpp_domains_util.inc>
2469 #include <mpp_domains_comm.inc>
2470 #include <mpp_domains_define.inc>
2471 #include <mpp_domains_misc.inc>
2472 #include <mpp_pack.inc>
2473 #include <mpp_domains_reduce.inc>
2474 #include <mpp_unstruct_domain.inc>
2475 
2476 end module mpp_domains_mod
subroutine mpp_get_overlap(domain, action, p, is, ie, js, je, dir, rot, position)
Set user stack size.
subroutine mpp_get_neighbor_pe_2d(domain, direction, pe)
Return PE North/South/East/West of this PE-domain. direction must be NORTH, SOUTH,...
subroutine mpp_get_global_domains1d(domain, begin, end, size)
Set user stack size.
integer function mpp_get_domain_npes(domain)
Set user stack size.
subroutine mpp_define_unstruct_domain(UG_domain, SG_domain, npts_tile, grid_nlev, ndivs, npes_io_group, grid_index, name)
integer, save a2_sort_len
length sorted memory list
subroutine mpp_define_nest_domains(nest_domain, domain, num_nest, nest_level, tile_fine, tile_coarse, istart_coarse, icount_coarse, jstart_coarse, jcount_coarse, npes_nest_tile, x_refine, y_refine, extra_halo, name)
Set up a domain to pass data between aligned coarse and fine grid of nested model.
logical function mpp_domainug_ne(a, b)
Overload the .ne. for UG.
subroutine mpp_modify_domain2d(domain_in, domain_out, isc, iec, jsc, jec, isg, ieg, jsg, jeg, whalo, ehalo, shalo, nhalo)
logical function mpp_domain2d_eq(a, b)
Set user stack size.
integer function mpp_get_tile_npes(domain)
Returns number of processors used on current tile.
integer, dimension(-1:max_dom_ids), save ids_idx
index of d_comm associated with sorted addesses
integer nthread_control_loop
Determine the loop order for packing and unpacking. When number of threads is greater than nthread_co...
integer, save i_sort_len
length sorted domain ids list
subroutine mpp_get_global_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, tile_count, position)
Set user stack size.
subroutine mpp_get_pelist1d(domain, pelist, pos)
Set user stack size.
subroutine mpp_set_global_domain1d(domain, begin, end, size)
Set user stack size.
subroutine mpp_get_layout2d(domain, layout)
Set user stack size.
subroutine mpp_get_tile_pelist(domain, pelist)
Get the processors list used on current tile.
logical efp_sum_overflow_check
If .true., always do overflow_check when doing EFP bitwise mpp_global_sum.
subroutine mpp_get_domain_components(domain, x, y, tile_count)
Retrieve 1D components of 2D decomposition.
subroutine mpp_get_domain_extents1d(domain, xextent, yextent)
Set user stack size.
logical function mpp_group_update_is_set(group)
Set user stack size.
subroutine logical mpp_broadcast_domain_1(domain)
broadcast domain (useful only outside the context of its own pelist)
integer function mpp_get_domain_tile_commid(domain)
Set user stack size.
character(len=32) debug_update_domain
namelist interface
subroutine mpp_domains_init(flags)
Initialize domain decomp package.
subroutine mpp_set_global_domain2d(domain, xbegin, xend, ybegin, yend, xsize, ysize, tile_count)
Set user stack size.
logical function mpp_domain1d_eq(a, b)
Set user stack size.
integer function, dimension(size(domain%tile_id(:))) mpp_get_tile_id(domain)
Returns the tile_id on current pe.
logical function mpp_domain_is_symmetry(domain)
Set user stack size.
subroutine mpp_create_super_grid_domain(domain)
Modifies the indices of the input domain to create the supergrid domain.
logical function mpp_mosaic_defined()
Accessor function for value of mosaic_defined.
integer function mpp_get_num_overlap(domain, action, p, position)
Set user stack size.
integer function mpp_get_current_ntile(domain)
Returns number of tile on current pe.
subroutine mpp_define_domains1d(global_indices, ndivs, domain, pelist, flags, halo, extent, maskmap, memory_size, begin_halo, end_halo)
Define data and computational domains on a 1D set of data (isg:ieg) and assign them to PEs.
subroutine mpp_set_domain_symmetry(domain, symmetry)
Set user stack size.
integer function mpp_get_ntile_count(domain)
Returns number of tiles in mosaic.
subroutine mpp_get_domain_extents2d(domain, xextent, yextent)
This will return xextent and yextent for each tile.
logical debug_message_passing
Will check the consistency on the boundary between processor/tile when updating domain for symmetric ...
subroutine mpp_get_global_domain1d(domain, begin, end, size, max_size)
Set user stack size.
integer function, dimension(2) mpp_get_io_domain_layout(domain)
Set user stack size.
subroutine mpp_shift_nest_domains(nest_domain, domain, delta_i_coarse, delta_j_coarse, extra_halo)
Based on mpp_define_nest_domains, but just resets positioning of nest Modifies the parent/coarse star...
subroutine mpp_get_neighbor_pe_1d(domain, direction, pe)
Return PE to the righ/left of this PE-domain.
subroutine mpp_define_mosaic_pelist(sizes, pe_start, pe_end, pelist, costpertile)
Defines a pelist for use with mosaic tiles.
subroutine mpp_get_tile_compute_domains(domain, xbegin, xend, ybegin, yend, position)
Set user stack size.
subroutine mpp_get_compute_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, x_is_global, y_is_global, tile_count, position)
Set user stack size.
subroutine mpp_get_compute_domain1d(domain, begin, end, size, max_size, is_global)
Set user stack size.
subroutine mpp_define_io_domain(domain, io_layout)
Define the layout for IO pe's for the given domain.
subroutine mpp_get_f2c_index_coarse(nest_domain, is_coarse, ie_coarse, js_coarse, je_coarse, nest_level, position)
subroutine mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
Computes extents for a grid decomposition with the given indices and divisions.
integer, dimension(-1:max_fields), save d_comm_idx
index of d_comm associated with sorted addresses
logical function mpp_domain1d_ne(a, b)
Set user stack size.
subroutine mpp_modify_domain1d(domain_in, domain_out, cbegin, cend, gbegin, gend, hbegin, hend)
Modifies the exents of a domain.
subroutine mpp_get_layout1d(domain, layout)
Set user stack size.
subroutine mpp_broadcast_domain_ug(domain)
Broadcast domain (useful only outside the context of its own pelist)
subroutine mpp_get_update_pelist(domain, action, pelist, position)
Set user stack size.
subroutine mpp_set_data_domain2d(domain, xbegin, xend, ybegin, yend, xsize, ysize, x_is_global, y_is_global, tile_count)
Set user stack size.
subroutine mpp_get_compute_domains1d(domain, begin, end, size)
Set user stack size.
integer(i8_kind), parameter addr2_base
= 0x0000000000010000
integer function mpp_get_domain_tile_root_pe(domain)
Set user stack size.
subroutine mpp_check_field_2d(field_in, pelist1, pelist2, domain, mesg, w_halo, s_halo, e_halo, n_halo, force_abort, position)
This routine is used to do parallel checking for 2d data between n and m pe. The comparison is is don...
integer, dimension(-1:max_addrs2), save addrs2_idx
index of addr2 associated with d_comm
subroutine mpp_define_mosaic(global_indices, layout, domain, num_tile, num_contact, tile1, tile2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2, pe_start, pe_end, pelist, whalo, ehalo, shalo, nhalo, xextent, yextent, maskmap, name, memory_size, symmetry, xflags, yflags, tile_id)
Defines a domain for mosaic tile grids.
integer, save n_comm
number of communicators used
subroutine mpp_domains_exit()
Exit mpp_domains_mod. Serves no particular purpose, but is provided should you require to re-initiali...
subroutine mpp_get_pelist2d(domain, pelist, pos)
Set user stack size.
integer, save n_ids
number of domain ids used (=i_sort_len; domain ids are never removed)
integer, save a_sort_len
length sorted memory list
subroutine mpp_get_memory_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, x_is_global, y_is_global, position)
Set user stack size.
subroutine mpp_check_field_3d(field_in, pelist1, pelist2, domain, mesg, w_halo, s_halo, e_halo, n_halo, force_abort, position)
This routine is used to do parallel checking for 3d data between n and m pe. The comparison is is don...
subroutine mpp_define_layout2d(global_indices, ndivs, layout)
type(mpi_comm) function mpp_get_domain_tile_comm(domain)
Set user stack size.
subroutine mpp_set_compute_domain1d(domain, begin, end, size, is_global)
Set user stack size.
integer function mpp_get_domain_pe(domain)
Set user stack size.
subroutine mpp_get_tile_list(domain, tiles)
Return the tile_id on current pelist. one-tile-per-pe is assumed.
subroutine mpp_get_f2c_index_fine(nest_domain, is_coarse, ie_coarse, js_coarse, je_coarse, is_fine, ie_fine, js_fine, je_fine, nest_level, position)
subroutine mpp_compute_block_extent(isg, ieg, ndivs, ibegin, iend)
Computes the extents of a grid block.
logical function mpp_group_update_initialized(group)
Set user stack size.
integer, save dc_sort_len
length sorted comm keys (=num active communicators)
subroutine mpp_set_compute_domain2d(domain, xbegin, xend, ybegin, yend, xsize, ysize, x_is_global, y_is_global, tile_count)
Set user stack size.
type(domain2d) function, pointer mpp_get_io_domain(domain)
Set user stack size.
subroutine mpp_get_compute_domains2d(domain, xbegin, xend, xsize, ybegin, yend, ysize, position)
Set user stack size.
subroutine mpp_copy_domain2d(domain_in, domain_out)
Copies input 2d domain to the output 2d domain.
type(mpi_comm) function mpp_get_domain_comm(domain)
Set user stack size.
integer(i8_kind), dimension(max_fields), save dckey_sorted
list of sorted local addresses
subroutine mpp_get_memory_domain1d(domain, begin, end, size, max_size, is_global)
Set user stack size.
type(domaincommunicator2d), dimension(:), allocatable, target, save d_comm
domain communicators
subroutine mpp_get_domain_shift(domain, ishift, jshift, position)
Returns the shift value in x and y-direction according to domain position..
logical function mpp_domain2d_ne(a, b)
Set user stack size.
logical function mpp_domain_is_initialized(domain)
Set user stack size.
subroutine mpp_broadcast_domain_nest_coarse(domain, tile_coarse)
Broadcast nested domain (useful only outside the context of its own pelist)
subroutine nullify_domain2d_list(domain)
Set user stack size.
integer, dimension(-1:max_addrs), save addrs_idx
index of address associated with d_comm
logical function mpp_domain_is_tile_root_pe(domain)
Returns if current pe is the root pe of the tile, if number of tiles on current pe is greater than 1,...
character(len=name_length) function mpp_get_domain_name(domain)
Set user stack size.
subroutine mpp_get_global_domains2d(domain, xbegin, xend, xsize, ybegin, yend, ysize, position)
Set user stack size.
subroutine mpp_get_c2f_index(nest_domain, is_fine, ie_fine, js_fine, je_fine, is_coarse, ie_coarse, js_coarse, je_coarse, dir, nest_level, position)
Get the index of the data passed from coarse grid to fine grid.
integer function mpp_get_domain_commid(domain)
Set user stack size.
integer, save n_addrs2
number of memory addresses used
subroutine mpp_get_data_domain2d(domain, xbegin, xend, ybegin, yend, xsize, xmax_size, ysize, ymax_size, x_is_global, y_is_global, tile_count, position)
Set user stack size.
subroutine mpp_get_domain_pelist(domain, pelist)
Set user stack size.
integer(i8_kind), dimension(max_addrs2), save addrs2_sorted
list of sorted local addresses
subroutine mpp_domains_set_stack_size(n)
Set user stack size.
subroutine mpp_clear_group_update(group)
Set user stack size.
subroutine mpp_get_update_size(domain, nsend, nrecv, position)
Set user stack size.
integer(i8_kind), dimension(max_addrs), save addrs_sorted
list of sorted local addresses
integer(i8_kind), dimension(max_dom_ids), save ids_sorted
list of sorted domain identifiers
integer function mpp_get_domain_root_pe(domain)
Set user stack size.
logical function mpp_domainug_eq(a, b)
Overload the .eq. for UG.
subroutine mpp_set_data_domain1d(domain, begin, end, size, is_global)
Set user stack size.
recursive subroutine mpp_copy_domain1d(domain_in, domain_out)
Copies input 1d domain to the output 1d domain.
integer, save n_addrs
number of memory addresses used
subroutine mpp_get_data_domain1d(domain, begin, end, size, max_size, is_global)
Set user stack size.
subroutine mpp_define_domains2d(global_indices, layout, domain, pelist, xflags, yflags, xhalo, yhalo, xextent, yextent, maskmap, name, symmetry, memory_size, whalo, ehalo, shalo, nhalo, is_mosaic, tile_count, tile_id, complete, x_cyclic_offset, y_cyclic_offset)
Define 2D data and computational domain on global rectilinear cartesian domain (isg:ieg,...
Private interface to pack an array into a vector.
Private interface to initialize an assumed-rank array.
Private interface for internal usage, compares two sizes.
Broadcasts domain to every pe. Only useful outside the context of it's own pelist.
Parallel checking between two ensembles which run on different set pes at the same time There are tw...
Private interface used for non blocking updates.
Completes a pending non-blocking group update Must follow a call to mpp_start_group_update.
Must be used after a call to mpp_start_update_domains in order to complete a nonblocking domain updat...
Constructor for the mpp_group_update_type which is then used with mpp_start_group_update.
Deallocate given 1D or 2D domain.
Set up a domain decomposition.
Retrieve layout associated with a domain decomposition. Given a global 2D domain and the number of di...
Defines a nullified 1D or 2D domain.
Private interface to updates data domain of 3D field whose computational domains have been computed.
Private interface used for mpp_update_domains.
Passes a data field from a unstructured grid to an structured grid Example usage:
Used by mpp_update_nest_coarse to perform domain updates.
Get the boundary data for symmetric domain when the data is at C, E, or N-cell center....
These routines retrieve the axis specifications associated with the compute domains....
Retrieve the entire array of compute domain extents associated with a decomposition.
These routines retrieve the axis specifications associated with the data domains. The domain is a der...
Get the index of the data passed from fine grid to coarse grid. Example usage:
These routines retrieve the axis specifications associated with the global domains....
Retrieve layout associated with a domain decomposition The 1D version of this call returns the number...
These routines retrieve the axis specifications associated with the memory domains....
Retrieve PE number of a neighboring domain.
Retrieve list of PEs associated with a domain decomposition. The 1D version of this call returns an a...
Fill in a global array from domain-decomposed arrays.
Same functionality as mpp_global_field but for unstructured domains.
Global max of domain-decomposed arrays. mpp_global_max is used to get the maximum value of a domain-...
Global min of domain-decomposed arrays. mpp_global_min is used to get the minimum value of a domain-...
Global sum of domain-decomposed arrays. mpp_global_sum is used to get the sum of a domain-decomposed...
Modifies the extents (compute, data and global) of a given domain.
Nullify domain list. This interface is needed in mpp_domains_test. 1-D case can be added in if needed...
Passes data from a structured grid to an unstructured grid Example usage:
Passes a data field from a structured grid to an unstructured grid Example usage:
Reorganization of distributed global arrays. mpp_redistribute is used to reorganize a distributed ar...
These routines set the axis specifications associated with the compute domains. The domain is a deriv...
These routines set the axis specifications associated with the data domains. The domain is a derived ...
These routines set the axis specifications associated with the global domains. The domain is a derive...
Private interface used for non blocking updates.
Starts non-blocking group update Must be followed up with a call to mpp_complete_group_update mpp_gro...
Interface to start halo updates mpp_start_update_domains is used to start a halo update of a domain-d...
Performs halo updates for a given domain.
Similar to mpp_update_domains , updates adjoint domains.
Pass the data from fine grid to fill the buffer to be ready to be interpolated onto coarse grid....
Pass the data from coarse grid to fill the buffer to be ready to be interpolated onto fine grid....
Private interface to unpack a vector into an array.
Type used to represent the contact between tiles.
One dimensional domain used to manage shared data access between pes.
A private type used to specify index limits for a domain decomposition.
The domain2D type contains all the necessary information to define the global, compute and data domai...
Private type to specify multiple index limits and pe information for a 2D domain.
Used to specify index limits along an axis of a domain.
Used for sending domain data between pe's.
Domain information for managing data on unstructured grids.
index bounds for use in nestSpec
used for updates on a group
domain with nested fine and course tiles
Private type to hold data for each level of nesting.
Used to specify bounds and index information for nested tiles as a linked list.
Used for nonblocking data transfer.
Type for overlapping data.
Private type for overlap specifications.
Upper and lower x and y bounds for a tile.
Private type for axis specification data for an unstructured grid.
Private type for axis specification data for an unstructured domain.
This interface uses a conversion to an integer representation of real numbers to give order-invariant...
Definition: mpp_efp.F90:70
subroutine, public mpp_memuse_end(text, unit)
End the memory collection, and report on total memory used during the execution of the model run.
subroutine, public mpp_memuse_begin
Initialize the memory module, and record the initial memory use.
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function stdout()
This function returns the current standard fortran unit numbers for output.
Definition: mpp_util.inc:42
subroutine mpp_set_current_pelist(pelist, no_sync)
Set context pelist.
Definition: mpp_util.inc:514
integer function stderr()
This function returns the current standard fortran unit numbers for error messages.
Definition: mpp_util.inc:50
subroutine mpp_type_free(dtype)
Deallocates memory for mpp_type objects @TODO This should probably not take a pointer,...
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
Definition: mpp_util.inc:58
integer function mpp_npes()
Returns processor count for current pelist.
Definition: mpp_util.inc:420
integer function mpp_pe()
Returns processor ID.
Definition: mpp_util.inc:406
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
integer function mpp_clock_id(name, flags, grain)
Return an ID for a new or existing clock.
Definition: mpp_util.inc:736
Scatter a vector across all PEs.
Definition: mpp.F90:824
Perform parallel broadcasts.
Definition: mpp.F90:1153
Error handler.
Definition: mpp.F90:385
Reduction operations. Find the max of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:568
Reduction operations. Find the min of scalar a from the PEs in pelist result is also automatically br...
Definition: mpp.F90:590
Receive data from another PE.
Definition: mpp.F90:999
Send data to a receiving PE.
Definition: mpp.F90:1066
Reduction operation.
Definition: mpp.F90:627
Calculates sum of a given numerical array across pe's for adjoint domains.
Definition: mpp.F90:672
Basic message-passing call.
Definition: mpp.F90:934
Create a mpp_type variable.
Definition: mpp.F90:540
Data types for generalized data transfer (e.g. MPI_Type)
Definition: mpp.F90:290
Declare a pelist. The two flavors of this subroutine differ in the type of their comm/commID argument...
Definition: mpp.F90:424
Get the current pelist. The two flavors of this subroutine differ in the type of their comm/commID ar...
Definition: mpp.F90:433