ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/UseTheForce/DarkSide/eam.F90
Revision: 1386
Committed: Fri Oct 23 18:41:09 2009 UTC (15 years, 9 months ago) by gezelter
Original Path: trunk/src/UseTheForce/DarkSide/eam.F90
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 246 !!
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 115 module eam
43 gezelter 960 use definitions
44 gezelter 115 use simulation
45     use force_globals
46     use status
47     use atype_module
48 chrisfen 578 use vector_class
49 gezelter 938 use interpolation
50 gezelter 115 #ifdef IS_MPI
51     use mpiSimulation
52     #endif
53     implicit none
54     PRIVATE
55 chuckv 656 #define __FORTRAN90
56     #include "UseTheForce/DarkSide/fInteractionMap.h"
57 gezelter 115
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 507 !! Logical that determines if eam arrays should be zeroed
69 gezelter 115 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 938 type(cubicSpline) :: rho
77     type(cubicSpline) :: Z
78     type(cubicSpline) :: F
79     type(cubicSpline) :: phi
80 gezelter 115 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 507 !! Arrays for MPI storage
88 gezelter 115 #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 507
102 gezelter 115 type (EAMtype), pointer :: EAMParams(:) => null()
103 chuckv 577 integer, pointer :: atidToEAMType(:) => null()
104 gezelter 115 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 472 public :: destroyEAMTypes
119 chrisfen 578 public :: getEAMCut
120 chrisfen 943 public :: lookupEAMSpline
121     public :: lookupEAMSpline1d
122 gezelter 115
123     contains
124    
125     subroutine newEAMtype(lattice_constant,eam_nrho,eam_drho,eam_nr,&
126 gezelter 938 eam_dr,rcut,eam_Z_r,eam_rho_r,eam_F_rho, c_ident, status)
127 gezelter 115 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 938 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 579 integer :: c_ident
137 gezelter 115 integer :: status
138    
139 chuckv 577 integer :: nAtypes,nEAMTypes,myATID
140 gezelter 115 integer :: maxVals
141     integer :: alloc_stat
142 gezelter 938 integer :: current, j
143 gezelter 115 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 577 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 115 end if
158    
159     EAMList%currentAddition = EAMList%currentAddition + 1
160     current = EAMList%currentAddition
161    
162 chrisfen 579 myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
163 chuckv 577 EAMList%atidToEAMType(myATID) = current
164 gezelter 507
165 chrisfen 579 EAMList%EAMParams(current)%eam_atype = c_ident
166 gezelter 115 EAMList%EAMParams(current)%eam_lattice = lattice_constant
167     EAMList%EAMParams(current)%eam_rcut = rcut
168    
169 gezelter 938 ! 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 939 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 115 end subroutine newEAMtype
195    
196    
197 chuckv 472 ! kills all eam types entered and sets simulation to uninitalized
198     subroutine destroyEAMtypes()
199     integer :: i
200     type(EAMType), pointer :: tempEAMType=>null()
201 gezelter 115
202 chuckv 472 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 507
209 chuckv 472 eamList%n_eam_types = 0
210     eamList%currentAddition = 0
211     end subroutine destroyEAMtypes
212    
213 chrisfen 578 function getEAMCut(atomID) result(cutValue)
214     integer, intent(in) :: atomID
215 chrisfen 579 integer :: eamID
216 chrisfen 578 real(kind=dp) :: cutValue
217    
218 chrisfen 579 eamID = EAMList%atidToEAMType(atomID)
219     cutValue = EAMList%EAMParams(eamID)%eam_rcut
220 chrisfen 578 end function getEAMCut
221    
222 gezelter 115 subroutine init_EAM_FF(status)
223     integer :: status
224     integer :: i,j
225     real(kind=dp) :: current_rcut_max
226 gezelter 938 #ifdef IS_MPI
227     integer :: nAtomsInRow
228     integer :: nAtomsInCol
229     #endif
230 gezelter 115 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 938
240 gezelter 507 !! Allocate arrays for force calculation
241 gezelter 938
242 gezelter 115 #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 938
254 gezelter 115 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 507 ! Now do column arrays
297 gezelter 115
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 507
317 gezelter 115 #endif
318    
319 gezelter 938 end subroutine init_EAM_FF
320 gezelter 115
321 gezelter 938 subroutine setCutoffEAM(rcut)
322 gezelter 115 real(kind=dp) :: rcut
323     EAM_rcut = rcut
324     end subroutine setCutoffEAM
325    
326     subroutine clean_EAM()
327 gezelter 507
328     ! clean non-IS_MPI first
329 gezelter 115 frho = 0.0_dp
330     rho = 0.0_dp
331     dfrhodrho = 0.0_dp
332 gezelter 507 ! clean MPI if needed
333 gezelter 115 #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 938 call deleteSpline(thisEAMType%F)
348     call deleteSpline(thisEAMType%rho)
349     call deleteSpline(thisEAMType%phi)
350     call deleteSpline(thisEAMType%Z)
351 gezelter 507
352 gezelter 115 end subroutine deallocate_EAMType
353    
354 gezelter 507 !! Calculates rho_r
355 gezelter 1386 subroutine calc_eam_prepair_rho(atom1,atom2,Atid1,Atid2,d,r,rijsq)
356     integer :: atom1, atom2, Atid1, Atid2
357 gezelter 115 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 1386
366 chuckv 592 integer :: myid_atom1 ! EAM atid
367     integer :: myid_atom2
368 gezelter 507
369     ! check to see if we need to be cleaned at the start of a force loop
370 gezelter 115
371 chuckv 592 Myid_atom1 = Eamlist%atidtoeamtype(Atid1)
372     Myid_atom2 = Eamlist%atidtoeamtype(Atid2)
373 gezelter 1386
374 gezelter 115 if (r.lt.EAMList%EAMParams(myid_atom1)%eam_rcut) then
375 gezelter 1386
376 chrisfen 943 call lookupEAMSpline(EAMList%EAMParams(myid_atom1)%rho, r, &
377 gezelter 938 rho_i_at_j)
378 gezelter 115
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 507 endif
385 gezelter 115
386 gezelter 507 if (r.lt.EAMList%EAMParams(myid_atom2)%eam_rcut) then
387 gezelter 115
388 chrisfen 943 call lookupEAMSpline(EAMList%EAMParams(myid_atom2)%rho, r, &
389 gezelter 938 rho_j_at_i)
390 gezelter 507
391 gezelter 115 #ifdef IS_MPI
392 gezelter 507 rho_row(atom1) = rho_row(atom1) + rho_j_at_i
393 gezelter 115 #else
394 gezelter 507 rho(atom1) = rho(atom1) + rho_j_at_i
395 gezelter 115 #endif
396 gezelter 507 endif
397 gezelter 115 end subroutine calc_eam_prepair_rho
398    
399    
400     !! Calculate the functional F(rho) for all local atoms
401 gezelter 1285 subroutine calc_eam_preforce_Frho(nlocal, pot, particle_pot)
402 gezelter 115 integer :: nlocal
403     real(kind=dp) :: pot
404 gezelter 938 integer :: i, j
405 gezelter 115 integer :: atom
406 gezelter 938 real(kind=dp) :: U,U1
407 gezelter 1285 real( kind = dp ), dimension(nlocal) :: particle_pot
408 gezelter 115 integer :: atype1
409 gezelter 938 integer :: me, atid1
410 gezelter 115
411     cleanme = .true.
412 gezelter 938 !! Scatter the electron density from pre-pair calculation back to
413     !! local atoms
414 gezelter 115 #ifdef IS_MPI
415     call scatter(rho_row,rho,plan_atom_row,eam_err)
416     if (eam_err /= 0 ) then
417 gezelter 507 write(errMsg,*) " Error scattering rho_row into rho"
418     call handleError(RoutineName,errMesg)
419     endif
420 gezelter 115 call scatter(rho_col,rho_tmp,plan_atom_col,eam_err)
421     if (eam_err /= 0 ) then
422 gezelter 507 write(errMsg,*) " Error scattering rho_col into rho"
423     call handleError(RoutineName,errMesg)
424     endif
425 gezelter 115
426 gezelter 507 rho(1:nlocal) = rho(1:nlocal) + rho_tmp(1:nlocal)
427 gezelter 115 #endif
428    
429 gezelter 507 !! Calculate F(rho) and derivative
430 gezelter 115 do atom = 1, nlocal
431 chuckv 592 atid1 = atid(atom)
432     me = eamList%atidToEAMtype(atid1)
433 gezelter 115
434 chrisfen 943 call lookupEAMSpline1d(EAMList%EAMParams(me)%F, rho(atom), &
435 gezelter 938 u, u1)
436    
437 gezelter 115 frho(atom) = u
438     dfrhodrho(atom) = u1
439     pot = pot + u
440 gezelter 1285 particle_pot(atom) = particle_pot(atom) + u
441 gezelter 939
442 gezelter 115 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 507
465 gezelter 115 end subroutine calc_eam_preforce_Frho
466 gezelter 938
467 gezelter 115 !! Does EAM pairwise Force calculation.
468 gezelter 1386 subroutine do_eam_pair(atom1, atom2, atid1, atid2, d, rij, r2, sw, vpair, particle_pot, &
469     fpair, pot, f1, do_pot)
470 gezelter 115 !Arguments
471 gezelter 1386 integer, intent(in) :: atom1, atom2, atid1, atid2
472 gezelter 115 real( kind = dp ), intent(in) :: rij, r2
473     real( kind = dp ) :: pot, sw, vpair
474 gezelter 1309 real( kind = dp ), dimension(nLocal) :: particle_pot
475 gezelter 1386 real( kind = dp ), dimension(3) :: f1
476 gezelter 115 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 507
481 gezelter 938 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 115 real( kind = dp ) :: dudr
486 gezelter 938 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 1309 real( kind = dp ) :: fshift1, fshift2, u1, u2
491 gezelter 115
492 gezelter 938 integer :: id1, id2
493 gezelter 115 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 592 mytype_atom1 = EAMList%atidToEAMType(atid1)
502     mytype_atom2 = EAMList%atidTOEAMType(atid2)
503    
504    
505 gezelter 115 ! 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 507
510 gezelter 115 drdx = d(1)/rij
511     drdy = d(2)/rij
512     drdz = d(3)/rij
513 gezelter 507
514 gezelter 115 if (rij.lt.rci) then
515 gezelter 938
516     ! Calculate rho and drho for atom1
517    
518 chrisfen 943 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%rho, &
519 gezelter 938 rij, rha, drha)
520    
521     ! Calculate Phi(r) for atom1.
522    
523 chrisfen 943 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom1)%phi, &
524 gezelter 938 rij, pha, dpha)
525    
526 gezelter 115 endif
527    
528     if (rij.lt.rcj) then
529 gezelter 507
530 gezelter 938 ! Calculate rho and drho for atom2
531    
532 chrisfen 943 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%rho, &
533 gezelter 938 rij, rhb, drhb)
534    
535     ! Calculate Phi(r) for atom2.
536    
537 chrisfen 943 call lookupEAMSpline1d(EAMList%EAMParams(mytype_atom2)%phi, &
538 gezelter 938 rij, phb, dphb)
539    
540 gezelter 115 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 507
548 gezelter 115 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 507
554 gezelter 115 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 1309 ! 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 115 end if
596    
597     #else
598    
599     if(do_pot) then
600 gezelter 1309 ! 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 115 end if
623    
624     #endif
625 gezelter 507
626 gezelter 1386 pot = pot + phab
627 gezelter 938
628 gezelter 1386 f1(1) = f1(1) + fx
629     f1(2) = f1(2) + fy
630     f1(3) = f1(3) + fz
631 gezelter 507
632 gezelter 1386 vpair = vpair + phab
633 gezelter 507
634     endif
635 gezelter 115 end subroutine do_eam_pair
636    
637 chrisfen 943 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 960 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
651 chrisfen 943
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 960 j = MAX(1, MIN(cs%n-1, int((xval-cs%x(1)) * cs%dx_i) + 1))
673 chrisfen 943
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 115 end module eam