32#include "../base/base_uses.f90"
38 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .true.
39 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'cg_utils'
57 RECURSIVE SUBROUTINE cg_linmin(gopt_env, xvec, xi, g, opt_energy, output_unit, gopt_param, &
61 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec, xi, g
62 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
63 INTEGER :: output_unit
67 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_linmin'
71 CALL timeset(routinen, handle)
72 gopt_env%do_line_search = .true.
73 SELECT CASE (gopt_env%type_id)
75 SELECT CASE (gopt_param%cg_ls%type_id)
77 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=gopt_param%cg_ls%grad_only, &
78 output_unit=output_unit)
80 CALL linmin_fit(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brack_limit, &
81 gopt_param%cg_ls%initial_step, output_unit, gopt_param, globenv)
83 CALL linmin_gold(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brent_tol, &
84 gopt_param%cg_ls%brent_max_iter, gopt_param%cg_ls%brack_limit, &
85 gopt_param%cg_ls%initial_step, output_unit, globenv)
87 cpabort(
"Line Search type not yet implemented in CG.")
90 SELECT CASE (gopt_param%cg_ls%type_id)
92 IF (gopt_env%dimer_rotation)
THEN
93 CALL rotmin_2pnt(gopt_env, gopt_env%dimer_env, xvec, xi, opt_energy)
95 CALL tslmin_2pnt(gopt_env, gopt_env%dimer_env, xvec, xi, opt_energy, gopt_param, &
99 cpabort(
"Line Search type not yet implemented in CG for TS search.")
102 SELECT CASE (gopt_param%cg_ls%type_id)
104 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=.true., &
105 output_unit=output_unit)
107 CALL linmin_fit(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brack_limit, &
108 gopt_param%cg_ls%initial_step, output_unit, gopt_param, globenv)
110 CALL linmin_gold(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brent_tol, &
111 gopt_param%cg_ls%brent_max_iter, gopt_param%cg_ls%brack_limit, &
112 gopt_param%cg_ls%initial_step, output_unit, globenv)
114 cpabort(
"Line Search type not yet implemented in CG for cell optimization.")
117 SELECT CASE (gopt_param%cg_ls%type_id)
119 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=.true., &
120 output_unit=output_unit)
122 cpabort(
"Line Search type not yet implemented in CG for shellcore optimization.")
126 gopt_env%do_line_search = .false.
127 CALL timestop(handle)
144 RECURSIVE SUBROUTINE linmin_2pnt(gopt_env, x0, ls_vec, g, opt_energy, gopt_param, use_only_grad, &
147 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, ls_vec, g
148 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
150 LOGICAL,
INTENT(IN),
OPTIONAL :: use_only_grad
151 INTEGER,
INTENT(IN) :: output_unit
153 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_2pnt'
156 LOGICAL :: my_use_only_grad, &
157 save_consistent_energy_force
158 REAL(kind=
dp) :: a, b, c, dx, dx_min, dx_min_save, &
159 dx_thrs, norm_grad1, norm_grad2, &
160 norm_ls_vec, opt_energy2, x_grad_zero
161 REAL(kind=
dp),
DIMENSION(:),
POINTER :: gradient2, ls_norm
163 CALL timeset(routinen, handle)
164 norm_ls_vec = norm2(ls_vec)
165 my_use_only_grad = .false.
166 IF (
PRESENT(use_only_grad)) my_use_only_grad = use_only_grad
167 IF (norm_ls_vec /= 0.0_dp)
THEN
168 ALLOCATE (ls_norm(
SIZE(ls_vec)))
169 ALLOCATE (gradient2(
SIZE(ls_vec)))
170 ls_norm = ls_vec/norm_ls_vec
172 dx_thrs = gopt_param%cg_ls%max_step
176 save_consistent_energy_force = gopt_env%require_consistent_energy_force
177 gopt_env%require_consistent_energy_force = .NOT. my_use_only_grad
178 CALL cp_eval_at(gopt_env, x0, opt_energy2, gradient2, master=gopt_env%force_env%para_env%mepos, &
179 para_env=gopt_env%force_env%para_env)
180 gopt_env%require_consistent_energy_force = save_consistent_energy_force
182 norm_grad1 = -dot_product(g, ls_norm)
183 norm_grad2 = dot_product(gradient2, ls_norm)
184 IF (my_use_only_grad)
THEN
189 a = (norm_grad2 - b)/dx
201 a = (c - (opt_energy2 - norm_grad2*dx))/dx**2
202 b = norm_grad2 - 2.0_dp*a*dx
204 IF (a /= 0.0_dp) dx_min = -b/(2.0_dp*a)
205 opt_energy = opt_energy2
210 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
211 x0 = x0 + (dx_min - dx)*ls_norm
214 IF (output_unit > 0)
THEN
215 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
216 WRITE (unit=output_unit, fmt=
"(T2,A,T31,A,T78,A)") &
217 "***",
"2PNT LINE SEARCH INFO",
"***"
218 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
219 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
220 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
221 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
222 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min,
"***"
223 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
226 DEALLOCATE (gradient2)
231 CALL timestop(handle)
232 END SUBROUTINE linmin_2pnt
245 SUBROUTINE tslmin_2pnt(gopt_env, dimer_env, x0, tls_vec, opt_energy, gopt_param, output_unit)
248 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, tls_vec
249 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
251 INTEGER,
INTENT(IN) :: output_unit
253 CHARACTER(len=*),
PARAMETER :: routinen =
'tslmin_2pnt'
256 REAL(kind=
dp) :: dx, dx_min, dx_min_acc, dx_min_save, &
257 dx_thrs, norm_tls_vec, opt_energy2
258 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tls_norm
260 CALL timeset(routinen, handle)
261 norm_tls_vec = norm2(tls_vec)
262 IF (norm_tls_vec /= 0.0_dp)
THEN
263 ALLOCATE (tls_norm(
SIZE(tls_vec)))
265 tls_norm = tls_vec/norm_tls_vec
266 dimer_env%tsl%tls_vec => tls_norm
269 dx_thrs = gopt_param%cg_ls%max_step
271 IF (dimer_env%rot%curvature > 0) dx = dx_thrs
272 x0 = x0 + dx*tls_norm
273 CALL cp_eval_at(gopt_env, x0, opt_energy2, master=gopt_env%force_env%para_env%mepos, &
274 para_env=gopt_env%force_env%para_env)
275 IF (dimer_env%rot%curvature > 0)
THEN
281 dx_min = -opt_energy/(opt_energy2 - opt_energy)*dx
285 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
289 x0 = x0 + dx_min*tls_norm
292 IF (output_unit > 0)
THEN
293 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
294 WRITE (unit=output_unit, fmt=
"(T2,A,T24,A,T78,A)") &
295 "***",
"2PNT TRANSLATIONAL LINE SEARCH INFO",
"***"
296 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
297 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T78,A)") &
298 "***",
"LOCAL CURVATURE =", dimer_env%rot%curvature,
"***"
299 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
300 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
301 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
302 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min_acc,
"***"
303 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
307 CALL cp_eval_at(gopt_env, x0, opt_energy, master=gopt_env%force_env%para_env%mepos, &
308 para_env=gopt_env%force_env%para_env)
310 DEALLOCATE (tls_norm)
315 CALL timestop(handle)
317 END SUBROUTINE tslmin_2pnt
328 SUBROUTINE rotmin_2pnt(gopt_env, dimer_env, x0, theta, opt_energy)
331 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, theta
332 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
334 CHARACTER(len=*),
PARAMETER :: routinen =
'rotmin_2pnt'
337 REAL(kind=
dp) :: a0, a1, angle, b1, curvature0, &
338 curvature1, curvature2, dcdp, f
339 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
341 CALL timeset(routinen, handle)
342 curvature0 = dimer_env%rot%curvature
343 dcdp = dimer_env%rot%dCdp
345 angle = -0.5_dp*atan(dcdp/(2.0_dp*abs(curvature0)))
346 dimer_env%rot%angle1 = angle
347 dimer_env%cg_rot%nvec_old = dimer_env%nvec
348 IF (angle > dimer_env%rot%angle_tol)
THEN
352 CALL cp_eval_at(gopt_env, x0, f, master=gopt_env%force_env%para_env%mepos, &
353 para_env=gopt_env%force_env%para_env)
355 curvature1 = dimer_env%rot%curvature
356 a1 = (curvature0 - curvature1 + b1*sin(2.0_dp*angle))/(1.0_dp - cos(2.0_dp*angle))
357 a0 = 2.0_dp*(curvature0 - a1)
358 angle = 0.5_dp*atan(b1/a1)
359 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*angle) + b1*sin(2.0_dp*angle)
360 IF (curvature2 > curvature0)
THEN
361 angle = angle +
pi/2.0_dp
362 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*angle) + b1*sin(2.0_dp*angle)
364 dimer_env%rot%angle2 = angle
365 dimer_env%rot%curvature = curvature2
367 dimer_env%nvec = dimer_env%cg_rot%nvec_old
372 ALLOCATE (work(
SIZE(dimer_env%nvec)))
373 work = dimer_env%rot%g1
374 work = sin(dimer_env%rot%angle1 - dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1 + &
375 sin(dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1p + &
376 (1.0_dp - cos(dimer_env%rot%angle2) - sin(dimer_env%rot%angle2)*tan(dimer_env%rot%angle1/2.0_dp))* &
378 work = -2.0_dp*(work - dimer_env%rot%g0)
379 work = work - dot_product(work, dimer_env%nvec)*dimer_env%nvec
380 opt_energy = norm2(work)
383 dimer_env%rot%angle2 = angle
384 CALL timestop(handle)
386 END SUBROUTINE rotmin_2pnt
407 SUBROUTINE linmin_fit(gopt_env, xvec, xi, opt_energy, &
408 brack_limit, step, output_unit, gopt_param, globenv)
410 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec, xi
411 REAL(kind=
dp) :: opt_energy, brack_limit, step
412 INTEGER :: output_unit
416 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_fit'
418 INTEGER :: handle, loc_iter, odim
419 LOGICAL :: should_stop
420 REAL(kind=
dp) :: ax, bx, fprev, rms_dr, rms_force, scale, &
422 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
423 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: hist
425 CALL timeset(routinen, handle)
427 NULLIFY (pcom, xicom, hist)
428 rms_dr = gopt_param%rms_dr
429 rms_force = gopt_param%rms_force
430 ALLOCATE (pcom(
SIZE(xvec)))
431 ALLOCATE (xicom(
SIZE(xvec)))
435 xicom = xicom/norm2(xicom)
439 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, brack_limit, output_unit, &
440 histpoint=hist, globenv=globenv)
443 opt_energy = minval(hist(:, 2))
447 DO WHILE (abs(hist(odim, 3)) > rms_force*scale .OR. abs(hist(odim, 1) - hist(odim - 1, 1)) > scale*rms_dr)
449 IF (should_stop)
EXIT
451 loc_iter = loc_iter + 1
453 xmin = findmin(hist(:, 1), hist(:, 2), hist(:, 3))
455 hist(odim + 1, 1) = xmin
456 hist(odim + 1, 3) = cg_deval1d(gopt_env, xmin, pcom, xicom, opt_energy)
457 hist(odim + 1, 2) = opt_energy
467 IF (output_unit > 0)
THEN
468 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
469 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
470 "***",
"FIT LS - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
471 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
473 CALL timestop(handle)
475 END SUBROUTINE linmin_fit
497 SUBROUTINE linmin_gold(gopt_env, xvec, xi, opt_energy, brent_tol, brent_max_iter, &
498 brack_limit, step, output_unit, globenv)
500 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec, xi
501 REAL(kind=
dp) :: opt_energy, brent_tol
502 INTEGER :: brent_max_iter
503 REAL(kind=
dp) :: brack_limit, step
504 INTEGER :: output_unit
507 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_gold'
510 REAL(kind=
dp) :: ax, bx, xmin, xx
511 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
513 CALL timeset(routinen, handle)
515 NULLIFY (pcom, xicom)
516 ALLOCATE (pcom(
SIZE(xvec)))
517 ALLOCATE (xicom(
SIZE(xvec)))
521 xicom = xicom/norm2(xicom)
525 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, brack_limit, output_unit, &
528 opt_energy = cg_dbrent(gopt_env, ax, xx, bx, brent_tol, brent_max_iter, &
529 xmin, pcom, xicom, output_unit, globenv)
535 CALL timestop(handle)
536 END SUBROUTINE linmin_gold
559 SUBROUTINE cg_mnbrak(gopt_env, ax, bx, cx, pcom, xicom, brack_limit, output_unit, &
562 REAL(kind=
dp) :: ax, bx, cx
563 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
564 REAL(kind=
dp) :: brack_limit
565 INTEGER :: output_unit
566 REAL(kind=
dp),
DIMENSION(:, :),
OPTIONAL,
POINTER :: histpoint
569 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_mnbrak'
571 INTEGER :: handle, loc_iter, odim
572 LOGICAL :: hist, should_stop
573 REAL(kind=
dp) :: dum, fa, fb, fc, fu, gold, q, r, u, ulim
575 CALL timeset(routinen, handle)
576 hist =
PRESENT(histpoint)
578 cpassert(.NOT.
ASSOCIATED(histpoint))
579 ALLOCATE (histpoint(3, 3))
581 gold = (1.0_dp + sqrt(5.0_dp))/2.0_dp
584 histpoint(1, 3) = cg_deval1d(gopt_env, ax, pcom, xicom, fa)
587 histpoint(2, 3) = cg_deval1d(gopt_env, bx, pcom, xicom, fb)
590 fa = cg_eval1d(gopt_env, ax, pcom, xicom)
591 fb = cg_eval1d(gopt_env, bx, pcom, xicom)
601 cx = bx + gold*(bx - ax)
604 histpoint(3, 3) = cg_deval1d(gopt_env, cx, pcom, xicom, fc)
607 fc = cg_eval1d(gopt_env, cx, pcom, xicom)
612 IF (should_stop)
EXIT
614 r = (bx - ax)*(fb - fc)
615 q = (bx - cx)*(fb - fa)
616 u = bx - ((bx - cx)*q - (bx - ax)*r)/(2.0_dp*sign(max(abs(q - r), tiny(0.0_dp)), q - r))
617 ulim = bx + brack_limit*(cx - bx)
618 IF ((bx - u)*(u - cx) > 0.0_dp)
THEN
620 odim =
SIZE(histpoint, 1)
622 histpoint(odim + 1, 1) = u
623 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
624 histpoint(odim + 1, 2) = fu
626 fu = cg_eval1d(gopt_env, u, pcom, xicom)
628 loc_iter = loc_iter + 1
635 ELSE IF (fu > fb)
THEN
640 u = cx + gold*(cx - bx)
642 odim =
SIZE(histpoint, 1)
644 histpoint(odim + 1, 1) = u
645 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
646 histpoint(odim + 1, 2) = fu
648 fu = cg_eval1d(gopt_env, u, pcom, xicom)
650 loc_iter = loc_iter + 1
651 ELSE IF ((cx - u)*(u - ulim) > 0.)
THEN
653 odim =
SIZE(histpoint, 1)
655 histpoint(odim + 1, 1) = u
656 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
657 histpoint(odim + 1, 2) = fu
659 fu = cg_eval1d(gopt_env, u, pcom, xicom)
661 loc_iter = loc_iter + 1
665 u = cx + gold*(cx - bx)
669 odim =
SIZE(histpoint, 1)
671 histpoint(odim + 1, 1) = u
672 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
673 histpoint(odim + 1, 2) = fu
675 fu = cg_eval1d(gopt_env, u, pcom, xicom)
677 loc_iter = loc_iter + 1
679 ELSE IF ((u - ulim)*(ulim - cx) >= 0.)
THEN
682 odim =
SIZE(histpoint, 1)
684 histpoint(odim + 1, 1) = u
685 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
686 histpoint(odim + 1, 2) = fu
688 fu = cg_eval1d(gopt_env, u, pcom, xicom)
690 loc_iter = loc_iter + 1
692 u = cx + gold*(cx - bx)
694 odim =
SIZE(histpoint, 1)
696 histpoint(odim + 1, 1) = u
697 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
698 histpoint(odim + 1, 2) = fu
700 fu = cg_eval1d(gopt_env, u, pcom, xicom)
702 loc_iter = loc_iter + 1
711 IF (output_unit > 0)
THEN
712 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
713 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
714 "***",
"MNBRACK - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
715 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
717 CALL timestop(handle)
718 END SUBROUTINE cg_mnbrak
747 FUNCTION cg_dbrent(gopt_env, ax, bx, cx, tol, itmax, xmin, pcom, xicom, output_unit, &
748 globenv)
RESULT(dbrent)
750 REAL(kind=
dp) :: ax, bx, cx, tol
752 REAL(kind=
dp) :: xmin
753 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
754 INTEGER :: output_unit
756 REAL(kind=
dp) :: dbrent
758 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_dbrent'
759 REAL(kind=
dp),
PARAMETER :: zeps = 1.0e-8_dp
761 INTEGER :: handle, iter, loc_iter
762 LOGICAL :: ok1, ok2, should_stop, skip0, skip1
763 REAL(kind=
dp) :: a, b, d, d1, d2, du, dv, dw, dx, e, fu, &
764 fv, fw, fx, olde, tol1, tol2, u, u1, &
767 CALL timeset(routinen, handle)
772 dx = cg_deval1d(gopt_env, x, pcom, xicom, fx)
780 IF (should_stop)
EXIT
783 tol1 = tol*abs(x) + zeps
787 IF (abs(x - xm) <= (tol2 - 0.5_dp*(b - a)))
EXIT
788 IF (abs(e) > tol1)
THEN
791 IF (dw /= dx) d1 = (w - x)*dx/(dx - dw)
792 IF (dv /= dx) d2 = (v - x)*dx/(dx - dv)
795 ok1 = ((a - u1)*(u1 - b) > 0.0_dp) .AND. (dx*d1 <= 0.0_dp)
796 ok2 = ((a - u2)*(u2 - b) > 0.0_dp) .AND. (dx*d2 <= 0.0_dp)
799 IF (.NOT. (ok1 .OR. ok2))
THEN
801 ELSE IF (ok1 .AND. ok2)
THEN
802 IF (abs(d1) < abs(d2))
THEN
812 IF (.NOT. skip0)
THEN
813 IF (abs(d) > abs(0.5_dp*olde)) skip0 = .true.
814 IF (.NOT. skip0)
THEN
816 IF ((u - a) < tol2 .OR. (b - u) < tol2) d = sign(tol1, xm - x)
821 IF (.NOT. skip1)
THEN
822 IF (dx >= 0.0_dp)
THEN
829 IF (abs(d) >= tol1)
THEN
831 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
832 loc_iter = loc_iter + 1
834 u = x + sign(tol1, d)
835 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
836 loc_iter = loc_iter + 1
845 v = w; fv = fw; dv = dw; w = x
846 fw = fx; dw = dx; x = u; fx = fu; dx = du
853 IF (fu <= fw .OR. w == x)
THEN
854 v = w; fv = fw; dv = dw
855 w = u; fw = fu; dw = du
856 ELSE IF (fu <= fv .OR. v == x .OR. v == w)
THEN
863 IF (output_unit > 0)
THEN
864 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
865 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
866 "***",
"BRENT - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
867 IF (iter == itmax + 1)
THEN
868 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,T78,A)") &
869 "***",
"BRENT - NUMBER OF ITERATIONS EXCEEDED ",
"***"
871 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
873 cpassert(iter /= itmax + 1)
876 CALL timestop(handle)
878 END FUNCTION cg_dbrent
892 FUNCTION cg_eval1d(gopt_env, x, pcom, xicom)
RESULT(my_val)
895 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
896 REAL(kind=
dp) :: my_val
898 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_eval1d'
901 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec
903 CALL timeset(routinen, handle)
905 ALLOCATE (xvec(
SIZE(pcom)))
906 xvec = pcom + x*xicom
907 CALL cp_eval_at(gopt_env, xvec, my_val, master=gopt_env%force_env%para_env%mepos, &
908 para_env=gopt_env%force_env%para_env)
911 CALL timestop(handle)
913 END FUNCTION cg_eval1d
928 FUNCTION cg_deval1d(gopt_env, x, pcom, xicom, fval)
RESULT(my_val)
931 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
932 REAL(kind=
dp) :: fval, my_val
934 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_deval1d'
937 REAL(kind=
dp) :: energy
938 REAL(kind=
dp),
DIMENSION(:),
POINTER :: grad, xvec
940 CALL timeset(routinen, handle)
942 ALLOCATE (xvec(
SIZE(pcom)))
943 ALLOCATE (grad(
SIZE(pcom)))
944 xvec = pcom + x*xicom
945 CALL cp_eval_at(gopt_env, xvec, energy, grad, master=gopt_env%force_env%para_env%mepos, &
946 para_env=gopt_env%force_env%para_env)
947 my_val = dot_product(grad, xicom)
951 CALL timestop(handle)
953 END FUNCTION cg_deval1d
965 FUNCTION findmin(x, y, dy)
RESULT(res)
966 REAL(kind=
dp),
DIMENSION(:) :: x, y, dy
969 INTEGER :: i, info, iwork(8*3), lwork, min_pos, np
970 REAL(kind=
dp) :: diag(3), res1(3), res2(3), res3(3), &
971 spread, sum_x, sum_xx, tmpw(1), &
973 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
974 REAL(kind=
dp),
DIMENSION(2*SIZE(x), 3) :: f
975 REAL(kind=
dp),
DIMENSION(2*SIZE(x)) :: b, w
976 REAL(kind=
dp) :: u(2*
SIZE(x), 3)
984 sum_xx = sum_xx + x(i)**2
986 IF (y(min_pos) > y(i)) min_pos = i
988 spread = sqrt(sum_xx/real(np,
dp) - (sum_x/real(np,
dp))**2)
990 w(i) = exp(-(real(np - i,
dp))**2/(real(2*9,
dp)))
991 w(i + np) = 2._dp*w(i)
996 f(i, 3) = x(i)**2*w(i)
998 f(i + np, 2) = w(i + np)
999 f(i + np, 3) = 2*x(i)*w(i + np)
1003 b(i + np) = dy(i)*w(i + np)
1006 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), tmpw, lwork, &
1008 lwork = ceiling(tmpw(1))
1009 ALLOCATE (work(lwork))
1010 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), work, lwork, &
1013 CALL dgemv(
'T',
SIZE(u, 1),
SIZE(u, 2), 1._dp, u,
SIZE(u, 1), b, 1, 0._dp, res1, 1)
1015 res2(i) = res1(i)/diag(i)
1017 CALL dgemv(
'T', 3, 3, 1._dp, vt,
SIZE(vt, 1), res2, 1, 0._dp, res3, 1)
1018 res = -0.5*res3(2)/res3(3)
1019 END FUNCTION findmin
1036 LOGICAL,
INTENT(IN) :: fletcher_reeves
1037 REAL(kind=
dp),
DIMENSION(:),
POINTER :: g, xi, h
1039 CHARACTER(len=*),
PARAMETER :: routinen =
'get_conjugate_direction'
1043 REAL(kind=
dp) :: dgg, gam, gg, norm, norm_h
1046 CALL timeset(routinen, handle)
1048 IF (.NOT. gopt_env%dimer_rotation)
THEN
1049 gg = dot_product(g, g)
1050 IF (fletcher_reeves)
THEN
1051 dgg = dot_product(xi, xi)
1053 dgg = dot_product((xi + g), xi)
1059 dimer_env => gopt_env%dimer_env
1060 check = abs(dot_product(g, g) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1063 check = abs(dot_product(xi, xi) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1066 check = abs(dot_product(h, dimer_env%cg_rot%nvec_old)) < max(1.0e-9_dp,
dimer_thrs)
1068 gg = dimer_env%cg_rot%norm_theta_old**2
1069 IF (fletcher_reeves)
THEN
1070 dgg = dimer_env%cg_rot%norm_theta**2
1072 norm = dimer_env%cg_rot%norm_theta*dimer_env%cg_rot%norm_theta_old
1073 dgg = dimer_env%cg_rot%norm_theta**2 + dot_product(g, xi)*norm
1076 CALL rotate_dimer(dimer_env%cg_rot%nvec_old, g, dimer_env%rot%angle2 +
pi/2.0_dp)
1079 h = -xi*dimer_env%cg_rot%norm_theta + gam*dimer_env%cg_rot%norm_h*dimer_env%cg_rot%nvec_old
1080 h = h - dot_product(h, dimer_env%nvec)*dimer_env%nvec
1082 IF (norm_h < epsilon(0.0_dp))
THEN
1087 dimer_env%cg_rot%norm_h = norm_h
1089 CALL timestop(handle)
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
subroutine, public 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...
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.
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