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 ELEMENTAL IMPURE FUNCTION expint(n, x, exp_mx)
1531 INTEGER,
INTENT(IN) :: n
1532 REAL(
dp),
INTENT(IN) :: x
1533 REAL(
dp),
INTENT(IN),
OPTIONAL :: exp_mx
1536 INTEGER,
PARAMETER :: maxit = 100
1537 REAL(
dp),
PARAMETER :: cf_rescale_inv = 1.0e-100_dp, cf_rescale_max = 1.0e100_dp, &
1538 eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp
1540 INTEGER :: i, ii, nm1
1541 REAL(
dp) :: a, a0, a1, a2, b, b0, b1, b2, del, fact, &
1546 IF (n < 0 .OR. x < 0.0_dp .OR. (x == 0.0_dp .AND. (n == 0 .OR. n == 1)))
THEN
1547 cpabort(
"Invalid argument")
1548 ELSE IF (n == 0)
THEN
1549 IF (
PRESENT(exp_mx))
THEN
1554 ELSE IF (x == 0.0_dp)
THEN
1556 ELSE IF (x > 750.0_dp)
THEN
1558 ELSE IF (x > 1.0_dp)
THEN
1559 IF (
PRESENT(exp_mx))
THEN
1575 IF (abs(b2) > cf_rescale_max)
THEN
1576 a2 = a2*cf_rescale_inv
1577 b2 = b2*cf_rescale_inv
1578 a1 = a1*cf_rescale_inv
1579 b1 = b1*cf_rescale_inv
1581 IF (abs(a2*b1 - a1*b2) < eps*abs(a2*b1) .OR. i == maxit)
THEN
1582 IF (abs(a2*b1 - a1*b2) >= eps*abs(a2*b1))
THEN
1583 cpabort(
"continued fraction failed in expint")
1585 expint = (a2/b2)*my_exp_mx
1603 del = -fact/(i - nm1)
1607 psi = psi + 1.0_dp/ii
1609 del = fact*(-log(x) + psi)
1612 IF (abs(del) < abs(
expint)*eps)
RETURN
1614 cpabort(
"series failed in expint")
1630 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1631 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1632 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1639 CALL diag(n, a, d, v)
1642 CALL eigsrt(n, d, v)
1658 INTEGER,
INTENT(IN) :: n
1659 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1660 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1661 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1663 CHARACTER(len=*),
PARAMETER :: routinen =
'diag'
1664 INTEGER,
PARAMETER :: maxit = 100
1665 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1667 CHARACTER(LEN=default_string_length) :: max_iter
1668 INTEGER :: handle, i, ip, iq
1669 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1670 t, tau, theta, tresh
1671 REAL(kind=
dp),
DIMENSION(n) :: b, z
1673 CALL timeset(routinen, handle)
1677 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1686 d_min = max(d_eps, minval(abs(b)))
1687 IF (a_max < a_eps*d_min)
THEN
1688 CALL timestop(handle)
1691 tresh = merge(a_max, 0.0_dp, (i < 4))
1698 g = 100.0_dp*abs(apq)
1699 IF (tresh < abs(apq))
THEN
1701 IF ((abs(h) + g) /= abs(h))
THEN
1702 theta = 0.5_dp*h/apq
1703 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1704 IF (theta < 0.0_dp) t = -t
1708 c = 1.0_dp/sqrt(1.0_dp + t**2)
1710 tau = s/(1.0_dp + c)
1717 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1718 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1719 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1720 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1721 ELSE IF ((4 < i) .AND. &
1722 ((abs(dip) + g) == abs(dip)) .AND. &
1723 ((abs(diq) + g) == abs(diq)))
THEN
1731 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1734 WRITE (max_iter, *) maxit
1735 CALL cp_warn(__location__, &
1736 "Jacobi matrix diagonalization does not converge after "// &
1737 trim(adjustl(max_iter))//
" iterations; stop here anyway")
1739 CALL timestop(handle)
1753 PURE SUBROUTINE jrotate(a, b, ss, tt)
1754 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1755 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1757 REAL(kind=
dp) :: u, v
1763 b = b*(u + ss*v) + a*v
1765 END SUBROUTINE jrotate
1777 SUBROUTINE eigsrt(n, d, v)
1778 INTEGER,
INTENT(IN) :: n
1779 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1780 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1785 j = sum(minloc(d(i:n))) + i - 1
1787 CALL swap(d(i), d(j))
1788 CALL swap(v(:, i), v(:, j))
1792 END SUBROUTINE eigsrt
1802 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1803 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1811 END SUBROUTINE swap_scalar
1821 SUBROUTINE swap_vector(a, b)
1822 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1829 IF (n /=
SIZE(b))
THEN
1830 cpabort(
"Check the array bounds of the parameters")
1839 END SUBROUTINE swap_vector
1852 REAL(
dp),
INTENT(in) :: eps, omg
1853 REAL(
dp),
INTENT(out) :: r_cutoff
1855 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1857 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1858 REAL(
dp) :: r0, f0, fprime0, delta_r
1859 INTEGER :: iter, handle
1860 INTEGER,
PARAMETER :: itermax = 1000
1862 CALL timeset(routinen, handle)
1865 r0 = sqrt(-log(eps*omg*10**2))/omg
1866 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1868 DO iter = 1, itermax
1869 delta_r = f0/fprime0
1871 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1872 IF (abs(delta_r) < abstol .OR. abs(f0) < soltol)
EXIT
1874 cpassert(iter <= itermax)
1877 CALL timestop(handle)
1887 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1888 REAL(
dp),
INTENT(in) :: r, eps, omega
1889 REAL(
dp),
INTENT(out) :: fn, df
1894 fn = erfc(qr) - r*eps
1895 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1896 END SUBROUTINE eval_transc_func
1907 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
1908 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
1909 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1911 CHARACTER(len=*),
PARAMETER :: routinen =
'diag_complex'
1913 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1914 INTEGER :: handle, info, liwork, lrwork, lwork, n
1915 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1916 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1918 CALL timeset(routinen, handle)
1920 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1924 ALLOCATE (iwork(1), rwork(1), work(1))
1931 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1933 lwork = ceiling(real(work(1), kind=
dp))
1934 lrwork = ceiling(rwork(1))
1937 DEALLOCATE (iwork, rwork, work)
1938 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1939 eigenvectors(:, :) = matrix(:, :)
1942 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1944 DEALLOCATE (iwork, rwork, work)
1946 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
1948 CALL timestop(handle)
1959 REAL(
dp),
DIMENSION(:, :) :: matrix
1960 COMPLEX(dp),
DIMENSION(:, :) :: evecs
1961 COMPLEX(dp),
DIMENSION(:) :: evals
1963 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_c
1965 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
1967 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1971 ALLOCATE (matrix_c(n, n), eigenvalues(n))
1973 matrix_c(:, :) = cmplx(0.0_dp, -matrix, kind=
dp)
1975 evals = cmplx(0.0_dp, eigenvalues, kind=
dp)
1977 DEALLOCATE (matrix_c, eigenvalues)
1989 SUBROUTINE zgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1990 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1991 CHARACTER,
INTENT(IN) :: A_trans
1992 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1993 CHARACTER,
INTENT(IN) :: B_trans
1994 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: C_out
1996 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_2'
1998 INTEGER :: handle, n
2001 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2002 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2003 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2004 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
2005 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
2006 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2007 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2008 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2009 cpabort(
"Unknown transpose character for array 1 (A).")
2011 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2012 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2013 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2014 cpabort(
"Unknown transpose character for array 2 (B).")
2017 CALL timeset(routinen, handle)
2019 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, c_out, n)
2021 CALL timestop(handle)
2023 END SUBROUTINE zgemm_square_2
2034 SUBROUTINE dgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
2035 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
2036 CHARACTER,
INTENT(IN) :: A_trans
2037 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
2038 CHARACTER,
INTENT(IN) :: B_trans
2039 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: c_out
2041 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_2'
2043 INTEGER :: handle, n
2046 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2047 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2048 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2049 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
2050 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
2051 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2052 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2053 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2054 cpabort(
"Unknown transpose character for array 1 (A).")
2056 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2057 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2058 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2059 cpabort(
"Unknown transpose character for array 2 (B).")
2062 CALL timeset(routinen, handle)
2064 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, c_out, n)
2066 CALL timestop(handle)
2068 END SUBROUTINE dgemm_square_2
2081 SUBROUTINE zgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
2082 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
2083 CHARACTER,
INTENT(IN) :: A_trans
2084 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
2085 CHARACTER,
INTENT(IN) :: B_trans
2086 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: C_in
2087 CHARACTER,
INTENT(IN) :: C_trans
2088 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: D_out
2090 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_3'
2092 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
2093 INTEGER :: handle, n
2096 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2097 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2098 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2099 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
2100 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2101 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2102 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2103 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2104 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2105 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2106 cpabort(
"Unknown transpose character for array 1 (A).")
2108 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2109 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2110 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2111 cpabort(
"Unknown transpose character for array 2 (B).")
2113 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2114 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2115 c_trans ==
'C' .OR. c_trans ==
'c'))
THEN
2116 cpabort(
"Unknown transpose character for array 3 (C).")
2119 CALL timeset(routinen, handle)
2121 ALLOCATE (work(n, n), source=
z_zero)
2123 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, work, n)
2124 CALL zgemm(
'N', c_trans, n, n, n,
z_one, work, n, c_in, n,
z_zero, d_out, n)
2128 CALL timestop(handle)
2130 END SUBROUTINE zgemm_square_3
2143 SUBROUTINE dgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
2144 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
2145 CHARACTER,
INTENT(IN) :: A_trans
2146 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
2147 CHARACTER,
INTENT(IN) :: B_trans
2148 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: c_in
2149 CHARACTER,
INTENT(IN) :: C_trans
2150 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_out
2152 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_3'
2154 INTEGER :: handle, n
2155 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
2158 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2159 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2160 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2161 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
2162 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2163 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2164 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2165 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2166 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2167 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2168 cpabort(
"Unknown transpose character for array 1 (A).")
2170 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2171 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2172 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2173 cpabort(
"Unknown transpose character for array 2 (B).")
2175 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2176 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2177 c_trans ==
'C' .OR. c_trans ==
'c'))
THEN
2178 cpabort(
"Unknown transpose character for array 3 (C).")
2181 CALL timeset(routinen, handle)
2183 ALLOCATE (work(n, n), source=0.0_dp)
2185 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, work, n)
2186 CALL dgemm(
'N', c_trans, n, n, n, 1.0_dp, work, n, c_in, n, 0.0_dp, d_out, n)
2190 CALL timestop(handle)
2192 END SUBROUTINE dgemm_square_3
2203 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: a_in, b_in
2204 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
2205 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
2207 CHARACTER(len=*),
PARAMETER :: routinen =
'geeig_right'
2208 COMPLEX(KIND=dp),
PARAMETER :: cone = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2209 czero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2211 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: cevals
2212 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a, b, work
2213 INTEGER :: handle, i, icol, irow, lda, ldb, ldc, &
2214 nao, nc, ncol, nmo, nx
2215 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
2217 CALL timeset(routinen, handle)
2221 nmo =
SIZE(eigenvalues)
2222 ALLOCATE (evals(nao), cevals(nao))
2223 ALLOCATE (work(nao, nao), b(nao, nao), a(nao, nao))
2224 a(:, :) = a_in(:, :)
2225 b(:, :) = b_in(:, :)
2230 evals(:) = -evals(:)
2233 IF (evals(i) < -1.0_dp)
THEN
2244 CALL zcopy(ncol*nao, work(1, nc + 1), 1, eigenvectors(1, nc + 1), 1)
2247 DO icol = nc + 1, nao
2249 work(irow, icol) = czero
2253 evals(nc + 1:nao) = 1.0_dp
2256 cevals(:) = cmplx(1.0_dp/sqrt(evals(:)), 0.0_dp, kind=
dp)
2257 DO i = 1, min(
SIZE(work, 2),
SIZE(cevals))
2258 work(1:min(
SIZE(work, 2),
SIZE(cevals)), i) = cevals(i)*work(1:min(
SIZE(work, 2),
SIZE(cevals)), i)
2265 DO icol = nc + 1, nao
2266 a(icol, icol) = 10000*cone
2271 eigenvalues(1:nmo) = evals(1:nmo)
2276 ldc =
SIZE(eigenvectors, 1)
2277 CALL zgemm(
"N",
"N", nao, nx, nc, cone, work, &
2278 lda, b, ldb, czero, eigenvectors, ldc)
2280 DEALLOCATE (evals, cevals, work, b, a)
2282 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 impure real(dp) function, public expint(n, x, exp_mx)
computes the exponential integral En(x) = Int(exp(-x*t)/t^n,t=1..infinity) x>0, n=0,...
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...
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.