2 !***********************************************************************
3 !* GNU Lesser General Public License
5 !* This file
is part of the GFDL Flexible Modeling System (FMS).
7 !* FMS
is free software: you can redistribute it and/or modify it under
8 !* the terms of the GNU Lesser General Public License as published by
9 !* the Free Software Foundation, either
version 3 of the License, or (at
10 !* your option) any later
version.
12 !* FMS
is distributed in the hope that it
will be useful, but WITHOUT
13 !* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 !* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 !* You should have
received a copy of the GNU Lesser General Public
18 !* License along with FMS. If
not, see <http:
19 !***********************************************************************
20 !
this routine
is used to retrieve scalar boundary data
for symmetric domain.
22 subroutine MPP_GET_BOUNDARY_2D_(
field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &
23 position, complete, tile_count)
24 type(domain2D), intent(in) :: domain
26 MPP_TYPE_, intent(inout), optional :: ebuffer(:), sbuffer(:), wbuffer(:), nbuffer(:)
27 integer, intent(in), optional :: flags, position, tile_count
28 logical, intent(in), optional :: complete
41 integer :: max_ntile,
tile, update_position, ishift, jshift
42 logical :: do_update, is_complete, set_mismatch
47 ntile =
size(domain%x(:))
49 if(present(flags)) then
50 call
mpp_error(FATAL,
"MPP_GET_BOUNDARY_2D_: flags is a dummy optional argument")
52 update_position = CENTER
53 if(present(position)) update_position = position
55 !---
check if the buffer are needed
57 if( domain%symmetry .AND. PRESENT(position) ) then
69 max_ntile = domain%max_ntile_pe
71 if(PRESENT(complete)) then
72 is_complete = complete
76 if(ntile>MAX_TILES) then
77 write(
text,
'(i2)' ) MAX_TILES
78 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D: MAX_TILES='
80 if(.NOT. present(tile_count) ) call
mpp_error(FATAL, "MPP_GET_BOUNDARY_2D: "
81 "optional argument tile_count should be present when number of tiles on this
pe is more than 1")
85 do_update = (
tile == ntile) .AND. is_complete
87 if(list > MAX_DOMAIN_FIELDS)then
88 write(
text,'(i2)' ) MAX_DOMAIN_FIELDS
89 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D: MAX_DOMAIN_FIELDS='
92 if(present(ebuffer)) then
93 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
94 'MPP_GET_BOUNDARY_2D: ebuffer should
not be present when
north is folded')
95 if(.
not. need_ebuffer) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D: ebuffer should
not be present')
96 b_addrs(1, list,
tile) = LOC(ebuffer)
97 buffer_size(1) =
size(ebuffer(:))
99 b_addrs(1, list,
tile) = 0
102 if(present(sbuffer)) then
104 b_addrs(2, list,
tile) = LOC(sbuffer)
105 buffer_size(2) =
size(sbuffer(:))
107 b_addrs(2, list,
tile) = 0
110 if(present(wbuffer)) then
112 b_addrs(3, list,
tile) = LOC(wbuffer)
113 buffer_size(3) =
size(wbuffer(:))
115 b_addrs(3, list,
tile) = 0
118 if(present(nbuffer)) then
119 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
120 'MPP_GET_BOUNDARY_2D: nbuffer should
not be present when
north is folded')
122 b_addrs(4, list,
tile) = LOC(nbuffer)
123 buffer_size(4) =
size(nbuffer(:))
125 b_addrs(4, list,
tile) = 0
129 if(list == 1 .AND.
tile == 1 )then
133 set_mismatch = .
false.
136 set_mismatch = set_mismatch .OR. ANY( bsize .NE. buffer_size )
137 set_mismatch = set_mismatch .OR. (update_position .NE.
pos)
139 write(
text,'(i2)' ) list
140 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D: Incompatible
field at count '
149 !--- only non-
center data in symmetry domain
will be retrieved.
150 if(position == CENTER .OR. (.NOT. domain%symmetry) ) return
151 bound => search_bound_overlap(domain, update_position)
152 call mpp_get_domain_shift(domain, ishift, jshift, update_position)
156 call mpp_do_get_boundary(f_addrs(1:l_size,1:ntile), domain,
bound, b_addrs(:,1:l_size,1:ntile), &
157 bsize,
ksize, d_type)
159 l_size=0; f_addrs=-9999; bsize=0; b_addrs=-9999;
isize=0;
jsize=0;
ksize=0
164 end subroutine MPP_GET_BOUNDARY_2D_
167 !
############################################################################################### 168 subroutine MPP_GET_BOUNDARY_3D_(
field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &
169 position, complete, tile_count)
170 type(domain2D), intent(in) :: domain
172 MPP_TYPE_, intent(inout), optional :: ebuffer(:,:), sbuffer(:,:), wbuffer(:,:), nbuffer(:,:)
173 integer, intent(in), optional :: flags, position, tile_count
174 logical, intent(in), optional :: complete
182 integer :: max_ntile,
tile, update_position, ishift, jshift
183 logical :: do_update, is_complete, set_mismatch
188 ntile =
size(domain%x(:))
190 if(present(flags)) then
191 call
mpp_error(FATAL,
"MPP_GET_BOUNDARY_3D_: flags is a dummy optional argument")
193 update_position = CENTER
194 if(present(position)) update_position = position
196 !---
check if the suitable buffer are present
198 if( domain%symmetry .AND. PRESENT(position) ) then
199 select
case(position)
210 max_ntile = domain%max_ntile_pe
212 if(PRESENT(complete)) then
213 is_complete = complete
217 if(ntile>MAX_TILES) then
218 write(
text,
'(i2)' ) MAX_TILES
219 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D: MAX_TILES='
221 if(.NOT. present(tile_count) ) call
mpp_error(FATAL, "MPP_GET_BOUNDARY_3D: "
222 "optional argument tile_count should be present when number of tiles on this
pe is more than 1")
226 do_update = (
tile == ntile) .AND. is_complete
228 if(list > MAX_DOMAIN_FIELDS)then
229 write(
text,'(i2)' ) MAX_DOMAIN_FIELDS
230 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D: MAX_DOMAIN_FIELDS='
233 if(present(ebuffer)) then
234 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
235 'MPP_GET_BOUNDARY_3D: ebuffer should
not be present when
north is folded')
236 if(.
not. need_ebuffer) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D: ebuffer should
not be present')
237 b_addrs(1, list,
tile) = LOC(ebuffer)
238 buffer_size(1) =
size(ebuffer,1)
240 b_addrs(1, list,
tile) = 0
243 if(present(sbuffer)) then
245 b_addrs(2, list,
tile) = LOC(sbuffer)
246 buffer_size(2) =
size(sbuffer,1)
248 b_addrs(2, list,
tile) = 0
251 if(present(wbuffer)) then
253 b_addrs(3, list,
tile) = LOC(wbuffer)
254 buffer_size(3) =
size(wbuffer,1)
256 b_addrs(3, list,
tile) = 0
259 if(present(nbuffer)) then
260 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
261 'MPP_GET_BOUNDARY_3D: nbuffer should
not be present when
north is folded')
263 b_addrs(4, list,
tile) = LOC(nbuffer)
264 buffer_size(4) =
size(nbuffer,1)
266 b_addrs(4, list,
tile) = 0
271 if(list == 1 .AND.
tile == 1 )then
275 set_mismatch = .
false.
279 set_mismatch = set_mismatch .OR. ANY( bsize .NE. buffer_size )
280 set_mismatch = set_mismatch .OR. (update_position .NE.
pos)
282 write(
text,'(i2)' ) list
283 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D: Incompatible
field at count '
292 !--- only non-
center data in symmetry domain
will be retrieved.
293 if(position == CENTER .OR. (.NOT. domain%symmetry) ) return
294 bound => search_bound_overlap(domain, update_position)
295 call mpp_get_domain_shift(domain, ishift, jshift, update_position)
299 call mpp_do_get_boundary(f_addrs(1:l_size,1:ntile), domain,
bound, b_addrs(:,1:l_size,1:ntile), &
300 bsize,
ksize, d_type)
302 l_size=0; f_addrs=-9999; bsize=0; b_addrs=-9999;
isize=0;
jsize=0;
ksize=0
305 end subroutine MPP_GET_BOUNDARY_3D_
308 !
#################################################################### 310 subroutine MPP_GET_BOUNDARY_2D_V_(fieldx, fieldy, domain, ebufferx, sbufferx, wbufferx, nbufferx, &
311 ebuffery, sbuffery, wbuffery, nbuffery, flags, gridtype, &
312 complete, tile_count)
313 type(domain2D), intent(in) :: domain
314 MPP_TYPE_, intent(in) :: fieldx(:,:), fieldy(:,:)
315 MPP_TYPE_, intent(inout), optional :: ebufferx(:), sbufferx(:), wbufferx(:), nbufferx(:)
316 MPP_TYPE_, intent(inout), optional :: ebuffery(:), sbuffery(:), wbuffery(:), nbuffery(:)
317 integer, intent(in), optional :: flags, gridtype, tile_count
318 logical, intent(in), optional :: complete
321 logical :: need_ebufferx, need_sbufferx, need_wbufferx, need_nbufferx
322 logical :: need_ebuffery, need_sbuffery, need_wbuffery, need_nbuffery
329 integer, save :: offset_type, upflags
330 integer :: bufferx_size(4), buffery_size(4)
332 logical :: do_update, is_complete, set_mismatch
335 type(overlapSpec), pointer :: boundx=>
NULL()
336 type(overlapSpec), pointer :: boundy=>
NULL()
337 integer :: position_x, position_y, ishift, jshift
339 ntile =
size(domain%x(:))
341 if( PRESENT(flags) ) then
345 !---
check if the suitable buffer are present
346 need_ebufferx=.FALSE.; need_sbufferx=.FALSE.
347 need_wbufferx=.FALSE.; need_nbufferx=.FALSE.
348 need_ebuffery=.FALSE.; need_sbuffery=.FALSE.
349 need_wbuffery=.FALSE.; need_nbuffery=.FALSE.
350 if( domain%symmetry .AND. PRESENT(gridtype) ) then
351 select
case(gridtype)
352 case(BGRID_NE, BGRID_SW)
353 need_ebufferx=.true.; need_sbufferx=.true.; need_wbufferx=.true.; need_nbufferx=.true.
354 need_ebuffery=.true.; need_sbuffery=.true.; need_wbuffery=.true.; need_nbuffery=.true.
355 case(CGRID_NE, CGRID_SW)
356 need_ebufferx=.true.; need_wbufferx=.true.; need_sbuffery=.true.; need_nbuffery=.true.
357 case(DGRID_NE, DGRID_SW)
358 need_ebuffery=.true.; need_wbuffery=.true.; need_sbufferx=.true.; need_nbufferx=.true.
363 max_ntile = domain%max_ntile_pe
365 if(PRESENT(complete)) then
366 is_complete = complete
370 if(ntile>MAX_TILES) then
371 write(
text,
'(i2)' ) MAX_TILES
372 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: MAX_TILES='
374 if(.NOT. present(tile_count) ) call
mpp_error(FATAL, "MPP_GET_BOUNDARY_2D_V: "
375 "optional argument tile_count should be present when number of tiles on this
pe is more than 1")
379 do_update = (
tile == ntile) .AND. is_complete
381 if(list > MAX_DOMAIN_FIELDS)then
382 write(
text,'(i2)' ) MAX_DOMAIN_FIELDS
383 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: MAX_DOMAIN_FIELDS='
385 f_addrsx(list,
tile) = LOC(fieldx)
386 f_addrsy(list,
tile) = LOC(fieldy)
388 if(present(ebufferx)) then
389 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
390 'MPP_GET_BOUNDARY_2D_V: ebufferx should
not be present when
north is folded')
391 if(.
not. need_ebufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: ebufferx should
not be present')
392 b_addrsx(1, list,
tile) = LOC(ebufferx)
393 bufferx_size(1) =
size(ebufferx,1)
395 b_addrsx(1, list,
tile) = 0
398 if(present(sbufferx)) then
399 if(.
not. need_sbufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: sbufferx should
not be present')
400 b_addrsx(2, list,
tile) = LOC(sbufferx)
401 bufferx_size(2) =
size(sbufferx,1)
403 b_addrsx(2, list,
tile) = 0
406 if(present(wbufferx)) then
407 if(.
not. need_wbufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: wbufferx should
not be present')
408 b_addrsx(3, list,
tile) = LOC(wbufferx)
409 bufferx_size(3) =
size(wbufferx,1)
411 b_addrsx(3, list,
tile) = 0
414 if(present(nbufferx)) then
415 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
416 'MPP_GET_BOUNDARY_2D_V: nbufferx should
not be present when
north is folded')
417 if(.
not. need_nbufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: nbufferx should
not be present')
418 b_addrsx(4, list,
tile) = LOC(nbufferx)
419 bufferx_size(4) =
size(nbufferx,1)
421 b_addrsx(4, list,
tile) = 0
425 if(present(ebuffery)) then
426 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
427 'MPP_GET_BOUNDARY_2D_V: ebuffery should
not be present when
north is folded')
428 if(.
not. need_ebuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: ebuffery should
not be present')
429 b_addrsy(1, list,
tile) = LOC(ebuffery)
430 buffery_size(1) =
size(ebuffery,1)
432 b_addrsy(1, list,
tile) = 0
435 if(present(sbuffery)) then
436 if(.
not. need_sbuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: sbuffery should
not be present')
437 b_addrsy(2, list,
tile) = LOC(sbuffery)
438 buffery_size(2) =
size(sbuffery,1)
440 b_addrsy(2, list,
tile) = 0
443 if(present(wbuffery)) then
444 if(.
not. need_wbuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: wbuffery should
not be present')
445 b_addrsy(3, list,
tile) = LOC(wbuffery)
446 buffery_size(3) =
size(wbuffery,1)
448 b_addrsy(3, list,
tile) = 0
451 if(present(nbuffery)) then
452 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
453 'MPP_GET_BOUNDARY_2D_V: nbuffery should
not be present when
north is folded')
454 if(.
not. need_nbuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_2D_V: nbuffery should
not be present')
455 b_addrsy(4, list,
tile) = LOC(nbuffery)
456 buffery_size(4) =
size(nbuffery,1)
458 b_addrsy(4, list,
tile) = 0
462 grid_offset_type = AGRID
463 if(present(gridtype)) grid_offset_type = gridtype
464 if(list == 1 .AND.
tile == 1 )then
466 ksize = 1; offset_type = grid_offset_type
467 bsizex = bufferx_size; bsizey = buffery_size; upflags =
update_flags 469 set_mismatch = .
false.
470 set_mismatch = set_mismatch .OR. (
isize(1) .NE.
size(fieldx,1))
471 set_mismatch = set_mismatch .OR. (
jsize(1) .NE.
size(fieldx,2))
472 set_mismatch = set_mismatch .OR. (
isize(2) .NE.
size(fieldy,1))
473 set_mismatch = set_mismatch .OR. (
jsize(2) .NE.
size(fieldy,2))
474 set_mismatch = set_mismatch .OR. ANY( bsizex .NE. bufferx_size )
475 set_mismatch = set_mismatch .OR. ANY( bsizey .NE. buffery_size )
476 set_mismatch = set_mismatch .OR. (offset_type .NE. grid_offset_type)
477 set_mismatch = set_mismatch .OR. (upflags .NE.
update_flags)
479 write(
text,'(i2)' ) list
480 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: Incompatible
field at count '
489 select
case(grid_offset_type)
493 case (BGRID_NE, BGRID_SW)
496 case (CGRID_NE, CGRID_SW)
499 case (DGRID_NE, DGRID_SW)
503 call
mpp_error(FATAL, "mpp_get_boundary.h: invalid value of grid_offset_type")
506 boundx => search_bound_overlap(domain, position_x)
507 boundy => search_bound_overlap(domain, position_y)
509 call mpp_get_domain_shift(domain, ishift, jshift, position_x)
510 if(
size(fieldx,1) .NE. domain%x(1)%memory%
size+ishift .OR.
size(fieldx,2) .NE. domain%y(1)%memory%
size+jshift ) &
511 call
mpp_error(FATAL, "MPP_GET_BOUNDARY_2D_V: fieldx
is not on memory domain")
512 call mpp_get_domain_shift(domain, ishift, jshift, position_y)
513 if(
size(fieldy,1) .NE. domain%x(1)%memory%
size+ishift .OR.
size(fieldy,2) .NE. domain%y(1)%memory%
size+jshift ) &
514 call
mpp_error(FATAL, "MPP_GET_BOUNDARY_2D_V: fieldy
is not on memory domain")
515 if(ASSOCIATED(boundx) ) then
516 call mpp_do_get_boundary(f_addrsx(1:l_size,1:ntile), f_addrsy(1:l_size,1:ntile), domain, boundx, boundy, &
517 b_addrsx(:,1:l_size,1:ntile), b_addrsy(:,1:l_size,1:ntile), bsizex, &
520 l_size=0; f_addrsx=-9999; f_addrsy=-9999; bsizex=0; bsizey=0;
527 end subroutine MPP_GET_BOUNDARY_2D_V_
530 !
############################################################################################### 531 subroutine MPP_GET_BOUNDARY_3D_V_(fieldx, fieldy, domain, ebufferx, sbufferx, wbufferx, nbufferx, &
532 ebuffery, sbuffery, wbuffery, nbuffery, flags, gridtype, &
533 complete, tile_count)
534 type(domain2D), intent(in) :: domain
537 MPP_TYPE_, intent(inout), optional :: ebufferx(:,:), sbufferx(:,:), wbufferx(:,:), nbufferx(:,:)
538 MPP_TYPE_, intent(inout), optional :: ebuffery(:,:), sbuffery(:,:), wbuffery(:,:), nbuffery(:,:)
539 integer, intent(in), optional :: flags, gridtype, tile_count
540 logical, intent(in), optional :: complete
543 logical :: need_ebufferx, need_sbufferx, need_wbufferx, need_nbufferx
544 logical :: need_ebuffery, need_sbuffery, need_wbuffery, need_nbuffery
551 integer, save :: offset_type, upflags
552 integer :: bufferx_size(4), buffery_size(4)
554 logical :: do_update, is_complete, set_mismatch
557 type(overlapSpec), pointer :: boundx=>
NULL()
558 type(overlapSpec), pointer :: boundy=>
NULL()
559 integer :: position_x, position_y, ishift, jshift
561 ntile =
size(domain%x(:))
563 if( PRESENT(flags) ) then
567 !---
check if the suitable buffer are present
568 need_ebufferx=.FALSE.; need_sbufferx=.FALSE.
569 need_wbufferx=.FALSE.; need_nbufferx=.FALSE.
570 need_ebuffery=.FALSE.; need_sbuffery=.FALSE.
571 need_wbuffery=.FALSE.; need_nbuffery=.FALSE.
572 if( domain%symmetry .AND. PRESENT(gridtype) ) then
573 select
case(gridtype)
574 case(BGRID_NE, BGRID_SW)
575 need_ebufferx=.true.; need_sbufferx=.true.; need_wbufferx=.true.; need_nbufferx=.true.
576 need_ebuffery=.true.; need_sbuffery=.true.; need_wbuffery=.true.; need_nbuffery=.true.
577 case(CGRID_NE, CGRID_SW)
578 need_ebufferx=.true.; need_wbufferx=.true.; need_sbuffery=.true.; need_nbuffery=.true.
579 case(DGRID_NE, DGRID_SW)
580 need_ebuffery=.true.; need_wbuffery=.true.; need_sbufferx=.true.; need_nbufferx=.true.
585 max_ntile = domain%max_ntile_pe
587 if(PRESENT(complete)) then
588 is_complete = complete
592 if(ntile>MAX_TILES) then
593 write(
text,
'(i2)' ) MAX_TILES
594 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: MAX_TILES='
596 if(.NOT. present(tile_count) ) call
mpp_error(FATAL, "MPP_GET_BOUNDARY_3D_V: "
597 "optional argument tile_count should be present when number of tiles on this
pe is more than 1")
601 do_update = (
tile == ntile) .AND. is_complete
603 if(list > MAX_DOMAIN_FIELDS)then
604 write(
text,'(i2)' ) MAX_DOMAIN_FIELDS
605 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: MAX_DOMAIN_FIELDS='
607 f_addrsx(list,
tile) = LOC(fieldx)
608 f_addrsy(list,
tile) = LOC(fieldy)
610 if(present(ebufferx)) then
611 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
612 'MPP_GET_BOUNDARY_3D_V: ebufferx should
not be present when
north is folded')
613 if(.
not. need_ebufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: ebufferx should
not be present')
614 b_addrsx(1, list,
tile) = LOC(ebufferx)
615 bufferx_size(1) =
size(ebufferx,1)
617 b_addrsx(1, list,
tile) = 0
620 if(present(sbufferx)) then
621 if(.
not. need_sbufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: sbufferx should
not be present')
622 b_addrsx(2, list,
tile) = LOC(sbufferx)
623 bufferx_size(2) =
size(sbufferx,1)
625 b_addrsx(2, list,
tile) = 0
628 if(present(wbufferx)) then
629 if(.
not. need_wbufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: wbufferx should
not be present')
630 b_addrsx(3, list,
tile) = LOC(wbufferx)
631 bufferx_size(3) =
size(wbufferx,1)
633 b_addrsx(3, list,
tile) = 0
636 if(present(nbufferx)) then
637 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
638 'MPP_GET_BOUNDARY_3D_V: nbufferx should
not be present when
north is folded')
639 if(.
not. need_nbufferx) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: nbufferx should
not be present')
640 b_addrsx(4, list,
tile) = LOC(nbufferx)
641 bufferx_size(4) =
size(nbufferx,1)
643 b_addrsx(4, list,
tile) = 0
647 if(present(ebuffery)) then
648 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
649 'MPP_GET_BOUNDARY_3D_V: ebuffery should
not be present when
north is folded')
650 if(.
not. need_ebuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: ebuffery should
not be present')
651 b_addrsy(1, list,
tile) = LOC(ebuffery)
652 buffery_size(1) =
size(ebuffery,1)
654 b_addrsy(1, list,
tile) = 0
657 if(present(sbuffery)) then
658 if(.
not. need_sbuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: sbuffery should
not be present')
659 b_addrsy(2, list,
tile) = LOC(sbuffery)
660 buffery_size(2) =
size(sbuffery,1)
662 b_addrsy(2, list,
tile) = 0
665 if(present(wbuffery)) then
666 if(.
not. need_wbuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: wbuffery should
not be present')
667 b_addrsy(3, list,
tile) = LOC(wbuffery)
668 buffery_size(3) =
size(wbuffery,1)
670 b_addrsy(3, list,
tile) = 0
673 if(present(nbuffery)) then
674 if(BTEST(domain%fold,NORTH)) call
mpp_error(FATAL, &
675 'MPP_GET_BOUNDARY_3D_V: nbuffery should
not be present when
north is folded')
676 if(.
not. need_nbuffery) call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: nbuffery should
not be present')
677 b_addrsy(4, list,
tile) = LOC(nbuffery)
678 buffery_size(4) =
size(nbuffery,1)
680 b_addrsy(4, list,
tile) = 0
684 grid_offset_type = AGRID
685 if(present(gridtype)) grid_offset_type = gridtype
686 if(list == 1 .AND.
tile == 1 )then
688 ksize =
size(fieldx,3); offset_type = grid_offset_type
689 bsizex = bufferx_size; bsizey = buffery_size; upflags =
update_flags 691 set_mismatch = .
false.
692 set_mismatch = set_mismatch .OR. (
isize(1) .NE.
size(fieldx,1))
693 set_mismatch = set_mismatch .OR. (
jsize(1) .NE.
size(fieldx,2))
694 set_mismatch = set_mismatch .OR. (
ksize .NE.
size(fieldx,3))
695 set_mismatch = set_mismatch .OR. (
isize(2) .NE.
size(fieldy,1))
696 set_mismatch = set_mismatch .OR. (
jsize(2) .NE.
size(fieldy,2))
697 set_mismatch = set_mismatch .OR. (
ksize .NE.
size(fieldy,3))
698 set_mismatch = set_mismatch .OR. ANY( bsizex .NE. bufferx_size )
699 set_mismatch = set_mismatch .OR. ANY( bsizey .NE. buffery_size )
700 set_mismatch = set_mismatch .OR. (offset_type .NE. grid_offset_type)
701 set_mismatch = set_mismatch .OR. (upflags .NE.
update_flags)
703 write(
text,'(i2)' ) list
704 call
mpp_error(FATAL,'MPP_GET_BOUNDARY_3D_V: Incompatible
field at count '
713 select
case(grid_offset_type)
717 case (BGRID_NE, BGRID_SW)
720 case (CGRID_NE, CGRID_SW)
723 case (DGRID_NE, DGRID_SW)
727 call
mpp_error(FATAL, "mpp_get_boundary.h: invalid value of grid_offset_type")
730 boundx => search_bound_overlap(domain, position_x)
731 boundy => search_bound_overlap(domain, position_y)
733 call mpp_get_domain_shift(domain, ishift, jshift, position_x)
734 if(
size(fieldx,1) .NE. domain%x(1)%memory%
size+ishift .OR.
size(fieldx,2) .NE. domain%y(1)%memory%
size+jshift ) &
735 call
mpp_error(FATAL, "MPP_GET_BOUNDARY_3D_V: fieldx
is not on memory domain")
736 call mpp_get_domain_shift(domain, ishift, jshift, position_y)
737 if(
size(fieldy,1) .NE. domain%x(1)%memory%
size+ishift .OR.
size(fieldy,2) .NE. domain%y(1)%memory%
size+jshift ) &
738 call
mpp_error(FATAL, "MPP_GET_BOUNDARY_3D_V: fieldy
is not on memory domain")
739 if(ASSOCIATED(boundx) ) then
740 call mpp_do_get_boundary(f_addrsx(1:l_size,1:ntile), f_addrsy(1:l_size,1:ntile), domain, boundx, boundy, &
741 b_addrsx(:,1:l_size,1:ntile), b_addrsy(:,1:l_size,1:ntile), bsizex, &
744 l_size=0; f_addrsx=-9999; f_addrsy=-9999; bsizex=0; bsizey=0;
748 end subroutine MPP_GET_BOUNDARY_3D_V_
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version will
type(ext_fieldtype), dimension(:), pointer, save, private field
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> set_mismatch integer ::tile update_position nbuffersz l_size integer
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> set_mismatch integer ::tile update_position nbuffersz ksize
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_WRITE_UNLIMITED_AXIS_1D_(unit, field, domain, data, nelems_io) integer, intent(in) ::unit type(fieldtype), intent(inout) ::field type(domain2D), intent(inout) ::domain MPP_TYPE_, intent(inout) ::data(:) integer, intent(in) ::nelems_io(:) ! number of compressed elements from each ! member of the io_domain. It MUST have the ! same order as the io_domain pelist. integer, allocatable ::pelist(:) integer ::i, j, nelems, npes type(domain2d), pointer ::io_domain=> allocatable
subroutine, public copy(self, rhs)
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT end
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************! this routine is used to retrieve scalar boundary data for symmetric domain. subroutine MPP_GET_BOUNDARY_2D_(field, domain, ebuffer, sbuffer, wbuffer, nbuffer, flags, &position, complete, tile_count) type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::field(:,:) MPP_TYPE_, intent(inout), optional ::ebuffer(:), sbuffer(:), wbuffer(:), nbuffer(:) integer, intent(in), optional ::flags, position, tile_count logical, intent(in), optional ::complete MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_, allocatable, dimension(:,:) ::ebuffer2D, sbuffer2D, wbuffer2D, nbuffer2D integer ::xcount, ycount integer ::ntile logical ::need_ebuffer, need_sbuffer, need_wbuffer, need_nbuffer integer(LONG_KIND), dimension(MAX_DOMAIN_FIELDS, MAX_TILES), save ::f_addrs=-9999 integer(LONG_KIND), dimension(4, MAX_DOMAIN_FIELDS, MAX_TILES), save ::b_addrs=-9999 integer, save ::bsize(4)=0, isize=0, jsize=0, ksize=0, pos, list=0, l_size=0, upflags integer ::buffer_size(4) integer ::max_ntile, tile, update_position, ishift, jshift logical ::do_update, is_complete, set_mismatch character(len=3) ::text MPP_TYPE_ ::d_type type(overlapSpec), pointer ::bound=> NULL() ntile
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If not
integer(long), parameter false
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible MPP_TYPE_
l_size ! loop over number of fields ke do je do ie to je n if(.NOT. d_comm%R_do_buf(list)) cycle from_pe
character(len=128) version
l_size ! loop over number of fields ke do je do ie to is
integer, parameter, public center
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_GLOBAL_FIELD_2D_(domain, local, global, flags, position, tile_count, default_data) type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::local(:,:) MPP_TYPE_, intent(out) ::global(:,:) integer, intent(in), optional ::flags integer, intent(in), optional ::position integer, intent(in), optional ::tile_count MPP_TYPE_, intent(in), optional ::default_data MPP_TYPE_ ::local3D(size(local, 1), size(local, 2), 1) MPP_TYPE_ ::global3D(size(global, 1), size(global, 2), 1) pointer(lptr, local3D) pointer(gptr, global3D) lptr=LOC(local) gptr=LOC(global) call mpp_global_field(domain, local3D, global3D, flags, position, tile_count, default_data) end subroutine MPP_GLOBAL_FIELD_2D_ subroutine MPP_GLOBAL_FIELD_3D_(domain, local, global, flags, position, tile_count, default_data)!get a global field from a local field!local field may be on compute OR data domain type(domain2D), intent(in) ::domain MPP_TYPE_, intent(in) ::local(:,:,:) MPP_TYPE_, intent(out) ::global(:,:,:) integer, intent(in), optional ::flags integer, intent(in), optional ::position integer, intent(in), optional ::tile_count MPP_TYPE_, intent(in), optional ::default_data integer ::ishift, jshift integer ::tile integer ::isize, jsize tile=1;if(PRESENT(tile_count)) tile=tile_count call mpp_get_domain_shift(domain, ishift, jshift, position) ! The alltoallw method requires that local and global be contiguous. ! We presume that `local` is contiguous if it matches the data domain;! `global` is presumed to always be contiguous. ! Ideally we would use the F2015 function IS_CONTIGUOUS() to validate ! contiguity, but it is not yet suppored in many compilers. ! Also worth noting that many of the nD-> conversion also assumes so there many be other issues here isize
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call mpp_error(FATAL, 'MPP_TRANSMIT:you cannot transmit to ANY_PE using MPI.') else if(to_pe.NE.NULL_PE) then !no other valid cases except NULL_PE call mpp_error(FATAL
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this case
logical function received(this, seqno)
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> set_mismatch integer ::tile update_flags
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine READ_RECORD_CORE_(unit, field, nwords, data, start, axsiz) integer, intent(in) ::unit type(fieldtype), intent(in) ::field integer, intent(in) ::nwords MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in) ::start(:), axsiz(:) integer(SHORT_KIND) ::i2vals(nwords)!rab used in conjunction with transfer intrinsic to determine size of a variable integer(KIND=1) ::one_byte(8) integer ::word_sz!#ifdef __sgi integer(INT_KIND) ::ivals(nwords) real(FLOAT_KIND) ::rvals(nwords)!#else! integer ::ivals(nwords)! real ::rvals(nwords)!#endif real(DOUBLE_KIND) ::r8vals(nwords) pointer(ptr1, i2vals) pointer(ptr2, ivals) pointer(ptr3, rvals) pointer(ptr4, r8vals) if(mpp_io_stack_size< nwords) call mpp_io_set_stack_size(nwords) call mpp_error(FATAL, 'MPP_READ currently requires use_netCDF option') end subroutine READ_RECORD_CORE_ subroutine READ_RECORD_(unit, field, nwords, data, time_level, domain, position, tile_count, start_in, axsiz_in)!routine that is finally called by all mpp_read routines to perform the read!a non-netCDF record contains:! field ID! a set of 4 coordinates(is:ie, js:je) giving the data subdomain! a timelevel and a timestamp(=NULLTIME if field is static)! 3D real data(stored as 1D)!if you are using direct access I/O, the RECL argument to OPEN must be large enough for the above!in a global direct access file, record position on PE is given by %record.!Treatment of timestamp:! We assume that static fields have been passed without a timestamp.! Here that is converted into a timestamp of NULLTIME.! For non-netCDF fields, field is treated no differently, but is written! with a timestamp of NULLTIME. There is no check in the code to prevent! the user from repeatedly writing a static field. integer, intent(in) ::unit, nwords type(fieldtype), intent(in) ::field MPP_TYPE_, intent(inout) ::data(nwords) integer, intent(in), optional ::time_level type(domain2D), intent(in), optional ::domain integer, intent(in), optional ::position, tile_count integer, intent(in), optional ::start_in(:), axsiz_in(:) integer, dimension(size(field%axes(:))) ::start, axsiz integer ::tlevel !, subdomain(4) integer ::i, error, is, ie, js, je, isg, ieg, jsg, jeg type(domain2d), pointer ::io_domain=> tlevel if(PRESENT(start_in) .AND. PRESENT(axsiz_in)) then if(size(start(! the data domain and compute domain must refer to the subdomain being passed ! In this ! since that attempts to gather all data on PE size(field%axes(:)) axsiz(i)
integer, parameter, public north
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) a
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> dimension(MAX_DOMAIN_FIELDS)
real(kind_real), parameter bound
*f90 *************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************subroutine MPP_UPDATE_NEST_FINE_2D_(field, nest_domain, wbuffer, ebuffer, sbuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::field3D(size(field, 1), size(field, 2), 1) MPP_TYPE_ ::wbuffer3D(size(wbuffer, 1), size(wbuffer, 2), 1) MPP_TYPE_ ::ebuffer3D(size(ebuffer, 1), size(ebuffer, 2), 1) MPP_TYPE_ ::sbuffer3D(size(sbuffer, 1), size(sbuffer, 2), 1) MPP_TYPE_ ::nbuffer3D(size(nbuffer, 1), size(nbuffer, 2), 1) pointer(ptr, field3D) pointer(ptr_w, wbuffer3D) pointer(ptr_e, ebuffer3D) pointer(ptr_s, sbuffer3D) pointer(ptr_n, nbuffer3D) ptr=LOC(field) ptr_w=LOC(wbuffer) ptr_e=LOC(ebuffer) ptr_s=LOC(sbuffer) ptr_n=LOC(nbuffer) call mpp_update_nest_fine(field3D, nest_domain, wbuffer3D, ebuffer3D, sbuffer3D, nbuffer3D, &flags, complete, position, extra_halo, name, tile_count) returnend subroutine MPP_UPDATE_NEST_FINE_2D_subroutine MPP_UPDATE_NEST_FINE_3D_(field, nest_domain, wbuffer, sbuffer, ebuffer, nbuffer, &flags, complete, position, extra_halo, name, tile_count) MPP_TYPE_, intent(in) ::field(:,:,:) type(nest_domain_type), intent(inout) ::nest_domain MPP_TYPE_, intent(inout) ::wbuffer(:,:,:) MPP_TYPE_, intent(inout) ::ebuffer(:,:,:) MPP_TYPE_, intent(inout) ::sbuffer(:,:,:) MPP_TYPE_, intent(inout) ::nbuffer(:,:,:) integer, intent(in), optional ::flags logical, intent(in), optional ::complete integer, intent(in), optional ::position integer, intent(in), optional ::extra_halo character(len= *), intent(in), optional ::name integer, intent(in), optional ::tile_count MPP_TYPE_ ::d_type type(nestSpec), pointer ::update=> set_mismatch integer ::tile update_position nbuffersz jsize
l_size ! loop over number of fields ke do je do ie pos
************************************************************************GNU Lesser General Public License **This file is part of the GFDL Flexible Modeling System(FMS). ! *! *FMS is free software without even the implied warranty of MERCHANTABILITY or *FITNESS FOR A PARTICULAR PURPOSE See the GNU General Public License *for more details **You should have received a copy of the GNU Lesser General Public *License along with FMS If see< http:! ***********************************************************************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! MPP_TRANSMIT !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! subroutine MPP_TRANSMIT_(put_data, put_len, to_pe, get_data, get_len, from_pe, block, tag, recv_request, send_request)!a message-passing routine intended to be reminiscent equally of both MPI and SHMEM!put_data and get_data are contiguous MPP_TYPE_ arrays!at each call, your put_data array is put to to_pe 's get_data! your get_data array is got from from_pe 's put_data!i.e we assume that typically(e.g updating halo regions) each PE performs a put _and_ a get!special PE designations:! NULL_PE:to disable a put or a get(e.g at boundaries)! ANY_PE:if remote PE for the put or get is to be unspecific! ALL_PES:broadcast and collect operations(collect not yet implemented)!ideally we would not pass length, but this f77-style call performs better(arrays passed by address, not descriptor)!further, this permits< length > contiguous words from an array of any rank to be passed(avoiding f90 rank conformance check)!caller is responsible for completion checks(mpp_sync_self) before and after integer, intent(in) ::put_len, to_pe, get_len, from_pe MPP_TYPE_, intent(in) ::put_data(*) MPP_TYPE_, intent(out) ::get_data(*) logical, intent(in), optional ::block integer, intent(in), optional ::tag integer, intent(out), optional ::recv_request, send_request logical ::block_comm integer ::i MPP_TYPE_, allocatable, save ::local_data(:) !local copy used by non-parallel code(no SHMEM or MPI) integer ::comm_tag integer ::rsize if(.NOT.module_is_initialized) call mpp_error(FATAL, 'MPP_TRANSMIT:You must first call mpp_init.') if(to_pe.EQ.NULL_PE .AND. from_pe.EQ.NULL_PE) return block_comm=.true. if(PRESENT(block)) block_comm=block if(debug) then call SYSTEM_CLOCK(tick) write(stdout_unit,'(a, i18, a, i6, a, 2i6, 2i8)')&'T=', tick, ' PE=', pe, ' MPP_TRANSMIT begin:to_pe, from_pe, put_len, get_len=', to_pe, from_pe, put_len, get_len end if comm_tag=DEFAULT_TAG if(present(tag)) comm_tag=tag!do put first and then get if(to_pe.GE.0 .AND. to_pe.LT.npes) then!use non-blocking sends if(debug .and.(current_clock.NE.0)) call SYSTEM_CLOCK(start_tick)!z1l:truly non-blocking send.! if(request(to_pe).NE.MPI_REQUEST_NULL) then !only one message from pe-> to_pe in queue *PE waiting for to_pe ! call error else get_len so only do gets but you cannot have a pure get with MPI call a get means do a wait to ensure put on remote PE is complete error call increase mpp_nml request_multiply call MPP_TRANSMIT get_len end if return end subroutine MPP_TRANSMIT_ ! MPP_BROADCAST ! subroutine but that doesn t allow !broadcast to a subset of PEs This version and mpp_transmit will remain !backward compatible intent(inout) MPP_BROADCAST begin