68 use fv_mp_mod, only: group_halo_update_type
69 use fv_mp_mod, only: start_group_halo_update, complete_group_halo_update
70 use mpp_domains_mod
, only: mpp_update_domains, cgrid_ne, domain2d
76 use mpp_mod
, only: mpp_error, fatal, mpp_broadcast, mpp_send, mpp_recv, mpp_sum, mpp_max
92 subroutine tracer_2d_1l(q, dp1, mfx, mfy, cx, cy, gridstruct, bd, domain, npx, npy, npz, &
93 nq, hord, q_split, dt, id_divg, q_pack, nord_tr, trdm, lim_fac)
96 integer,
intent(IN) :: npx
97 integer,
intent(IN) :: npy
98 integer,
intent(IN) :: npz
99 integer,
intent(IN) :: nq
100 integer,
intent(IN) :: hord, nord_tr
101 integer,
intent(IN) :: q_split
102 integer,
intent(IN) :: id_divg
103 real ,
intent(IN) :: dt, trdm
104 real ,
intent(IN) :: lim_fac
105 type(group_halo_update_type),
intent(inout) :: q_pack
106 real ,
intent(INOUT) :: q(bd%isd:bd%ied,bd%jsd:bd%jed,npz,nq)
107 real ,
intent(INOUT) :: dp1(bd%isd:bd%ied,bd%jsd:bd%jed,npz)
108 real ,
intent(INOUT) :: mfx(bd%is:bd%ie+1,bd%js:bd%je, npz)
109 real ,
intent(INOUT) :: mfy(bd%is:bd%ie ,bd%js:bd%je+1,npz)
110 real ,
intent(INOUT) :: cx(bd%is:bd%ie+1,bd%jsd:bd%jed ,npz)
111 real ,
intent(INOUT) :: cy(bd%isd:bd%ied,bd%js :bd%je +1,npz)
113 type(domain2d),
intent(INOUT) :: domain
116 real :: qn2(bd%isd:bd%ied,bd%jsd:bd%jed,nq)
117 real :: dp2(bd%is:bd%ie,bd%js:bd%je)
118 real :: fx(bd%is:bd%ie+1,bd%js:bd%je )
119 real :: fy(bd%is:bd%ie , bd%js:bd%je+1)
120 real :: ra_x(bd%is:bd%ie,bd%jsd:bd%jed)
121 real :: ra_y(bd%isd:bd%ied,bd%js:bd%je)
122 real :: xfx(bd%is:bd%ie+1,bd%jsd:bd%jed ,npz)
123 real :: yfx(bd%isd:bd%ied,bd%js: bd%je+1, npz)
127 integer :: i,j,k,it,iq
129 real,
pointer,
dimension(:,:) :: area, rarea
130 real,
pointer,
dimension(:,:,:) :: sin_sg
131 real,
pointer,
dimension(:,:) :: dxa, dya, dx, dy
133 integer :: is, ie, js, je
134 integer :: isd, ied, jsd, jed
145 area => gridstruct%area
146 rarea => gridstruct%rarea
148 sin_sg => gridstruct%sin_sg
149 dxa => gridstruct%dxa
150 dya => gridstruct%dya
159 if (cx(i,j,k) > 0.)
then 160 xfx(i,j,k) = cx(i,j,k)*dxa(i-1,j)*dy(i,j)*sin_sg(i-1,j,3)
162 xfx(i,j,k) = cx(i,j,k)*dxa(i, j)*dy(i,j)*sin_sg(i, j,1)
168 if (cy(i,j,k) > 0.)
then 169 yfx(i,j,k) = cy(i,j,k)*dya(i,j-1)*dx(i,j)*sin_sg(i,j-1,4)
171 yfx(i,j,k) = cy(i,j,k)*dya(i,j )*dx(i,j)*sin_sg(i,j, 2)
177 if ( k < npz/6 )
then 180 cmax(k) = max( cmax(k), abs(cx(i,j,k)), abs(cy(i,j,k)) )
186 cmax(k) = max( cmax(k), max(abs(cx(i,j,k)),abs(cy(i,j,k)))+1.-sin_sg(i,j,5) )
192 call mp_reduce_max(cmax,npz)
199 nsplt = int(1. + cmax(k))
200 if ( nsplt > 1 )
then 201 frac = 1. /
real(nsplt)
204 cx(i,j,k) = cx(i,j,k) * frac
205 xfx(i,j,k) = xfx(i,j,k) * frac
210 mfx(i,j,k) = mfx(i,j,k) * frac
215 cy(i,j,k) = cy(i,j,k) * frac
216 yfx(i,j,k) = yfx(i,j,k) * frac
221 mfy(i,j,k) = mfy(i,j,k) * frac
229 call complete_group_halo_update(q_pack, domain)
239 ra_x(i,j) = area(i,j) + xfx(i,j,k) - xfx(i+1,j,k)
241 if ( j>=js .and. j<=je )
then 243 ra_y(i,j) = area(i,j) + yfx(i,j,k) - yfx(i,j+1,k)
248 nsplt = int(1. + cmax(k))
254 dp2(i,j) = dp1(i,j,k) + (mfx(i,j,k)-mfx(i+1,j,k)+mfy(i,j,k)-mfy(i,j+1,k))*rarea(i,j)
262 if ( nsplt /= 1 )
then 266 qn2(i,j,iq) = q(i,j,k,iq)
270 call fv_tp_2d(qn2(isd,jsd,iq), cx(is,jsd,k), cy(isd,js,k), &
271 npx, npy, hord, fx, fy, xfx(is,jsd,k), yfx(isd,js,k), &
272 gridstruct, bd, ra_x, ra_y, lim_fac, mfx=mfx(is,js,k), mfy=mfy(is,js,k))
273 if ( it < nsplt )
then 276 qn2(i,j,iq) = (qn2(i,j,iq)*dp1(i,j,k)+(fx(i,j)-fx(i+1,j)+fy(i,j)-fy(i,j+1))*rarea(i,j))/dp2(i,j)
282 q(i,j,k,iq) = (qn2(i,j,iq)*dp1(i,j,k)+(fx(i,j)-fx(i+1,j)+fy(i,j)-fy(i,j+1))*rarea(i,j))/dp2(i,j)
287 call fv_tp_2d(q(isd,jsd,k,iq), cx(is,jsd,k), cy(isd,js,k), &
288 npx, npy, hord, fx, fy, xfx(is,jsd,k), yfx(isd,js,k), &
289 gridstruct, bd, ra_x, ra_y, lim_fac, mfx=mfx(is,js,k), mfy=mfy(is,js,k))
292 q(i,j,k,iq) = (q(i,j,k,iq)*dp1(i,j,k)+(fx(i,j)-fx(i+1,j)+fy(i,j)-fy(i,j+1))*rarea(i,j))/dp2(i,j)
298 if ( it < nsplt )
then 301 dp1(i,j,k) = dp2(i,j)
306 call mpp_update_domains(qn2, domain)
316 subroutine tracer_2d(q, dp1, mfx, mfy, cx, cy, gridstruct, bd, domain, npx, npy, npz, &
317 nq, hord, q_split, dt, id_divg, q_pack, nord_tr, trdm, lim_fac)
320 integer,
intent(IN) :: npx
321 integer,
intent(IN) :: npy
322 integer,
intent(IN) :: npz
323 integer,
intent(IN) :: nq
324 integer,
intent(IN) :: hord, nord_tr
325 integer,
intent(IN) :: q_split
326 integer,
intent(IN) :: id_divg
327 real ,
intent(IN) :: dt, trdm
328 real ,
intent(IN) :: lim_fac
329 type(group_halo_update_type),
intent(inout) :: q_pack
330 real ,
intent(INOUT) :: q(bd%isd:bd%ied,bd%jsd:bd%jed,npz,nq)
331 real ,
intent(INOUT) :: dp1(bd%isd:bd%ied,bd%jsd:bd%jed,npz)
332 real ,
intent(INOUT) :: mfx(bd%is:bd%ie+1,bd%js:bd%je, npz)
333 real ,
intent(INOUT) :: mfy(bd%is:bd%ie ,bd%js:bd%je+1,npz)
334 real ,
intent(INOUT) :: cx(bd%is:bd%ie+1,bd%jsd:bd%jed ,npz)
335 real ,
intent(INOUT) :: cy(bd%isd:bd%ied,bd%js :bd%je +1,npz)
337 type(domain2d),
intent(INOUT) :: domain
340 real :: dp2(bd%is:bd%ie,bd%js:bd%je)
341 real :: fx(bd%is:bd%ie+1,bd%js:bd%je )
342 real :: fy(bd%is:bd%ie , bd%js:bd%je+1)
343 real :: ra_x(bd%is:bd%ie,bd%jsd:bd%jed)
344 real :: ra_y(bd%isd:bd%ied,bd%js:bd%je)
345 real :: xfx(bd%is:bd%ie+1,bd%jsd:bd%jed ,npz)
346 real :: yfx(bd%isd:bd%ied,bd%js: bd%je+1, npz)
350 integer :: ksplt(npz)
352 integer :: i,j,k,it,iq
354 real,
pointer,
dimension(:,:) :: area, rarea
355 real,
pointer,
dimension(:,:,:) :: sin_sg
356 real,
pointer,
dimension(:,:) :: dxa, dya, dx, dy
358 integer :: is, ie, js, je
359 integer :: isd, ied, jsd, jed
370 area => gridstruct%area
371 rarea => gridstruct%rarea
373 sin_sg => gridstruct%sin_sg
374 dxa => gridstruct%dxa
375 dya => gridstruct%dya
384 if (cx(i,j,k) > 0.)
then 385 xfx(i,j,k) = cx(i,j,k)*dxa(i-1,j)*dy(i,j)*sin_sg(i-1,j,3)
387 xfx(i,j,k) = cx(i,j,k)*dxa(i,j)*dy(i,j)*sin_sg(i,j,1)
393 if (cy(i,j,k) > 0.)
then 394 yfx(i,j,k) = cy(i,j,k)*dya(i,j-1)*dx(i,j)*sin_sg(i,j-1,4)
396 yfx(i,j,k) = cy(i,j,k)*dya(i,j)*dx(i,j)*sin_sg(i,j,2)
401 if ( q_split == 0 )
then 403 if ( k < npz/6 )
then 406 cmax(k) = max( cmax(k), abs(cx(i,j,k)), abs(cy(i,j,k)) )
412 cmax(k) = max( cmax(k), max(abs(cx(i,j,k)),abs(cy(i,j,k)))+1.-sin_sg(i,j,5) )
424 if ( q_split == 0 )
then 425 call mp_reduce_max(cmax,npz)
430 c_global = max(cmax(k), c_global)
433 nsplt = int(1. + c_global)
434 if ( is_master() .and. nsplt > 4 )
write(*,*)
'Tracer_2d_split=', nsplt, c_global
441 if( nsplt /= 1 )
then 449 ksplt(k) = int(1. + cmax(k))
451 frac = 1. /
real(ksplt(k))
455 cx(i,j,k) = cx(i,j,k) * frac
456 xfx(i,j,k) = xfx(i,j,k) * frac
461 mfx(i,j,k) = mfx(i,j,k) * frac
467 cy(i,j,k) = cy(i,j,k) * frac
468 yfx(i,j,k) = yfx(i,j,k) * frac
473 mfy(i,j,k) = mfy(i,j,k) * frac
483 call complete_group_halo_update(q_pack, domain)
492 if ( it .le. ksplt(k) )
then 496 dp2(i,j) = dp1(i,j,k) + (mfx(i,j,k)-mfx(i+1,j,k)+mfy(i,j,k)-mfy(i,j+1,k))*rarea(i,j)
502 ra_x(i,j) = area(i,j) + xfx(i,j,k) - xfx(i+1,j,k)
507 ra_y(i,j) = area(i,j) + yfx(i,j,k) - yfx(i,j+1,k)
512 if ( it==1 .and. trdm>1.e-4 )
then 513 call fv_tp_2d(q(isd,jsd,k,iq), cx(is,jsd,k), cy(isd,js,k), &
514 npx, npy, hord, fx, fy, xfx(is,jsd,k), yfx(isd,js,k), &
515 gridstruct, bd, ra_x, ra_y, lim_fac, mfx=mfx(is,js,k), mfy=mfy(is,js,k), &
516 mass=dp1(isd,jsd,k), nord=nord_tr, damp_c=trdm)
518 call fv_tp_2d(q(isd,jsd,k,iq), cx(is,jsd,k), cy(isd,js,k), &
519 npx, npy, hord, fx, fy, xfx(is,jsd,k), yfx(isd,js,k), &
520 gridstruct, bd, ra_x, ra_y, lim_fac, mfx=mfx(is,js,k), mfy=mfy(is,js,k))
524 q(i,j,k,iq) = ( q(i,j,k,iq)*dp1(i,j,k) + &
525 (fx(i,j)-fx(i+1,j)+fy(i,j)-fy(i,j+1))*rarea(i,j) )/dp2(i,j)
530 if ( it /= nsplt )
then 533 dp1(i,j,k) = dp2(i,j)
542 if ( it /= nsplt )
then 545 call start_group_halo_update(q_pack, q, domain)
556 subroutine tracer_2d_nested(q, dp1, mfx, mfy, cx, cy, gridstruct, bd, domain, npx, npy, npz, &
557 nq, hord, q_split, dt, id_divg, q_pack, nord_tr, trdm, &
558 k_split, neststruct, parent_grid, n_map, lim_fac)
561 integer,
intent(IN) :: npx
562 integer,
intent(IN) :: npy
563 integer,
intent(IN) :: npz
564 integer,
intent(IN) :: nq
565 integer,
intent(IN) :: hord, nord_tr
566 integer,
intent(IN) :: q_split, k_split, n_map
567 integer,
intent(IN) :: id_divg
568 real ,
intent(IN) :: dt, trdm
569 real ,
intent(IN) :: lim_fac
570 type(group_halo_update_type),
intent(inout) :: q_pack
571 real ,
intent(INOUT) :: q(bd%isd:bd%ied,bd%jsd:bd%jed,npz,nq)
572 real ,
intent(INOUT) :: dp1(bd%isd:bd%ied,bd%jsd:bd%jed,npz)
573 real ,
intent(INOUT) :: mfx(bd%is:bd%ie+1,bd%js:bd%je, npz)
574 real ,
intent(INOUT) :: mfy(bd%is:bd%ie ,bd%js:bd%je+1,npz)
575 real ,
intent(INOUT) :: cx(bd%is:bd%ie+1,bd%jsd:bd%jed ,npz)
576 real ,
intent(INOUT) :: cy(bd%isd:bd%ied,bd%js :bd%je +1,npz)
580 type(domain2d),
intent(INOUT) :: domain
583 real :: dp2(bd%is:bd%ie,bd%js:bd%je)
584 real :: fx(bd%is:bd%ie+1,bd%js:bd%je )
585 real :: fy(bd%is:bd%ie , bd%js:bd%je+1)
586 real :: ra_x(bd%is:bd%ie,bd%jsd:bd%jed)
587 real :: ra_y(bd%isd:bd%ied,bd%js:bd%je)
588 real :: xfx(bd%is:bd%ie+1,bd%jsd:bd%jed ,npz)
589 real :: yfx(bd%isd:bd%ied,bd%js: bd%je+1, npz)
594 real :: recip_nsplt, reg_bc_update_time
595 integer :: nsplt, nsplt_parent, msg_split_steps = 1
596 integer :: i,j,k,it,iq
598 real,
pointer,
dimension(:,:) :: area, rarea
599 real,
pointer,
dimension(:,:,:) :: sin_sg
600 real,
pointer,
dimension(:,:) :: dxa, dya, dx, dy
602 integer :: is, ie, js, je
603 integer :: isd, ied, jsd, jed
614 area => gridstruct%area
615 rarea => gridstruct%rarea
617 sin_sg => gridstruct%sin_sg
618 dxa => gridstruct%dxa
619 dya => gridstruct%dya
628 if (cx(i,j,k) > 0.)
then 629 xfx(i,j,k) = cx(i,j,k)*dxa(i-1,j)*dy(i,j)*sin_sg(i-1,j,3)
631 xfx(i,j,k) = cx(i,j,k)*dxa(i,j)*dy(i,j)*sin_sg(i,j,1)
637 if (cy(i,j,k) > 0.)
then 638 yfx(i,j,k) = cy(i,j,k)*dya(i,j-1)*dx(i,j)*sin_sg(i,j-1,4)
640 yfx(i,j,k) = cy(i,j,k)*dya(i,j)*dx(i,j)*sin_sg(i,j,2)
647 if ( q_split == 0 )
then 658 cmax_t = max( abs(cx(i,j,k)), abs(cy(i,j,k)) )
659 cmax(k) = max( cmax_t, cmax(k) )
665 cmax_t = max(abs(cx(i,j,k)), abs(cy(i,j,k))) + 1.-sin_sg(i,j,5)
666 cmax(k) = max( cmax_t, cmax(k) )
671 call mp_reduce_max(cmax,npz)
677 c_global = max(cmax(k), c_global)
680 nsplt = int(1. + c_global)
681 if ( is_master() .and. nsplt > 3 )
write(*,*)
'Tracer_2d_split=', nsplt, c_global
684 if (gridstruct%nested .and. neststruct%nestbctype > 1) msg_split_steps = max(q_split/parent_grid%flagstruct%q_split,1)
689 frac = 1. /
real(nsplt)
690 recip_nsplt = 1. /
real(nsplt)
692 if( nsplt /= 1 )
then 697 cx(i,j,k) = cx(i,j,k) * frac
698 xfx(i,j,k) = xfx(i,j,k) * frac
703 mfx(i,j,k) = mfx(i,j,k) * frac
709 cy(i,j,k) = cy(i,j,k) * frac
710 yfx(i,j,k) = yfx(i,j,k) * frac
716 mfy(i,j,k) = mfy(i,j,k) * frac
724 if ( gridstruct%nested )
then 725 neststruct%tracer_nest_timestep = neststruct%tracer_nest_timestep + 1
729 call complete_group_halo_update(q_pack, domain)
733 if (gridstruct%nested)
then 736 0, 0, npx, npy, npz, bd, &
737 real(neststruct%tracer_nest_timestep)+
real(nsplt*k_split),
real(nsplt*k_split), &
738 neststruct%q_BC(iq), bctype=neststruct%nestbctype )
742 if (gridstruct%regional)
then 745 call regional_boundary_update(q(:,:,:,iq),
'q', &
746 isd, ied, jsd, jed, npz, &
748 isd, ied, jsd, jed, &
749 reg_bc_update_time, &
753 call mpp_update_domains(q, domain, complete=.true.)
765 dp2(i,j) = dp1(i,j,k) + (mfx(i,j,k)-mfx(i+1,j,k)+mfy(i,j,k)-mfy(i,j+1,k))*rarea(i,j)
771 ra_x(i,j) = area(i,j) + xfx(i,j,k) - xfx(i+1,j,k)
776 ra_y(i,j) = area(i,j) + yfx(i,j,k) - yfx(i,j+1,k)
781 if ( it==1 .and. trdm>1.e-4 )
then 782 call fv_tp_2d(q(isd,jsd,k,iq), cx(is,jsd,k), cy(isd,js,k), &
783 npx, npy, hord, fx, fy, xfx(is,jsd,k), yfx(isd,js,k), &
784 gridstruct, bd, ra_x, ra_y, lim_fac, mfx=mfx(is,js,k), mfy=mfy(is,js,k), &
785 mass=dp1(isd,jsd,k), nord=nord_tr, damp_c=trdm)
787 call fv_tp_2d(q(isd,jsd,k,iq), cx(is,jsd,k), cy(isd,js,k), &
788 npx, npy, hord, fx, fy, xfx(is,jsd,k), yfx(isd,js,k), &
789 gridstruct, bd, ra_x, ra_y, lim_fac, mfx=mfx(is,js,k), mfy=mfy(is,js,k))
793 q(i,j,k,iq) = ( q(i,j,k,iq)*dp1(i,j,k) + &
794 (fx(i,j)-fx(i+1,j)+fy(i,j)-fy(i,j+1))*rarea(i,j) )/dp2(i,j)
800 if ( it /= nsplt )
then 803 call start_group_halo_update(q_pack, q, domain)
810 if ( id_divg > 0 )
then 817 dp1(i,j,k) = (xfx(i+1,j,k)-xfx(i,j,k) + yfx(i,j+1,k)-yfx(i,j,k))*rarea(i,j)*rdt
subroutine, public regional_boundary_update(array, bc_vbl_name, lbnd_x, ubnd_x, lbnd_y, ubnd_y, ubnd_z, is, ie, js, je, isd, ied, jsd, jed, fcst_time, index4)
subroutine, public fv_tp_2d(q, crx, cry, npx, npy, hord, fx, fy, xfx, yfx, gridstruct, bd, ra_x, ra_y, lim_fac, mfx, mfy, mass, nord, damp_c)
The subroutine 'fv_tp_2d' contains the FV advection scheme .
real, public current_time_in_seconds
The module 'fv_mp_mod' is a single program multiple data (SPMD) parallel decompostion/communication m...
subroutine timing_off(blk_name)
The subroutine 'timing_off' stops a timer.
The type 'fv_grid_type' is made up of grid-dependent information from fv_grid_tools and fv_grid_utils...
real, dimension(:,:,:), allocatable nest_fx_west_accum
real, dimension(:,:,:), allocatable nest_fx_south_accum
The module 'fv_timing' contains FV3 timers.
The module 'boundary' contains utility routines for grid nesting and boundary conditions.
The module 'tp_core' is a collection of routines to support FV transport.
The module 'fv_tracer2d.F90' performs sub-cycled tracer advection.
subroutine, public tracer_2d_nested(q, dp1, mfx, mfy, cx, cy, gridstruct, bd, domain, npx, npy, npz, nq, hord, q_split, dt, id_divg, q_pack, nord_tr, trdm, k_split, neststruct, parent_grid, n_map, lim_fac)
The module 'fv_arrays' contains the 'fv_atmos_type' and associated datatypes.
subroutine timing_on(blk_name)
The subroutine 'timing_on' starts a timer.
real, dimension(:,:,:), allocatable nest_fx_east_accum
subroutine, public copy_corners(q, npx, npy, dir, bounded_domain, bd, sw_corner, se_corner, nw_corner, ne_corner)
subroutine, public nested_grid_bc_apply_intt(var_nest, istag, jstag, npx, npy, npz, bd, step, split, BC, bctype)
The subroutine 'nested_grid_BC_apply_intT' performs linear interpolation or extrapolation in time for...
subroutine, public tracer_2d_1l(q, dp1, mfx, mfy, cx, cy, gridstruct, bd, domain, npx, npy, npz, nq, hord, q_split, dt, id_divg, q_pack, nord_tr, trdm, lim_fac)
The subroutine 'tracer_2d_1L' performs 2-D horizontal-to-lagrangian transport.
real, dimension(:,:,:), allocatable nest_fx_north_accum
subroutine, public tracer_2d(q, dp1, mfx, mfy, cx, cy, gridstruct, bd, domain, npx, npy, npz, nq, hord, q_split, dt, id_divg, q_pack, nord_tr, trdm, lim_fac)
The subroutine 'tracer_2d' is the standard routine for sub-cycled tracer advection.