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-09-21 22:40:37 Functions: 68.4 % 19 13

            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