1 !wrf:MODEL_LAYER:DYNAMICS
13 MODULE module_big_step_utilities_em
15 USE module_domain, ONLY : domain
16 USE module_model_constants
17 USE module_state_description
18 USE module_configure, ONLY : grid_config_rec_type
23 !-------------------------------------------------------------------------------
25 SUBROUTINE calc_mu_uv ( config_flags, &
27 ids, ide, jds, jde, kds, kde, &
28 ims, ime, jms, jme, kms, kme, &
29 its, ite, jts, jte, kts, kte )
35 TYPE(grid_config_rec_type ) , INTENT(IN ) :: config_flags
37 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
38 ims, ime, jms, jme, kms, kme, &
39 its, ite, jts, jte, kts, kte
41 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT( OUT) :: muu, muv
42 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu, mub
46 INTEGER :: i, j, itf, jtf, im, jm
50 ! calc_mu_uv calculates the full column dry-air mass at the staggered
51 ! horizontal velocity points (u,v) and places the results in muu and muv.
52 ! This routine uses the reference state (mub) and perturbation state (mu)
60 IF ( ( its .NE. ids ) .AND. ( ite .NE. ide ) ) THEN
63 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
66 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .NE. ide ) ) THEN
69 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
74 if(config_flags%periodic_x) im = its-1
76 ! muu(i,j) = mu(i,j) +mub(i,j)
77 ! fix for periodic b.c., 13 march 2004, wcs
78 muu(i,j) = 0.5*(mu(i,j)+mu(im,j)+mub(i,j)+mub(im,j))
80 ELSE IF ( ( its .NE. ids ) .AND. ( ite .EQ. ide ) ) THEN
83 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
88 if(config_flags%periodic_x) im = ite
90 ! muu(i,j) = mu(i-1,j) +mub(i-1,j)
91 ! fix for periodic b.c., 13 march 2004, wcs
92 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j)+mub(i-1,j)+mub(im,j))
94 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .EQ. ide ) ) THEN
97 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
102 if(config_flags%periodic_x) im = its-1
104 ! muu(i,j) = mu(i,j) +mub(i,j)
105 ! fix for periodic b.c., 13 march 2004, wcs
106 muu(i,j) = 0.5*(mu(i,j)+mu(im,j)+mub(i,j)+mub(im,j))
110 if(config_flags%periodic_x) im = ite
112 ! muu(i,j) = mu(i-1,j) +mub(i-1,j)
113 ! fix for periodic b.c., 13 march 2004, wcs
114 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j)+mub(i-1,j)+mub(im,j))
121 IF ( ( jts .NE. jds ) .AND. ( jte .NE. jde ) ) THEN
124 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
127 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .NE. jde ) ) THEN
130 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
135 if(config_flags%periodic_y) jm = jts-1
137 ! muv(i,j) = mu(i,j) +mub(i,j)
138 ! fix for periodic b.c., 13 march 2004, wcs
139 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm)+mub(i,j)+mub(i,jm))
141 ELSE IF ( ( jts .NE. jds ) .AND. ( jte .EQ. jde ) ) THEN
144 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
149 if(config_flags%periodic_y) jm = jte
151 muv(i,j) = mu(i,j-1) +mub(i,j-1)
152 ! fix for periodic b.c., 13 march 2004, wcs
153 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm)+mub(i,j-1)+mub(i,jm))
155 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .EQ. jde ) ) THEN
158 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
163 if(config_flags%periodic_y) jm = jts-1
165 ! muv(i,j) = mu(i,j) +mub(i,j)
166 ! fix for periodic b.c., 13 march 2004, wcs
167 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm)+mub(i,j)+mub(i,jm))
171 if(config_flags%periodic_y) jm = jte
173 ! muv(i,j) = mu(i,j-1) +mub(i,j-1)
174 ! fix for periodic b.c., 13 march 2004, wcs
175 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm)+mub(i,j-1)+mub(i,jm))
179 END SUBROUTINE calc_mu_uv
181 !-------------------------------------------------------------------------------
183 SUBROUTINE calc_mu_uv_1 ( config_flags, &
185 ids, ide, jds, jde, kds, kde, &
186 ims, ime, jms, jme, kms, kme, &
187 its, ite, jts, jte, kts, kte )
193 TYPE(grid_config_rec_type ) , INTENT(IN ) :: config_flags
195 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
196 ims, ime, jms, jme, kms, kme, &
197 its, ite, jts, jte, kts, kte
199 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT( OUT) :: muu, muv
200 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu
204 INTEGER :: i, j, itf, jtf, im, jm
208 ! calc_mu_uv calculates the full column dry-air mass at the staggered
209 ! horizontal velocity points (u,v) and places the results in muu and muv.
210 ! This routine uses the full state (mu)
217 IF ( ( its .NE. ids ) .AND. ( ite .NE. ide ) ) THEN
220 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
223 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .NE. ide ) ) THEN
226 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
231 if(config_flags%periodic_x) im = its-1
233 muu(i,j) = 0.5*(mu(i,j)+mu(im,j))
235 ELSE IF ( ( its .NE. ids ) .AND. ( ite .EQ. ide ) ) THEN
238 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
243 if(config_flags%periodic_x) im = ite
245 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j))
247 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .EQ. ide ) ) THEN
250 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j))
255 if(config_flags%periodic_x) im = its-1
257 muu(i,j) = 0.5*(mu(i,j)+mu(im,j))
261 if(config_flags%periodic_x) im = ite
263 muu(i,j) = 0.5*(mu(i-1,j)+mu(im,j))
270 IF ( ( jts .NE. jds ) .AND. ( jte .NE. jde ) ) THEN
273 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
276 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .NE. jde ) ) THEN
279 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
284 if(config_flags%periodic_y) jm = jts-1
286 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm))
288 ELSE IF ( ( jts .NE. jds ) .AND. ( jte .EQ. jde ) ) THEN
291 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
296 if(config_flags%periodic_y) jm = jte
298 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm))
300 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .EQ. jde ) ) THEN
303 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1))
308 if(config_flags%periodic_y) jm = jts-1
310 muv(i,j) = 0.5*(mu(i,j)+mu(i,jm))
314 if(config_flags%periodic_y) jm = jte
316 muv(i,j) = 0.5*(mu(i,j-1)+mu(i,jm))
320 END SUBROUTINE calc_mu_uv_1
322 !-------------------------------------------------------------------------------
324 ! Map scale factor comments for this routine:
325 ! Locally not changed, but sent the correct map scale factors
326 ! from module_em (msfuy, msfvx, msfty)
328 SUBROUTINE couple_momentum ( muu, ru, u, msfu, &
329 muv, rv, v, msfv, msfv_inv, &
331 ids, ide, jds, jde, kds, kde, &
332 ims, ime, jms, jme, kms, kme, &
333 its, ite, jts, jte, kts, kte )
339 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
340 ims, ime, jms, jme, kms, kme, &
341 its, ite, jts, jte, kts, kte
343 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT( OUT) :: ru, rv, rw
345 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muu, muv, mut
346 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfu, msfv, msft, msfv_inv
348 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: u, v, w
352 INTEGER :: i, j, k, itf, jtf, ktf
356 ! couple_momentum couples the velocities to the full column mass and
369 ru(i,k,j)=u(i,k,j)*muu(i,j)/msfu(i,j)
380 rv(i,k,j)=v(i,k,j)*muv(i,j)*msfv_inv(i,j)
381 ! rv(i,k,j)=v(i,k,j)*muv(i,j)/msfv(i,j)
392 rw(i,k,j)=w(i,k,j)*mut(i,j)/msft(i,j)
397 END SUBROUTINE couple_momentum
399 !-------------------------------------------------------------------
401 SUBROUTINE calc_mu_staggered ( mu, mub, muu, muv, &
402 ids, ide, jds, jde, kds, kde, &
403 ims, ime, jms, jme, kms, kme, &
404 its, ite, jts, jte, kts, kte )
410 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
411 ims, ime, jms, jme, kms, kme, &
412 its, ite, jts, jte, kts, kte
414 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT( OUT) :: muu, muv
415 REAL, DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu, mub
419 INTEGER :: i, j, itf, jtf
423 ! calc_mu_staggered calculates the full dry air mass at the staggered
424 ! velocity points (u,v).
431 IF ( ( its .NE. ids ) .AND. ( ite .NE. ide ) ) THEN
434 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
437 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .NE. ide ) ) THEN
440 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
445 muu(i,j) = mu(i,j) +mub(i,j)
447 ELSE IF ( ( its .NE. ids ) .AND. ( ite .EQ. ide ) ) THEN
450 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
455 muu(i,j) = mu(i-1,j) +mub(i-1,j)
457 ELSE IF ( ( its .EQ. ids ) .AND. ( ite .EQ. ide ) ) THEN
460 muu(i,j) = 0.5*(mu(i,j)+mu(i-1,j)+mub(i,j)+mub(i-1,j))
465 muu(i,j) = mu(i,j) +mub(i,j)
469 muu(i,j) = mu(i-1,j) +mub(i-1,j)
476 IF ( ( jts .NE. jds ) .AND. ( jte .NE. jde ) ) THEN
479 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
482 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .NE. jde ) ) THEN
485 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
490 muv(i,j) = mu(i,j) +mub(i,j)
492 ELSE IF ( ( jts .NE. jds ) .AND. ( jte .EQ. jde ) ) THEN
495 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
500 muv(i,j) = mu(i,j-1) +mub(i,j-1)
502 ELSE IF ( ( jts .EQ. jds ) .AND. ( jte .EQ. jde ) ) THEN
505 muv(i,j) = 0.5*(mu(i,j)+mu(i,j-1)+mub(i,j)+mub(i,j-1))
510 muv(i,j) = mu(i,j) +mub(i,j)
514 muv(i,j) = mu(i,j-1) +mub(i,j-1)
518 END SUBROUTINE calc_mu_staggered
520 !-------------------------------------------------------------------------------
522 SUBROUTINE couple ( mu, mub, rfield, field, name, &
524 ids, ide, jds, jde, kds, kde, &
525 ims, ime, jms, jme, kms, kme, &
526 its, ite, jts, jte, kts, kte )
532 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
533 ims, ime, jms, jme, kms, kme, &
534 its, ite, jts, jte, kts, kte
536 CHARACTER(LEN=1) , INTENT(IN ) :: name
538 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT( OUT) :: rfield
540 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu, mub, msf
542 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: field
546 INTEGER :: i, j, k, itf, jtf, ktf
547 REAL , DIMENSION(ims:ime,jms:jme) :: muu , muv
551 ! subroutine couple couples the input variable with the dry-air
559 IF (name .EQ. 'u')THEN
561 CALL calc_mu_staggered ( mu, mub, muu, muv, &
562 ids, ide, jds, jde, kds, kde, &
563 ims, ime, jms, jme, kms, kme, &
564 its, ite, jts, jte, kts, kte )
572 rfield(i,k,j)=field(i,k,j)*muu(i,j)/msf(i,j)
577 ELSE IF (name .EQ. 'v')THEN
579 CALL calc_mu_staggered ( mu, mub, muu, muv, &
580 ids, ide, jds, jde, kds, kde, &
581 ims, ime, jms, jme, kms, kme, &
582 its, ite, jts, jte, kts, kte )
591 rfield(i,k,j)=field(i,k,j)*muv(i,j)/msf(i,j)
596 ELSE IF (name .EQ. 'w')THEN
602 rfield(i,k,j)=field(i,k,j)*(mu(i,j)+mub(i,j))/msf(i,j)
607 ELSE IF (name .EQ. 'h')THEN
613 rfield(i,k,j)=field(i,k,j)*(mu(i,j)+mub(i,j))
624 rfield(i,k,j)=field(i,k,j)*(mu(i,j)+mub(i,j))
631 END SUBROUTINE couple
634 !-------------------------------------------------------------------------------
636 SUBROUTINE calc_ww_cp ( u, v, mup, mub, ww, &
637 rdx, rdy, msftx, msfty, &
638 msfux, msfuy, msfvx, msfvx_inv, &
640 ids, ide, jds, jde, kds, kde, &
641 ims, ime, jms, jme, kms, kme, &
642 its, ite, jts, jte, kts, kte )
649 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
650 ims, ime, jms, jme, kms, kme, &
651 its, ite, jts, jte, kts, kte
653 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: u, v
654 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mup, mub, &
659 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: dnw
661 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT ) :: ww
662 REAL , INTENT(IN ) :: rdx, rdy
666 INTEGER :: i, j, k, itf, jtf, ktf
667 REAL , DIMENSION( its:ite ) :: dmdt
668 REAL , DIMENSION( its:ite, kts:kte ) :: divv
669 REAL , DIMENSION( its:ite+1, jts:jte+1 ) :: muu, muv
673 ! calc_ww calculates omega using the velocities (u,v) and the dry-air
674 ! column mass (mup+mub).
675 ! The algorithm integrates the continuity equation through the column
676 ! followed by a diagnosis of omega.
682 ! calc_ww_cp calculates omega using the velocities (u,v) and the
691 ! mu coupled with the appropriate map factor
694 DO i=its,min(ite+1,ide)
695 ! u is always coupled with my
696 muu(i,j) = 0.5*(mup(i,j)+mub(i,j)+mup(i-1,j)+mub(i-1,j))/msfuy(i,j)
700 DO j=jts,min(jte+1,jde)
702 ! v is always coupled with mx
703 ! muv(i,j) = 0.5*(mup(i,j)+mub(i,j)+mup(i,j-1)+mub(i,j-1))/msfvx(i,j)
704 muv(i,j) = 0.5*(mup(i,j)+mub(i,j)+mup(i,j-1)+mub(i,j-1))*msfvx_inv(i,j)
716 ! Comments on the modifications for map scale factors
717 ! ADT eqn 47 / my (putting rho -> 'mu') is:
718 ! (1/my) partial d mu/dt = -mx partial d/dx(mu u/my)
719 ! -mx partial d/dy(mu v/mx)
720 ! -partial d/dz(mu w/my)
722 ! Using nu instead of z the last term becomes:
723 ! -partial d/dnu(mu (dnu/dt)/my)
725 ! Integrating with respect to nu over ALL levels, with dnu/dt=0 at top
726 ! and bottom, the last term becomes = 0
728 ! Integral|bot->top[(1/my) partial d mu/dt]dnu =
729 ! Integral|bot->top[-mx partial d/dx(mu u/my)
730 ! -mx partial d/dy(mu v/mx)]dnu
732 ! muu='mu'[on u]/my, muv='mu'[on v]/mx
733 ! (1/my) partial d mu/dt is independent of nu
734 ! => LHS = Integral|bot->top[con]dnu = conservation*(-1) = -dmdt
736 ! => dmdt = mx*Integral|bot->top[partial d/dx(mu u/my) +
737 ! partial d/dy(mu v/mx)]dnu
738 ! => dmdt = sum_bot->top[divv]
740 ! divv=mx*[partial d/dx(mu u/my) + partial d/dy(mu v/mx)]*delta nu
745 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)) &
746 +rdy*(muv(i,j+1)*v(i,k,j+1)-muv(i,j)*v(i,k,j)) )
748 ! dmdt(i) = dmdt(i) + dnw(k)* ( rdx*(ru(i+1,k,j)-ru(i,k,j)) &
749 ! +rdy*(rv(i,k,j+1)-rv(i,k,j)) )
751 dmdt(i) = dmdt(i) + divv(i,k)
757 ! Further map scale factor notes:
758 ! Now integrate from bottom to top, level by level:
759 ! mu dnu/dt/my [k+1] = mu dnu/dt/my [k] + [-(1/my) partial d mu/dt
760 ! -mx partial d/dx(mu u/my)
761 ! -mx partial d/dy(mu v/mx)]*dnu[k->k+1]
762 ! ww [k+1] = ww [k] -(1/my) partial d mu/dt * dnu[k->k+1] - divv[k]
763 ! = ww [k] -dmdt * dnw[k] - divv[k]
768 ! ww(i,k,j)=ww(i,k-1,j) &
769 ! - dnw(k-1)* ( dmdt(i) &
770 ! +rdx*(ru(i+1,k-1,j)-ru(i,k-1,j)) &
771 ! +rdy*(rv(i,k-1,j+1)-rv(i,k-1,j)) )
773 ww(i,k,j)=ww(i,k-1,j) - dnw(k-1)*dmdt(i) - divv(i,k-1)
780 END SUBROUTINE calc_ww_cp
783 !-------------------------------------------------------------------------------
785 SUBROUTINE calc_cq ( moist, cqu, cqv, cqw, n_moist, &
786 ids, ide, jds, jde, kds, kde, &
787 ims, ime, jms, jme, kms, kme, &
788 its, ite, jts, jte, kts, kte )
794 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
795 ims, ime, jms, jme, kms, kme, &
796 its, ite, jts, jte, kts, kte
798 INTEGER , INTENT(IN ) :: n_moist
801 REAL, DIMENSION( ims:ime, kms:kme , jms:jme , n_moist ), INTENT(IN ) :: moist
803 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT( OUT) :: cqu, cqv, cqw
809 INTEGER :: i, j, k, itf, jtf, ktf, ispe
813 ! calc_cq calculates moist coefficients for the momentum equations.
821 IF( n_moist >= PARAM_FIRST_SCALAR ) THEN
828 DO ispe=PARAM_FIRST_SCALAR,n_moist
829 qtot = qtot + moist(i,k,j,ispe) + moist(i-1,k,j,ispe)
831 ! qtot = 0.5*( moist(i ,k,j,1)+moist(i ,k,j,2)+moist(i ,k,j,3)+ &
832 ! & moist(i-1,k,j,1)+moist(i-1,k,j,2)+moist(i-1,k,j,3) )
833 ! cqu(i,k,j) = 1./(1.+qtot)
834 cqu(i,k,j) = 1./(1.+0.5*qtot)
847 DO ispe=PARAM_FIRST_SCALAR,n_moist
848 qtot = qtot + moist(i,k,j,ispe) + moist(i,k,j-1,ispe)
850 ! qtot = 0.5*( moist(i,k,j ,1)+moist(i,k,j ,2)+moist(i,k,j ,3)+ &
851 ! & moist(i,k,j-1,1)+moist(i,k,j-1,2)+moist(i,k,j-1,3) )
852 ! cqv(i,k,j) = 1./(1.+qtot)
853 cqv(i,k,j) = 1./(1.+0.5*qtot)
865 DO ispe=PARAM_FIRST_SCALAR,n_moist
866 qtot = qtot + moist(i,k,j,ispe) + moist(i,k-1,j,ispe)
868 ! qtot = 0.5*( moist(i,k ,j,1)+moist(i,k ,j,2)+moist(i,k-1,j,3)+ &
869 ! & moist(i,k-1,j,1)+moist(i,k-1,j,2)+moist(i,k ,j,3) )
871 cqw(i,k,j) = 0.5*qtot
909 END SUBROUTINE calc_cq
911 !----------------------------------------------------------------------
913 SUBROUTINE calc_alt ( alt, al, alb, &
914 ids, ide, jds, jde, kds, kde, &
915 ims, ime, jms, jme, kms, kme, &
916 its, ite, jts, jte, kts, kte )
922 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
923 ims, ime, jms, jme, kms, kme, &
924 its, ite, jts, jte, kts, kte
926 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(IN ) :: alb, al
927 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT( OUT) :: alt
931 INTEGER :: i, j, k, itf, jtf, ktf
935 ! calc_alt computes the full inverse density
946 alt(i,k,j) = al(i,k,j)+alb(i,k,j)
952 END SUBROUTINE calc_alt
954 !----------------------------------------------------------------------
956 SUBROUTINE calc_p_rho_phi ( moist, n_moist, hypsometric_opt, &
957 al, alb, mu, muts, ph, phb, p, pb, &
958 t, p0, t0, ptop, znu, znw, dnw, rdnw, &
959 rdn, non_hydrostatic, &
960 ids, ide, jds, jde, kds, kde, &
961 ims, ime, jms, jme, kms, kme, &
962 its, ite, jts, jte, kts, kte )
968 LOGICAL , INTENT(IN ) :: non_hydrostatic
970 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
971 ims, ime, jms, jme, kms, kme, &
972 its, ite, jts, jte, kts, kte
974 INTEGER , INTENT(IN ) :: n_moist
975 INTEGER , INTENT(IN ) :: hypsometric_opt
977 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(IN ) :: alb, &
981 REAL, DIMENSION( ims:ime , kms:kme , jms:jme, n_moist ), INTENT(IN ) :: moist
983 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT( OUT) :: al, p
985 REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(INOUT) :: ph, phb
987 REAL, DIMENSION( ims:ime , jms:jme ), INTENT(IN ) :: mu, muts
989 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: znu, znw, dnw, rdnw, rdn
991 REAL, INTENT(IN ) :: t0, p0, ptop
995 INTEGER :: i, j, k, itf, jtf, ktf, ispe
996 REAL :: qvf, qtot, qf1, qf2
997 REAL, DIMENSION( its:ite) :: temp,cpovcv_v
998 REAL :: pfu, phm, pfd
1002 ! For the nonhydrostatic option, calc_p_rho_phi calculates the
1003 ! diagnostic quantities pressure and (inverse) density from the
1004 ! prognostic variables using the equation of state.
1006 ! For the hydrostatic option, calc_p_rho_phi calculates the
1007 ! diagnostic quantities (inverse) density and geopotential from the
1008 ! prognostic variables using the equation of state and the hydrostatic
1021 IF (non_hydrostatic) THEN
1023 IF (hypsometric_opt == 1) THEN
1027 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)))
1031 ELSE IF (hypsometric_opt == 2) THEN
1033 ! The relation used to get specific volume, al, is: al = -dZ/dp,
1034 ! where dp = mut * d(eta). The pressure depth, dp, is replaced with
1035 ! p*(dp/p) ~ p*LOG((p+0.5dp)/(p-0.5dp)). Difference between dp and p*dLOG(p)
1036 ! is as follows: p*dLOG(p) - dp = 1/12*(dp/p)**3 + 1/90*(dp/p)**5 + ...
1037 ! Therefore, p*dLOG(p) is always larger than dp and the difference is
1038 ! in proportion to dp/p. TKW, 02/16/2010
1043 pfu = muts(i,j)*znw(k+1)+ptop
1044 pfd = muts(i,j)*znw(k) +ptop
1045 phm = muts(i,j)*znu(k) +ptop
1046 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)
1051 CALL wrf_error_fatal ( 'calc_p_rho_phi: hypsometric_opt should be 1 or 2' )
1054 IF (n_moist >= PARAM_FIRST_SCALAR ) THEN
1059 qvf = 1.+rvovrd*moist(i,k,j,P_QV)
1060 temp(i)=(r_d*(t0+t(i,k,j))*qvf)/(p0*(al(i,k,j)+alb(i,k,j)))
1063 CALL VPOWX ( itf-its+1, temp(its), cpovcv, p(its,k,j) )
1065 ! use vector version from libmassv or from compat lib in frame/libmassv.F
1066 CALL VPOW ( p(its,k,j), temp(its), cpovcv_v(its), itf-its+1 )
1069 p(i,k,j)= p(i,k,j)*p0-pb(i,k,j)
1079 p(i,k,j)=p0*( (r_d*(t0+t(i,k,j)))/ &
1080 (p0*(al(i,k,j)+alb(i,k,j))) )**cpovcv &
1090 ! hydrostatic pressure, al, and ph1 calc; WCS, 5 sept 2001
1093 IF (n_moist >= PARAM_FIRST_SCALAR ) THEN
1101 DO ispe=PARAM_FIRST_SCALAR,n_moist
1102 qtot = qtot + moist(i,k,j,ispe)
1107 p(i,k,j) = - 0.5*(mu(i,j)+qf1*muts(i,j))/rdnw(k)/qf2
1108 qvf = 1.+rvovrd*moist(i,k,j,P_QV)
1109 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1110 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1114 DO k=ktf-1,kts,-1 ! remaining layers, integrate down
1118 DO ispe=PARAM_FIRST_SCALAR,n_moist
1119 qtot = qtot + 0.5*( moist(i,k ,j,ispe) + moist(i,k+1,j,ispe) )
1124 p(i,k,j) = p(i,k+1,j) - (mu(i,j) + qf1*muts(i,j))/qf2/rdn(k+1)
1125 qvf = 1.+rvovrd*moist(i,k,j,P_QV)
1126 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1127 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1144 p(i,k,j) = - 0.5*(mu(i,j)+qf1*muts(i,j))/rdnw(k)/qf2
1146 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1147 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1151 DO k=ktf-1,kts,-1 ! remaining layers, integrate down
1158 p(i,k,j) = p(i,k+1,j) - (mu(i,j) + qf1*muts(i,j))/qf2/rdn(k+1)
1160 al(i,k,j) = (r_d/p1000mb)*(t(i,k,j)+t0)*qvf* &
1161 (((p(i,k,j)+pb(i,k,j))/p1000mb)**cvpm) - alb(i,k,j)
1169 IF (hypsometric_opt == 1) THEN
1171 DO k=2,ktf+1 ! integrate hydrostatic equation for geopotential
1173 ph(i,k,j) = ph(i,k-1,j) - (dnw(k-1))*( &
1174 (muts(i,j))*al(i,k-1,j)+ &
1175 mu(i,j)*alb(i,k-1,j) )
1181 ! Revised hypsometric eq.: dZ=-al*p*dLOG(p), where p is dry pressure
1185 ph(i,kts,j) = phb(i,kts,j)
1190 pfu = muts(i,j)*znw(k) +ptop
1191 pfd = muts(i,j)*znw(k-1)+ptop
1192 phm = muts(i,j)*znu(k-1)+ptop
1193 ph(i,k,j) = ph(i,k-1,j) + (al(i,k-1,j)+alb(i,k-1,j))*phm*LOG(pfd/pfu)
1199 ph(i,k,j) = ph(i,k,j) - phb(i,k,j)
1208 END SUBROUTINE calc_p_rho_phi
1210 !----------------------------------------------------------------------
1212 SUBROUTINE calc_php ( php, ph, phb, &
1213 ids, ide, jds, jde, kds, kde, &
1214 ims, ime, jms, jme, kms, kme, &
1215 its, ite, jts, jte, kts, kte )
1221 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
1222 ims, ime, jms, jme, kms, kme, &
1223 its, ite, jts, jte, kts, kte
1225 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: phb, ph
1226 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT( OUT) :: php
1230 INTEGER :: i, j, k, itf, jtf, ktf
1234 ! calc_php calculates the full geopotential from the reference state
1235 ! geopotential and the perturbation geopotential (phb_ph).
1246 php(i,k,j) = 0.5*(phb(i,k,j)+phb(i,k+1,j)+ph(i,k,j)+ph(i,k+1,j))
1251 END SUBROUTINE calc_php
1253 !-------------------------------------------------------------------------------
1255 SUBROUTINE diagnose_w( ph_tend, ph_new, ph_old, w, mu, dt, &
1257 cf1, cf2, cf3, rdx, rdy, &
1259 ids, ide, jds, jde, kds, kde, &
1260 ims, ime, jms, jme, kms, kme, &
1261 its, ite, jts, jte, kts, kte )
1265 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
1266 ims, ime, jms, jme, kms, kme, &
1267 its, ite, jts, jte, kts, kte
1269 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: ph_tend, &
1276 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT( OUT) :: w
1278 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: mu, ht, msftx, msfty
1280 REAL, INTENT(IN ) :: dt, cf1, cf2, cf3, rdx, rdy
1282 INTEGER :: i, j, k, itf, jtf
1289 ! diagnose_w diagnoses the vertical velocity from the geopoential equation.
1290 ! Used with the hydrostatic option.
1298 ! Notes on map scale factors:
1299 ! Chain rule: if Z=Z(X,Y) [true at the surface] then
1300 ! dZ/dt = dZ/dX * dX/dt + dZ/dY * dY/dt, U=dX/dt, V=dY/dt
1301 ! Using capitals to denote actual values
1302 ! In mapped values, u=U, v=V, z=Z, 1/dX=mx/dx, 1/dY=my/dy
1303 ! => w = dz/dt = mx u dz/dx + my v dz/dy
1304 ! [where dz/dx is just the surface height change between x
1305 ! gridpoints, and dz/dy is the change between y gridpoints]
1306 ! [NB: cf1, cf2 and cf3 do vertical weighting of u or v values
1307 ! nearest the surface]
1309 ! Previously msft multiplied by rdy and rdx terms.
1310 ! Now msfty multiplies rdy term, and msftx multiplies msftx term
1312 w(i,1,j)= msfty(i,j)*.5*rdy*( &
1313 (ht(i,j+1)-ht(i,j )) &
1314 *(cf1*v(i,1,j+1)+cf2*v(i,2,j+1)+cf3*v(i,3,j+1)) &
1315 +(ht(i,j )-ht(i,j-1)) &
1316 *(cf1*v(i,1,j )+cf2*v(i,2,j )+cf3*v(i,3,j )) ) &
1317 +msftx(i,j)*.5*rdx*( &
1318 (ht(i+1,j)-ht(i,j )) &
1319 *(cf1*u(i+1,1,j)+cf2*u(i+1,2,j)+cf3*u(i+1,3,j)) &
1320 +(ht(i,j )-ht(i-1,j)) &
1321 *(cf1*u(i ,1,j)+cf2*u(i ,2,j)+cf3*u(i ,3,j)) )
1324 ! use geopotential equation to diagnose w
1326 ! Further notes on map scale factors
1327 ! If ph_tend contains: -mx partial d/dx(mu rho u/my)
1328 ! -mx partial d/dy(phi mu v/mx)
1329 ! -partial d/dz(phi mu w/my)
1330 ! then phi eqn is: partial d/dt(mu phi/my) = ph_tend + mu g w/my
1331 ! => w = [my/(mu*g)]*[partial d/dt(mu phi/my) - ph_tend]
1335 w(i,k,j) = msfty(i,j)*( (ph_new(i,k,j)-ph_old(i,k,j))/dt &
1336 - ph_tend(i,k,j)/mu(i,j) )/g
1343 END SUBROUTINE diagnose_w
1345 !-------------------------------------------------------------------------------
1347 SUBROUTINE rhs_ph( ph_tend, u, v, ww, &
1348 ph, ph_old, phb, w, &
1351 rdnw, cfn, cfn1, rdx, rdy, &
1352 msfux, msfuy, msfvx, &
1357 ids, ide, jds, jde, kds, kde, &
1358 ims, ime, jms, jme, kms, kme, &
1359 its, ite, jts, jte, kts, kte )
1362 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
1364 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
1365 ims, ime, jms, jme, kms, kme, &
1366 its, ite, jts, jte, kts, kte
1368 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: &
1377 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: ph_tend
1379 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: muu, muv, mut, &
1385 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw, fnm, fnp
1387 REAL, INTENT(IN ) :: cfn, cfn1, rdx, rdy
1389 LOGICAL, INTENT(IN ) :: non_hydrostatic
1393 INTEGER :: i, j, k, itf, jtf, ktf, kz, i_start, j_start
1394 REAL :: ur, ul, ub, vr, vl, vb
1395 REAL, DIMENSION(its:ite,kts:kte) :: wdwn
1397 INTEGER :: advective_order
1399 LOGICAL :: specified
1403 ! rhs_ph calculates the large-timestep tendency terms for the geopotential
1404 ! equation. These terms include the advection and "gw". The geopotential
1405 ! equation is cast in advective form, so we don't use the flux form advection
1411 if(config_flags%specified .or. config_flags%nested) specified = .true.
1413 advective_order = config_flags%h_sca_adv_order
1419 ! Notes on map scale factors (WCS, 2 march 2008)
1420 ! phi equation is: mu/my d/dt(phi) = -(1/my) mx mu u d/dx(phi)
1421 ! -(1/my) my mu v d/dy(phi)
1422 ! - omega d/d_eta(phi)
1425 ! A little further explanation...
1426 ! The tendency term we are computing here is for mu/my d/dt(phi). It is advective form
1427 ! but it is multiplied be mu/my. It will be decoupled from (mu/my) when the implicit w-phi
1428 ! solution is computed in subourine advance_w. The formulation dates from the early
1429 ! days of the mass coordinate model when we were testing both a flux and an advective formulation
1430 ! for the geopotential equation and different forms of the vertical momentum equation and the
1431 ! vertically implicit solver.
1433 ! advective form for the geopotential equation
1439 wdwn(i,k) = .5*(ww(i,k,j)+ww(i,k-1,j))*rdnw(k-1) &
1440 *(ph(i,k,j)-ph(i,k-1,j)+phb(i,k,j)-phb(i,k-1,j))
1444 ! RHS term 3 is: - omega partial d/dnu(phi)
1448 ph_tend(i,k,j) = ph_tend(i,k,j) &
1449 - (fnm(k)*wdwn(i,k+1)+fnp(k)*wdwn(i,k))
1455 IF (non_hydrostatic) THEN ! add in "gw" term.
1456 DO j = jts, jtf ! in hydrostatic mode, "gw" will be diagnosed
1457 ! after the timestep to give us "w"
1459 ph_tend(i,kde,j) = 0.
1464 ! phi equation RHS term 4
1465 ph_tend(i,k,j) = ph_tend(i,k,j) + mut(i,j)*g*w(i,k,j)/msfty(i,j)
1473 ! Notes on map scale factors:
1474 ! RHS terms 1 and 2 are: -(1/my) mx u mu partial d/dx(phi)
1475 ! -(1/my) my v mu partial d/dy(phi)
1477 IF (advective_order <= 2) THEN
1486 IF ( (config_flags%open_ys .or. specified) .and. jts == jds ) j_start = jts+1
1487 IF ( (config_flags%open_ye .or. specified) .and. jte == jde ) jtf = jtf-2
1493 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1494 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1495 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1496 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1497 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1503 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1504 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1505 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1506 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1507 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1519 IF ( (config_flags%open_xs .or. specified) .and. its == ids ) i_start = its+1
1520 IF ( (config_flags%open_xe .or. specified) .and. ite == ide ) itf = itf-2
1526 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1527 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1528 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1529 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1530 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1536 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1537 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1538 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1539 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
1540 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1545 ELSE IF (advective_order <= 4) THEN
1554 IF ( (config_flags%open_ys .or. specified) .and. jts == jds ) j_start = jts+2
1555 IF ( (config_flags%open_ye .or. specified) .and. jte == jde ) jtf = jtf-3
1561 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))*( &
1562 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1563 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j ))* (1./12.)*( &
1564 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1565 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1566 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1567 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1575 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))*( &
1576 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1577 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j ))* (1./12.)*( &
1578 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1579 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1580 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1581 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1587 ! pick up near boundary rows using 2nd order stencil for open and specified conditions
1589 IF ( (config_flags%open_ys .or. specified) .and. jts <= jds+1 ) THEN
1594 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1595 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1596 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1597 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1598 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1604 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1605 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1606 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1607 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1608 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1613 IF ( (config_flags%open_ye .or. specified) .and. jte >= jde-2 ) THEN
1618 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1619 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1620 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1621 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1622 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1628 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1629 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1630 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1631 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1632 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1644 IF ( (config_flags%open_xs) .and. its == ids ) i_start = its+2
1645 IF ( (config_flags%open_xe) .and. ite == ide ) itf = itf-3
1651 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1652 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1653 +muu(i,j )*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j) )* (1./12.)*( &
1654 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1655 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1656 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1657 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1663 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1664 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1665 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux(i ,j) )* (1./12.)*( &
1666 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1667 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1668 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1669 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1674 ! pick up near boundary rows using 2nd order stencil for open and specified conditions
1676 IF ( (config_flags%open_xs .or. specified) .and. its <= ids+1 ) THEN
1682 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1683 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1684 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1685 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1686 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1692 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1693 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1694 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1695 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
1696 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1701 IF ( (config_flags%open_xe .or. specified) .and. ite >= ide-2 ) THEN
1706 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1707 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1708 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1709 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1710 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1716 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1717 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
1718 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1719 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
1720 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1725 !--------------------------
1727 ELSE IF (advective_order <= 6) THEN
1729 !!! NOTE: this branch has been looked at and fixed with changes for overdecomposition
1730 !!! the branches covering the other advective_order cases have not. 20090923. JM
1739 IF (config_flags%open_ys .or. specified ) j_start = max(jts,jds+3)
1740 IF (config_flags%open_ye .or. specified ) jtf = min(jtf,jde-4)
1746 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* ( &
1747 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1748 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j ) )* (1./60.)*( &
1749 45.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1750 -9.*(ph(i,k,j+2)-ph(i,k,j-2)) &
1751 +(ph(i,k,j+3)-ph(i,k,j-3)) &
1752 +45.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1753 -9.*(phb(i,k,j+2)-phb(i,k,j-2)) &
1754 +(phb(i,k,j+3)-phb(i,k,j-3)) ) )
1762 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* ( &
1763 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1764 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j ) )* (1./60.)*( &
1765 45.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1766 -9.*(ph(i,k,j+2)-ph(i,k,j-2)) &
1767 +(ph(i,k,j+3)-ph(i,k,j-3)) &
1768 +45.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1769 -9.*(phb(i,k,j+2)-phb(i,k,j-2)) &
1770 +(phb(i,k,j+3)-phb(i,k,j-3)) ) )
1776 ! 4th order stencil for open or specified conditions two in form the boundary
1778 IF ( (config_flags%open_ys .or. specified) .and. jts <= jds+2 .and. jds+2 <= jte ) THEN
1783 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* ( &
1784 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1785 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j ) )* (1./12.)*( &
1786 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1787 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1788 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1789 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1797 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* ( &
1798 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1799 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j) )* (1./12.)*( &
1800 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1801 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1802 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1803 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1809 IF ( (config_flags%open_ye .or. specified) .and. jts <= jde-3 .and. jde-3 <= jte ) THEN
1813 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* ( &
1814 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1) &
1815 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j) )* (1./12.)*( &
1816 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1817 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1818 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1819 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1827 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* ( &
1828 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1) &
1829 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j) )* (1./12.)*( &
1830 8.*(ph(i,k,j+1)-ph(i,k,j-1)) &
1831 -(ph(i,k,j+2)-ph(i,k,j-2)) &
1832 +8.*(phb(i,k,j+1)-phb(i,k,j-1)) &
1833 -(phb(i,k,j+2)-phb(i,k,j-2)) ) )
1839 ! 2nd order stencil for open and specified conditions one row in from boundary
1841 IF ( (config_flags%open_ys .or. specified) .and. jts <= jds+1 .and. jds+1 <= jte ) THEN
1846 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1847 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1848 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1849 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1850 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1856 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1857 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1858 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1859 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1860 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1865 IF ( (config_flags%open_ye .or. specified) .and. jts <= jde-2 .and. jde-2 <= jte ) THEN
1870 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdy/msfty(i,j))* &
1871 ( muv(i,j+1)*(v(i,k,j+1)+v(i,k-1,j+1))*msfvy(i,j+1)* &
1872 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1873 +muv(i,j )*(v(i,k,j )+v(i,k-1,j ))*msfvy(i,j )* &
1874 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1880 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdy/msfty(i,j))* &
1881 ( muv(i,j+1)*(cfn*v(i,k-1,j+1)+cfn1*v(i,k-2,j+1))*msfvy(i,j+1)* &
1882 (phb(i,k,j+1)-phb(i,k,j )+ph(i,k,j+1)-ph(i,k,j )) &
1883 +muv(i,j )*(cfn*v(i,k-1,j )+cfn1*v(i,k-2,j ))*msfvy(i,j )* &
1884 (phb(i,k,j )-phb(i,k,j-1)+ph(i,k,j )-ph(i,k,j-1)) )
1896 IF (config_flags%open_xs .or. specified ) i_start = max(its,ids+3)
1897 IF (config_flags%open_xe .or. specified ) itf = min(itf,ide-4)
1903 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1904 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1905 +muu(i,j )*(u(i,k,j )+u(i,k-1,j ))*msfux(i,j) )* (1./60.)*( &
1906 45.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1907 -9.*(ph(i+2,k,j)-ph(i-2,k,j)) &
1908 +(ph(i+3,k,j)-ph(i-3,k,j)) &
1909 +45.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1910 -9.*(phb(i+2,k,j)-phb(i-2,k,j)) &
1911 +(phb(i+3,k,j)-phb(i-3,k,j)) ) )
1917 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1918 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1919 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i,k-2,j))*msfux(i,j) )* (1./60.)*( &
1920 45.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1921 -9.*(ph(i+2,k,j)-ph(i-2,k,j)) &
1922 +(ph(i+3,k,j)-ph(i-3,k,j)) &
1923 +45.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1924 -9.*(phb(i+2,k,j)-phb(i-2,k,j)) &
1925 +(phb(i+3,k,j)-phb(i-3,k,j)) ) )
1930 ! 4th order stencil two in from the boundary for open and specified conditions
1932 IF ( (config_flags%open_xs) .and. its <= ids+2 .and. ids+2 <= ite ) THEN
1936 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1937 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1938 +muu(i,j )*(u(i,k,j )+u(i,k-1,j ))*msfux(i,j) )* (1./12.)*( &
1939 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1940 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1941 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1942 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1945 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1946 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1947 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i,k-2,j))*msfux(i,j) )* (1./12.)*( &
1948 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1949 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1950 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1951 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1956 IF ( (config_flags%open_xe) .and. its <= ide-3 .and. ide-3 <= ite ) THEN
1960 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))*( &
1961 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j) &
1962 +muu(i,j )*(u(i,k,j )+u(i,k-1,j ))*msfux(i,j) )* (1./12.)*( &
1963 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1964 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1965 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1966 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1969 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))*( &
1970 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j) &
1971 +muu(i,j )*(cfn*u(i ,k-1,j)+cfn1*u(i,k-2,j))*msfux(i,j) )* (1./12.)*( &
1972 8.*(ph(i+1,k,j)-ph(i-1,k,j)) &
1973 -(ph(i+2,k,j)-ph(i-2,k,j)) &
1974 +8.*(phb(i+1,k,j)-phb(i-1,k,j)) &
1975 -(phb(i+2,k,j)-phb(i-2,k,j)) ) )
1980 ! 2nd order stencil for open and specified conditions one in from the boundary
1982 IF ( (config_flags%open_xs .or. specified) .and. its <= ids+1 .and. ids+1 <= ite ) THEN
1988 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
1989 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
1990 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
1991 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
1992 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
1998 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
1999 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
2000 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
2001 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
2002 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
2007 IF ( (config_flags%open_xe .or. specified) .and. its <= ide-2 .and. ide-2 <= ite ) THEN
2012 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.25*rdx/msfty(i,j))* &
2013 ( muu(i+1,j)*(u(i+1,k,j)+u(i+1,k-1,j))*msfux(i+1,j)* &
2014 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
2015 +muu(i ,j)*(u(i ,k,j)+u(i ,k-1,j))*msfux(i ,j)* &
2016 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
2022 ph_tend(i,k,j)=ph_tend(i,k,j) - (0.5*rdx/msfty(i,j))* &
2023 ( muu(i+1,j)*(cfn*u(i+1,k-1,j)+cfn1*u(i+1,k-2,j))*msfux(i+1,j)* &
2024 (phb(i+1,k,j)-phb(i ,k,j)+ph(i+1,k,j)-ph(i ,k,j)) &
2025 +muu(i ,j)*(cfn*u(i ,k-1,j)+cfn1*u(i ,k-2,j))*msfux( i,j)* &
2026 (phb(i ,k,j)-phb(i-1,k,j)+ph(i ,k,j)-ph(i-1,k,j)) )
2031 END IF ! 6th order advection
2033 ! lateral open boundary conditions,
2034 ! start with north and south (y) boundaries
2041 IF ( (config_flags%open_ys) .and. jts == jds ) THEN
2048 vb =.5*( fnm(kz)*(v(i,kz ,j+1)+v(i,kz ,j )) &
2049 +fnp(kz)*(v(i,kz-1,j+1)+v(i,kz-1,j )) )
2051 ph_tend(i,k,j)=ph_tend(i,k,j)-rdy*mut(i,j)*( &
2052 +vl*(ph_old(i,k,j+1)-ph_old(i,k,j)))
2060 IF ( (config_flags%open_ye) .and. jte == jde ) THEN
2067 vb=.5*( fnm(kz)*(v(i,kz ,j+1)+v(i,kz ,j)) &
2068 +fnp(kz)*(v(i,kz-1,j+1)+v(i,kz-1,j)) )
2070 ph_tend(i,k,j)=ph_tend(i,k,j)-rdy*mut(i,j)*( &
2071 +vr*(ph_old(i,k,j)-ph_old(i,k,j-1)))
2077 ! now the east and west (y) boundaries
2084 IF ( (config_flags%open_xs) .and. its == ids ) THEN
2091 ub =.5*( fnm(kz)*(u(i+1,kz ,j)+u(i ,kz ,j)) &
2092 +fnp(kz)*(u(i+1,kz-1,j)+u(i ,kz-1,j)) )
2094 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2095 +ul*(ph_old(i+1,k,j)-ph_old(i,k,j)))
2100 ub =.5*( fnm(kz)*(u(i+1,kz ,j)+u(i ,kz ,j)) &
2101 +fnp(kz)*(u(i+1,kz-1,j)+u(i ,kz-1,j)) )
2103 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2104 +ul*(ph_old(i+1,k,j)-ph_old(i,k,j)))
2111 IF ( (config_flags%open_xe) .and. ite == ide ) THEN
2118 ub=.5*( fnm(kz)*(u(i+1,kz ,j)+u(i,kz ,j)) &
2119 +fnp(kz)*(u(i+1,kz-1,j)+u(i,kz-1,j)) )
2121 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2122 +ur*(ph_old(i,k,j)-ph_old(i-1,k,j)))
2127 ub=.5*( fnm(kz)*(u(i+1,kz ,j)+u(i,kz ,j)) &
2128 +fnp(kz)*(u(i+1,kz-1,j)+u(i,kz-1,j)) )
2130 ph_tend(i,k,j)=ph_tend(i,k,j)-(msftx(i,j)/msfty(i,j))*rdx*mut(i,j)*( &
2131 +ur*(ph_old(i,k,j)-ph_old(i-1,k,j)))
2137 END SUBROUTINE rhs_ph
2140 !-------------------------------------------------------------------------------
2142 SUBROUTINE horizontal_pressure_gradient( ru_tend,rv_tend, &
2143 ph,alt,p,pb,al,php,cqu,cqv, &
2144 muu,muv,mu,fnm,fnp,rdnw, &
2145 cf1,cf2,cf3,rdx,rdy,msfux,msfuy,&
2146 msfvx,msfvy,msftx,msfty, &
2147 config_flags, non_hydrostatic, &
2149 ids, ide, jds, jde, kds, kde, &
2150 ims, ime, jms, jme, kms, kme, &
2151 its, ite, jts, jte, kts, kte )
2158 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2160 LOGICAL, INTENT (IN ) :: non_hydrostatic, top_lid
2162 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2163 ims, ime, jms, jme, kms, kme, &
2164 its, ite, jts, jte, kts, kte
2166 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: &
2177 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: &
2181 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: muu, muv, mu, &
2186 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw, fnm, fnp
2188 REAL, INTENT(IN ) :: rdx, rdy, cf1, cf2, cf3
2190 INTEGER :: i,j,k, itf, jtf, ktf, i_start, j_start
2191 REAL, DIMENSION( ims:ime, kms:kme ) :: dpn
2194 LOGICAL :: specified
2198 ! horizontal_pressure_gradient calculates the
2199 ! horizontal pressure gradient terms for the large-timestep tendency
2200 ! in the horizontal momentum equations (u,v).
2205 if(config_flags%specified .or. config_flags%nested) specified = .true.
2207 ! Notes on map scale factors:
2208 ! Calculates the pressure gradient terms in ADT eqns 44 and 45
2209 ! With upper rho -> 'mu', these are:
2210 ! Eqn 30: -mu*(mx/my)*(1/rho)*partial dp/dx
2211 ! Eqn 31: -mu*(my/mx)*(1/rho)*partial dp/dy
2213 ! As we are on nu, rather than height, surfaces:
2215 ! mu dp/dx = mu alpha partial dp'/dx + (nu mu partial dmubar/dx) alpha'
2216 ! + mu partial dphi'/dx + (partial dphi/dx)*(partial dp'/dnu - mu')
2218 ! mu dp/dy = mu alpha partial dp'/dy + (nu mu partial dmubar/dy) alpha'
2219 ! + mu partial dphi'/dy + (partial dphi/dy)*(partial dp'/dnu - mu')
2221 ! start with the north-south (y) pressure gradient
2228 IF ( (config_flags%open_ys .or. specified .or. &
2229 config_flags%nested .or. config_flags%polar ) .and. jts == jds ) j_start = jts+1
2230 IF ( (config_flags%open_ye .or. specified .or. &
2231 config_flags%nested .or. config_flags%polar ) .and. jte == jde ) jtf = jtf-1
2235 IF ( non_hydrostatic ) THEN
2240 dpn(i,k) = .5*( cf1*(p(i,k ,j-1)+p(i,k ,j)) &
2241 +cf2*(p(i,k+1,j-1)+p(i,k+1,j)) &
2242 +cf3*(p(i,k+2,j-1)+p(i,k+2,j)) )
2247 dpn(i,kde) = .5*( cf1*(p(i,kde-1,j-1)+p(i,kde-1,j)) &
2248 +cf2*(p(i,kde-2,j-1)+p(i,kde-2,j)) &
2249 +cf3*(p(i,kde-3,j-1)+p(i,kde-3,j)) )
2255 dpn(i,k) = .5*( fnm(k)*(p(i,k ,j-1)+p(i,k ,j)) &
2256 +fnp(k)*(p(i,k-1,j-1)+p(i,k-1,j)) )
2260 ! ADT eqn 45: -mu*(my/mx)*(1/rho)*partial dp/dy
2261 ! [alt, al are 1/rho terms; muv, mu are NOT coupled]
2264 ! Here are mu dp/dy terms 1-3
2265 dpy = (msfvy(i,j)/msfvx(i,j))*.5*rdy*muv(i,j)*( &
2266 (ph (i,k+1,j)-ph (i,k+1,j-1) + ph(i,k,j)-ph(i,k,j-1)) &
2267 +(alt(i,k ,j)+alt(i,k ,j-1))*(p (i,k,j)-p (i,k,j-1)) &
2268 +(al (i,k ,j)+al (i,k ,j-1))*(pb(i,k,j)-pb(i,k,j-1)) )
2269 ! Here is mu dp/dy term 4
2270 dpy = dpy + (msfvy(i,j)/msfvx(i,j))*rdy*(php(i,k,j)-php(i,k,j-1))* &
2271 (rdnw(k)*(dpn(i,k+1)-dpn(i,k))-.5*(mu(i,j-1)+mu(i,j)))
2272 rv_tend(i,k,j) = rv_tend(i,k,j)-cqv(i,k,j)*dpy
2278 ! ADT eqn 45: -mu*(my/mx)*(1/rho)*partial dp/dy
2279 ! [alt, al are 1/rho terms; muv, mu are NOT coupled]
2282 ! Here are mu dp/dy terms 1-3; term 4 not needed if hydrostatic
2283 dpy = (msfvy(i,j)/msfvx(i,j))*.5*rdy*muv(i,j)*( &
2284 (ph (i,k+1,j)-ph (i,k+1,j-1) + ph(i,k,j)-ph(i,k,j-1)) &
2285 +(alt(i,k ,j)+alt(i,k ,j-1))*(p (i,k,j)-p (i,k,j-1)) &
2286 +(al (i,k ,j)+al (i,k ,j-1))*(pb(i,k,j)-pb(i,k,j-1)) )
2287 rv_tend(i,k,j) = rv_tend(i,k,j)-cqv(i,k,j)*dpy
2295 ! now the east-west (x) pressure gradient
2302 IF ( (config_flags%open_xs .or. specified .or. &
2303 config_flags%nested ) .and. its == ids ) i_start = its+1
2304 IF ( (config_flags%open_xe .or. specified .or. &
2305 config_flags%nested ) .and. ite == ide ) itf = itf-1
2306 IF ( config_flags%periodic_x ) i_start = its
2307 IF ( config_flags%periodic_x ) itf=ite
2311 IF ( non_hydrostatic ) THEN
2316 dpn(i,k) = .5*( cf1*(p(i-1,k ,j)+p(i,k ,j)) &
2317 +cf2*(p(i-1,k+1,j)+p(i,k+1,j)) &
2318 +cf3*(p(i-1,k+2,j)+p(i,k+2,j)) )
2323 dpn(i,kde) = .5*( cf1*(p(i-1,kde-1,j)+p(i,kde-1,j)) &
2324 +cf2*(p(i-1,kde-2,j)+p(i,kde-2,j)) &
2325 +cf3*(p(i-1,kde-3,j)+p(i,kde-3,j)) )
2331 dpn(i,k) = .5*( fnm(k)*(p(i-1,k ,j)+p(i,k ,j)) &
2332 +fnp(k)*(p(i-1,k-1,j)+p(i,k-1,j)) )
2336 ! ADT eqn 44: -mu*(mx/my)*(1/rho)*partial dp/dx
2337 ! [alt, al are 1/rho terms; muu, mu are NOT coupled]
2340 ! Here are mu dp/dy terms 1-3
2341 dpx = (msfux(i,j)/msfuy(i,j))*.5*rdx*muu(i,j)*( &
2342 (ph (i,k+1,j)-ph (i-1,k+1,j) + ph(i,k,j)-ph(i-1,k,j)) &
2343 +(alt(i,k ,j)+alt(i-1,k ,j))*(p (i,k,j)-p (i-1,k,j)) &
2344 +(al (i,k ,j)+al (i-1,k ,j))*(pb(i,k,j)-pb(i-1,k,j)) )
2345 ! Here is mu dp/dy term 4
2346 dpx = dpx + (msfux(i,j)/msfuy(i,j))*rdx*(php(i,k,j)-php(i-1,k,j))* &
2347 (rdnw(k)*(dpn(i,k+1)-dpn(i,k))-.5*(mu(i-1,j)+mu(i,j)))
2348 ru_tend(i,k,j) = ru_tend(i,k,j)-cqu(i,k,j)*dpx
2354 ! ADT eqn 44: -mu*(mx/my)*(1/rho)*partial dp/dx
2355 ! [alt, al are 1/rho terms; muu, mu are NOT coupled]
2358 ! Here are mu dp/dy terms 1-3; term 4 not needed if hydrostatic
2359 dpx = (msfux(i,j)/msfuy(i,j))*.5*rdx*muu(i,j)*( &
2360 (ph (i,k+1,j)-ph (i-1,k+1,j) + ph(i,k,j)-ph(i-1,k,j)) &
2361 +(alt(i,k ,j)+alt(i-1,k ,j))*(p (i,k,j)-p (i-1,k,j)) &
2362 +(al (i,k ,j)+al (i-1,k ,j))*(pb(i,k,j)-pb(i-1,k,j)) )
2363 ru_tend(i,k,j) = ru_tend(i,k,j)-cqu(i,k,j)*dpx
2371 END SUBROUTINE horizontal_pressure_gradient
2373 !-------------------------------------------------------------------------------
2375 SUBROUTINE pg_buoy_w( rw_tend, p, cqw, mu, mub, &
2376 rdnw, rdn, g, msftx, msfty, &
2377 ids, ide, jds, jde, kds, kde, &
2378 ims, ime, jms, jme, kms, kme, &
2379 its, ite, jts, jte, kts, kte )
2385 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2386 ims, ime, jms, jme, kms, kme, &
2387 its, ite, jts, jte, kts, kte
2389 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: p
2390 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: cqw
2393 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: rw_tend
2395 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: mub, mu, msftx, msfty
2397 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw, rdn
2399 REAL, INTENT(IN ) :: g
2401 INTEGER :: itf, jtf, i, j, k
2407 ! pg_buoy_w calculates the
2408 ! vertical pressure gradient and buoyancy terms for the large-timestep
2409 ! tendency in the vertical momentum equation.
2413 ! BUOYANCY AND PRESSURE GRADIENT TERM IN W EQUATION AT TIME T
2415 ! Map scale factor notes
2416 ! ADT eqn 46 RHS terms 6 and 7 (where 7 is "-rho g")
2417 ! Dividing by my, and using mu and nu (see Klemp et al. eqns 32, 40)
2418 ! term 6: +(g/my) partial dp'/dnu
2419 ! term 7: -(g/my) mu'
2421 ! For moisture-free atmosphere, cq1=1, cq2=0
2422 ! => (1./msft(i,j)) * g * [rdn(k)*{p(i,k,j)-p(i,k-1,j)}-mu(i,j)]
2431 cq1 = 1./(1.+cqw(i,k-1,j))
2432 cq2 = cqw(i,k-1,j)*cq1
2433 rw_tend(i,k,j) = rw_tend(i,k,j)+(1./msfty(i,j))*g*( &
2434 cq1*2.*rdnw(k-1)*( -p(i,k-1,j)) &
2435 -mu(i,j)-cq2*mub(i,j) )
2440 cq1 = 1./(1.+cqw(i,k,j))
2441 cq2 = cqw(i,k,j)*cq1
2443 rw_tend(i,k,j) = rw_tend(i,k,j)+(1./msfty(i,j))*g*( &
2444 cq1*rdn(k)*(p(i,k,j)-p(i,k-1,j)) &
2445 -mu(i,j)-cq2*mub(i,j) )
2452 END SUBROUTINE pg_buoy_w
2454 !-------------------------------------------------------------------------------
2456 SUBROUTINE w_damp( rw_tend, max_vert_cfl,max_horiz_cfl, &
2457 u, v, ww, w, mut, rdnw, &
2458 rdx, rdy, msfux, msfuy, &
2461 ids, ide, jds, jde, kds, kde, &
2462 ims, ime, jms, jme, kms, kme, &
2463 its, ite, jts, jte, kts, kte )
2470 TYPE(grid_config_rec_type ) , INTENT(IN ) :: config_flags
2472 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2473 ims, ime, jms, jme, kms, kme, &
2474 its, ite, jts, jte, kts, kte
2476 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(IN ) :: u, v, ww, w
2478 REAL, DIMENSION( ims:ime, kms:kme , jms:jme ), INTENT(INOUT) :: rw_tend
2480 REAL, INTENT(OUT) :: max_vert_cfl
2481 REAL, INTENT(OUT) :: max_horiz_cfl
2484 REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: mut
2486 REAL, DIMENSION( kms:kme ), INTENT(IN ) :: rdnw
2488 REAL, INTENT(IN) :: dt
2489 REAL, INTENT(IN) :: rdx, rdy
2490 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, msfuy
2491 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfvx, msfvy
2493 REAL :: vert_cfl, cf_n, cf_d, maxdub, maxdeta
2495 INTEGER :: itf, jtf, i, j, k, maxi, maxj, maxk
2497 CHARACTER*512 :: temp
2499 CHARACTER (LEN=256) :: time_str
2500 CHARACTER (LEN=256) :: grid_str
2503 REAL :: msfuxt , msfxffl
2507 ! w_damp computes a damping term for the vertical velocity when the
2508 ! vertical Courant number is too large. This was found to be preferable to
2509 ! decreasing the timestep or increasing the diffusion in real-data applications
2510 ! that produced potentially-unstable large vertical velocities because of
2511 ! unphysically large heating rates coming from the cumulus parameterization
2512 ! schemes run at moderately high resolutions (dx ~ O(10) km).
2514 ! Additionally, w_damp returns the maximum cfl values due to vertical motion and
2515 ! horizontal motion. These values are returned via the max_vert_cfl and
2516 ! max_horiz_cfl variables. (Added by T. Hutchinson, WSI, 3/5/2007)
2528 IF(config_flags%map_proj == PROJ_CASSINI ) then
2529 msfxffl = 1.0/COS(config_flags%fft_filter_lat*degrad)
2532 IF ( config_flags%w_damping == 1 ) THEN
2538 IF(config_flags%map_proj == PROJ_CASSINI ) then
2539 msfuxt = MIN(msfux(i,j), msfxffl)
2543 vert_cfl = abs(ww(i,k,j)/mut(i,j)*rdnw(k)*dt)
2545 IF ( vert_cfl > max_vert_cfl ) THEN
2546 max_vert_cfl = vert_cfl ; maxi = i ; maxj = j ; maxk = k
2547 maxdub = w(i,k,j) ; maxdeta = -1./rdnw(k)
2550 horiz_cfl = max( abs(u(i,k,j) * rdx * msfuxt * dt), &
2551 abs(v(i,k,j) * rdy * msfvy(i,j) * dt) )
2552 if (horiz_cfl > max_horiz_cfl) then
2553 max_horiz_cfl = horiz_cfl
2556 if(vert_cfl .gt. w_beta)then
2558 ! restructure to get rid of divide
2560 ! This had been used for efficiency, but with the addition of returning the cfl values,
2561 ! the old version (above) was reinstated. (T. Hutchinson, 3/5/2007)
2563 cf_n = abs(ww(i,k,j)*rdnw(k)*dt)
2564 cf_d = abs(mut(i,j))
2565 if(cf_n .gt. cf_d*w_beta )then
2568 WRITE(temp,*)i,j,k,' vert_cfl,w,d(eta)=',vert_cfl,w(i,k,j),-1./rdnw(k)
2569 CALL wrf_debug ( 100 , TRIM(temp) )
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 WRITE(temp,*)i,j,k,' vert_cfl,w,d(eta)=',vert_cfl,w(i,k,j),-1./rdnw(k)
2615 CALL wrf_debug ( 100 , TRIM(temp) )
2616 if ( vert_cfl > 2. ) some = some + 1
2622 IF ( some .GT. 0 ) THEN
2623 CALL get_current_time_string( time_str )
2624 CALL get_current_grid_name( grid_str )
2625 WRITE(temp,*)some, &
2626 ' points exceeded cfl=2 in domain '//TRIM(grid_str)//' at time '//TRIM(time_str)//' hours'
2627 CALL wrf_debug ( 0 , TRIM(temp) )
2628 WRITE(temp,*)'MAX AT i,j,k: ',maxi,maxj,maxk,' vert_cfl,w,d(eta)=',max_vert_cfl, &
2630 CALL wrf_debug ( 0 , TRIM(temp) )
2633 END SUBROUTINE w_damp
2635 !-------------------------------------------------------------------------------
2637 SUBROUTINE horizontal_diffusion ( name, field, tendency, mu, &
2639 msfux, msfuy, msfvx, msfvx_inv, &
2640 msfvy, msftx, msfty, &
2641 khdif, xkmhd, rdx, rdy, &
2642 ids, ide, jds, jde, kds, kde, &
2643 ims, ime, jms, jme, kms, kme, &
2644 its, ite, jts, jte, kts, kte )
2650 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2652 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2653 ims, ime, jms, jme, kms, kme, &
2654 its, ite, jts, jte, kts, kte
2656 CHARACTER(LEN=1) , INTENT(IN ) :: name
2658 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: field, xkmhd
2660 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
2662 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu
2664 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
2672 REAL , INTENT(IN ) :: rdx, &
2678 INTEGER :: i, j, k, itf, jtf, ktf
2680 INTEGER :: i_start, i_end, j_start, j_end
2682 REAL :: mrdx, mkrdxm, mkrdxp, &
2683 mrdy, mkrdym, mkrdyp
2685 LOGICAL :: specified
2689 ! horizontal_diffusion computes the horizontal diffusion tendency
2690 ! on model horizontal coordinate surfaces.
2695 if(config_flags%specified .or. config_flags%nested) specified = .true.
2699 IF (name .EQ. 'u') THEN
2704 j_end = MIN(jte,jde-1)
2706 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2707 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-1,ite)
2708 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2709 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2710 IF ( config_flags%periodic_x ) i_start = its
2711 IF ( config_flags%periodic_x ) i_end = ite
2714 DO j = j_start, j_end
2716 DO i = i_start, i_end
2718 ! The interior is grad: (m_x*d/dx), the exterior is div: (m_x*m_y*d/dx(/m_y))
2719 ! setting up different averagings of m^2 partial d/dX and m^2 partial d/dY
2721 mkrdxm=(msftx(i-1,j)/msfty(i-1,j))*mu(i-1,j)*xkmhd(i-1,k,j)*rdx
2722 mkrdxp=(msftx(i,j)/msfty(i,j))*mu(i,j)*xkmhd(i,k,j)*rdx
2723 mrdx=msfux(i,j)*msfuy(i,j)*rdx
2724 mkrdym=( (msfuy(i,j)+msfuy(i,j-1))/(msfux(i,j)+msfux(i,j-1)) )* &
2725 0.25*(mu(i,j)+mu(i,j-1)+mu(i-1,j-1)+mu(i-1,j))* &
2726 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i-1,k,j-1)+xkmhd(i-1,k,j))*rdy
2727 mkrdyp=( (msfuy(i,j)+msfuy(i,j+1))/(msfux(i,j)+msfux(i,j+1)) )* &
2728 0.25*(mu(i,j)+mu(i,j+1)+mu(i-1,j+1)+mu(i-1,j))* &
2729 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j+1)+xkmhd(i-1,k,j+1)+xkmhd(i-1,k,j))*rdy
2730 ! need to do four-corners (t) for diffusion coefficient as there are
2731 ! no values at u,v points
2732 ! msfuy - has to be y as part of d/dY
2733 ! has to be u as we're at a u point
2734 mrdy=msfux(i,j)*msfuy(i,j)*rdy
2736 ! correctly averaged version of rho~ * m^2 *
2737 ! [partial d/dX(partial du^/dX) + partial d/dY(partial du^/dY)]
2738 tendency(i,k,j)=tendency(i,k,j)+( &
2739 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2740 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2741 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2742 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2747 ELSE IF (name .EQ. 'v')THEN
2750 i_end = MIN(ite,ide-1)
2754 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2755 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2756 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2757 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-1,jte)
2758 IF ( config_flags%periodic_x ) i_start = its
2759 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2760 IF ( config_flags%polar ) j_start = MAX(jds+1,jts)
2761 IF ( config_flags%polar ) j_end = MIN(jde-1,jte)
2763 DO j = j_start, j_end
2765 DO i = i_start, i_end
2767 mkrdxm=( (msfvx(i,j)+msfvx(i-1,j))/(msfvy(i,j)+msfvy(i-1,j)) )* &
2768 0.25*(mu(i,j)+mu(i,j-1)+mu(i-1,j-1)+mu(i-1,j))* &
2769 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i-1,k,j-1)+xkmhd(i-1,k,j))*rdx
2770 mkrdxp=( (msfvx(i,j)+msfvx(i+1,j))/(msfvy(i,j)+msfvy(i+1,j)) )* &
2771 0.25*(mu(i,j)+mu(i,j-1)+mu(i+1,j-1)+mu(i+1,j))* &
2772 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i+1,k,j-1)+xkmhd(i+1,k,j))*rdx
2773 mrdx=msfvx(i,j)*msfvy(i,j)*rdx
2774 mkrdym=(msfty(i,j-1)/msftx(i,j-1))*xkmhd(i,k,j-1)*rdy
2775 mkrdyp=(msfty(i,j)/msftx(i,j))*xkmhd(i,k,j)*rdy
2776 mrdy=msfvx(i,j)*msfvy(i,j)*rdy
2778 tendency(i,k,j)=tendency(i,k,j)+( &
2779 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2780 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2781 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2782 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2787 ELSE IF (name .EQ. 'w')THEN
2790 i_end = MIN(ite,ide-1)
2792 j_end = MIN(jte,jde-1)
2794 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2795 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2796 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2797 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2798 IF ( config_flags%periodic_x ) i_start = its
2799 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2801 DO j = j_start, j_end
2803 DO i = i_start, i_end
2805 mkrdxm=(msfux(i,j)/msfuy(i,j))* &
2806 0.25*(mu(i,j)+mu(i-1,j)+mu(i,j)+mu(i-1,j))* &
2807 0.25*(xkmhd(i,k,j)+xkmhd(i-1,k,j)+xkmhd(i,k-1,j)+xkmhd(i-1,k-1,j))*rdx
2808 mkrdxp=(msfux(i+1,j)/msfuy(i+1,j))* &
2809 0.25*(mu(i+1,j)+mu(i,j)+mu(i+1,j)+mu(i,j))* &
2810 0.25*(xkmhd(i+1,k,j)+xkmhd(i,k,j)+xkmhd(i+1,k-1,j)+xkmhd(i,k-1,j))*rdx
2811 mrdx=msftx(i,j)*msfty(i,j)*rdx
2812 ! mkrdym=(msfvy(i,j)/msfvx(i,j))* &
2813 mkrdym=(msfvy(i,j)*msfvx_inv(i,j))* &
2814 0.25*(mu(i,j)+mu(i,j-1)+mu(i,j)+mu(i,j-1))* &
2815 0.25*(xkmhd(i,k,j)+xkmhd(i,k,j-1)+xkmhd(i,k-1,j)+xkmhd(i,k-1,j-1))*rdy
2816 ! mkrdyp=(msfvy(i,j+1)/msfvx(i,j+1))* &
2817 mkrdyp=(msfvy(i,j+1)*msfvx_inv(i,j+1))* &
2818 0.25*(mu(i,j+1)+mu(i,j)+mu(i,j+1)+mu(i,j))* &
2819 0.25*(xkmhd(i,k,j+1)+xkmhd(i,k,j)+xkmhd(i,k-1,j+1)+xkmhd(i,k-1,j))*rdy
2820 mrdy=msftx(i,j)*msfty(i,j)*rdy
2822 tendency(i,k,j)=tendency(i,k,j)+( &
2823 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2824 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2825 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2826 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2835 i_end = MIN(ite,ide-1)
2837 j_end = MIN(jte,jde-1)
2839 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2840 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2841 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2842 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2843 IF ( config_flags%periodic_x ) i_start = its
2844 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2846 DO j = j_start, j_end
2848 DO i = i_start, i_end
2850 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
2851 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
2852 mrdx=msftx(i,j)*msfty(i,j)*rdx
2853 ! 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
2854 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
2855 ! 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
2856 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
2857 mrdy=msftx(i,j)*msfty(i,j)*rdy
2859 tendency(i,k,j)=tendency(i,k,j)+( &
2860 mrdx*(mkrdxp*(field(i+1,k,j)-field(i ,k,j)) &
2861 -mkrdxm*(field(i ,k,j)-field(i-1,k,j))) &
2862 +mrdy*(mkrdyp*(field(i,k,j+1)-field(i,k,j )) &
2863 -mkrdym*(field(i,k,j )-field(i,k,j-1))))
2870 END SUBROUTINE horizontal_diffusion
2872 !-----------------------------------------------------------------------------------------
2874 SUBROUTINE horizontal_diffusion_3dmp ( name, field, tendency, mu, &
2875 config_flags, base_3d, &
2876 msfux, msfuy, msfvx, msfvx_inv, &
2877 msfvy, msftx, msfty, &
2878 khdif, xkmhd, rdx, rdy, &
2879 ids, ide, jds, jde, kds, kde, &
2880 ims, ime, jms, jme, kms, kme, &
2881 its, ite, jts, jte, kts, kte )
2887 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2889 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2890 ims, ime, jms, jme, kms, kme, &
2891 its, ite, jts, jte, kts, kte
2893 CHARACTER(LEN=1) , INTENT(IN ) :: name
2895 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: field, &
2899 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
2901 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mu
2903 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
2911 REAL , INTENT(IN ) :: rdx, &
2917 INTEGER :: i, j, k, itf, jtf, ktf
2919 INTEGER :: i_start, i_end, j_start, j_end
2921 REAL :: mrdx, mkrdxm, mkrdxp, &
2922 mrdy, mkrdym, mkrdyp
2924 LOGICAL :: specified
2928 ! horizontal_diffusion_3dmp computes the horizontal diffusion tendency
2929 ! on model horizontal coordinate surfaces. This routine computes diffusion
2930 ! a perturbation scalar (field-base_3d).
2935 if(config_flags%specified .or. config_flags%nested) specified = .true.
2940 i_end = MIN(ite,ide-1)
2942 j_end = MIN(jte,jde-1)
2944 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
2945 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-2,ite)
2946 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
2947 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-2,jte)
2948 IF ( config_flags%periodic_x ) i_start = its
2949 IF ( config_flags%periodic_x ) i_end = MIN(ite,ide-1)
2951 DO j = j_start, j_end
2953 DO i = i_start, i_end
2955 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
2956 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
2957 mrdx=msftx(i,j)*msfty(i,j)*rdx
2958 ! 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
2959 ! 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
2960 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
2961 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
2962 mrdy=msftx(i,j)*msfty(i,j)*rdy
2964 tendency(i,k,j)=tendency(i,k,j)+( &
2965 mrdx*( mkrdxp*( field(i+1,k,j) -field(i ,k,j) &
2966 -base_3d(i+1,k,j)+base_3d(i ,k,j) ) &
2967 -mkrdxm*( field(i ,k,j) -field(i-1,k,j) &
2968 -base_3d(i ,k,j)+base_3d(i-1,k,j) ) ) &
2969 +mrdy*( mkrdyp*( field(i,k,j+1) -field(i,k,j ) &
2970 -base_3d(i,k,j+1)+base_3d(i,k,j ) ) &
2971 -mkrdym*( field(i,k,j ) -field(i,k,j-1) &
2972 -base_3d(i,k,j )+base_3d(i,k,j-1) ) ) &
2978 END SUBROUTINE horizontal_diffusion_3dmp
2980 !-----------------------------------------------------------------------------------------
2982 SUBROUTINE vertical_diffusion ( name, field, tendency, &
2984 alt, mut, rdn, rdnw, kvdif, &
2985 ids, ide, jds, jde, kds, kde, &
2986 ims, ime, jms, jme, kms, kme, &
2987 its, ite, jts, jte, kts, kte )
2994 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
2996 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
2997 ims, ime, jms, jme, kms, kme, &
2998 its, ite, jts, jte, kts, kte
3000 CHARACTER(LEN=1) , INTENT(IN ) :: name
3002 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3003 INTENT(IN ) :: field, &
3006 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3008 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mut
3010 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, rdnw
3012 REAL , INTENT(IN ) :: kvdif
3016 INTEGER :: i, j, k, itf, jtf, ktf
3017 INTEGER :: i_start, i_end, j_start, j_end
3019 REAL , DIMENSION(its:ite, jts:jte) :: vfluxm, vfluxp, zz
3020 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3024 LOGICAL :: specified
3028 ! vertical_diffusion
3029 ! computes vertical diffusion tendency.
3034 if(config_flags%specified .or. config_flags%nested) specified = .true.
3038 IF (name .EQ. 'w')THEN
3042 i_end = MIN(ite,ide-1)
3044 j_end = MIN(jte,jde-1)
3046 j_loop_w : DO j = j_start, j_end
3049 DO i = i_start, i_end
3050 vflux(i,k)= (kvdif/alt(i,k,j))*rdnw(k)*(field(i,k+1,j)-field(i,k,j))
3054 DO i = i_start, i_end
3059 DO i = i_start, i_end
3060 tendency(i,k,j)=tendency(i,k,j) &
3061 +rdn(k)*g*g/mut(i,j)/(0.5*(alt(i,k,j)+alt(i,k-1,j))) &
3062 *(vflux(i,k)-vflux(i,k-1))
3068 ELSE IF(name .EQ. 'm')THEN
3071 i_end = MIN(ite,ide-1)
3073 j_end = MIN(jte,jde-1)
3075 j_loop_s : DO j = j_start, j_end
3078 DO i = i_start, i_end
3079 vflux(i,k)=kvdif*rdn(k+1)/(0.5*(alt(i,k,j)+alt(i,k+1,j))) &
3080 *(field(i,k+1,j)-field(i,k,j))
3084 DO i = i_start, i_end
3085 vflux(i,0)=vflux(i,1)
3088 DO i = i_start, i_end
3093 DO i = i_start, i_end
3094 tendency(i,k,j)=tendency(i,k,j)+g*g/mut(i,j)/alt(i,k,j) &
3095 *rdnw(k)*(vflux(i,k)-vflux(i,k-1))
3103 END SUBROUTINE vertical_diffusion
3106 !-------------------------------------------------------------------------------
3108 SUBROUTINE vertical_diffusion_mp ( field, tendency, config_flags, &
3110 alt, mut, rdn, rdnw, kvdif, &
3111 ids, ide, jds, jde, kds, kde, &
3112 ims, ime, jms, jme, kms, kme, &
3113 its, ite, jts, jte, kts, kte )
3120 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3122 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3123 ims, ime, jms, jme, kms, kme, &
3124 its, ite, jts, jte, kts, kte
3126 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3127 INTENT(IN ) :: field, &
3130 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3132 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mut
3134 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, &
3138 REAL , INTENT(IN ) :: kvdif
3142 INTEGER :: i, j, k, itf, jtf, ktf
3143 INTEGER :: i_start, i_end, j_start, j_end
3145 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3149 LOGICAL :: specified
3153 ! vertical_diffusion_mp
3154 ! computes vertical diffusion tendency of a perturbation variable
3155 ! (field-base). Note that base as a 1D (k) field.
3160 if(config_flags%specified .or. config_flags%nested) specified = .true.
3165 i_end = MIN(ite,ide-1)
3167 j_end = MIN(jte,jde-1)
3169 j_loop_s : DO j = j_start, j_end
3172 DO i = i_start, i_end
3173 vflux(i,k)=kvdif*rdn(k+1)/(0.5*(alt(i,k,j)+alt(i,k+1,j))) &
3174 *(field(i,k+1,j)-field(i,k,j)-base(k+1)+base(k))
3178 DO i = i_start, i_end
3179 vflux(i,0)=vflux(i,1)
3182 DO i = i_start, i_end
3187 DO i = i_start, i_end
3188 tendency(i,k,j)=tendency(i,k,j)+g*g/mut(i,j)/alt(i,k,j) &
3189 *rdnw(k)*(vflux(i,k)-vflux(i,k-1))
3195 END SUBROUTINE vertical_diffusion_mp
3198 !-------------------------------------------------------------------------------
3200 SUBROUTINE vertical_diffusion_3dmp ( field, tendency, config_flags, &
3202 alt, mut, rdn, rdnw, kvdif, &
3203 ids, ide, jds, jde, kds, kde, &
3204 ims, ime, jms, jme, kms, kme, &
3205 its, ite, jts, jte, kts, kte )
3212 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3214 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3215 ims, ime, jms, jme, kms, kme, &
3216 its, ite, jts, jte, kts, kte
3218 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3219 INTENT(IN ) :: field, &
3223 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3225 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: mut
3227 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, &
3230 REAL , INTENT(IN ) :: kvdif
3234 INTEGER :: i, j, k, itf, jtf, ktf
3235 INTEGER :: i_start, i_end, j_start, j_end
3237 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3241 LOGICAL :: specified
3245 ! vertical_diffusion_3dmp
3246 ! computes vertical diffusion tendency of a perturbation variable
3252 if(config_flags%specified .or. config_flags%nested) specified = .true.
3257 i_end = MIN(ite,ide-1)
3259 j_end = MIN(jte,jde-1)
3261 j_loop_s : DO j = j_start, j_end
3264 DO i = i_start, i_end
3265 vflux(i,k)=kvdif*rdn(k+1)/(0.5*(alt(i,k,j)+alt(i,k+1,j))) &
3266 *( field(i,k+1,j) -field(i,k,j) &
3267 -base_3d(i,k+1,j)+base_3d(i,k,j) )
3271 DO i = i_start, i_end
3272 vflux(i,0)=vflux(i,1)
3275 DO i = i_start, i_end
3280 DO i = i_start, i_end
3281 tendency(i,k,j)=tendency(i,k,j)+g*g/mut(i,j)/alt(i,k,j) &
3282 *rdnw(k)*(vflux(i,k)-vflux(i,k-1))
3288 END SUBROUTINE vertical_diffusion_3dmp
3291 !-------------------------------------------------------------------------------
3294 SUBROUTINE vertical_diffusion_u ( field, tendency, &
3295 config_flags, u_base, &
3296 alt, muu, rdn, rdnw, kvdif, &
3297 ids, ide, jds, jde, kds, kde, &
3298 ims, ime, jms, jme, kms, kme, &
3299 its, ite, jts, jte, kts, kte )
3306 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3308 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3309 ims, ime, jms, jme, kms, kme, &
3310 its, ite, jts, jte, kts, kte
3312 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3313 INTENT(IN ) :: field, &
3316 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3318 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muu
3320 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, rdnw, u_base
3322 REAL , INTENT(IN ) :: kvdif
3326 INTEGER :: i, j, k, itf, jtf, ktf
3327 INTEGER :: i_start, i_end, j_start, j_end
3329 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3333 LOGICAL :: specified
3337 ! vertical_diffusion_u computes vertical diffusion tendency for
3338 ! the u momentum equation. This routine assumes a constant eddy
3344 if(config_flags%specified .or. config_flags%nested) specified = .true.
3351 j_end = MIN(jte,jde-1)
3353 IF ( config_flags%open_xs .or. specified ) i_start = MAX(ids+1,its)
3354 IF ( config_flags%open_xe .or. specified ) i_end = MIN(ide-1,ite)
3355 IF ( config_flags%periodic_x ) i_start = its
3356 IF ( config_flags%periodic_x ) i_end = ite
3359 j_loop_u : DO j = j_start, j_end
3362 DO i = i_start, i_end
3363 vflux(i,k)=kvdif*rdn(k+1)/(0.25*( alt(i ,k ,j) &
3366 +alt(i-1,k+1,j) ) ) &
3367 *(field(i,k+1,j)-field(i,k,j) &
3368 -u_base(k+1) +u_base(k) )
3372 DO i = i_start, i_end
3373 vflux(i,0)=vflux(i,1)
3376 DO i = i_start, i_end
3381 DO i = i_start, i_end
3382 tendency(i,k,j)=tendency(i,k,j)+ &
3383 g*g*rdnw(k)/muu(i,j)/(0.5*(alt(i-1,k,j)+alt(i,k,j)))* &
3384 (vflux(i,k)-vflux(i,k-1))
3390 END SUBROUTINE vertical_diffusion_u
3392 !-------------------------------------------------------------------------------
3395 SUBROUTINE vertical_diffusion_v ( field, tendency, &
3396 config_flags, v_base, &
3397 alt, muv, rdn, rdnw, kvdif, &
3398 ids, ide, jds, jde, kds, kde, &
3399 ims, ime, jms, jme, kms, kme, &
3400 its, ite, jts, jte, kts, kte )
3407 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
3409 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3410 ims, ime, jms, jme, kms, kme, &
3411 its, ite, jts, jte, kts, kte
3413 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
3414 INTENT(IN ) :: field, &
3416 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: rdn, rdnw, v_base
3418 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
3420 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muv
3422 REAL , INTENT(IN ) :: kvdif
3426 INTEGER :: i, j, k, itf, jtf, ktf, jm1
3427 INTEGER :: i_start, i_end, j_start, j_end
3429 REAL , DIMENSION(its:ite, 0:kte+1) :: vflux
3433 LOGICAL :: specified
3437 ! vertical_diffusion_v computes vertical diffusion tendency for
3438 ! the v momentum equation. This routine assumes a constant eddy
3444 if(config_flags%specified .or. config_flags%nested) specified = .true.
3449 i_end = MIN(ite,ide-1)
3451 j_end = MIN(jte,jde-1)
3453 IF ( config_flags%open_ys .or. specified ) j_start = MAX(jds+1,jts)
3454 IF ( config_flags%open_ye .or. specified ) j_end = MIN(jde-1,jte)
3456 j_loop_v : DO j = j_start, j_end
3461 DO i = i_start, i_end
3462 vflux(i,k)=kvdif*rdn(k+1)/(0.25*( alt(i,k ,j ) &
3465 +alt(i,k+1,jm1) ) ) &
3466 *(field(i,k+1,j)-field(i,k,j) &
3467 -v_base(k+1) +v_base(k) )
3471 DO i = i_start, i_end
3472 vflux(i,0)=vflux(i,1)
3475 DO i = i_start, i_end
3480 DO i = i_start, i_end
3481 tendency(i,k,j)=tendency(i,k,j)+ &
3482 g*g*rdnw(k)/muv(i,j)/(0.5*(alt(i,k,jm1)+alt(i,k,j)))* &
3483 (vflux(i,k)-vflux(i,k-1))
3489 END SUBROUTINE vertical_diffusion_v
3491 !*************** end new mass coordinate routines
3493 !-------------------------------------------------------------------------------
3495 SUBROUTINE calculate_full ( rfield, rfieldb, rfieldp, &
3496 ids, ide, jds, jde, kds, kde, &
3497 ims, ime, jms, jme, kms, kme, &
3498 its, ite, jts, jte, kts, kte )
3504 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3505 ims, ime, jms, jme, kms, kme, &
3506 its, ite, jts, jte, kts, kte
3508 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: rfieldb, &
3511 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT ) :: rfield
3515 INTEGER :: i, j, k, itf, jtf, ktf
3520 ! calculates full 3D field from pertubation and base field.
3531 rfield(i,k,j)=rfieldb(i,k,j)+rfieldp(i,k,j)
3536 END SUBROUTINE calculate_full
3538 !------------------------------------------------------------------------------
3540 SUBROUTINE coriolis ( ru, rv, rw, ru_tend, rv_tend, rw_tend, &
3542 msftx, msfty, msfux, msfuy, &
3544 f, e, sina, cosa, fzm, fzp, &
3545 ids, ide, jds, jde, kds, kde, &
3546 ims, ime, jms, jme, kms, kme, &
3547 its, ite, jts, jte, kts, kte )
3553 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
3555 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3556 ims, ime, jms, jme, kms, kme, &
3557 its, ite, jts, jte, kts, kte
3559 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: ru_tend, &
3562 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: ru, &
3566 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
3573 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: f, &
3578 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
3583 INTEGER :: i, j , k, ktf
3584 INTEGER :: i_start, i_end, j_start, j_end
3586 LOGICAL :: specified
3590 ! coriolis calculates the large timestep tendency terms in the
3591 ! u, v, and w momentum equations arise from the coriolis force.
3596 if(config_flags%specified .or. config_flags%nested) specified = .true.
3600 ! coriolis for u-momentum equation
3602 ! Notes on map scale factor
3603 ! cosa, sina are related to rotating the coordinate frame if desired
3604 ! generally sina=0, cosa=1
3605 ! ADT eqn 44, RHS terms 6 and 7: -2 mu w omega cos(lat)/my
3606 ! + 2 mu v omega sin(lat)/my
3607 ! Define f=2 omega sin(lat), e=2 omega cos(lat)
3608 ! => terms are: -e mu w / my + f mu v / my
3609 ! rv = mu v / mx ; rw = mu w / my
3610 ! => terms are: -e rw + f rv *mx / my
3614 IF ( config_flags%open_xs .or. specified .or. &
3615 config_flags%nested) i_start = MAX(ids+1,its)
3616 IF ( config_flags%open_xe .or. specified .or. &
3617 config_flags%nested) i_end = MIN(ide-1,ite)
3618 IF ( config_flags%periodic_x ) i_start = its
3619 IF ( config_flags%periodic_x ) i_end = ite
3621 DO j = jts, MIN(jte,jde-1)
3624 DO i = i_start, i_end
3626 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)) &
3627 *0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+rv(i-1,k,j)+rv(i,k,j)) &
3628 - 0.5*(e(i,j)+e(i-1,j))*0.5*(cosa(i,j)+cosa(i-1,j)) &
3629 *0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j))
3634 ! boundary loops for coriolis not needed for open bdy (commented out 20100611 JD)
3635 ! IF ( (config_flags%open_xs) .and. (its == ids) ) THEN
3639 ! ru_tend(its,k,j)=ru_tend(its,k,j) + (msfux(its,j)/msfuy(its,j))*0.5*(f(its,j)+f(its,j)) &
3640 ! *0.25*(rv(its,k,j+1)+rv(its,k,j+1)+rv(its,k,j)+rv(its,k,j)) &
3641 ! - 0.5*(e(its,j)+e(its,j))*0.5*(cosa(its,j)+cosa(its,j)) &
3642 ! *0.25*(rw(its,k+1,j)+rw(its,k,j)+rw(its,k+1,j)+rw(its,k,j))
3648 ! IF ( (config_flags%open_xe) .and. (ite == ide) ) THEN
3652 ! 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)) &
3653 ! *0.25*(rv(ite-1,k,j+1)+rv(ite-1,k,j+1)+rv(ite-1,k,j)+rv(ite-1,k,j)) &
3654 ! - 0.5*(e(ite-1,j)+e(ite-1,j))*0.5*(cosa(ite-1,j)+cosa(ite-1,j)) &
3655 ! *0.25*(rw(ite-1,k+1,j)+rw(ite-1,k,j)+rw(ite-1,k+1,j)+rw(ite-1,k,j))
3663 ! coriolis term for v-momentum equation
3665 ! Notes on map scale factors
3666 ! ADT eqn 45, RHS terms 6 and 6b [0 for sina=0]: -2 mu u omega sin(lat)/mx + ?
3667 ! Define f=2 omega sin(lat), e=2 omega cos(lat)
3668 ! => terms are: -f mu u / mx
3669 ! ru = mu u / my ; rw = mu w / my
3670 ! => terms are: -f ru *my / mx + ?
3675 IF ( config_flags%open_ys .or. specified .or. &
3676 config_flags%nested .or. config_flags%polar) j_start = MAX(jds+1,jts)
3677 IF ( config_flags%open_ye .or. specified .or. &
3678 config_flags%nested .or. config_flags%polar) j_end = MIN(jde-1,jte)
3680 ! boundary loops for coriolis not needed for open bdy (commented out 20100611 JD)
3681 ! IF ( (config_flags%open_ys) .and. (jts == jds) ) THEN
3684 ! DO i=its,MIN(ide-1,ite)
3686 ! rv_tend(i,k,jts)=rv_tend(i,k,jts) - (msfvy(i,jts)/msfvx(i,jts))*0.5*(f(i,jts)+f(i,jts)) &
3687 ! *0.25*(ru(i,k,jts)+ru(i+1,k,jts)+ru(i,k,jts)+ru(i+1,k,jts)) &
3688 ! + (msfvy(i,jts)/msfvx(i,jts))*0.5*(e(i,jts)+e(i,jts))*0.5*(sina(i,jts)+sina(i,jts)) &
3689 ! *0.25*(rw(i,k+1,jts)+rw(i,k,jts)+rw(i,k+1,jts)+rw(i,k,jts))
3698 DO i=its,MIN(ide-1,ite)
3700 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)) &
3701 *0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
3702 + (msfvy(i,j)/msfvx(i,j))*0.5*(e(i,j)+e(i,j-1))*0.5*(sina(i,j)+sina(i,j-1)) &
3703 *0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+rw(i,k+1,j)+rw(i,k,j))
3710 ! boundary loops for coriolis not needed for open bdy (commented out 20100611 JD)
3711 ! IF ( (config_flags%open_ye) .and. (jte == jde) ) THEN
3714 ! DO i=its,MIN(ide-1,ite)
3716 ! 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)) &
3717 ! *0.25*(ru(i,k,jte-1)+ru(i+1,k,jte-1)+ru(i,k,jte-1)+ru(i+1,k,jte-1)) &
3718 ! + (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)) &
3719 ! *0.25*(rw(i,k+1,jte-1)+rw(i,k,jte-1)+rw(i,k+1,jte-1)+rw(i,k,jte-1))
3726 ! coriolis term for w-mometum
3728 ! Notes on map scale factors
3729 ! ADT eqn 46/my, RHS terms 5 and 5b [0 for sina=0]: 2 mu u omega cos(lat)/my +?
3730 ! Define e=2 omega cos(lat)
3731 ! => terms are: e mu u / my + ???
3732 ! ru = mu u / my ; ru = mu v / mx
3733 ! => terms are: e ru + ???
3735 DO j=jts,MIN(jte, jde-1)
3737 DO i=its,MIN(ite, ide-1)
3739 rw_tend(i,k,j)=rw_tend(i,k,j) + e(i,j)* &
3740 (cosa(i,j)*0.5*(fzm(k)*(ru(i,k,j)+ru(i+1,k,j)) &
3741 +fzp(k)*(ru(i,k-1,j)+ru(i+1,k-1,j))) &
3742 -(msftx(i,j)/msfty(i,j))* &
3743 sina(i,j)*0.5*(fzm(k)*(rv(i,k,j)+rv(i,k,j+1)) &
3744 +fzp(k)*(rv(i,k-1,j)+rv(i,k-1,j+1))))
3750 END SUBROUTINE coriolis
3752 !------------------------------------------------------------------------------
3754 SUBROUTINE perturbation_coriolis ( ru_in, rv_in, rw, ru_tend, rv_tend, rw_tend, &
3756 u_base, v_base, z_base, &
3757 muu, muv, phb, ph, &
3758 msftx, msfty, msfux, msfuy, msfvx, msfvy, &
3759 f, e, sina, cosa, fzm, fzp, &
3760 ids, ide, jds, jde, kds, kde, &
3761 ims, ime, jms, jme, kms, kme, &
3762 its, ite, jts, jte, kts, kte )
3768 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
3770 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
3771 ims, ime, jms, jme, kms, kme, &
3772 its, ite, jts, jte, kts, kte
3774 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: ru_tend, &
3777 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: ru_in, &
3784 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
3791 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: f, &
3796 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: muu, &
3800 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
3803 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: u_base, &
3809 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) :: ru, &
3812 REAL :: z_at_u, z_at_v, wkp1, wk, wkm1
3816 INTEGER :: i, j , k, ktf
3817 INTEGER :: i_start, i_end, j_start, j_end
3819 LOGICAL :: specified
3823 ! perturbation_coriolis calculates the large timestep tendency terms in the
3824 ! u, v, and w momentum equations arise from the coriolis force. This version
3825 ! subtracts off the horizontal velocities from the initial sounding when
3826 ! computing the forcing terms, hence "perturbation" coriolis.
3831 if(config_flags%specified .or. config_flags%nested) specified = .true.
3835 ! coriolis for u-momentum equation
3839 IF ( config_flags%open_xs .or. specified .or. &
3840 config_flags%nested) i_start = MAX(ids+1,its)
3841 IF ( config_flags%open_xe .or. specified .or. &
3842 config_flags%nested) i_end = MIN(ide-1,ite)
3843 IF ( config_flags%periodic_x ) i_start = its
3844 IF ( config_flags%periodic_x ) i_end = ite
3846 ! compute perturbation mu*v for use in u momentum equation
3848 DO j = jts, MIN(jte,jde-1)+1
3850 DO i = i_start-1, i_end
3851 z_at_v = 0.25*( phb(i,k,j )+phb(i,k+1,j ) &
3852 +phb(i,k,j-1)+phb(i,k+1,j-1) &
3853 +ph(i,k,j )+ph(i,k+1,j ) &
3854 +ph(i,k,j-1)+ph(i,k+1,j-1))/g
3855 wkp1 = min(1.,max(0.,z_at_v-z_base(k))/(z_base(k+1)-z_base(k)))
3856 wkm1 = min(1.,max(0.,z_base(k)-z_at_v)/(z_base(k)-z_base(k-1)))
3858 rv(i,k,j) = rv_in(i,k,j) - muv(i,j)*( &
3867 ! pick up top and bottom v
3869 DO j = jts, MIN(jte,jde-1)+1
3870 DO i = i_start-1, i_end
3873 z_at_v = 0.25*( phb(i,k,j )+phb(i,k+1,j ) &
3874 +phb(i,k,j-1)+phb(i,k+1,j-1) &
3875 +ph(i,k,j )+ph(i,k+1,j ) &
3876 +ph(i,k,j-1)+ph(i,k+1,j-1))/g
3877 wkp1 = min(1.,max(0.,z_at_v-z_base(k))/(z_base(k+1)-z_base(k)))
3879 rv(i,k,j) = rv_in(i,k,j) - muv(i,j)*( &
3884 z_at_v = 0.25*( phb(i,k,j )+phb(i,k+1,j ) &
3885 +phb(i,k,j-1)+phb(i,k+1,j-1) &
3886 +ph(i,k,j )+ph(i,k+1,j ) &
3887 +ph(i,k,j-1)+ph(i,k+1,j-1))/g
3888 wkm1 = min(1.,max(0.,z_base(k)-z_at_v)/(z_base(k)-z_base(k-1)))
3890 rv(i,k,j) = rv_in(i,k,j) - muv(i,j)*( &
3897 ! compute coriolis forcing for u
3899 ! Map scale factors: see comments above for Coriolis
3901 DO j = jts, MIN(jte,jde-1)
3904 DO i = i_start, i_end
3905 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)) &
3906 *0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+rv(i-1,k,j)+rv(i,k,j)) &
3907 - 0.5*(e(i,j)+e(i-1,j))*0.5*(cosa(i,j)+cosa(i-1,j)) &
3908 *0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j))
3912 ! boundary loops for perturbation coriolis is needed for open bdy (20110225 JD)
3913 IF ( (config_flags%open_xs) .and. (its == ids) ) THEN
3917 ru_tend(its,k,j)=ru_tend(its,k,j) + (msfux(its,j)/msfuy(its,j))*0.5*(f(its,j)+f(its,j)) &
3918 *0.25*(rv(its,k,j+1)+rv(its,k,j+1)+rv(its,k,j)+rv(its,k,j)) &
3919 - 0.5*(e(its,j)+e(its,j))*0.5*(cosa(its,j)+cosa(its,j)) &
3920 *0.25*(rw(its,k+1,j)+rw(its,k,j)+rw(its,k+1,j)+rw(its,k,j))
3926 IF ( (config_flags%open_xe) .and. (ite == ide) ) THEN
3930 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)) &
3931 *0.25*(rv(ite-1,k,j+1)+rv(ite-1,k,j+1)+rv(ite-1,k,j)+rv(ite-1,k,j)) &
3932 - 0.5*(e(ite-1,j)+e(ite-1,j))*0.5*(cosa(ite-1,j)+cosa(ite-1,j)) &
3933 *0.25*(rw(ite-1,k+1,j)+rw(ite-1,k,j)+rw(ite-1,k+1,j)+rw(ite-1,k,j))
3941 ! coriolis term for v-momentum equation
3942 ! Map scale factors: see comments above for Coriolis
3947 IF ( config_flags%open_ys .or. specified .or. &
3948 config_flags%nested .or. config_flags%polar) j_start = MAX(jds+1,jts)
3949 IF ( config_flags%open_ye .or. specified .or. &
3950 config_flags%nested .or. config_flags%polar) j_end = MIN(jde-1,jte)
3952 ! compute perturbation mu*u for use in v momentum equation
3954 DO j = j_start-1,j_end
3956 DO i = its, MIN(ite,ide-1)+1
3957 z_at_u = 0.25*( phb(i ,k,j)+phb(i ,k+1,j) &
3958 +phb(i-1,k,j)+phb(i-1,k+1,j) &
3959 +ph(i ,k,j)+ph(i ,k+1,j) &
3960 +ph(i-1,k,j)+ph(i-1,k+1,j))/g
3961 wkp1 = min(1.,max(0.,z_at_u-z_base(k))/(z_base(k+1)-z_base(k)))
3962 wkm1 = min(1.,max(0.,z_base(k)-z_at_u)/(z_base(k)-z_base(k-1)))
3964 ru(i,k,j) = ru_in(i,k,j) - muu(i,j)*( &
3972 ! pick up top and bottom u
3974 DO j = j_start-1,j_end
3975 DO i = its, MIN(ite,ide-1)+1
3978 z_at_u = 0.25*( phb(i ,k,j)+phb(i ,k+1,j) &
3979 +phb(i-1,k,j)+phb(i-1,k+1,j) &
3980 +ph(i ,k,j)+ph(i ,k+1,j) &
3981 +ph(i-1,k,j)+ph(i-1,k+1,j))/g
3982 wkp1 = min(1.,max(0.,z_at_u-z_base(k))/(z_base(k+1)-z_base(k)))
3984 ru(i,k,j) = ru_in(i,k,j) - muu(i,j)*( &
3990 z_at_u = 0.25*( phb(i ,k,j)+phb(i ,k+1,j) &
3991 +phb(i-1,k,j)+phb(i-1,k+1,j) &
3992 +ph(i ,k,j)+ph(i ,k+1,j) &
3993 +ph(i-1,k,j)+ph(i-1,k+1,j))/g
3994 wkm1 = min(1.,max(0.,z_base(k)-z_at_u)/(z_base(k)-z_base(k-1)))
3996 ru(i,k,j) = ru_in(i,k,j) - muu(i,j)*( &
4003 ! compute coriolis forcing for v momentum equation
4004 ! Map scale factors: see comments above for Coriolis
4006 ! boundary loops for perturbation coriolis is needed for open bdy (20110225 JD)
4007 IF ( (config_flags%open_ys) .and. (jts == jds) ) THEN
4010 DO i=its,MIN(ide-1,ite)
4012 rv_tend(i,k,jts)=rv_tend(i,k,jts) - (msfvy(i,jts)/msfvx(i,jts))*0.5*(f(i,jts)+f(i,jts)) &
4013 *0.25*(ru(i,k,jts)+ru(i+1,k,jts)+ru(i,k,jts)+ru(i+1,k,jts)) &
4014 + (msfvy(i,jts)/msfvx(i,jts))*0.5*(e(i,jts)+e(i,jts))*0.5*(sina(i,jts)+sina(i,jts)) &
4015 *0.25*(rw(i,k+1,jts)+rw(i,k,jts)+rw(i,k+1,jts)+rw(i,k,jts))
4024 DO i=its,MIN(ide-1,ite)
4026 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)) &
4027 *0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
4028 + (msfvy(i,j)/msfvx(i,j))*0.5*(e(i,j)+e(i,j-1))*0.5*(sina(i,j)+sina(i,j-1)) &
4029 *0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+rw(i,k+1,j)+rw(i,k,j))
4036 ! boundary loops for perturbation coriolis is needed for open bdy (20110225 JD)
4037 IF ( (config_flags%open_ye) .and. (jte == jde) ) THEN
4040 DO i=its,MIN(ide-1,ite)
4042 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)) &
4043 *0.25*(ru(i,k,jte-1)+ru(i+1,k,jte-1)+ru(i,k,jte-1)+ru(i+1,k,jte-1)) &
4044 + (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)) &
4045 *0.25*(rw(i,k+1,jte-1)+rw(i,k,jte-1)+rw(i,k+1,jte-1)+rw(i,k,jte-1))
4052 ! coriolis term for w-mometum
4053 ! Map scale factors: see comments above for Coriolis
4055 DO j=jts,MIN(jte, jde-1)
4057 DO i=its,MIN(ite, ide-1)
4059 rw_tend(i,k,j)=rw_tend(i,k,j) + e(i,j)* &
4060 (cosa(i,j)*0.5*(fzm(k)*(ru(i,k,j)+ru(i+1,k,j)) &
4061 +fzp(k)*(ru(i,k-1,j)+ru(i+1,k-1,j))) &
4062 -(msftx(i,j)/msfty(i,j))*sina(i,j)*0.5*(fzm(k)*(rv(i,k,j)+rv(i,k,j+1)) &
4063 +fzp(k)*(rv(i,k-1,j)+rv(i,k-1,j+1))))
4069 END SUBROUTINE perturbation_coriolis
4071 !------------------------------------------------------------------------------
4073 SUBROUTINE curvature ( ru, rv, rw, u, v, w, ru_tend, rv_tend, rw_tend, &
4075 msfux, msfuy, msfvx, msfvy, msftx, msfty, &
4076 xlat, fzm, fzp, rdx, rdy, &
4077 ids, ide, jds, jde, kds, kde, &
4078 ims, ime, jms, jme, kms, kme, &
4079 its, ite, jts, jte, kts, kte )
4086 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
4088 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4089 ims, ime, jms, jme, kms, kme, &
4090 its, ite, jts, jte, kts, kte
4092 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4093 INTENT(INOUT) :: ru_tend, &
4097 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4098 INTENT(IN ) :: ru, &
4105 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN ) :: msfux, &
4113 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
4116 REAL , INTENT(IN ) :: rdx, &
4121 ! INTEGER :: i, j, k, itf, jtf, ktf, kp1, im, ip, jm, jp
4122 INTEGER :: i, j, k, itf, jtf, ktf
4123 INTEGER :: i_start, i_end, j_start, j_end
4124 ! INTEGER :: irmin, irmax, jrmin, jrmax
4126 REAL , DIMENSION( its-1:ite , kts:kte, jts-1:jte ) :: vxgm
4128 LOGICAL :: specified
4132 ! curvature calculates the large timestep tendency terms in the
4133 ! u, v, and w momentum equations arise from the curvature terms.
4138 if(config_flags%specified .or. config_flags%nested) specified = .true.
4148 ! IF ( config_flags%open_xs ) irmin = ids
4149 ! IF ( config_flags%open_xe ) irmax = ide-1
4150 ! IF ( config_flags%open_ys ) jrmin = jds
4151 ! IF ( config_flags%open_ye ) jrmax = jde-1
4153 ! Define v cross grad m at scalar points - vxgm(i,j)
4160 IF ( ( config_flags%open_xs .or. specified .or. &
4161 config_flags%nested) .and. (its == ids) ) i_start = its
4162 IF ( ( config_flags%open_xe .or. specified .or. &
4163 config_flags%nested) .and. (ite == ide) ) i_end = ite-1
4164 IF ( ( config_flags%open_ys .or. specified .or. &
4165 config_flags%nested .or. config_flags%polar) .and. (jts == jds) ) j_start = jts
4166 IF ( ( config_flags%open_ye .or. specified .or. &
4167 config_flags%nested .or. config_flags%polar) .and. (jte == jde) ) j_end = jte-1
4168 IF ( config_flags%periodic_x ) i_start = its-1
4169 IF ( config_flags%periodic_x ) i_end = ite
4174 ! Map scale factor notes:
4175 ! msf...y is constant everywhere for cylindrical map projection
4176 ! msf...x varies with y only
4177 ! But we know that this is not = 0 for cylindrical,
4178 ! therefore use msfvX in 1st line
4179 ! which => by symmetry use msfuY in 2nd line - ???
4180 vxgm(i,k,j)=0.5*(u(i,k,j)+u(i+1,k,j))*(msfvx(i,j+1)-msfvx(i,j))*rdy - &
4181 0.5*(v(i,k,j)+v(i,k,j+1))*(msfuy(i+1,j)-msfuy(i,j))*rdx
4186 ! Pick up the boundary rows for open (radiation) lateral b.c.
4187 ! Rather crude at present, we are assuming there is no
4188 ! variation in this term at the boundary.
4190 IF ( ( config_flags%open_xs .or. (specified .AND. .NOT. config_flags%periodic_x) .or. &
4191 config_flags%nested) .and. (its == ids) ) THEN
4195 vxgm(its-1,k,j) = vxgm(its,k,j)
4201 IF ( ( config_flags%open_xe .or. (specified .AND. .NOT. config_flags%periodic_x) .or. &
4202 config_flags%nested) .and. (ite == ide) ) THEN
4206 vxgm(ite,k,j) = vxgm(ite-1,k,j)
4212 ! Polar boundary condition:
4213 ! The following change is needed in case one tries using the vxgm route with
4214 ! polar B.C.'s in the future, but not needed if 'tan' used
4215 IF ( ( config_flags%open_ys .or. specified .or. &
4216 config_flags%nested .or. config_flags%polar) .and. (jts == jds) ) THEN
4220 vxgm(i,k,jts-1) = vxgm(i,k,jts)
4226 ! Polar boundary condition:
4227 ! The following change is needed in case one tries using the vxgm route with
4228 ! polar B.C.'s in the future, but not needed if 'tan' used
4229 IF ( ( config_flags%open_ye .or. specified .or. &
4230 config_flags%nested .or. config_flags%polar) .and. (jte == jde) ) THEN
4234 vxgm(i,k,jte) = vxgm(i,k,jte-1)
4240 ! curvature term for u momentum eqn.
4242 ! Map scale factor notes:
4243 ! ADT eqn 44, RHS terms 4 and 5, in cylindrical: mu u v tan(lat)/(a my)
4245 ! ru = mu u / my ; rw = mu w / my ; rv = mu v / mx
4247 ! (mx/my)*u rv tan(lat) / a - u rw / a = (u/a)*[(mx/my) rv tan(lat) - rw]
4248 ! ru v tan(lat) / a - u rw / a
4249 ! xlat defined with end points half grid space from pole,
4250 ! hence are on u latitude points
4253 IF ( config_flags%open_xs .or. specified .or. &
4254 config_flags%nested) i_start = MAX ( ids+1 , its )
4255 IF ( config_flags%open_xe .or. specified .or. &
4256 config_flags%nested) i_end = MIN ( ide-1 , ite )
4257 IF ( config_flags%periodic_x ) i_start = its
4258 IF ( config_flags%periodic_x ) i_end = ite
4260 ! Polar boundary condition
4261 IF ((config_flags%map_proj == 6) .OR. (config_flags%polar)) THEN
4263 DO j=jts,MIN(jde-1,jte)
4267 ru_tend(i,k,j)=ru_tend(i,k,j) + u(i,k,j)*reradius* ( &
4268 (msfux(i,j)/msfuy(i,j))*0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+ &
4269 rv(i-1,k,j)+rv(i,k,j))*tan(xlat(i,j)*degrad) &
4270 - 0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j)) )
4278 DO j=jts,MIN(jde-1,jte)
4282 ru_tend(i,k,j)=ru_tend(i,k,j) + 0.5*(vxgm(i,k,j)+vxgm(i-1,k,j)) &
4283 *0.25*(rv(i-1,k,j+1)+rv(i,k,j+1)+rv(i-1,k,j)+rv(i,k,j)) &
4284 - u(i,k,j)*reradius &
4285 *0.25*(rw(i-1,k+1,j)+rw(i-1,k,j)+rw(i,k+1,j)+rw(i,k,j))
4293 ! curvature term for v momentum eqn.
4295 ! Map scale factor notes
4296 ! ADT eqn 45, RHS terms 4 and 5, in cylindrical: - mu u*u tan(lat)/(a mx)
4298 ! ru = mu u / my ; rw = mu w / my ; rv = mu v / mx
4300 ! - (my/mx)*u ru tan(lat) / a - (my/mx)*v rw / a
4301 ! = - [my/(mx*a)]*[u ru tan(lat) + v rw]
4302 ! - (1/a)*[(my/mx)*u ru tan(lat) + w rv]
4303 ! xlat defined with end points half grid space from pole, hence are on
4304 ! u latitude points => av here
4306 ! in original wrf, there was a sign error for the rw contribution
4309 IF ( config_flags%open_ys .or. specified .or. &
4310 config_flags%nested .or. config_flags%polar) j_start = MAX ( jds+1 , jts )
4311 IF ( config_flags%open_ye .or. specified .or. &
4312 config_flags%nested .or. config_flags%polar) j_end = MIN ( jde-1 , jte )
4314 IF ((config_flags%map_proj == 6) .OR. (config_flags%polar)) THEN
4318 DO i=its,MIN(ite,ide-1)
4319 rv_tend(i,k,j)=rv_tend(i,k,j) - (msfvy(i,j)/msfvx(i,j))*reradius* ( &
4320 0.25*(u(i,k,j)+u(i+1,k,j)+u(i,k,j-1)+u(i+1,k,j-1))* &
4321 tan((xlat(i,j)+xlat(i,j-1))*0.5*degrad)* &
4322 0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
4323 + v(i,k,j)*0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+ &
4324 rw(i,k+1,j)+rw(i,k,j)) )
4333 DO i=its,MIN(ite,ide-1)
4335 rv_tend(i,k,j)=rv_tend(i,k,j) - 0.5*(vxgm(i,k,j)+vxgm(i,k,j-1)) &
4336 *0.25*(ru(i,k,j)+ru(i+1,k,j)+ru(i,k,j-1)+ru(i+1,k,j-1)) &
4337 - (msfvy(i,j)/msfvx(i,j))*v(i,k,j)*reradius &
4338 *0.25*(rw(i,k+1,j-1)+rw(i,k,j-1)+rw(i,k+1,j)+rw(i,k,j))
4346 ! curvature term for vertical momentum eqn.
4348 ! Notes on map scale factors:
4349 ! ADT eqn 46, RHS term 4: [mu/(a my)]*[u*u + v*v]
4350 ! ru = mu u / my ; rw = mu w / my ; rv = mu v / mx
4351 ! terms are: u ru / a + (mx/my)v rv / a
4353 DO j=jts,MIN(jte,jde-1)
4355 DO i=its,MIN(ite,ide-1)
4357 rw_tend(i,k,j)=rw_tend(i,k,j) + reradius* &
4358 (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))) &
4359 *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))) &
4360 +(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))) &
4361 *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))))
4367 END SUBROUTINE curvature
4369 !------------------------------------------------------------------------------
4371 SUBROUTINE decouple ( rr, rfield, field, name, config_flags, &
4373 ids, ide, jds, jde, kds, kde, &
4374 ims, ime, jms, jme, kms, kme, &
4375 its, ite, jts, jte, kts, kte )
4381 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
4383 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4384 ims, ime, jms, jme, kms, kme, &
4385 its, ite, jts, jte, kts, kte
4387 CHARACTER(LEN=1) , INTENT(IN ) :: name
4389 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: rfield
4391 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN ) :: rr
4393 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT ) :: field
4395 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, fzp
4399 INTEGER :: i, j, k, itf, jtf, ktf
4403 ! decouple decouples a variable from the column dry-air mass.
4409 IF (name .EQ. 'u')THEN
4416 field(i,k,j)=rfield(i,k,j)/(0.5*(rr(i,k,j)+rr(i-1,k,j)))
4421 ELSE IF (name .EQ. 'v')THEN
4428 field(i,k,j)=rfield(i,k,j)/(0.5*(rr(i,k,j)+rr(i,k,j-1)))
4433 ELSE IF (name .EQ. 'w')THEN
4439 field(i,k,j)=rfield(i,k,j)/(fzm(k)*rr(i,k,j)+fzp(k)*rr(i,k-1,j))
4453 ! For theta we will decouple tb and tp and add them to give t afterwards
4457 field(i,k,j)=rfield(i,k,j)/rr(i,k,j)
4464 END SUBROUTINE decouple
4466 !-------------------------------------------------------------------------------
4469 SUBROUTINE zero_tend ( tendency, &
4470 ids, ide, jds, jde, kds, kde, &
4471 ims, ime, jms, jme, kms, kme, &
4472 its, ite, jts, jte, kts, kte )
4479 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4480 ims, ime, jms, jme, kms, kme, &
4481 its, ite, jts, jte, kts, kte
4483 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: tendency
4487 INTEGER :: i, j, k, itf, jtf, ktf
4491 ! zero_tend sets the input tendency array to zero.
4498 tendency(i,k,j) = 0.
4503 END SUBROUTINE zero_tend
4505 !-------------------------------------------------------------------------------
4506 ! Sets the an array on the polar v point(s) to zero
4507 SUBROUTINE zero_pole ( field, &
4508 ids, ide, jds, jde, kds, kde, &
4509 ims, ime, jms, jme, kms, kme, &
4510 its, ite, jts, jte, kts, kte )
4517 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4518 ims, ime, jms, jme, kms, kme, &
4519 its, ite, jts, jte, kts, kte
4521 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: field
4527 IF (jts == jds) THEN
4534 IF (jte == jde) THEN
4542 END SUBROUTINE zero_pole
4544 !-------------------------------------------------------------------------------
4545 ! Sets the an array on the polar v point(s)
4546 SUBROUTINE pole_point_bc ( field, &
4547 ids, ide, jds, jde, kds, kde, &
4548 ims, ime, jms, jme, kms, kme, &
4549 its, ite, jts, jte, kts, kte )
4556 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4557 ims, ime, jms, jme, kms, kme, &
4558 its, ite, jts, jte, kts, kte
4560 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(INOUT) :: field
4566 IF (jts == jds) THEN
4569 ! field(i,k,jts) = 2*field(i,k,jts+1) - field(i,k,jts+2)
4570 field(i,k,jts) = field(i,k,jts+1)
4574 IF (jte == jde) THEN
4577 ! field(i,k,jte) = 2*field(i,k,jte-1) - field(i,k,jte-2)
4578 field(i,k,jte) = field(i,k,jte-1)
4583 END SUBROUTINE pole_point_bc
4585 !======================================================================
4586 ! physics prep routines
4587 !======================================================================
4589 SUBROUTINE phy_prep ( config_flags, & ! input
4590 mu, muu, muv, u, v, p, pb, alt, ph, & ! input
4591 phb, t, tsk, moist, n_moist, & ! input
4592 rho, th_phy, p_phy , pi_phy , & ! output
4593 u_phy, v_phy, p8w, t_phy, t8w, & ! output
4594 z, z_at_w, dz8w, & ! output
4595 p_hyd, p_hyd_w, dnw, & ! output
4596 fzm, fzp, znw, p_top, & ! params
4598 RTHBLTEN, RUBLTEN, RVBLTEN, &
4599 RQVBLTEN, RQCBLTEN, RQIBLTEN, &
4600 RUCUTEN, RVCUTEN, RTHCUTEN, &
4601 RQVCUTEN, RQCCUTEN, RQRCUTEN, &
4602 RQICUTEN, RQSCUTEN, &
4603 RUSHTEN, RVSHTEN, RTHSHTEN, &
4604 RQVSHTEN, RQCSHTEN, RQRSHTEN, &
4605 RQISHTEN, RQSSHTEN, RQGSHTEN, &
4607 RUNDGDTEN, RVNDGDTEN, RTHNDGDTEN, &
4608 RPHNDGDTEN,RQVNDGDTEN, RMUNDGDTEN, &
4609 ids, ide, jds, jde, kds, kde, &
4610 ims, ime, jms, jme, kms, kme, &
4611 its, ite, jts, jte, kts, kte )
4612 !----------------------------------------------------------------------
4614 !----------------------------------------------------------------------
4616 TYPE(grid_config_rec_type) , INTENT(IN ) :: config_flags
4618 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
4619 ims, ime, jms, jme, kms, kme, &
4620 its, ite, jts, jte, kts, kte
4621 INTEGER , INTENT(IN ) :: n_moist
4623 REAL, DIMENSION( ims:ime, kms:kme , jms:jme , n_moist ), INTENT(IN) :: moist
4626 REAL , DIMENSION( ims:ime, jms:jme ), INTENT(IN ) :: TSK, mu, muu, muv
4628 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4629 INTENT( OUT) :: u_phy, &
4642 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4643 INTENT( OUT) :: p_hyd, &
4646 REAL , INTENT(IN ) :: p_top
4648 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , &
4649 INTENT(IN ) :: pb, &
4659 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
4662 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: znw, &
4665 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
4666 INTENT(INOUT) :: RTHRATEN
4668 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
4669 INTENT(INOUT) :: RUCUTEN, &
4687 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
4688 INTENT(INOUT) :: RUBLTEN, &
4695 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
4696 INTENT(INOUT) :: RTHFTEN, &
4699 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ) , &
4700 INTENT(INOUT) :: RUNDGDTEN, &
4706 REAL, DIMENSION( ims:ime, jms:jme ) , &
4707 INTENT(INOUT) :: RMUNDGDTEN
4709 INTEGER :: i_start, i_end, j_start, j_end, k_start, k_end, i_startu, j_startv
4711 REAL :: w1, w2, z0, z1, z2
4715 !-----------------------------------------------------------------------
4719 ! phys_prep calculates a number of diagnostic quantities needed by
4720 ! the physics routines. It also decouples the physics tendencies from
4721 ! the column dry-air mass (the physics routines expect to see/update the
4722 ! uncoupled tendencies).
4726 ! set up loop bounds for this grid's boundary conditions
4729 i_end = min( ite,ide-1 )
4731 j_end = min( jte,jde-1 )
4734 k_end = min( kte, kde-1 )
4736 ! compute thermodynamics and velocities at pressure points (or half levels)
4738 do j = j_start,j_end
4739 do k = k_start, k_end
4740 do i = i_start, i_end
4742 th_phy(i,k,j) = t(i,k,j) + t0
4743 p_phy(i,k,j) = p(i,k,j) + pb(i,k,j)
4744 pi_phy(i,k,j) = (p_phy(i,k,j)/p1000mb)**rcp
4745 t_phy(i,k,j) = th_phy(i,k,j)*pi_phy(i,k,j)
4746 rho(i,k,j) = 1./alt(i,k,j)*(1.+moist(i,k,j,P_QV))
4747 u_phy(i,k,j) = 0.5*(u(i,k,j)+u(i+1,k,j))
4748 v_phy(i,k,j) = 0.5*(v(i,k,j)+v(i,k,j+1))
4754 ! compute z at w points
4756 do j = j_start,j_end
4758 do i = i_start, i_end
4759 z_at_w(i,k,j) = (phb(i,k,j)+ph(i,k,j))/g
4764 do j = j_start,j_end
4765 do k = k_start, kte-1
4766 do i = i_start, i_end
4767 dz8w(i,k,j) = z_at_w(i,k+1,j)-z_at_w(i,k,j)
4772 do j = j_start,j_end
4773 do i = i_start, i_end
4778 ! compute z at p points or half levels (average of z at full levels)
4780 do j = j_start,j_end
4781 do k = k_start, k_end
4782 do i = i_start, i_end
4783 z(i,k,j) = 0.5*(z_at_w(i,k,j) +z_at_w(i,k+1,j) )
4788 ! interp t and p to full levels
4790 do j = j_start,j_end
4792 do i = i_start, i_end
4793 p8w(i,k,j) = fzm(k)*p_phy(i,k,j)+fzp(k)*p_phy(i,k-1,j)
4794 t8w(i,k,j) = fzm(k)*t_phy(i,k,j)+fzp(k)*t_phy(i,k-1,j)
4799 ! extrapolate p and t to surface and top.
4800 ! we'll use an extrapolation in z for now
4802 do j = j_start,j_end
4803 do i = i_start, i_end
4810 w1 = (z0 - z2)/(z1 - z2)
4812 p8w(i,1,j) = w1*p_phy(i,1,j)+w2*p_phy(i,2,j)
4813 t8w(i,1,j) = w1*t_phy(i,1,j)+w2*t_phy(i,2,j)
4817 z0 = z_at_w(i,kte,j)
4820 w1 = (z0 - z2)/(z1 - z2)
4823 ! p8w(i,kde,j) = w1*p_phy(i,kde-1,j)+w2*p_phy(i,kde-2,j)
4824 !!! bug fix extrapolate ln(p) so p is positive definite
4825 p8w(i,kde,j) = exp(w1*log(p_phy(i,kde-1,j))+w2*log(p_phy(i,kde-2,j)))
4826 t8w(i,kde,j) = w1*t_phy(i,kde-1,j)+w2*t_phy(i,kde-2,j)
4831 ! calculate hydrostatic pressure at both full and half levels
4832 ! first, full level p: assuming dry over model top
4834 do j = j_start,j_end
4835 do i = i_start, i_end
4836 p_hyd_w(i,kte,j) = p_top
4840 do j = j_start,j_end
4841 do k = kte-1, k_start, -1
4842 do i = i_start, i_end
4844 do n = PARAM_FIRST_SCALAR,n_moist
4845 qtot = qtot + moist(i,k,j,n)
4847 p_hyd_w(i,k,j) = p_hyd_w(i,k+1,j) - (1.+qtot)*mu(i,j)*dnw(k)
4848 ! 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)
4853 ! now calculate hydrostatic pressure at half levels
4855 do j = j_start,j_end
4856 do k = k_start, k_end
4857 do i = i_start, i_end
4858 p_hyd(i,k,j) = 0.5*(p_hyd_w(i,k,j)+p_hyd_w(i,k+1,j))
4863 ! decouple all physics tendencies
4865 IF (config_flags%ra_lw_physics .gt. 0 .or. config_flags%ra_sw_physics .gt. 0) THEN
4870 RTHRATEN(I,K,J)=RTHRATEN(I,K,J)/mu(I,J)
4877 IF (config_flags%cu_physics .gt. 0) THEN
4882 RUCUTEN(I,K,J) =RUCUTEN(I,K,J)/mu(I,J)
4883 RVCUTEN(I,K,J) =RVCUTEN(I,K,J)/mu(I,J)
4884 RTHCUTEN(I,K,J)=RTHCUTEN(I,K,J)/mu(I,J)
4889 IF (P_QV .ge. PARAM_FIRST_SCALAR)THEN
4893 RQVCUTEN(I,K,J)=RQVCUTEN(I,K,J)/mu(I,J)
4899 IF (P_QC .ge. PARAM_FIRST_SCALAR)THEN
4903 RQCCUTEN(I,K,J)=RQCCUTEN(I,K,J)/mu(I,J)
4909 IF (P_QR .ge. PARAM_FIRST_SCALAR)THEN
4913 RQRCUTEN(I,K,J)=RQRCUTEN(I,K,J)/mu(I,J)
4919 IF (P_QI .ge. PARAM_FIRST_SCALAR)THEN
4923 RQICUTEN(I,K,J)=RQICUTEN(I,K,J)/mu(I,J)
4929 IF(P_QS .ge. PARAM_FIRST_SCALAR)THEN
4933 RQSCUTEN(I,K,J)=RQSCUTEN(I,K,J)/mu(I,J)
4941 IF (config_flags%shcu_physics .gt. 0) THEN
4946 RUSHTEN(I,K,J) =RUSHTEN(I,K,J)/mu(I,J)
4947 RVSHTEN(I,K,J) =RVSHTEN(I,K,J)/mu(I,J)
4948 RTHSHTEN(I,K,J)=RTHSHTEN(I,K,J)/mu(I,J)
4953 IF (P_QV .ge. PARAM_FIRST_SCALAR)THEN
4957 RQVSHTEN(I,K,J)=RQVSHTEN(I,K,J)/mu(I,J)
4963 IF (P_QC .ge. PARAM_FIRST_SCALAR)THEN
4967 RQCSHTEN(I,K,J)=RQCSHTEN(I,K,J)/mu(I,J)
4973 IF (P_QR .ge. PARAM_FIRST_SCALAR)THEN
4977 RQRSHTEN(I,K,J)=RQRSHTEN(I,K,J)/mu(I,J)
4983 IF (P_QI .ge. PARAM_FIRST_SCALAR)THEN
4987 RQISHTEN(I,K,J)=RQISHTEN(I,K,J)/mu(I,J)
4993 IF(P_QS .ge. PARAM_FIRST_SCALAR)THEN
4997 RQSSHTEN(I,K,J)=RQSSHTEN(I,K,J)/mu(I,J)
5003 IF(P_QG .ge. PARAM_FIRST_SCALAR)THEN
5007 RQGSHTEN(I,K,J)=RQGSHTEN(I,K,J)/mu(I,J)
5015 IF (config_flags%bl_pbl_physics .gt. 0) THEN
5020 RUBLTEN(I,K,J) =RUBLTEN(I,K,J)/mu(I,J)
5021 RVBLTEN(I,K,J) =RVBLTEN(I,K,J)/mu(I,J)
5022 RTHBLTEN(I,K,J)=RTHBLTEN(I,K,J)/mu(I,J)
5027 IF (P_QV .ge. PARAM_FIRST_SCALAR) THEN
5031 RQVBLTEN(I,K,J)=RQVBLTEN(I,K,J)/mu(I,J)
5037 IF (P_QC .ge. PARAM_FIRST_SCALAR) THEN
5041 RQCBLTEN(I,K,J)=RQCBLTEN(I,K,J)/mu(I,J)
5047 IF (P_QI .ge. PARAM_FIRST_SCALAR) THEN
5051 RQIBLTEN(I,K,J)=RQIBLTEN(I,K,J)/mu(I,J)
5059 ! decouple advective forcing required by Grell-Devenyi scheme
5061 if(( config_flags%cu_physics == GDSCHEME ) .OR. &
5062 ( config_flags%cu_physics == G3SCHEME ) .OR. &
5063 ( config_flags%cu_physics == KFETASCHEME ) .OR. &
5064 ( config_flags%cu_physics == TIEDTKESCHEME ) ) then ! Tiedtke ZCX&YQW
5069 RTHFTEN(I,K,J)=RTHFTEN(I,K,J)/mu(I,J)
5074 IF (P_QV .ge. PARAM_FIRST_SCALAR)THEN
5078 RQVFTEN(I,K,J)=RQVFTEN(I,K,J)/mu(I,J)
5087 ! note fdda u and v tendencies are staggered, also only interior points have muu/muv,
5088 ! so only decouple those
5090 IF (config_flags%grid_fdda .gt. 0) THEN
5092 i_startu=MAX(its,ids+1)
5093 j_startv=MAX(jts,jds+1)
5098 RUNDGDTEN(I,K,J) =RUNDGDTEN(I,K,J)/muu(I,J)
5105 RVNDGDTEN(I,K,J) =RVNDGDTEN(I,K,J)/muv(I,J)
5112 RTHNDGDTEN(I,K,J)=RTHNDGDTEN(I,K,J)/mu(I,J)
5113 ! RMUNDGDTEN(I,J) - no coupling
5118 IF (config_flags%grid_fdda .EQ. 2) THEN
5122 RPHNDGDTEN(I,K,J)=RPHNDGDTEN(I,K,J)/mu(I,J)
5127 ELSE IF (config_flags%grid_fdda .EQ. 1) THEN
5128 IF (P_QV .ge. PARAM_FIRST_SCALAR) THEN
5132 RQVNDGDTEN(I,K,J)=RQVNDGDTEN(I,K,J)/mu(I,J)
5141 END SUBROUTINE phy_prep
5143 !------------------------------------------------------------
5145 SUBROUTINE moist_physics_prep_em( t_new, t_old, t0, rho, al, alb, &
5146 p, p8w, p0, pb, ph, phb, &
5150 config_flags,fzm, fzp, &
5151 ids,ide, jds,jde, kds,kde, &
5152 ims,ime, jms,jme, kms,kme, &
5153 its,ite, jts,jte, kts,kte )
5157 ! Here we construct full fields
5158 ! needed by the microphysics
5160 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
5162 INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
5163 INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
5164 INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
5166 REAL, INTENT(IN ) :: dt
5168 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5169 INTENT(IN ) :: al, &
5177 REAL , DIMENSION( kms:kme ) , INTENT(IN ) :: fzm, &
5180 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5181 INTENT( OUT) :: rho, &
5190 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5191 INTENT(INOUT) :: h_diabatic
5193 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5194 INTENT(INOUT) :: t_new, &
5197 REAL, INTENT(IN ) :: t0, p0
5198 REAL :: z0,z1,z2,w1,w2
5200 INTEGER :: i_start, i_end, j_start, j_end, k_start, k_end
5203 !--------------------------------------------------------------------
5207 ! moist_phys_prep_em calculates a number of diagnostic quantities needed by
5208 ! the microphysics routines.
5212 ! set up loop bounds for this grid's boundary conditions
5215 i_end = min( ite,ide-1 )
5217 j_end = min( jte,jde-1 )
5220 k_end = min( kte, kde-1 )
5222 DO j = j_start, j_end
5224 DO i = i_start, i_end
5225 z_at_w(i,k,j) = (ph(i,k,j)+phb(i,k,j))/g
5230 do j = j_start,j_end
5231 do k = k_start, kte-1
5232 do i = i_start, i_end
5233 dz8w(i,k,j) = z_at_w(i,k+1,j)-z_at_w(i,k,j)
5238 do j = j_start,j_end
5239 do i = i_start, i_end
5245 ! compute full pii, rho, and z at the new time-level
5246 ! (needed for physics).
5247 ! convert perturbation theta to full theta (th_phy)
5248 ! use h_diabatic to temporarily save pre-microphysics full theta
5250 DO j = j_start, j_end
5251 DO k = k_start, k_end
5252 DO i = i_start, i_end
5255 t_new(i,k,j) = t_new(i,k,j)-h_diabatic(i,k,j)*dt
5257 th_phy(i,k,j) = t_new(i,k,j) + t0
5258 h_diabatic(i,k,j) = th_phy(i,k,j)
5259 rho(i,k,j) = 1./(al(i,k,j)+alb(i,k,j))
5260 pii(i,k,j) = ((p(i,k,j)+pb(i,k,j))/p0)**rcp
5261 z(i,k,j) = 0.5*(z_at_w(i,k,j) +z_at_w(i,k+1,j) )
5262 pf(i,k,j) = p(i,k,j)+pb(i,k,j)
5268 ! interp t and p at w points
5270 do j = j_start,j_end
5272 do i = i_start, i_end
5273 p8w(i,k,j) = fzm(k)*pf(i,k,j)+fzp(k)*pf(i,k-1,j)
5278 ! extrapolate p and t to surface and top.
5279 ! we'll use an extrapolation in z for now
5281 do j = j_start,j_end
5282 do i = i_start, i_end
5289 w1 = (z0 - z2)/(z1 - z2)
5291 p8w(i,1,j) = w1*pf(i,1,j)+w2*pf(i,2,j)
5295 z0 = z_at_w(i,kte,j)
5298 w1 = (z0 - z2)/(z1 - z2)
5300 ! p8w(i,kde,j) = w1*pf(i,kde-1,j)+w2*pf(i,kde-2,j)
5301 p8w(i,kde,j) = exp(w1*log(pf(i,kde-1,j))+w2*log(pf(i,kde-2,j)))
5306 END SUBROUTINE moist_physics_prep_em
5308 !------------------------------------------------------------------------------
5310 SUBROUTINE moist_physics_finish_em( t_new, t_old, t0, mut, &
5311 th_phy, h_diabatic, dt, &
5313 #if ( WRF_DFI_RADAR == 1 )
5314 dfi_tten_rad,dfi_stage, &
5316 ids,ide, jds,jde, kds,kde, &
5317 ims,ime, jms,jme, kms,kme, &
5318 its,ite, jts,jte, kts,kte )
5322 ! Here we construct full fields
5323 ! needed by the microphysics
5325 TYPE(grid_config_rec_type), INTENT(IN ) :: config_flags
5327 INTEGER, INTENT(IN ) :: ids,ide, jds,jde, kds,kde
5328 INTEGER, INTENT(IN ) :: ims,ime, jms,jme, kms,kme
5329 INTEGER, INTENT(IN ) :: its,ite, jts,jte, kts,kte
5331 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5332 INTENT(INOUT) :: t_new, &
5336 #if ( WRF_DFI_RADAR == 1 )
5337 REAL, DIMENSION( ims:ime , kms:kme, jms:jme ), &
5338 INTENT(IN), OPTIONAL :: dfi_tten_rad
5339 INTEGER, INTENT(IN ) ,OPTIONAL :: dfi_stage
5340 REAL :: dfi_tten_max, old_max
5343 REAL mpten, mptenmax, mptenmin
5345 REAL, DIMENSION( ims:ime , jms:jme ), INTENT(INOUT) :: mut
5348 REAL, INTENT(IN ) :: t0, dt
5350 INTEGER :: i_start, i_end, j_start, j_end, k_start, k_end
5351 INTEGER :: i, j, k, imax, jmax, imin, jmin
5353 !--------------------------------------------------------------------
5357 ! moist_phys_finish_em resets theta to its perturbation value and
5358 ! computes and stores the microphysics diabatic heating term.
5362 ! set up loop bounds for this grid's boundary conditions
5366 i_end = min( ite,ide-1 )
5368 j_end = min( jte,jde-1 )
5369 ! i_start=max(its,ids+4)
5370 ! i_end=min(ite,ide-5)
5371 ! j_start=max(jts,jds+4)
5372 ! j_end=min(jte,jde-5)
5375 k_end = min( kte, kde-1 )
5377 #if ( WRF_DFI_RADAR == 1 )
5378 IF ( PRESENT(dfi_stage) .and. PRESENT(dfi_tten_rad) ) THEN
5379 IF ( dfi_stage ==DFI_FWD ) THEN
5380 WRITE(wrf_err_message,*)'Add radar tendency: i_start,j_start: ', i_start, j_start
5381 CALL wrf_debug ( 100 , TRIM(wrf_err_message) )
5388 ! add microphysics theta diff to perturbation theta, set h_diabatic
5390 IF ( config_flags%no_mp_heating .eq. 0 ) THEN
5393 DO j = j_start, j_end
5394 DO k = k_start, k_end
5395 DO i = i_start, i_end
5396 mpten = th_phy(i,k,j)-h_diabatic(i,k,j)
5397 #if ( WRF_DFI_RADAR == 1 )
5398 if(mpten.gt.mptenmax) then
5403 if(mpten.lt.mptenmin) then
5408 mpten=min(config_flags%mp_tend_lim*dt, mpten)
5409 mpten=max(-config_flags%mp_tend_lim*dt, mpten)
5412 if(dfi_tten_max < dfi_tten_rad(i,k,j) ) dfi_tten_max = dfi_tten_rad(i,k,j)
5413 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)
5416 IF ( PRESENT(dfi_stage) .and. PRESENT(dfi_tten_rad) ) THEN
5417 IF ( dfi_stage == DFI_FWD .and. dfi_tten_rad(i,k,j) >= -0.1 .and. &
5418 dfi_tten_rad(i,k,j) <= 0.1 .and. k < k_end ) THEN
5419 ! add radar temp tendency
5420 ! there is radar coverage
5421 t_new(i,k,j) = t_new(i,k,j) + (dfi_tten_rad(i,k,j))*dt
5424 t_new(i,k,j) = t_new(i,k,j) + mpten
5428 t_new(i,k,j) = t_new(i,k,j) + mpten
5430 h_diabatic(i,k,j) = mpten/dt
5437 DO j = j_start, j_end
5438 DO k = k_start, k_end
5439 DO i = i_start, i_end
5440 ! t_new(i,k,j) = t_new(i,k,j)
5441 h_diabatic(i,k,j) = 0.
5447 END SUBROUTINE moist_physics_finish_em
5449 !----------------------------------------------------------------
5452 SUBROUTINE init_module_big_step
5453 END SUBROUTINE init_module_big_step
5455 SUBROUTINE set_tend ( field, field_adv_tend, msf, &
5456 ids, ide, jds, jde, kds, kde, &
5457 ims, ime, jms, jme, kms, kme, &
5458 its, ite, jts, jte, kts, kte )
5464 INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
5465 ims, ime, jms, jme, kms, kme, &
5466 its, ite, jts, jte, kts, kte
5468 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(OUT) :: field
5470 REAL , DIMENSION( ims:ime , kms:kme , jms:jme ) , INTENT(IN) :: field_adv_tend
5472 REAL , DIMENSION( ims:ime , jms:jme ) , INTENT(IN) :: msf
5476 INTEGER :: i, j, k, itf, jtf, ktf
5480 ! set_tend copies the advective tendency array into the tendency array.
5484 jtf = MIN(jte,jde-1)
5485 ktf = MIN(kte,kde-1)
5486 itf = MIN(ite,ide-1)
5490 field(i,k,j) = field_adv_tend(i,k,j)*msf(i,j)
5495 END SUBROUTINE set_tend
5497 !------------------------------------------------------------------------------
5499 SUBROUTINE rk_rayleigh_damp( ru_tendf, rv_tendf, &
5500 rw_tendf, t_tendf, &
5501 u, v, w, t, t_init, &
5502 mut, muu, muv, ph, phb, &
5503 u_base, v_base, t_base, z_base, &
5505 ids, ide, jds, jde, kds, kde, &
5506 ims, ime, jms, jme, kms, kme, &
5507 its, ite, jts, jte, kts, kte )
5509 ! History: Apr 2005 Modifications by George Bryan, NCAR:
5510 ! - Generalized the code in a way that allows for
5511 ! simulations with steep terrain.
5513 ! Jul 2004 Modifications by George Bryan, NCAR:
5514 ! - Modified the code to use u_base, v_base, and t_base
5515 ! arrays for the background state. Removed the hard-wired
5516 ! base-state values.
5517 ! - Modified the code to use dampcoef, zdamp, and damp_opt,
5518 ! i.e., the upper-level damper variables in namelist.input.
5519 ! Removed the hard-wired variables in the older version.
5520 ! This damper is used when damp_opt = 2.
5521 ! - Modified the code to account for the movement of the
5522 ! model surfaces with time. The code now obtains a base-
5523 ! state value by interpolation using the "_base" arrays.
5525 ! Nov 2003 Bug fix by Jason Knievel, NCAR
5527 ! Aug 2003 Meridional dimension, some comments, and
5528 ! changes in layout of the code added by
5529 ! Jason Knievel, NCAR
5531 ! Jul 2003 Original code by Bill Skamarock, NCAR
5533 ! Purpose: This routine applies Rayleigh damping to a layer at top
5534 ! of the model domain.
5536 !-----------------------------------------------------------------------
5537 ! Begin declarations.
5541 INTEGER, INTENT( IN ) &
5542 :: ids, ide, jds, jde, kds, kde, &
5543 ims, ime, jms, jme, kms, kme, &
5544 its, ite, jts, jte, kts, kte
5546 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( INOUT ) &
5547 :: ru_tendf, rv_tendf, rw_tendf, t_tendf
5549 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( IN ) &
5550 :: u, v, w, t, t_init, ph, phb
5552 REAL, DIMENSION( ims:ime, jms:jme ), INTENT( IN ) &
5555 REAL, DIMENSION( kms:kme ) , INTENT(IN ) &
5556 :: u_base, v_base, t_base, z_base
5564 :: i_start, i_end, j_start, j_end, k_start, k_end, i, j, k, ktf, k1, k2
5567 :: pii, dcoef, z, ztop
5569 REAL :: wkp1, wk, wkm1
5571 REAL, DIMENSION( kms:kme ) :: z00, u00, v00, t00
5574 !-----------------------------------------------------------------------
5576 pii = 2.0 * asin(1.0)
5578 ktf = MIN( kte, kde-1 )
5580 !-----------------------------------------------------------------------
5581 ! Adjust u to base state.
5583 DO j = jts, MIN( jte, jde-1 )
5584 DO i = its, MIN( ite, ide )
5586 ! Get height at top of model
5587 ztop = 0.5*( phb(i ,kde,j)+phb(i-1,kde,j) &
5588 +ph(i ,kde,j)+ph(i-1,kde,j) )/g
5590 ! Find bottom of damping layer
5593 DO WHILE( z >= (ztop-zdamp) )
5594 z = 0.25*( phb(i ,k1,j)+phb(i ,k1+1,j) &
5595 +phb(i-1,k1,j)+phb(i-1,k1+1,j) &
5596 +ph(i ,k1,j)+ph(i ,k1+1,j) &
5597 +ph(i-1,k1,j)+ph(i-1,k1+1,j))/g
5603 ! Get reference state at model levels
5606 DO WHILE( z_base(k2) .gt. z00(k) )
5610 u00(k) = u_base(k2) + ( u_base(k2) - u_base(k2-1) ) &
5611 * ( z00(k) - z_base(k2) ) &
5612 / ( z_base(k2) - z_base(k2-1) )
5614 u00(k) = u_base(k2) + ( u_base(k2+1) - u_base(k2) ) &
5615 * ( z00(k) - z_base(k2) ) &
5616 / ( z_base(k2+1) - z_base(k2) )
5620 ! Apply the Rayleigh damper
5622 dcoef = 1.0 - MIN( 1.0, ( ztop - z00(k) ) / zdamp )
5623 dcoef = (SIN( 0.5 * pii * dcoef ) )**2
5624 ru_tendf(i,k,j) = ru_tendf(i,k,j) - &
5625 muu(i,j) * ( dcoef * dampcoef ) * &
5626 ( u(i,k,j) - u00(k) )
5632 ! End adjustment of u.
5633 !-----------------------------------------------------------------------
5635 !-----------------------------------------------------------------------
5636 ! Adjust v to base state.
5638 DO j = jts, MIN( jte, jde )
5639 DO i = its, MIN( ite, ide-1 )
5641 ! Get height at top of model
5642 ztop = 0.5*( phb(i,kde,j )+phb(i,kde,j-1) &
5643 +ph(i,kde,j )+ph(i,kde,j-1) )/g
5645 ! Find bottom of damping layer
5648 DO WHILE( z >= (ztop-zdamp) )
5649 z = 0.25*( phb(i,k1,j )+phb(i,k1+1,j ) &
5650 +phb(i,k1,j-1)+phb(i,k1+1,j-1) &
5651 +ph(i,k1,j )+ph(i,k1+1,j ) &
5652 +ph(i,k1,j-1)+ph(i,k1+1,j-1))/g
5658 ! Get reference state at model levels
5661 DO WHILE( z_base(k2) .gt. z00(k) )
5665 v00(k) = v_base(k2) + ( v_base(k2) - v_base(k2-1) ) &
5666 * ( z00(k) - z_base(k2) ) &
5667 / ( z_base(k2) - z_base(k2-1) )
5669 v00(k) = v_base(k2) + ( v_base(k2+1) - v_base(k2) ) &
5670 * ( z00(k) - z_base(k2) ) &
5671 / ( z_base(k2+1) - z_base(k2) )
5675 ! Apply the Rayleigh damper
5677 dcoef = 1.0 - MIN( 1.0, ( ztop - z00(k) ) / zdamp )
5678 dcoef = (SIN( 0.5 * pii * dcoef ) )**2
5679 rv_tendf(i,k,j) = rv_tendf(i,k,j) - &
5680 muv(i,j) * ( dcoef * dampcoef ) * &
5681 ( v(i,k,j) - v00(k) )
5687 ! End adjustment of v.
5688 !-----------------------------------------------------------------------
5690 !-----------------------------------------------------------------------
5691 ! Adjust w to base state.
5693 DO j = jts, MIN( jte, jde-1 )
5694 DO i = its, MIN( ite, ide-1 )
5695 ztop = ( phb(i,kde,j) + ph(i,kde,j) ) / g
5696 DO k = kts, MIN( kte, kde )
5697 z = ( phb(i,k,j) + ph(i,k,j) ) / g
5698 IF ( z >= (ztop-zdamp) ) THEN
5699 dcoef = 1.0 - MIN( 1.0, ( ztop - z ) / zdamp )
5700 dcoef = ( SIN( 0.5 * pii * dcoef ) )**2
5701 rw_tendf(i,k,j) = rw_tendf(i,k,j) - &
5702 mut(i,j) * ( dcoef * dampcoef ) * w(i,k,j)
5708 ! End adjustment of w.
5709 !-----------------------------------------------------------------------
5711 !-----------------------------------------------------------------------
5712 ! Adjust potential temperature to base state.
5714 DO j = jts, MIN( jte, jde-1 )
5715 DO i = its, MIN( ite, ide-1 )
5717 ! Get height at top of model
5718 ztop = ( phb(i,kde,j) + ph(i,kde,j) ) / g
5720 ! Find bottom of damping layer
5723 DO WHILE( z >= (ztop-zdamp) )
5724 z = 0.5 * ( phb(i,k1,j) + phb(i,k1+1,j) + &
5725 ph(i,k1,j) + ph(i,k1+1,j) ) / g
5731 ! Get reference state at model levels
5734 DO WHILE( z_base(k2) .gt. z00(k) )
5738 t00(k) = t_base(k2) + ( t_base(k2) - t_base(k2-1) ) &
5739 * ( z00(k) - z_base(k2) ) &
5740 / ( z_base(k2) - z_base(k2-1) )
5742 t00(k) = t_base(k2) + ( t_base(k2+1) - t_base(k2) ) &
5743 * ( z00(k) - z_base(k2) ) &
5744 / ( z_base(k2+1) - z_base(k2) )
5748 ! Apply the Rayleigh damper
5750 dcoef = 1.0 - MIN( 1.0, ( ztop - z00(k) ) / zdamp )
5751 dcoef = (SIN( 0.5 * pii * dcoef ) )**2
5752 t_tendf(i,k,j) = t_tendf(i,k,j) - &
5753 mut(i,j) * ( dcoef * dampcoef ) * &
5754 ( t(i,k,j) - t00(k) )
5760 ! End adjustment of potential temperature.
5761 !-----------------------------------------------------------------------
5763 END SUBROUTINE rk_rayleigh_damp
5765 !==============================================================================
5766 !==============================================================================
5768 SUBROUTINE theta_relaxation( t_tendf, t, t_init, &
5771 ids, ide, jds, jde, kds, kde, &
5772 ims, ime, jms, jme, kms, kme, &
5773 its, ite, jts, jte, kts, kte )
5775 ! Purpose: Newtonian relaxation on potential temperature. Serves two
5776 ! purposes: 1) to mimic atmospheric radiation in a simple
5777 ! manner, and 2) to keep the vertical profile of temperature
5778 ! close to the initial (base-state) profile, which is useful
5779 ! for certain idealized applications.
5781 ! Reference: Rotunno and Emanuel, 1987, JAS, p. 546
5783 !-----------------------------------------------------------------------
5784 ! Begin declarations.
5788 INTEGER, INTENT( IN ) &
5789 :: ids, ide, jds, jde, kds, kde, &
5790 ims, ime, jms, jme, kms, kme, &
5791 its, ite, jts, jte, kts, kte
5793 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( INOUT ) &
5796 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT( IN ) &
5797 :: t, t_init, ph, phb
5799 REAL, DIMENSION( ims:ime, jms:jme ), INTENT( IN ) &
5802 REAL, DIMENSION( kms:kme ) , INTENT(IN ) &
5807 INTEGER :: i, j, k, ktf, k2
5808 REAL :: tau_r , rmax , rmin , inv_tau_r , inv_g , rterm
5809 REAL, DIMENSION( kms:kme ) :: z00,t00
5812 !-----------------------------------------------------------------------
5814 ! set tau_r to 12 h, following RE87
5817 ! limit rterm to +/- 2 K/day
5821 ktf = MIN( kte, kde-1 )
5822 inv_tau_r = 1.0/tau_r
5825 !-----------------------------------------------------------------------
5826 ! Adjust potential temperature to base state.
5828 DO j = jts, MIN( jte, jde-1 )
5829 DO i = its, MIN( ite, ide-1 )
5831 ! Get height of model levels:
5833 z00(k) = 0.5 * ( phb(i,k,j) + phb(i,k+1,j) + &
5834 ph(i,k,j) + ph(i,k+1,j) ) * inv_g
5837 ! Get reference state:
5840 DO WHILE( z_base(k2) .gt. z00(k) .and. k2 .gt. 1 )
5844 t00(k) = t_base(k2) + ( t_base(k2) - t_base(k2-1) ) &
5845 * ( z00(k) - z_base(k2) ) &
5846 / ( z_base(k2) - z_base(k2-1) )
5848 t00(k) = t_base(k2) + ( t_base(k2+1) - t_base(k2) ) &
5849 * ( z00(k) - z_base(k2) ) &
5850 / ( z_base(k2+1) - z_base(k2) )
5854 ! Apply the RE87 R term:
5856 rterm = -( t(i,k,j) - t00(k) )*inv_tau_r
5858 rterm = min( rterm , rmax )
5859 rterm = max( rterm , rmin )
5860 t_tendf(i,k,j) = t_tendf(i,k,j) + mut(i,j)*rterm
5866 END SUBROUTINE theta_relaxation
5868 !==============================================================================
5869 !==============================================================================
5871 SUBROUTINE sixth_order_diffusion( name, field, tendency, mu, dt, &
5873 diff_6th_opt, diff_6th_factor, &
5874 ids, ide, jds, jde, kds, kde, &
5875 ims, ime, jms, jme, kms, kme, &
5876 its, ite, jts, jte, kts, kte )
5878 ! History: 14 Nov 2006 Name of variable changed by Jason Knievel
5879 ! 07 Jun 2006 Revised and generalized by Jason Knievel
5880 ! 25 Apr 2005 Original code by Jason Knievel, NCAR
5882 ! Purpose: Apply 6th-order, monotonic (flux-limited), numerical
5883 ! diffusion to 3-d velocity and to scalars.
5885 ! References: Ming Xue (MWR Aug 2000)
5886 ! Durran ("Numerical Methods for Wave Equations..." 1999)
5887 ! George Bryan (personal communication)
5889 !------------------------------------------------------------------------------
5890 ! Begin: Declarations.
5894 INTEGER, INTENT(IN) &
5895 :: ids, ide, jds, jde, kds, kde, &
5896 ims, ime, jms, jme, kms, kme, &
5897 its, ite, jts, jte, kts, kte
5899 TYPE(grid_config_rec_type), INTENT(IN) &
5902 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(INOUT) &
5905 REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), INTENT(IN) &
5908 REAL, DIMENSION( ims:ime , jms:jme ), INTENT(IN) &
5917 INTEGER, INTENT(IN) &
5920 CHARACTER(LEN=1) , INTENT(IN) &
5931 :: dflux_x_p0, dflux_y_p0, &
5932 dflux_x_p1, dflux_y_p1, &
5933 tendency_x, tendency_y, &
5934 mu_avg_p0, mu_avg_p1, &
5940 ! End: Declarations.
5941 !------------------------------------------------------------------------------
5943 !------------------------------------------------------------------------------
5944 ! Begin: Translate the diffusion factor into a diffusion coefficient. See
5945 ! Durran's text, section 2.4.3, then adjust for sixth-order diffusion (not
5946 ! fourth) and for diffusion in two dimensions (not one). For reference, a
5947 ! factor of 1.0 would mean complete diffusion of a 2dx wave in one time step,
5948 ! although application of the flux limiter reduces somewhat the effects of
5949 ! diffusion for a given coefficient.
5951 diff_6th_coef = diff_6th_factor * 0.015625 / ( 2.0 * dt )
5953 ! End: Translate diffusion factor.
5954 !------------------------------------------------------------------------------
5956 !------------------------------------------------------------------------------
5957 ! Begin: Assign limits of spatial loops depending on variable to be diffused.
5958 ! The halo regions are already filled with values by the time this subroutine
5959 ! is called, which allows the stencil to extend beyond the domains' edges.
5961 ktf = MIN( kte, kde-1 )
5963 IF ( name .EQ. 'u' ) THEN
5968 j_end = MIN(jde-1,jte)
5972 ELSE IF ( name .EQ. 'v' ) THEN
5975 i_end = MIN(ide-1,ite)
5981 ELSE IF ( name .EQ. 'w' ) THEN
5984 i_end = MIN(ide-1,ite)
5986 j_end = MIN(jde-1,jte)
5993 i_end = MIN(ide-1,ite)
5995 j_end = MIN(jde-1,jte)
6001 ! End: Assignment of limits of spatial loops.
6002 !------------------------------------------------------------------------------
6004 !------------------------------------------------------------------------------
6005 ! Begin: Loop across spatial dimensions.
6007 DO j = j_start, j_end
6008 DO k = k_start, k_end
6009 DO i = i_start, i_end
6011 !------------------------------------------------------------------------------
6012 ! Begin: Diffusion in x (i index).
6014 ! Calculate the diffusive flux in x direction (from Xue's eq. 3).
6016 dflux_x_p0 = ( 10.0 * ( field(i, k,j) - field(i-1,k,j) ) &
6017 - 5.0 * ( field(i+1,k,j) - field(i-2,k,j) ) &
6018 + ( field(i+2,k,j) - field(i-3,k,j) ) )
6020 dflux_x_p1 = ( 10.0 * ( field(i+1,k,j) - field(i ,k,j) ) &
6021 - 5.0 * ( field(i+2,k,j) - field(i-1,k,j) ) &
6022 + ( field(i+3,k,j) - field(i-2,k,j) ) )
6024 ! If requested in the namelist (diff_6th_opt=2), prohibit up-gradient diffusion
6025 ! (variation on Xue's eq. 10).
6027 IF ( diff_6th_opt .EQ. 2 ) THEN
6029 IF ( dflux_x_p0 * ( field(i ,k,j)-field(i-1,k,j) ) .LE. 0.0 ) THEN
6033 IF ( dflux_x_p1 * ( field(i+1,k,j)-field(i ,k,j) ) .LE. 0.0 ) THEN
6039 ! Apply 6th-order diffusion in x direction.
6041 IF ( name .EQ. 'u' ) THEN
6042 mu_avg_p0 = mu(i-1,j)
6043 mu_avg_p1 = mu(i ,j)
6044 ELSE IF ( name .EQ. 'v' ) THEN
6045 mu_avg_p0 = 0.25 * ( &
6050 mu_avg_p1 = 0.25 * ( &
6056 mu_avg_p0 = 0.5 * ( &
6059 mu_avg_p1 = 0.5 * ( &
6064 tendency_x = diff_6th_coef * &
6065 ( ( mu_avg_p1 * dflux_x_p1 ) - ( mu_avg_p0 * dflux_x_p0 ) )
6067 ! End: Diffusion in x.
6068 !------------------------------------------------------------------------------
6070 !------------------------------------------------------------------------------
6071 ! Begin: Diffusion in y (j index).
6073 ! Calculate the diffusive flux in y direction (from Xue's eq. 3).
6075 dflux_y_p0 = ( 10.0 * ( field(i,k,j ) - field(i,k,j-1) ) &
6076 - 5.0 * ( field(i,k,j+1) - field(i,k,j-2) ) &
6077 + ( field(i,k,j+2) - field(i,k,j-3) ) )
6079 dflux_y_p1 = ( 10.0 * ( field(i,k,j+1) - field(i,k,j ) ) &
6080 - 5.0 * ( field(i,k,j+2) - field(i,k,j-1) ) &
6081 + ( field(i,k,j+3) - field(i,k,j-2) ) )
6083 ! If requested in the namelist (diff_6th_opt=2), prohibit up-gradient diffusion
6084 ! (variation on Xue's eq. 10).
6086 IF ( diff_6th_opt .EQ. 2 ) THEN
6088 IF ( dflux_y_p0 * ( field(i,k,j )-field(i,k,j-1) ) .LE. 0.0 ) THEN
6092 IF ( dflux_y_p1 * ( field(i,k,j+1)-field(i,k,j ) ) .LE. 0.0 ) THEN
6098 ! Apply 6th-order diffusion in y direction.
6100 IF ( name .EQ. 'u' ) THEN
6101 mu_avg_p0 = 0.25 * ( &
6106 mu_avg_p1 = 0.25 * ( &
6111 ELSE IF ( name .EQ. 'v' ) THEN
6112 mu_avg_p0 = mu(i,j-1)
6113 mu_avg_p1 = mu(i,j )
6115 mu_avg_p0 = 0.5 * ( &
6118 mu_avg_p1 = 0.5 * ( &
6123 tendency_y = diff_6th_coef * &
6124 ( ( mu_avg_p1 * dflux_y_p1 ) - ( mu_avg_p0 * dflux_y_p0 ) )
6126 ! End: Diffusion in y.
6127 !------------------------------------------------------------------------------
6129 !------------------------------------------------------------------------------
6130 ! Begin: Combine diffusion in x and y.
6132 tendency(i,k,j) = tendency(i,k,j) + tendency_x + tendency_y
6134 ! End: Combine diffusion in x and y.
6135 !------------------------------------------------------------------------------
6141 ! End: Loop across spatial dimensions.
6142 !------------------------------------------------------------------------------
6144 END SUBROUTINE sixth_order_diffusion
6146 !==============================================================================
6147 !==============================================================================
6149 END MODULE module_big_step_utilities_em