PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/wrfv2_fire/share/dfi.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 2909 lines | 1731 code | 567 blank | 611 comment | 17 complexity | cc24b016fea48a0ad33b12ada0258f2f MD5 | raw file
Possible License(s): AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. SUBROUTINE dfi_accumulate( grid )
  2. USE module_domain, ONLY : domain
  3. ! USE module_configure
  4. USE module_driver_constants
  5. USE module_machine
  6. ! USE module_dm
  7. USE module_model_constants
  8. USE module_state_description
  9. IMPLICIT NONE
  10. REAL hn
  11. CHARACTER*80 mess
  12. ! Input data.
  13. TYPE(domain) , POINTER :: grid
  14. IF ( grid%dfi_opt .EQ. DFI_NODFI .OR. grid%dfi_stage .EQ. DFI_FST ) RETURN
  15. #if (EM_CORE == 1)
  16. hn = grid%hcoeff(grid%itimestep+1)
  17. ! accumulate dynamic variables
  18. grid%dfi_mu(:,:) = grid%dfi_mu(:,:) + grid%mu_2(:,:) * hn
  19. grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u_2(:,:,:) * hn
  20. grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v_2(:,:,:) * hn
  21. grid%dfi_w(:,:,:) = grid%dfi_w(:,:,:) + grid%w_2(:,:,:) * hn
  22. grid%dfi_ww(:,:,:) = grid%dfi_ww(:,:,:) + grid%ww(:,:,:) * hn
  23. grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t_2(:,:,:) * hn
  24. grid%dfi_phb(:,:,:) = grid%dfi_phb(:,:,:) + grid%phb(:,:,:) * hn
  25. grid%dfi_ph0(:,:,:) = grid%dfi_ph0(:,:,:) + grid%ph0(:,:,:) * hn
  26. grid%dfi_php(:,:,:) = grid%dfi_php(:,:,:) + grid%php(:,:,:) * hn
  27. grid%dfi_p(:,:,:) = grid%dfi_p(:,:,:) + grid%p(:,:,:) * hn
  28. grid%dfi_ph(:,:,:) = grid%dfi_ph(:,:,:) + grid%ph_2(:,:,:) * hn
  29. grid%dfi_tke(:,:,:) = grid%dfi_tke(:,:,:) + grid%tke_2(:,:,:) * hn
  30. grid%dfi_al(:,:,:) = grid%dfi_al(:,:,:) + grid%al(:,:,:) * hn
  31. grid%dfi_alt(:,:,:) = grid%dfi_alt(:,:,:) + grid%alt(:,:,:) * hn
  32. grid%dfi_pb(:,:,:) = grid%dfi_pb(:,:,:) + grid%pb(:,:,:) * hn
  33. ! neg. check on hydrometeor and scalar variables
  34. grid%moist(:,:,:,:) = max(0.,grid%moist(:,:,:,:))
  35. grid%dfi_scalar(:,:,:,:) = max(0.,grid%dfi_scalar(:,:,:,:))
  36. #if ( WRF_DFI_RADAR == 1 )
  37. IF ( grid%dfi_radar .EQ. 0 ) then
  38. grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
  39. ELSE
  40. grid%dfi_moist(:,:,:,P_QV) = grid%dfi_moist(:,:,:,P_QV) + grid%moist(:,:,:,P_QV) * hn
  41. ENDIF
  42. #else
  43. grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
  44. #endif
  45. grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
  46. ! accumulate DFI coefficient
  47. grid%hcoeff_tot = grid%hcoeff_tot + hn
  48. #endif
  49. #if (NMM_CORE == 1)
  50. hn = grid%hcoeff(grid%ntsd+1)
  51. grid%dfi_pd(:,:) = grid%dfi_pd(:,:) + grid%pd(:,:) * hn
  52. grid%dfi_pint(:,:,:) = grid%dfi_pint(:,:,:) + grid%pint(:,:,:) * hn
  53. grid%dfi_dwdt(:,:,:) = grid%dfi_dwdt(:,:,:) + grid%dwdt(:,:,:) * hn
  54. grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t(:,:,:) * hn
  55. grid%dfi_q(:,:,:) = grid%dfi_q(:,:,:) + grid%q(:,:,:) * hn
  56. grid%dfi_q2(:,:,:) = grid%dfi_q2(:,:,:) + grid%q2(:,:,:) * hn
  57. grid%dfi_cwm(:,:,:) = grid%dfi_cwm(:,:,:) + grid%cwm(:,:,:) * hn
  58. grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u(:,:,:) * hn
  59. grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v(:,:,:) * hn
  60. grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
  61. grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
  62. ! accumulate DFI coefficient
  63. grid%hcoeff_tot = grid%hcoeff_tot + hn
  64. write(mess,*) 'grid%hcoeff_tot: ', grid%hcoeff_tot
  65. call wrf_message(mess)
  66. #endif
  67. END SUBROUTINE dfi_accumulate
  68. SUBROUTINE dfi_bck_init ( grid )
  69. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
  70. USE module_utility
  71. USE module_state_description
  72. IMPLICIT NONE
  73. TYPE (domain) , POINTER :: grid
  74. INTEGER rc
  75. CHARACTER*80 mess
  76. INTERFACE
  77. SUBROUTINE Setup_Timekeeping(grid)
  78. USE module_domain, ONLY : domain
  79. TYPE (domain), POINTER :: grid
  80. END SUBROUTINE Setup_Timekeeping
  81. SUBROUTINE dfi_save_arrays(grid)
  82. USE module_domain, ONLY : domain
  83. TYPE (domain), POINTER :: grid
  84. END SUBROUTINE dfi_save_arrays
  85. SUBROUTINE dfi_clear_accumulation(grid)
  86. USE module_domain, ONLY : domain
  87. TYPE (domain), POINTER :: grid
  88. END SUBROUTINE dfi_clear_accumulation
  89. SUBROUTINE optfil_driver(grid)
  90. USE module_domain, ONLY : domain
  91. TYPE (domain), POINTER :: grid
  92. END SUBROUTINE optfil_driver
  93. SUBROUTINE start_domain(grid, allowed_to_read)
  94. USE module_domain, ONLY : domain
  95. TYPE (domain) :: grid
  96. LOGICAL, INTENT(IN) :: allowed_to_read
  97. END SUBROUTINE start_domain
  98. END INTERFACE
  99. grid%dfi_stage = DFI_BCK
  100. ! Negate time step
  101. IF ( grid%time_step_dfi .gt. 0 ) THEN
  102. CALL nl_set_time_step ( 1, -grid%time_step_dfi )
  103. ELSE
  104. CALL nl_set_time_step ( 1, -grid%time_step )
  105. CALL nl_set_time_step_fract_num ( 1, -grid%time_step_fract_num )
  106. ENDIF
  107. CALL Setup_Timekeeping (grid)
  108. !tgs 7apr11 - need to call start_domain here to reset bc initialization for negative dt
  109. CALL start_domain ( grid , .TRUE. )
  110. !tgs 7apr11 - save arrays should be done after start_domain to get correct grid%p field
  111. CALL dfi_save_arrays ( grid )
  112. ! set physics options to zero
  113. CALL nl_set_mp_physics( grid%id, 0 )
  114. CALL nl_set_ra_lw_physics( grid%id, 0 )
  115. CALL nl_set_ra_sw_physics( grid%id, 0 )
  116. CALL nl_set_sf_surface_physics( grid%id, 0 )
  117. CALL nl_set_sf_sfclay_physics( grid%id, 0 )
  118. CALL nl_set_sf_urban_physics( grid%id, 0 )
  119. CALL nl_set_bl_pbl_physics( grid%id, 0 )
  120. CALL nl_set_cu_physics( grid%id, 0 )
  121. CALL nl_set_damp_opt( grid%id, 0 )
  122. CALL nl_set_sst_update( grid%id, 0 )
  123. CALL nl_set_fractional_seaice( grid%id, 0 )
  124. CALL nl_set_gwd_opt( grid%id, 0 )
  125. CALL nl_set_feedback( grid%id, 0 )
  126. ! set bc
  127. #if (EM_CORE == 1)
  128. CALL nl_set_diff_6th_opt( grid%id, 0 )
  129. CALL nl_set_constant_bc(1, grid%constant_bc)
  130. CALL nl_set_use_adaptive_time_step( grid%id, .false. )
  131. #endif
  132. #ifdef WRF_CHEM
  133. ! set chemistry option to zero
  134. CALL nl_set_chem_opt (grid%id, 0)
  135. CALL nl_set_aer_ra_feedback (grid%id, 0)
  136. CALL nl_set_io_form_auxinput5 (grid%id, 0)
  137. CALL nl_set_io_form_auxinput7 (grid%id, 0)
  138. CALL nl_set_io_form_auxinput8 (grid%id, 0)
  139. #endif
  140. ! set diffusion to zero for backward integration
  141. #if (EM_CORE == 1)
  142. CALL nl_set_km_opt( grid%id, grid%km_opt_dfi)
  143. CALL nl_set_moist_adv_dfi_opt( grid%id, grid%moist_adv_dfi_opt)
  144. IF ( grid%moist_adv_opt == 2 ) THEN
  145. CALL nl_set_moist_adv_opt( grid%id, 0)
  146. ENDIF
  147. #endif
  148. #if (NMM_CORE == 1)
  149. !
  150. ! CHANGE (SIGN ONLY OF) IMPORTANT TIME CONSTANTS
  151. !
  152. CALL nl_get_time_step( grid%id, grid%time_step )
  153. if (grid%time_step .lt. 0) then
  154. ! DT =-DT
  155. write(mess,*) 'changing signs for backward integration'
  156. call wrf_message(mess)
  157. grid%CPGFV = -grid%CPGFV
  158. grid%EN = -grid%EN
  159. grid%ENT = -grid%ENT
  160. grid%F4D = -grid%F4D
  161. grid%F4Q = -grid%F4Q
  162. grid%EF4T = -grid%EF4T
  163. grid%EM(:) = -grid%EM(:)
  164. grid%EMT(:) = -grid%EMT(:)
  165. grid%F4Q2(:) = -grid%F4Q2(:)
  166. grid%WPDAR(:,:)= -grid%WPDAR(:,:)
  167. grid%CPGFU(:,:)= -grid%CPGFU(:,:)
  168. grid%CURV(:,:)= -grid%CURV(:,:)
  169. grid%FCP(:,:)= -grid%FCP(:,:)
  170. grid%FAD(:,:)= -grid%FAD(:,:)
  171. grid%F(:,:)= -grid%F(:,:)
  172. endif
  173. #endif
  174. grid%start_subtime = domain_get_start_time ( grid )
  175. grid%stop_subtime = domain_get_stop_time ( grid )
  176. CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
  177. !tgs 7apr11 - this call has been moved up
  178. ! CALL dfi_save_arrays ( grid )
  179. CALL dfi_clear_accumulation( grid )
  180. CALL optfil_driver(grid)
  181. !tgs need to call start_domain here to reset bc initialization for negative dt
  182. CALL start_domain ( grid , .TRUE. )
  183. END SUBROUTINE dfi_bck_init
  184. SUBROUTINE dfi_fwd_init ( grid )
  185. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
  186. USE module_utility, ONLY : WRFU_ClockSet
  187. USE module_state_description
  188. IMPLICIT NONE
  189. TYPE (domain) , POINTER :: grid
  190. INTEGER rc
  191. CHARACTER*80 mess
  192. INTERFACE
  193. SUBROUTINE Setup_Timekeeping(grid)
  194. USE module_domain, ONLY : domain
  195. TYPE (domain), POINTER :: grid
  196. END SUBROUTINE Setup_Timekeeping
  197. SUBROUTINE dfi_save_arrays(grid)
  198. USE module_domain, ONLY : domain
  199. TYPE (domain), POINTER :: grid
  200. END SUBROUTINE dfi_save_arrays
  201. SUBROUTINE dfi_clear_accumulation(grid)
  202. USE module_domain, ONLY : domain
  203. TYPE (domain), POINTER :: grid
  204. END SUBROUTINE dfi_clear_accumulation
  205. SUBROUTINE optfil_driver(grid)
  206. USE module_domain, ONLY : domain
  207. TYPE (domain), POINTER :: grid
  208. END SUBROUTINE optfil_driver
  209. SUBROUTINE start_domain(grid, allowed_to_read)
  210. USE module_domain, ONLY : domain
  211. TYPE (domain) :: grid
  212. LOGICAL, INTENT(IN) :: allowed_to_read
  213. END SUBROUTINE start_domain
  214. END INTERFACE
  215. grid%dfi_stage = DFI_FWD
  216. ! for Setup_Timekeeping to use when setting the clock
  217. IF ( grid%time_step_dfi .gt. 0 ) THEN
  218. CALL nl_set_time_step ( grid%id, grid%time_step_dfi )
  219. ELSE
  220. CALL nl_get_time_step( grid%id, grid%time_step )
  221. CALL nl_get_time_step_fract_num( grid%id, grid%time_step_fract_num )
  222. grid%time_step = abs(grid%time_step)
  223. CALL nl_set_time_step( grid%id, grid%time_step )
  224. grid%time_step_fract_num = abs(grid%time_step_fract_num)
  225. CALL nl_set_time_step_fract_num( grid%id, grid%time_step_fract_num )
  226. ENDIF
  227. grid%itimestep=0
  228. grid%xtime=0.
  229. ! reset physics options to normal
  230. CALL nl_set_mp_physics( grid%id, grid%mp_physics)
  231. CALL nl_set_ra_lw_physics( grid%id, grid%ra_lw_physics)
  232. CALL nl_set_ra_sw_physics( grid%id, grid%ra_sw_physics)
  233. CALL nl_set_sf_surface_physics( grid%id, grid%sf_surface_physics)
  234. CALL nl_set_sf_sfclay_physics( grid%id, grid%sf_sfclay_physics)
  235. CALL nl_set_sf_urban_physics( grid%id, grid%sf_urban_physics)
  236. CALL nl_set_bl_pbl_physics( grid%id, grid%bl_pbl_physics)
  237. CALL nl_set_cu_physics( grid%id, grid%cu_physics)
  238. CALL nl_set_damp_opt( grid%id, grid%damp_opt)
  239. CALL nl_set_sst_update( grid%id, 0)
  240. CALL nl_set_fractional_seaice( grid%id, grid%fractional_seaice)
  241. CALL nl_set_gwd_opt( grid%id, grid%gwd_opt)
  242. CALL nl_set_feedback( grid%id, 0 )
  243. #if (EM_CORE == 1)
  244. CALL nl_set_diff_6th_opt( grid%id, grid%diff_6th_opt)
  245. CALL nl_set_use_adaptive_time_step( grid%id, .false. )
  246. ! set bc
  247. CALL nl_set_constant_bc(grid%id, grid%constant_bc)
  248. #endif
  249. #if (NMM_CORE == 1)
  250. !
  251. ! CHANGE (SIGN ONLY OF) IMPORTANT TIME CONSTANTS
  252. !
  253. !mptest CALL nl_get_time_step( grid%id, grid%time_step )
  254. !!! here need to key off something else being the "wrong" sign
  255. if (grid%cpgfv .gt. 0) then
  256. write(mess,*) 'changing signs for forward integration'
  257. call wrf_message(mess)
  258. grid%CPGFV = -grid%CPGFV
  259. grid%EN = -grid%EN
  260. grid%ENT = -grid%ENT
  261. grid%F4D = -grid%F4D
  262. grid%F4Q = -grid%F4Q
  263. grid%EF4T = -grid%EF4T
  264. grid%EM(:) = -grid%EM(:)
  265. grid%EMT(:) = -grid%EMT(:)
  266. grid%F4Q2(:) = -grid%F4Q2(:)
  267. grid%WPDAR(:,:)= -grid%WPDAR(:,:)
  268. grid%CPGFU(:,:)= -grid%CPGFU(:,:)
  269. grid%CURV(:,:)= -grid%CURV(:,:)
  270. grid%FCP(:,:)= -grid%FCP(:,:)
  271. grid%FAD(:,:)= -grid%FAD(:,:)
  272. grid%F(:,:)= -grid%F(:,:)
  273. endif
  274. #endif
  275. !#ifdef WRF_CHEM
  276. ! ! reset chem option to normal
  277. ! CALL nl_set_chem_opt( grid%id, grid%chem_opt)
  278. ! CALL nl_set_aer_ra_feedback (grid%id, grid%aer_ra_feedback)
  279. !#endif
  280. #if (EM_CORE == 1)
  281. ! reset km_opt to norlmal
  282. CALL nl_set_km_opt( grid%id, grid%km_opt)
  283. CALL nl_set_moist_adv_opt( grid%id, grid%moist_adv_opt)
  284. #endif
  285. CALL Setup_Timekeeping (grid)
  286. grid%start_subtime = domain_get_start_time ( head_grid )
  287. grid%stop_subtime = domain_get_stop_time ( head_grid )
  288. CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
  289. IF ( grid%dfi_opt .EQ. DFI_DFL ) THEN
  290. CALL dfi_save_arrays ( grid )
  291. END IF
  292. CALL dfi_clear_accumulation( grid )
  293. CALL optfil_driver(grid)
  294. !tgs need to call it here to reset bc initialization for positive time_step
  295. CALL start_domain ( grid , .TRUE. )
  296. END SUBROUTINE dfi_fwd_init
  297. SUBROUTINE dfi_fst_init ( grid )
  298. USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time
  299. USE module_state_description
  300. IMPLICIT NONE
  301. TYPE (domain) , POINTER :: grid
  302. CHARACTER (LEN=80) :: wrf_error_message
  303. INTERFACE
  304. SUBROUTINE Setup_Timekeeping(grid)
  305. USE module_domain, ONLY : domain
  306. TYPE (domain), POINTER :: grid
  307. END SUBROUTINE Setup_Timekeeping
  308. SUBROUTINE dfi_save_arrays(grid)
  309. USE module_domain, ONLY : domain
  310. TYPE (domain), POINTER :: grid
  311. END SUBROUTINE dfi_save_arrays
  312. SUBROUTINE dfi_clear_accumulation(grid)
  313. USE module_domain, ONLY : domain
  314. TYPE (domain), POINTER :: grid
  315. END SUBROUTINE dfi_clear_accumulation
  316. SUBROUTINE optfil_driver(grid)
  317. USE module_domain, ONLY : domain
  318. TYPE (domain), POINTER :: grid
  319. END SUBROUTINE optfil_driver
  320. SUBROUTINE start_domain(grid, allowed_to_read)
  321. USE module_domain, ONLY : domain
  322. TYPE (domain) :: grid
  323. LOGICAL, INTENT(IN) :: allowed_to_read
  324. END SUBROUTINE start_domain
  325. END INTERFACE
  326. grid%dfi_stage = DFI_FST
  327. ! reset time_step to normal and adaptive_time_step
  328. CALL nl_set_time_step( grid%id, grid%time_step )
  329. grid%itimestep=0
  330. grid%xtime=0. ! BUG: This will probably not work for all DFI options
  331. ! only use adaptive time stepping for forecast
  332. #if (EM_CORE == 1)
  333. if (grid%id == 1) then
  334. CALL nl_set_use_adaptive_time_step( 1, grid%use_adaptive_time_step )
  335. endif
  336. CALL nl_set_sst_update( grid%id, grid%sst_update)
  337. ! reset to normal bc
  338. CALL nl_set_constant_bc(grid%id, .false.)
  339. #endif
  340. CALL nl_set_feedback( grid%id, grid%feedback )
  341. #ifdef WRF_CHEM
  342. ! reset chem option to normal
  343. CALL nl_set_chem_opt( grid%id, grid%chem_opt)
  344. CALL nl_set_aer_ra_feedback (grid%id, grid%aer_ra_feedback)
  345. CALL nl_set_io_form_auxinput5 (grid%id, grid%io_form_auxinput5)
  346. CALL nl_set_io_form_auxinput7 (grid%id, grid%io_form_auxinput7)
  347. CALL nl_set_io_form_auxinput8 (grid%id, grid%io_form_auxinput8)
  348. #endif
  349. CALL Setup_Timekeeping (grid)
  350. grid%start_subtime = domain_get_start_time ( grid )
  351. grid%stop_subtime = domain_get_stop_time ( grid )
  352. CALL start_domain ( grid , .TRUE. )
  353. END SUBROUTINE dfi_fst_init
  354. SUBROUTINE dfi_write_initialized_state( grid )
  355. ! Driver layer
  356. USE module_domain, ONLY : domain, head_grid
  357. USE module_io_domain
  358. USE module_configure, ONLY : grid_config_rec_type, model_config_rec
  359. IMPLICIT NONE
  360. TYPE (domain) , POINTER :: grid
  361. INTEGER :: fid, ierr
  362. CHARACTER (LEN=80) :: wrf_error_message
  363. CHARACTER (LEN=80) :: rstname
  364. CHARACTER (LEN=132) :: message
  365. TYPE (grid_config_rec_type) :: config_flags
  366. CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
  367. WRITE (wrf_err_message,'(A,I4)') 'Writing out initialized model state'
  368. CALL wrf_message(TRIM(wrf_err_message))
  369. WRITE (rstname,'(A,I2.2)')'wrfinput_initialized_d',grid%id
  370. CALL open_w_dataset ( fid, TRIM(rstname), grid, config_flags, output_input, "DATASET=INPUT", ierr )
  371. IF ( ierr .NE. 0 ) THEN
  372. WRITE( message , '("program wrf: error opening ",A," for writing")') TRIM(rstname)
  373. CALL WRF_ERROR_FATAL ( message )
  374. END IF
  375. CALL output_input ( fid, grid, config_flags, ierr )
  376. CALL close_dataset ( fid, config_flags, "DATASET=INPUT" )
  377. END SUBROUTINE dfi_write_initialized_state
  378. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  379. ! DFI array reset group of functions
  380. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  381. SUBROUTINE wrf_dfi_array_reset ( )
  382. USE module_domain, ONLY : domain, head_grid, set_current_grid_ptr
  383. IMPLICIT NONE
  384. INTERFACE
  385. RECURSIVE SUBROUTINE dfi_array_reset_recurse(grid)
  386. USE module_domain, ONLY : domain
  387. TYPE (domain), POINTER :: grid
  388. END SUBROUTINE dfi_array_reset_recurse
  389. END INTERFACE
  390. ! Copy filtered arrays back into state arrays in grid structure, and
  391. ! restore original land surface fields
  392. CALL dfi_array_reset_recurse(head_grid)
  393. CALL set_current_grid_ptr( head_grid )
  394. END SUBROUTINE wrf_dfi_array_reset
  395. SUBROUTINE dfi_array_reset( grid )
  396. USE module_domain, ONLY : domain
  397. ! USE module_configure
  398. ! USE module_driver_constants
  399. ! USE module_machine
  400. ! USE module_dm
  401. USE module_model_constants
  402. USE module_state_description
  403. IMPLICIT NONE
  404. INTEGER :: its, ite, jts, jte, kts, kte, &
  405. i, j, k
  406. ! Input data.
  407. TYPE(domain) , POINTER :: grid
  408. ! local
  409. ! real p1000mb,eps,svp1,svp2,svp3,svpt0
  410. real eps
  411. ! parameter (p1000mb = 1.e+05, eps=0.622,svp1=0.6112,svp3=29.65,svpt0=273.15)
  412. parameter (eps=0.622)
  413. REAL es,qs,pol,tx,temp,pres,rslf
  414. CHARACTER*80 mess
  415. IF ( grid%dfi_opt .EQ. DFI_NODFI ) RETURN
  416. ! Set dynamic variables
  417. ! divide by total DFI coefficient
  418. #if (EM_CORE == 1)
  419. grid%mu_2(:,:) = grid%dfi_mu(:,:) / grid%hcoeff_tot
  420. grid%u_2(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
  421. grid%v_2(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
  422. grid%w_2(:,:,:) = grid%dfi_w(:,:,:) / grid%hcoeff_tot
  423. grid%ww(:,:,:) = grid%dfi_ww(:,:,:) / grid%hcoeff_tot
  424. grid%t_2(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
  425. grid%phb(:,:,:) = grid%dfi_phb(:,:,:) / grid%hcoeff_tot
  426. grid%ph0(:,:,:) = grid%dfi_ph0(:,:,:) / grid%hcoeff_tot
  427. grid%php(:,:,:) = grid%dfi_php(:,:,:) / grid%hcoeff_tot
  428. grid%p(:,:,:) = grid%dfi_p(:,:,:) / grid%hcoeff_tot
  429. grid%ph_2(:,:,:) = grid%dfi_ph(:,:,:) / grid%hcoeff_tot
  430. grid%tke_2(:,:,:) = grid%dfi_tke(:,:,:) / grid%hcoeff_tot
  431. grid%al(:,:,:) = grid%dfi_al(:,:,:) / grid%hcoeff_tot
  432. grid%alt(:,:,:) = grid%dfi_alt(:,:,:) / grid%hcoeff_tot
  433. grid%pb(:,:,:) = grid%dfi_pb(:,:,:) / grid%hcoeff_tot
  434. #if ( WRF_DFI_RADAR == 1 )
  435. IF ( grid%dfi_radar .EQ. 0 ) then ! tgs no radar assimilation
  436. grid%moist(:,:,:,:) = max(0.,grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot)
  437. ELSE
  438. grid%moist(:,:,:,P_QV) = max(0.,grid%dfi_moist(:,:,:,P_QV) / grid%hcoeff_tot)
  439. ENDIF
  440. #else
  441. grid%moist(:,:,:,:) = max(0.,grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot)
  442. #endif
  443. grid%scalar(:,:,:,:) = max(0.,grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot)
  444. ! restore initial fields
  445. grid%SNOW (:,:) = grid%dfi_SNOW (:,:)
  446. grid%SNOWH (:,:) = grid%dfi_SNOWH (:,:)
  447. grid%SNOWC (:,:) = grid%dfi_SNOWC (:,:)
  448. grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
  449. grid%TSK (:,:) = grid%dfi_TSK (:,:)
  450. grid%TSLB (:,:,:) = grid%dfi_TSLB (:,:,:)
  451. grid%SMOIS (:,:,:) = grid%dfi_SMOIS (:,:,:)
  452. IF ( grid%sf_surface_physics .EQ. 3 ) then
  453. grid%QVG (:,:) = grid%dfi_QVG (:,:)
  454. grid%TSNAV (:,:) = grid%dfi_TSNAV (:,:)
  455. grid%SOILT1(:,:) = grid%dfi_SOILT1(:,:)
  456. grid%SMFR3D(:,:,:) = grid%dfi_SMFR3D (:,:,:)
  457. grid%KEEPFR3DFLAG(:,:,:) = grid%dfi_KEEPFR3DFLAG(:,:,:)
  458. ENDIF
  459. ! restore analized hydrometeor fileds
  460. #if ( WRF_DFI_RADAR == 1 )
  461. IF ( grid%dfi_radar .EQ. 1 ) then
  462. ! grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) !tgs
  463. grid%moist(:,:,:,P_QC) = grid%dfi_moist(:,:,:,P_QC) !tgs
  464. grid%moist(:,:,:,P_QR) = grid%dfi_moist(:,:,:,P_QR) !tgs
  465. grid%moist(:,:,:,P_QI) = grid%dfi_moist(:,:,:,P_QI) !tgs
  466. grid%moist(:,:,:,P_QS) = grid%dfi_moist(:,:,:,P_QS) !tgs
  467. grid%moist(:,:,:,P_QG) = grid%dfi_moist(:,:,:,P_QG) !tgs
  468. if(grid%dfi_stage .EQ. DFI_FWD) then
  469. !tgs change QV to restore initial RH field after the diabatic DFI
  470. its = grid%sp31 ; ite = grid%ep31 ;
  471. kts = grid%sp32 ; kte = grid%ep32 ;
  472. jts = grid%sp33 ; jte = grid%ep33 ;
  473. DO j=jts,jte
  474. DO i=its,ite
  475. do k = kts , kte
  476. temp = (grid%t_2(i,k,j)+t0)*( (grid%p(i,k,j)+grid%pb(i,k,j))/p1000mb )&
  477. ** (r_d / Cp)
  478. pres = grid%p(i,k,j)+grid%pb(i,k,j)
  479. !tgs rslf - function to compute qs from Thompson microphysics
  480. qs = rslf(pres, temp)
  481. ! if(i.eq. 178 .and. j.eq. 148 .and. k.eq.11) then
  482. ! print *,'temp,pres,qs-thomp',temp,pres,qs
  483. ! endif
  484. IF(grid%moist(i,k,j,P_QC) .GT. 1.e-6 .or. &
  485. grid%moist(i,k,j,P_QI) .GT. 1.e-6) THEN
  486. grid%moist (i,k,j,P_QV) = MAX(0.,grid%dfi_rh(i,k,j)*QS)
  487. ENDIF
  488. ! if(i.eq. 178 .and. j.eq. 148 .and. k.eq.11) then
  489. ! print *,'temp,pres,qs,grid%moist (i,k,j,P_QV)',temp,pres,qs, &
  490. ! grid%moist(i,k,j,P_QV)
  491. ! endif
  492. enddo
  493. ENDDO
  494. ENDDO
  495. endif
  496. ENDIF
  497. #endif
  498. #endif
  499. #if (NMM_CORE == 1)
  500. write(mess,*) ' divide by grid%hcoeff_tot: ', grid%hcoeff_tot
  501. call wrf_message(mess)
  502. if (grid%hcoeff_tot .lt. 0.0001) then
  503. call wrf_error_fatal("bad grid%hcoeff_tot")
  504. endif
  505. grid%pd(:,:) = grid%dfi_pd(:,:) / grid%hcoeff_tot
  506. grid%pint(:,:,:) = grid%dfi_pint(:,:,:) / grid%hcoeff_tot
  507. ! grid%dwdt(:,:,:) = grid%dfi_dwdt(:,:,:) / grid%hcoeff_tot
  508. grid%t(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
  509. grid%q(:,:,:) = grid%dfi_q(:,:,:) / grid%hcoeff_tot
  510. grid%q2(:,:,:) = grid%dfi_q2(:,:,:) / grid%hcoeff_tot
  511. grid%cwm(:,:,:) = grid%dfi_cwm(:,:,:) / grid%hcoeff_tot
  512. grid%u(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
  513. grid%v(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
  514. grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot
  515. grid%scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot
  516. ! restore initial fields
  517. grid%SNOW(:,:) = grid%dfi_SNOW(:,:)
  518. grid%SNOWH(:,:) = grid%dfi_SNOWH(:,:)
  519. ! grid%SNOWC(:,:) = grid%dfi_SNOWC(:,:)
  520. grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
  521. grid%NMM_TSK(:,:) = grid%dfi_NMM_TSK(:,:)
  522. ! save soil fields
  523. grid%STC(:,:,:) = grid%dfi_STC(:,:,:)
  524. grid%SMC(:,:,:) = grid%dfi_SMC(:,:,:)
  525. grid%SH2O(:,:,:) = grid%dfi_SH2O(:,:,:)
  526. #endif
  527. END SUBROUTINE dfi_array_reset
  528. SUBROUTINE optfil_driver( grid )
  529. USE module_domain, ONLY : domain
  530. USE module_utility
  531. ! USE module_wrf_error
  532. ! USE module_timing
  533. ! USE module_date_time
  534. ! USE module_configure
  535. USE module_state_description
  536. USE module_model_constants
  537. IMPLICIT NONE
  538. TYPE (domain) , POINTER :: grid
  539. ! Local variables
  540. integer :: nstep2, nstepmax, rundfi, i, rc,hr,min,sec
  541. integer :: yr,jday
  542. real :: timestep, tauc
  543. TYPE(WRFU_TimeInterval) :: run_interval
  544. CHARACTER*80 mess
  545. timestep=abs(grid%dt)
  546. run_interval = grid%stop_subtime - grid%start_subtime
  547. CALL WRFU_TimeGet(grid%start_subtime, YY=yr, dayofYear=jday, H=hr, M=min, S=sec, rc=rc)
  548. CALL WRFU_TimeGet(grid%stop_subtime, YY=yr, dayofYear=jday, H=hr, M=min, S=sec, rc=rc)
  549. CALL WRFU_TimeIntervalGet( run_interval, S=rundfi, rc=rc )
  550. rundfi = abs(rundfi)
  551. nstep2= ceiling((1.0 + real(rundfi)/timestep) / 2.0)
  552. ! nstep2 is equal to a half of timesteps per initialization period,
  553. ! should not exceed nstepmax
  554. tauc = real(grid%dfi_cutoff_seconds)
  555. ! Get DFI coefficient
  556. grid%hcoeff(:) = 0.0
  557. IF ( grid%dfi_nfilter < 0 .OR. grid%dfi_nfilter > 8 ) THEN
  558. write(mess,*) 'Invalid filter specified in namelist.'
  559. call wrf_message(mess)
  560. ELSE
  561. call dfcoef(nstep2-1, grid%dt, tauc, grid%dfi_nfilter, grid%hcoeff)
  562. END IF
  563. IF ( MOD(int(1.0 + real(rundfi)/timestep),2) /= 0 ) THEN
  564. DO i=1,nstep2-1
  565. grid%hcoeff(2*nstep2-i) = grid%hcoeff(i)
  566. END DO
  567. ELSE
  568. DO i=1,nstep2
  569. grid%hcoeff(2*nstep2-i+1) = grid%hcoeff(i)
  570. END DO
  571. END IF
  572. END SUBROUTINE optfil_driver
  573. SUBROUTINE dfi_clear_accumulation( grid )
  574. USE module_domain, ONLY : domain
  575. ! USE module_configure
  576. ! USE module_driver_constants
  577. ! USE module_machine
  578. ! USE module_dm
  579. ! USE module_model_constants
  580. USE module_state_description
  581. IMPLICIT NONE
  582. ! Input data.
  583. TYPE(domain) , POINTER :: grid
  584. #if (EM_CORE == 1)
  585. grid%dfi_mu(:,:) = 0.
  586. grid%dfi_u(:,:,:) = 0.
  587. grid%dfi_v(:,:,:) = 0.
  588. grid%dfi_w(:,:,:) = 0.
  589. grid%dfi_ww(:,:,:) = 0.
  590. grid%dfi_t(:,:,:) = 0.
  591. grid%dfi_phb(:,:,:) = 0.
  592. grid%dfi_ph0(:,:,:) = 0.
  593. grid%dfi_php(:,:,:) = 0.
  594. grid%dfi_p(:,:,:) = 0.
  595. grid%dfi_ph(:,:,:) = 0.
  596. grid%dfi_tke(:,:,:) = 0.
  597. grid%dfi_al(:,:,:) = 0.
  598. grid%dfi_alt(:,:,:) = 0.
  599. grid%dfi_pb(:,:,:) = 0.
  600. #if ( WRF_DFI_RADAR == 1 )
  601. IF ( grid%dfi_radar .EQ. 0 ) then
  602. grid%dfi_moist(:,:,:,:) = 0.
  603. ELSE
  604. grid%dfi_moist(:,:,:,P_QV) = 0.
  605. ENDIF
  606. #else
  607. grid%dfi_moist(:,:,:,:) = 0.
  608. #endif
  609. grid%dfi_scalar(:,:,:,:) = 0.
  610. #endif
  611. #if (NMM_CORE == 1)
  612. grid%dfi_pd(:,:) = 0.
  613. grid%dfi_pint(:,:,:) = 0.
  614. grid%dfi_dwdt(:,:,:) = 0.
  615. grid%dfi_t(:,:,:) = 0.
  616. grid%dfi_q(:,:,:) = 0.
  617. grid%dfi_q2(:,:,:) = 0.
  618. grid%dfi_cwm(:,:,:) = 0.
  619. grid%dfi_u(:,:,:) = 0.
  620. grid%dfi_v(:,:,:) = 0.
  621. grid%dfi_moist(:,:,:,:) = 0.
  622. grid%dfi_scalar(:,:,:,:) = 0.
  623. #endif
  624. grid%hcoeff_tot = 0.0
  625. END SUBROUTINE dfi_clear_accumulation
  626. SUBROUTINE dfi_save_arrays( grid )
  627. USE module_domain, ONLY : domain
  628. ! USE module_configure
  629. ! USE module_driver_constants
  630. ! USE module_machine
  631. ! USE module_dm
  632. USE module_model_constants
  633. USE module_state_description
  634. IMPLICIT NONE
  635. INTEGER :: its, ite, jts, jte, kts, kte, &
  636. i, j, k
  637. ! Input data.
  638. TYPE(domain) , POINTER :: grid
  639. ! local
  640. REAL es,qs,pol,tx,temp,pres,rslf
  641. #if (EM_CORE == 1)
  642. ! save surface 2-D fields
  643. grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
  644. grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
  645. grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
  646. grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
  647. grid%dfi_TSK(:,:) = grid%TSK(:,:)
  648. ! save soil fields
  649. grid%dfi_TSLB(:,:,:) = grid%TSLB(:,:,:)
  650. grid%dfi_SMOIS(:,:,:) = grid%SMOIS(:,:,:)
  651. ! RUC LSM only, need conditional
  652. IF ( grid%sf_surface_physics .EQ. 3 ) then
  653. grid%dfi_QVG(:,:) = grid%QVG(:,:)
  654. grid%dfi_SOILT1(:,:) = grid%SOILT1(:,:)
  655. grid%dfi_TSNAV(:,:) = grid%TSNAV(:,:)
  656. grid%dfi_SMFR3D(:,:,:) = grid%SMFR3D(:,:,:)
  657. grid%dfi_KEEPFR3DFLAG(:,:,:) = grid%KEEPFR3DFLAG(:,:,:)
  658. ENDIF
  659. #endif
  660. #if (NMM_CORE == 1)
  661. ! save surface 2-D fields
  662. grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
  663. grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
  664. ! grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
  665. grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
  666. grid%dfi_NMM_TSK(:,:) = grid%NMM_TSK(:,:)
  667. ! save soil fields
  668. grid%dfi_STC(:,:,:) = grid%STC(:,:,:)
  669. grid%dfi_SMC(:,:,:) = grid%SMC(:,:,:)
  670. grid%dfi_SH2O(:,:,:) = grid%SH2O(:,:,:)
  671. #endif
  672. ! save hydrometeor fields
  673. #if (EM_CORE == 1)
  674. #if ( WRF_DFI_RADAR == 1 )
  675. IF ( grid%dfi_radar .EQ. 1 ) then !tgs
  676. ! grid%dfi_moist(:,:,:,:) = grid%moist(:,:,:,:)
  677. grid%dfi_moist(:,:,:,P_QC) = grid%moist(:,:,:,P_QC)
  678. grid%dfi_moist(:,:,:,P_QR) = grid%moist(:,:,:,P_QR)
  679. grid%dfi_moist(:,:,:,P_QI) = grid%moist(:,:,:,P_QI)
  680. grid%dfi_moist(:,:,:,P_QS) = grid%moist(:,:,:,P_QS)
  681. grid%dfi_moist(:,:,:,P_QG) = grid%moist(:,:,:,P_QG)
  682. if(grid%dfi_stage .EQ. DFI_BCK) then
  683. ! compute initial RH field to be reintroduced after the diabatic DFI
  684. its = grid%sp31 ; ite = grid%ep31 ;
  685. kts = grid%sp32 ; kte = grid%ep32 ;
  686. jts = grid%sp33 ; jte = grid%ep33 ;
  687. DO j=jts,jte
  688. DO i=its,ite
  689. do k = kts , kte
  690. temp = (grid%t_2(i,k,j)+t0)*( (grid%p(i,k,j)+grid%pb(i,k,j))/p1000mb )&
  691. ** (r_d / Cp)
  692. pres = grid%p(i,k,j)+grid%pb(i,k,j)
  693. !tgs rslf - function to compute qs from Thompson microphysics
  694. qs = rslf(pres, temp)
  695. grid%dfi_rh (i,k,j) = MIN(1.,MAX(0.,grid%moist(i,k,j,P_QV)/qs))
  696. !tgs saturation check for points with water or ice clouds
  697. IF ((grid%moist (i,k,j,P_QC) .GT. 1.e-6 .or. &
  698. grid%moist (i,k,j,P_QI) .GT. 1.e-6) .and. &
  699. grid%dfi_rh (i,k,j) .lt. 1.) THEN
  700. grid%dfi_rh (i,k,j)=1.
  701. ENDIF
  702. end do
  703. END DO
  704. ENDDO
  705. endif
  706. ENDIF
  707. #endif
  708. #endif
  709. END SUBROUTINE dfi_save_arrays
  710. SUBROUTINE dfcoef (NSTEPS,DT,TAUC,NFILT,H)
  711. !
  712. ! calculate filter weights with selected window.
  713. !
  714. ! peter lynch and xiang-yu huang
  715. !
  716. ! ref: see hamming, r.w., 1989: digital filters,
  717. ! prentice-hall international. 3rd edition.
  718. !
  719. ! input: nsteps - number of timesteps
  720. ! forward or backward.
  721. ! dt - time step in seconds.
  722. ! tauc - cut-off period in seconds.
  723. ! nfilt - indicator for selected filter.
  724. !
  725. ! output: h - array(0:nsteps) with the
  726. ! required filter weights
  727. !
  728. !------------------------------------------------------------
  729. implicit none
  730. integer, intent(in) :: nsteps, nfilt
  731. real , intent(in) :: dt, tauc
  732. real, intent(out) :: h(1:nsteps+1)
  733. ! Local data
  734. integer :: n
  735. real :: pi, omegac, x, window, deltat
  736. real :: hh(0:nsteps)
  737. pi=4*ATAN(1.)
  738. deltat=ABS(dt)
  739. ! windows are defined by a call and held in hh.
  740. if ( nfilt .eq. -1) call debug (nsteps,h)
  741. IF ( NFILT .EQ. 0 ) CALL UNIFORM (NSTEPS,HH)
  742. IF ( NFILT .EQ. 1 ) CALL LANCZOS (NSTEPS,HH)
  743. IF ( NFILT .EQ. 2 ) CALL HAMMING (NSTEPS,HH)
  744. IF ( NFILT .EQ. 3 ) CALL BLACKMAN (NSTEPS,HH)
  745. IF ( NFILT .EQ. 4 ) CALL KAISER (NSTEPS,HH)
  746. IF ( NFILT .EQ. 5 ) CALL POTTER2 (NSTEPS,HH)
  747. IF ( NFILT .EQ. 6 ) CALL DOLPHWIN (NSTEPS,HH)
  748. IF ( NFILT .LE. 6 ) THEN ! sinc-windowed filters
  749. ! calculate the cutoff frequency
  750. OMEGAC = 2.*PI/TAUC
  751. DO N=0,NSTEPS
  752. WINDOW = HH(N)
  753. IF ( N .EQ. 0 ) THEN
  754. X = (OMEGAC*DELTAT/PI)
  755. ELSE
  756. X = SIN(N*OMEGAC*DELTAT)/(N*PI)
  757. END IF
  758. HH(N) = X*WINDOW
  759. END DO
  760. ! normalize the sums to be unity
  761. CALL NORMLZ(HH,NSTEPS)
  762. DO N=0,NSTEPS
  763. H(N+1) = HH(NSTEPS-N)
  764. END DO
  765. ELSE IF ( NFILT .EQ. 7 ) THEN ! dolph filter
  766. CALL DOLPH(DT,TAUC,NSTEPS,H)
  767. ELSE IF ( NFILT .EQ. 8 ) THEN ! 2nd order, 2nd type quick start filter (RHO)
  768. CALL RHOFIL(DT,TAUC,2,NSTEPS*2,2,H,NSTEPS)
  769. END IF
  770. RETURN
  771. END SUBROUTINE dfcoef
  772. SUBROUTINE NORMLZ(HH,NMAX)
  773. ! normalize the sum of hh to be unity
  774. implicit none
  775. integer, intent(in) :: nmax
  776. real , dimension(0:nmax), intent(out) :: hh
  777. ! local data
  778. real :: sumhh
  779. integer :: n
  780. SUMHH = HH(0)
  781. DO N=1,NMAX
  782. SUMHH = SUMHH + 2*HH(N)
  783. ENDDO
  784. DO N=0,NMAX
  785. HH(N) = HH(N)/SUMHH
  786. ENDDO
  787. RETURN
  788. END subroutine normlz
  789. subroutine debug(nsteps, ww)
  790. implicit none
  791. integer, intent(in) :: nsteps
  792. real , dimension(0:nsteps), intent(out) :: ww
  793. integer :: n
  794. do n=0,nsteps
  795. ww(n)=0
  796. end do
  797. ww(int(nsteps/2))=1
  798. return
  799. end subroutine debug
  800. SUBROUTINE UNIFORM(NSTEPS,WW)
  801. ! define uniform or rectangular window function.
  802. implicit none
  803. integer, intent(in) :: nsteps
  804. real , dimension(0:nsteps), intent(out) :: ww
  805. integer :: n
  806. DO N=0,NSTEPS
  807. WW(N) = 1.
  808. ENDDO
  809. RETURN
  810. END subroutine uniform
  811. SUBROUTINE LANCZOS(NSTEPS,WW)
  812. ! define (genaralised) lanczos window function.
  813. implicit none
  814. integer, parameter :: nmax = 1000
  815. integer, intent(in) :: nsteps
  816. real , dimension(0:nmax), intent(out) :: ww
  817. integer :: n
  818. real :: power, pi, w
  819. ! (for the usual lanczos window, power = 1 )
  820. POWER = 1
  821. PI=4*ATAN(1.)
  822. DO N=0,NSTEPS
  823. IF ( N .EQ. 0 ) THEN
  824. W = 1.0
  825. ELSE
  826. W = SIN(N*PI/(NSTEPS+1)) / ( N*PI/(NSTEPS+1))
  827. ENDIF
  828. WW(N) = W**POWER
  829. ENDDO
  830. RETURN
  831. END SUBROUTINE lanczos
  832. SUBROUTINE HAMMING(NSTEPS,WW)
  833. ! define (genaralised) hamming window function.
  834. implicit none
  835. integer, intent(in) :: nsteps
  836. real, dimension(0:nsteps) :: ww
  837. integer :: n
  838. real :: alpha, pi, w
  839. ! (for the usual hamming window, alpha=0.54,
  840. ! for the hann window, alpha=0.50).
  841. ALPHA=0.54
  842. PI=4*ATAN(1.)
  843. DO N=0,NSTEPS
  844. IF ( N .EQ. 0 ) THEN
  845. W = 1.0
  846. ELSE
  847. W = ALPHA + (1-ALPHA)*COS(N*PI/(NSTEPS))
  848. ENDIF
  849. WW(N) = W
  850. ENDDO
  851. RETURN
  852. END SUBROUTINE hamming
  853. SUBROUTINE BLACKMAN(NSTEPS,WW)
  854. ! define blackman window function.
  855. implicit none
  856. integer, intent(in) :: nsteps
  857. real, dimension(0:nsteps) :: ww
  858. integer :: n
  859. real :: pi, w
  860. PI=4*ATAN(1.)
  861. DO N=0,NSTEPS
  862. IF ( N .EQ. 0 ) THEN
  863. W = 1.0
  864. ELSE
  865. W = 0.42 + 0.50*COS( N*PI/(NSTEPS)) &
  866. + 0.08*COS(2*N*PI/(NSTEPS))
  867. ENDIF
  868. WW(N) = W
  869. ENDDO
  870. RETURN
  871. END SUBROUTINE blackman
  872. SUBROUTINE KAISER(NSTEPS,WW)
  873. ! define kaiser window function.
  874. implicit none
  875. real, external :: bessi0
  876. integer, intent(in) :: nsteps
  877. real, dimension(0:nsteps) :: ww
  878. integer :: n
  879. real :: alpha, xi0a, xn, as
  880. ALPHA = 1
  881. XI0A = BESSI0(ALPHA)
  882. DO N=0,NSTEPS
  883. XN = N
  884. AS = ALPHA*SQRT(1.-(XN/NSTEPS)**2)
  885. WW(N) = BESSI0(AS) / XI0A
  886. ENDDO
  887. RETURN
  888. END SUBROUTINE kaiser
  889. REAL FUNCTION BESSI0(X)
  890. ! from numerical recipes (press, et al.)
  891. implicit none
  892. real(8) :: Y
  893. real(8) :: P1 = 1.0d0
  894. real(8) :: P2 = 3.5156230D0
  895. real(8) :: P3 = 3.0899424D0
  896. real(8) :: P4 = 1.2067492D0
  897. real(8) :: P5 = 0.2659732D0
  898. real(8) :: P6 = 0.360768D-1
  899. real(8) :: P7 = 0.45813D-2
  900. real*8 :: Q1 = 0.39894228D0
  901. real*8 :: Q2 = 0.1328592D-1
  902. real*8 :: Q3 = 0.225319D-2
  903. real*8 :: Q4 = -0.157565D-2
  904. real*8 :: Q5 = 0.916281D-2
  905. real*8 :: Q6 = -0.2057706D-1
  906. real*8 :: Q7 = 0.2635537D-1
  907. real*8 :: Q8 = -0.1647633D-1
  908. real*8 :: Q9 = 0.392377D-2
  909. real :: x, ax
  910. IF (ABS(X).LT.3.75) THEN
  911. Y=(X/3.75)**2
  912. BESSI0=P1+Y*(P2+Y*(P3+Y*(P4+Y*(P5+Y*(P6+Y*P7)))))
  913. ELSE
  914. AX=ABS(X)
  915. Y=3.75/AX
  916. BESSI0=(EXP(AX)/SQRT(AX))*(Q1+Y*(Q2+Y*(Q3+Y*(Q4 &
  917. +Y*(Q5+Y*(Q6+Y*(Q7+Y*(Q8+Y*Q9))))))))
  918. ENDIF
  919. RETURN
  920. END FUNCTION bessi0
  921. SUBROUTINE POTTER2(NSTEPS,WW)
  922. ! define potter window function.
  923. ! modified to fall off over twice the range.
  924. implicit none
  925. integer, intent(in) :: nsteps
  926. real, dimension(0:nsteps),intent(out) :: ww
  927. integer :: n
  928. real :: ck, sum, arg
  929. ! local data
  930. real, dimension(0:3) :: d
  931. real :: pi
  932. integer :: ip
  933. d(0) = 0.35577019
  934. d(1) = 0.2436983
  935. d(2) = 0.07211497
  936. d(3) = 0.00630165
  937. PI=4*ATAN(1.)
  938. CK = 1.0
  939. DO N=0,NSTEPS
  940. IF (N.EQ.NSTEPS) CK = 0.5
  941. ARG = PI*FLOAT(N)/FLOAT(NSTEPS)
  942. !min--- modification in next statement
  943. ARG = ARG/2.
  944. !min--- end of modification
  945. SUM = D(0)
  946. DO IP=1,3
  947. SUM = SUM + 2.*D(IP)*COS(ARG*FLOAT(IP))
  948. END DO
  949. WW(N) = CK*SUM
  950. END DO
  951. RETURN
  952. END SUBROUTINE potter2
  953. SUBROUTINE dolphwin(m, window)
  954. ! calculation of dolph-chebyshev window or, for short,
  955. ! dolph window, using the expression in the reference:
  956. !
  957. ! antoniou, andreas, 1993: digital filters: analysis,
  958. ! design and applications. mcgraw-hill, inc., 689pp.
  959. !
  960. ! the dolph window is optimal in the following sense:
  961. ! for a given main-lobe width, the stop-band attenuation
  962. ! is minimal; for a given stop-band level, the main-lobe
  963. ! width is minimal.
  964. !
  965. ! it is possible to specify either the ripple-ratio r
  966. ! or the stop-band edge thetas.
  967. IMPLICIT NONE
  968. ! Arguments
  969. INTEGER, INTENT(IN) :: m
  970. REAL, DIMENSION(0:M), INTENT(OUT) :: window
  971. ! local data
  972. REAL, DIMENSION(0:2*M) :: t
  973. REAL, DIMENSION(0:M) :: w, time
  974. REAL :: pi, thetas, x0, term1, term2, rr, r, db, sum, arg
  975. INTEGER :: n, nm1, nt, i
  976. PI = 4*ATAN(1.D0)
  977. THETAS = 2*PI/M
  978. N = 2*M+1
  979. NM1 = N-1
  980. X0 = 1/COS(THETAS/2)
  981. TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
  982. TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
  983. RR = 0.5*(TERM1+TERM2)
  984. R = 1/RR
  985. DB = 20*LOG10(R)
  986. WRITE(*,'(1X,''DOLPH: M,N='',2I8)')M,N
  987. WRITE(*,'(1X,''DOLPH: THETAS (STOP-BAND EDGE)='',F10.3)')THETAS
  988. WRITE(*,'(1X,''DOLPH: R,DB='',2F10.3)')R, DB
  989. DO NT=0,M
  990. SUM = RR
  991. DO I=1,M
  992. ARG = X0*COS(I*PI/N)
  993. CALL CHEBY(T,NM1,ARG)
  994. TERM1 = T(NM1)
  995. TERM2 = COS(2*NT*PI*I/N)
  996. SUM = SUM + 2*TERM1*TERM2
  997. ENDDO
  998. W(NT) = SUM/N
  999. TIME(NT) = NT
  1000. ENDDO
  1001. ! fill up the array for return
  1002. DO NT=0,M
  1003. WINDOW(NT) = W(NT)
  1004. ENDDO
  1005. RETURN
  1006. END SUBROUTINE dolphwin
  1007. SUBROUTINE dolph(deltat, taus, m, window)
  1008. ! calculation of dolph-chebyshev window or, for short,
  1009. ! dolph window, using the expression in the reference:
  1010. !
  1011. ! antoniou, andreas, 1993: digital filters: analysis,
  1012. ! design and applications. mcgraw-hill, inc., 689pp.
  1013. !
  1014. ! the dolph window is optimal in the following sense:
  1015. ! for a given main-lobe width, the stop-band attenuation
  1016. ! is minimal; for a given stop-band level, the main-lobe
  1017. ! width is minimal.
  1018. IMPLICIT NONE
  1019. ! Arguments
  1020. INTEGER, INTENT(IN) :: m
  1021. REAL, DIMENSION(0:M), INTENT(OUT) :: window
  1022. REAL, INTENT(IN) :: deltat, taus
  1023. ! local data
  1024. integer, PARAMETER :: NMAX = 5000
  1025. REAL, dimension(0:NMAX) :: t, w, time
  1026. real, dimension(0:2*nmax) :: w2
  1027. INTEGER :: NPRPE=0 ! no of pe
  1028. CHARACTER*80 :: MES
  1029. real :: pi, thetas, x0, term1, term2, rr, r,db, sum, arg, sumw
  1030. integer :: n, nm1, i, nt
  1031. PI = 4*ATAN(1.D0)
  1032. WRITE (mes,'(A,F8.2,A,F10.2)') 'In dolph, deltat = ',deltat,' taus = ',taus
  1033. CALL wrf_message(TRIM(mes))
  1034. N = 2*M+1
  1035. NM1 = N-1
  1036. THETAS = 2*PI*ABS(DELTAT/TAUS)
  1037. X0 = 1/COS(THETAS/2)
  1038. TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
  1039. TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
  1040. RR = 0.5*(TERM1+TERM2)
  1041. R = 1/RR
  1042. DB = 20*LOG10(R)
  1043. WRITE (mes,'(A,2I8)') 'In dolph: M,N = ', M,N
  1044. CALL wrf_message(TRIM(mes))
  1045. WRITE (mes,'(A,F10.3)') 'In dolph: THETAS (STOP-BAND EDGE) = ', thetas
  1046. CALL wrf_message(TRIM(mes))
  1047. WRITE (mes,'(A,2F10.3)') 'In dolph: R,DB = ', R,DB
  1048. CALL wrf_message(TRIM(mes))
  1049. DO NT=0,M
  1050. SUM = 1
  1051. DO I=1,M
  1052. ARG = X0*COS(I*PI/N)
  1053. CALL CHEBY(T,NM1,ARG)
  1054. TERM1 = T(NM1)
  1055. TERM2 = COS(2*NT*PI*I/N)
  1056. SUM = SUM + R*2*TERM1*TERM2
  1057. ENDDO
  1058. W(NT) = SUM/N
  1059. TIME(NT) = NT
  1060. WRITE (mes,'(A,F10.6,2x,E17.7)') 'In dolph: TIME, W = ', TIME(NT), W(NT)
  1061. CALL wrf_message(TRIM(mes))
  1062. ENDDO
  1063. ! fill in the negative-time values by symmetry.
  1064. DO NT=0,M
  1065. W2(M+NT) = W(NT)
  1066. W2(M-NT) = W(NT)
  1067. ENDDO
  1068. ! fill up the array for return
  1069. SUMW = 0.
  1070. DO NT=0,2*M
  1071. SUMW = SUMW + W2(NT)
  1072. ENDDO
  1073. WRITE (mes,'(A,F10.4)') 'In dolph: SUM OF WEIGHTS W2 = ', sumw
  1074. CALL wrf_message(TRIM(mes))
  1075. DO NT=0,M
  1076. WINDOW(NT) = W2(NT)
  1077. ENDDO
  1078. RETURN
  1079. END SUBROUTINE dolph
  1080. SUBROUTINE cheby(t, n, x)
  1081. ! calculate all chebyshev polynomials up to order n
  1082. ! for the argument value x.
  1083. ! reference: numerical recipes, page 184, recurrence
  1084. ! t_n(x) = 2xt_{n-1}(x) - t_{n-2}(x) , n>=2.
  1085. IMPLICIT NONE
  1086. ! Arguments
  1087. INTEGER, INTENT(IN) :: n
  1088. REAL, INTENT(IN) :: x
  1089. REAL, DIMENSION(0:N) :: t
  1090. integer :: nn
  1091. T(0) = 1
  1092. T(1) = X
  1093. IF(N.LT.2) RETURN
  1094. DO NN=2,N
  1095. T(NN) = 2*X*T(NN-1) - T(NN-2)
  1096. ENDDO
  1097. RETURN
  1098. END SUBROUTINE cheby
  1099. SUBROUTINE rhofil(dt, tauc, norder, nstep, ictype, frow, nosize)
  1100. ! RHO = recurssive high order.
  1101. !
  1102. ! This routine calculates and returns the
  1103. ! Last Row, FROW, of the FILTER matrix.
  1104. !
  1105. ! Input Parameters:
  1106. ! DT : Time Step in seconds
  1107. ! TAUC : Cut-off period (hours)
  1108. ! NORDER : Order of QS Filter
  1109. ! NSTEP : Number of step/Size of row.
  1110. ! ICTYPE : Initial Conditions
  1111. ! NOSIZE : Max. side of FROW.
  1112. !
  1113. ! Working Fields:
  1114. ! ACOEF : X-coefficients of filter
  1115. ! BCOEF : Y-coefficients of filter
  1116. ! FILTER : Filter Matrix.
  1117. !
  1118. ! Output Parameters:
  1119. ! FROW : Last Row of Filter Matrix.
  1120. !
  1121. ! Note: Two types of initial conditions are permitted.
  1122. ! ICTYPE = 1 : Order increasing each row to NORDER.
  1123. ! ICTYPE = 2 : Order fixed at NORDER throughout.
  1124. !
  1125. ! DOUBLE PRECISION USED THROUGHOUT.
  1126. IMPLICIT DOUBLE PRECISION (A-H,O-Z)
  1127. DOUBLE PRECISION MUC
  1128. ! N.B. Single Precision for List Parameters.
  1129. REAL, intent(in) :: DT,TAUC
  1130. ! Space for the last row of FILTER.
  1131. integer, intent(in) :: norder, nstep, ictype, nosize
  1132. REAL , dimension(0:nosize), intent(out):: FROW
  1133. ! Arrays for rho filter.
  1134. integer, PARAMETER :: NOMAX=100
  1135. real , dimension(0:NOMAX) :: acoef, bcoef
  1136. real , dimension(0:NOMAX,0:NOMAX) :: filter
  1137. ! Working space.
  1138. real , dimension(0:NOMAX) :: alpha, beta
  1139. real :: DTT
  1140. DTT = ABS(DT)
  1141. PI = 2*DASIN(1.D0)
  1142. IOTA = CMPLX(0.,1.)
  1143. ! Filtering Parameters (derived).
  1144. THETAC = 2*PI*DTT/(TAUC)
  1145. MUC = tan(THETAC/2)
  1146. FC = THETAC/(2*PI)
  1147. ! Clear the arrays.
  1148. DO NC=0,NOMAX
  1149. ACOEF(NC) = 0.
  1150. BCOEF(NC) = 0.
  1151. ALPHA(NC) = 0.
  1152. BETA (NC) = 0.
  1153. FROW (NC) = 0.
  1154. DO NR=0,NOMAX
  1155. FILTER(NR,NC) = 0.
  1156. ENDDO
  1157. ENDDO
  1158. ! Fill up the Filter Matrix.
  1159. FILTER(0,0) = 1.
  1160. ! Get the coefficients of the Filter.
  1161. IF ( ICTYPE.eq.2 ) THEN
  1162. CALL RHOCOF(NORDER,NOMAX,MUC, ACOEF,BCOEF)
  1163. ENDIF
  1164. DO 100 NROW=1,NSTEP
  1165. IF ( ICTYPE.eq.1 ) THEN
  1166. NORD = MIN(NROW,NORDER)
  1167. IF ( NORD.le.NORDER) THEN
  1168. CALL RHOCOF(NORD,NOMAX,MUC, ACOEF,BCOEF)
  1169. ENDIF
  1170. ENDIF
  1171. DO K=0,NROW
  1172. ALPHA(K) = ACOEF(NROW-K)
  1173. IF(K.lt.NROW) BETA(K) = BCOEF(NROW-K)
  1174. ENDDO
  1175. ! Correction for terms of negative index.
  1176. IF ( ICTYPE.eq.2 ) THEN
  1177. IF ( NROW.lt.NORDER ) THEN
  1178. CN = 0.
  1179. DO NN=NROW+1,NORDER
  1180. CN = CN + (ACOEF(NN)+BCOEF(NN))
  1181. ENDDO
  1182. ALPHA(0) = ALPHA(0) + CN
  1183. ENDIF
  1184. ENDIF
  1185. ! Check sum of ALPHAs and BETAs = 1
  1186. SUMAB = 0.
  1187. DO NN=0,NROW
  1188. SUMAB = SUMAB + ALPHA(NN)
  1189. IF(NN.lt.NROW) SUMAB = SUMAB + BETA(NN)
  1190. ENDDO
  1191. DO KK=0,NROW-1
  1192. SUMBF = 0.
  1193. DO LL=0,NROW-1
  1194. SUMBF = SUMBF + BETA(LL)*FILTER(LL,KK)
  1195. ENDDO
  1196. FILTER(NROW,KK) = ALPHA(KK)+SUMBF
  1197. ENDDO
  1198. FILTER(NROW,NROW) = ALPHA(NROW)
  1199. ! Check sum of row elements = 1
  1200. SUMROW = 0.
  1201. DO NN=0,NROW
  1202. SUMROW = SUMROW + FILTER(NROW,NN)
  1203. ENDDO
  1204. 100 CONTINUE
  1205. DO NC=0,NSTEP
  1206. FROW(NC) = FILTER(NSTEP,NC)
  1207. ENDDO
  1208. RETURN
  1209. END SUBROUTINE rhofil
  1210. SUBROUTINE rhocof(nord, nomax, muc, ca, cb)
  1211. ! Get the coefficients of the RHO Filter
  1212. ! IMPLICIT DOUBLE PRECISION (A-H,O-Z)
  1213. IMPLICIT NONE
  1214. ! Arguments
  1215. integer, intent(in) :: nord, nomax
  1216. real, dimension(0:nomax) :: ca, cb
  1217. ! Functions
  1218. double precision, external :: cnr
  1219. ! Local variables
  1220. INTEGER :: nn
  1221. COMPLEX :: IOTA
  1222. DOUBLE PRECISION :: MUC, ZN
  1223. DOUBLE PRECISION :: pi, root2, rn, sigma, gain, sumcof
  1224. PI = 2*ASIN(1.)
  1225. ROOT2 = SQRT(2.)
  1226. IOTA = (0.,1.)
  1227. RN = 1./FLOAT(NORD)
  1228. SIGMA = 1./( SQRT(2.**RN-1.) )
  1229. GAIN = (MUC*SIGMA/(1+MUC*SIGMA))**NORD
  1230. ZN = (1-MUC*SIGMA)/(1+MUC*SIGMA)
  1231. DO NN=0,NORD
  1232. CA(NN) = CNR(NORD,NN)*GAIN
  1233. IF(NN.gt.0) CB(NN) = -CNR(NORD,NN)*(-ZN)**NN
  1234. ENDDO
  1235. ! Check sum of coefficients = 1
  1236. SUMCOF = 0.
  1237. DO NN=0,NORD
  1238. SUMCOF = SUMCOF + CA(NN)
  1239. IF(NN.gt.0) SUMCOF = SUMCOF + CB(NN)
  1240. ENDDO
  1241. RETURN
  1242. END SUBROUTINE RHOCOF
  1243. DOUBLE PRECISION FUNCTION cnr(n,r)
  1244. ! Binomial Coefficient (n,r).
  1245. ! IMPLICIT DOUBLE PRECISION(C,X)
  1246. IMPLICIT NONE
  1247. ! Arguments
  1248. INTEGER , intent(in) :: n, R
  1249. ! Local variables
  1250. INTEGER :: k
  1251. DOUBLE PRECISION :: coeff, xn, xr, xk
  1252. IF ( R.eq.0 ) THEN
  1253. CNR = 1.0
  1254. RETURN
  1255. ENDIF
  1256. Coeff = 1.0
  1257. XN = DFLOAT(N)
  1258. XR = DFLOAT(R)
  1259. DO K=1,R
  1260. XK = DFLOAT(K)
  1261. COEFF = COEFF * ( (XN-XR+XK)/XK )
  1262. ENDDO
  1263. CNR = COEFF
  1264. RETURN
  1265. END FUNCTION cnr
  1266. SUBROUTINE optfil (grid,NH,DELTAT,NHMAX)
  1267. !----------------------------------------------------------------------
  1268. ! SUBROUTINE optfil (NH,DELTAT,TAUP,TAUS,LPRINT, &
  1269. ! H,NHMAX)
  1270. !
  1271. ! - Huang and Lynch optimal filter
  1272. ! Monthly Weather Review, Feb 1993
  1273. !----------------------------------------------------------
  1274. ! Input Parameters in List:
  1275. ! NH : Half-length of the Filter
  1276. ! DELTAT : Time-step (in seconds).
  1277. ! TAUP : Period of pass-band edge (hours).
  1278. ! TAUS : Period of stop-band edge (hours).
  1279. ! LPRINT : Logical switch for messages.
  1280. ! NHMAX : Maximum permitted Half-length.
  1281. !
  1282. ! Output Parameters in List:
  1283. ! H : Impulse Response.
  1284. ! DP : Deviation in pass-band (db)
  1285. ! DS : Deviation in stop-band (db)
  1286. !----------------------------------------------------------
  1287. !
  1288. USE module_domain, ONLY : domain
  1289. TYPE(domain) , POINTER :: grid
  1290. REAL,DIMENSION( 20) :: EDGE
  1291. REAL,DIMENSION( 10) :: FX, WTX, DEVIAT
  1292. REAL,DIMENSION(2*NHMAX+1) :: H
  1293. logical LPRINT
  1294. REAL, INTENT (IN) :: DELTAT
  1295. INTEGER, INTENT (IN) :: NH, NHMAX
  1296. !
  1297. TAUP = 3.
  1298. TAUS = 1.5
  1299. LPRINT = .true.
  1300. !initialize H array
  1301. NL=2*NHMAX+1
  1302. do 101 n=1,NL
  1303. H(n)=0.
  1304. 101 continue
  1305. NFILT = 2*NH+1
  1306. print *,' start optfil, NFILT=', nfilt
  1307. !
  1308. ! 930325 PL & XYH : the upper limit is changed from 64 to 128.
  1309. IF(NFILT.LE.0 .OR. NFILT.GT.128 ) THEN
  1310. WRITE(6,*) 'NH=',NH
  1311. CALL wrf_error_fatal (' Sorry, error 1 in call to OPTFIL ')
  1312. ENDIF
  1313. !
  1314. ! The following four should always be the same.
  1315. JTYPE = 1
  1316. NBANDS = 2
  1317. !CC JPRINT = 0
  1318. LGRID = 16
  1319. !
  1320. ! calculate transition frequencies.
  1321. DT = ABS(DELTAT)
  1322. FS = DT/(TAUS*3600.)
  1323. FP = DT/(TAUP*3600.)
  1324. IF(FS.GT.0.5) then
  1325. ! print *,' FS too large in OPTFIL '
  1326. CALL wrf_error_fatal (' FS too large in OPTFIL …

Large files files are truncated, but you can click here to view the full file