1 SUBROUTINE dfi_accumulate( grid )
5 USE module_driver_constants
8 USE module_model_constants
9 USE module_state_description
17 TYPE(domain) , POINTER :: grid
21 IF ( grid%dfi_opt .EQ. DFI_NODFI .OR. grid%dfi_stage .EQ. DFI_FST ) RETURN
23 hn = grid%hcoeff(grid%itimestep+1)
25 ! accumulate dynamic variables
26 grid%dfi_mu(:,:) = grid%dfi_mu(:,:) + grid%mu_2(:,:) * hn
27 grid%dfi_u(:,:,:) = grid%dfi_u(:,:,:) + grid%u_2(:,:,:) * hn
28 grid%dfi_v(:,:,:) = grid%dfi_v(:,:,:) + grid%v_2(:,:,:) * hn
29 grid%dfi_w(:,:,:) = grid%dfi_w(:,:,:) + grid%w_2(:,:,:) * hn
30 grid%dfi_ww(:,:,:) = grid%dfi_ww(:,:,:) + grid%ww(:,:,:) * hn
31 grid%dfi_t(:,:,:) = grid%dfi_t(:,:,:) + grid%t_2(:,:,:) * hn
32 grid%dfi_phb(:,:,:) = grid%dfi_phb(:,:,:) + grid%phb(:,:,:) * hn
33 grid%dfi_ph0(:,:,:) = grid%dfi_ph0(:,:,:) + grid%ph0(:,:,:) * hn
34 grid%dfi_php(:,:,:) = grid%dfi_php(:,:,:) + grid%php(:,:,:) * hn
35 grid%dfi_p(:,:,:) = grid%dfi_p(:,:,:) + grid%p(:,:,:) * hn
36 grid%dfi_ph(:,:,:) = grid%dfi_ph(:,:,:) + grid%ph_2(:,:,:) * hn
37 grid%dfi_tke(:,:,:) = grid%dfi_tke(:,:,:) + grid%tke_2(:,:,:) * hn
38 grid%dfi_al(:,:,:) = grid%dfi_al(:,:,:) + grid%al(:,:,:) * hn
39 grid%dfi_alt(:,:,:) = grid%dfi_alt(:,:,:) + grid%alt(:,:,:) * hn
40 grid%dfi_pb(:,:,:) = grid%dfi_pb(:,:,:) + grid%pb(:,:,:) * hn
41 grid%dfi_moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) + grid%moist(:,:,:,:) * hn
42 grid%dfi_scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) + grid%scalar(:,:,:,:) * hn
44 ! accumulate DFI coefficient
45 grid%hcoeff_tot = grid%hcoeff_tot + hn
48 END SUBROUTINE dfi_accumulate
52 SUBROUTINE wrf_dfi_bck_init ( )
62 SUBROUTINE Setup_Timekeeping(grid)
64 TYPE (domain), POINTER :: grid
65 END SUBROUTINE Setup_Timekeeping
67 SUBROUTINE dfi_save_arrays(grid)
69 TYPE (domain), POINTER :: grid
70 END SUBROUTINE dfi_save_arrays
72 SUBROUTINE dfi_clear_accumulation(grid)
74 TYPE (domain), POINTER :: grid
75 END SUBROUTINE dfi_clear_accumulation
77 SUBROUTINE optfil_driver(grid)
79 TYPE (domain), POINTER :: grid
80 END SUBROUTINE optfil_driver
82 SUBROUTINE start_domain(grid, allowed_to_read)
85 LOGICAL, INTENT(IN) :: allowed_to_read
86 END SUBROUTINE start_domain
89 head_grid%dfi_stage = DFI_BCK
92 CALL nl_set_time_step ( 1, -head_grid%time_step )
94 CALL Setup_Timekeeping (head_grid)
96 ! set physics options to zero
97 CALL nl_set_mp_physics( 1, 0 )
98 CALL nl_set_ra_lw_physics( 1, 0 )
99 CALL nl_set_ra_sw_physics( 1, 0 )
100 CALL nl_set_sf_surface_physics( 1, 0 )
101 CALL nl_set_sf_sfclay_physics( 1, 0 )
102 CALL nl_set_bl_pbl_physics( 1, 0 )
103 CALL nl_set_cu_physics( 1, 0 )
105 ! set diffusion to zero for backward integration
106 CALL nl_set_km_opt( 1, head_grid%km_opt_dfi)
107 CALL nl_set_pd_moist( 1, head_grid%pd_moist_dfi)
109 head_grid%start_subtime = domain_get_start_time ( head_grid )
110 head_grid%stop_subtime = domain_get_stop_time ( head_grid )
112 CALL WRFU_ClockSet(head_grid%domain_clock, currTime=head_grid%start_subtime, rc=rc)
114 CALL dfi_save_arrays ( head_grid )
115 CALL dfi_clear_accumulation( head_grid )
116 CALL optfil_driver(head_grid)
118 !tgs need to call start_domain here to reset bc initialization for negative dt
119 CALL start_domain ( head_grid , .TRUE. )
121 END SUBROUTINE wrf_dfi_bck_init
124 SUBROUTINE wrf_dfi_fwd_init ( )
134 SUBROUTINE Setup_Timekeeping(grid)
136 TYPE (domain), POINTER :: grid
137 END SUBROUTINE Setup_Timekeeping
139 SUBROUTINE dfi_save_arrays(grid)
141 TYPE (domain), POINTER :: grid
142 END SUBROUTINE dfi_save_arrays
144 SUBROUTINE dfi_clear_accumulation(grid)
146 TYPE (domain), POINTER :: grid
147 END SUBROUTINE dfi_clear_accumulation
149 SUBROUTINE optfil_driver(grid)
151 TYPE (domain), POINTER :: grid
152 END SUBROUTINE optfil_driver
154 SUBROUTINE start_domain(grid, allowed_to_read)
156 TYPE (domain) :: grid
157 LOGICAL, INTENT(IN) :: allowed_to_read
158 END SUBROUTINE start_domain
161 head_grid%dfi_stage = DFI_FWD
163 ! get the negative time step from the namelist and store
164 ! it as positive again.
165 ! for Setup_Timekeeping to use when setting the clock
166 ! note that this ignores fractional parts of time step
167 CALL nl_get_time_step( 1, head_grid%time_step )
168 head_grid%time_step = abs(head_grid%time_step)
169 CALL nl_set_time_step( 1, head_grid%time_step )
171 head_grid%itimestep=0
174 ! reset physics options to normal
175 CALL nl_set_mp_physics( 1, head_grid%mp_physics)
176 CALL nl_set_ra_lw_physics( 1, head_grid%ra_lw_physics)
177 CALL nl_set_ra_sw_physics( 1, head_grid%ra_sw_physics)
178 CALL nl_set_sf_surface_physics( 1, head_grid%sf_surface_physics)
179 CALL nl_set_sf_sfclay_physics( 1, head_grid%sf_sfclay_physics)
180 CALL nl_set_bl_pbl_physics( 1, head_grid%bl_pbl_physics)
181 CALL nl_set_cu_physics( 1, head_grid%cu_physics)
183 ! reset km_opt to norlmal
184 CALL nl_set_km_opt( 1, head_grid%km_opt)
185 CALL nl_set_pd_moist( 1, head_grid%pd_moist)
187 CALL Setup_Timekeeping (head_grid)
188 head_grid%start_subtime = domain_get_start_time ( head_grid )
189 head_grid%stop_subtime = domain_get_stop_time ( head_grid )
191 CALL WRFU_ClockSet(head_grid%domain_clock, currTime=head_grid%start_subtime, rc=rc)
193 IF ( head_grid%dfi_opt .EQ. DFI_DFL ) THEN
194 CALL dfi_save_arrays ( head_grid )
196 CALL dfi_clear_accumulation( head_grid )
197 CALL optfil_driver(head_grid)
199 !tgs need to call it here to reset bc initialization for positive time_step
200 CALL start_domain ( head_grid , .TRUE. )
202 END SUBROUTINE wrf_dfi_fwd_init
205 SUBROUTINE wrf_dfi_fst_init ( )
211 CHARACTER (LEN=80) :: wrf_error_message
214 SUBROUTINE Setup_Timekeeping(grid)
216 TYPE (domain), POINTER :: grid
217 END SUBROUTINE Setup_Timekeeping
219 SUBROUTINE dfi_save_arrays(grid)
221 TYPE (domain), POINTER :: grid
222 END SUBROUTINE dfi_save_arrays
224 SUBROUTINE dfi_clear_accumulation(grid)
226 TYPE (domain), POINTER :: grid
227 END SUBROUTINE dfi_clear_accumulation
229 SUBROUTINE optfil_driver(grid)
231 TYPE (domain), POINTER :: grid
232 END SUBROUTINE optfil_driver
234 SUBROUTINE start_domain(grid, allowed_to_read)
236 TYPE (domain) :: grid
237 LOGICAL, INTENT(IN) :: allowed_to_read
238 END SUBROUTINE start_domain
241 head_grid%dfi_stage = DFI_FST
243 head_grid%itimestep=0
244 head_grid%xtime=0. ! BUG: This will probably not work for all DFI options
246 CALL Setup_Timekeeping (head_grid)
247 head_grid%start_subtime = domain_get_start_time ( head_grid )
248 head_grid%stop_subtime = domain_get_stop_time ( head_grid )
250 CALL start_domain ( head_grid , .TRUE. )
252 END SUBROUTINE wrf_dfi_fst_init
255 SUBROUTINE wrf_dfi_write_initialized_state( )
265 CHARACTER (LEN=80) :: wrf_error_message
266 CHARACTER (LEN=80) :: rstname
267 CHARACTER (LEN=132) :: message
269 TYPE (grid_config_rec_type) :: config_flags
271 CALL model_to_grid_config_rec ( head_grid%id , model_config_rec , config_flags )
273 WRITE (wrf_err_message,'(A,I4)') 'Writing out initialized model state'
274 CALL wrf_message(TRIM(wrf_err_message))
276 rstname = 'wrfinput_initialized_d01'
277 CALL open_w_dataset ( fid, TRIM(rstname), head_grid, config_flags, output_model_input, "DATASET=INPUT", ierr )
278 IF ( ierr .NE. 0 ) THEN
279 WRITE( message , '("program wrf: error opening ",A," for writing")') TRIM(rstname)
280 CALL WRF_ERROR_FATAL ( message )
282 CALL output_model_input ( fid, head_grid, config_flags, ierr )
283 CALL close_dataset ( fid, config_flags, "DATASET=INPUT" )
285 END SUBROUTINE wrf_dfi_write_initialized_state
288 SUBROUTINE wrf_dfi_array_reset ( )
295 SUBROUTINE dfi_array_reset(grid)
297 TYPE (domain), POINTER :: grid
298 END SUBROUTINE dfi_array_reset
301 ! Copy filtered arrays back into state arrays in grid structure, and
302 ! restore original land surface fields
303 CALL dfi_array_reset( head_grid )
305 END SUBROUTINE wrf_dfi_array_reset
308 SUBROUTINE optfil_driver( grid )
315 USE module_state_description
316 USE module_model_constants
320 TYPE (domain) , POINTER :: grid
323 integer :: nstep2, nstepmax, rundfi, i, rc
324 real :: timestep, tauc
325 TYPE(WRFU_TimeInterval) :: run_interval
327 timestep=abs(grid%dt)
328 run_interval = grid%stop_subtime - grid%start_subtime
330 CALL WRFU_TimeIntervalGet( run_interval, S=rundfi, rc=rc )
333 nstep2= ceiling((1.0 + real(rundfi)/timestep) / 2.0)
335 ! nstep2 is equal to a half of timesteps per initialization period,
336 ! should not exceed nstepmax
338 tauc = real(grid%dfi_cutoff_seconds)
340 ! Get DFI coefficient
342 IF ( grid%dfi_nfilter < 0 .OR. grid%dfi_nfilter > 8 ) THEN
343 write(0,*) 'Invalid filter specified in namelist.'
345 call dfcoef(nstep2-1, grid%dt, tauc, grid%dfi_nfilter, grid%hcoeff)
348 IF ( MOD(int(1.0 + real(rundfi)/timestep),2) /= 0 ) THEN
350 grid%hcoeff(2*nstep2-i) = grid%hcoeff(i)
354 grid%hcoeff(2*nstep2-i+1) = grid%hcoeff(i)
358 END SUBROUTINE optfil_driver
361 SUBROUTINE dfi_clear_accumulation( grid )
365 USE module_driver_constants
368 USE module_model_constants
369 USE module_state_description
374 TYPE(domain) , POINTER :: grid
376 grid%dfi_mu(:,:) = 0.
377 grid%dfi_u(:,:,:) = 0.
378 grid%dfi_v(:,:,:) = 0.
379 grid%dfi_w(:,:,:) = 0.
380 grid%dfi_ww(:,:,:) = 0.
381 grid%dfi_t(:,:,:) = 0.
382 grid%dfi_phb(:,:,:) = 0.
383 grid%dfi_ph0(:,:,:) = 0.
384 grid%dfi_php(:,:,:) = 0.
385 grid%dfi_p(:,:,:) = 0.
386 grid%dfi_ph(:,:,:) = 0.
387 grid%dfi_tke(:,:,:) = 0.
388 grid%dfi_al(:,:,:) = 0.
389 grid%dfi_alt(:,:,:) = 0.
390 grid%dfi_pb(:,:,:) = 0.
391 grid%dfi_moist(:,:,:,:) = 0.
392 grid%dfi_scalar(:,:,:,:) = 0.
394 grid%hcoeff_tot = 0.0
396 END SUBROUTINE dfi_clear_accumulation
399 SUBROUTINE dfi_save_arrays( grid )
403 USE module_driver_constants
406 USE module_model_constants
407 USE module_state_description
412 TYPE(domain) , POINTER :: grid
414 ! save surface 2-D fields
415 grid%dfi_SNOW(:,:) = grid%SNOW(:,:)
416 grid%dfi_SNOWH(:,:) = grid%SNOWH(:,:)
417 grid%dfi_SNOWC(:,:) = grid%SNOWC(:,:)
418 grid%dfi_CANWAT(:,:) = grid%CANWAT(:,:)
419 grid%dfi_TSK(:,:) = grid%TSK(:,:)
420 grid%dfi_QVG(:,:) = grid%QVG(:,:)
421 grid%dfi_SOILT1(:,:) = grid%SOILT1(:,:)
422 grid%dfi_TSNAV(:,:) = grid%TSNAV(:,:)
425 grid%dfi_TSLB(:,:,:) = grid%TSLB(:,:,:)
426 grid%dfi_SMOIS(:,:,:) = grid%SMOIS(:,:,:)
427 grid%dfi_SMFR3D(:,:,:) = grid%SMFR3D(:,:,:)
428 grid%dfi_KEEPFR3DFLAG(:,:,:) = grid%KEEPFR3DFLAG(:,:,:)
430 END SUBROUTINE dfi_save_arrays
433 SUBROUTINE dfi_array_reset( grid )
437 USE module_driver_constants
440 USE module_model_constants
441 USE module_state_description
446 TYPE(domain) , POINTER :: grid
448 IF ( grid%dfi_opt .EQ. DFI_NODFI ) RETURN
451 ! Set dynamic variables
452 ! divide by total DFI coefficient
453 grid%mu_2(:,:) = grid%dfi_mu(:,:) / grid%hcoeff_tot
454 grid%u_2(:,:,:) = grid%dfi_u(:,:,:) / grid%hcoeff_tot
455 grid%v_2(:,:,:) = grid%dfi_v(:,:,:) / grid%hcoeff_tot
456 grid%w_2(:,:,:) = grid%dfi_w(:,:,:) / grid%hcoeff_tot
457 grid%ww(:,:,:) = grid%dfi_ww(:,:,:) / grid%hcoeff_tot
458 grid%t_2(:,:,:) = grid%dfi_t(:,:,:) / grid%hcoeff_tot
459 grid%phb(:,:,:) = grid%dfi_phb(:,:,:) / grid%hcoeff_tot
460 grid%ph0(:,:,:) = grid%dfi_ph0(:,:,:) / grid%hcoeff_tot
461 grid%php(:,:,:) = grid%dfi_php(:,:,:) / grid%hcoeff_tot
462 grid%p(:,:,:) = grid%dfi_p(:,:,:) / grid%hcoeff_tot
463 grid%ph_2(:,:,:) = grid%dfi_ph(:,:,:) / grid%hcoeff_tot
464 grid%tke_2(:,:,:) = grid%dfi_tke(:,:,:) / grid%hcoeff_tot
465 grid%al(:,:,:) = grid%dfi_al(:,:,:) / grid%hcoeff_tot
466 grid%alt(:,:,:) = grid%dfi_alt(:,:,:) / grid%hcoeff_tot
467 grid%pb(:,:,:) = grid%dfi_pb(:,:,:) / grid%hcoeff_tot
468 grid%moist(:,:,:,:) = grid%dfi_moist(:,:,:,:) / grid%hcoeff_tot
469 grid%scalar(:,:,:,:) = grid%dfi_scalar(:,:,:,:) / grid%hcoeff_tot
471 ! restore initial fields
472 grid%SNOW (:,:) = grid%dfi_SNOW (:,:)
473 grid%SNOWH (:,:) = grid%dfi_SNOWH (:,:)
474 grid%SNOWC (:,:) = grid%dfi_SNOWC (:,:)
475 grid%CANWAT(:,:) = grid%dfi_CANWAT(:,:)
476 grid%TSK (:,:) = grid%dfi_TSK (:,:)
477 grid%QVG (:,:) = grid%dfi_QVG (:,:)
478 grid%SOILT1(:,:) = grid%dfi_SOILT1(:,:)
479 grid%TSNAV (:,:) = grid%dfi_TSNAV (:,:)
481 grid%TSLB (:,:,:) = grid%dfi_TSLB (:,:,:)
482 grid%SMOIS (:,:,:) = grid%dfi_SMOIS (:,:,:)
483 grid%SMFR3D(:,:,:) = grid%dfi_SMFR3D (:,:,:)
484 grid%KEEPFR3DFLAG(:,:,:) = grid%dfi_KEEPFR3DFLAG(:,:,:)
486 END SUBROUTINE dfi_array_reset
489 SUBROUTINE dfcoef (NSTEPS,DT,TAUC,NFILT,H)
491 ! calculate filter weights with selected window.
493 ! peter lynch and xiang-yu huang
495 ! ref: see hamming, r.w., 1989: digital filters,
496 ! prentice-hall international. 3rd edition.
498 ! input: nsteps - number of timesteps
499 ! forward or backward.
500 ! dt - time step in seconds.
501 ! tauc - cut-off period in seconds.
502 ! nfilt - indicator for selected filter.
504 ! output: h - array(0:nsteps) with the
505 ! required filter weights
507 !------------------------------------------------------------
511 integer, intent(in) :: nsteps, nfilt
512 real , intent(in) :: dt, tauc
513 real, intent(out) :: h(1:nsteps+1)
518 real :: pi, omegac, x, window, deltat
524 ! windows are defined by a call and held in hh.
526 if ( nfilt .eq. -1) call debug (nsteps,h)
528 IF ( NFILT .EQ. 0 ) CALL UNIFORM (NSTEPS,HH)
529 IF ( NFILT .EQ. 1 ) CALL LANCZOS (NSTEPS,HH)
530 IF ( NFILT .EQ. 2 ) CALL HAMMING (NSTEPS,HH)
531 IF ( NFILT .EQ. 3 ) CALL BLACKMAN (NSTEPS,HH)
532 IF ( NFILT .EQ. 4 ) CALL KAISER (NSTEPS,HH)
533 IF ( NFILT .EQ. 5 ) CALL POTTER2 (NSTEPS,HH)
534 IF ( NFILT .EQ. 6 ) CALL DOLPHWIN (NSTEPS,HH)
536 IF ( NFILT .LE. 6 ) THEN ! sinc-windowed filters
538 ! calculate the cutoff frequency
544 X = (OMEGAC*DELTAT/PI)
546 X = SIN(N*OMEGAC*DELTAT)/(N*PI)
551 ! normalize the sums to be unity
552 CALL NORMLZ(HH,NSTEPS)
555 H(N+1) = HH(NSTEPS-N)
558 ELSE IF ( NFILT .EQ. 7 ) THEN ! dolph filter
560 CALL DOLPH(DT,TAUC,NSTEPS,H)
562 ELSE IF ( NFILT .EQ. 8 ) THEN ! 2nd order, 2nd type quick start filter (RHO)
564 CALL RHOFIL(DT,TAUC,2,NSTEPS*2,2,H,NSTEPS)
570 END SUBROUTINE dfcoef
573 SUBROUTINE NORMLZ(HH,NMAX)
575 ! normalize the sum of hh to be unity
579 integer, intent(in) :: nmax
580 real , dimension(0:nmax), intent(out) :: hh
588 SUMHH = SUMHH + 2*HH(N)
596 END subroutine normlz
599 subroutine debug(nsteps, ww)
603 integer, intent(in) :: nsteps
604 real , dimension(0:nsteps), intent(out) :: ww
618 SUBROUTINE UNIFORM(NSTEPS,WW)
620 ! define uniform or rectangular window function.
624 integer, intent(in) :: nsteps
625 real , dimension(0:nsteps), intent(out) :: ww
635 END subroutine uniform
638 SUBROUTINE LANCZOS(NSTEPS,WW)
640 ! define (genaralised) lanczos window function.
644 integer, parameter :: nmax = 1000
645 integer, intent(in) :: nsteps
646 real , dimension(0:nmax), intent(out) :: ww
650 ! (for the usual lanczos window, power = 1 )
658 W = SIN(N*PI/(NSTEPS+1)) / ( N*PI/(NSTEPS+1))
665 END SUBROUTINE lanczos
668 SUBROUTINE HAMMING(NSTEPS,WW)
670 ! define (genaralised) hamming window function.
674 integer, intent(in) :: nsteps
675 real, dimension(0:nsteps) :: ww
679 ! (for the usual hamming window, alpha=0.54,
680 ! for the hann window, alpha=0.50).
688 W = ALPHA + (1-ALPHA)*COS(N*PI/(NSTEPS))
695 END SUBROUTINE hamming
698 SUBROUTINE BLACKMAN(NSTEPS,WW)
700 ! define blackman window function.
704 integer, intent(in) :: nsteps
705 real, dimension(0:nsteps) :: ww
715 W = 0.42 + 0.50*COS( N*PI/(NSTEPS)) &
716 + 0.08*COS(2*N*PI/(NSTEPS))
723 END SUBROUTINE blackman
726 SUBROUTINE KAISER(NSTEPS,WW)
728 ! define kaiser window function.
732 real, external :: bessi0
734 integer, intent(in) :: nsteps
735 real, dimension(0:nsteps) :: ww
737 real :: alpha, xi0a, xn, as
744 AS = ALPHA*SQRT(1.-(XN/NSTEPS)**2)
745 WW(N) = BESSI0(AS) / XI0A
750 END SUBROUTINE kaiser
753 REAL FUNCTION BESSI0(X)
755 ! from numerical recipes (press, et al.)
760 real(8) :: P1 = 1.0d0
761 real(8) :: P2 = 3.5156230D0
762 real(8) :: P3 = 3.0899424D0
763 real(8) :: P4 = 1.2067492D0
764 real(8) :: P5 = 0.2659732D0
765 real(8) :: P6 = 0.360768D-1
766 real(8) :: P7 = 0.45813D-2
768 real*8 :: Q1 = 0.39894228D0
769 real*8 :: Q2 = 0.1328592D-1
770 real*8 :: Q3 = 0.225319D-2
771 real*8 :: Q4 = -0.157565D-2
772 real*8 :: Q5 = 0.916281D-2
773 real*8 :: Q6 = -0.2057706D-1
774 real*8 :: Q7 = 0.2635537D-1
775 real*8 :: Q8 = -0.1647633D-1
776 real*8 :: Q9 = 0.392377D-2
781 IF (ABS(X).LT.3.75) THEN
783 BESSI0=P1+Y*(P2+Y*(P3+Y*(P4+Y*(P5+Y*(P6+Y*P7)))))
787 BESSI0=(EXP(AX)/SQRT(AX))*(Q1+Y*(Q2+Y*(Q3+Y*(Q4 &
788 +Y*(Q5+Y*(Q6+Y*(Q7+Y*(Q8+Y*Q9))))))))
795 SUBROUTINE POTTER2(NSTEPS,WW)
797 ! define potter window function.
798 ! modified to fall off over twice the range.
802 integer, intent(in) :: nsteps
803 real, dimension(0:nsteps),intent(out) :: ww
808 real, dimension(0:3) :: d
821 IF (N.EQ.NSTEPS) CK = 0.5
822 ARG = PI*FLOAT(N)/FLOAT(NSTEPS)
823 !min--- modification in next statement
825 !min--- end of modification
828 SUM = SUM + 2.*D(IP)*COS(ARG*FLOAT(IP))
835 END SUBROUTINE potter2
838 SUBROUTINE dolphwin(m, window)
840 ! calculation of dolph-chebyshev window or, for short,
841 ! dolph window, using the expression in the reference:
843 ! antoniou, andreas, 1993: digital filters: analysis,
844 ! design and applications. mcgraw-hill, inc., 689pp.
846 ! the dolph window is optimal in the following sense:
847 ! for a given main-lobe width, the stop-band attenuation
848 ! is minimal; for a given stop-band level, the main-lobe
851 ! it is possible to specify either the ripple-ratio r
852 ! or the stop-band edge thetas.
857 INTEGER, INTENT(IN) :: m
858 REAL, DIMENSION(0:M), INTENT(OUT) :: window
861 REAL, DIMENSION(0:2*M) :: t
862 REAL, DIMENSION(0:M) :: w, time
863 REAL :: pi, thetas, x0, term1, term2, rr, r, db, sum, arg
864 INTEGER :: n, nm1, nt, i
873 TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
874 TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
875 RR = 0.5*(TERM1+TERM2)
878 WRITE(*,'(1X,''DOLPH: M,N='',2I8)')M,N
879 WRITE(*,'(1X,''DOLPH: THETAS (STOP-BAND EDGE)='',F10.3)')THETAS
880 WRITE(*,'(1X,''DOLPH: R,DB='',2F10.3)')R, DB
886 CALL CHEBY(T,NM1,ARG)
888 TERM2 = COS(2*NT*PI*I/N)
889 SUM = SUM + 2*TERM1*TERM2
895 ! fill up the array for return
902 END SUBROUTINE dolphwin
905 SUBROUTINE dolph(deltat, taus, m, window)
907 ! calculation of dolph-chebyshev window or, for short,
908 ! dolph window, using the expression in the reference:
910 ! antoniou, andreas, 1993: digital filters: analysis,
911 ! design and applications. mcgraw-hill, inc., 689pp.
913 ! the dolph window is optimal in the following sense:
914 ! for a given main-lobe width, the stop-band attenuation
915 ! is minimal; for a given stop-band level, the main-lobe
921 INTEGER, INTENT(IN) :: m
922 REAL, DIMENSION(0:M), INTENT(OUT) :: window
923 REAL, INTENT(IN) :: deltat, taus
926 integer, PARAMETER :: NMAX = 5000
927 REAL, dimension(0:NMAX) :: t, w, time
928 real, dimension(0:2*nmax) :: w2
929 INTEGER :: NPRPE=0 ! no of pe
932 real :: pi, thetas, x0, term1, term2, rr, r,db, sum, arg, sumw
933 integer :: n, nm1, i, nt
937 print *, 'in dfcoef, deltat = ', deltat, 'taus=',taus
942 THETAS = 2*PI*ABS(DELTAT/TAUS)
944 TERM1 = (X0 + SQRT(X0**2-1))**(FLOAT(N-1))
945 TERM2 = (X0 - SQRT(X0**2-1))**(FLOAT(N-1))
946 RR = 0.5*(TERM1+TERM2)
951 WRITE(*,'(1X,''DOLPH: M,N='',2I8)')M,N
952 WRITE(*,'(1X,''DOLPH: THETAS (STOP-BAND EDGE)='',F10.3)')THETAS
953 WRITE(*,'(1X,''DOLPH: R,DB='',2F10.3)')R, DB
959 CALL CHEBY(T,NM1,ARG)
961 TERM2 = COS(2*NT*PI*I/N)
962 SUM = SUM + R*2*TERM1*TERM2
966 WRITE(*,'(1X,''DOLPH: TIME, W='',F10.6,2X,E17.7)') &
969 ! fill in the negative-time values by symmetry.
975 ! fill up the array for return
980 WRITE(*,'(1X,''DOLPH: SUM OF WEIGHTS W2='',F10.4)')SUMW
991 SUBROUTINE cheby(t, n, x)
993 ! calculate all chebyshev polynomials up to order n
994 ! for the argument value x.
996 ! reference: numerical recipes, page 184, recurrence
997 ! t_n(x) = 2xt_{n-1}(x) - t_{n-2}(x) , n>=2.
1002 INTEGER, INTENT(IN) :: n
1003 REAL, INTENT(IN) :: x
1004 REAL, DIMENSION(0:N) :: t
1012 T(NN) = 2*X*T(NN-1) - T(NN-2)
1017 END SUBROUTINE cheby
1020 SUBROUTINE rhofil(dt, tauc, norder, nstep, ictype, frow, nosize)
1022 ! RHO = recurssive high order.
1024 ! This routine calculates and returns the
1025 ! Last Row, FROW, of the FILTER matrix.
1028 ! DT : Time Step in seconds
1029 ! TAUC : Cut-off period (hours)
1030 ! NORDER : Order of QS Filter
1031 ! NSTEP : Number of step/Size of row.
1032 ! ICTYPE : Initial Conditions
1033 ! NOSIZE : Max. side of FROW.
1036 ! ACOEF : X-coefficients of filter
1037 ! BCOEF : Y-coefficients of filter
1038 ! FILTER : Filter Matrix.
1040 ! Output Parameters:
1041 ! FROW : Last Row of Filter Matrix.
1043 ! Note: Two types of initial conditions are permitted.
1044 ! ICTYPE = 1 : Order increasing each row to NORDER.
1045 ! ICTYPE = 2 : Order fixed at NORDER throughout.
1047 ! DOUBLE PRECISION USED THROUGHOUT.
1049 IMPLICIT DOUBLE PRECISION (A-H,O-Z)
1051 DOUBLE PRECISION MUC
1053 ! N.B. Single Precision for List Parameters.
1054 REAL, intent(in) :: DT,TAUC
1056 ! Space for the last row of FILTER.
1057 integer, intent(in) :: norder, nstep, ictype, nosize
1058 REAL , dimension(0:nosize), intent(out):: FROW
1060 ! Arrays for rho filter.
1061 integer, PARAMETER :: NOMAX=100
1062 real , dimension(0:NOMAX) :: acoef, bcoef
1063 real , dimension(0:NOMAX,0:NOMAX) :: filter
1065 real , dimension(0:NOMAX) :: alpha, beta
1073 ! Filtering Parameters (derived).
1074 THETAC = 2*PI*DTT/(TAUC)
1090 ! Fill up the Filter Matrix.
1093 ! Get the coefficients of the Filter.
1094 IF ( ICTYPE.eq.2 ) THEN
1095 CALL RHOCOF(NORDER,NOMAX,MUC, ACOEF,BCOEF)
1100 IF ( ICTYPE.eq.1 ) THEN
1101 NORD = MIN(NROW,NORDER)
1102 IF ( NORD.le.NORDER) THEN
1103 CALL RHOCOF(NORD,NOMAX,MUC, ACOEF,BCOEF)
1108 ALPHA(K) = ACOEF(NROW-K)
1109 IF(K.lt.NROW) BETA(K) = BCOEF(NROW-K)
1112 ! Correction for terms of negative index.
1113 IF ( ICTYPE.eq.2 ) THEN
1114 IF ( NROW.lt.NORDER ) THEN
1117 CN = CN + (ACOEF(NN)+BCOEF(NN))
1119 ALPHA(0) = ALPHA(0) + CN
1123 ! Check sum of ALPHAs and BETAs = 1
1126 SUMAB = SUMAB + ALPHA(NN)
1127 IF(NN.lt.NROW) SUMAB = SUMAB + BETA(NN)
1133 SUMBF = SUMBF + BETA(LL)*FILTER(LL,KK)
1135 FILTER(NROW,KK) = ALPHA(KK)+SUMBF
1137 FILTER(NROW,NROW) = ALPHA(NROW)
1139 ! Check sum of row elements = 1
1142 SUMROW = SUMROW + FILTER(NROW,NN)
1148 FROW(NC) = FILTER(NSTEP,NC)
1153 END SUBROUTINE rhofil
1156 SUBROUTINE rhocof(nord, nomax, muc, ca, cb)
1158 ! Get the coefficients of the RHO Filter
1160 ! IMPLICIT DOUBLE PRECISION (A-H,O-Z)
1164 integer, intent(in) :: nord, nomax
1165 real, dimension(0:nomax) :: ca, cb
1168 double precision, external :: cnr
1173 DOUBLE PRECISION :: MUC, ZN
1174 DOUBLE PRECISION :: pi, root2, rn, sigma, gain, sumcof
1181 SIGMA = 1./( SQRT(2.**RN-1.) )
1183 GAIN = (MUC*SIGMA/(1+MUC*SIGMA))**NORD
1184 ZN = (1-MUC*SIGMA)/(1+MUC*SIGMA)
1187 CA(NN) = CNR(NORD,NN)*GAIN
1188 IF(NN.gt.0) CB(NN) = -CNR(NORD,NN)*(-ZN)**NN
1191 ! Check sum of coefficients = 1
1194 SUMCOF = SUMCOF + CA(NN)
1195 IF(NN.gt.0) SUMCOF = SUMCOF + CB(NN)
1200 END SUBROUTINE RHOCOF
1203 DOUBLE PRECISION FUNCTION cnr(n,r)
1205 ! Binomial Coefficient (n,r).
1207 ! IMPLICIT DOUBLE PRECISION(C,X)
1211 INTEGER , intent(in) :: n, R
1215 DOUBLE PRECISION :: coeff, xn, xr, xk
1226 COEFF = COEFF * ( (XN-XR+XK)/XK )
1235 SUBROUTINE optfil (grid,NH,DELTAT,NHMAX)
1236 !----------------------------------------------------------------------
1238 ! SUBROUTINE optfil (NH,DELTAT,TAUP,TAUS,LPRINT, &
1241 ! - Huang and Lynch optimal filter
1242 ! Monthly Weather Review, Feb 1993
1243 !----------------------------------------------------------
1244 ! Input Parameters in List:
1245 ! NH : Half-length of the Filter
1246 ! DELTAT : Time-step (in seconds).
1247 ! TAUP : Period of pass-band edge (hours).
1248 ! TAUS : Period of stop-band edge (hours).
1249 ! LPRINT : Logical switch for messages.
1250 ! NHMAX : Maximum permitted Half-length.
1252 ! Output Parameters in List:
1253 ! H : Impulse Response.
1254 ! DP : Deviation in pass-band (db)
1255 ! DS : Deviation in stop-band (db)
1256 !----------------------------------------------------------
1260 TYPE(domain) , POINTER :: grid
1262 REAL,DIMENSION( 20) :: EDGE
1263 REAL,DIMENSION( 10) :: FX, WTX, DEVIAT
1264 REAL,DIMENSION(2*NHMAX+1) :: H
1266 REAL, INTENT (IN) :: DELTAT
1267 INTEGER, INTENT (IN) :: NH, NHMAX
1280 print *,' start optfil, NFILT=', nfilt
1283 ! 930325 PL & XYH : the upper limit is changed from 64 to 128.
1284 IF(NFILT.LE.0 .OR. NFILT.GT.128 ) THEN
1286 CALL wrf_error_fatal (' Sorry, error 1 in call to OPTFIL ')
1289 ! The following four should always be the same.
1295 ! calculate transition frequencies.
1297 FS = DT/(TAUS*3600.)
1298 FP = DT/(TAUP*3600.)
1300 ! print *,' FS too large in OPTFIL '
1301 CALL wrf_error_fatal (' FS too large in OPTFIL ')
1305 ! print *, ' FP too small in OPTFIL '
1306 CALL wrf_error_fatal (' FP too small in OPTFIL ')
1310 ! Relative Weights in pass- and stop-bands.
1314 !CC NOTE: (FP,FC,FS) is an arithmetic progression, so
1315 !CC (1/FS,1/FC,1/FP) is a harmonic one.
1316 !CC TAUP = 1/( (1/TAUC)-(1/DTAU) )
1317 !CC TAUS = 1/( (1/TAUC)+(1/DTAU) )
1318 !CC TAUC : Cut-off Period (hours).
1319 !CC DTAU : Transition half-width (hours).
1320 !CC FC = 1/TAUC ; DF = 1/DTAU
1321 !CC FP = FC - DF : FS = FC + DF
1324 TAUC = 2./((1/TAUS)+(1/TAUP))
1325 DTAU = 2./((1/TAUS)-(1/TAUP))
1326 FC = DT/(TAUC*3600.)
1327 DF = DT/(DTAU*3600.)
1328 WRITE(6,*) ' DT ' , dt
1329 WRITE(6,*) ' TAUS, TAUP ' , TAUS,TAUP
1330 WRITE(6,*) ' TAUC, DTAU ' , TAUC,DTAU
1331 WRITE(6,*) ' FP, FS ' , FP, FS
1332 WRITE(6,*) ' FC, DF ' , FC, DF
1333 WRITE(6,*) ' WTS, WTP ' , WTS, WTP
1336 ! Fill the control vectors for MCCPAR
1346 CALL MCCPAR(NFILT,JTYPE,NBANDS,LPRINT,LGRID, &
1347 EDGE,FX,WTX,DEVIAT, h )
1349 ! Save the deviations in the pass- and stop-bands.
1353 ! Fill out the array H (only first half filled in MCCPAR).
1354 IF(MOD(NFILT,2).EQ.0) THEN
1360 H(NFILT+1-nn) = h(nn)
1363 ! normalize the sums to be unity
1368 print *,'SUMH =', sumh
1376 ! print *,'HCOEFF(n) ', grid%hcoeff
1378 END SUBROUTINE optfil
1381 SUBROUTINE MCCPAR (NFILT,JTYPE,NBANDS,LPRINT,LGRID, &
1382 EDGE,FX,WTX,DEVIAT,h )
1384 ! PROGRAM FOR THE DESIGN OF LINEAR PHASE FINITE IMPULSE
1385 ! REPONSE (FIR) FILTERS USING THE REMEZ EXCHANGE ALGORITHM
1387 !************************************************************
1388 !* Reference: McClellan, J.H., T.W. Parks and L.R.Rabiner, *
1389 !* 1973: A computer program for designing *
1390 !* optimum FIR linear phase digital filters. *
1391 !* IEEE Trans. on Audio and Electroacoustics, *
1392 !* Vol AU-21, No. 6, 506-526. *
1393 !************************************************************
1395 ! THREE TYPES OF FILTERS ARE INCLUDED -- BANDPASS FILTERS
1396 ! DIFFERENTIATORS, AND HILBERT TRANSFORM FILTERS
1398 !---------------------------------------------------------------
1400 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
1401 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
1403 DIMENSION DES(1045),GRID(1045),WT(1045)
1404 DIMENSION EDGE(20),FX(10),WTX(10),DEVIAT(10)
1405 DOUBLE PRECISION PI2,PI
1406 DOUBLE PRECISION AD,DEV,X,Y
1409 PI = 3.141592653589793
1410 PI2 = 6.283185307179586
1417 ! PROGRAM INPUT SECTION
1419 !CC READ(5,*) NFILT,JTYPE,NBANDS,JPRINT,LGRID
1421 IF(NFILT.GT.NFMAX.OR.NFILT.LT.3) THEN
1422 CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
1424 IF(NBANDS.LE.0) NBANDS = 1
1428 IF(LGRID.LE.0) LGRID = 16
1430 !cc READ(5,*) (EDGE(J),J=1,JB)
1431 !cc READ(5,*) (FX(J),J=1,NBANDS)
1432 !cc READ(5,*) (WTX(J),J=1,NBANDS)
1434 CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
1437 IF(JTYPE.EQ.1) NEG = 0
1441 IF(NODD.EQ.1.AND.NEG.EQ.0) NFCNS = NFCNS+1
1448 IF(NEG.EQ.0) GOTO 135
1449 IF(EDGE(1).LT.DELF) GRID(1) = DELF
1459 DES(J) = EFF(TEMP,FX,WTX,LBAND,JTYPE)
1460 WT(J) = WATE(TEMP,FX,WTX,LBAND,JTYPE)
1463 IF(GRID(J).GT.FUP) GOTO 150
1466 DES(J-1) = EFF(FUP,FX,WTX,LBAND,JTYPE)
1467 WT(J-1) = WATE(FUP,FX,WTX,LBAND,JTYPE)
1470 IF(LBAND.GT.NBANDS) GOTO 160
1474 IF(NEG.NE.NODD) GOTO 165
1475 IF(GRID(NGRID).GT.(0.5-DELF)) NGRID = NGRID-1
1481 170 IF(NODD.EQ.1) GOTO 200
1483 CHANGE = DCOS(PI*GRID(J))
1484 DES(J) = DES(J)/CHANGE
1485 WT(J) = WT(J)*CHANGE
1488 180 IF(NODD.EQ.1) GOTO 190
1490 CHANGE = DSIN(PI*GRID(J))
1491 DES(J) = DES(J)/CHANGE
1492 WT(J) = WT(J)*CHANGE
1495 190 DO 195 J =1,NGRID
1496 CHANGE = DSIN(PI2*GRID(J))
1497 DES(J) = DES(J)/CHANGE
1498 WT(J) = WT(J)*CHANGE
1503 200 TEMP = FLOAT(NGRID-1)/FLOAT(NFCNS)
1505 IEXT(J) = (J-1)*TEMP+1
1507 IEXT(NFCNS+1) = NGRID
1511 ! CALL THE REMEZ EXCHANGE ALGORITHM TO DO THE APPROXIMATION PROBLEM
1513 CALL REMEZ(EDGE,NBANDS,PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID)
1515 ! CALCULATE THE IMPULSE RESPONSE
1518 300 IF(NODD.EQ.0) GOTO 310
1520 H(J) = 0.5*ALPHA(NZ-J)
1524 310 H(1) = 0.25*ALPHA(NFCNS)
1526 H(J) = 0.25*(ALPHA(NZ-J)+ALPHA(NFCNS+2-J))
1528 H(NFCNS) = 0.5*ALPHA(1)+0.25*ALPHA(2)
1530 320 IF(NODD.EQ.0) GOTO 330
1531 H(1) = 0.25*ALPHA(NFCNS)
1532 H(2) = 0.25*ALPHA(NM1)
1534 H(J) = 0.25*(ALPHA(NZ-J)-ALPHA(NFCNS+3-J))
1536 H(NFCNS) = 0.5*ALPHA(1)-0.25*ALPHA(3)
1539 330 H(1) = 0.25*ALPHA(NFCNS)
1541 H(J) = 0.25*(ALPHA(NZ-J)-ALPHA(NFCNS+2-J))
1543 H(NFCNS) = 0.5*ALPHA(1)-0.25*ALPHA(2)
1545 ! PROGRAM OUTPUT SECTION
1551 print *, '****************************************************'
1552 print *, 'FINITE IMPULSE RESPONSE (FIR)'
1553 print *, 'LINEAR PHASE DIGITAL FILTER DESIGN'
1554 print *, 'REMEZ EXCHANGE ALGORITHM'
1556 IF(JTYPE.EQ.1) WRITE(6,365)
1557 365 FORMAT(25X,'BANDPASS FILTER'/)
1559 IF(JTYPE.EQ.2) WRITE(6,370)
1560 370 FORMAT(25X,'DIFFERENTIATOR '/)
1562 IF(JTYPE.EQ.3) WRITE(6,375)
1563 375 FORMAT(25X,'HILBERT TRANSFORMER '/)
1566 378 FORMAT(15X,'FILTER LENGTH =',I3/)
1569 380 FORMAT(15X,'***** IMPULSE RESPONSE *****')
1573 IF(NEG.EQ.0) WRITE(6,382) J,H(J),K
1574 IF(NEG.EQ.1) WRITE(6,383) J,H(J),K
1576 382 FORMAT(20X,'H(',I3,') = ',E15.8,' = H(',I4,')')
1577 383 FORMAT(20X,'H(',I3,') = ',E15.8,' = -H(',I4,')')
1579 IF(NEG.EQ.1.AND.NODD.EQ.1) WRITE(6,384) NZ
1580 384 FORMAT(20X,'H(',I3,') = 0.0')
1584 IF(KUP.GT.NBANDS) KUP = NBANDS
1586 WRITE(6,385) (J,J=K,KUP)
1587 385 FORMAT(24X,4('BAND',I3,8X))
1588 WRITE(6,390) (EDGE(2*J-1),J=K,KUP)
1589 390 FORMAT(2X,'LOWER BAND EDGE',5F15.8)
1590 WRITE(6,395) (EDGE(2*J),J=K,KUP)
1591 395 FORMAT(2X,'UPPER BAND EDGE',5F15.8)
1592 IF(JTYPE.NE.2) WRITE(6,400) (FX(J),J=K,KUP)
1593 400 FORMAT(2X,'DESIRED VALUE',2X,5F15.8)
1594 IF(JTYPE.EQ.2) WRITE(6,405) (FX(J),J=K,KUP)
1595 405 FORMAT(2X,'DESIRED SLOPE',2X,5F15.8)
1596 WRITE(6,410) (WTX(J),J=K,KUP)
1597 410 FORMAT(2X,'WEIGHTING',6X,5F15.8)
1599 DEVIAT(J) = DEV/WTX(J)
1601 WRITE(6,425) (DEVIAT(J),J=K,KUP)
1602 425 FORMAT(2X,'DEVIATION',6X,5F15.8)
1603 IF(JTYPE.NE.1) GOTO 450
1605 DEVIAT(J) = 20.0*ALOG10(DEVIAT(J))
1607 WRITE(6,435) (DEVIAT(J),J=K,KUP)
1608 435 FORMAT(2X,'DEVIATION IN DB',5F15.8)
1610 print *, 'EXTREMAL FREQUENCIES'
1611 WRITE(6,455) (GRID(IEXT(J)),J=1,NZ)
1612 455 FORMAT((2X,5F15.7))
1614 460 FORMAT(1X,70(1H*))
1618 !CC IF(NFILT.NE.0) GOTO 100 ! removal of re-run loop.
1620 END SUBROUTINE mccpar
1623 FUNCTION EFF(TEMP,FX,WTX,LBAND,JTYPE)
1624 DIMENSION FX(5),WTX(5)
1625 IF(JTYPE.EQ.2) GOTO 1
1628 1 EFF = FX(LBAND)*TEMP
1632 FUNCTION WATE(TEMP,FX,WTX,LBAND,JTYPE)
1633 DIMENSION FX(5),WTX(5)
1634 IF(JTYPE.EQ.2) GOTO 1
1637 1 IF(FX(LBAND).LT.0.0001) GOTO 2
1638 WATE = WTX(LBAND)/TEMP
1645 !! WRITE(6,*)' **** ERROR IN INPUT DATA ****'
1646 ! CALL wrf_error_fatal (' **** ERROR IN INPUT DATA ****' )
1647 ! END SUBROUTINE error
1650 SUBROUTINE REMEZ(EDGE,NBANDS,PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID)
1651 ! THIS SUBROUTINE IMPLEMENTS THE REMEZ EXCHANGE ALGORITHM
1652 ! FOR THE WEIGHTED CHEBCHEV APPROXIMATION OF A CONTINUOUS
1653 ! FUNCTION WITH A SUM OF COSINES. INPUTS TO THE SUBROUTINE
1654 ! ARE A DENSE GRID WHICH REPLACES THE FREQUENCY AXIS, THE
1655 ! DESIRED FUNCTION ON THIS GRID, THE WEIGHT FUNCTION ON THE
1656 ! GRID, THE NUMBER OF COSINES, AND THE INITIAL GUESS OF THE
1657 ! EXTREMAL FREQUENCIES. THE PROGRAM MINIMIZES THE CHEBYSHEV
1658 ! ERROR BY DETERMINING THE BEST LOCATION OF THE EXTREMAL
1659 ! FREQUENCIES (POINTS OF MAXIMUM ERROR) AND THEN CALCULATES
1660 ! THE COEFFICIENTS OF THE BEST APPROXIMATION.
1662 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
1664 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
1665 DIMENSION DES(1045),GRID(1045),WT(1045)
1666 DIMENSION A(66),P(65),Q(65)
1667 DOUBLE PRECISION PI2,DNUM,DDEN,DTEMP,A,P,Q
1668 DOUBLE PRECISION AD,DEV,X,Y
1669 DOUBLE PRECISION, EXTERNAL :: D, GEE
1671 ! THE PROGRAM ALLOWS A MAXIMUM NUMBER OF ITERATIONS OF 25
1681 IF(NITER.GT.ITRMAX) GO TO 400
1684 DTEMP=DCOS(DTEMP*PI2)
1688 120 AD(J)=D(J,NZ,JET,X)
1701 IF(DEV.GT.0.0) NU=-1
1709 IF(DEV.GE.DEVL) GO TO 150
1710 WRITE(6,*) ' ******** FAILURE TO CONVERGE *********** '
1711 WRITE(6,*) ' PROBABLE CAUSE IS MACHINE ROUNDING ERROR '
1712 WRITE(6,*) ' THE IMPULSE RESPONSE MAY BE CORRECT '
1713 WRITE(6,*) ' CHECK WITH A FREQUENCY RESPONSE '
1714 WRITE(6,*) ' **************************************** '
1724 ! SEARCH FOR THE EXTERMAL FREQUENCIES OF THE BEST
1727 200 IF(J.EQ.NZZ) YNZ=COMP
1728 IF(J.GE.NZZ) GO TO 300
1734 IF(L.GE.KUP) GO TO 220
1735 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1736 ERR=(ERR-DES(L))*WT(L)
1738 IF(DTEMP.LE.0.0) GO TO 220
1741 IF(L.GE.KUP) GO TO 215
1742 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1743 ERR=(ERR-DES(L))*WT(L)
1745 IF(DTEMP.LE.0.0) GO TO 215
1755 IF(L.LE.KLOW) GO TO 250
1756 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1757 ERR=(ERR-DES(L))*WT(L)
1759 IF(DTEMP.GT.0.0) GO TO 230
1760 IF(JCHNGE.LE.0) GO TO 225
1764 IF(L.LE.KLOW) GO TO 240
1765 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1766 ERR=(ERR-DES(L))*WT(L)
1768 IF(DTEMP.LE.0.0) GO TO 240
1777 IF(JCHNGE.GT.0) GO TO 215
1779 IF(L.GE.KUP) GO TO 260
1780 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1781 ERR=(ERR-DES(L))*WT(L)
1783 IF(DTEMP.LE.0.0) GO TO 255
1789 300 IF(J.GT.NZZ) GO TO 320
1790 IF(K1.GT.IEXT(1)) K1=IEXT(1)
1791 IF(KNZ.LT.IEXT(NZ)) KNZ=IEXT(NZ)
1799 IF(L.GE.KUP) GO TO 315
1800 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1801 ERR=(ERR-DES(L))*WT(L)
1803 IF(DTEMP.LE.0.0) GO TO 310
1809 320 IF(LUCK.GT.9) GO TO 350
1810 IF(COMP.GT.Y1) Y1=COMP
1817 IF(L.LE.KLOW) GO TO 340
1818 ERR=GEE(L,NZ,GRID,PI2,X,Y,AD)
1819 ERR=(ERR-DES(L))*WT(L)
1821 IF(DTEMP.LE.0.0) GO TO 330
1826 340 IF(LUCK.EQ.6) GO TO 370
1828 345 IEXT(NZZ-J)=IEXT(NZ-J)
1833 360 IEXT(J)=IEXT(J+1)
1836 370 IF(JCHNGE.GT.0) GO TO 100
1838 ! CALCULATION OF THE COEFFICIENTS OF THE BEST APPROXIMATION
1839 ! USING THE INVERSE DISCRETE FOURIER TRANSFORM.
1850 IF(EDGE(1).EQ.0.0.AND.EDGE(2*NBANDS).EQ.0.5) KKK=1
1851 IF(NFCNS.LE.3) KKK=1
1852 IF(KKK.EQ.1) GO TO 405
1853 DTEMP=DCOS(PI2*GRID(1))
1854 DNUM=DCOS(PI2*GRID(NGRID))
1856 BB=-(DTEMP+DNUM)/(DTEMP-DNUM)
1861 IF(KKK.EQ.1) GO TO 410
1863 ! original : FT=ARCOS(XT)/PI2
1866 IF(XT.GT.XE) GO TO 420
1867 IF((XE-XT).LT.FSH) GO TO 415
1872 420 IF((XT-XE).LT.FSH) GO TO 415
1874 A(J)=GEE(1,NZ,GRID,PI2,X,Y,AD)
1883 IF(NM1.LT.1) GO TO 505
1885 500 DTEMP=DTEMP+A(K+1)*DCOS(DNUM*K)
1886 505 DTEMP=2.0*DTEMP+A(1)
1889 550 ALPHA(J)=2*ALPHA(J)/CN
1890 ALPHA(1)=ALPHA(1)/CN
1891 IF(KKK.EQ.1) GO TO 545
1892 P(1)=2.0*ALPHA(NFCNS)*BB+ALPHA(NM1)
1893 P(2)=2.0*AA*ALPHA(NFCNS)
1894 Q(1)=ALPHA(NFCNS-2)-ALPHA(NFCNS)
1896 IF(J.LT.NM1) GO TO 515
1903 520 P(K)=2.0*BB*A(K)
1904 P(2)=P(2)+A(1)*2.0*AA
1907 525 P(K)=P(K)+Q(K)+AA*A(K+1)
1910 530 P(K)=P(K)+AA*A(K-1)
1911 IF(J.EQ.NM1) GO TO 540
1914 Q(1)=Q(1)+ALPHA(NFCNS-1-J)
1919 IF(NFCNS.GT.3) RETURN
1922 END SUBROUTINE remez
1924 DOUBLE PRECISION FUNCTION D(K,N,M,X)
1925 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
1926 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
1927 DIMENSION DES(1045),GRID(1045),WT(1045)
1928 DOUBLE PRECISION AD,DEV,X,Y
1930 DOUBLE PRECISION PI2
1936 1 D = 2.0*D*(Q-X(J))
1943 DOUBLE PRECISION FUNCTION GEE(K,N,GRID,PI2,X,Y,AD)
1944 ! COMMON /x3x/ PI2,AD,DEV,X,Y,GRID,DES,WT,ALPHA,IEXT,NFCNS,NGRID
1945 DIMENSION IEXT(66),AD(66),ALPHA(66),X(66),Y(66)
1946 DIMENSION DES(1045),GRID(1045),WT(1045)
1947 DOUBLE PRECISION AD,DEV,X,Y
1948 DOUBLE PRECISION P,C,D,XF
1949 DOUBLE PRECISION PI2