!wrf:model_layer:physics
!
!ckay=KIRAN ALAPATY @ US EPA -- November 01, 2015
!
! Tim Glotfelty@CNSU; AJ Deng@PSU
!modified for use with FASDAS
!Flux Adjusting Surface Data Assimilation System to assimilate
!surface layer and soil layers temperature and moisture using
! surfance reanalsys
!Reference: Alapaty et al., 2008: Development of the flux-adjusting surface
! data assimilation system for mesoscale models. JAMC, 47, 2331-2350
!
!
MODULE module_fdda_psufddagd 2
CONTAINS
!
!-------------------------------------------------------------------
!
SUBROUTINE fddagd(itimestep,dx,dt,xtime, & 1,12
id,analysis_interval, end_fdda_hour, &
if_no_pbl_nudging_uv, if_no_pbl_nudging_t, if_no_pbl_nudging_q, &
if_zfac_uv, k_zfac_uv, if_zfac_t, k_zfac_t, if_zfac_q, k_zfac_q, &
guv, gt, gq, if_ramping, dtramp_min, &
grid_sfdda, &
analysis_interval_sfc, end_fdda_hour_sfc, guv_sfc, gt_sfc, gq_sfc, &
rinblw, &
u3d,v3d,th3d,t3d, &
qv3d, &
p3d,pi3d, &
u_ndg_old,v_ndg_old,t_ndg_old,q_ndg_old,mu_ndg_old, &
u_ndg_new,v_ndg_new,t_ndg_new,q_ndg_new,mu_ndg_new, &
u10_ndg_old, v10_ndg_old, t2_ndg_old, th2_ndg_old, q2_ndg_old, &
rh_ndg_old, psl_ndg_old, ps_ndg_old, tob_ndg_old, odis_ndg_old, &
u10_ndg_new, v10_ndg_new, t2_ndg_new, th2_ndg_new, q2_ndg_new, &
rh_ndg_new, psl_ndg_new, ps_ndg_new, tob_ndg_new, odis_ndg_new, &
RUNDGDTEN,RVNDGDTEN,RTHNDGDTEN,RQVNDGDTEN,RMUNDGDTEN,&
fasdas, SDA_HFX, SDA_QFX, & ! fasdas
HFX_FDDA,dz8w, & ! fasdas
pblh, ht, regime, znt, z, z_at_w, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte )
!-------------------------------------------------------------------
implicit none
!-------------------------------------------------------------------
!
! This code was implemented by Aijun Deng (Penn State). The 3-D analysis nudging was comleted
! and released in December 2006. The surface analysis nudging capability was added and
! released in March 2009 with WRFV3.1.
!
!-- u3d 3d u-velocity staggered on u points
!-- v3d 3d v-velocity staggered on v points
!-- th3d 3d potential temperature (k)
!-- t3d temperature (k)
!-- qv3d 3d water vapor mixing ratio (kg/kg)
!-- p3d 3d pressure (pa)
!-- pi3d 3d exner function (dimensionless)
!-- rundgdten staggered u tendency due to
! fdda grid nudging (m/s/s)
!-- rvndgdten staggered v tendency due to
! fdda grid nudging (m/s/s)
!-- rthndgdten theta tendency due to
! fdda grid nudging (K/s)
!-- rqvndgdten qv tendency due to
! fdda grid nudging (kg/kg/s)
!-- rmundgdten mu tendency due to
! fdda grid nudging (Pa/s)
!-- ids start index for i in domain
!-- ide end index for i in domain
!-- jds start index for j in domain
!-- jde end index for j in domain
!-- kds start index for k in domain
!-- kde end index for k in domain
!-- ims start index for i in memory
!-- ime end index for i in memory
!-- jms start index for j in memory
!-- jme end index for j in memory
!-- kms start index for k in memory
!-- kme end index for k in memory
!-- its start index for i in tile
!-- ite end index for i in tile
!-- jts start index for j in tile
!-- jte end index for j in tile
!-- kts start index for k in tile
!-- kte end index for k in tile
!-------------------------------------------------------------------
!
INTEGER, INTENT(IN) :: itimestep, analysis_interval, end_fdda_hour
INTEGER, INTENT(IN) :: analysis_interval_sfc, end_fdda_hour_sfc
INTEGER, INTENT(IN) :: grid_sfdda
INTEGER, INTENT(IN) :: if_no_pbl_nudging_uv, if_no_pbl_nudging_t, &
if_no_pbl_nudging_q
INTEGER, INTENT(IN) :: if_zfac_uv, if_zfac_t, if_zfac_q
INTEGER, INTENT(IN) :: k_zfac_uv, k_zfac_t, k_zfac_q
INTEGER, INTENT(IN) :: if_ramping
INTEGER , INTENT(IN) :: id
REAL, INTENT(IN) :: DT, dx, xtime, dtramp_min
INTEGER, INTENT(IN) :: ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(IN) :: qv3d, &
p3d, &
pi3d, &
th3d, &
t3d, &
z, &
z_at_w
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(INOUT) :: rundgdten, &
rvndgdten, &
rthndgdten, &
rqvndgdten
!
! FASDAS
!
INTEGER, INTENT(IN) :: fasdas
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(INOUT) :: SDA_HFX, &
SDA_QFX
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(INOUT) :: HFX_FDDA
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(IN) :: dz8w
!
! END FASDAS
!
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(INOUT) :: rmundgdten
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(IN) :: u_ndg_old, &
v_ndg_old, &
t_ndg_old, &
q_ndg_old, &
u_ndg_new, &
v_ndg_new, &
t_ndg_new, &
q_ndg_new
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(IN) :: u10_ndg_old, &
v10_ndg_old, &
t2_ndg_old, &
th2_ndg_old, &
q2_ndg_old, &
rh_ndg_old, &
psl_ndg_old, &
ps_ndg_old, &
u10_ndg_new, &
v10_ndg_new, &
t2_ndg_new, &
th2_ndg_new, &
q2_ndg_new, &
rh_ndg_new, &
psl_ndg_new, &
ps_ndg_new
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(IN) :: tob_ndg_old, &
tob_ndg_new
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(INOUT) :: mu_ndg_old, &
mu_ndg_new
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(IN) :: odis_ndg_old, odis_ndg_new
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(IN) :: u3d, &
v3d
REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN) :: pblh, &
ht, &
regime, &
znt
REAL, INTENT(IN) :: guv, gt, gq
REAL, INTENT(IN) :: guv_sfc, gt_sfc, gq_sfc, rinblw
INTEGER :: i, j, k, itsu, jtsv, itf, jtf, ktf, i0, k0, j0
REAL :: xtime_old, xtime_new, coef, val_analysis
INTEGER :: kpbl, dbg_level
REAL :: zpbl, zagl, zagl_bot, zagl_top, tfac, actual_end_fdda_min
!BPR BEGIN
REAL :: tfac_sfc, actual_end_fdda_min_sfc
!BPR END
REAL, DIMENSION( its:ite, kts:kte, jts:jte, 4 ) :: wpbl ! 1: u, 2: v, 3: t, 4: q
REAL, DIMENSION( kts:kte, 4 ) :: wzfac ! 1: u, 2: v, 3: t, 4: q
! TWG 2015 Pseudo Radiative Flux
REAL, DIMENSION( its:ite, kts:kte, jts:jte) :: rho_air
! END TWG 2015
LOGICAL , EXTERNAL :: wrf_dm_on_monitor
CHARACTER (LEN=256) :: message
INTEGER :: int4
int4 = 1 ! 1: temporal interpolation. else: target nudging toward *_ndg_new values
actual_end_fdda_min = end_fdda_hour*60.0
!BPR BEGIN
actual_end_fdda_min_sfc = end_fdda_hour*60.0
!BPR END
IF( if_ramping == 1 .AND. dtramp_min > 0.0 ) &
actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
!BPR BEGIN
actual_end_fdda_min_sfc = end_fdda_hour_sfc*60.0 + ABS(dtramp_min)
!BPR END
!BPR BEGIN
!IF( xtime > actual_end_fdda_min ) THEN
IF( ( xtime > actual_end_fdda_min ) .AND. ( xtime > actual_end_fdda_min_sfc ) ) THEN
!BPR END
! If xtime is greater than the end time, no need to calculate tendencies. Just set the tendencies
! to zero to turn off nudging and return.
DO j = jts, jte
DO k = kts, kte
DO i = its, ite
RUNDGDTEN(i,k,j) = 0.0
RVNDGDTEN(i,k,j) = 0.0
RTHNDGDTEN(i,k,j) = 0.0
RQVNDGDTEN(i,k,j) = 0.0
IF( k .EQ. kts ) RMUNDGDTEN(i,j) = 0.
ENDDO
ENDDO
ENDDO
RETURN
ENDIF
IF( analysis_interval <= 0 )CALL wrf_error_fatal
('In grid FDDA, gfdda_interval_m must be > 0')
xtime_old = FLOOR(xtime/analysis_interval) * analysis_interval * 1.0
xtime_new = xtime_old + analysis_interval
IF( int4 == 1 ) THEN
coef = (xtime-xtime_old)/(xtime_new-xtime_old)
ELSE
coef = 1.0 ! Nudging toward a target value (*_ndg_new values)
ENDIF
IF ( wrf_dm_on_monitor()) THEN
CALL get_wrf_debug_level
( dbg_level )
IF( xtime-xtime_old < 0.5*dt/60.0 ) THEN
IF( xtime < end_fdda_hour*60.0 ) THEN
WRITE(message,'(a,i1,a,f10.3,a)') &
'D0',id,' 3-D analysis nudging reads new data at time = ', xtime, ' min.'
CALL wrf_message
( TRIM(message) )
WRITE(message,'(a,i1,a,2f8.2,a)') &
'D0',id,' 3-D analysis nudging bracketing times = ', xtime_old, xtime_new, ' min.'
CALL wrf_message
( TRIM(message) )
ENDIF
actual_end_fdda_min = end_fdda_hour*60.0
IF( if_ramping == 1 .AND. dtramp_min > 0.0 ) &
actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min ) THEN
! Find the mid point of the tile and print out the sample values
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
IF( guv > 0.0 ) THEN
DO k = kts, kte
WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
' D0',id,' sample 3-D analysis values at i,k,j=', i0, k, j0, &
' u_ndg_old=', u_ndg_old(i0,k,j0), ' u_ndg_new=', u_ndg_new(i0,k,j0)
CALL wrf_message
( TRIM(message) )
ENDDO
WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
' D0',id,' sample 3-D analysis values at i,k,j=', i0, k, j0, &
' mu_ndg_old=', mu_ndg_old(i0,j0), ' mu_ndg_new=', mu_ndg_new(i0,j0)
CALL wrf_message
( TRIM(message) )
DO k = kts, kte
WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
' D0',id,' sample 3-D analysis values at i,k,j=', i0, k, j0, &
' v_ndg_old=', v_ndg_old(i0,k,j0), ' v_ndg_new=', v_ndg_new(i0,k,j0)
CALL wrf_message
( TRIM(message) )
ENDDO
ENDIF
IF( gt > 0.0 ) THEN
DO k = kts, kte
WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
' D0',id,' sample 3-D analysis values at i,k,j=', i0, k, j0, &
' t_ndg_old=', t_ndg_old(i0,k,j0), ' t_ndg_new=', t_ndg_new(i0,k,j0)
CALL wrf_message
( TRIM(message) )
ENDDO
ENDIF
IF( gq > 0.0 ) THEN
DO k = kts, kte
WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
' D0',id,' sample 3-D analysis values at i,k,j=', i0, k, j0, &
' q_ndg_old=', q_ndg_old(i0,k,j0), ' q_ndg_new=', q_ndg_new(i0,k,j0)
CALL wrf_message
( TRIM(message) )
ENDDO
ENDIF
IF( int4 == 1 ) then
WRITE(message,'(a,i1,a)') ' D0',id, &
' 3-D nudging towards the temporally interpolated analysis'
ELSE
WRITE(message,'(a,i1,a)') ' D0',id, &
' 3-D nudging towards the target analysis'
ENDIF
ENDIF
ENDIF
ENDIF
jtsv=MAX0(jts,jds+1)
itsu=MAX0(its,ids+1)
jtf=MIN0(jte,jde-1)
ktf=MIN0(kte,kde-1)
itf=MIN0(ite,ide-1)
!
! If the user-defined namelist switches (if_no_pbl_nudging_uv, if_no_pbl_nudging_t,
! if_no_pbl_nudging_q switches) are set to 1, compute the weighting function, wpbl(:,k,:,:),
! based on the PBL depth. wpbl = 1 above the PBL and wpbl = 0 in the PBL. If all
! the switches are set to zero, wpbl = 1 (default value).
!
wpbl(:,:,:,:) = 1.0
IF( if_no_pbl_nudging_uv == 1 .OR. grid_sfdda >= 1 ) THEN
DO j=jts,jtf
DO i=itsu,itf
kpbl = 1
zpbl = 0.5 * ( pblh(i-1,j) + pblh(i,j) )
loop_ku: DO k=kts,ktf
! zagl = 0.5 * ( z(i-1,k,j)-ht(i-1,j) + z(i,k,j)-ht(i,j) )
zagl_bot = 0.5 * ( z_at_w(i-1,k, j)-ht(i-1,j) + z_at_w(i,k, j)-ht(i,j) )
zagl_top = 0.5 * ( z_at_w(i-1,k+1,j)-ht(i-1,j) + z_at_w(i,k+1,j)-ht(i,j) )
IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
kpbl = k
EXIT loop_ku
ENDIF
ENDDO loop_ku
DO k=kts,ktf
IF( k <= kpbl ) wpbl(i, k, j, 1) = 0.0
IF( k == kpbl+1 ) wpbl(i, k, j, 1) = 0.1
IF( k > kpbl+1 ) wpbl(i, k, j, 1) = 1.0
ENDDO
ENDDO
ENDDO
DO i=its,itf
DO j=jtsv,jtf
kpbl = 1
zpbl = 0.5 * ( pblh(i,j-1) + pblh(i,j) )
loop_kv: DO k=kts,ktf
! zagl = 0.5 * ( z(i,k,j-1)-ht(i,j-1) + z(i,k,j)-ht(i,j) )
zagl_bot = 0.5 * ( z_at_w(i,k, j-1)-ht(i,j-1) + z_at_w(i,k, j)-ht(i,j) )
zagl_top = 0.5 * ( z_at_w(i,k+1,j-1)-ht(i,j-1) + z_at_w(i,k+1,j)-ht(i,j) )
IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
kpbl = k
EXIT loop_kv
ENDIF
ENDDO loop_kv
DO k=kts,ktf
IF( k <= kpbl ) wpbl(i, k, j, 2) = 0.0
IF( k == kpbl+1 ) wpbl(i, k, j, 2) = 0.1
IF( k > kpbl+1 ) wpbl(i, k, j, 2) = 1.0
ENDDO
ENDDO
ENDDO
ENDIF
IF( if_no_pbl_nudging_t == 1 .OR. grid_sfdda >= 1 ) THEN
DO j=jts,jtf
DO i=its,itf
kpbl = 1
zpbl = pblh(i,j)
loop_kt: DO k=kts,ktf
! zagl = z(i,k,j)-ht(i,j)
zagl_bot = z_at_w(i,k, j)-ht(i,j)
zagl_top = z_at_w(i,k+1,j)-ht(i,j)
IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
kpbl = k
EXIT loop_kt
ENDIF
ENDDO loop_kt
DO k=kts,ktf
IF( k <= kpbl ) wpbl(i, k, j, 3) = 0.0
IF( k == kpbl+1 ) wpbl(i, k, j, 3) = 0.1
IF( k > kpbl+1 ) wpbl(i, k, j, 3) = 1.0
ENDDO
ENDDO
ENDDO
ENDIF
IF( if_no_pbl_nudging_q == 1 .OR. grid_sfdda >= 1 ) THEN
DO j=jts,jtf
DO i=its,itf
kpbl = 1
zpbl = pblh(i,j)
loop_kq: DO k=kts,ktf
! zagl = z(i,k,j)-ht(i,j)
zagl_bot = z_at_w(i,k, j)-ht(i,j)
zagl_top = z_at_w(i,k+1,j)-ht(i,j)
IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
kpbl = k
EXIT loop_kq
ENDIF
ENDDO loop_kq
DO k=kts,ktf
IF( k <= kpbl ) wpbl(i, k, j, 4) = 0.0
IF( k == kpbl+1 ) wpbl(i, k, j, 4) = 0.1
IF( k > kpbl+1 ) wpbl(i, k, j, 4) = 1.0
ENDDO
ENDDO
ENDDO
ENDIF
!
! If the user-defined namelist switches (if_zfac_uv, if_zfac_t,
! if_zfac_q swithes) are set to 1, compute the weighting function, wzfac(k,:),
! based on the namelist specified k values (k_zfac_uv, k_zfac_t and k_zfac_q) below which analysis
! nudging is turned off (wzfac = 1 above k_zfac_x and = 0 in below k_zfac_x). If all
! the switche are set to zero, wzfac = 1 (default value).
!
wzfac(:,:) = 1.0
IF( if_zfac_uv == 1 ) THEN
DO j=jts,jtf
DO i=itsu,itf
DO k=kts,ktf
IF( k <= k_zfac_uv ) wzfac(k, 1:2) = 0.0
IF( k == k_zfac_uv+1 ) wzfac(k, 1:2) = 0.1
IF( k > k_zfac_uv+1 ) wzfac(k, 1:2) = 1.0
ENDDO
ENDDO
ENDDO
ENDIF
IF( if_zfac_t == 1 ) THEN
DO j=jts,jtf
DO i=itsu,itf
DO k=kts,ktf
IF( k <= k_zfac_t ) wzfac(k, 3) = 0.0
IF( k == k_zfac_t+1 ) wzfac(k, 3) = 0.1
IF( k > k_zfac_t+1 ) wzfac(k, 3) = 1.0
ENDDO
ENDDO
ENDDO
ENDIF
IF( if_zfac_q == 1 ) THEN
DO j=jts,jtf
DO i=itsu,itf
DO k=kts,ktf
IF( k <= k_zfac_q ) wzfac(k, 4) = 0.0
IF( k == k_zfac_q+1 ) wzfac(k, 4) = 0.1
IF( k > k_zfac_q+1 ) wzfac(k, 4) = 1.0
ENDDO
ENDDO
ENDDO
ENDIF
!
! If if_ramping and dtramp_min are defined by user, compute a time weighting function, tfac,
! for analysis nudging so that at the end of the nudging period (which has to be at a
! analysis time) we ramp down the nudging coefficient, based on the use-defined sign of dtramp_min.
!
! When dtramp_min is negative, ramping ends at end_fdda_hour and starts at
! end_fdda_hour-ABS(dtramp_min).
!
! When dtramp_min is positive, ramping starts at end_fdda_hour and ends at
! end_fdda_hour+ABS(dtramp_min).
! BPR BEGIN
! In this case, during the rampdown we nudge towards the most recent past analysis and ignore
! the future analysis (implemented by setting coef = 0.0)
! THE FOLLOWING COMMENT IS NO LONGER APPLICABLE
! In this case, the obs values are extrapolated using
! the obs tendency saved from the previous FDDA window. More specifically for extrapolation,
! coef (see codes below) is recalculated to reflect extrapolation during the ramping period.
! THE PRECEDING COMMENT IS NOT LONGER APPLICABLE
! BPR END
!
tfac = 1.0
!BPR BEGIN
tfac_sfc = 1.0
!BPR END
IF( if_ramping == 1 .AND. ABS(dtramp_min) > 0.0 ) THEN
IF( dtramp_min <= 0.0 ) THEN
actual_end_fdda_min = end_fdda_hour*60.0
ELSE
actual_end_fdda_min = end_fdda_hour*60.0 + dtramp_min
ENDIF
IF( xtime < actual_end_fdda_min-ABS(dtramp_min) )THEN
tfac = 1.0
ELSEIF( xtime >= actual_end_fdda_min-ABS(dtramp_min) .AND. xtime <= actual_end_fdda_min )THEN
tfac = ( actual_end_fdda_min - xtime ) / ABS(dtramp_min)
!BPR BEGIN
!The original method assumed that to be here in the code with dtramp_min>0
!meant that we were after the valid time of *_ndg_new and so used the
!values *_ndg_old and *_ndg_new to extrapolate a current analysis value.
!HOWEVER, in practice once we get to the valid time of *_ndg_new WRF will
!read in the next pair of *_ndg_old and *_ndg_new values, even if we are
!at the beginning of the rampdown period. Since the *_ndg_new values have
!a valid time after the beginning of the rampdown period we do not want
!to use them as we would be using analyses valid after the supposed end
!time of the analysis nudging.
!IF( dtramp_min > 0.0 ) coef = (xtime-xtime_old+analysis_interval)/(analysis_interval*1.0)
!Use only the *_ndg_old values
IF( dtramp_min > 0.0 ) coef = 0.0
!BPR END
ELSE
tfac = 0.0
ENDIF
!BPR BEGIN
!Now calculate the same quantities for surface analysis nudging
!Add actual_end_fdda_min_sfc, tfac_sfc
IF( dtramp_min <= 0.0 ) THEN
actual_end_fdda_min_sfc = end_fdda_hour_sfc*60.0
ELSE
actual_end_fdda_min_sfc = end_fdda_hour_sfc*60.0 + dtramp_min
ENDIF
IF( xtime < actual_end_fdda_min_sfc-ABS(dtramp_min) )THEN
tfac_sfc = 1.0
ELSEIF( xtime >= actual_end_fdda_min_sfc-ABS(dtramp_min) .AND. xtime <= actual_end_fdda_min_sfc )THEN
tfac_sfc = ( actual_end_fdda_min_sfc - xtime ) / ABS(dtramp_min)
ELSE
tfac_sfc = 0.0
ENDIF
!BPR END
ENDIF
!
! Surface Analysis Nudging
!
IF( grid_sfdda >= 1 ) THEN
CALL SFDDAGD
(itimestep,dx,dt,xtime, id, &
analysis_interval_sfc, end_fdda_hour_sfc, guv_sfc, gt_sfc, gq_sfc, &
rinblw, &
u3d,v3d,th3d,t3d, &
qv3d, &
p3d,pi3d, &
u10_ndg_old, v10_ndg_old, t2_ndg_old, th2_ndg_old, q2_ndg_old, &
rh_ndg_old, psl_ndg_old, ps_ndg_old, tob_ndg_old, odis_ndg_old, &
u10_ndg_new, v10_ndg_new, t2_ndg_new, th2_ndg_new, q2_ndg_new, &
rh_ndg_new, psl_ndg_new, ps_ndg_new, tob_ndg_new, odis_ndg_new, &
RUNDGDTEN,RVNDGDTEN,RTHNDGDTEN,RQVNDGDTEN,RMUNDGDTEN,&
pblh, ht, regime, znt, z, z_at_w, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte, wpbl, wzfac, if_ramping, dtramp_min, &
!BPR BEGIN
! actual_end_fdda_min, tfac &
actual_end_fdda_min_sfc, tfac_sfc &
!BPR END
!
! FASDAS
!
,fasdas, SDA_HFX, SDA_QFX &
!
! END FASDAS
!
)
ENDIF
!
! Compute 3-D nudging tendencies for u, v, t and q
!
DO j=jts,jtf
DO k=kts,ktf
DO i=itsu,itf
val_analysis = u_ndg_old(i,k,j) *( 1.0 - coef ) + u_ndg_new(i,k,j) * coef
RUNDGDTEN(i,k,j) = RUNDGDTEN(i,k,j) + guv * wpbl(i,k,j,1) * wzfac(k,1) * tfac * &
( val_analysis - u3d(i,k,j) )
ENDDO
ENDDO
ENDDO
DO j=jtsv,jtf
DO k=kts,ktf
DO i=its,itf
val_analysis = v_ndg_old(i,k,j) *( 1.0 - coef ) + v_ndg_new(i,k,j) * coef
RVNDGDTEN(i,k,j) = RVNDGDTEN(i,k,j) + guv * wpbl(i,k,j,2) * wzfac(k,2) * tfac * &
( val_analysis - v3d(i,k,j) )
ENDDO
ENDDO
ENDDO
DO j=jts,jtf
DO k=kts,ktf
DO i=its,itf
val_analysis = t_ndg_old(i,k,j) *( 1.0 - coef ) + t_ndg_new(i,k,j) * coef
RTHNDGDTEN(i,k,j) = RTHNDGDTEN(i,k,j) + gt * wpbl(i,k,j,3) * wzfac(k,3) * tfac * &
( val_analysis - th3d(i,k,j) + 300.0 )
!
!FASDAS
!
!TWG 2015 Pseudo Radiative Flux
rho_air(i,k,j) = p3d(i,k,j)/(287.0*th3d(i,k,j))
HFX_FDDA(i,k,j) = rho_air(i,k,j)*1004.0*RTHNDGDTEN(i,k,j)*dz8w(i,k,j)
!TWG 2015 END
!
!END FASDAS
!
val_analysis = q_ndg_old(i,k,j) *( 1.0 - coef ) + q_ndg_new(i,k,j) * coef
RQVNDGDTEN(i,k,j) = RQVNDGDTEN(i,k,j) + gq * wpbl(i,k,j,4) * wzfac(k,4) * tfac * &
( val_analysis - qv3d(i,k,j) )
ENDDO
ENDDO
ENDDO
!BPR BEGIN
!Diagnostic print
IF ( wrf_dm_on_monitor()) THEN
IF( dbg_level .GE. 10 ) THEN
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
k0 = (kte-kts)/2+kts
WRITE(message,'(a,i1,a,f7.2,a,i4,a,i4,a,i4,a,f7.2,a,f4.2,a,f7.2,a,f4.2,a,f4.2 )') &
' D0',id,' At xtime=',xtime,' FDDA sample pot. temp. analysis (i=',i0,', j=',j0,' k=', &
k0,') = (t_ndg_old=', t_ndg_old(i0,k0,j0),') * ',1.0-coef,' + (t_ndg_new=', &
t_ndg_new(i0,k0,j0),') * ',coef, ' where tfac=',tfac
CALL wrf_message
( TRIM(message) )
WRITE(message,'(a,i1,a,f7.2,a,i4,a,f7.2,a,f7.2)') &
' D0',id,' xtime_old=',xtime_old,' analysis_interval=',analysis_interval,' actual_end_fdda_min=', &
actual_end_fdda_min,' dtramp_min=',dtramp_min
CALL wrf_message
( TRIM(message) )
END IF
END IF
!BPR END
END SUBROUTINE fddagd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE sfddagd(itimestep,dx,dt,xtime, & 1,21
id, analysis_interval_sfc, end_fdda_hour_sfc, &
guv_sfc, gt_sfc, gq_sfc, rinblw, &
u3d,v3d,th3d,t3d, &
qv3d, &
p3d,pi3d, &
u10_ndg_old, v10_ndg_old, t2_ndg_old, th2_ndg_old, q2_ndg_old, &
rh_ndg_old, psl_ndg_old, ps_ndg_old, tob_ndg_old, odis_ndg_old, &
u10_ndg_new, v10_ndg_new, t2_ndg_new, th2_ndg_new, q2_ndg_new, &
rh_ndg_new, psl_ndg_new, ps_ndg_new, tob_ndg_new, odis_ndg_new, &
RUNDGDTEN,RVNDGDTEN,RTHNDGDTEN,RQVNDGDTEN,RMUNDGDTEN, &
pblh, ht, regime, znt, z, z_at_w, &
ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte, wpbl, wzfac, if_ramping, dtramp_min, &
!BPR BEGIN
! actual_end_fdda_min, tfac &
actual_end_fdda_min_sfc, tfac_sfc &
!BPR END
!
! FASDAS
!
,fasdas, SDA_HFX, SDA_QFX &
!
! END FASDAS
!
)
!-------------------------------------------------------------------
USE module_model_constants
implicit none
!-------------------------------------------------------------------
!
! This code was implemented by Aijun Deng (Penn State). The 3-D analysis nudging was comleted
! and released in December 2006. The surface analysis nudging capability was added and
! released in March 2009 with WRFV3.1.
!
!-- u3d 3d u-velocity staggered on u points
!-- v3d 3d v-velocity staggered on v points
!-- th3d 3d potential temperature (k)
!-- t3d temperature (k)
!-- qv3d 3d water vapor mixing ratio (kg/kg)
!-- p3d 3d pressure (pa)
!-- pi3d 3d exner function (dimensionless)
!-- rundgdten staggered u tendency due to
! fdda grid nudging (m/s/s)
!-- rvndgdten staggered v tendency due to
! fdda grid nudging (m/s/s)
!-- rthndgdten theta tendency due to
! fdda grid nudging (K/s)
!-- rqvndgdten qv tendency due to
! fdda grid nudging (kg/kg/s)
!-- rmundgdten mu tendency due to
! fdda grid nudging (Pa/s)
!-- ids start index for i in domain
!-- ide end index for i in domain
!-- jds start index for j in domain
!-- jde end index for j in domain
!-- kds start index for k in domain
!-- kde end index for k in domain
!-- ims start index for i in memory
!-- ime end index for i in memory
!-- jms start index for j in memory
!-- jme end index for j in memory
!-- kms start index for k in memory
!-- kme end index for k in memory
!-- its start index for i in tile
!-- ite end index for i in tile
!-- jts start index for j in tile
!-- jte end index for j in tile
!-- kts start index for k in tile
!-- kte end index for k in tile
!-------------------------------------------------------------------
!
INTEGER, INTENT(IN) :: itimestep, analysis_interval_sfc, end_fdda_hour_sfc
INTEGER , INTENT(IN) :: id
REAL, INTENT(IN) :: dx,DT, xtime
INTEGER, INTENT(IN) :: ids,ide, jds,jde, kds,kde, &
ims,ime, jms,jme, kms,kme, &
its,ite, jts,jte, kts,kte
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(IN) :: qv3d, &
p3d, &
pi3d, &
th3d, &
t3d, &
z, &
z_at_w
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(INOUT) :: rundgdten, &
rvndgdten, &
rthndgdten, &
rqvndgdten
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(INOUT) :: rmundgdten
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(IN) :: u10_ndg_old, &
v10_ndg_old, &
t2_ndg_old, &
th2_ndg_old, &
q2_ndg_old, &
rh_ndg_old, &
psl_ndg_old, &
ps_ndg_old, &
u10_ndg_new, &
v10_ndg_new, &
t2_ndg_new, &
th2_ndg_new, &
q2_ndg_new, &
rh_ndg_new, &
psl_ndg_new, &
ps_ndg_new
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(IN) :: tob_ndg_old, &
tob_ndg_new
REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
INTENT(IN) :: u3d, &
v3d
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT(IN) :: odis_ndg_old, odis_ndg_new
REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN) :: pblh, &
ht, &
regime, &
znt
REAL, INTENT(IN) :: guv_sfc, gt_sfc, gq_sfc, rinblw
INTEGER :: i, j, k, itsu, jtsv, itf, jtf, ktf, i0, j0
REAL :: xtime_old_sfc, xtime_new_sfc, coef, val_analysis, es
INTEGER :: kpbl, dbg_level
REAL :: zpbl, zagl, zagl_bot, zagl_top, tfac_sfc, actual_end_fdda_min_sfc
REAL, DIMENSION( its:ite, kts:kte, jts:jte, 4 ), &
INTENT(INout) :: wpbl ! 1: u, 2: v, 3: t, 4: q
REAL, DIMENSION( kts:kte, 4 ), &
INTENT(IN) :: wzfac ! 1: u, 2: v, 3: t, 4: q
REAL, DIMENSION( its:ite, jts:jte) :: wndcor_u, wndcor_v
REAL, DIMENSION( its-2:ite+2, jts-2:jte+2) :: blw_old, blw_new
REAL, DIMENSION( its:ite, kts:kte, jts:jte) :: qsat
REAL :: m, b=1.8, blw, rindx, x
REAL :: difz, wr14, wr1z, wr24, wr2z, wndfac, reg, znt0
INTEGER, INTENT(IN) :: if_ramping
REAL, INTENT(IN) :: dtramp_min
LOGICAL , EXTERNAL :: wrf_dm_on_monitor
CHARACTER (LEN=256) :: message
INTEGER :: iwinds, idd, iqsat, int4
!
! FASDAS
!
INTEGER, INTENT(IN) :: fasdas
REAL, DIMENSION( ims:ime, jms:jme ), &
INTENT( OUT) :: SDA_HFX, &
SDA_QFX
REAL :: stabFac, exf, DiffTN
REAL, DIMENSION( its:ite, kts:kte, jts:jte ) :: wpblfasdas
!
! END FASDAS
!
iwinds = 1 ! 1: Scale the surface wind analysis to the lowest model level,
! if the first model half-layer is greater than 10 meters
! and we are in the free convection regime (REGIME=4.0). else: no
idd = 1 ! 1: Obs data density correction is applied. else: no
iqsat = 1 ! 1: Remove super saturation. eles: no
int4 = 1 ! 1: temporal ionterpolation. else: target nudging toward *_ndg_new values
IF( analysis_interval_sfc <= 0 )CALL wrf_error_fatal
('In grid sfc FDDA, sgfdda_interval_m must be > 0')
xtime_old_sfc = FLOOR(xtime/analysis_interval_sfc) * analysis_interval_sfc * 1.0
xtime_new_sfc = xtime_old_sfc + analysis_interval_sfc
IF( int4 == 1 ) THEN
coef = (xtime-xtime_old_sfc)/(xtime_new_sfc-xtime_old_sfc) ! Temporal interpolation
ELSE
coef = 1.0 ! Nudging toward a target value (*_ndg_new values)
ENDIF
IF ( wrf_dm_on_monitor()) THEN
CALL get_wrf_debug_level
( dbg_level )
IF( xtime-xtime_old_sfc < 0.5*dt/60.0 ) THEN
IF( xtime < end_fdda_hour_sfc*60.0 ) THEN
WRITE(message,'(a,i1,a,f10.3,a)') &
'D0',id,' surface analysis nudging reads new data at time = ', xtime, ' min.'
CALL wrf_message
( TRIM(message) )
WRITE(message,'(a,i1,a,2f8.2,a)') &
'D0',id,' surface analysis nudging bracketing times = ', xtime_old_sfc, xtime_new_sfc, ' min.'
CALL wrf_message
( TRIM(message) )
ENDIF
IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min_sfc ) THEN
! Find the mid point of the tile and print out the sample values
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
IF( guv_sfc > 0.0 ) THEN
WRITE(message,'(a,i1,a,2i4,a,f10.4,a,f10.4)') &
' D0',id,' sample surface analysis values at i,j=', i0, j0, &
' u10_ndg_old=', u10_ndg_old(i0,j0), ' u10_ndg_new=', u10_ndg_new(i0,j0)
CALL wrf_message
( TRIM(message) )
WRITE(message,'(a,i1,a,2i4,a,f10.4,a,f10.4)') &
' D0',id,' sample surface analysis values at i,j=', i0, j0, &
' v10_ndg_old=', v10_ndg_old(i0,j0), ' v10_ndg_new=', v10_ndg_new(i0,j0)
CALL wrf_message
( TRIM(message) )
ENDIF
IF( gt_sfc > 0.0 ) THEN
WRITE(message,'(a,i1,a,2i4,a,f10.4,a,f10.4)') &
' D0',id,' sample surface analysis values at i,j=', i0, j0, &
' th2_ndg_old=', th2_ndg_old(i0,j0), ' th2_ndg_new=', th2_ndg_new(i0,j0)
CALL wrf_message
( TRIM(message) )
ENDIF
IF( gq_sfc > 0.0 ) THEN
WRITE(message,'(a,i1,a,2i4,a,f10.4,a,f10.4)') &
' D0',id,' sample surface analysis values at i,j=', i0, j0, &
' q2_ndg_old=', q2_ndg_old(i0,j0), ' q2_ndg_new=', q2_ndg_new(i0,j0)
CALL wrf_message
( TRIM(message) )
ENDIF
IF( iwinds == 1 ) &
WRITE(message,'(a,i1,a)') ' D0',id, &
' surface wind analysis s scaled to the lowest model level, if dz1 > 10m and REGIME=4.'
IF( idd == 1 ) &
WRITE(message,'(a,i1,a)') ' D0',id, &
' obs data density is used for additional weighting function'
IF( iqsat == 1 ) &
WRITE(message,'(a,i1,a)') ' D0',id, &
' super saturation is not allowed for q analysis'
IF( int4 == 1 ) then
WRITE(message,'(a,i1,a)') ' D0',id, &
' surface nudging towards the temporally interpolated analysis'
ELSE
WRITE(message,'(a,i1,a)') ' D0',id, &
' surface nudging towards the target analysis'
ENDIF
ENDIF
ENDIF
ENDIF
jtsv=MAX0(jts,jds+1)
itsu=MAX0(its,ids+1)
jtf=MIN0(jte,jde-1)
ktf=MIN0(kte,kde-1)
itf=MIN0(ite,ide-1)
!
! Compute the vertical weighting function to scale the surface wind analysis to
! the lowest model level, if the first model half-layer is greater
! than 10 meters and we are in the free convection regime (REGIME=4.0).
!
IF( iwinds == 1 ) THEN
wndcor_u(:,:) = 1.0
DO j=jts,jtf
DO i=itsu,itf
reg = 0.5 * ( regime(i-1, j) + regime(i, j) )
difz = 0.5 * ( z(i-1,1,j) - ht(i-1,j) &
+ z(i, 1,j) - ht(i, j) )
IF( reg > 3.5 .AND. difz > 10.0 ) THEN
znt0 = 0.5 * ( znt(i-1, j) + znt(i, j) )
IF( znt0 <= 0.2) THEN
wndcor_u(i,j) = 1.0+0.320*znt0**0.2
ELSE
wndcor_u(i,j) = 1.169+0.315*znt0
ENDIF
wr14 = log(40.0/0.05)
wr1z = log(difz/0.05)
wr24 = log(40.0/1.0)
wr2z = log(difz/1.0)
wndfac = 0.5*(WR1Z/WR14+WR2Z/WR24)
wndcor_u(i,j) = wndfac*wndcor_u(i,j)
ENDIF
ENDDO
ENDDO
IF ( wrf_dm_on_monitor()) THEN
IF( xtime-xtime_old_sfc < 0.5*dt/60.0 ) THEN
IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min_sfc ) THEN
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
WRITE(message,'(a,i1,a,2i4,a,f10.4)') &
' D0',id,' sample wndcor_u values at i,j=', i0, j0, &
' wndcor_u=', wndcor_u(i0,j0)
CALL wrf_message
( TRIM(message) )
ENDIF
ENDIF
ENDIF
ELSE
wndcor_u(:,:) = 1.0
ENDIF
IF( iwinds == 1 ) THEN
wndcor_v(:,:) = 1.0
DO j=jtsv,jtf
DO i=its,itf
reg = 0.5 * ( regime(i, j-1) + regime(i, j) )
difz = 0.5 * ( z(i,1,j-1) - ht(i,j-1) &
+ z(i,1,j ) - ht(i,j ) )
IF( reg > 3.5 .AND. difz > 10.0 ) THEN
znt0 = 0.5 * ( znt(i, j-1) + znt(i, j) )
IF( znt0 <= 0.2) THEN
wndcor_v(i,j) = 1.0+0.320*znt0**0.2
ELSE
wndcor_v(i,j) = 1.169+0.315*znt0
ENDIF
wr14 = log(40.0/0.05)
wr1z = log(difz/0.05)
wr24 = log(40.0/1.0)
wr2z = log(difz/1.0)
wndfac = 0.5*(WR1Z/WR14+WR2Z/WR24)
wndcor_v(i,j) = wndfac*wndcor_v(i,j)
ENDIF
ENDDO
ENDDO
IF ( wrf_dm_on_monitor()) THEN
IF( xtime-xtime_old_sfc < 0.5*dt/60.0 ) THEN
IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min_sfc ) THEN
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
WRITE(message,'(a,i1,a,2i4,a,f10.4)') &
' D0',id,' sample wndcor_v values at i,j=', i0, j0, &
' wndcor_v=', wndcor_v(i0,j0)
CALL wrf_message
( TRIM(message) )
ENDIF
ENDIF
ENDIF
ELSE
wndcor_v(:,:) = 1.0
ENDIF
!
! Compute saturation mixing ratio so that nudging to a super-saturated state
! is not allowed.
!
IF( iqsat == 1 ) THEN
DO j=jts,jtf
DO k=kts,ktf
DO i=its,itf
es = SVP1*EXP(SVP2*(t3d(i,k,j)-SVPT0)/(t3d(i,k,j)-SVP3)) * 10.0 ! mb
qsat(i,k,j) = EP_2*es/(p3d(i,k,j)/100.0-es)
ENDDO
ENDDO
ENDDO
IF ( wrf_dm_on_monitor()) THEN
IF( xtime-xtime_old_sfc < 0.5*dt/60.0 ) THEN
IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min_sfc ) THEN
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
DO k = kts, kte
WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
' D0',id,' sample moisture values (g/kg) at i,k,j=', i0, k, j0, &
' qv3d=', qv3d(i0,k,j0)*1000.0, ' qsat=', qsat(i0,k,j0)*1000.0
CALL wrf_message
( TRIM(message) )
ENDDO
ENDIF
ENDIF
ENDIF
ENDIF
!
! Obs data density weighting.
!
IF( idd == 1 ) THEN
IF( rinblw < 0.001 ) THEN
IF ( wrf_dm_on_monitor()) THEN
WRITE(message,'(a)') 'Error in rinblw, please specify a reasonable value ***'
CALL wrf_message
( TRIM(message) )
ENDIF
CALL wrf_error_fatal
('In grid FDDA')
ENDIF
rindx = rinblw*1000.0/dx
m = -0.8*2.0/rindx
DO j=MAX(jts-2,jds),MIN(jte+2,jde-1)
DO i=MAX(its-2,ids),MIN(ite+2,ide-1)
IF( odis_ndg_old(i,j) < 0.5*rinblw ) THEN
blw_old(i,j) = 1.0
ELSE
x = min( odis_ndg_old(i,j)*1000./dx, rindx )
blw_old(i,j) = m * x + b
ENDIF
IF( odis_ndg_new(i,j) < 0.5*rinblw ) THEN
blw_new(i,j) = 1.0
ELSE
x = min( odis_ndg_new(i,j)*1000./dx, rindx )
blw_new(i,j) = m * x + b
ENDIF
ENDDO
ENDDO
! Smoother applies one point outside the tile, but one point in from boundaries
CALL smther
(blw_old, its-2,ite+2, jts-2,jte+2, 1, &
MAX(its-1,ids+1), MIN(ite+1,ide-2), MAX(jts-1,jds+1), MIN(jte+1,jde-2))
CALL smther
(blw_new, its-2,ite+2, jts-2,jte+2, 1, &
MAX(its-1,ids+1), MIN(ite+1,ide-2), MAX(jts-1,jds+1), MIN(jte+1,jde-2))
WHERE ( blw_old > 1.0)
blw_old = 1.0
END WHERE
WHERE ( blw_new > 1.0)
blw_new = 1.0
END WHERE
WHERE ( blw_old < 0.0)
blw_old = 0.0
END WHERE
WHERE ( blw_new < 0.0)
blw_new = 0.0
END WHERE
IF ( wrf_dm_on_monitor()) THEN
IF( xtime-xtime_old_sfc < 0.5*dt/60.0 ) THEN
IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min_sfc ) THEN
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
WRITE(message,'(a,i1,a,2i4,4(a,f10.4))') &
' D0',id,' sample blw values at i,j=', i0, j0, &
' odis_ndg_old=', odis_ndg_old(i0,j0), ' km odis_ndg_new=', odis_ndg_new(i0,j0), &
' km blw_old=', blw_old(i0,j0), ' blw_new=', blw_new(i0,j0)
CALL wrf_message
( TRIM(message) )
ENDIF
ENDIF
ENDIF
ENDIF
!
! tfac_sfc for surface analysis nudging
!
IF( xtime >= actual_end_fdda_min_sfc-ABS(dtramp_min) .AND. xtime <= actual_end_fdda_min_sfc &
.AND. dtramp_min > 0.0 .AND. if_ramping == 1 ) &
!BPR BEGIN
!The original method assumed that to be here in the code with dtramp_min>0
!meant that we were after the valid time of *_ndg_new and so used the
!values *_ndg_old and *_ndg_new to extrapolate a current analysis value.
!HOWEVER, in practice once we get to the valid time of *_ndg_new WRF will
!read in the next pair of *_ndg_old and *_ndg_new values, even if we are
!at the beginning of the rampdown period. Since the *_ndg_new values have
!a valid time after the beginning of the rampdown period we do not want
!to use them as we would be using analyses valid after the supposed end
!time of the analysis nudging.
!coef = (xtime-xtime_old_sfc+analysis_interval_sfc)/(analysis_interval_sfc*1.0)
!Use only the *_ndg_old values
coef = 0.0
!BPR END
! print*, 'coef =', xtime_old_sfc, xtime, xtime_new_sfc, coef
!
! Compute surface analysis nudging tendencies for u, v, t and q
!
! FASDAS
!
IF( fasdas == 1 ) THEN
!Edit TWG2015 Add new variable wpblfasdas to avoid altering global wpbl
!field when using the FASDAS option
wpblfasdas = 1.0
DO j=jts,jtf
DO k=kts,ktf
DO i=its,itf
if( k == 1 ) then
wpblfasdas(i, k, j) = 0.0
else
wpblfasdas(i, k, j) = 1.0
endif
ENDDO
ENDDO
ENDDO
ENDIF
!
! END FASDAS
!
DO j=jts,jtf
DO k=kts,ktf
DO i=itsu,itf
IF( idd == 1 ) THEN
blw = 0.5* (blw_old(i-1,j)+blw_old(i,j)) * ( 1.0 - coef ) &
+ 0.5* (blw_new(i-1,j)+blw_new(i,j)) * coef
ELSE
blw = 1.0
ENDIF
val_analysis = u10_ndg_old(i,j) *( 1.0 - coef ) + u10_ndg_new(i,j) * coef
val_analysis = val_analysis * wndcor_u(i,j)
RUNDGDTEN(i,k,j) = guv_sfc * (1.0-wpbl(i,k,j,1)) * wzfac(k,1) * tfac_sfc * blw * &
( val_analysis - u3d(i,1,j) )
ENDDO
ENDDO
ENDDO
DO j=jtsv,jtf
DO k=kts,ktf
DO i=its,itf
IF( idd == 1 ) THEN
blw = 0.5* (blw_old(i,j-1)+blw_old(i,j)) * ( 1.0 - coef ) &
+ 0.5* (blw_new(i,j-1)+blw_new(i,j)) * coef
ELSE
blw = 1.0
ENDIF
val_analysis = v10_ndg_old(i,j) *( 1.0 - coef ) + v10_ndg_new(i,j) * coef
val_analysis = val_analysis * wndcor_v(i,j)
RVNDGDTEN(i,k,j) = guv_sfc * (1.0-wpbl(i,k,j,2)) * wzfac(k,2) * tfac_sfc * blw * &
( val_analysis - v3d(i,1,j) )
ENDDO
ENDDO
ENDDO
DO j=jts,jtf
DO k=kts,ktf
DO i=its,itf
IF( idd == 1 ) THEN
blw = blw_old(i,j) * ( 1.0 - coef ) + blw_new(i,j) * coef
ELSE
blw = 1.0
ENDIF
!ckay2015 and TWG2015 add stability factor for stable regime, ensure
!consistency between Direct and Indirect nudging, and Convert potential
!temperature tendency to temperature tendency
!
! FASDAS
!
IF( fasdas == 1 ) THEN
if(regime(i,j).le.1.1) then
stabFac = 1.0/3.0
else
stabFac = 1.0
end if
val_analysis = th2_ndg_old(i,j) *( 1.0 - coef ) + th2_ndg_new(i,j) * coef
!BPR BEGIN
!RTHNDGDTEN(i,k,j) = stabFac*gt_sfc * (1.0-wpblfasdas(i,k,j)) * wzfac(k,3) * tfac * blw * &
RTHNDGDTEN(i,k,j) = stabFac*gt_sfc * (1.0-wpblfasdas(i,k,j)) * wzfac(k,3) * tfac_sfc * blw * &
!BPR END
( val_analysis - th3d(i,1,j))
DiffTN = val_analysis - th3d(i,1,j)
if(k.eq.1) then
exf = (1.0E05/p3d(i,k,j))**(287./1004.)
SDA_HFX(i,j) = RTHNDGDTEN(i,k,j)/exf !TWG 2015
else
RTHNDGDTEN(i,k,j) = 0.0
end if
val_analysis = q2_ndg_old(i,j) *( 1.0 - coef ) + q2_ndg_new(i,j) * coef
IF( iqsat == 1 .AND. val_analysis > qsat(i,k,j) ) val_analysis = qsat
(i,k,j)
!BPR BEGIN
!RQVNDGDTEN(i,k,j) = stabFac*gq_sfc * (1.0-wpblfasdas(i,k,j)) * wzfac(k,4) * tfac * blw * &
RQVNDGDTEN(i,k,j) = stabFac*gq_sfc * (1.0-wpblfasdas(i,k,j)) * wzfac(k,4) * tfac_sfc * blw * &
!BPR END
( val_analysis - qv3d(i,k,j) )
if(k.eq.1) then
SDA_QFX(i,j) = RQVNDGDTEN(i,k,j)
else
RQVNDGDTEN(i,k,j) = 0.0
end if
ELSE
val_analysis = th2_ndg_old(i,j) *( 1.0 - coef ) + th2_ndg_new(i,j) * coef
!BPR BEGIN
!RTHNDGDTEN(i,k,j) = gt_sfc * (1.0-wpbl(i,k,j,3)) * wzfac(k,3) * tfac * blw * &
RTHNDGDTEN(i,k,j) = gt_sfc * (1.0-wpbl(i,k,j,3)) * wzfac(k,3) * tfac_sfc * blw * &
!BPR END
( val_analysis - th3d(i,1,j))
val_analysis = q2_ndg_old(i,j) *( 1.0 - coef ) + q2_ndg_new(i,j) * coef
IF( iqsat == 1 .AND. val_analysis > qsat(i,k,j) ) val_analysis = qsat
(i,k,j)
!BPR BEGIN
!RQVNDGDTEN(i,k,j) = gq_sfc * (1.0-wpbl(i,k,j,4)) * wzfac(k,4) * tfac * blw * &
RQVNDGDTEN(i,k,j) = gq_sfc * (1.0-wpbl(i,k,j,4)) * wzfac(k,4) * tfac_sfc * blw * &
!BPR END
( val_analysis - qv3d(i,k,j) )
ENDIF
!
! END FASDAS
!
ENDDO
ENDDO
ENDDO
!BPR BEGIN
!Diagnostic print
IF ( wrf_dm_on_monitor()) THEN
IF( dbg_level .GE. 10 ) THEN
i0 = (ite-its)/2+its
j0 = (jte-jts)/2+jts
WRITE(message,'(a,i1,a,f7.2,a,i4,a,i4,a,f7.2,a,f4.2,a,f7.2,a,f4.2,a,f4.2 )') &
' D0',id,' At xtime=',xtime,' SFC FDDA sample TH2 analysis (i=',i0,', j=',j0,') = (th2_ndg_old=', &
th2_ndg_old(i0,j0),') * ',1.0-coef,' + (th2_ndg_new=',th2_ndg_new(i0,j0),') * ',coef, &
' where tfac_sfc=',tfac_sfc
CALL wrf_message
( TRIM(message) )
WRITE(message,'(a,i1,a,f7.2,a,i4,a,f7.2,a,f7.2)') &
' D0',id,' xtime_old_sfc=',xtime_old_sfc,' analysis_interval_sfc=',analysis_interval_sfc, &
' actual_end_fdda_min_sfc=', actual_end_fdda_min_sfc,' dtramp_min=',dtramp_min
CALL wrf_message
( TRIM(message) )
END IF
END IF
!BPR END
END SUBROUTINE sfddagd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE fddagdinit(id,rundgdten,rvndgdten,rthndgdten,rqvndgdten,rmundgdten,& 1,26
SDA_HFX, SDA_QFX, QNORM, HFX_BOTH, QFX_BOTH, fasdas,& !fasdas
HFX_FDDA, & !fasdas
run_hours, &
if_no_pbl_nudging_uv, if_no_pbl_nudging_t, if_no_pbl_nudging_q, &
if_zfac_uv, k_zfac_uv, if_zfac_t, k_zfac_t, if_zfac_q, k_zfac_q, &
guv, gt, gq, if_ramping, dtramp_min, end_fdda_hour, &
grid_sfdda, guv_sfc, gt_sfc, gq_sfc, &
restart, allowed_to_read, &
ids, ide, jds, jde, kds, kde, &
ims, ime, jms, jme, kms, kme, &
its, ite, jts, jte, kts, kte )
!-------------------------------------------------------------------
IMPLICIT NONE
!-------------------------------------------------------------------
!
INTEGER , INTENT(IN) :: id
LOGICAL, INTENT(IN) :: restart, allowed_to_read
INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde, &
ims, ime, jms, jme, kms, kme, &
its, ite, jts, jte, kts, kte
REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(OUT) :: &
rundgdten, &
rvndgdten, &
rthndgdten, &
rqvndgdten
!
! FASDAS
!
REAL, DIMENSION( ims:ime , jms:jme ), INTENT(OUT) :: &
SDA_HFX, &
SDA_QFX, &
QNORM, HFX_BOTH, QFX_BOTH
INTEGER, INTENT(IN ) :: fasdas
REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(OUT) :: &
HFX_FDDA
!
! END FASDAS
!
INTEGER, INTENT(IN) :: run_hours
INTEGER, INTENT(IN) :: if_no_pbl_nudging_uv, if_no_pbl_nudging_t, &
if_no_pbl_nudging_q, end_fdda_hour
INTEGER, INTENT(IN) :: if_zfac_uv, if_zfac_t, if_zfac_q
INTEGER, INTENT(IN) :: k_zfac_uv, k_zfac_t, k_zfac_q
INTEGER, INTENT(IN) :: if_ramping, grid_sfdda
REAL, INTENT(IN) :: dtramp_min
REAL, INTENT(IN) :: guv, gt, gq
REAL, INTENT(IN) :: guv_sfc, gt_sfc, gq_sfc
REAL :: actual_end_fdda_min
REAL, DIMENSION( ims:ime , jms:jme ), INTENT(OUT) :: rmundgdten
INTEGER :: i, j, k
LOGICAL , EXTERNAL :: wrf_dm_on_monitor
CHARACTER (LEN=256) :: message
IF ( wrf_dm_on_monitor() ) THEN
IF( guv > 0.0 ) THEN
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' 3-D analysis nudging for wind is applied and Guv= ', guv
CALL wrf_message
(TRIM(message))
ELSE IF( guv < 0.0 ) THEN
CALL wrf_error_fatal
('In grid FDDA, Guv must be positive.')
ELSE
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' 3-D analysis nudging for wind is not applied and Guv= ', guv
CALL wrf_message
(TRIM(message))
ENDIF
IF( gt > 0.0 ) THEN
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' 3-D analysis nudging for temperature is applied and Gt= ', gt
CALL wrf_message
(TRIM(message))
ELSE IF( gt < 0.0 ) THEN
CALL wrf_error_fatal
('In grid FDDA, Gt must be positive.')
ELSE
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' 3-D analysis nudging for temperature is not applied and Gt= ', gt
CALL wrf_message
(TRIM(message))
ENDIF
IF( gq > 0.0 ) THEN
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' 3-D analysis nudging for water vapor mixing ratio is applied and Gq= ', gq
CALL wrf_message
(TRIM(message))
ELSE IF( gq < 0.0 ) THEN
CALL wrf_error_fatal
('In grid FDDA, Gq must be positive.')
ELSE
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' 3-D analysis nudging for water vapor mixing ratio is not applied and Gq= ', gq
CALL wrf_message
(TRIM(message))
ENDIF
IF( guv > 0.0 .AND. if_no_pbl_nudging_uv == 1 ) THEN
WRITE(message,'(a,i1,a)') &
'D0',id,' 3-D analysis nudging for wind is turned off within the PBL.'
CALL wrf_message
(TRIM(message))
ENDIF
IF( gt > 0.0 .AND. if_no_pbl_nudging_t == 1 ) THEN
WRITE(message,'(a,i1,a)') &
'D0',id,' 3-D analysis nudging for temperature is turned off within the PBL.'
CALL wrf_message
(TRIM(message))
ENDIF
IF( gq > 0.0 .AND. if_no_pbl_nudging_q == 1 ) THEN
WRITE(message,'(a,i1,a)') &
'D0',id,' 3-D analysis nudging for water vapor mixing ratio is turned off within the PBL.'
CALL wrf_message
(TRIM(message))
ENDIF
IF( guv > 0.0 .AND. if_zfac_uv == 1 ) THEN
WRITE(message,'(a,i1,a,i3)') &
'D0',id,' 3-D analysis nudging for wind is turned off below layer', k_zfac_uv
CALL wrf_message
(TRIM(message))
ENDIF
IF( gt > 0.0 .AND. if_zfac_t == 1 ) THEN
WRITE(message,'(a,i1,a,i3)') &
'D0',id,' 3-D analysis nudging for temperature is turned off below layer', k_zfac_t
CALL wrf_message
(TRIM(message))
ENDIF
IF( gq > 0.0 .AND. if_zfac_q == 1 ) THEN
WRITE(message,'(a,i1,a,i3)') &
'D0',id,' 3-D analysis nudging for water vapor mixing ratio is turned off below layer', &
k_zfac_q
CALL wrf_message
(TRIM(message))
ENDIF
IF( grid_sfdda >=1 ) THEN
IF( guv_sfc > 0.0 ) THEN
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' surface analysis nudging for wind is applied and Guv_sfc= ', guv_sfc
CALL wrf_message
(TRIM(message))
ELSE IF( guv_sfc < 0.0 ) THEN
CALL wrf_error_fatal
('In grid FDDA, Guv_sfc must be positive.')
ELSE
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' surface analysis nudging for wind is not applied and Guv_sfc= ', guv_sfc
CALL wrf_message
(TRIM(message))
ENDIF
IF( gt_sfc > 0.0 ) THEN
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' surface analysis nudging for temperature is applied and Gt_sfc= ', gt_sfc
CALL wrf_message
(TRIM(message))
ELSE IF( gt_sfc < 0.0 ) THEN
CALL wrf_error_fatal
('In grid FDDA, Gt_sfc must be positive.')
ELSE
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' surafce analysis nudging for temperature is not applied and Gt_sfc= ', gt_sfc
CALL wrf_message
(TRIM(message))
ENDIF
IF( gq_sfc > 0.0 ) THEN
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' surface analysis nudging for water vapor mixing ratio is applied and Gq_sfc= ', gq_sfc
CALL wrf_message
(TRIM(message))
ELSE IF( gq_sfc < 0.0 ) THEN
CALL wrf_error_fatal
('In grid FDDA, Gq_sfc must be positive.')
ELSE
WRITE(message,'(a,i1,a,e12.4)') &
'D0',id,' surface analysis nudging for water vapor mixing ratio is not applied and Gq_sfc= ', gq_sfc
CALL wrf_message
(TRIM(message))
ENDIF
ENDIF
IF( if_ramping == 1 .AND. ABS(dtramp_min) > 0.0 ) THEN
IF( dtramp_min <= 0.0 ) THEN
actual_end_fdda_min = end_fdda_hour*60.0
ELSE
actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
ENDIF
IF( actual_end_fdda_min <= run_hours*60. ) THEN
WRITE(message,'(a,i1,a)') &
'D0',id,' analysis nudging is ramped down near the end of the nudging period,'
CALL wrf_message
(TRIM(message))
WRITE(message,'(a,f6.2,a,f6.2,a)') &
' starting at ', (actual_end_fdda_min - ABS(dtramp_min))/60.0, &
'h, ending at ', actual_end_fdda_min/60.0,'h.'
CALL wrf_message
(TRIM(message))
ENDIF
ENDIF
ENDIF
IF(.not.restart) THEN
DO j = jts,jte
DO k = kts,kte
DO i = its,ite
rundgdten(i,k,j) = 0.
rvndgdten(i,k,j) = 0.
rthndgdten(i,k,j) = 0.
rqvndgdten(i,k,j) = 0.
! TWG 2015 Psuedo radiative flux
HFX_FDDA(i,k,j) = 0.
! TWG END
if(k.eq.kts) rmundgdten(i,j) = 0.
ENDDO
ENDDO
ENDDO
!
! FASDAS
!
IF( fasdas == 1 ) THEN
DO j = jts,jte
DO i = its,ite
SDA_HFX(I,J) = 0.0
SDA_QFX(I,J) = 0.0
QNORM(I,J) = 0.0
HFX_BOTH(I,J) = 0.0
QFX_BOTH(I,J) = 0.0
ENDDO
ENDDO
ENDIF
!
! END FASDAS
!
ENDIF
END SUBROUTINE fddagdinit
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
SUBROUTINE smther(slab, idimst, idimnd, jdimst, jdimnd, npass, ist, ind, jst, jnd) 2
!
! PURPOSE: SPATIALLY SMOOTH DATA IN SLAB TO DAMPEN SHORT
! WAVELENGTH COMPONENTS.
!
! Implemented based on the same smoothing subroutine used in MM5, with modifications to
! remove the extra loop that causes unneccessary desmoothing. Aijun Deng (Penn State),
! December 2008
!
IMPLICIT NONE
INTEGER :: idimst, idimnd, jdimst, jdimnd, npass, ist, ind, jst, jnd
INTEGER :: i, j, k, kk
REAL :: avg
REAL, DIMENSION(idimst:idimnd, jdimst:jdimnd) :: SLAB
REAL, DIMENSION(idimst:idimnd, jdimst:jdimnd) :: SLAB_ORIG
REAL, DIMENSION(2) :: XNU
IF(NPASS.EQ.0)RETURN
XNU(1)=0.50
XNU(2)=-0.52
DO K=1,NPASS
KK = 2 - MOD(K,2)
DO J=JDIMST,JDIMND
DO I=IDIMST,IDIMND
SLAB_ORIG(I,J) = SLAB(I,J)
END DO
END DO
DO J=JST,JND
DO I=IST,IND
AVG = ( SLAB_ORIG(I+1,J ) + &
SLAB_ORIG(I-1,J ) + &
SLAB_ORIG(I ,J+1) + &
SLAB_ORIG(I ,J-1) ) * 0.25
SLAB(I,J)=SLAB_ORIG(I,J)+XNU(KK)*(AVG - SLAB_ORIG(I,J))
ENDDO
ENDDO
ENDDO
END SUBROUTINE smther
!-------------------------------------------------------------------
END MODULE module_fdda_psufddagd