24#include "../base/base_uses.f90"
30 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mathlib'
31 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 = sqrt(dot_product(a, a))
191 length_of_b = sqrt(dot_product(b, 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)) &
1001 determinant = determinant*sig(i)
1002 sig_plus(i, i) = 1._dp/sig(i)
1004 sig_plus(i, i) = 0.0_dp
1009 CALL dgemm(
"N",
"T", n, n, n, 1._dp, sig_plus, n, u, n, 0._dp, temp_mat, n)
1010 CALL dgemm(
"T",
"N", n, n, n, 1._dp, vt, n, temp_mat, n, 0._dp, a_pinverse, n)
1012 DEALLOCATE (u, vt, sig, iwork, work, sig_plus, temp_mat)
1014 CALL timestop(handle)
1027 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
1028 REAL(kind=
dp),
INTENT(IN) :: rskip
1030 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_diag'
1032 INTEGER :: handle, i, info, lwork, n
1033 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig, work
1034 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dinv, temp_mat
1036 CALL timeset(routinen, handle)
1040 ALLOCATE (dinv(n, n), eig(n), work(1), temp_mat(n, n))
1048 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1050 cpabort(
"ERROR in DSYEV: Could not retrieve work array sizes")
1052 lwork = int(work(1))
1054 ALLOCATE (work(lwork))
1058 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1061 cpabort(
"Matrix diagonalization failed")
1066 IF (eig(i) > rskip*maxval(eig))
THEN
1067 dinv(i, i) = 1.0_dp/eig(i)
1074 CALL dgemm(
"N",
"T", n, n, n, 1._dp, dinv, n, a, n, 0._dp, temp_mat, n)
1075 CALL dgemm(
"N",
"N", n, n, n, 1._dp, a, n, temp_mat, n, 0._dp, a_pinverse, n)
1077 DEALLOCATE (eig, work, dinv, temp_mat)
1079 CALL timestop(handle)
1094 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1095 REAL(kind=
dp),
DIMENSION(3) :: a_mirror
1097 REAL(kind=
dp) :: length_of_b, scapro
1098 REAL(kind=
dp),
DIMENSION(3) :: d
1100 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1102 IF (length_of_b > eps_geo)
THEN
1104 d(:) = b(:)/length_of_b
1107 scapro = a(1)*d(1) + a(2)*d(2) + a(3)*d(3)
1109 a_mirror(:) = a(:) - 2.0_dp*scapro*d(:)
1113 a_mirror(:) = 0.0_dp
1132 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
1133 REAL(kind=
dp),
INTENT(IN) :: phi
1134 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: b
1135 REAL(kind=
dp),
DIMENSION(3) :: a_rot
1137 REAL(kind=
dp) :: length_of_b
1138 REAL(kind=
dp),
DIMENSION(3, 3) :: rotmat
1140 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1141 IF (length_of_b > eps_geo)
THEN
1147 a_rot(:) = matmul(rotmat, a)
1165 PURE SUBROUTINE set_diag_scalar_d(a, b)
1166 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1167 REAL(kind=
dp),
INTENT(IN) :: b
1171 n = min(
SIZE(a, 1),
SIZE(a, 2))
1176 END SUBROUTINE set_diag_scalar_d
1183 PURE SUBROUTINE set_diag_scalar_z(a, b)
1184 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1185 COMPLEX(KIND=dp),
INTENT(IN) :: b
1189 n = min(
SIZE(a, 1),
SIZE(a, 2))
1194 END SUBROUTINE set_diag_scalar_z
1205 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1206 CHARACTER(LEN=*),
INTENT(IN) :: option
1210 n = min(
SIZE(a, 1),
SIZE(a, 2))
1212 IF (option ==
"lower_to_upper")
THEN
1214 a(i, i + 1:n) = a(i + 1:n, i)
1216 ELSE IF (option ==
"upper_to_lower")
THEN
1218 a(i + 1:n, i) = a(i, i + 1:n)
1220 ELSE IF (option ==
"anti_lower_to_upper")
THEN
1222 a(i, i + 1:n) = -a(i + 1:n, i)
1224 ELSE IF (option ==
"anti_upper_to_lower")
THEN
1226 a(i + 1:n, i) = -a(i, i + 1:n)
1229 cpabort(
"Invalid option <"//trim(option)//
"> was specified for parameter #2")
1241 PURE SUBROUTINE unit_matrix_d(a)
1242 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1247 END SUBROUTINE unit_matrix_d
1253 PURE SUBROUTINE unit_matrix_z(a)
1254 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1256 a(:, :) = (0.0_dp, 0.0_dp)
1259 END SUBROUTINE unit_matrix_z
1271 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1272 REAL(kind=
dp),
DIMENSION(3) :: c
1274 c(1) = a(2)*b(3) - a(3)*b(2)
1275 c(2) = a(3)*b(1) - a(1)*b(3)
1276 c(3) = a(1)*b(2) - a(2)*b(1)
1288 INTEGER,
INTENT(IN) :: a, b
1291 INTEGER :: aa, ab, l, rem, s
1323 INTEGER,
INTENT(IN) :: a, b
1333 lcm = abs((a/tmp)*b)
1347 INTEGER,
PARAMETER :: maxit = 100
1348 REAL(
dp),
PARAMETER :: eps = epsilon(0.0_dp), &
1349 fpmin = tiny(0.0_dp)
1352 REAL(
dp) :: fact, prev, sum1, term
1354 IF (x <= 0._dp)
THEN
1355 cpabort(
"Invalid argument")
1360 ELSE IF (x <= -log(eps))
THEN
1364 fact = fact*x/real(k,
dp)
1365 term = fact/real(k,
dp)
1367 IF (term < eps*sum1)
EXIT
1369 ei = sum1 + log(x) +
euler
1375 term = term*real(k,
dp)/x
1376 IF (term < eps)
EXIT
1377 IF (term < prev)
THEN
1384 ei = exp(x)*(1._dp + sum1)/x
1401 INTEGER,
INTENT(IN) :: n
1402 REAL(
dp),
INTENT(IN) :: x
1405 INTEGER,
PARAMETER :: maxit = 100
1406 REAL(
dp),
PARAMETER :: eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp, &
1407 fpmin = tiny(0.0_dp)
1409 INTEGER :: i, ii, nm1
1410 REAL(
dp) :: a, b, c, d, del, fact, h, psi
1414 IF (n < 0 .OR. x < 0.0_dp .OR. (x == 0.0_dp .AND. (n == 0 .OR. n == 1)))
THEN
1415 cpabort(
"Invalid argument")
1416 ELSE IF (n == 0)
THEN
1418 ELSE IF (x == 0.0_dp)
THEN
1420 ELSE IF (x > 1.0_dp)
THEN
1428 d = 1.0_dp/(a*d + b)
1432 IF (abs(del - 1.0_dp) < eps)
THEN
1437 cpabort(
"continued fraction failed in expint")
1448 del = -fact/(i - nm1)
1452 psi = psi + 1.0_dp/ii
1454 del = fact*(-log(x) + psi)
1457 IF (abs(del) < abs(
expint)*eps)
RETURN
1459 cpabort(
"series failed in expint")
1476 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1477 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1478 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1485 CALL diag(n, a, d, v)
1488 CALL eigsrt(n, d, v)
1504 INTEGER,
INTENT(IN) :: n
1505 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1506 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1507 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1509 CHARACTER(len=*),
PARAMETER :: routinen =
'diag'
1510 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1512 INTEGER :: handle, i, ip, iq
1513 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1514 t, tau, theta, tresh
1515 REAL(kind=
dp),
DIMENSION(n) :: b, z
1517 CALL timeset(routinen, handle)
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)
THEN
1533 CALL timestop(handle)
1536 tresh = merge(a_max, 0.0_dp, (i < 4))
1543 g = 100.0_dp*abs(apq)
1544 IF (tresh < abs(apq))
THEN
1546 IF ((abs(h) + g) /= abs(h))
THEN
1547 theta = 0.5_dp*h/apq
1548 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1549 IF (theta < 0.0_dp) t = -t
1553 c = 1.0_dp/sqrt(1.0_dp + t**2)
1555 tau = s/(1.0_dp + c)
1562 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1563 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1564 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1565 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1566 ELSE IF ((4 < i) .AND. &
1567 ((abs(dip) + g) == abs(dip)) .AND. &
1568 ((abs(diq) + g) == abs(diq)))
THEN
1576 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1579 WRITE (*,
'(/,T2,A,/)')
'Too many iterations in jacobi'
1581 CALL timestop(handle)
1595 PURE SUBROUTINE jrotate(a, b, ss, tt)
1596 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1597 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1599 REAL(kind=
dp) :: u, v
1605 b = b*(u + ss*v) + a*v
1607 END SUBROUTINE jrotate
1619 SUBROUTINE eigsrt(n, d, v)
1620 INTEGER,
INTENT(IN) :: n
1621 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1622 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1627 j = sum(minloc(d(i:n))) + i - 1
1629 CALL swap(d(i), d(j))
1630 CALL swap(v(:, i), v(:, j))
1634 END SUBROUTINE eigsrt
1644 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1645 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1653 END SUBROUTINE swap_scalar
1663 SUBROUTINE swap_vector(a, b)
1664 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1671 IF (n /=
SIZE(b))
THEN
1672 cpabort(
"Check the array bounds of the parameters")
1681 END SUBROUTINE swap_vector
1696 REAL(
dp),
INTENT(in) :: eps, omg
1697 REAL(
dp),
INTENT(out) :: r_cutoff
1699 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1701 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1702 REAL(
dp) :: r0, f0, fprime0, delta_r
1703 INTEGER :: iter, handle
1704 INTEGER,
PARAMETER :: itermax = 1000
1706 CALL timeset(routinen, handle)
1709 r0 = sqrt(-log(eps*omg*10**2))/omg
1710 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1712 DO iter = 1, itermax
1713 delta_r = f0/fprime0
1715 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1716 IF (abs(delta_r) < abstol .OR. abs(f0) < soltol)
EXIT
1718 cpassert(iter <= itermax)
1721 CALL timestop(handle)
1731 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1732 REAL(
dp),
INTENT(in) :: r, eps, omega
1733 REAL(
dp),
INTENT(out) :: fn, df
1738 fn = erfc(qr) - r*eps
1739 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1740 END SUBROUTINE eval_transc_func
1751 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
1752 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
1753 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1755 CHARACTER(len=*),
PARAMETER :: routinen =
'diag_complex'
1757 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1758 INTEGER :: handle, info, liwork, lrwork, lwork, n
1759 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1760 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1762 CALL timeset(routinen, handle)
1764 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1768 ALLOCATE (iwork(1), rwork(1), work(1))
1775 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1777 lwork = ceiling(real(work(1), kind=
dp))
1778 lrwork = ceiling(rwork(1))
1781 DEALLOCATE (iwork, rwork, work)
1782 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1783 eigenvectors(:, :) = matrix(:, :)
1786 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1788 DEALLOCATE (iwork, rwork, work)
1790 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
1792 CALL timestop(handle)
1803 REAL(
dp),
DIMENSION(:, :) :: matrix
1804 COMPLEX(dp),
DIMENSION(:, :) :: evecs
1805 COMPLEX(dp),
DIMENSION(:) :: evals
1807 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_c
1809 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
1811 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1815 ALLOCATE (matrix_c(n, n), eigenvalues(n))
1817 matrix_c(:, :) = cmplx(0.0_dp, -matrix, kind=
dp)
1819 evals = cmplx(0.0_dp, eigenvalues, kind=
dp)
1821 DEALLOCATE (matrix_c, eigenvalues)
1833 SUBROUTINE zgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1834 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1835 CHARACTER,
INTENT(IN) :: A_trans
1836 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1837 CHARACTER,
INTENT(IN) :: B_trans
1838 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: C_out
1840 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_2'
1842 INTEGER :: handle, n
1845 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1846 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1847 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1848 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
1849 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
1850 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1851 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1852 a_trans ==
'C' .OR. a_trans ==
'c')) &
1853 cpabort(
"Unknown transpose character for array 1 (A).")
1854 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1855 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1856 b_trans ==
'C' .OR. b_trans ==
'c')) &
1857 cpabort(
"Unknown transpose character for array 2 (B).")
1859 CALL timeset(routinen, handle)
1861 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, c_out, n)
1863 CALL timestop(handle)
1865 END SUBROUTINE zgemm_square_2
1876 SUBROUTINE dgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1877 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
1878 CHARACTER,
INTENT(IN) :: A_trans
1879 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
1880 CHARACTER,
INTENT(IN) :: B_trans
1881 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: c_out
1883 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_2'
1885 INTEGER :: handle, n
1888 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1889 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1890 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1891 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
1892 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
1893 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1894 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1895 a_trans ==
'C' .OR. a_trans ==
'c')) &
1896 cpabort(
"Unknown transpose character for array 1 (A).")
1897 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1898 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1899 b_trans ==
'C' .OR. b_trans ==
'c')) &
1900 cpabort(
"Unknown transpose character for array 2 (B).")
1902 CALL timeset(routinen, handle)
1904 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, c_out, n)
1906 CALL timestop(handle)
1908 END SUBROUTINE dgemm_square_2
1921 SUBROUTINE zgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
1922 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1923 CHARACTER,
INTENT(IN) :: A_trans
1924 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1925 CHARACTER,
INTENT(IN) :: B_trans
1926 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: C_in
1927 CHARACTER,
INTENT(IN) :: C_trans
1928 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: D_out
1930 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_3'
1932 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
1933 INTEGER :: handle, n
1936 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1937 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1938 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1939 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
1940 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
1941 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
1942 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
1943 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1944 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1945 a_trans ==
'C' .OR. a_trans ==
'c')) &
1946 cpabort(
"Unknown transpose character for array 1 (A).")
1947 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1948 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1949 b_trans ==
'C' .OR. b_trans ==
'c')) &
1950 cpabort(
"Unknown transpose character for array 2 (B).")
1951 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
1952 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
1953 c_trans ==
'C' .OR. c_trans ==
'c')) &
1954 cpabort(
"Unknown transpose character for array 3 (C).")
1956 CALL timeset(routinen, handle)
1958 ALLOCATE (work(n, n), source=
z_zero)
1960 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, work, n)
1961 CALL zgemm(
'N', c_trans, n, n, n,
z_one, work, n, c_in, n,
z_zero, d_out, n)
1965 CALL timestop(handle)
1967 END SUBROUTINE zgemm_square_3
1980 SUBROUTINE dgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
1981 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
1982 CHARACTER,
INTENT(IN) :: A_trans
1983 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
1984 CHARACTER,
INTENT(IN) :: B_trans
1985 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: c_in
1986 CHARACTER,
INTENT(IN) :: C_trans
1987 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_out
1989 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_3'
1991 INTEGER :: handle, n
1992 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
1995 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1996 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1997 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1998 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
1999 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
2000 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
2001 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
2002 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2003 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2004 a_trans ==
'C' .OR. a_trans ==
'c')) &
2005 cpabort(
"Unknown transpose character for array 1 (A).")
2006 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2007 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2008 b_trans ==
'C' .OR. b_trans ==
'c')) &
2009 cpabort(
"Unknown transpose character for array 2 (B).")
2010 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2011 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2012 c_trans ==
'C' .OR. c_trans ==
'c')) &
2013 cpabort(
"Unknown transpose character for array 3 (C).")
2015 CALL timeset(routinen, handle)
2017 ALLOCATE (work(n, n), source=0.0_dp)
2019 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, work, n)
2020 CALL dgemm(
'N', c_trans, n, n, n, 1.0_dp, work, n, c_in, n, 0.0_dp, d_out, n)
2024 CALL timestop(handle)
2026 END SUBROUTINE dgemm_square_3
2037 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: a_in, b_in
2038 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
2039 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
2041 CHARACTER(len=*),
PARAMETER :: routinen =
'geeig_right'
2042 COMPLEX(KIND=dp),
PARAMETER :: cone = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2043 czero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2045 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: cevals
2046 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a, b, work
2047 INTEGER :: handle, i, icol, irow, lda, ldb, ldc, &
2048 nao, nc, ncol, nmo, nx
2049 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
2051 CALL timeset(routinen, handle)
2055 nmo =
SIZE(eigenvalues)
2056 ALLOCATE (evals(nao), cevals(nao))
2057 ALLOCATE (work(nao, nao), b(nao, nao), a(nao, nao))
2058 a(:, :) = a_in(:, :)
2059 b(:, :) = b_in(:, :)
2064 evals(:) = -evals(:)
2067 IF (evals(i) < -1.0_dp)
THEN
2078 CALL zcopy(ncol*nao, work(1, nc + 1), 1, eigenvectors(1, nc + 1), 1)
2081 DO icol = nc + 1, nao
2083 work(irow, icol) = czero
2087 evals(nc + 1:nao) = 1.0_dp
2090 cevals(:) = cmplx(1.0_dp/sqrt(evals(:)), 0.0_dp, kind=
dp)
2091 DO i = 1, min(
SIZE(work, 2),
SIZE(cevals))
2092 CALL zscal(min(
SIZE(work, 2),
SIZE(cevals)), cevals(i), work(1, i), 1)
2099 DO icol = nc + 1, nao
2100 a(icol, icol) = 10000*cone
2105 eigenvalues(1:nmo) = evals(1:nmo)
2110 ldc =
SIZE(eigenvectors, 1)
2111 CALL zgemm(
"N",
"N", nao, nx, nc, cone, work, &
2112 lda, b, ldb, czero, eigenvectors, ldc)
2114 DEALLOCATE (evals, cevals, work, b, a)
2116 CALL timestop(handle)
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public oorootpi
complex(kind=dp), parameter, public z_one
real(kind=dp), parameter, public euler
real(kind=dp), dimension(0:maxfac), parameter, public fac
complex(kind=dp), parameter, public z_zero
Collection of simple mathematical functions and subroutines.
subroutine, public get_pseudo_inverse_svd(a, a_pinverse, rskip, determinant, sval)
returns the pseudoinverse of a real, square matrix using singular value decomposition
subroutine, public jacobi(a, d, v)
Jacobi matrix diagonalization. The eigenvalues are returned in vector d and the eigenvectors are retu...
elemental real(kind=dp) function, public binomial(n, k)
The binomial coefficient n over k for 0 <= k <= n is calculated, otherwise zero is returned.
elemental integer function, public lcm(a, b)
computes the least common multiplier of two numbers
subroutine, public get_pseudo_inverse_diag(a, a_pinverse, rskip)
returns the pseudoinverse of a real, symmetric and positive definite matrix using diagonalization.
elemental real(kind=dp) function, public binomial_gen(z, k)
The generalized binomial coefficient z over k for 0 <= k <= n is calculated. (z) z*(z-1)*....
subroutine, public invmat_symm(a, potrf, uplo)
returns inverse of real symmetric, positive definite matrix
pure real(kind=dp) function, dimension(min(size(a, 1), size(a, 2))), public get_diag(a)
Return the diagonal elements of matrix a as a vector.
pure real(kind=dp) function, dimension(3), public reflect_vector(a, b)
Reflection of the vector a through a mirror plane defined by the normal vector b. The reflected vecto...
pure real(kind=dp) function, public angle(a, b)
Calculation of the angle between the vectors a and b. The angle is returned in radians.
subroutine, public diag_complex(matrix, eigenvectors, eigenvalues)
Diagonalizes a local complex Hermitian matrix using LAPACK. Based on cp_cfm_heevd.
subroutine, public diag_antisym(matrix, evecs, evals)
Helper routine for diagonalizing anti symmetric matrices.
pure subroutine, public build_rotmat(phi, a, rotmat)
The rotation matrix rotmat which rotates a vector about a rotation axis defined by the vector a is bu...
elemental integer function, public gcd(a, b)
computes the greatest common divisor of two number
subroutine, public symmetrize_matrix(a, option)
Symmetrize the matrix a.
pure real(kind=dp) function, dimension(3, 3), public inv_3x3(a)
Returns the inverse of the 3 x 3 matrix a.
subroutine, public invmat(a, info)
returns inverse of matrix using the lapack routines DGETRF and DGETRI
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
subroutine, public diag(n, a, d, v)
Diagonalize matrix a. The eigenvalues are returned in vector d and the eigenvectors are returned in m...
subroutine, public geeig_right(a_in, b_in, eigenvalues, eigenvectors)
Solve the generalized eigenvalue equation for complex matrices A*v = B*v*λ
pure real(kind=dp) function, dimension(3), public rotate_vector(a, phi, b)
Rotation of the vector a about an rotation axis defined by the vector b. The rotation angle is phi (r...
subroutine, public erfc_cutoff(eps, omg, r_cutoff)
compute a truncation radius for the shortrange operator
logical function, public abnormal_value(a)
determines if a value is not normal (e.g. for Inf and Nan) based on IO to work also under optimizatio...
elemental impure real(dp) function, public expint(n, x)
computes the exponential integral En(x) = Int(exp(-x*t)/t^n,t=1..infinity) x>0, n=0,...
pure real(kind=dp) function, public dihedral_angle(ab, bc, cd)
Returns the dihedral angle, i.e. the angle between the planes defined by the vectors (-ab,...
real(kind=dp) function, public pswitch(x, a, b, order)
Polynomial (5th degree) switching function f(a) = 1 .... f(b) = 0 with f'(a) = f"(a) = f'(b) = f"(b) ...
pure real(kind=dp) function, dimension(3), public vector_product(a, b)
Calculation of the vector product c = a x b.
pure real(kind=dp) function, public multinomial(n, k)
Calculates the multinomial coefficients.