关于在Visual Studio Fortran环境下同时配置IMSL数据库和MKL库可能会出现的几点问题(保姆级教程)
如何在vsFortran上同时配置IMSL库和MKL库
在写完第一篇关于vs Fortran配置mkl库的文章以后我发现MKL库里面没有关于数值积分,尤其是高斯积分的函数,所以我又想到可以安装IMSL库,安装IMSL库的时候我主要参考的是下面这篇文章:关于VS2013 IVF 中IMSL函数库的安装及使用 - 知乎。
后面把这两个库弄在一起运行也是十分曲折,所以为了大家以后可以在这方面少花一点时间,我做一个教程关于遇见常见错误的一些处理方法。
一:库安装
因为我的Visual Studio是2019版,比较新,所以我安装ISML库的时候就是安装的IMSL7.0函数库。
按照上面我给出链接的文章和我的前一篇文章,先安装ISML库和MKL库。其中安装IMSL库简短来说就是在下载安装到你的电脑上后,记得编辑系统的环境变量和在编译器中指明lib和include的所在位置。然后一定要记得要看你安装的vs是32位还是64位的,我的是安装的vs是32位的,但是也能以64位运行。这里的“以64位运行”就是运行时debug或者Release使用的是32位还是64位(这里的x86你也可以认为是32位的,具体跟32位的区别我不太清楚)。。
但是你安装的vs是32位还是64位的可以参考上面那篇安装IMSL库的文章。因为我的vs是32位的,所以IMSL库也安装成32位版本的。
重点来了,因为我的电脑是64位的,所以我正常要是使用MKL库时,input选项导入的就需要是64位的库(具体看我上一篇文章,就是添加的是intel64_win文件夹下的mkl_lapack95_lp64.lib),所以如果在同一项目中使用这两个库,就需要在你这个项目的属性页上不同的位数上配置不同的内容!简单讲就是下面这张图:
因为MKL库是64位运行的,而IMSL库又是32位的,所以你需要切换不同位数的平台(红线标记位置)后配置不同的内容。就是在属性页的win32位上配置IMSL库,而在x64上配置MKL库。
二:常见错误解决办法
在你配置完使用程序验证你可能会遇到以下问题:
1:找不到imslmkl_dll
这个时候你就在为win32位的项目属性页的linker->input中填入imsl_dll.lib
2:Windows版本不兼容
这个时候检查以下你运行debug使用的是x32(x86)还是x64,因为安装的IMSL库的位数是32位的,所以必须要在x32(x86)下运行
3:IMSL库证书过期,或者是当你调用IMSL库里面的函数能编译成功,但是运行后输出界面一闪而过时:
根据网上的说法,这个是IMSL库5.0以后版本经常出现的问题,需要修改系统的时间,这个网上很多教程,只需要修改到2016年及以前就行。
4:找不到imslmkl_dll:
在你安装IMSL库的文件夹下找到这文件,我的是在:C:\Program Files (x86)\VNI\imsl\fnl700\winin111i32\lib,然后把它加到系统环境变量的path中就行了(这部分上面的文章链接也有)
三:无法编译module的解决办法
最后如果你像我一样把使用IMSL库的函数和MKL库的函数都做成了子例程(subroutine),并且放进来一个module里了,这个时候你在调试程序有可能会遇到一个问题:error #7002: Error in opening the compiled module file. Check INCLUDE paths. [你的module的名字]。意思就是你的module没有编译成功(这个时候如果你去你创建的vs项目默认输出的debug文件夹下也会发现找不到这个module编译成功的.mod文件),这个时候你需要考虑:
1:检查你的module里面有没有一些语法错误(就是康康vs的错误行里除了这个错误以外有没有什么其他的语法错误)
2:检查你对于IMSL库的那些链接步骤和MKL库的链接步骤是否正确
3:重新创建一个新的f90文件将你module里面的subroutine和function一点一点重新去除进行编译,引发module编译错误的程序。并检查你这些程序使用的是IMSL库还是MKL库,并且针对这些库再进行链接的检查。如果你使用的是mkl库的module或是函数,你发现还是解决不了这个问题,那么你可以直接去你MKL库的include文件夹下直接找这个module对应的f90文件,并且直接把它加入你的项目中进行编译,有时能解决问题。(我的是在D:\VSXE\XE\compilers_and_libraries_2020\windows\mkl\include中)
最后我把我自己写的测试的程序放在最后:(如果你有关于vsFortran或者是有限元的问题欢迎在评论区留言交流)
program main
use Math_Tool,only : guass_legendre_integration_1D
use Math_Tool,only : PARDISO_solve
end program
Module Math_Tool
Implicit none
contains
!!!!!!!!!!!!!!!!!!!!!!!!!一维高斯积分方法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Subroutine guass_legendre_integration_1D(a,b,f,N,ANSWER)
INCLUDE 'link_fnl_shared.h'
USE GQRUL_INT
USE UMACH_INT
use precision_definition,only : sp
IMPLICIT NONE
!integer, parameter :: sp = kind(1.0E0)
real(sp),intent(in) :: a,b
INTEGER(sp),intent(in) :: N
real,external :: f
REAL(sp),intent(out) :: ANSWER
INTEGER(sp) :: I, NOUT
REAL(sp) :: QW(N), QX(N), SUM!QX是高斯点数组,QW是高斯权重(系数)的数组
! Get output unit number
CALL UMACH (2, NOUT)!用于收集错误信息的函数
! Get points and weights from GQRUL
CALL GQRUL (N, QX, QW)!
! Write results from GQRUL
SUM = 0.0
ANSWER = 0.0
DO I=1, N
SUM = SUM + (b-a)/2.0*f((b-a)/2.0*QX(I)+(b+a)/2.0)*QW(I)
enddo
ANSWER = SUM
WRITE (NOUT,99999) ANSWER
99999 FORMAT (' The 1D_guass_integration result is ', 1PE10.4)
end subroutine
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!pardiso解大型稀疏线性方程组!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Subroutine PARDISO_solve(K,x,b,K_dimension,mtype)
USE mkl_PARDISO
use precision_definition,only : dp,sp,character_length
IMPLICIT NONE
integer(sp),intent(in) :: mtype!mtype值与对应A矩阵类型的注释:=1:实数和结构对称矩阵。=2:实对称正定矩阵。=-2:实对称不定矩阵。=3:复的结构对称矩阵。
integer(dp),intent(in) :: K_dimension
!=4:复的厄米正定矩阵。=-4:复的厄米不定矩阵。=6:复对称矩阵。=11:实非对称矩阵.=12:复非对称矩阵
real(dp),intent(inout) :: K(K_dimension,K_dimension),b(K_dimension)
real(dp),intent(inout) :: x( K_dimension )
!.. Internal solver memory pointer
TYPE(MKL_PARDISO_HANDLE), ALLOCATABLE :: pt(:)
!.. All other variables
integer :: maxfct, mnum, phase, n, nrhs, error, msglvl, nnz
integer :: error1
integer, ALLOCATABLE :: iparm( : )
integer, ALLOCATABLE :: ia( : )
integer, ALLOCATABLE :: ja( : )
real(dp), ALLOCATABLE :: a( : )
integer :: i, j, idum(1),nonzero_number,line_nonzero_number
real(dp) ddum(1)
!.. Fill all arrays containing matrix data.
nrhs = 1 !需要解的右边的个数,我猜是右边b矩阵的个数?
maxfct = 1 !在大多数应用程序中,这个值等于1,具体意义和作用看MKL库pardiso函数的的注释文档
mnum = 1 !在大多数应用程序中,这个值等于1,具体意义和作用看MKL库pardiso函数的的注释文档
ALLOCATE(ia(K_dimension + 1))
nonzero_number=0
do i=1,K_dimension
do j=i,K_dimension
if(K(i,j)/=0)then
nonzero_number=nonzero_number+1
endif
enddo
enddo
ALLOCATE(ja(nonzero_number))
ALLOCATE(a(nonzero_number))
line_nonzero_number=1
ia(1)=1
do i=1,K_dimension
do j=i,K_dimension
if(K(i,j)/=0)then
line_nonzero_number=line_nonzero_number+1
a(line_nonzero_number-1)=K(i,j)
ja(line_nonzero_number-1)=j
endif
enddo
ia(i+1)=line_nonzero_number
enddo
if (line_nonzero_number-1==nonzero_number) then
print*,"ia,a,ja读取排布成功"
else
print*,"ia,a,ja读取排布失败"
endif
!..
!.. Set up PARDISO control parameter
!..
ALLOCATE(iparm(64))
DO i = 1, 64
iparm(i) = 0
END DO
iparm(1) = 1 ! no solver default(默认没有求解器)
iparm(2) = 2 ! fill-in reordering from METIS(从METIS填写重新排序),iparm(3)包含可用于并行执行的处理器数量
iparm(4) = 0 ! no iterative-direct algorithm(没有迭代直接算法)
iparm(5) = 0 ! no user fill-in reducing permutation(没有用户填充减少排列)
iparm(6) = 0 ! =0 solution on the first n components of x(=0 x的前n个分量的解)
iparm(8) = 2 ! numbers of iterative refinement steps(迭代求精步骤的数量)
iparm(10) = 13 ! perturb the pivot elements with 1E-13(用1E-13扰动主元素)
iparm(11) = 1 ! use nonsymmetric permutation and scaling MPS(使用非对称排列和缩放MPS)
iparm(13) = 0 ! maximum weighted matching algorithm is switched-off (default for symmetric). Try iparm(13) = 1 in case of inappropriate accuracy(最大加权匹配算法被关闭(默认为对称)。如果精度不合适,请尝试iparm(13) = 1)
iparm(14) = 0 ! Output: number of perturbed pivots(输出:扰动枢轴数)
iparm(18) = -1 ! Output: number of nonzeros in the factor LU(输出:因子LU中非零的个数)
iparm(19) = -1 ! Output: Mflops for LU factorization(输出:用于LU分解的Mflops)
iparm(20) = 0 ! Output: Numbers of CG Iterations(输出:CG迭代次数)
error = 0 ! initialize error flag(初始化错误标志)
msglvl = 1 ! print statistical information(打印统计信息),如果msglvl = 1,求解器将统计信息打印到屏幕上。
!mtype = -2 ! symmetric, indefinite(实对称的,非正定的)
!.. Initialize the internal solver memory pointer. This is only
! necessary for the FIRST call of the PARDISO solver.(初始化内部求解器内存指针。只有第一次调用PARDISO求解器时才需要这样做)
ALLOCATE (pt(64))
DO i = 1, 64
pt(i)%DUMMY = 0 !将pt的全部元素置零
END DO
!.. Reordering and Symbolic Factorization, This step also allocates
! all memory that is necessary for the factorization(重排和符号因子分解,这一步还会分配因子分解所需的所有内存)
phase = 11 ! only reordering and symbolic factorization(只有重排和符号分解)
n=K_dimension
CALL PARDISO (pt, maxfct, mnum, mtype, phase, n, a, ia, ja, &
idum, nrhs, iparm, msglvl, ddum, ddum, error)
WRITE(*,*) 'Reordering completed ...(重新排序完成) '!(重新排序完成)
IF (error /= 0) THEN
WRITE(*,*) 'The following ERROR was detected(排序检测到以下错误): ', error
GOTO 1000
END IF
WRITE(*,*) 'Number of nonzeros in factors(因数中非零的个数) = ',iparm(18)
WRITE(*,*) 'Number of factorization MFLOPS(因子分解的次数MFLOPS) = ',iparm(19)
!.. Factorization.因子分解
phase = 22 ! only factorization 只有因子分解
CALL PARDISO (pt, maxfct, mnum, mtype, phase, n, a, ia, ja, &
idum, nrhs, iparm, msglvl, ddum, ddum, error)
WRITE(*,*) 'Factorization completed((分解完成)) ... '!(分解完成)
IF (error /= 0) THEN
WRITE(*,*) 'The following ERROR was detected(分解检测到以下错误): ', error
GOTO 1000
ENDIF
!.. Back substitution and iterative refinement!反向替换和迭代求精
iparm(8) = 2 ! max numbers of iterative refinement steps!迭代求精的最大步骤数
phase = 33 ! only solving(只有求解)
CALL PARDISO (pt, maxfct, mnum, mtype, phase, n, a, ia, ja, &
idum, nrhs, iparm, msglvl, b, x, error)
WRITE(*,*) 'Solve completed(求解完成) ... '
IF (error /= 0) THEN
WRITE(*,*) 'The following ERROR was detected(求解检测到以下错误): ', error
GOTO 1000
ENDIF
!WRITE(*,*) 'The solution of the system is(方程组的解是) '
!DO i = 1, n
! WRITE(*,*) ' x(',i,') = ', x(i)
!END DO
1000 CONTINUE
!.. Termination and release of memory!内存的终止和释放
phase = -1 ! release internal memory!
CALL PARDISO (pt, maxfct, mnum, mtype, phase, n, ddum, idum, idum, &
idum, nrhs, iparm, msglvl, ddum, ddum, error1)
IF (ALLOCATED(ia)) DEALLOCATE(ia)
IF (ALLOCATED(ja)) DEALLOCATE(ja)
IF (ALLOCATED(a)) DEALLOCATE(a)
IF (ALLOCATED(iparm)) DEALLOCATE(iparm)
IF (error1 /= 0) THEN
WRITE(*,*) 'The following ERROR on release stage was detected(在释放阶段检测到以下错误): ', error1
STOP 1
ENDIF
IF (error /= 0) STOP 1
end subroutine
end module
更多推荐
所有评论(0)