|
在你的代码里。realft 这个函数用来求取傅氏变换。但是代码却是空白的。
nr.f90 里面只是接口,应该提供的是静态库。这里的代码只有接口,没有内部实现,不能直接复制过来用。
关于卷积呢。有两种:线性卷积和圆周卷积。根据你的结果是 n+m-1 来看,应该是想求取线性卷积。
而如果采用 FFT 的方式来求取,则是圆周卷积。
(你可以用补一个周期的 0 做圆周卷积,来代替线性卷积)
所以,一共有4种方法:
1.直接求取圆周卷积。(考虑周期的两层循环)
2.直接求取线性卷积。(两层循环)
3.傅氏变换求取圆周卷积。(傅氏变换的乘积,等于卷积的傅氏变换)
4.傅氏变换求取线性卷积。(补一个周期的0,再求第3方法)
在这里,给出2,4两种的代码。(我自己写的,没有用到你给的 nr 代码)
方法2:
[Fortran] 纯文本查看 复制代码 05 | FUNCTION convlv ( x 1 , x 2 ) |
06 | REAL , DIMENSION ( : ) , INTENT ( IN ) :: x 1 , x 2 |
07 | REAL , DIMENSION ( size ( x 1 ) + size ( x 2 ) -1 ) :: convlv |
11 | Integer , Parameter :: n = 16 , m = 9 |
12 | Real :: data 1 ( 2 * n ) , respns ( m ) , tmpr ( n + m -1 ) |
15 | data 1 ( ( n / 2 - n / 8 ) : ( n / 2 + n / 8 ) ) = 1.0 |
19 | tmpr = convlv ( data 1 , respns ) |
20 | Write ( * , '(9999(f5.1,1x))' ) tmpr |
21 | End Program conv_main_fft |
23 | Function convlv ( X 1 , X 2 ) |
24 | Real , Intent ( IN ) :: x 1 ( : ) , x 2 ( : ) |
25 | REAL , DIMENSION ( size ( x 1 ) + size ( x 2 ) -1 ) :: convlv |
26 | integer :: i , j , m , n , t |
28 | m = size ( x 1 ) ; n = size ( x 2 ) |
32 | if ( ( i - j ) >= 1 .and. ( i - j ) <= n ) then |
33 | convlv ( i ) = convlv ( i ) + x 1 ( j ) * x 2 ( i - j ) |
方法4:
[Fortran] 纯文本查看 复制代码 003 | Integer , parameter :: DP = Selected_Real_Kind ( 5 ) |
004 | Integer , parameter :: FFT_Forward = 1 |
005 | Integer , parameter :: FFT_Inverse = -1 |
008 | Subroutine fcFFT ( x , forback ) |
011 | Real ( Kind = DP ) , parameter :: PI = 3.141592654 _DP |
012 | Complex ( Kind = DP ) , Intent ( INOUT ) :: x ( : ) |
013 | Integer , Intent ( IN ) :: forback |
015 | integer :: i , j , k , ncur , ntmp , itmp |
017 | complex ( Kind = DP ) :: ctmp |
022 | e = 2.0 _DP * PI / ncur |
028 | ctmp = x ( i ) - x ( itmp ) |
029 | x ( i ) = x ( i ) + x ( itmp ) |
030 | x ( itmp ) = ctmp * exp ( forback * cmplx ( 0.0 _DP , e * ( j -1 ) ) ) |
054 | Integer , parameter :: SP = Selected_Real_Kind ( p = 5 ) |
055 | Integer , parameter :: I 4 b = Selected_Int_Kind ( 5 ) |
058 | Function convlv ( x , respns , isign ) |
062 | Real ( Kind = sp ) , Dimension ( : ) , Intent ( Inout ) :: x |
063 | Real ( Kind = sp ) , Dimension ( : ) , Intent ( In ) :: respns |
064 | Integer ( Kind = i 4 b ) , Intent ( In ) :: isign |
065 | Real ( Kind = sp ) , Dimension ( size ( x ) ) :: convlv |
066 | Integer ( Kind = i 4 b ) :: n , m |
067 | Complex ( Kind = SP ) , Dimension ( size ( x ) ) :: tmpd , tmpr |
072 | tmpd = cmplx ( x , 0.0 _sp ) |
073 | call fcFFT ( tmpd , FFT_Forward ) |
074 | tmpr = cmplx ( respns , 0.0 _sp ) |
075 | call fcFFT ( tmpr , FFT_Forward ) |
077 | tmpr ( 1 ) = cmplx ( real ( tmpd ( 1 ) ) * real ( tmpr ( 1 ) ) / n , aimag ( tmpd ( 1 ) ) * aimag ( tmpr ( 1 ) ) / n , kind = sp ) |
078 | tmpr ( 2 : ) = tmpd ( 2 : ) * tmpr ( 2 : ) / n |
079 | Else If ( isign == -1 ) Then |
080 | If ( any ( abs ( tmpr ( 2 : ) ) == 0.0 ) .Or. real ( tmpr ( 1 ) ) == 0.0 .Or. aimag ( tmpr ( 1 ) ) == 0.0 ) write ( * , * ) 'deconvolving at response zero in convlv' |
081 | tmpr ( 1 ) = cmplx ( real ( tmpd ( 1 ) ) / real ( tmpr ( 1 ) ) / n , aimag ( tmpd ( 1 ) ) / aimag ( tmpr ( 1 ) ) / n , kind = sp ) |
082 | tmpr ( 2 : ) = tmpd ( 2 : ) / tmpr ( 2 : ) / n |
084 | write ( * , * ) 'no meaning for isign in convlv' |
086 | Call fcFFT ( tmpr , FFT_Inverse ) |
087 | convlv = real ( tmpr ) |
095 | FUNCTION convlv ( data , respns , isign ) |
097 | REAL ( SP ) , DIMENSION ( : ) , INTENT ( INOUT ) :: data |
098 | REAL ( SP ) , DIMENSION ( : ) , INTENT ( IN ) :: respns |
099 | INTEGER ( I 4 B ) , INTENT ( IN ) :: isign |
100 | REAL ( SP ) , DIMENSION ( size ( data ) ) :: convlv |
104 | Integer , Parameter :: n = 16 , m = 16 |
105 | Real ( Kind = SP ) :: data 1 ( 2 * n ) , respns ( m ) , tmpr ( 2 * n ) |
108 | data 1 ( ( n / 2 - n / 8 ) : ( n / 2 + n / 8 ) ) = 1.0 _SP |
110 | respns ( 3 : 6 ) = 1.0 _SP |
113 | tmpr = convlv ( data 1 , respns , isign ) |
114 | Write ( * , '(9999(f5.1,1x))' ) tmpr |
115 | End Program conv_main_fft |
|
|