PageRenderTime 69ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  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 ')
  1327. ! return
  1328. end if
  1329. IF(FP.LT.0.0) then
  1330. ! print *, ' FP too small in OPTFIL '
  1331. CALL wrf_error_fatal (' FP too small in OPTFIL ')
  1332. ! return
  1333. end if
  1334. !
  1335. ! Relative Weights in pass- and stop-bands.
  1336. WTP = 1.0
  1337. WTS = 1.0
  1338. !
  1339. !CC NOTE: (FP,FC,FS) is an arithmetic progression, so
  1340. !CC (1/FS,1/FC,1/FP) is a harmonic one.
  1341. !CC TAUP = 1/( (1/TAUC)-(1/DTAU) )
  1342. !CC TAUS = 1/( (1/TAUC)+(1/DTAU) )
  1343. !CC TAUC : Cut-off Period (hours).
  1344. !CC DTAU : Transition half-width (hours).
  1345. !CC FC = 1/TAUC ; DF = 1/DTAU
  1346. !CC FP = FC - DF : FS = FC + DF
  1347. !
  1348. IF ( LPRINT ) THEN
  1349. TAUC = 2./((1/TAUS)+(1/TAUP))
  1350. DTAU = 2./((1/TAUS)-(1/TAUP))
  1351. FC = DT/(TAUC*3600.)
  1352. DF = DT/(DTAU*3600.)
  1353. WRITE(6,*) ' DT ' , dt
  1354. WRITE(6,*) ' TAUS, TAUP ' , TAUS,TAUP
  1355. WRITE(6,*) ' TAUC, DTAU ' , TAUC,DTAU
  1356. WRITE(6,*) ' FP, FS ' , FP, FS
  1357. WRITE(6,*) ' FC, DF ' , FC, DF
  1358. WRITE(6,*) ' WTS, WTP ' , WTS, WTP
  1359. ENDIF
  1360. !
  1361. ! Fill the control vectors for MCCPAR
  1362. EDGE(1) = 0.0
  1363. EDGE(2) = FP
  1364. EDGE(3) = FS
  1365. EDGE(4) = 0.5
  1366. FX(1) = 1.0
  1367. FX(2) = 0.0
  1368. WTX(1) = WTP
  1369. WTX(2) = WTS
  1370. CALL MCCPAR(NFILT,JTYPE,NBANDS,LPRINT,LGRID, &
  1371. EDGE,FX,WTX,DEVIAT, h )
  1372. !
  1373. ! Save the deviations in the pass- and stop-bands.
  1374. DP = DEVIAT(1)
  1375. DS = DEVIAT(2)
  1376. !
  1377. ! Fill out the array H (only first half filled in MCCPAR).
  1378. IF(MOD(NFILT,2).EQ.0) THEN
  1379. NHALF = ( NFILT )/2
  1380. ELSE
  1381. NHALF = (NFILT+1)/2
  1382. ENDIF
  1383. DO 100 nn=1,NHALF
  1384. H(NFILT+1-nn) = h(nn)
  1385. 100 CONTINUE
  1386. ! normalize the sums to be unity
  1387. sumh = 0
  1388. do 150 n=1,NFILT
  1389. sumh = sumh + H(n)
  1390. 150 continue
  1391. print *,'SUMH =', sumh
  1392. do 200 n=1,NFILT
  1393. H(n) = H(n)/sumh
  1394. 200 continue
  1395. do 201 n=1,NFILT
  1396. grid%hcoeff(n)=H(n)
  1397. 201 continue
  1398. ! print *,'HCOEFF(n) ', grid%hcoeff
  1399. !
  1400. END SUBROUTINE optfil
  1401. SUBROUTINE MCCPAR (NFILT,JTYPE,NBANDS,LPRINT,LGRID, &
  1402. EDGE,FX,WTX,DEVIAT,h )
  1403. ! PROGRAM FOR THE DESIGN OF LINEAR PHASE FINITE IMPULSE
  1404. ! REPONSE (FIR) FILTERS USING THE REMEZ EXCHANGE ALGORITHM
  1405. !
  1406. !************************************************************
  1407. !* Reference: McClellan, J.H., T.W. Parks and L.R.Rabiner, *
  1408. !* 1973: A computer program for designing *
  1409. !* optimum FIR linear phase digital filters. *
  1410. !* IEEE Trans. on Audio and Electroacoustics, *
  1411. !* Vol AU-21, No. 6, 506-526. *
  1412. !************************************************************
  1413. !
  1414. ! THREE TYPES OF FILTERS ARE INCLUDED -- BANDPASS FILTERS
  1415. ! DIFFERENTIATORS, AND HILBERT TRANSFORM FILTERS
  1416. !
  1417. !---------------------------------------------------------------
  1418. !
  1419. ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
  1420. DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
  1421. DIMENSION H(66)
  1422. DIMENSION DES(1045),GRID(1045),WT(1045)
  1423. DIMENSION EDGE(20),FX(10),WTX(10),DEVIAT(10)
  1424. DOUBLE PRECISION PI2,PI
  1425. DOUBLE PRECISION AD,DEV,X,Y
  1426. LOGICAL LPRINT
  1427. PI = 3.141592653589793
  1428. PI2 = 6.283185307179586
  1429. ! ......
  1430. NFMAX = 128
  1431. 100 CONTINUE
  1432. ! PROGRAM INPUT SECTION
  1433. !CC READ(5,*) NFILT,JTYPE,NBANDS,JPRINT,LGRID
  1434. IF(NFILT.GT.NFMAX.OR.NFILT.LT.3) THEN
  1435. CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
  1436. END IF
  1437. IF(NBANDS.LE.0) NBANDS = 1
  1438. ! ....
  1439. IF(LGRID.LE.0) LGRID = 16
  1440. JB = 2*NBANDS
  1441. !cc READ(5,*) (EDGE(J),J=1,JB)
  1442. !cc READ(5,*) (FX(J),J=1,NBANDS)
  1443. !cc READ(5,*) (WTX(J),J=1,NBANDS)
  1444. IF(JTYPE.EQ.0) THEN
  1445. CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
  1446. END IF
  1447. NEG = 1
  1448. IF(JTYPE.EQ.1) NEG = 0
  1449. NODD = NFILT/2
  1450. NODD = NFILT-2*NODD
  1451. NFCNS = NFILT/2
  1452. IF(NODD.EQ.1.AND.NEG.EQ.0) NFCNS = NFCNS+1
  1453. ! ...
  1454. GRID(1) = EDGE(1)
  1455. DELF = LGRID*NFCNS
  1456. DELF = 0.5/DELF
  1457. IF(NEG.EQ.0) GOTO 135
  1458. IF(EDGE(1).LT.DELF) GRID(1) = DELF
  1459. 135 CONTINUE
  1460. J = 1
  1461. L = 1
  1462. LBAND = 1
  1463. 140 FUP = EDGE(L+1)
  1464. 145 TEMP = GRID(J)
  1465. ! ....
  1466. DES(J) = EFF(TEMP,FX,WTX,LBAND,JTYPE)
  1467. WT(J) = WATE(TEMP,FX,WTX,LBAND,JTYPE)
  1468. J = J+1
  1469. GRID(J) = TEMP+DELF
  1470. IF(GRID(J).GT.FUP) GOTO 150
  1471. GOTO 145
  1472. 150 GRID(J-1) = FUP
  1473. DES(J-1) = EFF(FUP,FX,WTX,LBAND,JTYPE)
  1474. WT(J-1) = WATE(FUP,FX,WTX,LBAND,JTYPE)
  1475. LBAND = LBAND+1
  1476. L = L+2
  1477. IF(LBAND.GT.NBANDS) GOTO 160
  1478. GRID(J) = EDGE(L)
  1479. GOTO 140
  1480. 160 NGRID = J-1
  1481. IF(NEG.NE.NODD) GOTO 165
  1482. IF(GRID(NGRID).GT.(0.5-DELF)) NGRID = NGRID-1
  1483. 165 CONTINUE
  1484. ! ......
  1485. IF(NEG) 170,170,180
  1486. 170 IF(NODD.EQ.1) GOTO 200
  1487. DO 175 J=1,NGRID
  1488. CHANGE = DCOS(PI*GRID(J))
  1489. DES(J) = DES(J)/CHANGE
  1490. WT(J) = WT(J)*CHANGE
  1491. 175 CONTINUE
  1492. GOTO 200
  1493. 180 IF(NODD.EQ.1) GOTO 190
  1494. DO 185 J = 1,NGRID
  1495. CHANGE = DSIN(PI*GRID(J))
  1496. DES(J) = DES(J)/CHANGE
  1497. WT(J) = WT(J)*CHANGE
  1498. 185 CONTINUE
  1499. GOTO 200
  1500. 190 DO 195 J =1,NGRID
  1501. CHANGE = DSIN(PI2*GRID(J))
  1502. DES(J) = DES(J)/CHANGE
  1503. WT(J) = WT(J)*CHANGE
  1504. 195 CONTINUE
  1505. ! ......
  1506. 200 TEMP = FLOAT(NGRID-1)/FLOAT(NFCNS)
  1507. DO 210 J = 1,NFCNS
  1508. IEXT(J) = (J-1)*TEMP+1
  1509. 210 CONTINUE
  1510. IEXT(NFCNS+1) = NGRID
  1511. NM1 = NFCNS-1
  1512. NZ = NFCNS+1
  1513. ! CALL THE REMEZ EXCHANGE ALGORITHM TO DO THE APPROXIMATION PROBLEM
  1514. CALL REMEZ(EDGE,NBANDS,PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID)
  1515. ! CALCULATE THE IMPULSE RESPONSE
  1516. IF(NEG) 300,300,320
  1517. 300 IF(NODD.EQ.0) GOTO 310
  1518. DO 305 J=1,NM1
  1519. H(J) = 0.5*ALPHA(NZ-J)
  1520. 305 CONTINUE
  1521. H(NFCNS)=ALPHA(1)
  1522. GOTO 350
  1523. 310 H(1) = 0.25*ALPHA(NFCNS)
  1524. DO 315 J = 2,NM1
  1525. H(J) = 0.25*(ALPHA(NZ-J)+ALPHA(NFCNS+2-J))
  1526. 315 CONTINUE
  1527. H(NFCNS) = 0.5*ALPHA(1)+0.25*ALPHA(2)
  1528. GOTO 350
  1529. 320 IF(NODD.EQ.0) GOTO 330
  1530. H(1) = 0.25*ALPHA(NFCNS)
  1531. H(2) = 0.25*ALPHA(NM1)
  1532. DO 325 J = 3,NM1
  1533. H(J) = 0.25*(ALPHA(NZ-J)-ALPHA(NFCNS+3-J))
  1534. 325 CONTINUE
  1535. H(NFCNS) = 0.5*ALPHA(1)-0.25*ALPHA(3)
  1536. H(NZ) = 0.0
  1537. GOTO 350
  1538. 330 H(1) = 0.25*ALPHA(NFCNS)
  1539. DO 335 J =2,NM1
  1540. H(J) = 0.25*(ALPHA(NZ-J)-ALPHA(NFCNS+2-J))
  1541. 335 CONTINUE
  1542. H(NFCNS) = 0.5*ALPHA(1)-0.25*ALPHA(2)
  1543. ! PROGRAM OUTPUT SECTION
  1544. 350 CONTINUE
  1545. !
  1546. IF(LPRINT) THEN
  1547. print *, '****************************************************'
  1548. print *, 'FINITE IMPULSE RESPONSE (FIR)'
  1549. print *, 'LINEAR PHASE DIGITAL FILTER DESIGN'
  1550. print *, 'REMEZ EXCHANGE ALGORITHM'
  1551. IF(JTYPE.EQ.1) WRITE(6,365)
  1552. 365 FORMAT(25X,'BANDPASS FILTER'/)
  1553. IF(JTYPE.EQ.2) WRITE(6,370)
  1554. 370 FORMAT(25X,'DIFFERENTIATOR '/)
  1555. IF(JTYPE.EQ.3) WRITE(6,375)
  1556. 375 FORMAT(25X,'HILBERT TRANSFORMER '/)
  1557. WRITE(6,378) NFILT
  1558. 378 FORMAT(15X,'FILTER LENGTH =',I3/)
  1559. WRITE(6,380)
  1560. 380 FORMAT(15X,'***** IMPULSE RESPONSE *****')
  1561. DO 381 J = 1,NFCNS
  1562. K = NFILT+1-J
  1563. IF(NEG.EQ.0) WRITE(6,382) J,H(J),K
  1564. IF(NEG.EQ.1) WRITE(6,383) J,H(J),K
  1565. 381 CONTINUE
  1566. 382 FORMAT(20X,'H(',I3,') = ',E15.8,' = H(',I4,')')
  1567. 383 FORMAT(20X,'H(',I3,') = ',E15.8,' = -H(',I4,')')
  1568. IF(NEG.EQ.1.AND.NODD.EQ.1) WRITE(6,384) NZ
  1569. 384 FORMAT(20X,'H(',I3,') = 0.0')
  1570. DO 450 K=1,NBANDS,4
  1571. KUP = K+3
  1572. IF(KUP.GT.NBANDS) KUP = NBANDS
  1573. print *
  1574. WRITE(6,385) (J,J=K,KUP)
  1575. 385 FORMAT(24X,4('BAND',I3,8X))
  1576. WRITE(6,390) (EDGE(2*J-1),J=K,KUP)
  1577. 390 FORMAT(2X,'LOWER BAND EDGE',5F15.8)
  1578. WRITE(6,395) (EDGE(2*J),J=K,KUP)
  1579. 395 FORMAT(2X,'UPPER BAND EDGE',5F15.8)
  1580. IF(JTYPE.NE.2) WRITE(6,400) (FX(J),J=K,KUP)
  1581. 400 FORMAT(2X,'DESIRED VALUE',2X,5F15.8)
  1582. IF(JTYPE.EQ.2) WRITE(6,405) (FX(J),J=K,KUP)
  1583. 405 FORMAT(2X,'DESIRED SLOPE',2X,5F15.8)
  1584. WRITE(6,410) (WTX(J),J=K,KUP)
  1585. 410 FORMAT(2X,'WEIGHTING',6X,5F15.8)
  1586. DO 420 J = K,KUP
  1587. DEVIAT(J) = DEV/WTX(J)
  1588. 420 CONTINUE
  1589. WRITE(6,425) (DEVIAT(J),J=K,KUP)
  1590. 425 FORMAT(2X,'DEVIATION',6X,5F15.8)
  1591. IF(JTYPE.NE.1) GOTO 450
  1592. DO 430 J = K,KUP
  1593. DEVIAT(J) = 20.0*ALOG10(DEVIAT(J))
  1594. 430 CONTINUE
  1595. WRITE(6,435) (DEVIAT(J),J=K,KUP)
  1596. 435 FORMAT(2X,'DEVIATION IN DB',5F15.8)
  1597. 450 CONTINUE
  1598. print *, 'EXTREMAL FREQUENCIES'
  1599. WRITE(6,455) (GRID(IEXT(J)),J=1,NZ)
  1600. 455 FORMAT((2X,5F15.7))
  1601. WRITE(6,460)
  1602. 460 FORMAT(1X,70(1H*))
  1603. !
  1604. ENDIF
  1605. !
  1606. !CC IF(NFILT.NE.0) GOTO 100 ! removal of re-run loop.
  1607. !
  1608. END SUBROUTINE mccpar
  1609. FUNCTION EFF(TEMP,FX,WTX,LBAND,JTYPE)
  1610. DIMENSION FX(5),WTX(5)
  1611. IF(JTYPE.EQ.2) GOTO 1
  1612. EFF = FX(LBAND)
  1613. RETURN
  1614. 1 EFF = FX(LBAND)*TEMP
  1615. END FUNCTION eff
  1616. FUNCTION WATE(TEMP,FX,WTX,LBAND,JTYPE)
  1617. DIMENSION FX(5),WTX(5)
  1618. IF(JTYPE.EQ.2) GOTO 1
  1619. WATE = WTX(LBAND)
  1620. RETURN
  1621. 1 IF(FX(LBAND).LT.0.0001) GOTO 2
  1622. WATE = WTX(LBAND)/TEMP
  1623. RETURN
  1624. 2 WATE = WTX(LBAND)
  1625. END FUNCTION wate
  1626. ! SUBROUTINE ERROR
  1627. !! WRITE(6,*)' **** ERROR IN INPUT DATA ****'
  1628. ! CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
  1629. ! END SUBROUTINE error
  1630. SUBROUTINE REMEZ(EDGE,NBANDS,PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID)
  1631. ! THIS SUBROUTINE IMPLEMENTS THE REMEZ EXCHANGE ALGORITHM
  1632. ! FOR THE WEIGHTED CHEBCHEV APPROXIMATION OF A CONTINUOUS
  1633. ! FUNCTION WITH A SUM OF COSINES. INPUTS TO THE SUBROUTINE
  1634. ! ARE A DENSE GRID WHICH REPLACES THE FREQUENCY AXIS, THE
  1635. ! DESIRED FUNCTION ON THIS GRID, THE WEIGHT FUNCTION ON THE
  1636. ! GRID, THE NUMBER OF COSINES, AND THE INITIAL GUESS OF THE
  1637. ! EXTREMAL FREQUENCIES. THE PROGRAM MINIMIZES THE CHEBYSHEV
  1638. ! ERROR BY DETERMINING THE BEST LOCATION OF THE EXTREMAL
  1639. ! FREQUENCIES (POINTS OF MAXIMUM ERROR) AND THEN CALCULATES
  1640. ! THE COEFFICIENTS OF THE BEST APPROXIMATION.
  1641. !
  1642. ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
  1643. DIMENSION EDGE(20)
  1644. DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
  1645. DIMENSION DES(1045),GRID(1045),WT(1045)
  1646. DIMENSION A(66),P(65),Q(65)
  1647. DOUBLE PRECISION PI2,DNUM,DDEN,DTEMP,A,P,Q
  1648. DOUBLE PRECISION AD,DEV,X,Y
  1649. DOUBLE PRECISION, EXTERNAL :: D, GEE
  1650. !
  1651. ! THE PROGRAM ALLOWS A MAXIMUM NUMBER OF ITERATIONS OF 25
  1652. !
  1653. ITRMAX=25
  1654. DEVL=-1.0
  1655. NZ=NFCNS+1
  1656. NZZ=NFCNS+2
  1657. NITER=0
  1658. 100 CONTINUE
  1659. IEXT(NZZ)=NGRID+1
  1660. NITER=NITER+1
  1661. IF(NITER.GT.ITRMAX) GO TO 400
  1662. DO 110 J=1,NZ
  1663. DTEMP=GRID(IEXT(J))
  1664. DTEMP=DCOS(DTEMP*PI2)
  1665. 110 X(J)=DTEMP
  1666. JET=(NFCNS-1)/15+1
  1667. DO 120 J=1,NZ
  1668. 120 AD(J)=D(J,NZ,JET,X)
  1669. DNUM=0.0
  1670. DDEN=0.0
  1671. K=1
  1672. DO 130 J=1,NZ
  1673. L=IEXT(J)
  1674. DTEMP=AD(J)*DES(L)
  1675. DNUM=DNUM+DTEMP
  1676. DTEMP=K*AD(J)/WT(L)
  1677. DDEN=DDEN+DTEMP
  1678. 130 K=-K
  1679. DEV=DNUM/DDEN
  1680. NU=1
  1681. IF(DEV.GT.0.0) NU=-1
  1682. DEV=-NU*DEV
  1683. K=NU
  1684. DO 140 J=1,NZ
  1685. L=IEXT(J)
  1686. DTEMP=K*DEV/WT(L)
  1687. Y(J)=DES(L)+DTEMP
  1688. 140 K=-K
  1689. IF(DEV.GE.DEVL) GO TO 150
  1690. WRITE(6,*) ' ******** FAILURE TO CONVERGE *********** '
  1691. WRITE(6,*) ' PROBABLE CAUSE IS MACHINE ROUNDING ERROR '
  1692. WRITE(6,*) ' THE IMPULSE RESPONSE MAY BE CORRECT '
  1693. WRITE(6,*) ' CHECK WITH A FREQUENCY RESPONSE '
  1694. WRITE(6,*) ' **************************************** '
  1695. GO TO 400
  1696. 150 DEVL=DEV
  1697. JCHNGE=0
  1698. K1=IEXT(1)
  1699. KNZ=IEXT(NZ)
  1700. KLOW=0
  1701. NUT=-NU
  1702. J=1
  1703. !
  1704. ! SEARCH FOR THE EXTERMAL FREQUENCIES OF THE BEST
  1705. ! APPROXIMATION.
  1706. 200 IF(J.EQ.NZZ) YNZ=COMP
  1707. IF(J.GE.NZZ) GO TO 300
  1708. KUP=IEXT(J+1)
  1709. L=IEXT(J)+1
  1710. NUT=-NUT
  1711. IF(J.EQ.2) Y1=COMP
  1712. COMP=DEV
  1713. IF(L.GE.KUP) GO TO 220
  1714. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1715. ERR=(ERR-DES(L))*WT(L)
  1716. DTEMP=NUT*ERR-COMP
  1717. IF(DTEMP.LE.0.0) GO TO 220
  1718. COMP=NUT*ERR
  1719. 210 L=L+1
  1720. IF(L.GE.KUP) GO TO 215
  1721. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1722. ERR=(ERR-DES(L))*WT(L)
  1723. DTEMP=NUT*ERR-COMP
  1724. IF(DTEMP.LE.0.0) GO TO 215
  1725. COMP=NUT*ERR
  1726. GO TO 210
  1727. 215 IEXT(J)=L-1
  1728. J=J+1
  1729. KLOW=L-1
  1730. JCHNGE=JCHNGE+1
  1731. GO TO 200
  1732. 220 L=L-1
  1733. 225 L=L-1
  1734. IF(L.LE.KLOW) GO TO 250
  1735. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1736. ERR=(ERR-DES(L))*WT(L)
  1737. DTEMP=NUT*ERR-COMP
  1738. IF(DTEMP.GT.0.0) GO TO 230
  1739. IF(JCHNGE.LE.0) GO TO 225
  1740. GO TO 260
  1741. 230 COMP=NUT*ERR
  1742. 235 L=L-1
  1743. IF(L.LE.KLOW) GO TO 240
  1744. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1745. ERR=(ERR-DES(L))*WT(L)
  1746. DTEMP=NUT*ERR-COMP
  1747. IF(DTEMP.LE.0.0) GO TO 240
  1748. COMP=NUT*ERR
  1749. GO TO 235
  1750. 240 KLOW=IEXT(J)
  1751. IEXT(J)=L+1
  1752. J=J+1
  1753. JCHNGE=JCHNGE+1
  1754. GO TO 200
  1755. 250 L=IEXT(J)+1
  1756. IF(JCHNGE.GT.0) GO TO 215
  1757. 255 L=L+1
  1758. IF(L.GE.KUP) GO TO 260
  1759. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1760. ERR=(ERR-DES(L))*WT(L)
  1761. DTEMP=NUT*ERR-COMP
  1762. IF(DTEMP.LE.0.0) GO TO 255
  1763. COMP=NUT*ERR
  1764. GO TO 210
  1765. 260 KLOW=IEXT(J)
  1766. J=J+1
  1767. GO TO 200
  1768. 300 IF(J.GT.NZZ) GO TO 320
  1769. IF(K1.GT.IEXT(1)) K1=IEXT(1)
  1770. IF(KNZ.LT.IEXT(NZ)) KNZ=IEXT(NZ)
  1771. NUT1=NUT
  1772. NUT=-NU
  1773. L=0
  1774. KUP=K1
  1775. COMP=YNZ*(1.00001)
  1776. LUCK=1
  1777. 310 L=L+1
  1778. IF(L.GE.KUP) GO TO 315
  1779. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1780. ERR=(ERR-DES(L))*WT(L)
  1781. DTEMP=NUT*ERR-COMP
  1782. IF(DTEMP.LE.0.0) GO TO 310
  1783. COMP=NUT*ERR
  1784. J=NZZ
  1785. GO TO 210
  1786. 315 LUCK=6
  1787. GO TO 325
  1788. 320 IF(LUCK.GT.9) GO TO 350
  1789. IF(COMP.GT.Y1) Y1=COMP
  1790. K1=IEXT(NZZ)
  1791. 325 L=NGRID+1
  1792. KLOW=KNZ
  1793. NUT=-NUT1
  1794. COMP=Y1*(1.00001)
  1795. 330 L=L-1
  1796. IF(L.LE.KLOW) GO TO 340
  1797. ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
  1798. ERR=(ERR-DES(L))*WT(L)
  1799. DTEMP=NUT*ERR-COMP
  1800. IF(DTEMP.LE.0.0) GO TO 330
  1801. J=NZZ
  1802. COMP=NUT*ERR
  1803. LUCK=LUCK+10
  1804. GO TO 235
  1805. 340 IF(LUCK.EQ.6) GO TO 370
  1806. DO 345 J=1,NFCNS
  1807. 345 IEXT(NZZ-J)=IEXT(NZ-J)
  1808. IEXT(1)=K1
  1809. GO TO 100
  1810. 350 KN=IEXT(NZZ)
  1811. DO 360 J=1,NFCNS
  1812. 360 IEXT(J)=IEXT(J+1)
  1813. IEXT(NZ)=KN
  1814. GO TO 100
  1815. 370 IF(JCHNGE.GT.0) GO TO 100
  1816. !
  1817. ! CALCULATION OF THE COEFFICIENTS OF THE BEST APPROXIMATION
  1818. ! USING THE INVERSE DISCRETE FOURIER TRANSFORM.
  1819. !
  1820. 400 CONTINUE
  1821. NM1=NFCNS-1
  1822. FSH=1.0E-06
  1823. GTEMP=GRID(1)
  1824. X(NZZ)=-2.0
  1825. CN=2*NFCNS-1
  1826. DELF=1.0/CN
  1827. L=1
  1828. KKK=0
  1829. IF(EDGE(1).EQ.0.0.AND.EDGE(2*NBANDS).EQ.0.5) KKK=1
  1830. IF(NFCNS.LE.3) KKK=1
  1831. IF(KKK.EQ.1) GO TO 405
  1832. DTEMP=DCOS(PI2*GRID(1))
  1833. DNUM=DCOS(PI2*GRID(NGRID))
  1834. AA=2.0/(DTEMP-DNUM)
  1835. BB=-(DTEMP+DNUM)/(DTEMP-DNUM)
  1836. 405 CONTINUE
  1837. DO 430 J=1,NFCNS
  1838. FT=(J-1)*DELF
  1839. XT=DCOS(PI2*FT)
  1840. IF(KKK.EQ.1) GO TO 410
  1841. XT=(XT-BB)/AA
  1842. ! original : FT=ARCOS(XT)/PI2
  1843. FT=ACOS(XT)/PI2
  1844. 410 XE=X(L)
  1845. IF(XT.GT.XE) GO TO 420
  1846. IF((XE-XT).LT.FSH) GO TO 415
  1847. L=L+1
  1848. GO TO 410
  1849. 415 A(J)=Y(L)
  1850. GO TO 425
  1851. 420 IF((XT-XE).LT.FSH) GO TO 415
  1852. GRID(1)=FT
  1853. A(J)=GEE(1,NZ,GRID,PI2,X,Y,AD)
  1854. 425 CONTINUE
  1855. IF(L.GT.1) L=L-1
  1856. 430 CONTINUE
  1857. GRID(1)=GTEMP
  1858. DDEN=PI2/CN
  1859. DO 510 J=1,NFCNS
  1860. DTEMP=0.0
  1861. DNUM=(J-1)*DDEN
  1862. IF(NM1.LT.1) GO TO 505
  1863. DO 500 K=1,NM1
  1864. 500 DTEMP=DTEMP+A(K+1)*DCOS(DNUM*K)
  1865. 505 DTEMP=2.0*DTEMP+A(1)
  1866. 510 ALPHA(J)=DTEMP
  1867. DO 550 J=2,NFCNS
  1868. 550 ALPHA(J)=2*ALPHA(J)/CN
  1869. ALPHA(1)=ALPHA(1)/CN
  1870. IF(KKK.EQ.1) GO TO 545
  1871. P(1)=2.0*ALPHA(NFCNS)*BB+ALPHA(NM1)
  1872. P(2)=2.0*AA*ALPHA(NFCNS)
  1873. Q(1)=ALPHA(NFCNS-2)-ALPHA(NFCNS)
  1874. DO 540 J=2,NM1
  1875. IF(J.LT.NM1) GO TO 515
  1876. AA=0.5*AA
  1877. BB=0.5*BB
  1878. 515 CONTINUE
  1879. P(J+1)=0.0
  1880. DO 520 K=1,J
  1881. A(K)=P(K)
  1882. 520 P(K)=2.0*BB*A(K)
  1883. P(2)=P(2)+A(1)*2.0*AA
  1884. JM1=J-1
  1885. DO 525 K=1,JM1
  1886. 525 P(K)=P(K)+Q(K)+AA*A(K+1)
  1887. JP1=J+1
  1888. DO 530 K=3,JP1
  1889. 530 P(K)=P(K)+AA*A(K-1)
  1890. IF(J.EQ.NM1) GO TO 540
  1891. DO 535 K=1,J
  1892. 535 Q(K)=-A(K)
  1893. Q(1)=Q(1)+ALPHA(NFCNS-1-J)
  1894. 540 CONTINUE
  1895. DO 543 J=1,NFCNS
  1896. 543 ALPHA(J)=P(J)
  1897. 545 CONTINUE
  1898. IF(NFCNS.GT.3) RETURN
  1899. ALPHA(NFCNS+1)=0.0
  1900. ALPHA(NFCNS+2)=0.0
  1901. END SUBROUTINE remez
  1902. DOUBLE PRECISION FUNCTION D(K,N,M,X)
  1903. ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
  1904. DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
  1905. DIMENSION DES(1045),GRID(1045),WT(1045)
  1906. DOUBLE PRECISION AD,DEV,X,Y
  1907. DOUBLE PRECISION Q
  1908. DOUBLE PRECISION PI2
  1909. D = 1.0
  1910. Q = X(K)
  1911. DO 3 L = 1,M
  1912. DO 2 J = L,N,M
  1913. IF(J-K) 1,2,1
  1914. 1 D = 2.0*D*(Q-X(J))
  1915. 2 CONTINUE
  1916. 3 CONTINUE
  1917. D = 1.0/D
  1918. END FUNCTION D
  1919. DOUBLE PRECISION FUNCTION GEE(K,N,GRID,PI2,X,Y,AD)
  1920. ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
  1921. DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
  1922. DIMENSION DES(1045),GRID(1045),WT(1045)
  1923. DOUBLE PRECISION AD,DEV,X,Y
  1924. DOUBLE PRECISION P,C,D,XF
  1925. DOUBLE PRECISION PI2
  1926. P = 0.0
  1927. XF = GRID(K)
  1928. XF = DCOS(PI2*XF)
  1929. D = 0.0
  1930. DO 1 J =1,N
  1931. C = XF-X(J)
  1932. C = AD(J)/C
  1933. D = D+C
  1934. P = P+C*Y(J)
  1935. 1 CONTINUE
  1936. GEE = P/D
  1937. END FUNCTION GEE
  1938. REAL FUNCTION RSLF(P,T)
  1939. IMPLICIT NONE
  1940. REAL, INTENT(IN):: P, T
  1941. REAL:: ESL,X
  1942. REAL, PARAMETER:: C0= .611583699E03
  1943. REAL, PARAMETER:: C1= .444606896E02
  1944. REAL, PARAMETER:: C2= .143177157E01
  1945. REAL, PARAMETER:: C3= .264224321E-1
  1946. REAL, PARAMETER:: C4= .299291081E-3
  1947. REAL, PARAMETER:: C5= .203154182E-5
  1948. REAL, PARAMETER:: C6= .702620698E-8
  1949. REAL, PARAMETER:: C7= .379534310E-11
  1950. REAL, PARAMETER:: C8=-.321582393E-13
  1951. X=MAX(-80.,T-273.16)
  1952. ! ESL=612.2*EXP(17.67*X/(T-29.65))
  1953. ESL=C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X*(C6+X*(C7+X*C8)))))))
  1954. RSLF=.622*ESL/(P-ESL)
  1955. END FUNCTION RSLF
  1956. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1957. ! DFI startfwd group of functions
  1958. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  1959. SUBROUTINE wrf_dfi_startfwd_init ( )
  1960. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
  1961. USE module_utility
  1962. IMPLICIT NONE
  1963. INTERFACE
  1964. SUBROUTINE dfi_startfwd_init_recurse(grid)
  1965. USE module_domain, ONLY : domain
  1966. TYPE (domain), POINTER :: grid
  1967. END SUBROUTINE dfi_startfwd_init_recurse
  1968. END INTERFACE
  1969. ! Now, setup all nests
  1970. CALL dfi_startfwd_init_recurse(head_grid)
  1971. CALL set_current_grid_ptr( head_grid )
  1972. END SUBROUTINE wrf_dfi_startfwd_init
  1973. RECURSIVE SUBROUTINE dfi_startfwd_init_recurse(grid)
  1974. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
  1975. IMPLICIT NONE
  1976. INTERFACE
  1977. SUBROUTINE dfi_startfwd_init(grid)
  1978. USE module_domain, ONLY : domain
  1979. TYPE (domain), POINTER :: grid
  1980. END SUBROUTINE dfi_startfwd_init
  1981. END INTERFACE
  1982. INTEGER :: kid
  1983. TYPE (domain), POINTER :: grid
  1984. TYPE (domain), POINTER :: grid_ptr
  1985. grid_ptr => grid
  1986. DO WHILE ( ASSOCIATED( grid_ptr ) )
  1987. !
  1988. ! Assure that time-step is set back to positive
  1989. ! for this forward step.
  1990. !
  1991. grid_ptr%dt = abs(grid_ptr%dt)
  1992. grid_ptr%time_step = abs(grid_ptr%time_step)
  1993. CALL set_current_grid_ptr( grid_ptr )
  1994. CALL dfi_startfwd_init( grid_ptr )
  1995. DO kid = 1, max_nests
  1996. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  1997. CALL dfi_startfwd_init_recurse(grid_ptr%nests(kid)%ptr)
  1998. ENDIF
  1999. END DO
  2000. grid_ptr => grid_ptr%sibling
  2001. END DO
  2002. END SUBROUTINE dfi_startfwd_init_recurse
  2003. SUBROUTINE dfi_startfwd_init ( grid )
  2004. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
  2005. USE module_utility
  2006. USE module_state_description
  2007. IMPLICIT NONE
  2008. TYPE (domain) , POINTER :: grid
  2009. INTEGER rc
  2010. INTERFACE
  2011. SUBROUTINE Setup_Timekeeping(grid)
  2012. USE module_domain, ONLY : domain
  2013. TYPE (domain), POINTER :: grid
  2014. END SUBROUTINE Setup_Timekeeping
  2015. END INTERFACE
  2016. grid%dfi_stage = DFI_STARTFWD
  2017. #if (EM_CORE == 1)
  2018. ! No need for adaptive time-step
  2019. CALL nl_set_use_adaptive_time_step( grid%id, .false. )
  2020. #endif
  2021. CALL Setup_Timekeeping (grid)
  2022. grid%start_subtime = domain_get_start_time ( head_grid )
  2023. grid%stop_subtime = domain_get_stop_time ( head_grid )
  2024. CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
  2025. END SUBROUTINE dfi_startfwd_init
  2026. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2027. ! DFI startbck group of functions
  2028. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2029. SUBROUTINE wrf_dfi_startbck_init ( )
  2030. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
  2031. USE module_utility
  2032. IMPLICIT NONE
  2033. INTERFACE
  2034. SUBROUTINE dfi_startbck_init_recurse(grid)
  2035. USE module_domain, ONLY : domain
  2036. TYPE (domain), POINTER :: grid
  2037. END SUBROUTINE dfi_startbck_init_recurse
  2038. END INTERFACE
  2039. ! Now, setup all nests
  2040. CALL dfi_startbck_init_recurse(head_grid)
  2041. CALL set_current_grid_ptr( head_grid )
  2042. END SUBROUTINE wrf_dfi_startbck_init
  2043. RECURSIVE SUBROUTINE dfi_startbck_init_recurse(grid)
  2044. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
  2045. IMPLICIT NONE
  2046. INTERFACE
  2047. SUBROUTINE dfi_startbck_init(grid)
  2048. USE module_domain, ONLY : domain
  2049. TYPE (domain), POINTER :: grid
  2050. END SUBROUTINE dfi_startbck_init
  2051. END INTERFACE
  2052. INTEGER :: kid
  2053. TYPE (domain), POINTER :: grid
  2054. TYPE (domain), POINTER :: grid_ptr
  2055. grid_ptr => grid
  2056. DO WHILE ( ASSOCIATED( grid_ptr ) )
  2057. !
  2058. ! Assure that time-step is set back to positive
  2059. ! for this forward step.
  2060. !
  2061. grid_ptr%dt = abs(grid_ptr%dt)
  2062. grid_ptr%time_step = abs(grid_ptr%time_step)
  2063. CALL set_current_grid_ptr( grid_ptr )
  2064. CALL dfi_startbck_init( grid_ptr )
  2065. DO kid = 1, max_nests
  2066. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  2067. CALL dfi_startbck_init_recurse(grid_ptr%nests(kid)%ptr)
  2068. ENDIF
  2069. END DO
  2070. grid_ptr => grid_ptr%sibling
  2071. END DO
  2072. END SUBROUTINE dfi_startbck_init_recurse
  2073. SUBROUTINE dfi_startbck_init ( grid )
  2074. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
  2075. USE module_utility
  2076. USE module_state_description
  2077. IMPLICIT NONE
  2078. TYPE (domain) , POINTER :: grid
  2079. INTEGER rc
  2080. INTERFACE
  2081. SUBROUTINE Setup_Timekeeping(grid)
  2082. USE module_domain, ONLY : domain
  2083. TYPE (domain), POINTER :: grid
  2084. END SUBROUTINE Setup_Timekeeping
  2085. END INTERFACE
  2086. grid%dfi_stage = DFI_STARTBCK
  2087. ! set physics options to zero
  2088. CALL nl_set_mp_physics( grid%id, 0 )
  2089. CALL nl_set_ra_lw_physics( grid%id, 0 )
  2090. CALL nl_set_ra_sw_physics( grid%id, 0 )
  2091. CALL nl_set_sf_surface_physics( grid%id, 0 )
  2092. CALL nl_set_sf_sfclay_physics( grid%id, 0 )
  2093. CALL nl_set_sf_urban_physics( grid%id, 0 )
  2094. CALL nl_set_bl_pbl_physics( grid%id, 0 )
  2095. CALL nl_set_cu_physics( grid%id, 0 )
  2096. CALL nl_set_damp_opt( grid%id, 0 )
  2097. CALL nl_set_sst_update( grid%id, 0 )
  2098. CALL nl_set_gwd_opt( grid%id, 0 )
  2099. #if (EM_CORE == 1)
  2100. CALL nl_set_diff_6th_opt( grid%id, 0 )
  2101. CALL nl_set_use_adaptive_time_step( grid%id, .false. )
  2102. #endif
  2103. CALL nl_set_feedback( grid%id, 0 )
  2104. #if (EM_CORE == 1)
  2105. ! set bc
  2106. CALL nl_set_constant_bc( grid%id, head_grid%constant_bc)
  2107. #endif
  2108. #ifdef WRF_CHEM
  2109. ! set chemistry option to zero
  2110. CALL nl_set_chem_opt (grid%id, 0)
  2111. CALL nl_set_aer_ra_feedback (grid%id, 0)
  2112. CALL nl_set_io_form_auxinput5 (grid%id, 0)
  2113. CALL nl_set_io_form_auxinput7 (grid%id, 0)
  2114. CALL nl_set_io_form_auxinput8 (grid%id, 0)
  2115. #endif
  2116. #if (EM_CORE == 1)
  2117. ! set diffusion to zero for backward integration
  2118. CALL nl_set_km_opt( grid%id, grid%km_opt_dfi)
  2119. CALL nl_set_moist_adv_dfi_opt( grid%id, grid%moist_adv_dfi_opt)
  2120. IF ( grid%moist_adv_opt == 2 ) THEN
  2121. CALL nl_set_moist_adv_opt( grid%id, 0)
  2122. ENDIF
  2123. #endif
  2124. !tgs need to call start_domain here to reset bc initialization for
  2125. ! negative dt, but only for outer domain.
  2126. if (grid%id == 1) then
  2127. CALL start_domain ( grid , .TRUE. )
  2128. endif
  2129. ! Call wrf_run to advance forward 1 step
  2130. ! Negate time step
  2131. CALL nl_set_time_step ( grid%id, -grid%time_step )
  2132. CALL Setup_Timekeeping (grid)
  2133. grid%start_subtime = domain_get_start_time ( grid )
  2134. grid%stop_subtime = domain_get_stop_time ( grid )
  2135. CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
  2136. END SUBROUTINE dfi_startbck_init
  2137. SUBROUTINE wrf_dfi_bck_init ( )
  2138. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
  2139. USE module_utility
  2140. USE module_state_description
  2141. IMPLICIT NONE
  2142. INTERFACE
  2143. SUBROUTINE dfi_bck_init_recurse(grid)
  2144. USE module_domain, ONLY : domain
  2145. TYPE (domain), POINTER :: grid
  2146. END SUBROUTINE dfi_bck_init_recurse
  2147. END INTERFACE
  2148. ! We can only call dfi_bck_init for the head_grid
  2149. ! since nests have not been instantiated at this point,
  2150. ! so, dfi_bck_init will need to be called for each
  2151. ! nest from integrate.
  2152. CALL dfi_bck_init_recurse(head_grid)
  2153. END SUBROUTINE wrf_dfi_bck_init
  2154. RECURSIVE SUBROUTINE dfi_bck_init_recurse(grid)
  2155. USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
  2156. IMPLICIT NONE
  2157. INTERFACE
  2158. SUBROUTINE dfi_bck_init(grid)
  2159. USE module_domain, ONLY : domain
  2160. TYPE (domain), POINTER :: grid
  2161. END SUBROUTINE dfi_bck_init
  2162. END INTERFACE
  2163. INTEGER :: kid
  2164. TYPE (domain), POINTER :: grid
  2165. TYPE (domain), POINTER :: grid_ptr
  2166. grid_ptr => grid
  2167. DO WHILE ( ASSOCIATED( grid_ptr ) )
  2168. !
  2169. ! Assure that time-step is set back to positive
  2170. ! for this forward step.
  2171. !
  2172. grid_ptr%dt = abs(grid_ptr%dt)
  2173. grid_ptr%time_step = abs(grid_ptr%time_step)
  2174. CALL set_current_grid_ptr( grid_ptr )
  2175. CALL dfi_bck_init( grid_ptr )
  2176. DO kid = 1, max_nests
  2177. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  2178. CALL dfi_bck_init_recurse(grid_ptr%nests(kid)%ptr)
  2179. ENDIF
  2180. END DO
  2181. grid_ptr => grid_ptr%sibling
  2182. END DO
  2183. END SUBROUTINE dfi_bck_init_recurse
  2184. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2185. ! DFI forward initialization group of functions
  2186. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2187. SUBROUTINE wrf_dfi_fwd_init ( )
  2188. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
  2189. USE module_utility
  2190. IMPLICIT NONE
  2191. INTERFACE
  2192. SUBROUTINE dfi_fwd_init_recurse(grid)
  2193. USE module_domain, ONLY : domain
  2194. TYPE (domain), POINTER :: grid
  2195. END SUBROUTINE dfi_fwd_init_recurse
  2196. END INTERFACE
  2197. ! Now, setup all nests
  2198. CALL dfi_fwd_init_recurse(head_grid)
  2199. CALL set_current_grid_ptr( head_grid )
  2200. END SUBROUTINE wrf_dfi_fwd_init
  2201. RECURSIVE SUBROUTINE dfi_fwd_init_recurse(grid)
  2202. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
  2203. IMPLICIT NONE
  2204. INTERFACE
  2205. SUBROUTINE dfi_fwd_init(grid)
  2206. USE module_domain, ONLY : domain
  2207. TYPE (domain), POINTER :: grid
  2208. END SUBROUTINE dfi_fwd_init
  2209. END INTERFACE
  2210. INTEGER :: kid
  2211. TYPE (domain), POINTER :: grid
  2212. TYPE (domain), POINTER :: grid_ptr
  2213. grid_ptr => grid
  2214. DO WHILE ( ASSOCIATED( grid_ptr ) )
  2215. !
  2216. ! Assure that time-step is set back to positive
  2217. ! for this forward step.
  2218. !
  2219. grid_ptr%dt = abs(grid_ptr%dt)
  2220. grid_ptr%time_step = abs(grid_ptr%time_step)
  2221. CALL set_current_grid_ptr( grid_ptr )
  2222. CALL dfi_fwd_init( grid_ptr )
  2223. DO kid = 1, max_nests
  2224. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  2225. CALL dfi_fwd_init_recurse(grid_ptr%nests(kid)%ptr)
  2226. ENDIF
  2227. END DO
  2228. grid_ptr => grid_ptr%sibling
  2229. END DO
  2230. END SUBROUTINE dfi_fwd_init_recurse
  2231. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2232. ! DFI forecast initialization group of functions
  2233. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2234. SUBROUTINE wrf_dfi_fst_init ( )
  2235. USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
  2236. USE module_utility
  2237. IMPLICIT NONE
  2238. INTERFACE
  2239. SUBROUTINE dfi_fst_init_recurse(grid)
  2240. USE module_domain, ONLY : domain
  2241. TYPE (domain), POINTER :: grid
  2242. END SUBROUTINE dfi_fst_init_recurse
  2243. END INTERFACE
  2244. ! Now, setup all nests
  2245. CALL dfi_fst_init_recurse(head_grid)
  2246. CALL set_current_grid_ptr( head_grid )
  2247. END SUBROUTINE wrf_dfi_fst_init
  2248. RECURSIVE SUBROUTINE dfi_fst_init_recurse ( grid )
  2249. USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
  2250. IMPLICIT NONE
  2251. INTERFACE
  2252. SUBROUTINE dfi_fst_init(grid)
  2253. USE module_domain, ONLY : domain
  2254. TYPE (domain), POINTER :: grid
  2255. END SUBROUTINE dfi_fst_init
  2256. END INTERFACE
  2257. INTEGER :: kid
  2258. TYPE (domain), POINTER :: grid
  2259. TYPE (domain), POINTER :: grid_ptr
  2260. grid_ptr => grid
  2261. DO WHILE ( ASSOCIATED( grid_ptr ) )
  2262. !
  2263. ! Assure that time-step is set back to positive
  2264. ! for this forward step.
  2265. !
  2266. grid_ptr%dt = abs(grid_ptr%dt)
  2267. grid_ptr%time_step = abs(grid_ptr%time_step)
  2268. CALL set_current_grid_ptr( grid_ptr )
  2269. CALL dfi_fst_init( grid_ptr )
  2270. DO kid = 1, max_nests
  2271. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  2272. CALL dfi_fst_init_recurse(grid_ptr%nests(kid)%ptr)
  2273. ENDIF
  2274. END DO
  2275. grid_ptr => grid_ptr%sibling
  2276. END DO
  2277. END SUBROUTINE dfi_fst_init_recurse
  2278. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2279. ! DFI write initialization group of functions
  2280. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  2281. SUBROUTINE wrf_dfi_write_initialized_state( )
  2282. USE module_domain, ONLY : domain, head_grid
  2283. INTERFACE
  2284. SUBROUTINE dfi_write_initialized_state_recurse(grid)
  2285. USE module_domain, ONLY : domain
  2286. TYPE (domain), POINTER :: grid
  2287. END SUBROUTINE dfi_write_initialized_state_recurse
  2288. END INTERFACE
  2289. ! Now, setup all nests
  2290. CALL dfi_write_initialized_state_recurse(head_grid)
  2291. END SUBROUTINE wrf_dfi_write_initialized_state
  2292. RECURSIVE SUBROUTINE dfi_write_initialized_state_recurse( grid )
  2293. USE module_domain, ONLY : domain, max_nests
  2294. IMPLICIT NONE
  2295. INTERFACE
  2296. SUBROUTINE dfi_write_initialized_state( grid )
  2297. USE module_domain, ONLY : domain
  2298. TYPE (domain), POINTER :: grid
  2299. END SUBROUTINE dfi_write_initialized_state
  2300. END INTERFACE
  2301. INTEGER :: kid
  2302. TYPE (domain), POINTER :: grid
  2303. TYPE (domain), POINTER :: grid_ptr
  2304. grid_ptr => grid
  2305. DO WHILE ( ASSOCIATED( grid_ptr ) )
  2306. !
  2307. ! Assure that time-step is set back to positive
  2308. ! for this forward step.
  2309. !
  2310. CALL dfi_write_initialized_state( grid_ptr )
  2311. DO kid = 1, max_nests
  2312. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  2313. CALL dfi_write_initialized_state_recurse(grid_ptr%nests(kid)%ptr)
  2314. ENDIF
  2315. END DO
  2316. grid_ptr => grid_ptr%sibling
  2317. END DO
  2318. END SUBROUTINE dfi_write_initialized_state_recurse
  2319. RECURSIVE SUBROUTINE dfi_array_reset_recurse(grid)
  2320. USE module_domain, ONLY : domain, max_nests, set_current_grid_ptr
  2321. IMPLICIT NONE
  2322. INTERFACE
  2323. SUBROUTINE dfi_array_reset(grid)
  2324. USE module_domain, ONLY : domain
  2325. TYPE (domain), POINTER :: grid
  2326. END SUBROUTINE dfi_array_reset
  2327. END INTERFACE
  2328. INTEGER :: kid
  2329. TYPE (domain), POINTER :: grid
  2330. TYPE (domain), POINTER :: grid_ptr
  2331. grid_ptr => grid
  2332. DO WHILE ( ASSOCIATED( grid_ptr ) )
  2333. CALL set_current_grid_ptr( grid_ptr )
  2334. CALL dfi_array_reset( grid_ptr )
  2335. DO kid = 1, max_nests
  2336. IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
  2337. CALL dfi_array_reset_recurse(grid_ptr%nests(kid)%ptr)
  2338. ENDIF
  2339. END DO
  2340. grid_ptr => grid_ptr%sibling
  2341. END DO
  2342. END SUBROUTINE dfi_array_reset_recurse