ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/calc_eam.F90
Revision: 492
Committed: Mon Apr 14 18:19:15 2003 UTC (21 years, 2 months ago) by chuckv
File size: 17049 byte(s)
Log Message:
Added first mangling of EAM.

File Contents

# Content
1 module calc_eam
2 use definitions, ONLY : DP
3 use force_globals
4 #ifdef MPI
5 use mpiSimulation
6 #endif
7
8
9
10
11 !! standard eam stuff
12 integer :: n_eam_atypes
13 integer, allocatable, dimension(:) :: eam_atype
14 real( kind = DP ), allocatable, dimension(:) :: eam_dr
15 integer, allocatable, dimension(:) :: eam_nr
16 integer, allocatable, dimension(:) :: eam_nrho
17 real( kind = DP ), allocatable, dimension(:) :: eam_lattice
18 real( kind = DP ), allocatable, dimension(:) :: eam_drho
19 integer , allocatable, dimension(:) :: eam_atype_map
20 real( kind = DP ), allocatable, dimension(:,:) :: eam_rvals
21 real( kind = DP ), allocatable, dimension(:,:) :: eam_rhovals
22 real( kind = DP ), allocatable, dimension(:) :: eam_rcut
23 real( kind = DP ), allocatable, dimension(:,:) :: eam_F_rho
24 real( kind = DP ), allocatable, dimension(:,:) :: eam_Z_r
25 real( kind = DP ), allocatable, dimension(:,:) :: eam_rho_r
26 real( kind = DP ), allocatable, dimension(:,:) :: eam_phi_r
27 real( kind = DP ), allocatable, dimension(:,:) :: eam_F_rho_pp
28 real( kind = DP ), allocatable, dimension(:,:) :: eam_Z_r_pp
29 real( kind = DP ), allocatable, dimension(:,:) :: eam_rho_r_pp
30 real( kind = DP ), allocatable, dimension(:,:) :: eam_phi_r_pp
31
32
33 real( kind = DP ), private :: time0,time1,time2,time3
34
35 integer, private :: eam_err
36
37 private :: mass_weight
38 private :: allocate_eam_atype,allocate_eam_module,deallocate_eam_module
39 private :: read_eam_pot, get_eam_sizes
40
41
42 contains
43 subroutine initialize_eam()
44
45
46
47 character(len=80) :: eam_pot_file
48 integer :: i, j, max_size, prev_max_size
49 integer :: number_rho, number_r
50 integer :: eam_unit
51 integer :: this_error
52 character(len=300) :: msg
53 integer, external :: nfiles
54 !for mpi
55
56
57 #ifdef MPI
58 if (node == 0) &
59 n_eam_atypes = nfiles(trim(eam_pot_dir)//char(0))
60
61 call mpi_bcast(n_eam_atypes,1,mpi_integer,0,mpi_comm_world,mpi_err)
62 if (n_eam_atypes == -1) then
63 call error("INITIALIZE_EAM","NO EAM potentials found!")
64 endif
65 write(msg,'(a5,i4,a12,i5,a14)') 'Node: ',node,' reading ...', &
66 n_eam_atypes, ' eam atom types'
67 call info('INITIALIZE_EAM', trim(msg))
68 #else
69 n_eam_atypes = nfiles(trim(eam_pot_dir)//char(0))
70 if (n_eam_atypes == -1) then
71 call error("INITIALIZE_EAM","NO EAM potentials found!")
72 endif
73
74 write(msg,'(a12,i5,a14)') ' Reading ...', &
75 n_eam_atypes, ' eam atom types'
76 call info('INITIALIZE_EAM', trim(msg))
77 #endif
78
79
80 call allocate_eam_atype(n_eam_atypes)
81
82
83
84 !! get largest number of data points for any potential
85 #ifdef MPI
86 if (node == 0) then
87 #endif
88 prev_max_size = 0
89 do i = 1, n_eam_atypes
90 call getfilename(i, eam_pot_file)
91 max_size = max(get_eam_sizes( &
92 trim(eam_pot_dir) // '/' // eam_pot_file), &
93 prev_max_size)
94 prev_max_size = max_size
95 end do
96 #ifdef MPI
97 end if
98
99
100 call mpi_bcast(max_size,1,mpi_integer,0,mpi_comm_world,mpi_err)
101 #endif
102
103 call allocate_eam_module(n_eam_atypes,max_size)
104 allocate(eam_atype_map(get_max_atype()))
105
106 #ifdef MPI
107 if (node == 0) then
108 #endif
109 do i = 1, n_eam_atypes
110 call getfilename(i, eam_pot_file)
111 call read_eam_pot(i,trim(eam_pot_dir) // '/' // eam_pot_file, &
112 this_error)
113
114 do j = 1, eam_nr(i)
115 eam_rvals(j,i) = dble(j-1)*eam_dr(i)
116 enddo
117
118 do j = 1, eam_nrho(i)
119 eam_rhovals(j,i) = dble(j-1)*eam_drho(i)
120 enddo
121
122 ! convert from eV to kcal / mol:
123 do j = 1, eam_nrho(i)
124 eam_F_rho(j,i) = eam_F_rho(j,i)*23.06054E0_DP
125 enddo
126
127 ! precompute the pair potential and get it into kcal / mol:
128 eam_phi_r(1,i) = 0.0E0_DP
129 do j = 2, eam_nr(i)
130 eam_phi_r(j,i) = (eam_Z_r(j,i)**2)/eam_rvals(j,i)
131 eam_phi_r(j,i) = eam_phi_r(j,i)*331.999296E0_DP
132 enddo
133
134 end do
135 #ifdef MPI
136 call info('INITIALIZE_EAM','NODE 0: Distributing spline arrays')
137 endif
138
139 call mpi_bcast(this_error,n_eam_atypes,mpi_integer,0, &
140 mpi_comm_world,mpi_err)
141 if (this_error /= 0) then
142 call error('INITIALIZE_EAM',"Cannot read eam files")
143 endif
144
145 call mpi_bcast(eam_atype,n_eam_atypes,mpi_integer,0, &
146 mpi_comm_world,mpi_err)
147
148 !! distribute values to cluster......
149 call mpi_bcast(eam_nr,n_eam_atypes,mpi_integer,&
150 0,mpi_comm_world,mpi_err)
151 call mpi_bcast(eam_nrho,n_eam_atypes,mpi_integer,&
152 0,mpi_comm_world,mpi_err)
153 call mpi_bcast(eam_rvals,n_eam_atypes*max_size,mpi_double_precision, &
154 0,mpi_comm_world,mpi_err)
155 call mpi_bcast(eam_rcut,n_eam_atypes,mpi_double_precision, &
156 0,mpi_comm_world,mpi_err)
157 call mpi_bcast(eam_rhovals,n_eam_atypes*max_size,mpi_double_precision, &
158 0,mpi_comm_world,mpi_err)
159
160 !! distribute arrays
161 call mpi_bcast(eam_rho_r,n_eam_atypes*max_size,mpi_double_precision, &
162 0,mpi_comm_world,mpi_err)
163 call mpi_bcast(eam_Z_r,n_eam_atypes*max_size,mpi_double_precision, &
164 0,mpi_comm_world,mpi_err)
165 call mpi_bcast(eam_F_rho,n_eam_atypes*max_size,mpi_double_precision, &
166 0,mpi_comm_world,mpi_err)
167 call mpi_bcast(eam_phi_r,n_eam_atypes*max_size,mpi_double_precision, &
168 0,mpi_comm_world,mpi_err)
169
170 #endif
171 call info('INITIALIZE_EAM', 'creating splines')
172
173 do i = 1, n_eam_atypes
174 number_r = eam_nr(i)
175 number_rho = eam_nrho(i)
176
177 call eam_spline(i, number_r, eam_rvals, eam_rho_r, eam_rho_r_pp, &
178 0.0E0_DP, 0.0E0_DP, 'N')
179 call eam_spline(i, number_r, eam_rvals, eam_Z_r, eam_Z_r_pp, &
180 0.0E0_DP, 0.0E0_DP, 'N')
181 call eam_spline(i, number_rho, eam_rhovals, eam_F_rho, eam_F_rho_pp, &
182 0.0E0_DP, 0.0E0_DP, 'N')
183 call eam_spline(i, number_r, eam_rvals, eam_phi_r, eam_phi_r_pp, &
184 0.0E0_DP, 0.0E0_DP, 'N')
185 enddo
186
187 do i = 1, n_eam_atypes
188 eam_atype_map(eam_atype(i)) = i
189 end do
190
191
192
193 call info('INITIALIZE_EAM','Done creating splines')
194
195 return
196 end subroutine initialize_eam
197
198
199 subroutine allocate_eam_atype(n_size_atype)
200 integer, intent(in) :: n_size_atype
201
202 allocate(eam_atype(n_size_atype))
203 allocate(eam_drho(n_size_atype))
204 allocate(eam_dr(n_size_atype))
205 allocate(eam_nr(n_size_atype))
206 allocate(eam_nrho(n_size_atype))
207 allocate(eam_lattice(n_size_atype))
208 allocate(eam_rcut(n_size_atype))
209
210 end subroutine allocate_eam_atype
211
212 subroutine allocate_eam_module(n_size_atype,n_eam_points)
213 integer, intent(in) :: n_eam_points
214 integer, intent(in) :: n_size_atype
215
216 allocate(eam_rvals(n_eam_points,n_size_atype))
217 allocate(eam_rhovals(n_eam_points,n_size_atype))
218 allocate(eam_F_rho(n_eam_points,n_size_atype))
219 allocate(eam_Z_r(n_eam_points,n_size_atype))
220 allocate(eam_rho_r(n_eam_points,n_size_atype))
221 allocate(eam_phi_r(n_eam_points,n_size_atype))
222 allocate(eam_F_rho_pp(n_eam_points,n_size_atype))
223 allocate(eam_Z_r_pp(n_eam_points,n_size_atype))
224 allocate(eam_rho_r_pp(n_eam_points,n_size_atype))
225 allocate(eam_phi_r_pp(n_eam_points,n_size_atype))
226
227 end subroutine allocate_eam_module
228
229 subroutine deallocate_eam_module()
230
231 deallocate(eam_atype)
232 deallocate(eam_drho)
233 deallocate(eam_dr)
234 deallocate(eam_nr)
235 deallocate(eam_nrho)
236 deallocate(eam_lattice)
237 deallocate(eam_atype_map)
238 deallocate(eam_rvals)
239 deallocate(eam_rhovals)
240 deallocate(eam_rcut)
241 deallocate(eam_Z_r)
242 deallocate(eam_rho_r)
243 deallocate(eam_phi_r)
244 deallocate(eam_F_rho_pp)
245 deallocate(eam_Z_r_pp)
246 deallocate(eam_rho_r_pp)
247 deallocate(eam_phi_r_pp)
248
249 end subroutine deallocate_eam_module
250
251
252 subroutine calc_eam_pair(atom1,atom2,d,rij,r2,pot,f,do_pot,do_stress)
253 !Arguments
254 integer, intent(in) :: atom1, atom2
255 real( kind = dp ), intent(in) :: rij, r2
256 real( kind = dp ) :: pot
257 real( kind = dp ), dimension(3,getNlocal()) :: f
258 real( kind = dp ), intent(in), dimension(3) :: d
259 logical, intent(in) :: do_pot, do_stress
260
261 !Local Variables
262
263
264 if (rij .lt. EAM_rcut) then
265
266 r = dsqrt(rijsq)
267 efr(1,j) = -rxij
268 efr(2,j) = -ryij
269 efr(3,j) = -rzij
270
271
272 call calc_eam_rho(r, rha, drha, d2rha, atype1)
273 call calc_eam_phi(r, pha, dpha, d2pha, atype1)
274 rci = eam_rcut(eam_atype_map(atype1))
275 #ifdef MPI
276 atype2 = ident_col(j)
277 #else
278 atype2 = ident(j)
279 #endif
280
281 call calc_eam_rho(r, rhb, drhb, d2rhb, atype2)
282 call calc_eam_phi(r, phb, dphb, d2phb, atype2)
283 rcj = eam_rcut(eam_atype_map(atype2))
284
285 phab = 0.0E0_DP
286 dvpdr = 0.0E0_DP
287 d2vpdrdr = 0.0E0_DP
288
289 if (r.lt.rci) then
290 phab = phab + 0.5E0_DP*(rhb/rha)*pha
291 dvpdr = dvpdr + 0.5E0_DP*((rhb/rha)*dpha + &
292 pha*((drhb/rha) - (rhb*drha/rha/rha)))
293 d2vpdrdr = d2vpdrdr + 0.5E0_DP*((rhb/rha)*d2pha + &
294 2.0E0_DP*dpha*((drhb/rha) - (rhb*drha/rha/rha)) + &
295 pha*((d2rhb/rha) - 2.0E0_DP*(drhb*drha/rha/rha) + &
296 (2.0E0_DP*rhb*drha*drha/rha/rha/rha) - (rhb*d2rha/rha/rha)))
297 endif
298
299
300 if (r.lt.rcj) then
301 phab = phab + 0.5E0_DP*(rha/rhb)*phb
302 dvpdr = dvpdr + 0.5E0_DP*((rha/rhb)*dphb + &
303 phb*((drha/rhb) - (rha*drhb/rhb/rhb)))
304 d2vpdrdr = d2vpdrdr + 0.5E0_DP*((rha/rhb)*d2phb + &
305 2.0E0_DP*dphb*((drha/rhb) - (rha*drhb/rhb/rhb)) + &
306 phb*((d2rha/rhb) - 2.0E0_DP*(drha*drhb/rhb/rhb) + &
307 (2.0E0_DP*rha*drhb*drhb/rhb/rhb/rhb) - (rha*d2rhb/rhb/rhb)))
308 endif
309
310
311 #ifdef MPI
312
313 e_row(i) = e_row(i) + phab*0.5
314 e_col(i) = e_col(i) + phab*0.5
315 #else
316 if (do_pot) pot = pot + phab
317 #endif
318
319 drhoidr = drha
320 drhojdr = drhb
321
322 d2rhoidrdr = d2rha
323 d2rhojdrdr = d2rhb
324 #ifdef MPI
325 dudr = drhojdr*dfrhodrho_row(i)+drhoidr*dfrhodrho_col(j) &
326 + dvpdr
327
328 if (nmflag) then
329 d2 = d2vpdrdr + &
330 d2rhoidrdr*dfrhodrho_col(j) + &
331 d2rhojdrdr*dfrhodrho_row(i) + &
332 drhoidr*drhoidr*d2frhodrhodrho_col(j) + &
333 drhojdr*drhojdr*d2frhodrhodrho_row(i)
334 endif
335 #else
336 dudr = drhojdr*dfrhodrho(i)+drhoidr*dfrhodrho(j) &
337 + dvpdr
338
339 d2 = d2vpdrdr + &
340 d2rhoidrdr*dfrhodrho(j) + &
341 d2rhojdrdr*dfrhodrho(i) + &
342 drhoidr*drhoidr*d2frhodrhodrho(j) + &
343 drhojdr*drhojdr*d2frhodrhodrho(i)
344 #endif
345
346
347 do dim = 1, 3
348
349 drdx1 = efr(dim,j) / r
350 ftmp = dudr * drdx1
351
352 #ifdef MPI
353 f_col(dim,j) = f_col(dim,j) - ftmp
354 f_row(dim,i) = f_row(dim,i) + ftmp
355 #else
356 f(dim,j) = f(dim,j) - ftmp
357 f(dim,i) = f(dim,i) + ftmp
358 #endif
359
360 if (nmflag) then
361 idim = 3 * (i-1) + dim
362 jdim = 3 * (j-1) + dim
363
364 do dim2 = 1, 3
365
366 kt1 = d2 * efr(dim,j) * efr(dim2,j)/r/r
367 kt2 = - dudr * efr(dim,j) * efr(dim2,j)/r/r/r
368
369 if (dim.eq.dim2) then
370 kt3 = dudr / r
371 else
372 kt3 = 0.0E0_DP
373 endif
374
375 ! The factor of 2 below is to compensate for
376 ! overcounting.
377 ! Mass weighting is done separately...
378
379 ktmp = (kt1+kt2+kt3)/2.0E0_DP
380 idim2 = 3 * (i-1) + dim2
381 jdim2 = 3 * (j-1) + dim2
382
383 d(idim, idim2) = d(idim,idim2) + ktmp
384 d(idim2, idim) = d(idim2,idim) + ktmp
385
386 d(idim, jdim2) = d(idim,jdim2) - ktmp
387 d(idim2, jdim) = d(idim2,jdim) - ktmp
388
389 d(jdim, idim2) = d(jdim,idim2) - ktmp
390 d(jdim2, idim) = d(jdim2,idim) - ktmp
391
392 d(jdim, jdim2) = d(jdim,jdim2) + ktmp
393 d(jdim2, jdim) = d(jdim2,jdim) + ktmp
394
395 enddo
396 endif
397 enddo
398
399 endif
400 enddo
401 endif
402
403 enddo
404
405
406
407
408 end subroutine calc_eam_pair
409
410 subroutine calc_eam_rho(r, rho, drho, d2rho, atype)
411
412 ! include 'headers/sizes.h'
413
414
415 integer atype, etype, number_r
416 real( kind = DP ) :: r, rho, drho, d2rho
417 integer :: i
418
419
420 etype = eam_atype_map(atype)
421
422 if (r.lt.eam_rcut(etype)) then
423 number_r = eam_nr(etype)
424 call eam_splint(etype, number_r, eam_rvals, eam_rho_r, &
425 eam_rho_r_pp, r, rho, drho, d2rho)
426 else
427 rho = 0.0E0_DP
428 drho = 0.0E0_DP
429 d2rho = 0.0E0_DP
430 endif
431
432 return
433 end subroutine calc_eam_rho
434
435 subroutine calc_eam_frho(dens, u, u1, u2, atype)
436
437 ! include 'headers/sizes.h'
438
439 integer atype, etype, number_rho
440 real( kind = DP ) :: dens, u, u1, u2
441 real( kind = DP ) :: rho_vals
442
443 etype = eam_atype_map(atype)
444 number_rho = eam_nrho(etype)
445 if (dens.lt.eam_rhovals(number_rho, etype)) then
446 call eam_splint(etype, number_rho, eam_rhovals, eam_f_rho, &
447 eam_f_rho_pp, dens, u, u1, u2)
448 else
449 rho_vals = eam_rhovals(number_rho,etype)
450 call eam_splint(etype, number_rho, eam_rhovals, eam_f_rho, &
451 eam_f_rho_pp, rho_vals, u, u1, u2)
452 endif
453
454 return
455 end subroutine calc_eam_frho
456
457 subroutine calc_eam_phi(r, phi, dphi, d2phi, atype)
458
459
460
461
462 integer atype, etype, number_r
463 real( kind = DP ) :: r, phi, dphi, d2phi
464
465 etype = eam_atype_map(atype)
466
467 if (r.lt.eam_rcut(etype)) then
468 number_r = eam_nr(etype)
469 call eam_splint(etype, number_r, eam_rvals, eam_phi_r, &
470 eam_phi_r_pp, r, phi, dphi, d2phi)
471 else
472 phi = 0.0E0_DP
473 dphi = 0.0E0_DP
474 d2phi = 0.0E0_DP
475 endif
476
477 return
478 end subroutine calc_eam_phi
479
480
481 subroutine eam_splint(atype, nx, xa, ya, yppa, x, y, dy, d2y)
482
483 ! include 'headers/sizes.h'
484
485 real( kind = DP ), dimension(:,:) :: xa
486 real( kind = DP ), dimension(:,:) :: ya
487 real( kind = DP ), dimension(:,:) :: yppa
488 real( kind = DP ) :: x, y, dy, d2y
489 real( kind = DP ) :: del, h, a, b, c, d
490
491
492 integer atype, nx, j
493
494
495 ! this spline code assumes that the x points are equally spaced
496 ! do not attempt to use this code if they are not.
497
498
499 ! find the closest point with a value below our own:
500 j = FLOOR(dble(nx-1) * (x - xa(1,atype)) / (xa(nx,atype) - xa(1,atype))) + 1
501
502 ! check to make sure we're inside the spline range:
503 if ((j.gt.nx).or.(j.lt.1)) call error('eam_splint', &
504 'x is outside bounds of spline')
505
506 ! check to make sure we haven't screwed up the calculation of j:
507 if ((x.lt.xa(j,atype)).or.(x.gt.xa(j+1,atype))) then
508 if (j.ne.nx) then
509 call error('eam_splint', &
510 'x is outside bounding range')
511 endif
512 endif
513
514 del = xa(j+1,atype) - x
515 h = xa(j+1,atype) - xa(j,atype)
516
517 a = del / h
518 b = 1.0E0_DP - a
519 c = a*(a*a - 1.0E0_DP)*h*h/6.0E0_DP
520 d = b*(b*b - 1.0E0_DP)*h*h/6.0E0_DP
521
522 y = a*ya(j,atype) + b*ya(j+1,atype) + c*yppa(j,atype) + d*yppa(j+1,atype)
523
524 dy = (ya(j+1,atype)-ya(j,atype))/h &
525 - (3.0E0_DP*a*a - 1.0E0_DP)*h*yppa(j,atype)/6.0E0_DP &
526 + (3.0E0_DP*b*b - 1.0E0_DP)*h*yppa(j+1,atype)/6.0E0_DP
527
528 d2y = a*yppa(j,atype) + b*yppa(j+1,atype)
529
530 return
531 end subroutine eam_splint
532
533 subroutine eam_spline(atype, nx, xa, ya, yppa, yp1, ypn, boundary)
534
535 ! include 'headers/sizes.h'
536
537
538 ! yp1 and ypn are the first derivatives of y at the two endpoints
539 ! if boundary is 'L' the lower derivative is used
540 ! if boundary is 'U' the upper derivative is used
541 ! if boundary is 'B' then both derivatives are used
542 ! if boundary is anything else, then both derivatives are assumed to be 0
543
544 integer nx, i, k, atype, max_array_size
545
546 real( kind = DP ), dimension(:,:) :: xa
547 real( kind = DP ), dimension(:,:) :: ya
548 real( kind = DP ), dimension(:,:) :: yppa
549 real( kind = DP ), allocatable, dimension(:) :: u
550 real( kind = DP ) :: yp1,ypn,un,qn,sig,p
551 character boundary
552
553 max_array_size = size(xa,1)
554 allocate(u(max_array_size))
555
556
557 if ((boundary.eq.'l').or.(boundary.eq.'L').or. &
558 (boundary.eq.'b').or.(boundary.eq.'B')) then
559 yppa(1, atype) = -0.5E0_DP
560 u(1) = (3.0E0_DP/(xa(2,atype)-xa(1,atype)))*((ya(2,atype)-&
561 ya(1,atype))/(xa(2,atype)-xa(1,atype))-yp1)
562 else
563 yppa(1,atype) = 0.0E0_DP
564 u(1) = 0.0E0_DP
565 endif
566
567 do i = 2, nx - 1
568 sig = (xa(i,atype) - xa(i-1,atype)) / (xa(i+1,atype) - xa(i-1,atype))
569 p = sig * yppa(i-1,atype) + 2.0E0_DP
570 yppa(i,atype) = (sig - 1.0E0_DP) / p
571 u(i) = (6.0E0_DP*((ya(i+1,atype)-ya(i,atype))/(xa(i+1,atype)-xa(i,atype)) - &
572 (ya(i,atype)-ya(i-1,atype))/(xa(i,atype)-xa(i-1,atype)))/ &
573 (xa(i+1,atype)-xa(i-1,atype)) - sig * u(i-1))/p
574 enddo
575
576 if ((boundary.eq.'u').or.(boundary.eq.'U').or. &
577 (boundary.eq.'b').or.(boundary.eq.'B')) then
578 qn = 0.5E0_DP
579 un = (3.0E0_DP/(xa(nx,atype)-xa(nx-1,atype)))* &
580 (ypn-(ya(nx,atype)-ya(nx-1,atype))/(xa(nx,atype)-xa(nx-1,atype)))
581 else
582 qn = 0.0E0_DP
583 un = 0.0E0_DP
584 endif
585
586 yppa(nx,atype)=(un-qn*u(nx-1))/(qn*yppa(nx-1,atype)+1.0E0_DP)
587
588 do k = nx-1, 1, -1
589 yppa(k,atype)=yppa(k,atype)*yppa(k+1,atype)+u(k)
590 enddo
591
592 deallocate(u)
593 return
594 end subroutine eam_spline
595
596
597
598
599 end module calc_eam