Branch data Line data Source code
1 : : !!****m* ABINIT/m_lattice_berendsen_NPT_mover
2 : : !! TODO: This is not yet implemented.
3 : : !! NAME
4 : : !! m_lattice_berendsen_NPT_mover
5 : : !!
6 : : !! FUNCTION
7 : : !! This module contains the berendsen (NPT) lattice mover.
8 : : !! The method is described in
9 : : !! H.J.C. Berendsen, J.P.M. Postma, A. DiNola, and J.R. Haak,
10 : : !! "Molecular dynamics with coupling to an external bath,"
11 : : !! J. Chem. Phys., 81 3684-3690 (1984)
12 : : !! NOTE: that this method does NOT generate properly the thermostated
13 : : !! ensemble. It does not have the correct distribution of the kinetic energy.
14 : : !! However, it approches the target temperature exponentially without oscillation,
15 : : !! for which the steps can be easily controlled.
16 : : !!
17 : : !! Datatypes:
18 : : !!
19 : : !! * lattice_berendsen_NPT_mover_t: defines the lattice movers
20 : : !!
21 : : !! Subroutines:
22 : : !! TODO: add this when F2003 doc style is determined.
23 : : !!
24 : : !!
25 : : !! COPYRIGHT
26 : : !! Copyright (C) 2001-2026 ABINIT group (hexu)
27 : : !! This file is distributed under the terms of the
28 : : !! GNU General Public License, see ~abinit/COPYING
29 : : !! or http://www.gnu.org/copyleft/gpl.txt .
30 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
31 : : !!
32 : : !! SOURCE
33 : :
34 : :
35 : :
36 : : #if defined HAVE_CONFIG_H
37 : : #include "config.h"
38 : : #endif
39 : :
40 : : #include "abi_common.h"
41 : :
42 : : module m_lattice_berendsen_NPT_mover
43 : : use defs_basis
44 : : use m_abicore
45 : : use m_errors
46 : :
47 : : use m_multibinit_dataset, only: multibinit_dtset_type
48 : : use m_abstract_potential, only: abstract_potential_t
49 : : use m_abstract_mover, only: abstract_mover_t
50 : : use m_lattice_mover, only: lattice_mover_t
51 : : use m_multibinit_cell, only: mbcell_t, mbsupercell_t
52 : : use m_random_xoroshiro128plus, only: rng_t
53 : : use m_hashtable_strval, only: hash_table_t
54 : : !!***
55 : :
56 : : implicit none
57 : :
58 : : private
59 : :
60 : : type, public, extends(lattice_mover_t) :: lattice_berendsen_NPT_mover_t
61 : : real(dp) :: taut ! the characteristic time of the relaxation of velocity.
62 : : ! it is usually larger than the time step.
63 : : real(dp) :: taup ! the characteristic time of the relaxation of pressure.
64 : : real(dp) :: compressibility
65 : : contains
66 : : procedure :: initialize
67 : : procedure :: finalize
68 : : procedure :: run_one_step
69 : : procedure :: scale_velocities
70 : : end type lattice_berendsen_NPT_mover_t
71 : :
72 : : contains
73 : :
74 : :
75 : :
76 : 0 : subroutine initialize(self,params, supercell, rng)
77 : : class(lattice_berendsen_NPT_mover_t), intent(inout) :: self
78 : : type(multibinit_dtset_type), target, intent(in):: params
79 : : type(mbsupercell_t), target, intent(in) :: supercell
80 : : type(rng_t), target, intent(in) :: rng
81 : 0 : self%taut = params%latt_taut
82 : : !self%taup = params%latt_taup
83 : : !self%compressibility =params%latt_compressibility
84 : 0 : call self%lattice_mover_t%initialize(params, supercell, rng)
85 : 0 : ABI_ERROR("The Berendsen NPT mover has not yet been implemented")
86 : : !TODO: Implement
87 : 0 : end subroutine initialize
88 : :
89 : :
90 : 0 : subroutine finalize(self)
91 : : class(lattice_berendsen_NPT_mover_t), intent(inout) :: self
92 : 0 : call self%lattice_mover_t%finalize()
93 : 0 : end subroutine finalize
94 : :
95 : :
96 : : !-------------------------------------------------------------------!
97 : : ! scale_velocities:
98 : : ! scale the velocities so that they get close to the required temperture
99 : : !
100 : : !-------------------------------------------------------------------!
101 : 0 : subroutine scale_velocities(self)
102 : : class(lattice_berendsen_NPT_mover_t), intent(inout) :: self
103 : : real(dp) :: tautscl, old_temperature, scale_temperature, tmp
104 : 0 : tautscl = self%dt / self%taut
105 : 0 : old_temperature=self%T_ob
106 : 0 : tmp=1.0 +(self%temperature / old_temperature - 1.0) * tautscl
107 [ # # ]: 0 : if(tmp< 0.0) then
108 : 0 : ABI_ERROR("The time scale for the Berendsen Algorithm should be at least larger than dtion.")
109 : : else
110 : 0 : scale_temperature=sqrt(tmp)
111 : : end if
112 : : ! Limit the velocity scaling to reasonable values
113 [ # # ]: 0 : if( scale_temperature > 1.1) then
114 : : scale_temperature = 1.1
115 : : elseif (scale_temperature < 0.9) then
116 : : scale_temperature = 0.9
117 : : endif
118 [ # # # # ]: 0 : self%current_vcart(:,:) = self%current_vcart(:,:) * scale_temperature
119 : 0 : end subroutine scale_velocities
120 : :
121 : :
122 : : !-------------------------------------------------------------------!
123 : : ! run_one_step.
124 : : ! The algorithm is almost the same as the velocity verlet algorithm,
125 : : ! except at the begining, the velocities are scaled so that the temperature
126 : : ! is getting closer to the required temperature.
127 : : !-------------------------------------------------------------------!
128 [ # # # # : 0 : subroutine run_one_step(self, effpot,displacement, strain, spin, lwf, energy_table)
# # # # #
# # # ]
129 : : class(lattice_berendsen_NPT_mover_t), intent(inout) :: self
130 : : class(abstract_potential_t), intent(inout) :: effpot
131 : : real(dp), optional, intent(inout) :: displacement(:,:), strain(:,:), spin(:,:), lwf(:)
132 : : type(hash_table_t), optional, intent(inout) :: energy_table
133 : : integer :: i
134 : : character(len=40) :: key
135 : :
136 : : ABI_UNUSED(displacement)
137 : : ABI_UNUSED(strain)
138 : :
139 : : ! scale the velocity.
140 : 0 : call self%scale_velocities()
141 : :
142 : 0 : self%energy=0.0
143 [ # # # # ]: 0 : self%forces(:,:) =0.0
144 : : call effpot%calculate( displacement=self%displacement, strain=self%strain, &
145 : : & spin=spin, lwf=lwf, force=self%forces, stress=self%stress, &
146 [ # # # # ]: 0 : & energy=self%energy, energy_table=energy_table)
147 [ # # ]: 0 : do i=1, self%natom
148 : : self%current_vcart(:,i) = self%current_vcart(:,i) + &
149 [ # # ]: 0 : & (0.5_dp * self%dt) * self%forces(:,i)/self%masses(i)
150 : : end do
151 : 0 : call self%force_stationary()
152 [ # # # # ]: 0 : self%displacement(:,:) = self%displacement(:,:)+self%current_vcart(:,:) * self%dt
153 : :
154 : :
155 : : ! second half of velocity update.
156 : : ! v(t+dt) = v(t + 1/2 dt) + F/m * 1/2 dt
157 : : ! NOTE: energy and forces should be initialized before every calculation!
158 : 0 : self%energy=0.0
159 [ # # # # ]: 0 : self%forces(:,:)=0.0
160 : : call effpot%calculate( displacement=self%displacement, &
161 : : & strain=self%strain, spin=spin, lwf=lwf, force=self%forces, &
162 [ # # # # ]: 0 : & stress=self%stress, energy=self%energy, energy_table=energy_table)
163 [ # # ]: 0 : do i=1, self%natom
164 : : self%current_vcart(:,i) = self%current_vcart(:,i) &
165 [ # # ]: 0 : & + (0.5_dp * self%dt) * self%forces(:,i)/self%masses(i)
166 : : end do
167 : 0 : call self%force_stationary()
168 : :
169 : 0 : call self%get_T_and_Ek()
170 [ # # ]: 0 : if (present(energy_table)) then
171 : 0 : key = 'Lattice kinetic energy'
172 : 0 : call energy_table%put(key, self%Ek)
173 : : end if
174 : :
175 : :
176 : 0 : end subroutine run_one_step
177 : :
178 [ # # # # : 0 : end module m_lattice_berendsen_NPT_mover
# # # # #
# # # ]
179 : :
|