23 open_namelist_file, close_file, stdlog, &
32 use fv_mp_nlm_mod,
only: mp_stop, mp_reduce_min, mp_reduce_max, is_master
70 character(len=128)::
surf_file =
"INPUT/topo1min.nc" 89 subroutine surfdrv(npx, npy, grid, agrid, area, dx, dy, dxa, dya, dxc, dyc, sin_sg, phis, &
90 stretch_fac, nested, npx_global, domain,grid_number, bd)
94 integer,
intent(in):: npx, npy
98 real(kind=R_GRID),
intent(in)::area(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng)
99 real,
intent(in):: dx(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng+1)
100 real,
intent(in):: dy(bd%is-ng:bd%ie+ng+1, bd%js-ng:bd%je+ng)
101 real,
intent(in),
dimension(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng)::dxa, dya
102 real,
intent(in)::dxc(bd%is-ng:bd%ie+ng+1, bd%js-ng:bd%je+ng)
103 real,
intent(in)::dyc(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng+1)
105 real(kind=R_GRID),
intent(in):: grid(bd%is-ng:bd%ie+ng+1, bd%js-ng:bd%je+ng+1,2)
106 real(kind=R_GRID),
intent(in):: agrid(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng,2)
107 real,
intent(IN):: sin_sg(bd%isd:bd%ied,bd%jsd:bd%jed,9)
108 real(kind=R_GRID),
intent(IN):: stretch_fac
109 logical,
intent(IN) :: nested
110 integer,
intent(IN) :: npx_global
111 type(
domain2d),
intent(INOUT) :: domain
112 integer,
intent(IN) :: grid_number
115 real,
intent(out):: phis(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng)
117 real,
allocatable :: z2(:,:)
121 character(len=80) :: topoflnm
122 real(kind=4),
allocatable :: ft(:,:), zs(:,:)
123 real,
allocatable :: lon1(:), lat1(:)
124 real dx1, dx2, dy1, dy2, lats, latn, r2d
125 real(kind=R_GRID) da_max
126 real zmean, z2mean, delg, rgrav
128 integer i, j, n, mdim
130 integer ncid, lonid, latid, ftopoid, htopoid
131 integer jstart, jend, start(4), nread(4)
134 integer :: is, ie, js, je
135 integer :: isd, ied, jsd, jed
136 real phis_coarse(bd%isd:bd%ied, bd%jsd:bd%jed)
152 phis(i,j) = phis(i,j)*rgrav
158 phis_coarse(i,j) = phis(i,j)
171 if (grid_number > 1)
write(
grid_string,
'(A, I1)')
' g', grid_number
180 status = nf_open(
surf_file, nf_nowrite, ncid)
181 if (status .ne. nf_noerr)
call handle_err(status)
183 status = nf_inq_dimid(ncid,
'lon', lonid)
184 if (status .ne. nf_noerr)
call handle_err(status)
185 status = nf_inq_dimlen(ncid, lonid, londim)
186 if (status .ne. nf_noerr)
call handle_err(status)
189 status = nf_inq_dimid(ncid,
'lat', latid)
190 if (status .ne. nf_noerr)
call handle_err(status)
191 status = nf_inq_dimlen(ncid, latid, latdim)
192 if (status .ne. nf_noerr)
call handle_err(status)
195 if ( is_master() )
then 196 if (
nlon==43200 )
then 204 call error_mesg (
'surfdrv',
'Raw IEEE data format no longer supported !!!', fatal )
210 allocate ( lat1(
nlat+1) )
211 allocate ( lon1(
nlon+1) )
221 lon1(i) = dx1 *
real(i-1) 227 lat1(j) = -0.5*
pi + dy1*(j-1)
242 lats =
min( lats, grid(i,j,2), grid(i+1,j,2), grid(i,j+1,2), grid(i+1,j+1,2), agrid(i,j,2) )
243 latn =
max( latn, grid(i,j,2), grid(i+1,j,2), grid(i,j+1,2), grid(i+1,j+1,2), agrid(i,j,2) )
254 if (
min(je-js+1,ie-is+1) < 15)
then 255 delg =
max( 0.4*(latn-lats),
pi/
real(npx_global-1), 2.*
pi/
real(nlat) )
257 delg =
max( 0.2*(latn-lats),
pi/
real(npx_global-1), 2.*
pi/
real(nlat) )
259 lats =
max( -0.5*
pi, lats - delg )
260 latn =
min( 0.5*
pi, latn + delg )
264 if ( lats < lat1(j) )
then 269 jstart =
max(jstart-1, 1)
273 if ( latn < lat1(j+1) )
then 280 jt = jend - jstart + 1
281 igh =
nlon/8 +
nlon/(2*(npx_global-1))
283 if (is_master())
write(*,*)
'Terrain dataset =',
nlon,
'jt=', jt
284 if (is_master())
write(*,*)
'igh (terrain ghosting)=', igh
286 status = nf_inq_varid(ncid,
'ftopo', ftopoid)
287 if (status .ne. nf_noerr)
call handle_err(status)
290 start(2) = jstart; nread(2) = jend - jstart + 1
292 allocate ( ft(-igh:
nlon+igh,jt) )
293 status = nf_get_vara_real(ncid, ftopoid, start, nread, ft(1:
nlon,1:jt))
294 if (status .ne. nf_noerr)
call handle_err(status)
298 ft(i,j) = ft(i+
nlon,j)
301 ft(i,j) = ft(i-
nlon,j)
305 status = nf_inq_varid(ncid,
'htopo', htopoid)
306 if (status .ne. nf_noerr)
call handle_err(status)
307 allocate ( zs(-igh:
nlon+igh,jt) )
308 status = nf_get_vara_real(ncid, htopoid, start, nread, zs(1:
nlon,1:jt))
309 if (status .ne. nf_noerr)
call handle_err(status)
310 status = nf_close(ncid)
311 if (status .ne. nf_noerr)
call handle_err(status)
315 zs(i,j) = zs(i+
nlon,j)
318 zs(i,j) = zs(i-
nlon,j)
330 allocate (
oro_g(isd:ied, jsd:jed) )
331 allocate (
sgh_g(isd:ied, jsd:jed) )
334 phis,
oro_g,
sgh_g, npx, npy, jstart, jend, stretch_fac, nested, npx_global, bd)
335 if (is_master())
write(*,*)
'map_to_cubed_raw: master PE done' 343 allocate (
zs_g(is:ie, js:je) )
344 allocate ( z2(is:ie,js:je) )
347 zs_g(i,j) = phis(i,j)
348 z2(i,j) = phis(i,j)**2
355 zmean =
g_sum(domain,
zs_g(is:ie,js:je), is, ie, js, je, ng, area, 1)
356 z2mean =
g_sum(domain, z2(is:ie,js:je) , is, ie, js, je, ng, area, 1)
357 if ( is_master() )
then 358 write(*,*)
'Before filter ZS', trim(
grid_string),
' min=',
da_min,
' Max=', da_max,
' Mean=',zmean
359 write(*,*)
'*** Mean variance', trim(
grid_string),
' *** =', z2mean
373 if (is_master())
write(*,*)
'Blending nested and coarse grid topography' 376 wt =
max(0.,
min(1.,
real(5 -
min(i,j,npx-i,npy-j,5))/5. ))
377 phis(i,j) = (1.-wt)*phis(i,j) + wt*phis_coarse(i,j)
384 if ( is_master() )
write(*,*)
'ORO', trim(
grid_string),
' min=',
da_min,
' Max=', da_max
391 write(*,*)
'Applying terrain filters. zero_ocean is',
zero_ocean 393 call fv3_zs_filter (bd, isd, ied, jsd, jed, npx, npy, npx_global, &
394 stretch_fac, nested, domain, area, dxa, dya, dx, dy, dxc, dyc, grid, &
395 agrid, sin_sg, phis,
oro_g)
402 z2(i,j) = phis(i,j)**2
407 zmean =
g_sum(domain, phis(is:ie,js:je), is, ie, js, je, ng, area, 1)
408 z2mean =
g_sum(domain, z2, is, ie, js, je, ng, area, 1)
411 if ( is_master() )
then 412 write(*,*)
'After filter Phis', trim(
grid_string),
' min=',
da_min,
' Max=', da_max,
'Mean=', zmean
413 write(*,*)
'*** Mean variance', trim(
grid_string),
' *** =', z2mean
437 phis(i,j) =
grav * phis(i,j)
438 if (
sgh_g(i,j) <= 0. )
then 447 if ( is_master() )
write(*,*)
'Before filter SGH', trim(
grid_string),
' min=',
da_min,
' Max=', da_max
455 if(
zs_filter)
call del4_cubed_sphere(npx, npy,
sgh_g, area, dx, dy, dxc, dyc, sin_sg, 1,
zero_ocean,
oro_g, nested, domain, bd)
458 if ( is_master() )
write(*,*)
'After filter SGH', trim(
grid_string),
' min=',
da_min,
' Max=', da_max
467 subroutine fv3_zs_filter (bd, isd, ied, jsd, jed, npx, npy, npx_global, &
468 stretch_fac, nested, domain, area, dxa, dya, dx, dy, dxc, dyc, grid, &
469 agrid, sin_sg, phis, oro )
470 integer,
intent(in):: isd, ied, jsd, jed, npx, npy, npx_global
472 real(kind=R_GRID),
intent(in),
dimension(isd:ied,jsd:jed)::area
473 real,
intent(in),
dimension(isd:ied,jsd:jed)::dxa, dya
474 real,
intent(in),
dimension(isd:ied, jsd:jed+1):: dx, dyc
475 real,
intent(in),
dimension(isd:ied+1,jsd:jed):: dy, dxc
477 real(kind=R_GRID),
intent(in):: grid(isd:ied+1, jsd:jed+1,2)
478 real(kind=R_GRID),
intent(in):: agrid(isd:ied, jsd:jed, 2)
479 real,
intent(IN):: sin_sg(9,isd:ied,jsd:jed)
480 real(kind=R_GRID),
intent(IN):: stretch_fac
481 logical,
intent(IN) :: nested
482 real,
intent(inout):: phis(isd:ied,jsd,jed)
483 real,
intent(inout):: oro(isd:ied,jsd,jed)
484 type(
domain2d),
intent(INOUT) :: domain
486 real(kind=R_GRID) da_max
488 if (is_master()) print*,
' Calling FV3_zs_filter...' 493 mdim = nint(
real(npx_global) *
min(10., stretch_fac) )
498 if ( npx_global<=97)
then 500 elseif ( npx_global<=193 )
then 509 call two_delta_filter(npx, npy, phis, area, dx, dy, dxa, dya, dxc, dyc, sin_sg,
cd2,
zero_ocean, &
514 if ( mdim<=193 )
then 516 elseif ( mdim<=1537 )
then 522 call del4_cubed_sphere(npx, npy, phis, area, dx, dy, dxc, dyc, sin_sg,
n_del4,
zero_ocean, oro, nested, domain, bd)
525 call two_delta_filter(npx, npy, phis, area, dx, dy, dxa, dya, dxc, dyc, sin_sg,
cd2,
zero_ocean, &
532 subroutine two_delta_filter(npx, npy, q, area, dx, dy, dxa, dya, dxc, dyc, sin_sg, cd, zero_ocean, &
533 check_slope, filter_type, oro, nested, domain, bd, ntmax)
534 type(fv_grid_bounds_type),
intent(IN) :: bd
535 integer,
intent(in):: npx, npy
536 integer,
intent(in):: ntmax
537 integer,
intent(in):: filter_type
538 real,
intent(in):: cd
540 real(kind=R_GRID),
intent(in)::area(bd%isd:bd%ied, bd%jsd:bd%jed)
541 real,
intent(in):: dx(bd%isd:bd%ied, bd%jsd:bd%jed+1)
542 real,
intent(in):: dy(bd%isd:bd%ied+1,bd%jsd:bd%jed)
543 real,
intent(in):: dxa(bd%isd:bd%ied, bd%jsd:bd%jed)
544 real,
intent(in):: dya(bd%isd:bd%ied, bd%jsd:bd%jed)
545 real,
intent(in):: dxc(bd%isd:bd%ied+1,bd%jsd:bd%jed)
546 real,
intent(in):: dyc(bd%isd:bd%ied, bd%jsd:bd%jed+1)
547 real,
intent(in):: sin_sg(9,bd%isd:bd%ied,bd%jsd:bd%jed)
548 real,
intent(in):: oro(bd%isd:bd%ied, bd%jsd:bd%jed)
549 logical,
intent(in):: zero_ocean, check_slope
550 logical,
intent(in):: nested
551 type(domain2d),
intent(inout) :: domain
553 real,
intent(inout):: q(bd%isd:bd%ied, bd%jsd:bd%jed)
555 real,
parameter:: p1 = 7./12.
556 real,
parameter:: p2 = -1./12.
557 real,
parameter:: c1 = -2./14.
558 real,
parameter:: c2 = 11./14.
559 real,
parameter:: c3 = 5./14.
560 real:: ddx(bd%is:bd%ie+1,bd%js:bd%je), ddy(bd%is:bd%ie,bd%js:bd%je+1)
561 logical:: extm(bd%is-1:bd%ie+1)
562 logical:: ext2(bd%is:bd%ie,bd%js-1:bd%je+1)
563 real:: a1(bd%is-1:bd%ie+2)
564 real:: a2(bd%is:bd%ie,bd%js-1:bd%je+2)
565 real(kind=R_GRID):: a3(bd%is:bd%ie,bd%js:bd%je)
566 real(kind=R_GRID):: smax, smin
569 integer:: is, ie, js, je
570 integer:: isd, ied, jsd, jed
571 integer:: is1, ie2, js1, je2
583 is1 = is-1; ie2 = ie+2
584 js1 = js-1; je2 = je+2
586 is1 =
max(3,is-1); ie2 =
min(npx-2,ie+2)
587 js1 =
max(3,js-1); je2 =
min(npy-2,je+2)
590 if ( check_slope )
then 601 if ( nt==1 .and. check_slope )
then 604 ddx(i,j) = (q(i,j) - q(i-1,j))/dxc(i,j)
605 ddx(i,j) = abs(ddx(i,j))
610 ddy(i,j) = (q(i,j) - q(i,j-1))/dyc(i,j)
611 ddy(i,j) = abs(ddy(i,j))
616 a3(i,j) =
max( ddx(i,j), ddx(i+1,j), ddy(i,j), ddy(i,j+1) )
620 if ( is_master() )
write(*,*)
'Before filter: Max_slope=', smax
624 if ( .not. nested .and. nt==1 )
then 625 if ( is==1 .and. js==1 )
then 626 q(1,1) = (q(1,1)*area(1,1)+q(0,1)*area(0,1)+q(1,0)*area(1,0)) &
627 / ( area(1,1)+ area(0,1)+ area(1,0) )
631 if ( (ie+1)==npx .and. js==1 )
then 632 q(ie, 1) = (q(ie,1)*area(ie,1)+q(npx,1)*area(npx,1)+q(ie,0)*area(ie,0)) &
633 / ( area(ie,1)+ area(npx,1)+ area(ie,0))
637 if ( is==1 .and. (je+1)==npy )
then 638 q(1, je) = (q(1,je)*area(1,je)+q(0,je)*area(0,je)+q(1,npy)*area(1,npy)) &
639 / ( area(1,je)+ area(0,je)+ area(1,npy))
643 if ( (ie+1)==npx .and. (je+1)==npy )
then 644 q(ie, je) = (q(ie,je)*area(ie,je)+q(npx,je)*area(npx,je)+q(ie,npy)*area(ie,npy)) &
645 / ( area(ie,je)+ area(npx,je)+ area(ie,npy))
656 a1(i) = p1*(q(i-1,j)+q(i,j)) + p2*(q(i-2,j)+q(i+1,j))
659 if ( .not. nested )
then 661 a1(0) = c1*q(-2,j) + c2*q(-1,j) + c3*q(0,j)
662 a1(1) = 0.5*(((2.*dxa(0,j)+dxa(-1,j))*q(0,j)-dxa(0,j)*q(-1,j))/(dxa(-1,j)+dxa(0,j)) &
663 + ((2.*dxa(1,j)+dxa( 2,j))*q(1,j)-dxa(1,j)*q( 2,j))/(dxa(1, j)+dxa(2,j)))
664 a1(2) = c3*q(1,j) + c2*q(2,j) +c1*q(3,j)
666 if ( (ie+1)==npx )
then 667 a1(npx-1) = c1*q(npx-3,j) + c2*q(npx-2,j) + c3*q(npx-1,j)
668 a1(npx) = 0.5*(((2.*dxa(npx-1,j)+dxa(npx-2,j))*q(npx-1,j)-dxa(npx-1,j)*q(npx-2,j))/(dxa(npx-2,j)+dxa(npx-1,j)) &
669 + ((2.*dxa(npx, j)+dxa(npx+1,j))*q(npx, j)-dxa(npx, j)*q(npx+1,j))/(dxa(npx, j)+dxa(npx+1,j)))
670 a1(npx+1) = c3*q(npx,j) + c2*q(npx+1,j) + c1*q(npx+2,j)
674 if ( filter_type == 0 )
then 676 if( abs(3.*(a1(i)+a1(i+1)-2.*q(i,j))) > abs(a1(i)-a1(i+1)) )
then 684 if ( (a1(i)-q(i,j))*(a1(i+1)-q(i,j)) > 0. )
then 693 ddx(i,j) = (q(i-1,j)-q(i,j))/dxc(i,j)
694 if ( extm(i-1).and.extm(i) )
then 695 ddx(i,j) = 0.5*(sin_sg(3,i-1,j)+sin_sg(1,i,j))*dy(i,j)*ddx(i,j)
696 elseif ( abs(ddx(i,j)) > m_slope )
then 697 fac =
min(1.,
max(0.1,(abs(ddx(i,j))-m_slope)/m_slope ) )
698 ddx(i,j) = fac*0.5*(sin_sg(3,i-1,j)+sin_sg(1,i,j))*dy(i,j)*ddx(i,j)
708 a2(i,j) = p1*(q(i,j-1)+q(i,j)) + p2*(q(i,j-2)+q(i,j+1))
711 if ( .not. nested )
then 714 a2(i,0) = c1*q(i,-2) + c2*q(i,-1) + c3*q(i,0)
715 a2(i,1) = 0.5*(((2.*dya(i,0)+dya(i,-1))*q(i,0)-dya(i,0)*q(i,-1))/(dya(i,-1)+dya(i,0)) &
716 + ((2.*dya(i,1)+dya(i, 2))*q(i,1)-dya(i,1)*q(i, 2))/(dya(i, 1)+dya(i,2)))
717 a2(i,2) = c3*q(i,1) + c2*q(i,2) + c1*q(i,3)
720 if( (je+1)==npy )
then 722 a2(i,npy-1) = c1*q(i,npy-3) + c2*q(i,npy-2) + c3*q(i,npy-1)
723 a2(i,npy) = 0.5*(((2.*dya(i,npy-1)+dya(i,npy-2))*q(i,npy-1)-dya(i,npy-1)*q(i,npy-2))/(dya(i,npy-2)+dya(i,npy-1)) &
724 + ((2.*dya(i,npy)+dya(i,npy+1))*q(i,npy)-dya(i,npy)*q(i,npy+1))/(dya(i,npy)+dya(i,npy+1)))
725 a2(i,npy+1) = c3*q(i,npy) + c2*q(i,npy+1) + c1*q(i,npy+2)
730 if ( filter_type == 0 )
then 733 if( abs(3.*(a2(i,j)+a2(i,j+1)-2.*q(i,j))) > abs(a2(i,j)-a2(i,j+1)) )
then 743 if ( (a2(i,j)-q(i,j))*(a2(i,j+1)-q(i,j)) > 0. )
then 754 ddy(i,j) = (q(i,j-1)-q(i,j))/dyc(i,j)
755 if ( ext2(i,j-1) .and. ext2(i,j) )
then 756 ddy(i,j) = 0.5*(sin_sg(4,i,j-1)+sin_sg(2,i,j))*dx(i,j)*ddy(i,j)
757 elseif ( abs(ddy(i,j))>m_slope )
then 758 fac =
min(1.,
max(0.1,(abs(ddy(i,j))-m_slope)/m_slope))
759 ddy(i,j) = fac*0.5*(sin_sg(4,i,j-1)+sin_sg(2,i,j))*dx(i,j)*ddy(i,j)
766 if ( zero_ocean )
then 770 ddx(i,j) =
max(0.,
min(oro(i-1,j), oro(i,j))) * ddx(i,j)
775 ddy(i,j) =
max(0.,
min(oro(i,j-1), oro(i,j))) * ddy(i,j)
782 q(i,j) = q(i,j) + cd/area(i,j)*(ddx(i,j)-ddx(i+1,j)+ddy(i,j)-ddy(i,j+1))
788 if ( check_slope )
then 792 ddx(i,j) = (q(i,j) - q(i-1,j))/dxc(i,j)
793 ddx(i,j) = abs(ddx(i,j))
798 ddy(i,j) = (q(i,j) - q(i,j-1))/dyc(i,j)
799 ddy(i,j) = abs(ddy(i,j))
804 a3(i,j) =
max( ddx(i,j), ddx(i+1,j), ddy(i,j), ddy(i,j+1) )
808 if ( is_master() )
write(*,*)
'After filter: Max_slope=', smax
815 subroutine del2_cubed_sphere(npx, npy, q, area, dx, dy, dxc, dyc, sin_sg, nmax, cd, zero_ocean, oro, nested, domain, bd)
817 integer,
intent(in):: npx, npy
818 integer,
intent(in):: nmax
819 real(kind=R_GRID),
intent(in):: cd
822 real(kind=R_GRID),
intent(in)::area(bd%isd:bd%ied, bd%jsd:bd%jed)
823 real,
intent(in):: dx(bd%isd:bd%ied, bd%jsd:bd%jed+1)
824 real,
intent(in):: dy(bd%isd:bd%ied+1,bd%jsd:bd%jed)
825 real,
intent(in):: dxc(bd%isd:bd%ied+1,bd%jsd:bd%jed)
826 real,
intent(in):: dyc(bd%isd:bd%ied, bd%jsd:bd%jed+1)
827 real,
intent(IN):: sin_sg(bd%isd:bd%ied,bd%jsd:bd%jed,9)
828 real,
intent(in):: oro(bd%isd:bd%ied, bd%jsd:bd%jed)
829 logical,
intent(IN) :: nested
830 type(
domain2d),
intent(INOUT) :: domain
832 real,
intent(inout):: q(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng)
834 real ddx(bd%is:bd%ie+1,bd%js:bd%je), ddy(bd%is:bd%ie,bd%js:bd%je+1)
837 integer :: is, ie, js, je
838 integer :: isd, ied, jsd, jed
853 if ( is==1 .and. js==1 .and. .not. nested)
then 854 q(1,1) = (q(1,1)*area(1,1)+q(0,1)*area(0,1)+q(1,0)*area(1,0)) &
855 / ( area(1,1)+ area(0,1)+ area(1,0) )
859 if ( (ie+1)==npx .and. js==1 .and. .not. nested)
then 860 q(ie, 1) = (q(ie,1)*area(ie,1)+q(npx,1)*area(npx,1)+q(ie,0)*area(ie,0)) &
861 / ( area(ie,1)+ area(npx,1)+ area(ie,0))
865 if ( (ie+1)==npx .and. (je+1)==npy .and. .not. nested )
then 866 q(ie, je) = (q(ie,je)*area(ie,je)+q(npx,je)*area(npx,je)+q(ie,npy)*area(ie,npy)) &
867 / ( area(ie,je)+ area(npx,je)+ area(ie,npy))
871 if ( is==1 .and. (je+1)==npy .and. .not. nested)
then 872 q(1, je) = (q(1,je)*area(1,je)+q(0,je)*area(0,je)+q(1,npy)*area(1,npy)) &
873 / ( area(1,je)+ area(0,je)+ area(1,npy))
883 ddx(i,j) = 0.5*(sin_sg(i-1,j,3)+sin_sg(i,j,1))*dy(i,j)*(q(i-1,j)-q(i,j))/dxc(i,j)
888 ddy(i,j) = dx(i,j)*(q(i,j-1)-q(i,j))/dyc(i,j) &
889 *0.5*(sin_sg(i,j-1,4)+sin_sg(i,j,2))
897 ddx(i,j) =
max(0.,
min(oro(i-1,j), oro(i,j))) * ddx(i,j)
902 ddy(i,j) =
max(0.,
min(oro(i,j-1), oro(i,j))) * ddy(i,j)
909 q(i,j) = q(i,j) + cd/area(i,j)*(ddx(i,j)-ddx(i+1,j)+ddy(i,j)-ddy(i,j+1))
917 subroutine del4_cubed_sphere(npx, npy, q, area, dx, dy, dxc, dyc, sin_sg, nmax, zero_ocean, oro, nested, domain, bd)
919 integer,
intent(in):: npx, npy, nmax
921 real,
intent(in):: oro(bd%isd:bd%ied, bd%jsd:bd%jed)
922 real(kind=R_GRID),
intent(in)::area(bd%isd:bd%ied, bd%jsd:bd%jed)
923 real,
intent(in):: dx(bd%isd:bd%ied, bd%jsd:bd%jed+1)
924 real,
intent(in):: dy(bd%isd:bd%ied+1,bd%jsd:bd%jed)
925 real,
intent(in):: dxc(bd%isd:bd%ied+1,bd%jsd:bd%jed)
926 real,
intent(in):: dyc(bd%isd:bd%ied, bd%jsd:bd%jed+1)
927 real,
intent(IN):: sin_sg(bd%isd:bd%ied,bd%jsd:bd%jed,9)
928 real,
intent(inout):: q(bd%is-ng:bd%ie+ng, bd%js-ng:bd%je+ng)
929 logical,
intent(IN) :: nested
930 type(
domain2d),
intent(INOUT) :: domain
932 real :: diff(bd%is-3:bd%ie+2,bd%js-3:bd%je+2)
934 real :: fx1(bd%is:bd%ie+1,bd%js:bd%je), fy1(bd%is:bd%ie,bd%js:bd%je+1)
935 real :: fx2(bd%is:bd%ie+1,bd%js:bd%je), fy2(bd%is:bd%ie,bd%js:bd%je+1)
936 real :: fx4(bd%is:bd%ie+1,bd%js:bd%je), fy4(bd%is:bd%ie,bd%js:bd%je+1)
937 real,
dimension(bd%isd:bd%ied,bd%jsd:bd%jed):: d2, win, wou
938 real,
dimension(bd%is:bd%ie,bd%js:bd%je):: qlow, qmin, qmax, q0
939 real,
parameter:: esl = 1.e-20
942 integer :: is, ie, js, je
943 integer :: isd, ied, jsd, jed
961 diff(i,j) =
cd4*area(i,j)
975 if ( is==1 .and. js==1 .and. .not. nested)
then 976 q(1,1) = (q(1,1)*area(1,1)+q(0,1)*area(0,1)+q(1,0)*area(1,0)) &
977 / ( area(1,1)+ area(0,1)+ area(1,0) )
982 if ( (ie+1)==npx .and. js==1 .and. .not. nested)
then 983 q(ie, 1) = (q(ie,1)*area(ie,1)+q(npx,1)*area(npx,1)+q(ie,0)*area(ie,0)) &
984 / ( area(ie,1)+ area(npx,1)+ area(ie,0))
989 if ( (ie+1)==npx .and. (je+1)==npy .and. .not. nested)
then 990 q(ie, je) = (q(ie,je)*area(ie,je)+q(npx,je)*area(npx,je)+q(ie,npy)*area(ie,npy)) &
991 / ( area(ie,je)+ area(npx,je)+ area(ie,npy))
992 q(npx, je) = q(ie,je)
993 q(ie, npy) = q(ie,je)
994 q(npx,npy) = q(ie,je)
996 if ( is==1 .and. (je+1)==npy .and. .not. nested)
then 997 q(1, je) = (q(1,je)*area(1,je)+q(0,je)*area(0,je)+q(1,npy)*area(1,npy)) &
998 / ( area(1,je)+ area(0,je)+ area(1,npy))
1006 qmin(i,j) =
min(q0(i,j), q(i-1,j-1), q(i,j-1), q(i+1,j-1), &
1007 q(i-1,j ), q(i,j ), q(i+1,j ), &
1008 q(i-1,j+1), q(i,j+1), q(i+1,j+1) )
1009 qmax(i,j) =
max(
peak_fac*q0(i,j), q(i-1,j-1), q(i,j-1), q(i+1,j-1), &
1010 q(i-1,j ), q(i,j ), q(i+1,j ), &
1011 q(i-1,j+1), q(i,j+1), q(i+1,j+1) )
1021 fx2(i,j) = 0.25*(diff(i-1,j)+diff(i,j))*dy(i,j)*(q(i-1,j)-q(i,j))/dxc(i,j) &
1022 *(sin_sg(i,j,1)+sin_sg(i-1,j,3))
1029 fy2(i,j) = 0.25*(diff(i,j-1)+diff(i,j))*dx(i,j)*(q(i,j-1)-q(i,j))/dyc(i,j) &
1030 *(sin_sg(i,j,2)+sin_sg(i,j-1,4))
1036 d2(i,j) = (fx2(i,j)-fx2(i+1,j)+fy2(i,j)-fy2(i,j+1)) / area(i,j)
1045 fx1(i,j) =
max(0.,
min(oro(i-1,j), oro(i,j))) * fx2(i,j)
1050 fy1(i,j) =
max(0.,
min(oro(i,j-1), oro(i,j))) * fy2(i,j)
1055 qlow(i,j) = q(i,j) + (fx1(i,j)-fx1(i+1,j)+fy1(i,j)-fy1(i,j+1)) / area(i,j)
1056 d2(i,j) = diff(i,j) * d2(i,j)
1062 qlow(i,j) = q(i,j) + d2(i,j)
1063 d2(i,j) = diff(i,j) * d2(i,j)
1076 fx4(i,j) = 0.5*(sin_sg(i-1,j,3)+sin_sg(i,j,1))*dy(i,j)*(d2(i,j)-d2(i-1,j))/dxc(i,j)-fx2(i,j)
1083 fy4(i,j) = dx(i,j)*(d2(i,j)-d2(i,j-1))/dyc(i,j) &
1084 *0.5*(sin_sg(i,j,2)+sin_sg(i,j-1,4))-fy2(i,j)
1093 win(i,j) =
max(0.,fx4(i, j)) -
min(0.,fx4(i+1,j)) + &
1094 max(0.,fy4(i, j)) -
min(0.,fy4(i,j+1)) + esl
1095 wou(i,j) =
max(0.,fx4(i+1,j)) -
min(0.,fx4(i, j)) + &
1096 max(0.,fy4(i,j+1)) -
min(0.,fy4(i, j)) + esl
1097 win(i,j) =
max(0., qmax(i,j) - qlow(i,j)) / win(i,j)*area(i,j)
1098 wou(i,j) =
max(0., qlow(i,j) - qmin(i,j)) / wou(i,j)*area(i,j)
1107 if ( fx4(i,j) > 0. )
then 1108 fx4(i,j) =
min(1., wou(i-1,j), win(i,j)) * fx4(i,j)
1110 fx4(i,j) =
min(1., win(i-1,j), wou(i,j)) * fx4(i,j)
1116 if ( fy4(i,j) > 0. )
then 1117 fy4(i,j) =
min(1., wou(i,j-1), win(i,j)) * fy4(i,j)
1119 fy4(i,j) =
min(1., win(i,j-1), wou(i,j)) * fy4(i,j)
1129 fx4(i,j) =
max(0.,
min(oro(i-1,j), oro(i,j))) * fx4(i,j)
1134 fy4(i,j) =
max(0.,
min(oro(i,j-1), oro(i,j))) * fy4(i,j)
1142 q(i,j) = qlow(i,j) + (fx4(i,j)-fx4(i+1,j)+fy4(i,j)-fy4(i,j+1))/area(i,j)
1151 subroutine map_to_cubed_raw(igh, im, jt, lat1, lon1, zs, ft, grid, agrid, &
1152 q2, f2, h2, npx, npy, jstart, jend, stretch_fac, &
1153 nested, npx_global, bd)
1156 type(fv_grid_bounds_type),
intent(IN) :: bd
1157 integer,
intent(in):: igh, im, jt
1158 integer,
intent(in):: npx, npy, npx_global
1159 real,
intent(in):: lat1(jt+1)
1160 real,
intent(in):: lon1(im+1)
1161 real(kind=4),
intent(in),
dimension(-igh:im+igh,jt):: zs, ft
1162 real(kind=R_GRID),
intent(in):: grid(bd%isd:bd%ied+1, bd%jsd:bd%jed+1,2)
1163 real(kind=R_GRID),
intent(in):: agrid(bd%isd:bd%ied, bd%jsd:bd%jed, 2)
1164 integer,
intent(in):: jstart, jend
1165 real(kind=R_GRID),
intent(IN) :: stretch_fac
1166 logical,
intent(IN) :: nested
1168 real,
intent(out):: q2(bd%isd:bd%ied,bd%jsd:bd%jed)
1169 real,
intent(out):: f2(bd%isd:bd%ied,bd%jsd:bd%jed)
1170 real,
intent(out):: h2(bd%isd:bd%ied,bd%jsd:bd%jed)
1172 real :: lon_g(-igh:im+igh)
1173 real lat_g(jt), cos_g(jt)
1174 real(kind=R_GRID) e2(2)
1175 real(kind=R_GRID) grid3(3, bd%isd:bd%ied+1, bd%jsd:bd%jed+1)
1176 real(kind=R_GRID),
dimension(3):: p1, p2, p3, p4, pc, pp
1177 real(kind=R_GRID),
dimension(3):: vp_12, vp_23, vp_34, vp_14
1179 integer ii, jj, i1, i2, j1, j2, min_pts
1180 real th1, aa, asum, qsum, fsum, hsum, lon_w, lon_e, lat_s, lat_n, r2d
1183 real delg, th0, tmp1, prod1, prod2, prod3, prod4
1188 integer :: is, ie, js, je
1189 integer :: isd, ied, jsd, jed
1205 lon_g(i) = 0.5*(lon1(i)+lon1(i+1))
1208 lon_g(i) = lon_g(i+im)
1211 lon_g(i) = lon_g(i-im)
1215 lat_g(j) = 0.5*(lat1(j)+lat1(j+1))
1216 cos_g(j) = cos( lat_g(j) )
1221 call latlon2xyz(
real(grid(i,j,1:2),kind=R_GRID), grid3(1,i,j))
1225 if(is_master())
write(*,*)
'surf_map: Search started ....' 1228 lat_crit = nint( stretch_fac*
real(nlat)/
real(npx_global-1) )
1229 lat_crit =
min( jt,
max( 4, lat_crit ) )
1231 if ( jstart==1 )
then 1232 write(*,*) mpp_pe(),
'lat_crit=', r2d*lat_g(lat_crit)
1233 elseif ( jend==nlat )
then 1240 iF ( jstart == 1 )
then 1249 qsum = qsum + zs(i,j)*aa
1250 fsum = fsum + ft(i,j)*aa
1260 hsum = hsum + (qsp-zs(i,j))**2
1263 hsp = hsum /
real(np)
1269 iF ( jend == nlat )
then 1274 do jp=jend-lat_crit+1, jend
1279 qsum = qsum + zs(i,j)*aa
1280 fsum = fsum + ft(i,j)*aa
1287 do jp=jend-lat_crit+1, jend
1291 hsum = hsum + (qnp-zs(i,j))**2
1294 hnp = hsum /
real(np)
1303 if (((i < is .and. j < js) .or. &
1304 (i < is .and. j > je) .or. &
1305 (i > ie .and. j < js) .or. &
1306 (i > ie .and. j > je)) .and. .not. nested)
then 1313 if ( agrid(i,j,2) < -pi5+stretch_fac*pi5/
real(npx_global-1) ) then
1319 elseif ( agrid(i,j,2) > pi5-stretch_fac*pi5/
real(npx_global-1) ) then
1327 lat_s =
min( grid(i,j,2), grid(i+1,j,2), grid(i,j+1,2), grid(i+1,j+1,2), agrid(i,j,2) )
1328 lat_n =
max( grid(i,j,2), grid(i+1,j,2), grid(i,j+1,2), grid(i+1,j+1,2), agrid(i,j,2) )
1330 delg =
max( 0.2*(lat_n-lat_s),
pi/
real(npx_global-1), pi2/
real(nlat) )
1331 lat_s =
max(-pi5, lat_s - delg)
1332 lat_n =
min( pi5, lat_n + delg)
1334 j1 = nint( (pi5+lat_s)/(
pi/
real(nlat)) ) - 1
1335 if ( lat_s*r2d < (-90.+90./
real(npx_global-1)) ) j1 = 1
1336 j1 =
max(jstart, j1)
1338 j2 = nint( (pi5+lat_n)/(
pi/
real(nlat)) ) + 1
1339 if ( lat_n*r2d > (90.-90./
real(npx_global-1)) ) j2 = nlat
1342 j1 = j1 - jstart + 1
1343 j2 = j2 - jstart + 1
1345 lon_w =
min( grid(i,j,1), grid(i+1,j,1), grid(i,j+1,1), grid(i+1,j+1,1) )
1346 lon_e =
max( grid(i,j,1), grid(i+1,j,1), grid(i,j+1,1), grid(i+1,j+1,1) )
1348 if ( (lon_e-lon_w) >
pi )
then 1349 i1 = -nint( (pi2-lon_e)/pi2 *
real(im) ) - 1
1350 i2 = nint( lon_w/pi2 *
real(im) ) + 1
1352 i1 = nint( lon_w/pi2 *
real(im) ) - 1
1353 i2 = nint( lon_e/pi2 *
real(im) ) + 1
1357 ig_lon =
max(1, (i2-i1)/8)
1358 i1 =
max( -igh, i1 - ig_lon)
1359 i2 =
min(im+igh, i2 + ig_lon)
1374 p1(k) = grid3(k,i, j)
1375 p2(k) = grid3(k,i+1,j)
1376 p3(k) = grid3(k,i+1,j+1)
1377 p4(k) = grid3(k,i,j+1)
1378 pc(k) = p1(k) + p2(k) + p3(k) + p4(k)
1382 th0 =
min( v_prod(p1,p3), v_prod(p2, p4) )
1383 th1 =
min(
cos_grid, cos(0.25*acos(
max(v_prod(p1,p3), v_prod(p2, p4)))))
1390 prod1 = v_prod(p3, vp_12)
1391 prod2 = v_prod(p1, vp_23)
1392 prod3 = v_prod(p1, vp_34)
1393 prod4 = v_prod(p2, vp_14)
1402 tmp1 = v_prod(pp, pc)
1404 if ( tmp1 > th1 )
goto 1111
1406 if ( tmp1 < th0 )
goto 2222
1408 if ( v_prod(pp, vp_12)*prod1 < 0. )
goto 2222
1409 if ( v_prod(pp, vp_23)*prod2 < 0. )
goto 2222
1410 if ( v_prod(pp, vp_34)*prod3 < 0. )
goto 2222
1411 if ( v_prod(pp, vp_14)*prod4 < 0. )
goto 2222
1413 qsum = qsum + zs(ii,jj)*aa
1414 fsum = fsum + ft(ii,jj)*aa
1415 hsum = hsum + zs(ii,jj)**2
1422 q2(i,j) = qsum / asum
1423 f2(i,j) = fsum / asum
1424 h2(i,j) = hsum /
real(np) - q2(i,j)**2
1425 min_pts =
min(min_pts, np)
1427 write(*,*)
'min and max lat_g is ', r2d*minval(lat_g), r2d*maxval(lat_g), mpp_pe()
1428 write(*,*)
'Surf_map failed for GID=', mpp_pe(), i,j,
'(lon,lat)=', r2d*agrid(i,j,1),r2d*agrid(i,j,2)
1429 write(*,*)
'[jstart, jend]', jstart, jend
1436 if(is_master())
write(*,*)
'surf_map: minimum pts per cell (master PE)=', min_pts
1437 if ( min_pts <3 )
then 1438 if(is_master())
write(*,*)
'Warning: too few points used in creating the cell mean terrain !!!' 1445 logical function inside_p4(p1, p2, p3, p4, pp, th0)
1447 real,
intent(in):: p1(3), p2(3), p3(3), p4(3)
1448 real,
intent(in):: pp(3)
1449 real,
intent(in):: th0
1452 real(kind=R_GRID) v1(3), v2(3), vp(3)
1453 real(kind=R_GRID) tmp1
1460 vp(k) = p1(k) + p2(k) + p3(k) + p4(k)
1464 tmp1 = v_prod(pp, vp)
1465 if ( tmp1 < th0 )
then 1471 if ( v_prod(pp, vp)*v_prod(p3, vp) < 0. )
return 1474 if ( v_prod(pp, vp)*v_prod(p1, vp) < 0. )
return 1477 if ( v_prod(pp, vp)*v_prod(p1, vp) < 0. )
return 1480 if ( v_prod(pp, vp)*v_prod(p2, vp) < 0. )
return 1488 #include <netcdf.inc> 1491 if (status .ne. nf_noerr)
then 1492 print *, nf_strerror(status)
1502 type(fv_grid_bounds_type),
intent(IN) :: bd
1503 real(kind=R_GRID),
intent(in) :: lon(bd%isd:bd%ied,bd%jsd:bd%jed), lat(bd%isd:bd%ied,bd%jsd:bd%jed)
1504 real,
intent(inout) :: lfrac(bd%isd:bd%ied,bd%jsd:bd%jed)
1506 integer :: is, ie, js, je
1507 integer :: isd, ied, jsd, jed
1514 real :: dtr, phs, phn
1532 if ( lat(i,j) < phn )
then 1534 if ( lat(i,j) < phs )
then 1539 if ( sin(lon(i,j)) < 0. .and. cos(lon(i,j)) > 0.)
then 1555 integer :: unit, ierr, io
1562 #ifdef INTERNAL_FILE_NML 1566 unit = open_namelist_file( )
1568 do while (ierr /= 0)
1569 read (unit, nml=surf_map_nml, iostat=io, end=10)
1572 10
call close_file (unit)
1577 if (mpp_pe() == mpp_root_pe())
then 1579 write (unit, nml=surf_map_nml)
1588 integer,
intent(in):: im
1589 real(kind=4),
intent(inout):: p(im)
1590 real,
intent(out):: zmean
1595 zmean = zmean + p(i)
1597 zmean = zmean /
real(im)
real, parameter, public radius
Radius of the Earth [m].
subroutine, public del4_cubed_sphere(npx, npy, q, area, dx, dy, dxc, dyc, sin_sg, nmax, zero_ocean, oro, nested, domain, bd)
real, dimension(:,:), allocatable, public zs_g
character(len=128) surf_file
real(kind=8), parameter, public pi_8
Ratio of circle circumference to diameter [N/A].
character(len=6) surf_format
real(kind=r_grid) function, public v_prod(v1, v2)
subroutine, public global_mx(q, n_g, qmin, qmax, bd)
subroutine two_delta_filter(npx, npy, q, area, dx, dy, dxa, dya, dxc, dyc, sin_sg, cd, zero_ocean, check_slope, filter_type, oro, nested, domain, bd, ntmax)
void vect_cross(const double *p1, const double *p2, double *e)
real, dimension(:,:), allocatable, public oro_g
integer function, public check_nml_error(IOSTAT, NML_NAME)
character(len=input_str_length), dimension(:), allocatable, target, public input_nml_file
subroutine handle_err(status)
integer, parameter, public ng
subroutine timing_on(blk_name)
integer, parameter, public r_grid
subroutine, public surfdrv(npx, npy, grid, agrid, area, dx, dy, dxa, dya, dxc, dyc, sin_sg, phis, stretch_fac, nested, npx_global, domain, grid_number, bd)
real function, public great_circle_dist(q1, q2, radius)
subroutine remove_ice_sheets(lon, lat, lfrac, bd)
logical function inside_p4(p1, p2, p3, p4, pp, th0)
subroutine zonal_mean(im, p, zmean)
real, parameter, public grav
Acceleration due to gravity [m/s^2].
real function, public g_sum(domain, p, ifirst, ilast, jfirst, jlast, ngc, area, mode, reproduce)
void normalize_vect(double *e)
subroutine, public fv3_zs_filter(bd, isd, ied, jsd, jed, npx, npy, npx_global, stretch_fac, nested, domain, area, dxa, dya, dx, dy, dxc, dyc, grid, agrid, sin_sg, phis, oro)
real, dimension(:,:), allocatable, public sgh_g
subroutine, public del2_cubed_sphere(npx, npy, q, area, dx, dy, dxc, dyc, sin_sg, nmax, cd, zero_ocean, oro, nested, domain, bd)
void latlon2xyz(int size, const double *lon, const double *lat, double *x, double *y, double *z)
subroutine, public error_mesg(routine, message, level)
subroutine map_to_cubed_raw(igh, im, jt, lat1, lon1, zs, ft, grid, agrid, q2, f2, h2, npx, npy, jstart, jend, stretch_fac, nested, npx_global, bd)
real(fp), parameter, public pi
subroutine timing_off(blk_name)
character(len=3) grid_string