68 USE ieee_arithmetic,
ONLY: ieee_is_finite
77 USE iso_fortran_env,
ONLY: iostat_end
92#include "../base/base_uses.f90"
97 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'bfgs_optimizer'
100 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: lindh_alpha(3, 3) = &
101 reshape([1.0_dp, 0.3494_dp, 0.3494_dp, &
102 0.3949_dp, 0.2800_dp, 0.2800_dp, &
103 0.3949_dp, 0.2800_dp, 0.1800_dp], [3, 3])
104 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: lindh_r0(3, 3) = &
105 reshape([1.35_dp, 2.10_dp, 2.53_dp, &
106 2.10_dp, 2.87_dp, 3.40_dp, &
107 2.53_dp, 3.40_dp, 3.40_dp], [3, 3])
108 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: lindh_cutoff = 6.0_dp
109 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: lindh_stretch_factor = 0.45_dp
110 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: lindh_angle_factor = 0.15_dp
111 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: lindh_denom_floor = 0.01_dp
112 LOGICAL,
PARAMETER :: debug_this_module = .true.
115 CHARACTER(LEN=16),
PARAMETER :: bfgs_restart_magic =
"CP2K BFGS STATE "
116 INTEGER,
PARAMETER :: bfgs_restart_version = 1
117 REAL(KIND=
dp),
PARAMETER :: min_hessian_eigenvalue = 1.0e-4_dp
134 RECURSIVE SUBROUTINE geoopt_bfgs(force_env, gopt_param, globenv, geo_section, gopt_env, x0)
141 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0
143 CHARACTER(len=*),
PARAMETER :: routinen =
'geoopt_bfgs'
144 REAL(kind=
dp),
PARAMETER :: one = 1.0_dp, zero = 0.0_dp
146 CHARACTER(LEN=5) :: wildcard
147 INTEGER :: handle, info, iter_nr, its, &
148 matrix_method, maxiter, ndf, &
150 LOGICAL :: conv, hesrest, hess_reset, inverse, &
151 shell_present, should_stop, &
153 REAL(kind=
dp) :: ediff, emin, eold, etot, pred, rad, rat, &
154 step, t_diff, t_now, t_old
155 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: dg, dr, dx, eigval, gold, work, xold
156 REAL(kind=
dp),
DIMENSION(:),
POINTER :: g
160 TYPE(
cp_fm_type) :: eigvec_mat, hess_mat, hess_tmp
167 NULLIFY (logger, g, blacs_env, spgr)
169 para_env => force_env%para_env
170 root_section => force_env%root_section
171 spgr => gopt_env%spgr
174 CALL timeset(routinen, handle)
179 maxiter = gopt_param%max_iter
185 SELECT CASE (gopt_env%type_id)
187 cpabort(
"BFGS method not yet working with DIMER")
193 IF (inverse .AND. use_rfo)
THEN
194 CALL cp_abort(__location__, &
195 "BFGS METHOD INVERSE does not support USE_RAT_FUN_OPT")
198 IF (.NOT. ieee_is_finite(rad) .OR. rad <= 0.0_dp)
THEN
199 CALL cp_abort(__location__, &
200 "BFGS TRUST_RADIUS must be finite and positive")
205 IF (output_unit > 0)
THEN
207 WRITE (unit=output_unit, fmt=
"(/,T2,A)")
"BFGS| Matrix update method: INVERSE"
209 WRITE (unit=output_unit, fmt=
"(/,T2,A)")
"BFGS| Matrix update method: DIRECT"
212 WRITE (unit=output_unit, fmt=
"(/,T2,A,T78,A3)") &
213 "BFGS| Use rational function optimization for step estimation: ",
"YES"
215 WRITE (unit=output_unit, fmt=
"(/,T2,A,T78,A3)") &
216 "BFGS| Use rational function optimization for step estimation: ",
" NO"
218 IF (use_mod_hes)
THEN
219 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A3)") &
220 "BFGS| Use model Hessian for initial guess: ",
"YES"
222 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A3)") &
223 "BFGS| Use model Hessian for initial guess: ",
" NO"
226 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A3)") &
227 "BFGS| Restart Hessian: ",
"YES"
229 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A3)") &
230 "BFGS| Restart Hessian: ",
" NO"
232 WRITE (unit=output_unit, fmt=
"(T2,A,T61,F20.3)") &
233 "BFGS| Trust radius: ", rad
237 IF (ndf > 3000 .AND. .NOT. inverse)
THEN
238 CALL cp_warn(__location__, &
239 "The dimension of the Hessian matrix ("// &
240 trim(adjustl(
cp_to_string(ndf)))//
") is greater than 3000. "// &
241 "The diagonalisation of the full Hessian matrix needed for BFGS "// &
242 "is computationally expensive. You should consider to use the linear "// &
243 "scaling variant L-BFGS instead.")
248 globenv%blacs_repeatable)
250 nrow_global=ndf, ncol_global=ndf)
251 CALL cp_fm_create(hess_mat, fm_struct_hes, name=
"hess_mat")
256 IF (use_mod_hes)
THEN
257 IF (shell_present)
THEN
258 CALL cp_warn(__location__, &
259 "No model Hessian is available for core-shell models. "// &
260 "A unit matrix is used as the initial Hessian.")
261 use_mod_hes = .false.
264 CALL cp_warn(__location__, &
265 "No model Hessian is available for cell optimizations. "// &
266 "A unit matrix is used as the initial Hessian.")
267 use_mod_hes = .false.
274 IF (.NOT. inverse .OR. (use_mod_hes .AND. .NOT. hesrest))
THEN
275 CALL cp_fm_create(hess_tmp, fm_struct_hes, name=
"hess_tmp")
276 CALL cp_fm_create(eigvec_mat, fm_struct_hes, name=
"eigvec_mat")
277 ALLOCATE (eigval(ndf))
282 IF (use_mod_hes .AND. .NOT. hesrest)
THEN
283 CALL build_initial_hess(hess_mat, hess_tmp, eigvec_mat, eigval, force_env, &
289 CALL build_initial_hess(hess_mat, hess_tmp, eigvec_mat, eigval, force_env, &
290 use_mod_hes, .false.)
293 IF (inverse .AND.
ALLOCATED(eigval))
THEN
300 IF (hesrest)
CALL read_bfgs_hessian(geo_section, hess_mat, logger, gopt_env, x0, matrix_method)
324 IF (spgr%keep_space_group)
THEN
331 CALL cp_iterate(logger%iter_info, increment=0, iter_nr_out=iter_nr)
335 CALL cp_eval_at(gopt_env, x0, etot, g, master=gopt_env%force_env%para_env%mepos, &
336 para_env=gopt_env%force_env%para_env)
339 IF (spgr%keep_space_group)
THEN
347 t_diff = t_now - t_old
349 CALL gopt_f_io_init(gopt_env, output_unit, etot, wildcard=wildcard, its=iter_nr, used_time=t_diff)
350 DO its = iter_nr + 1, maxiter
351 CALL cp_iterate(logger%iter_info, last=(its == maxiter))
355 IF ((its - iter_nr) > 1)
THEN
357 IF (spgr%keep_space_group)
THEN
363 dx(:) = x0(:) - xold(:)
364 dg(:) = g(:) - gold(:)
366 CALL bfgs_inverse_update(ndf, dx, dg, hess_mat, work)
368 CALL bfgs(ndf, dx, dg, hess_mat, work, para_env, output_unit, hess_reset)
370 CALL build_initial_hess(hess_mat, hess_tmp, eigvec_mat, eigval, force_env, &
371 use_mod_hes, .false.)
375 IF (spgr%keep_space_group)
THEN
381 CALL write_bfgs_hessian(geo_section, hess_mat, logger, gopt_env, matrix_method)
386 IF (spgr%keep_space_group)
THEN
396 CALL bfgs_inverse_step(hess_mat, g, dr)
405 IF (output_unit > 0)
THEN
406 WRITE (output_unit, *) &
407 "BFGS: Matrix diagonalization failed, resetting Hessian to unity."
415 CALL set_hes_eig(ndf, eigval, work)
417 CALL rat_fun_opt(ndf, dg, eigval, work, eigvec_mat, g, para_env)
419 CALL geoopt_get_step(ndf, eigval, eigvec_mat, hess_tmp, dr, g, para_env, use_rfo)
423 CALL bfgs_project_cell_step(gopt_env, dr)
427 IF (spgr%keep_space_group)
THEN
434 step = maxval(abs(dr))
441 CALL trust_radius(ndf, step, rad, rat, dr, output_unit)
448 IF (spgr%keep_space_group)
THEN
455 CALL cp_eval_at(gopt_env, x0, etot, g, master=gopt_env%force_env%para_env%mepos, &
456 para_env=gopt_env%force_env%para_env)
459 dr(:) = x0(:) - xold(:)
460 step = maxval(abs(dr))
463 IF (.NOT. inverse)
CALL energy_predict(ndf, work, hess_mat, dr, gold, pred, para_env)
468 IF (spgr%keep_space_group)
THEN
474 IF (should_stop)
EXIT
478 t_diff = t_now - t_old
481 CALL gopt_f_io(gopt_env, force_env, root_section, its, etot, output_unit, &
482 eold, emin, wildcard, gopt_param, ndf, dr, g, conv, &
483 rat=rat, step=step, rad=rad, used_time=t_diff)
485 CALL gopt_f_io(gopt_env, force_env, root_section, its, etot, output_unit, &
486 eold, emin, wildcard, gopt_param, ndf, dr, g, conv, pred, rat, &
487 step, rad, used_time=t_diff)
490 IF (conv .OR. (its == maxiter))
EXIT
491 IF (etot < emin) emin = etot
492 IF (use_rfo)
CALL update_trust_rad(rat, rad, step, ediff)
495 IF (its == maxiter .AND. (.NOT. conv))
THEN
500 IF (spgr%show_space_group)
THEN
506 CALL cp_iterate(logger%iter_info, last=.true., increment=0)
507 CALL write_bfgs_hessian(geo_section, hess_mat, logger, gopt_env, matrix_method)
509 gopt_env%force_env%para_env, gopt_env%force_env%para_env%mepos, output_unit)
513 IF (.NOT. inverse)
THEN
524 IF (
ALLOCATED(eigval))
DEALLOCATE (eigval)
529 "PRINT%PROGRAM_RUN_INFO")
530 CALL timestop(handle)
542 SUBROUTINE bfgs_inverse_update(ndf, dx, dg, hess_mat, work)
543 INTEGER,
INTENT(IN) :: ndf
544 REAL(kind=
dp),
INTENT(IN) :: dx(ndf), dg(ndf)
546 REAL(kind=
dp),
INTENT(OUT) :: work(ndf)
548 REAL(kind=
dp),
PARAMETER :: min_curvature = 0.2_dp
550 INTEGER :: handle, i, ig, invalid, j, jg, nc, nr
551 INTEGER,
DIMENSION(:),
POINTER :: cols, rows
552 REAL(kind=
dp) :: coeff, rho, sy, theta, yhy
553 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
555 REAL(kind=
dp),
DIMENSION(ndf) :: secant
557 CALL timeset(
"bfgs_inverse_update", handle)
558 IF (.NOT. all(ieee_is_finite(dx)) .OR. .NOT. all(ieee_is_finite(dg)))
THEN
559 cpabort(
"Non-finite displacement or gradient difference in inverse BFGS")
562 IF (norm2(dx) == 0.0_dp .OR. norm2(dg) == 0.0_dp)
THEN
563 CALL timestop(handle)
568 sy = dot_product(dx, dg)
569 yhy = dot_product(dg, work)
570 IF (.NOT. ieee_is_finite(sy) .OR. .NOT. ieee_is_finite(yhy))
THEN
571 cpabort(
"Non-finite curvature in inverse BFGS")
573 IF (yhy <= 0.0_dp)
THEN
574 CALL cp_warn(__location__, &
575 "BFGS: non-positive inverse curvature; resetting to unity.")
577 CALL timestop(handle)
582 IF (sy < min_curvature*yhy)
THEN
585 theta = ((1.0_dp - min_curvature)*yhy)/(yhy - sy)
586 secant = theta*dx + (1.0_dp - theta)*work
587 sy = dot_product(secant, dg)
589 IF (sy <= tiny(1.0_dp)/epsilon(1.0_dp))
THEN
590 CALL timestop(handle)
594 coeff = (1.0_dp + yhy*rho)*rho
595 IF (.NOT. ieee_is_finite(coeff))
THEN
596 CALL cp_warn(__location__, &
597 "BFGS: unrepresentable inverse update; retaining the previous matrix.")
598 CALL timestop(handle)
602 CALL cp_fm_get_info(hess_mat, row_indices=rows, col_indices=cols, &
603 local_data=
DATA, nrow_local=nr, ncol_local=nc)
609 DATA(i, j) =
DATA(i, j) + coeff*(secant(ig)*secant(jg)) - &
610 rho*(secant(ig)*work(jg) + work(ig)*secant(jg))
615 IF (.NOT. all(ieee_is_finite(
DATA(1:nr, 1:nc)))) invalid = 1
616 CALL hess_mat%matrix_struct%para_env%max(invalid)
617 IF (invalid /= 0)
THEN
618 CALL cp_warn(__location__, &
619 "BFGS: non-finite inverse matrix; resetting to unity.")
622 CALL timestop(handle)
623 END SUBROUTINE bfgs_inverse_update
631 SUBROUTINE bfgs_inverse_step(hess_mat, g, dr)
633 REAL(kind=
dp),
INTENT(IN) :: g(:)
634 REAL(kind=
dp),
INTENT(OUT) :: dr(:)
636 REAL(kind=
dp) :: slope
638 IF (.NOT. all(ieee_is_finite(g)))
THEN
639 CALL cp_abort(__location__,
"Non-finite gradient in inverse BFGS")
642 IF (maxval(abs(g)) == 0.0_dp)
RETURN
644 slope = dot_product(g, dr)
645 IF (.NOT. ieee_is_finite(slope) .OR. slope >= 0.0_dp)
THEN
646 CALL cp_warn(__location__, &
647 "BFGS: inverse matrix is not a descent model; resetting to unity.")
651 END SUBROUTINE bfgs_inverse_step
658 SUBROUTINE bfgs_project_cell_step(gopt_env, dr)
660 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT),
TARGET :: dr
662 REAL(kind=
dp),
DIMENSION(:),
POINTER :: cell_step
664 cell_step => dr(
SIZE(dr) - 5:
SIZE(dr))
666 gopt_env%cell_env%keep_angles, gopt_env%cell_env%keep_symmetry, &
667 gopt_env%cell_env%constraint_id)
668 END SUBROUTINE bfgs_project_cell_step
675 SUBROUTINE bfgs_invert_matrix(matrix, from_inverse)
677 LOGICAL,
INTENT(IN) :: from_inverse
679 INTEGER :: handle, info, ndf
680 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenvalues
684 CALL timeset(
"bfgs_invert_matrix", handle)
685 CALL cp_fm_get_info(matrix, matrix_struct=matrix_struct, nrow_global=ndf)
686 CALL cp_fm_create(scratch, matrix_struct, name=
"bfgs_restart_scratch")
687 CALL cp_fm_create(eigenvectors, matrix_struct, name=
"bfgs_restart_eigenvectors")
688 ALLOCATE (eigenvalues(ndf))
692 CALL cp_abort(__location__,
"BFGS restart matrix diagonalization failed")
694 IF (.NOT. all(ieee_is_finite(eigenvalues)))
THEN
695 CALL cp_abort(__location__,
"Non-finite BFGS restart spectrum")
697 IF (from_inverse)
THEN
699 IF (minval(eigenvalues) <= 0.0_dp)
THEN
700 CALL cp_abort(__location__, &
701 "BFGS inverse restart matrix is not positive definite")
704 IF (minval(eigenvalues) < min_hessian_eigenvalue)
THEN
705 CALL cp_warn(__location__, &
706 "BFGS: regularizing the direct restart before conversion to INVERSE.")
708 eigenvalues(:) = max(min_hessian_eigenvalue, eigenvalues(:))
710 eigenvalues(:) = 1.0_dp/eigenvalues(:)
711 IF (.NOT. all(ieee_is_finite(eigenvalues)))
THEN
712 CALL cp_abort(__location__, &
713 "Unrepresentable inverse of BFGS restart matrix")
717 CALL parallel_gemm(
"N",
"T", ndf, ndf, ndf, 1.0_dp, scratch, eigenvectors, 0.0_dp, matrix)
720 DEALLOCATE (eigenvalues)
721 CALL timestop(handle)
722 END SUBROUTINE bfgs_invert_matrix
735 reference_cell, cell_frame)
736 INTEGER,
INTENT(IN) :: unit
737 INTEGER,
INTENT(OUT) :: stored_method, stored_ndf, stored_type
738 LOGICAL,
INTENT(OUT) :: tagged
739 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: reference_cell, cell_frame
741 CHARACTER(LEN=16) :: magic
742 INTEGER :: ios, version
747 reference_cell = 0.0_dp
750 READ (unit, iostat=ios) magic
751 tagged = ios == 0 .AND. magic == bfgs_restart_magic
754 READ (unit, iostat=ios) magic, version, stored_method, stored_ndf, stored_type, &
755 reference_cell, cell_frame
756 IF (ios /= 0) cpabort(
"Invalid BFGS restart header")
757 IF (version /= bfgs_restart_version)
THEN
758 CALL cp_abort(__location__,
"Unsupported BFGS restart version")
761 cpabort(
"Unknown matrix representation in BFGS restart")
763 IF (stored_ndf <= 0) cpabort(
"Invalid matrix dimension in BFGS restart")
764 IF (.NOT. all(ieee_is_finite(reference_cell)) .OR. .NOT. all(ieee_is_finite(cell_frame)))
THEN
765 cpabort(
"Non-finite coordinate frame in BFGS restart")
780 SUBROUTINE bfgs_read_header(unit, ndf, opt_type, stored_method, tagged, reference_cell, cell_frame)
781 INTEGER,
INTENT(IN) :: unit, ndf, opt_type
782 INTEGER,
INTENT(OUT) :: stored_method
783 LOGICAL,
INTENT(OUT) :: tagged
784 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(OUT) :: reference_cell, cell_frame
786 INTEGER :: ios, j, stored_ndf, stored_type
787 REAL(kind=
dp) :: extra
788 REAL(kind=
dp),
DIMENSION(ndf) :: column
791 reference_cell, cell_frame)
793 IF (stored_ndf /= ndf)
THEN
794 CALL cp_abort(__location__, &
795 "BFGS restart dimension does not match the optimization variables")
797 IF (stored_type /= opt_type)
THEN
798 CALL cp_abort(__location__,
"BFGS restart optimization type does not match")
805 READ (unit, iostat=ios) column
807 CALL cp_abort(__location__, &
808 "Truncated BFGS restart or incompatible legacy matrix dimension")
810 IF (.NOT. all(ieee_is_finite(column)))
THEN
811 CALL cp_abort(__location__,
"Non-finite matrix in BFGS restart")
814 READ (unit, iostat=ios) extra
815 IF (ios /= iostat_end)
THEN
816 CALL cp_abort(__location__, &
817 "Extra matrix columns or invalid trailing data in BFGS restart")
820 IF (tagged)
READ (unit)
821 END SUBROUTINE bfgs_read_header
832 SUBROUTINE read_bfgs_hessian(geo_section, hess_mat, logger, gopt_env, x0, matrix_method)
837 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: x0
838 INTEGER,
INTENT(IN) :: matrix_method
840 CHARACTER(LEN=default_path_length) :: filename
841 INTEGER :: ndf, stored_method, unit
843 REAL(kind=
dp),
DIMENSION(3, 3) :: cell_frame, reference_cell
846 para_env => gopt_env%force_env%para_env
849 IF (para_env%is_source())
THEN
851 IF (len_trim(filename) == 0) filename = trim(logger%iter_info%project_name)//
"-BFGS.Hessian"
852 CALL open_file(file_name=trim(filename), file_status=
"OLD", &
853 file_form=
"UNFORMATTED", file_action=
"READ", unit_number=unit)
854 CALL bfgs_read_header(unit, ndf, gopt_env%type_id, stored_method, tagged, reference_cell, cell_frame)
856 CALL para_env%bcast(stored_method, 0)
857 CALL para_env%bcast(tagged, 0)
858 CALL para_env%bcast(reference_cell, 0)
859 CALL para_env%bcast(cell_frame, 0)
861 IF (para_env%is_source())
CALL close_file(unit_number=unit)
865 CALL bfgs_restore_cell_frame(gopt_env, x0, reference_cell, cell_frame)
867 CALL cp_warn(__location__,
"Legacy BFGS restart has no reference cell; "// &
868 "assuming the current CELL_OPT coordinate frame. Exact frame recovery is not possible.")
871 IF (stored_method /= matrix_method)
THEN
872 CALL bfgs_invert_matrix(hess_mat, stored_method ==
bfgs_inverse)
874 END SUBROUTINE read_bfgs_hessian
883 SUBROUTINE bfgs_restore_cell_frame(gopt_env, x0, reference_cell, cell_frame)
885 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: x0
886 REAL(kind=
dp),
DIMENSION(3, 3),
INTENT(IN) :: reference_cell, cell_frame
889 REAL(kind=
dp),
DIMENSION(3, 3) :: transform
893 IF (maxval(abs(cell_frame - gopt_env%cell_env%opt_to_input)) > 1.0e-8_dp)
THEN
894 CALL cp_abort(__location__, &
895 "BFGS restart cell orientation differs; use a matching structure or RESTART_HESSIAN F")
897 IF (abs(
det_3x3(reference_cell)) <= epsilon(1.0_dp)*maxval(abs(reference_cell))**3)
THEN
898 cpabort(
"Singular reference cell in BFGS restart")
900 transform = matmul(reference_cell,
inv_3x3(gopt_env%h_ref))
901 DO i = 1,
SIZE(x0) - 6, 3
902 x0(i:i + 2) = matmul(transform, x0(i:i + 2))
904 gopt_env%h_ref = reference_cell
905 END SUBROUTINE bfgs_restore_cell_frame
917 SUBROUTINE rat_fun_opt(ndf, dg, eigval, work, eigvec_mat, g, para_env)
919 INTEGER,
INTENT(IN) :: ndf
920 REAL(kind=
dp),
INTENT(INOUT) :: dg(ndf), eigval(ndf), work(ndf)
922 REAL(kind=
dp),
INTENT(INOUT) :: g(ndf)
925 CHARACTER(LEN=*),
PARAMETER :: routinen =
'rat_fun_opt'
926 REAL(kind=
dp),
PARAMETER :: one = 1.0_dp
928 INTEGER :: handle, i, indf, iref, iter, j, k, l, &
929 maxit, ncol_local, nrow_local
930 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
931 LOGICAL :: bisec, conv, fail, set
932 REAL(kind=
dp) :: fun, fun1, fun2, fun3, fung, lam1, lam2, &
933 ln, lp, ssize, step, stol
934 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
935 POINTER :: local_data
937 CALL timeset(routinen, handle)
947 CALL cp_fm_get_info(eigvec_mat, row_indices=row_indices, col_indices=col_indices, &
948 local_data=local_data, nrow_local=nrow_local, ncol_local=ncol_local)
954 dg(l) = dg(l) + local_data(i, k)*g(j)
957 CALL para_env%sum(dg)
968 IF (eigval(iref) < 0.0_dp) ln = eigval(iref) - 0.01_dp
977 fun = fun + dg(indf)**2/(ln - eigval(indf))
978 fung = fung - dg(indf)**2/((ln - eigval(indf))**2)
984 IF (abs(step) < stol)
THEN
988 IF (iter >= maxit)
EXIT
996 IF (eigval(iref) < 0.0_dp) lam1 = eigval(iref) - 0.01_dp
999 fun1 = fun1 + dg(indf)**2/(lam1 - eigval(indf))
1002 step = abs(lam1)/1000.0_dp
1003 IF (step < ssize) step = ssize
1006 IF (iter > maxit)
THEN
1013 lam2 = lam1 - iter*step
1015 fun2 = fun2 + dg(indf)**2/(lam2 - eigval(indf))
1018 IF (fun2*fun1 < 0.0_dp)
THEN
1022 IF (iter > maxit)
THEN
1028 step = (lam1 + lam2)/2
1031 fun3 = fun3 + dg(indf)**2/(step - eigval(indf))
1035 IF (abs(step - lam2) < stol)
THEN
1040 IF (fun3*fun1 < stol)
THEN
1049 IF ((ln > eigval(iref)) .OR. ((ln > 0.0_dp) .AND. &
1050 (eigval(iref) > 0.0_dp)))
THEN
1052 IF (.NOT. bisec)
THEN
1063 IF (fail .AND. .NOT. set)
THEN
1066 eigval(indf) = eigval(indf)*work(indf)
1076 eigval(indf) = eigval(indf) - ln
1081 CALL timestop(handle)
1083 END SUBROUTINE rat_fun_opt
1097 SUBROUTINE bfgs(ndf, dx, dg, hess_mat, work, para_env, output_unit, hess_reset)
1098 INTEGER,
INTENT(IN) :: ndf
1099 REAL(kind=
dp),
INTENT(INOUT) :: dx(ndf), dg(ndf)
1101 REAL(kind=
dp),
INTENT(INOUT) :: work(ndf)
1103 INTEGER,
INTENT(IN) :: output_unit
1104 LOGICAL,
INTENT(OUT) :: hess_reset
1106 CHARACTER(LEN=*),
PARAMETER :: routinen =
'bfgs'
1107 INTEGER,
PARAMETER :: exit_reset = 2, exit_skip = 1, &
1109 REAL(kind=
dp),
PARAMETER :: min_curvature = 0.2_dp, one = 1.0_dp, &
1110 min_sbs = 10.0_dp*tiny(one), &
1113 INTEGER :: exit_flag, handle, i, invalid, j, k, l, &
1114 ncol_local, nrow_local
1115 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1116 REAL(kind=
dp) :: dxw, eta_i, eta_j, gdx, sbs, seta, sy, &
1118 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1119 POINTER :: local_hes
1121 CALL timeset(routinen, handle)
1122 hess_reset = .false.
1124 CALL cp_fm_get_info(hess_mat, row_indices=row_indices, col_indices=col_indices, &
1125 local_data=local_hes, nrow_local=nrow_local, ncol_local=ncol_local)
1128 IF (.NOT. all(ieee_is_finite(dx(1:ndf))) .OR. .NOT. all(ieee_is_finite(dg(1:ndf))))
THEN
1129 cpabort(
"Non-finite displacement or gradient difference")
1133 DO i = 1, nrow_local
1135 DO k = 1, ncol_local
1137 work(j) = work(j) + local_hes(i, k)*dx(l)
1141 IF (
PRESENT(para_env))
CALL para_env%sum(work)
1143 sy = dot_product(dg(1:ndf), dx(1:ndf))
1144 sbs = dot_product(dx(1:ndf), work(1:ndf))
1153 exit_flag = exit_update
1154 IF (dot_product(dx(1:ndf), dx(1:ndf)) == zero .OR. &
1155 dot_product(dg(1:ndf), dg(1:ndf)) == zero)
THEN
1156 exit_flag = exit_skip
1157 ELSE IF (.NOT. ieee_is_finite(sy) .OR. .NOT. ieee_is_finite(sbs) .OR. &
1158 sbs <= max(epsilon(one)*abs(sy), min_sbs))
THEN
1159 exit_flag = exit_reset
1165 IF (
PRESENT(para_env))
CALL para_env%max(exit_flag)
1167 IF (exit_flag == exit_skip)
THEN
1170 ELSE IF (exit_flag == exit_reset)
THEN
1174 CALL cp_warn(__location__, &
1175 "BFGS: vanishing or non-positive predicted curvature, resetting the Hessian")
1187 IF (sy < min_curvature*sbs)
THEN
1188 theta = ((one - min_curvature)*sbs)/(sbs - sy)
1189 IF (output_unit > 0)
THEN
1190 WRITE (unit=output_unit, fmt=
"(T2,A,F10.4,A,F3.1,A)") &
1191 "BFGS| Damped update, curvature ratio y.s/(s.B.s): ", sy/sbs, &
1192 " (threshold ", min_curvature,
")"
1196 seta = theta*sy + (one - theta)*sbs
1200 DO i = 1, nrow_local
1202 eta_i = theta*dg(j) + (one - theta)*work(j)
1203 DO k = 1, ncol_local
1205 eta_j = theta*dg(l) + (one - theta)*work(l)
1206 local_hes(i, k) = local_hes(i, k) + gdx*eta_i*eta_j - &
1213 IF (.NOT. all(ieee_is_finite(local_hes(1:nrow_local, 1:ncol_local)))) invalid = 1
1214 IF (
PRESENT(para_env))
CALL para_env%max(invalid)
1215 IF (invalid /= 0)
THEN
1216 CALL cp_warn(__location__,
"BFGS: non-finite Hessian after the update, resetting")
1221 CALL timestop(handle)
1236 SUBROUTINE build_initial_hess(hess_mat, hess_tmp, eigvec, eigval, force_env, use_model, inverse)
1237 TYPE(
cp_fm_type),
INTENT(IN) :: hess_mat, hess_tmp, eigvec
1238 REAL(kind=
dp),
DIMENSION(:),
INTENT(OUT) :: eigval
1240 LOGICAL,
INTENT(IN) :: use_model, inverse
1242 CHARACTER(LEN=*),
PARAMETER :: routinen =
'build_initial_hess'
1243 REAL(kind=
dp),
PARAMETER :: min_eig = 0.1_dp, one = 1.0_dp, &
1246 INTEGER :: handle, indf, info, ndf
1248 CALL timeset(routinen, handle)
1251 cpassert(
ASSOCIATED(force_env))
1256 CALL construct_initial_hess(force_env, hess_mat)
1261 CALL cp_warn(__location__,
"BFGS: model Hessian diagonalization failed, using unity")
1266 IF (eigval(indf) < min_eig) eigval(indf) = min_eig
1267 IF (inverse) eigval(indf) = one/eigval(indf)
1271 CALL parallel_gemm(
"N",
"T", ndf, ndf, ndf, one, hess_tmp, eigvec, zero, hess_mat)
1281 CALL timestop(handle)
1283 END SUBROUTINE build_initial_hess
1291 SUBROUTINE set_hes_eig(ndf, eigval, work)
1292 INTEGER,
INTENT(IN) :: ndf
1293 REAL(kind=
dp),
INTENT(INOUT) :: eigval(ndf), work(ndf)
1295 CHARACTER(LEN=*),
PARAMETER :: routinen =
'set_hes_eig'
1296 REAL(kind=
dp),
PARAMETER :: max_eig = 1000.0_dp, max_neg = -0.5_dp, &
1297 max_pos = 5.0_dp, min_eig = 0.005_dp, &
1300 INTEGER :: handle, indf
1302 CALL timeset(routinen, handle)
1305 IF (eigval(indf) > max_eig) eigval(indf) = max_eig
1308 IF (eigval(indf) < 0.0_dp)
THEN
1309 IF (eigval(indf) < max_neg)
THEN
1310 eigval(indf) = max_neg
1311 ELSE IF (eigval(indf) > -min_eig)
THEN
1312 eigval(indf) = -min_eig
1314 ELSE IF (eigval(indf) < 1000.0_dp)
THEN
1315 IF (eigval(indf) < min_eig)
THEN
1316 eigval(indf) = min_eig
1317 ELSE IF (eigval(indf) > max_pos)
THEN
1318 eigval(indf) = max_pos
1324 IF (eigval(indf) < 0.0_dp)
THEN
1331 CALL timestop(handle)
1333 END SUBROUTINE set_hes_eig
1346 SUBROUTINE geoopt_get_step(ndf, eigval, eigvec_mat, hess_tmp, dr, g, para_env, use_rfo)
1348 INTEGER,
INTENT(IN) :: ndf
1349 REAL(kind=
dp),
INTENT(INOUT) :: eigval(ndf)
1350 TYPE(
cp_fm_type),
INTENT(IN) :: eigvec_mat, hess_tmp
1351 REAL(kind=
dp),
INTENT(INOUT) :: dr(ndf), g(ndf)
1355 REAL(kind=
dp),
PARAMETER :: one = 1.0_dp, zero = 0.0_dp
1357 INTEGER :: i, indf, j, k, l, ncol_local, nrow_local
1358 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1359 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1360 POINTER :: local_data
1367 eigval(indf) = one/eigval(indf)
1371 eigval(indf) = one/max(min_hessian_eigenvalue, eigval(indf))
1380 CALL parallel_gemm(
"N",
"T", ndf, ndf, ndf, one, hess_tmp, eigvec_mat, zero, tmp)
1387 CALL cp_fm_get_info(hess_tmp, row_indices=row_indices, col_indices=col_indices, &
1388 local_data=local_data, nrow_local=nrow_local, ncol_local=ncol_local)
1391 DO i = 1, nrow_local
1393 DO k = 1, ncol_local
1395 dr(j) = dr(j) - local_data(i, k)*g(l)
1399 CALL para_env%sum(dr)
1401 END SUBROUTINE geoopt_get_step
1412 SUBROUTINE trust_radius(ndf, step, rad, rat, dr, output_unit)
1413 INTEGER,
INTENT(IN) :: ndf
1414 REAL(kind=
dp),
INTENT(INOUT) :: step, rad, rat, dr(ndf)
1415 INTEGER,
INTENT(IN) :: output_unit
1417 CHARACTER(LEN=*),
PARAMETER :: routinen =
'trust_radius'
1418 REAL(kind=
dp),
PARAMETER :: one = 1.0_dp
1421 REAL(kind=
dp) :: scal
1423 CALL timeset(routinen, handle)
1425 step = maxval(abs(dr))
1426 scal = max(one, rad/step)
1428 IF (step > rad)
THEN
1430 CALL dscal(ndf, rat, dr, 1)
1432 IF (output_unit > 0)
THEN
1433 WRITE (unit=output_unit, fmt=
"(/,T2,A,F8.5)") &
1434 " Step is scaled; Scaling factor = ", rat
1438 CALL timestop(handle)
1440 END SUBROUTINE trust_radius
1452 SUBROUTINE energy_predict(ndf, work, hess_mat, dr, g, pred, para_env)
1454 INTEGER,
INTENT(IN) :: ndf
1455 REAL(kind=
dp),
INTENT(INOUT) :: work(ndf)
1457 REAL(kind=
dp),
INTENT(INOUT) :: dr(ndf), g(ndf), pred
1460 CHARACTER(LEN=*),
PARAMETER :: routinen =
'energy_predict'
1461 REAL(kind=
dp),
PARAMETER :: zero = 0.0_dp
1463 INTEGER :: handle, i, j, k, l, ncol_local, &
1465 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1466 REAL(kind=
dp) :: ener1, ener2
1467 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1468 POINTER :: local_data
1470 CALL timeset(routinen, handle)
1472 ener1 = dot_product(g(1:ndf), dr(1:ndf))
1474 CALL cp_fm_get_info(hess_mat, row_indices=row_indices, col_indices=col_indices, &
1475 local_data=local_data, nrow_local=nrow_local, ncol_local=ncol_local)
1478 DO i = 1, nrow_local
1480 DO k = 1, ncol_local
1482 work(j) = work(j) + local_data(i, k)*dr(l)
1486 CALL para_env%sum(work)
1487 ener2 = dot_product(dr(1:ndf), work(1:ndf))
1488 pred = ener1 + 0.5_dp*ener2
1489 CALL timestop(handle)
1491 END SUBROUTINE energy_predict
1500 SUBROUTINE update_trust_rad(rat, rad, step, ediff)
1502 REAL(kind=
dp),
INTENT(INOUT) :: rat, rad, step, ediff
1504 CHARACTER(LEN=*),
PARAMETER :: routinen =
'update_trust_rad'
1505 REAL(kind=
dp),
PARAMETER :: max_trust = 1.0_dp, min_trust = 0.1_dp
1509 CALL timeset(routinen, handle)
1511 IF (rat > 4.0_dp)
THEN
1512 IF (ediff < 0.0_dp)
THEN
1517 ELSE IF (rat > 2.0_dp)
THEN
1518 IF (ediff < 0.0_dp)
THEN
1523 ELSE IF (rat > 4.0_dp/3.0_dp)
THEN
1524 IF (ediff < 0.0_dp)
THEN
1529 ELSE IF (rat > 10.0_dp/9.0_dp)
THEN
1530 IF (ediff < 0.0_dp)
THEN
1535 ELSE IF (rat > 0.9_dp)
THEN
1536 IF (ediff < 0.0_dp)
THEN
1541 ELSE IF (rat > 0.75_dp)
THEN
1542 IF (ediff < 0.0_dp)
THEN
1547 ELSE IF (rat > 0.5_dp)
THEN
1548 IF (ediff < 0.0_dp)
THEN
1553 ELSE IF (rat > 0.25_dp)
THEN
1554 IF (ediff < 0.0_dp)
THEN
1559 ELSE IF (ediff < 0.0_dp)
THEN
1565 rad = max(rad, min_trust)
1566 rad = min(rad, max_trust)
1567 CALL timestop(handle)
1569 END SUBROUTINE update_trust_rad
1581 SUBROUTINE write_bfgs_hessian(geo_section, hess_mat, logger, gopt_env, matrix_method)
1587 INTEGER,
INTENT(IN) :: matrix_method
1589 CHARACTER(LEN=*),
PARAMETER :: routinen =
'write_bfgs_hessian'
1591 INTEGER :: handle, hesunit, ndf
1592 REAL(kind=
dp),
DIMENSION(3, 3) :: cell_frame
1594 CALL timeset(routinen, handle)
1599 extension=
".Hessian", file_form=
"UNFORMATTED", file_action=
"WRITE", &
1600 file_position=
"REWIND")
1601 IF (hesunit > 0)
THEN
1602 WRITE (hesunit) bfgs_restart_magic, bfgs_restart_version, matrix_method, ndf, &
1603 gopt_env%type_id, gopt_env%h_ref, cell_frame
1608 CALL timestop(handle)
1610 END SUBROUTINE write_bfgs_hessian
1618 SUBROUTINE construct_initial_hess(force_env, hess_mat)
1623 INTEGER :: i, iat_col, iat_row, iglobal, iind, j, &
1624 jat_row, jglobal, jind, k, natom, &
1625 ncol_local, nrow_local, z
1626 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: at_row
1627 INTEGER,
DIMENSION(:),
POINTER :: col_indices, row_indices
1628 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: d_ij, rho_ij
1629 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :, :) :: r_ij
1630 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
1631 POINTER :: fixed, local_data
1632 REAL(kind=
dp),
DIMENSION(3, 3) :: alpha, r0
1639 CALL force_env_get(force_env=force_env, subsys=subsys, cell=cell)
1641 particles=particles)
1646 CALL cp_fm_get_info(hess_mat, row_indices=row_indices, col_indices=col_indices, &
1647 local_data=local_data, nrow_local=nrow_local, ncol_local=ncol_local)
1648 natom = particles%n_els
1649 ALLOCATE (at_row(natom))
1650 ALLOCATE (rho_ij(natom, natom))
1651 ALLOCATE (d_ij(natom, natom))
1652 ALLOCATE (r_ij(natom, natom, 3))
1653 ALLOCATE (fixed(3, natom))
1657 CALL hess_mat%matrix_struct%para_env%min(fixed(i, :))
1663 IF (z <= 10) at_row(i) = 2
1664 IF (z <= 2) at_row(i) = 1
1671 r_ij(j, i, :) =
pbc(particles%els(i)%r, particles%els(j)%r, cell)
1672 r_ij(i, j, :) = -r_ij(j, i, :)
1673 d_ij(j, i) = norm2(r_ij(j, i, :))
1674 d_ij(i, j) = d_ij(j, i)
1675 rho_ij(j, i) = exp(alpha(jat_row, iat_row)*(r0(jat_row, iat_row)**2 - d_ij(j, i)**2))
1676 rho_ij(i, j) = rho_ij(j, i)
1679 DO i = 1, ncol_local
1680 iglobal = col_indices(i)
1681 iind = mod(iglobal - 1, 3) + 1
1682 iat_col = (iglobal + 2)/3
1683 IF (iat_col > natom) cycle
1684 DO j = 1, nrow_local
1685 jglobal = row_indices(j)
1686 jind = mod(jglobal - 1, 3) + 1
1687 iat_row = (jglobal + 2)/3
1688 IF (iat_row > natom) cycle
1689 IF (iat_row /= iat_col)
THEN
1690 IF (d_ij(iat_row, iat_col) < lindh_cutoff)
THEN
1691 local_data(j, i) = local_data(j, i) + &
1692 angle_second_deriv(r_ij, d_ij, rho_ij, iind, jind, iat_col, iat_row, natom)
1695 local_data(j, i) = local_data(j, i) + &
1696 angle_second_deriv(r_ij, d_ij, rho_ij, iind, jind, iat_col, iat_row, natom)
1698 IF (iat_col /= iat_row)
THEN
1699 IF (d_ij(iat_row, iat_col) < lindh_cutoff)
THEN
1700 local_data(j, i) = local_data(j, i) - &
1701 dist_second_deriv(r_ij(iat_col, iat_row, :), &
1702 iind, jind, d_ij(iat_row, iat_col), rho_ij(iat_row, iat_col))
1706 IF (k == iat_col) cycle
1707 IF (d_ij(iat_row, k) < lindh_cutoff)
THEN
1708 local_data(j, i) = local_data(j, i) + &
1709 dist_second_deriv(r_ij(iat_col, k, :), &
1710 iind, jind, d_ij(iat_row, k), rho_ij(iat_row, k))
1714 IF (fixed(jind, iat_row) < 0.5_dp .OR. fixed(iind, iat_col) < 0.5_dp)
THEN
1715 local_data(j, i) = 0.0_dp
1716 IF (jind == iind .AND. iat_row == iat_col) local_data(j, i) = 1.0_dp
1726 END SUBROUTINE construct_initial_hess
1737 PURE FUNCTION dist_second_deriv(r1, i, j, d, rho)
RESULT(deriv)
1738 REAL(kind=
dp),
DIMENSION(3),
INTENT(IN) :: r1
1739 INTEGER,
INTENT(IN) :: i, j
1740 REAL(kind=
dp),
INTENT(IN) :: d, rho
1741 REAL(kind=
dp) :: deriv
1743 deriv = lindh_stretch_factor*rho*(r1(i)*r1(j))/d**2
1744 END FUNCTION dist_second_deriv
1758 FUNCTION angle_second_deriv(r_ij, d_ij, rho_ij, idir, jdir, iat_der, jat_der, natom)
RESULT(deriv)
1759 REAL(kind=
dp),
DIMENSION(:, :, :) :: r_ij
1760 REAL(kind=
dp),
DIMENSION(:, :) :: d_ij, rho_ij
1761 INTEGER :: idir, jdir, iat_der, jat_der, natom
1762 REAL(kind=
dp) :: deriv
1764 REAL(kind=
dp),
PARAMETER :: rho_thre = 1.0e-5_dp
1766 INTEGER :: i, iat, idr, j, jat, jdr
1767 REAL(kind=
dp) :: d12, d23, d31, d_mat(3, 2), denom1, &
1768 denom2, denom3, ka1, ka2, ka3, rho12, &
1769 rho23, rho31, rsst1, rsst2, rsst3
1770 REAL(kind=
dp),
DIMENSION(3) :: r12, r23, r31
1773 IF (iat_der == jat_der)
THEN
1775 IF (rho_ij(iat_der, i) < rho_thre) cycle
1777 IF (rho_ij(iat_der, j) < rho_thre) cycle
1778 IF (i == iat_der .OR. j == iat_der) cycle
1779 IF (iat_der < i .OR. iat_der > j)
THEN
1780 r12 = r_ij(iat_der, i, :); r23 = r_ij(i, j, :); r31 = r_ij(j, iat_der, :)
1781 d12 = d_ij(iat_der, i); d23 = d_ij(i, j); d31 = d_ij(j, iat_der)
1782 rho12 = rho_ij(iat_der, i); rho23 = rho_ij(i, j); rho31 = rho_ij(j, iat_der)
1784 r12 = r_ij(iat_der, j, :); r23 = r_ij(j, i, :); r31 = r_ij(i, iat_der, :)
1785 d12 = d_ij(iat_der, j); d23 = d_ij(j, i); d31 = d_ij(i, iat_der)
1786 rho12 = rho_ij(iat_der, j); rho23 = rho_ij(j, i); rho31 = rho_ij(i, iat_der)
1788 ka1 = lindh_angle_factor*rho12*rho23; ka2 = lindh_angle_factor*rho23*rho31; ka3 = lindh_angle_factor*rho31*rho12
1789 rsst1 = dot_product(r12, r23); rsst2 = dot_product(r23, r31); rsst3 = dot_product(r31, r12)
1790 denom1 = 1.0_dp - rsst1**2/(d12**2*d23**2); denom2 = 1.0_dp - rsst2**2/(d23**2*d31**2)
1791 denom3 = 1.0_dp - rsst3**2/(d31**2*d12**2)
1792 denom1 = sign(1.0_dp, denom1)*max(abs(denom1), lindh_denom_floor)
1793 denom2 = sign(1.0_dp, denom2)*max(abs(denom2), lindh_denom_floor)
1794 denom3 = sign(1.0_dp, denom3)*max(abs(denom3), lindh_denom_floor)
1795 d_mat(1, 1) = r23(idir)/(d12*d23) - rsst1*r12(idir)/(d12**3*d23)
1796 d_mat(1, 2) = r23(jdir)/(d12*d23) - rsst1*r12(jdir)/(d12**3*d23)
1797 d_mat(2, 1) = -r23(idir)/(d23*d31) + rsst2*r31(idir)/(d23*d31**3)
1798 d_mat(2, 2) = -r23(jdir)/(d23*d31) + rsst2*r31(jdir)/(d23*d31**3)
1799 d_mat(3, 1) = (r31(idir) - r12(idir))/(d31*d12) + rsst3*r31(idir)/(d31**3*d12) - &
1800 rsst3*r12(idir)/(d31*d12**3)
1801 d_mat(3, 2) = (r31(jdir) - r12(jdir))/(d31*d12) + rsst3*r31(jdir)/(d31**3*d12) - &
1802 rsst3*r12(jdir)/(d31*d12**3)
1803 IF (abs(denom1) <= 0.011_dp) d_mat(1, 1) = 0.0_dp
1804 IF (abs(denom2) <= 0.011_dp) d_mat(2, 1) = 0.0_dp
1805 IF (abs(denom3) <= 0.011_dp) d_mat(3, 1) = 0.0_dp
1806 deriv = deriv + ka1*d_mat(1, 1)*d_mat(1, 2)/denom1 + &
1807 ka2*d_mat(2, 1)*d_mat(2, 2)/denom2 + &
1808 ka3*d_mat(3, 1)*d_mat(3, 2)/denom3
1814 IF (i == iat_der .OR. i == jat_der) cycle
1815 IF (jat_der < iat_der)
THEN
1816 iat = jat_der; jat = iat_der; idr = jdir; jdr = idir
1818 iat = iat_der; jat = jat_der; idr = idir; jdr = jdir
1820 IF (jat < i .OR. iat > i)
THEN
1821 r12 = r_ij(iat, jat, :); r23 = r_ij(jat, i, :); r31 = r_ij(i, iat, :)
1822 d12 = d_ij(iat, jat); d23 = d_ij(jat, i); d31 = d_ij(i, iat)
1823 rho12 = rho_ij(iat, jat); rho23 = rho_ij(jat, i); rho31 = rho_ij(i, iat)
1825 r12 = r_ij(iat, i, :); r23 = r_ij(i, jat, :); r31 = r_ij(jat, iat, :)
1826 d12 = d_ij(iat, i); d23 = d_ij(i, jat); d31 = d_ij(jat, iat)
1827 rho12 = rho_ij(iat, i); rho23 = rho_ij(i, jat); rho31 = rho_ij(jat, iat)
1829 ka1 = lindh_angle_factor*rho12*rho23; ka2 = lindh_angle_factor*rho23*rho31; ka3 = lindh_angle_factor*rho31*rho12
1830 rsst1 = dot_product(r12, r23); rsst2 = dot_product(r23, r31); rsst3 = dot_product(r31, r12)
1831 denom1 = 1.0_dp - rsst1**2/(d12**2*d23**2); denom2 = 1.0_dp - rsst2**2/(d23**2*d31**2)
1832 denom3 = 1.0_dp - rsst3**2/(d31**2*d12**2)
1833 denom1 = sign(1.0_dp, denom1)*max(abs(denom1), lindh_denom_floor)
1834 denom2 = sign(1.0_dp, denom2)*max(abs(denom2), lindh_denom_floor)
1835 denom3 = sign(1.0_dp, denom3)*max(abs(denom3), lindh_denom_floor)
1836 d_mat(1, 1) = r23(idr)/(d12*d23) - rsst1*r12(idr)/(d12**3*d23)
1837 d_mat(2, 1) = -r23(idr)/(d23*d31) + rsst2*r31(idr)/(d23*d31**3)
1838 d_mat(3, 1) = (r31(idr) - r12(idr))/(d31*d12) + rsst3*r31(idr)/(d31**3*d12) - &
1839 rsst3*r12(idr)/(d31*d12**3)
1840 IF (jat < i .OR. iat > i)
THEN
1841 d_mat(1, 2) = (r12(jdr) - r23(jdr))/(d12*d23) + rsst1*r12(jdr)/(d12**3*d23) - &
1842 rsst1*r23(jdr)/(d12*d23**3)
1843 d_mat(2, 2) = r31(jdr)/(d23*d31) - rsst2*r23(jdr)/(d23**3*d31)
1844 d_mat(3, 2) = -r31(jdr)/(d31*d12) + rsst3*r12(jdr)/(d31*d12**3)
1846 d_mat(1, 2) = -r12(jdr)/(d12*d23) + rsst1*r23(jdr)/(d12*d23**3)
1847 d_mat(2, 2) = (r23(jdr) - r31(jdr))/(d23*d31) + rsst2*r23(jdr)/(d23**3*d31) - &
1848 rsst2*r31(jdr)/(d23*d31**3)
1849 d_mat(3, 2) = r12(jdr)/(d31*d12) - rsst3*r31(jdr)/(d31**3*d12)
1851 IF (abs(denom1) <= 0.011_dp) d_mat(1, 1) = 0.0_dp
1852 IF (abs(denom2) <= 0.011_dp) d_mat(2, 1) = 0.0_dp
1853 IF (abs(denom3) <= 0.011_dp) d_mat(3, 1) = 0.0_dp
1855 deriv = deriv + ka1*d_mat(1, 1)*d_mat(1, 2)/denom1 + &
1856 ka2*d_mat(2, 1)*d_mat(2, 2)/denom2 + &
1857 ka3*d_mat(3, 1)*d_mat(3, 2)/denom3
1860 deriv = 0.25_dp*deriv
1862 END FUNCTION angle_second_deriv
represent a simple array based list of the given type
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind_set(atomic_kind_set, atom_of_kind, kind_of, natom_of_kind, maxatom, natom, nshell, fist_potential_present, shell_present, shell_adiabatic, shell_check_distance, damping_present)
Get attributes of an atomic kind set.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
Routines for Geometry optimization using BFGS algorithm.
subroutine, public bfgs_read_restart_header(unit, stored_method, stored_ndf, stored_type, tagged, reference_cell, cell_frame)
Read the metadata of a tagged BFGS restart, or identify a legacy raw Hessian.
recursive subroutine, public geoopt_bfgs(force_env, gopt_param, globenv, geo_section, gopt_env, x0)
Main driver for BFGS geometry optimizations.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public lindh1995
contains a functional that calculates the energy and its derivatives for the geometry optimizer
subroutine, public apply_cell_constraints(gradient, cell, keep_angles, keep_symmetry, constraint_id)
Apply cell constraints.
Handles all functions related to the CELL.
subroutine, public fix_atom_control(force_env, w)
allows for fix atom constraints
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
Routines to handle the external control of CP2K.
subroutine, public external_control(should_stop, flag, globenv, target_time, start_time, force_check)
External manipulations during a run : when the <PROJECT_NAME>.EXIT_$runtype command is sent the progr...
Utility routines to open and close files.
subroutine, public open_file(file_name, unit_number, file_status, file_form, file_action, file_position, file_pad, file_access, debug)
Opens a file and returns its logical unit number.
subroutine, public close_file(unit_number, file_status)
Closes an open file given by its logical unit number.
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
subroutine, public cp_fm_transpose(matrix, matrixt)
transposes a matrix matrixt = matrix ^ T
subroutine, public cp_fm_matvec(amat, xv, yv, alpha, beta)
Calculates yv = alpha*amat*xv + beta*yv where amat: fm matrix xv : vector replicated yv : vector repl...
used for collecting some of the diagonalization schemes available for cp_fm_type. cp_fm_power also mo...
subroutine, public choose_eigv_solver(matrix, eigenvectors, eigenvalues, info)
Choose the Eigensolver depending on which library is available ELPA seems to be unstable for small sy...
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_write_unformatted(fm, unit)
...
subroutine, public cp_fm_read_unformatted(fm, unit)
...
subroutine, public cp_fm_set_all(matrix, alpha, beta)
set all elements of a matrix to the same value, and optionally the diagonal to a different one
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
integer, parameter, public cp_p_file
subroutine, public cp_iterate(iteration_info, last, iter_nr, increment, iter_nr_out)
adds one to the actual iteration
integer function, public cp_print_key_should_output(iteration_info, basis_section, print_key_path, used_print_key, first_time)
returns what should be done with the given property if btest(res,cp_p_store) then the property should...
types that represent a subsys, i.e. a part of the system
subroutine, public cp_subsys_get(subsys, ref_count, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell)
returns information about various attributes of the given subsys
Interface for the force calculations.
recursive subroutine, public force_env_get(force_env, in_use, fist_env, qs_env, meta_env, fp_env, subsys, para_env, potential_energy, additional_potential, kinetic_energy, harmonic_shell, kinetic_shell, cell, sub_force_env, qmmm_env, qmmmx_env, eip_env, pwdft_env, globenv, input, force_env_section, method_name_id, root_section, mixed_env, nnp_env, embed_env, ipi_env)
returns various attributes about the force environment
Define type storing the global information of a run. Keep the amount of stored data small....
contains a functional that calculates the energy and its derivatives for the geometry optimizer
subroutine, public print_geo_opt_header(gopt_env, output_unit, label)
...
subroutine, public gopt_f_io_init(gopt_env, output_unit, opt_energy, wildcard, its, used_time)
Handles the Output during an optimization run.
recursive subroutine, public gopt_f_io_finalize(gopt_env, force_env, x0, conv, its, root_section, para_env, master, output_unit)
Handles the Output at the end of an optimization run.
subroutine, public gopt_f_io(gopt_env, force_env, root_section, its, opt_energy, output_unit, eold, emin, wildcard, gopt_param, ndf, dx, xi, conv, pred, rat, step, rad, used_time)
Handles the Output during an optimization run.
subroutine, public print_geo_opt_nc(gopt_env, output_unit)
...
subroutine, public cp_eval_at(gopt_env, x, f, gradient, master, para_env)
evaluete the potential energy and its gradients using an array with same dimension as the particle_se...
subroutine, public gopt_f_ii(its, output_unit)
Prints iteration step of the optimization procedure on screen.
contains a functional that calculates the energy and its derivatives for the geometry optimizer
contains typo and related routines to handle parameters controlling the GEO_OPT module
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_path_length
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
real(kind=dp) function, public m_walltime()
returns time from a real-time clock, protected against rolling early/easily
Collection of simple mathematical functions and subroutines.
pure real(kind=dp) function, dimension(3, 3), public inv_3x3(a)
Returns the inverse of the 3 x 3 matrix a.
Interface to the message passing library MPI.
basic linear algebra operations for full matrixes
represent a simple array based list of the given type
Space Group Symmetry Type Module (version 1.0, Ferbruary 12, 2021).
Space Group Symmetry Module (version 1.0, January 16, 2020).
subroutine, public print_spgr(spgr)
routine prints Space Group Information.
subroutine, public spgr_apply_rotations_coord(spgr, coord)
routine applies the rotation matrices to the coordinates.
subroutine, public identify_space_group(subsys, geo_section, gopt_env, iunit)
routine indentifies the space group and finds rotation matrices.
subroutine, public spgr_apply_rotations_force(spgr, force)
routine applies the rotation matrices to the forces.
represent a list of objects
Type defining parameters related to the simulation cell.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
type of a logger, at the moment it contains just a print level starting at which level it should be l...
represents a system: atoms, molecules, their pos,vel,...
wrapper to abstract the force evaluation of the various methods
contains the initially parsed file and the initial parallel environment
calculates the potential energy of a system, and its derivatives
stores all the informations relevant to an mpi environment
represent a list of objects