ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/UseTheForce/DarkSide/eam.F90
Revision: 3559
Committed: Fri Oct 23 18:41:09 2009 UTC (15 years, 10 months ago) by gezelter
File size: 21096 byte(s)
Log Message:
removing MPI responsibilities from the lowest level force routines.  This is
in preparation for migrating these routines (LJ, electrostatic, eam, suttonchen,
gay-berne, sticky) to C++

File Contents

# User Rev Content
1 gezelter 1930 !!
2     !! Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     !!
4     !! The University of Notre Dame grants you ("Licensee") a
5     !! non-exclusive, royalty free, license to use, modify and
6     !! redistribute this software in source and binary code form, provided
7     !! that the following conditions are met:
8     !!
9     !! 1. Acknowledgement of the program authors must be made in any
10     !! publication of scientific results based in part on use of the
11     !! program. An acceptable form of acknowledgement is citation of
12     !! the article in which the program was described (Matthew
13     !! A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14     !! J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15     !! Parallel Simulation Engine for Molecular Dynamics,"
16     !! J. Comput. Chem. 26, pp. 252-271 (2005))
17     !!
18     !! 2. Redistributions of source code must retain the above copyright
19     !! notice, this list of conditions and the following disclaimer.
20     !!
21     !! 3. Redistributions in binary form must reproduce the above copyright
22     !! notice, this list of conditions and the following disclaimer in the
23     !! documentation and/or other materials provided with the
24     !! distribution.
25     !!
26     !! This software is provided "AS IS," without a warranty of any
27     !! kind. All express or implied conditions, representations and
28     !! warranties, including any implied warranty of merchantability,
29     !! fitness for a particular purpose or non-infringement, are hereby
30     !! excluded. The University of Notre Dame and its licensors shall not
31     !! be liable for any damages suffered by licensee as a result of
32     !! using, modifying or distributing the software or its
33     !! derivatives. In no event will the University of Notre Dame or its
34     !! licensors be liable for any lost revenue, profit or data, or for
35     !! direct, indirect, special, consequential, incidental or punitive
36     !! damages, however caused and regardless of the theory of liability,
37     !! arising out of the use of or inability to use software, even if the
38     !! University of Notre Dame has been advised of the possibility of
39     !! such damages.
40     !!
41    
42 gezelter 1608 module eam
43 gezelter 2756 use definitions
44 gezelter 1608 use simulation
45     use force_globals
46     use status
47     use atype_module
48 chrisfen 2277 use vector_class
49 gezelter 2717 use interpolation
50 gezelter 1608 #ifdef IS_MPI
51     use mpiSimulation
52     #endif
53     implicit none
54     PRIVATE
55 chuckv 2355 #define __FORTRAN90
56     #include "UseTheForce/DarkSide/fInteractionMap.h"
57 gezelter 1608
58     logical, save :: EAM_FF_initialized = .false.
59     integer, save :: EAM_Mixing_Policy
60     real(kind = dp), save :: EAM_rcut
61     logical, save :: haveRcut = .false.
62    
63     character(len = statusMsgSize) :: errMesg
64     integer :: eam_err
65    
66     character(len = 200) :: errMsg
67     character(len=*), parameter :: RoutineName = "EAM MODULE"
68 gezelter 2204 !! Logical that determines if eam arrays should be zeroed
69 gezelter 1608 logical :: cleanme = .true.
70    
71     type, private :: EAMtype
72     integer :: eam_atype
73     real( kind = DP ) :: eam_lattice
74     real( kind = DP ) :: eam_rcut
75     integer :: eam_atype_map
76 gezelter 2717 type(cubicSpline) :: rho
77     type(cubicSpline) :: Z
78     type(cubicSpline) :: F
79     type(cubicSpline) :: phi
80 gezelter 1608 end type EAMtype
81    
82     !! Arrays for derivatives used in force calculation
83     real( kind = dp), dimension(:), allocatable :: frho
84     real( kind = dp), dimension(:), allocatable :: rho
85     real( kind = dp), dimension(:), allocatable :: dfrhodrho
86    
87 gezelter 2204 !! Arrays for MPI storage
88 gezelter 1608 #ifdef IS_MPI
89     real( kind = dp),save, dimension(:), allocatable :: dfrhodrho_col
90     real( kind = dp),save, dimension(:), allocatable :: dfrhodrho_row
91     real( kind = dp),save, dimension(:), allocatable :: frho_row
92     real( kind = dp),save, dimension(:), allocatable :: frho_col
93     real( kind = dp),save, dimension(:), allocatable :: rho_row
94     real( kind = dp),save, dimension(:), allocatable :: rho_col
95     real( kind = dp),save, dimension(:), allocatable :: rho_tmp
96     #endif
97    
98     type, private :: EAMTypeList
99     integer :: n_eam_types = 0
100     integer :: currentAddition = 0
101 gezelter 2204
102 gezelter 1608 type (EAMtype), pointer :: EAMParams(:) => null()
103 chuckv 2276 integer, pointer :: atidToEAMType(:) => null()
104 gezelter 1608 end type EAMTypeList
105    
106     type (eamTypeList), save :: EAMList
107    
108     !! standard eam stuff
109    
110    
111     public :: init_EAM_FF
112     public :: setCutoffEAM
113     public :: do_eam_pair
114     public :: newEAMtype
115     public :: calc_eam_prepair_rho
116     public :: calc_eam_preforce_Frho
117     public :: clean_EAM
118 chuckv 2169 public :: destroyEAMTypes
119 chrisfen 2277 public :: getEAMCut
120 chrisfen 2728 public :: lookupEAMSpline
121     public :: lookupEAMSpline1d
122 gezelter 1608
123     contains
124    
125     subroutine newEAMtype(lattice_constant,eam_nrho,eam_drho,eam_nr,&
126 gezelter 2717 eam_dr,rcut,eam_Z_r,eam_rho_r,eam_F_rho, c_ident, status)
127 gezelter 1608 real (kind = dp ) :: lattice_constant
128     integer :: eam_nrho
129     real (kind = dp ) :: eam_drho
130     integer :: eam_nr
131     real (kind = dp ) :: eam_dr
132     real (kind = dp ) :: rcut
133 gezelter 2717 real (kind = dp ), dimension(eam_nr) :: eam_Z_r, rvals
134     real (kind = dp ), dimension(eam_nr) :: eam_rho_r, eam_phi_r
135     real (kind = dp ), dimension(eam_nrho) :: eam_F_rho, rhovals
136 chrisfen 2278 integer :: c_ident
137 gezelter 1608 integer :: status
138    
139 chuckv 2276 integer :: nAtypes,nEAMTypes,myATID
140 gezelter 1608 integer :: maxVals
141     integer :: alloc_stat
142 gezelter 2717 integer :: current, j
143 gezelter 1608 integer,pointer :: Matchlist(:) => null()
144    
145     status = 0
146    
147     !! Assume that atypes has already been set and get the total number of types in atypes
148     !! Also assume that every member of atypes is a EAM model.
149    
150     ! check to see if this is the first time into
151     if (.not.associated(EAMList%EAMParams)) then
152 chuckv 2276 call getMatchingElementList(atypes, "is_EAM", .true., nEAMtypes, MatchList)
153     EAMList%n_eam_types = nEAMtypes
154     allocate(EAMList%EAMParams(nEAMTypes))
155     nAtypes = getSize(atypes)
156     allocate(EAMList%atidToEAMType(nAtypes))
157 gezelter 1608 end if
158    
159     EAMList%currentAddition = EAMList%currentAddition + 1
160     current = EAMList%currentAddition
161    
162 chrisfen 2278 myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
163 chuckv 2276 EAMList%atidToEAMType(myATID) = current
164 gezelter 2204
165 chrisfen 2278 EAMList%EAMParams(current)%eam_atype = c_ident
166 gezelter 1608 EAMList%EAMParams(current)%eam_lattice = lattice_constant
167     EAMList%EAMParams(current)%eam_rcut = rcut
168    
169 gezelter 2717 ! Build array of r values
170     do j = 1, eam_nr
171     rvals(j) = real(j-1,kind=dp) * eam_dr
172     end do
173    
174     ! Build array of rho values
175     do j = 1, eam_nrho
176     rhovals(j) = real(j-1,kind=dp) * eam_drho
177     end do
178    
179     ! convert from eV to kcal / mol:
180     do j = 1, eam_nrho
181     eam_F_rho(j) = eam_F_rho(j) * 23.06054E0_DP
182     end do
183    
184     ! precompute the pair potential and get it into kcal / mol:
185     eam_phi_r(1) = 0.0E0_DP
186     do j = 2, eam_nr
187     eam_phi_r(j) = 331.999296E0_DP * (eam_Z_r(j)**2) / rvals(j)
188     enddo
189    
190 gezelter 2722 call newSpline(EAMList%EAMParams(current)%rho, rvals, eam_rho_r, .true.)
191     call newSpline(EAMList%EAMParams(current)%Z, rvals, eam_Z_r, .true.)
192     call newSpline(EAMList%EAMParams(current)%F, rhovals, eam_F_rho, .true.)
193     call newSpline(EAMList%EAMParams(current)%phi, rvals, eam_phi_r, .true.)
194 gezelter 1608 end subroutine newEAMtype
195    
196    
197 chuckv 2169 ! kills all eam types entered and sets simulation to uninitalized
198     subroutine destroyEAMtypes()
199     integer :: i
200     type(EAMType), pointer :: tempEAMType=>null()
201 gezelter 1608
202 chuckv 2169 do i = 1, EAMList%n_eam_types
203     tempEAMType => eamList%EAMParams(i)
204     call deallocate_EAMType(tempEAMType)
205     end do
206     if(associated( eamList%EAMParams)) deallocate( eamList%EAMParams)
207     eamList%EAMParams => null()
208 gezelter 2204
209 chuckv 2169 eamList%n_eam_types = 0
210     eamList%currentAddition = 0
211     end subroutine destroyEAMtypes
212    
213 chrisfen 2277 function getEAMCut(atomID) result(cutValue)
214     integer, intent(in) :: atomID
215 chrisfen 2278 integer :: eamID
216 chrisfen 2277 real(kind=dp) :: cutValue
217    
218 chrisfen 2278 eamID = EAMList%atidToEAMType(atomID)
219     cutValue = EAMList%EAMParams(eamID)%eam_rcut
220 chrisfen 2277 end function getEAMCut
221    
222 gezelter 1608 subroutine init_EAM_FF(status)
223     integer :: status
224     integer :: i,j
225     real(kind=dp) :: current_rcut_max
226 gezelter 2717 #ifdef IS_MPI
227     integer :: nAtomsInRow
228     integer :: nAtomsInCol
229     #endif
230 gezelter 1608 integer :: alloc_stat
231     integer :: number_r, number_rho
232    
233     status = 0
234     if (EAMList%currentAddition == 0) then
235     call handleError("init_EAM_FF","No members in EAMList")
236     status = -1
237     return
238     end if
239 gezelter 2717
240 gezelter 2204 !! Allocate arrays for force calculation
241 gezelter 2717
242 gezelter 1608 #ifdef IS_MPI
243     nAtomsInRow = getNatomsInRow(plan_atom_row)
244     nAtomsInCol = getNatomsInCol(plan_atom_col)
245     #endif
246    
247     if (allocated(frho)) deallocate(frho)
248     allocate(frho(nlocal),stat=alloc_stat)
249     if (alloc_stat /= 0) then
250     status = -1
251     return
252     end if
253 gezelter 2717
254 gezelter 1608 if (allocated(rho)) deallocate(rho)
255     allocate(rho(nlocal),stat=alloc_stat)
256     if (alloc_stat /= 0) then
257     status = -1
258     return
259     end if
260    
261     if (allocated(dfrhodrho)) deallocate(dfrhodrho)
262     allocate(dfrhodrho(nlocal),stat=alloc_stat)
263     if (alloc_stat /= 0) then
264     status = -1
265     return
266     end if
267    
268     #ifdef IS_MPI
269    
270     if (allocated(rho_tmp)) deallocate(rho_tmp)
271     allocate(rho_tmp(nlocal),stat=alloc_stat)
272     if (alloc_stat /= 0) then
273     status = -1
274     return
275     end if
276    
277     if (allocated(frho_row)) deallocate(frho_row)
278     allocate(frho_row(nAtomsInRow),stat=alloc_stat)
279     if (alloc_stat /= 0) then
280     status = -1
281     return
282     end if
283     if (allocated(rho_row)) deallocate(rho_row)
284     allocate(rho_row(nAtomsInRow),stat=alloc_stat)
285     if (alloc_stat /= 0) then
286     status = -1
287     return
288     end if
289     if (allocated(dfrhodrho_row)) deallocate(dfrhodrho_row)
290     allocate(dfrhodrho_row(nAtomsInRow),stat=alloc_stat)
291     if (alloc_stat /= 0) then
292     status = -1
293     return
294     end if
295    
296 gezelter 2204 ! Now do column arrays
297 gezelter 1608
298     if (allocated(frho_col)) deallocate(frho_col)
299     allocate(frho_col(nAtomsInCol),stat=alloc_stat)
300     if (alloc_stat /= 0) then
301     status = -1
302     return
303     end if
304     if (allocated(rho_col)) deallocate(rho_col)
305     allocate(rho_col(nAtomsInCol),stat=alloc_stat)
306     if (alloc_stat /= 0) then
307     status = -1
308     return
309     end if
310     if (allocated(dfrhodrho_col)) deallocate(dfrhodrho_col)
311     allocate(dfrhodrho_col(nAtomsInCol),stat=alloc_stat)
312     if (alloc_stat /= 0) then
313     status = -1
314     return
315     end if
316 gezelter 2204
317 gezelter 1608 #endif
318    
319 gezelter 2717 end subroutine init_EAM_FF
320 gezelter 1608
321 gezelter 2717 subroutine setCutoffEAM(rcut)
322 gezelter 1608 real(kind=dp) :: rcut
323     EAM_rcut = rcut
324     end subroutine setCutoffEAM
325    
326     subroutine clean_EAM()
327 gezelter 2204
328     ! clean non-IS_MPI first
329 gezelter 1608 frho = 0.0_dp
330     rho = 0.0_dp
331     dfrhodrho = 0.0_dp
332 gezelter 2204 ! clean MPI if needed
333 gezelter 1608 #ifdef IS_MPI
334     frho_row = 0.0_dp
335     frho_col = 0.0_dp
336     rho_row = 0.0_dp
337     rho_col = 0.0_dp
338     rho_tmp = 0.0_dp
339     dfrhodrho_row = 0.0_dp
340     dfrhodrho_col = 0.0_dp
341     #endif
342     end subroutine clean_EAM
343    
344     subroutine deallocate_EAMType(thisEAMType)
345     type (EAMtype), pointer :: thisEAMType
346    
347 gezelter 2717 call deleteSpline(thisEAMType%F)
348     call deleteSpline(thisEAMType%rho)
349     call deleteSpline(thisEAMType%phi)
350     call deleteSpline(thisEAMType%Z)
351 gezelter 2204
352 gezelter 1608 end subroutine deallocate_EAMType
353    
354 gezelter 2204 !! Calculates rho_r
355 gezelter 3559 subroutine calc_eam_prepair_rho(atom1,atom2,Atid1,Atid2,d,r,rijsq)
356     integer :: atom1, atom2, Atid1, Atid2
357 gezelter 1608 real(kind = dp), dimension(3) :: d
358     real(kind = dp), intent(inout) :: r
359     real(kind = dp), intent(inout) :: rijsq
360     ! value of electron density rho do to atom i at atom j
361     real(kind = dp) :: rho_i_at_j
362     ! value of electron density rho do to atom j at atom i
363     real(kind = dp) :: rho_j_at_i
364     integer :: eam_err
365 gezelter 3559
366 chuckv 2291 integer :: myid_atom1 ! EAM atid
367     integer :: myid_atom2
368 gezelter 2204
369     ! check to see if we need to be cleaned at the start of a force loop
370 gezelter 1608
371 chuckv 2291 Myid_atom1 = Eamlist%atidtoeamtype(Atid1)
372     Myid_atom2 = Eamlist%atidtoeamtype(Atid2)
373 gezelter 3559
374 gezelter 1608 if (r.lt.EAMList%EAMParams(myid_atom1)%eam_rcut) then
375 gezelter 3559
376 chrisfen 2728 call lookupEAMSpline(EAMList%EAMParams(myid_atom1)%rho, r, &
377 gezelter 2717 rho_i_at_j)
378 gezelter 1608
379     #ifdef IS_MPI
380     rho_col(atom2) = rho_col(atom2) + rho_i_at_j
381     #else
382     rho(atom2) = rho(atom2) + rho_i_at_j
383     #endif
384 gezelter 2204 endif
385 gezelter 1608
386 gezelter 2204 if (r.lt.EAMList%EAMParams(myid_atom2)%eam_rcut) then
387 gezelter 1608
388 chrisfen 2728 call lookupEAMSpline(EAMList%EAMParams(myid_atom2)%rho, r, &
389 gezelter 2717 rho_j_at_i)
390 gezelter 2204
391 gezelter 1608 #ifdef IS_MPI
392 gezelter 2204 rho_row(atom1) = rho_row(atom1) + rho_j_at_i
393 gezelter 1608 #else
394 gezelter 2204 rho(atom1) = rho(atom1) + rho_j_at_i
395 gezelter 1608 #endif
396 gezelter 2204 endif
397 gezelter 1608 end subroutine calc_eam_prepair_rho
398    
399    
400     !! Calculate the functional F(rho) for all local atoms
401 gezelter 3440 subroutine calc_eam_preforce_Frho(nlocal, pot, particle_pot)
402 gezelter 1608 integer :: nlocal
403     real(kind=dp) :: pot
404 gezelter 2717 integer :: i, j
405 gezelter 1608 integer :: atom
406 gezelter 2717 real(kind=dp) :: U,U1
407 gezelter 3440 real( kind = dp ), dimension(nlocal) :: particle_pot
408 gezelter 1608 integer :: atype1
409 gezelter 2717 integer :: me, atid1
410 gezelter 1608
411     cleanme = .true.
412 gezelter 2717 !! Scatter the electron density from pre-pair calculation back to
413     !! local atoms
414 gezelter 1608 #ifdef IS_MPI
415     call scatter(rho_row,rho,plan_atom_row,eam_err)
416     if (eam_err /= 0 ) then
417 gezelter 2204 write(errMsg,*) " Error scattering rho_row into rho"
418     call handleError(RoutineName,errMesg)
419     endif
420 gezelter 1608 call scatter(rho_col,rho_tmp,plan_atom_col,eam_err)
421     if (eam_err /= 0 ) then
422 gezelter 2204 write(errMsg,*) " Error scattering rho_col into rho"
423     call handleError(RoutineName,errMesg)
424     endif
425 gezelter 1608
426 gezelter 2204 rho(1:nlocal) = rho(1:nlocal) + rho_tmp(1:nlocal)
427 gezelter 1608 #endif
428    
429 gezelter 2204 !! Calculate F(rho) and derivative
430 gezelter 1608 do atom = 1, nlocal
431 chuckv 2291 atid1 = atid(atom)
432     me = eamList%atidToEAMtype(atid1)
433 gezelter 1608
434 chrisfen 2728 call lookupEAMSpline1d(EAMList%EAMParams(me)%F, rho(atom), &
435 gezelter 2717 u, u1)
436    
437 gezelter 1608 frho(atom) = u
438     dfrhodrho(atom) = u1
439     pot = pot + u
440 gezelter 3440 particle_pot(atom) = particle_pot(atom) + u
441 gezelter 2722
442 gezelter 1608 enddo
443    
444     #ifdef IS_MPI
445     !! communicate f(rho) and derivatives back into row and column arrays
446     call gather(frho,frho_row,plan_atom_row, eam_err)
447     if (eam_err /= 0) then
448     call handleError("cal_eam_forces()","MPI gather frho_row failure")
449     endif
450     call gather(dfrhodrho,dfrhodrho_row,plan_atom_row, eam_err)
451     if (eam_err /= 0) then
452     call handleError("cal_eam_forces()","MPI gather dfrhodrho_row failure")
453     endif
454     call gather(frho,frho_col,plan_atom_col, eam_err)
455     if (eam_err /= 0) then
456     call handleError("cal_eam_forces()","MPI gather frho_col failure")
457     endif
458     call gather(dfrhodrho,dfrhodrho_col,plan_atom_col, eam_err)
459     if (eam_err /= 0) then
460     call handleError("cal_eam_forces()","MPI gather dfrhodrho_col failure")
461     endif
462     #endif
463    
464 gezelter 2204
465 gezelter 1608 end subroutine calc_eam_preforce_Frho
466 gezelter 2717
467 gezelter 1608 !! Does EAM pairwise Force calculation.
468 gezelter 3559 subroutine do_eam_pair(atom1, atom2, atid1, atid2, d, rij, r2, sw, vpair, particle_pot, &
469     fpair, pot, f1, do_pot)
470 gezelter 1608 !Arguments
471 gezelter 3559 integer, intent(in) :: atom1, atom2, atid1, atid2
472 gezelter 1608 real( kind = dp ), intent(in) :: rij, r2
473     real( kind = dp ) :: pot, sw, vpair
474 gezelter 3466 real( kind = dp ), dimension(nLocal) :: particle_pot
475 gezelter 3559 real( kind = dp ), dimension(3) :: f1
476 gezelter 1608 real( kind = dp ), intent(in), dimension(3) :: d
477     real( kind = dp ), intent(inout), dimension(3) :: fpair
478    
479     logical, intent(in) :: do_pot
480 gezelter 2204
481 gezelter 2717 real( kind = dp ) :: drdx, drdy, drdz
482     real( kind = dp ) :: phab, pha, dvpdr
483     real( kind = dp ) :: rha, drha, dpha
484     real( kind = dp ) :: rhb, drhb, dphb
485 gezelter 1608 real( kind = dp ) :: dudr
486 gezelter 2717 real( kind = dp ) :: rci, rcj
487     real( kind = dp ) :: drhoidr, drhojdr
488     real( kind = dp ) :: Fx, Fy, Fz
489     real( kind = dp ) :: r, phb
490 gezelter 3466 real( kind = dp ) :: fshift1, fshift2, u1, u2
491 gezelter 1608
492 gezelter 2717 integer :: id1, id2
493 gezelter 1608 integer :: mytype_atom1
494     integer :: mytype_atom2
495    
496     phab = 0.0E0_DP
497     dvpdr = 0.0E0_DP
498    
499     if (rij .lt. EAM_rcut) then
500    
501 chuckv 2291 mytype_atom1 = EAMList%atidToEAMType(atid1)
502     mytype_atom2 = EAMList%atidTOEAMType(atid2)
503    
504    
505 gezelter 1608 ! get cutoff for atom 1
506     rci = EAMList%EAMParams(mytype_atom1)%eam_rcut
507     ! get type specific cutoff for atom 2
508     rcj = EAMList%EAMParams(mytype_atom2)%eam_rcut
509 gezelter 2204
510 gezelter 1608 drdx = d(1)/rij
511     drdy = d(2)/rij
512     drdz = d(3)/rij
513 gezelter 2204
514 gezelter 1608 if (rij.lt.rci) then
515 gezelter 2717
516     ! Calculate rho and drho for atom1
517    
518 chrisfen 2728 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%rho, &
519 gezelter 2717 rij, rha, drha)
520    
521     ! Calculate Phi(r) for atom1.
522    
523 chrisfen 2728 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%phi, &
524 gezelter 2717 rij, pha, dpha)
525    
526 gezelter 1608 endif
527    
528     if (rij.lt.rcj) then
529 gezelter 2204
530 gezelter 2717 ! Calculate rho and drho for atom2
531    
532 chrisfen 2728 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%rho, &
533 gezelter 2717 rij, rhb, drhb)
534    
535     ! Calculate Phi(r) for atom2.
536    
537 chrisfen 2728 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%phi, &
538 gezelter 2717 rij, phb, dphb)
539    
540 gezelter 1608 endif
541    
542     if (rij.lt.rci) then
543     phab = phab + 0.5E0_DP*(rhb/rha)*pha
544     dvpdr = dvpdr + 0.5E0_DP*((rhb/rha)*dpha + &
545     pha*((drhb/rha) - (rhb*drha/rha/rha)))
546     endif
547 gezelter 2204
548 gezelter 1608 if (rij.lt.rcj) then
549     phab = phab + 0.5E0_DP*(rha/rhb)*phb
550     dvpdr = dvpdr + 0.5E0_DP*((rha/rhb)*dphb + &
551     phb*((drha/rhb) - (rha*drhb/rhb/rhb)))
552     endif
553 gezelter 2204
554 gezelter 1608 drhoidr = drha
555     drhojdr = drhb
556    
557     #ifdef IS_MPI
558     dudr = drhojdr*dfrhodrho_row(atom1)+drhoidr*dfrhodrho_col(atom2) &
559     + dvpdr
560    
561     #else
562     dudr = drhojdr*dfrhodrho(atom1)+drhoidr*dfrhodrho(atom2) &
563     + dvpdr
564     #endif
565    
566     fx = dudr * drdx
567     fy = dudr * drdy
568     fz = dudr * drdz
569    
570    
571     #ifdef IS_MPI
572     if (do_pot) then
573 gezelter 3466 ! particle_pot is the difference between the full potential
574     ! and the full potential without the presence of a particular
575     ! particle (atom1).
576     !
577     ! This reduces the density at other particle locations, so
578     ! we need to recompute the density at atom2 assuming atom1
579     ! didn't contribute. This then requires recomputing the
580     ! density functional for atom2 as well.
581     !
582     ! Most of the particle_pot heavy lifting comes from the
583     ! pair interaction, and will be handled by vpair.
584    
585     call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%F, &
586     rho_row(atom1)-rhb, &
587     fshift1, u1)
588     call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%F, &
589     rho_col(atom2)-rha, &
590     fshift2, u2)
591    
592     ppot_Row(atom1) = ppot_Row(atom1) - frho_row(atom2) + fshift2
593     ppot_Col(atom2) = ppot_Col(atom2) - frho_col(atom1) + fshift1
594    
595 gezelter 1608 end if
596    
597     #else
598    
599     if(do_pot) then
600 gezelter 3466 ! particle_pot is the difference between the full potential
601     ! and the full potential without the presence of a particular
602     ! particle (atom1).
603     !
604     ! This reduces the density at other particle locations, so
605     ! we need to recompute the density at atom2 assuming atom1
606     ! didn't contribute. This then requires recomputing the
607     ! density functional for atom2 as well.
608     !
609     ! Most of the particle_pot heavy lifting comes from the
610     ! pair interaction, and will be handled by vpair.
611    
612     call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%F, &
613     rho(atom1)-rhb, &
614     fshift1, u1)
615     call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%F, &
616     rho(atom2)-rha, &
617     fshift2, u2)
618    
619     particle_pot(atom1) = particle_pot(atom1) - frho(atom2) + fshift2
620     particle_pot(atom2) = particle_pot(atom2) - frho(atom1) + fshift1
621    
622 gezelter 1608 end if
623    
624     #endif
625 gezelter 2204
626 gezelter 3559 pot = pot + phab
627 gezelter 2717
628 gezelter 3559 f1(1) = f1(1) + fx
629     f1(2) = f1(2) + fy
630     f1(3) = f1(3) + fz
631 gezelter 2204
632 gezelter 3559 vpair = vpair + phab
633 gezelter 2204
634     endif
635 gezelter 1608 end subroutine do_eam_pair
636    
637 chrisfen 2728 subroutine lookupEAMSpline(cs, xval, yval)
638    
639     implicit none
640    
641     type (cubicSpline), intent(in) :: cs
642     real( kind = DP ), intent(in) :: xval
643     real( kind = DP ), intent(out) :: yval
644     real( kind = DP ) :: dx
645     integer :: i, j
646     !
647     ! Find the interval J = [ cs%x(J), cs%x(J+1) ] that contains
648     ! or is nearest to xval.
649    
650 gezelter 2756 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
651 chrisfen 2728
652     dx = xval - cs%x(j)
653     yval = cs%y(j) + dx*(cs%b(j) + dx*(cs%c(j) + dx*cs%d(j)))
654    
655     return
656     end subroutine lookupEAMSpline
657    
658     subroutine lookupEAMSpline1d(cs, xval, yval, dydx)
659    
660     implicit none
661    
662     type (cubicSpline), intent(in) :: cs
663     real( kind = DP ), intent(in) :: xval
664     real( kind = DP ), intent(out) :: yval, dydx
665     real( kind = DP ) :: dx
666     integer :: i, j
667    
668     ! Find the interval J = [ cs%x(J), cs%x(J+1) ] that contains
669     ! or is nearest to xval.
670    
671    
672 gezelter 2756 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
673 chrisfen 2728
674     dx = xval - cs%x(j)
675     yval = cs%y(j) + dx*(cs%b(j) + dx*(cs%c(j) + dx*cs%d(j)))
676    
677     dydx = cs%b(j) + dx*(2.0d0 * cs%c(j) + 3.0d0 * dx * cs%d(j))
678    
679     return
680     end subroutine lookupEAMSpline1d
681    
682 gezelter 1608 end module eam