ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/UseTheForce/DarkSide/electrostatic.F90
Revision: 2552
Committed: Thu Jan 12 16:47:25 2006 UTC (18 years, 5 months ago) by chrisfen
File size: 52567 byte(s)
Log Message:
unifying function name in electrostatics

File Contents

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