Novice 发表于 2023-6-5 15:59:12

MKL_DFTI, MODULE, INCLUDE

本帖最后由 Novice 于 2023-6-5 16:13 编辑

mkl_dft在fortran中的模块调用
使用原帖中的代码:
Module MKL_FFT !// 以下代码复制粘贴,直接使用
Use MKL_DFTI
private
Type , public :: CLS_FFT
    type(DFTI_DESCRIPTOR), Pointer :: h => NULL()
    Integer :: Err
contains
    Procedure :: Create
    Procedure :: Forward
    Procedure :: Backward
    Procedure :: Destory
End Type CLS_FFT

contains

Subroutine Create( this , N )
    class( CLS_FFT ) :: this
    Integer , Intent( IN ) :: N
    this%Err = DftiCreateDescriptor( this%h , DFTI_SINGLE , DFTI_REAL , 1 , N )
    this%Err = DftiSetValue( this%h , DFTI_PLACEMENT , DFTI_NOT_INPLACE )
    this%Err = DftiCommitDescriptor( this%h )
End Subroutine Create

Function Forward( this , X ) result( F )
    class( CLS_FFT ) :: this
    Real :: X(:)
    Complex :: F( size(X)/2+1 )
    this%Err = DftiComputeForward( this%h , X , F )
End Function Forward

Function Backward( this , X ) result( T )
    class( CLS_FFT ) :: this
    Complex :: X(:)
    Real    :: T( size(X)*2-1 )
    this%Err = DftiComputeBackward( this%h , X , T )
End Function Backward

Subroutine Destory( this )
    class( CLS_FFT ) :: this
    this%Err = DftiFreeDescriptor( this%h )
End Subroutine Destory

End Module MKL_FFT
!// 以上代码复制粘贴,直接使用

Program Test_FFT
use MKL_FFT   !// 这句代码必须 *************
Type( CLS_FFT ) :: FFT !// 这句定义一个 FFT 的过程 ************
Integer , parameter :: N = 30 !//不需要2^k 次方整幂
Real   :: r(N) = & !// 时间域
   
Complex:: f(N/2+1) !// 频率域,为复数,大小为 n/2 + 1

call FFT%Create( N ) !// 创建FFT过程。N 是 FFT 的点数 ************
f= FFT%Forward( r )!// 正向 FFT 变换*************
Do i = 1 , size(f)
    Write( * , * ) i , f( i ) !// 输出频率域
End Do
r = FFT%Backward( f ) / n !// 这一句可以做反傅氏变换 *************
call FFT%Destory() !// 销毁 FFT 过程*************
Do i = 1 , size(r)
    Write( * , * ) i , r(i) !// 输出反变换
End Do
Read(*,*)
End Program Test_FFT
编译环境:Ubuntu22.04 + ifort (OneAPI)
编译命令:ifort -o MKL_FFT MKL_FFT.f90 -L${MKLROOT}/lib/intel64 -I${MKLROOT}/include -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm
无法编译,报错为MKL_FFT.f90(3): error #7002: Error in opening the compiled module file.Check INCLUDE paths.   

Use MKL_DFTI
- 第一个问题:这个错误为编译命令中未先生成mkl相关的Mod吗?
- 第二个问题:在声明使用MKL_DFTI mod之前,参考troubleshot_mkl_fortran加入include如下:
Module MKL_FFT !// 以下代码复制粘贴,直接使用
INCLUDE 'mkl_dfti.f90'
Use MKL_DFTI
编译报错为:/opt/intel/oneapi/mkl/2023.1.0/include/mkl_dfti.f90(20): error #6218: This statement is positioned incorrectly and/or has syntax errors.
MODULE MKL_DFT_TYPE
但将include置于MOD声明之前,如下:
INCLUDE 'mkl_dfti.f90'
Module MKL_FFT !// 以下代码复制粘贴,直接使用
Use MKL_DFTI
则编译正常,这个问题是因为include为预处理命令,得在编译前先加入才能在编译mod时使用吗?还是有其他的原因导致此处include的位置对编译成败有影响?先向前辈们致谢!

fcode 发表于 2023-6-5 19:09:35

我一般是单独编译 mkl_dfti.f90 文件。

它是一些独立的module,你可以打开这个文件自行查看:
通常内含两个module,即:
MODULE MKL_DFT_TYPE
MODULE MKL_DFTI

Fortran 不允许在一个module中直接包含另一个module,所以你不能把include语句放在
Module MKL_FFT 里面,因为这样的话 Module MKL_FFT 就包含了 MODULE MKL_DFT_TYPE 和 MODULE MKL_DFTI
放在mod语句前面可以避免这个问题。但是 include 的写法,只适合于“你的整个工程,只有 MKL_FFT 这个模块需要 MKL_DFTI”

更好的方法,是单独编译 mkl_dfti.f90,得到 MKL_DFT_TYPE.mod 和 MODULE MKL_DFTI.mod
然后再编译 Module MKL_FFT 。
这样无需写 include,并且可以解决多个源代码文件中都需要使用 MKL_DFT_TYPE 和 MKL_DFTI 的问题。
如果你在多个源代码文件中,例如在 MKL_FFT 和 MKL_FFT_ABC 中,都写了 INCLUDE 'mkl_dfti.f90',就会产生冲突。

Novice 发表于 2023-6-6 10:04:49

fcode 发表于 2023-6-5 19:09
我一般是单独编译 mkl_dfti.f90 文件。

它是一些独立的module,你可以打开这个文件自行查看:


多谢前辈回复,所以应该避免将多次使用的外部module直接放在代码中,而应该先编译这些mod再编译主要的源代码,所以这个命令一般只适合单一模块需要外部module :ifort -o MKL_FFT MKL_FFT.f90 -L${MKLROOT}/lib/intel64 -I${MKLROOT}/include -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm,一般还是得把外部文件例如mkl_dfti.f90和源代码放在一起编译

fcode 发表于 2023-6-7 08:19:41

通常来说,1个module,1个源代码文件。

少数情况下,2-3个强烈相关联的module可以放同一个源代码文件。
比如 mkl_dfti.f90 中有2个module,MODULE MKL_DFT_TYPE 和 MODULE MKL_DFTI。但它们几乎不分开使用,所以放一起没什么问题。

woduiren 发表于 2023-6-8 00:18:12

我想实现二维快速傅里叶变换,不知道怎么编写程序,希望有大佬能指导指导:-loveliness:
页: [1]
查看完整版本: MKL_DFTI, MODULE, INCLUDE