Branch data Line data Source code
1 : : !!****m* ABINIT/m_hide_lapack
2 : : !! NAME
3 : : !! m_hide_lapack
4 : : !!
5 : : !! FUNCTION
6 : : !! ABINIT Linear Algebra Subroutine Interfaces.
7 : : !!
8 : : !! This modules provides interfaces performing the overloading of commonly used Lapack routines.
9 : : !! The main purpose of this module is to create a layer between abinit routines and Lapack procedures.
10 : : !! This layer can be used to hide the parallel Scalapack version. In this case, only the MPI commutator
11 : : !! has to be provided in input as the wrapper will take care of the initialization of the Scalapack grid as
12 : : !! well as of the distribution of the matrix. Note that this allows one to reduce
13 : : !! the CPU time per processor but not the memory allocated since the entire matrix has to be provided in input.
14 : : !! The interfaces are very similar to the Lapack F77 version (neither F90 constructs nor
15 : : !! F90 assumed size arrays are used). The main simplification with respect to the F77 version
16 : : !! of Lapack is that the work arrays are allocated inside the wrapper with optimal size
17 : : !! thus reducing the number of input argcomm_scalapackuments that has to be passed.
18 : : !! Leading dimensions have been removed from the interface whenever possible.
19 : : !! In F90 one can pass the array descriptor if the routines should operate on a slice
20 : : !! of the local array (seldom done in abinit).
21 : : !! Using array descriptor is OK but will it likely slow-down the calculation as
22 : : !! some compilers perform a copy of the input-output data.
23 : : !! If efficiency is a concern, then the F77 call should be used
24 : : !!
25 : : !! COPYRIGHT
26 : : !! Copyright (C) 1992-2026 ABINIT group (MG, GMR, XG)
27 : : !! This file is distributed under the terms of the
28 : : !! GNU General Public License, see ~abinit/COPYING
29 : : !! or http://www.gnu.org/copyleft/gpl.txt .
30 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
31 : : !!
32 : : !! TODO
33 : : !! 1) Use a function to define the size of the Scalapack block according to some heuristic method.
34 : : !! 2) Define a threshold below which Scalapack is not used although the MPI communicator is passed.
35 : : !! 3) Split MPI communicator for Scalapack (.i.e. use a max size for the Scalapack comm; see abi_linalg_init).
36 : : !! 4) On certain networks, xmpi_sum might crash due to the size of the MPI packet.
37 : : !! This problem should be solved in hide_mpi (Module containing a private global variable
38 : : !! defining a threshold above which the input array is split into smaller chunks.
39 : : !!
40 : : !! SOURCE
41 : :
42 : : #if defined HAVE_CONFIG_H
43 : : #include "config.h"
44 : : #endif
45 : :
46 : : #include "abi_common.h"
47 : :
48 : : MODULE m_hide_lapack
49 : :
50 : : use defs_basis
51 : : use m_abicore
52 : : use m_xmpi
53 : : use m_errors
54 : : use m_slk
55 : : use m_linalg_interfaces
56 : :
57 : : use m_time, only : cwtime
58 : : use m_fstrings, only : firstchar
59 : :
60 : : implicit none
61 : :
62 : : private
63 : :
64 : : ! ==========================
65 : : ! Complex Hermitian matrices
66 : : ! ==========================
67 : : ! The _cplex version receives matrices declared as arr(cplex,N,M)
68 : : ! and calls the complex/real version depending on cplex (used e.g. for istwf_k = 2)
69 : :
70 : : public :: xheev ! Computes all the eigenvalues and, optionally, eigenvectors of a complex Hermitian matrix.
71 : : public :: xheev_cplex
72 : :
73 : : public :: xhpev ! Computes all the eigenvalues and, optionally, eigenvectors of a complex Hermitian matrix
74 : : ! in packed storage (Scalapack version not available)
75 : :
76 : : public :: xhegv ! Compute all the eigenvalues, and optionally, the eigenvectors of a complex generalized
77 : : ! Hermitian-definite eigenproblem, of the form:
78 : : ! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x
79 : :
80 : : public :: xheevx ! Computes selected eigenvalues and, optionally, eigenvectors of a complex Hermitian matrix A.
81 : : ! Eigenvalues and eigenvectors can be selected by specifying either a range of values or a range of
82 : : ! indices for the desired eigenvalues.
83 : :
84 : : public :: xheevx_cplex
85 : :
86 : : public :: xhegvx ! Computes selected eigenvalues, and optionally, eigenvectors
87 : : ! of a complex generalized Hermitian-definite eigenproblem,
88 : : ! of the form A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x.
89 : : ! Eigenvalues and eigenvectors can be selected by specifying either a range of values or a range of
90 : : ! indices for the desired eigenvalues.
91 : : public :: xhegvx_cplex
92 : :
93 : :
94 : : public :: xhesv_cplex ! Solve A * X = B, where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS matrices.
95 : :
96 : :
97 : : ! ==============================
98 : : ! Complex non-symmetric matrices
99 : : ! ==============================
100 : :
101 : : public :: xgeev ! Computes for a complex nonsymmetric matrix A, the eigenvalues and, optionally,
102 : : ! the left and/or right eigenvectors.
103 : :
104 : : public :: xginv ! Invert a general matrix of complex elements by means of LU factorization.
105 : :
106 : :
107 : : public :: xhdp_invert ! Invert a Hermitian positive definite matrix.
108 : :
109 : : interface xheev
110 : : module procedure wrap_CHEEV
111 : : module procedure wrap_ZHEEV
112 : : end interface xheev
113 : :
114 : : interface xhpev
115 : : module procedure wrap_CHPEV
116 : : module procedure wrap_ZHPEV
117 : : end interface xhpev
118 : :
119 : : interface xhegv
120 : : module procedure wrap_ZHEGV
121 : : end interface xhegv
122 : :
123 : : public :: xhegv_cplex
124 : :
125 : : interface xheevx
126 : : module procedure wrap_ZHEEVX
127 : : end interface xheevx
128 : :
129 : : interface xhegvx
130 : : module procedure wrap_ZHEGVX
131 : : end interface xhegvx
132 : :
133 : : interface xgeev
134 : : module procedure wrap_CGEEV
135 : : module procedure wrap_ZGEEV
136 : : end interface xgeev
137 : :
138 : : interface xginv
139 : : module procedure cginv
140 : : module procedure zginv
141 : : end interface xginv
142 : :
143 : : interface xhdp_invert
144 : : module procedure zhpd_invert
145 : : end interface xhdp_invert
146 : :
147 : : public :: matrginv ! Invert a general matrix of real*8 elements.
148 : : public :: matr3eigval ! Find the eigenvalues of a real symmetric 3x3 matrix, entered in full storage mode.
149 : :
150 : : !FIXME This procedures are deprecated, use lapack API
151 : : public :: jacobi ! Computes all eigenvalues and eigenvectors of a real symmetric matrix a,
152 : : public :: ludcmp
153 : : public :: lubksb
154 : : public :: dzgedi
155 : : public :: dzgefa
156 : :
157 : : !----------------------------------------------------------------------
158 : : ! support for unitary tests and profiling.
159 : :
160 : : type,public :: latime_t
161 : : character(len=500) :: testname
162 : : integer :: msize
163 : : real(dp) :: ctime
164 : : real(dp) :: wtime
165 : : real(dp) :: max_abserr=-one
166 : : real(dp) :: gflops
167 : : end type latime_t
168 : :
169 : : public :: test_xginv
170 : :
171 : : !----------------------------------------------------------------------
172 : : ! private variables
173 : :
174 : : integer,private,parameter :: SLK_BLOCK_SIZE = 24
175 : : ! Default block size for Scalapack distribution.
176 : : ! As recommended by Intel MKL, a more sensible default than the previous value of 40
177 : :
178 : : CONTAINS !=========================================================================================================================
179 : : !!***
180 : :
181 : : !!****f* m_hide_lapack/wrap_CHEEV
182 : : !! NAME
183 : : !! wrap_CHEEV
184 : : !!
185 : : !! FUNCTION
186 : : !! wrap_CHEEV computes the eigenvalues and, optionally, the eigenvectors of a
187 : : !! complex Hermitian matrix in single precision. [PRIVATE]
188 : : !!
189 : : !! INPUTS
190 : : !! JOBZ (input) CHARACTER*1
191 : : !! = 'N': Compute eigenvalues only;
192 : : !! = 'V': Compute eigenvalues and eigenvectors.
193 : : !!
194 : : !! UPLO (input) CHARACTER*1
195 : : !! = 'U': Upper triangle of A is stored;
196 : : !! = 'L': Lower triangle of A is stored.
197 : : !!
198 : : !! N (input) INTEGER
199 : : !! The order of the matrix A. N >= 0.
200 : : !!
201 : : !! OUTPUT
202 : : !! W (output) REAL(SP) array, dimension (N)
203 : : !! If INFO = 0, the eigenvalues in ascending order.
204 : : !!
205 : : !! See also SIDE EFFECTS
206 : : !!
207 : : !! SIDE EFFECTS
208 : : !! A (input/output) COMPLEX(sp) array, dimension (N, N)
209 : : !! On entry, the Hermitian matrix A. If UPLO = 'U', the
210 : : !! leading N-by-N upper triangular part of A contains the
211 : : !! upper triangular part of the matrix A. If UPLO = 'L',
212 : : !! the leading N-by-N lower triangular part of A contains
213 : : !! the lower triangular part of the matrix A.
214 : : !! On exit, if JOBZ = 'V', then if INFO = 0, A contains the
215 : : !! orthonormal eigenvectors of the matrix A.
216 : : !! If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
217 : : !! or the upper triangle (if UPLO='U') of A, including the
218 : : !! diagonal, is destroyed.
219 : : !!
220 : : !! SOURCE
221 : :
222 : 0 : subroutine wrap_CHEEV(jobz, uplo, n, a, w)
223 : :
224 : : !Arguments ------------------------------------
225 : : !scalars
226 : : integer,intent(in) :: n
227 : : character(len=*),intent(in) :: jobz,uplo
228 : : !scalars
229 : : real(sp),intent(out) :: w(n)
230 : : complex(sp),intent(inout) :: a(n,n)
231 : :
232 : : !Local variables ------------------------------
233 : : !scalars
234 : : integer :: lwork,info
235 : : character(len=500) :: msg
236 : : !arrays
237 : 0 : real(sp),allocatable :: rwork(:)
238 : 0 : complex(sp),allocatable :: work(:)
239 : : !************************************************************************
240 : :
241 : 0 : lwork = MAX(1,2*n-1)
242 : :
243 [ # # # # : 0 : ABI_MALLOC(work, (lwork))
# # # # #
# ]
244 [ # # # # : 0 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
# # # # #
# ]
245 : :
246 : 0 : call CHEEV(jobz,uplo,n,a,n,w,work,lwork,rwork,info)
247 : :
248 [ # # ]: 0 : if (info < 0) then
249 : 0 : write(msg,'(a,i0,a)')"The ",-info,"-th argument of CHEEV had an illegal value."
250 : 0 : ABI_ERROR(msg)
251 : : end if
252 : :
253 [ # # ]: 0 : if (info > 0) then
254 : : write(msg,'(2a,i0,a)')&
255 : 0 : "CHEEV: the algorithm failed to converge; ",ch10,&
256 : 0 : info," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
257 : 0 : ABI_ERROR(msg)
258 : : end if
259 : :
260 [ # # ]: 0 : ABI_FREE(rwork)
261 [ # # ]: 0 : ABI_FREE(work)
262 : :
263 : : !TODO scaLAPACK version (complex single precision buffer is needed in slkmat_dp_t)
264 : :
265 : 0 : end subroutine wrap_CHEEV
266 : : !!***
267 : :
268 : : !----------------------------------------------------------------------
269 : :
270 : : !!****f* m_hide_lapack/wrap_ZHEEV
271 : : !! NAME
272 : : !! wrap_ZHEEV
273 : : !!
274 : : !! FUNCTION
275 : : !! wrap_ZHEEV computes the eigenvalues and, optionally, the eigenvectors of a
276 : : !! complex Hermitian matrix in double precision. [PRIVATE]
277 : : !!
278 : : !! INPUTS
279 : : !! JOBZ (input) CHARACTER*1
280 : : !! = 'N': Compute eigenvalues only;
281 : : !! = 'V': Compute eigenvalues and eigenvectors.
282 : : !!
283 : : !! UPLO (input) CHARACTER*1
284 : : !! = 'U': Upper triangle of A is stored;
285 : : !! = 'L': Lower triangle of A is stored.
286 : : !!
287 : : !! N (input) INTEGER
288 : : !! The order of the matrix A. N >= 0.
289 : : !!
290 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
291 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
292 : : !! in this case the sequential LAPACK routine is called.
293 : : !! OUTPUT
294 : : !! W (output) REAL(DP) array, dimension (N)
295 : : !! If INFO = 0, the eigenvalues in ascending order.
296 : : !!
297 : : !! See also SIDE EFFECTS
298 : : !!
299 : : !! SIDE EFFECTS
300 : : !! A (input/output) COMPLEX(DP) array, dimension (N, N)
301 : : !! On entry, the Hermitian matrix A. If UPLO = 'U', the
302 : : !! leading N-by-N upper triangular part of A contains the
303 : : !! upper triangular part of the matrix A. If UPLO = 'L',
304 : : !! the leading N-by-N lower triangular part of A contains
305 : : !! the lower triangular part of the matrix A.
306 : : !! On exit, if JOBZ = 'V', then if INFO = 0, A contains the
307 : : !! orthonormal eigenvectors of the matrix A.
308 : : !! If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
309 : : !! or the upper triangle (if UPLO='U') of A, including the
310 : : !! diagonal, is destroyed.
311 : : !!
312 : : !! SOURCE
313 : :
314 : 52400 : subroutine wrap_ZHEEV(jobz, uplo, n, a, w, comm)
315 : :
316 : : !Arguments ------------------------------------
317 : : !scalars
318 : : integer,intent(in) :: n
319 : : integer,optional,intent(in) :: comm
320 : : character(len=*),intent(in) :: jobz,uplo
321 : : !arrays
322 : : complex(dp),intent(inout) :: a(n,n)
323 : : real(dp),intent(out) :: w(n)
324 : :
325 : : !Local variables ------------------------------
326 : : !scalars
327 : : integer :: lwork,info,nprocs
328 : : logical :: use_scalapack
329 : : character(len=500) :: msg
330 : : !arrays
331 : 52400 : real(dp),allocatable :: rwork(:)
332 : 52400 : complex(dp),allocatable :: work(:)
333 : : #ifdef HAVE_LINALG_SCALAPACK
334 : : integer :: ierr,istwf_k
335 : : logical :: want_eigenvectors
336 : : type(slkmat_dp_t) :: Slk_mat,Slk_vec
337 : : type(slk_processor_t) :: Slk_processor
338 : : #endif
339 : : !************************************************************************
340 : :
341 : 52400 : use_scalapack=.FALSE.
342 [ - + ]: 52400 : if (PRESENT(comm)) then
343 : 0 : nprocs = xmpi_comm_size(comm)
344 : : #ifdef HAVE_LINALG_SCALAPACK
345 : : use_scalapack = (nprocs>1)
346 : : #endif
347 : : end if
348 : :
349 : : SELECT CASE(use_scalapack)
350 : : CASE (.FALSE.)
351 : :
352 : 52400 : lwork = MAX(1,2*n-1)
353 [ - + + - : 157200 : ABI_MALLOC(work, (lwork))
+ - - + -
+ ]
354 [ - + + - : 157200 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
+ - - + -
+ ]
355 : :
356 : 52400 : call ZHEEV(jobz,uplo,n,a,n,w,work,lwork,rwork,info)
357 : :
358 [ - + ]: 52400 : if (info < 0) then
359 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZHEEV had an illegal value."
360 : 0 : ABI_ERROR(msg)
361 : : end if
362 : :
363 [ - + ]: 52400 : if (info > 0) then
364 : : write(msg,'(2a,i0,a)')&
365 : 0 : "ZHEEV: the algorithm failed to converge; ",ch10,&
366 : 0 : info," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
367 : 0 : ABI_ERROR(msg)
368 : : end if
369 : :
370 [ - + ]: 52400 : ABI_FREE(rwork)
371 [ - + ]: 52400 : ABI_FREE(work)
372 : : RETURN
373 : :
374 : : CASE (.TRUE.)
375 : : #ifdef HAVE_LINALG_SCALAPACK
376 : : call Slk_processor%init(comm)
377 : : istwf_k=1
378 : :
379 : : ! Initialize and fill Scalapack matrix from the global one.
380 : : call Slk_mat%init(n,n,Slk_processor,istwf_k)
381 : : call slk_matrix_from_global_dpc_2D(Slk_mat,uplo,a)
382 : :
383 : : want_eigenvectors = firstchar(jobz,(/"V","v"/))
384 : : if (want_eigenvectors) then
385 : : ! Initialize the distributed vectors.
386 : : call Slk_vec%init(n,n,Slk_processor,istwf_k)
387 : : end if
388 : :
389 : : ! Solve the problem with scaLAPACK.
390 : : call slk_mat%heev(jobz, uplo, Slk_vec, w)
391 : : call Slk_mat%free()
392 : :
393 : : if (want_eigenvectors) then ! A is overwritten with the eigenvectors
394 : : a = czero
395 : : call slk_matrix_to_global_dpc_2D(Slk_vec,"All",a) ! Fill the entries calculated by this node.
396 : : call Slk_vec%free()
397 : : call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
398 : : end if
399 : :
400 : : call Slk_processor%free()
401 : : RETURN
402 : : #endif
403 : :
404 : : ABI_BUG("You should not be here!")
405 : : END SELECT
406 : :
407 : : end subroutine wrap_ZHEEV
408 : : !!***
409 : :
410 : : !----------------------------------------------------------------------
411 : :
412 : : !!****f* m_hide_lapack/xheev_cplex
413 : : !! NAME
414 : : !! xheev_cplex
415 : : !!
416 : : !! FUNCTION
417 : : !! xheev_cplex computes the eigenvalues and, optionally, the eigenvectors of a
418 : : !! (complex Hermitian| real symmetric) matrix in double precision.
419 : : !!
420 : : !! INPUTS
421 : : !! JOBZ (input) CHARACTER*1
422 : : !! = 'N': Compute eigenvalues only;
423 : : !! = 'V': Compute eigenvalues and eigenvectors.
424 : : !!
425 : : !! UPLO (input) CHARACTER*1
426 : : !! = 'U': Upper triangle of A is stored;
427 : : !! = 'L': Lower triangle of A is stored.
428 : : !!
429 : : !! CPLEX= Size of the first dimension of the A matrix.
430 : : !! 1 for a real symmetric matrix.
431 : : !! 2 for complex Hermitian matrix stored in a real array with real and imaginary part.
432 : : !!
433 : : !! N (input) INTEGER
434 : : !! The order of the matrix A. N >= 0.
435 : : !!
436 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
437 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
438 : : !! in this case the sequential LAPACK routine is called.
439 : : !!
440 : : !! OUTPUT
441 : : !! W (output) REAL(DP) array, dimension (N)
442 : : !! If INFO = 0, the eigenvalues in ascending order.
443 : : !!
444 : : !! See also SIDE EFFECTS
445 : : !!
446 : : !! SIDE EFFECTS
447 : : !! A (input/output) REAL(DP) array, dimension (CPLEX, N, N)
448 : : !! On entry, the (complex Hermitian|Real symmetric) matrix A. If UPLO = 'U', the
449 : : !! leading N-by-N upper triangular part of A contains the
450 : : !! upper triangular part of the matrix A. If UPLO = 'L',
451 : : !! the leading N-by-N lower triangular part of A contains
452 : : !! the lower triangular part of the matrix A.
453 : : !! On exit, if JOBZ = 'V', then if INFO = 0, A contains the
454 : : !! orthonormal eigenvectors of the matrix A.
455 : : !! If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
456 : : !! or the upper triangle (if UPLO='U') of A, including the
457 : : !! diagonal, is destroyed.
458 : : !!
459 : : !! SOURCE
460 : :
461 : 0 : subroutine xheev_cplex(jobz, uplo, cplex, n, a, w, msg, ierr, comm)
462 : :
463 : : !Arguments ------------------------------------
464 : : !scalars
465 : : integer,intent(in) :: n,cplex
466 : : integer,optional,intent(in) :: comm
467 : : character(len=*),intent(in) :: jobz,uplo
468 : : integer,intent(out) :: ierr
469 : : character(len=*),intent(out) :: msg
470 : : !arrays
471 : : real(dp),intent(inout) :: a(cplex,n,n)
472 : : real(dp),intent(out) :: w(n)
473 : :
474 : : !Local variables ------------------------------
475 : : !scalars
476 : : integer :: lwork,nprocs
477 : : logical :: use_scalapack
478 : : !arrays
479 : 0 : real(dp),allocatable :: rwork(:)
480 : 0 : real(dp),allocatable :: work_real(:)
481 : 0 : complex(dp),allocatable :: work_cplx(:)
482 : : #ifdef HAVE_LINALG_SCALAPACK
483 : : !integer :: istwf_k
484 : : !logical :: want_eigenvectors
485 : : !type(slkmat_dp_t) :: Slk_mat,Slk_vec
486 : : !type(slk_processor_t) :: Slk_processor
487 : : #endif
488 : : !************************************************************************
489 : :
490 : 0 : use_scalapack=.FALSE.
491 [ # # ]: 0 : if (PRESENT(comm)) then
492 : 0 : nprocs = xmpi_comm_size(comm)
493 : : #ifdef HAVE_LINALG_SCALAPACK
494 : : use_scalapack = (nprocs>1)
495 : : #endif
496 : : end if
497 : :
498 [ # # ]: 0 : if (ALL(cplex/= [1, 2])) then
499 : 0 : write(msg,'(a,i0)')" Wrong value for cplex: ",cplex
500 : 0 : ierr = 1; return
501 : : end if
502 : :
503 : : SELECT CASE(use_scalapack)
504 : : CASE (.FALSE.)
505 [ # # ]: 0 : if (cplex==1) then
506 : : ! Real symmetric case.
507 : 0 : lwork = MAX(1,3*n-1)
508 [ # # # # : 0 : ABI_MALLOC(work_real,(lwork))
# # # # #
# ]
509 : :
510 : 0 : call DSYEV(jobz,uplo,n,a,n,w,work_real,lwork,ierr)
511 : :
512 [ # # ]: 0 : if (ierr < 0) then
513 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of DSYEV had an illegal value."
514 : : end if
515 : :
516 [ # # ]: 0 : if (ierr > 0) then
517 : : write(msg,'(2a,i0,a)')&
518 : 0 : "DSYEV: the algorithm failed to converge; ",ch10,&
519 : 0 : ierr," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
520 : : end if
521 : :
522 [ # # ]: 0 : ABI_FREE(work_real)
523 : 0 : RETURN
524 : :
525 : : else
526 : : ! Hermitian case.
527 : 0 : lwork = MAX(1,2*n-1)
528 : :
529 [ # # # # : 0 : ABI_MALLOC(work_cplx, (lwork))
# # # # #
# ]
530 [ # # # # : 0 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
# # # # #
# ]
531 : :
532 : 0 : call ZHEEV(jobz,uplo,n,a,n,w,work_cplx,lwork,rwork,ierr)
533 : :
534 [ # # ]: 0 : if (ierr < 0) then
535 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of ZHEEV had an illegal value."
536 : : end if
537 : :
538 [ # # ]: 0 : if (ierr > 0) then
539 : : write(msg,'(2a,i0,a)')&
540 : 0 : "ZHEEV: the algorithm failed to converge; ",ch10,&
541 : 0 : ierr," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
542 : : end if
543 : :
544 [ # # ]: 0 : ABI_FREE(rwork)
545 [ # # ]: 0 : ABI_FREE(work_cplx)
546 : 0 : RETURN
547 : : end if ! cplex
548 : :
549 : : CASE (.TRUE.)
550 : :
551 : : #ifdef HAVE_LINALG_SCALAPACK
552 : : ABI_ERROR("Not coded yet")
553 : :
554 : : !call Slk_processor%init(comm)
555 : : !istwf_k=1
556 : : !
557 : : !! Initialize and fill Scalapack matrix from the global one.
558 : : !call Slk_mat%init(n,n,Slk_processor,istwf_k)
559 : : !
560 : : !call slk_matrix_from_global_dpc_2D(Slk_mat,uplo,a)
561 : : !
562 : : !want_eigenvectors = firstchar(jobz,(/"V","v"/))
563 : : !if (want_eigenvectors) then ! Initialize the distributed vectors.
564 : : ! call Slk_vec%init(n,n,Slk_processor,istwf_k)
565 : : !end if
566 : : !
567 : : !! Solve the problem with scaLAPACK.
568 : : !call slk_mat%heev(jobz,uplo,Slk_vec,w)
569 : : !call Slk_mat%free()
570 : : !
571 : : !if (want_eigenvectors) then ! A is overwritten with the eigenvectors
572 : : ! a = czero
573 : : ! call slk_matrix_to_global_dpc_2D(Slk_vec,"All",a) ! Fill the entries calculated by this node.
574 : : ! call Slk_vec%free()
575 : : ! call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
576 : : !end if
577 : : !
578 : : !call Slk_processor%free()
579 : :
580 : : RETURN
581 : : #endif
582 : :
583 : : ABI_BUG("You should not be here!")
584 : : END SELECT
585 : :
586 : : end subroutine xheev_cplex
587 : : !!***
588 : :
589 : : !----------------------------------------------------------------------
590 : :
591 : : !!****f* m_hide_lapack/wrap_CHPEV
592 : : !! NAME
593 : : !! wrap_CHPEV
594 : : !!
595 : : !! FUNCTION
596 : : !! wrap_CHPEV computes all the eigenvalues and, optionally, eigenvectors of a
597 : : !! complex Hermitian matrix in packed storage. Scalapack version is not available. [PRIVATE].
598 : : !!
599 : : !! INPUTS
600 : : !! JOBZ (input) CHARACTER*1
601 : : !! = 'N': Compute eigenvalues only;
602 : : !! = 'V': Compute eigenvalues and eigenvectors.
603 : : !!
604 : : !! UPLO (input) CHARACTER*1
605 : : !! = 'U': Upper triangle of A is stored;
606 : : !! = 'L': Lower triangle of A is stored.
607 : : !!
608 : : !! N (input) INTEGER
609 : : !! The order of the matrix A. N >= 0.
610 : : !!
611 : : !! LDZ (input) INTEGER
612 : : !! The leading dimension of the array Z. LDZ >= 1, and if
613 : : !! JOBZ = 'V', LDZ >= max(1,N).
614 : : !!
615 : : !! OUTPUT
616 : : !! W (output) REAL(SP) array, dimension (N)
617 : : !! If INFO = 0, the eigenvalues in ascending order.
618 : : !!
619 : : !! Z (output) COMPLEX(sp) array, dimension (LDZ, N)
620 : : !! If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
621 : : !! eigenvectors of the matrix A, with the i-th column of Z
622 : : !! holding the eigenvector associated with W(i).
623 : : !! If JOBZ = 'N', then Z is not referenced.
624 : : !!
625 : : !! See also SIDE EFFECTS
626 : : !!
627 : : !! SIDE EFFECTS
628 : : !!
629 : : !! AP (input/output) COMPLEX(sp) array, dimension (N*(N+1)/2)
630 : : !! On entry, the upper or lower triangle of the Hermitian matrix
631 : : !! A, packed columnwise in a linear array. The j-th column of A
632 : : !! is stored in the array AP as follows:
633 : : !! if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
634 : : !! if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.
635 : : !!
636 : : !! On exit, AP is overwritten by values generated during the
637 : : !! reduction to tridiagonal form. If UPLO = 'U', the diagonal
638 : : !! and first superdiagonal of the tridiagonal matrix T overwrite
639 : : !! the corresponding elements of A, and if UPLO = 'L', the
640 : : !! diagonal and first subdiagonal of T overwrite the
641 : : !! corresponding elements of A.
642 : : !!
643 : : !! SOURCE
644 : :
645 : 0 : subroutine wrap_CHPEV(jobz, uplo, n, ap, w, z, ldz)
646 : :
647 : : !Arguments ------------------------------------
648 : : !scalars
649 : : integer,intent(in) :: n,ldz
650 : : character(len=*),intent(in) :: jobz,uplo
651 : : !arrays
652 : : real(sp),intent(out) :: w(n)
653 : : complex(sp),intent(inout) :: ap(n*(n+1)/2)
654 : : complex(sp),intent(out) :: z(ldz,n)
655 : :
656 : : !Local variables ------------------------------
657 : : !scalars
658 : : integer :: info
659 : : character(len=500) :: msg
660 : : !arrays
661 : 0 : real(sp),allocatable :: rwork(:)
662 : 0 : complex(sp),allocatable :: work(:)
663 : : !************************************************************************
664 : :
665 [ # # # # : 0 : ABI_MALLOC(work, (MAX(1,2*n-1)))
# # # # #
# ]
666 [ # # # # : 0 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
# # # # #
# ]
667 : :
668 : 0 : call CHPEV( JOBZ, UPLO, N, AP, W, Z, LDZ, WORK, RWORK, INFO )
669 : :
670 [ # # ]: 0 : if (info < 0) then
671 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZHEEV had an illegal value."
672 : 0 : ABI_ERROR(msg)
673 : : end if
674 : :
675 [ # # ]: 0 : if (info > 0) then
676 : : write(msg,'(2a,i0,a)')&
677 : 0 : "ZHPEV: the algorithm failed to converge; ",ch10,&
678 : 0 : info," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
679 : 0 : ABI_ERROR(msg)
680 : : end if
681 : :
682 [ # # ]: 0 : ABI_FREE(rwork)
683 [ # # ]: 0 : ABI_FREE(work)
684 : :
685 : 0 : end subroutine wrap_CHPEV
686 : : !!***
687 : :
688 : : !----------------------------------------------------------------------
689 : :
690 : : !!****f* m_hide_lapack/wrap_ZHPEV
691 : : !! NAME
692 : : !! wrap_ZHPEV
693 : : !!
694 : : !! FUNCTION
695 : : !! wrap_ZHPEV computes all the eigenvalues and, optionally, eigenvectors of a
696 : : !! complex Hermitian matrix in packed storage. Scalapack version is not available. [PRIVATE].
697 : : !!
698 : : !! INPUTS
699 : : !! JOBZ (input) CHARACTER*1
700 : : !! = 'N': Compute eigenvalues only;
701 : : !! = 'V': Compute eigenvalues and eigenvectors.
702 : : !!
703 : : !! UPLO (input) CHARACTER*1
704 : : !! = 'U': Upper triangle of A is stored;
705 : : !! = 'L': Lower triangle of A is stored.
706 : : !!
707 : : !! N (input) INTEGER
708 : : !! The order of the matrix A. N >= 0.
709 : : !!
710 : : !! LDZ (input) INTEGER
711 : : !! The leading dimension of the array Z. LDZ >= 1, and if
712 : : !! JOBZ = 'V', LDZ >= max(1,N).
713 : : !!
714 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
715 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
716 : : !! in this case the sequential LAPACK routine is called. Note that scalapack does not provide native
717 : : !! support for packed symmetric matrices. Therefore we have to distribute the full matrix among the nodes.
718 : : !! in order to perform the calculation in parallel.
719 : : !!
720 : : !! OUTPUT
721 : : !! W (output) REAL(DP) array, dimension (N)
722 : : !! If INFO = 0, the eigenvalues in ascending order.
723 : : !!
724 : : !! Z (output) COMPLEX(DP) array, dimension (LDZ, N)
725 : : !! If JOBZ = 'V', then if INFO = 0, Z contains the orthonormal
726 : : !! eigenvectors of the matrix A, with the i-th column of Z
727 : : !! holding the eigenvector associated with W(i).
728 : : !! If JOBZ = 'N', then Z is not referenced.
729 : : !!
730 : : !! See also SIDE EFFECTS
731 : : !!
732 : : !! SIDE EFFECTS
733 : : !!
734 : : !! AP (input/output) COMPLEX(DP) array, dimension (N*(N+1)/2)
735 : : !! On entry, the upper or lower triangle of the Hermitian matrix
736 : : !! A, packed columnwise in a linear array. The j-th column of A
737 : : !! is stored in the array AP as follows:
738 : : !! if UPLO = 'U', AP(i + (j-1)*j/2) = A(i,j) for 1<=i<=j;
739 : : !! if UPLO = 'L', AP(i + (j-1)*(2*n-j)/2) = A(i,j) for j<=i<=n.
740 : : !!
741 : : !! On exit, AP is overwritten by values generated during the
742 : : !! reduction to tridiagonal form. If UPLO = 'U', the diagonal
743 : : !! and first superdiagonal of the tridiagonal matrix T overwrite
744 : : !! the corresponding elements of A, and if UPLO = 'L', the
745 : : !! diagonal and first subdiagonal of T overwrite the
746 : : !! corresponding elements of A. Unchanged if ScaLAPACK is used.
747 : : !!
748 : : !! SOURCE
749 : :
750 : 21 : subroutine wrap_ZHPEV(jobz, uplo, n, ap, w, z, ldz, comm)
751 : :
752 : : !Arguments ------------------------------------
753 : : !scalars
754 : : integer,intent(in) :: n,ldz
755 : : integer,optional,intent(in) :: comm
756 : : character(len=*),intent(in) :: jobz,uplo
757 : : !arrays
758 : : real(dp),intent(out) :: w(n)
759 : : complex(dp),intent(inout) :: ap(n*(n+1)/2)
760 : : complex(dp),intent(out) :: z(ldz,n)
761 : :
762 : : !Local variables ------------------------------
763 : : !scalars
764 : : integer :: info,nprocs
765 : : logical :: use_scalapack
766 : : character(len=500) :: msg
767 : : !arrays
768 : 21 : real(dp),allocatable :: rwork(:)
769 : 21 : complex(dp),allocatable :: work(:)
770 : : #ifdef HAVE_LINALG_SCALAPACK
771 : : integer :: ierr,istwf_k
772 : : logical :: want_eigenvectors
773 : : type(slkmat_dp_t) :: Slk_mat,Slk_vec
774 : : type(slk_processor_t) :: Slk_processor
775 : : #endif
776 : : !************************************************************************
777 : :
778 : 21 : use_scalapack=.FALSE.
779 [ - + ]: 21 : if (PRESENT(comm)) then
780 : 0 : nprocs = xmpi_comm_size(comm)
781 : : #ifdef HAVE_LINALG_SCALAPACK
782 : : use_scalapack = (nprocs>1)
783 : : #endif
784 : : end if
785 : :
786 : : SELECT CASE(use_scalapack)
787 : : CASE (.FALSE.)
788 [ - + + - : 63 : ABI_MALLOC(work, (MAX(1,2*n-1)))
+ - - + -
+ ]
789 [ - + + - : 63 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
+ - - + -
+ ]
790 : :
791 : 21 : call ZHPEV(jobz,uplo,n,ap,w,z,ldz,work,rwork,info)
792 : :
793 [ - + ]: 21 : if (info < 0) then
794 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZHPEV had an illegal value."
795 : 0 : ABI_ERROR(msg)
796 : : end if
797 : :
798 [ - + ]: 21 : if (info > 0) then
799 : : write(msg,'(2a,i0,a)')&
800 : 0 : "ZHPEV: the algorithm failed to converge; ",ch10,&
801 : 0 : info," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
802 : 0 : ABI_ERROR(msg)
803 : : end if
804 : :
805 [ - + ]: 21 : ABI_FREE(rwork)
806 [ - + ]: 21 : ABI_FREE(work)
807 : : RETURN
808 : :
809 : : CASE (.TRUE.)
810 : :
811 : : #ifdef HAVE_LINALG_SCALAPACK
812 : : call Slk_processor%init(comm)
813 : : istwf_k=1
814 : :
815 : : ! Initialize and fill Scalapack matrix from the global one.
816 : : call Slk_mat%init(n,n,Slk_processor,istwf_k)
817 : : call slk_matrix_from_global_dpc_1Dp(Slk_mat,uplo,ap)
818 : :
819 : : want_eigenvectors = firstchar(jobz,(/"V","v"/))
820 : : if (want_eigenvectors) then
821 : : ! Initialize the distributed vectors.
822 : : call Slk_vec%init(n,n,Slk_processor,istwf_k)
823 : : end if
824 : :
825 : : ! Solve the problem with scaLAPACK.
826 : : call slk_mat%heev(jobz,uplo,Slk_vec,w)
827 : : call Slk_mat%free()
828 : :
829 : : if (want_eigenvectors) then ! Collect the eigenvectors.
830 : : z = zero
831 : : call slk_matrix_to_global_dpc_2D(Slk_vec,"All",z) ! Fill the entries calculated by this node.
832 : : call Slk_vec%free()
833 : : call xmpi_sum(z,comm,ierr) ! Fill the remaining entries of the global matrix
834 : : end if
835 : :
836 : : call Slk_processor%free()
837 : :
838 : : RETURN
839 : : #endif
840 : :
841 : : ABI_BUG("You should not be here!")
842 : : END SELECT
843 : :
844 : : end subroutine wrap_ZHPEV
845 : : !!***
846 : :
847 : : !----------------------------------------------------------------------
848 : :
849 : : !!****f* m_hide_lapack/wrap_ZHEGV
850 : : !! NAME
851 : : !! wrap_ZHEGV
852 : : !!
853 : : !! FUNCTION
854 : : !! wrap_ZHEGV computes all the eigenvalues, and optionally, the eigenvectors of a complex generalized
855 : : !! Hermitian-definite eigenproblem, of the form
856 : : !! A*x=(lambda)*B*x (1),
857 : : !! A*Bx=(lambda)*x, (2), or
858 : : !! B*A*x=(lambda)*x (3).
859 : : !! Here A and B are assumed to be Hermitian and B is also positive definite.
860 : : !!
861 : : !! INPUTS
862 : : !! ITYPE (input) INTEGER Specifies the problem type to be solved:
863 : : !! = 1: A*x = (lambda)*B*x
864 : : !! = 2: A*B*x = (lambda)*x
865 : : !! = 3: B*A*x = (lambda)*x
866 : : !!
867 : : !! JOBZ (input) CHARACTER*1
868 : : !! = "N": Compute eigenvalues only;
869 : : !! = "V": Compute eigenvalues and eigenvectors.
870 : : !!
871 : : !! UPLO (input) CHARACTER*1
872 : : !! = "U": Upper triangle of A and B are stored;
873 : : !! = "L": Lower triangle of A and B are stored.
874 : : !!
875 : : !! N (input) INTEGER
876 : : !! The order of the matrices A and B. N >= 0.
877 : : !!
878 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
879 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
880 : : !! in this case the sequential LAPACK routine is called.
881 : : !!
882 : : !! OUTPUT
883 : : !! W (output) REAL(DP) array, dimension (N)
884 : : !! If INFO = 0, the eigenvalues in ascending order.
885 : : !!
886 : : !! See also SIDE EFFECTS
887 : : !!
888 : : !! SIDE EFFECTS
889 : : !! A (input/output) COMPLEX(DP) array, dimension (N, N)
890 : : !! On entry, the Hermitian matrix A. If UPLO = "U", the leading N-by-N upper triangular part of A
891 : : !! <S-F1>contains the upper triangular part of the matrix A.
892 : : !! If UPLO = "L", the leading N-by-N lower triangular part of A contains the lower triangular part of the matrix A.
893 : : !!
894 : : !! On exit, if JOBZ = "V", then A contains the matrix Z of eigenvectors.
895 : : !! The eigenvectors are normalized as follows: if ITYPE = 1 or 2,
896 : : !! Z**H*B*Z = I; if ITYPE = 3, Z**H*inv(B)*Z = I.
897 : : !! If JOBZ = "N", then on exit the upper triangle (if UPLO="U") or the lower triangle
898 : : !! (if UPLO="L") of A, including the diagonal, is destroyed.
899 : : !!
900 : : !! B (input/output) COMPLEX*16 array, dimension (LDB, N)
901 : : !! On entry, the Hermitian positive definite matrix B.
902 : : !! If UPLO = "U", the leading N-by-N upper triangular part of B contains the upper triangular part of the matrix B.
903 : : !! If UPLO = "L", the leading N-by-N lower triangular part of B contains the lower triangular part of the matrix B.
904 : : !!
905 : : !! On exit, if INFO <= N, the part of B containing the matrix is overwritten by the triangular
906 : : !! factor U or L from the Cholesky factorization B = U**H*U or B = L*L**H.
907 : : !!
908 : : !! SOURCE
909 : :
910 : 19 : subroutine wrap_ZHEGV(itype, jobz, uplo, n, a, b, w, comm)
911 : :
912 : : !Arguments ------------------------------------
913 : : !scalars
914 : : integer,intent(in) :: n,itype
915 : : integer,optional,intent(in) :: comm
916 : : character(len=*),intent(in) :: jobz,uplo
917 : : !arrays
918 : : complex(dp),intent(inout) :: a(n,n),b(n,n)
919 : : real(dp),intent(out) :: w(n)
920 : :
921 : : !Local variables ------------------------------
922 : : !scalars
923 : : integer :: lwork,info,nprocs,ii
924 : : logical :: use_scalapack
925 : : character(len=500) :: msg
926 : : !arrays
927 : 19 : real(dp),allocatable :: rwork(:)
928 : 19 : complex(dp),allocatable :: work(:)
929 : : #ifdef HAVE_LINALG_SCALAPACK
930 : : integer :: ierr,istwf_k
931 : : type(slkmat_dp_t) :: Slk_matA,Slk_matB
932 : : type(slk_processor_t) :: Slk_processor
933 : : #endif
934 : : !************************************************************************
935 : :
936 : 19 : use_scalapack=.FALSE.
937 [ - + ]: 19 : if (PRESENT(comm)) then
938 : 0 : nprocs = xmpi_comm_size(comm)
939 : : #ifdef HAVE_LINALG_SCALAPACK
940 : : use_scalapack = (nprocs>1)
941 : : #endif
942 : : end if
943 : :
944 : : SELECT CASE(use_scalapack)
945 : : CASE (.FALSE.)
946 : 19 : lwork = MAX(1,2*n-1)
947 : :
948 [ - + + - : 57 : ABI_MALLOC(work, (lwork))
+ - - + -
+ ]
949 [ - + + - : 57 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
+ - - + -
+ ]
950 : :
951 : 19 : call ZHEGV(itype,jobz,uplo,n,a,n,b,n,w,work,lwork,rwork,info)
952 : :
953 [ - + ]: 19 : if (info < 0) then
954 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZHEGV had an illegal value."
955 : 0 : ABI_ERROR(msg)
956 : : end if
957 : :
958 [ - + ]: 19 : if (info > 0) then
959 [ # # ]: 0 : if (info<= n) then
960 : : write(msg,'(2a,i0,a)')&
961 : 0 : "ZHEGV failed to converge: ",ch10,&
962 : 0 : info," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
963 : : else
964 : 0 : ii = info -n
965 : : write(msg,'(3a,i0,3a)')&
966 : 0 : "ZHEGV failed to converge: ",ch10,&
967 : 0 : "The leading minor of order ",ii," of B is not positive definite. ",ch10,&
968 : 0 : "The factorization of B could not be completed and no eigenvalues or eigenvectors were computed."
969 : : end if
970 : 0 : ABI_ERROR(msg)
971 : : end if
972 : :
973 [ - + ]: 19 : ABI_FREE(rwork)
974 [ - + ]: 19 : ABI_FREE(work)
975 : : RETURN
976 : :
977 : : CASE (.TRUE.)
978 : :
979 : : #ifdef HAVE_LINALG_SCALAPACK
980 : : call Slk_processor%init(comm)
981 : : istwf_k=1
982 : :
983 : : ! Initialize and fill Scalapack matrix from the global one.
984 : : call Slk_matA%init(n,n,Slk_processor,istwf_k)
985 : : call slk_matrix_from_global_dpc_2D(Slk_matA,uplo,a)
986 : :
987 : : call Slk_matB%init(n,n,Slk_processor,istwf_k)
988 : : call slk_matrix_from_global_dpc_2D(Slk_matB,uplo,b)
989 : :
990 : : ! Solve the problem with scaLAPACK.
991 : : ABI_ERROR("slk_pZHEGV not yet coded")
992 : : ! TODO
993 : : !% call slk_pzhegv(itype,jobz,uplo,Slk_matA,Slk_matB,w)
994 : :
995 : : call Slk_matB%free()
996 : :
997 : : if (firstchar(jobz,(/"V","v"/))) then ! A is overwritten with the eigenvectors
998 : : a = czero
999 : : call slk_matrix_to_global_dpc_2D(Slk_matA,"All",a) ! Fill the entries calculated by this node.
1000 : : call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
1001 : : end if
1002 : :
1003 : : call Slk_matA%free()
1004 : : call Slk_processor%free()
1005 : : RETURN
1006 : : #endif
1007 : :
1008 : : ABI_BUG("You should not be here!")
1009 : : END SELECT
1010 : :
1011 : : end subroutine wrap_ZHEGV
1012 : : !!***
1013 : :
1014 : : !----------------------------------------------------------------------
1015 : :
1016 : : !!****f* m_hide_lapack/xhegv_cplex
1017 : : !! NAME
1018 : : !! xhegv_cplex
1019 : : !!
1020 : : !! FUNCTION
1021 : : !! xhegv_cplex computes all the eigenvalues, and optionally, the eigenvectors of a
1022 : : !! (real generalized symmetric-definite| complex generalized Hermitian-definite)
1023 : : !! eigenproblem, of the form
1024 : : !! A*x=(lambda)*B*x (1),
1025 : : !! A*Bx=(lambda)*x, (2), or
1026 : : !! B*A*x=(lambda)*x (3).
1027 : : !! Here A and B are assumed to be (symmetric|Hermitian) and B is also positive definite.
1028 : : !!
1029 : : !! INPUTS
1030 : : !! ITYPE (input) INTEGER Specifies the problem type to be solved:
1031 : : !! = 1: A*x = (lambda)*B*x
1032 : : !! = 2: A*B*x = (lambda)*x
1033 : : !! = 3: B*A*x = (lambda)*x
1034 : : !!
1035 : : !! JOBZ (input) CHARACTER*1
1036 : : !! = "N": Compute eigenvalues only;
1037 : : !! = "V": Compute eigenvalues and eigenvectors.
1038 : : !!
1039 : : !! UPLO (input) CHARACTER*1
1040 : : !! = "U": Upper triangle of A and B are stored;
1041 : : !! = "L": Lower triangle of A and B are stored.
1042 : : !!
1043 : : !! CPLEX Size of the first dimension of the A and B matrices.
1044 : : !! 1 for a real symmetric matrix.
1045 : : !! 2 for a complex Hermitian matrix.
1046 : : !!
1047 : : !! N (input) INTEGER
1048 : : !! The order of the matrices A and B. N >= 0.
1049 : : !!
1050 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
1051 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
1052 : : !! in this case the sequential LAPACK routine is called.
1053 : : !!
1054 : : !! OUTPUT
1055 : : !! W (output) REAL(DP) array, dimension (N)
1056 : : !! If INFO = 0, the eigenvalues in ascending order.
1057 : : !!
1058 : : !! See also SIDE EFFECTS
1059 : : !!
1060 : : !! SIDE EFFECTS
1061 : : !! A (input/output) REAL(DP) array, dimension (CPLEX,N, N)
1062 : : !! On entry, the (real symmetric|Hermitian) matrix A. If UPLO = "U", the leading N-by-N upper triangular part of A
1063 : : !! <S-F1>contains the upper triangular part of the matrix A.
1064 : : !! If UPLO = "L", the leading N-by-N lower triangular part of A contains the lower triangular part of the matrix A.
1065 : : !!
1066 : : !! On exit, if JOBZ = "V", then A contains the matrix Z of eigenvectors.
1067 : : !! The eigenvectors are normalized as follows:
1068 : : !! if ITYPE =1 or 2:
1069 : : !! Z**T*B*Z = I if CPLEX=1
1070 : : !! Z**H*B*Z = I if CPLEX=2.
1071 : : !! if ITYPE = 3,
1072 : : !! Z**T*inv(B)*Z = I if CPLEX=1
1073 : : !! Z**H*inv(B)*Z = I if CPLEX=2
1074 : : !!
1075 : : !! If JOBZ = "N", then on exit the upper triangle (if UPLO="U") or the lower triangle
1076 : : !! (if UPLO="L") of A, including the diagonal, is destroyed.
1077 : : !!
1078 : : !! B (input/output) REAL(DP) array, dimension (CPLEX,N, N)
1079 : : !! On entry, the (real symmetric|Hermitian) positive definite matrix B.
1080 : : !! If UPLO = "U", the leading N-by-N upper triangular part of B contains the upper triangular part of the matrix B.
1081 : : !! If UPLO = "L", the leading N-by-N lower triangular part of B contains the lower triangular part of the matrix B.
1082 : : !!
1083 : : !! On exit, if INFO <= N, the part of B containing the matrix is overwritten by the triangular
1084 : : !! factor U or L from the Cholesky factorization
1085 : : !! B = U**T*U or B = L*L**T if CPLEX=1
1086 : : !! B = U**H*U or B = L*L**H if CPLEX=2
1087 : : !!
1088 : : !! SOURCE
1089 : :
1090 : 0 : subroutine xhegv_cplex(itype, jobz, uplo, cplex, n, a, b, w, msg, ierr, comm)
1091 : :
1092 : : !Arguments ------------------------------------
1093 : : !scalars
1094 : : integer,intent(in) :: n,itype,cplex
1095 : : character(len=*),intent(in) :: jobz, uplo
1096 : : character(len=*),intent(out) :: msg
1097 : : integer,intent(out) :: ierr
1098 : : integer,optional,intent(in) :: comm
1099 : : !arrays
1100 : : real(dp),intent(inout) :: a(cplex,n,n), b(cplex,n,n)
1101 : : real(dp),intent(out) :: w(n)
1102 : :
1103 : : !Local variables ------------------------------
1104 : : !scalars
1105 : : integer :: lwork,nprocs,ii
1106 : : logical :: use_scalapack
1107 : : !arrays
1108 : 0 : real(dp),allocatable :: rwork(:), work_real(:)
1109 : 0 : complex(dp),allocatable :: work_cplx(:)
1110 : : #ifdef HAVE_LINALG_SCALAPACK
1111 : : !integer :: istwf_k
1112 : : !type(slkmat_dp_t) :: Slk_matA,Slk_matB
1113 : : !type(slk_processor_t) :: Slk_processor
1114 : : #endif
1115 : : !************************************************************************
1116 : :
1117 : 0 : use_scalapack = .FALSE.
1118 [ # # ]: 0 : if (present(comm)) then
1119 : 0 : nprocs = xmpi_comm_size(comm)
1120 : : #ifdef HAVE_LINALG_SCALAPACK
1121 : : use_scalapack = nprocs > 1
1122 : : #endif
1123 : : end if
1124 : :
1125 [ # # ]: 0 : if (all(cplex /= [1, 2])) then
1126 : 0 : write(msg,'(a,i0)')"Wrong value for cplex: ",cplex
1127 : 0 : ierr = 1; return
1128 : : end if
1129 : :
1130 : : SELECT CASE(use_scalapack)
1131 : : CASE (.FALSE.)
1132 : :
1133 [ # # ]: 0 : if (cplex==1) then
1134 : : ! Real symmetric case.
1135 : 0 : lwork = MAX(1,3*n-1)
1136 : :
1137 [ # # # # : 0 : ABI_MALLOC(work_real,(lwork))
# # # # #
# ]
1138 : 0 : call DSYGV(itype,jobz,uplo,n,a,n,b,n,w,work_real,lwork,ierr)
1139 : :
1140 [ # # ]: 0 : if (ierr < 0) then
1141 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of DSYGV had an illegal value."
1142 : : end if
1143 : :
1144 [ # # ]: 0 : if (ierr > 0) then
1145 [ # # ]: 0 : if (ierr <= n) then
1146 : : write(msg,'(2a,i0,a)')&
1147 : 0 : " DSYGV failed to converge: ",ch10,&
1148 : 0 : ierr," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
1149 : : else
1150 : 0 : ii = ierr - n
1151 : : write(msg,'(3a,i0,3a)')&
1152 : 0 : "DSYGV failed to converge: ",ch10,&
1153 : 0 : "The leading minor of order ",ii," of B is not positive definite. ",ch10,&
1154 : 0 : "The factorization of B could not be completed and no eigenvalues or eigenvectors were computed."
1155 : : end if
1156 : : end if
1157 : :
1158 [ # # ]: 0 : ABI_FREE(work_real)
1159 : 0 : return
1160 : :
1161 : : else
1162 : : ! complex Hermitian case
1163 : 0 : lwork = MAX(1,2*n-1)
1164 : :
1165 [ # # # # : 0 : ABI_MALLOC(work_cplx,(lwork))
# # # # #
# ]
1166 [ # # # # : 0 : ABI_MALLOC(rwork,(MAX(1,3*n-2)))
# # # # #
# ]
1167 : :
1168 : 0 : call ZHEGV(itype,jobz,uplo,n,a,n,b,n,w,work_cplx,lwork,rwork,ierr)
1169 : :
1170 [ # # ]: 0 : if (ierr < 0) then
1171 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of ZHEGV had an illegal value."
1172 : : end if
1173 : :
1174 [ # # ]: 0 : if (ierr > 0) then
1175 [ # # ]: 0 : if (ierr <= n) then
1176 : : write(msg,'(2a,i0,a)')&
1177 : 0 : "ZHEGV failed to converge: ",ch10,&
1178 : 0 : ierr," off-diagonal elements of an intermediate tridiagonal form did not converge to zero. "
1179 : : else
1180 : 0 : ii = ierr -n
1181 : : write(msg,'(3a,i0,3a)')&
1182 : 0 : "ZHEGV failed to converge: ",ch10,&
1183 : 0 : "The leading minor of order ",ii," of B is not positive definite. ",ch10,&
1184 : 0 : "The factorization of B could not be completed and no eigenvalues or eigenvectors were computed."
1185 : : end if
1186 : : end if
1187 : :
1188 [ # # ]: 0 : ABI_FREE(rwork)
1189 [ # # ]: 0 : ABI_FREE(work_cplx)
1190 : 0 : return
1191 : : end if ! cplex
1192 : :
1193 : : CASE (.TRUE.)
1194 : :
1195 : : #ifdef HAVE_LINALG_SCALAPACK
1196 : :
1197 : : ABI_ERROR("Not coded yet")
1198 : : ! call Slk_processor%init(comm)
1199 : : ! istwf_k=1
1200 : :
1201 : : ! ! Initialize and fill Scalapack matrix from the global one.
1202 : : ! call Slk_matA%init(n,n,Slk_processor,istwf_k)
1203 : : ! call slk_matrix_from_global_dpc_2D(Slk_matA,uplo,a)
1204 : :
1205 : : ! call Slk_matB%init(n,n,Slk_processor,istwf_k)
1206 : : ! call slk_matrix_from_global_dpc_2D(Slk_matB,uplo,b)
1207 : :
1208 : : ! ! Solve the problem with scaLAPACK.
1209 : : ! ABI_ERROR("slk_pZHEGV not yet coded")
1210 : : ! ! TODO
1211 : : ! call slk_pzhegv(itype,jobz,uplo,Slk_matA,Slk_matB,w)
1212 : :
1213 : : ! call Slk_matB%free()
1214 : : !
1215 : : ! if (firstchar(jobz,(/"V","v"/))) then ! A is overwritten with the eigenvectors
1216 : : ! a = czero
1217 : : ! call slk_matrix_to_global_dpc_2D(Slk_matA,"All",a) ! Fill the entries calculated by this node.
1218 : : ! call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
1219 : : ! end if
1220 : :
1221 : : ! call Slk_matA%free()
1222 : :
1223 : : ! call Slk_processor%free()
1224 : :
1225 : : RETURN
1226 : : #endif
1227 : :
1228 : : ABI_BUG("You should not be here!")
1229 : : END SELECT
1230 : :
1231 : : end subroutine xhegv_cplex
1232 : : !!***
1233 : :
1234 : : !----------------------------------------------------------------------
1235 : :
1236 : : !!****f* m_hide_lapack/wrap_ZHEEVX
1237 : : !! NAME
1238 : : !! wrap_ZHEEVX
1239 : : !!
1240 : : !! FUNCTION
1241 : : !! wrap_ZHEEVX computes selected eigenvalues and, optionally, eigenvectors
1242 : : !! of a complex Hermitian matrix A. Eigenvalues and eigenvectors can
1243 : : !! be selected by specifying either a range of values or a range of
1244 : : !! indices for the desired eigenvalues.
1245 : : !!
1246 : : !! INPUTS
1247 : : !! JOBZ (input) CHARACTER*1
1248 : : !! = 'N': Compute eigenvalues only;
1249 : : !! = 'V': Compute eigenvalues and eigenvectors.
1250 : : !!
1251 : : !! RANGE (input) CHARACTER*1
1252 : : !! = 'A': all eigenvalues will be found.
1253 : : !! = 'V': all eigenvalues in the half-open interval (VL,VU]
1254 : : !! will be found.
1255 : : !! = 'I': the IL-th through IU-th eigenvalues will be found.
1256 : : !!
1257 : : !! UPLO (input) CHARACTER*1
1258 : : !! = 'U': Upper triangle of A is stored;
1259 : : !! = 'L': Lower triangle of A is stored.
1260 : : !!
1261 : : !! N (input) INTEGER
1262 : : !! The order of the matrix A. N >= 0.
1263 : : !!
1264 : : !! LDA (input) INTEGER
1265 : : !! The leading dimension of the array A. LDA >= max(1,N).
1266 : : !!
1267 : : !! VL (input) REAL(DP)
1268 : : !! VU (input) REAL(DP)
1269 : : !! If RANGE='V', the lower and upper bounds of the interval to
1270 : : !! be searched for eigenvalues. VL < VU.
1271 : : !! Not referenced if RANGE = 'A' or 'I'.
1272 : : !!
1273 : : !! IL (input) INTEGER
1274 : : !! IU (input) INTEGER
1275 : : !! If RANGE='I', the indices (in ascending order) of the
1276 : : !! smallest and largest eigenvalues to be returned.
1277 : : !! 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
1278 : : !! Not referenced if RANGE = 'A' or 'V'.
1279 : : !!
1280 : : !! ABSTOL (input) REAL(DP)
1281 : : !! The absolute error tolerance for the eigenvalues.
1282 : : !! An approximate eigenvalue is accepted as converged
1283 : : !! when it is determined to lie in an interval [a,b]
1284 : : !! of width less than or equal to
1285 : : !!
1286 : : !! ABSTOL + EPS * max( |a|,|b| ) ,
1287 : : !!
1288 : : !! where EPS is the machine precision. If ABSTOL is less than
1289 : : !! or equal to zero, then EPS*|T| will be used in its place,
1290 : : !! where |T| is the 1-norm of the tridiagonal matrix obtained
1291 : : !! by reducing A to tridiagonal form.
1292 : : !!
1293 : : !! Eigenvalues will be computed most accurately when ABSTOL is
1294 : : !! set to twice the underflow threshold 2*DLAMCH('S'), not zero.
1295 : : !! If this routine returns with INFO>0, indicating that some
1296 : : !! eigenvectors did not converge, try setting ABSTOL to
1297 : : !! 2*DLAMCH('S').
1298 : : !!
1299 : : !! See "Computing Small Singular Values of Bidiagonal Matrices
1300 : : !! with Guaranteed High Relative Accuracy," by Demmel and
1301 : : !! Kahan, LAPACK Working Note #3.
1302 : : !!
1303 : : !! LDZ (input) INTEGER
1304 : : !! The leading dimension of the array Z. LDZ >= 1, and if
1305 : : !! JOBZ = 'V', LDZ >= max(1,N).
1306 : : !!
1307 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
1308 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
1309 : : !! in this case the sequential LAPACK routine is called.
1310 : : !!
1311 : : !! OUTPUT
1312 : : !! M (output) INTEGER
1313 : : !! The total number of eigenvalues found. 0 <= M <= N.
1314 : : !! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
1315 : : !!
1316 : : !! W (output) REAL(DP) array, dimension (N)
1317 : : !! On normal exit, the first M elements contain the selected
1318 : : !! eigenvalues in ascending order.
1319 : : !!
1320 : : !! Z (output) COMPLEX(DP) array, dimension (LDZ, max(1,M))
1321 : : !! If JOBZ = 'V', then if INFO = 0, the first M columns of Z
1322 : : !! contain the orthonormal eigenvectors of the matrix A
1323 : : !! corresponding to the selected eigenvalues, with the i-th
1324 : : !! column of Z holding the eigenvector associated with W(i).
1325 : : !! If an eigenvector fails to converge, then that column of Z
1326 : : !! contains the latest approximation to the eigenvector, and the
1327 : : !! index of the eigenvector is returned in IFAIL.
1328 : : !! If JOBZ = 'N', then Z is not referenced.
1329 : : !! Note: the user must ensure that at least max(1,M) columns are
1330 : : !! supplied in the array Z; if RANGE = 'V', the exact value of M
1331 : : !! is not known in advance and an upper bound must be used.
1332 : : !!
1333 : : !! See also SIDE EFFECTS
1334 : : !!
1335 : : !! SIDE EFFECTS
1336 : : !! A (input/output) COMPLEX(DP) array, dimension (N, N)
1337 : : !! On entry, the Hermitian matrix A. If UPLO = 'U', the
1338 : : !! leading N-by-N upper triangular part of A contains the
1339 : : !! upper triangular part of the matrix A. If UPLO = 'L',
1340 : : !! the leading N-by-N lower triangular part of A contains
1341 : : !! the lower triangular part of the matrix A.
1342 : : !! On exit, the lower triangle (if UPLO='L') or the upper
1343 : : !! triangle (if UPLO='U') of A, including the diagonal, is
1344 : : !! destroyed.
1345 : : !!
1346 : : !! SOURCE
1347 : :
1348 : 1 : subroutine wrap_ZHEEVX(jobz,range,uplo,n,a,vl,vu,il,iu,abstol,m,w,z,ldz,comm)
1349 : :
1350 : : !Arguments ------------------------------------
1351 : : !scalars
1352 : : integer,intent(in) :: il,iu,ldz,n
1353 : : integer,optional,intent(in) :: comm
1354 : : integer,intent(inout) :: m
1355 : : real(dp),intent(in) :: abstol,vl,vu
1356 : : character(len=*),intent(in) :: jobz,range,uplo
1357 : : !arrays
1358 : : real(dp),intent(out) :: w(n)
1359 : : complex(dp),intent(out) :: z(ldz,m)
1360 : : complex(dp),intent(inout) :: a(n,n)
1361 : :
1362 : : !Local variables ------------------------------
1363 : : !scalars
1364 : : integer :: lwork,info,nprocs
1365 : : logical :: use_scalapack
1366 : : character(len=500) :: msg
1367 : : !arrays
1368 : 1 : integer,allocatable :: ifail(:),iwork(:)
1369 : 1 : real(dp),allocatable :: rwork(:)
1370 : 1 : complex(dp),allocatable :: work(:)
1371 : : #ifdef HAVE_LINALG_SCALAPACK
1372 : : integer :: ierr,istwf_k
1373 : : logical :: want_eigenvectors
1374 : : type(slkmat_dp_t) :: Slk_mat,Slk_vec
1375 : : type(slk_processor_t) :: Slk_processor
1376 : : #endif
1377 : : !************************************************************************
1378 : :
1379 : 1 : use_scalapack=.FALSE.
1380 [ - + ]: 1 : if (PRESENT(comm)) then
1381 : 0 : nprocs = xmpi_comm_size(comm)
1382 : : #ifdef HAVE_LINALG_SCALAPACK
1383 : : use_scalapack = (nprocs>1)
1384 : : #endif
1385 : : end if
1386 : :
1387 : : SELECT CASE(use_scalapack)
1388 : : CASE (.FALSE.) ! Standard LAPACK call.
1389 : :
1390 : 1 : lwork = MAX(1,2*n)
1391 [ - + + - : 3 : ABI_MALLOC(work,(lwork))
+ - - + -
+ ]
1392 [ + - - + : 3 : ABI_MALLOC(rwork,(7*n))
+ - + - +
- - + -
+ ]
1393 [ + - - + : 3 : ABI_MALLOC(iwork,(5*n))
+ - + - +
- - + -
+ ]
1394 [ - + + - : 3 : ABI_MALLOC(ifail,(n))
+ - + - -
+ - + ]
1395 : :
1396 : 1 : call ZHEEVX(jobz,range,uplo,n,a,n,vl,vu,il,iu,abstol,m,w,z,ldz,work,lwork,rwork,iwork,ifail,info)
1397 : :
1398 [ - + ]: 1 : if (info < 0) then
1399 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZHEEVX had an illegal value."
1400 : 0 : ABI_ERROR(msg)
1401 : : end if
1402 : :
1403 [ - + ]: 1 : if (info > 0) then
1404 : 0 : write(msg,'(2a,i0,a)')"ZHEEVX: the algorithm failed to converge; ",ch10,&
1405 : 0 : info,"eigenvectors failed to converge. "
1406 : 0 : ABI_ERROR(msg)
1407 : : end if
1408 : :
1409 [ - + ]: 1 : ABI_FREE(iwork)
1410 [ - + ]: 1 : ABI_FREE(ifail)
1411 [ - + ]: 1 : ABI_FREE(rwork)
1412 [ - + ]: 1 : ABI_FREE(work)
1413 : : RETURN
1414 : :
1415 : : CASE (.TRUE.)
1416 : :
1417 : : #ifdef HAVE_LINALG_SCALAPACK
1418 : : call Slk_processor%init(comm)
1419 : : istwf_k=1
1420 : :
1421 : : ! Initialize and fill Scalapack matrix from the global one.
1422 : : call Slk_mat%init(n,n,Slk_processor,istwf_k)
1423 : : call slk_matrix_from_global_dpc_2D(Slk_mat,uplo,a)
1424 : :
1425 : : want_eigenvectors = firstchar(jobz,(/"V","v"/))
1426 : : if (want_eigenvectors) then
1427 : : ! Initialize the distributed vectors.
1428 : : call Slk_vec%init(n,n,Slk_processor,istwf_k)
1429 : : end if
1430 : :
1431 : : ! Solve the problem.
1432 : : call slk_mat%pzheevx(jobz,range,uplo,vl,vu,il,iu,abstol,Slk_vec,m,w)
1433 : : call Slk_mat%free()
1434 : :
1435 : : if (want_eigenvectors) then ! A is overwritten with the eigenvectors
1436 : : z = czero
1437 : : call slk_matrix_to_global_dpc_2D(Slk_vec,"All",z) ! Fill the entries calculated by this node.
1438 : : call Slk_vec%free()
1439 : : call xmpi_sum(z,comm,ierr) ! Fill the remaining entries of the global matrix
1440 : : end if
1441 : :
1442 : : call Slk_processor%free()
1443 : : RETURN
1444 : : #endif
1445 : :
1446 : : ABI_BUG("You should not be here!")
1447 : : END SELECT
1448 : :
1449 : : end subroutine wrap_ZHEEVX
1450 : : !!***
1451 : :
1452 : : !----------------------------------------------------------------------
1453 : :
1454 : : !!****f* m_hide_lapack/xheevx_cplex
1455 : : !! NAME
1456 : : !! xheevx_cplex
1457 : : !!
1458 : : !! FUNCTION
1459 : : !! xheevx_cplex computes selected eigenvalues and, optionally, eigenvectors
1460 : : !! of a (real symmetric|complex Hermitian) matrix A. Eigenvalues and eigenvectors can
1461 : : !! be selected by specifying either a range of values or a range of
1462 : : !! indices for the desired eigenvalues.
1463 : : !!
1464 : : !! INPUTS
1465 : : !! JOBZ (input) CHARACTER*1
1466 : : !! = 'N': Compute eigenvalues only;
1467 : : !! = 'V': Compute eigenvalues and eigenvectors.
1468 : : !!
1469 : : !! RANGE (input) CHARACTER*1
1470 : : !! = 'A': all eigenvalues will be found.
1471 : : !! = 'V': all eigenvalues in the half-open interval (VL,VU]
1472 : : !! will be found.
1473 : : !! = 'I': the IL-th through IU-th eigenvalues will be found.
1474 : : !!
1475 : : !! UPLO (input) CHARACTER*1
1476 : : !! = 'U': Upper triangle of A is stored;
1477 : : !! = 'L': Lower triangle of A is stored.
1478 : : !!
1479 : : !! CPLEX Size of the first dimension of the matrix A.
1480 : : !! 1 for real symmetric matrix
1481 : : !! 2 for complex Hermitian matrix.
1482 : : !!
1483 : : !! N (input) INTEGER
1484 : : !! The order of the matrix A. N >= 0.
1485 : : !!
1486 : : !! LDA (input) INTEGER
1487 : : !! The leading dimension of the array A. LDA >= max(1,N).
1488 : : !!
1489 : : !! VL (input) REAL(DP)
1490 : : !! VU (input) REAL(DP)
1491 : : !! If RANGE='V', the lower and upper bounds of the interval to
1492 : : !! be searched for eigenvalues. VL < VU.
1493 : : !! Not referenced if RANGE = 'A' or 'I'.
1494 : : !!
1495 : : !! IL (input) INTEGER
1496 : : !! IU (input) INTEGER
1497 : : !! If RANGE='I', the indices (in ascending order) of the
1498 : : !! smallest and largest eigenvalues to be returned.
1499 : : !! 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
1500 : : !! Not referenced if RANGE = 'A' or 'V'.
1501 : : !!
1502 : : !! ABSTOL (input) REAL(DP)
1503 : : !! The absolute error tolerance for the eigenvalues.
1504 : : !! An approximate eigenvalue is accepted as converged
1505 : : !! when it is determined to lie in an interval [a,b]
1506 : : !! of width less than or equal to
1507 : : !!
1508 : : !! ABSTOL + EPS * max( |a|,|b| ) ,
1509 : : !!
1510 : : !! where EPS is the machine precision. If ABSTOL is less than
1511 : : !! or equal to zero, then EPS*|T| will be used in its place,
1512 : : !! where |T| is the 1-norm of the tridiagonal matrix obtained
1513 : : !! by reducing A to tridiagonal form.
1514 : : !!
1515 : : !! Eigenvalues will be computed most accurately when ABSTOL is
1516 : : !! set to twice the underflow threshold 2*DLAMCH('S'), not zero.
1517 : : !! If this routine returns with INFO>0, indicating that some
1518 : : !! eigenvectors did not converge, try setting ABSTOL to
1519 : : !! 2*DLAMCH('S').
1520 : : !!
1521 : : !! See "Computing Small Singular Values of Bidiagonal Matrices
1522 : : !! with Guaranteed High Relative Accuracy," by Demmel and
1523 : : !! Kahan, LAPACK Working Note #3.
1524 : : !!
1525 : : !! LDZ (input) INTEGER
1526 : : !! The leading dimension of the array Z. LDZ >= 1, and if
1527 : : !! JOBZ = 'V', LDZ >= max(1,N).
1528 : : !!
1529 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
1530 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
1531 : : !! in this case the sequential LAPACK routine is called.
1532 : : !!
1533 : : !! OUTPUT
1534 : : !! M (output) INTEGER
1535 : : !! The total number of eigenvalues found. 0 <= M <= N.
1536 : : !! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
1537 : : !!
1538 : : !! W (output) REAL(DP) array, dimension (N)
1539 : : !! On normal exit, the first M elements contain the selected
1540 : : !! eigenvalues in ascending order.
1541 : : !!
1542 : : !! Z (output) REAL(DP) array, dimension (CPLEX, LDZ, max(1,M))
1543 : : !! If JOBZ = 'V', then if INFO = 0, the first M columns of Z
1544 : : !! contain the orthonormal eigenvectors of the matrix A
1545 : : !! corresponding to the selected eigenvalues, with the i-th
1546 : : !! column of Z holding the eigenvector associated with W(i).
1547 : : !! If an eigenvector fails to converge, then that column of Z
1548 : : !! contains the latest approximation to the eigenvector, and the
1549 : : !! index of the eigenvector is returned in IFAIL.
1550 : : !! If JOBZ = 'N', then Z is not referenced.
1551 : : !! Note: the user must ensure that at least max(1,M) columns are
1552 : : !! supplied in the array Z; if RANGE = 'V', the exact value of M
1553 : : !! is not known in advance and an upper bound must be used.
1554 : : !!
1555 : : !! See also SIDE EFFECTS
1556 : : !!
1557 : : !! SIDE EFFECTS
1558 : : !! A (input/output) REAL(DP) array, dimension (CPLEX, N, N)
1559 : : !! On entry, the (real symmetric|complex Hermitian) matrix A. If UPLO = 'U', the
1560 : : !! leading N-by-N upper triangular part of A contains the
1561 : : !! upper triangular part of the matrix A. If UPLO = 'L',
1562 : : !! the leading N-by-N lower triangular part of A contains
1563 : : !! the lower triangular part of the matrix A.
1564 : : !! On exit, the lower triangle (if UPLO='L') or the upper
1565 : : !! triangle (if UPLO='U') of A, including the diagonal, is
1566 : : !! destroyed.
1567 : : !!
1568 : : !! SOURCE
1569 : :
1570 : 10 : subroutine xheevx_cplex(jobz, range, uplo, cplex, n, a, vl, vu, il, iu, &
1571 : 10 : abstol, m, w, z, ldz, msg, ierr, comm)
1572 : :
1573 : : !Arguments ------------------------------------
1574 : : !scalars
1575 : : integer,intent(in) :: il,iu,ldz,n,cplex
1576 : : integer,optional,intent(in) :: comm
1577 : : integer,intent(inout) :: m
1578 : : integer,intent(out) :: ierr
1579 : : real(dp),intent(in) :: abstol,vl,vu
1580 : : character(len=*),intent(in) :: jobz,range,uplo
1581 : : character(len=*),intent(out) :: msg
1582 : : !arrays
1583 : : real(dp),intent(out) :: w(n)
1584 : : !real(dp),intent(out) :: z(cplex,ldz,n)
1585 : : real(dp),intent(out) :: z(cplex,ldz,m)
1586 : : real(dp),intent(inout) :: a(cplex,n,n)
1587 : :
1588 : : !Local variables ------------------------------
1589 : : !scalars
1590 : : integer :: lwork,nprocs
1591 : : logical :: use_scalapack
1592 : : !arrays
1593 : 10 : integer,allocatable :: ifail(:),iwork(:)
1594 : 10 : real(dp),allocatable :: rwork(:)
1595 : 10 : real(dp),allocatable :: work_real(:)
1596 : 10 : complex(dp),allocatable :: work_cplx(:)
1597 : : #ifdef HAVE_LINALG_SCALAPACK
1598 : : !integer :: istwf_k
1599 : : !logical :: want_eigenvectors
1600 : : !type(slkmat_dp_t) :: Slk_mat,Slk_vec
1601 : : !type(slk_processor_t) :: Slk_processor
1602 : : #endif
1603 : : !************************************************************************
1604 : :
1605 : 10 : use_scalapack=.FALSE.
1606 [ - + ]: 10 : if (PRESENT(comm)) then
1607 : 0 : nprocs = xmpi_comm_size(comm)
1608 : : #ifdef HAVE_LINALG_SCALAPACK
1609 : : use_scalapack = (nprocs>1)
1610 : : #endif
1611 : : end if
1612 : :
1613 [ - + ]: 10 : if (ALL(cplex/=(/1,2/))) then
1614 : 0 : write(msg,'(a,i0)')" Wrong value for cplex: ",cplex
1615 : 0 : ierr = 1; return
1616 : : end if
1617 : :
1618 : : SELECT CASE(use_scalapack)
1619 : : CASE (.FALSE.)
1620 : : ! Standard LAPACK call.
1621 : :
1622 [ - + ]: 10 : if (cplex==1) then
1623 : : ! Real symmetric case
1624 : 0 : lwork = MAX(1,8*n)
1625 [ # # # # : 0 : ABI_MALLOC(work_real,(lwork))
# # # # #
# ]
1626 [ # # # # : 0 : ABI_MALLOC(iwork,(5*n))
# # # # #
# # # #
# ]
1627 [ # # # # : 0 : ABI_MALLOC(ifail,(n))
# # # # #
# # # ]
1628 : :
1629 : 0 : call DSYEVX(jobz,range,uplo,n,a,n,vl,vu,il,iu,abstol,m,w,z,ldz,work_real,lwork,iwork,ifail,ierr)
1630 : :
1631 [ # # ]: 0 : if (ierr < 0) then
1632 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of DSYEVX had an illegal value."
1633 : : end if
1634 : :
1635 [ # # ]: 0 : if (ierr > 0) then
1636 : : write(msg,'(2a,i0,a)')&
1637 : 0 : "DSYEVX: the algorithm failed to converge; ",ch10,ierr,"eigenvectors failed to converge. "
1638 : : end if
1639 : :
1640 [ # # ]: 0 : ABI_FREE(work_real)
1641 [ # # ]: 0 : ABI_FREE(iwork)
1642 [ # # ]: 0 : ABI_FREE(ifail)
1643 : 0 : RETURN
1644 : :
1645 : : else
1646 : : ! Complex Hermitian case.
1647 : 10 : lwork = MAX(1,2*n)
1648 [ - + + - : 30 : ABI_MALLOC(work_cplx,(lwork))
+ - - + -
+ ]
1649 [ + - - + : 30 : ABI_MALLOC(rwork,(7*n))
+ - + - +
- - + -
+ ]
1650 [ + - - + : 30 : ABI_MALLOC(iwork,(5*n))
+ - + - +
- - + -
+ ]
1651 [ - + + - : 30 : ABI_MALLOC(ifail,(n))
+ - + - -
+ - + ]
1652 : :
1653 : 10 : call ZHEEVX(jobz,range,uplo,n,a,n,vl,vu,il,iu,abstol,m,w,z,ldz,work_cplx,lwork,rwork,iwork,ifail,ierr)
1654 : :
1655 [ - + ]: 10 : if (ierr < 0) then
1656 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of ZHEEVX had an illegal value."
1657 : : end if
1658 : :
1659 [ - + ]: 10 : if (ierr > 0) then
1660 : : write(msg,'(2a,i0,a)')&
1661 : 0 : "ZHEEVX: the algorithm failed to converge; ",ch10,ierr,"eigenvectors failed to converge. "
1662 : : end if
1663 : :
1664 [ - + ]: 10 : ABI_FREE(iwork)
1665 [ - + ]: 10 : ABI_FREE(ifail)
1666 [ - + ]: 10 : ABI_FREE(rwork)
1667 [ - + ]: 10 : ABI_FREE(work_cplx)
1668 : 10 : RETURN
1669 : : end if
1670 : :
1671 : : CASE (.TRUE.)
1672 : :
1673 : : #ifdef HAVE_LINALG_SCALAPACK
1674 : : ABI_ERROR("Not coded yet")
1675 : : ! call Slk_processor%init(comm)
1676 : : ! istwf_k=1
1677 : :
1678 : : ! ! Initialize and fill Scalapack matrix from the global one.
1679 : : ! call Slk_mat%init(n,n,Slk_processor,istwf_k)
1680 : : ! call slk_matrix_from_global_dpc_2D(Slk_mat,uplo,a)
1681 : :
1682 : : ! want_eigenvectors = firstchar(jobz,(/"V","v"/))
1683 : : ! if (want_eigenvectors) then ! Initialize the distributed vectors.
1684 : : ! call Slk_vec%init(n,n,Slk_processor,istwf_k)
1685 : : ! end if
1686 : :
1687 : : ! ! Solve the problem.
1688 : : ! call slk_mat%pzheevx(jobz,range,uplo,vl,vu,il,iu,abstol,Slk_vec,m,w)
1689 : : ! call Slk_mat%free()
1690 : : !
1691 : : ! if (want_eigenvectors) then ! A is overwritten with the eigenvectors
1692 : : ! z = czero
1693 : : ! call slk_matrix_to_global_dpc_2D(Slk_vec,"All",z) ! Fill the entries calculated by this node.
1694 : : ! call Slk_vec%free()
1695 : : ! call xmpi_sum(z,comm,ierr) ! Fill the remaining entries of the global matrix
1696 : : ! end if
1697 : :
1698 : : ! call Slk_processor%free()
1699 : :
1700 : : RETURN
1701 : : #endif
1702 : :
1703 : : ABI_BUG("You should not be here!")
1704 : : END SELECT
1705 : :
1706 : : end subroutine xheevx_cplex
1707 : : !!***
1708 : :
1709 : : !----------------------------------------------------------------------
1710 : :
1711 : : !!****f* m_hide_lapack/wrap_ZHEGVX
1712 : : !! NAME
1713 : : !! wrap_ZHEGVX
1714 : : !!
1715 : : !! FUNCTION
1716 : : !! wrap_ZHEGVX - compute selected eigenvalues, and optionally, eigenvectors of a
1717 : : !! complex generalized Hermitian-definite eigenproblem, of the form A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x.
1718 : : !! Eigenvalues and eigenvectors can be selected by specifying either a range of values or a range of
1719 : : !! indices for the desired eigenvalues.
1720 : : !!
1721 : : !! INPUTS
1722 : : !!
1723 : : !! ITYPE (input) INTEGER Specifies the problem type to be solved:
1724 : : !! = 1: A*x = (lambda)*B*x
1725 : : !! = 2: A*B*x = (lambda)*x
1726 : : !! = 3: B*A*x = (lambda)*x
1727 : : !!
1728 : : !! JOBZ (input) CHARACTER*1
1729 : : !! = 'N': Compute eigenvalues only;
1730 : : !! = 'V': Compute eigenvalues and eigenvectors.
1731 : : !!
1732 : : !! RANGE (input) CHARACTER*1
1733 : : !! = 'A': all eigenvalues will be found.
1734 : : !! = 'V': all eigenvalues in the half-open interval (VL,VU]
1735 : : !! will be found.
1736 : : !! = 'I': the IL-th through IU-th eigenvalues will be found.
1737 : : !!
1738 : : !! UPLO (input) CHARACTER*1
1739 : : !! = 'U': Upper triangle of A is stored;
1740 : : !! = 'L': Lower triangle of A is stored.
1741 : : !!
1742 : : !! N (input) INTEGER
1743 : : !! The order of the matrices A and B. N >= 0.
1744 : : !!
1745 : : !! LDA (input) INTEGER
1746 : : !! The leading dimension of the array A. LDA >= max(1,N).
1747 : : !!
1748 : : !! VL (input) REAL(DP)
1749 : : !! VU (input) REAL(DP)
1750 : : !! If RANGE='V', the lower and upper bounds of the interval to
1751 : : !! be searched for eigenvalues. VL < VU.
1752 : : !! Not referenced if RANGE = 'A' or 'I'.
1753 : : !!
1754 : : !! IL (input) INTEGER
1755 : : !! IU (input) INTEGER
1756 : : !! If RANGE='I', the indices (in ascending order) of the
1757 : : !! smallest and largest eigenvalues to be returned.
1758 : : !! 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
1759 : : !! Not referenced if RANGE = 'A' or 'V'.
1760 : : !!
1761 : : !! ABSTOL (input) REAL(DP)
1762 : : !! The absolute error tolerance for the eigenvalues.
1763 : : !! An approximate eigenvalue is accepted as converged
1764 : : !! when it is determined to lie in an interval [a,b]
1765 : : !! of width less than or equal to
1766 : : !!
1767 : : !! ABSTOL + EPS * max( |a|,|b| ) ,
1768 : : !!
1769 : : !! where EPS is the machine precision. If ABSTOL is less than
1770 : : !! or equal to zero, then EPS*|T| will be used in its place,
1771 : : !! where |T| is the 1-norm of the tridiagonal matrix obtained
1772 : : !! by reducing A to tridiagonal form.
1773 : : !!
1774 : : !! Eigenvalues will be computed most accurately when ABSTOL is
1775 : : !! set to twice the underflow threshold 2*DLAMCH('S'), not zero.
1776 : : !! If this routine returns with INFO>0, indicating that some
1777 : : !! eigenvectors did not converge, try setting ABSTOL to
1778 : : !! 2*DLAMCH('S').
1779 : : !!
1780 : : !! LDZ (input) INTEGER
1781 : : !! The leading dimension of the array Z. LDZ >= 1, and if
1782 : : !! JOBZ = 'V', LDZ >= max(1,N).
1783 : : !!
1784 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
1785 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
1786 : : !! in this case the sequential LAPACK routine is called.
1787 : : !!
1788 : : !! OUTPUT
1789 : : !! M (output) INTEGER
1790 : : !! The total number of eigenvalues found. 0 <= M <= N.
1791 : : !! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
1792 : : !!
1793 : : !! W (output) REAL(DP) array, dimension (N)
1794 : : !! On normal exit, the first M elements contain the selected
1795 : : !! eigenvalues in ascending order.
1796 : : !!
1797 : : !! Z (output) COMPLEX(DP) array, dimension (LDZ, max(1,M))
1798 : : !! If JOBZ = 'V', then if INFO = 0, the first M columns of Z
1799 : : !! contain the orthonormal eigenvectors of the matrix A
1800 : : !! corresponding to the selected eigenvalues, with the i-th
1801 : : !! column of Z holding the eigenvector associated with W(i).
1802 : : !! The eigenvectors are normalized as follows: if ITYPE = 1 or 2, Z**T*B*Z = I; if ITYPE = 3, Z**T*inv(B)*Z = I.
1803 : : !! If an eigenvector fails to converge, then that column of Z
1804 : : !! contains the latest approximation to the eigenvector, and the
1805 : : !! index of the eigenvector is returned in IFAIL.
1806 : : !! If JOBZ = 'N', then Z is not referenced.
1807 : : !! Note: the user must ensure that at least max(1,M) columns are
1808 : : !! supplied in the array Z; if RANGE = 'V', the exact value of M
1809 : : !! is not known in advance and an upper bound must be used.
1810 : : !!
1811 : : !! See also SIDE EFFECTS
1812 : : !!
1813 : : !! SIDE EFFECTS
1814 : : !! A (input/output) COMPLEX(DP) array, dimension (N, N)
1815 : : !! On entry, the Hermitian matrix A. If UPLO = 'U', the
1816 : : !! leading N-by-N upper triangular part of A contains the
1817 : : !! upper triangular part of the matrix A. If UPLO = "L",
1818 : : !! the leading N-by-N lower triangular part of A contains
1819 : : !! the lower triangular part of the matrix A.
1820 : : !!
1821 : : !! On exit, the lower triangle (if UPLO="L") or the upper
1822 : : !! triangle (if UPLO="U") of A, including the diagonal, is
1823 : : !! destroyed.
1824 : : !!
1825 : : !! B (input/output) COMPLEX(DP) array, dimension (LDB, N)
1826 : : !! On entry, the Hermitian matrix B. If UPLO = "U", the leading N-by-N upper triangular part
1827 : : !! of B contains the upper triangular part of the matrix B.
1828 : : !! If UPLO = "L", the leading N-by-N lower triangular part of B contains the lower triangular part of the matrix B.
1829 : : !!
1830 : : !! On exit, if INFO <= N, the part of B containing the matrix is overwritten by the triangular factor
1831 : : !! U or L from the Cholesky factorization B = U**H*U or B = L*L**H.
1832 : : !!
1833 : : !! SOURCE
1834 : :
1835 : 0 : subroutine wrap_ZHEGVX(itype,jobz,range,uplo,n,a,b,vl,vu,il,iu,abstol,m,w,z,ldz,comm)
1836 : :
1837 : : !Arguments ------------------------------------
1838 : : !scalars
1839 : : integer,intent(in) :: il,iu,ldz,n,itype
1840 : : integer,optional,intent(in) :: comm
1841 : : integer,intent(inout) :: m
1842 : : real(dp),intent(in) :: abstol,vl,vu
1843 : : character(len=*),intent(in) :: jobz,range,uplo
1844 : : !arrays
1845 : : real(dp),intent(out) :: w(n)
1846 : : !complex(dp),intent(out) :: z(ldz,n)
1847 : : complex(dp),intent(out) :: z(ldz,m)
1848 : : complex(dp),intent(inout) :: a(n,n),b(n,n)
1849 : :
1850 : : !Local variables ------------------------------
1851 : : !scalars
1852 : : integer :: lwork,info,nprocs,ii
1853 : : logical :: use_scalapack
1854 : : character(len=500) :: msg
1855 : : !arrays
1856 : 0 : integer,allocatable :: ifail(:),iwork(:)
1857 : 0 : real(dp),allocatable :: rwork(:)
1858 : 0 : complex(dp),allocatable :: work(:)
1859 : : #ifdef HAVE_LINALG_SCALAPACK
1860 : : integer :: ierr,istwf_k
1861 : : logical :: want_eigenvectors
1862 : : type(slkmat_dp_t) :: Slk_matA,Slk_matB,Slk_vec
1863 : : type(slk_processor_t) :: Slk_processor
1864 : : #endif
1865 : : !************************************************************************
1866 : :
1867 : 0 : use_scalapack=.FALSE.
1868 [ # # ]: 0 : if (PRESENT(comm)) then
1869 : 0 : nprocs = xmpi_comm_size(comm)
1870 : : #ifdef HAVE_LINALG_SCALAPACK
1871 : : use_scalapack = (nprocs>1)
1872 : : #endif
1873 : : end if
1874 : :
1875 : : SELECT CASE(use_scalapack)
1876 : : CASE (.FALSE.)
1877 : : ! Standard LAPACK call.
1878 : 0 : lwork = MAX(1,2*n)
1879 [ # # # # : 0 : ABI_MALLOC(work,(lwork))
# # # # #
# ]
1880 [ # # # # : 0 : ABI_MALLOC(rwork,(7*n))
# # # # #
# # # #
# ]
1881 [ # # # # : 0 : ABI_MALLOC(iwork,(5*n))
# # # # #
# # # #
# ]
1882 [ # # # # : 0 : ABI_MALLOC(ifail,(n))
# # # # #
# # # ]
1883 : :
1884 : 0 : call ZHEGVX(itype,jobz,range,uplo,n,a,n,b,n,vl,vu,il,iu,abstol,m,w,z,ldz,work,lwork,rwork,iwork,ifail,info)
1885 : :
1886 [ # # ]: 0 : if (info < 0) then
1887 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZHEGVX had an illegal value."
1888 : 0 : ABI_ERROR(msg)
1889 : : end if
1890 : :
1891 [ # # ]: 0 : if (info > 0) then
1892 [ # # ]: 0 : if (info<= n) then
1893 : 0 : write(msg,'(a,i0,a)')"ZHEGVX failed to converge: ",info," eigenvectors failed to converge. "
1894 : : else
1895 : 0 : ii = info -n
1896 : : write(msg,'(3a,i0,3a)')&
1897 : 0 : "ZHEEVX failed to converge: ",ch10,&
1898 : 0 : "The leading minor of order ",ii," of B is not positive definite. ",ch10,&
1899 : 0 : "The factorization of B could not be completed and no eigenvalues or eigenvectors were computed."
1900 : : end if
1901 : 0 : ABI_ERROR(msg)
1902 : : end if
1903 : :
1904 [ # # ]: 0 : ABI_FREE(iwork)
1905 [ # # ]: 0 : ABI_FREE(ifail)
1906 [ # # ]: 0 : ABI_FREE(rwork)
1907 [ # # ]: 0 : ABI_FREE(work)
1908 : : RETURN
1909 : :
1910 : : CASE (.TRUE.)
1911 : :
1912 : : #ifdef HAVE_LINALG_SCALAPACK
1913 : : call Slk_processor%init(comm)
1914 : : istwf_k=1
1915 : :
1916 : : ! Initialize and fill Scalapack matrix from the global one.
1917 : : call Slk_matA%init(n,n,Slk_processor,istwf_k)
1918 : : call slk_matrix_from_global_dpc_2D(Slk_matA,uplo,a)
1919 : :
1920 : : call Slk_matB%init(n,n,Slk_processor,istwf_k)
1921 : : call slk_matrix_from_global_dpc_2D(Slk_matB,uplo,b)
1922 : :
1923 : : want_eigenvectors = firstchar(jobz,(/"V","v"/))
1924 : : if (want_eigenvectors) then ! Initialize the distributed vectors.
1925 : : call Slk_vec%init(n,n,Slk_processor,istwf_k)
1926 : : end if
1927 : :
1928 : : ! Solve the problem.
1929 : : ABI_ERROR("slk_pZHEGVX not coded yet")
1930 : : ! TODO write the scaLAPACK wrapper.
1931 : : !call slk_pZHEGVX(itype,jobz,range,uplo,Slk_matA,Slk_matB,vl,vu,il,iu,abstol,Slk_vec,m,w)
1932 : :
1933 : : call Slk_matA%free()
1934 : : call Slk_matB%free()
1935 : :
1936 : : if (want_eigenvectors) then ! A is overwritten with the eigenvectors
1937 : : z = czero
1938 : : call slk_matrix_to_global_dpc_2D(Slk_vec,"All",z) ! Fill the entries calculated by this node.
1939 : : call Slk_vec%free()
1940 : : call xmpi_sum(z,comm,ierr) ! Fill the remaining entries of the global matrix
1941 : : end if
1942 : :
1943 : : call Slk_processor%free()
1944 : :
1945 : : RETURN
1946 : : #endif
1947 : :
1948 : : ABI_BUG("You should not be here!")
1949 : : END SELECT
1950 : :
1951 : : end subroutine wrap_ZHEGVX
1952 : : !!***
1953 : :
1954 : : !----------------------------------------------------------------------
1955 : :
1956 : : !!****f* m_hide_lapack/xhegvx_cplex
1957 : : !! NAME
1958 : : !! xhegvx_cplex
1959 : : !!
1960 : : !! FUNCTION
1961 : : !! xhegvx_cplex - compute selected eigenvalues, and optionally, eigenvectors of a
1962 : : !! (real symmetric-definite|complex generalized Hermitian-definite) eigenproblem, of the form
1963 : : !! A*x=(lambda)*B*x, A*Bx=(lambda)*x, or B*A*x=(lambda)*x.
1964 : : !! Here A and B are assumed to be (real symmetric|complex Hermitian) and B is also positive definite.
1965 : : !! Eigenvalues and eigenvectors can be selected by specifying either a range of values or a range of
1966 : : !! indices for the desired eigenvalues.
1967 : : !!
1968 : : !! INPUTS
1969 : : !!
1970 : : !! ITYPE (input) INTEGER Specifies the problem type to be solved:
1971 : : !! = 1: A*x = (lambda)*B*x
1972 : : !! = 2: A*B*x = (lambda)*x
1973 : : !! = 3: B*A*x = (lambda)*x
1974 : : !!
1975 : : !! JOBZ (input) CHARACTER*1
1976 : : !! = 'N': Compute eigenvalues only;
1977 : : !! = 'V': Compute eigenvalues and eigenvectors.
1978 : : !!
1979 : : !! RANGE (input) CHARACTER*1
1980 : : !! = 'A': all eigenvalues will be found.
1981 : : !! = 'V': all eigenvalues in the half-open interval (VL,VU]
1982 : : !! will be found.
1983 : : !! = 'I': the IL-th through IU-th eigenvalues will be found.
1984 : : !!
1985 : : !! UPLO (input) CHARACTER*1
1986 : : !! = 'U': Upper triangle of A is stored;
1987 : : !! = 'L': Lower triangle of A is stored.
1988 : : !!
1989 : : !! CPLEX Size of the first dimension of the matrices A and B
1990 : : !! 1 for Real symmetric matrices
1991 : : !! 2 for complex Hermitianmatrices
1992 : : !!
1993 : : !! N (input) INTEGER
1994 : : !! The order of the matrices A and B. N >= 0.
1995 : : !!
1996 : : !! LDA (input) INTEGER
1997 : : !! The leading dimension of the array A. LDA >= max(1,N).
1998 : : !!
1999 : : !! VL (input) REAL(DP)
2000 : : !! VU (input) REAL(DP)
2001 : : !! If RANGE='V', the lower and upper bounds of the interval to
2002 : : !! be searched for eigenvalues. VL < VU.
2003 : : !! Not referenced if RANGE = 'A' or 'I'.
2004 : : !!
2005 : : !! IL (input) INTEGER
2006 : : !! IU (input) INTEGER
2007 : : !! If RANGE='I', the indices (in ascending order) of the
2008 : : !! smallest and largest eigenvalues to be returned.
2009 : : !! 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
2010 : : !! Not referenced if RANGE = 'A' or 'V'.
2011 : : !!
2012 : : !! ABSTOL (input) REAL(DP)
2013 : : !! The absolute error tolerance for the eigenvalues.
2014 : : !! An approximate eigenvalue is accepted as converged
2015 : : !! when it is determined to lie in an interval [a,b]
2016 : : !! of width less than or equal to
2017 : : !!
2018 : : !! ABSTOL + EPS * max( |a|,|b| ) ,
2019 : : !!
2020 : : !! where EPS is the machine precision. If ABSTOL is less than
2021 : : !! or equal to zero, then EPS*|T| will be used in its place,
2022 : : !! where |T| is the 1-norm of the tridiagonal matrix obtained
2023 : : !! by reducing A to tridiagonal form.
2024 : : !!
2025 : : !! Eigenvalues will be computed most accurately when ABSTOL is
2026 : : !! set to twice the underflow threshold 2*DLAMCH('S'), not zero.
2027 : : !! If this routine returns with INFO>0, indicating that some
2028 : : !! eigenvectors did not converge, try setting ABSTOL to
2029 : : !! 2*DLAMCH('S').
2030 : : !!
2031 : : !! LDZ (input) INTEGER
2032 : : !! The leading dimension of the array Z. LDZ >= 1, and if
2033 : : !! JOBZ = 'V', LDZ >= max(1,N).
2034 : : !!
2035 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
2036 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
2037 : : !! in this case the sequential LAPACK routine is called.
2038 : : !!
2039 : : !! OUTPUT
2040 : : !! M (output) INTEGER
2041 : : !! The total number of eigenvalues found. 0 <= M <= N.
2042 : : !! If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
2043 : : !!
2044 : : !! W (output) REAL(DP) array, dimension (N)
2045 : : !! On normal exit, the first M elements contain the selected
2046 : : !! eigenvalues in ascending order.
2047 : : !!
2048 : : !! Z (output) REAL(DP) array, dimension (CPLEX ,LDZ, max(1,M))
2049 : : !! If JOBZ = 'V', then if INFO = 0, the first M columns of Z
2050 : : !! contain the orthonormal eigenvectors of the matrix A
2051 : : !! corresponding to the selected eigenvalues, with the i-th
2052 : : !! column of Z holding the eigenvector associated with W(i).
2053 : : !! The eigenvectors are normalized as follows:
2054 : : !! if ITYPE = 1 or 2, Z**T*B*Z = I; if ITYPE = 3, Z**T*inv(B)*Z = I.
2055 : : !!
2056 : : !! If an eigenvector fails to converge, then that column of Z
2057 : : !! contains the latest approximation to the eigenvector, and the
2058 : : !! index of the eigenvector is returned in IFAIL.
2059 : : !! If JOBZ = 'N', then Z is not referenced.
2060 : : !! Note: the user must ensure that at least max(1,M) columns are
2061 : : !! supplied in the array Z; if RANGE = 'V', the exact value of M
2062 : : !! is not known in advance and an upper bound must be used.
2063 : : !!
2064 : : !! See also SIDE EFFECTS
2065 : : !!
2066 : : !! SIDE EFFECTS
2067 : : !! A (input/output) REAL(DP) array, dimension (CPLEX, N, N)
2068 : : !! On entry, the (real symmetric| complex Hermitian) matrix A. If UPLO = 'U', the
2069 : : !! leading N-by-N upper triangular part of A contains the
2070 : : !! upper triangular part of the matrix A. If UPLO = "L",
2071 : : !! the leading N-by-N lower triangular part of A contains
2072 : : !! the lower triangular part of the matrix A.
2073 : : !!
2074 : : !! On exit, the lower triangle (if UPLO="L") or the upper
2075 : : !! triangle (if UPLO="U") of A, including the diagonal, is
2076 : : !! destroyed.
2077 : : !!
2078 : : !! B (input/output) REAL(DP) array, dimension (CPLEX, LDB, N)
2079 : : !! On entry, the (real symmetric| complex Hermitian) matrix B. If UPLO = "U", the leading N-by-N upper triangular part
2080 : : !! of B contains the upper triangular part of the matrix B.
2081 : : !! If UPLO = "L", the leading N-by-N lower triangular part of B contains the lower triangular part of the matrix B.
2082 : : !!
2083 : : !! On exit, if INFO <= N, the part of B containing the matrix is overwritten by the triangular factor
2084 : : !! U or L from the Cholesky factorization B = U**H*U or B = L*L**H.
2085 : : !!
2086 : : !! SOURCE
2087 : :
2088 : 0 : subroutine xhegvx_cplex(itype, jobz, range, uplo, cplex, n, a, b, &
2089 : 0 : vl, vu, il, iu, abstol, m, w, z, ldz, msg, ierr, comm)
2090 : :
2091 : : !Arguments ------------------------------------
2092 : : !scalars
2093 : : integer,intent(in) :: il,iu,ldz,n,itype,cplex
2094 : : integer,optional,intent(in) :: comm
2095 : : integer,intent(inout) :: m
2096 : : integer,intent(out) :: ierr
2097 : : real(dp),intent(in) :: abstol,vl,vu
2098 : : character(len=*),intent(in) :: jobz,range,uplo
2099 : : character(len=*),intent(out) :: msg
2100 : : !arrays
2101 : : real(dp),intent(out) :: w(n)
2102 : : !real(dp),intent(out) :: z(cplex,ldz,n)
2103 : : real(dp),intent(out) :: z(cplex,ldz,m)
2104 : : real(dp),intent(inout) :: a(cplex,n,n),b(cplex,n,n)
2105 : :
2106 : : !Local variables ------------------------------
2107 : : !scalars
2108 : : integer :: lwork,nprocs,ii
2109 : : logical :: use_scalapack
2110 : : !arrays
2111 : 0 : integer,allocatable :: ifail(:),iwork(:)
2112 : 0 : real(dp),allocatable :: rwork(:)
2113 : 0 : real(dp),allocatable :: work_real(:)
2114 : 0 : complex(dp),allocatable :: work_cplx(:)
2115 : : #ifdef HAVE_LINALG_SCALAPACK
2116 : : !integer :: istwf_k
2117 : : !logical :: want_eigenvectors
2118 : : !type(slkmat_dp_t) :: Slk_matA,Slk_matB,Slk_vec
2119 : : !type(slk_processor_t) :: Slk_processor
2120 : : #endif
2121 : : !************************************************************************
2122 : :
2123 : 0 : use_scalapack=.FALSE.
2124 [ # # ]: 0 : if (PRESENT(comm)) then
2125 : 0 : nprocs = xmpi_comm_size(comm)
2126 : : #ifdef HAVE_LINALG_SCALAPACK
2127 : : use_scalapack = (nprocs>1)
2128 : : #endif
2129 : : end if
2130 : :
2131 [ # # ]: 0 : if (ALL(cplex/=(/1,2/))) then
2132 : 0 : write(msg,'(a,i0)')" Wrong value for cplex: ",cplex
2133 : 0 : ierr = 1; return
2134 : : end if
2135 : :
2136 : : SELECT CASE(use_scalapack)
2137 : :
2138 : : CASE (.FALSE.)
2139 : : ! Standard LAPACK call.
2140 [ # # ]: 0 : if (cplex==1) then
2141 : : ! Real symmetric case
2142 : 0 : lwork = MAX(1,8*n)
2143 : :
2144 [ # # # # : 0 : ABI_MALLOC(work_real,(lwork))
# # # # #
# ]
2145 [ # # # # : 0 : ABI_MALLOC(iwork,(5*n))
# # # # #
# # # #
# ]
2146 [ # # # # : 0 : ABI_MALLOC(ifail,(n))
# # # # #
# # # ]
2147 : :
2148 : 0 : call DSYGVX(itype,jobz,range,uplo,n,a,n,b,n,vl,vu,il,iu,abstol,m,w,z,ldz,work_real,lwork,iwork,ifail,ierr)
2149 : :
2150 [ # # ]: 0 : if (ierr < 0) then
2151 : 0 : write(msg,'(a,i0,a)')" The ",-ierr,"-th argument of DSYGVX had an illegal value."
2152 : : end if
2153 : :
2154 [ # # ]: 0 : if (ierr > 0) then
2155 [ # # ]: 0 : if (ierr<= n) then
2156 : 0 : write(msg,'(a,i0,a)')" DSYGVX failed to converge: ",ierr," eigenvectors failed to converge. "
2157 : : else
2158 : 0 : ii = ierr - n
2159 : : write(msg,'(3a,i0,3a)')&
2160 : 0 : " DSYGVX failed to converge: ",ch10,&
2161 : 0 : " The leading minor of order ",ii," of B is not positive definite. ",ch10,&
2162 : 0 : " The factorization of B could not be completed and no eigenvalues or eigenvectors were computed."
2163 : : end if
2164 : : end if
2165 : :
2166 [ # # ]: 0 : ABI_FREE(iwork)
2167 [ # # ]: 0 : ABI_FREE(ifail)
2168 [ # # ]: 0 : ABI_FREE(work_real)
2169 : 0 : RETURN
2170 : :
2171 : : else
2172 : : ! Complex Hermitian case.
2173 : 0 : lwork = MAX(1,2*n)
2174 : :
2175 [ # # # # : 0 : ABI_MALLOC(work_cplx,(lwork))
# # # # #
# ]
2176 [ # # # # : 0 : ABI_MALLOC(rwork,(7*n))
# # # # #
# # # #
# ]
2177 [ # # # # : 0 : ABI_MALLOC(iwork,(5*n))
# # # # #
# # # #
# ]
2178 [ # # # # : 0 : ABI_MALLOC(ifail,(n))
# # # # #
# # # ]
2179 : :
2180 : : !write(std_out,*)"Calling ZHEGVX"
2181 : 0 : call ZHEGVX(itype,jobz,range,uplo,n,a,n,b,n,vl,vu,il,iu,abstol,m,w,z,ldz,work_cplx,lwork,rwork,iwork,ifail,ierr)
2182 : :
2183 [ # # ]: 0 : if (ierr < 0) then
2184 : 0 : write(msg,'(a,i0,a)')"The ",-ierr,"-th argument of ZHEGVX had an illegal value."
2185 : : end if
2186 : :
2187 [ # # ]: 0 : if (ierr > 0) then
2188 [ # # ]: 0 : if (ierr<= n) then
2189 : 0 : write(msg,'(a,i0,a)')"ZHEGVX failed to converge: ",ierr," eigenvectors failed to converge. "
2190 : : else
2191 : 0 : ii = ierr -n
2192 : : write(msg,'(3a,i0,3a)')&
2193 : 0 : "ZHEEVX failed to converge: ",ch10,&
2194 : 0 : "The leading minor of order ",ii," of B is not positive definite. ",ch10,&
2195 : 0 : "The factorization of B could not be completed and no eigenvalues or eigenvectors were computed."
2196 : : end if
2197 : : end if
2198 : :
2199 [ # # ]: 0 : ABI_FREE(iwork)
2200 [ # # ]: 0 : ABI_FREE(ifail)
2201 [ # # ]: 0 : ABI_FREE(rwork)
2202 [ # # ]: 0 : ABI_FREE(work_cplx)
2203 : 0 : RETURN
2204 : : end if ! cplex
2205 : :
2206 : : CASE (.TRUE.)
2207 : :
2208 : : #ifdef HAVE_LINALG_SCALAPACK
2209 : : ABI_ERROR("not coded yet")
2210 : : ! call Slk_processor%init(comm)
2211 : : ! istwf_k=1
2212 : :
2213 : : ! ! Initialize and fill Scalapack matrix from the global one.
2214 : : ! call Slk_matA%init(n,n,Slk_processor,istwf_k)
2215 : : ! call slk_matrix_from_global_dpc_2D(Slk_matA,uplo,a)
2216 : :
2217 : : ! call Slk_matB%init(n,n,Slk_processor,istwf_k)
2218 : : ! call slk_matrix_from_global_dpc_2D(Slk_matB,uplo,b)
2219 : :
2220 : : ! want_eigenvectors = firstchar(jobz,(/"V","v"/))
2221 : : ! if (want_eigenvectors) then ! Initialize the distributed vectors.
2222 : : ! call Slk_vec%init(n,n,Slk_processor,istwf_k)
2223 : : ! end if
2224 : :
2225 : : ! ! Solve the problem.
2226 : : ! ABI_ERROR("slk_pZHEGVX not coded yet")
2227 : : ! ! TODO write the scaLAPACK wrapper.
2228 : : ! call slk_pZHEGVX(itype,jobz,range,uplo,Slk_matA,Slk_matB,vl,vu,il,iu,abstol,Slk_vec,m,w)
2229 : :
2230 : : ! call Slk_matA%free()
2231 : : ! call Slk_matB%free()
2232 : : !
2233 : : ! if (want_eigenvectors) then ! A is overwritten with the eigenvectors
2234 : : ! z = czero
2235 : : ! call slk_matrix_to_global_dpc_2D(Slk_vec,"All",z) ! Fill the entries calculated by this node.
2236 : : ! call Slk_vec%free()
2237 : : ! call xmpi_sum(z,comm,ierr) ! Fill the remaining entries of the global matrix
2238 : : ! end if
2239 : :
2240 : : ! call Slk_processor%free()
2241 : :
2242 : : ! RETURN
2243 : : #endif
2244 : :
2245 : : ABI_BUG("You should not be here!")
2246 : : END SELECT
2247 : :
2248 : : end subroutine xhegvx_cplex
2249 : : !!***
2250 : :
2251 : : !----------------------------------------------------------------------
2252 : :
2253 : : !!****f* m_hide_lapack/wrap_CGEEV
2254 : : !! NAME
2255 : : !! wrap_CGEEV
2256 : : !!
2257 : : !! FUNCTION
2258 : : !! wrap_CGEEV computes for an N-by-N complex nonsymmetric matrix A, the
2259 : : !! eigenvalues and, optionally, the left and/or right eigenvectors using single precision arithmetic. [PRIVATE]
2260 : : !!
2261 : : !! The right eigenvector v(j) of A satisfies: A * v(j) = lambda(j) * v(j)
2262 : : !! where lambda(j) is its eigenvalue.
2263 : : !! The left eigenvector u(j) of A satisfies u(j)**H * A = lambda(j) * u(j)**H
2264 : : !! where u(j)**H denotes the conjugate transpose of u(j).
2265 : : !!
2266 : : !! The computed eigenvectors are normalized to have Euclidean norm
2267 : : !! equal to 1 and largest component real.
2268 : : !!
2269 : : !! INPUTS
2270 : : !! JOBVL (input) CHARACTER*1
2271 : : !! = 'N': left eigenvectors of A are not computed;
2272 : : !! = 'V': left eigenvectors of are computed.
2273 : : !!
2274 : : !! JOBVR (input) CHARACTER*1
2275 : : !! = 'N': right eigenvectors of A are not computed;
2276 : : !! = 'V': right eigenvectors of A are computed.
2277 : : !!
2278 : : !! N (input) INTEGER
2279 : : !! The order of the matrix A. N >= 0.
2280 : : !!
2281 : : !! LDA (input) INTEGER
2282 : : !! The leading dimension of the array A. LDA >= max(1,N).
2283 : : !!
2284 : : !! LDVL (input) INTEGER
2285 : : !! The leading dimension of the array VL. LDVL >= 1; if
2286 : : !! JOBVL = 'V', LDVL >= N.
2287 : : !!
2288 : : !! LDVR (input) INTEGER
2289 : : !! The leading dimension of the array VR. LDVR >= 1; if
2290 : : !! JOBVR = 'V', LDVR >= N.
2291 : : !!
2292 : : !! OUTPUT
2293 : : !! W (output) COMPLEX(sp) array, dimension (N)
2294 : : !! W contains the computed eigenvalues.
2295 : : !! VL (output) COMPLEX(SCP) array, dimension (LDVL,N)
2296 : : !! If JOBVL = 'V', the left eigenvectors u(j) are stored one
2297 : : !! after another in the columns of VL, in the same order
2298 : : !! as their eigenvalues.
2299 : : !! If JOBVL = 'N', VL is not referenced.
2300 : : !! u(j) = VL(:,j), the j-th column of VL.
2301 : : !! VR (output) COMPLEX(sp) array, dimension (LDVR,N)
2302 : : !! If JOBVR = 'V', the right eigenvectors v(j) are stored one
2303 : : !! after another in the columns of VR, in the same order
2304 : : !! as their eigenvalues.
2305 : : !! If JOBVR = 'N', VR is not referenced.
2306 : : !! v(j) = VR(:,j), the j-th column of VR.
2307 : : !!
2308 : : !! See also SIDE EFFECTS
2309 : : !!
2310 : : !! SIDE EFFECTS
2311 : : !! A (input/output) COMPLEX(sp) array, dimension (LDA,N)
2312 : : !! On entry, the N-by-N matrix A.
2313 : : !! On exit, A has been overwritten.
2314 : : !!
2315 : : !! SOURCE
2316 : :
2317 : 0 : subroutine wrap_CGEEV(jobvl, jobvr, n, a, lda, w, vl, ldvl, vr, ldvr)
2318 : :
2319 : : !Arguments ------------------------------------
2320 : : !scalars
2321 : : integer,intent(in) :: n,lda,ldvl,ldvr
2322 : : character(len=*),intent(in) :: jobvl,jobvr
2323 : : !arrays
2324 : : complex(sp),intent(inout) :: a(lda,n)
2325 : : complex(sp),intent(out) :: w(n)
2326 : : complex(sp),intent(out) :: vl(ldvl,n)
2327 : : complex(sp),intent(out) :: vr(ldvr,n)
2328 : :
2329 : : !Local variables ------------------------------
2330 : : !scalars
2331 : : integer :: info,lwork
2332 : : character(len=500) :: msg
2333 : : !arrays
2334 : 0 : real(sp),allocatable :: rwork(:)
2335 : 0 : complex(sp),allocatable :: work(:)
2336 : : !************************************************************************
2337 : :
2338 : 0 : lwork = MAX(1,2*n)
2339 : :
2340 [ # # # # : 0 : ABI_MALLOC(work,(lwork))
# # # # #
# ]
2341 [ # # # # : 0 : ABI_MALLOC(rwork,(2*n))
# # # # #
# # # #
# ]
2342 : :
2343 : 0 : call CGEEV(jobvl,jobvr,n,a,lda,w,vl,ldvl,vr,ldvr,work,lwork,rwork,info)
2344 : :
2345 [ # # ]: 0 : if (info < 0) then
2346 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of CGEEV had an illegal value."
2347 : 0 : ABI_ERROR(msg)
2348 : : end if
2349 : :
2350 [ # # ]: 0 : if (info > 0) then
2351 : : write(msg,'(3a,i0,a,i0,a)')&
2352 : 0 : "CGEEV: The QR algorithm failed to compute all the eigenvalues, and no eigenvectors have been computed;",ch10,&
2353 : 0 : "Elements ",info+1,":",n," of W contain eigenvalues which have converged. "
2354 : 0 : ABI_ERROR(msg)
2355 : : end if
2356 : :
2357 [ # # ]: 0 : ABI_FREE(work)
2358 [ # # ]: 0 : ABI_FREE(rwork)
2359 : :
2360 : 0 : end subroutine wrap_CGEEV
2361 : : !!***
2362 : :
2363 : : !----------------------------------------------------------------------
2364 : :
2365 : : !!****f* m_hide_lapack/wrap_ZGEEV
2366 : : !! NAME
2367 : : !! wrap_ZGEEV
2368 : : !!
2369 : : !! FUNCTION
2370 : : !! wrap_ZGEEV computes for an N-by-N complex nonsymmetric matrix A, the
2371 : : !! eigenvalues and, optionally, the left and/or right eigenvectors using double precision arithmetic. [PRIVATE]
2372 : : !!
2373 : : !! The right eigenvector v(j) of A satisfies: A * v(j) = lambda(j) * v(j)
2374 : : !! where lambda(j) is its eigenvalue.
2375 : : !! The left eigenvector u(j) of A satisfies u(j)**H * A = lambda(j) * u(j)**H
2376 : : !! where u(j)**H denotes the conjugate transpose of u(j).
2377 : : !!
2378 : : !! The computed eigenvectors are normalized to have Euclidean norm
2379 : : !! equal to 1 and largest component real.
2380 : : !! No scalapack version is available (PZGEEV is not provided by the Scalapack team)
2381 : : !!
2382 : : !! INPUTS
2383 : : !! JOBVL (input) CHARACTER*1
2384 : : !! = 'N': left eigenvectors of A are not computed;
2385 : : !! = 'V': left eigenvectors of are computed.
2386 : : !!
2387 : : !! JOBVR (input) CHARACTER*1
2388 : : !! = 'N': right eigenvectors of A are not computed;
2389 : : !! = 'V': right eigenvectors of A are computed.
2390 : : !!
2391 : : !! N (input) INTEGER
2392 : : !! The order of the matrix A. N >= 0.
2393 : : !!
2394 : : !! LDA (input) INTEGER
2395 : : !! The leading dimension of the array A. LDA >= max(1,N).
2396 : : !!
2397 : : !! LDVL (input) INTEGER
2398 : : !! The leading dimension of the array VL. LDVL >= 1; if
2399 : : !! JOBVL = 'V', LDVL >= N.
2400 : : !!
2401 : : !! LDVR (input) INTEGER
2402 : : !! The leading dimension of the array VR. LDVR >= 1; if
2403 : : !! JOBVR = 'V', LDVR >= N.
2404 : : !!
2405 : : !! OUTPUT
2406 : : !! W (output) COMPLEX(DP) array, dimension (N)
2407 : : !! W contains the computed eigenvalues.
2408 : : !! VL (output) COMPLEX(DP) array, dimension (LDVL,N)
2409 : : !! If JOBVL = 'V', the left eigenvectors u(j) are stored one
2410 : : !! after another in the columns of VL, in the same order
2411 : : !! as their eigenvalues.
2412 : : !! If JOBVL = 'N', VL is not referenced.
2413 : : !! u(j) = VL(:,j), the j-th column of VL.
2414 : : !! VR (output) COMPLEX(DP) array, dimension (LDVR,N)
2415 : : !! If JOBVR = 'V', the right eigenvectors v(j) are stored one
2416 : : !! after another in the columns of VR, in the same order
2417 : : !! as their eigenvalues.
2418 : : !! If JOBVR = 'N', VR is not referenced.
2419 : : !! v(j) = VR(:,j), the j-th column of VR.
2420 : : !!
2421 : : !! See also SIDE EFFECTS
2422 : : !!
2423 : : !! SIDE EFFECTS
2424 : : !! A (input/output) COMPLEX(DP) array, dimension (LDA,N)
2425 : : !! On entry, the N-by-N matrix A.
2426 : : !! On exit, A has been overwritten.
2427 : : !!
2428 : : !! SOURCE
2429 : :
2430 : 10 : subroutine wrap_ZGEEV(jobvl,jobvr,n,a,lda,w,vl,ldvl,vr,ldvr)
2431 : :
2432 : : !Arguments ------------------------------------
2433 : : !scalars
2434 : : integer,intent(in) :: n,lda,ldvl,ldvr
2435 : : character(len=*),intent(in) :: jobvl,jobvr
2436 : : !arrays
2437 : : complex(dp),intent(inout) :: a(lda,n)
2438 : : complex(dp),intent(out) :: w(n)
2439 : : complex(dp),intent(out) :: vl(ldvl,n)
2440 : : complex(dp),intent(out) :: vr(ldvr,n)
2441 : :
2442 : : !Local variables ------------------------------
2443 : : !scalars
2444 : : integer :: info,lwork
2445 : : logical :: use_scalapack
2446 : : character(len=500) :: msg
2447 : : !arrays
2448 : 10 : real(dp),allocatable :: rwork(:)
2449 : 10 : complex(dp),allocatable :: work(:)
2450 : : !************************************************************************
2451 : :
2452 : 10 : use_scalapack=.FALSE.
2453 : :
2454 : : SELECT CASE(use_scalapack)
2455 : : CASE (.FALSE.)
2456 : :
2457 : 10 : lwork = MAX(1,2*n)
2458 [ - + + - : 30 : ABI_MALLOC(work,(lwork))
+ - - + -
+ ]
2459 [ + - - + : 40 : ABI_MALLOC(rwork,(2*n))
+ - + - +
- - + -
+ ]
2460 : :
2461 : 10 : call ZGEEV(jobvl,jobvr,n,a,lda,w,vl,ldvl,vr,ldvr,work,lwork,rwork,info)
2462 : :
2463 [ - + ]: 10 : if (info < 0) then
2464 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZGEEV had an illegal value."
2465 : 0 : ABI_ERROR(msg)
2466 : : end if
2467 : :
2468 [ - + ]: 10 : if (info > 0) then
2469 : : write(msg,'(3a,i0,a,i0,a)')&
2470 : 0 : "ZGEEV: The QR algorithm failed to compute all the eigenvalues, and no eigenvectors have been computed;",ch10,&
2471 : 0 : "Elements ",info+1,":",n," of W contain eigenvalues which have converged. "
2472 : 0 : ABI_ERROR(msg)
2473 : : end if
2474 : :
2475 [ - + ]: 10 : ABI_FREE(work)
2476 [ - + ]: 10 : ABI_FREE(rwork)
2477 : : RETURN
2478 : :
2479 : : CASE (.TRUE.)
2480 : : ABI_BUG("You should not be here!")
2481 : : END SELECT
2482 : :
2483 : : end subroutine wrap_ZGEEV
2484 : : !!***
2485 : :
2486 : : !----------------------------------------------------------------------
2487 : :
2488 : : !!****f* m_hide_lapack/cginv
2489 : : !! NAME
2490 : : !! cginv
2491 : : !!
2492 : : !! FUNCTION
2493 : : !! Invert a general matrix of complex elements in single precision.
2494 : : !! CGETRF computes an LU factorization of a general N-by-N matrix A using partial pivoting with row interchanges.
2495 : : !! CGETRI computes the inverse of a matrix using the LU factorization computed by CGETRF.
2496 : : !!
2497 : : !! INPUTS
2498 : : !! n=size of complex matrix a
2499 : : !! a=matrix of complex elements
2500 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
2501 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1,
2502 : : !! in this case the sequential LAPACK routine is called.
2503 : : !!
2504 : : !! SIDE EFFECTS
2505 : : !! a(n,n)= array of complex elements, input, inverted at output
2506 : : !!
2507 : : !! TODO
2508 : : !! Add Scalapack version
2509 : : !!
2510 : : !! SOURCE
2511 : :
2512 : 0 : subroutine cginv(a, n, comm)
2513 : :
2514 : : !Arguments ------------------------------------
2515 : : !scalars
2516 : : integer,intent(in) :: n
2517 : : integer,optional,intent(in) :: comm
2518 : : !arrays
2519 : : complex(sp),intent(inout) :: a(n,n)
2520 : :
2521 : : !Local variables-------------------------------
2522 : : !scalars
2523 : : integer :: lwork,info,nprocs
2524 : : logical :: use_scalapack
2525 : : character(len=500) :: msg
2526 : : !arrays
2527 : 0 : integer,allocatable :: ipiv(:)
2528 : 0 : complex(sp),allocatable :: work(:)
2529 : : #ifdef HAVE_LINALG_SCALAPACK
2530 : : !integer :: ierr,istwf_k,ipiv_size,liwork
2531 : : !integer,allocatable :: iwork(:)
2532 : : !type(slkmat_dp_t) :: Slk_mat
2533 : : !type(slk_processor_t) :: Slk_processor
2534 : : #endif
2535 : : ! *************************************************************************
2536 : :
2537 : 0 : use_scalapack=.FALSE.
2538 [ # # ]: 0 : if (PRESENT(comm)) then
2539 : 0 : nprocs = xmpi_comm_size(comm)
2540 : : ! TODO
2541 : : !#ifdef HAVE_LINALG_SCALAPACK
2542 : : ! use_scalapack = (nprocs>1)
2543 : : !#endif
2544 : : end if
2545 : :
2546 : : SELECT CASE(use_scalapack)
2547 : :
2548 : : CASE (.FALSE.)
2549 [ # # # # : 0 : ABI_MALLOC(ipiv, (n))
# # # # #
# # # ]
2550 : :
2551 : 0 : call CGETRF(n,n,a,n,ipiv,info) ! P* L* U Factorization.
2552 : :
2553 [ # # ]: 0 : if (info < 0) then
2554 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of CGETRF had an illegal value."
2555 : 0 : ABI_ERROR(msg)
2556 : : end if
2557 : :
2558 [ # # ]: 0 : if (info > 0) then
2559 : : write(msg,'(3a,i0,4a)')&
2560 : 0 : "The matrix that has been passed in argument is probably either singular or nearly singular.",ch10,&
2561 : 0 : "U(i,i) in the P*L*U factorization is exactly zero for i = ",info,ch10,&
2562 : 0 : "The factorization has been completed but the factor U is exactly singular.",ch10,&
2563 : 0 : "Division by zero will occur if it is used to solve a system of equations."
2564 : 0 : ABI_ERROR(msg)
2565 : : end if
2566 : :
2567 : 0 : lwork=MAX(1,n)
2568 [ # # # # : 0 : ABI_MALLOC(work,(lwork))
# # # # #
# ]
2569 : :
2570 : 0 : call CGETRI(n,a,n,ipiv,work,lwork,info) ! Inverts U and the computes inv(A)
2571 : :
2572 [ # # ]: 0 : if (info < 0) then
2573 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of CGETRI had an illegal value."
2574 : 0 : ABI_ERROR(msg)
2575 : : end if
2576 : :
2577 [ # # ]: 0 : if (info > 0) then
2578 : : write(msg,'(3a,i0,a)')&
2579 : 0 : "The matrix that has been passed to this subroutine is probably either singular or nearly singular.",ch10,&
2580 : 0 : "U(i,i) for i= ",info," is exactly zero; the matrix is singular and its inverse could not be computed."
2581 : 0 : ABI_ERROR(msg)
2582 : : end if
2583 : :
2584 [ # # ]: 0 : ABI_FREE(ipiv)
2585 [ # # ]: 0 : ABI_FREE(work)
2586 : : RETURN
2587 : :
2588 : : CASE (.TRUE.)
2589 : :
2590 : : #if 0
2591 : : ! FIXME slkmat_dp_t does not have a single precision complex buffer
2592 : :
2593 : : #ifdef HAVE_LINALG_SCALAPACK
2594 : : call Slk_processor%init(comm)
2595 : : istwf_k=1
2596 : :
2597 : : ! Initialize and fill Scalapack matrix from the global one.
2598 : : call Slk_mat%init(n,n,Slk_processor,istwf_k)
2599 : :
2600 : : ! IMPORTANT NOTE: PZGETRF requires square block decomposition i.e., MB_A = NB_A.
2601 : : if ( Slk_mat%descript%tab(MB_)/=Slk_mat%descript%tab(NB_) ) then
2602 : : msg ="PZGETRF requires square block decomposition i.e., MB_A = NB_A."
2603 : : ABI_ERROR(msg)
2604 : : end if
2605 : :
2606 : : !!call slk_matrix_from_global_dpc_2D(Slk_mat,"All",a)
2607 : :
2608 : : ipiv_size = my_locr(Slk_mat) + Slk_mat%descript%tab(MB_)
2609 : : ABI_MALLOC(ipiv,(ipiv_size))
2610 : :
2611 : : call PCGETRF(Slk_mat%sizeb_global(1),Slk_mat%sizeb_global(2),Slk_mat%buffer_cplx_sp,&
2612 : : & 1,1,Slk_mat%descript%tab,ipiv,info) ! P * L * U Factorization.
2613 : :
2614 : : if (info/=0) then
2615 : : write(msg,'(a,i0)')"PCGETRF returned info= ",info
2616 : : ABI_ERROR(msg)
2617 : : end if
2618 : :
2619 : : ! Get optimal size of workspace for PCGETRI.
2620 : : lwork=-1; liwork=-1
2621 : : ABI_MALLOC(work,(1))
2622 : : ABI_MALLOC(iwork,(1))
2623 : :
2624 : : call PCGETRI(Slk_mat%sizeb_global(1),Slk_mat%buffer_cplx_sp,1,1,Slk_mat%descript%tab,ipiv,&
2625 : : & work,lwork,iwork,liwork,info)
2626 : :
2627 : : ABI_CHECK(info==0,"PZGETRI: Error during computation of workspace size")
2628 : :
2629 : : lwork = NINT(DBLE(work(1))); liwork=iwork(1)
2630 : : ABI_FREE(work)
2631 : : ABI_FREE(iwork)
2632 : :
2633 : : ! Solve the problem.
2634 : : ABI_MALLOC(work,(lwork))
2635 : : ABI_MALLOC(iwork,(liwork))
2636 : :
2637 : : call PCGETRI(Slk_mat%sizeb_global(1),Slk_mat%buffer_cplx_sp,1,1,Slk_mat%descript%tab,ipiv,&
2638 : : & work,lwork,iwork,liwork,info)
2639 : :
2640 : : if (info/=0) then
2641 : : write(msg,'(a,i0)')"PZGETRI returned info= ",info
2642 : : ABI_ERROR(msg)
2643 : : end if
2644 : :
2645 : : ABI_FREE(work)
2646 : : ABI_FREE(iwork)
2647 : : ABI_FREE(ipiv)
2648 : :
2649 : : ! Reconstruct the global matrix from the distributed one.
2650 : : a = czero
2651 : : !! call slk_matrix_to_global_dpc_2D(Slk_mat,"All",a) ! Fill the entries calculated by this node.
2652 : : call Slk_mat%free()
2653 : :
2654 : : call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
2655 : : call Slk_processor%free()
2656 : :
2657 : : RETURN
2658 : : #endif
2659 : :
2660 : : #endif
2661 : :
2662 : : ABI_BUG("You should not be here!")
2663 : :
2664 : : END SELECT
2665 : :
2666 : : end subroutine cginv
2667 : : !!***
2668 : :
2669 : : !----------------------------------------------------------------------
2670 : :
2671 : : !!****f* m_hide_lapack/zginv
2672 : : !! NAME
2673 : : !! zginv
2674 : : !!
2675 : : !! FUNCTION
2676 : : !! Invert a general matrix of complex elements in double precision.
2677 : : !! ZGETRF computes an LU factorization of a general N-by-N matrix A using partial pivoting with row interchanges.
2678 : : !! ZGETRI computes the inverse of a matrix using the LU factorization computed by ZGETRF.
2679 : : !!
2680 : : !! INPUTS
2681 : : !! n=size of complex matrix a
2682 : : !! a=matrix of complex elements
2683 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
2684 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1.
2685 : : !! In this case the sequential LAPACK routine is called.
2686 : : !!
2687 : : !! SIDE EFFECTS
2688 : : !! a(n,n)= array of complex elements, input, inverted at output
2689 : : !!
2690 : : !! SOURCE
2691 : :
2692 : 8463501 : subroutine zginv(a, n, comm)
2693 : :
2694 : : !Arguments ------------------------------------
2695 : : !scalars
2696 : : integer,intent(in) :: n
2697 : : integer,optional,intent(in) :: comm
2698 : : !arrays
2699 : : complex(dp),intent(inout) :: a(n,n)
2700 : :
2701 : : !Local variables-------------------------------
2702 : : !scalars
2703 : : integer :: lwork,info,nprocs
2704 : : logical :: use_scalapack
2705 : : character(len=500) :: msg
2706 : : !arrays
2707 : 8463501 : integer,allocatable :: ipiv(:)
2708 : 8463501 : complex(dp),allocatable :: work(:)
2709 : : #ifdef HAVE_LINALG_SCALAPACK
2710 : : integer :: istwf_k,ierr
2711 : : type(slkmat_dp_t) :: Slk_mat
2712 : : type(slk_processor_t) :: Slk_processor
2713 : : #endif
2714 : : ! *************************************************************************
2715 : :
2716 : 8463501 : use_scalapack=.FALSE.
2717 [ + + ]: 8463501 : if (PRESENT(comm)) then
2718 : 5995 : nprocs = xmpi_comm_size(comm)
2719 : : #ifdef HAVE_LINALG_SCALAPACK
2720 : : use_scalapack = (nprocs>1)
2721 : : #endif
2722 : : end if
2723 : :
2724 : : SELECT CASE(use_scalapack)
2725 : : CASE (.FALSE.)
2726 [ - + + - : 25390503 : ABI_MALLOC(ipiv, (n))
+ - + - -
+ - + ]
2727 : 8463501 : call ZGETRF(n,n,a,n,ipiv,info) ! P* L* U Factorization.
2728 : :
2729 [ - + ]: 8463501 : if (info < 0) then
2730 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZGETRF had an illegal value."
2731 : 0 : ABI_ERROR(msg)
2732 : : end if
2733 : :
2734 [ - + ]: 8463501 : if (info > 0) then
2735 : : write(msg,'(3a,i0,4a)')&
2736 : 0 : "The matrix that has been passed in argument is probably either singular or nearly singular.",ch10,&
2737 : 0 : "U(i,i) in the P*L*U factorization is exactly zero for i = ",info,ch10,&
2738 : 0 : "The factorization has been completed but the factor U is exactly singular.",ch10,&
2739 : 0 : "Division by zero will occur if it is used to solve a system of equations."
2740 : 0 : ABI_ERROR(msg)
2741 : : end if
2742 : :
2743 : 8463501 : lwork=MAX(1,n)
2744 [ - + + - : 25390503 : ABI_MALLOC(work,(lwork))
+ - - + -
+ ]
2745 : :
2746 : 8463501 : call ZGETRI(n,a,n,ipiv,work,lwork,info) ! Invert U and then compute inv(A)
2747 : :
2748 [ - + ]: 8463501 : if (info < 0) then
2749 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZGETRI had an illegal value."
2750 : 0 : ABI_ERROR(msg)
2751 : : end if
2752 : :
2753 [ - + ]: 8463501 : if (info > 0) then
2754 : : write(msg,'(3a,i0,a)')&
2755 : 0 : "The matrix that has been passed to this subroutine is probably either singular or nearly singular.",ch10,&
2756 : 0 : "U(i,i) for i= ",info," is exactly zero; the matrix is singular and its inverse could not be computed."
2757 : 0 : ABI_ERROR(msg)
2758 : : end if
2759 : :
2760 [ - + ]: 8463501 : ABI_FREE(ipiv)
2761 [ - + ]: 8463501 : ABI_FREE(work)
2762 : : RETURN
2763 : :
2764 : : CASE (.TRUE.)
2765 : :
2766 : : #ifdef HAVE_LINALG_SCALAPACK
2767 : : call Slk_processor%init(comm)
2768 : : istwf_k=1
2769 : :
2770 : : ! Initialize and fill Scalapack matrix from the global one.
2771 : : call Slk_mat%init(n,n,Slk_processor,istwf_k)
2772 : : call slk_matrix_from_global_dpc_2D(Slk_mat,"All",a)
2773 : :
2774 : : ! Perform the calculation with scaLAPACK.
2775 : : call Slk_mat%invert()
2776 : :
2777 : : ! Reconstruct the global matrix from the distributed one.
2778 : : a = czero
2779 : : call slk_matrix_to_global_dpc_2D(Slk_mat,"All",a) ! Fill the entries calculated by this node.
2780 : : call Slk_mat%free()
2781 : :
2782 : : call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
2783 : : call Slk_processor%free()
2784 : :
2785 : : return
2786 : : #endif
2787 : :
2788 : : ABI_BUG("You should not be here!")
2789 : : END SELECT
2790 : :
2791 : : end subroutine zginv
2792 : : !!***
2793 : :
2794 : : !----------------------------------------------------------------------
2795 : :
2796 : : !!****f* m_hide_lapack/zhpd_invert
2797 : : !! NAME
2798 : : !! zhpd_invert
2799 : : !!
2800 : : !! FUNCTION
2801 : : !! Invert a Hermitian positive definite matrix of complex elements in double precision.
2802 : : !!
2803 : : !! INPUTS
2804 : : !! uplo= 'U': Upper triangle of A is stored;
2805 : : !! = 'L': Lower triangle of A is stored.
2806 : : !! n=size of complex matrix a
2807 : : !! a=matrix of complex elements
2808 : : !! [comm]=MPI communicator for ScaLAPACK inversion. Only available if the code has been compiled with Scalapack support.
2809 : : !! To avoid wasting CPU time the scalapack initialization is avoided if the number of processors in 1.
2810 : : !! In this case the sequential LAPACK routine is called.
2811 : : !!
2812 : : !! SIDE EFFECTS
2813 : : !! a(n,n)=
2814 : : !! On entry, the Hermitian matrix A. If UPLO = 'U', the leading
2815 : : !! N-by-N upper triangular part of A contains the upper
2816 : : !! triangular part of the matrix A, and the strictly lower
2817 : : !! triangular part of A is not referenced. If UPLO = 'L', the
2818 : : !! leading N-by-N lower triangular part of A contains the lower
2819 : : !! triangular part of the matrix A, and the strictly upper
2820 : : !! triangular part of A is not referenced.
2821 : : !! On exit, the upper or lower triangle of the (Hermitian) inverse of A
2822 : : !!
2823 : : !! SOURCE
2824 : :
2825 : 1 : subroutine zhpd_invert(uplo, a, n, comm)
2826 : :
2827 : : !Arguments ------------------------------------
2828 : : !scalars
2829 : : character(len=*),intent(in) :: uplo
2830 : : integer,intent(in) :: n
2831 : : integer,optional,intent(in) :: comm
2832 : : !arrays
2833 : : complex(dp),intent(inout) :: a(n,n)
2834 : :
2835 : : !Local variables-------------------------------
2836 : : !scalars
2837 : : integer :: info,nprocs
2838 : : logical :: use_scalapack
2839 : : character(len=500) :: msg
2840 : : !arrays
2841 : : #ifdef HAVE_LINALG_SCALAPACK
2842 : : integer :: istwf_k,ierr
2843 : : type(slkmat_dp_t) :: Slk_mat
2844 : : type(slk_processor_t) :: Slk_processor
2845 : : #endif
2846 : : ! *************************************************************************
2847 : :
2848 : 1 : use_scalapack=.FALSE.
2849 [ - + ]: 1 : if (PRESENT(comm)) then
2850 : 0 : nprocs = xmpi_comm_size(comm)
2851 : : #ifdef HAVE_LINALG_SCALAPACK
2852 : : use_scalapack = (nprocs>1)
2853 : : #endif
2854 : : end if
2855 : :
2856 : : SELECT CASE(use_scalapack)
2857 : : CASE (.FALSE.)
2858 : : ! * ZPOTRF computes the Cholesky factorization of a complex Hermitian positive definite.
2859 : : ! * A = U**H * U, if UPLO = 'U', or
2860 : : ! * A = L * L**H, if UPLO = 'L',
2861 : 1 : call ZPOTRF(uplo,n,a,n,info)
2862 : :
2863 [ - + ]: 1 : if (info < 0) then
2864 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZPOTRF had an illegal value."
2865 : 0 : ABI_ERROR(msg)
2866 : : end if
2867 : :
2868 [ - + ]: 1 : if (info > 0) then
2869 : : write(msg,'(a,i0,3a)')&
2870 : 0 : "The leading minor of order ",info," is not positive definite, ",ch10,&
2871 : 0 : "and the factorization could not be completed."
2872 : 0 : ABI_ERROR(msg)
2873 : : end if
2874 : : !
2875 : : ! * ZPOTRI computes the inverse of a complex Hermitian positive definite
2876 : : ! * matrix A using the Cholesky factorization A = U**H*U or A = L*L**H
2877 : : ! * computed by ZPOTRF.
2878 : : ! * On exit, the upper or lower triangle of the (Hermitian)
2879 : : ! * inverse of A, overwriting the input factor U or L.
2880 : 1 : call ZPOTRI(uplo,n,a,n,info)
2881 : :
2882 [ - + ]: 1 : if (info < 0) then
2883 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZPOTRI had an illegal value."
2884 : 0 : ABI_ERROR(msg)
2885 : : end if
2886 : :
2887 [ - + ]: 1 : if (info > 0) then
2888 : : write(msg,'(a,2(1x,i0),a)')&
2889 : 0 : "The ( ",info,info,")element of the factor U or L is zero, and the inverse could not be computed."
2890 : 0 : ABI_ERROR(msg)
2891 : : end if
2892 : :
2893 : 1 : RETURN
2894 : :
2895 : : CASE (.TRUE.)
2896 : :
2897 : : #ifdef HAVE_LINALG_SCALAPACK
2898 : : call Slk_processor%init(comm)
2899 : : istwf_k=1
2900 : :
2901 : : ! Initialize and fill Scalapack matrix from the global one.
2902 : : call Slk_mat%init(n,n,Slk_processor,istwf_k)
2903 : : call slk_matrix_from_global_dpc_2D(Slk_mat,uplo,a)
2904 : :
2905 : : ! Perform the calculation with scaLAPACK.
2906 : : call Slk_mat%hpd_invert(uplo, full=.False.)
2907 : :
2908 : : ! Reconstruct the global matrix from the distributed one.
2909 : : a = czero
2910 : : call slk_matrix_to_global_dpc_2D(Slk_mat,uplo,a) ! Fill the entries calculated by this node.
2911 : : call Slk_mat%free()
2912 : :
2913 : : call xmpi_sum(a,comm,ierr) ! Fill the remaining entries of the global matrix
2914 : : call Slk_processor%free()
2915 : :
2916 : : RETURN
2917 : : #endif
2918 : :
2919 : : ABI_BUG("You should not be here!")
2920 : : END SELECT
2921 : :
2922 : : end subroutine zhpd_invert
2923 : : !!***
2924 : :
2925 : : !----------------------------------------------------------------------
2926 : :
2927 : : !!****f* m_hide_lapack/matrginv
2928 : : !! NAME
2929 : : !! matrginv
2930 : : !!
2931 : : !! FUNCTION
2932 : : !! Invert a general matrix of real*8 elements.
2933 : : !!
2934 : : !! INPUTS
2935 : : !! lda=leading dimension of complex matrix a
2936 : : !! n=size of complex matrix a
2937 : : !! a=matrix of real elements
2938 : : !! OUTPUT
2939 : : !! a=inverse of a input matrix
2940 : : !!
2941 : : !! SIDE EFFECTS
2942 : : !! a(lda,n)= array of real elements, input, inverted at output
2943 : : !!
2944 : : !! SOURCE
2945 : :
2946 : 9242 : subroutine matrginv(a,lda,n)
2947 : :
2948 : : !Arguments ------------------------------------
2949 : : !scalars
2950 : : integer,intent(in) :: lda,n
2951 : : !arrays
2952 : : real(dp),intent(inout) :: a(lda,n)
2953 : :
2954 : : !Local variables-------------------------------
2955 : : !scalars
2956 : : integer :: ierr,nwork
2957 : : #if defined HAVE_LINALG_ESSL
2958 : : real(dp) :: rcond
2959 : : #endif
2960 : : character(len=500) :: message
2961 : : !arrays
2962 : 9242 : integer,allocatable :: ipvt(:)
2963 : : #if defined HAVE_LINALG_ESSL
2964 : : real(dp) :: det(2)
2965 : : #elif defined HAVE_LINALG_ASL
2966 : : real(dp) :: det(2)
2967 : : #endif
2968 : 9242 : real(dp),allocatable :: work(:)
2969 : : ! *************************************************************************
2970 : :
2971 : : #if defined HAVE_LINALG_ESSL
2972 : : nwork=200*n
2973 : : #else
2974 : 9242 : nwork=n
2975 : : #endif
2976 : :
2977 [ - + + - : 27726 : ABI_MALLOC(work,(nwork))
+ - + - -
+ - + ]
2978 [ - + + - : 27726 : ABI_MALLOC(ipvt,(n))
+ - + - -
+ - + ]
2979 : :
2980 : : #if defined HAVE_LINALG_ESSL
2981 : :
2982 : : call dgeicd(a,lda,n,0,rcond,det,work,nwork)
2983 : : if(abs(rcond)==zero) then
2984 : : write(message, '(7a)' )&
2985 : : ' The matrix that has been passed in argument of this subroutine',ch10,&
2986 : : ' is probably either singular or nearly singular.',ch10,&
2987 : : ' The ESSL routine dgeicd failed.',ch10,&
2988 : : ' Action: Contact ABINIT group '
2989 : : ABI_ERROR(message)
2990 : : end if
2991 : :
2992 : : #elif defined HAVE_LINALG_ASL
2993 : :
2994 : : call dbgmlu(a,lda,n,ipvt,ierr)
2995 : : if(ierr /= 0) then
2996 : : write(message, '(7a)' ) ch10,&
2997 : : ' The matrix that has been passed in argument of this subroutine',ch10,&
2998 : : ' is probably either singular or nearly singular.',ch10,&
2999 : : ' The ASL routine dbgmlu failed.',ch10,&
3000 : : ' Action: Contact ABINIT group '
3001 : : ABI_ERROR(message)
3002 : : end if
3003 : :
3004 : : call dbgmdi(a,lda,n,ipvt,det,-1,work,ierr)
3005 : :
3006 : : if(ierr /= 0) then
3007 : : write(message, '(7a)' ) &
3008 : : ' The matrix that has been passed in argument of this subroutine',ch10,&
3009 : : ' is probably either singular or nearly singular.',ch10,&
3010 : : ' The ASL routine dbgmdi failed.',ch10,&
3011 : : ' Action: Contact ABINIT group '
3012 : : ABI_ERROR(message)
3013 : : end if
3014 : :
3015 : : #else
3016 : :
3017 : 9242 : call dgetrf(n,n,a,lda,ipvt,ierr)
3018 [ - + ]: 9242 : if(ierr /= 0) then
3019 : : write(message, '(7a)' ) &
3020 : 0 : ' The matrix that has been passed in argument of this subroutine',ch10,&
3021 : 0 : ' is probably either singular or nearly singular.',ch10,&
3022 : 0 : ' The LAPACK routine dgetrf failed.',ch10,&
3023 : 0 : ' Action: Contact ABINIT group '
3024 : 0 : ABI_ERROR(message)
3025 : : end if
3026 : :
3027 : 9242 : call dgetri(n,a,lda,ipvt,work,n,ierr)
3028 : :
3029 [ - + ]: 9242 : if(ierr /= 0) then
3030 : : write(message, '(7a)' ) &
3031 : 0 : ' The matrix that has been passed in argument of this subroutine',ch10,&
3032 : 0 : ' is probably either singular or nearly singular.',ch10,&
3033 : 0 : ' The LAPACK routine dgetri failed.',ch10,&
3034 : 0 : ' Action: Contact ABINIT group '
3035 : 0 : ABI_ERROR(message)
3036 : : end if
3037 : :
3038 : : #endif
3039 : :
3040 [ - + ]: 9242 : ABI_FREE(work)
3041 [ - + ]: 9242 : ABI_FREE(ipvt)
3042 : :
3043 : 9242 : end subroutine matrginv
3044 : : !!***
3045 : :
3046 : : !!****f* m_hide_lapack/matr3eigval
3047 : : !! NAME
3048 : : !! matr3eigval
3049 : : !!
3050 : : !! FUNCTION
3051 : : !! Find the eigenvalues of a real symmetric 3x3 matrix, entered in full storage mode.
3052 : : !!
3053 : : !! INPUTS
3054 : : !! matr(3,3)=real symmetric 3x3 matrix
3055 : : !!
3056 : : !! OUTPUT
3057 : : !! eigval(3)=three eigenvalues
3058 : : !!
3059 : : !! SOURCE
3060 : :
3061 : 11540 : subroutine matr3eigval(eigval,matr)
3062 : :
3063 : : !Arguments ------------------------------------
3064 : : !arrays
3065 : : real(dp),intent(in) :: matr(3,3)
3066 : : real(dp),intent(out) :: eigval(3)
3067 : :
3068 : : !Local variables-------------------------------
3069 : : !scalars
3070 : : integer :: ier
3071 : : !arrays
3072 : : real(dp) :: eigvec(2,3,3),matrx(2,6),zhpev1(2,2*3-1),zhpev2(3*3-2)
3073 : : ! *************************************************************************
3074 : :
3075 : 11540 : matrx(1,1)=matr(1,1)
3076 : 11540 : matrx(1,2)=matr(1,2)
3077 : 11540 : matrx(1,3)=matr(2,2)
3078 : 11540 : matrx(1,4)=matr(1,3)
3079 : 11540 : matrx(1,5)=matr(2,3)
3080 : 11540 : matrx(1,6)=matr(3,3)
3081 [ + + ]: 80780 : matrx(2,:)=zero
3082 : :
3083 : 11540 : call ZHPEV ('V','U',3,matrx,eigval,eigvec,3,zhpev1,zhpev2,ier)
3084 : : !write(std_out,*)' eigval=',eigval
3085 : :
3086 : 11540 : end subroutine matr3eigval
3087 : : !!***
3088 : :
3089 : : !!****f* ABINIT/jacobi
3090 : : !! NAME
3091 : : !! jacobi
3092 : : !!
3093 : : !! FUNCTION
3094 : : !! Computes all eigenvalues and eigenvectors of a real symmetric matrix a,
3095 : : !! which is of size n by n, stored in a physical np by np array. On output,
3096 : : !! elements of a above the diagonal are destroyed. d returns the
3097 : : !! eigenvalues of a in its first n elements. v is a matrix with the same
3098 : : !! logical and physical dimensions as a, whose columns contain, on output,
3099 : : !! the normalized eigenvectors of a. nrot returns the number of Jacobi
3100 : : !! rotations that were required.
3101 : : !!
3102 : : !! INPUTS
3103 : : !!
3104 : : !! OUTPUT
3105 : : !!
3106 : : !! NOTES
3107 : : !! This routine is deprecated, use Lapack API
3108 : : !!
3109 : : !! SOURCE
3110 : :
3111 : 119591 : subroutine jacobi(a,n,np,d,v,nrot)
3112 : :
3113 : : !Arguments
3114 : : integer :: n,np,nrot
3115 : : real*8 :: a(np,np),d(np),v(np,np)
3116 : : !Local variables
3117 : : integer, parameter :: NMAX=500
3118 : : integer i,ip,iq,j
3119 : : real*8 c,g,h,s,sm,t,tau,theta,tresh,b(NMAX),z(NMAX)
3120 [ + + ]: 484092 : do ip=1,n
3121 [ + + ]: 1480916 : do iq=1,n
3122 : 1480916 : v(ip,iq)=0.
3123 : : enddo
3124 : 484092 : v(ip,ip)=1.
3125 : : enddo
3126 [ + + ]: 484092 : do ip=1,n
3127 : 364501 : b(ip)=a(ip,ip)
3128 : 364501 : d(ip)=b(ip)
3129 : 484092 : z(ip)=0.
3130 : : enddo
3131 : 119591 : nrot=0
3132 [ + - ]: 724069 : do i=1,50
3133 : : sm=0.
3134 [ + + ]: 2209846 : do ip=1,n-1
3135 [ + + ]: 4494970 : do iq=ip+1,n
3136 : 3770901 : sm=sm+abs(a(ip,iq))
3137 : : enddo
3138 : : enddo
3139 [ + + ]: 724069 : if(sm.eq.0.)return
3140 [ + + ]: 604478 : if(i.lt.4)then
3141 : 358692 : tresh=0.2*sm/n**2
3142 : : else
3143 : : tresh=0.
3144 : : endif
3145 [ + + ]: 1845345 : do ip=1,n-1
3146 [ + + ]: 3754512 : do iq=ip+1,n
3147 : 1909167 : g=100.*abs(a(ip,iq))
3148 : : if((i.gt.4).and.(abs(d(ip))+g.eq.abs(d(ip))) &
3149 [ + + + + : 3150034 : & .and.(abs(d(iq))+g.eq.abs(d(iq))))then
+ + ]
3150 : 365245 : a(ip,iq)=0.
3151 [ + + ]: 1543922 : else if(abs(a(ip,iq)).gt.tresh)then
3152 : 1114296 : h=d(iq)-d(ip)
3153 [ + + ]: 1114296 : if(abs(h)+g.eq.abs(h))then
3154 : 122227 : t=a(ip,iq)/h
3155 : : else
3156 : 992069 : theta=0.5*h/a(ip,iq)
3157 : 992069 : t=1./(abs(theta)+sqrt(1.+theta**2))
3158 [ + + ]: 992069 : if(theta.lt.0.)t=-t
3159 : : endif
3160 : 1114296 : c=1./sqrt(1+t**2)
3161 : 1114296 : s=t*c
3162 : 1114296 : tau=s/(1.+c)
3163 : 1114296 : h=t*a(ip,iq)
3164 : 1114296 : z(ip)=z(ip)-h
3165 : 1114296 : z(iq)=z(iq)+h
3166 : 1114296 : d(ip)=d(ip)-h
3167 : 1114296 : d(iq)=d(iq)+h
3168 : 1114296 : a(ip,iq)=0.
3169 [ + + ]: 1497377 : do j=1,ip-1
3170 : 383081 : g=a(j,ip)
3171 : 383081 : h=a(j,iq)
3172 : 383081 : a(j,ip)=g-s*(h+g*tau)
3173 : 1497377 : a(j,iq)=h+s*(g-h*tau)
3174 : : enddo
3175 [ + + ]: 1526917 : do j=ip+1,iq-1
3176 : 412621 : g=a(ip,j)
3177 : 412621 : h=a(j,iq)
3178 : 412621 : a(ip,j)=g-s*(h+g*tau)
3179 : 1526917 : a(j,iq)=h+s*(g-h*tau)
3180 : : enddo
3181 [ + + ]: 1537000 : do j=iq+1,n
3182 : 422704 : g=a(ip,j)
3183 : 422704 : h=a(iq,j)
3184 : 422704 : a(ip,j)=g-s*(h+g*tau)
3185 : 1537000 : a(iq,j)=h+s*(g-h*tau)
3186 : : enddo
3187 [ + + ]: 4561294 : do j=1,n
3188 : 3446998 : g=v(j,ip)
3189 : 3446998 : h=v(j,iq)
3190 : 3446998 : v(j,ip)=g-s*(h+g*tau)
3191 : 4561294 : v(j,iq)=h+s*(g-h*tau)
3192 : : enddo
3193 : 1114296 : nrot=nrot+1
3194 : : endif
3195 : : enddo
3196 : : enddo
3197 [ + + ]: 2449823 : do ip=1,n
3198 : 1845345 : b(ip)=b(ip)+z(ip)
3199 : 1845345 : d(ip)=b(ip)
3200 : 2449823 : z(ip)=0.
3201 : : enddo
3202 : : enddo
3203 : 0 : write(std_out,*) 'too many iterations in jacobi'
3204 : :
3205 : : end subroutine jacobi
3206 : : !!***
3207 : :
3208 : : !!****f* m_hide_lapack/ludcmp
3209 : : !! NAME
3210 : : !! ludcmp
3211 : : !!
3212 : : !! FUNCTION
3213 : : !! Given a matrix a(1:n,1:n), with physical dimension np by np, this
3214 : : !! routine replaces it by the LU decomposition of a rowwise permutation of
3215 : : !! itself. a and n are input. a is output, arranged as in equation (2.3.14)
3216 : : !! above; indx(1:n) is an output vector that records the row permutation
3217 : : !! effected by the partial pivoting; id is output as +- 1 depending on
3218 : : !! whether the number of row interchanges was even or odd,
3219 : : !! respectively. This routine is used in combination with lubksb to solve
3220 : : !! linear equations or invert a matrix.
3221 : : !!
3222 : : !! NOTES
3223 : : !! This routine is deprecated, use lapack API
3224 : : !!
3225 : : !! SOURCE
3226 : :
3227 : 2071 : SUBROUTINE ludcmp(a,n,np,indx,id,info)
3228 : :
3229 : : INTEGER n,np,indx(n),NMAX,id,info
3230 : : REAL*8 a(np,np),TINY
3231 : : PARAMETER (NMAX=500,TINY=1.0e-20)
3232 : :
3233 : : INTEGER i,imax,j,k
3234 : : REAL*8 aamax,dum,sum,vv(NMAX)
3235 : :
3236 : : ! write(std_out,*) 'ENTERING LUDCMP...'
3237 : : ! write(std_out,*) 'in ludcmp n=',n,' np=',np
3238 : : ! write(std_out,201) ((a(i,j),j=1,n),i=1,n)
3239 : : ! 201 FORMAT('A in ludcmp ',/,3F16.8,/,3F16.8,/,3F16.8)
3240 : 2071 : id=1
3241 : 2071 : info=0
3242 [ + + ]: 8284 : do i=1,n
3243 : : aamax=0.
3244 [ + + ]: 24852 : do j=1,n
3245 : 24852 : if (abs(a(i,j)).gt.aamax) aamax=abs(a(i,j))
3246 : : enddo
3247 [ - + ]: 6213 : if (aamax.eq.0.) then
3248 : 0 : write(std_out,*) 'LUDCMP: singular matrix !!!'
3249 [ # # ]: 0 : do j=1,3
3250 : 0 : write(std_out,*) (a(j,k),k=1,3)
3251 : : enddo
3252 : 0 : info=1
3253 : 0 : return
3254 : : ! stop 'singular matrix in ludcmp'
3255 : : endif
3256 : 8284 : vv(i)=1./aamax
3257 : : enddo
3258 [ + + ]: 8284 : do j=1,n
3259 [ + + ]: 12426 : do i=1,j-1
3260 : 6213 : sum=a(i,j)
3261 [ + + ]: 8284 : do k=1,i-1
3262 : 8284 : sum=sum-a(i,k)*a(k,j)
3263 : : enddo
3264 : 12426 : a(i,j)=sum
3265 : : enddo
3266 : : aamax=0.
3267 [ + + ]: 18639 : do i=j,n
3268 : 12426 : sum=a(i,j)
3269 [ + + ]: 20710 : do k=1,j-1
3270 : 20710 : sum=sum-a(i,k)*a(k,j)
3271 : : enddo
3272 : 12426 : a(i,j)=sum
3273 : 12426 : dum=vv(i)*abs(sum)
3274 [ + + ]: 18639 : if (dum.ge.aamax) then
3275 : 6940 : imax=i
3276 : 6940 : aamax=dum
3277 : : endif
3278 : : enddo
3279 [ + + ]: 6213 : if (j.ne.imax)then
3280 [ + + ]: 2768 : do k=1,n
3281 : 2076 : dum=a(imax,k)
3282 : 2076 : a(imax,k)=a(j,k)
3283 : 2768 : a(j,k)=dum
3284 : : enddo
3285 : 692 : id=-id
3286 : 692 : vv(imax)=vv(j)
3287 : : endif
3288 : 6213 : indx(j)=imax
3289 [ - + ]: 6213 : if(a(j,j).eq.0.)a(j,j)=TINY
3290 [ + + ]: 8284 : if(j.ne.n)then
3291 : 4142 : dum=1./a(j,j)
3292 [ + + ]: 10355 : do i=j+1,n
3293 : 10355 : a(i,j)=a(i,j)*dum
3294 : : enddo
3295 : : endif
3296 : : enddo
3297 : : ! write(std_out,*) 'LEAVING LUDCMP...'
3298 : : return
3299 : : END SUBROUTINE ludcmp
3300 : : !!***
3301 : :
3302 : : !!****f* m_hide_lapack/lubksb
3303 : : !! NAME
3304 : : !! lubksb
3305 : : !!
3306 : : !! FUNCTION
3307 : : !! Solves the set of n linear equations A . X = B. Here a is input, not as
3308 : : !! the matrix A but rather as its LU decomposition, determined by the
3309 : : !! routine ludcmp. indx is input as the permutation vector returned by
3310 : : !! ludcmp. b(1:n) is input as the right-hand side vector B, and returns
3311 : : !! with the solution vector X. a, n, np, and indx are not modified by this
3312 : : !! routine and can be left in place for successive calls with different
3313 : : !! right-hand sides b. This routine takes into account the possibility that
3314 : : !! b will begin with many zero elements, so it is efficient for use in
3315 : : !! matrix inversion.
3316 : : !!
3317 : : !! NOTES
3318 : : !! This routine is deprecated, use lapack API
3319 : : !!
3320 : : !! SOURCE
3321 : :
3322 : 6213 : SUBROUTINE lubksb(a,n,np,indx,b)
3323 : :
3324 : : INTEGER n,np,indx(n)
3325 : : REAL*8 a(np,np),b(n)
3326 : :
3327 : : INTEGER i,ii,j,ll
3328 : : REAL*8 sum
3329 : : ! write(std_out,*) 'ENTERING LUBKSB...'
3330 : : ! write(std_out,201) ((a(i,j),j=1,n),i=1,n)
3331 : : ! 201 FORMAT('A in lubksb ',/,3F16.8,/,3F16.8,/,3F16.8)
3332 : :
3333 : 6213 : ii=0
3334 [ + + ]: 24852 : do i=1,n
3335 : 18639 : ll=indx(i)
3336 : 18639 : sum=b(ll)
3337 : 18639 : b(ll)=b(i)
3338 [ + + ]: 18639 : if (ii.ne.0)then
3339 [ + + ]: 14497 : do j=ii,i-1
3340 : 14497 : sum=sum-a(i,j)*b(j)
3341 : : enddo
3342 [ + + ]: 12426 : else if (sum.ne.0.) then
3343 : 6213 : ii=i
3344 : : endif
3345 : 24852 : b(i)=sum
3346 : : enddo
3347 [ + + ]: 24852 : do i=n,1,-1
3348 : 18639 : sum=b(i)
3349 [ + + ]: 37278 : do j=i+1,n
3350 : 37278 : sum=sum-a(i,j)*b(j)
3351 : : enddo
3352 : 24852 : b(i)=sum/a(i,i)
3353 : : enddo
3354 : : ! write(std_out,*) 'LEAVING LUBKSB...'
3355 : 6213 : return
3356 : :
3357 : : END SUBROUTINE LUBKSB
3358 : : !!***
3359 : :
3360 : : !!****f* m_hide_lapack/dzegdi
3361 : : !! NAME
3362 : : !! dzgedi
3363 : : !!
3364 : : !! FUNCTION
3365 : : !! This routine is the clone of zgefa.F90 using real*8 a(2) instead of complex*16
3366 : : !! for the purpose of ABINIT
3367 : : !!
3368 : : !! NOTES
3369 : : !! This routine is deprecated, use lapack API
3370 : : !!
3371 : : !! SOURCE
3372 : :
3373 : 2394114 : subroutine dzgedi(a,lda,n,ipvt,det,work,job)
3374 : :
3375 : : integer :: lda,n,ipvt(n),job
3376 : : real*8 :: a(2,lda,n),det(2,2),work(2,n)
3377 : : !
3378 : : ! zgedi computes the determinant and inverse of a matrix
3379 : : ! using the factors computed by zgeco or zgefa.
3380 : : !
3381 : : ! on entry
3382 : : !
3383 : : ! a complex*16(lda, n)
3384 : : ! the output from zgeco or zgefa.
3385 : : !
3386 : : ! lda integer
3387 : : ! the leading dimension of the array a .
3388 : : !
3389 : : ! n integer
3390 : : ! the order of the matrix a .
3391 : : !
3392 : : ! ipvt integer(n)
3393 : : ! the pivot vector from zgeco or zgefa.
3394 : : !
3395 : : ! work complex*16(n)
3396 : : ! work vector. contents destroyed.
3397 : : !
3398 : : ! job integer
3399 : : ! = 11 both determinant and inverse.
3400 : : ! = 01 inverse only.
3401 : : ! = 10 determinant only.
3402 : : !
3403 : : ! on return
3404 : : !
3405 : : ! a inverse of original matrix if requested.
3406 : : ! otherwise unchanged.
3407 : : !
3408 : : ! det complex*16(2)
3409 : : ! determinant of original matrix if requested.
3410 : : ! otherwise not referenced.
3411 : : ! determinant = det(1) * 10.0**det(2)
3412 : : ! with 1.0 .le. cabs1(det(1)) .lt. 10.0
3413 : : ! or det(1) .eq. 0.0 .
3414 : : !
3415 : : ! error condition
3416 : : !
3417 : : ! a division by zero will occur if the input factor contains
3418 : : ! a zero on the diagonal and the inverse is requested.
3419 : : ! it will not occur if the subroutines are called correctly
3420 : : ! and if zgeco has set rcond .gt. 0.0 or zgefa has set
3421 : : ! info .eq. 0 .
3422 : : !
3423 : : ! linpack. this version dated 08/14/78 .
3424 : : ! cleve moler, university of new mexico, argonne national lab.
3425 : : !
3426 : : ! subroutines and functions
3427 : : !
3428 : : ! internal variables
3429 : : !
3430 : : double precision :: r(2),rk(2),rkj(2)
3431 : : double precision :: ten,rinv2,rabs
3432 : : integer :: i,j,k,kb,kp1,l,nm1
3433 : : !
3434 : : ! compute determinant
3435 : : !
3436 [ + + ]: 2394114 : if (job/10 .eq. 0) go to 70
3437 : 2363834 : det(1,1) = 1.0d0; det(2,1) = 0.0d0
3438 : 2363834 : det(1,2) = 0.0d0; det(2,2) = 0.0d0
3439 : 2363834 : ten = 10.0d0
3440 [ + + ]: 31739050 : do i = 1, n
3441 [ + + ]: 29375216 : if (ipvt(i) .ne. i) then
3442 : 12598326 : det(1,1) = -det(1,1)
3443 : 12598326 : det(2,1) = -det(2,1)
3444 : : end if
3445 : 29375216 : r(1)=det(1,1); r(2)=det(2,1)
3446 : 29375216 : det(1,1) = r(1)*a(1,i,i)-r(2)*a(2,i,i)
3447 : 29375216 : det(2,1) = r(2)*a(1,i,i)+r(1)*a(2,i,i)
3448 : : ! ...exit
3449 : 29375216 : rabs = abs(det(1,1))+abs(det(2,1))
3450 [ - + ]: 29375216 : if (rabs .eq. 0.0d0) go to 60
3451 : : 10 continue
3452 : 33686378 : rabs = abs(det(1,1))+abs(det(2,1))
3453 [ + + ]: 33686378 : if (rabs .ge. 1.0d0) go to 20
3454 : 4311162 : det(1,1) = ten*det(1,1); det(2,1) = ten*det(2,1)
3455 : 4311162 : det(1,2) = det(1,2) - 1.0d0
3456 : 33686378 : go to 10
3457 : : 20 continue
3458 : : 30 continue
3459 : 30755395 : rabs = abs(det(1,1))+abs(det(2,1))
3460 [ + + ]: 30755395 : if (rabs .lt. ten) go to 40
3461 : 1380179 : det(1,1) = det(1,1)/ten; det(2,1) = det(2,1)/ten
3462 : 1380179 : det(1,2) = det(1,2) + 1.0d0
3463 : 30755395 : go to 30
3464 : 2394114 : 40 continue
3465 : : end do
3466 : : 60 continue
3467 : : 70 continue
3468 : : !
3469 : : ! compute inverse(u)
3470 : : !
3471 [ + + ]: 2394114 : if (mod(job,10) .eq. 0) go to 150
3472 [ + + ]: 16029689 : do 100 k = 1, n
3473 : : !a(k,k) = (1.0d0,0.0d0)/a(k,k)
3474 : : !t = -a(k,k)
3475 : : !call zscal(k-1,t,a(1,k),1)
3476 : 14800065 : rinv2 = 1.d0/(a(1,k,k)**2+a(2,k,k)**2)
3477 : 14800065 : a(1,k,k) = rinv2*a(1,k,k)
3478 : 14800065 : a(2,k,k) = -rinv2*a(2,k,k)
3479 : 14800065 : rk(1) = -a(1,k,k); rk(2) = -a(2,k,k)
3480 [ + + ]: 201539483 : do i=1,k-1
3481 : 186739418 : r(1)=a(1,i,k)
3482 : 186739418 : r(2)=a(2,i,k)
3483 : 186739418 : a(1,i,k)=rk(1)*r(1)-rk(2)*r(2)
3484 : 201539483 : a(2,i,k)=rk(1)*r(2)+rk(2)*r(1)
3485 : : end do
3486 : 14800065 : kp1 = k + 1
3487 [ + + ]: 14800065 : if (n .lt. kp1) go to 90
3488 [ + + ]: 200309859 : do 80 j = kp1, n
3489 : : !t = a(k,j)
3490 : : !a(k,j) = (0.0d0,0.0d0)
3491 : : !call zaxpy(k,t,a(1,k),1,a(1,j),1)
3492 : 186739418 : rkj(1) = a(1,k,j); rkj(2) = a(2,k,j)
3493 : 186739418 : a(1,k,j) = 0.d0; a(2,k,j) = 0.d0
3494 [ + + ]: 2298677559 : do i=1,k
3495 : 2111938141 : a(1,i,j)=rkj(1)*a(1,i,k)-rkj(2)*a(2,i,k)+a(1,i,j)
3496 : 2298677559 : a(2,i,j)=rkj(2)*a(1,i,k)+rkj(1)*a(2,i,k)+a(2,i,j)
3497 : : end do
3498 : 14800065 : 80 continue
3499 : : 90 continue
3500 : 1229624 : 100 continue
3501 : : do i=1,n
3502 : : end do
3503 : : !
3504 : : ! form inverse(u)*inverse(l)
3505 : : !
3506 : 1229624 : nm1 = n - 1
3507 [ + + ]: 1229624 : if (nm1 .lt. 1) go to 140
3508 [ + + ]: 14799945 : do 130 kb = 1, nm1
3509 : 13570441 : k = n - kb
3510 : 13570441 : kp1 = k + 1
3511 [ + + ]: 200309859 : do 110 i = kp1, n
3512 : 186739418 : work(1,i) = a(1,i,k); work(2,i) = a(2,i,k)
3513 : 186739418 : a(1,i,k) = 0.0d0; a(2,i,k) = 0.d0
3514 : 13570441 : 110 continue
3515 [ + + ]: 200309859 : do 120 j = kp1, n
3516 : 186739418 : r(1) = work(1,j); r(2) = work(2,j)
3517 : : !call zaxpy(n,t,a(1,j),1,a(1,k),1)
3518 [ + + ]: 6335814423 : do i=1,n
3519 : 6149075005 : a(1,i,k)=r(1)*a(1,i,j)-r(2)*a(2,i,j)+a(1,i,k)
3520 : 6335814423 : a(2,i,k)=r(2)*a(1,i,j)+r(1)*a(2,i,j)+a(2,i,k)
3521 : : end do
3522 : 13570441 : 120 continue
3523 : 13570441 : l = ipvt(k)
3524 [ + + ]: 13570441 : if (l .ne. k) then
3525 : : !call zswap(n,a(1,k),1,a(1,l),1)
3526 [ + + ]: 184583184 : do i=1,n
3527 : 178896595 : r(1) = a(1,i,k); r(2) = a(2,i,k)
3528 : 178896595 : a(1,i,k) = a(1,i,l); a(2,i,k) = a(2,i,l)
3529 : 184583184 : a(1,i,l) = r(1); a(2,i,l) = r(2)
3530 : : end do
3531 : : end if
3532 : 2394114 : 130 continue
3533 : : 140 continue
3534 : : 150 continue
3535 : :
3536 : 2394114 : end subroutine dzgedi
3537 : : !!***
3538 : :
3539 : : !!****f* m_hide_lapack/dzgefa
3540 : : !! NAME
3541 : : !! dzgefa
3542 : : !!
3543 : : !! FUNCTION
3544 : : !! This routine is the clone of zgefa.F90 using real*8 a(2) instead of complex*16
3545 : : !! for the purpose of ABINIT (2008,TD)
3546 : : !!
3547 : : !! NOTES
3548 : : !! This routine is deprecated, use lapack API
3549 : : !!
3550 : : !! SOURCE
3551 : :
3552 : 2394114 : subroutine dzgefa(a,lda,n,ipvt,info)
3553 : :
3554 : : use m_linalg_interfaces
3555 : :
3556 : : !Arguments
3557 : : integer :: lda,n,ipvt(n),info
3558 : : real*8 :: a(2,lda,n)
3559 : : !
3560 : : ! zgefa factors a complex*16 matrix by gaussian elimination.
3561 : : !
3562 : : ! dzgefa is usually called by zgeco, but it can be called
3563 : : ! directly with a saving in time if rcond is not needed.
3564 : : ! (time for zgeco) = (1 + 9/n)*(time for zgefa) .
3565 : : !
3566 : : ! on entry
3567 : : !
3568 : : ! a complex*16(lda, n)
3569 : : ! the matrix to be factored.
3570 : : !
3571 : : ! lda integer
3572 : : ! the leading dimension of the array a .
3573 : : !
3574 : : ! n integer
3575 : : ! the order of the matrix a .
3576 : : !
3577 : : ! on return
3578 : : !
3579 : : ! a an upper triangular matrix and the multipliers
3580 : : ! which were used to obtain it.
3581 : : ! the factorization can be written a = l*u where
3582 : : ! l is a product of permutation and unit lower
3583 : : ! triangular matrices and u is upper triangular.
3584 : : !
3585 : : ! ipvt integer(n)
3586 : : ! an integer vector of pivot indices.
3587 : : !
3588 : : ! info integer
3589 : : ! = 0 normal value.
3590 : : ! = k if u(k,k) .eq. 0.0 . this is not an error
3591 : : ! condition for this subroutine, but it does
3592 : : ! indicate that zgesl or zgedi will divide by zero
3593 : : ! if called. use rcond in zgeco for a reliable
3594 : : ! indication of singularity.
3595 : : !
3596 : : ! linpack. this version dated 08/14/78 .
3597 : : ! cleve moler, university of new mexico, argonne national lab.
3598 : : !
3599 : : ! subroutines and functions
3600 : : !
3601 : : ! internal variables
3602 : : !
3603 : : !Local variables
3604 : : real*8 :: r(2),rk(2),rlj(2)
3605 : : real*8 :: rinv2,rmax,rabs
3606 : : integer :: i,j,k,kp1,l,nm1
3607 : :
3608 : : !
3609 : : ! gaussian elimination with partial pivoting
3610 : : !
3611 : 2394114 : info = 0
3612 : 2394114 : nm1 = n - 1
3613 [ + + ]: 2394114 : if (nm1 .lt. 1) go to 70
3614 [ + + ]: 29495797 : do 60 k = 1, nm1
3615 : 27101803 : kp1 = k + 1
3616 : : !
3617 : : ! find l = pivot index
3618 : : !
3619 : : !l = izamax(n-k+1,a(k,k),1) + k - 1
3620 : 27101803 : rmax=0.d0
3621 : 27101803 : l=0
3622 [ + + ]: 429945310 : do i=k,n
3623 : 402843507 : rabs=abs(a(1,i,k))+abs(a(2,i,k))
3624 [ + + ]: 429945310 : if(rmax<=rabs) then
3625 : 44409324 : rmax=rabs
3626 : 44409324 : l=i
3627 : : end if
3628 : : end do
3629 : 27101803 : ipvt(k) = l
3630 : : !
3631 : : ! zero pivot implies this column already triangularized
3632 : : !
3633 [ + - ]: 27101803 : if (abs(a(1,l,k))+abs(a(2,l,k)) .eq. 0.0d0) go to 40
3634 : : !
3635 : : ! interchange if necessary
3636 : : !
3637 [ + + ]: 27101803 : if (l .eq. k) go to 10
3638 : 12609440 : r(1) = a(1,l,k); r(2) = a(2,l,k)
3639 : 12609440 : a(1,l,k) = a(1,k,k); a(2,l,k) = a(2,k,k)
3640 : 27101803 : a(1,k,k) = r(1); a(2,k,k) = r(2)
3641 : : 10 continue
3642 : : !
3643 : : ! compute multipliers
3644 : : !
3645 : 27101803 : rinv2 = 1.d0/(a(1,k,k)**2+a(2,k,k)**2)
3646 : 27101803 : rk(1) = -rinv2*a(1,k,k)
3647 : 27101803 : rk(2) = rinv2*a(2,k,k)
3648 : : !call zscal(n-k,t,a(k+1,k),1)
3649 [ + + ]: 402843507 : do i=k+1,n
3650 : 375741704 : r(1)=a(1,i,k)
3651 : 375741704 : r(2)=a(2,i,k)
3652 : 375741704 : a(1,i,k)=rk(1)*r(1)-rk(2)*r(2)
3653 : 402843507 : a(2,i,k)=rk(1)*r(2)+rk(2)*r(1)
3654 : : end do
3655 : : !
3656 : : ! row elimination with column indexing
3657 : : !
3658 [ + + ]: 402843507 : do j = kp1, n
3659 : 375741704 : rlj(1) = a(1,l,j); rlj(2) = a(2,l,j)
3660 [ + + ]: 375741704 : if (l .eq. k) go to 20
3661 : 171271954 : a(1,l,j) = a(1,k,j); a(2,l,j) = a(2,k,j)
3662 : 375741704 : a(1,k,j) = rlj(1); a(2,k,j) = rlj(2)
3663 : : 20 continue
3664 : : !call zaxpy(n-k,t,a(1,k+1,k),1,a(1,k+1,j),1)
3665 [ + + ]: 8534416049 : do i=k+1,n
3666 : 8131572542 : a(1,i,j)=rlj(1)*a(1,i,k)-rlj(2)*a(2,i,k)+a(1,i,j)
3667 : 8507314246 : a(2,i,j)=rlj(2)*a(1,i,k)+rlj(1)*a(2,i,k)+a(2,i,j)
3668 : : end do
3669 : : end do
3670 : 0 : go to 50
3671 : : 40 continue
3672 : 0 : info = k
3673 : : 50 continue
3674 : 2394114 : 60 continue
3675 : : 70 continue
3676 : 2394114 : ipvt(n) = n
3677 [ - + ]: 2394114 : if (abs(a(1,n,n))+abs(a(2,n,n)) .eq. 0.0d0) info = n
3678 : :
3679 : 2394114 : end subroutine dzgefa
3680 : : !!***
3681 : :
3682 : : !!****f* m_hide_lapack/test_xginv
3683 : : !! NAME
3684 : : !! test_xginv
3685 : : !!
3686 : : !! FUNCTION
3687 : :
3688 : 0 : subroutine test_xginv(msize,skinds,do_check,Tres,comm)
3689 : :
3690 : : !Arguments -----------------------------------
3691 : : !scalars
3692 : : integer,intent(in) :: msize,comm
3693 : : logical,intent(in) :: do_check
3694 : : character(len=*),intent(in) :: skinds
3695 : : type(latime_t),intent(out) :: Tres
3696 : : !arrays
3697 : : !complex(sp),allocatable :: cmat_spc(:,:)
3698 : : !complex(sp),allocatable :: cmat_spc_check(:,:)
3699 : 0 : complex(dp),allocatable :: cmat_dpc(:,:)
3700 : 0 : complex(dp),allocatable :: cmat_dpc_check(:,:)
3701 : :
3702 : : !Local variables-------------------------------
3703 : : integer :: ii
3704 : : real(dp) :: max_abserr
3705 : : ! *************************************************************************
3706 : :
3707 : : if (.FALSE.) write(std_out,*)skinds
3708 : :
3709 [ # # ]: 0 : if (do_check) then
3710 [ # # # # : 0 : ABI_MALLOC(cmat_dpc_check,(msize,msize))
# # # # #
# # # # #
# # ]
3711 [ # # # # ]: 0 : cmat_dpc_check = czero
3712 [ # # ]: 0 : do ii=1,msize
3713 : 0 : cmat_dpc_check(ii,ii) = cone
3714 : : end do
3715 : : !call xginv(cmat_dpc_check,msize,comm=xmpi_comm_self)
3716 : : end if
3717 : :
3718 [ # # # # : 0 : ABI_MALLOC(cmat_dpc,(msize,msize))
# # # # #
# # # # #
# # ]
3719 [ # # ]: 0 : do ii=1,msize
3720 : 0 : cmat_dpc(ii,ii) = cone
3721 : : end do
3722 : :
3723 : 0 : call cwtime(Tres%ctime,Tres%wtime,Tres%gflops,"start")
3724 : :
3725 : 0 : call xginv(cmat_dpc,msize,comm)
3726 : :
3727 : 0 : call cwtime(Tres%ctime,Tres%wtime,Tres%gflops,"stop")
3728 : 0 : Tres%testname = 'test_xginv'
3729 : 0 : Tres%msize = msize
3730 : :
3731 : 0 : max_abserr = -one
3732 [ # # ]: 0 : if (do_check) then
3733 [ # # # # : 0 : max_abserr = MAXVAL( ABS(cmat_dpc - cmat_dpc_check) )
# # # # #
# # # ]
3734 : : end if
3735 : 0 : Tres%max_abserr = max_abserr
3736 : :
3737 [ # # ]: 0 : ABI_FREE(cmat_dpc)
3738 [ # # ]: 0 : ABI_SFREE(cmat_dpc_check)
3739 : :
3740 : 0 : end subroutine test_xginv
3741 : : !!***
3742 : :
3743 : : !!****f* m_cgtools/xhesv_cplex
3744 : : !! NAME
3745 : : !! xhesv_cplex
3746 : : !!
3747 : : !! FUNCTION
3748 : : !! ZHESV computes the solution to a complex (real) system of linear equations
3749 : : !! A * X = B,
3750 : : !!
3751 : : !! where A is an N-by-N Hermitian matrix and X and B are N-by-NRHS matrices.
3752 : : !! The value of cplex (1 or 2) defines whether we have a complex Hermitian or real symmetric matrix
3753 : : !!
3754 : : !! The diagonal pivoting method is used to factor A as
3755 : : !! A = U * D * U**H, if UPLO = 'U', or
3756 : : !! A = L * D * L**H, if UPLO = 'L',
3757 : : !!
3758 : : !! where U (or L) is a product of permutation and unit upper (lower)
3759 : : !! triangular matrices, and D is Hermitian and block diagonal with
3760 : : !! 1-by-1 and 2-by-2 diagonal blocks. The factored form of A is then
3761 : : !! used to solve the system of equations A * X = B.
3762 : : !!
3763 : : !! INPUTS
3764 : : !!
3765 : : !![in] UPLO
3766 : : !! UPLO is CHARACTER*1
3767 : : !! = 'U': Upper triangle of A is stored;
3768 : : !! = 'L': Lower triangle of A is stored.
3769 : : !![in] N
3770 : : !! N is INTEGER
3771 : : !! The number of linear equations, i.e., the order of the
3772 : : !! matrix A. N >= 0.
3773 : : !![in] NRHS
3774 : : !! NRHS is INTEGER
3775 : : !! The number of right hand sides, i.e., the number of columns
3776 : : !! of the matrix B. NRHS >= 0.
3777 : : !![in,out] A
3778 : : !! A is COMPLEX*16 array, dimension (LDA,N)
3779 : : !! On entry, the Hermitian matrix A. If UPLO = 'U', the leading
3780 : : !! N-by-N upper triangular part of A contains the upper
3781 : : !! triangular part of the matrix A, and the strictly lower
3782 : : !! triangular part of A is not referenced. If UPLO = 'L', the
3783 : : !! leading N-by-N lower triangular part of A contains the lower
3784 : : !! triangular part of the matrix A, and the strictly upper
3785 : : !! triangular part of A is not referenced.
3786 : : !!
3787 : : !! On exit, if INFO = 0, the block diagonal matrix D and the
3788 : : !! multipliers used to obtain the factor U or L from the
3789 : : !! factorization A = U*D*U**H or A = L*D*L**H as computed by
3790 : : !! ZHETRF.
3791 : : !![in,out] B
3792 : : !! B is COMPLEX*16 array, dimension (LDB,NRHS)
3793 : : !! On entry, the N-by-NRHS right hand side matrix B.
3794 : : !! On exit, if INFO = 0, the N-by-NRHS solution matrix X.
3795 : : !![out] INFO
3796 : : !! INFO is INTEGER
3797 : : !! = 0: successful exit
3798 : : !! < 0: if INFO = -i, the i-th argument had an illegal value
3799 : : !! > 0: if INFO = i, D(i,i) is exactly zero. The factorization
3800 : : !! has been completed, but the block diagonal matrix D is
3801 : : !! exactly singular, so the solution could not be computed.
3802 : : !! SOURCE
3803 : :
3804 : 9576 : subroutine xhesv_cplex(UPLO, cplex, N, NRHS, A, B, msg, info)
3805 : :
3806 : : !Arguments ------------------------------------
3807 : : character(len=1),intent(in) :: UPLO
3808 : : integer,intent(in) :: cplex, N, NRHS
3809 : : real(dp),intent(inout) :: A(cplex, N, N)
3810 : : real(dp),intent(inout) :: B(cplex, N, NRHS)
3811 : : character(len=*),intent(out) :: msg
3812 : : integer,intent(out) :: info
3813 : :
3814 : : !Local variables ------------------------------
3815 : : !scalars
3816 : : integer :: lwork, lda, ldb
3817 : 9576 : integer,allocatable :: ipiv(:)
3818 : 9576 : real(dp),allocatable :: work(:,:)
3819 : : !************************************************************************
3820 : :
3821 [ + - + + : 17148 : if (all(cplex /= [1, 2])) then
- + ]
3822 : 0 : write(msg,'(a,i0)')" Wrong value for cplex: ",cplex
3823 : 0 : info = 1; return
3824 : : end if
3825 : :
3826 : 9576 : lda = N; ldb = N
3827 : :
3828 [ - + + - : 28728 : ABI_MALLOC(ipiv, (N))
+ - + - -
+ - + ]
3829 [ - + + - : 28728 : ABI_MALLOC(work, (cplex, 1))
+ - + - -
+ - + ]
3830 : 9576 : lwork = -1
3831 : :
3832 [ + + ]: 9576 : if (cplex == 2) then
3833 : : ! Complex version
3834 : 7572 : call zhesv(uplo, N, NRHS, A, lda, ipiv, B, ldb, work, lwork, info)
3835 : 7572 : lwork = int(work(1, 1))
3836 [ - + + - : 30288 : ABI_REMALLOC(work, (cplex, lwork))
- + + - +
- + - - +
- + - + ]
3837 : :
3838 : 7572 : call zhesv(uplo, N, NRHS, A, lda, ipiv, B, ldb, work, lwork, info)
3839 : : else
3840 : : ! Read version
3841 : 2004 : call dsysv(uplo, N, NRHS, A, lda, ipiv, B, ldb, work, lwork, info)
3842 : 2004 : lwork = int(work(1, 1))
3843 [ - + + - : 8016 : ABI_REMALLOC(work, (cplex, lwork))
- + + - +
- + - - +
- + - + ]
3844 : :
3845 : 2004 : call dsysv(uplo, N, NRHS, A, lda, ipiv, B, ldb, work, lwork, info)
3846 : : end if
3847 : :
3848 [ - + ]: 9576 : ABI_FREE(ipiv)
3849 [ - + ]: 9576 : ABI_FREE(work)
3850 : :
3851 [ - + ]: 9576 : if (info < 0) then
3852 : 0 : write(msg,'(a,i0,a)')" The ",-info,"-th argument of ZPOTRI had an illegal value."
3853 [ - + ]: 9576 : else if (info > 0) then
3854 : : write(msg, "(a,i0,4a)") &
3855 : 0 : " D(i,i) is exactly zero for i= ", info, ch10, &
3856 : 0 : "The factorization has been completed, but the block diagonal matrix D is ", ch10, &
3857 : 0 : "exactly singular, so the solution could not be computed."
3858 : : end if
3859 : :
3860 : : end subroutine xhesv_cplex
3861 : : !!***
3862 : :
3863 : 0 : end module m_hide_lapack
3864 : : !!***
|