Community
cancel
Showing results for 
Search instead for 
Did you mean: 
yang__dong
Beginner
151 Views

About COO with duplicate entries, and MKL_sparse_export_csr

Hello everyone,

Because I am working FEM, global stiffness matrix is sparse, which can be easily assembled in a COO format. But it's noted that this formed COO matrix have many unsorted duplicate entries (there are many values with same row and col value) which need to be sorted and consolidated or summed. In many other platforms, like matlab and python, sparse function can automatically sort and sum these duplicates, producing correct final COO format matrix. 

But in MKL for Fortran users, I use mkl_?csrcoo, and it doens't consolidate these duplicates even though it produce sorted CSR matrix. Now I am using Matrix Manipulation Rountines in IE Sparse BLAS to do these things. I am not sure if these new rountines can operate COO with duplicate entries. 

In addition, the routine mkl_spares_?_export_csr always give out wrong results. I also don't how to allocate array 'col_indx' and 'values', because I even don't know the length of these arrays if the duplicate entries have been consolidated.

My computer environment is VS 2015 community and Intel composer XE2018 update1.

 

Thanks in advance.

Eric

0 Kudos
1 Reply
yang__dong
Beginner
151 Views

Hello, everyone!

Now I find an indirect way to convert COO (with duplicates) into CSR. This approach was in fact given by an expert called mecej4 in this forum. It can be divided into two steps. First, we can use MKL_?CSRCOO subroutine to convert COO (with duplicates) into CSR with job(1)=2, then we will get a sorted CSR data even though it also has some duplicates. Second, I wrote my own simple subroutine 'Sum_duplicate' to consolidate those duplicates in CSR data, and then returns the final CSR data with no duplicates. 

I have successfully used this approach to assemble the FEM stiffness matrix in a CSR format, and together with Pardiso solver to solve the equation 'KU=F'. It takes less than 1s to solve an linear elastic case with almost 200K DOFs.

The simple subroutine is attached, hoping it can help someone!

 

Best regards!

Eric

 

include 'mkl_spblas.f90'

module Consolidate
implicit none

contains
subroutine Sum_duplicate(ia, ja, a, ia_new, ja_new, a_new, q)
integer :: ia(:), ja(:), ia_new(:), ja_new(:), q
integer :: p, num_new, num_old, i, j
real *8 :: a(:), a_new(:)

num_new=0; num_old=0; p=0; q=0

do i=1, size(ia)-1
    num_old = num_new
    num_new = num_new + ia(i+1)-ia(i)
    ia_new(i) = ia(i)-p
    if (ia(i+1)-ia(i)==0) cycle
    q=q+1; ja_new(q)=ja(num_old+1); a_new(q)=a(num_old+1)
    if (ia(i+1)-ia(i) >= 2)then
        do j=num_old+2, num_new
            if(ja(j)==ja(j-1))then
                p=p+1
                a_new(q)=a_new(q)+a(j)
            elseif (ja(j) /= ja(j-1)) then
                q=q+1
                ja_new(q)=ja(j); a_new(q)=a(j)
            end if
        end do
    end if
end do
ia_new(size(ia))=ia(size(ia))-p

return
end subroutine Sum_duplicate

end module Consolidate


Program ConvertCSR_test
    use mkl_spblas
    use Consolidate
    implicit none
    !include 'mkl_spblas.fi'
    Integer  n, nnz, info
    real *8, allocatable :: a(:), a_new(:), acoo(:)
    integer, allocatable :: ia(:), ja(:), ia_new(:), ja_new(:), rowind(:), colind(:)
    integer, allocatable :: iab(:), iae(:)
    integer job(8), stat, index, rows,cols, q_size
    type(SPARSE_MATRIX_T) :: A_csr, A_coo
    integer,allocatable, dimension(:) :: iab_p, iae_p, ja_p
    real *8,allocatable, dimension(:) :: acsr_p
    
    n=4
    nnz=6
    
    allocate(rowind(nnz))
    allocate(colind(nnz))
    allocate(acoo(nnz))
    
    rowind=(/4,1,3,3,4,4/)
    colind=(/4,1,2,3,3,4/)
    acoo=(/2,1,2,3,2,4/)
    
    job(1)=2
    job(2)=1
    job(3)=1
    job(6)=0
    
    allocate(ia(n+1))
    allocate(ja(nnz))
    allocate(acsr(nnz))
    
    call mkl_dcsrcoo(job, n, a, ja, ia, nnz, acoo, rowind, colind, info)
    
    write(*,*) info
    
    write(*,*) ia
    write(*,*) ja
    write(*,*) a
     
    allocate(ia_new(size(ia)))
    allocate(ja_new(size(ja)))
    allocate(a_new(size(a)))
    
    call Sum_duplicate(ia, ja, a, ia_new, ja_new, a_new, q_size)
    
    write(*,*) q_size
    write(*,*) ia_new
    write(*,*) ja_new(1:q_size)
    write(*,*) a_new(1:q_size)
    
end Program

 

Reply