22#include "../base/base_uses.f90"
28 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mathlib'
29 REAL(KIND=
dp),
PARAMETER :: eps_geo = 1.0e-6_dp
66 MODULE PROCEDURE det_3x3_1, det_3x3_2
70 MODULE PROCEDURE invert_matrix_d, invert_matrix_z
74 MODULE PROCEDURE set_diag_scalar_d, set_diag_scalar_z
78 MODULE PROCEDURE swap_scalar, swap_vector
82 MODULE PROCEDURE unit_matrix_d, unit_matrix_z
98 FUNCTION pswitch(x, a, b, order)
RESULT(fx)
99 REAL(kind=
dp) :: x, a, b
103 REAL(kind=
dp) :: u, u2, u3
106 IF (x < a .OR. x > b)
THEN
127 fx = 1._dp - 10._dp*u3 + 15._dp*u2*u2 - 6._dp*u2*u3
130 fx = -30._dp*u2 + 60._dp*u*u2 - 30._dp*u2*u2
134 fx = -60._dp*u + 180._dp*u2 - 120._dp*u*u2
137 cpabort(
'order not defined')
152 CHARACTER(LEN=32) :: buffer
160 IF (index(buffer,
"N") .NE. 0 .OR. index(buffer,
"n") .NE. 0)
abnormal_value = .true.
174 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
175 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: a, b
176 REAL(kind=
dp) :: angle_ab
178 REAL(kind=
dp) :: length_of_a, length_of_b
179 REAL(kind=
dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
181 length_of_a = sqrt(dot_product(a, a))
182 length_of_b = sqrt(dot_product(b, b))
184 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
185 a_norm(:) = a(:)/length_of_a
186 b_norm(:) = b(:)/length_of_b
187 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
205 INTEGER,
INTENT(IN) :: n, k
206 REAL(kind=
dp) :: n_over_k
208 IF ((k >= 0) .AND. (k <= n))
THEN
229 REAL(kind=
dp),
INTENT(IN) :: z
230 INTEGER,
INTENT(IN) :: k
231 REAL(kind=
dp) :: z_over_k
238 z_over_k = z_over_k*(z - i + 1)/real(i,
dp)
254 INTEGER,
INTENT(IN) :: n
255 INTEGER,
DIMENSION(:),
INTENT(IN) :: k
259 REAL(kind=
dp) :: denom
261 IF (all(k >= 0) .AND. sum(k) == n)
THEN
264 denom = denom*
fac(k(i))
285 REAL(kind=
dp),
INTENT(IN) :: phi
286 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
287 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: rotmat
289 REAL(kind=
dp) :: cosp, cost, length_of_a, sinp
290 REAL(kind=
dp),
DIMENSION(3) :: d
292 length_of_a = sqrt(a(1)*a(1) + a(2)*a(2) + a(3)*a(3))
294 IF (length_of_a > eps_geo)
THEN
296 d(:) = a(:)/length_of_a
302 rotmat(1, 1) = d(1)*d(1)*cost + cosp
303 rotmat(1, 2) = d(1)*d(2)*cost - d(3)*sinp
304 rotmat(1, 3) = d(1)*d(3)*cost + d(2)*sinp
305 rotmat(2, 1) = d(2)*d(1)*cost + d(3)*sinp
306 rotmat(2, 2) = d(2)*d(2)*cost + cosp
307 rotmat(2, 3) = d(2)*d(3)*cost - d(1)*sinp
308 rotmat(3, 1) = d(3)*d(1)*cost - d(2)*sinp
309 rotmat(3, 2) = d(3)*d(2)*cost + d(1)*sinp
310 rotmat(3, 3) = d(3)*d(3)*cost + cosp
325 PURE FUNCTION det_3x3_1(a)
RESULT(det_a)
326 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
327 REAL(kind=
dp) :: det_a
329 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
330 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
331 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
333 END FUNCTION det_3x3_1
345 PURE FUNCTION det_3x3_2(a1, a2, a3)
RESULT(det_a)
346 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3
347 REAL(kind=
dp) :: det_a
349 det_a = a1(1)*(a2(2)*a3(3) - a3(2)*a2(3)) + &
350 a2(1)*(a3(2)*a1(3) - a1(2)*a3(3)) + &
351 a3(1)*(a1(2)*a2(3) - a2(2)*a1(3))
353 END FUNCTION det_3x3_2
372 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
373 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigval
374 LOGICAL,
INTENT(IN),
OPTIONAL :: dac
376 CHARACTER(len=*),
PARAMETER :: routinen =
'diamat_all'
378 INTEGER :: handle, info, liwork, lwork, n, nb
379 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
380 INTEGER,
EXTERNAL :: ilaenv
381 LOGICAL :: divide_and_conquer
382 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
384 EXTERNAL dsyev, dsyevd
386 CALL timeset(routinen, handle)
392 IF (
SIZE(a, 2) /= n)
THEN
393 cpabort(
"Check the size of matrix a (parameter #1)")
397 IF (
SIZE(eigval) /= n)
THEN
398 cpabort(
"The dimension of vector eigval is too small")
403 IF (
PRESENT(dac))
THEN
404 divide_and_conquer = dac
406 divide_and_conquer = .false.
411 IF (divide_and_conquer)
THEN
412 lwork = 2*n**2 + 6*n + 1
415 nb = ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1)
421 ALLOCATE (work(lwork))
422 IF (divide_and_conquer)
THEN
423 ALLOCATE (iwork(liwork))
429 IF (divide_and_conquer)
THEN
430 CALL dsyevd(
"V",
"U", n, a, n, eigval, work, lwork, iwork, liwork, info)
432 CALL dsyev(
"V",
"U", n, a, n, eigval, work, lwork, info)
436 IF (divide_and_conquer)
THEN
437 cpabort(
"The matrix diagonalization with dsyevd failed")
439 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
547 INTEGER,
ALLOCATABLE :: ipiv(:)
548 REAL(kind=
dp),
ALLOCATABLE :: work(:)
553 ALLOCATE (work(lwork))
557 CALL dgetrf(n, n, a, n, ipiv, info)
559 CALL dgetri(n, a, n, ipiv, work, lwork, info)
561 DEALLOCATE (ipiv, work)
574 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
575 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: cholesky_triangle
577 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat_symm'
579 CHARACTER(LEN=1) :: my_triangle
580 INTEGER :: handle, i, info, n
582 CALL timeset(routinen, handle)
587 IF (
PRESENT(cholesky_triangle))
THEN
588 my_triangle = cholesky_triangle
594 IF (.NOT.
PRESENT(cholesky_triangle))
THEN
595 CALL dpotrf(my_triangle, n, a, n, info)
597 cpabort(
"DPOTRF failed")
602 CALL dpotri(my_triangle, n, a, n, info)
604 cpabort(
"Matrix inversion failed")
607 IF (my_triangle ==
"U")
THEN
609 a(i + 1:n, i) = a(i, i + 1:n)
613 a(i, i + 1:n) = a(i + 1:n, i)
617 CALL timestop(handle)
643 SUBROUTINE invert_matrix_d(a, a_inverse, eval_error, option, improve)
644 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
645 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
646 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
647 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
648 LOGICAL,
INTENT(IN),
OPTIONAL :: improve
650 CHARACTER(LEN=1) :: norm, trans
651 CHARACTER(LEN=default_string_length) :: message
652 INTEGER :: info, iter, n
653 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv, iwork
654 LOGICAL :: do_improve
655 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
656 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, work
657 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
658 REAL(KIND=
dp),
EXTERNAL :: dlange
660 EXTERNAL dgecon, dgerfs, dgetrf, dgetrs
663 IF (
PRESENT(option))
THEN
669 IF (
PRESENT(improve))
THEN
680 cpabort(
"Matrix to be inverted of zero size")
683 IF (n /=
SIZE(a, 2))
THEN
684 cpabort(
"Check the array bounds of parameter #1")
687 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
688 (n /=
SIZE(a_inverse, 2)))
THEN
689 cpabort(
"Check the array bounds of parameter #2")
693 ALLOCATE (a_lu(n, n))
707 a_lu(1:n, 1:n) = a(1:n, 1:n)
710 CALL dgetrf(n, n, a_lu, n, ipiv, info)
713 cpabort(
"The LU factorization in dgetrf failed")
718 IF (trans ==
"N")
THEN
724 a_norm = dlange(norm, n, n, a, n, work)
728 CALL dgecon(norm, n, a_lu, n, a_norm, r_cond, work, iwork, info)
731 cpabort(
"The computation of the condition number in dgecon failed")
734 IF (r_cond < epsilon(0.0_dp))
THEN
735 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
736 CALL cp_abort(__location__, &
737 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
738 "working precision)")
745 CALL dgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
748 cpabort(
"Solving the system of linear equations in dgetrs failed")
759 CALL dgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
763 cpabort(
"Improving the computed solution in dgerfs failed")
766 old_eval_error = eval_error
767 eval_error = maxval(ferr)
769 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
783 END SUBROUTINE invert_matrix_d
805 SUBROUTINE invert_matrix_z(a, a_inverse, eval_error, option)
806 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: a
807 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
808 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
809 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
811 CHARACTER(LEN=1) :: norm, trans
812 CHARACTER(LEN=default_string_length) :: message
813 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: work
814 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
815 INTEGER :: info, iter, n
816 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
817 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
818 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, rwork
819 REAL(KIND=
dp),
EXTERNAL :: zlange
821 EXTERNAL zgecon, zgerfs, zgetrf, zgetrs
824 IF (
PRESENT(option))
THEN
835 cpabort(
"Matrix to be inverted of zero size")
838 IF (n /=
SIZE(a, 2))
THEN
839 cpabort(
"Check the array bounds of parameter #1")
842 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
843 (n /=
SIZE(a_inverse, 2)))
THEN
844 cpabort(
"Check the array bounds of parameter #2")
848 ALLOCATE (a_lu(n, n))
858 ALLOCATE (rwork(2*n))
862 a_lu(1:n, 1:n) = a(1:n, 1:n)
865 CALL zgetrf(n, n, a_lu, n, ipiv, info)
868 cpabort(
"The LU factorization in dgetrf failed")
873 IF (trans ==
"N")
THEN
879 a_norm = zlange(norm, n, n, a, n, work)
883 CALL zgecon(norm, n, a_lu, n, a_norm, r_cond, work, rwork, info)
886 cpabort(
"The computation of the condition number in dgecon failed")
889 IF (r_cond < epsilon(0.0_dp))
THEN
890 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
891 CALL cp_abort(__location__, &
892 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
893 "working precision)")
900 CALL zgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
903 cpabort(
"Solving the system of linear equations in dgetrs failed")
913 CALL zgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
917 cpabort(
"Improving the computed solution in dgerfs failed")
920 old_eval_error = eval_error
921 eval_error = maxval(ferr)
923 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
936 END SUBROUTINE invert_matrix_z
949 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
950 REAL(kind=
dp),
INTENT(IN) :: rskip
951 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: determinant
952 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT), &
953 OPTIONAL,
POINTER :: sval
955 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_svd'
957 INTEGER :: handle, i, info, lwork, n
958 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
959 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: sig, work
960 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: sig_plus, temp_mat, u, vt
962 CALL timeset(routinen, handle)
965 ALLOCATE (u(n, n), vt(n, n), sig(n), sig_plus(n, n), iwork(8*n), work(1), temp_mat(n, n))
972 IF (
PRESENT(determinant)) determinant = 1.0_dp
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(
"ERROR in DGESDD: Could not retrieve work array sizes")
984 ALLOCATE (work(lwork))
987 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
988 lwork, iwork(1), info)
991 cpabort(
"SVD failed")
994 IF (
PRESENT(sval))
THEN
995 cpassert(.NOT.
ASSOCIATED(sval))
1002 IF (sig(i) > rskip*maxval(sig))
THEN
1003 IF (
PRESENT(determinant)) &
1004 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 INTEGER,
INTENT(IN) :: n
1405 REAL(
dp),
INTENT(IN) :: x
1408 INTEGER,
PARAMETER :: maxit = 100
1409 REAL(
dp),
PARAMETER :: eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp, &
1410 fpmin = tiny(0.0_dp)
1412 INTEGER :: i, ii, nm1
1413 REAL(
dp) :: a, b, c, d, del, fact, h, psi
1417 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
1418 cpabort(
"Invalid argument")
1419 ELSE IF (n .EQ. 0)
THEN
1421 ELSE IF (x .EQ. 0.0_dp)
THEN
1423 ELSE IF (x .GT. 1.0_dp)
THEN
1431 d = 1.0_dp/(a*d + b)
1435 IF (abs(del - 1.0_dp) .LT. eps)
THEN
1440 cpabort(
"continued fraction failed in expint")
1442 IF (nm1 .NE. 0)
THEN
1450 IF (i .NE. nm1)
THEN
1451 del = -fact/(i - nm1)
1455 psi = psi + 1.0_dp/ii
1457 del = fact*(-log(x) + psi)
1460 IF (abs(del) .LT. abs(
expint)*eps)
RETURN
1462 cpabort(
"series failed in expint")
1479 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1480 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1481 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1488 CALL diag(n, a, d, v)
1491 CALL eigsrt(n, d, v)
1507 INTEGER,
INTENT(IN) :: n
1508 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1509 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1510 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1512 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1514 INTEGER :: i, ip, iq
1515 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1516 t, tau, theta, tresh
1517 REAL(kind=
dp),
DIMENSION(n) :: b, z
1521 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1531 d_min = max(d_eps, minval(abs(b)))
1532 IF (a_max < a_eps*d_min)
RETURN
1533 tresh = merge(a_max, 0.0_dp, (i < 4))
1540 g = 100.0_dp*abs(apq)
1541 IF (tresh < abs(apq))
THEN
1543 IF ((abs(h) + g) .NE. abs(h))
THEN
1544 theta = 0.5_dp*h/apq
1545 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1546 IF (theta < 0.0_dp) t = -t
1550 c = 1.0_dp/sqrt(1.0_dp + t**2)
1552 tau = s/(1.0_dp + c)
1559 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1560 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1561 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1562 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1563 ELSE IF ((4 < i) .AND. &
1564 ((abs(dip) + g) == abs(dip)) .AND. &
1565 ((abs(diq) + g) == abs(diq)))
THEN
1573 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1576 WRITE (*,
'(/,T2,A,/)')
'Too many iterations in jacobi'
1590 PURE SUBROUTINE jrotate(a, b, ss, tt)
1591 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1592 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1594 REAL(kind=
dp) :: u, v
1600 b = b*(u + ss*v) + a*v
1602 END SUBROUTINE jrotate
1614 SUBROUTINE eigsrt(n, d, v)
1615 INTEGER,
INTENT(IN) :: n
1616 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1617 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1622 j = sum(minloc(d(i:n))) + i - 1
1624 CALL swap(d(i), d(j))
1625 CALL swap(v(:, i), v(:, j))
1629 END SUBROUTINE eigsrt
1639 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1640 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1648 END SUBROUTINE swap_scalar
1658 SUBROUTINE swap_vector(a, b)
1659 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1666 IF (n /=
SIZE(b))
THEN
1667 cpabort(
"Check the array bounds of the parameters")
1676 END SUBROUTINE swap_vector
1691 REAL(
dp),
INTENT(in) :: eps, omg
1692 REAL(
dp),
INTENT(out) :: r_cutoff
1694 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1696 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1697 REAL(
dp) :: r0, f0, fprime0, delta_r
1698 INTEGER :: iter, handle
1699 INTEGER,
PARAMETER :: itermax = 1000
1701 CALL timeset(routinen, handle)
1704 r0 = sqrt(-log(eps*omg*10**2))/omg
1705 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1707 DO iter = 1, itermax
1708 delta_r = f0/fprime0
1710 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1711 IF (abs(delta_r) .LT. abstol .OR. abs(f0) .LT. soltol)
EXIT
1713 cpassert(iter <= itermax)
1716 CALL timestop(handle)
1726 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1727 REAL(
dp),
INTENT(in) :: r, eps, omega
1728 REAL(
dp),
INTENT(out) :: fn, df
1733 fn = erfc(qr) - r*eps
1734 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1735 END SUBROUTINE eval_transc_func
1746 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: matrix, eigenvectors
1747 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1749 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1750 INTEGER :: info, liwork, lrwork, lwork, n
1751 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1752 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1754 eigenvectors(:, :) = matrix(:, :)
1757 ALLOCATE (iwork(1), rwork(1), work(1))
1764 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1766 lwork = ceiling(real(work(1), kind=
dp))
1767 lrwork = ceiling(real(rwork(1), kind=
dp))
1770 DEALLOCATE (iwork, rwork, work)
1771 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1774 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1776 DEALLOCATE (iwork, rwork, work)
1778 cpabort(
"Diagonalisation of a complex matrix failed")
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.
subroutine, public invmat_symm(a, cholesky_triangle)
returns inverse of real symmetric, positive definite matrix
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)*....
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.
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.
subroutine, public complex_diag(matrix, eigenvectors, eigenvalues)
Diagonalizes a local complex Hermitian matrix using LAPACK. Based on cp_cfm_heevd.
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.