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'
70 LOGICAL :: use_only_grad
72 CALL timeset(routinen, handle)
73 gopt_env%do_line_search = .true.
74 SELECT CASE (gopt_env%type_id)
77 SELECT CASE (gopt_param%cg_ls%type_id)
79 IF (use_only_grad)
THEN
80 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=.true., &
81 output_unit=output_unit)
83 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, &
84 use_only_grad=gopt_param%cg_ls%grad_only, output_unit=output_unit)
87 CALL linmin_bracketed(gopt_env, xvec, xi, opt_energy, output_unit, gopt_param, globenv, &
88 use_fit=gopt_param%cg_ls%type_id ==
ls_fit)
90 IF (use_only_grad)
THEN
91 cpabort(
"Line Search type not yet implemented in CG for cell optimization.")
93 cpabort(
"Line Search type not yet implemented in CG.")
97 SELECT CASE (gopt_param%cg_ls%type_id)
99 IF (gopt_env%dimer_rotation)
THEN
100 CALL rotmin_2pnt(gopt_env, gopt_env%dimer_env, xvec, xi, opt_energy)
102 CALL tslmin_2pnt(gopt_env, gopt_env%dimer_env, xvec, xi, opt_energy, gopt_param, &
106 cpabort(
"Line Search type not yet implemented in CG for TS search.")
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=.true., &
112 output_unit=output_unit)
114 cpabort(
"Line Search type not yet implemented in CG for shellcore optimization.")
118 gopt_env%do_line_search = .false.
119 CALL timestop(handle)
136 RECURSIVE SUBROUTINE linmin_2pnt(gopt_env, x0, ls_vec, g, opt_energy, gopt_param, use_only_grad, &
139 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, ls_vec, g
140 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
142 LOGICAL,
INTENT(IN),
OPTIONAL :: use_only_grad
143 INTEGER,
INTENT(IN) :: output_unit
145 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_2pnt'
148 LOGICAL :: my_use_only_grad, &
149 save_consistent_energy_force
150 REAL(kind=
dp) :: a, b, c, dx, dx_min, dx_min_save, &
151 dx_thrs, norm_grad1, norm_grad2, &
152 norm_ls_vec, opt_energy2, x_grad_zero
153 REAL(kind=
dp),
DIMENSION(:),
POINTER :: gradient2, ls_norm
155 CALL timeset(routinen, handle)
156 norm_ls_vec = norm2(ls_vec)
157 my_use_only_grad = .false.
158 IF (
PRESENT(use_only_grad)) my_use_only_grad = use_only_grad
159 IF (norm_ls_vec /= 0.0_dp)
THEN
160 ALLOCATE (ls_norm(
SIZE(ls_vec)))
161 ALLOCATE (gradient2(
SIZE(ls_vec)))
162 ls_norm = ls_vec/norm_ls_vec
164 dx_thrs = gopt_param%cg_ls%max_step
168 save_consistent_energy_force = gopt_env%require_consistent_energy_force
169 gopt_env%require_consistent_energy_force = .NOT. my_use_only_grad
170 CALL cp_eval_at(gopt_env, x0, opt_energy2, gradient2, master=gopt_env%force_env%para_env%mepos, &
171 para_env=gopt_env%force_env%para_env)
172 gopt_env%require_consistent_energy_force = save_consistent_energy_force
174 norm_grad1 = -dot_product(g, ls_norm)
175 norm_grad2 = dot_product(gradient2, ls_norm)
176 IF (my_use_only_grad)
THEN
181 a = (norm_grad2 - b)/dx
193 a = (c - (opt_energy2 - norm_grad2*dx))/dx**2
194 b = norm_grad2 - 2.0_dp*a*dx
196 IF (a /= 0.0_dp) dx_min = -b/(2.0_dp*a)
197 opt_energy = opt_energy2
202 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
203 x0 = x0 + (dx_min - dx)*ls_norm
206 IF (output_unit > 0)
THEN
207 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
208 WRITE (unit=output_unit, fmt=
"(T2,A,T31,A,T78,A)") &
209 "***",
"2PNT LINE SEARCH INFO",
"***"
210 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
211 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
212 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
213 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
214 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min,
"***"
215 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
218 DEALLOCATE (gradient2)
223 CALL timestop(handle)
224 END SUBROUTINE linmin_2pnt
237 SUBROUTINE tslmin_2pnt(gopt_env, dimer_env, x0, tls_vec, opt_energy, gopt_param, output_unit)
240 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, tls_vec
241 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
243 INTEGER,
INTENT(IN) :: output_unit
245 CHARACTER(len=*),
PARAMETER :: routinen =
'tslmin_2pnt'
248 REAL(kind=
dp) :: dx, dx_min, dx_min_acc, dx_min_save, &
249 dx_thrs, norm_tls_vec, opt_energy2
250 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tls_norm
252 CALL timeset(routinen, handle)
253 norm_tls_vec = norm2(tls_vec)
254 IF (norm_tls_vec /= 0.0_dp)
THEN
255 ALLOCATE (tls_norm(
SIZE(tls_vec)))
257 tls_norm = tls_vec/norm_tls_vec
258 dimer_env%tsl%tls_vec => tls_norm
261 dx_thrs = gopt_param%cg_ls%max_step
263 IF (dimer_env%rot%curvature > 0) dx = dx_thrs
264 x0 = x0 + dx*tls_norm
265 CALL cp_eval_at(gopt_env, x0, opt_energy2, master=gopt_env%force_env%para_env%mepos, &
266 para_env=gopt_env%force_env%para_env)
267 IF (dimer_env%rot%curvature > 0)
THEN
273 dx_min = -opt_energy/(opt_energy2 - opt_energy)*dx
277 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
281 x0 = x0 + dx_min*tls_norm
284 IF (output_unit > 0)
THEN
285 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
286 WRITE (unit=output_unit, fmt=
"(T2,A,T24,A,T78,A)") &
287 "***",
"2PNT TRANSLATIONAL LINE SEARCH INFO",
"***"
288 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
289 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T78,A)") &
290 "***",
"LOCAL CURVATURE =", dimer_env%rot%curvature,
"***"
291 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
292 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
293 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
294 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min_acc,
"***"
295 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
299 CALL cp_eval_at(gopt_env, x0, opt_energy, master=gopt_env%force_env%para_env%mepos, &
300 para_env=gopt_env%force_env%para_env)
302 DEALLOCATE (tls_norm)
307 CALL timestop(handle)
309 END SUBROUTINE tslmin_2pnt
320 SUBROUTINE rotmin_2pnt(gopt_env, dimer_env, x0, theta, opt_energy)
323 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, theta
324 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
326 CHARACTER(len=*),
PARAMETER :: routinen =
'rotmin_2pnt'
329 REAL(kind=
dp) :: a0, a1, angle, b1, curvature0, &
330 curvature1, curvature2, dcdp, f
331 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
333 CALL timeset(routinen, handle)
334 curvature0 = dimer_env%rot%curvature
335 dcdp = dimer_env%rot%dCdp
337 angle = -0.5_dp*atan(dcdp/(2.0_dp*abs(curvature0)))
338 dimer_env%rot%angle1 = angle
339 dimer_env%cg_rot%nvec_old = dimer_env%nvec
340 IF (angle > dimer_env%rot%angle_tol)
THEN
344 CALL cp_eval_at(gopt_env, x0, f, master=gopt_env%force_env%para_env%mepos, &
345 para_env=gopt_env%force_env%para_env)
347 curvature1 = dimer_env%rot%curvature
348 a1 = (curvature0 - curvature1 + b1*sin(2.0_dp*angle))/(1.0_dp - cos(2.0_dp*angle))
349 a0 = 2.0_dp*(curvature0 - a1)
350 angle = 0.5_dp*atan(b1/a1)
351 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*angle) + b1*sin(2.0_dp*angle)
352 IF (curvature2 > curvature0)
THEN
353 angle = angle +
pi/2.0_dp
354 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*angle) + b1*sin(2.0_dp*angle)
356 dimer_env%rot%angle2 = angle
357 dimer_env%rot%curvature = curvature2
359 dimer_env%nvec = dimer_env%cg_rot%nvec_old
364 ALLOCATE (work(
SIZE(dimer_env%nvec)))
365 work = dimer_env%rot%g1
366 work = sin(dimer_env%rot%angle1 - dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1 + &
367 sin(dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1p + &
368 (1.0_dp - cos(dimer_env%rot%angle2) - sin(dimer_env%rot%angle2)*tan(dimer_env%rot%angle1/2.0_dp))* &
370 work = -2.0_dp*(work - dimer_env%rot%g0)
371 work = work - dot_product(work, dimer_env%nvec)*dimer_env%nvec
372 opt_energy = norm2(work)
375 dimer_env%rot%angle2 = angle
376 CALL timestop(handle)
378 END SUBROUTINE rotmin_2pnt
394 SUBROUTINE linmin_bracketed(gopt_env, xvec, xi, opt_energy, output_unit, gopt_param, globenv, use_fit)
396 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec, xi
397 REAL(kind=
dp) :: opt_energy
398 INTEGER :: output_unit
401 LOGICAL,
INTENT(IN) :: use_fit
403 CHARACTER(len=*),
PARAMETER :: fit_routinen =
'linmin_fit', &
404 gold_routinen =
'linmin_gold'
406 INTEGER :: handle, loc_iter, odim
407 LOGICAL :: should_stop
408 REAL(kind=
dp) :: ax, bx, fprev, rms_dr, rms_force, scale, &
410 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
411 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: hist
414 CALL timeset(fit_routinen, handle)
416 CALL timeset(gold_routinen, handle)
419 NULLIFY (pcom, xicom, hist)
421 rms_dr = gopt_param%rms_dr
422 rms_force = gopt_param%rms_force
424 ALLOCATE (pcom(
SIZE(xvec)))
425 ALLOCATE (xicom(
SIZE(xvec)))
429 xicom = xicom/norm2(xicom)
431 gopt_param%cg_ls%initial_step = gopt_param%cg_ls%initial_step*0.8_dp
433 xx = gopt_param%cg_ls%initial_step
435 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, gopt_param%cg_ls%brack_limit, output_unit, &
436 histpoint=hist, globenv=globenv)
439 opt_energy = minval(hist(:, 2))
443 DO WHILE (abs(hist(odim, 3)) > rms_force*scale .OR. &
444 abs(hist(odim, 1) - hist(odim - 1, 1)) > scale*rms_dr)
446 IF (should_stop)
EXIT
448 loc_iter = loc_iter + 1
450 xmin = findmin(hist(:, 1), hist(:, 2), hist(:, 3))
452 hist(odim + 1, 1) = xmin
453 hist(odim + 1, 3) = cg_deval1d(gopt_env, xmin, pcom, xicom, opt_energy)
454 hist(odim + 1, 2) = opt_energy
458 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, gopt_param%cg_ls%brack_limit, output_unit, &
460 opt_energy = cg_dbrent(gopt_env, ax, xx, bx, gopt_param%cg_ls%brent_tol, &
461 gopt_param%cg_ls%brent_max_iter, xmin, pcom, xicom, output_unit, globenv)
465 gopt_param%cg_ls%initial_step = xmin
472 IF (use_fit .AND. output_unit > 0)
THEN
473 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
474 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
475 "***",
"FIT LS - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
476 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
478 CALL timestop(handle)
480 END SUBROUTINE linmin_bracketed
503 SUBROUTINE cg_mnbrak(gopt_env, ax, bx, cx, pcom, xicom, brack_limit, output_unit, &
506 REAL(kind=
dp) :: ax, bx, cx
507 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
508 REAL(kind=
dp) :: brack_limit
509 INTEGER :: output_unit
510 REAL(kind=
dp),
DIMENSION(:, :),
OPTIONAL,
POINTER :: histpoint
513 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_mnbrak'
515 INTEGER :: handle, loc_iter, odim
516 LOGICAL :: hist, should_stop
517 REAL(kind=
dp) :: dum, fa, fb, fc, fu, gold, q, r, u, ulim
519 CALL timeset(routinen, handle)
520 hist =
PRESENT(histpoint)
522 cpassert(.NOT.
ASSOCIATED(histpoint))
523 ALLOCATE (histpoint(3, 3))
525 gold = (1.0_dp + sqrt(5.0_dp))/2.0_dp
528 histpoint(1, 3) = cg_deval1d(gopt_env, ax, pcom, xicom, fa)
531 histpoint(2, 3) = cg_deval1d(gopt_env, bx, pcom, xicom, fb)
534 fa = cg_eval1d(gopt_env, ax, pcom, xicom)
535 fb = cg_eval1d(gopt_env, bx, pcom, xicom)
545 cx = bx + gold*(bx - ax)
548 histpoint(3, 3) = cg_deval1d(gopt_env, cx, pcom, xicom, fc)
551 fc = cg_eval1d(gopt_env, cx, pcom, xicom)
556 IF (should_stop)
EXIT
558 r = (bx - ax)*(fb - fc)
559 q = (bx - cx)*(fb - fa)
560 u = bx - ((bx - cx)*q - (bx - ax)*r)/(2.0_dp*sign(max(abs(q - r), tiny(0.0_dp)), q - r))
561 ulim = bx + brack_limit*(cx - bx)
562 IF ((bx - u)*(u - cx) > 0.0_dp)
THEN
564 odim =
SIZE(histpoint, 1)
566 histpoint(odim + 1, 1) = u
567 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
568 histpoint(odim + 1, 2) = fu
570 fu = cg_eval1d(gopt_env, u, pcom, xicom)
572 loc_iter = loc_iter + 1
579 ELSE IF (fu > fb)
THEN
584 u = cx + gold*(cx - bx)
586 odim =
SIZE(histpoint, 1)
588 histpoint(odim + 1, 1) = u
589 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
590 histpoint(odim + 1, 2) = fu
592 fu = cg_eval1d(gopt_env, u, pcom, xicom)
594 loc_iter = loc_iter + 1
595 ELSE IF ((cx - u)*(u - ulim) > 0.0_dp)
THEN
597 odim =
SIZE(histpoint, 1)
599 histpoint(odim + 1, 1) = u
600 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
601 histpoint(odim + 1, 2) = fu
603 fu = cg_eval1d(gopt_env, u, pcom, xicom)
605 loc_iter = loc_iter + 1
609 u = cx + gold*(cx - bx)
613 odim =
SIZE(histpoint, 1)
615 histpoint(odim + 1, 1) = u
616 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
617 histpoint(odim + 1, 2) = fu
619 fu = cg_eval1d(gopt_env, u, pcom, xicom)
621 loc_iter = loc_iter + 1
623 ELSE IF ((u - ulim)*(ulim - cx) >= 0.0_dp)
THEN
626 odim =
SIZE(histpoint, 1)
628 histpoint(odim + 1, 1) = u
629 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
630 histpoint(odim + 1, 2) = fu
632 fu = cg_eval1d(gopt_env, u, pcom, xicom)
634 loc_iter = loc_iter + 1
636 u = cx + gold*(cx - bx)
638 odim =
SIZE(histpoint, 1)
640 histpoint(odim + 1, 1) = u
641 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
642 histpoint(odim + 1, 2) = fu
644 fu = cg_eval1d(gopt_env, u, pcom, xicom)
646 loc_iter = loc_iter + 1
655 IF (output_unit > 0)
THEN
656 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
657 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
658 "***",
"MNBRACK - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
659 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
661 CALL timestop(handle)
662 END SUBROUTINE cg_mnbrak
691 FUNCTION cg_dbrent(gopt_env, ax, bx, cx, tol, itmax, xmin, pcom, xicom, output_unit, &
692 globenv)
RESULT(dbrent)
694 REAL(kind=
dp) :: ax, bx, cx, tol
696 REAL(kind=
dp) :: xmin
697 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
698 INTEGER :: output_unit
700 REAL(kind=
dp) :: dbrent
702 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_dbrent'
703 REAL(kind=
dp),
PARAMETER :: zeps = 1.0e-8_dp
705 INTEGER :: handle, iter, loc_iter
706 LOGICAL :: ok1, ok2, should_stop, skip0, skip1
707 REAL(kind=
dp) :: a, b, d, d1, d2, du, dv, dw, dx, e, fu, &
708 fv, fw, fx, olde, tol1, tol2, u, u1, &
711 CALL timeset(routinen, handle)
716 dx = cg_deval1d(gopt_env, x, pcom, xicom, fx)
724 IF (should_stop)
EXIT
727 tol1 = tol*abs(x) + zeps
731 IF (abs(x - xm) <= (tol2 - 0.5_dp*(b - a)))
EXIT
732 IF (abs(e) > tol1)
THEN
735 IF (dw /= dx) d1 = (w - x)*dx/(dx - dw)
736 IF (dv /= dx) d2 = (v - x)*dx/(dx - dv)
739 ok1 = ((a - u1)*(u1 - b) > 0.0_dp) .AND. (dx*d1 <= 0.0_dp)
740 ok2 = ((a - u2)*(u2 - b) > 0.0_dp) .AND. (dx*d2 <= 0.0_dp)
743 IF (.NOT. (ok1 .OR. ok2))
THEN
745 ELSE IF (ok1 .AND. ok2)
THEN
746 IF (abs(d1) < abs(d2))
THEN
756 IF (.NOT. skip0)
THEN
757 IF (abs(d) > abs(0.5_dp*olde)) skip0 = .true.
758 IF (.NOT. skip0)
THEN
760 IF ((u - a) < tol2 .OR. (b - u) < tol2) d = sign(tol1, xm - x)
765 IF (.NOT. skip1)
THEN
766 IF (dx >= 0.0_dp)
THEN
773 IF (abs(d) >= tol1)
THEN
775 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
776 loc_iter = loc_iter + 1
778 u = x + sign(tol1, d)
779 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
780 loc_iter = loc_iter + 1
789 v = w; fv = fw; dv = dw; w = x
790 fw = fx; dw = dx; x = u; fx = fu; dx = du
797 IF (fu <= fw .OR. w == x)
THEN
798 v = w; fv = fw; dv = dw
799 w = u; fw = fu; dw = du
800 ELSE IF (fu <= fv .OR. v == x .OR. v == w)
THEN
807 IF (output_unit > 0)
THEN
808 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
809 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
810 "***",
"BRENT - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
811 IF (iter == itmax + 1)
THEN
812 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,T78,A)") &
813 "***",
"BRENT - NUMBER OF ITERATIONS EXCEEDED ",
"***"
815 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
817 cpassert(iter /= itmax + 1)
820 CALL timestop(handle)
822 END FUNCTION cg_dbrent
833 SUBROUTINE cg_eval1d_trial(gopt_env, x, pcom, xicom, energy, gradient)
836 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
837 REAL(kind=
dp) :: energy
838 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL,
POINTER :: gradient
840 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec
842 ALLOCATE (xvec(
SIZE(pcom)))
843 xvec = pcom + x*xicom
844 CALL cp_eval_at(gopt_env, xvec, energy, gradient, master=gopt_env%force_env%para_env%mepos, &
845 para_env=gopt_env%force_env%para_env)
848 END SUBROUTINE cg_eval1d_trial
862 FUNCTION cg_eval1d(gopt_env, x, pcom, xicom)
RESULT(my_val)
865 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
866 REAL(kind=
dp) :: my_val
868 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_eval1d'
872 CALL timeset(routinen, handle)
874 CALL cg_eval1d_trial(gopt_env, x, pcom, xicom, my_val)
876 CALL timestop(handle)
878 END FUNCTION cg_eval1d
893 FUNCTION cg_deval1d(gopt_env, x, pcom, xicom, fval)
RESULT(my_val)
896 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
897 REAL(kind=
dp) :: fval, my_val
899 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_deval1d'
902 REAL(kind=
dp) :: energy
903 REAL(kind=
dp),
DIMENSION(:),
POINTER :: grad
905 CALL timeset(routinen, handle)
907 ALLOCATE (grad(
SIZE(pcom)))
908 CALL cg_eval1d_trial(gopt_env, x, pcom, xicom, energy, gradient=grad)
909 my_val = dot_product(grad, xicom)
912 CALL timestop(handle)
914 END FUNCTION cg_deval1d
926 FUNCTION findmin(x, y, dy)
RESULT(res)
927 REAL(kind=
dp),
DIMENSION(:) :: x, y, dy
930 INTEGER :: i, info, iwork(8*3), lwork, min_pos, np
931 REAL(kind=
dp) :: diag(3), res1(3), res2(3), res3(3), &
932 spread, sum_x, sum_xx, tmpw(1), &
934 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
935 REAL(kind=
dp),
DIMENSION(2*SIZE(x), 3) :: f
936 REAL(kind=
dp),
DIMENSION(2*SIZE(x)) :: b, w
937 REAL(kind=
dp) :: u(2*
SIZE(x), 3)
945 sum_xx = sum_xx + x(i)**2
947 IF (y(min_pos) > y(i)) min_pos = i
949 spread = sqrt(sum_xx/real(np,
dp) - (sum_x/real(np,
dp))**2)
951 w(i) = exp(-(real(np - i,
dp))**2/(real(2*9,
dp)))
952 w(i + np) = 2._dp*w(i)
957 f(i, 3) = x(i)**2*w(i)
959 f(i + np, 2) = w(i + np)
960 f(i + np, 3) = 2*x(i)*w(i + np)
964 b(i + np) = dy(i)*w(i + np)
967 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), tmpw, lwork, &
969 lwork = ceiling(tmpw(1))
970 ALLOCATE (work(lwork))
971 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), work, lwork, &
974 CALL dgemv(
'T',
SIZE(u, 1),
SIZE(u, 2), 1._dp, u,
SIZE(u, 1), b, 1, 0._dp, res1, 1)
976 res2(i) = res1(i)/diag(i)
978 CALL dgemv(
'T', 3, 3, 1._dp, vt,
SIZE(vt, 1), res2, 1, 0._dp, res3, 1)
979 res = -0.5_dp*res3(2)/res3(3)
997 LOGICAL,
INTENT(IN) :: fletcher_reeves
998 REAL(kind=
dp),
DIMENSION(:),
POINTER :: g, xi, h
1000 CHARACTER(len=*),
PARAMETER :: routinen =
'get_conjugate_direction'
1004 REAL(kind=
dp) :: dgg, gam, gg, norm, norm_h
1007 CALL timeset(routinen, handle)
1009 IF (.NOT. gopt_env%dimer_rotation)
THEN
1010 gg = dot_product(g, g)
1011 IF (fletcher_reeves)
THEN
1012 dgg = dot_product(xi, xi)
1014 dgg = dot_product((xi + g), xi)
1020 dimer_env => gopt_env%dimer_env
1024 check = abs(dot_product(xi, xi) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1027 check = abs(dot_product(h, dimer_env%cg_rot%nvec_old)) < max(1.0e-9_dp,
dimer_thrs)
1029 gg = dimer_env%cg_rot%norm_theta_old**2
1030 IF (fletcher_reeves)
THEN
1031 dgg = dimer_env%cg_rot%norm_theta**2
1033 norm = dimer_env%cg_rot%norm_theta*dimer_env%cg_rot%norm_theta_old
1034 dgg = dimer_env%cg_rot%norm_theta**2 + dot_product(g, xi)*norm
1037 CALL rotate_dimer(dimer_env%cg_rot%nvec_old, g, dimer_env%rot%angle2 +
pi/2.0_dp)
1040 h = -xi*dimer_env%cg_rot%norm_theta + gam*dimer_env%cg_rot%norm_h*dimer_env%cg_rot%nvec_old
1041 h = h - dot_product(h, dimer_env%nvec)*dimer_env%nvec
1043 IF (norm_h < epsilon(0.0_dp))
THEN
1048 dimer_env%cg_rot%norm_h = norm_h
1050 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, 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.
subroutine check(condition, label)
Stops with an error message if a test fails.
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