77 #include <fms_platform.h> 78 use constants_mod
, only: omega, pi=>pi_8, cnst_radius=>
radius 79 use mpp_mod
, only: fatal, mpp_error, warning
81 use mpp_domains_mod
, only: mpp_update_domains, dgrid_ne, mpp_global_sum
82 use mpp_domains_mod
, only: bitwise_exact_sum, domain2d, bitwise_efp_sum
83 use mpp_parameter_mod
, only: agrid_param=>agrid, cgrid_ne_param=>cgrid_ne
84 use mpp_parameter_mod
, only: corner, scalar_pair
90 use fv_mp_mod, only: mp_reduce_sum, mp_reduce_min, mp_reduce_max
91 use fv_mp_mod, only: fill_corners, xdir, ydir
97 #ifdef NO_QUAD_PRECISION 99 integer,
parameter::
f_p = selected_real_kind(15)
102 integer,
parameter::
f_p = selected_real_kind(20)
133 subroutine grid_utils_init(Atm, npx, npy, npz, non_ortho, grid_type, c2l_order)
136 logical,
intent(in):: non_ortho
137 integer,
intent(in):: npx, npy, npz
138 integer,
intent(in):: grid_type, c2l_order
148 real(kind=R_GRID) grid3(3,atm%bd%isd:atm%bd%ied+1,atm%bd%jsd:atm%bd%jed+1)
149 real(kind=R_GRID) p1(3), p2(3), p3(3), p4(3), pp(3), ex(3), ey(3), e1(3), e2(3)
150 real(kind=R_GRID) pp1(2), pp2(2), pp3(2)
151 real(kind=R_GRID) sin2, tmp1, tmp2
152 integer i, j, k, n, ip
154 integer :: is, ie, js, je
155 integer :: isd, ied, jsd, jed
158 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: agrid, grid
159 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
160 real(kind=R_GRID),
pointer,
dimension(:,:) :: sina, cosa, dx, dy, dxc, dyc, dxa, dya
161 real,
pointer,
dimension(:,:) :: del6_u, del6_v
162 real,
pointer,
dimension(:,:) :: divg_u, divg_v
163 real,
pointer,
dimension(:,:) :: cosa_u, cosa_v, cosa_s
164 real,
pointer,
dimension(:,:) :: sina_u, sina_v
165 real,
pointer,
dimension(:,:) :: rsin_u, rsin_v
166 real,
pointer,
dimension(:,:) :: rsina, rsin2
167 real,
pointer,
dimension(:,:,:) :: sin_sg, cos_sg
168 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: ee1, ee2, ec1, ec2
169 real(kind=R_GRID),
pointer,
dimension(:,:,:,:) :: ew, es
170 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: en1, en2
172 logical,
pointer :: sw_corner, se_corner, ne_corner, nw_corner
184 agrid => atm%gridstruct%agrid_64
185 grid => atm%gridstruct%grid_64
186 area => atm%gridstruct%area_64
187 area_c => atm%gridstruct%area_c_64
188 dx => atm%gridstruct%dx_64
189 dy => atm%gridstruct%dy_64
190 dxc => atm%gridstruct%dxc_64
191 dyc => atm%gridstruct%dyc_64
192 dxa => atm%gridstruct%dxa_64
193 dya => atm%gridstruct%dya_64
194 sina => atm%gridstruct%sina_64
195 cosa => atm%gridstruct%cosa_64
197 divg_u => atm%gridstruct%divg_u
198 divg_v => atm%gridstruct%divg_v
200 del6_u => atm%gridstruct%del6_u
201 del6_v => atm%gridstruct%del6_v
203 cosa_u => atm%gridstruct%cosa_u
204 cosa_v => atm%gridstruct%cosa_v
205 cosa_s => atm%gridstruct%cosa_s
206 sina_u => atm%gridstruct%sina_u
207 sina_v => atm%gridstruct%sina_v
208 rsin_u => atm%gridstruct%rsin_u
209 rsin_v => atm%gridstruct%rsin_v
210 rsina => atm%gridstruct%rsina
211 rsin2 => atm%gridstruct%rsin2
212 ee1 => atm%gridstruct%ee1
213 ee2 => atm%gridstruct%ee2
214 ec1 => atm%gridstruct%ec1
215 ec2 => atm%gridstruct%ec2
216 ew => atm%gridstruct%ew
217 es => atm%gridstruct%es
218 sin_sg => atm%gridstruct%sin_sg
219 cos_sg => atm%gridstruct%cos_sg
220 en1 => atm%gridstruct%en1
221 en2 => atm%gridstruct%en2
225 sw_corner => atm%gridstruct%sw_corner
226 se_corner => atm%gridstruct%se_corner
227 ne_corner => atm%gridstruct%ne_corner
228 nw_corner => atm%gridstruct%nw_corner
230 if ( atm%flagstruct%do_schmidt .and. abs(atm%flagstruct%stretch_fac-1.) > 1.e-5 )
then 231 atm%gridstruct%stretched_grid = .true.
234 atm%gridstruct%stretched_grid = .false.
245 elseif ( .not. atm%flagstruct%hybrid_z )
then 247 if (.not. atm%flagstruct%external_eta)
then 248 call set_eta(npz, atm%ks, atm%ptop, atm%ak, atm%bk)
249 if ( is_master() )
then 250 write(*,*)
'Grid_init', npz, atm%ks, atm%ptop
251 tmp1 = atm%ak(atm%ks+1)
253 tmp1 = max(tmp1, (atm%ak(k)-atm%ak(k+1))/max(1.e-9, (atm%bk(k+1)-atm%bk(k))) )
255 write(*,*)
'Hybrid Sigma-P: minimum allowable surface pressure (hpa)=', tmp1/100.
256 if ( tmp1 > 420.e2 )
write(*,*)
'Warning: the chosen setting in set_eta can cause instability' 263 if (.not.
allocated(sst_ncep))
allocate (sst_ncep(i_sst,j_sst))
264 if (.not.
allocated(sst_anom))
allocate (sst_anom(i_sst,j_sst))
276 if (grid_type < 3 .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 277 if ( is==1 .and. js==1 ) sw_corner = .true.
278 if ( (ie+1)==npx .and. js==1 ) se_corner = .true.
279 if ( (ie+1)==npx .and. (je+1)==npy ) ne_corner = .true.
280 if ( is==1 .and. (je+1)==npy ) nw_corner = .true.
283 if ( sw_corner )
then 286 write(*,*)
'Corner interpolation coefficient=', tmp2/(tmp2-tmp1)
289 if (grid_type < 3)
then 291 if ( .not. atm%neststruct%nested .and. .not.atm%flagstruct%regional )
then 292 call fill_corners(grid(:,:,1), npx, npy, fill=xdir, bgrid=.true.)
293 call fill_corners(grid(:,:,2), npx, npy, fill=xdir, bgrid=.true.)
306 if (.not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 316 if ( ( (i<1 .and. j<1 ) .or. (i>npx .and. j<1 ) .or. &
317 (i>npx .and. j>(npy-1)) .or. (i<1 .and. j>(npy-1)) ) .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 320 call mid_pt_cart( grid(i,j,1:2), grid(i,j+1,1:2), pp)
321 if (i==1 .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 324 elseif(i==npx .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 335 call vect_cross(p1, grid3(1,i,j), grid3(1,i,j+1))
344 if ( ( (i<1 .and. j<1 ) .or. (i>(npx-1) .and. j<1 ) .or. &
345 (i>(npx-1) .and. j>npy) .or. (i<1 .and. j>npy) ) .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 348 call mid_pt_cart(grid(i,j,1:2), grid(i+1,j,1:2), pp)
349 if (j==1 .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 352 elseif (j==npy .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 363 call vect_cross(p3, grid3(1,i,j), grid3(1,i+1,j))
380 cos_sg(i,j,6) =
cos_angle( grid3(1,i,j), grid3(1,i+1,j), grid3(1,i,j+1) )
382 cos_sg(i,j,7) = -
cos_angle( grid3(1,i+1,j), grid3(1,i,j), grid3(1,i+1,j+1) )
384 cos_sg(i,j,8) =
cos_angle( grid3(1,i+1,j+1), grid3(1,i+1,j), grid3(1,i,j+1) )
386 cos_sg(i,j,9) = -
cos_angle( grid3(1,i,j+1), grid3(1,i,j), grid3(1,i+1,j+1) )
396 cos_sg(i,j,1) =
cos_angle( p1, p3, grid3(1,i,j+1) )
398 cos_sg(i,j,2) =
cos_angle( p1, grid3(1,i+1,j), p3 )
400 cos_sg(i,j,3) =
cos_angle( p1, p3, grid3(1,i+1,j) )
402 cos_sg(i,j,4) =
cos_angle( p1, grid3(1,i,j+1), p3 )
405 cos_sg(i,j,5) =
inner_prod( ec1(1:3,i,j), ec2(1:3,i,j) )
412 sin_sg(i,j,ip) = min(1.0, sqrt( max(0., 1.-cos_sg(i,j,ip)**2) ) )
421 if (.not. atm%neststruct%nested .and. .not. atm%flagstruct%regional)
then 422 if ( sw_corner )
then 424 sin_sg(0,i,3) = sin_sg(i,1,2)
425 sin_sg(i,0,4) = sin_sg(1,i,1)
428 if ( nw_corner )
then 430 sin_sg(0,i,3) = sin_sg(npy-i,npy-1,4)
433 sin_sg(i,npy,2) = sin_sg(1,npx+i,1)
436 if ( se_corner )
then 438 sin_sg(npx,j,1) = sin_sg(npx-j,1,2)
441 sin_sg(i,0,4) = sin_sg(npx-1,npx-i,3)
444 if ( ne_corner )
then 446 sin_sg(npx,i,1) = sin_sg(i,npy-1,4)
447 sin_sg(i,npy,2) = sin_sg(npx-1,i,3)
455 pp1(:) = grid(i ,j ,1:2)
456 pp2(:) = grid(i,j+1 ,1:2)
460 atm%gridstruct%l2c_v(i,j) = cos(pp3(2)) *
inner_prod(e2, ex)
465 pp1(:) = grid(i, j,1:2)
466 pp2(:) = grid(i+1,j,1:2)
470 atm%gridstruct%l2c_u(i,j) = cos(pp3(2)) *
inner_prod(e1, ex)
503 if ( non_ortho )
then 519 if (i==1 .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 520 call vect_cross(pp, grid3(1,i, j), grid3(1,i+1,j))
521 elseif(i==npx .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 522 call vect_cross(pp, grid3(1,i-1,j), grid3(1,i, j))
524 call vect_cross(pp, grid3(1,i-1,j), grid3(1,i+1,j))
526 call vect_cross(ee1(1:3,i,j), pp, grid3(1:3,i,j))
530 if (j==1 .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 531 call vect_cross(pp, grid3(1:3,i,j ), grid3(1:3,i,j+1))
532 elseif(j==npy .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 533 call vect_cross(pp, grid3(1:3,i,j-1), grid3(1:3,i,j ))
535 call vect_cross(pp, grid3(1:3,i,j-1), grid3(1:3,i,j+1))
537 call vect_cross(ee2(1:3,i,j), pp, grid3(1:3,i,j))
543 cosa(i,j) = sign(min(1., abs(tmp1)), tmp1)
544 sina(i,j) = sqrt(max(0.,1. -cosa(i,j)**2))
546 cosa(i,j) = 0.5*(cos_sg(i-1,j-1,8)+cos_sg(i,j,6))
547 sina(i,j) = 0.5*(sin_sg(i-1,j-1,8)+sin_sg(i,j,6))
559 cosa_u(i,j) = 0.5*(cos_sg(i-1,j,3)+cos_sg(i,j,1))
560 sina_u(i,j) = 0.5*(sin_sg(i-1,j,3)+sin_sg(i,j,1))
562 rsin_u(i,j) = 1. / max(
tiny_number, sina_u(i,j)**2)
567 cosa_v(i,j) = 0.5*(cos_sg(i,j-1,4)+cos_sg(i,j,2))
568 sina_v(i,j) = 0.5*(sin_sg(i,j-1,4)+sin_sg(i,j,2))
570 rsin_v(i,j) = 1. / max(
tiny_number, sina_v(i,j)**2)
576 cosa_s(i,j) = cos_sg(i,j,5)
578 rsin2(i,j) = 1. / max(
tiny_number, sin_sg(i,j,5)**2)
582 if (.not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 590 if ( i==npx .and. j==npy .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 591 else if ( ( i==1 .or. i==npx .or. j==1 .or. j==npy ) .and. .not. (atm%neststruct%nested.or.atm%flagstruct%regional) )
then 602 if ( (i==1 .or. i==npx) .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional) )
then 604 rsin_u(i,j) = 1. / sign(max(
tiny_number,abs(sina_u(i,j))), sina_u(i,j))
611 if ( (j==1 .or. j==npy) .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional) )
then 613 rsin_v(i,j) = 1. / sign(max(
tiny_number,abs(sina_v(i,j))), sina_v(i,j))
622 if (.not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 632 if ( sw_corner )
then 634 sin_sg(0,i,3) = sin_sg(i,1,2)
635 sin_sg(i,0,4) = sin_sg(1,i,1)
636 cos_sg(0,i,3) = cos_sg(i,1,2)
637 cos_sg(i,0,4) = cos_sg(1,i,1)
646 if ( nw_corner )
then 648 sin_sg(0,i,3) = sin_sg(npy-i,npy-1,4)
649 cos_sg(0,i,3) = cos_sg(npy-i,npy-1,4)
654 sin_sg(i,npy,2) = sin_sg(1,npy-i,1)
655 cos_sg(i,npy,2) = cos_sg(1,npy-i,1)
661 if ( se_corner )
then 663 sin_sg(npx,j,1) = sin_sg(npx-j,1,2)
664 cos_sg(npx,j,1) = cos_sg(npx-j,1,2)
669 sin_sg(i,0,4) = sin_sg(npx-1,npx-i,3)
670 cos_sg(i,0,4) = cos_sg(npx-1,npx-i,3)
676 if ( ne_corner )
then 678 sin_sg(npx,npy+i,1) = sin_sg(npx+i,npy-1,4)
679 sin_sg(npx+i,npy,2) = sin_sg(npx-1,npy+i,3)
680 cos_sg(npx,npy+i,1) = cos_sg(npx+i,npy-1,4)
683 cos_sg(npx+i,npy,2) = cos_sg(npx-1,npy+i,3)
704 if ( grid_type < 3 )
then 711 if (.not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 715 call vect_cross(ew(1,i,j,1), grid3(1,i,j+1), grid3(1,i,j))
718 if ( (ie+1)==npx )
then 720 call vect_cross(ew(1,i,j,1), grid3(1,i,j+1), grid3(1,i,j))
728 call vect_cross(es(1,i,j,2), grid3(1,i,j),grid3(1,i+1,j))
732 if ( (je+1)==npy )
then 735 call vect_cross(es(1,i,j,2), grid3(1,i,j),grid3(1,i+1,j))
746 call vect_cross(en1(1:3,i,j), grid3(1,i,j), grid3(1,i+1,j))
752 call vect_cross(en2(1:3,i,j), grid3(1,i,j+1), grid3(1,i,j))
765 if ((j==1 .OR. j==npy) .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 767 divg_u(i,j) = 0.5*(sin_sg(i,j,2)+sin_sg(i,j-1,4))*dyc(i,j)/dx(i,j)
768 del6_u(i,j) = 0.5*(sin_sg(i,j,2)+sin_sg(i,j-1,4))*dx(i,j)/dyc(i,j)
772 divg_u(i,j) = sina_v(i,j)*dyc(i,j)/dx(i,j)
773 del6_u(i,j) = sina_v(i,j)*dx(i,j)/dyc(i,j)
779 divg_v(i,j) = sina_u(i,j)*dxc(i,j)/dy(i,j)
780 del6_v(i,j) = sina_u(i,j)*dy(i,j)/dxc(i,j)
782 if (is == 1 .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 783 divg_v(is,j) = 0.5*(sin_sg(1,j,1)+sin_sg(0,j,3))*dxc(is,j)/dy(is,j)
784 del6_v(is,j) = 0.5*(sin_sg(1,j,1)+sin_sg(0,j,3))*dy(is,j)/dxc(is,j)
786 if (ie+1 == npx .and. .not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 787 divg_v(ie+1,j) = 0.5*(sin_sg(npx,j,1)+sin_sg(npx-1,j,3))*dxc(ie+1,j)/dy(ie+1,j)
788 del6_v(ie+1,j) = 0.5*(sin_sg(npx,j,1)+sin_sg(npx-1,j,3))*dy(ie+1,j)/dxc(ie+1,j)
793 call init_cubed_to_latlon( atm%gridstruct, atm%flagstruct%hydrostatic, agrid, grid_type, c2l_order, atm%bd )
795 call global_mx(area, ng, atm%gridstruct%da_min, atm%gridstruct%da_max, atm%bd)
796 if( is_master() )
write(*,*)
'da_max/da_min=', atm%gridstruct%da_max/atm%gridstruct%da_min
798 call global_mx_c(area_c(is:ie,js:je), is, ie, js, je, atm%gridstruct%da_min_c, atm%gridstruct%da_max_c)
800 if( is_master() )
write(*,*)
'da_max_c/da_min_c=', atm%gridstruct%da_max_c/atm%gridstruct%da_min_c
806 if (grid_type < 3 .and. .not. atm%neststruct%nested .and. .not. atm%flagstruct%regional )
then 807 call mpp_update_domains(divg_v, divg_u, atm%domain, flags=scalar_pair, &
808 gridtype=cgrid_ne_param, complete=.true.)
809 call mpp_update_domains(del6_v, del6_u, atm%domain, flags=scalar_pair, &
810 gridtype=cgrid_ne_param, complete=.true.)
811 call edge_factors (atm%gridstruct%edge_s, atm%gridstruct%edge_n, atm%gridstruct%edge_w, &
812 atm%gridstruct%edge_e, non_ortho, grid, agrid, npx, npy, atm%bd)
813 call efactor_a2c_v(atm%gridstruct%edge_vect_s, atm%gridstruct%edge_vect_n, &
814 atm%gridstruct%edge_vect_w, atm%gridstruct%edge_vect_e, &
815 non_ortho, grid, agrid, npx, npy, atm%neststruct%nested, atm%bd, atm%flagstruct%regional)
833 atm%gridstruct%grid = atm%gridstruct%grid_64
834 atm%gridstruct%agrid = atm%gridstruct%agrid_64
835 atm%gridstruct%area = atm%gridstruct%area_64
836 atm%gridstruct%area_c = atm%gridstruct%area_c_64
837 atm%gridstruct%dx = atm%gridstruct%dx_64
838 atm%gridstruct%dy = atm%gridstruct%dy_64
839 atm%gridstruct%dxa = atm%gridstruct%dxa_64
840 atm%gridstruct%dya = atm%gridstruct%dya_64
841 atm%gridstruct%dxc = atm%gridstruct%dxc_64
842 atm%gridstruct%dyc = atm%gridstruct%dyc_64
843 atm%gridstruct%cosa = atm%gridstruct%cosa_64
844 atm%gridstruct%sina = atm%gridstruct%sina_64
850 deallocate ( atm%gridstruct%area_c_64 )
853 deallocate ( atm%gridstruct%dxa_64 )
854 deallocate ( atm%gridstruct%dya_64 )
855 deallocate ( atm%gridstruct%dxc_64 )
856 deallocate ( atm%gridstruct%dyc_64 )
857 deallocate ( atm%gridstruct%cosa_64 )
858 deallocate ( atm%gridstruct%sina_64 )
908 if (
allocated(sst_ncep))
deallocate( sst_ncep )
909 if (
allocated(sst_anom))
deallocate( sst_anom )
918 real(kind=R_GRID),
intent(in):: c
919 real(kind=R_GRID),
intent(in):: lon_p, lat_p
920 integer,
intent(in):: n
921 integer,
intent(in):: i1, i2, j1, j2
923 real(kind=R_GRID),
intent(inout),
dimension(i1:i2,j1:j2):: lon, lat
925 real(f_p):: lat_t, sin_p, cos_p, sin_lat, cos_lat, sin_o, p2, two_pi
926 real(f_p):: c2p1, c2m1
932 if( is_master() .and. n==1 )
then 933 write(*,*) n,
'Schmidt transformation: stretching factor=', c,
' center=', lon_p, lat_p
944 if ( abs(c2m1) > 1.d-7 )
then 945 sin_lat = sin(lat(i,j))
946 lat_t = asin( (c2m1+c2p1*sin_lat)/(c2p1+c2m1*sin_lat) )
952 sin_o = -(sin_p*sin_lat + cos_p*cos_lat*cos(lon(i,j)))
953 if ( (1.-abs(sin_o)) < 1.d-7 )
then 955 lat(i,j) = sign( p2, sin_o )
957 lat(i,j) = asin( sin_o )
958 lon(i,j) = lon_p + atan2( -cos_lat*sin(lon(i,j)), &
959 -sin_lat*cos_p+cos_lat*sin_p*cos(lon(i,j)))
960 if ( lon(i,j) < 0.d0 )
then 961 lon(i,j) = lon(i,j) + two_pi
962 elseif( lon(i,j) >= two_pi )
then 963 lon(i,j) = lon(i,j) - two_pi
973 real(kind=R_GRID),
intent(in):: v1(3), v2(3)
974 real (f_p) :: vp1(3), vp2(3), prod16
978 vp1(k) =
real(v1(k),kind=
f_p)
979 vp2(k) =
real(v2(k),kind=
f_p)
981 prod16 = vp1(1)*vp2(1) + vp1(2)*vp2(2) + vp1(3)*vp2(3)
988 subroutine efactor_a2c_v(edge_vect_s, edge_vect_n, edge_vect_w, edge_vect_e, non_ortho, grid, agrid, npx, npy, nested, bd, regional)
990 real(kind=R_GRID),
intent(INOUT),
dimension(bd%isd:bd%ied) :: edge_vect_s, edge_vect_n
991 real(kind=R_GRID),
intent(INOUT),
dimension(bd%jsd:bd%jed) :: edge_vect_w, edge_vect_e
992 logical,
intent(in):: non_ortho, nested, regional
993 real(kind=R_GRID),
intent(in):: grid(bd%isd:bd%ied+1,bd%jsd:bd%jed+1,2)
994 real(kind=R_GRID),
intent(in):: agrid(bd%isd:bd%ied ,bd%jsd:bd%jed ,2)
995 integer,
intent(in):: npx, npy
997 real(kind=R_GRID) px(2,bd%isd:bd%ied+1), py(2,bd%jsd:bd%jed+1)
998 real(kind=R_GRID) p1(2,bd%isd:bd%ied+1), p2(2,bd%jsd:bd%jed+1)
999 real(kind=R_GRID) d1, d2
1003 integer :: is, ie, js, je
1004 integer :: isd, ied, jsd, jed
1016 if ( .not. non_ortho )
then 1027 if ( npx /= npy .and. .not. (nested .or. regional))
call mpp_error(fatal,
'efactor_a2c_v: npx /= npy')
1028 if ( (npx/2)*2 == npx )
call mpp_error(fatal,
'efactor_a2c_v: npx/npy is not an odd number')
1036 call mid_pt_sphere(agrid(i-1,j,1:2), agrid(i,j, 1:2), py(1,j))
1037 call mid_pt_sphere( grid(i, j,1:2), grid(i,j+1,1:2), p2(1,j))
1048 edge_vect_w(j) = d1 / ( d1 + d2 )
1052 edge_vect_w(j) = d1 / ( d2 + d1 )
1056 edge_vect_w(0) = edge_vect_w(1)
1058 if ( (je+1)==npy )
then 1059 edge_vect_w(npy) = edge_vect_w(je)
1066 if ( (ie+1)==npx )
then 1069 call mid_pt_sphere(agrid(i-1,j,1:2), agrid(i,j, 1:2), py(1,j))
1070 call mid_pt_sphere( grid(i, j,1:2), grid(i,j+1,1:2), p2(1,j))
1077 edge_vect_e(j) = d1 / ( d1 + d2 )
1081 edge_vect_e(j) = d1 / ( d2 + d1 )
1085 edge_vect_e(0) = edge_vect_e(1)
1087 if ( (je+1)==npy )
then 1088 edge_vect_e(npy) = edge_vect_e(je)
1098 call mid_pt_sphere(agrid(i,j-1,1:2), agrid(i, j,1:2), px(1,i))
1099 call mid_pt_sphere( grid(i,j, 1:2), grid(i+1,j,1:2), p1(1,i))
1109 edge_vect_s(i) = d1 / ( d1 + d2 )
1113 edge_vect_s(i) = d1 / ( d2 + d1 )
1117 edge_vect_s(0) = edge_vect_s(1)
1119 if ( (ie+1)==npx )
then 1120 edge_vect_s(npx) = edge_vect_s(ie)
1128 if ( (je+1)==npy )
then 1132 call mid_pt_sphere(agrid(i,j-1,1:2), agrid(i, j,1:2), px(1,i))
1133 call mid_pt_sphere( grid(i,j, 1:2), grid(i+1,j,1:2), p1(1,i))
1140 edge_vect_n(i) = d1 / ( d1 + d2 )
1144 edge_vect_n(i) = d1 / ( d2 + d1 )
1148 edge_vect_n(0) = edge_vect_n(1)
1150 if ( (ie+1)==npx )
then 1151 edge_vect_n(npx) = edge_vect_n(ie)
1165 subroutine edge_factors(edge_s, edge_n, edge_w, edge_e, non_ortho, grid, agrid, npx, npy, bd)
1167 real(kind=R_GRID),
intent(INOUT),
dimension(npx) :: edge_s, edge_n
1168 real(kind=R_GRID),
intent(INOUT),
dimension(npy) :: edge_w, edge_e
1169 logical,
intent(in):: non_ortho
1170 real(kind=R_GRID),
intent(in):: grid(bd%isd:bd%ied+1,bd%jsd:bd%jed+1,2)
1171 real(kind=R_GRID),
intent(in):: agrid(bd%isd:bd%ied ,bd%jsd:bd%jed ,2)
1172 integer,
intent(in):: npx, npy
1174 real(kind=R_GRID) px(2,npx), py(2,npy)
1175 real(kind=R_GRID) d1, d2
1178 integer :: is, ie, js, je
1179 integer :: isd, ied, jsd, jed
1190 if ( .not. non_ortho )
then 1207 do j=max(1,js-1), min(npy-1,je+1)
1208 call mid_pt_sphere(agrid(i-1,j,1:2), agrid(i,j,1:2), py(1,j))
1210 do j=max(2,js), min(npy-1,je+1)
1213 edge_w(j) = d2 / ( d1 + d2 )
1221 if ( (ie+1)==npx )
then 1223 do j=max(1,js-1), min(npy-1,je+1)
1224 call mid_pt_sphere(agrid(i-1,j,1:2), agrid(i,j,1:2), py(1,j))
1226 do j=max(2,js), min(npy-1,je+1)
1229 edge_e(j) = d2 / ( d1 + d2 )
1242 do i=max(1,is-1), min(npx-1,ie+1)
1243 call mid_pt_sphere(agrid(i,j-1,1:2), agrid(i,j,1:2), px(1,i))
1245 do i=max(2,is), min(npx-1,ie+1)
1248 edge_s(i) = d2 / ( d1 + d2 )
1256 if ( (je+1)==npy )
then 1258 do i=max(1,is-1), min(npx-1,ie+1)
1259 call mid_pt_sphere(agrid(i,j-1,1:2), agrid(i,j,1:2), px(1,i))
1261 do i=max(2,is), min(npx-1,ie+1)
1264 edge_n(i) = d2 / ( d1 + d2 )
1274 integer,
intent(in):: im, grid_type
1275 real(kind=R_GRID),
intent(out):: lon(im+1,im+1)
1276 real(kind=R_GRID),
intent(out):: lat(im+1,im+1)
1284 if(grid_type<3)
then 1288 lon(i,j) = lon(i,j) - pi
1310 integer,
intent(in):: im
1311 real(kind=R_GRID),
intent(out):: lamda(im+1,im+1)
1312 real(kind=R_GRID),
intent(out):: theta(im+1,im+1)
1315 real(kind=R_GRID) pp(3,im+1,im+1)
1316 real(kind=R_GRID) p1(2), p2(2)
1317 real(f_p):: rsq3, alpha, delx, dely
1320 rsq3 = 1.d0/sqrt(3.d0)
1321 alpha = asin( rsq3 )
1327 dely = 2.d0*alpha /
real(im,kind=
f_p)
1331 lamda(1, j) = 0.75d0*pi
1332 lamda(im+1,j) = 1.25d0*pi
1333 theta(1, j) = -alpha + dely*
real(j-1,kind=f_p) 1334 theta(im+1,j) = theta(1,j)
1340 call mirror_latlon(lamda(1,1), theta(1,1), lamda(im+1,im+1), theta(im+1,im+1), &
1341 lamda(1,i), theta(1,i), lamda(i,1), theta(i, 1) )
1342 lamda(i,im+1) = lamda(i,1)
1343 theta(i,im+1) = -theta(i,1)
1347 call latlon2xyz2(lamda(1 , 1), theta(1, 1), pp(1, 1, 1))
1348 call latlon2xyz2(lamda(im+1, 1), theta(im+1, 1), pp(1,im+1, 1))
1349 call latlon2xyz2(lamda(1, im+1), theta(1, im+1), pp(1, 1,im+1))
1350 call latlon2xyz2(lamda(im+1,im+1), theta(im+1,im+1), pp(1,im+1,im+1))
1357 call latlon2xyz2(lamda(i,j), theta(i,j), pp(1,i,j))
1358 pp(2,i,j) = -pp(2,i,j)*rsq3/pp(1,i,j)
1359 pp(3,i,j) = -pp(3,i,j)*rsq3/pp(1,i,j)
1364 call latlon2xyz2(lamda(i,j), theta(i,j), pp(1,i,1))
1365 pp(2,i,1) = -pp(2,i,1)*rsq3/pp(1,i,1)
1366 pp(3,i,1) = -pp(3,i,1)*rsq3/pp(1,i,1)
1378 pp(2,i,j) = pp(2,i,1)
1380 pp(3,i,j) = pp(3,1,j)
1387 if ( is_master() )
then 1388 p1(1) = lamda(1,1); p1(2) = theta(1,1)
1389 p2(1) = lamda(2,1); p2(2) = theta(2,1)
1405 integer,
intent(IN) :: im, in, nghost
1406 real(kind=R_GRID),
intent(IN),
dimension(2) :: lL, lR, uL, uR
1407 real(kind=R_GRID),
intent(OUT) :: lamda(1-nghost:im+1+nghost,1-nghost:in+1+nghost)
1408 real(kind=R_GRID),
intent(OUT) :: theta(1-nghost:im+1+nghost,1-nghost:in+1+nghost)
1411 real(kind=R_GRID) pp(3,1-nghost:im+1+nghost,1-nghost:in+1+nghost)
1412 real(kind=R_GRID) p1(2), p2(2)
1413 real(f_p):: rsq3, alpha, delx, dely
1414 integer i, j, k, irefl
1416 rsq3 = 1.d0/sqrt(3.d0)
1417 alpha = asin( rsq3 )
1419 lamda(1,1) = ll(1); theta(1,1) = ll(2)
1420 lamda(im+1,1) = lr(1); theta(im+1,1) = lr(2)
1421 lamda(1,in+1) = ul(1); theta(1,in+1) = ul(2)
1422 lamda(im+1,in+1) = ur(1); theta(im+1,in+1) = ur(2)
1426 dely = (ul(2) - ll(2))/in
1428 theta(1,j) = theta(1,j-1) + dely
1429 theta(in+1,j) = theta(in+1,j-1) + dely
1430 lamda(1,j) = lamda(1,1)
1431 lamda(in+1,j) = lamda(in+1,1)
1434 theta(1,j) = theta(1,j+1) - dely
1435 theta(in+1,j) = theta(in+1,j+1) - dely
1436 lamda(1,j) = lamda(1,1)
1437 lamda(in+1,j) = lamda(in+1,1)
1440 lamda(1,:) = lamda(1,1)
1441 lamda(in+1,:) = lamda(in+1,1)
1445 do i=1-nghost,im+1+nghost
1450 (/lamda(1,1),theta(1,1)/), (/lamda(im+1,1),theta(im+1,1)/), p1 )
1452 (/lamda(1,in+1),theta(1,in+1)/), (/lamda(im+1,in+1),theta(im+1,in+1)/), p2 )
1454 lamda(i,1) = p1(1); theta(i,1) = p1(2)
1455 lamda(i,in+1) = p2(1); theta(i,in+1) = p2(2)
1462 do j=1-nghost,in+1+nghost
1463 call latlon2xyz2(lamda(i,j), theta(i,j), pp(1,i,j))
1464 pp(2,i,j) = -pp(2,i,j)*rsq3/pp(1,i,j)
1465 pp(3,i,j) = -pp(3,i,j)*rsq3/pp(1,i,j)
1469 do i=1-nghost,im+1+nghost
1470 call latlon2xyz2(lamda(i,j), theta(i,j), pp(1,i,1))
1471 pp(2,i,1) = -pp(2,i,1)*rsq3/pp(1,i,1)
1472 pp(3,i,1) = -pp(3,i,1)*rsq3/pp(1,i,1)
1477 do j=1-nghost,in+1+nghost
1478 do i=1-nghost,im+1+nghost
1483 do j=1-nghost,in+1+nghost
1484 do i=1-nghost,im+1+nghost
1486 pp(2,i,j) = pp(2,i,1)
1488 pp(3,i,j) = pp(3,1,j)
1493 pp(:,1-nghost:im+1+nghost,1-nghost:in+1+nghost), &
1494 lamda(1-nghost:im+1+nghost,1-nghost:in+1+nghost), &
1495 theta(1-nghost:im+1+nghost,1-nghost:in+1+nghost))
1499 if ( is_master() )
then 1500 p1(1) = lamda(1,1); p1(2) = theta(1,1)
1501 p2(1) = lamda(2,1); p2(2) = theta(2,1)
1503 p2(1) = lamda(1,2); p2(2) = theta(1,2)
1516 real(kind=R_GRID) lamda(im+1,im+1)
1517 real(kind=R_GRID) theta(im+1,im+1)
1518 real(kind=R_GRID) p(3,im+1,im+1)
1520 real(kind=R_GRID) rsq3, xf, y0, z0, y, x, z, ds
1521 real(kind=R_GRID) dy, dz
1523 real(kind=R_GRID) dp
1525 dp = 0.5d0*pi/
real(im,kind=
r_grid)
1527 rsq3 = 1.d0/sqrt(3.d0)
1531 p(2,j,k) =-rsq3*tan(-0.25d0*pi+(j-1)*dp)
1532 p(3,j,k) = rsq3*tan(-0.25d0*pi+(k-1)*dp)
1543 real(kind=R_GRID) lamda(im+1,im+1)
1544 real(kind=R_GRID) theta(im+1,im+1)
1545 real(kind=R_GRID) p(3,im+1,im+1)
1547 real(kind=R_GRID) rsq3, xf, y0, z0, y, x, z, ds
1548 real(kind=R_GRID) dy, dz
1553 rsq3 = 1.d0/sqrt(3.d0)
1555 y0 = rsq3; dy = -2.d0*rsq3/im
1556 z0 = -rsq3; dz = 2.d0*rsq3/im
1561 p(2,j,k) = y0 + (j-1)*dy
1562 p(3,j,k) = z0 + (k-1)*dz
1569 subroutine symm_ed(im, lamda, theta)
1572 real(kind=R_GRID) lamda(im+1,im+1)
1573 real(kind=R_GRID) theta(im+1,im+1)
1575 real(kind=R_GRID) avg
1579 lamda(i,j) = lamda(i,1)
1586 avg = 0.5d0*(lamda(i,j)-lamda(ip,j))
1587 lamda(i, j) = avg + pi
1588 lamda(ip,j) = pi - avg
1589 avg = 0.5d0*(theta(i,j)+theta(ip,j))
1599 avg = 0.5d0*(lamda(i,j)+lamda(i,jp))
1602 avg = 0.5d0*(theta(i,j)-theta(i,jp))
1611 real(kind=R_GRID),
intent(in):: lon, lat
1612 real(kind=R_GRID),
intent(out):: p3(3)
1613 real(kind=R_GRID) e(2)
1615 e(1) = lon; e(2) = lat
1623 real(kind=R_GRID),
intent(in) :: p(2)
1624 real(kind=R_GRID),
intent(out):: e(3)
1625 integer,
optional,
intent(in):: id
1629 real (f_p):: e1, e2, e3
1635 e1 = cos(q(2)) * cos(q(1))
1636 e2 = cos(q(2)) * sin(q(1))
1661 real(kind=R_GRID),
intent(in) :: p1(3), p2(3), p0(3)
1662 real(kind=R_GRID),
intent(out):: p(3)
1664 real(kind=R_GRID):: x1, y1, z1, x2, y2, z2, x0, y0, z0
1665 real(kind=R_GRID) nb(3)
1666 real(kind=R_GRID) pdot
1670 pdot = sqrt(nb(1)**2+nb(2)**2+nb(3)**2)
1672 nb(k) = nb(k) / pdot
1675 pdot = p0(1)*nb(1) + p0(2)*nb(2) + p0(3)*nb(3)
1677 p(k) = p0(k) - 2.d0*pdot*nb(k)
1685 subroutine mirror_latlon(lon1, lat1, lon2, lat2, lon0, lat0, lon3, lat3)
1686 real(kind=R_GRID),
intent(in):: lon1, lat1, lon2, lat2, lon0, lat0
1687 real(kind=R_GRID),
intent(out):: lon3, lat3
1689 real(kind=R_GRID) p0(3), p1(3), p2(3), nb(3), pp(3), sp(2)
1690 real(kind=R_GRID) pdot
1698 pdot = sqrt(nb(1)**2+nb(2)**2+nb(3)**2)
1700 nb(k) = nb(k) / pdot
1703 pdot = p0(1)*nb(1) + p0(2)*nb(2) + p0(3)*nb(3)
1705 pp(k) = p0(k) - 2.d0*pdot*nb(k)
1717 integer,
intent(in):: np
1718 real(kind=R_GRID),
intent(inout):: q(3,np)
1719 real(kind=R_GRID),
intent(inout):: xs(np), ys(np)
1721 real(kind=R_GRID),
parameter:: esl=1.d-10
1723 real (f_p):: dist, lat, lon
1730 dist = sqrt(p(1)**2 + p(2)**2 + p(3)**2)
1735 if ( (abs(p(1))+abs(p(2))) < esl )
then 1736 lon =
real(0.,kind=
f_p)
1738 lon = atan2( p(2), p(1) )
1741 if ( lon < 0.) lon =
real(2.,kind=
f_p)*pi + lon
1758 real(kind=R_GRID),
intent(in) :: p1(3), p2(3)
1759 real(kind=R_GRID),
intent(out):: e(3)
1761 e(1) = p1(2)*p2(3) - p1(3)*p2(2)
1762 e(2) = p1(3)*p2(1) - p1(1)*p2(3)
1763 e(3) = p1(1)*p2(2) - p1(2)*p2(1)
1769 integer,
intent(in):: npx, npy
1770 real(kind=R_GRID),
intent(in) :: pp(3,bd%isd:bd%ied+1,bd%jsd:bd%jed+1)
1771 real(kind=R_GRID),
intent(out):: u1(3,bd%isd:bd%ied, bd%jsd:bd%jed)
1772 real(kind=R_GRID),
intent(out):: u2(3,bd%isd:bd%ied, bd%jsd:bd%jed)
1775 real(kind=R_GRID) p1(3), p2(3), pc(3), p3(3)
1777 integer :: isd, ied, jsd, jed
1786 if ( (i<1 .and. j<1 ) .or. (i>(npx-1) .and. j<1) .or. &
1787 (i>(npx-1) .and. j>(npy-1)) .or. (i<1 .and. j>(npy-1)))
then 1793 u1(k,i,j) = pp(k,i+1,j)+pp(k,i+1,j+1) - pp(k,i,j)-pp(k,i,j+1)
1794 u2(k,i,j) = pp(k,i,j+1)+pp(k,i+1,j+1) - pp(k,i,j)-pp(k,i+1,j)
1799 call cell_center3(pp(1,i,j), pp(1,i+1,j), pp(1,i,j+1), pp(1,i+1,j+1), pc)
1821 real(kind=R_GRID),
intent(in) :: e1(2), e2(2)
1822 real(kind=R_GRID),
intent(out):: uc(3)
1824 real(kind=R_GRID),
dimension(3):: pc, p1, p2, p3
1838 real(kind=R_GRID),
intent(in) :: p1(3), p2(3)
1839 real(kind=R_GRID),
intent(out):: uc(3)
1841 real(kind=R_GRID),
dimension(3):: pc, p3
1853 real(kind=R_GRID),
intent(inout):: e(3)
1857 pdot = e(1)**2 + e(2)**2 + e(3)**2
1868 real(kind=R_GRID),
intent(in):: beta
1869 real(kind=R_GRID),
intent(in):: p1(2), p2(2)
1870 real(kind=R_GRID),
intent(out):: x_o, y_o
1872 real(kind=R_GRID):: pm(2)
1873 real(kind=R_GRID):: e1(3), e2(3), e3(3)
1874 real(kind=R_GRID):: s1, s2, s3, dd, alpha
1881 s1 = alpha*e1(1) + beta*e2(1)
1882 s2 = alpha*e1(2) + beta*e2(2)
1883 s3 = alpha*e1(3) + beta*e2(3)
1885 dd = sqrt( s1**2 + s2**2 + s3**2 )
1903 real(kind=R_GRID),
intent(in):: beta
1904 real(kind=R_GRID),
intent(in):: p1(2), p2(2)
1905 real(kind=R_GRID),
intent(out):: pb(2)
1907 real(kind=R_GRID):: pm(2)
1908 real(kind=R_GRID):: e1(3), e2(3), eb(3)
1909 real(kind=R_GRID):: dd, alpha, omg
1911 if ( abs(p1(1) - p2(1)) < 1.d-8 .and. abs(p1(2) - p2(2)) < 1.d-8)
then 1912 call mpp_error(warning,
'spherical_linear_interpolation was passed two colocated points.')
1920 dd = sqrt( e1(1)**2 + e1(2)**2 + e1(3)**2 )
1926 dd = sqrt( e2(1)**2 + e2(2)**2 + e2(3)**2 )
1934 omg = acos( e1(1)*e2(1) + e1(2)*e2(2) + e1(3)*e2(3) )
1936 if ( abs(omg) < 1.d-5 )
then 1937 print*,
'spherical_linear_interpolation: ', omg, p1, p2
1938 call mpp_error(fatal,
'spherical_linear_interpolation: interpolation not well defined between antipodal points')
1941 eb(1) = sin( beta*omg )*e2(1) + sin(alpha*omg)*e1(1)
1942 eb(2) = sin( beta*omg )*e2(2) + sin(alpha*omg)*e1(2)
1943 eb(3) = sin( beta*omg )*e2(3) + sin(alpha*omg)*e1(3)
1945 eb(1) = eb(1) / sin(omg)
1946 eb(2) = eb(2) / sin(omg)
1947 eb(3) = eb(3) / sin(omg)
1954 real(kind=R_GRID) ,
intent(IN) :: p1(2), p2(2)
1955 real(kind=R_GRID) ,
intent(OUT) :: pm(2)
1957 real(kind=R_GRID) e1(3), e2(3), e3(3)
1969 real(kind=R_GRID),
intent(IN) :: p1(3), p2(3)
1970 real(kind=R_GRID),
intent(OUT) :: e(3)
1972 real (f_p):: q1(3), q2(3)
1973 real (f_p):: dd, e1, e2, e3
1985 dd = sqrt( e1**2 + e2**2 + e3**2 )
1999 real(kind=R_GRID),
intent(IN) :: p1(2), p2(2)
2000 real(kind=R_GRID),
intent(OUT) :: e3(3)
2002 real(kind=R_GRID) e1(3), e2(3)
2013 real(kind=R_GRID),
intent(IN) :: q1(2), q2(2)
2014 real(kind=R_GRID),
intent(IN),
optional :: radius
2016 real (f_p):: p1(2), p2(2)
2025 beta = asin( sqrt( sin((p1(2)-p2(2))/2.)**2 + cos(p1(2))*cos(p2(2))* &
2026 sin((p1(1)-p2(1))/2.)**2 ) ) * 2.
2028 if (
present(radius) )
then 2042 real(kind=R_GRID) :: great_circle_dist_cart
2043 real(kind=R_GRID),
dimension(3),
intent(in) :: v1, v2
2044 real(kind=R_GRID),
intent(IN),
optional :: radius
2045 real(kind=R_GRID) :: norm
2047 norm = (v1(1)*v1(1)+v1(2)*v1(2)+v1(3)*v1(3)) &
2048 *(v2(1)*v2(1)+v2(2)*v2(2)+v2(3)*v2(3))
2052 great_circle_dist_cart=(v1(1)*v2(1)+v1(2)*v2(2)+v1(3)*v2(3)) &
2054 great_circle_dist_cart = sign(min(1.,abs(great_circle_dist_cart)),great_circle_dist_cart)
2055 great_circle_dist_cart=acos(great_circle_dist_cart)
2057 if (
present(radius) )
then 2058 great_circle_dist_cart = radius * great_circle_dist_cart
2075 subroutine intersect(a1,a2,b1,b2,radius,x_inter,local_a,local_b)
2077 real(kind=R_GRID),
dimension(3),
intent(in) :: a1, a2, b1, b2
2078 real(kind=R_GRID),
intent(in) :: radius
2079 real(kind=R_GRID),
dimension(3),
intent(out) :: x_inter
2080 logical,
intent(out) :: local_a,local_b
2084 real(kind=R_GRID) :: a2_xy, b1_xy, b2_xy, a2_xz, b1_xz, b2_xz, &
2085 b1_xyz, b2_xyz, length
2089 a2_xy=a2(1)*a1(2)-a2(2)*a1(1)
2090 b1_xy=b1(1)*a1(2)-b1(2)*a1(1)
2091 b2_xy=b2(1)*a1(2)-b2(2)*a1(1)
2093 a2_xz=a2(1)*a1(3)-a2(3)*a1(1)
2094 b1_xz=b1(1)*a1(3)-b1(3)*a1(1)
2095 b2_xz=b2(1)*a1(3)-b2(3)*a1(1)
2097 b1_xyz=b1_xy*a2_xz-b1_xz*a2_xy
2098 b2_xyz=b2_xy*a2_xz-b2_xz*a2_xy
2100 if (b1_xyz==0.0d0)
then 2102 elseif (b2_xyz==0.0d0)
then 2105 x_inter(:)=b2(:)-b1(:)*b2_xyz/b1_xyz
2106 length=sqrt(x_inter(1)*x_inter(1)+x_inter(2)*x_inter(2)+x_inter(3)*x_inter(3))
2107 x_inter(:)=radius/length*x_inter(:)
2119 real(kind=R_GRID),
dimension(3) :: center, dx
2120 real(kind=R_GRID) :: dist1,dist2
2122 center(:)=0.25*(a1(:)+a2(:)+b1(:)+b2(:))
2123 dx(:)=+x_inter(:)-center(:)
2124 dist1=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2125 dx(:)=-x_inter(:)-center(:)
2126 dist2=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2128 if (dist2<dist1) x_inter(:)=-x_inter(:)
2133 real(kind=R_GRID),
dimension(3),
intent(in) :: x1,x2
2134 logical,
intent(out) :: local
2136 real(kind=R_GRID),
dimension(3) :: dx
2137 real(kind=R_GRID) :: dist, dist1, dist2
2140 dist=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2142 dx(:)=x1(:)-x_inter(:)
2143 dist1=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2144 dx(:)=x2(:)-x_inter(:)
2145 dist2=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2147 if (dist1<=dist .and. dist2<=dist)
then 2167 subroutine intersect_cross(a1,a2,b1,b2,radius,x_inter,local_a,local_b)
2169 real(kind=R_GRID),
dimension(3),
intent(in) :: a1, a2, b1, b2
2170 real(kind=R_GRID),
intent(in) :: radius
2171 real(kind=R_GRID),
dimension(3),
intent(out) :: x_inter
2172 logical,
intent(out) :: local_a,local_b
2173 real(kind=R_GRID),
dimension(3) :: v1, v2
2191 v1 = v1/sqrt(v1(1)**2 + v1(2)**2 + v1(3)**2)
2192 v2 = v2/sqrt(v2(1)**2 + v2(2)**2 + v2(3)**2)
2196 x_inter = x_inter/sqrt(x_inter(1)**2 + x_inter(2)**2 + x_inter(3)**2)
2205 real(kind=R_GRID),
dimension(3) :: center, dx
2206 real(kind=R_GRID) :: dist1,dist2
2208 center(:)=0.25*(a1(:)+a2(:)+b1(:)+b2(:))
2209 dx(:)=+x_inter(:)-center(:)
2210 dist1=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2211 dx(:)=-x_inter(:)-center(:)
2212 dist2=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2214 if (dist2<dist1) x_inter(:)=-x_inter(:)
2219 real(kind=R_GRID),
dimension(3),
intent(in) :: x1,x2
2220 logical,
intent(out) :: local
2222 real(kind=R_GRID),
dimension(3) :: dx
2223 real(kind=R_GRID) :: dist, dist1, dist2
2226 dist=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2228 dx(:)=x1(:)-x_inter(:)
2229 dist1=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2230 dx(:)=x2(:)-x_inter(:)
2231 dist2=dx(1)*dx(1)+dx(2)*dx(2)+dx(3)*dx(3)
2233 if (dist1<=dist .and. dist2<=dist)
then 2246 real(kind=R_GRID),
intent(IN) :: pp(2)
2247 real(kind=R_GRID),
intent(OUT) :: elon(3), elat(3)
2249 real (f_p):: lon, lat
2250 real (f_p):: sin_lon, cos_lon, sin_lat, cos_lat
2264 elat(1) = -sin_lat*cos_lon
2265 elat(2) = -sin_lat*sin_lon
2272 real(kind=R_GRID) function v_prod(v1, v2)
2273 real(kind=R_GRID) v1(3), v2(3)
2275 v_prod = v1(1)*v2(1) + v1(2)*v2(2) + v1(3)*v2(3)
2282 logical,
intent(in):: hydrostatic
2283 real(kind=R_GRID),
intent(in) :: agrid(bd%isd:bd%ied,bd%jsd:bd%jed,2)
2284 integer,
intent(in) :: grid_type
2285 integer,
intent(in) :: ord
2286 type(
fv_grid_type),
intent(INOUT),
target :: gridstruct
2289 integer :: is, ie, js, je
2292 real,
pointer,
dimension(:,:) :: a11, a12, a21, a22
2293 real,
pointer,
dimension(:,:) :: z11, z12, z21, z22
2294 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: vlon, vlat
2295 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: ee1, ee2, ec1, ec2
2302 if ( grid_type < 4 )
then 2304 vlon => gridstruct%vlon
2305 vlat => gridstruct%vlat
2306 a11 => gridstruct%a11
2307 a12 => gridstruct%a12
2308 a21 => gridstruct%a21
2309 a22 => gridstruct%a22
2310 z11 => gridstruct%z11
2311 z12 => gridstruct%z12
2312 z21 => gridstruct%z21
2313 z22 => gridstruct%z22
2314 ee1 => gridstruct%ee1
2315 ee2 => gridstruct%ee2
2316 ec1 => gridstruct%ec1
2317 ec2 => gridstruct%ec2
2327 z11(i,j) =
v_prod(ec1(1:3,i,j), vlon(i,j,1:3))
2328 z12(i,j) =
v_prod(ec1(1:3,i,j), vlat(i,j,1:3))
2329 z21(i,j) =
v_prod(ec2(1:3,i,j), vlon(i,j,1:3))
2330 z22(i,j) =
v_prod(ec2(1:3,i,j), vlat(i,j,1:3))
2332 a11(i,j) = 0.5d0*z22(i,j) / gridstruct%sin_sg(i,j,5)
2333 a12(i,j) = -0.5d0*z12(i,j) / gridstruct%sin_sg(i,j,5)
2334 a21(i,j) = -0.5d0*z21(i,j) / gridstruct%sin_sg(i,j,5)
2335 a22(i,j) = 0.5d0*z11(i,j) / gridstruct%sin_sg(i,j,5)
2345 subroutine cubed_to_latlon(u, v, ua, va, gridstruct, npx, npy, km, mode, grid_type, domain, nested, c2l_ord, bd)
2347 integer,
intent(in) :: km, npx, npy, grid_type, c2l_ord
2348 integer,
intent(in) :: mode
2350 real,
intent(inout):: u(bd%isd:bd%ied,bd%jsd:bd%jed+1,km)
2351 real,
intent(inout):: v(bd%isd:bd%ied+1,bd%jsd:bd%jed,km)
2352 real,
intent(out):: ua(bd%isd:bd%ied, bd%jsd:bd%jed,km)
2353 real,
intent(out):: va(bd%isd:bd%ied, bd%jsd:bd%jed,km)
2354 type(domain2d),
intent(INOUT) :: domain
2355 logical,
intent(IN) :: nested
2357 if ( c2l_ord == 2 )
then 2358 call c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, .false.)
2360 call c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, domain, nested, mode, bd)
2366 subroutine c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, domain, nested, mode, bd)
2369 integer,
intent(in) :: km, npx, npy, grid_type
2370 integer,
intent(in):: mode
2372 real,
intent(inout):: u(bd%isd:bd%ied,bd%jsd:bd%jed+1,km)
2373 real,
intent(inout):: v(bd%isd:bd%ied+1,bd%jsd:bd%jed,km)
2374 real,
intent(out):: ua(bd%isd:bd%ied, bd%jsd:bd%jed,km)
2375 real,
intent(out):: va(bd%isd:bd%ied, bd%jsd:bd%jed,km)
2376 type(domain2d),
intent(INOUT) :: domain
2377 logical,
intent(IN) :: nested
2381 real :: a2 = -0.0625
2384 real utmp(bd%is:bd%ie, bd%js:bd%je+1)
2385 real vtmp(bd%is:bd%ie+1,bd%js:bd%je)
2386 real wu(bd%is:bd%ie, bd%js:bd%je+1)
2387 real wv(bd%is:bd%ie+1,bd%js:bd%je)
2390 integer :: is, ie, js, je
2398 if ( mode > 0 )
then 2400 call mpp_update_domains(u, v, domain, gridtype=dgrid_ne)
2408 if ( grid_type < 4 )
then 2410 do j=max(1,js),min(npy-1,je)
2411 do i=max(1,is),min(npx-1,ie)
2412 utmp(i,j) = c2*(u(i,j-1,k)+u(i,j+2,k)) + c1*(u(i,j,k)+u(i,j+1,k))
2413 vtmp(i,j) = c2*(v(i-1,j,k)+v(i+2,j,k)) + c1*(v(i,j,k)+v(i+1,j,k))
2417 do j=max(2,js),min(npy-2,je)
2418 do i=max(2,is),min(npx-2,ie)
2419 utmp(i,j) = c2*(u(i,j-1,k)+u(i,j+2,k)) + c1*(u(i,j,k)+u(i,j+1,k))
2420 vtmp(i,j) = c2*(v(i-1,j,k)+v(i+2,j,k)) + c1*(v(i,j,k)+v(i+1,j,k))
2426 wv(i,1) = v(i,1,k)*gridstruct%dy(i,1)
2429 vtmp(i,1) = 2.*(wv(i,1) + wv(i+1,1)) / (gridstruct%dy(i,1)+gridstruct%dy(i+1,1))
2430 utmp(i,1) = 2.*(u(i,1,k)*gridstruct%dx(i,1) + u(i,2,k)*gridstruct%dx(i,2)) &
2431 / ( gridstruct%dx(i,1) + gridstruct%dx(i,2))
2437 if ( (je+1)==npy )
then 2440 wv(i,j) = v(i,j,k)*gridstruct%dy(i,j)
2443 vtmp(i,j) = 2.*(wv(i,j) + wv(i+1,j)) / (gridstruct%dy(i,j)+gridstruct%dy(i+1,j))
2444 utmp(i,j) = 2.*(u(i,j,k)*gridstruct%dx(i,j) + u(i,j+1,k)*gridstruct%dx(i,j+1)) &
2445 / ( gridstruct%dx(i,j) + gridstruct%dx(i,j+1))
2454 wv(1,j) = v(1,j,k)*gridstruct%dy(1,j)
2455 wv(2,j) = v(2,j,k)*gridstruct%dy(2,j)
2458 wu(i,j) = u(i,j,k)*gridstruct%dx(i,j)
2461 utmp(i,j) = 2.*(wu(i,j) + wu(i,j+1))/(gridstruct%dx(i,j)+gridstruct%dx(i,j+1))
2462 vtmp(i,j) = 2.*(wv(1,j) + wv(2,j ))/(gridstruct%dy(1,j)+gridstruct%dy(2,j))
2468 if ( (ie+1)==npx)
then 2471 wv(i, j) = v(i, j,k)*gridstruct%dy(i, j)
2472 wv(i+1,j) = v(i+1,j,k)*gridstruct%dy(i+1,j)
2475 wu(i,j) = u(i,j,k)*gridstruct%dx(i,j)
2478 utmp(i,j) = 2.*(wu(i,j) + wu(i, j+1))/(gridstruct%dx(i,j)+gridstruct%dx(i,j+1))
2479 vtmp(i,j) = 2.*(wv(i,j) + wv(i+1,j ))/(gridstruct%dy(i,j)+gridstruct%dy(i+1,j))
2490 ua(i,j,k) = gridstruct%a11(i,j)*utmp(i,j) + gridstruct%a12(i,j)*vtmp(i,j)
2491 va(i,j,k) = gridstruct%a21(i,j)*utmp(i,j) + gridstruct%a22(i,j)*vtmp(i,j)
2498 ua(i,j,k) = a2*(u(i,j-1,k)+u(i,j+2,k)) + a1*(u(i,j,k)+u(i,j+1,k))
2499 va(i,j,k) = a2*(v(i-1,j,k)+v(i+2,j,k)) + a1*(v(i,j,k)+v(i+1,j,k))
2506 subroutine c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, do_halo)
2508 integer,
intent(in) :: km, grid_type
2509 real,
intent(in) :: u(bd%isd:bd%ied,bd%jsd:bd%jed+1,km)
2510 real,
intent(in) :: v(bd%isd:bd%ied+1,bd%jsd:bd%jed,km)
2512 logical,
intent(in) :: do_halo
2514 real,
intent(out):: ua(bd%isd:bd%ied, bd%jsd:bd%jed,km)
2515 real,
intent(out):: va(bd%isd:bd%ied, bd%jsd:bd%jed,km)
2518 real wu(bd%is-1:bd%ie+1, bd%js-1:bd%je+2)
2519 real wv(bd%is-1:bd%ie+2, bd%js-1:bd%je+1)
2520 real u1(bd%is-1:bd%ie+1), v1(bd%is-1:bd%ie+1)
2522 integer :: is, ie, js, je
2524 real,
dimension(:,:),
pointer :: a11, a12, a21, a22
2525 real,
dimension(:,:),
pointer :: dx, dy, rdxa, rdya
2527 a11 => gridstruct%a11
2528 a12 => gridstruct%a12
2529 a21 => gridstruct%a21
2530 a22 => gridstruct%a22
2534 rdxa => gridstruct%rdxa
2535 rdya => gridstruct%rdya
2552 if ( grid_type < 4 )
then 2555 wu(i,j) = u(i,j,k)*dx(i,j)
2560 wv(i,j) = v(i,j,k)*dy(i,j)
2567 u1(i) = 2.*(wu(i,j) + wu(i,j+1)) / (dx(i,j)+dx(i,j+1))
2568 v1(i) = 2.*(wv(i,j) + wv(i+1,j)) / (dy(i,j)+dy(i+1,j))
2572 ua(i,j,k) = a11(i,j)*u1(i) + a12(i,j)*v1(i)
2573 va(i,j,k) = a21(i,j)*u1(i) + a22(i,j)*v1(i)
2580 ua(i,j,k) = 0.5*(u(i,j,k)+u(i, j+1,k))
2581 va(i,j,k) = 0.5*(v(i,j,k)+v(i+1,j, k))
2590 subroutine expand_cell(q1, q2, q3, q4, a1, a2, a3, a4, fac)
2597 real(kind=R_GRID),
intent(in):: q1(2), q2(2), q3(2), q4(2)
2598 real(kind=R_GRID),
intent(in):: fac
2601 real(kind=R_GRID),
intent(out):: a1(2), a2(2), a3(2), a4(2)
2603 real(kind=R_GRID) qq1(3), qq2(3), qq3(3), qq4(3)
2604 real(kind=R_GRID) p1(3), p2(3), p3(3), p4(3)
2605 real(kind=R_GRID) ec(3)
2606 real(f_p):: dd, d1, d2, d3, d4
2617 ec(k) = p1(k) + p2(k) + p3(k) + p4(k)
2619 dd = sqrt( ec(1)**2 + ec(2)**2 + ec(3)**2 )
2627 qq1(k) = ec(k) + fac*(p1(k)-ec(k))
2628 qq2(k) = ec(k) + fac*(p2(k)-ec(k))
2629 qq3(k) = ec(k) + fac*(p3(k)-ec(k))
2630 qq4(k) = ec(k) + fac*(p4(k)-ec(k))
2636 d1 = sqrt( qq1(1)**2 + qq1(2)**2 + qq1(3)**2 )
2637 d2 = sqrt( qq2(1)**2 + qq2(2)**2 + qq2(3)**2 )
2638 d3 = sqrt( qq3(1)**2 + qq3(2)**2 + qq3(3)**2 )
2639 d4 = sqrt( qq4(1)**2 + qq4(2)**2 + qq4(3)**2 )
2641 qq1(k) = qq1(k) / d1
2642 qq2(k) = qq2(k) / d2
2643 qq3(k) = qq3(k) / d3
2644 qq4(k) = qq4(k) / d4
2660 real(kind=R_GRID) ,
intent(in ) :: q1(2), q2(2), q3(2), q4(2)
2661 real(kind=R_GRID) ,
intent(out) :: e2(2)
2663 real(kind=R_GRID) p1(3), p2(3), p3(3), p4(3)
2664 real(kind=R_GRID) ec(3)
2665 real(kind=R_GRID) dd
2674 ec(k) = p1(k) + p2(k) + p3(k) + p4(k)
2676 dd = sqrt( ec(1)**2 + ec(2)**2 + ec(3)**2 )
2688 real(kind=R_GRID) ,
intent(IN) :: p1(3), p2(3), p3(3), p4(3)
2689 real(kind=R_GRID) ,
intent(OUT) :: ec(3)
2695 ec(k) = p1(k) + p2(k) + p3(k) + p4(k)
2697 dd = sqrt( ec(1)**2 + ec(2)**2 + ec(3)**2 )
2707 real(kind=R_GRID) function get_area(p1, p4, p2, p3, radius)
2709 real(kind=R_GRID),
intent(in),
dimension(2):: p1, p2, p3, p4
2710 real(kind=R_GRID),
intent(in),
optional:: radius
2712 real(kind=R_GRID) e1(3), e2(3), e3(3)
2713 real(kind=R_GRID) ang1, ang2, ang3, ang4
2742 if (
present(radius) )
then 2743 get_area = (ang1 + ang2 + ang3 + ang4 - 2.*pi) * radius**2
2745 get_area = ang1 + ang2 + ang3 + ang4 - 2.*pi
2756 real(kind=R_GRID) :: dist2side
2757 real(kind=R_GRID),
dimension(3),
intent(in) :: v1, v2, point
2759 real(kind=R_GRID) :: angle, side
2763 dist2side = asin(sin(side)*sin(angle))
2771 real(kind=R_GRID) :: dist2side_latlon
2772 real(kind=R_GRID),
dimension(2),
intent(in) :: v1, v2, point
2774 real(kind=R_GRID),
dimension(3) :: c1, c2, cpoint
2776 real(kind=R_GRID) :: angle,side
2786 dist2side_latlon = asin(sin(side)*sin(angle))
2804 real(kind=R_GRID) p1(3), p2(3), p3(3)
2806 real (f_p):: e1(3), e2(3), e3(3)
2807 real (f_p):: px, py, pz
2808 real (f_p):: qx, qy, qz
2809 real (f_p):: angle, ddd
2822 px = e1(2)*e2(3) - e1(3)*e2(2)
2823 py = e1(3)*e2(1) - e1(1)*e2(3)
2824 pz = e1(1)*e2(2) - e1(2)*e2(1)
2826 qx = e1(2)*e3(3) - e1(3)*e3(2)
2827 qy = e1(3)*e3(1) - e1(1)*e3(3)
2828 qz = e1(1)*e3(2) - e1(2)*e3(1)
2830 ddd = (px*px+py*py+pz*pz)*(qx*qx+qy*qy+qz*qz)
2832 if ( ddd <= 0.0d0 )
then 2835 ddd = (px*qx+py*qy+pz*qz) / sqrt(ddd)
2836 if ( abs(ddd)>1.d0)
then 2837 angle = 2.d0*atan(1.0)
2839 if (ddd < 0.d0)
then 2840 angle = 4.d0*atan(1.0d0)
2854 real(kind=R_GRID) function cos_angle(p1, p2, p3)
2862 real(kind=R_GRID),
intent(in):: p1(3), p2(3), p3(3)
2864 real (f_p):: e1(3), e2(3), e3(3)
2865 real (f_p):: px, py, pz
2866 real (f_p):: qx, qy, qz
2867 real (f_p):: angle, ddd
2880 px = e1(2)*e2(3) - e1(3)*e2(2)
2881 py = e1(3)*e2(1) - e1(1)*e2(3)
2882 pz = e1(1)*e2(2) - e1(2)*e2(1)
2885 qx = e1(2)*e3(3) - e1(3)*e3(2)
2886 qy = e1(3)*e3(1) - e1(1)*e3(3)
2887 qz = e1(1)*e3(2) - e1(2)*e3(1)
2890 ddd = sqrt( (px**2+py**2+pz**2)*(qx**2+qy**2+qz**2) )
2891 if ( ddd > 0.d0 )
then 2892 angle = (px*qx+py*qy+pz*qz) / ddd
2901 real function g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
2902 integer,
intent(IN) :: ifirst, ilast
2903 integer,
intent(IN) :: jfirst, jlast, ngc
2904 integer,
intent(IN) :: mode
2905 logical,
intent(in),
optional :: reproduce
2906 real,
intent(IN) :: p(ifirst:ilast,jfirst:jlast)
2907 real(kind=R_GRID),
intent(IN) :: area(ifirst-ngc:ilast+ngc,jfirst-ngc:jlast+ngc)
2908 type(domain2d),
intent(IN) :: domain
2911 logical,
SAVE :: g_sum_initialized = .false.
2912 real(kind=R_GRID),
SAVE :: global_area
2913 real :: tmp(ifirst:ilast,jfirst:jlast)
2915 if ( .not. g_sum_initialized )
then 2916 global_area = mpp_global_sum(domain, area, flags=bitwise_efp_sum)
2917 if ( is_master() )
write(*,*)
'Global Area=',global_area
2918 g_sum_initialized = .true.
2924 if (
present(reproduce) )
then 2926 gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast), &
2927 flags=bitwise_efp_sum)
2929 gsum = mpp_global_sum(domain, p(:,:)*area(ifirst:ilast,jfirst:jlast))
2938 gsum = gsum + p(i,j)*area(i,j)
2941 call mp_reduce_sum(gsum)
2945 g_sum = gsum / global_area
2953 real function global_qsum(p, ifirst, ilast, jfirst, jlast)
2954 integer,
intent(IN) :: ifirst, ilast
2955 integer,
intent(IN) :: jfirst, jlast
2956 real,
intent(IN) :: p(ifirst:ilast,jfirst:jlast)
2963 gsum = gsum + p(i,j)
2966 call mp_reduce_sum(gsum)
2973 subroutine global_mx(q, n_g, qmin, qmax, bd)
2976 integer,
intent(in):: n_g
2977 real(kind=R_GRID),
intent(in)::q(bd%is-n_g:bd%ie+n_g, bd%js-n_g:bd%je+n_g)
2978 real(kind=R_GRID),
intent(out):: qmin, qmax
2981 integer :: is, ie, js, je
2992 qmin = min(qmin, q(i,j))
2993 qmax = max(qmax, q(i,j))
2996 call mp_reduce_min(qmin)
2997 call mp_reduce_max(qmax)
3002 subroutine global_mx_c(q, i1, i2, j1, j2, qmin, qmax)
3003 integer,
intent(in):: i1, i2, j1, j2
3004 real(kind=R_GRID),
intent(in) :: q(i1:i2,j1:j2)
3005 real(kind=R_GRID),
intent(out) :: qmin, qmax
3012 qmin = min(qmin, q(i,j))
3013 qmax = max(qmax, q(i,j))
3016 call mp_reduce_min(qmin)
3017 call mp_reduce_max(qmax)
3026 real(kind=4),
intent(inout):: q(bd%isd:bd%ied,bd%jsd:bd%jed)
3027 integer,
intent(in):: npx, npy
3028 real,
intent(in):: value
3031 integer :: is, ie, js, je
3032 integer :: isd, ied, jsd, jed
3045 if ( (i<1 .and. j<1) )
then 3048 if ( i>(npx-1) .and. j<1 )
then 3051 if ( i>(npx-1) .and. j>(npy-1) )
then 3054 if ( i<1 .and. j>(npy-1) )
then 3066 real(kind=R_GRID),
intent(inout):: q(bd%isd:bd%ied,bd%jsd:bd%jed)
3067 integer,
intent(in):: npx, npy
3068 real,
intent(in):: value
3071 integer :: is, ie, js, je
3072 integer :: isd, ied, jsd, jed
3085 if ( (i<1 .and. j<1) )
then 3088 if ( i>(npx-1) .and. j<1 )
then 3091 if ( i>(npx-1) .and. j>(npy-1) )
then 3094 if ( i<1 .and. j>(npy-1) )
then 3104 subroutine make_eta_level(km, pe, area, kks, ak, bk, ptop, domain, bd)
3106 integer,
intent(in ):: km
3107 integer,
intent(out):: kks
3108 real(kind=R_GRID),
intent(in):: area(bd%isd:bd%ied,bd%jsd:bd%jed)
3109 real,
intent(INOUT) :: ptop
3110 real,
intent(inout):: pe(bd%is-1:bd%ie+1,km+1,bd%js-1:bd%je+1)
3111 real,
intent(out):: ak(km+1), bk(km+1)
3112 type(domain2d),
intent(IN) :: domain
3115 real,
allocatable:: pem(:,:)
3118 integer :: is, ie, js, je
3125 allocate ( pem(is:ie,js:je) )
3131 pem(i,j) = pe(i,k,j)
3136 p4 =
g_sum(domain, pem, is, ie, js, je, ng, area, 1)
3155 bk(k) = (ph(k) - ph(1)) / (ph(km+1)-ph(1))
3156 ak(k) = ph(1)*(1.-bk(k))
3159 if ( is_master() )
then 3160 write(*,*)
'Make_eta_level ...., ptop=', ptop
3163 write(*,*) ph(k), ak(k), bk(k)
3173 integer,
intent (in) :: n
3175 real(kind=R_GRID),
intent (inout),
dimension (n,n):: a
3176 real(kind=R_GRID),
intent (out),
dimension (n,n):: x
3177 real(kind=R_GRID),
dimension (n,n) :: b
3190 call elgs (a,n,indx)
3195 b(indx(j),k) = b(indx(j),k) - a(indx(j),i)*b(indx(i),k)
3201 x(n,i) = b(indx(n),i)/a(indx(n),n)
3203 x(j,i) = b(indx(j),i)
3205 x(j,i) = x(j,i)-a(indx(j),k)*x(k,i)
3207 x(j,i) = x(j,i)/a(indx(j),j)
3216 subroutine elgs (a,n,indx)
3217 integer,
intent (in) :: n
3218 integer :: i,j,k,itmp
3219 integer,
intent (out),
dimension (n) :: indx
3220 real(kind=R_GRID),
intent (inout),
dimension (n,n) :: a
3222 real(kind=R_GRID) :: c1, pie, pi1, pj
3223 real(kind=R_GRID),
dimension (n) :: c
3234 c1 = max(c1,abs(a(i,j)))
3244 pie = abs(a(indx(i),j))/c(indx(i))
3257 pj = a(indx(i),j)/a(indx(j),j)
3266 a(indx(i),k) = a(indx(i),k)-pj*a(indx(j),k)
3274 real(kind=R_GRID),
intent(IN) :: pp(2)
3275 real(kind=R_GRID),
intent(OUT) :: elon(3), elat(3)
3277 elon(1) = -sin(pp(1))
3278 elon(2) = cos(pp(1))
3280 elat(1) = -sin(pp(2))*cos(pp(1))
3281 elat(2) = -sin(pp(2))*sin(pp(1))
3283 elat(3) = cos(pp(2))
3294 integer,
intent(in):: np
3295 real(kind=R_GRID),
intent(in):: e(3,np)
3296 real(kind=R_GRID),
intent(inout):: f(3,np)
3302 ap = f(1,i)*e(1,i) + f(2,i)*e(2,i) + f(3,i)*e(3,i)
3303 f(1,i) = f(1,i) - ap*e(1,i)
3304 f(2,i) = f(2,i) - ap*e(2,i)
3305 f(3,i) = f(3,i) - ap*e(3,i)
3311 subroutine init_mq(phis, gridstruct, npx, npy, is, ie, js, je, ng)
3312 integer,
intent(in):: npx, npy, is, ie, js, je, ng
3313 real,
intent(in):: phis(is-ng:ie+ng, js-ng:je+ng)
3317 real zs(is-ng:ie+ng, js-ng:je+ng)
3318 real zb(is-ng:ie+ng, js-ng:je+ng)
3319 real pdx(3,is:ie,js:je+1)
3320 real pdy(3,is:ie+1,js:je)
3323 real,
pointer :: rarea(:,:)
3324 real,
pointer,
dimension(:,:) :: dx, dy
3325 real,
pointer,
dimension(:,:,:) :: en1, en2, agrid, vlon, vlat
3327 rarea => gridstruct%rarea
3330 en1 => gridstruct%en1
3331 en2 => gridstruct%en2
3332 agrid => gridstruct%agrid
3333 vlon => gridstruct%vlon
3334 vlat => gridstruct%vlat
3340 zs(i,j) = phis(i,j) / grav
3346 call a2b_ord4(zs, zb, gridstruct, npx, npy, is, ie, js, je, ng)
3351 pdx(n,i,j) = 0.5*(zb(i,j)+zb(i+1,j))*dx(i,j)*en1(n,i,j)
3358 pdy(n,i,j) = 0.5*(zb(i,j)+zb(i,j+1))*dy(i,j)*en2(n,i,j)
3366 idiag%zxg(i,j) = vlon(i,j,1)*(pdx(1,i,j+1)-pdx(1,i,j)-pdy(1,i,j)+pdy(1,i+1,j)) &
3367 + vlon(i,j,2)*(pdx(2,i,j+1)-pdx(2,i,j)-pdy(2,i,j)+pdy(2,i+1,j)) &
3368 + vlon(i,j,3)*(pdx(3,i,j+1)-pdx(3,i,j)-pdy(3,i,j)+pdy(3,i+1,j))
3371 idiag%zxg(i,j) = idiag%zxg(i,j)*rarea(i,j) *
radius*cos(agrid(i,j,2))
subroutine, public mid_pt_cart(p1, p2, e3)
subroutine, public cart_to_latlon(np, q, xs, ys)
subroutine elgs(a, n, indx)
The subroutine 'elgs' performs the partial-pivoting gaussian elimination.
subroutine global_mx_c(q, i1, i2, j1, j2, qmin, qmax)
The subroutine 'global_mx_c' computes the global max and min at the cell corners. ...
subroutine, public mid_pt_sphere(p1, p2, pm)
real(kind=r_grid) function, public cos_angle(p1, p2, p3)
subroutine init_cubed_to_latlon(gridstruct, hydrostatic, agrid, grid_type, ord, bd)
subroutine get_unit_vect3(p1, p2, uc)
real function, public global_qsum(p, ifirst, ilast, jfirst, jlast)
The function 'global_qsum' computes the quick global sum without area weighting.
The module 'fv_mp_mod' is a single program multiple data (SPMD) parallel decompostion/communication m...
subroutine timing_off(blk_name)
The subroutine 'timing_off' stops a timer.
The type 'fv_grid_type' is made up of grid-dependent information from fv_grid_tools and fv_grid_utils...
real, parameter tiny_number
subroutine, public normalize_vect(e)
The subroutine 'normalize_vect' makes 'e' a unit vector.
subroutine init_mq(phis, gridstruct, npx, npy, is, ie, js, je, ng)
subroutine intersect_cross(a1, a2, b1, b2, radius, x_inter, local_a, local_b)
The subroutine 'intersect_cross' calculates the intersection of two great circles.
subroutine cell_center3(p1, p2, p3, p4, ec)
The subroutine 'cell_center3' gets the center position of a cell.
subroutine, public set_eta(km, ks, ptop, ak, bk)
This is the version of set_eta used in fvGFS and AM4.
subroutine, public intp_great_circle(beta, p1, p2, x_o, y_o)
subroutine invert_matrix(n, a, x)
subroutine, public direct_transform(c, i1, i2, j1, j2, lon_p, lat_p, n, lon, lat)
The subroutine 'direct_transform' performs a direct transformation of the standard (symmetrical) cubi...
subroutine latlon2xyz2(lon, lat, p3)
subroutine efactor_a2c_v(edge_vect_s, edge_vect_n, edge_vect_w, edge_vect_e, non_ortho, grid, agrid, npx, npy, nested, bd, regional)
The subroutine 'efactor_a2c_v' initializes interpolation factors at face edges for interpolating vect...
real(kind=r_grid) function, public dist2side_latlon(v1, v2, point)
The function 'dist2side_latlon' is the version of 'dist2side' that takes points in latitude-longitude...
real(kind=r_grid) function, public spherical_angle(p1, p2, p3)
real function, public g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
The function 'g_sum' is the fast version of 'globalsum'.
real function, public inner_prod(v1, v2)
subroutine, public spherical_linear_interpolation(beta, p1, p2, pb)
The subroutine 'spherical_linear_interpolation' interpolates along the great circle connecting points...
subroutine, public get_latlon_vector(pp, elon, elat)
subroutine, public get_unit_vect2(e1, e2, uc)
subroutine gnomonic_angl(im, lamda, theta)
integer, parameter, public r_grid
subroutine, public make_eta_level(km, pe, area, kks, ak, bk, ptop, domain, bd)
subroutine c2l_ord4(u, v, ua, va, gridstruct, npx, npy, km, grid_type, domain, nested, mode, bd)
The module 'fv_timing' contains FV3 timers.
subroutine, public unit_vect_latlon(pp, elon, elat)
subroutine mirror_latlon(lon1, lat1, lon2, lat2, lon0, lat0, lon3, lat3)
The subroutine 'mirror_latlon' computes the mirror image of (lon0, lat0) as (lon3, lat3) given the "mirror" as defined by (lon1, lat1), (lon2, lat2), and center of the sphere.
subroutine, public global_mx(q, n_g, qmin, qmax, bd)
real, parameter, public ptop_min
integer, parameter, public f_p
subroutine gnomonic_ed(im, lamda, theta)
The subroutine 'gnomonic_ed' computes the equal distances along the 4 edges of the cubed sphere...
logical, public symm_grid
subroutine symm_ed(im, lamda, theta)
The module 'fv_arrays' contains the 'fv_atmos_type' and associated datatypes.
real, parameter, public big_number
real function, public great_circle_dist(q1, q2, radius)
real(kind=r_grid) function, public get_area(p1, p4, p2, p3, radius)
subroutine gnomonic_ed_limited(im, in, nghost, lL, lR, uL, uR, lamda, theta)
The subroutine 'gnomonic_ed_limited' creates a limited-area equidistant gnomonic grid with corners gi...
subroutine, public cell_center2(q1, q2, q3, q4, e2)
The module 'fv_eta' contains routine to set up the reference (Eulerian) pressure coordinate.
real(kind=r_grid) function, public v_prod(v1, v2)
subroutine, public grid_utils_init(Atm, npx, npy, npz, non_ortho, grid_type, c2l_order)
subroutine, public vect_cross(e, p1, p2)
The subroutine 'vect_cross performs cross products of 3D vectors: e = P1 X P2.
subroutine timing_on(blk_name)
The subroutine 'timing_on' starts a timer.
subroutine, public project_sphere_v(np, f, e)
integer, parameter, public ng
subroutine, public c2l_ord2(u, v, ua, va, gridstruct, km, grid_type, bd, do_halo)
subroutine intersect(a1, a2, b1, b2, radius, x_inter, local_a, local_b)
The subroutine 'intersect' calculates the intersection of two great circles.
The module 'fv_grid_utils' contains routines for setting up and computing grid-related quantities...
real(kind=r_grid) function dist2side(v1, v2, point)
The function 'dist2side' calculates the shortest normalized distance on a sphere from point to straig...
subroutine check_local(x1, x2, local)
subroutine fill_ghost_r4(q, npx, npy, value, bd)
subroutine edge_factors(edge_s, edge_n, edge_w, edge_e, non_ortho, grid, agrid, npx, npy, bd)
The subroutine 'edge_factors' initializes interpolation factors at face edges for interpolation from ...
subroutine gnomonic_dist(im, lamda, theta)
subroutine mirror_xyz(p1, p2, p0, p)
The subroutine 'mirror_xyz' computes the mirror image of p0(x0, y0, z0) as p(x, y, z) given the "mirror" as defined by p1(x1, y1, z1), p2(x2, y2, z2), and the center of the sphere.
subroutine fill_ghost_r8(q, npx, npy, value, bd)
subroutine get_center_vect(npx, npy, pp, u1, u2, bd)
subroutine, public grid_utils_end
subroutine, public expand_cell(q1, q2, q3, q4, a1, a2, a3, a4, fac)
subroutine, public cubed_to_latlon(u, v, ua, va, gridstruct, npx, npy, km, mode, grid_type, domain, nested, c2l_ord, bd)
subroutine, public gnomonic_grids(grid_type, im, lon, lat)
real(kind=r_grid) function great_circle_dist_cart(v1, v2, radius)
The function 'great_circle_dist_cart' calculates the normalized great circle distance between 'v1' an...
subroutine mid_pt3_cart(p1, p2, e)
subroutine, public latlon2xyz(p, e, id)
The subroutine 'latlon2xyz' maps (lon, lat) to (x,y,z)