ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/UseTheForce/DarkSide/electrostatic.F90
Revision: 2724
Committed: Fri Apr 21 03:19:52 2006 UTC (18 years, 4 months ago) by chrisfen
File size: 53991 byte(s)
Log Message:
Electrosplines added...

File Contents

# User Rev Content
1 gezelter 2095 !!
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     module electrostatic_module
43 gezelter 2204
44 gezelter 2095 use force_globals
45     use definitions
46     use atype_module
47     use vector_class
48     use simulation
49     use status
50 chrisfen 2715 use interpolation
51 gezelter 2095 #ifdef IS_MPI
52     use mpiSimulation
53     #endif
54     implicit none
55    
56     PRIVATE
57    
58 chuckv 2355
59 gezelter 2301 #define __FORTRAN90
60 chuckv 2355 #include "UseTheForce/DarkSide/fInteractionMap.h"
61 gezelter 2301 #include "UseTheForce/DarkSide/fElectrostaticSummationMethod.h"
62 chrisfen 2415 #include "UseTheForce/DarkSide/fElectrostaticScreeningMethod.h"
63 gezelter 2301
64 chuckv 2355
65 gezelter 2118 !! these prefactors convert the multipole interactions into kcal / mol
66     !! all were computed assuming distances are measured in angstroms
67     !! Charge-Charge, assuming charges are measured in electrons
68 gezelter 2717 real(kind=dp), parameter :: pre11 = 332.0637778d0
69 gezelter 2118 !! Charge-Dipole, assuming charges are measured in electrons, and
70     !! dipoles are measured in debyes
71 gezelter 2717 real(kind=dp), parameter :: pre12 = 69.13373d0
72 gezelter 2118 !! Dipole-Dipole, assuming dipoles are measured in debyes
73 gezelter 2717 real(kind=dp), parameter :: pre22 = 14.39325d0
74 gezelter 2118 !! Charge-Quadrupole, assuming charges are measured in electrons, and
75     !! quadrupoles are measured in 10^-26 esu cm^2
76     !! This unit is also known affectionately as an esu centi-barn.
77 gezelter 2717 real(kind=dp), parameter :: pre14 = 69.13373d0
78 gezelter 2095
79 gezelter 2722 real(kind=dp), parameter :: zero = 0.0d0
80 chrisfen 2724
81     !! number of points for electrostatic splines
82     integer, parameter :: np = 100
83 gezelter 2722
84 chrisfen 2411 !! variables to handle different summation methods for long-range
85     !! electrostatics:
86 gezelter 2301 integer, save :: summationMethod = NONE
87 chrisfen 2409 integer, save :: screeningMethod = UNDAMPED
88 chrisfen 2302 logical, save :: summationMethodChecked = .false.
89 gezelter 2301 real(kind=DP), save :: defaultCutoff = 0.0_DP
90 chrisfen 2381 real(kind=DP), save :: defaultCutoff2 = 0.0_DP
91 gezelter 2301 logical, save :: haveDefaultCutoff = .false.
92     real(kind=DP), save :: dampingAlpha = 0.0_DP
93 chrisfen 2415 real(kind=DP), save :: alpha2 = 0.0_DP
94 gezelter 2301 logical, save :: haveDampingAlpha = .false.
95 chrisfen 2381 real(kind=DP), save :: dielectric = 1.0_DP
96 gezelter 2301 logical, save :: haveDielectric = .false.
97     real(kind=DP), save :: constEXP = 0.0_DP
98 chrisfen 2381 real(kind=dp), save :: rcuti = 0.0_DP
99     real(kind=dp), save :: rcuti2 = 0.0_DP
100     real(kind=dp), save :: rcuti3 = 0.0_DP
101     real(kind=dp), save :: rcuti4 = 0.0_DP
102     real(kind=dp), save :: alphaPi = 0.0_DP
103     real(kind=dp), save :: invRootPi = 0.0_DP
104     real(kind=dp), save :: rrf = 1.0_DP
105     real(kind=dp), save :: rt = 1.0_DP
106     real(kind=dp), save :: rrfsq = 1.0_DP
107     real(kind=dp), save :: preRF = 0.0_DP
108 chrisfen 2394 real(kind=dp), save :: preRF2 = 0.0_DP
109 chrisfen 2415 real(kind=dp), save :: f0 = 1.0_DP
110     real(kind=dp), save :: f1 = 1.0_DP
111     real(kind=dp), save :: f2 = 0.0_DP
112 chrisfen 2548 real(kind=dp), save :: f3 = 0.0_DP
113     real(kind=dp), save :: f4 = 0.0_DP
114 chrisfen 2415 real(kind=dp), save :: f0c = 1.0_DP
115     real(kind=dp), save :: f1c = 1.0_DP
116     real(kind=dp), save :: f2c = 0.0_DP
117 chrisfen 2548 real(kind=dp), save :: f3c = 0.0_DP
118     real(kind=dp), save :: f4c = 0.0_DP
119 chrisfen 2724 real(kind=dp), save :: df0 = 0.0_DP
120     type(cubicSpline), save :: f0spline
121     logical, save :: haveElectroSpline = .false.
122 chrisfen 2415
123 chrisfen 2724
124 gezelter 2508 #if defined(__IFC) || defined(__PGI)
125 chuckv 2331 ! error function for ifc version > 7.
126 chuckv 2330 double precision, external :: derfc
127 chuckv 2331 #endif
128    
129 chrisfen 2552 public :: setElectrostaticSummationMethod
130 chrisfen 2409 public :: setScreeningMethod
131 gezelter 2301 public :: setElectrostaticCutoffRadius
132 chrisfen 2409 public :: setDampingAlpha
133 gezelter 2301 public :: setReactionFieldDielectric
134 chrisfen 2724 public :: buildElectroSpline
135 gezelter 2095 public :: newElectrostaticType
136     public :: setCharge
137     public :: setDipoleMoment
138     public :: setSplitDipoleDistance
139     public :: setQuadrupoleMoments
140     public :: doElectrostaticPair
141     public :: getCharge
142     public :: getDipoleMoment
143 chuckv 2189 public :: destroyElectrostaticTypes
144 chrisfen 2402 public :: self_self
145 chrisfen 2399 public :: rf_self_excludes
146 gezelter 2095
147 chrisfen 2715
148 gezelter 2095 type :: Electrostatic
149     integer :: c_ident
150     logical :: is_Charge = .false.
151     logical :: is_Dipole = .false.
152     logical :: is_SplitDipole = .false.
153     logical :: is_Quadrupole = .false.
154 chrisfen 2229 logical :: is_Tap = .false.
155 gezelter 2095 real(kind=DP) :: charge = 0.0_DP
156     real(kind=DP) :: dipole_moment = 0.0_DP
157     real(kind=DP) :: split_dipole_distance = 0.0_DP
158     real(kind=DP), dimension(3) :: quadrupole_moments = 0.0_DP
159     end type Electrostatic
160    
161     type(Electrostatic), dimension(:), allocatable :: ElectrostaticMap
162    
163 gezelter 2717 logical, save :: hasElectrostaticMap
164    
165 gezelter 2095 contains
166    
167 chrisfen 2552 subroutine setElectrostaticSummationMethod(the_ESM)
168 gezelter 2301 integer, intent(in) :: the_ESM
169    
170     if ((the_ESM .le. 0) .or. (the_ESM .gt. REACTION_FIELD)) then
171 chrisfen 2552 call handleError("setElectrostaticSummationMethod", "Unsupported Summation Method")
172 gezelter 2301 endif
173    
174 chrisfen 2309 summationMethod = the_ESM
175 chrisfen 2325
176 chrisfen 2552 end subroutine setElectrostaticSummationMethod
177 gezelter 2301
178 chrisfen 2409 subroutine setScreeningMethod(the_SM)
179     integer, intent(in) :: the_SM
180     screeningMethod = the_SM
181     end subroutine setScreeningMethod
182    
183 chrisfen 2381 subroutine setElectrostaticCutoffRadius(thisRcut, thisRsw)
184 gezelter 2301 real(kind=dp), intent(in) :: thisRcut
185 chrisfen 2381 real(kind=dp), intent(in) :: thisRsw
186 gezelter 2301 defaultCutoff = thisRcut
187 chrisfen 2548 defaultCutoff2 = defaultCutoff*defaultCutoff
188 chrisfen 2381 rrf = defaultCutoff
189     rt = thisRsw
190 gezelter 2301 haveDefaultCutoff = .true.
191     end subroutine setElectrostaticCutoffRadius
192    
193 chrisfen 2409 subroutine setDampingAlpha(thisAlpha)
194 gezelter 2301 real(kind=dp), intent(in) :: thisAlpha
195     dampingAlpha = thisAlpha
196 chrisfen 2415 alpha2 = dampingAlpha*dampingAlpha
197 gezelter 2301 haveDampingAlpha = .true.
198 chrisfen 2409 end subroutine setDampingAlpha
199 gezelter 2301
200     subroutine setReactionFieldDielectric(thisDielectric)
201     real(kind=dp), intent(in) :: thisDielectric
202     dielectric = thisDielectric
203     haveDielectric = .true.
204     end subroutine setReactionFieldDielectric
205    
206 chrisfen 2724 subroutine buildElectroSpline()
207     real( kind = dp ), dimension(np) :: xvals, yvals
208     real( kind = dp ) :: dx, rmin, rval
209     integer :: i
210 chrisfen 2715
211 chrisfen 2724 rmin = 0.0d0
212    
213     dx = (defaultCutoff-rmin) / dble(np-1)
214    
215     do i = 1, np
216     rval = rmin + dble(i-1)*dx
217     xvals(i) = rval
218     yvals(i) = derfc(dampingAlpha*rval)
219     enddo
220    
221     call newSpline(f0spline, xvals, yvals, .true.)
222    
223     haveElectroSpline = .true.
224     end subroutine buildElectroSpline
225    
226 gezelter 2095 subroutine newElectrostaticType(c_ident, is_Charge, is_Dipole, &
227 chrisfen 2229 is_SplitDipole, is_Quadrupole, is_Tap, status)
228 gezelter 2204
229 gezelter 2095 integer, intent(in) :: c_ident
230     logical, intent(in) :: is_Charge
231     logical, intent(in) :: is_Dipole
232     logical, intent(in) :: is_SplitDipole
233     logical, intent(in) :: is_Quadrupole
234 chrisfen 2229 logical, intent(in) :: is_Tap
235 gezelter 2095 integer, intent(out) :: status
236     integer :: nAtypes, myATID, i, j
237    
238     status = 0
239     myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
240 gezelter 2204
241 gezelter 2095 !! Be simple-minded and assume that we need an ElectrostaticMap that
242     !! is the same size as the total number of atom types
243    
244     if (.not.allocated(ElectrostaticMap)) then
245 gezelter 2204
246 gezelter 2095 nAtypes = getSize(atypes)
247 gezelter 2204
248 gezelter 2095 if (nAtypes == 0) then
249     status = -1
250     return
251     end if
252 gezelter 2204
253 gezelter 2717 allocate(ElectrostaticMap(nAtypes))
254 gezelter 2204
255 gezelter 2095 end if
256    
257     if (myATID .gt. size(ElectrostaticMap)) then
258     status = -1
259     return
260     endif
261 gezelter 2204
262 gezelter 2095 ! set the values for ElectrostaticMap for this atom type:
263    
264     ElectrostaticMap(myATID)%c_ident = c_ident
265     ElectrostaticMap(myATID)%is_Charge = is_Charge
266     ElectrostaticMap(myATID)%is_Dipole = is_Dipole
267     ElectrostaticMap(myATID)%is_SplitDipole = is_SplitDipole
268     ElectrostaticMap(myATID)%is_Quadrupole = is_Quadrupole
269 chrisfen 2229 ElectrostaticMap(myATID)%is_Tap = is_Tap
270 gezelter 2204
271 gezelter 2717 hasElectrostaticMap = .true.
272    
273 gezelter 2095 end subroutine newElectrostaticType
274    
275     subroutine setCharge(c_ident, charge, status)
276     integer, intent(in) :: c_ident
277     real(kind=dp), intent(in) :: charge
278     integer, intent(out) :: status
279     integer :: myATID
280    
281     status = 0
282     myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
283    
284 gezelter 2717 if (.not.hasElectrostaticMap) then
285 gezelter 2095 call handleError("electrostatic", "no ElectrostaticMap was present before first call of setCharge!")
286     status = -1
287     return
288     end if
289    
290     if (myATID .gt. size(ElectrostaticMap)) then
291     call handleError("electrostatic", "ElectrostaticMap was found to be too small during setCharge!")
292     status = -1
293     return
294     endif
295    
296     if (.not.ElectrostaticMap(myATID)%is_Charge) then
297     call handleError("electrostatic", "Attempt to setCharge of an atom type that is not a charge!")
298     status = -1
299     return
300 gezelter 2204 endif
301 gezelter 2095
302     ElectrostaticMap(myATID)%charge = charge
303     end subroutine setCharge
304    
305     subroutine setDipoleMoment(c_ident, dipole_moment, status)
306     integer, intent(in) :: c_ident
307     real(kind=dp), intent(in) :: dipole_moment
308     integer, intent(out) :: status
309     integer :: myATID
310    
311     status = 0
312     myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
313    
314 gezelter 2717 if (.not.hasElectrostaticMap) then
315 gezelter 2095 call handleError("electrostatic", "no ElectrostaticMap was present before first call of setDipoleMoment!")
316     status = -1
317     return
318     end if
319    
320     if (myATID .gt. size(ElectrostaticMap)) then
321     call handleError("electrostatic", "ElectrostaticMap was found to be too small during setDipoleMoment!")
322     status = -1
323     return
324     endif
325    
326     if (.not.ElectrostaticMap(myATID)%is_Dipole) then
327     call handleError("electrostatic", "Attempt to setDipoleMoment of an atom type that is not a dipole!")
328     status = -1
329     return
330     endif
331    
332     ElectrostaticMap(myATID)%dipole_moment = dipole_moment
333     end subroutine setDipoleMoment
334    
335     subroutine setSplitDipoleDistance(c_ident, split_dipole_distance, status)
336     integer, intent(in) :: c_ident
337     real(kind=dp), intent(in) :: split_dipole_distance
338     integer, intent(out) :: status
339     integer :: myATID
340    
341     status = 0
342     myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
343    
344 gezelter 2717 if (.not.hasElectrostaticMap) then
345 gezelter 2095 call handleError("electrostatic", "no ElectrostaticMap was present before first call of setSplitDipoleDistance!")
346     status = -1
347     return
348     end if
349    
350     if (myATID .gt. size(ElectrostaticMap)) then
351     call handleError("electrostatic", "ElectrostaticMap was found to be too small during setSplitDipoleDistance!")
352     status = -1
353     return
354     endif
355    
356     if (.not.ElectrostaticMap(myATID)%is_SplitDipole) then
357     call handleError("electrostatic", "Attempt to setSplitDipoleDistance of an atom type that is not a splitDipole!")
358     status = -1
359     return
360     endif
361    
362     ElectrostaticMap(myATID)%split_dipole_distance = split_dipole_distance
363     end subroutine setSplitDipoleDistance
364    
365     subroutine setQuadrupoleMoments(c_ident, quadrupole_moments, status)
366     integer, intent(in) :: c_ident
367     real(kind=dp), intent(in), dimension(3) :: quadrupole_moments
368     integer, intent(out) :: status
369     integer :: myATID, i, j
370    
371     status = 0
372     myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
373    
374 gezelter 2717 if (.not.hasElectrostaticMap) then
375 gezelter 2095 call handleError("electrostatic", "no ElectrostaticMap was present before first call of setQuadrupoleMoments!")
376     status = -1
377     return
378     end if
379    
380     if (myATID .gt. size(ElectrostaticMap)) then
381     call handleError("electrostatic", "ElectrostaticMap was found to be too small during setQuadrupoleMoments!")
382     status = -1
383     return
384     endif
385    
386     if (.not.ElectrostaticMap(myATID)%is_Quadrupole) then
387     call handleError("electrostatic", "Attempt to setQuadrupoleMoments of an atom type that is not a quadrupole!")
388     status = -1
389     return
390     endif
391 gezelter 2204
392 gezelter 2095 do i = 1, 3
393 gezelter 2204 ElectrostaticMap(myATID)%quadrupole_moments(i) = &
394     quadrupole_moments(i)
395     enddo
396 gezelter 2095
397     end subroutine setQuadrupoleMoments
398    
399 gezelter 2204
400 gezelter 2095 function getCharge(atid) result (c)
401     integer, intent(in) :: atid
402     integer :: localError
403     real(kind=dp) :: c
404 gezelter 2204
405 gezelter 2717 if (.not.hasElectrostaticMap) then
406 gezelter 2095 call handleError("electrostatic", "no ElectrostaticMap was present before first call of getCharge!")
407     return
408     end if
409 gezelter 2204
410 gezelter 2095 if (.not.ElectrostaticMap(atid)%is_Charge) then
411     call handleError("electrostatic", "getCharge was called for an atom type that isn't a charge!")
412     return
413     endif
414 gezelter 2204
415 gezelter 2095 c = ElectrostaticMap(atid)%charge
416     end function getCharge
417    
418     function getDipoleMoment(atid) result (dm)
419     integer, intent(in) :: atid
420     integer :: localError
421     real(kind=dp) :: dm
422 gezelter 2204
423 gezelter 2717 if (.not.hasElectrostaticMap) then
424 gezelter 2095 call handleError("electrostatic", "no ElectrostaticMap was present before first call of getDipoleMoment!")
425     return
426     end if
427 gezelter 2204
428 gezelter 2095 if (.not.ElectrostaticMap(atid)%is_Dipole) then
429     call handleError("electrostatic", "getDipoleMoment was called for an atom type that isn't a dipole!")
430     return
431     endif
432 gezelter 2204
433 gezelter 2095 dm = ElectrostaticMap(atid)%dipole_moment
434     end function getDipoleMoment
435    
436 gezelter 2301 subroutine checkSummationMethod()
437    
438 chrisfen 2306 if (.not.haveDefaultCutoff) then
439     call handleError("checkSummationMethod", "no Default Cutoff set!")
440     endif
441    
442     rcuti = 1.0d0 / defaultCutoff
443     rcuti2 = rcuti*rcuti
444     rcuti3 = rcuti2*rcuti
445     rcuti4 = rcuti2*rcuti2
446    
447 chrisfen 2409 if (screeningMethod .eq. DAMPED) then
448 chrisfen 2402 if (.not.haveDampingAlpha) then
449     call handleError("checkSummationMethod", "no Damping Alpha set!")
450     endif
451    
452     if (.not.haveDefaultCutoff) then
453     call handleError("checkSummationMethod", "no Default Cutoff set!")
454     endif
455 chrisfen 2302
456 chrisfen 2548 constEXP = exp(-alpha2*defaultCutoff2)
457 chrisfen 2402 invRootPi = 0.56418958354775628695d0
458 chrisfen 2415 alphaPi = 2.0d0*dampingAlpha*invRootPi
459     f0c = derfc(dampingAlpha*defaultCutoff)
460     f1c = alphaPi*defaultCutoff*constEXP + f0c
461 chrisfen 2548 f2c = alphaPi*2.0d0*alpha2*constEXP
462     f3c = alphaPi*2.0d0*alpha2*constEXP*defaultCutoff2*defaultCutoff
463 gezelter 2301 endif
464    
465 chrisfen 2302 if (summationMethod .eq. REACTION_FIELD) then
466 chrisfen 2402 if (haveDielectric) then
467     defaultCutoff2 = defaultCutoff*defaultCutoff
468     preRF = (dielectric-1.0d0) / &
469     ((2.0d0*dielectric+1.0d0)*defaultCutoff2*defaultCutoff)
470     preRF2 = 2.0d0*preRF
471     else
472     call handleError("checkSummationMethod", "Dielectric not set")
473 chrisfen 2302 endif
474 chrisfen 2402
475 chrisfen 2302 endif
476    
477 chrisfen 2724 if (.not.haveElectroSpline) then
478     call buildElectroSpline()
479     end if
480    
481 chrisfen 2302 summationMethodChecked = .true.
482 gezelter 2301 end subroutine checkSummationMethod
483    
484 chrisfen 2411
485 gezelter 2461 subroutine doElectrostaticPair(atom1, atom2, d, rij, r2, rcut, sw, &
486 chrisfen 2411 vpair, fpair, pot, eFrame, f, t, do_pot)
487 gezelter 2204
488 chrisfen 2402 logical, intent(in) :: do_pot
489 gezelter 2204
490 gezelter 2095 integer, intent(in) :: atom1, atom2
491     integer :: localError
492    
493 gezelter 2461 real(kind=dp), intent(in) :: rij, r2, sw, rcut
494 gezelter 2095 real(kind=dp), intent(in), dimension(3) :: d
495     real(kind=dp), intent(inout) :: vpair
496 chrisfen 2402 real(kind=dp), intent(inout), dimension(3) :: fpair
497 gezelter 2095
498 chrisfen 2325 real( kind = dp ) :: pot
499 gezelter 2095 real( kind = dp ), dimension(9,nLocal) :: eFrame
500     real( kind = dp ), dimension(3,nLocal) :: f
501 chrisfen 2409 real( kind = dp ), dimension(3,nLocal) :: felec
502 gezelter 2095 real( kind = dp ), dimension(3,nLocal) :: t
503 gezelter 2204
504 gezelter 2123 real (kind = dp), dimension(3) :: ux_i, uy_i, uz_i
505     real (kind = dp), dimension(3) :: ux_j, uy_j, uz_j
506     real (kind = dp), dimension(3) :: dudux_i, duduy_i, duduz_i
507     real (kind = dp), dimension(3) :: dudux_j, duduy_j, duduz_j
508 gezelter 2095
509     logical :: i_is_Charge, i_is_Dipole, i_is_SplitDipole, i_is_Quadrupole
510     logical :: j_is_Charge, j_is_Dipole, j_is_SplitDipole, j_is_Quadrupole
511 chrisfen 2229 logical :: i_is_Tap, j_is_Tap
512 gezelter 2095 integer :: me1, me2, id1, id2
513     real (kind=dp) :: q_i, q_j, mu_i, mu_j, d_i, d_j
514 gezelter 2123 real (kind=dp) :: qxx_i, qyy_i, qzz_i
515     real (kind=dp) :: qxx_j, qyy_j, qzz_j
516     real (kind=dp) :: cx_i, cy_i, cz_i
517     real (kind=dp) :: cx_j, cy_j, cz_j
518     real (kind=dp) :: cx2, cy2, cz2
519 chrisfen 2418 real (kind=dp) :: ct_i, ct_j, ct_ij, a0, a1
520 gezelter 2105 real (kind=dp) :: riji, ri, ri2, ri3, ri4
521 chrisfen 2296 real (kind=dp) :: pref, vterm, epot, dudr, vterm1, vterm2
522 gezelter 2105 real (kind=dp) :: xhat, yhat, zhat
523 gezelter 2095 real (kind=dp) :: dudx, dudy, dudz
524 chrisfen 2325 real (kind=dp) :: scale, sc2, bigR
525 chrisfen 2415 real (kind=dp) :: varEXP
526 chrisfen 2418 real (kind=dp) :: pot_term
527 chrisfen 2394 real (kind=dp) :: preVal, rfVal
528 chrisfen 2548 real (kind=dp) :: f13, f134
529 gezelter 2095
530 gezelter 2301 if (.not.summationMethodChecked) then
531     call checkSummationMethod()
532     endif
533    
534 gezelter 2095 #ifdef IS_MPI
535     me1 = atid_Row(atom1)
536     me2 = atid_Col(atom2)
537     #else
538     me1 = atid(atom1)
539     me2 = atid(atom2)
540     #endif
541    
542     !! some variables we'll need independent of electrostatic type:
543    
544     riji = 1.0d0 / rij
545 chrisfen 2343
546 gezelter 2105 xhat = d(1) * riji
547     yhat = d(2) * riji
548     zhat = d(3) * riji
549 gezelter 2095
550     !! logicals
551     i_is_Charge = ElectrostaticMap(me1)%is_Charge
552     i_is_Dipole = ElectrostaticMap(me1)%is_Dipole
553     i_is_SplitDipole = ElectrostaticMap(me1)%is_SplitDipole
554     i_is_Quadrupole = ElectrostaticMap(me1)%is_Quadrupole
555 chrisfen 2229 i_is_Tap = ElectrostaticMap(me1)%is_Tap
556 gezelter 2095
557     j_is_Charge = ElectrostaticMap(me2)%is_Charge
558     j_is_Dipole = ElectrostaticMap(me2)%is_Dipole
559     j_is_SplitDipole = ElectrostaticMap(me2)%is_SplitDipole
560     j_is_Quadrupole = ElectrostaticMap(me2)%is_Quadrupole
561 chrisfen 2229 j_is_Tap = ElectrostaticMap(me2)%is_Tap
562 gezelter 2095
563     if (i_is_Charge) then
564     q_i = ElectrostaticMap(me1)%charge
565     endif
566 gezelter 2204
567 gezelter 2095 if (i_is_Dipole) then
568     mu_i = ElectrostaticMap(me1)%dipole_moment
569     #ifdef IS_MPI
570 gezelter 2123 uz_i(1) = eFrame_Row(3,atom1)
571     uz_i(2) = eFrame_Row(6,atom1)
572     uz_i(3) = eFrame_Row(9,atom1)
573 gezelter 2095 #else
574 gezelter 2123 uz_i(1) = eFrame(3,atom1)
575     uz_i(2) = eFrame(6,atom1)
576     uz_i(3) = eFrame(9,atom1)
577 gezelter 2095 #endif
578 gezelter 2123 ct_i = uz_i(1)*xhat + uz_i(2)*yhat + uz_i(3)*zhat
579 gezelter 2095
580     if (i_is_SplitDipole) then
581     d_i = ElectrostaticMap(me1)%split_dipole_distance
582     endif
583 gezelter 2722 duduz_i = zero
584 gezelter 2095 endif
585    
586 gezelter 2123 if (i_is_Quadrupole) then
587     qxx_i = ElectrostaticMap(me1)%quadrupole_moments(1)
588     qyy_i = ElectrostaticMap(me1)%quadrupole_moments(2)
589     qzz_i = ElectrostaticMap(me1)%quadrupole_moments(3)
590     #ifdef IS_MPI
591     ux_i(1) = eFrame_Row(1,atom1)
592     ux_i(2) = eFrame_Row(4,atom1)
593     ux_i(3) = eFrame_Row(7,atom1)
594     uy_i(1) = eFrame_Row(2,atom1)
595     uy_i(2) = eFrame_Row(5,atom1)
596     uy_i(3) = eFrame_Row(8,atom1)
597     uz_i(1) = eFrame_Row(3,atom1)
598     uz_i(2) = eFrame_Row(6,atom1)
599     uz_i(3) = eFrame_Row(9,atom1)
600     #else
601     ux_i(1) = eFrame(1,atom1)
602     ux_i(2) = eFrame(4,atom1)
603     ux_i(3) = eFrame(7,atom1)
604     uy_i(1) = eFrame(2,atom1)
605     uy_i(2) = eFrame(5,atom1)
606     uy_i(3) = eFrame(8,atom1)
607     uz_i(1) = eFrame(3,atom1)
608     uz_i(2) = eFrame(6,atom1)
609     uz_i(3) = eFrame(9,atom1)
610     #endif
611     cx_i = ux_i(1)*xhat + ux_i(2)*yhat + ux_i(3)*zhat
612     cy_i = uy_i(1)*xhat + uy_i(2)*yhat + uy_i(3)*zhat
613     cz_i = uz_i(1)*xhat + uz_i(2)*yhat + uz_i(3)*zhat
614 gezelter 2722 dudux_i = zero
615     duduy_i = zero
616     duduz_i = zero
617 gezelter 2123 endif
618    
619 gezelter 2095 if (j_is_Charge) then
620     q_j = ElectrostaticMap(me2)%charge
621     endif
622 gezelter 2204
623 gezelter 2095 if (j_is_Dipole) then
624     mu_j = ElectrostaticMap(me2)%dipole_moment
625     #ifdef IS_MPI
626 gezelter 2123 uz_j(1) = eFrame_Col(3,atom2)
627     uz_j(2) = eFrame_Col(6,atom2)
628     uz_j(3) = eFrame_Col(9,atom2)
629 gezelter 2095 #else
630 gezelter 2123 uz_j(1) = eFrame(3,atom2)
631     uz_j(2) = eFrame(6,atom2)
632     uz_j(3) = eFrame(9,atom2)
633 gezelter 2095 #endif
634 chrisfen 2162 ct_j = uz_j(1)*xhat + uz_j(2)*yhat + uz_j(3)*zhat
635 gezelter 2095
636     if (j_is_SplitDipole) then
637     d_j = ElectrostaticMap(me2)%split_dipole_distance
638     endif
639 gezelter 2722 duduz_j = zero
640 gezelter 2095 endif
641    
642 gezelter 2123 if (j_is_Quadrupole) then
643     qxx_j = ElectrostaticMap(me2)%quadrupole_moments(1)
644     qyy_j = ElectrostaticMap(me2)%quadrupole_moments(2)
645     qzz_j = ElectrostaticMap(me2)%quadrupole_moments(3)
646     #ifdef IS_MPI
647     ux_j(1) = eFrame_Col(1,atom2)
648     ux_j(2) = eFrame_Col(4,atom2)
649     ux_j(3) = eFrame_Col(7,atom2)
650     uy_j(1) = eFrame_Col(2,atom2)
651     uy_j(2) = eFrame_Col(5,atom2)
652     uy_j(3) = eFrame_Col(8,atom2)
653     uz_j(1) = eFrame_Col(3,atom2)
654     uz_j(2) = eFrame_Col(6,atom2)
655     uz_j(3) = eFrame_Col(9,atom2)
656     #else
657     ux_j(1) = eFrame(1,atom2)
658     ux_j(2) = eFrame(4,atom2)
659     ux_j(3) = eFrame(7,atom2)
660     uy_j(1) = eFrame(2,atom2)
661     uy_j(2) = eFrame(5,atom2)
662     uy_j(3) = eFrame(8,atom2)
663     uz_j(1) = eFrame(3,atom2)
664     uz_j(2) = eFrame(6,atom2)
665     uz_j(3) = eFrame(9,atom2)
666     #endif
667     cx_j = ux_j(1)*xhat + ux_j(2)*yhat + ux_j(3)*zhat
668     cy_j = uy_j(1)*xhat + uy_j(2)*yhat + uy_j(3)*zhat
669     cz_j = uz_j(1)*xhat + uz_j(2)*yhat + uz_j(3)*zhat
670 gezelter 2722 dudux_j = zero
671     duduy_j = zero
672     duduz_j = zero
673 gezelter 2123 endif
674 chrisfen 2251
675 gezelter 2722 epot = zero
676     dudx = zero
677     dudy = zero
678     dudz = zero
679 gezelter 2095
680     if (i_is_Charge) then
681    
682     if (j_is_Charge) then
683 chrisfen 2438 if (screeningMethod .eq. DAMPED) then
684 chrisfen 2724 call lookupUniformSpline1d(f0spline, rij, f0, df0)
685     f1 = -rij * df0 + f0
686     !!$ f0 = derfc(dampingAlpha*rij)
687     !!$ varEXP = exp(-alpha2*rij*rij)
688     !!$ f1 = alphaPi*rij*varEXP + f0
689 chrisfen 2438 endif
690 gezelter 2204
691 chrisfen 2438 preVal = pre11 * q_i * q_j
692    
693 chrisfen 2409 if (summationMethod .eq. SHIFTED_POTENTIAL) then
694 chrisfen 2438 vterm = preVal * (riji*f0 - rcuti*f0c)
695 chrisfen 2296
696 chrisfen 2438 dudr = -sw * preVal * riji * riji * f1
697    
698 chrisfen 2409 elseif (summationMethod .eq. SHIFTED_FORCE) then
699 chrisfen 2438 vterm = preVal * ( riji*f0 - rcuti*f0c + &
700 chrisfen 2415 f1c*rcuti2*(rij-defaultCutoff) )
701    
702 chrisfen 2438 dudr = -sw*preVal * (riji*riji*f1 - rcuti2*f1c)
703    
704 chrisfen 2394 elseif (summationMethod .eq. REACTION_FIELD) then
705     rfVal = preRF*rij*rij
706     vterm = preVal * ( riji + rfVal )
707 chrisfen 2399
708 chrisfen 2394 dudr = sw * preVal * ( 2.0d0*rfVal - riji )*riji
709 chrisfen 2438
710 chrisfen 2296 else
711 chrisfen 2438 vterm = preVal * riji*f0
712 chrisfen 2296
713 chrisfen 2438 dudr = - sw * preVal * riji*riji*f1
714    
715 chrisfen 2296 endif
716    
717 chrisfen 2438 vpair = vpair + vterm
718     epot = epot + sw*vterm
719    
720     dudx = dudx + dudr * xhat
721     dudy = dudy + dudr * yhat
722     dudz = dudz + dudr * zhat
723    
724 gezelter 2095 endif
725    
726     if (j_is_Dipole) then
727 chrisfen 2548 if (screeningMethod .eq. DAMPED) then
728 chrisfen 2724 call lookupUniformSpline1d(f0spline, rij, f0, df0)
729     f1 = -rij * df0 + f0
730     f3 = -2.0d0*alpha2*df0*rij*rij*rij
731     !!$ f0 = derfc(dampingAlpha*rij)
732     !!$ varEXP = exp(-alpha2*rij*rij)
733     !!$ f1 = alphaPi*rij*varEXP + f0
734     !!$ f3 = alphaPi*2.0d0*alpha2*varEXP*rij*rij*rij
735 chrisfen 2548 endif
736 gezelter 2095
737 chrisfen 2325 pref = pre12 * q_i * mu_j
738 gezelter 2095
739 chrisfen 2409 if (summationMethod .eq. REACTION_FIELD) then
740 chrisfen 2399 ri2 = riji * riji
741     ri3 = ri2 * riji
742 chrisfen 2395
743     vterm = - pref * ct_j * ( ri2 - preRF2*rij )
744     vpair = vpair + vterm
745     epot = epot + sw*vterm
746    
747     !! this has a + sign in the () because the rij vector is
748     !! r_j - r_i and the charge-dipole potential takes the origin
749     !! as the point dipole, which is atom j in this case.
750    
751     dudx = dudx - sw*pref*( ri3*(uz_j(1) - 3.0d0*ct_j*xhat) - &
752     preRF2*uz_j(1) )
753     dudy = dudy - sw*pref*( ri3*(uz_j(2) - 3.0d0*ct_j*yhat) - &
754     preRF2*uz_j(2) )
755     dudz = dudz - sw*pref*( ri3*(uz_j(3) - 3.0d0*ct_j*zhat) - &
756     preRF2*uz_j(3) )
757     duduz_j(1) = duduz_j(1) - sw*pref * xhat * ( ri2 - preRF2*rij )
758     duduz_j(2) = duduz_j(2) - sw*pref * yhat * ( ri2 - preRF2*rij )
759     duduz_j(3) = duduz_j(3) - sw*pref * zhat * ( ri2 - preRF2*rij )
760    
761 chrisfen 2296 else
762     if (j_is_SplitDipole) then
763 gezelter 2717 BigR = sqrt(r2 + 0.25d0 * d_j * d_j)
764     ri = 1.0d0 / BigR
765 chrisfen 2296 scale = rij * ri
766     else
767     ri = riji
768 gezelter 2717 scale = 1.0d0
769 chrisfen 2296 endif
770    
771     ri2 = ri * ri
772     ri3 = ri2 * ri
773     sc2 = scale * scale
774 chrisfen 2325
775 chrisfen 2548 pot_term = ri2 * scale * f1
776     vterm = - pref * ct_j * pot_term
777 chrisfen 2325 vpair = vpair + vterm
778     epot = epot + sw*vterm
779 chrisfen 2296
780     !! this has a + sign in the () because the rij vector is
781     !! r_j - r_i and the charge-dipole potential takes the origin
782     !! as the point dipole, which is atom j in this case.
783    
784 chrisfen 2548 dudx = dudx - sw*pref * ri3 * ( uz_j(1)*f1 - &
785     ct_j*xhat*sc2*( 3.0d0*f1 + f3 ) )
786     dudy = dudy - sw*pref * ri3 * ( uz_j(2)*f1 - &
787     ct_j*yhat*sc2*( 3.0d0*f1 + f3 ) )
788     dudz = dudz - sw*pref * ri3 * ( uz_j(3)*f1 - &
789     ct_j*zhat*sc2*( 3.0d0*f1 + f3 ) )
790    
791     duduz_j(1) = duduz_j(1) - sw*pref * pot_term * xhat
792     duduz_j(2) = duduz_j(2) - sw*pref * pot_term * yhat
793     duduz_j(3) = duduz_j(3) - sw*pref * pot_term * zhat
794 gezelter 2095
795 chrisfen 2296 endif
796 gezelter 2095 endif
797 gezelter 2105
798 gezelter 2123 if (j_is_Quadrupole) then
799 chrisfen 2548 if (screeningMethod .eq. DAMPED) then
800 chrisfen 2724 call lookupUniformSpline1d(f0spline, rij, f0, df0)
801     !!$ f0 = derfc(dampingAlpha*rij)
802     !!$ varEXP = exp(-alpha2*rij*rij)
803     !!$ f1 = alphaPi*rij*varEXP + f0
804     !!$ f2 = alphaPi*2.0d0*alpha2*varEXP
805     f1 = -rij * df0 + f0
806     f2 = -2.0d0*alpha2*df0
807 chrisfen 2548 f3 = f2*rij*rij*rij
808     f4 = 2.0d0*alpha2*f2*rij
809     endif
810    
811 gezelter 2123 ri2 = riji * riji
812     ri3 = ri2 * riji
813 gezelter 2124 ri4 = ri2 * ri2
814 gezelter 2123 cx2 = cx_j * cx_j
815     cy2 = cy_j * cy_j
816     cz2 = cz_j * cz_j
817    
818 gezelter 2717 pref = pre14 * q_i / 3.0d0
819     pot_term = ri3*(qxx_j * (3.0d0*cx2 - 1.0d0) + &
820     qyy_j * (3.0d0*cy2 - 1.0d0) + &
821     qzz_j * (3.0d0*cz2 - 1.0d0))
822 chrisfen 2548 vterm = pref * (pot_term*f1 + (qxx_j*cx2 + qyy_j*cy2 + qzz_j*cz2)*f2)
823 chrisfen 2439 vpair = vpair + vterm
824     epot = epot + sw*vterm
825 chrisfen 2296
826 chrisfen 2548 dudx = dudx - sw*pref*pot_term*riji*xhat*(5.0d0*f1 + f3) + &
827     sw*pref*ri4 * ( &
828 gezelter 2717 qxx_j*(2.0d0*cx_j*ux_j(1)*(3.0d0*f1 + f3) - 2.0d0*xhat*f1) + &
829     qyy_j*(2.0d0*cy_j*uy_j(1)*(3.0d0*f1 + f3) - 2.0d0*xhat*f1) + &
830     qzz_j*(2.0d0*cz_j*uz_j(1)*(3.0d0*f1 + f3) - 2.0d0*xhat*f1) ) &
831 chrisfen 2548 + (qxx_j*cx2 + qyy_j*cy2 + qzz_j*cz2)*f4
832     dudy = dudy - sw*pref*pot_term*riji*yhat*(5.0d0*f1 + f3) + &
833     sw*pref*ri4 * ( &
834 gezelter 2717 qxx_j*(2.0d0*cx_j*ux_j(2)*(3.0d0*f1 + f3) - 2.0d0*yhat*f1) + &
835     qyy_j*(2.0d0*cy_j*uy_j(2)*(3.0d0*f1 + f3) - 2.0d0*yhat*f1) + &
836     qzz_j*(2.0d0*cz_j*uz_j(2)*(3.0d0*f1 + f3) - 2.0d0*yhat*f1) ) &
837 chrisfen 2548 + (qxx_j*cx2 + qyy_j*cy2 + qzz_j*cz2)*f4
838     dudz = dudz - sw*pref*pot_term*riji*zhat*(5.0d0*f1 + f3) + &
839     sw*pref*ri4 * ( &
840 gezelter 2717 qxx_j*(2.0d0*cx_j*ux_j(3)*(3.0d0*f1 + f3) - 2.0d0*zhat*f1) + &
841     qyy_j*(2.0d0*cy_j*uy_j(3)*(3.0d0*f1 + f3) - 2.0d0*zhat*f1) + &
842     qzz_j*(2.0d0*cz_j*uz_j(3)*(3.0d0*f1 + f3) - 2.0d0*zhat*f1) ) &
843 chrisfen 2548 + (qxx_j*cx2 + qyy_j*cy2 + qzz_j*cz2)*f4
844 chrisfen 2439
845 gezelter 2717 dudux_j(1) = dudux_j(1) + sw*pref*ri3*( (qxx_j*2.0d0*cx_j*xhat) &
846 chrisfen 2548 * (3.0d0*f1 + f3) )
847 gezelter 2717 dudux_j(2) = dudux_j(2) + sw*pref*ri3*( (qxx_j*2.0d0*cx_j*yhat) &
848 chrisfen 2548 * (3.0d0*f1 + f3) )
849 gezelter 2717 dudux_j(3) = dudux_j(3) + sw*pref*ri3*( (qxx_j*2.0d0*cx_j*zhat) &
850 chrisfen 2548 * (3.0d0*f1 + f3) )
851 chrisfen 2439
852 gezelter 2717 duduy_j(1) = duduy_j(1) + sw*pref*ri3*( (qyy_j*2.0d0*cy_j*xhat) &
853 chrisfen 2548 * (3.0d0*f1 + f3) )
854 gezelter 2717 duduy_j(2) = duduy_j(2) + sw*pref*ri3*( (qyy_j*2.0d0*cy_j*yhat) &
855 chrisfen 2548 * (3.0d0*f1 + f3) )
856 gezelter 2717 duduy_j(3) = duduy_j(3) + sw*pref*ri3*( (qyy_j*2.0d0*cy_j*zhat) &
857 chrisfen 2548 * (3.0d0*f1 + f3) )
858 chrisfen 2439
859 gezelter 2717 duduz_j(1) = duduz_j(1) + sw*pref*ri3*( (qzz_j*2.0d0*cz_j*xhat) &
860 chrisfen 2548 * (3.0d0*f1 + f3) )
861 gezelter 2717 duduz_j(2) = duduz_j(2) + sw*pref*ri3*( (qzz_j*2.0d0*cz_j*yhat) &
862 chrisfen 2548 * (3.0d0*f1 + f3) )
863 gezelter 2717 duduz_j(3) = duduz_j(3) + sw*pref*ri3*( (qzz_j*2.0d0*cz_j*zhat) &
864 chrisfen 2548 * (3.0d0*f1 + f3) )
865    
866 gezelter 2123 endif
867 gezelter 2095 endif
868 chrisfen 2439
869 gezelter 2095 if (i_is_Dipole) then
870 gezelter 2204
871 gezelter 2095 if (j_is_Charge) then
872 chrisfen 2548 if (screeningMethod .eq. DAMPED) then
873 chrisfen 2724 call lookupUniformSpline1d(f0spline, rij, f0, df0)
874     f1 = -rij * df0 + f0
875     f3 = -2.0d0*alpha2*df0*rij*rij*rij
876     !!$ f0 = derfc(dampingAlpha*rij)
877     !!$ varEXP = exp(-alpha2*rij*rij)
878     !!$ f1 = alphaPi*rij*varEXP + f0
879     !!$ f3 = alphaPi*2.0d0*alpha2*varEXP*rij*rij*rij
880 chrisfen 2548 endif
881 chrisfen 2325
882 chrisfen 2439 pref = pre12 * q_j * mu_i
883    
884 chrisfen 2418 if (summationMethod .eq. SHIFTED_POTENTIAL) then
885 chrisfen 2296 ri2 = riji * riji
886     ri3 = ri2 * riji
887 chrisfen 2418
888 chrisfen 2548 pot_term = ri2*f1 - rcuti2*f1c
889 chrisfen 2418 vterm = pref * ct_i * pot_term
890     vpair = vpair + vterm
891     epot = epot + sw*vterm
892    
893 chrisfen 2548 dudx = dudx + sw*pref*( ri3*(uz_i(1)*f1-ct_i*xhat*(3.0d0*f1+f3)) )
894     dudy = dudy + sw*pref*( ri3*(uz_i(2)*f1-ct_i*yhat*(3.0d0*f1+f3)) )
895     dudz = dudz + sw*pref*( ri3*(uz_i(3)*f1-ct_i*zhat*(3.0d0*f1+f3)) )
896 chrisfen 2418
897     duduz_i(1) = duduz_i(1) + sw*pref * xhat * pot_term
898     duduz_i(2) = duduz_i(2) + sw*pref * yhat * pot_term
899     duduz_i(3) = duduz_i(3) + sw*pref * zhat * pot_term
900 gezelter 2204
901 chrisfen 2418 elseif (summationMethod .eq. SHIFTED_FORCE) then
902     ri2 = riji * riji
903     ri3 = ri2 * riji
904    
905 chrisfen 2548 !! might need a -(f1c-f0c) or dct_i/dr in the derivative term...
906     pot_term = ri2*f1 - rcuti2*f1c + &
907     (2.0d0*rcuti3*f1c + f2c)*( rij - defaultCutoff )
908 chrisfen 2418 vterm = pref * ct_i * pot_term
909     vpair = vpair + vterm
910     epot = epot + sw*vterm
911    
912 chrisfen 2548 dudx = dudx + sw*pref*( ri3*(uz_i(1)*f1-ct_i*xhat*(3.0d0*f1+f3)) &
913     - rcuti3*(uz_i(1)*f1c-ct_i*xhat*(3.0d0*f1c+f3c)) )
914     dudy = dudy + sw*pref*( ri3*(uz_i(2)*f1-ct_i*yhat*(3.0d0*f1+f3)) &
915     - rcuti3*(uz_i(1)*f1c-ct_i*xhat*(3.0d0*f1c+f3c)) )
916     dudz = dudz + sw*pref*( ri3*(uz_i(3)*f1-ct_i*zhat*(3.0d0*f1+f3)) &
917     - rcuti3*(uz_i(1)*f1c-ct_i*xhat*(3.0d0*f1c+f3c)) )
918 chrisfen 2418
919     duduz_i(1) = duduz_i(1) + sw*pref * xhat * pot_term
920     duduz_i(2) = duduz_i(2) + sw*pref * yhat * pot_term
921     duduz_i(3) = duduz_i(3) + sw*pref * zhat * pot_term
922 chrisfen 2548
923 chrisfen 2418 elseif (summationMethod .eq. REACTION_FIELD) then
924     ri2 = riji * riji
925     ri3 = ri2 * riji
926    
927 chrisfen 2399 vterm = pref * ct_i * ( ri2 - preRF2*rij )
928 chrisfen 2395 vpair = vpair + vterm
929     epot = epot + sw*vterm
930    
931 chrisfen 2399 dudx = dudx + sw*pref * ( ri3*(uz_i(1) - 3.0d0*ct_i*xhat) - &
932     preRF2*uz_i(1) )
933     dudy = dudy + sw*pref * ( ri3*(uz_i(2) - 3.0d0*ct_i*yhat) - &
934     preRF2*uz_i(2) )
935     dudz = dudz + sw*pref * ( ri3*(uz_i(3) - 3.0d0*ct_i*zhat) - &
936     preRF2*uz_i(3) )
937 chrisfen 2395
938 chrisfen 2399 duduz_i(1) = duduz_i(1) + sw*pref * xhat * ( ri2 - preRF2*rij )
939     duduz_i(2) = duduz_i(2) + sw*pref * yhat * ( ri2 - preRF2*rij )
940     duduz_i(3) = duduz_i(3) + sw*pref * zhat * ( ri2 - preRF2*rij )
941 chrisfen 2395
942 chrisfen 2296 else
943     if (i_is_SplitDipole) then
944 gezelter 2717 BigR = sqrt(r2 + 0.25d0 * d_i * d_i)
945     ri = 1.0d0 / BigR
946 chrisfen 2296 scale = rij * ri
947     else
948 gezelter 2105 ri = riji
949 gezelter 2717 scale = 1.0d0
950 gezelter 2105 endif
951 chrisfen 2296
952     ri2 = ri * ri
953     ri3 = ri2 * ri
954     sc2 = scale * scale
955 chrisfen 2325
956 chrisfen 2548 pot_term = ri2 * f1 * scale
957     vterm = pref * ct_i * pot_term
958 chrisfen 2325 vpair = vpair + vterm
959     epot = epot + sw*vterm
960 chrisfen 2296
961 chrisfen 2548 dudx = dudx + sw*pref * ri3 * ( uz_i(1)*f1 - &
962     ct_i*xhat*sc2*( 3.0d0*f1 + f3 ) )
963     dudy = dudy + sw*pref * ri3 * ( uz_i(2)*f1 - &
964     ct_i*yhat*sc2*( 3.0d0*f1 + f3 ) )
965     dudz = dudz + sw*pref * ri3 * ( uz_i(3)*f1 - &
966     ct_i*zhat*sc2*( 3.0d0*f1 + f3 ) )
967 chrisfen 2296
968 chrisfen 2548 duduz_i(1) = duduz_i(1) + sw*pref * pot_term * xhat
969     duduz_i(2) = duduz_i(2) + sw*pref * pot_term * yhat
970     duduz_i(3) = duduz_i(3) + sw*pref * pot_term * zhat
971 gezelter 2105 endif
972 chrisfen 2296 endif
973 chrisfen 2325
974 chrisfen 2296 if (j_is_Dipole) then
975 chrisfen 2548 if (screeningMethod .eq. DAMPED) then
976 chrisfen 2724 call lookupUniformSpline1d(f0spline, rij, f0, df0)
977     !!$ f0 = derfc(dampingAlpha*rij)
978     !!$ varEXP = exp(-alpha2*rij*rij)
979     !!$ f1 = alphaPi*rij*varEXP + f0
980     !!$ f2 = alphaPi*2.0d0*alpha2*varEXP
981     f1 = -rij * df0 + f0
982     f2 = -2.0d0*alpha2*df0
983 chrisfen 2548 f3 = f2*rij*rij*rij
984     f4 = 2.0d0*alpha2*f3*rij*rij
985     endif
986    
987 chrisfen 2418 ct_ij = uz_i(1)*uz_j(1) + uz_i(2)*uz_j(2) + uz_i(3)*uz_j(3)
988    
989     ri2 = riji * riji
990     ri3 = ri2 * riji
991     ri4 = ri2 * ri2
992    
993     pref = pre22 * mu_i * mu_j
994 gezelter 2105
995 chrisfen 2409 if (summationMethod .eq. REACTION_FIELD) then
996 chrisfen 2394 vterm = pref*( ri3*(ct_ij - 3.0d0 * ct_i * ct_j) - &
997     preRF2*ct_ij )
998     vpair = vpair + vterm
999     epot = epot + sw*vterm
1000    
1001     a1 = 5.0d0 * ct_i * ct_j - ct_ij
1002    
1003     dudx = dudx + sw*pref*3.0d0*ri4 &
1004     * (a1*xhat-ct_i*uz_j(1)-ct_j*uz_i(1))
1005     dudy = dudy + sw*pref*3.0d0*ri4 &
1006     * (a1*yhat-ct_i*uz_j(2)-ct_j*uz_i(2))
1007     dudz = dudz + sw*pref*3.0d0*ri4 &
1008     * (a1*zhat-ct_i*uz_j(3)-ct_j*uz_i(3))
1009    
1010     duduz_i(1) = duduz_i(1) + sw*pref*(ri3*(uz_j(1)-3.0d0*ct_j*xhat) &
1011     - preRF2*uz_j(1))
1012     duduz_i(2) = duduz_i(2) + sw*pref*(ri3*(uz_j(2)-3.0d0*ct_j*yhat) &
1013     - preRF2*uz_j(2))
1014     duduz_i(3) = duduz_i(3) + sw*pref*(ri3*(uz_j(3)-3.0d0*ct_j*zhat) &
1015     - preRF2*uz_j(3))
1016     duduz_j(1) = duduz_j(1) + sw*pref*(ri3*(uz_i(1)-3.0d0*ct_i*xhat) &
1017     - preRF2*uz_i(1))
1018     duduz_j(2) = duduz_j(2) + sw*pref*(ri3*(uz_i(2)-3.0d0*ct_i*yhat) &
1019     - preRF2*uz_i(2))
1020     duduz_j(3) = duduz_j(3) + sw*pref*(ri3*(uz_i(3)-3.0d0*ct_i*zhat) &
1021     - preRF2*uz_i(3))
1022    
1023 chrisfen 2296 else
1024     if (i_is_SplitDipole) then
1025     if (j_is_SplitDipole) then
1026 gezelter 2717 BigR = sqrt(r2 + 0.25d0 * d_i * d_i + 0.25d0 * d_j * d_j)
1027 chrisfen 2296 else
1028 gezelter 2717 BigR = sqrt(r2 + 0.25d0 * d_i * d_i)
1029 chrisfen 2296 endif
1030 gezelter 2717 ri = 1.0d0 / BigR
1031 chrisfen 2296 scale = rij * ri
1032     else
1033     if (j_is_SplitDipole) then
1034 gezelter 2717 BigR = sqrt(r2 + 0.25d0 * d_j * d_j)
1035     ri = 1.0d0 / BigR
1036 chrisfen 2296 scale = rij * ri
1037     else
1038     ri = riji
1039 gezelter 2717 scale = 1.0d0
1040 chrisfen 2296 endif
1041     endif
1042    
1043     sc2 = scale * scale
1044 chrisfen 2418
1045 chrisfen 2548 pot_term = (ct_ij - 3.0d0 * ct_i * ct_j * sc2)
1046     vterm = pref * ( ri3*pot_term*f1 + (ct_i * ct_j)*f2 )
1047 chrisfen 2325 vpair = vpair + vterm
1048     epot = epot + sw*vterm
1049 chrisfen 2296
1050 chrisfen 2548 f13 = f1+f3
1051     f134 = f13 + f4
1052 chrisfen 2296
1053 chrisfen 2548 !!$ dudx = dudx + sw*pref * ( ri4*scale*( &
1054     !!$ 3.0d0*(a1*xhat-ct_i*uz_j(1)-ct_j*uz_i(1))*f1 &
1055     !!$ - pot_term*f3) &
1056     !!$ + 2.0d0*ct_i*ct_j*xhat*(ct_i*uz_j(1)+ct_j*uz_i(1))*f3 &
1057     !!$ + (ct_i * ct_j)*f4 )
1058     !!$ dudy = dudy + sw*pref * ( ri4*scale*( &
1059     !!$ 3.0d0*(a1*yhat-ct_i*uz_j(2)-ct_j*uz_i(2))*f1 &
1060     !!$ - pot_term*f3) &
1061     !!$ + 2.0d0*ct_i*ct_j*yhat*(ct_i*uz_j(2)+ct_j*uz_i(2))*f3 &
1062     !!$ + (ct_i * ct_j)*f4 )
1063     !!$ dudz = dudz + sw*pref * ( ri4*scale*( &
1064     !!$ 3.0d0*(a1*zhat-ct_i*uz_j(3)-ct_j*uz_i(3))*f1 &
1065     !!$ - pot_term*f3) &
1066     !!$ + 2.0d0*ct_i*ct_j*zhat*(ct_i*uz_j(3)+ct_j*uz_i(3))*f3 &
1067     !!$ + (ct_i * ct_j)*f4 )
1068    
1069     dudx = dudx + sw*pref * ( ri4*scale*( &
1070     15.0d0*(ct_i * ct_j * sc2)*xhat*f134 - &
1071     3.0d0*(ct_i*uz_j(1) + ct_j*uz_i(1) + ct_ij*xhat)*f134) )
1072     dudy = dudy + sw*pref * ( ri4*scale*( &
1073     15.0d0*(ct_i * ct_j * sc2)*yhat*f134 - &
1074     3.0d0*(ct_i*uz_j(2) + ct_j*uz_i(2) + ct_ij*yhat)*f134) )
1075     dudz = dudz + sw*pref * ( ri4*scale*( &
1076     15.0d0*(ct_i * ct_j * sc2)*zhat*f134 - &
1077     3.0d0*(ct_i*uz_j(3) + ct_j*uz_i(3) + ct_ij*zhat)*f134) )
1078 chrisfen 2296
1079 chrisfen 2548 duduz_i(1) = duduz_i(1) + sw*pref * &
1080     ( ri3*(uz_j(1) - 3.0d0*ct_j*xhat*sc2)*f1 + (ct_j*xhat)*f2 )
1081     duduz_i(2) = duduz_i(2) + sw*pref * &
1082     ( ri3*(uz_j(2) - 3.0d0*ct_j*yhat*sc2)*f1 + (ct_j*yhat)*f2 )
1083     duduz_i(3) = duduz_i(3) + sw*pref * &
1084     ( ri3*(uz_j(3) - 3.0d0*ct_j*zhat*sc2)*f1 + (ct_j*zhat)*f2 )
1085 chrisfen 2296
1086 chrisfen 2548 duduz_j(1) = duduz_j(1) + sw*pref * &
1087     ( ri3*(uz_i(1) - 3.0d0*ct_i*xhat*sc2)*f1 + (ct_i*xhat)*f2 )
1088     duduz_j(2) = duduz_j(2) + sw*pref * &
1089     ( ri3*(uz_i(2) - 3.0d0*ct_i*yhat*sc2)*f1 + (ct_i*yhat)*f2 )
1090     duduz_j(3) = duduz_j(3) + sw*pref * &
1091     ( ri3*(uz_i(3) - 3.0d0*ct_i*zhat*sc2)*f1 + (ct_i*zhat)*f2 )
1092 chrisfen 2296 endif
1093 gezelter 2095 endif
1094     endif
1095 gezelter 2123
1096     if (i_is_Quadrupole) then
1097     if (j_is_Charge) then
1098 chrisfen 2548 if (screeningMethod .eq. DAMPED) then
1099 chrisfen 2724 call lookupUniformSpline1d(f0spline, rij, f0, df0)
1100     !!$ f0 = derfc(dampingAlpha*rij)
1101     !!$ varEXP = exp(-alpha2*rij*rij)
1102     !!$ f1 = alphaPi*rij*varEXP + f0
1103     !!$ f2 = alphaPi*2.0d0*alpha2*varEXP
1104     f1 = -rij * df0 + f0
1105     f2 = -2.0d0*alpha2*df0
1106 chrisfen 2548 f3 = f2*rij*rij*rij
1107     f4 = 2.0d0*alpha2*f2*rij
1108     endif
1109    
1110 gezelter 2123 ri2 = riji * riji
1111     ri3 = ri2 * riji
1112 gezelter 2124 ri4 = ri2 * ri2
1113 gezelter 2123 cx2 = cx_i * cx_i
1114     cy2 = cy_i * cy_i
1115     cz2 = cz_i * cz_i
1116 gezelter 2204
1117 gezelter 2717 pref = pre14 * q_j / 3.0d0
1118     pot_term = ri3 * (qxx_i * (3.0d0*cx2 - 1.0d0) + &
1119     qyy_i * (3.0d0*cy2 - 1.0d0) + &
1120     qzz_i * (3.0d0*cz2 - 1.0d0))
1121 chrisfen 2548 vterm = pref * (pot_term*f1 + (qxx_i*cx2 + qyy_i*cy2 + qzz_i*cz2)*f2)
1122 chrisfen 2439 vpair = vpair + vterm
1123     epot = epot + sw*vterm
1124    
1125 chrisfen 2548 dudx = dudx - sw*pref*pot_term*riji*xhat*(5.0d0*f1 + f3) + &
1126     sw*pref*ri4 * ( &
1127 gezelter 2717 qxx_i*(2.0d0*cx_i*ux_i(1)*(3.0d0*f1 + f3) - 2.0d0*xhat*f1) + &
1128     qyy_i*(2.0d0*cy_i*uy_i(1)*(3.0d0*f1 + f3) - 2.0d0*xhat*f1) + &
1129     qzz_i*(2.0d0*cz_i*uz_i(1)*(3.0d0*f1 + f3) - 2.0d0*xhat*f1) ) &
1130 chrisfen 2548 + (qxx_i*cx2 + qyy_i*cy2 + qzz_i*cz2)*f4
1131     dudy = dudy - sw*pref*pot_term*riji*yhat*(5.0d0*f1 + f3) + &
1132     sw*pref*ri4 * ( &
1133 gezelter 2717 qxx_i*(2.0d0*cx_i*ux_i(2)*(3.0d0*f1 + f3) - 2.0d0*yhat*f1) + &
1134     qyy_i*(2.0d0*cy_i*uy_i(2)*(3.0d0*f1 + f3) - 2.0d0*yhat*f1) + &
1135     qzz_i*(2.0d0*cz_i*uz_i(2)*(3.0d0*f1 + f3) - 2.0d0*yhat*f1) ) &
1136 chrisfen 2548 + (qxx_i*cx2 + qyy_i*cy2 + qzz_i*cz2)*f4
1137     dudz = dudz - sw*pref*pot_term*riji*zhat*(5.0d0*f1 + f3) + &
1138     sw*pref*ri4 * ( &
1139 gezelter 2717 qxx_i*(2.0d0*cx_i*ux_i(3)*(3.0d0*f1 + f3) - 2.0d0*zhat*f1) + &
1140     qyy_i*(2.0d0*cy_i*uy_i(3)*(3.0d0*f1 + f3) - 2.0d0*zhat*f1) + &
1141     qzz_i*(2.0d0*cz_i*uz_i(3)*(3.0d0*f1 + f3) - 2.0d0*zhat*f1) ) &
1142 chrisfen 2548 + (qxx_i*cx2 + qyy_i*cy2 + qzz_i*cz2)*f4
1143 chrisfen 2439
1144 gezelter 2717 dudux_i(1) = dudux_i(1) + sw*pref*( ri3*(qxx_i*2.0d0*cx_i*xhat) &
1145 chrisfen 2548 * (3.0d0*f1 + f3) )
1146 gezelter 2717 dudux_i(2) = dudux_i(2) + sw*pref*( ri3*(qxx_i*2.0d0*cx_i*yhat) &
1147 chrisfen 2548 * (3.0d0*f1 + f3) )
1148 gezelter 2717 dudux_i(3) = dudux_i(3) + sw*pref*( ri3*(qxx_i*2.0d0*cx_i*zhat) &
1149 chrisfen 2548 * (3.0d0*f1 + f3) )
1150 chrisfen 2439
1151 gezelter 2717 duduy_i(1) = duduy_i(1) + sw*pref*( ri3*(qyy_i*2.0d0*cy_i*xhat) &
1152 chrisfen 2548 * (3.0d0*f1 + f3) )
1153 gezelter 2717 duduy_i(2) = duduy_i(2) + sw*pref*( ri3*(qyy_i*2.0d0*cy_i*yhat) &
1154 chrisfen 2548 * (3.0d0*f1 + f3) )
1155 gezelter 2717 duduy_i(3) = duduy_i(3) + sw*pref*( ri3*(qyy_i*2.0d0*cy_i*zhat) &
1156 chrisfen 2548 * (3.0d0*f1 + f3) )
1157 chrisfen 2439
1158 gezelter 2717 duduz_i(1) = duduz_i(1) + sw*pref*( ri3*(qzz_i*2.0d0*cz_i*xhat) &
1159 chrisfen 2548 * (3.0d0*f1 + f3) )
1160 gezelter 2717 duduz_i(2) = duduz_i(2) + sw*pref*( ri3*(qzz_i*2.0d0*cz_i*yhat) &
1161 chrisfen 2548 * (3.0d0*f1 + f3) )
1162 gezelter 2717 duduz_i(3) = duduz_i(3) + sw*pref*( ri3*(qzz_i*2.0d0*cz_i*zhat) &
1163 chrisfen 2548 * (3.0d0*f1 + f3) )
1164 chrisfen 2439
1165 gezelter 2123 endif
1166     endif
1167 gezelter 2204
1168    
1169 gezelter 2095 if (do_pot) then
1170     #ifdef IS_MPI
1171 chuckv 2355 pot_row(ELECTROSTATIC_POT,atom1) = pot_row(ELECTROSTATIC_POT,atom1) + 0.5d0*epot
1172     pot_col(ELECTROSTATIC_POT,atom2) = pot_col(ELECTROSTATIC_POT,atom2) + 0.5d0*epot
1173 gezelter 2095 #else
1174     pot = pot + epot
1175     #endif
1176     endif
1177 gezelter 2204
1178 gezelter 2095 #ifdef IS_MPI
1179     f_Row(1,atom1) = f_Row(1,atom1) + dudx
1180     f_Row(2,atom1) = f_Row(2,atom1) + dudy
1181     f_Row(3,atom1) = f_Row(3,atom1) + dudz
1182 gezelter 2204
1183 gezelter 2095 f_Col(1,atom2) = f_Col(1,atom2) - dudx
1184     f_Col(2,atom2) = f_Col(2,atom2) - dudy
1185     f_Col(3,atom2) = f_Col(3,atom2) - dudz
1186 gezelter 2204
1187 gezelter 2095 if (i_is_Dipole .or. i_is_Quadrupole) then
1188 gezelter 2123 t_Row(1,atom1)=t_Row(1,atom1) - uz_i(2)*duduz_i(3) + uz_i(3)*duduz_i(2)
1189     t_Row(2,atom1)=t_Row(2,atom1) - uz_i(3)*duduz_i(1) + uz_i(1)*duduz_i(3)
1190     t_Row(3,atom1)=t_Row(3,atom1) - uz_i(1)*duduz_i(2) + uz_i(2)*duduz_i(1)
1191 gezelter 2095 endif
1192 gezelter 2123 if (i_is_Quadrupole) then
1193     t_Row(1,atom1)=t_Row(1,atom1) - ux_i(2)*dudux_i(3) + ux_i(3)*dudux_i(2)
1194     t_Row(2,atom1)=t_Row(2,atom1) - ux_i(3)*dudux_i(1) + ux_i(1)*dudux_i(3)
1195     t_Row(3,atom1)=t_Row(3,atom1) - ux_i(1)*dudux_i(2) + ux_i(2)*dudux_i(1)
1196 gezelter 2095
1197 gezelter 2123 t_Row(1,atom1)=t_Row(1,atom1) - uy_i(2)*duduy_i(3) + uy_i(3)*duduy_i(2)
1198     t_Row(2,atom1)=t_Row(2,atom1) - uy_i(3)*duduy_i(1) + uy_i(1)*duduy_i(3)
1199     t_Row(3,atom1)=t_Row(3,atom1) - uy_i(1)*duduy_i(2) + uy_i(2)*duduy_i(1)
1200     endif
1201    
1202 gezelter 2095 if (j_is_Dipole .or. j_is_Quadrupole) then
1203 gezelter 2123 t_Col(1,atom2)=t_Col(1,atom2) - uz_j(2)*duduz_j(3) + uz_j(3)*duduz_j(2)
1204     t_Col(2,atom2)=t_Col(2,atom2) - uz_j(3)*duduz_j(1) + uz_j(1)*duduz_j(3)
1205     t_Col(3,atom2)=t_Col(3,atom2) - uz_j(1)*duduz_j(2) + uz_j(2)*duduz_j(1)
1206 gezelter 2095 endif
1207 gezelter 2123 if (j_is_Quadrupole) then
1208     t_Col(1,atom2)=t_Col(1,atom2) - ux_j(2)*dudux_j(3) + ux_j(3)*dudux_j(2)
1209     t_Col(2,atom2)=t_Col(2,atom2) - ux_j(3)*dudux_j(1) + ux_j(1)*dudux_j(3)
1210     t_Col(3,atom2)=t_Col(3,atom2) - ux_j(1)*dudux_j(2) + ux_j(2)*dudux_j(1)
1211 gezelter 2095
1212 gezelter 2123 t_Col(1,atom2)=t_Col(1,atom2) - uy_j(2)*duduy_j(3) + uy_j(3)*duduy_j(2)
1213     t_Col(2,atom2)=t_Col(2,atom2) - uy_j(3)*duduy_j(1) + uy_j(1)*duduy_j(3)
1214     t_Col(3,atom2)=t_Col(3,atom2) - uy_j(1)*duduy_j(2) + uy_j(2)*duduy_j(1)
1215     endif
1216    
1217 gezelter 2095 #else
1218     f(1,atom1) = f(1,atom1) + dudx
1219     f(2,atom1) = f(2,atom1) + dudy
1220     f(3,atom1) = f(3,atom1) + dudz
1221 gezelter 2204
1222 gezelter 2095 f(1,atom2) = f(1,atom2) - dudx
1223     f(2,atom2) = f(2,atom2) - dudy
1224     f(3,atom2) = f(3,atom2) - dudz
1225 gezelter 2204
1226 gezelter 2095 if (i_is_Dipole .or. i_is_Quadrupole) then
1227 gezelter 2123 t(1,atom1)=t(1,atom1) - uz_i(2)*duduz_i(3) + uz_i(3)*duduz_i(2)
1228     t(2,atom1)=t(2,atom1) - uz_i(3)*duduz_i(1) + uz_i(1)*duduz_i(3)
1229     t(3,atom1)=t(3,atom1) - uz_i(1)*duduz_i(2) + uz_i(2)*duduz_i(1)
1230 gezelter 2095 endif
1231 gezelter 2123 if (i_is_Quadrupole) then
1232     t(1,atom1)=t(1,atom1) - ux_i(2)*dudux_i(3) + ux_i(3)*dudux_i(2)
1233     t(2,atom1)=t(2,atom1) - ux_i(3)*dudux_i(1) + ux_i(1)*dudux_i(3)
1234     t(3,atom1)=t(3,atom1) - ux_i(1)*dudux_i(2) + ux_i(2)*dudux_i(1)
1235    
1236     t(1,atom1)=t(1,atom1) - uy_i(2)*duduy_i(3) + uy_i(3)*duduy_i(2)
1237     t(2,atom1)=t(2,atom1) - uy_i(3)*duduy_i(1) + uy_i(1)*duduy_i(3)
1238     t(3,atom1)=t(3,atom1) - uy_i(1)*duduy_i(2) + uy_i(2)*duduy_i(1)
1239     endif
1240    
1241 gezelter 2095 if (j_is_Dipole .or. j_is_Quadrupole) then
1242 gezelter 2123 t(1,atom2)=t(1,atom2) - uz_j(2)*duduz_j(3) + uz_j(3)*duduz_j(2)
1243     t(2,atom2)=t(2,atom2) - uz_j(3)*duduz_j(1) + uz_j(1)*duduz_j(3)
1244     t(3,atom2)=t(3,atom2) - uz_j(1)*duduz_j(2) + uz_j(2)*duduz_j(1)
1245 gezelter 2095 endif
1246 gezelter 2123 if (j_is_Quadrupole) then
1247     t(1,atom2)=t(1,atom2) - ux_j(2)*dudux_j(3) + ux_j(3)*dudux_j(2)
1248     t(2,atom2)=t(2,atom2) - ux_j(3)*dudux_j(1) + ux_j(1)*dudux_j(3)
1249     t(3,atom2)=t(3,atom2) - ux_j(1)*dudux_j(2) + ux_j(2)*dudux_j(1)
1250    
1251     t(1,atom2)=t(1,atom2) - uy_j(2)*duduy_j(3) + uy_j(3)*duduy_j(2)
1252     t(2,atom2)=t(2,atom2) - uy_j(3)*duduy_j(1) + uy_j(1)*duduy_j(3)
1253     t(3,atom2)=t(3,atom2) - uy_j(1)*duduy_j(2) + uy_j(2)*duduy_j(1)
1254     endif
1255    
1256 gezelter 2095 #endif
1257 gezelter 2204
1258 gezelter 2095 #ifdef IS_MPI
1259     id1 = AtomRowToGlobal(atom1)
1260     id2 = AtomColToGlobal(atom2)
1261     #else
1262     id1 = atom1
1263     id2 = atom2
1264     #endif
1265    
1266     if (molMembershipList(id1) .ne. molMembershipList(id2)) then
1267 gezelter 2204
1268 gezelter 2095 fpair(1) = fpair(1) + dudx
1269     fpair(2) = fpair(2) + dudy
1270     fpair(3) = fpair(3) + dudz
1271    
1272     endif
1273    
1274     return
1275     end subroutine doElectrostaticPair
1276 chuckv 2189
1277     subroutine destroyElectrostaticTypes()
1278    
1279 gezelter 2204 if(allocated(ElectrostaticMap)) deallocate(ElectrostaticMap)
1280    
1281 chuckv 2189 end subroutine destroyElectrostaticTypes
1282    
1283 chrisfen 2402 subroutine self_self(atom1, eFrame, mypot, t, do_pot)
1284 chrisfen 2394 logical, intent(in) :: do_pot
1285 chrisfen 2381 integer, intent(in) :: atom1
1286 chrisfen 2394 integer :: atid1
1287 chrisfen 2381 real(kind=dp), dimension(9,nLocal) :: eFrame
1288 chrisfen 2394 real(kind=dp), dimension(3,nLocal) :: t
1289 chrisfen 2402 real(kind=dp) :: mu1, c1
1290     real(kind=dp) :: preVal, epot, mypot
1291 chrisfen 2394 real(kind=dp) :: eix, eiy, eiz
1292 chrisfen 2381
1293 chrisfen 2394 ! this is a local only array, so we use the local atom type id's:
1294     atid1 = atid(atom1)
1295 chrisfen 2402
1296     if (.not.summationMethodChecked) then
1297     call checkSummationMethod()
1298     endif
1299 chrisfen 2394
1300 chrisfen 2402 if (summationMethod .eq. REACTION_FIELD) then
1301     if (ElectrostaticMap(atid1)%is_Dipole) then
1302     mu1 = getDipoleMoment(atid1)
1303    
1304     preVal = pre22 * preRF2 * mu1*mu1
1305     mypot = mypot - 0.5d0*preVal
1306    
1307     ! The self-correction term adds into the reaction field vector
1308    
1309     eix = preVal * eFrame(3,atom1)
1310     eiy = preVal * eFrame(6,atom1)
1311     eiz = preVal * eFrame(9,atom1)
1312    
1313     ! once again, this is self-self, so only the local arrays are needed
1314     ! even for MPI jobs:
1315    
1316     t(1,atom1)=t(1,atom1) - eFrame(6,atom1)*eiz + &
1317     eFrame(9,atom1)*eiy
1318     t(2,atom1)=t(2,atom1) - eFrame(9,atom1)*eix + &
1319     eFrame(3,atom1)*eiz
1320     t(3,atom1)=t(3,atom1) - eFrame(3,atom1)*eiy + &
1321     eFrame(6,atom1)*eix
1322    
1323     endif
1324    
1325 chrisfen 2442 elseif ( (summationMethod .eq. SHIFTED_FORCE) .or. &
1326     (summationMethod .eq. SHIFTED_POTENTIAL) ) then
1327 chrisfen 2416 if (ElectrostaticMap(atid1)%is_Charge) then
1328     c1 = getCharge(atid1)
1329    
1330     if (screeningMethod .eq. DAMPED) then
1331 gezelter 2717 mypot = mypot - (f0c * rcuti * 0.5d0 + &
1332 chrisfen 2416 dampingAlpha*invRootPi) * c1 * c1
1333    
1334     else
1335 gezelter 2717 mypot = mypot - (rcuti * 0.5d0 * c1 * c1)
1336 chrisfen 2416
1337     endif
1338     endif
1339     endif
1340 chrisfen 2394
1341 chrisfen 2381 return
1342 chrisfen 2402 end subroutine self_self
1343 chrisfen 2381
1344 chrisfen 2402 subroutine rf_self_excludes(atom1, atom2, sw, eFrame, d, rij, vpair, myPot, &
1345 chrisfen 2399 f, t, do_pot)
1346     logical, intent(in) :: do_pot
1347     integer, intent(in) :: atom1
1348     integer, intent(in) :: atom2
1349     logical :: i_is_Charge, j_is_Charge
1350     logical :: i_is_Dipole, j_is_Dipole
1351     integer :: atid1
1352     integer :: atid2
1353     real(kind=dp), intent(in) :: rij
1354     real(kind=dp), intent(in) :: sw
1355     real(kind=dp), intent(in), dimension(3) :: d
1356     real(kind=dp), intent(inout) :: vpair
1357     real(kind=dp), dimension(9,nLocal) :: eFrame
1358     real(kind=dp), dimension(3,nLocal) :: f
1359     real(kind=dp), dimension(3,nLocal) :: t
1360     real (kind = dp), dimension(3) :: duduz_i
1361     real (kind = dp), dimension(3) :: duduz_j
1362     real (kind = dp), dimension(3) :: uz_i
1363     real (kind = dp), dimension(3) :: uz_j
1364     real(kind=dp) :: q_i, q_j, mu_i, mu_j
1365     real(kind=dp) :: xhat, yhat, zhat
1366     real(kind=dp) :: ct_i, ct_j
1367     real(kind=dp) :: ri2, ri3, riji, vterm
1368 chrisfen 2402 real(kind=dp) :: pref, preVal, rfVal, myPot
1369 chrisfen 2399 real(kind=dp) :: dudx, dudy, dudz, dudr
1370    
1371 chrisfen 2402 if (.not.summationMethodChecked) then
1372     call checkSummationMethod()
1373 chrisfen 2399 endif
1374    
1375 gezelter 2722 dudx = zero
1376     dudy = zero
1377     dudz = zero
1378 chrisfen 2399
1379     riji = 1.0d0/rij
1380    
1381     xhat = d(1) * riji
1382     yhat = d(2) * riji
1383     zhat = d(3) * riji
1384    
1385     ! this is a local only array, so we use the local atom type id's:
1386     atid1 = atid(atom1)
1387     atid2 = atid(atom2)
1388     i_is_Charge = ElectrostaticMap(atid1)%is_Charge
1389     j_is_Charge = ElectrostaticMap(atid2)%is_Charge
1390     i_is_Dipole = ElectrostaticMap(atid1)%is_Dipole
1391     j_is_Dipole = ElectrostaticMap(atid2)%is_Dipole
1392    
1393     if (i_is_Charge.and.j_is_Charge) then
1394     q_i = ElectrostaticMap(atid1)%charge
1395     q_j = ElectrostaticMap(atid2)%charge
1396    
1397     preVal = pre11 * q_i * q_j
1398     rfVal = preRF*rij*rij
1399     vterm = preVal * rfVal
1400    
1401 chrisfen 2402 myPot = myPot + sw*vterm
1402    
1403 chrisfen 2399 dudr = sw*preVal * 2.0d0*rfVal*riji
1404 chrisfen 2402
1405 chrisfen 2399 dudx = dudx + dudr * xhat
1406     dudy = dudy + dudr * yhat
1407     dudz = dudz + dudr * zhat
1408 chrisfen 2402
1409 chrisfen 2399 elseif (i_is_Charge.and.j_is_Dipole) then
1410     q_i = ElectrostaticMap(atid1)%charge
1411     mu_j = ElectrostaticMap(atid2)%dipole_moment
1412     uz_j(1) = eFrame(3,atom2)
1413     uz_j(2) = eFrame(6,atom2)
1414     uz_j(3) = eFrame(9,atom2)
1415     ct_j = uz_j(1)*xhat + uz_j(2)*yhat + uz_j(3)*zhat
1416 chrisfen 2402
1417 chrisfen 2399 ri2 = riji * riji
1418     ri3 = ri2 * riji
1419    
1420     pref = pre12 * q_i * mu_j
1421     vterm = - pref * ct_j * ( ri2 - preRF2*rij )
1422 chrisfen 2402 myPot = myPot + sw*vterm
1423    
1424     dudx = dudx - sw*pref*( ri3*(uz_j(1)-3.0d0*ct_j*xhat) &
1425     - preRF2*uz_j(1) )
1426     dudy = dudy - sw*pref*( ri3*(uz_j(2)-3.0d0*ct_j*yhat) &
1427     - preRF2*uz_j(2) )
1428     dudz = dudz - sw*pref*( ri3*(uz_j(3)-3.0d0*ct_j*zhat) &
1429     - preRF2*uz_j(3) )
1430    
1431 chrisfen 2399 duduz_j(1) = duduz_j(1) - sw * pref * xhat * ( ri2 - preRF2*rij )
1432     duduz_j(2) = duduz_j(2) - sw * pref * yhat * ( ri2 - preRF2*rij )
1433     duduz_j(3) = duduz_j(3) - sw * pref * zhat * ( ri2 - preRF2*rij )
1434 chrisfen 2402
1435 chrisfen 2399 elseif (i_is_Dipole.and.j_is_Charge) then
1436     mu_i = ElectrostaticMap(atid1)%dipole_moment
1437     q_j = ElectrostaticMap(atid2)%charge
1438     uz_i(1) = eFrame(3,atom1)
1439     uz_i(2) = eFrame(6,atom1)
1440     uz_i(3) = eFrame(9,atom1)
1441     ct_i = uz_i(1)*xhat + uz_i(2)*yhat + uz_i(3)*zhat
1442 chrisfen 2402
1443 chrisfen 2399 ri2 = riji * riji
1444     ri3 = ri2 * riji
1445    
1446     pref = pre12 * q_j * mu_i
1447     vterm = pref * ct_i * ( ri2 - preRF2*rij )
1448 chrisfen 2402 myPot = myPot + sw*vterm
1449 chrisfen 2399
1450 chrisfen 2402 dudx = dudx + sw*pref*( ri3*(uz_i(1)-3.0d0*ct_i*xhat) &
1451     - preRF2*uz_i(1) )
1452     dudy = dudy + sw*pref*( ri3*(uz_i(2)-3.0d0*ct_i*yhat) &
1453     - preRF2*uz_i(2) )
1454     dudz = dudz + sw*pref*( ri3*(uz_i(3)-3.0d0*ct_i*zhat) &
1455     - preRF2*uz_i(3) )
1456 chrisfen 2399
1457     duduz_i(1) = duduz_i(1) + sw * pref * xhat * ( ri2 - preRF2*rij )
1458     duduz_i(2) = duduz_i(2) + sw * pref * yhat * ( ri2 - preRF2*rij )
1459     duduz_i(3) = duduz_i(3) + sw * pref * zhat * ( ri2 - preRF2*rij )
1460    
1461     endif
1462 chrisfen 2402
1463    
1464     ! accumulate the forces and torques resulting from the self term
1465 chrisfen 2399 f(1,atom1) = f(1,atom1) + dudx
1466     f(2,atom1) = f(2,atom1) + dudy
1467     f(3,atom1) = f(3,atom1) + dudz
1468    
1469     f(1,atom2) = f(1,atom2) - dudx
1470     f(2,atom2) = f(2,atom2) - dudy
1471     f(3,atom2) = f(3,atom2) - dudz
1472    
1473     if (i_is_Dipole) then
1474     t(1,atom1)=t(1,atom1) - uz_i(2)*duduz_i(3) + uz_i(3)*duduz_i(2)
1475     t(2,atom1)=t(2,atom1) - uz_i(3)*duduz_i(1) + uz_i(1)*duduz_i(3)
1476     t(3,atom1)=t(3,atom1) - uz_i(1)*duduz_i(2) + uz_i(2)*duduz_i(1)
1477     elseif (j_is_Dipole) then
1478     t(1,atom2)=t(1,atom2) - uz_j(2)*duduz_j(3) + uz_j(3)*duduz_j(2)
1479     t(2,atom2)=t(2,atom2) - uz_j(3)*duduz_j(1) + uz_j(1)*duduz_j(3)
1480     t(3,atom2)=t(3,atom2) - uz_j(1)*duduz_j(2) + uz_j(2)*duduz_j(1)
1481     endif
1482    
1483     return
1484     end subroutine rf_self_excludes
1485    
1486 gezelter 2095 end module electrostatic_module