fortran使用pardiso求解器求解稀疏非对称线性方程组

program nonsymmetric
    implicit none
    integer, parameter        :: n = 4  !// depend on your equation
    integer                   :: i, j, mm, tmp, nn, fileid, first, num
    real(kind=8)              :: matrix(n,n), b(n), x(n)
    real(kind=8), allocatable :: aa(:)
    integer, allocatable      :: ia(:), ja(:)
  
    !// =====================the variables of pardiso====================
    integer(kind=8)           :: pt(64)   !// kind=8:x64; kind=4:win32
    integer                   :: maxfct, mnum, mtype, phase, nrhs, error, msglvl
    integer, allocatable      :: perm(:)
    integer                   :: iparm(64)
    integer, external         :: mkl_get_max_threads
    !// =====================the variables of pardiso====================
  
    type                      :: node
        real(kind=8)          :: s
        integer               :: k1, k2
        type (node), pointer  :: next
    end type node 
    type (node), pointer      :: head, tail, p, q  
  
    !// input data
    allocate( perm( n ) )
    open ( newunit = fileid, file = 'invM2M1.dat' )  !// The sparse matrix data needs to be given by itself
    do i = 1, n
            read( fileid,* ) matrix(i,:)
    end do
    read( fileid,* ) b
    close( fileid )
 
    !// =========================store data by CSR format=======================
    first = 1
    if ( .not.associated(p) ) then
        allocate( p )
        q    => p
        nullify( p%next )
        q%k2 = first
        tmp  = q%k2
    end if
  
    num = 0  !// calculate the number of no-zero
    do i =  1, n
        mm = 0  !// calculate the position of no-zero in every row
        do j = 1, n
            if ( matrix(i,j) /= 0.0 ) then
                if ( .not.associated(head) ) then
                    allocate( head )
                    tail    => head
                    nullify( tail%next )
                    tail%s  = matrix(i,j)
                    tail%k1 = j
                    num     = num + 1
                    mm      = mm + 1
                else
                    allocate( tail%next )
                    tail    => tail%next
                    tail%s  = matrix(i,j)
                    tail%k1 = j
                    num     = num + 1  
                    mm      = mm + 1  
                    nullify( tail%next )
                end if
            end if
        end do
        if ( associated(p) ) then
            allocate( q%next )
            q    => q%next
            q%k2 = tmp + mm
            tmp  = q%k2
            nullify( q%next )
        end if
    end do
  
    allocate( aa(num), ja(num), ia(n+1) )  !// store the no-zero element
    !// output a and ja
    tail => head
    j = 1
    do 
        if ( .not.associated(tail) ) exit
        aa(j) = tail%s
        ja(j) = tail%k1
        j     = j + 1
        tail  => tail%next
    end do
  
    !// output ia
    q => p
    j = 1
    do 
        if ( .not.associated(q) ) exit
        ia(j) = q%k2
        j     = j + 1
        q     => q%next
    end do
  
    nullify( head, tail, p, q )
    !// =========================store data by CSR format=======================
    write ( *,'(a)' ) '>> Original data'
    do i = 1, n
            write( *,'(*(f7.2))' ) matrix(i,:)
    end do
    write ( *,'(a)' ) '>> CSR data'
    write ( *,'(*(f7.2))' ) aa
    write ( *,'(a)' ) '>> B data'
    write ( *,'(*(f7.2))' ) b
    write ( *,'(a)' ) '>> Colnum of CSR data'
    write ( *,'(*(i4))' ) ja
    write ( *,'(a)' ) '>> The position of CSR data'
    write ( *,'(*(i4))' ) ia
  
    !// ===========================solve equations=============================
    pt = 0  !// pointer initialization
    maxfct = 1; mnum = 1; mtype = 11  !// mtype = -2: symmetric nonpositive definite matrix, mtype = 2: symmetric positive definite matrix
    perm = 0; nrhs = 1
    x = 0.d0
    iparm(1) = 0  !// iparm use default values
    iparm(3) = mkl_get_max_threads()  !// iparm(3): parallel threads are obtained by MKL. In general, the number of cpus is the same as the number of threads
    error = 0  
    msglvl = 0
    
    phase = 12  !// LU decompose
    call pardiso( pt, maxfct, mnum, mtype, phase, n, aa, ia, ja, perm, nrhs, iparm, msglvl, b, x, error )
    phase = 33  !// solve equations
    call pardiso( pt, maxfct, mnum, mtype, phase, n, aa, ia, ja, perm, nrhs, iparm, msglvl, b, x, error )
    write ( *,'(a)' ) '>> The solution as follows ...... '
    do i = 1, n
        write( *,'(f7.4)' ) x(i)
    end do
    
    phase = -1
    call pardiso (pt, maxfct, mnum, mtype, phase, n, aa, ia, ja, perm, nrhs, iparm, msglvl, b, x, error)
    
    deallocate( aa, ja, ia, perm )
    !// ===========================stop solving equations=============================
  
end program nonsymmetric

结果如下:
>> Original data
   1.00   7.00   0.00   0.00
   0.00   2.00   8.00   0.00
   5.00   0.00   3.00   9.00
   0.00   6.00   0.00   4.00
>> CSR data
   1.00   7.00   2.00   8.00   5.00   3.00   9.00   6.00   4.00
>> B data
  15.00  28.00  50.00  28.00
>> Colnum of CSR data
   1   2   2   3   1   3   4   2   4
>> The position of CSR data
   1   3   5   8  10
>> The solution as follows ......
 1.0000
 2.0000
 3.0000
 4.0000
请按任意键继续. . .

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
Fortran编程使用PARDISO求解大型稀疏复数非对称矩阵方程也是很常见的需求。PARDISO是一种高效的直接求解,可以用于求解非对称矩阵方程。 以下是一个使用PARDISO库求解大型稀疏复数非对称矩阵方程的简单示例代码: ```fortran program sparse_solver implicit none ! PARDISO库的接口声明 interface subroutine pardisoinit(pt, mtype, iparm) integer, intent(inout) :: pt(:), iparm(:) integer, intent(in) :: mtype end subroutine pardisoinit subroutine pardiso(pt, maxfct, mnum, mtype, phase, n, a, ia, ja, perm, nrhs, iparm, msglvl, b, x, error) integer, intent(inout) :: pt(:), iparm(:), perm(:), ia(:), ja(:) integer, intent(in) :: maxfct, mnum, mtype, phase, n, nrhs, msglvl complex, intent(inout) :: a(:) complex, intent(inout) :: b(:), x(:) real(kind=8), intent(out) :: error end subroutine pardiso subroutine pardisofree(pt, mtype) integer, intent(inout) :: pt(:) integer, intent(in) :: mtype end subroutine pardisofree end interface ! 定义PARDISO相关参数 integer :: pt(64), iparm(64) integer :: maxfct, mnum, mtype, phase, n, nrhs integer :: ia(n+1), ja(:), perm(n) complex :: a(:), b(n), x(n) real(kind=8) :: error character(len=64) :: msg ! 初始化PARDISO库 maxfct = 1 mnum = 1 mtype = 11 ! 非对称矩阵 phase = 11 ! 初始化阶段 n = ! 矩阵的维度 nrhs = 1 ! 方程右侧的列数 call pardisoinit(pt, mtype, iparm) ! 设置PARDISO的参数 iparm(1) = 1 ! 使用默认配置 iparm(3) = 0 ! 不打印统计信息 iparm(4) = 0 ! 不打印错误信息 ! 填充稀疏矩阵A的数据 ! ... ! 填充向量b的数据 ! ... ! 调用PARDISO求解方程 call pardiso(pt, maxfct, mnum, mtype, phase, n, a, ia, ja, perm, nrhs, iparm, 0, b, x, error) ! 检查求解状态 if (error /= 0.0) then write(*, *) "PARDISO solver failed with error code: ", error stop end if ! 输出解向量x的结果 ! ... ! 释放PARDISO库占用的内存 call pardisofree(pt, mtype) end program sparse_solver ``` 请注意,上述示例的部分代码需要根据您的具体问题进行填充,包括稀疏矩阵A和向量b的数据填充以及解向量x的结果输出。同时,您需要确保已经正确安装并链接了PARDISO库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值