LCOV - code coverage report
Current view: top level - src/78_effpot - m_spmat_NDCOO.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.6 % 217 164
Test Date: 2026-11-08 00:10:28 Functions: 68.4 % 19 13
Branches: 52.2 % 224 117

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_spmat_ndcoo
       2                 :             : !! NAME
       3                 :             : !! m_spmat_ndcoo
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module contains the a NDCOO (n-dimensional coordinate) format of sparse matrix.
       7                 :             : !! Datatypes:
       8                 :             : !!  NDCOO_mat_t: ND COO matrix
       9                 :             : !!
      10                 :             : !! Subroutines:
      11                 :             : !! TODO: add this when F2003 doc style is determined.
      12                 :             : !!
      13                 :             : !!
      14                 :             : !! COPYRIGHT
      15                 :             : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      16                 :             : !! This file is distributed under the terms of the
      17                 :             : !! GNU General Public License, see ~abinit/COPYING
      18                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      19                 :             : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      20                 :             : !!
      21                 :             : !! SOURCE
      22                 :             : 
      23                 :             : #if defined HAVE_CONFIG_H
      24                 :             : #include "config.h"
      25                 :             : #endif
      26                 :             : #include "abi_common.h"
      27                 :             : 
      28                 :             : module m_spmat_NDCOO
      29                 :             :   use defs_basis
      30                 :             :   use m_abicore
      31                 :             :   use m_errors
      32                 :             :   use m_xmpi
      33                 :             :   use m_spmat_base
      34                 :             :   use m_dynamic_array, only: int2d_array_type, real_array_type, int_array_type
      35                 :             :   implicit none
      36                 :             :   !!***
      37                 :             :   private
      38                 :             : 
      39                 :             :   !-----------------------------------------------------------------------
      40                 :             :   !> @brief NDCOO_mat_t : N-dimensional COO matrix type
      41                 :             :   !     The matrix is stored in two arrays, one for the indices, and
      42                 :             :   !     the other for the values.
      43                 :             :   !     e.g. a 3D matrix (M) with nnz non-zero entries will have an
      44                 :             :   !     (3,nnz) array as indices, and a (nnz) array value.
      45                 :             :   !     Both the index array and the value array are dynamic, so entries
      46                 :             :   !     can be appended.
      47                 :             :   !     let M be a 4*5*6 matrix,
      48                 :             :   !       M(1,2,3)=1.9, M(1,3,4)=2.4, M(...) =0
      49                 :             :   !     We'll have
      50                 :             :   !       ndim=3, nnz=2, mshape=[4,5,6]
      51                 :             :   !       ind = [ 1 2 3,
      52                 :             :   !               1 3 4 ]
      53                 :             :   !       val = [1.9, 2.4]
      54                 :             :   !       (ind and val are dynamic array.)
      55                 :             :   !-----------------------------------------------------------------------
      56                 :             :   type, public :: ndcoo_mat_t
      57                 :             :      integer :: ndim=0                  ! number of dimensions
      58                 :             :      integer :: nnz=0                   ! Number of (None-zero) entries.
      59                 :             :      integer, allocatable :: mshape(:)  ! the shape of the matrix. len(mshape)=ndim.
      60                 :             :      ! Note that it is not checked if the index by the shaped. If the shape for some
      61                 :             :      ! dimension is unkown, it can be set to -1.
      62                 :             :      type(int2d_array_type) :: ind      ! The index array
      63                 :             :      type(real_array_type) :: val       ! The value array
      64                 :             :      logical :: is_sorted = .False.     ! If the matrix is sorted by index
      65                 :             :      logical :: is_unique = .False.     ! If the matrix is made unique (no entry could have same index).
      66                 :             :      logical :: is_pair_grouped = .False. ! If the matrix entries are grouped by first two indices
      67                 :             :      type(int_array_type) :: pair_1list ! first index of the pair
      68                 :             :      type(int_array_type) :: pair_2list ! second index of the pair
      69                 :             :      type(int_array_type) :: pair_startend ! start and end matrix index of each group
      70                 :             : 
      71                 :             :    contains
      72                 :             :      procedure :: initialize
      73                 :             :      procedure :: finalize
      74                 :             :      procedure :: add_entry             ! add one entry
      75                 :             :      procedure :: remove_zeros          ! remove entries which are (or close to ) zero
      76                 :             :      procedure :: sort_indices          ! sort the matrix by indices
      77                 :             :      procedure :: sum_duplicates        ! remove duplicate indices by adding them up
      78                 :             :      procedure :: get_val_inz           ! get the z'th value.
      79                 :             :      procedure :: get_ind_inz           ! get the z'th indices.
      80                 :             :      procedure :: get_ind               ! get the indices for all in a dimension
      81                 :             :      procedure :: group_by_1dim         ! group the matrix by first dimension
      82                 :             :      procedure :: group_by_pair         ! group the matrix by first two dimensions
      83                 :             :      procedure :: mv1vec                ! multiply vector, return NDCOO entity with one dimension less
      84                 :             :      procedure :: mv2vec                ! multiply 2 vectors, return NDCOO entity with two dimensions less
      85                 :             :      procedure :: vec_product2d         ! multiply 2d matrix with one vector, return vector
      86                 :             :      procedure :: vec_product           ! multiply 3d matrix with two vectors, return vector
      87                 :             :      procedure :: vec_product4d         ! multiply 4d matrix with three vectors
      88                 :             :      !procedure :: print
      89                 :             :   end type ndcoo_mat_t
      90                 :             : 
      91                 :             :   public:: test_ndcoo
      92                 :             : contains
      93                 :             : 
      94                 :             :   !-------------------------------------------------------------------!
      95                 :             :   ! ndcoo_mat_t initializer:
      96                 :             :   ! Input:
      97                 :             :   !  mshape: the shape of the N-dimension matrix. array(ndim)
      98                 :             :   !-------------------------------------------------------------------!
      99         [ -  + ]:          27 :   subroutine initialize(self, mshape)
     100                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     101                 :             :     integer, intent(in) :: mshape(:)
     102                 :          27 :     self%ndim=size(mshape)
     103   [ -  +  +  -  :          81 :     ABI_MALLOC(self%mshape, (self%ndim))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     104   [ +  -  -  +  :         141 :     self%mshape=mshape
             -  -  +  + ]
     105                 :          27 :     self%nnz=0
     106                 :          27 :     self%is_sorted=.False.
     107                 :          27 :     self%is_unique=.False.
     108                 :          27 :     self%is_pair_grouped = .False.
     109                 :             : 
     110                 :          27 :   end subroutine initialize
     111                 :             : 
     112                 :             :   !-------------------------------------------------------------------!
     113                 :             :   ! Finalizer of ndcoo_mat_t
     114                 :             :   !-------------------------------------------------------------------!
     115                 :          38 :   subroutine finalize(self)
     116                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     117                 :          38 :     self%ndim=0
     118                 :          38 :     self%nnz=0
     119                 :          38 :     self%is_sorted=.False.
     120                 :          38 :     self%is_unique=.False.
     121         [ +  + ]:          38 :     if((self%is_pair_grouped)) then
     122                 :           2 :       call self%pair_1list%finalize()
     123                 :           2 :       call self%pair_2list%finalize()
     124                 :           2 :       call self%pair_startend%finalize()
     125                 :             :     endif
     126                 :          38 :     self%is_pair_grouped = .False.
     127                 :             : 
     128         [ +  + ]:          38 :     if (allocated(self%mshape)) then
     129                 :          27 :        ABI_FREE(self%mshape)
     130                 :             :     endif
     131                 :          38 :     call self%ind%finalize()
     132                 :          38 :     call self%val%finalize()
     133                 :          38 :   end subroutine finalize
     134                 :             : 
     135                 :             :   !-------------------------------------------------------------------!
     136                 :             :   ! Add one entry to the ndcoo_mat_t
     137                 :             :   ! Inputs:
     138                 :             :   !   ind: indices of the matrix.
     139                 :             :   !   val: value of matrix.
     140                 :             :   ! Example:
     141                 :             :   !  call m%add_entry([1,2,3], 0.5)
     142                 :             :   !-------------------------------------------------------------------!
     143                 :     2553449 :   subroutine add_entry(self, ind, val)
     144                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     145                 :             :     integer, intent(in) :: ind(self%ndim)
     146                 :             :     real(dp), intent(in) :: val
     147                 :     2553449 :     self%nnz=self%nnz+1
     148                 :     2553449 :     call self%ind%push(ind)
     149                 :     2553449 :     call self%val%push(val)
     150                 :     2553449 :     self%is_sorted=.False.
     151                 :     2553449 :     self%is_unique=.False.
     152                 :     2553449 :     self%is_pair_grouped=.False.
     153                 :     2553449 :   end subroutine add_entry
     154                 :             : 
     155                 :             : 
     156                 :             :   !-------------------------------------------------------------------!
     157                 :             :   ! sort the entries by indices. (left to right)
     158                 :             :   !-------------------------------------------------------------------!
     159                 :          12 :   subroutine sort_indices(self)
     160                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     161                 :          24 :     real(dp) :: tmp(self%nnz)
     162                 :           0 :     integer :: reorder(self%nnz)
     163   [ +  -  -  + ]:          12 :     if(self%is_sorted .or. self%nnz==0) return
     164                 :          12 :     call self%ind%sort(order=reorder)
     165         [ +  + ]:     1278504 :     tmp(:)=self%val%data(1:self%nnz)
     166         [ +  + ]:     1278504 :     self%val%data(1:self%nnz)=tmp(reorder)
     167                 :          12 :     self%is_sorted=.True.
     168                 :          12 :   end subroutine sort_indices
     169                 :             : 
     170                 :             : 
     171                 :             :   !-------------------------------------------------------------------!
     172                 :             :   ! Remove zero entries in coo matrix.
     173                 :             :   !  zero means abs(x)<eps
     174                 :             :   !-------------------------------------------------------------------!
     175                 :          15 :   subroutine remove_zeros(self, eps)
     176                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     177                 :             :     real(dp), optional, intent(in) :: eps
     178                 :             :     real(dp) :: eps1
     179                 :             :     integer :: i, counter
     180                 :             :     if (present(eps)) then
     181                 :             :        eps1=eps
     182                 :             :     else
     183                 :             :        eps1=epsilon(1.0_dp)
     184                 :             :     end if
     185                 :          15 :     counter=0
     186         [ +  + ]:     1330623 :     do i=1, self%nnz
     187         [ +  + ]:     1330623 :        if (abs(self%val%data(i))> epsilon(1.0)) then
     188                 :     1283640 :           counter=counter+1
     189         [ +  + ]:     5206800 :           self%ind%data(:,counter) =self%ind%data(:, i)
     190                 :     1283640 :           self%val%data(counter) = self%val%data(i)
     191                 :             :        end if
     192                 :             :     end do
     193                 :          15 :     self%nnz=counter
     194                 :          15 :     self%ind%size=counter
     195                 :          15 :     self%val%size=counter
     196                 :          15 :   end subroutine remove_zeros
     197                 :             : 
     198                 :             :   !-------------------------------------------------------------------!
     199                 :             :   ! sum duplicate entries (also sort by indices)
     200                 :             :   !-------------------------------------------------------------------!
     201                 :          15 :   subroutine sum_duplicates(self)
     202                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     203                 :          30 :     integer :: new_ind(self%ndim, self%nnz), i, counter
     204                 :          30 :     real(dp) :: new_val(self%nnz)
     205         [ -  + ]:          15 :     if (self%nnz==0) then
     206                 :           0 :        self%is_unique=.True.
     207                 :             :        return
     208                 :             :     end if
     209                 :          15 :     call self%remove_zeros()
     210         [ +  + ]:          15 :     if (.not. self%is_sorted) then
     211                 :          12 :        call self%sort_indices()
     212                 :             :     end if
     213                 :          15 :     counter=1
     214         [ +  + ]:          80 :     new_ind(:, counter)= self%ind%data(:, 1)
     215                 :          15 :     new_val(counter)=self%val%data(1)
     216         [ +  + ]:     1283640 :     do i=2, self%nnz
     217   [ +  +  +  +  :     3879670 :        if (all(self%ind%data(:, i)==self%ind%data(:, i-1))) then
                   +  + ]
     218                 :       19440 :           new_val(counter)=new_val(counter)+self%val%data(i)
     219                 :             :        else
     220                 :     1264185 :           counter=counter+1
     221         [ +  + ]:     5148400 :           new_ind(:, counter)= self%ind%data(:, i)
     222                 :     1264185 :           new_val(counter)=self%val%data(i)
     223                 :             :        end if
     224                 :             :     end do
     225                 :          15 :     self%nnz=counter
     226   [ +  +  +  + ]:     5148495 :     self%ind%data(:,1:counter)=new_ind(:,1:counter)
     227         [ +  + ]:     1264215 :     self%val%data(1:counter)=new_val(1:counter)
     228                 :          15 :     self%ind%size=self%nnz
     229                 :          15 :     self%val%size=self%nnz
     230                 :          15 :     self%is_unique=.True.
     231                 :          15 :   end subroutine sum_duplicates
     232                 :             : 
     233                 :             :   !-------------------------------------------------------------------!
     234                 :             :   ! Get the i'th value of the matrix.
     235                 :             :   !-------------------------------------------------------------------!
     236                 :           0 :   function get_val_inz(self, i) result(v)
     237                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     238                 :             :     integer, intent(in) :: i
     239                 :             :     real(dp) :: v
     240                 :           0 :     v= self%val%data(i)
     241                 :           0 :   end function get_val_inz
     242                 :             : 
     243                 :             : 
     244                 :             :   !-------------------------------------------------------------------!
     245                 :             :   ! get all the indices for the ith entry
     246                 :             :   ! Input:
     247                 :             :   !  i: ith entry
     248                 :             :   ! Return:
     249                 :             :   !  a integer array of indices.
     250                 :             :   !-------------------------------------------------------------------!
     251         [ -  + ]:        5304 :   function get_ind_inz(self, i) result(ind)
     252                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     253                 :             :     integer, intent(in) :: i
     254                 :             :     integer :: ind(self%ndim)
     255         [ +  + ]:       32160 :     ind(:)=self%ind%data(:,i)
     256                 :        5304 :   end function get_ind_inz
     257                 :             : 
     258                 :             :   !-------------------------------------------------------------------!
     259                 :             :   ! Group the sparse matrix by the first dimension
     260                 :             :   !> Output:
     261                 :             :   !> ngroup: number of groups
     262                 :             :   !> i1_list: list of 1st indices (array(ngroup))
     263                 :             :   !> istartend: start and end of each group (array(ngroup+1))
     264                 :             :   !>           The starts will be istartend(1:ngroup)
     265                 :             :   !>           The ends will be istartend(2: ngroup+1)-1
     266                 :             :   !-------------------------------------------------------------------!
     267                 :           3 :   subroutine group_by_1dim(self, ngroup, i1_list, istartend)
     268                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     269                 :             :     integer,            intent(inout) :: ngroup
     270                 :             :     integer, allocatable, intent(inout) :: i1_list(:), istartend(:)
     271                 :             : 
     272                 :             :     integer :: i, ii
     273                 :           3 :     type(int_array_type) :: j1, jstartend
     274                 :             : 
     275         [ +  - ]:           3 :     if (.not. (self%is_unique))  then
     276                 :           3 :       call self%sum_duplicates()
     277                 :             :     end if
     278         [ +  - ]:           3 :     if (self%nnz<1) then
     279                 :             :       ngroup=0
     280         [ -  + ]:           3 :     else if (self%nnz==1) then
     281                 :           0 :       i=1
     282                 :           0 :       ii=self%ind%data(1,i)
     283                 :           0 :       call j1%push(ii)
     284                 :           0 :       call jstartend%push(1)
     285                 :           0 :       call jstartend%push(2)
     286                 :             :     else
     287                 :           3 :       i=1
     288                 :           3 :       ii=self%ind%data(1,i)
     289                 :           3 :       call j1%push(ii)
     290                 :           3 :       call jstartend%push(i)
     291         [ +  + ]:     1109568 :       do i=2, self%nnz
     292                 :     1109565 :         ii=self%ind%data(1,i)
     293         [ +  + ]:     1109568 :         if(ii == self%ind%data(1, i-1)) then
     294                 :             :           cycle
     295                 :             :         else
     296                 :        2317 :           call j1%push(ii)
     297                 :     1109565 :           call jstartend%push(i)
     298                 :             :         end if
     299                 :             :       end do
     300                 :           3 :       call jstartend%push(self%nnz+1)
     301                 :             :     end if
     302                 :           3 :     ngroup=j1%size
     303         [ +  - ]:           3 :     if(ngroup>0) then
     304   [ -  +  +  -  :           9 :       ABI_MALLOC(i1_list, (ngroup))
          +  -  -  +  -  
                +  -  + ]
     305   [ -  +  +  -  :           9 :       ABI_MALLOC(istartend, (ngroup+1))
          +  -  -  +  -  
                +  -  + ]
     306         [ +  + ]:        2323 :       i1_list(:)=j1%data(1: j1%size)
     307         [ +  + ]:        2326 :       istartend(:)=jstartend%data(1: jstartend%size)
     308                 :             :     end if
     309                 :           3 :     call j1%finalize()
     310                 :           3 :     call jstartend%finalize()
     311   [ -  +  -  + ]:           3 :   end subroutine group_by_1dim
     312                 :             : 
     313                 :             :   !-------------------------------------------------------------------!
     314                 :             :   ! Group the sparse matrix by first two indices
     315                 :             :   !> Output:
     316                 :             :   !> ngroup: number of groups
     317                 :             :   !> ilist: list of one index of the pair (array(ngroup))
     318                 :             :   !> jlist: list of other index of the pair (array(ngroup))
     319                 :             :   !> ijstartend: start and end of each group (array(ngroup+1))
     320                 :             :   !>           The starts will be ijstartend(1:ngroup)
     321                 :             :   !>           The ends will be ijstartend(2: ngroup+1)-1
     322                 :             :   !-------------------------------------------------------------------!
     323                 :             : 
     324                 :           2 :   subroutine group_by_pair(self)
     325                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     326                 :             : 
     327                 :             :     integer :: i, ii, ij
     328                 :             : !    type(int_array_type) :: i1, j1, startend
     329                 :             : 
     330         [ -  + ]:           2 :     if((self%is_pair_grouped)) return
     331                 :             : 
     332         [ +  - ]:           2 :     if (.not. (self%is_unique))  then
     333                 :           2 :       call self%sum_duplicates()
     334                 :             :     end if
     335         [ +  - ]:           2 :     if (self%nnz<1) then
     336                 :             : 
     337         [ -  + ]:           2 :     else if (self%nnz==1) then
     338                 :             :       i=1
     339                 :           0 :       ii=self%ind%data(1,i)
     340                 :           0 :       ij=self%ind%data(2,i)
     341                 :           0 :       call self%pair_1list%push(ii)
     342                 :           0 :       call self%pair_2list%push(ij)
     343                 :           0 :       call self%pair_startend%push(1)
     344                 :           0 :       call self%pair_startend%push(2)
     345                 :             :     else
     346                 :           2 :       i=1
     347                 :           2 :       ii=self%ind%data(1,i)
     348                 :           2 :       ij=self%ind%data(2,i)
     349                 :           2 :       call self%pair_1list%push(ii)
     350                 :           2 :       call self%pair_2list%push(ij)
     351                 :           2 :       call self%pair_startend%push(i)
     352         [ +  + ]:      139968 :       do i=2, self%nnz
     353                 :      139966 :         ii=self%ind%data(1,i)
     354                 :      139966 :         ij=self%ind%data(2,i)
     355   [ +  +  +  + ]:      139968 :         if(ii == self%ind%data(1, i-1) .and. ij == self%ind%data(2, i-1)) then
     356                 :             :           cycle
     357                 :             :         else
     358                 :        7774 :           call self%pair_1list%push(ii)
     359                 :        7774 :           call self%pair_2list%push(ij)
     360                 :        7774 :           call self%pair_startend%push(i)
     361                 :             :         end if
     362                 :             :       end do
     363                 :           2 :       call self%pair_startend%push(self%nnz+1)
     364                 :             :     end if
     365                 :             : 
     366                 :           2 :     self%is_pair_grouped = .true.
     367                 :             : 
     368                 :             :   end subroutine group_by_pair
     369                 :             : 
     370                 :             : 
     371                 :             :   !-------------------------------------------------------------------!
     372                 :             :   ! Get the indices of the dim'th dimension
     373                 :             :   ! Input:
     374                 :             :   !   dim: dimension
     375                 :             :   ! Returns:
     376                 :             :   !   a integer array(nnz)
     377                 :             :   !-------------------------------------------------------------------!
     378         [ #  # ]:           0 :   function get_ind(self, dim) result(ilist)
     379                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     380                 :             :     integer, intent(in) :: dim
     381                 :             :     integer :: ilist(self%nnz)
     382         [ #  # ]:           0 :     ilist(:)=self%ind%data(dim, 1:self%nnz)
     383                 :           0 :   end function get_ind
     384                 :             : 
     385                 :             : 
     386                 :             :   ! matrix vector product
     387         [ #  # ]:           0 :   subroutine mv1vec(self, vec, iv, res)
     388                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     389                 :             :     real(dp),           intent(in)    :: vec(:)
     390                 :             :     integer,            intent(in)    :: iv  ! which index is used for multiplication
     391                 :             :     class(ndcoo_mat_t), intent(inout) :: res ! result
     392                 :             : 
     393                 :             :     integer :: iind, iiv, j, jv
     394                 :           0 :     integer :: ind(1:res%ndim)
     395                 :             :     real(dp) :: val
     396                 :             : 
     397         [ #  # ]:           0 :     if(self%ndim .ne. res%ndim+1) then
     398                 :           0 :       ABI_ERROR('Dimension of resulting matrix is not equal to (dimension of initial matrix -1)')
     399                 :             :     endif
     400                 :             : 
     401         [ #  # ]:           0 :     do iind =1 , self%nnz
     402                 :           0 :       iiv=self%ind%data(iv, iind)
     403                 :           0 :       jv=0
     404         [ #  # ]:           0 :       do j=1, self%ndim
     405         [ #  # ]:           0 :         if(j.ne.iv) then
     406                 :           0 :           jv=jv+1
     407                 :           0 :           ind(jv) = self%ind%data(j, iind)
     408                 :             :         endif
     409                 :             :       enddo
     410                 :           0 :       val = self%val%data(iind)*vec(iiv)
     411                 :           0 :       call res%add_entry(ind, val)
     412                 :             :     end do
     413                 :             : 
     414                 :           0 :     call sum_duplicates(res)
     415                 :             : 
     416                 :           0 :   end subroutine mv1vec
     417                 :             : 
     418                 :             : 
     419   [ -  +  -  + ]:           1 :   subroutine mv2vec(self, veci, vecj, iv, jv, res)
     420                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     421                 :             :     real(dp),           intent(in)    :: veci(:), vecj(:) ! vectors to be multiplied with
     422                 :             :     integer,            intent(in)    :: iv, jv  ! which indices are used for multiplication
     423                 :             :     class(ndcoo_mat_t), intent(inout) :: res ! result
     424                 :             : 
     425                 :             :     integer :: iind, iiv, ijv, jnew, j
     426                 :           2 :     integer :: ind(1:res%ndim)
     427                 :             :     real(dp) :: val
     428                 :             : 
     429         [ -  + ]:           1 :     if(self%ndim .ne. res%ndim+2) then
     430                 :           0 :       ABI_ERROR('Dimension of resulting matrix is not equal to (dimension of initial matrix -2)')
     431                 :             :     endif
     432         [ +  + ]:       69985 :     do iind =1 , self%nnz
     433                 :       69984 :       iiv=self%ind%data(iv, iind)
     434                 :       69984 :       ijv=self%ind%data(jv, iind)
     435                 :       69984 :       jnew=0
     436         [ +  + ]:      349920 :       do j=1, self%ndim
     437   [ +  +  +  + ]:      349920 :         if(j.ne.iv .and. j.ne.jv) then
     438                 :      139968 :           jnew=jnew+1
     439                 :      139968 :           ind(jnew) = self%ind%data(j, iind)
     440                 :             :         endif
     441                 :             :       enddo
     442                 :       69984 :       val = self%val%data(iind)*veci(iiv)*vecj(ijv)
     443                 :       69985 :       call res%add_entry(ind, val)
     444                 :             :     end do
     445                 :           1 :     call sum_duplicates(res)
     446                 :             : 
     447                 :           1 :   end subroutine mv2vec
     448                 :             : 
     449                 :             : 
     450   [ -  +  -  + ]:        4004 :   subroutine vec_product2d(self, iv, veci, rv, res)
     451                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     452                 :             :     real(dp), intent(in) :: veci(:)
     453                 :             :     integer ,intent(in) :: iv, rv               !
     454                 :             :     real(dp), intent(inout) :: res(:)
     455                 :             :     integer :: iind, iiv, irv
     456         [ +  + ]:    15571556 :     do iind =1 , self%nnz
     457                 :    15567552 :       iiv=self%ind%data(iv, iind)
     458                 :    15567552 :       irv=self%ind%data(rv, iind)
     459                 :    15571556 :       res(irv) = res(irv) + self%val%data(iind) * veci(iiv)
     460                 :             :     end do
     461                 :        4004 :   end subroutine vec_product2d
     462                 :             : 
     463                 :             : 
     464                 :             : 
     465                 :             :   ! matrix vector vector  product. matrix should be dim3.
     466                 :             :   ! n(vector)=ndim-1
     467                 :             :   ! which returns a vecor
     468                 :             :   ! res_r = \sum_ij M_{ijr} V_i V_j
     469                 :             :   ! i, j, r can be in any order.
     470   [ -  +  -  +  :       12014 :   subroutine vec_product(self, iv, veci, jv, vecj, rv, res)
                   -  + ]
     471                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     472                 :             :     real(dp), intent(in) :: veci(:), vecj(:)
     473                 :             :     integer ,intent(in) :: iv, jv, rv               !
     474                 :             :     real(dp), intent(inout) :: res(:)
     475                 :             :     integer :: iind, iiv, ijv, irv
     476         [ +  + ]:  6259209902 :     do iind =1 , self%nnz
     477                 :  6259197888 :       iiv=self%ind%data(iv, iind)
     478                 :  6259197888 :       ijv=self%ind%data(jv, iind)
     479                 :  6259197888 :       irv=self%ind%data(rv, iind)
     480                 :  6259209902 :       res(irv) = res(irv) + self%val%data(iind) * veci(iiv)*vecj(ijv)
     481                 :             :     end do
     482                 :       12014 :   end subroutine vec_product
     483                 :             : 
     484                 :             : 
     485                 :             :   ! matrix vector vector vector product. matrix should be dim4.
     486                 :             :   ! n(vector)=ndim-1
     487                 :             :   ! which returns a vecor
     488                 :             :   ! res_r = \sum_ijk M_{ijkr} V_i V_j V_k
     489                 :             :   ! i, j, k, r can be in any order.
     490   [ -  +  -  +  :        6006 :   subroutine vec_product4d(self, veci, vecj, kv, veck, rv, res)
             -  +  -  + ]
     491                 :             :     class(ndcoo_mat_t), intent(inout) :: self
     492                 :             :     real(dp), intent(in) :: veci(:), vecj(:), veck(:)
     493                 :             :     integer ,intent(in) :: kv, rv
     494                 :             :     real(dp), intent(inout) :: res(:)
     495                 :             : 
     496                 :             :     integer :: iind, iiv, ijv, ikv, irv, igroup, istart, iend
     497                 :             :     real(dp) :: scalprod
     498                 :             : 
     499         [ -  + ]:        6006 :     if(.not.(self%is_pair_grouped)) then
     500                 :           0 :       call self%group_by_pair()
     501                 :             :     endif
     502                 :             : 
     503         [ +  + ]:    23357334 :     do igroup = 1, self%pair_1list%size
     504                 :             :       !precalculate scalar product of first and second columns for each group
     505                 :    23351328 :       istart=self%pair_startend%data(igroup)
     506                 :    23351328 :       iend=self%pair_startend%data(igroup+1)-1
     507                 :    23351328 :       iiv=self%pair_1list%data(igroup)
     508                 :    23351328 :       ijv=self%pair_2list%data(igroup)
     509                 :    23351328 :       scalprod=veci(iiv)*vecj(ijv)
     510         [ +  + ]:   443681238 :       do iind=istart, iend
     511                 :   420323904 :         ikv=self%ind%data(kv, iind)
     512                 :   420323904 :         irv=self%ind%data(rv, iind)
     513                 :   443675232 :         res(irv) = res(irv) + self%val%data(iind) * veck(ikv)* scalprod
     514                 :             :       end do
     515                 :             :     enddo
     516                 :        6006 :   end subroutine vec_product4d
     517                 :             : 
     518                 :             : 
     519                 :             : 
     520                 :           0 :   subroutine test_ndcoo()
     521                 :           0 :     type(ndcoo_mat_t) :: m
     522                 :             :     integer :: ngroup
     523                 :           0 :     integer, allocatable :: i1list(:), ise(:)
     524                 :           0 :     call m%initialize(mshape=[3,3,3])
     525                 :           0 :     call m%add_entry(ind=[3, 2,1], val=0.3d0)
     526                 :           0 :     call m%add_entry(ind=[1, 2,1], val=0.3d0)
     527                 :           0 :     call m%add_entry(ind=[1, 2,1], val=0.4d0)
     528                 :           0 :     call m%add_entry(ind=[3, 2,1], val=0.5d0)
     529                 :           0 :     call m%add_entry(ind=[1, 1,2], val=0.5d0)
     530                 :           0 :     call m%add_entry(ind=[2,5,1], val=0.0d0)
     531                 :             :     !call m%print()
     532                 :           0 :     call m%sort_indices()
     533                 :           0 :     call m%sum_duplicates()
     534                 :             :     !print *, "After sum"
     535                 :             :     !call m%print()
     536                 :             :     !print *, "Grouping"
     537                 :           0 :     call m%group_by_1dim(ngroup, i1list, ise)
     538                 :             :     !print *,  "ngroup: ", ngroup
     539                 :             :     !print *, "i1list: ", i1list
     540                 :             :     !print *, "ise: ", ise
     541         [ #  # ]:           0 :     ABI_SFREE(i1list)
     542         [ #  # ]:           0 :     ABI_SFREE(ise)
     543   [ #  #  #  #  :           0 :   end subroutine test_ndcoo
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     544                 :             : 
     545   [ #  #  #  #  :           0 : end module m_spmat_NDCOO
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     546                 :             : 
        

Generated by: LCOV version 2.3-1