125 #include <fms_platform.h> 128 error_mesg, close_file, fatal, note, stdlog, &
130 field_size, lowercase,
string, &
134 mpp_sync_self, stdout,
mpp_max, event_recv, &
135 mpp_get_current_pelist, mpp_clock_id,
mpp_min, &
137 mpp_clock_begin, mpp_clock_end, mpp_clock_sync, &
138 comm_tag_1, comm_tag_2, comm_tag_3, comm_tag_4, &
139 comm_tag_5, comm_tag_6, comm_tag_7, comm_tag_8, &
140 comm_tag_9, comm_tag_10
145 yupdate, mpp_get_current_ntile, mpp_get_tile_id, &
146 mpp_get_ntile_count, mpp_get_tile_list, &
149 mpp_get_domain_npes, mpp_get_domain_root_pe, &
151 mpp_get_domain_pelist, mpp_compute_extent, &
152 domainug, mpp_get_ug_compute_domains, &
153 mpp_get_ug_domains_index, mpp_get_ug_domain_grid_index, &
155 use mpp_io_mod,
only: mpp_open, mpp_multi, mpp_single, mpp_overwr
318 integer :: i1, j1, i2, j2
331 real,
dimension(:,:),
pointer :: dx => null()
332 real,
dimension(:,:),
pointer :: dy => null()
333 real,
dimension(:,:),
pointer :: area => null()
334 real,
dimension(:),
pointer :: edge_w => null()
335 real,
dimension(:),
pointer :: edge_e => null()
336 real,
dimension(:),
pointer :: edge_s => null()
337 real,
dimension(:),
pointer :: edge_n => null()
338 real,
dimension(:,:,:),
pointer :: en1 => null()
339 real,
dimension(:,:,:),
pointer :: en2 => null()
340 real,
dimension(:,:,:),
pointer :: vlon => null()
341 real,
dimension(:,:,:),
pointer :: vlat => null()
345 character(len=3) :: id
347 logical :: on_this_pe
349 integer,
pointer,
dimension(:) :: pelist
352 integer,
pointer,
dimension(:) :: tile =>null()
353 integer,
pointer,
dimension(:) :: is =>null(), ie =>null()
354 integer,
pointer,
dimension(:) :: js =>null(), je =>null()
355 integer,
pointer :: is_me =>null(), ie_me =>null()
356 integer,
pointer :: js_me =>null(), je_me =>null()
357 integer :: isd_me, ied_me
358 integer :: jsd_me, jed_me
359 integer :: nxd_me, nyd_me
360 integer :: nxc_me, nyc_me
361 integer,
pointer :: tile_me
362 integer :: im , jm , km
363 real,
pointer,
dimension(:) :: lon =>null(), lat =>null()
364 real,
pointer,
dimension(:,:) :: geolon=>null(), geolat=>null()
365 real,
pointer,
dimension(:,:,:) :: frac_area =>null()
366 real,
pointer,
dimension(:,:) :: area =>null()
367 real,
pointer,
dimension(:,:) :: area_inv =>null()
368 integer :: first, last
369 integer :: first_get, last_get
372 integer :: size_repro
381 integer,
pointer :: ls_me =>null(), le_me =>null()
382 integer,
pointer,
dimension(:) :: ls =>null(), le =>null()
383 integer,
pointer :: gs_me =>null(), ge_me =>null()
384 integer,
pointer,
dimension(:) :: gs =>null(), ge =>null()
385 integer,
pointer,
dimension(:) :: l_index =>null()
400 integer :: i, j, l, k, pos
408 integer :: buffer_pos
409 integer, _allocatable :: i(:) _null
410 integer, _allocatable :: j(:) _null
411 integer, _allocatable ::
g(:) _null
412 integer, _allocatable :: xloc(:) _null
413 integer, _allocatable :: tile(:) _null
414 real, _allocatable :: di(:) _null
415 real, _allocatable :: dj(:) _null
419 integer :: nsend, nrecv
420 integer :: sendsize, recvsize
421 integer,
pointer,
dimension(:) :: unpack_ind=>null()
431 integer :: me, npes, root_pe
432 logical,
pointer,
dimension(:) :: your1my2 =>null()
435 logical,
pointer,
dimension(:) :: your2my1 =>null()
438 integer,
pointer,
dimension(:) :: your2my1_size=>null()
443 type(
grid_type),
pointer,
dimension(:) :: grids =>null()
448 type(
x1_type),
pointer,
dimension(:) :: x1 =>null()
449 type(
x1_type),
pointer,
dimension(:) :: x1_put =>null()
450 type(
x2_type),
pointer,
dimension(:) :: x2 =>null()
451 type(
x2_type),
pointer,
dimension(:) :: x2_get =>null()
453 integer,
pointer,
dimension(:) :: send_count_repro =>null()
454 integer,
pointer,
dimension(:) :: recv_count_repro =>null()
455 integer :: send_count_repro_tot
456 integer :: recv_count_repro_tot
459 integer,
pointer,
dimension(:) :: ind_get1 =>null()
460 integer,
pointer,
dimension(:) :: ind_put1 =>null()
468 #include<file_version.h> 470 real,
parameter ::
eps = 1.0e-10
507 logical function in_box(i, j, is, ie, js, je)
508 integer,
intent(in) :: i, j, is, ie, js, je
510 in_box = (i>=is) .and. (i<=ie) .and. (j>=js) .and. (j<=je)
532 integer,
intent(out) :: remap_method
534 integer :: unit, ierr, io, out_unit
540 #ifdef INTERNAL_FILE_NML 544 if ( file_exist(
'input.nml' ) )
then 545 unit = open_namelist_file( )
547 do while ( ierr /= 0 )
548 read ( unit, nml = xgrid_nml, iostat = io, end = 10 )
552 call close_file ( unit )
557 call write_version_number(
"XGRID_MOD", version)
561 if ( mpp_pe() == mpp_root_pe() )
write (unit,nml=xgrid_nml)
562 call close_file (unit)
571 'xgrid_nml monotonic_exchange must be .false. when interp_method = first_order', fatal)
572 write(out_unit,*)
"NOTE from xgrid_mod: use first_order conservative exchange" 575 write(out_unit,*)
"NOTE from xgrid_mod: use monotonic second_order conservative exchange" 577 write(out_unit,*)
"NOTE from xgrid_mod: use second_order conservative exchange" 582 ' is not a valid namelist option', fatal)
592 id_setup_xmap = mpp_clock_id(
"setup_xmap", flags=mpp_clock_sync)
611 subroutine load_xgrid (xmap, grid, grid_file, grid1_id, grid_id, tile1, tile2, use_higher_order)
612 type(xmap_type),
intent(inout) :: xmap
613 type(grid_type),
intent(inout) :: grid
614 character(len=*),
intent(in) :: grid_file
615 character(len=3),
intent(in) :: grid1_id, grid_id
616 integer,
intent(in) :: tile1, tile2
617 logical,
intent(in) :: use_higher_order
619 integer,
pointer,
dimension(:) :: i1=>null(), j1=>null()
620 integer,
pointer,
dimension(:) :: i2=>null(), j2=>null()
621 real,
pointer,
dimension(:) :: di=>null(), dj=>null()
622 real,
pointer,
dimension(:) :: area =>null()
623 integer,
pointer,
dimension(:) :: i1_tmp=>null(), j1_tmp=>null()
624 integer,
pointer,
dimension(:) :: i2_tmp=>null(), j2_tmp=>null()
625 real,
pointer,
dimension(:) :: di_tmp=>null(), dj_tmp=>null()
626 real,
pointer,
dimension(:) :: area_tmp =>null()
627 integer,
pointer,
dimension(:) :: i1_side1=>null(), j1_side1=>null()
628 integer,
pointer,
dimension(:) :: i2_side1=>null(), j2_side1=>null()
629 real,
pointer,
dimension(:) :: di_side1=>null(), dj_side1=>null()
630 real,
pointer,
dimension(:) :: area_side1 =>null()
632 real,
allocatable,
dimension(:,:) :: tmp
633 real,
allocatable,
dimension(:) :: send_buffer, recv_buffer
634 type(
grid_type),
pointer,
save :: grid1 =>null()
635 integer :: l, ll, ll_repro, p, siz(4), nxgrid, size_prev
636 type(xcell_type),
allocatable :: x_local(:)
637 integer :: size_repro, out_unit
638 logical :: scale_exist = .false.
639 logical :: is_distribute = .false.
640 real,
allocatable,
dimension(:) :: scale
642 integer :: npes, isc, iec, nxgrid_local, pe, nxgrid_local_orig
643 integer :: nxgrid1, nxgrid2, nset1, nset2, ndivs, cur_ind
644 integer :: pos, nsend, nrecv, l1, l2, n, mypos, m
645 integer :: start(4), nread(4)
647 character(len=128) :: attvalue
648 integer,
dimension(0:xmap%npes-1) :: pelist
649 logical,
dimension(0:xmap%npes-1) :: subset_rootpe
650 integer,
dimension(0:xmap%npes-1) :: nsend1, nsend2, nrecv1, nrecv2
651 integer,
dimension(0:xmap%npes-1) :: send_cnt, recv_cnt
652 integer,
dimension(0:xmap%npes-1) :: send_buffer_pos, recv_buffer_pos
653 integer,
dimension(0:xmap%npes-1) :: ibegin, iend, pebegin, peend
654 integer,
dimension(2*xmap%npes) :: ibuf1, ibuf2
655 integer,
dimension(0:xmap%npes-1) :: pos_x, y2m1_size
656 integer,
allocatable,
dimension(:) :: y2m1_pe
657 integer,
pointer,
save :: iarray(:), jarray(:)
658 integer,
allocatable,
save :: pos_s(:)
659 integer,
pointer,
dimension(:) :: iarray2(:)=>null(), jarray2(:)=>null()
661 integer :: nxgrid1_old
664 scale_exist = .false.
665 grid1 => xmap%grids(1)
669 mypos = mpp_pe()-mpp_root_pe()
671 call mpp_get_current_pelist(pelist)
673 if( npes .NE. pelist(npes-1) - pelist(0) + 1 )
then 674 print*,
"npes =", npes,
", pelist(npes-1)=", pelist(npes-1),
", pelist(0)=", pelist(0)
675 call error_mesg(
'xgrid_mod', .NE.
'npes pelist(npes-1) - pelist(0)', fatal)
678 select case(xmap%version)
680 call field_size(grid_file,
'AREA_'//grid1_id//
'x'//grid_id, siz)
682 if(nxgrid .LE. 0)
return 686 if(nxgrid .LE. 0)
return 690 if(nxgrid > npes)
then 693 call mpp_compute_extent( 1, nxgrid, ndivs, ibegin, iend)
694 if(npes == ndivs)
then 695 p = mpp_pe()-mpp_root_pe()
698 subset_rootpe(:) = .true.
701 call mpp_compute_extent(pelist(0), pelist(npes-1), ndivs, pebegin, peend)
703 if(pe == pebegin(n))
then 710 subset_rootpe(:) = .false.
713 if(pelist(n) == pebegin(cur_ind))
then 714 subset_rootpe(n) = .true.
716 if(cur_ind == ndivs)
exit 720 is_distribute = .true.
722 is_distribute = .false.
723 isc = 1; iec = nxgrid
728 if(use_higher_order)
then 732 if(scale_exist) nset2 = nset1 + 1
735 if(iec .GE. isc)
then 736 nxgrid_local = iec - isc + 1
737 allocate(i1_tmp(isc:iec), j1_tmp(isc:iec), i2_tmp(isc:iec), j2_tmp(isc:iec), area_tmp(isc:iec) )
738 if(use_higher_order)
allocate(di_tmp(isc:iec), dj_tmp(isc:iec))
742 select case(xmap%version)
744 start(1) = isc; nread(1) = nxgrid_local
745 allocate(tmp(nxgrid_local,1))
746 call read_data(grid_file,
'I_'//grid1_id//
'_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
748 call read_data(grid_file,
'J_'//grid1_id//
'_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
750 call read_data(grid_file,
'I_'//grid_id//
'_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
752 call read_data(grid_file,
'J_'//grid_id//
'_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
754 call read_data(grid_file,
'AREA_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
756 if(use_higher_order)
then 757 call read_data(grid_file,
'DI_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
759 call read_data(grid_file,
'DJ_'//grid1_id//
'x'//grid_id, tmp, start, nread, no_domain=.true.)
764 nread(1) = 2; start(2) = isc; nread(2) = nxgrid_local
765 allocate(tmp(2, isc:iec))
766 call read_data(grid_file,
"tile1_cell", tmp, start, nread, no_domain=.true.)
767 i1_tmp(isc:iec) = tmp(1, isc:iec)
768 j1_tmp(isc:iec) = tmp(2, isc:iec)
769 call read_data(grid_file,
"tile2_cell", tmp, start, nread, no_domain=.true.)
770 i2_tmp(isc:iec) = tmp(1, isc:iec)
771 j2_tmp(isc:iec) = tmp(2, isc:iec)
772 if(use_higher_order)
then 773 call read_data(grid_file,
"tile1_distance", tmp, start, nread, no_domain=.true.)
774 di_tmp(isc:iec) = tmp(1, isc:iec)
775 dj_tmp(isc:iec) = tmp(2, isc:iec)
778 start(1) = isc; nread(1) = nxgrid_local
780 allocate(tmp(isc:iec,1) )
781 call read_data(grid_file,
"xgrid_area", tmp(:,1:1), start, nread, no_domain=.true.)
784 if( trim(attvalue) ==
'm2' )
then 786 area_tmp = tmp(:,1)/garea
787 else if( trim(attvalue) ==
'none' )
then 790 call error_mesg(
'xgrid_mod',
'In file '//trim(grid_file)//
', xgrid_area units = '// &
791 trim(attvalue)//
' should be "m2" or "none"', fatal)
796 if(grid1_id ==
'LND' .AND. grid_id ==
'OCN')
then 798 allocate(scale(isc:iec))
799 write(out_unit, *)
"NOTE from load_xgrid(xgrid_mod): field 'scale' exist in the file "// &
800 trim(grid_file)//
", this field will be read and the exchange grid cell area will be multiplied by scale" 801 call read_data(grid_file,
"scale", tmp, start, nread, no_domain=.true.)
811 nxgrid_local_orig = nxgrid_local
812 allocate(i1(isc:iec), j1(isc:iec), i2(isc:iec), j2(isc:iec), area(isc:iec) )
813 if(use_higher_order)
allocate(di(isc:iec), dj(isc:iec))
819 if(grid1%tile(p) == tile1)
then 820 if(
in_box_nbr(i1_tmp(l), j1_tmp(l), grid1, p))
then 829 if(grid%tile(p) == tile2)
then 830 if (
in_box_nbr(i2_tmp(l), j2_tmp(l), grid, p))
then 836 area(pos) = area_tmp(l)
837 if(use_higher_order)
then 848 deallocate(i1_tmp, i2_tmp, j1_tmp, j2_tmp, area_tmp)
849 if(use_higher_order)
deallocate( di_tmp, dj_tmp)
851 if(iec .GE. isc)
then 852 nxgrid_local = iec - isc + 1
858 nxgrid_local_orig = 0
863 if(is_distribute)
then 867 nsend1(:) = 0; nrecv1(:) = 0
868 nsend2(:) = 0; nrecv2(:) = 0
869 ibuf1(:)= 0; ibuf2(:)= 0
872 if(nxgrid_local>0)
then 873 allocate( send_buffer(nxgrid_local * (nset1+nset2)) )
876 send_buffer_pos(p) = pos
877 if(grid%tile(p) == tile2)
then 880 nsend2(p) = nsend2(p) + 1
881 send_buffer(pos+1) = i1(l)
882 send_buffer(pos+2) = j1(l)
883 send_buffer(pos+3) = i2(l)
884 send_buffer(pos+4) = j2(l)
885 send_buffer(pos+5) = area(l)
886 if(use_higher_order)
then 887 send_buffer(pos+6) = di(l)
888 send_buffer(pos+7) = dj(l)
890 if(scale_exist) send_buffer(pos+nset2) = scale(l)
895 if(grid1%tile(p) == tile1)
then 898 nsend1(p) = nsend1(p) + 1
899 send_buffer(pos+1) = i1(l)
900 send_buffer(pos+2) = j1(l)
901 send_buffer(pos+3) = i2(l)
902 send_buffer(pos+4) = j2(l)
903 send_buffer(pos+5) = area(l)
904 if(use_higher_order)
then 905 send_buffer(pos+6) = di(l)
906 send_buffer(pos+7) = dj(l)
921 ibuf1(2*p+1) = nsend1(p)
922 ibuf1(2*p+2) = nsend2(p)
927 p = mod(mypos+npes-n, npes)
928 if(.not. subset_rootpe(p)) cycle
929 call mpp_recv( ibuf2(2*p+1), glen=2, from_pe=pelist(p), block=.false., tag=comm_tag_1)
932 if(nxgrid_local_orig>0)
then 934 p = mod(mypos+n, npes)
935 ibuf1(2*p+1) = nsend1(p)
936 ibuf1(2*p+2) = nsend2(p)
937 call mpp_send( ibuf1(2*p+1), plen=2, to_pe=pelist(p), tag=comm_tag_1)
940 call mpp_sync_self(
check=event_recv)
943 nrecv1(p) = ibuf2(2*p+1)
944 nrecv2(p) = ibuf2(2*p+2)
952 recv_buffer_pos(p) = pos
953 pos = pos + nrecv1(p) * nset1 + nrecv2(p) * nset2
957 nxgrid1 = sum(nrecv1)
958 nxgrid2 = sum(nrecv2)
959 if(nxgrid1>0 .OR. nxgrid2>0)
allocate(recv_buffer(nxgrid1*nset1+nxgrid2*nset2))
963 send_cnt(:) = nset1 * nsend1(:) + nset2 * nsend2(:)
964 recv_cnt(:) = nset1 * nrecv1(:) + nset2 * nrecv2(:)
966 call mpp_alltoall(send_buffer, send_cnt, send_buffer_pos, &
967 recv_buffer, recv_cnt, recv_buffer_pos)
970 p = mod(mypos+npes-n, npes)
971 nrecv = nrecv1(p)*nset1+nrecv2(p)*nset2
973 pos = recv_buffer_pos(p)
974 call mpp_recv(recv_buffer(pos+1), glen=nrecv, from_pe=pelist(p), &
975 block=.false., tag=comm_tag_2)
979 p = mod(mypos+n, npes)
980 nsend = nsend1(p)*nset1 + nsend2(p)*nset2
982 pos = send_buffer_pos(p)
983 call mpp_send(send_buffer(pos+1), plen=nsend, to_pe=pelist(p), &
986 call mpp_sync_self(
check=event_recv)
990 if( nxgrid_local>0)
then 991 deallocate(i1,j1,i2,j2,area)
994 allocate(i1(nxgrid2), j1(nxgrid2))
995 allocate(i2(nxgrid2), j2(nxgrid2))
996 allocate(area(nxgrid2))
997 allocate(i1_side1(nxgrid1), j1_side1(nxgrid1))
998 allocate(i2_side1(nxgrid1), j2_side1(nxgrid1))
999 allocate(area_side1(nxgrid1))
1000 if(use_higher_order)
then 1001 if(nxgrid_local>0)
deallocate(di,dj)
1002 allocate(di(nxgrid2), dj(nxgrid2))
1003 allocate(di_side1(nxgrid1), dj_side1(nxgrid1))
1005 if(scale_exist)
then 1006 if(nxgrid_local>0)
deallocate(scale)
1007 allocate(scale(nxgrid2))
1014 i1(l2) = recv_buffer(pos+1)
1015 j1(l2) = recv_buffer(pos+2)
1016 i2(l2) = recv_buffer(pos+3)
1017 j2(l2) = recv_buffer(pos+4)
1018 area(l2) = recv_buffer(pos+5)
1019 if(use_higher_order)
then 1020 di(l2) = recv_buffer(pos+6)
1021 dj(l2) = recv_buffer(pos+7)
1023 if(scale_exist)scale(l2) = recv_buffer(pos+nset2)
1028 i1_side1(l1) = recv_buffer(pos+1)
1029 j1_side1(l1) = recv_buffer(pos+2)
1030 i2_side1(l1) = recv_buffer(pos+3)
1031 j2_side1(l1) = recv_buffer(pos+4)
1032 area_side1(l1) = recv_buffer(pos+5)
1033 if(use_higher_order)
then 1034 di_side1(l1) = recv_buffer(pos+6)
1035 dj_side1(l1) = recv_buffer(pos+7)
1040 call mpp_sync_self()
1041 if(
allocated(send_buffer))
deallocate(send_buffer)
1042 if(
allocated(recv_buffer))
deallocate(recv_buffer)
1047 i1_side1 => i1; j1_side1 => j1
1048 i2_side1 => i2; j2_side1 => j2
1050 if(use_higher_order)
then 1059 size_prev = grid%size
1061 if(grid%tile_me == tile2)
then 1063 if (
in_box_me(i2(l), j2(l), grid) )
then 1064 grid%size = grid%size + 1
1066 if( grid1_id .NE.
"ATM" .OR. tile1 .NE.
tile_parent .OR. &
1069 lll = grid%l_index((j2(l)-1)*grid%im+i2(l))
1070 grid%area(lll,1) = grid%area(lll,1)+area(l)
1072 grid%area(i2(l),j2(l)) = grid%area(i2(l),j2(l))+area(l)
1076 if(grid1%tile(p) == tile1)
then 1078 xmap%your1my2(p) = .true.
1086 if(grid%size > size_prev)
then 1087 if(size_prev > 0)
then 1088 allocate(x_local(size_prev))
1090 if(
ASSOCIATED(grid%x))
deallocate(grid%x)
1091 allocate( grid%x( grid%size ) )
1092 grid%x(1:size_prev) = x_local
1095 allocate( grid%x( grid%size ) )
1096 grid%x%di = 0.0; grid%x%dj = 0.0
1101 if( grid%tile_me == tile2 )
then 1106 grid%x(ll)%i1 = i1(l); grid%x(ll)%i2 = i2(l)
1107 grid%x(ll)%j1 = j1(l); grid%x(ll)%j2 = j2(l)
1109 grid%x(ll)%l2 = grid%l_index((j2(l)-1)*grid%im + i2(l))
1114 grid%x(ll)%tile = tile1
1115 grid%x(ll)%area = area(l)
1116 if(scale_exist)
then 1117 grid%x(ll)%scale = scale(l)
1119 grid%x(ll)%scale = 1.0
1121 if(use_higher_order)
then 1122 grid%x(ll)%di = di(l)
1123 grid%x(ll)%dj = dj(l)
1128 if(grid1%tile(p) == tile1)
then 1130 grid%x(ll)%pe = p + xmap%root_pe
1139 if(grid%id == xmap%grids(
size(xmap%grids(:)))%id)
then 1146 if(grid1%tile_me == tile1)
then 1147 if(
associated(iarray))
then 1148 nxgrid1_old =
size(iarray(:))
1153 allocate(y2m1_pe(nxgrid1))
1154 if(.not. last_grid )
allocate(pos_s(0:xmap%npes-1))
1156 if(nxgrid1_old > 0)
then 1158 y2m1_size(p) = xmap%your2my1_size(p)
1165 if (
in_box_me(i1_side1(l), j1_side1(l), grid1) )
then 1166 if(grid1%is_ug)
then 1167 lll = grid1%l_index((j1_side1(l)-1)*grid1%im+i1_side1(l))
1168 grid1%area(lll,1) = grid1%area(lll,1) + area_side1(l)
1170 grid1%area(i1_side1(l),j1_side1(l)) = grid1%area(i1_side1(l),j1_side1(l))+area_side1(l)
1173 if (grid%tile(p) == tile2)
then 1174 if (
in_box_nbr(i2_side1(l), j2_side1(l), grid, p))
then 1175 xmap%your2my1(p) = .true.
1177 y2m1_size(p) = y2m1_size(p) + 1
1181 size_repro = size_repro + 1
1186 pos_x(p) = pos_x(p-1) + y2m1_size(p-1)
1189 if(.not. last_grid) pos_s(:) = pos_x(:)
1191 if(nxgrid1_old > 0)
then 1192 y2m1_size(:) = xmap%your2my1_size(:)
1195 allocate(iarray(nxgrid1+nxgrid1_old), jarray(nxgrid1+nxgrid1_old))
1198 do n = 1, xmap%your2my1_size(p)
1199 iarray(pos_x(p)+n) = iarray2(pos_s(p)+n)
1200 jarray(pos_x(p)+n) = jarray2(pos_s(p)+n)
1203 deallocate(iarray2, jarray2)
1205 allocate(iarray(nxgrid1), jarray(nxgrid1))
1215 if(y2m1_size(p) > 0)
then 1216 pos = pos_x(p)+y2m1_size(p)
1217 if( i1_side1(l) == iarray(pos) .AND. j1_side1(l) == jarray(pos) )
then 1221 do n = 1, y2m1_size(p)
1223 if(i1_side1(l) == iarray(pos) .AND. j1_side1(l) == jarray(pos))
then 1231 y2m1_size(p) = y2m1_size(p)+1
1232 pos = pos_x(p)+y2m1_size(p)
1233 iarray(pos) = i1_side1(l)
1234 jarray(pos) = j1_side1(l)
1237 xmap%your2my1_size(:) = y2m1_size(:)
1240 deallocate(iarray, jarray)
1241 if(
allocated(pos_s))
deallocate(pos_s)
1245 if (grid1%tile_me == tile1 .and. size_repro > 0)
then 1246 ll_repro = grid%size_repro
1247 grid%size_repro = ll_repro + size_repro
1248 if(ll_repro > 0)
then 1249 allocate(x_local(ll_repro))
1250 x_local = grid%x_repro
1251 if(
ASSOCIATED(grid%x_repro))
deallocate(grid%x_repro)
1252 allocate( grid%x_repro(grid%size_repro ) )
1253 grid%x_repro(1:ll_repro) = x_local
1256 allocate( grid%x_repro( grid%size_repro ) )
1257 grid%x_repro%di = 0.0; grid%x_repro%dj = 0.0
1260 if (
in_box_me(i1_side1(l),j1_side1(l), grid1) )
then 1261 ll_repro = ll_repro + 1
1262 grid%x_repro(ll_repro)%i1 = i1_side1(l); grid%x_repro(ll_repro)%i2 = i2_side1(l)
1263 grid%x_repro(ll_repro)%j1 = j1_side1(l); grid%x_repro(ll_repro)%j2 = j2_side1(l)
1264 if(grid1%is_ug)
then 1265 grid%x_repro(ll_repro)%l1 = grid1%l_index((j1_side1(l)-1)*grid1%im+i1_side1(l))
1270 grid%x_repro(ll_repro)%tile = tile1
1271 grid%x_repro(ll_repro)%area = area_side1(l)
1272 if(use_higher_order)
then 1273 grid%x_repro(ll_repro)%di = di_side1(l)
1274 grid%x_repro(ll_repro)%dj = dj_side1(l)
1278 if(grid%tile(p) == tile2)
then 1279 if (
in_box_nbr(i2_side1(l), j2_side1(l), grid, p))
then 1280 grid%x_repro(ll_repro)%pe = p + xmap%root_pe
1288 deallocate(i1, j1, i2, j2, area)
1289 if(use_higher_order)
deallocate(di, dj)
1290 if(scale_exist)
deallocate(scale)
1291 if(is_distribute)
then 1292 deallocate(i1_side1, j1_side1, i2_side1, j2_side1, area_side1)
1293 if(use_higher_order)
deallocate(di_side1, dj_side1)
1296 i1=>null(); j1=>null(); i2=>null(); j2=>null()
1311 subroutine get_grid(grid, grid_id, grid_file, grid_version)
1312 type(grid_type),
intent(inout) :: grid
1313 character(len=3),
intent(in) :: grid_id
1314 character(len=*),
intent(in) :: grid_file
1315 integer,
intent(in) :: grid_version
1317 real,
dimension(grid%im) :: lonb
1318 real,
dimension(grid%jm) :: latb
1319 real,
allocatable :: tmpx(:,:), tmpy(:,:)
1321 integer :: is, ie, js, je, nlon, nlat, siz(4), i, j
1322 integer :: start(4), nread(4), isc2, iec2, jsc2, jec2
1328 select case(grid_version)
1330 allocate(grid%lon(grid%im), grid%lat(grid%jm))
1331 if(grid_id ==
'ATM')
then 1343 else if(grid_id ==
'LND')
then 1354 else if(grid_id ==
'OCN' )
then 1361 if(grid_id ==
'LND' .or. grid_id ==
'ATM')
then 1362 grid%lon = lonb * d2r
1363 grid%lat = latb * d2r
1365 grid%is_latlon = .true.
1367 call field_size(grid_file,
'area', siz)
1368 nlon = siz(1); nlat = siz(2)
1369 if( mod(nlon,2) .NE. 0)
call error_mesg(
'xgrid_mod', &
1370 'flux_exchange_mod: atmos supergrid longitude size can not be divided by 2', fatal)
1371 if( mod(nlat,2) .NE. 0)
call error_mesg(
'xgrid_mod', &
1372 'flux_exchange_mod: atmos supergrid latitude size can not be divided by 2', fatal)
1375 if(nlon .NE. grid%im .OR. nlat .NE. grid%jm)
call error_mesg(
'xgrid_mod', &
1376 'grid size in tile_file does not match the global grid size', fatal)
1378 if( grid_id ==
'LND' .or. grid_id ==
'ATM' .or. grid_id ==
'WAV' )
then 1379 isc2 = 2*grid%is_me-1; iec2 = 2*grid%ie_me+1
1380 jsc2 = 2*grid%js_me-1; jec2 = 2*grid%je_me+1
1381 allocate(tmpx(isc2:iec2, jsc2:jec2) )
1382 allocate(tmpy(isc2:iec2, jsc2:jec2) )
1383 start = 1; nread = 1
1384 start(1) = isc2; nread(1) = iec2 - isc2 + 1
1385 start(2) = jsc2; nread(2) = jec2 - jsc2 + 1
1386 call read_data(grid_file,
'x', tmpx, start, nread, no_domain=.true.)
1387 call read_data(grid_file,
'y', tmpy, start, nread, no_domain=.true.)
1389 deallocate(tmpx, tmpy)
1390 start = 1; nread = 1
1391 start(2) = 2; nread(1) = nlon*2+1
1392 allocate(tmpx(nlon*2+1, 1), tmpy(1, nlat*2+1))
1393 call read_data(grid_file,
"x", tmpx, start, nread, no_domain=.true.)
1394 allocate(grid%lon(grid%im), grid%lat(grid%jm))
1396 grid%lon(i) = tmpx(2*i,1) * d2r
1398 start = 1; nread = 1
1399 start(1) = 2; nread(2) = nlat*2+1
1400 call read_data(grid_file,
"y", tmpy, start, nread, no_domain=.true.)
1402 grid%lat(j) = tmpy(1, 2*j) * d2r
1404 grid%is_latlon = .true.
1406 allocate(grid%geolon(grid%isd_me:grid%ied_me, grid%jsd_me:grid%jed_me))
1407 allocate(grid%geolat(grid%isd_me:grid%ied_me, grid%jsd_me:grid%jed_me))
1411 do j = grid%js_me,grid%je_me
1412 do i = grid%is_me,grid%ie_me
1413 grid%geolon(i, j) = tmpx(i*2,j*2)*d2r
1414 grid%geolat(i, j) = tmpy(i*2,j*2)*d2r
1419 grid%is_latlon = .false.
1421 deallocate(tmpx, tmpy)
1432 character(len=*),
intent(in) :: file
1433 character(len=*),
intent(in) :: name
1434 type(domain2d),
intent(in) :: domain
1435 real,
intent(out) :: data(:,:)
1438 call read_data(file, name,
data, domain)
1440 call error_mesg(
'xgrid_mod',
'no field named '//trim(name)//
' in grid file '//trim(file)// &
1441 ' Will set data to negative values...', note)
1469 type(
domain2d),
intent(in) :: domain
1470 character(len=*),
intent(in) :: grid_file
1471 integer :: is, ie, js, je
1479 if(ie < is .or. je < js )
return 1513 subroutine setup_xmap(xmap, grid_ids, grid_domains, grid_file, atm_grid, lnd_ug_domain)
1515 character(len=3),
dimension(:),
intent(in ) :: grid_ids
1516 type(
domain2d),
dimension(:),
intent(in ) :: grid_domains
1517 character(len=*),
intent(in ) :: grid_file
1519 type(
domainug),
optional,
intent(in ) :: lnd_ug_domain
1521 integer ::
g, p, send_size, recv_size, i, siz(4)
1522 integer :: unit, nxgrid_file, i1, i2, i3, tile1, tile2, j
1523 integer :: nxc, nyc, out_unit
1524 type(
grid_type),
pointer,
save :: grid =>null(), grid1 =>null()
1525 real,
dimension(3) :: xxx
1526 real,
dimension(:,:),
allocatable :: check_data
1527 real,
dimension(:,:,:),
allocatable :: check_data_3d
1528 real,
allocatable :: tmp_2d(:,:), tmp_3d(:,:,:)
1529 character(len=256) :: xgrid_file, xgrid_name
1530 character(len=256) :: tile_file, mosaic_file
1531 character(len=256) :: mosaic1, mosaic2, contact
1532 character(len=256) :: tile1_name, tile2_name
1533 character(len=256),
allocatable :: tile1_list(:), tile2_list(:)
1534 integer :: npes, npes2
1535 integer,
allocatable :: pelist(:)
1537 logical :: use_higher_order = .false.
1538 integer :: lnd_ug_id, l
1539 integer,
allocatable :: grid_index(:)
1543 if(
interp_method .ne.
'first_order') use_higher_order = .true.
1547 xmap%npes = mpp_npes()
1548 xmap%root_pe = mpp_root_pe()
1550 allocate( xmap%grids(1:
size(grid_ids(:))) )
1552 allocate ( xmap%your1my2(0:xmap%npes-1), xmap%your2my1(0:xmap%npes-1) )
1553 allocate ( xmap%your2my1_size(0:xmap%npes-1) )
1555 xmap%your1my2 = .false.; xmap%your2my1 = .false.;
1556 xmap%your2my1_size = 0
1561 else if(
field_exist(grid_file,
"ocn_mosaic_file" ) )
then 1564 call error_mesg(
'xgrid_mod',
'both AREA_ATMxOCN and ocn_mosaic_file does not exist in '//trim(grid_file), fatal)
1568 call error_mesg(
'xgrid_mod',
'reading exchange grid information from grid spec file', note)
1570 call error_mesg(
'xgrid_mod',
'reading exchange grid information from mosaic grid file', note)
1575 if(
present(lnd_ug_domain))
then 1576 do g=1,
size(grid_ids(:))
1577 if(grid_ids(
g) ==
'LND') lnd_ug_id =
g 1582 do g=1,
size(grid_ids(:))
1583 grid => xmap%grids(
g)
1584 if (
g==1) grid1 => xmap%grids(
g)
1585 grid%id = grid_ids(
g)
1586 grid%domain = grid_domains(
g)
1587 grid%on_this_pe = mpp_domain_is_initialized(grid_domains(
g))
1588 allocate ( grid%is(0:xmap%npes-1), grid%ie(0:xmap%npes-1) )
1589 allocate ( grid%js(0:xmap%npes-1), grid%je(0:xmap%npes-1) )
1590 allocate ( grid%tile(0:xmap%npes-1) )
1600 select case(xmap%version)
1604 call read_data(grid_file, lowercase(grid_ids(
g))//
'_mosaic_file', mosaic_file)
1608 if(
g == 1 .AND. grid_ids(1) ==
'ATM' )
then 1609 if( .NOT. grid%on_this_pe )
call error_mesg(
'xgrid_mod',
'ATM domain is not defined on some processor' ,fatal)
1611 grid%npes = mpp_get_domain_npes(grid%domain)
1612 if( xmap%npes > grid%npes .AND.
g == 1 .AND. grid_ids(1) ==
'ATM' )
then 1614 else if(xmap%npes > grid%npes)
then 1616 grid%npes = mpp_get_domain_npes(grid%domain)
1620 allocate(grid%pelist(0:npes-1))
1621 call mpp_get_domain_pelist(grid%domain, grid%pelist)
1622 grid%root_pe = mpp_get_domain_root_pe(grid%domain)
1624 call mpp_get_data_domain(grid%domain, grid%isd_me, grid%ied_me, grid%jsd_me, grid%jed_me, &
1625 xsize=grid%nxd_me, ysize=grid%nyd_me)
1628 if( grid%root_pe == xmap%root_pe )
then 1630 ybegin=grid%js(0:npes-1), yend=grid%je(0:npes-1) )
1631 call mpp_get_tile_list(grid%domain, grid%tile(0:npes-1))
1632 if( xmap%npes > npes .AND.
g == 1 .AND. grid_ids(1) ==
'ATM' )
then 1634 ybegin=grid%js(npes:xmap%npes-1), yend=grid%je(npes:xmap%npes-1) )
1635 call mpp_get_tile_list(domain2, grid%tile(npes:xmap%npes-1))
1638 npes2 = xmap%npes-npes
1640 ybegin=grid%js(0:npes2-1), yend=grid%je(0:npes2-1) )
1641 call mpp_get_compute_domains(grid%domain, xbegin=grid%is(npes2:xmap%npes-1), xend=grid%ie(npes2:xmap%npes-1), &
1642 ybegin=grid%js(npes2:xmap%npes-1), yend=grid%je(npes2:xmap%npes-1) )
1643 call mpp_get_tile_list(domain2, grid%tile(0:npes2-1))
1644 call mpp_get_tile_list(grid%domain, grid%tile(npes2:xmap%npes-1))
1646 if( xmap%npes > grid%npes .AND.
g == 1 .AND. grid_ids(1) ==
'ATM' )
then 1650 if(
g == 1 .AND. grid_ids(1) ==
'ATM' ) npes = xmap%npes
1652 if(grid%tile(p) > grid%ntile .or. grid%tile(p) < 1)
call error_mesg(
'xgrid_mod', &
1653 'tile id should between 1 and ntile', fatal)
1661 grid%is_me => grid%is(xmap%me-xmap%root_pe); grid%ie_me => grid%ie(xmap%me-xmap%root_pe)
1662 grid%js_me => grid%js(xmap%me-xmap%root_pe); grid%je_me => grid%je(xmap%me-xmap%root_pe)
1663 grid%nxc_me = grid%ie_me - grid%is_me + 1
1664 grid%nyc_me = grid%je_me - grid%js_me + 1
1665 grid%tile_me => grid%tile(xmap%me-xmap%root_pe)
1668 grid%is_ug = .false.
1670 if(
g == lnd_ug_id )
then 1672 'does not support unstructured grid for VERSION1 grid' ,fatal)
1674 grid%ug_domain = lnd_ug_domain
1675 allocate ( grid%ls(0:xmap%npes-1), grid%le(0:xmap%npes-1) )
1676 allocate ( grid%gs(0:xmap%npes-1), grid%ge(0:xmap%npes-1) )
1681 if(xmap%npes > grid%npes)
then 1684 call mpp_get_ug_compute_domains(grid%ug_domain, begin=grid%ls(0:npes-1), end=grid%le(0:npes-1) )
1685 call mpp_get_ug_domains_index(grid%ug_domain, grid%gs(0:npes-1), grid%ge(0:npes-1) )
1686 call mpp_get_ug_domain_tile_list(grid%ug_domain, grid%tile(0:npes-1))
1687 grid%ls_me => grid%ls(xmap%me-xmap%root_pe); grid%le_me => grid%le(xmap%me-xmap%root_pe)
1688 grid%gs_me => grid%gs(xmap%me-xmap%root_pe); grid%ge_me => grid%ge(xmap%me-xmap%root_pe)
1689 grid%tile_me => grid%tile(xmap%me-xmap%root_pe)
1690 grid%nxl_me = grid%le_me - grid%ls_me + 1
1691 allocate(grid%l_index(grid%gs_me:grid%ge_me))
1692 allocate(grid_index(grid%ls_me:grid%le_me))
1693 call mpp_get_ug_domain_grid_index(grid%ug_domain, grid_index)
1696 do l = grid%ls_me,grid%le_me
1697 grid%l_index(grid_index(l)) = l
1700 if( grid%on_this_pe )
then 1701 allocate( grid%area (grid%ls_me:grid%le_me,1) )
1702 allocate( grid%area_inv(grid%ls_me:grid%le_me,1) )
1707 else if( grid%on_this_pe )
then 1708 allocate( grid%area (grid%is_me:grid%ie_me, grid%js_me:grid%je_me) )
1709 allocate( grid%area_inv(grid%is_me:grid%ie_me, grid%js_me:grid%je_me) )
1716 if(.not. grid%is_ug)
then 1717 select case(xmap%version)
1719 if( grid%npes .NE. xmap%npes )
then 1720 call error_mesg(
'xgrid_mod', .NE.
' grid%npes xmap%npes ', fatal)
1722 call get_grid(grid, grid_ids(
g), grid_file, xmap%version)
1724 allocate(pelist(0:xmap%npes-1))
1725 call mpp_get_current_pelist(pelist)
1726 if( grid%on_this_pe )
then 1727 call mpp_set_current_pelist(grid%pelist)
1728 call get_mosaic_tile_grid(tile_file,
'INPUT/'//trim(mosaic_file), grid%domain)
1729 call get_grid(grid, grid_ids(
g), tile_file, xmap%version)
1731 call mpp_set_current_pelist(pelist)
1734 if(
g == 1 .AND. grid_ids(1) ==
'ATM' )
then 1740 if( use_higher_order .AND. grid%id ==
'ATM')
then 1741 if(
nnest > 0 )
call error_mesg(
'xgrid_mod',
'second_order is not supported for nested coupler', fatal)
1742 if( grid%is_latlon )
then 1743 call mpp_modify_domain(grid%domain, grid%domain_with_halo, whalo=1, ehalo=1, shalo=1, nhalo=1)
1744 call mpp_get_data_domain(grid%domain_with_halo, grid%isd_me, grid%ied_me, grid%jsd_me, grid%jed_me, &
1745 xsize=grid%nxd_me, ysize=grid%nyd_me)
1747 if(.NOT.
present(atm_grid))
call error_mesg(
'xgrid_mod', &
1748 'when first grid is "ATM", atm_grid should be present', fatal)
1749 if(grid%is_me-grid%isd_me .NE. 1 .or. grid%ied_me-grid%ie_me .NE. 1 .or. &
1750 grid%js_me-grid%jsd_me .NE. 1 .or. grid%jed_me-grid%je_me .NE. 1 )
call error_mesg( &
1751 'xgrid_mod',
'for non-latlon grid (cubic grid), the halo size should be 1 in all four direction', fatal)
1752 if(.NOT.(
ASSOCIATED(atm_grid%dx) .AND.
ASSOCIATED(atm_grid%dy) .AND.
ASSOCIATED(atm_grid%edge_w) .AND. &
1753 ASSOCIATED(atm_grid%edge_e) .AND.
ASSOCIATED(atm_grid%edge_s) .AND.
ASSOCIATED(atm_grid%edge_n) .AND. &
1754 ASSOCIATED(atm_grid%en1) .AND.
ASSOCIATED(atm_grid%en2) .AND.
ASSOCIATED(atm_grid%vlon) .AND. &
1755 ASSOCIATED(atm_grid%vlat) ) )
call error_mesg(
'xgrid_mod', &
1756 'for non-latlon grid (cubic grid), all the fields in atm_grid data type should be allocated', fatal)
1757 nxc = grid%ie_me - grid%is_me + 1
1758 nyc = grid%je_me - grid%js_me + 1
1759 if(
size(atm_grid%dx,1) .NE. nxc .OR.
size(atm_grid%dx,2) .NE. nyc+1) &
1760 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%dx', fatal)
1761 if(
size(atm_grid%dy,1) .NE. nxc+1 .OR.
size(atm_grid%dy,2) .NE. nyc) &
1762 call error_mesg(
'xgrid_mod',
'incorrect dimension sizeof atm_grid%dy', fatal)
1763 if(
size(atm_grid%area,1) .NE. nxc .OR.
size(atm_grid%area,2) .NE. nyc) &
1764 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%area', fatal)
1765 if(
size(atm_grid%edge_w(:)) .NE. nyc+1 .OR.
size(atm_grid%edge_e(:)) .NE. nyc+1) &
1766 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%edge_w/edge_e', fatal)
1767 if(
size(atm_grid%edge_s(:)) .NE. nxc+1 .OR.
size(atm_grid%edge_n(:)) .NE. nxc+1) &
1768 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%edge_s/edge_n', fatal)
1769 if(
size(atm_grid%en1,1) .NE. 3 .OR.
size(atm_grid%en1,2) .NE. nxc .OR.
size(atm_grid%en1,3) .NE. nyc+1) &
1770 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%en1', fatal)
1771 if(
size(atm_grid%en2,1) .NE. 3 .OR.
size(atm_grid%en2,2) .NE. nxc+1 .OR.
size(atm_grid%en2,3) .NE. nyc) &
1772 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%en2', fatal)
1773 if(
size(atm_grid%vlon,1) .NE. 3 .OR.
size(atm_grid%vlon,2) .NE. nxc .OR.
size(atm_grid%vlon,3) .NE. nyc) &
1774 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%vlon', fatal)
1775 if(
size(atm_grid%vlat,1) .NE. 3 .OR.
size(atm_grid%vlat,2) .NE. nxc .OR.
size(atm_grid%vlat,3) .NE. nyc) &
1776 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%vlat', fatal)
1777 allocate(grid%box%dx (grid%is_me:grid%ie_me, grid%js_me:grid%je_me+1 ))
1778 allocate(grid%box%dy (grid%is_me:grid%ie_me+1, grid%js_me:grid%je_me ))
1779 allocate(grid%box%area (grid%is_me:grid%ie_me, grid%js_me:grid%je_me ))
1780 allocate(grid%box%edge_w(grid%js_me:grid%je_me+1))
1781 allocate(grid%box%edge_e(grid%js_me:grid%je_me+1))
1782 allocate(grid%box%edge_s(grid%is_me:grid%ie_me+1))
1783 allocate(grid%box%edge_n(grid%is_me:grid%ie_me+1))
1784 allocate(grid%box%en1 (3, grid%is_me:grid%ie_me, grid%js_me:grid%je_me+1 ))
1785 allocate(grid%box%en2 (3, grid%is_me:grid%ie_me+1, grid%js_me:grid%je_me ))
1786 allocate(grid%box%vlon (3, grid%is_me:grid%ie_me, grid%js_me:grid%je_me ))
1787 allocate(grid%box%vlat (3, grid%is_me:grid%ie_me, grid%js_me:grid%je_me ))
1788 grid%box%dx = atm_grid%dx
1789 grid%box%dy = atm_grid%dy
1790 grid%box%area = atm_grid%area
1791 grid%box%edge_w = atm_grid%edge_w
1792 grid%box%edge_e = atm_grid%edge_e
1793 grid%box%edge_s = atm_grid%edge_s
1794 grid%box%edge_n = atm_grid%edge_n
1795 grid%box%en1 = atm_grid%en1
1796 grid%box%en2 = atm_grid%en2
1797 grid%box%vlon = atm_grid%vlon
1798 grid%box%vlat = atm_grid%vlat
1804 if(grid%on_this_pe)
then 1806 allocate( grid%frac_area(grid%ls_me:grid%le_me, 1, grid%km) )
1808 allocate( grid%frac_area(grid%is_me:grid%ie_me, grid%js_me:grid%je_me, grid%km) )
1810 grid%frac_area = 1.0
1814 select case(xmap%version)
1816 call load_xgrid (xmap, grid, grid_file, grid_ids(1), grid_ids(
g), 1, 1, use_higher_order)
1818 select case(grid_ids(1))
1826 call error_mesg(
'xgrid_mod',
'grid_ids(1) should be ATM, LND or WAV', fatal)
1828 select case(grid_ids(
g))
1830 xgrid_name = trim(xgrid_name)//
'Xl_file' 1832 xgrid_name = trim(xgrid_name)//
'Xo_file' 1834 xgrid_name = trim(xgrid_name)//
'Xw_file' 1836 call error_mesg(
'xgrid_mod',
'grid_ids(g) should be LND, OCN or WAV', fatal)
1839 call read_data(grid_file, lowercase(grid_ids(1))//
'_mosaic_file', mosaic1)
1840 call read_data(grid_file, lowercase(grid_ids(
g))//
'_mosaic_file', mosaic2)
1841 mosaic1 =
'INPUT/'//trim(mosaic1)
1842 mosaic2 =
'INPUT/'//trim(mosaic2)
1843 allocate(tile1_list(grid1%ntile), tile2_list(grid%ntile) )
1844 do j = 1, grid1%ntile
1845 call read_data(mosaic1,
'gridtiles', tile1_list(j), level=j)
1847 do j = 1, grid%ntile
1848 call read_data(mosaic2,
'gridtiles', tile2_list(j), level=j)
1851 call field_size(grid_file, xgrid_name, siz)
1852 nxgrid_file = siz(2)
1854 do i = 1, nxgrid_file
1855 call read_data(grid_file, xgrid_name, xgrid_file, level = i)
1856 xgrid_file =
'INPUT/'//trim(xgrid_file)
1857 if( .NOT. file_exist(xgrid_file) )
call error_mesg(
'xgrid_mod', &
1858 'file '//trim(xgrid_file)//
' does not exist, check your xgrid file.', fatal)
1861 call read_data(xgrid_file,
"contact", contact)
1862 i1 = index(contact,
":")
1863 i2 = index(contact,
"::")
1864 i3 = index(contact,
":", back=.true. )
1865 if(i1 == 0 .OR. i2 == 0)
call error_mesg(
'xgrid_mod', &
1866 'field contact in file '//trim(xgrid_file)//
' should contains ":" and "::" ', fatal)
1868 'field contact in file '//trim(xgrid_file)//
' should contains two ":"', fatal)
1869 tile1_name = contact(i1+1:i2-1)
1870 tile2_name = contact(i3+1:len_trim(contact))
1871 tile1 = 0; tile2 = 0
1872 do j = 1, grid1%ntile
1873 if( tile1_name == tile1_list(j) )
then 1878 do j = 1, grid%ntile
1879 if( tile2_name == tile2_list(j) )
then 1884 if(tile1 == 0)
call error_mesg(
'xgrid_mod', &
1885 trim(tile1_name)//
' is not a tile of mosaic '//trim(mosaic1), fatal)
1886 if(tile2 == 0)
call error_mesg(
'xgrid_mod', &
1887 trim(tile2_name)//
' is not a tile of mosaic '//trim(mosaic2), fatal)
1889 call load_xgrid (xmap, grid, xgrid_file, grid_ids(1), grid_ids(
g), tile1, tile2, &
1893 deallocate(tile1_list, tile2_list)
1895 if(grid%on_this_pe)
then 1896 grid%area_inv = 0.0;
1897 where (grid%area>0.0) grid%area_inv = 1.0/grid%area
1904 grid1%area_inv = 0.0;
1905 where (grid1%area>0.0)
1906 grid1%area_inv = 1.0/grid1%area
1909 xmap%your1my2(xmap%me-xmap%root_pe) = .false.
1910 xmap%your2my1(xmap%me-xmap%root_pe) = .false.
1913 allocate( xmap%send_count_repro(0:xmap%npes-1) )
1914 allocate( xmap%recv_count_repro(0:xmap%npes-1) )
1915 xmap%send_count_repro = 0
1916 xmap%recv_count_repro = 0
1917 do g=2,
size(xmap%grids(:))
1919 if(xmap%grids(
g)%size >0) &
1920 xmap%send_count_repro(p) = xmap%send_count_repro(p) &
1921 +count(xmap%grids(
g)%x (:)%pe==p+xmap%root_pe)
1922 if(xmap%grids(
g)%size_repro >0) &
1923 xmap%recv_count_repro(p) = xmap%recv_count_repro(p) &
1924 +count(xmap%grids(
g)%x_repro(:)%pe==p+xmap%root_pe)
1927 xmap%send_count_repro_tot = sum(xmap%send_count_repro)
1928 xmap%recv_count_repro_tot = sum(xmap%recv_count_repro)
1930 xmap%send_count_repro_tot = 0
1931 xmap%recv_count_repro_tot = 0
1935 call mpp_open( unit,
'xgrid.out', action=mpp_overwr, threading=mpp_multi, &
1936 fileset=mpp_multi, nohdrs=.true. )
1938 write( unit,* )xmap%grids(:)%id,
' GRID: PE ', xmap%me,
' #XCELLS=', &
1939 xmap%grids(2:
size(xmap%grids(:)))%size,
' #COMM. PARTNERS=', &
1940 count(xmap%your1my2),
'/', count(xmap%your2my1), &
1941 pack((/(p+xmap%root_pe,p=0,xmap%npes-1)/), xmap%your1my2), &
1942 '/', pack((/(p+xmap%root_pe,p=0,xmap%npes-1)/), xmap%your2my1)
1943 call close_file (unit)
1946 allocate( xmap%x1(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
1947 allocate( xmap%x2(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
1948 allocate( xmap%x1_put(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
1949 allocate( xmap%x2_get(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
1952 allocate(xmap%get1, xmap%put1)
1960 allocate(xmap%get1_repro)
1972 if(lnd_ug_id ==0)
then 1975 allocate(tmp_2d(grid1%is_me:grid1%ie_me, grid1%js_me:grid1%je_me))
1980 write(out_unit,* )
"Checked data is array of constant 1" 1981 write(out_unit,* )grid1%id,
'(',xmap%grids(:)%id,
')=', xxx
1983 if(lnd_ug_id == 0)
then 1984 do g=2,
size(xmap%grids(:))
1986 write( out_unit,* )xmap%grids(
g)%id,
'(',xmap%grids(:)%id,
')=', xxx
1989 do g=2,
size(xmap%grids(:))
1990 grid => xmap%grids(
g)
1991 allocate(tmp_3d(grid%is_me:grid%ie_me, grid%js_me:grid%je_me,grid%km))
1994 write( out_unit,* )xmap%grids(
g)%id,
'(',xmap%grids(:)%id,
')=', xxx
1999 if(grid1%id ==
"ATM")
then 2000 allocate(check_data(
size(grid1%area,1),
size(grid1%area,2)))
2001 call random_number(check_data)
2004 if(lnd_ug_id ==0)
then 2009 write( out_unit,* ) &
2010 "Checked data is array of random number between 0 and 1 using "//trim(
interp_method)
2011 write( out_unit,* )grid1%id,
'(',xmap%grids(:)%id,
')=', xxx
2013 deallocate(check_data)
2014 do g=2,
size(xmap%grids(:))
2015 allocate(check_data_3d(xmap%grids(
g)%is_me:xmap%grids(
g)%ie_me, &
2016 xmap%grids(
g)%js_me:xmap%grids(
g)%je_me, grid1%km))
2017 call random_number(check_data_3d)
2018 if(lnd_ug_id ==0)
then 2023 write( out_unit,* )xmap%grids(
g)%id,
'(',xmap%grids(:)%id,
')=', xxx
2024 deallocate( check_data_3d)
2036 function get_nest_contact(mosaic_file, tile_nest_out, tile_parent_out, is_nest_out, &
2037 ie_nest_out, js_nest_out, je_nest_out, is_parent_out, &
2038 ie_parent_out, js_parent_out, je_parent_out)
2039 character(len=*),
intent(in) :: mosaic_file
2040 integer,
intent(out) :: tile_nest_out, tile_parent_out
2041 integer,
intent(out) :: is_nest_out, ie_nest_out
2042 integer,
intent(out) :: js_nest_out, je_nest_out
2043 integer,
intent(out) :: is_parent_out, ie_parent_out
2044 integer,
intent(out) :: js_parent_out, je_parent_out
2047 integer :: ntiles, ncontacts, n, t1, t2
2048 integer :: nx1_contact, ny1_contact
2049 integer :: nx2_contact, ny2_contact
2050 integer,
allocatable,
dimension(:) :: nx, ny
2051 integer,
allocatable,
dimension(:) :: tile1, tile2
2052 integer,
allocatable,
dimension(:) :: istart1, iend1, jstart1, jend1
2053 integer,
allocatable,
dimension(:) :: istart2, iend2, jstart2, jend2
2055 tile_nest_out = 0; tile_parent_out = 0
2056 is_nest_out = 0; ie_nest_out = 0
2057 js_nest_out = 0; je_nest_out = 0
2058 is_parent_out = 0; ie_parent_out = 0
2059 js_parent_out = 0; je_parent_out = 0
2064 if( ntiles == 1 )
return 2065 allocate(nx(ntiles), ny(ntiles))
2069 if(ncontacts == 0)
return 2070 allocate(tile1(ncontacts), tile2(ncontacts))
2071 allocate(istart1(ncontacts), iend1(ncontacts))
2072 allocate(jstart1(ncontacts), jend1(ncontacts))
2073 allocate(istart2(ncontacts), iend2(ncontacts))
2074 allocate(jstart2(ncontacts), jend2(ncontacts))
2076 call get_mosaic_contact( mosaic_file, tile1, tile2, istart1, iend1, jstart1, jend1, &
2077 istart2, iend2, jstart2, jend2)
2080 if( tile1(n) == tile2(n) ) cycle
2082 nx1_contact = iend1(n)-istart1(n)+1
2083 ny1_contact = jend1(n)-jstart1(n)+1
2084 nx2_contact = iend2(n)-istart2(n)+1
2085 ny2_contact = jend2(n)-jstart2(n)+1
2089 if( (nx(t1) .NE. nx1_contact .OR. ny(t1) .NE. ny1_contact ) .AND. &
2090 (nx(t2) .NE. nx2_contact .OR. ny(t2) .NE. ny2_contact ) ) cycle
2091 if(nx1_contact == nx2_contact .AND. ny1_contact == ny2_contact)
then 2092 call error_mesg(
'xgrid_mod',
'There is no refinement for the overlapping region', fatal)
2097 call error_mesg(
'xgrid_mod',
'only support one nest region, contact developer' ,fatal)
2099 if(nx2_contact*ny2_contact > nx1_contact*ny1_contact)
then 2100 is_nest_out = istart2(n);
2101 ie_nest_out = iend2(n);
2102 js_nest_out = jstart2(n);
2103 je_nest_out = jend2(n);
2104 tile_nest_out = tile2(n);
2105 is_parent_out = istart1(n);
2106 ie_parent_out = iend1(n);
2107 js_parent_out = jstart1(n);
2108 je_parent_out = jend1(n);
2109 tile_parent_out = tile1(n);
2111 is_nest_out = istart1(n);
2112 ie_nest_out = iend1(n);
2113 js_nest_out = jstart1(n);
2114 je_nest_out = jend1(n);
2115 tile_nest_out = tile1(n);
2116 is_parent_out = istart2(n);
2117 ie_parent_out = iend2(n);
2118 js_parent_out = jstart2(n);
2119 je_parent_out = jend2(n);
2120 tile_parent_out = tile2(n);
2124 deallocate(nx, ny, tile1, tile2)
2125 deallocate(istart1, iend1, jstart1, jend1)
2126 deallocate(istart2, iend2, jstart2, jend2)
2136 integer,
dimension(xmap%npes) :: pe_ind, cnt
2137 integer,
dimension(0:xmap%npes-1) :: send_ind, recv_ind, pl
2138 integer :: npes, nsend, nrecv, mypos
2139 integer :: m, p, pos, n, g, l, im, i, j
2140 type(comm_type),
pointer,
save :: comm => null()
2142 comm => xmap%get1_repro
2146 mypos = mpp_pe() - mpp_root_pe()
2148 p = mod(mypos+npes-m, npes)
2149 if( xmap%recv_count_repro(p) > 0 )
then 2156 if( nrecv > 0 )
then 2157 allocate(comm%recv(nrecv))
2161 comm%recv(n)%count = xmap%recv_count_repro(p)
2162 comm%recv(n)%pe = p + xmap%root_pe
2163 comm%recv(n)%buffer_pos = pos
2164 pos = pos + comm%recv(n)%count
2171 mypos = mpp_pe() - mpp_root_pe()
2173 p = mod(mypos+m, npes)
2174 if( xmap%send_count_repro(p) > 0 )
then 2182 if( nsend > 0 )
then 2183 allocate(comm%send(nsend))
2188 comm%send(n)%count = xmap%send_count_repro(p)
2189 comm%send(n)%pe = p + xmap%root_pe
2190 comm%send(n)%buffer_pos = pos
2191 pos = pos + comm%send(n)%count
2192 allocate(comm%send(n)%i(comm%send(n)%count))
2193 allocate(comm%send(n)%j(comm%send(n)%count))
2194 allocate(comm%send(n)%g(comm%send(n)%count))
2195 allocate(comm%send(n)%xLoc(comm%send(n)%count))
2198 do g=2,
size(xmap%grids(:))
2199 im = xmap%grids(g)%im
2200 do l=1,xmap%grids(g)%size
2201 p = xmap%grids(g)%x(l)%pe-xmap%root_pe
2205 i = xmap%grids(g)%x(l)%i2
2206 j = xmap%grids(g)%x(l)%j2
2207 if(xmap%grids(g)%is_ug)
then 2208 comm%send(n)%i(pos) = xmap%grids(g)%l_index((j-1)*im+i)
2209 comm%send(n)%j(pos) = 1
2211 comm%send(n)%i(pos) = xmap%grids(g)%x(l)%i2
2212 comm%send(n)%j(pos) = xmap%grids(g)%x(l)%j2
2214 comm%send(n)%g(pos) = g
2219 if( comm%send(n)%count .NE. cnt(n) )
call error_mesg(
'xgrid_mod', &
2220 .NE.
'comm%send(n)%count cnt(n)', fatal)
2226 do g=2,
size(xmap%grids(:))
2227 do l=1,xmap%grids(g)%size_repro
2228 p = xmap%grids(g)%x_repro(l)%pe-xmap%root_pe
2229 xmap%grids(g)%x_repro(l)%recv_pos = pl(p)
2241 type(
grid_type),
pointer,
save :: grid1 =>null()
2242 integer,
allocatable :: send_size(:)
2243 integer,
allocatable :: recv_size(:)
2244 integer :: max_size, g, npes, l, ll, nset, m
2245 integer :: i1, j1, tile1, p, n, pos, buffer_pos, mypos
2246 integer :: nsend, nrecv, rbuf_size, sbuf_size, msgsize
2248 real,
allocatable :: recv_buf(:), send_buf(:)
2249 real,
allocatable :: diarray(:), djarray(:)
2250 integer,
allocatable :: iarray(:), jarray(:), tarray(:)
2251 integer,
allocatable :: pos_x(:), pelist(:), size_pe(:), pe_side1(:)
2252 integer :: recv_buffer_pos(0:xmap%npes)
2253 integer :: send_buffer_pos(0:xmap%npes)
2254 type(comm_type),
pointer,
save :: comm => null()
2258 do g=2,
size(xmap%grids(:))
2259 max_size = max_size + xmap%grids(g)%size
2262 grid1 => xmap%grids(1)
2267 allocate(pelist(0:npes-1))
2268 call mpp_get_current_pelist(pelist)
2269 allocate(send_size(0:npes-1))
2270 allocate(recv_size(0:npes-1))
2271 allocate(size_pe(0:npes-1))
2272 allocate(pos_x(0:npes-1))
2277 if(max_size > 0)
then 2278 allocate(pe_side1(max_size))
2279 allocate(xmap%ind_get1(max_size))
2283 do g=2,
size(xmap%grids(:))
2284 do l=1,xmap%grids(g)%size
2285 i1 = xmap%grids(g)%x(l)%i1
2286 j1 = xmap%grids(g)%x(l)%j1
2287 tile1 = xmap%grids(g)%x(l)%tile
2289 if(grid1%tile(p) == tile1)
then 2291 size_pe(p) = size_pe(p) + 1
2296 if( p == npes )
then 2297 call error_mesg(
'xgrid_mod',
'tile is not in grid1%tile(:)', fatal)
2306 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2310 allocate(iarray(max_size))
2311 allocate(jarray(max_size))
2312 allocate(tarray(max_size))
2314 allocate(diarray(max_size))
2315 allocate(djarray(max_size))
2320 do g=2,
size(xmap%grids(:))
2321 do l=1,xmap%grids(g)%size
2322 i1 = xmap%grids(g)%x(l)%i1
2323 j1 = xmap%grids(g)%x(l)%j1
2324 tile1 = xmap%grids(g)%x(l)%tile
2329 if(send_size(p) > 0)
then 2330 if( i1 == iarray(pos_x(p)+send_size(p)) .AND. j1 == jarray(pos_x(p)+send_size(p)) &
2331 .AND. tile1 == tarray(pos_x(p)+send_size(p)))
then 2336 do n = 1, send_size(p)
2337 if(i1 == iarray(pos_x(p)+n) .AND. j1 == jarray(pos_x(p)+n) .AND. tile1 == tarray(pos_x(p)+n))
then 2345 send_size(p) = send_size(p)+1
2346 pos = pos_x(p)+send_size(p)
2351 diarray(pos) = xmap%grids(g)%x(l)%di
2352 djarray(pos) = xmap%grids(g)%x(l)%dj
2356 xmap%ind_get1(ll) = n
2362 pos_x(p) = pos_x(p-1) + send_size(p-1)
2366 do g=2,
size(xmap%grids(:))
2367 do l=1,xmap%grids(g)%size
2370 xmap%ind_get1(ll) = pos_x(p) + xmap%ind_get1(ll)
2375 mypos = mpp_pe()-mpp_root_pe()
2378 recv_size(:) = xmap%your2my1_size(:)
2379 nsend = count( send_size> 0)
2382 allocate(comm%send(nsend))
2383 comm%send(:)%count = 0
2388 send_buffer_pos(p) = pos
2389 pos = pos + send_size(p)
2395 p = mod(mypos+n, npes)
2396 if(send_size(p)>0)
then 2398 allocate(comm%send(pos)%i(send_size(p)))
2399 comm%send(pos)%buffer_pos = send_buffer_pos(p)
2400 comm%send(pos)%count = send_size(p)
2401 comm%send(pos)%pe = pelist(p)
2402 comm%sendsize = comm%sendsize + send_size(p)
2408 rbuf_size = sum(recv_size)*nset
2409 sbuf_size = sum(send_size)*nset
2410 if(rbuf_size>0)
allocate(recv_buf(rbuf_size))
2411 if(sbuf_size>0)
allocate(send_buf(sbuf_size))
2415 p = mod(mypos+npes-n, npes)
2416 if(recv_size(p) ==0) cycle
2417 msgsize = recv_size(p)*nset
2418 call mpp_recv(recv_buf(pos+1), glen=msgsize, from_pe=pelist(p), block=.false., tag=comm_tag_4)
2424 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2429 p = mod(mypos+n, npes)
2430 do l = 1, send_size(p)
2431 send_buf(pos+1) = iarray(pos_x(p)+l)
2432 send_buf(pos+2) = jarray(pos_x(p)+l)
2433 send_buf(pos+3) = tarray(pos_x(p)+l)
2435 send_buf(pos+4) = diarray(pos_x(p)+l)
2436 send_buf(pos+5) = djarray(pos_x(p)+l)
2444 p = mod(mypos+n, npes)
2445 if(send_size(p) ==0) cycle
2446 msgsize = send_size(p)*nset
2447 call mpp_send(send_buf(pos+1), plen=msgsize, to_pe=pelist(p), tag=comm_tag_4 )
2451 call mpp_sync_self(
check=event_recv)
2452 nrecv = count(recv_size>0)
2457 allocate(comm%recv(nrecv))
2458 comm%recv(:)%count = 0
2462 recv_buffer_pos(p) = buffer_pos
2463 buffer_pos = buffer_pos + recv_size(p)
2468 p = mod(mypos+npes-m, npes)
2469 if(recv_size(p)>0)
then 2471 allocate(comm%recv(pos)%i(recv_size(p)))
2472 allocate(comm%recv(pos)%j(recv_size(p)))
2473 allocate(comm%recv(pos)%tile(recv_size(p)))
2474 comm%recv(pos)%buffer_pos = recv_buffer_pos(p)
2475 comm%recv(pos)%pe = pelist(p)
2476 comm%recv(pos)%count = recv_size(p)
2477 comm%recvsize = comm%recvsize + recv_size(p)
2479 allocate(comm%recv(pos)%di(recv_size(p)))
2480 allocate(comm%recv(pos)%dj(recv_size(p)))
2482 if(grid1%is_ug)
then 2483 do n = 1, recv_size(p)
2484 i = recv_buf(buffer_pos+1)
2485 j = recv_buf(buffer_pos+2)
2486 comm%recv(pos)%i(n) = grid1%l_index((j-1)*grid1%im+i)
2487 comm%recv(pos)%j(n) = 1
2488 comm%recv(pos)%tile(n) = recv_buf(buffer_pos+3)
2490 comm%recv(pos)%di(n) = recv_buf(buffer_pos+4)
2491 comm%recv(pos)%dj(n) = recv_buf(buffer_pos+5)
2493 buffer_pos = buffer_pos + nset
2496 do n = 1, recv_size(p)
2497 comm%recv(pos)%i(n) = recv_buf(buffer_pos+1) - grid1%is_me + 1
2498 comm%recv(pos)%j(n) = recv_buf(buffer_pos+2) - grid1%js_me + 1
2499 comm%recv(pos)%tile(n) = recv_buf(buffer_pos+3)
2501 comm%recv(pos)%di(n) = recv_buf(buffer_pos+4)
2502 comm%recv(pos)%dj(n) = recv_buf(buffer_pos+5)
2504 buffer_pos = buffer_pos + nset
2509 allocate(comm%unpack_ind(nrecv))
2512 if(recv_size(p)>0)
then 2515 if(comm%recv(m)%pe == pelist(p))
then 2516 comm%unpack_ind(pos) = m
2523 call mpp_sync_self()
2525 if(
allocated(send_buf) )
deallocate(send_buf)
2526 if(
allocated(recv_buf) )
deallocate(recv_buf)
2527 if(
allocated(pelist) )
deallocate(pelist)
2528 if(
allocated(pos_x) )
deallocate(pos_x)
2529 if(
allocated(pelist) )
deallocate(pelist)
2530 if(
allocated(iarray) )
deallocate(iarray)
2531 if(
allocated(jarray) )
deallocate(jarray)
2532 if(
allocated(tarray) )
deallocate(tarray)
2533 if(
allocated(size_pe) )
deallocate(size_pe)
2540 type(
grid_type),
pointer,
save :: grid1 =>null()
2541 integer,
allocatable :: send_size(:)
2542 integer,
allocatable :: recv_size(:)
2543 integer :: max_size, g, npes, l, ll, m, mypos
2544 integer :: i1, j1, tile1, p, n, pos, buffer_pos
2545 integer :: nsend, nrecv, msgsize, nset, rbuf_size, sbuf_size
2547 real,
allocatable :: recv_buf(:), send_buf(:)
2548 real,
allocatable :: diarray(:), djarray(:)
2549 integer,
allocatable :: iarray(:), jarray(:), tarray(:)
2550 integer,
allocatable :: pos_x(:), pelist(:), size_pe(:), pe_put1(:)
2551 integer :: root_pe, recvsize, sendsize
2552 integer :: recv_buffer_pos(0:xmap%npes)
2553 type(comm_type),
pointer,
save :: comm => null()
2557 if(
nnest == 0 .OR. xmap%grids(1)%id .NE.
'ATM' )
then 2558 comm%nsend = xmap%get1%nrecv
2559 comm%nrecv = xmap%get1%nsend
2560 comm%sendsize = xmap%get1%recvsize
2561 comm%recvsize = xmap%get1%sendsize
2562 comm%send => xmap%get1%recv
2563 comm%recv => xmap%get1%send
2564 xmap%ind_put1 => xmap%ind_get1
2569 do g=2,
size(xmap%grids(:))
2570 max_size = max_size + xmap%grids(g)%size
2572 grid1 => xmap%grids(1)
2576 allocate(pelist(0:npes-1))
2577 call mpp_get_current_pelist(pelist)
2578 allocate(send_size(0:npes-1))
2579 allocate(recv_size(0:npes-1))
2580 allocate(size_pe(0:npes-1))
2581 allocate(pos_x(0:npes-1))
2586 if(max_size > 0)
then 2587 allocate(pe_put1(max_size))
2588 allocate(xmap%ind_put1(max_size))
2592 do g=2,
size(xmap%grids(:))
2593 do l=1,xmap%grids(g)%size
2594 i1 = xmap%grids(g)%x(l)%i1
2595 j1 = xmap%grids(g)%x(l)%j1
2596 tile1 = xmap%grids(g)%x(l)%tile
2598 if(grid1%tile(p) == tile1)
then 2599 if(
in_box(i1, j1, grid1%is(p), grid1%ie(p), grid1%js(p), grid1%je(p)))
then 2600 size_pe(p) = size_pe(p) + 1
2612 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2616 allocate(iarray(max_size))
2617 allocate(jarray(max_size))
2618 allocate(tarray(max_size))
2620 allocate(diarray(max_size))
2621 allocate(djarray(max_size))
2626 do g=2,
size(xmap%grids(:))
2627 do l=1,xmap%grids(g)%size
2628 i1 = xmap%grids(g)%x(l)%i1
2629 j1 = xmap%grids(g)%x(l)%j1
2630 tile1 = xmap%grids(g)%x(l)%tile
2635 if(send_size(p) > 0)
then 2636 if( i1 == iarray(pos_x(p)+send_size(p)) .AND. j1 == jarray(pos_x(p)+send_size(p)) &
2637 .AND. tile1 == tarray(pos_x(p)+send_size(p)))
then 2642 do n = 1, send_size(p)
2643 if(i1 == iarray(pos_x(p)+n) .AND. j1 == jarray(pos_x(p)+n) .AND. tile1 == tarray(pos_x(p)+n))
then 2651 send_size(p) = send_size(p)+1
2652 pos = pos_x(p)+send_size(p)
2657 diarray(pos) = xmap%grids(g)%x(l)%di
2658 djarray(pos) = xmap%grids(g)%x(l)%dj
2662 xmap%ind_put1(ll) = n
2668 pos_x(p) = pos_x(p-1) + send_size(p-1)
2672 do g=2,
size(xmap%grids(:))
2673 do l=1,xmap%grids(g)%size
2674 i1 = xmap%grids(g)%x(l)%i1
2675 j1 = xmap%grids(g)%x(l)%j1
2676 tile1 = xmap%grids(g)%x(l)%tile
2679 xmap%ind_put1(ll) = pos_x(p) + xmap%ind_put1(ll)
2685 mypos = mpp_pe()-mpp_root_pe()
2691 p = mod(mypos+npes-n, npes)
2692 call mpp_recv(recv_size(p), glen=1, from_pe=pelist(p), block=.false., tag=comm_tag_5)
2697 p = mod(mypos+n, npes)
2698 call mpp_send(send_size(p), plen=1, to_pe=pelist(p), tag=comm_tag_5)
2701 call mpp_sync_self(
check=event_recv)
2702 call mpp_sync_self()
2705 nrecv = count( send_size> 0)
2708 allocate(comm%recv(nrecv))
2709 comm%recv(:)%count = 0
2714 recv_buffer_pos(p) = pos
2715 pos = pos + send_size(p)
2720 p = mod(mypos+npes-n, npes)
2721 if(send_size(p)>0)
then 2723 allocate(comm%recv(pos)%i(send_size(p)))
2724 comm%recv(pos)%buffer_pos = recv_buffer_pos(p)
2725 comm%recv(pos)%count = send_size(p)
2726 comm%recv(pos)%pe = pelist(p)
2727 comm%recvsize = comm%recvsize + send_size(p)
2733 rbuf_size = sum(recv_size)*nset
2734 sbuf_size = sum(send_size)*nset
2735 if(rbuf_size>0)
allocate(recv_buf(rbuf_size))
2736 if(sbuf_size>0)
allocate(send_buf(sbuf_size))
2740 p = mod(mypos+npes-n, npes)
2741 if(recv_size(p) ==0) cycle
2742 msgsize = recv_size(p)*nset
2743 call mpp_recv(recv_buf(pos+1), glen=msgsize, from_pe=pelist(p), block=.false., tag=comm_tag_6)
2749 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2754 p = mod(mypos+n, npes)
2755 do l = 1, send_size(p)
2756 send_buf(pos+1) = iarray(pos_x(p)+l)
2757 send_buf(pos+2) = jarray(pos_x(p)+l)
2758 send_buf(pos+3) = tarray(pos_x(p)+l)
2760 send_buf(pos+4) = diarray(pos_x(p)+l)
2761 send_buf(pos+5) = djarray(pos_x(p)+l)
2769 p = mod(mypos+n, npes)
2770 if(send_size(p) ==0) cycle
2771 msgsize = send_size(p)*nset
2772 call mpp_send(send_buf(pos+1), plen=msgsize, to_pe=pelist(p), tag=comm_tag_6 )
2776 call mpp_sync_self(
check=event_recv)
2777 nsend = count(recv_size>0)
2782 allocate(comm%send(nsend))
2783 comm%send(:)%count = 0
2787 p = mod(mypos+npes-m, npes)
2788 if(recv_size(p)>0)
then 2790 allocate(comm%send(pos)%i(recv_size(p)))
2791 allocate(comm%send(pos)%j(recv_size(p)))
2792 allocate(comm%send(pos)%tile(recv_size(p)))
2793 comm%send(pos)%pe = pelist(p)
2794 comm%send(pos)%count = recv_size(p)
2795 comm%sendsize = comm%sendsize + recv_size(p)
2797 allocate(comm%send(pos)%di(recv_size(p)))
2798 allocate(comm%send(pos)%dj(recv_size(p)))
2800 do n = 1, recv_size(p)
2801 comm%send(pos)%i(n) = recv_buf(buffer_pos+1) - grid1%is_me + 1
2802 comm%send(pos)%j(n) = recv_buf(buffer_pos+2) - grid1%js_me + 1
2803 comm%send(pos)%tile(n) = recv_buf(buffer_pos+3)
2805 comm%send(pos)%di(n) = recv_buf(buffer_pos+4)
2806 comm%send(pos)%dj(n) = recv_buf(buffer_pos+5)
2808 buffer_pos = buffer_pos + nset
2814 call mpp_sync_self()
2815 if(
allocated(send_buf) )
deallocate(send_buf)
2816 if(
allocated(recv_buf) )
deallocate(recv_buf)
2817 if(
allocated(pelist) )
deallocate(pelist)
2818 if(
allocated(pos_x) )
deallocate(pos_x)
2819 if(
allocated(pelist) )
deallocate(pelist)
2820 if(
allocated(iarray) )
deallocate(iarray)
2821 if(
allocated(jarray) )
deallocate(jarray)
2822 if(
allocated(tarray) )
deallocate(tarray)
2823 if(
allocated(size_pe) )
deallocate(size_pe)
2829 subroutine regen(xmap)
2832 integer :: g, l, k, max_size
2833 integer :: i1, j1, i2, j2, p
2836 logical :: overlap_with_nest
2837 integer :: cnt(xmap%get1%nsend)
2838 integer :: i,j,n,xloc,pos,nsend,m,npes, mypos
2839 integer :: send_ind(0:xmap%npes-1)
2843 do g=2,
size(xmap%grids(:))
2844 max_size = max_size + xmap%grids(g)%size * xmap%grids(g)%km
2847 if (max_size>
size(xmap%x1(:)))
then 2850 allocate( xmap%x1(1:max_size) )
2851 allocate( xmap%x2(1:max_size) )
2855 do g=2,
size(xmap%grids(:))
2856 xmap%grids(g)%first = 1
2857 xmap%grids(g)%last = 0
2862 do g=2,
size(xmap%grids(:))
2863 xmap%grids(g)%first = xmap%size + 1;
2865 do l=1,xmap%grids(g)%size
2866 i1 = xmap%grids(g)%x(l)%i1
2867 j1 = xmap%grids(g)%x(l)%j1
2868 i2 = xmap%grids(g)%x(l)%i2
2869 j2 = xmap%grids(g)%x(l)%j2
2870 tile1 = xmap%grids(g)%x(l)%tile
2872 if(xmap%grids(g)%is_ug)
then 2873 do k=1,xmap%grids(g)%km
2874 lll = xmap%grids(g)%l_index((j2-1)*xmap%grids(g)%im+i2)
2875 if (xmap%grids(g)%frac_area(lll,1,k)/=0.0)
then 2876 xmap%size = xmap%size+1
2877 xmap%x1(xmap%size)%pos = xmap%ind_get1(ll)
2878 xmap%x1(xmap%size)%i = xmap%grids(g)%x(l)%i1
2879 xmap%x1(xmap%size)%j = xmap%grids(g)%x(l)%j1
2880 xmap%x1(xmap%size)%tile = xmap%grids(g)%x(l)%tile
2881 xmap%x1(xmap%size)%area = xmap%grids(g)%x(l)%area &
2882 *xmap%grids(g)%frac_area(lll,1,k)
2883 xmap%x1(xmap%size)%di = xmap%grids(g)%x(l)%di
2884 xmap%x1(xmap%size)%dj = xmap%grids(g)%x(l)%dj
2885 xmap%x2(xmap%size)%i = xmap%grids(g)%x(l)%i2
2886 xmap%x2(xmap%size)%j = xmap%grids(g)%x(l)%j2
2887 xmap%x2(xmap%size)%l = lll
2888 xmap%x2(xmap%size)%k = k
2889 xmap%x2(xmap%size)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
2893 do k=1,xmap%grids(g)%km
2894 if (xmap%grids(g)%frac_area(i2,j2,k)/=0.0)
then 2895 xmap%size = xmap%size+1
2896 xmap%x1(xmap%size)%pos = xmap%ind_get1(ll)
2897 xmap%x1(xmap%size)%i = xmap%grids(g)%x(l)%i1
2898 xmap%x1(xmap%size)%j = xmap%grids(g)%x(l)%j1
2899 xmap%x1(xmap%size)%tile = xmap%grids(g)%x(l)%tile
2900 xmap%x1(xmap%size)%area = xmap%grids(g)%x(l)%area &
2901 *xmap%grids(g)%frac_area(i2,j2,k)
2902 xmap%x1(xmap%size)%di = xmap%grids(g)%x(l)%di
2903 xmap%x1(xmap%size)%dj = xmap%grids(g)%x(l)%dj
2904 xmap%x2(xmap%size)%i = xmap%grids(g)%x(l)%i2
2905 xmap%x2(xmap%size)%j = xmap%grids(g)%x(l)%j2
2906 xmap%x2(xmap%size)%k = k
2907 xmap%x2(xmap%size)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
2912 xmap%grids(g)%last = xmap%size
2916 if (max_size>
size(xmap%x1_put(:)))
then 2917 deallocate(xmap%x1_put)
2918 allocate( xmap%x1_put(1:max_size) )
2920 if (max_size>
size(xmap%x2_get(:)))
then 2921 deallocate(xmap%x2_get)
2922 allocate( xmap%x2_get(1:max_size) )
2925 do g=2,
size(xmap%grids(:))
2926 xmap%grids(g)%first_get = 1
2927 xmap%grids(g)%last_get = 0
2933 do g=2,
size(xmap%grids(:))
2934 xmap%grids(g)%first_get = xmap%size_get2 + 1;
2936 do l=1,xmap%grids(g)%size
2937 i1 = xmap%grids(g)%x(l)%i1
2938 j1 = xmap%grids(g)%x(l)%j1
2939 i2 = xmap%grids(g)%x(l)%i2
2940 j2 = xmap%grids(g)%x(l)%j2
2941 tile1 = xmap%grids(g)%x(l)%tile
2943 overlap_with_nest = .false.
2944 if( xmap%grids(1)%id ==
"ATM" .AND. tile1 ==
tile_parent .AND. &
2946 if(xmap%grids(g)%is_ug)
then 2947 do k=1,xmap%grids(g)%km
2948 lll = xmap%grids(g)%l_index((j2-1)*xmap%grids(g)%im+i2)
2949 if (xmap%grids(g)%frac_area(lll,1,k)/=0.0)
then 2950 xmap%size_put1 = xmap%size_put1+1
2951 xmap%x1_put(xmap%size_put1)%pos = xmap%ind_put1(ll)
2952 xmap%x1_put(xmap%size_put1)%i = xmap%grids(g)%x(l)%i1
2953 xmap%x1_put(xmap%size_put1)%j = xmap%grids(g)%x(l)%j1
2954 xmap%x1_put(xmap%size_put1)%tile = xmap%grids(g)%x(l)%tile
2955 xmap%x1_put(xmap%size_put1)%area = xmap%grids(g)%x(l)%area &
2956 *xmap%grids(g)%frac_area(lll,1,k)
2957 xmap%x1_put(xmap%size_put1)%di = xmap%grids(g)%x(l)%di
2958 xmap%x1_put(xmap%size_put1)%dj = xmap%grids(g)%x(l)%dj
2959 if( .not. overlap_with_nest)
then 2960 xmap%size_get2 = xmap%size_get2+1
2961 xmap%x2_get(xmap%size_get2)%i = xmap%grids(g)%x(l)%i2
2962 xmap%x2_get(xmap%size_get2)%j = xmap%grids(g)%x(l)%j2
2963 xmap%x2_get(xmap%size_get2)%l = lll
2964 xmap%x2_get(xmap%size_get2)%k = k
2965 xmap%x2_get(xmap%size_get2)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
2966 xmap%x2_get(xmap%size_get2)%pos = xmap%size_put1
2971 do k=1,xmap%grids(g)%km
2972 if (xmap%grids(g)%frac_area(i2,j2,k)/=0.0)
then 2973 xmap%size_put1 = xmap%size_put1+1
2974 xmap%x1_put(xmap%size_put1)%pos = xmap%ind_put1(ll)
2975 xmap%x1_put(xmap%size_put1)%i = xmap%grids(g)%x(l)%i1
2976 xmap%x1_put(xmap%size_put1)%j = xmap%grids(g)%x(l)%j1
2977 xmap%x1_put(xmap%size_put1)%tile = xmap%grids(g)%x(l)%tile
2978 xmap%x1_put(xmap%size_put1)%area = xmap%grids(g)%x(l)%area &
2979 *xmap%grids(g)%frac_area(i2,j2,k)
2980 xmap%x1_put(xmap%size_put1)%di = xmap%grids(g)%x(l)%di
2981 xmap%x1_put(xmap%size_put1)%dj = xmap%grids(g)%x(l)%dj
2982 if( .not. overlap_with_nest)
then 2983 xmap%size_get2 = xmap%size_get2+1
2984 xmap%x2_get(xmap%size_get2)%i = xmap%grids(g)%x(l)%i2
2985 xmap%x2_get(xmap%size_get2)%j = xmap%grids(g)%x(l)%j2
2986 xmap%x2_get(xmap%size_get2)%k = k
2987 xmap%x2_get(xmap%size_get2)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
2988 xmap%x2_get(xmap%size_get2)%pos = xmap%size_put1
2994 xmap%grids(g)%last_get = xmap%size_get2
2999 if (xmap%get1_repro%nsend > 0)
then 3003 mypos = mpp_pe() - mpp_root_pe()
3006 p = mod(mypos+m, npes)
3007 if( xmap%send_count_repro(p) > 0 )
then 3012 do g=2,
size(xmap%grids(:))
3013 do l=1,xmap%grids(g)%size
3014 p = xmap%grids(g)%x(l)%pe-xmap%root_pe
3018 xmap%get1_repro%send(n)%xLoc(pos) = xloc
3019 if( xmap%grids(g)%is_ug )
then 3020 i = xmap%grids(g)%x(l)%l2
3021 xloc = xloc + count(xmap%grids(g)%frac_area(i,1,:)/=0.0)
3023 i = xmap%grids(g)%x(l)%i2
3024 j = xmap%grids(g)%x(l)%j2
3025 xloc = xloc + count(xmap%grids(g)%frac_area(i,j,:)/=0.0)
3032 end subroutine regen 3053 real,
dimension(:,:,:),
intent(in ) :: f
3054 character(len=3),
intent(in ) :: grid_id
3058 type(grid_type),
pointer,
save :: grid =>null()
3060 if (grid_id==xmap%grids(1)%id)
call error_mesg (
'xgrid_mod', &
3061 'set_frac_area called on side 1 grid', fatal)
3062 do g=2,
size(xmap%grids(:))
3063 grid => xmap%grids(g)
3064 if (grid_id==grid%id)
then 3065 if (
size(f,3)/=
size(grid%frac_area,3))
then 3066 deallocate (grid%frac_area)
3067 grid%km =
size(f,3);
3068 allocate( grid%frac_area(grid%is_me:grid%ie_me, grid%js_me:grid%je_me, &
3077 call error_mesg (
'xgrid_mod',
'set_frac_area: could not find grid id', fatal)
3101 real,
dimension(:,:),
intent(in ) :: f
3102 character(len=3),
intent(in ) :: grid_id
3106 type(
grid_type),
pointer,
save :: grid =>null()
3108 if (grid_id==xmap%grids(1)%id)
call error_mesg (
'xgrid_mod', &
3109 'set_frac_area_ug called on side 1 grid', fatal)
3110 if (grid_id .NE.
'LND' )
call error_mesg (
'xgrid_mod', &
3111 .NE.
'set_frac_area_ug called for grid_id LND', fatal)
3112 do g=2,
size(xmap%grids(:))
3113 grid => xmap%grids(
g)
3114 if (grid_id==grid%id)
then 3115 if (
size(f,2)/=
size(grid%frac_area,3))
then 3116 deallocate (grid%frac_area)
3117 grid%km =
size(f,2);
3118 allocate( grid%frac_area(grid%ls_me:grid%le_me, 1, grid%km) )
3120 grid%frac_area(:,1,:) = f(:,:);
3126 call error_mesg (
'xgrid_mod',
'set_frac_area_ug: could not find grid id', fatal)
3167 real,
dimension(:,:),
intent(in ) :: d
3168 character(len=3),
intent(in ) :: grid_id
3169 real,
dimension(:),
intent(inout) :: x
3171 integer,
intent(in),
optional :: remap_method
3172 logical,
intent(in),
optional :: complete
3174 logical :: is_complete, set_mismatch
3175 integer :: g, method
3176 character(len=2) :: text
3177 integer,
save :: isize=0
3178 integer,
save :: jsize=0
3179 integer,
save :: lsize=0
3180 integer,
save :: xsize=0
3181 integer,
save :: method_saved=0
3182 character(len=3),
save :: grid_id_saved=
"" 3183 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: d_addrs=-9999
3184 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: x_addrs=-9999
3186 if (grid_id==xmap%grids(1)%id)
then 3188 if(
present(remap_method)) method = remap_method
3189 is_complete = .true.
3190 if(
present(complete)) is_complete=complete
3194 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group put_side1_to_xgrid', fatal)
3196 d_addrs(lsize) = loc(d)
3197 x_addrs(lsize) = loc(x)
3203 method_saved = method
3204 grid_id_saved = grid_id
3206 set_mismatch = .false.
3207 set_mismatch = set_mismatch .OR. (isize /=
size(d,1))
3208 set_mismatch = set_mismatch .OR. (jsize /=
size(d,2))
3209 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
3210 set_mismatch = set_mismatch .OR. (method_saved /= method)
3211 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
3212 if(set_mismatch)
then 3213 write( text,
'(i2)' ) lsize
3214 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text//
' for group put_side1_to_xgrid', fatal )
3218 if(is_complete)
then 3225 if(grid_id .NE.
'ATM')
call error_mesg (
'xgrid_mod', &
3226 "second order put_to_xgrid should only be applied to 'ATM' model, "//&
3227 "contact developer", fatal)
3243 do g=2,
size(xmap%grids(:))
3244 if (grid_id==xmap%grids(g)%id) &
3246 'put_to_xgrid expects a 3D side 2 grid', fatal)
3249 call error_mesg (
'xgrid_mod',
'put_to_xgrid: could not find grid id', fatal)
3263 real,
dimension(:,:,:),
intent(in ) :: d
3264 character(len=3),
intent(in ) :: grid_id
3265 real,
dimension(:),
intent(inout) :: x
3270 if (grid_id==xmap%grids(1)%id) &
3272 'put_to_xgrid expects a 2D side 1 grid', fatal)
3274 do g=2,
size(xmap%grids(:))
3275 if (grid_id==xmap%grids(g)%id)
then 3281 call error_mesg (
'xgrid_mod',
'put_to_xgrid: could not find grid id', fatal)
3295 real,
dimension(:,:),
intent( out) :: d
3296 character(len=3),
intent(in ) :: grid_id
3297 real,
dimension(:),
intent(in ) :: x
3299 logical,
intent(in),
optional :: complete
3301 logical :: is_complete, set_mismatch
3303 character(len=2) :: text
3304 integer,
save :: isize=0
3305 integer,
save :: jsize=0
3306 integer,
save :: lsize=0
3307 integer,
save :: xsize=0
3308 character(len=3),
save :: grid_id_saved=
"" 3309 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: d_addrs=-9999
3310 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: x_addrs=-9999
3312 if (grid_id==xmap%grids(1)%id)
then 3313 is_complete = .true.
3314 if(
present(complete)) is_complete=complete
3318 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group get_side1_from_xgrid', fatal)
3320 d_addrs(lsize) = loc(d)
3321 x_addrs(lsize) = loc(x)
3327 grid_id_saved = grid_id
3329 set_mismatch = .false.
3330 set_mismatch = set_mismatch .OR. (isize /=
size(d,1))
3331 set_mismatch = set_mismatch .OR. (jsize /=
size(d,2))
3332 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
3333 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
3334 if(set_mismatch)
then 3335 write( text,
'(i2)' ) lsize
3336 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text//
' for group get_side1_from_xgrid', fatal )
3340 if(is_complete)
then 3346 d_addrs(1:lsize) = -9999
3347 x_addrs(1:lsize) = -9999
3357 do g=2,
size(xmap%grids(:))
3358 if (grid_id==xmap%grids(g)%id) &
3360 'get_from_xgrid expects a 3D side 2 grid', fatal)
3363 call error_mesg (
'xgrid_mod',
'get_from_xgrid: could not find grid id', fatal)
3377 real,
dimension(:,:,:),
intent( out) :: d
3378 character(len=3),
intent(in ) :: grid_id
3379 real,
dimension(:),
intent(in ) :: x
3384 if (grid_id==xmap%grids(1)%id) &
3386 'get_from_xgrid expects a 2D side 1 grid', fatal)
3388 do g=2,
size(xmap%grids(:))
3389 if (grid_id==xmap%grids(g)%id)
then 3395 call error_mesg (
'xgrid_mod',
'get_from_xgrid: could not find grid id', fatal)
3420 subroutine some(xmap, some_arr, grid_id)
3422 character(len=3),
optional,
intent(in) :: grid_id
3423 logical,
dimension(:),
intent(out) :: some_arr
3427 if (.not.
present(grid_id))
then 3429 if(xmap%size > 0)
then 3437 if (grid_id==xmap%grids(1)%id) &
3438 call error_mesg (
'xgrid_mod',
'some expects a side 2 grid id', fatal)
3440 do g=2,
size(xmap%grids(:))
3441 if (grid_id==xmap%grids(
g)%id)
then 3443 some_arr(xmap%grids(
g)%first:xmap%grids(
g)%last) = .true.;
3448 call error_mesg (
'xgrid_mod',
'some could not find grid id', fatal)
3457 real,
dimension(grid%is_me:grid%ie_me, &
grid%js_me:grid%je_me, grid%km),
intent(in) :: d
3458 real,
dimension(: ),
intent(inout) :: x
3464 do l=grid%first,grid%last
3465 x(l) = d(xmap%x2(l)%i,xmap%x2(l)%j,xmap%x2(l)%k)
3475 real,
dimension(grid%is_me:grid%ie_me, &
grid%js_me:grid%je_me, grid%km),
intent(out) :: d
3476 real,
dimension(:),
intent(in ) :: x
3484 do l=grid%first_get,grid%last_get
3485 d(xmap%x2_get(l)%i,xmap%x2_get(l)%j,xmap%x2_get(l)%k) = &
3486 d(xmap%x2_get(l)%i,xmap%x2_get(l)%j,xmap%x2_get(l)%k) + xmap%x2_get(l)%area*x(xmap%x2_get(l)%pos)
3492 d(:,:,k) = d(:,:,k) * grid%area_inv
3502 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
3503 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
3505 integer,
intent(in) :: isize, jsize, xsize, lsize
3507 integer :: i, j, p, buffer_pos, msgsize
3508 integer :: from_pe, to_pe, pos, n, l, count
3509 integer :: ibegin, istart, iend, start_pos
3510 type(
comm_type),
pointer,
save :: comm =>null()
3511 real :: recv_buffer(xmap%put1%recvsize*lsize)
3512 real :: send_buffer(xmap%put1%sendsize*lsize)
3513 real :: unpack_buffer(xmap%put1%recvsize)
3515 real,
dimension(isize, jsize) :: d
3516 real,
dimension(xsize) :: x
3524 do p = 1, comm%nrecv
3525 msgsize = comm%recv(p)%count*lsize
3526 from_pe = comm%recv(p)%pe
3527 buffer_pos = comm%recv(p)%buffer_pos*lsize
3528 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = from_pe, block=.false., tag=comm_tag_7)
3533 do p = 1, comm%nsend
3534 msgsize = comm%send(p)%count*lsize
3535 to_pe = comm%send(p)%pe
3539 do n = 1, comm%send(p)%count
3541 i = comm%send(p)%i(n)
3542 j = comm%send(p)%j(n)
3543 send_buffer(pos) = d(i,j)
3546 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_7 )
3547 buffer_pos = buffer_pos + msgsize
3550 call mpp_sync_self(
check=event_recv)
3553 if( lsize == 1)
then 3555 do l=1,xmap%size_put1
3556 x(l) = recv_buffer(xmap%x1_put(l)%pos)
3564 do p = 1, comm%nrecv
3565 count = comm%recv(p)%count
3566 ibegin = comm%recv(p)%buffer_pos*lsize + 1
3567 istart = ibegin + (l-1)*count
3568 iend = istart + count - 1
3569 pos = comm%recv(p)%buffer_pos
3572 unpack_buffer(pos) = recv_buffer(n)
3575 do i=1,xmap%size_put1
3576 x(i) = unpack_buffer(xmap%x1_put(i)%pos)
3581 call mpp_sync_self()
3591 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
3592 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
3594 integer,
intent(in) :: isize, jsize, xsize, lsize
3597 real,
dimension(0:isize+1, 0:jsize+1, lsize) :: tmp
3598 real,
dimension(isize, jsize, lsize) :: tmpx, tmpy
3599 real,
dimension(isize, jsize, lsize) :: d_bar_max, d_bar_min
3600 real,
dimension(isize, jsize, lsize) :: d_max, d_min
3602 integer :: i, is, ie, im, j, js, je, jm, ii, jj
3603 integer :: p, l, ioff, joff, isd, jsd
3604 type(
grid_type),
pointer,
save :: grid1 =>null()
3605 type(
comm_type),
pointer,
save :: comm =>null()
3606 integer :: buffer_pos, msgsize, from_pe, to_pe, pos, n
3607 integer :: ibegin, count, istart, iend
3608 real :: recv_buffer(xmap%put1%recvsize*lsize*3)
3609 real :: send_buffer(xmap%put1%sendsize*lsize*3)
3610 real :: unpack_buffer(xmap%put1%recvsize*3)
3611 logical :: on_west_edge, on_east_edge, on_south_edge, on_north_edge
3612 real,
dimension(isize, jsize) :: d
3613 real,
dimension(xsize) :: x
3618 grid1 => xmap%grids(1)
3620 is = grid1%is_me; ie = grid1%ie_me
3621 js = grid1%js_me; je = grid1%je_me
3629 tmp(1:isize,1:jsize,l) = d(:,:)
3632 if(grid1%is_latlon)
then 3636 tmpy(:,:,l) =
grad_merid_latlon(tmp(:,:,l), grid1%lat, is, ie, js, je, isd, jsd)
3637 tmpx(:,:,l) =
grad_zonal_latlon(tmp(:,:,l), grid1%lon, grid1%lat, is, ie, js, je, isd, jsd)
3641 on_west_edge = (is==1)
3642 on_east_edge = (ie==grid1%im)
3643 on_south_edge = (js==1)
3644 on_north_edge = (je==grid1%jm)
3648 call gradient_cubic(tmp(:,:,l), grid1%box%dx, grid1%box%dy, grid1%box%area, &
3649 grid1%box%edge_w, grid1%box%edge_e, grid1%box%edge_s, &
3650 grid1%box%edge_n, grid1%box%en1, grid1%box%en2, &
3651 grid1%box%vlon, grid1%box%vlat, tmpx(:,:,l), tmpy(:,:,l), &
3652 on_west_edge, on_east_edge, on_south_edge, on_north_edge)
3659 do p = 1, comm%nrecv
3660 msgsize = comm%recv(p)%count*lsize
3661 buffer_pos = comm%recv(p)%buffer_pos*lsize
3664 buffer_pos = buffer_pos*3
3666 from_pe = comm%recv(p)%pe
3667 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = from_pe, block=.false., tag=comm_tag_8)
3683 if(tmp(i,j,l) > d_bar_max(i,j,l)) d_bar_max(i,j,l) = tmp(i,j,l)
3684 if(tmp(i,j,l) < d_bar_min(i,j,l)) d_bar_min(i,j,l) = tmp(i,j,l)
3697 do p = 1, comm%nsend
3698 msgsize = comm%send(p)%count*lsize
3699 to_pe = comm%send(p)%pe
3702 do n = 1, comm%send(p)%count
3704 i = comm%send(p)%i(n)
3705 j = comm%send(p)%j(n)
3706 send_buffer(pos) = d(i,j) + tmpy(i,j,l)*comm%send(p)%dj(n) + tmpx(i,j,l)*comm%send(p)%di(n)
3707 if(send_buffer(pos) > d_max(i,j,l)) d_max(i,j,l) = send_buffer(pos)
3708 if(send_buffer(pos) < d_min(i,j,l)) d_min(i,j,l) = send_buffer(pos)
3713 do p = 1, comm%nsend
3714 msgsize = comm%send(p)%count*lsize
3715 to_pe = comm%send(p)%pe
3719 do n = 1, comm%send(p)%count
3721 i = comm%send(p)%i(n)
3722 j = comm%send(p)%j(n)
3724 if( d_max(i,j,l) > d_bar_max(i,j,l) )
then 3725 send_buffer(pos) = d_bar + ((send_buffer(pos)-d_bar)/(d_max(i,j,l)-d_bar)) * (d_bar_max(i,j,l)-d_bar)
3726 else if( d_min(i,j,l) < d_bar_min(i,j,l) )
then 3727 send_buffer(pos) = d_bar + ((send_buffer(pos)-d_bar)/(d_min(i,j,l)-d_bar)) * (d_bar_min(i,j,l)-d_bar)
3731 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_8 )
3732 buffer_pos = buffer_pos + msgsize
3735 do p = 1, comm%nsend
3736 msgsize = comm%send(p)%count*lsize*3
3737 to_pe = comm%send(p)%pe
3741 do n = 1, comm%send(p)%count
3743 i = comm%send(p)%i(n)
3744 j = comm%send(p)%j(n)
3745 send_buffer(pos-2) = d(i,j)
3746 send_buffer(pos-1) = tmpy(i,j,l)
3747 send_buffer(pos ) = tmpx(i,j,l)
3750 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_8 )
3751 buffer_pos = buffer_pos + msgsize
3755 call mpp_sync_self(
check=event_recv)
3759 if( lsize == 1)
then 3761 do l=1,xmap%size_put1
3762 pos = xmap%x1_put(l)%pos
3763 x(l) = recv_buffer(pos)
3769 do p = 1, comm%nsend
3770 count = comm%send(p)%count
3771 ibegin = comm%recv(p)%buffer_pos*lsize + 1
3772 istart = ibegin + (l-1)*count
3773 iend = istart + count - 1
3774 pos = comm%recv(p)%buffer_pos
3777 unpack_buffer(pos) = recv_buffer(n)
3780 do i=1,xmap%size_put1
3781 pos = xmap%x1_put(i)%pos
3782 x(i) = unpack_buffer(pos)
3787 if( lsize == 1)
then 3790 do l=1,xmap%size_put1
3791 pos = xmap%x1_put(l)%pos
3792 x(l) = recv_buffer(3*pos-2) + recv_buffer(3*pos-1)*xmap%x1_put(l)%dj + recv_buffer(3*pos)*xmap%x1_put(l)%di
3801 do p = 1, comm%nrecv
3802 count = comm%recv(p)%count*3
3803 ibegin = comm%recv(p)%buffer_pos*lsize*3 + 1
3804 istart = ibegin + (l-1)*count
3805 iend = istart + count - 1
3806 pos = comm%recv(p)%buffer_pos*3
3809 unpack_buffer(pos) = recv_buffer(n)
3812 do i=1,xmap%size_put1
3813 pos = xmap%x1_put(i)%pos
3814 x(i) = unpack_buffer(3*pos-2) + unpack_buffer(3*pos-1)*xmap%x1_put(i)%dj + unpack_buffer(3*pos)*xmap%x1_put(i)%di
3820 call mpp_sync_self()
3827 subroutine get_1_from_xgrid(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3828 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
3829 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
3831 integer,
intent(in) :: isize, jsize, xsize, lsize
3833 real,
dimension(xmap%size),
target :: dg(xmap%size, lsize)
3834 integer :: i, j, l, p, n, m
3835 integer :: msgsize, buffer_pos, pos
3836 integer :: istart, iend, count
3837 real ,
pointer,
save :: dgp =>null()
3838 type(
grid_type) ,
pointer,
save :: grid1 =>null()
3839 type(
comm_type) ,
pointer,
save :: comm =>null()
3840 type(overlap_type),
pointer,
save :: send => null()
3841 type(overlap_type),
pointer,
save :: recv => null()
3842 real :: recv_buffer(xmap%get1%recvsize*lsize*3)
3843 real :: send_buffer(xmap%get1%sendsize*lsize*3)
3844 real :: unpack_buffer(xmap%get1%recvsize*3)
3845 real :: d(isize,jsize)
3846 real,
dimension(xsize) :: x
3853 grid1 => xmap%grids(1)
3855 do p = 1, comm%nrecv
3856 recv => comm%recv(p)
3857 msgsize = recv%count*lsize
3858 buffer_pos = recv%buffer_pos*lsize
3859 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_9)
3867 dgp => dg(xmap%x1(i)%pos,l)
3868 dgp = dgp + xmap%x1(i)%area*x(i)
3876 do p = 1, comm%nsend
3877 send => comm%send(p)
3878 msgsize = send%count*lsize
3880 istart = send%buffer_pos+1
3881 iend = istart + send%count - 1
3885 send_buffer(pos) = dg(n,l)
3888 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = send%pe, tag=comm_tag_9 )
3889 buffer_pos = buffer_pos + msgsize
3893 call mpp_sync_self(
check=event_recv)
3902 do p = 1, comm%nrecv
3903 recv => comm%recv(p)
3905 buffer_pos = recv%buffer_pos*lsize
3906 if( recv%pe == xmap%me )
then 3910 pos = buffer_pos + (l-1)*count
3916 d(i,j) = recv_buffer(pos)
3924 do m = 1, comm%nrecv
3925 p = comm%unpack_ind(m)
3926 recv => comm%recv(p)
3927 if( recv%pe == xmap%me )
then 3930 buffer_pos = recv%buffer_pos*lsize
3934 pos = buffer_pos + (l-1)*recv%count
3936 do n = 1, recv%count
3940 d(i,j) = d(i,j) + recv_buffer(pos)
3951 d = d * grid1%area_inv
3953 call mpp_sync_self()
3961 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
3962 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
3964 integer,
intent(in) :: xsize, lsize
3966 integer :: g, i, j, k, p, l, n, l2, m, l3
3967 integer :: msgsize, buffer_pos, pos
3968 type(
grid_type),
pointer,
save :: grid =>null()
3969 type(comm_type),
pointer,
save :: comm => null()
3970 type(overlap_type),
pointer,
save :: send => null()
3971 type(overlap_type),
pointer,
save :: recv => null()
3972 integer,
dimension(0:xmap%npes-1) :: pl, ml
3973 real :: recv_buffer(xmap%recv_count_repro_tot*lsize)
3974 real :: send_buffer(xmap%send_count_repro_tot*lsize)
3975 real :: d(xmap%grids(1)%is_me:xmap%grids(1)%ie_me, &
3976 xmap%grids(1)%js_me:xmap%grids(1)%je_me)
3977 real,
dimension(xsize) :: x
3982 comm => xmap%get1_repro
3984 do p = 1, comm%nrecv
3985 recv => comm%recv(p)
3986 msgsize = recv%count*lsize
3987 buffer_pos = recv%buffer_pos*lsize
3988 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_10)
3989 n = recv%pe -xmap%root_pe
3995 send_buffer(:) = 0.0
3998 do p = 1, comm%nsend
3999 pos = comm%send(p)%buffer_pos*lsize
4000 send => comm%send(p)
4003 do n = 1, send%count
4009 do k =1, xmap%grids(g)%km
4010 if(xmap%grids(g)%frac_area(i,j,k)/=0.0)
then 4012 send_buffer(pos) = send_buffer(pos) + xmap%x1(l2)%area *x(l2)
4020 buffer_pos = comm%send(p)%buffer_pos*lsize
4021 msgsize = comm%send(p)%count*lsize
4022 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe=comm%send(p)%pe, tag=comm_tag_10)
4030 call mpp_sync_self(
check=event_recv)
4036 do g=2,
size(xmap%grids(:))
4037 grid => xmap%grids(g)
4038 do l3=1,grid%size_repro
4039 i = grid%x_repro(l3)%i1
4040 j = grid%x_repro(l3)%j1
4041 p = grid%x_repro(l3)%pe-xmap%root_pe
4042 pos = pl(p) + (l-1)*ml(p) + grid%x_repro(l3)%recv_pos
4043 d(i,j) = d(i,j) + recv_buffer(pos)
4047 d = d * xmap%grids(1)%area_inv
4050 call mpp_sync_self()
4069 real,
dimension(:,:),
intent(in ) :: d
4070 character(len=3),
intent(in ) :: grid_id
4073 integer,
intent(in),
optional :: remap_method
4076 real,
dimension(xmap%size) :: x_over, x_back
4077 real,
dimension(size(d,1),size(d,2)) :: d1
4078 real,
dimension(:,:,:),
allocatable :: d2
4080 type(
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4082 grid1 => xmap%grids(1)
4088 call put_to_xgrid (d, grid1%id, x_over, xmap, remap_method)
4089 do g=2,
size(xmap%grids(:))
4090 grid2 => xmap%grids(
g)
4091 if(grid2%on_this_pe)
then 4092 allocate (d2(grid2%is_me:grid2%ie_me, grid2%js_me:grid2%je_me, grid2%km) )
4095 if(grid2%on_this_pe)
then 4099 if(
allocated(d2))
deallocate (d2)
4123 real,
dimension(:,:,:),
intent(in ) :: d
4124 character(len=3),
intent(in ) :: grid_id
4127 integer,
intent(in),
optional :: remap_method
4130 real,
dimension(xmap%size) :: x_over, x_back
4131 real,
dimension(:,: ),
allocatable :: d1
4132 real,
dimension(:,:,:),
allocatable :: d2
4134 type(
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4136 grid1 => xmap%grids(1)
4138 do g = 2,
size(xmap%grids(:))
4139 grid2 => xmap%grids(
g)
4140 if (grid_id==grid2%id)
then 4141 if(grid2%on_this_pe)
then 4146 call put_to_xgrid(0.0 * grid2%frac_area, grid2%id, x_over, xmap)
4150 allocate ( d1(
size(grid1%area,1),
size(grid1%area,2)) )
4153 call put_to_xgrid(d1, grid1%id, x_back, xmap,remap_method)
4157 do g = 2,
size(xmap%grids(:))
4158 grid2 => xmap%grids(
g)
4159 if(grid2%on_this_pe)
then 4160 allocate ( d2(
size(grid2%frac_area, 1),
size(grid2%frac_area, 2), &
4161 size(grid2%frac_area, 3) ) )
4165 if(
allocated(d2) )
deallocate ( d2 )
4185 real,
dimension(:,:),
intent(in ) :: d
4186 character(len=3),
intent(in ) :: grid_id
4189 integer,
intent(in),
optional :: remap_method
4192 real,
dimension(xmap%size) :: x_over, x_back
4193 real,
dimension(size(d,1),size(d,2)) :: d1
4194 real,
dimension(:,:,:),
allocatable :: d2
4195 real,
dimension(: ),
allocatable :: d_ug
4196 real,
dimension(:,:),
allocatable :: d2_ug
4198 type(
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4200 grid1 => xmap%grids(1)
4204 if(grid1%is_ug)
then 4205 allocate(d_ug(grid1%ls_me:grid1%le_me))
4211 call put_to_xgrid (d, grid1%id, x_over, xmap, remap_method)
4213 do g=2,
size(xmap%grids(:))
4214 grid2 => xmap%grids(
g)
4215 if(grid2%is_ug)
then 4216 if(grid2%on_this_pe)
then 4217 allocate (d2_ug(grid2%ls_me:grid2%le_me, grid2%km) )
4221 if(grid2%on_this_pe)
then 4223 sum( grid2%area(:,1) * sum(grid2%frac_area(:,1,:)*d2_ug,dim=2) )
4226 if(
allocated(d2_ug))
deallocate (d2_ug)
4228 if(grid2%on_this_pe)
then 4229 allocate (d2(grid2%is_me:grid2%ie_me, grid2%js_me:grid2%je_me, grid2%km) )
4232 if(grid2%on_this_pe)
then 4236 if(
allocated(d2))
deallocate (d2)
4239 if(grid1%is_ug)
then 4246 if(
allocated(d_ug))
deallocate(d_ug)
4265 real,
dimension(:,:,:),
intent(in ) :: d
4266 character(len=3),
intent(in ) :: grid_id
4269 integer,
intent(in),
optional :: remap_method
4272 real,
dimension(xmap%size) :: x_over, x_back
4273 real,
dimension(:,: ),
allocatable :: d1, d_ug
4274 real,
dimension(:,:,:),
allocatable :: d2
4276 type(
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4278 grid1 => xmap%grids(1)
4280 do g = 2,
size(xmap%grids(:))
4281 grid2 => xmap%grids(
g)
4282 if (grid_id==grid2%id)
then 4283 if(grid2%on_this_pe)
then 4284 if(grid2%is_ug)
then 4285 allocate(d_ug(grid2%ls_me:grid2%le_me,grid2%km))
4292 if(grid2%is_ug)
then 4297 if(
allocated(d_ug))
deallocate(d_ug)
4299 if(grid2%is_ug)
then 4300 call put_to_xgrid_ug(0.0 * grid2%frac_area(:,1,:), grid2%id, x_over, xmap)
4302 call put_to_xgrid(0.0 * grid2%frac_area, grid2%id, x_over, xmap)
4307 allocate ( d1(
size(grid1%area,1),
size(grid1%area,2)) )
4308 if(grid1%is_ug)
then 4314 if(grid1%is_ug)
then 4317 call put_to_xgrid(d1, grid1%id, x_back, xmap,remap_method)
4322 do g = 2,
size(xmap%grids(:))
4323 grid2 => xmap%grids(
g)
4324 if(grid2%on_this_pe)
then 4325 allocate ( d2(
size(grid2%frac_area, 1),
size(grid2%frac_area, 2), &
4326 size(grid2%frac_area, 3) ) )
4328 if(grid2%is_ug)
then 4334 if(
allocated(d2) )
deallocate ( d2 )
4345 character(len=3),
intent(in ) :: id
4347 real,
dimension(:,:),
intent(out ) :: area
4352 do g = 1,
size(xmap%grids(:))
4353 if (id==xmap%grids(
g)%id )
then 4354 if(
size(area,1) .NE.
size(xmap%grids(
g)%area,1) .OR.
size(area,2) .NE.
size(xmap%grids(
g)%area,2) ) &
4355 call error_mesg(
"xgrid_mod",
"size mismatch between area and xmap%grids(g)%area", fatal)
4356 area = xmap%grids(
g)%area
4362 if(.not. found)
call error_mesg(
"xgrid_mod", id//
" is not found in xmap%grids id", fatal)
4374 integer,
intent(in) :: isd, jsd
4375 real,
dimension(isd:,jsd:),
intent(in) :: d
4376 real,
dimension(:),
intent(in) :: lon
4377 real,
dimension(:),
intent(in) :: lat
4378 integer,
intent(in) :: is, ie, js, je
4380 real :: dx, costheta
4381 integer :: i, j, ip1, im1
4387 else if(i==
size(lon(:)) )
then 4390 ip1 = i+1; im1 = i-1
4392 dx = lon(ip1) - lon(im1)
4393 if(abs(dx).lt.
eps )
call error_mesg(
'xgrids_mod(grad_zonal_latlon)',
'Improper grid size in lontitude', fatal)
4394 if(dx .gt.
pi) dx = dx - 2.0*
pi 4395 if(dx .lt. -
pi) dx = dx + 2.0*
pi 4397 costheta = cos(lat(j))
4398 if(abs(costheta) .lt.
eps)
call error_mesg(
'xgrids_mod(grad_zonal_latlon)',
'Improper latitude grid', fatal)
4413 integer,
intent(in) :: isd, jsd
4414 real,
dimension(isd:,jsd:),
intent(in) :: d
4415 real,
dimension(:),
intent(in) :: lat
4416 integer,
intent(in) :: is, ie, js, je
4419 integer :: i, j, jp1, jm1
4425 else if(j ==
size(lat(:)) )
then 4428 jp1 = j+1; jm1 = j-1
4430 dy = lat(jp1) - lat(jm1)
4431 if(abs(dy).lt.
eps)
call error_mesg(
'xgrids_mod(grad_merid_latlon)',
'Improper grid size in latitude', fatal)
4445 integer,
intent(in) :: grid_index
4446 integer,
intent(out) :: is, ie, js, je, km
4448 is = xmap % grids(grid_index) % is_me
4449 ie = xmap % grids(grid_index) % ie_me
4450 js = xmap % grids(grid_index) % js_me
4451 je = xmap % grids(grid_index) % je_me
4452 km = xmap % grids(grid_index) % km
4457 subroutine stock_move_3d(from, to, grid_index, data, xmap, &
4458 & delta_t, from_side, to_side, radius, verbose, ier)
4468 type(stock_type),
intent(inout),
optional :: from, to
4469 integer,
intent(in) :: grid_index
4470 real,
intent(in) :: data(:,:,:)
4471 type(xmap_type),
intent(in) :: xmap
4472 real,
intent(in) :: delta_t
4473 integer,
intent(in) :: from_side, to_side
4474 real,
intent(in) :: radius
4475 character(len=*),
intent(in),
optional :: verbose
4476 integer,
intent(out) :: ier
4478 real :: from_dq, to_dq
4481 if(grid_index == 1)
then 4487 if(.not.
associated(xmap%grids) )
then 4492 from_dq = delta_t * 4.0*
pi*radius**2 * sum( sum(xmap%grids(grid_index)%area * &
4493 & sum(xmap%grids(grid_index)%frac_area *
data, dim=3), dim=1))
4497 if(
present(to )) to % dq( to_side) = to % dq( to_side) + to_dq
4498 if(
present(from)) from % dq(from_side) = from % dq(from_side) - from_dq
4503 from_dq = from_dq/(4.0*
pi*radius**2)
4504 to_dq = to_dq /(4.0*
pi*radius**2)
4505 if(mpp_pe()==mpp_root_pe())
then 4506 write(
stocks_file,
'(a,es19.12,a,es19.12,a)') verbose, from_dq,
' [*/m^2]' 4514 subroutine stock_move_2d(from, to, grid_index, data, xmap, &
4515 & delta_t, from_side, to_side, radius, verbose, ier)
4524 type(stock_type),
intent(inout),
optional :: from, to
4525 integer,
optional,
intent(in) :: grid_index
4526 real,
intent(in) :: data(:,:)
4527 type(xmap_type),
intent(in) :: xmap
4528 real,
intent(in) :: delta_t
4529 integer,
intent(in) :: from_side, to_side
4530 real,
intent(in) :: radius
4531 character(len=*),
intent(in) :: verbose
4532 integer,
intent(out) :: ier
4534 real :: to_dq, from_dq
4538 if(.not.
associated(xmap%grids) )
then 4543 if( .not.
present(grid_index) .or. grid_index==1 )
then 4546 from_dq = delta_t * 4.0*
pi*radius**2 * sum(sum(xmap%grids(1)%area *
data, dim=1))
4557 if(
present(to )) to % dq( to_side) = to % dq( to_side) + to_dq
4558 if(
present(from)) from % dq(from_side) = from % dq(from_side) - from_dq
4563 from_dq = from_dq/(4.0*
pi*radius**2)
4564 to_dq = to_dq /(4.0*
pi*radius**2)
4565 if(mpp_pe()==mpp_root_pe())
then 4566 write(
stocks_file,
'(a,es19.12,a,es19.12,a)') verbose, from_dq,
' [*/m^2]' 4575 & delta_t, from_side, to_side, radius, verbose, ier)
4585 type(stock_type),
intent(inout),
optional :: from, to
4586 integer,
intent(in) :: grid_index
4587 real,
intent(in) :: data(:,:)
4588 type(xmap_type),
intent(in) :: xmap
4589 real,
intent(in) :: delta_t
4590 integer,
intent(in) :: from_side, to_side
4591 real,
intent(in) :: radius
4592 character(len=*),
intent(in),
optional :: verbose
4593 integer,
intent(out) :: ier
4594 real,
dimension(size(data,1),size(data,2)) :: tmp
4596 real :: from_dq, to_dq
4599 if(grid_index == 1)
then 4605 if(.not.
associated(xmap%grids) )
then 4610 tmp = xmap%grids(grid_index)%frac_area(:,1,:) *
data 4611 from_dq = delta_t * 4.0*
pi*radius**2 * sum( xmap%grids(grid_index)%area(:,1) * &
4616 if(
present(to )) to % dq( to_side) = to % dq( to_side) + to_dq
4617 if(
present(from)) from % dq(from_side) = from % dq(from_side) - from_dq
4622 from_dq = from_dq/(4.0*
pi*radius**2)
4623 to_dq = to_dq /(4.0*
pi*radius**2)
4624 if(mpp_pe()==mpp_root_pe())
then 4625 write(
stocks_file,
'(a,es19.12,a,es19.12,a)') verbose, from_dq,
' [*/m^2]' 4640 real,
intent(in) :: data(:,:)
4642 real,
intent(in) :: delta_t
4643 real,
intent(in) ::
radius 4644 real,
intent(out) :: res
4645 integer,
intent(out) :: ier
4650 if(.not.
associated(xmap%grids) )
then 4655 res = delta_t * 4.0*
pi*
radius**2 * sum(sum(xmap%grids(1)%area *
data, dim=1))
4664 subroutine stock_print(stck, Time, comp_name, index, ref_value, radius, pelist)
4672 character(len=*) :: comp_name
4673 integer,
intent(in) :: index
4674 real,
intent(in) :: ref_value
4675 real,
intent(in) ::
radius 4676 integer,
intent(in),
optional :: pelist(:)
4678 integer,
parameter :: initid = -2
4682 real :: f_value, c_value, planet_area
4683 character(len=80) :: formatstring
4684 integer :: iday, isec, hours
4685 integer :: diagid, compind
4686 integer,
dimension(NELEMS,4),
save :: f_valuediagid = initid
4687 integer,
dimension(NELEMS,4),
save :: c_valuediagid = initid
4688 integer,
dimension(NELEMS,4),
save :: fmc_valuediagid = initid
4692 character(len=30) :: field_name, units
4694 f_value = sum(stck % dq)
4695 c_value = ref_value - stck % q_start
4696 if(
present(pelist))
then 4697 call mpp_sum(f_value, pelist=pelist)
4698 call mpp_sum(c_value, pelist=pelist)
4704 if(mpp_pe() == mpp_root_pe())
then 4707 f_value = f_value / planet_area
4708 c_value = c_value / planet_area
4710 if(comp_name ==
'ATM') compind = 1
4711 if(comp_name ==
'LND') compind = 2
4712 if(comp_name ==
'ICE') compind = 3
4713 if(comp_name ==
'OCN') compind = 4
4716 if(f_valuediagid(index,compind) == initid)
then 4717 field_name = trim(comp_name) // trim(
stock_names(index))
4718 field_name = trim(field_name) //
'StocksChange_Flux' 4724 if(c_valuediagid(index,compind) == initid)
then 4725 field_name = trim(comp_name) // trim(
stock_names(index))
4726 field_name = trim(field_name) //
'StocksChange_Comp' 4732 if(fmc_valuediagid(index,compind) == initid)
then 4733 field_name = trim(comp_name) // trim(
stock_names(index))
4734 field_name = trim(field_name) //
'StocksChange_Diff' 4740 diagid=f_valuediagid(index,compind)
4742 if (diagid > 0) used =
send_data(diagid, diagfield, time)
4743 diagid=c_valuediagid(index,compind)
4745 if (diagid > 0) used =
send_data(diagid, diagfield, time)
4746 diagid=fmc_valuediagid(index,compind)
4747 diagfield = f_value-c_value
4748 if (diagid > 0) used =
send_data(diagid, diagfield, time)
4752 hours = iday*24 + isec/3600
4753 formatstring =
'(a,a,a,i16,2x,es22.15,2x,es22.15,2x,es22.15)' 4755 ,hours,f_value,c_value,f_value-c_value
4765 real,
dimension(:,:),
intent(in) :: lon, lat
4767 integer :: i, j, nlon, nlat, num
4772 loop_lat:
do j = 1, nlat
4774 if(lat(i,j) .NE. lat(1,j))
then 4782 loop_lon:
do i = 1, nlon
4784 if(lon(i,j) .NE. lon(i,1))
then 4813 real,
dimension(:),
intent( out) :: d
4814 character(len=3),
intent(in ) :: grid_id
4815 real,
dimension(:),
intent(in ) :: x
4817 logical,
intent(in),
optional :: complete
4819 logical :: is_complete, set_mismatch
4821 character(len=2) :: text
4822 integer,
save :: isize=0
4823 integer,
save :: lsize=0
4824 integer,
save :: xsize=0
4825 character(len=3),
save :: grid_id_saved=
"" 4826 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: d_addrs=-9999
4827 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: x_addrs=-9999
4829 if (grid_id==xmap%grids(1)%id)
then 4830 is_complete = .true.
4831 if(
present(complete)) is_complete=complete
4835 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group get_side1_from_xgrid_ug', fatal)
4837 d_addrs(lsize) = loc(d)
4838 x_addrs(lsize) = loc(x)
4843 grid_id_saved = grid_id
4845 set_mismatch = .false.
4846 set_mismatch = set_mismatch .OR. (isize /=
size(d(:)))
4847 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
4848 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
4849 if(set_mismatch)
then 4850 write( text,
'(i2)' ) lsize
4851 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text//
' for group get_side1_from_xgrid_ug', fatal )
4855 if(is_complete)
then 4861 d_addrs(1:lsize) = -9999
4862 x_addrs(1:lsize) = -9999
4871 do g=2,
size(xmap%grids(:))
4872 if (grid_id==xmap%grids(g)%id) &
4874 'get_from_xgrid_ug expects a 3D side 2 grid', fatal)
4877 call error_mesg (
'xgrid_mod',
'get_from_xgrid_ug: could not find grid id', fatal)
4892 real,
dimension(:),
intent(in ) :: d
4893 character(len=3),
intent(in ) :: grid_id
4894 real,
dimension(:),
intent(inout) :: x
4896 logical,
intent(in),
optional :: complete
4898 logical :: is_complete, set_mismatch
4900 character(len=2) :: text
4901 integer,
save :: dsize=0
4902 integer,
save :: lsize=0
4903 integer,
save :: xsize=0
4904 character(len=3),
save :: grid_id_saved=
"" 4905 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: d_addrs=-9999
4906 integer(LONG_KIND),
dimension(MAX_FIELDS),
save :: x_addrs=-9999
4908 if (grid_id==xmap%grids(1)%id)
then 4909 is_complete = .true.
4910 if(
present(complete)) is_complete=complete
4914 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group put_side1_to_xgrid_ug', fatal)
4916 d_addrs(lsize) = loc(d)
4917 x_addrs(lsize) = loc(x)
4922 grid_id_saved = grid_id
4924 set_mismatch = .false.
4925 set_mismatch = set_mismatch .OR. (dsize /=
size(d(:)))
4926 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
4927 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
4928 if(set_mismatch)
then 4929 write( text,
'(i2)' ) lsize
4930 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text//
' for group put_side1_to_xgrid_ug', fatal )
4934 if(is_complete)
then 4936 d_addrs(1:lsize) = -9999
4937 x_addrs(1:lsize) = -9999
4946 do g=2,
size(xmap%grids(:))
4947 if (grid_id==xmap%grids(g)%id) &
4949 'put_to_xgrid_ug expects a 2D side 2 grid', fatal)
4952 call error_mesg (
'xgrid_mod',
'put_to_xgrid_ug: could not find grid id', fatal)
4966 real,
dimension(:,:),
intent(in ) :: d
4967 character(len=3),
intent(in ) :: grid_id
4968 real,
dimension(:),
intent(inout) :: x
4973 if (grid_id==xmap%grids(1)%id) &
4975 'put_to_xgrid_ug expects a 2D side 1 grid', fatal)
4977 do g=2,
size(xmap%grids(:))
4978 if (grid_id==xmap%grids(g)%id)
then 4984 call error_mesg (
'xgrid_mod',
'put_to_xgrid_ug: could not find grid id', fatal)
4998 real,
dimension(:,:),
intent( out) :: d
4999 character(len=3),
intent(in ) :: grid_id
5000 real,
dimension(:),
intent(in ) :: x
5005 if (grid_id==xmap%grids(1)%id) &
5007 'get_from_xgrid_ug expects a 2D side 1 grid', fatal)
5009 do g=2,
size(xmap%grids(:))
5010 if (grid_id==xmap%grids(g)%id)
then 5016 call error_mesg (
'xgrid_mod',
'get_from_xgrid_ug: could not find grid id', fatal)
5025 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
5026 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
5028 integer,
intent(in) :: dsize, xsize, lsize
5030 integer :: i, j, p, buffer_pos, msgsize
5031 integer :: from_pe, to_pe, pos, n, l, count
5032 integer :: ibegin, istart, iend, start_pos
5033 type(
comm_type),
pointer,
save :: comm =>null()
5034 real :: recv_buffer(xmap%put1%recvsize*lsize)
5035 real :: send_buffer(xmap%put1%sendsize*lsize)
5036 real :: unpack_buffer(xmap%put1%recvsize)
5038 real,
dimension(dsize) :: d
5039 real,
dimension(xsize) :: x
5048 do p = 1, comm%nrecv
5049 msgsize = comm%recv(p)%count*lsize
5050 from_pe = comm%recv(p)%pe
5051 buffer_pos = comm%recv(p)%buffer_pos*lsize
5052 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = from_pe, block=.false., tag=comm_tag_7)
5057 do p = 1, comm%nsend
5058 msgsize = comm%send(p)%count*lsize
5059 to_pe = comm%send(p)%pe
5063 do n = 1, comm%send(p)%count
5065 lll = comm%send(p)%i(n)
5066 send_buffer(pos) = d(lll)
5069 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_7 )
5070 buffer_pos = buffer_pos + msgsize
5073 call mpp_sync_self(
check=event_recv)
5076 if( lsize == 1)
then 5078 do l=1,xmap%size_put1
5079 x(l) = recv_buffer(xmap%x1_put(l)%pos)
5087 do p = 1, comm%nrecv
5088 count = comm%recv(p)%count
5089 ibegin = comm%recv(p)%buffer_pos*lsize + 1
5090 istart = ibegin + (l-1)*count
5091 iend = istart + count - 1
5092 pos = comm%recv(p)%buffer_pos
5095 unpack_buffer(pos) = recv_buffer(n)
5098 do i=1,xmap%size_put1
5099 x(i) = unpack_buffer(xmap%x1_put(i)%pos)
5104 call mpp_sync_self()
5114 real,
dimension(grid%ls_me:grid%le_me, grid%km),
intent(in) :: d
5115 real,
dimension(: ),
intent(inout) :: x
5121 do l=grid%first,grid%last
5122 x(l) = d(xmap%x2(l)%l,xmap%x2(l)%k)
5130 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
5131 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
5133 integer,
intent(in) :: isize, xsize, lsize
5135 real,
dimension(xmap%size),
target :: dg(xmap%size, lsize)
5136 integer :: i, j, l, p, n, m
5137 integer :: msgsize, buffer_pos, pos
5138 integer :: istart, iend, count
5139 real ,
pointer,
save :: dgp =>null()
5140 type(
grid_type) ,
pointer,
save :: grid1 =>null()
5141 type(
comm_type) ,
pointer,
save :: comm =>null()
5142 type(overlap_type),
pointer,
save :: send => null()
5143 type(overlap_type),
pointer,
save :: recv => null()
5144 real :: recv_buffer(xmap%get1%recvsize*lsize*3)
5145 real :: send_buffer(xmap%get1%sendsize*lsize*3)
5146 real :: unpack_buffer(xmap%get1%recvsize*3)
5148 real,
dimension(xsize) :: x
5155 grid1 => xmap%grids(1)
5157 do p = 1, comm%nrecv
5158 recv => comm%recv(p)
5159 msgsize = recv%count*lsize
5160 buffer_pos = recv%buffer_pos*lsize
5161 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_9)
5169 dgp => dg(xmap%x1(i)%pos,l)
5170 dgp = dgp + xmap%x1(i)%area*x(i)
5178 do p = 1, comm%nsend
5179 send => comm%send(p)
5180 msgsize = send%count*lsize
5182 istart = send%buffer_pos+1
5183 iend = istart + send%count - 1
5187 send_buffer(pos) = dg(n,l)
5190 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = send%pe, tag=comm_tag_9 )
5191 buffer_pos = buffer_pos + msgsize
5195 call mpp_sync_self(
check=event_recv)
5204 do p = 1, comm%nrecv
5205 recv => comm%recv(p)
5207 buffer_pos = recv%buffer_pos*lsize
5208 if( recv%pe == xmap%me )
then 5212 pos = buffer_pos + (l-1)*count
5217 d(i) = recv_buffer(pos)
5225 do m = 1, comm%nrecv
5226 p = comm%unpack_ind(m)
5227 recv => comm%recv(p)
5228 if( recv%pe == xmap%me )
then 5231 buffer_pos = recv%buffer_pos*lsize
5235 pos = buffer_pos + (l-1)*recv%count
5237 do n = 1, recv%count
5240 d(i) = d(i) + recv_buffer(pos)
5251 d = d * grid1%area_inv(:,1)
5253 call mpp_sync_self()
5261 integer(LONG_KIND),
dimension(:),
intent(in) :: d_addrs
5262 integer(LONG_KIND),
dimension(:),
intent(in) :: x_addrs
5264 integer,
intent(in) :: xsize, lsize
5266 integer :: g, i, j, k, p, l, n, l2, m, l3
5267 integer :: msgsize, buffer_pos, pos
5268 type(
grid_type),
pointer,
save :: grid =>null()
5269 type(comm_type),
pointer,
save :: comm => null()
5270 type(overlap_type),
pointer,
save :: send => null()
5271 type(overlap_type),
pointer,
save :: recv => null()
5272 integer,
dimension(0:xmap%npes-1) :: pl, ml
5273 real :: recv_buffer(xmap%recv_count_repro_tot*lsize)
5274 real :: send_buffer(xmap%send_count_repro_tot*lsize)
5275 real :: d(xmap%grids(1)%ls_me:xmap%grids(1)%le_me)
5276 real,
dimension(xsize) :: x
5281 comm => xmap%get1_repro
5283 do p = 1, comm%nrecv
5284 recv => comm%recv(p)
5285 msgsize = recv%count*lsize
5286 buffer_pos = recv%buffer_pos*lsize
5287 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_10)
5288 n = recv%pe -xmap%root_pe
5294 send_buffer(:) = 0.0
5297 do p = 1, comm%nsend
5298 pos = comm%send(p)%buffer_pos*lsize
5299 send => comm%send(p)
5302 do n = 1, send%count
5308 do k =1, xmap%grids(g)%km
5309 if(xmap%grids(g)%frac_area(i,j,k)/=0.0)
then 5311 send_buffer(pos) = send_buffer(pos) + xmap%x1(l2)%area *x(l2)
5319 buffer_pos = comm%send(p)%buffer_pos*lsize
5320 msgsize = comm%send(p)%count*lsize
5321 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe=comm%send(p)%pe, tag=comm_tag_10)
5329 call mpp_sync_self(
check=event_recv)
5335 do g=2,
size(xmap%grids(:))
5336 grid => xmap%grids(g)
5337 do l3=1,grid%size_repro
5338 i = grid%x_repro(l3)%l1
5339 p = grid%x_repro(l3)%pe-xmap%root_pe
5340 pos = pl(p) + (l-1)*ml(p) + grid%x_repro(l3)%recv_pos
5341 d(i) = d(i) + recv_buffer(pos)
5345 d = d * xmap%grids(1)%area_inv(:,1)
5348 call mpp_sync_self()
5358 real,
dimension(grid%ls_me:grid%le_me, grid%km),
intent(out) :: d
5359 real,
dimension(:),
intent(in ) :: x
5367 do l=grid%first_get,grid%last_get
5368 d(xmap%x2_get(l)%l,xmap%x2_get(l)%k) = &
5369 d(xmap%x2_get(l)%l,xmap%x2_get(l)%k) + xmap%x2_get(l)%area*x(xmap%x2_get(l)%pos)
5375 d(:,k) = d(:,k) * grid%area_inv(:,1)
5384 integer,
intent(in) :: i, j
5389 g = (j-1)*grid%ni + i
5392 in_box_me = (i>=grid%is_me) .and. (i<=grid%ie_me) .and. (j>=grid%js_me) .and. (j<=grid%je_me)
5399 integer,
intent(in) :: i, j, p
5404 g = (j-1)*grid%ni + i
5407 in_box_nbr = (i>=grid%is(p)) .and. (i<=grid%ie(p)) .and. (j>=grid%js(p)) .and. (j<=grid%je(p))
5446 type(
xmap_type) :: xmap_sfc, xmap_runoff
5447 integer :: npes, pe, root, i, nx, ny, ier
5448 integer :: patm_beg, patm_end, pocn_beg, pocn_end
5449 integer :: is, ie, js, je, km, index_ice, index_lnd
5450 integer :: layout(2)
5452 & Lnd_stock(NELEMS), Ocn_stock(NELEMS)
5453 type(
domain2d) :: atm_domain, ice_domain, lnd_domain, ocn_domain
5454 logical,
pointer :: maskmap(:,:)
5455 real,
allocatable :: data2d(:,:), data3d(:,:,:)
5456 real :: dt, dq_tot_atm, dq_tot_ice, dq_tot_lnd, dq_tot_ocn
5464 root = mpp_root_pe()
5466 patm_end = npes/2 - 1
5467 pocn_beg = patm_end + 1
5470 if(npes /= 30)
call mpp_error(fatal,
'must run unit test on 30 pes')
5472 call mpp_domains_init
5474 call mpp_declare_pelist( (/ (i, i=patm_beg, patm_end) /),
'atm_lnd_ice pes' )
5475 call mpp_declare_pelist( (/ (i, i=pocn_beg, pocn_end) /),
'ocn pes' )
5484 call mpp_set_current_pelist( (/ (i, i=patm_beg, patm_end) /) )
5491 & xflags = cyclic_global_domain, name =
'LAND MODEL' )
5506 call setup_xmap(xmap_sfc, (/
'ATM',
'OCN',
'LND' /), &
5507 & (/ atm_domain, ice_domain, lnd_domain /), &
5508 &
"INPUT/grid_spec.nc")
5519 call get_index_range(xmap=xmap_sfc, grid_index=i, is=is, ie=ie, js=js, je=je, km=km)
5521 allocate(data3d(is:ie, js:je, km))
5522 data3d(:,:,1 ) = 1.0/(4.0*
pi)
5523 data3d(:,:,2:km) = 0.0
5525 & grid_index=i, data=data3d, xmap=xmap_sfc, &
5533 call get_index_range(xmap=xmap_sfc, grid_index=i, is=is, ie=ie, js=js, je=je, km=km)
5535 allocate(data3d(is:ie, js:je, km))
5536 data3d(:,:,1 ) = 1.0/(4.0*
pi)
5537 data3d(:,:,2:km) = 0.0
5539 & grid_index=i, data=data3d, xmap=xmap_sfc, &
5545 call mpp_set_current_pelist( (/ (i, i=pocn_beg, pocn_end) /) )
5559 if( pe < pocn_beg )
then 5561 call get_index_range(xmap=xmap_sfc, grid_index=i, is=is, ie=ie, js=js, je=je, km=km)
5563 allocate(data3d(is:ie, js:je, km))
5564 data3d(:,:,1 ) = 1.0/(4.0*
pi)
5565 data3d(:,:,2:km) = 0.0
5572 allocate(data3d(is:ie, js:je, km))
5576 & grid_index=i, data=data3d(:,:,1), xmap=xmap_sfc, &
5595 write(*,
'(a,4f10.7,a,e10.2)')
' Total delta_q(water) Atm/Lnd/Ice/Ocn: ', &
5596 & dq_tot_atm, dq_tot_lnd, dq_tot_ice, dq_tot_ocn, &
5597 &
' residue: ', dq_tot_atm + dq_tot_lnd + dq_tot_ice + dq_tot_ocn
5604
subroutine, public get_mosaic_contact(mosaic_file, tile1, tile2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2)
real, parameter, public radius
Radius of the Earth [m].
subroutine get_1_from_xgrid_ug_repro(d_addrs, x_addrs, xmap, xsize, lsize)
subroutine put_2_to_xgrid_ug(d, grid, x, xmap)
subroutine load_xgrid(xmap, grid, grid_file, grid1_id, grid_id, tile1, tile2, use_higher_order)
integer id_put_1_to_xgrid_order_2
character(len=64) interp_method
real function, dimension(3) conservation_check_ug_side1(d, grid_id, xmap, remap_method)
subroutine put_1_to_xgrid_order_2(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
logical make_exchange_reproduce
real, dimension(:,:), allocatable, public area_atm_model
logical monotonic_exchange
subroutine check(action, status)
real(kind=kind_real), parameter g
gravity (m^2 s^{-2})
integer id_put_1_to_xgrid_order_1
subroutine get_2_from_xgrid_ug(d, grid, x, xmap)
subroutine stock_move_2d(from, to, grid_index, data, xmap, delta_t, from_side, to_side, radius, verbose, ier)
real, dimension(:,:), allocatable, public area_ocn_sphere
integer, parameter, public istock_heat
integer, parameter, public istock_bottom
integer function, public get_mosaic_ntiles(mosaic_file)
integer id_put_2_to_xgrid
subroutine get_area_elements(file, name, domain, data)
character(len=12), dimension(nelems), parameter stock_units
subroutine, public get_ocean_model_area_elements(domain, grid_file)
integer id_get_1_from_xgrid_repro
subroutine put_side2_to_xgrid_ug(d, grid_id, x, xmap)
integer function, public check_nml_error(IOSTAT, NML_NAME)
integer, parameter, public first_order
integer, parameter, public istock_top
integer, parameter, public nelems
subroutine, public get_mosaic_grid_sizes(mosaic_file, nx, ny)
real, dimension(:,:), allocatable area_lnd_model
integer, parameter, public second_order
integer, parameter, public istock_side
subroutine get_side1_from_xgrid(d, grid_id, x, xmap, complete)
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file
integer function get_nest_contact(mosaic_file, tile_nest_out, tile_parent_out, is_nest_out, ie_nest_out, js_nest_out, je_nest_out, is_parent_out, ie_parent_out, js_parent_out, je_parent_out)
subroutine, public get_mosaic_xgrid(xgrid_file, i1, j1, i2, j2, area, ibegin, iend)
subroutine set_frac_area_sg(f, grid_id, xmap)
subroutine put_side2_to_xgrid(d, grid_id, x, xmap)
real, dimension(:,:), allocatable, public area_ocn_model
integer, public stocks_file
subroutine get_1_from_xgrid(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
int field_exist(const char *file, const char *name)
subroutine, public fms_init(localcomm)
real function, dimension(is:ie, js:je) grad_merid_latlon(d, lat, is, ie, js, je, isd, jsd)
subroutine, public stock_print(stck, Time, comp_name, index, ref_value, radius, pelist)
subroutine put_side1_to_xgrid_ug(d, grid_id, x, xmap, complete)
subroutine stock_move_3d(from, to, grid_index, data, xmap, delta_t, from_side, to_side, radius, verbose, ier)
subroutine get_side1_from_xgrid_ug(d, grid_id, x, xmap, complete)
logical function in_box(i, j, is, ie, js, je)
logical function in_box_me(i, j, grid)
subroutine get_2_from_xgrid(d, grid, x, xmap)
integer id_get_1_from_xgrid
logical function is_lat_lon(lon, lat)
subroutine put_1_to_xgrid_ug_order_1(d_addrs, x_addrs, xmap, dsize, xsize, lsize)
subroutine, public stock_integrate_2d(data, xmap, delta_t, radius, res, ier)
subroutine, public get_index_range(xmap, grid_index, is, ie, js, je, km)
real function, dimension(is:ie, js:je) grad_zonal_latlon(d, lon, lat, is, ie, js, je, isd, jsd)
integer, parameter version1
character(len=5), dimension(nelems), parameter stock_names
real function, dimension(3) conservation_check_side1(d, grid_id, xmap, remap_method)
integer function, public get_mosaic_ncontacts(mosaic_file)
subroutine, public setup_xmap(xmap, grid_ids, grid_domains, grid_file, atm_grid, lnd_ug_domain)
integer, parameter, public istock_water
integer id_get_2_from_xgrid
subroutine get_side2_from_xgrid_ug(d, grid_id, x, xmap)
************************************************************************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 id_conservation_check
real, parameter large_number
subroutine get_side2_from_xgrid(d, grid_id, x, xmap)
logical module_is_initialized
subroutine get_1_from_xgrid_repro(d_addrs, x_addrs, xmap, xsize, lsize)
subroutine put_side1_to_xgrid(d, grid_id, x, xmap, remap_method, complete)
subroutine set_comm_put1(xmap)
subroutine put_1_to_xgrid_order_1(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
integer function, public xgrid_count(xmap)
subroutine, public gradient_cubic(pin, dx, dy, area, edge_w, edge_e, edge_s, edge_n, en_n, en_e, vlon, vlat, grad_x, grad_y, on_west_edge, on_east_edge, on_south_edge, on_north_edge)
integer function, public get_mosaic_xgrid_size(xgrid_file)
logical function in_box_nbr(i, j, grid, p)
real function, dimension(3) conservation_check_ug_side2(d, grid_id, xmap, remap_method)
integer, parameter version2
real, dimension(:,:), allocatable area_lnd_sphere
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
subroutine, public xgrid_init(remap_method)
subroutine, public error_mesg(routine, message, level)
subroutine, public some(xmap, some_arr, grid_id)
subroutine, public get_xmap_grid_area(id, xmap, area)
subroutine set_comm_get1_repro(xmap)
integer, parameter max_fields
subroutine set_comm_get1(xmap)
real function, dimension(3) conservation_check_side2(d, grid_id, xmap, remap_method)
subroutine get_1_from_xgrid_ug(d_addrs, x_addrs, xmap, isize, xsize, lsize)
real, dimension(:,:), allocatable, public area_atm_sphere
subroutine stock_move_ug_3d(from, to, grid_index, data, xmap, delta_t, from_side, to_side, radius, verbose, ier)
subroutine put_2_to_xgrid(d, grid, x, xmap)
subroutine, public set_frac_area_ug(f, grid_id, xmap)
real(fp), parameter, public pi