118 use constants_mod
, only: grav, omega, pi=>pi_8, cnst_radius=>
radius 126 use fv_mp_mod, only: is_master, fill_corners, xdir, ydir
127 use fv_mp_mod, only: mp_gather, mp_bcst, mp_reduce_max, mp_stop, grids_master_procs
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
153 use mpp_mod
, only: mpp_transmit, mpp_recv
156 #include <netcdf.inc> 158 real(kind=R_GRID),
parameter::
radius = cnst_radius
160 real(kind=R_GRID) ,
parameter::
todeg = 180.0d0/pi
161 real(kind=R_GRID) ,
parameter::
torad = pi/180.0d0
162 real(kind=R_GRID) ,
parameter::
missing = 1.d25
175 subroutine read_grid(Atm, grid_file, ndims, nregions, ng)
177 character(len=*),
intent(IN) :: grid_file
178 integer,
intent(IN) :: ndims
179 integer,
intent(IN) :: nregions
180 integer,
intent(IN) :: ng
182 real,
allocatable,
dimension(:,:) :: tmpx, tmpy
183 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: grid
184 character(len=128) :: units =
"" 185 character(len=256) :: atm_mosaic, atm_hgrid, grid_form
186 character(len=1024) :: attvalue
187 integer :: ntiles, i, j, stdunit
188 integer :: isc2, iec2, jsc2, jec2
189 integer :: start(4), nread(4)
190 integer :: is, ie, js, je
191 integer :: isd, ied, jsd, jed
192 integer,
save :: halo=3
202 grid => atm%gridstruct%grid_64
204 if(.not. file_exist(grid_file))
call mpp_error(fatal,
'fv_grid_tools(read_grid): file '// &
205 trim(grid_file)//
' does not exist')
208 if( field_exist(grid_file,
'atm_mosaic_file') .OR. field_exist(grid_file,
'gridfiles') )
then 210 write(stdunit,*)
'==>Note from fv_grid_tools_mod(read_grid): read atmosphere grid from mosaic version grid' 212 call mpp_error(fatal,
'fv_grid_tools(read_grid): neither atm_mosaic_file nor gridfiles exists in file ' &
216 if(field_exist(grid_file,
'atm_mosaic_file'))
then 217 call read_data(grid_file,
"atm_mosaic_file", atm_mosaic)
218 atm_mosaic =
"INPUT/"//trim(atm_mosaic)
220 atm_mosaic = trim(grid_file)
223 call get_mosaic_tile_grid(atm_hgrid, atm_mosaic, atm%domain)
226 if( get_global_att_value(atm_hgrid,
"history", attvalue) )
then 227 if( index(attvalue,
"gnomonic_ed") > 0) grid_form =
"gnomonic_ed" 229 if(grid_form .NE.
"gnomonic_ed")
call mpp_error(fatal, &
230 "fv_grid_tools(read_grid): the grid should be 'gnomonic_ed' when reading from grid file, contact developer")
233 ntiles = get_mosaic_ntiles(atm_mosaic)
234 if( .not. atm%gridstruct%bounded_domain)
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%gridstruct%bounded_domain )
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%gridstruct%bounded_domain)
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)
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, tile_coarse)
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
538 integer,
intent(IN) :: tile_coarse(:)
540 real(kind=R_GRID) :: xs(npx,npy)
541 real(kind=R_GRID) :: ys(npx,npy)
543 real(kind=R_GRID) :: dp, dl
544 real(kind=R_GRID) :: x1,x2,y1,y2,z1,z2
545 integer :: i,j,k,n,nreg
548 real(kind=R_GRID) :: p1(3), p2(3), p3(3), p4(3)
549 real(kind=R_GRID) :: dist,dist1,dist2, pa(2), pa1(2), pa2(2), pb(2)
550 real(kind=R_GRID) :: pt(3), pt1(3), pt2(3), pt3(3)
551 real(kind=R_GRID) :: ee1(3), ee2(3)
553 real(kind=R_GRID) :: angN,angM,angAV,ang
554 real(kind=R_GRID) :: aspN,aspM,aspAV,asp
555 real(kind=R_GRID) :: dxN, dxM, dxAV
556 real(kind=R_GRID) :: dx_local, dy_local
558 real(kind=R_GRID) :: vec1(3), vec2(3), vec3(3), vec4(3)
559 real(kind=R_GRID) :: vecAvg(3), vec3a(3), vec3b(3), vec4a(3), vec4b(3)
560 real(kind=R_GRID) :: xyz1(3), xyz2(3)
563 integer :: ios, ip, jp
568 character(len=80) :: tmpFile
570 real(kind=R_GRID),
dimension(Atm%bd%is:Atm%bd%ie) :: sbuffer, nbuffer
571 real(kind=R_GRID),
dimension(Atm%bd%js:Atm%bd%je) :: wbuffer, ebuffer
573 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: agrid, grid
574 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
576 real(kind=R_GRID),
pointer,
dimension(:,:) :: sina, cosa, dx, dy, dxc, dyc, dxa, dya
577 real,
pointer,
dimension(:,:,:) :: e1, e2
579 real,
pointer,
dimension(:,:) :: rarea, rarea_c
580 real,
pointer,
dimension(:,:) :: rdx, rdy, rdxc, rdyc, rdxa, rdya
582 integer,
pointer,
dimension(:,:,:) :: iinta, jinta, iintb, jintb
584 real(kind=R_GRID),
pointer,
dimension(:,:,:,:) :: grid_global
586 integer,
pointer :: npx_g, npy_g, ntiles_g, tile
587 logical,
pointer :: sw_corner, se_corner, ne_corner, nw_corner
588 logical,
pointer :: latlon, cubed_sphere, have_south_pole, have_north_pole, stretched_grid
590 type(domain2d),
pointer :: domain
591 integer :: is, ie, js, je
592 integer :: isd, ied, jsd, jed
593 integer :: istart, iend, jstart, jend
605 agrid => atm%gridstruct%agrid_64
606 grid => atm%gridstruct%grid_64
608 area => atm%gridstruct%area_64
609 area_c => atm%gridstruct%area_c_64
610 rarea => atm%gridstruct%rarea
611 rarea_c => atm%gridstruct%rarea_c
613 sina => atm%gridstruct%sina_64
614 cosa => atm%gridstruct%cosa_64
615 dx => atm%gridstruct%dx_64
616 dy => atm%gridstruct%dy_64
617 dxc => atm%gridstruct%dxc_64
618 dyc => atm%gridstruct%dyc_64
619 dxa => atm%gridstruct%dxa_64
620 dya => atm%gridstruct%dya_64
621 rdx => atm%gridstruct%rdx
622 rdy => atm%gridstruct%rdy
623 rdxc => atm%gridstruct%rdxc
624 rdyc => atm%gridstruct%rdyc
625 rdxa => atm%gridstruct%rdxa
626 rdya => atm%gridstruct%rdya
627 e1 => atm%gridstruct%e1
628 e2 => atm%gridstruct%e2
630 if (atm%neststruct%nested .or. any(atm%neststruct%child_grids))
then 631 grid_global => atm%grid_global
632 else if( trim(grid_file) .EQ.
'Inline')
then 633 allocate(grid_global(1-ng:npx +ng,1-ng:npy +ng,ndims,1:nregions))
636 iinta => atm%gridstruct%iinta
637 jinta => atm%gridstruct%jinta
638 iintb => atm%gridstruct%iintb
639 jintb => atm%gridstruct%jintb
640 npx_g => atm%gridstruct%npx_g
641 npy_g => atm%gridstruct%npy_g
642 ntiles_g => atm%gridstruct%ntiles_g
643 sw_corner => atm%gridstruct%sw_corner
644 se_corner => atm%gridstruct%se_corner
645 ne_corner => atm%gridstruct%ne_corner
646 nw_corner => atm%gridstruct%nw_corner
647 latlon => atm%gridstruct%latlon
648 cubed_sphere => atm%gridstruct%cubed_sphere
649 have_south_pole => atm%gridstruct%have_south_pole
650 have_north_pole => atm%gridstruct%have_north_pole
651 stretched_grid => atm%gridstruct%stretched_grid
653 tile => atm%tile_of_mosaic
661 cubed_sphere = .false.
663 if ( (atm%flagstruct%do_schmidt .or. atm%flagstruct%do_cube_transform) .and. abs(atm%flagstruct%stretch_fac-1.) > 1.e-5 )
then 664 stretched_grid = .true.
665 if (atm%flagstruct%do_schmidt .and. atm%flagstruct%do_cube_transform)
then 666 call mpp_error(fatal,
' Cannot set both do_schmidt and do_cube_transform to .true.')
670 if (atm%flagstruct%grid_type>3)
then 671 if (atm%flagstruct%grid_type == 4)
then 672 call setup_cartesian(npx, npy, atm%flagstruct%dx_const, atm%flagstruct%dy_const, &
673 atm%flagstruct%deglat, atm%bd)
675 call mpp_error(fatal,
'init_grid: unsupported grid type')
679 cubed_sphere = .true.
681 if (atm%neststruct%nested)
then 686 if(trim(grid_file) .NE.
'Inline')
then 687 call read_grid(atm, grid_file, ndims, nregions, ng)
689 if (atm%flagstruct%grid_type>=0)
call gnomonic_grids(atm%flagstruct%grid_type, npx-1, xs, ys)
690 if (is_master())
then 691 if (atm%flagstruct%grid_type>=0)
then 694 grid_global(i,j,1,1) = xs(i,j)
695 grid_global(i,j,2,1) = ys(i,j)
707 if ( .not. ( atm%flagstruct%do_schmidt .or. atm%flagstruct%do_cube_transform) .and. (atm%flagstruct%shift_fac)>1.e-4 ) &
708 grid_global(i,j,1,n) = grid_global(i,j,1,n) - pi/atm%flagstruct%shift_fac
710 if ( grid_global(i,j,1,n) < 0. ) &
711 grid_global(i,j,1,n) = grid_global(i,j,1,n) + 2.*pi
712 if (abs(grid_global(i,j,1,1)) < 1.d-10) grid_global(i,j,1,1) = 0.0
713 if (abs(grid_global(i,j,2,1)) < 1.d-10) grid_global(i,j,2,1) = 0.0
718 call mpp_error(fatal,
"fv_grid_tools: reading of ASCII grid files no longer supported")
721 grid_global( 1,1:npy,:,2)=grid_global(npx,1:npy,:,1)
722 grid_global( 1,1:npy,:,3)=grid_global(npx:1:-1,npy,:,1)
723 grid_global(1:npx,npy,:,5)=grid_global(1,npy:1:-1,:,1)
724 grid_global(1:npx,npy,:,6)=grid_global(1:npx,1,:,1)
726 grid_global(1:npx, 1,:,3)=grid_global(1:npx,npy,:,2)
727 grid_global(1:npx, 1,:,4)=grid_global(npx,npy:1:-1,:,2)
728 grid_global(npx,1:npy,:,6)=grid_global(npx:1:-1,1,:,2)
730 grid_global( 1,1:npy,:,4)=grid_global(npx,1:npy,:,3)
731 grid_global( 1,1:npy,:,5)=grid_global(npx:1:-1,npy,:,3)
733 grid_global(npx,1:npy,:,3)=grid_global(1,1:npy,:,4)
734 grid_global(1:npx, 1,:,5)=grid_global(1:npx,npy,:,4)
735 grid_global(1:npx, 1,:,6)=grid_global(npx,npy:1:-1,:,4)
737 grid_global( 1,1:npy,:,6)=grid_global(npx,1:npy,:,5)
742 if ( atm%flagstruct%do_schmidt )
then 745 atm%flagstruct%target_lon, atm%flagstruct%target_lat, &
746 n, grid_global(1:npx,1:npy,1,n), grid_global(1:npx,1:npy,2,n))
748 elseif (atm%flagstruct%do_cube_transform)
then 751 atm%flagstruct%target_lon, atm%flagstruct%target_lat, &
752 n, grid_global(1:npx,1:npy,1,n), grid_global(1:npx,1:npy,2,n))
756 call mpp_broadcast(grid_global,
size(grid_global), mpp_root_pe())
761 grid(i,j,n) = grid_global(i,j,n,tile)
769 call mpp_update_domains( grid, atm%domain, position=corner)
770 if (.not. (atm%gridstruct%bounded_domain))
then 771 call fill_corners(grid(:,:,1), npx, npy, fill=xdir, bgrid=.true.)
772 call fill_corners(grid(:,:,2), npx, npy, fill=xdir, bgrid=.true.)
776 if( .not. atm%gridstruct%bounded_domain)
then 788 do j = jstart, jend+1
792 p2(1) = grid(i+1,j,1)
793 p2(2) = grid(i+1,j,2)
797 if( stretched_grid .or. atm%gridstruct%bounded_domain )
then 799 do i = istart, iend+1
802 p2(1) = grid(i,j+1,1)
803 p2(2) = grid(i,j+1,2)
808 call get_symmetry(dx(is:ie,js:je+1), dy(is:ie+1,js:je), 0, 1, atm%layout(1), atm%layout(2), &
809 atm%domain, atm%tile_of_mosaic, atm%gridstruct%npx_g, atm%bd)
812 call mpp_get_boundary( dy, dx, atm%domain, ebufferx=ebuffer, wbufferx=wbuffer, sbuffery=sbuffer, nbuffery=nbuffer,&
813 flags=scalar_pair+xupdate, gridtype=cgrid_ne_param)
814 if( .not. atm%gridstruct%bounded_domain )
then 815 if(is == 1 .AND. mod(tile,2) .NE. 0)
then 816 dy(is, js:je) = wbuffer(js:je)
819 dy(ie+1, js:je) = ebuffer(js:je)
823 call mpp_update_domains( dy, dx, atm%domain, flags=scalar_pair, &
824 gridtype=cgrid_ne_param, complete=.true.)
825 if (cubed_sphere .and. (.not. (atm%gridstruct%bounded_domain)))
then 826 call fill_corners(dx, dy, npx, npy, dgrid=.true.)
829 if( .not. stretched_grid ) &
830 call sorted_inta(isd, ied, jsd, jed, cubed_sphere, grid, iinta, jinta)
832 agrid(:,:,:) = -1.e25
838 if ( stretched_grid )
then 840 grid(i,j+1,1:2), grid(i+1,j+1,1:2), &
843 call cell_center2(grid(iinta(1,i,j),jinta(1,i,j),1:2), &
844 grid(iinta(2,i,j),jinta(2,i,j),1:2), &
845 grid(iinta(3,i,j),jinta(3,i,j),1:2), &
846 grid(iinta(4,i,j),jinta(4,i,j),1:2), &
852 call mpp_update_domains( agrid, atm%domain, position=center, complete=.true. )
853 if (.not. (atm%gridstruct%bounded_domain))
then 854 call fill_corners(agrid(:,:,1), npx, npy, xdir, agrid=.true.)
855 call fill_corners(agrid(:,:,2), npx, npy, ydir, agrid=.true.)
870 if (cubed_sphere .and. (.not. (atm%gridstruct%bounded_domain)))
then 871 call fill_corners(dxa, dya, npx, npy, agrid=.true.)
885 dxc(isd,j) = dxc(isd+1,j)
886 dxc(ied+1,j) = dxc(ied,j)
900 dyc(i,jsd) = dyc(i,jsd+1)
901 dyc(i,jed+1) = dyc(i,jed)
905 if( .not. stretched_grid ) &
906 call sorted_intb(isd, ied, jsd, jed, is, ie, js, je, npx, npy, &
907 cubed_sphere, agrid, iintb, jintb)
909 call grid_area( npx, npy, ndims, nregions, atm%gridstruct%bounded_domain, atm%gridstruct, atm%domain, atm%bd )
915 if ( .not. stretched_grid .and. (.not. (atm%gridstruct%bounded_domain)))
then 922 p2(1:2) = agrid(i,j-1,1:2)
923 p3(1:2) = agrid(i,j, 1:2)
928 p2(1:2) = agrid(i,j,1:2)
932 if ( (ie+1)==npx )
then 935 p1(1:2) = agrid(i-1,j-1,1:2)
938 p4(1:2) = agrid(i-1,j,1:2)
942 p1(1:2) = agrid(i-1,j,1:2)
952 p3(1:2) = agrid(i, j,1:2)
953 p4(1:2) = agrid(i-1,j,1:2)
958 p2(1:2) = agrid(i,j,1:2)
962 if ( (je+1)==npy )
then 965 p1(1:2) = agrid(i-1,j-1,1:2)
966 p2(1:2) = agrid(i ,j-1,1:2)
972 p1(1:2) = agrid(i,j-1,1:2)
978 if ( sw_corner )
then 980 p1(1:2) = grid(i,j,1:2)
982 p3(1:2) = agrid(i,j,1:2)
986 if ( se_corner )
then 989 p2(1:2) = grid(i,j,1:2)
991 p4(1:2) = agrid(i,j,1:2)
994 if ( ne_corner )
then 996 p1(1:2) = agrid(i-1,j-1,1:2)
998 p3(1:2) = grid(i,j,1:2)
1002 if ( nw_corner )
then 1005 p2(1:2) = agrid(i,j-1,1:2)
1007 p4(1:2) = grid(i,j,1:2)
1013 call mpp_update_domains( dxc, dyc, atm%domain, flags=scalar_pair, &
1014 gridtype=cgrid_ne_param, complete=.true.)
1015 if (cubed_sphere .and. (.not. (atm%gridstruct%bounded_domain)))
then 1016 call fill_corners(dxc, dyc, npx, npy, cgrid=.true.)
1019 call mpp_update_domains( area, atm%domain, complete=.true. )
1023 if (atm%gridstruct%bounded_domain)
then 1026 area_c(isd,j) = area_c(isd+1,j)
1028 if (js == 1) area_c(isd,jsd) = area_c(isd+1,jsd+1)
1029 if (js == npy-1) area_c(isd,jed+1) = area_c(isd+1,jed)
1031 if (ie == npx-1)
then 1033 area_c(ied+1,j) = area_c(ied,j)
1035 if (js == 1) area_c(ied+1,jsd) = area_c(ied,jsd+1)
1036 if (js == npy-1) area_c(ied+1,jed+1) = area_c(ied,jed)
1040 area_c(i,jsd) = area_c(i,jsd+1)
1043 if (je == npy-1)
then 1045 area_c(i,jed+1) = area_c(i,jed)
1050 call mpp_update_domains( area_c, atm%domain, position=corner, complete=.true.)
1053 if (cubed_sphere .and. (.not. (atm%gridstruct%bounded_domain)))
then 1055 call fill_corners(area_c, npx, npy, fill=xdir, bgrid=.true.)
1060 rdx(i,j) = 1.0/dx(i,j)
1065 rdy(i,j) = 1.0/dy(i,j)
1070 rdxc(i,j) = 1.0/dxc(i,j)
1075 rdyc(i,j) = 1.0/dyc(i,j)
1080 rarea(i,j) = 1.0/area(i,j)
1081 rdxa(i,j) = 1./dxa(i,j)
1082 rdya(i,j) = 1./dya(i,j)
1087 rarea_c(i,j) = 1.0/area_c(i,j)
1091 200
format(a,f9.2,a,f9.2,a,f9.2)
1092 201
format(a,f9.2,a,f9.2,a,f9.2,a,f9.2)
1093 202
format(a,a,i4.4,a,i4.4,a)
1108 if(i>ceiling(npx/2.) .OR. j>ceiling(npy/2.)) cycle
1109 ang =
get_angle(2, grid(i,j+1,1:2), grid(i,j,1:2), grid(i+1,j,1:2))
1110 ang = abs(90.0 - ang)
1112 if ( (i==1) .and. (j==1) )
then 1115 angm = max(angm,ang)
1116 angn = min(angn,ang)
1122 dxav = dxav + 0.5 * (dx_local + dy_local)
1123 dxm = max(dxm,dx_local)
1124 dxm = max(dxm,dy_local)
1125 dxn = min(dxn,dx_local)
1126 dxn = min(dxn,dy_local)
1128 asp = abs(dx_local/dy_local)
1129 if (asp < 1.0) asp = 1.0/asp
1131 aspm = max(aspm,asp)
1132 aspn = min(aspn,asp)
1146 if( is_master() )
then 1148 angav = angav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) - 1 )
1149 dxav = dxav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) )
1150 aspav = aspav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) )
1153 write(*,*)
' REDUCED EARTH: Radius is ',
radius,
', omega is ', omega
1155 write(*,* )
' Cubed-Sphere Grid Stats : ', npx,
'x',npy,
'x',nregions
1156 print*, dxn, dxm, dxav, dxn, dxm
1157 write(*,201)
' Grid Length : min: ', dxn,
' max: ', dxm,
' avg: ', dxav,
' min/max: ',dxn/dxm
1158 write(*,200)
' Deviation from Orthogonal : min: ',angn,
' max: ',angm,
' avg: ',angav
1159 write(*,200)
' Aspect Ratio : min: ',aspn,
' max: ',aspm,
' avg: ',aspav
1166 do n=1,
size(atm%neststruct%child_grids)
1167 if (atm%neststruct%child_grids(n) .and. is_master())
then 1169 if (ntiles_g > 1)
then 1173 call mpp_send(grid_global(:,:,:,tile_coarse(n)), &
1174 size(grid_global)/atm%flagstruct%ntiles,grids_master_procs(n))
1176 call mpp_send(grid_global(:,:,:,1),
size(grid_global),grids_master_procs(n))
1178 call mpp_sync_self()
1182 if (atm%neststruct%nested .or. any(atm%neststruct%child_grids))
then 1183 nullify(grid_global)
1184 else if( trim(grid_file) .EQ.
'Inline')
then 1185 deallocate(grid_global)
1225 nullify(cubed_sphere)
1226 nullify(have_south_pole)
1227 nullify(have_north_pole)
1228 nullify(stretched_grid)
1239 integer,
intent(in):: npx, npy
1240 real(kind=R_GRID),
intent(IN) :: dx_const, dy_const, deglat
1241 real(kind=R_GRID) lat_rad, lon_rad, domain_rad
1243 integer :: is, ie, js, je
1244 integer :: isd, ied, jsd, jed
1256 lat_rad = deglat * pi/180.
1260 rdx(:,:) = 1./dx_const
1262 rdy(:,:) = 1./dy_const
1265 rdxc(:,:) = 1./dx_const
1267 rdyc(:,:) = 1./dy_const
1270 rdxa(:,:) = 1./dx_const
1272 rdya(:,:) = 1./dy_const
1274 area(:,:) = dx_const*dy_const
1275 rarea(:,:) = 1./(dx_const*dy_const)
1277 area_c(:,:) = dx_const*dy_const
1278 rarea_c(:,:) = 1./(dx_const*dy_const)
1281 do j=max(1,jsd),min(jed,npy)
1282 do i=max(1,isd),min(ied,npx)
1283 grid(i,j,1) = lon_rad - 0.5*domain_rad +
real(i-1)/
real(npx-1)*domain_rad
1284 grid(i,j,2) = lat_rad - 0.5*domain_rad +
real(j-1)/
real(npy-1)*domain_rad
1288 agrid(:,:,1) = lon_rad
1289 agrid(:,:,2) = lat_rad
1323 integer :: isd_p, ied_p, jsd_p, jed_p
1324 integer :: isg, ieg, jsg, jeg
1325 integer :: ic, jc, imod, jmod
1328 real(kind=R_GRID),
allocatable,
dimension(:,:,:) :: p_grid_u, p_grid_v, pa_grid, p_grid, c_grid_u, c_grid_v
1329 integer :: p_ind(1-ng:npx +ng,1-ng:npy +ng,4)
1334 real(kind=R_GRID) sum
1335 real(kind=R_GRID) :: dist1, dist2, dist3, dist4
1336 real(kind=R_GRID),
dimension(2) :: q1, q2
1338 integer,
pointer :: parent_tile, refinement, ioffset, joffset
1339 integer,
pointer,
dimension(:,:,:) :: ind_h, ind_u, ind_v
1340 real,
pointer,
dimension(:,:,:) :: wt_h, wt_u, wt_v
1342 integer,
pointer,
dimension(:,:,:) :: ind_b
1343 real,
pointer,
dimension(:,:,:) :: wt_b
1345 integer :: is, ie, js, je
1346 integer :: isd, ied, jsd, jed
1359 parent_tile => atm%neststruct%parent_tile
1360 refinement => atm%neststruct%refinement
1361 ioffset => atm%neststruct%ioffset
1362 joffset => atm%neststruct%joffset
1364 ind_h => atm%neststruct%ind_h
1365 ind_u => atm%neststruct%ind_u
1366 ind_v => atm%neststruct%ind_v
1368 wt_h => atm%neststruct%wt_h
1369 wt_u => atm%neststruct%wt_u
1370 wt_v => atm%neststruct%wt_v
1372 ind_b => atm%neststruct%ind_b
1373 wt_b => atm%neststruct%wt_b
1375 call mpp_get_data_domain( atm%parent_grid%domain, &
1376 isd_p, ied_p, jsd_p, jed_p )
1377 call mpp_get_global_domain( atm%parent_grid%domain, &
1380 allocate(p_grid_u(isg:ieg ,jsg:jeg+1,1:2))
1381 allocate(p_grid_v(isg:ieg+1,jsg:jeg ,1:2))
1382 allocate(pa_grid(isg:ieg,jsg:jeg ,1:2))
1385 allocate(p_grid( isg-ng:ieg+1+ng, jsg-ng:jeg+1+ng,1:2) )
1390 if( is_master() )
then 1392 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)), &
1393 atm%parent_grid%pelist(1))
1400 call mpp_broadcast( p_grid(isg-ng:ieg+ng+1, jsg-ng:jeg+ng+1, :), &
1401 (ieg-isg+2+2*ng)*(jeg-jsg+2+2*ng)*ndims, mpp_root_pe() )
1415 jc = joffset + (j-1)/refinement
1416 jmod = mod(j-1,refinement)
1417 if (j-1 < 0 .and. jmod /= 0) jc = jc - 1
1418 if (jmod < 0) jmod = jmod + refinement
1421 ic = ioffset + (i-1)/refinement
1422 imod = mod(i-1,refinement)
1423 if (i-1 < 0 .and. imod /= 0) ic = ic - 1
1424 if (imod < 0) imod = imod + refinement
1426 if (ic+1 > ieg+1 .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1427 print*,
'p_grid:', i, j,
' OUT OF BOUNDS' 1429 print*, isg, ieg, jsg, jeg
1434 q1 = p_grid(ic, jc, 1:2)
1435 q2 = p_grid(ic+1,jc,1:2)
1438 p_grid(ic, jc, 1:2), p_grid(ic, jc+1, 1:2), q1)
1440 p_grid(ic+1, jc, 1:2), p_grid(ic+1, jc+1, 1:2), q2)
1444 grid_global(i,j,:,1) = q1
1447 q1,q2,grid_global(i,j,:,1))
1460 if (grid_global(i,j,1,1) > 2.*pi) grid_global(i,j,1,1) = grid_global(i,j,1,1) - 2.*pi
1461 if (grid_global(i,j,1,1) < 0.) grid_global(i,j,1,1) = grid_global(i,j,1,1) + 2.*pi
1469 call mid_pt_sphere(p_grid(i, j,1:2), p_grid(i+1, j,1:2), p_grid_u(i,j,:))
1475 call mid_pt_sphere(p_grid(i, j,1:2), p_grid(i, j+1,1:2), p_grid_v(i,j,:))
1481 call cell_center2(p_grid(i,j, 1:2), p_grid(i+1,j, 1:2), &
1482 p_grid(i,j+1,1:2), p_grid(i+1,j+1,1:2), &
1503 grid(i,j,n) = grid_global(i,j,n,1)
1517 if (imod < refinement/2)
then 1522 ind_h(i,j,1) = ic - 1
1527 if (jmod < refinement/2)
then 1528 ind_h(i,j,2) = jc - 1
1569 if (imod < refinement/2)
then 1573 ind_u(i,j,1) = ic - 1
1581 ind_u(i,j,4) = p_ind(i,j,4)
1599 if (jmod < refinement/2)
then 1600 ind_v(i,j,2) = jc - 1
1607 ind_v(i,j,3) = p_ind(i,j,3)
1613 agrid(:,:,:) = -1.e25
1618 grid(i,j+1,1:2), grid(i+1,j+1,1:2), &
1623 call mpp_update_domains( agrid, atm%domain, position=center, complete=.true. )
1648 dist1 =
dist2side_latlon(pa_grid(ic,jc,:) ,pa_grid(ic,jc+1,:),agrid(i,j,:))
1649 dist2 =
dist2side_latlon(pa_grid(ic,jc+1,:) ,pa_grid(ic+1,jc+1,:),agrid(i,j,:))
1650 dist3 =
dist2side_latlon(pa_grid(ic+1,jc+1,:),pa_grid(ic+1,jc,:),agrid(i,j,:))
1651 dist4 =
dist2side_latlon(pa_grid(ic,jc,:) ,pa_grid(ic+1,jc,:),agrid(i,j,:))
1653 wt_h(i,j,1)=dist2*dist3
1654 wt_h(i,j,2)=dist3*dist4
1655 wt_h(i,j,3)=dist4*dist1
1656 wt_h(i,j,4)=dist1*dist2
1658 sum=wt_h(i,j,1)+wt_h(i,j,2)+wt_h(i,j,3)+wt_h(i,j,4)
1659 wt_h(i,j,:)=wt_h(i,j,:)/sum
1675 dist2 =
dist2side_latlon(p_grid(ic,jc+1,:), p_grid(ic+1,jc+1,:), grid(i,j,:))
1676 dist3 =
dist2side_latlon(p_grid(ic+1,jc+1,:), p_grid(ic+1,jc,:), grid(i,j,:))
1679 wt_b(i,j,1)=dist2*dist3
1680 wt_b(i,j,2)=dist3*dist4
1681 wt_b(i,j,3)=dist4*dist1
1682 wt_b(i,j,4)=dist1*dist2
1684 sum=wt_b(i,j,1)+wt_b(i,j,2)+wt_b(i,j,3)+wt_b(i,j,4)
1685 wt_b(i,j,:)=wt_b(i,j,:)/sum
1693 allocate(c_grid_u(isd:ied+1,jsd:jed,2))
1694 allocate(c_grid_v(isd:ied,jsd:jed+1,2))
1698 call mid_pt_sphere(grid(i, j,1:2), grid(i, j+1,1:2), c_grid_u(i,j,:))
1704 call mid_pt_sphere(grid(i,j ,1:2), grid(i+1,j ,1:2), c_grid_v(i,j,:))
1732 if (ic+1 > ieg .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1733 print*,
'IND_U ', i, j,
' OUT OF BOUNDS' 1735 print*, isg, ieg, jsg, jeg
1744 wt_u(i,j,1) = 1. ; wt_u(i,j,2) = 0.
1746 dist1 =
dist2side_latlon(p_grid_u(ic,jc,:), p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1747 dist2 =
dist2side_latlon(p_grid_u(ic,jc+1,:), p_grid_u(ic+1,jc+1,:), c_grid_v(i,j,:))
1749 wt_u(i,j,1) = dist2/sum
1750 wt_u(i,j,2) = dist1/sum
1754 dist1 =
dist2side_latlon(p_grid_u(ic,jc,:) ,p_grid_u(ic,jc+1,:), c_grid_v(i,j,:))
1755 dist2 =
dist2side_latlon(p_grid_u(ic,jc+1,:) ,p_grid_u(ic+1,jc+1,:),c_grid_v(i,j,:))
1756 dist3 =
dist2side_latlon(p_grid_u(ic+1,jc+1,:),p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1758 dist4 =
dist2side_latlon(p_grid_u(ic,jc,:) ,p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1760 wt_u(i,j,1)=dist2*dist3
1761 wt_u(i,j,2)=dist3*dist4
1762 wt_u(i,j,3)=dist4*dist1
1763 wt_u(i,j,4)=dist1*dist2
1765 sum=wt_u(i,j,1)+wt_u(i,j,2)+wt_u(i,j,3)+wt_u(i,j,4)
1766 wt_u(i,j,:)=wt_u(i,j,:)/sum
1779 if (ic+1 > ieg .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1780 print*,
'IND_V ', i, j,
' OUT OF BOUNDS' 1782 print*, isg, ieg, jsg, jeg
1788 wt_v(i,j,1) = 1. ; wt_v(i,j,4) = 0.
1790 dist1 =
dist2side_latlon(p_grid_v(ic,jc,:), p_grid_v(ic,jc+1,:), c_grid_u(i,j,:))
1791 dist2 =
dist2side_latlon(p_grid_v(ic+1,jc,:), p_grid_v(ic+1,jc+1,:), c_grid_u(i,j,:))
1793 wt_v(i,j,1) = dist2/sum
1794 wt_v(i,j,4) = dist1/sum
1796 wt_v(i,j,2) = 0. ; wt_v(i,j,3) = 0.
1798 dist1 =
dist2side_latlon(p_grid_v(ic,jc,:) ,p_grid_v(ic,jc+1,:), c_grid_u(i,j,:))
1799 dist2 =
dist2side_latlon(p_grid_v(ic,jc+1,:) ,p_grid_v(ic+1,jc+1,:),c_grid_u(i,j,:))
1800 dist3 =
dist2side_latlon(p_grid_v(ic+1,jc+1,:),p_grid_v(ic+1,jc,:), c_grid_u(i,j,:))
1801 dist4 =
dist2side_latlon(p_grid_v(ic,jc,:) ,p_grid_v(ic+1,jc,:), c_grid_u(i,j,:))
1803 wt_v(i,j,1)=dist2*dist3
1804 wt_v(i,j,2)=dist3*dist4
1805 wt_v(i,j,3)=dist4*dist1
1806 wt_v(i,j,4)=dist1*dist2
1808 sum=wt_v(i,j,1)+wt_v(i,j,2)+wt_v(i,j,3)+wt_v(i,j,4)
1809 wt_v(i,j,:)=wt_v(i,j,:)/sum
1815 deallocate(c_grid_u)
1816 deallocate(c_grid_v)
1819 deallocate(p_grid_u)
1820 deallocate(p_grid_v)
1822 if (is_master())
then 1823 if (atm%neststruct%nested)
then 1825 write(*,*)
'NESTED GRID ', atm%grid_number
1826 ic = p_ind(1,1,1) ; jc = p_ind(1,1,1)
1827 write(*,
'(A, 2I5, 4F10.4)')
'SW CORNER: ', ic, jc, grid_global(1,1,:,1)*90./pi
1828 ic = p_ind(1,npy,1) ; jc = p_ind(1,npy,1)
1829 write(*,
'(A, 2I5, 4F10.4)')
'NW CORNER: ', ic, jc, grid_global(1,npy,:,1)*90./pi
1830 ic = p_ind(npx,npy,1) ; jc = p_ind(npx,npy,1)
1831 write(*,
'(A, 2I5, 4F10.4)')
'NE CORNER: ', ic, jc, grid_global(npx,npy,:,1)*90./pi
1832 ic = p_ind(npx,1,1) ; jc = p_ind(npx,1,1)
1833 write(*,
'(A, 2I5, 4F10.4)')
'SE CORNER: ', ic, jc, grid_global(npx,1,:,1)*90./pi
1835 write(*,*)
'PARENT GRID ', atm%parent_grid%grid_number, atm%parent_grid%global_tile
1836 ic = p_ind(1,1,1) ; jc = p_ind(1,1,1)
1837 write(*,
'(A, 2I5, 4F10.4)')
'SW CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1838 ic = p_ind(1,npy,1) ; jc = p_ind(1,npy,1)
1839 write(*,
'(A, 2I5, 4F10.4)')
'NW CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1840 ic = p_ind(npx,npy,1) ; jc = p_ind(npx,npy,1)
1841 write(*,
'(A, 2I5, 4F10.4)')
'NE CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1842 ic = p_ind(npx,1,1) ; jc = p_ind(npx,1,1)
1843 write(*,
'(A, 2I5, 4F10.4)')
'SE CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./pi
1849 subroutine setup_latlon(deglon_start,deglon_stop, deglat_start, deglat_stop, bd )
1852 real(kind=R_GRID),
intent(IN) :: deglon_start,deglon_stop, deglat_start, deglat_stop
1853 real(kind=R_GRID) :: lon_start, lat_start, area_j
1854 integer :: is, ie, js, je
1855 integer :: isd, ied, jsd, jed
1867 dl = (deglon_stop-deglon_start)*pi/(180.*(npx-1))
1868 dp = (deglat_stop-deglat_start)*pi/(180.*(npy-1))
1870 lon_start = deglon_start*pi/180.
1871 lat_start = deglat_start*pi/180.
1875 grid(i,j,1) = lon_start +
real(i-1)*dl
1876 grid(i,j,2) = lat_start +
real(j-1)*dp
1882 agrid(i,j,1) = (grid(i,j,1) + grid(i+1,j,1))/2.
1883 agrid(i,j,2) = (grid(i,j,2) + grid(i,j+1,2))/2.
1890 dxc(i,j) = dl*
radius*cos(agrid(is,j,2))
1891 rdxc(i,j) = 1./dxc(i,j)
1897 rdyc(i,j) = 1./dyc(i,j)
1903 dxa(i,j) = dl*
radius*cos(agrid(i,j,2))
1905 rdxa(i,j) = 1./dxa(i,j)
1906 rdya(i,j) = 1./dya(i,j)
1912 dx(i,j) = dl*
radius*cos(grid(i,j,2))
1913 rdx(i,j) = 1./dx(i,j)
1919 rdy(i,j) = 1./dy(i,j)
1924 area_j =
radius*
radius*dl*(sin(grid(is,j+1,2))-sin(grid(is,j,2)))
1927 rarea(i,j) = 1./area_j
1932 area_j =
radius*
radius*dl*(sin(agrid(is,j,2))-sin(agrid(is,j-1,2)))
1934 area_c(i,j) = area_j
1935 rarea_c(i,j) = 1./area_j
1940 area_j =
radius*
radius*dl*(sin(agrid(is,j,2))-sin(agrid(is,j,2)-dp))
1942 area_c(i,j) = area_j
1943 rarea_c(i,j) = 1./area_j
1946 if (jed+1==npy)
then 1948 area_j =
radius*
radius*dl*(sin(agrid(is,j-1,2)+dp)-sin(agrid(is,j-1,2)))
1950 area_c(i,j) = area_j
1951 rarea_c(i,j) = 1./area_j
1954 call mpp_update_domains( area_c, atm%domain, position=corner, complete=.true.)
1972 real(kind=R_GRID) ,
intent(IN) :: x, y, z
1973 real(kind=R_GRID) ,
intent(OUT) :: lon, lat, r
1975 r = sqrt(x*x + y*y + z*z)
1976 if ( (abs(x) + abs(y)) < 1.e-10 )
then 1985 lat = acos(z/r) - pi/2.
1990 real(kind=R_GRID) ,
intent(IN) :: lon, lat, r
1991 real(kind=R_GRID) ,
intent(OUT) :: x, y, z
1993 x = r * cos(lon) * cos(lat)
1994 y = r * sin(lon) * cos(lat)
2004 subroutine rot_3d(axis, x1in, y1in, z1in, angle, x2out, y2out, z2out, degrees, convert)
2005 integer,
intent(IN) :: axis
2006 real(kind=R_GRID) ,
intent(IN) :: x1in, y1in, z1in
2007 real(kind=R_GRID) ,
intent(INOUT) :: angle
2008 real(kind=R_GRID) ,
intent(OUT) :: x2out, y2out, z2out
2009 integer,
intent(IN),
optional :: degrees
2011 integer,
intent(IN),
optional :: convert
2015 real(kind=R_GRID) :: c, s
2016 real(kind=R_GRID) :: x1,y1,z1, x2,y2,z2
2018 if (
present(convert) )
then 2026 if (
present(degrees) )
then 2048 write(*,*)
"Invalid axis: must be 1 for X, 2 for Y, 3 for Z." 2052 if (
present(convert) )
then 2067 real(kind=R_GRID) function get_area_tri(ndims, p_1, p_2, p_3) &
2070 integer,
intent(IN) :: ndims
2071 real(kind=R_GRID) ,
intent(IN) :: p_1(ndims)
2072 real(kind=R_GRID) ,
intent(IN) :: p_2(ndims)
2073 real(kind=R_GRID) ,
intent(IN) :: p_3(ndims)
2075 real(kind=R_GRID) :: angA, angB, angC
2077 if ( ndims==3 )
then 2078 anga = spherical_angle(p_1, p_2, p_3)
2079 angb = spherical_angle(p_2, p_3, p_1)
2080 angc = spherical_angle(p_3, p_1, p_2)
2082 anga =
get_angle(ndims, p_1, p_2, p_3, 1)
2083 angb =
get_angle(ndims, p_2, p_3, p_1, 1)
2084 angc =
get_angle(ndims, p_3, p_1, p_2, 1)
2087 myarea = (anga+angb+angc - pi) *
radius**2
2094 subroutine grid_area(nx, ny, ndims, nregions, bounded_domain, gridstruct, domain, bd )
2096 integer,
intent(IN) :: nx, ny, ndims, nregions
2097 logical,
intent(IN) :: bounded_domain
2099 type(domain2d),
intent(INOUT) :: domain
2101 real(kind=R_GRID) :: p_lL(ndims)
2102 real(kind=R_GRID) :: p_uL(ndims)
2103 real(kind=R_GRID) :: p_lR(ndims)
2104 real(kind=R_GRID) :: p_uR(ndims)
2105 real(kind=R_GRID) :: a1, d1, d2, mydx, mydy, globalarea
2107 real(kind=R_GRID) :: p1(ndims), p2(ndims), p3(ndims), pi1(ndims), pi2(ndims)
2109 real(kind=R_GRID) :: maxarea, minarea
2111 integer :: i,j,n, nreg
2114 real(kind=R_GRID),
allocatable :: p_R8(:,:,:)
2116 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: grid, agrid
2117 integer,
pointer,
dimension(:,:,:) :: iinta, jinta, iintb, jintb
2118 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
2120 integer :: is, ie, js, je
2121 integer :: isd, ied, jsd, jed, ng
2133 grid => gridstruct%grid_64
2134 agrid => gridstruct%agrid_64
2135 iinta => gridstruct%iinta
2136 jinta => gridstruct%jinta
2137 iintb => gridstruct%iintb
2138 jintb => gridstruct%jintb
2140 area => gridstruct%area_64
2141 area_c => gridstruct%area_c_64
2143 if (bounded_domain) nh = ng
2152 if ( gridstruct%stretched_grid .or. bounded_domain )
then 2153 p_ll(n) = grid(i ,j ,n)
2154 p_ul(n) = grid(i ,j+1,n)
2155 p_lr(n) = grid(i+1,j ,n)
2156 p_ur(n) = grid(i+1,j+1,n)
2158 p_ll(n) = grid(iinta(1,i,j), jinta(1,i,j), n)
2159 p_ul(n) = grid(iinta(2,i,j), jinta(2,i,j), n)
2160 p_lr(n) = grid(iinta(4,i,j), jinta(4,i,j), n)
2161 p_ur(n) = grid(iinta(3,i,j), jinta(3,i,j), n)
2166 area(i,j) = get_area(p_ll, p_ul, p_lr, p_ur,
radius)
2200 globalarea = mpp_global_sum(domain, area)
2201 maxarea = mpp_global_max(domain, area)
2202 minarea = mpp_global_min(domain, area)
2204 if (is_master())
write(*,209)
'MAX AREA (m*m):', maxarea,
' MIN AREA (m*m):', minarea
2205 if (is_master())
write(*,209)
'GLOBAL AREA (m*m):', globalarea,
' IDEAL GLOBAL AREA (m*m):', 4.0*pi*
radius**2
2206 209
format(a,e21.14,a,e21.14)
2208 if (bounded_domain)
then 2216 if ( gridstruct%stretched_grid .or. bounded_domain )
then 2217 p_ll(n) = agrid(i-1,j-1,n)
2218 p_lr(n) = agrid(i ,j-1,n)
2219 p_ul(n) = agrid(i-1,j ,n)
2220 p_ur(n) = agrid(i ,j ,n)
2222 p_ll(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2223 p_lr(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2224 p_ul(n) = agrid(iintb(4,i,j), jintb(4,i,j), n)
2225 p_ur(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2229 area_c(i,j) = get_area(p_ll, p_ul, p_lr, p_ur,
radius)
2234 if (gridstruct%cubed_sphere .and. .not. bounded_domain)
then 2238 if ( (is==1) .and. (js==1) )
then 2240 if ( gridstruct%stretched_grid )
then 2241 p1(n) = agrid(i-1,j ,n)
2242 p2(n) = agrid(i ,j ,n)
2243 p3(n) = agrid(i ,j-1,n)
2245 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2246 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2247 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2255 if ( (ie+1==nx) .and. (js==1) )
then 2257 if ( gridstruct%stretched_grid )
then 2258 p1(n) = agrid(i ,j ,n)
2259 p2(n) = agrid(i-1,j ,n)
2260 p3(n) = agrid(i-1,j-1,n)
2262 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2263 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2264 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2272 if ( (ie+1==nx) .and. (je+1==ny) )
then 2274 if ( gridstruct%stretched_grid )
then 2275 p1(n) = agrid(i-1,j ,n)
2276 p2(n) = agrid(i-1,j-1,n)
2277 p3(n) = agrid(i ,j-1,n)
2279 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2280 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2281 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2289 if ( (is==1) .and. (je+1==ny) )
then 2291 if ( gridstruct%stretched_grid )
then 2292 p1(n) = agrid(i ,j ,n)
2293 p2(n) = agrid(i ,j-1,n)
2294 p3(n) = agrid(i-1,j-1,n)
2296 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2297 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2298 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2311 real(kind=R_GRID) function get_angle(ndims, p1, p2, p3, rad)
result (angle)
2313 integer,
intent(IN) :: ndims
2314 real(kind=R_GRID) ,
intent(IN) :: p1(ndims)
2315 real(kind=R_GRID) ,
intent(IN) :: p2(ndims)
2316 real(kind=R_GRID) ,
intent(IN) :: p3(ndims)
2317 integer,
intent(in),
optional:: rad
2319 real(kind=R_GRID) :: e1(3), e2(3), e3(3)
2321 if (ndims == 2)
then 2326 e1 = p2; e2 = p1; e3 = p3
2330 if (
present(rad) )
then 2331 angle = spherical_angle(e1, e2, e3)
2333 angle =
todeg * spherical_angle(e1, e2, e3)
2339 subroutine mirror_grid(grid_global,ng,npx,npy,ndims,nregions)
2340 integer,
intent(IN) :: ng,npx,npy,ndims,nregions
2341 real(kind=R_GRID) ,
intent(INOUT) :: grid_global(1-ng:npx +ng,1-ng:npy +ng,ndims,1:nregions)
2342 integer :: i,j,n,n1,n2,nreg
2343 real(kind=R_GRID) :: x1,y1,z1, x2,y2,z2, ang
2346 do j=1,ceiling(npy/2.)
2347 do i=1,ceiling(npx/2.)
2349 x1 = 0.25d0 * (abs(grid_global(i ,j ,1,nreg)) + &
2350 abs(grid_global(npx-(i-1),j ,1,nreg)) + &
2351 abs(grid_global(i ,npy-(j-1),1,nreg)) + &
2352 abs(grid_global(npx-(i-1),npy-(j-1),1,nreg)))
2353 grid_global(i ,j ,1,nreg) = sign(x1,grid_global(i ,j ,1,nreg))
2354 grid_global(npx-(i-1),j ,1,nreg) = sign(x1,grid_global(npx-(i-1),j ,1,nreg))
2355 grid_global(i ,npy-(j-1),1,nreg) = sign(x1,grid_global(i ,npy-(j-1),1,nreg))
2356 grid_global(npx-(i-1),npy-(j-1),1,nreg) = sign(x1,grid_global(npx-(i-1),npy-(j-1),1,nreg))
2358 y1 = 0.25d0 * (abs(grid_global(i ,j ,2,nreg)) + &
2359 abs(grid_global(npx-(i-1),j ,2,nreg)) + &
2360 abs(grid_global(i ,npy-(j-1),2,nreg)) + &
2361 abs(grid_global(npx-(i-1),npy-(j-1),2,nreg)))
2362 grid_global(i ,j ,2,nreg) = sign(y1,grid_global(i ,j ,2,nreg))
2363 grid_global(npx-(i-1),j ,2,nreg) = sign(y1,grid_global(npx-(i-1),j ,2,nreg))
2364 grid_global(i ,npy-(j-1),2,nreg) = sign(y1,grid_global(i ,npy-(j-1),2,nreg))
2365 grid_global(npx-(i-1),npy-(j-1),2,nreg) = sign(y1,grid_global(npx-(i-1),npy-(j-1),2,nreg))
2368 if (mod(npx,2) /= 0)
then 2369 if ( (i==1+(npx-1)/2.0d0) )
then 2370 grid_global(i,j ,1,nreg) = 0.0d0
2371 grid_global(i,npy-(j-1),1,nreg) = 0.0d0
2382 x1 = grid_global(i,j,1,1)
2383 y1 = grid_global(i,j,2,1)
2388 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2389 elseif (nreg == 3)
then 2391 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2393 call rot_3d( 1, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2399 if (mod(npx,2) /= 0)
then 2400 if ( (i==1+(npx-1)/2.0d0) .and. (i==j) )
then 2404 if ( (j==1+(npy-1)/2.0d0) .and. (i < 1+(npx-1)/2.0d0) )
then 2407 if ( (j==1+(npy-1)/2.0d0) .and. (i > 1+(npx-1)/2.0d0) )
then 2412 elseif (nreg == 4)
then 2414 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2416 call rot_3d( 1, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2422 if (mod(npx,2) /= 0)
then 2423 if ( (j==1+(npy-1)/2.0d0) )
then 2428 elseif (nreg == 5)
then 2430 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2432 call rot_3d( 2, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2436 elseif (nreg == 6)
then 2438 call rot_3d( 2, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2440 call rot_3d( 3, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2446 if (mod(npx,2) /= 0)
then 2447 if ( (i==1+(npx-1)/2.0d0) .and. (i==j) )
then 2451 if ( (i==1+(npx-1)/2.0d0) .and. (j > 1+(npy-1)/2.0d0) )
then 2454 if ( (i==1+(npx-1)/2.0d0) .and. (j < 1+(npy-1)/2.0d0) )
then 2461 grid_global(i,j,1,nreg) = x2
2462 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.
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 cube_transform(c, i1, i2, j1, j2, lon_p, lat_p, n, lon, lat)
subroutine, public gnomonic_grids(grid_type, im, lon, lat)