PageRenderTime 52ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/wrfv2_fire/phys/module_fdda_spnudging.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 1087 lines | 658 code | 230 blank | 199 comment | 18 complexity | 325b380e0394c020783b2b679289484d MD5 | raw file
Possible License(s): AGPL-1.0
  1. !wrf:model_layer:physics
  2. !
  3. ! Code contributed by Gonzalo Miguez-Macho, Univ. de Santiago de Compostela, Galicia, Spain
  4. !
  5. MODULE module_fdda_spnudging
  6. #ifdef DM_PARALLEL
  7. USE module_dm , ONLY : ntasks_x, ntasks_y, local_communicator_x, local_communicator_y, data_order_xzy
  8. #endif
  9. USE module_wrf_error , ONLY : wrf_err_message
  10. CONTAINS
  11. !
  12. !-------------------------------------------------------------------
  13. !
  14. SUBROUTINE spectral_nudging(grid,itimestep,dt,xtime,id,analysis_interval, end_fdda_hour, &
  15. if_no_pbl_nudging_uv, if_no_pbl_nudging_t, if_no_pbl_nudging_ph,&
  16. if_zfac_uv, k_zfac_uv, dk_zfac_uv, &
  17. if_zfac_t, k_zfac_t, dk_zfac_t, &
  18. if_zfac_ph, k_zfac_ph, dk_zfac_ph, &
  19. guv, gt, gph, if_ramping, dtramp_min, xwavenum, ywavenum, &
  20. u3d,v3d,th3d,ph3d, &
  21. u_ndg_old,v_ndg_old,t_ndg_old,ph_ndg_old, &
  22. u_ndg_new,v_ndg_new,t_ndg_new,ph_ndg_new, &
  23. RUNDGDTEN,RVNDGDTEN,RTHNDGDTEN,RPHNDGDTEN,&
  24. pblh, ht, z, z_at_w, &
  25. ids,ide, jds,jde, kds,kde, &
  26. ims,ime, jms,jme, kms,kme, &
  27. i_start,i_end, j_start,j_end, kts,kte, num_tiles, &
  28. ips,ipe,jps,jpe,kps,kpe, &
  29. imsx,imex,jmsx,jmex,kmsx,kmex, &
  30. ipsx,ipex,jpsx,jpex,kpsx,kpex, &
  31. imsy,imey,jmsy,jmey,kmsy,kmey, &
  32. ipsy,ipey,jpsy,jpey,kpsy,kpey )
  33. USE module_state_description
  34. USE module_domain, ONLY : domain
  35. !-------------------------------------------------------------------
  36. implicit none
  37. !-------------------------------------------------------------------
  38. !-- u3d 3d u-velocity staggered on u points
  39. !-- v3d 3d v-velocity staggered on v points
  40. !-- th3d 3d potential temperature (k)
  41. !---ph3d 3d perturbation geopotential
  42. !-- rundgdten staggered u tendency due to
  43. ! spectral nudging (m/s/s)
  44. !-- rvndgdten staggered v tendency due to
  45. ! spectral nudging (m/s/s)
  46. !-- rthndgdten theta tendency due to
  47. ! spectral nudging (K/s)
  48. !-- phndgdten ph tendency due to
  49. ! spectral nudging (m2/s2/s)
  50. !-- ids start index for i in domain
  51. !-- ide end index for i in domain
  52. !-- jds start index for j in domain
  53. !-- jde end index for j in domain
  54. !-- kds start index for k in domain
  55. !-- kde end index for k in domain
  56. !-- ims start index for i in memory
  57. !-- ime end index for i in memory
  58. !-- jms start index for j in memory
  59. !-- jme end index for j in memory
  60. !-- kms start index for k in memory
  61. !-- kme end index for k in memory
  62. !-- its start index for i in tile
  63. !-- ite end index for i in tile
  64. !-- jts start index for j in tile
  65. !-- jte end index for j in tile
  66. !-- kts start index for k in tile
  67. !-- kte end index for k in tile
  68. !-------------------------------------------------------------------
  69. !
  70. TYPE(domain) , TARGET :: grid
  71. INTEGER, INTENT(IN) :: itimestep, analysis_interval, end_fdda_hour
  72. INTEGER, INTENT(IN) :: if_no_pbl_nudging_uv, if_no_pbl_nudging_t, &
  73. if_no_pbl_nudging_ph
  74. INTEGER, INTENT(IN) :: if_zfac_uv, if_zfac_t, if_zfac_ph
  75. INTEGER, INTENT(IN) :: k_zfac_uv, k_zfac_t, k_zfac_ph
  76. INTEGER, INTENT(IN) :: dk_zfac_uv, dk_zfac_t, dk_zfac_ph
  77. INTEGER, INTENT(IN) :: if_ramping
  78. INTEGER, INTENT(IN) :: xwavenum,ywavenum
  79. INTEGER , INTENT(IN) :: id
  80. REAL, INTENT(IN) :: DT, xtime, dtramp_min
  81. INTEGER, INTENT(IN) :: ids,ide, jds,jde, kds,kde, &
  82. ims,ime, jms,jme, kms,kme, &
  83. kts,kte, num_tiles, &
  84. ips,ipe,jps,jpe,kps,kpe, &
  85. imsx,imex,jmsx,jmex,kmsx,kmex, &
  86. ipsx,ipex,jpsx,jpex,kpsx,kpex, &
  87. imsy,imey,jmsy,jmey,kmsy,kmey, &
  88. ipsy,ipey,jpsy,jpey,kpsy,kpey
  89. INTEGER, DIMENSION(num_tiles), INTENT(IN) :: &
  90. & i_start,i_end,j_start,j_end
  91. REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
  92. INTENT(IN) :: ph3d, &
  93. th3d, &
  94. z, &
  95. z_at_w
  96. REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
  97. INTENT(INOUT) :: rundgdten, &
  98. rvndgdten, &
  99. rthndgdten, &
  100. rphndgdten
  101. REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
  102. INTENT(INOUT) :: u_ndg_old, &
  103. v_ndg_old, &
  104. t_ndg_old, &
  105. ph_ndg_old, &
  106. u_ndg_new, &
  107. v_ndg_new, &
  108. t_ndg_new, &
  109. ph_ndg_new
  110. REAL, DIMENSION( ims:ime, kms:kme, jms:jme ), &
  111. INTENT(IN) :: u3d, &
  112. v3d
  113. REAL, DIMENSION( ims:ime, jms:jme ), INTENT(IN) :: pblh, &
  114. ht
  115. REAL, INTENT(IN) :: guv, gt ,gph
  116. INTEGER :: its,ite, jts,jte,ij
  117. INTEGER :: i, j, k, itsu, jtsv, itf, jtf, ktf, i0, k0, j0
  118. REAL :: xtime_old, xtime_new, coef, val_analysis
  119. INTEGER :: kpbl, dbg_level
  120. REAL :: zpbl, zagl, zagl_bot, zagl_top, tfac, actual_end_fdda_min
  121. REAL, DIMENSION( ips:ipe, kps:kpe, jps:jpe, 4 ) :: wpbl ! 1: u, 2: v, 3: t, 4: ph
  122. REAL, DIMENSION( kps:kpe, 4 ) :: wzfac ! 1: u, 2: v, 3: t, 4: ph
  123. LOGICAL , EXTERNAL :: wrf_dm_on_monitor
  124. CHARACTER (LEN=256) :: message
  125. #if ! ( NMM_CORE == 1 )
  126. DO ij = 1 , num_tiles
  127. its=i_start(ij)
  128. ite=i_end(ij)
  129. jts=j_start(ij)
  130. jte=j_end(ij)
  131. ENDDO
  132. !GMM default values for vertical coefficients, set here
  133. wpbl(:,:,:,:) = 1.0
  134. wzfac(:,:) = 1.0
  135. !$OMP PARALLEL DO &
  136. !$OMP PRIVATE ( ij, i,j,k ) ! only for part of the calculation.
  137. DO ij = 1 , num_tiles
  138. DO j = jts, jte
  139. DO k = kts, kte
  140. DO i = its, ite
  141. RUNDGDTEN(i,k,j) = 0.0
  142. RVNDGDTEN(i,k,j) = 0.0
  143. RTHNDGDTEN(i,k,j) = 0.0
  144. RPHNDGDTEN(i,k,j) = 0.0
  145. ENDDO
  146. ENDDO
  147. ENDDO
  148. ENDDO
  149. !$OMP END PARALLEL DO
  150. actual_end_fdda_min = end_fdda_hour*60.0
  151. IF( if_ramping == 1 .AND. dtramp_min > 0.0 ) &
  152. actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
  153. IF( xtime > actual_end_fdda_min ) RETURN
  154. !$OMP PARALLEL DO &
  155. !$OMP PRIVATE ( ij, i,j,k ) ! only for part of the calculation.
  156. !GMM Transpose and filtering needs to be done on patch
  157. DO ij = 1 , num_tiles
  158. ! actual_end_fdda_min = end_fdda_hour*60.0
  159. ! IF( if_ramping == 1 .AND. dtramp_min > 0.0 ) &
  160. ! actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
  161. xtime_old = FLOOR(xtime/analysis_interval) * analysis_interval * 1.0
  162. xtime_new = xtime_old + analysis_interval
  163. coef = (xtime-xtime_old)/(xtime_new-xtime_old)
  164. IF ( wrf_dm_on_monitor()) THEN
  165. CALL get_wrf_debug_level( dbg_level )
  166. IF( xtime-xtime_old < 0.5*dt/60.0 ) THEN
  167. IF( xtime < end_fdda_hour*60.0 ) THEN
  168. WRITE(message,FMT='(a,i2.2,a,f15.3,a)') &
  169. 'D',id,' Spectral nudging read in new data at time = ', xtime, ' min.'
  170. CALL wrf_message( TRIM(message) )
  171. WRITE(message,FMT='(a,i2.2,a,2(f15.3,1x),a)') &
  172. 'D',id,' Spectral nudging bracketing times = ', xtime_old, xtime_new, ' min.'
  173. CALL wrf_message( TRIM(message) )
  174. ENDIF
  175. actual_end_fdda_min = end_fdda_hour*60.0
  176. IF( if_ramping == 1 .AND. dtramp_min > 0.0 ) &
  177. actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
  178. IF( dbg_level .GE. 10 .AND. xtime <= actual_end_fdda_min ) THEN
  179. ! Find the mid point of the tile and print out the sample values
  180. i0 = (ite-its)/2+its
  181. j0 = (jte-jts)/2+jts
  182. IF( guv > 0.0 ) THEN
  183. DO k = kts, kte
  184. WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
  185. ' D0',id,' sample analysis values at i,k,j=', i0, k, j0, &
  186. ' u_ndg_old=', u_ndg_old(i0,k,j0), ' u_ndg_new=', u_ndg_new(i0,k,j0)
  187. CALL wrf_message( TRIM(message) )
  188. ENDDO
  189. DO k = kts, kte
  190. WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
  191. ' D0',id,' sample analysis values at i,k,j=', i0, k, j0, &
  192. ' v_ndg_old=', v_ndg_old(i0,k,j0), ' v_ndg_new=', v_ndg_new(i0,k,j0)
  193. CALL wrf_message( TRIM(message) )
  194. ENDDO
  195. ENDIF
  196. IF( gt > 0.0 ) THEN
  197. DO k = kts, kte
  198. WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
  199. ' D0',id,' sample analysis values at i,k,j=', i0, k, j0, &
  200. ' t_ndg_old=', t_ndg_old(i0,k,j0), ' t_ndg_new=', t_ndg_new(i0,k,j0)
  201. CALL wrf_message( TRIM(message) )
  202. ENDDO
  203. ENDIF
  204. IF( gph > 0.0 ) THEN
  205. DO k = kts, kte
  206. WRITE(message,'(a,i1,a,3i4,a,f10.4,a,f10.4)') &
  207. ' D0',id,' sample analysis values at i,k,j=', i0, k, j0, &
  208. ' ph_ndg_old=', ph_ndg_old(i0,k,j0), ' ph_ndg_new=', ph_ndg_new(i0,k,j0)
  209. CALL wrf_message( TRIM(message) )
  210. ENDDO
  211. ENDIF
  212. ENDIF
  213. ENDIF
  214. ENDIF
  215. jtsv=MAX0(jts,jds+1)
  216. itsu=MAX0(its,ids+1)
  217. jtf=MIN0(jte,jde-1)
  218. ktf=MIN0(kte,kde-1)
  219. itf=MIN0(ite,ide-1)
  220. !
  221. ! If the user-defined namelist switches (if_no_pbl_nudging_uv, if_no_pbl_nudging_t,
  222. ! if_no_pbl_nudging_ph swithes) are set to 1, compute the weighting function, wpbl(:,k,:,:),
  223. ! based on the PBL depth. wpbl = 1 above the PBL and wpbl = 0 in the PBL. If all
  224. ! the switche are set to zero, wpbl = 1 (default value).
  225. !
  226. !GMM If those are set to zero, then check if the user-defined namelist switches (if_zfac_uv, if_zfac_t,
  227. ! if_zfac_ph swithes) are set to 1, compute the weighting function, wzfac(k,:),
  228. ! based on the namelist specified k values (k_zfac_uv, k_zfac_t and k_zfac_ph)
  229. ! below which analysis nudging is turned off (wzfac = 1 above k_zfac_x and = 0 in below k_zfac_x).
  230. ! The strength of nudging increases linearly from k_zfac to kzfac + dk_zfac
  231. ! (dk_zfac_uv, dk_zfac_t and kd_zfac_ph are also set in the namelist, default value is 1).
  232. !If all switches are set to zero, wzfac = 1 (default value).
  233. !
  234. IF( if_no_pbl_nudging_uv == 1 ) THEN
  235. DO j=jts,jtf
  236. DO i=itsu,itf
  237. kpbl = 1
  238. zpbl = 0.5 * ( pblh(i-1,j) + pblh(i,j) )
  239. loop_ku: DO k=kts,ktf
  240. zagl_bot = 0.5 * ( z_at_w(i-1,k, j)-ht(i-1,j) + z_at_w(i,k, j)-ht(i,j) )
  241. 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) )
  242. IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
  243. kpbl = k
  244. EXIT loop_ku
  245. ENDIF
  246. ENDDO loop_ku
  247. DO k=kts,ktf
  248. wpbl(i, k, j, 1) = max ( min ( float(k-kpbl) / float(dk_zfac_uv) , 1. ) , 0.)
  249. ENDDO
  250. ENDDO
  251. ENDDO
  252. DO i=its,itf
  253. DO j=jtsv,jtf
  254. kpbl = 1
  255. zpbl = 0.5 * ( pblh(i,j-1) + pblh(i,j) )
  256. loop_kv: DO k=kts,ktf
  257. zagl_bot = 0.5 * ( z_at_w(i,k, j-1)-ht(i,j-1) + z_at_w(i,k, j)-ht(i,j) )
  258. 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) )
  259. IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
  260. kpbl = k
  261. EXIT loop_kv
  262. ENDIF
  263. ENDDO loop_kv
  264. DO k=kts,ktf
  265. wpbl(i, k, j, 2) = max ( min ( float(k-kpbl) / float(dk_zfac_uv) , 1. ) , 0.)
  266. ENDDO
  267. ENDDO
  268. ENDDO
  269. ELSEIF( if_zfac_uv == 1 ) THEN
  270. DO j=jts,jte
  271. DO k=kts,ktf
  272. DO i=its,ite
  273. wpbl(i, k, j, 1) = max ( min ( float(k-k_zfac_uv) / float(dk_zfac_uv) , 1. ) , 0.)
  274. wpbl(i, k, j, 2) = wpbl(i, k, j, 1)
  275. ENDDO
  276. ENDDO
  277. ENDDO
  278. ENDIF
  279. IF( if_no_pbl_nudging_t == 1 ) THEN
  280. DO j=jts,jtf
  281. DO i=its,itf
  282. kpbl = 1
  283. zpbl = pblh(i,j)
  284. loop_kt: DO k=kts,ktf
  285. zagl_bot = z_at_w(i,k, j)-ht(i,j)
  286. zagl_top = z_at_w(i,k+1,j)-ht(i,j)
  287. IF( zpbl >= zagl_bot .AND. zpbl < zagl_top ) THEN
  288. kpbl = k
  289. EXIT loop_kt
  290. ENDIF
  291. ENDDO loop_kt
  292. DO k=kts,ktf
  293. wpbl(i, k, j, 3) = max ( min ( float(k-kpbl) / float(dk_zfac_t) , 1. ) , 0.)
  294. ENDDO
  295. ENDDO
  296. ENDDO
  297. ELSEIF( if_zfac_t == 1 ) THEN
  298. DO j=jts,jtf
  299. DO k=kts,ktf
  300. DO i=its,itf
  301. wpbl(i, k, j, 3) = max ( min ( float(k-k_zfac_t) / float(dk_zfac_t) , 1. ) , 0.)
  302. ENDDO
  303. ENDDO
  304. ENDDO
  305. ENDIF
  306. IF( if_no_pbl_nudging_ph == 1 ) THEN
  307. DO j=jts,jtf
  308. DO i=its,itf
  309. kpbl = 1
  310. zpbl = pblh(i,j)
  311. loop_kph: DO k=kts,kte
  312. zagl = z_at_w(i,k, j)-ht(i,j)
  313. IF( zpbl >= zagl) THEN
  314. kpbl = k
  315. EXIT loop_kph
  316. ENDIF
  317. ENDDO loop_kph
  318. DO k=kts,kte
  319. wpbl(i, k, j, 4) = max ( min ( float(k-kpbl) / float(dk_zfac_ph) , 1. ) , 0.)
  320. ENDDO
  321. ENDDO
  322. ENDDO
  323. ELSEIF( if_zfac_ph == 1 ) THEN
  324. DO j=jts,jtf
  325. DO k=kts,kte
  326. DO i=its,itf
  327. wpbl(i, k, j, 4) = max ( min ( float(k-k_zfac_ph) / float(dk_zfac_ph) , 1. ) , 0.)
  328. ENDDO
  329. ENDDO
  330. ENDDO
  331. ENDIF
  332. ! If if_ramping and dtramp_min are defined by user, comput a time weighting function, tfac,
  333. ! for analysis nudging so that at the end of the nudging period (which has to be at a
  334. ! analysis time) we ramp down the nudging coefficient, based on the use-defined sign of dtramp_min.
  335. !
  336. ! When dtramp_min is negative, ramping ends at end_fdda_hour and starts at
  337. ! end_fdda_hour-ABS(dtramp_min).
  338. !
  339. ! When dtramp_min is positive, ramping starts at end_fdda_hour and ends at
  340. ! end_fdda_hour+ABS(dtramp_min). In this case, the obs values are extrapolated using
  341. ! the obs tendency saved from the previous FDDA wondow. More specifically for extrapolation,
  342. ! coef (see codes below) is recalculated to reflect extrapolation during the ramping period.
  343. !
  344. tfac = 1.0
  345. IF( if_ramping == 1 .AND. ABS(dtramp_min) > 0.0 ) THEN
  346. IF( dtramp_min <= 0.0 ) THEN
  347. actual_end_fdda_min = end_fdda_hour*60.0
  348. ELSE
  349. actual_end_fdda_min = end_fdda_hour*60.0 + dtramp_min
  350. ENDIF
  351. IF( xtime < actual_end_fdda_min-ABS(dtramp_min) )THEN
  352. tfac = 1.0
  353. ELSEIF( xtime >= actual_end_fdda_min-ABS(dtramp_min) .AND. xtime <= actual_end_fdda_min )THEN
  354. tfac = ( actual_end_fdda_min - xtime ) / ABS(dtramp_min)
  355. IF( dtramp_min > 0.0 ) coef = (xtime-xtime_old+analysis_interval)/analysis_interval
  356. ELSE
  357. tfac = 0.0
  358. ENDIF
  359. ENDIF
  360. ENDDO
  361. !$OMP END PARALLEL DO
  362. !
  363. ! Compute 3-D nudging tendencies for u, v
  364. !
  365. !
  366. !GMM Fist calculate differences between model variables and analysis values,
  367. !then filter in the x and y direction all wave numbers higher than
  368. ! xwavenum and ywavenum, as specified in the namelist.
  369. !If either xwavenum or ywavenum are not specified,
  370. ! default values are zero, and spectral nudging is turned off
  371. !Then use the filtered differences to calculate the spectral nudging tendencies
  372. IF(guv > 0. ) then
  373. !$OMP PARALLEL DO &
  374. !$OMP PRIVATE ( ij, i,j,k )
  375. DO ij = 1 , num_tiles
  376. DO j=jts,jte
  377. DO k=kts,ktf
  378. DO i=its,ite
  379. val_analysis = u_ndg_old(i,k,j) *( 1.0 - coef ) + u_ndg_new(i,k,j) * coef
  380. grid%dif_analysis(i,k,j) = val_analysis - u3d(i,k,j)
  381. ENDDO
  382. ENDDO
  383. ENDDO
  384. ENDDO
  385. !$OMP END PARALLEL DO
  386. !Filter
  387. #if ( defined( DM_PARALLEL ) && ( ! defined( STUBMPI ) ) )
  388. # include "XPOSE_SPECTRAL_NUDGING_z2x.inc"
  389. CALL spectral_nudging_filter_3dx( grid%dif_xxx, xwavenum, &
  390. ids, ide, jds, jde, kds, kde, &
  391. imsx, imex, jmsx, jmex, kmsx, kmex, &
  392. ipsx, ipex, jpsx, jpex, kpsx, MIN(kde-1,kpex) )
  393. # include "XPOSE_SPECTRAL_NUDGING_x2y.inc"
  394. CALL spectral_nudging_filter_3dy( grid%dif_yyy, ywavenum, &
  395. ids, ide, jds, jde, kds, kde, &
  396. imsy, imey, jmsy, jmey, kmsy, kmey, &
  397. ipsy, ipey, jpsy, jpey, kpsy, MIN(kde-1,kpey) )
  398. # include "XPOSE_SPECTRAL_NUDGING_y2z.inc"
  399. #else
  400. CALL spectral_nudging_filter_3dx( grid%dif_analysis, xwavenum, &
  401. ids, ide, jds, jde, kds, kde, &
  402. ims, ime, jms, jme, kms, kme, &
  403. ips, ipe, jps, jpe, kps, MIN(kde-1,kpe) )
  404. CALL spectral_nudging_filter_3dy( grid%dif_analysis, ywavenum, &
  405. ids, ide, jds, jde, kds, kde, &
  406. ims, ime, jms, jme, kms, kme, &
  407. ips, ipe, jps, jpe, kps, MIN(kde-1,kpe) )
  408. #endif
  409. ! Calculate tendency
  410. !$OMP PARALLEL DO &
  411. !$OMP PRIVATE ( ij, i,j,k )
  412. DO ij = 1 , num_tiles
  413. DO j=jts,jte
  414. DO k=kts,ktf
  415. DO i=its,ite
  416. RUNDGDTEN(i,k,j) = guv * wpbl(i,k,j,1) * wzfac(k,1) * tfac * &
  417. grid%dif_analysis(i,k,j)
  418. ENDDO
  419. ENDDO
  420. ENDDO
  421. !
  422. ! Now V component
  423. !
  424. DO j=jts,jte
  425. DO k=kts,ktf
  426. DO i=its,ite
  427. val_analysis = v_ndg_old(i,k,j) *( 1.0 - coef ) + v_ndg_new(i,k,j) * coef
  428. grid%dif_analysis(i,k,j) = val_analysis - v3d(i,k,j)
  429. ENDDO
  430. ENDDO
  431. ENDDO
  432. ENDDO
  433. !$OMP END PARALLEL DO
  434. !
  435. ! Filter
  436. !
  437. #if ( defined( DM_PARALLEL ) && ( ! defined( STUBMPI ) ) )
  438. # include "XPOSE_SPECTRAL_NUDGING_z2x.inc"
  439. CALL spectral_nudging_filter_3dx( grid%dif_xxx, xwavenum, &
  440. ids, ide, jds, jde, kds, kde, &
  441. imsx, imex, jmsx, jmex, kmsx, kmex, &
  442. ipsx, ipex, jpsx, jpex, kpsx, MIN(kde-1,kpex) )
  443. # include "XPOSE_SPECTRAL_NUDGING_x2y.inc"
  444. CALL spectral_nudging_filter_3dy( grid%dif_yyy, ywavenum, &
  445. ids, ide, jds, jde, kds, kde-1, &
  446. imsy, imey, jmsy, jmey, kmsy, kmey, &
  447. ipsy, ipey, jpsy, jpey, kpsy, MIN(kde-1,kpey) )
  448. # include "XPOSE_SPECTRAL_NUDGING_y2z.inc"
  449. #else
  450. CALL spectral_nudging_filter_3dx( grid%dif_analysis, xwavenum, &
  451. ids, ide, jds, jde, kds, kde, &
  452. ims, ime, jms, jme, kms, kme, &
  453. ips, ipe, jps, jpe, kps, MIN(kde-1,kpe) )
  454. CALL spectral_nudging_filter_3dy( grid%dif_analysis, ywavenum, &
  455. ids, ide, jds, jde, kds, kde, &
  456. ims, ime, jms, jme, kms, kme, &
  457. ips, ipe, jps, jpe, kps, MIN(kde-1,kpe) )
  458. #endif
  459. ! Calculate tendency
  460. !$OMP PARALLEL DO &
  461. !$OMP PRIVATE ( ij, i,j,k )
  462. DO ij = 1 , num_tiles
  463. DO j=jts,jte
  464. DO k=kts,ktf
  465. DO i=its,ite
  466. RVNDGDTEN(i,k,j) = guv * wpbl(i,k,j,2) * wzfac(k,2) * tfac * &
  467. grid%dif_analysis(i,k,j)
  468. ENDDO
  469. ENDDO
  470. ENDDO
  471. ENDDO
  472. !$OMP END PARALLEL DO
  473. ENDIF
  474. IF(gt > 0. ) then
  475. !$OMP PARALLEL DO &
  476. !$OMP PRIVATE ( ij, i,j,k )
  477. DO ij = 1 , num_tiles
  478. DO j=jts,jte
  479. DO k=kts,ktf
  480. DO i=its,ite
  481. val_analysis = t_ndg_old(i,k,j) *( 1.0 - coef ) + t_ndg_new(i,k,j) * coef
  482. grid%dif_analysis(i,k,j) = val_analysis - th3d(i,k,j) + 300.
  483. ENDDO
  484. ENDDO
  485. ENDDO
  486. ENDDO
  487. !$OMP END PARALLEL DO
  488. !Filter
  489. #if ( defined( DM_PARALLEL ) && ( ! defined( STUBMPI ) ) )
  490. # include "XPOSE_SPECTRAL_NUDGING_z2x.inc"
  491. CALL spectral_nudging_filter_3dx( grid%dif_xxx, xwavenum, &
  492. ids, ide, jds, jde, kds, kde, &
  493. imsx, imex, jmsx, jmex, kmsx, kmex, &
  494. ipsx, ipex, jpsx, jpex, kpsx, MIN(kde-1,kpex) )
  495. # include "XPOSE_SPECTRAL_NUDGING_x2y.inc"
  496. CALL spectral_nudging_filter_3dy( grid%dif_yyy, ywavenum, &
  497. ids, ide, jds, jde, kds, kde, &
  498. imsy, imey, jmsy, jmey, kmsy, kmey, &
  499. ipsy, ipey, jpsy, jpey, kpsy, MIN(kde-1,kpey) )
  500. # include "XPOSE_SPECTRAL_NUDGING_y2z.inc"
  501. #else
  502. CALL spectral_nudging_filter_3dx( grid%dif_analysis, xwavenum, &
  503. ids, ide, jds, jde, kds, kde, &
  504. ims, ime, jms, jme, kms, kme, &
  505. ips, ipe, jps, jpe, kps, MIN(kde-1,kpe) )
  506. CALL spectral_nudging_filter_3dy( grid%dif_analysis, ywavenum, &
  507. ids, ide, jds, jde, kds, kde, &
  508. ims, ime, jms, jme, kms, kme, &
  509. ips, ipe, jps, jpe, kps, MIN(kde-1,kpe) )
  510. #endif
  511. ! Calculate tendency
  512. !$OMP PARALLEL DO &
  513. !$OMP PRIVATE ( ij, i,j,k )
  514. DO ij = 1 , num_tiles
  515. DO j=jts,jte
  516. DO k=kts,ktf
  517. DO i=its,ite
  518. RTHNDGDTEN(i,k,j) = gt * wpbl(i,k,j,3) * wzfac(k,3) * tfac * &
  519. grid%dif_analysis(i,k,j)
  520. ENDDO
  521. ENDDO
  522. ENDDO
  523. ENDDO
  524. !$OMP END PARALLEL DO
  525. ENDIF
  526. IF(gph > 0. ) then
  527. !$OMP PARALLEL DO &
  528. !$OMP PRIVATE ( ij, i,j,k )
  529. DO ij = 1 , num_tiles
  530. DO j=jts,jte
  531. DO k=kts,kte
  532. DO i=its,ite
  533. val_analysis = ph_ndg_old(i,k,j) *( 1.0 - coef ) + ph_ndg_new(i,k,j) * coef
  534. grid%dif_analysis(i,k,j) = val_analysis - ph3d(i,k,j)
  535. ENDDO
  536. ENDDO
  537. ENDDO
  538. ENDDO
  539. !$OMP END PARALLEL DO
  540. !Filter
  541. #if ( defined( DM_PARALLEL ) && ( ! defined( STUBMPI ) ) )
  542. # include "XPOSE_SPECTRAL_NUDGING_z2x.inc"
  543. CALL spectral_nudging_filter_3dx( grid%dif_xxx, xwavenum, &
  544. ids, ide, jds, jde, kds, kde, &
  545. imsx, imex, jmsx, jmex, kmsx, kmex, &
  546. ipsx, ipex, jpsx, jpex, kpsx, kpex )
  547. # include "XPOSE_SPECTRAL_NUDGING_x2y.inc"
  548. CALL spectral_nudging_filter_3dy( grid%dif_yyy, ywavenum, &
  549. ids, ide, jds, jde, kds, kde, &
  550. imsy, imey, jmsy, jmey, kmsy, kmey, &
  551. ipsy, ipey, jpsy, jpey, kpsy, kpey )
  552. # include "XPOSE_SPECTRAL_NUDGING_y2z.inc"
  553. #else
  554. CALL spectral_nudging_filter_3dx( grid%dif_analysis, xwavenum, &
  555. ids, ide, jds, jde, kds, kde, &
  556. ims, ime, jms, jme, kms, kme, &
  557. ips, ipe, jps, jpe, kps, kpe )
  558. CALL spectral_nudging_filter_3dy( grid%dif_analysis, ywavenum, &
  559. ids, ide, jds, jde, kds, kde, &
  560. ims, ime, jms, jme, kms, kme, &
  561. ips, ipe, jps, jpe, kps, kpe )
  562. #endif
  563. ! Calculate tendency
  564. !$OMP PARALLEL DO &
  565. !$OMP PRIVATE ( ij, i,j,k )
  566. DO ij = 1 , num_tiles
  567. DO j=jts,jte
  568. DO k=kts,kte
  569. DO i=its,ite
  570. RPHNDGDTEN(i,k,j) = gph * wpbl(i,k,j,4) * wzfac(k,4) * tfac * &
  571. grid%dif_analysis(i,k,j)
  572. ENDDO
  573. ENDDO
  574. ENDDO
  575. ENDDO
  576. !$OMP END PARALLEL DO
  577. ENDIF
  578. #endif
  579. END SUBROUTINE spectral_nudging
  580. !------------------------------------------------------------------------------
  581. SUBROUTINE spectral_nudging_filter_3dx( f, nwave, &
  582. ids, ide, jds, jde, kds, kde, &
  583. ims, ime, jms, jme, kms, kme, &
  584. its, ite, jts, jte, kts, kte )
  585. IMPLICIT NONE
  586. INTEGER , INTENT(IN ) :: nwave
  587. INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
  588. ims, ime, jms, jme, kms, kme, &
  589. its, ite, jts, jte, kts, kte
  590. REAL , DIMENSION( ims:ime , kms:kme, jms:jme ) , INTENT(INOUT) :: f
  591. REAL , DIMENSION(1:ide-ids+1,1:kte-kts+1) :: sheet
  592. INTEGER :: i, j, j_end, k, nx, ny
  593. ! Variables will stay in domain form since this routine is meaningless
  594. ! unless tile extent is the same as domain extent in E/W direction, i.e.,
  595. ! the processor has access to all grid points in E/W direction.
  596. ! There may be other ways of doing FFTs, but we haven't learned them yet...
  597. ! Check to make sure we have full access to all E/W points
  598. IF ((its /= ids) .OR. (ite /= ide)) THEN
  599. WRITE ( wrf_err_message , * ) 'module_spectral_nudging: 3d: (its /= ids) or (ite /= ide)',its,ids,ite,ide
  600. CALL wrf_error_fatal ( TRIM( wrf_err_message ) )
  601. END IF
  602. nx = ide-ids+1
  603. ny = kte-kts+1 ! we can filter extra level for variables that are non-Z-staggered
  604. j_end = MIN(jte, jde-1)
  605. IF (j_end == jde-1) j_end = jde
  606. DO j = jts, j_end
  607. DO k=kts,kte
  608. DO i=ids,ide-1
  609. sheet(i-ids+1,k-kts+1) = f(i,k,j)
  610. END DO
  611. sheet(ide,k-kts+1) = 0.
  612. END DO
  613. CALL spectralnudgingfilterfft2dncar(nx,ny,nwave,sheet)
  614. DO k=kts,kte
  615. DO i=ids,ide
  616. f(i,k,j) = sheet(i-ids+1,k-kts+1)
  617. END DO
  618. END DO
  619. END DO ! outer j (latitude) loop
  620. END SUBROUTINE spectral_nudging_filter_3dx
  621. !------------------------------------------------------------------------------
  622. SUBROUTINE spectral_nudging_filter_3dy( f, nwave, &
  623. ids, ide, jds, jde, kds, kde, &
  624. ims, ime, jms, jme, kms, kme, &
  625. its, ite, jts, jte, kts, kte )
  626. IMPLICIT NONE
  627. INTEGER , INTENT(IN ) :: nwave
  628. INTEGER , INTENT(IN ) :: ids, ide, jds, jde, kds, kde, &
  629. ims, ime, jms, jme, kms, kme, &
  630. its, ite, jts, jte, kts, kte
  631. REAL , DIMENSION( ims:ime , kms:kme, jms:jme ) , INTENT(INOUT) :: f
  632. REAL , DIMENSION(1:jde-jds+1,1:kte-kts+1) :: sheet
  633. INTEGER :: i, j, i_end, k, nx, ny
  634. ! Variables will stay in domain form since this routine is meaningless
  635. ! unless tile extent is the same as domain extent in S/N direction, i.e.,
  636. ! the processor has access to all grid points in S/N direction.
  637. ! There may be other ways of doing FFTs, but we haven't learned them yet...
  638. ! Check to make sure we have full access to all S/N points
  639. IF ((jts /= jds) .OR. (jte /= jde)) THEN
  640. WRITE ( wrf_err_message , * ) 'module_spectral_nudging: 3d: (jts /= jds) or (jte /= jde)',jts,ids,ite,ide
  641. CALL wrf_error_fatal ( TRIM( wrf_err_message ) )
  642. END IF
  643. nx = jde-jds+1
  644. ny = kte-kts+1 ! we can filter extra level for variables that are non-Z-staggered
  645. i_end = MIN(ite, ide-1)
  646. IF (i_end == ide-1) i_end = ide
  647. DO i = its, i_end
  648. DO k=kts,kte
  649. DO j=jds,jde
  650. sheet(j-jds+1,k-kts+1) = f(i,k,j)
  651. END DO
  652. sheet(jde,k-kts+1) = 0.
  653. END DO
  654. CALL spectralnudgingfilterfft2dncar(nx,ny,nwave,sheet)
  655. DO k=kts,kte
  656. DO j=jds,jde
  657. f(i,k,j) = sheet(j-jds+1,k-kts+1)
  658. END DO
  659. END DO
  660. END DO ! outer i (longitude) loop
  661. END SUBROUTINE spectral_nudging_filter_3dy
  662. !------------------------------------------------------------------------------
  663. SUBROUTINE spectralnudgingfilterfft2dncar(nx,ny,nwave,fin)
  664. IMPLICIT NONE
  665. INTEGER , INTENT(IN) :: nx, ny, nwave
  666. REAL , DIMENSION(nx,ny), INTENT(INOUT) :: fin
  667. INTEGER :: i, j
  668. REAL, dimension(nx,ny) :: fp
  669. INTEGER :: lensave, ier, nh, n1
  670. INTEGER :: lot, jump, n, inc, lenr, lensav, lenwrk
  671. REAL, DIMENSION(nx+15) :: wsave
  672. REAL, DIMENSION(nx,ny) :: work
  673. ! we are following the naming convention of the fftpack5 routines
  674. n = nx
  675. lot = ny
  676. lensav = n+15
  677. inc = 1
  678. lenr = nx*ny
  679. jump = nx
  680. lenwrk = lenr
  681. ! forward transform
  682. ! initialize coefficients, place in wsave
  683. ! (should place this in init and save wsave at program start)
  684. call rfftmi(n,wsave,lensav,ier)
  685. IF(ier /= 0) THEN
  686. write(0,*) ' error in rfftmi ',ier
  687. END IF
  688. ! do the forward transform
  689. call rfftmf( lot, jump, n, inc, fin, lenr, wsave, lensav, work, lenwrk, ier )
  690. IF(ier /= 0) THEN
  691. write(0,*) ' error in rfftmf ',ier
  692. END IF
  693. if(MOD(n,2) == 0) then
  694. nh = n/2 - 1
  695. else
  696. nh = (n-1)/2
  697. end if
  698. ! filter all waves with wavenumber larger than nwave
  699. fp = 1.
  700. DO j=1,ny
  701. DO i=nwave+1,nh
  702. fp(2*i-1,j) = 0.
  703. fp(2*i,j) = 0.
  704. ENDDO
  705. ENDDO
  706. DO j=1,ny
  707. DO i=1,nx
  708. fin(i,j) = fp(i,j)*fin(i,j)
  709. ENDDO
  710. ENDDO
  711. ! do the backward transform
  712. call rfftmb( lot, jump, n, inc, fin, lenr, wsave, lensav, work, lenwrk, ier )
  713. IF(ier /= 0) THEN
  714. write(0,*) ' error in rfftmb ',ier
  715. END IF
  716. END SUBROUTINE spectralnudgingfilterfft2dncar
  717. !-------------------------------------------------------------------
  718. SUBROUTINE fddaspnudginginit(id,rundgdten,rvndgdten,rthndgdten,rphndgdten, &
  719. run_hours, &
  720. if_no_pbl_nudging_uv, if_no_pbl_nudging_t, if_no_pbl_nudging_ph, &
  721. if_zfac_uv, k_zfac_uv, dk_zfac_uv, &
  722. if_zfac_t, k_zfac_t, dk_zfac_t, &
  723. if_zfac_ph, k_zfac_ph, dk_zfac_ph, &
  724. guv, gt, gph, if_ramping, dtramp_min, end_fdda_hour, &
  725. xwavenum,ywavenum, &
  726. restart, allowed_to_read, &
  727. ids, ide, jds, jde, kds, kde, &
  728. ims, ime, jms, jme, kms, kme, &
  729. its, ite, jts, jte, kts, kte )
  730. !-------------------------------------------------------------------
  731. IMPLICIT NONE
  732. !-------------------------------------------------------------------
  733. !
  734. INTEGER , INTENT(IN) :: id
  735. LOGICAL, INTENT(IN) :: restart, allowed_to_read
  736. INTEGER, INTENT(IN) :: ids, ide, jds, jde, kds, kde, &
  737. ims, ime, jms, jme, kms, kme, &
  738. its, ite, jts, jte, kts, kte
  739. REAL, DIMENSION( ims:ime , kms:kme , jms:jme ), INTENT(OUT) :: &
  740. rundgdten, &
  741. rvndgdten, &
  742. rthndgdten, &
  743. rphndgdten
  744. INTEGER, INTENT(IN) :: run_hours
  745. INTEGER, INTENT(IN) :: if_no_pbl_nudging_uv, if_no_pbl_nudging_t, &
  746. if_no_pbl_nudging_ph, end_fdda_hour
  747. INTEGER, INTENT(IN) :: if_zfac_uv, if_zfac_t, if_zfac_ph
  748. INTEGER, INTENT(IN) :: k_zfac_uv, k_zfac_t, k_zfac_ph
  749. INTEGER, INTENT(IN) :: dk_zfac_uv, dk_zfac_t, dk_zfac_ph
  750. INTEGER, INTENT(IN) :: if_ramping
  751. INTEGER, INTENT(IN) :: xwavenum,ywavenum
  752. REAL, INTENT(IN) :: dtramp_min
  753. REAL, INTENT(IN) :: guv, gt, gph
  754. REAL :: actual_end_fdda_min
  755. INTEGER :: i, j, k
  756. LOGICAL , EXTERNAL :: wrf_dm_on_monitor
  757. CHARACTER (LEN=256) :: message
  758. IF ( wrf_dm_on_monitor() ) THEN
  759. IF( guv > 0.0) THEN
  760. WRITE(message,'(a,i1,a,e12.4,a,i4,a,i4)') &
  761. 'D0',id,' Spectral nudging for wind is turned on and Guv= ', guv,' xwave= ',xwavenum,' ywavenum= ',ywavenum
  762. CALL wrf_message(TRIM(message))
  763. ELSE IF( guv < 0.0 ) THEN
  764. CALL wrf_error_fatal('In grid FDDA, Guv must be positive.')
  765. ELSE
  766. WRITE(message,'(a,i1,a,e12.4)') &
  767. 'D0',id,' Spectral nudging for wind is turned off and Guv= ', guv
  768. CALL wrf_message(TRIM(message))
  769. ENDIF
  770. IF( gt > 0.0) THEN
  771. WRITE(message,'(a,i1,a,e12.4,a,i4,a,i4)') &
  772. 'D0',id,' Spectral nudging for temperature is turned on and Gt= ', gt,' xwave= ',xwavenum,' ywavenum= ',ywavenum
  773. CALL wrf_message(TRIM(message))
  774. ELSE IF( gt < 0.0 ) THEN
  775. CALL wrf_error_fatal('In grid FDDA, Gt must be positive.')
  776. ELSE
  777. WRITE(message,'(a,i1,a,e12.4)') &
  778. 'D0',id,' Spectral nudging for temperature is turned off and Gt= ', gt
  779. CALL wrf_message(TRIM(message))
  780. ENDIF
  781. IF( gph > 0.0) THEN
  782. WRITE(message,'(a,i1,a,e12.4,a,i4,a,i4)') &
  783. 'D0',id,' Spectral nudging for geopotential is turned on and Gph= ', gph,' xwave= ',xwavenum,' ywavenum= ',ywavenum
  784. CALL wrf_message(TRIM(message))
  785. ELSE IF( gph < 0.0 ) THEN
  786. CALL wrf_error_fatal('In grid FDDA, Gph must be positive.')
  787. ELSE
  788. WRITE(message,'(a,i1,a,e12.4)') &
  789. 'D0',id,' Spectral nudging for geopotential is turned off and Gph= ', gph
  790. CALL wrf_message(TRIM(message))
  791. ENDIF
  792. IF( guv > 0.0 .AND. if_no_pbl_nudging_uv == 1 ) THEN
  793. WRITE(message,'(a,i1,a)') &
  794. 'D0',id,' Spectral nudging for wind is turned off within the PBL.'
  795. CALL wrf_message(TRIM(message))
  796. IF( dk_zfac_uv < 1 ) CALL wrf_error_fatal('In spectral nudging, dk_zfac_uv must be greater or equal than 1.')
  797. ELSEIF( guv > 0.0 .AND. if_zfac_uv == 1 ) THEN
  798. WRITE(message,'(a,i1,a,i3)') &
  799. 'D0',id,' Spectral nudging for wind is turned off below layer', k_zfac_uv
  800. CALL wrf_message(TRIM(message))
  801. IF( dk_zfac_uv < 1 ) CALL wrf_error_fatal('In spectral nudging, dk_zfac_uv must be greater or equal than 1.')
  802. ENDIF
  803. IF( gt > 0.0 .AND. if_no_pbl_nudging_t == 1 ) THEN
  804. WRITE(message,'(a,i1,a)') &
  805. 'D0',id,' Spectral nudging for temperature is turned off within the PBL.'
  806. CALL wrf_message(TRIM(message))
  807. IF( dk_zfac_t < 1 ) CALL wrf_error_fatal('In spectral nudging, dk_zfac_t must be greater or equal than 1.')
  808. ELSEIF( gt > 0.0 .AND. if_zfac_t == 1 ) THEN
  809. WRITE(message,'(a,i1,a,i3)') &
  810. 'D0',id,' Spectral nudging for temperature is turned off below layer', k_zfac_t
  811. CALL wrf_message(TRIM(message))
  812. IF( dk_zfac_t < 1 ) CALL wrf_error_fatal('In spectral nudging, dk_zfac_t must be greater or equal than 1.')
  813. ENDIF
  814. IF( gph > 0.0 .AND. if_no_pbl_nudging_ph == 1 ) THEN
  815. WRITE(message,'(a,i1,a)') &
  816. 'D0',id,' Spectral nudging for geopotential is turned off within the PBL.'
  817. CALL wrf_message(TRIM(message))
  818. IF( dk_zfac_ph < 1 ) CALL wrf_error_fatal('In spectral nudging, dk_zfac_ph must be greater or equal than 1.')
  819. ELSEIF( gph > 0.0 .AND. if_zfac_ph == 1 ) THEN
  820. WRITE(message,'(a,i1,a,i3)') &
  821. 'D0',id,' Spectral nudging for geopotential is turned off below layer', &
  822. k_zfac_ph
  823. CALL wrf_message(TRIM(message))
  824. IF( dk_zfac_ph < 1 ) CALL wrf_error_fatal('In spectral nudging, dk_zfac_ph must be greater or equal than 1.')
  825. ENDIF
  826. IF( if_ramping == 1 .AND. ABS(dtramp_min) > 0.0 ) THEN
  827. IF( dtramp_min <= 0.0 ) THEN
  828. actual_end_fdda_min = end_fdda_hour*60.0
  829. ELSE
  830. actual_end_fdda_min = end_fdda_hour*60.0 + ABS(dtramp_min)
  831. ENDIF
  832. IF( actual_end_fdda_min <= run_hours*60. ) THEN
  833. WRITE(message,'(a,i1,a)') &
  834. 'D0',id,' Spectral nudging is ramped down near the end of the nudging period,'
  835. CALL wrf_message(TRIM(message))
  836. WRITE(message,'(a,f6.2,a,f6.2,a)') &
  837. ' starting at ', (actual_end_fdda_min - ABS(dtramp_min))/60.0,&
  838. 'h, ending at ', actual_end_fdda_min/60.0,'h.'
  839. CALL wrf_message(TRIM(message))
  840. ENDIF
  841. ENDIF
  842. ENDIF
  843. IF(.not.restart) THEN
  844. DO j = jts,jte
  845. DO k = kts,kte
  846. DO i = its,ite
  847. rundgdten(i,k,j) = 0.
  848. rvndgdten(i,k,j) = 0.
  849. rthndgdten(i,k,j) = 0.
  850. rphndgdten(i,k,j) = 0.
  851. ENDDO
  852. ENDDO
  853. ENDDO
  854. ENDIF
  855. END SUBROUTINE fddaspnudginginit
  856. !-------------------------------------------------------------------
  857. END MODULE module_fdda_spnudging