ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/UseTheForce/DarkSide/eam.F90
Revision: 2722
Committed: Thu Apr 20 18:24:24 2006 UTC (18 years, 4 months ago) by gezelter
File size: 18835 byte(s)
Log Message:
Complete rewrite of spline code and everything that uses it.

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     use simulation
44     use force_globals
45     use status
46     use atype_module
47 chrisfen 2277 use vector_class
48 gezelter 2717 use interpolation
49 gezelter 1608 #ifdef IS_MPI
50     use mpiSimulation
51     #endif
52     implicit none
53     PRIVATE
54 chuckv 2355 #define __FORTRAN90
55     #include "UseTheForce/DarkSide/fInteractionMap.h"
56 gezelter 1608
57 chuckv 1624 INTEGER, PARAMETER :: DP = selected_real_kind(15)
58 gezelter 1608
59     logical, save :: EAM_FF_initialized = .false.
60     integer, save :: EAM_Mixing_Policy
61     real(kind = dp), save :: EAM_rcut
62     logical, save :: haveRcut = .false.
63    
64     character(len = statusMsgSize) :: errMesg
65     integer :: eam_err
66    
67     character(len = 200) :: errMsg
68     character(len=*), parameter :: RoutineName = "EAM MODULE"
69 gezelter 2204 !! Logical that determines if eam arrays should be zeroed
70 gezelter 1608 logical :: cleanme = .true.
71    
72     type, private :: EAMtype
73     integer :: eam_atype
74     real( kind = DP ) :: eam_lattice
75     real( kind = DP ) :: eam_rcut
76     integer :: eam_atype_map
77 gezelter 2717 type(cubicSpline) :: rho
78     type(cubicSpline) :: Z
79     type(cubicSpline) :: F
80     type(cubicSpline) :: phi
81 gezelter 1608 end type EAMtype
82    
83     !! Arrays for derivatives used in force calculation
84     real( kind = dp), dimension(:), allocatable :: frho
85     real( kind = dp), dimension(:), allocatable :: rho
86     real( kind = dp), dimension(:), allocatable :: dfrhodrho
87    
88 gezelter 2204 !! Arrays for MPI storage
89 gezelter 1608 #ifdef IS_MPI
90     real( kind = dp),save, dimension(:), allocatable :: dfrhodrho_col
91     real( kind = dp),save, dimension(:), allocatable :: dfrhodrho_row
92     real( kind = dp),save, dimension(:), allocatable :: frho_row
93     real( kind = dp),save, dimension(:), allocatable :: frho_col
94     real( kind = dp),save, dimension(:), allocatable :: rho_row
95     real( kind = dp),save, dimension(:), allocatable :: rho_col
96     real( kind = dp),save, dimension(:), allocatable :: rho_tmp
97     #endif
98    
99     type, private :: EAMTypeList
100     integer :: n_eam_types = 0
101     integer :: currentAddition = 0
102 gezelter 2204
103 gezelter 1608 type (EAMtype), pointer :: EAMParams(:) => null()
104 chuckv 2276 integer, pointer :: atidToEAMType(:) => null()
105 gezelter 1608 end type EAMTypeList
106    
107     type (eamTypeList), save :: EAMList
108    
109     !! standard eam stuff
110    
111    
112     public :: init_EAM_FF
113     public :: setCutoffEAM
114     public :: do_eam_pair
115     public :: newEAMtype
116     public :: calc_eam_prepair_rho
117     public :: calc_eam_preforce_Frho
118     public :: clean_EAM
119 chuckv 2169 public :: destroyEAMTypes
120 chrisfen 2277 public :: getEAMCut
121 gezelter 1608
122     contains
123    
124     subroutine newEAMtype(lattice_constant,eam_nrho,eam_drho,eam_nr,&
125 gezelter 2717 eam_dr,rcut,eam_Z_r,eam_rho_r,eam_F_rho, c_ident, status)
126 gezelter 1608 real (kind = dp ) :: lattice_constant
127     integer :: eam_nrho
128     real (kind = dp ) :: eam_drho
129     integer :: eam_nr
130     real (kind = dp ) :: eam_dr
131     real (kind = dp ) :: rcut
132 gezelter 2717 real (kind = dp ), dimension(eam_nr) :: eam_Z_r, rvals
133     real (kind = dp ), dimension(eam_nr) :: eam_rho_r, eam_phi_r
134     real (kind = dp ), dimension(eam_nrho) :: eam_F_rho, rhovals
135 chrisfen 2278 integer :: c_ident
136 gezelter 1608 integer :: status
137    
138 chuckv 2276 integer :: nAtypes,nEAMTypes,myATID
139 gezelter 1608 integer :: maxVals
140     integer :: alloc_stat
141 gezelter 2717 integer :: current, j
142 gezelter 1608 integer,pointer :: Matchlist(:) => null()
143    
144     status = 0
145    
146     !! Assume that atypes has already been set and get the total number of types in atypes
147     !! Also assume that every member of atypes is a EAM model.
148    
149     ! check to see if this is the first time into
150     if (.not.associated(EAMList%EAMParams)) then
151 chuckv 2276 call getMatchingElementList(atypes, "is_EAM", .true., nEAMtypes, MatchList)
152     EAMList%n_eam_types = nEAMtypes
153     allocate(EAMList%EAMParams(nEAMTypes))
154     nAtypes = getSize(atypes)
155     allocate(EAMList%atidToEAMType(nAtypes))
156 gezelter 1608 end if
157    
158     EAMList%currentAddition = EAMList%currentAddition + 1
159     current = EAMList%currentAddition
160    
161 chrisfen 2278 myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
162 chuckv 2276 EAMList%atidToEAMType(myATID) = current
163 gezelter 2204
164 chrisfen 2278 EAMList%EAMParams(current)%eam_atype = c_ident
165 gezelter 1608 EAMList%EAMParams(current)%eam_lattice = lattice_constant
166     EAMList%EAMParams(current)%eam_rcut = rcut
167    
168 gezelter 2717 ! Build array of r values
169     do j = 1, eam_nr
170     rvals(j) = real(j-1,kind=dp) * eam_dr
171     end do
172    
173     ! Build array of rho values
174     do j = 1, eam_nrho
175     rhovals(j) = real(j-1,kind=dp) * eam_drho
176     end do
177    
178     ! convert from eV to kcal / mol:
179     do j = 1, eam_nrho
180     eam_F_rho(j) = eam_F_rho(j) * 23.06054E0_DP
181     end do
182    
183     ! precompute the pair potential and get it into kcal / mol:
184     eam_phi_r(1) = 0.0E0_DP
185     do j = 2, eam_nr
186     eam_phi_r(j) = 331.999296E0_DP * (eam_Z_r(j)**2) / rvals(j)
187     enddo
188    
189 gezelter 2722 call newSpline(EAMList%EAMParams(current)%rho, rvals, eam_rho_r, .true.)
190     call newSpline(EAMList%EAMParams(current)%Z, rvals, eam_Z_r, .true.)
191     call newSpline(EAMList%EAMParams(current)%F, rhovals, eam_F_rho, .true.)
192     call newSpline(EAMList%EAMParams(current)%phi, rvals, eam_phi_r, .true.)
193 gezelter 1608 end subroutine newEAMtype
194    
195    
196 chuckv 2169 ! kills all eam types entered and sets simulation to uninitalized
197     subroutine destroyEAMtypes()
198     integer :: i
199     type(EAMType), pointer :: tempEAMType=>null()
200 gezelter 1608
201 chuckv 2169 do i = 1, EAMList%n_eam_types
202     tempEAMType => eamList%EAMParams(i)
203     call deallocate_EAMType(tempEAMType)
204     end do
205     if(associated( eamList%EAMParams)) deallocate( eamList%EAMParams)
206     eamList%EAMParams => null()
207 gezelter 2204
208 chuckv 2169 eamList%n_eam_types = 0
209     eamList%currentAddition = 0
210     end subroutine destroyEAMtypes
211    
212 chrisfen 2277 function getEAMCut(atomID) result(cutValue)
213     integer, intent(in) :: atomID
214 chrisfen 2278 integer :: eamID
215 chrisfen 2277 real(kind=dp) :: cutValue
216    
217 chrisfen 2278 eamID = EAMList%atidToEAMType(atomID)
218     cutValue = EAMList%EAMParams(eamID)%eam_rcut
219 chrisfen 2277 end function getEAMCut
220    
221 gezelter 1608 subroutine init_EAM_FF(status)
222     integer :: status
223     integer :: i,j
224     real(kind=dp) :: current_rcut_max
225 gezelter 2717 #ifdef IS_MPI
226     integer :: nAtomsInRow
227     integer :: nAtomsInCol
228     #endif
229 gezelter 1608 integer :: alloc_stat
230     integer :: number_r, number_rho
231    
232     status = 0
233     if (EAMList%currentAddition == 0) then
234     call handleError("init_EAM_FF","No members in EAMList")
235     status = -1
236     return
237     end if
238 gezelter 2717
239 gezelter 2204 !! Allocate arrays for force calculation
240 gezelter 2717
241 gezelter 1608 #ifdef IS_MPI
242     nAtomsInRow = getNatomsInRow(plan_atom_row)
243     nAtomsInCol = getNatomsInCol(plan_atom_col)
244     #endif
245    
246     if (allocated(frho)) deallocate(frho)
247     allocate(frho(nlocal),stat=alloc_stat)
248     if (alloc_stat /= 0) then
249     status = -1
250     return
251     end if
252 gezelter 2717
253 gezelter 1608 if (allocated(rho)) deallocate(rho)
254     allocate(rho(nlocal),stat=alloc_stat)
255     if (alloc_stat /= 0) then
256     status = -1
257     return
258     end if
259    
260     if (allocated(dfrhodrho)) deallocate(dfrhodrho)
261     allocate(dfrhodrho(nlocal),stat=alloc_stat)
262     if (alloc_stat /= 0) then
263     status = -1
264     return
265     end if
266    
267     #ifdef IS_MPI
268    
269     if (allocated(rho_tmp)) deallocate(rho_tmp)
270     allocate(rho_tmp(nlocal),stat=alloc_stat)
271     if (alloc_stat /= 0) then
272     status = -1
273     return
274     end if
275    
276     if (allocated(frho_row)) deallocate(frho_row)
277     allocate(frho_row(nAtomsInRow),stat=alloc_stat)
278     if (alloc_stat /= 0) then
279     status = -1
280     return
281     end if
282     if (allocated(rho_row)) deallocate(rho_row)
283     allocate(rho_row(nAtomsInRow),stat=alloc_stat)
284     if (alloc_stat /= 0) then
285     status = -1
286     return
287     end if
288     if (allocated(dfrhodrho_row)) deallocate(dfrhodrho_row)
289     allocate(dfrhodrho_row(nAtomsInRow),stat=alloc_stat)
290     if (alloc_stat /= 0) then
291     status = -1
292     return
293     end if
294    
295 gezelter 2204 ! Now do column arrays
296 gezelter 1608
297     if (allocated(frho_col)) deallocate(frho_col)
298     allocate(frho_col(nAtomsInCol),stat=alloc_stat)
299     if (alloc_stat /= 0) then
300     status = -1
301     return
302     end if
303     if (allocated(rho_col)) deallocate(rho_col)
304     allocate(rho_col(nAtomsInCol),stat=alloc_stat)
305     if (alloc_stat /= 0) then
306     status = -1
307     return
308     end if
309     if (allocated(dfrhodrho_col)) deallocate(dfrhodrho_col)
310     allocate(dfrhodrho_col(nAtomsInCol),stat=alloc_stat)
311     if (alloc_stat /= 0) then
312     status = -1
313     return
314     end if
315 gezelter 2204
316 gezelter 1608 #endif
317    
318 gezelter 2717 end subroutine init_EAM_FF
319 gezelter 1608
320 gezelter 2717 subroutine setCutoffEAM(rcut)
321 gezelter 1608 real(kind=dp) :: rcut
322     EAM_rcut = rcut
323     end subroutine setCutoffEAM
324    
325     subroutine clean_EAM()
326 gezelter 2204
327     ! clean non-IS_MPI first
328 gezelter 1608 frho = 0.0_dp
329     rho = 0.0_dp
330     dfrhodrho = 0.0_dp
331 gezelter 2204 ! clean MPI if needed
332 gezelter 1608 #ifdef IS_MPI
333     frho_row = 0.0_dp
334     frho_col = 0.0_dp
335     rho_row = 0.0_dp
336     rho_col = 0.0_dp
337     rho_tmp = 0.0_dp
338     dfrhodrho_row = 0.0_dp
339     dfrhodrho_col = 0.0_dp
340     #endif
341     end subroutine clean_EAM
342    
343     subroutine deallocate_EAMType(thisEAMType)
344     type (EAMtype), pointer :: thisEAMType
345    
346 gezelter 2717 call deleteSpline(thisEAMType%F)
347     call deleteSpline(thisEAMType%rho)
348     call deleteSpline(thisEAMType%phi)
349     call deleteSpline(thisEAMType%Z)
350 gezelter 2204
351 gezelter 1608 end subroutine deallocate_EAMType
352    
353 gezelter 2204 !! Calculates rho_r
354 gezelter 1608 subroutine calc_eam_prepair_rho(atom1,atom2,d,r,rijsq)
355 gezelter 2717 integer :: atom1, atom2
356 gezelter 1608 real(kind = dp), dimension(3) :: d
357     real(kind = dp), intent(inout) :: r
358     real(kind = dp), intent(inout) :: rijsq
359     ! value of electron density rho do to atom i at atom j
360     real(kind = dp) :: rho_i_at_j
361     ! value of electron density rho do to atom j at atom i
362     real(kind = dp) :: rho_j_at_i
363     integer :: eam_err
364 chuckv 2291
365 gezelter 2717 integer :: atid1, atid2 ! Global atid
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     #ifdef IS_MPI
372 chuckv 2291 Atid1 = Atid_row(Atom1)
373     Atid2 = Atid_col(Atom2)
374 gezelter 1608 #else
375 chuckv 2291 Atid1 = Atid(Atom1)
376     Atid2 = Atid(Atom2)
377 gezelter 1608 #endif
378    
379 chuckv 2291 Myid_atom1 = Eamlist%atidtoeamtype(Atid1)
380     Myid_atom2 = Eamlist%atidtoeamtype(Atid2)
381    
382 gezelter 1608 if (r.lt.EAMList%EAMParams(myid_atom1)%eam_rcut) then
383    
384 gezelter 2717 call lookupUniformSpline(EAMList%EAMParams(myid_atom1)%rho, r, &
385     rho_i_at_j)
386 gezelter 1608
387     #ifdef IS_MPI
388     rho_col(atom2) = rho_col(atom2) + rho_i_at_j
389     #else
390     rho(atom2) = rho(atom2) + rho_i_at_j
391     #endif
392 gezelter 2204 endif
393 gezelter 1608
394 gezelter 2204 if (r.lt.EAMList%EAMParams(myid_atom2)%eam_rcut) then
395 gezelter 1608
396 gezelter 2717 call lookupUniformSpline(EAMList%EAMParams(myid_atom2)%rho, r, &
397     rho_j_at_i)
398 gezelter 2204
399 gezelter 1608 #ifdef IS_MPI
400 gezelter 2204 rho_row(atom1) = rho_row(atom1) + rho_j_at_i
401 gezelter 1608 #else
402 gezelter 2204 rho(atom1) = rho(atom1) + rho_j_at_i
403 gezelter 1608 #endif
404 gezelter 2204 endif
405 gezelter 1608 end subroutine calc_eam_prepair_rho
406    
407    
408     !! Calculate the functional F(rho) for all local atoms
409 gezelter 2717 subroutine calc_eam_preforce_Frho(nlocal, pot)
410 gezelter 1608 integer :: nlocal
411     real(kind=dp) :: pot
412 gezelter 2717 integer :: i, j
413 gezelter 1608 integer :: atom
414 gezelter 2717 real(kind=dp) :: U,U1
415 gezelter 1608 integer :: atype1
416 gezelter 2717 integer :: me, atid1
417 gezelter 1608
418     cleanme = .true.
419 gezelter 2717 !! Scatter the electron density from pre-pair calculation back to
420     !! local atoms
421 gezelter 1608 #ifdef IS_MPI
422     call scatter(rho_row,rho,plan_atom_row,eam_err)
423     if (eam_err /= 0 ) then
424 gezelter 2204 write(errMsg,*) " Error scattering rho_row into rho"
425     call handleError(RoutineName,errMesg)
426     endif
427 gezelter 1608 call scatter(rho_col,rho_tmp,plan_atom_col,eam_err)
428     if (eam_err /= 0 ) then
429 gezelter 2204 write(errMsg,*) " Error scattering rho_col into rho"
430     call handleError(RoutineName,errMesg)
431     endif
432 gezelter 1608
433 gezelter 2204 rho(1:nlocal) = rho(1:nlocal) + rho_tmp(1:nlocal)
434 gezelter 1608 #endif
435    
436 gezelter 2204 !! Calculate F(rho) and derivative
437 gezelter 1608 do atom = 1, nlocal
438 chuckv 2291 atid1 = atid(atom)
439     me = eamList%atidToEAMtype(atid1)
440 gezelter 1608
441 gezelter 2717 call lookupUniformSpline1d(EAMList%EAMParams(me)%F, rho(atom), &
442     u, u1)
443    
444 gezelter 1608 frho(atom) = u
445     dfrhodrho(atom) = u1
446     pot = pot + u
447 gezelter 2722
448 gezelter 1608 enddo
449    
450     #ifdef IS_MPI
451     !! communicate f(rho) and derivatives back into row and column arrays
452     call gather(frho,frho_row,plan_atom_row, eam_err)
453     if (eam_err /= 0) then
454     call handleError("cal_eam_forces()","MPI gather frho_row failure")
455     endif
456     call gather(dfrhodrho,dfrhodrho_row,plan_atom_row, eam_err)
457     if (eam_err /= 0) then
458     call handleError("cal_eam_forces()","MPI gather dfrhodrho_row failure")
459     endif
460     call gather(frho,frho_col,plan_atom_col, eam_err)
461     if (eam_err /= 0) then
462     call handleError("cal_eam_forces()","MPI gather frho_col failure")
463     endif
464     call gather(dfrhodrho,dfrhodrho_col,plan_atom_col, eam_err)
465     if (eam_err /= 0) then
466     call handleError("cal_eam_forces()","MPI gather dfrhodrho_col failure")
467     endif
468     #endif
469    
470 gezelter 2204
471 gezelter 1608 end subroutine calc_eam_preforce_Frho
472 gezelter 2717
473 gezelter 1608 !! Does EAM pairwise Force calculation.
474     subroutine do_eam_pair(atom1, atom2, d, rij, r2, sw, vpair, fpair, &
475     pot, f, do_pot)
476     !Arguments
477     integer, intent(in) :: atom1, atom2
478     real( kind = dp ), intent(in) :: rij, r2
479     real( kind = dp ) :: pot, sw, vpair
480     real( kind = dp ), dimension(3,nLocal) :: f
481     real( kind = dp ), intent(in), dimension(3) :: d
482     real( kind = dp ), intent(inout), dimension(3) :: fpair
483    
484     logical, intent(in) :: do_pot
485 gezelter 2204
486 gezelter 2717 real( kind = dp ) :: drdx, drdy, drdz
487     real( kind = dp ) :: phab, pha, dvpdr
488     real( kind = dp ) :: rha, drha, dpha
489     real( kind = dp ) :: rhb, drhb, dphb
490 gezelter 1608 real( kind = dp ) :: dudr
491 gezelter 2717 real( kind = dp ) :: rci, rcj
492     real( kind = dp ) :: drhoidr, drhojdr
493     real( kind = dp ) :: Fx, Fy, Fz
494     real( kind = dp ) :: r, phb
495 gezelter 1608
496 gezelter 2717 integer :: id1, id2
497 gezelter 1608 integer :: mytype_atom1
498     integer :: mytype_atom2
499 gezelter 2717 integer :: atid1, atid2
500 gezelter 1608
501     phab = 0.0E0_DP
502     dvpdr = 0.0E0_DP
503    
504     if (rij .lt. EAM_rcut) then
505    
506     #ifdef IS_MPI
507 chuckv 2291 atid1 = atid_row(atom1)
508     atid2 = atid_col(atom2)
509 gezelter 1608 #else
510 chuckv 2291 atid1 = atid(atom1)
511     atid2 = atid(atom2)
512 gezelter 1608 #endif
513 chuckv 2291
514     mytype_atom1 = EAMList%atidToEAMType(atid1)
515     mytype_atom2 = EAMList%atidTOEAMType(atid2)
516    
517    
518 gezelter 1608 ! get cutoff for atom 1
519     rci = EAMList%EAMParams(mytype_atom1)%eam_rcut
520     ! get type specific cutoff for atom 2
521     rcj = EAMList%EAMParams(mytype_atom2)%eam_rcut
522 gezelter 2204
523 gezelter 1608 drdx = d(1)/rij
524     drdy = d(2)/rij
525     drdz = d(3)/rij
526 gezelter 2204
527 gezelter 1608 if (rij.lt.rci) then
528 gezelter 2717
529     ! Calculate rho and drho for atom1
530    
531     call lookupUniformSpline1d(EAMList%EAMParams(mytype_atom1)%rho, &
532     rij, rha, drha)
533    
534     ! Calculate Phi(r) for atom1.
535    
536     call lookupUniformSpline1d(EAMList%EAMParams(mytype_atom1)%phi, &
537     rij, pha, dpha)
538    
539 gezelter 1608 endif
540    
541     if (rij.lt.rcj) then
542 gezelter 2204
543 gezelter 2717 ! Calculate rho and drho for atom2
544    
545     call lookupUniformSpline1d(EAMList%EAMParams(mytype_atom2)%rho, &
546     rij, rhb, drhb)
547    
548     ! Calculate Phi(r) for atom2.
549    
550     call lookupUniformSpline1d(EAMList%EAMParams(mytype_atom2)%phi, &
551     rij, phb, dphb)
552    
553 gezelter 1608 endif
554    
555     if (rij.lt.rci) then
556     phab = phab + 0.5E0_DP*(rhb/rha)*pha
557     dvpdr = dvpdr + 0.5E0_DP*((rhb/rha)*dpha + &
558     pha*((drhb/rha) - (rhb*drha/rha/rha)))
559     endif
560 gezelter 2204
561 gezelter 1608 if (rij.lt.rcj) then
562     phab = phab + 0.5E0_DP*(rha/rhb)*phb
563     dvpdr = dvpdr + 0.5E0_DP*((rha/rhb)*dphb + &
564     phb*((drha/rhb) - (rha*drhb/rhb/rhb)))
565     endif
566 gezelter 2204
567 gezelter 1608 drhoidr = drha
568     drhojdr = drhb
569    
570     #ifdef IS_MPI
571     dudr = drhojdr*dfrhodrho_row(atom1)+drhoidr*dfrhodrho_col(atom2) &
572     + dvpdr
573    
574     #else
575     dudr = drhojdr*dfrhodrho(atom1)+drhoidr*dfrhodrho(atom2) &
576     + dvpdr
577     #endif
578    
579     fx = dudr * drdx
580     fy = dudr * drdy
581     fz = dudr * drdz
582    
583    
584     #ifdef IS_MPI
585     if (do_pot) then
586 gezelter 2361 pot_Row(METALLIC_POT,atom1) = pot_Row(METALLIC_POT,atom1) + phab*0.5
587     pot_Col(METALLIC_POT,atom2) = pot_Col(METALLIC_POT,atom2) + phab*0.5
588 gezelter 1608 end if
589    
590     f_Row(1,atom1) = f_Row(1,atom1) + fx
591     f_Row(2,atom1) = f_Row(2,atom1) + fy
592     f_Row(3,atom1) = f_Row(3,atom1) + fz
593 gezelter 2204
594 gezelter 1608 f_Col(1,atom2) = f_Col(1,atom2) - fx
595     f_Col(2,atom2) = f_Col(2,atom2) - fy
596     f_Col(3,atom2) = f_Col(3,atom2) - fz
597     #else
598    
599     if(do_pot) then
600     pot = pot + phab
601     end if
602    
603     f(1,atom1) = f(1,atom1) + fx
604     f(2,atom1) = f(2,atom1) + fy
605     f(3,atom1) = f(3,atom1) + fz
606 gezelter 2204
607 gezelter 1608 f(1,atom2) = f(1,atom2) - fx
608     f(2,atom2) = f(2,atom2) - fy
609     f(3,atom2) = f(3,atom2) - fz
610     #endif
611 gezelter 2204
612 gezelter 1608 vpair = vpair + phab
613 gezelter 2717
614 gezelter 1608 #ifdef IS_MPI
615     id1 = AtomRowToGlobal(atom1)
616     id2 = AtomColToGlobal(atom2)
617     #else
618     id1 = atom1
619     id2 = atom2
620     #endif
621 gezelter 2204
622 gezelter 1608 if (molMembershipList(id1) .ne. molMembershipList(id2)) then
623 gezelter 2204
624 gezelter 1608 fpair(1) = fpair(1) + fx
625     fpair(2) = fpair(2) + fy
626     fpair(3) = fpair(3) + fz
627 gezelter 2204
628 gezelter 1608 endif
629 gezelter 2204 endif
630 gezelter 1608 end subroutine do_eam_pair
631    
632     end module eam