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 : :
|