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.
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!
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