22#include "../base/base_uses.f90"
28 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mathlib'
29 REAL(KIND=
dp),
PARAMETER :: eps_geo = 1.0e-6_dp
67 MODULE PROCEDURE det_3x3_1, det_3x3_2
71 MODULE PROCEDURE invert_matrix_d, invert_matrix_z
75 MODULE PROCEDURE set_diag_scalar_d, set_diag_scalar_z
79 MODULE PROCEDURE swap_scalar, swap_vector
83 MODULE PROCEDURE unit_matrix_d, unit_matrix_z
99 FUNCTION pswitch(x, a, b, order)
RESULT(fx)
100 REAL(kind=
dp) :: x, a, b
104 REAL(kind=
dp) :: u, u2, u3
107 IF (x < a .OR. x > b)
THEN
128 fx = 1._dp - 10._dp*u3 + 15._dp*u2*u2 - 6._dp*u2*u3
131 fx = -30._dp*u2 + 60._dp*u*u2 - 30._dp*u2*u2
135 fx = -60._dp*u + 180._dp*u2 - 120._dp*u*u2
138 cpabort(
'order not defined')
153 CHARACTER(LEN=32) :: buffer
161 IF (index(buffer,
"N") .NE. 0 .OR. index(buffer,
"n") .NE. 0)
abnormal_value = .true.
175 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
176 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: a, b
177 REAL(kind=
dp) :: angle_ab
179 REAL(kind=
dp) :: length_of_a, length_of_b
180 REAL(kind=
dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
182 length_of_a = sqrt(dot_product(a, a))
183 length_of_b = sqrt(dot_product(b, b))
185 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
186 a_norm(:) = a(:)/length_of_a
187 b_norm(:) = b(:)/length_of_b
188 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
206 INTEGER,
INTENT(IN) :: n, k
207 REAL(kind=
dp) :: n_over_k
209 IF ((k >= 0) .AND. (k <= n))
THEN
230 REAL(kind=
dp),
INTENT(IN) :: z
231 INTEGER,
INTENT(IN) :: k
232 REAL(kind=
dp) :: z_over_k
239 z_over_k = z_over_k*(z - i + 1)/real(i,
dp)
255 INTEGER,
INTENT(IN) :: n
256 INTEGER,
DIMENSION(:),
INTENT(IN) :: k
260 REAL(kind=
dp) :: denom
262 IF (all(k >= 0) .AND. sum(k) == n)
THEN
265 denom = denom*
fac(k(i))
286 REAL(kind=
dp),
INTENT(IN) :: phi
287 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
288 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: rotmat
290 REAL(kind=
dp) :: cosp, cost, length_of_a, sinp
291 REAL(kind=
dp),
DIMENSION(3) :: d
293 length_of_a = sqrt(a(1)*a(1) + a(2)*a(2) + a(3)*a(3))
295 IF (length_of_a > eps_geo)
THEN
297 d(:) = a(:)/length_of_a
303 rotmat(1, 1) = d(1)*d(1)*cost + cosp
304 rotmat(1, 2) = d(1)*d(2)*cost - d(3)*sinp
305 rotmat(1, 3) = d(1)*d(3)*cost + d(2)*sinp
306 rotmat(2, 1) = d(2)*d(1)*cost + d(3)*sinp
307 rotmat(2, 2) = d(2)*d(2)*cost + cosp
308 rotmat(2, 3) = d(2)*d(3)*cost - d(1)*sinp
309 rotmat(3, 1) = d(3)*d(1)*cost - d(2)*sinp
310 rotmat(3, 2) = d(3)*d(2)*cost + d(1)*sinp
311 rotmat(3, 3) = d(3)*d(3)*cost + cosp
326 PURE FUNCTION det_3x3_1(a)
RESULT(det_a)
327 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
328 REAL(kind=
dp) :: det_a
330 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
331 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
332 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
334 END FUNCTION det_3x3_1
346 PURE FUNCTION det_3x3_2(a1, a2, a3)
RESULT(det_a)
347 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3
348 REAL(kind=
dp) :: det_a
350 det_a = a1(1)*(a2(2)*a3(3) - a3(2)*a2(3)) + &
351 a2(1)*(a3(2)*a1(3) - a1(2)*a3(3)) + &
352 a3(1)*(a1(2)*a2(3) - a2(2)*a1(3))
354 END FUNCTION det_3x3_2
373 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
374 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigval
375 LOGICAL,
INTENT(IN),
OPTIONAL :: dac
377 CHARACTER(len=*),
PARAMETER :: routinen =
'diamat_all'
379 INTEGER :: handle, info, liwork, lwork, n, nb
380 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
381 INTEGER,
EXTERNAL :: ilaenv
382 LOGICAL :: divide_and_conquer
383 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
385 EXTERNAL dsyev, dsyevd
387 CALL timeset(routinen, handle)
393 IF (
SIZE(a, 2) /= n)
THEN
394 cpabort(
"Check the size of matrix a (parameter #1)")
398 IF (
SIZE(eigval) /= n)
THEN
399 cpabort(
"The dimension of vector eigval is too small")
404 IF (
PRESENT(dac))
THEN
405 divide_and_conquer = dac
407 divide_and_conquer = .false.
412 IF (divide_and_conquer)
THEN
413 lwork = 2*n**2 + 6*n + 1
416 nb = ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1)
422 ALLOCATE (work(lwork))
423 IF (divide_and_conquer)
THEN
424 ALLOCATE (iwork(liwork))
430 IF (divide_and_conquer)
THEN
431 CALL dsyevd(
"V",
"U", n, a, n, eigval, work, lwork, iwork, liwork, info)
433 CALL dsyev(
"V",
"U", n, a, n, eigval, work, lwork, info)
437 IF (divide_and_conquer)
THEN
438 cpabort(
"The matrix diagonalization with dsyevd failed")
440 cpabort(
"The matrix diagonalization with dsyev failed")
447 IF (divide_and_conquer)
THEN
451 CALL timestop(handle)
468 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: ab, bc, cd
469 REAL(kind=
dp) :: dihedral_angle_abcd
471 REAL(kind=
dp) :: det_abcd
472 REAL(kind=
dp),
DIMENSION(3) :: abc, bcd
479 det_abcd =
det_3x3(abc, bcd, -bc)
480 dihedral_angle_abcd = sign(1.0_dp, det_abcd)*
angle(abc, bcd)
493 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
495 DIMENSION(MIN(SIZE(a, 1), SIZE(a, 2))) :: a_diag
499 n = min(
SIZE(a, 1),
SIZE(a, 2))
516 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
517 REAL(kind=
dp),
DIMENSION(3, 3) :: a_inv
519 REAL(kind=
dp) :: det_a
523 a_inv(1, 1) = (a(2, 2)*a(3, 3) - a(3, 2)*a(2, 3))*det_a
524 a_inv(2, 1) = (a(2, 3)*a(3, 1) - a(3, 3)*a(2, 1))*det_a
525 a_inv(3, 1) = (a(2, 1)*a(3, 2) - a(3, 1)*a(2, 2))*det_a
527 a_inv(1, 2) = (a(1, 3)*a(3, 2) - a(3, 3)*a(1, 2))*det_a
528 a_inv(2, 2) = (a(1, 1)*a(3, 3) - a(3, 1)*a(1, 3))*det_a
529 a_inv(3, 2) = (a(1, 2)*a(3, 1) - a(3, 2)*a(1, 1))*det_a
531 a_inv(1, 3) = (a(1, 2)*a(2, 3) - a(2, 2)*a(1, 3))*det_a
532 a_inv(2, 3) = (a(1, 3)*a(2, 1) - a(2, 3)*a(1, 1))*det_a
533 a_inv(3, 3) = (a(1, 1)*a(2, 2) - a(2, 1)*a(1, 2))*det_a
543 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
544 INTEGER,
INTENT(OUT) :: info
546 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat'
548 INTEGER :: handle, lwork, n
549 INTEGER,
ALLOCATABLE :: ipiv(:)
550 REAL(kind=
dp),
ALLOCATABLE :: work(:)
552 CALL timeset(routinen, handle)
557 ALLOCATE (work(lwork))
561 CALL dgetrf(n, n, a, n, ipiv, info)
563 CALL dgetri(n, a, n, ipiv, work, lwork, info)
565 DEALLOCATE (ipiv, work)
567 CALL timestop(handle)
580 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
581 LOGICAL,
INTENT(IN),
OPTIONAL :: potrf
582 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: uplo
584 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat_symm'
586 CHARACTER(LEN=1) :: myuplo
587 INTEGER :: handle, info, n
590 CALL timeset(routinen, handle)
593 IF (
PRESENT(potrf)) do_potrf = potrf
596 IF (
PRESENT(uplo)) myuplo = uplo
603 CALL dpotrf(myuplo, n, a, n, info)
604 IF (info /= 0) cpabort(
"DPOTRF failed")
608 CALL dpotri(myuplo, n, a, n, info)
609 IF (info /= 0) cpabort(
"Matrix inversion failed")
612 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
618 CALL timestop(handle)
644 SUBROUTINE invert_matrix_d(a, a_inverse, eval_error, option, improve)
645 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
646 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
647 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
648 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
649 LOGICAL,
INTENT(IN),
OPTIONAL :: improve
651 CHARACTER(LEN=1) :: norm, trans
652 CHARACTER(LEN=default_string_length) :: message
653 INTEGER :: info, iter, n
654 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv, iwork
655 LOGICAL :: do_improve
656 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
657 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, work
658 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
659 REAL(KIND=
dp),
EXTERNAL :: dlange
661 EXTERNAL dgecon, dgerfs, dgetrf, dgetrs
664 IF (
PRESENT(option))
THEN
670 IF (
PRESENT(improve))
THEN
681 cpabort(
"Matrix to be inverted of zero size")
684 IF (n /=
SIZE(a, 2))
THEN
685 cpabort(
"Check the array bounds of parameter #1")
688 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
689 (n /=
SIZE(a_inverse, 2)))
THEN
690 cpabort(
"Check the array bounds of parameter #2")
694 ALLOCATE (a_lu(n, n))
702 a_lu(1:n, 1:n) = a(1:n, 1:n)
705 CALL dgetrf(n, n, a_lu, n, ipiv, info)
708 cpabort(
"The LU factorization in dgetrf failed")
713 IF (trans ==
"N")
THEN
719 a_norm = dlange(norm, n, n, a, n, work)
723 CALL dgecon(norm, n, a_lu, n, a_norm, r_cond, work, iwork, info)
726 cpabort(
"The computation of the condition number in dgecon failed")
729 IF (r_cond < epsilon(0.0_dp))
THEN
730 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
731 CALL cp_abort(__location__, &
732 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
733 "working precision)")
740 CALL dgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
743 cpabort(
"Solving the system of linear equations in dgetrs failed")
754 CALL dgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
758 cpabort(
"Improving the computed solution in dgerfs failed")
761 old_eval_error = eval_error
762 eval_error = maxval(ferr)
764 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
778 END SUBROUTINE invert_matrix_d
800 SUBROUTINE invert_matrix_z(a, a_inverse, eval_error, option)
801 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: a
802 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
803 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
804 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
806 CHARACTER(LEN=1) :: norm, trans
807 CHARACTER(LEN=default_string_length) :: message
808 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: work
809 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
810 INTEGER :: info, iter, n
811 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
812 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
813 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, rwork
814 REAL(KIND=
dp),
EXTERNAL :: zlange
816 EXTERNAL zgecon, zgerfs, zgetrf, zgetrs
819 IF (
PRESENT(option))
THEN
830 cpabort(
"Matrix to be inverted of zero size")
833 IF (n /=
SIZE(a, 2))
THEN
834 cpabort(
"Check the array bounds of parameter #1")
837 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
838 (n /=
SIZE(a_inverse, 2)))
THEN
839 cpabort(
"Check the array bounds of parameter #2")
843 ALLOCATE (a_lu(n, n))
848 ALLOCATE (rwork(2*n))
851 a_lu(1:n, 1:n) = a(1:n, 1:n)
854 CALL zgetrf(n, n, a_lu, n, ipiv, info)
857 cpabort(
"The LU factorization in dgetrf failed")
862 IF (trans ==
"N")
THEN
868 a_norm = zlange(norm, n, n, a, n, work)
872 CALL zgecon(norm, n, a_lu, n, a_norm, r_cond, work, rwork, info)
875 cpabort(
"The computation of the condition number in dgecon failed")
878 IF (r_cond < epsilon(0.0_dp))
THEN
879 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
880 CALL cp_abort(__location__, &
881 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
882 "working precision)")
889 CALL zgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
892 cpabort(
"Solving the system of linear equations in dgetrs failed")
902 CALL zgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
906 cpabort(
"Improving the computed solution in dgerfs failed")
909 old_eval_error = eval_error
910 eval_error = maxval(ferr)
912 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
925 END SUBROUTINE invert_matrix_z
938 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
939 REAL(kind=
dp),
INTENT(IN) :: rskip
940 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: determinant
941 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT), &
942 OPTIONAL,
POINTER :: sval
944 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_svd'
946 INTEGER :: handle, i, info, lwork, n
947 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
948 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: sig, work
949 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: sig_plus, temp_mat, u, vt
951 CALL timeset(routinen, handle)
954 ALLOCATE (u(n, n), vt(n, n), sig(n), sig_plus(n, n), iwork(8*n), work(1), temp_mat(n, n))
961 IF (
PRESENT(determinant)) determinant = 1.0_dp
965 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
966 lwork, iwork(1), info)
969 cpabort(
"ERROR in DGESDD: Could not retrieve work array sizes")
973 ALLOCATE (work(lwork))
976 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
977 lwork, iwork(1), info)
980 cpabort(
"SVD failed")
983 IF (
PRESENT(sval))
THEN
984 cpassert(.NOT.
ASSOCIATED(sval))
991 IF (sig(i) > rskip*maxval(sig))
THEN
992 IF (
PRESENT(determinant)) &
993 determinant = determinant*sig(i)
994 sig_plus(i, i) = 1._dp/sig(i)
996 sig_plus(i, i) = 0.0_dp
1001 CALL dgemm(
"N",
"T", n, n, n, 1._dp, sig_plus, n, u, n, 0._dp, temp_mat, n)
1002 CALL dgemm(
"T",
"N", n, n, n, 1._dp, vt, n, temp_mat, n, 0._dp, a_pinverse, n)
1004 DEALLOCATE (u, vt, sig, iwork, work, sig_plus, temp_mat)
1006 CALL timestop(handle)
1019 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
1020 REAL(kind=
dp),
INTENT(IN) :: rskip
1022 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_diag'
1024 INTEGER :: handle, i, info, lwork, n
1025 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig, work
1026 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dinv, temp_mat
1028 CALL timeset(routinen, handle)
1032 ALLOCATE (dinv(n, n), eig(n), work(1), temp_mat(n, n))
1040 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1042 cpabort(
"ERROR in DSYEV: Could not retrieve work array sizes")
1044 lwork = int(work(1))
1046 ALLOCATE (work(lwork))
1050 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1053 cpabort(
"Matrix diagonalization failed")
1058 IF (eig(i) > rskip*maxval(eig))
THEN
1059 dinv(i, i) = 1.0_dp/eig(i)
1066 CALL dgemm(
"N",
"T", n, n, n, 1._dp, dinv, n, a, n, 0._dp, temp_mat, n)
1067 CALL dgemm(
"N",
"N", n, n, n, 1._dp, a, n, temp_mat, n, 0._dp, a_pinverse, n)
1069 DEALLOCATE (eig, work, dinv, temp_mat)
1071 CALL timestop(handle)
1086 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1087 REAL(kind=
dp),
DIMENSION(3) :: a_mirror
1089 REAL(kind=
dp) :: length_of_b, scapro
1090 REAL(kind=
dp),
DIMENSION(3) :: d
1092 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1094 IF (length_of_b > eps_geo)
THEN
1096 d(:) = b(:)/length_of_b
1099 scapro = a(1)*d(1) + a(2)*d(2) + a(3)*d(3)
1101 a_mirror(:) = a(:) - 2.0_dp*scapro*d(:)
1105 a_mirror(:) = 0.0_dp
1124 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
1125 REAL(kind=
dp),
INTENT(IN) :: phi
1126 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: b
1127 REAL(kind=
dp),
DIMENSION(3) :: a_rot
1129 REAL(kind=
dp) :: length_of_b
1130 REAL(kind=
dp),
DIMENSION(3, 3) :: rotmat
1132 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1133 IF (length_of_b > eps_geo)
THEN
1139 a_rot(:) = matmul(rotmat, a)
1157 PURE SUBROUTINE set_diag_scalar_d(a, b)
1158 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1159 REAL(kind=
dp),
INTENT(IN) :: b
1163 n = min(
SIZE(a, 1),
SIZE(a, 2))
1168 END SUBROUTINE set_diag_scalar_d
1175 PURE SUBROUTINE set_diag_scalar_z(a, b)
1176 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1177 COMPLEX(KIND=dp),
INTENT(IN) :: b
1181 n = min(
SIZE(a, 1),
SIZE(a, 2))
1186 END SUBROUTINE set_diag_scalar_z
1197 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1198 CHARACTER(LEN=*),
INTENT(IN) :: option
1202 n = min(
SIZE(a, 1),
SIZE(a, 2))
1204 IF (option ==
"lower_to_upper")
THEN
1206 a(i, i + 1:n) = a(i + 1:n, i)
1208 ELSE IF (option ==
"upper_to_lower")
THEN
1210 a(i + 1:n, i) = a(i, i + 1:n)
1212 ELSE IF (option ==
"anti_lower_to_upper")
THEN
1214 a(i, i + 1:n) = -a(i + 1:n, i)
1216 ELSE IF (option ==
"anti_upper_to_lower")
THEN
1218 a(i + 1:n, i) = -a(i, i + 1:n)
1221 cpabort(
"Invalid option <"//trim(option)//
"> was specified for parameter #2")
1233 PURE SUBROUTINE unit_matrix_d(a)
1234 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1239 END SUBROUTINE unit_matrix_d
1245 PURE SUBROUTINE unit_matrix_z(a)
1246 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1248 a(:, :) = (0.0_dp, 0.0_dp)
1251 END SUBROUTINE unit_matrix_z
1263 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1264 REAL(kind=
dp),
DIMENSION(3) :: c
1266 c(1) = a(2)*b(3) - a(3)*b(2)
1267 c(2) = a(3)*b(1) - a(1)*b(3)
1268 c(3) = a(1)*b(2) - a(2)*b(1)
1280 INTEGER,
INTENT(IN) :: a, b
1283 INTEGER :: aa, ab, l, rem, s
1315 INTEGER,
INTENT(IN) :: a, b
1325 lcm = abs((a/tmp)*b)
1339 INTEGER,
PARAMETER :: maxit = 100
1340 REAL(
dp),
PARAMETER :: eps = epsilon(0.0_dp), &
1341 fpmin = tiny(0.0_dp)
1344 REAL(
dp) :: fact, prev, sum1, term
1346 IF (x <= 0._dp)
THEN
1347 cpabort(
"Invalid argument")
1352 ELSE IF (x <= -log(eps))
THEN
1356 fact = fact*x/real(k,
dp)
1357 term = fact/real(k,
dp)
1359 IF (term < eps*sum1)
EXIT
1361 ei = sum1 + log(x) +
euler
1367 term = term*real(k,
dp)/x
1368 IF (term < eps)
EXIT
1369 IF (term < prev)
THEN
1376 ei = exp(x)*(1._dp + sum1)/x
1393 INTEGER,
INTENT(IN) :: n
1394 REAL(
dp),
INTENT(IN) :: x
1397 INTEGER,
PARAMETER :: maxit = 100
1398 REAL(
dp),
PARAMETER :: eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp, &
1399 fpmin = tiny(0.0_dp)
1401 INTEGER :: i, ii, nm1
1402 REAL(
dp) :: a, b, c, d, del, fact, h, psi
1406 IF (n .LT. 0 .OR. x .LT. 0.0_dp .OR. (x .EQ. 0.0_dp .AND. (n .EQ. 0 .OR. n .EQ. 1)))
THEN
1407 cpabort(
"Invalid argument")
1408 ELSE IF (n .EQ. 0)
THEN
1410 ELSE IF (x .EQ. 0.0_dp)
THEN
1412 ELSE IF (x .GT. 1.0_dp)
THEN
1420 d = 1.0_dp/(a*d + b)
1424 IF (abs(del - 1.0_dp) .LT. eps)
THEN
1429 cpabort(
"continued fraction failed in expint")
1431 IF (nm1 .NE. 0)
THEN
1439 IF (i .NE. nm1)
THEN
1440 del = -fact/(i - nm1)
1444 psi = psi + 1.0_dp/ii
1446 del = fact*(-log(x) + psi)
1449 IF (abs(del) .LT. abs(
expint)*eps)
RETURN
1451 cpabort(
"series failed in expint")
1468 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1469 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1470 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1477 CALL diag(n, a, d, v)
1480 CALL eigsrt(n, d, v)
1496 INTEGER,
INTENT(IN) :: n
1497 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1498 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1499 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1501 CHARACTER(len=*),
PARAMETER :: routinen =
'diag'
1502 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1504 INTEGER :: handle, i, ip, iq
1505 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1506 t, tau, theta, tresh
1507 REAL(kind=
dp),
DIMENSION(n) :: b, z
1509 CALL timeset(routinen, handle)
1513 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1523 d_min = max(d_eps, minval(abs(b)))
1524 IF (a_max < a_eps*d_min)
THEN
1525 CALL timestop(handle)
1528 tresh = merge(a_max, 0.0_dp, (i < 4))
1535 g = 100.0_dp*abs(apq)
1536 IF (tresh < abs(apq))
THEN
1538 IF ((abs(h) + g) .NE. abs(h))
THEN
1539 theta = 0.5_dp*h/apq
1540 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1541 IF (theta < 0.0_dp) t = -t
1545 c = 1.0_dp/sqrt(1.0_dp + t**2)
1547 tau = s/(1.0_dp + c)
1554 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1555 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1556 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1557 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1558 ELSE IF ((4 < i) .AND. &
1559 ((abs(dip) + g) == abs(dip)) .AND. &
1560 ((abs(diq) + g) == abs(diq)))
THEN
1568 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1571 WRITE (*,
'(/,T2,A,/)')
'Too many iterations in jacobi'
1573 CALL timestop(handle)
1587 PURE SUBROUTINE jrotate(a, b, ss, tt)
1588 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1589 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1591 REAL(kind=
dp) :: u, v
1597 b = b*(u + ss*v) + a*v
1599 END SUBROUTINE jrotate
1611 SUBROUTINE eigsrt(n, d, v)
1612 INTEGER,
INTENT(IN) :: n
1613 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1614 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1619 j = sum(minloc(d(i:n))) + i - 1
1621 CALL swap(d(i), d(j))
1622 CALL swap(v(:, i), v(:, j))
1626 END SUBROUTINE eigsrt
1636 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1637 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1645 END SUBROUTINE swap_scalar
1655 SUBROUTINE swap_vector(a, b)
1656 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1663 IF (n /=
SIZE(b))
THEN
1664 cpabort(
"Check the array bounds of the parameters")
1673 END SUBROUTINE swap_vector
1688 REAL(
dp),
INTENT(in) :: eps, omg
1689 REAL(
dp),
INTENT(out) :: r_cutoff
1691 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1693 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1694 REAL(
dp) :: r0, f0, fprime0, delta_r
1695 INTEGER :: iter, handle
1696 INTEGER,
PARAMETER :: itermax = 1000
1698 CALL timeset(routinen, handle)
1701 r0 = sqrt(-log(eps*omg*10**2))/omg
1702 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1704 DO iter = 1, itermax
1705 delta_r = f0/fprime0
1707 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1708 IF (abs(delta_r) .LT. abstol .OR. abs(f0) .LT. soltol)
EXIT
1710 cpassert(iter <= itermax)
1713 CALL timestop(handle)
1723 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1724 REAL(
dp),
INTENT(in) :: r, eps, omega
1725 REAL(
dp),
INTENT(out) :: fn, df
1730 fn = erfc(qr) - r*eps
1731 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1732 END SUBROUTINE eval_transc_func
1743 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
1744 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
1745 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1747 CHARACTER(len=*),
PARAMETER :: routinen =
'diag_complex'
1749 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1750 INTEGER :: handle, info, liwork, lrwork, lwork, n
1751 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1752 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1754 CALL timeset(routinen, handle)
1756 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1760 ALLOCATE (iwork(1), rwork(1), work(1))
1767 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1769 lwork = ceiling(real(work(1), kind=
dp))
1770 lrwork = ceiling(rwork(1))
1773 DEALLOCATE (iwork, rwork, work)
1774 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1775 eigenvectors(:, :) = matrix(:, :)
1778 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1780 DEALLOCATE (iwork, rwork, work)
1782 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
1784 CALL timestop(handle)
1795 REAL(
dp),
DIMENSION(:, :) :: matrix
1796 COMPLEX(dp),
DIMENSION(:, :) :: evecs
1797 COMPLEX(dp),
DIMENSION(:) :: evals
1799 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_c
1801 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
1803 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1807 ALLOCATE (matrix_c(n, n), eigenvalues(n))
1809 matrix_c(:, :) = cmplx(0.0_dp, -matrix, kind=
dp)
1811 evals = cmplx(0.0_dp, eigenvalues, kind=
dp)
1813 DEALLOCATE (matrix_c, eigenvalues)
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 euler
real(kind=dp), dimension(0:maxfac), parameter, public fac
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...
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...
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.