32#include "../base/base_uses.f90"
51 SUBROUTINE cp_eval_at(gopt_env, x, f, gradient, master, &
52 final_evaluation, para_env)
58 TYPE(gopt_f_type),
POINTER :: gopt_env
59 REAL(KIND=
dp),
DIMENSION(:),
POINTER :: x
60 REAL(KIND=
dp),
INTENT(out),
OPTIONAL :: f
61 REAL(KIND=
dp),
DIMENSION(:),
OPTIONAL, &
63 INTEGER,
INTENT(IN) :: master
64 LOGICAL,
INTENT(IN),
OPTIONAL :: final_evaluation
65 TYPE(mp_para_env_type),
POINTER :: para_env
72 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
73 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cg_utils'
91 RECURSIVE SUBROUTINE cg_linmin(gopt_env, xvec, xi, g, opt_energy, output_unit, gopt_param, &
94 TYPE(gopt_f_type),
POINTER :: gopt_env
95 REAL(kind=dp),
DIMENSION(:),
POINTER :: xvec, xi, g
96 REAL(kind=dp),
INTENT(INOUT) :: opt_energy
97 INTEGER :: output_unit
101 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_linmin'
105 CALL timeset(routinen, handle)
106 gopt_env%do_line_search = .true.
107 SELECT CASE (gopt_env%type_id)
109 SELECT CASE (gopt_param%cg_ls%type_id)
111 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=gopt_param%cg_ls%grad_only, &
112 output_unit=output_unit)
114 CALL linmin_fit(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brack_limit, &
115 gopt_param%cg_ls%initial_step, output_unit, gopt_param, globenv)
117 CALL linmin_gold(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brent_tol, &
118 gopt_param%cg_ls%brent_max_iter, gopt_param%cg_ls%brack_limit, &
119 gopt_param%cg_ls%initial_step, output_unit, globenv)
121 cpabort(
"Line Search type not yet implemented in CG.")
124 SELECT CASE (gopt_param%cg_ls%type_id)
126 IF (gopt_env%dimer_rotation)
THEN
127 CALL rotmin_2pnt(gopt_env, gopt_env%dimer_env, xvec, xi, opt_energy)
129 CALL tslmin_2pnt(gopt_env, gopt_env%dimer_env, xvec, xi, opt_energy, gopt_param, &
133 cpabort(
"Line Search type not yet implemented in CG for TS search.")
136 SELECT CASE (gopt_param%cg_ls%type_id)
138 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=.true., &
139 output_unit=output_unit)
141 CALL linmin_fit(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brack_limit, &
142 gopt_param%cg_ls%initial_step, output_unit, gopt_param, globenv)
144 CALL linmin_gold(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brent_tol, &
145 gopt_param%cg_ls%brent_max_iter, gopt_param%cg_ls%brack_limit, &
146 gopt_param%cg_ls%initial_step, output_unit, globenv)
148 cpabort(
"Line Search type not yet implemented in CG for cell optimization.")
151 SELECT CASE (gopt_param%cg_ls%type_id)
153 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=.true., &
154 output_unit=output_unit)
156 cpabort(
"Line Search type not yet implemented in CG for shellcore optimization.")
160 gopt_env%do_line_search = .false.
161 CALL timestop(handle)
178 RECURSIVE SUBROUTINE linmin_2pnt(gopt_env, x0, ls_vec, g, opt_energy, gopt_param, use_only_grad, &
180 TYPE(gopt_f_type),
POINTER :: gopt_env
181 REAL(kind=dp),
DIMENSION(:),
POINTER :: x0, ls_vec, g
182 REAL(kind=dp),
INTENT(INOUT) :: opt_energy
184 LOGICAL,
INTENT(IN),
OPTIONAL :: use_only_grad
185 INTEGER,
INTENT(IN) :: output_unit
187 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_2pnt'
190 LOGICAL :: my_use_only_grad, &
191 save_consistent_energy_force
192 REAL(kind=dp) :: a, b, c, dx, dx_min, dx_min_save, &
193 dx_thrs, norm_grad1, norm_grad2, &
194 norm_ls_vec, opt_energy2, x_grad_zero
195 REAL(kind=dp),
DIMENSION(:),
POINTER :: gradient2, ls_norm
197 CALL timeset(routinen, handle)
198 norm_ls_vec = sqrt(dot_product(ls_vec, ls_vec))
199 my_use_only_grad = .false.
200 IF (
PRESENT(use_only_grad)) my_use_only_grad = use_only_grad
201 IF (norm_ls_vec /= 0.0_dp)
THEN
202 ALLOCATE (ls_norm(
SIZE(ls_vec)))
203 ALLOCATE (gradient2(
SIZE(ls_vec)))
204 ls_norm = ls_vec/norm_ls_vec
206 dx_thrs = gopt_param%cg_ls%max_step
210 save_consistent_energy_force = gopt_env%require_consistent_energy_force
211 gopt_env%require_consistent_energy_force = .NOT. my_use_only_grad
212 CALL cp_eval_at(gopt_env, x0, opt_energy2, gradient2, master=gopt_env%force_env%para_env%mepos, &
213 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
214 gopt_env%require_consistent_energy_force = save_consistent_energy_force
216 norm_grad1 = -dot_product(g, ls_norm)
217 norm_grad2 = dot_product(gradient2, ls_norm)
218 IF (my_use_only_grad)
THEN
223 a = (norm_grad2 - b)/dx
235 a = (c - (opt_energy2 - norm_grad2*dx))/dx**2
236 b = norm_grad2 - 2.0_dp*a*dx
238 IF (a /= 0.0_dp) dx_min = -b/(2.0_dp*a)
239 opt_energy = opt_energy2
244 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
245 x0 = x0 + (dx_min - dx)*ls_norm
248 IF (output_unit > 0)
THEN
249 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
250 WRITE (unit=output_unit, fmt=
"(T2,A,T31,A,T78,A)") &
251 "***",
"2PNT LINE SEARCH INFO",
"***"
252 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
253 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
254 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
255 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
256 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min,
"***"
257 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
260 DEALLOCATE (gradient2)
265 CALL timestop(handle)
266 END SUBROUTINE linmin_2pnt
279 SUBROUTINE tslmin_2pnt(gopt_env, dimer_env, x0, tls_vec, opt_energy, gopt_param, output_unit)
280 TYPE(gopt_f_type),
POINTER :: gopt_env
282 REAL(kind=dp),
DIMENSION(:),
POINTER :: x0, tls_vec
283 REAL(kind=dp),
INTENT(INOUT) :: opt_energy
285 INTEGER,
INTENT(IN) :: output_unit
287 CHARACTER(len=*),
PARAMETER :: routinen =
'tslmin_2pnt'
290 REAL(kind=dp) :: dx, dx_min, dx_min_acc, dx_min_save, &
291 dx_thrs, norm_tls_vec, opt_energy2
292 REAL(kind=dp),
DIMENSION(:),
POINTER :: tls_norm
294 CALL timeset(routinen, handle)
295 norm_tls_vec = sqrt(dot_product(tls_vec, tls_vec))
296 IF (norm_tls_vec /= 0.0_dp)
THEN
297 ALLOCATE (tls_norm(
SIZE(tls_vec)))
299 tls_norm = tls_vec/norm_tls_vec
300 dimer_env%tsl%tls_vec => tls_norm
303 dx_thrs = gopt_param%cg_ls%max_step
305 IF (dimer_env%rot%curvature > 0) dx = dx_thrs
306 x0 = x0 + dx*tls_norm
307 CALL cp_eval_at(gopt_env, x0, opt_energy2, master=gopt_env%force_env%para_env%mepos, &
308 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
309 IF (dimer_env%rot%curvature > 0)
THEN
315 dx_min = -opt_energy/(opt_energy2 - opt_energy)*dx
319 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
323 x0 = x0 + dx_min*tls_norm
326 IF (output_unit > 0)
THEN
327 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
328 WRITE (unit=output_unit, fmt=
"(T2,A,T24,A,T78,A)") &
329 "***",
"2PNT TRANSLATIONAL LINE SEARCH INFO",
"***"
330 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
331 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T78,A)") &
332 "***",
"LOCAL CURVATURE =", dimer_env%rot%curvature,
"***"
333 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
334 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
335 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
336 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min_acc,
"***"
337 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
341 CALL cp_eval_at(gopt_env, x0, opt_energy, master=gopt_env%force_env%para_env%mepos, &
342 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
344 DEALLOCATE (tls_norm)
349 CALL timestop(handle)
351 END SUBROUTINE tslmin_2pnt
362 SUBROUTINE rotmin_2pnt(gopt_env, dimer_env, x0, theta, opt_energy)
363 TYPE(gopt_f_type),
POINTER :: gopt_env
365 REAL(kind=dp),
DIMENSION(:),
POINTER :: x0, theta
366 REAL(kind=dp),
INTENT(INOUT) :: opt_energy
368 CHARACTER(len=*),
PARAMETER :: routinen =
'rotmin_2pnt'
371 REAL(kind=dp) :: a0, a1, angle, b1, curvature0, &
372 curvature1, curvature2, dcdp, f
373 REAL(kind=dp),
DIMENSION(:),
POINTER :: work
375 CALL timeset(routinen, handle)
376 curvature0 = dimer_env%rot%curvature
377 dcdp = dimer_env%rot%dCdp
379 angle = -0.5_dp*atan(dcdp/(2.0_dp*abs(curvature0)))
380 dimer_env%rot%angle1 = angle
381 dimer_env%cg_rot%nvec_old = dimer_env%nvec
382 IF (angle > dimer_env%rot%angle_tol)
THEN
386 CALL cp_eval_at(gopt_env, x0, f, master=gopt_env%force_env%para_env%mepos, &
387 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
389 curvature1 = dimer_env%rot%curvature
390 a1 = (curvature0 - curvature1 + b1*sin(2.0_dp*angle))/(1.0_dp - cos(2.0_dp*angle))
391 a0 = 2.0_dp*(curvature0 - a1)
392 angle = 0.5_dp*atan(b1/a1)
393 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*angle) + b1*sin(2.0_dp*angle)
394 IF (curvature2 > curvature0)
THEN
395 angle = angle +
pi/2.0_dp
396 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*angle) + b1*sin(2.0_dp*angle)
398 dimer_env%rot%angle2 = angle
399 dimer_env%rot%curvature = curvature2
401 dimer_env%nvec = dimer_env%cg_rot%nvec_old
406 ALLOCATE (work(
SIZE(dimer_env%nvec)))
407 work = dimer_env%rot%g1
408 work = sin(dimer_env%rot%angle1 - dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1 + &
409 sin(dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1p + &
410 (1.0_dp - cos(dimer_env%rot%angle2) - sin(dimer_env%rot%angle2)*tan(dimer_env%rot%angle1/2.0_dp))* &
412 work = -2.0_dp*(work - dimer_env%rot%g0)
413 work = work - dot_product(work, dimer_env%nvec)*dimer_env%nvec
414 opt_energy = sqrt(dot_product(work, work))
417 dimer_env%rot%angle2 = angle
418 CALL timestop(handle)
420 END SUBROUTINE rotmin_2pnt
441 SUBROUTINE linmin_fit(gopt_env, xvec, xi, opt_energy, &
442 brack_limit, step, output_unit, gopt_param, globenv)
443 TYPE(gopt_f_type),
POINTER :: gopt_env
444 REAL(kind=dp),
DIMENSION(:),
POINTER :: xvec, xi
445 REAL(kind=dp) :: opt_energy, brack_limit, step
446 INTEGER :: output_unit
450 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_fit'
452 INTEGER :: handle, loc_iter, odim
453 LOGICAL :: should_stop
454 REAL(kind=dp) :: ax, bx, fprev, rms_dr, rms_force, scale, &
456 REAL(kind=dp),
DIMENSION(:),
POINTER :: pcom, xicom
457 REAL(kind=dp),
DIMENSION(:, :),
POINTER :: hist
459 CALL timeset(routinen, handle)
461 NULLIFY (pcom, xicom, hist)
462 rms_dr = gopt_param%rms_dr
463 rms_force = gopt_param%rms_force
464 ALLOCATE (pcom(
SIZE(xvec)))
465 ALLOCATE (xicom(
SIZE(xvec)))
469 xicom = xicom/sqrt(dot_product(xicom, xicom))
473 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, brack_limit, output_unit, &
474 histpoint=hist, globenv=globenv)
477 opt_energy = minval(hist(:, 2))
481 DO WHILE (abs(hist(odim, 3)) > rms_force*scale .OR. abs(hist(odim, 1) - hist(odim - 1, 1)) > scale*rms_dr)
483 IF (should_stop)
EXIT
485 loc_iter = loc_iter + 1
487 xmin = findmin(hist(:, 1), hist(:, 2), hist(:, 3))
489 hist(odim + 1, 1) = xmin
490 hist(odim + 1, 3) = cg_deval1d(gopt_env, xmin, pcom, xicom, opt_energy)
491 hist(odim + 1, 2) = opt_energy
501 IF (output_unit > 0)
THEN
502 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
503 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
504 "***",
"FIT LS - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
505 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
507 CALL timestop(handle)
509 END SUBROUTINE linmin_fit
531 SUBROUTINE linmin_gold(gopt_env, xvec, xi, opt_energy, brent_tol, brent_max_iter, &
532 brack_limit, step, output_unit, globenv)
533 TYPE(gopt_f_type),
POINTER :: gopt_env
534 REAL(kind=dp),
DIMENSION(:),
POINTER :: xvec, xi
535 REAL(kind=dp) :: opt_energy, brent_tol
536 INTEGER :: brent_max_iter
537 REAL(kind=dp) :: brack_limit, step
538 INTEGER :: output_unit
541 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_gold'
544 REAL(kind=dp) :: ax, bx, xmin, xx
545 REAL(kind=dp),
DIMENSION(:),
POINTER :: pcom, xicom
547 CALL timeset(routinen, handle)
549 NULLIFY (pcom, xicom)
550 ALLOCATE (pcom(
SIZE(xvec)))
551 ALLOCATE (xicom(
SIZE(xvec)))
555 xicom = xicom/sqrt(dot_product(xicom, xicom))
559 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, brack_limit, output_unit, &
562 opt_energy = cg_dbrent(gopt_env, ax, xx, bx, brent_tol, brent_max_iter, &
563 xmin, pcom, xicom, output_unit, globenv)
569 CALL timestop(handle)
570 END SUBROUTINE linmin_gold
593 SUBROUTINE cg_mnbrak(gopt_env, ax, bx, cx, pcom, xicom, brack_limit, output_unit, &
595 TYPE(gopt_f_type),
POINTER :: gopt_env
596 REAL(kind=dp) :: ax, bx, cx
597 REAL(kind=dp),
DIMENSION(:),
POINTER :: pcom, xicom
598 REAL(kind=dp) :: brack_limit
599 INTEGER :: output_unit
600 REAL(kind=dp),
DIMENSION(:, :),
OPTIONAL,
POINTER :: histpoint
603 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_mnbrak'
605 INTEGER :: handle, loc_iter, odim
606 LOGICAL :: hist, should_stop
607 REAL(kind=dp) :: dum, fa, fb, fc, fu, gold, q, r, u, ulim
609 CALL timeset(routinen, handle)
610 hist =
PRESENT(histpoint)
612 cpassert(.NOT.
ASSOCIATED(histpoint))
613 ALLOCATE (histpoint(3, 3))
615 gold = (1.0_dp + sqrt(5.0_dp))/2.0_dp
618 histpoint(1, 3) = cg_deval1d(gopt_env, ax, pcom, xicom, fa)
621 histpoint(2, 3) = cg_deval1d(gopt_env, bx, pcom, xicom, fb)
624 fa = cg_eval1d(gopt_env, ax, pcom, xicom)
625 fb = cg_eval1d(gopt_env, bx, pcom, xicom)
635 cx = bx + gold*(bx - ax)
638 histpoint(3, 3) = cg_deval1d(gopt_env, cx, pcom, xicom, fc)
641 fc = cg_eval1d(gopt_env, cx, pcom, xicom)
646 IF (should_stop)
EXIT
648 r = (bx - ax)*(fb - fc)
649 q = (bx - cx)*(fb - fa)
650 u = bx - ((bx - cx)*q - (bx - ax)*r)/(2.0_dp*sign(max(abs(q - r), tiny(0.0_dp)), q - r))
651 ulim = bx + brack_limit*(cx - bx)
652 IF ((bx - u)*(u - cx) > 0.0_dp)
THEN
654 odim =
SIZE(histpoint, 1)
656 histpoint(odim + 1, 1) = u
657 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
658 histpoint(odim + 1, 2) = fu
660 fu = cg_eval1d(gopt_env, u, pcom, xicom)
662 loc_iter = loc_iter + 1
669 ELSE IF (fu > fb)
THEN
674 u = cx + gold*(cx - bx)
676 odim =
SIZE(histpoint, 1)
678 histpoint(odim + 1, 1) = u
679 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
680 histpoint(odim + 1, 2) = fu
682 fu = cg_eval1d(gopt_env, u, pcom, xicom)
684 loc_iter = loc_iter + 1
685 ELSE IF ((cx - u)*(u - ulim) > 0.)
THEN
687 odim =
SIZE(histpoint, 1)
689 histpoint(odim + 1, 1) = u
690 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
691 histpoint(odim + 1, 2) = fu
693 fu = cg_eval1d(gopt_env, u, pcom, xicom)
695 loc_iter = loc_iter + 1
699 u = cx + gold*(cx - bx)
703 odim =
SIZE(histpoint, 1)
705 histpoint(odim + 1, 1) = u
706 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
707 histpoint(odim + 1, 2) = fu
709 fu = cg_eval1d(gopt_env, u, pcom, xicom)
711 loc_iter = loc_iter + 1
713 ELSE IF ((u - ulim)*(ulim - cx) >= 0.)
THEN
716 odim =
SIZE(histpoint, 1)
718 histpoint(odim + 1, 1) = u
719 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
720 histpoint(odim + 1, 2) = fu
722 fu = cg_eval1d(gopt_env, u, pcom, xicom)
724 loc_iter = loc_iter + 1
726 u = cx + gold*(cx - bx)
728 odim =
SIZE(histpoint, 1)
730 histpoint(odim + 1, 1) = u
731 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
732 histpoint(odim + 1, 2) = fu
734 fu = cg_eval1d(gopt_env, u, pcom, xicom)
736 loc_iter = loc_iter + 1
745 IF (output_unit > 0)
THEN
746 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
747 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
748 "***",
"MNBRACK - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
749 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
751 CALL timestop(handle)
752 END SUBROUTINE cg_mnbrak
781 FUNCTION cg_dbrent(gopt_env, ax, bx, cx, tol, itmax, xmin, pcom, xicom, output_unit, &
782 globenv)
RESULT(dbrent)
783 TYPE(gopt_f_type),
POINTER :: gopt_env
784 REAL(kind=dp) :: ax, bx, cx, tol
786 REAL(kind=dp) :: xmin
787 REAL(kind=dp),
DIMENSION(:),
POINTER :: pcom, xicom
788 INTEGER :: output_unit
790 REAL(kind=dp) :: dbrent
792 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_dbrent'
793 REAL(kind=dp),
PARAMETER :: zeps = 1.0e-8_dp
795 INTEGER :: handle, iter, loc_iter
796 LOGICAL :: ok1, ok2, should_stop, skip0, skip1
797 REAL(kind=dp) :: a, b, d, d1, d2, du, dv, dw, dx, e, fu, &
798 fv, fw, fx, olde, tol1, tol2, u, u1, &
801 CALL timeset(routinen, handle)
806 dx = cg_deval1d(gopt_env, x, pcom, xicom, fx)
814 IF (should_stop)
EXIT
817 tol1 = tol*abs(x) + zeps
821 IF (abs(x - xm) <= (tol2 - 0.5_dp*(b - a)))
EXIT
822 IF (abs(e) > tol1)
THEN
825 IF (dw /= dx) d1 = (w - x)*dx/(dx - dw)
826 IF (dv /= dx) d2 = (v - x)*dx/(dx - dv)
829 ok1 = ((a - u1)*(u1 - b) > 0.0_dp) .AND. (dx*d1 <= 0.0_dp)
830 ok2 = ((a - u2)*(u2 - b) > 0.0_dp) .AND. (dx*d2 <= 0.0_dp)
833 IF (.NOT. (ok1 .OR. ok2))
THEN
835 ELSE IF (ok1 .AND. ok2)
THEN
836 IF (abs(d1) < abs(d2))
THEN
846 IF (.NOT. skip0)
THEN
847 IF (abs(d) > abs(0.5_dp*olde)) skip0 = .true.
848 IF (.NOT. skip0)
THEN
850 IF ((u - a) < tol2 .OR. (b - u) < tol2) d = sign(tol1, xm - x)
855 IF (.NOT. skip1)
THEN
856 IF (dx >= 0.0_dp)
THEN
863 IF (abs(d) >= tol1)
THEN
865 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
866 loc_iter = loc_iter + 1
868 u = x + sign(tol1, d)
869 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
870 loc_iter = loc_iter + 1
879 v = w; fv = fw; dv = dw; w = x
880 fw = fx; dw = dx; x = u; fx = fu; dx = du
887 IF (fu <= fw .OR. w == x)
THEN
888 v = w; fv = fw; dv = dw
889 w = u; fw = fu; dw = du
890 ELSE IF (fu <= fv .OR. v == x .OR. v == w)
THEN
897 IF (output_unit > 0)
THEN
898 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
899 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
900 "***",
"BRENT - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
901 IF (iter == itmax + 1) &
902 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,T78,A)") &
903 "***",
"BRENT - NUMBER OF ITERATIONS EXCEEDED ",
"***"
904 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
906 cpassert(iter /= itmax + 1)
909 CALL timestop(handle)
911 END FUNCTION cg_dbrent
925 FUNCTION cg_eval1d(gopt_env, x, pcom, xicom)
RESULT(my_val)
926 TYPE(gopt_f_type),
POINTER :: gopt_env
928 REAL(kind=dp),
DIMENSION(:),
POINTER :: pcom, xicom
929 REAL(kind=dp) :: my_val
931 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_eval1d'
934 REAL(kind=dp),
DIMENSION(:),
POINTER :: xvec
936 CALL timeset(routinen, handle)
938 ALLOCATE (xvec(
SIZE(pcom)))
939 xvec = pcom + x*xicom
940 CALL cp_eval_at(gopt_env, xvec, my_val, master=gopt_env%force_env%para_env%mepos, &
941 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
944 CALL timestop(handle)
946 END FUNCTION cg_eval1d
961 FUNCTION cg_deval1d(gopt_env, x, pcom, xicom, fval)
RESULT(my_val)
962 TYPE(gopt_f_type),
POINTER :: gopt_env
964 REAL(kind=dp),
DIMENSION(:),
POINTER :: pcom, xicom
965 REAL(kind=dp) :: fval, my_val
967 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_deval1d'
970 REAL(kind=dp) :: energy
971 REAL(kind=dp),
DIMENSION(:),
POINTER :: grad, xvec
973 CALL timeset(routinen, handle)
975 ALLOCATE (xvec(
SIZE(pcom)))
976 ALLOCATE (grad(
SIZE(pcom)))
977 xvec = pcom + x*xicom
978 CALL cp_eval_at(gopt_env, xvec, energy, grad, master=gopt_env%force_env%para_env%mepos, &
979 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
980 my_val = dot_product(grad, xicom)
984 CALL timestop(handle)
986 END FUNCTION cg_deval1d
998 FUNCTION findmin(x, y, dy)
RESULT(res)
999 REAL(kind=dp),
DIMENSION(:) :: x, y, dy
1000 REAL(kind=dp) :: res
1002 INTEGER :: i, info, iwork(8*3), lwork, min_pos, np
1003 REAL(kind=dp) :: diag(3), res1(3), res2(3), res3(3), &
1004 spread, sum_x, sum_xx, tmpw(1), &
1006 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: work
1007 REAL(kind=dp),
DIMENSION(2*SIZE(x), 3) :: f
1008 REAL(kind=dp),
DIMENSION(2*SIZE(x)) :: b, w
1009 REAL(kind=dp) :: u(2*
SIZE(x), 3)
1017 sum_xx = sum_xx + x(i)**2
1018 sum_x = sum_x + x(i)
1019 IF (y(min_pos) > y(i)) min_pos = i
1021 spread = sqrt(sum_xx/real(np, dp) - (sum_x/real(np, dp))**2)
1023 w(i) = exp(-(real(np - i, dp))**2/(real(2*9, dp)))
1024 w(i + np) = 2._dp*w(i)
1029 f(i, 3) = x(i)**2*w(i)
1031 f(i + np, 2) = w(i + np)
1032 f(i + np, 3) = 2*x(i)*w(i + np)
1036 b(i + np) = dy(i)*w(i + np)
1039 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), tmpw, lwork, &
1041 lwork = ceiling(tmpw(1))
1042 ALLOCATE (work(lwork))
1043 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), work, lwork, &
1046 CALL dgemv(
'T',
SIZE(u, 1),
SIZE(u, 2), 1._dp, u,
SIZE(u, 1), b, 1, 0._dp, res1, 1)
1048 res2(i) = res1(i)/diag(i)
1050 CALL dgemv(
'T', 3, 3, 1._dp, vt,
SIZE(vt, 1), res2, 1, 0._dp, res3, 1)
1051 res = -0.5*res3(2)/res3(3)
1052 END FUNCTION findmin
1068 TYPE(gopt_f_type),
POINTER :: gopt_env
1069 LOGICAL,
INTENT(IN) :: fletcher_reeves
1070 REAL(kind=dp),
DIMENSION(:),
POINTER :: g, xi, h
1072 CHARACTER(len=*),
PARAMETER :: routinen =
'get_conjugate_direction'
1076 REAL(kind=dp) :: dgg, gam, gg, norm, norm_h
1079 CALL timeset(routinen, handle)
1081 IF (.NOT. gopt_env%dimer_rotation)
THEN
1082 gg = dot_product(g, g)
1083 IF (fletcher_reeves)
THEN
1084 dgg = dot_product(xi, xi)
1086 dgg = dot_product((xi + g), xi)
1092 dimer_env => gopt_env%dimer_env
1093 check = abs(dot_product(g, g) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1096 check = abs(dot_product(xi, xi) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1099 check = abs(dot_product(h, dimer_env%cg_rot%nvec_old)) < max(1.0e-9_dp,
dimer_thrs)
1101 gg = dimer_env%cg_rot%norm_theta_old**2
1102 IF (fletcher_reeves)
THEN
1103 dgg = dimer_env%cg_rot%norm_theta**2
1105 norm = dimer_env%cg_rot%norm_theta*dimer_env%cg_rot%norm_theta_old
1106 dgg = dimer_env%cg_rot%norm_theta**2 + dot_product(g, xi)*norm
1109 CALL rotate_dimer(dimer_env%cg_rot%nvec_old, g, dimer_env%rot%angle2 +
pi/2.0_dp)
1112 h = -xi*dimer_env%cg_rot%norm_theta + gam*dimer_env%cg_rot%norm_h*dimer_env%cg_rot%nvec_old
1113 h = h - dot_product(h, dimer_env%nvec)*dimer_env%nvec
1114 norm_h = sqrt(dot_product(h, h))
1115 IF (norm_h < epsilon(0.0_dp))
THEN
1120 dimer_env%cg_rot%norm_h = norm_h
1122 CALL timestop(handle)
subroutine cp_eval_at(gopt_env, x, f, gradient, master, final_evaluation, para_env)
evaluete the potential energy and its gradients using an array with same dimension as the particle_se...
Utilities for Geometry optimization using Conjugate Gradients.
subroutine, public get_conjugate_direction(gopt_env, fletcher_reeves, g, xi, h)
Computes the Conjugate direction for the next search.
recursive subroutine, public cg_linmin(gopt_env, xvec, xi, g, opt_energy, output_unit, gopt_param, globenv)
Main driver for line minimization routines for CG.
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...
Contains types used for a Dimer Method calculations.
Contains utilities for a Dimer Method calculations.
subroutine, public rotate_dimer(nvec, theta, dt)
Performs a rotation of the unit dimer vector.
real(kind=dp), parameter, public dimer_thrs
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
contains typo and related routines to handle parameters controlling the GEO_OPT module
Defines the basic variable types.
integer, parameter, public dp
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Utility routines for the memory handling.
Interface to the message passing library MPI.
Defines the environment for a Dimer Method calculation.
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