(git:f2099e5)
Loading...
Searching...
No Matches
pint_qtb.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Methods to apply the QTB thermostat to PI runs.
10!> Based on the PILE implementation from Felix Uhl (pint_pile.F)
11!> \author Fabien Brieuc
12!> \par History
13!> 02.2018 created [Fabien Brieuc]
14! **************************************************************************************************
16 USE cp_files, ONLY: open_file
21 USE fft_tools, ONLY: fwfft,&
23 fft_alloc,&
24 fft_dealloc
30 USE kinds, ONLY: dp
31 USE mathconstants, ONLY: pi,&
32 twopi
34 USE parallel_rng_types, ONLY: gaussian,&
38 USE pint_io, ONLY: pint_write_line
42#include "../base/base_uses.f90"
43
44 IMPLICIT NONE
45
46 PRIVATE
47
48 PUBLIC :: pint_qtb_step, &
52
53 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pint_qtb'
54
55CONTAINS
56
57! ***************************************************************************
58!> \brief initializes the data for a QTB run
59!> \brief ...
60!> \param qtb_therm ...
61!> \param pint_env ...
62!> \param normalmode_env ...
63!> \param section ...
64! **************************************************************************************************
65 SUBROUTINE pint_qtb_init(qtb_therm, pint_env, normalmode_env, section)
66 TYPE(qtb_therm_type), POINTER :: qtb_therm
67 TYPE(pint_env_type), INTENT(INOUT) :: pint_env
68 TYPE(normalmode_env_type), POINTER :: normalmode_env
69 TYPE(section_vals_type), POINTER :: section
70
71 CHARACTER(LEN=rng_record_length) :: rng_record
72 INTEGER :: i, j, p
73 LOGICAL :: restart
74 REAL(kind=dp) :: dti2, ex
75 REAL(kind=dp), DIMENSION(3, 2) :: initial_seed
76 TYPE(section_vals_type), POINTER :: rng_section
77
78 IF (pint_env%propagator%prop_kind /= propagator_rpmd) THEN
79 cpabort("QTB is designed to work with the RPMD propagator only")
80 END IF
81
82 pint_env%e_qtb = 0.0_dp
83 ALLOCATE (qtb_therm)
84 qtb_therm%thermostat_energy = 0.0_dp
85
86 !Get input parameters
87 CALL section_vals_val_get(section, "TAU", r_val=qtb_therm%tau)
88 CALL section_vals_val_get(section, "LAMBDA", r_val=qtb_therm%lamb)
89 CALL section_vals_val_get(section, "TAUCUT", r_val=qtb_therm%taucut)
90 CALL section_vals_val_get(section, "LAMBCUT", r_val=qtb_therm%lambcut)
91 CALL section_vals_val_get(section, "FP", i_val=qtb_therm%fp)
92 CALL section_vals_val_get(section, "NF", i_val=qtb_therm%nf)
93 CALL section_vals_val_get(section, "THERMOSTAT_ENERGY", r_val=qtb_therm%thermostat_energy)
94
95 p = pint_env%p
96 dti2 = 0.5_dp*pint_env%dt
97 ALLOCATE (qtb_therm%c1(p))
98 ALLOCATE (qtb_therm%c2(p))
99 ALLOCATE (qtb_therm%g_fric(p))
100 ALLOCATE (qtb_therm%massfact(p, pint_env%ndim))
101
102 !Initialize everything
103 qtb_therm%g_fric(1) = 1.0_dp/qtb_therm%tau
104 DO i = 2, p
105 qtb_therm%g_fric(i) = sqrt((1.d0/qtb_therm%tau)**2 + (qtb_therm%lamb)**2* &
106 normalmode_env%lambda(i))
107 END DO
108 DO i = 1, p
109 ex = -dti2*qtb_therm%g_fric(i)
110 qtb_therm%c1(i) = exp(ex)
111 ex = qtb_therm%c1(i)*qtb_therm%c1(i)
112 qtb_therm%c2(i) = sqrt(1.0_dp - ex)
113 END DO
114 DO j = 1, pint_env%ndim
115 DO i = 1, pint_env%p
116 qtb_therm%massfact(i, j) = sqrt(1.0_dp/pint_env%mass_fict(i, j))
117 END DO
118 END DO
119
120 !prepare Random number generator
121 NULLIFY (rng_section)
122 rng_section => section_vals_get_subs_vals(section, &
123 subsection_name="RNG_INIT")
124 CALL section_vals_get(rng_section, explicit=restart)
125 IF (restart) THEN
126 CALL section_vals_val_get(rng_section, "_DEFAULT_KEYWORD_", &
127 i_rep_val=1, c_val=rng_record)
128 qtb_therm%gaussian_rng_stream = rng_stream_type_from_record(rng_record)
129 ELSE
130 initial_seed(:, :) = real(pint_env%thermostat_rng_seed, dp)
131 qtb_therm%gaussian_rng_stream = rng_stream_type( &
132 name="qtb_rng_gaussian", distribution_type=gaussian, &
133 extended_precision=.true., &
134 seed=initial_seed)
135 END IF
136
137 !Initialization of the QTB random forces
138 CALL pint_qtb_forces_init(pint_env, normalmode_env, qtb_therm, restart)
139
140 END SUBROUTINE pint_qtb_init
141
142! **************************************************************************************************
143!> \brief ...
144!> \param vold ...
145!> \param vnew ...
146!> \param p ...
147!> \param ndim ...
148!> \param masses ...
149!> \param qtb_therm ...
150! **************************************************************************************************
151 SUBROUTINE pint_qtb_step(vold, vnew, p, ndim, masses, qtb_therm)
152 REAL(kind=dp), DIMENSION(:, :), POINTER :: vold, vnew
153 INTEGER, INTENT(IN) :: p, ndim
154 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: masses
155 TYPE(qtb_therm_type), POINTER :: qtb_therm
156
157 CHARACTER(len=*), PARAMETER :: routinen = 'pint_qtb_step'
158
159 INTEGER :: handle, i, ibead, idim
160 REAL(kind=dp) :: delta_ekin
161
162 CALL timeset(routinen, handle)
163 delta_ekin = 0.0_dp
164
165 !update random forces
166 DO ibead = 1, p
167 qtb_therm%cpt(ibead) = qtb_therm%cpt(ibead) + 1
168 !new random forces at every qtb_therm%step
169 IF (qtb_therm%cpt(ibead) == 2*qtb_therm%step(ibead)) THEN
170 IF (ibead == 1) THEN
171 !update the rng status
172 DO i = 1, qtb_therm%nf - 1
173 qtb_therm%rng_status(i) = qtb_therm%rng_status(i + 1)
174 END DO
175 CALL qtb_therm%gaussian_rng_stream%dump(qtb_therm%rng_status(qtb_therm%nf))
176 END IF
177 DO idim = 1, ndim
178 !update random numbers
179 DO i = 1, qtb_therm%nf - 1
180 qtb_therm%r(i, ibead, idim) = qtb_therm%r(i + 1, ibead, idim)
181 END DO
182 qtb_therm%r(qtb_therm%nf, ibead, idim) = qtb_therm%gaussian_rng_stream%next()
183 !compute new random force through the convolution product
184 qtb_therm%rf(ibead, idim) = 0.0_dp
185 DO i = 1, qtb_therm%nf
186 qtb_therm%rf(ibead, idim) = qtb_therm%rf(ibead, idim) + &
187 qtb_therm%h(i, ibead)*qtb_therm%r(i, ibead, idim)
188 END DO
189 END DO
190 qtb_therm%cpt(ibead) = 0
191 END IF
192 END DO
193
194 !perform MD step
195 DO idim = 1, ndim
196 DO ibead = 1, p
197 vnew(ibead, idim) = qtb_therm%c1(ibead)*vold(ibead, idim) + &
198 qtb_therm%massfact(ibead, idim)*qtb_therm%c2(ibead)* &
199 qtb_therm%rf(ibead, idim)
200 delta_ekin = delta_ekin + masses(ibead, idim)*( &
201 vnew(ibead, idim)*vnew(ibead, idim) - &
202 vold(ibead, idim)*vold(ibead, idim))
203 END DO
204 END DO
205
206 qtb_therm%thermostat_energy = qtb_therm%thermostat_energy - 0.5_dp*delta_ekin
207
208 CALL timestop(handle)
209 END SUBROUTINE pint_qtb_step
210
211! ***************************************************************************
212!> \brief releases the qtb environment
213!> \param qtb_therm qtb data to be released
214! **************************************************************************************************
215 SUBROUTINE pint_qtb_release(qtb_therm)
216
217 TYPE(qtb_therm_type), INTENT(INOUT) :: qtb_therm
218
219 DEALLOCATE (qtb_therm%c1)
220 DEALLOCATE (qtb_therm%c2)
221 DEALLOCATE (qtb_therm%g_fric)
222 DEALLOCATE (qtb_therm%massfact)
223 DEALLOCATE (qtb_therm%rf)
224 DEALLOCATE (qtb_therm%h)
225 DEALLOCATE (qtb_therm%r)
226 DEALLOCATE (qtb_therm%cpt)
227 DEALLOCATE (qtb_therm%step)
228 DEALLOCATE (qtb_therm%rng_status)
229
230 END SUBROUTINE pint_qtb_release
231
232! ***************************************************************************
233!> \brief returns the qtb kinetic energy contribution
234!> \param pint_env ...
235! **************************************************************************************************
236 SUBROUTINE pint_calc_qtb_energy(pint_env)
237 TYPE(pint_env_type), INTENT(INOUT) :: pint_env
238
239 IF (ASSOCIATED(pint_env%qtb_therm)) THEN
240 pint_env%e_qtb = pint_env%qtb_therm%thermostat_energy
241 END IF
242
243 END SUBROUTINE pint_calc_qtb_energy
244
245! ***************************************************************************
246!> \brief initialize the QTB random forces
247!> \param pint_env ...
248!> \param normalmode_env ...
249!> \param qtb_therm ...
250!> \param restart ...
251!> \author Fabien Brieuc
252! **************************************************************************************************
253 SUBROUTINE pint_qtb_forces_init(pint_env, normalmode_env, qtb_therm, restart)
254 TYPE(pint_env_type), INTENT(IN) :: pint_env
255 TYPE(normalmode_env_type), POINTER :: normalmode_env
256 TYPE(qtb_therm_type), POINTER :: qtb_therm
257 LOGICAL :: restart
258
259 CHARACTER(len=*), PARAMETER :: routinen = 'pint_qtb_forces_init'
260
261 COMPLEX(KIND=dp) :: tmp1
262 COMPLEX(KIND=dp), CONTIGUOUS, DIMENSION(:), &
263 POINTER :: filter_in, filter_out
264 INTEGER :: handle, i, ibead, idim, log_unit, ndim, &
265 nf, p, print_level, step
266 REAL(kind=dp) :: aa, bb, correct, dt, dw, fcut, h, kt, &
267 tmp, w
268 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: fp
269 REAL(kind=dp), DIMENSION(:), POINTER :: fp1
270 TYPE(cp_logger_type), POINTER :: logger
271 TYPE(mp_para_env_type), POINTER :: para_env
272
273 CALL timeset(routinen, handle)
274
275 p = pint_env%p
276 ndim = pint_env%ndim
277 dt = pint_env%dt
278 IF (mod(qtb_therm%nf, 2) /= 0) qtb_therm%nf = qtb_therm%nf + 1
279 nf = qtb_therm%nf
280
281 para_env => pint_env%logger%para_env
282
283 ALLOCATE (qtb_therm%rng_status(nf))
284 ALLOCATE (qtb_therm%h(nf, p))
285 ALLOCATE (qtb_therm%step(p))
286
287 !initialize random forces on ionode only
288 IF (para_env%is_source()) THEN
289
290 NULLIFY (logger)
291 logger => cp_get_default_logger()
292 print_level = logger%iter_info%print_level
293
294 !physical temperature (T) not the simulation one (TxP)
295 kt = pint_env%kT*pint_env%propagator%temp_sim2phys
296
297 ALLOCATE (fp(nf/2))
298 CALL fft_alloc(filter_in, [nf])
299 CALL fft_alloc(filter_out, [nf])
300
301 IF (print_level == debug_print_level) THEN
302 !create log file if print_level is debug
303 CALL open_file(file_name=trim(logger%iter_info%project_name)//".qtbLog", &
304 file_action="WRITE", file_status="UNKNOWN", unit_number=log_unit)
305 WRITE (log_unit, '(A)') ' # Log file for the QTB random forces generation'
306 WRITE (log_unit, '(A)') ' # ------------------------------------------------'
307 WRITE (log_unit, '(A,I5)') ' # Number of beads P = ', p
308 WRITE (log_unit, '(A,I6)') ' # Number of dimension 3*N = ', ndim
309 WRITE (log_unit, '(A,I4)') ' # Number of filter parameters Nf=', nf
310 END IF
311
312 DO ibead = 1, p
313 !fcut is adapted to the NM freq.
314 !Note that lambda is the angular free ring freq. squared
315 fcut = sqrt((1.d0/qtb_therm%taucut)**2 + (qtb_therm%lambcut)**2* &
316 normalmode_env%lambda(ibead))
317 fcut = fcut/twopi
318 !new random forces are drawn every step
319 qtb_therm%step(ibead) = nint(1.0_dp/(2.0_dp*fcut*dt))
320 IF (qtb_therm%step(ibead) == 0) qtb_therm%step(ibead) = 1
321 step = qtb_therm%step(ibead)
322 !effective timestep h = step*dt = 1/(2*fcut)
323 h = step*dt
324 !angular freq. step - dw = 2*pi/(nf*h) = 2*wcut/nf
325 dw = twopi/(nf*h)
326
327 !generate f_P function
328 IF (qtb_therm%fp == 0) THEN
329 CALL pint_qtb_computefp0(pint_env, fp, fp1, dw, aa, bb, log_unit, ibead, print_level)
330 ELSE
331 CALL pint_qtb_computefp1(pint_env, fp, fp1, dw, aa, bb, log_unit, ibead, print_level)
332 END IF
333 fp = p*kt*fp ! fp is now in cp2k energy units
334
335 IF (print_level == debug_print_level) THEN
336 WRITE (log_unit, '(A,I4,A)') ' # -------- NM ', ibead, ' --------'
337 WRITE (log_unit, '(A,I4,A)') ' # New random forces every ', step, ' MD steps'
338 WRITE (log_unit, '(A,ES13.3,A)') ' # Angular cutoff freq. = ', twopi*fcut*4.1341e4_dp, ' rad/ps'
339 WRITE (log_unit, '(A,ES13.3,A)') ' # Free ring polymer angular freq.= ', &
340 sqrt(normalmode_env%lambda(ibead))*4.1341e4_dp, ' rad/ps'
341 WRITE (log_unit, '(A,ES13.3,A)') ' # Friction coeff. = ', qtb_therm%g_fric(ibead)*4.1341e4_dp, ' THz'
342 WRITE (log_unit, '(A,ES13.3,A)') ' # Angular frequency step dw = ', dw*4.1341e4_dp, ' rad/ps'
343 END IF
344
345 !compute the filter in Fourier space
346 IF (p == 1) THEN
347 filter_in(1) = sqrt(kt)*(1.0_dp, 0.0_dp)
348 ELSE IF (qtb_therm%fp == 1 .AND. ibead == 1) THEN
349 filter_in(1) = sqrt(p*kt)*(1.0_dp, 0.0_dp)
350 ELSE
351 filter_in(1) = sqrt(p*kt*fp1(1))*(1.0_dp, 0.0_dp)
352 END IF
353 DO i = 1, nf/2
354 w = i*dw
355 tmp = 0.5_dp*w*h
356 correct = sin(tmp)/tmp
357 filter_in(i + 1) = sqrt(fp(i))/correct*(1.0_dp, 0.0_dp)
358 filter_in(nf - i + 1) = conjg(filter_in(i + 1))
359 END DO
360
361 !compute the filter in time space - FFT
362 CALL pint_qtb_fft(filter_in, filter_out, nf)
363 !reordering + normalisation
364 !normalisation : 1/nf comes from the DFT, 1/sqrt(step) is to
365 !take into account the effective timestep h = step*dt and
366 !1/sqrt(2.0_dp) is to take into account the fact that the
367 !same random force is used for the two thermostat "half-steps"
368 DO i = 1, nf/2
369 tmp1 = filter_out(i)/(nf*sqrt(2.0_dp*step))
370 filter_out(i) = filter_out(nf/2 + i)/(nf*sqrt(2.0_dp*step))
371 filter_out(nf/2 + i) = tmp1
372 END DO
373
374 DO i = 1, nf
375 qtb_therm%h(i, ibead) = real(filter_out(i), dp)
376 END DO
377 END DO
378
379 CALL fft_dealloc(filter_in)
380 CALL fft_dealloc(filter_out)
381 DEALLOCATE (fp)
382 IF (p > 1) DEALLOCATE (fp1)
383 END IF
384
385 CALL para_env%bcast(qtb_therm%h)
386 CALL para_env%bcast(qtb_therm%step)
387
388 ALLOCATE (qtb_therm%r(nf, p, ndim))
389 ALLOCATE (qtb_therm%cpt(p))
390 ALLOCATE (qtb_therm%rf(p, ndim))
391
392 IF (restart) THEN
393 CALL pint_qtb_restart(pint_env, qtb_therm)
394 ELSE
395 !update the rng status
396 DO i = 1, qtb_therm%nf
397 CALL qtb_therm%gaussian_rng_stream%dump(qtb_therm%rng_status(i))
398 END DO
399 !if no restart then initialize random numbers from scratch
400 qtb_therm%cpt = 0
401 DO idim = 1, ndim
402 DO ibead = 1, p
403 DO i = 1, nf
404 qtb_therm%r(i, ibead, idim) = qtb_therm%gaussian_rng_stream%next()
405 END DO
406 END DO
407 END DO
408 END IF
409
410 !compute the first random forces
411 DO idim = 1, ndim
412 DO ibead = 1, p
413 qtb_therm%rf(ibead, idim) = 0.0_dp
414 DO i = 1, nf
415 qtb_therm%rf(ibead, idim) = qtb_therm%rf(ibead, idim) + &
416 qtb_therm%h(i, ibead)*qtb_therm%r(i, ibead, idim)
417 END DO
418 END DO
419 END DO
420
421 CALL timestop(handle)
422 END SUBROUTINE pint_qtb_forces_init
423
424! ***************************************************************************
425!> \brief control the generation of the first random forces in the case
426!> of a restart
427!> \param pint_env ...
428!> \param qtb_therm ...
429!> \author Fabien Brieuc
430! **************************************************************************************************
431 SUBROUTINE pint_qtb_restart(pint_env, qtb_therm)
432 TYPE(pint_env_type), INTENT(IN) :: pint_env
433 TYPE(qtb_therm_type), POINTER :: qtb_therm
434
435 INTEGER :: begin, i, ibead, idim, istep
436
437 begin = pint_env%first_step - mod(pint_env%first_step, qtb_therm%step(1)) - &
438 (qtb_therm%nf - 1)*qtb_therm%step(1)
439
440 IF (begin <= 0) THEN
441 qtb_therm%cpt = 0
442 !update the rng status
443 DO i = 1, qtb_therm%nf
444 CALL qtb_therm%gaussian_rng_stream%dump(qtb_therm%rng_status(i))
445 END DO
446 !first random numbers initialized from scratch
447 DO idim = 1, pint_env%ndim
448 DO ibead = 1, pint_env%p
449 DO i = 1, qtb_therm%nf
450 qtb_therm%r(i, ibead, idim) = qtb_therm%gaussian_rng_stream%next()
451 END DO
452 END DO
453 END DO
454 begin = 1
455 ELSE
456 qtb_therm%cpt(1) = 2*(qtb_therm%step(1) - 1)
457 DO ibead = 2, pint_env%p
458 qtb_therm%cpt(ibead) = 2*mod(begin - 1, qtb_therm%step(ibead))
459 END DO
460 END IF
461
462 !from istep = 1,2*(the last previous MD step - begin) because
463 !the thermostat step is called two times per MD step
464 !DO istep = 2*begin, 2*pint_env%first_step
465 DO istep = 1, 2*(pint_env%first_step - begin + 1)
466 DO ibead = 1, pint_env%p
467 qtb_therm%cpt(ibead) = qtb_therm%cpt(ibead) + 1
468 !new random forces at every qtb_therm%step
469 IF (qtb_therm%cpt(ibead) == 2*qtb_therm%step(ibead)) THEN
470 IF (ibead == 1) THEN
471 !update the rng status
472 DO i = 1, qtb_therm%nf - 1
473 qtb_therm%rng_status(i) = qtb_therm%rng_status(i + 1)
474 END DO
475 CALL qtb_therm%gaussian_rng_stream%dump(qtb_therm%rng_status(qtb_therm%nf))
476 END IF
477 DO idim = 1, pint_env%ndim
478 !update random numbers
479 DO i = 1, qtb_therm%nf - 1
480 qtb_therm%r(i, ibead, idim) = qtb_therm%r(i + 1, ibead, idim)
481 END DO
482 qtb_therm%r(qtb_therm%nf, ibead, idim) = qtb_therm%gaussian_rng_stream%next()
483 END DO
484 qtb_therm%cpt(ibead) = 0
485 END IF
486 END DO
487 END DO
488
489 END SUBROUTINE pint_qtb_restart
490
491! ***************************************************************************
492!> \brief compute the f_P^(0) function necessary for coupling QTB with PIMD
493!> \param pint_env ...
494!> \param fp stores the computed function on the grid used for the generation
495!> of the filter h
496!> \param fp1 stores the computed function on an larger and finer grid
497!> \param dw angular frequency step
498!> \param aa ...
499!> \param bb ...
500!> \param log_unit ...
501!> \param ibead ...
502!> \param print_level ...
503!> \author Fabien Brieuc
504! **************************************************************************************************
505 SUBROUTINE pint_qtb_computefp0(pint_env, fp, fp1, dw, aa, bb, log_unit, ibead, print_level)
506 TYPE(pint_env_type), INTENT(IN) :: pint_env
507 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: fp
508 REAL(kind=dp), DIMENSION(:), POINTER :: fp1
509 REAL(kind=dp), INTENT(IN) :: dw, aa, bb
510 INTEGER, INTENT(IN) :: log_unit, ibead, print_level
511
512 CHARACTER(len=200) :: line
513 INTEGER :: i, j, k, n, niter, nx, p
514 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: kk
515 REAL(kind=dp) :: dx, dx1, err, fprev, hbokt, malpha, op, &
516 r2, tmp, w, x1, xmax, xmin, xx
517 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: h, x, x2
518 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: fpxk, xk, xk2
519
520 n = SIZE(fp)
521 p = pint_env%p
522
523 !using the physical temperature (T) not the simulation one (TxP)
524 hbokt = 1.0_dp/(pint_env%kT*pint_env%propagator%temp_sim2phys)
525
526 !P = 1 : standard QTB
527 !fp = theta(w, T) / kT
528 IF (p == 1) THEN
529 DO j = 1, n
530 w = j*dw
531 tmp = hbokt*w
532 fp(j) = tmp*(0.5_dp + 1.0_dp/(exp(tmp) - 1.0_dp))
533 END DO
534
535 IF (print_level == debug_print_level) THEN
536 WRITE (log_unit, '(A)') ' # ------------------------------------------------'
537 WRITE (log_unit, '(A)') ' # computed fp^(0) function'
538 WRITE (log_unit, '(A)') ' # i, w(a.u.), fp'
539 DO j = 1, n
540 WRITE (log_unit, *) j, j*dw, j*0.5_dp*hbokt*dw, fp(j)
541 END DO
542 END IF
543 ! P > 1: QTB-PIMD
544 ELSE
545 !**** initialization ****
546 dx1 = 0.5_dp*hbokt*dw
547 xmin = 1.0e-7_dp !these values allows for an acceptable
548 dx = 0.05_dp !ratio between accuracy, computing time and
549 xmax = 10000.0_dp !memory requirement - tested for P up to 1024
550 nx = int((xmax - xmin)/dx) + 1
551 nx = nx + nx/5 !add 20% points to avoid any problems at the end
552 !of the interval (probably unnecessary)
553 IF (ibead == 1) THEN
554 op = 1.0_dp/p
555 malpha = op !mixing parameter alpha = 1/P
556 niter = 30 !30 iterations are enough to converge
557
558 IF (print_level == debug_print_level) THEN
559 WRITE (log_unit, '(A)') ' # ------------------------------------------------'
560 WRITE (log_unit, '(A)') ' # computing fp^(0) function'
561 WRITE (log_unit, '(A)') ' # parameters used:'
562 WRITE (log_unit, '(A,ES13.3)') ' # dx = ', dx
563 WRITE (log_unit, '(A,ES13.3)') ' # xmin = ', xmin
564 WRITE (log_unit, '(A,ES13.3)') ' # xmax = ', xmax
565 WRITE (log_unit, '(A,I8,I8)') ' # nx, n = ', nx, n
566 END IF
567
568 ALLOCATE (x(nx))
569 ALLOCATE (x2(nx))
570 ALLOCATE (h(nx))
571 ALLOCATE (fp1(nx))
572 ALLOCATE (xk(p - 1, nx))
573 ALLOCATE (xk2(p - 1, nx))
574 ALLOCATE (kk(p - 1, nx))
575 ALLOCATE (fpxk(p - 1, nx))
576
577 ! initialize fp(x)
578 ! fp1 = fp(x) = h(x/P)
579 ! fpxk = fp(xk) = h(xk/P)
580 DO j = 1, nx
581 x(j) = xmin + (j - 1)*dx
582 x2(j) = x(j)**2
583 h(j) = x(j)/tanh(x(j))
584 IF (x(j) <= 1.0e-10_dp) h(j) = 1.0_dp
585 fp1(j) = op*x(j)/tanh(x(j)*op)
586 IF (x(j)*op <= 1.0e-10_dp) fp1(j) = 1.0_dp
587 DO k = 1, p - 1
588 xk2(k, j) = x2(j) + (p*sin(k*pi*op))**2
589 xk(k, j) = sqrt(xk2(k, j))
590 kk(k, j) = nint((xk(k, j) - xmin)/dx) + 1
591 fpxk(k, j) = xk(k, j)*op/tanh(xk(k, j)*op)
592 IF (xk(k, j)*op <= 1.0e-10_dp) fpxk(k, j) = 1.0_dp
593 END DO
594 END DO
595
596 ! **** resolution ****
597 ! compute fp(x)
598 DO i = 1, niter
599 err = 0.0_dp
600 DO j = 1, nx
601 tmp = 0.0_dp
602 DO k = 1, p - 1
603 tmp = tmp + fpxk(k, j)*x2(j)/xk2(k, j)
604 END DO
605 fprev = fp1(j)
606 fp1(j) = malpha*(h(j) - tmp) + (1.0_dp - malpha)*fp1(j)
607 IF (j <= n) err = err + abs(1.0_dp - fp1(j)/fprev) ! compute "errors"
608 END DO
609 err = err/n
610
611 ! Linear regression on the last 20% of the F_P function
612 CALL pint_qtb_linreg(fp1(8*nx/10:nx), x(8*nx/10:nx), aa, bb, r2, log_unit, print_level)
613
614 ! compute the new F_P(xk*sqrt(P))
615 ! through linear interpolation
616 ! or linear extrapolation if outside of the range
617 DO j = 1, nx
618 DO k = 1, p - 1
619 IF (kk(k, j) < nx) THEN
620 fpxk(k, j) = fp1(kk(k, j)) + (fp1(kk(k, j) + 1) - fp1(kk(k, j)))/dx* &
621 (xk(k, j) - x(kk(k, j)))
622 ELSE
623 fpxk(k, j) = aa*xk(k, j) + bb
624 END IF
625 END DO
626 END DO
627 END DO
628
629 IF (print_level == debug_print_level) THEN
630 ! **** tests ****
631 WRITE (log_unit, '(A,ES9.3)') ' # average error during computation: ', err
632 WRITE (log_unit, '(A,ES9.3)') ' # slope of F_P at high freq. - theoretical: ', op
633 WRITE (log_unit, '(A,ES9.3)') ' # slope of F_P at high freq. - calculated: ', aa
634 WRITE (log_unit, '(A,F6.3)') ' # F_P at zero freq. - theoretical: ', 1.0_dp
635 WRITE (log_unit, '(A,F6.3)') ' # F_P at zero freq. - calculated: ', fp1(1)
636 ELSE IF (print_level > silent_print_level) THEN
637 CALL pint_write_line("QTB| Initialization of random forces using fP0 function")
638 CALL pint_write_line("QTB| Computation of fP0 function")
639 WRITE (line, '(A,ES9.3)') 'QTB| average error ', err
640 CALL pint_write_line(trim(line))
641 WRITE (line, '(A,ES9.3)') 'QTB| slope at high frequency - theoretical: ', op
642 CALL pint_write_line(trim(line))
643 WRITE (line, '(A,ES9.3)') 'QTB| slope at high frequency - calculated: ', aa
644 CALL pint_write_line(trim(line))
645 WRITE (line, '(A,F6.3)') 'QTB| value at zero frequency - theoretical: ', 1.0_dp
646 CALL pint_write_line(trim(line))
647 WRITE (line, '(A,F6.3)') 'QTB| value at zero frequency - calculated: ', fp1(1)
648 CALL pint_write_line(trim(line))
649 END IF
650
651 IF (print_level == debug_print_level) THEN
652 ! **** write solution ****
653 WRITE (log_unit, '(A)') ' # ------------------------------------------------'
654 WRITE (log_unit, '(A)') ' # computed fp function'
655 WRITE (log_unit, '(A)') ' # i, w(a.u.), x, fp'
656 DO j = 1, nx
657 WRITE (log_unit, *) j, j*dw, xmin + (j - 1)*dx, fp1(j)
658 END DO
659 END IF
660
661 DEALLOCATE (x)
662 DEALLOCATE (x2)
663 DEALLOCATE (h)
664 DEALLOCATE (xk)
665 DEALLOCATE (xk2)
666 DEALLOCATE (kk)
667 DEALLOCATE (fpxk)
668 END IF
669
670 ! compute values of fP on the grid points for the current NM
671 ! through linear interpolation / regression
672 DO j = 1, n
673 x1 = j*dx1
674 k = nint((x1 - xmin)/dx) + 1
675 IF (k > nx) THEN
676 fp(j) = aa*x1 + bb
677 ELSE IF (k <= 0) THEN
678 CALL pint_write_line("QTB| error in fp computation x < xmin")
679 cpabort("Error in fp computation (x < xmin) in initialization of QTB random forces")
680 ELSE
681 xx = xmin + (k - 1)*dx
682 IF (x1 > xx) THEN
683 fp(j) = fp1(k) + (fp1(k + 1) - fp1(k))/dx*(x1 - xx)
684 ELSE
685 fp(j) = fp1(k) + (fp1(k) - fp1(k - 1))/dx*(x1 - xx)
686 END IF
687 END IF
688 END DO
689
690 END IF
691
692 END SUBROUTINE pint_qtb_computefp0
693
694! ***************************************************************************
695!> \brief compute the f_P^(1) function necessary for coupling QTB with PIMD
696!> \param pint_env ...
697!> \param fp stores the computed function on the grid used for the generation
698!> of the filter h
699!> \param fp1 stores the computed function on an larger and finer grid
700!> \param dw angular frequency step
701!> \param aa ...
702!> \param bb ...
703!> \param log_unit ...
704!> \param ibead ...
705!> \param print_level ...
706!> \author Fabien Brieuc
707! **************************************************************************************************
708 SUBROUTINE pint_qtb_computefp1(pint_env, fp, fp1, dw, aa, bb, log_unit, ibead, print_level)
709 TYPE(pint_env_type), INTENT(IN) :: pint_env
710 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: fp
711 REAL(kind=dp), DIMENSION(:), POINTER :: fp1
712 REAL(kind=dp) :: dw, aa, bb
713 INTEGER, INTENT(IN) :: log_unit, ibead, print_level
714
715 CHARACTER(len=200) :: line
716 INTEGER :: i, j, k, n, niter, nx, p
717 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: kk
718 REAL(kind=dp) :: dx, dx1, err, fprev, hbokt, malpha, op, &
719 op1, r2, tmp, tmp1, xmax, xmin, xx
720 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: h, x, x2
721 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: fpxk, xk, xk2
722
723 n = SIZE(fp)
724 p = pint_env%p
725
726 !using the physical temperature (T) not the simulation one (TxP)
727 hbokt = 1.0_dp/(pint_env%kT*pint_env%propagator%temp_sim2phys)
728
729 !Centroid NM (ibead=1) : classical
730 !fp = 1
731 IF (ibead == 1) THEN
732 DO j = 1, n
733 fp(j) = 1.0_dp
734 END DO
735 ELSE
736 !**** initialization ****
737 dx1 = 0.5_dp*hbokt*dw
738 xmin = 1.0e-3_dp !these values allows for an acceptable
739 dx = 0.05_dp !ratio between accuracy, computing time and
740 xmax = 10000.0_dp !memory requirement - tested for P up to 1024
741 nx = int((xmax - xmin)/dx) + 1
742 nx = nx + nx/5 !add 20% points to avoid problem at the end
743 !of the interval (probably unnecessary)
744 op = 1.0_dp/p
745 IF (ibead == 2) THEN
746 op1 = 1.0_dp/(p - 1)
747 malpha = op !mixing parameter alpha = 1/P
748 niter = 40 !40 iterations are enough to converge
749
750 IF (print_level == debug_print_level) THEN
751 ! **** write solution ****
752 WRITE (log_unit, '(A)') ' # ------------------------------------------------'
753 WRITE (log_unit, '(A)') ' # computing fp^(1) function'
754 WRITE (log_unit, '(A)') ' # parameters used:'
755 WRITE (log_unit, '(A,ES13.3)') ' # dx = ', dx
756 WRITE (log_unit, '(A,ES13.3)') ' # xmin = ', xmin
757 WRITE (log_unit, '(A,ES13.3)') ' # xmax = ', xmax
758 WRITE (log_unit, '(A,I8,I8)') ' # nx, n = ', nx, n
759 END IF
760
761 ALLOCATE (x(nx))
762 ALLOCATE (x2(nx))
763 ALLOCATE (h(nx))
764 ALLOCATE (fp1(nx))
765 ALLOCATE (xk(p - 1, nx))
766 ALLOCATE (xk2(p - 1, nx))
767 ALLOCATE (kk(p - 1, nx))
768 ALLOCATE (fpxk(p - 1, nx))
769
770 ! initialize F_P(x) = f_P(x_1)
771 ! fp1 = fp(x) = h(x/(P-1))
772 ! fpxk = fp(xk) = h(xk/(P-1))
773 DO j = 1, nx
774 x(j) = xmin + (j - 1)*dx
775 x2(j) = x(j)**2
776 h(j) = x(j)/tanh(x(j))
777 IF (x(j) <= 1.0e-10_dp) h(j) = 1.0_dp
778 fp1(j) = op1*x(j)/tanh(x(j)*op1)
779 IF (x(j)*op1 <= 1.0e-10_dp) fp1(j) = 1.0_dp
780 DO k = 1, p - 1
781 xk2(k, j) = x2(j) + (p*sin(k*pi*op))**2
782 xk(k, j) = sqrt(xk2(k, j) - (p*sin(pi*op))**2)
783 kk(k, j) = nint((xk(k, j) - xmin)/dx) + 1
784 fpxk(k, j) = xk(k, j)*op1/tanh(xk(k, j)*op1)
785 IF (xk(k, j)*op1 <= 1.0e-10_dp) fpxk(k, j) = 1.0_dp
786 END DO
787 END DO
788
789 ! **** resolution ****
790 ! compute fp(x)
791 DO i = 1, niter
792 err = 0.0_dp
793 DO j = 1, nx
794 tmp = 0.0_dp
795 DO k = 2, p - 1
796 tmp = tmp + fpxk(k, j)*x2(j)/xk2(k, j)
797 END DO
798 fprev = fp1(j)
799 tmp1 = 1.0_dp + (p*sin(pi*op)/x(j))**2
800 fp1(j) = malpha*tmp1*(h(j) - 1.0_dp - tmp) + (1.0_dp - malpha)*fp1(j)
801 IF (j <= n) err = err + abs(1.0_dp - fp1(j)/fprev) ! compute "errors"
802 END DO
803 err = err/n
804
805 ! Linear regression on the last 20% of the F_P function
806 CALL pint_qtb_linreg(fp1(8*nx/10:nx), x(8*nx/10:nx), aa, bb, r2, log_unit, print_level)
807
808 ! compute the new F_P(xk*sqrt(P))
809 ! through linear interpolation
810 ! or linear extrapolation if outside of the range
811 DO j = 1, nx
812 DO k = 1, p - 1
813 IF (kk(k, j) < nx) THEN
814 fpxk(k, j) = fp1(kk(k, j)) + (fp1(kk(k, j) + 1) - fp1(kk(k, j)))/dx* &
815 (xk(k, j) - x(kk(k, j)))
816 ELSE
817 fpxk(k, j) = aa*xk(k, j) + bb
818 END IF
819 END DO
820 END DO
821 END DO
822
823 IF (print_level == debug_print_level) THEN
824 ! **** tests ****
825 WRITE (log_unit, '(A,ES9.3)') ' # average error during computation: ', err
826 WRITE (log_unit, '(A,ES9.3)') ' # slope of F_P at high freq. - theoretical: ', op1
827 WRITE (log_unit, '(A,ES9.3)') ' # slope of F_P at high freq. - calculated: ', aa
828 ELSE IF (print_level > silent_print_level) THEN
829 CALL pint_write_line("QTB| Initialization of random forces using fP1 function")
830 CALL pint_write_line("QTB| Computation of fP1 function")
831 WRITE (line, '(A,ES9.3)') 'QTB| average error ', err
832 CALL pint_write_line(trim(line))
833 WRITE (line, '(A,ES9.3)') 'QTB| slope at high frequency - theoretical: ', op1
834 CALL pint_write_line(trim(line))
835 WRITE (line, '(A,ES9.3)') 'QTB| slope at high frequency - calculated: ', aa
836 CALL pint_write_line(trim(line))
837 END IF
838
839 IF (print_level == debug_print_level) THEN
840 ! **** write solution ****
841 WRITE (log_unit, '(A)') ' # ------------------------------------------------'
842 WRITE (log_unit, '(A)') ' # computed fp function'
843 WRITE (log_unit, '(A)') ' # i, w(a.u.), x, fp'
844 DO j = 1, nx
845 WRITE (log_unit, *) j, j*dw, xmin + (j - 1)*dx, fp1(j)
846 END DO
847 END IF
848
849 DEALLOCATE (x2)
850 DEALLOCATE (h)
851 DEALLOCATE (xk)
852 DEALLOCATE (xk2)
853 DEALLOCATE (kk)
854 DEALLOCATE (fpxk)
855 END IF
856
857 ! compute values of fP on the grid points for the current NM
858 ! trough linear interpolation / regression
859 DO j = 1, n
860 tmp = (j*dx1)**2 - (p*sin(pi*op))**2
861 IF (tmp < 0.d0) THEN
862 fp(j) = fp1(1)
863 ELSE
864 tmp = sqrt(tmp)
865 k = nint((tmp - xmin)/dx) + 1
866 IF (k > nx) THEN
867 fp(j) = aa*tmp + bb
868 ELSE IF (k <= 0) THEN
869 fp(j) = fp1(1)
870 ELSE
871 xx = xmin + (k - 1)*dx
872 IF (tmp > xx) THEN
873 fp(j) = fp1(k) + (fp1(k + 1) - fp1(k))/dx*(tmp - xx)
874 ELSE
875 fp(j) = fp1(k) + (fp1(k) - fp1(k - 1))/dx*(tmp - xx)
876 END IF
877 END IF
878 END IF
879 END DO
880
881 END IF
882
883 END SUBROUTINE pint_qtb_computefp1
884
885! ***************************************************************************
886!> \brief perform a simple linear regression - y(x) = a*x + b
887!> \param y ...
888!> \param x ...
889!> \param a ...
890!> \param b ...
891!> \param r2 ...
892!> \param log_unit ...
893!> \param print_level ...
894!> \author Fabien Brieuc
895! **************************************************************************************************
896 SUBROUTINE pint_qtb_linreg(y, x, a, b, r2, log_unit, print_level)
897 REAL(kind=dp), DIMENSION(:) :: y, x
898 REAL(kind=dp) :: a, b, r2
899 INTEGER :: log_unit, print_level
900
901 CHARACTER(len=200) :: line
902 INTEGER :: i, n
903 REAL(kind=dp) :: xav, xvar, xycov, yav, yvar
904
905 n = SIZE(y)
906
907 xav = 0.0_dp
908 yav = 0.0_dp
909 xycov = 0.0_dp
910 xvar = 0.0_dp
911 yvar = 0.0_dp
912
913 DO i = 1, n
914 xav = xav + x(i)
915 yav = yav + y(i)
916 xycov = xycov + x(i)*y(i)
917 xvar = xvar + x(i)**2
918 yvar = yvar + y(i)**2
919 END DO
920
921 xav = xav/n
922 yav = yav/n
923 xycov = xycov/n
924 xycov = xycov - xav*yav
925 xvar = xvar/n
926 xvar = xvar - xav**2
927 yvar = yvar/n
928 yvar = yvar - yav**2
929
930 a = xycov/xvar
931 b = yav - a*xav
932
933 r2 = xycov/sqrt(xvar*yvar)
934
935 IF (r2 < 0.9_dp) THEN
936 IF (print_level == debug_print_level) THEN
937 WRITE (log_unit, '(A, E10.3)') '# possible error during linear regression: r^2 = ', r2
938 ELSE IF (print_level > silent_print_level) THEN
939 WRITE (line, '(A,E10.3)') 'QTB| possible error during linear regression: r^2 = ', r2
940 CALL pint_write_line(trim(line))
941 END IF
942 END IF
943
944 END SUBROUTINE pint_qtb_linreg
945
946! **************************************************************************************************
947!> \brief ...
948!> \param z_in ...
949!> \param z_out ...
950!> \param n ...
951! **************************************************************************************************
952 SUBROUTINE pint_qtb_fft(z_in, z_out, n)
953
954 INTEGER :: n
955 COMPLEX(KIND=dp), DIMENSION(n) :: z_out, z_in
956
957 INTEGER :: stat
958
959 CALL fft_1d_many(fwfft, n, 1, .false., .false., n, n, z_in, z_out, 1.0_dp, stat)
960 END SUBROUTINE pint_qtb_fft
961
962END MODULE pint_qtb
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:323
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer, parameter, public debug_print_level
integer, parameter, public silent_print_level
subroutine, public fft_1d_many(sign, n, m, trans_in, trans_out, ldx_in, ldx_out, zin, zout, scale, stat)
Performs m 1-D forward FFT-s of size n.
Definition fft_tools.F:350
integer, parameter, public fwfft
Definition fft_tools.F:146
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public propagator_rpmd
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public twopi
Interface to the message passing library MPI.
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
type(rng_stream_type) function, public rng_stream_type_from_record(rng_record)
Create a RNG stream from a record given as an internal file (string).
integer, parameter, public rng_record_length
integer, parameter, public gaussian
I/O subroutines for pint_env.
Definition pint_io.F:13
subroutine, public pint_write_line(line)
Writes out a line of text to the default output unit.
Definition pint_io.F:76
Methods to apply the QTB thermostat to PI runs. Based on the PILE implementation from Felix Uhl (pint...
Definition pint_qtb.F:15
subroutine, public pint_qtb_step(vold, vnew, p, ndim, masses, qtb_therm)
...
Definition pint_qtb.F:152
subroutine, public pint_calc_qtb_energy(pint_env)
returns the qtb kinetic energy contribution
Definition pint_qtb.F:237
subroutine, public pint_qtb_release(qtb_therm)
releases the qtb environment
Definition pint_qtb.F:216
subroutine, public pint_qtb_init(qtb_therm, pint_env, normalmode_env, section)
initializes the data for a QTB run
Definition pint_qtb.F:66
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment
data to perform the normalmode transformation
Definition pint_types.F:165
environment for a path integral run
Definition pint_types.F:112
data to use the qtb thermostat
Definition pint_types.F:268