LCOV - code coverage report
Current view: top level - src/78_effpot - m_spmat_convert.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 30.4 % 115 35
Test Date: 2026-09-20 18:56:22 Functions: 22.2 % 9 2

            Line data    Source code
       1              : !!****m* ABINIT/m_spmat_convert
       2              : !! NAME
       3              : !! m_spmat_convert
       4              : !!
       5              : !! FUNCTION
       6              : !! This module contains the functions to convert between sparse matrix formats
       7              : !!
       8              : !!
       9              : !! Subroutines:
      10              : !! - dense_to_LIL
      11              : !! - LIL_to_dense
      12              : !! - LIL_to_COO
      13              : !! - LIL_to_CSR
      14              : !! - Dense_to_CSR
      15              : !!
      16              : !!
      17              : !! COPYRIGHT
      18              : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      19              : !! This file is distributed under the terms of the
      20              : !! GNU General Public License, see ~abinit/COPYING
      21              : !! or http://www.gnu.org/copyleft/gpl.txt .
      22              : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      23              : !!
      24              : !! SOURCE
      25              : 
      26              : #if defined HAVE_CONFIG_H
      27              : #include "config.h"
      28              : #endif
      29              : #include "abi_common.h"
      30              : 
      31              : 
      32              : module m_spmat_convert
      33              :   use defs_basis
      34              :   use m_xmpi
      35              :   use m_abicore
      36              :   use m_errors
      37              :   use m_spmat_dense
      38              :   use m_linked_list
      39              :   use m_spmat_lil
      40              :   use m_spmat_csr
      41              :   use m_spmat_coo
      42              :   use m_spmat_lco
      43              :   implicit none
      44              : !!****m*
      45              :   public
      46              :   !-----------------------------------------------------------------------
      47              :   !> @brief convert one type of matrix Amat to the other Bmat
      48              :   !> Note that the dense matrix is not the dense_mat_t because a
      49              :   !> simple 2d array is more generally used.
      50              :   !> @param [in] Amat
      51              :   !> @param [out] Bmat
      52              :   !-----------------------------------------------------------------------
      53              :   interface spmat_convert
      54              :      !procedure  dense_to_LIL
      55              :      procedure  LIL_to_dense
      56              :      procedure  LIL_to_COO
      57              :      procedure  LIL_to_CSR
      58              :      procedure dense_to_CSR
      59              :      procedure dense_to_COO
      60              :      procedure  COO_to_CSR
      61              :      !procedure LCO_to_CSR
      62              :   end interface spmat_convert
      63              : 
      64              :   public :: COO_to_dense
      65              : contains
      66              : 
      67              :   !-----------------------------------------------------------------------
      68              :   !> @brief dense matrix to LIL matrix
      69              :   !> @param [in] mat: 2D array
      70              :   !> @param [out] ll : LIL matrix
      71              :   !-----------------------------------------------------------------------
      72            0 :   subroutine dense_to_LIL(mat, ll)
      73              :     ! check shape
      74              :     real(dp), intent(in):: mat(:, :)
      75              :     type(LIL_mat_t), intent(inout) :: ll
      76              :     integer :: s(2), irow, icol
      77            0 :     s=shape(mat)
      78            0 :     call ll%initialize(s)
      79            0 :     do icol=1, ll%ncol, 1
      80            0 :        do irow=1, ll%nrow, 1
      81            0 :           call ll%insert(irow,icol,mat(irow, icol),0)
      82              :        enddo
      83              :     enddo
      84            0 :   end subroutine dense_to_LIL
      85              : 
      86              :   !-----------------------------------------------------------------------
      87              :   !> @brief LIL matrix to dense matrix
      88              :   !> @param [in] ll : LIL matrix
      89              :   !> @param [out] mat: 2D array
      90              :   !-----------------------------------------------------------------------
      91            0 :   subroutine LIL_to_dense(ll, mat)
      92              :     class(LIL_mat_t) , intent(inout):: ll
      93              :     real(dp), intent(out):: mat(ll%nrow,ll%ncol)
      94              :     integer:: irow
      95            0 :     mat(:,:)=0.0d0
      96            0 :     do irow=1, ll%nrow
      97            0 :        call llist_iter_restart(ll%rows(irow))
      98            0 :        do while(associated(ll%rows(irow)%iter))
      99            0 :           mat(irow, ll%rows(irow)%iter%i)=ll%rows(irow)%iter%val
     100            0 :           ll%rows(irow)%iter=>ll%rows(irow)%iter%next
     101              :        enddo
     102              :     enddo
     103            0 :   end subroutine LIL_to_dense
     104              : 
     105              :   !-----------------------------------------------------------------------
     106              :   !> @brief LIL matrix to COO matrix
     107              :   !> @param [in] ll : LIL matrix
     108              :   !> @param [out] csrmat: COO matrix
     109              :   !-----------------------------------------------------------------------
     110            0 :   subroutine LIL_to_COO(ll, COO)
     111              :     class(LIL_mat_t) , intent(inout):: ll
     112              :     class(COO_mat_t), intent(out):: COO
     113              :     integer ::  irow
     114            0 :     call  COO%initialize(mshape=ll%mshape)
     115            0 :     do irow=1, ll%nrow
     116            0 :        call llist_iter_restart(ll%rows(irow))
     117            0 :        do while(associated(ll%rows(irow)%iter))
     118            0 :           call coo%add_entry([irow, ll%rows(irow)%iter%i], ll%rows(irow)%iter%val)
     119            0 :           ll%rows(irow)%iter=>ll%rows(irow)%iter%next
     120              :        enddo
     121              :     end do
     122              : 
     123            0 :   end subroutine LIL_to_COO
     124              : 
     125              :   !-----------------------------------------------------------------------
     126              :   !> @brief LIL matrix to CSR matrix
     127              :   !> @param [in] ll : LIL matrix
     128              :   !> @param [out] csrmat: CSR matrix
     129              :   !-----------------------------------------------------------------------
     130            2 :   subroutine LIL_to_CSR(ll, csrmat)
     131              :     type(LIL_mat_t) , intent(inout):: ll
     132              :     type(CSR_mat_t), intent(inout):: csrmat
     133              :     integer:: irow,  i, nzrow
     134            6 :     call  csrmat%initialize([ll%nrow, ll%ncol])
     135            2 :     call csrmat%set(nnz=ll%get_nnz())
     136            2 :     i=0
     137            2 :     csrmat%row_shift(1)=1
     138         1298 :     do irow=1, ll%nrow
     139         1296 :        nzrow=0
     140         1296 :        call llist_iter_restart(ll%rows(irow))
     141        34992 :        do while(associated(ll%rows(irow)%iter))
     142        33696 :           nzrow=nzrow+1
     143        33696 :           i=i+1
     144        33696 :           csrmat%icol(i)=ll%rows(irow)%iter%i
     145        33696 :           csrmat%val(i)=ll%rows(irow)%iter%val
     146        33696 :           ll%rows(irow)%iter=>ll%rows(irow)%iter%next
     147              :        enddo
     148         1298 :        csrmat%row_shift(irow+1)=csrmat%row_shift(irow)+nzrow
     149              :     enddo
     150            2 :   end subroutine LIL_to_CSR
     151              : 
     152              :   !-----------------------------------------------------------------------
     153              :   !> @brief dense matrix to CSR matrix
     154              :   !> @param [in] mat: dense matrix
     155              :   !> @param [out] csrmat: CSR matrix
     156              :   !-----------------------------------------------------------------------
     157            0 :   subroutine dense_to_CSR(mat, csrmat)
     158              :     real(dp), intent(in):: mat(:, :)
     159              :     type(csr_mat_t), intent(out) :: csrmat
     160              :     !type(lil_mat_t):: lilmat
     161              :     integer :: i, j, nnz, nrow, ncol, inz, nzrow
     162              :     !call dense_to_lil(mat, lilmat)
     163              :     !call lil_to_csr(lilmat, csrmat)
     164              :     !call lilmat%finalize()
     165            0 :     nnz=count(mat /= 0.0_dp)
     166            0 :     nrow=size(mat, 1)
     167            0 :     ncol=size(mat, 2)
     168            0 :     call  csrmat%initialize([nrow, ncol])
     169            0 :     call csrmat%set(nnz=nnz)
     170            0 :     csrmat%row_shift(1)=1
     171            0 :     inz=0
     172            0 :     do i=1, nrow
     173              :        nzrow=0
     174            0 :        do j=1, ncol
     175            0 :           if (mat(i, j)/=0.0_dp) then
     176            0 :              inz=inz+1
     177            0 :              nzrow=nzrow+1
     178            0 :              csrmat%icol(inz)=j
     179            0 :              csrmat%val(inz)=mat(i,j)
     180              :           end if
     181              :        end do
     182            0 :        csrmat%row_shift(i+1)=csrmat%row_shift(i)+nzrow
     183              :     end do
     184            0 :   end subroutine dense_to_CSR
     185              : 
     186              :   !-------------------------------------------------------------------!
     187              :   ! dense_to_coo
     188              :   ! Dense to COO matrix convertion
     189              :   !-------------------------------------------------------------------!
     190            0 :   subroutine dense_to_coo(mat, coo)
     191              :     real(dp), intent(in) :: mat(:,:)
     192              :     type(coo_mat_t), intent(inout) :: coo
     193              :     integer:: i, j
     194            0 :     call coo%initialize(shape(mat))
     195            0 :     do j=1, size(mat, dim=2)
     196            0 :        do i=1, size(mat, dim=1)
     197            0 :           if (abs(mat(i, j)) >tiny(1.0d0) ) then
     198            0 :              call coo%add_entry(ind=[i,j], val=mat(i,j))
     199              :           end if
     200              :        end do
     201              :     end do
     202            0 :   end subroutine dense_to_coo
     203              : 
     204              :   !-------------------------------------------------------------------!
     205              :   ! COO_to_CSR:
     206              :   !  translate COO matrix to CSR matrix
     207              :   !  NOTE: This can be quite slow when it is large due to the sort algorithm
     208              :   ! Input:
     209              :   !  COO matrix
     210              :   ! Output:
     211              :   !   CSR matrix
     212              :   !-------------------------------------------------------------------!
     213            1 :   subroutine COO_to_CSR(coo, csr)
     214              :     type(COO_mat_t), intent(inout) :: coo
     215              :     type(CSR_mat_t), intent(inout) :: csr
     216              :     integer :: ngroup
     217            1 :     integer, allocatable :: i1_list(:), istartend(:)
     218            2 :     integer :: row_nz(coo%mshape(1))
     219              :     integer :: i, irow
     220            1 :     call coo%group_by_1dim(ngroup, i1_list, istartend)
     221            1 :     call csr%initialize(coo%mshape)
     222            1 :     call csr%set(nnz=coo%nnz)
     223        67585 :     csr%icol(:)=coo%ind%data(2,1:coo%nnz)
     224        67585 :     csr%val(:) = coo%val%data(1:coo%nnz)
     225         1026 :     csr%row_shift(:)=0
     226         1025 :     row_nz(:)=0
     227         1025 :     do i=1, ngroup
     228         1024 :        irow=i1_list(i)
     229         1025 :        row_nz(irow) = istartend(i+1)-istartend(i)
     230              :     end do
     231              : 
     232            1 :     csr%row_shift(1)=1
     233         1025 :     do i=2, csr%nrow+1
     234         1025 :        csr%row_shift(i)= csr%row_shift(i-1)+row_nz(i-1)
     235              :     end do
     236            1 :     ABI_SFREE(i1_list)
     237            1 :     ABI_SFREE(istartend)
     238            1 :   end subroutine COO_to_CSR
     239              : 
     240              : 
     241              :   !-------------------------------------------------------------------!
     242              :   ! COO_to_dense
     243              :   !   COO matrix to dense matrix
     244              :   ! Input:
     245              :   !   COO: coo matrix
     246              :   ! Output:
     247              :   !   dense: dense matrix
     248              :   !-------------------------------------------------------------------!
     249            0 :   subroutine COO_to_dense(coo, dense)
     250              :     type(COO_mat_t), intent(inout) :: coo
     251              :     real(dp), intent(inout) :: dense(:,:)
     252              :     integer :: i, j, inz
     253              :     real(dp) :: val
     254            0 :     dense(:,:) =0.0
     255            0 :     do inz =1, coo%nnz
     256            0 :        i=coo%ind%data(1, inz)
     257            0 :        j=coo%ind%data(2, inz)
     258            0 :        val= coo%val%data(inz)
     259            0 :        dense(i,j) = dense(i,j) + val
     260              :     end do
     261            0 :   end subroutine COO_to_dense
     262              : 
     263              : 
     264              : !  subroutine LCO_to_CSR(lco, csr)
     265              : !    type(LCO_mat_t), intent(inout) :: lco
     266              : !    type(CSR_mat_t), intent(inout) :: csr
     267              : !    integer, allocatable :: i1_list(:), istartend(:)
     268              : !    integer :: row_nz(lco%mshape(1))
     269              : !    integer :: i, irow
     270              : !
     271              : !  end subroutine LCO_to_CSR
     272              : 
     273              : 
     274              : 
     275            0 :   subroutine spmat_convert_unittest()
     276              :     real(dp) ::mat(4,4), x(4), b(4)
     277            0 :     type(coo_mat_t) :: coo
     278            0 :     type(csr_mat_t) :: csr, csr2
     279              :     integer :: ngroup
     280            0 :     integer, allocatable :: i1list(:), ise(:)
     281            0 :     mat=reshape([1,2,0,0, 8, 3, 0,0, 0,2,0,0, 0,0,0,9], [4,4])*1.0d0
     282            0 :     call dense_to_coo(mat, coo)
     283            0 :     call coo%sum_duplicates()
     284            0 :     call dense_to_csr(mat, csr)
     285            0 :     call coo%group_by_1dim(ngroup, i1list, ise)
     286            0 :     call coo%sum_duplicates()
     287            0 :     ABI_SFREE(i1list)
     288            0 :     ABI_SFREE(ise)
     289            0 :     call coo_to_csr(coo, csr2)
     290              : 
     291            0 :     x=[1,2,3,4]
     292            0 :     b=matmul(mat, x)
     293            0 :     b=0
     294            0 :     call csr%mv(x, b)
     295            0 :     b=0
     296            0 :     call csr2%mv(x, b)
     297              : 
     298            0 :     b=0
     299            0 :     call csr2%mv(x, b)
     300              : 
     301              : 
     302              : 
     303            0 :     call coo%finalize()
     304            0 :     call csr%finalize()
     305            0 :     call csr2%finalize()
     306            0 :   end subroutine spmat_convert_unittest
     307              : 
     308              : 
     309              : end module m_spmat_convert
        

Generated by: LCOV version 2.3-1