24#include "../base/base_uses.f90"
29 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mathlib'
30 REAL(KIND=
dp),
PARAMETER :: eps_geo = 1.0e-6_dp
71 MODULE PROCEDURE det_3x3_1, det_3x3_2
75 MODULE PROCEDURE invert_matrix_d, invert_matrix_z
79 MODULE PROCEDURE set_diag_scalar_d, set_diag_scalar_z
83 MODULE PROCEDURE swap_scalar, swap_vector
87 MODULE PROCEDURE unit_matrix_d, unit_matrix_z
91 MODULE PROCEDURE zgemm_square_2, zgemm_square_3, dgemm_square_2, dgemm_square_3
108 REAL(kind=
dp) :: x, a, b
112 REAL(kind=
dp) :: u, u2, u3
115 IF (x < a .OR. x > b)
THEN
136 fx = 1._dp - 10._dp*u3 + 15._dp*u2*u2 - 6._dp*u2*u3
139 fx = -30._dp*u2 + 60._dp*u*u2 - 30._dp*u2*u2
143 fx = -60._dp*u + 180._dp*u2 - 120._dp*u*u2
146 cpabort(
'order not defined')
161 CHARACTER(LEN=32) :: buffer
169 IF (index(buffer,
"N") /= 0 .OR. index(buffer,
"n") /= 0)
abnormal_value = .true.
183 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
184 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: a, b
185 REAL(kind=
dp) :: angle_ab
187 REAL(kind=
dp) :: length_of_a, length_of_b
188 REAL(kind=
dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
190 length_of_a = norm2(a)
191 length_of_b = norm2(b)
193 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
194 a_norm(:) = a(:)/length_of_a
195 b_norm(:) = b(:)/length_of_b
196 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
214 INTEGER,
INTENT(IN) :: n, k
215 REAL(kind=
dp) :: n_over_k
217 IF ((k >= 0) .AND. (k <= n))
THEN
238 REAL(kind=
dp),
INTENT(IN) :: z
239 INTEGER,
INTENT(IN) :: k
240 REAL(kind=
dp) :: z_over_k
247 z_over_k = z_over_k*(z - i + 1)/real(i,
dp)
263 INTEGER,
INTENT(IN) :: n
264 INTEGER,
DIMENSION(:),
INTENT(IN) :: k
268 REAL(kind=
dp) :: denom
270 IF (all(k >= 0) .AND. sum(k) == n)
THEN
273 denom = denom*
fac(k(i))
294 REAL(kind=
dp),
INTENT(IN) :: phi
295 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
296 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: rotmat
298 REAL(kind=
dp) :: cosp, cost, length_of_a, sinp
299 REAL(kind=
dp),
DIMENSION(3) :: d
301 length_of_a = sqrt(a(1)*a(1) + a(2)*a(2) + a(3)*a(3))
303 IF (length_of_a > eps_geo)
THEN
305 d(:) = a(:)/length_of_a
311 rotmat(1, 1) = d(1)*d(1)*cost + cosp
312 rotmat(1, 2) = d(1)*d(2)*cost - d(3)*sinp
313 rotmat(1, 3) = d(1)*d(3)*cost + d(2)*sinp
314 rotmat(2, 1) = d(2)*d(1)*cost + d(3)*sinp
315 rotmat(2, 2) = d(2)*d(2)*cost + cosp
316 rotmat(2, 3) = d(2)*d(3)*cost - d(1)*sinp
317 rotmat(3, 1) = d(3)*d(1)*cost - d(2)*sinp
318 rotmat(3, 2) = d(3)*d(2)*cost + d(1)*sinp
319 rotmat(3, 3) = d(3)*d(3)*cost + cosp
334 PURE FUNCTION det_3x3_1(a)
RESULT(det_a)
335 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
336 REAL(kind=
dp) :: det_a
338 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
339 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
340 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
342 END FUNCTION det_3x3_1
354 PURE FUNCTION det_3x3_2(a1, a2, a3)
RESULT(det_a)
355 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3
356 REAL(kind=
dp) :: det_a
358 det_a = a1(1)*(a2(2)*a3(3) - a3(2)*a2(3)) + &
359 a2(1)*(a3(2)*a1(3) - a1(2)*a3(3)) + &
360 a3(1)*(a1(2)*a2(3) - a2(2)*a1(3))
362 END FUNCTION det_3x3_2
381 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
382 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigval
383 LOGICAL,
INTENT(IN),
OPTIONAL :: dac
385 CHARACTER(len=*),
PARAMETER :: routinen =
'diamat_all'
387 INTEGER :: handle, info, liwork, lwork, n, nb
388 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
389 INTEGER,
EXTERNAL :: ilaenv
390 LOGICAL :: divide_and_conquer
391 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
393 EXTERNAL dsyev, dsyevd
395 CALL timeset(routinen, handle)
401 IF (
SIZE(a, 2) /= n)
THEN
402 cpabort(
"Check the size of matrix a (parameter #1)")
406 IF (
SIZE(eigval) /= n)
THEN
407 cpabort(
"The dimension of vector eigval is too small")
412 IF (
PRESENT(dac))
THEN
413 divide_and_conquer = dac
415 divide_and_conquer = .false.
420 IF (divide_and_conquer)
THEN
421 lwork = 2*n**2 + 6*n + 1
424 nb = ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1)
430 ALLOCATE (work(lwork))
431 IF (divide_and_conquer)
THEN
432 ALLOCATE (iwork(liwork))
438 IF (divide_and_conquer)
THEN
439 CALL dsyevd(
"V",
"U", n, a, n, eigval, work, lwork, iwork, liwork, info)
441 CALL dsyev(
"V",
"U", n, a, n, eigval, work, lwork, info)
445 IF (divide_and_conquer)
THEN
446 cpabort(
"The matrix diagonalization with dsyevd failed")
448 cpabort(
"The matrix diagonalization with dsyev failed")
455 IF (divide_and_conquer)
THEN
459 CALL timestop(handle)
476 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: ab, bc, cd
477 REAL(kind=
dp) :: dihedral_angle_abcd
479 REAL(kind=
dp) :: det_abcd
480 REAL(kind=
dp),
DIMENSION(3) :: abc, bcd
487 det_abcd =
det_3x3(abc, bcd, -bc)
488 dihedral_angle_abcd = sign(1.0_dp, det_abcd)*
angle(abc, bcd)
501 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
503 DIMENSION(MIN(SIZE(a, 1), SIZE(a, 2))) :: a_diag
507 n = min(
SIZE(a, 1),
SIZE(a, 2))
524 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
525 REAL(kind=
dp),
DIMENSION(3, 3) :: a_inv
527 REAL(kind=
dp) :: det_a
531 a_inv(1, 1) = (a(2, 2)*a(3, 3) - a(3, 2)*a(2, 3))*det_a
532 a_inv(2, 1) = (a(2, 3)*a(3, 1) - a(3, 3)*a(2, 1))*det_a
533 a_inv(3, 1) = (a(2, 1)*a(3, 2) - a(3, 1)*a(2, 2))*det_a
535 a_inv(1, 2) = (a(1, 3)*a(3, 2) - a(3, 3)*a(1, 2))*det_a
536 a_inv(2, 2) = (a(1, 1)*a(3, 3) - a(3, 1)*a(1, 3))*det_a
537 a_inv(3, 2) = (a(1, 2)*a(3, 1) - a(3, 2)*a(1, 1))*det_a
539 a_inv(1, 3) = (a(1, 2)*a(2, 3) - a(2, 2)*a(1, 3))*det_a
540 a_inv(2, 3) = (a(1, 3)*a(2, 1) - a(2, 3)*a(1, 1))*det_a
541 a_inv(3, 3) = (a(1, 1)*a(2, 2) - a(2, 1)*a(1, 2))*det_a
551 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
552 INTEGER,
INTENT(OUT) :: info
554 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat'
556 INTEGER :: handle, lwork, n
557 INTEGER,
ALLOCATABLE :: ipiv(:)
558 REAL(kind=
dp),
ALLOCATABLE :: work(:)
560 CALL timeset(routinen, handle)
565 ALLOCATE (work(lwork))
569 CALL dgetrf(n, n, a, n, ipiv, info)
571 CALL dgetri(n, a, n, ipiv, work, lwork, info)
573 DEALLOCATE (ipiv, work)
575 CALL timestop(handle)
588 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
589 LOGICAL,
INTENT(IN),
OPTIONAL :: potrf
590 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: uplo
592 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat_symm'
594 CHARACTER(LEN=1) :: myuplo
595 INTEGER :: handle, info, n
598 CALL timeset(routinen, handle)
601 IF (
PRESENT(potrf)) do_potrf = potrf
604 IF (
PRESENT(uplo)) myuplo = uplo
611 CALL dpotrf(myuplo, n, a, n, info)
612 IF (info /= 0) cpabort(
"DPOTRF failed")
616 CALL dpotri(myuplo, n, a, n, info)
617 IF (info /= 0) cpabort(
"Matrix inversion failed")
620 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
626 CALL timestop(handle)
652 SUBROUTINE invert_matrix_d(a, a_inverse, eval_error, option, improve)
653 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
654 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
655 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
656 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
657 LOGICAL,
INTENT(IN),
OPTIONAL :: improve
659 CHARACTER(LEN=1) :: norm, trans
660 CHARACTER(LEN=default_string_length) :: message
661 INTEGER :: info, iter, n
662 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv, iwork
663 LOGICAL :: do_improve
664 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
665 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, work
666 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
667 REAL(KIND=
dp),
EXTERNAL :: dlange
669 EXTERNAL dgecon, dgerfs, dgetrf, dgetrs
672 IF (
PRESENT(option))
THEN
678 IF (
PRESENT(improve))
THEN
689 cpabort(
"Matrix to be inverted of zero size")
692 IF (n /=
SIZE(a, 2))
THEN
693 cpabort(
"Check the array bounds of parameter #1")
696 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
697 (n /=
SIZE(a_inverse, 2)))
THEN
698 cpabort(
"Check the array bounds of parameter #2")
702 ALLOCATE (a_lu(n, n))
710 a_lu(1:n, 1:n) = a(1:n, 1:n)
713 CALL dgetrf(n, n, a_lu, n, ipiv, info)
716 cpabort(
"The LU factorization in dgetrf failed")
721 IF (trans ==
"N")
THEN
727 a_norm = dlange(norm, n, n, a, n, work)
731 CALL dgecon(norm, n, a_lu, n, a_norm, r_cond, work, iwork, info)
734 cpabort(
"The computation of the condition number in dgecon failed")
737 IF (r_cond < epsilon(0.0_dp))
THEN
738 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
739 CALL cp_abort(__location__, &
740 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
741 "working precision)")
748 CALL dgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
751 cpabort(
"Solving the system of linear equations in dgetrs failed")
762 CALL dgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
766 cpabort(
"Improving the computed solution in dgerfs failed")
769 old_eval_error = eval_error
770 eval_error = maxval(ferr)
772 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
786 END SUBROUTINE invert_matrix_d
808 SUBROUTINE invert_matrix_z(a, a_inverse, eval_error, option)
809 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: a
810 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
811 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
812 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
814 CHARACTER(LEN=1) :: norm, trans
815 CHARACTER(LEN=default_string_length) :: message
816 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: work
817 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
818 INTEGER :: info, iter, n
819 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
820 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
821 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, rwork
822 REAL(KIND=
dp),
EXTERNAL :: zlange
824 EXTERNAL zgecon, zgerfs, zgetrf, zgetrs
827 IF (
PRESENT(option))
THEN
838 cpabort(
"Matrix to be inverted of zero size")
841 IF (n /=
SIZE(a, 2))
THEN
842 cpabort(
"Check the array bounds of parameter #1")
845 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
846 (n /=
SIZE(a_inverse, 2)))
THEN
847 cpabort(
"Check the array bounds of parameter #2")
851 ALLOCATE (a_lu(n, n))
856 ALLOCATE (rwork(2*n))
859 a_lu(1:n, 1:n) = a(1:n, 1:n)
862 CALL zgetrf(n, n, a_lu, n, ipiv, info)
865 cpabort(
"The LU factorization in dgetrf failed")
870 IF (trans ==
"N")
THEN
876 a_norm = zlange(norm, n, n, a, n, work)
880 CALL zgecon(norm, n, a_lu, n, a_norm, r_cond, work, rwork, info)
883 cpabort(
"The computation of the condition number in dgecon failed")
886 IF (r_cond < epsilon(0.0_dp))
THEN
887 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
888 CALL cp_abort(__location__, &
889 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
890 "working precision)")
897 CALL zgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
900 cpabort(
"Solving the system of linear equations in dgetrs failed")
910 CALL zgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
914 cpabort(
"Improving the computed solution in dgerfs failed")
917 old_eval_error = eval_error
918 eval_error = maxval(ferr)
920 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
933 END SUBROUTINE invert_matrix_z
946 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
947 REAL(kind=
dp),
INTENT(IN) :: rskip
948 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: determinant
949 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT), &
950 OPTIONAL,
POINTER :: sval
952 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_svd'
954 INTEGER :: handle, i, info, lwork, n
955 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
956 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: sig, work
957 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: sig_plus, temp_mat, u, vt
959 CALL timeset(routinen, handle)
962 ALLOCATE (u(n, n), vt(n, n), sig(n), sig_plus(n, n), iwork(8*n), work(1), temp_mat(n, n))
969 IF (
PRESENT(determinant)) determinant = 1.0_dp
973 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
974 lwork, iwork(1), info)
977 cpabort(
"ERROR in DGESDD: Could not retrieve work array sizes")
981 ALLOCATE (work(lwork))
984 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
985 lwork, iwork(1), info)
988 cpabort(
"SVD failed")
991 IF (
PRESENT(sval))
THEN
992 cpassert(.NOT.
ASSOCIATED(sval))
999 IF (sig(i) > rskip*maxval(sig))
THEN
1000 IF (
PRESENT(determinant))
THEN
1001 determinant = determinant*sig(i)
1003 sig_plus(i, i) = 1._dp/sig(i)
1005 sig_plus(i, i) = 0.0_dp
1010 CALL dgemm(
"N",
"T", n, n, n, 1._dp, sig_plus, n, u, n, 0._dp, temp_mat, n)
1011 CALL dgemm(
"T",
"N", n, n, n, 1._dp, vt, n, temp_mat, n, 0._dp, a_pinverse, n)
1013 DEALLOCATE (u, vt, sig, iwork, work, sig_plus, temp_mat)
1015 CALL timestop(handle)
1028 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
1029 REAL(kind=
dp),
INTENT(IN) :: rskip
1031 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_diag'
1033 INTEGER :: handle, i, info, lwork, n
1034 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig, work
1035 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dinv, temp_mat
1037 CALL timeset(routinen, handle)
1041 ALLOCATE (dinv(n, n), eig(n), work(1), temp_mat(n, n))
1049 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1051 cpabort(
"ERROR in DSYEV: Could not retrieve work array sizes")
1053 lwork = int(work(1))
1055 ALLOCATE (work(lwork))
1059 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1062 cpabort(
"Matrix diagonalization failed")
1067 IF (eig(i) > rskip*maxval(eig))
THEN
1068 dinv(i, i) = 1.0_dp/eig(i)
1075 CALL dgemm(
"N",
"T", n, n, n, 1._dp, dinv, n, a, n, 0._dp, temp_mat, n)
1076 CALL dgemm(
"N",
"N", n, n, n, 1._dp, a, n, temp_mat, n, 0._dp, a_pinverse, n)
1078 DEALLOCATE (eig, work, dinv, temp_mat)
1080 CALL timestop(handle)
1095 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1096 REAL(kind=
dp),
DIMENSION(3) :: a_mirror
1098 REAL(kind=
dp) :: length_of_b, scapro
1099 REAL(kind=
dp),
DIMENSION(3) :: d
1101 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1103 IF (length_of_b > eps_geo)
THEN
1105 d(:) = b(:)/length_of_b
1108 scapro = a(1)*d(1) + a(2)*d(2) + a(3)*d(3)
1110 a_mirror(:) = a(:) - 2.0_dp*scapro*d(:)
1114 a_mirror(:) = 0.0_dp
1133 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
1134 REAL(kind=
dp),
INTENT(IN) :: phi
1135 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: b
1136 REAL(kind=
dp),
DIMENSION(3) :: a_rot
1138 REAL(kind=
dp) :: length_of_b
1139 REAL(kind=
dp),
DIMENSION(3, 3) :: rotmat
1141 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1142 IF (length_of_b > eps_geo)
THEN
1148 a_rot(:) = matmul(rotmat, a)
1166 PURE SUBROUTINE set_diag_scalar_d(a, b)
1167 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1168 REAL(kind=
dp),
INTENT(IN) :: b
1172 n = min(
SIZE(a, 1),
SIZE(a, 2))
1177 END SUBROUTINE set_diag_scalar_d
1184 PURE SUBROUTINE set_diag_scalar_z(a, b)
1185 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1186 COMPLEX(KIND=dp),
INTENT(IN) :: b
1190 n = min(
SIZE(a, 1),
SIZE(a, 2))
1195 END SUBROUTINE set_diag_scalar_z
1206 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1207 CHARACTER(LEN=*),
INTENT(IN) :: option
1211 n = min(
SIZE(a, 1),
SIZE(a, 2))
1213 IF (option ==
"lower_to_upper")
THEN
1215 a(i, i + 1:n) = a(i + 1:n, i)
1217 ELSE IF (option ==
"upper_to_lower")
THEN
1219 a(i + 1:n, i) = a(i, i + 1:n)
1221 ELSE IF (option ==
"anti_lower_to_upper")
THEN
1223 a(i, i + 1:n) = -a(i + 1:n, i)
1225 ELSE IF (option ==
"anti_upper_to_lower")
THEN
1227 a(i + 1:n, i) = -a(i, i + 1:n)
1230 cpabort(
"Invalid option <"//trim(option)//
"> was specified for parameter #2")
1242 PURE SUBROUTINE unit_matrix_d(a)
1243 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1248 END SUBROUTINE unit_matrix_d
1254 PURE SUBROUTINE unit_matrix_z(a)
1255 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1257 a(:, :) = (0.0_dp, 0.0_dp)
1260 END SUBROUTINE unit_matrix_z
1272 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1273 REAL(kind=
dp),
DIMENSION(3) :: c
1275 c(1) = a(2)*b(3) - a(3)*b(2)
1276 c(2) = a(3)*b(1) - a(1)*b(3)
1277 c(3) = a(1)*b(2) - a(2)*b(1)
1289 INTEGER,
INTENT(IN) :: a, b
1292 INTEGER :: aa, ab, l, rem, s
1324 INTEGER,
INTENT(IN) :: a, b
1334 lcm = abs((a/tmp)*b)
1348 INTEGER,
PARAMETER :: maxit = 100
1349 REAL(
dp),
PARAMETER :: eps = epsilon(0.0_dp), &
1350 fpmin = tiny(0.0_dp)
1353 REAL(
dp) :: fact, prev, sum1, term
1355 IF (x <= 0._dp)
THEN
1356 cpabort(
"Invalid argument")
1361 ELSE IF (x <= -log(eps))
THEN
1365 fact = fact*x/real(k,
dp)
1366 term = fact/real(k,
dp)
1368 IF (term < eps*sum1)
EXIT
1370 ei = sum1 + log(x) +
euler
1376 term = term*real(k,
dp)/x
1377 IF (term < eps)
EXIT
1378 IF (term < prev)
THEN
1385 ei = exp(x)*(1._dp + sum1)/x
1402 REAL(
dp),
INTENT(IN) :: xx
1405 REAL(
dp),
PARAMETER :: dx0 = 1.461632144968362341262659542325721325e0_dp, p1(7) = [ &
1406 .895385022981970e-02_dp, .477762828042627e+01_dp, .142441585084029e+03_dp, &
1407 .118645200713425e+04_dp, .363351846806499e+04_dp, .413810161269013e+04_dp, &
1408 .130560269827897e+04_dp], p2(4) = [-.212940445131011e+01_dp, -.701677227766759e+01_dp, &
1409 -.448616543918019e+01_dp, -.648157123766197e+00_dp], piov4 = .785398163397448e0_dp, q1(6) &
1410 = [.448452573429826e+02_dp, .520752771467162e+03_dp, .221000799247830e+04_dp, &
1411 .364127349079381e+04_dp, .190831076596300e+04_dp, .691091682714533e-05_dp]
1412 REAL(
dp),
PARAMETER :: q2(4) = [.322703493791143e+02_dp, .892920700481861e+02_dp, &
1413 .546117738103215e+02_dp, .777788548522962e+01_dp]
1415 INTEGER :: i, m, n, nq
1416 REAL(
dp) :: aug, den, sgn, upper, w, x, xmax1, xmx0, &
1426 xmax1 = min(real(huge(0), kind=
dp), 1.0e0_dp/epsilon(1.0e0_dp))
1431 IF (x < 0.5e0_dp)
THEN
1433 IF (abs(x) <= xsmall)
THEN
1434 IF (x == 0.0e0_dp)
THEN
1446 IF (w <= 0.0e0_dp)
THEN
1450 IF (w >= xmax1)
THEN
1457 nq = int(w*4.0e0_dp)
1458 w = 4.0e0_dp*(w - nq*.25e0_dp)
1461 IF ((n + n) /= nq) w = 1.0e0_dp - w
1464 IF ((m + m) /= n) sgn = -sgn
1471 aug = sgn*((sin(z)/cos(z))*4.0e0_dp)
1473 IF (z == 0.0e0_dp)
THEN
1478 aug = sgn*((cos(z)/sin(z))*4.0e0_dp)
1484 IF (x <= 3.0e0_dp)
THEN
1490 den = (den + q1(i))*x
1491 upper = (upper + p1(i + 1))*x
1494 den = (upper + p1(7))/(den + q1(6))
1496 fn_val = den*xmx0 + aug
1507 den = (den + q2(i))*w
1508 upper = (upper + p2(i + 1))*w
1511 aug = upper/(den + q2(4)) - 0.5e0_dp/x + aug
1514 fn_val = aug + log(x)
1530 INTEGER,
INTENT(IN) :: n
1531 REAL(
dp),
INTENT(IN) :: x
1534 INTEGER,
PARAMETER :: maxit = 100
1535 REAL(
dp),
PARAMETER :: eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp, &
1536 fpmin = tiny(0.0_dp)
1538 INTEGER :: i, ii, nm1
1539 REAL(
dp) :: a, b, c, d, del, fact, h, psi
1543 IF (n < 0 .OR. x < 0.0_dp .OR. (x == 0.0_dp .AND. (n == 0 .OR. n == 1)))
THEN
1544 cpabort(
"Invalid argument")
1545 ELSE IF (n == 0)
THEN
1547 ELSE IF (x == 0.0_dp)
THEN
1549 ELSE IF (x > 1.0_dp)
THEN
1557 d = 1.0_dp/(a*d + b)
1561 IF (abs(del - 1.0_dp) < eps)
THEN
1566 cpabort(
"continued fraction failed in expint")
1577 del = -fact/(i - nm1)
1581 psi = psi + 1.0_dp/ii
1583 del = fact*(-log(x) + psi)
1586 IF (abs(del) < abs(
expint)*eps)
RETURN
1588 cpabort(
"series failed in expint")
1605 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1606 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1607 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1614 CALL diag(n, a, d, v)
1617 CALL eigsrt(n, d, v)
1633 INTEGER,
INTENT(IN) :: n
1634 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1635 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1636 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1638 CHARACTER(len=*),
PARAMETER :: routinen =
'diag'
1639 INTEGER,
PARAMETER :: maxit = 100
1640 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1642 CHARACTER(LEN=default_string_length) :: max_iter
1643 INTEGER :: handle, i, ip, iq
1644 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1645 t, tau, theta, tresh
1646 REAL(kind=
dp),
DIMENSION(n) :: b, z
1648 CALL timeset(routinen, handle)
1652 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1661 d_min = max(d_eps, minval(abs(b)))
1662 IF (a_max < a_eps*d_min)
THEN
1663 CALL timestop(handle)
1666 tresh = merge(a_max, 0.0_dp, (i < 4))
1673 g = 100.0_dp*abs(apq)
1674 IF (tresh < abs(apq))
THEN
1676 IF ((abs(h) + g) /= abs(h))
THEN
1677 theta = 0.5_dp*h/apq
1678 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1679 IF (theta < 0.0_dp) t = -t
1683 c = 1.0_dp/sqrt(1.0_dp + t**2)
1685 tau = s/(1.0_dp + c)
1692 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1693 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1694 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1695 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1696 ELSE IF ((4 < i) .AND. &
1697 ((abs(dip) + g) == abs(dip)) .AND. &
1698 ((abs(diq) + g) == abs(diq)))
THEN
1706 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1709 WRITE (max_iter, *) maxit
1710 CALL cp_warn(__location__, &
1711 "Jacobi matrix diagonalization does not converge after "// &
1712 trim(adjustl(max_iter))//
" iterations; stop here anyway")
1714 CALL timestop(handle)
1728 PURE SUBROUTINE jrotate(a, b, ss, tt)
1729 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1730 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1732 REAL(kind=
dp) :: u, v
1738 b = b*(u + ss*v) + a*v
1740 END SUBROUTINE jrotate
1752 SUBROUTINE eigsrt(n, d, v)
1753 INTEGER,
INTENT(IN) :: n
1754 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1755 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1760 j = sum(minloc(d(i:n))) + i - 1
1762 CALL swap(d(i), d(j))
1763 CALL swap(v(:, i), v(:, j))
1767 END SUBROUTINE eigsrt
1777 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1778 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1786 END SUBROUTINE swap_scalar
1796 SUBROUTINE swap_vector(a, b)
1797 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1804 IF (n /=
SIZE(b))
THEN
1805 cpabort(
"Check the array bounds of the parameters")
1814 END SUBROUTINE swap_vector
1827 REAL(
dp),
INTENT(in) :: eps, omg
1828 REAL(
dp),
INTENT(out) :: r_cutoff
1830 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1832 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1833 REAL(
dp) :: r0, f0, fprime0, delta_r
1834 INTEGER :: iter, handle
1835 INTEGER,
PARAMETER :: itermax = 1000
1837 CALL timeset(routinen, handle)
1840 r0 = sqrt(-log(eps*omg*10**2))/omg
1841 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1843 DO iter = 1, itermax
1844 delta_r = f0/fprime0
1846 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1847 IF (abs(delta_r) < abstol .OR. abs(f0) < soltol)
EXIT
1849 cpassert(iter <= itermax)
1852 CALL timestop(handle)
1862 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1863 REAL(
dp),
INTENT(in) :: r, eps, omega
1864 REAL(
dp),
INTENT(out) :: fn, df
1869 fn = erfc(qr) - r*eps
1870 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1871 END SUBROUTINE eval_transc_func
1882 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
1883 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
1884 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1886 CHARACTER(len=*),
PARAMETER :: routinen =
'diag_complex'
1888 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1889 INTEGER :: handle, info, liwork, lrwork, lwork, n
1890 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1891 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1893 CALL timeset(routinen, handle)
1895 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1899 ALLOCATE (iwork(1), rwork(1), work(1))
1906 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1908 lwork = ceiling(real(work(1), kind=
dp))
1909 lrwork = ceiling(rwork(1))
1912 DEALLOCATE (iwork, rwork, work)
1913 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1914 eigenvectors(:, :) = matrix(:, :)
1917 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1919 DEALLOCATE (iwork, rwork, work)
1921 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
1923 CALL timestop(handle)
1934 REAL(
dp),
DIMENSION(:, :) :: matrix
1935 COMPLEX(dp),
DIMENSION(:, :) :: evecs
1936 COMPLEX(dp),
DIMENSION(:) :: evals
1938 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_c
1940 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
1942 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1946 ALLOCATE (matrix_c(n, n), eigenvalues(n))
1948 matrix_c(:, :) = cmplx(0.0_dp, -matrix, kind=
dp)
1950 evals = cmplx(0.0_dp, eigenvalues, kind=
dp)
1952 DEALLOCATE (matrix_c, eigenvalues)
1964 SUBROUTINE zgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1965 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1966 CHARACTER,
INTENT(IN) :: A_trans
1967 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1968 CHARACTER,
INTENT(IN) :: B_trans
1969 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: C_out
1971 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_2'
1973 INTEGER :: handle, n
1976 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1977 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1978 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1979 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
1980 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
1981 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1982 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1983 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
1984 cpabort(
"Unknown transpose character for array 1 (A).")
1986 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1987 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1988 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
1989 cpabort(
"Unknown transpose character for array 2 (B).")
1992 CALL timeset(routinen, handle)
1994 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, c_out, n)
1996 CALL timestop(handle)
1998 END SUBROUTINE zgemm_square_2
2009 SUBROUTINE dgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
2010 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
2011 CHARACTER,
INTENT(IN) :: A_trans
2012 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
2013 CHARACTER,
INTENT(IN) :: B_trans
2014 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: c_out
2016 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_2'
2018 INTEGER :: handle, n
2021 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2022 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2023 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2024 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
2025 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
2026 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2027 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2028 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2029 cpabort(
"Unknown transpose character for array 1 (A).")
2031 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2032 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2033 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2034 cpabort(
"Unknown transpose character for array 2 (B).")
2037 CALL timeset(routinen, handle)
2039 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, c_out, n)
2041 CALL timestop(handle)
2043 END SUBROUTINE dgemm_square_2
2056 SUBROUTINE zgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
2057 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
2058 CHARACTER,
INTENT(IN) :: A_trans
2059 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
2060 CHARACTER,
INTENT(IN) :: B_trans
2061 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: C_in
2062 CHARACTER,
INTENT(IN) :: C_trans
2063 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: D_out
2065 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_3'
2067 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
2068 INTEGER :: handle, n
2071 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2072 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2073 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2074 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
2075 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2076 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2077 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2078 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2079 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2080 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2081 cpabort(
"Unknown transpose character for array 1 (A).")
2083 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2084 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2085 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2086 cpabort(
"Unknown transpose character for array 2 (B).")
2088 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2089 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2090 c_trans ==
'C' .OR. c_trans ==
'c'))
THEN
2091 cpabort(
"Unknown transpose character for array 3 (C).")
2094 CALL timeset(routinen, handle)
2096 ALLOCATE (work(n, n), source=
z_zero)
2098 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, work, n)
2099 CALL zgemm(
'N', c_trans, n, n, n,
z_one, work, n, c_in, n,
z_zero, d_out, n)
2103 CALL timestop(handle)
2105 END SUBROUTINE zgemm_square_3
2118 SUBROUTINE dgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
2119 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
2120 CHARACTER,
INTENT(IN) :: A_trans
2121 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
2122 CHARACTER,
INTENT(IN) :: B_trans
2123 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: c_in
2124 CHARACTER,
INTENT(IN) :: C_trans
2125 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_out
2127 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_3'
2129 INTEGER :: handle, n
2130 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
2133 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2134 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2135 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2136 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
2137 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2138 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2139 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2140 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2141 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2142 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2143 cpabort(
"Unknown transpose character for array 1 (A).")
2145 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2146 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2147 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2148 cpabort(
"Unknown transpose character for array 2 (B).")
2150 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2151 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2152 c_trans ==
'C' .OR. c_trans ==
'c'))
THEN
2153 cpabort(
"Unknown transpose character for array 3 (C).")
2156 CALL timeset(routinen, handle)
2158 ALLOCATE (work(n, n), source=0.0_dp)
2160 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, work, n)
2161 CALL dgemm(
'N', c_trans, n, n, n, 1.0_dp, work, n, c_in, n, 0.0_dp, d_out, n)
2165 CALL timestop(handle)
2167 END SUBROUTINE dgemm_square_3
2178 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: a_in, b_in
2179 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
2180 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
2182 CHARACTER(len=*),
PARAMETER :: routinen =
'geeig_right'
2183 COMPLEX(KIND=dp),
PARAMETER :: cone = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2184 czero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2186 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: cevals
2187 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a, b, work
2188 INTEGER :: handle, i, icol, irow, lda, ldb, ldc, &
2189 nao, nc, ncol, nmo, nx
2190 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
2192 CALL timeset(routinen, handle)
2196 nmo =
SIZE(eigenvalues)
2197 ALLOCATE (evals(nao), cevals(nao))
2198 ALLOCATE (work(nao, nao), b(nao, nao), a(nao, nao))
2199 a(:, :) = a_in(:, :)
2200 b(:, :) = b_in(:, :)
2205 evals(:) = -evals(:)
2208 IF (evals(i) < -1.0_dp)
THEN
2219 CALL zcopy(ncol*nao, work(1, nc + 1), 1, eigenvectors(1, nc + 1), 1)
2222 DO icol = nc + 1, nao
2224 work(irow, icol) = czero
2228 evals(nc + 1:nao) = 1.0_dp
2231 cevals(:) = cmplx(1.0_dp/sqrt(evals(:)), 0.0_dp, kind=
dp)
2232 DO i = 1, min(
SIZE(work, 2),
SIZE(cevals))
2233 work(1:min(
SIZE(work, 2),
SIZE(cevals)), i) = cevals(i)*work(1:min(
SIZE(work, 2),
SIZE(cevals)), i)
2240 DO icol = nc + 1, nao
2241 a(icol, icol) = 10000*cone
2246 eigenvalues(1:nmo) = evals(1:nmo)
2251 ldc =
SIZE(eigenvectors, 1)
2252 CALL zgemm(
"N",
"N", nao, nx, nc, cone, work, &
2253 lda, b, ldb, czero, eigenvectors, ldc)
2255 DEALLOCATE (evals, cevals, work, b, a)
2257 CALL timestop(handle)
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public oorootpi
complex(kind=dp), parameter, public z_one
real(kind=dp), parameter, public euler
real(kind=dp), dimension(0:maxfac), parameter, public fac
complex(kind=dp), parameter, public z_zero
Collection of simple mathematical functions and subroutines.
subroutine, public get_pseudo_inverse_svd(a, a_pinverse, rskip, determinant, sval)
returns the pseudoinverse of a real, square matrix using singular value decomposition
subroutine, public jacobi(a, d, v)
Jacobi matrix diagonalization. The eigenvalues are returned in vector d and the eigenvectors are retu...
elemental real(kind=dp) function, public binomial(n, k)
The binomial coefficient n over k for 0 <= k <= n is calculated, otherwise zero is returned.
elemental integer function, public lcm(a, b)
computes the least common multiplier of two numbers
subroutine, public get_pseudo_inverse_diag(a, a_pinverse, rskip)
returns the pseudoinverse of a real, symmetric and positive definite matrix using diagonalization.
elemental real(kind=dp) function, public binomial_gen(z, k)
The generalized binomial coefficient z over k for 0 <= k <= n is calculated. (z) z*(z-1)*....
subroutine, public invmat_symm(a, potrf, uplo)
returns inverse of real symmetric, positive definite matrix
pure real(kind=dp) function, dimension(min(size(a, 1), size(a, 2))), public get_diag(a)
Return the diagonal elements of matrix a as a vector.
pure real(kind=dp) function, dimension(3), public reflect_vector(a, b)
Reflection of the vector a through a mirror plane defined by the normal vector b. The reflected vecto...
pure real(kind=dp) function, public angle(a, b)
Calculation of the angle between the vectors a and b. The angle is returned in radians.
subroutine, public diag_complex(matrix, eigenvectors, eigenvalues)
Diagonalizes a local complex Hermitian matrix using LAPACK. Based on cp_cfm_heevd.
subroutine, public diag_antisym(matrix, evecs, evals)
Helper routine for diagonalizing anti symmetric matrices.
pure subroutine, public build_rotmat(phi, a, rotmat)
The rotation matrix rotmat which rotates a vector about a rotation axis defined by the vector a is bu...
pure real(dp) function, public digamma(xx)
Computes the digamma function, the logarithmic derivative of the gamma function.
elemental integer function, public gcd(a, b)
computes the greatest common divisor of two number
subroutine, public symmetrize_matrix(a, option)
Symmetrize the matrix a.
pure real(kind=dp) function, dimension(3, 3), public inv_3x3(a)
Returns the inverse of the 3 x 3 matrix a.
subroutine, public invmat(a, info)
returns inverse of matrix using the lapack routines DGETRF and DGETRI
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
subroutine, public diag(n, a, d, v)
Diagonalize matrix a. The eigenvalues are returned in vector d and the eigenvectors are returned in m...
subroutine, public geeig_right(a_in, b_in, eigenvalues, eigenvectors)
Solve the generalized eigenvalue equation for complex matrices A*v = B*v*λ
pure real(kind=dp) function, dimension(3), public rotate_vector(a, phi, b)
Rotation of the vector a about an rotation axis defined by the vector b. The rotation angle is phi (r...
subroutine, public erfc_cutoff(eps, omg, r_cutoff)
compute a truncation radius for the shortrange operator
logical function, public abnormal_value(a)
determines if a value is not normal (e.g. for Inf and Nan) based on IO to work also under optimizatio...
elemental impure real(dp) function, public expint(n, x)
computes the exponential integral En(x) = Int(exp(-x*t)/t^n,t=1..infinity) x>0, n=0,...
pure real(kind=dp) function, public dihedral_angle(ab, bc, cd)
Returns the dihedral angle, i.e. the angle between the planes defined by the vectors (-ab,...
real(kind=dp) function, public pswitch(x, a, b, order)
Polynomial (5th degree) switching function f(a) = 1 .... f(b) = 0 with f'(a) = f"(a) = f'(b) = f"(b) ...
pure real(kind=dp) function, dimension(3), public vector_product(a, b)
Calculation of the vector product c = a x b.
pure real(kind=dp) function, public multinomial(n, k)
Calculates the multinomial coefficients.