(git:374b731)
Loading...
Searching...
No Matches
graph_methods.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Program to Map on grid the hills spawned during a metadynamics run
10!> \author Teodoro Laino [tlaino] - 06.2009
11!> \par History
12!> 03.2006 created [tlaino]
13!> teodoro.laino .at. gmail.com
14!> 11.2007 - tlaino (University of Zurich): Periodic COLVAR - cleaning.
15!> 12.2010 - teodoro.laino@gmail.com: addition of the MEP for FES
16!>
17!> \par Note
18!> Please report any bug to the author
19! **************************************************************************************************
21
22 USE cp_files, ONLY: close_file,&
24 USE graph_utils, ONLY: derivative,&
27 pbc,&
30 USE kinds, ONLY: dp
33 nelem,&
34 ptable
35 USE physcon, ONLY: bohr
37#include "../base/base_uses.f90"
38
39 IMPLICIT NONE
40 PRIVATE
41
42 PUBLIC :: fes_compute_low, &
43 fes_write, &
45 fes_min, &
46 fes_path, &
48
49CONTAINS
50! **************************************************************************************************
51!> \brief Efficiently map the gaussians on the grid
52!> \param idim ...
53!> \param nn ...
54!> \param fes ...
55!> \param gauss ...
56!> \param ind ...
57!> \param ind0 ...
58!> \param nfes ...
59!> \param ndim ...
60!> \param ngauss ...
61!> \param ngrid ...
62!> \param iperd ...
63!> \par History
64!> 03.2006 created [tlaino]
65!> teodoro.laino .at. gmail.com
66!> \author Teodoro Laino
67! **************************************************************************************************
68 RECURSIVE SUBROUTINE fes_compute_low(idim, nn, fes, gauss, ind, ind0, nfes, ndim, &
69 ngauss, ngrid, iperd)
70 INTEGER, INTENT(in) :: idim
71 INTEGER, DIMENSION(:) :: nn
72 REAL(kind=dp), DIMENSION(:), POINTER :: fes
73 REAL(kind=dp), DIMENSION(:, :), POINTER :: gauss
74 INTEGER, DIMENSION(:) :: ind, ind0
75 INTEGER, INTENT(in) :: nfes, ndim, ngauss
76 INTEGER, DIMENSION(:), POINTER :: ngrid
77 INTEGER, DIMENSION(:) :: iperd
78
79 INTEGER :: i, j, k, pnt
80 INTEGER, DIMENSION(:), POINTER :: ll, pos
81 REAL(kind=dp) :: prod
82
83 ALLOCATE (pos(ndim), ll(ndim))
84 pos = ind
85 k = nn(idim)
86
87 DO i = -k, k
88 pos(idim) = ind(idim) + i
89 IF (iperd(idim) == 0) THEN
90 IF (pos(idim) .GT. ngrid(idim)) cycle
91 IF (pos(idim) .LT. 1) cycle
92 END IF
93 IF (idim /= 1) THEN
94 CALL fes_compute_low(idim - 1, nn, fes, gauss, pos, ind0, nfes, ndim, ngauss, ngrid, iperd)
95 ELSE
96 pnt = point_pbc(pos, iperd, ngrid, ndim)
97 prod = 1.0_dp
98 DO j = 1, ndim
99 ll(j) = pos(j) - ind0(j)
100 prod = prod*gauss(ll(j), j)
101 END DO
102 fes(pnt) = fes(pnt) + prod
103 END IF
104 END DO
105 DEALLOCATE (pos, ll)
106
107 END SUBROUTINE fes_compute_low
108
109! **************************************************************************************************
110!> \brief Writes the FES on the file
111!> \param unit_nr ...
112!> \param idim ...
113!> \param fes ...
114!> \param pos ...
115!> \param ndim ...
116!> \param ngrid ...
117!> \param dp_grid ...
118!> \param x0 ...
119!> \param ndw ...
120!> \param l_fes_int ...
121!> \param array ...
122!> \par History
123!> 03.2006 created [tlaino]
124!> teodoro.laino .at. gmail.com
125!> \author Teodoro Laino
126! **************************************************************************************************
127 RECURSIVE SUBROUTINE fes_write(unit_nr, idim, fes, pos, ndim, ngrid, &
128 dp_grid, x0, ndw, l_fes_int, array)
129 INTEGER, INTENT(IN) :: unit_nr, idim
130 REAL(kind=dp), DIMENSION(:), POINTER :: fes
131 INTEGER, DIMENSION(:), POINTER :: pos
132 INTEGER, INTENT(IN) :: ndim
133 INTEGER, DIMENSION(:), POINTER :: ngrid
134 REAL(kind=dp), DIMENSION(:), POINTER :: dp_grid, x0
135 INTEGER, INTENT(IN) :: ndw
136 LOGICAL, INTENT(IN) :: l_fes_int
137 REAL(kind=dp), DIMENSION(:), OPTIONAL :: array
138
139 INTEGER :: dimval, i, id, ind, is, it, itt, np, pnt
140 REAL(kind=dp) :: dvol, sum_fes
141 REAL(kind=dp), DIMENSION(:), POINTER :: xx
142
143 ALLOCATE (xx(ndim))
144 xx = x0
145 DO i = 1, ngrid(idim)
146 pos(idim) = i
147 IF (idim /= ndim - ndw + 1) THEN
148 IF (PRESENT(array)) THEN
149 CALL fes_write(unit_nr, idim - 1, fes, pos, ndim, ngrid, dp_grid, &
150 x0, ndw, l_fes_int, array)
151 ELSE
152 CALL fes_write(unit_nr, idim - 1, fes, pos, ndim, ngrid, dp_grid, &
153 x0, ndw, l_fes_int)
154 END IF
155 ELSE
156 IF (PRESENT(array)) THEN
157 ind = 1
158 np = ngrid(ndim)*ngrid(ndim - 1)*ngrid(ndim - 2)
159 DO is = 1, ndw
160 itt = 1
161 DO it = 1, is - 1
162 itt = itt*ngrid(ndim - it)
163 END DO
164 ind = ind + (pos(ndim - is + 1) - 1)*itt
165 END DO
166 IF (ind > np) cpabort("something wrong in indexing ..")
167 END IF
168 pnt = point_no_pbc(pos, ngrid, ndim)
169 xx = x0 + dp_grid*(pos - 1)
170 dimval = product(ngrid(1:ndim - ndw))
171
172 IF (.NOT. l_fes_int) THEN
173 IF (PRESENT(array)) THEN
174 array(ind) = minval(-fes(pnt:pnt + dimval - 1))
175 ELSE
176 WRITE (unit_nr, '(10f20.10)') (xx(id), id=ndim, ndim - ndw + 1, -1), minval(-fes(pnt:pnt + dimval - 1))
177 END IF
178 ELSE
179 sum_fes = 0.0_dp
180 dvol = 1.0_dp
181 dvol = product(dp_grid(1:ndim - ndw))
182 DO is = pnt, pnt + dimval - 1
183 sum_fes = sum_fes + fes(is)*dvol
184 END DO
185 IF (PRESENT(array)) THEN
186 array(ind) = -sum_fes
187 ELSE
188 WRITE (unit_nr, '(10f20.10)') (xx(id), id=ndim, ndim - ndw + 1, -1), -sum_fes
189 END IF
190 END IF
191 END IF
192 END DO
193 DEALLOCATE (xx)
194
195 END SUBROUTINE fes_write
196
197! **************************************************************************************************
198!> \brief Writes the FES on the file when stride is requested
199!> \param idim ...
200!> \param fes ...
201!> \param pos ...
202!> \param ndim ...
203!> \param ngrid ...
204!> \param dp_grid ...
205!> \param ndw ...
206!> \param l_fes_int ...
207!> \param unit_nr ...
208!> \par History
209!> 03.2006 created [tlaino]
210!> teodoro.laino .at. gmail.com
211!> \author Teodoro Laino
212! **************************************************************************************************
213 RECURSIVE SUBROUTINE fes_only_write(idim, fes, pos, ndim, ngrid, dp_grid, ndw, l_fes_int, unit_nr)
214 INTEGER, INTENT(IN) :: idim
215 REAL(kind=dp), DIMENSION(:), POINTER :: fes
216 INTEGER, DIMENSION(:), POINTER :: pos
217 INTEGER, INTENT(IN) :: ndim
218 INTEGER, DIMENSION(:), POINTER :: ngrid
219 REAL(kind=dp), DIMENSION(:), POINTER :: dp_grid
220 INTEGER, INTENT(IN) :: ndw
221 LOGICAL, INTENT(IN) :: l_fes_int
222 INTEGER :: unit_nr
223
224 INTEGER :: dimval, i, is, pnt
225 REAL(kind=dp) :: dvol, sum_fes
226
227 DO i = 1, ngrid(idim)
228 pos(idim) = i
229 IF (idim /= ndim - ndw + 1) THEN
230 CALL fes_only_write(idim - 1, fes, pos, ndim, ngrid, dp_grid, ndw, l_fes_int, unit_nr)
231 ELSE
232 pnt = point_no_pbc(pos, ngrid, ndim)
233 dimval = product(ngrid(1:ndim - ndw))
234 IF (l_fes_int) THEN
235 WRITE (unit_nr, '(1f12.5)') minval(-fes(pnt:pnt + dimval - 1))
236 ELSE
237 sum_fes = 0.0_dp
238 dvol = product(dp_grid(1:ndim - ndw))
239 DO is = pnt, pnt + dimval - 1
240 sum_fes = sum_fes + fes(is)*dvol
241 END DO
242 WRITE (unit_nr, '(1f12.5)') - sum_fes
243 END IF
244 END IF
245 END DO
246
247 END SUBROUTINE fes_only_write
248
249! **************************************************************************************************
250!> \brief Finds minima of the FES
251!> \param fes ...
252!> \param ndim ...
253!> \param iperd ...
254!> \param ngrid ...
255!> \param dp_grid ...
256!> \param x0 ...
257!> \param ndw ...
258!> \par History
259!> 06.2009 created [tlaino]
260!> teodoro.laino .at. gmail.com
261!> \author Teodoro Laino
262! **************************************************************************************************
263 SUBROUTINE fes_min(fes, ndim, iperd, ngrid, dp_grid, x0, ndw)
264 REAL(kind=dp), DIMENSION(:), POINTER :: fes
265 INTEGER, INTENT(IN) :: ndim
266 INTEGER, DIMENSION(:), POINTER :: iperd, ngrid
267 REAL(kind=dp), DIMENSION(:), POINTER :: dp_grid, x0
268 INTEGER, INTENT(IN) :: ndw
269
270 INTEGER :: i, id, iter, j, k, max_ntrust, nacc, &
271 ntrials, pnt
272 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: history
273 INTEGER, DIMENSION(:), POINTER :: pos, pos0
274 INTEGER, DIMENSION(ndim) :: dpos, ntrust
275 LOGICAL :: do_save
276 REAL(kind=dp) :: fes_now, fes_old, norm_dx, resto
277 REAL(kind=dp), DIMENSION(:), POINTER :: dx, rnd, xx
278
279 IF (ndw /= ndim) cpabort("Not implemented for projected FES!")
280
281 ntrust = ngrid/10
282 ntrials = product(ngrid)
283 WRITE (*, '(A,10I6)', advance="no") "FES| Trust hyper-radius ", ntrust
284 WRITE (*, '(A,10F12.6)') " which is equivalent to: ", ntrust*dp_grid
285
286 ALLOCATE (xx(ndim), dx(ndim), pos0(ndim), rnd(ndim), pos(ndim))
287 ALLOCATE (history(ndim, ntrials))
288 history = 0
289 nacc = 0
290 trials: DO j = 1, ntrials
291 ! Loop over all points
292 pnt = j
293 DO k = ndim, 2, -1
294 pos0(k) = pnt/product(ngrid(1:k - 1))
295 resto = mod(pnt, product(ngrid(1:k - 1)))
296 IF (resto /= 0) THEN
297 pnt = pnt - pos0(k)*product(ngrid(1:k - 1))
298 pos0(k) = pos0(k) + 1
299 ELSE
300 pnt = product(ngrid(1:k - 1))
301 END IF
302 END DO
303 pos0(1) = pnt
304
305 ! Loop over the frame points unless it is periodic
306 DO k = 1, ndim
307 IF ((iperd(k) == 0) .AND. (pos0(k) < ntrust(k))) cycle trials
308 IF ((iperd(k) == 0) .AND. (pos0(k) > ngrid(k) - ntrust(k))) cycle trials
309 END DO
310
311 ! Evaluate position and derivative
312 pos = pos0
313 xx = x0 + dp_grid*(pos - 1)
314 dx = derivative(fes, pos, iperd, ndim, ngrid, dp_grid)
315
316 ! Integrate till derivative is small enough..
317 pnt = point_no_pbc(pos, ngrid, ndim)
318 fes_now = -fes(pnt)
319 fes_old = huge(0.0_dp)
320
321 i = 1
322 DO WHILE ((i <= 100) .OR. (fes_now < fes_old))
323 fes_old = fes_now
324 !WRITE(10+j,'(10f20.10)')(xx(id),id=ndim,1,-1),-fes(pnt)
325
326 norm_dx = sqrt(dot_product(dx, dx))
327 IF (norm_dx == 0.0_dp) EXIT ! It is in a really flat region
328 xx = xx - min(0.1_dp, norm_dx)*dx/norm_dx
329 ! Re-evaluating pos
330 pos = ceiling((xx - x0)/dp_grid) + 1
331 CALL pbc(pos, iperd, ngrid, ndim)
332
333 ! Incremental pos
334 dx = derivative(fes, pos, iperd, ndim, ngrid, dp_grid)
335 pnt = point_no_pbc(pos, ngrid, ndim)
336 fes_now = -fes(pnt)
337 i = i + 1
338 END DO
339 iter = i
340
341 ! Compare with the available minima and if they are the same skip
342 ! saving this position..
343 do_save = fes(pnt) >= 1.0e-3_dp
344 IF (do_save) THEN
345 DO i = 1, nacc
346 dpos = pos - history(:, i)
347 norm_dx = dot_product(dpos, dpos)
348 max_ntrust = maxval(ntrust)
349 ! (SQRT(REAL(norm_dx, KIND=dp)) <= MAXVAL(ntrust)) ...
350 IF ((norm_dx <= real(max_ntrust*max_ntrust, kind=dp)) .OR. (fes(pnt) < 1.0e-3_dp)) THEN
351 do_save = .false.
352 EXIT
353 END IF
354 END DO
355 END IF
356 IF (do_save) THEN
357 pnt = point_no_pbc(pos, ngrid, ndim)
358 xx = x0 + dp_grid*(pos - 1)
359 WRITE (*, '(A,5F12.6)', advance="NO") "FES| Minimum found (", (xx(id), id=ndim, ndim - ndw + 1, -1)
360 WRITE (*, '(A,F12.6,A,I6)') " ). FES value = ", -fes(pnt), " Hartree. Number of Iter: ", iter
361 nacc = nacc + 1
362 history(:, nacc) = pos
363 END IF
364 END DO trials
365 WRITE (*, '(A,I6,A)') "FES| Number of Minimum found: ", nacc, "."
366
367 DEALLOCATE (xx, dx, pos0, rnd, pos)
368 DEALLOCATE (history)
369
370 END SUBROUTINE fes_min
371
372! **************************************************************************************************
373!> \brief Finds path between two points (a) and (b)
374!> \param fes ...
375!> \param ndim ...
376!> \param ngrid ...
377!> \param dp_grid ...
378!> \param iperd ...
379!> \param x0 ...
380!> \param ndw ...
381!> \param mep_input_data ...
382!> \param l_int ...
383!> \par History
384!> 12.2010 created [tlaino]
385!> teodoro.laino .at. gmail.com
386!> \author Teodoro Laino
387! **************************************************************************************************
388 SUBROUTINE fes_path(fes, ndim, ngrid, dp_grid, iperd, x0, ndw, mep_input_data, l_int)
389 REAL(kind=dp), DIMENSION(:), POINTER :: fes
390 INTEGER, INTENT(IN) :: ndim
391 INTEGER, DIMENSION(:), POINTER :: ngrid
392 REAL(kind=dp), DIMENSION(:), POINTER :: dp_grid
393 INTEGER, DIMENSION(:), POINTER :: iperd
394 REAL(kind=dp), DIMENSION(:), POINTER :: x0
395 INTEGER, INTENT(IN) :: ndw
396 TYPE(mep_input_data_type), INTENT(IN) :: mep_input_data
397 LOGICAL :: l_int
398
399 INTEGER :: i, id, irep, iter, nf, nreplica, ns, &
400 pnt, unit_nr
401 INTEGER, DIMENSION(:), POINTER :: ipos
402 LOGICAL :: converged
403 REAL(kind=dp) :: avg1, avg2, diff, ene, norm_dx, xx0, yy0
404 REAL(kind=dp), DIMENSION(:), POINTER :: davg1, davg2, dxx, dyy, fes_rep, tang, &
405 xx, yy
406 REAL(kind=dp), DIMENSION(:, :), POINTER :: dx, pos, pos_old
407
408 IF (ndw /= ndim) cpabort("Not implemented for projected FES!")
409 nreplica = mep_input_data%nreplica
410 ALLOCATE (xx(ndim), dx(ndim, nreplica), pos_old(ndim, nreplica), pos(ndim, nreplica), &
411 ipos(ndim), fes_rep(nreplica), dxx(ndim), dyy(ndim), yy(ndim), davg1(ndim), &
412 tang(ndim), davg2(ndim))
413
414 IF (l_int) THEN
415 id = 0
416 DO i = ndim, ndim - ndw + 1, -1
417 id = id + 1
418 pos(i, 1) = mep_input_data%minima(id, 1)
419 pos(i, nreplica) = mep_input_data%minima(id, 2)
420 END DO
421
422 ! Interpolate nreplica-2 points
423 xx = (pos(:, nreplica) - pos(:, 1))/real(nreplica - 1, kind=dp)
424 DO irep = 2, nreplica - 1
425 pos(:, irep) = pos(:, 1) + xx(:)*real(irep - 1, kind=dp)
426 END DO
427
428 ELSE
429 pos = mep_input_data%minima
430 END IF
431
432 ! Compute value and derivative in all replicas
433 DO irep = 1, nreplica
434 ipos = floor((pos(:, irep) - x0)/dp_grid) + 1
435 pnt = point_no_pbc(ipos, ngrid, ndim)
436 dx(:, irep) = derivative(fes, ipos, iperd, ndim, ngrid, dp_grid)
437 fes_rep(irep) = -fes(pnt)
438 END DO
439
440 ! Implement a simple elastic band method (Hamiltonian): definitely not the best
441 ! method, but for such a simple task it should be more than enough
442 converged = .false.
443 pos_old = pos
444 iter = 0
445 DO WHILE ((.NOT. converged) .AND. (iter <= mep_input_data%max_iter))
446 iter = iter + 1
447 avg1 = 0.0_dp
448 ! compute average length (distance 1)
449 DO irep = 2, nreplica
450 xx = pos(:, irep) - pos(:, irep - 1)
451 avg1 = avg1 + sqrt(dot_product(xx, xx))
452 END DO
453 avg1 = avg1/real(nreplica - 1, kind=dp)
454
455 avg2 = 0.0_dp
456 ! compute average length (distance 2)
457 DO irep = 3, nreplica
458 xx = pos(:, irep) - pos(:, irep - 2)
459 avg2 = avg2 + sqrt(dot_product(xx, xx))
460 END DO
461 avg2 = avg2/real(nreplica - 2, kind=dp)
462
463 ! compute energy and derivatives
464 dx = 0.0_dp
465 ene = 0.0_dp
466 ns = 1
467 nf = nreplica
468 DO irep = 1, nreplica
469 ! compute energy and map point replica irep
470 ipos = floor((pos(:, irep) - x0)/dp_grid) + 1
471 pnt = point_no_pbc(ipos, ngrid, ndim)
472 fes_rep(irep) = -fes(pnt)
473 IF ((irep == 1) .OR. (irep == nreplica)) cycle
474
475 ! -------------------------------------------------------------
476 ! compute non-linear elastic terms : including only 2-d springs
477 ! -------------------------------------------------------------
478 davg2 = 0.0_dp
479 IF (irep < nf - 1) THEN
480 xx = pos(:, irep) - pos(:, irep + 2)
481 xx0 = sqrt(dot_product(xx, xx))
482 dxx = 1.0_dp/xx0*xx
483 ene = ene + 0.25_dp*mep_input_data%kb*(xx0 - avg2)**2
484 davg2 = davg2 + dxx
485 END IF
486
487 IF (irep > ns + 1) THEN
488 xx = pos(:, irep) - pos(:, irep - 2)
489 yy0 = sqrt(dot_product(xx, xx))
490 dyy = 1.0_dp/yy0*xx
491 davg2 = davg2 + dyy
492 END IF
493 davg2 = davg2/real(nreplica - 2, kind=dp)
494
495 IF (irep < nf - 1) THEN
496 dx(:, irep) = dx(:, irep) + 0.5_dp*mep_input_data%kb*(xx0 - avg2)*(dxx - davg2)
497 END IF
498 IF (irep > ns + 1) THEN
499 dx(:, irep) = dx(:, irep) + 0.5_dp*mep_input_data%kb*(yy0 - avg2)*(dyy - davg2)
500 END IF
501
502 ! -------------------------------------------------------------
503 ! Evaluation of the elastic term
504 ! -------------------------------------------------------------
505 xx = pos(:, irep) - pos(:, irep + 1)
506 yy0 = sqrt(dot_product(xx, xx))
507 dyy = 1.0_dp/yy0*xx
508
509 xx = pos(:, irep) - pos(:, irep - 1)
510 xx0 = sqrt(dot_product(xx, xx))
511 dxx = 1.0_dp/xx0*xx
512 davg1 = (dxx + dyy)/real(nreplica - 1, kind=dp)
513
514 ene = ene + 0.5_dp*mep_input_data%kb*(xx0 - avg1)**2
515 dx(:, irep) = dx(:, irep) + mep_input_data%kb*(xx0 - avg1)*(dxx - davg1) + &
516 mep_input_data%kb*(yy0 - avg1)*(dyy - davg1)
517
518 ! Evaluate the tangent
519 xx = pos(:, irep + 1) - pos(:, irep)
520 xx = xx/sqrt(dot_product(xx, xx))
521 yy = pos(:, irep) - pos(:, irep - 1)
522 yy = yy/sqrt(dot_product(yy, yy))
523 tang = xx + yy
524 tang = tang/sqrt(dot_product(tang, tang))
525
526 xx = derivative(fes, ipos, iperd, ndim, ngrid, dp_grid)
527 dx(:, irep) = dot_product(dx(:, irep), tang)*tang + &
528 xx - dot_product(xx, tang)*tang
529 END DO
530 dx(:, 1) = 0.0_dp
531 dx(:, nreplica) = 0.0_dp
532
533 ! propagate the band with a SD step
534 diff = 0.0_dp
535 DO irep = 1, nreplica
536 ene = ene + fes_rep(irep)
537 IF ((irep == 1) .OR. (irep == nreplica)) cycle
538
539 norm_dx = sqrt(dot_product(dx(:, irep), dx(:, irep)))
540 IF (norm_dx /= 0.0_dp) THEN
541 pos(:, irep) = pos(:, irep) - min(0.1_dp, norm_dx)*dx(:, irep)/norm_dx
542 END IF
543 xx = pos(:, irep) - pos_old(:, irep)
544 diff = diff + dot_product(xx, xx)
545 END DO
546 ! SQRT(diff) <= 0.001_dp
547 IF (diff <= 1.0e-6_dp) THEN
548 converged = .true.
549 END IF
550 pos_old = pos
551 WRITE (*, *) "Iteration nr.", iter, sqrt(diff)
552 END DO
553
554 WRITE (*, *) "MEP saved on <mep.data> file."
555 CALL open_file(unit_number=unit_nr, file_name="mep.data", file_action="WRITE", file_status="UNKNOWN", file_form="FORMATTED")
556 DO irep = 1, nreplica
557 ! compute energy and derivative for each single point of the replica
558 ipos = floor((pos(:, irep) - x0)/dp_grid) + 1
559 pnt = point_no_pbc(ipos, ngrid, ndim)
560 fes_rep(irep) = -fes(pnt)
561 WRITE (unit_nr, *) irep, pos(:, nreplica - irep + 1), fes_rep(nreplica - irep + 1)
562 END DO
563 CALL close_file(unit_nr)
564
565 DEALLOCATE (xx, dx, pos, fes_rep, ipos, pos_old, yy, dyy, dxx, davg1, tang, davg2)
566 END SUBROUTINE fes_path
567
568! **************************************************************************************************
569!> \brief Dump FES with a GAUSSIAN cube format - Useful for multidimensional FES
570!> \param idim ...
571!> \param fes ...
572!> \param pos ...
573!> \param ndim ...
574!> \param ngrid ...
575!> \param dp_grid ...
576!> \param x0 ...
577!> \param ndw ...
578!> \param l_fes_int ...
579!> \param file ...
580!> \par History
581!> 12.2013 created [tlaino]
582!> teodoro.laino .at. gmail.com
583!> \author Teodoro Laino
584! **************************************************************************************************
585 SUBROUTINE fes_cube_write(idim, fes, pos, ndim, ngrid, dp_grid, x0, ndw, l_fes_int, file)
586 INTEGER, INTENT(IN) :: idim
587 REAL(kind=dp), DIMENSION(:), POINTER :: fes
588 INTEGER, DIMENSION(:), POINTER :: pos
589 INTEGER, INTENT(IN) :: ndim
590 INTEGER, DIMENSION(:), POINTER :: ngrid
591 REAL(kind=dp), DIMENSION(:), POINTER :: dp_grid, x0
592 INTEGER, INTENT(IN) :: ndw
593 LOGICAL, INTENT(IN) :: l_fes_int
594 CHARACTER(LEN=80) :: file
595
596 CHARACTER(LEN=120) :: line
597 CHARACTER(LEN=5) :: label, labelp
598 INTEGER :: i, id(3), ii, iix, iiy, iiz, ix, iy, iz, &
599 natoms, np
600 INTEGER, DIMENSION(:), POINTER :: izat
601 REAL(kind=dp) :: cell(3, 3), delta(3), dr(3), residual, &
602 rt(3)
603 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: rho, rhot
604 REAL(kind=dp), DIMENSION(:, :), POINTER :: xat
605
607 IF (ndw .GT. 3) THEN
608 WRITE (*, *)
609 WRITE (*, *) 'ERROR: GAUSSIAN format can only handle FES on 3 CV !'
610 cpabort("")
611 END IF
612
613 OPEN (10, file=file, status='old')
614 CALL get_val_res(unit=10, section="&SUBSYS", subsection="&CELL")
615 READ (10, *) label, cell(1, 1), cell(2, 1), cell(3, 1)
616 READ (10, *) label, cell(1, 2), cell(2, 2), cell(3, 2)
617 READ (10, *) label, cell(1, 3), cell(2, 3), cell(3, 3)
618 rt(1) = -(cell(1, 1)/2._dp)
619 rt(2) = -(cell(2, 2)/2._dp)
620 rt(3) = -(cell(3, 3)/2._dp)
621
622 WRITE (*, *) 'Dumping GAUSSIAN CUBE format'
623 WRITE (*, *) 'Cell vectors'
624 WRITE (*, *)
625
626 residual = 0.0d0
627 DO ix = 1, 3
628 DO iy = ix + 1, 3
629 residual = residual + cell(ix, iy)**2
630 END DO
631 END DO
632
633 IF (residual .GT. 1.0d-6) THEN
634 WRITE (*, *)
635 WRITE (*, *) 'ERROR: this program can only handle orthogonal cells'
636 WRITE (*, *) ' with vectors pointing in the X, Y and Z directions'
637 cpabort("")
638 END IF
639
640 WRITE (*, *)
641 WRITE (*, *) 'Cube grid mesh: ', ngrid(1), 'x', ngrid(2), 'x', ngrid(3)
642 WRITE (*, *) 'Origin in:', rt
643 WRITE (*, *)
644
645 DO ix = 1, 3
646 dr(ix) = cell(ix, ix)/real(ngrid(ix), kind=dp)
647 END DO
648
649 np = ngrid(1)*ngrid(2)*ngrid(3)
650 ALLOCATE (rho(np), rhot(np))
651 CALL fes_write(123, idim, fes, pos, ndim, ngrid, dp_grid, x0, ndw, l_fes_int, rho)
652 WRITE (*, *) 'Internal FES transfer completed!'
653
654 ! translate cell
655 DO ix = 1, 3
656 delta(ix) = rt(ix)/dr(ix)
657 id(ix) = int(delta(ix))
658 delta(ix) = rt(ix) - id(ix)*dr(ix)
659 END DO
660
661 DO iz = 1, ngrid(3)
662 DO iy = 1, ngrid(2)
663 DO ix = 1, ngrid(1)
664 iix = ix + id(1)
665 iiy = iy + id(2)
666 iiz = iz + id(3)
667 IF (iix .LT. 1) iix = iix + ngrid(1)
668 IF (iiy .LT. 1) iiy = iiy + ngrid(2)
669 IF (iiz .LT. 1) iiz = iiz + ngrid(3)
670 IF (iix .GT. ngrid(1)) iix = iix - ngrid(1)
671 IF (iiy .GT. ngrid(2)) iiy = iiy - ngrid(2)
672 IF (iiz .GT. ngrid(3)) iiz = iiz - ngrid(3)
673
674 IF (iix .LT. 1) cpabort("ix < 0")
675 IF (iiy .LT. 1) cpabort("iy < 0")
676 IF (iiz .LT. 1) cpabort("iz < 0")
677 IF (iix .GT. ngrid(1)) cpabort("ix > cell")
678 IF (iiy .GT. ngrid(2)) cpabort("iy > cell")
679 IF (iiz .GT. ngrid(3)) cpabort("iz > cell")
680 i = ix + (iy - 1)*ngrid(1) + (iz - 1)*ngrid(1)*ngrid(2)
681 ii = iix + (iiy - 1)*ngrid(1) + (iiz - 1)*ngrid(1)*ngrid(2)
682 rhot(ii) = rho(i)
683 END DO
684 END DO
685 END DO
686
687 rewind(10)
688 CALL get_val_res(unit=10, section="&SUBSYS", subsection="&COORD")
689 natoms = 0
690 ALLOCATE (xat(1000, 3))
691 ALLOCATE (izat(1000))
692 DO WHILE (.true.)
693 READ (10, '(A)') line
694 IF (index(line, '&END') /= 0) EXIT
695 natoms = natoms + 1
696 READ (line, *) label, (xat(natoms, ix), ix=1, 3)
697 IF (natoms == SIZE(xat, 1)) THEN
698 CALL reallocate(xat, 1, SIZE(xat, 1)*2, 1, 3)
699 CALL reallocate(izat, 1, SIZE(izat)*2)
700 END IF
701 CALL uppercase(label)
702 DO i = 1, nelem
703 labelp = ptable(i)%symbol
704 CALL uppercase(labelp)
705 IF (trim(label) == trim(labelp)) EXIT
706 END DO
707 IF (i == nelem + 1) THEN
708 WRITE (*, *) trim(label), "In line: ", line
709 cpabort("Element not recognized!")
710 END IF
711 izat(natoms) = i
712 END DO
713 CALL reallocate(xat, 1, natoms, 1, 3)
714 CALL reallocate(izat, 1, natoms)
715
716 DO i = 1, natoms
717 DO ix = 1, 3
718 xat(i, ix) = xat(i, ix) + rt(ix) - delta(ix)
719 IF (xat(i, ix) .LT. rt(ix)) xat(i, ix) = xat(i, ix) + cell(ix, ix)
720 IF (xat(i, ix) .GT. -rt(ix)) xat(i, ix) = xat(i, ix) - cell(ix, ix)
721 END DO
722 END DO
723
724 WRITE (123, *) "FES on CUBE"
725 WRITE (123, *) "created by fes in CP2K"
726 WRITE (123, '(i5,3f12.6)') natoms, rt(1:3)*bohr
727
728 DO ix = 1, 3
729 ii = ngrid(ix)
730 WRITE (123, '(i5,4f12.6)') ii, (cell(ix, iy)/ii*bohr, iy=1, 3)
731 END DO
732
733 DO i = 1, natoms
734 WRITE (123, '(i5,4f12.6)') izat(i), 0.0, (xat(i, ix)*bohr, ix=1, 3)
735 END DO
736
737 DO ix = 1, ngrid(1)
738 DO iy = 1, ngrid(2)
739
740 WRITE (123, '(6e13.5)') (rhot(ix + (iy - 1)*ngrid(1) + (iz - 1)*ngrid(1)&
741 &*ngrid(2)), iz=1, ngrid(3))
742 END DO
743 END DO
744 DEALLOCATE (xat, rho, rhot)
745
746 END SUBROUTINE fes_cube_write
747
748END MODULE graph_methods
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
Program to Map on grid the hills spawned during a metadynamics run.
subroutine, public fes_min(fes, ndim, iperd, ngrid, dp_grid, x0, ndw)
Finds minima of the FES.
recursive subroutine, public fes_compute_low(idim, nn, fes, gauss, ind, ind0, nfes, ndim, ngauss, ngrid, iperd)
Efficiently map the gaussians on the grid.
subroutine, public fes_cube_write(idim, fes, pos, ndim, ngrid, dp_grid, x0, ndw, l_fes_int, file)
Dump FES with a GAUSSIAN cube format - Useful for multidimensional FES.
recursive subroutine, public fes_write(unit_nr, idim, fes, pos, ndim, ngrid, dp_grid, x0, ndw, l_fes_int, array)
Writes the FES on the file.
recursive subroutine, public fes_only_write(idim, fes, pos, ndim, ngrid, dp_grid, ndw, l_fes_int, unit_nr)
Writes the FES on the file when stride is requested.
subroutine, public fes_path(fes, ndim, ngrid, dp_grid, iperd, x0, ndw, mep_input_data, l_int)
Finds path between two points (a) and (b)
Module containing utils for mapping FESs.
Definition graph_utils.F:18
real(kind=dp) function, dimension(ndim), public derivative(fes, pos0, iperd, ndim, ngrid, dp_grid)
computes the derivative of the FES w.r.t CVs
Definition graph_utils.F:56
subroutine, public get_val_res(unit, section, keyword, subsection, i_val, r_val)
Parser informations from the cp2k input/restart.
integer function, public point_no_pbc(pos, ngrid, ndim)
Computes the pointer to the 1D array given the n-dimensional position non-PBC version.
subroutine, public pbc(pos, iperd, ngrid, ndim)
Computes the pointer to the 1D array given the n-dimensional position PBC version.
integer function, public point_pbc(pos, iperd, ngrid, ndim)
Computes the pointer to the 1D array given the n-dimensional position PBC version.
Definition graph_utils.F:96
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Utility routines for the memory handling.
Periodic Table related data definitions.
type(atom), dimension(0:nelem), public ptable
subroutine, public init_periodic_table()
Initialization of Periodic Table related data.
integer, parameter, public nelem
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public bohr
Definition physcon.F:147
Utilities for string manipulations.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.