17 #include "../base/base_uses.f90"
22 TYPE history_fingerprint_type
24 REAL(KIND=
dp) :: epot = 0.0
25 REAL(KIND=
dp),
DIMENSION(:),
ALLOCATABLE :: goedecker
26 END TYPE history_fingerprint_type
28 TYPE history_entry_type
29 TYPE(history_fingerprint_type),
POINTER :: p => null()
31 END TYPE history_entry_type
35 TYPE(history_entry_type),
DIMENSION(:),
POINTER :: entries => null()
38 REAL(KIND=
dp) :: e_precision = 0.0
39 REAL(KIND=
dp) :: fp_precision = 0.0
42 PUBLIC :: history_type, history_fingerprint_type
48 LOGICAL,
PARAMETER :: debug = .false.
49 INTEGER,
PARAMETER :: history_grow_unit = 1000
60 TYPE(history_type),
INTENT(INOUT) :: history
61 TYPE(section_vals_type),
POINTER :: history_section
64 ALLOCATE (history%entries(history_grow_unit))
67 r_val=history%E_precision)
69 r_val=history%FP_precision)
72 WRITE (iw,
'(A,T66,E15.3)') &
73 " GLBOPT| History energy precision", history%E_precision
74 WRITE (iw,
'(A,T66,E15.3)') &
75 " GLBOPT| History fingerprint precision", history%FP_precision
87 REAL(kind=
dp),
INTENT(IN) :: epot
88 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: pos
89 TYPE(history_fingerprint_type) :: fp
92 REAL(kind=
dp),
DIMENSION(:),
POINTER :: tmp
94 CALL timeset(
"glbopt_history_fingerprint", handle)
98 CALL goedecker_fingerprint(pos, tmp)
101 ALLOCATE (fp%goedecker(
SIZE(tmp)))
102 fp%goedecker(:) = tmp
105 CALL timestop(handle)
115 SUBROUTINE goedecker_fingerprint(pos, res)
116 REAL(kind=
dp),
DIMENSION(:),
INTENT(IN) :: pos
117 REAL(kind=
dp),
DIMENSION(:),
POINTER :: res
119 INTEGER :: i, info, j, n
120 REAL(kind=
dp) :: d2, t
121 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: matrix, work
122 REAL(kind=
dp),
DIMENSION(3) :: d
124 IF (
ASSOCIATED(res)) cpabort(
"goedecker_fingerprint: res already allocated")
127 ALLOCATE (matrix(n, n), work(n, n))
131 d = pos(3*i - 2:3*i) - pos(3*j - 2:3*j)
141 CALL dsyev(
'N',
'U', n, matrix, n, res, work, n**2, info)
142 IF (info /= 0) cpabort(
"goedecker_fingerprint: DSYEV failed")
143 END SUBROUTINE goedecker_fingerprint
154 TYPE(history_type),
INTENT(IN) :: history
155 TYPE(history_fingerprint_type),
INTENT(IN) :: fp1, fp2
158 res = (abs(fp1%Epot - fp2%Epot) < history%E_precision) .AND. &
159 (fingerprint_distance(fp1, fp2) < history%fp_precision)
171 PURE FUNCTION fingerprint_distance(fp1, fp2)
RESULT(res)
172 TYPE(history_fingerprint_type),
INTENT(IN) :: fp1, fp2
175 res = sqrt(sum((fp1%goedecker - fp2%goedecker)**2)/
SIZE(fp1%goedecker))
176 END FUNCTION fingerprint_distance
187 TYPE(history_type),
INTENT(INOUT) :: history
188 TYPE(history_fingerprint_type),
INTENT(IN) :: fingerprint
189 INTEGER,
INTENT(IN),
OPTIONAL :: id
191 INTEGER :: handle, i, k, n
192 TYPE(history_entry_type),
DIMENSION(:),
POINTER :: tmp
194 CALL timeset(
"glbopt_history_add", handle)
196 n =
SIZE(history%entries)
197 IF (n == history%length)
THEN
199 tmp => history%entries
200 ALLOCATE (history%entries(n + history_grow_unit))
201 history%entries(1:n) = tmp(:)
203 n = n + history_grow_unit
206 k = interpolation_search(history, fingerprint%Epot)
212 history%entries(i) = history%entries(i - 1)
215 ALLOCATE (history%entries(k)%p)
216 history%entries(k)%p = fingerprint
218 history%entries(k)%id = id
219 history%length = history%length + 1
223 DO k = 1, history%length
226 IF (history%entries(k - 1)%p%Epot > history%entries(k)%p%Epot) &
227 cpabort(
"history_add: history in wrong order")
232 CALL timestop(handle)
244 TYPE(history_type),
INTENT(IN) :: history
245 TYPE(history_fingerprint_type),
INTENT(IN) :: fingerprint
246 LOGICAL,
INTENT(OUT) :: found
247 INTEGER,
INTENT(OUT),
OPTIONAL :: id
249 INTEGER :: found_i, handle, i, k, k_max, k_min
250 REAL(kind=
dp) :: best_match, dist, epot
252 CALL timeset(
"glbopt_history_lookup", handle)
255 IF (
PRESENT(id)) id = -1
256 best_match = huge(1.0_dp)
258 IF (history%length > 0)
THEN
259 epot = fingerprint%Epot
260 k = interpolation_search(history, fingerprint%Epot)
262 DO k_min = k - 1, 1, -1
263 IF (history%entries(k_min)%p%Epot < epot - history%E_precision)
EXIT
266 DO k_max = k, history%length
267 IF (history%entries(k_max)%p%Epot > epot + history%E_precision)
EXIT
270 k_min = max(k_min + 1, 1)
271 k_max = min(k_max - 1, history%length)
273 IF (debug) found_i = -1
276 dist = fingerprint_distance(fingerprint, history%entries(i)%p)
278 IF (dist < history%fp_precision .AND. dist < best_match)
THEN
281 IF (
PRESENT(id)) id = history%entries(i)%id
282 IF (debug) found_i = i
286 IF (debug)
CALL verify_history_lookup(history, fingerprint, found_i)
289 CALL timestop(handle)
300 FUNCTION interpolation_search(history, Efind)
RESULT(res)
301 TYPE(history_type),
INTENT(IN) :: history
302 REAL(kind=
dp),
INTENT(IN) :: efind
305 INTEGER :: high, low, mid
306 REAL(kind=
dp) :: slope
309 high = history%length
311 DO WHILE (low < high)
313 slope = real(high - low, kind=
dp)/(history%entries(high)%p%Epot - history%entries(low)%p%Epot)
314 mid = low + int(slope*(efind - history%entries(low)%p%Epot))
315 mid = min(max(mid, low), high)
317 IF (history%entries(mid)%p%Epot < efind)
THEN
324 IF (0 < low .AND. low <= history%length)
THEN
325 IF (efind > history%entries(low)%p%Epot) low = low + 1
329 END FUNCTION interpolation_search
338 SUBROUTINE verify_history_lookup(history, fingerprint, found_i_ref)
339 TYPE(history_type),
INTENT(IN) :: history
340 TYPE(history_fingerprint_type),
INTENT(IN) :: fingerprint
341 INTEGER,
INTENT(IN) :: found_i_ref
343 INTEGER :: found_i, i
344 REAL(kind=
dp) :: best_fp_match, epot_dist, fp_dist
347 best_fp_match = huge(1.0_dp)
349 DO i = 1, history%length
350 epot_dist = abs(fingerprint%Epot - history%entries(i)%p%Epot)
351 IF (epot_dist > history%E_precision) cycle
352 fp_dist = fingerprint_distance(fingerprint, history%entries(i)%p)
354 IF (fp_dist < history%fp_precision .AND. fp_dist < best_fp_match)
THEN
355 best_fp_match = fp_dist
360 IF (found_i /= found_i_ref)
THEN
361 WRITE (*, *) found_i, found_i_ref
362 cpabort(
"verify_history_lookup failed")
365 END SUBROUTINE verify_history_lookup
373 TYPE(history_type) :: history
377 DO i = 1, history%length
378 IF (
ASSOCIATED(history%entries(i)%p)) &
379 DEALLOCATE (history%entries(i)%p)
382 DEALLOCATE (history%entries)
History of minima, calculates, stores and compares fingerprints of minima. Used by Minima Hopping and...
subroutine, public history_init(history, history_section, iw)
Initializes a history.
subroutine, public history_lookup(history, fingerprint, found, id)
Checks if a given fingerprints is contained in the history.
subroutine, public history_finalize(history)
Finalizes a history.
subroutine, public history_add(history, fingerprint, id)
Addes a new fingerprints to the history. Optionally, an abitrary id can be stored alongside the finge...
type(history_fingerprint_type) function, public history_fingerprint(Epot, pos)
Calculates a fingerprint for a given configuration.
logical function, public history_fingerprint_match(history, fp1, fp2)
Checks if two given fingerprints match.
Defines the basic variable types.
integer, parameter, public dp