25#include "../base/base_uses.f90"
30 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mathlib'
31 REAL(KIND=
dp),
PARAMETER :: eps_geo = 1.0e-6_dp
73 MODULE PROCEDURE det_3x3_1, det_3x3_2
77 MODULE PROCEDURE invert_matrix_d, invert_matrix_z
81 MODULE PROCEDURE set_diag_scalar_d, set_diag_scalar_z
85 MODULE PROCEDURE swap_scalar, swap_vector
89 MODULE PROCEDURE unit_matrix_d, unit_matrix_z
93 MODULE PROCEDURE zgemm_square_2, zgemm_square_3, dgemm_square_2, dgemm_square_3
110 REAL(kind=
dp) :: x, a, b
114 REAL(kind=
dp) :: u, u2, u3
117 IF (x < a .OR. x > b)
THEN
138 fx = 1._dp - 10._dp*u3 + 15._dp*u2*u2 - 6._dp*u2*u3
141 fx = -30._dp*u2 + 60._dp*u*u2 - 30._dp*u2*u2
145 fx = -60._dp*u + 180._dp*u2 - 120._dp*u*u2
148 cpabort(
'order not defined')
163 CHARACTER(LEN=32) :: buffer
171 IF (index(buffer,
"N") /= 0 .OR. index(buffer,
"n") /= 0)
abnormal_value = .true.
185 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
186 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: a, b
187 REAL(kind=
dp) :: angle_ab
189 REAL(kind=
dp) :: length_of_a, length_of_b
190 REAL(kind=
dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
192 length_of_a = norm2(a)
193 length_of_b = norm2(b)
195 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
196 a_norm(:) = a(:)/length_of_a
197 b_norm(:) = b(:)/length_of_b
198 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
216 INTEGER,
INTENT(IN) :: n, k
217 REAL(kind=
dp) :: n_over_k
219 IF ((k >= 0) .AND. (k <= n))
THEN
240 REAL(kind=
dp),
INTENT(IN) :: z
241 INTEGER,
INTENT(IN) :: k
242 REAL(kind=
dp) :: z_over_k
249 z_over_k = z_over_k*(z - i + 1)/real(i,
dp)
265 INTEGER,
INTENT(IN) :: n
266 INTEGER,
DIMENSION(:),
INTENT(IN) :: k
270 REAL(kind=
dp) :: denom
272 IF (all(k >= 0) .AND. sum(k) == n)
THEN
275 denom = denom*
fac(k(i))
296 REAL(kind=
dp),
INTENT(IN) :: phi
297 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
298 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: rotmat
300 REAL(kind=
dp) :: cosp, cost, length_of_a, sinp
301 REAL(kind=
dp),
DIMENSION(3) :: d
303 length_of_a = sqrt(a(1)*a(1) + a(2)*a(2) + a(3)*a(3))
305 IF (length_of_a > eps_geo)
THEN
307 d(:) = a(:)/length_of_a
313 rotmat(1, 1) = d(1)*d(1)*cost + cosp
314 rotmat(1, 2) = d(1)*d(2)*cost - d(3)*sinp
315 rotmat(1, 3) = d(1)*d(3)*cost + d(2)*sinp
316 rotmat(2, 1) = d(2)*d(1)*cost + d(3)*sinp
317 rotmat(2, 2) = d(2)*d(2)*cost + cosp
318 rotmat(2, 3) = d(2)*d(3)*cost - d(1)*sinp
319 rotmat(3, 1) = d(3)*d(1)*cost - d(2)*sinp
320 rotmat(3, 2) = d(3)*d(2)*cost + d(1)*sinp
321 rotmat(3, 3) = d(3)*d(3)*cost + cosp
336 PURE FUNCTION det_3x3_1(a)
RESULT(det_a)
337 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
338 REAL(kind=
dp) :: det_a
340 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
341 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
342 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
344 END FUNCTION det_3x3_1
356 PURE FUNCTION det_3x3_2(a1, a2, a3)
RESULT(det_a)
357 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3
358 REAL(kind=
dp) :: det_a
360 det_a = a1(1)*(a2(2)*a3(3) - a3(2)*a2(3)) + &
361 a2(1)*(a3(2)*a1(3) - a1(2)*a3(3)) + &
362 a3(1)*(a1(2)*a2(3) - a2(2)*a1(3))
364 END FUNCTION det_3x3_2
383 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
384 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigval
385 LOGICAL,
INTENT(IN),
OPTIONAL :: dac
387 CHARACTER(len=*),
PARAMETER :: routinen =
'diamat_all'
389 INTEGER :: handle, info, liwork, lwork, n, nb
390 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
391 INTEGER,
EXTERNAL :: ilaenv
392 LOGICAL :: divide_and_conquer
393 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
395 EXTERNAL dsyev, dsyevd
397 CALL timeset(routinen, handle)
403 IF (
SIZE(a, 2) /= n)
THEN
404 cpabort(
"Check the size of matrix a (parameter #1)")
408 IF (
SIZE(eigval) /= n)
THEN
409 cpabort(
"The dimension of vector eigval is too small")
414 IF (
PRESENT(dac))
THEN
415 divide_and_conquer = dac
417 divide_and_conquer = .false.
422 IF (divide_and_conquer)
THEN
423 lwork = 2*n**2 + 6*n + 1
426 nb = ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1)
432 ALLOCATE (work(lwork))
433 IF (divide_and_conquer)
THEN
434 ALLOCATE (iwork(liwork))
440 IF (divide_and_conquer)
THEN
441 CALL dsyevd(
"V",
"U", n, a, n, eigval, work, lwork, iwork, liwork, info)
443 CALL dsyev(
"V",
"U", n, a, n, eigval, work, lwork, info)
447 IF (divide_and_conquer)
THEN
448 cpabort(
"The matrix diagonalization with dsyevd failed")
450 cpabort(
"The matrix diagonalization with dsyev failed")
457 IF (divide_and_conquer)
THEN
461 CALL timestop(handle)
478 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: ab, bc, cd
479 REAL(kind=
dp) :: dihedral_angle_abcd
481 REAL(kind=
dp) :: det_abcd
482 REAL(kind=
dp),
DIMENSION(3) :: abc, bcd
489 det_abcd =
det_3x3(abc, bcd, -bc)
490 dihedral_angle_abcd = sign(1.0_dp, det_abcd)*
angle(abc, bcd)
503 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
505 DIMENSION(MIN(SIZE(a, 1), SIZE(a, 2))) :: a_diag
509 n = min(
SIZE(a, 1),
SIZE(a, 2))
526 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
527 REAL(kind=
dp),
DIMENSION(3, 3) :: a_inv
529 REAL(kind=
dp) :: det_a
533 a_inv(1, 1) = (a(2, 2)*a(3, 3) - a(3, 2)*a(2, 3))*det_a
534 a_inv(2, 1) = (a(2, 3)*a(3, 1) - a(3, 3)*a(2, 1))*det_a
535 a_inv(3, 1) = (a(2, 1)*a(3, 2) - a(3, 1)*a(2, 2))*det_a
537 a_inv(1, 2) = (a(1, 3)*a(3, 2) - a(3, 3)*a(1, 2))*det_a
538 a_inv(2, 2) = (a(1, 1)*a(3, 3) - a(3, 1)*a(1, 3))*det_a
539 a_inv(3, 2) = (a(1, 2)*a(3, 1) - a(3, 2)*a(1, 1))*det_a
541 a_inv(1, 3) = (a(1, 2)*a(2, 3) - a(2, 2)*a(1, 3))*det_a
542 a_inv(2, 3) = (a(1, 3)*a(2, 1) - a(2, 3)*a(1, 1))*det_a
543 a_inv(3, 3) = (a(1, 1)*a(2, 2) - a(2, 1)*a(1, 2))*det_a
553 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
554 INTEGER,
INTENT(OUT) :: info
556 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat'
558 INTEGER :: handle, lwork, n
559 INTEGER,
ALLOCATABLE :: ipiv(:)
560 REAL(kind=
dp),
ALLOCATABLE :: work(:)
562 CALL timeset(routinen, handle)
567 ALLOCATE (work(lwork))
571 CALL dgetrf(n, n, a, n, ipiv, info)
573 CALL dgetri(n, a, n, ipiv, work, lwork, info)
575 DEALLOCATE (ipiv, work)
577 CALL timestop(handle)
590 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
591 LOGICAL,
INTENT(IN),
OPTIONAL :: potrf
592 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: uplo
594 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat_symm'
596 CHARACTER(LEN=1) :: myuplo
597 INTEGER :: handle, info, n
600 CALL timeset(routinen, handle)
603 IF (
PRESENT(potrf)) do_potrf = potrf
606 IF (
PRESENT(uplo)) myuplo = uplo
613 CALL dpotrf(myuplo, n, a, n, info)
614 IF (info /= 0) cpabort(
"DPOTRF failed")
618 CALL dpotri(myuplo, n, a, n, info)
619 IF (info /= 0) cpabort(
"Matrix inversion failed")
622 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
628 CALL timestop(handle)
654 SUBROUTINE invert_matrix_d(a, a_inverse, eval_error, option, improve)
655 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
656 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
657 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
658 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
659 LOGICAL,
INTENT(IN),
OPTIONAL :: improve
661 CHARACTER(LEN=1) :: norm, trans
662 CHARACTER(LEN=default_string_length) :: message
663 INTEGER :: info, iter, n
664 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv, iwork
665 LOGICAL :: do_improve
666 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
667 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, work
668 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
669 REAL(KIND=
dp),
EXTERNAL :: dlange
671 EXTERNAL dgecon, dgerfs, dgetrf, dgetrs
674 IF (
PRESENT(option))
THEN
680 IF (
PRESENT(improve))
THEN
691 cpabort(
"Matrix to be inverted of zero size")
694 IF (n /=
SIZE(a, 2))
THEN
695 cpabort(
"Check the array bounds of parameter #1")
698 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
699 (n /=
SIZE(a_inverse, 2)))
THEN
700 cpabort(
"Check the array bounds of parameter #2")
704 ALLOCATE (a_lu(n, n))
712 a_lu(1:n, 1:n) = a(1:n, 1:n)
715 CALL dgetrf(n, n, a_lu, n, ipiv, info)
718 cpabort(
"The LU factorization in dgetrf failed")
723 IF (trans ==
"N")
THEN
729 a_norm = dlange(norm, n, n, a, n, work)
733 CALL dgecon(norm, n, a_lu, n, a_norm, r_cond, work, iwork, info)
736 cpabort(
"The computation of the condition number in dgecon failed")
739 IF (r_cond < epsilon(0.0_dp))
THEN
740 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
741 CALL cp_abort(__location__, &
742 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
743 "working precision)")
750 CALL dgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
753 cpabort(
"Solving the system of linear equations in dgetrs failed")
764 CALL dgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
768 cpabort(
"Improving the computed solution in dgerfs failed")
771 old_eval_error = eval_error
772 eval_error = maxval(ferr)
774 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
788 END SUBROUTINE invert_matrix_d
810 SUBROUTINE invert_matrix_z(a, a_inverse, eval_error, option)
811 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: a
812 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
813 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
814 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
816 CHARACTER(LEN=1) :: norm, trans
817 CHARACTER(LEN=default_string_length) :: message
818 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: work
819 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
820 INTEGER :: info, iter, n
821 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
822 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
823 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, rwork
824 REAL(KIND=
dp),
EXTERNAL :: zlange
826 EXTERNAL zgecon, zgerfs, zgetrf, zgetrs
829 IF (
PRESENT(option))
THEN
840 cpabort(
"Matrix to be inverted of zero size")
843 IF (n /=
SIZE(a, 2))
THEN
844 cpabort(
"Check the array bounds of parameter #1")
847 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
848 (n /=
SIZE(a_inverse, 2)))
THEN
849 cpabort(
"Check the array bounds of parameter #2")
853 ALLOCATE (a_lu(n, n))
858 ALLOCATE (rwork(2*n))
861 a_lu(1:n, 1:n) = a(1:n, 1:n)
864 CALL zgetrf(n, n, a_lu, n, ipiv, info)
867 cpabort(
"The LU factorization in dgetrf failed")
872 IF (trans ==
"N")
THEN
878 a_norm = zlange(norm, n, n, a, n, work)
882 CALL zgecon(norm, n, a_lu, n, a_norm, r_cond, work, rwork, info)
885 cpabort(
"The computation of the condition number in dgecon failed")
888 IF (r_cond < epsilon(0.0_dp))
THEN
889 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
890 CALL cp_abort(__location__, &
891 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
892 "working precision)")
899 CALL zgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
902 cpabort(
"Solving the system of linear equations in dgetrs failed")
912 CALL zgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
916 cpabort(
"Improving the computed solution in dgerfs failed")
919 old_eval_error = eval_error
920 eval_error = maxval(ferr)
922 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
935 END SUBROUTINE invert_matrix_z
948 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
949 REAL(kind=
dp),
INTENT(IN) :: rskip
950 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: determinant
951 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT), &
952 OPTIONAL,
POINTER :: sval
954 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_svd'
956 INTEGER :: handle, i, info, lwork, n
957 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
958 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: sig, work
959 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: sig_plus, temp_mat, u, vt
961 CALL timeset(routinen, handle)
964 ALLOCATE (u(n, n), vt(n, n), sig(n), sig_plus(n, n), iwork(8*n), work(1), temp_mat(n, n))
971 IF (
PRESENT(determinant)) determinant = 1.0_dp
975 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
976 lwork, iwork(1), info)
979 cpabort(
"ERROR in DGESDD: Could not retrieve work array sizes")
983 ALLOCATE (work(lwork))
986 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
987 lwork, iwork(1), info)
990 cpabort(
"SVD failed")
993 IF (
PRESENT(sval))
THEN
994 cpassert(.NOT.
ASSOCIATED(sval))
1001 IF (sig(i) > rskip*maxval(sig))
THEN
1002 IF (
PRESENT(determinant))
THEN
1003 determinant = determinant*sig(i)
1005 sig_plus(i, i) = 1._dp/sig(i)
1007 sig_plus(i, i) = 0.0_dp
1012 CALL dgemm(
"N",
"T", n, n, n, 1._dp, sig_plus, n, u, n, 0._dp, temp_mat, n)
1013 CALL dgemm(
"T",
"N", n, n, n, 1._dp, vt, n, temp_mat, n, 0._dp, a_pinverse, n)
1015 DEALLOCATE (u, vt, sig, iwork, work, sig_plus, temp_mat)
1017 CALL timestop(handle)
1030 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
1031 REAL(kind=
dp),
INTENT(IN) :: rskip
1033 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_diag'
1035 INTEGER :: handle, i, info, lwork, n
1036 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig, work
1037 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dinv, temp_mat
1039 CALL timeset(routinen, handle)
1043 ALLOCATE (dinv(n, n), eig(n), work(1), temp_mat(n, n))
1051 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1053 cpabort(
"ERROR in DSYEV: Could not retrieve work array sizes")
1055 lwork = int(work(1))
1057 ALLOCATE (work(lwork))
1061 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1064 cpabort(
"Matrix diagonalization failed")
1069 IF (eig(i) > rskip*maxval(eig))
THEN
1070 dinv(i, i) = 1.0_dp/eig(i)
1077 CALL dgemm(
"N",
"T", n, n, n, 1._dp, dinv, n, a, n, 0._dp, temp_mat, n)
1078 CALL dgemm(
"N",
"N", n, n, n, 1._dp, a, n, temp_mat, n, 0._dp, a_pinverse, n)
1080 DEALLOCATE (eig, work, dinv, temp_mat)
1082 CALL timestop(handle)
1097 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1098 REAL(kind=
dp),
DIMENSION(3) :: a_mirror
1100 REAL(kind=
dp) :: length_of_b, scapro
1101 REAL(kind=
dp),
DIMENSION(3) :: d
1103 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1105 IF (length_of_b > eps_geo)
THEN
1107 d(:) = b(:)/length_of_b
1110 scapro = a(1)*d(1) + a(2)*d(2) + a(3)*d(3)
1112 a_mirror(:) = a(:) - 2.0_dp*scapro*d(:)
1116 a_mirror(:) = 0.0_dp
1135 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
1136 REAL(kind=
dp),
INTENT(IN) :: phi
1137 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: b
1138 REAL(kind=
dp),
DIMENSION(3) :: a_rot
1140 REAL(kind=
dp) :: length_of_b
1141 REAL(kind=
dp),
DIMENSION(3, 3) :: rotmat
1143 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1144 IF (length_of_b > eps_geo)
THEN
1150 a_rot(:) = matmul(rotmat, a)
1168 PURE SUBROUTINE set_diag_scalar_d(a, b)
1169 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1170 REAL(kind=
dp),
INTENT(IN) :: b
1174 n = min(
SIZE(a, 1),
SIZE(a, 2))
1179 END SUBROUTINE set_diag_scalar_d
1186 PURE SUBROUTINE set_diag_scalar_z(a, b)
1187 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1188 COMPLEX(KIND=dp),
INTENT(IN) :: b
1192 n = min(
SIZE(a, 1),
SIZE(a, 2))
1197 END SUBROUTINE set_diag_scalar_z
1208 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1209 CHARACTER(LEN=*),
INTENT(IN) :: option
1213 n = min(
SIZE(a, 1),
SIZE(a, 2))
1215 IF (option ==
"lower_to_upper")
THEN
1217 a(i, i + 1:n) = a(i + 1:n, i)
1219 ELSE IF (option ==
"upper_to_lower")
THEN
1221 a(i + 1:n, i) = a(i, i + 1:n)
1223 ELSE IF (option ==
"anti_lower_to_upper")
THEN
1225 a(i, i + 1:n) = -a(i + 1:n, i)
1227 ELSE IF (option ==
"anti_upper_to_lower")
THEN
1229 a(i + 1:n, i) = -a(i, i + 1:n)
1232 cpabort(
"Invalid option <"//trim(option)//
"> was specified for parameter #2")
1244 PURE SUBROUTINE unit_matrix_d(a)
1245 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1250 END SUBROUTINE unit_matrix_d
1256 PURE SUBROUTINE unit_matrix_z(a)
1257 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1259 a(:, :) = (0.0_dp, 0.0_dp)
1262 END SUBROUTINE unit_matrix_z
1274 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1275 REAL(kind=
dp),
DIMENSION(3) :: c
1277 c(1) = a(2)*b(3) - a(3)*b(2)
1278 c(2) = a(3)*b(1) - a(1)*b(3)
1279 c(3) = a(1)*b(2) - a(2)*b(1)
1291 INTEGER,
INTENT(IN) :: a, b
1294 INTEGER :: aa, ab, l, rem, s
1326 INTEGER,
INTENT(IN) :: a, b
1336 lcm = abs((a/tmp)*b)
1350 INTEGER,
PARAMETER :: maxit = 100
1351 REAL(
dp),
PARAMETER :: eps = epsilon(0.0_dp), &
1352 fpmin = tiny(0.0_dp)
1355 REAL(
dp) :: fact, prev, sum1, term
1357 IF (x <= 0._dp)
THEN
1358 cpabort(
"Invalid argument")
1363 ELSE IF (x <= -log(eps))
THEN
1367 fact = fact*x/real(k,
dp)
1368 term = fact/real(k,
dp)
1370 IF (term < eps*sum1)
EXIT
1372 ei = sum1 + log(x) +
euler
1378 term = term*real(k,
dp)/x
1379 IF (term < eps)
EXIT
1380 IF (term < prev)
THEN
1387 ei = exp(x)*(1._dp + sum1)/x
1404 REAL(
dp),
INTENT(IN) :: xx
1407 REAL(
dp),
PARAMETER :: dx0 = 1.461632144968362341262659542325721325e0_dp, p1(7) = [ &
1408 .895385022981970e-02_dp, .477762828042627e+01_dp, .142441585084029e+03_dp, &
1409 .118645200713425e+04_dp, .363351846806499e+04_dp, .413810161269013e+04_dp, &
1410 .130560269827897e+04_dp], p2(4) = [-.212940445131011e+01_dp, -.701677227766759e+01_dp, &
1411 -.448616543918019e+01_dp, -.648157123766197e+00_dp], piov4 = .785398163397448e0_dp, q1(6) &
1412 = [.448452573429826e+02_dp, .520752771467162e+03_dp, .221000799247830e+04_dp, &
1413 .364127349079381e+04_dp, .190831076596300e+04_dp, .691091682714533e-05_dp]
1414 REAL(
dp),
PARAMETER :: q2(4) = [.322703493791143e+02_dp, .892920700481861e+02_dp, &
1415 .546117738103215e+02_dp, .777788548522962e+01_dp]
1417 INTEGER :: i, m, n, nq
1418 REAL(
dp) :: aug, den, sgn, upper, w, x, xmax1, xmx0, &
1428 xmax1 = min(real(huge(0), kind=
dp), 1.0e0_dp/epsilon(1.0e0_dp))
1433 IF (x < 0.5e0_dp)
THEN
1435 IF (abs(x) <= xsmall)
THEN
1436 IF (x == 0.0e0_dp)
THEN
1448 IF (w <= 0.0e0_dp)
THEN
1452 IF (w >= xmax1)
THEN
1459 nq = int(w*4.0e0_dp)
1460 w = 4.0e0_dp*(w - nq*.25e0_dp)
1463 IF ((n + n) /= nq) w = 1.0e0_dp - w
1466 IF ((m + m) /= n) sgn = -sgn
1473 aug = sgn*((sin(z)/cos(z))*4.0e0_dp)
1475 IF (z == 0.0e0_dp)
THEN
1480 aug = sgn*((cos(z)/sin(z))*4.0e0_dp)
1486 IF (x <= 3.0e0_dp)
THEN
1492 den = (den + q1(i))*x
1493 upper = (upper + p1(i + 1))*x
1496 den = (upper + p1(7))/(den + q1(6))
1498 fn_val = den*xmx0 + aug
1509 den = (den + q2(i))*w
1510 upper = (upper + p2(i + 1))*w
1513 aug = upper/(den + q2(4)) - 0.5e0_dp/x + aug
1516 fn_val = aug + log(x)
1532 ELEMENTAL IMPURE FUNCTION expint(n, x, exp_mx)
1533 INTEGER,
INTENT(IN) :: n
1534 REAL(
dp),
INTENT(IN) :: x
1535 REAL(
dp),
INTENT(IN),
OPTIONAL :: exp_mx
1538 INTEGER,
PARAMETER :: maxit = 100
1539 REAL(
dp),
PARAMETER :: cf_rescale_inv = 1.0e-100_dp, cf_rescale_max = 1.0e100_dp, &
1540 eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp
1542 INTEGER :: i, ii, nm1
1543 REAL(
dp) :: a, a0, a1, a2, b, b0, b1, b2, del, fact, &
1548 IF (n < 0 .OR. x < 0.0_dp .OR. (x == 0.0_dp .AND. (n == 0 .OR. n == 1)))
THEN
1549 cpabort(
"Invalid argument")
1550 ELSE IF (n == 0)
THEN
1551 IF (
PRESENT(exp_mx))
THEN
1556 ELSE IF (x == 0.0_dp)
THEN
1558 ELSE IF (x > 750.0_dp)
THEN
1560 ELSE IF (x > 1.0_dp)
THEN
1561 IF (
PRESENT(exp_mx))
THEN
1577 IF (abs(b2) > cf_rescale_max)
THEN
1578 a2 = a2*cf_rescale_inv
1579 b2 = b2*cf_rescale_inv
1580 a1 = a1*cf_rescale_inv
1581 b1 = b1*cf_rescale_inv
1583 IF (abs(a2*b1 - a1*b2) < eps*abs(a2*b1) .OR. i == maxit)
THEN
1584 IF (abs(a2*b1 - a1*b2) >= eps*abs(a2*b1))
THEN
1585 cpabort(
"continued fraction failed in expint")
1587 expint = (a2/b2)*my_exp_mx
1605 del = -fact/(i - nm1)
1609 psi = psi + 1.0_dp/ii
1611 del = fact*(-log(x) + psi)
1614 IF (abs(del) < abs(
expint)*eps)
RETURN
1616 cpabort(
"series failed in expint")
1632 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1633 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1634 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1641 CALL diag(n, a, d, v)
1644 CALL eigsrt(n, d, v)
1660 INTEGER,
INTENT(IN) :: n
1661 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1662 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1663 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1665 CHARACTER(len=*),
PARAMETER :: routinen =
'diag'
1666 INTEGER,
PARAMETER :: maxit = 100
1667 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1669 CHARACTER(LEN=default_string_length) :: max_iter
1670 INTEGER :: handle, i, ip, iq
1671 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1672 t, tau, theta, tresh
1673 REAL(kind=
dp),
DIMENSION(n) :: b, z
1675 CALL timeset(routinen, handle)
1679 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1688 d_min = max(d_eps, minval(abs(b)))
1689 IF (a_max < a_eps*d_min)
THEN
1690 CALL timestop(handle)
1693 tresh = merge(a_max, 0.0_dp, (i < 4))
1700 g = 100.0_dp*abs(apq)
1701 IF (tresh < abs(apq))
THEN
1703 IF ((abs(h) + g) /= abs(h))
THEN
1704 theta = 0.5_dp*h/apq
1705 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1706 IF (theta < 0.0_dp) t = -t
1710 c = 1.0_dp/sqrt(1.0_dp + t**2)
1712 tau = s/(1.0_dp + c)
1719 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1720 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1721 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1722 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1723 ELSE IF ((4 < i) .AND. &
1724 ((abs(dip) + g) == abs(dip)) .AND. &
1725 ((abs(diq) + g) == abs(diq)))
THEN
1733 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1736 WRITE (max_iter, *) maxit
1737 CALL cp_warn(__location__, &
1738 "Jacobi matrix diagonalization does not converge after "// &
1739 trim(adjustl(max_iter))//
" iterations; stop here anyway")
1741 CALL timestop(handle)
1755 PURE SUBROUTINE jrotate(a, b, ss, tt)
1756 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1757 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1759 REAL(kind=
dp) :: u, v
1765 b = b*(u + ss*v) + a*v
1767 END SUBROUTINE jrotate
1779 SUBROUTINE eigsrt(n, d, v)
1780 INTEGER,
INTENT(IN) :: n
1781 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1782 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1787 j = sum(minloc(d(i:n))) + i - 1
1789 CALL swap(d(i), d(j))
1790 CALL swap(v(:, i), v(:, j))
1794 END SUBROUTINE eigsrt
1804 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1805 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1813 END SUBROUTINE swap_scalar
1823 SUBROUTINE swap_vector(a, b)
1824 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1831 IF (n /=
SIZE(b))
THEN
1832 cpabort(
"Check the array bounds of the parameters")
1841 END SUBROUTINE swap_vector
1854 REAL(
dp),
INTENT(in) :: eps, omg
1855 REAL(
dp),
INTENT(out) :: r_cutoff
1857 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1859 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1860 REAL(
dp) :: r0, f0, fprime0, delta_r
1861 INTEGER :: iter, handle
1862 INTEGER,
PARAMETER :: itermax = 1000
1864 CALL timeset(routinen, handle)
1867 r0 = sqrt(-log(eps*omg*10**2))/omg
1868 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1870 DO iter = 1, itermax
1871 delta_r = f0/fprime0
1873 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1874 IF (abs(delta_r) < abstol .OR. abs(f0) < soltol)
EXIT
1876 cpassert(iter <= itermax)
1879 CALL timestop(handle)
1889 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1890 REAL(
dp),
INTENT(in) :: r, eps, omega
1891 REAL(
dp),
INTENT(out) :: fn, df
1896 fn = erfc(qr) - r*eps
1897 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1898 END SUBROUTINE eval_transc_func
1909 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
1910 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
1911 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1913 CHARACTER(len=*),
PARAMETER :: routinen =
'diag_complex'
1915 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1916 INTEGER :: handle, info, liwork, lrwork, lwork, n
1917 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1918 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1920 CALL timeset(routinen, handle)
1922 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1926 ALLOCATE (iwork(1), rwork(1), work(1))
1933 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1935 lwork = ceiling(real(work(1), kind=
dp))
1936 lrwork = ceiling(rwork(1))
1939 DEALLOCATE (iwork, rwork, work)
1940 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1941 eigenvectors(:, :) = matrix(:, :)
1944 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1946 DEALLOCATE (iwork, rwork, work)
1948 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
1950 CALL timestop(handle)
1961 REAL(
dp),
DIMENSION(:, :) :: matrix
1962 COMPLEX(dp),
DIMENSION(:, :) :: evecs
1963 COMPLEX(dp),
DIMENSION(:) :: evals
1965 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_c
1967 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
1969 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1973 ALLOCATE (matrix_c(n, n), eigenvalues(n))
1975 matrix_c(:, :) = cmplx(0.0_dp, -matrix, kind=
dp)
1977 evals = cmplx(0.0_dp, eigenvalues, kind=
dp)
1979 DEALLOCATE (matrix_c, eigenvalues)
1991 SUBROUTINE zgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1992 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1993 CHARACTER,
INTENT(IN) :: A_trans
1994 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1995 CHARACTER,
INTENT(IN) :: B_trans
1996 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: C_out
1998 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_2'
2000 INTEGER :: handle, n
2003 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2004 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2005 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2006 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
2007 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
2008 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2009 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2010 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2011 cpabort(
"Unknown transpose character for array 1 (A).")
2013 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2014 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2015 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2016 cpabort(
"Unknown transpose character for array 2 (B).")
2019 CALL timeset(routinen, handle)
2021 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, c_out, n)
2023 CALL timestop(handle)
2025 END SUBROUTINE zgemm_square_2
2036 SUBROUTINE dgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
2037 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
2038 CHARACTER,
INTENT(IN) :: A_trans
2039 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
2040 CHARACTER,
INTENT(IN) :: B_trans
2041 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: c_out
2043 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_2'
2045 INTEGER :: handle, n
2048 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2049 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2050 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2051 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
2052 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
2053 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2054 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2055 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2056 cpabort(
"Unknown transpose character for array 1 (A).")
2058 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2059 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2060 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2061 cpabort(
"Unknown transpose character for array 2 (B).")
2064 CALL timeset(routinen, handle)
2066 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, c_out, n)
2068 CALL timestop(handle)
2070 END SUBROUTINE dgemm_square_2
2083 SUBROUTINE zgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
2084 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
2085 CHARACTER,
INTENT(IN) :: A_trans
2086 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
2087 CHARACTER,
INTENT(IN) :: B_trans
2088 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: C_in
2089 CHARACTER,
INTENT(IN) :: C_trans
2090 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: D_out
2092 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_3'
2094 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
2095 INTEGER :: handle, n
2098 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2099 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2100 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2101 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
2102 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2103 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2104 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2105 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2106 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2107 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2108 cpabort(
"Unknown transpose character for array 1 (A).")
2110 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2111 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2112 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2113 cpabort(
"Unknown transpose character for array 2 (B).")
2115 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2116 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2117 c_trans ==
'C' .OR. c_trans ==
'c'))
THEN
2118 cpabort(
"Unknown transpose character for array 3 (C).")
2121 CALL timeset(routinen, handle)
2123 ALLOCATE (work(n, n), source=
z_zero)
2125 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, work, n)
2126 CALL zgemm(
'N', c_trans, n, n, n,
z_one, work, n, c_in, n,
z_zero, d_out, n)
2130 CALL timestop(handle)
2132 END SUBROUTINE zgemm_square_3
2145 SUBROUTINE dgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
2146 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
2147 CHARACTER,
INTENT(IN) :: A_trans
2148 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
2149 CHARACTER,
INTENT(IN) :: B_trans
2150 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: c_in
2151 CHARACTER,
INTENT(IN) :: C_trans
2152 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_out
2154 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_3'
2156 INTEGER :: handle, n
2157 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
2160 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
2161 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
2162 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
2163 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
2164 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2165 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2166 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2167 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2168 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2169 a_trans ==
'C' .OR. a_trans ==
'c'))
THEN
2170 cpabort(
"Unknown transpose character for array 1 (A).")
2172 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2173 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2174 b_trans ==
'C' .OR. b_trans ==
'c'))
THEN
2175 cpabort(
"Unknown transpose character for array 2 (B).")
2177 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2178 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2179 c_trans ==
'C' .OR. c_trans ==
'c'))
THEN
2180 cpabort(
"Unknown transpose character for array 3 (C).")
2183 CALL timeset(routinen, handle)
2185 ALLOCATE (work(n, n), source=0.0_dp)
2187 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, work, n)
2188 CALL dgemm(
'N', c_trans, n, n, n, 1.0_dp, work, n, c_in, n, 0.0_dp, d_out, n)
2192 CALL timestop(handle)
2194 END SUBROUTINE dgemm_square_3
2205 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: a_in, b_in
2206 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
2207 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
2209 CHARACTER(len=*),
PARAMETER :: routinen =
'geeig_right'
2210 COMPLEX(KIND=dp),
PARAMETER :: cone = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2211 czero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2213 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: cevals
2214 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a, b, work
2215 INTEGER :: handle, i, icol, irow, lda, ldb, ldc, &
2216 nao, nc, ncol, nmo, nx
2217 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
2219 CALL timeset(routinen, handle)
2223 nmo =
SIZE(eigenvalues)
2224 ALLOCATE (evals(nao), cevals(nao))
2225 ALLOCATE (work(nao, nao), b(nao, nao), a(nao, nao))
2226 a(:, :) = a_in(:, :)
2227 b(:, :) = b_in(:, :)
2232 evals(:) = -evals(:)
2235 IF (evals(i) < -1.0_dp)
THEN
2246 CALL zcopy(ncol*nao, work(1, nc + 1), 1, eigenvectors(1, nc + 1), 1)
2249 DO icol = nc + 1, nao
2251 work(irow, icol) = czero
2255 evals(nc + 1:nao) = 1.0_dp
2258 cevals(:) = cmplx(1.0_dp/sqrt(evals(:)), 0.0_dp, kind=
dp)
2259 DO i = 1, min(
SIZE(work, 2),
SIZE(cevals))
2260 work(1:min(
SIZE(work, 2),
SIZE(cevals)), i) = cevals(i)*work(1:min(
SIZE(work, 2),
SIZE(cevals)), i)
2267 DO icol = nc + 1, nao
2268 a(icol, icol) = 10000*cone
2273 eigenvalues(1:nmo) = evals(1:nmo)
2278 ldc =
SIZE(eigenvectors, 1)
2279 CALL zgemm(
"N",
"N", nao, nx, nc, cone, work, &
2280 lda, b, ldb, czero, eigenvectors, ldc)
2282 DEALLOCATE (evals, cevals, work, b, a)
2284 CALL timestop(handle)
2295 INTEGER,
INTENT(IN) :: n
2296 REAL(kind=
dp),
DIMENSION(n),
INTENT(OUT) :: nodes, weights
2298 INTEGER,
PARAMETER :: max_iter = 100
2300 INTEGER :: i, iter, j
2301 REAL(kind=
dp) :: derivative, dz, p0, p1, p2, z
2304 z = cos(
pi*(real(i,
dp) - 0.25_dp)/(real(n,
dp) + 0.5_dp))
2305 DO iter = 1, max_iter
2311 p0 = (real(2*j - 1,
dp)*z*p1 - real(j - 1,
dp)*p2)/real(j,
dp)
2313 derivative = real(n,
dp)*(z*p0 - p1)/(z*z - 1.0_dp)
2316 IF (abs(dz) <= epsilon(1.0_dp))
EXIT
2318 IF (iter > max_iter) cpabort(
"Gauss-Legendre roots did not converge")
2320 nodes(n + 1 - i) = z
2321 weights(i) = 2.0_dp/((1.0_dp - z*z)*derivative**2)
2322 weights(n + 1 - i) = weights(i)
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
real(kind=dp), parameter, public pi
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...
subroutine, public gauss_legendre(n, nodes, weights)
Gauss-Legendre nodes and weights on [-1,1], with nodes in ascending order. The Legendre roots are ref...
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.