118 use constants_mod,
only: grav, omega, pi=>pi_8, cnst_radius=>
radius 126 use fv_mp_mod,
only:
ng, is_master, fill_corners, xdir, ydir
127 use fv_mp_mod,
only: mp_gather, mp_bcst, mp_reduce_max, mp_stop
129 use mpp_mod,
only: mpp_error, fatal, get_unit, mpp_chksum, mpp_pe, stdout, &
130 mpp_send, mpp_recv, mpp_sync_self, event_recv, mpp_npes, &
131 mpp_sum, mpp_max, mpp_min, mpp_root_pe, mpp_broadcast, mpp_transmit
132 use mpp_domains_mod,
only: mpp_update_domains, mpp_get_boundary, &
133 mpp_get_ntile_count, mpp_get_pelist, &
134 mpp_get_compute_domains, mpp_global_field, &
135 mpp_get_data_domain, mpp_get_compute_domain, &
136 mpp_get_global_domain, mpp_global_sum, mpp_global_max, mpp_global_min
137 use mpp_domains_mod,
only: domain2d
138 use mpp_io_mod,
only: mpp_get_att_value
140 use mpp_parameter_mod,
only: agrid_param=>agrid, &
141 dgrid_ne_param=>dgrid_ne, &
142 cgrid_ne_param=>cgrid_ne, &
143 cgrid_sw_param=>cgrid_sw, &
144 bgrid_ne_param=>bgrid_ne, &
145 bgrid_sw_param=>bgrid_sw, &
147 corner, center, xupdate
148 use fms_mod,
only: get_mosaic_tile_grid
149 use fms_io_mod,
only: file_exist, field_exist, read_data, &
150 get_global_att_value, get_var_att_value
151 use mosaic_mod,
only : get_mosaic_ntiles
155 #include <netcdf.inc> 157 real(kind=R_GRID),
parameter::
radius = cnst_radius
159 real(kind=R_GRID) ,
parameter::
todeg = 180.0d0/pi
160 real(kind=R_GRID) ,
parameter::
torad = pi/180.0d0
161 real(kind=R_GRID) ,
parameter::
missing = 1.d25
174 subroutine read_grid(Atm, grid_file, ndims, nregions, ng)
175 type(fv_atmos_type),
intent(inout),
target :: Atm
176 character(len=*),
intent(IN) :: grid_file
177 integer,
intent(IN) :: ndims
178 integer,
intent(IN) :: nregions
179 integer,
intent(IN) :: ng
181 real,
allocatable,
dimension(:,:) :: tmpx, tmpy
182 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: grid
183 character(len=128) :: units =
"" 184 character(len=256) :: atm_mosaic, atm_hgrid, grid_form
185 character(len=1024) :: attvalue
186 integer :: ntiles, i, j, stdunit
187 integer :: isc2, iec2, jsc2, jec2
188 integer :: start(4), nread(4)
189 integer :: is, ie, js, je
190 integer :: isd, ied, jsd, jed
191 integer,
save :: halo=3
201 grid => atm%gridstruct%grid_64
203 if(.not. file_exist(grid_file))
call mpp_error(fatal,
'fv_grid_tools(read_grid): file '// &
204 trim(grid_file)//
' does not exist')
207 if( field_exist(grid_file,
'atm_mosaic_file') .OR. field_exist(grid_file,
'gridfiles') )
then 209 write(stdunit,*)
'==>Note from fv_grid_tools_mod(read_grid): read atmosphere grid from mosaic version grid' 211 call mpp_error(fatal,
'fv_grid_tools(read_grid): neither atm_mosaic_file nor gridfiles exists in file ' &
215 if(field_exist(grid_file,
'atm_mosaic_file'))
then 216 call read_data(grid_file,
"atm_mosaic_file", atm_mosaic)
217 atm_mosaic =
"INPUT/"//trim(atm_mosaic)
219 atm_mosaic = trim(grid_file)
222 call get_mosaic_tile_grid(atm_hgrid, atm_mosaic, atm%domain)
225 if( get_global_att_value(atm_hgrid,
"history", attvalue) )
then 226 if( index(attvalue,
"gnomonic_ed") > 0) grid_form =
"gnomonic_ed" 228 if(grid_form .NE.
"gnomonic_ed")
call mpp_error(fatal, &
229 "fv_grid_tools(read_grid): the grid should be 'gnomonic_ed' when reading from grid file, contact developer")
232 ntiles = get_mosaic_ntiles(atm_mosaic)
234 if( .not. atm%flagstruct%regional)
then 235 if(ntiles .NE. 6)
call mpp_error(fatal, &
236 'fv_grid_tools(read_grid): ntiles should be 6 in mosaic file '//trim(atm_mosaic) )
237 if(nregions .NE. 6)
call mpp_error(fatal, &
238 'fv_grid_tools(read_grid): nregions should be 6 when reading from mosaic file '//trim(grid_file) )
241 call get_var_att_value(atm_hgrid,
'x',
'units', units)
244 isc2 = 2*is-1; iec2 = 2*ie+1
245 jsc2 = 2*js-1; jec2 = 2*je+1
246 if( atm%flagstruct%regional)
then 247 isc2 = 2*(isd+halo)-1; iec2 = 2*(ied+1+halo)-1
248 jsc2 = 2*(jsd+halo)-1; jec2 = 2*(jed+1+halo)-1
250 allocate(tmpx(isc2:iec2, jsc2:jec2) )
251 allocate(tmpy(isc2:iec2, jsc2:jec2) )
253 start(1) = isc2; nread(1) = iec2 - isc2 + 1
254 start(2) = jsc2; nread(2) = jec2 - jsc2 + 1
255 call read_data(atm_hgrid,
'x', tmpx, start, nread, no_domain=.true.)
256 call read_data(atm_hgrid,
'y', tmpy, start, nread, no_domain=.true.)
259 grid(isd: is-1, jsd:js-1,1:ndims)=0.
260 grid(isd: is-1, je+2:jed+1,1:ndims)=0.
261 grid(ie+2:ied+1,jsd:js-1,1:ndims)=0.
262 grid(ie+2:ied+1,je+2:jed+1,1:ndims)=0.
263 if(len_trim(units) < 6)
call mpp_error(fatal, &
264 "fv_grid_tools_mod(read_grid): the length of units must be no less than 6")
265 if(units(1:6) ==
'degree')
then 266 if( .not. atm%flagstruct%regional)
then 269 grid(i,j,1) = tmpx(2*i-1,2*j-1)*pi/180.
270 grid(i,j,2) = tmpy(2*i-1,2*j-1)*pi/180.
280 grid(i,j,1) = tmpx(2*i+halo+2,2*j+halo+2)*pi/180.
281 grid(i,j,2) = tmpy(2*i+halo+2,2*j+halo+2)*pi/180.
286 else if(units(1:6) ==
'radian')
then 289 grid(i,j,1) = tmpx(2*i-1,2*j-1)
290 grid(i,j,2) = tmpy(2*i-1,2*j-1)
294 print*,
'units is ' , trim(units), len_trim(units), mpp_pe()
295 call mpp_error(fatal,
'fv_grid_tools_mod(read_grid): units must start with degree or radian')
298 deallocate(tmpx, tmpy)
306 subroutine get_symmetry(data_in, data_out, ishift, jshift, npes_x, npes_y, domain, tile, npx_g, bd)
307 type(fv_grid_bounds_type),
intent(IN) :: bd
308 integer,
intent(in) :: ishift, jshift, npes_x, npes_y
309 real(kind=R_GRID),
dimension(bd%is:bd%ie+ishift, bd%js:bd%je+jshift ),
intent(in) :: data_in
310 real(kind=R_GRID),
dimension(bd%is:bd%ie+jshift, bd%js:bd%je+ishift ),
intent(out) :: data_out
311 real(kind=R_GRID),
dimension(:),
allocatable :: send_buffer
312 real(kind=R_GRID),
dimension(:),
allocatable :: recv_buffer
313 integer,
dimension(:),
allocatable :: is_recv, ie_recv, js_recv, je_recv, pe_recv
314 integer,
dimension(:),
allocatable :: is_send, ie_send, js_send, je_send, pe_send
315 integer,
dimension(:),
allocatable :: isl, iel, jsl, jel, pelist, msg1, msg2
316 integer :: msgsize, pos, ntiles, npes_per_tile, npes
317 integer :: send_buf_size, recv_buf_size, buffer_pos
318 integer :: is0, ie0, js0, je0
319 integer :: is1, ie1, js1, je1
320 integer :: is2, ie2, js2, je2
321 integer :: i, j, p, nrecv, nsend, tile_you, is3, ie3, nlist
322 integer :: start_pe, ipos, jpos, from_pe, to_pe
323 type(domain2d) :: domain
324 integer :: tile, npx_g
325 integer :: is, ie, js, je
326 integer :: isd, ied, jsd, jed
339 ntiles = mpp_get_ntile_count(domain)
342 if(ntiles .NE. 6 )
call mpp_error(fatal,
'fv_grid_tools(get_symmetry): ntiles should be 6 ')
343 if(mod(npes,ntiles) /= 0)
call mpp_error(fatal,
'fv_grid_tools(get_symmetry): npes should be divided by ntiles')
344 npes_per_tile = npes/ntiles
347 if(npes_x == npes_y .AND. mod(npx_g-1,npes_x) == 0 )
then 348 msgsize = (ie-is+1+jshift)*(je-js+1+ishift)
350 pos = mod((mpp_pe()-mpp_root_pe()), npes_x*npes_y)
351 start_pe = mpp_pe() - pos
352 ipos = mod(pos, npes_x)
354 from_pe = start_pe + ipos*npes_x + jpos
356 allocate(recv_buffer(msgsize))
357 call mpp_recv(recv_buffer(1), glen=msgsize, from_pe=from_pe, block=.false. )
360 allocate(send_buffer(msgsize))
364 send_buffer(pos) = data_in(i,j)
368 call mpp_send(send_buffer(1), plen=msgsize, to_pe=to_pe)
369 call mpp_sync_self(check=event_recv)
376 data_out(i,j) = recv_buffer(pos)
381 deallocate(send_buffer, recv_buffer)
384 allocate(is_recv(0:npes_per_tile-1), ie_recv(0:npes_per_tile-1))
385 allocate(js_recv(0:npes_per_tile-1), je_recv(0:npes_per_tile-1))
386 allocate(is_send(0:npes_per_tile-1), ie_send(0:npes_per_tile-1))
387 allocate(js_send(0:npes_per_tile-1), je_send(0:npes_per_tile-1))
388 allocate(pe_send(0:npes_per_tile-1), pe_recv(0:npes_per_tile-1))
390 allocate(msg1(0:npes_per_tile-1), msg2(0:npes_per_tile-1))
395 allocate(pelist(0:npes-1))
396 call mpp_get_pelist(domain, pelist)
397 allocate(isl(0:npes-1), iel(0:npes-1), jsl(0:npes-1), jel(0:npes-1) )
398 call mpp_get_compute_domains(domain, xbegin=isl, xend=iel, ybegin=jsl, yend=jel)
408 tile_you = p/(npes_x*npes_y) + 1
409 if(tile_you .NE. tile) cycle
412 is1 = js; ie1 = je + ishift;
413 js1 = is; je1 = ie + jshift;
415 is2 = isl(p); ie2 = iel(p) + ishift;
416 js2 = jsl(p); je2 = jel(p) + jshift;
417 is0 = max(is1,is2); ie0 = min(ie1,ie2)
418 js0 = max(js1,js2); je0 = min(je1,je2)
420 if(ie0 .GE. is0 .AND. je0 .GE. js0)
then 421 msgsize = (ie0-is0+1)*(je0-js0+1)
422 recv_buf_size = recv_buf_size + msgsize
423 pe_recv(nrecv) = pelist(p)
425 is_recv(nrecv) = js0; ie_recv(nrecv) = je0
426 js_recv(nrecv) = is0; je_recv(nrecv) = ie0
430 msg1(nlist) = msgsize
431 call mpp_recv(msg2(nlist), glen=1, from_pe=pelist(p), block=.false. )
439 tile_you = p/(npes_x*npes_y) + 1
440 if(tile_you .NE. tile) cycle
442 is1 = is; ie1 = ie + ishift;
443 js1 = js; je1 = je + jshift;
445 is2 = jsl(p); ie2 = jel(p) + ishift;
446 js2 = isl(p); je2 = iel(p) + jshift;
447 is0 = max(is1,is2); ie0 = min(ie1,ie2)
448 js0 = max(js1,js2); je0 = min(je1,je2)
450 if(ie0 .GE. is0 .AND. je0 .GE. js0 )
then 451 msgsize = (ie0-is0+1)*(je0-js0+1)
452 send_buf_size = send_buf_size + msgsize
453 pe_send(nsend) = pelist(p)
454 is_send(nsend) = is0; ie_send(nsend) = ie0
455 js_send(nsend) = js0; je_send(nsend) = je0
463 call mpp_sync_self(check=event_recv)
465 if(msg1(p) .NE. msg2(p))
then 466 call mpp_error(fatal,
"fv_grid_tools_mod(get_symmetry): mismatch on send and recv size")
470 deallocate(msg1, msg2)
474 allocate(recv_buffer(recv_buf_size))
477 is0 = is_recv(p); ie0 = ie_recv(p)
478 js0 = js_recv(p); je0 = je_recv(p)
479 msgsize = (ie0-is0+1)*(je0-js0+1)
480 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe=pe_recv(p), block=.false. )
481 buffer_pos = buffer_pos + msgsize
486 allocate(send_buffer(send_buf_size))
488 is0 = is_send(p); ie0 = ie_send(p)
489 js0 = js_send(p); je0 = je_send(p)
490 msgsize = (ie0-is0+1)*(je0-js0+1)
495 send_buffer(pos) = data_in(i,j)
498 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe=pe_send(p) )
499 buffer_pos = buffer_pos + msgsize
502 call mpp_sync_self(check=event_recv)
507 is0 = is_recv(p); ie0 = ie_recv(p)
508 js0 = js_recv(p); je0 = je_recv(p)
513 data_out(i,j) = recv_buffer(pos)
519 deallocate(isl, iel, jsl, jel, pelist)
520 deallocate(is_recv, ie_recv, js_recv, je_recv, pe_recv)
521 deallocate(is_send, ie_send, js_send, je_send, pe_send)
522 deallocate(recv_buffer, send_buffer)
529 subroutine init_grid(Atm, grid_name, grid_file, npx, npy, npz, ndims, nregions, ng)
532 character(len=80),
intent(IN) :: grid_name
533 character(len=120),
intent(IN) :: grid_file
534 integer,
intent(IN) :: npx, npy, npz
535 integer,
intent(IN) :: ndims
536 integer,
intent(IN) :: nregions
537 integer,
intent(IN) :: ng
539 real(kind=R_GRID) :: xs(npx,npy)
540 real(kind=R_GRID) :: ys(npx,npy)
542 real(kind=R_GRID) :: dp, dl
543 real(kind=R_GRID) :: x1,x2,y1,y2,z1,z2
544 integer :: i,j,k,n,nreg
547 real(kind=R_GRID) :: p1(3), p2(3), p3(3), p4(3)
548 real(kind=R_GRID) :: dist,dist1,dist2, pa(2), pa1(2), pa2(2), pb(2)
549 real(kind=R_GRID) :: pt(3), pt1(3), pt2(3), pt3(3)
550 real(kind=R_GRID) :: ee1(3), ee2(3)
552 real(kind=R_GRID) :: angn,angm,angav,ang
553 real(kind=R_GRID) :: aspn,aspm,aspav,asp
554 real(kind=R_GRID) :: dxn, dxm, dxav
555 real(kind=R_GRID) :: dx_local, dy_local
557 real(kind=R_GRID) :: vec1(3), vec2(3), vec3(3), vec4(3)
558 real(kind=R_GRID) :: vecavg(3), vec3a(3), vec3b(3), vec4a(3), vec4b(3)
559 real(kind=R_GRID) :: xyz1(3), xyz2(3)
562 integer :: ios, ip, jp
567 character(len=80) :: tmpfile
569 real(kind=R_GRID),
dimension(Atm%bd%is:Atm%bd%ie) :: sbuffer, nbuffer
570 real(kind=R_GRID),
dimension(Atm%bd%js:Atm%bd%je) :: wbuffer, ebuffer
572 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: agrid, grid
573 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
575 real(kind=R_GRID),
pointer,
dimension(:,:) :: sina, cosa, dx, dy, dxc, dyc, dxa, dya
576 real,
pointer,
dimension(:,:,:) :: e1, e2
578 real,
pointer,
dimension(:,:) :: rarea, rarea_c
579 real,
pointer,
dimension(:,:) :: rdx, rdy, rdxc, rdyc, rdxa, rdya
581 integer,
pointer,
dimension(:,:,:) :: iinta, jinta, iintb, jintb
583 real(kind=R_GRID),
pointer,
dimension(:,:,:,:) :: grid_global
585 integer,
pointer :: npx_g, npy_g, ntiles_g, tile
586 logical,
pointer :: sw_corner, se_corner, ne_corner, nw_corner
587 logical,
pointer :: latlon, cubed_sphere, have_south_pole, have_north_pole, stretched_grid
589 type(domain2d),
pointer :: domain
590 integer :: is, ie, js, je
591 integer :: isd, ied, jsd, jed
592 integer :: istart, iend, jstart, jend
604 agrid => atm%gridstruct%agrid_64
605 grid => atm%gridstruct%grid_64
607 area => atm%gridstruct%area_64
608 area_c => atm%gridstruct%area_c_64
609 rarea => atm%gridstruct%rarea
610 rarea_c => atm%gridstruct%rarea_c
612 sina => atm%gridstruct%sina_64
613 cosa => atm%gridstruct%cosa_64
614 dx => atm%gridstruct%dx_64
615 dy => atm%gridstruct%dy_64
616 dxc => atm%gridstruct%dxc_64
617 dyc => atm%gridstruct%dyc_64
618 dxa => atm%gridstruct%dxa_64
619 dya => atm%gridstruct%dya_64
620 rdx => atm%gridstruct%rdx
621 rdy => atm%gridstruct%rdy
622 rdxc => atm%gridstruct%rdxc
623 rdyc => atm%gridstruct%rdyc
624 rdxa => atm%gridstruct%rdxa
625 rdya => atm%gridstruct%rdya
626 e1 => atm%gridstruct%e1
627 e2 => atm%gridstruct%e2
629 if (atm%neststruct%nested .or. any(atm%neststruct%child_grids))
then 630 grid_global => atm%grid_global
631 else if( trim(grid_file) .NE.
'INPUT/grid_spec.nc')
then 632 allocate(grid_global(1-ng:npx +ng,1-ng:npy +ng,ndims,1:nregions))
635 iinta => atm%gridstruct%iinta
636 jinta => atm%gridstruct%jinta
637 iintb => atm%gridstruct%iintb
638 jintb => atm%gridstruct%jintb
639 npx_g => atm%gridstruct%npx_g
640 npy_g => atm%gridstruct%npy_g
641 ntiles_g => atm%gridstruct%ntiles_g
642 sw_corner => atm%gridstruct%sw_corner
643 se_corner => atm%gridstruct%se_corner
644 ne_corner => atm%gridstruct%ne_corner
645 nw_corner => atm%gridstruct%nw_corner
646 latlon => atm%gridstruct%latlon
647 cubed_sphere => atm%gridstruct%cubed_sphere
648 have_south_pole => atm%gridstruct%have_south_pole
649 have_north_pole => atm%gridstruct%have_north_pole
650 stretched_grid => atm%gridstruct%stretched_grid
660 cubed_sphere = .false.
662 if ( atm%flagstruct%do_schmidt .and. abs(atm%flagstruct%stretch_fac-1.) > 1.e-5 ) stretched_grid = .true.
664 if (atm%flagstruct%grid_type>3)
then 665 if (atm%flagstruct%grid_type == 4)
then 666 call setup_cartesian(npx, npy, atm%flagstruct%dx_const, atm%flagstruct%dy_const, &
667 atm%flagstruct%deglat, atm%bd)
669 call mpp_error(fatal,
'init_grid: unsupported grid type')
673 cubed_sphere = .true.
674 if (atm%neststruct%nested)
then 677 if(trim(grid_file) ==
'INPUT/grid_spec.nc')
then 678 call read_grid(atm, grid_file, ndims, nregions, ng)
680 if (atm%flagstruct%grid_type>=0)
call gnomonic_grids(atm%flagstruct%grid_type, npx-1, xs, ys)
681 if (is_master())
then 682 if (atm%flagstruct%grid_type>=0)
then 685 grid_global(i,j,1,1) = xs(i,j)
686 grid_global(i,j,2,1) = ys(i,j)
698 if ( .not.atm%flagstruct%do_schmidt .and. (atm%flagstruct%shift_fac)>1.e-4 ) &
699 grid_global(i,j,1,n) = grid_global(i,j,1,n) - pi/atm%flagstruct%shift_fac
701 if ( grid_global(i,j,1,n) < 0. ) &
702 grid_global(i,j,1,n) = grid_global(i,j,1,n) + 2.*pi
703 if (abs(grid_global(i,j,1,1)) < 1.d-10) grid_global(i,j,1,1) = 0.0
704 if (abs(grid_global(i,j,2,1)) < 1.d-10) grid_global(i,j,2,1) = 0.0
709 call mpp_error(fatal,
"fv_grid_tools: reading of ASCII grid files no longer supported")
712 grid_global( 1,1:npy,:,2)=grid_global(npx,1:npy,:,1)
713 grid_global( 1,1:npy,:,3)=grid_global(npx:1:-1,npy,:,1)
714 grid_global(1:npx,npy,:,5)=grid_global(1,npy:1:-1,:,1)
715 grid_global(1:npx,npy,:,6)=grid_global(1:npx,1,:,1)
717 grid_global(1:npx, 1,:,3)=grid_global(1:npx,npy,:,2)
718 grid_global(1:npx, 1,:,4)=grid_global(npx,npy:1:-1,:,2)
719 grid_global(npx,1:npy,:,6)=grid_global(npx:1:-1,1,:,2)
721 grid_global( 1,1:npy,:,4)=grid_global(npx,1:npy,:,3)
722 grid_global( 1,1:npy,:,5)=grid_global(npx:1:-1,npy,:,3)
724 grid_global(npx,1:npy,:,3)=grid_global(1,1:npy,:,4)
725 grid_global(1:npx, 1,:,5)=grid_global(1:npx,npy,:,4)
726 grid_global(1:npx, 1,:,6)=grid_global(npx,npy:1:-1,:,4)
728 grid_global( 1,1:npy,:,6)=grid_global(npx,1:npy,:,5)
733 if ( atm%flagstruct%do_schmidt )
then 736 atm%flagstruct%target_lon, atm%flagstruct%target_lat, &
737 n, grid_global(1:npx,1:npy,1,n), grid_global(1:npx,1:npy,2,n))
741 call mpp_broadcast(grid_global,
size(grid_global), mpp_root_pe())
746 grid(i,j,n) = grid_global(i,j,n,tile)
755 call mpp_update_domains( grid, atm%domain, position=corner)
756 if (.not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 757 call fill_corners(grid(:,:,1), npx, npy, fill=xdir, bgrid=.true.)
758 call fill_corners(grid(:,:,2), npx, npy, fill=xdir, bgrid=.true.)
764 if( .not. atm%flagstruct%regional)
then 776 do j = jstart, jend+1
780 p2(1) = grid(i+1,j,1)
781 p2(2) = grid(i+1,j,2)
785 if( stretched_grid )
then 787 do i = istart, iend+1
790 p2(1) = grid(i,j+1,1)
791 p2(2) = grid(i,j+1,2)
796 call get_symmetry(dx(is:ie,js:je+1), dy(is:ie+1,js:je), 0, 1, atm%layout(1), atm%layout(2), &
797 atm%domain, atm%tile, atm%gridstruct%npx_g, atm%bd)
800 call mpp_get_boundary( dy, dx, atm%domain, ebufferx=ebuffer, wbufferx=wbuffer, sbuffery=sbuffer, nbuffery=nbuffer,&
801 flags=scalar_pair+xupdate, gridtype=cgrid_ne_param)
802 if( .not. atm%flagstruct%regional )
then 803 if(is == 1 .AND. mod(tile,2) .NE. 0)
then 804 dy(is, js:je) = wbuffer(js:je)
807 dy(ie+1, js:je) = ebuffer(js:je)
811 call mpp_update_domains( dy, dx, atm%domain, flags=scalar_pair, &
812 gridtype=cgrid_ne_param, complete=.true.)
813 if (cubed_sphere .and. (.not. (atm%neststruct%nested .or. atm%flagstruct%regional)))
then 814 call fill_corners(dx, dy, npx, npy, dgrid=.true.)
817 if( .not. stretched_grid ) &
818 call sorted_inta(isd, ied, jsd, jed, cubed_sphere, grid, iinta, jinta)
820 agrid(:,:,:) = -1.e25
826 if ( stretched_grid )
then 828 grid(i,j+1,1:2), grid(i+1,j+1,1:2), &
831 call cell_center2(grid(iinta(1,i,j),jinta(1,i,j),1:2), &
832 grid(iinta(2,i,j),jinta(2,i,j),1:2), &
833 grid(iinta(3,i,j),jinta(3,i,j),1:2), &
834 grid(iinta(4,i,j),jinta(4,i,j),1:2), &
840 call mpp_update_domains( agrid, atm%domain, position=center, complete=.true. )
841 if (.not. (atm%neststruct%nested .or. atm%flagstruct%regional))
then 842 call fill_corners(agrid(:,:,1), npx, npy, xdir, agrid=.true.)
843 call fill_corners(agrid(:,:,2), npx, npy, ydir, agrid=.true.)
858 if (cubed_sphere .and. (.not. (atm%neststruct%nested .or. atm%flagstruct%regional)))
then 859 call fill_corners(dxa, dya, npx, npy, agrid=.true.)
872 dxc(isd,j) = dxc(isd+1,j)
873 dxc(ied+1,j) = dxc(ied,j)
887 dyc(i,jsd) = dyc(i,jsd+1)
888 dyc(i,jed+1) = dyc(i,jed)
892 if( .not. stretched_grid ) &
893 call sorted_intb(isd, ied, jsd, jed, is, ie, js, je, npx, npy, &
894 cubed_sphere, agrid, iintb, jintb)
896 call grid_area( npx, npy, ndims, nregions, atm%neststruct%nested, atm%gridstruct, atm%domain, atm%bd, atm%flagstruct%regional )
903 if ( .not. stretched_grid .and. (.not. (atm%neststruct%nested .or. atm%flagstruct%regional)))
then 910 p2(1:2) = agrid(i,j-1,1:2)
911 p3(1:2) = agrid(i,j, 1:2)
916 p2(1:2) = agrid(i,j,1:2)
920 if ( (ie+1)==npx )
then 923 p1(1:2) = agrid(i-1,j-1,1:2)
926 p4(1:2) = agrid(i-1,j,1:2)
930 p1(1:2) = agrid(i-1,j,1:2)
940 p3(1:2) = agrid(i, j,1:2)
941 p4(1:2) = agrid(i-1,j,1:2)
946 p2(1:2) = agrid(i,j,1:2)
950 if ( (je+1)==npy )
then 953 p1(1:2) = agrid(i-1,j-1,1:2)
954 p2(1:2) = agrid(i ,j-1,1:2)
960 p1(1:2) = agrid(i,j-1,1:2)
966 if ( sw_corner )
then 968 p1(1:2) = grid(i,j,1:2)
970 p3(1:2) = agrid(i,j,1:2)
974 if ( se_corner )
then 977 p2(1:2) = grid(i,j,1:2)
979 p4(1:2) = agrid(i,j,1:2)
982 if ( ne_corner )
then 984 p1(1:2) = agrid(i-1,j-1,1:2)
986 p3(1:2) = grid(i,j,1:2)
990 if ( nw_corner )
then 993 p2(1:2) = agrid(i,j-1,1:2)
995 p4(1:2) = grid(i,j,1:2)
1001 call mpp_update_domains( dxc, dyc, atm%domain, flags=scalar_pair, &
1002 gridtype=cgrid_ne_param, complete=.true.)
1003 if (cubed_sphere .and. (.not. (atm%neststruct%nested .or. atm%flagstruct%regional)))
then 1004 call fill_corners(dxc, dyc, npx, npy, cgrid=.true.)
1007 call mpp_update_domains( area, atm%domain, complete=.true. )
1011 if (atm%neststruct%nested .or. atm%flagstruct%regional)
then 1014 area_c(isd,j) = area_c(isd+1,j)
1016 if (js == 1) area_c(isd,jsd) = area_c(isd+1,jsd+1)
1017 if (js == npy-1) area_c(isd,jed+1) = area_c(isd+1,jed)
1019 if (ie == npx-1)
then 1021 area_c(ied+1,j) = area_c(ied,j)
1023 if (js == 1) area_c(ied+1,jsd) = area_c(ied,jsd+1)
1024 if (js == npy-1) area_c(ied+1,jed+1) = area_c(ied,jed)
1028 area_c(i,jsd) = area_c(i,jsd+1)
1031 if (je == npy-1)
then 1033 area_c(i,jed+1) = area_c(i,jed)
1038 call mpp_update_domains( area_c, atm%domain, position=corner, complete=.true.)
1041 if (cubed_sphere .and. (.not. (atm%neststruct%nested .or. atm%flagstruct%regional)))
then 1043 call fill_corners(area_c, npx, npy, fill=xdir, bgrid=.true.)
1048 rdx(i,j) = 1.0/dx(i,j)
1053 rdy(i,j) = 1.0/dy(i,j)
1058 rdxc(i,j) = 1.0/dxc(i,j)
1063 rdyc(i,j) = 1.0/dyc(i,j)
1068 rarea(i,j) = 1.0/area(i,j)
1069 rdxa(i,j) = 1./dxa(i,j)
1070 rdya(i,j) = 1./dya(i,j)
1075 rarea_c(i,j) = 1.0/area_c(i,j)
1079 200
format(a,f9.2,a,f9.2,a,f9.2)
1080 201
format(a,f9.2,a,f9.2,a,f9.2,a,f9.2)
1081 202
format(a,a,i4.4,a,i4.4,a)
1096 if(i>ceiling(npx/2.) .OR. j>ceiling(npy/2.)) cycle
1097 ang =
get_angle(2, grid(i,j+1,1:2), grid(i,j,1:2), grid(i+1,j,1:2))
1098 ang = abs(90.0 - ang)
1100 if ( (i==1) .and. (j==1) )
then 1103 angm = max(angm,ang)
1104 angn = min(angn,ang)
1110 dxav = dxav + 0.5 * (dx_local + dy_local)
1111 dxm = max(dxm,dx_local)
1112 dxm = max(dxm,dy_local)
1113 dxn = min(dxn,dx_local)
1114 dxn = min(dxn,dy_local)
1116 asp = abs(dx_local/dy_local)
1117 if (asp < 1.0) asp = 1.0/asp
1119 aspm = max(aspm,asp)
1120 aspn = min(aspn,asp)
1134 if( is_master() )
then 1136 angav = angav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) - 1 )
1137 dxav = dxav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) )
1138 aspav = aspav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) )
1141 write(*,*)
' REDUCED EARTH: Radius is ',
radius,
', omega is ', omega
1143 write(*,* )
' Cubed-Sphere Grid Stats : ', npx,
'x',npy,
'x',nregions
1145 write(*,200)
' Deviation from Orthogonal : min: ',angn,
' max: ',angm,
' avg: ',angav
1146 write(*,200)
' Aspect Ratio : min: ',aspn,
' max: ',aspm,
' avg: ',aspav
1151 if (atm%neststruct%nested .or. any(atm%neststruct%child_grids))
then 1152 nullify(grid_global)
1153 else if( trim(grid_file) .NE.
'INPUT/grid_spec.nc')
then 1154 deallocate(grid_global)
1194 nullify(cubed_sphere)
1195 nullify(have_south_pole)
1196 nullify(have_north_pole)
1197 nullify(stretched_grid)
1207 type(fv_grid_bounds_type),
intent(IN) :: bd
1208 integer,
intent(in):: npx, npy
1209 real(kind=R_GRID),
intent(IN) :: dx_const, dy_const, deglat
1210 real(kind=R_GRID) lat_rad, lon_rad, domain_rad
1212 integer :: is, ie, js, je
1213 integer :: isd, ied, jsd, jed
1225 lat_rad = deglat * pi/180.
1229 rdx(:,:) = 1./dx_const
1231 rdy(:,:) = 1./dy_const
1234 rdxc(:,:) = 1./dx_const
1236 rdyc(:,:) = 1./dy_const
1239 rdxa(:,:) = 1./dx_const
1241 rdya(:,:) = 1./dy_const
1243 area(:,:) = dx_const*dy_const
1244 rarea(:,:) = 1./(dx_const*dy_const)
1246 area_c(:,:) = dx_const*dy_const
1247 rarea_c(:,:) = 1./(dx_const*dy_const)
1250 do j=max(1,jsd),min(jed,npy)
1251 do i=max(1,isd),min(ied,npx)
1252 grid(i,j,1) = lon_rad - 0.5*domain_rad +
real(i-1)/
real(npx-1)*domain_rad
1253 grid(i,j,2) = lat_rad - 0.5*domain_rad +
real(j-1)/
real(npy-1)*domain_rad
1257 agrid(:,:,1) = lon_rad
1258 agrid(:,:,2) = lat_rad
1275 type(fv_atmos_type),
intent(INOUT),
target :: Atm
1277 integer :: isd_p, ied_p, jsd_p, jed_p
1278 integer :: isg, ieg, jsg, jeg
1279 integer :: ic, jc, imod, jmod
1282 real(kind=R_GRID),
allocatable,
dimension(:,:,:) :: p_grid_u, p_grid_v, pa_grid, p_grid, c_grid_u, c_grid_v
1283 integer :: p_ind(1-ng:npx +ng,1-ng:npy +ng,4)
1288 real(kind=R_GRID) sum
1289 real(kind=R_GRID) :: dist1, dist2, dist3, dist4
1290 real(kind=R_GRID),
dimension(2) :: q1, q2
1292 integer,
pointer :: parent_tile, refinement, ioffset, joffset
1293 integer,
pointer,
dimension(:,:,:) :: ind_h, ind_u, ind_v, ind_update_h
1294 real,
pointer,
dimension(:,:,:) :: wt_h, wt_u, wt_v
1296 integer,
pointer,
dimension(:,:,:) :: ind_b
1297 real,
pointer,
dimension(:,:,:) :: wt_b
1299 integer :: is, ie, js, je
1300 integer :: isd, ied, jsd, jed
1313 parent_tile => atm%neststruct%parent_tile
1314 refinement => atm%neststruct%refinement
1315 ioffset => atm%neststruct%ioffset
1316 joffset => atm%neststruct%joffset
1318 ind_h => atm%neststruct%ind_h
1319 ind_u => atm%neststruct%ind_u
1320 ind_v => atm%neststruct%ind_v
1322 ind_update_h => atm%neststruct%ind_update_h
1324 wt_h => atm%neststruct%wt_h
1325 wt_u => atm%neststruct%wt_u
1326 wt_v => atm%neststruct%wt_v
1328 ind_b => atm%neststruct%ind_b
1329 wt_b => atm%neststruct%wt_b
1331 call mpp_get_data_domain( atm%parent_grid%domain, &
1332 isd_p, ied_p, jsd_p, jed_p )
1333 call mpp_get_global_domain( atm%parent_grid%domain, &
1336 allocate(p_grid_u(isg:ieg ,jsg:jeg+1,1:2))
1337 allocate(p_grid_v(isg:ieg+1,jsg:jeg ,1:2))
1338 allocate(pa_grid(isg:ieg,jsg:jeg ,1:2))
1341 allocate(p_grid( isg-ng:ieg+1+ng, jsg-ng:jeg+1+ng,1:2) )
1345 if( is_master() )
then 1348 call mpp_recv(p_grid( isg-ng:ieg+1+ng, jsg-ng:jeg+1+ng,1:2),
size(p_grid( isg-ng:ieg+1+ng, jsg-ng:jeg+1+ng,1:2)), &
1349 atm%parent_grid%pelist(1))
1353 if ( joffset + floor(
real(1-ng) /
real(refinement) ) < 1-ng .or. &
1354 ioffset + floor(
real(1-ng) /
real(refinement) ) < 1-ng .or. &
1355 joffset + floor(
real(npy+ng) /
real(refinement) ) > Atm%parent_grid%npy+ng .or. &
1356 ioffset + floor(
real(npx+ng) /
real(refinement) ) > Atm%parent_grid%npx+ng ) then
1357 call mpp_error(fatal,
'nested grid lies outside its parent')
1361 jc = joffset + (j-1)/refinement
1362 jmod = mod(j-1,refinement)
1363 if (j-1 < 0 .and. jmod /= 0) jc = jc - 1
1364 if (jmod < 0) jmod = jmod + refinement
1367 ic = ioffset + (i-1)/refinement
1368 imod = mod(i-1,refinement)
1369 if (i-1 < 0 .and. imod /= 0) ic = ic - 1
1370 if (imod < 0) imod = imod + refinement
1372 if (ic+1 > ieg+1 .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1373 print*,
'p_grid:', i, j,
' OUT OF BOUNDS' 1375 print*, isg, ieg, jsg, jeg
1380 q1 = p_grid(ic, jc, 1:2)
1381 q2 = p_grid(ic+1,jc,1:2)
1384 p_grid(ic, jc, 1:2), p_grid(ic, jc+1, 1:2), q1)
1386 p_grid(ic+1, jc, 1:2), p_grid(ic+1, jc+1, 1:2), q2)
1390 grid_global(i,j,:,1) = q1
1393 q1,q2,grid_global(i,j,:,1))
1406 if (grid_global(i,j,1,1) > 2.*pi) grid_global(i,j,1,1) = grid_global(i,j,1,1) - 2.*pi
1407 if (grid_global(i,j,1,1) < 0.) grid_global(i,j,1,1) = grid_global(i,j,1,1) + 2.*pi
1415 call mid_pt_sphere(p_grid(i, j,1:2), p_grid(i+1, j,1:2), p_grid_u(i,j,:))
1421 call mid_pt_sphere(p_grid(i, j,1:2), p_grid(i, j+1,1:2), p_grid_v(i,j,:))
1427 call cell_center2(p_grid(i,j, 1:2), p_grid(i+1,j, 1:2), &
1428 p_grid(i,j+1,1:2), p_grid(i+1,j+1,1:2), &
1435 call mpp_broadcast(grid_global(1-ng:npx+ng, 1-ng:npy+ng ,:,1), &
1436 ((npx+ng)-(1-ng)+1)*((npy+ng)-(1-ng)+1)*ndims, mpp_root_pe() )
1437 call mpp_broadcast( p_ind(1-ng:npx+ng, 1-ng:npy+ng ,1:4), &
1438 ((npx+ng)-(1-ng)+1)*((npy+ng)-(1-ng)+1)*4, mpp_root_pe() )
1439 call mpp_broadcast( pa_grid( isg:ieg , jsg:jeg , :), &
1440 ((ieg-isg+1))*(jeg-jsg+1)*ndims, mpp_root_pe())
1441 call mpp_broadcast( p_grid_u( isg:ieg , jsg:jeg+1, :), &
1442 (ieg-isg+1)*(jeg-jsg+2)*ndims, mpp_root_pe())
1443 call mpp_broadcast( p_grid_v( isg:ieg+1, jsg:jeg , :), &
1444 (ieg-isg+2)*(jeg-jsg+1)*ndims, mpp_root_pe())
1446 call mpp_broadcast( p_grid(isg-ng:ieg+ng+1, jsg-ng:jeg+ng+1, :), &
1447 (ieg-isg+2+2*ng)*(jeg-jsg+2+2*ng)*ndims, mpp_root_pe() )
1452 grid(i,j,n) = grid_global(i,j,n,1)
1466 if (imod < refinement/2)
then 1471 ind_h(i,j,1) = ic - 1
1476 if (jmod < refinement/2)
then 1477 ind_h(i,j,2) = jc - 1
1520 if (imod < refinement/2)
then 1524 ind_u(i,j,1) = ic - 1
1532 ind_u(i,j,4) = p_ind(i,j,4)
1550 if (jmod < refinement/2)
then 1551 ind_v(i,j,2) = jc - 1
1558 ind_v(i,j,3) = p_ind(i,j,3)
1564 agrid(:,:,:) = -1.e25
1569 grid(i,j+1,1:2), grid(i+1,j+1,1:2), &
1574 call mpp_update_domains( agrid, atm%domain, position=center, complete=.true. )
1599 dist1 =
dist2side_latlon(pa_grid(ic,jc,:) ,pa_grid(ic,jc+1,:),agrid(i,j,:))
1600 dist2 =
dist2side_latlon(pa_grid(ic,jc+1,:) ,pa_grid(ic+1,jc+1,:),agrid(i,j,:))
1601 dist3 =
dist2side_latlon(pa_grid(ic+1,jc+1,:),pa_grid(ic+1,jc,:),agrid(i,j,:))
1602 dist4 =
dist2side_latlon(pa_grid(ic,jc,:) ,pa_grid(ic+1,jc,:),agrid(i,j,:))
1604 wt_h(i,j,1)=dist2*dist3
1605 wt_h(i,j,2)=dist3*dist4
1606 wt_h(i,j,3)=dist4*dist1
1607 wt_h(i,j,4)=dist1*dist2
1609 sum=wt_h(i,j,1)+wt_h(i,j,2)+wt_h(i,j,3)+wt_h(i,j,4)
1610 wt_h(i,j,:)=wt_h(i,j,:)/sum
1626 dist2 =
dist2side_latlon(p_grid(ic,jc+1,:), p_grid(ic+1,jc+1,:), grid(i,j,:))
1627 dist3 =
dist2side_latlon(p_grid(ic+1,jc+1,:), p_grid(ic+1,jc,:), grid(i,j,:))
1630 wt_b(i,j,1)=dist2*dist3
1631 wt_b(i,j,2)=dist3*dist4
1632 wt_b(i,j,3)=dist4*dist1
1633 wt_b(i,j,4)=dist1*dist2
1635 sum=wt_b(i,j,1)+wt_b(i,j,2)+wt_b(i,j,3)+wt_b(i,j,4)
1636 wt_b(i,j,:)=wt_b(i,j,:)/sum
1644 allocate(c_grid_u(isd:ied+1,jsd:jed,2))
1645 allocate(c_grid_v(isd:ied,jsd:jed+1,2))
1649 call mid_pt_sphere(grid(i, j,1:2), grid(i, j+1,1:2), c_grid_u(i,j,:))
1655 call mid_pt_sphere(grid(i,j ,1:2), grid(i+1,j ,1:2), c_grid_v(i,j,:))
1683 if (ic+1 > ieg .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1684 print*,
'IND_U ', i, j,
' OUT OF BOUNDS' 1686 print*, isg, ieg, jsg, jeg
1695 wt_u(i,j,1) = 1. ; wt_u(i,j,2) = 0.
1697 dist1 =
dist2side_latlon(p_grid_u(ic,jc,:), p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1698 dist2 =
dist2side_latlon(p_grid_u(ic,jc+1,:), p_grid_u(ic+1,jc+1,:), c_grid_v(i,j,:))
1700 wt_u(i,j,1) = dist2/sum
1701 wt_u(i,j,2) = dist1/sum
1705 dist1 =
dist2side_latlon(p_grid_u(ic,jc,:) ,p_grid_u(ic,jc+1,:), c_grid_v(i,j,:))
1706 dist2 =
dist2side_latlon(p_grid_u(ic,jc+1,:) ,p_grid_u(ic+1,jc+1,:),c_grid_v(i,j,:))
1707 dist3 =
dist2side_latlon(p_grid_u(ic+1,jc+1,:),p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1709 dist4 =
dist2side_latlon(p_grid_u(ic,jc,:) ,p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1711 wt_u(i,j,1)=dist2*dist3
1712 wt_u(i,j,2)=dist3*dist4
1713 wt_u(i,j,3)=dist4*dist1
1714 wt_u(i,j,4)=dist1*dist2
1716 sum=wt_u(i,j,1)+wt_u(i,j,2)+wt_u(i,j,3)+wt_u(i,j,4)
1717 wt_u(i,j,:)=wt_u(i,j,:)/sum
1730 if (ic+1 > ieg .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1731 print*,
'IND_V ', i, j,
' OUT OF BOUNDS' 1733 print*, isg, ieg, jsg, jeg
1739 wt_v(i,j,1) = 1. ; wt_v(i,j,4) = 0.
1741 dist1 =
dist2side_latlon(p_grid_v(ic,jc,:), p_grid_v(ic,jc+1,:), c_grid_u(i,j,:))
1742 dist2 =
dist2side_latlon(p_grid_v(ic+1,jc,:), p_grid_v(ic+1,jc+1,:), c_grid_u(i,j,:))
1744 wt_v(i,j,1) = dist2/sum
1745 wt_v(i,j,4) = dist1/sum
1747 wt_v(i,j,2) = 0. ; wt_v(i,j,3) = 0.
1749 dist1 =
dist2side_latlon(p_grid_v(ic,jc,:) ,p_grid_v(ic,jc+1,:), c_grid_u(i,j,:))
1750 dist2 =
dist2side_latlon(p_grid_v(ic,jc+1,:) ,p_grid_v(ic+1,jc+1,:),c_grid_u(i,j,:))
1751 dist3 =
dist2side_latlon(p_grid_v(ic+1,jc+1,:),p_grid_v(ic+1,jc,:), c_grid_u(i,j,:))
1752 dist4 =
dist2side_latlon(p_grid_v(ic,jc,:) ,p_grid_v(ic+1,jc,:), c_grid_u(i,j,:))
1754 wt_v(i,j,1)=dist2*dist3
1755 wt_v(i,j,2)=dist3*dist4
1756 wt_v(i,j,3)=dist4*dist1
1757 wt_v(i,j,4)=dist1*dist2
1759 sum=wt_v(i,j,1)+wt_v(i,j,2)+wt_v(i,j,3)+wt_v(i,j,4)
1760 wt_v(i,j,:)=wt_v(i,j,:)/sum
1766 deallocate(c_grid_u)
1767 deallocate(c_grid_v)
1770 deallocate(p_grid_u)
1771 deallocate(p_grid_v)
1773 if (is_master())
then 1774 if (atm%neststruct%nested)
then 1776 write(*,*)
'NESTED GRID ', atm%grid_number
1777 ic = p_ind(1,1,1) ; jc = p_ind(1,1,1)
1778 write(*,
'(A, 2I5, 4F10.4)')
'SW CORNER: ', ic, jc, grid_global(1,1,:,1)*90./pi
1779 ic = p_ind(1,npy,1) ; jc = p_ind(1,npy,1)
1780 write(*,
'(A, 2I5, 4F10.4)')
'NW CORNER: ', ic, jc, grid_global(1,npy,:,1)*90./pi
1781 ic = p_ind(npx,npy,1) ; jc = p_ind(npx,npy,1)
1782 write(*,
'(A, 2I5, 4F10.4)')
'NE CORNER: ', ic, jc, grid_global(npx,npy,:,1)*90./pi
1783 ic = p_ind(npx,1,1) ; jc = p_ind(npx,1,1)
1784 write(*,
'(A, 2I5, 4F10.4)')
'SE CORNER: ', ic, jc, grid_global(npx,1,:,1)*90./pi
1786 write(*,*)
'PARENT GRID ', atm%parent_grid%grid_number, atm%parent_grid%tile
1787 ic = p_ind(1,1,1) ; jc = p_ind(1,1,1)
1788 write(*,
'(A, 2I5, 4F10.4)')
'SW CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1789 ic = p_ind(1,npy,1) ; jc = p_ind(1,npy,1)
1790 write(*,
'(A, 2I5, 4F10.4)')
'NW CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1791 ic = p_ind(npx,npy,1) ; jc = p_ind(npx,npy,1)
1792 write(*,
'(A, 2I5, 4F10.4)')
'NE CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1793 ic = p_ind(npx,1,1) ; jc = p_ind(npx,1,1)
1794 write(*,
'(A, 2I5, 4F10.4)')
'SE CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1800 subroutine setup_latlon(deglon_start,deglon_stop, deglat_start, deglat_stop, bd )
1802 type(fv_grid_bounds_type),
intent(IN) :: bd
1803 real(kind=R_GRID),
intent(IN) :: deglon_start,deglon_stop, deglat_start, deglat_stop
1804 real(kind=R_GRID) :: lon_start, lat_start, area_j
1805 integer :: is, ie, js, je
1806 integer :: isd, ied, jsd, jed
1818 dl = (deglon_stop-deglon_start)*pi/(180.*(npx-1))
1819 dp = (deglat_stop-deglat_start)*pi/(180.*(npy-1))
1821 lon_start = deglon_start*pi/180.
1822 lat_start = deglat_start*pi/180.
1826 grid(i,j,1) = lon_start +
real(i-1)*dl
1827 grid(i,j,2) = lat_start +
real(j-1)*dp
1833 agrid(i,j,1) = (grid(i,j,1) + grid(i+1,j,1))/2.
1834 agrid(i,j,2) = (grid(i,j,2) + grid(i,j+1,2))/2.
1841 dxc(i,j) = dl*
radius*cos(agrid(is,j,2))
1842 rdxc(i,j) = 1./dxc(i,j)
1848 rdyc(i,j) = 1./dyc(i,j)
1854 dxa(i,j) = dl*
radius*cos(agrid(i,j,2))
1856 rdxa(i,j) = 1./dxa(i,j)
1857 rdya(i,j) = 1./dya(i,j)
1863 dx(i,j) = dl*
radius*cos(grid(i,j,2))
1864 rdx(i,j) = 1./dx(i,j)
1870 rdy(i,j) = 1./dy(i,j)
1875 area_j =
radius*
radius*dl*(sin(grid(is,j+1,2))-sin(grid(is,j,2)))
1878 rarea(i,j) = 1./area_j
1883 area_j =
radius*
radius*dl*(sin(agrid(is,j,2))-sin(agrid(is,j-1,2)))
1885 area_c(i,j) = area_j
1886 rarea_c(i,j) = 1./area_j
1891 area_j =
radius*
radius*dl*(sin(agrid(is,j,2))-sin(agrid(is,j,2)-dp))
1893 area_c(i,j) = area_j
1894 rarea_c(i,j) = 1./area_j
1897 if (jed+1==npy)
then 1899 area_j =
radius*
radius*dl*(sin(agrid(is,j-1,2)+dp)-sin(agrid(is,j-1,2)))
1901 area_c(i,j) = area_j
1902 rarea_c(i,j) = 1./area_j
1905 call mpp_update_domains( area_c, atm%domain, position=corner, complete=.true.)
1923 real(kind=R_GRID) ,
intent(IN) :: x, y, z
1924 real(kind=R_GRID) ,
intent(OUT) :: lon, lat, r
1926 r = sqrt(x*x + y*y + z*z)
1927 if ( (abs(x) + abs(y)) < 1.e-10 )
then 1936 lat = acos(z/r) - pi/2.
1941 real(kind=R_GRID) ,
intent(IN) :: lon, lat, r
1942 real(kind=R_GRID) ,
intent(OUT) :: x, y, z
1944 x = r * cos(lon) * cos(lat)
1945 y = r * sin(lon) * cos(lat)
1955 subroutine rot_3d(axis, x1in, y1in, z1in, angle, x2out, y2out, z2out, degrees, convert)
1956 integer,
intent(IN) :: axis
1957 real(kind=R_GRID) ,
intent(IN) :: x1in, y1in, z1in
1958 real(kind=R_GRID) ,
intent(INOUT) :: angle
1959 real(kind=R_GRID) ,
intent(OUT) :: x2out, y2out, z2out
1960 integer,
intent(IN),
optional :: degrees
1962 integer,
intent(IN),
optional :: convert
1966 real(kind=R_GRID) :: c, s
1967 real(kind=R_GRID) :: x1,y1,z1, x2,y2,z2
1969 if (
present(convert) )
then 1977 if (
present(degrees) )
then 1999 write(*,*)
"Invalid axis: must be 1 for X, 2 for Y, 3 for Z." 2003 if (
present(convert) )
then 2018 real(kind=R_GRID) function get_area_tri(ndims, p_1, p_2, p_3) &
2021 integer,
intent(IN) :: ndims
2022 real(kind=R_GRID) ,
intent(IN) :: p_1(ndims)
2023 real(kind=R_GRID) ,
intent(IN) :: p_2(ndims)
2024 real(kind=R_GRID) ,
intent(IN) :: p_3(ndims)
2026 real(kind=R_GRID) :: anga, angb, angc
2028 if ( ndims==3 )
then 2029 anga = spherical_angle(p_1, p_2, p_3)
2030 angb = spherical_angle(p_2, p_3, p_1)
2031 angc = spherical_angle(p_3, p_1, p_2)
2033 anga =
get_angle(ndims, p_1, p_2, p_3, 1)
2034 angb =
get_angle(ndims, p_2, p_3, p_1, 1)
2035 angc =
get_angle(ndims, p_3, p_1, p_2, 1)
2038 myarea = (anga+angb+angc - pi) *
radius**2
2045 subroutine grid_area(nx, ny, ndims, nregions, nested, gridstruct, domain, bd, regional )
2046 type(fv_grid_bounds_type),
intent(IN) :: bd
2047 integer,
intent(IN) :: nx, ny, ndims, nregions
2048 logical,
intent(IN) :: nested, regional
2049 type(fv_grid_type),
intent(IN),
target :: gridstruct
2050 type(domain2d),
intent(INOUT) :: domain
2052 real(kind=R_GRID) :: p_lL(ndims)
2053 real(kind=R_GRID) :: p_uL(ndims)
2054 real(kind=R_GRID) :: p_lR(ndims)
2055 real(kind=R_GRID) :: p_uR(ndims)
2056 real(kind=R_GRID) :: a1, d1, d2, mydx, mydy, globalarea
2058 real(kind=R_GRID) :: p1(ndims), p2(ndims), p3(ndims), pi1(ndims), pi2(ndims)
2060 real(kind=R_GRID) :: maxarea, minarea
2062 integer :: i,j,n, nreg
2065 real(kind=R_GRID),
allocatable :: p_R8(:,:,:)
2067 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: grid, agrid
2068 integer,
pointer,
dimension(:,:,:) :: iinta, jinta, iintb, jintb
2069 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
2071 integer :: is, ie, js, je
2072 integer :: isd, ied, jsd, jed
2083 grid => gridstruct%grid_64
2084 agrid => gridstruct%agrid_64
2085 iinta => gridstruct%iinta
2086 jinta => gridstruct%jinta
2087 iintb => gridstruct%iintb
2088 jintb => gridstruct%jintb
2090 area => gridstruct%area_64
2091 area_c => gridstruct%area_c_64
2093 if (nested .or. regional) nh = ng
2102 if ( gridstruct%stretched_grid .or. nested )
then 2103 p_ll(n) = grid(i ,j ,n)
2104 p_ul(n) = grid(i ,j+1,n)
2105 p_lr(n) = grid(i+1,j ,n)
2106 p_ur(n) = grid(i+1,j+1,n)
2108 p_ll(n) = grid(iinta(1,i,j), jinta(1,i,j), n)
2109 p_ul(n) = grid(iinta(2,i,j), jinta(2,i,j), n)
2110 p_lr(n) = grid(iinta(4,i,j), jinta(4,i,j), n)
2111 p_ur(n) = grid(iinta(3,i,j), jinta(3,i,j), n)
2116 area(i,j) = get_area(p_ll, p_ul, p_lr, p_ur,
radius)
2150 globalarea = mpp_global_sum(domain, area)
2151 maxarea = mpp_global_max(domain, area)
2152 minarea = mpp_global_min(domain, area)
2154 if (is_master())
write(*,209)
'MAX AREA (m*m):', maxarea,
' MIN AREA (m*m):', minarea
2155 if (is_master())
write(*,209)
'GLOBAL AREA (m*m):', globalarea,
' IDEAL GLOBAL AREA (m*m):', 4.0*pi*
radius**2
2156 209
format(a,e21.14,a,e21.14)
2158 if (nested .or. regional)
then 2166 if ( gridstruct%stretched_grid .or. nested )
then 2167 p_ll(n) = agrid(i-1,j-1,n)
2168 p_lr(n) = agrid(i ,j-1,n)
2169 p_ul(n) = agrid(i-1,j ,n)
2170 p_ur(n) = agrid(i ,j ,n)
2172 p_ll(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2173 p_lr(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2174 p_ul(n) = agrid(iintb(4,i,j), jintb(4,i,j), n)
2175 p_ur(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2179 area_c(i,j) = get_area(p_ll, p_ul, p_lr, p_ur,
radius)
2184 if (gridstruct%cubed_sphere .and. .not. (nested .or. regional))
then 2188 if ( (is==1) .and. (js==1) )
then 2190 if ( gridstruct%stretched_grid )
then 2191 p1(n) = agrid(i-1,j ,n)
2192 p2(n) = agrid(i ,j ,n)
2193 p3(n) = agrid(i ,j-1,n)
2195 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2196 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2197 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2205 if ( (ie+1==nx) .and. (js==1) )
then 2207 if ( gridstruct%stretched_grid )
then 2208 p1(n) = agrid(i ,j ,n)
2209 p2(n) = agrid(i-1,j ,n)
2210 p3(n) = agrid(i-1,j-1,n)
2212 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2213 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2214 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2222 if ( (ie+1==nx) .and. (je+1==ny) )
then 2224 if ( gridstruct%stretched_grid )
then 2225 p1(n) = agrid(i-1,j ,n)
2226 p2(n) = agrid(i-1,j-1,n)
2227 p3(n) = agrid(i ,j-1,n)
2229 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2230 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2231 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2239 if ( (is==1) .and. (je+1==ny) )
then 2241 if ( gridstruct%stretched_grid )
then 2242 p1(n) = agrid(i ,j ,n)
2243 p2(n) = agrid(i ,j-1,n)
2244 p3(n) = agrid(i-1,j-1,n)
2246 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2247 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2248 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2261 real(kind=R_GRID) function get_angle(ndims, p1, p2, p3, rad)
result (angle)
2263 integer,
intent(IN) :: ndims
2264 real(kind=R_GRID) ,
intent(IN) :: p1(ndims)
2265 real(kind=R_GRID) ,
intent(IN) :: p2(ndims)
2266 real(kind=R_GRID) ,
intent(IN) :: p3(ndims)
2267 integer,
intent(in),
optional:: rad
2269 real(kind=R_GRID) :: e1(3), e2(3), e3(3)
2271 if (ndims == 2)
then 2276 e1 = p2; e2 = p1; e3 = p3
2280 if (
present(rad) )
then 2281 angle = spherical_angle(e1, e2, e3)
2283 angle =
todeg * spherical_angle(e1, e2, e3)
2289 subroutine mirror_grid(grid_global,ng,npx,npy,ndims,nregions)
2290 integer,
intent(IN) :: ng,npx,npy,ndims,nregions
2291 real(kind=R_GRID) ,
intent(INOUT) :: grid_global(1-ng:npx +ng,1-ng:npy +ng,ndims,1:nregions)
2292 integer :: i,j,n,n1,n2,nreg
2293 real(kind=R_GRID) :: x1,y1,z1, x2,y2,z2, ang
2296 do j=1,ceiling(npy/2.)
2297 do i=1,ceiling(npx/2.)
2299 x1 = 0.25d0 * (abs(grid_global(i ,j ,1,nreg)) + &
2300 abs(grid_global(npx-(i-1),j ,1,nreg)) + &
2301 abs(grid_global(i ,npy-(j-1),1,nreg)) + &
2302 abs(grid_global(npx-(i-1),npy-(j-1),1,nreg)))
2303 grid_global(i ,j ,1,nreg) = sign(x1,grid_global(i ,j ,1,nreg))
2304 grid_global(npx-(i-1),j ,1,nreg) = sign(x1,grid_global(npx-(i-1),j ,1,nreg))
2305 grid_global(i ,npy-(j-1),1,nreg) = sign(x1,grid_global(i ,npy-(j-1),1,nreg))
2306 grid_global(npx-(i-1),npy-(j-1),1,nreg) = sign(x1,grid_global(npx-(i-1),npy-(j-1),1,nreg))
2308 y1 = 0.25d0 * (abs(grid_global(i ,j ,2,nreg)) + &
2309 abs(grid_global(npx-(i-1),j ,2,nreg)) + &
2310 abs(grid_global(i ,npy-(j-1),2,nreg)) + &
2311 abs(grid_global(npx-(i-1),npy-(j-1),2,nreg)))
2312 grid_global(i ,j ,2,nreg) = sign(y1,grid_global(i ,j ,2,nreg))
2313 grid_global(npx-(i-1),j ,2,nreg) = sign(y1,grid_global(npx-(i-1),j ,2,nreg))
2314 grid_global(i ,npy-(j-1),2,nreg) = sign(y1,grid_global(i ,npy-(j-1),2,nreg))
2315 grid_global(npx-(i-1),npy-(j-1),2,nreg) = sign(y1,grid_global(npx-(i-1),npy-(j-1),2,nreg))
2318 if (mod(npx,2) /= 0)
then 2319 if ( (i==1+(npx-1)/2.0d0) )
then 2320 grid_global(i,j ,1,nreg) = 0.0d0
2321 grid_global(i,npy-(j-1),1,nreg) = 0.0d0
2332 x1 = grid_global(i,j,1,1)
2333 y1 = grid_global(i,j,2,1)
2338 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2339 elseif (nreg == 3)
then 2341 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2343 call rot_3d( 1, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2349 if (mod(npx,2) /= 0)
then 2350 if ( (i==1+(npx-1)/2.0d0) .and. (i==j) )
then 2354 if ( (j==1+(npy-1)/2.0d0) .and. (i < 1+(npx-1)/2.0d0) )
then 2357 if ( (j==1+(npy-1)/2.0d0) .and. (i > 1+(npx-1)/2.0d0) )
then 2362 elseif (nreg == 4)
then 2364 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2366 call rot_3d( 1, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2372 if (mod(npx,2) /= 0)
then 2373 if ( (j==1+(npy-1)/2.0d0) )
then 2378 elseif (nreg == 5)
then 2380 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2382 call rot_3d( 2, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2386 elseif (nreg == 6)
then 2388 call rot_3d( 2, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2390 call rot_3d( 3, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2396 if (mod(npx,2) /= 0)
then 2397 if ( (i==1+(npx-1)/2.0d0) .and. (i==j) )
then 2401 if ( (i==1+(npx-1)/2.0d0) .and. (j > 1+(npy-1)/2.0d0) )
then 2404 if ( (i==1+(npx-1)/2.0d0) .and. (j < 1+(npy-1)/2.0d0) )
then 2411 grid_global(i,j,1,nreg) = x2
2412 grid_global(i,j,2,nreg) = y2
subroutine, public mid_pt_sphere(p1, p2, pm)
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...
The module 'sorted_index' sorts cell corner indices in lat-lon space to ensure the same order of oper...
subroutine, public sorted_intb(isd, ied, jsd, jed, is, ie, js, je, npx, npy, cubed_sphere, agrid, iintb, jintb)
The subroutine 'sorted_intb' sorts cell corner indices in latlon space based on grid locations in ind...
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...
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 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...
integer, parameter, public r_grid
The module 'fv_timing' contains FV3 timers.
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, public cell_center2(q1, q2, q3, q4, e2)
subroutine timing_on(blk_name)
The subroutine 'timing_on' starts a timer.
integer, parameter, public ng
The module 'fv_grid_utils' contains routines for setting up and computing grid-related quantities...
subroutine, public sorted_inta(isd, ied, jsd, jed, cubed_sphere, bgrid, iinta, jinta)
The subroutine 'sorted_inta' sorts cell corner indices in latlon space based on grid locations in ind...
subroutine, public gnomonic_grids(grid_type, im, lon, lat)