1 !wrf:MODEL_LAYER:DYNAMICS
13 MODULE module_big_step_utilities_em
15 USE module_model_constants
16 USE module_state_description, only: p_qg, p_qs, p_qi, gdscheme, tiedtkescheme, kfetascheme, g3scheme, &
17 p_qv, param_first_scalar, p_qr, p_qc
18 USE module_configure, ONLY : grid_config_rec_type
22 !-------------------------------------------------------------------------------
24 SUBROUTINE calc_mu_uv ( config_flags, &
26 ids, ide, jds, jde, kds, kde, &
27 ims, ime, jms, jme, kms, kme, &
28 its, ite, jts, jte, kts, kte )
34 TYPE(grid_config_rec_type ) , INTENT(IN ) :: config_flags
36 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
37 ims, ime, jms, jme, kms, kme, &
38 its, ite, jts, jte, kts, kte
40 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT( OUT) :: muu, muv
41 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu, mub
45 INTEGER :: i, j, itf, jtf, im, jm
49 ! calc_mu_uv calculates the full column dry-air mass at the staggered
50 ! horizontal velocity points (u,v) and places the results in muu and muv.
51 ! This routine uses the reference state (mub) and perturbation state (mu)
59 IF ( ( its .NE. ids ) .AND. ( ite .NE. ide ) ) THEN
62 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
65 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .NE. ide ) ) THEN
68 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
73 if(config_flags%periodic_x) im = its-1
75 ! muu(i,j) = mu(i,j) +mub(i,j)
76 ! fix for periodic b.c., 13 march 2004, wcs
77 muu(i,j) = 0.5*(mu(i,j)+mu(im,j)+mub(i,j)+mub(im,j))
79 ELSE IF ( ( its .NE. ids ) .AND. ( ite .EQ. ide ) ) THEN
82 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
87 if(config_flags%periodic_x) im = ite
89 ! muu(i,j) = mu(i-1,j) +mub(i-1,j)
90 ! fix for periodic b.c., 13 march 2004, wcs
91 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j)+mub(i-1,j)+mub(im,j))
93 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .EQ. ide ) ) THEN
96 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
101 if(config_flags%periodic_x) im = its-1
103 ! muu(i,j) = mu(i,j) +mub(i,j)
104 ! fix for periodic b.c., 13 march 2004, wcs
105 muu(i,j) = 0.5*(mu(i,j)+mu(im,j)+mub(i,j)+mub(im,j))
109 if(config_flags%periodic_x) im = ite
111 ! muu(i,j) = mu(i-1,j) +mub(i-1,j)
112 ! fix for periodic b.c., 13 march 2004, wcs
113 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j)+mub(i-1,j)+mub(im,j))
120 IF ( ( jts .NE. jds ) .AND. ( jte .NE. jde ) ) THEN
123 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
126 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .NE. jde ) ) THEN
129 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
134 if(config_flags%periodic_y) jm = jts-1
136 ! muv(i,j) = mu(i,j) +mub(i,j)
137 ! fix for periodic b.c., 13 march 2004, wcs
138 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm)+mub(i,j)+mub(i,jm))
140 ELSE IF ( ( jts .NE. jds ) .AND. ( jte .EQ. jde ) ) THEN
143 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
148 if(config_flags%periodic_y) jm = jte
150 muv(i,j) = mu(i,j-1) +mub(i,j-1)
151 ! fix for periodic b.c., 13 march 2004, wcs
152 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm)+mub(i,j-1)+mub(i,jm))
154 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .EQ. jde ) ) THEN
157 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
162 if(config_flags%periodic_y) jm = jts-1
164 ! muv(i,j) = mu(i,j) +mub(i,j)
165 ! fix for periodic b.c., 13 march 2004, wcs
166 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm)+mub(i,j)+mub(i,jm))
170 if(config_flags%periodic_y) jm = jte
172 ! muv(i,j) = mu(i,j-1) +mub(i,j-1)
173 ! fix for periodic b.c., 13 march 2004, wcs
174 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm)+mub(i,j-1)+mub(i,jm))
178 END SUBROUTINE calc_mu_uv
180 !-------------------------------------------------------------------------------
182 SUBROUTINE calc_mu_uv_1 ( config_flags, &
184 ids, ide, jds, jde, kds, kde, &
185 ims, ime, jms, jme, kms, kme, &
186 its, ite, jts, jte, kts, kte )
192 TYPE(grid_config_rec_type ) , INTENT(IN ) :: config_flags
194 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
195 ims, ime, jms, jme, kms, kme, &
196 its, ite, jts, jte, kts, kte
198 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT( OUT) :: muu, muv
199 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu
203 INTEGER :: i, j, itf, jtf, im, jm
207 ! calc_mu_uv calculates the full column dry-air mass at the staggered
208 ! horizontal velocity points (u,v) and places the results in muu and muv.
209 ! This routine uses the full state (mu)
216 IF ( ( its .NE. ids ) .AND. ( ite .NE. ide ) ) THEN
219 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
222 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .NE. ide ) ) THEN
225 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
230 if(config_flags%periodic_x) im = its-1
232 muu(i,j) = 0.5*(mu(i,j)+mu(im,j))
234 ELSE IF ( ( its .NE. ids ) .AND. ( ite .EQ. ide ) ) THEN
237 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
242 if(config_flags%periodic_x) im = ite
244 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j))
246 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .EQ. ide ) ) THEN
249 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
254 if(config_flags%periodic_x) im = its-1
256 muu(i,j) = 0.5*(mu(i,j)+mu(im,j))
260 if(config_flags%periodic_x) im = ite
262 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j))
269 IF ( ( jts .NE. jds ) .AND. ( jte .NE. jde ) ) THEN
272 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
275 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .NE. jde ) ) THEN
278 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
283 if(config_flags%periodic_y) jm = jts-1
285 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm))
287 ELSE IF ( ( jts .NE. jds ) .AND. ( jte .EQ. jde ) ) THEN
290 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
295 if(config_flags%periodic_y) jm = jte
297 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm))
299 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .EQ. jde ) ) THEN
302 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
307 if(config_flags%periodic_y) jm = jts-1
309 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm))
313 if(config_flags%periodic_y) jm = jte
315 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm))
319 END SUBROUTINE calc_mu_uv_1
321 !-------------------------------------------------------------------------------
323 ! Map scale factor comments for this routine:
324 ! Locally not changed, but sent the correct map scale factors
325 ! from module_em (msfuy, msfvx, msfty)
327 SUBROUTINE couple_momentum ( muu, ru, u, msfu, &
328 muv, rv, v, msfv, msfv_inv, &
330 ids, ide, jds, jde, kds, kde, &
331 ims, ime, jms, jme, kms, kme, &
332 its, ite, jts, jte, kts, kte )
338 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
339 ims, ime, jms, jme, kms, kme, &
340 its, ite, jts, jte, kts, kte
342 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT( OUT) :: ru, rv, rw
344 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muu, muv, mut
345 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfu, msfv, msft, msfv_inv
347 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: u, v, w
351 INTEGER :: i, j, k, itf, jtf, ktf
355 ! couple_momentum couples the velocities to the full column mass and
368 ru(i,k,j)=u(i,k,j)*muu(i,j)/msfu(i,j)
379 rv(i,k,j)=v(i,k,j)*muv(i,j)*msfv_inv(i,j)
380 ! rv(i,k,j)=v(i,k,j)*muv(i,j)/msfv(i,j)
391 rw(i,k,j)=w(i,k,j)*mut(i,j)/msft(i,j)
396 END SUBROUTINE couple_momentum
398 !-------------------------------------------------------------------
400 SUBROUTINE calc_mu_staggered ( mu, mub, muu, muv, &
401 ids, ide, jds, jde, kds, kde, &
402 ims, ime, jms, jme, kms, kme, &
403 its, ite, jts, jte, kts, kte )
409 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
410 ims, ime, jms, jme, kms, kme, &
411 its, ite, jts, jte, kts, kte
413 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT( OUT) :: muu, muv
414 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu, mub
418 INTEGER :: i, j, itf, jtf
422 ! calc_mu_staggered calculates the full dry air mass at the staggered
423 ! velocity points (u,v).
430 IF ( ( its .NE. ids ) .AND. ( ite .NE. ide ) ) THEN
433 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
436 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .NE. ide ) ) THEN
439 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
444 muu(i,j) = mu(i,j) +mub(i,j)
446 ELSE IF ( ( its .NE. ids ) .AND. ( ite .EQ. ide ) ) THEN
449 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
454 muu(i,j) = mu(i-1,j) +mub(i-1,j)
456 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .EQ. ide ) ) THEN
459 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
464 muu(i,j) = mu(i,j) +mub(i,j)
468 muu(i,j) = mu(i-1,j) +mub(i-1,j)
475 IF ( ( jts .NE. jds ) .AND. ( jte .NE. jde ) ) THEN
478 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
481 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .NE. jde ) ) THEN
484 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
489 muv(i,j) = mu(i,j) +mub(i,j)
491 ELSE IF ( ( jts .NE. jds ) .AND. ( jte .EQ. jde ) ) THEN
494 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
499 muv(i,j) = mu(i,j-1) +mub(i,j-1)
501 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .EQ. jde ) ) THEN
504 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
509 muv(i,j) = mu(i,j) +mub(i,j)
513 muv(i,j) = mu(i,j-1) +mub(i,j-1)
517 END SUBROUTINE calc_mu_staggered
519 !-------------------------------------------------------------------------------
521 SUBROUTINE couple ( mu, mub, rfield, field, name, &
523 ids, ide, jds, jde, kds, kde, &
524 ims, ime, jms, jme, kms, kme, &
525 its, ite, jts, jte, kts, kte )
531 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
532 ims, ime, jms, jme, kms, kme, &
533 its, ite, jts, jte, kts, kte
535 CHARACTER(LEN=1) , INTENT(IN ) :: name
537 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT( OUT) :: rfield
539 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu, mub, msf
541 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: field
545 INTEGER :: i, j, k, itf, jtf, ktf
546 REAL , DIMENSION(ims:ime,jms:jme) :: muu , muv
550 ! subroutine couple couples the input variable with the dry-air
558 IF (name .EQ. 'u')THEN
560 CALL calc_mu_staggered ( mu, mub, muu, muv, &
561 ids, ide, jds, jde, kds, kde, &
562 ims, ime, jms, jme, kms, kme, &
563 its, ite, jts, jte, kts, kte )
571 rfield(i,k,j)=field(i,k,j)*muu(i,j)/msf(i,j)
576 ELSE IF (name .EQ. 'v')THEN
578 CALL calc_mu_staggered ( mu, mub, muu, muv, &
579 ids, ide, jds, jde, kds, kde, &
580 ims, ime, jms, jme, kms, kme, &
581 its, ite, jts, jte, kts, kte )
590 rfield(i,k,j)=field(i,k,j)*muv(i,j)/msf(i,j)
595 ELSE IF (name .EQ. 'w')THEN
601 rfield(i,k,j)=field(i,k,j)*(mu(i,j)+mub(i,j))/msf(i,j)
606 ELSE IF (name .EQ. 'h')THEN
612 rfield(i,k,j)=field(i,k,j)*(mu(i,j)+mub(i,j))
623 rfield(i,k,j)=field(i,k,j)*(mu(i,j)+mub(i,j))
630 END SUBROUTINE couple
633 !-------------------------------------------------------------------------------
635 SUBROUTINE calc_ww_cp ( u, v, mup, mub, ww, &
636 rdx, rdy, msftx, msfty, &
637 msfux, msfuy, msfvx, msfvx_inv, &
639 ids, ide, jds, jde, kds, kde, &
640 ims, ime, jms, jme, kms, kme, &
641 its, ite, jts, jte, kts, kte )
648 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
649 ims, ime, jms, jme, kms, kme, &
650 its, ite, jts, jte, kts, kte
652 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: u, v
653 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mup, mub, &
658 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: dnw
660 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT ) :: ww
661 REAL , INTENT(IN ) :: rdx, rdy
665 INTEGER :: i, j, k, itf, jtf, ktf
666 REAL , DIMENSION( its:ite ) :: dmdt
667 REAL , DIMENSION( its:ite, kts:kte ) :: divv
668 REAL , DIMENSION( its:ite+1, jts:jte+1 ) :: muu, muv
672 ! calc_ww calculates omega using the velocities (u,v) and the dry-air
673 ! column mass (mup+mub).
674 ! The algorithm integrates the continuity equation through the column
675 ! followed by a diagnosis of omega.
681 ! calc_ww_cp calculates omega using the velocities (u,v) and the
690 ! mu coupled with the appropriate map factor
693 DO i=its,min(ite+1,ide)
694 ! u is always coupled with my
695 muu(i,j) = 0.5*(mup(i,j)+mub(i,j)+mup(i-1,j)+mub(i-1,j))/msfuy(i,j)
699 DO j=jts,min(jte+1,jde)
701 ! v is always coupled with mx
702 ! muv(i,j) = 0.5*(mup(i,j)+mub(i,j)+mup(i,j-1)+mub(i,j-1))/msfvx(i,j)
703 muv(i,j) = 0.5*(mup(i,j)+mub(i,j)+mup(i,j-1)+mub(i,j-1))*msfvx_inv(i,j)
715 ! Comments on the modifications for map scale factors
716 ! ADT eqn 47 / my (putting rho -> 'mu') is:
717 ! (1/my) partial d mu/dt = -mx partial d/dx(mu u/my)
718 ! -mx partial d/dy(mu v/mx)
719 ! -partial d/dz(mu w/my)
721 ! Using nu instead of z the last term becomes:
722 ! -partial d/dnu(mu (dnu/dt)/my)
724 ! Integrating with respect to nu over ALL levels, with dnu/dt=0 at top
725 ! and bottom, the last term becomes = 0
727 ! Integral|bot->top[(1/my) partial d mu/dt]dnu =
728 ! Integral|bot->top[-mx partial d/dx(mu u/my)
729 ! -mx partial d/dy(mu v/mx)]dnu
731 ! muu='mu'[on u]/my, muv='mu'[on v]/mx
732 ! (1/my) partial d mu/dt is independent of nu
733 ! => LHS = Integral|bot->top[con]dnu = conservation*(-1) = -dmdt
735 ! => dmdt = mx*Integral|bot->top[partial d/dx(mu u/my) +
736 ! partial d/dy(mu v/mx)]dnu
737 ! => dmdt = sum_bot->top[divv]
739 ! divv=mx*[partial d/dx(mu u/my) + partial d/dy(mu v/mx)]*delta nu
744 divv(i,k) = msftx(i,j)*dnw(k)*( rdx*(muu(i+1,j)*u(i+1,k,j)-muu(i,j)*u(i,k,j)) &
745 +rdy*(muv(i,j+1)*v(i,k,j+1)-muv(i,j)*v(i,k,j)) )
747 ! dmdt(i) = dmdt(i) + dnw(k)* ( rdx*(ru(i+1,k,j)-ru(i,k,j)) &
748 ! +rdy*(rv(i,k,j+1)-rv(i,k,j)) )
750 dmdt(i) = dmdt(i) + divv(i,k)
756 ! Further map scale factor notes:
757 ! Now integrate from bottom to top, level by level:
758 ! mu dnu/dt/my [k+1] = mu dnu/dt/my [k] + [-(1/my) partial d mu/dt
759 ! -mx partial d/dx(mu u/my)
760 ! -mx partial d/dy(mu v/mx)]*dnu[k->k+1]
761 ! ww [k+1] = ww [k] -(1/my) partial d mu/dt * dnu[k->k+1] - divv[k]
762 ! = ww [k] -dmdt * dnw[k] - divv[k]
767 ! ww(i,k,j)=ww(i,k-1,j) &
768 ! - dnw(k-1)* ( dmdt(i) &
769 ! +rdx*(ru(i+1,k-1,j)-ru(i,k-1,j)) &
770 ! +rdy*(rv(i,k-1,j+1)-rv(i,k-1,j)) )
772 ww(i,k,j)=ww(i,k-1,j) - dnw(k-1)*dmdt(i) - divv(i,k-1)
779 END SUBROUTINE calc_ww_cp
782 !-------------------------------------------------------------------------------
784 SUBROUTINE calc_cq ( moist, cqu, cqv, cqw, n_moist, &
785 ids, ide, jds, jde, kds, kde, &
786 ims, ime, jms, jme, kms, kme, &
787 its, ite, jts, jte, kts, kte )
793 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
794 ims, ime, jms, jme, kms, kme, &
795 its, ite, jts, jte, kts, kte
797 INTEGER , INTENT(IN ) :: n_moist
800 REAL, DIMENSION( ims:ime, kms:kme , jms:jme , n_moist ), INTENT(IN ) :: moist
802 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT( OUT) :: cqu, cqv, cqw
808 INTEGER :: i, j, k, itf, jtf, ktf, ispe
812 ! calc_cq calculates moist coefficients for the momentum equations.
820 IF( n_moist >= PARAM_FIRST_SCALAR ) THEN
827 DO ispe=PARAM_FIRST_SCALAR,n_moist
828 qtot = qtot + moist(i,k,j,ispe) + moist(i-1,k,j,ispe)
830 ! qtot = 0.5*( moist(i ,k,j,1)+moist(i ,k,j,2)+moist(i ,k,j,3)+ &
831 ! & moist(i-1,k,j,1)+moist(i-1,k,j,2)+moist(i-1,k,j,3) )
832 ! cqu(i,k,j) = 1./(1.+qtot)
833 cqu(i,k,j) = 1./(1.+0.5*qtot)
846 DO ispe=PARAM_FIRST_SCALAR,n_moist
847 qtot = qtot + moist(i,k,j,ispe) + moist(i,k,j-1,ispe)
849 ! qtot = 0.5*( moist(i,k,j ,1)+moist(i,k,j ,2)+moist(i,k,j ,3)+ &
850 ! & moist(i,k,j-1,1)+moist(i,k,j-1,2)+moist(i,k,j-1,3) )
851 ! cqv(i,k,j) = 1./(1.+qtot)
852 cqv(i,k,j) = 1./(1.+0.5*qtot)
864 DO ispe=PARAM_FIRST_SCALAR,n_moist
865 qtot = qtot + moist(i,k,j,ispe) + moist(i,k-1,j,ispe)
867 ! qtot = 0.5*( moist(i,k ,j,1)+moist(i,k ,j,2)+moist(i,k-1,j,3)+ &
868 ! & moist(i,k-1,j,1)+moist(i,k-1,j,2)+moist(i,k ,j,3) )
870 cqw(i,k,j) = 0.5*qtot
908 END SUBROUTINE calc_cq
910 !----------------------------------------------------------------------
912 SUBROUTINE calc_alt ( alt, al, alb, &
913 ids, ide, jds, jde, kds, kde, &
914 ims, ime, jms, jme, kms, kme, &
915 its, ite, jts, jte, kts, kte )
921 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
922 ims, ime, jms, jme, kms, kme, &
923 its, ite, jts, jte, kts, kte
925 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(IN ) :: alb, al
926 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT( OUT) :: alt
930 INTEGER :: i, j, k, itf, jtf, ktf
934 ! calc_alt computes the full inverse density
945 alt(i,k,j) = al(i,k,j)+alb(i,k,j)
951 END SUBROUTINE calc_alt
953 !----------------------------------------------------------------------
955 SUBROUTINE calc_p_rho_phi ( moist, n_moist, hypsometric_opt, &
956 al, alb, mu, muts, ph, phb, p, pb, &
957 t, p0, t0, ptop, znu, znw, dnw, rdnw, &
958 rdn, non_hydrostatic, &
959 ids, ide, jds, jde, kds, kde, &
960 ims, ime, jms, jme, kms, kme, &
961 its, ite, jts, jte, kts, kte )
967 LOGICAL , INTENT(IN ) :: non_hydrostatic
969 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
970 ims, ime, jms, jme, kms, kme, &
971 its, ite, jts, jte, kts, kte
973 INTEGER , INTENT(IN ) :: n_moist
974 INTEGER , INTENT(IN ) :: hypsometric_opt
976 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(IN ) :: alb, &
980 REAL, DIMENSION( ims:ime , kms:kme , jms:jme, n_moist ), INTENT(IN ) :: moist
982 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT( OUT) :: al, p
984 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(INOUT) :: ph, phb
986 REAL, DIMENSION( ims:ime , jms:jme ), INTENT(IN ) :: mu, muts
988 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: znu, znw, dnw, rdnw, rdn
990 REAL, INTENT(IN ) :: t0, p0, ptop
994 INTEGER :: i, j, k, itf, jtf, ktf, ispe
995 REAL :: qvf, qtot, qf1, qf2
996 REAL, DIMENSION( its:ite) :: temp,cpovcv_v
997 REAL :: pfu, phm, pfd
1001 ! For the nonhydrostatic option, calc_p_rho_phi calculates the
1002 ! diagnostic quantities pressure and (inverse) density from the
1003 ! prognostic variables using the equation of state.
1005 ! For the hydrostatic option, calc_p_rho_phi calculates the
1006 ! diagnostic quantities (inverse) density and geopotential from the
1007 ! prognostic variables using the equation of state and the hydrostatic
1020 IF (non_hydrostatic) THEN
1022 IF (hypsometric_opt == 1) THEN
1026 al(i,k,j)=-1./muts(i,j)*(alb(i,k,j)*mu(i,j) + rdnw(k)*(ph(i,k+1,j)-ph(i,k,j)))
1030 ELSE IF (hypsometric_opt == 2) THEN
1032 ! The relation used to get specific volume, al, is: al = -dZ/dp,
1033 ! where dp = mut * d(eta). The pressure depth, dp, is replaced with
1034 ! p*(dp/p) ~ p*LOG((p+0.5dp)/(p-0.5dp)). Difference between dp and p*dLOG(p)
1035 ! is as follows: p*dLOG(p) - dp = 1/12*(dp/p)**3 + 1/90*(dp/p)**5 + ...
1036 ! Therefore, p*dLOG(p) is always larger than dp and the difference is
1037 ! in proportion to dp/p. TKW, 02/16/2010
1042 pfu = muts(i,j)*znw(k+1)+ptop
1043 pfd = muts(i,j)*znw(k) +ptop
1044 phm = muts(i,j)*znu(k) +ptop
1045 al(i,k,j) = (ph(i,k+1,j)-ph(i,k,j)+phb(i,k+1,j)-phb(i,k,j))/phm/LOG(pfd/pfu)-alb(i,k,j)
1050 CALL wrf_error_fatal ( 'calc_p_rho_phi: hypsometric_opt should be 1 or 2' )
1053 IF (n_moist >= PARAM_FIRST_SCALAR ) THEN
1058 qvf = 1.+rvovrd*moist(i,k,j,P_QV)
1059 temp(i)=(r_d*(t0+t(i,k,j))*qvf)/(p0*(al(i,k,j)+alb(i,k,j)))
1062 CALL VPOWX ( itf-its+1, temp(its), cpovcv, p(its,k,j) )
1064 ! use vector version from libmassv or from compat lib in frame/libmassv.F
1065 CALL VPOW ( p(its,k,j), temp(its), cpovcv_v(its), itf-its+1 )
1068 p(i,k,j)= p(i,k,j)*p0-pb(i,k,j)
1078 p(i,k,j)=p0*( (r_d*(t0+t(i,k,j)))/ &
1079 (p0*(al(i,k,j)+alb(i,k,j))) )**cpovcv &
1089 ! hydrostatic pressure, al, and ph1 calc; WCS, 5 sept 2001
1092 IF (n_moist >= PARAM_FIRST_SCALAR ) THEN
1100 DO ispe=PARAM_FIRST_SCALAR,n_moist
1101 qtot = qtot + moist(i,k,j,ispe)
1106 p(i,k,j) = - 0.5*(mu(i,j)+qf1*muts(i,j))/rdnw(k)/qf2
1107 qvf = 1.+rvovrd*moist(i,k,j,P_QV)
1108 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1109 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1113 DO k=ktf-1,kts,-1 ! remaining layers, integrate down
1117 DO ispe=PARAM_FIRST_SCALAR,n_moist
1118 qtot = qtot + 0.5*( moist(i,k ,j,ispe) + moist(i,k+1,j,ispe) )
1123 p(i,k,j) = p(i,k+1,j) - (mu(i,j) + qf1*muts(i,j))/qf2/rdn(k+1)
1124 qvf = 1.+rvovrd*moist(i,k,j,P_QV)
1125 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1126 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1143 p(i,k,j) = - 0.5*(mu(i,j)+qf1*muts(i,j))/rdnw(k)/qf2
1145 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1146 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1150 DO k=ktf-1,kts,-1 ! remaining layers, integrate down
1157 p(i,k,j) = p(i,k+1,j) - (mu(i,j) + qf1*muts(i,j))/qf2/rdn(k+1)
1159 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1160 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1168 IF (hypsometric_opt == 1) THEN
1170 DO k=2,ktf+1 ! integrate hydrostatic equation for geopotential
1172 ph(i,k,j) = ph(i,k-1,j) - (dnw(k-1))*( &
1173 (muts(i,j))*al(i,k-1,j)+ &
1174 mu(i,j)*alb(i,k-1,j) )
1180 ! Revised hypsometric eq.: dZ=-al*p*dLOG(p), where p is dry pressure
1184 ph(i,kts,j) = phb(i,kts,j)
1189 pfu = muts(i,j)*znw(k) +ptop
1190 pfd = muts(i,j)*znw(k-1)+ptop
1191 phm = muts(i,j)*znu(k-1)+ptop
1192 ph(i,k,j) = ph(i,k-1,j) + (al(i,k-1,j)+alb(i,k-1,j))*phm*LOG(pfd/pfu)
1198 ph(i,k,j) = ph(i,k,j) - phb(i,k,j)
1207 END SUBROUTINE calc_p_rho_phi
1209 !----------------------------------------------------------------------
1211 SUBROUTINE calc_php ( php, ph, phb, &
1212 ids, ide, jds, jde, kds, kde, &
1213 ims, ime, jms, jme, kms, kme, &
1214 its, ite, jts, jte, kts, kte )
1220 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
1221 ims, ime, jms, jme, kms, kme, &
1222 its, ite, jts, jte, kts, kte
1224 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: phb, ph
1225 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT( OUT) :: php
1229 INTEGER :: i, j, k, itf, jtf, ktf
1233 ! calc_php calculates the full geopotential from the reference state
1234 ! geopotential and the perturbation geopotential (phb_ph).
1245 php(i,k,j) = 0.5*(phb(i,k,j)+phb(i,k+1,j)+ph(i,k,j)+ph(i,k+1,j))
1250 END SUBROUTINE calc_php
1252 !-------------------------------------------------------------------------------
1254 SUBROUTINE diagnose_w( ph_tend, ph_new, ph_old, w, mu, dt, &
1256 cf1, cf2, cf3, rdx, rdy, &
1258 ids, ide, jds, jde, kds, kde, &
1259 ims, ime, jms, jme, kms, kme, &
1260 its, ite, jts, jte, kts, kte )
1264 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
1265 ims, ime, jms, jme, kms, kme, &
1266 its, ite, jts, jte, kts, kte
1268 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: ph_tend, &
1275 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT( OUT) :: w
1277 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: mu, ht, msftx, msfty
1279 REAL, INTENT(IN ) :: dt, cf1, cf2, cf3, rdx, rdy
1281 INTEGER :: i, j, k, itf, jtf
1288 ! diagnose_w diagnoses the vertical velocity from the geopoential equation.
1289 ! Used with the hydrostatic option.
1297 ! Notes on map scale factors:
1298 ! Chain rule: if Z=Z(X,Y) [true at the surface] then
1299 ! dZ/dt = dZ/dX * dX/dt + dZ/dY * dY/dt, U=dX/dt, V=dY/dt
1300 ! Using capitals to denote actual values
1301 ! In mapped values, u=U, v=V, z=Z, 1/dX=mx/dx, 1/dY=my/dy
1302 ! => w = dz/dt = mx u dz/dx + my v dz/dy
1303 ! [where dz/dx is just the surface height change between x
1304 ! gridpoints, and dz/dy is the change between y gridpoints]
1305 ! [NB: cf1, cf2 and cf3 do vertical weighting of u or v values
1306 ! nearest the surface]
1308 ! Previously msft multiplied by rdy and rdx terms.
1309 ! Now msfty multiplies rdy term, and msftx multiplies msftx term
1311 w(i,1,j)= msfty(i,j)*.5*rdy*( &
1312 (ht(i,j+1)-ht(i,j )) &
1313 *(cf1*v(i,1,j+1)+cf2*v(i,2,j+1)+cf3*v(i,3,j+1)) &
1314 +(ht(i,j )-ht(i,j-1)) &
1315 *(cf1*v(i,1,j )+cf2*v(i,2,j )+cf3*v(i,3,j )) ) &
1316 +msftx(i,j)*.5*rdx*( &
1317 (ht(i+1,j)-ht(i,j )) &
1318 *(cf1*u(i+1,1,j)+cf2*u(i+1,2,j)+cf3*u(i+1,3,j)) &
1319 +(ht(i,j )-ht(i-1,j)) &
1320 *(cf1*u(i ,1,j)+cf2*u(i ,2,j)+cf3*u(i ,3,j)) )
1323 ! use geopotential equation to diagnose w
1325 ! Further notes on map scale factors
1326 ! If ph_tend contains: -mx partial d/dx(mu rho u/my)
1327 ! -mx partial d/dy(phi mu v/mx)
1328 ! -partial d/dz(phi mu w/my)
1329 ! then phi eqn is: partial d/dt(mu phi/my) = ph_tend + mu g w/my
1330 ! => w = [my/(mu*g)]*[partial d/dt(mu phi/my) - ph_tend]
1334 w(i,k,j) = msfty(i,j)*( (ph_new(i,k,j)-ph_old(i,k,j))/dt &
1335 - ph_tend(i,k,j)/mu(i,j) )/g
1342 END SUBROUTINE diagnose_w
1344 !-------------------------------------------------------------------------------
1346 SUBROUTINE rhs_ph( ph_tend, u, v, ww, &
1347 ph, ph_old, phb, w, &
1350 rdnw, cfn, cfn1, rdx, rdy, &
1351 msfux, msfuy, msfvx, &
1356 ids, ide, jds, jde, kds, kde, &
1357 ims, ime, jms, jme, kms, kme, &
1358 its, ite, jts, jte, kts, kte )
1361 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
1363 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
1364 ims, ime, jms, jme, kms, kme, &
1365 its, ite, jts, jte, kts, kte
1367 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: &
1376 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: ph_tend
1378 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: muu, muv, mut, &
1384 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw, fnm, fnp
1386 REAL, INTENT(IN ) :: cfn, cfn1, rdx, rdy
1388 LOGICAL, INTENT(IN ) :: non_hydrostatic
1392 INTEGER :: i, j, k, itf, jtf, ktf, kz, i_start, j_start
1393 REAL :: ur, ul, ub, vr, vl, vb
1394 REAL, DIMENSION(its:ite,kts:kte) :: wdwn
1396 INTEGER :: advective_order
1398 LOGICAL :: specified
1402 ! rhs_ph calculates the large-timestep tendency terms for the geopotential
1403 ! equation. These terms include the advection and "gw". The geopotential
1404 ! equation is cast in advective form, so we don't use the flux form advection
1410 if(config_flags%specified .or. config_flags%nested) specified = .true.
1412 advective_order = config_flags%h_sca_adv_order
1418 ! Notes on map scale factors (WCS, 2 march 2008)
1419 ! phi equation is: mu/my d/dt(phi) = -(1/my) mx mu u d/dx(phi)
1420 ! -(1/my) my mu v d/dy(phi)
1421 ! - omega d/d_eta(phi)
1424 ! A little further explanation...
1425 ! The tendency term we are computing here is for mu/my d/dt(phi). It is advective form
1426 ! but it is multiplied be mu/my. It will be decoupled from (mu/my) when the implicit w-phi
1427 ! solution is computed in subourine advance_w. The formulation dates from the early
1428 ! days of the mass coordinate model when we were testing both a flux and an advective formulation
1429 ! for the geopotential equation and different forms of the vertical momentum equation and the
1430 ! vertically implicit solver.
1432 ! advective form for the geopotential equation
1438 wdwn(i,k) = .5*(ww(i,k,j)+ww(i,k-1,j))*rdnw(k-1) &
1439 *(ph(i,k,j)-ph(i,k-1,j)+phb(i,k,j)-phb(i,k-1,j))
1443 ! RHS term 3 is: - omega partial d/dnu(phi)
1447 ph_tend(i,k,j) = ph_tend(i,k,j) &
1448 - (fnm(k)*wdwn(i,k+1)+fnp(k)*wdwn(i,k))
1454 IF (non_hydrostatic) THEN ! add in "gw" term.
1455 DO j = jts, jtf ! in hydrostatic mode, "gw" will be diagnosed
1456 ! after the timestep to give us "w"
1458 ph_tend(i,kde,j) = 0.
1463 ! phi equation RHS term 4
1464 ph_tend(i,k,j) = ph_tend(i,k,j) + mut(i,j)*g*w(i,k,j)/msfty(i,j)
1472 ! Notes on map scale factors:
1473 ! RHS terms 1 and 2 are: -(1/my) mx u mu partial d/dx(phi)
1474 ! -(1/my) my v mu partial d/dy(phi)
1476 IF (advective_order <= 2) THEN
1485 IF ( (config_flags%open_ys .or. specified) .and. jts == jds ) j_start = jts+1
1486 IF ( (config_flags%open_ye .or. specified) .and. jte == jde ) jtf = jtf-2
1492 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1493 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1494 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1495 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1496 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1502 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1503 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1504 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1505 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1506 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1518 IF ( (config_flags%open_xs .or. specified) .and. its == ids ) i_start = its+1
1519 IF ( (config_flags%open_xe .or. specified) .and. ite == ide ) itf = itf-2
1525 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1526 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1527 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1528 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1529 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1535 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1536 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1537 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1538 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
1539 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1544 ELSE IF (advective_order <= 4) THEN
1553 IF ( (config_flags%open_ys .or. specified) .and. jts == jds ) j_start = jts+2
1554 IF ( (config_flags%open_ye .or. specified) .and. jte == jde ) jtf = jtf-3
1560 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))*( &
1561 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1562 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j ))* (1./12.)*( &
1563 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1564 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1565 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1566 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1574 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))*( &
1575 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1576 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j ))* (1./12.)*( &
1577 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1578 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1579 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1580 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1586 ! pick up near boundary rows using 2nd order stencil for open and specified conditions
1588 IF ( (config_flags%open_ys .or. specified) .and. jts <= jds+1 ) THEN
1593 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1594 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1595 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1596 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1597 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1603 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1604 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1605 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1606 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1607 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1612 IF ( (config_flags%open_ye .or. specified) .and. jte >= jde-2 ) THEN
1617 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1618 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1619 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1620 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1621 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1627 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1628 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1629 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1630 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1631 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1643 IF ( (config_flags%open_xs) .and. its == ids ) i_start = its+2
1644 IF ( (config_flags%open_xe) .and. ite == ide ) itf = itf-3
1650 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1651 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1652 +muu(i,j )*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j) )* (1./12.)*( &
1653 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1654 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1655 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1656 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1662 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1663 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1664 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux(i ,j) )* (1./12.)*( &
1665 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1666 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1667 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1668 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1673 ! pick up near boundary rows using 2nd order stencil for open and specified conditions
1675 IF ( (config_flags%open_xs .or. specified) .and. its <= ids+1 ) THEN
1681 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1682 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1683 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1684 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1685 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1691 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1692 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1693 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1694 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
1695 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1700 IF ( (config_flags%open_xe .or. specified) .and. ite >= ide-2 ) THEN
1705 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1706 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1707 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1708 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1709 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1715 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1716 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1717 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1718 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
1719 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1724 !--------------------------
1726 ELSE IF (advective_order <= 6) THEN
1728 !!! NOTE: this branch has been looked at and fixed with changes for overdecomposition
1729 !!! the branches covering the other advective_order cases have not. 20090923. JM
1738 IF (config_flags%open_ys .or. specified ) j_start = max(jts,jds+3)
1739 IF (config_flags%open_ye .or. specified ) jtf = min(jtf,jde-4)
1745 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* ( &
1746 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1747 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j ) )* (1./60.)*( &
1748 45.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1749 -9.*(ph(i,k,j+2)-ph(i,k,j-2)) &
1750 +(ph(i,k,j+3)-ph(i,k,j-3)) &
1751 +45.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1752 -9.*(phb(i,k,j+2)-phb(i,k,j-2)) &
1753 +(phb(i,k,j+3)-phb(i,k,j-3)) ) )
1761 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* ( &
1762 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1763 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j ) )* (1./60.)*( &
1764 45.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1765 -9.*(ph(i,k,j+2)-ph(i,k,j-2)) &
1766 +(ph(i,k,j+3)-ph(i,k,j-3)) &
1767 +45.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1768 -9.*(phb(i,k,j+2)-phb(i,k,j-2)) &
1769 +(phb(i,k,j+3)-phb(i,k,j-3)) ) )
1775 ! 4th order stencil for open or specified conditions two in form the boundary
1777 IF ( (config_flags%open_ys .or. specified) .and. jts <= jds+2 .and. jds+2 <= jte ) THEN
1782 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* ( &
1783 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1784 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j ) )* (1./12.)*( &
1785 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1786 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1787 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1788 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1796 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* ( &
1797 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1798 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j) )* (1./12.)*( &
1799 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1800 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1801 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1802 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1808 IF ( (config_flags%open_ye .or. specified) .and. jts <= jde-3 .and. jde-3 <= jte ) THEN
1812 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* ( &
1813 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1814 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j) )* (1./12.)*( &
1815 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1816 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1817 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1818 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1826 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* ( &
1827 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1828 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j) )* (1./12.)*( &
1829 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1830 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1831 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1832 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1838 ! 2nd order stencil for open and specified conditions one row in from boundary
1840 IF ( (config_flags%open_ys .or. specified) .and. jts <= jds+1 .and. jds+1 <= jte ) THEN
1845 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1846 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1847 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1848 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1849 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1855 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1856 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1857 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1858 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1859 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1864 IF ( (config_flags%open_ye .or. specified) .and. jts <= jde-2 .and. jde-2 <= jte ) THEN
1869 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1870 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1871 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1872 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1873 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1879 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1880 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1881 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1882 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1883 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1895 IF (config_flags%open_xs .or. specified ) i_start = max(its,ids+3)
1896 IF (config_flags%open_xe .or. specified ) itf = min(itf,ide-4)
1902 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1903 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1904 +muu(i,j )*(u(i,k,j )+u(i,k-1,j ))*msfux(i,j) )* (1./60.)*( &
1905 45.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1906 -9.*(ph(i+2,k,j)-ph(i-2,k,j)) &
1907 +(ph(i+3,k,j)-ph(i-3,k,j)) &
1908 +45.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1909 -9.*(phb(i+2,k,j)-phb(i-2,k,j)) &
1910 +(phb(i+3,k,j)-phb(i-3,k,j)) ) )
1916 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1917 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1918 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i,k-2,j))*msfux(i,j) )* (1./60.)*( &
1919 45.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1920 -9.*(ph(i+2,k,j)-ph(i-2,k,j)) &
1921 +(ph(i+3,k,j)-ph(i-3,k,j)) &
1922 +45.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1923 -9.*(phb(i+2,k,j)-phb(i-2,k,j)) &
1924 +(phb(i+3,k,j)-phb(i-3,k,j)) ) )
1929 ! 4th order stencil two in from the boundary for open and specified conditions
1931 IF ( (config_flags%open_xs) .and. its <= ids+2 .and. ids+2 <= ite ) THEN
1935 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1936 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1937 +muu(i,j )*(u(i,k,j )+u(i,k-1,j ))*msfux(i,j) )* (1./12.)*( &
1938 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1939 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1940 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1941 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1944 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1945 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1946 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i,k-2,j))*msfux(i,j) )* (1./12.)*( &
1947 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1948 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1949 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1950 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1955 IF ( (config_flags%open_xe) .and. its <= ide-3 .and. ide-3 <= ite ) THEN
1959 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1960 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1961 +muu(i,j )*(u(i,k,j )+u(i,k-1,j ))*msfux(i,j) )* (1./12.)*( &
1962 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1963 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1964 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1965 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1968 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1969 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1970 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i,k-2,j))*msfux(i,j) )* (1./12.)*( &
1971 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1972 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1973 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1974 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1979 ! 2nd order stencil for open and specified conditions one in from the boundary
1981 IF ( (config_flags%open_xs .or. specified) .and. its <= ids+1 .and. ids+1 <= ite ) THEN
1987 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1988 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1989 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1990 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1991 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1997 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1998 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1999 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
2000 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
2001 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
2006 IF ( (config_flags%open_xe .or. specified) .and. its <= ide-2 .and. ide-2 <= ite ) THEN
2011 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
2012 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
2013 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
2014 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
2015 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
2021 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
2022 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
2023 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
2024 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
2025 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
2030 END IF ! 6th order advection
2032 ! lateral open boundary conditions,
2033 ! start with north and south (y) boundaries
2040 IF ( (config_flags%open_ys) .and. jts == jds ) THEN
2047 vb =.5*( fnm(kz)*(v(i,kz ,j+1)+v(i,kz ,j )) &
2048 +fnp(kz)*(v(i,kz-1,j+1)+v(i,kz-1,j )) )
2050 ph_tend(i,k,j)=ph_tend(i,k,j)-rdy*mut(i,j)*( &
2051 +vl*(ph_old(i,k,j+1)-ph_old(i,k,j)))
2059 IF ( (config_flags%open_ye) .and. jte == jde ) THEN
2066 vb=.5*( fnm(kz)*(v(i,kz ,j+1)+v(i,kz ,j)) &
2067 +fnp(kz)*(v(i,kz-1,j+1)+v(i,kz-1,j)) )
2069 ph_tend(i,k,j)=ph_tend(i,k,j)-rdy*mut(i,j)*( &
2070 +vr*(ph_old(i,k,j)-ph_old(i,k,j-1)))
2076 ! now the east and west (y) boundaries
2083 IF ( (config_flags%open_xs) .and. its == ids ) THEN
2090 ub =.5*( fnm(kz)*(u(i+1,kz ,j)+u(i ,kz ,j)) &
2091 +fnp(kz)*(u(i+1,kz-1,j)+u(i ,kz-1,j)) )
2093 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2094 +ul*(ph_old(i+1,k,j)-ph_old(i,k,j)))
2099 ub =.5*( fnm(kz)*(u(i+1,kz ,j)+u(i ,kz ,j)) &
2100 +fnp(kz)*(u(i+1,kz-1,j)+u(i ,kz-1,j)) )
2102 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2103 +ul*(ph_old(i+1,k,j)-ph_old(i,k,j)))
2110 IF ( (config_flags%open_xe) .and. ite == ide ) THEN
2117 ub=.5*( fnm(kz)*(u(i+1,kz ,j)+u(i,kz ,j)) &
2118 +fnp(kz)*(u(i+1,kz-1,j)+u(i,kz-1,j)) )
2120 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2121 +ur*(ph_old(i,k,j)-ph_old(i-1,k,j)))
2126 ub=.5*( fnm(kz)*(u(i+1,kz ,j)+u(i,kz ,j)) &
2127 +fnp(kz)*(u(i+1,kz-1,j)+u(i,kz-1,j)) )
2129 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2130 +ur*(ph_old(i,k,j)-ph_old(i-1,k,j)))
2136 END SUBROUTINE rhs_ph
2139 !-------------------------------------------------------------------------------
2141 SUBROUTINE horizontal_pressure_gradient( ru_tend,rv_tend, &
2142 ph,alt,p,pb,al,php,cqu,cqv, &
2143 muu,muv,mu,fnm,fnp,rdnw, &
2144 cf1,cf2,cf3,rdx,rdy,msfux,msfuy,&
2145 msfvx,msfvy,msftx,msfty, &
2146 config_flags, non_hydrostatic, &
2148 ids, ide, jds, jde, kds, kde, &
2149 ims, ime, jms, jme, kms, kme, &
2150 its, ite, jts, jte, kts, kte )
2157 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2159 LOGICAL, INTENT (IN ) :: non_hydrostatic, top_lid
2161 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2162 ims, ime, jms, jme, kms, kme, &
2163 its, ite, jts, jte, kts, kte
2165 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: &
2176 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: &
2180 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: muu, muv, mu, &
2185 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw, fnm, fnp
2187 REAL, INTENT(IN ) :: rdx, rdy, cf1, cf2, cf3
2189 INTEGER :: i,j,k, itf, jtf, ktf, i_start, j_start
2190 REAL, DIMENSION( ims:ime, kms:kme ) :: dpn
2193 LOGICAL :: specified
2197 ! horizontal_pressure_gradient calculates the
2198 ! horizontal pressure gradient terms for the large-timestep tendency
2199 ! in the horizontal momentum equations (u,v).
2204 if(config_flags%specified .or. config_flags%nested) specified = .true.
2206 ! Notes on map scale factors:
2207 ! Calculates the pressure gradient terms in ADT eqns 44 and 45
2208 ! With upper rho -> 'mu', these are:
2209 ! Eqn 30: -mu*(mx/my)*(1/rho)*partial dp/dx
2210 ! Eqn 31: -mu*(my/mx)*(1/rho)*partial dp/dy
2212 ! As we are on nu, rather than height, surfaces:
2214 ! mu dp/dx = mu alpha partial dp'/dx + (nu mu partial dmubar/dx) alpha'
2215 ! + mu partial dphi'/dx + (partial dphi/dx)*(partial dp'/dnu - mu')
2217 ! mu dp/dy = mu alpha partial dp'/dy + (nu mu partial dmubar/dy) alpha'
2218 ! + mu partial dphi'/dy + (partial dphi/dy)*(partial dp'/dnu - mu')
2220 ! start with the north-south (y) pressure gradient
2227 IF ( (config_flags%open_ys .or. specified .or. &
2228 config_flags%nested .or. config_flags%polar ) .and. jts == jds ) j_start = jts+1
2229 IF ( (config_flags%open_ye .or. specified .or. &
2230 config_flags%nested .or. config_flags%polar ) .and. jte == jde ) jtf = jtf-1
2234 IF ( non_hydrostatic ) THEN
2239 dpn(i,k) = .5*( cf1*(p(i,k ,j-1)+p(i,k ,j)) &
2240 +cf2*(p(i,k+1,j-1)+p(i,k+1,j)) &
2241 +cf3*(p(i,k+2,j-1)+p(i,k+2,j)) )
2246 dpn(i,kde) = .5*( cf1*(p(i,kde-1,j-1)+p(i,kde-1,j)) &
2247 +cf2*(p(i,kde-2,j-1)+p(i,kde-2,j)) &
2248 +cf3*(p(i,kde-3,j-1)+p(i,kde-3,j)) )
2254 dpn(i,k) = .5*( fnm(k)*(p(i,k ,j-1)+p(i,k ,j)) &
2255 +fnp(k)*(p(i,k-1,j-1)+p(i,k-1,j)) )
2259 ! ADT eqn 45: -mu*(my/mx)*(1/rho)*partial dp/dy
2260 ! [alt, al are 1/rho terms; muv, mu are NOT coupled]
2263 ! Here are mu dp/dy terms 1-3
2264 dpy = (msfvy(i,j)/msfvx(i,j))*.5*rdy*muv(i,j)*( &
2265 (ph (i,k+1,j)-ph (i,k+1,j-1) + ph(i,k,j)-ph(i,k,j-1)) &
2266 +(alt(i,k ,j)+alt(i,k ,j-1))*(p (i,k,j)-p (i,k,j-1)) &
2267 +(al (i,k ,j)+al (i,k ,j-1))*(pb(i,k,j)-pb(i,k,j-1)) )
2268 ! Here is mu dp/dy term 4
2269 dpy = dpy + (msfvy(i,j)/msfvx(i,j))*rdy*(php(i,k,j)-php(i,k,j-1))* &
2270 (rdnw(k)*(dpn(i,k+1)-dpn(i,k))-.5*(mu(i,j-1)+mu(i,j)))
2271 rv_tend(i,k,j) = rv_tend(i,k,j)-cqv(i,k,j)*dpy
2277 ! ADT eqn 45: -mu*(my/mx)*(1/rho)*partial dp/dy
2278 ! [alt, al are 1/rho terms; muv, mu are NOT coupled]
2281 ! Here are mu dp/dy terms 1-3; term 4 not needed if hydrostatic
2282 dpy = (msfvy(i,j)/msfvx(i,j))*.5*rdy*muv(i,j)*( &
2283 (ph (i,k+1,j)-ph (i,k+1,j-1) + ph(i,k,j)-ph(i,k,j-1)) &
2284 +(alt(i,k ,j)+alt(i,k ,j-1))*(p (i,k,j)-p (i,k,j-1)) &
2285 +(al (i,k ,j)+al (i,k ,j-1))*(pb(i,k,j)-pb(i,k,j-1)) )
2286 rv_tend(i,k,j) = rv_tend(i,k,j)-cqv(i,k,j)*dpy
2294 ! now the east-west (x) pressure gradient
2301 IF ( (config_flags%open_xs .or. specified .or. &
2302 config_flags%nested ) .and. its == ids ) i_start = its+1
2303 IF ( (config_flags%open_xe .or. specified .or. &
2304 config_flags%nested ) .and. ite == ide ) itf = itf-1
2305 IF ( config_flags%periodic_x ) i_start = its
2306 IF ( config_flags%periodic_x ) itf=ite
2310 IF ( non_hydrostatic ) THEN
2315 dpn(i,k) = .5*( cf1*(p(i-1,k ,j)+p(i,k ,j)) &
2316 +cf2*(p(i-1,k+1,j)+p(i,k+1,j)) &
2317 +cf3*(p(i-1,k+2,j)+p(i,k+2,j)) )
2322 dpn(i,kde) = .5*( cf1*(p(i-1,kde-1,j)+p(i,kde-1,j)) &
2323 +cf2*(p(i-1,kde-2,j)+p(i,kde-2,j)) &
2324 +cf3*(p(i-1,kde-3,j)+p(i,kde-3,j)) )
2330 dpn(i,k) = .5*( fnm(k)*(p(i-1,k ,j)+p(i,k ,j)) &
2331 +fnp(k)*(p(i-1,k-1,j)+p(i,k-1,j)) )
2335 ! ADT eqn 44: -mu*(mx/my)*(1/rho)*partial dp/dx
2336 ! [alt, al are 1/rho terms; muu, mu are NOT coupled]
2339 ! Here are mu dp/dy terms 1-3
2340 dpx = (msfux(i,j)/msfuy(i,j))*.5*rdx*muu(i,j)*( &
2341 (ph (i,k+1,j)-ph (i-1,k+1,j) + ph(i,k,j)-ph(i-1,k,j)) &
2342 +(alt(i,k ,j)+alt(i-1,k ,j))*(p (i,k,j)-p (i-1,k,j)) &
2343 +(al (i,k ,j)+al (i-1,k ,j))*(pb(i,k,j)-pb(i-1,k,j)) )
2344 ! Here is mu dp/dy term 4
2345 dpx = dpx + (msfux(i,j)/msfuy(i,j))*rdx*(php(i,k,j)-php(i-1,k,j))* &
2346 (rdnw(k)*(dpn(i,k+1)-dpn(i,k))-.5*(mu(i-1,j)+mu(i,j)))
2347 ru_tend(i,k,j) = ru_tend(i,k,j)-cqu(i,k,j)*dpx
2353 ! ADT eqn 44: -mu*(mx/my)*(1/rho)*partial dp/dx
2354 ! [alt, al are 1/rho terms; muu, mu are NOT coupled]
2357 ! Here are mu dp/dy terms 1-3; term 4 not needed if hydrostatic
2358 dpx = (msfux(i,j)/msfuy(i,j))*.5*rdx*muu(i,j)*( &
2359 (ph (i,k+1,j)-ph (i-1,k+1,j) + ph(i,k,j)-ph(i-1,k,j)) &
2360 +(alt(i,k ,j)+alt(i-1,k ,j))*(p (i,k,j)-p (i-1,k,j)) &
2361 +(al (i,k ,j)+al (i-1,k ,j))*(pb(i,k,j)-pb(i-1,k,j)) )
2362 ru_tend(i,k,j) = ru_tend(i,k,j)-cqu(i,k,j)*dpx
2370 END SUBROUTINE horizontal_pressure_gradient
2372 !-------------------------------------------------------------------------------
2374 SUBROUTINE pg_buoy_w( rw_tend, p, cqw, mu, mub, &
2375 rdnw, rdn, g, msftx, msfty, &
2376 ids, ide, jds, jde, kds, kde, &
2377 ims, ime, jms, jme, kms, kme, &
2378 its, ite, jts, jte, kts, kte )
2384 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2385 ims, ime, jms, jme, kms, kme, &
2386 its, ite, jts, jte, kts, kte
2388 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: p
2389 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: cqw
2392 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: rw_tend
2394 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: mub, mu, msftx, msfty
2396 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw, rdn
2398 REAL, INTENT(IN ) :: g
2400 INTEGER :: itf, jtf, i, j, k
2406 ! pg_buoy_w calculates the
2407 ! vertical pressure gradient and buoyancy terms for the large-timestep
2408 ! tendency in the vertical momentum equation.
2412 ! BUOYANCY AND PRESSURE GRADIENT TERM IN W EQUATION AT TIME T
2414 ! Map scale factor notes
2415 ! ADT eqn 46 RHS terms 6 and 7 (where 7 is "-rho g")
2416 ! Dividing by my, and using mu and nu (see Klemp et al. eqns 32, 40)
2417 ! term 6: +(g/my) partial dp'/dnu
2418 ! term 7: -(g/my) mu'
2420 ! For moisture-free atmosphere, cq1=1, cq2=0
2421 ! => (1./msft(i,j)) * g * [rdn(k)*{p(i,k,j)-p(i,k-1,j)}-mu(i,j)]
2430 cq1 = 1./(1.+cqw(i,k-1,j))
2431 cq2 = cqw(i,k-1,j)*cq1
2432 rw_tend(i,k,j) = rw_tend(i,k,j)+(1./msfty(i,j))*g*( &
2433 cq1*2.*rdnw(k-1)*( -p(i,k-1,j)) &
2434 -mu(i,j)-cq2*mub(i,j) )
2439 cq1 = 1./(1.+cqw(i,k,j))
2440 cq2 = cqw(i,k,j)*cq1
2442 rw_tend(i,k,j) = rw_tend(i,k,j)+(1./msfty(i,j))*g*( &
2443 cq1*rdn(k)*(p(i,k,j)-p(i,k-1,j)) &
2444 -mu(i,j)-cq2*mub(i,j) )
2451 END SUBROUTINE pg_buoy_w
2453 !-------------------------------------------------------------------------------
2455 SUBROUTINE w_damp( rw_tend, max_vert_cfl,max_horiz_cfl, &
2456 u, v, ww, w, mut, rdnw, &
2457 rdx, rdy, msfux, msfuy, &
2460 ids, ide, jds, jde, kds, kde, &
2461 ims, ime, jms, jme, kms, kme, &
2462 its, ite, jts, jte, kts, kte )
2469 TYPE(grid_config_rec_type ) , INTENT(IN ) :: config_flags
2471 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2472 ims, ime, jms, jme, kms, kme, &
2473 its, ite, jts, jte, kts, kte
2475 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: u, v, ww, w
2477 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: rw_tend
2479 REAL, INTENT(OUT) :: max_vert_cfl
2480 REAL, INTENT(OUT) :: max_horiz_cfl
2483 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: mut
2485 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw
2487 REAL, INTENT(IN) :: dt
2488 REAL, INTENT(IN) :: rdx, rdy
2489 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, msfuy
2490 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfvx, msfvy
2492 REAL :: vert_cfl, cf_n, cf_d, maxdub, maxdeta
2494 INTEGER :: itf, jtf, i, j, k, maxi, maxj, maxk
2496 CHARACTER*512 :: temp
2498 CHARACTER (LEN=256) :: time_str
2499 CHARACTER (LEN=256) :: grid_str
2502 REAL :: msfuxt , msfxffl
2506 ! w_damp computes a damping term for the vertical velocity when the
2507 ! vertical Courant number is too large. This was found to be preferable to
2508 ! decreasing the timestep or increasing the diffusion in real-data applications
2509 ! that produced potentially-unstable large vertical velocities because of
2510 ! unphysically large heating rates coming from the cumulus parameterization
2511 ! schemes run at moderately high resolutions (dx ~ O(10) km).
2513 ! Additionally, w_damp returns the maximum cfl values due to vertical motion and
2514 ! horizontal motion. These values are returned via the max_vert_cfl and
2515 ! max_horiz_cfl variables. (Added by T. Hutchinson, WSI, 3/5/2007)
2527 IF(config_flags%map_proj == PROJ_CASSINI ) then
2528 msfxffl = 1.0/COS(config_flags%fft_filter_lat*degrad)
2531 IF ( config_flags%w_damping == 1 ) THEN
2537 IF(config_flags%map_proj == PROJ_CASSINI ) then
2538 msfuxt = MIN(msfux(i,j), msfxffl)
2542 vert_cfl = abs(ww(i,k,j)/mut(i,j)*rdnw(k)*dt)
2544 IF ( vert_cfl > max_vert_cfl ) THEN
2545 max_vert_cfl = vert_cfl ; maxi = i ; maxj = j ; maxk = k
2546 maxdub = w(i,k,j) ; maxdeta = -1./rdnw(k)
2549 horiz_cfl = max( abs(u(i,k,j) * rdx * msfuxt * dt), &
2550 abs(v(i,k,j) * rdy * msfvy(i,j) * dt) )
2551 if (horiz_cfl > max_horiz_cfl) then
2552 max_horiz_cfl = horiz_cfl
2555 if(vert_cfl .gt. w_beta)then
2557 ! restructure to get rid of divide
2559 ! This had been used for efficiency, but with the addition of returning the cfl values,
2560 ! the old version (above) was reinstated. (T. Hutchinson, 3/5/2007)
2562 cf_n = abs(ww(i,k,j)*rdnw(k)*dt)
2563 cf_d = abs(mut(i,j))
2564 if(cf_n .gt. cf_d*w_beta )then
2566 !$OMP CRITICAL(big_step_utilities)
2567 WRITE(temp,*)i,j,k,' vert_cfl,w,d(eta)=',vert_cfl,w(i,k,j),-1./rdnw(k)
2568 CALL wrf_debug ( 100 , TRIM(temp) )
2569 !$OMP END CRITICAL(big_step_utilities)
2570 if ( vert_cfl > 2. ) some = some + 1
2571 rw_tend(i,k,j) = rw_tend(i,k,j)-sign(1.,w(i,k,j))*w_alpha*(vert_cfl-w_beta)*mut(i,j)
2584 IF(config_flags%map_proj == PROJ_CASSINI ) then
2585 msfuxt = MIN(msfux(i,j), msfxffl)
2589 vert_cfl = abs(ww(i,k,j)/mut(i,j)*rdnw(k)*dt)
2591 IF ( vert_cfl > max_vert_cfl ) THEN
2592 max_vert_cfl = vert_cfl ; maxi = i ; maxj = j ; maxk = k
2593 maxdub = w(i,k,j) ; maxdeta = -1./rdnw(k)
2596 horiz_cfl = max( abs(u(i,k,j) * rdx * msfuxt * dt), &
2597 abs(v(i,k,j) * rdy * msfvy(i,j) * dt) )
2599 if (horiz_cfl > max_horiz_cfl) then
2600 max_horiz_cfl = horiz_cfl
2603 if(vert_cfl .gt. w_beta)then
2605 ! restructure to get rid of divide
2607 ! This had been used for efficiency, but with the addition of returning the cfl values,
2608 ! the old version (above) was reinstated. (T. Hutchinson, 3/5/2007)
2610 cf_n = abs(ww(i,k,j)*rdnw(k)*dt)
2611 cf_d = abs(mut(i,j))
2612 if(cf_n .gt. cf_d*w_beta )then
2614 !$OMP CRITICAL(big_step_utilities)
2615 WRITE(temp,*)i,j,k,' vert_cfl,w,d(eta)=',vert_cfl,w(i,k,j),-1./rdnw(k)
2616 CALL wrf_debug ( 100 , TRIM(temp) )
2617 !$OMP END CRITICAL(big_step_utilities)
2618 if ( vert_cfl > 2. ) some = some + 1
2624 IF ( some .GT. 0 ) THEN
2625 CALL get_current_time_string( time_str )
2626 CALL get_current_grid_name( grid_str )
2627 !$OMP CRITICAL(big_step_utilities)
2628 WRITE(wrf_err_message,*)some, &
2629 ' points exceeded cfl=2 in domain '//TRIM(grid_str)//' at time '//TRIM(time_str)//' hours'
2630 CALL wrf_debug ( 0 , TRIM(wrf_err_message) )
2631 WRITE(wrf_err_message,*)'MAX AT i,j,k: ',maxi,maxj,maxk,' vert_cfl,w,d(eta)=',max_vert_cfl, &
2633 CALL wrf_debug ( 0 , TRIM(wrf_err_message) )
2634 !$OMP END CRITICAL(big_step_utilities)
2637 END SUBROUTINE w_damp
2639 !-------------------------------------------------------------------------------
2641 SUBROUTINE horizontal_diffusion ( name, field, tendency, mu, &
2643 msfux, msfuy, msfvx, msfvx_inv, &
2644 msfvy, msftx, msfty, &
2645 khdif, xkmhd, rdx, rdy, &
2646 ids, ide, jds, jde, kds, kde, &
2647 ims, ime, jms, jme, kms, kme, &
2648 its, ite, jts, jte, kts, kte )
2654 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2656 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2657 ims, ime, jms, jme, kms, kme, &
2658 its, ite, jts, jte, kts, kte
2660 CHARACTER(LEN=1) , INTENT(IN ) :: name
2662 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: field, xkmhd
2664 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
2666 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu
2668 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
2676 REAL , INTENT(IN ) :: rdx, &
2682 INTEGER :: i, j, k, itf, jtf, ktf
2684 INTEGER :: i_start, i_end, j_start, j_end
2686 REAL :: mrdx, mkrdxm, mkrdxp, &
2687 mrdy, mkrdym, mkrdyp
2689 LOGICAL :: specified
2693 ! horizontal_diffusion computes the horizontal diffusion tendency
2694 ! on model horizontal coordinate surfaces.
2699 if(config_flags%specified .or. config_flags%nested) specified = .true.
2703 IF (name .EQ. 'u') THEN
2708 j_end = MIN(jte,jde-1)
2710 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2711 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-1,ite)
2712 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2713 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2714 IF ( config_flags%periodic_x ) i_start = its
2715 IF ( config_flags%periodic_x ) i_end = ite
2718 DO j = j_start, j_end
2720 DO i = i_start, i_end
2722 ! The interior is grad: (m_x*d/dx), the exterior is div: (m_x*m_y*d/dx(/m_y))
2723 ! setting up different averagings of m^2 partial d/dX and m^2 partial d/dY
2725 mkrdxm=(msftx(i-1,j)/msfty(i-1,j))*mu(i-1,j)*xkmhd(i-1,k,j)*rdx
2726 mkrdxp=(msftx(i,j)/msfty(i,j))*mu(i,j)*xkmhd(i,k,j)*rdx
2727 mrdx=msfux(i,j)*msfuy(i,j)*rdx
2728 mkrdym=( (msfuy(i,j)+msfuy(i,j-1))/(msfux(i,j)+msfux(i,j-1)) )* &
2729 0.25*(mu(i,j)+mu(i,j-1)+mu(i-1,j-1)+mu(i-1,j))* &
2730 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i-1,k,j-1)+xkmhd(i-1,k,j))*rdy
2731 mkrdyp=( (msfuy(i,j)+msfuy(i,j+1))/(msfux(i,j)+msfux(i,j+1)) )* &
2732 0.25*(mu(i,j)+mu(i,j+1)+mu(i-1,j+1)+mu(i-1,j))* &
2733 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j+1)+xkmhd(i-1,k,j+1)+xkmhd(i-1,k,j))*rdy
2734 ! need to do four-corners (t) for diffusion coefficient as there are
2735 ! no values at u,v points
2736 ! msfuy - has to be y as part of d/dY
2737 ! has to be u as we're at a u point
2738 mrdy=msfux(i,j)*msfuy(i,j)*rdy
2740 ! correctly averaged version of rho~ * m^2 *
2741 ! [partial d/dX(partial du^/dX) + partial d/dY(partial du^/dY)]
2742 tendency(i,k,j)=tendency(i,k,j)+( &
2743 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2744 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2745 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2746 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2751 ELSE IF (name .EQ. 'v')THEN
2754 i_end = MIN(ite,ide-1)
2758 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2759 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2760 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2761 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-1,jte)
2762 IF ( config_flags%periodic_x ) i_start = its
2763 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2764 IF ( config_flags%polar ) j_start = MAX(jds+1,jts)
2765 IF ( config_flags%polar ) j_end = MIN(jde-1,jte)
2767 DO j = j_start, j_end
2769 DO i = i_start, i_end
2771 mkrdxm=( (msfvx(i,j)+msfvx(i-1,j))/(msfvy(i,j)+msfvy(i-1,j)) )* &
2772 0.25*(mu(i,j)+mu(i,j-1)+mu(i-1,j-1)+mu(i-1,j))* &
2773 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i-1,k,j-1)+xkmhd(i-1,k,j))*rdx
2774 mkrdxp=( (msfvx(i,j)+msfvx(i+1,j))/(msfvy(i,j)+msfvy(i+1,j)) )* &
2775 0.25*(mu(i,j)+mu(i,j-1)+mu(i+1,j-1)+mu(i+1,j))* &
2776 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i+1,k,j-1)+xkmhd(i+1,k,j))*rdx
2777 mrdx=msfvx(i,j)*msfvy(i,j)*rdx
2778 mkrdym=(msfty(i,j-1)/msftx(i,j-1))*xkmhd(i,k,j-1)*rdy
2779 mkrdyp=(msfty(i,j)/msftx(i,j))*xkmhd(i,k,j)*rdy
2780 mrdy=msfvx(i,j)*msfvy(i,j)*rdy
2782 tendency(i,k,j)=tendency(i,k,j)+( &
2783 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2784 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2785 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2786 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2791 ELSE IF (name .EQ. 'w')THEN
2794 i_end = MIN(ite,ide-1)
2796 j_end = MIN(jte,jde-1)
2798 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2799 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2800 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2801 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2802 IF ( config_flags%periodic_x ) i_start = its
2803 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2805 DO j = j_start, j_end
2807 DO i = i_start, i_end
2809 mkrdxm=(msfux(i,j)/msfuy(i,j))* &
2810 0.25*(mu(i,j)+mu(i-1,j)+mu(i,j)+mu(i-1,j))* &
2811 0.25*(xkmhd(i,k,j)+xkmhd(i-1,k,j)+xkmhd(i,k-1,j)+xkmhd(i-1,k-1,j))*rdx
2812 mkrdxp=(msfux(i+1,j)/msfuy(i+1,j))* &
2813 0.25*(mu(i+1,j)+mu(i,j)+mu(i+1,j)+mu(i,j))* &
2814 0.25*(xkmhd(i+1,k,j)+xkmhd(i,k,j)+xkmhd(i+1,k-1,j)+xkmhd(i,k-1,j))*rdx
2815 mrdx=msftx(i,j)*msfty(i,j)*rdx
2816 ! mkrdym=(msfvy(i,j)/msfvx(i,j))* &
2817 mkrdym=(msfvy(i,j)*msfvx_inv(i,j))* &
2818 0.25*(mu(i,j)+mu(i,j-1)+mu(i,j)+mu(i,j-1))* &
2819 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i,k-1,j)+xkmhd(i,k-1,j-1))*rdy
2820 ! mkrdyp=(msfvy(i,j+1)/msfvx(i,j+1))* &
2821 mkrdyp=(msfvy(i,j+1)*msfvx_inv(i,j+1))* &
2822 0.25*(mu(i,j+1)+mu(i,j)+mu(i,j+1)+mu(i,j))* &
2823 0.25*(xkmhd(i,k,j+1)+xkmhd(i,k,j)+xkmhd(i,k-1,j+1)+xkmhd(i,k-1,j))*rdy
2824 mrdy=msftx(i,j)*msfty(i,j)*rdy
2826 tendency(i,k,j)=tendency(i,k,j)+( &
2827 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2828 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2829 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2830 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2839 i_end = MIN(ite,ide-1)
2841 j_end = MIN(jte,jde-1)
2843 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2844 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2845 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2846 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2847 IF ( config_flags%periodic_x ) i_start = its
2848 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2850 DO j = j_start, j_end
2852 DO i = i_start, i_end
2854 mkrdxm=(msfux(i,j)/msfuy(i,j))*0.5*(xkmhd(i,k,j)+xkmhd(i-1,k,j))*0.5*(mu(i,j)+mu(i-1,j))*rdx
2855 mkrdxp=(msfux(i+1,j)/msfuy(i+1,j))*0.5*(xkmhd(i+1,k,j)+xkmhd(i,k,j))*0.5*(mu(i+1,j)+mu(i,j))*rdx
2856 mrdx=msftx(i,j)*msfty(i,j)*rdx
2857 ! mkrdym=(msfvy(i,j)/msfvx(i,j))*0.5*(xkmhd(i,k,j)+xkmhd(i,k,j-1))*0.5*(mu(i,j)+mu(i,j-1))*rdy
2858 mkrdym=(msfvy(i,j)*msfvx_inv(i,j))*0.5*(xkmhd(i,k,j)+xkmhd(i,k,j-1))*0.5*(mu(i,j)+mu(i,j-1))*rdy
2859 ! mkrdyp=(msfvy(i,j+1)/msfvx(i,j+1))*0.5*(xkmhd(i,k,j+1)+xkmhd(i,k,j))*0.5*(mu(i,j+1)+mu(i,j))*rdy
2860 mkrdyp=(msfvy(i,j+1)*msfvx_inv(i,j+1))*0.5*(xkmhd(i,k,j+1)+xkmhd(i,k,j))*0.5*(mu(i,j+1)+mu(i,j))*rdy
2861 mrdy=msftx(i,j)*msfty(i,j)*rdy
2863 tendency(i,k,j)=tendency(i,k,j)+( &
2864 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2865 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2866 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2867 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2874 END SUBROUTINE horizontal_diffusion
2876 !-----------------------------------------------------------------------------------------
2878 SUBROUTINE horizontal_diffusion_3dmp ( name, field, tendency, mu, &
2879 config_flags, base_3d, &
2880 msfux, msfuy, msfvx, msfvx_inv, &
2881 msfvy, msftx, msfty, &
2882 khdif, xkmhd, rdx, rdy, &
2883 ids, ide, jds, jde, kds, kde, &
2884 ims, ime, jms, jme, kms, kme, &
2885 its, ite, jts, jte, kts, kte )
2891 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2893 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2894 ims, ime, jms, jme, kms, kme, &
2895 its, ite, jts, jte, kts, kte
2897 CHARACTER(LEN=1) , INTENT(IN ) :: name
2899 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: field, &
2903 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
2905 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu
2907 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
2915 REAL , INTENT(IN ) :: rdx, &
2921 INTEGER :: i, j, k, itf, jtf, ktf
2923 INTEGER :: i_start, i_end, j_start, j_end
2925 REAL :: mrdx, mkrdxm, mkrdxp, &
2926 mrdy, mkrdym, mkrdyp
2928 LOGICAL :: specified
2932 ! horizontal_diffusion_3dmp computes the horizontal diffusion tendency
2933 ! on model horizontal coordinate surfaces. This routine computes diffusion
2934 ! a perturbation scalar (field-base_3d).
2939 if(config_flags%specified .or. config_flags%nested) specified = .true.
2944 i_end = MIN(ite,ide-1)
2946 j_end = MIN(jte,jde-1)
2948 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2949 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2950 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2951 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2952 IF ( config_flags%periodic_x ) i_start = its
2953 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2955 DO j = j_start, j_end
2957 DO i = i_start, i_end
2959 mkrdxm=(msfux(i,j)/msfuy(i,j))*0.5*(xkmhd(i,k,j)+xkmhd(i-1,k,j))*0.5*(mu(i,j)+mu(i-1,j))*rdx
2960 mkrdxp=(msfux(i+1,j)/msfuy(i+1,j))*0.5*(xkmhd(i+1,k,j)+xkmhd(i,k,j))*0.5*(mu(i+1,j)+mu(i,j))*rdx
2961 mrdx=msftx(i,j)*msfty(i,j)*rdx
2962 ! mkrdym=(msfvy(i,j)/msfvx(i,j))*0.5*(xkmhd(i,k,j)+xkmhd(i,k,j-1))*0.5*(mu(i,j)+mu(i,j-1))*rdy
2963 ! mkrdyp=(msfvy(i,j+1)/msfvx(i,j+1))*0.5*(xkmhd(i,k,j+1)+xkmhd(i,k,j))*0.5*(mu(i,j+1)+mu(i,j))*rdy
2964 mkrdym=(msfvy(i,j)*msfvx_inv(i,j))*0.5*(xkmhd(i,k,j)+xkmhd(i,k,j-1))*0.5*(mu(i,j)+mu(i,j-1))*rdy
2965 mkrdyp=(msfvy(i,j+1)*msfvx_inv(i,j+1))*0.5*(xkmhd(i,k,j+1)+xkmhd(i,k,j))*0.5*(mu(i,j+1)+mu(i,j))*rdy
2966 mrdy=msftx(i,j)*msfty(i,j)*rdy
2968 tendency(i,k,j)=tendency(i,k,j)+( &
2969 mrdx*( mkrdxp*( field(i+1,k,j) -field(i ,k,j) &
2970 -base_3d(i+1,k,j)+base_3d(i ,k,j) ) &
2971 -mkrdxm*( field(i ,k,j) -field(i-1,k,j) &
2972 -base_3d(i ,k,j)+base_3d(i-1,k,j) ) ) &
2973 +mrdy*( mkrdyp*( field(i,k,j+1) -field(i,k,j ) &
2974 -base_3d(i,k,j+1)+base_3d(i,k,j ) ) &
2975 -mkrdym*( field(i,k,j ) -field(i,k,j-1) &
2976 -base_3d(i,k,j )+base_3d(i,k,j-1) ) ) &
2982 END SUBROUTINE horizontal_diffusion_3dmp
2984 !-----------------------------------------------------------------------------------------
2986 SUBROUTINE vertical_diffusion ( name, field, tendency, &
2988 alt, mut, rdn, rdnw, kvdif, &
2989 ids, ide, jds, jde, kds, kde, &
2990 ims, ime, jms, jme, kms, kme, &
2991 its, ite, jts, jte, kts, kte )
2998 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3000 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3001 ims, ime, jms, jme, kms, kme, &
3002 its, ite, jts, jte, kts, kte
3004 CHARACTER(LEN=1) , INTENT(IN ) :: name
3006 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3007 INTENT(IN ) :: field, &
3010 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3012 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mut
3014 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, rdnw
3016 REAL , INTENT(IN ) :: kvdif
3020 INTEGER :: i, j, k, itf, jtf, ktf
3021 INTEGER :: i_start, i_end, j_start, j_end
3023 REAL , DIMENSION(its:ite, jts:jte) :: vfluxm, vfluxp, zz
3024 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3028 LOGICAL :: specified
3032 ! vertical_diffusion
3033 ! computes vertical diffusion tendency.
3038 if(config_flags%specified .or. config_flags%nested) specified = .true.
3042 IF (name .EQ. 'w')THEN
3046 i_end = MIN(ite,ide-1)
3048 j_end = MIN(jte,jde-1)
3050 j_loop_w : DO j = j_start, j_end
3053 DO i = i_start, i_end
3054 vflux(i,k)= (kvdif/alt(i,k,j))*rdnw(k)*(field(i,k+1,j)-field(i,k,j))
3058 DO i = i_start, i_end
3063 DO i = i_start, i_end
3064 tendency(i,k,j)=tendency(i,k,j) &
3065 +rdn(k)*g*g/mut(i,j)/(0.5*(alt(i,k,j)+alt(i,k-1,j))) &
3066 *(vflux(i,k)-vflux(i,k-1))
3072 ELSE IF(name .EQ. 'm')THEN
3075 i_end = MIN(ite,ide-1)
3077 j_end = MIN(jte,jde-1)
3079 j_loop_s : DO j = j_start, j_end
3082 DO i = i_start, i_end
3083 vflux(i,k)=kvdif*rdn(k+1)/(0.5*(alt(i,k,j)+alt(i,k+1,j))) &
3084 *(field(i,k+1,j)-field(i,k,j))
3088 DO i = i_start, i_end
3089 vflux(i,0)=vflux(i,1)
3092 DO i = i_start, i_end
3097 DO i = i_start, i_end
3098 tendency(i,k,j)=tendency(i,k,j)+g*g/mut(i,j)/alt(i,k,j) &
3099 *rdnw(k)*(vflux(i,k)-vflux(i,k-1))
3107 END SUBROUTINE vertical_diffusion
3110 !-------------------------------------------------------------------------------
3112 SUBROUTINE vertical_diffusion_mp ( field, tendency, config_flags, &
3114 alt, mut, rdn, rdnw, kvdif, &
3115 ids, ide, jds, jde, kds, kde, &
3116 ims, ime, jms, jme, kms, kme, &
3117 its, ite, jts, jte, kts, kte )
3124 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3126 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3127 ims, ime, jms, jme, kms, kme, &
3128 its, ite, jts, jte, kts, kte
3130 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3131 INTENT(IN ) :: field, &
3134 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3136 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mut
3138 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, &
3142 REAL , INTENT(IN ) :: kvdif
3146 INTEGER :: i, j, k, itf, jtf, ktf
3147 INTEGER :: i_start, i_end, j_start, j_end
3149 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3153 LOGICAL :: specified
3157 ! vertical_diffusion_mp
3158 ! computes vertical diffusion tendency of a perturbation variable
3159 ! (field-base). Note that base as a 1D (k) field.
3164 if(config_flags%specified .or. config_flags%nested) specified = .true.
3169 i_end = MIN(ite,ide-1)
3171 j_end = MIN(jte,jde-1)
3173 j_loop_s : DO j = j_start, j_end
3176 DO i = i_start, i_end
3177 vflux(i,k)=kvdif*rdn(k+1)/(0.5*(alt(i,k,j)+alt(i,k+1,j))) &
3178 *(field(i,k+1,j)-field(i,k,j)-base(k+1)+base(k))
3182 DO i = i_start, i_end
3183 vflux(i,0)=vflux(i,1)
3186 DO i = i_start, i_end
3191 DO i = i_start, i_end
3192 tendency(i,k,j)=tendency(i,k,j)+g*g/mut(i,j)/alt(i,k,j) &
3193 *rdnw(k)*(vflux(i,k)-vflux(i,k-1))
3199 END SUBROUTINE vertical_diffusion_mp
3202 !-------------------------------------------------------------------------------
3204 SUBROUTINE vertical_diffusion_3dmp ( field, tendency, config_flags, &
3206 alt, mut, rdn, rdnw, kvdif, &
3207 ids, ide, jds, jde, kds, kde, &
3208 ims, ime, jms, jme, kms, kme, &
3209 its, ite, jts, jte, kts, kte )
3216 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3218 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3219 ims, ime, jms, jme, kms, kme, &
3220 its, ite, jts, jte, kts, kte
3222 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3223 INTENT(IN ) :: field, &
3227 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3229 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mut
3231 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, &
3234 REAL , INTENT(IN ) :: kvdif
3238 INTEGER :: i, j, k, itf, jtf, ktf
3239 INTEGER :: i_start, i_end, j_start, j_end
3241 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3245 LOGICAL :: specified
3249 ! vertical_diffusion_3dmp
3250 ! computes vertical diffusion tendency of a perturbation variable
3256 if(config_flags%specified .or. config_flags%nested) specified = .true.
3261 i_end = MIN(ite,ide-1)
3263 j_end = MIN(jte,jde-1)
3265 j_loop_s : DO j = j_start, j_end
3268 DO i = i_start, i_end
3269 vflux(i,k)=kvdif*rdn(k+1)/(0.5*(alt(i,k,j)+alt(i,k+1,j))) &
3270 *( field(i,k+1,j) -field(i,k,j) &
3271 -base_3d(i,k+1,j)+base_3d(i,k,j) )
3275 DO i = i_start, i_end
3276 vflux(i,0)=vflux(i,1)
3279 DO i = i_start, i_end
3284 DO i = i_start, i_end
3285 tendency(i,k,j)=tendency(i,k,j)+g*g/mut(i,j)/alt(i,k,j) &
3286 *rdnw(k)*(vflux(i,k)-vflux(i,k-1))
3292 END SUBROUTINE vertical_diffusion_3dmp
3295 !-------------------------------------------------------------------------------
3298 SUBROUTINE vertical_diffusion_u ( field, tendency, &
3299 config_flags, u_base, &
3300 alt, muu, rdn, rdnw, kvdif, &
3301 ids, ide, jds, jde, kds, kde, &
3302 ims, ime, jms, jme, kms, kme, &
3303 its, ite, jts, jte, kts, kte )
3310 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3312 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3313 ims, ime, jms, jme, kms, kme, &
3314 its, ite, jts, jte, kts, kte
3316 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3317 INTENT(IN ) :: field, &
3320 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3322 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muu
3324 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, rdnw, u_base
3326 REAL , INTENT(IN ) :: kvdif
3330 INTEGER :: i, j, k, itf, jtf, ktf
3331 INTEGER :: i_start, i_end, j_start, j_end
3333 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3337 LOGICAL :: specified
3341 ! vertical_diffusion_u computes vertical diffusion tendency for
3342 ! the u momentum equation. This routine assumes a constant eddy
3348 if(config_flags%specified .or. config_flags%nested) specified = .true.
3355 j_end = MIN(jte,jde-1)
3357 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
3358 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-1,ite)
3359 IF ( config_flags%periodic_x ) i_start = its
3360 IF ( config_flags%periodic_x ) i_end = ite
3363 j_loop_u : DO j = j_start, j_end
3366 DO i = i_start, i_end
3367 vflux(i,k)=kvdif*rdn(k+1)/(0.25*( alt(i ,k ,j) &
3370 +alt(i-1,k+1,j) ) ) &
3371 *(field(i,k+1,j)-field(i,k,j) &
3372 -u_base(k+1) +u_base(k) )
3376 DO i = i_start, i_end
3377 vflux(i,0)=vflux(i,1)
3380 DO i = i_start, i_end
3385 DO i = i_start, i_end
3386 tendency(i,k,j)=tendency(i,k,j)+ &
3387 g*g*rdnw(k)/muu(i,j)/(0.5*(alt(i-1,k,j)+alt(i,k,j)))* &
3388 (vflux(i,k)-vflux(i,k-1))
3394 END SUBROUTINE vertical_diffusion_u
3396 !-------------------------------------------------------------------------------
3399 SUBROUTINE vertical_diffusion_v ( field, tendency, &
3400 config_flags, v_base, &
3401 alt, muv, rdn, rdnw, kvdif, &
3402 ids, ide, jds, jde, kds, kde, &
3403 ims, ime, jms, jme, kms, kme, &
3404 its, ite, jts, jte, kts, kte )
3411 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3413 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3414 ims, ime, jms, jme, kms, kme, &
3415 its, ite, jts, jte, kts, kte
3417 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3418 INTENT(IN ) :: field, &
3420 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, rdnw, v_base
3422 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3424 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muv
3426 REAL , INTENT(IN ) :: kvdif
3430 INTEGER :: i, j, k, itf, jtf, ktf, jm1
3431 INTEGER :: i_start, i_end, j_start, j_end
3433 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3437 LOGICAL :: specified
3441 ! vertical_diffusion_v computes vertical diffusion tendency for
3442 ! the v momentum equation. This routine assumes a constant eddy
3448 if(config_flags%specified .or. config_flags%nested) specified = .true.
3453 i_end = MIN(ite,ide-1)
3455 j_end = MIN(jte,jde-1)
3457 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
3458 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-1,jte)
3460 j_loop_v : DO j = j_start, j_end
3465 DO i = i_start, i_end
3466 vflux(i,k)=kvdif*rdn(k+1)/(0.25*( alt(i,k ,j ) &
3469 +alt(i,k+1,jm1) ) ) &
3470 *(field(i,k+1,j)-field(i,k,j) &
3471 -v_base(k+1) +v_base(k) )
3475 DO i = i_start, i_end
3476 vflux(i,0)=vflux(i,1)
3479 DO i = i_start, i_end
3484 DO i = i_start, i_end
3485 tendency(i,k,j)=tendency(i,k,j)+ &
3486 g*g*rdnw(k)/muv(i,j)/(0.5*(alt(i,k,jm1)+alt(i,k,j)))* &
3487 (vflux(i,k)-vflux(i,k-1))
3493 END SUBROUTINE vertical_diffusion_v
3495 !*************** end new mass coordinate routines
3497 !-------------------------------------------------------------------------------
3499 SUBROUTINE calculate_full ( rfield, rfieldb, rfieldp, &
3500 ids, ide, jds, jde, kds, kde, &
3501 ims, ime, jms, jme, kms, kme, &
3502 its, ite, jts, jte, kts, kte )
3508 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3509 ims, ime, jms, jme, kms, kme, &
3510 its, ite, jts, jte, kts, kte
3512 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: rfieldb, &
3515 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT ) :: rfield
3519 INTEGER :: i, j, k, itf, jtf, ktf
3524 ! calculates full 3D field from pertubation and base field.
3535 rfield(i,k,j)=rfieldb(i,k,j)+rfieldp(i,k,j)
3540 END SUBROUTINE calculate_full
3542 !------------------------------------------------------------------------------
3544 SUBROUTINE coriolis ( ru, rv, rw, ru_tend, rv_tend, rw_tend, &
3546 msftx, msfty, msfux, msfuy, &
3548 f, e, sina, cosa, fzm, fzp, &
3549 ids, ide, jds, jde, kds, kde, &
3550 ims, ime, jms, jme, kms, kme, &
3551 its, ite, jts, jte, kts, kte )
3557 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
3559 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3560 ims, ime, jms, jme, kms, kme, &
3561 its, ite, jts, jte, kts, kte
3563 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: ru_tend, &
3566 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: ru, &
3570 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
3577 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: f, &
3582 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
3587 INTEGER :: i, j , k, ktf
3588 INTEGER :: i_start, i_end, j_start, j_end
3590 LOGICAL :: specified
3594 ! coriolis calculates the large timestep tendency terms in the
3595 ! u, v, and w momentum equations arise from the coriolis force.
3600 if(config_flags%specified .or. config_flags%nested) specified = .true.
3604 ! coriolis for u-momentum equation
3606 ! Notes on map scale factor
3607 ! cosa, sina are related to rotating the coordinate frame if desired
3608 ! generally sina=0, cosa=1
3609 ! ADT eqn 44, RHS terms 6 and 7: -2 mu w omega cos(lat)/my
3610 ! + 2 mu v omega sin(lat)/my
3611 ! Define f=2 omega sin(lat), e=2 omega cos(lat)
3612 ! => terms are: -e mu w / my + f mu v / my
3613 ! rv = mu v / mx ; rw = mu w / my
3614 ! => terms are: -e rw + f rv *mx / my
3618 IF ( config_flags%open_xs .or. specified .or. &
3619 config_flags%nested) i_start = MAX(ids+1,its)
3620 IF ( config_flags%open_xe .or. specified .or. &
3621 config_flags%nested) i_end = MIN(ide-1,ite)
3622 IF ( config_flags%periodic_x ) i_start = its
3623 IF ( config_flags%periodic_x ) i_end = ite
3625 DO j = jts, MIN(jte,jde-1)
3628 DO i = i_start, i_end
3630 ru_tend(i,k,j)=ru_tend(i,k,j) + (msfux(i,j)/msfuy(i,j))*0.5*(f(i,j)+f(i-1,j)) &
3631 *0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+rv(i-1,k,j)+rv(i,k,j)) &
3632 - 0.5*(e(i,j)+e(i-1,j))*0.5*(cosa(i,j)+cosa(i-1,j)) &
3633 *0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j))
3638 ! boundary loops for coriolis not needed for open bdy (commented out 20100611 JD)
3639 ! IF ( (config_flags%open_xs) .and. (its == ids) ) THEN
3643 ! ru_tend(its,k,j)=ru_tend(its,k,j) + (msfux(its,j)/msfuy(its,j))*0.5*(f(its,j)+f(its,j)) &
3644 ! *0.25*(rv(its,k,j+1)+rv(its,k,j+1)+rv(its,k,j)+rv(its,k,j)) &
3645 ! - 0.5*(e(its,j)+e(its,j))*0.5*(cosa(its,j)+cosa(its,j)) &
3646 ! *0.25*(rw(its,k+1,j)+rw(its,k,j)+rw(its,k+1,j)+rw(its,k,j))
3652 ! IF ( (config_flags%open_xe) .and. (ite == ide) ) THEN
3656 ! ru_tend(ite,k,j)=ru_tend(ite,k,j) + (msfux(ite,j)/msfuy(ite,j))*0.5*(f(ite-1,j)+f(ite-1,j)) &
3657 ! *0.25*(rv(ite-1,k,j+1)+rv(ite-1,k,j+1)+rv(ite-1,k,j)+rv(ite-1,k,j)) &
3658 ! - 0.5*(e(ite-1,j)+e(ite-1,j))*0.5*(cosa(ite-1,j)+cosa(ite-1,j)) &
3659 ! *0.25*(rw(ite-1,k+1,j)+rw(ite-1,k,j)+rw(ite-1,k+1,j)+rw(ite-1,k,j))
3667 ! coriolis term for v-momentum equation
3669 ! Notes on map scale factors
3670 ! ADT eqn 45, RHS terms 6 and 6b [0 for sina=0]: -2 mu u omega sin(lat)/mx + ?
3671 ! Define f=2 omega sin(lat), e=2 omega cos(lat)
3672 ! => terms are: -f mu u / mx
3673 ! ru = mu u / my ; rw = mu w / my
3674 ! => terms are: -f ru *my / mx + ?
3679 IF ( config_flags%open_ys .or. specified .or. &
3680 config_flags%nested .or. config_flags%polar) j_start = MAX(jds+1,jts)
3681 IF ( config_flags%open_ye .or. specified .or. &
3682 config_flags%nested .or. config_flags%polar) j_end = MIN(jde-1,jte)
3684 ! boundary loops for coriolis not needed for open bdy (commented out 20100611 JD)
3685 ! IF ( (config_flags%open_ys) .and. (jts == jds) ) THEN
3688 ! DO i=its,MIN(ide-1,ite)
3690 ! rv_tend(i,k,jts)=rv_tend(i,k,jts) - (msfvy(i,jts)/msfvx(i,jts))*0.5*(f(i,jts)+f(i,jts)) &
3691 ! *0.25*(ru(i,k,jts)+ru(i+1,k,jts)+ru(i,k,jts)+ru(i+1,k,jts)) &
3692 ! + (msfvy(i,jts)/msfvx(i,jts))*0.5*(e(i,jts)+e(i,jts))*0.5*(sina(i,jts)+sina(i,jts)) &
3693 ! *0.25*(rw(i,k+1,jts)+rw(i,k,jts)+rw(i,k+1,jts)+rw(i,k,jts))
3702 DO i=its,MIN(ide-1,ite)
3704 rv_tend(i,k,j)=rv_tend(i,k,j) - (msfvy(i,j)/msfvx(i,j))*0.5*(f(i,j)+f(i,j-1)) &
3705 *0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
3706 + (msfvy(i,j)/msfvx(i,j))*0.5*(e(i,j)+e(i,j-1))*0.5*(sina(i,j)+sina(i,j-1)) &
3707 *0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+rw(i,k+1,j)+rw(i,k,j))
3714 ! boundary loops for coriolis not needed for open bdy (commented out 20100611 JD)
3715 ! IF ( (config_flags%open_ye) .and. (jte == jde) ) THEN
3718 ! DO i=its,MIN(ide-1,ite)
3720 ! rv_tend(i,k,jte)=rv_tend(i,k,jte) - (msfvy(i,jte)/msfvx(i,jte))*0.5*(f(i,jte-1)+f(i,jte-1)) &
3721 ! *0.25*(ru(i,k,jte-1)+ru(i+1,k,jte-1)+ru(i,k,jte-1)+ru(i+1,k,jte-1)) &
3722 ! + (msfvy(i,jte)/msfvx(i,jte))*0.5*(e(i,jte-1)+e(i,jte-1))*0.5*(sina(i,jte-1)+sina(i,jte-1)) &
3723 ! *0.25*(rw(i,k+1,jte-1)+rw(i,k,jte-1)+rw(i,k+1,jte-1)+rw(i,k,jte-1))
3730 ! coriolis term for w-mometum
3732 ! Notes on map scale factors
3733 ! ADT eqn 46/my, RHS terms 5 and 5b [0 for sina=0]: 2 mu u omega cos(lat)/my +?
3734 ! Define e=2 omega cos(lat)
3735 ! => terms are: e mu u / my + ???
3736 ! ru = mu u / my ; ru = mu v / mx
3737 ! => terms are: e ru + ???
3739 DO j=jts,MIN(jte, jde-1)
3741 DO i=its,MIN(ite, ide-1)
3743 rw_tend(i,k,j)=rw_tend(i,k,j) + e(i,j)* &
3744 (cosa(i,j)*0.5*(fzm(k)*(ru(i,k,j)+ru(i+1,k,j)) &
3745 +fzp(k)*(ru(i,k-1,j)+ru(i+1,k-1,j))) &
3746 -(msftx(i,j)/msfty(i,j))* &
3747 sina(i,j)*0.5*(fzm(k)*(rv(i,k,j)+rv(i,k,j+1)) &
3748 +fzp(k)*(rv(i,k-1,j)+rv(i,k-1,j+1))))
3754 END SUBROUTINE coriolis
3756 !------------------------------------------------------------------------------
3758 SUBROUTINE perturbation_coriolis ( ru_in, rv_in, rw, ru_tend, rv_tend, rw_tend, &
3760 u_base, v_base, z_base, &
3761 muu, muv, phb, ph, &
3762 msftx, msfty, msfux, msfuy, msfvx, msfvy, &
3763 f, e, sina, cosa, fzm, fzp, &
3764 ids, ide, jds, jde, kds, kde, &
3765 ims, ime, jms, jme, kms, kme, &
3766 its, ite, jts, jte, kts, kte )
3772 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
3774 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3775 ims, ime, jms, jme, kms, kme, &
3776 its, ite, jts, jte, kts, kte
3778 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: ru_tend, &
3781 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: ru_in, &
3788 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
3795 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: f, &
3800 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muu, &
3804 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
3807 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: u_base, &
3813 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) :: ru, &
3816 REAL :: z_at_u, z_at_v, wkp1, wk, wkm1
3820 INTEGER :: i, j , k, ktf
3821 INTEGER :: i_start, i_end, j_start, j_end
3823 LOGICAL :: specified
3827 ! perturbation_coriolis calculates the large timestep tendency terms in the
3828 ! u, v, and w momentum equations arise from the coriolis force. This version
3829 ! subtracts off the horizontal velocities from the initial sounding when
3830 ! computing the forcing terms, hence "perturbation" coriolis.
3835 if(config_flags%specified .or. config_flags%nested) specified = .true.
3839 ! coriolis for u-momentum equation
3843 IF ( config_flags%open_xs .or. specified .or. &
3844 config_flags%nested) i_start = MAX(ids+1,its)
3845 IF ( config_flags%open_xe .or. specified .or. &
3846 config_flags%nested) i_end = MIN(ide-1,ite)
3847 IF ( config_flags%periodic_x ) i_start = its
3848 IF ( config_flags%periodic_x ) i_end = ite
3850 ! compute perturbation mu*v for use in u momentum equation
3852 DO j = jts, MIN(jte,jde-1)+1
3854 DO i = i_start-1, i_end
3855 z_at_v = 0.25*( phb(i,k,j )+phb(i,k+1,j ) &
3856 +phb(i,k,j-1)+phb(i,k+1,j-1) &
3857 +ph(i,k,j )+ph(i,k+1,j ) &
3858 +ph(i,k,j-1)+ph(i,k+1,j-1))/g
3859 wkp1 = min(1.,max(0.,z_at_v-z_base(k))/(z_base(k+1)-z_base(k)))
3860 wkm1 = min(1.,max(0.,z_base(k)-z_at_v)/(z_base(k)-z_base(k-1)))
3862 rv(i,k,j) = rv_in(i,k,j) - muv(i,j)*( &
3871 ! pick up top and bottom v
3873 DO j = jts, MIN(jte,jde-1)+1
3874 DO i = i_start-1, i_end
3877 z_at_v = 0.25*( phb(i,k,j )+phb(i,k+1,j ) &
3878 +phb(i,k,j-1)+phb(i,k+1,j-1) &
3879 +ph(i,k,j )+ph(i,k+1,j ) &
3880 +ph(i,k,j-1)+ph(i,k+1,j-1))/g
3881 wkp1 = min(1.,max(0.,z_at_v-z_base(k))/(z_base(k+1)-z_base(k)))
3883 rv(i,k,j) = rv_in(i,k,j) - muv(i,j)*( &
3888 z_at_v = 0.25*( phb(i,k,j )+phb(i,k+1,j ) &
3889 +phb(i,k,j-1)+phb(i,k+1,j-1) &
3890 +ph(i,k,j )+ph(i,k+1,j ) &
3891 +ph(i,k,j-1)+ph(i,k+1,j-1))/g
3892 wkm1 = min(1.,max(0.,z_base(k)-z_at_v)/(z_base(k)-z_base(k-1)))
3894 rv(i,k,j) = rv_in(i,k,j) - muv(i,j)*( &
3901 ! compute coriolis forcing for u
3903 ! Map scale factors: see comments above for Coriolis
3905 DO j = jts, MIN(jte,jde-1)
3908 DO i = i_start, i_end
3909 ru_tend(i,k,j)=ru_tend(i,k,j) + (msfux(i,j)/msfuy(i,j))*0.5*(f(i,j)+f(i-1,j)) &
3910 *0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+rv(i-1,k,j)+rv(i,k,j)) &
3911 - 0.5*(e(i,j)+e(i-1,j))*0.5*(cosa(i,j)+cosa(i-1,j)) &
3912 *0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j))
3916 ! boundary loops for perturbation coriolis is needed for open bdy (20110225 JD)
3917 IF ( (config_flags%open_xs) .and. (its == ids) ) THEN
3921 ru_tend(its,k,j)=ru_tend(its,k,j) + (msfux(its,j)/msfuy(its,j))*0.5*(f(its,j)+f(its,j)) &
3922 *0.25*(rv(its,k,j+1)+rv(its,k,j+1)+rv(its,k,j)+rv(its,k,j)) &
3923 - 0.5*(e(its,j)+e(its,j))*0.5*(cosa(its,j)+cosa(its,j)) &
3924 *0.25*(rw(its,k+1,j)+rw(its,k,j)+rw(its,k+1,j)+rw(its,k,j))
3930 IF ( (config_flags%open_xe) .and. (ite == ide) ) THEN
3934 ru_tend(ite,k,j)=ru_tend(ite,k,j) + (msfux(ite,j)/msfuy(ite,j))*0.5*(f(ite-1,j)+f(ite-1,j)) &
3935 *0.25*(rv(ite-1,k,j+1)+rv(ite-1,k,j+1)+rv(ite-1,k,j)+rv(ite-1,k,j)) &
3936 - 0.5*(e(ite-1,j)+e(ite-1,j))*0.5*(cosa(ite-1,j)+cosa(ite-1,j)) &
3937 *0.25*(rw(ite-1,k+1,j)+rw(ite-1,k,j)+rw(ite-1,k+1,j)+rw(ite-1,k,j))
3945 ! coriolis term for v-momentum equation
3946 ! Map scale factors: see comments above for Coriolis
3951 IF ( config_flags%open_ys .or. specified .or. &
3952 config_flags%nested .or. config_flags%polar) j_start = MAX(jds+1,jts)
3953 IF ( config_flags%open_ye .or. specified .or. &
3954 config_flags%nested .or. config_flags%polar) j_end = MIN(jde-1,jte)
3956 ! compute perturbation mu*u for use in v momentum equation
3958 DO j = j_start-1,j_end
3960 DO i = its, MIN(ite,ide-1)+1
3961 z_at_u = 0.25*( phb(i ,k,j)+phb(i ,k+1,j) &
3962 +phb(i-1,k,j)+phb(i-1,k+1,j) &
3963 +ph(i ,k,j)+ph(i ,k+1,j) &
3964 +ph(i-1,k,j)+ph(i-1,k+1,j))/g
3965 wkp1 = min(1.,max(0.,z_at_u-z_base(k))/(z_base(k+1)-z_base(k)))
3966 wkm1 = min(1.,max(0.,z_base(k)-z_at_u)/(z_base(k)-z_base(k-1)))
3968 ru(i,k,j) = ru_in(i,k,j) - muu(i,j)*( &
3976 ! pick up top and bottom u
3978 DO j = j_start-1,j_end
3979 DO i = its, MIN(ite,ide-1)+1
3982 z_at_u = 0.25*( phb(i ,k,j)+phb(i ,k+1,j) &
3983 +phb(i-1,k,j)+phb(i-1,k+1,j) &
3984 +ph(i ,k,j)+ph(i ,k+1,j) &
3985 +ph(i-1,k,j)+ph(i-1,k+1,j))/g
3986 wkp1 = min(1.,max(0.,z_at_u-z_base(k))/(z_base(k+1)-z_base(k)))
3988 ru(i,k,j) = ru_in(i,k,j) - muu(i,j)*( &
3994 z_at_u = 0.25*( phb(i ,k,j)+phb(i ,k+1,j) &
3995 +phb(i-1,k,j)+phb(i-1,k+1,j) &
3996 +ph(i ,k,j)+ph(i ,k+1,j) &
3997 +ph(i-1,k,j)+ph(i-1,k+1,j))/g
3998 wkm1 = min(1.,max(0.,z_base(k)-z_at_u)/(z_base(k)-z_base(k-1)))
4000 ru(i,k,j) = ru_in(i,k,j) - muu(i,j)*( &
4007 ! compute coriolis forcing for v momentum equation
4008 ! Map scale factors: see comments above for Coriolis
4010 ! boundary loops for perturbation coriolis is needed for open bdy (20110225 JD)
4011 IF ( (config_flags%open_ys) .and. (jts == jds) ) THEN
4014 DO i=its,MIN(ide-1,ite)
4016 rv_tend(i,k,jts)=rv_tend(i,k,jts) - (msfvy(i,jts)/msfvx(i,jts))*0.5*(f(i,jts)+f(i,jts)) &
4017 *0.25*(ru(i,k,jts)+ru(i+1,k,jts)+ru(i,k,jts)+ru(i+1,k,jts)) &
4018 + (msfvy(i,jts)/msfvx(i,jts))*0.5*(e(i,jts)+e(i,jts))*0.5*(sina(i,jts)+sina(i,jts)) &
4019 *0.25*(rw(i,k+1,jts)+rw(i,k,jts)+rw(i,k+1,jts)+rw(i,k,jts))
4028 DO i=its,MIN(ide-1,ite)
4030 rv_tend(i,k,j)=rv_tend(i,k,j) - (msfvy(i,j)/msfvx(i,j))*0.5*(f(i,j)+f(i,j-1)) &
4031 *0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
4032 + (msfvy(i,j)/msfvx(i,j))*0.5*(e(i,j)+e(i,j-1))*0.5*(sina(i,j)+sina(i,j-1)) &
4033 *0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+rw(i,k+1,j)+rw(i,k,j))
4040 ! boundary loops for perturbation coriolis is needed for open bdy (20110225 JD)
4041 IF ( (config_flags%open_ye) .and. (jte == jde) ) THEN
4044 DO i=its,MIN(ide-1,ite)
4046 rv_tend(i,k,jte)=rv_tend(i,k,jte) - (msfvy(i,jte)/msfvx(i,jte))*0.5*(f(i,jte-1)+f(i,jte-1)) &
4047 *0.25*(ru(i,k,jte-1)+ru(i+1,k,jte-1)+ru(i,k,jte-1)+ru(i+1,k,jte-1)) &
4048 + (msfvy(i,jte)/msfvx(i,jte))*0.5*(e(i,jte-1)+e(i,jte-1))*0.5*(sina(i,jte-1)+sina(i,jte-1)) &
4049 *0.25*(rw(i,k+1,jte-1)+rw(i,k,jte-1)+rw(i,k+1,jte-1)+rw(i,k,jte-1))
4056 ! coriolis term for w-mometum
4057 ! Map scale factors: see comments above for Coriolis
4059 DO j=jts,MIN(jte, jde-1)
4061 DO i=its,MIN(ite, ide-1)
4063 rw_tend(i,k,j)=rw_tend(i,k,j) + e(i,j)* &
4064 (cosa(i,j)*0.5*(fzm(k)*(ru(i,k,j)+ru(i+1,k,j)) &
4065 +fzp(k)*(ru(i,k-1,j)+ru(i+1,k-1,j))) &
4066 -(msftx(i,j)/msfty(i,j))*sina(i,j)*0.5*(fzm(k)*(rv(i,k,j)+rv(i,k,j+1)) &
4067 +fzp(k)*(rv(i,k-1,j)+rv(i,k-1,j+1))))
4073 END SUBROUTINE perturbation_coriolis
4075 !------------------------------------------------------------------------------
4077 SUBROUTINE curvature ( ru, rv, rw, u, v, w, ru_tend, rv_tend, rw_tend, &
4079 msfux, msfuy, msfvx, msfvy, msftx, msfty, &
4080 xlat, fzm, fzp, rdx, rdy, &
4081 ids, ide, jds, jde, kds, kde, &
4082 ims, ime, jms, jme, kms, kme, &
4083 its, ite, jts, jte, kts, kte )
4090 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
4092 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4093 ims, ime, jms, jme, kms, kme, &
4094 its, ite, jts, jte, kts, kte
4096 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4097 INTENT(INOUT) :: ru_tend, &
4101 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4102 INTENT(IN ) :: ru, &
4109 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
4117 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
4120 REAL , INTENT(IN ) :: rdx, &
4125 ! INTEGER :: i, j, k, itf, jtf, ktf, kp1, im, ip, jm, jp
4126 INTEGER :: i, j, k, itf, jtf, ktf
4127 INTEGER :: i_start, i_end, j_start, j_end
4128 ! INTEGER :: irmin, irmax, jrmin, jrmax
4130 REAL , DIMENSION( its-1:ite , kts:kte, jts-1:jte ) :: vxgm
4132 LOGICAL :: specified
4136 ! curvature calculates the large timestep tendency terms in the
4137 ! u, v, and w momentum equations arise from the curvature terms.
4142 if(config_flags%specified .or. config_flags%nested) specified = .true.
4152 ! IF ( config_flags%open_xs ) irmin = ids
4153 ! IF ( config_flags%open_xe ) irmax = ide-1
4154 ! IF ( config_flags%open_ys ) jrmin = jds
4155 ! IF ( config_flags%open_ye ) jrmax = jde-1
4157 ! Define v cross grad m at scalar points - vxgm(i,j)
4164 IF ( ( config_flags%open_xs .or. specified .or. &
4165 config_flags%nested) .and. (its == ids) ) i_start = its
4166 IF ( ( config_flags%open_xe .or. specified .or. &
4167 config_flags%nested) .and. (ite == ide) ) i_end = ite-1
4168 IF ( ( config_flags%open_ys .or. specified .or. &
4169 config_flags%nested .or. config_flags%polar) .and. (jts == jds) ) j_start = jts
4170 IF ( ( config_flags%open_ye .or. specified .or. &
4171 config_flags%nested .or. config_flags%polar) .and. (jte == jde) ) j_end = jte-1
4172 IF ( config_flags%periodic_x ) i_start = its-1
4173 IF ( config_flags%periodic_x ) i_end = ite
4178 ! Map scale factor notes:
4179 ! msf...y is constant everywhere for cylindrical map projection
4180 ! msf...x varies with y only
4181 ! But we know that this is not = 0 for cylindrical,
4182 ! therefore use msfvX in 1st line
4183 ! which => by symmetry use msfuY in 2nd line - ???
4184 vxgm(i,k,j)=0.5*(u(i,k,j)+u(i+1,k,j))*(msfvx(i,j+1)-msfvx(i,j))*rdy - &
4185 0.5*(v(i,k,j)+v(i,k,j+1))*(msfuy(i+1,j)-msfuy(i,j))*rdx
4190 ! Pick up the boundary rows for open (radiation) lateral b.c.
4191 ! Rather crude at present, we are assuming there is no
4192 ! variation in this term at the boundary.
4194 IF ( ( config_flags%open_xs .or. (specified .AND. .NOT. config_flags%periodic_x) .or. &
4195 config_flags%nested) .and. (its == ids) ) THEN
4199 vxgm(its-1,k,j) = vxgm(its,k,j)
4205 IF ( ( config_flags%open_xe .or. (specified .AND. .NOT. config_flags%periodic_x) .or. &
4206 config_flags%nested) .and. (ite == ide) ) THEN
4210 vxgm(ite,k,j) = vxgm(ite-1,k,j)
4216 ! Polar boundary condition:
4217 ! The following change is needed in case one tries using the vxgm route with
4218 ! polar B.C.'s in the future, but not needed if 'tan' used
4219 IF ( ( config_flags%open_ys .or. specified .or. &
4220 config_flags%nested .or. config_flags%polar) .and. (jts == jds) ) THEN
4224 vxgm(i,k,jts-1) = vxgm(i,k,jts)
4230 ! Polar boundary condition:
4231 ! The following change is needed in case one tries using the vxgm route with
4232 ! polar B.C.'s in the future, but not needed if 'tan' used
4233 IF ( ( config_flags%open_ye .or. specified .or. &
4234 config_flags%nested .or. config_flags%polar) .and. (jte == jde) ) THEN
4238 vxgm(i,k,jte) = vxgm(i,k,jte-1)
4244 ! curvature term for u momentum eqn.
4246 ! Map scale factor notes:
4247 ! ADT eqn 44, RHS terms 4 and 5, in cylindrical: mu u v tan(lat)/(a my)
4249 ! ru = mu u / my ; rw = mu w / my ; rv = mu v / mx
4251 ! (mx/my)*u rv tan(lat) / a - u rw / a = (u/a)*[(mx/my) rv tan(lat) - rw]
4252 ! ru v tan(lat) / a - u rw / a
4253 ! xlat defined with end points half grid space from pole,
4254 ! hence are on u latitude points
4257 IF ( config_flags%open_xs .or. specified .or. &
4258 config_flags%nested) i_start = MAX ( ids+1 , its )
4259 IF ( config_flags%open_xe .or. specified .or. &
4260 config_flags%nested) i_end = MIN ( ide-1 , ite )
4261 IF ( config_flags%periodic_x ) i_start = its
4262 IF ( config_flags%periodic_x ) i_end = ite
4264 ! Polar boundary condition
4265 IF ((config_flags%map_proj == 6) .OR. (config_flags%polar)) THEN
4267 DO j=jts,MIN(jde-1,jte)
4271 ru_tend(i,k,j)=ru_tend(i,k,j) + u(i,k,j)*reradius* ( &
4272 (msfux(i,j)/msfuy(i,j))*0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+ &
4273 rv(i-1,k,j)+rv(i,k,j))*tan(xlat(i,j)*degrad) &
4274 - 0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j)) )
4282 DO j=jts,MIN(jde-1,jte)
4286 ru_tend(i,k,j)=ru_tend(i,k,j) + 0.5*(vxgm(i,k,j)+vxgm(i-1,k,j)) &
4287 *0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+rv(i-1,k,j)+rv(i,k,j)) &
4288 - u(i,k,j)*reradius &
4289 *0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j))
4297 ! curvature term for v momentum eqn.
4299 ! Map scale factor notes
4300 ! ADT eqn 45, RHS terms 4 and 5, in cylindrical: - mu u*u tan(lat)/(a mx)
4302 ! ru = mu u / my ; rw = mu w / my ; rv = mu v / mx
4304 ! - (my/mx)*u ru tan(lat) / a - (my/mx)*v rw / a
4305 ! = - [my/(mx*a)]*[u ru tan(lat) + v rw]
4306 ! - (1/a)*[(my/mx)*u ru tan(lat) + w rv]
4307 ! xlat defined with end points half grid space from pole, hence are on
4308 ! u latitude points => av here
4310 ! in original wrf, there was a sign error for the rw contribution
4313 IF ( config_flags%open_ys .or. specified .or. &
4314 config_flags%nested .or. config_flags%polar) j_start = MAX ( jds+1 , jts )
4315 IF ( config_flags%open_ye .or. specified .or. &
4316 config_flags%nested .or. config_flags%polar) j_end = MIN ( jde-1 , jte )
4318 IF ((config_flags%map_proj == 6) .OR. (config_flags%polar)) THEN
4322 DO i=its,MIN(ite,ide-1)
4323 rv_tend(i,k,j)=rv_tend(i,k,j) - (msfvy(i,j)/msfvx(i,j))*reradius* ( &
4324 0.25*(u(i,k,j)+u(i+1,k,j)+u(i,k,j-1)+u(i+1,k,j-1))* &
4325 tan((xlat(i,j)+xlat(i,j-1))*0.5*degrad)* &
4326 0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
4327 + v(i,k,j)*0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+ &
4328 rw(i,k+1,j)+rw(i,k,j)) )
4337 DO i=its,MIN(ite,ide-1)
4339 rv_tend(i,k,j)=rv_tend(i,k,j) - 0.5*(vxgm(i,k,j)+vxgm(i,k,j-1)) &
4340 *0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
4341 - (msfvy(i,j)/msfvx(i,j))*v(i,k,j)*reradius &
4342 *0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+rw(i,k+1,j)+rw(i,k,j))
4350 ! curvature term for vertical momentum eqn.
4352 ! Notes on map scale factors:
4353 ! ADT eqn 46, RHS term 4: [mu/(a my)]*[u*u + v*v]
4354 ! ru = mu u / my ; rw = mu w / my ; rv = mu v / mx
4355 ! terms are: u ru / a + (mx/my)v rv / a
4357 DO j=jts,MIN(jte,jde-1)
4359 DO i=its,MIN(ite,ide-1)
4361 rw_tend(i,k,j)=rw_tend(i,k,j) + reradius* &
4362 (0.5*(fzm(k)*(ru(i,k,j)+ru(i+1,k,j))+fzp(k)*(ru(i,k-1,j)+ru(i+1,k-1,j))) &
4363 *0.5*(fzm(k)*( u(i,k,j) +u(i+1,k,j))+fzp(k)*( u(i,k-1,j) +u(i+1,k-1,j))) &
4364 +(msftx(i,j)/msfty(i,j))*0.5*(fzm(k)*(rv(i,k,j)+rv(i,k,j+1))+fzp(k)*(rv(i,k-1,j)+rv(i,k-1,j+1))) &
4365 *0.5*(fzm(k)*( v(i,k,j) +v(i,k,j+1))+fzp(k)*( v(i,k-1,j) +v(i,k-1,j+1))))
4371 END SUBROUTINE curvature
4373 !------------------------------------------------------------------------------
4375 SUBROUTINE decouple ( rr, rfield, field, name, config_flags, &
4377 ids, ide, jds, jde, kds, kde, &
4378 ims, ime, jms, jme, kms, kme, &
4379 its, ite, jts, jte, kts, kte )
4385 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
4387 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4388 ims, ime, jms, jme, kms, kme, &
4389 its, ite, jts, jte, kts, kte
4391 CHARACTER(LEN=1) , INTENT(IN ) :: name
4393 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: rfield
4395 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: rr
4397 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT ) :: field
4399 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, fzp
4403 INTEGER :: i, j, k, itf, jtf, ktf
4407 ! decouple decouples a variable from the column dry-air mass.
4413 IF (name .EQ. 'u')THEN
4420 field(i,k,j)=rfield(i,k,j)/(0.5*(rr(i,k,j)+rr(i-1,k,j)))
4425 ELSE IF (name .EQ. 'v')THEN
4432 field(i,k,j)=rfield(i,k,j)/(0.5*(rr(i,k,j)+rr(i,k,j-1)))
4437 ELSE IF (name .EQ. 'w')THEN
4443 field(i,k,j)=rfield(i,k,j)/(fzm(k)*rr(i,k,j)+fzp(k)*rr(i,k-1,j))
4457 ! For theta we will decouple tb and tp and add them to give t afterwards
4461 field(i,k,j)=rfield(i,k,j)/rr(i,k,j)
4468 END SUBROUTINE decouple
4470 !-------------------------------------------------------------------------------
4473 SUBROUTINE zero_tend ( tendency, &
4474 ids, ide, jds, jde, kds, kde, &
4475 ims, ime, jms, jme, kms, kme, &
4476 its, ite, jts, jte, kts, kte )
4483 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4484 ims, ime, jms, jme, kms, kme, &
4485 its, ite, jts, jte, kts, kte
4487 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
4491 INTEGER :: i, j, k, itf, jtf, ktf
4495 ! zero_tend sets the input tendency array to zero.
4502 tendency(i,k,j) = 0.
4507 END SUBROUTINE zero_tend
4509 !-------------------------------------------------------------------------------
4510 ! Sets the an array on the polar v point(s) to zero
4511 SUBROUTINE zero_pole ( field, &
4512 ids, ide, jds, jde, kds, kde, &
4513 ims, ime, jms, jme, kms, kme, &
4514 its, ite, jts, jte, kts, kte )
4521 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4522 ims, ime, jms, jme, kms, kme, &
4523 its, ite, jts, jte, kts, kte
4525 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: field
4531 IF (jts == jds) THEN
4538 IF (jte == jde) THEN
4546 END SUBROUTINE zero_pole
4548 !-------------------------------------------------------------------------------
4549 ! Sets the an array on the polar v point(s)
4550 SUBROUTINE pole_point_bc ( field, &
4551 ids, ide, jds, jde, kds, kde, &
4552 ims, ime, jms, jme, kms, kme, &
4553 its, ite, jts, jte, kts, kte )
4560 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4561 ims, ime, jms, jme, kms, kme, &
4562 its, ite, jts, jte, kts, kte
4564 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: field
4570 IF (jts == jds) THEN
4573 ! field(i,k,jts) = 2*field(i,k,jts+1) - field(i,k,jts+2)
4574 field(i,k,jts) = field(i,k,jts+1)
4578 IF (jte == jde) THEN
4581 ! field(i,k,jte) = 2*field(i,k,jte-1) - field(i,k,jte-2)
4582 field(i,k,jte) = field(i,k,jte-1)
4587 END SUBROUTINE pole_point_bc
4589 !======================================================================
4590 ! physics prep routines
4591 !======================================================================
4593 SUBROUTINE phy_prep ( config_flags, & ! input
4594 mu, muu, muv, u, v, p, pb, alt, ph, & ! input
4595 phb, t, tsk, moist, n_moist, & ! input
4596 rho, th_phy, p_phy , pi_phy , & ! output
4597 u_phy, v_phy, p8w, t_phy, t8w, & ! output
4598 z, z_at_w, dz8w, & ! output
4599 p_hyd, p_hyd_w, dnw, & ! output
4600 fzm, fzp, znw, p_top, & ! params
4602 RTHBLTEN, RUBLTEN, RVBLTEN, &
4603 RQVBLTEN, RQCBLTEN, RQIBLTEN, &
4604 RUCUTEN, RVCUTEN, RTHCUTEN, &
4605 RQVCUTEN, RQCCUTEN, RQRCUTEN, &
4606 RQICUTEN, RQSCUTEN, &
4607 RUSHTEN, RVSHTEN, RTHSHTEN, &
4608 RQVSHTEN, RQCSHTEN, RQRSHTEN, &
4609 RQISHTEN, RQSSHTEN, RQGSHTEN, &
4611 RUNDGDTEN, RVNDGDTEN, RTHNDGDTEN, &
4612 RPHNDGDTEN,RQVNDGDTEN, RMUNDGDTEN, &
4613 ids, ide, jds, jde, kds, kde, &
4614 ims, ime, jms, jme, kms, kme, &
4615 its, ite, jts, jte, kts, kte )
4616 !----------------------------------------------------------------------
4618 !----------------------------------------------------------------------
4620 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
4622 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4623 ims, ime, jms, jme, kms, kme, &
4624 its, ite, jts, jte, kts, kte
4625 INTEGER , INTENT(IN ) :: n_moist
4627 REAL, DIMENSION( ims:ime, kms:kme , jms:jme , n_moist ), INTENT(IN) :: moist
4630 REAL , DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: TSK, mu, muu, muv
4632 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4633 INTENT( OUT) :: u_phy, &
4646 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4647 INTENT( OUT) :: p_hyd, &
4650 REAL , INTENT(IN ) :: p_top
4652 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4653 INTENT(IN ) :: pb, &
4663 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
4666 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: znw, &
4669 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
4670 INTENT(INOUT) :: RTHRATEN
4672 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
4673 INTENT(INOUT) :: RUCUTEN, &
4691 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
4692 INTENT(INOUT) :: RUBLTEN, &
4699 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
4700 INTENT(INOUT) :: RTHFTEN, &
4703 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
4704 INTENT(INOUT) :: RUNDGDTEN, &
4710 REAL, DIMENSION( ims:ime, jms:jme ) , &
4711 INTENT(INOUT) :: RMUNDGDTEN
4713 INTEGER :: i_start, i_end, j_start, j_end, k_start, k_end, i_startu, j_startv
4715 REAL :: w1, w2, z0, z1, z2
4719 !-----------------------------------------------------------------------
4723 ! phys_prep calculates a number of diagnostic quantities needed by
4724 ! the physics routines. It also decouples the physics tendencies from
4725 ! the column dry-air mass (the physics routines expect to see/update the
4726 ! uncoupled tendencies).
4730 ! set up loop bounds for this grid's boundary conditions
4733 i_end = min( ite,ide-1 )
4735 j_end = min( jte,jde-1 )
4738 k_end = min( kte, kde-1 )
4740 ! compute thermodynamics and velocities at pressure points (or half levels)
4742 do j = j_start,j_end
4743 do k = k_start, k_end
4744 do i = i_start, i_end
4746 th_phy(i,k,j) = t(i,k,j) + t0
4747 p_phy(i,k,j) = p(i,k,j) + pb(i,k,j)
4748 pi_phy(i,k,j) = (p_phy(i,k,j)/p1000mb)**rcp
4749 t_phy(i,k,j) = th_phy(i,k,j)*pi_phy(i,k,j)
4750 rho(i,k,j) = 1./alt(i,k,j)*(1.+moist(i,k,j,P_QV))
4751 u_phy(i,k,j) = 0.5*(u(i,k,j)+u(i+1,k,j))
4752 v_phy(i,k,j) = 0.5*(v(i,k,j)+v(i,k,j+1))
4758 ! compute z at w points
4760 do j = j_start,j_end
4762 do i = i_start, i_end
4763 z_at_w(i,k,j) = (phb(i,k,j)+ph(i,k,j))/g
4768 do j = j_start,j_end
4769 do k = k_start, kte-1
4770 do i = i_start, i_end
4771 dz8w(i,k,j) = z_at_w(i,k+1,j)-z_at_w(i,k,j)
4776 do j = j_start,j_end
4777 do i = i_start, i_end
4782 ! compute z at p points or half levels (average of z at full levels)
4784 do j = j_start,j_end
4785 do k = k_start, k_end
4786 do i = i_start, i_end
4787 z(i,k,j) = 0.5*(z_at_w(i,k,j) +z_at_w(i,k+1,j) )
4792 ! interp t and p to full levels
4794 do j = j_start,j_end
4796 do i = i_start, i_end
4797 p8w(i,k,j) = fzm(k)*p_phy(i,k,j)+fzp(k)*p_phy(i,k-1,j)
4798 t8w(i,k,j) = fzm(k)*t_phy(i,k,j)+fzp(k)*t_phy(i,k-1,j)
4803 ! extrapolate p and t to surface and top.
4804 ! we'll use an extrapolation in z for now
4806 do j = j_start,j_end
4807 do i = i_start, i_end
4814 w1 = (z0 - z2)/(z1 - z2)
4816 p8w(i,1,j) = w1*p_phy(i,1,j)+w2*p_phy(i,2,j)
4817 t8w(i,1,j) = w1*t_phy(i,1,j)+w2*t_phy(i,2,j)
4821 z0 = z_at_w(i,kte,j)
4824 w1 = (z0 - z2)/(z1 - z2)
4827 ! p8w(i,kde,j) = w1*p_phy(i,kde-1,j)+w2*p_phy(i,kde-2,j)
4828 !!! bug fix extrapolate ln(p) so p is positive definite
4829 p8w(i,kde,j) = exp(w1*log(p_phy(i,kde-1,j))+w2*log(p_phy(i,kde-2,j)))
4830 t8w(i,kde,j) = w1*t_phy(i,kde-1,j)+w2*t_phy(i,kde-2,j)
4835 ! calculate hydrostatic pressure at both full and half levels
4836 ! first, full level p: assuming dry over model top
4838 do j = j_start,j_end
4839 do i = i_start, i_end
4840 p_hyd_w(i,kte,j) = p_top
4844 do j = j_start,j_end
4845 do k = kte-1, k_start, -1
4846 do i = i_start, i_end
4848 do n = PARAM_FIRST_SCALAR,n_moist
4849 qtot = qtot + moist(i,k,j,n)
4851 p_hyd_w(i,k,j) = p_hyd_w(i,k+1,j) - (1.+qtot)*mu(i,j)*dnw(k)
4852 ! p_hyd_w(i,k,j) = p_hyd_w(i,k+1,j)+1./alt(i,k,j)*(1.+moist(i,k,j,P_QV))*g*dz8w(i,k,j)
4857 ! now calculate hydrostatic pressure at half levels
4859 do j = j_start,j_end
4860 do k = k_start, k_end
4861 do i = i_start, i_end
4862 p_hyd(i,k,j) = 0.5*(p_hyd_w(i,k,j)+p_hyd_w(i,k+1,j))
4867 ! decouple all physics tendencies
4869 IF (config_flags%ra_lw_physics .gt. 0 .or. config_flags%ra_sw_physics .gt. 0) THEN
4874 RTHRATEN(I,K,J)=RTHRATEN(I,K,J)/mu(I,J)
4881 IF (config_flags%cu_physics .gt. 0) THEN
4886 RUCUTEN(I,K,J) =RUCUTEN(I,K,J)/mu(I,J)
4887 RVCUTEN(I,K,J) =RVCUTEN(I,K,J)/mu(I,J)
4888 RTHCUTEN(I,K,J)=RTHCUTEN(I,K,J)/mu(I,J)
4893 IF (P_QV .ge. PARAM_FIRST_SCALAR)THEN
4897 RQVCUTEN(I,K,J)=RQVCUTEN(I,K,J)/mu(I,J)
4903 IF (P_QC .ge. PARAM_FIRST_SCALAR)THEN
4907 RQCCUTEN(I,K,J)=RQCCUTEN(I,K,J)/mu(I,J)
4913 IF (P_QR .ge. PARAM_FIRST_SCALAR)THEN
4917 RQRCUTEN(I,K,J)=RQRCUTEN(I,K,J)/mu(I,J)
4923 IF (P_QI .ge. PARAM_FIRST_SCALAR)THEN
4927 RQICUTEN(I,K,J)=RQICUTEN(I,K,J)/mu(I,J)
4933 IF(P_QS .ge. PARAM_FIRST_SCALAR)THEN
4937 RQSCUTEN(I,K,J)=RQSCUTEN(I,K,J)/mu(I,J)
4945 IF (config_flags%shcu_physics .gt. 0) THEN
4950 RUSHTEN(I,K,J) =RUSHTEN(I,K,J)/mu(I,J)
4951 RVSHTEN(I,K,J) =RVSHTEN(I,K,J)/mu(I,J)
4952 RTHSHTEN(I,K,J)=RTHSHTEN(I,K,J)/mu(I,J)
4957 IF (P_QV .ge. PARAM_FIRST_SCALAR)THEN
4961 RQVSHTEN(I,K,J)=RQVSHTEN(I,K,J)/mu(I,J)
4967 IF (P_QC .ge. PARAM_FIRST_SCALAR)THEN
4971 RQCSHTEN(I,K,J)=RQCSHTEN(I,K,J)/mu(I,J)
4977 IF (P_QR .ge. PARAM_FIRST_SCALAR)THEN
4981 RQRSHTEN(I,K,J)=RQRSHTEN(I,K,J)/mu(I,J)
4987 IF (P_QI .ge. PARAM_FIRST_SCALAR)THEN
4991 RQISHTEN(I,K,J)=RQISHTEN(I,K,J)/mu(I,J)
4997 IF(P_QS .ge. PARAM_FIRST_SCALAR)THEN
5001 RQSSHTEN(I,K,J)=RQSSHTEN(I,K,J)/mu(I,J)
5007 IF(P_QG .ge. PARAM_FIRST_SCALAR)THEN
5011 RQGSHTEN(I,K,J)=RQGSHTEN(I,K,J)/mu(I,J)
5019 IF (config_flags%bl_pbl_physics .gt. 0) THEN
5024 RUBLTEN(I,K,J) =RUBLTEN(I,K,J)/mu(I,J)
5025 RVBLTEN(I,K,J) =RVBLTEN(I,K,J)/mu(I,J)
5026 RTHBLTEN(I,K,J)=RTHBLTEN(I,K,J)/mu(I,J)
5031 IF (P_QV .ge. PARAM_FIRST_SCALAR) THEN
5035 RQVBLTEN(I,K,J)=RQVBLTEN(I,K,J)/mu(I,J)
5041 IF (P_QC .ge. PARAM_FIRST_SCALAR) THEN
5045 RQCBLTEN(I,K,J)=RQCBLTEN(I,K,J)/mu(I,J)
5051 IF (P_QI .ge. PARAM_FIRST_SCALAR) THEN
5055 RQIBLTEN(I,K,J)=RQIBLTEN(I,K,J)/mu(I,J)
5063 ! decouple advective forcing required by Grell-Devenyi scheme
5065 if(( config_flags%cu_physics == GDSCHEME ) .OR. &
5066 ( config_flags%cu_physics == G3SCHEME ) .OR. &
5067 ( config_flags%cu_physics == KFETASCHEME ) .OR. &
5068 ( config_flags%cu_physics == TIEDTKESCHEME ) ) then ! Tiedtke ZCX&YQW
5073 RTHFTEN(I,K,J)=RTHFTEN(I,K,J)/mu(I,J)
5078 IF (P_QV .ge. PARAM_FIRST_SCALAR)THEN
5082 RQVFTEN(I,K,J)=RQVFTEN(I,K,J)/mu(I,J)
5091 ! note fdda u and v tendencies are staggered, also only interior points have muu/muv,
5092 ! so only decouple those
5094 IF (config_flags%grid_fdda .gt. 0) THEN
5096 i_startu=MAX(its,ids+1)
5097 j_startv=MAX(jts,jds+1)
5102 RUNDGDTEN(I,K,J) =RUNDGDTEN(I,K,J)/muu(I,J)
5109 RVNDGDTEN(I,K,J) =RVNDGDTEN(I,K,J)/muv(I,J)
5116 RTHNDGDTEN(I,K,J)=RTHNDGDTEN(I,K,J)/mu(I,J)
5117 ! RMUNDGDTEN(I,J) - no coupling
5122 IF (config_flags%grid_fdda .EQ. 2) THEN
5126 RPHNDGDTEN(I,K,J)=RPHNDGDTEN(I,K,J)/mu(I,J)
5131 ELSE IF (config_flags%grid_fdda .EQ. 1) THEN
5132 IF (P_QV .ge. PARAM_FIRST_SCALAR) THEN
5136 RQVNDGDTEN(I,K,J)=RQVNDGDTEN(I,K,J)/mu(I,J)
5145 END SUBROUTINE phy_prep
5147 !------------------------------------------------------------
5149 SUBROUTINE moist_physics_prep_em( t_new, t_old, t0, rho, al, alb, &
5150 p, p8w, p0, pb, ph, phb, &
5154 config_flags,fzm, fzp, &
5155 ids,ide, jds,jde, kds,kde, &
5156 ims,ime, jms,jme, kms,kme, &
5157 its,ite, jts,jte, kts,kte )
5161 ! Here we construct full fields
5162 ! needed by the microphysics
5164 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
5166 INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
5167 INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
5168 INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
5170 REAL, INTENT(IN ) :: dt
5172 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5173 INTENT(IN ) :: al, &
5181 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
5184 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5185 INTENT( OUT) :: rho, &
5194 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5195 INTENT(INOUT) :: h_diabatic
5197 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5198 INTENT(INOUT) :: t_new, &
5201 REAL, INTENT(IN ) :: t0, p0
5202 REAL :: z0,z1,z2,w1,w2
5204 INTEGER :: i_start, i_end, j_start, j_end, k_start, k_end
5207 !--------------------------------------------------------------------
5211 ! moist_phys_prep_em calculates a number of diagnostic quantities needed by
5212 ! the microphysics routines.
5216 ! set up loop bounds for this grid's boundary conditions
5219 i_end = min( ite,ide-1 )
5221 j_end = min( jte,jde-1 )
5224 k_end = min( kte, kde-1 )
5226 DO j = j_start, j_end
5228 DO i = i_start, i_end
5229 z_at_w(i,k,j) = (ph(i,k,j)+phb(i,k,j))/g
5234 do j = j_start,j_end
5235 do k = k_start, kte-1
5236 do i = i_start, i_end
5237 dz8w(i,k,j) = z_at_w(i,k+1,j)-z_at_w(i,k,j)
5242 do j = j_start,j_end
5243 do i = i_start, i_end
5249 ! compute full pii, rho, and z at the new time-level
5250 ! (needed for physics).
5251 ! convert perturbation theta to full theta (th_phy)
5252 ! use h_diabatic to temporarily save pre-microphysics full theta
5254 DO j = j_start, j_end
5255 DO k = k_start, k_end
5256 DO i = i_start, i_end
5259 t_new(i,k,j) = t_new(i,k,j)-h_diabatic(i,k,j)*dt
5261 th_phy(i,k,j) = t_new(i,k,j) + t0
5262 h_diabatic(i,k,j) = th_phy(i,k,j)
5263 rho(i,k,j) = 1./(al(i,k,j)+alb(i,k,j))
5264 pii(i,k,j) = ((p(i,k,j)+pb(i,k,j))/p0)**rcp
5265 z(i,k,j) = 0.5*(z_at_w(i,k,j) +z_at_w(i,k+1,j) )
5266 pf(i,k,j) = p(i,k,j)+pb(i,k,j)
5272 ! interp t and p at w points
5274 do j = j_start,j_end
5276 do i = i_start, i_end
5277 p8w(i,k,j) = fzm(k)*pf(i,k,j)+fzp(k)*pf(i,k-1,j)
5282 ! extrapolate p and t to surface and top.
5283 ! we'll use an extrapolation in z for now
5285 do j = j_start,j_end
5286 do i = i_start, i_end
5293 w1 = (z0 - z2)/(z1 - z2)
5295 p8w(i,1,j) = w1*pf(i,1,j)+w2*pf(i,2,j)
5299 z0 = z_at_w(i,kte,j)
5302 w1 = (z0 - z2)/(z1 - z2)
5304 ! p8w(i,kde,j) = w1*pf(i,kde-1,j)+w2*pf(i,kde-2,j)
5305 p8w(i,kde,j) = exp(w1*log(pf(i,kde-1,j))+w2*log(pf(i,kde-2,j)))
5310 END SUBROUTINE moist_physics_prep_em
5312 !------------------------------------------------------------------------------
5314 SUBROUTINE moist_physics_finish_em( t_new, t_old, t0, mut, &
5315 th_phy, h_diabatic, dt, &
5317 #if ( WRF_DFI_RADAR == 1 )
5318 dfi_tten_rad,dfi_stage, &
5320 ids,ide, jds,jde, kds,kde, &
5321 ims,ime, jms,jme, kms,kme, &
5322 its,ite, jts,jte, kts,kte )
5326 ! Here we construct full fields
5327 ! needed by the microphysics
5329 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
5331 INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
5332 INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
5333 INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
5335 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5336 INTENT(INOUT) :: t_new, &
5340 #if ( WRF_DFI_RADAR == 1 )
5341 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5342 INTENT(IN), OPTIONAL :: dfi_tten_rad
5343 INTEGER, INTENT(IN ) ,OPTIONAL :: dfi_stage
5344 REAL :: dfi_tten_max, old_max
5347 REAL mpten, mptenmax, mptenmin
5349 REAL, DIMENSION( ims:ime , jms:jme ), INTENT(INOUT) :: mut
5352 REAL, INTENT(IN ) :: t0, dt
5354 INTEGER :: i_start, i_end, j_start, j_end, k_start, k_end
5355 INTEGER :: i, j, k, imax, jmax, imin, jmin
5357 !--------------------------------------------------------------------
5361 ! moist_phys_finish_em resets theta to its perturbation value and
5362 ! computes and stores the microphysics diabatic heating term.
5366 ! set up loop bounds for this grid's boundary conditions
5370 i_end = min( ite,ide-1 )
5372 j_end = min( jte,jde-1 )
5373 ! i_start=max(its,ids+4)
5374 ! i_end=min(ite,ide-5)
5375 ! j_start=max(jts,jds+4)
5376 ! j_end=min(jte,jde-5)
5379 k_end = min( kte, kde-1 )
5381 #if ( WRF_DFI_RADAR == 1 )
5382 IF ( PRESENT(dfi_stage) .and. PRESENT(dfi_tten_rad) ) THEN
5383 IF ( dfi_stage ==DFI_FWD ) THEN
5384 !$OMP CRITICAL(big_step_utilities)
5385 WRITE(wrf_err_message,*)'Add radar tendency: i_start,j_start: ', i_start, j_start
5386 CALL wrf_debug ( 100 , TRIM(wrf_err_message) )
5387 !$OMP END CRITICAL(big_step_utilities)
5394 ! add microphysics theta diff to perturbation theta, set h_diabatic
5396 IF ( config_flags%no_mp_heating .eq. 0 ) THEN
5399 DO j = j_start, j_end
5400 DO k = k_start, k_end
5401 DO i = i_start, i_end
5402 mpten = th_phy(i,k,j)-h_diabatic(i,k,j)
5403 #if ( WRF_DFI_RADAR == 1 )
5404 if(mpten.gt.mptenmax) then
5409 if(mpten.lt.mptenmin) then
5414 mpten=min(config_flags%mp_tend_lim*dt, mpten)
5415 mpten=max(-config_flags%mp_tend_lim*dt, mpten)
5418 if(dfi_tten_max < dfi_tten_rad(i,k,j) ) dfi_tten_max = dfi_tten_rad(i,k,j)
5419 if(old_max < (th_phy(i,k,j)-h_diabatic(i,k,j)) ) old_max=th_phy(i,k,j)-h_diabatic(i,k,j)
5422 IF ( PRESENT(dfi_stage) .and. PRESENT(dfi_tten_rad) ) THEN
5423 IF ( dfi_stage == DFI_FWD .and. dfi_tten_rad(i,k,j) >= -0.1 .and. &
5424 dfi_tten_rad(i,k,j) <= 0.1 .and. k < k_end ) THEN
5425 ! add radar temp tendency
5426 ! there is radar coverage
5427 t_new(i,k,j) = t_new(i,k,j) + (dfi_tten_rad(i,k,j))*dt
5430 t_new(i,k,j) = t_new(i,k,j) + mpten
5434 t_new(i,k,j) = t_new(i,k,j) + mpten
5436 h_diabatic(i,k,j) = mpten/dt
5443 DO j = j_start, j_end
5444 DO k = k_start, k_end
5445 DO i = i_start, i_end
5446 ! t_new(i,k,j) = t_new(i,k,j)
5447 h_diabatic(i,k,j) = 0.
5453 END SUBROUTINE moist_physics_finish_em
5455 !----------------------------------------------------------------
5458 SUBROUTINE init_module_big_step
5459 END SUBROUTINE init_module_big_step
5461 SUBROUTINE set_tend ( field, field_adv_tend, msf, &
5462 ids, ide, jds, jde, kds, kde, &
5463 ims, ime, jms, jme, kms, kme, &
5464 its, ite, jts, jte, kts, kte )
5470 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
5471 ims, ime, jms, jme, kms, kme, &
5472 its, ite, jts, jte, kts, kte
5474 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT) :: field
5476 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN) :: field_adv_tend
5478 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN) :: msf
5482 INTEGER :: i, j, k, itf, jtf, ktf
5486 ! set_tend copies the advective tendency array into the tendency array.
5490 jtf = MIN(jte,jde-1)
5491 ktf = MIN(kte,kde-1)
5492 itf = MIN(ite,ide-1)
5496 field(i,k,j) = field_adv_tend(i,k,j)*msf(i,j)
5501 END SUBROUTINE set_tend
5503 !------------------------------------------------------------------------------
5505 SUBROUTINE rk_rayleigh_damp( ru_tendf, rv_tendf, &
5506 rw_tendf, t_tendf, &
5507 u, v, w, t, t_init, &
5508 mut, muu, muv, ph, phb, &
5509 u_base, v_base, t_base, z_base, &
5511 ids, ide, jds, jde, kds, kde, &
5512 ims, ime, jms, jme, kms, kme, &
5513 its, ite, jts, jte, kts, kte )
5515 ! History: Apr 2005 Modifications by George Bryan, NCAR:
5516 ! - Generalized the code in a way that allows for
5517 ! simulations with steep terrain.
5519 ! Jul 2004 Modifications by George Bryan, NCAR:
5520 ! - Modified the code to use u_base, v_base, and t_base
5521 ! arrays for the background state. Removed the hard-wired
5522 ! base-state values.
5523 ! - Modified the code to use dampcoef, zdamp, and damp_opt,
5524 ! i.e., the upper-level damper variables in namelist.input.
5525 ! Removed the hard-wired variables in the older version.
5526 ! This damper is used when damp_opt = 2.
5527 ! - Modified the code to account for the movement of the
5528 ! model surfaces with time. The code now obtains a base-
5529 ! state value by interpolation using the "_base" arrays.
5531 ! Nov 2003 Bug fix by Jason Knievel, NCAR
5533 ! Aug 2003 Meridional dimension, some comments, and
5534 ! changes in layout of the code added by
5535 ! Jason Knievel, NCAR
5537 ! Jul 2003 Original code by Bill Skamarock, NCAR
5539 ! Purpose: This routine applies Rayleigh damping to a layer at top
5540 ! of the model domain.
5542 !-----------------------------------------------------------------------
5543 ! Begin declarations.
5547 INTEGER, INTENT( IN ) &
5548 :: ids, ide, jds, jde, kds, kde, &
5549 ims, ime, jms, jme, kms, kme, &
5550 its, ite, jts, jte, kts, kte
5552 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( INOUT ) &
5553 :: ru_tendf, rv_tendf, rw_tendf, t_tendf
5555 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( IN ) &
5556 :: u, v, w, t, t_init, ph, phb
5558 REAL, DIMENSION( ims:ime, jms:jme ), INTENT( IN ) &
5561 REAL, DIMENSION( kms:kme ) , INTENT(IN ) &
5562 :: u_base, v_base, t_base, z_base
5570 :: i_start, i_end, j_start, j_end, k_start, k_end, i, j, k, ktf, k1, k2
5573 :: pii, dcoef, z, ztop
5575 REAL :: wkp1, wk, wkm1
5577 REAL, DIMENSION( kms:kme ) :: z00, u00, v00, t00
5580 !-----------------------------------------------------------------------
5582 pii = 2.0 * asin(1.0)
5584 ktf = MIN( kte, kde-1 )
5586 !-----------------------------------------------------------------------
5587 ! Adjust u to base state.
5589 DO j = jts, MIN( jte, jde-1 )
5590 DO i = its, MIN( ite, ide )
5592 ! Get height at top of model
5593 ztop = 0.5*( phb(i ,kde,j)+phb(i-1,kde,j) &
5594 +ph(i ,kde,j)+ph(i-1,kde,j) )/g
5596 ! Find bottom of damping layer
5599 DO WHILE( z >= (ztop-zdamp) )
5600 z = 0.25*( phb(i ,k1,j)+phb(i ,k1+1,j) &
5601 +phb(i-1,k1,j)+phb(i-1,k1+1,j) &
5602 +ph(i ,k1,j)+ph(i ,k1+1,j) &
5603 +ph(i-1,k1,j)+ph(i-1,k1+1,j))/g
5609 ! Get reference state at model levels
5612 DO WHILE( z_base(k2) .gt. z00(k) )
5616 u00(k) = u_base(k2) + ( u_base(k2) - u_base(k2-1) ) &
5617 * ( z00(k) - z_base(k2) ) &
5618 / ( z_base(k2) - z_base(k2-1) )
5620 u00(k) = u_base(k2) + ( u_base(k2+1) - u_base(k2) ) &
5621 * ( z00(k) - z_base(k2) ) &
5622 / ( z_base(k2+1) - z_base(k2) )
5626 ! Apply the Rayleigh damper
5628 dcoef = 1.0 - MIN( 1.0, ( ztop - z00(k) ) / zdamp )
5629 dcoef = (SIN( 0.5 * pii * dcoef ) )**2
5630 ru_tendf(i,k,j) = ru_tendf(i,k,j) - &
5631 muu(i,j) * ( dcoef * dampcoef ) * &
5632 ( u(i,k,j) - u00(k) )
5638 ! End adjustment of u.
5639 !-----------------------------------------------------------------------
5641 !-----------------------------------------------------------------------
5642 ! Adjust v to base state.
5644 DO j = jts, MIN( jte, jde )
5645 DO i = its, MIN( ite, ide-1 )
5647 ! Get height at top of model
5648 ztop = 0.5*( phb(i,kde,j )+phb(i,kde,j-1) &
5649 +ph(i,kde,j )+ph(i,kde,j-1) )/g
5651 ! Find bottom of damping layer
5654 DO WHILE( z >= (ztop-zdamp) )
5655 z = 0.25*( phb(i,k1,j )+phb(i,k1+1,j ) &
5656 +phb(i,k1,j-1)+phb(i,k1+1,j-1) &
5657 +ph(i,k1,j )+ph(i,k1+1,j ) &
5658 +ph(i,k1,j-1)+ph(i,k1+1,j-1))/g
5664 ! Get reference state at model levels
5667 DO WHILE( z_base(k2) .gt. z00(k) )
5671 v00(k) = v_base(k2) + ( v_base(k2) - v_base(k2-1) ) &
5672 * ( z00(k) - z_base(k2) ) &
5673 / ( z_base(k2) - z_base(k2-1) )
5675 v00(k) = v_base(k2) + ( v_base(k2+1) - v_base(k2) ) &
5676 * ( z00(k) - z_base(k2) ) &
5677 / ( z_base(k2+1) - z_base(k2) )
5681 ! Apply the Rayleigh damper
5683 dcoef = 1.0 - MIN( 1.0, ( ztop - z00(k) ) / zdamp )
5684 dcoef = (SIN( 0.5 * pii * dcoef ) )**2
5685 rv_tendf(i,k,j) = rv_tendf(i,k,j) - &
5686 muv(i,j) * ( dcoef * dampcoef ) * &
5687 ( v(i,k,j) - v00(k) )
5693 ! End adjustment of v.
5694 !-----------------------------------------------------------------------
5696 !-----------------------------------------------------------------------
5697 ! Adjust w to base state.
5699 DO j = jts, MIN( jte, jde-1 )
5700 DO i = its, MIN( ite, ide-1 )
5701 ztop = ( phb(i,kde,j) + ph(i,kde,j) ) / g
5702 DO k = kts, MIN( kte, kde )
5703 z = ( phb(i,k,j) + ph(i,k,j) ) / g
5704 IF ( z >= (ztop-zdamp) ) THEN
5705 dcoef = 1.0 - MIN( 1.0, ( ztop - z ) / zdamp )
5706 dcoef = ( SIN( 0.5 * pii * dcoef ) )**2
5707 rw_tendf(i,k,j) = rw_tendf(i,k,j) - &
5708 mut(i,j) * ( dcoef * dampcoef ) * w(i,k,j)
5714 ! End adjustment of w.
5715 !-----------------------------------------------------------------------
5717 !-----------------------------------------------------------------------
5718 ! Adjust potential temperature to base state.
5720 DO j = jts, MIN( jte, jde-1 )
5721 DO i = its, MIN( ite, ide-1 )
5723 ! Get height at top of model
5724 ztop = ( phb(i,kde,j) + ph(i,kde,j) ) / g
5726 ! Find bottom of damping layer
5729 DO WHILE( z >= (ztop-zdamp) )
5730 z = 0.5 * ( phb(i,k1,j) + phb(i,k1+1,j) + &
5731 ph(i,k1,j) + ph(i,k1+1,j) ) / g
5737 ! Get reference state at model levels
5740 DO WHILE( z_base(k2) .gt. z00(k) )
5744 t00(k) = t_base(k2) + ( t_base(k2) - t_base(k2-1) ) &
5745 * ( z00(k) - z_base(k2) ) &
5746 / ( z_base(k2) - z_base(k2-1) )
5748 t00(k) = t_base(k2) + ( t_base(k2+1) - t_base(k2) ) &
5749 * ( z00(k) - z_base(k2) ) &
5750 / ( z_base(k2+1) - z_base(k2) )
5754 ! Apply the Rayleigh damper
5756 dcoef = 1.0 - MIN( 1.0, ( ztop - z00(k) ) / zdamp )
5757 dcoef = (SIN( 0.5 * pii * dcoef ) )**2
5758 t_tendf(i,k,j) = t_tendf(i,k,j) - &
5759 mut(i,j) * ( dcoef * dampcoef ) * &
5760 ( t(i,k,j) - t00(k) )
5766 ! End adjustment of potential temperature.
5767 !-----------------------------------------------------------------------
5769 END SUBROUTINE rk_rayleigh_damp
5771 !==============================================================================
5772 !==============================================================================
5774 SUBROUTINE theta_relaxation( t_tendf, t, t_init, &
5777 ids, ide, jds, jde, kds, kde, &
5778 ims, ime, jms, jme, kms, kme, &
5779 its, ite, jts, jte, kts, kte )
5781 ! Purpose: Newtonian relaxation on potential temperature. Serves two
5782 ! purposes: 1) to mimic atmospheric radiation in a simple
5783 ! manner, and 2) to keep the vertical profile of temperature
5784 ! close to the initial (base-state) profile, which is useful
5785 ! for certain idealized applications.
5787 ! Reference: Rotunno and Emanuel, 1987, JAS, p. 546
5789 !-----------------------------------------------------------------------
5790 ! Begin declarations.
5794 INTEGER, INTENT( IN ) &
5795 :: ids, ide, jds, jde, kds, kde, &
5796 ims, ime, jms, jme, kms, kme, &
5797 its, ite, jts, jte, kts, kte
5799 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( INOUT ) &
5802 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( IN ) &
5803 :: t, t_init, ph, phb
5805 REAL, DIMENSION( ims:ime, jms:jme ), INTENT( IN ) &
5808 REAL, DIMENSION( kms:kme ) , INTENT(IN ) &
5813 INTEGER :: i, j, k, ktf, k2
5814 REAL :: tau_r , rmax , rmin , inv_tau_r , inv_g , rterm
5815 REAL, DIMENSION( kms:kme ) :: z00,t00
5818 !-----------------------------------------------------------------------
5820 ! set tau_r to 12 h, following RE87
5823 ! limit rterm to +/- 2 K/day
5827 ktf = MIN( kte, kde-1 )
5828 inv_tau_r = 1.0/tau_r
5831 !-----------------------------------------------------------------------
5832 ! Adjust potential temperature to base state.
5834 DO j = jts, MIN( jte, jde-1 )
5835 DO i = its, MIN( ite, ide-1 )
5837 ! Get height of model levels:
5839 z00(k) = 0.5 * ( phb(i,k,j) + phb(i,k+1,j) + &
5840 ph(i,k,j) + ph(i,k+1,j) ) * inv_g
5843 ! Get reference state:
5846 DO WHILE( z_base(k2) .gt. z00(k) .and. k2 .gt. 1 )
5850 t00(k) = t_base(k2) + ( t_base(k2) - t_base(k2-1) ) &
5851 * ( z00(k) - z_base(k2) ) &
5852 / ( z_base(k2) - z_base(k2-1) )
5854 t00(k) = t_base(k2) + ( t_base(k2+1) - t_base(k2) ) &
5855 * ( z00(k) - z_base(k2) ) &
5856 / ( z_base(k2+1) - z_base(k2) )
5860 ! Apply the RE87 R term:
5862 rterm = -( t(i,k,j) - t00(k) )*inv_tau_r
5864 rterm = min( rterm , rmax )
5865 rterm = max( rterm , rmin )
5866 t_tendf(i,k,j) = t_tendf(i,k,j) + mut(i,j)*rterm
5872 END SUBROUTINE theta_relaxation
5874 !==============================================================================
5875 !==============================================================================
5877 SUBROUTINE sixth_order_diffusion( name, field, tendency, mu, dt, &
5879 diff_6th_opt, diff_6th_factor, &
5880 ids, ide, jds, jde, kds, kde, &
5881 ims, ime, jms, jme, kms, kme, &
5882 its, ite, jts, jte, kts, kte )
5884 ! History: 14 Nov 2006 Name of variable changed by Jason Knievel
5885 ! 07 Jun 2006 Revised and generalized by Jason Knievel
5886 ! 25 Apr 2005 Original code by Jason Knievel, NCAR
5888 ! Purpose: Apply 6th-order, monotonic (flux-limited), numerical
5889 ! diffusion to 3-d velocity and to scalars.
5891 ! References: Ming Xue (MWR Aug 2000)
5892 ! Durran ("Numerical Methods for Wave Equations..." 1999)
5893 ! George Bryan (personal communication)
5895 !------------------------------------------------------------------------------
5896 ! Begin: Declarations.
5900 INTEGER, INTENT(IN) &
5901 :: ids, ide, jds, jde, kds, kde, &
5902 ims, ime, jms, jme, kms, kme, &
5903 its, ite, jts, jte, kts, kte
5905 TYPE(grid_config_rec_type), INTENT(IN) &
5908 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(INOUT) &
5911 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(IN) &
5914 REAL, DIMENSION( ims:ime , jms:jme ), INTENT(IN) &
5923 INTEGER, INTENT(IN) &
5926 CHARACTER(LEN=1) , INTENT(IN) &
5937 :: dflux_x_p0, dflux_y_p0, &
5938 dflux_x_p1, dflux_y_p1, &
5939 tendency_x, tendency_y, &
5940 mu_avg_p0, mu_avg_p1, &
5946 ! End: Declarations.
5947 !------------------------------------------------------------------------------
5949 !------------------------------------------------------------------------------
5950 ! Begin: Translate the diffusion factor into a diffusion coefficient. See
5951 ! Durran's text, section 2.4.3, then adjust for sixth-order diffusion (not
5952 ! fourth) and for diffusion in two dimensions (not one). For reference, a
5953 ! factor of 1.0 would mean complete diffusion of a 2dx wave in one time step,
5954 ! although application of the flux limiter reduces somewhat the effects of
5955 ! diffusion for a given coefficient.
5957 diff_6th_coef = diff_6th_factor * 0.015625 / ( 2.0 * dt )
5959 ! End: Translate diffusion factor.
5960 !------------------------------------------------------------------------------
5962 !------------------------------------------------------------------------------
5963 ! Begin: Assign limits of spatial loops depending on variable to be diffused.
5964 ! The halo regions are already filled with values by the time this subroutine
5965 ! is called, which allows the stencil to extend beyond the domains' edges.
5967 ktf = MIN( kte, kde-1 )
5969 IF ( name .EQ. 'u' ) THEN
5974 j_end = MIN(jde-1,jte)
5978 ELSE IF ( name .EQ. 'v' ) THEN
5981 i_end = MIN(ide-1,ite)
5987 ELSE IF ( name .EQ. 'w' ) THEN
5990 i_end = MIN(ide-1,ite)
5992 j_end = MIN(jde-1,jte)
5999 i_end = MIN(ide-1,ite)
6001 j_end = MIN(jde-1,jte)
6007 ! End: Assignment of limits of spatial loops.
6008 !------------------------------------------------------------------------------
6010 !------------------------------------------------------------------------------
6011 ! Begin: Loop across spatial dimensions.
6013 DO j = j_start, j_end
6014 DO k = k_start, k_end
6015 DO i = i_start, i_end
6017 !------------------------------------------------------------------------------
6018 ! Begin: Diffusion in x (i index).
6020 ! Calculate the diffusive flux in x direction (from Xue's eq. 3).
6022 dflux_x_p0 = ( 10.0 * ( field(i, k,j) - field(i-1,k,j) ) &
6023 - 5.0 * ( field(i+1,k,j) - field(i-2,k,j) ) &
6024 + ( field(i+2,k,j) - field(i-3,k,j) ) )
6026 dflux_x_p1 = ( 10.0 * ( field(i+1,k,j) - field(i ,k,j) ) &
6027 - 5.0 * ( field(i+2,k,j) - field(i-1,k,j) ) &
6028 + ( field(i+3,k,j) - field(i-2,k,j) ) )
6030 ! If requested in the namelist (diff_6th_opt=2), prohibit up-gradient diffusion
6031 ! (variation on Xue's eq. 10).
6033 IF ( diff_6th_opt .EQ. 2 ) THEN
6035 IF ( dflux_x_p0 * ( field(i ,k,j)-field(i-1,k,j) ) .LE. 0.0 ) THEN
6039 IF ( dflux_x_p1 * ( field(i+1,k,j)-field(i ,k,j) ) .LE. 0.0 ) THEN
6045 ! Apply 6th-order diffusion in x direction.
6047 IF ( name .EQ. 'u' ) THEN
6048 mu_avg_p0 = mu(i-1,j)
6049 mu_avg_p1 = mu(i ,j)
6050 ELSE IF ( name .EQ. 'v' ) THEN
6051 mu_avg_p0 = 0.25 * ( &
6056 mu_avg_p1 = 0.25 * ( &
6062 mu_avg_p0 = 0.5 * ( &
6065 mu_avg_p1 = 0.5 * ( &
6070 tendency_x = diff_6th_coef * &
6071 ( ( mu_avg_p1 * dflux_x_p1 ) - ( mu_avg_p0 * dflux_x_p0 ) )
6073 ! End: Diffusion in x.
6074 !------------------------------------------------------------------------------
6076 !------------------------------------------------------------------------------
6077 ! Begin: Diffusion in y (j index).
6079 ! Calculate the diffusive flux in y direction (from Xue's eq. 3).
6081 dflux_y_p0 = ( 10.0 * ( field(i,k,j ) - field(i,k,j-1) ) &
6082 - 5.0 * ( field(i,k,j+1) - field(i,k,j-2) ) &
6083 + ( field(i,k,j+2) - field(i,k,j-3) ) )
6085 dflux_y_p1 = ( 10.0 * ( field(i,k,j+1) - field(i,k,j ) ) &
6086 - 5.0 * ( field(i,k,j+2) - field(i,k,j-1) ) &
6087 + ( field(i,k,j+3) - field(i,k,j-2) ) )
6089 ! If requested in the namelist (diff_6th_opt=2), prohibit up-gradient diffusion
6090 ! (variation on Xue's eq. 10).
6092 IF ( diff_6th_opt .EQ. 2 ) THEN
6094 IF ( dflux_y_p0 * ( field(i,k,j )-field(i,k,j-1) ) .LE. 0.0 ) THEN
6098 IF ( dflux_y_p1 * ( field(i,k,j+1)-field(i,k,j ) ) .LE. 0.0 ) THEN
6104 ! Apply 6th-order diffusion in y direction.
6106 IF ( name .EQ. 'u' ) THEN
6107 mu_avg_p0 = 0.25 * ( &
6112 mu_avg_p1 = 0.25 * ( &
6117 ELSE IF ( name .EQ. 'v' ) THEN
6118 mu_avg_p0 = mu(i,j-1)
6119 mu_avg_p1 = mu(i,j )
6121 mu_avg_p0 = 0.5 * ( &
6124 mu_avg_p1 = 0.5 * ( &
6129 tendency_y = diff_6th_coef * &
6130 ( ( mu_avg_p1 * dflux_y_p1 ) - ( mu_avg_p0 * dflux_y_p0 ) )
6132 ! End: Diffusion in y.
6133 !------------------------------------------------------------------------------
6135 !------------------------------------------------------------------------------
6136 ! Begin: Combine diffusion in x and y.
6138 tendency(i,k,j) = tendency(i,k,j) + tendency_x + tendency_y
6140 ! End: Combine diffusion in x and y.
6141 !------------------------------------------------------------------------------
6147 ! End: Loop across spatial dimensions.
6148 !------------------------------------------------------------------------------
6150 END SUBROUTINE sixth_order_diffusion
6152 !==============================================================================
6153 !==============================================================================
6155 END MODULE module_big_step_utilities_em