/wrfv2_fire/share/dfi.F
FORTRAN Legacy | 2909 lines | 1731 code | 567 blank | 611 comment | 17 complexity | cc24b016fea48a0ad33b12ada0258f2f MD5 | raw file
Possible License(s): AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- SUBROUTINE dfi_accumulate( grid )
- USE module_domain, ONLY : domain
- ! USE module_configure
- USE module_driver_constants
- USE module_machine
- ! USE module_dm
- USE module_model_constants
- USE module_state_description
- IMPLICIT NONE
- REAL hn
- CHARACTER*80 mess
- ! Input data.
- TYPE(domain) , POINTER :: grid
- IF ( grid%dfi_opt .EQ. DFI_NODFI .OR. grid%dfi_stage .EQ. DFI_FST ) RETURN
- #if (EM_CORE == 1)
- hn = grid%hcoeff(grid%itimestep+1)
- ! accumulate dynamic variables
- grid%dfi_mu(:,:) = grid%dfi_mu(:,:) + grid%mu_2(:,:) * hn
- grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u_2(:,:,:) * hn
- grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v_2(:,:,:) * hn
- grid%dfi_w(:,:,:) = grid%dfi_w(:,:,:) + grid%w_2(:,:,:) * hn
- grid%dfi_ww(:,:,:) = grid%dfi_ww(:,:,:) + grid%ww(:,:,:) * hn
- grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t_2(:,:,:) * hn
- grid%dfi_phb(:,:,:) = grid%dfi_phb(:,:,:) + grid%phb(:,:,:) * hn
- grid%dfi_ph0(:,:,:) = grid%dfi_ph0(:,:,:) + grid%ph0(:,:,:) * hn
- grid%dfi_php(:,:,:) = grid%dfi_php(:,:,:) + grid%php(:,:,:) * hn
- grid%dfi_p(:,:,:) = grid%dfi_p(:,:,:) + grid%p(:,:,:) * hn
- grid%dfi_ph(:,:,:) = grid%dfi_ph(:,:,:) + grid%ph_2(:,:,:) * hn
- grid%dfi_tke(:,:,:) = grid%dfi_tke(:,:,:) + grid%tke_2(:,:,:) * hn
- grid%dfi_al(:,:,:) = grid%dfi_al(:,:,:) + grid%al(:,:,:) * hn
- grid%dfi_alt(:,:,:) = grid%dfi_alt(:,:,:) + grid%alt(:,:,:) * hn
- grid%dfi_pb(:,:,:) = grid%dfi_pb(:,:,:) + grid%pb(:,:,:) * hn
- ! neg. check on hydrometeor and scalar variables
- grid%moist(:,:,:,:) = max(0.,grid%moist(:,:,:,:))
- grid%dfi_scalar(:,:,:,:) = max(0.,grid%dfi_scalar(:,:,:,:))
- #if ( WRF_DFI_RADAR == 1 )
- IF ( grid%dfi_radar .EQ. 0 ) then
- grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
- ELSE
- grid%dfi_moist(:,:,:,P_QV) = grid%dfi_moist(:,:,:,P_QV) + grid%moist(:,:,:,P_QV) * hn
- ENDIF
- #else
- grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
- #endif
- grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
- ! accumulate DFI coefficient
- grid%hcoeff_tot = grid%hcoeff_tot + hn
- #endif
- #if (NMM_CORE == 1)
- hn = grid%hcoeff(grid%ntsd+1)
- grid%dfi_pd(:,:) = grid%dfi_pd(:,:) + grid%pd(:,:) * hn
- grid%dfi_pint(:,:,:) = grid%dfi_pint(:,:,:) + grid%pint(:,:,:) * hn
- grid%dfi_dwdt(:,:,:) = grid%dfi_dwdt(:,:,:) + grid%dwdt(:,:,:) * hn
- grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t(:,:,:) * hn
- grid%dfi_q(:,:,:) = grid%dfi_q(:,:,:) + grid%q(:,:,:) * hn
- grid%dfi_q2(:,:,:) = grid%dfi_q2(:,:,:) + grid%q2(:,:,:) * hn
- grid%dfi_cwm(:,:,:) = grid%dfi_cwm(:,:,:) + grid%cwm(:,:,:) * hn
- grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u(:,:,:) * hn
- grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v(:,:,:) * hn
- grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
- grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
- ! accumulate DFI coefficient
- grid%hcoeff_tot = grid%hcoeff_tot + hn
- write(mess,*) 'grid%hcoeff_tot: ', grid%hcoeff_tot
- call wrf_message(mess)
- #endif
- END SUBROUTINE dfi_accumulate
- SUBROUTINE dfi_bck_init ( grid )
- USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
- USE module_utility
- USE module_state_description
- IMPLICIT NONE
- TYPE (domain) , POINTER :: grid
- INTEGER rc
- CHARACTER*80 mess
- INTERFACE
- SUBROUTINE Setup_Timekeeping(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE Setup_Timekeeping
- SUBROUTINE dfi_save_arrays(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_save_arrays
- SUBROUTINE dfi_clear_accumulation(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_clear_accumulation
- SUBROUTINE optfil_driver(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE optfil_driver
- SUBROUTINE start_domain(grid, allowed_to_read)
- USE module_domain, ONLY : domain
- TYPE (domain) :: grid
- LOGICAL, INTENT(IN) :: allowed_to_read
- END SUBROUTINE start_domain
- END INTERFACE
- grid%dfi_stage = DFI_BCK
- ! Negate time step
- IF ( grid%time_step_dfi .gt. 0 ) THEN
- CALL nl_set_time_step ( 1, -grid%time_step_dfi )
- ELSE
- CALL nl_set_time_step ( 1, -grid%time_step )
- CALL nl_set_time_step_fract_num ( 1, -grid%time_step_fract_num )
- ENDIF
- CALL Setup_Timekeeping (grid)
- !tgs 7apr11 - need to call start_domain here to reset bc initialization for negative dt
- CALL start_domain ( grid , .TRUE. )
- !tgs 7apr11 - save arrays should be done after start_domain to get correct grid%p field
- CALL dfi_save_arrays ( grid )
- ! set physics options to zero
- CALL nl_set_mp_physics( grid%id, 0 )
- CALL nl_set_ra_lw_physics( grid%id, 0 )
- CALL nl_set_ra_sw_physics( grid%id, 0 )
- CALL nl_set_sf_surface_physics( grid%id, 0 )
- CALL nl_set_sf_sfclay_physics( grid%id, 0 )
- CALL nl_set_sf_urban_physics( grid%id, 0 )
- CALL nl_set_bl_pbl_physics( grid%id, 0 )
- CALL nl_set_cu_physics( grid%id, 0 )
- CALL nl_set_damp_opt( grid%id, 0 )
- CALL nl_set_sst_update( grid%id, 0 )
- CALL nl_set_fractional_seaice( grid%id, 0 )
- CALL nl_set_gwd_opt( grid%id, 0 )
- CALL nl_set_feedback( grid%id, 0 )
- ! set bc
- #if (EM_CORE == 1)
- CALL nl_set_diff_6th_opt( grid%id, 0 )
- CALL nl_set_constant_bc(1, grid%constant_bc)
- CALL nl_set_use_adaptive_time_step( grid%id, .false. )
- #endif
- #ifdef WRF_CHEM
- ! set chemistry option to zero
- CALL nl_set_chem_opt (grid%id, 0)
- CALL nl_set_aer_ra_feedback (grid%id, 0)
- CALL nl_set_io_form_auxinput5 (grid%id, 0)
- CALL nl_set_io_form_auxinput7 (grid%id, 0)
- CALL nl_set_io_form_auxinput8 (grid%id, 0)
- #endif
- ! set diffusion to zero for backward integration
- #if (EM_CORE == 1)
- CALL nl_set_km_opt( grid%id, grid%km_opt_dfi)
- CALL nl_set_moist_adv_dfi_opt( grid%id, grid%moist_adv_dfi_opt)
- IF ( grid%moist_adv_opt == 2 ) THEN
- CALL nl_set_moist_adv_opt( grid%id, 0)
- ENDIF
- #endif
- #if (NMM_CORE == 1)
- !
- ! CHANGE (SIGN ONLY OF) IMPORTANT TIME CONSTANTS
- !
- CALL nl_get_time_step( grid%id, grid%time_step )
- if (grid%time_step .lt. 0) then
- ! DT =-DT
- write(mess,*) 'changing signs for backward integration'
- call wrf_message(mess)
- grid%CPGFV = -grid%CPGFV
- grid%EN = -grid%EN
- grid%ENT = -grid%ENT
- grid%F4D = -grid%F4D
- grid%F4Q = -grid%F4Q
- grid%EF4T = -grid%EF4T
-
- grid%EM(:) = -grid%EM(:)
- grid%EMT(:) = -grid%EMT(:)
- grid%F4Q2(:) = -grid%F4Q2(:)
-
- grid%WPDAR(:,:)= -grid%WPDAR(:,:)
- grid%CPGFU(:,:)= -grid%CPGFU(:,:)
- grid%CURV(:,:)= -grid%CURV(:,:)
- grid%FCP(:,:)= -grid%FCP(:,:)
- grid%FAD(:,:)= -grid%FAD(:,:)
- grid%F(:,:)= -grid%F(:,:)
- endif
- #endif
- grid%start_subtime = domain_get_start_time ( grid )
- grid%stop_subtime = domain_get_stop_time ( grid )
- CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
- !tgs 7apr11 - this call has been moved up
- ! CALL dfi_save_arrays ( grid )
- CALL dfi_clear_accumulation( grid )
- CALL optfil_driver(grid)
- !tgs need to call start_domain here to reset bc initialization for negative dt
- CALL start_domain ( grid , .TRUE. )
- END SUBROUTINE dfi_bck_init
- SUBROUTINE dfi_fwd_init ( grid )
- USE module_domain, ONLY : domain, head_grid, domain_get_stop_time, domain_get_start_time
- USE module_utility, ONLY : WRFU_ClockSet
- USE module_state_description
- IMPLICIT NONE
- TYPE (domain) , POINTER :: grid
- INTEGER rc
- CHARACTER*80 mess
- INTERFACE
- SUBROUTINE Setup_Timekeeping(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE Setup_Timekeeping
- SUBROUTINE dfi_save_arrays(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_save_arrays
- SUBROUTINE dfi_clear_accumulation(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_clear_accumulation
- SUBROUTINE optfil_driver(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE optfil_driver
- SUBROUTINE start_domain(grid, allowed_to_read)
- USE module_domain, ONLY : domain
- TYPE (domain) :: grid
- LOGICAL, INTENT(IN) :: allowed_to_read
- END SUBROUTINE start_domain
- END INTERFACE
- grid%dfi_stage = DFI_FWD
- ! for Setup_Timekeeping to use when setting the clock
- IF ( grid%time_step_dfi .gt. 0 ) THEN
- CALL nl_set_time_step ( grid%id, grid%time_step_dfi )
- ELSE
- CALL nl_get_time_step( grid%id, grid%time_step )
- CALL nl_get_time_step_fract_num( grid%id, grid%time_step_fract_num )
- grid%time_step = abs(grid%time_step)
- CALL nl_set_time_step( grid%id, grid%time_step )
- grid%time_step_fract_num = abs(grid%time_step_fract_num)
- CALL nl_set_time_step_fract_num( grid%id, grid%time_step_fract_num )
- ENDIF
- grid%itimestep=0
- grid%xtime=0.
- ! reset physics options to normal
- CALL nl_set_mp_physics( grid%id, grid%mp_physics)
- CALL nl_set_ra_lw_physics( grid%id, grid%ra_lw_physics)
- CALL nl_set_ra_sw_physics( grid%id, grid%ra_sw_physics)
- CALL nl_set_sf_surface_physics( grid%id, grid%sf_surface_physics)
- CALL nl_set_sf_sfclay_physics( grid%id, grid%sf_sfclay_physics)
- CALL nl_set_sf_urban_physics( grid%id, grid%sf_urban_physics)
- CALL nl_set_bl_pbl_physics( grid%id, grid%bl_pbl_physics)
- CALL nl_set_cu_physics( grid%id, grid%cu_physics)
- CALL nl_set_damp_opt( grid%id, grid%damp_opt)
- CALL nl_set_sst_update( grid%id, 0)
- CALL nl_set_fractional_seaice( grid%id, grid%fractional_seaice)
- CALL nl_set_gwd_opt( grid%id, grid%gwd_opt)
- CALL nl_set_feedback( grid%id, 0 )
- #if (EM_CORE == 1)
- CALL nl_set_diff_6th_opt( grid%id, grid%diff_6th_opt)
- CALL nl_set_use_adaptive_time_step( grid%id, .false. )
- ! set bc
- CALL nl_set_constant_bc(grid%id, grid%constant_bc)
- #endif
- #if (NMM_CORE == 1)
- !
- ! CHANGE (SIGN ONLY OF) IMPORTANT TIME CONSTANTS
- !
- !mptest CALL nl_get_time_step( grid%id, grid%time_step )
- !!! here need to key off something else being the "wrong" sign
- if (grid%cpgfv .gt. 0) then
- write(mess,*) 'changing signs for forward integration'
- call wrf_message(mess)
- grid%CPGFV = -grid%CPGFV
- grid%EN = -grid%EN
- grid%ENT = -grid%ENT
- grid%F4D = -grid%F4D
- grid%F4Q = -grid%F4Q
- grid%EF4T = -grid%EF4T
-
- grid%EM(:) = -grid%EM(:)
- grid%EMT(:) = -grid%EMT(:)
- grid%F4Q2(:) = -grid%F4Q2(:)
-
- grid%WPDAR(:,:)= -grid%WPDAR(:,:)
- grid%CPGFU(:,:)= -grid%CPGFU(:,:)
- grid%CURV(:,:)= -grid%CURV(:,:)
- grid%FCP(:,:)= -grid%FCP(:,:)
- grid%FAD(:,:)= -grid%FAD(:,:)
- grid%F(:,:)= -grid%F(:,:)
- endif
- #endif
- !#ifdef WRF_CHEM
- ! ! reset chem option to normal
- ! CALL nl_set_chem_opt( grid%id, grid%chem_opt)
- ! CALL nl_set_aer_ra_feedback (grid%id, grid%aer_ra_feedback)
- !#endif
- #if (EM_CORE == 1)
- ! reset km_opt to norlmal
- CALL nl_set_km_opt( grid%id, grid%km_opt)
- CALL nl_set_moist_adv_opt( grid%id, grid%moist_adv_opt)
- #endif
- CALL Setup_Timekeeping (grid)
- grid%start_subtime = domain_get_start_time ( head_grid )
- grid%stop_subtime = domain_get_stop_time ( head_grid )
- CALL WRFU_ClockSet(grid%domain_clock, currTime=grid%start_subtime, rc=rc)
- IF ( grid%dfi_opt .EQ. DFI_DFL ) THEN
- CALL dfi_save_arrays ( grid )
- END IF
- CALL dfi_clear_accumulation( grid )
- CALL optfil_driver(grid)
- !tgs need to call it here to reset bc initialization for positive time_step
- CALL start_domain ( grid , .TRUE. )
- END SUBROUTINE dfi_fwd_init
- SUBROUTINE dfi_fst_init ( grid )
- USE module_domain, ONLY : domain, domain_get_stop_time, domain_get_start_time
- USE module_state_description
- IMPLICIT NONE
- TYPE (domain) , POINTER :: grid
- CHARACTER (LEN=80) :: wrf_error_message
- INTERFACE
- SUBROUTINE Setup_Timekeeping(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE Setup_Timekeeping
- SUBROUTINE dfi_save_arrays(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_save_arrays
- SUBROUTINE dfi_clear_accumulation(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_clear_accumulation
- SUBROUTINE optfil_driver(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE optfil_driver
- SUBROUTINE start_domain(grid, allowed_to_read)
- USE module_domain, ONLY : domain
- TYPE (domain) :: grid
- LOGICAL, INTENT(IN) :: allowed_to_read
- END SUBROUTINE start_domain
- END INTERFACE
- grid%dfi_stage = DFI_FST
- ! reset time_step to normal and adaptive_time_step
- CALL nl_set_time_step( grid%id, grid%time_step )
- grid%itimestep=0
- grid%xtime=0. ! BUG: This will probably not work for all DFI options
- ! only use adaptive time stepping for forecast
- #if (EM_CORE == 1)
- if (grid%id == 1) then
- CALL nl_set_use_adaptive_time_step( 1, grid%use_adaptive_time_step )
- endif
- CALL nl_set_sst_update( grid%id, grid%sst_update)
- ! reset to normal bc
- CALL nl_set_constant_bc(grid%id, .false.)
- #endif
- CALL nl_set_feedback( grid%id, grid%feedback )
- #ifdef WRF_CHEM
- ! reset chem option to normal
- CALL nl_set_chem_opt( grid%id, grid%chem_opt)
- CALL nl_set_aer_ra_feedback (grid%id, grid%aer_ra_feedback)
- CALL nl_set_io_form_auxinput5 (grid%id, grid%io_form_auxinput5)
- CALL nl_set_io_form_auxinput7 (grid%id, grid%io_form_auxinput7)
- CALL nl_set_io_form_auxinput8 (grid%id, grid%io_form_auxinput8)
- #endif
- CALL Setup_Timekeeping (grid)
- grid%start_subtime = domain_get_start_time ( grid )
- grid%stop_subtime = domain_get_stop_time ( grid )
- CALL start_domain ( grid , .TRUE. )
- END SUBROUTINE dfi_fst_init
- SUBROUTINE dfi_write_initialized_state( grid )
- ! Driver layer
- USE module_domain, ONLY : domain, head_grid
- USE module_io_domain
- USE module_configure, ONLY : grid_config_rec_type, model_config_rec
- IMPLICIT NONE
- TYPE (domain) , POINTER :: grid
- INTEGER :: fid, ierr
- CHARACTER (LEN=80) :: wrf_error_message
- CHARACTER (LEN=80) :: rstname
- CHARACTER (LEN=132) :: message
- TYPE (grid_config_rec_type) :: config_flags
- CALL model_to_grid_config_rec ( grid%id , model_config_rec , config_flags )
- WRITE (wrf_err_message,'(A,I4)') 'Writing out initialized model state'
- CALL wrf_message(TRIM(wrf_err_message))
- WRITE (rstname,'(A,I2.2)')'wrfinput_initialized_d',grid%id
- CALL open_w_dataset ( fid, TRIM(rstname), grid, config_flags, output_input, "DATASET=INPUT", ierr )
- IF ( ierr .NE. 0 ) THEN
- WRITE( message , '("program wrf: error opening ",A," for writing")') TRIM(rstname)
- CALL WRF_ERROR_FATAL ( message )
- END IF
- CALL output_input ( fid, grid, config_flags, ierr )
- CALL close_dataset ( fid, config_flags, "DATASET=INPUT" )
- END SUBROUTINE dfi_write_initialized_state
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- ! DFI array reset group of functions
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- SUBROUTINE wrf_dfi_array_reset ( )
- USE module_domain, ONLY : domain, head_grid, set_current_grid_ptr
- IMPLICIT NONE
- INTERFACE
- RECURSIVE SUBROUTINE dfi_array_reset_recurse(grid)
- USE module_domain, ONLY : domain
- TYPE (domain), POINTER :: grid
- END SUBROUTINE dfi_array_reset_recurse
- END INTERFACE
- ! Copy filtered arrays back into state arrays in grid structure, and
- ! restore original land surface fields
- CALL dfi_array_reset_recurse(head_grid)
- CALL set_current_grid_ptr( head_grid )
- END SUBROUTINE wrf_dfi_array_reset
- SUBROUTINE dfi_array_reset( grid )
- USE module_domain, ONLY : domain
- ! USE module_configure
- ! USE module_driver_constants
- ! USE module_machine
- ! USE module_dm
- USE module_model_constants
- USE module_state_description
- IMPLICIT NONE
- INTEGER :: its, ite, jts, jte, kts, kte, &
- i, j, k
- ! Input data.
- TYPE(domain) , POINTER :: grid
- ! local
- ! real p1000mb,eps,svp1,svp2,svp3,svpt0
- real eps
- ! parameter (p1000mb = 1.e+05, eps=0.622,svp1=0.6112,svp3=29.65,svpt0=273.15)
- parameter (eps=0.622)
- REAL es,qs,pol,tx,temp,pres,rslf
- CHARACTER*80 mess
- IF ( grid%dfi_opt .EQ. DFI_NODFI ) RETURN
- ! Set dynamic variables
- ! divide by total DFI coefficient
- #if (EM_CORE == 1)
- grid%mu_2(:,:) = grid%dfi_mu(:,:) / grid%hcoeff_tot
- grid%u_2(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
- grid%v_2(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
- grid%w_2(:,:,:) = grid%dfi_w(:,:,:) / grid%hcoeff_tot
- grid%ww(:,:,:) = grid%dfi_ww(:,:,:) / grid%hcoeff_tot
- grid%t_2(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
- grid%phb(:,:,:) = grid%dfi_phb(:,:,:) / grid%hcoeff_tot
- grid%ph0(:,:,:) = grid%dfi_ph0(:,:,:) / grid%hcoeff_tot
- grid%php(:,:,:) = grid%dfi_php(:,:,:) / grid%hcoeff_tot
- grid%p(:,:,:) = grid%dfi_p(:,:,:) / grid%hcoeff_tot
- grid%ph_2(:,:,:) = grid%dfi_ph(:,:,:) / grid%hcoeff_tot
- grid%tke_2(:,:,:) = grid%dfi_tke(:,:,:) / grid%hcoeff_tot
- grid%al(:,:,:) = grid%dfi_al(:,:,:) / grid%hcoeff_tot
- grid%alt(:,:,:) = grid%dfi_alt(:,:,:) / grid%hcoeff_tot
- grid%pb(:,:,:) = grid%dfi_pb(:,:,:) / grid%hcoeff_tot
- #if ( WRF_DFI_RADAR == 1 )
- IF ( grid%dfi_radar .EQ. 0 ) then ! tgs no radar assimilation
- grid%moist(:,:,:,:) = max(0.,grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot)
- ELSE
- grid%moist(:,:,:,P_QV) = max(0.,grid%dfi_moist(:,:,:,P_QV) / grid%hcoeff_tot)
- ENDIF
- #else
- grid%moist(:,:,:,:) = max(0.,grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot)
- #endif
- grid%scalar(:,:,:,:) = max(0.,grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot)
- ! restore initial fields
- grid%SNOW (:,:) = grid%dfi_SNOW (:,:)
- grid%SNOWH (:,:) = grid%dfi_SNOWH (:,:)
- grid%SNOWC (:,:) = grid%dfi_SNOWC (:,:)
- grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
- grid%TSK (:,:) = grid%dfi_TSK (:,:)
- grid%TSLB (:,:,:) = grid%dfi_TSLB (:,:,:)
- grid%SMOIS (:,:,:) = grid%dfi_SMOIS (:,:,:)
- IF ( grid%sf_surface_physics .EQ. 3 ) then
- grid%QVG (:,:) = grid%dfi_QVG (:,:)
- grid%TSNAV (:,:) = grid%dfi_TSNAV (:,:)
- grid%SOILT1(:,:) = grid%dfi_SOILT1(:,:)
- grid%SMFR3D(:,:,:) = grid%dfi_SMFR3D (:,:,:)
- grid%KEEPFR3DFLAG(:,:,:) = grid%dfi_KEEPFR3DFLAG(:,:,:)
- ENDIF
- ! restore analized hydrometeor fileds
- #if ( WRF_DFI_RADAR == 1 )
- IF ( grid%dfi_radar .EQ. 1 ) then
- ! grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) !tgs
- grid%moist(:,:,:,P_QC) = grid%dfi_moist(:,:,:,P_QC) !tgs
- grid%moist(:,:,:,P_QR) = grid%dfi_moist(:,:,:,P_QR) !tgs
- grid%moist(:,:,:,P_QI) = grid%dfi_moist(:,:,:,P_QI) !tgs
- grid%moist(:,:,:,P_QS) = grid%dfi_moist(:,:,:,P_QS) !tgs
- grid%moist(:,:,:,P_QG) = grid%dfi_moist(:,:,:,P_QG) !tgs
- if(grid%dfi_stage .EQ. DFI_FWD) then
- !tgs change QV to restore initial RH field after the diabatic DFI
- its = grid%sp31 ; ite = grid%ep31 ;
- kts = grid%sp32 ; kte = grid%ep32 ;
- jts = grid%sp33 ; jte = grid%ep33 ;
- DO j=jts,jte
- DO i=its,ite
- do k = kts , kte
- temp = (grid%t_2(i,k,j)+t0)*( (grid%p(i,k,j)+grid%pb(i,k,j))/p1000mb )&
- ** (r_d / Cp)
- pres = grid%p(i,k,j)+grid%pb(i,k,j)
- !tgs rslf - function to compute qs from Thompson microphysics
- qs = rslf(pres, temp)
- ! if(i.eq. 178 .and. j.eq. 148 .and. k.eq.11) then
- ! print *,'temp,pres,qs-thomp',temp,pres,qs
- ! endif
- IF(grid%moist(i,k,j,P_QC) .GT. 1.e-6 .or. &
- grid%moist(i,k,j,P_QI) .GT. 1.e-6) THEN
- grid%moist (i,k,j,P_QV) = MAX(0.,grid%dfi_rh(i,k,j)*QS)
- ENDIF
- ! if(i.eq. 178 .and. j.eq. 148 .and. k.eq.11) then
- ! print *,'temp,pres,qs,grid%moist (i,k,j,P_QV)',temp,pres,qs, &
- ! grid%moist(i,k,j,P_QV)
- ! endif
- enddo
- ENDDO
- ENDDO
- endif
- ENDIF
- #endif
- #endif
- #if (NMM_CORE == 1)
- write(mess,*) ' divide by grid%hcoeff_tot: ', grid%hcoeff_tot
- call wrf_message(mess)
- if (grid%hcoeff_tot .lt. 0.0001) then
- call wrf_error_fatal("bad grid%hcoeff_tot")
- endif
- grid%pd(:,:) = grid%dfi_pd(:,:) / grid%hcoeff_tot
- grid%pint(:,:,:) = grid%dfi_pint(:,:,:) / grid%hcoeff_tot
- ! grid%dwdt(:,:,:) = grid%dfi_dwdt(:,:,:) / grid%hcoeff_tot
- grid%t(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
- grid%q(:,:,:) = grid%dfi_q(:,:,:) / grid%hcoeff_tot
- grid%q2(:,:,:) = grid%dfi_q2(:,:,:) / grid%hcoeff_tot
- grid%cwm(:,:,:) = grid%dfi_cwm(:,:,:) / grid%hcoeff_tot
- grid%u(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
- grid%v(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
- grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot
- grid%scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot
- ! restore initial fields
- grid%SNOW(:,:) = grid%dfi_SNOW(:,:)
- grid%SNOWH(:,:) = grid%dfi_SNOWH(:,:)
- ! grid%SNOWC(:,:) = grid%dfi_SNOWC(:,:)
- grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
- grid%NMM_TSK(:,:) = grid%dfi_NMM_TSK(:,:)
- ! save soil fields
- grid%STC(:,:,:) = grid%dfi_STC(:,:,:)
- grid%SMC(:,:,:) = grid%dfi_SMC(:,:,:)
- grid%SH2O(:,:,:) = grid%dfi_SH2O(:,:,:)
- #endif
- END SUBROUTINE dfi_array_reset
- SUBROUTINE optfil_driver( grid )
- USE module_domain, ONLY : domain
- USE module_utility
- ! USE module_wrf_error
- ! USE module_timing
- ! USE module_date_time
- ! USE module_configure
- USE module_state_description
- USE module_model_constants
- IMPLICIT NONE
- TYPE (domain) , POINTER :: grid
- ! Local variables
- integer :: nstep2, nstepmax, rundfi, i, rc,hr,min,sec
- integer :: yr,jday
- real :: timestep, tauc
- TYPE(WRFU_TimeInterval) :: run_interval
- CHARACTER*80 mess
- timestep=abs(grid%dt)
- run_interval = grid%stop_subtime - grid%start_subtime
- CALL WRFU_TimeGet(grid%start_subtime, YY=yr, dayofYear=jday, H=hr, M=min, S=sec, rc=rc)
- CALL WRFU_TimeGet(grid%stop_subtime, YY=yr, dayofYear=jday, H=hr, M=min, S=sec, rc=rc)
- CALL WRFU_TimeIntervalGet( run_interval, S=rundfi, rc=rc )
- rundfi = abs(rundfi)
- nstep2= ceiling((1.0 + real(rundfi)/timestep) / 2.0)
- ! nstep2 is equal to a half of timesteps per initialization period,
- ! should not exceed nstepmax
- tauc = real(grid%dfi_cutoff_seconds)
- ! Get DFI coefficient
- grid%hcoeff(:) = 0.0
- IF ( grid%dfi_nfilter < 0 .OR. grid%dfi_nfilter > 8 ) THEN
- write(mess,*) 'Invalid filter specified in namelist.'
- call wrf_message(mess)
- ELSE
- call dfcoef(nstep2-1, grid%dt, tauc, grid%dfi_nfilter, grid%hcoeff)
- END IF
- IF ( MOD(int(1.0 + real(rundfi)/timestep),2) /= 0 ) THEN
- DO i=1,nstep2-1
- grid%hcoeff(2*nstep2-i) = grid%hcoeff(i)
- END DO
- ELSE
- DO i=1,nstep2
- grid%hcoeff(2*nstep2-i+1) = grid%hcoeff(i)
- END DO
- END IF
- END SUBROUTINE optfil_driver
- SUBROUTINE dfi_clear_accumulation( grid )
- USE module_domain, ONLY : domain
- ! USE module_configure
- ! USE module_driver_constants
- ! USE module_machine
- ! USE module_dm
- ! USE module_model_constants
- USE module_state_description
- IMPLICIT NONE
- ! Input data.
- TYPE(domain) , POINTER :: grid
- #if (EM_CORE == 1)
- grid%dfi_mu(:,:) = 0.
- grid%dfi_u(:,:,:) = 0.
- grid%dfi_v(:,:,:) = 0.
- grid%dfi_w(:,:,:) = 0.
- grid%dfi_ww(:,:,:) = 0.
- grid%dfi_t(:,:,:) = 0.
- grid%dfi_phb(:,:,:) = 0.
- grid%dfi_ph0(:,:,:) = 0.
- grid%dfi_php(:,:,:) = 0.
- grid%dfi_p(:,:,:) = 0.
- grid%dfi_ph(:,:,:) = 0.
- grid%dfi_tke(:,:,:) = 0.
- grid%dfi_al(:,:,:) = 0.
- grid%dfi_alt(:,:,:) = 0.
- grid%dfi_pb(:,:,:) = 0.
- #if ( WRF_DFI_RADAR == 1 )
- IF ( grid%dfi_radar .EQ. 0 ) then
- grid%dfi_moist(:,:,:,:) = 0.
- ELSE
- grid%dfi_moist(:,:,:,P_QV) = 0.
- ENDIF
- #else
- grid%dfi_moist(:,:,:,:) = 0.
- #endif
- grid%dfi_scalar(:,:,:,:) = 0.
- #endif
- #if (NMM_CORE == 1)
- grid%dfi_pd(:,:) = 0.
- grid%dfi_pint(:,:,:) = 0.
- grid%dfi_dwdt(:,:,:) = 0.
- grid%dfi_t(:,:,:) = 0.
- grid%dfi_q(:,:,:) = 0.
- grid%dfi_q2(:,:,:) = 0.
- grid%dfi_cwm(:,:,:) = 0.
- grid%dfi_u(:,:,:) = 0.
- grid%dfi_v(:,:,:) = 0.
- grid%dfi_moist(:,:,:,:) = 0.
- grid%dfi_scalar(:,:,:,:) = 0.
- #endif
- grid%hcoeff_tot = 0.0
- END SUBROUTINE dfi_clear_accumulation
- SUBROUTINE dfi_save_arrays( grid )
- USE module_domain, ONLY : domain
- ! USE module_configure
- ! USE module_driver_constants
- ! USE module_machine
- ! USE module_dm
- USE module_model_constants
- USE module_state_description
- IMPLICIT NONE
- INTEGER :: its, ite, jts, jte, kts, kte, &
- i, j, k
- ! Input data.
- TYPE(domain) , POINTER :: grid
- ! local
- REAL es,qs,pol,tx,temp,pres,rslf
- #if (EM_CORE == 1)
- ! save surface 2-D fields
- grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
- grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
- grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
- grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
- grid%dfi_TSK(:,:) = grid%TSK(:,:)
- ! save soil fields
- grid%dfi_TSLB(:,:,:) = grid%TSLB(:,:,:)
- grid%dfi_SMOIS(:,:,:) = grid%SMOIS(:,:,:)
- ! RUC LSM only, need conditional
- IF ( grid%sf_surface_physics .EQ. 3 ) then
- grid%dfi_QVG(:,:) = grid%QVG(:,:)
- grid%dfi_SOILT1(:,:) = grid%SOILT1(:,:)
- grid%dfi_TSNAV(:,:) = grid%TSNAV(:,:)
- grid%dfi_SMFR3D(:,:,:) = grid%SMFR3D(:,:,:)
- grid%dfi_KEEPFR3DFLAG(:,:,:) = grid%KEEPFR3DFLAG(:,:,:)
- ENDIF
- #endif
- #if (NMM_CORE == 1)
- ! save surface 2-D fields
- grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
- grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
- ! grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
- grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
- grid%dfi_NMM_TSK(:,:) = grid%NMM_TSK(:,:)
- ! save soil fields
- grid%dfi_STC(:,:,:) = grid%STC(:,:,:)
- grid%dfi_SMC(:,:,:) = grid%SMC(:,:,:)
- grid%dfi_SH2O(:,:,:) = grid%SH2O(:,:,:)
- #endif
- ! save hydrometeor fields
- #if (EM_CORE == 1)
- #if ( WRF_DFI_RADAR == 1 )
- IF ( grid%dfi_radar .EQ. 1 ) then !tgs
- ! grid%dfi_moist(:,:,:,:) = grid%moist(:,:,:,:)
- grid%dfi_moist(:,:,:,P_QC) = grid%moist(:,:,:,P_QC)
- grid%dfi_moist(:,:,:,P_QR) = grid%moist(:,:,:,P_QR)
- grid%dfi_moist(:,:,:,P_QI) = grid%moist(:,:,:,P_QI)
- grid%dfi_moist(:,:,:,P_QS) = grid%moist(:,:,:,P_QS)
- grid%dfi_moist(:,:,:,P_QG) = grid%moist(:,:,:,P_QG)
- if(grid%dfi_stage .EQ. DFI_BCK) then
- ! compute initial RH field to be reintroduced after the diabatic DFI
- its = grid%sp31 ; ite = grid%ep31 ;
- kts = grid%sp32 ; kte = grid%ep32 ;
- jts = grid%sp33 ; jte = grid%ep33 ;
- DO j=jts,jte
- DO i=its,ite
- do k = kts , kte
- temp = (grid%t_2(i,k,j)+t0)*( (grid%p(i,k,j)+grid%pb(i,k,j))/p1000mb )&
- ** (r_d / Cp)
- pres = grid%p(i,k,j)+grid%pb(i,k,j)
- !tgs rslf - function to compute qs from Thompson microphysics
- qs = rslf(pres, temp)
- grid%dfi_rh (i,k,j) = MIN(1.,MAX(0.,grid%moist(i,k,j,P_QV)/qs))
- !tgs saturation check for points with water or ice clouds
- IF ((grid%moist (i,k,j,P_QC) .GT. 1.e-6 .or. &
- grid%moist (i,k,j,P_QI) .GT. 1.e-6) .and. &
- grid%dfi_rh (i,k,j) .lt. 1.) THEN
- grid%dfi_rh (i,k,j)=1.
- ENDIF
-
- end do
- END DO
- ENDDO
- endif
- ENDIF
- #endif
- #endif
- END SUBROUTINE dfi_save_arrays
- SUBROUTINE dfcoef (NSTEPS,DT,TAUC,NFILT,H)
- !
- ! calculate filter weights with selected window.
- !
- ! peter lynch and xiang-yu huang
- !
- ! ref: see hamming, r.w., 1989: digital filters,
- ! prentice-hall international. 3rd edition.
- !
- ! input: nsteps - number of timesteps
- ! forward or backward.
- ! dt - time step in seconds.
- ! tauc - cut-off period in seconds.
- ! nfilt - indicator for selected filter.
- !
- ! output: h - array(0:nsteps) with the
- ! required filter weights
- !
- !------------------------------------------------------------
-
- implicit none
- integer, intent(in) :: nsteps, nfilt
- real , intent(in) :: dt, tauc
- real, intent(out) :: h(1:nsteps+1)
-
- ! Local data
- integer :: n
- real :: pi, omegac, x, window, deltat
- real :: hh(0:nsteps)
- pi=4*ATAN(1.)
- deltat=ABS(dt)
- ! windows are defined by a call and held in hh.
- if ( nfilt .eq. -1) call debug (nsteps,h)
- IF ( NFILT .EQ. 0 ) CALL UNIFORM (NSTEPS,HH)
- IF ( NFILT .EQ. 1 ) CALL LANCZOS (NSTEPS,HH)
- IF ( NFILT .EQ. 2 ) CALL HAMMING (NSTEPS,HH)
- IF ( NFILT .EQ. 3 ) CALL BLACKMAN (NSTEPS,HH)
- IF ( NFILT .EQ. 4 ) CALL KAISER (NSTEPS,HH)
- IF ( NFILT .EQ. 5 ) CALL POTTER2 (NSTEPS,HH)
- IF ( NFILT .EQ. 6 ) CALL DOLPHWIN (NSTEPS,HH)
- IF ( NFILT .LE. 6 ) THEN ! sinc-windowed filters
- ! calculate the cutoff frequency
- OMEGAC = 2.*PI/TAUC
- DO N=0,NSTEPS
- WINDOW = HH(N)
- IF ( N .EQ. 0 ) THEN
- X = (OMEGAC*DELTAT/PI)
- ELSE
- X = SIN(N*OMEGAC*DELTAT)/(N*PI)
- END IF
- HH(N) = X*WINDOW
- END DO
- ! normalize the sums to be unity
- CALL NORMLZ(HH,NSTEPS)
- DO N=0,NSTEPS
- H(N+1) = HH(NSTEPS-N)
- END DO
- ELSE IF ( NFILT .EQ. 7 ) THEN ! dolph filter
- CALL DOLPH(DT,TAUC,NSTEPS,H)
- ELSE IF ( NFILT .EQ. 8 ) THEN ! 2nd order, 2nd type quick start filter (RHO)
- CALL RHOFIL(DT,TAUC,2,NSTEPS*2,2,H,NSTEPS)
- END IF
- RETURN
- END SUBROUTINE dfcoef
- SUBROUTINE NORMLZ(HH,NMAX)
- ! normalize the sum of hh to be unity
- implicit none
-
- integer, intent(in) :: nmax
- real , dimension(0:nmax), intent(out) :: hh
- ! local data
- real :: sumhh
- integer :: n
- SUMHH = HH(0)
- DO N=1,NMAX
- SUMHH = SUMHH + 2*HH(N)
- ENDDO
- DO N=0,NMAX
- HH(N) = HH(N)/SUMHH
- ENDDO
- RETURN
- END subroutine normlz
- subroutine debug(nsteps, ww)
- implicit none
- integer, intent(in) :: nsteps
- real , dimension(0:nsteps), intent(out) :: ww
- integer :: n
- do n=0,nsteps
- ww(n)=0
- end do
- ww(int(nsteps/2))=1
- return
- end subroutine debug
- SUBROUTINE UNIFORM(NSTEPS,WW)
- ! define uniform or rectangular window function.
- implicit none
- integer, intent(in) :: nsteps
- real , dimension(0:nsteps), intent(out) :: ww
-
- integer :: n
- DO N=0,NSTEPS
- WW(N) = 1.
- ENDDO
- RETURN
- END subroutine uniform
- SUBROUTINE LANCZOS(NSTEPS,WW)
- ! define (genaralised) lanczos window function.
- implicit none
- integer, parameter :: nmax = 1000
- integer, intent(in) :: nsteps
- real , dimension(0:nmax), intent(out) :: ww
- integer :: n
- real :: power, pi, w
- ! (for the usual lanczos window, power = 1 )
- POWER = 1
- PI=4*ATAN(1.)
- DO N=0,NSTEPS
- IF ( N .EQ. 0 ) THEN
- W = 1.0
- ELSE
- W = SIN(N*PI/(NSTEPS+1)) / ( N*PI/(NSTEPS+1))
- ENDIF
- WW(N) = W**POWER
- ENDDO
- RETURN
- END SUBROUTINE lanczos
- SUBROUTINE HAMMING(NSTEPS,WW)
- ! define (genaralised) hamming window function.
- implicit none
- integer, intent(in) :: nsteps
- real, dimension(0:nsteps) :: ww
- integer :: n
- real :: alpha, pi, w
- ! (for the usual hamming window, alpha=0.54,
- ! for the hann window, alpha=0.50).
- ALPHA=0.54
- PI=4*ATAN(1.)
- DO N=0,NSTEPS
- IF ( N .EQ. 0 ) THEN
- W = 1.0
- ELSE
- W = ALPHA + (1-ALPHA)*COS(N*PI/(NSTEPS))
- ENDIF
- WW(N) = W
- ENDDO
- RETURN
- END SUBROUTINE hamming
- SUBROUTINE BLACKMAN(NSTEPS,WW)
- ! define blackman window function.
- implicit none
- integer, intent(in) :: nsteps
- real, dimension(0:nsteps) :: ww
- integer :: n
- real :: pi, w
- PI=4*ATAN(1.)
- DO N=0,NSTEPS
- IF ( N .EQ. 0 ) THEN
- W = 1.0
- ELSE
- W = 0.42 + 0.50*COS( N*PI/(NSTEPS)) &
- + 0.08*COS(2*N*PI/(NSTEPS))
- ENDIF
- WW(N) = W
- ENDDO
- RETURN
- END SUBROUTINE blackman
- SUBROUTINE KAISER(NSTEPS,WW)
- ! define kaiser window function.
- implicit none
- real, external :: bessi0
- integer, intent(in) :: nsteps
- real, dimension(0:nsteps) :: ww
- integer :: n
- real :: alpha, xi0a, xn, as
- ALPHA = 1
- XI0A = BESSI0(ALPHA)
- DO N=0,NSTEPS
- XN = N
- AS = ALPHA*SQRT(1.-(XN/NSTEPS)**2)
- WW(N) = BESSI0(AS) / XI0A
- ENDDO
- RETURN
- END SUBROUTINE kaiser
- REAL FUNCTION BESSI0(X)
- ! from numerical recipes (press, et al.)
- implicit none
- real(8) :: Y
- real(8) :: P1 = 1.0d0
- real(8) :: P2 = 3.5156230D0
- real(8) :: P3 = 3.0899424D0
- real(8) :: P4 = 1.2067492D0
- real(8) :: P5 = 0.2659732D0
- real(8) :: P6 = 0.360768D-1
- real(8) :: P7 = 0.45813D-2
- real*8 :: Q1 = 0.39894228D0
- real*8 :: Q2 = 0.1328592D-1
- real*8 :: Q3 = 0.225319D-2
- real*8 :: Q4 = -0.157565D-2
- real*8 :: Q5 = 0.916281D-2
- real*8 :: Q6 = -0.2057706D-1
- real*8 :: Q7 = 0.2635537D-1
- real*8 :: Q8 = -0.1647633D-1
- real*8 :: Q9 = 0.392377D-2
- real :: x, ax
- IF (ABS(X).LT.3.75) THEN
- Y=(X/3.75)**2
- BESSI0=P1+Y*(P2+Y*(P3+Y*(P4+Y*(P5+Y*(P6+Y*P7)))))
- ELSE
- AX=ABS(X)
- Y=3.75/AX
- BESSI0=(EXP(AX)/SQRT(AX))*(Q1+Y*(Q2+Y*(Q3+Y*(Q4 &
- +Y*(Q5+Y*(Q6+Y*(Q7+Y*(Q8+Y*Q9))))))))
- ENDIF
- RETURN
- END FUNCTION bessi0
- SUBROUTINE POTTER2(NSTEPS,WW)
- ! define potter window function.
- ! modified to fall off over twice the range.
- implicit none
- integer, intent(in) :: nsteps
- real, dimension(0:nsteps),intent(out) :: ww
- integer :: n
- real :: ck, sum, arg
- ! local data
- real, dimension(0:3) :: d
- real :: pi
- integer :: ip
- d(0) = 0.35577019
- d(1) = 0.2436983
- d(2) = 0.07211497
- d(3) = 0.00630165
- PI=4*ATAN(1.)
- CK = 1.0
- DO N=0,NSTEPS
- IF (N.EQ.NSTEPS) CK = 0.5
- ARG = PI*FLOAT(N)/FLOAT(NSTEPS)
- !min--- modification in next statement
- ARG = ARG/2.
- !min--- end of modification
- SUM = D(0)
- DO IP=1,3
- SUM = SUM + 2.*D(IP)*COS(ARG*FLOAT(IP))
- END DO
- WW(N) = CK*SUM
- END DO
- RETURN
- END SUBROUTINE potter2
- SUBROUTINE dolphwin(m, window)
- ! calculation of dolph-chebyshev window or, for short,
- ! dolph window, using the expression in the reference:
- !
- ! antoniou, andreas, 1993: digital filters: analysis,
- ! design and applications. mcgraw-hill, inc., 689pp.
- !
- ! the dolph window is optimal in the following sense:
- ! for a given main-lobe width, the stop-band attenuation
- ! is minimal; for a given stop-band level, the main-lobe
- ! width is minimal.
- !
- ! it is possible to specify either the ripple-ratio r
- ! or the stop-band edge thetas.
- IMPLICIT NONE
- ! Arguments
- INTEGER, INTENT(IN) :: m
- REAL, DIMENSION(0:M), INTENT(OUT) :: window
- ! local data
- REAL, DIMENSION(0:2*M) :: t
- REAL, DIMENSION(0:M) :: w, time
- REAL :: pi, thetas, x0, term1, term2, rr, r, db, sum, arg
- INTEGER :: n, nm1, nt, i
- PI = 4*ATAN(1.D0)
- THETAS = 2*PI/M
- N = 2*M+1
- NM1 = N-1
- X0 = 1/COS(THETAS/2)
- TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
- TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
- RR = 0.5*(TERM1+TERM2)
- R = 1/RR
- DB = 20*LOG10(R)
- WRITE(*,'(1X,''DOLPH: M,N='',2I8)')M,N
- WRITE(*,'(1X,''DOLPH: THETAS (STOP-BAND EDGE)='',F10.3)')THETAS
- WRITE(*,'(1X,''DOLPH: R,DB='',2F10.3)')R, DB
- DO NT=0,M
- SUM = RR
- DO I=1,M
- ARG = X0*COS(I*PI/N)
- CALL CHEBY(T,NM1,ARG)
- TERM1 = T(NM1)
- TERM2 = COS(2*NT*PI*I/N)
- SUM = SUM + 2*TERM1*TERM2
- ENDDO
- W(NT) = SUM/N
- TIME(NT) = NT
- ENDDO
- ! fill up the array for return
- DO NT=0,M
- WINDOW(NT) = W(NT)
- ENDDO
- RETURN
- END SUBROUTINE dolphwin
- SUBROUTINE dolph(deltat, taus, m, window)
- ! calculation of dolph-chebyshev window or, for short,
- ! dolph window, using the expression in the reference:
- !
- ! antoniou, andreas, 1993: digital filters: analysis,
- ! design and applications. mcgraw-hill, inc., 689pp.
- !
- ! the dolph window is optimal in the following sense:
- ! for a given main-lobe width, the stop-band attenuation
- ! is minimal; for a given stop-band level, the main-lobe
- ! width is minimal.
- IMPLICIT NONE
- ! Arguments
- INTEGER, INTENT(IN) :: m
- REAL, DIMENSION(0:M), INTENT(OUT) :: window
- REAL, INTENT(IN) :: deltat, taus
- ! local data
- integer, PARAMETER :: NMAX = 5000
- REAL, dimension(0:NMAX) :: t, w, time
- real, dimension(0:2*nmax) :: w2
- INTEGER :: NPRPE=0 ! no of pe
- CHARACTER*80 :: MES
- real :: pi, thetas, x0, term1, term2, rr, r,db, sum, arg, sumw
- integer :: n, nm1, i, nt
-
- PI = 4*ATAN(1.D0)
- WRITE (mes,'(A,F8.2,A,F10.2)') 'In dolph, deltat = ',deltat,' taus = ',taus
- CALL wrf_message(TRIM(mes))
- N = 2*M+1
- NM1 = N-1
- THETAS = 2*PI*ABS(DELTAT/TAUS)
- X0 = 1/COS(THETAS/2)
- TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
- TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
- RR = 0.5*(TERM1+TERM2)
- R = 1/RR
- DB = 20*LOG10(R)
- WRITE (mes,'(A,2I8)') 'In dolph: M,N = ', M,N
- CALL wrf_message(TRIM(mes))
- WRITE (mes,'(A,F10.3)') 'In dolph: THETAS (STOP-BAND EDGE) = ', thetas
- CALL wrf_message(TRIM(mes))
- WRITE (mes,'(A,2F10.3)') 'In dolph: R,DB = ', R,DB
- CALL wrf_message(TRIM(mes))
- DO NT=0,M
- SUM = 1
- DO I=1,M
- ARG = X0*COS(I*PI/N)
- CALL CHEBY(T,NM1,ARG)
- TERM1 = T(NM1)
- TERM2 = COS(2*NT*PI*I/N)
- SUM = SUM + R*2*TERM1*TERM2
- ENDDO
- W(NT) = SUM/N
- TIME(NT) = NT
- WRITE (mes,'(A,F10.6,2x,E17.7)') 'In dolph: TIME, W = ', TIME(NT), W(NT)
- CALL wrf_message(TRIM(mes))
- ENDDO
- ! fill in the negative-time values by symmetry.
- DO NT=0,M
- W2(M+NT) = W(NT)
- W2(M-NT) = W(NT)
- ENDDO
- ! fill up the array for return
- SUMW = 0.
- DO NT=0,2*M
- SUMW = SUMW + W2(NT)
- ENDDO
- WRITE (mes,'(A,F10.4)') 'In dolph: SUM OF WEIGHTS W2 = ', sumw
- CALL wrf_message(TRIM(mes))
- DO NT=0,M
- WINDOW(NT) = W2(NT)
- ENDDO
- RETURN
- END SUBROUTINE dolph
- SUBROUTINE cheby(t, n, x)
- ! calculate all chebyshev polynomials up to order n
- ! for the argument value x.
- ! reference: numerical recipes, page 184, recurrence
- ! t_n(x) = 2xt_{n-1}(x) - t_{n-2}(x) , n>=2.
- IMPLICIT NONE
- ! Arguments
- INTEGER, INTENT(IN) :: n
- REAL, INTENT(IN) :: x
- REAL, DIMENSION(0:N) :: t
-
- integer :: nn
- T(0) = 1
- T(1) = X
- IF(N.LT.2) RETURN
- DO NN=2,N
- T(NN) = 2*X*T(NN-1) - T(NN-2)
- ENDDO
- RETURN
- END SUBROUTINE cheby
- SUBROUTINE rhofil(dt, tauc, norder, nstep, ictype, frow, nosize)
- ! RHO = recurssive high order.
- !
- ! This routine calculates and returns the
- ! Last Row, FROW, of the FILTER matrix.
- !
- ! Input Parameters:
- ! DT : Time Step in seconds
- ! TAUC : Cut-off period (hours)
- ! NORDER : Order of QS Filter
- ! NSTEP : Number of step/Size of row.
- ! ICTYPE : Initial Conditions
- ! NOSIZE : Max. side of FROW.
- !
- ! Working Fields:
- ! ACOEF : X-coefficients of filter
- ! BCOEF : Y-coefficients of filter
- ! FILTER : Filter Matrix.
- !
- ! Output Parameters:
- ! FROW : Last Row of Filter Matrix.
- !
- ! Note: Two types of initial conditions are permitted.
- ! ICTYPE = 1 : Order increasing each row to NORDER.
- ! ICTYPE = 2 : Order fixed at NORDER throughout.
- !
- ! DOUBLE PRECISION USED THROUGHOUT.
- IMPLICIT DOUBLE PRECISION (A-H,O-Z)
- DOUBLE PRECISION MUC
- ! N.B. Single Precision for List Parameters.
- REAL, intent(in) :: DT,TAUC
- ! Space for the last row of FILTER.
- integer, intent(in) :: norder, nstep, ictype, nosize
- REAL , dimension(0:nosize), intent(out):: FROW
- ! Arrays for rho filter.
- integer, PARAMETER :: NOMAX=100
- real , dimension(0:NOMAX) :: acoef, bcoef
- real , dimension(0:NOMAX,0:NOMAX) :: filter
- ! Working space.
- real , dimension(0:NOMAX) :: alpha, beta
- real :: DTT
- DTT = ABS(DT)
- PI = 2*DASIN(1.D0)
- IOTA = CMPLX(0.,1.)
- ! Filtering Parameters (derived).
- THETAC = 2*PI*DTT/(TAUC)
- MUC = tan(THETAC/2)
- FC = THETAC/(2*PI)
- ! Clear the arrays.
- DO NC=0,NOMAX
- ACOEF(NC) = 0.
- BCOEF(NC) = 0.
- ALPHA(NC) = 0.
- BETA (NC) = 0.
- FROW (NC) = 0.
- DO NR=0,NOMAX
- FILTER(NR,NC) = 0.
- ENDDO
- ENDDO
- ! Fill up the Filter Matrix.
- FILTER(0,0) = 1.
- ! Get the coefficients of the Filter.
- IF ( ICTYPE.eq.2 ) THEN
- CALL RHOCOF(NORDER,NOMAX,MUC, ACOEF,BCOEF)
- ENDIF
- DO 100 NROW=1,NSTEP
- IF ( ICTYPE.eq.1 ) THEN
- NORD = MIN(NROW,NORDER)
- IF ( NORD.le.NORDER) THEN
- CALL RHOCOF(NORD,NOMAX,MUC, ACOEF,BCOEF)
- ENDIF
- ENDIF
- DO K=0,NROW
- ALPHA(K) = ACOEF(NROW-K)
- IF(K.lt.NROW) BETA(K) = BCOEF(NROW-K)
- ENDDO
- ! Correction for terms of negative index.
- IF ( ICTYPE.eq.2 ) THEN
- IF ( NROW.lt.NORDER ) THEN
- CN = 0.
- DO NN=NROW+1,NORDER
- CN = CN + (ACOEF(NN)+BCOEF(NN))
- ENDDO
- ALPHA(0) = ALPHA(0) + CN
- ENDIF
- ENDIF
- ! Check sum of ALPHAs and BETAs = 1
- SUMAB = 0.
- DO NN=0,NROW
- SUMAB = SUMAB + ALPHA(NN)
- IF(NN.lt.NROW) SUMAB = SUMAB + BETA(NN)
- ENDDO
- DO KK=0,NROW-1
- SUMBF = 0.
- DO LL=0,NROW-1
- SUMBF = SUMBF + BETA(LL)*FILTER(LL,KK)
- ENDDO
- FILTER(NROW,KK) = ALPHA(KK)+SUMBF
- ENDDO
- FILTER(NROW,NROW) = ALPHA(NROW)
- ! Check sum of row elements = 1
- SUMROW = 0.
- DO NN=0,NROW
- SUMROW = SUMROW + FILTER(NROW,NN)
- ENDDO
- 100 CONTINUE
- DO NC=0,NSTEP
- FROW(NC) = FILTER(NSTEP,NC)
- ENDDO
- RETURN
- END SUBROUTINE rhofil
- SUBROUTINE rhocof(nord, nomax, muc, ca, cb)
- ! Get the coefficients of the RHO Filter
- ! IMPLICIT DOUBLE PRECISION (A-H,O-Z)
- IMPLICIT NONE
- ! Arguments
- integer, intent(in) :: nord, nomax
- real, dimension(0:nomax) :: ca, cb
- ! Functions
- double precision, external :: cnr
- ! Local variables
- INTEGER :: nn
- COMPLEX :: IOTA
- DOUBLE PRECISION :: MUC, ZN
- DOUBLE PRECISION :: pi, root2, rn, sigma, gain, sumcof
- PI = 2*ASIN(1.)
- ROOT2 = SQRT(2.)
- IOTA = (0.,1.)
- RN = 1./FLOAT(NORD)
- SIGMA = 1./( SQRT(2.**RN-1.) )
- GAIN = (MUC*SIGMA/(1+MUC*SIGMA))**NORD
- ZN = (1-MUC*SIGMA)/(1+MUC*SIGMA)
- DO NN=0,NORD
- CA(NN) = CNR(NORD,NN)*GAIN
- IF(NN.gt.0) CB(NN) = -CNR(NORD,NN)*(-ZN)**NN
- ENDDO
- ! Check sum of coefficients = 1
- SUMCOF = 0.
- DO NN=0,NORD
- SUMCOF = SUMCOF + CA(NN)
- IF(NN.gt.0) SUMCOF = SUMCOF + CB(NN)
- ENDDO
- RETURN
- END SUBROUTINE RHOCOF
- DOUBLE PRECISION FUNCTION cnr(n,r)
- ! Binomial Coefficient (n,r).
- ! IMPLICIT DOUBLE PRECISION(C,X)
- IMPLICIT NONE
- ! Arguments
- INTEGER , intent(in) :: n, R
- ! Local variables
- INTEGER :: k
- DOUBLE PRECISION :: coeff, xn, xr, xk
- IF ( R.eq.0 ) THEN
- CNR = 1.0
- RETURN
- ENDIF
- Coeff = 1.0
- XN = DFLOAT(N)
- XR = DFLOAT(R)
- DO K=1,R
- XK = DFLOAT(K)
- COEFF = COEFF * ( (XN-XR+XK)/XK )
- ENDDO
- CNR = COEFF
- RETURN
- END FUNCTION cnr
- SUBROUTINE optfil (grid,NH,DELTAT,NHMAX)
- !----------------------------------------------------------------------
- ! SUBROUTINE optfil (NH,DELTAT,TAUP,TAUS,LPRINT, &
- ! H,NHMAX)
- !
- ! - Huang and Lynch optimal filter
- ! Monthly Weather Review, Feb 1993
- !----------------------------------------------------------
- ! Input Parameters in List:
- ! NH : Half-length of the Filter
- ! DELTAT : Time-step (in seconds).
- ! TAUP : Period of pass-band edge (hours).
- ! TAUS : Period of stop-band edge (hours).
- ! LPRINT : Logical switch for messages.
- ! NHMAX : Maximum permitted Half-length.
- !
- ! Output Parameters in List:
- ! H : Impulse Response.
- ! DP : Deviation in pass-band (db)
- ! DS : Deviation in stop-band (db)
- !----------------------------------------------------------
- !
- USE module_domain, ONLY : domain
-
- TYPE(domain) , POINTER :: grid
- REAL,DIMENSION( 20) :: EDGE
- REAL,DIMENSION( 10) :: FX, WTX, DEVIAT
- REAL,DIMENSION(2*NHMAX+1) :: H
- logical LPRINT
- REAL, INTENT (IN) :: DELTAT
- INTEGER, INTENT (IN) :: NH, NHMAX
- !
- TAUP = 3.
- TAUS = 1.5
- LPRINT = .true.
- !initialize H array
- NL=2*NHMAX+1
- do 101 n=1,NL
- H(n)=0.
- 101 continue
- NFILT = 2*NH+1
- print *,' start optfil, NFILT=', nfilt
- !
- ! 930325 PL & XYH : the upper limit is changed from 64 to 128.
- IF(NFILT.LE.0 .OR. NFILT.GT.128 ) THEN
- WRITE(6,*) 'NH=',NH
- CALL wrf_error_fatal (' Sorry, error 1 in call to OPTFIL ')
- ENDIF
- !
- ! The following four should always be the same.
- JTYPE = 1
- NBANDS = 2
- !CC JPRINT = 0
- LGRID = 16
- !
- ! calculate transition frequencies.
- DT = ABS(DELTAT)
- FS = DT/(TAUS*3600.)
- FP = DT/(TAUP*3600.)
- IF(FS.GT.0.5) then
- ! print *,' FS too large in OPTFIL '
- CALL wrf_error_fatal (' FS too large in OPTFIL …
Large files files are truncated, but you can click here to view the full file