Matrix Fortran语言中的稀疏矩阵向量积

Matrix Fortran语言中的稀疏矩阵向量积,matrix,vector,fortran,sparse-matrix,Matrix,Vector,Fortran,Sparse Matrix,知道我的矩阵是稀疏的,我如何用Fortran进行矩阵向量乘法 例如,我想计算3x3矩阵之间的乘积 0 1 2 3 0 0 4 0 5 矢量呢 1 2 3 我曾考虑在不等于零的情况下存储行、列以及值,但没有任何结果。除非您想了解如何实现这一点,否则可以使用稀疏矩阵库。例如SPARSKIT或suitesparse。除非您想了解如何实现此功能,否则可以使用稀疏矩阵库。例如SPARSKIT或suitesparse。首先,您需要确定稀疏代数还是密集代数的速度更快: 实际计算中涉及的矩阵大小是多少?如

知道我的矩阵是稀疏的,我如何用Fortran进行矩阵向量乘法

例如,我想计算3x3矩阵之间的乘积

0 1 2
3 0 0
4 0 5 
矢量呢

1
2
3

我曾考虑在不等于零的情况下存储行、列以及值,但没有任何结果。

除非您想了解如何实现这一点,否则可以使用稀疏矩阵库。例如SPARSKIT或suitesparse。

除非您想了解如何实现此功能,否则可以使用稀疏矩阵库。例如SPARSKIT或suitesparse。

首先,您需要确定稀疏代数还是密集代数的速度更快:


实际计算中涉及的矩阵大小是多少?如果它是某个维度m,n,其中,比如说,m首先,你需要决定稀疏代数还是稠密代数会更快:


实际计算中涉及的矩阵大小是多少?如果它是某个维度m,n,比如说,mI想学习如何在有限差分2d上实现它。谢谢,我要试试这些。我想学习如何在二维有限差分上实现它。谢谢,我要试试这些。我只是想说Fortran 77已经过时30年了——如果你想这样做,为什么要在有更好的工具可用的时候使用它呢?因为这是我第一年在课堂上学习Fortran,他们希望我们从底层学习。稍后我们将使用Fortran 95。我只想说Fortran 77已经过时30年了。如果你想这样做,为什么要在有更好的工具可用的时候使用它呢?因为这是我第一年在课堂上使用Fortran,他们希望我们从底层学习它。我们将使用Fortran 95 laterNice,这是一次很好的尝试,可以将这个问题拖到这个千年!只需一条评论,使用ieee_算术内在模块中的ieee_值比从这里的神奇常数转换生成NaN更清晰。很好,很好的尝试将问题拖到这个千年!只需一个注释,使用ieee_算术内在模块中的ieee_值,比从这里的神奇常数转换生成NAN更清晰。
module sparse_CSR
  use iso_fortran_env
  implicit none
  public

    type, public :: CSRMatrix
       integer :: m = 0
       integer :: n = 0
       integer, allocatable :: rowPtr(:)
       integer, allocatable :: colPtr(:)
       real(real64), allocatable :: aij(:)
    end type CSRMatrix 
    
    contains
    
    ! Convert a dense matrix to a sparse one. 
    pure type(CSRMatrix) function dense_to_sparse(matrix) result(sparse)
       real(real64), intent(in) :: matrix(:,:)

       integer :: ierr,m,n,nnz,row,nnz_row,j1,j2,colIndex(size(matrix,2))
       logical :: row_nonZeroes(size(matrix,2))

       ! Get matrix size
       m = size(matrix,1)
       n = size(matrix,2)
       nnz = count(matrix/=0.0_real64)

       ! Create an array of indices
       forall(j1=1:n) colIndex(j1) = j1

       ! Set matrix size
       sparse%m = m
       sparse%n = n
       
       ! Allocate data
       allocate(sparse%rowPtr(m+1),sparse%colPtr(nnz),sparse%aij(nnz))

       ! Fill rows
       sparse%rowPtr(1) = 1
       fill_by_rows: do row=1,m
          row_nonZeroes = matrix(row,:)/=0.d0      
          nnz_row = count(row_nonZeroes)
          
          j1 = sparse%rowPtr(row)
          j2 = j1+nnz_row-1
          sparse%colPtr(j1:j2) = pack(colIndex     ,row_nonZeroes)
          sparse%aij   (j1:j2) = pack(matrix(row,:),row_nonZeroes)

          ! Set pointer for beginning of next line
          sparse%rowPtr(row+1) = j2+1
     
       end do fill_by_rows

    end function dense_to_sparse
     
    ! Compute matrix-vector product
    pure function sparse_matvec(matrix,vector) result(MxV)
       type(CSRMatrix), intent(in) :: matrix
       real(real64), intent(in) :: vector(:)
       real(real64) :: MxV(matrix%m)

       integer :: row,j,j1,j2,col
       real(real64) :: aij

       ! Check size. Cannot stop in a pure procedure. 
       ! So, return NaNs
       if (size(vector,1)/=matrix%n) then 
          MxV(:) = transfer(-2251799813685248_int64, 1._real64)
          return
       endif  

       ! Compute product by rows
       do row=1,matrix%m
          j1 = matrix%rowPtr(row)
          j2 = matrix%rowPtr(row+1)-1; 

          MxV(row) = 0.0_real64
          do j=j1,j2
             col = matrix%colPtr(j)
             aij = matrix%aij(j)
             MxV(row) = MxV(row) + aij*vector(col) 
          end do
       end do         

    end function sparse_matvec

end module sparse_CSR

program test_sparse
  use sparse_CSR
  use iso_fortran_env
  implicit none

  real(real64) :: dense(3,3) = reshape(real([0,3,4,1,0,0,2,0,5],real64),[3,3]) 
  real(real64) :: vector(3) = real([1,2,3],real64)
  type(CSRMatrix) :: sparse
  real(real64) :: MxV(3)

  sparse = dense_to_sparse(dense)
  MxV = sparse_matvec(sparse,vector)

  print *, 'MxV = ',MxV

end program test_sparse
 MxV =    8.0000000000000000        3.0000000000000000        19.000000000000000