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 52387 : 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 52387 : real(dp),allocatable :: rwork(:)
332 52387 : 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 52387 : use_scalapack=.FALSE.
342 52387 : 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 52387 : lwork = MAX(1,2*n-1)
353 157161 : ABI_MALLOC(work, (lwork))
354 157161 : ABI_MALLOC(rwork, (MAX(1,3*n-2)))
355 :
356 52387 : call ZHEEV(jobz,uplo,n,a,n,w,work,lwork,rwork,info)
357 :
358 52387 : 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 52387 : 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 52387 : ABI_FREE(rwork)
371 52387 : 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 8463483 : 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 8463483 : integer,allocatable :: ipiv(:)
2708 8463483 : 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 8463483 : use_scalapack=.FALSE.
2717 8463483 : if (PRESENT(comm)) then
2718 5977 : 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 25390449 : ABI_MALLOC(ipiv, (n))
2727 8463483 : call ZGETRF(n,n,a,n,ipiv,info) ! P* L* U Factorization.
2728 :
2729 8463483 : 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 8463483 : 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 8463483 : lwork=MAX(1,n)
2744 25390449 : ABI_MALLOC(work,(lwork))
2745 :
2746 8463483 : call ZGETRI(n,a,n,ipiv,work,lwork,info) ! Invert U and then compute inv(A)
2747 :
2748 8463483 : 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 8463483 : 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 8463483 : ABI_FREE(ipiv)
2761 8463483 : 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 : !!***
|