ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/nano_mpi/src/dynamics_langevin_verlet.F90
Revision: 4
Committed: Mon Jun 10 17:18:36 2002 UTC (22 years, 1 month ago) by chuckv
File size: 10471 byte(s)
Log Message:
Import Root

File Contents

# User Rev Content
1 chuckv 4 !===========================================================================
2     !
3     !===========================================================================
4     ! . Subroutines:
5     ! LANGEVIN_VERLET_DYNAMICS molecular dynamics using langevin
6     ! dynamics
7     !===========================================================================
8    
9    
10     module dynamics_langevin_verlet
11     use definitions, ONLY : DP,NDIM
12     use constants, ONLY : AMU_TO_KG,K_BOLTZ,MS_TO_AFS, &
13     KCALMOL_TO_AMUA2FS2, PI
14     use simulation
15     use parameter
16     use force_module, ONLY : calc_forces
17     use second_deriv
18     use force_utilities, ONLY : check
19     use status
20     ! use velocity, ONLY : scale_velocities
21     use dynamics_utilities, ONLY : evolve_time, init_dynamics_loop, &
22     sim_status,DT2,DTSQRT,DTSQ2, init_status
23     use velocity, ONLY : calc_temp
24     #ifdef MPI
25     use mpi_module, ONLY : mpi_comm_world,mpi_err
26     #endif
27    
28     implicit none
29     PRIVATE
30     SAVE
31    
32     ! . Constants common to langevin dynamcics
33    
34     real ( kind = dp ) :: C0,C1,C2
35     real ( kind = dp ), allocatable, dimension(:) :: CRV1,CRV2
36     real ( kind = dp ), allocatable, dimension(:) :: FACR1,FACR2
37     real ( kind = dp ), allocatable, dimension(:) :: FACV1,FACV2,FACV3
38    
39     real ( kind = dp ), allocatable, dimension(:) :: SDR,SDV
40    
41    
42     ! . langevin arrays
43     real ( kind = dp ), allocatable, dimension(:,:) :: v_lang
44     real ( kind = dp ), allocatable, dimension(:) :: MASFAC
45    
46     type (sim_status) :: langevin_status
47    
48     public :: langevin_verlet_dynamics
49    
50    
51    
52    
53     contains
54    
55     ! . subroutine init_langevin sets up common
56     ! constants for dynamics
57     subroutine init_langevin
58     use model_module, ONLY : get_max_atype
59     integer :: n_atypes_known
60     character(len=80) :: msg
61     real( kind = dp ) :: fact
62     real( kind = dp ) :: this_eta
63     ! . allocate nlocal arrays
64     allocate(v_lang(ndim,nlocal))
65     allocate(masfac(nlocal))
66     ! . find out how many atypes the simulation
67     ! . knows about
68    
69     n_atypes_known = get_max_atype()
70     allocate(SDR(n_atypes_known))
71     allocate(SDV(n_atypes_known))
72     allocate(CRV1(n_atypes_known))
73     allocate(CRV2(n_atypes_known))
74     allocate(FACR1(n_atypes_known))
75     allocate(FACR2(n_atypes_known))
76     allocate(FACV1(n_atypes_known))
77     allocate(FACV2(n_atypes_known))
78     allocate(FACV3(n_atypes_known))
79    
80    
81     this_eta = eta
82     call calc_gamma_factors(this_eta)
83    
84     ! . Temperature and mass factors.
85     FACT = ( K_BOLTZ * bath_temp / AMU_TO_KG )
86     !!!!!DANGER DANGER WILL
87     ! WHERE ( .NOT. ATMFIX ) MASFAC = MS_TO_AFS * SQRT ( FACT / mass ) ! A fs^-1.
88     MASFAC = MS_TO_AFS * SQRT ( FACT / mass ) ! A fs^-1.
89    
90     write(msg,*) "Visocity of solvent is: ", eta
91     call info("INIT_LANGEVIN",msg)
92    
93    
94     end subroutine init_langevin
95    
96    
97     subroutine langevin_verlet_dynamics()
98     use langevin_cluster_list, ONLY : init_langevin_list,create_langevin_list
99    
100    
101     logical :: update_nlist
102     logical :: do_pot
103     logical :: not_done
104     logical :: nmflag
105    
106     integer :: step, i
107     real(kind = dp) :: temp
108     call init_status(langevin_status)
109     call init_dynamics_loop(langevin_status)
110     call init_langevin_list(nlocal)
111     ! Start the main simulation loop.
112    
113     do_pot = .true.
114     not_done = .true.
115     nmflag = .false.
116     step = 0
117     !. initialize constants for dynamics
118     call init_langevin()
119     call create_langevin_list()
120     dynamics: do
121     if (.not.not_done) exit dynamics
122    
123     step = step + 1
124    
125    
126     ! if (checktemp.and.(mod(step,check_temp_steps).eq.0)) then
127     ! call calc_temp(langevin_status%temp)
128     ! if (dabs(langevin_status%temp-target_temp).gt.therm_variance) then
129     ! call scale_velocities(target_temp)
130     ! end if
131     ! end if
132    
133    
134    
135     call check(update_nlist)
136     if (update_nlist) then
137     call create_langevin_list()
138     endif
139    
140     call langevina()
141    
142     ! . Add in random forces
143     call RANDOM_FORCES
144    
145     if (do_pot) then
146     call calc_forces(update_nlist,nmflag,pe = langevin_status%pot_e)
147     else
148     call calc_forces(update_nlist,nmflag)
149     endif
150    
151    
152     call langevinb()
153    
154     call evolve_time(step,langevin_status,do_pot,not_done)
155    
156    
157     #ifdef MPI
158     call mpi_barrier(mpi_comm_world,mpi_err)
159     #endif
160     end do dynamics
161    
162     deallocate(v_lang)
163     deallocate(masfac)
164     end subroutine langevin_verlet_dynamics
165    
166    
167     ! . First part of langevin dynamics
168     ! Advances positions from T to T + DT
169     ! Advances velocities from T to T + DT/2
170     !===================================
171     subroutine langevina()
172     !===================================
173     use langevin_cluster_list, ONLY : langevin_list
174     integer :: i
175     ! units for time are femtosec (10^-15 sec)
176     ! units for distance are angstroms (10^-10 m)
177     ! units for velocity are angstroms femtosec^-1
178     ! units for mass are a.m.u. (1.661 * 10^-27 kg)
179     ! units for force are kcal mol^-1 angstrom^-1
180     !
181     ! converter will put the final terms into angstroms.
182     ! or angstrom/femtosecond.
183    
184     ! Calculate new positions and velocities
185     v_lang = 0.0_DP
186    
187     do i = 1, nlocal
188     if (langevin_list(i)) then
189    
190     q(1:ndim,i) = q(1:ndim,i) + &
191     FACR1(ident(i)) * v(1:ndim,i) + &
192     (FACR2(ident(i)) * f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
193     v_lang(1:ndim,i) = FACV1(ident(i)) * v(1:ndim,i) + &
194     (FACV2(ident(i)) * f(1:ndim,i)/mass(i)) * KCALMOL_TO_AMUA2FS2
195    
196     else
197     q(1:ndim,i) = q(1:ndim,i) + dt*v(1:ndim,i) &
198     + (dtsq2*f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
199     v(1:ndim,i) = v(1:ndim,i) &
200     + (dt2*f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
201    
202     endif
203    
204    
205     end do
206    
207     end subroutine langevina
208    
209    
210     !========================
211     subroutine langevinb( )
212     !=========================
213     use langevin_cluster_list, ONLY : langevin_list
214     integer :: i
215     ! units for time are femtosec (10^-15 sec)
216     ! units for distance are angstroms (10^-10 m)
217     ! units for velocity are angstroms femtosec^-1
218     ! units for mass are a.m.u. (1.661 * 10^-27 kg)
219     ! units for force are kcal mol^-1 angstrom^-1
220    
221     do i = 1, nlocal
222     if (langevin_list(i)) then
223     v(1:ndim,i) = v_lang(1:ndim,i) &
224     + (FACV3(ident(i)) * f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
225     else ! standard movea
226     v(1:ndim,i) = v(1:ndim,i) &
227     + (dt2*f(1:ndim,i)/mass(i))*KCALMOL_TO_AMUA2FS2
228     endif
229     enddo
230    
231     end subroutine langevinb
232    
233    
234    
235     !-----------------------
236     SUBROUTINE RANDOM_FORCES
237     !-----------------------
238     use langevin_cluster_list, ONLY : langevin_list
239     use sprng_mod, ONLY : random_gauss
240     ! . Local scalars.
241     INTEGER :: I, IATOM
242     REAL ( KIND = DP ) :: RANR, RANV, R1, R2
243    
244     ! . Loop over the atoms.
245     DO IATOM = 1,nlocal
246    
247     ! . The atom is free.
248     IF ( langevin_list(iatom) ) THEN
249    
250     ! . Loop over the Cartesian components for the atom.
251     DO I = 1,ndim
252    
253     ! . Generate two Gaussian random numbers.
254     R1 = RANDOM_GAUSS ( )
255     R2 = RANDOM_GAUSS ( )
256    
257     ! . Calculate the position and velocity changes.
258     RANR = MASFAC(IATOM) * SDR(ident(iatom)) * R1
259     RANV = MASFAC(IATOM) * SDV(ident(iatom)) * &
260     ( CRV1(ident(iatom)) * R1 + CRV2(ident(iatom)) * R2 )
261    
262     ! . Add in the components.
263     q(I,IATOM) = q(I,IATOM) + RANR
264     v_lang(I,IATOM) = v_lang(I,IATOM) + RANV
265    
266     END DO
267     END IF
268     END DO
269    
270     END SUBROUTINE RANDOM_FORCES
271    
272     SUBROUTINE calc_gamma_factors(this_eta)
273     use model_module, ONLY : atype_mass,atype_identifier
274     integer :: atype, i
275     character(len = 80) :: msg
276     real( kind = dp ), intent(in) :: this_eta
277     real( kind = dp ) :: gamma
278     real( kind = dp ) :: FACT
279     real( kind = dp ) :: C0
280     real( kind = dp ) :: C1
281     real( kind = dp ) :: C2
282    
283    
284     do i = 1, n_atypes_present
285     gamma = 0.0_DP
286     fact = 0.0_DP
287     C0 = 0.0_DP
288     C1 = 0.0_DP
289     C2 = 0.0_DP
290    
291     atype = present_atypes(i)
292     !. calculate Gamma in fs^-1
293     !. gamma = (6 * pi * atom sigma(angstroms) * viscosity(poise) * 100cm/m) * 1fs/10^-15sec /
294     !. (atom mass(amu) * amu_to_kg * 1000g/kg)
295    
296     gamma = (6 * pi * get_langevin_sigma(atype) * this_eta ) / &
297     (atype_mass(atype)*amu_to_kg*10) * 1E-15_DP
298     write(msg,*) "Gamma for ",atype_identifier(atype), "is: ", gamma
299     call info("CALC_GAMMA_FACTORS",msg)
300    
301     FACT = dt * gamma
302    
303     C0 = EXP ( - FACT )
304     C1 = ( 1.0_DP - C0 ) / FACT
305     C2 = ( 1.0_DP - C1 ) / FACT
306    
307     ! . Random force constants.
308     SDR(atype) = SQRT ( dt * dt * &
309     ( 2.0_DP - ( 3.0_DP - 4.0_DP * C0 + C0 * C0 ) / FACT ) / FACT ) ! fs.
310     SDV(atype) = SQRT ( ( 1.0_DP - C0 * C0 ) ) ! Dimensionless.
311     CRV1(atype) = dt * ( 1.0_DP - C0 )**2 / ( FACT * SDR(atype) * SDV(atype) ) ! Dimensionless.
312     CRV2(atype) = SQRT ( 1.0_DP - CRV1(atype) * CRV1(atype) ) ! Dimensionless.
313    
314    
315     ! . Calculate some integration constants.
316     FACR1(atype) = C1 * dt ! fs.
317     FACR2(atype) = C2 * dt * dt ! fs^2.
318     FACV1(atype) = C0 ! Dimensionless.
319     FACV2(atype) = ( C1 - C2 ) * dt ! fs.
320     FACV3(atype) = C2 * dt ! fs.
321    
322     end do
323     END SUBROUTINE calc_gamma_factors
324    
325    
326     function get_langevin_sigma(this_atype) result(this_sigma)
327     integer, intent(in) :: this_atype
328     real( kind = dp ) :: this_sigma
329     include 'headers/atom.h'
330    
331     select case (this_atype)
332    
333     case(Au_atom)
334     this_sigma = 1.647E-10_DP
335     case(Ag_atom)
336     this_sigma = 1.574E-10_DP
337     case(Pt_atom)
338     this_sigma = 1.377E-10_DP
339     case(Pb_atom)
340     this_sigma = 2.148E-10_DP
341     case(Cu_atom)
342     this_sigma = 1.748E-10_DP
343     case(Ni_atom)
344     this_sigma = 1.417E-10_DP
345     case(Pd_atom)
346     this_sigma = 1.450E-10_DP
347     case default
348     call error("get_langevin_sigma","Unknown atom type")
349     end select
350     end function get_langevin_sigma
351     end module dynamics_langevin_verlet