1 SUBROUTINE dfi_accumulate( grid )
3 USE module_domain, ONLY : domain
5 USE module_driver_constants
8 USE module_model_constants
9 USE module_state_description
18 TYPE(domain) , POINTER :: grid
20 IF ( grid%dfi_opt .EQ. DFI_NODFI .OR. grid%dfi_stage .EQ. DFI_FST ) RETURN
25 hn = grid%hcoeff(grid%itimestep+1)
27 ! accumulate dynamic variables
28 grid%dfi_mu(:,:) = grid%dfi_mu(:,:) + grid%mu_2(:,:) * hn
29 grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u_2(:,:,:) * hn
30 grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v_2(:,:,:) * hn
31 grid%dfi_w(:,:,:) = grid%dfi_w(:,:,:) + grid%w_2(:,:,:) * hn
32 grid%dfi_ww(:,:,:) = grid%dfi_ww(:,:,:) + grid%ww(:,:,:) * hn
33 grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t_2(:,:,:) * hn
34 grid%dfi_phb(:,:,:) = grid%dfi_phb(:,:,:) + grid%phb(:,:,:) * hn
35 grid%dfi_ph0(:,:,:) = grid%dfi_ph0(:,:,:) + grid%ph0(:,:,:) * hn
36 grid%dfi_php(:,:,:) = grid%dfi_php(:,:,:) + grid%php(:,:,:) * hn
37 grid%dfi_p(:,:,:) = grid%dfi_p(:,:,:) + grid%p(:,:,:) * hn
38 grid%dfi_ph(:,:,:) = grid%dfi_ph(:,:,:) + grid%ph_2(:,:,:) * hn
39 grid%dfi_tke(:,:,:) = grid%dfi_tke(:,:,:) + grid%tke_2(:,:,:) * hn
40 grid%dfi_al(:,:,:) = grid%dfi_al(:,:,:) + grid%al(:,:,:) * hn
41 grid%dfi_alt(:,:,:) = grid%dfi_alt(:,:,:) + grid%alt(:,:,:) * hn
42 grid%dfi_pb(:,:,:) = grid%dfi_pb(:,:,:) + grid%pb(:,:,:) * hn
43 ! neg. check on hydrometeor and scalar variables
44 grid%moist(:,:,:,:) = max(0.,grid%moist(:,:,:,:))
45 grid%dfi_scalar(:,:,:,:) = max(0.,grid%dfi_scalar(:,:,:,:))
46 #if ( WRF_DFI_RADAR == 1 )
47 IF ( grid%dfi_radar .EQ. 0 ) then
48 grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
50 grid%dfi_moist(:,:,:,P_QV) = grid%dfi_moist(:,:,:,P_QV) + grid%moist(:,:,:,P_QV) * hn
53 grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
55 grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
57 ! accumulate DFI coefficient
58 grid%hcoeff_tot = grid%hcoeff_tot + hn
62 hn = grid%hcoeff(grid%ntsd+1)
63 grid%dfi_pd(:,:) = grid%dfi_pd(:,:) + grid%pd(:,:) * hn
64 grid%dfi_pint(:,:,:) = grid%dfi_pint(:,:,:) + grid%pint(:,:,:) * hn
65 grid%dfi_dwdt(:,:,:) = grid%dfi_dwdt(:,:,:) + grid%dwdt(:,:,:) * hn
66 grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t(:,:,:) * hn
67 grid%dfi_q(:,:,:) = grid%dfi_q(:,:,:) + grid%q(:,:,:) * hn
68 grid%dfi_q2(:,:,:) = grid%dfi_q2(:,:,:) + grid%q2(:,:,:) * hn
69 grid%dfi_cwm(:,:,:) = grid%dfi_cwm(:,:,:) + grid%cwm(:,:,:) * hn
70 grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u(:,:,:) * hn
71 grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v(:,:,:) * hn
72 grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
73 grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
74 ! accumulate DFI coefficient
75 grid%hcoeff_tot = grid%hcoeff_tot + hn
76 write(mess,*) 'grid%hcoeff_tot: ', grid%hcoeff_tot
77 call wrf_message(mess)
80 END SUBROUTINE dfi_accumulate
82 SUBROUTINE dfi_bck_init ( grid )
84 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
86 USE module_state_description
90 TYPE (domain) , POINTER :: grid
95 SUBROUTINE Setup_Timekeeping(grid)
96 USE module_domain, ONLY : domain
97 TYPE (domain), POINTER :: grid
98 END SUBROUTINE Setup_Timekeeping
100 SUBROUTINE dfi_save_arrays(grid)
101 USE module_domain, ONLY : domain
102 TYPE (domain), POINTER :: grid
103 END SUBROUTINE dfi_save_arrays
105 SUBROUTINE dfi_clear_accumulation(grid)
106 USE module_domain, ONLY : domain
107 TYPE (domain), POINTER :: grid
108 END SUBROUTINE dfi_clear_accumulation
110 SUBROUTINE optfil_driver(grid)
111 USE module_domain, ONLY : domain
112 TYPE (domain), POINTER :: grid
113 END SUBROUTINE optfil_driver
115 SUBROUTINE start_domain(grid, allowed_to_read)
116 USE module_domain, ONLY : domain
117 TYPE (domain) :: grid
118 LOGICAL, INTENT(IN) :: allowed_to_read
119 END SUBROUTINE start_domain
122 grid%dfi_stage = DFI_BCK
125 IF ( grid%time_step_dfi .gt. 0 ) THEN
126 CALL nl_set_time_step ( 1, -grid%time_step_dfi )
128 CALL nl_set_time_step ( 1, -grid%time_step )
129 CALL nl_set_time_step_fract_num ( 1, -grid%time_step_fract_num )
132 CALL Setup_Timekeeping (grid)
134 !tgs 7apr11 - need to call start_domain here to reset bc initialization for negative dt
135 CALL start_domain ( grid , .TRUE. )
136 !tgs 7apr11 - save arrays should be done after start_domain to get correct grid%p field
137 CALL dfi_save_arrays ( grid )
139 ! set physics options to zero
140 CALL nl_set_mp_physics( grid%id, 0 )
141 CALL nl_set_ra_lw_physics( grid%id, 0 )
142 CALL nl_set_ra_sw_physics( grid%id, 0 )
143 CALL nl_set_sf_surface_physics( grid%id, 0 )
144 CALL nl_set_sf_sfclay_physics( grid%id, 0 )
145 CALL nl_set_sf_urban_physics( grid%id, 0 )
146 CALL nl_set_bl_pbl_physics( grid%id, 0 )
147 CALL nl_set_cu_physics( grid%id, 0 )
148 CALL nl_set_damp_opt( grid%id, 0 )
149 CALL nl_set_sst_update( grid%id, 0 )
150 CALL nl_set_fractional_seaice( grid%id, 0 )
151 CALL nl_set_gwd_opt( grid%id, 0 )
152 CALL nl_set_feedback( grid%id, 0 )
155 CALL nl_set_diff_6th_opt( grid%id, 0 )
156 CALL nl_set_constant_bc(1, grid%constant_bc)
157 CALL nl_set_use_adaptive_time_step( grid%id, .false. )
161 ! set chemistry option to zero
162 CALL nl_set_chem_opt (grid%id, 0)
163 CALL nl_set_aer_ra_feedback (grid%id, 0)
164 CALL nl_set_io_form_auxinput5 (grid%id, 0)
165 CALL nl_set_io_form_auxinput7 (grid%id, 0)
166 CALL nl_set_io_form_auxinput8 (grid%id, 0)
169 ! set diffusion to zero for backward integration
172 CALL nl_set_km_opt( grid%id, grid%km_opt_dfi)
173 CALL nl_set_moist_adv_dfi_opt( grid%id, grid%moist_adv_dfi_opt)
174 IF ( grid%moist_adv_opt == 2 ) THEN
175 CALL nl_set_moist_adv_opt( grid%id, 0)
182 ! CHANGE (SIGN ONLY OF) IMPORTANT TIME CONSTANTS
184 CALL nl_get_time_step( grid%id, grid%time_step )
185 if (grid%time_step .lt. 0) then
188 write(mess,*) 'changing signs for backward integration'
189 call wrf_message(mess)
190 grid%CPGFV = -grid%CPGFV
195 grid%EF4T = -grid%EF4T
197 grid%EM(:) = -grid%EM(:)
198 grid%EMT(:) = -grid%EMT(:)
199 grid%F4Q2(:) = -grid%F4Q2(:)
201 grid%WPDAR(:,:)= -grid%WPDAR(:,:)
202 grid%CPGFU(:,:)= -grid%CPGFU(:,:)
203 grid%CURV(:,:)= -grid%CURV(:,:)
204 grid%FCP(:,:)= -grid%FCP(:,:)
205 grid%FAD(:,:)= -grid%FAD(:,:)
206 grid%F(:,:)= -grid%F(:,:)
210 grid%start_subtime = domain_get_start_time ( grid )
211 grid%stop_subtime = domain_get_stop_time ( grid )
213 CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
215 !tgs 7apr11 - this call has been moved up
216 ! CALL dfi_save_arrays ( grid )
217 CALL dfi_clear_accumulation( grid )
218 CALL optfil_driver(grid)
220 !tgs need to call start_domain here to reset bc initialization for negative dt
221 CALL start_domain ( grid , .TRUE. )
223 END SUBROUTINE dfi_bck_init
226 SUBROUTINE dfi_fwd_init ( grid )
228 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
229 USE module_utility, ONLY : WRFU_ClockSet
230 USE module_state_description
234 TYPE (domain) , POINTER :: grid
239 SUBROUTINE Setup_Timekeeping(grid)
240 USE module_domain, ONLY : domain
241 TYPE (domain), POINTER :: grid
242 END SUBROUTINE Setup_Timekeeping
244 SUBROUTINE dfi_save_arrays(grid)
245 USE module_domain, ONLY : domain
246 TYPE (domain), POINTER :: grid
247 END SUBROUTINE dfi_save_arrays
249 SUBROUTINE dfi_clear_accumulation(grid)
250 USE module_domain, ONLY : domain
251 TYPE (domain), POINTER :: grid
252 END SUBROUTINE dfi_clear_accumulation
254 SUBROUTINE optfil_driver(grid)
255 USE module_domain, ONLY : domain
256 TYPE (domain), POINTER :: grid
257 END SUBROUTINE optfil_driver
259 SUBROUTINE start_domain(grid, allowed_to_read)
260 USE module_domain, ONLY : domain
261 TYPE (domain) :: grid
262 LOGICAL, INTENT(IN) :: allowed_to_read
263 END SUBROUTINE start_domain
266 grid%dfi_stage = DFI_FWD
268 ! for Setup_Timekeeping to use when setting the clock
270 IF ( grid%time_step_dfi .gt. 0 ) THEN
271 CALL nl_set_time_step ( grid%id, grid%time_step_dfi )
274 CALL nl_get_time_step( grid%id, grid%time_step )
275 CALL nl_get_time_step_fract_num( grid%id, grid%time_step_fract_num )
277 grid%time_step = abs(grid%time_step)
278 CALL nl_set_time_step( grid%id, grid%time_step )
280 grid%time_step_fract_num = abs(grid%time_step_fract_num)
281 CALL nl_set_time_step_fract_num( grid%id, grid%time_step_fract_num )
288 ! reset physics options to normal
289 CALL nl_set_mp_physics( grid%id, grid%mp_physics)
290 CALL nl_set_ra_lw_physics( grid%id, grid%ra_lw_physics)
291 CALL nl_set_ra_sw_physics( grid%id, grid%ra_sw_physics)
292 CALL nl_set_sf_surface_physics( grid%id, grid%sf_surface_physics)
293 CALL nl_set_sf_sfclay_physics( grid%id, grid%sf_sfclay_physics)
294 CALL nl_set_sf_urban_physics( grid%id, grid%sf_urban_physics)
295 CALL nl_set_bl_pbl_physics( grid%id, grid%bl_pbl_physics)
296 CALL nl_set_cu_physics( grid%id, grid%cu_physics)
297 CALL nl_set_damp_opt( grid%id, grid%damp_opt)
298 CALL nl_set_sst_update( grid%id, 0)
299 CALL nl_set_fractional_seaice( grid%id, grid%fractional_seaice)
300 CALL nl_set_gwd_opt( grid%id, grid%gwd_opt)
301 CALL nl_set_feedback( grid%id, 0 )
303 CALL nl_set_diff_6th_opt( grid%id, grid%diff_6th_opt)
304 CALL nl_set_use_adaptive_time_step( grid%id, .false. )
306 CALL nl_set_constant_bc(grid%id, grid%constant_bc)
311 ! CHANGE (SIGN ONLY OF) IMPORTANT TIME CONSTANTS
313 !mptest CALL nl_get_time_step( grid%id, grid%time_step )
316 !!! here need to key off something else being the "wrong" sign
317 if (grid%cpgfv .gt. 0) then
319 write(mess,*) 'changing signs for forward integration'
320 call wrf_message(mess)
321 grid%CPGFV = -grid%CPGFV
326 grid%EF4T = -grid%EF4T
328 grid%EM(:) = -grid%EM(:)
329 grid%EMT(:) = -grid%EMT(:)
330 grid%F4Q2(:) = -grid%F4Q2(:)
332 grid%WPDAR(:,:)= -grid%WPDAR(:,:)
333 grid%CPGFU(:,:)= -grid%CPGFU(:,:)
334 grid%CURV(:,:)= -grid%CURV(:,:)
335 grid%FCP(:,:)= -grid%FCP(:,:)
336 grid%FAD(:,:)= -grid%FAD(:,:)
337 grid%F(:,:)= -grid%F(:,:)
343 ! ! reset chem option to normal
344 ! CALL nl_set_chem_opt( grid%id, grid%chem_opt)
345 ! CALL nl_set_aer_ra_feedback (grid%id, grid%aer_ra_feedback)
349 ! reset km_opt to norlmal
350 CALL nl_set_km_opt( grid%id, grid%km_opt)
351 CALL nl_set_moist_adv_opt( grid%id, grid%moist_adv_opt)
355 CALL Setup_Timekeeping (grid)
356 grid%start_subtime = domain_get_start_time ( head_grid )
357 grid%stop_subtime = domain_get_stop_time ( head_grid )
359 CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
361 IF ( grid%dfi_opt .EQ. DFI_DFL ) THEN
362 CALL dfi_save_arrays ( grid )
364 CALL dfi_clear_accumulation( grid )
365 CALL optfil_driver(grid)
367 !tgs need to call it here to reset bc initialization for positive time_step
368 CALL start_domain ( grid , .TRUE. )
370 END SUBROUTINE dfi_fwd_init
372 SUBROUTINE dfi_fst_init ( grid )
374 USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time
375 USE module_state_description
379 TYPE (domain) , POINTER :: grid
380 CHARACTER (LEN=80) :: wrf_error_message
383 SUBROUTINE Setup_Timekeeping(grid)
384 USE module_domain, ONLY : domain
385 TYPE (domain), POINTER :: grid
386 END SUBROUTINE Setup_Timekeeping
388 SUBROUTINE dfi_save_arrays(grid)
389 USE module_domain, ONLY : domain
390 TYPE (domain), POINTER :: grid
391 END SUBROUTINE dfi_save_arrays
393 SUBROUTINE dfi_clear_accumulation(grid)
394 USE module_domain, ONLY : domain
395 TYPE (domain), POINTER :: grid
396 END SUBROUTINE dfi_clear_accumulation
398 SUBROUTINE optfil_driver(grid)
399 USE module_domain, ONLY : domain
400 TYPE (domain), POINTER :: grid
401 END SUBROUTINE optfil_driver
403 SUBROUTINE start_domain(grid, allowed_to_read)
404 USE module_domain, ONLY : domain
405 TYPE (domain) :: grid
406 LOGICAL, INTENT(IN) :: allowed_to_read
407 END SUBROUTINE start_domain
410 grid%dfi_stage = DFI_FST
412 ! reset time_step to normal and adaptive_time_step
413 CALL nl_set_time_step( grid%id, grid%time_step )
416 grid%xtime=0. ! BUG: This will probably not work for all DFI options
417 ! only use adaptive time stepping for forecast
419 if (grid%id == 1) then
420 CALL nl_set_use_adaptive_time_step( 1, grid%use_adaptive_time_step )
422 CALL nl_set_sst_update( grid%id, grid%sst_update)
424 CALL nl_set_constant_bc(grid%id, .false.)
426 CALL nl_set_feedback( grid%id, grid%feedback )
429 ! reset chem option to normal
430 CALL nl_set_chem_opt( grid%id, grid%chem_opt)
431 CALL nl_set_aer_ra_feedback (grid%id, grid%aer_ra_feedback)
432 CALL nl_set_io_form_auxinput5 (grid%id, grid%io_form_auxinput5)
433 CALL nl_set_io_form_auxinput7 (grid%id, grid%io_form_auxinput7)
434 CALL nl_set_io_form_auxinput8 (grid%id, grid%io_form_auxinput8)
438 CALL Setup_Timekeeping (grid)
439 grid%start_subtime = domain_get_start_time ( grid )
440 grid%stop_subtime = domain_get_stop_time ( grid )
442 CALL start_domain ( grid , .TRUE. )
444 END SUBROUTINE dfi_fst_init
447 SUBROUTINE dfi_write_initialized_state( grid )
450 USE module_domain, ONLY : domain, head_grid
452 USE module_configure, ONLY : grid_config_rec_type, model_config_rec
456 TYPE (domain) , POINTER :: grid
458 CHARACTER (LEN=80) :: wrf_error_message
459 CHARACTER (LEN=80) :: rstname
460 CHARACTER (LEN=132) :: message
462 TYPE (grid_config_rec_type) :: config_flags
464 CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
466 WRITE (wrf_err_message,'(A,I4)') 'Writing out initialized model state'
467 CALL wrf_message(TRIM(wrf_err_message))
469 WRITE (rstname,'(A,I2.2)')'wrfinput_initialized_d',grid%id
470 CALL open_w_dataset ( fid, TRIM(rstname), grid, config_flags, output_input, "DATASET=INPUT", ierr )
471 IF ( ierr .NE. 0 ) THEN
472 WRITE( message , '("program wrf: error opening ",A," for writing")') TRIM(rstname)
473 CALL WRF_ERROR_FATAL ( message )
475 CALL output_input ( fid, grid, config_flags, ierr )
476 CALL close_dataset ( fid, config_flags, "DATASET=INPUT" )
478 END SUBROUTINE dfi_write_initialized_state
480 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
481 ! DFI array reset group of functions
482 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
484 SUBROUTINE wrf_dfi_array_reset ( )
486 USE module_domain, ONLY : domain, head_grid, set_current_grid_ptr
491 RECURSIVE SUBROUTINE dfi_array_reset_recurse(grid)
492 USE module_domain, ONLY : domain
493 TYPE (domain), POINTER :: grid
494 END SUBROUTINE dfi_array_reset_recurse
497 ! Copy filtered arrays back into state arrays in grid structure, and
498 ! restore original land surface fields
500 CALL dfi_array_reset_recurse(head_grid)
502 CALL set_current_grid_ptr( head_grid )
504 END SUBROUTINE wrf_dfi_array_reset
506 SUBROUTINE dfi_array_reset( grid )
508 USE module_domain, ONLY : domain
509 ! USE module_configure
510 ! USE module_driver_constants
513 USE module_model_constants
514 USE module_state_description
518 INTEGER :: its, ite, jts, jte, kts, kte, &
522 TYPE(domain) , POINTER :: grid
525 ! real p1000mb,eps,svp1,svp2,svp3,svpt0
527 ! parameter (p1000mb = 1.e+05, eps=0.622,svp1=0.6112,svp3=29.65,svpt0=273.15)
528 parameter (eps=0.622)
529 REAL es,qs,pol,tx,temp,pres,rslf
532 IF ( grid%dfi_opt .EQ. DFI_NODFI ) RETURN
535 ! Set dynamic variables
536 ! divide by total DFI coefficient
539 grid%mu_2(:,:) = grid%dfi_mu(:,:) / grid%hcoeff_tot
540 grid%u_2(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
541 grid%v_2(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
542 grid%w_2(:,:,:) = grid%dfi_w(:,:,:) / grid%hcoeff_tot
543 grid%ww(:,:,:) = grid%dfi_ww(:,:,:) / grid%hcoeff_tot
544 grid%t_2(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
545 grid%phb(:,:,:) = grid%dfi_phb(:,:,:) / grid%hcoeff_tot
546 grid%ph0(:,:,:) = grid%dfi_ph0(:,:,:) / grid%hcoeff_tot
547 grid%php(:,:,:) = grid%dfi_php(:,:,:) / grid%hcoeff_tot
548 grid%p(:,:,:) = grid%dfi_p(:,:,:) / grid%hcoeff_tot
549 grid%ph_2(:,:,:) = grid%dfi_ph(:,:,:) / grid%hcoeff_tot
550 grid%tke_2(:,:,:) = grid%dfi_tke(:,:,:) / grid%hcoeff_tot
551 grid%al(:,:,:) = grid%dfi_al(:,:,:) / grid%hcoeff_tot
552 grid%alt(:,:,:) = grid%dfi_alt(:,:,:) / grid%hcoeff_tot
553 grid%pb(:,:,:) = grid%dfi_pb(:,:,:) / grid%hcoeff_tot
554 #if ( WRF_DFI_RADAR == 1 )
555 IF ( grid%dfi_radar .EQ. 0 ) then ! tgs no radar assimilation
556 grid%moist(:,:,:,:) = max(0.,grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot)
558 grid%moist(:,:,:,P_QV) = max(0.,grid%dfi_moist(:,:,:,P_QV) / grid%hcoeff_tot)
561 grid%moist(:,:,:,:) = max(0.,grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot)
563 grid%scalar(:,:,:,:) = max(0.,grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot)
565 ! restore initial fields
566 grid%SNOW (:,:) = grid%dfi_SNOW (:,:)
567 grid%SNOWH (:,:) = grid%dfi_SNOWH (:,:)
568 grid%SNOWC (:,:) = grid%dfi_SNOWC (:,:)
569 grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
570 grid%TSK (:,:) = grid%dfi_TSK (:,:)
572 grid%TSLB (:,:,:) = grid%dfi_TSLB (:,:,:)
573 grid%SMOIS (:,:,:) = grid%dfi_SMOIS (:,:,:)
574 IF ( grid%sf_surface_physics .EQ. 3 ) then
575 grid%QVG (:,:) = grid%dfi_QVG (:,:)
576 grid%TSNAV (:,:) = grid%dfi_TSNAV (:,:)
577 grid%SOILT1(:,:) = grid%dfi_SOILT1(:,:)
578 grid%SMFR3D(:,:,:) = grid%dfi_SMFR3D (:,:,:)
579 grid%KEEPFR3DFLAG(:,:,:) = grid%dfi_KEEPFR3DFLAG(:,:,:)
582 ! restore analized hydrometeor fileds
583 #if ( WRF_DFI_RADAR == 1 )
584 IF ( grid%dfi_radar .EQ. 1 ) then
585 ! grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) !tgs
586 grid%moist(:,:,:,P_QC) = grid%dfi_moist(:,:,:,P_QC) !tgs
587 grid%moist(:,:,:,P_QR) = grid%dfi_moist(:,:,:,P_QR) !tgs
588 grid%moist(:,:,:,P_QI) = grid%dfi_moist(:,:,:,P_QI) !tgs
589 grid%moist(:,:,:,P_QS) = grid%dfi_moist(:,:,:,P_QS) !tgs
590 grid%moist(:,:,:,P_QG) = grid%dfi_moist(:,:,:,P_QG) !tgs
592 if(grid%dfi_stage .EQ. DFI_FWD) then
593 !tgs change QV to restore initial RH field after the diabatic DFI
594 its = grid%sp31 ; ite = grid%ep31 ;
595 kts = grid%sp32 ; kte = grid%ep32 ;
596 jts = grid%sp33 ; jte = grid%ep33 ;
600 temp = (grid%t_2(i,k,j)+t0)*( (grid%p(i,k,j)+grid%pb(i,k,j))/p1000mb )&
602 pres = grid%p(i,k,j)+grid%pb(i,k,j)
603 !tgs rslf - function to compute qs from Thompson microphysics
604 qs = rslf(pres, temp)
606 ! if(i.eq. 178 .and. j.eq. 148 .and. k.eq.11) then
607 ! print *,'temp,pres,qs-thomp',temp,pres,qs
610 IF(grid%moist(i,k,j,P_QC) .GT. 1.e-6 .or. &
611 grid%moist(i,k,j,P_QI) .GT. 1.e-6) THEN
612 grid%moist (i,k,j,P_QV) = MAX(0.,grid%dfi_rh(i,k,j)*QS)
615 ! if(i.eq. 178 .and. j.eq. 148 .and. k.eq.11) then
616 ! print *,'temp,pres,qs,grid%moist (i,k,j,P_QV)',temp,pres,qs, &
617 ! grid%moist(i,k,j,P_QV)
629 write(mess,*) ' divide by grid%hcoeff_tot: ', grid%hcoeff_tot
630 call wrf_message(mess)
631 if (grid%hcoeff_tot .lt. 0.0001) then
632 call wrf_error_fatal("bad grid%hcoeff_tot")
634 grid%pd(:,:) = grid%dfi_pd(:,:) / grid%hcoeff_tot
635 grid%pint(:,:,:) = grid%dfi_pint(:,:,:) / grid%hcoeff_tot
636 ! grid%dwdt(:,:,:) = grid%dfi_dwdt(:,:,:) / grid%hcoeff_tot
637 grid%t(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
638 grid%q(:,:,:) = grid%dfi_q(:,:,:) / grid%hcoeff_tot
639 grid%q2(:,:,:) = grid%dfi_q2(:,:,:) / grid%hcoeff_tot
640 grid%cwm(:,:,:) = grid%dfi_cwm(:,:,:) / grid%hcoeff_tot
641 grid%u(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
642 grid%v(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
643 grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot
644 grid%scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot
646 ! restore initial fields
647 grid%SNOW(:,:) = grid%dfi_SNOW(:,:)
648 grid%SNOWH(:,:) = grid%dfi_SNOWH(:,:)
649 ! grid%SNOWC(:,:) = grid%dfi_SNOWC(:,:)
650 grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
651 grid%NMM_TSK(:,:) = grid%dfi_NMM_TSK(:,:)
653 grid%STC(:,:,:) = grid%dfi_STC(:,:,:)
654 grid%SMC(:,:,:) = grid%dfi_SMC(:,:,:)
655 grid%SH2O(:,:,:) = grid%dfi_SH2O(:,:,:)
659 END SUBROUTINE dfi_array_reset
661 SUBROUTINE optfil_driver( grid )
663 USE module_domain, ONLY : domain
665 ! USE module_wrf_error
667 ! USE module_date_time
668 ! USE module_configure
669 USE module_state_description
670 USE module_model_constants
674 TYPE (domain) , POINTER :: grid
677 integer :: nstep2, nstepmax, rundfi, i, rc,hr,min,sec
679 real :: timestep, tauc
680 TYPE(WRFU_TimeInterval) :: run_interval
683 timestep=abs(grid%dt)
684 run_interval = grid%stop_subtime - grid%start_subtime
685 CALL WRFU_TimeGet(grid%start_subtime, YY=yr, dayofYear=jday, H=hr, M=min, S=sec, rc=rc)
686 CALL WRFU_TimeGet(grid%stop_subtime, YY=yr, dayofYear=jday, H=hr, M=min, S=sec, rc=rc)
688 CALL WRFU_TimeIntervalGet( run_interval, S=rundfi, rc=rc )
691 nstep2= ceiling((1.0 + real(rundfi)/timestep) / 2.0)
693 ! nstep2 is equal to a half of timesteps per initialization period,
694 ! should not exceed nstepmax
696 tauc = real(grid%dfi_cutoff_seconds)
698 ! Get DFI coefficient
700 IF ( grid%dfi_nfilter < 0 .OR. grid%dfi_nfilter > 8 ) THEN
701 write(mess,*) 'Invalid filter specified in namelist.'
702 call wrf_message(mess)
704 call dfcoef(nstep2-1, grid%dt, tauc, grid%dfi_nfilter, grid%hcoeff)
707 IF ( MOD(int(1.0 + real(rundfi)/timestep),2) /= 0 ) THEN
709 grid%hcoeff(2*nstep2-i) = grid%hcoeff(i)
713 grid%hcoeff(2*nstep2-i+1) = grid%hcoeff(i)
717 END SUBROUTINE optfil_driver
720 SUBROUTINE dfi_clear_accumulation( grid )
722 USE module_domain, ONLY : domain
723 ! USE module_configure
724 ! USE module_driver_constants
727 ! USE module_model_constants
728 USE module_state_description
733 TYPE(domain) , POINTER :: grid
736 grid%dfi_mu(:,:) = 0.
737 grid%dfi_u(:,:,:) = 0.
738 grid%dfi_v(:,:,:) = 0.
739 grid%dfi_w(:,:,:) = 0.
740 grid%dfi_ww(:,:,:) = 0.
741 grid%dfi_t(:,:,:) = 0.
742 grid%dfi_phb(:,:,:) = 0.
743 grid%dfi_ph0(:,:,:) = 0.
744 grid%dfi_php(:,:,:) = 0.
745 grid%dfi_p(:,:,:) = 0.
746 grid%dfi_ph(:,:,:) = 0.
747 grid%dfi_tke(:,:,:) = 0.
748 grid%dfi_al(:,:,:) = 0.
749 grid%dfi_alt(:,:,:) = 0.
750 grid%dfi_pb(:,:,:) = 0.
751 #if ( WRF_DFI_RADAR == 1 )
752 IF ( grid%dfi_radar .EQ. 0 ) then
753 grid%dfi_moist(:,:,:,:) = 0.
755 grid%dfi_moist(:,:,:,P_QV) = 0.
758 grid%dfi_moist(:,:,:,:) = 0.
760 grid%dfi_scalar(:,:,:,:) = 0.
764 grid%dfi_pd(:,:) = 0.
765 grid%dfi_pint(:,:,:) = 0.
766 grid%dfi_dwdt(:,:,:) = 0.
767 grid%dfi_t(:,:,:) = 0.
768 grid%dfi_q(:,:,:) = 0.
769 grid%dfi_q2(:,:,:) = 0.
770 grid%dfi_cwm(:,:,:) = 0.
771 grid%dfi_u(:,:,:) = 0.
772 grid%dfi_v(:,:,:) = 0.
773 grid%dfi_moist(:,:,:,:) = 0.
774 grid%dfi_scalar(:,:,:,:) = 0.
777 grid%hcoeff_tot = 0.0
779 END SUBROUTINE dfi_clear_accumulation
782 SUBROUTINE dfi_save_arrays( grid )
784 USE module_domain, ONLY : domain
785 ! USE module_configure
786 ! USE module_driver_constants
789 USE module_model_constants
790 USE module_state_description
794 INTEGER :: its, ite, jts, jte, kts, kte, &
798 TYPE(domain) , POINTER :: grid
801 REAL es,qs,pol,tx,temp,pres,rslf
804 ! save surface 2-D fields
805 grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
806 grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
807 grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
808 grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
809 grid%dfi_TSK(:,:) = grid%TSK(:,:)
812 grid%dfi_TSLB(:,:,:) = grid%TSLB(:,:,:)
813 grid%dfi_SMOIS(:,:,:) = grid%SMOIS(:,:,:)
814 ! RUC LSM only, need conditional
815 IF ( grid%sf_surface_physics .EQ. 3 ) then
816 grid%dfi_QVG(:,:) = grid%QVG(:,:)
817 grid%dfi_SOILT1(:,:) = grid%SOILT1(:,:)
818 grid%dfi_TSNAV(:,:) = grid%TSNAV(:,:)
819 grid%dfi_SMFR3D(:,:,:) = grid%SMFR3D(:,:,:)
820 grid%dfi_KEEPFR3DFLAG(:,:,:) = grid%KEEPFR3DFLAG(:,:,:)
825 ! save surface 2-D fields
826 grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
827 grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
828 ! grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
829 grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
830 grid%dfi_NMM_TSK(:,:) = grid%NMM_TSK(:,:)
832 grid%dfi_STC(:,:,:) = grid%STC(:,:,:)
833 grid%dfi_SMC(:,:,:) = grid%SMC(:,:,:)
834 grid%dfi_SH2O(:,:,:) = grid%SH2O(:,:,:)
838 ! save hydrometeor fields
840 #if ( WRF_DFI_RADAR == 1 )
841 IF ( grid%dfi_radar .EQ. 1 ) then !tgs
842 ! grid%dfi_moist(:,:,:,:) = grid%moist(:,:,:,:)
843 grid%dfi_moist(:,:,:,P_QC) = grid%moist(:,:,:,P_QC)
844 grid%dfi_moist(:,:,:,P_QR) = grid%moist(:,:,:,P_QR)
845 grid%dfi_moist(:,:,:,P_QI) = grid%moist(:,:,:,P_QI)
846 grid%dfi_moist(:,:,:,P_QS) = grid%moist(:,:,:,P_QS)
847 grid%dfi_moist(:,:,:,P_QG) = grid%moist(:,:,:,P_QG)
849 if(grid%dfi_stage .EQ. DFI_BCK) then
850 ! compute initial RH field to be reintroduced after the diabatic DFI
851 its = grid%sp31 ; ite = grid%ep31 ;
852 kts = grid%sp32 ; kte = grid%ep32 ;
853 jts = grid%sp33 ; jte = grid%ep33 ;
857 temp = (grid%t_2(i,k,j)+t0)*( (grid%p(i,k,j)+grid%pb(i,k,j))/p1000mb )&
859 pres = grid%p(i,k,j)+grid%pb(i,k,j)
860 !tgs rslf - function to compute qs from Thompson microphysics
861 qs = rslf(pres, temp)
862 grid%dfi_rh (i,k,j) = MIN(1.,MAX(0.,grid%moist(i,k,j,P_QV)/qs))
864 !tgs saturation check for points with water or ice clouds
865 IF ((grid%moist (i,k,j,P_QC) .GT. 1.e-6 .or. &
866 grid%moist (i,k,j,P_QI) .GT. 1.e-6) .and. &
867 grid%dfi_rh (i,k,j) .lt. 1.) THEN
868 grid%dfi_rh (i,k,j)=1.
880 END SUBROUTINE dfi_save_arrays
883 SUBROUTINE dfcoef (NSTEPS,DT,TAUC,NFILT,H)
885 ! calculate filter weights with selected window.
887 ! peter lynch and xiang-yu huang
889 ! ref: see hamming, r.w., 1989: digital filters,
890 ! prentice-hall international. 3rd edition.
892 ! input: nsteps - number of timesteps
893 ! forward or backward.
894 ! dt - time step in seconds.
895 ! tauc - cut-off period in seconds.
896 ! nfilt - indicator for selected filter.
898 ! output: h - array(0:nsteps) with the
899 ! required filter weights
901 !------------------------------------------------------------
905 integer, intent(in) :: nsteps, nfilt
906 real , intent(in) :: dt, tauc
907 real, intent(out) :: h(1:nsteps+1)
912 real :: pi, omegac, x, window, deltat
918 ! windows are defined by a call and held in hh.
920 if ( nfilt .eq. -1) call debug (nsteps,h)
922 IF ( NFILT .EQ. 0 ) CALL UNIFORM (NSTEPS,HH)
923 IF ( NFILT .EQ. 1 ) CALL LANCZOS (NSTEPS,HH)
924 IF ( NFILT .EQ. 2 ) CALL HAMMING (NSTEPS,HH)
925 IF ( NFILT .EQ. 3 ) CALL BLACKMAN (NSTEPS,HH)
926 IF ( NFILT .EQ. 4 ) CALL KAISER (NSTEPS,HH)
927 IF ( NFILT .EQ. 5 ) CALL POTTER2 (NSTEPS,HH)
928 IF ( NFILT .EQ. 6 ) CALL DOLPHWIN (NSTEPS,HH)
930 IF ( NFILT .LE. 6 ) THEN ! sinc-windowed filters
932 ! calculate the cutoff frequency
938 X = (OMEGAC*DELTAT/PI)
940 X = SIN(N*OMEGAC*DELTAT)/(N*PI)
945 ! normalize the sums to be unity
946 CALL NORMLZ(HH,NSTEPS)
949 H(N+1) = HH(NSTEPS-N)
952 ELSE IF ( NFILT .EQ. 7 ) THEN ! dolph filter
954 CALL DOLPH(DT,TAUC,NSTEPS,H)
956 ELSE IF ( NFILT .EQ. 8 ) THEN ! 2nd order, 2nd type quick start filter (RHO)
958 CALL RHOFIL(DT,TAUC,2,NSTEPS*2,2,H,NSTEPS)
964 END SUBROUTINE dfcoef
967 SUBROUTINE NORMLZ(HH,NMAX)
969 ! normalize the sum of hh to be unity
973 integer, intent(in) :: nmax
974 real , dimension(0:nmax), intent(out) :: hh
982 SUMHH = SUMHH + 2*HH(N)
990 END subroutine normlz
993 subroutine debug(nsteps, ww)
997 integer, intent(in) :: nsteps
998 real , dimension(0:nsteps), intent(out) :: ww
1009 end subroutine debug
1012 SUBROUTINE UNIFORM(NSTEPS,WW)
1014 ! define uniform or rectangular window function.
1018 integer, intent(in) :: nsteps
1019 real , dimension(0:nsteps), intent(out) :: ww
1029 END subroutine uniform
1032 SUBROUTINE LANCZOS(NSTEPS,WW)
1034 ! define (genaralised) lanczos window function.
1038 integer, parameter :: nmax = 1000
1039 integer, intent(in) :: nsteps
1040 real , dimension(0:nmax), intent(out) :: ww
1042 real :: power, pi, w
1044 ! (for the usual lanczos window, power = 1 )
1049 IF ( N .EQ. 0 ) THEN
1052 W = SIN(N*PI/(NSTEPS+1)) / ( N*PI/(NSTEPS+1))
1059 END SUBROUTINE lanczos
1062 SUBROUTINE HAMMING(NSTEPS,WW)
1064 ! define (genaralised) hamming window function.
1068 integer, intent(in) :: nsteps
1069 real, dimension(0:nsteps) :: ww
1071 real :: alpha, pi, w
1073 ! (for the usual hamming window, alpha=0.54,
1074 ! for the hann window, alpha=0.50).
1079 IF ( N .EQ. 0 ) THEN
1082 W = ALPHA + (1-ALPHA)*COS(N*PI/(NSTEPS))
1089 END SUBROUTINE hamming
1092 SUBROUTINE BLACKMAN(NSTEPS,WW)
1094 ! define blackman window function.
1098 integer, intent(in) :: nsteps
1099 real, dimension(0:nsteps) :: ww
1106 IF ( N .EQ. 0 ) THEN
1109 W = 0.42 + 0.50*COS( N*PI/(NSTEPS)) &
1110 + 0.08*COS(2*N*PI/(NSTEPS))
1117 END SUBROUTINE blackman
1120 SUBROUTINE KAISER(NSTEPS,WW)
1122 ! define kaiser window function.
1126 real, external :: bessi0
1128 integer, intent(in) :: nsteps
1129 real, dimension(0:nsteps) :: ww
1131 real :: alpha, xi0a, xn, as
1135 XI0A = BESSI0(ALPHA)
1138 AS = ALPHA*SQRT(1.-(XN/NSTEPS)**2)
1139 WW(N) = BESSI0(AS) / XI0A
1144 END SUBROUTINE kaiser
1147 REAL FUNCTION BESSI0(X)
1149 ! from numerical recipes (press, et al.)
1154 real(8) :: P1 = 1.0d0
1155 real(8) :: P2 = 3.5156230D0
1156 real(8) :: P3 = 3.0899424D0
1157 real(8) :: P4 = 1.2067492D0
1158 real(8) :: P5 = 0.2659732D0
1159 real(8) :: P6 = 0.360768D-1
1160 real(8) :: P7 = 0.45813D-2
1162 real*8 :: Q1 = 0.39894228D0
1163 real*8 :: Q2 = 0.1328592D-1
1164 real*8 :: Q3 = 0.225319D-2
1165 real*8 :: Q4 = -0.157565D-2
1166 real*8 :: Q5 = 0.916281D-2
1167 real*8 :: Q6 = -0.2057706D-1
1168 real*8 :: Q7 = 0.2635537D-1
1169 real*8 :: Q8 = -0.1647633D-1
1170 real*8 :: Q9 = 0.392377D-2
1175 IF (ABS(X).LT.3.75) THEN
1177 BESSI0=P1+Y*(P2+Y*(P3+Y*(P4+Y*(P5+Y*(P6+Y*P7)))))
1181 BESSI0=(EXP(AX)/SQRT(AX))*(Q1+Y*(Q2+Y*(Q3+Y*(Q4 &
1182 +Y*(Q5+Y*(Q6+Y*(Q7+Y*(Q8+Y*Q9))))))))
1189 SUBROUTINE POTTER2(NSTEPS,WW)
1191 ! define potter window function.
1192 ! modified to fall off over twice the range.
1196 integer, intent(in) :: nsteps
1197 real, dimension(0:nsteps),intent(out) :: ww
1199 real :: ck, sum, arg
1202 real, dimension(0:3) :: d
1215 IF (N.EQ.NSTEPS) CK = 0.5
1216 ARG = PI*FLOAT(N)/FLOAT(NSTEPS)
1217 !min--- modification in next statement
1219 !min--- end of modification
1222 SUM = SUM + 2.*D(IP)*COS(ARG*FLOAT(IP))
1229 END SUBROUTINE potter2
1232 SUBROUTINE dolphwin(m, window)
1234 ! calculation of dolph-chebyshev window or, for short,
1235 ! dolph window, using the expression in the reference:
1237 ! antoniou, andreas, 1993: digital filters: analysis,
1238 ! design and applications. mcgraw-hill, inc., 689pp.
1240 ! the dolph window is optimal in the following sense:
1241 ! for a given main-lobe width, the stop-band attenuation
1242 ! is minimal; for a given stop-band level, the main-lobe
1245 ! it is possible to specify either the ripple-ratio r
1246 ! or the stop-band edge thetas.
1251 INTEGER, INTENT(IN) :: m
1252 REAL, DIMENSION(0:M), INTENT(OUT) :: window
1255 REAL, DIMENSION(0:2*M) :: t
1256 REAL, DIMENSION(0:M) :: w, time
1257 REAL :: pi, thetas, x0, term1, term2, rr, r, db, sum, arg
1258 INTEGER :: n, nm1, nt, i
1265 X0 = 1/COS(THETAS/2)
1267 TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
1268 TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
1269 RR = 0.5*(TERM1+TERM2)
1272 WRITE(*,'(1X,''DOLPH: M,N='',2I8)')M,N
1273 WRITE(*,'(1X,''DOLPH: THETAS (STOP-BAND EDGE)='',F10.3)')THETAS
1274 WRITE(*,'(1X,''DOLPH: R,DB='',2F10.3)')R, DB
1279 ARG = X0*COS(I*PI/N)
1280 CALL CHEBY(T,NM1,ARG)
1282 TERM2 = COS(2*NT*PI*I/N)
1283 SUM = SUM + 2*TERM1*TERM2
1289 ! fill up the array for return
1296 END SUBROUTINE dolphwin
1299 SUBROUTINE dolph(deltat, taus, m, window)
1301 ! calculation of dolph-chebyshev window or, for short,
1302 ! dolph window, using the expression in the reference:
1304 ! antoniou, andreas, 1993: digital filters: analysis,
1305 ! design and applications. mcgraw-hill, inc., 689pp.
1307 ! the dolph window is optimal in the following sense:
1308 ! for a given main-lobe width, the stop-band attenuation
1309 ! is minimal; for a given stop-band level, the main-lobe
1315 INTEGER, INTENT(IN) :: m
1316 REAL, DIMENSION(0:M), INTENT(OUT) :: window
1317 REAL, INTENT(IN) :: deltat, taus
1320 integer, PARAMETER :: NMAX = 5000
1321 REAL, dimension(0:NMAX) :: t, w, time
1322 real, dimension(0:2*nmax) :: w2
1323 INTEGER :: NPRPE=0 ! no of pe
1326 real :: pi, thetas, x0, term1, term2, rr, r,db, sum, arg, sumw
1327 integer :: n, nm1, i, nt
1331 WRITE (mes,'(A,F8.2,A,F10.2)') 'In dolph, deltat = ',deltat,' taus = ',taus
1332 CALL wrf_message(TRIM(mes))
1337 THETAS = 2*PI*ABS(DELTAT/TAUS)
1338 X0 = 1/COS(THETAS/2)
1339 TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
1340 TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
1341 RR = 0.5*(TERM1+TERM2)
1345 WRITE (mes,'(A,2I8)') 'In dolph: M,N = ', M,N
1346 CALL wrf_message(TRIM(mes))
1347 WRITE (mes,'(A,F10.3)') 'In dolph: THETAS (STOP-BAND EDGE) = ', thetas
1348 CALL wrf_message(TRIM(mes))
1349 WRITE (mes,'(A,2F10.3)') 'In dolph: R,DB = ', R,DB
1350 CALL wrf_message(TRIM(mes))
1355 ARG = X0*COS(I*PI/N)
1356 CALL CHEBY(T,NM1,ARG)
1358 TERM2 = COS(2*NT*PI*I/N)
1359 SUM = SUM + R*2*TERM1*TERM2
1363 WRITE (mes,'(A,F10.6,2x,E17.7)') 'In dolph: TIME, W = ', TIME(NT), W(NT)
1364 CALL wrf_message(TRIM(mes))
1366 ! fill in the negative-time values by symmetry.
1372 ! fill up the array for return
1375 SUMW = SUMW + W2(NT)
1377 WRITE (mes,'(A,F10.4)') 'In dolph: SUM OF WEIGHTS W2 = ', sumw
1378 CALL wrf_message(TRIM(mes))
1386 END SUBROUTINE dolph
1389 SUBROUTINE cheby(t, n, x)
1391 ! calculate all chebyshev polynomials up to order n
1392 ! for the argument value x.
1394 ! reference: numerical recipes, page 184, recurrence
1395 ! t_n(x) = 2xt_{n-1}(x) - t_{n-2}(x) , n>=2.
1400 INTEGER, INTENT(IN) :: n
1401 REAL, INTENT(IN) :: x
1402 REAL, DIMENSION(0:N) :: t
1410 T(NN) = 2*X*T(NN-1) - T(NN-2)
1415 END SUBROUTINE cheby
1418 SUBROUTINE rhofil(dt, tauc, norder, nstep, ictype, frow, nosize)
1420 ! RHO = recurssive high order.
1422 ! This routine calculates and returns the
1423 ! Last Row, FROW, of the FILTER matrix.
1426 ! DT : Time Step in seconds
1427 ! TAUC : Cut-off period (hours)
1428 ! NORDER : Order of QS Filter
1429 ! NSTEP : Number of step/Size of row.
1430 ! ICTYPE : Initial Conditions
1431 ! NOSIZE : Max. side of FROW.
1434 ! ACOEF : X-coefficients of filter
1435 ! BCOEF : Y-coefficients of filter
1436 ! FILTER : Filter Matrix.
1438 ! Output Parameters:
1439 ! FROW : Last Row of Filter Matrix.
1441 ! Note: Two types of initial conditions are permitted.
1442 ! ICTYPE = 1 : Order increasing each row to NORDER.
1443 ! ICTYPE = 2 : Order fixed at NORDER throughout.
1445 ! DOUBLE PRECISION USED THROUGHOUT.
1447 IMPLICIT DOUBLE PRECISION (A-H,O-Z)
1449 DOUBLE PRECISION MUC
1451 ! N.B. Single Precision for List Parameters.
1452 REAL, intent(in) :: DT,TAUC
1454 ! Space for the last row of FILTER.
1455 integer, intent(in) :: norder, nstep, ictype, nosize
1456 REAL , dimension(0:nosize), intent(out):: FROW
1458 ! Arrays for rho filter.
1459 integer, PARAMETER :: NOMAX=100
1460 real , dimension(0:NOMAX) :: acoef, bcoef
1461 real , dimension(0:NOMAX,0:NOMAX) :: filter
1463 real , dimension(0:NOMAX) :: alpha, beta
1471 ! Filtering Parameters (derived).
1472 THETAC = 2*PI*DTT/(TAUC)
1488 ! Fill up the Filter Matrix.
1491 ! Get the coefficients of the Filter.
1492 IF ( ICTYPE.eq.2 ) THEN
1493 CALL RHOCOF(NORDER,NOMAX,MUC, ACOEF,BCOEF)
1498 IF ( ICTYPE.eq.1 ) THEN
1499 NORD = MIN(NROW,NORDER)
1500 IF ( NORD.le.NORDER) THEN
1501 CALL RHOCOF(NORD,NOMAX,MUC, ACOEF,BCOEF)
1506 ALPHA(K) = ACOEF(NROW-K)
1507 IF(K.lt.NROW) BETA(K) = BCOEF(NROW-K)
1510 ! Correction for terms of negative index.
1511 IF ( ICTYPE.eq.2 ) THEN
1512 IF ( NROW.lt.NORDER ) THEN
1515 CN = CN + (ACOEF(NN)+BCOEF(NN))
1517 ALPHA(0) = ALPHA(0) + CN
1521 ! Check sum of ALPHAs and BETAs = 1
1524 SUMAB = SUMAB + ALPHA(NN)
1525 IF(NN.lt.NROW) SUMAB = SUMAB + BETA(NN)
1531 SUMBF = SUMBF + BETA(LL)*FILTER(LL,KK)
1533 FILTER(NROW,KK) = ALPHA(KK)+SUMBF
1535 FILTER(NROW,NROW) = ALPHA(NROW)
1537 ! Check sum of row elements = 1
1540 SUMROW = SUMROW + FILTER(NROW,NN)
1546 FROW(NC) = FILTER(NSTEP,NC)
1551 END SUBROUTINE rhofil
1554 SUBROUTINE rhocof(nord, nomax, muc, ca, cb)
1556 ! Get the coefficients of the RHO Filter
1558 ! IMPLICIT DOUBLE PRECISION (A-H,O-Z)
1562 integer, intent(in) :: nord, nomax
1563 real, dimension(0:nomax) :: ca, cb
1566 double precision, external :: cnr
1571 DOUBLE PRECISION :: MUC, ZN
1572 DOUBLE PRECISION :: pi, root2, rn, sigma, gain, sumcof
1579 SIGMA = 1./( SQRT(2.**RN-1.) )
1581 GAIN = (MUC*SIGMA/(1+MUC*SIGMA))**NORD
1582 ZN = (1-MUC*SIGMA)/(1+MUC*SIGMA)
1585 CA(NN) = CNR(NORD,NN)*GAIN
1586 IF(NN.gt.0) CB(NN) = -CNR(NORD,NN)*(-ZN)**NN
1589 ! Check sum of coefficients = 1
1592 SUMCOF = SUMCOF + CA(NN)
1593 IF(NN.gt.0) SUMCOF = SUMCOF + CB(NN)
1598 END SUBROUTINE RHOCOF
1601 DOUBLE PRECISION FUNCTION cnr(n,r)
1603 ! Binomial Coefficient (n,r).
1605 ! IMPLICIT DOUBLE PRECISION(C,X)
1609 INTEGER , intent(in) :: n, R
1613 DOUBLE PRECISION :: coeff, xn, xr, xk
1624 COEFF = COEFF * ( (XN-XR+XK)/XK )
1633 SUBROUTINE optfil (grid,NH,DELTAT,NHMAX)
1634 !----------------------------------------------------------------------
1636 ! SUBROUTINE optfil (NH,DELTAT,TAUP,TAUS,LPRINT, &
1639 ! - Huang and Lynch optimal filter
1640 ! Monthly Weather Review, Feb 1993
1641 !----------------------------------------------------------
1642 ! Input Parameters in List:
1643 ! NH : Half-length of the Filter
1644 ! DELTAT : Time-step (in seconds).
1645 ! TAUP : Period of pass-band edge (hours).
1646 ! TAUS : Period of stop-band edge (hours).
1647 ! LPRINT : Logical switch for messages.
1648 ! NHMAX : Maximum permitted Half-length.
1650 ! Output Parameters in List:
1651 ! H : Impulse Response.
1652 ! DP : Deviation in pass-band (db)
1653 ! DS : Deviation in stop-band (db)
1654 !----------------------------------------------------------
1656 USE module_domain, ONLY : domain
1658 TYPE(domain) , POINTER :: grid
1660 REAL,DIMENSION( 20) :: EDGE
1661 REAL,DIMENSION( 10) :: FX, WTX, DEVIAT
1662 REAL,DIMENSION(2*NHMAX+1) :: H
1664 REAL, INTENT (IN) :: DELTAT
1665 INTEGER, INTENT (IN) :: NH, NHMAX
1678 print *,' start optfil, NFILT=', nfilt
1681 ! 930325 PL & XYH : the upper limit is changed from 64 to 128.
1682 IF(NFILT.LE.0 .OR. NFILT.GT.128 ) THEN
1684 CALL wrf_error_fatal (' Sorry, error 1 in call to OPTFIL ')
1687 ! The following four should always be the same.
1693 ! calculate transition frequencies.
1695 FS = DT/(TAUS*3600.)
1696 FP = DT/(TAUP*3600.)
1698 ! print *,' FS too large in OPTFIL '
1699 CALL wrf_error_fatal (' FS too large in OPTFIL ')
1703 ! print *, ' FP too small in OPTFIL '
1704 CALL wrf_error_fatal (' FP too small in OPTFIL ')
1708 ! Relative Weights in pass- and stop-bands.
1712 !CC NOTE: (FP,FC,FS) is an arithmetic progression, so
1713 !CC (1/FS,1/FC,1/FP) is a harmonic one.
1714 !CC TAUP = 1/( (1/TAUC)-(1/DTAU) )
1715 !CC TAUS = 1/( (1/TAUC)+(1/DTAU) )
1716 !CC TAUC : Cut-off Period (hours).
1717 !CC DTAU : Transition half-width (hours).
1718 !CC FC = 1/TAUC ; DF = 1/DTAU
1719 !CC FP = FC - DF : FS = FC + DF
1722 TAUC = 2./((1/TAUS)+(1/TAUP))
1723 DTAU = 2./((1/TAUS)-(1/TAUP))
1724 FC = DT/(TAUC*3600.)
1725 DF = DT/(DTAU*3600.)
1726 WRITE(6,*) ' DT ' , dt
1727 WRITE(6,*) ' TAUS, TAUP ' , TAUS,TAUP
1728 WRITE(6,*) ' TAUC, DTAU ' , TAUC,DTAU
1729 WRITE(6,*) ' FP, FS ' , FP, FS
1730 WRITE(6,*) ' FC, DF ' , FC, DF
1731 WRITE(6,*) ' WTS, WTP ' , WTS, WTP
1734 ! Fill the control vectors for MCCPAR
1744 CALL MCCPAR(NFILT,JTYPE,NBANDS,LPRINT,LGRID, &
1745 EDGE,FX,WTX,DEVIAT, h )
1747 ! Save the deviations in the pass- and stop-bands.
1751 ! Fill out the array H (only first half filled in MCCPAR).
1752 IF(MOD(NFILT,2).EQ.0) THEN
1758 H(NFILT+1-nn) = h(nn)
1761 ! normalize the sums to be unity
1766 print *,'SUMH =', sumh
1774 ! print *,'HCOEFF(n) ', grid%hcoeff
1776 END SUBROUTINE optfil
1779 SUBROUTINE MCCPAR (NFILT,JTYPE,NBANDS,LPRINT,LGRID, &
1780 EDGE,FX,WTX,DEVIAT,h )
1782 ! PROGRAM FOR THE DESIGN OF LINEAR PHASE FINITE IMPULSE
1783 ! REPONSE (FIR) FILTERS USING THE REMEZ EXCHANGE ALGORITHM
1785 !************************************************************
1786 !* Reference: McClellan, J.H., T.W. Parks and L.R.Rabiner, *
1787 !* 1973: A computer program for designing *
1788 !* optimum FIR linear phase digital filters. *
1789 !* IEEE Trans. on Audio and Electroacoustics, *
1790 !* Vol AU-21, No. 6, 506-526. *
1791 !************************************************************
1793 ! THREE TYPES OF FILTERS ARE INCLUDED -- BANDPASS FILTERS
1794 ! DIFFERENTIATORS, AND HILBERT TRANSFORM FILTERS
1796 !---------------------------------------------------------------
1798 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
1799 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
1801 DIMENSION DES(1045),GRID(1045),WT(1045)
1802 DIMENSION EDGE(20),FX(10),WTX(10),DEVIAT(10)
1803 DOUBLE PRECISION PI2,PI
1804 DOUBLE PRECISION AD,DEV,X,Y
1807 PI = 3.141592653589793
1808 PI2 = 6.283185307179586
1815 ! PROGRAM INPUT SECTION
1817 !CC READ(5,*) NFILT,JTYPE,NBANDS,JPRINT,LGRID
1819 IF(NFILT.GT.NFMAX.OR.NFILT.LT.3) THEN
1820 CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
1822 IF(NBANDS.LE.0) NBANDS = 1
1826 IF(LGRID.LE.0) LGRID = 16
1828 !cc READ(5,*) (EDGE(J),J=1,JB)
1829 !cc READ(5,*) (FX(J),J=1,NBANDS)
1830 !cc READ(5,*) (WTX(J),J=1,NBANDS)
1832 CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
1835 IF(JTYPE.EQ.1) NEG = 0
1839 IF(NODD.EQ.1.AND.NEG.EQ.0) NFCNS = NFCNS+1
1846 IF(NEG.EQ.0) GOTO 135
1847 IF(EDGE(1).LT.DELF) GRID(1) = DELF
1857 DES(J) = EFF(TEMP,FX,WTX,LBAND,JTYPE)
1858 WT(J) = WATE(TEMP,FX,WTX,LBAND,JTYPE)
1861 IF(GRID(J).GT.FUP) GOTO 150
1864 DES(J-1) = EFF(FUP,FX,WTX,LBAND,JTYPE)
1865 WT(J-1) = WATE(FUP,FX,WTX,LBAND,JTYPE)
1868 IF(LBAND.GT.NBANDS) GOTO 160
1872 IF(NEG.NE.NODD) GOTO 165
1873 IF(GRID(NGRID).GT.(0.5-DELF)) NGRID = NGRID-1
1879 170 IF(NODD.EQ.1) GOTO 200
1881 CHANGE = DCOS(PI*GRID(J))
1882 DES(J) = DES(J)/CHANGE
1883 WT(J) = WT(J)*CHANGE
1886 180 IF(NODD.EQ.1) GOTO 190
1888 CHANGE = DSIN(PI*GRID(J))
1889 DES(J) = DES(J)/CHANGE
1890 WT(J) = WT(J)*CHANGE
1893 190 DO 195 J =1,NGRID
1894 CHANGE = DSIN(PI2*GRID(J))
1895 DES(J) = DES(J)/CHANGE
1896 WT(J) = WT(J)*CHANGE
1901 200 TEMP = FLOAT(NGRID-1)/FLOAT(NFCNS)
1903 IEXT(J) = (J-1)*TEMP+1
1905 IEXT(NFCNS+1) = NGRID
1909 ! CALL THE REMEZ EXCHANGE ALGORITHM TO DO THE APPROXIMATION PROBLEM
1911 CALL REMEZ(EDGE,NBANDS,PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID)
1913 ! CALCULATE THE IMPULSE RESPONSE
1916 300 IF(NODD.EQ.0) GOTO 310
1918 H(J) = 0.5*ALPHA(NZ-J)
1922 310 H(1) = 0.25*ALPHA(NFCNS)
1924 H(J) = 0.25*(ALPHA(NZ-J)+ALPHA(NFCNS+2-J))
1926 H(NFCNS) = 0.5*ALPHA(1)+0.25*ALPHA(2)
1928 320 IF(NODD.EQ.0) GOTO 330
1929 H(1) = 0.25*ALPHA(NFCNS)
1930 H(2) = 0.25*ALPHA(NM1)
1932 H(J) = 0.25*(ALPHA(NZ-J)-ALPHA(NFCNS+3-J))
1934 H(NFCNS) = 0.5*ALPHA(1)-0.25*ALPHA(3)
1937 330 H(1) = 0.25*ALPHA(NFCNS)
1939 H(J) = 0.25*(ALPHA(NZ-J)-ALPHA(NFCNS+2-J))
1941 H(NFCNS) = 0.5*ALPHA(1)-0.25*ALPHA(2)
1943 ! PROGRAM OUTPUT SECTION
1949 print *, '****************************************************'
1950 print *, 'FINITE IMPULSE RESPONSE (FIR)'
1951 print *, 'LINEAR PHASE DIGITAL FILTER DESIGN'
1952 print *, 'REMEZ EXCHANGE ALGORITHM'
1954 IF(JTYPE.EQ.1) WRITE(6,365)
1955 365 FORMAT(25X,'BANDPASS FILTER'/)
1957 IF(JTYPE.EQ.2) WRITE(6,370)
1958 370 FORMAT(25X,'DIFFERENTIATOR '/)
1960 IF(JTYPE.EQ.3) WRITE(6,375)
1961 375 FORMAT(25X,'HILBERT TRANSFORMER '/)
1964 378 FORMAT(15X,'FILTER LENGTH =',I3/)
1967 380 FORMAT(15X,'***** IMPULSE RESPONSE *****')
1971 IF(NEG.EQ.0) WRITE(6,382) J,H(J),K
1972 IF(NEG.EQ.1) WRITE(6,383) J,H(J),K
1974 382 FORMAT(20X,'H(',I3,') = ',E15.8,' = H(',I4,')')
1975 383 FORMAT(20X,'H(',I3,') = ',E15.8,' = -H(',I4,')')
1977 IF(NEG.EQ.1.AND.NODD.EQ.1) WRITE(6,384) NZ
1978 384 FORMAT(20X,'H(',I3,') = 0.0')
1982 IF(KUP.GT.NBANDS) KUP = NBANDS
1984 WRITE(6,385) (J,J=K,KUP)
1985 385 FORMAT(24X,4('BAND',I3,8X))
1986 WRITE(6,390) (EDGE(2*J-1),J=K,KUP)
1987 390 FORMAT(2X,'LOWER BAND EDGE',5F15.8)
1988 WRITE(6,395) (EDGE(2*J),J=K,KUP)
1989 395 FORMAT(2X,'UPPER BAND EDGE',5F15.8)
1990 IF(JTYPE.NE.2) WRITE(6,400) (FX(J),J=K,KUP)
1991 400 FORMAT(2X,'DESIRED VALUE',2X,5F15.8)
1992 IF(JTYPE.EQ.2) WRITE(6,405) (FX(J),J=K,KUP)
1993 405 FORMAT(2X,'DESIRED SLOPE',2X,5F15.8)
1994 WRITE(6,410) (WTX(J),J=K,KUP)
1995 410 FORMAT(2X,'WEIGHTING',6X,5F15.8)
1997 DEVIAT(J) = DEV/WTX(J)
1999 WRITE(6,425) (DEVIAT(J),J=K,KUP)
2000 425 FORMAT(2X,'DEVIATION',6X,5F15.8)
2001 IF(JTYPE.NE.1) GOTO 450
2003 DEVIAT(J) = 20.0*ALOG10(DEVIAT(J))
2005 WRITE(6,435) (DEVIAT(J),J=K,KUP)
2006 435 FORMAT(2X,'DEVIATION IN DB',5F15.8)
2008 print *, 'EXTREMAL FREQUENCIES'
2009 WRITE(6,455) (GRID(IEXT(J)),J=1,NZ)
2010 455 FORMAT((2X,5F15.7))
2012 460 FORMAT(1X,70(1H*))
2016 !CC IF(NFILT.NE.0) GOTO 100 ! removal of re-run loop.
2018 END SUBROUTINE mccpar
2021 FUNCTION EFF(TEMP,FX,WTX,LBAND,JTYPE)
2022 DIMENSION FX(5),WTX(5)
2023 IF(JTYPE.EQ.2) GOTO 1
2026 1 EFF = FX(LBAND)*TEMP
2030 FUNCTION WATE(TEMP,FX,WTX,LBAND,JTYPE)
2031 DIMENSION FX(5),WTX(5)
2032 IF(JTYPE.EQ.2) GOTO 1
2035 1 IF(FX(LBAND).LT.0.0001) GOTO 2
2036 WATE = WTX(LBAND)/TEMP
2043 !! WRITE(6,*)' **** ERROR IN INPUT DATA ****'
2044 ! CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
2045 ! END SUBROUTINE error
2048 SUBROUTINE REMEZ(EDGE,NBANDS,PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID)
2049 ! THIS SUBROUTINE IMPLEMENTS THE REMEZ EXCHANGE ALGORITHM
2050 ! FOR THE WEIGHTED CHEBCHEV APPROXIMATION OF A CONTINUOUS
2051 ! FUNCTION WITH A SUM OF COSINES. INPUTS TO THE SUBROUTINE
2052 ! ARE A DENSE GRID WHICH REPLACES THE FREQUENCY AXIS, THE
2053 ! DESIRED FUNCTION ON THIS GRID, THE WEIGHT FUNCTION ON THE
2054 ! GRID, THE NUMBER OF COSINES, AND THE INITIAL GUESS OF THE
2055 ! EXTREMAL FREQUENCIES. THE PROGRAM MINIMIZES THE CHEBYSHEV
2056 ! ERROR BY DETERMINING THE BEST LOCATION OF THE EXTREMAL
2057 ! FREQUENCIES (POINTS OF MAXIMUM ERROR) AND THEN CALCULATES
2058 ! THE COEFFICIENTS OF THE BEST APPROXIMATION.
2060 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
2062 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
2063 DIMENSION DES(1045),GRID(1045),WT(1045)
2064 DIMENSION A(66),P(65),Q(65)
2065 DOUBLE PRECISION PI2,DNUM,DDEN,DTEMP,A,P,Q
2066 DOUBLE PRECISION AD,DEV,X,Y
2067 DOUBLE PRECISION, EXTERNAL :: D, GEE
2069 ! THE PROGRAM ALLOWS A MAXIMUM NUMBER OF ITERATIONS OF 25
2079 IF(NITER.GT.ITRMAX) GO TO 400
2082 DTEMP=DCOS(DTEMP*PI2)
2086 120 AD(J)=D(J,NZ,JET,X)
2099 IF(DEV.GT.0.0) NU=-1
2107 IF(DEV.GE.DEVL) GO TO 150
2108 WRITE(6,*) ' ******** FAILURE TO CONVERGE *********** '
2109 WRITE(6,*) ' PROBABLE CAUSE IS MACHINE ROUNDING ERROR '
2110 WRITE(6,*) ' THE IMPULSE RESPONSE MAY BE CORRECT '
2111 WRITE(6,*) ' CHECK WITH A FREQUENCY RESPONSE '
2112 WRITE(6,*) ' **************************************** '
2122 ! SEARCH FOR THE EXTERMAL FREQUENCIES OF THE BEST
2125 200 IF(J.EQ.NZZ) YNZ=COMP
2126 IF(J.GE.NZZ) GO TO 300
2132 IF(L.GE.KUP) GO TO 220
2133 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2134 ERR=(ERR-DES(L))*WT(L)
2136 IF(DTEMP.LE.0.0) GO TO 220
2139 IF(L.GE.KUP) GO TO 215
2140 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2141 ERR=(ERR-DES(L))*WT(L)
2143 IF(DTEMP.LE.0.0) GO TO 215
2153 IF(L.LE.KLOW) GO TO 250
2154 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2155 ERR=(ERR-DES(L))*WT(L)
2157 IF(DTEMP.GT.0.0) GO TO 230
2158 IF(JCHNGE.LE.0) GO TO 225
2162 IF(L.LE.KLOW) GO TO 240
2163 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2164 ERR=(ERR-DES(L))*WT(L)
2166 IF(DTEMP.LE.0.0) GO TO 240
2175 IF(JCHNGE.GT.0) GO TO 215
2177 IF(L.GE.KUP) GO TO 260
2178 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2179 ERR=(ERR-DES(L))*WT(L)
2181 IF(DTEMP.LE.0.0) GO TO 255
2187 300 IF(J.GT.NZZ) GO TO 320
2188 IF(K1.GT.IEXT(1)) K1=IEXT(1)
2189 IF(KNZ.LT.IEXT(NZ)) KNZ=IEXT(NZ)
2197 IF(L.GE.KUP) GO TO 315
2198 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2199 ERR=(ERR-DES(L))*WT(L)
2201 IF(DTEMP.LE.0.0) GO TO 310
2207 320 IF(LUCK.GT.9) GO TO 350
2208 IF(COMP.GT.Y1) Y1=COMP
2215 IF(L.LE.KLOW) GO TO 340
2216 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
2217 ERR=(ERR-DES(L))*WT(L)
2219 IF(DTEMP.LE.0.0) GO TO 330
2224 340 IF(LUCK.EQ.6) GO TO 370
2226 345 IEXT(NZZ-J)=IEXT(NZ-J)
2231 360 IEXT(J)=IEXT(J+1)
2234 370 IF(JCHNGE.GT.0) GO TO 100
2236 ! CALCULATION OF THE COEFFICIENTS OF THE BEST APPROXIMATION
2237 ! USING THE INVERSE DISCRETE FOURIER TRANSFORM.
2248 IF(EDGE(1).EQ.0.0.AND.EDGE(2*NBANDS).EQ.0.5) KKK=1
2249 IF(NFCNS.LE.3) KKK=1
2250 IF(KKK.EQ.1) GO TO 405
2251 DTEMP=DCOS(PI2*GRID(1))
2252 DNUM=DCOS(PI2*GRID(NGRID))
2254 BB=-(DTEMP+DNUM)/(DTEMP-DNUM)
2259 IF(KKK.EQ.1) GO TO 410
2261 ! original : FT=ARCOS(XT)/PI2
2264 IF(XT.GT.XE) GO TO 420
2265 IF((XE-XT).LT.FSH) GO TO 415
2270 420 IF((XT-XE).LT.FSH) GO TO 415
2272 A(J)=GEE(1,NZ,GRID,PI2,X,Y,AD)
2281 IF(NM1.LT.1) GO TO 505
2283 500 DTEMP=DTEMP+A(K+1)*DCOS(DNUM*K)
2284 505 DTEMP=2.0*DTEMP+A(1)
2287 550 ALPHA(J)=2*ALPHA(J)/CN
2288 ALPHA(1)=ALPHA(1)/CN
2289 IF(KKK.EQ.1) GO TO 545
2290 P(1)=2.0*ALPHA(NFCNS)*BB+ALPHA(NM1)
2291 P(2)=2.0*AA*ALPHA(NFCNS)
2292 Q(1)=ALPHA(NFCNS-2)-ALPHA(NFCNS)
2294 IF(J.LT.NM1) GO TO 515
2301 520 P(K)=2.0*BB*A(K)
2302 P(2)=P(2)+A(1)*2.0*AA
2305 525 P(K)=P(K)+Q(K)+AA*A(K+1)
2308 530 P(K)=P(K)+AA*A(K-1)
2309 IF(J.EQ.NM1) GO TO 540
2312 Q(1)=Q(1)+ALPHA(NFCNS-1-J)
2317 IF(NFCNS.GT.3) RETURN
2320 END SUBROUTINE remez
2322 DOUBLE PRECISION FUNCTION D(K,N,M,X)
2323 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
2324 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
2325 DIMENSION DES(1045),GRID(1045),WT(1045)
2326 DOUBLE PRECISION AD,DEV,X,Y
2328 DOUBLE PRECISION PI2
2334 1 D = 2.0*D*(Q-X(J))
2341 DOUBLE PRECISION FUNCTION GEE(K,N,GRID,PI2,X,Y,AD)
2342 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
2343 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
2344 DIMENSION DES(1045),GRID(1045),WT(1045)
2345 DOUBLE PRECISION AD,DEV,X,Y
2346 DOUBLE PRECISION P,C,D,XF
2347 DOUBLE PRECISION PI2
2361 REAL FUNCTION RSLF(P,T)
2364 REAL, INTENT(IN):: P, T
2366 REAL, PARAMETER:: C0= .611583699E03
2367 REAL, PARAMETER:: C1= .444606896E02
2368 REAL, PARAMETER:: C2= .143177157E01
2369 REAL, PARAMETER:: C3= .264224321E-1
2370 REAL, PARAMETER:: C4= .299291081E-3
2371 REAL, PARAMETER:: C5= .203154182E-5
2372 REAL, PARAMETER:: C6= .702620698E-8
2373 REAL, PARAMETER:: C7= .379534310E-11
2374 REAL, PARAMETER:: C8=-.321582393E-13
2376 X=MAX(-80.,T-273.16)
2378 ! ESL=612.2*EXP(17.67*X/(T-29.65))
2379 ESL=C0+X*(C1+X*(C2+X*(C3+X*(C4+X*(C5+X*(C6+X*(C7+X*C8)))))))
2380 RSLF=.622*ESL/(P-ESL)
2384 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2385 ! DFI startfwd group of functions
2386 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2388 SUBROUTINE wrf_dfi_startfwd_init ( )
2390 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
2396 SUBROUTINE dfi_startfwd_init_recurse(grid)
2397 USE module_domain, ONLY : domain
2398 TYPE (domain), POINTER :: grid
2399 END SUBROUTINE dfi_startfwd_init_recurse
2402 ! Now, setup all nests
2404 CALL dfi_startfwd_init_recurse(head_grid)
2406 CALL set_current_grid_ptr( head_grid )
2408 END SUBROUTINE wrf_dfi_startfwd_init
2411 RECURSIVE SUBROUTINE dfi_startfwd_init_recurse(grid)
2413 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
2418 SUBROUTINE dfi_startfwd_init(grid)
2419 USE module_domain, ONLY : domain
2420 TYPE (domain), POINTER :: grid
2421 END SUBROUTINE dfi_startfwd_init
2425 TYPE (domain), POINTER :: grid
2426 TYPE (domain), POINTER :: grid_ptr
2430 DO WHILE ( ASSOCIATED( grid_ptr ) )
2432 ! Assure that time-step is set back to positive
2433 ! for this forward step.
2435 grid_ptr%dt = abs(grid_ptr%dt)
2436 grid_ptr%time_step = abs(grid_ptr%time_step)
2437 CALL set_current_grid_ptr( grid_ptr )
2438 CALL dfi_startfwd_init( grid_ptr )
2439 DO kid = 1, max_nests
2440 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2441 CALL dfi_startfwd_init_recurse(grid_ptr%nests(kid)%ptr)
2444 grid_ptr => grid_ptr%sibling
2447 END SUBROUTINE dfi_startfwd_init_recurse
2450 SUBROUTINE dfi_startfwd_init ( grid )
2452 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
2454 USE module_state_description
2458 TYPE (domain) , POINTER :: grid
2462 SUBROUTINE Setup_Timekeeping(grid)
2463 USE module_domain, ONLY : domain
2464 TYPE (domain), POINTER :: grid
2465 END SUBROUTINE Setup_Timekeeping
2469 grid%dfi_stage = DFI_STARTFWD
2472 ! No need for adaptive time-step
2473 CALL nl_set_use_adaptive_time_step( grid%id, .false. )
2476 CALL Setup_Timekeeping (grid)
2477 grid%start_subtime = domain_get_start_time ( head_grid )
2478 grid%stop_subtime = domain_get_stop_time ( head_grid )
2480 CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
2482 END SUBROUTINE dfi_startfwd_init
2484 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2485 ! DFI startbck group of functions
2486 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2488 SUBROUTINE wrf_dfi_startbck_init ( )
2490 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
2496 SUBROUTINE dfi_startbck_init_recurse(grid)
2497 USE module_domain, ONLY : domain
2498 TYPE (domain), POINTER :: grid
2499 END SUBROUTINE dfi_startbck_init_recurse
2502 ! Now, setup all nests
2504 CALL dfi_startbck_init_recurse(head_grid)
2506 CALL set_current_grid_ptr( head_grid )
2508 END SUBROUTINE wrf_dfi_startbck_init
2511 RECURSIVE SUBROUTINE dfi_startbck_init_recurse(grid)
2513 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
2518 SUBROUTINE dfi_startbck_init(grid)
2519 USE module_domain, ONLY : domain
2520 TYPE (domain), POINTER :: grid
2521 END SUBROUTINE dfi_startbck_init
2525 TYPE (domain), POINTER :: grid
2526 TYPE (domain), POINTER :: grid_ptr
2530 DO WHILE ( ASSOCIATED( grid_ptr ) )
2532 ! Assure that time-step is set back to positive
2533 ! for this forward step.
2535 grid_ptr%dt = abs(grid_ptr%dt)
2536 grid_ptr%time_step = abs(grid_ptr%time_step)
2537 CALL set_current_grid_ptr( grid_ptr )
2538 CALL dfi_startbck_init( grid_ptr )
2539 DO kid = 1, max_nests
2540 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2541 CALL dfi_startbck_init_recurse(grid_ptr%nests(kid)%ptr)
2544 grid_ptr => grid_ptr%sibling
2547 END SUBROUTINE dfi_startbck_init_recurse
2550 SUBROUTINE dfi_startbck_init ( grid )
2552 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
2554 USE module_state_description
2558 TYPE (domain) , POINTER :: grid
2562 SUBROUTINE Setup_Timekeeping(grid)
2563 USE module_domain, ONLY : domain
2564 TYPE (domain), POINTER :: grid
2565 END SUBROUTINE Setup_Timekeeping
2569 grid%dfi_stage = DFI_STARTBCK
2571 ! set physics options to zero
2572 CALL nl_set_mp_physics( grid%id, 0 )
2573 CALL nl_set_ra_lw_physics( grid%id, 0 )
2574 CALL nl_set_ra_sw_physics( grid%id, 0 )
2575 CALL nl_set_sf_surface_physics( grid%id, 0 )
2576 CALL nl_set_sf_sfclay_physics( grid%id, 0 )
2577 CALL nl_set_sf_urban_physics( grid%id, 0 )
2578 CALL nl_set_bl_pbl_physics( grid%id, 0 )
2579 CALL nl_set_cu_physics( grid%id, 0 )
2580 CALL nl_set_damp_opt( grid%id, 0 )
2581 CALL nl_set_sst_update( grid%id, 0 )
2582 CALL nl_set_gwd_opt( grid%id, 0 )
2584 CALL nl_set_diff_6th_opt( grid%id, 0 )
2585 CALL nl_set_use_adaptive_time_step( grid%id, .false. )
2587 CALL nl_set_feedback( grid%id, 0 )
2590 CALL nl_set_constant_bc( grid%id, head_grid%constant_bc)
2594 ! set chemistry option to zero
2595 CALL nl_set_chem_opt (grid%id, 0)
2596 CALL nl_set_aer_ra_feedback (grid%id, 0)
2597 CALL nl_set_io_form_auxinput5 (grid%id, 0)
2598 CALL nl_set_io_form_auxinput7 (grid%id, 0)
2599 CALL nl_set_io_form_auxinput8 (grid%id, 0)
2603 ! set diffusion to zero for backward integration
2604 CALL nl_set_km_opt( grid%id, grid%km_opt_dfi)
2605 CALL nl_set_moist_adv_dfi_opt( grid%id, grid%moist_adv_dfi_opt)
2606 IF ( grid%moist_adv_opt == 2 ) THEN
2607 CALL nl_set_moist_adv_opt( grid%id, 0)
2611 !tgs need to call start_domain here to reset bc initialization for
2612 ! negative dt, but only for outer domain.
2613 if (grid%id == 1) then
2614 CALL start_domain ( grid , .TRUE. )
2617 ! Call wrf_run to advance forward 1 step
2620 CALL nl_set_time_step ( grid%id, -grid%time_step )
2622 CALL Setup_Timekeeping (grid)
2624 grid%start_subtime = domain_get_start_time ( grid )
2625 grid%stop_subtime = domain_get_stop_time ( grid )
2627 CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
2629 END SUBROUTINE dfi_startbck_init
2632 SUBROUTINE wrf_dfi_bck_init ( )
2634 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
2636 USE module_state_description
2641 SUBROUTINE dfi_bck_init_recurse(grid)
2642 USE module_domain, ONLY : domain
2643 TYPE (domain), POINTER :: grid
2644 END SUBROUTINE dfi_bck_init_recurse
2647 ! We can only call dfi_bck_init for the head_grid
2648 ! since nests have not been instantiated at this point,
2649 ! so, dfi_bck_init will need to be called for each
2650 ! nest from integrate.
2651 CALL dfi_bck_init_recurse(head_grid)
2653 END SUBROUTINE wrf_dfi_bck_init
2655 RECURSIVE SUBROUTINE dfi_bck_init_recurse(grid)
2657 USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
2662 SUBROUTINE dfi_bck_init(grid)
2663 USE module_domain, ONLY : domain
2664 TYPE (domain), POINTER :: grid
2665 END SUBROUTINE dfi_bck_init
2669 TYPE (domain), POINTER :: grid
2670 TYPE (domain), POINTER :: grid_ptr
2674 DO WHILE ( ASSOCIATED( grid_ptr ) )
2676 ! Assure that time-step is set back to positive
2677 ! for this forward step.
2679 grid_ptr%dt = abs(grid_ptr%dt)
2680 grid_ptr%time_step = abs(grid_ptr%time_step)
2681 CALL set_current_grid_ptr( grid_ptr )
2682 CALL dfi_bck_init( grid_ptr )
2683 DO kid = 1, max_nests
2684 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2685 CALL dfi_bck_init_recurse(grid_ptr%nests(kid)%ptr)
2688 grid_ptr => grid_ptr%sibling
2691 END SUBROUTINE dfi_bck_init_recurse
2693 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2694 ! DFI forward initialization group of functions
2695 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2697 SUBROUTINE wrf_dfi_fwd_init ( )
2699 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
2705 SUBROUTINE dfi_fwd_init_recurse(grid)
2706 USE module_domain, ONLY : domain
2707 TYPE (domain), POINTER :: grid
2708 END SUBROUTINE dfi_fwd_init_recurse
2711 ! Now, setup all nests
2713 CALL dfi_fwd_init_recurse(head_grid)
2715 CALL set_current_grid_ptr( head_grid )
2717 END SUBROUTINE wrf_dfi_fwd_init
2719 RECURSIVE SUBROUTINE dfi_fwd_init_recurse(grid)
2721 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
2726 SUBROUTINE dfi_fwd_init(grid)
2727 USE module_domain, ONLY : domain
2728 TYPE (domain), POINTER :: grid
2729 END SUBROUTINE dfi_fwd_init
2733 TYPE (domain), POINTER :: grid
2734 TYPE (domain), POINTER :: grid_ptr
2738 DO WHILE ( ASSOCIATED( grid_ptr ) )
2740 ! Assure that time-step is set back to positive
2741 ! for this forward step.
2743 grid_ptr%dt = abs(grid_ptr%dt)
2744 grid_ptr%time_step = abs(grid_ptr%time_step)
2745 CALL set_current_grid_ptr( grid_ptr )
2746 CALL dfi_fwd_init( grid_ptr )
2747 DO kid = 1, max_nests
2748 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2749 CALL dfi_fwd_init_recurse(grid_ptr%nests(kid)%ptr)
2752 grid_ptr => grid_ptr%sibling
2755 END SUBROUTINE dfi_fwd_init_recurse
2757 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2758 ! DFI forecast initialization group of functions
2759 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2761 SUBROUTINE wrf_dfi_fst_init ( )
2763 USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time, set_current_grid_ptr
2769 SUBROUTINE dfi_fst_init_recurse(grid)
2770 USE module_domain, ONLY : domain
2771 TYPE (domain), POINTER :: grid
2772 END SUBROUTINE dfi_fst_init_recurse
2775 ! Now, setup all nests
2777 CALL dfi_fst_init_recurse(head_grid)
2779 CALL set_current_grid_ptr( head_grid )
2781 END SUBROUTINE wrf_dfi_fst_init
2783 RECURSIVE SUBROUTINE dfi_fst_init_recurse ( grid )
2785 USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time, max_nests, set_current_grid_ptr
2790 SUBROUTINE dfi_fst_init(grid)
2791 USE module_domain, ONLY : domain
2792 TYPE (domain), POINTER :: grid
2793 END SUBROUTINE dfi_fst_init
2797 TYPE (domain), POINTER :: grid
2798 TYPE (domain), POINTER :: grid_ptr
2802 DO WHILE ( ASSOCIATED( grid_ptr ) )
2804 ! Assure that time-step is set back to positive
2805 ! for this forward step.
2807 grid_ptr%dt = abs(grid_ptr%dt)
2808 grid_ptr%time_step = abs(grid_ptr%time_step)
2809 CALL set_current_grid_ptr( grid_ptr )
2810 CALL dfi_fst_init( grid_ptr )
2811 DO kid = 1, max_nests
2812 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2813 CALL dfi_fst_init_recurse(grid_ptr%nests(kid)%ptr)
2816 grid_ptr => grid_ptr%sibling
2819 END SUBROUTINE dfi_fst_init_recurse
2821 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2822 ! DFI write initialization group of functions
2823 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2825 SUBROUTINE wrf_dfi_write_initialized_state( )
2827 USE module_domain, ONLY : domain, head_grid
2830 SUBROUTINE dfi_write_initialized_state_recurse(grid)
2831 USE module_domain, ONLY : domain
2832 TYPE (domain), POINTER :: grid
2833 END SUBROUTINE dfi_write_initialized_state_recurse
2836 ! Now, setup all nests
2838 CALL dfi_write_initialized_state_recurse(head_grid)
2840 END SUBROUTINE wrf_dfi_write_initialized_state
2842 RECURSIVE SUBROUTINE dfi_write_initialized_state_recurse( grid )
2844 USE module_domain, ONLY : domain, max_nests
2849 SUBROUTINE dfi_write_initialized_state( grid )
2850 USE module_domain, ONLY : domain
2851 TYPE (domain), POINTER :: grid
2852 END SUBROUTINE dfi_write_initialized_state
2856 TYPE (domain), POINTER :: grid
2857 TYPE (domain), POINTER :: grid_ptr
2861 DO WHILE ( ASSOCIATED( grid_ptr ) )
2863 ! Assure that time-step is set back to positive
2864 ! for this forward step.
2866 CALL dfi_write_initialized_state( grid_ptr )
2867 DO kid = 1, max_nests
2868 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2869 CALL dfi_write_initialized_state_recurse(grid_ptr%nests(kid)%ptr)
2872 grid_ptr => grid_ptr%sibling
2875 END SUBROUTINE dfi_write_initialized_state_recurse
2878 RECURSIVE SUBROUTINE dfi_array_reset_recurse(grid)
2880 USE module_domain, ONLY : domain, max_nests, set_current_grid_ptr
2885 SUBROUTINE dfi_array_reset(grid)
2886 USE module_domain, ONLY : domain
2887 TYPE (domain), POINTER :: grid
2888 END SUBROUTINE dfi_array_reset
2892 TYPE (domain), POINTER :: grid
2893 TYPE (domain), POINTER :: grid_ptr
2897 DO WHILE ( ASSOCIATED( grid_ptr ) )
2898 CALL set_current_grid_ptr( grid_ptr )
2899 CALL dfi_array_reset( grid_ptr )
2900 DO kid = 1, max_nests
2901 IF ( ASSOCIATED( grid_ptr%nests(kid)%ptr ) ) THEN
2902 CALL dfi_array_reset_recurse(grid_ptr%nests(kid)%ptr)
2905 grid_ptr => grid_ptr%sibling
2908 END SUBROUTINE dfi_array_reset_recurse