Eötvös Quantum Utilities  v4.9.146
Providing the Horsepowers in the Quantum Realm
getPartialInv.F90
Go to the documentation of this file.
1 !======================================================================
2 ! Module to calculate the partial inverse of a real/complex sparse matrix via the PARDISO libraries.
3 ! This file is part of the EQuUs package. (for details see: http://eqt.elte.hu/equus/home)
4 ! Copyright (C) 2016 Peter Rakyta, Ph.D.
5 !
6 ! This program is free software: you can redistribute it and/or modify
7 ! it under the terms of the GNU General Public License as published by
8 ! the Free Software Foundation, either version 3 of the License, or
9 ! (at your option) any later version.
10 !
11 ! This program is distributed in the hope that it will be useful,
12 ! but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ! GNU General Public License for more details.
15 !
16 ! You should have received a copy of the GNU General Public License
17 ! along with this program. If not, see http://www.gnu.org/licenses/.
18 !
19 !======================================================================
23 ! MODULE getPartialInv
26 
27 #ifndef MAXNRHS
28 #define MAXNRHS 100
29 #endif
30 
31 #ifndef MAXMEM
32 #define MAXMEM 16000000 !In kilobytes
33 #endif
34 
35 !****************************************************************
36  CONTAINS
37 !****************************************************************
38 
39 ! DESCRIPTION:
49 #ifdef MIC
50 !dir$ attributes offload:mic :: dgetPartialInv
51 #endif
52  subroutine dgetpartialinv(sizeA, nonzerosA, a, ia, ja, sizeInv, invA, error)
53  use mkl_pardiso
54  use mkl_service
55 
56  IMPLICIT NONE
57 
58 
59 ! Internal solver memory pointer
60  TYPE(mkl_pardiso_handle), pointer :: PT(:) => null()
61  integer*4, pointer :: idum(:) => null(), pia(:) => null(), pja(:) => null()
62  real(KIND=8), pointer :: ddum(:) => null(), pa(:) => null(), pb(:,:) => null(), px(:,:) => null()
63  INTEGER*4 maxfct, mnum, mtype, phase, nrhs, error, msglvl, i, nnz, numIterations, idxIterations, offset
64  INTEGER*4 iparm(64)
65 
66 
67 ! The matrix is given in the CSR format A = (a, ia, ja)
68  INTEGER*4 sizeA, nonzerosA !matrix A is of size sizeA x sizeA
69  INTEGER*4, TARGET :: ia(sizeA+1), ja(nonzerosA)
70  real*8, TARGET :: a(nonzerosa)
71 
72  INTEGER*4, ALLOCATABLE :: perm(:)
73 
74  INTEGER*4 sizeInv !size of the inverse matrix
75  real*8 :: inva(sizeinv,sizeinv)
76 
77  INTEGER*4 idx, jdx
78  integer maxmem
79 
80  DATA nrhs /1/, maxfct /1/, mnum /1/
81  allocate( pt(64), idum(0), ddum(0) )
82 
83  do i = 1, 64
84  pt(i)%DUMMY = 0
85  end do
86  pa => a
87  pia => ia
88  pja => ja
89 ! initialize error flag
90  error = 0
91 
92 #ifdef DEBUG
93  write(0,*)
94  write(0,*) 'The input matrix: (getPartialInv)'
95  idx = 0
96  do jdx = 1, nonzerosa
97  if (jdx >= ia(idx+1)) then
98  idx=idx+1
99  end if
100 
101  if (jdx < ia(idx+1)) then
102  !write(0,*) 'row', idx, 'col', ja(jdx), 'element of a = ', a(jdx)
103  end if
104  end do
105  write(0,*) 'The size of the Partial inverse to be calculated:', sizeinv
106 #endif
107 
108 !
109 ! .. Setup Pardiso control parameters und initialize the solvers
110 ! internal adress pointers. This is only necessary for the FIRST
111 ! call of the PARDISO solver.
112 !
113 ! choose the matrix type for pardiso factorization
114  mtype = 1 ! structurally symmetric real matrix
115 
116 ! .. PARDISO license check and initialize solver
117  call pardisoinit(pt, mtype, iparm)
118 
119 
120 
121 
122 
123 ! Reordering and Factorization, This step also allocates
124 ! all memory that is necessary for the factorization
125 #ifdef DEBUG
126  msglvl = 1 ! with statistical information
127  iparm(27) = 1 ! perform matrix check
128 #else
129  msglvl = 0 ! without statistical information
130  iparm(27) = 0 ! perform matrix check
131 #endif
132  iparm(6) = 0 ! The solution is written into x
133  iparm(28) = 0 ! double real/complex
134 
135 #ifdef MIC
136  iparm(2) = 3 ! parallel OpenMP version of the nested dissection
137  iparm(24) = 1 ! Intel MKL PARDISO uses a two-level factorization algorithm
138  iparm(25) = 0 ! Intel MKL PARDISO uses a parallel algorithm for the solve step.
139  iparm(34) = 0 !
140  iparm(60) = 0 ! in-core (IC) mode
141 #else
142  iparm(2) = 2 !
143  iparm(24) = 0 ! Intel MKL PARDISO uses a single-level factorization algorithm
144  iparm(25) = 0 ! Intel MKL PARDISO uses a parallel algorithm for the solve step.
145  iparm(34) = 0 !
146  iparm(60) = 0 ! in-core (IC) mode
147 #endif
148 
149  phase = 11 ! analysis
150 
151  ! setting the appropriate number of right hand sides.
152 #ifdef MIC
153  nrhs = maxnrhs
154  if (nrhs.GT.sizeinv) then
155  nrhs = sizeinv
156  end if
157 #else
158  nrhs = 1
159 #endif
160 
161 #ifdef DEBUG
162  write(0,*) 'number of right sides: ', nrhs
163 #endif
164 
165  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, pa, pia, pja, &
166  idum, nrhs, iparm, msglvl, ddum, ddum, error)
167  maxmem = (iparm(16)+iparm(17))
168 
169 #ifdef DEBUG
170  write(0,*) 'maxmem: ', maxmem, ' kbytes'
171  write(0,*) 'maxmem total: ', maxmem+sizea*nrhs*16/1000, ' kbytes'
172 #endif
173 
174  IF ((maxmem+sizea*nrhs*16/1000).GT.maxmem) then
175  nrhs = floor(real(maxmem-maxmem)/real(sizea*16)*1000)
176  write(0,*) 'number of right sides: ', nrhs
177  IF (nrhs.EQ.0) THEN
178  error = -2
179  RETURN
180  ENDIF
181  ENDIF
182 
183  phase = 22 ! factorization
184  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, pa, pia, pja, &
185  idum, nrhs, iparm, msglvl, ddum, ddum, error)
186 
187 #ifdef DEBUG
188  write(0,*) 'Reordering and factorization completed ... '
189 #endif
190  IF (error .NE. 0) THEN
191  write(0,*) 'The following ERROR was detected at the factorization step: ', error
192  RETURN
193  ENDIF
194 
195 
196 
197 ! Set parameters to calculate only the last sizeInv components of the solution
198  iparm(31) = 3
199  phase = 33 ! solver
200  allocate( perm(sizea) )
201  perm = 0
202  do idx = 1, sizeinv
203  perm(sizea-sizeinv+idx) = 1
204  end do
205 
206 ! Calculating the chunk of the solution to be calculated at once
207  if (modulo(sizeinv, nrhs).EQ.0) then
208  numiterations = sizeinv/nrhs
209  else
210  numiterations = floor(real(sizeinv)/real(nrhs)) + 1
211  end if
212 
213 #ifdef DEBUG
214  write(0,*) 'Number of iterations to obtain the right solutions ', numiterations
215 #endif
216 
217 
218 
219 
220 ! Allocating the right hand side
221  allocate( pb(sizea, nrhs) )
222  allocate( px(sizea, nrhs) )
223 
224  do idxiterations = 1, numiterations
225 
226  offset = (idxiterations-1)*nrhs
227 
228  if ((sizeinv-offset).LT.nrhs) then
229  nrhs = sizeinv-offset
230  deallocate(pb, px)
231  allocate( pb(sizea, nrhs) )
232  allocate( px(sizea, nrhs) )
233  end if
234 
235  if ((sizeinv-offset).LT.nrhs) then
236  nrhs = sizeinv-offset
237  end if
238 
239 ! Creating the right hand side
240  pb = 0.d0
241  px = 0.d0
242  do idx = 1, nrhs
243  pb(sizea-sizeinv+offset+idx, idx) = 1.d0
244  end do
245 ! Solver
246  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, pa, pia, pja, &
247  perm, nrhs, iparm, msglvl, pb, px, error)
248 
249  IF (error .NE. 0) THEN
250  exit
251  ENDIF
252 
253 
254  do idx = 1, nrhs
255  do jdx = 1,sizeinv
256  inva(offset+idx,jdx) = px(sizea-sizeinv+jdx, idx)
257  end do
258  end do
259 
260  end do
261 
262  deallocate(pb, px, perm)
263 
264 
265  IF (error .NE. 0) THEN
266  write(0,*) 'The following ERROR was detected at the solution step: ', error
267  RETURN
268  ENDIF
269 
270 
271 #ifdef DEBUG
272  do idx = 1,sizeinv
273  do jdx = 1,sizeinv
274  write(0,*) 'row', idx, 'col', jdx, 'element of a = ', inva(jdx, idx)
275  end do
276  end do
277 #endif
278 
279 
280 
281 !
282 ! Termination and release of memory
283  phase = -1 ! release internal memory
284  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, ddum, &
285  idum, idum, &
286  idum, nrhs, iparm, msglvl, ddum, ddum, error)
287 
288  deallocate(idum, ddum, pt)
289 
290  IF (error .NE. 0) THEN
291  write(0,*) 'The following ERROR was detected at releasing the memory: ', error
292  RETURN
293  ENDIF
294 
295 
296  end
297 
298 
299 
300 ! DESCRIPTION:
311 #ifdef MIC
312 !dir$ attributes offload:mic :: zgetPartialInv
313 #endif
314  subroutine zgetpartialinv(sizeA, nonzerosA, a, ia, ja, sizeInv, real_invA, imag_invA, error)
316  use mkl_pardiso
317 
318  IMPLICIT NONE
319 
320 ! Internal solver memory pointer
321  TYPE(mkl_pardiso_handle), pointer :: PT(:) => null()
322  integer*4, pointer :: idum(:) => null(), pia(:) => null(), pja(:) => null()
323  complex(KIND=8), pointer :: ddum(:) => null(), pa(:) => null(), pb(:,:) => null(), px(:,:) => null()
324  INTEGER*4 maxfct, mnum, mtype, phase, nrhs, error, msglvl, nnz, numIterations, idxIterations, offset
325  INTEGER*4 iparm(64)
326 
327 
328 ! The matrix is given in the CSR format A = (a, ia, ja)
329  INTEGER*4 sizeA, nonzerosA !matrix A is of size sizeA x sizeA
330  INTEGER*4, TARGET :: ia(sizeA+1), ja(nonzerosA)
331  COMPLEX*16, TARGET :: a(nonzerosA)
332 
333  INTEGER*4, ALLOCATABLE :: perm(:)
334 
335  INTEGER*4 sizeInv !size of the inverse matrix
336  real*8 :: real_inva(sizeinv,sizeinv)
337  real*8 :: imag_inva(sizeinv,sizeinv)
338 
339  INTEGER*4 idx, jdx, maxmem
340 
341 
342 
343  DATA maxfct /1/, mnum /1/
344  allocate( pt(64), idum(0), ddum(0) )
345 
346  do idx = 1, 64
347  pt(idx)%DUMMY = 0
348  end do
349  pa => a
350  pia => ia
351  pja => ja
352 ! initialize error flag
353  error = 0
354 
355 
356 #ifdef DEBUG
357  write(0,*)
358  write(0,*) 'The input matrix: (getPartialInv)'
359  idx = 0
360  do jdx = 1, nonzerosa
361  if (jdx >= ia(idx+1)) then
362  idx=idx+1
363  end if
364 
365  if (jdx < ia(idx+1)) then
366  !write(0,*) 'row', idx, 'col', ja(jdx), 'element of a = ', a(jdx)
367  end if
368  end do
369  write(0,*) 'The size of the partial inverse to be calculated:', sizeinv
370 #endif
371 
372 !
373 ! .. Setup Pardiso control parameters und initialize the solvers
374 ! internal adress pointers. This is only necessary for the FIRST
375 ! call of the PARDISO solver.
376 !
377 ! choose the matrix type for pardiso factorization
378  mtype = 3 ! structurally symmetric complex matrix
379 
380 ! .. PARDISO license check and initialize solver
381  call pardisoinit(pt, mtype, iparm)
382 
383 
384 
385 
386 ! Reordering and Factorization, This step also allocates
387 ! all memory that is necessary for the factorization
388 #ifdef DEBUG
389  msglvl = 1 ! with statistical information
390  iparm(27) = 1 ! perform matrix check
391 #else
392  msglvl = 0 ! without statistical information
393  iparm(27) = 0 ! perform matrix check
394 #endif
395  iparm(6) = 0 ! The solution is written into x
396  iparm(28) = 0 ! double real/complex
397 
398 #ifdef MIC
399  iparm(2) = 3 ! parallel OpenMP version of the nested dissection
400  iparm(24) = 1 ! Intel MKL PARDISO uses a two-level factorization algorithm
401  iparm(25) = 0 ! Intel MKL PARDISO uses a parallel algorithm for the solve step.
402  iparm(34) = 0 !
403  iparm(60) = 0 ! in-core (IC) mode
404 #else
405  iparm(2) = 2 ! parallel OpenMP version of the nested dissection
406  iparm(24) = 0 ! Intel MKL PARDISO uses a two-level factorization algorithm
407  iparm(25) = 0 ! Intel MKL PARDISO uses a parallel algorithm for the solve step.
408  iparm(34) = 0 !
409  iparm(60) = 0 ! in-core (IC) mode
410 #endif
411 
412  phase = 11 ! Analysis
413 
414  ! setting the appropriate number of right hand sides.
415 #ifdef MIC
416  nrhs = maxnrhs
417  if (nrhs.GT.sizeinv) then
418  nrhs = sizeinv
419  end if
420 #else
421  nrhs = 1
422 #endif
423 
424 #ifdef DEBUG
425  write(0,*) 'number of right sides: ', nrhs
426 #endif
427 
428 
429 
430  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, pa, pia, pja, &
431  idum, nrhs, iparm, msglvl, ddum, ddum, error)
432  maxmem = (iparm(16)+iparm(17))
433 
434 #ifdef DEBUG
435  write(0,*) 'maxmem: ', maxmem, ' kbytes'
436  write(0,*) 'maxmem total: ', maxmem+sizea*nrhs*32/1000, ' kbytes'
437 #endif
438 
439  IF ((maxmem+sizea*nrhs*32/1000).GT.maxmem) then
440  nrhs = floor(real(maxmem-maxmem)/real(sizea*32)*1000)
441  write(0,*) 'number of right sides: ', nrhs
442  IF (nrhs.EQ.0) THEN
443  error = -2
444  RETURN
445  ENDIF
446  ENDIF
447 
448  phase = 22 ! factorization
449  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, pa, pia, pja, &
450  idum, nrhs, iparm, msglvl, ddum, ddum, error)
451 
452 #ifdef DEBUG
453  write(0,*) 'Reordering and factorization completed ... '
454 #endif
455  IF (error .NE. 0) THEN
456  write(0,*) 'The following ERROR was detected at the factorization step: ', error
457  RETURN
458  ENDIF
459 
460 
461 
462 ! Set parameters to calculate only the last sizeInv components of the solution
463  iparm(31) = 3
464  phase = 33 ! solver
465  allocate( perm(sizea) )
466  perm = 0
467  do idx = 1, sizeinv
468  perm(sizea-sizeinv+idx) = 1
469  end do
470 
471 ! Calculating the chunk of the solution to be calculated at once
472  if (modulo(sizeinv, nrhs).EQ.0) then
473  numiterations = sizeinv/nrhs
474  else
475  numiterations = floor(real(sizeinv)/real(nrhs)) + 1
476  end if
477 
478 #ifdef DEBUG
479  write(0,*) 'Number of iterations to obtain the right solutions ', numiterations
480 #endif
481 
482 ! Allocating the right hand side
483  allocate( pb(sizea, nrhs) )
484  allocate( px(sizea, nrhs) )
485 
486  do idxiterations = 1, numiterations
487 
488  offset = (idxiterations-1)*nrhs
489 
490  if ((sizeinv-offset).LT.nrhs) then
491  nrhs = sizeinv-offset
492  deallocate(pb, px)
493  allocate( pb(sizea, nrhs) )
494  allocate( px(sizea, nrhs) )
495  end if
496 
497 ! Creating the right hand side
498  pb = (0.d0, 0.d0)
499  px = (0.d0, 0.d0)
500  do idx = 1, nrhs
501  pb(sizea-sizeinv+offset+idx, idx) = (1.d0, 0.d0)
502  end do
503 ! Solver
504  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, pa, pia, pja, &
505  perm, nrhs, iparm, msglvl, pb, px, error)
506 
507  IF (error .NE. 0) THEN
508  exit
509  ENDIF
510 
511  do idx = 1, nrhs
512  do jdx = 1,sizeinv
513  real_inva(offset+idx,jdx) = real(px(sizea-sizeinv+jdx, idx))
514  imag_inva(offset+idx,jdx) = aimag(px(sizea-sizeinv+jdx, idx))
515  end do
516  end do
517 
518  end do
519 
520  deallocate(pb, px, perm)
521 
522 
523  IF (error .NE. 0) THEN
524  write(0,*) 'The following ERROR was detected at the solution step: ', error
525  RETURN
526  ENDIF
527 
528 !
529 ! Termination and release of memory
530  phase = -1 ! release internal memory
531  CALL pardiso (pt, maxfct, mnum, mtype, phase, sizea, ddum, &
532  idum, idum, &
533  idum, nrhs, iparm, msglvl, ddum, ddum, error)
534 
535  deallocate(idum, ddum, pt)
536 
537  IF (error .NE. 0) THEN
538  write(0,*) 'The following ERROR was detected at releasing the memory: ', error
539  RETURN
540  ENDIF
541 
542  end
543 
544 
545 
546 end module
547 
548 
subroutine zgetpartialinv(sizeA, nonzerosA, a, ia, ja, sizeInv, real_invA, imag_invA, error)
Get the partial inverse of a complex valued real matrices.
Module to calculate the partial inverse of a real/complex sparse matrix via the PARDISO libraries.
subroutine dgetpartialinv(sizeA, nonzerosA, a, ia, ja, sizeInv, invA, error)
Get the partial inverse of double valued real matrices.