33 #include "../base/base_uses.f90"
37 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'neb_opt_utils'
38 LOGICAL,
PARAMETER,
PRIVATE :: debug_this_module = .false.
43 REAL(KIND=
dp),
DIMENSION(2:10),
PRIVATE :: acceptance_factor = &
44 (/0.97_dp, 0.84_dp, 0.71_dp, 0.67_dp, 0.62_dp, 0.56_dp, 0.49_dp, 0.41_dp, 0.0_dp/)
63 check_diis, iw2)
RESULT(accepted)
64 LOGICAL,
INTENT(IN) :: apply_diis
65 INTEGER,
INTENT(IN) :: n_diis
66 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: err, crr
67 INTEGER,
DIMENSION(:),
POINTER :: set_err
68 TYPE(neb_var_type),
POINTER :: sline, coords
69 LOGICAL,
INTENT(IN) :: check_diis
70 INTEGER,
INTENT(IN) :: iw2
73 CHARACTER(LEN=default_string_length) :: line
74 INTEGER :: i, iend, ind, indi, indj, info, istart, &
75 iv, iw, j, jv, k, lwork, np, nv
76 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: iwork
77 LOGICAL :: increase_error
78 REAL(
dp),
DIMENSION(:, :),
POINTER :: work
79 REAL(kind=
dp) :: eps_svd
80 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: s, work_dgesdd
81 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: u, vt, wrk, wrk_inv
82 REAL(kind=
dp),
DIMENSION(:),
POINTER :: awrk, cwrk, ref, step
87 nv = minloc(set_err, 1)
88 IF (iw2 > 0)
WRITE (iw2,
'(A,I3)')
"Entering into the DIIS module. Error vector number:: ", nv
91 ALLOCATE (step(sline%size_wrk(1)*sline%size_wrk(2)))
92 ALLOCATE (ref(sline%size_wrk(1)*sline%size_wrk(2)))
93 err(:, nv) = reshape(sline%wrk, (/sline%size_wrk(1)*sline%size_wrk(2)/))
94 crr(:, nv) = reshape(coords%wrk, (/coords%size_wrk(1)*coords%size_wrk(2)/))
96 IF (all(set_err == 1) .AND. apply_diis)
THEN
97 IF (iw2 > 0)
WRITE (iw2,
'(A)')
"Applying DIIS equations"
101 IF (iw2 > 0)
WRITE (iw2,
'(A,I5,A)')
"Applying DIIS equations with the last", &
103 ALLOCATE (wrk(np, np))
104 ALLOCATE (work(np, np))
105 ALLOCATE (wrk_inv(np, np))
113 indi = n_diis - i + 1
115 indj = n_diis - j + 1
116 wrk(i, j) = dot_product(err(:, indi), err(:, indj))
117 wrk(j, i) = wrk(i, j)
121 line =
"DIIS Matrix"//cp_to_string(np)//
"x"//cp_to_string(np)//
"."
122 WRITE (iw2,
'(A)') trim(line)
123 WRITE (iw2,
'('//cp_to_string(np)//
'F12.6)') wrk
126 work = transpose(wrk)
128 ALLOCATE (iwork(8*np))
131 ALLOCATE (vt(np, np))
132 ALLOCATE (work_dgesdd(1))
134 CALL dgesdd(
'S', np, np, work, np, s, u, np, vt, np, work_dgesdd, lwork, iwork, info)
135 lwork = int(work_dgesdd(1))
136 DEALLOCATE (work_dgesdd)
137 ALLOCATE (work_dgesdd(lwork))
138 CALL dgesdd(
'S', np, np, work, np, s, u, np, vt, np, work_dgesdd, lwork, iwork, info)
142 IF (s(k) < eps_svd)
THEN
147 vt(k, :) = vt(k, :)*s(k)
149 CALL dgemm(
'T',
'T', np, np, np, 1.0_dp, vt, np, u, np, 0.0_dp, wrk_inv, np)
154 DEALLOCATE (work_dgesdd)
155 cwrk = matmul(wrk_inv, awrk)
159 DO i = n_diis, n_diis - jv + 1, -1
161 step = step + (crr(:, i) + err(:, i))*cwrk(ind)
163 step = step - crr(:, n_diis)
165 increase_error = check_diis_solution(jv, cwrk, step, ref, &
168 IF (increase_error)
THEN
170 sline%wrk = reshape(step, (/sline%size_wrk(1), sline%size_wrk(2)/))
186 line =
"Exiting DIIS accepting"//cp_to_string(min(n_diis, jv))//
" errors."
187 WRITE (iw2,
'(A)') trim(line)
190 IF (all(set_err == 1))
THEN
194 istart = max(2, n_diis - jv + 2)
199 err(:, indi) = err(:, iv)
200 crr(:, indi) = crr(:, iv)
203 DO iv = indi + 1, iend
223 FUNCTION check_diis_solution(nv, cwrk, step, ref, output_unit, check_diis) &
225 INTEGER,
INTENT(IN) :: nv
226 REAL(kind=
dp),
DIMENSION(:),
POINTER :: cwrk, step, ref
227 INTEGER,
INTENT(IN) :: output_unit
228 LOGICAL,
INTENT(IN) :: check_diis
231 REAL(kind=
dp) :: costh, norm1, norm2
232 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
235 ALLOCATE (tmp(
SIZE(step)))
240 norm1 = sqrt(dot_product(ref, ref))
241 norm2 = sqrt(dot_product(step, step))
242 costh = dot_product(ref, step)/(norm1*norm2)
244 IF (costh < acceptance_factor(min(10, nv))) accepted = .false.
246 IF (costh <= 0.0_dp) accepted = .false.
248 IF (output_unit > 0 .AND. (.NOT. accepted))
THEN
249 WRITE (output_unit,
'(T2,"DIIS|",A)') &
250 "The direction of the DIIS step, can be compared to the reference step.", &
251 "If the angle is grater than a specified value, the DIIS step is not", &
252 "acceptable. Value exceeded. Reset DIIS!"
253 WRITE (output_unit,
'(T2,"DIIS|",A,F6.3,A,F6.3,A)') &
254 "Present Cosine <", costh,
"> compared with the optimal value <", &
255 acceptance_factor(min(10, nv)),
"> ."
258 IF (accepted .AND. check_diis)
THEN
261 IF (norm1 > norm2*10.0_dp) accepted = .false.
262 IF (output_unit > 0 .AND. (.NOT. accepted))
THEN
263 WRITE (output_unit,
'(T2,"DIIS|",A)') &
264 "The length of the DIIS step is limited to be no more than 10 times", &
265 "the reference step. Value exceeded. Reset DIIS!"
268 IF (accepted .AND. check_diis)
THEN
273 IF (any(abs(cwrk(1:nv)/norm1) > 10**8_dp)) accepted = .false.
274 IF (output_unit > 0 .AND. (.NOT. accepted))
THEN
275 WRITE (output_unit,
'(T2,"DIIS|",A)') &
276 "If the DIIS matrix is nearly singular, the norm of the DIIS step", &
277 "vector becomes small and Coeff/E_norm becomes large, signaling a", &
278 "numerical stability problems. IF the magnitude of Coeff/E_norm", &
279 "exceeds 10^8 THEN the step size is assumed to be unacceptable.", &
280 "Value exceeded. Reset DIIS!"
284 END FUNCTION check_diis_solution
304 SUBROUTINE neb_ls(stepsize, sline, rep_env, neb_env, coords, energies, forces, &
305 vels, particle_set, iw, output_unit, distances, diis_section, iw2)
306 REAL(kind=
dp),
INTENT(INOUT) :: stepsize
307 TYPE(neb_var_type),
POINTER :: sline
308 TYPE(replica_env_type),
POINTER :: rep_env
309 TYPE(neb_type),
OPTIONAL,
POINTER :: neb_env
310 TYPE(neb_var_type),
POINTER :: coords
311 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: energies
312 TYPE(neb_var_type),
POINTER :: forces, vels
313 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
314 INTEGER,
INTENT(IN) :: iw, output_unit
315 REAL(kind=
dp),
DIMENSION(:),
INTENT(INOUT) :: distances
316 TYPE(section_vals_type),
POINTER :: diis_section
317 INTEGER,
INTENT(IN) :: iw2
320 REAL(kind=
dp) :: a, b, max_stepsize, xa, xb, xc_cray, ya, &
322 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: icoord
326 ALLOCATE (icoord(coords%size_wrk(1), coords%size_wrk(2)))
329 icoord(:, :) = coords%wrk
331 ya = sum(sline%wrk*forces%wrk)
332 xb = xa + min(ya*stepsize, max_stepsize)
335 DO WHILE (i <= np - 1)
337 coords%wrk = icoord + xb*sline%wrk
338 CALL reorient_images(neb_env%rotate_frames, particle_set, coords, vels, &
339 output_unit, distances, neb_env%number_of_replica)
340 neb_env%avg_distance = sqrt(sum(distances*distances)/real(
SIZE(distances), kind=
dp))
343 yb = sum(sline%wrk*forces%wrk)
344 a = (ya - yb)/(2.0_dp*(xa - xb))
346 xc_cray = -b/(2.0_dp*a)
347 IF (xc_cray > max_stepsize)
THEN
348 IF (iw2 > 0)
WRITE (iw2,
'(T2,2(A,F6.3),A)') &
349 "LS| Predicted stepsize (", xc_cray,
") greater than allowed stepsize (", &
350 max_stepsize,
"). Reset!"
351 xc_cray = max_stepsize
355 IF ((xc_cray <= min(xa, xb) .OR. xc_cray >= max(xa, xb)) .AND. (abs(xa - xb) > 1.0e-5_dp))
THEN
356 IF (iw2 > 0)
WRITE (iw2,
'(T2,2(A,I5),A)') &
357 "LS| Increasing the number of point from ", np,
" to ", np + 1,
"."
361 IF (abs(yb) < abs(ya))
THEN
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Module with utility to perform MD Nudged Elastic Band Calculation.
logical function, public accept_diis_step(apply_diis, n_diis, err, crr, set_err, sline, coords, check_diis, iw2)
Performs few basic operations for the NEB DIIS optimization.
subroutine, public neb_ls(stepsize, sline, rep_env, neb_env, coords, energies, forces, vels, particle_set, iw, output_unit, distances, diis_section, iw2)
Perform a line minimization search in optimizing a NEB with DIIS.
Typo for Nudged Elastic Band Calculation.
Module with utility for Nudged Elastic Band Calculation.
subroutine, public neb_calc_energy_forces(rep_env, neb_env, coords, energies, forces, particle_set, output_unit)
Driver to compute energy and forces within a NEB, Based on the use of the replica_env.
subroutine, public reorient_images(rotate_frames, particle_set, coords, vels, iw, distances, number_of_replica)
Reorient iteratively all images of the NEB chain in order to have always the smaller RMSD between two...
Define the data structure for the particle information.
types used to handle many replica of the same system that differ only in atom positions,...