24#include "../base/base_uses.f90"
29 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mathlib'
30 REAL(KIND=
dp),
PARAMETER :: eps_geo = 1.0e-6_dp
70 MODULE PROCEDURE det_3x3_1, det_3x3_2
74 MODULE PROCEDURE invert_matrix_d, invert_matrix_z
78 MODULE PROCEDURE set_diag_scalar_d, set_diag_scalar_z
82 MODULE PROCEDURE swap_scalar, swap_vector
86 MODULE PROCEDURE unit_matrix_d, unit_matrix_z
90 MODULE PROCEDURE zgemm_square_2, zgemm_square_3, dgemm_square_2, dgemm_square_3
107 REAL(kind=
dp) :: x, a, b
111 REAL(kind=
dp) :: u, u2, u3
114 IF (x < a .OR. x > b)
THEN
135 fx = 1._dp - 10._dp*u3 + 15._dp*u2*u2 - 6._dp*u2*u3
138 fx = -30._dp*u2 + 60._dp*u*u2 - 30._dp*u2*u2
142 fx = -60._dp*u + 180._dp*u2 - 120._dp*u*u2
145 cpabort(
'order not defined')
160 CHARACTER(LEN=32) :: buffer
168 IF (index(buffer,
"N") /= 0 .OR. index(buffer,
"n") /= 0)
abnormal_value = .true.
182 PURE FUNCTION angle(a, b)
RESULT(angle_ab)
183 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: a, b
184 REAL(kind=
dp) :: angle_ab
186 REAL(kind=
dp) :: length_of_a, length_of_b
187 REAL(kind=
dp),
DIMENSION(SIZE(a, 1)) :: a_norm, b_norm
189 length_of_a = sqrt(dot_product(a, a))
190 length_of_b = sqrt(dot_product(b, b))
192 IF ((length_of_a > eps_geo) .AND. (length_of_b > eps_geo))
THEN
193 a_norm(:) = a(:)/length_of_a
194 b_norm(:) = b(:)/length_of_b
195 angle_ab = acos(min(max(dot_product(a_norm, b_norm), -1.0_dp), 1.0_dp))
213 INTEGER,
INTENT(IN) :: n, k
214 REAL(kind=
dp) :: n_over_k
216 IF ((k >= 0) .AND. (k <= n))
THEN
237 REAL(kind=
dp),
INTENT(IN) :: z
238 INTEGER,
INTENT(IN) :: k
239 REAL(kind=
dp) :: z_over_k
246 z_over_k = z_over_k*(z - i + 1)/real(i,
dp)
262 INTEGER,
INTENT(IN) :: n
263 INTEGER,
DIMENSION(:),
INTENT(IN) :: k
267 REAL(kind=
dp) :: denom
269 IF (all(k >= 0) .AND. sum(k) == n)
THEN
272 denom = denom*
fac(k(i))
293 REAL(kind=
dp),
INTENT(IN) :: phi
294 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
295 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: rotmat
297 REAL(kind=
dp) :: cosp, cost, length_of_a, sinp
298 REAL(kind=
dp),
DIMENSION(3) :: d
300 length_of_a = sqrt(a(1)*a(1) + a(2)*a(2) + a(3)*a(3))
302 IF (length_of_a > eps_geo)
THEN
304 d(:) = a(:)/length_of_a
310 rotmat(1, 1) = d(1)*d(1)*cost + cosp
311 rotmat(1, 2) = d(1)*d(2)*cost - d(3)*sinp
312 rotmat(1, 3) = d(1)*d(3)*cost + d(2)*sinp
313 rotmat(2, 1) = d(2)*d(1)*cost + d(3)*sinp
314 rotmat(2, 2) = d(2)*d(2)*cost + cosp
315 rotmat(2, 3) = d(2)*d(3)*cost - d(1)*sinp
316 rotmat(3, 1) = d(3)*d(1)*cost - d(2)*sinp
317 rotmat(3, 2) = d(3)*d(2)*cost + d(1)*sinp
318 rotmat(3, 3) = d(3)*d(3)*cost + cosp
333 PURE FUNCTION det_3x3_1(a)
RESULT(det_a)
334 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
335 REAL(kind=
dp) :: det_a
337 det_a = a(1, 1)*(a(2, 2)*a(3, 3) - a(2, 3)*a(3, 2)) + &
338 a(1, 2)*(a(2, 3)*a(3, 1) - a(2, 1)*a(3, 3)) + &
339 a(1, 3)*(a(2, 1)*a(3, 2) - a(2, 2)*a(3, 1))
341 END FUNCTION det_3x3_1
353 PURE FUNCTION det_3x3_2(a1, a2, a3)
RESULT(det_a)
354 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a1, a2, a3
355 REAL(kind=
dp) :: det_a
357 det_a = a1(1)*(a2(2)*a3(3) - a3(2)*a2(3)) + &
358 a2(1)*(a3(2)*a1(3) - a1(2)*a3(3)) + &
359 a3(1)*(a1(2)*a2(3) - a2(2)*a1(3))
361 END FUNCTION det_3x3_2
380 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
381 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigval
382 LOGICAL,
INTENT(IN),
OPTIONAL :: dac
384 CHARACTER(len=*),
PARAMETER :: routinen =
'diamat_all'
386 INTEGER :: handle, info, liwork, lwork, n, nb
387 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
388 INTEGER,
EXTERNAL :: ilaenv
389 LOGICAL :: divide_and_conquer
390 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
392 EXTERNAL dsyev, dsyevd
394 CALL timeset(routinen, handle)
400 IF (
SIZE(a, 2) /= n)
THEN
401 cpabort(
"Check the size of matrix a (parameter #1)")
405 IF (
SIZE(eigval) /= n)
THEN
406 cpabort(
"The dimension of vector eigval is too small")
411 IF (
PRESENT(dac))
THEN
412 divide_and_conquer = dac
414 divide_and_conquer = .false.
419 IF (divide_and_conquer)
THEN
420 lwork = 2*n**2 + 6*n + 1
423 nb = ilaenv(1,
"DSYTRD",
"U", n, -1, -1, -1)
429 ALLOCATE (work(lwork))
430 IF (divide_and_conquer)
THEN
431 ALLOCATE (iwork(liwork))
437 IF (divide_and_conquer)
THEN
438 CALL dsyevd(
"V",
"U", n, a, n, eigval, work, lwork, iwork, liwork, info)
440 CALL dsyev(
"V",
"U", n, a, n, eigval, work, lwork, info)
444 IF (divide_and_conquer)
THEN
445 cpabort(
"The matrix diagonalization with dsyevd failed")
447 cpabort(
"The matrix diagonalization with dsyev failed")
454 IF (divide_and_conquer)
THEN
458 CALL timestop(handle)
475 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: ab, bc, cd
476 REAL(kind=
dp) :: dihedral_angle_abcd
478 REAL(kind=
dp) :: det_abcd
479 REAL(kind=
dp),
DIMENSION(3) :: abc, bcd
486 det_abcd =
det_3x3(abc, bcd, -bc)
487 dihedral_angle_abcd = sign(1.0_dp, det_abcd)*
angle(abc, bcd)
500 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
502 DIMENSION(MIN(SIZE(a, 1), SIZE(a, 2))) :: a_diag
506 n = min(
SIZE(a, 1),
SIZE(a, 2))
523 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: a
524 REAL(kind=
dp),
DIMENSION(3, 3) :: a_inv
526 REAL(kind=
dp) :: det_a
530 a_inv(1, 1) = (a(2, 2)*a(3, 3) - a(3, 2)*a(2, 3))*det_a
531 a_inv(2, 1) = (a(2, 3)*a(3, 1) - a(3, 3)*a(2, 1))*det_a
532 a_inv(3, 1) = (a(2, 1)*a(3, 2) - a(3, 1)*a(2, 2))*det_a
534 a_inv(1, 2) = (a(1, 3)*a(3, 2) - a(3, 3)*a(1, 2))*det_a
535 a_inv(2, 2) = (a(1, 1)*a(3, 3) - a(3, 1)*a(1, 3))*det_a
536 a_inv(3, 2) = (a(1, 2)*a(3, 1) - a(3, 2)*a(1, 1))*det_a
538 a_inv(1, 3) = (a(1, 2)*a(2, 3) - a(2, 2)*a(1, 3))*det_a
539 a_inv(2, 3) = (a(1, 3)*a(2, 1) - a(2, 3)*a(1, 1))*det_a
540 a_inv(3, 3) = (a(1, 1)*a(2, 2) - a(2, 1)*a(1, 2))*det_a
550 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
551 INTEGER,
INTENT(OUT) :: info
553 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat'
555 INTEGER :: handle, lwork, n
556 INTEGER,
ALLOCATABLE :: ipiv(:)
557 REAL(kind=
dp),
ALLOCATABLE :: work(:)
559 CALL timeset(routinen, handle)
564 ALLOCATE (work(lwork))
568 CALL dgetrf(n, n, a, n, ipiv, info)
570 CALL dgetri(n, a, n, ipiv, work, lwork, info)
572 DEALLOCATE (ipiv, work)
574 CALL timestop(handle)
587 REAL(kind=
dp),
INTENT(INOUT) :: a(:, :)
588 LOGICAL,
INTENT(IN),
OPTIONAL :: potrf
589 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: uplo
591 CHARACTER(LEN=*),
PARAMETER :: routinen =
'invmat_symm'
593 CHARACTER(LEN=1) :: myuplo
594 INTEGER :: handle, info, n
597 CALL timeset(routinen, handle)
600 IF (
PRESENT(potrf)) do_potrf = potrf
603 IF (
PRESENT(uplo)) myuplo = uplo
610 CALL dpotrf(myuplo, n, a, n, info)
611 IF (info /= 0) cpabort(
"DPOTRF failed")
615 CALL dpotri(myuplo, n, a, n, info)
616 IF (info /= 0) cpabort(
"Matrix inversion failed")
619 IF ((myuplo ==
"U") .OR. (myuplo ==
"u"))
THEN
625 CALL timestop(handle)
651 SUBROUTINE invert_matrix_d(a, a_inverse, eval_error, option, improve)
652 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: a
653 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
654 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
655 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
656 LOGICAL,
INTENT(IN),
OPTIONAL :: improve
658 CHARACTER(LEN=1) :: norm, trans
659 CHARACTER(LEN=default_string_length) :: message
660 INTEGER :: info, iter, n
661 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv, iwork
662 LOGICAL :: do_improve
663 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
664 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, work
665 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
666 REAL(KIND=
dp),
EXTERNAL :: dlange
668 EXTERNAL dgecon, dgerfs, dgetrf, dgetrs
671 IF (
PRESENT(option))
THEN
677 IF (
PRESENT(improve))
THEN
688 cpabort(
"Matrix to be inverted of zero size")
691 IF (n /=
SIZE(a, 2))
THEN
692 cpabort(
"Check the array bounds of parameter #1")
695 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
696 (n /=
SIZE(a_inverse, 2)))
THEN
697 cpabort(
"Check the array bounds of parameter #2")
701 ALLOCATE (a_lu(n, n))
709 a_lu(1:n, 1:n) = a(1:n, 1:n)
712 CALL dgetrf(n, n, a_lu, n, ipiv, info)
715 cpabort(
"The LU factorization in dgetrf failed")
720 IF (trans ==
"N")
THEN
726 a_norm = dlange(norm, n, n, a, n, work)
730 CALL dgecon(norm, n, a_lu, n, a_norm, r_cond, work, iwork, info)
733 cpabort(
"The computation of the condition number in dgecon failed")
736 IF (r_cond < epsilon(0.0_dp))
THEN
737 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
738 CALL cp_abort(__location__, &
739 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
740 "working precision)")
747 CALL dgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
750 cpabort(
"Solving the system of linear equations in dgetrs failed")
761 CALL dgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
765 cpabort(
"Improving the computed solution in dgerfs failed")
768 old_eval_error = eval_error
769 eval_error = maxval(ferr)
771 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
785 END SUBROUTINE invert_matrix_d
807 SUBROUTINE invert_matrix_z(a, a_inverse, eval_error, option)
808 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: a
809 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: a_inverse
810 REAL(KIND=
dp),
INTENT(OUT) :: eval_error
811 CHARACTER(LEN=1),
INTENT(IN),
OPTIONAL :: option
813 CHARACTER(LEN=1) :: norm, trans
814 CHARACTER(LEN=default_string_length) :: message
815 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: work
816 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a_lu, b
817 INTEGER :: info, iter, n
818 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ipiv
819 REAL(KIND=
dp) :: a_norm, old_eval_error, r_cond
820 REAL(KIND=
dp),
ALLOCATABLE,
DIMENSION(:) :: berr, ferr, rwork
821 REAL(KIND=
dp),
EXTERNAL :: zlange
823 EXTERNAL zgecon, zgerfs, zgetrf, zgetrs
826 IF (
PRESENT(option))
THEN
837 cpabort(
"Matrix to be inverted of zero size")
840 IF (n /=
SIZE(a, 2))
THEN
841 cpabort(
"Check the array bounds of parameter #1")
844 IF ((n /=
SIZE(a_inverse, 1)) .OR. &
845 (n /=
SIZE(a_inverse, 2)))
THEN
846 cpabort(
"Check the array bounds of parameter #2")
850 ALLOCATE (a_lu(n, n))
855 ALLOCATE (rwork(2*n))
858 a_lu(1:n, 1:n) = a(1:n, 1:n)
861 CALL zgetrf(n, n, a_lu, n, ipiv, info)
864 cpabort(
"The LU factorization in dgetrf failed")
869 IF (trans ==
"N")
THEN
875 a_norm = zlange(norm, n, n, a, n, work)
879 CALL zgecon(norm, n, a_lu, n, a_norm, r_cond, work, rwork, info)
882 cpabort(
"The computation of the condition number in dgecon failed")
885 IF (r_cond < epsilon(0.0_dp))
THEN
886 WRITE (message,
"(A,ES10.3)")
"R_COND =", r_cond
887 CALL cp_abort(__location__, &
888 "Bad condition number "//trim(message)//
" (smaller than the machine "// &
889 "working precision)")
896 CALL zgetrs(trans, n, n, a_lu, n, ipiv, a_inverse, n, info)
899 cpabort(
"Solving the system of linear equations in dgetrs failed")
909 CALL zgerfs(trans, n, n, a, n, a_lu, n, ipiv, b, n, a_inverse, n, ferr, berr, &
913 cpabort(
"Improving the computed solution in dgerfs failed")
916 old_eval_error = eval_error
917 eval_error = maxval(ferr)
919 IF (abs(eval_error - old_eval_error) <= epsilon(1.0_dp))
EXIT
932 END SUBROUTINE invert_matrix_z
945 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
946 REAL(kind=
dp),
INTENT(IN) :: rskip
947 REAL(kind=
dp),
INTENT(OUT),
OPTIONAL :: determinant
948 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT), &
949 OPTIONAL,
POINTER :: sval
951 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_svd'
953 INTEGER :: handle, i, info, lwork, n
954 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
955 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: sig, work
956 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: sig_plus, temp_mat, u, vt
958 CALL timeset(routinen, handle)
961 ALLOCATE (u(n, n), vt(n, n), sig(n), sig_plus(n, n), iwork(8*n), work(1), temp_mat(n, n))
968 IF (
PRESENT(determinant)) determinant = 1.0_dp
972 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
973 lwork, iwork(1), info)
976 cpabort(
"ERROR in DGESDD: Could not retrieve work array sizes")
980 ALLOCATE (work(lwork))
983 CALL dgesdd(
'A', n, n, a(1, 1), n, sig(1), u(1, 1), n, vt(1, 1), n, work(1), &
984 lwork, iwork(1), info)
987 cpabort(
"SVD failed")
990 IF (
PRESENT(sval))
THEN
991 cpassert(.NOT.
ASSOCIATED(sval))
998 IF (sig(i) > rskip*maxval(sig))
THEN
999 IF (
PRESENT(determinant)) &
1000 determinant = determinant*sig(i)
1001 sig_plus(i, i) = 1._dp/sig(i)
1003 sig_plus(i, i) = 0.0_dp
1008 CALL dgemm(
"N",
"T", n, n, n, 1._dp, sig_plus, n, u, n, 0._dp, temp_mat, n)
1009 CALL dgemm(
"T",
"N", n, n, n, 1._dp, vt, n, temp_mat, n, 0._dp, a_pinverse, n)
1011 DEALLOCATE (u, vt, sig, iwork, work, sig_plus, temp_mat)
1013 CALL timestop(handle)
1026 REAL(kind=
dp),
DIMENSION(:, :) :: a, a_pinverse
1027 REAL(kind=
dp),
INTENT(IN) :: rskip
1029 CHARACTER(LEN=*),
PARAMETER :: routinen =
'get_pseudo_inverse_diag'
1031 INTEGER :: handle, i, info, lwork, n
1032 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eig, work
1033 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: dinv, temp_mat
1035 CALL timeset(routinen, handle)
1039 ALLOCATE (dinv(n, n), eig(n), work(1), temp_mat(n, n))
1047 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1049 cpabort(
"ERROR in DSYEV: Could not retrieve work array sizes")
1051 lwork = int(work(1))
1053 ALLOCATE (work(lwork))
1057 CALL dsyev(
'V',
'U', n, a, n, eig(1), work(1), lwork, info)
1060 cpabort(
"Matrix diagonalization failed")
1065 IF (eig(i) > rskip*maxval(eig))
THEN
1066 dinv(i, i) = 1.0_dp/eig(i)
1073 CALL dgemm(
"N",
"T", n, n, n, 1._dp, dinv, n, a, n, 0._dp, temp_mat, n)
1074 CALL dgemm(
"N",
"N", n, n, n, 1._dp, a, n, temp_mat, n, 0._dp, a_pinverse, n)
1076 DEALLOCATE (eig, work, dinv, temp_mat)
1078 CALL timestop(handle)
1093 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1094 REAL(kind=
dp),
DIMENSION(3) :: a_mirror
1096 REAL(kind=
dp) :: length_of_b, scapro
1097 REAL(kind=
dp),
DIMENSION(3) :: d
1099 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1101 IF (length_of_b > eps_geo)
THEN
1103 d(:) = b(:)/length_of_b
1106 scapro = a(1)*d(1) + a(2)*d(2) + a(3)*d(3)
1108 a_mirror(:) = a(:) - 2.0_dp*scapro*d(:)
1112 a_mirror(:) = 0.0_dp
1131 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a
1132 REAL(kind=
dp),
INTENT(IN) :: phi
1133 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: b
1134 REAL(kind=
dp),
DIMENSION(3) :: a_rot
1136 REAL(kind=
dp) :: length_of_b
1137 REAL(kind=
dp),
DIMENSION(3, 3) :: rotmat
1139 length_of_b = sqrt(b(1)*b(1) + b(2)*b(2) + b(3)*b(3))
1140 IF (length_of_b > eps_geo)
THEN
1146 a_rot(:) = matmul(rotmat, a)
1164 PURE SUBROUTINE set_diag_scalar_d(a, b)
1165 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1166 REAL(kind=
dp),
INTENT(IN) :: b
1170 n = min(
SIZE(a, 1),
SIZE(a, 2))
1175 END SUBROUTINE set_diag_scalar_d
1182 PURE SUBROUTINE set_diag_scalar_z(a, b)
1183 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1184 COMPLEX(KIND=dp),
INTENT(IN) :: b
1188 n = min(
SIZE(a, 1),
SIZE(a, 2))
1193 END SUBROUTINE set_diag_scalar_z
1204 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1205 CHARACTER(LEN=*),
INTENT(IN) :: option
1209 n = min(
SIZE(a, 1),
SIZE(a, 2))
1211 IF (option ==
"lower_to_upper")
THEN
1213 a(i, i + 1:n) = a(i + 1:n, i)
1215 ELSE IF (option ==
"upper_to_lower")
THEN
1217 a(i + 1:n, i) = a(i, i + 1:n)
1219 ELSE IF (option ==
"anti_lower_to_upper")
THEN
1221 a(i, i + 1:n) = -a(i + 1:n, i)
1223 ELSE IF (option ==
"anti_upper_to_lower")
THEN
1225 a(i + 1:n, i) = -a(i, i + 1:n)
1228 cpabort(
"Invalid option <"//trim(option)//
"> was specified for parameter #2")
1240 PURE SUBROUTINE unit_matrix_d(a)
1241 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1246 END SUBROUTINE unit_matrix_d
1252 PURE SUBROUTINE unit_matrix_z(a)
1253 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1255 a(:, :) = (0.0_dp, 0.0_dp)
1258 END SUBROUTINE unit_matrix_z
1270 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: a, b
1271 REAL(kind=
dp),
DIMENSION(3) :: c
1273 c(1) = a(2)*b(3) - a(3)*b(2)
1274 c(2) = a(3)*b(1) - a(1)*b(3)
1275 c(3) = a(1)*b(2) - a(2)*b(1)
1287 INTEGER,
INTENT(IN) :: a, b
1290 INTEGER :: aa, ab, l, rem, s
1322 INTEGER,
INTENT(IN) :: a, b
1332 lcm = abs((a/tmp)*b)
1346 INTEGER,
PARAMETER :: maxit = 100
1347 REAL(
dp),
PARAMETER :: eps = epsilon(0.0_dp), &
1348 fpmin = tiny(0.0_dp)
1351 REAL(
dp) :: fact, prev, sum1, term
1353 IF (x <= 0._dp)
THEN
1354 cpabort(
"Invalid argument")
1359 ELSE IF (x <= -log(eps))
THEN
1363 fact = fact*x/real(k,
dp)
1364 term = fact/real(k,
dp)
1366 IF (term < eps*sum1)
EXIT
1368 ei = sum1 + log(x) +
euler
1374 term = term*real(k,
dp)/x
1375 IF (term < eps)
EXIT
1376 IF (term < prev)
THEN
1383 ei = exp(x)*(1._dp + sum1)/x
1400 INTEGER,
INTENT(IN) :: n
1401 REAL(
dp),
INTENT(IN) :: x
1404 INTEGER,
PARAMETER :: maxit = 100
1405 REAL(
dp),
PARAMETER :: eps = 6.e-14_dp,
euler = 0.5772156649015328606065120_dp, &
1406 fpmin = tiny(0.0_dp)
1408 INTEGER :: i, ii, nm1
1409 REAL(
dp) :: a, b, c, d, del, fact, h, psi
1413 IF (n < 0 .OR. x < 0.0_dp .OR. (x == 0.0_dp .AND. (n == 0 .OR. n == 1)))
THEN
1414 cpabort(
"Invalid argument")
1415 ELSE IF (n == 0)
THEN
1417 ELSE IF (x == 0.0_dp)
THEN
1419 ELSE IF (x > 1.0_dp)
THEN
1427 d = 1.0_dp/(a*d + b)
1431 IF (abs(del - 1.0_dp) < eps)
THEN
1436 cpabort(
"continued fraction failed in expint")
1447 del = -fact/(i - nm1)
1451 psi = psi + 1.0_dp/ii
1453 del = fact*(-log(x) + psi)
1456 IF (abs(del) < abs(
expint)*eps)
RETURN
1458 cpabort(
"series failed in expint")
1475 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1476 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1477 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1484 CALL diag(n, a, d, v)
1487 CALL eigsrt(n, d, v)
1503 INTEGER,
INTENT(IN) :: n
1504 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: a
1505 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: d
1506 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(OUT) :: v
1508 CHARACTER(len=*),
PARAMETER :: routinen =
'diag'
1509 REAL(kind=
dp),
PARAMETER :: a_eps = 1.0e-10_dp, d_eps = 1.0e-3_dp
1511 INTEGER :: handle, i, ip, iq
1512 REAL(kind=
dp) :: a_max, apq, c, d_min, dip, diq, g, h, s, &
1513 t, tau, theta, tresh
1514 REAL(kind=
dp),
DIMENSION(n) :: b, z
1516 CALL timeset(routinen, handle)
1520 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1530 d_min = max(d_eps, minval(abs(b)))
1531 IF (a_max < a_eps*d_min)
THEN
1532 CALL timestop(handle)
1535 tresh = merge(a_max, 0.0_dp, (i < 4))
1542 g = 100.0_dp*abs(apq)
1543 IF (tresh < abs(apq))
THEN
1545 IF ((abs(h) + g) /= abs(h))
THEN
1546 theta = 0.5_dp*h/apq
1547 t = 1.0_dp/(abs(theta) + sqrt(1.0_dp + theta**2))
1548 IF (theta < 0.0_dp) t = -t
1552 c = 1.0_dp/sqrt(1.0_dp + t**2)
1554 tau = s/(1.0_dp + c)
1561 CALL jrotate(a(1:ip - 1, ip), a(1:ip - 1, iq), s, tau)
1562 CALL jrotate(a(ip, ip + 1:iq - 1), a(ip + 1:iq - 1, iq), s, tau)
1563 CALL jrotate(a(ip, iq + 1:n), a(iq, iq + 1:n), s, tau)
1564 CALL jrotate(v(:, ip), v(:, iq), s, tau)
1565 ELSE IF ((4 < i) .AND. &
1566 ((abs(dip) + g) == abs(dip)) .AND. &
1567 ((abs(diq) + g) == abs(diq)))
THEN
1575 a_max = max(a_max, maxval(abs(a(ip, ip + 1:n))))
1578 WRITE (*,
'(/,T2,A,/)')
'Too many iterations in jacobi'
1580 CALL timestop(handle)
1594 PURE SUBROUTINE jrotate(a, b, ss, tt)
1595 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1596 REAL(kind=
dp),
INTENT(IN) :: ss, tt
1598 REAL(kind=
dp) :: u, v
1604 b = b*(u + ss*v) + a*v
1606 END SUBROUTINE jrotate
1618 SUBROUTINE eigsrt(n, d, v)
1619 INTEGER,
INTENT(IN) :: n
1620 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: d
1621 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: v
1626 j = sum(minloc(d(i:n))) + i - 1
1628 CALL swap(d(i), d(j))
1629 CALL swap(v(:, i), v(:, j))
1633 END SUBROUTINE eigsrt
1643 ELEMENTAL SUBROUTINE swap_scalar(a, b)
1644 REAL(kind=
dp),
INTENT(INOUT) :: a, b
1652 END SUBROUTINE swap_scalar
1662 SUBROUTINE swap_vector(a, b)
1663 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: a, b
1670 IF (n /=
SIZE(b))
THEN
1671 cpabort(
"Check the array bounds of the parameters")
1680 END SUBROUTINE swap_vector
1693 REAL(
dp),
INTENT(in) :: eps, omg
1694 REAL(
dp),
INTENT(out) :: r_cutoff
1696 CHARACTER(LEN=*),
PARAMETER :: routinen =
'erfc_cutoff'
1698 REAL(
dp),
PARAMETER :: abstol = 1e-10_dp, soltol = 1e-16_dp
1699 REAL(
dp) :: r0, f0, fprime0, delta_r
1700 INTEGER :: iter, handle
1701 INTEGER,
PARAMETER :: itermax = 1000
1703 CALL timeset(routinen, handle)
1706 r0 = sqrt(-log(eps*omg*10**2))/omg
1707 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1709 DO iter = 1, itermax
1710 delta_r = f0/fprime0
1712 CALL eval_transc_func(r0, eps, omg, f0, fprime0)
1713 IF (abs(delta_r) < abstol .OR. abs(f0) < soltol)
EXIT
1715 cpassert(iter <= itermax)
1718 CALL timestop(handle)
1728 ELEMENTAL SUBROUTINE eval_transc_func(r, eps, omega, fn, df)
1729 REAL(
dp),
INTENT(in) :: r, eps, omega
1730 REAL(
dp),
INTENT(out) :: fn, df
1735 fn = erfc(qr) - r*eps
1736 df = -2.0_dp*
oorootpi*omega*exp(-qr**2) - eps
1737 END SUBROUTINE eval_transc_func
1748 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(IN) :: matrix
1749 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
1750 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
1752 CHARACTER(len=*),
PARAMETER :: routinen =
'diag_complex'
1754 COMPLEX(KIND=dp),
DIMENSION(:),
ALLOCATABLE :: work
1755 INTEGER :: handle, info, liwork, lrwork, lwork, n
1756 INTEGER,
DIMENSION(:),
ALLOCATABLE :: iwork
1757 REAL(kind=
dp),
DIMENSION(:),
ALLOCATABLE :: rwork
1759 CALL timeset(routinen, handle)
1761 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1765 ALLOCATE (iwork(1), rwork(1), work(1))
1772 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1774 lwork = ceiling(real(work(1), kind=
dp))
1775 lrwork = ceiling(rwork(1))
1778 DEALLOCATE (iwork, rwork, work)
1779 ALLOCATE (iwork(liwork), rwork(lrwork), work(lwork))
1780 eigenvectors(:, :) = matrix(:, :)
1783 CALL zheevd(
'V',
'U', n, eigenvectors, n, eigenvalues, work, lwork, rwork, lrwork, iwork, liwork, info)
1785 DEALLOCATE (iwork, rwork, work)
1787 IF (info /= 0) cpabort(
"Diagonalisation of a complex matrix failed")
1789 CALL timestop(handle)
1800 REAL(
dp),
DIMENSION(:, :) :: matrix
1801 COMPLEX(dp),
DIMENSION(:, :) :: evecs
1802 COMPLEX(dp),
DIMENSION(:) :: evals
1804 COMPLEX(dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix_c
1806 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
1808 IF (
SIZE(matrix, 1) /=
SIZE(matrix, 2)) cpabort(
"Expected square matrix")
1812 ALLOCATE (matrix_c(n, n), eigenvalues(n))
1814 matrix_c(:, :) = cmplx(0.0_dp, -matrix, kind=
dp)
1816 evals = cmplx(0.0_dp, eigenvalues, kind=
dp)
1818 DEALLOCATE (matrix_c, eigenvalues)
1830 SUBROUTINE zgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1831 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1832 CHARACTER,
INTENT(IN) :: A_trans
1833 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1834 CHARACTER,
INTENT(IN) :: B_trans
1835 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: C_out
1837 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_2'
1839 INTEGER :: handle, n
1842 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1843 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1844 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1845 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
1846 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
1847 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1848 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1849 a_trans ==
'C' .OR. a_trans ==
'c')) &
1850 cpabort(
"Unknown transpose character for array 1 (A).")
1851 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1852 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1853 b_trans ==
'C' .OR. b_trans ==
'c')) &
1854 cpabort(
"Unknown transpose character for array 2 (B).")
1856 CALL timeset(routinen, handle)
1858 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, c_out, n)
1860 CALL timestop(handle)
1862 END SUBROUTINE zgemm_square_2
1873 SUBROUTINE dgemm_square_2(A_in, A_trans, B_in, B_trans, C_out)
1874 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
1875 CHARACTER,
INTENT(IN) :: A_trans
1876 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
1877 CHARACTER,
INTENT(IN) :: B_trans
1878 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: c_out
1880 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_2'
1882 INTEGER :: handle, n
1885 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1886 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1887 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1888 IF (n /=
SIZE(c_out, 1)) cpabort(
"Incompatible (rows) result array 3 (C).")
1889 IF (n /=
SIZE(c_out, 2)) cpabort(
"Incompatible (cols) result array 3 (C).")
1890 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1891 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1892 a_trans ==
'C' .OR. a_trans ==
'c')) &
1893 cpabort(
"Unknown transpose character for array 1 (A).")
1894 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1895 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1896 b_trans ==
'C' .OR. b_trans ==
'c')) &
1897 cpabort(
"Unknown transpose character for array 2 (B).")
1899 CALL timeset(routinen, handle)
1901 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, c_out, n)
1903 CALL timestop(handle)
1905 END SUBROUTINE dgemm_square_2
1918 SUBROUTINE zgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
1919 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: A_in
1920 CHARACTER,
INTENT(IN) :: A_trans
1921 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: B_in
1922 CHARACTER,
INTENT(IN) :: B_trans
1923 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: C_in
1924 CHARACTER,
INTENT(IN) :: C_trans
1925 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(INOUT) :: D_out
1927 CHARACTER(len=*),
PARAMETER :: routineN =
'zgemm_square_3'
1929 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
1930 INTEGER :: handle, n
1933 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1934 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1935 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1936 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
1937 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
1938 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
1939 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
1940 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
1941 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
1942 a_trans ==
'C' .OR. a_trans ==
'c')) &
1943 cpabort(
"Unknown transpose character for array 1 (A).")
1944 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
1945 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
1946 b_trans ==
'C' .OR. b_trans ==
'c')) &
1947 cpabort(
"Unknown transpose character for array 2 (B).")
1948 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
1949 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
1950 c_trans ==
'C' .OR. c_trans ==
'c')) &
1951 cpabort(
"Unknown transpose character for array 3 (C).")
1953 CALL timeset(routinen, handle)
1955 ALLOCATE (work(n, n), source=
z_zero)
1957 CALL zgemm(a_trans, b_trans, n, n, n,
z_one, a_in, n, b_in, n,
z_zero, work, n)
1958 CALL zgemm(
'N', c_trans, n, n, n,
z_one, work, n, c_in, n,
z_zero, d_out, n)
1962 CALL timestop(handle)
1964 END SUBROUTINE zgemm_square_3
1977 SUBROUTINE dgemm_square_3(A_in, A_trans, B_in, B_trans, C_in, C_trans, D_out)
1978 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: a_in
1979 CHARACTER,
INTENT(IN) :: A_trans
1980 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: b_in
1981 CHARACTER,
INTENT(IN) :: B_trans
1982 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(IN) :: c_in
1983 CHARACTER,
INTENT(IN) :: C_trans
1984 REAL(kind=
dp),
DIMENSION(:, :),
INTENT(INOUT) :: d_out
1986 CHARACTER(len=*),
PARAMETER :: routineN =
'dgemm_square_3'
1988 INTEGER :: handle, n
1989 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: work
1992 IF (n /=
SIZE(a_in, 2)) cpabort(
"Non-square array 1 (A).")
1993 IF (n /=
SIZE(b_in, 1)) cpabort(
"Incompatible (rows) array 2 (B).")
1994 IF (n /=
SIZE(b_in, 2)) cpabort(
"Non-square array 2 (B).")
1995 IF (n /=
SIZE(c_in, 1)) cpabort(
"Incompatible (rows) array 3 (C).")
1996 IF (n /=
SIZE(c_in, 2)) cpabort(
"Non-square array 3 (C).")
1997 IF (n /=
SIZE(d_out, 1)) cpabort(
"Incompatible (rows) result array 4 (D).")
1998 IF (n /=
SIZE(d_out, 2)) cpabort(
"Incompatible (cols) result array 4 (D).")
1999 IF (.NOT. (a_trans ==
'N' .OR. a_trans ==
'n' .OR. &
2000 a_trans ==
'T' .OR. a_trans ==
't' .OR. &
2001 a_trans ==
'C' .OR. a_trans ==
'c')) &
2002 cpabort(
"Unknown transpose character for array 1 (A).")
2003 IF (.NOT. (b_trans ==
'N' .OR. b_trans ==
'n' .OR. &
2004 b_trans ==
'T' .OR. b_trans ==
't' .OR. &
2005 b_trans ==
'C' .OR. b_trans ==
'c')) &
2006 cpabort(
"Unknown transpose character for array 2 (B).")
2007 IF (.NOT. (c_trans ==
'N' .OR. c_trans ==
'n' .OR. &
2008 c_trans ==
'T' .OR. c_trans ==
't' .OR. &
2009 c_trans ==
'C' .OR. c_trans ==
'c')) &
2010 cpabort(
"Unknown transpose character for array 3 (C).")
2012 CALL timeset(routinen, handle)
2014 ALLOCATE (work(n, n), source=0.0_dp)
2016 CALL dgemm(a_trans, b_trans, n, n, n, 1.0_dp, a_in, n, b_in, n, 0.0_dp, work, n)
2017 CALL dgemm(
'N', c_trans, n, n, n, 1.0_dp, work, n, c_in, n, 0.0_dp, d_out, n)
2021 CALL timestop(handle)
2023 END SUBROUTINE dgemm_square_3
2034 COMPLEX(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: a_in, b_in
2035 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigenvalues
2036 COMPLEX(KIND=dp),
DIMENSION(:, :),
INTENT(OUT) :: eigenvectors
2038 CHARACTER(len=*),
PARAMETER :: routinen =
'geeig_right'
2039 COMPLEX(KIND=dp),
PARAMETER :: cone = cmplx(1.0_dp, 0.0_dp, kind=
dp), &
2040 czero = cmplx(0.0_dp, 0.0_dp, kind=
dp)
2042 COMPLEX(KIND=dp),
ALLOCATABLE,
DIMENSION(:) :: cevals
2043 COMPLEX(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: a, b, work
2044 INTEGER :: handle, i, icol, irow, lda, ldb, ldc, &
2045 nao, nc, ncol, nmo, nx
2046 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: evals
2048 CALL timeset(routinen, handle)
2052 nmo =
SIZE(eigenvalues)
2053 ALLOCATE (evals(nao), cevals(nao))
2054 ALLOCATE (work(nao, nao), b(nao, nao), a(nao, nao))
2055 a(:, :) = a_in(:, :)
2056 b(:, :) = b_in(:, :)
2061 evals(:) = -evals(:)
2064 IF (evals(i) < -1.0_dp)
THEN
2075 CALL zcopy(ncol*nao, work(1, nc + 1), 1, eigenvectors(1, nc + 1), 1)
2078 DO icol = nc + 1, nao
2080 work(irow, icol) = czero
2084 evals(nc + 1:nao) = 1.0_dp
2087 cevals(:) = cmplx(1.0_dp/sqrt(evals(:)), 0.0_dp, kind=
dp)
2088 DO i = 1, min(
SIZE(work, 2),
SIZE(cevals))
2089 CALL zscal(min(
SIZE(work, 2),
SIZE(cevals)), cevals(i), work(1, i), 1)
2096 DO icol = nc + 1, nao
2097 a(icol, icol) = 10000*cone
2102 eigenvalues(1:nmo) = evals(1:nmo)
2107 ldc =
SIZE(eigenvectors, 1)
2108 CALL zgemm(
"N",
"N", nao, nx, nc, cone, work, &
2109 lda, b, ldb, czero, eigenvectors, ldc)
2111 DEALLOCATE (evals, cevals, work, b, a)
2113 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.