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
98 TYPE(gopt_param_type),
POINTER :: gopt_param
99 TYPE(global_environment_type),
POINTER :: globenv
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_gold(gopt_env, xvec, xi, opt_energy, gopt_param%cg_ls%brent_tol, &
142 gopt_param%cg_ls%brent_max_iter, gopt_param%cg_ls%brack_limit, &
143 gopt_param%cg_ls%initial_step, output_unit, globenv)
145 cpabort(
"Line Search type not yet implemented in CG for cell optimization.")
148 SELECT CASE (gopt_param%cg_ls%type_id)
150 CALL linmin_2pnt(gopt_env, xvec, xi, g, opt_energy, gopt_param, use_only_grad=.true., &
151 output_unit=output_unit)
153 cpabort(
"Line Search type not yet implemented in CG for shellcore optimization.")
157 gopt_env%do_line_search = .false.
158 CALL timestop(handle)
175 RECURSIVE SUBROUTINE linmin_2pnt(gopt_env, x0, ls_vec, g, opt_energy, gopt_param, use_only_grad, &
177 TYPE(gopt_f_type),
POINTER :: gopt_env
178 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, ls_vec, g
179 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
180 TYPE(gopt_param_type),
POINTER :: gopt_param
181 LOGICAL,
INTENT(IN),
OPTIONAL :: use_only_grad
182 INTEGER,
INTENT(IN) :: output_unit
184 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_2pnt'
187 LOGICAL :: my_use_only_grad, &
188 save_consistent_energy_force
189 REAL(kind=
dp) :: a, b, c, dx, dx_min, dx_min_save, &
190 dx_thrs, norm_grad1, norm_grad2, &
191 norm_ls_vec, opt_energy2, x_grad_zero
192 REAL(kind=
dp),
DIMENSION(:),
POINTER :: gradient2, ls_norm
194 CALL timeset(routinen, handle)
195 norm_ls_vec = sqrt(dot_product(ls_vec, ls_vec))
196 my_use_only_grad = .false.
197 IF (
PRESENT(use_only_grad)) my_use_only_grad = use_only_grad
198 IF (norm_ls_vec /= 0.0_dp)
THEN
199 ALLOCATE (ls_norm(
SIZE(ls_vec)))
200 ALLOCATE (gradient2(
SIZE(ls_vec)))
201 ls_norm = ls_vec/norm_ls_vec
203 dx_thrs = gopt_param%cg_ls%max_step
207 save_consistent_energy_force = gopt_env%require_consistent_energy_force
208 gopt_env%require_consistent_energy_force = .NOT. my_use_only_grad
209 CALL cp_eval_at(gopt_env, x0, opt_energy2, gradient2, master=gopt_env%force_env%para_env%mepos, &
210 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
211 gopt_env%require_consistent_energy_force = save_consistent_energy_force
213 norm_grad1 = -dot_product(g, ls_norm)
214 norm_grad2 = dot_product(gradient2, ls_norm)
215 IF (my_use_only_grad)
THEN
220 a = (norm_grad2 - b)/dx
232 a = (c - (opt_energy2 - norm_grad2*dx))/dx**2
233 b = norm_grad2 - 2.0_dp*a*dx
235 IF (a /= 0.0_dp) dx_min = -b/(2.0_dp*a)
236 opt_energy = opt_energy2
241 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
242 x0 = x0 + (dx_min - dx)*ls_norm
245 IF (output_unit > 0)
THEN
246 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
247 WRITE (unit=output_unit, fmt=
"(T2,A,T31,A,T78,A)") &
248 "***",
"2PNT LINE SEARCH INFO",
"***"
249 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
250 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
251 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
252 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
253 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min,
"***"
254 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
257 DEALLOCATE (gradient2)
262 CALL timestop(handle)
263 END SUBROUTINE linmin_2pnt
276 SUBROUTINE tslmin_2pnt(gopt_env, dimer_env, x0, tls_vec, opt_energy, gopt_param, output_unit)
277 TYPE(gopt_f_type),
POINTER :: gopt_env
278 TYPE(dimer_env_type),
POINTER :: dimer_env
279 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, tls_vec
280 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
281 TYPE(gopt_param_type),
POINTER :: gopt_param
282 INTEGER,
INTENT(IN) :: output_unit
284 CHARACTER(len=*),
PARAMETER :: routinen =
'tslmin_2pnt'
287 REAL(kind=
dp) :: dx, dx_min, dx_min_acc, dx_min_save, &
288 dx_thrs, norm_tls_vec, opt_energy2
289 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tls_norm
291 CALL timeset(routinen, handle)
292 norm_tls_vec = sqrt(dot_product(tls_vec, tls_vec))
293 IF (norm_tls_vec /= 0.0_dp)
THEN
294 ALLOCATE (tls_norm(
SIZE(tls_vec)))
296 tls_norm = tls_vec/norm_tls_vec
297 dimer_env%tsl%tls_vec => tls_norm
300 dx_thrs = gopt_param%cg_ls%max_step
302 IF (dimer_env%rot%curvature > 0) dx = dx_thrs
303 x0 = x0 + dx*tls_norm
304 CALL cp_eval_at(gopt_env, x0, opt_energy2, master=gopt_env%force_env%para_env%mepos, &
305 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
306 IF (dimer_env%rot%curvature > 0)
THEN
312 dx_min = -opt_energy/(opt_energy2 - opt_energy)*dx
316 IF (abs(dx_min) > dx_thrs) dx_min = sign(1.0_dp, dx_min)*dx_thrs
320 x0 = x0 + dx_min*tls_norm
323 IF (output_unit > 0)
THEN
324 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
325 WRITE (unit=output_unit, fmt=
"(T2,A,T24,A,T78,A)") &
326 "***",
"2PNT TRANSLATIONAL LINE SEARCH INFO",
"***"
327 WRITE (unit=output_unit, fmt=
"(T2,A,T78,A)")
"***",
"***"
328 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T78,A)") &
329 "***",
"LOCAL CURVATURE =", dimer_env%rot%curvature,
"***"
330 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
331 "***",
"DX (EVALUATED)=", dx,
"DX (THRESHOLD)=", dx_thrs,
"***"
332 WRITE (unit=output_unit, fmt=
"(T2,A,3X,A,F12.6,T45,A,F12.6,T78,A)") &
333 "***",
"DX (FITTED )=", dx_min_save,
"DX (ACCEPTED )=", dx_min_acc,
"***"
334 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
338 CALL cp_eval_at(gopt_env, x0, opt_energy, master=gopt_env%force_env%para_env%mepos, &
339 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
341 DEALLOCATE (tls_norm)
346 CALL timestop(handle)
348 END SUBROUTINE tslmin_2pnt
359 SUBROUTINE rotmin_2pnt(gopt_env, dimer_env, x0, theta, opt_energy)
360 TYPE(gopt_f_type),
POINTER :: gopt_env
361 TYPE(dimer_env_type),
POINTER :: dimer_env
362 REAL(kind=
dp),
DIMENSION(:),
POINTER :: x0, theta
363 REAL(kind=
dp),
INTENT(INOUT) :: opt_energy
365 CHARACTER(len=*),
PARAMETER :: routinen =
'rotmin_2pnt'
368 REAL(kind=
dp) :: a0, a1,
angle, b1, curvature0, &
369 curvature1, curvature2, dcdp, f
370 REAL(kind=
dp),
DIMENSION(:),
POINTER :: work
372 CALL timeset(routinen, handle)
373 curvature0 = dimer_env%rot%curvature
374 dcdp = dimer_env%rot%dCdp
376 angle = -0.5_dp*atan(dcdp/(2.0_dp*abs(curvature0)))
377 dimer_env%rot%angle1 =
angle
378 dimer_env%cg_rot%nvec_old = dimer_env%nvec
379 IF (
angle > dimer_env%rot%angle_tol)
THEN
383 CALL cp_eval_at(gopt_env, x0, f, master=gopt_env%force_env%para_env%mepos, &
384 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
386 curvature1 = dimer_env%rot%curvature
387 a1 = (curvature0 - curvature1 + b1*sin(2.0_dp*
angle))/(1.0_dp - cos(2.0_dp*
angle))
388 a0 = 2.0_dp*(curvature0 - a1)
389 angle = 0.5_dp*atan(b1/a1)
390 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*
angle) + b1*sin(2.0_dp*
angle)
391 IF (curvature2 > curvature0)
THEN
393 curvature2 = a0/2.0_dp + a1*cos(2.0_dp*
angle) + b1*sin(2.0_dp*
angle)
395 dimer_env%rot%angle2 =
angle
396 dimer_env%rot%curvature = curvature2
398 dimer_env%nvec = dimer_env%cg_rot%nvec_old
403 ALLOCATE (work(
SIZE(dimer_env%nvec)))
404 work = dimer_env%rot%g1
405 work = sin(dimer_env%rot%angle1 - dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1 + &
406 sin(dimer_env%rot%angle2)/sin(dimer_env%rot%angle1)*dimer_env%rot%g1p + &
407 (1.0_dp - cos(dimer_env%rot%angle2) - sin(dimer_env%rot%angle2)*tan(dimer_env%rot%angle1/2.0_dp))* &
409 work = -2.0_dp*(work - dimer_env%rot%g0)
410 work = work - dot_product(work, dimer_env%nvec)*dimer_env%nvec
411 opt_energy = sqrt(dot_product(work, work))
414 dimer_env%rot%angle2 =
angle
415 CALL timestop(handle)
417 END SUBROUTINE rotmin_2pnt
438 SUBROUTINE linmin_fit(gopt_env, xvec, xi, opt_energy, &
439 brack_limit, step, output_unit, gopt_param, globenv)
440 TYPE(gopt_f_type),
POINTER :: gopt_env
441 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec, xi
442 REAL(kind=
dp) :: opt_energy, brack_limit, step
443 INTEGER :: output_unit
444 TYPE(gopt_param_type),
POINTER :: gopt_param
445 TYPE(global_environment_type),
POINTER :: globenv
447 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_fit'
449 INTEGER :: handle, loc_iter, odim
450 LOGICAL :: should_stop
451 REAL(kind=
dp) :: ax, bx, fprev, rms_dr, rms_force, scale, &
453 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
454 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: hist
456 CALL timeset(routinen, handle)
458 NULLIFY (pcom, xicom, hist)
459 rms_dr = gopt_param%rms_dr
460 rms_force = gopt_param%rms_force
461 ALLOCATE (pcom(
SIZE(xvec)))
462 ALLOCATE (xicom(
SIZE(xvec)))
466 xicom = xicom/sqrt(dot_product(xicom, xicom))
470 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, brack_limit, output_unit, &
471 histpoint=hist, globenv=globenv)
474 opt_energy = minval(hist(:, 2))
478 DO WHILE (abs(hist(odim, 3)) > rms_force*scale .OR. abs(hist(odim, 1) - hist(odim - 1, 1)) > scale*rms_dr)
480 IF (should_stop)
EXIT
482 loc_iter = loc_iter + 1
484 xmin = findmin(hist(:, 1), hist(:, 2), hist(:, 3))
485 CALL reallocate(hist, 1, odim + 1, 1, 3)
486 hist(odim + 1, 1) = xmin
487 hist(odim + 1, 3) = cg_deval1d(gopt_env, xmin, pcom, xicom, opt_energy)
488 hist(odim + 1, 2) = opt_energy
498 IF (output_unit > 0)
THEN
499 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
500 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
501 "***",
"FIT LS - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
502 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
504 CALL timestop(handle)
506 END SUBROUTINE linmin_fit
528 SUBROUTINE linmin_gold(gopt_env, xvec, xi, opt_energy, brent_tol, brent_max_iter, &
529 brack_limit, step, output_unit, globenv)
530 TYPE(gopt_f_type),
POINTER :: gopt_env
531 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec, xi
532 REAL(kind=
dp) :: opt_energy, brent_tol
533 INTEGER :: brent_max_iter
534 REAL(kind=
dp) :: brack_limit, step
535 INTEGER :: output_unit
536 TYPE(global_environment_type),
POINTER :: globenv
538 CHARACTER(len=*),
PARAMETER :: routinen =
'linmin_gold'
541 REAL(kind=
dp) :: ax, bx, xmin, xx
542 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
544 CALL timeset(routinen, handle)
546 NULLIFY (pcom, xicom)
547 ALLOCATE (pcom(
SIZE(xvec)))
548 ALLOCATE (xicom(
SIZE(xvec)))
552 xicom = xicom/sqrt(dot_product(xicom, xicom))
556 CALL cg_mnbrak(gopt_env, ax, xx, bx, pcom, xicom, brack_limit, output_unit, &
559 opt_energy = cg_dbrent(gopt_env, ax, xx, bx, brent_tol, brent_max_iter, &
560 xmin, pcom, xicom, output_unit, globenv)
566 CALL timestop(handle)
567 END SUBROUTINE linmin_gold
590 SUBROUTINE cg_mnbrak(gopt_env, ax, bx, cx, pcom, xicom, brack_limit, output_unit, &
592 TYPE(gopt_f_type),
POINTER :: gopt_env
593 REAL(kind=
dp) :: ax, bx, cx
594 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
595 REAL(kind=
dp) :: brack_limit
596 INTEGER :: output_unit
597 REAL(kind=
dp),
DIMENSION(:, :),
OPTIONAL,
POINTER :: histpoint
598 TYPE(global_environment_type),
POINTER :: globenv
600 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_mnbrak'
602 INTEGER :: handle, loc_iter, odim
603 LOGICAL :: hist, should_stop
604 REAL(kind=
dp) :: dum, fa, fb, fc, fu, gold, q, r, u, ulim
606 CALL timeset(routinen, handle)
607 hist =
PRESENT(histpoint)
609 cpassert(.NOT.
ASSOCIATED(histpoint))
610 ALLOCATE (histpoint(3, 3))
612 gold = (1.0_dp + sqrt(5.0_dp))/2.0_dp
615 histpoint(1, 3) = cg_deval1d(gopt_env, ax, pcom, xicom, fa)
618 histpoint(2, 3) = cg_deval1d(gopt_env, bx, pcom, xicom, fb)
621 fa = cg_eval1d(gopt_env, ax, pcom, xicom)
622 fb = cg_eval1d(gopt_env, bx, pcom, xicom)
632 cx = bx + gold*(bx - ax)
635 histpoint(3, 3) = cg_deval1d(gopt_env, cx, pcom, xicom, fc)
638 fc = cg_eval1d(gopt_env, cx, pcom, xicom)
641 DO WHILE (fb .GE. fc)
643 IF (should_stop)
EXIT
645 r = (bx - ax)*(fb - fc)
646 q = (bx - cx)*(fb - fa)
647 u = bx - ((bx - cx)*q - (bx - ax)*r)/(2.0_dp*sign(max(abs(q - r), tiny(0.0_dp)), q - r))
648 ulim = bx + brack_limit*(cx - bx)
649 IF ((bx - u)*(u - cx) .GT. 0.0_dp)
THEN
651 odim =
SIZE(histpoint, 1)
652 CALL reallocate(histpoint, 1, odim + 1, 1, 3)
653 histpoint(odim + 1, 1) = u
654 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
655 histpoint(odim + 1, 2) = fu
657 fu = cg_eval1d(gopt_env, u, pcom, xicom)
659 loc_iter = loc_iter + 1
666 ELSE IF (fu .GT. fb)
THEN
671 u = cx + gold*(cx - bx)
673 odim =
SIZE(histpoint, 1)
674 CALL reallocate(histpoint, 1, odim + 1, 1, 3)
675 histpoint(odim + 1, 1) = u
676 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
677 histpoint(odim + 1, 2) = fu
679 fu = cg_eval1d(gopt_env, u, pcom, xicom)
681 loc_iter = loc_iter + 1
682 ELSE IF ((cx - u)*(u - ulim) .GT. 0.)
THEN
684 odim =
SIZE(histpoint, 1)
685 CALL reallocate(histpoint, 1, odim + 1, 1, 3)
686 histpoint(odim + 1, 1) = u
687 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
688 histpoint(odim + 1, 2) = fu
690 fu = cg_eval1d(gopt_env, u, pcom, xicom)
692 loc_iter = loc_iter + 1
696 u = cx + gold*(cx - bx)
700 odim =
SIZE(histpoint, 1)
701 CALL reallocate(histpoint, 1, odim + 1, 1, 3)
702 histpoint(odim + 1, 1) = u
703 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
704 histpoint(odim + 1, 2) = fu
706 fu = cg_eval1d(gopt_env, u, pcom, xicom)
708 loc_iter = loc_iter + 1
710 ELSE IF ((u - ulim)*(ulim - cx) .GE. 0.)
THEN
713 odim =
SIZE(histpoint, 1)
714 CALL reallocate(histpoint, 1, odim + 1, 1, 3)
715 histpoint(odim + 1, 1) = u
716 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
717 histpoint(odim + 1, 2) = fu
719 fu = cg_eval1d(gopt_env, u, pcom, xicom)
721 loc_iter = loc_iter + 1
723 u = cx + gold*(cx - bx)
725 odim =
SIZE(histpoint, 1)
726 CALL reallocate(histpoint, 1, odim + 1, 1, 3)
727 histpoint(odim + 1, 1) = u
728 histpoint(odim + 1, 3) = cg_deval1d(gopt_env, u, pcom, xicom, fu)
729 histpoint(odim + 1, 2) = fu
731 fu = cg_eval1d(gopt_env, u, pcom, xicom)
733 loc_iter = loc_iter + 1
742 IF (output_unit > 0)
THEN
743 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
744 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
745 "***",
"MNBRACK - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
746 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
748 CALL timestop(handle)
749 END SUBROUTINE cg_mnbrak
778 FUNCTION cg_dbrent(gopt_env, ax, bx, cx, tol, itmax, xmin, pcom, xicom, output_unit, &
779 globenv)
RESULT(dbrent)
780 TYPE(gopt_f_type),
POINTER :: gopt_env
781 REAL(kind=
dp) :: ax, bx, cx, tol
783 REAL(kind=
dp) :: xmin
784 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
785 INTEGER :: output_unit
786 TYPE(global_environment_type),
POINTER :: globenv
787 REAL(kind=
dp) :: dbrent
789 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_dbrent'
790 REAL(kind=
dp),
PARAMETER :: zeps = 1.0e-8_dp
792 INTEGER :: handle, iter, loc_iter
793 LOGICAL :: ok1, ok2, should_stop, skip0, skip1
794 REAL(kind=
dp) :: a, b, d, d1, d2, du, dv, dw, dx, e, fu, &
795 fv, fw, fx, olde, tol1, tol2, u, u1, &
798 CALL timeset(routinen, handle)
803 dx = cg_deval1d(gopt_env, x, pcom, xicom, fx)
811 IF (should_stop)
EXIT
814 tol1 = tol*abs(x) + zeps
818 IF (abs(x - xm) .LE. (tol2 - 0.5_dp*(b - a)))
EXIT
819 IF (abs(e) .GT. tol1)
THEN
822 IF (dw .NE. dx) d1 = (w - x)*dx/(dx - dw)
823 IF (dv .NE. dx) d2 = (v - x)*dx/(dx - dv)
826 ok1 = ((a - u1)*(u1 - b) .GT. 0.0_dp) .AND. (dx*d1 .LE. 0.0_dp)
827 ok2 = ((a - u2)*(u2 - b) .GT. 0.0_dp) .AND. (dx*d2 .LE. 0.0_dp)
830 IF (.NOT. (ok1 .OR. ok2))
THEN
832 ELSE IF (ok1 .AND. ok2)
THEN
833 IF (abs(d1) .LT. abs(d2))
THEN
843 IF (.NOT. skip0)
THEN
844 IF (abs(d) .GT. abs(0.5_dp*olde)) skip0 = .true.
845 IF (.NOT. skip0)
THEN
847 IF ((u - a) .LT. tol2 .OR. (b - u) .LT. tol2) d = sign(tol1, xm - x)
852 IF (.NOT. skip1)
THEN
853 IF (dx .GE. 0.0_dp)
THEN
860 IF (abs(d) .GE. tol1)
THEN
862 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
863 loc_iter = loc_iter + 1
865 u = x + sign(tol1, d)
866 du = cg_deval1d(gopt_env, u, pcom, xicom, fu)
867 loc_iter = loc_iter + 1
876 v = w; fv = fw; dv = dw; w = x
877 fw = fx; dw = dx; x = u; fx = fu; dx = du
884 IF (fu .LE. fw .OR. w .EQ. x)
THEN
885 v = w; fv = fw; dv = dw
886 w = u; fw = fu; dw = du
887 ELSE IF (fu .LE. fv .OR. v .EQ. x .OR. v .EQ. w)
THEN
894 IF (output_unit > 0)
THEN
895 WRITE (unit=output_unit, fmt=
"(/,T2,A)") repeat(
"*", 79)
896 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,I7,T78,A)") &
897 "***",
"BRENT - NUMBER OF ENERGY EVALUATIONS : ", loc_iter,
"***"
898 IF (iter == itmax + 1) &
899 WRITE (unit=output_unit, fmt=
"(T2,A,T22,A,T78,A)") &
900 "***",
"BRENT - NUMBER OF ITERATIONS EXCEEDED ",
"***"
901 WRITE (unit=output_unit, fmt=
"(T2,A)") repeat(
"*", 79)
903 cpassert(iter /= itmax + 1)
906 CALL timestop(handle)
908 END FUNCTION cg_dbrent
922 FUNCTION cg_eval1d(gopt_env, x, pcom, xicom)
RESULT(my_val)
923 TYPE(gopt_f_type),
POINTER :: gopt_env
925 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
926 REAL(kind=
dp) :: my_val
928 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_eval1d'
931 REAL(kind=
dp),
DIMENSION(:),
POINTER :: xvec
933 CALL timeset(routinen, handle)
935 ALLOCATE (xvec(
SIZE(pcom)))
936 xvec = pcom + x*xicom
937 CALL cp_eval_at(gopt_env, xvec, my_val, master=gopt_env%force_env%para_env%mepos, &
938 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
941 CALL timestop(handle)
943 END FUNCTION cg_eval1d
958 FUNCTION cg_deval1d(gopt_env, x, pcom, xicom, fval)
RESULT(my_val)
959 TYPE(gopt_f_type),
POINTER :: gopt_env
961 REAL(kind=
dp),
DIMENSION(:),
POINTER :: pcom, xicom
962 REAL(kind=
dp) :: fval, my_val
964 CHARACTER(len=*),
PARAMETER :: routinen =
'cg_deval1d'
967 REAL(kind=
dp) :: energy
968 REAL(kind=
dp),
DIMENSION(:),
POINTER :: grad, xvec
970 CALL timeset(routinen, handle)
972 ALLOCATE (xvec(
SIZE(pcom)))
973 ALLOCATE (grad(
SIZE(pcom)))
974 xvec = pcom + x*xicom
975 CALL cp_eval_at(gopt_env, xvec, energy, grad, master=gopt_env%force_env%para_env%mepos, &
976 final_evaluation=.false., para_env=gopt_env%force_env%para_env)
977 my_val = dot_product(grad, xicom)
981 CALL timestop(handle)
983 END FUNCTION cg_deval1d
995 FUNCTION findmin(x, y, dy)
RESULT(res)
996 REAL(kind=
dp),
DIMENSION(:) :: x, y, dy
999 INTEGER :: i, info, iwork(8*3), lwork, min_pos, np
1000 REAL(kind=
dp) :: diag(3), res1(3), res2(3), res3(3), &
1001 spread, sum_x, sum_xx, tmpw(1), &
1003 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: work
1004 REAL(kind=
dp),
DIMENSION(2*SIZE(x), 3) :: f
1005 REAL(kind=
dp),
DIMENSION(2*SIZE(x)) :: b, w
1006 REAL(kind=
dp) :: u(2*
SIZE(x), 3)
1014 sum_xx = sum_xx + x(i)**2
1015 sum_x = sum_x + x(i)
1016 IF (y(min_pos) > y(i)) min_pos = i
1018 spread = sqrt(sum_xx/real(np,
dp) - (sum_x/real(np,
dp))**2)
1020 w(i) = exp(-(real(np - i,
dp))**2/(real(2*9,
dp)))
1021 w(i + np) = 2._dp*w(i)
1026 f(i, 3) = x(i)**2*w(i)
1028 f(i + np, 2) = w(i + np)
1029 f(i + np, 3) = 2*x(i)*w(i + np)
1033 b(i + np) = dy(i)*w(i + np)
1036 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), tmpw, lwork, &
1038 lwork = ceiling(tmpw(1))
1039 ALLOCATE (work(lwork))
1040 CALL dgesdd(
'S',
SIZE(f, 1),
SIZE(f, 2), f,
SIZE(f, 1), diag, u,
SIZE(u, 1), vt,
SIZE(vt, 1), work, lwork, &
1043 CALL dgemv(
'T',
SIZE(u, 1),
SIZE(u, 2), 1._dp, u,
SIZE(u, 1), b, 1, 0._dp, res1, 1)
1045 res2(i) = res1(i)/diag(i)
1047 CALL dgemv(
'T', 3, 3, 1._dp, vt,
SIZE(vt, 1), res2, 1, 0._dp, res3, 1)
1048 res = -0.5*res3(2)/res3(3)
1049 END FUNCTION findmin
1065 TYPE(gopt_f_type),
POINTER :: gopt_env
1066 LOGICAL,
INTENT(IN) :: fletcher_reeves
1067 REAL(kind=
dp),
DIMENSION(:),
POINTER :: g, xi, h
1069 CHARACTER(len=*),
PARAMETER :: routinen =
'get_conjugate_direction'
1073 REAL(kind=
dp) :: dgg, gam, gg, norm, norm_h
1074 TYPE(dimer_env_type),
POINTER :: dimer_env
1076 CALL timeset(routinen, handle)
1078 IF (.NOT. gopt_env%dimer_rotation)
THEN
1079 gg = dot_product(g, g)
1080 IF (fletcher_reeves)
THEN
1081 dgg = dot_product(xi, xi)
1083 dgg = dot_product((xi + g), xi)
1089 dimer_env => gopt_env%dimer_env
1090 check = abs(dot_product(g, g) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1093 check = abs(dot_product(xi, xi) - 1.0_dp) < max(1.0e-9_dp,
dimer_thrs)
1096 check = abs(dot_product(h, dimer_env%cg_rot%nvec_old)) < max(1.0e-9_dp,
dimer_thrs)
1098 gg = dimer_env%cg_rot%norm_theta_old**2
1099 IF (fletcher_reeves)
THEN
1100 dgg = dimer_env%cg_rot%norm_theta**2
1102 norm = dimer_env%cg_rot%norm_theta*dimer_env%cg_rot%norm_theta_old
1103 dgg = dimer_env%cg_rot%norm_theta**2 + dot_product(g, xi)*norm
1106 CALL rotate_dimer(dimer_env%cg_rot%nvec_old, g, dimer_env%rot%angle2 +
pi/2.0_dp)
1109 h = -xi*dimer_env%cg_rot%norm_theta + gam*dimer_env%cg_rot%norm_h*dimer_env%cg_rot%nvec_old
1110 h = h - dot_product(h, dimer_env%nvec)*dimer_env%nvec
1111 norm_h = sqrt(dot_product(h, h))
1112 IF (norm_h < epsilon(0.0_dp))
THEN
1117 dimer_env%cg_rot%norm_h = norm_h
1119 CALL timestop(handle)
pure real(kind=dp) function angle(a, b)
Calculation of the angle between the vectors a and b. The angle is returned in radians.
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.