Note
Function that returns an apodized array.
To prevent gaps from appearing after FFT (because of non periodic waves), the surface must
be transformed, but not too much. Here a modified Tukey window is determined. The starting
surface is not modified below the “correlation lengths”. Above the correlation lengths, a
smooth decrease is forced with a cosine squared.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
real(kind=R8), | intent(in), | dimension(1:long, 1:larg) | :: | tab_in |
input acf |
|
real(kind=R8), | intent(out), | dimension(1:long, 1:larg) | :: | tab_out |
apodized acf |
|
integer(kind=I4), | intent(in) | :: | long |
surface acf length |
||
integer(kind=I4), | intent(in) | :: | larg |
surface acf width |
||
real(kind=R8), | intent(in) | :: | tau1 |
surface first correlation length |
||
real(kind=R8), | intent(in) | :: | tau2 |
surface second correlation length |
||
real(kind=R8), | intent(in) | :: | ang |
ellipsis angle |
subroutine apod2(tab_in, tab_out, long, larg, tau1, tau2, ang) !================================================================================================ !<@note Function that returns an apodized array.<br/> !< To prevent gaps from appearing after FFT (because of non periodic waves), the surface must !< be transformed, but not too much. Here a modified Tukey window is determined. The starting !< surface is not modified below the "correlation lengths". Above the correlation lengths, a !< smooth decrease is forced with a cosine squared. !<@endnote !------------------------------------------------------------------------------------------------ implicit none integer(kind=I4), intent(in ) :: long !! *surface acf length* integer(kind=I4), intent(in ) :: larg !! *surface acf width* real (kind=R8), intent(in ) :: tau1 !! *surface first correlation length* real (kind=R8), intent(in ) :: tau2 !! *surface second correlation length* real (kind=R8), intent(in ) :: ang !! *ellipsis angle* real (kind=R8), intent(in ), dimension(1:long, 1:larg) :: tab_in !! *input acf* real (kind=R8), intent(out), dimension(1:long, 1:larg) :: tab_out !! *apodized acf* real (kind=R8) :: r2, c0, s0, rd, rr, theta, theta_diag, x, y, t, a_min, sum_inn, sum_tab, sum_int integer(kind=I4) :: i, j, k, long2, larg2, npt_out, n real(kind=R8), allocatable, dimension(:,:) :: tab_tmp ! first bissector angle (rad) theta_diag = atan2( PARAM%surf_height, PARAM%surf_width ) ! sine and cosine of the ellipsis angle c0 = cos(ang) ; s0 = sin(ang) long2 = long / 2 larg2 = larg / 2 if ( long == 2 * (long/2) ) long2 = long/2 + 1 if ( larg == 2 * (larg/2) ) larg2 = larg/2 + 1 tab_out(1:long, 1:larg) = tab_in(1:long, 1:larg) rr = 1.e6_R8 do j = 1, larg do i = 1, long x = ( i - long2 ) * PARAM%surf_dx y = ( j - larg2 ) * PARAM%surf_dy ! Distance as expressed in the theoretical acf. When r2 is 1., the acf is 0.2. r2 = ( (+ c0 * x + s0 * y) / tau1 ) ** 2 + & ! ( (- s0 * x + c0 * y) / tau2 ) ** 2 ! Below the correlation length, no transformation if ( r2 <= 1._R8 ) cycle ! The correlation length is exceeded. ! The angle corresponding to the position (i,j) is calculated theta = atan2( y, x ) ; if ( theta < 0. ) theta = theta + 2 * Pi_R8 t = tan(theta) ! According the location of (i,j) (right, top, left or bottom) the line that begin at the surface center, passing by (i,j), ! ends on one of the four borders. if ( theta > 2 * Pi_R8 - theta_diag .or. theta <= + theta_diag ) then ; x = ( long - long2 ) * PARAM%surf_dx ; y = x * t ; endif if ( theta > + theta_diag .and. theta <= PI_R8 - theta_diag ) then ; y = ( larg - larg2 ) * PARAM%surf_dy ; x = y / t ; endif if ( theta > PI_R8 - theta_diag .and. theta <= PI_R8 + theta_diag ) then ; x = ( 1 - long2 ) * PARAM%surf_dx ; y = x * t ; endif if ( theta > PI_R8 + theta_diag .and. theta <= 2 * Pi_R8 - theta_diag ) then ; y = ( 1 - larg2 ) * PARAM%surf_dy ; x = y / t ; endif ! The same distance as above is calculated, from the center to the surface edge, then ... rd = ( (+ c0 * x + s0 * y) / tau1 ) ** 2 + & ! ( (- s0 * x + c0 * y) / tau2 ) ** 2 rr = min( rr, sqrt(rd) ) enddo enddo rr = 0.99 * rr sum_inn = 0 sum_tab = 0 sum_int = 0 npt_out = 0 n = 2 do j = 1, larg do i = 1, long x = ( i - long2 ) * PARAM%surf_dx y = ( j - larg2 ) * PARAM%surf_dy ! Distance as expressed in the theoretical acf. When r2 is 1., the acf is 0.2. r2 = ( (+ c0 * x + s0 * y) / tau1 ) ** 2 + & ! ( (- s0 * x + c0 * y) / tau2 ) ** 2 ! Below the correlation length, no transformation if ( r2 <= 1._R8 ) then sum_inn = sum_inn + tab_in(i, j) cycle endif r2 = sqrt(r2) if ( r2 >= rr ) then npt_out = npt_out + 1 cycle endif ! ... the modified Tuckey window can be determined. sum_tab = sum_tab + ( cos( 0.5_R8 * PI_R8 * ( r2 - 1. ) / ( rr - 1. ) ) ** n ) * tab_in(i, j) sum_int = sum_int + ( r2 - 1. ) / ( rr - 1. ) enddo enddo a_min = -( sum_inn + sum_tab ) / ( npt_out + sum_int ) do j = 1, larg do i = 1, long x = ( i - long2 ) * PARAM%surf_dx y = ( j - larg2 ) * PARAM%surf_dy ! Distance as expressed in the theoretical acf. When r2 is 1., the acf is 0.2. r2 = ( (+ c0 * x + s0 * y) / tau1 ) ** 2 + & ! ( (- s0 * x + c0 * y) / tau2 ) ** 2 ! Below the correlation length, no transformation if ( r2 <= 1._R8 ) cycle r2 = sqrt(r2) if ( r2 >= rr ) then tab_out(i, j) = a_min cycle endif ! ... the modified Tuckey window can be determined. tab_out(i, j) = ( cos( 0.5_R8 * PI_R8 * ( r2 - 1. ) / ( rr - 1. ) ) ** n ) * tab_in(i, j) + a_min * ( r2 - 1. ) / ( rr - 1. ) enddo enddo allocate( tab_tmp(1:long, 1:larg) ) do k = 1, 10 tab_tmp(1:long, 1:larg) = tab_out(1:long, 1:larg) do j = 1 + 1, larg - 1 do i = 1 + 1, long - 1 x = ( i - long2 ) * PARAM%surf_dx y = ( j - larg2 ) * PARAM%surf_dy ! Distance as expressed in the theoretical acf. When r2 is 1., the acf is 0.2. r2 = ( (+ c0 * x + s0 * y) / tau1 ) ** 2 + & ! ( (- s0 * x + c0 * y) / tau2 ) ** 2 r2 = sqrt(r2) if ( r2 <= 0.98_R8 .or. ( r2 >= 1.02_R8 .and. r2 <= 0.98_R8 * rr ) .or. r2 >= 1.02_R8 * rr ) cycle tab_out(i, j) = ( 2*tab_tmp(i, j) +tab_tmp(i +1, j ) +tab_tmp(i -1, j ) + & ! tab_tmp(i , j +1) +tab_tmp(i , j -1) +( tab_tmp(i +1, j -1) +tab_tmp(i -1, j -1) + & ! tab_tmp(i -1, j +1) +tab_tmp(i +1, j +1) )/sqrt(2._R8) )/( 6. +4./sqrt(2._R8) ) enddo enddo enddo deallocate( tab_tmp ) return endsubroutine apod2