102 mpp_clock_begin, mpp_clock_end, mpp_clock_sync, &
103 comm_tag_1, comm_tag_2, comm_tag_3, comm_tag_4, &
104 comm_tag_5, comm_tag_6, comm_tag_7, comm_tag_8, &
105 comm_tag_9, comm_tag_10
117 domainug, mpp_get_ug_compute_domains, &
118 mpp_get_ug_domains_index, mpp_get_ug_domain_grid_index, &
120 use constants_mod,
only: pi, radius
125 use stock_constants_mod,
only: istock_top, istock_bottom, istock_side, stock_names, &
127 use gradient_mod,
only: gradient_cubic
129 use fms2_io_mod,
only: fmsnetcdfdomainfile_t,
read_data, get_dimension_size
130 use fms2_io_mod,
only: get_variable_units, dimension_exists
131 use platform_mod,
only: r8_kind, i8_kind, fms_file_len
145 integer,
parameter :: FIRST_ORDER = 1
146 integer,
parameter :: SECOND_ORDER = 2
149 integer,
parameter :: max_fields = 100
156 logical :: debug_stocks = .false.
157 logical :: xgrid_clocks_on = .false.
158 logical :: monotonic_exchange = .false.
166 logical :: do_alltoall = .true.
167 logical :: do_alltoallv = .false.
170 monotonic_exchange,
nsubset, do_alltoall, do_alltoallv
175 real(r8_kind),
allocatable,
dimension(:,:) ::
area_atm_model, area_lnd_model, area_ocn_model
177 real(r8_kind),
allocatable,
dimension(:,:) ::
area_atm_sphere, area_lnd_sphere, area_ocn_sphere
212 module procedure put_side2_to_xgrid_ug
220 module procedure get_side2_from_xgrid_ug
221 module procedure get_side1_from_xgrid_ug
274 real(r8_kind) :: area
279 real(r8_kind) :: scale
285 real(r8_kind),
dimension(:,:),
pointer :: dx => null()
286 real(r8_kind),
dimension(:,:),
pointer :: dy => null()
287 real(r8_kind),
dimension(:,:),
pointer :: area => null()
288 real(r8_kind),
dimension(:),
pointer :: edge_w => null()
289 real(r8_kind),
dimension(:),
pointer :: edge_e => null()
290 real(r8_kind),
dimension(:),
pointer :: edge_s => null()
291 real(r8_kind),
dimension(:),
pointer :: edge_n => null()
292 real(r8_kind),
dimension(:,:,:),
pointer :: en1 => null()
293 real(r8_kind),
dimension(:,:,:),
pointer :: en2 => null()
294 real(r8_kind),
dimension(:,:,:),
pointer :: vlon => null()
295 real(r8_kind),
dimension(:,:,:),
pointer :: vlat => null()
301 character(len=3) :: id
303 logical :: on_this_pe
305 integer,
pointer,
dimension(:) :: pelist
309 integer,
pointer,
dimension(:) :: tile =>null()
310 integer,
pointer,
dimension(:) :: is =>null()
311 integer,
pointer,
dimension(:) :: ie =>null()
312 integer,
pointer,
dimension(:) :: js =>null()
313 integer,
pointer,
dimension(:) :: je =>null()
314 integer,
pointer :: is_me =>null()
315 integer,
pointer :: ie_me =>null()
316 integer,
pointer :: js_me =>null()
317 integer,
pointer :: je_me =>null()
326 integer,
pointer :: tile_me
330 real(r8_kind),
pointer,
dimension(:) :: lon =>null()
331 real(r8_kind),
pointer,
dimension(:) :: lat =>null()
332 real(r8_kind),
pointer,
dimension(:,:) :: geolon=>null()
333 real(r8_kind),
pointer,
dimension(:,:) :: geolat=>null()
334 real(r8_kind),
pointer,
dimension(:,:,:) :: frac_area =>null()
335 real(r8_kind),
pointer,
dimension(:,:) :: area =>null()
336 real(r8_kind),
pointer,
dimension(:,:) :: area_inv =>null()
343 integer :: size_repro
352 integer,
pointer :: ls_me =>null()
353 integer,
pointer :: le_me =>null()
354 integer,
pointer,
dimension(:) :: ls =>null(), le =>null()
355 integer,
pointer :: gs_me =>null(), ge_me =>null()
356 integer,
pointer,
dimension(:) :: gs =>null(), ge =>null()
357 integer,
pointer,
dimension(:) :: l_index =>null()
366 real(r8_kind) :: area
377 integer :: i, j, l, k, pos
378 real(r8_kind) :: area
387 integer :: buffer_pos
388 integer,
allocatable :: i(:)
389 integer,
allocatable :: j(:)
390 integer,
allocatable :: g(:)
391 integer,
allocatable :: xLoc(:)
392 integer,
allocatable :: tile(:)
393 real(r8_kind),
allocatable :: di(:)
394 real(r8_kind),
allocatable :: dj(:)
400 integer :: nsend, nrecv
401 integer :: sendsize, recvsize
402 integer,
pointer,
dimension(:) :: unpack_ind=>null()
403 type(overlap_type),
pointer,
dimension(:) :: send=>null()
404 type(overlap_type),
pointer,
dimension(:) :: recv=>null()
414 integer :: me, npes, root_pe
415 logical,
pointer,
dimension(:) :: your1my2 =>null()
418 logical,
pointer,
dimension(:) :: your2my1 =>null()
421 integer,
pointer,
dimension(:) :: your2my1_size=>null()
426 type (
grid_type),
pointer,
dimension(:) :: grids =>null()
431 type(
x1_type),
pointer,
dimension(:) :: x1 =>null()
432 type(
x1_type),
pointer,
dimension(:) :: x1_put =>null()
433 type(
x2_type),
pointer,
dimension(:) :: x2 =>null()
434 type(
x2_type),
pointer,
dimension(:) :: x2_get =>null()
436 integer,
pointer,
dimension(:) :: send_count_repro =>null()
437 integer,
pointer,
dimension(:) :: recv_count_repro =>null()
438 integer :: send_count_repro_tot
439 integer :: recv_count_repro_tot
442 integer,
pointer,
dimension(:) :: ind_get1 =>null()
443 integer,
pointer,
dimension(:) :: ind_put1 =>null()
453 #include<file_version.h>
455 real(r8_kind),
parameter :: eps = 1.0e-10_r8_kind
456 real(r8_kind),
parameter :: large_number = 1.e20_r8_kind
457 logical :: module_is_initialized = .false.
458 integer :: id_put_1_to_xgrid_order_1 = 0
459 integer :: id_put_1_to_xgrid_order_2 = 0
460 integer :: id_get_1_from_xgrid = 0
461 integer :: id_get_1_from_xgrid_repro = 0
462 integer :: id_get_2_from_xgrid = 0
463 integer :: id_put_2_to_xgrid = 0
464 integer :: id_setup_xmap = 0
465 integer :: id_load_xgrid1, id_load_xgrid2, id_load_xgrid3
466 integer :: id_load_xgrid4, id_load_xgrid5
467 integer :: id_load_xgrid, id_set_comm, id_regen, id_conservation_check
471 integer :: nnest=0, tile_nest, tile_parent
472 integer :: is_nest=0, ie_nest=0, js_nest=0, je_nest=0
473 integer :: is_parent=0, ie_parent=0, js_parent=0, je_parent=0
485 module procedure stock_move_ug_3d
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)
519 integer,
intent(out) :: remap_method
522 integer :: iunit, ierr, io, out_unit
524 if (module_is_initialized)
return
525 module_is_initialized = .true.
527 read (input_nml_file, xgrid_nml, iostat=io)
535 if (
mpp_pe() == mpp_root_pe() )
write (iunit,nml=xgrid_nml)
542 remap_method = first_order
543 if( monotonic_exchange )
call error_mesg(
'xgrid_mod', &
544 'xgrid_nml monotonic_exchange must be .false. when interp_method = first_order', fatal)
545 write(out_unit,*)
"NOTE from xgrid_mod: use first_order conservative exchange"
547 if(monotonic_exchange)
then
548 write(out_unit,*)
"NOTE from xgrid_mod: use monotonic second_order conservative exchange"
550 write(out_unit,*)
"NOTE from xgrid_mod: use second_order conservative exchange"
552 remap_method = second_order
555 ' is not a valid namelist option', fatal)
558 if(xgrid_clocks_on)
then
559 id_put_1_to_xgrid_order_1 =
mpp_clock_id(
"put_1_to_xgrid_order_1", flags=mpp_clock_sync)
560 id_put_1_to_xgrid_order_2 =
mpp_clock_id(
"put_1_to_xgrid_order_2", flags=mpp_clock_sync)
561 id_get_1_from_xgrid =
mpp_clock_id(
"get_1_from_xgrid", flags=mpp_clock_sync)
562 id_get_1_from_xgrid_repro =
mpp_clock_id(
"get_1_from_xgrid_repro", flags=mpp_clock_sync)
563 id_get_2_from_xgrid =
mpp_clock_id(
"get_2_from_xgrid", flags=mpp_clock_sync)
564 id_put_2_to_xgrid =
mpp_clock_id(
"put_2_to_xgrid", flags=mpp_clock_sync)
565 id_setup_xmap =
mpp_clock_id(
"setup_xmap", flags=mpp_clock_sync)
568 id_conservation_check =
mpp_clock_id(
"conservation_check")
583 subroutine load_xgrid (xmap, grid, grid_file, grid1_id, grid_id, tile1, tile2, use_higher_order)
586 character(len=*),
intent(in) :: grid_file
587 character(len=3),
intent(in) :: grid1_id, grid_id
588 integer,
intent(in) :: tile1, tile2
589 logical,
intent(in) :: use_higher_order
591 integer,
pointer,
dimension(:) :: i1=>null(), j1=>null()
592 integer,
pointer,
dimension(:) :: i2=>null(), j2=>null()
593 real(r8_kind),
pointer,
dimension(:) :: di=>null(), dj=>null()
594 real(r8_kind),
pointer,
dimension(:) :: area =>null()
595 integer,
pointer,
dimension(:) :: i1_tmp=>null(), j1_tmp=>null()
596 integer,
pointer,
dimension(:) :: i2_tmp=>null(), j2_tmp=>null()
597 real(r8_kind),
pointer,
dimension(:) :: di_tmp=>null(), dj_tmp=>null()
598 real(r8_kind),
pointer,
dimension(:) :: area_tmp =>null()
599 integer,
pointer,
dimension(:) :: i1_side1=>null(), j1_side1=>null()
600 integer,
pointer,
dimension(:) :: i2_side1=>null(), j2_side1=>null()
601 real(r8_kind),
pointer,
dimension(:) :: di_side1=>null(), dj_side1=>null()
602 real(r8_kind),
pointer,
dimension(:) :: area_side1 =>null()
604 real(r8_kind),
allocatable,
dimension(:,:) :: tmp
605 real(r8_kind),
allocatable,
dimension(:) :: send_buffer, recv_buffer
606 type (
grid_type),
pointer,
save :: grid1 =>null()
607 integer :: l, ll, ll_repro, p, nxgrid, size_prev
609 integer :: size_repro, out_unit
610 logical :: scale_exist = .false.
611 logical :: is_distribute = .false.
612 real(r8_kind),
allocatable,
dimension(:) :: scale
613 real(r8_kind) :: garea
614 integer :: npes, isc, iec, nxgrid_local, pe, nxgrid_local_orig
615 integer :: nxgrid1, nxgrid2, nset1, nset2, ndivs, cur_ind
616 integer :: pos, nsend, nrecv, l1, l2, n, mypos
617 integer :: start(4), nread(4)
619 character(len=128) :: attvalue
620 integer,
dimension(0:xmap%npes-1) :: pelist
621 logical,
dimension(0:xmap%npes-1) :: subset_rootpe
622 integer,
dimension(0:xmap%npes-1) :: nsend1, nsend2, nrecv1, nrecv2
623 integer,
dimension(0:xmap%npes-1) :: send_cnt, recv_cnt
624 integer,
dimension(0:xmap%npes-1) :: send_buffer_pos, recv_buffer_pos
625 integer,
dimension(0:xmap%npes-1) :: ibegin, iend, pebegin, peend
626 integer,
dimension(2*xmap%npes) :: ibuf1, ibuf2
627 integer,
dimension(0:xmap%npes-1) :: pos_x, y2m1_size
628 integer,
allocatable,
dimension(:) :: y2m1_pe
629 integer,
pointer,
save :: iarray(:), jarray(:)
630 integer,
allocatable,
save :: pos_s(:)
631 integer,
pointer,
dimension(:) :: iarray2(:)=>null(), jarray2(:)=>null()
633 integer :: nxgrid1_old
635 type(fmsnetcdffile_t) :: fileobj
637 if(.not.
open_file(fileobj, grid_file,
'read' ))
then
638 call error_mesg(
'xgrid_mod(load_xgrid)',
'Error in opening file '//trim(grid_file), fatal)
641 scale_exist = .false.
642 grid1 => xmap%grids(1)
646 mypos =
mpp_pe()-mpp_root_pe()
650 if( npes .NE. pelist(npes-1) - pelist(0) + 1 )
then
651 print*,
"npes =", npes,
", pelist(npes-1)=", pelist(npes-1),
", pelist(0)=", pelist(0)
652 call error_mesg(
'xgrid_mod', .NE.
'npes pelist(npes-1) - pelist(0)', fatal)
655 select case(xmap%version)
658 if (dimension_exists(fileobj,
'i_'//lowercase(grid1_id)//
'X'//lowercase(grid_id)))
then
659 call get_dimension_size(fileobj,
'i_'//lowercase(grid1_id)//
'X'//lowercase(grid_id), nxgrid)
661 if(nxgrid .LE. 0)
return
665 if(nxgrid .LE. 0)
return
669 if(nxgrid > npes)
then
673 if(npes == ndivs)
then
674 p =
mpp_pe()-mpp_root_pe()
677 subset_rootpe(:) = .true.
682 if(pe == pebegin(n))
then
689 subset_rootpe(:) = .false.
692 if(pelist(n) == pebegin(cur_ind))
then
693 subset_rootpe(n) = .true.
695 if(cur_ind == ndivs)
exit
699 is_distribute = .true.
701 is_distribute = .false.
702 isc = 1; iec = nxgrid
707 if(use_higher_order)
then
711 if(scale_exist) nset2 = nset1 + 1
713 call mpp_clock_begin(id_load_xgrid1)
714 if(iec .GE. isc)
then
715 nxgrid_local = iec - isc + 1
716 allocate(i1_tmp(isc:iec), j1_tmp(isc:iec), i2_tmp(isc:iec), j2_tmp(isc:iec), area_tmp(isc:iec) )
717 if(use_higher_order)
allocate(di_tmp(isc:iec), dj_tmp(isc:iec))
721 select case(xmap%version)
723 start(1) = isc; nread(1) = nxgrid_local
724 allocate(tmp(nxgrid_local,1))
725 call read_data(fileobj,
'I_'//grid1_id//
'_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
726 i1_tmp = int(tmp(:,1))
727 call read_data(fileobj,
'J_'//grid1_id//
'_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
728 j1_tmp = int(tmp(:,1))
729 call read_data(fileobj,
'I_'//grid_id//
'_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
730 i2_tmp = int(tmp(:,1))
731 call read_data(fileobj,
'J_'//grid_id//
'_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
732 j2_tmp = int(tmp(:,1))
733 call read_data(fileobj,
'AREA_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
735 if(use_higher_order)
then
736 call read_data(fileobj,
'DI_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
738 call read_data(fileobj,
'DJ_'//grid1_id//
'x'//grid_id, tmp, corner=start, edge_lengths=nread)
743 nread(1) = 2; start(2) = isc; nread(2) = nxgrid_local
744 allocate(tmp(2, isc:iec))
745 call read_data(fileobj,
"tile1_cell", tmp, corner=start, edge_lengths=nread)
746 i1_tmp(isc:iec) = int(tmp(1, isc:iec))
747 j1_tmp(isc:iec) = int(tmp(2, isc:iec))
748 call read_data(fileobj,
"tile2_cell", tmp, corner=start, edge_lengths=nread)
749 i2_tmp(isc:iec) = int(tmp(1, isc:iec))
750 j2_tmp(isc:iec) = int(tmp(2, isc:iec))
751 if(use_higher_order)
then
752 call read_data(fileobj,
"tile1_distance", tmp, corner=start, edge_lengths=nread)
753 di_tmp(isc:iec) = tmp(1, isc:iec)
754 dj_tmp(isc:iec) = tmp(2, isc:iec)
757 start(1) = isc; nread(1) = nxgrid_local
759 allocate(tmp(isc:iec,1) )
761 call read_data(fileobj,
"xgrid_area", tmp(:,1:1), corner=start, edge_lengths=nread)
763 call get_variable_units(fileobj,
"xgrid_area", attvalue)
765 if( trim(attvalue) ==
'm2' )
then
766 garea = 4.0_r8_kind * pi * radius * radius;
767 area_tmp = tmp(:,1)/garea
768 else if( trim(attvalue) ==
'none' )
then
771 call error_mesg(
'xgrid_mod',
'In file '//trim(grid_file)//
', xgrid_area units = '// &
772 trim(attvalue)//
' should be "m2" or "none"', fatal)
777 if(grid1_id ==
'LND' .AND. grid_id ==
'OCN')
then
778 if(variable_exists(fileobj,
"scale"))
then
779 allocate(scale(isc:iec))
780 write(out_unit, *)
"NOTE from load_xgrid(xgrid_mod): field 'scale' exist in the file "// &
781 & trim(grid_file)//
", this field will be read and the exchange grid cell area will be"// &
782 &
" multiplied by scale"
783 call read_data(fileobj,
"scale", tmp, corner=start, edge_lengths=nread)
793 nxgrid_local_orig = nxgrid_local
794 allocate(i1(isc:iec), j1(isc:iec), i2(isc:iec), j2(isc:iec), area(isc:iec) )
795 if(use_higher_order)
allocate(di(isc:iec), dj(isc:iec))
801 if(grid1%tile(p) == tile1)
then
802 if(
in_box_nbr(i1_tmp(l), j1_tmp(l), grid1, p))
then
811 if(grid%tile(p) == tile2)
then
812 if (
in_box_nbr(i2_tmp(l), j2_tmp(l), grid, p))
then
818 area(pos) = area_tmp(l)
819 if(use_higher_order)
then
830 deallocate(i1_tmp, i2_tmp, j1_tmp, j2_tmp, area_tmp)
831 if(use_higher_order)
deallocate( di_tmp, dj_tmp)
833 if(iec .GE. isc)
then
834 nxgrid_local = iec - isc + 1
840 nxgrid_local_orig = 0
845 call mpp_clock_end(id_load_xgrid1)
847 if(is_distribute)
then
851 nsend1(:) = 0; nrecv1(:) = 0
852 nsend2(:) = 0; nrecv2(:) = 0
853 ibuf1(:)= 0; ibuf2(:)= 0
855 call mpp_clock_begin(id_load_xgrid2)
856 if(nxgrid_local>0)
then
857 allocate( send_buffer(nxgrid_local * (nset1+nset2)) )
860 send_buffer_pos(p) = pos
861 if(grid%tile(p) == tile2)
then
864 nsend2(p) = nsend2(p) + 1
865 send_buffer(pos+1) = real(i1(l), r8_kind)
866 send_buffer(pos+2) = real(j1(l), r8_kind)
867 send_buffer(pos+3) = real(i2(l), r8_kind)
868 send_buffer(pos+4) = real(j2(l), r8_kind)
869 send_buffer(pos+5) = area(l)
870 if(use_higher_order)
then
871 send_buffer(pos+6) = di(l)
872 send_buffer(pos+7) = dj(l)
874 if(scale_exist) send_buffer(pos+nset2) = scale(l)
879 if(grid1%tile(p) == tile1)
then
882 nsend1(p) = nsend1(p) + 1
883 send_buffer(pos+1) = real(i1(l), r8_kind)
884 send_buffer(pos+2) = real(j1(l), r8_kind)
885 send_buffer(pos+3) = real(i2(l), r8_kind)
886 send_buffer(pos+4) = real(j2(l), r8_kind)
887 send_buffer(pos+5) = area(l)
888 if(use_higher_order)
then
889 send_buffer(pos+6) = di(l)
890 send_buffer(pos+7) = dj(l)
898 call mpp_clock_end(id_load_xgrid2)
901 call mpp_clock_begin(id_load_xgrid3)
903 if (do_alltoall)
then
905 ibuf1(2*p+1) = nsend1(p)
906 ibuf1(2*p+2) = nsend2(p)
911 p = mod(mypos+npes-n, npes)
912 if(.not. subset_rootpe(p)) cycle
913 call mpp_recv( ibuf2(2*p+1), glen=2, from_pe=pelist(p), block=.false., tag=comm_tag_1)
916 if(nxgrid_local_orig>0)
then
918 p = mod(mypos+n, npes)
919 ibuf1(2*p+1) = nsend1(p)
920 ibuf1(2*p+2) = nsend2(p)
921 call mpp_send( ibuf1(2*p+1), plen=2, to_pe=pelist(p), tag=comm_tag_1)
927 nrecv1(p) = ibuf2(2*p+1)
928 nrecv2(p) = ibuf2(2*p+2)
932 call mpp_clock_end(id_load_xgrid3)
933 call mpp_clock_begin(id_load_xgrid4)
936 recv_buffer_pos(p) = pos
937 pos = pos + nrecv1(p) * nset1 + nrecv2(p) * nset2
941 nxgrid1 = sum(nrecv1)
942 nxgrid2 = sum(nrecv2)
943 if(nxgrid1>0 .OR. nxgrid2>0)
allocate(recv_buffer(nxgrid1*nset1+nxgrid2*nset2))
945 if (do_alltoallv)
then
947 send_cnt(:) = nset1 * nsend1(:) + nset2 * nsend2(:)
948 recv_cnt(:) = nset1 * nrecv1(:) + nset2 * nrecv2(:)
950 call mpp_alltoall(send_buffer, send_cnt, send_buffer_pos, &
951 recv_buffer, recv_cnt, recv_buffer_pos)
954 p = mod(mypos+npes-n, npes)
955 nrecv = nrecv1(p)*nset1+nrecv2(p)*nset2
957 pos = recv_buffer_pos(p)
958 call mpp_recv(recv_buffer(pos+1), glen=nrecv, from_pe=pelist(p), &
959 block=.false., tag=comm_tag_2)
963 p = mod(mypos+n, npes)
964 nsend = nsend1(p)*nset1 + nsend2(p)*nset2
966 pos = send_buffer_pos(p)
967 call mpp_send(send_buffer(pos+1), plen=nsend, to_pe=pelist(p), &
972 call mpp_clock_end(id_load_xgrid4)
974 if( nxgrid_local>0)
then
975 deallocate(i1,j1,i2,j2,area)
978 allocate(i1(nxgrid2), j1(nxgrid2))
979 allocate(i2(nxgrid2), j2(nxgrid2))
980 allocate(area(nxgrid2))
981 allocate(i1_side1(nxgrid1), j1_side1(nxgrid1))
982 allocate(i2_side1(nxgrid1), j2_side1(nxgrid1))
983 allocate(area_side1(nxgrid1))
984 if(use_higher_order)
then
985 if(nxgrid_local>0)
deallocate(di,dj)
986 allocate(di(nxgrid2), dj(nxgrid2))
987 allocate(di_side1(nxgrid1), dj_side1(nxgrid1))
990 if(nxgrid_local>0)
deallocate(scale)
991 allocate(scale(nxgrid2))
998 i1(l2) = int(recv_buffer(pos+1))
999 j1(l2) = int(recv_buffer(pos+2))
1000 i2(l2) = int(recv_buffer(pos+3))
1001 j2(l2) = int(recv_buffer(pos+4))
1002 area(l2) = recv_buffer(pos+5)
1003 if(use_higher_order)
then
1004 di(l2) = recv_buffer(pos+6)
1005 dj(l2) = recv_buffer(pos+7)
1007 if(scale_exist)scale(l2) = recv_buffer(pos+nset2)
1012 i1_side1(l1) = int(recv_buffer(pos+1))
1013 j1_side1(l1) = int(recv_buffer(pos+2))
1014 i2_side1(l1) = int(recv_buffer(pos+3))
1015 j2_side1(l1) = int(recv_buffer(pos+4))
1016 area_side1(l1) = recv_buffer(pos+5)
1017 if(use_higher_order)
then
1018 di_side1(l1) = recv_buffer(pos+6)
1019 dj_side1(l1) = recv_buffer(pos+7)
1025 if(
allocated(send_buffer))
deallocate(send_buffer)
1026 if(
allocated(recv_buffer))
deallocate(recv_buffer)
1031 i1_side1 => i1; j1_side1 => j1
1032 i2_side1 => i2; j2_side1 => j2
1034 if(use_higher_order)
then
1040 call mpp_clock_begin(id_load_xgrid5)
1043 size_prev = grid%size
1045 if(grid%tile_me == tile2)
then
1047 if (
in_box_me(i2(l), j2(l), grid) )
then
1048 grid%size = grid%size + 1
1050 if( grid1_id .NE.
"ATM" .OR. tile1 .NE. tile_parent .OR. &
1051 .NOT.
in_box(i1(l), j1(l), is_parent, ie_parent, js_parent, je_parent) )
then
1053 lll = grid%l_index((j2(l)-1)*grid%im+i2(l))
1054 grid%area(lll,1) = grid%area(lll,1)+area(l)
1056 grid%area(i2(l),j2(l)) = grid%area(i2(l),j2(l))+area(l)
1060 if(grid1%tile(p) == tile1)
then
1062 xmap%your1my2(p) = .true.
1070 if(grid%size > size_prev)
then
1071 if(size_prev > 0)
then
1072 allocate(x_local(size_prev))
1074 if(
ASSOCIATED(grid%x))
deallocate(grid%x)
1075 allocate( grid%x( grid%size ) )
1076 grid%x(1:size_prev) = x_local
1079 if(
ASSOCIATED(grid%x))
deallocate(grid%x)
1080 allocate( grid%x( grid%size ) )
1081 grid%x%di = 0.0_r8_kind; grid%x%dj = 0.0_r8_kind
1086 if( grid%tile_me == tile2 )
then
1091 grid%x(ll)%i1 = i1(l); grid%x(ll)%i2 = i2(l)
1092 grid%x(ll)%j1 = j1(l); grid%x(ll)%j2 = j2(l)
1094 grid%x(ll)%l2 = grid%l_index((j2(l)-1)*grid%im + i2(l))
1099 grid%x(ll)%tile = tile1
1100 grid%x(ll)%area = area(l)
1101 if(scale_exist)
then
1102 grid%x(ll)%scale = scale(l)
1104 grid%x(ll)%scale = 1.0_r8_kind
1106 if(use_higher_order)
then
1107 grid%x(ll)%di = di(l)
1108 grid%x(ll)%dj = dj(l)
1113 if(grid1%tile(p) == tile1)
then
1115 grid%x(ll)%pe = p + xmap%root_pe
1124 if(grid%id == xmap%grids(
size(xmap%grids(:)))%id)
then
1131 if(grid1%tile_me == tile1)
then
1132 if(
associated(iarray))
then
1133 nxgrid1_old =
size(iarray(:))
1138 allocate(y2m1_pe(nxgrid1))
1139 if(.not. last_grid )
allocate(pos_s(0:xmap%npes-1))
1141 if(nxgrid1_old > 0)
then
1143 y2m1_size(p) = xmap%your2my1_size(p)
1150 if (
in_box_me(i1_side1(l), j1_side1(l), grid1) )
then
1151 if(grid1%is_ug)
then
1152 lll = grid1%l_index((j1_side1(l)-1)*grid1%im+i1_side1(l))
1153 grid1%area(lll,1) = grid1%area(lll,1) + area_side1(l)
1155 grid1%area(i1_side1(l),j1_side1(l)) = grid1%area(i1_side1(l),j1_side1(l))+area_side1(l)
1158 if (grid%tile(p) == tile2)
then
1159 if (
in_box_nbr(i2_side1(l), j2_side1(l), grid, p))
then
1160 xmap%your2my1(p) = .true.
1162 y2m1_size(p) = y2m1_size(p) + 1
1166 size_repro = size_repro + 1
1171 pos_x(p) = pos_x(p-1) + y2m1_size(p-1)
1174 if(.not. last_grid) pos_s(:) = pos_x(:)
1176 if(nxgrid1_old > 0)
then
1177 y2m1_size(:) = xmap%your2my1_size(:)
1180 allocate(iarray(nxgrid1+nxgrid1_old), jarray(nxgrid1+nxgrid1_old))
1183 do n = 1, xmap%your2my1_size(p)
1184 iarray(pos_x(p)+n) = iarray2(pos_s(p)+n)
1185 jarray(pos_x(p)+n) = jarray2(pos_s(p)+n)
1188 deallocate(iarray2, jarray2)
1190 allocate(iarray(nxgrid1), jarray(nxgrid1))
1200 if(y2m1_size(p) > 0)
then
1201 pos = pos_x(p)+y2m1_size(p)
1202 if( i1_side1(l) == iarray(pos) .AND. j1_side1(l) == jarray(pos) )
then
1206 do n = 1, y2m1_size(p)
1208 if(i1_side1(l) == iarray(pos) .AND. j1_side1(l) == jarray(pos))
then
1215 if( (.NOT. found) .OR. monotonic_exchange )
then
1216 y2m1_size(p) = y2m1_size(p)+1
1217 pos = pos_x(p)+y2m1_size(p)
1218 iarray(pos) = i1_side1(l)
1219 jarray(pos) = j1_side1(l)
1222 xmap%your2my1_size(:) = y2m1_size(:)
1225 deallocate(iarray, jarray)
1226 if(
allocated(pos_s))
deallocate(pos_s)
1230 if (grid1%tile_me == tile1 .and. size_repro > 0)
then
1231 ll_repro = grid%size_repro
1232 grid%size_repro = ll_repro + size_repro
1233 if(ll_repro > 0)
then
1234 allocate(x_local(ll_repro))
1235 x_local = grid%x_repro
1236 if(
ASSOCIATED(grid%x_repro))
deallocate(grid%x_repro)
1237 allocate( grid%x_repro(grid%size_repro ) )
1238 grid%x_repro(1:ll_repro) = x_local
1241 if(
ASSOCIATED(grid%x_repro))
deallocate(grid%x_repro)
1242 allocate( grid%x_repro( grid%size_repro ) )
1243 grid%x_repro%di = 0.0_r8_kind; grid%x_repro%dj = 0.0_r8_kind
1246 if (
in_box_me(i1_side1(l),j1_side1(l), grid1) )
then
1247 ll_repro = ll_repro + 1
1248 grid%x_repro(ll_repro)%i1 = i1_side1(l); grid%x_repro(ll_repro)%i2 = i2_side1(l)
1249 grid%x_repro(ll_repro)%j1 = j1_side1(l); grid%x_repro(ll_repro)%j2 = j2_side1(l)
1250 if(grid1%is_ug)
then
1251 grid%x_repro(ll_repro)%l1 = grid1%l_index((j1_side1(l)-1)*grid1%im+i1_side1(l))
1256 grid%x_repro(ll_repro)%tile = tile1
1257 grid%x_repro(ll_repro)%area = area_side1(l)
1258 if(use_higher_order)
then
1259 grid%x_repro(ll_repro)%di = di_side1(l)
1260 grid%x_repro(ll_repro)%dj = dj_side1(l)
1264 if(grid%tile(p) == tile2)
then
1265 if (
in_box_nbr(i2_side1(l), j2_side1(l), grid, p))
then
1266 grid%x_repro(ll_repro)%pe = p + xmap%root_pe
1274 deallocate(i1, j1, i2, j2, area)
1275 if(use_higher_order)
deallocate(di, dj)
1276 if(scale_exist)
deallocate(scale)
1277 if(is_distribute)
then
1278 deallocate(i1_side1, j1_side1, i2_side1, j2_side1, area_side1)
1279 if(use_higher_order)
deallocate(di_side1, dj_side1)
1282 i1=>null(); j1=>null(); i2=>null(); j2=>null()
1283 call mpp_clock_end(id_load_xgrid5)
1287 end subroutine load_xgrid
1296 character(len=3),
intent(in) :: grid_id
1297 character(len=*),
intent(in) :: grid_file
1299 real(r8_kind),
dimension(grid%im) :: lonb
1300 real(r8_kind),
dimension(grid%jm) :: latb
1301 real(r8_kind) :: d2r
1302 integer :: is, ie, js, je
1303 type(fmsnetcdfdomainfile_t) :: fileobj
1305 d2r = pi / 180.0_r8_kind
1307 if(.not.
open_file(fileobj, grid_file,
'read', grid%domain) )
then
1308 call error_mesg(
'xgrid_mod(get_grid_version1)',
'Error in opening file '//trim(grid_file), fatal)
1312 if (
associated(grid%lon))
deallocate(grid%lon)
1313 if (
associated(grid%lat))
deallocate(grid%lat)
1314 allocate(grid%lon(grid%im), grid%lat(grid%jm))
1315 if(grid_id ==
'ATM')
then
1327 else if(grid_id ==
'LND')
then
1330 if(.not.
allocated(area_lnd_model))
then
1331 allocate(area_lnd_model(is:ie, js:je))
1334 if(.not.
allocated(area_lnd_sphere))
then
1335 allocate(area_lnd_sphere(is:ie, js:je))
1338 else if(grid_id ==
'OCN' )
then
1339 if(.not.
allocated(area_ocn_sphere))
then
1340 allocate(area_ocn_sphere(is:ie, js:je))
1345 if(grid_id ==
'LND' .or. grid_id ==
'ATM')
then
1346 grid%lon = lonb * d2r
1347 grid%lat = latb * d2r
1349 grid%is_latlon = .true.
1364 character(len=3),
intent(in) :: grid_id
1365 character(len=*),
intent(in) :: grid_file
1367 real(r8_kind),
allocatable :: tmpx(:,:), tmpy(:,:)
1368 real(r8_kind) :: d2r
1369 integer :: is, ie, js, je, nlon, nlat, i, j
1370 integer :: start(4), nread(4), isc2, iec2, jsc2, jec2
1371 type(fmsnetcdffile_t) :: fileobj
1373 if(.not.
open_file(fileobj, grid_file,
'read') )
then
1374 call error_mesg(
'xgrid_mod(get_grid_version2)',
'Error in opening file '//trim(grid_file), fatal)
1377 d2r = pi / 180.0_r8_kind
1381 call get_dimension_size(fileobj,
"nx", nlon)
1382 call get_dimension_size(fileobj,
"ny", nlat)
1383 if( mod(nlon,2) .NE. 0)
call error_mesg(
'xgrid_mod', &
1384 'flux_exchange_mod: atmos supergrid longitude size can not be divided by 2', fatal)
1385 if( mod(nlat,2) .NE. 0)
call error_mesg(
'xgrid_mod', &
1386 'flux_exchange_mod: atmos supergrid latitude size can not be divided by 2', fatal)
1389 if(nlon .NE. grid%im .OR. nlat .NE. grid%jm)
call error_mesg(
'xgrid_mod', &
1390 'grid size in tile_file does not match the global grid size', fatal)
1392 if( grid_id ==
'LND' .or. grid_id ==
'ATM' .or. grid_id ==
'WAV' )
then
1393 isc2 = 2*grid%is_me-1; iec2 = 2*grid%ie_me+1
1394 jsc2 = 2*grid%js_me-1; jec2 = 2*grid%je_me+1
1395 allocate(tmpx(isc2:iec2, jsc2:jec2) )
1396 allocate(tmpy(isc2:iec2, jsc2:jec2) )
1397 start = 1; nread = 1
1398 start(1) = isc2; nread(1) = iec2 - isc2 + 1
1399 start(2) = jsc2; nread(2) = jec2 - jsc2 + 1
1400 call read_data(fileobj,
'x', tmpx, corner=start, edge_lengths=nread)
1401 call read_data(fileobj,
'y', tmpy, corner=start, edge_lengths=nread)
1402 if(is_lat_lon(tmpx, tmpy) )
then
1403 deallocate(tmpx, tmpy)
1404 start = 1; nread = 1
1405 start(2) = 2; nread(1) = nlon*2+1
1406 allocate(tmpx(nlon*2+1, 1), tmpy(1, nlat*2+1))
1407 call read_data(fileobj,
"x", tmpx, corner=start, edge_lengths=nread)
1408 if (
associated(grid%lon))
deallocate(grid%lon)
1409 if (
associated(grid%lat))
deallocate(grid%lat)
1410 allocate(grid%lon(grid%im), grid%lat(grid%jm))
1412 grid%lon(i) = tmpx(2*i,1) * d2r
1414 start = 1; nread = 1
1415 start(1) = 2; nread(2) = nlat*2+1
1416 call read_data(fileobj,
"y", tmpy, corner=start, edge_lengths=nread)
1418 grid%lat(j) = tmpy(1, 2*j) * d2r
1420 grid%is_latlon = .true.
1422 if (
associated(grid%geolon))
deallocate(grid%geolon)
1423 if (
associated(grid%geolat))
deallocate(grid%geolat)
1424 allocate(grid%geolon(grid%isd_me:grid%ied_me, grid%jsd_me:grid%jed_me))
1425 allocate(grid%geolat(grid%isd_me:grid%ied_me, grid%jsd_me:grid%jed_me))
1426 grid%geolon = 1.0e10_r8_kind
1427 grid%geolat = 1.0e10_r8_kind
1429 do j = grid%js_me,grid%je_me
1430 do i = grid%is_me,grid%ie_me
1431 grid%geolon(i, j) = tmpx(i*2,j*2)*d2r
1432 grid%geolat(i, j) = tmpy(i*2,j*2)*d2r
1437 grid%is_latlon = .false.
1439 deallocate(tmpx, tmpy)
1451 type(fmsnetcdfdomainfile_t),
intent(in) :: fileobj
1452 character(len=*),
intent(in) :: name
1453 real(r8_kind),
intent(out) :: get_area_data(:,:)
1455 if(variable_exists(fileobj, name))
then
1456 call read_data(fileobj, name, get_area_data)
1458 call error_mesg(
'xgrid_mod',
'no field named '//trim(name)//
' in grid file '//trim(fileobj%path)// &
1459 ' Will set data to negative values...', note)
1461 get_area_data = -1.0_r8_kind
1475 type(
domain2d),
intent(in) :: domain
1476 character(len=*),
intent(in) :: grid_file
1477 integer :: is, ie, js, je
1478 type(fmsnetcdffile_t) :: fileobj
1480 if(
allocated(area_ocn_model))
return
1485 allocate(area_ocn_model(is:ie, js:je))
1486 if(ie < is .or. je < js )
return
1488 if(.not.
open_file(fileobj, grid_file,
'read') )
then
1489 call error_mesg(
'xgrid_mod(get_ocean_model_area_elements)',
'Error in opening file '//trim(grid_file), fatal)
1492 if(variable_exists(fileobj,
'AREA_OCN_MODEL') )
then
1493 call read_data(fileobj,
'AREA_OCN_MODEL', area_ocn_model)
1495 deallocate(area_ocn_model)
1506 subroutine setup_xmap(xmap, grid_ids, grid_domains, grid_file, atm_grid, lnd_ug_domain)
1508 character(len=3),
dimension(:),
intent(in ) :: grid_ids
1509 type(
domain2d),
dimension(:),
intent(in ) :: grid_domains
1510 character(len=*),
intent(in ) :: grid_file
1512 type(
domainug),
optional,
intent(in ) :: lnd_ug_domain
1515 integer :: nxgrid_file, i1, i2, i3, tile1, tile2, j
1516 integer :: nxc, nyc, out_unit
1517 type(
grid_type),
pointer :: grid => null()
1518 type(
grid_type),
pointer,
save :: grid1 => null()
1519 real(r8_kind),
dimension(3) :: xxx
1520 real(r8_kind),
dimension(:,:),
allocatable :: check_data
1521 real(r8_kind),
dimension(:,:,:),
allocatable :: check_data_3d
1522 real(r8_kind),
allocatable :: tmp_2d(:,:), tmp_3d(:,:,:)
1523 character(len=FMS_FILE_LEN) :: xgrid_file, xgrid_name
1524 character(len=FMS_FILE_LEN) :: tile_file, mosaic_file
1525 character(len=256) :: mosaic1, mosaic2, contact, xgrid_dimname
1526 character(len=256) :: tile1_name, tile2_name
1527 character(len=256),
allocatable :: tile1_list(:), tile2_list(:)
1528 character(len=FMS_FILE_LEN),
allocatable :: xgrid_filelist(:)
1529 integer :: npes, npes2
1530 integer,
allocatable :: pelist(:)
1532 logical :: use_higher_order = .false.
1533 integer :: lnd_ug_id, l
1534 integer,
allocatable :: grid_index(:)
1535 type(fmsnetcdffile_t) :: gridfileobj, mosaicfileobj, fileobj
1536 type(
grid_type),
allocatable,
target :: grids_tmp(:)
1539 call mpp_clock_begin(id_setup_xmap)
1541 if(
interp_method .ne.
'first_order') use_higher_order = .true.
1546 xmap%root_pe = mpp_root_pe()
1548 if (
associated(xmap%grids))
deallocate(xmap%grids)
1549 allocate( xmap%grids(1:
size(grid_ids(:))) )
1551 if (
associated(xmap%your1my2))
deallocate(xmap%your1my2)
1552 if (
associated(xmap%your2my1))
deallocate(xmap%your2my1)
1553 if (
associated(xmap%your2my1_size))
deallocate(xmap%your2my1_size)
1554 allocate ( xmap%your1my2(0:xmap%npes-1), xmap%your2my1(0:xmap%npes-1) )
1555 allocate ( xmap%your2my1_size(0:xmap%npes-1) )
1557 xmap%your1my2 = .false.; xmap%your2my1 = .false.;
1558 xmap%your2my1_size = 0
1560 if(.not.
open_file(gridfileobj,trim(grid_file),
"read"))
then
1561 call error_mesg(
'xgrid_mod',
'Error when opening file'//trim(grid_file), fatal)
1565 if(variable_exists(gridfileobj,
"AREA_ATMxOCN" ) )
then
1568 else if(variable_exists(gridfileobj,
"ocn_mosaic_file" ) )
then
1571 call error_mesg(
'xgrid_mod',
'both AREA_ATMxOCN and ocn_mosaic_file does not exist in '//trim(grid_file), fatal)
1576 call error_mesg(
'xgrid_mod',
'reading exchange grid information from grid spec file', note)
1578 call error_mesg(
'xgrid_mod',
'reading exchange grid information from mosaic grid file', note)
1583 if(
present(lnd_ug_domain))
then
1584 do g=1,
size(grid_ids(:))
1585 if(grid_ids(g) ==
'LND') lnd_ug_id = g
1589 call mpp_clock_begin(id_load_xgrid)
1593 grids_tmp = xmap%grids
1595 grid1 => xmap%grids(1)
1597 do g=1,
size(grid_ids(:))
1599 grid => grids_tmp(g)
1601 grid%id = grid_ids(g)
1602 grid%domain = grid_domains(g)
1604 if (
associated(grid%is))
deallocate(grid%is)
1605 if (
associated(grid%ie))
deallocate(grid%ie)
1606 if (
associated(grid%js))
deallocate(grid%js)
1607 if (
associated(grid%je))
deallocate(grid%je)
1608 if (
associated(grid%tile))
deallocate(grid%tile)
1609 allocate ( grid%is(0:xmap%npes-1), grid%ie(0:xmap%npes-1) )
1610 allocate ( grid%js(0:xmap%npes-1), grid%je(0:xmap%npes-1) )
1611 allocate ( grid%tile(0:xmap%npes-1) )
1621 select case(xmap%version)
1625 call read_data(gridfileobj, lowercase(grid_ids(g))//
'_mosaic_file', mosaic_file)
1626 if(.not.
open_file(mosaicfileobj,
'INPUT/'//trim(mosaic_file),
"read"))
then
1627 call error_mesg(
'xgrid_mod',
'Error when opening solo mosaic file INPUT/'//trim(mosaic_file), fatal)
1629 call get_dimension_size(mosaicfileobj,
'ntiles', grid%ntile)
1632 if( g == 1 .AND. grid_ids(1) ==
'ATM' )
then
1633 if( .NOT. grid%on_this_pe )
call error_mesg(
'xgrid_mod',
'ATM domain is not defined on some processor' ,fatal)
1636 if( xmap%npes > grid%npes .AND. g == 1 .AND. grid_ids(1) ==
'ATM' )
then
1638 else if(xmap%npes > grid%npes)
then
1644 allocate(grid%pelist(0:npes-1))
1648 call mpp_get_data_domain(grid%domain, grid%isd_me, grid%ied_me, grid%jsd_me, grid%jed_me, &
1649 xsize=grid%nxd_me, ysize=grid%nyd_me)
1652 if( grid%root_pe == xmap%root_pe )
then
1654 ybegin=grid%js(0:npes-1), yend=grid%je(0:npes-1) )
1656 if( xmap%npes > npes .AND. g == 1 .AND. grid_ids(1) ==
'ATM' )
then
1658 ybegin=grid%js(npes:xmap%npes-1), yend=grid%je(npes:xmap%npes-1) )
1662 npes2 = xmap%npes-npes
1664 ybegin=grid%js(0:npes2-1), yend=grid%je(0:npes2-1) )
1665 call mpp_get_compute_domains(grid%domain, xbegin=grid%is(npes2:xmap%npes-1), xend=grid%ie(npes2:xmap%npes-1), &
1666 ybegin=grid%js(npes2:xmap%npes-1), yend=grid%je(npes2:xmap%npes-1) )
1670 if( xmap%npes > grid%npes .AND. g == 1 .AND. grid_ids(1) ==
'ATM' )
then
1674 if( g == 1 .AND. grid_ids(1) ==
'ATM' ) npes = xmap%npes
1676 if(grid%tile(p) > grid%ntile .or. grid%tile(p) < 1)
call error_mesg(
'xgrid_mod', &
1677 'tile id should between 1 and ntile', fatal)
1685 grid%is_me => grid%is(xmap%me-xmap%root_pe); grid%ie_me => grid%ie(xmap%me-xmap%root_pe)
1686 grid%js_me => grid%js(xmap%me-xmap%root_pe); grid%je_me => grid%je(xmap%me-xmap%root_pe)
1687 grid%nxc_me = grid%ie_me - grid%is_me + 1
1688 grid%nyc_me = grid%je_me - grid%js_me + 1
1689 grid%tile_me => grid%tile(xmap%me-xmap%root_pe)
1692 grid%is_ug = .false.
1694 if( g == lnd_ug_id )
then
1696 'does not support unstructured grid for VERSION1 grid' ,fatal)
1698 grid%ug_domain = lnd_ug_domain
1699 if (
associated(grid%ls))
deallocate(grid%ls)
1700 if (
associated(grid%le))
deallocate(grid%le)
1701 if (
associated(grid%gs))
deallocate(grid%gs)
1702 if (
associated(grid%ge))
deallocate(grid%ge)
1703 allocate ( grid%ls(0:xmap%npes-1), grid%le(0:xmap%npes-1) )
1704 allocate ( grid%gs(0:xmap%npes-1), grid%ge(0:xmap%npes-1) )
1709 if(xmap%npes > grid%npes)
then
1712 call mpp_get_ug_compute_domains(grid%ug_domain, begin=grid%ls(0:npes-1),
end=grid%le(0:npes-1) )
1713 call mpp_get_ug_domains_index(grid%ug_domain, grid%gs(0:npes-1), grid%ge(0:npes-1) )
1714 call mpp_get_ug_domain_tile_list(grid%ug_domain, grid%tile(0:npes-1))
1715 grid%ls_me => grid%ls(xmap%me-xmap%root_pe); grid%le_me => grid%le(xmap%me-xmap%root_pe)
1716 grid%gs_me => grid%gs(xmap%me-xmap%root_pe); grid%ge_me => grid%ge(xmap%me-xmap%root_pe)
1717 grid%tile_me => grid%tile(xmap%me-xmap%root_pe)
1718 grid%nxl_me = grid%le_me - grid%ls_me + 1
1719 if (
associated(grid%l_index))
deallocate(grid%l_index)
1720 allocate(grid%l_index(grid%gs_me:grid%ge_me))
1721 allocate(grid_index(grid%ls_me:grid%le_me))
1722 call mpp_get_ug_domain_grid_index(grid%ug_domain, grid_index)
1725 do l = grid%ls_me,grid%le_me
1726 grid%l_index(grid_index(l)) = l
1729 if( grid%on_this_pe )
then
1730 if (
associated(grid%area))
deallocate(grid%area)
1731 if (
associated(grid%area_inv))
deallocate(grid%area_inv)
1732 allocate( grid%area (grid%ls_me:grid%le_me,1) )
1733 allocate( grid%area_inv(grid%ls_me:grid%le_me,1) )
1734 grid%area = 0.0_r8_kind
1738 else if( grid%on_this_pe )
then
1739 if (
associated(grid%area))
deallocate(grid%area)
1740 if (
associated(grid%area_inv))
deallocate(grid%area_inv)
1741 allocate( grid%area (grid%is_me:grid%ie_me, grid%js_me:grid%je_me) )
1742 allocate( grid%area_inv(grid%is_me:grid%ie_me, grid%js_me:grid%je_me) )
1743 grid%area = 0.0_r8_kind
1749 if(.not. grid%is_ug)
then
1750 select case(xmap%version)
1752 if( grid%npes .NE. xmap%npes )
then
1753 call error_mesg(
'xgrid_mod', .NE.
' grid%npes xmap%npes ', fatal)
1757 allocate(pelist(0:xmap%npes-1))
1759 if( grid%on_this_pe )
then
1767 if( g == 1 .AND. grid_ids(1) ==
'ATM' )
then
1769 ie_nest, js_nest, je_nest, is_parent, ie_parent, js_parent, je_parent)
1774 if( use_higher_order .AND. grid%id ==
'ATM')
then
1775 if( nnest > 0 )
call error_mesg(
'xgrid_mod',
'second_order is not supported for nested coupler', fatal)
1776 if( grid%is_latlon )
then
1777 call mpp_modify_domain(grid%domain, grid%domain_with_halo, whalo=1, ehalo=1, shalo=1, nhalo=1)
1778 call mpp_get_data_domain(grid%domain_with_halo, grid%isd_me, grid%ied_me, grid%jsd_me, grid%jed_me, &
1779 xsize=grid%nxd_me, ysize=grid%nyd_me)
1781 if(.NOT.
present(atm_grid))
call error_mesg(
'xgrid_mod', &
1782 'when first grid is "ATM", atm_grid should be present', fatal)
1783 if(grid%is_me-grid%isd_me .NE. 1 .or. grid%ied_me-grid%ie_me .NE. 1 .or. &
1784 grid%js_me-grid%jsd_me .NE. 1 .or. grid%jed_me-grid%je_me .NE. 1 ) &
1785 &
call error_mesg(
'xgrid_mod',
'for non-latlon grid (cubic grid), '//&
1786 &
'the halo size should be 1 in all four direction', fatal)
1787 if(.NOT.(
ASSOCIATED(atm_grid%dx) .AND.
ASSOCIATED(atm_grid%dy) .AND.
ASSOCIATED(atm_grid%edge_w) .AND. &
1788 ASSOCIATED(atm_grid%edge_e) .AND.
ASSOCIATED(atm_grid%edge_s) .AND.
ASSOCIATED(atm_grid%edge_n).AND.&
1789 ASSOCIATED(atm_grid%en1) .AND.
ASSOCIATED(atm_grid%en2) .AND.
ASSOCIATED(atm_grid%vlon) .AND. &
1790 ASSOCIATED(atm_grid%vlat) ) )
call error_mesg(
'xgrid_mod', &
1791 'for non-latlon grid (cubic grid), all the fields in atm_grid data type should be allocated', fatal)
1792 nxc = grid%ie_me - grid%is_me + 1
1793 nyc = grid%je_me - grid%js_me + 1
1794 if(
size(atm_grid%dx,1) .NE. nxc .OR.
size(atm_grid%dx,2) .NE. nyc+1) &
1795 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%dx', fatal)
1796 if(
size(atm_grid%dy,1) .NE. nxc+1 .OR.
size(atm_grid%dy,2) .NE. nyc) &
1797 call error_mesg(
'xgrid_mod',
'incorrect dimension sizeof atm_grid%dy', fatal)
1798 if(
size(atm_grid%area,1) .NE. nxc .OR.
size(atm_grid%area,2) .NE. nyc) &
1799 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%area', fatal)
1800 if(
size(atm_grid%edge_w(:)) .NE. nyc+1 .OR.
size(atm_grid%edge_e(:)) .NE. nyc+1) &
1801 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%edge_w/edge_e', fatal)
1802 if(
size(atm_grid%edge_s(:)) .NE. nxc+1 .OR.
size(atm_grid%edge_n(:)) .NE. nxc+1) &
1803 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%edge_s/edge_n', fatal)
1804 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) &
1805 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%en1', fatal)
1806 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) &
1807 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%en2', fatal)
1808 if(
size(atm_grid%vlon,1) .NE. 3 .OR.
size(atm_grid%vlon,2) .NE. nxc .OR.
size(atm_grid%vlon,3) .NE. nyc)&
1809 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%vlon', fatal)
1810 if(
size(atm_grid%vlat,1) .NE. 3 .OR.
size(atm_grid%vlat,2) .NE. nxc .OR.
size(atm_grid%vlat,3) .NE. nyc)&
1811 call error_mesg(
'xgrid_mod',
'incorrect dimension size of atm_grid%vlat', fatal)
1812 if (
associated(grid%box%dx))
deallocate(grid%box%dx)
1813 if (
associated(grid%box%dy))
deallocate(grid%box%dy)
1814 if (
associated(grid%box%area))
deallocate(grid%box%area)
1815 if (
associated(grid%box%edge_w))
deallocate(grid%box%edge_w)
1816 if (
associated(grid%box%edge_e))
deallocate(grid%box%edge_e)
1817 if (
associated(grid%box%edge_s))
deallocate(grid%box%edge_s)
1818 if (
associated(grid%box%edge_n))
deallocate(grid%box%edge_n)
1819 if (
associated(grid%box%en1))
deallocate(grid%box%en1)
1820 if (
associated(grid%box%en2))
deallocate(grid%box%en2)
1821 if (
associated(grid%box%vlon))
deallocate(grid%box%vlon)
1822 if (
associated(grid%box%vlat))
deallocate(grid%box%vlat)
1823 allocate(grid%box%dx (grid%is_me:grid%ie_me, grid%js_me:grid%je_me+1 ))
1824 allocate(grid%box%dy (grid%is_me:grid%ie_me+1, grid%js_me:grid%je_me ))
1825 allocate(grid%box%area (grid%is_me:grid%ie_me, grid%js_me:grid%je_me ))
1826 allocate(grid%box%edge_w(grid%js_me:grid%je_me+1))
1827 allocate(grid%box%edge_e(grid%js_me:grid%je_me+1))
1828 allocate(grid%box%edge_s(grid%is_me:grid%ie_me+1))
1829 allocate(grid%box%edge_n(grid%is_me:grid%ie_me+1))
1830 allocate(grid%box%en1 (3, grid%is_me:grid%ie_me, grid%js_me:grid%je_me+1 ))
1831 allocate(grid%box%en2 (3, grid%is_me:grid%ie_me+1, grid%js_me:grid%je_me ))
1832 allocate(grid%box%vlon (3, grid%is_me:grid%ie_me, grid%js_me:grid%je_me ))
1833 allocate(grid%box%vlat (3, grid%is_me:grid%ie_me, grid%js_me:grid%je_me ))
1834 grid%box%dx = atm_grid%dx
1835 grid%box%dy = atm_grid%dy
1836 grid%box%area = atm_grid%area
1837 grid%box%edge_w = atm_grid%edge_w
1838 grid%box%edge_e = atm_grid%edge_e
1839 grid%box%edge_s = atm_grid%edge_s
1840 grid%box%edge_n = atm_grid%edge_n
1841 grid%box%en1 = atm_grid%en1
1842 grid%box%en2 = atm_grid%en2
1843 grid%box%vlon = atm_grid%vlon
1844 grid%box%vlat = atm_grid%vlat
1850 if(grid%on_this_pe)
then
1851 if (
associated(grid%frac_area))
deallocate(grid%frac_area)
1853 allocate( grid%frac_area(grid%ls_me:grid%le_me, 1, grid%km) )
1855 allocate( grid%frac_area(grid%is_me:grid%ie_me, grid%js_me:grid%je_me, grid%km) )
1857 grid%frac_area = 1.0_r8_kind
1861 xmap%grids(g) = grid
1864 select case(xmap%version)
1866 call load_xgrid (xmap, grid, grid_file, grid_ids(1), grid_ids(g), 1, 1, use_higher_order)
1868 select case(grid_ids(1))
1876 call error_mesg(
'xgrid_mod',
'grid_ids(1) should be ATM, LND or WAV', fatal)
1878 select case(grid_ids(g))
1880 xgrid_dimname =
'nfile_'//trim(xgrid_name)//
'Xl'
1881 xgrid_name = trim(xgrid_name)//
'Xl_file'
1883 xgrid_dimname =
'nfile_'//trim(xgrid_name)//
'Xo'
1884 xgrid_name = trim(xgrid_name)//
'Xo_file'
1886 xgrid_dimname =
'nfile_'//trim(xgrid_name)//
'Xw'
1887 xgrid_name = trim(xgrid_name)//
'Xw_file'
1889 call error_mesg(
'xgrid_mod',
'grid_ids(g) should be LND, OCN or WAV', fatal)
1893 call read_data(gridfileobj, lowercase(grid_ids(1))//
'_mosaic_file', mosaic1)
1894 call read_data(gridfileobj, lowercase(grid_ids(g))//
'_mosaic_file', mosaic2)
1896 mosaic1 =
'INPUT/'//trim(mosaic1)
1897 mosaic2 =
'INPUT/'//trim(mosaic2)
1899 allocate(tile1_list(grid1%ntile), tile2_list(grid%ntile) )
1900 if(.not.
open_file(fileobj,mosaic1,
"read"))
then
1901 call error_mesg(
'xgrid_mod(setup_xmap)',
'Error when opening mosaic1 file '//trim(mosaic1), fatal)
1903 call read_data(fileobj,
'gridtiles', tile1_list)
1906 if(.not.
open_file(fileobj,mosaic2,
"read"))
then
1907 call error_mesg(
'xgrid_mod(setup_xmap)',
'Error when opening mosaic2 file '//trim(mosaic2), fatal)
1909 call read_data(fileobj,
'gridtiles', tile2_list)
1912 if(variable_exists(gridfileobj, xgrid_name))
then
1913 call get_dimension_size(gridfileobj, xgrid_dimname, nxgrid_file)
1914 if(nxgrid_file>0)
then
1915 allocate(xgrid_filelist(nxgrid_file))
1916 call read_data(gridfileobj, xgrid_name, xgrid_filelist)
1919 do i = 1, nxgrid_file
1920 xgrid_file =
'INPUT/'//trim(xgrid_filelist(i))
1921 if(.not.
open_file(fileobj,xgrid_file,
"read"))
then
1922 call error_mesg(
'xgrid_mod(setup_xmap)',
'Error when opening xgrid file '// &
1923 & trim(xgrid_file), fatal)
1927 call read_data(fileobj,
"contact", contact)
1928 i1 = index(contact,
":")
1929 i2 = index(contact,
"::")
1930 i3 = index(contact,
":", back=.true. )
1931 if(i1 == 0 .OR. i2 == 0)
call error_mesg(
'xgrid_mod', &
1932 'field contact in file '//trim(xgrid_file)//
' should contains ":" and "::" ', fatal)
1934 'field contact in file '//trim(xgrid_file)//
' should contains two ":"', fatal)
1935 tile1_name = contact(i1+1:i2-1)
1936 tile2_name = contact(i3+1:len_trim(contact))
1937 tile1 = 0; tile2 = 0
1938 do j = 1, grid1%ntile
1939 if( trim(tile1_name) == trim(tile1_list(j)) )
then
1944 do j = 1, grid%ntile
1945 if( tile2_name == tile2_list(j) )
then
1951 if(tile1 == 0)
call error_mesg(
'xgrid_mod', &
1952 trim(tile1_name)//
' is not a tile of mosaic '//trim(mosaic1), fatal)
1953 if(tile2 == 0)
call error_mesg(
'xgrid_mod', &
1954 trim(tile2_name)//
' is not a tile of mosaic '//trim(mosaic2), fatal)
1956 call load_xgrid (xmap, grid, xgrid_file, grid_ids(1), grid_ids(g), tile1, tile2, &
1959 deallocate(xgrid_filelist)
1961 deallocate(tile1_list, tile2_list)
1963 if(grid%on_this_pe)
then
1964 grid%area_inv = 0.0_r8_kind;
1965 where (grid%area>0.0_r8_kind) grid%area_inv = 1.0_r8_kind/grid%area
1970 xmap%grids(g) = grid
1975 call mpp_clock_end(id_load_xgrid)
1977 grid1%area_inv = 0.0_r8_kind;
1978 where (grid1%area>0.0_r8_kind)
1979 grid1%area_inv = 1.0_r8_kind/grid1%area
1982 xmap%your1my2(xmap%me-xmap%root_pe) = .false.
1983 xmap%your2my1(xmap%me-xmap%root_pe) = .false.
1986 if (
associated(xmap%send_count_repro))
deallocate(xmap%send_count_repro)
1987 if (
associated(xmap%recv_count_repro))
deallocate(xmap%recv_count_repro)
1988 allocate( xmap%send_count_repro(0:xmap%npes-1) )
1989 allocate( xmap%recv_count_repro(0:xmap%npes-1) )
1990 xmap%send_count_repro = 0
1991 xmap%recv_count_repro = 0
1992 do g=2,
size(xmap%grids(:))
1994 if(xmap%grids(g)%size >0) &
1995 xmap%send_count_repro(p) = xmap%send_count_repro(p) &
1996 +count(xmap%grids(g)%x (:)%pe==p+xmap%root_pe)
1997 if(xmap%grids(g)%size_repro >0) &
1998 xmap%recv_count_repro(p) = xmap%recv_count_repro(p) &
1999 +count(xmap%grids(g)%x_repro(:)%pe==p+xmap%root_pe)
2002 xmap%send_count_repro_tot = sum(xmap%send_count_repro)
2003 xmap%recv_count_repro_tot = sum(xmap%recv_count_repro)
2005 xmap%send_count_repro_tot = 0
2006 xmap%recv_count_repro_tot = 0
2009 if (
associated(xmap%x1))
deallocate(xmap%x1)
2010 if (
associated(xmap%x2))
deallocate(xmap%x2)
2011 if (
associated(xmap%x1_put))
deallocate(xmap%x1_put)
2012 if (
associated(xmap%x2_get))
deallocate(xmap%x2_get)
2013 allocate( xmap%x1(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
2014 allocate( xmap%x2(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
2015 allocate( xmap%x1_put(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
2016 allocate( xmap%x2_get(1:sum(xmap%grids(2:
size(xmap%grids(:)))%size)) )
2019 if (
associated(xmap%get1))
deallocate(xmap%get1)
2020 if (
associated(xmap%put1))
deallocate(xmap%put1)
2021 allocate(xmap%get1, xmap%put1)
2022 call mpp_clock_begin(id_set_comm)
2024 call set_comm_get1(xmap)
2026 call set_comm_put1(xmap)
2029 if (
associated(xmap%get1_repro))
deallocate(xmap%get1_repro)
2030 allocate(xmap%get1_repro)
2031 call set_comm_get1_repro(xmap)
2034 call mpp_clock_end(id_set_comm)
2036 call mpp_clock_begin(id_regen)
2038 call mpp_clock_end(id_regen)
2040 call mpp_clock_begin(id_conservation_check)
2042 if(lnd_ug_id ==0)
then
2045 allocate(tmp_2d(grid1%is_me:grid1%ie_me, grid1%js_me:grid1%je_me))
2046 tmp_2d = 1.0_r8_kind
2050 write(out_unit,* )
"Checked data is array of constant 1"
2051 write(out_unit,* )grid1%id,
'(',xmap%grids(:)%id,
')=', xxx
2053 if(lnd_ug_id == 0)
then
2054 do g=2,
size(xmap%grids(:))
2055 xxx =
conservation_check(xmap%grids(g)%frac_area*0.0_r8_kind+1.0_r8_kind, xmap%grids(g)%id, xmap )
2056 write( out_unit,* )xmap%grids(g)%id,
'(',xmap%grids(:)%id,
')=', xxx
2059 do g=2,
size(xmap%grids(:))
2060 grid => xmap%grids(g)
2061 allocate(tmp_3d(grid%is_me:grid%ie_me, grid%js_me:grid%je_me,grid%km))
2062 tmp_3d = 1.0_r8_kind
2064 write( out_unit,* )xmap%grids(g)%id,
'(',xmap%grids(:)%id,
')=', xxx
2069 if(grid1%id ==
"ATM")
then
2070 allocate(check_data(
size(grid1%area,1),
size(grid1%area,2)))
2071 call random_number(check_data)
2074 if(lnd_ug_id ==0)
then
2079 write( out_unit,* ) &
2080 "Checked data is array of random number between 0 and 1 using "//trim(
interp_method)
2081 write( out_unit,* )grid1%id,
'(',xmap%grids(:)%id,
')=', xxx
2083 deallocate(check_data)
2084 do g=2,
size(xmap%grids(:))
2085 allocate(check_data_3d(xmap%grids(g)%is_me:xmap%grids(g)%ie_me, &
2086 xmap%grids(g)%js_me:xmap%grids(g)%je_me, grid1%km))
2087 call random_number(check_data_3d)
2088 if(lnd_ug_id ==0)
then
2093 write( out_unit,* )xmap%grids(g)%id,
'(',xmap%grids(:)%id,
')=', xxx
2094 deallocate( check_data_3d)
2097 call mpp_clock_end(id_conservation_check)
2099 call mpp_clock_end(id_setup_xmap)
2108 ie_nest_out, js_nest_out, je_nest_out, is_parent_out, &
2109 ie_parent_out, js_parent_out, je_parent_out) &
2111 type(fmsnetcdffile_t),
intent(in) :: fileobj
2112 integer,
intent(out) :: tile_nest_out, tile_parent_out
2113 integer,
intent(out) :: is_nest_out, ie_nest_out
2114 integer,
intent(out) :: js_nest_out, je_nest_out
2115 integer,
intent(out) :: is_parent_out, ie_parent_out
2116 integer,
intent(out) :: js_parent_out, je_parent_out
2119 integer :: ntiles, ncontacts, n, t1, t2
2120 integer :: nx1_contact, ny1_contact
2121 integer :: nx2_contact, ny2_contact
2122 integer,
allocatable,
dimension(:) :: nx, ny
2123 integer,
allocatable,
dimension(:) :: tile1, tile2
2124 integer,
allocatable,
dimension(:) :: istart1, iend1, jstart1, jend1
2125 integer,
allocatable,
dimension(:) :: istart2, iend2, jstart2, jend2
2127 tile_nest_out = 0; tile_parent_out = 0
2128 is_nest_out = 0; ie_nest_out = 0
2129 js_nest_out = 0; je_nest_out = 0
2130 is_parent_out = 0; ie_parent_out = 0
2131 js_parent_out = 0; je_parent_out = 0
2135 ntiles = get_mosaic_ntiles(fileobj)
2136 if( ntiles == 1 )
return
2138 allocate(nx(ntiles), ny(ntiles))
2139 call get_mosaic_grid_sizes(fileobj, nx, ny)
2141 ncontacts = get_mosaic_ncontacts(fileobj)
2142 if(ncontacts == 0)
return
2143 allocate(tile1(ncontacts), tile2(ncontacts))
2144 allocate(istart1(ncontacts), iend1(ncontacts))
2145 allocate(jstart1(ncontacts), jend1(ncontacts))
2146 allocate(istart2(ncontacts), iend2(ncontacts))
2147 allocate(jstart2(ncontacts), jend2(ncontacts))
2149 call get_mosaic_contact( fileobj, tile1, tile2, istart1, iend1, jstart1, jend1, &
2150 istart2, iend2, jstart2, jend2)
2153 if( tile1(n) == tile2(n) ) cycle
2155 nx1_contact = iend1(n)-istart1(n)+1
2156 ny1_contact = jend1(n)-jstart1(n)+1
2157 nx2_contact = iend2(n)-istart2(n)+1
2158 ny2_contact = jend2(n)-jstart2(n)+1
2162 if( (nx(t1) .NE. nx1_contact .OR. ny(t1) .NE. ny1_contact ) .AND. &
2163 (nx(t2) .NE. nx2_contact .OR. ny(t2) .NE. ny2_contact ) ) cycle
2164 if(nx1_contact == nx2_contact .AND. ny1_contact == ny2_contact)
then
2165 call error_mesg(
'xgrid_mod',
'There is no refinement for the overlapping region', fatal)
2170 call error_mesg(
'xgrid_mod',
'only support one nest region, contact developer' ,fatal)
2172 if(nx2_contact*ny2_contact > nx1_contact*ny1_contact)
then
2173 is_nest_out = istart2(n);
2174 ie_nest_out = iend2(n);
2175 js_nest_out = jstart2(n);
2176 je_nest_out = jend2(n);
2177 tile_nest_out = tile2(n);
2178 is_parent_out = istart1(n);
2179 ie_parent_out = iend1(n);
2180 js_parent_out = jstart1(n);
2181 je_parent_out = jend1(n);
2182 tile_parent_out = tile1(n);
2184 is_nest_out = istart1(n);
2185 ie_nest_out = iend1(n);
2186 js_nest_out = jstart1(n);
2187 je_nest_out = jend1(n);
2188 tile_nest_out = tile1(n);
2189 is_parent_out = istart2(n);
2190 ie_parent_out = iend2(n);
2191 js_parent_out = jstart2(n);
2192 je_parent_out = jend2(n);
2193 tile_parent_out = tile2(n);
2197 deallocate(nx, ny, tile1, tile2)
2198 deallocate(istart1, iend1, jstart1, jend1)
2199 deallocate(istart2, iend2, jstart2, jend2)
2207 subroutine set_comm_get1_repro(xmap)
2209 integer,
dimension(xmap%npes) :: pe_ind, cnt
2210 integer,
dimension(0:xmap%npes-1) :: send_ind, pl
2211 integer :: npes, nsend, nrecv, mypos
2212 integer :: m, p, pos, n, g, l, im, i, j
2213 type(
comm_type),
pointer,
save :: comm => null()
2215 comm => xmap%get1_repro
2219 mypos =
mpp_pe() - mpp_root_pe()
2221 p = mod(mypos+npes-m, npes)
2222 if( xmap%recv_count_repro(p) > 0 )
then
2229 if( nrecv > 0 )
then
2230 if (
associated(comm%recv))
deallocate(comm%recv)
2231 allocate(comm%recv(nrecv))
2235 comm%recv(n)%count = xmap%recv_count_repro(p)
2236 comm%recv(n)%pe = p + xmap%root_pe
2237 comm%recv(n)%buffer_pos = pos
2238 pos = pos + comm%recv(n)%count
2245 mypos =
mpp_pe() - mpp_root_pe()
2247 p = mod(mypos+m, npes)
2248 if( xmap%send_count_repro(p) > 0 )
then
2256 if( nsend > 0 )
then
2257 if (
associated(comm%send))
deallocate(comm%send)
2258 allocate(comm%send(nsend))
2263 comm%send(n)%count = xmap%send_count_repro(p)
2264 comm%send(n)%pe = p + xmap%root_pe
2265 comm%send(n)%buffer_pos = pos
2266 pos = pos + comm%send(n)%count
2267 allocate(comm%send(n)%i(comm%send(n)%count))
2268 allocate(comm%send(n)%j(comm%send(n)%count))
2269 allocate(comm%send(n)%g(comm%send(n)%count))
2270 allocate(comm%send(n)%xLoc(comm%send(n)%count))
2273 do g=2,
size(xmap%grids(:))
2274 im = xmap%grids(g)%im
2275 do l=1,xmap%grids(g)%size
2276 p = xmap%grids(g)%x(l)%pe-xmap%root_pe
2280 i = xmap%grids(g)%x(l)%i2
2281 j = xmap%grids(g)%x(l)%j2
2282 if(xmap%grids(g)%is_ug)
then
2283 comm%send(n)%i(pos) = xmap%grids(g)%l_index((j-1)*im+i)
2284 comm%send(n)%j(pos) = 1
2286 comm%send(n)%i(pos) = xmap%grids(g)%x(l)%i2
2287 comm%send(n)%j(pos) = xmap%grids(g)%x(l)%j2
2289 comm%send(n)%g(pos) = g
2294 if( comm%send(n)%count .NE. cnt(n) )
call error_mesg(
'xgrid_mod', &
2295 .NE.
'comm%send(n)%count cnt(n)', fatal)
2301 do g=2,
size(xmap%grids(:))
2302 do l=1,xmap%grids(g)%size_repro
2303 p = xmap%grids(g)%x_repro(l)%pe-xmap%root_pe
2304 xmap%grids(g)%x_repro(l)%recv_pos = pl(p)
2311 end subroutine set_comm_get1_repro
2314 subroutine set_comm_get1(xmap)
2316 type (
grid_type),
pointer,
save :: grid1 =>null()
2317 integer,
allocatable :: send_size(:)
2318 integer,
allocatable :: recv_size(:)
2319 integer :: max_size, g, npes, l, ll, nset, m
2320 integer :: i1, j1, tile1, p, n, pos, buffer_pos, mypos
2321 integer :: nsend, nrecv, rbuf_size, sbuf_size, msgsize
2323 real(r8_kind),
allocatable :: recv_buf(:), send_buf(:)
2324 real(r8_kind),
allocatable :: diarray(:), djarray(:)
2325 integer,
allocatable :: iarray(:), jarray(:), tarray(:)
2326 integer,
allocatable :: pos_x(:), pelist(:), size_pe(:), pe_side1(:)
2327 integer :: recv_buffer_pos(0:xmap%npes)
2328 integer :: send_buffer_pos(0:xmap%npes)
2329 type(
comm_type),
pointer,
save :: comm => null()
2333 do g=2,
size(xmap%grids(:))
2334 max_size = max_size + xmap%grids(g)%size
2337 grid1 => xmap%grids(1)
2342 allocate(pelist(0:npes-1))
2343 call mpp_get_current_pelist(pelist)
2344 allocate(send_size(0:npes-1))
2345 allocate(recv_size(0:npes-1))
2346 allocate(size_pe(0:npes-1))
2347 allocate(pos_x(0:npes-1))
2352 if(max_size > 0)
then
2353 allocate(pe_side1(max_size))
2354 if (
associated(xmap%ind_get1))
deallocate(xmap%ind_get1)
2355 allocate(xmap%ind_get1(max_size))
2359 do g=2,
size(xmap%grids(:))
2360 do l=1,xmap%grids(g)%size
2361 i1 = xmap%grids(g)%x(l)%i1
2362 j1 = xmap%grids(g)%x(l)%j1
2363 tile1 = xmap%grids(g)%x(l)%tile
2365 if(grid1%tile(p) == tile1)
then
2367 size_pe(p) = size_pe(p) + 1
2372 if( p == npes )
then
2373 call error_mesg(
'xgrid_mod',
'tile is not in grid1%tile(:)', fatal)
2382 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2386 allocate(iarray(max_size))
2387 allocate(jarray(max_size))
2388 allocate(tarray(max_size))
2389 if(monotonic_exchange)
then
2390 allocate(diarray(max_size))
2391 allocate(djarray(max_size))
2396 do g=2,
size(xmap%grids(:))
2397 do l=1,xmap%grids(g)%size
2398 i1 = xmap%grids(g)%x(l)%i1
2399 j1 = xmap%grids(g)%x(l)%j1
2400 tile1 = xmap%grids(g)%x(l)%tile
2405 if(send_size(p) > 0)
then
2406 if( i1 == iarray(pos_x(p)+send_size(p)) .AND. j1 == jarray(pos_x(p)+send_size(p)) &
2407 .AND. tile1 == tarray(pos_x(p)+send_size(p)))
then
2412 do n = 1, send_size(p)
2413 if(i1 == iarray(pos_x(p)+n) .AND. j1 == jarray(pos_x(p)+n) .AND. tile1 == tarray(pos_x(p)+n))
then
2420 if( (.NOT. found) .OR. monotonic_exchange )
then
2421 send_size(p) = send_size(p)+1
2422 pos = pos_x(p)+send_size(p)
2426 if(monotonic_exchange)
then
2427 diarray(pos) = xmap%grids(g)%x(l)%di
2428 djarray(pos) = xmap%grids(g)%x(l)%dj
2432 xmap%ind_get1(ll) = n
2438 pos_x(p) = pos_x(p-1) + send_size(p-1)
2442 do g=2,
size(xmap%grids(:))
2443 do l=1,xmap%grids(g)%size
2446 xmap%ind_get1(ll) = pos_x(p) + xmap%ind_get1(ll)
2451 mypos =
mpp_pe()-mpp_root_pe()
2454 recv_size(:) = xmap%your2my1_size(:)
2455 nsend = count( send_size> 0)
2458 if (
associated(comm%send))
deallocate(comm%send)
2459 allocate(comm%send(nsend))
2460 comm%send(:)%count = 0
2465 send_buffer_pos(p) = pos
2466 pos = pos + send_size(p)
2472 p = mod(mypos+n, npes)
2473 if(send_size(p)>0)
then
2475 allocate(comm%send(pos)%i(send_size(p)))
2476 comm%send(pos)%buffer_pos = send_buffer_pos(p)
2477 comm%send(pos)%count = send_size(p)
2478 comm%send(pos)%pe = pelist(p)
2479 comm%sendsize = comm%sendsize + send_size(p)
2484 if(monotonic_exchange) nset = 5
2485 rbuf_size = sum(recv_size)*nset
2486 sbuf_size = sum(send_size)*nset
2487 if(rbuf_size>0)
allocate(recv_buf(rbuf_size))
2488 if(sbuf_size>0)
allocate(send_buf(sbuf_size))
2492 p = mod(mypos+npes-n, npes)
2493 if(recv_size(p) ==0) cycle
2494 msgsize = recv_size(p)*nset
2495 call mpp_recv(recv_buf(pos+1), glen=msgsize, from_pe=pelist(p), block=.false., tag=comm_tag_4)
2501 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2506 p = mod(mypos+n, npes)
2507 do l = 1, send_size(p)
2508 send_buf(pos+1) = real(iarray(pos_x(p)+l), r8_kind)
2509 send_buf(pos+2) = real(jarray(pos_x(p)+l), r8_kind)
2510 send_buf(pos+3) = real(tarray(pos_x(p)+l), r8_kind)
2511 if(monotonic_exchange)
then
2512 send_buf(pos+4) = diarray(pos_x(p)+l)
2513 send_buf(pos+5) = djarray(pos_x(p)+l)
2521 p = mod(mypos+n, npes)
2522 if(send_size(p) ==0) cycle
2523 msgsize = send_size(p)*nset
2524 call mpp_send(send_buf(pos+1), plen=msgsize, to_pe=pelist(p), tag=comm_tag_4 )
2529 nrecv = count(recv_size>0)
2534 if (
associated(comm%recv))
deallocate(comm%recv)
2535 allocate(comm%recv(nrecv))
2536 comm%recv(:)%count = 0
2540 recv_buffer_pos(p) = buffer_pos
2541 buffer_pos = buffer_pos + recv_size(p)
2546 p = mod(mypos+npes-m, npes)
2547 if(recv_size(p)>0)
then
2549 allocate(comm%recv(pos)%i(recv_size(p)))
2550 allocate(comm%recv(pos)%j(recv_size(p)))
2551 allocate(comm%recv(pos)%tile(recv_size(p)))
2552 comm%recv(pos)%buffer_pos = recv_buffer_pos(p)
2553 comm%recv(pos)%pe = pelist(p)
2554 comm%recv(pos)%count = recv_size(p)
2555 comm%recvsize = comm%recvsize + recv_size(p)
2556 if(monotonic_exchange)
then
2557 allocate(comm%recv(pos)%di(recv_size(p)))
2558 allocate(comm%recv(pos)%dj(recv_size(p)))
2560 if(grid1%is_ug)
then
2561 do n = 1, recv_size(p)
2562 i = int(recv_buf(buffer_pos+1))
2563 j = int(recv_buf(buffer_pos+2))
2564 comm%recv(pos)%i(n) = grid1%l_index((j-1)*grid1%im+i)
2565 comm%recv(pos)%j(n) = 1
2566 comm%recv(pos)%tile(n) = int(recv_buf(buffer_pos+3))
2567 if(monotonic_exchange)
then
2568 comm%recv(pos)%di(n) = recv_buf(buffer_pos+4)
2569 comm%recv(pos)%dj(n) = recv_buf(buffer_pos+5)
2571 buffer_pos = buffer_pos + nset
2574 do n = 1, recv_size(p)
2575 comm%recv(pos)%i(n) = int(recv_buf(buffer_pos+1) )- grid1%is_me + 1
2576 comm%recv(pos)%j(n) = int(recv_buf(buffer_pos+2) )- grid1%js_me + 1
2577 comm%recv(pos)%tile(n) = int(recv_buf(buffer_pos+3))
2578 if(monotonic_exchange)
then
2579 comm%recv(pos)%di(n) = recv_buf(buffer_pos+4)
2580 comm%recv(pos)%dj(n) = recv_buf(buffer_pos+5)
2582 buffer_pos = buffer_pos + nset
2587 if (
associated(comm%unpack_ind))
deallocate(comm%unpack_ind)
2588 allocate(comm%unpack_ind(nrecv))
2591 if(recv_size(p)>0)
then
2594 if(comm%recv(m)%pe == pelist(p))
then
2595 comm%unpack_ind(pos) = m
2604 if(
allocated(send_buf) )
deallocate(send_buf)
2605 if(
allocated(recv_buf) )
deallocate(recv_buf)
2606 if(
allocated(pelist) )
deallocate(pelist)
2607 if(
allocated(pos_x) )
deallocate(pos_x)
2608 if(
allocated(pelist) )
deallocate(pelist)
2609 if(
allocated(iarray) )
deallocate(iarray)
2610 if(
allocated(jarray) )
deallocate(jarray)
2611 if(
allocated(tarray) )
deallocate(tarray)
2612 if(
allocated(size_pe) )
deallocate(size_pe)
2614 end subroutine set_comm_get1
2617 subroutine set_comm_put1(xmap)
2619 type (
grid_type),
pointer,
save :: grid1 =>null()
2620 integer,
allocatable :: send_size(:)
2621 integer,
allocatable :: recv_size(:)
2622 integer :: max_size, g, npes, l, ll, m, mypos
2623 integer :: i1, j1, tile1, p, n, pos, buffer_pos
2624 integer :: nsend, nrecv, msgsize, nset, rbuf_size, sbuf_size
2626 real(r8_kind),
allocatable :: recv_buf(:), send_buf(:)
2627 real(r8_kind),
allocatable :: diarray(:), djarray(:)
2628 integer,
allocatable :: iarray(:), jarray(:), tarray(:)
2629 integer,
allocatable :: pos_x(:), pelist(:), size_pe(:), pe_put1(:)
2630 integer :: recv_buffer_pos(0:xmap%npes)
2631 type(
comm_type),
pointer,
save :: comm => null()
2635 if(nnest == 0 .OR. xmap%grids(1)%id .NE.
'ATM' )
then
2636 comm%nsend = xmap%get1%nrecv
2637 comm%nrecv = xmap%get1%nsend
2638 comm%sendsize = xmap%get1%recvsize
2639 comm%recvsize = xmap%get1%sendsize
2640 comm%send => xmap%get1%recv
2641 comm%recv => xmap%get1%send
2642 xmap%ind_put1 => xmap%ind_get1
2647 do g=2,
size(xmap%grids(:))
2648 max_size = max_size + xmap%grids(g)%size
2650 grid1 => xmap%grids(1)
2654 allocate(pelist(0:npes-1))
2655 call mpp_get_current_pelist(pelist)
2656 allocate(send_size(0:npes-1))
2657 allocate(recv_size(0:npes-1))
2658 allocate(size_pe(0:npes-1))
2659 allocate(pos_x(0:npes-1))
2664 if(max_size > 0)
then
2665 allocate(pe_put1(max_size))
2666 if (
associated(xmap%ind_put1))
deallocate(xmap%ind_put1)
2667 allocate(xmap%ind_put1(max_size))
2671 do g=2,
size(xmap%grids(:))
2672 do l=1,xmap%grids(g)%size
2673 i1 = xmap%grids(g)%x(l)%i1
2674 j1 = xmap%grids(g)%x(l)%j1
2675 tile1 = xmap%grids(g)%x(l)%tile
2677 if(grid1%tile(p) == tile1)
then
2678 if(
in_box(i1, j1, grid1%is(p), grid1%ie(p), grid1%js(p), grid1%je(p)))
then
2679 size_pe(p) = size_pe(p) + 1
2691 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2695 allocate(iarray(max_size))
2696 allocate(jarray(max_size))
2697 allocate(tarray(max_size))
2698 if(monotonic_exchange)
then
2699 allocate(diarray(max_size))
2700 allocate(djarray(max_size))
2705 do g=2,
size(xmap%grids(:))
2706 do l=1,xmap%grids(g)%size
2707 i1 = xmap%grids(g)%x(l)%i1
2708 j1 = xmap%grids(g)%x(l)%j1
2709 tile1 = xmap%grids(g)%x(l)%tile
2714 if(send_size(p) > 0)
then
2715 if( i1 == iarray(pos_x(p)+send_size(p)) .AND. j1 == jarray(pos_x(p)+send_size(p)) &
2716 .AND. tile1 == tarray(pos_x(p)+send_size(p)))
then
2721 do n = 1, send_size(p)
2722 if(i1 == iarray(pos_x(p)+n) .AND. j1 == jarray(pos_x(p)+n) .AND. tile1 == tarray(pos_x(p)+n))
then
2729 if( (.NOT. found) .OR. monotonic_exchange )
then
2730 send_size(p) = send_size(p)+1
2731 pos = pos_x(p)+send_size(p)
2735 if(monotonic_exchange)
then
2736 diarray(pos) = xmap%grids(g)%x(l)%di
2737 djarray(pos) = xmap%grids(g)%x(l)%dj
2741 xmap%ind_put1(ll) = n
2747 pos_x(p) = pos_x(p-1) + send_size(p-1)
2751 do g=2,
size(xmap%grids(:))
2752 do l=1,xmap%grids(g)%size
2753 i1 = xmap%grids(g)%x(l)%i1
2754 j1 = xmap%grids(g)%x(l)%j1
2755 tile1 = xmap%grids(g)%x(l)%tile
2758 xmap%ind_put1(ll) = pos_x(p) + xmap%ind_put1(ll)
2764 mypos =
mpp_pe()-mpp_root_pe()
2766 if (do_alltoall)
then
2767 call mpp_alltoall(send_size, 1, recv_size, 1)
2770 p = mod(mypos+npes-n, npes)
2771 call mpp_recv(recv_size(p), glen=1, from_pe=pelist(p), block=.false., tag=comm_tag_5)
2776 p = mod(mypos+n, npes)
2777 call mpp_send(send_size(p), plen=1, to_pe=pelist(p), tag=comm_tag_5)
2784 nrecv = count( send_size> 0)
2787 if (
associated(comm%recv))
deallocate(comm%recv)
2788 allocate(comm%recv(nrecv))
2789 comm%recv(:)%count = 0
2794 recv_buffer_pos(p) = pos
2795 pos = pos + send_size(p)
2800 p = mod(mypos+npes-n, npes)
2801 if(send_size(p)>0)
then
2803 allocate(comm%recv(pos)%i(send_size(p)))
2804 comm%recv(pos)%buffer_pos = recv_buffer_pos(p)
2805 comm%recv(pos)%count = send_size(p)
2806 comm%recv(pos)%pe = pelist(p)
2807 comm%recvsize = comm%recvsize + send_size(p)
2812 if(monotonic_exchange) nset = 5
2813 rbuf_size = sum(recv_size)*nset
2814 sbuf_size = sum(send_size)*nset
2815 if(rbuf_size>0)
allocate(recv_buf(rbuf_size))
2816 if(sbuf_size>0)
allocate(send_buf(sbuf_size))
2820 p = mod(mypos+npes-n, npes)
2821 if(recv_size(p) ==0) cycle
2822 msgsize = recv_size(p)*nset
2823 call mpp_recv(recv_buf(pos+1), glen=msgsize, from_pe=pelist(p), block=.false., tag=comm_tag_6)
2829 pos_x(p) = pos_x(p-1) + size_pe(p-1)
2834 p = mod(mypos+n, npes)
2835 do l = 1, send_size(p)
2836 send_buf(pos+1) = real(iarray(pos_x(p)+l), r8_kind)
2837 send_buf(pos+2) = real(jarray(pos_x(p)+l), r8_kind)
2838 send_buf(pos+3) = real(tarray(pos_x(p)+l), r8_kind)
2839 if(monotonic_exchange)
then
2840 send_buf(pos+4) = diarray(pos_x(p)+l)
2841 send_buf(pos+5) = djarray(pos_x(p)+l)
2849 p = mod(mypos+n, npes)
2850 if(send_size(p) ==0) cycle
2851 msgsize = send_size(p)*nset
2852 call mpp_send(send_buf(pos+1), plen=msgsize, to_pe=pelist(p), tag=comm_tag_6 )
2857 nsend = count(recv_size>0)
2862 if (
associated(comm%send))
deallocate(comm%send)
2863 allocate(comm%send(nsend))
2864 comm%send(:)%count = 0
2868 p = mod(mypos+npes-m, npes)
2869 if(recv_size(p)>0)
then
2871 allocate(comm%send(pos)%i(recv_size(p)))
2872 allocate(comm%send(pos)%j(recv_size(p)))
2873 allocate(comm%send(pos)%tile(recv_size(p)))
2874 comm%send(pos)%pe = pelist(p)
2875 comm%send(pos)%count = recv_size(p)
2876 comm%sendsize = comm%sendsize + recv_size(p)
2877 if(monotonic_exchange)
then
2878 allocate(comm%send(pos)%di(recv_size(p)))
2879 allocate(comm%send(pos)%dj(recv_size(p)))
2881 do n = 1, recv_size(p)
2882 comm%send(pos)%i(n) = int(recv_buf(buffer_pos+1) )- grid1%is_me + 1
2883 comm%send(pos)%j(n) = int(recv_buf(buffer_pos+2) )- grid1%js_me + 1
2884 comm%send(pos)%tile(n) = int(recv_buf(buffer_pos+3))
2885 if(monotonic_exchange)
then
2886 comm%send(pos)%di(n) = recv_buf(buffer_pos+4)
2887 comm%send(pos)%dj(n) = recv_buf(buffer_pos+5)
2889 buffer_pos = buffer_pos + nset
2896 if(
allocated(send_buf) )
deallocate(send_buf)
2897 if(
allocated(recv_buf) )
deallocate(recv_buf)
2898 if(
allocated(pelist) )
deallocate(pelist)
2899 if(
allocated(pos_x) )
deallocate(pos_x)
2900 if(
allocated(pelist) )
deallocate(pelist)
2901 if(
allocated(iarray) )
deallocate(iarray)
2902 if(
allocated(jarray) )
deallocate(jarray)
2903 if(
allocated(tarray) )
deallocate(tarray)
2904 if(
allocated(size_pe) )
deallocate(size_pe)
2906 end subroutine set_comm_put1
2930 type (xmap_type),
intent(inout) :: xmap
2932 integer :: g, l, k, max_size
2933 integer :: i1, j1, i2, j2, p
2936 logical :: overlap_with_nest
2937 integer :: cnt(xmap%get1%nsend)
2938 integer :: i,j,n,xloc,pos,nsend,m,npes, mypos
2939 integer :: send_ind(0:xmap%npes-1)
2943 do g=2,
size(xmap%grids(:))
2944 max_size = max_size + xmap%grids(g)%size * xmap%grids(g)%km
2947 if (max_size>
size(xmap%x1(:)))
then
2948 if (
associated(xmap%x1))
deallocate(xmap%x1)
2949 if (
associated(xmap%x2))
deallocate(xmap%x2)
2950 allocate( xmap%x1(1:max_size) )
2951 allocate( xmap%x2(1:max_size) )
2955 do g=2,
size(xmap%grids(:))
2956 xmap%grids(g)%first = 1
2957 xmap%grids(g)%last = 0
2962 do g=2,
size(xmap%grids(:))
2963 xmap%grids(g)%first = xmap%size + 1;
2965 do l=1,xmap%grids(g)%size
2966 i1 = xmap%grids(g)%x(l)%i1
2967 j1 = xmap%grids(g)%x(l)%j1
2968 i2 = xmap%grids(g)%x(l)%i2
2969 j2 = xmap%grids(g)%x(l)%j2
2970 tile1 = xmap%grids(g)%x(l)%tile
2972 if(xmap%grids(g)%is_ug)
then
2973 do k=1,xmap%grids(g)%km
2974 lll = xmap%grids(g)%l_index((j2-1)*xmap%grids(g)%im+i2)
2975 if (xmap%grids(g)%frac_area(lll,1,k)/=0.0_r8_kind)
then
2976 xmap%size = xmap%size+1
2977 xmap%x1(xmap%size)%pos = xmap%ind_get1(ll)
2978 xmap%x1(xmap%size)%i = xmap%grids(g)%x(l)%i1
2979 xmap%x1(xmap%size)%j = xmap%grids(g)%x(l)%j1
2980 xmap%x1(xmap%size)%tile = xmap%grids(g)%x(l)%tile
2981 xmap%x1(xmap%size)%area = xmap%grids(g)%x(l)%area &
2982 *xmap%grids(g)%frac_area(lll,1,k)
2983 xmap%x1(xmap%size)%di = xmap%grids(g)%x(l)%di
2984 xmap%x1(xmap%size)%dj = xmap%grids(g)%x(l)%dj
2985 xmap%x2(xmap%size)%i = xmap%grids(g)%x(l)%i2
2986 xmap%x2(xmap%size)%j = xmap%grids(g)%x(l)%j2
2987 xmap%x2(xmap%size)%l = lll
2988 xmap%x2(xmap%size)%k = k
2989 xmap%x2(xmap%size)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
2993 do k=1,xmap%grids(g)%km
2994 if (xmap%grids(g)%frac_area(i2,j2,k)/=0.0_r8_kind)
then
2995 xmap%size = xmap%size+1
2996 xmap%x1(xmap%size)%pos = xmap%ind_get1(ll)
2997 xmap%x1(xmap%size)%i = xmap%grids(g)%x(l)%i1
2998 xmap%x1(xmap%size)%j = xmap%grids(g)%x(l)%j1
2999 xmap%x1(xmap%size)%tile = xmap%grids(g)%x(l)%tile
3000 xmap%x1(xmap%size)%area = xmap%grids(g)%x(l)%area &
3001 *xmap%grids(g)%frac_area(i2,j2,k)
3002 xmap%x1(xmap%size)%di = xmap%grids(g)%x(l)%di
3003 xmap%x1(xmap%size)%dj = xmap%grids(g)%x(l)%dj
3004 xmap%x2(xmap%size)%i = xmap%grids(g)%x(l)%i2
3005 xmap%x2(xmap%size)%j = xmap%grids(g)%x(l)%j2
3006 xmap%x2(xmap%size)%k = k
3007 xmap%x2(xmap%size)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
3012 xmap%grids(g)%last = xmap%size
3016 if (max_size>
size(xmap%x1_put(:)))
then
3017 if (
associated(xmap%x1_put))
deallocate(xmap%x1_put)
3018 allocate( xmap%x1_put(1:max_size) )
3020 if (max_size>
size(xmap%x2_get(:)))
then
3021 if (
associated(xmap%x2_get))
deallocate(xmap%x2_get)
3022 allocate( xmap%x2_get(1:max_size) )
3025 do g=2,
size(xmap%grids(:))
3026 xmap%grids(g)%first_get = 1
3027 xmap%grids(g)%last_get = 0
3033 do g=2,
size(xmap%grids(:))
3034 xmap%grids(g)%first_get = xmap%size_get2 + 1;
3036 do l=1,xmap%grids(g)%size
3037 i1 = xmap%grids(g)%x(l)%i1
3038 j1 = xmap%grids(g)%x(l)%j1
3039 i2 = xmap%grids(g)%x(l)%i2
3040 j2 = xmap%grids(g)%x(l)%j2
3041 tile1 = xmap%grids(g)%x(l)%tile
3043 overlap_with_nest = .false.
3044 if( xmap%grids(1)%id ==
"ATM" .AND. tile1 == tile_parent .AND. &
3045 in_box(i1, j1, is_parent, ie_parent, js_parent, je_parent) ) overlap_with_nest = .true.
3046 if(xmap%grids(g)%is_ug)
then
3047 do k=1,xmap%grids(g)%km
3048 lll = xmap%grids(g)%l_index((j2-1)*xmap%grids(g)%im+i2)
3049 if (xmap%grids(g)%frac_area(lll,1,k)/=0.0_r8_kind)
then
3050 xmap%size_put1 = xmap%size_put1+1
3051 xmap%x1_put(xmap%size_put1)%pos = xmap%ind_put1(ll)
3052 xmap%x1_put(xmap%size_put1)%i = xmap%grids(g)%x(l)%i1
3053 xmap%x1_put(xmap%size_put1)%j = xmap%grids(g)%x(l)%j1
3054 xmap%x1_put(xmap%size_put1)%tile = xmap%grids(g)%x(l)%tile
3055 xmap%x1_put(xmap%size_put1)%area = xmap%grids(g)%x(l)%area &
3056 *xmap%grids(g)%frac_area(lll,1,k)
3057 xmap%x1_put(xmap%size_put1)%di = xmap%grids(g)%x(l)%di
3058 xmap%x1_put(xmap%size_put1)%dj = xmap%grids(g)%x(l)%dj
3059 if( .not. overlap_with_nest)
then
3060 xmap%size_get2 = xmap%size_get2+1
3061 xmap%x2_get(xmap%size_get2)%i = xmap%grids(g)%x(l)%i2
3062 xmap%x2_get(xmap%size_get2)%j = xmap%grids(g)%x(l)%j2
3063 xmap%x2_get(xmap%size_get2)%l = lll
3064 xmap%x2_get(xmap%size_get2)%k = k
3065 xmap%x2_get(xmap%size_get2)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
3066 xmap%x2_get(xmap%size_get2)%pos = xmap%size_put1
3071 do k=1,xmap%grids(g)%km
3072 if (xmap%grids(g)%frac_area(i2,j2,k)/=0.0_r8_kind)
then
3073 xmap%size_put1 = xmap%size_put1+1
3074 xmap%x1_put(xmap%size_put1)%pos = xmap%ind_put1(ll)
3075 xmap%x1_put(xmap%size_put1)%i = xmap%grids(g)%x(l)%i1
3076 xmap%x1_put(xmap%size_put1)%j = xmap%grids(g)%x(l)%j1
3077 xmap%x1_put(xmap%size_put1)%tile = xmap%grids(g)%x(l)%tile
3078 xmap%x1_put(xmap%size_put1)%area = xmap%grids(g)%x(l)%area &
3079 *xmap%grids(g)%frac_area(i2,j2,k)
3080 xmap%x1_put(xmap%size_put1)%di = xmap%grids(g)%x(l)%di
3081 xmap%x1_put(xmap%size_put1)%dj = xmap%grids(g)%x(l)%dj
3082 if( .not. overlap_with_nest)
then
3083 xmap%size_get2 = xmap%size_get2+1
3084 xmap%x2_get(xmap%size_get2)%i = xmap%grids(g)%x(l)%i2
3085 xmap%x2_get(xmap%size_get2)%j = xmap%grids(g)%x(l)%j2
3086 xmap%x2_get(xmap%size_get2)%k = k
3087 xmap%x2_get(xmap%size_get2)%area = xmap%grids(g)%x(l)%area * xmap%grids(g)%x(l)%scale
3088 xmap%x2_get(xmap%size_get2)%pos = xmap%size_put1
3094 xmap%grids(g)%last_get = xmap%size_get2
3099 if (xmap%get1_repro%nsend > 0)
then
3103 mypos =
mpp_pe() - mpp_root_pe()
3106 p = mod(mypos+m, npes)
3107 if( xmap%send_count_repro(p) > 0 )
then
3112 do g=2,
size(xmap%grids(:))
3113 do l=1,xmap%grids(g)%size
3114 p = xmap%grids(g)%x(l)%pe-xmap%root_pe
3118 xmap%get1_repro%send(n)%xLoc(pos) = xloc
3119 if( xmap%grids(g)%is_ug )
then
3120 i = xmap%grids(g)%x(l)%l2
3121 xloc = xloc + count(xmap%grids(g)%frac_area(i,1,:)/=0.0_r8_kind)
3123 i = xmap%grids(g)%x(l)%i2
3124 j = xmap%grids(g)%x(l)%j2
3125 xloc = xloc + count(xmap%grids(g)%frac_area(i,j,:)/=0.0_r8_kind)
3132 end subroutine regen
3163 real(r8_kind),
dimension(:,:,:),
intent(in) :: f
3164 character(len=3),
intent(in) :: grid_id
3165 type (xmap_type),
intent(inout) :: xmap
3168 type(
grid_type),
pointer,
save :: grid =>null()
3170 if (grid_id==xmap%grids(1)%id)
call error_mesg (
'xgrid_mod', &
3171 'set_frac_area called on side 1 grid', fatal)
3172 do g=2,
size(xmap%grids(:))
3173 grid => xmap%grids(g)
3174 if (grid_id==grid%id)
then
3175 if (
size(f,3)/=
size(grid%frac_area,3))
then
3176 if (
associated(grid%frac_area))
deallocate (grid%frac_area)
3177 grid%km =
size(f,3);
3178 allocate( grid%frac_area(grid%is_me:grid%ie_me, grid%js_me:grid%je_me, &
3187 call error_mesg (
'xgrid_mod',
'set_frac_area: could not find grid id', fatal)
3195 real(r8_kind),
dimension(:,:),
intent(in) :: f
3196 character(len=3),
intent(in) :: grid_id
3197 type (xmap_type),
intent(inout) :: xmap
3200 type(
grid_type),
pointer,
save :: grid =>null()
3202 if (grid_id==xmap%grids(1)%id)
call error_mesg (
'xgrid_mod', &
3203 'set_frac_area_ug called on side 1 grid', fatal)
3204 if (grid_id .NE.
'LND' )
call error_mesg (
'xgrid_mod', &
3205 .NE.
'set_frac_area_ug called for grid_id LND', fatal)
3206 do g=2,
size(xmap%grids(:))
3207 grid => xmap%grids(g)
3208 if (grid_id==grid%id)
then
3209 if (
size(f,2)/=
size(grid%frac_area,3))
then
3210 if (
associated(grid%frac_area))
deallocate (grid%frac_area)
3211 grid%km =
size(f,2);
3212 allocate( grid%frac_area(grid%ls_me:grid%le_me, 1, grid%km) )
3214 grid%frac_area(:,1,:) = f(:,:);
3220 call error_mesg (
'xgrid_mod',
'set_frac_area_ug: could not find grid id', fatal)
3238 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_loc
3239 real(r8_kind),
target,
contiguous,
intent(in) :: d(:,:)
3240 character(len=3),
intent(in) :: grid_id
3241 real(r8_kind),
target,
contiguous,
intent(inout) :: x(:)
3242 type (xmap_type),
intent(inout) :: xmap
3243 integer,
intent(in),
optional :: remap_method
3245 logical,
intent(in),
optional :: complete
3247 logical :: is_complete, set_mismatch
3248 integer :: g, method
3249 character(len=2) :: text
3250 integer,
save :: isize=0
3251 integer,
save :: jsize=0
3252 integer,
save :: lsize=0
3253 integer,
save :: xsize=0
3254 integer,
save :: method_saved=0
3255 character(len=3),
save :: grid_id_saved=
""
3256 type(c_ptr),
dimension(MAX_FIELDS),
save :: d_addrs = c_null_ptr
3257 type(c_ptr),
dimension(MAX_FIELDS),
save :: x_addrs = c_null_ptr
3259 if (grid_id==xmap%grids(1)%id)
then
3260 method = first_order
3261 if(
present(remap_method)) method = remap_method
3262 is_complete = .true.
3263 if(
present(complete)) is_complete=complete
3265 if( lsize > max_fields )
then
3266 write( text,
'(i2)' ) max_fields
3267 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group put_side1_to_xgrid', fatal)
3269 d_addrs(lsize) = c_loc(d)
3270 x_addrs(lsize) = c_loc(x)
3276 method_saved = method
3277 grid_id_saved = grid_id
3279 set_mismatch = .false.
3280 set_mismatch = set_mismatch .OR. (isize /=
size(d,1))
3281 set_mismatch = set_mismatch .OR. (jsize /=
size(d,2))
3282 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
3283 set_mismatch = set_mismatch .OR. (method_saved /= method)
3284 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
3285 if(set_mismatch)
then
3286 write( text,
'(i2)' ) lsize
3287 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text//
' for group put_side1_to_xgrid', fatal )
3291 if(is_complete)
then
3294 if(monotonic_exchange .AND. grid_id ==
'ATM')
then
3295 call put_1_to_xgrid_order_2(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3296 else if(method == first_order)
then
3297 call put_1_to_xgrid_order_1(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3299 if(grid_id .NE.
'ATM')
call error_mesg (
'xgrid_mod', &
3300 "second order put_to_xgrid should only be applied to 'ATM' model, "//&
3301 "contact developer", fatal)
3302 call put_1_to_xgrid_order_2(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3305 d_addrs = c_null_ptr
3306 x_addrs = c_null_ptr
3317 do g=2,
size(xmap%grids(:))
3318 if (grid_id==xmap%grids(g)%id) &
3319 call error_mesg (
'xgrid_mod', &
3320 'put_to_xgrid expects a 3D side 2 grid', fatal)
3323 call error_mesg (
'xgrid_mod',
'put_to_xgrid: could not find grid id', fatal)
3331 real(r8_kind),
dimension(:,:,:),
intent(in) :: d
3332 character(len=3),
intent(in) :: grid_id
3333 real(r8_kind),
dimension(:),
intent(inout) :: x
3334 type (xmap_type),
intent(inout) :: xmap
3338 if (grid_id==xmap%grids(1)%id) &
3339 call error_mesg (
'xgrid_mod', &
3340 'put_side2_to_xgrid expects a 3D side 2 grid', fatal)
3342 do g=2,
size(xmap%grids(:))
3343 if (grid_id==xmap%grids(g)%id)
then
3344 call put_2_to_xgrid(d, xmap%grids(g), x, xmap)
3349 call error_mesg (
'xgrid_mod',
'put_to_xgrid: could not find grid id', fatal)
3356 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_loc
3357 real(r8_kind),
target,
contiguous,
intent(out) :: d(:,:)
3358 character(len=3),
intent(in) :: grid_id
3359 real(r8_kind),
target,
contiguous,
intent(in) :: x(:)
3360 type (xmap_type),
intent(inout) :: xmap
3361 logical,
intent(in),
optional :: complete
3363 logical :: is_complete, set_mismatch
3365 character(len=2) :: text
3366 integer,
save :: isize=0
3367 integer,
save :: jsize=0
3368 integer,
save :: lsize=0
3369 integer,
save :: xsize=0
3370 character(len=3),
save :: grid_id_saved=
""
3371 type(c_ptr),
dimension(MAX_FIELDS),
save :: d_addrs = c_null_ptr
3372 type(c_ptr),
dimension(MAX_FIELDS),
save :: x_addrs = c_null_ptr
3375 if (grid_id==xmap%grids(1)%id)
then
3376 is_complete = .true.
3377 if(
present(complete)) is_complete=complete
3379 if( lsize > max_fields )
then
3380 write( text,
'(i2)' ) max_fields
3381 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group get_side1_from_xgrid', fatal)
3383 d_addrs(lsize) = c_loc(d)
3384 x_addrs(lsize) = c_loc(x)
3390 grid_id_saved = grid_id
3392 set_mismatch = .false.
3393 set_mismatch = set_mismatch .OR. (isize /=
size(d,1))
3394 set_mismatch = set_mismatch .OR. (jsize /=
size(d,2))
3395 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
3396 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
3397 if(set_mismatch)
then
3398 write( text,
'(i2)' ) lsize
3399 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text// &
3400 &
' for group get_side1_from_xgrid', fatal )
3404 if(is_complete)
then
3406 call get_1_from_xgrid_repro(d_addrs, x_addrs, xmap, xsize, lsize)
3408 call get_1_from_xgrid(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3410 d_addrs(1:lsize) = c_null_ptr
3411 x_addrs(1:lsize) = c_null_ptr
3421 do g=2,
size(xmap%grids(:))
3422 if (grid_id==xmap%grids(g)%id) &
3423 call error_mesg (
'xgrid_mod', &
3424 'get_from_xgrid expects a 3D side 2 grid', fatal)
3427 call error_mesg (
'xgrid_mod',
'get_from_xgrid: could not find grid id', fatal)
3434 real(r8_kind),
dimension(:,:,:),
intent(out) :: d
3435 character(len=3),
intent(in) :: grid_id
3436 real(r8_kind),
dimension(:),
intent(in) :: x
3437 type (xmap_type),
intent(in) :: xmap
3441 if (grid_id==xmap%grids(1)%id) &
3442 call error_mesg (
'xgrid_mod', &
3443 'get_from_xgrid expects a 2D side 1 grid', fatal)
3445 do g=2,
size(xmap%grids(:))
3446 if (grid_id==xmap%grids(g)%id)
then
3447 call get_2_from_xgrid(d, xmap%grids(g), x, xmap)
3452 call error_mesg (
'xgrid_mod',
'get_from_xgrid: could not find grid id', fatal)
3459 subroutine some(xmap, some_arr, grid_id)
3461 character(len=3),
optional,
intent(in) :: grid_id
3462 logical,
dimension(:),
intent(out) :: some_arr
3466 if (.not.
present(grid_id))
then
3468 if(xmap%size > 0)
then
3476 if (grid_id==xmap%grids(1)%id) &
3477 call error_mesg (
'xgrid_mod',
'some expects a side 2 grid id', fatal)
3479 do g=2,
size(xmap%grids(:))
3480 if (grid_id==xmap%grids(g)%id)
then
3482 some_arr(xmap%grids(g)%first:xmap%grids(g)%last) = .true.;
3487 call error_mesg (
'xgrid_mod',
'some could not find grid id', fatal)
3493 subroutine put_2_to_xgrid(d, grid, x, xmap)
3495 real(r8_kind),
dimension(grid%is_me:grid%ie_me, &
grid%js_me:grid%je_me, grid%km),
intent(in) :: d
3496 real(r8_kind),
dimension(:),
intent(inout) :: x
3500 call mpp_clock_begin(id_put_2_to_xgrid)
3502 do l=grid%first,grid%last
3503 x(l) = d(xmap%x2(l)%i,xmap%x2(l)%j,xmap%x2(l)%k)
3506 call mpp_clock_end(id_put_2_to_xgrid)
3507 end subroutine put_2_to_xgrid
3511 subroutine get_2_from_xgrid(d, grid, x, xmap)
3513 real(r8_kind),
dimension(grid%is_me:grid%ie_me, &
grid%js_me:grid%je_me, grid%km),
intent(out) :: d
3514 real(r8_kind),
dimension(:),
intent(in) :: x
3519 call mpp_clock_begin(id_get_2_from_xgrid)
3522 do l=grid%first_get,grid%last_get
3523 d(xmap%x2_get(l)%i,xmap%x2_get(l)%j,xmap%x2_get(l)%k) = &
3524 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)
3530 d(:,:,k) = d(:,:,k) * grid%area_inv
3533 call mpp_clock_end(id_get_2_from_xgrid)
3535 end subroutine get_2_from_xgrid
3539 subroutine put_1_to_xgrid_order_1(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3540 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
3541 type(c_ptr),
dimension(:),
intent(in) :: d_addrs
3542 type(c_ptr),
dimension(:),
intent(in) :: x_addrs
3544 integer,
intent(in) :: isize, jsize, xsize, lsize
3546 integer :: i, j, p, buffer_pos, msgsize
3547 integer :: from_pe, to_pe, pos, n, l, count
3548 integer :: ibegin, istart, iend, start_pos
3549 type (
comm_type),
pointer,
save :: comm =>null()
3550 real(r8_kind) :: recv_buffer(xmap%put1%recvsize*lsize)
3551 real(r8_kind) :: send_buffer(xmap%put1%sendsize*lsize)
3552 real(r8_kind) :: unpack_buffer(xmap%put1%recvsize)
3554 real(r8_kind),
pointer :: d(:,:)
3555 real(r8_kind),
pointer :: x(:)
3557 call mpp_clock_begin(id_put_1_to_xgrid_order_1)
3561 do p = 1, comm%nrecv
3562 msgsize = comm%recv(p)%count*lsize
3563 from_pe = comm%recv(p)%pe
3564 buffer_pos = comm%recv(p)%buffer_pos*lsize
3565 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = from_pe, block=.false., tag=comm_tag_7)
3570 do p = 1, comm%nsend
3571 msgsize = comm%send(p)%count*lsize
3572 to_pe = comm%send(p)%pe
3575 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3576 do n = 1, comm%send(p)%count
3578 i = comm%send(p)%i(n)
3579 j = comm%send(p)%j(n)
3580 send_buffer(pos) = d(i,j)
3583 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_7 )
3584 buffer_pos = buffer_pos + msgsize
3590 if( lsize == 1)
then
3591 call c_f_pointer(x_addrs(1), x, shape=[xsize])
3592 do l=1,xmap%size_put1
3593 x(l) = recv_buffer(xmap%x1_put(l)%pos)
3600 call c_f_pointer(x_addrs(l), x, shape=[xsize])
3601 do p = 1, comm%nrecv
3602 count = comm%recv(p)%count
3603 ibegin = comm%recv(p)%buffer_pos*lsize + 1
3604 istart = ibegin + (l-1)*count
3605 iend = istart + count - 1
3606 pos = comm%recv(p)%buffer_pos
3609 unpack_buffer(pos) = recv_buffer(n)
3612 do i=1,xmap%size_put1
3613 x(i) = unpack_buffer(xmap%x1_put(i)%pos)
3620 call mpp_clock_end(id_put_1_to_xgrid_order_1)
3622 end subroutine put_1_to_xgrid_order_1
3627 subroutine put_1_to_xgrid_order_2(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3628 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
3629 type(c_ptr),
intent(in) :: d_addrs(:)
3630 type(c_ptr),
intent(in) :: x_addrs(:)
3632 integer,
intent(in) :: isize, jsize, xsize, lsize
3635 real(r8_kind),
dimension(0:isize+1, 0:jsize+1, lsize) :: tmp
3636 real(r8_kind),
dimension(isize, jsize, lsize) :: tmpx, tmpy
3637 real(r8_kind),
dimension(isize, jsize, lsize) :: d_bar_max, d_bar_min
3638 real(r8_kind),
dimension(isize, jsize, lsize) :: d_max, d_min
3639 real(r8_kind) :: d_bar
3640 integer :: i, is, ie, j, js, je, ii, jj
3641 integer :: p, l, isd, jsd
3642 type (
grid_type),
pointer,
save :: grid1 =>null()
3643 type (
comm_type),
pointer,
save :: comm =>null()
3644 integer :: buffer_pos, msgsize, from_pe, to_pe, pos, n
3645 integer :: ibegin, count, istart, iend
3646 real(r8_kind) :: recv_buffer(xmap%put1%recvsize*lsize*3)
3647 real(r8_kind) :: send_buffer(xmap%put1%sendsize*lsize*3)
3648 real(r8_kind) :: unpack_buffer(xmap%put1%recvsize*3)
3649 logical :: on_west_edge, on_east_edge, on_south_edge, on_north_edge
3650 real(r8_kind),
pointer :: d(:,:)
3651 real(r8_kind),
pointer :: x(:)
3653 call mpp_clock_begin(id_put_1_to_xgrid_order_2)
3654 grid1 => xmap%grids(1)
3656 is = grid1%is_me; ie = grid1%ie_me
3657 js = grid1%js_me; je = grid1%je_me
3663 tmp(:,:,l) = large_number
3664 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3665 tmp(1:isize,1:jsize,l) = d(:,:)
3668 if(grid1%is_latlon)
then
3669 call mpp_update_domains(tmp,grid1%domain_with_halo)
3672 tmpy(:,:,l) =
grad_merid_latlon(tmp(:,:,l), grid1%lat, is, ie, js, je, isd, jsd)
3673 tmpx(:,:,l) =
grad_zonal_latlon(tmp(:,:,l), grid1%lon, grid1%lat, is, ie, js, je, isd, jsd)
3676 call mpp_update_domains(tmp,grid1%domain)
3677 on_west_edge = (is==1)
3678 on_east_edge = (ie==grid1%im)
3679 on_south_edge = (js==1)
3680 on_north_edge = (je==grid1%jm)
3684 call gradient_cubic(tmp(:,:,l), grid1%box%dx, grid1%box%dy, grid1%box%area, &
3685 grid1%box%edge_w, grid1%box%edge_e, grid1%box%edge_s, &
3686 grid1%box%edge_n, grid1%box%en1, grid1%box%en2, &
3687 grid1%box%vlon, grid1%box%vlat, tmpx(:,:,l), tmpy(:,:,l), &
3688 on_west_edge, on_east_edge, on_south_edge, on_north_edge)
3695 do p = 1, comm%nrecv
3696 msgsize = comm%recv(p)%count*lsize
3697 buffer_pos = comm%recv(p)%buffer_pos*lsize
3698 if(.NOT. monotonic_exchange)
then
3700 buffer_pos = buffer_pos*3
3702 from_pe = comm%recv(p)%pe
3703 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = from_pe, block=.false., tag=comm_tag_8)
3707 if(monotonic_exchange)
then
3712 d_bar_max(i,j,l) = -large_number
3713 d_bar_min(i,j,l) = large_number
3714 d_max(i,j,l) = -large_number
3715 d_min(i,j,l) = large_number
3718 if(tmp(i,j,l) .NE. large_number)
then
3719 if(tmp(i,j,l) > d_bar_max(i,j,l)) d_bar_max(i,j,l) = tmp(i,j,l)
3720 if(tmp(i,j,l) < d_bar_min(i,j,l)) d_bar_min(i,j,l) = tmp(i,j,l)
3731 if(monotonic_exchange)
then
3733 do p = 1, comm%nsend
3734 msgsize = comm%send(p)%count*lsize
3735 to_pe = comm%send(p)%pe
3737 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3738 do n = 1, comm%send(p)%count
3740 i = comm%send(p)%i(n)
3741 j = comm%send(p)%j(n)
3742 send_buffer(pos) = d(i,j) + tmpy(i,j,l)*comm%send(p)%dj(n) + tmpx(i,j,l)*comm%send(p)%di(n)
3743 if(send_buffer(pos) > d_max(i,j,l)) d_max(i,j,l) = send_buffer(pos)
3744 if(send_buffer(pos) < d_min(i,j,l)) d_min(i,j,l) = send_buffer(pos)
3749 do p = 1, comm%nsend
3750 msgsize = comm%send(p)%count*lsize
3751 to_pe = comm%send(p)%pe
3754 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3755 do n = 1, comm%send(p)%count
3757 i = comm%send(p)%i(n)
3758 j = comm%send(p)%j(n)
3760 if( d_max(i,j,l) > d_bar_max(i,j,l) )
then
3761 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)
3762 else if( d_min(i,j,l) < d_bar_min(i,j,l) )
then
3763 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)
3767 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_8 )
3768 buffer_pos = buffer_pos + msgsize
3771 do p = 1, comm%nsend
3772 msgsize = comm%send(p)%count*lsize*3
3773 to_pe = comm%send(p)%pe
3776 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3777 do n = 1, comm%send(p)%count
3779 i = comm%send(p)%i(n)
3780 j = comm%send(p)%j(n)
3781 send_buffer(pos-2) = d(i,j)
3782 send_buffer(pos-1) = tmpy(i,j,l)
3783 send_buffer(pos ) = tmpx(i,j,l)
3786 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_8 )
3787 buffer_pos = buffer_pos + msgsize
3794 if(monotonic_exchange)
then
3795 if( lsize == 1)
then
3796 call c_f_pointer(x_addrs(1), x, shape=[xsize])
3797 do l=1,xmap%size_put1
3798 pos = xmap%x1_put(l)%pos
3799 x(l) = recv_buffer(pos)
3803 call c_f_pointer(x_addrs(l), x, shape=[xsize])
3805 do p = 1, comm%nsend
3806 count = comm%send(p)%count
3807 ibegin = comm%recv(p)%buffer_pos*lsize + 1
3808 istart = ibegin + (l-1)*count
3809 iend = istart + count - 1
3810 pos = comm%recv(p)%buffer_pos
3813 unpack_buffer(pos) = recv_buffer(n)
3816 do i=1,xmap%size_put1
3817 pos = xmap%x1_put(i)%pos
3818 x(i) = unpack_buffer(pos)
3823 if( lsize == 1)
then
3824 call c_f_pointer(x_addrs(1), x, shape=[xsize])
3826 do l=1,xmap%size_put1
3827 pos = xmap%x1_put(l)%pos
3828 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
3834 call c_f_pointer(x_addrs(l), x, shape=[xsize])
3837 do p = 1, comm%nrecv
3838 count = comm%recv(p)%count*3
3839 ibegin = comm%recv(p)%buffer_pos*lsize*3 + 1
3840 istart = ibegin + (l-1)*count
3841 iend = istart + count - 1
3842 pos = comm%recv(p)%buffer_pos*3
3845 unpack_buffer(pos) = recv_buffer(n)
3848 do i=1,xmap%size_put1
3849 pos = xmap%x1_put(i)%pos
3850 x(i) = unpack_buffer(3*pos-2) + unpack_buffer(3*pos-1)*xmap%x1_put(i)%dj + unpack_buffer(3*pos) &
3851 & * xmap%x1_put(i)%di
3858 call mpp_clock_end(id_put_1_to_xgrid_order_2)
3860 end subroutine put_1_to_xgrid_order_2
3864 subroutine get_1_from_xgrid(d_addrs, x_addrs, xmap, isize, jsize, xsize, lsize)
3865 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
3866 type(c_ptr),
intent(in) :: d_addrs(:)
3867 type(c_ptr),
intent(in) :: x_addrs(:)
3869 integer,
intent(in) :: isize, jsize, xsize, lsize
3871 real(r8_kind),
dimension(xmap%size),
target :: dg(xmap%size, lsize)
3872 integer :: i, j, l, p, n, m
3873 integer :: msgsize, buffer_pos, pos
3874 integer :: istart, iend, count
3875 real(r8_kind) ,
pointer,
save :: dgp =>null()
3876 type(
grid_type) ,
pointer,
save :: grid1 =>null()
3877 type(
comm_type) ,
pointer,
save :: comm =>null()
3880 real(r8_kind) :: recv_buffer(xmap%get1%recvsize*lsize*3)
3881 real(r8_kind) :: send_buffer(xmap%get1%sendsize*lsize*3)
3882 real(r8_kind),
pointer :: d(:,:)
3883 real(r8_kind),
pointer :: x(:)
3885 call mpp_clock_begin(id_get_1_from_xgrid)
3888 grid1 => xmap%grids(1)
3890 do p = 1, comm%nrecv
3891 recv => comm%recv(p)
3892 msgsize = recv%count*lsize
3893 buffer_pos = recv%buffer_pos*lsize
3894 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_9)
3900 call c_f_pointer(x_addrs(l), x, shape=[xsize])
3902 dgp => dg(xmap%x1(i)%pos,l)
3903 dgp = dgp + xmap%x1(i)%area*x(i)
3911 do p = 1, comm%nsend
3912 send => comm%send(p)
3913 msgsize = send%count*lsize
3915 istart = send%buffer_pos+1
3916 iend = istart + send%count - 1
3920 send_buffer(pos) = dg(n,l)
3923 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = send%pe, tag=comm_tag_9 )
3924 buffer_pos = buffer_pos + msgsize
3932 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3937 do p = 1, comm%nrecv
3938 recv => comm%recv(p)
3940 buffer_pos = recv%buffer_pos*lsize
3941 if( recv%pe == xmap%me )
then
3945 pos = buffer_pos + (l-1)*count
3946 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3951 d(i,j) = recv_buffer(pos)
3959 do m = 1, comm%nrecv
3960 p = comm%unpack_ind(m)
3961 recv => comm%recv(p)
3962 if( recv%pe == xmap%me )
then
3965 buffer_pos = recv%buffer_pos*lsize
3969 pos = buffer_pos + (l-1)*recv%count
3970 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3971 do n = 1, recv%count
3975 d(i,j) = d(i,j) + recv_buffer(pos)
3985 call c_f_pointer(d_addrs(l), d, shape=[isize, jsize])
3986 d = d * grid1%area_inv
3989 call mpp_clock_end(id_get_1_from_xgrid)
3991 end subroutine get_1_from_xgrid
3995 subroutine get_1_from_xgrid_repro(d_addrs, x_addrs, xmap, xsize, lsize)
3996 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
3997 type(c_ptr),
intent(in) :: d_addrs(:)
3998 type(c_ptr),
intent(in) :: x_addrs(:)
4000 integer,
intent(in) :: xsize, lsize
4002 integer :: g, i, j, k, p, l, n, l2, l3
4003 integer :: msgsize, buffer_pos, pos
4004 type (
grid_type),
pointer,
save :: grid =>null()
4005 type(
comm_type),
pointer,
save :: comm => null()
4008 integer,
dimension(0:xmap%npes-1) :: pl, ml
4009 real(r8_kind) :: recv_buffer(xmap%recv_count_repro_tot*lsize)
4010 real(r8_kind) :: send_buffer(xmap%send_count_repro_tot*lsize)
4011 real(r8_kind),
pointer :: d(:,:)
4012 real(r8_kind),
pointer :: x(:)
4013 real(r8_kind),
pointer,
contiguous :: tmpptr(:,:)
4014 integer :: shape_d(2)
4015 integer :: i_off, j_off
4017 call mpp_clock_begin(id_get_1_from_xgrid_repro)
4018 shape_d = [xmap%grids(1)%ie_me-xmap%grids(1)%is_me+1, xmap%grids(1)%je_me-xmap%grids(1)%js_me+1]
4019 i_off = xmap%grids(1)%is_me - 1
4020 j_off = xmap%grids(1)%js_me - 1
4021 comm => xmap%get1_repro
4023 do p = 1, comm%nrecv
4024 recv => comm%recv(p)
4025 msgsize = recv%count*lsize
4026 buffer_pos = recv%buffer_pos*lsize
4027 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_10)
4028 n = recv%pe -xmap%root_pe
4034 send_buffer(:) = 0.0_r8_kind
4037 do p = 1, comm%nsend
4038 pos = comm%send(p)%buffer_pos*lsize
4039 send => comm%send(p)
4041 call c_f_pointer(x_addrs(l), x, shape=[xsize])
4042 do n = 1, send%count
4048 do k =1, xmap%grids(g)%km
4049 if(xmap%grids(g)%frac_area(i,j,k)/=0.0_r8_kind)
then
4051 send_buffer(pos) = send_buffer(pos) + xmap%x1(l2)%area *x(l2)
4059 buffer_pos = comm%send(p)%buffer_pos*lsize
4060 msgsize = comm%send(p)%count*lsize
4061 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe=comm%send(p)%pe, tag=comm_tag_10)
4065 call c_f_pointer(d_addrs(l), tmpptr, shape=shape_d)
4075 call c_f_pointer(d_addrs(l), tmpptr, shape=shape_d)
4077 do g=2,
size(xmap%grids(:))
4078 grid => xmap%grids(g)
4079 do l3=1,grid%size_repro
4080 i = grid%x_repro(l3)%i1
4081 j = grid%x_repro(l3)%j1
4082 p = grid%x_repro(l3)%pe-xmap%root_pe
4083 pos = pl(p) + (l-1)*ml(p) + grid%x_repro(l3)%recv_pos
4084 d(i - i_off, j - j_off) = d(i - i_off, j - j_off) + recv_buffer(pos)
4088 d = d * xmap%grids(1)%area_inv
4093 call mpp_clock_end(id_get_1_from_xgrid_repro)
4095 end subroutine get_1_from_xgrid_repro
4104 real(r8_kind),
dimension(:,:),
intent(in) :: d
4105 character(len=3),
intent(in) :: grid_id
4108 integer,
intent(in),
optional :: remap_method
4111 real(r8_kind),
dimension(xmap%size) :: x_over, x_back
4112 real(r8_kind),
dimension(size(d,1),size(d,2)) :: d1
4113 real(r8_kind),
dimension(:,:,:),
allocatable :: d2
4115 type (
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4117 grid1 => xmap%grids(1)
4123 call put_to_xgrid (d, grid1%id, x_over, xmap, remap_method)
4124 do g=2,
size(xmap%grids(:))
4125 grid2 => xmap%grids(g)
4126 if(grid2%on_this_pe)
then
4127 allocate (d2(grid2%is_me:grid2%ie_me, grid2%js_me:grid2%je_me, grid2%km) )
4130 if(grid2%on_this_pe)
then
4134 if(
allocated(d2))
deallocate (d2)
4151 real(r8_kind),
dimension(:,:,:),
intent(in) :: d
4152 character(len=3),
intent(in) :: grid_id
4155 integer,
intent(in),
optional :: remap_method
4158 real(r8_kind),
dimension(xmap%size) :: x_over, x_back
4159 real(r8_kind),
dimension(:,: ),
allocatable :: d1
4160 real(r8_kind),
dimension(:,:,:),
allocatable :: d2
4162 type (
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4164 grid1 => xmap%grids(1)
4166 do g = 2,
size(xmap%grids(:))
4167 grid2 => xmap%grids(g)
4168 if (grid_id==grid2%id)
then
4169 if(grid2%on_this_pe)
then
4174 call put_to_xgrid(0.0_r8_kind * grid2%frac_area, grid2%id, x_over, xmap)
4178 allocate ( d1(
size(grid1%area,1),
size(grid1%area,2)) )
4181 call put_to_xgrid(d1, grid1%id, x_back, xmap,remap_method)
4185 do g = 2,
size(xmap%grids(:))
4186 grid2 => xmap%grids(g)
4187 if(grid2%on_this_pe)
then
4188 allocate ( d2(
size(grid2%frac_area, 1),
size(grid2%frac_area, 2), &
4189 size(grid2%frac_area, 3) ) )
4193 if(
allocated(d2) )
deallocate ( d2 )
4207 real(r8_kind),
dimension(:,:),
intent(in) :: d
4208 character(len=3),
intent(in) :: grid_id
4211 integer,
intent(in),
optional :: remap_method
4213 real(r8_kind),
dimension(xmap%size) :: x_over, x_back
4214 real(r8_kind),
dimension(size(d,1),size(d,2)) :: d1
4215 real(r8_kind),
dimension(:,:,:),
allocatable :: d2
4216 real(r8_kind),
dimension(: ),
allocatable :: d_ug
4217 real(r8_kind),
dimension(:,:),
allocatable :: d2_ug
4219 type (
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4221 grid1 => xmap%grids(1)
4225 if(grid1%is_ug)
then
4226 allocate(d_ug(grid1%ls_me:grid1%le_me))
4227 call mpp_pass_sg_to_ug(grid1%ug_domain, d, d_ug)
4232 call put_to_xgrid (d, grid1%id, x_over, xmap, remap_method)
4234 do g=2,
size(xmap%grids(:))
4235 grid2 => xmap%grids(g)
4236 if(grid2%is_ug)
then
4237 if(grid2%on_this_pe)
then
4238 allocate (d2_ug(grid2%ls_me:grid2%le_me, grid2%km) )
4242 if(grid2%on_this_pe)
then
4244 sum( grid2%area(:,1) * sum(grid2%frac_area(:,1,:)*d2_ug,dim=2) )
4247 if(
allocated(d2_ug))
deallocate (d2_ug)
4249 if(grid2%on_this_pe)
then
4250 allocate (d2(grid2%is_me:grid2%ie_me, grid2%js_me:grid2%je_me, grid2%km) )
4253 if(grid2%on_this_pe)
then
4255 & + sum( grid2%area * sum(grid2%frac_area*d2,dim=3) )
4258 if(
allocated(d2))
deallocate (d2)
4261 if(grid1%is_ug)
then
4268 if(
allocated(d_ug))
deallocate(d_ug)
4280 real(r8_kind),
dimension(:,:,:),
intent(in) :: d
4281 character(len=3),
intent(in) :: grid_id
4284 integer,
intent(in),
optional :: remap_method
4287 real(r8_kind),
dimension(xmap%size) :: x_over, x_back
4288 real(r8_kind),
dimension(:,: ),
allocatable :: d1, d_ug
4289 real(r8_kind),
dimension(:,:,:),
allocatable :: d2
4291 type (
grid_type),
pointer,
save :: grid1 =>null(), grid2 =>null()
4293 grid1 => xmap%grids(1)
4295 do g = 2,
size(xmap%grids(:))
4296 grid2 => xmap%grids(g)
4297 if (grid_id==grid2%id)
then
4298 if(grid2%on_this_pe)
then
4299 if(grid2%is_ug)
then
4300 allocate(d_ug(grid2%ls_me:grid2%le_me,grid2%km))
4301 call mpp_pass_sg_to_ug(grid2%ug_domain, d, d_ug)
4307 if(grid2%is_ug)
then
4312 if(
allocated(d_ug))
deallocate(d_ug)
4314 if(grid2%is_ug)
then
4315 call put_to_xgrid_ug(0.0_r8_kind * grid2%frac_area(:,1,:), grid2%id, x_over, xmap)
4317 call put_to_xgrid(0.0_r8_kind * grid2%frac_area, grid2%id, x_over, xmap)
4322 allocate ( d1(
size(grid1%area,1),
size(grid1%area,2)) )
4323 if(grid1%is_ug)
then
4329 if(grid1%is_ug)
then
4332 call put_to_xgrid(d1, grid1%id, x_back, xmap,remap_method)
4337 do g = 2,
size(xmap%grids(:))
4338 grid2 => xmap%grids(g)
4339 if(grid2%on_this_pe)
then
4340 allocate ( d2(
size(grid2%frac_area, 1),
size(grid2%frac_area, 2), &
4341 size(grid2%frac_area, 3) ) )
4343 if(grid2%is_ug)
then
4349 if(
allocated(d2) )
deallocate ( d2 )
4360 character(len=3),
intent(in) :: id
4362 real(r8_kind),
dimension(:,:),
intent(out) :: area
4367 do g = 1,
size(xmap%grids(:))
4368 if (id==xmap%grids(g)%id )
then
4369 if(
size(area,1) .NE.
size(xmap%grids(g)%area,1) .OR.
size(area,2) .NE.
size(xmap%grids(g)%area,2) ) &
4370 call error_mesg(
"xgrid_mod",
"size mismatch between area and xmap%grids(g)%area", fatal)
4371 area = xmap%grids(g)%area
4377 if(.not. found)
call error_mesg(
"xgrid_mod", id//
" is not found in xmap%grids id", fatal)
4389 integer,
intent(in) :: isd, jsd
4390 real(r8_kind),
dimension(isd:,jsd:),
intent(in) :: d
4391 real(r8_kind),
dimension(:),
intent(in) :: lon
4392 real(r8_kind),
dimension(:),
intent(in) :: lat
4393 integer,
intent(in) :: is, ie, js, je
4395 real(r8_kind) :: dx, costheta
4396 integer :: i, j, ip1, im1
4402 else if(i==
size(lon(:)) )
then
4405 ip1 = i+1; im1 = i-1
4407 dx = lon(ip1) - lon(im1)
4408 if(abs(dx).lt.eps )
call error_mesg(
'xgrids_mod(grad_zonal_latlon)',
'Improper grid size in lontitude', fatal)
4409 if(dx .gt. pi) dx = dx - 2.0_r8_kind* pi
4410 if(dx .lt. -pi) dx = dx + 2.0_r8_kind* pi
4412 costheta = cos(lat(j))
4413 if(abs(costheta) .lt. eps)
call error_mesg(
'xgrids_mod(grad_zonal_latlon)',
'Improper latitude grid', fatal)
4428 integer,
intent(in) :: isd, jsd
4429 real(r8_kind),
dimension(isd:,jsd:),
intent(in) :: d
4430 real(r8_kind),
dimension(:),
intent(in) :: lat
4431 integer,
intent(in) :: is, ie, js, je
4434 integer :: i, j, jp1, jm1
4440 else if(j ==
size(lat(:)) )
then
4443 jp1 = j+1; jm1 = j-1
4445 dy = lat(jp1) - lat(jm1)
4446 if(abs(dy).lt.eps)
call error_mesg(
'xgrids_mod(grad_merid_latlon)',
'Improper grid size in latitude', fatal)
4457 subroutine get_index_range(xmap, grid_index, is, ie, js, je, km)
4460 integer,
intent(in) :: grid_index
4461 integer,
intent(out) :: is, ie, js, je, km
4463 is = xmap % grids(grid_index) % is_me
4464 ie = xmap % grids(grid_index) % ie_me
4465 js = xmap % grids(grid_index) % js_me
4466 je = xmap % grids(grid_index) % je_me
4467 km = xmap % grids(grid_index) % km
4469 end subroutine get_index_range
4476 subroutine stock_move_3d(from, to, grid_index, stock_data3d, xmap, &
4477 & delta_t, from_side, to_side, radius, verbose, ier)
4487 type(stock_type),
intent(inout),
optional :: from, to
4488 integer,
intent(in) :: grid_index
4489 real(r8_kind),
intent(in) :: stock_data3d(:,:,:)
4491 real(r8_kind),
intent(in) :: delta_t
4492 integer,
intent(in) :: from_side
4493 integer,
intent(in) :: to_side
4494 real(r8_kind),
intent(in) :: radius
4495 character(len=*),
intent(in),
optional :: verbose
4496 integer,
intent(out) :: ier
4498 real(r8_kind) :: from_dq, to_dq
4501 if(grid_index == 1)
then
4507 if(.not.
associated(xmap%grids) )
then
4512 from_dq = delta_t * 4.0_r8_kind * pi * radius**2 * sum( sum(xmap%grids(grid_index)%area * &
4513 & sum(xmap%grids(grid_index)%frac_area * stock_data3d, dim=3), dim=1))
4517 if(
present(to )) to % dq( to_side) = to % dq( to_side) + to_dq
4518 if(
present(from)) from % dq(from_side) = from % dq(from_side) - from_dq
4520 if(
present(verbose).and.debug_stocks)
then
4523 from_dq = from_dq/(4.0_r8_kind*pi*radius**2)
4524 to_dq = to_dq /(4.0_r8_kind*pi*radius**2)
4525 if(
mpp_pe()==mpp_root_pe())
then
4526 write(stocks_file,
'(a,es19.12,a,es19.12,a)') verbose, from_dq,
' [*/m^2]'
4536 subroutine stock_move_2d(from, to, grid_index, stock_data2d, xmap, &
4537 & delta_t, from_side, to_side, radius, verbose, ier)
4546 type(stock_type),
intent(inout),
optional :: from, to
4547 integer,
optional,
intent(in) :: grid_index
4548 real(r8_kind),
intent(in) :: stock_data2d(:,:)
4550 real(r8_kind),
intent(in) :: delta_t
4551 integer,
intent(in) :: from_side
4552 integer,
intent(in) :: to_side
4553 real(r8_kind),
intent(in) :: radius
4554 character(len=*),
intent(in) :: verbose
4555 integer,
intent(out) :: ier
4557 real(r8_kind) :: to_dq, from_dq
4561 if(.not.
associated(xmap%grids) )
then
4566 if( .not.
present(grid_index) .or. grid_index==1 )
then
4569 from_dq = delta_t * 4.0_r8_kind*pi*radius**2 * sum(sum(xmap%grids(1)%area * stock_data2d, dim=1))
4580 if(
present(to )) to % dq( to_side) = to % dq( to_side) + to_dq
4581 if(
present(from)) from % dq(from_side) = from % dq(from_side) - from_dq
4583 if(debug_stocks)
then
4586 from_dq = from_dq/(4.0_r8_kind*pi*radius**2)
4587 to_dq = to_dq /(4.0_r8_kind*pi*radius**2)
4588 if(
mpp_pe()==mpp_root_pe())
then
4589 write(stocks_file,
'(a,es19.12,a,es19.12,a)') verbose, from_dq,
' [*/m^2]'
4593 end subroutine stock_move_2d
4600 subroutine stock_move_ug_3d(from, to, grid_index, stock_ug_data3d, xmap, &
4601 & delta_t, from_side, to_side, radius, verbose, ier)
4611 type(stock_type),
intent(inout),
optional :: from, to
4612 integer,
intent(in) :: grid_index
4613 real(r8_kind),
intent(in) :: stock_ug_data3d(:,:)
4615 real(r8_kind),
intent(in) :: delta_t
4616 integer,
intent(in) :: from_side
4617 integer,
intent(in) :: to_side
4618 real(r8_kind),
intent(in) :: radius
4619 character(len=*),
intent(in),
optional :: verbose
4620 integer,
intent(out) :: ier
4621 real(r8_kind),
dimension(size(stock_ug_data3d,1),size(stock_ug_data3d,2)) :: tmp
4623 real(r8_kind) :: from_dq, to_dq
4626 if(grid_index == 1)
then
4632 if(.not.
associated(xmap%grids) )
then
4637 tmp = xmap%grids(grid_index)%frac_area(:,1,:) * stock_ug_data3d
4638 from_dq = delta_t * 4.0_r8_kind * pi * radius**2 * sum( xmap%grids(grid_index)%area(:,1) * &
4643 if(
present(to )) to % dq( to_side) = to % dq( to_side) + to_dq
4644 if(
present(from)) from % dq(from_side) = from % dq(from_side) - from_dq
4646 if(
present(verbose).and.debug_stocks)
then
4649 from_dq = from_dq/(4.0_r8_kind*pi*radius**2)
4650 to_dq = to_dq /(4.0_r8_kind*pi*radius**2)
4651 if(
mpp_pe()==mpp_root_pe())
then
4652 write(stocks_file,
'(a,es19.12,a,es19.12,a)') verbose, from_dq,
' [*/m^2]'
4656 end subroutine stock_move_ug_3d
4662 subroutine stock_integrate_2d(integrate_data2d, xmap, delta_t, radius, res, ier)
4668 real(r8_kind),
intent(in) :: integrate_data2d(:,:)
4670 real(r8_kind),
intent(in) :: delta_t
4671 real(r8_kind),
intent(in) :: radius
4672 real(r8_kind),
intent(out) :: res
4673 integer,
intent(out) :: ier
4678 if(.not.
associated(xmap%grids) )
then
4683 res = delta_t * 4.0_r8_kind * pi * radius**2 * sum(sum(xmap%grids(1)%area * integrate_data2d, dim=1))
4685 end subroutine stock_integrate_2d
4692 subroutine stock_print(stck, Time, comp_name, index, ref_value, radius, pelist)
4698 type(stock_type),
intent(in) :: stck
4700 character(len=*) :: comp_name
4701 integer,
intent(in) :: index
4702 real(r8_kind),
intent(in) :: ref_value
4703 real(r8_kind),
intent(in) :: radius
4704 integer,
intent(in),
optional :: pelist(:)
4706 integer,
parameter :: initID = -2
4710 real(r8_kind) :: f_value, c_value, planet_area
4711 character(len=80) :: formatString
4712 integer :: iday, isec, hours
4713 integer :: diagID, compInd
4714 integer,
dimension(NELEMS,4),
save :: f_valueDiagID = initid
4715 integer,
dimension(NELEMS,4),
save :: c_valueDiagID = initid
4716 integer,
dimension(NELEMS,4),
save :: fmc_valueDiagID = initid
4718 real(r8_kind) :: diagField
4720 character(len=30) :: field_name, units
4722 f_value = sum(stck % dq)
4723 c_value = ref_value - stck % q_start
4724 if(
present(pelist))
then
4725 call mpp_sum(f_value, pelist=pelist)
4726 call mpp_sum(c_value, pelist=pelist)
4732 if(
mpp_pe() == mpp_root_pe())
then
4734 planet_area = 4.0_r8_kind * pi * radius**2
4735 f_value = f_value / planet_area
4736 c_value = c_value / planet_area
4738 if(comp_name ==
'ATM') compind = 1
4739 if(comp_name ==
'LND') compind = 2
4740 if(comp_name ==
'ICE') compind = 3
4741 if(comp_name ==
'OCN') compind = 4
4744 if(f_valuediagid(index,compind) == initid)
then
4745 field_name = trim(comp_name) // trim(stock_names(index))
4746 field_name = trim(field_name) //
'StocksChange_Flux'
4747 units = trim(stock_units(index))
4752 if(c_valuediagid(index,compind) == initid)
then
4753 field_name = trim(comp_name) // trim(stock_names(index))
4754 field_name = trim(field_name) //
'StocksChange_Comp'
4755 units = trim(stock_units(index))
4760 if(fmc_valuediagid(index,compind) == initid)
then
4761 field_name = trim(comp_name) // trim(stock_names(index))
4762 field_name = trim(field_name) //
'StocksChange_Diff'
4763 units = trim(stock_units(index))
4768 diagid=f_valuediagid(index,compind)
4770 if (diagid > 0) used =
send_data(diagid, diagfield, time = time)
4771 diagid=c_valuediagid(index,compind)
4773 if (diagid > 0) used =
send_data(diagid, diagfield, time)
4774 diagid=fmc_valuediagid(index,compind)
4775 diagfield = f_value-c_value
4776 if (diagid > 0) used =
send_data(diagid, diagfield, time=time)
4780 hours = iday*24 + isec/3600
4781 formatstring =
'(a,a,a,i16,2x,es22.15,2x,es22.15,2x,es22.15)'
4782 write(stocks_file,formatstring) trim(comp_name),stock_names(index),stock_units(index) &
4783 ,hours,f_value,c_value,f_value-c_value
4788 end subroutine stock_print
4793 function is_lat_lon(lon, lat)
4794 real(r8_kind),
dimension(:,:),
intent(in) :: lon, lat
4795 logical :: is_lat_lon
4796 integer :: i, j, nlon, nlat, num
4801 loop_lat:
do j = 1, nlat
4803 if(lat(i,j) .NE. lat(1,j))
then
4804 is_lat_lon = .false.
4811 loop_lon:
do i = 1, nlon
4813 if(lon(i,j) .NE. lon(i,1))
then
4814 is_lat_lon = .false.
4822 if(is_lat_lon) num = 1
4827 is_lat_lon = .false.
4831 end function is_lat_lon
4841 subroutine get_side1_from_xgrid_ug(d, grid_id, x, xmap, complete)
4842 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_loc
4843 real(r8_kind),
target,
contiguous,
intent(out) :: d(:)
4844 character(len=3),
intent(in) :: grid_id
4845 real(r8_kind),
target,
contiguous,
intent(in) :: x(:)
4846 type (xmap_type),
intent(inout) :: xmap
4847 logical,
intent(in),
optional :: complete
4849 logical :: is_complete, set_mismatch
4851 character(len=2) :: text
4852 integer,
save :: isize=0
4853 integer,
save :: lsize=0
4854 integer,
save :: xsize=0
4855 character(len=3),
save :: grid_id_saved=
""
4856 type(c_ptr),
dimension(MAX_FIELDS),
save :: d_addrs = c_null_ptr
4857 type(c_ptr),
dimension(MAX_FIELDS),
save :: x_addrs = c_null_ptr
4860 if (grid_id==xmap%grids(1)%id)
then
4861 is_complete = .true.
4862 if(
present(complete)) is_complete=complete
4864 if( lsize > max_fields )
then
4865 write( text,
'(i2)' ) max_fields
4866 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group get_side1_from_xgrid_ug', fatal)
4868 d_addrs(lsize) = c_loc(d)
4869 x_addrs(lsize) = c_loc(x)
4874 grid_id_saved = grid_id
4876 set_mismatch = .false.
4877 set_mismatch = set_mismatch .OR. (isize /=
size(d(:)))
4878 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
4879 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
4880 if(set_mismatch)
then
4881 write( text,
'(i2)' ) lsize
4882 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text// &
4883 &
' for group get_side1_from_xgrid_ug', fatal )
4887 if(is_complete)
then
4889 call get_1_from_xgrid_ug_repro(d_addrs, x_addrs, xmap, xsize, lsize)
4891 call get_1_from_xgrid_ug(d_addrs, x_addrs, xmap, isize, xsize, lsize)
4893 d_addrs(1:lsize) = c_null_ptr
4894 x_addrs(1:lsize) = c_null_ptr
4903 do g=2,
size(xmap%grids(:))
4904 if (grid_id==xmap%grids(g)%id) &
4905 call error_mesg (
'xgrid_mod', &
4906 'get_from_xgrid_ug expects a 3D side 2 grid', fatal)
4909 call error_mesg (
'xgrid_mod',
'get_from_xgrid_ug: could not find grid id', fatal)
4911 end subroutine get_side1_from_xgrid_ug
4925 use,
intrinsic :: iso_c_binding, only: c_ptr, c_null_ptr, c_loc
4926 real(r8_kind),
target,
contiguous,
intent(in) :: d(:)
4927 character(len=3),
intent(in) :: grid_id
4928 real(r8_kind),
target,
contiguous,
intent(inout) :: x(:)
4929 type (xmap_type),
intent(inout) :: xmap
4930 logical,
intent(in),
optional :: complete
4932 logical :: is_complete, set_mismatch
4934 character(len=2) :: text
4935 integer,
save :: dsize=0
4936 integer,
save :: lsize=0
4937 integer,
save :: xsize=0
4938 character(len=3),
save :: grid_id_saved=
""
4939 type(c_ptr),
dimension(MAX_FIELDS),
save :: d_addrs = c_null_ptr
4940 type(c_ptr),
dimension(MAX_FIELDS),
save :: x_addrs = c_null_ptr
4942 if (grid_id==xmap%grids(1)%id)
then
4943 is_complete = .true.
4944 if(
present(complete)) is_complete=complete
4946 if( lsize > max_fields )
then
4947 write( text,
'(i2)' ) max_fields
4948 call error_mesg (
'xgrid_mod',
'MAX_FIELDS='//trim(text)//
' exceeded for group put_side1_to_xgrid_ug', fatal)
4950 d_addrs(lsize) = c_loc(d)
4951 x_addrs(lsize) = c_loc(x)
4956 grid_id_saved = grid_id
4958 set_mismatch = .false.
4959 set_mismatch = set_mismatch .OR. (dsize /=
size(d(:)))
4960 set_mismatch = set_mismatch .OR. (xsize /=
size(x(:)))
4961 set_mismatch = set_mismatch .OR. (grid_id_saved /= grid_id)
4962 if(set_mismatch)
then
4963 write( text,
'(i2)' ) lsize
4964 call error_mesg (
'xgrid_mod',
'Incompatible field at count '//text// &
4965 &
' for group put_side1_to_xgrid_ug', fatal )
4969 if(is_complete)
then
4970 call put_1_to_xgrid_ug_order_1(d_addrs, x_addrs, xmap, dsize, xsize, lsize)
4971 d_addrs(1:lsize) = c_null_ptr
4972 x_addrs(1:lsize) = c_null_ptr
4981 do g=2,
size(xmap%grids(:))
4982 if (grid_id==xmap%grids(g)%id) &
4983 call error_mesg (
'xgrid_mod', &
4984 'put_to_xgrid_ug expects a 2D side 2 grid', fatal)
4987 call error_mesg (
'xgrid_mod',
'put_to_xgrid_ug: could not find grid id', fatal)
5000 subroutine put_side2_to_xgrid_ug(d, grid_id, x, xmap)
5001 real(r8_kind),
dimension(:,:),
intent(in) :: d
5002 character(len=3),
intent(in) :: grid_id
5003 real(r8_kind),
dimension(:),
intent(inout) :: x
5004 type (xmap_type),
intent(inout) :: xmap
5008 if (grid_id==xmap%grids(1)%id) &
5009 call error_mesg (
'xgrid_mod', &
5010 'put_to_xgrid_ug expects a 2D side 1 grid', fatal)
5012 do g=2,
size(xmap%grids(:))
5013 if (grid_id==xmap%grids(g)%id)
then
5014 call put_2_to_xgrid_ug(d, xmap%grids(g), x, xmap)
5019 call error_mesg (
'xgrid_mod',
'put_to_xgrid_ug: could not find grid id', fatal)
5021 end subroutine put_side2_to_xgrid_ug
5032 subroutine get_side2_from_xgrid_ug(d, grid_id, x, xmap)
5033 real(r8_kind),
dimension(:,:),
intent(out) :: d
5034 character(len=3),
intent(in) :: grid_id
5035 real(r8_kind),
dimension(:),
intent(in) :: x
5036 type (xmap_type),
intent(in) :: xmap
5040 if (grid_id==xmap%grids(1)%id) &
5041 call error_mesg (
'xgrid_mod', &
5042 'get_from_xgrid_ug expects a 2D side 1 grid', fatal)
5044 do g=2,
size(xmap%grids(:))
5045 if (grid_id==xmap%grids(g)%id)
then
5046 call get_2_from_xgrid_ug(d, xmap%grids(g), x, xmap)
5051 call error_mesg (
'xgrid_mod',
'get_from_xgrid_ug: could not find grid id', fatal)
5053 end subroutine get_side2_from_xgrid_ug
5059 subroutine put_1_to_xgrid_ug_order_1(d_addrs, x_addrs, xmap, dsize, xsize, lsize)
5060 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
5061 type(c_ptr),
intent(in) :: d_addrs(:)
5062 type(c_ptr),
intent(in) :: x_addrs(:)
5063 type (xmap_type),
intent(inout) :: xmap
5064 integer,
intent(in) :: dsize, xsize, lsize
5066 integer :: i, p, buffer_pos, msgsize
5067 integer :: from_pe, to_pe, pos, n, l, count
5068 integer :: ibegin, istart, iend, start_pos
5069 type (comm_type),
pointer,
save :: comm =>null()
5070 real(r8_kind) :: recv_buffer(xmap%put1%recvsize*lsize)
5071 real(r8_kind) :: send_buffer(xmap%put1%sendsize*lsize)
5072 real(r8_kind) :: unpack_buffer(xmap%put1%recvsize)
5074 real(r8_kind),
pointer :: d(:)
5075 real(r8_kind),
pointer :: x(:)
5078 call mpp_clock_begin(id_put_1_to_xgrid_order_1)
5082 do p = 1, comm%nrecv
5083 msgsize = comm%recv(p)%count*lsize
5084 from_pe = comm%recv(p)%pe
5085 buffer_pos = comm%recv(p)%buffer_pos*lsize
5086 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = from_pe, block=.false., tag=comm_tag_7)
5091 do p = 1, comm%nsend
5092 msgsize = comm%send(p)%count*lsize
5093 to_pe = comm%send(p)%pe
5096 call c_f_pointer(d_addrs(l), d, shape=[dsize])
5097 do n = 1, comm%send(p)%count
5099 lll = comm%send(p)%i(n)
5100 send_buffer(pos) = d(lll)
5103 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = to_pe, tag=comm_tag_7 )
5104 buffer_pos = buffer_pos + msgsize
5110 if( lsize == 1)
then
5111 call c_f_pointer(x_addrs(1), x, shape=[xsize])
5112 do l=1,xmap%size_put1
5113 x(l) = recv_buffer(xmap%x1_put(l)%pos)
5120 call c_f_pointer(x_addrs(l), x, shape=[xsize])
5121 do p = 1, comm%nrecv
5122 count = comm%recv(p)%count
5123 ibegin = comm%recv(p)%buffer_pos*lsize + 1
5124 istart = ibegin + (l-1)*count
5125 iend = istart + count - 1
5126 pos = comm%recv(p)%buffer_pos
5129 unpack_buffer(pos) = recv_buffer(n)
5132 do i=1,xmap%size_put1
5133 x(i) = unpack_buffer(xmap%x1_put(i)%pos)
5140 call mpp_clock_end(id_put_1_to_xgrid_order_1)
5142 end subroutine put_1_to_xgrid_ug_order_1
5146 subroutine put_2_to_xgrid_ug(d, grid, x, xmap)
5147 type (grid_type),
intent(in) :: grid
5148 real(r8_kind),
dimension(grid%ls_me:grid%le_me, grid%km),
intent(in) :: d
5149 real(r8_kind),
dimension(:),
intent(inout) :: x
5150 type (xmap_type),
intent(in) :: xmap
5153 call mpp_clock_begin(id_put_2_to_xgrid)
5155 do l=grid%first,grid%last
5156 x(l) = d(xmap%x2(l)%l,xmap%x2(l)%k)
5159 call mpp_clock_end(id_put_2_to_xgrid)
5160 end subroutine put_2_to_xgrid_ug
5163 subroutine get_1_from_xgrid_ug(d_addrs, x_addrs, xmap, isize, xsize, lsize)
5164 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
5165 type(c_ptr),
intent(in) :: d_addrs(:)
5166 type(c_ptr),
intent(in) :: x_addrs(:)
5167 type (xmap_type),
intent(inout) :: xmap
5168 integer,
intent(in) :: isize, xsize, lsize
5170 real(r8_kind),
dimension(xmap%size),
target :: dg(xmap%size, lsize)
5171 integer :: i, j, l, p, n, m
5172 integer :: msgsize, buffer_pos, pos
5173 integer :: istart, iend, count
5174 real(r8_kind) ,
pointer,
save :: dgp =>null()
5175 type (grid_type) ,
pointer,
save :: grid1 =>null()
5176 type (comm_type) ,
pointer,
save :: comm =>null()
5179 real(r8_kind) :: recv_buffer(xmap%get1%recvsize*lsize*3)
5180 real(r8_kind) :: send_buffer(xmap%get1%sendsize*lsize*3)
5181 real(r8_kind),
pointer :: d(:)
5182 real(r8_kind),
pointer :: x(:)
5184 call mpp_clock_begin(id_get_1_from_xgrid)
5187 grid1 => xmap%grids(1)
5189 do p = 1, comm%nrecv
5190 recv => comm%recv(p)
5191 msgsize = recv%count*lsize
5192 buffer_pos = recv%buffer_pos*lsize
5193 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_9)
5199 call c_f_pointer(x_addrs(l), x, shape=[xsize])
5201 dgp => dg(xmap%x1(i)%pos,l)
5202 dgp = dgp + xmap%x1(i)%area*x(i)
5210 do p = 1, comm%nsend
5211 send => comm%send(p)
5212 msgsize = send%count*lsize
5214 istart = send%buffer_pos+1
5215 iend = istart + send%count - 1
5219 send_buffer(pos) = dg(n,l)
5222 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe = send%pe, tag=comm_tag_9 )
5223 buffer_pos = buffer_pos + msgsize
5231 call c_f_pointer(d_addrs(l), d, shape=[isize])
5236 do p = 1, comm%nrecv
5237 recv => comm%recv(p)
5239 buffer_pos = recv%buffer_pos*lsize
5240 if( recv%pe == xmap%me )
then
5244 pos = buffer_pos + (l-1)*count
5245 call c_f_pointer(d_addrs(l), d, shape=[isize])
5249 d(i) = recv_buffer(pos)
5257 do m = 1, comm%nrecv
5258 p = comm%unpack_ind(m)
5259 recv => comm%recv(p)
5260 if( recv%pe == xmap%me )
then
5263 buffer_pos = recv%buffer_pos*lsize
5267 pos = buffer_pos + (l-1)*recv%count
5268 call c_f_pointer(d_addrs(l), d, shape=[isize])
5269 do n = 1, recv%count
5272 d(i) = d(i) + recv_buffer(pos)
5282 call c_f_pointer(d_addrs(l), d, shape=[isize])
5283 d = d * grid1%area_inv(:,1)
5286 call mpp_clock_end(id_get_1_from_xgrid)
5288 end subroutine get_1_from_xgrid_ug
5292 subroutine get_1_from_xgrid_ug_repro(d_addrs, x_addrs, xmap, xsize, lsize)
5293 use,
intrinsic :: iso_c_binding, only: c_ptr, c_f_pointer
5294 type(c_ptr),
intent(in) :: d_addrs(:)
5295 type(c_ptr),
intent(in) :: x_addrs(:)
5296 type (xmap_type),
intent(inout) :: xmap
5297 integer,
intent(in) :: xsize, lsize
5299 integer :: g, i, j, k, p, l, n, l2, l3
5300 integer :: msgsize, buffer_pos, pos
5301 type (grid_type),
pointer,
save :: grid =>null()
5302 type(
comm_type),
pointer,
save :: comm => null()
5305 integer,
dimension(0:xmap%npes-1) :: pl, ml
5306 real(r8_kind) :: recv_buffer(xmap%recv_count_repro_tot*lsize)
5307 real(r8_kind) :: send_buffer(xmap%send_count_repro_tot*lsize)
5308 real(r8_kind),
pointer :: d(:)
5309 real(r8_kind),
pointer :: x(:)
5310 real(r8_kind),
pointer,
contiguous :: tmpptr(:)
5311 integer :: shape_d(1)
5313 call mpp_clock_begin(id_get_1_from_xgrid_repro)
5314 shape_d = [xmap%grids(1)%le_me-xmap%grids(1)%ls_me+1]
5315 comm => xmap%get1_repro
5317 do p = 1, comm%nrecv
5318 recv => comm%recv(p)
5319 msgsize = recv%count*lsize
5320 buffer_pos = recv%buffer_pos*lsize
5321 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe = recv%pe, block=.false., tag=comm_tag_10)
5322 n = recv%pe -xmap%root_pe
5328 send_buffer(:) = 0.0_r8_kind
5331 do p = 1, comm%nsend
5332 pos = comm%send(p)%buffer_pos*lsize
5333 send => comm%send(p)
5335 call c_f_pointer(x_addrs(l), x, shape=[xsize])
5336 do n = 1, send%count
5342 do k =1, xmap%grids(g)%km
5343 if(xmap%grids(g)%frac_area(i,j,k)/=0.0_r8_kind)
then
5345 send_buffer(pos) = send_buffer(pos) + xmap%x1(l2)%area *x(l2)
5353 buffer_pos = comm%send(p)%buffer_pos*lsize
5354 msgsize = comm%send(p)%count*lsize
5355 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe=comm%send(p)%pe, tag=comm_tag_10)
5359 call c_f_pointer(d_addrs(l), tmpptr, shape=shape_d)
5360 d(xmap%grids(1)%ls_me:xmap%grids(1)%le_me) => tmpptr
5369 call c_f_pointer(d_addrs(l), tmpptr, shape=shape_d)
5370 d(xmap%grids(1)%ls_me:xmap%grids(1)%le_me) => tmpptr
5371 do g=2,
size(xmap%grids(:))
5372 grid => xmap%grids(g)
5373 do l3=1,grid%size_repro
5374 i = grid%x_repro(l3)%l1
5375 p = grid%x_repro(l3)%pe-xmap%root_pe
5376 pos = pl(p) + (l-1)*ml(p) + grid%x_repro(l3)%recv_pos
5377 d(i) = d(i) + recv_buffer(pos)
5381 d = d * xmap%grids(1)%area_inv(:,1)
5386 call mpp_clock_end(id_get_1_from_xgrid_repro)
5388 end subroutine get_1_from_xgrid_ug_repro
5392 subroutine get_2_from_xgrid_ug(d, grid, x, xmap)
5393 type (grid_type),
intent(in) :: grid
5394 real(r8_kind),
dimension(grid%ls_me:grid%le_me, grid%km),
intent(out) :: d
5395 real(r8_kind),
dimension(:),
intent(in) :: x
5396 type (xmap_type),
intent(in) :: xmap
5400 call mpp_clock_begin(id_get_2_from_xgrid)
5403 do l=grid%first_get,grid%last_get
5404 d(xmap%x2_get(l)%l,xmap%x2_get(l)%k) = &
5405 d(xmap%x2_get(l)%l,xmap%x2_get(l)%k) + xmap%x2_get(l)%area*x(xmap%x2_get(l)%pos)
5411 d(:,k) = d(:,k) * grid%area_inv(:,1)
5414 call mpp_clock_end(id_get_2_from_xgrid)
5416 end subroutine get_2_from_xgrid_ug
5421 integer,
intent(in) :: i, j
5426 g = (j-1)*grid%ni + i
5427 in_box_me = (g>=grid%gs_me) .and. (g<=grid%ge_me)
5429 in_box_me = (i>=grid%is_me) .and. (i<=grid%ie_me) .and. (j>=grid%js_me) .and. (j<=grid%je_me)
5437 integer,
intent(in) :: i, j, p
5442 g = (j-1)*grid%ni + i
5443 in_box_nbr = (g>=grid%gs(p)) .and. (g<=grid%ge(p))
5445 in_box_nbr = (i>=grid%is(p)) .and. (i<=grid%ie(p)) .and. (j>=grid%js(p)) .and. (j<=grid%je(p))
5450 end module xgrid_mod
5453 Register a diagnostic field for a given module.
Send data over to output fields.
Close a netcdf or domain file opened with open_file or open_virtual_file.
Opens a NetCDF dataset on disk and initializes the file object.
Read data from a defined field in a file.
integer function, public check_nml_error(IOSTAT, NML_NAME)
Checks the iostat argument that is returned after reading a namelist and determines if the error code...
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
subroutine, public error_mesg(routine, message, level)
Print notes, warnings and error messages; terminates program for warning and error messages....
integer function, public get_mosaic_xgrid_size(fileobj)
return exchange grid size of mosaic xgrid file.
subroutine, public get_mosaic_contact(fileobj, tile1, tile2, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2)
Get contact information from mosaic_file Example usage: call get_mosaic_contact(mosaic_file,...
integer function, public get_mosaic_ntiles(fileobj)
Get number of tiles in the mosaic_file.
subroutine, public get_mosaic_tile_grid(grid_file, fileobj, domain, tile_count)
Gets the name of a mosaic tile grid file.
integer function, public get_mosaic_ncontacts(fileobj)
Get number of contacts in the mosaic_file.
subroutine, public get_mosaic_grid_sizes(fileobj, nx, ny)
Get grid size of each tile from mosaic_file.
integer function mpp_get_domain_npes(domain)
Set user stack size.
integer function, dimension(size(domain%tile_id(:))) mpp_get_tile_id(domain)
Returns the tile_id on current pe.
integer function mpp_get_current_ntile(domain)
Returns number of tile on current pe.
integer function mpp_get_ntile_count(domain)
Returns number of tiles in mosaic.
subroutine mpp_compute_extent(isg, ieg, ndivs, ibegin, iend, extent)
Computes extents for a grid decomposition with the given indices and divisions.
subroutine mpp_get_tile_list(domain, tiles)
Return the tile_id on current pelist. one-tile-per-pe is assumed.
logical function mpp_domain_is_initialized(domain)
Set user stack size.
subroutine mpp_get_domain_pelist(domain, pelist)
Set user stack size.
integer function mpp_get_domain_root_pe(domain)
Set user stack size.
Broadcasts domain to every pe. Only useful outside the context of it's own pelist.
Deallocate given 1D or 2D domain.
Set up a domain decomposition.
These routines retrieve the axis specifications associated with the compute domains....
Retrieve the entire array of compute domain extents associated with a decomposition.
These routines retrieve the axis specifications associated with the data domains. The domain is a der...
These routines retrieve the axis specifications associated with the global domains....
Global sum of domain-decomposed arrays. mpp_global_sum is used to get the sum of a domain-decomposed...
Modifies the extents (compute, data and global) of a given domain.
Passes data from a structured grid to an unstructured grid Example usage:
Reorganization of distributed global arrays. mpp_redistribute is used to reorganize a distributed ar...
Performs halo updates for a given domain.
One dimensional domain used to manage shared data access between pes.
The domain2D type contains all the necessary information to define the global, compute and data domai...
Domain information for managing data on unstructured grids.
subroutine mpp_sync_self(pelist, check, request, msg_size, msg_type)
This is to check if current PE's outstanding puts are complete but we can't use shmem_fence because w...
integer function stdout()
This function returns the current standard fortran unit numbers for output.
subroutine mpp_set_current_pelist(pelist, no_sync)
Set context pelist.
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
integer function mpp_npes()
Returns processor count for current pelist.
integer function mpp_pe()
Returns processor ID.
subroutine mpp_sync(pelist, do_self)
Synchronize PEs in list.
integer function mpp_clock_id(name, flags, grain)
Return an ID for a new or existing clock.
Scatter a vector across all PEs.
Reduction operations. Find the max of scalar a from the PEs in pelist result is also automatically br...
Reduction operations. Find the min of scalar a from the PEs in pelist result is also automatically br...
Receive data from another PE.
Send data to a receiving PE.
Holds stocks amounts per PE values.
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
Returns days and seconds ( < 86400 ) corresponding to a time. err_msg should be checked for any error...
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.
subroutine get_area_elements_fms2_io(fileobj, name, get_area_data)
Read the area elements from NetCDF file.
integer function, public xgrid_count(xmap)
Returns current size of exchange grid variables.
subroutine, public some(xmap, some_arr, grid_id)
Returns logical associating exchange grid cells with given side two grid.
subroutine regen(xmap)
Regenerate/Update the xmap.
integer nsubset
Number of processors to read exchange grid information. Those processors that read the exchange grid ...
subroutine put_side1_to_xgrid(d, grid_id, x, xmap, remap_method, complete)
Scatters data to exchange grid.
integer function get_nest_contact_fms2_io(fileobj, 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)
currently we are assuming there is only one nest region
subroutine, public get_ocean_model_area_elements(domain, grid_file)
Read Ocean area element data from netCDF file.
subroutine, public set_frac_area_ug(f, grid_id, xmap)
Changes sub-grid portion areas and/or number.
real(r8_kind) function, dimension(3) conservation_check_ug_side1(d, grid_id, xmap, remap_method)
conservation_check_ug - returns three numbers which are the global sum of a variable (1) on its home ...
subroutine get_side1_from_xgrid(d, grid_id, x, xmap, complete)
subroutine stock_move_3d(from, to, grid_index, stock_data3d, xmap, delta_t, from_side, to_side, radius, verbose, ier)
this version takes rank 3 data, it can be used to compute the flux on anything but the first grid,...
real(r8_kind), dimension(:,:), allocatable, public area_atm_sphere
Area elements based on a the spherical model used by the ICE layer.
logical function in_box_me(i, j, grid)
logical function in_box(i, j, is, ie, js, je)
integer remapping_method
xgrid nml
subroutine get_grid_version2(grid, grid_id, grid_file)
read the center point of the grid from version 1 grid file. only the grid at the side 1 is needed,...
subroutine get_side2_from_xgrid(d, grid_id, x, xmap)
real(r8_kind) function, dimension(3) conservation_check_ug_side2(d, grid_id, xmap, remap_method)
conservation_check_ug - returns three numbers which are the global sum of a variable (1) on its home ...
real(r8_kind) function, dimension(is:ie, js:je) grad_merid_latlon(d, lat, is, ie, js, je, isd, jsd)
This function is used to calculate the gradient along meridinal direction. Maybe need to setup a limi...
logical make_exchange_reproduce
Set to .true. to make xgrid_mod reproduce answers on different numbers of PEs. This option has a cons...
character(len=64) interp_method
Exchange grid interpolation method. It has two options: "first_order", "second_order".
integer, parameter version2
mosaic grid file
subroutine, public setup_xmap(xmap, grid_ids, grid_domains, grid_file, atm_grid, lnd_ug_domain)
Sets up exchange grid connectivity using grid specification file and processor domain decomposition.
subroutine get_grid_version1(grid, grid_id, grid_file)
read the center point of the grid from version 1 grid file. only the grid at the side 1 is needed,...
subroutine put_side1_to_xgrid_ug(d, grid_id, x, xmap, complete)
Currently only support first order.
subroutine put_side2_to_xgrid(d, grid_id, x, xmap)
Scatters data to exchange grid.
subroutine set_frac_area_sg(f, grid_id, xmap)
Changes sub-grid portion areas and/or number.
logical function in_box_nbr(i, j, grid, p)
integer, parameter version1
grid spec file
real(r8_kind) function, dimension(3) conservation_check_side2(d, grid_id, xmap, remap_method)
conservation_check - returns three numbers which are the global sum of a variable (1) on its home mod...
real(r8_kind) function, dimension(3) conservation_check_side1(d, grid_id, xmap, remap_method)
conservation_check - returns three numbers which are the global sum of a variable (1) on its home mod...
subroutine, public xgrid_init(remap_method)
Initialize the xgrid_mod.
real(r8_kind), dimension(:,:), allocatable, public area_atm_model
Area elements used inside each model.
real(r8_kind) function, dimension(is:ie, js:je) grad_zonal_latlon(d, lon, lat, is, ie, js, je, isd, jsd)
This function is used to calculate the gradient along zonal direction. Maybe need to setup a limit fo...
subroutine, public get_xmap_grid_area(id, xmap, area)
This routine is used to get the grid area of component model with id.
Returns three numbers which are the global sum of a variable.
For an unstructured grid, returns three numbers which are the global sum of a variable (1) on its hom...
Sums data from exchange grid to model grid.
get_from_xgrid for unstructured grids.
Scatters data from model grid onto exchange grid.
put_to_xgrid for unstructured grids.
Sets sub-grid area and numbering in the given exchange grid.
Private type used for exchange grid communication.
Type to hold pointers for grid boxes.
Private type to hold all data needed from given grid for an exchange grid.
Private type for overlap exchange grid data.
Private type for exchange grid data.
Private type for exchange grid data.
Private type for cell indices and data in the exchange grid.
Type for an exchange grid, holds pointers to included grids and any necessary data.
Get the current pelist. The two flavors of this subroutine differ in the type of their comm/commID ar...