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