33 use fv_mp_nlm_mod,
only: mp_gather, mp_bcst, mp_reduce_max, mp_stop
54 use fms_mod,
only: get_mosaic_tile_grid
64 real(kind=R_GRID),
parameter::
radius = cnst_radius
66 real(kind=R_GRID) ,
parameter::
todeg = 180.0d0/
pi 67 real(kind=R_GRID) ,
parameter::
torad =
pi/180.0d0
68 real(kind=R_GRID) ,
parameter::
missing = 1.d25
85 subroutine read_grid(Atm, grid_file, ndims, nregions, ng)
87 type(fv_atmos_type),
intent(inout),
target :: Atm
88 character(len=*),
intent(IN) :: grid_file
89 integer,
intent(IN) :: ndims
90 integer,
intent(IN) :: nregions
91 integer,
intent(IN) :: ng
93 real,
allocatable,
dimension(:,:) :: tmpx, tmpy
94 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: grid
95 character(len=128) :: units =
"" 96 character(len=256) :: atm_mosaic, atm_hgrid, grid_form
97 character(len=1024) :: attvalue
98 integer :: ntiles, i, j, stdunit
99 integer :: isc2, iec2, jsc2, jec2
100 integer :: start(4), nread(4)
101 integer :: is, ie, js, je
102 integer :: isd, ied, jsd, jed
112 grid => atm%gridstruct%grid_64
114 if(.not.
file_exist(grid_file))
call mpp_error(fatal,
'fv_grid_tools(read_grid): file '// &
115 trim(grid_file)//
' does not exist')
120 write(stdunit,*)
'==>Note from fv_grid_tools_nlm_mod(read_grid): read atmosphere grid from mosaic version grid' 122 call mpp_error(fatal,
'fv_grid_tools(read_grid): neither atm_mosaic_file nor gridfiles exists in file ' &
127 call read_data(grid_file,
"atm_mosaic_file", atm_mosaic)
128 atm_mosaic =
"INPUT/"//trim(atm_mosaic)
130 atm_mosaic = trim(grid_file)
133 call get_mosaic_tile_grid(atm_hgrid, atm_mosaic, atm%domain)
137 if( index(attvalue,
"gnomonic_ed") > 0) grid_form =
"gnomonic_ed" 139 if(grid_form .NE.
"gnomonic_ed")
call mpp_error(fatal, &
140 "fv_grid_tools(read_grid): the grid should be 'gnomonic_ed' when reading from grid file, contact developer")
144 if(ntiles .NE. 6)
call mpp_error(fatal, &
145 'fv_grid_tools(read_grid): ntiles should be 6 in mosaic file '//trim(atm_mosaic) )
146 if(nregions .NE. 6)
call mpp_error(fatal, &
147 'fv_grid_tools(read_grid): nregions should be 6 when reading from mosaic file '//trim(grid_file) )
152 isc2 = 2*is-1; iec2 = 2*ie+1
153 jsc2 = 2*js-1; jec2 = 2*je+1
154 allocate(tmpx(isc2:iec2, jsc2:jec2) )
155 allocate(tmpy(isc2:iec2, jsc2:jec2) )
157 start(1) = isc2; nread(1) = iec2 - isc2 + 1
158 start(2) = jsc2; nread(2) = jec2 - jsc2 + 1
159 call read_data(atm_hgrid,
'x', tmpx, start, nread, no_domain=.true.)
160 call read_data(atm_hgrid,
'y', tmpy, start, nread, no_domain=.true.)
163 grid(isd: is-1, jsd:js-1,1:ndims)=0.
164 grid(isd: is-1, je+2:jed+1,1:ndims)=0.
165 grid(ie+2:ied+1,jsd:js-1,1:ndims)=0.
166 grid(ie+2:ied+1,je+2:jed+1,1:ndims)=0.
167 if(len_trim(units) < 6)
call mpp_error(fatal, &
168 "fv_grid_tools_nlm_mod(read_grid): the length of units must be no less than 6")
169 if(units(1:6) ==
'degree')
then 172 grid(i,j,1) = tmpx(2*i-1,2*j-1)*
pi/180.
173 grid(i,j,2) = tmpy(2*i-1,2*j-1)*
pi/180.
176 else if(units(1:6) ==
'radian')
then 179 grid(i,j,1) = tmpx(2*i-1,2*j-1)
180 grid(i,j,2) = tmpy(2*i-1,2*j-1)
184 print*,
'units is ' , trim(units), len_trim(units), mpp_pe()
185 call mpp_error(fatal,
'fv_grid_tools_nlm_mod(read_grid): units must start with degree or radian')
188 deallocate(tmpx, tmpy)
196 subroutine get_symmetry(data_in, data_out, ishift, jshift, npes_x, npes_y, domain, tile, npx_g, bd)
197 type(fv_grid_bounds_type),
intent(IN) :: bd
198 integer,
intent(in) :: ishift, jshift, npes_x, npes_y
199 real(kind=R_GRID),
dimension(bd%is:bd%ie+ishift, bd%js:bd%je+jshift ),
intent(in) :: data_in
200 real(kind=R_GRID),
dimension(bd%is:bd%ie+jshift, bd%js:bd%je+ishift ),
intent(out) :: data_out
201 real(kind=R_GRID),
dimension(:),
allocatable :: send_buffer
202 real(kind=R_GRID),
dimension(:),
allocatable :: recv_buffer
203 integer,
dimension(:),
allocatable :: is_recv, ie_recv, js_recv, je_recv, pe_recv
204 integer,
dimension(:),
allocatable :: is_send, ie_send, js_send, je_send, pe_send
205 integer,
dimension(:),
allocatable :: isl, iel, jsl, jel, pelist, msg1, msg2
206 integer :: msgsize, pos, ntiles, npes_per_tile, npes
207 integer :: send_buf_size, recv_buf_size, buffer_pos
208 integer :: is0, ie0, js0, je0
209 integer :: is1, ie1, js1, je1
210 integer :: is2, ie2, js2, je2
211 integer :: i, j, p, nrecv, nsend, tile_you, is3, ie3, nlist
212 integer :: start_pe, ipos, jpos, from_pe, to_pe
213 type(domain2d) :: domain
214 integer :: tile, npx_g
215 integer :: is, ie, js, je
216 integer :: isd, ied, jsd, jed
229 ntiles = mpp_get_ntile_count(domain)
232 if(ntiles .NE. 6 )
call mpp_error(fatal,
'fv_grid_tools(get_symmetry): ntiles should be 6 ')
233 if(mod(npes,ntiles) /= 0)
call mpp_error(fatal,
'fv_grid_tools(get_symmetry): npes should be divided by ntiles')
234 npes_per_tile = npes/ntiles
237 if(npes_x == npes_y .AND. mod(npx_g-1,npes_x) == 0 )
then 238 msgsize = (ie-is+1+jshift)*(je-js+1+ishift)
240 pos = mod((mpp_pe()-mpp_root_pe()), npes_x*npes_y)
241 start_pe = mpp_pe() - pos
242 ipos = mod(pos, npes_x)
244 from_pe = start_pe + ipos*npes_x + jpos
246 allocate(recv_buffer(msgsize))
247 call mpp_recv(recv_buffer(1), glen=msgsize, from_pe=from_pe, block=.false. )
250 allocate(send_buffer(msgsize))
254 send_buffer(pos) = data_in(i,j)
258 call mpp_send(send_buffer(1), plen=msgsize, to_pe=to_pe)
259 call mpp_sync_self(check=event_recv)
266 data_out(i,j) = recv_buffer(pos)
271 deallocate(send_buffer, recv_buffer)
274 allocate(is_recv(0:npes_per_tile-1), ie_recv(0:npes_per_tile-1))
275 allocate(js_recv(0:npes_per_tile-1), je_recv(0:npes_per_tile-1))
276 allocate(is_send(0:npes_per_tile-1), ie_send(0:npes_per_tile-1))
277 allocate(js_send(0:npes_per_tile-1), je_send(0:npes_per_tile-1))
278 allocate(pe_send(0:npes_per_tile-1), pe_recv(0:npes_per_tile-1))
280 allocate(msg1(0:npes_per_tile-1), msg2(0:npes_per_tile-1))
285 allocate(pelist(0:npes-1))
287 allocate(isl(0:npes-1), iel(0:npes-1), jsl(0:npes-1), jel(0:npes-1) )
298 tile_you = p/(npes_x*npes_y) + 1
299 if(tile_you .NE. tile) cycle
302 is1 = js; ie1 = je + ishift;
303 js1 = is; je1 = ie + jshift;
305 is2 = isl(p); ie2 = iel(p) + ishift;
306 js2 = jsl(p); je2 = jel(p) + jshift;
307 is0 =
max(is1,is2); ie0 =
min(ie1,ie2)
308 js0 =
max(js1,js2); je0 =
min(je1,je2)
310 if(ie0 .GE. is0 .AND. je0 .GE. js0)
then 311 msgsize = (ie0-is0+1)*(je0-js0+1)
312 recv_buf_size = recv_buf_size + msgsize
313 pe_recv(nrecv) = pelist(p)
315 is_recv(nrecv) = js0; ie_recv(nrecv) = je0
316 js_recv(nrecv) = is0; je_recv(nrecv) = ie0
320 msg1(nlist) = msgsize
321 call mpp_recv(msg2(nlist), glen=1, from_pe=pelist(p), block=.false. )
329 tile_you = p/(npes_x*npes_y) + 1
330 if(tile_you .NE. tile) cycle
332 is1 = is; ie1 = ie + ishift;
333 js1 = js; je1 = je + jshift;
335 is2 = jsl(p); ie2 = jel(p) + ishift;
336 js2 = isl(p); je2 = iel(p) + jshift;
337 is0 =
max(is1,is2); ie0 =
min(ie1,ie2)
338 js0 =
max(js1,js2); je0 =
min(je1,je2)
340 if(ie0 .GE. is0 .AND. je0 .GE. js0 )
then 341 msgsize = (ie0-is0+1)*(je0-js0+1)
342 send_buf_size = send_buf_size + msgsize
343 pe_send(nsend) = pelist(p)
344 is_send(nsend) = is0; ie_send(nsend) = ie0
345 js_send(nsend) = js0; je_send(nsend) = je0
353 call mpp_sync_self(check=event_recv)
355 if(msg1(p) .NE. msg2(p))
then 356 call mpp_error(fatal,
"fv_grid_tools_nlm_mod(get_symmetry): mismatch on send and recv size")
360 deallocate(msg1, msg2)
364 allocate(recv_buffer(recv_buf_size))
367 is0 = is_recv(p); ie0 = ie_recv(p)
368 js0 = js_recv(p); je0 = je_recv(p)
369 msgsize = (ie0-is0+1)*(je0-js0+1)
370 call mpp_recv(recv_buffer(buffer_pos+1), glen=msgsize, from_pe=pe_recv(p), block=.false. )
371 buffer_pos = buffer_pos + msgsize
376 allocate(send_buffer(send_buf_size))
378 is0 = is_send(p); ie0 = ie_send(p)
379 js0 = js_send(p); je0 = je_send(p)
380 msgsize = (ie0-is0+1)*(je0-js0+1)
385 send_buffer(pos) = data_in(i,j)
388 call mpp_send(send_buffer(buffer_pos+1), plen=msgsize, to_pe=pe_send(p) )
389 buffer_pos = buffer_pos + msgsize
392 call mpp_sync_self(check=event_recv)
397 is0 = is_recv(p); ie0 = ie_recv(p)
398 js0 = js_recv(p); je0 = je_recv(p)
403 data_out(i,j) = recv_buffer(pos)
409 deallocate(isl, iel, jsl, jel, pelist)
410 deallocate(is_recv, ie_recv, js_recv, je_recv, pe_recv)
411 deallocate(is_send, ie_send, js_send, je_send, pe_send)
412 deallocate(recv_buffer, send_buffer)
417 subroutine init_grid(Atm, grid_name, grid_file, npx, npy, npz, ndims, nregions, ng)
423 character(len=80),
intent(IN) :: grid_name
424 character(len=120),
intent(IN) :: grid_file
425 integer,
intent(IN) :: npx, npy, npz
426 integer,
intent(IN) :: ndims
427 integer,
intent(IN) :: nregions
428 integer,
intent(IN) :: ng
430 real(kind=R_GRID) :: xs(npx,npy)
431 real(kind=R_GRID) :: ys(npx,npy)
433 real(kind=R_GRID) :: dp, dl
434 real(kind=R_GRID) :: x1,x2,y1,y2,z1,z2
435 integer :: i,j,k,n,nreg
438 real(kind=R_GRID) :: p1(3), p2(3), p3(3), p4(3)
439 real(kind=R_GRID) :: dist,dist1,dist2, pa(2), pa1(2), pa2(2), pb(2)
440 real(kind=R_GRID) :: pt(3), pt1(3), pt2(3), pt3(3)
441 real(kind=R_GRID) :: ee1(3), ee2(3)
443 real(kind=R_GRID) :: angn,angm,angav,ang
444 real(kind=R_GRID) :: aspn,aspm,aspav,asp
445 real(kind=R_GRID) :: dxn, dxm, dxav
446 real(kind=R_GRID) :: dx_local, dy_local
448 real(kind=R_GRID) :: vec1(3), vec2(3), vec3(3), vec4(3)
449 real(kind=R_GRID) :: vecavg(3), vec3a(3), vec3b(3), vec4a(3), vec4b(3)
450 real(kind=R_GRID) :: xyz1(3), xyz2(3)
453 integer :: ios,
ip, jp
458 character(len=80) :: tmpfile
460 real(kind=R_GRID),
dimension(Atm%bd%is:Atm%bd%ie) :: sbuffer, nbuffer
461 real(kind=R_GRID),
dimension(Atm%bd%js:Atm%bd%je) :: wbuffer, ebuffer
463 real(kind=R_GRID),
pointer,
dimension(:,:,:) ::
agrid, grid
464 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
466 real(kind=R_GRID),
pointer,
dimension(:,:) :: sina, cosa, dx, dy, dxc, dyc, dxa, dya
467 real,
pointer,
dimension(:,:,:) :: e1, e2
469 real,
pointer,
dimension(:,:) :: rarea, rarea_c
470 real,
pointer,
dimension(:,:) :: rdx, rdy, rdxc, rdyc, rdxa, rdya
472 integer,
pointer,
dimension(:,:,:) :: iinta, jinta, iintb, jintb
474 real(kind=R_GRID),
pointer,
dimension(:,:,:,:) :: grid_global
476 integer,
pointer :: npx_g, npy_g, ntiles_g, tile
477 logical,
pointer :: sw_corner, se_corner, ne_corner, nw_corner
478 logical,
pointer :: latlon, cubed_sphere, have_south_pole, have_north_pole, stretched_grid
481 integer :: is, ie, js, je
482 integer :: isd, ied, jsd, jed
494 agrid => atm%gridstruct%agrid_64
495 grid => atm%gridstruct%grid_64
497 area => atm%gridstruct%area_64
498 area_c => atm%gridstruct%area_c_64
499 rarea => atm%gridstruct%rarea
500 rarea_c => atm%gridstruct%rarea_c
502 sina => atm%gridstruct%sina_64
503 cosa => atm%gridstruct%cosa_64
504 dx => atm%gridstruct%dx_64
505 dy => atm%gridstruct%dy_64
506 dxc => atm%gridstruct%dxc_64
507 dyc => atm%gridstruct%dyc_64
508 dxa => atm%gridstruct%dxa_64
509 dya => atm%gridstruct%dya_64
510 rdx => atm%gridstruct%rdx
511 rdy => atm%gridstruct%rdy
512 rdxc => atm%gridstruct%rdxc
513 rdyc => atm%gridstruct%rdyc
514 rdxa => atm%gridstruct%rdxa
515 rdya => atm%gridstruct%rdya
516 e1 => atm%gridstruct%e1
517 e2 => atm%gridstruct%e2
519 if (atm%neststruct%nested .or. any(atm%neststruct%child_grids))
then 520 grid_global => atm%grid_global
521 else if( trim(grid_file) .NE.
'INPUT/grid_spec.nc')
then 522 allocate(grid_global(1-ng:npx +ng,1-ng:npy +ng,ndims,1:nregions))
525 iinta => atm%gridstruct%iinta
526 jinta => atm%gridstruct%jinta
527 iintb => atm%gridstruct%iintb
528 jintb => atm%gridstruct%jintb
529 npx_g => atm%gridstruct%npx_g
530 npy_g => atm%gridstruct%npy_g
531 ntiles_g => atm%gridstruct%ntiles_g
532 sw_corner => atm%gridstruct%sw_corner
533 se_corner => atm%gridstruct%se_corner
534 ne_corner => atm%gridstruct%ne_corner
535 nw_corner => atm%gridstruct%nw_corner
536 latlon => atm%gridstruct%latlon
537 cubed_sphere => atm%gridstruct%cubed_sphere
538 have_south_pole => atm%gridstruct%have_south_pole
539 have_north_pole => atm%gridstruct%have_north_pole
540 stretched_grid => atm%gridstruct%stretched_grid
550 cubed_sphere = .false.
552 if ( atm%flagstruct%do_schmidt .and. abs(atm%flagstruct%stretch_fac-1.) > 1.e-5 ) stretched_grid = .true.
554 if (atm%flagstruct%grid_type>3)
then 555 if (atm%flagstruct%grid_type == 4)
then 556 call setup_cartesian(npx, npy, atm%flagstruct%dx_const, atm%flagstruct%dy_const, &
557 atm%flagstruct%deglat, atm%bd)
559 call mpp_error(fatal,
'init_grid: unsupported grid type')
563 cubed_sphere = .true.
565 if (atm%neststruct%nested)
then 568 if(trim(grid_file) ==
'INPUT/grid_spec.nc')
then 569 call read_grid(atm, grid_file, ndims, nregions, ng)
572 if (atm%flagstruct%grid_type>=0)
call gnomonic_grids(atm%flagstruct%grid_type, npx-1, xs, ys)
574 if (is_master())
then 576 if (atm%flagstruct%grid_type>=0)
then 579 grid_global(i,j,1,1) = xs(i,j)
580 grid_global(i,j,2,1) = ys(i,j)
592 if ( .not.atm%flagstruct%do_schmidt .and. (atm%flagstruct%shift_fac)>1.e-4 ) &
593 grid_global(i,j,1,n) = grid_global(i,j,1,n) -
pi/atm%flagstruct%shift_fac
595 if ( grid_global(i,j,1,n) < 0. ) &
596 grid_global(i,j,1,n) = grid_global(i,j,1,n) + 2.*
pi 597 if (abs(grid_global(i,j,1,1)) < 1.d-10) grid_global(i,j,1,1) = 0.0
598 if (abs(grid_global(i,j,2,1)) < 1.d-10) grid_global(i,j,2,1) = 0.0
603 call mpp_error(fatal,
"fv_grid_tools: reading of ASCII grid files no longer supported")
606 grid_global( 1,1:npy,:,2)=grid_global(npx,1:npy,:,1)
607 grid_global( 1,1:npy,:,3)=grid_global(npx:1:-1,npy,:,1)
608 grid_global(1:npx,npy,:,5)=grid_global(1,npy:1:-1,:,1)
609 grid_global(1:npx,npy,:,6)=grid_global(1:npx,1,:,1)
611 grid_global(1:npx, 1,:,3)=grid_global(1:npx,npy,:,2)
612 grid_global(1:npx, 1,:,4)=grid_global(npx,npy:1:-1,:,2)
613 grid_global(npx,1:npy,:,6)=grid_global(npx:1:-1,1,:,2)
615 grid_global( 1,1:npy,:,4)=grid_global(npx,1:npy,:,3)
616 grid_global( 1,1:npy,:,5)=grid_global(npx:1:-1,npy,:,3)
618 grid_global(npx,1:npy,:,3)=grid_global(1,1:npy,:,4)
619 grid_global(1:npx, 1,:,5)=grid_global(1:npx,npy,:,4)
620 grid_global(1:npx, 1,:,6)=grid_global(npx,npy:1:-1,:,4)
622 grid_global( 1,1:npy,:,6)=grid_global(npx,1:npy,:,5)
627 if ( atm%flagstruct%do_schmidt )
then 629 call direct_transform(atm%flagstruct%stretch_fac, 1, npx, 1, npy, &
630 atm%flagstruct%target_lon, atm%flagstruct%target_lat, &
631 n, grid_global(1:npx,1:npy,1,n), grid_global(1:npx,1:npy,2,n))
635 call mpp_broadcast(grid_global,
size(grid_global), mpp_root_pe())
640 grid(i,j,n) = grid_global(i,j,n,tile)
649 if (.not. atm%neststruct%nested)
call fill_corners(grid(:,:,1), npx, npy, fill=xdir, bgrid=.true.)
650 if (.not. atm%neststruct%nested)
call fill_corners(grid(:,:,2), npx, npy, fill=xdir, bgrid=.true.)
657 p2(1) = grid(i+1,j,1)
658 p2(2) = grid(i+1,j,2)
659 dx(i,j) = great_circle_dist( p2, p1,
radius )
662 if( stretched_grid )
then 667 p2(1) = grid(i,j+1,1)
668 p2(2) = grid(i,j+1,2)
669 dy(i,j) = great_circle_dist( p2, p1,
radius )
673 call get_symmetry(dx(is:ie,js:je+1), dy(is:ie+1,js:je), 0, 1, atm%layout(1), atm%layout(2), &
674 atm%domain, atm%tile, atm%gridstruct%npx_g, atm%bd)
677 call mpp_get_boundary( dy, dx, atm%domain, ebufferx=ebuffer, wbufferx=wbuffer, sbuffery=sbuffer, nbuffery=nbuffer,&
679 if(is == 1 .AND. mod(tile,2) .NE. 0)
then 680 dy(is, js:je) = wbuffer(js:je)
683 dy(ie+1, js:je) = ebuffer(js:je)
687 gridtype=cgrid_ne_param, complete=.true.)
688 if (cubed_sphere .and. .not. atm%neststruct%nested)
call fill_corners(dx, dy, npx, npy, dgrid=.true.)
690 if( .not. stretched_grid ) &
691 call sorted_inta(isd, ied, jsd, jed, cubed_sphere, grid, iinta, jinta)
693 agrid(:,:,:) = -1.e25
697 if ( stretched_grid )
then 698 call cell_center2(grid(i,j, 1:2), grid(i+1,j, 1:2), &
699 grid(i,j+1,1:2), grid(i+1,j+1,1:2), &
702 call cell_center2(grid(iinta(1,i,j),jinta(1,i,j),1:2), &
703 grid(iinta(2,i,j),jinta(2,i,j),1:2), &
704 grid(iinta(3,i,j),jinta(3,i,j),1:2), &
705 grid(iinta(4,i,j),jinta(4,i,j),1:2), &
712 if (.not. atm%neststruct%nested)
call fill_corners(
agrid(:,:,1), npx, npy, xdir,
agrid=.true.)
713 if (.not. atm%neststruct%nested)
call fill_corners(
agrid(:,:,2), npx, npy, ydir,
agrid=.true.)
719 dxa(i,j) = great_circle_dist( p2, p1,
radius )
723 dya(i,j) = great_circle_dist( p2, p1,
radius )
727 if (cubed_sphere .and. .not. atm%neststruct%nested)
call fill_corners(dxa, dya, npx, npy,
agrid=.true.)
738 dxc(isd,j) = dxc(isd+1,j)
739 dxc(ied+1,j) = dxc(ied,j)
750 dyc(i,jsd) = dyc(i,jsd+1)
751 dyc(i,jed+1) = dyc(i,jed)
755 if( .not. stretched_grid ) &
756 call sorted_intb(isd, ied, jsd, jed, is, ie, js, je, npx, npy, &
757 cubed_sphere,
agrid, iintb, jintb)
759 call grid_area( npx, npy, ndims, nregions, atm%neststruct%nested, atm%gridstruct, atm%domain, atm%bd )
765 if ( .not. stretched_grid .and. .not. atm%neststruct%nested)
then 772 p2(1:2) =
agrid(i,j-1,1:2)
773 p3(1:2) =
agrid(i,j, 1:2)
774 area_c(i,j) = 2.*get_area(p1, p4, p2, p3,
radius)
778 p2(1:2) =
agrid(i,j,1:2)
779 dxc(i,j) = 2.*great_circle_dist( p1, p2,
radius )
782 if ( (ie+1)==npx )
then 785 p1(1:2) =
agrid(i-1,j-1,1:2)
788 p4(1:2) =
agrid(i-1,j,1:2)
789 area_c(i,j) = 2.*get_area(p1, p4, p2, p3,
radius)
792 p1(1:2) =
agrid(i-1,j,1:2)
794 dxc(i,j) = 2.*great_circle_dist( p1, p2,
radius )
802 p3(1:2) =
agrid(i, j,1:2)
803 p4(1:2) =
agrid(i-1,j,1:2)
804 area_c(i,j) = 2.*get_area(p1, p4, p2, p3,
radius)
808 p2(1:2) =
agrid(i,j,1:2)
809 dyc(i,j) = 2.*great_circle_dist( p1, p2,
radius )
812 if ( (je+1)==npy )
then 815 p1(1:2) =
agrid(i-1,j-1,1:2)
816 p2(1:2) =
agrid(i ,j-1,1:2)
819 area_c(i,j) = 2.*get_area(p1, p4, p2, p3,
radius)
822 p1(1:2) =
agrid(i,j-1,1:2)
824 dyc(i,j) = 2.*great_circle_dist( p1, p2,
radius )
828 if ( sw_corner )
then 830 p1(1:2) = grid(i,j,1:2)
832 p3(1:2) =
agrid(i,j,1:2)
834 area_c(i,j) = 3.*get_area(p1, p4, p2, p3,
radius)
836 if ( se_corner )
then 839 p2(1:2) = grid(i,j,1:2)
841 p4(1:2) =
agrid(i,j,1:2)
842 area_c(i,j) = 3.*get_area(p1, p4, p2, p3,
radius)
844 if ( ne_corner )
then 846 p1(1:2) =
agrid(i-1,j-1,1:2)
848 p3(1:2) = grid(i,j,1:2)
850 area_c(i,j) = 3.*get_area(p1, p4, p2, p3,
radius)
852 if ( nw_corner )
then 855 p2(1:2) =
agrid(i,j-1,1:2)
857 p4(1:2) = grid(i,j,1:2)
858 area_c(i,j) = 3.*get_area(p1, p4, p2, p3,
radius)
864 gridtype=cgrid_ne_param, complete=.true.)
865 if (cubed_sphere .and. .not. atm%neststruct%nested)
call fill_corners(dxc, dyc, npx, npy, cgrid=.true.)
871 if (atm%neststruct%nested)
then 874 area_c(isd,j) = area_c(isd+1,j)
876 if (js == 1) area_c(isd,jsd) = area_c(isd+1,jsd+1)
877 if (js == npy-1) area_c(isd,jed+1) = area_c(isd+1,jed)
879 if (ie == npx-1)
then 881 area_c(ied+1,j) = area_c(ied,j)
883 if (js == 1) area_c(ied+1,jsd) = area_c(ied,jsd+1)
884 if (js == npy-1) area_c(ied+1,jed+1) = area_c(ied,jed)
888 area_c(i,jsd) = area_c(i,jsd+1)
891 if (je == npy-1)
then 893 area_c(i,jed+1) = area_c(i,jed)
901 if (cubed_sphere .and. .not. atm%neststruct%nested)
then 902 call fill_ghost(area, npx, npy, -big_number, atm%bd)
903 call fill_corners(area_c, npx, npy, fill=xdir, bgrid=.true.)
908 rdx(i,j) = 1.0/dx(i,j)
913 rdy(i,j) = 1.0/dy(i,j)
918 rdxc(i,j) = 1.0/dxc(i,j)
923 rdyc(i,j) = 1.0/dyc(i,j)
928 rarea(i,j) = 1.0/area(i,j)
929 rdxa(i,j) = 1./dxa(i,j)
930 rdya(i,j) = 1./dya(i,j)
935 rarea_c(i,j) = 1.0/area_c(i,j)
939 200
format(a,f9.2,a,f9.2,a,f9.2)
940 201
format(a,f9.2,a,f9.2,a,f9.2,a,f9.2)
941 202
format(a,a,i4.4,a,i4.4,a)
956 if(i>ceiling(npx/2.) .OR. j>ceiling(npy/2.)) cycle
957 ang =
get_angle(2, grid(i,j+1,1:2), grid(i,j,1:2), grid(i+1,j,1:2))
958 ang = abs(90.0 - ang)
960 if ( (i==1) .and. (j==1) )
then 970 dxav = dxav + 0.5 * (dx_local + dy_local)
971 dxm =
max(dxm,dx_local)
972 dxm =
max(dxm,dy_local)
973 dxn =
min(dxn,dx_local)
974 dxn =
min(dxn,dy_local)
976 asp = abs(dx_local/dy_local)
977 if (asp < 1.0) asp = 1.0/asp
994 if( is_master() )
then 996 angav = angav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) - 1 )
997 dxav = dxav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) )
998 aspav = aspav / ( (ceiling(npy/2.0))*(ceiling(npx/2.0)) )
1001 write(*,*)
' REDUCED EARTH: Radius is ',
radius,
', omega is ',
omega 1003 write(*,* )
' Cubed-Sphere Grid Stats : ', npx,
'x',npy,
'x',nregions
1004 write(*,201)
' Grid Length : min: ', dxn,
' max: ', dxm,
' avg: ', dxav,
' min/max: ',dxn/dxm
1005 write(*,200)
' Deviation from Orthogonal : min: ',angn,
' max: ',angm,
' avg: ',angav
1006 write(*,200)
' Aspect Ratio : min: ',aspn,
' max: ',aspm,
' avg: ',aspav
1011 if (atm%neststruct%nested .or. any(atm%neststruct%child_grids))
then 1012 nullify(grid_global)
1013 else if( trim(grid_file) .NE.
'INPUT/grid_spec.nc')
then 1014 deallocate(grid_global)
1054 nullify(cubed_sphere)
1055 nullify(have_south_pole)
1056 nullify(have_north_pole)
1057 nullify(stretched_grid)
1067 type(fv_grid_bounds_type),
intent(IN) :: bd
1068 integer,
intent(in):: npx, npy
1069 real(kind=R_GRID),
intent(IN) :: dx_const, dy_const, deglat
1070 real(kind=R_GRID) lat_rad, lon_rad, domain_rad
1072 integer :: is, ie, js, je
1073 integer :: isd, ied, jsd, jed
1085 lat_rad = deglat *
pi/180.
1089 rdx(:,:) = 1./dx_const
1091 rdy(:,:) = 1./dy_const
1094 rdxc(:,:) = 1./dx_const
1096 rdyc(:,:) = 1./dy_const
1099 rdxa(:,:) = 1./dx_const
1101 rdya(:,:) = 1./dy_const
1103 area(:,:) = dx_const*dy_const
1104 rarea(:,:) = 1./(dx_const*dy_const)
1106 area_c(:,:) = dx_const*dy_const
1107 rarea_c(:,:) = 1./(dx_const*dy_const)
1111 do j=
max(1,jsd),
min(jed,npy)
1112 do i=
max(1,isd),
min(ied,npx)
1113 grid(i,j,1) = lon_rad - 0.5*domain_rad +
real(i-1)/
real(npx-1)*domain_rad
1114 grid(i,j,2) = lat_rad - 0.5*domain_rad +
real(j-1)/
real(npy-1)*domain_rad
1119 domain_rad = 1.e-2/npx
1120 do j=
max(1,jsd),
min(jed,npy)
1121 do i=
max(1,isd),
min(ied,npx)
1122 grid(i,j,1) = (0.0 + float(i-1)*domain_rad)*
pi/180.0
1123 grid(i,j,2) = (deglat + float(j-1)*domain_rad)*
pi/180.0
1128 agrid(:,:,1) = lon_rad
1129 agrid(:,:,2) = lat_rad
1146 type(fv_atmos_type),
intent(INOUT),
target :: Atm
1148 integer :: isd_p, ied_p, jsd_p, jed_p
1149 integer :: isg, ieg, jsg, jeg
1150 integer :: ic, jc, imod, jmod
1153 real(kind=R_GRID),
allocatable,
dimension(:,:,:) :: p_grid_u, p_grid_v, pa_grid, p_grid, c_grid_u, c_grid_v
1154 integer :: p_ind(1-ng:npx +ng,1-ng:npy +ng,4)
1159 real(kind=R_GRID) sum
1160 real(kind=R_GRID) :: dist1, dist2, dist3, dist4
1161 real(kind=R_GRID),
dimension(2) :: q1, q2
1163 integer,
pointer :: parent_tile, refinement, ioffset, joffset
1164 integer,
pointer,
dimension(:,:,:) :: ind_h, ind_u, ind_v, ind_update_h
1165 real,
pointer,
dimension(:,:,:) :: wt_h, wt_u, wt_v
1167 integer,
pointer,
dimension(:,:,:) :: ind_b
1168 real,
pointer,
dimension(:,:,:) :: wt_b
1170 integer :: is, ie, js, je
1171 integer :: isd, ied, jsd, jed
1184 parent_tile => atm%neststruct%parent_tile
1185 refinement => atm%neststruct%refinement
1186 ioffset => atm%neststruct%ioffset
1187 joffset => atm%neststruct%joffset
1189 ind_h => atm%neststruct%ind_h
1190 ind_u => atm%neststruct%ind_u
1191 ind_v => atm%neststruct%ind_v
1193 ind_update_h => atm%neststruct%ind_update_h
1195 wt_h => atm%neststruct%wt_h
1196 wt_u => atm%neststruct%wt_u
1197 wt_v => atm%neststruct%wt_v
1199 ind_b => atm%neststruct%ind_b
1200 wt_b => atm%neststruct%wt_b
1203 isd_p, ied_p, jsd_p, jed_p )
1207 allocate(p_grid_u(isg:ieg ,jsg:jeg+1,1:2))
1208 allocate(p_grid_v(isg:ieg+1,jsg:jeg ,1:2))
1209 allocate(pa_grid(isg:ieg,jsg:jeg ,1:2))
1212 allocate(p_grid( isg-ng:ieg+1+ng, jsg-ng:jeg+1+ng,1:2) )
1216 if( is_master() )
then 1219 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)), &
1220 atm%parent_grid%pelist(1))
1224 if ( joffset + floor(
real(1-ng) /
real(refinement) ) < 1-ng .or. &
1225 ioffset + floor(
real(1-ng) /
real(refinement) ) < 1-ng .or. &
1226 joffset + floor(
real(npy+ng) /
real(refinement) ) > Atm%parent_grid%npy+ng .or. &
1227 ioffset + floor(
real(npx+ng) /
real(refinement) ) > Atm%parent_grid%npx+ng ) then
1228 call mpp_error(fatal,
'nested grid lies outside its parent')
1232 jc = joffset + (j-1)/refinement
1233 jmod = mod(j-1,refinement)
1234 if (j-1 < 0 .and. jmod /= 0) jc = jc - 1
1235 if (jmod < 0) jmod = jmod + refinement
1238 ic = ioffset + (i-1)/refinement
1239 imod = mod(i-1,refinement)
1240 if (i-1 < 0 .and. imod /= 0) ic = ic - 1
1241 if (imod < 0) imod = imod + refinement
1243 if (ic+1 > ieg+1 .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1244 print*,
'p_grid:', i, j,
' OUT OF BOUNDS' 1246 print*, isg, ieg, jsg, jeg
1251 q1 = p_grid(ic, jc, 1:2)
1252 q2 = p_grid(ic+1,jc,1:2)
1254 call spherical_linear_interpolation(
real(jmod,kind=
r_grid)/
real(refinement,kind=R_GRID), &
1255 p_grid(ic, jc, 1:2), p_grid(ic, jc+1, 1:2), q1)
1256 call spherical_linear_interpolation(
real(jmod,kind=
r_grid)/
real(refinement,kind=R_GRID), &
1257 p_grid(ic+1, jc, 1:2), p_grid(ic+1, jc+1, 1:2), q2)
1261 grid_global(i,j,:,1) = q1
1263 call spherical_linear_interpolation(
real(imod,kind=
r_grid)/
real(refinement,kind=R_GRID), &
1264 q1,q2,grid_global(i,j,:,1))
1277 if (grid_global(i,j,1,1) > 2.*
pi) grid_global(i,j,1,1) = grid_global(i,j,1,1) - 2.*
pi 1278 if (grid_global(i,j,1,1) < 0.) grid_global(i,j,1,1) = grid_global(i,j,1,1) + 2.*
pi 1286 call mid_pt_sphere(p_grid(i, j,1:2), p_grid(i+1, j,1:2), p_grid_u(i,j,:))
1292 call mid_pt_sphere(p_grid(i, j,1:2), p_grid(i, j+1,1:2), p_grid_v(i,j,:))
1298 call cell_center2(p_grid(i,j, 1:2), p_grid(i+1,j, 1:2), &
1299 p_grid(i,j+1,1:2), p_grid(i+1,j+1,1:2), &
1306 call mpp_broadcast(grid_global(1-ng:npx+ng, 1-ng:npy+ng ,:,1), &
1307 ((npx+ng)-(1-ng)+1)*((npy+ng)-(1-ng)+1)*ndims, mpp_root_pe() )
1309 ((npx+ng)-(1-ng)+1)*((npy+ng)-(1-ng)+1)*4, mpp_root_pe() )
1311 ((ieg-isg+1))*(jeg-jsg+1)*ndims, mpp_root_pe())
1313 (ieg-isg+1)*(jeg-jsg+2)*ndims, mpp_root_pe())
1315 (ieg-isg+2)*(jeg-jsg+1)*ndims, mpp_root_pe())
1317 call mpp_broadcast( p_grid(isg-ng:ieg+ng+1, jsg-ng:jeg+ng+1, :), &
1318 (ieg-isg+2+2*ng)*(jeg-jsg+2+2*ng)*ndims, mpp_root_pe() )
1323 grid(i,j,n) = grid_global(i,j,n,1)
1337 if (imod < refinement/2)
then 1342 ind_h(i,j,1) = ic - 1
1347 if (jmod < refinement/2)
then 1348 ind_h(i,j,2) = jc - 1
1391 if (imod < refinement/2)
then 1395 ind_u(i,j,1) = ic - 1
1403 ind_u(i,j,4) = p_ind(i,j,4)
1421 if (jmod < refinement/2)
then 1422 ind_v(i,j,2) = jc - 1
1429 ind_v(i,j,3) = p_ind(i,j,3)
1435 agrid(:,:,:) = -1.e25
1439 call cell_center2(grid(i,j, 1:2), grid(i+1,j, 1:2), &
1440 grid(i,j+1,1:2), grid(i+1,j+1,1:2), &
1450 dx(i,j) = great_circle_dist(grid_global(i,j,:,1), grid_global(i+1,j,:,1),
radius)
1457 dy(i,j) = great_circle_dist(grid_global(i,j,:,1), grid_global(i,j+1,:,1),
radius)
1470 dist1 = dist2side_latlon(pa_grid(ic,jc,:) ,pa_grid(ic,jc+1,:),
agrid(i,j,:))
1471 dist2 = dist2side_latlon(pa_grid(ic,jc+1,:) ,pa_grid(ic+1,jc+1,:),
agrid(i,j,:))
1472 dist3 = dist2side_latlon(pa_grid(ic+1,jc+1,:),pa_grid(ic+1,jc,:),
agrid(i,j,:))
1473 dist4 = dist2side_latlon(pa_grid(ic,jc,:) ,pa_grid(ic+1,jc,:),
agrid(i,j,:))
1475 wt_h(i,j,1)=dist2*dist3
1476 wt_h(i,j,2)=dist3*dist4
1477 wt_h(i,j,3)=dist4*dist1
1478 wt_h(i,j,4)=dist1*dist2
1480 sum=wt_h(i,j,1)+wt_h(i,j,2)+wt_h(i,j,3)+wt_h(i,j,4)
1481 wt_h(i,j,:)=wt_h(i,j,:)/sum
1496 dist1 = dist2side_latlon(p_grid(ic,jc,:), p_grid(ic,jc+1,:), grid(i,j,:))
1497 dist2 = dist2side_latlon(p_grid(ic,jc+1,:), p_grid(ic+1,jc+1,:), grid(i,j,:))
1498 dist3 = dist2side_latlon(p_grid(ic+1,jc+1,:), p_grid(ic+1,jc,:), grid(i,j,:))
1499 dist4 = dist2side_latlon(p_grid(ic,jc,:), p_grid(ic+1,jc,:), grid(i,j,:))
1501 wt_b(i,j,1)=dist2*dist3
1502 wt_b(i,j,2)=dist3*dist4
1503 wt_b(i,j,3)=dist4*dist1
1504 wt_b(i,j,4)=dist1*dist2
1506 sum=wt_b(i,j,1)+wt_b(i,j,2)+wt_b(i,j,3)+wt_b(i,j,4)
1507 wt_b(i,j,:)=wt_b(i,j,:)/sum
1515 allocate(c_grid_u(isd:ied+1,jsd:jed,2))
1516 allocate(c_grid_v(isd:ied,jsd:jed+1,2))
1520 call mid_pt_sphere(grid(i, j,1:2), grid(i, j+1,1:2), c_grid_u(i,j,:))
1526 call mid_pt_sphere(grid(i,j ,1:2), grid(i+1,j ,1:2), c_grid_v(i,j,:))
1533 dxa(i,j) = great_circle_dist(c_grid_u(i,j,:), c_grid_u(i+1,j,:),
radius)
1539 dya(i,j) = great_circle_dist(c_grid_v(i,j,:), c_grid_v(i,j+1,:),
radius)
1554 if (ic+1 > ieg .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1555 print*,
'IND_U ', i, j,
' OUT OF BOUNDS' 1557 print*, isg, ieg, jsg, jeg
1566 wt_u(i,j,1) = 1. ; wt_u(i,j,2) = 0.
1568 dist1 = dist2side_latlon(p_grid_u(ic,jc,:), p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1569 dist2 = dist2side_latlon(p_grid_u(ic,jc+1,:), p_grid_u(ic+1,jc+1,:), c_grid_v(i,j,:))
1571 wt_u(i,j,1) = dist2/sum
1572 wt_u(i,j,2) = dist1/sum
1576 dist1 = dist2side_latlon(p_grid_u(ic,jc,:) ,p_grid_u(ic,jc+1,:), c_grid_v(i,j,:))
1577 dist2 = dist2side_latlon(p_grid_u(ic,jc+1,:) ,p_grid_u(ic+1,jc+1,:),c_grid_v(i,j,:))
1578 dist3 = dist2side_latlon(p_grid_u(ic+1,jc+1,:),p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1580 dist4 = dist2side_latlon(p_grid_u(ic,jc,:) ,p_grid_u(ic+1,jc,:), c_grid_v(i,j,:))
1582 wt_u(i,j,1)=dist2*dist3
1583 wt_u(i,j,2)=dist3*dist4
1584 wt_u(i,j,3)=dist4*dist1
1585 wt_u(i,j,4)=dist1*dist2
1587 sum=wt_u(i,j,1)+wt_u(i,j,2)+wt_u(i,j,3)+wt_u(i,j,4)
1588 wt_u(i,j,:)=wt_u(i,j,:)/sum
1601 if (ic+1 > ieg .or. ic < isg .or. jc+1 > jeg+1 .or. jc < jsg)
then 1602 print*,
'IND_V ', i, j,
' OUT OF BOUNDS' 1604 print*, isg, ieg, jsg, jeg
1610 wt_v(i,j,1) = 1. ; wt_v(i,j,4) = 0.
1612 dist1 = dist2side_latlon(p_grid_v(ic,jc,:), p_grid_v(ic,jc+1,:), c_grid_u(i,j,:))
1613 dist2 = dist2side_latlon(p_grid_v(ic+1,jc,:), p_grid_v(ic+1,jc+1,:), c_grid_u(i,j,:))
1615 wt_v(i,j,1) = dist2/sum
1616 wt_v(i,j,4) = dist1/sum
1618 wt_v(i,j,2) = 0. ; wt_v(i,j,3) = 0.
1620 dist1 = dist2side_latlon(p_grid_v(ic,jc,:) ,p_grid_v(ic,jc+1,:), c_grid_u(i,j,:))
1621 dist2 = dist2side_latlon(p_grid_v(ic,jc+1,:) ,p_grid_v(ic+1,jc+1,:),c_grid_u(i,j,:))
1622 dist3 = dist2side_latlon(p_grid_v(ic+1,jc+1,:),p_grid_v(ic+1,jc,:), c_grid_u(i,j,:))
1623 dist4 = dist2side_latlon(p_grid_v(ic,jc,:) ,p_grid_v(ic+1,jc,:), c_grid_u(i,j,:))
1625 wt_v(i,j,1)=dist2*dist3
1626 wt_v(i,j,2)=dist3*dist4
1627 wt_v(i,j,3)=dist4*dist1
1628 wt_v(i,j,4)=dist1*dist2
1630 sum=wt_v(i,j,1)+wt_v(i,j,2)+wt_v(i,j,3)+wt_v(i,j,4)
1631 wt_v(i,j,:)=wt_v(i,j,:)/sum
1637 deallocate(c_grid_u)
1638 deallocate(c_grid_v)
1641 deallocate(p_grid_u)
1642 deallocate(p_grid_v)
1644 if (is_master())
then 1645 if (atm%neststruct%nested)
then 1647 write(*,*)
'NESTED GRID ', atm%grid_number
1648 ic = p_ind(1,1,1) ; jc = p_ind(1,1,1)
1649 write(*,
'(A, 2I5, 4F10.4)')
'SW CORNER: ', ic, jc, grid_global(1,1,:,1)*90./
pi 1650 ic = p_ind(1,npy,1) ; jc = p_ind(1,npy,1)
1651 write(*,
'(A, 2I5, 4F10.4)')
'NW CORNER: ', ic, jc, grid_global(1,npy,:,1)*90./
pi 1652 ic = p_ind(npx,npy,1) ; jc = p_ind(npx,npy,1)
1653 write(*,
'(A, 2I5, 4F10.4)')
'NE CORNER: ', ic, jc, grid_global(npx,npy,:,1)*90./
pi 1654 ic = p_ind(npx,1,1) ; jc = p_ind(npx,1,1)
1655 write(*,
'(A, 2I5, 4F10.4)')
'SE CORNER: ', ic, jc, grid_global(npx,1,:,1)*90./
pi 1657 write(*,*)
'PARENT GRID ', atm%parent_grid%grid_number, atm%parent_grid%tile
1658 ic = p_ind(1,1,1) ; jc = p_ind(1,1,1)
1659 write(*,
'(A, 2I5, 4F10.4)')
'SW CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./
pi 1660 ic = p_ind(1,npy,1) ; jc = p_ind(1,npy,1)
1661 write(*,
'(A, 2I5, 4F10.4)')
'NW CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./
pi 1662 ic = p_ind(npx,npy,1) ; jc = p_ind(npx,npy,1)
1663 write(*,
'(A, 2I5, 4F10.4)')
'NE CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./
pi 1664 ic = p_ind(npx,1,1) ; jc = p_ind(npx,1,1)
1665 write(*,
'(A, 2I5, 4F10.4)')
'SE CORNER: ', ic, jc, atm%parent_grid%grid_global(ic,jc,:,parent_tile)*90./
pi 1671 subroutine setup_latlon(deglon_start,deglon_stop, deglat_start, deglat_stop, bd )
1673 type(fv_grid_bounds_type),
intent(IN) :: bd
1674 real(kind=R_GRID),
intent(IN) :: deglon_start,deglon_stop, deglat_start, deglat_stop
1675 real(kind=R_GRID) :: lon_start, lat_start, area_j
1676 integer :: is, ie, js, je
1677 integer :: isd, ied, jsd, jed
1689 dl = (deglon_stop-deglon_start)*
pi/(180.*(npx-1))
1690 dp = (deglat_stop-deglat_start)*
pi/(180.*(npy-1))
1692 lon_start = deglon_start*
pi/180.
1693 lat_start = deglat_start*
pi/180.
1697 grid(i,j,1) = lon_start +
real(i-1)*dl
1698 grid(i,j,2) = lat_start +
real(j-1)*dp
1704 agrid(i,j,1) = (grid(i,j,1) + grid(i+1,j,1))/2.
1705 agrid(i,j,2) = (grid(i,j,2) + grid(i,j+1,2))/2.
1713 rdxc(i,j) = 1./dxc(i,j)
1719 rdyc(i,j) = 1./dyc(i,j)
1727 rdxa(i,j) = 1./dxa(i,j)
1728 rdya(i,j) = 1./dya(i,j)
1734 dx(i,j) = dl*
radius*cos(grid(i,j,2))
1735 rdx(i,j) = 1./dx(i,j)
1741 rdy(i,j) = 1./dy(i,j)
1746 area_j =
radius*
radius*dl*(sin(grid(is,j+1,2))-sin(grid(is,j,2)))
1749 rarea(i,j) = 1./area_j
1756 area_c(i,j) = area_j
1757 rarea_c(i,j) = 1./area_j
1764 area_c(i,j) = area_j
1765 rarea_c(i,j) = 1./area_j
1768 if (jed+1==npy)
then 1772 area_c(i,j) = area_j
1773 rarea_c(i,j) = 1./area_j
1794 real(kind=R_GRID) ,
intent(IN) :: x, y, z
1795 real(kind=R_GRID) ,
intent(OUT) :: lon, lat, r
1797 r = sqrt(x*x + y*y + z*z)
1798 if ( (abs(x) + abs(y)) < 1.e-10 )
then 1807 lat = acos(z/r) -
pi/2.
1812 real(kind=R_GRID) ,
intent(IN) :: lon, lat, r
1813 real(kind=R_GRID) ,
intent(OUT) :: x, y, z
1815 x = r * cos(lon) * cos(lat)
1816 y = r * sin(lon) * cos(lat)
1830 subroutine rot_3d(axis, x1in, y1in, z1in, angle, x2out, y2out, z2out, degrees, convert)
1832 integer,
intent(IN) :: axis
1833 real(kind=R_GRID) ,
intent(IN) :: x1in, y1in, z1in
1834 real(kind=R_GRID) ,
intent(INOUT) :: angle
1835 real(kind=R_GRID) ,
intent(OUT) :: x2out, y2out, z2out
1836 integer,
intent(IN),
optional :: degrees
1838 integer,
intent(IN),
optional :: convert
1842 real(kind=R_GRID) :: c, s
1843 real(kind=R_GRID) :: x1,y1,z1, x2,y2,z2
1845 if (
present(convert) )
then 1853 if (
present(degrees) )
then 1875 write(*,*)
"Invalid axis: must be 1 for X, 2 for Y, 3 for Z." 1879 if (
present(convert) )
then 1893 real(kind=R_GRID) function get_area_tri(ndims, p_1, p_2, p_3) &
1901 integer,
intent(IN) :: ndims
1902 real(kind=R_GRID) ,
intent(IN) :: p_1(ndims)
1903 real(kind=R_GRID) ,
intent(IN) :: p_2(ndims)
1904 real(kind=R_GRID) ,
intent(IN) :: p_3(ndims)
1906 real(kind=R_GRID) :: anga, angb, angc
1908 if ( ndims==3 )
then 1913 anga =
get_angle(ndims, p_1, p_2, p_3, 1)
1914 angb =
get_angle(ndims, p_2, p_3, p_1, 1)
1915 angc =
get_angle(ndims, p_3, p_1, p_2, 1)
1918 myarea = (anga+angb+angc -
pi) *
radius**2
1932 subroutine grid_area(nx, ny, ndims, nregions, nested, gridstruct, domain, bd )
1934 type(fv_grid_bounds_type),
intent(IN) :: bd
1935 integer,
intent(IN) :: nx, ny, ndims, nregions
1936 logical,
intent(IN) :: nested
1937 type(fv_grid_type),
intent(IN),
target :: gridstruct
1938 type(domain2d),
intent(INOUT) :: domain
1940 real(kind=R_GRID) :: p_lL(ndims)
1941 real(kind=R_GRID) :: p_uL(ndims)
1942 real(kind=R_GRID) :: p_lR(ndims)
1943 real(kind=R_GRID) :: p_uR(ndims)
1944 real(kind=R_GRID) :: a1, d1, d2, mydx, mydy, globalarea
1946 real(kind=R_GRID) :: p1(ndims), p2(ndims), p3(ndims), pi1(ndims), pi2(ndims)
1948 real(kind=R_GRID) :: maxarea, minarea
1950 integer :: i,j,n, nreg
1953 real(kind=R_GRID),
allocatable :: p_R8(:,:,:)
1955 real(kind=R_GRID),
pointer,
dimension(:,:,:) :: grid, agrid
1956 integer,
pointer,
dimension(:,:,:) :: iinta, jinta, iintb, jintb
1957 real(kind=R_GRID),
pointer,
dimension(:,:) :: area, area_c
1959 integer :: is, ie, js, je
1960 integer :: isd, ied, jsd, jed
1971 grid => gridstruct%grid_64
1972 agrid => gridstruct%agrid_64
1973 iinta => gridstruct%iinta
1974 jinta => gridstruct%jinta
1975 iintb => gridstruct%iintb
1976 jintb => gridstruct%jintb
1978 area => gridstruct%area_64
1979 area_c => gridstruct%area_c_64
1990 if ( gridstruct%stretched_grid .or. nested )
then 1991 p_ll(n) = grid(i ,j ,n)
1992 p_ul(n) = grid(i ,j+1,n)
1993 p_lr(n) = grid(i+1,j ,n)
1994 p_ur(n) = grid(i+1,j+1,n)
1996 p_ll(n) = grid(iinta(1,i,j), jinta(1,i,j), n)
1997 p_ul(n) = grid(iinta(2,i,j), jinta(2,i,j), n)
1998 p_lr(n) = grid(iinta(4,i,j), jinta(4,i,j), n)
1999 p_ur(n) = grid(iinta(3,i,j), jinta(3,i,j), n)
2004 area(i,j) = get_area(p_ll, p_ul, p_lr, p_ur,
radius)
2042 if (is_master())
write(*,209)
'MAX AREA (m*m):', maxarea,
' MIN AREA (m*m):', minarea
2043 if (is_master())
write(*,209)
'GLOBAL AREA (m*m):', globalarea,
' IDEAL GLOBAL AREA (m*m):', 4.0*
pi*
radius**2
2044 209
format(a,e21.14,a,e21.14)
2054 if ( gridstruct%stretched_grid .or. nested )
then 2055 p_ll(n) = agrid(i-1,j-1,n)
2056 p_lr(n) = agrid(i ,j-1,n)
2057 p_ul(n) = agrid(i-1,j ,n)
2058 p_ur(n) = agrid(i ,j ,n)
2060 p_ll(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2061 p_lr(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2062 p_ul(n) = agrid(iintb(4,i,j), jintb(4,i,j), n)
2063 p_ur(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2067 area_c(i,j) = get_area(p_ll, p_ul, p_lr, p_ur,
radius)
2072 if (gridstruct%cubed_sphere .and. .not. nested)
then 2076 if ( (is==1) .and. (js==1) )
then 2078 if ( gridstruct%stretched_grid )
then 2079 p1(n) = agrid(i-1,j ,n)
2080 p2(n) = agrid(i ,j ,n)
2081 p3(n) = agrid(i ,j-1,n)
2083 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2084 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2085 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2093 if ( (ie+1==nx) .and. (js==1) )
then 2095 if ( gridstruct%stretched_grid )
then 2096 p1(n) = agrid(i ,j ,n)
2097 p2(n) = agrid(i-1,j ,n)
2098 p3(n) = agrid(i-1,j-1,n)
2100 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2101 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2102 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2110 if ( (ie+1==nx) .and. (je+1==ny) )
then 2112 if ( gridstruct%stretched_grid )
then 2113 p1(n) = agrid(i-1,j ,n)
2114 p2(n) = agrid(i-1,j-1,n)
2115 p3(n) = agrid(i ,j-1,n)
2117 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2118 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2119 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2127 if ( (is==1) .and. (je+1==ny) )
then 2129 if ( gridstruct%stretched_grid )
then 2130 p1(n) = agrid(i ,j ,n)
2131 p2(n) = agrid(i ,j-1,n)
2132 p3(n) = agrid(i-1,j-1,n)
2134 p1(n) = agrid(iintb(1,i,j), jintb(1,i,j), n)
2135 p2(n) = agrid(iintb(2,i,j), jintb(2,i,j), n)
2136 p3(n) = agrid(iintb(3,i,j), jintb(3,i,j), n)
2147 real(kind=R_GRID) function get_angle(ndims, p1, p2, p3, rad)
result (angle)
2152 integer,
intent(IN) :: ndims
2153 real(kind=R_GRID) ,
intent(IN) :: p1(ndims)
2154 real(kind=R_GRID) ,
intent(IN) :: p2(ndims)
2155 real(kind=R_GRID) ,
intent(IN) :: p3(ndims)
2156 integer,
intent(in),
optional:: rad
2158 real(kind=R_GRID) :: e1(3), e2(3), e3(3)
2160 if (ndims == 2)
then 2165 e1 = p2; e2 = p1; e3 = p3
2169 if (
present(rad) )
then 2181 subroutine mirror_grid(grid_global,ng,npx,npy,ndims,nregions)
2182 integer,
intent(IN) :: ng,npx,npy,ndims,nregions
2183 real(kind=R_GRID) ,
intent(INOUT) :: grid_global(1-ng:npx +ng,1-ng:npy +ng,ndims,1:nregions)
2184 integer :: i,j,n,n1,n2,nreg
2185 real(kind=R_GRID) :: x1,y1,z1, x2,y2,z2, ang
2190 do j=1,ceiling(npy/2.)
2191 do i=1,ceiling(npx/2.)
2193 x1 = 0.25d0 * (abs(grid_global(i ,j ,1,nreg)) + &
2194 abs(grid_global(npx-(i-1),j ,1,nreg)) + &
2195 abs(grid_global(i ,npy-(j-1),1,nreg)) + &
2196 abs(grid_global(npx-(i-1),npy-(j-1),1,nreg)))
2197 grid_global(i ,j ,1,nreg) = sign(x1,grid_global(i ,j ,1,nreg))
2198 grid_global(npx-(i-1),j ,1,nreg) = sign(x1,grid_global(npx-(i-1),j ,1,nreg))
2199 grid_global(i ,npy-(j-1),1,nreg) = sign(x1,grid_global(i ,npy-(j-1),1,nreg))
2200 grid_global(npx-(i-1),npy-(j-1),1,nreg) = sign(x1,grid_global(npx-(i-1),npy-(j-1),1,nreg))
2202 y1 = 0.25d0 * (abs(grid_global(i ,j ,2,nreg)) + &
2203 abs(grid_global(npx-(i-1),j ,2,nreg)) + &
2204 abs(grid_global(i ,npy-(j-1),2,nreg)) + &
2205 abs(grid_global(npx-(i-1),npy-(j-1),2,nreg)))
2206 grid_global(i ,j ,2,nreg) = sign(y1,grid_global(i ,j ,2,nreg))
2207 grid_global(npx-(i-1),j ,2,nreg) = sign(y1,grid_global(npx-(i-1),j ,2,nreg))
2208 grid_global(i ,npy-(j-1),2,nreg) = sign(y1,grid_global(i ,npy-(j-1),2,nreg))
2209 grid_global(npx-(i-1),npy-(j-1),2,nreg) = sign(y1,grid_global(npx-(i-1),npy-(j-1),2,nreg))
2212 if (mod(npx,2) /= 0)
then 2213 if ( (i==1+(npx-1)/2.0d0) )
then 2214 grid_global(i,j ,1,nreg) = 0.0d0
2215 grid_global(i,npy-(j-1),1,nreg) = 0.0d0
2226 x1 = grid_global(i,j,1,1)
2227 y1 = grid_global(i,j,2,1)
2232 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2233 elseif (nreg == 3)
then 2235 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2237 call rot_3d( 1, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2243 if (mod(npx,2) /= 0)
then 2244 if ( (i==1+(npx-1)/2.0d0) .and. (i==j) )
then 2248 if ( (j==1+(npy-1)/2.0d0) .and. (i < 1+(npx-1)/2.0d0) )
then 2251 if ( (j==1+(npy-1)/2.0d0) .and. (i > 1+(npx-1)/2.0d0) )
then 2256 elseif (nreg == 4)
then 2258 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2260 call rot_3d( 1, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2266 if (mod(npx,2) /= 0)
then 2267 if ( (j==1+(npy-1)/2.0d0) )
then 2272 elseif (nreg == 5)
then 2274 call rot_3d( 3, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2276 call rot_3d( 2, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2280 elseif (nreg == 6)
then 2282 call rot_3d( 2, x1, y1, z1, ang, x2, y2, z2, 1, 1)
2284 call rot_3d( 3, x2, y2, z2, ang, x1, y1, z1, 1, 1)
2290 if (mod(npx,2) /= 0)
then 2291 if ( (i==1+(npx-1)/2.0d0) .and. (i==j) )
then 2295 if ( (i==1+(npx-1)/2.0d0) .and. (j > 1+(npy-1)/2.0d0) )
then 2298 if ( (i==1+(npx-1)/2.0d0) .and. (j < 1+(npy-1)/2.0d0) )
then 2305 grid_global(i,j,1,nreg) = x2
2306 grid_global(i,j,2,nreg) = y2
2316 real(kind=R_GRID),
intent(in):: p1(2), p2(2), p3(2)
2317 real(kind=R_GRID),
intent(out):: uvect(3)
2320 real(kind=R_GRID) :: xyz1(3), xyz2(3), xyz3(3)
2328 uvect(n) = xyz3(n)-xyz1(n)
2330 call project_sphere_v(1, uvect,xyz2)
2337 real(kind=R_GRID),
intent(in):: p1(2), p2(2)
2338 real(kind=R_GRID),
intent(out):: uvect(3)
2341 real(kind=R_GRID) :: xyz1(3), xyz2(3)
2347 uvect(n) = xyz2(n)-xyz1(n)
2349 call project_sphere_v(1, uvect,xyz1)
2359 integer,
intent(in):: np
2360 real(kind=R_GRID),
intent(inout):: e(3,np)
2363 real(kind=R_GRID) pdot
2366 pdot = sqrt(e(1,n)**2+e(2,n)**2+e(3,n)**2)
2368 e(k,n) = e(k,n) / pdot
real, parameter, public radius
Radius of the Earth [m].
integer, parameter, public bgrid_ne
integer, parameter, public cgrid_sw
real, parameter, public omega
Rotation rate of the Earth [1/s].
subroutine, public spherical_linear_interpolation(beta, p1, p2, pb)
integer, parameter, public dgrid_ne
real(kind=8), parameter, public pi_8
Ratio of circle circumference to diameter [N/A].
subroutine, public cell_center2(q1, q2, q3, q4, e2)
integer, parameter, public ip
logical function, public file_exist(file_name, domain, no_domain)
integer, parameter, public corner
subroutine, public gnomonic_grids(grid_type, im, lon, lat)
integer, parameter, public bgrid_sw
void mid_pt_sphere(const double *p1, const double *p2, double *pm)
integer function, public get_mosaic_ntiles(mosaic_file)
double spherical_angle(const double *v1, const double *v2, const double *v3)
subroutine, public project_sphere_v(np, f, e)
l_size ! loop over number of fields ke do je do ie to je n if(.NOT. d_comm%R_do_buf(list)) cycle from_pe
integer, parameter, public agrid
real(kind=r_grid) function, public get_area(p1, p4, p2, p3, radius)
real, parameter, public big_number
integer, parameter, public center
integer, parameter, public ng
subroutine timing_on(blk_name)
real(kind=r_grid) function, public dist2side_latlon(v1, v2, point)
integer, parameter, public r_grid
real function, public great_circle_dist(q1, q2, radius)
subroutine, public direct_transform(c, i1, i2, j1, j2, lon_p, lat_p, n, lon, lat)
real, parameter, public grav
Acceleration due to gravity [m/s^2].
integer, parameter, public xupdate
void normalize_vect(double *e)
subroutine, public sorted_intb(isd, ied, jsd, jed, is, ie, js, je, npx, npy, cubed_sphere, agrid, iintb, jintb)
real function, public inner_prod(v1, v2)
subroutine, public sorted_inta(isd, ied, jsd, jed, cubed_sphere, bgrid, iinta, jinta)
integer, parameter, public scalar_pair
integer, parameter, public cgrid_ne
logical function, public field_exist(file_name, field_name, domain, no_domain)
real(fp), parameter, public pi
subroutine timing_off(blk_name)